mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-03-16 22:10:32 +00:00
Fix opacity parsing from classes and from fill-opacity (#3747)
* fix to parser * fix opacity parsing * fix opacity parsing * added tests * fix for parsing attributes equalt to 0 * added test * fixed better * removed fix
This commit is contained in:
parent
c3a6447aff
commit
211edecdfd
2 changed files with 94 additions and 29 deletions
|
|
@ -41,7 +41,8 @@
|
|||
'stroke-opacity': 'strokeOpacity',
|
||||
'stroke-width': 'strokeWidth',
|
||||
'text-decoration': 'textDecoration',
|
||||
'text-anchor': 'originX'
|
||||
'text-anchor': 'originX',
|
||||
opacity: 'opacity'
|
||||
},
|
||||
|
||||
colorAttributes = {
|
||||
|
|
@ -93,6 +94,12 @@
|
|||
value = false;
|
||||
}
|
||||
}
|
||||
else if (attr === 'opacity') {
|
||||
value = parseFloat(value);
|
||||
if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {
|
||||
value *= parentAttributes.opacity;
|
||||
}
|
||||
}
|
||||
else if (attr === 'originX' /* text-anchor */) {
|
||||
value = value === 'start' ? 'left' : value === 'end' ? 'right' : 'center';
|
||||
}
|
||||
|
|
@ -311,8 +318,8 @@
|
|||
style.replace(/;\s*$/, '').split(';').forEach(function (chunk) {
|
||||
var pair = chunk.split(':');
|
||||
|
||||
attr = normalizeAttr(pair[0].trim().toLowerCase());
|
||||
value = normalizeValue(attr, pair[1].trim());
|
||||
attr = pair[0].trim().toLowerCase();
|
||||
value = pair[1].trim();
|
||||
|
||||
oStyle[attr] = value;
|
||||
});
|
||||
|
|
@ -328,8 +335,8 @@
|
|||
continue;
|
||||
}
|
||||
|
||||
attr = normalizeAttr(prop.toLowerCase());
|
||||
value = normalizeValue(attr, style[prop]);
|
||||
attr = prop.toLowerCase();
|
||||
value = style[prop];
|
||||
|
||||
oStyle[attr] = value;
|
||||
}
|
||||
|
|
@ -758,23 +765,27 @@
|
|||
|
||||
var ownAttributes = attributes.reduce(function(memo, attr) {
|
||||
value = element.getAttribute(attr);
|
||||
if (value) {
|
||||
attr = normalizeAttr(attr);
|
||||
value = normalizeValue(attr, value, parentAttributes, fontSize);
|
||||
|
||||
if (value) { // eslint-disable-line
|
||||
memo[attr] = value;
|
||||
}
|
||||
return memo;
|
||||
}, { });
|
||||
|
||||
// add values parsed from style, which take precedence over attributes
|
||||
// (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);
|
||||
|
||||
var normalizedAttr, normalizedValue, normalizedStyle = {};
|
||||
for (var attr in ownAttributes) {
|
||||
normalizedAttr = normalizeAttr(attr);
|
||||
normalizedValue = normalizeValue(normalizedAttr, ownAttributes[attr], parentAttributes, fontSize);
|
||||
normalizedStyle[normalizedAttr] = normalizedValue;
|
||||
}
|
||||
return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes));
|
||||
if (normalizedStyle && normalizedStyle.font) {
|
||||
fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);
|
||||
}
|
||||
var mergedAttrs = extend(parentAttributes, normalizedStyle);
|
||||
return reAllowedParents.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -884,8 +895,8 @@
|
|||
|
||||
for (var i = 0, len = propertyValuePairs.length; i < len; i++) {
|
||||
var pair = propertyValuePairs[i].split(/\s*:\s*/),
|
||||
property = normalizeAttr(pair[0]),
|
||||
value = normalizeValue(property, pair[1], pair[0]);
|
||||
property = pair[0],
|
||||
value = pair[1];
|
||||
ruleObj[property] = value;
|
||||
}
|
||||
rule = match[1];
|
||||
|
|
|
|||
|
|
@ -145,10 +145,10 @@
|
|||
var styleObj = fabric.parseStyleAttribute(element);
|
||||
// TODO: looks like this still fails with % values
|
||||
var expectedObject = {
|
||||
'left': 10,
|
||||
'top': 356.8,
|
||||
'width': 137.93333333333334,
|
||||
'height': 20
|
||||
left: '10px',
|
||||
top: '22.3em',
|
||||
width: '103.45pt',
|
||||
height: '20%'
|
||||
};
|
||||
deepEqual(styleObj, expectedObject);
|
||||
});
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
element.setAttribute('style', 'left:10px');
|
||||
|
||||
var expectedObject = {
|
||||
'left': 10
|
||||
left: '10px'
|
||||
};
|
||||
deepEqual(fabric.parseStyleAttribute(element), expectedObject);
|
||||
});
|
||||
|
|
@ -168,8 +168,8 @@
|
|||
element.setAttribute('style', 'left:10px; top:5px; ');
|
||||
|
||||
var expectedObject = {
|
||||
'left': 10,
|
||||
'top': 5
|
||||
left: '10px',
|
||||
top: '5px'
|
||||
};
|
||||
deepEqual(fabric.parseStyleAttribute(element), expectedObject);
|
||||
});
|
||||
|
|
@ -179,8 +179,8 @@
|
|||
element.setAttribute('style', 'fill:none; stroke-dasharray: 2 0.4;');
|
||||
|
||||
var expectedObject = {
|
||||
'fill': '',
|
||||
'strokeDashArray': [2, 0.4]
|
||||
fill: 'none',
|
||||
'stroke-dasharray': '2 0.4'
|
||||
};
|
||||
deepEqual(fabric.parseStyleAttribute(element), expectedObject);
|
||||
});
|
||||
|
|
@ -244,6 +244,16 @@
|
|||
deepEqual(fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES), expectedObject);
|
||||
});
|
||||
|
||||
test('parse 0 attribute', function() {
|
||||
var element = fabric.document.createElement('path');
|
||||
element.setAttribute('opacity', 0);
|
||||
|
||||
var expectedObject = {
|
||||
opacity: 0,
|
||||
};
|
||||
deepEqual(fabric.parseAttributes(element, fabric.Path.ATTRIBUTE_NAMES), expectedObject);
|
||||
});
|
||||
|
||||
test('parsePointsAttribute', function() {
|
||||
ok(fabric.parsePointsAttribute);
|
||||
|
||||
|
|
@ -348,6 +358,50 @@
|
|||
});
|
||||
});
|
||||
|
||||
asyncTest('parseSVGFromString nested opacity', function() {
|
||||
var string = '<?xml version="1.0" encoding="UTF-8"?>' +
|
||||
'<svg version="1.2" baseProfile="tiny" xml:id="svg-root" width="300" height="400" ' +
|
||||
'viewBox="0 0 300 400" xmlns="http://www.w3.org/2000/svg" ' +
|
||||
'xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xe="http://www.w3.org/2001/xml-events">' +
|
||||
'<defs>' +
|
||||
'<style>' +
|
||||
'.cls-3{opacity:0.5;}' +
|
||||
'.cls-4{opacity:0.5;}' +
|
||||
'</style>' +
|
||||
'</defs>' +
|
||||
'<g fill="red" stroke="#000000" fill-opacity="0.5">' +
|
||||
'<circle cx="50" cy="50" r="50" fill-opacity="1" fill="rgba(255,0,0,0.3)" />' +
|
||||
'<circle cx="150" cy="50" r="50" fill="rgba(0,255,0,0.5)" />' +
|
||||
'<circle cx="50" cy="150" r="50" />' +
|
||||
'<circle cx="150" cy="150" r="50" fill-opacity="0.5" fill="rgb(0,0,255)" />' +
|
||||
'<circle cx="250" cy="50" r="50" fill-opacity="0.5" fill="rgba(0,0,255,0.5)" />' +
|
||||
'<circle cx="250" cy="150" r="50" fill-opacity="1" fill="rgb(0,0,255)" />' +
|
||||
'</g>' +
|
||||
'<g class="cls-3" transform="translate(0,200)">' +
|
||||
'<circle cx="50" cy="50" r="50" class="cls-4" fill="red" />' +
|
||||
'<circle cx="150" cy="50" r="50" fill="red" />' +
|
||||
'</g>' +
|
||||
'</svg>';
|
||||
|
||||
fabric.loadSVGFromString(string, function(objects) {
|
||||
equal(objects[0].fill, 'rgba(255,0,0,0.3)', 'first circle has opacity 0.3 from rgba');
|
||||
equal(objects[0].fillOpacity, 1,'first circle has fill-opacity 1');
|
||||
equal(objects[1].fill, 'rgba(0,255,0,0.25)', 'first circle has opacity 0.5 from rgba and 0.5 from gtoup fill opacity');
|
||||
equal(objects[1].fillOpacity, 0.5,'first circle has fill-opacity 0.5');
|
||||
equal(objects[2].fill, 'rgba(255,0,0,0.5)', 'first circle has opacity 0.5 from group fill opacity');
|
||||
equal(objects[2].fillOpacity, 0.5,'first circle has fill-opacity 0.5');
|
||||
equal(objects[3].fill, 'rgba(0,0,255,0.5)', 'first circle has opacity 0.5 from fill opacity');
|
||||
equal(objects[3].fillOpacity, 0.5,'first circle has fill-opacity 1');
|
||||
equal(objects[4].fill, 'rgba(0,0,255,0.25)', 'first circle has opacity 0.5 from rgba and 0.5 from fill opacity');
|
||||
equal(objects[4].fillOpacity, 0.5,'first circle has fill-opacity 0.5');
|
||||
equal(objects[5].fill, 'rgba(0,0,255,1)', 'first circle has opacity 1 from rgba');
|
||||
equal(objects[5].fillOpacity, 1,'first circle has fill-opacity 1');
|
||||
equal(objects[6].opacity, 0.25, 'opacity is 0.25 for cls-3 * cls-4');
|
||||
equal(objects[7].opacity, 0.5,'opacity is 0.5 from cls-3');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('parseSVGFromString with svg:namespace', function() {
|
||||
var string = '<?xml version="1.0" standalone="no"?><svg width="100%" height="100%" version="1.1" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' +
|
||||
'<svg:defs><svg:rect id="myrect" width="300" height="100" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"/></svg:defs>' +
|
||||
|
|
@ -523,15 +577,15 @@
|
|||
'g polygon.cls': {
|
||||
'fill': '#FF0000',
|
||||
'stroke': '#000000',
|
||||
'strokeWidth': 0.25
|
||||
'stroke-width': '0.25px'
|
||||
},
|
||||
'rect': {
|
||||
'fill': '#FF0000',
|
||||
'stroke': '#000000',
|
||||
'strokeWidth': 0.25
|
||||
'stroke-width': '0.25px'
|
||||
},
|
||||
'polygon.cls': {
|
||||
'fill': '',
|
||||
'fill': 'none',
|
||||
'stroke': '#0000FF'
|
||||
}
|
||||
};
|
||||
|
|
@ -575,13 +629,13 @@
|
|||
'.cls1': {
|
||||
'fill': '#FF0000',
|
||||
'stroke': '#00FF00',
|
||||
'strokeWidth': 3
|
||||
'stroke-width': '3'
|
||||
},
|
||||
'.cls2': {
|
||||
'fill': '#FF0000'
|
||||
},
|
||||
'.cls3': {
|
||||
'strokeWidth': 3
|
||||
'stroke-width': '3'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue