1 | import BoundingRect from '../core/BoundingRect.js';
|
2 | import LRU from '../core/LRU.js';
|
3 | import { DEFAULT_FONT, platformApi } from '../core/platform.js';
|
4 | var textWidthCache = {};
|
5 | export function getWidth(text, font) {
|
6 | font = font || DEFAULT_FONT;
|
7 | var cacheOfFont = textWidthCache[font];
|
8 | if (!cacheOfFont) {
|
9 | cacheOfFont = textWidthCache[font] = new LRU(500);
|
10 | }
|
11 | var width = cacheOfFont.get(text);
|
12 | if (width == null) {
|
13 | width = platformApi.measureText(text, font).width;
|
14 | cacheOfFont.put(text, width);
|
15 | }
|
16 | return width;
|
17 | }
|
18 | export function innerGetBoundingRect(text, font, textAlign, textBaseline) {
|
19 | var width = getWidth(text, font);
|
20 | var height = getLineHeight(font);
|
21 | var x = adjustTextX(0, width, textAlign);
|
22 | var y = adjustTextY(0, height, textBaseline);
|
23 | var rect = new BoundingRect(x, y, width, height);
|
24 | return rect;
|
25 | }
|
26 | export function getBoundingRect(text, font, textAlign, textBaseline) {
|
27 | var textLines = ((text || '') + '').split('\n');
|
28 | var len = textLines.length;
|
29 | if (len === 1) {
|
30 | return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline);
|
31 | }
|
32 | else {
|
33 | var uniondRect = new BoundingRect(0, 0, 0, 0);
|
34 | for (var i = 0; i < textLines.length; i++) {
|
35 | var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline);
|
36 | i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect);
|
37 | }
|
38 | return uniondRect;
|
39 | }
|
40 | }
|
41 | export function adjustTextX(x, width, textAlign) {
|
42 | if (textAlign === 'right') {
|
43 | x -= width;
|
44 | }
|
45 | else if (textAlign === 'center') {
|
46 | x -= width / 2;
|
47 | }
|
48 | return x;
|
49 | }
|
50 | export function adjustTextY(y, height, verticalAlign) {
|
51 | if (verticalAlign === 'middle') {
|
52 | y -= height / 2;
|
53 | }
|
54 | else if (verticalAlign === 'bottom') {
|
55 | y -= height;
|
56 | }
|
57 | return y;
|
58 | }
|
59 | export function getLineHeight(font) {
|
60 | return getWidth('国', font);
|
61 | }
|
62 | export function measureText(text, font) {
|
63 | return platformApi.measureText(text, font);
|
64 | }
|
65 | export function parsePercent(value, maxValue) {
|
66 | if (typeof value === 'string') {
|
67 | if (value.lastIndexOf('%') >= 0) {
|
68 | return parseFloat(value) / 100 * maxValue;
|
69 | }
|
70 | return parseFloat(value);
|
71 | }
|
72 | return value;
|
73 | }
|
74 | export function calculateTextPosition(out, opts, rect) {
|
75 | var textPosition = opts.position || 'inside';
|
76 | var distance = opts.distance != null ? opts.distance : 5;
|
77 | var height = rect.height;
|
78 | var width = rect.width;
|
79 | var halfHeight = height / 2;
|
80 | var x = rect.x;
|
81 | var y = rect.y;
|
82 | var textAlign = 'left';
|
83 | var textVerticalAlign = 'top';
|
84 | if (textPosition instanceof Array) {
|
85 | x += parsePercent(textPosition[0], rect.width);
|
86 | y += parsePercent(textPosition[1], rect.height);
|
87 | textAlign = null;
|
88 | textVerticalAlign = null;
|
89 | }
|
90 | else {
|
91 | switch (textPosition) {
|
92 | case 'left':
|
93 | x -= distance;
|
94 | y += halfHeight;
|
95 | textAlign = 'right';
|
96 | textVerticalAlign = 'middle';
|
97 | break;
|
98 | case 'right':
|
99 | x += distance + width;
|
100 | y += halfHeight;
|
101 | textVerticalAlign = 'middle';
|
102 | break;
|
103 | case 'top':
|
104 | x += width / 2;
|
105 | y -= distance;
|
106 | textAlign = 'center';
|
107 | textVerticalAlign = 'bottom';
|
108 | break;
|
109 | case 'bottom':
|
110 | x += width / 2;
|
111 | y += height + distance;
|
112 | textAlign = 'center';
|
113 | break;
|
114 | case 'inside':
|
115 | x += width / 2;
|
116 | y += halfHeight;
|
117 | textAlign = 'center';
|
118 | textVerticalAlign = 'middle';
|
119 | break;
|
120 | case 'insideLeft':
|
121 | x += distance;
|
122 | y += halfHeight;
|
123 | textVerticalAlign = 'middle';
|
124 | break;
|
125 | case 'insideRight':
|
126 | x += width - distance;
|
127 | y += halfHeight;
|
128 | textAlign = 'right';
|
129 | textVerticalAlign = 'middle';
|
130 | break;
|
131 | case 'insideTop':
|
132 | x += width / 2;
|
133 | y += distance;
|
134 | textAlign = 'center';
|
135 | break;
|
136 | case 'insideBottom':
|
137 | x += width / 2;
|
138 | y += height - distance;
|
139 | textAlign = 'center';
|
140 | textVerticalAlign = 'bottom';
|
141 | break;
|
142 | case 'insideTopLeft':
|
143 | x += distance;
|
144 | y += distance;
|
145 | break;
|
146 | case 'insideTopRight':
|
147 | x += width - distance;
|
148 | y += distance;
|
149 | textAlign = 'right';
|
150 | break;
|
151 | case 'insideBottomLeft':
|
152 | x += distance;
|
153 | y += height - distance;
|
154 | textVerticalAlign = 'bottom';
|
155 | break;
|
156 | case 'insideBottomRight':
|
157 | x += width - distance;
|
158 | y += height - distance;
|
159 | textAlign = 'right';
|
160 | textVerticalAlign = 'bottom';
|
161 | break;
|
162 | }
|
163 | }
|
164 | out = out || {};
|
165 | out.x = x;
|
166 | out.y = y;
|
167 | out.align = textAlign;
|
168 | out.verticalAlign = textVerticalAlign;
|
169 | return out;
|
170 | }
|