Update text.js

This commit is contained in:
Andrea Bogazzi 2014-10-21 22:50:34 +02:00
parent 51fcd6cc52
commit 552c6a833c
5 changed files with 101 additions and 71 deletions

View file

@ -49,3 +49,4 @@ fabric.SHARED_ATTRIBUTES = [
* Pixel per Inch as a default value set to 96. Can be changed for more realistic conversion.
*/
fabric.DPI = 96;
fabric.reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)';

View file

@ -649,7 +649,7 @@
angle = 360 + angle;
}
t.target.angle = angle;
t.target.angle = angle % 360;
},
/**

View file

@ -56,7 +56,7 @@
return attr;
}
function normalizeValue(attr, value, parentAttributes) {
function normalizeValue(attr, value, parentAttributes, fontSize) {
var isArray = Object.prototype.toString.call(value) === '[object Array]',
parsed;
@ -88,7 +88,7 @@
value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';
}
else {
parsed = isArray ? value.map(parseUnit) : parseUnit(value);
parsed = isArray ? value.map(parseUnit) : parseUnit(value, fontSize);
}
return (!isArray && isNaN(parsed) ? value : parsed);
@ -167,7 +167,7 @@
],
// == begin transform regexp
number = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)',
number = fabric.reNum,
commaWsp = '(?:\\s+,?\\s*|,\\s*)',
@ -270,40 +270,6 @@
};
})();
function parseFontDeclaration(value, oStyle) {
// TODO: support non-px font size
var match = value.match(/(normal|italic)?\s*(normal|small-caps)?\s*(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\s*(\d+)px(?:\/(normal|[\d\.]+))?\s+(.*)/);
if (!match) {
return;
}
var fontStyle = match[1],
// font variant is not used
// fontVariant = match[2],
fontWeight = match[3],
fontSize = match[4],
lineHeight = match[5],
fontFamily = match[6];
if (fontStyle) {
oStyle.fontStyle = fontStyle;
}
if (fontWeight) {
oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
}
if (fontSize) {
oStyle.fontSize = parseFloat(fontSize);
}
if (fontFamily) {
oStyle.fontFamily = fontFamily;
}
if (lineHeight) {
oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;
}
}
/**
* @private
*/
@ -315,12 +281,7 @@
attr = normalizeAttr(pair[0].trim().toLowerCase());
value = normalizeValue(attr, pair[1].trim());
if (attr === 'font') {
parseFontDeclaration(value, oStyle);
}
else {
oStyle[attr] = value;
}
oStyle[attr] = value;
});
}
@ -337,12 +298,7 @@
attr = normalizeAttr(prop.toLowerCase());
value = normalizeValue(attr, style[prop]);
if (attr === 'font') {
parseFontDeclaration(value, oStyle);
}
else {
oStyle[attr] = value;
}
oStyle[attr] = value;
}
}
@ -431,7 +387,7 @@
}
if (attr.nodeName === 'transform') {
currentTrans = currentTrans + ' ' + attr.nodeValue;
currentTrans = attr.nodeValue + ' ' + currentTrans;
}
else {
el2.setAttribute(attr.nodeName, attr.nodeValue);
@ -453,14 +409,12 @@
// http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
// matches, e.g.: +14.56e-12, etc.
var reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)',
reViewBoxAttrValue = new RegExp(
var reViewBoxAttrValue = new RegExp(
'^' +
'\\s*(' + reNum + '+)\\s*,?' +
'\\s*(' + reNum + '+)\\s*,?' +
'\\s*(' + reNum + '+)\\s*,?' +
'\\s*(' + reNum + '+)\\s*' +
'\\s*(' + fabric.reNum + '+)\\s*,?' +
'\\s*(' + fabric.reNum + '+)\\s*,?' +
'\\s*(' + fabric.reNum + '+)\\s*,?' +
'\\s*(' + fabric.reNum + '+)\\s*' +
'$'
),
viewBoxAttr = element.getAttribute('viewBox'),
@ -588,7 +542,6 @@
fabric.gradientDefs[svgUid] = fabric.getGradientDefs(doc);
fabric.cssRules[svgUid] = fabric.getCSSRules(doc);
// Precedence of rules: style > class > attribute
fabric.parseElements(elements, function(instances) {
fabric.documentParsingTime = new Date() - startTime;
if (callback) {
@ -656,6 +609,48 @@
}
extend(fabric, {
/**
* Parses a short font declaration, building adding its properties to a style object
* @static
* @function
* @memberOf fabric
* @param {String} value font declaration
* @param {Object} oStyle definition
*/
parseFontDeclaration: function(value, oStyle) {
var fontDeclaration = '(normal|italic)?\\s*(normal|small-caps)?\\s*'
+ '(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900)?\\s*('
+ fabric.reNum
+ '(?:px|cm|mm|em|pt|pc|in)*)(?:\\/(normal|' + fabric.reNum + '))?\\s+(.*)',
match = value.match(fontDeclaration);
if (!match) {
return;
}
var fontStyle = match[1],
// font variant is not used
// fontVariant = match[2],
fontWeight = match[3],
fontSize = match[4],
lineHeight = match[5],
fontFamily = match[6];
if (fontStyle) {
oStyle.fontStyle = fontStyle;
}
if (fontWeight) {
oStyle.fontWeight = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
}
if (fontSize) {
oStyle.fontSize = parseUnit(fontSize);
}
if (fontFamily) {
oStyle.fontFamily = fontFamily;
}
if (lineHeight) {
oStyle.lineHeight = lineHeight === 'normal' ? 1 : lineHeight;
}
},
/**
* Parses an SVG document, returning all of the gradient declarations found in it
@ -717,7 +712,8 @@
}
var value,
parentAttributes = { };
parentAttributes = { },
fontSize;
if (typeof svgUid === 'undefined') {
svgUid = element.getAttribute('svgUid');
@ -726,12 +722,14 @@
if (element.parentNode && /^symbol|[g|a]$/i.test(element.parentNode.nodeName)) {
parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);
}
fontSize = (parentAttributes && parentAttributes.fontSize ) ||
element.getAttribute('font-size') || fabric.Text.DEFAULT_SVG_FONT_SIZE;
var ownAttributes = attributes.reduce(function(memo, attr) {
value = element.getAttribute(attr);
if (value) {
attr = normalizeAttr(attr);
value = normalizeValue(attr, value, parentAttributes);
value = normalizeValue(attr, value, parentAttributes, fontSize);
memo[attr] = value;
}
@ -742,7 +740,9 @@
// (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)
ownAttributes = extend(ownAttributes,
extend(getGlobalStylesForElement(element, svgUid), fabric.parseStyleAttribute(element)));
if (ownAttributes.font) {
fabric.parseFontDeclaration(ownAttributes.font, ownAttributes);
}
return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes));
},
@ -859,7 +859,11 @@
}
rule = match[1];
rule.split(',').forEach(function(_rule) {
allRules[_rule.trim()] = fabric.util.object.clone(ruleObj);
_rule = _rule.replace(/^svg/i, '').trim();
if (_rule === '') {
return;
}
allRules[_rule] = fabric.util.object.clone(ruleObj);
});
});
}

View file

@ -138,10 +138,12 @@
* @param {Number|String} value number to operate on
* @return {Number|String}
*/
parseUnit: function(value) {
parseUnit: function(value, fontSize) {
var unit = /\D{0,2}$/.exec(value),
number = parseFloat(value);
if (!fontSize) {
fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;
}
switch (unit[0]) {
case 'mm':
return number * fabric.DPI / 25.4;
@ -158,6 +160,9 @@
case 'pc':
return number * fabric.DPI / 72 * 12; // or * 16
case 'em':
return number * fontSize;
default:
return number;
}

View file

@ -125,15 +125,15 @@
var element = fabric.document.createElement('path');
element.setAttribute('style', 'left:10px;top:22.3em;width:103.45pt;height:20%;');
// TODO: looks like this still fails with % and em values
var styleObj = fabric.parseStyleAttribute(element);
// TODO: looks like this still fails with % values
var expectedObject = {
'left': 10,
'top': 22.3,
'top': 356.8,
'width': 137.93333333333334,
'height': 20
};
deepEqual(fabric.parseStyleAttribute(element), expectedObject);
deepEqual(styleObj, expectedObject);
});
test('parseStyleAttribute with one pair', function() {
@ -160,13 +160,33 @@
test('parseStyleAttribute with short font declaration', function() {
var element = fabric.document.createElement('path');
element.setAttribute('style', 'font: italic 12px Arial,Helvetica,sans-serif');
var styleObj = fabric.parseStyleAttribute(element);
if (styleObj.font) {
fabric.parseFontDeclaration(styleObj.font, styleObj);
}
var expectedObject = {
'font': 'italic 12px Arial,Helvetica,sans-serif',
'fontSize': 12,
'fontStyle': 'italic',
'fontFamily': 'Arial,Helvetica,sans-serif'
};
deepEqual(fabric.parseStyleAttribute(element), expectedObject);
deepEqual(styleObj, expectedObject);
//testing different unit
element.setAttribute('style', 'font: italic 1.5em Arial,Helvetica,sans-serif');
var styleObj = fabric.parseStyleAttribute(element);
if (styleObj.font) {
fabric.parseFontDeclaration(styleObj.font, styleObj);
}
var expectedObject = {
'font': 'italic 1.5em Arial,Helvetica,sans-serif',
'fontSize': 24,
'fontStyle': 'italic',
'fontFamily': 'Arial,Helvetica,sans-serif'
};
deepEqual(styleObj, expectedObject);
});
test('parseAttributes (style to have higher priority than attribute)', function() {