@@ -16,6 +16,8 @@ define(function (require) {
16
16
p5 . prototype . _textFont = 'sans-serif' ;
17
17
p5 . prototype . _textSize = 12 ;
18
18
p5 . prototype . _textStyle = constants . NORMAL ;
19
+ p5 . prototype . _textAscent = null ;
20
+ p5 . prototype . _textDescent = null ;
19
21
20
22
/**
21
23
* Sets the current alignment for drawing text. The parameters LEFT, CENTER,
@@ -46,27 +48,6 @@ define(function (require) {
46
48
}
47
49
} ;
48
50
49
- /**
50
- * Calculates and returns the height of any character or text string.
51
- *
52
- * @method textHeight
53
- * @param {String } s the String of characters to measure
54
- * @example
55
- * <div>
56
- * <code>
57
- * background(0);
58
- * fill(255);
59
- * textSize(14);
60
- * s = "String.";
61
- * text(s, 10, 23);
62
- * console.log(textHeight(s));
63
- * </code>
64
- * </div>
65
- */
66
- p5 . prototype . textHeight = function ( s ) {
67
- return this . drawingContext . measureText ( s ) . height ;
68
- } ;
69
-
70
51
/**
71
52
* Sets the spacing between lines of text in units of pixels. This
72
53
* setting will be used in all subsequent calls to the text() function.
@@ -173,15 +154,126 @@ define(function (require) {
173
154
return this . drawingContext . measureText ( s ) . width ;
174
155
} ;
175
156
157
+ /**
158
+ * Returns ascent of the current font at its current size.
159
+ * @example
160
+ * <div>
161
+ * <code>
162
+ * var base = height * 0.75;
163
+ * var scalar = 0.8; // Different for each font
164
+ *
165
+ * textSize(32); // Set initial text size
166
+ * var a = textAscent() * scalar; // Calc ascent
167
+ * line(0, base-a, width, base-a);
168
+ * text("dp", 0, base); // Draw text on baseline
169
+ *
170
+ * textSize(64); // Increase text size
171
+ * a = textAscent() * scalar; // Recalc ascent
172
+ * line(40, base-a, width, base-a);
173
+ * text("dp", 40, base); // Draw text on baseline
174
+ * </code>
175
+ * </div>
176
+ */
177
+ p5 . prototype . textAscent = function ( ) {
178
+ if ( this . _textAscent == null ) { this . _updateTextMetrics ( ) ; }
179
+ return this . _textAscent ;
180
+ } ;
181
+
182
+ /**
183
+ * Returns descent of the current font at its current size.
184
+ * @example
185
+ * <div>
186
+ * <code>
187
+ * var base = height * 0.75;
188
+ * var scalar = 0.8; // Different for each font
189
+ *
190
+ * textSize(32); // Set initial text size
191
+ * var a = textDescent() * scalar; // Calc ascent
192
+ * line(0, base+a, width, base+a);
193
+ * text("dp", 0, base); // Draw text on baseline
194
+ *
195
+ * textSize(64); // Increase text size
196
+ * a = textDescent() * scalar; // Recalc ascent
197
+ * line(40, base+a, width, base+a);
198
+ * text("dp", 40, base); // Draw text on baseline
199
+ * </code>
200
+ * </div>
201
+ */
202
+ p5 . prototype . textDescent = function ( ) {
203
+ if ( this . _textDescent == null ) { this . _updateTextMetrics ( ) ; }
204
+ return this . _textDescent ;
205
+ } ;
206
+
176
207
/**
177
208
* Helper fxn to apply text properties.
178
- *
179
209
*/
180
210
p5 . prototype . _applyTextProperties = function ( ) {
211
+ this . _setProperty ( '_textAscent' , null ) ;
212
+ this . _setProperty ( '_textDescent' , null ) ;
213
+
181
214
var str = this . _textStyle + ' ' + this . _textSize + 'px ' + this . _textFont ;
182
215
this . drawingContext . font = str ;
183
216
} ;
184
217
218
+ /**
219
+ * Helper fxn to measure ascent and descent.
220
+ * Adapted from http://stackoverflow.com/a/25355178
221
+ */
222
+ p5 . prototype . _updateTextMetrics = function ( ) {
223
+
224
+ var text = document . createElement ( 'span' ) ;
225
+ text . style . fontFamily = this . _textFont ;
226
+ text . style . fontSize = this . _textSize + 'px' ;
227
+ text . innerHTML = 'ABCjgq|' ;
228
+
229
+ var block = document . createElement ( 'div' ) ;
230
+ block . style . display = 'inline-block' ;
231
+ block . style . width = '1px' ;
232
+ block . style . height = '0px' ;
233
+
234
+ var container = document . createElement ( 'div' ) ;
235
+ container . appendChild ( text ) ;
236
+ container . appendChild ( block ) ;
237
+
238
+ container . style . height = '0px' ;
239
+ container . style . overflow = 'hidden' ;
240
+ document . body . appendChild ( container ) ;
241
+
242
+ block . style . verticalAlign = 'baseline' ;
243
+ var blockOffset = this . _calculateOffset ( block ) ;
244
+ var textOffset = this . _calculateOffset ( text ) ;
245
+ var ascent = blockOffset [ 1 ] - textOffset [ 1 ] ;
246
+
247
+ block . style . verticalAlign = 'bottom' ;
248
+ blockOffset = this . _calculateOffset ( block ) ;
249
+ textOffset = this . _calculateOffset ( text ) ;
250
+ var height = blockOffset [ 1 ] - textOffset [ 1 ] ;
251
+ var descent = height - ascent ;
252
+
253
+ document . body . removeChild ( container ) ;
254
+
255
+ this . _setProperty ( '_textAscent' , ascent ) ;
256
+ this . _setProperty ( '_textDescent' , descent ) ;
257
+ } ;
258
+
259
+ /**
260
+ * Helper fxn to measure ascent and descent.
261
+ * Adapted from http://stackoverflow.com/a/25355178
262
+ */
263
+ p5 . prototype . _calculateOffset = function ( object ) {
264
+ var currentLeft = 0 , currentTop = 0 ;
265
+ if ( object . offsetParent ) {
266
+ do {
267
+ currentLeft += object . offsetLeft ;
268
+ currentTop += object . offsetTop ;
269
+ } while ( object = object . offsetParent ) ;
270
+ } else {
271
+ currentLeft += object . offsetLeft ;
272
+ currentTop += object . offsetTop ;
273
+ }
274
+ return [ currentLeft , currentTop ] ;
275
+ } ;
276
+
185
277
return p5 ;
186
278
187
279
} ) ;
0 commit comments