mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-04-28 17:24:42 +00:00
Better strokeDashArray support + Fixes
- fabric.Text has now strokeDashArray support (only native support) - fabric.Text.fill = null should now work - Fix save/restore context in render methods => setLineDash affected drawBorder/drawControls - Add strokeLineCap (default "butt"), strokeLineJoin (default "miter") and strokeMiterLimit (default 10) - Add support for fabric.Object#fromElement for strokeDashArray (and other stroke properties) - Add @default tag to properties (JSDoc 3) - strokeDashArray now only works if stroke property is defined - Add trokeLineCap (default "round"), strokeLineJoin (default "round") to fabric.BaseBrush - Updated unit tests
This commit is contained in:
parent
4491b24a75
commit
d80fec5df1
30 changed files with 781 additions and 462 deletions
|
|
@ -7,38 +7,58 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|||
/**
|
||||
* Color of a brush
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
color: 'rgb(0, 0, 0)',
|
||||
color: 'rgb(0, 0, 0)',
|
||||
|
||||
/**
|
||||
* Width of a brush
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
width: 1,
|
||||
width: 1,
|
||||
|
||||
/**
|
||||
* Shadow blur of a brush
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
shadowBlur: 0,
|
||||
shadowBlur: 0,
|
||||
|
||||
/**
|
||||
* Shadow color of a brush
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
shadowColor: '',
|
||||
shadowColor: '',
|
||||
|
||||
/**
|
||||
* Shadow offset x of a brush
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetX: 0,
|
||||
|
||||
/**
|
||||
* Shadow offset y of a brush
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
shadowOffsetY: 0,
|
||||
shadowOffsetY: 0,
|
||||
|
||||
/**
|
||||
* Line endings style of a brush (one of "butt", "round", "square")
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
strokeLineCap: 'round',
|
||||
|
||||
/**
|
||||
* Corner style of a brush (one of "bevil", "round", "miter")
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
strokeLineJoin: 'round',
|
||||
|
||||
/**
|
||||
* Sets brush styles
|
||||
|
|
@ -48,7 +68,8 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|||
|
||||
ctx.strokeStyle = this.color;
|
||||
ctx.lineWidth = this.width;
|
||||
ctx.lineCap = ctx.lineJoin = 'round';
|
||||
ctx.lineCap = this.strokeLineCap;
|
||||
ctx.lineJoin = this.strokeLineJoin;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'circle',
|
||||
|
||||
|
|
@ -132,7 +133,10 @@
|
|||
* @static
|
||||
* @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement
|
||||
*/
|
||||
fabric.Circle.ATTRIBUTE_NAMES = 'cx cy r fill fill-opacity opacity stroke stroke-width transform'.split(' ');
|
||||
fabric.Circle.ATTRIBUTE_NAMES = (
|
||||
'cx cy r fill fill-opacity opacity stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Returns {@link fabric.Circle} instance from an SVG element
|
||||
|
|
|
|||
|
|
@ -22,20 +22,23 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'ellipse',
|
||||
|
||||
/**
|
||||
* Horizontal radius
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
rx: 0,
|
||||
rx: 0,
|
||||
|
||||
/**
|
||||
* Vertical radius
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
ry: 0,
|
||||
ry: 0,
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
|
@ -138,7 +141,10 @@
|
|||
* @static
|
||||
* @see http://www.w3.org/TR/SVG/shapes.html#EllipseElement
|
||||
*/
|
||||
fabric.Ellipse.ATTRIBUTE_NAMES = 'cx cy rx ry fill fill-opacity opacity stroke stroke-width transform'.split(' ');
|
||||
fabric.Ellipse.ATTRIBUTE_NAMES = (
|
||||
'cx cy rx ry fill fill-opacity opacity stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Returns {@link fabric.Ellipse} instance from an SVG element
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'group',
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'image',
|
||||
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
this.transform(ctx);
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
this._setShadow(ctx);
|
||||
this.clipTo && fabric.util.clipContext(this, ctx);
|
||||
this._render(ctx);
|
||||
|
|
@ -112,6 +114,7 @@
|
|||
}
|
||||
this._renderStroke(ctx);
|
||||
this.clipTo && ctx.restore();
|
||||
ctx.restore();
|
||||
|
||||
if (this.active && !noTransform) {
|
||||
this.drawBorders(ctx);
|
||||
|
|
@ -127,7 +130,12 @@
|
|||
_stroke: function(ctx) {
|
||||
ctx.save();
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
ctx.strokeStyle = this.stroke;
|
||||
ctx.lineCap = this.strokeLineCap;
|
||||
ctx.lineJoin = this.strokeLineJoin;
|
||||
ctx.miterLimit = this.strokeMiterLimit;
|
||||
ctx.strokeStyle = this.stroke.toLive
|
||||
? this.stroke.toLive(ctx)
|
||||
: this.stroke;
|
||||
ctx.beginPath();
|
||||
ctx.strokeRect(-this.width / 2, -this.height / 2, this.width, this.height);
|
||||
ctx.beginPath();
|
||||
|
|
@ -145,7 +153,12 @@
|
|||
h = this.height;
|
||||
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
ctx.strokeStyle = this.stroke;
|
||||
ctx.lineCap = this.strokeLineCap;
|
||||
ctx.lineJoin = this.strokeLineJoin;
|
||||
ctx.miterLimit = this.strokeMiterLimit;
|
||||
ctx.strokeStyle = this.stroke.toLive
|
||||
? this.stroke.toLive(ctx)
|
||||
: this.stroke;
|
||||
ctx.beginPath();
|
||||
fabric.util.drawDashedLine(ctx, x, y, x+w, y, this.strokeDashArray);
|
||||
fabric.util.drawDashedLine(ctx, x+w, y, x+w, y+h, this.strokeDashArray);
|
||||
|
|
@ -434,7 +447,7 @@
|
|||
* @static
|
||||
* @see http://www.w3.org/TR/SVG/struct.html#ImageElement
|
||||
*/
|
||||
fabric.Image.ATTRIBUTE_NAMES = 'x y width height fill fill-opacity opacity stroke stroke-width transform xlink:href'.split(' ');
|
||||
fabric.Image.ATTRIBUTE_NAMES = 'x y width height fill fill-opacity opacity transform xlink:href'.split(' ');
|
||||
|
||||
/**
|
||||
* Returns {@link fabric.Image} instance from an SVG element
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'line',
|
||||
|
||||
|
|
@ -175,7 +176,10 @@
|
|||
* @static
|
||||
* @see http://www.w3.org/TR/SVG/shapes.html#LineElement
|
||||
*/
|
||||
fabric.Line.ATTRIBUTE_NAMES = 'x1 y1 x2 y2 stroke stroke-width transform'.split(' ');
|
||||
fabric.Line.ATTRIBUTE_NAMES = (
|
||||
'x1 y1 x2 y2 stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Returns fabric.Line instance from an SVG element
|
||||
|
|
|
|||
|
|
@ -22,147 +22,191 @@
|
|||
/**
|
||||
* Type of an object (rect, circle, path, etc.)
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'object',
|
||||
|
||||
/**
|
||||
* Horizontal origin of transformation of an object (one of "left", "right", "center")
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
originX: 'center',
|
||||
|
||||
/**
|
||||
* Vertical origin of transformation of an object (one of "top", "bottom", "center")
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
originY: 'center',
|
||||
|
||||
/**
|
||||
* Top position of an object. Note that by default it's relative to object center. You can change this by setting originY={top/center/bottom}
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
top: 0,
|
||||
|
||||
/**
|
||||
* Left position of an object. Note that by default it's relative to object center. You can change this by setting originX={left/center/right}
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
left: 0,
|
||||
|
||||
/**
|
||||
* Object width
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
width: 0,
|
||||
|
||||
/**
|
||||
* Object height
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
height: 0,
|
||||
|
||||
/**
|
||||
* Object scale factor (horizontal)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
scaleX: 1,
|
||||
|
||||
/**
|
||||
* Object scale factor (vertical)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
scaleY: 1,
|
||||
|
||||
/**
|
||||
* When true, an object is rendered as flipped horizontally
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
flipX: false,
|
||||
|
||||
/**
|
||||
* When true, an object is rendered as flipped vertically
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
flipY: false,
|
||||
|
||||
/**
|
||||
* Opacity of an object
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
opacity: 1,
|
||||
|
||||
/**
|
||||
* Angle of rotation of an object (in degrees)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
angle: 0,
|
||||
|
||||
/**
|
||||
* Size of object's corners (in pixels)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
cornerSize: 12,
|
||||
|
||||
/**
|
||||
* When true, object's corners are rendered as transparent inside (i.e. stroke instead of fill)
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
transparentCorners: true,
|
||||
|
||||
/**
|
||||
* Padding between object and its borders (in pixels)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
padding: 0,
|
||||
|
||||
/**
|
||||
* Border color of an object (when it's active)
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
borderColor: 'rgba(102,153,255,0.75)',
|
||||
|
||||
/**
|
||||
* Corner color of an object (when it's active)
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
cornerColor: 'rgba(102,153,255,0.5)',
|
||||
|
||||
/**
|
||||
* Color of object's fill
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
fill: 'rgb(0,0,0)',
|
||||
|
||||
/**
|
||||
* Fill rule used to fill an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
fillRule: 'source-over',
|
||||
|
||||
/**
|
||||
* Overlay fill (takes precedence over fill value)
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
overlayFill: null,
|
||||
|
||||
/**
|
||||
* When `true`, an object is rendered via stroke and this property specifies its color
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
stroke: null,
|
||||
|
||||
/**
|
||||
* Width of a stroke used to render this object
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
strokeWidth: 1,
|
||||
|
||||
/**
|
||||
* Array specifying dash pattern of an object's stroke
|
||||
* Array specifying dash pattern of an object's stroke (stroke must be defined)
|
||||
* @type Array
|
||||
*/
|
||||
strokeDashArray: null,
|
||||
|
||||
/**
|
||||
* Line endings style of an object's stroke (one of "butt", "round", "square")
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
strokeLineCap: 'butt',
|
||||
|
||||
/**
|
||||
* Corner style of an object's stroke (one of "bevil", "round", "miter")
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
strokeLineJoin: 'miter',
|
||||
|
||||
/**
|
||||
* Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
strokeMiterLimit: 10,
|
||||
|
||||
/**
|
||||
* Shadow object representing shadow of this shape
|
||||
* @type fabric.Shadow
|
||||
|
|
@ -172,12 +216,14 @@
|
|||
/**
|
||||
* Border opacity when object is active and moving
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
borderOpacityWhenMoving: 0.4,
|
||||
|
||||
/**
|
||||
* Border scale factor
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
borderScaleFactor: 1,
|
||||
|
||||
|
|
@ -190,54 +236,63 @@
|
|||
/**
|
||||
* Minimum allowed scale value of an object
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
minScaleLimit: 0.01,
|
||||
|
||||
/**
|
||||
* When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection)
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
selectable: true,
|
||||
|
||||
/**
|
||||
* When set to `false`, an object is not rendered on canvas
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
visible: true,
|
||||
|
||||
/**
|
||||
* When set to `false`, object's controls are not displayed and can not be used to manipulate object
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
hasControls: true,
|
||||
|
||||
/**
|
||||
* When set to `false`, object's borders are not rendered
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
hasBorders: true,
|
||||
|
||||
/**
|
||||
* When set to `false`, object's rotating point will not be visible or selectable
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
hasRotatingPoint: true,
|
||||
|
||||
/**
|
||||
* Offset for object's rotating point (when enabled via `hasRotatingPoint`)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
rotatingPointOffset: 40,
|
||||
|
||||
/**
|
||||
* When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
perPixelTargetFind: false,
|
||||
|
||||
/**
|
||||
* When `false`, default object's values are not included in its serialization
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
includeDefaultValues: true,
|
||||
|
||||
|
|
@ -250,38 +305,44 @@
|
|||
/**
|
||||
* When `true`, object horizontal movement is locked
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
lockMovementX: false,
|
||||
lockMovementX: false,
|
||||
|
||||
/**
|
||||
* When `true`, object vertical movement is locked
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
lockMovementY: false,
|
||||
lockMovementY: false,
|
||||
|
||||
/**
|
||||
* When `true`, object rotation is locked
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
lockRotation: false,
|
||||
lockRotation: false,
|
||||
|
||||
/**
|
||||
* When `true`, object horizontal scaling is locked
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
lockScalingX: false,
|
||||
lockScalingX: false,
|
||||
|
||||
/**
|
||||
* When `true`, object vertical scaling is locked
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
lockScalingY: false,
|
||||
lockScalingY: false,
|
||||
|
||||
/**
|
||||
* When `true`, object non-uniform scaling is locked
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
lockUniScaling: false,
|
||||
lockUniScaling: false,
|
||||
|
||||
/**
|
||||
* List of properties to consider when checking if state
|
||||
|
|
@ -386,8 +447,11 @@
|
|||
fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,
|
||||
overlayFill: this.overlayFill,
|
||||
stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,
|
||||
strokeWidth: this.strokeWidth,
|
||||
strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),
|
||||
strokeDashArray: this.strokeDashArray,
|
||||
strokeLineCap: this.strokeLineCap,
|
||||
strokeLineJoin: this.strokeLineJoin,
|
||||
strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),
|
||||
scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),
|
||||
scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),
|
||||
angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS),
|
||||
|
|
@ -431,6 +495,9 @@
|
|||
"stroke: ", (this.stroke ? this.stroke : 'none'), "; ",
|
||||
"stroke-width: ", (this.strokeWidth ? this.strokeWidth : '0'), "; ",
|
||||
"stroke-dasharray: ", (this.strokeDashArray ? this.strokeDashArray.join(' ') : ''), "; ",
|
||||
"stroke-linecap: ", (this.strokeLineCap ? this.strokeLineCap : 'butt'), "; ",
|
||||
"stroke-linejoin: ", (this.strokeLineJoin ? this.strokeLineJoin : 'miter'), "; ",
|
||||
"stroke-miterlimit: ", (this.strokeMiterLimit ? this.strokeMiterLimit : '4'), "; ",
|
||||
"fill: ", (this.fill ? (this.fill && this.fill.toLive ? 'url(#SVGID_' + this.fill.id + ')' : this.fill) : 'none'), "; ",
|
||||
"opacity: ", (typeof this.opacity !== 'undefined' ? this.opacity : '1'), ";",
|
||||
(this.visible ? '' : " visibility: hidden;")
|
||||
|
|
@ -600,14 +667,15 @@
|
|||
this.transform(ctx);
|
||||
}
|
||||
|
||||
if (this.stroke || this.strokeDashArray) {
|
||||
ctx.save();
|
||||
if (this.stroke) {
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
if (this.stroke && this.stroke.toLive) {
|
||||
ctx.strokeStyle = this.stroke.toLive(ctx);
|
||||
}
|
||||
else {
|
||||
ctx.strokeStyle = this.stroke;
|
||||
}
|
||||
ctx.lineCap = this.strokeLineCap;
|
||||
ctx.lineJoin = this.strokeLineJoin;
|
||||
ctx.miterLimit = this.strokeMiterLimit;
|
||||
ctx.strokeStyle = this.stroke.toLive
|
||||
? this.stroke.toLive(ctx)
|
||||
: this.stroke;
|
||||
}
|
||||
|
||||
if (this.overlayFill) {
|
||||
|
|
@ -629,6 +697,7 @@
|
|||
this._render(ctx, noTransform);
|
||||
this.clipTo && ctx.restore();
|
||||
this._removeShadow(ctx);
|
||||
ctx.restore();
|
||||
|
||||
if (this.active && !noTransform) {
|
||||
this.drawBorders(ctx);
|
||||
|
|
@ -686,7 +755,7 @@
|
|||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_renderStroke: function(ctx) {
|
||||
if (!this.stroke && !this.strokeDashArray) return;
|
||||
if (!this.stroke) return;
|
||||
|
||||
if (this.strokeDashArray) {
|
||||
// Spec requires the concatenation of two copies the dash list when the number of elements is odd
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
'fill-opacity': 'opacity',
|
||||
'fill-rule': 'fillRule',
|
||||
'stroke-width': 'strokeWidth',
|
||||
'stroke-dasharray': 'strokeDashArray',
|
||||
'stroke-linecap': 'strokeLineCap',
|
||||
'stroke-linejoin': 'strokeLineJoin',
|
||||
'stroke-miterlimit':'strokeMiterLimit',
|
||||
'transform': 'transformMatrix',
|
||||
'text-decoration': 'textDecoration',
|
||||
'font-size': 'fontSize',
|
||||
|
|
@ -39,20 +43,31 @@
|
|||
}
|
||||
|
||||
function normalizeValue(attr, value, parentAttributes) {
|
||||
var isArray;
|
||||
|
||||
if ((attr === 'fill' || attr === 'stroke') && value === 'none') {
|
||||
return '';
|
||||
value = '';
|
||||
}
|
||||
if (attr === 'fill-rule') {
|
||||
return (value === 'evenodd') ? 'destination-over' : value;
|
||||
else if (attr === 'fillRule') {
|
||||
value = (value === 'evenodd') ? 'destination-over' : value;
|
||||
}
|
||||
if (attr === 'transform') {
|
||||
else if (attr === 'strokeDashArray') {
|
||||
value = value.replace(/,/g, ' ').split(/\s+/);
|
||||
}
|
||||
else if (attr === 'transformMatrix') {
|
||||
if (parentAttributes && parentAttributes.transformMatrix) {
|
||||
return multiplyTransformMatrices(
|
||||
value = multiplyTransformMatrices(
|
||||
parentAttributes.transformMatrix, fabric.parseTransformAttribute(value));
|
||||
}
|
||||
return fabric.parseTransformAttribute(value);
|
||||
value = fabric.parseTransformAttribute(value);
|
||||
}
|
||||
return value;
|
||||
|
||||
isArray = Object.prototype.toString.call(value) === '[object Array]';
|
||||
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = isArray ? value.map(parseFloat) : parseFloat(value);
|
||||
|
||||
return (!isArray && isNaN(parsed) ? value : parsed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,7 +86,6 @@
|
|||
}
|
||||
|
||||
var value,
|
||||
parsed,
|
||||
parentAttributes = { };
|
||||
|
||||
// if there's a parent container (`g` node), parse its attributes recursively upwards
|
||||
|
|
@ -81,12 +95,11 @@
|
|||
|
||||
var ownAttributes = attributes.reduce(function(memo, attr) {
|
||||
value = element.getAttribute(attr);
|
||||
parsed = parseFloat(value);
|
||||
if (value) {
|
||||
value = normalizeValue(attr, value, parentAttributes);
|
||||
attr = normalizeAttr(attr);
|
||||
value = normalizeValue(attr, value, parentAttributes);
|
||||
|
||||
memo[attr] = isNaN(parsed) ? value : parsed;
|
||||
memo[attr] = value;
|
||||
}
|
||||
return memo;
|
||||
}, { });
|
||||
|
|
@ -324,24 +337,23 @@
|
|||
*/
|
||||
function parseStyleAttribute(element) {
|
||||
var oStyle = { },
|
||||
style = element.getAttribute('style');
|
||||
style = element.getAttribute('style'),
|
||||
attr, value;
|
||||
|
||||
if (!style) return oStyle;
|
||||
|
||||
if (typeof style === 'string') {
|
||||
style.replace(/;$/, '').split(';').forEach(function (chunk) {
|
||||
|
||||
var pair = chunk.split(':');
|
||||
var attr = normalizeAttr(pair[0].trim().toLowerCase());
|
||||
var value = normalizeValue(attr, pair[1].trim());
|
||||
|
||||
attr = normalizeAttr(pair[0].trim().toLowerCase());
|
||||
value = normalizeValue(attr, pair[1].trim());
|
||||
|
||||
if (attr === 'font') {
|
||||
parseFontDeclaration(value, oStyle);
|
||||
}
|
||||
else {
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
oStyle[attr] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -349,16 +361,14 @@
|
|||
for (var prop in style) {
|
||||
if (typeof style[prop] === 'undefined') continue;
|
||||
|
||||
var attr = normalizeAttr(prop.toLowerCase());
|
||||
var value = normalizeValue(attr, style[prop]);
|
||||
attr = normalizeAttr(prop.toLowerCase());
|
||||
value = normalizeValue(attr, style[prop]);
|
||||
|
||||
if (attr === 'font') {
|
||||
parseFontDeclaration(value, oStyle);
|
||||
}
|
||||
else {
|
||||
// TODO: need to normalize em, %, pt, etc. to px (!)
|
||||
var parsed = parseFloat(value);
|
||||
oStyle[attr] = isNaN(parsed) ? value : parsed;
|
||||
oStyle[attr] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'path',
|
||||
|
||||
|
|
@ -539,6 +540,7 @@
|
|||
}
|
||||
// ctx.globalCompositeOperation = this.fillRule;
|
||||
|
||||
ctx.save();
|
||||
if (this.overlayFill) {
|
||||
ctx.fillStyle = this.overlayFill;
|
||||
}
|
||||
|
|
@ -549,27 +551,25 @@
|
|||
}
|
||||
|
||||
if (this.stroke) {
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
ctx.lineCap = this.strokeLineCap;
|
||||
ctx.lineJoin = this.strokeLineJoin;
|
||||
ctx.miterLimit = this.strokeMiterLimit;
|
||||
ctx.strokeStyle = this.stroke.toLive
|
||||
? this.stroke.toLive(ctx)
|
||||
: this.stroke;
|
||||
}
|
||||
|
||||
this._setShadow(ctx);
|
||||
this.clipTo && fabric.util.clipContext(this, ctx);
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
this._render(ctx);
|
||||
this._renderFill(ctx);
|
||||
|
||||
if (this.stroke) {
|
||||
ctx.strokeStyle = this.stroke;
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
ctx.lineCap = ctx.lineJoin = 'round';
|
||||
this._renderStroke(ctx);
|
||||
}
|
||||
this._renderStroke(ctx);
|
||||
this.clipTo && ctx.restore();
|
||||
|
||||
this._removeShadow(ctx);
|
||||
ctx.restore();
|
||||
|
||||
if (!noTransform && this.active) {
|
||||
this.drawBorders(ctx);
|
||||
|
|
@ -796,7 +796,10 @@
|
|||
* @static
|
||||
* @see http://www.w3.org/TR/SVG/paths.html#PathElement
|
||||
*/
|
||||
fabric.Path.ATTRIBUTE_NAMES = 'd fill fill-opacity opacity fill-rule stroke stroke-width transform'.split(' ');
|
||||
fabric.Path.ATTRIBUTE_NAMES = (
|
||||
'd fill fill-opacity opacity fill-rule stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Creates an instance of fabric.Path from an SVG <path> element
|
||||
|
|
|
|||
|
|
@ -24,12 +24,14 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'path-group',
|
||||
|
||||
/**
|
||||
* Fill value
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
fill: '',
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,8 @@
|
|||
path.fill = null;
|
||||
path.stroke = this.color;
|
||||
path.strokeWidth = this.width;
|
||||
path.strokeLineCap = this.strokeLineCap;
|
||||
path.strokeLineJoin = this.strokeLineJoin;
|
||||
path.setShadow({
|
||||
color: this.shadowColor || this.color,
|
||||
blur: this.shadowBlur,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'polygon',
|
||||
|
||||
|
|
@ -161,7 +162,10 @@
|
|||
* @static
|
||||
* @see: http://www.w3.org/TR/SVG/shapes.html#PolygonElement
|
||||
*/
|
||||
fabric.Polygon.ATTRIBUTE_NAMES = 'fill fill-opacity opacity stroke stroke-width transform'.split(' ');
|
||||
fabric.Polygon.ATTRIBUTE_NAMES = (
|
||||
'fill fill-opacity opacity stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Returns {@link fabric.Polygon} instance from an SVG element
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'polyline',
|
||||
|
||||
|
|
@ -132,7 +133,10 @@
|
|||
* @static
|
||||
* @see: http://www.w3.org/TR/SVG/shapes.html#PolylineElement
|
||||
*/
|
||||
fabric.Polyline.ATTRIBUTE_NAMES = 'fill fill-opacity opacity stroke stroke-width transform'.split(' ');
|
||||
fabric.Polyline.ATTRIBUTE_NAMES = (
|
||||
'fill fill-opacity opacity stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Returns fabric.Polyline instance from an SVG element
|
||||
|
|
|
|||
|
|
@ -21,20 +21,23 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'rect',
|
||||
|
||||
/**
|
||||
* Horizontal border radius
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
rx: 0,
|
||||
rx: 0,
|
||||
|
||||
/**
|
||||
* Vertical border radius
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
ry: 0,
|
||||
ry: 0,
|
||||
|
||||
/**
|
||||
* Used to specify dash pattern for stroke on this object
|
||||
|
|
@ -210,7 +213,10 @@
|
|||
* List of attribute names to account for when parsing SVG element (used by `fabric.Rect.fromElement`)
|
||||
* @static
|
||||
*/
|
||||
fabric.Rect.ATTRIBUTE_NAMES = 'x y width height rx ry fill fill-opacity opacity stroke stroke-width transform'.split(' ');
|
||||
fabric.Rect.ATTRIBUTE_NAMES = (
|
||||
'x y width height rx ry fill fill-opacity opacity stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
var fabric = global.fabric || (global.fabric = { }),
|
||||
extend = fabric.util.object.extend,
|
||||
clone = fabric.util.object.clone,
|
||||
toFixed = fabric.util.toFixed;
|
||||
toFixed = fabric.util.toFixed,
|
||||
supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
|
||||
|
||||
if (fabric.Text) {
|
||||
fabric.warn('fabric.Text is already defined');
|
||||
|
|
@ -54,90 +55,105 @@
|
|||
/**
|
||||
* Font size (in pixels)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
fontSize: 40,
|
||||
|
||||
/**
|
||||
* Font weight (e.g. bold, normal, 400, 600, 800)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
fontWeight: 'normal',
|
||||
|
||||
/**
|
||||
* Font family
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
fontFamily: 'Times New Roman',
|
||||
|
||||
/**
|
||||
* Text decoration (e.g. underline, overline)
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
textDecoration: '',
|
||||
|
||||
/**
|
||||
* Text shadow
|
||||
* @type String | null
|
||||
* @default
|
||||
*/
|
||||
textShadow: '',
|
||||
|
||||
/**
|
||||
* Text alignment. Possible values: "left", "center", or "right".
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
textAlign: 'left',
|
||||
|
||||
/**
|
||||
* Font style (e.g. italic)
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
fontStyle: '',
|
||||
|
||||
/**
|
||||
* Line height
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
lineHeight: 1.3,
|
||||
|
||||
/**
|
||||
* Stroke style. When specified, text is rendered with stroke
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
stroke: '',
|
||||
|
||||
/**
|
||||
* Stroke width
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
strokeWidth: 1,
|
||||
|
||||
/**
|
||||
* Background color of an entire text box
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
backgroundColor: '',
|
||||
|
||||
/**
|
||||
* Background color of text lines
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
textBackgroundColor: '',
|
||||
|
||||
/**
|
||||
* URL of a font file, when using Cufon
|
||||
* @type String | null
|
||||
* @default
|
||||
*/
|
||||
path: null,
|
||||
|
||||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'text',
|
||||
|
||||
/**
|
||||
* Indicates whether canvas native text methods should be used to render text (otherwise, Cufon is used)
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
useNative: true,
|
||||
|
||||
|
|
@ -278,12 +294,14 @@
|
|||
ctx.translate(this.textAlign === 'center' ? (this.width / 2) : this.width, 0);
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
this._setTextShadow(ctx);
|
||||
this.clipTo && fabric.util.clipContext(this, ctx);
|
||||
this._renderTextFill(ctx, textLines);
|
||||
this._renderTextStroke(ctx, textLines);
|
||||
this.clipTo && ctx.restore();
|
||||
this.textShadow && ctx.restore();
|
||||
ctx.restore();
|
||||
|
||||
if (this.textAlign !== 'left' && this.textAlign !== 'justify') {
|
||||
ctx.restore();
|
||||
|
|
@ -319,11 +337,20 @@
|
|||
* @private
|
||||
*/
|
||||
_setTextStyles: function(ctx) {
|
||||
ctx.fillStyle = this.fill.toLive
|
||||
? this.fill.toLive(ctx)
|
||||
: this.fill;
|
||||
ctx.strokeStyle = this.stroke;
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
if (this.fill) {
|
||||
ctx.fillStyle = this.fill.toLive
|
||||
? this.fill.toLive(ctx)
|
||||
: this.fill;
|
||||
}
|
||||
if (this.stroke) {
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
ctx.lineCap = this.strokeLineCap;
|
||||
ctx.lineJoin = this.strokeLineJoin;
|
||||
ctx.miterLimit = this.strokeMiterLimit;
|
||||
ctx.strokeStyle = this.stroke.toLive
|
||||
? this.stroke.toLive(ctx)
|
||||
: this.stroke;
|
||||
}
|
||||
ctx.textBaseline = 'alphabetic';
|
||||
ctx.textAlign = this.textAlign;
|
||||
ctx.font = this._getFontDeclaration();
|
||||
|
|
@ -443,15 +470,17 @@
|
|||
* @private
|
||||
*/
|
||||
_renderTextFill: function(ctx, textLines) {
|
||||
this._boundaries = [ ];
|
||||
for (var i = 0, len = textLines.length; i < len; i++) {
|
||||
this._drawTextLine(
|
||||
'fillText',
|
||||
ctx,
|
||||
textLines[i],
|
||||
this._getLeftOffset(),
|
||||
this._getTopOffset() + (i * this.fontSize * this.lineHeight) + this.fontSize
|
||||
);
|
||||
if (this.fill) {
|
||||
this._boundaries = [ ];
|
||||
for (var i = 0, len = textLines.length; i < len; i++) {
|
||||
this._drawTextLine(
|
||||
'fillText',
|
||||
ctx,
|
||||
textLines[i],
|
||||
this._getLeftOffset(),
|
||||
this._getTopOffset() + (i * this.fontSize * this.lineHeight) + this.fontSize
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -460,6 +489,14 @@
|
|||
*/
|
||||
_renderTextStroke: function(ctx, textLines) {
|
||||
if (this.stroke) {
|
||||
if (this.strokeDashArray) {
|
||||
// Spec requires the concatenation of two copies the dash list when the number of elements is odd
|
||||
if (1 & this.strokeDashArray.length) {
|
||||
this.strokeDashArray.push.apply(this.strokeDashArray, this.strokeDashArray);
|
||||
}
|
||||
supportsLineDash && ctx.setLineDash(this.strokeDashArray);
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
for (var i = 0, len = textLines.length; i < len; i++) {
|
||||
this._drawTextLine(
|
||||
|
|
@ -870,9 +907,11 @@
|
|||
* List of attribute names to account for when parsing SVG element (used by {@link fabric.Text.fromElement})
|
||||
* @static
|
||||
*/
|
||||
fabric.Text.ATTRIBUTE_NAMES =
|
||||
('x y fill fill-opacity opacity stroke stroke-width transform ' +
|
||||
'font-family font-style font-weight font-size text-decoration').split(' ');
|
||||
fabric.Text.ATTRIBUTE_NAMES = (
|
||||
'x y fill fill-opacity opacity stroke stroke-width stroke-dasharray ' +
|
||||
'stroke-linejoin stroke-linecap stroke-miterlimit transform ' +
|
||||
'font-family font-style font-weight font-size text-decoration'
|
||||
).split(' ');
|
||||
|
||||
/**
|
||||
* Returns fabric.Text instance from an object representation
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
/**
|
||||
* Type of an object
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
type: 'triangle',
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@
|
|||
'13.99], ["z", null]]}], "background": "#ff5555"}';
|
||||
|
||||
var PATH_DATALESS_JSON = '{"objects":[{"type":"path","originX":"center","originY":"center","left":200,"top":200,"width":200,"height":200,"fill":"rgb(0,0,0)",'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,'+
|
||||
'"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,'+
|
||||
'"perPixelTargetFind":false,"shadow":null,"visible":true,"path":"http://example.com/"}],"background":""}';
|
||||
|
||||
var RECT_JSON = '{"objects":[{"type":"rect","originX":"center","originY":"center","left":0,"top":0,"width":10,"height":10,"fill":"rgb(0,0,0)","overlayFill":null,'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+
|
||||
'"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,'+
|
||||
'"visible":true,"rx":0,"ry":0}],"background":"#ff5555"}';
|
||||
|
||||
|
|
|
|||
|
|
@ -20,19 +20,19 @@
|
|||
'13.99], ["z", null]]}], "background": "#ff5555"}';
|
||||
|
||||
var PATH_DATALESS_JSON = '{"objects":[{"type":"path","originX":"center","originY":"center","left":200,"top":200,"width":200,"height":200,"fill":"rgb(0,0,0)",'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,'+
|
||||
'"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,'+
|
||||
'"perPixelTargetFind":false,"shadow":null,"visible":true,"path":"http://example.com/"}],"background":""}';
|
||||
|
||||
var RECT_JSON = '{"objects":[{"type":"rect","originX":"center","originY":"center","left":0,"top":0,"width":10,"height":10,"fill":"rgb(0,0,0)","overlayFill":null,'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,'+
|
||||
'"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,"visible":true,"rx":0,"ry":0}],'+
|
||||
'"background":"#ff5555"}';
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,'+
|
||||
'"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,"visible":true,"rx":0,"ry":0}],"background":"#ff5555"}';
|
||||
|
||||
var RECT_JSON_WITH_PADDING = '{"objects":[{"type":"rect","originX":"center","originY":"center","left":0,"top":0,"width":10,"height":20,"fill":"rgb(0,0,0)","overlayFill":null,'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,'+
|
||||
'"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,"visible":true,"padding":123,"foo":"bar","rx":0,"ry":0}],'+
|
||||
'"background":""}';
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,'+
|
||||
'"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,"visible":true,"padding":123,"foo":"bar","rx":0,"ry":0}],"background":""}';
|
||||
|
||||
// force creation of static canvas
|
||||
// TODO: fix this
|
||||
|
|
|
|||
|
|
@ -60,33 +60,36 @@
|
|||
test('toObject', function() {
|
||||
var circle = new fabric.Circle();
|
||||
var defaultProperties = {
|
||||
'type': 'circle',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'circle',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'radius': 0
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'radius': 0
|
||||
};
|
||||
ok(typeof circle.toObject == 'function');
|
||||
deepEqual(circle.toObject(), defaultProperties);
|
||||
|
|
@ -105,13 +108,17 @@
|
|||
test('fromElement', function() {
|
||||
ok(typeof fabric.Circle.fromElement == 'function');
|
||||
|
||||
var elCircle = fabric.document.createElement('circle'),
|
||||
radius = 10,
|
||||
left = 12,
|
||||
top = 15,
|
||||
fill = 'ff5555',
|
||||
fillOpacity = 0.5,
|
||||
strokeWidth = 2;
|
||||
var elCircle = fabric.document.createElement('circle'),
|
||||
radius = 10,
|
||||
left = 12,
|
||||
top = 15,
|
||||
fill = 'ff5555',
|
||||
fillOpacity = 0.5,
|
||||
strokeWidth = 2,
|
||||
strokeDashArray = [5, 2],
|
||||
strokeLineCap = 'round',
|
||||
strokeLineJoin = 'bevil',
|
||||
strokeMiterLimit = 5;
|
||||
|
||||
|
||||
elCircle.setAttribute('r', radius);
|
||||
|
|
@ -120,6 +127,10 @@
|
|||
elCircle.setAttribute('fill', fill);
|
||||
elCircle.setAttribute('fill-opacity', fillOpacity);
|
||||
elCircle.setAttribute('stroke-width', strokeWidth);
|
||||
elCircle.setAttribute('stroke-dasharray', '5, 2');
|
||||
elCircle.setAttribute('stroke-linecap', strokeLineCap);
|
||||
elCircle.setAttribute('stroke-linejoin', strokeLineJoin);
|
||||
elCircle.setAttribute('stroke-miterlimit', strokeMiterLimit);
|
||||
|
||||
var oCircle = fabric.Circle.fromElement(elCircle);
|
||||
ok(oCircle instanceof fabric.Circle);
|
||||
|
|
@ -130,6 +141,10 @@
|
|||
equal(oCircle.get('fill'), fill);
|
||||
equal(oCircle.get('opacity'), fillOpacity);
|
||||
equal(oCircle.get('strokeWidth'), strokeWidth);
|
||||
deepEqual(oCircle.get('strokeDashArray'), strokeDashArray);
|
||||
equal(oCircle.get('strokeLineCap'), strokeLineCap);
|
||||
equal(oCircle.get('strokeLineJoin'), strokeLineJoin);
|
||||
equal(oCircle.get('strokeMiterLimit'), strokeMiterLimit);
|
||||
|
||||
elFaultyCircle = fabric.document.createElement('circle');
|
||||
elFaultyCircle.setAttribute('r', '-10');
|
||||
|
|
|
|||
|
|
@ -22,34 +22,37 @@
|
|||
test('toObject', function() {
|
||||
var ellipse = new fabric.Ellipse();
|
||||
var defaultProperties = {
|
||||
'type': 'ellipse',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'rx': 0,
|
||||
'ry': 0,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'ellipse',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'rx': 0,
|
||||
'ry': 0,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
ok(typeof ellipse.toObject == 'function');
|
||||
deepEqual(defaultProperties, ellipse.toObject());
|
||||
|
|
@ -83,14 +86,18 @@
|
|||
test('fromElement', function() {
|
||||
ok(typeof fabric.Ellipse.fromElement == 'function');
|
||||
|
||||
var elEllipse = fabric.document.createElement('ellipse'),
|
||||
rx = 5,
|
||||
ry = 7,
|
||||
left = 12,
|
||||
top = 15,
|
||||
fill = 'ff5555',
|
||||
fillOpacity = 0.5,
|
||||
strokeWidth = 2;
|
||||
var elEllipse = fabric.document.createElement('ellipse'),
|
||||
rx = 5,
|
||||
ry = 7,
|
||||
left = 12,
|
||||
top = 15,
|
||||
fill = 'ff5555',
|
||||
fillOpacity = 0.5,
|
||||
strokeWidth = 2,
|
||||
strokeDashArray = [5, 2],
|
||||
strokeLineCap = 'round',
|
||||
strokeLineJoin = 'bevil',
|
||||
strokeMiterLimit = 5;
|
||||
|
||||
elEllipse.setAttribute('rx', rx);
|
||||
elEllipse.setAttribute('ry', ry);
|
||||
|
|
@ -99,6 +106,10 @@
|
|||
elEllipse.setAttribute('fill', fill);
|
||||
elEllipse.setAttribute('fill-opacity', fillOpacity);
|
||||
elEllipse.setAttribute('stroke-width', strokeWidth);
|
||||
elEllipse.setAttribute('stroke-dasharray', '5, 2');
|
||||
elEllipse.setAttribute('stroke-linecap', strokeLineCap);
|
||||
elEllipse.setAttribute('stroke-linejoin', strokeLineJoin);
|
||||
elEllipse.setAttribute('stroke-miterlimit', strokeMiterLimit);
|
||||
|
||||
var oEllipse = fabric.Ellipse.fromElement(elEllipse);
|
||||
ok(oEllipse instanceof fabric.Ellipse);
|
||||
|
|
@ -110,6 +121,10 @@
|
|||
equal(oEllipse.get('fill'), fill);
|
||||
equal(oEllipse.get('opacity'), fillOpacity);
|
||||
equal(oEllipse.get('strokeWidth'), strokeWidth);
|
||||
deepEqual(oEllipse.get('strokeDashArray'), strokeDashArray);
|
||||
equal(oEllipse.get('strokeLineCap'), strokeLineCap);
|
||||
equal(oEllipse.get('strokeLineJoin'), strokeLineJoin);
|
||||
equal(oEllipse.get('strokeMiterLimit'), strokeMiterLimit);
|
||||
});
|
||||
|
||||
test('fromObject', function() {
|
||||
|
|
|
|||
|
|
@ -133,33 +133,36 @@
|
|||
var clone = group.toObject();
|
||||
|
||||
var expectedObject = {
|
||||
'type': 'group',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 80,
|
||||
'top': 117.5,
|
||||
'width': 70,
|
||||
'height': 45,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'group',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 80,
|
||||
'top': 117.5,
|
||||
'width': 70,
|
||||
'height': 45,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'objects': clone.objects
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'objects': clone.objects
|
||||
};
|
||||
|
||||
deepEqual(clone, expectedObject);
|
||||
|
|
@ -336,7 +339,7 @@
|
|||
var group = makeGroupWith2Objects();
|
||||
ok(typeof group.toSVG == 'function');
|
||||
|
||||
var expectedSVG = '<g transform="translate(80 117.5)"><rect x="-5" y="-20" rx="0" ry="0" width="10" height="40" style="stroke: none; stroke-width: 1; stroke-dasharray: ; fill: rgb(0,0,0); opacity: 1;" transform="translate(-30 2.5)"/><rect x="-15" y="-5" rx="0" ry="0" width="30" height="10" style="stroke: none; stroke-width: 1; stroke-dasharray: ; fill: rgb(0,0,0); opacity: 1;" transform="translate(20 -17.5)"/></g>';
|
||||
var expectedSVG = '<g transform="translate(80 117.5)"><rect x="-5" y="-20" rx="0" ry="0" width="10" height="40" style="stroke: none; stroke-width: 1; stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); opacity: 1;" transform="translate(-30 2.5)"/><rect x="-15" y="-5" rx="0" ry="0" width="30" height="10" style="stroke: none; stroke-width: 1; stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); opacity: 1;" transform="translate(20 -17.5)"/></g>';
|
||||
equal(group.toSVG(), expectedSVG);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -15,34 +15,37 @@
|
|||
IMG_HEIGHT = 110;
|
||||
|
||||
var REFERENCE_IMG_OBJECT = {
|
||||
'type': 'image',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects
|
||||
'height': IMG_HEIGHT, // or does it now?
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'src': fabric.isLikelyNode ? undefined : IMG_SRC,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'image',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects
|
||||
'height': IMG_HEIGHT, // or does it now?
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'src': fabric.isLikelyNode ? undefined : IMG_SRC,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'filters': []
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'filters': []
|
||||
};
|
||||
|
||||
function _createImageElement() {
|
||||
|
|
|
|||
|
|
@ -1,36 +1,39 @@
|
|||
(function(){
|
||||
|
||||
var LINE_OBJECT = {
|
||||
'type': 'line',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 12,
|
||||
'top': 13,
|
||||
'width': 2,
|
||||
'height': 2,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'x1': 11,
|
||||
'y1': 12,
|
||||
'x2': 13,
|
||||
'y2': 14,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'line',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 12,
|
||||
'top': 13,
|
||||
'width': 2,
|
||||
'height': 2,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'x1': 11,
|
||||
'y1': 12,
|
||||
'x2': 13,
|
||||
'y2': 14,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
|
||||
QUnit.module('fabric.Line');
|
||||
|
|
@ -78,13 +81,17 @@
|
|||
test('fromElement', function() {
|
||||
ok(typeof fabric.Line.fromElement == 'function');
|
||||
|
||||
var lineEl = fabric.document.createElement('line'),
|
||||
x1 = 11,
|
||||
y1 = 23,
|
||||
x2 = 34,
|
||||
y2 = 7,
|
||||
stroke = 'ff5555',
|
||||
strokeWidth = 2;
|
||||
var lineEl = fabric.document.createElement('line'),
|
||||
x1 = 11,
|
||||
y1 = 23,
|
||||
x2 = 34,
|
||||
y2 = 7,
|
||||
stroke = 'ff5555',
|
||||
strokeWidth = 2,
|
||||
strokeDashArray = [5, 2],
|
||||
strokeLineCap = 'round',
|
||||
strokeLineJoin = 'bevil',
|
||||
strokeMiterLimit = 5;
|
||||
|
||||
lineEl.setAttribute('x1', x1);
|
||||
lineEl.setAttribute('x2', x2);
|
||||
|
|
@ -92,6 +99,10 @@
|
|||
lineEl.setAttribute('y2', y2);
|
||||
lineEl.setAttribute('stroke', stroke);
|
||||
lineEl.setAttribute('stroke-width', strokeWidth);
|
||||
lineEl.setAttribute('stroke-dasharray', '5, 2');
|
||||
lineEl.setAttribute('stroke-linecap', strokeLineCap);
|
||||
lineEl.setAttribute('stroke-linejoin', strokeLineJoin);
|
||||
lineEl.setAttribute('stroke-miterlimit', strokeMiterLimit);
|
||||
|
||||
var oLine = fabric.Line.fromElement(lineEl);
|
||||
ok(oLine instanceof fabric.Line);
|
||||
|
|
@ -102,6 +113,10 @@
|
|||
equal(oLine.get('y2'), y2);
|
||||
equal(oLine.get('stroke'), stroke);
|
||||
equal(oLine.get('strokeWidth'), strokeWidth);
|
||||
deepEqual(oLine.get('strokeDashArray'), strokeDashArray);
|
||||
equal(oLine.get('strokeLineCap'), strokeLineCap);
|
||||
equal(oLine.get('strokeLineJoin'), strokeLineJoin);
|
||||
equal(oLine.get('strokeMiterLimit'), strokeMiterLimit);
|
||||
|
||||
var lineElWithMissingAttributes = fabric.document.createElement('line');
|
||||
lineElWithMissingAttributes.setAttribute('x1', 10);
|
||||
|
|
|
|||
|
|
@ -110,80 +110,94 @@
|
|||
|
||||
test('toJSON', function() {
|
||||
var emptyObjectJSON = '{"type":"object","originX":"center","originY":"center","left":0,"top":0,"width":0,"height":0,"fill":"rgb(0,0,0)",'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,'+
|
||||
'"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,'+
|
||||
'"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,"visible":true}';
|
||||
|
||||
var augmentedJSON = '{"type":"object","originX":"center","originY":"center","left":0,"top":0,"width":122,"height":0,"fill":"rgb(0,0,0)",'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1.3,"scaleY":1,"angle":0,'+
|
||||
'"flipX":false,"flipY":true,"opacity":0.88,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,'+
|
||||
'"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":[5,2],"strokeLineCap":"round","strokeLineJoin":"bevil","strokeMiterLimit":5,'+
|
||||
'"scaleX":1.3,"scaleY":1,"angle":0,"flipX":false,"flipY":true,"opacity":0.88,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":true,'+
|
||||
'"transparentCorners":true,"perPixelTargetFind":false,"shadow":null,"visible":true}';
|
||||
|
||||
var cObj = new fabric.Object();
|
||||
ok(typeof cObj.toJSON == 'function');
|
||||
equal(JSON.stringify(cObj.toJSON()), emptyObjectJSON);
|
||||
|
||||
cObj.set('opacity', 0.88).set('scaleX', 1.3).set('width', 122).set('flipY', true);
|
||||
cObj.set('opacity', 0.88)
|
||||
.set('scaleX', 1.3)
|
||||
.set('width', 122)
|
||||
.set('flipY', true)
|
||||
.set('strokeDashArray', [5, 2])
|
||||
.set('strokeLineCap', 'round')
|
||||
.set('strokeLineJoin', 'bevil')
|
||||
.set('strokeMiterLimit', 5);
|
||||
|
||||
equal(JSON.stringify(cObj.toJSON()), augmentedJSON);
|
||||
});
|
||||
|
||||
test('toObject', function() {
|
||||
var emptyObjectRepr = {
|
||||
'type': "object",
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': "object",
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
|
||||
var augmentedObjectRepr = {
|
||||
'type': "object",
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 10,
|
||||
'top': 20,
|
||||
'width': 30,
|
||||
'height': 40,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': true,
|
||||
'flipY': false,
|
||||
'opacity': 0.13,
|
||||
'selectable': false,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': "object",
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 10,
|
||||
'top': 20,
|
||||
'width': 30,
|
||||
'height': 40,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': [5, 2],
|
||||
'strokeLineCap': 'round',
|
||||
'strokeLineJoin': 'bevil',
|
||||
'strokeMiterLimit': 5,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': true,
|
||||
'flipY': false,
|
||||
'opacity': 0.13,
|
||||
'selectable': false,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
|
||||
var cObj = new fabric.Object();
|
||||
|
|
@ -195,7 +209,11 @@
|
|||
.set('height', 40)
|
||||
.set('flipX', true)
|
||||
.set('opacity', 0.13)
|
||||
.set('selectable', false);
|
||||
.set('selectable', false)
|
||||
.set('strokeDashArray', [5, 2])
|
||||
.set('strokeLineCap', 'round')
|
||||
.set('strokeLineJoin', 'bevil')
|
||||
.set('strokeMiterLimit', 5);
|
||||
|
||||
deepEqual(augmentedObjectRepr, cObj.toObject());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +1,36 @@
|
|||
(function() {
|
||||
|
||||
var REFERENCE_PATH_OBJECT = {
|
||||
'type': 'path',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 200,
|
||||
'top': 200,
|
||||
'width': 200,
|
||||
'height': 200,
|
||||
'fill': 'red',
|
||||
'overlayFill': null,
|
||||
'stroke': 'blue',
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'path': [['M', 100, 100], ['L', 300, 100], ['L', 200, 300], ['z']],
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'path',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 200,
|
||||
'top': 200,
|
||||
'width': 200,
|
||||
'height': 200,
|
||||
'fill': 'red',
|
||||
'overlayFill': null,
|
||||
'stroke': 'blue',
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'path': [['M', 100, 100], ['L', 300, 100], ['L', 200, 300], ['z']],
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
|
||||
function getPathElement(path) {
|
||||
|
|
@ -35,7 +38,10 @@
|
|||
el.setAttribute('d', path);
|
||||
el.setAttribute('fill', 'red');
|
||||
el.setAttribute('stroke', 'blue');
|
||||
el.setAttribute('troke-width', 3);
|
||||
el.setAttribute('stroke-width', 1);
|
||||
el.setAttribute('stroke-linecap', 'butt');
|
||||
el.setAttribute('stroke-linejoin', 'miter');
|
||||
el.setAttribute('stroke-miterlimit', 10);
|
||||
return el;
|
||||
}
|
||||
|
||||
|
|
@ -114,16 +120,24 @@
|
|||
elPath.setAttribute('fill-opacity', '1');
|
||||
elPath.setAttribute('stroke', 'blue');
|
||||
elPath.setAttribute('stroke-width', '1');
|
||||
elPath.setAttribute('stroke-dasharray', '5, 2');
|
||||
elPath.setAttribute('stroke-linecap', 'round');
|
||||
elPath.setAttribute('stroke-linejoin', 'bevil');
|
||||
elPath.setAttribute('stroke-miterlimit', '5');
|
||||
|
||||
// TODO (kangax): to support multiple transformation keywords, we need to do proper matrix multiplication
|
||||
// elPath.setAttribute('transform', 'scale(2) translate(10, -20)');
|
||||
//elPath.setAttribute('transform', 'scale(2) translate(10, -20)');
|
||||
elPath.setAttribute('transform', 'scale(2)');
|
||||
|
||||
var path = fabric.Path.fromElement(elPath);
|
||||
ok(path instanceof fabric.Path);
|
||||
|
||||
deepEqual(fabric.util.object.extend(REFERENCE_PATH_OBJECT, {
|
||||
transformMatrix: [2, 0, 0, 2, 0, 0]
|
||||
strokeDashArray: [5, 2],
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'bevil',
|
||||
strokeMiterLimit: 5,
|
||||
transformMatrix: [2, 0, 0, 2, 0, 0]
|
||||
}), path.toObject());
|
||||
|
||||
var ANGLE = 90;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
|
|
|
|||
|
|
@ -8,33 +8,36 @@
|
|||
}
|
||||
|
||||
var REFERENCE_OBJECT = {
|
||||
'type': 'polygon',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 10,
|
||||
'height': 10,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'points': getPoints(),
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'polygon',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 10,
|
||||
'height': 10,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'points': getPoints(),
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
|
||||
QUnit.module('fabric.Polygon');
|
||||
|
|
@ -99,6 +102,10 @@
|
|||
elPolygonWithAttrs.setAttribute('stroke-width', '3');
|
||||
elPolygonWithAttrs.setAttribute('stroke', 'blue');
|
||||
elPolygonWithAttrs.setAttribute('transform', 'translate(-10,-20) scale(2)');
|
||||
elPolygonWithAttrs.setAttribute('stroke-dasharray', '5, 2');
|
||||
elPolygonWithAttrs.setAttribute('stroke-linecap', 'round');
|
||||
elPolygonWithAttrs.setAttribute('stroke-linejoin', 'bevil');
|
||||
elPolygonWithAttrs.setAttribute('stroke-miterlimit', '5');
|
||||
|
||||
var polygonWithAttrs = fabric.Polygon.fromElement(elPolygonWithAttrs);
|
||||
var expectedPoints = [
|
||||
|
|
@ -114,6 +121,10 @@
|
|||
'fill': 'rgb(255,255,255)',
|
||||
'stroke': 'blue',
|
||||
'strokeWidth': 3,
|
||||
'strokeDashArray': [5, 2],
|
||||
'strokeLineCap': 'round',
|
||||
'strokeLineJoin': 'bevil',
|
||||
'strokeMiterLimit': 5,
|
||||
'opacity': 0.34,
|
||||
'points': expectedPoints
|
||||
}), polygonWithAttrs.toObject());
|
||||
|
|
|
|||
|
|
@ -8,33 +8,36 @@
|
|||
}
|
||||
|
||||
var REFERENCE_OBJECT = {
|
||||
'type': 'polyline',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 10,
|
||||
'height': 10,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'points': getPoints(),
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'polyline',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 10,
|
||||
'height': 10,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'points': getPoints(),
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
'shadow': null,
|
||||
'visible': true
|
||||
};
|
||||
|
||||
QUnit.module('fabric.Polyline');
|
||||
|
|
@ -92,6 +95,10 @@
|
|||
elPolylineWithAttrs.setAttribute('stroke-width', '3');
|
||||
elPolylineWithAttrs.setAttribute('stroke', 'blue');
|
||||
elPolylineWithAttrs.setAttribute('transform', 'translate(-10,-20) scale(2)');
|
||||
elPolylineWithAttrs.setAttribute('stroke-dasharray', '5, 2');
|
||||
elPolylineWithAttrs.setAttribute('stroke-linecap', 'round');
|
||||
elPolylineWithAttrs.setAttribute('stroke-linejoin', 'bevil');
|
||||
elPolylineWithAttrs.setAttribute('stroke-miterlimit', '5');
|
||||
|
||||
var polylineWithAttrs = fabric.Polyline.fromElement(elPolylineWithAttrs);
|
||||
|
||||
|
|
@ -103,6 +110,10 @@
|
|||
'fill': 'rgb(255,255,255)',
|
||||
'stroke': 'blue',
|
||||
'strokeWidth': 3,
|
||||
'strokeDashArray': [5, 2],
|
||||
'strokeLineCap': 'round',
|
||||
'strokeLineJoin': 'bevil',
|
||||
'strokeMiterLimit': 5,
|
||||
'opacity': 0.34,
|
||||
'points': expectedPoints
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,34 +1,37 @@
|
|||
(function() {
|
||||
|
||||
var REFERENCE_RECT = {
|
||||
'type': 'rect',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'type': 'rect',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'rx': 0,
|
||||
'ry': 0
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'rx': 0,
|
||||
'ry': 0
|
||||
};
|
||||
|
||||
QUnit.module('fabric.Rect');
|
||||
|
|
@ -89,6 +92,10 @@
|
|||
elRectWithAttrs.setAttribute('fill-opacity', 0.45);
|
||||
elRectWithAttrs.setAttribute('stroke', 'blue');
|
||||
elRectWithAttrs.setAttribute('stroke-width', 3);
|
||||
elRectWithAttrs.setAttribute('stroke-dasharray', '5, 2');
|
||||
elRectWithAttrs.setAttribute('stroke-linecap', 'round');
|
||||
elRectWithAttrs.setAttribute('stroke-linejoin', 'bevil');
|
||||
elRectWithAttrs.setAttribute('stroke-miterlimit', 5);
|
||||
//elRectWithAttrs.setAttribute('transform', 'translate(-10,-20) scale(2) rotate(45) translate(5,10)');
|
||||
|
||||
var rectWithAttrs = fabric.Rect.fromElement(elRectWithAttrs);
|
||||
|
|
@ -103,6 +110,10 @@
|
|||
opacity: 0.45,
|
||||
stroke: 'blue',
|
||||
strokeWidth: 3,
|
||||
strokeDashArray: [5, 2],
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'bevil',
|
||||
strokeMiterLimit: 5,
|
||||
rx: 11,
|
||||
ry: 12
|
||||
});
|
||||
|
|
@ -125,6 +136,6 @@
|
|||
var rect = new fabric.Rect({ width: 100, height: 100, rx: 20, ry: 30 });
|
||||
var svg = rect.toSVG();
|
||||
|
||||
equal('<rect x="-50" y="-50" rx="20" ry="30" width="100" height="100" style="stroke: none; stroke-width: 1; stroke-dasharray: ; fill: rgb(0,0,0); opacity: 1;" transform="translate(0 0)"/>', svg);
|
||||
equal('<rect x="-50" y="-50" rx="20" ry="30" width="100" height="100" style="stroke: none; stroke-width: 1; stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); opacity: 1;" transform="translate(0 0)"/>', svg);
|
||||
});
|
||||
})();
|
||||
|
|
@ -7,45 +7,48 @@
|
|||
}
|
||||
|
||||
var REFERENCE_TEXT_OBJECT = {
|
||||
'type': 'text',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 20,
|
||||
'height': 52,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': '',
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'text': 'x',
|
||||
'fontSize': 40,
|
||||
'fontWeight': 'normal',
|
||||
'fontFamily': 'Times New Roman',
|
||||
'fontStyle': '',
|
||||
'lineHeight': 1.3,
|
||||
'textDecoration': '',
|
||||
'textShadow': '',
|
||||
'textAlign': 'left',
|
||||
'path': null,
|
||||
'backgroundColor': '',
|
||||
'textBackgroundColor': '',
|
||||
'useNative': true
|
||||
'type': 'text',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': 20,
|
||||
'height': 52,
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'overlayFill': null,
|
||||
'stroke': '',
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'selectable': true,
|
||||
'hasControls': true,
|
||||
'hasBorders': true,
|
||||
'hasRotatingPoint': true,
|
||||
'transparentCorners': true,
|
||||
'perPixelTargetFind': false,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'text': 'x',
|
||||
'fontSize': 40,
|
||||
'fontWeight': 'normal',
|
||||
'fontFamily': 'Times New Roman',
|
||||
'fontStyle': '',
|
||||
'lineHeight': 1.3,
|
||||
'textDecoration': '',
|
||||
'textShadow': '',
|
||||
'textAlign': 'left',
|
||||
'path': null,
|
||||
'backgroundColor': '',
|
||||
'textBackgroundColor': '',
|
||||
'useNative': true
|
||||
};
|
||||
|
||||
test('constructor', function() {
|
||||
|
|
@ -165,6 +168,10 @@
|
|||
elTextWithAttrs.setAttribute('fill-opacity', 0.45);
|
||||
elTextWithAttrs.setAttribute('stroke', 'blue');
|
||||
elTextWithAttrs.setAttribute('stroke-width', 3);
|
||||
elTextWithAttrs.setAttribute('stroke-dasharray', '5, 2');
|
||||
elTextWithAttrs.setAttribute('stroke-linecap', 'round');
|
||||
elTextWithAttrs.setAttribute('stroke-linejoin', 'bevil');
|
||||
elTextWithAttrs.setAttribute('stroke-miterlimit', 5);
|
||||
elTextWithAttrs.setAttribute('font-family', 'Monaco');
|
||||
elTextWithAttrs.setAttribute('font-style', 'italic');
|
||||
elTextWithAttrs.setAttribute('font-weight', 'bold');
|
||||
|
|
@ -179,19 +186,23 @@
|
|||
|
||||
var expectedObject = fabric.util.object.extend(fabric.util.object.clone(REFERENCE_TEXT_OBJECT), {
|
||||
/* left varies slightly due to node-canvas rendering */
|
||||
left: fabric.util.toFixed(textWithAttrs.left + '', 2),
|
||||
top: -59.95,
|
||||
width: 20,
|
||||
height: 159.9,
|
||||
fill: 'rgb(255,255,255)',
|
||||
opacity: 0.45,
|
||||
stroke: 'blue',
|
||||
strokeWidth: 3,
|
||||
fontFamily: 'Monaco',
|
||||
fontStyle: 'italic',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 123,
|
||||
textDecoration: 'underline'
|
||||
left: fabric.util.toFixed(textWithAttrs.left + '', 2),
|
||||
top: -59.95,
|
||||
width: 20,
|
||||
height: 159.9,
|
||||
fill: 'rgb(255,255,255)',
|
||||
opacity: 0.45,
|
||||
stroke: 'blue',
|
||||
strokeWidth: 3,
|
||||
strokeDashArray: [5, 2],
|
||||
strokeLineCap: 'round',
|
||||
strokeLineJoin: 'bevil',
|
||||
strokeMiterLimit: 5,
|
||||
fontFamily: 'Monaco',
|
||||
fontStyle: 'italic',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 123,
|
||||
textDecoration: 'underline'
|
||||
});
|
||||
|
||||
deepEqual(textWithAttrs.toObject(), expectedObject);
|
||||
|
|
|
|||
Loading…
Reference in a new issue