| OLD | NEW |
| (Empty) |
| 1 // | |
| 2 // Copyright 2014 Google Inc. All rights reserved. | |
| 3 // | |
| 4 // Use of this source code is governed by a BSD-style | |
| 5 // license that can be found in the LICENSE file or at | |
| 6 // https://developers.google.com/open-source/licenses/bsd | |
| 7 // | |
| 8 | |
| 9 /// Provides a way to measure rendered text width for clipping | |
| 10 /// text on tooltips and ticks when they are too long. | |
| 11 library charted.core.text_metrics; | |
| 12 | |
| 13 import "dart:html"; | |
| 14 import "package:charted/core/text_metrics/segmentation.dart"; | |
| 15 | |
| 16 /// Utilities to measure text width. | |
| 17 class TextMetrics { | |
| 18 static CanvasElement canvas; | |
| 19 static CanvasRenderingContext2D context; | |
| 20 static TextMetrics instance; | |
| 21 | |
| 22 static const MAX_STRING_LENGTH = 250; | |
| 23 static final FONT_SIZE_REGEX = new RegExp("\s?([0-9]+)px\s?"); | |
| 24 | |
| 25 final String fontStyle; | |
| 26 int fontSize = 16; | |
| 27 | |
| 28 String currentFontStyle; | |
| 29 | |
| 30 factory TextMetrics({String fontStyle}) { | |
| 31 if (canvas == null || context == null) { | |
| 32 canvas = document.createElement('canvas'); | |
| 33 context = canvas.getContext('2d'); | |
| 34 } | |
| 35 if (instance == null) { | |
| 36 instance = new TextMetrics._internal(fontStyle); | |
| 37 } | |
| 38 return instance; | |
| 39 } | |
| 40 TextMetrics._internal(this.fontStyle) { | |
| 41 Match match = FONT_SIZE_REGEX.firstMatch(fontStyle); | |
| 42 fontSize = int.parse(match.group(1)); | |
| 43 } | |
| 44 | |
| 45 void setFontStyle(String fontStyle) { | |
| 46 if (fontStyle == null) { | |
| 47 fontStyle = this.fontStyle; | |
| 48 } | |
| 49 if (currentFontStyle != fontStyle) { | |
| 50 context.font = fontStyle; | |
| 51 currentFontStyle = fontStyle; | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 /// Measure width of [text] in pixels. | |
| 56 /// Optionally, uses [fontStyle] instead of using the default style | |
| 57 double getTextWidth(String text, {String fontStyle}) { | |
| 58 assert(text.length <= MAX_STRING_LENGTH); | |
| 59 setFontStyle(fontStyle); | |
| 60 return context.measureText(text).width; | |
| 61 } | |
| 62 | |
| 63 /// Gets length of the longest string in the given [strings]. | |
| 64 /// Optionally, uses [fontStyle] instead of using the default style. | |
| 65 double getLongestTextWidth(Iterable<String> strings, {String fontStyle}) { | |
| 66 setFontStyle(fontStyle); | |
| 67 double maxWidth = 0.0; | |
| 68 for (int i = 0; i < strings.length; ++i) { | |
| 69 assert(strings.elementAt(i).length <= MAX_STRING_LENGTH); | |
| 70 double width = context.measureText(strings.elementAt(i)).width; | |
| 71 if (width > maxWidth) { | |
| 72 maxWidth = width; | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 return maxWidth; | |
| 77 } | |
| 78 | |
| 79 /// Truncates given [text] to fit in [width]. Adds an ellipsis to the | |
| 80 /// returned string, if it needed to be truncated. | |
| 81 /// Optionally, uses [fontStyle] instead of using the default style. | |
| 82 String ellipsizeText(String text, double width, {String fontStyle}) { | |
| 83 assert(text.length <= MAX_STRING_LENGTH); | |
| 84 setFontStyle(fontStyle); | |
| 85 double computedWidth = context.measureText(text).width; | |
| 86 if (computedWidth > width) { | |
| 87 var indices = graphemeBreakIndices(text); | |
| 88 var position = 0, | |
| 89 min = 0, max = indices.length - 1, mid, | |
| 90 ellipsis = context.measureText('…').width; | |
| 91 width = width - ellipsis; | |
| 92 while (max >= min) { | |
| 93 mid = (min + max) ~/ 2; | |
| 94 position = indices[mid]; | |
| 95 if (context.measureText(text.substring(0, position)).width > width) { | |
| 96 max = mid - 1; | |
| 97 } else { | |
| 98 min = mid + 1; | |
| 99 } | |
| 100 } | |
| 101 text = text.substring(0, indices[max]) + '…'; | |
| 102 } | |
| 103 return text; | |
| 104 } | |
| 105 | |
| 106 /// Truncates text in the given [element], which is either a [SvgTextElement] | |
| 107 /// or a [SvgTspanElement] to fit in [width]. Appends an ellipsis to the text | |
| 108 /// if it had to be truncated. | |
| 109 /// Calling this method may force a layout on the document. For better | |
| 110 /// performance, use [TextMetrics.ellipsizeText]. | |
| 111 static ellipsizeTextElement() { | |
| 112 } | |
| 113 } | |
| OLD | NEW |