]> git.proxmox.com Git - sencha-touch.git/blob - src/src/draw/TextMeasurer.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / src / draw / TextMeasurer.js
1 /**
2 * Utility class to provide a way to *approximately* measure the dimension of texts without a drawing context.
3 */
4 Ext.define("Ext.draw.TextMeasurer", {
5 singleton: true,
6
7 uses: ['Ext.draw.engine.Canvas'],
8
9 measureDiv: null,
10 measureCache: {},
11
12 /**
13 * @private Measure the size of a text with specific font by using DOM to measure it.
14 * Could be very expensive therefore should be used lazily.
15 * @param {String} text
16 * @param {String} font
17 * @return {Object} An object with `width` and `height` properties.
18 * @return {Number} return.width
19 * @return {Number} return.height
20 */
21 actualMeasureText: function (text, font) {
22 var me = Ext.draw.TextMeasurer,
23 measureDiv = me.measureDiv,
24 FARAWAY = 100000,
25 size;
26
27 if (!measureDiv) {
28 var parent = Ext.Element.create({
29 style: {
30 "overflow": "hidden",
31 "position": "relative",
32 "float": "left", // DO NOT REMOVE THE QUOTE OR IT WILL BREAK COMPRESSOR
33 "width": 0,
34 "height": 0
35 }
36 });
37 me.measureDiv = measureDiv = Ext.Element.create({});
38 measureDiv.setStyle({
39 "position": 'absolute',
40 "x": FARAWAY,
41 "y": FARAWAY,
42 "z-index": -FARAWAY,
43 "white-space": "nowrap",
44 "display": 'block',
45 "padding": 0,
46 "margin": 0
47 });
48 Ext.getBody().appendChild(parent);
49 parent.appendChild(measureDiv);
50 }
51 if (font) {
52 measureDiv.setStyle({
53 font: font,
54 lineHeight: 'normal'
55 });
56 }
57 measureDiv.setText('(' + text + ')');
58 size = measureDiv.getSize();
59 measureDiv.setText('()');
60 size.width -= measureDiv.getSize().width;
61 return size;
62 },
63
64 /**
65 * Measure a single-line text with specific font.
66 * This will split the text to characters and add up their size.
67 * That may *not* be the exact size of the text as it is displayed.
68 * @param {String} text
69 * @param {String} font
70 * @return {Object} An object with `width` and `height` properties.
71 * @return {Number} return.width
72 * @return {Number} return.height
73 */
74 measureTextSingleLine: function (text, font) {
75 text = text.toString();
76 var cache = this.measureCache,
77 chars = text.split(''),
78 width = 0,
79 height = 0,
80 cachedItem, charactor, i, ln, size;
81
82 if (!cache[font]) {
83 cache[font] = {};
84 }
85 cache = cache[font];
86
87 if (cache[text]) {
88 return cache[text];
89 }
90
91 for (i = 0, ln = chars.length; i < ln; i++) {
92 charactor = chars[i];
93 if (!(cachedItem = cache[charactor])) {
94 size = this.actualMeasureText(charactor, font);
95 cachedItem = cache[charactor] = size;
96 }
97 width += cachedItem.width;
98 height = Math.max(height, cachedItem.height);
99 }
100 return cache[text] = {
101 width: width,
102 height: height
103 };
104 },
105
106 /**
107 * Measure a text with specific font.
108 * This will split the text to lines and add up their size.
109 * That may *not* be the exact size of the text as it is displayed.
110 * @param {String} text
111 * @param {String} font
112 * @return {Object} An object with `width`, `height` and `sizes` properties.
113 * @return {Number} return.width
114 * @return {Number} return.height
115 * @return {Array} return.sizes Results of individual line measurements, in case of multiline text.
116 */
117 measureText: function (text, font) {
118 var lines = text.split('\n'),
119 ln = lines.length,
120 height = 0,
121 width = 0,
122 line, i,
123 sizes;
124
125 if (ln === 1) {
126 return this.measureTextSingleLine(text, font);
127 }
128
129 sizes = [];
130 for (i = 0; i < ln; i++) {
131 line = this.measureTextSingleLine(lines[i], font);
132 sizes.push(line);
133 height += line.height;
134 width = Math.max(width, line.width);
135 }
136
137 return {
138 width: width,
139 height: height,
140 sizes: sizes
141 };
142 }
143 });