55 */
66
77var p5 = require ( './core' ) ;
8+ var constants = require ( '../core/constants' ) ;
89
910/**
1011 * Main graphics and rendering context, as well as the base API
@@ -33,6 +34,15 @@ p5.Renderer = function(elt, pInst, isMainCanvas) {
3334 this . canvas . style . display = 'none' ;
3435 this . _styles = [ ] ; // non-main elt styles stored in p5.Renderer
3536 }
37+
38+
39+ this . _textSize = 12 ;
40+ this . _textLeading = 15 ;
41+ this . _textFont = 'sans-serif' ;
42+ this . _textStyle = constants . NORMAL ;
43+ this . _textAscent = null ;
44+ this . _textDescent = null ;
45+
3646} ;
3747
3848p5 . Renderer . prototype = Object . create ( p5 . Element . prototype ) ;
@@ -53,4 +63,283 @@ p5.Renderer.prototype.resize = function(w, h) {
5363 }
5464} ;
5565
66+
67+ /**
68+ * Sets/gets the spacing between lines of text in units of pixels. This
69+ * setting will be used in all subsequent calls to the text() function.
70+ *
71+ * @method textLeading
72+ * @param {Number } l the size in pixels for spacing between lines
73+ * @return {Object|Number }
74+ * @example
75+ * <div>
76+ * <code>
77+ * // Text to display. The "\n" is a "new line" character
78+ * lines = "L1\nL2\nL3";
79+ * textSize(12);
80+ * fill(0); // Set fill to black
81+ *
82+ * textLeading(10); // Set leading to 10
83+ * text(lines, 10, 25);
84+ *
85+ * textLeading(20); // Set leading to 20
86+ * text(lines, 40, 25);
87+ *
88+ * textLeading(30); // Set leading to 30
89+ * text(lines, 70, 25);
90+ * </code>
91+ * </div>
92+ */
93+ p5 . Renderer . prototype . textLeading = function ( l ) {
94+
95+ if ( arguments . length ) {
96+
97+ this . _setProperty ( '_textLeading' , l ) ;
98+ return this ;
99+ }
100+
101+ return this . _textLeading ;
102+ } ;
103+
104+ /**
105+ * Sets/gets the current font size. This size will be used in all subsequent
106+ * calls to the text() function. Font size is measured in units of pixels.
107+ *
108+ * @method textSize
109+ * @param {Number } s the size of the letters in units of pixels
110+ * @return {Object|Number }
111+ * @example
112+ * <div>
113+ * <code>
114+ * textSize(12);
115+ * text("Font Size 12", 10, 30);
116+ * textSize(14);
117+ * text("Font Size 14", 10, 60);
118+ * textSize(16);
119+ * text("Font Size 16", 10, 90);
120+ * </code>
121+ * </div>
122+ */
123+ p5 . Renderer . prototype . textSize = function ( s ) {
124+
125+ if ( arguments . length ) {
126+
127+ this . _setProperty ( '_textSize' , s ) ;
128+ this . _setProperty ( '_textLeading' , s * constants . _DEFAULT_LEADMULT ) ;
129+ return this . _applyTextProperties ( ) ;
130+ }
131+
132+ return this . _textSize ;
133+ } ;
134+
135+ /**
136+ * Sets/gets the style of the text to NORMAL, ITALIC, or BOLD. Note this is
137+ * overridden by CSS styling.
138+ * (Style only apply to system font, for custom fonts, please load styled
139+ * fonts instead.)
140+ *
141+ * @method textStyle
142+ * @param {Number/Constant } s styling for text, either NORMAL,
143+ * ITALIC, or BOLD
144+ * @return {Object|String }
145+ * @example
146+ * <div>
147+ * <code>
148+ * fill(0);
149+ * strokeWeight(0);
150+ * textSize(12);
151+ * textStyle(NORMAL);
152+ * text("Font Style Normal", 10, 30);
153+ * textStyle(ITALIC);
154+ * text("Font Style Italic", 10, 60);
155+ * textStyle(BOLD);
156+ * text("Font Style Bold", 10, 90);
157+ * </code>
158+ * </div>
159+ */
160+ p5 . Renderer . prototype . textStyle = function ( s ) {
161+
162+ if ( arguments . length ) {
163+
164+ if ( s === constants . NORMAL ||
165+ s === constants . ITALIC ||
166+ s === constants . BOLD ) {
167+ this . _setProperty ( '_textStyle' , s ) ;
168+ }
169+
170+ return this . _applyTextProperties ( ) ;
171+ }
172+
173+ return this . _textStyle ;
174+ } ;
175+
176+
177+ /**
178+ * Returns ascent of the current font at its current size.
179+ * @return {Number }
180+ * @example
181+ * <div>
182+ * <code>
183+ * var base = height * 0.75;
184+ * var scalar = 0.8; // Different for each font
185+ *
186+ * textSize(32); // Set initial text size
187+ * var a = textAscent() * scalar; // Calc ascent
188+ * line(0, base-a, width, base-a);
189+ * text("dp", 0, base); // Draw text on baseline
190+ *
191+ * textSize(64); // Increase text size
192+ * a = textAscent() * scalar; // Recalc ascent
193+ * line(40, base-a, width, base-a);
194+ * text("dp", 40, base); // Draw text on baseline
195+ * </code>
196+ * </div>
197+ */
198+ p5 . Renderer . prototype . textAscent = function ( ) {
199+ if ( this . _textAscent === null ) {
200+ this . _updateTextMetrics ( ) ;
201+ }
202+ return this . _textAscent ;
203+ } ;
204+
205+ /*p5.prototype.fontMetrics = function(font, text, x, y, fontSize) {
206+
207+ var xMins = [], yMins = [], xMaxs= [], yMaxs = [], p5 = this;
208+ //font = font || this._textFont;
209+ fontSize = fontSize || p5._textSize;
210+
211+ font.forEachGlyph(text, x, y, fontSize,
212+ {}, function(glyph, gX, gY, gFontSize) {
213+
214+ var gm = glyph.getMetrics();
215+
216+ gX = gX !== undefined ? gX : 0;
217+ gY = gY !== undefined ? gY : 0;
218+ fontSize = fontSize !== undefined ? fontSize : 24;
219+
220+ var scale = 1 / font.unitsPerEm * fontSize;
221+
222+ p5.noFill();
223+ p5.rectMode(p5.CORNERS);
224+ p5.rect(gX + (gm.xMin * scale), gY + (-gm.yMin * scale),
225+ gX + (gm.xMax * scale), gY + (-gm.yMax * scale));
226+
227+ p5.rectMode(p5.CORNER);
228+ });
229+
230+ return { // metrics
231+ xMin: Math.min.apply(null, xMins),
232+ yMin: Math.min.apply(null, yMins),
233+ xMax: Math.max.apply(null, xMaxs),
234+ yMax: Math.max.apply(null, yMaxs)
235+ };
236+ };*/
237+
238+ /**
239+ * Returns descent of the current font at its current size.
240+ * @return {Number }
241+ * @example
242+ * <div>
243+ * <code>
244+ * var base = height * 0.75;
245+ * var scalar = 0.8; // Different for each font
246+ *
247+ * textSize(32); // Set initial text size
248+ * var a = textDescent() * scalar; // Calc ascent
249+ * line(0, base+a, width, base+a);
250+ * text("dp", 0, base); // Draw text on baseline
251+ *
252+ * textSize(64); // Increase text size
253+ * a = textDescent() * scalar; // Recalc ascent
254+ * line(40, base+a, width, base+a);
255+ * text("dp", 40, base); // Draw text on baseline
256+ * </code>
257+ * </div>
258+ */
259+ p5 . Renderer . prototype . textDescent = function ( ) {
260+
261+ if ( this . _textDescent === null ) {
262+ this . _updateTextMetrics ( ) ;
263+ }
264+ return this . _textDescent ;
265+ } ;
266+
267+ /**
268+ * Helper fxn to check font type (system or otf)
269+ */
270+ p5 . Renderer . prototype . _isOpenType = function ( f ) {
271+
272+ f = f || this . _textFont ;
273+ return ( typeof f === 'object' && f . font && f . font . supported ) ;
274+ } ;
275+
276+ /**
277+ * Helper fxn to measure ascent and descent.
278+ */
279+ p5 . Renderer . prototype . _updateTextMetrics = function ( ) {
280+
281+ if ( this . _isOpenType ( ) ) {
282+
283+ this . _setProperty ( '_textAscent' , this . _textFont . _textAscent ( ) ) ;
284+ this . _setProperty ( '_textDescent' , this . _textFont . _textDescent ( ) ) ;
285+ return this ;
286+ }
287+
288+ // Adapted from http://stackoverflow.com/a/25355178
289+ var text = document . createElement ( 'span' ) ;
290+ text . style . fontFamily = this . _textFont ;
291+ text . style . fontSize = this . _textSize + 'px' ;
292+ text . innerHTML = 'ABCjgq|' ;
293+
294+ var block = document . createElement ( 'div' ) ;
295+ block . style . display = 'inline-block' ;
296+ block . style . width = '1px' ;
297+ block . style . height = '0px' ;
298+
299+ var container = document . createElement ( 'div' ) ;
300+ container . appendChild ( text ) ;
301+ container . appendChild ( block ) ;
302+
303+ container . style . height = '0px' ;
304+ container . style . overflow = 'hidden' ;
305+ document . body . appendChild ( container ) ;
306+
307+ block . style . verticalAlign = 'baseline' ;
308+ var blockOffset = calculateOffset ( block ) ;
309+ var textOffset = calculateOffset ( text ) ;
310+ var ascent = blockOffset [ 1 ] - textOffset [ 1 ] ;
311+
312+ block . style . verticalAlign = 'bottom' ;
313+ blockOffset = calculateOffset ( block ) ;
314+ textOffset = calculateOffset ( text ) ;
315+ var height = blockOffset [ 1 ] - textOffset [ 1 ] ;
316+ var descent = height - ascent ;
317+
318+ document . body . removeChild ( container ) ;
319+
320+ this . _setProperty ( '_textAscent' , ascent ) ;
321+ this . _setProperty ( '_textDescent' , descent ) ;
322+
323+ return this ;
324+ } ;
325+
326+ /**
327+ * Helper fxn to measure ascent and descent.
328+ * Adapted from http://stackoverflow.com/a/25355178
329+ */
330+ function calculateOffset ( object ) {
331+ var currentLeft = 0 ,
332+ currentTop = 0 ;
333+ if ( object . offsetParent ) {
334+ do {
335+ currentLeft += object . offsetLeft ;
336+ currentTop += object . offsetTop ;
337+ } while ( object = object . offsetParent ) ;
338+ } else {
339+ currentLeft += object . offsetLeft ;
340+ currentTop += object . offsetTop ;
341+ }
342+ return [ currentLeft , currentTop ] ;
343+ }
344+
56345module . exports = p5 . Renderer ;
0 commit comments