fabric-rails 1.0.12.1 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/lib/fabric/rails/version.rb +2 -2
- data/vendor/assets/javascripts/cufon.js +1226 -0
- data/vendor/assets/javascripts/event.js +20 -20
- data/vendor/assets/javascripts/excanvas.js +1464 -0
- data/vendor/assets/javascripts/fabric.js +56 -33
- data/vendor/assets/javascripts/fabric/HEADER.js +2 -4
- data/vendor/assets/javascripts/fabric/brushes/base_brush.class.js +96 -0
- data/vendor/assets/javascripts/fabric/brushes/circle_brush.class.js +99 -0
- data/vendor/assets/javascripts/fabric/brushes/pattern_brush.class.js +55 -0
- data/vendor/assets/javascripts/fabric/{freedrawing.class.js → brushes/pencil_brush.class.js} +73 -65
- data/vendor/assets/javascripts/fabric/brushes/spray_brush.class.js +157 -0
- data/vendor/assets/javascripts/fabric/canvas.class.js +154 -135
- data/vendor/assets/javascripts/fabric/color.class.js +195 -29
- data/vendor/assets/javascripts/fabric/filters/brightness_filter.class.js +70 -0
- data/vendor/assets/javascripts/fabric/filters/convolute_filter.class.js +122 -0
- data/vendor/assets/javascripts/fabric/filters/gradienttransparency_filter.class.js +69 -0
- data/vendor/assets/javascripts/fabric/filters/grayscale_filter.class.js +61 -0
- data/vendor/assets/javascripts/fabric/filters/invert_filter.class.js +57 -0
- data/vendor/assets/javascripts/fabric/filters/noise_filter.class.js +73 -0
- data/vendor/assets/javascripts/fabric/filters/pixelate_filter.class.js +98 -0
- data/vendor/assets/javascripts/fabric/filters/removewhite_filter.class.js +86 -0
- data/vendor/assets/javascripts/fabric/filters/sepia2_filter.class.js +61 -0
- data/vendor/assets/javascripts/fabric/filters/sepia_filter.class.js +58 -0
- data/vendor/assets/javascripts/fabric/filters/tint_filter.class.js +80 -0
- data/vendor/assets/javascripts/fabric/gradient.class.js +232 -80
- data/vendor/assets/javascripts/fabric/intersection.class.js +10 -28
- data/vendor/assets/javascripts/fabric/log.js +0 -2
- data/vendor/assets/javascripts/fabric/{canvas_animation.mixin.js → mixins/canvas_animation.mixin.js} +3 -6
- data/vendor/assets/javascripts/fabric/mixins/canvas_dataurl_exporter.mixin.js +137 -0
- data/vendor/assets/javascripts/fabric/{canvas_events.mixin.js → mixins/canvas_events.mixin.js} +97 -144
- data/vendor/assets/javascripts/fabric/{canvas_gestures.mixin.js → mixins/canvas_gestures.mixin.js} +4 -8
- data/vendor/assets/javascripts/fabric/{canvas_serialization.mixin.js → mixins/canvas_serialization.mixin.js} +19 -14
- data/vendor/assets/javascripts/fabric/mixins/collection.mixin.js +137 -0
- data/vendor/assets/javascripts/fabric/{object_geometry.mixin.js → mixins/object_geometry.mixin.js} +130 -47
- data/vendor/assets/javascripts/fabric/{object_interactivity.mixin.js → mixins/object_interactivity.mixin.js} +21 -102
- data/vendor/assets/javascripts/fabric/{object_origin.mixin.js → mixins/object_origin.mixin.js} +36 -26
- data/vendor/assets/javascripts/fabric/{object_straightening.mixin.js → mixins/object_straightening.mixin.js} +4 -9
- data/vendor/assets/javascripts/fabric/{observable.mixin.js → mixins/observable.mixin.js} +27 -35
- data/vendor/assets/javascripts/fabric/mixins/stateful.mixin.js +45 -0
- data/vendor/assets/javascripts/fabric/node.js +62 -26
- data/vendor/assets/javascripts/fabric/parser.js +181 -58
- data/vendor/assets/javascripts/fabric/pattern.class.js +43 -14
- data/vendor/assets/javascripts/fabric/point.class.js +4 -43
- data/vendor/assets/javascripts/fabric/shadow.class.js +19 -19
- data/vendor/assets/javascripts/fabric/{circle.class.js → shapes/circle.class.js} +32 -29
- data/vendor/assets/javascripts/fabric/{ellipse.class.js → shapes/ellipse.class.js} +45 -27
- data/vendor/assets/javascripts/fabric/{group.class.js → shapes/group.class.js} +67 -169
- data/vendor/assets/javascripts/fabric/{image.class.js → shapes/image.class.js} +134 -72
- data/vendor/assets/javascripts/fabric/{line.class.js → shapes/line.class.js} +67 -36
- data/vendor/assets/javascripts/fabric/{object.class.js → shapes/object.class.js} +394 -252
- data/vendor/assets/javascripts/fabric/{path.class.js → shapes/path.class.js} +89 -174
- data/vendor/assets/javascripts/fabric/{path_group.class.js → shapes/path_group.class.js} +12 -18
- data/vendor/assets/javascripts/fabric/{polygon.class.js → shapes/polygon.class.js} +64 -38
- data/vendor/assets/javascripts/fabric/{polyline.class.js → shapes/polyline.class.js} +64 -39
- data/vendor/assets/javascripts/fabric/{rect.class.js → shapes/rect.class.js} +78 -112
- data/vendor/assets/javascripts/fabric/{text.class.js → shapes/text.class.js} +264 -270
- data/vendor/assets/javascripts/fabric/shapes/text.cufon.js +79 -0
- data/vendor/assets/javascripts/fabric/{triangle.class.js → shapes/triangle.class.js} +46 -26
- data/vendor/assets/javascripts/fabric/static_canvas.class.js +134 -358
- data/vendor/assets/javascripts/fabric/util/anim_ease.js +2 -31
- data/vendor/assets/javascripts/fabric/util/dom_event.js +21 -7
- data/vendor/assets/javascripts/fabric/util/dom_misc.js +49 -39
- data/vendor/assets/javascripts/fabric/util/dom_request.js +1 -2
- data/vendor/assets/javascripts/fabric/util/dom_style.js +1 -2
- data/vendor/assets/javascripts/fabric/util/lang_array.js +19 -13
- data/vendor/assets/javascripts/fabric/util/lang_class.js +1 -2
- data/vendor/assets/javascripts/fabric/util/lang_function.js +3 -1
- data/vendor/assets/javascripts/fabric/util/lang_object.js +5 -5
- data/vendor/assets/javascripts/fabric/util/lang_string.js +7 -5
- data/vendor/assets/javascripts/fabric/util/misc.js +207 -42
- metadata +47 -29
- data/vendor/assets/javascripts/fabric/image_filters.js +0 -809
- data/vendor/assets/javascripts/fabric/scout.js +0 -45
- data/vendor/assets/javascripts/fabric/stateful.js +0 -88
@@ -1,16 +1,14 @@
|
|
1
|
-
|
2
|
-
* @namespace
|
3
|
-
*/
|
4
|
-
fabric.Observable = {
|
1
|
+
(function(){
|
5
2
|
|
6
3
|
/**
|
7
4
|
* Observes specified event
|
8
|
-
* @
|
9
|
-
* @
|
5
|
+
* @deprecated `observe` deprecated since 0.8.34 (use `on` instead)
|
6
|
+
* @memberOf fabric.Observable
|
7
|
+
* @alias on
|
10
8
|
* @param {String} eventName
|
11
9
|
* @param {Function} handler
|
12
10
|
*/
|
13
|
-
observe
|
11
|
+
function observe(eventName, handler) {
|
14
12
|
if (!this.__eventListeners) {
|
15
13
|
this.__eventListeners = { };
|
16
14
|
}
|
@@ -26,16 +24,17 @@ fabric.Observable = {
|
|
26
24
|
}
|
27
25
|
this.__eventListeners[eventName].push(handler);
|
28
26
|
}
|
29
|
-
}
|
27
|
+
}
|
30
28
|
|
31
29
|
/**
|
32
30
|
* Stops event observing for a particular event handler
|
33
|
-
* @
|
34
|
-
* @
|
31
|
+
* @deprecated `stopObserving` deprecated since 0.8.34 (use `off` instead)
|
32
|
+
* @memberOf fabric.Observable
|
33
|
+
* @alias off
|
35
34
|
* @param {String} eventName
|
36
35
|
* @param {Function} handler
|
37
36
|
*/
|
38
|
-
stopObserving
|
37
|
+
function stopObserving(eventName, handler) {
|
39
38
|
if (!this.__eventListeners) {
|
40
39
|
this.__eventListeners = { };
|
41
40
|
}
|
@@ -47,16 +46,17 @@ fabric.Observable = {
|
|
47
46
|
this.__eventListeners[eventName].length = 0;
|
48
47
|
}
|
49
48
|
}
|
50
|
-
}
|
49
|
+
}
|
51
50
|
|
52
51
|
/**
|
53
52
|
* Fires event with an optional options object
|
54
|
-
* @deprecated since 1.0.7
|
55
|
-
* @
|
53
|
+
* @deprecated `fire` deprecated since 1.0.7 (use `trigger` instead)
|
54
|
+
* @memberOf fabric.Observable
|
55
|
+
* @alias trigger
|
56
56
|
* @param {String} eventName
|
57
57
|
* @param {Object} [options]
|
58
58
|
*/
|
59
|
-
fire
|
59
|
+
function fire(eventName, options) {
|
60
60
|
if (!this.__eventListeners) {
|
61
61
|
this.__eventListeners = { };
|
62
62
|
}
|
@@ -67,25 +67,17 @@ fabric.Observable = {
|
|
67
67
|
listenersForEvent[i](options || { });
|
68
68
|
}
|
69
69
|
}
|
70
|
-
};
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Alias for observe
|
74
|
-
* @method observe
|
75
|
-
* @type function
|
76
|
-
*/
|
77
|
-
fabric.Observable.on = fabric.Observable.observe;
|
78
70
|
|
79
|
-
/**
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
71
|
+
/**
|
72
|
+
* @namespace fabric.Observable
|
73
|
+
*/
|
74
|
+
fabric.Observable = {
|
75
|
+
observe: observe,
|
76
|
+
stopObserving: stopObserving,
|
77
|
+
fire: fire,
|
85
78
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
fabric.Observable.trigger = fabric.Observable.fire;
|
79
|
+
on: observe,
|
80
|
+
off: stopObserving,
|
81
|
+
trigger: fire
|
82
|
+
};
|
83
|
+
})();
|
@@ -0,0 +1,45 @@
|
|
1
|
+
/*
|
2
|
+
Depends on `stateProperties`
|
3
|
+
*/
|
4
|
+
fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Returns true if object state (one of its state properties) was changed
|
8
|
+
* @return {Boolean} true if instance' state has changed since `{@link fabric.Object#saveState}` was called
|
9
|
+
*/
|
10
|
+
hasStateChanged: function() {
|
11
|
+
return this.stateProperties.some(function(prop) {
|
12
|
+
return this[prop] !== this.originalState[prop];
|
13
|
+
}, this);
|
14
|
+
},
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Saves state of an object
|
18
|
+
* @param {Object} [options] Object with additional `stateProperties` array to include when saving state
|
19
|
+
* @return {fabric.Object} thisArg
|
20
|
+
*/
|
21
|
+
saveState: function(options) {
|
22
|
+
this.stateProperties.forEach(function(prop) {
|
23
|
+
this.originalState[prop] = this.get(prop);
|
24
|
+
}, this);
|
25
|
+
|
26
|
+
if (options && options.stateProperties) {
|
27
|
+
options.stateProperties.forEach(function(prop) {
|
28
|
+
this.originalState[prop] = this.get(prop);
|
29
|
+
}, this);
|
30
|
+
}
|
31
|
+
|
32
|
+
return this;
|
33
|
+
},
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Setups state of an object
|
37
|
+
* @return {fabric.Object} thisArg
|
38
|
+
*/
|
39
|
+
setupState: function() {
|
40
|
+
this.originalState = { };
|
41
|
+
this.saveState();
|
42
|
+
|
43
|
+
return this;
|
44
|
+
}
|
45
|
+
});
|
@@ -7,27 +7,29 @@
|
|
7
7
|
var DOMParser = new require('xmldom').DOMParser,
|
8
8
|
URL = require('url'),
|
9
9
|
HTTP = require('http'),
|
10
|
+
HTTPS = require('https'),
|
10
11
|
|
11
12
|
Canvas = require('canvas'),
|
12
13
|
Image = require('canvas').Image;
|
13
14
|
|
14
15
|
/** @private */
|
15
16
|
function request(url, encoding, callback) {
|
16
|
-
var oURL = URL.parse(url)
|
17
|
-
client = HTTP.createClient(oURL.port, oURL.hostname),
|
18
|
-
req = client.request('GET', oURL.pathname, { 'host': oURL.hostname });
|
17
|
+
var oURL = URL.parse(url);
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
else {
|
25
|
-
fabric.log(err.message);
|
26
|
-
}
|
27
|
-
});
|
19
|
+
// detect if http or https is used
|
20
|
+
if ( !oURL.port ) {
|
21
|
+
oURL.port = ( oURL.protocol.indexOf('https:') === 0 ) ? 443 : 80;
|
22
|
+
}
|
28
23
|
|
29
|
-
|
30
|
-
|
24
|
+
// assign request handler based on protocol
|
25
|
+
var reqHandler = ( oURL.port === 443 ) ? HTTPS : HTTP;
|
26
|
+
|
27
|
+
var req = reqHandler.request({
|
28
|
+
hostname: oURL.hostname,
|
29
|
+
port: oURL.port,
|
30
|
+
path: oURL.path,
|
31
|
+
method: 'GET'
|
32
|
+
}, function(response){
|
31
33
|
var body = "";
|
32
34
|
if (encoding) {
|
33
35
|
response.setEncoding(encoding);
|
@@ -41,29 +43,64 @@
|
|
41
43
|
}
|
42
44
|
});
|
43
45
|
});
|
46
|
+
|
47
|
+
req.on('error', function(err) {
|
48
|
+
if (err.errno === process.ECONNREFUSED) {
|
49
|
+
fabric.log('ECONNREFUSED: connection refused to ' + oURL.hostname + ':' + oURL.port);
|
50
|
+
}
|
51
|
+
else {
|
52
|
+
fabric.log(err.message);
|
53
|
+
}
|
54
|
+
});
|
55
|
+
|
56
|
+
req.end();
|
57
|
+
}
|
58
|
+
|
59
|
+
/** @private */
|
60
|
+
function request_fs(url, callback){
|
61
|
+
var fs = require('fs'),
|
62
|
+
stream = fs.createReadStream(url),
|
63
|
+
body = '';
|
64
|
+
stream.on('data', function(chunk){
|
65
|
+
body += chunk;
|
66
|
+
});
|
67
|
+
stream.on('end', function(){
|
68
|
+
callback(body);
|
69
|
+
});
|
44
70
|
}
|
45
71
|
|
46
72
|
fabric.util.loadImage = function(url, callback, context) {
|
73
|
+
var createImageAndCallBack = function(data){
|
74
|
+
img.src = new Buffer(data, 'binary');
|
75
|
+
// preserving original url, which seems to be lost in node-canvas
|
76
|
+
img._src = url;
|
77
|
+
callback && callback.call(context, img);
|
78
|
+
};
|
47
79
|
var img = new Image();
|
48
|
-
if (url && url.indexOf('data') === 0) {
|
80
|
+
if (url && (url instanceof Buffer || url.indexOf('data') === 0)) {
|
49
81
|
img.src = img._src = url;
|
50
82
|
callback && callback.call(context, img);
|
51
83
|
}
|
84
|
+
else if (url && url.indexOf('http') !== 0) {
|
85
|
+
request_fs(url, createImageAndCallBack);
|
86
|
+
}
|
52
87
|
else if (url) {
|
53
|
-
request(url, 'binary',
|
54
|
-
img.src = new Buffer(body, 'binary');
|
55
|
-
// preserving original url, which seems to be lost in node-canvas
|
56
|
-
img._src = url;
|
57
|
-
callback && callback.call(context, img);
|
58
|
-
});
|
88
|
+
request(url, 'binary', createImageAndCallBack);
|
59
89
|
}
|
60
90
|
};
|
61
91
|
|
62
92
|
fabric.loadSVGFromURL = function(url, callback) {
|
63
93
|
url = url.replace(/^\n\s*/, '').replace(/\?.*$/, '').trim();
|
64
|
-
|
65
|
-
|
66
|
-
|
94
|
+
if (url.indexOf('http') !== 0) {
|
95
|
+
request_fs(url, function(body) {
|
96
|
+
fabric.loadSVGFromString(body, callback);
|
97
|
+
});
|
98
|
+
}
|
99
|
+
else {
|
100
|
+
request(url, '', function(body) {
|
101
|
+
fabric.loadSVGFromString(body, callback);
|
102
|
+
});
|
103
|
+
}
|
67
104
|
};
|
68
105
|
|
69
106
|
fabric.loadSVGFromString = function(string, callback) {
|
@@ -92,7 +129,6 @@
|
|
92
129
|
|
93
130
|
/**
|
94
131
|
* Only available when running fabric on node.js
|
95
|
-
* @method createCanvasForNode
|
96
132
|
* @param width Canvas width
|
97
133
|
* @param height Canvas height
|
98
134
|
* @return {Object} wrapped canvas instance
|
@@ -128,7 +164,7 @@
|
|
128
164
|
|
129
165
|
var origSetWidth = fabric.StaticCanvas.prototype.setWidth;
|
130
166
|
fabric.StaticCanvas.prototype.setWidth = function(width) {
|
131
|
-
origSetWidth.call(this);
|
167
|
+
origSetWidth.call(this, width);
|
132
168
|
this.nodeCanvas.width = width;
|
133
169
|
return this;
|
134
170
|
};
|
@@ -138,7 +174,7 @@
|
|
138
174
|
|
139
175
|
var origSetHeight = fabric.StaticCanvas.prototype.setHeight;
|
140
176
|
fabric.StaticCanvas.prototype.setHeight = function(height) {
|
141
|
-
origSetHeight.call(this);
|
177
|
+
origSetHeight.call(this, height);
|
142
178
|
this.nodeCanvas.height = height;
|
143
179
|
return this;
|
144
180
|
};
|
@@ -10,23 +10,42 @@
|
|
10
10
|
var fabric = global.fabric || (global.fabric = { }),
|
11
11
|
extend = fabric.util.object.extend,
|
12
12
|
capitalize = fabric.util.string.capitalize,
|
13
|
-
clone = fabric.util.object.clone
|
13
|
+
clone = fabric.util.object.clone,
|
14
|
+
toFixed = fabric.util.toFixed,
|
15
|
+
multiplyTransformMatrices = fabric.util.multiplyTransformMatrices;
|
16
|
+
|
17
|
+
fabric.SHARED_ATTRIBUTES = [
|
18
|
+
"transform",
|
19
|
+
"fill", "fill-opacity", "fill-rule",
|
20
|
+
"opacity",
|
21
|
+
"stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width"
|
22
|
+
];
|
14
23
|
|
15
24
|
var attributesMap = {
|
25
|
+
'fill-opacity': 'fillOpacity',
|
26
|
+
'fill-rule': 'fillRule',
|
27
|
+
'font-family': 'fontFamily',
|
28
|
+
'font-size': 'fontSize',
|
29
|
+
'font-style': 'fontStyle',
|
30
|
+
'font-weight': 'fontWeight',
|
16
31
|
'cx': 'left',
|
17
32
|
'x': 'left',
|
18
|
-
'cy': 'top',
|
19
|
-
'y': 'top',
|
20
33
|
'r': 'radius',
|
21
|
-
'
|
22
|
-
'
|
34
|
+
'stroke-dasharray': 'strokeDashArray',
|
35
|
+
'stroke-linecap': 'strokeLineCap',
|
36
|
+
'stroke-linejoin': 'strokeLineJoin',
|
37
|
+
'stroke-miterlimit':'strokeMiterLimit',
|
38
|
+
'stroke-opacity': 'strokeOpacity',
|
23
39
|
'stroke-width': 'strokeWidth',
|
24
|
-
'transform': 'transformMatrix',
|
25
40
|
'text-decoration': 'textDecoration',
|
26
|
-
'
|
27
|
-
'
|
28
|
-
'
|
29
|
-
|
41
|
+
'cy': 'top',
|
42
|
+
'y': 'top',
|
43
|
+
'transform': 'transformMatrix'
|
44
|
+
};
|
45
|
+
|
46
|
+
var colorAttributes = {
|
47
|
+
'stroke': 'strokeOpacity',
|
48
|
+
'fill': 'fillOpacity'
|
30
49
|
};
|
31
50
|
|
32
51
|
function normalizeAttr(attr) {
|
@@ -37,12 +56,57 @@
|
|
37
56
|
return attr;
|
38
57
|
}
|
39
58
|
|
59
|
+
function normalizeValue(attr, value, parentAttributes) {
|
60
|
+
var isArray;
|
61
|
+
|
62
|
+
if ((attr === 'fill' || attr === 'stroke') && value === 'none') {
|
63
|
+
value = '';
|
64
|
+
}
|
65
|
+
else if (attr === 'fillRule') {
|
66
|
+
value = (value === 'evenodd') ? 'destination-over' : value;
|
67
|
+
}
|
68
|
+
else if (attr === 'strokeDashArray') {
|
69
|
+
value = value.replace(/,/g, ' ').split(/\s+/);
|
70
|
+
}
|
71
|
+
else if (attr === 'transformMatrix') {
|
72
|
+
if (parentAttributes && parentAttributes.transformMatrix) {
|
73
|
+
value = multiplyTransformMatrices(
|
74
|
+
parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
value = fabric.parseTransformAttribute(value);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
isArray = Object.prototype.toString.call(value) === '[object Array]';
|
82
|
+
|
83
|
+
// TODO: need to normalize em, %, pt, etc. to px (!)
|
84
|
+
var parsed = isArray ? value.map(parseFloat) : parseFloat(value);
|
85
|
+
|
86
|
+
return (!isArray && isNaN(parsed) ? value : parsed);
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* @private
|
91
|
+
* @param {Object} attributes Array of attributes to parse
|
92
|
+
*/
|
93
|
+
function _setStrokeFillOpacity(attributes) {
|
94
|
+
for (var attr in colorAttributes) {
|
95
|
+
if (!attributes[attr] || typeof attributes[colorAttributes[attr]] === 'undefined') continue;
|
96
|
+
|
97
|
+
var color = new fabric.Color(attributes[attr]);
|
98
|
+
attributes[attr] = color.setAlpha(toFixed(color.getAlpha() * attributes[colorAttributes[attr]], 2)).toRgba();
|
99
|
+
|
100
|
+
delete attributes[colorAttributes[attr]];
|
101
|
+
}
|
102
|
+
return attributes;
|
103
|
+
}
|
104
|
+
|
40
105
|
/**
|
41
106
|
* Returns an object of attributes' name/value, given element and an array of attribute names;
|
42
107
|
* Parses parent "g" nodes recursively upwards.
|
43
108
|
* @static
|
44
109
|
* @memberOf fabric
|
45
|
-
* @method parseAttributes
|
46
110
|
* @param {DOMElement} element Element to parse
|
47
111
|
* @param {Array} attributes Array of attributes to parse
|
48
112
|
* @return {Object} object containing parsed attributes' names/values
|
@@ -54,7 +118,6 @@
|
|
54
118
|
}
|
55
119
|
|
56
120
|
var value,
|
57
|
-
parsed,
|
58
121
|
parentAttributes = { };
|
59
122
|
|
60
123
|
// if there's a parent container (`g` node), parse its attributes recursively upwards
|
@@ -64,20 +127,11 @@
|
|
64
127
|
|
65
128
|
var ownAttributes = attributes.reduce(function(memo, attr) {
|
66
129
|
value = element.getAttribute(attr);
|
67
|
-
parsed = parseFloat(value);
|
68
130
|
if (value) {
|
69
|
-
// "normalize" attribute values
|
70
|
-
if ((attr === 'fill' || attr === 'stroke') && value === 'none') {
|
71
|
-
value = '';
|
72
|
-
}
|
73
|
-
if (attr === 'fill-rule') {
|
74
|
-
value = (value === 'evenodd') ? 'destination-over' : value;
|
75
|
-
}
|
76
|
-
if (attr === 'transform') {
|
77
|
-
value = fabric.parseTransformAttribute(value);
|
78
|
-
}
|
79
131
|
attr = normalizeAttr(attr);
|
80
|
-
|
132
|
+
value = normalizeValue(attr, value, parentAttributes);
|
133
|
+
|
134
|
+
memo[attr] = value;
|
81
135
|
}
|
82
136
|
return memo;
|
83
137
|
}, { });
|
@@ -85,8 +139,9 @@
|
|
85
139
|
// add values parsed from style, which take precedence over attributes
|
86
140
|
// (see: http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes)
|
87
141
|
|
88
|
-
ownAttributes = extend(ownAttributes,
|
89
|
-
|
142
|
+
ownAttributes = extend(ownAttributes,
|
143
|
+
extend(getGlobalStylesForElement(element), fabric.parseStyleAttribute(element)));
|
144
|
+
return _setStrokeFillOpacity(extend(parentAttributes, ownAttributes));
|
90
145
|
}
|
91
146
|
|
92
147
|
/**
|
@@ -94,7 +149,6 @@
|
|
94
149
|
* @static
|
95
150
|
* @function
|
96
151
|
* @memberOf fabric
|
97
|
-
* @method parseTransformAttribute
|
98
152
|
* @param attributeValue {String} string containing attribute value
|
99
153
|
* @return {Array} array of 6 elements representing transformation matrix
|
100
154
|
*/
|
@@ -177,12 +231,13 @@
|
|
177
231
|
reTransformList = new RegExp(transform_list),
|
178
232
|
// == end transform regexp
|
179
233
|
|
180
|
-
reTransform = new RegExp(transform);
|
234
|
+
reTransform = new RegExp(transform, 'g');
|
181
235
|
|
182
236
|
return function(attributeValue) {
|
183
237
|
|
184
238
|
// start with identity matrix
|
185
239
|
var matrix = iMatrix.concat();
|
240
|
+
var matrices = [ ];
|
186
241
|
|
187
242
|
// return if no argument was given or
|
188
243
|
// an argument does not match transform attribute regexp
|
@@ -218,8 +273,19 @@
|
|
218
273
|
matrix = args;
|
219
274
|
break;
|
220
275
|
}
|
276
|
+
|
277
|
+
// snapshot current matrix into matrices array
|
278
|
+
matrices.push(matrix.concat());
|
279
|
+
// reset
|
280
|
+
matrix = iMatrix.concat();
|
221
281
|
});
|
222
|
-
|
282
|
+
|
283
|
+
var combinedMatrix = matrices[0];
|
284
|
+
while (matrices.length > 1) {
|
285
|
+
matrices.shift();
|
286
|
+
combinedMatrix = fabric.util.multiplyTransformMatrices(combinedMatrix, matrices[0]);
|
287
|
+
}
|
288
|
+
return combinedMatrix;
|
223
289
|
};
|
224
290
|
})();
|
225
291
|
|
@@ -227,7 +293,6 @@
|
|
227
293
|
* Parses "points" attribute, returning an array of values
|
228
294
|
* @static
|
229
295
|
* @memberOf fabric
|
230
|
-
* @method parsePointsAttribute
|
231
296
|
* @param points {String} points attribute string
|
232
297
|
* @return {Array} array of points
|
233
298
|
*/
|
@@ -267,38 +332,76 @@
|
|
267
332
|
return parsedPoints;
|
268
333
|
}
|
269
334
|
|
335
|
+
function parseFontDeclaration(value, oStyle) {
|
336
|
+
|
337
|
+
// TODO: support non-px font size
|
338
|
+
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\s+(.*)/);
|
339
|
+
|
340
|
+
if (!match) return;
|
341
|
+
|
342
|
+
var fontStyle = match[1];
|
343
|
+
// Font variant is not used
|
344
|
+
// var fontVariant = match[2];
|
345
|
+
var fontWeight = match[3];
|
346
|
+
var fontSize = match[4];
|
347
|
+
var fontFamily = match[5];
|
348
|
+
|
349
|
+
if (fontStyle) {
|
350
|
+
oStyle.fontStyle = fontStyle;
|
351
|
+
}
|
352
|
+
if (fontWeight) {
|
353
|
+
oStyle.fontSize = isNaN(parseFloat(fontWeight)) ? fontWeight : parseFloat(fontWeight);
|
354
|
+
}
|
355
|
+
if (fontSize) {
|
356
|
+
oStyle.fontSize = parseFloat(fontSize);
|
357
|
+
}
|
358
|
+
if (fontFamily) {
|
359
|
+
oStyle.fontFamily = fontFamily;
|
360
|
+
}
|
361
|
+
}
|
362
|
+
|
270
363
|
/**
|
271
364
|
* Parses "style" attribute, retuning an object with values
|
272
365
|
* @static
|
273
366
|
* @memberOf fabric
|
274
|
-
* @method parseStyleAttribute
|
275
367
|
* @param {SVGElement} element Element to parse
|
276
368
|
* @return {Object} Objects with values parsed from style attribute of an element
|
277
369
|
*/
|
278
370
|
function parseStyleAttribute(element) {
|
279
371
|
var oStyle = { },
|
280
|
-
style = element.getAttribute('style')
|
372
|
+
style = element.getAttribute('style'),
|
373
|
+
attr, value;
|
281
374
|
|
282
375
|
if (!style) return oStyle;
|
283
376
|
|
284
377
|
if (typeof style === 'string') {
|
285
|
-
style
|
378
|
+
style.replace(/;$/, '').split(';').forEach(function (chunk) {
|
379
|
+
var pair = chunk.split(':');
|
286
380
|
|
287
|
-
|
288
|
-
|
381
|
+
attr = normalizeAttr(pair[0].trim().toLowerCase());
|
382
|
+
value = normalizeValue(attr, pair[1].trim());
|
289
383
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
384
|
+
if (attr === 'font') {
|
385
|
+
parseFontDeclaration(value, oStyle);
|
386
|
+
}
|
387
|
+
else {
|
388
|
+
oStyle[attr] = value;
|
389
|
+
}
|
294
390
|
});
|
295
391
|
}
|
296
392
|
else {
|
297
393
|
for (var prop in style) {
|
298
394
|
if (typeof style[prop] === 'undefined') continue;
|
299
395
|
|
300
|
-
|
301
|
-
|
396
|
+
attr = normalizeAttr(prop.toLowerCase());
|
397
|
+
value = normalizeValue(attr, style[prop]);
|
398
|
+
|
399
|
+
if (attr === 'font') {
|
400
|
+
parseFontDeclaration(value, oStyle);
|
401
|
+
}
|
402
|
+
else {
|
403
|
+
oStyle[attr] = value;
|
404
|
+
}
|
302
405
|
}
|
303
406
|
}
|
304
407
|
|
@@ -325,7 +428,6 @@
|
|
325
428
|
* Transforms an array of svg elements to corresponding fabric.* instances
|
326
429
|
* @static
|
327
430
|
* @memberOf fabric
|
328
|
-
* @method parseElements
|
329
431
|
* @param {Array} elements Array of elements to parse
|
330
432
|
* @param {Function} callback Being passed an array of fabric instances (transformed from SVG elements)
|
331
433
|
* @param {Object} [options] Options object
|
@@ -356,7 +458,7 @@
|
|
356
458
|
instances.splice(index, 0, obj);
|
357
459
|
checkIfDone();
|
358
460
|
};
|
359
|
-
})(index), options);
|
461
|
+
})(index, el), options);
|
360
462
|
}
|
361
463
|
else {
|
362
464
|
var obj = klass.fromElement(el, options);
|
@@ -380,7 +482,6 @@
|
|
380
482
|
* @static
|
381
483
|
* @function
|
382
484
|
* @memberOf fabric
|
383
|
-
* @method getCSSRules
|
384
485
|
* @param {SVGDocument} doc SVG document to parse
|
385
486
|
* @return {Object} CSS rules of this document
|
386
487
|
*/
|
@@ -451,7 +552,6 @@
|
|
451
552
|
* @static
|
452
553
|
* @function
|
453
554
|
* @memberOf fabric
|
454
|
-
* @method parseSVGDocument
|
455
555
|
* @param {SVGDocument} doc SVG document to parse
|
456
556
|
* @param {Function} callback Callback to call when parsing is finished; It's being passed an array of elements (parsed from a document).
|
457
557
|
* @param {Function} [reviver] Method for further parsing of SVG elements, called after each fabric object created.
|
@@ -546,15 +646,13 @@
|
|
546
646
|
};
|
547
647
|
})();
|
548
648
|
|
549
|
-
|
649
|
+
/**
|
550
650
|
* Used for caching SVG documents (loaded via `fabric.Canvas#loadSVGFromURL`)
|
551
|
-
* @property
|
552
651
|
* @namespace
|
553
652
|
*/
|
554
653
|
var svgCache = {
|
555
654
|
|
556
655
|
/**
|
557
|
-
* @method has
|
558
656
|
* @param {String} name
|
559
657
|
* @param {Function} callback
|
560
658
|
*/
|
@@ -563,7 +661,6 @@
|
|
563
661
|
},
|
564
662
|
|
565
663
|
/**
|
566
|
-
* @method get
|
567
664
|
* @param {String} url
|
568
665
|
* @param {Function} callback
|
569
666
|
*/
|
@@ -572,7 +669,6 @@
|
|
572
669
|
},
|
573
670
|
|
574
671
|
/**
|
575
|
-
* @method set
|
576
672
|
* @param {String} url
|
577
673
|
* @param {Object} object
|
578
674
|
*/
|
@@ -582,8 +678,7 @@
|
|
582
678
|
};
|
583
679
|
|
584
680
|
/**
|
585
|
-
* Takes url corresponding to an SVG document, and parses it into a set of fabric objects
|
586
|
-
* @method loadSVGFromURL
|
681
|
+
* Takes url corresponding to an SVG document, and parses it into a set of fabric objects. Note that SVG is fetched via XMLHttpRequest, so it needs to conform to SOP (Same Origin Policy)
|
587
682
|
* @memberof fabric
|
588
683
|
* @param {String} url
|
589
684
|
* @param {Function} callback
|
@@ -630,8 +725,8 @@
|
|
630
725
|
}
|
631
726
|
|
632
727
|
/**
|
633
|
-
|
634
|
-
|
728
|
+
* @private
|
729
|
+
*/
|
635
730
|
function _enlivenCachedObject(cachedObject) {
|
636
731
|
|
637
732
|
var objects = cachedObject.objects,
|
@@ -646,7 +741,6 @@
|
|
646
741
|
|
647
742
|
/**
|
648
743
|
* Takes string corresponding to an SVG document, and parses it into a set of fabric objects
|
649
|
-
* @method loadSVGFromString
|
650
744
|
* @memberof fabric
|
651
745
|
* @param {String} string
|
652
746
|
* @param {Function} callback
|
@@ -675,7 +769,6 @@
|
|
675
769
|
|
676
770
|
/**
|
677
771
|
* Creates markup containing SVG font faces
|
678
|
-
* @method createSVGFontFacesMarkup
|
679
772
|
* @param {Array} objects Array of fabric objects
|
680
773
|
* @return {String}
|
681
774
|
*/
|
@@ -708,7 +801,6 @@
|
|
708
801
|
|
709
802
|
/**
|
710
803
|
* Creates markup containing SVG referenced elements like patterns, gradients etc.
|
711
|
-
* @method createSVGRefElementsMarkup
|
712
804
|
* @param {fabric.Canvas} canvas instance of fabric.Canvas
|
713
805
|
* @return {String}
|
714
806
|
*/
|
@@ -732,6 +824,35 @@
|
|
732
824
|
return markup;
|
733
825
|
}
|
734
826
|
|
827
|
+
/**
|
828
|
+
* Parses an SVG document, returning all of the gradient declarations found in it
|
829
|
+
* @static
|
830
|
+
* @function
|
831
|
+
* @memberOf fabric
|
832
|
+
* @param {SVGDocument} doc SVG document to parse
|
833
|
+
* @return {Object} Gradient definitions; key corresponds to element id, value -- to gradient definition element
|
834
|
+
*/
|
835
|
+
function getGradientDefs(doc) {
|
836
|
+
var linearGradientEls = doc.getElementsByTagName('linearGradient'),
|
837
|
+
radialGradientEls = doc.getElementsByTagName('radialGradient'),
|
838
|
+
el, i,
|
839
|
+
gradientDefs = { };
|
840
|
+
|
841
|
+
i = linearGradientEls.length;
|
842
|
+
for (; i--; ) {
|
843
|
+
el = linearGradientEls[i];
|
844
|
+
gradientDefs[el.getAttribute('id')] = el;
|
845
|
+
}
|
846
|
+
|
847
|
+
i = radialGradientEls.length;
|
848
|
+
for (; i--; ) {
|
849
|
+
el = radialGradientEls[i];
|
850
|
+
gradientDefs[el.getAttribute('id')] = el;
|
851
|
+
}
|
852
|
+
|
853
|
+
return gradientDefs;
|
854
|
+
}
|
855
|
+
|
735
856
|
extend(fabric, {
|
736
857
|
|
737
858
|
parseAttributes: parseAttributes,
|
@@ -744,7 +865,9 @@
|
|
744
865
|
loadSVGFromString: loadSVGFromString,
|
745
866
|
|
746
867
|
createSVGFontFacesMarkup: createSVGFontFacesMarkup,
|
747
|
-
createSVGRefElementsMarkup: createSVGRefElementsMarkup
|
868
|
+
createSVGRefElementsMarkup: createSVGRefElementsMarkup,
|
869
|
+
|
870
|
+
getGradientDefs: getGradientDefs
|
748
871
|
});
|
749
872
|
|
750
873
|
})(typeof exports !== 'undefined' ? exports : this);
|