Fix text alignment in SVG export. Center- and right-aligned text now displays properly. Add more tests to SVG export test suite.

This commit is contained in:
kangax 2012-01-04 17:18:42 -05:00
parent ffc8362b4a
commit c451f32c9f
7 changed files with 71 additions and 53 deletions

View file

@ -1,6 +1,6 @@
/*! Fabric.js Copyright 2008-2011, Bitsonnet (Juriy Zaytsev, Maxim Chernyak) */
var fabric = fabric || { version: "0.7.5" };
var fabric = fabric || { version: "0.7.6" };
if (typeof exports != 'undefined') {
exports.fabric = fabric;

59
dist/all.js vendored
View file

@ -1,6 +1,6 @@
/*! Fabric.js Copyright 2008-2011, Bitsonnet (Juriy Zaytsev, Maxim Chernyak) */
var fabric = fabric || { version: "0.7.5" };
var fabric = fabric || { version: "0.7.6" };
if (typeof exports != 'undefined') {
exports.fabric = fabric;
@ -1253,6 +1253,7 @@ Cufon.registerEngine('canvas', (function() {
scale = roundedHeight / viewBox.height;
Cufon.textOptions.fontAscent = font.ascent * scale;
Cufon.textOptions.boundaries = null;
g.save();
g.scale(scale, scale);
@ -1287,15 +1288,16 @@ Cufon.registerEngine('canvas', (function() {
g.fillStyle = options.backgroundColor;
var left = 0, lineNum = 0;
var left = 0, lineNum = 0, boundaries = [{ left: 0 }];
if (options.textAlign === 'right') {
g.translate(lineOffsets[lineNum], 0);
boundaries[0].left = lineOffsets[lineNum] * scale;
}
else if (options.textAlign === 'center') {
g.translate(lineOffsets[lineNum] / 2, 0);
boundaries[0].left = lineOffsets[lineNum] / 2 * scale;
}
var bgBoundaries = [];
for (var i = 0, l = chars.length; i < l; ++i) {
if (chars[i] === '\n') {
@ -1303,25 +1305,30 @@ Cufon.registerEngine('canvas', (function() {
lineNum++;
var topOffset = -font.ascent - ((font.ascent / 5) * options.lineHeight);
var boundary = boundaries[boundaries.length - 1];
var nextBoundary = { left: 0 };
boundary.width = left * scale;
boundary.height = (-font.ascent + font.descent) * scale;
if (options.textAlign === 'right') {
g.translate(-width, topOffset);
g.translate(lineOffsets[lineNum], 0);
nextBoundary.left = lineOffsets[lineNum] * scale;
}
else if (options.textAlign === 'center') {
// offset to the start of text in previous line AND half of its offset
// (essentially moving caret to the left edge of bounding box)
g.translate(-left - (lineOffsets[lineNum - 1] / 2), topOffset);
g.translate(lineOffsets[lineNum] / 2, 0);
nextBoundary.left = lineOffsets[lineNum] / 2 * scale;
}
else {
g.translate(-left, topOffset);
}
bgBoundaries.push({
width: left * scale,
height: (-font.ascent + font.descent) * scale
});
/* push next boundary (for the next line) */
boundaries.push(nextBoundary);
left = 0;
@ -1332,24 +1339,25 @@ Cufon.registerEngine('canvas', (function() {
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();
// only draw background when there's some kind of value
if (options.backgroundColor) {
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;
if (i == l-1) {
bgBoundaries.push({
width: left * scale,
height: (-font.ascent + font.descent) * scale
});
boundaries[boundaries.length - 1].width = left * scale;
boundaries[boundaries.length - 1].height = (-font.ascent + font.descent) * scale;
}
}
g.restore();
Cufon.textOptions.bgBoundaries = bgBoundaries;
Cufon.textOptions.boundaries = boundaries;
}
function renderText() {
@ -1461,9 +1469,7 @@ Cufon.registerEngine('canvas', (function() {
}
g.save();
if (options.backgroundColor) {
renderBackground();
}
renderBackground();
renderText();
g.restore();
g.restore();
@ -11569,7 +11575,7 @@ fabric.Image.filters.RemoveWhite.fromObject = function(object) {
this.height = o.height;
this._totalLineHeight = o.totalLineHeight;
this._fontAscent = o.fontAscent;
this._bgBoundaries = o.bgBoundaries;
this._boundaries = o.boundaries;
// need to set coords _after_ the width/height was retreived from Cufon
this.setCoords();
@ -11656,22 +11662,25 @@ fabric.Image.filters.RemoveWhite.fromObject = function(object) {
textTopOffset = (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight;
for (var i = 0, len = textLines.length; i < len; i++) {
textSpans.push('<tspan x="0" dy="', lineTopOffset, '">', textLines[i], '</tspan>');
var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0;
textSpans.push('<tspan x="', lineLeftOffset, '" dy="', lineTopOffset, '">', textLines[i], '</tspan>');
if (!this.backgroundColor) continue;
textBgRects.push(
'<rect fill="',
this.backgroundColor,
'" x="',
textLeftOffset,
textLeftOffset + this._boundaries[i].left,
'" y="',
(lineTopOffset * i) - this.height / 2 + (this.lineHeight * 2.6) /* an offset that seems to straighten things out */,
'" width="',
this._bgBoundaries[i].width,
this._boundaries[i].width,
'" height="',
this._bgBoundaries[i].height,
this._boundaries[i].height,
'"></rect>');
}
return [
'<g transform="', this.getSvgTransform(), '">',
textBgRects.join(''),

4
dist/all.min.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/all.min.js.gz vendored

Binary file not shown.

View file

@ -747,6 +747,7 @@ Cufon.registerEngine('canvas', (function() {
scale = roundedHeight / viewBox.height;
Cufon.textOptions.fontAscent = font.ascent * scale;
Cufon.textOptions.boundaries = null;
g.save();
g.scale(scale, scale);
@ -781,15 +782,16 @@ Cufon.registerEngine('canvas', (function() {
g.fillStyle = options.backgroundColor;
var left = 0, lineNum = 0;
var left = 0, lineNum = 0, boundaries = [{ left: 0 }];
if (options.textAlign === 'right') {
g.translate(lineOffsets[lineNum], 0);
boundaries[0].left = lineOffsets[lineNum] * scale;
}
else if (options.textAlign === 'center') {
g.translate(lineOffsets[lineNum] / 2, 0);
boundaries[0].left = lineOffsets[lineNum] / 2 * scale;
}
var bgBoundaries = [];
for (var i = 0, l = chars.length; i < l; ++i) {
if (chars[i] === '\n') {
@ -797,25 +799,30 @@ Cufon.registerEngine('canvas', (function() {
lineNum++;
var topOffset = -font.ascent - ((font.ascent / 5) * options.lineHeight);
var boundary = boundaries[boundaries.length - 1];
var nextBoundary = { left: 0 };
boundary.width = left * scale;
boundary.height = (-font.ascent + font.descent) * scale;
if (options.textAlign === 'right') {
g.translate(-width, topOffset);
g.translate(lineOffsets[lineNum], 0);
nextBoundary.left = lineOffsets[lineNum] * scale;
}
else if (options.textAlign === 'center') {
// offset to the start of text in previous line AND half of its offset
// (essentially moving caret to the left edge of bounding box)
g.translate(-left - (lineOffsets[lineNum - 1] / 2), topOffset);
g.translate(lineOffsets[lineNum] / 2, 0);
nextBoundary.left = lineOffsets[lineNum] / 2 * scale;
}
else {
g.translate(-left, topOffset);
}
bgBoundaries.push({
width: left * scale,
height: (-font.ascent + font.descent) * scale
});
/* push next boundary (for the next line) */
boundaries.push(nextBoundary);
left = 0;
@ -826,24 +833,25 @@ Cufon.registerEngine('canvas', (function() {
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();
// only draw background when there's some kind of value
if (options.backgroundColor) {
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;
if (i == l-1) {
bgBoundaries.push({
width: left * scale,
height: (-font.ascent + font.descent) * scale
});
boundaries[boundaries.length - 1].width = left * scale;
boundaries[boundaries.length - 1].height = (-font.ascent + font.descent) * scale;
}
}
g.restore();
Cufon.textOptions.bgBoundaries = bgBoundaries;
Cufon.textOptions.boundaries = boundaries;
}
function renderText() {
@ -955,9 +963,7 @@ Cufon.registerEngine('canvas', (function() {
}
g.save();
if (options.backgroundColor) {
renderBackground();
}
renderBackground();
renderText();
g.restore();
g.restore();

View file

@ -1,7 +1,7 @@
{
"name": "fabric",
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
"version": "0.7.5",
"version": "0.7.6",
"author": "Juriy Zaytsev <kangax@gmail.com>",
"keywords": ["canvas", "graphic", "graphics", "SVG", "node-canvas", "parser", "HTML5", "object model"],
"repository": "git://github.com/kangax/fabric.js",

View file

@ -194,7 +194,7 @@
this.height = o.height;
this._totalLineHeight = o.totalLineHeight;
this._fontAscent = o.fontAscent;
this._bgBoundaries = o.bgBoundaries;
this._boundaries = o.boundaries;
// need to set coords _after_ the width/height was retreived from Cufon
this.setCoords();
@ -281,22 +281,25 @@
textTopOffset = (this.height/2) - (textLines.length * this.fontSize) - this._totalLineHeight;
for (var i = 0, len = textLines.length; i < len; i++) {
textSpans.push('<tspan x="0" dy="', lineTopOffset, '">', textLines[i], '</tspan>');
var lineLeftOffset = (this._boundaries && this._boundaries[i]) ? this._boundaries[i].left : 0;
textSpans.push('<tspan x="', lineLeftOffset, '" dy="', lineTopOffset, '">', textLines[i], '</tspan>');
if (!this.backgroundColor) continue;
textBgRects.push(
'<rect fill="',
this.backgroundColor,
'" x="',
textLeftOffset,
textLeftOffset + this._boundaries[i].left,
'" y="',
(lineTopOffset * i) - this.height / 2 + (this.lineHeight * 2.6) /* an offset that seems to straighten things out */,
'" width="',
this._bgBoundaries[i].width,
this._boundaries[i].width,
'" height="',
this._bgBoundaries[i].height,
this._boundaries[i].height,
'"></rect>');
}
return [
'<g transform="', this.getSvgTransform(), '">',
textBgRects.join(''),