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
@@ -12,35 +12,41 @@
|
|
12
12
|
|
13
13
|
/**
|
14
14
|
* Rectangle class
|
15
|
-
* @class Rect
|
15
|
+
* @class fabric.Rect
|
16
16
|
* @extends fabric.Object
|
17
|
+
* @return {fabric.Rect} thisArg
|
17
18
|
*/
|
18
|
-
fabric.Rect = fabric.util.createClass(fabric.Object, /** @
|
19
|
+
fabric.Rect = fabric.util.createClass(fabric.Object, /** @lends fabric.Rect.prototype */ {
|
19
20
|
|
20
21
|
/**
|
21
22
|
* Type of an object
|
22
|
-
* @property
|
23
23
|
* @type String
|
24
|
+
* @default
|
24
25
|
*/
|
25
26
|
type: 'rect',
|
26
27
|
|
27
28
|
/**
|
28
29
|
* Horizontal border radius
|
29
|
-
* @property
|
30
30
|
* @type Number
|
31
|
+
* @default
|
31
32
|
*/
|
32
|
-
rx:
|
33
|
+
rx: 0,
|
33
34
|
|
34
35
|
/**
|
35
36
|
* Vertical border radius
|
36
|
-
* @property
|
37
37
|
* @type Number
|
38
|
+
* @default
|
38
39
|
*/
|
39
|
-
ry:
|
40
|
+
ry: 0,
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Used to specify dash pattern for stroke on this object
|
44
|
+
* @type Array
|
45
|
+
*/
|
46
|
+
strokeDashArray: null,
|
40
47
|
|
41
48
|
/**
|
42
49
|
* Constructor
|
43
|
-
* @method initialize
|
44
50
|
* @param {Object} [options] Options object
|
45
51
|
* @return {Object} thisArg
|
46
52
|
*/
|
@@ -51,15 +57,14 @@
|
|
51
57
|
this.callSuper('initialize', options);
|
52
58
|
this._initRxRy();
|
53
59
|
|
54
|
-
this.x = 0;
|
55
|
-
this.y = 0;
|
60
|
+
this.x = options.x || 0;
|
61
|
+
this.y = options.y || 0;
|
56
62
|
},
|
57
63
|
|
58
64
|
/**
|
59
65
|
* Creates `stateProperties` list on an instance, and adds `fabric.Rect` -specific ones to it
|
60
66
|
* (such as "rx", "ry", etc.)
|
61
67
|
* @private
|
62
|
-
* @method _initStateProperties
|
63
68
|
*/
|
64
69
|
_initStateProperties: function() {
|
65
70
|
this.stateProperties = this.stateProperties.concat(['rx', 'ry']);
|
@@ -68,7 +73,6 @@
|
|
68
73
|
/**
|
69
74
|
* Initializes rx/ry attributes
|
70
75
|
* @private
|
71
|
-
* @method _initRxRy
|
72
76
|
*/
|
73
77
|
_initRxRy: function() {
|
74
78
|
if (this.rx && !this.ry) {
|
@@ -81,7 +85,6 @@
|
|
81
85
|
|
82
86
|
/**
|
83
87
|
* @private
|
84
|
-
* @method _render
|
85
88
|
* @param ctx {CanvasRenderingContext2D} context to render on
|
86
89
|
*/
|
87
90
|
_render: function(ctx) {
|
@@ -90,168 +93,132 @@
|
|
90
93
|
x = -this.width / 2,
|
91
94
|
y = -this.height / 2,
|
92
95
|
w = this.width,
|
93
|
-
h = this.height
|
96
|
+
h = this.height,
|
97
|
+
isInPathGroup = this.group && this.group.type !== 'group';
|
94
98
|
|
95
99
|
ctx.beginPath();
|
96
|
-
ctx.globalAlpha =
|
100
|
+
ctx.globalAlpha = isInPathGroup ? (ctx.globalAlpha * this.opacity) : this.opacity;
|
97
101
|
|
98
|
-
if (this.transformMatrix &&
|
102
|
+
if (this.transformMatrix && isInPathGroup) {
|
99
103
|
ctx.translate(
|
100
104
|
this.width / 2 + this.x,
|
101
105
|
this.height / 2 + this.y);
|
102
106
|
}
|
103
|
-
if (!this.transformMatrix &&
|
107
|
+
if (!this.transformMatrix && isInPathGroup) {
|
104
108
|
ctx.translate(
|
105
109
|
-this.group.width / 2 + this.width / 2 + this.x,
|
106
110
|
-this.group.height / 2 + this.height / 2 + this.y);
|
107
111
|
}
|
108
112
|
|
113
|
+
var isRounded = rx !== 0 || ry !== 0;
|
114
|
+
|
109
115
|
ctx.moveTo(x+rx, y);
|
110
116
|
ctx.lineTo(x+w-rx, y);
|
111
|
-
ctx.quadraticCurveTo(x+w, y, x+w, y+ry, x+w, y+ry);
|
117
|
+
isRounded && ctx.quadraticCurveTo(x+w, y, x+w, y+ry, x+w, y+ry);
|
112
118
|
ctx.lineTo(x+w, y+h-ry);
|
113
|
-
ctx.quadraticCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h);
|
119
|
+
isRounded && ctx.quadraticCurveTo(x+w,y+h,x+w-rx,y+h,x+w-rx,y+h);
|
114
120
|
ctx.lineTo(x+rx,y+h);
|
115
|
-
ctx.quadraticCurveTo(x,y+h,x,y+h-ry,x,y+h-ry);
|
121
|
+
isRounded && ctx.quadraticCurveTo(x,y+h,x,y+h-ry,x,y+h-ry);
|
116
122
|
ctx.lineTo(x,y+ry);
|
117
|
-
ctx.quadraticCurveTo(x,y,x+rx,y,x+rx,y);
|
123
|
+
isRounded && ctx.quadraticCurveTo(x,y,x+rx,y,x+rx,y);
|
118
124
|
ctx.closePath();
|
119
125
|
|
120
|
-
|
121
|
-
|
122
|
-
}
|
123
|
-
|
124
|
-
this._removeShadow(ctx);
|
125
|
-
|
126
|
-
if (this.strokeDashArray) {
|
127
|
-
this._renderDashedStroke(ctx);
|
128
|
-
}
|
129
|
-
else if (this.stroke) {
|
130
|
-
ctx.stroke();
|
131
|
-
}
|
126
|
+
this._renderFill(ctx);
|
127
|
+
this._renderStroke(ctx);
|
132
128
|
},
|
133
129
|
|
134
130
|
/**
|
135
131
|
* @private
|
136
|
-
* @
|
132
|
+
* @param ctx {CanvasRenderingContext2D} context to render on
|
137
133
|
*/
|
138
134
|
_renderDashedStroke: function(ctx) {
|
135
|
+
var x = -this.width/2,
|
136
|
+
y = -this.height/2,
|
137
|
+
w = this.width,
|
138
|
+
h = this.height;
|
139
139
|
|
140
|
-
if (1 & this.strokeDashArray.length /* if odd number of items */) {
|
141
|
-
/* duplicate items */
|
142
|
-
this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
|
143
|
-
}
|
144
|
-
|
145
|
-
var i = 0,
|
146
|
-
x = -this.width/2, y = -this.height/2,
|
147
|
-
_this = this,
|
148
|
-
padding = this.padding,
|
149
|
-
dashedArrayLength = this.strokeDashArray.length;
|
150
|
-
|
151
|
-
ctx.save();
|
152
140
|
ctx.beginPath();
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
var lineLength = 0,
|
158
|
-
lengthDiff = 0,
|
159
|
-
sideLength = (yMultiplier ? _this.height : _this.width) + padding * 2;
|
160
|
-
|
161
|
-
while (lineLength < sideLength) {
|
162
|
-
|
163
|
-
var lengthOfSubPath = _this.strokeDashArray[i++];
|
164
|
-
lineLength += lengthOfSubPath;
|
165
|
-
|
166
|
-
if (lineLength > sideLength) {
|
167
|
-
lengthDiff = lineLength - sideLength;
|
168
|
-
}
|
169
|
-
|
170
|
-
// track coords
|
171
|
-
if (xMultiplier) {
|
172
|
-
x += (lengthOfSubPath * xMultiplier) - (lengthDiff * xMultiplier || 0);
|
173
|
-
}
|
174
|
-
else {
|
175
|
-
y += (lengthOfSubPath * yMultiplier) - (lengthDiff * yMultiplier || 0);
|
176
|
-
}
|
177
|
-
|
178
|
-
ctx[1 & i /* odd */ ? 'moveTo' : 'lineTo'](x, y);
|
179
|
-
if (i >= dashedArrayLength) {
|
180
|
-
i = 0;
|
181
|
-
}
|
182
|
-
}
|
183
|
-
}
|
184
|
-
|
185
|
-
renderSide(1, 0);
|
186
|
-
renderSide(0, 1);
|
187
|
-
renderSide(-1, 0);
|
188
|
-
renderSide(0, -1);
|
189
|
-
|
190
|
-
ctx.stroke();
|
141
|
+
fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray);
|
142
|
+
fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray);
|
143
|
+
fabric.util.drawDashedLine(ctx, x+w, y+h, x, y+h, this.strokeDashArray);
|
144
|
+
fabric.util.drawDashedLine(ctx, x, y+h, x, y, this.strokeDashArray);
|
191
145
|
ctx.closePath();
|
192
|
-
ctx.restore();
|
193
146
|
},
|
194
147
|
|
195
148
|
/**
|
196
|
-
* @method _normalizeLeftTopProperties
|
197
|
-
* @private
|
198
149
|
* Since coordinate system differs from that of SVG
|
150
|
+
* @private
|
199
151
|
*/
|
200
152
|
_normalizeLeftTopProperties: function(parsedAttributes) {
|
201
|
-
if (parsedAttributes
|
153
|
+
if ('left' in parsedAttributes) {
|
202
154
|
this.set('left', parsedAttributes.left + this.getWidth() / 2);
|
203
155
|
}
|
204
156
|
this.set('x', parsedAttributes.left || 0);
|
205
|
-
if (parsedAttributes
|
157
|
+
if ('top' in parsedAttributes) {
|
206
158
|
this.set('top', parsedAttributes.top + this.getHeight() / 2);
|
207
159
|
}
|
208
160
|
this.set('y', parsedAttributes.top || 0);
|
209
161
|
return this;
|
210
162
|
},
|
211
163
|
|
212
|
-
/**
|
213
|
-
* Returns complexity of an instance
|
214
|
-
* @method complexity
|
215
|
-
* @return {Number} complexity
|
216
|
-
*/
|
217
|
-
complexity: function() {
|
218
|
-
return 1;
|
219
|
-
},
|
220
|
-
|
221
164
|
/**
|
222
165
|
* Returns object representation of an instance
|
223
|
-
* @method toObject
|
224
166
|
* @param {Array} propertiesToInclude
|
225
167
|
* @return {Object} object representation of an instance
|
226
168
|
*/
|
227
169
|
toObject: function(propertiesToInclude) {
|
228
170
|
return extend(this.callSuper('toObject', propertiesToInclude), {
|
229
171
|
rx: this.get('rx') || 0,
|
230
|
-
ry: this.get('ry') || 0
|
172
|
+
ry: this.get('ry') || 0,
|
173
|
+
x: this.get('x'),
|
174
|
+
y: this.get('y')
|
231
175
|
});
|
232
176
|
},
|
233
177
|
|
178
|
+
/* _TO_SVG_START_ */
|
234
179
|
/**
|
235
180
|
* Returns svg representation of an instance
|
236
|
-
* @method toSVG
|
237
181
|
* @return {String} svg representation of an instance
|
238
182
|
*/
|
239
183
|
toSVG: function() {
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
184
|
+
var markup = [];
|
185
|
+
|
186
|
+
if (this.fill && this.fill.toLive) {
|
187
|
+
markup.push(this.fill.toSVG(this, false));
|
188
|
+
}
|
189
|
+
if (this.stroke && this.stroke.toLive) {
|
190
|
+
markup.push(this.stroke.toSVG(this, false));
|
191
|
+
}
|
192
|
+
|
193
|
+
markup.push(
|
194
|
+
'<rect ',
|
195
|
+
'x="', (-1 * this.width / 2), '" y="', (-1 * this.height / 2),
|
196
|
+
'" rx="', this.get('rx'), '" ry="', this.get('ry'),
|
197
|
+
'" width="', this.width, '" height="', this.height,
|
198
|
+
'" style="', this.getSvgStyles(),
|
199
|
+
'" transform="', this.getSvgTransform(),
|
200
|
+
'"/>'
|
201
|
+
);
|
202
|
+
|
203
|
+
return markup.join('');
|
204
|
+
},
|
205
|
+
/* _TO_SVG_END_ */
|
206
|
+
|
207
|
+
/**
|
208
|
+
* Returns complexity of an instance
|
209
|
+
* @return {Number} complexity
|
210
|
+
*/
|
211
|
+
complexity: function() {
|
212
|
+
return 1;
|
247
213
|
}
|
248
214
|
});
|
249
215
|
|
216
|
+
/* _FROM_SVG_START_ */
|
250
217
|
/**
|
251
218
|
* List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
|
252
219
|
* @static
|
253
220
|
*/
|
254
|
-
fabric.Rect.ATTRIBUTE_NAMES = 'x y
|
221
|
+
fabric.Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));
|
255
222
|
|
256
223
|
/**
|
257
224
|
* @private
|
@@ -265,7 +232,6 @@
|
|
265
232
|
/**
|
266
233
|
* Returns {@link fabric.Rect} instance from an SVG element
|
267
234
|
* @static
|
268
|
-
* @method fabric.Rect.fromElement
|
269
235
|
* @param {SVGElement} element Element to parse
|
270
236
|
* @param {Object} [options] Options object
|
271
237
|
* @return {fabric.Rect} Instance of fabric.Rect
|
@@ -283,11 +249,11 @@
|
|
283
249
|
|
284
250
|
return rect;
|
285
251
|
};
|
252
|
+
/* _FROM_SVG_END_ */
|
286
253
|
|
287
254
|
/**
|
288
255
|
* Returns {@link fabric.Rect} instance from an object representation
|
289
256
|
* @static
|
290
|
-
* @method fabric.Rect.fromObject
|
291
257
|
* @param object {Object} object to create an instance from
|
292
258
|
* @return {Object} instance of fabric.Rect
|
293
259
|
*/
|
@@ -295,4 +261,4 @@
|
|
295
261
|
return new fabric.Rect(object);
|
296
262
|
};
|
297
263
|
|
298
|
-
})(typeof exports !== 'undefined' ? exports : this);
|
264
|
+
})(typeof exports !== 'undefined' ? exports : this);
|
@@ -5,25 +5,14 @@
|
|
5
5
|
var fabric = global.fabric || (global.fabric = { }),
|
6
6
|
extend = fabric.util.object.extend,
|
7
7
|
clone = fabric.util.object.clone,
|
8
|
-
toFixed = fabric.util.toFixed
|
8
|
+
toFixed = fabric.util.toFixed,
|
9
|
+
supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
|
9
10
|
|
10
11
|
if (fabric.Text) {
|
11
12
|
fabric.warn('fabric.Text is already defined');
|
12
13
|
return;
|
13
14
|
}
|
14
15
|
|
15
|
-
var dimensionAffectingProps = {
|
16
|
-
fontSize: true,
|
17
|
-
fontWeight: true,
|
18
|
-
fontFamily: true,
|
19
|
-
textDecoration: true,
|
20
|
-
fontStyle: true,
|
21
|
-
lineHeight: true,
|
22
|
-
strokeStyle: true,
|
23
|
-
strokeWidth: true,
|
24
|
-
text: true
|
25
|
-
};
|
26
|
-
|
27
16
|
var stateProperties = fabric.Object.prototype.stateProperties.concat();
|
28
17
|
stateProperties.push(
|
29
18
|
'fontFamily',
|
@@ -36,8 +25,6 @@
|
|
36
25
|
'textAlign',
|
37
26
|
'fontStyle',
|
38
27
|
'lineHeight',
|
39
|
-
'strokeStyle',
|
40
|
-
'strokeWidth',
|
41
28
|
'backgroundColor',
|
42
29
|
'textBackgroundColor',
|
43
30
|
'useNative'
|
@@ -45,136 +32,140 @@
|
|
45
32
|
|
46
33
|
/**
|
47
34
|
* Text class
|
48
|
-
* @class Text
|
35
|
+
* @class fabric.Text
|
49
36
|
* @extends fabric.Object
|
37
|
+
* @return {fabric.Text} thisArg
|
50
38
|
*/
|
51
|
-
fabric.Text = fabric.util.createClass(fabric.Object, /** @
|
39
|
+
fabric.Text = fabric.util.createClass(fabric.Object, /** @lends fabric.Text.prototype */ {
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Properties which when set cause object to change dimensions
|
43
|
+
* @type Object
|
44
|
+
* @private
|
45
|
+
*/
|
46
|
+
_dimensionAffectingProps: {
|
47
|
+
fontSize: true,
|
48
|
+
fontWeight: true,
|
49
|
+
fontFamily: true,
|
50
|
+
textDecoration: true,
|
51
|
+
fontStyle: true,
|
52
|
+
lineHeight: true,
|
53
|
+
stroke: true,
|
54
|
+
strokeWidth: true,
|
55
|
+
text: true
|
56
|
+
},
|
57
|
+
|
58
|
+
/**
|
59
|
+
* Type of an object
|
60
|
+
* @type String
|
61
|
+
* @default
|
62
|
+
*/
|
63
|
+
type: 'text',
|
52
64
|
|
53
65
|
/**
|
54
66
|
* Font size (in pixels)
|
55
|
-
* @property
|
56
67
|
* @type Number
|
68
|
+
* @default
|
57
69
|
*/
|
58
70
|
fontSize: 40,
|
59
71
|
|
60
72
|
/**
|
61
73
|
* Font weight (e.g. bold, normal, 400, 600, 800)
|
62
|
-
* @property
|
63
74
|
* @type Number
|
75
|
+
* @default
|
64
76
|
*/
|
65
77
|
fontWeight: 'normal',
|
66
78
|
|
67
79
|
/**
|
68
80
|
* Font family
|
69
|
-
* @property
|
70
81
|
* @type String
|
82
|
+
* @default
|
71
83
|
*/
|
72
84
|
fontFamily: 'Times New Roman',
|
73
85
|
|
74
86
|
/**
|
75
|
-
* Text decoration
|
76
|
-
* @property
|
87
|
+
* Text decoration Possible values: "", "underline", "overline" or "line-through".
|
77
88
|
* @type String
|
89
|
+
* @default
|
78
90
|
*/
|
79
91
|
textDecoration: '',
|
80
92
|
|
81
93
|
/**
|
82
94
|
* Text shadow
|
83
|
-
* @property
|
84
95
|
* @type String | null
|
96
|
+
* @default
|
85
97
|
*/
|
86
98
|
textShadow: '',
|
87
99
|
|
88
100
|
/**
|
89
101
|
* Text alignment. Possible values: "left", "center", or "right".
|
90
|
-
* @property
|
91
102
|
* @type String
|
103
|
+
* @default
|
92
104
|
*/
|
93
105
|
textAlign: 'left',
|
94
106
|
|
95
107
|
/**
|
96
|
-
* Font style
|
97
|
-
* @property
|
108
|
+
* Font style . Possible values: "", "normal", "italic" or "oblique".
|
98
109
|
* @type String
|
110
|
+
* @default
|
99
111
|
*/
|
100
112
|
fontStyle: '',
|
101
113
|
|
102
114
|
/**
|
103
115
|
* Line height
|
104
|
-
* @property
|
105
116
|
* @type Number
|
117
|
+
* @default
|
106
118
|
*/
|
107
119
|
lineHeight: 1.3,
|
108
120
|
|
109
|
-
/**
|
110
|
-
* Stroke style. When specified, text is rendered with stroke
|
111
|
-
* @property
|
112
|
-
* @type String
|
113
|
-
*/
|
114
|
-
strokeStyle: '',
|
115
|
-
|
116
|
-
/**
|
117
|
-
* Stroke width
|
118
|
-
* @property
|
119
|
-
* @type Number
|
120
|
-
*/
|
121
|
-
strokeWidth: 1,
|
122
|
-
|
123
121
|
/**
|
124
122
|
* Background color of an entire text box
|
125
|
-
* @property
|
126
123
|
* @type String
|
124
|
+
* @default
|
127
125
|
*/
|
128
126
|
backgroundColor: '',
|
129
127
|
|
130
128
|
/**
|
131
129
|
* Background color of text lines
|
132
|
-
* @property
|
133
130
|
* @type String
|
131
|
+
* @default
|
134
132
|
*/
|
135
133
|
textBackgroundColor: '',
|
136
134
|
|
137
135
|
/**
|
138
136
|
* URL of a font file, when using Cufon
|
139
|
-
* @property
|
140
137
|
* @type String | null
|
138
|
+
* @default
|
141
139
|
*/
|
142
140
|
path: null,
|
143
141
|
|
144
|
-
/**
|
145
|
-
* Type of an object
|
146
|
-
* @property
|
147
|
-
* @type String
|
148
|
-
*/
|
149
|
-
type: 'text',
|
150
|
-
|
151
142
|
/**
|
152
143
|
* Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used)
|
153
|
-
* @property
|
154
144
|
* @type Boolean
|
145
|
+
* @default
|
155
146
|
*/
|
156
147
|
useNative: true,
|
157
148
|
|
158
149
|
/**
|
159
|
-
* List of properties to consider when checking if state of an object is changed (fabric.Object#hasStateChanged)
|
150
|
+
* List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
|
160
151
|
* as well as for history (undo/redo) purposes
|
161
|
-
* @property
|
162
152
|
* @type Array
|
163
153
|
*/
|
164
154
|
stateProperties: stateProperties,
|
165
155
|
|
166
156
|
/**
|
167
157
|
* Constructor
|
168
|
-
* @
|
169
|
-
* @param {
|
170
|
-
* @param {Object} [options]
|
158
|
+
* @param {String} text Text string
|
159
|
+
* @param {Object} [options] Options object
|
171
160
|
* @return {fabric.Text} thisArg
|
172
161
|
*/
|
173
162
|
initialize: function(text, options) {
|
174
163
|
options = options || { };
|
175
164
|
|
176
165
|
this.text = text;
|
166
|
+
this.__skipDimension = true;
|
177
167
|
this.setOptions(options);
|
168
|
+
this.__skipDimension = false;
|
178
169
|
this._initDimensions();
|
179
170
|
this.setCoords();
|
180
171
|
},
|
@@ -182,16 +173,15 @@
|
|
182
173
|
/**
|
183
174
|
* Renders text object on offscreen canvas, so that it would get dimensions
|
184
175
|
* @private
|
185
|
-
* @method _initDimensions
|
186
176
|
*/
|
187
177
|
_initDimensions: function() {
|
178
|
+
if (this.__skipDimension) return;
|
188
179
|
var canvasEl = fabric.util.createCanvasElement();
|
189
180
|
this._render(canvasEl.getContext('2d'));
|
190
181
|
},
|
191
182
|
|
192
183
|
/**
|
193
184
|
* Returns string representation of an instance
|
194
|
-
* @method toString
|
195
185
|
* @return {String} String representation of text object
|
196
186
|
*/
|
197
187
|
toString: function() {
|
@@ -201,10 +191,18 @@
|
|
201
191
|
|
202
192
|
/**
|
203
193
|
* @private
|
204
|
-
* @method _render
|
205
194
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
206
195
|
*/
|
207
196
|
_render: function(ctx) {
|
197
|
+
|
198
|
+
var isInPathGroup = this.group && this.group.type !== 'group';
|
199
|
+
if (isInPathGroup && !this.transformMatrix) {
|
200
|
+
ctx.translate(-this.group.width/2 + this.left, -this.group.height / 2 + this.top);
|
201
|
+
}
|
202
|
+
else if (isInPathGroup && this.transformMatrix) {
|
203
|
+
ctx.translate(-this.group.width/2, -this.group.height/2);
|
204
|
+
}
|
205
|
+
|
208
206
|
if (typeof Cufon === 'undefined' || this.useNative === true) {
|
209
207
|
this._renderViaNative(ctx);
|
210
208
|
}
|
@@ -215,63 +213,12 @@
|
|
215
213
|
|
216
214
|
/**
|
217
215
|
* @private
|
218
|
-
* @method _renderViaCufon
|
219
|
-
*/
|
220
|
-
_renderViaCufon: function(ctx) {
|
221
|
-
var o = Cufon.textOptions || (Cufon.textOptions = { });
|
222
|
-
|
223
|
-
// export options to be used by cufon.js
|
224
|
-
o.left = this.left;
|
225
|
-
o.top = this.top;
|
226
|
-
o.context = ctx;
|
227
|
-
o.color = this.fill;
|
228
|
-
|
229
|
-
var el = this._initDummyElementForCufon();
|
230
|
-
|
231
|
-
// set "cursor" to top/left corner
|
232
|
-
this.transform(ctx);
|
233
|
-
|
234
|
-
// draw text
|
235
|
-
Cufon.replaceElement(el, {
|
236
|
-
engine: 'canvas',
|
237
|
-
separate: 'none',
|
238
|
-
fontFamily: this.fontFamily,
|
239
|
-
fontWeight: this.fontWeight,
|
240
|
-
textDecoration: this.textDecoration,
|
241
|
-
textShadow: this.textShadow,
|
242
|
-
textAlign: this.textAlign,
|
243
|
-
fontStyle: this.fontStyle,
|
244
|
-
lineHeight: this.lineHeight,
|
245
|
-
strokeStyle: this.strokeStyle,
|
246
|
-
strokeWidth: this.strokeWidth,
|
247
|
-
backgroundColor: this.backgroundColor,
|
248
|
-
textBackgroundColor: this.textBackgroundColor
|
249
|
-
});
|
250
|
-
|
251
|
-
// update width, height
|
252
|
-
this.width = o.width;
|
253
|
-
this.height = o.height;
|
254
|
-
|
255
|
-
this._totalLineHeight = o.totalLineHeight;
|
256
|
-
this._fontAscent = o.fontAscent;
|
257
|
-
this._boundaries = o.boundaries;
|
258
|
-
this._shadowOffsets = o.shadowOffsets;
|
259
|
-
this._shadows = o.shadows || [ ];
|
260
|
-
|
261
|
-
el = null;
|
262
|
-
|
263
|
-
// need to set coords _after_ the width/height was retreived from Cufon
|
264
|
-
this.setCoords();
|
265
|
-
},
|
266
|
-
|
267
|
-
/**
|
268
|
-
* @private
|
269
|
-
* @method _render_native
|
270
216
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
271
217
|
*/
|
272
218
|
_renderViaNative: function(ctx) {
|
273
219
|
|
274
|
-
this.transform(ctx);
|
220
|
+
this.transform(ctx, fabric.isLikelyNode);
|
221
|
+
|
275
222
|
this._setTextStyles(ctx);
|
276
223
|
|
277
224
|
var textLines = this.text.split(/\r?\n/);
|
@@ -286,11 +233,15 @@
|
|
286
233
|
ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0);
|
287
234
|
}
|
288
235
|
|
236
|
+
ctx.save();
|
289
237
|
this._setTextShadow(ctx);
|
238
|
+
this.clipTo && fabric.util.clipContext(this, ctx);
|
290
239
|
this._renderTextFill(ctx, textLines);
|
240
|
+
this._renderTextStroke(ctx, textLines);
|
241
|
+
this.clipTo && ctx.restore();
|
291
242
|
this.textShadow && ctx.restore();
|
243
|
+
ctx.restore();
|
292
244
|
|
293
|
-
this._renderTextStroke(ctx, textLines);
|
294
245
|
if (this.textAlign !== 'left' && this.textAlign !== 'justify') {
|
295
246
|
ctx.restore();
|
296
247
|
}
|
@@ -304,7 +255,8 @@
|
|
304
255
|
|
305
256
|
/**
|
306
257
|
* @private
|
307
|
-
* @
|
258
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
259
|
+
* @param {Array} textLines Array of all text lines
|
308
260
|
*/
|
309
261
|
_setBoundaries: function(ctx, textLines) {
|
310
262
|
this._boundaries = [ ];
|
@@ -324,14 +276,23 @@
|
|
324
276
|
|
325
277
|
/**
|
326
278
|
* @private
|
327
|
-
* @
|
279
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
328
280
|
*/
|
329
281
|
_setTextStyles: function(ctx) {
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
282
|
+
if (this.fill) {
|
283
|
+
ctx.fillStyle = this.fill.toLive
|
284
|
+
? this.fill.toLive(ctx)
|
285
|
+
: this.fill;
|
286
|
+
}
|
287
|
+
if (this.stroke) {
|
288
|
+
ctx.lineWidth = this.strokeWidth;
|
289
|
+
ctx.lineCap = this.strokeLineCap;
|
290
|
+
ctx.lineJoin = this.strokeLineJoin;
|
291
|
+
ctx.miterLimit = this.strokeMiterLimit;
|
292
|
+
ctx.strokeStyle = this.stroke.toLive
|
293
|
+
? this.stroke.toLive(ctx)
|
294
|
+
: this.stroke;
|
295
|
+
}
|
335
296
|
ctx.textBaseline = 'alphabetic';
|
336
297
|
ctx.textAlign = this.textAlign;
|
337
298
|
ctx.font = this._getFontDeclaration();
|
@@ -339,7 +300,9 @@
|
|
339
300
|
|
340
301
|
/**
|
341
302
|
* @private
|
342
|
-
* @
|
303
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
304
|
+
* @param {Array} textLines Array of all text lines
|
305
|
+
* @return {Number} Height of fabric.Text object
|
343
306
|
*/
|
344
307
|
_getTextHeight: function(ctx, textLines) {
|
345
308
|
return this.fontSize * textLines.length * this.lineHeight;
|
@@ -347,7 +310,9 @@
|
|
347
310
|
|
348
311
|
/**
|
349
312
|
* @private
|
350
|
-
* @
|
313
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
314
|
+
* @param {Array} textLines Array of all text lines
|
315
|
+
* @return {Number} Maximum width of fabric.Text object
|
351
316
|
*/
|
352
317
|
_getTextWidth: function(ctx, textLines) {
|
353
318
|
var maxWidth = ctx.measureText(textLines[0]).width;
|
@@ -363,48 +328,46 @@
|
|
363
328
|
|
364
329
|
/**
|
365
330
|
* @private
|
366
|
-
* @
|
331
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
367
332
|
*/
|
368
333
|
_setTextShadow: function(ctx) {
|
369
|
-
if (this.textShadow)
|
334
|
+
if (!this.textShadow) return;
|
370
335
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
336
|
+
// "rgba(0,0,0,0.2) 2px 2px 10px"
|
337
|
+
// "rgb(0, 100, 0) 0 0 5px"
|
338
|
+
// "red 2px 2px 1px"
|
339
|
+
// "#f55 123 345 567"
|
340
|
+
var reOffsetsAndBlur = /\s+(-?\d+)(?:px)?\s+(-?\d+)(?:px)?\s+(\d+)(?:px)?\s*/;
|
376
341
|
|
377
|
-
|
378
|
-
|
379
|
-
|
342
|
+
var shadowDeclaration = this.textShadow;
|
343
|
+
var offsetsAndBlur = reOffsetsAndBlur.exec(this.textShadow);
|
344
|
+
var shadowColor = shadowDeclaration.replace(reOffsetsAndBlur, '');
|
380
345
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
}
|
346
|
+
ctx.save();
|
347
|
+
ctx.shadowColor = shadowColor;
|
348
|
+
ctx.shadowOffsetX = parseInt(offsetsAndBlur[1], 10);
|
349
|
+
ctx.shadowOffsetY = parseInt(offsetsAndBlur[2], 10);
|
350
|
+
ctx.shadowBlur = parseInt(offsetsAndBlur[3], 10);
|
351
|
+
|
352
|
+
this._shadows = [{
|
353
|
+
blur: ctx.shadowBlur,
|
354
|
+
color: ctx.shadowColor,
|
355
|
+
offX: ctx.shadowOffsetX,
|
356
|
+
offY: ctx.shadowOffsetY
|
357
|
+
}];
|
358
|
+
|
359
|
+
this._shadowOffsets = [[
|
360
|
+
parseInt(ctx.shadowOffsetX, 10), parseInt(ctx.shadowOffsetY, 10)
|
361
|
+
]];
|
398
362
|
},
|
399
363
|
|
400
364
|
/**
|
401
365
|
* @private
|
402
|
-
* @method
|
403
|
-
* @param
|
404
|
-
* @param
|
405
|
-
* @param
|
406
|
-
* @param
|
407
|
-
* param top
|
366
|
+
* @param {String} method Method name ("fillText" or "strokeText")
|
367
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
368
|
+
* @param {String} line Text to render
|
369
|
+
* @param {Number} left Left position of text
|
370
|
+
* @param {Number} top Top position of text
|
408
371
|
*/
|
409
372
|
_drawTextLine: function(method, ctx, line, left, top) {
|
410
373
|
|
@@ -439,44 +402,88 @@
|
|
439
402
|
|
440
403
|
/**
|
441
404
|
* @private
|
442
|
-
* @
|
405
|
+
* @return {Number} Left offset
|
406
|
+
*/
|
407
|
+
_getLeftOffset: function() {
|
408
|
+
if (fabric.isLikelyNode && (this.originX === 'left' || this.originX === 'center')) {
|
409
|
+
return 0;
|
410
|
+
}
|
411
|
+
return -this.width / 2;
|
412
|
+
},
|
413
|
+
|
414
|
+
/**
|
415
|
+
* @private
|
416
|
+
* @return {Number} Top offset
|
417
|
+
*/
|
418
|
+
_getTopOffset: function() {
|
419
|
+
if (fabric.isLikelyNode) {
|
420
|
+
if (this.originY === 'center') {
|
421
|
+
return -this.height / 2;
|
422
|
+
}
|
423
|
+
else if (this.originY === 'bottom') {
|
424
|
+
return -this.height;
|
425
|
+
}
|
426
|
+
return 0;
|
427
|
+
}
|
428
|
+
// in browser, text drawing always starts at vertical center
|
429
|
+
return -this.height / 2;
|
430
|
+
},
|
431
|
+
|
432
|
+
/**
|
433
|
+
* @private
|
434
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
435
|
+
* @param {Array} textLines Array of all text lines
|
443
436
|
*/
|
444
437
|
_renderTextFill: function(ctx, textLines) {
|
438
|
+
if (!this.fill) return;
|
439
|
+
|
445
440
|
this._boundaries = [ ];
|
446
441
|
for (var i = 0, len = textLines.length; i < len; i++) {
|
447
442
|
this._drawTextLine(
|
448
443
|
'fillText',
|
449
444
|
ctx,
|
450
445
|
textLines[i],
|
451
|
-
|
452
|
-
|
446
|
+
this._getLeftOffset(),
|
447
|
+
this._getTopOffset() + (i * this.fontSize * this.lineHeight) + this.fontSize
|
453
448
|
);
|
454
449
|
}
|
455
450
|
},
|
456
451
|
|
457
452
|
/**
|
458
453
|
* @private
|
459
|
-
* @
|
454
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
455
|
+
* @param {Array} textLines Array of all text lines
|
460
456
|
*/
|
461
457
|
_renderTextStroke: function(ctx, textLines) {
|
462
|
-
if (this.
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
-this.width / 2,
|
470
|
-
(-this.height / 2) + (i * this.fontSize * this.lineHeight) + this.fontSize
|
471
|
-
);
|
458
|
+
if (!this.stroke) return;
|
459
|
+
|
460
|
+
ctx.save();
|
461
|
+
if (this.strokeDashArray) {
|
462
|
+
// Spec requires the concatenation of two copies the dash list when the number of elements is odd
|
463
|
+
if (1 & this.strokeDashArray.length) {
|
464
|
+
this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
|
472
465
|
}
|
473
|
-
ctx.
|
466
|
+
supportsLineDash && ctx.setLineDash(this.strokeDashArray);
|
474
467
|
}
|
468
|
+
|
469
|
+
ctx.beginPath();
|
470
|
+
for (var i = 0, len = textLines.length; i < len; i++) {
|
471
|
+
this._drawTextLine(
|
472
|
+
'strokeText',
|
473
|
+
ctx,
|
474
|
+
textLines[i],
|
475
|
+
this._getLeftOffset(),
|
476
|
+
this._getTopOffset() + (i * this.fontSize * this.lineHeight) + this.fontSize
|
477
|
+
);
|
478
|
+
}
|
479
|
+
ctx.closePath();
|
480
|
+
ctx.restore();
|
475
481
|
},
|
476
482
|
|
477
483
|
/**
|
478
484
|
* @private
|
479
|
-
* @
|
485
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
486
|
+
* @param {Array} textLines Array of all text lines
|
480
487
|
*/
|
481
488
|
_renderTextBackground: function(ctx, textLines) {
|
482
489
|
this._renderTextBoxBackground(ctx);
|
@@ -485,55 +492,57 @@
|
|
485
492
|
|
486
493
|
/**
|
487
494
|
* @private
|
488
|
-
* @
|
495
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
489
496
|
*/
|
490
497
|
_renderTextBoxBackground: function(ctx) {
|
491
|
-
if (this.backgroundColor)
|
492
|
-
ctx.save();
|
493
|
-
ctx.fillStyle = this.backgroundColor;
|
498
|
+
if (!this.backgroundColor) return;
|
494
499
|
|
495
|
-
|
496
|
-
|
497
|
-
(-this.height / 2),
|
498
|
-
this.width,
|
499
|
-
this.height
|
500
|
-
);
|
500
|
+
ctx.save();
|
501
|
+
ctx.fillStyle = this.backgroundColor;
|
501
502
|
|
502
|
-
|
503
|
-
|
503
|
+
ctx.fillRect(
|
504
|
+
this._getLeftOffset(),
|
505
|
+
this._getTopOffset(),
|
506
|
+
this.width,
|
507
|
+
this.height
|
508
|
+
);
|
509
|
+
|
510
|
+
ctx.restore();
|
504
511
|
},
|
505
512
|
|
506
513
|
/**
|
507
514
|
* @private
|
508
|
-
* @
|
515
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
516
|
+
* @param {Array} textLines Array of all text lines
|
509
517
|
*/
|
510
518
|
_renderTextLinesBackground: function(ctx, textLines) {
|
511
|
-
if (this.textBackgroundColor)
|
512
|
-
ctx.save();
|
513
|
-
ctx.fillStyle = this.textBackgroundColor;
|
519
|
+
if (!this.textBackgroundColor) return;
|
514
520
|
|
515
|
-
|
521
|
+
ctx.save();
|
522
|
+
ctx.fillStyle = this.textBackgroundColor;
|
516
523
|
|
517
|
-
|
524
|
+
for (var i = 0, len = textLines.length; i < len; i++) {
|
518
525
|
|
519
|
-
|
520
|
-
var lineLeftOffset = this._getLineLeftOffset(lineWidth);
|
526
|
+
if (textLines[i] !== '') {
|
521
527
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
)
|
528
|
-
|
528
|
+
var lineWidth = this._getLineWidth(ctx, textLines[i]);
|
529
|
+
var lineLeftOffset = this._getLineLeftOffset(lineWidth);
|
530
|
+
|
531
|
+
ctx.fillRect(
|
532
|
+
this._getLeftOffset() + lineLeftOffset,
|
533
|
+
this._getTopOffset() + (i * this.fontSize * this.lineHeight),
|
534
|
+
lineWidth,
|
535
|
+
this.fontSize * this.lineHeight
|
536
|
+
);
|
529
537
|
}
|
530
|
-
ctx.restore();
|
531
538
|
}
|
539
|
+
ctx.restore();
|
532
540
|
},
|
533
541
|
|
534
542
|
/**
|
535
543
|
* @private
|
536
|
-
* @
|
544
|
+
* @param {Number} lineWidth Width of text line
|
545
|
+
* @return {Number} Line left offset
|
537
546
|
*/
|
538
547
|
_getLineLeftOffset: function(lineWidth) {
|
539
548
|
if (this.textAlign === 'center') {
|
@@ -547,9 +556,9 @@
|
|
547
556
|
|
548
557
|
/**
|
549
558
|
* @private
|
550
|
-
* @
|
551
|
-
* @param
|
552
|
-
* @
|
559
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
560
|
+
* @param {String} line Text line
|
561
|
+
* @return {Number} Line width
|
553
562
|
*/
|
554
563
|
_getLineWidth: function(ctx, line) {
|
555
564
|
return this.textAlign === 'justify'
|
@@ -559,11 +568,13 @@
|
|
559
568
|
|
560
569
|
/**
|
561
570
|
* @private
|
562
|
-
* @
|
571
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
572
|
+
* @param {Array} textLines Array of all text lines
|
563
573
|
*/
|
564
574
|
_renderTextDecoration: function(ctx, textLines) {
|
575
|
+
if (!this.textDecoration) return;
|
565
576
|
|
566
|
-
var halfOfVerticalBox = this._getTextHeight(ctx, textLines) / 2;
|
577
|
+
var halfOfVerticalBox = this.originY === 'top' ? 0 : this._getTextHeight(ctx, textLines) / 2;
|
567
578
|
var _this = this;
|
568
579
|
|
569
580
|
/** @ignore */
|
@@ -574,7 +585,7 @@
|
|
574
585
|
var lineLeftOffset = _this._getLineLeftOffset(lineWidth);
|
575
586
|
|
576
587
|
ctx.fillRect(
|
577
|
-
|
588
|
+
_this._getLeftOffset() + lineLeftOffset,
|
578
589
|
(offset + (i * _this.fontSize * _this.lineHeight)) - halfOfVerticalBox,
|
579
590
|
lineWidth,
|
580
591
|
1);
|
@@ -594,7 +605,6 @@
|
|
594
605
|
|
595
606
|
/**
|
596
607
|
* @private
|
597
|
-
* @method _getFontDeclaration
|
598
608
|
*/
|
599
609
|
_getFontDeclaration: function() {
|
600
610
|
return [
|
@@ -606,39 +616,15 @@
|
|
606
616
|
].join(' ');
|
607
617
|
},
|
608
618
|
|
609
|
-
/**
|
610
|
-
* @private
|
611
|
-
* @method _initDummyElement
|
612
|
-
*/
|
613
|
-
_initDummyElementForCufon: function() {
|
614
|
-
var el = fabric.document.createElement('pre'),
|
615
|
-
container = fabric.document.createElement('div');
|
616
|
-
|
617
|
-
// Cufon doesn't play nice with textDecoration=underline if element doesn't have a parent
|
618
|
-
container.appendChild(el);
|
619
|
-
|
620
|
-
if (typeof G_vmlCanvasManager === 'undefined') {
|
621
|
-
el.innerHTML = this.text;
|
622
|
-
}
|
623
|
-
else {
|
624
|
-
// IE 7 & 8 drop newlines and white space on text nodes
|
625
|
-
// see: http://web.student.tuwien.ac.at/~e0226430/innerHtmlQuirk.html
|
626
|
-
// see: http://www.w3schools.com/dom/dom_mozilla_vs_ie.asp
|
627
|
-
el.innerText = this.text.replace(/\r?\n/gi, '\r');
|
628
|
-
}
|
629
|
-
|
630
|
-
el.style.fontSize = this.fontSize + 'px';
|
631
|
-
el.style.letterSpacing = 'normal';
|
632
|
-
|
633
|
-
return el;
|
634
|
-
},
|
635
|
-
|
636
619
|
/**
|
637
620
|
* Renders text instance on a specified context
|
638
|
-
* @
|
639
|
-
* @param
|
621
|
+
* @param {CanvasRenderingContext2D} ctx Context to render on
|
622
|
+
* @param {Boolean} [noTransform] When true, context is not transformed
|
640
623
|
*/
|
641
624
|
render: function(ctx, noTransform) {
|
625
|
+
// do not render if object is not visible
|
626
|
+
if (!this.visible) return;
|
627
|
+
|
642
628
|
ctx.save();
|
643
629
|
this._render(ctx);
|
644
630
|
if (!noTransform && this.active) {
|
@@ -650,9 +636,8 @@
|
|
650
636
|
|
651
637
|
/**
|
652
638
|
* Returns object representation of an instance
|
653
|
-
* @
|
654
|
-
* @
|
655
|
-
* @return {Object} object representation of an instance
|
639
|
+
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
|
640
|
+
* @return {Object} Object representation of an instance
|
656
641
|
*/
|
657
642
|
toObject: function(propertiesToInclude) {
|
658
643
|
return extend(this.callSuper('toObject', propertiesToInclude), {
|
@@ -666,17 +651,15 @@
|
|
666
651
|
textShadow: this.textShadow,
|
667
652
|
textAlign: this.textAlign,
|
668
653
|
path: this.path,
|
669
|
-
strokeStyle: this.strokeStyle,
|
670
|
-
strokeWidth: this.strokeWidth,
|
671
654
|
backgroundColor: this.backgroundColor,
|
672
655
|
textBackgroundColor: this.textBackgroundColor,
|
673
656
|
useNative: this.useNative
|
674
657
|
});
|
675
658
|
},
|
676
659
|
|
660
|
+
/* _TO_SVG_START_ */
|
677
661
|
/**
|
678
662
|
* Returns SVG representation of an instance
|
679
|
-
* @method toSVG
|
680
663
|
* @return {String} svg representation of an instance
|
681
664
|
*/
|
682
665
|
toSVG: function() {
|
@@ -718,7 +701,9 @@
|
|
718
701
|
|
719
702
|
/**
|
720
703
|
* @private
|
721
|
-
* @
|
704
|
+
* @param {Number} lineTopOffset Line top offset
|
705
|
+
* @param {Array} textLines Array of all text lines
|
706
|
+
* @return {Array}
|
722
707
|
*/
|
723
708
|
_getSVGShadows: function(lineTopOffset, textLines) {
|
724
709
|
var shadowSpans = [], j, i, jlen, ilen, lineTopOffsetMultiplier = 1;
|
@@ -755,7 +740,10 @@
|
|
755
740
|
|
756
741
|
/**
|
757
742
|
* @private
|
758
|
-
* @
|
743
|
+
* @param {Number} lineTopOffset Line top offset
|
744
|
+
* @param {Number} textLeftOffset Text left offset
|
745
|
+
* @param {Array} textLines Array of all text lines
|
746
|
+
* @return {Object}
|
759
747
|
*/
|
760
748
|
_getSVGTextAndBg: function(lineTopOffset, textLeftOffset, textLines) {
|
761
749
|
var textSpans = [ ], textBgRects = [ ], i, lineLeftOffset, len, lineTopOffsetMultiplier = 1;
|
@@ -825,19 +813,20 @@
|
|
825
813
|
* we work around it by "moving" alpha channel into opacity attribute and setting fill's alpha to 1
|
826
814
|
*
|
827
815
|
* @private
|
828
|
-
* @
|
816
|
+
* @param {Any} value
|
817
|
+
* @return {String}
|
829
818
|
*/
|
830
819
|
_getFillAttributes: function(value) {
|
831
|
-
var fillColor = value ? new fabric.Color(value) : '';
|
820
|
+
var fillColor = (value && typeof value === 'string') ? new fabric.Color(value) : '';
|
832
821
|
if (!fillColor || !fillColor.getSource() || fillColor.getAlpha() === 1) {
|
833
822
|
return 'fill="' + value + '"';
|
834
823
|
}
|
835
824
|
return 'opacity="' + fillColor.getAlpha() + '" fill="' + fillColor.setAlpha(1).toRgb() + '"';
|
836
825
|
},
|
826
|
+
/* _TO_SVG_END_ */
|
837
827
|
|
838
828
|
/**
|
839
829
|
* Sets "color" of an instance (alias of `set('fill', …)`)
|
840
|
-
* @method setColor
|
841
830
|
* @param {String} value
|
842
831
|
* @return {fabric.Text} thisArg
|
843
832
|
* @chainable
|
@@ -849,7 +838,6 @@
|
|
849
838
|
|
850
839
|
/**
|
851
840
|
* Returns actual text value of an instance
|
852
|
-
* @method getText
|
853
841
|
* @return {String}
|
854
842
|
*/
|
855
843
|
getText: function() {
|
@@ -858,7 +846,6 @@
|
|
858
846
|
|
859
847
|
/**
|
860
848
|
* Sets specified property to a specified value
|
861
|
-
* @method set
|
862
849
|
* @param {String} name
|
863
850
|
* @param {Any} value
|
864
851
|
* @return {fabric.Text} thisArg
|
@@ -870,39 +857,35 @@
|
|
870
857
|
}
|
871
858
|
this.callSuper('_set', name, value);
|
872
859
|
|
873
|
-
if (name in
|
860
|
+
if (name in this._dimensionAffectingProps) {
|
874
861
|
this._initDimensions();
|
875
862
|
this.setCoords();
|
876
863
|
}
|
864
|
+
},
|
865
|
+
|
866
|
+
/**
|
867
|
+
* Returns complexity of an instance
|
868
|
+
* @return {Number} complexity
|
869
|
+
*/
|
870
|
+
complexity: function() {
|
871
|
+
return 1;
|
877
872
|
}
|
878
873
|
});
|
879
874
|
|
875
|
+
/* _FROM_SVG_START_ */
|
880
876
|
/**
|
881
877
|
* List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})
|
882
878
|
* @static
|
883
879
|
*/
|
884
|
-
fabric.Text.ATTRIBUTE_NAMES =
|
885
|
-
|
886
|
-
'font-family font-style font-weight font-size text-decoration').split(' ');
|
887
|
-
|
888
|
-
/**
|
889
|
-
* Returns fabric.Text instance from an object representation
|
890
|
-
* @static
|
891
|
-
* @method fromObject
|
892
|
-
* @param {Object} object to create an instance from
|
893
|
-
* @return {fabric.Text} an instance
|
894
|
-
*/
|
895
|
-
fabric.Text.fromObject = function(object) {
|
896
|
-
return new fabric.Text(object.text, clone(object));
|
897
|
-
};
|
880
|
+
fabric.Text.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat(
|
881
|
+
'x y font-family font-style font-weight font-size text-decoration'.split(' '));
|
898
882
|
|
899
883
|
/**
|
900
884
|
* Returns fabric.Text instance from an SVG element (<b>not yet implemented</b>)
|
901
885
|
* @static
|
902
|
-
* @
|
903
|
-
* @param
|
904
|
-
* @
|
905
|
-
* @return {fabric.Text} an instance
|
886
|
+
* @param {SVGElement} element Element to parse
|
887
|
+
* @param {Object} [options] Options object
|
888
|
+
* @return {fabric.Text} Instance of fabric.Text
|
906
889
|
*/
|
907
890
|
fabric.Text.fromElement = function(element, options) {
|
908
891
|
|
@@ -928,7 +911,18 @@
|
|
928
911
|
|
929
912
|
return text;
|
930
913
|
};
|
914
|
+
/* _FROM_SVG_END_ */
|
915
|
+
|
916
|
+
/**
|
917
|
+
* Returns fabric.Text instance from an object representation
|
918
|
+
* @static
|
919
|
+
* @param object {Object} object Object to create an instance from
|
920
|
+
* @return {fabric.Text} Instance of fabric.Text
|
921
|
+
*/
|
922
|
+
fabric.Text.fromObject = function(object) {
|
923
|
+
return new fabric.Text(object.text, clone(object));
|
924
|
+
};
|
931
925
|
|
932
926
|
fabric.util.createAccessors(fabric.Text);
|
933
927
|
|
934
|
-
})(typeof exports !== 'undefined' ? exports : this);
|
928
|
+
})(typeof exports !== 'undefined' ? exports : this);
|