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 |