From abaa87fbd068598f123b244f1965ef9462275c4d Mon Sep 17 00:00:00 2001 From: kangax Date: Fri, 13 May 2011 14:34:24 -0400 Subject: [PATCH] Add `fabric.Text#backgroundColor` (can be used for text highlighting). Change default lineheight of text objects from 1 to 1.6. --- dist/all.js | 53 +++++++++++++++++++++++++++++++++++--------- fabric.js | 2 +- lib/cufon.js | 45 ++++++++++++++++++++++++++++++------- src/text.class.js | 12 ++++++---- test/demo/demo.css | 7 ++++-- test/demo/demo.js | 39 +++++++++++++++++++++++--------- test/demo/index.html | 13 ++++++----- test/unit/text.js | 13 ++++++----- 8 files changed, 137 insertions(+), 47 deletions(-) diff --git a/dist/all.js b/dist/all.js index 025a38ac..8e721bf7 100644 --- a/dist/all.js +++ b/dist/all.js @@ -1,6 +1,6 @@ /*! Fabric.js Copyright 2008-2011, Bitsonnet (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: "0.2.4" }; +var fabric = fabric || { version: "0.2.5" }; /** * Wrapper around `console.log` (when available) @@ -1189,18 +1189,44 @@ Cufon.registerEngine('canvas', (function() { var textDecoration = options.enableTextDecoration ? Cufon.CSS.textDecoration(el, style) : {}, isItalic = options.fontStyle === 'italic'; - g.fillStyle = Cufon.textOptions.color || style.get('color'); + function renderBackground() { + g.save(); + g.fillStyle = options.backgroundColor; - function renderText() { var left = 0; for (var i = 0, l = chars.length; i < l; ++i) { if (chars[i] === '\n') { - g.translate(-left, -font.ascent - ((font.ascent / 5) * options.lineHeight) /* space between lines */); + g.translate(-left, -font.ascent - ((font.ascent / 5) * options.lineHeight)); left = 0; continue; } var glyph = font.glyphs[chars[i]] || font.missingGlyph; + if (!glyph) continue; + var charWidth = Number(glyph.w || font.w) + letterSpacing; + + g.save(); + g.translate(0, font.ascent); + g.fillRect(0, 0, charWidth + 10, -font.ascent + font.descent); + g.restore(); + + g.translate(charWidth, 0); + left += charWidth; + } + g.restore(); + } + + function renderText() { + g.fillStyle = Cufon.textOptions.color || style.get('color'); + + var left = 0; + for (var i = 0, l = chars.length; i < l; ++i) { + if (chars[i] === '\n') { + g.translate(-left, -font.ascent - ((font.ascent / 5) * options.lineHeight)); + left = 0; + continue; + } + var glyph = font.glyphs[chars[i]] || font.missingGlyph; if (!glyph) continue; var charWidth = Number(glyph.w || font.w) + letterSpacing; @@ -1268,6 +1294,7 @@ Cufon.registerEngine('canvas', (function() { } g.save(); + renderBackground(); renderText(); g.restore(); g.restore(); @@ -1333,13 +1360,15 @@ Cufon.registerEngine('vml', (function() { var viewBox = font.viewBox; - var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize)); + var size = style.computedFontSize || + (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize)); var letterSpacing = style.computedLSpacing; if (letterSpacing == undefined) { letterSpacing = style.get('letterSpacing'); - style.computedLSpacing = letterSpacing = (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing)); + style.computedLSpacing = letterSpacing = + (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing)); } var wrapper, canvas; @@ -9501,9 +9530,10 @@ fabric.util.animate = animate; textDecoration: '', textShadow: null, fontStyle: '', - lineHeight: 1, + lineHeight: 1.6, strokeStyle: '', strokeWidth: 1, + backgroundColor: '', path: null, /** @@ -9546,7 +9576,8 @@ fabric.util.animate = animate; 'fontStyle', 'lineHeight', 'strokeStyle', - 'strokeWidth' + 'strokeWidth', + 'backgroundColor' ); fabric.util.removeFromArray(this.stateProperties, 'width'); }, @@ -9587,7 +9618,8 @@ fabric.util.animate = animate; fontStyle: this.fontStyle, lineHeight: this.lineHeight, strokeStyle: this.strokeStyle, - strokeWidth: this.strokeWidth + strokeWidth: this.strokeWidth, + backgroundColor: this.backgroundColor }); this.width = o.width; @@ -9649,7 +9681,8 @@ fabric.util.animate = animate; textShadow: this.textShadow, path: this.path, strokeStyle: this.strokeStyle, - strokeWidth: this.strokeWidth + strokeWidth: this.strokeWidth, + backgroundColor: this.backgroundColor }); }, diff --git a/fabric.js b/fabric.js index e471363c..937e69db 100644 --- a/fabric.js +++ b/fabric.js @@ -1,6 +1,6 @@ /*! Fabric.js Copyright 2008-2011, Bitsonnet (Juriy Zaytsev, Maxim Chernyak) */ -var fabric = fabric || { version: "0.2.4" }; +var fabric = fabric || { version: "0.2.5" }; /** * Wrapper around `console.log` (when available) diff --git a/lib/cufon.js b/lib/cufon.js index 49a6bab4..84e47f47 100644 --- a/lib/cufon.js +++ b/lib/cufon.js @@ -779,19 +779,45 @@ Cufon.registerEngine('canvas', (function() { var textDecoration = options.enableTextDecoration ? Cufon.CSS.textDecoration(el, style) : {}, isItalic = options.fontStyle === 'italic'; - - g.fillStyle = Cufon.textOptions.color || style.get('color'); - - function renderText() { + + function renderBackground() { + g.save(); + g.fillStyle = options.backgroundColor; + var left = 0; for (var i = 0, l = chars.length; i < l; ++i) { if (chars[i] === '\n') { - g.translate(-left, -font.ascent - ((font.ascent / 5) * options.lineHeight) /* space between lines */); + g.translate(-left, -font.ascent - ((font.ascent / 5) * options.lineHeight)); left = 0; continue; } var glyph = font.glyphs[chars[i]] || font.missingGlyph; + if (!glyph) continue; + var charWidth = Number(glyph.w || font.w) + letterSpacing; + + g.save(); + g.translate(0, font.ascent); + g.fillRect(0, 0, charWidth + 10, -font.ascent + font.descent); + g.restore(); + + g.translate(charWidth, 0); + left += charWidth; + } + g.restore(); + } + + function renderText() { + g.fillStyle = Cufon.textOptions.color || style.get('color'); + + var left = 0; + for (var i = 0, l = chars.length; i < l; ++i) { + if (chars[i] === '\n') { + g.translate(-left, -font.ascent - ((font.ascent / 5) * options.lineHeight)); + left = 0; + continue; + } + var glyph = font.glyphs[chars[i]] || font.missingGlyph; if (!glyph) continue; var charWidth = Number(glyph.w || font.w) + letterSpacing; @@ -846,7 +872,7 @@ Cufon.registerEngine('canvas', (function() { left += charWidth; } } - + if (shadows) { for (var i = 0, l = shadows.length; i < l; ++i) { var shadow = shadows[i]; @@ -859,6 +885,7 @@ Cufon.registerEngine('canvas', (function() { } g.save(); + renderBackground(); renderText(); g.restore(); g.restore(); @@ -927,13 +954,15 @@ Cufon.registerEngine('vml', (function() { var viewBox = font.viewBox; - var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize)); + var size = style.computedFontSize || + (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize)); var letterSpacing = style.computedLSpacing; if (letterSpacing == undefined) { letterSpacing = style.get('letterSpacing'); - style.computedLSpacing = letterSpacing = (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing)); + style.computedLSpacing = letterSpacing = + (letterSpacing == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, letterSpacing)); } var wrapper, canvas; diff --git a/src/text.class.js b/src/text.class.js index 7f84af8c..c9500383 100644 --- a/src/text.class.js +++ b/src/text.class.js @@ -29,9 +29,10 @@ textDecoration: '', textShadow: null, fontStyle: '', - lineHeight: 1, + lineHeight: 1.6, strokeStyle: '', strokeWidth: 1, + backgroundColor: '', path: null, /** @@ -74,7 +75,8 @@ 'fontStyle', 'lineHeight', 'strokeStyle', - 'strokeWidth' + 'strokeWidth', + 'backgroundColor' ); fabric.util.removeFromArray(this.stateProperties, 'width'); }, @@ -118,7 +120,8 @@ fontStyle: this.fontStyle, lineHeight: this.lineHeight, strokeStyle: this.strokeStyle, - strokeWidth: this.strokeWidth + strokeWidth: this.strokeWidth, + backgroundColor: this.backgroundColor }); // update width, height @@ -184,7 +187,8 @@ textShadow: this.textShadow, path: this.path, strokeStyle: this.strokeStyle, - strokeWidth: this.strokeWidth + strokeWidth: this.strokeWidth, + backgroundColor: this.backgroundColor }); }, diff --git a/test/demo/demo.css b/test/demo/demo.css index 2ce4d75e..c53ed25d 100644 --- a/test/demo/demo.css +++ b/test/demo/demo.css @@ -9,8 +9,11 @@ h2 { background: #ffc; margin-top: 0; padding: 5px; color: #333; font-size: 1em; #rasterize { margin-top: 10px; color: green; } #complexity { clear: both; padding-top: 10px; } #controls { margin-bottom: 5px; } -#text-controls { clear: both; margin-top: 20px } -#text-controls button { vertical-align: top; } +#text-controls { clear: both; margin-top: 20px; overflow: hidden; } +#text-controls textarea { float: left; margin-right: 10px; } +#text-controls button { vertical-align: top; display: block; margin-bottom: 7px; } +#text-controls label { display: block; } +#text-control-buttons { float: left; } #drawing-mode-options { margin-top: 5px; background: #ffc; padding: 5px; border: 1px solid #aaa; } #text { position: relative; width: 350px; height: 200px; } #text-cmd-linethrough { text-decoration: line-through; } diff --git a/test/demo/demo.js b/test/demo/demo.js index 40f29b62..36a719bd 100644 --- a/test/demo/demo.js +++ b/test/demo/demo.js @@ -393,14 +393,20 @@ canvas.freeDrawingLineWidth = parseInt(drawingLineWidthEl.value, 10) || 1; - var helloWorld = new fabric.Text('Hello world!', { - left: getRandomInt(100, 650), - top: getRandomInt(100, 650), + var text = 'Lorem ipsum dolor sit amet,\nconsectetur adipisicing elit,\nsed do eiusmod tempor incididunt\nut labore et dolore magna aliqua.\n' + + 'Ut enim ad minim veniam,\nquis nostrud exercitation ullamco\nlaboris nisi ut aliquip ex ea commodo consequat.'; + + var textSample = new fabric.Text(text, { + left: getRandomInt(300, 550), + top: getRandomInt(500, 550), fontfamily: 'delicious_500', - angle: getRandomInt(-20, 20) + angle: getRandomInt(-10, 10), + fill: '#' + getRandomColor(), + scaleX: 0.5, + scaleY: 0.5 }); - canvas.add(helloWorld); + canvas.add(textSample); updateComplexity(); @@ -530,19 +536,30 @@ }; } + var bgColorField = document.getElementById('text-bg-color'); + if (bgColorField) { + bgColorField.onchange = function() { + var activeObject = canvas.getActiveObject(); + if (activeObject && activeObject.type === 'text') { + activeObject.backgroundColor = this.value; + canvas.renderAll(); + } + }; + } + if (supportsSlider) { (function(){ - var container = document.getElementById('text-controls'); + var container = document.getElementById('text-control-buttons'); var slider = document.createElement('input'); - // var label = document.createElement('label'); - // label.innerHTML = 'Line height'; + var label = document.createElement('label'); + label.innerHTML = 'Line height: '; slider.type = 'range'; slider.min = -2; slider.max = 10; slider.step = 0.1; - slider.value = 1; - // container.appendChild(label); - container.appendChild(slider); + slider.value = 1.5; + container.appendChild(label); + label.appendChild(slider); slider.title = "Line height"; slider.onchange = function(){ var activeObject = canvas.getActiveObject(); diff --git a/test/demo/index.html b/test/demo/index.html index 37fc741f..846e0701 100644 --- a/test/demo/index.html +++ b/test/demo/index.html @@ -34,11 +34,14 @@
Canvas complexity (number of paths):
- - - - - +
+ + + + + + +
diff --git a/test/unit/text.js b/test/unit/text.js index 6f0a91f1..d7ef0906 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -27,12 +27,13 @@ 'fontsize': 20, 'fontweight': 100, 'fontfamily': 'Modernist_One_400', - "lineHeight": 1, - "textDecoration": '', - "textShadow": null, - "strokeStyle": '', - "fontStyle": '', - "path": null + 'lineHeight': 1.6, + 'textDecoration': '', + 'textShadow': null, + 'strokeStyle': '', + 'fontStyle': '', + 'path': null, + 'backgroundColor': '' }; module('fabric.Text');