Merge branch 'master' of github.com:paperjs/paper.js

This commit is contained in:
Jürg Lehni 2012-09-30 14:08:44 -07:00
commit 59a55f7574
27 changed files with 1896 additions and 1027 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
/files/
/patches/
/node_modules/

2405
dist/paper.js vendored

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Resize</title>
<link rel="stylesheet" href="../css/style.css">
<script type="text/javascript" src="../../dist/paper.js"></script>
<script type="text/paperscript" canvas="canvas">
var redPath = new Path.Circle(view.center, 10);
redPath.fillColor = 'red';
var whitePath = new Path.Circle(view.center, 10);
whitePath.fillColor = 'white';
var text = new PointText();
text.content = 'Resize your window';
text.justification = 'center';
function onResize(event) {
// Resize the red circle to fill the bounds of the view:
redPath.fitBounds(view.bounds, true);
// Resize the white circle to fit within the bounds of the view:
whitePath.fitBounds(view.bounds, false);
// Move the text to the center of the view:
text.position = view.bounds.center;
}
</script>
</head>
<body>
<canvas id="canvas" resize></canvas>
</body>
</html>

View file

@ -1 +0,0 @@
module.exports = require('./src/loadNode.js');

View file

@ -1,9 +1,7 @@
var fs = require('fs'),
vm = require('vm'),
path = require('path'),
// Have HTMLCanvasElement reference Canvas too, so we do not handle browser
// and server differently in some places of our code.
Canvas = HTMLCanvasElement =require('canvas');
Canvas = require('canvas');
__dirname = path.resolve(__dirname, '../src/');
@ -16,6 +14,7 @@ var context = vm.createContext({
fs: fs,
// Node Canvas library: https://github.com/learnboost/node-canvas
Canvas: Canvas,
HTMLCanvasElement: Canvas,
Image: Canvas.Image,
// Copy over global variables:
console: console,

View file

@ -13,8 +13,8 @@
"keywords": ["canvas", "graphic", "graphics", "vector", "paper.js"],
"repository": "git://github.com/paperjs/paper.js/",
"dependencies": {
"canvas": "0.7.0"
"canvas": ">= 0.7.0"
},
"engines": { "node": ">= 0.4.0 && < 0.6.0" },
"engines": { "node": ">= 0.4.0" },
"main": "./node.js/index.js"
}

View file

@ -428,7 +428,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
// squared length should be returned. Hide it so it produces a bean
// property called #length.
var l = this.x * this.x + this.y * this.y;
return arguments[0] ? l : Math.sqrt(l);
return (arguments.length && arguments[0]) ? l : Math.sqrt(l);
},
setLength: function(length) {

View file

@ -33,6 +33,39 @@ var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
this.type = type || 'linear';
},
/**
* Called by various setters whenever a gradient value changes
*/
_changed: function() {
// Loop through the gradient-colors that use this gradient and notify
// them, so they can notify the items they belong to.
for (var i = 0, l = this._owners && this._owners.length; i < l; i++)
this._owners[i]._changed();
},
/**
* Called by GradientColor#initialize
* This is required to pass on _changed() notifications to the _owners.
*/
_addOwner: function(color) {
if (!this._owners)
this._owners = [];
this._owners.push(color);
},
// TODO: Where and when should this be called:
/**
* Called by GradientColor whenever this gradient stops being used.
*/
_removeOwner: function(color) {
var index = this._owners ? this._owners.indexOf(color) : -1;
if (index != -1) {
this._owners.splice(index, 1);
if (this._owners.length == 0)
delete this._owners;
}
},
/**
* @return {Gradient} a copy of the gradient
*/
@ -54,6 +87,13 @@ var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
},
setStops: function(stops) {
// If this gradient already contains stops, first remove
// this gradient as their owner.
if (this.stops) {
for (var i = 0, l = this._stops.length; i < l; i++) {
this._stops[i]._removeOwner(this);
}
}
if (stops.length < 2)
throw new Error(
'Gradient stop list needs to contain at least two stops.');
@ -61,9 +101,11 @@ var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
// Now reassign ramp points if they were not specified.
for (var i = 0, l = this._stops.length; i < l; i++) {
var stop = this._stops[i];
stop._addOwner(this);
if (stop._defaultRamp)
stop.setRampPoint(i / (l - 1));
}
this._changed();
},
/**

View file

@ -84,6 +84,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
*/
initialize: function(gradient, origin, destination, hilite) {
this.gradient = gradient || new Gradient();
this.gradient._addOwner(this);
this.setOrigin(origin);
this.setDestination(destination);
if (hilite)

View file

@ -44,6 +44,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
}
},
// TODO: Do we really need to also clone the color here?
/**
* @return {GradientColor} a copy of the gradient-stop
*/
@ -51,6 +52,40 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
return new GradientStop(this._color.clone(), this._rampPoint);
},
/**
* Called by various setters whenever a value changes
*/
_changed: function() {
// Loop through the gradients that use this stop and notify them about
// the change, so they can notify their gradient colors, which in turn
// will notify the items they are used in:
for (var i = 0, l = this._owners && this._owners.length; i < l; i++)
this._owners[i]._changed(Change.STYLE);
},
/**
* Called by Gradient whenever this stop is used. This is required to pass
* on _changed() notifications to the _owners.
*/
_addOwner: function(gradient) {
if (!this._owners)
this._owners = [];
this._owners.push(gradient);
},
/**
* Called by Gradient whenever this GradientStop is no longer used by it.
*/
_removeOwner: function(gradient) {
var index = this._owners ? this._owners.indexOf(gradient) : -1;
if (index != -1) {
this._owners.splice(index, 1);
if (this._owners.length == 0)
delete this._owners;
}
},
/**
* The ramp-point of the gradient stop as a value between {@code 0} and
* {@code 1}.
@ -92,6 +127,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
setRampPoint: function(rampPoint) {
this._defaultRamp = rampPoint == null;
this._rampPoint = rampPoint || 0;
this._changed();
},
/**
@ -129,7 +165,13 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
},
setColor: function(color) {
// If the stop already contained a color,
// remove it as an owner:
if (this._color)
this._color._removeOwner(this);
this._color = Color.read(arguments);
this._color._addOwner(this);
this._changed();
},
equals: function(stop) {

View file

@ -155,7 +155,7 @@ var PaperScript = this.PaperScript = new function() {
function evaluate(code, scope) {
// Set currently active scope.
paper = scope;
var view = scope.project.view,
var view = scope.project && scope.project.view,
res;
// Define variables for potential handlers, so eval() calls below to
// fetch their values do not require try-catch around them.

View file

@ -120,8 +120,11 @@ var Group = this.Group = Item.extend(/** @lends Group# */{
draw: function(ctx, param) {
var clipItem = this._getClipItem();
if (clipItem)
if (clipItem) {
param.clipping = true;
Item.draw(clipItem, ctx, param);
delete param.clipping;
}
for (var i = 0, l = this._children.length; i < l; i++) {
var item = this._children[i];
if (item != clipItem)

View file

@ -209,7 +209,7 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{
if (this._name)
this._removeFromNamed();
this._name = name || undefined;
if (name) {
if (name && this._parent) {
var children = this._parent._children,
namedChildren = this._parent._namedChildren;
(namedChildren[name] = namedChildren[name] || []).push(this);
@ -1169,8 +1169,10 @@ function(name) {
* @return {Boolean} {@true it was inserted}
*/
insertAbove: function(item) {
return item._parent && item._parent.insertChild(
item._index + 1, this);
var index = item._index;
if (item._parent == this._parent && index < this._index)
index++;
return item._parent.insertChild(index, this);
},
/**
@ -1180,8 +1182,10 @@ function(name) {
* @return {Boolean} {@true it was inserted}
*/
insertBelow: function(item) {
return item._parent && item._parent.insertChild(
item._index - 1, this);
var index = item._index;
if (item._parent == this._parent && index > this._index)
index--;
return item._parent.insertChild(index, this);
},
/**
@ -1957,7 +1961,6 @@ function(name) {
scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
? rectangle.width / bounds.width
: rectangle.height / bounds.height,
delta = rectangle.getCenter().subtract(bounds.getCenter()),
newBounds = new Rectangle(new Point(),
Size.create(bounds.width * scale, bounds.height * scale));
newBounds.setCenter(rectangle.getCenter());
@ -2449,14 +2452,16 @@ function(name) {
// so we draw onto it, instead of the parentCtx
ctx = tempCanvas.getContext('2d');
}
ctx.save();
if (!param.clipping)
ctx.save();
// Translate the context so the topLeft of the item is at (0, 0)
// on the temporary canvas.
if (tempCanvas)
ctx.translate(-itemOffset.x, -itemOffset.y);
item._matrix.applyToContext(ctx);
item.draw(ctx, param);
ctx.restore();
if (!param.clipping)
ctx.restore();
// If we created a temporary canvas before, composite it onto the
// parent canvas:
if (tempCanvas) {

View file

@ -124,6 +124,9 @@ var paper = new function() {
/*#*/ include('util/CanvasProvider.js');
/*#*/ include('util/Numerical.js');
/*#*/ include('util/BlendMode.js');
/*#*/ if (options.version == 'dev') {
/*#*/ include('util/ProxyContext.js');
/*#*/ } // options.browser
/*#*/ include('core/PaperScript.js');

View file

@ -68,6 +68,12 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
delete this._length;
// Clockwise state becomes undefined as soon as geometry changes.
delete this._clockwise;
// Curves are no longer valid
if (this._curves != null) {
for (var i = 0, l = this._curves.length; i < l; i++) {
this._curves[i]._changed(Change.GEOMETRY);
}
}
} else if (flags & ChangeFlag.STROKE) {
// TODO: We could preserve the purely geometric bounds that are not
// affected by stroke: _bounds.bounds and _bounds.handleBounds
@ -828,6 +834,7 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
var handleIn = segment._handleIn;
segment._handleIn = segment._handleOut;
segment._handleOut = handleIn;
segment._index = i;
}
// Flip clockwise state if it's defined
if (this._clockwise !== undefined)
@ -1450,6 +1457,9 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{
drawSegments(ctx, this);
}
if (this._closed)
ctx.closePath();
if (this._clipMask) {
ctx.clip();
} else if (!param.compound && (fillColor || strokeColor)) {

View file

@ -140,7 +140,7 @@ var PathFitter = Base.extend({
c1 = C[1][0] + C[1][1];
if (Math.abs(c0) > epsilon) {
alpha1 = alpha2 = X[0] / c0;
} else if (Math.abs(c0) > epsilon) {
} else if (Math.abs(c1) > epsilon) {
alpha1 = alpha2 = X[1] / c1;
} else {
// Handle below

View file

@ -108,7 +108,7 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{
setCharacterStyle: function(style) {
this.setStyle(style);
},
}
/**
* The paragraph style of the text item.

View file

@ -392,4 +392,66 @@ var Tool = this.Tool = PaperScopeItem.extend(Callback, /** @lends Tool# */{
// Return if a callback was called or not.
return called;
}
/**
* {@grouptitle Event Handling}
*
* Attach an event handler to the tool.
*
* @name Tool#attach
* @function
* @param {String('mousedown', 'mouseup', 'mousedrag', 'mousemove',
* 'keydown', 'keyup')} type the event type
* @param {Function} function The function to be called when the event
* occurs
*/
/**
* Attach one or more event handlers to the tool.
*
* @name Tool#attach^2
* @function
* @param {Object} param An object literal containing one or more of the
* following properties: {@code mousedown, mouseup, mousedrag, mousemove,
* keydown, keyup}.
*/
/**
* Detach an event handler from the tool.
*
* @name Tool#detach
* @function
* @param {String('mousedown', 'mouseup', 'mousedrag', 'mousemove',
* 'keydown', 'keyup')} type the event type
* @param {Function} function The function to be detached
*/
/**
* Detach one or more event handlers from the tool.
*
* @name Tool#detach^2
* @function
* @param {Object} param An object literal containing one or more of the
* following properties: {@code mousedown, mouseup, mousedrag, mousemove,
* keydown, keyup}
*/
/**
* Fire an event on the tool.
*
* @name Tool#fire
* @function
* @param {String('mousedown', 'mouseup', 'mousedrag', 'mousemove',
* 'keydown', 'keyup')} type the event type
* @param {Object} event An object literal containing properties describing
* the event.
*/
/**
* Check if the tool has one or more event handlers of the specified type.
*
* @name Tool#responds
* @function
* @param {String('mousedown', 'mouseup', 'mousedrag', 'mousemove',
* 'keydown', 'keyup')} type the event type
* @return {Boolean} {@true if the tool has one or more event handlers of
* the specified type}
*/
});

View file

@ -395,6 +395,62 @@ var View = this.View = Base.extend(Callback, /** @lends View# */{
* @property
* @type Function
*/
/**
* {@grouptitle Event Handling}
*
* Attach an event handler to the view.
*
* @name View#attach
* @function
* @param {String('frame', 'resize')} type the event type
* @param {Function} function The function to be called when the event
* occurs
*/
/**
* Attach one or more event handlers to the view.
*
* @name View#attach^2
* @function
* @param {Object} param An object literal containing one or more of the
* following properties: {@code frame, resize}.
*/
/**
* Detach an event handler from the view.
*
* @name View#detach
* @function
* @param {String('frame', 'resize')} type the event type
* @param {Function} function The function to be detached
*/
/**
* Detach one or more event handlers from the view.
*
* @name View#detach^2
* @function
* @param {Object} param An object literal containing one or more of the
* following properties: {@code frame, resize}
*/
/**
* Fire an event on the view.
*
* @name View#fire
* @function
* @param {String('frame', 'resize')} type the event type
* @param {Object} event An object literal containing properties describing
* the event.
*/
/**
* Check if the view has one or more event handlers of the specified type.
*
* @name View#responds
* @function
* @param {String('frame', 'resize')} type the event type
* @return {Boolean} {@true if the view has one or more event handlers of
* the specified type}
*/
}, {
statics: {
_views: [],

93
src/util/ProxyContext.js Normal file
View file

@ -0,0 +1,93 @@
/*
* Paper.js
*
* This file is part of Paper.js, a JavaScript Vector Graphics Library,
* based on Scriptographer.org and designed to be largely API compatible.
* http://paperjs.org/
* http://scriptographer.org/
*
* Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
* http://lehni.org/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
/**
* @name ProxyContext
*
* @class The ProxyContext is a helper class that helps Canvas debugging
* by logging all interactions with a 2D Canvas context.
*
* @classexample
* view._context = new ProxyContext(view._context);
*/
var ProxyContext = new function() {
var descriptions = [
'save()', 'restore()', 'scale(x,y)', 'rotate(angle)', 'translate(x,y)',
'transform(a,b,c,d,e,f)', 'setTransform(a,b,c,d,e,f)', 'globalAlpha',
'globalCompositeOperation', 'strokeStyle', 'fillStyle',
'createLinearGradient(x0,y0,x1,y1)',
'createRadialGradient(x0,y0,r0,x1,y1,r1)',
'createPattern(image,repetition)', 'lineWidth', 'lineCap', 'lineJoin',
'miterLimit', 'shadowOffsetX', 'shadowOffsetY', 'shadowBlur',
'shadowColor', 'clearRect(x,y,w,h)', 'fillRect(x,y,w,h)',
'strokeRect(x,y,w,h)', 'beginPath()', 'closePath()', 'moveTo(x,y)',
'lineTo(x,y)', 'quadraticCurveTo(cpx,cpy,x,y)',
'bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)', 'arcTo(x1,y1,x2,y2,radius)',
'rect(x,y,w,h)', 'arc(x,y,radius,startAngle,endAngle,anticlockwise)',
'fill()', 'stroke()', 'drawSystemFocusRing()', 'drawCustomFocusRing()',
'scrollPathIntoView()', 'clip()', 'isPointInPath(x,y)', 'font',
'textAlign', 'textBaseline', 'fillText(text,x,y,maxWidth)',
'strokeText(text,x,y,maxWidth)', 'measureText(text)',
'drawImage(image,dx,dy)', 'drawImage(image,dx,dy,dw,dh)',
'drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)', 'createImageData(sw,sh)',
'createImageData(imagedata)', 'getImageData(sx,sy,sw,sh)',
'putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight)'
];
var param = {
initialize: function(context) {
this._ctx = context;
this._indents = 0;
},
getIndentation: function() {
var str = '';
for (var i = 0; i < this._indents; i++) {
str += ' ';
}
return str;
}
};
Base.each(descriptions, function(description) {
var matches = description.match(/^([^(]+)(\()*/),
name = matches[1],
isFunction = !!matches[2];
if (isFunction) {
param[name] = function() {
if (name == 'restore') {
this._indents--;
}
var args = Array.prototype.slice.call(arguments, 0).join(', '),
string = 'ctx.' + name + '(' + args + ');';
console.log(this.getIndentation() + string);
if (name == 'save') {
this._indents++;
}
return this._ctx[name].apply(this._ctx, arguments);
};
} else {
var capitalized = Base.capitalize(name);
param['set' + capitalized] = function(value) {
var logValue = value && value.substring ? '\'' + value + '\'' : value,
string = 'ctx.' + name + ' = ' + logValue + ';';
console.log(this.getIndentation() + string);
return this._ctx[name] = value;
};
param['get' + capitalized] = function() {
return this._ctx[name];
};
}
});
return Base.extend(param);
};

View file

@ -410,4 +410,52 @@ test('hitting guides', function() {
}
});
test('hitting raster items', function() {
// Create a path, rasterize it and then remove the path:
var path = new Path.Rectangle(new Point(), new Size(320, 240));
path.fillColor = 'red';
var raster = path.rasterize();
var hitResult = paper.project.hitTest(new Point(160, 120));
equals(function() {
return hitResult && hitResult.item == raster;
}, true, 'Hit raster item before moving');
// Move the raster:
raster.translate(100, 100);
var hitResult = paper.project.hitTest(new Point(160, 120));
equals(function() {
return hitResult && hitResult.item == raster;
}, true, 'Hit raster item after moving');
});
test('hitting path with a text item in the project', function() {
var path = new Path.Rectangle(new Point(50, 50), new Point(100, 100));
path.fillColor = 'blue';
var hitResult = paper.project.hitTest(new Point(75, 75));
equals(function() {
return hitResult && hitResult.item == path;
}, true, 'Hit path item before adding text item');
var text1 = new PointText(30, 30);
text1.content = "Text 1";
var hitResult = paper.project.hitTest(new Point(75, 75));
equals(function() {
return !!hitResult;
}, true, 'A hitresult should be returned.');
equals(function() {
return !!hitResult && hitResult.item == path;
}, true, 'We should have hit the path');
});
// TODO: project.hitTest(point, {type: AnItemType});

View file

@ -464,6 +464,17 @@ test('Changing item#position.x', function() {
equals(path.position.toString(), '{ x: 55, y: 50 }', 'path.position.x += 5');
});
test('Naming a removed item', function() {
var path = new Path();
path.remove();
path.name = 'test';
});
test('Naming a layer', function() {
var layer = new Layer();
layer.name = 'test';
});
test('Cloning a linked size', function() {
var path = new Path([40, 75], [140, 75]);
var error = null;

View file

@ -42,3 +42,12 @@ test('item.bounds caching', function() {
}, 2);
compareRectangles(group.bounds, { x: 50, y: 50, width: 125, height: 125 }, 'group.bounds with circle');
});
test('group.bounds when group contains empty group', function() {
var group = new Group();
var rectangle = new Path.Rectangle(new Point(75, 75), new Point(175, 175));
group.addChild(rectangle);
compareRectangles(group.bounds, { x: 75, y: 75, width: 100, height: 100 }, 'group.bounds without empty group');
group.addChild(new Group());
compareRectangles(group.bounds, { x: 75, y: 75, width: 100, height: 100 }, 'group.bounds with empty group');
});

View file

@ -57,3 +57,45 @@ test('Item Order', function() {
return group.isBelow(circle);
}, false);
});
test('Item#moveAbove(item) / Item#moveBelow(item)', function() {
var item0, item1, item2;
var testMove = function(command, indexes) {
paper.project.activeLayer.remove();
new Layer();
item0 = new Group();
item1 = new Group();
item2 = new Group();
command();
equals(function() {
return item0.index;
}, indexes[0], command.toString());
equals(function() {
return item1.index;
}, indexes[1]);
equals(function() {
return item2.index;
}, indexes[2]);
}
testMove(function() { item0.moveBelow(item0) }, [0,1,2]);
testMove(function() { item0.moveBelow(item1) }, [0,1,2]);
testMove(function() { item0.moveBelow(item2) }, [1,0,2]);
testMove(function() { item1.moveBelow(item0) }, [1,0,2]);
testMove(function() { item1.moveBelow(item1) }, [0,1,2]);
testMove(function() { item1.moveBelow(item2) }, [0,1,2]);
testMove(function() { item2.moveBelow(item0) }, [1,2,0]);
testMove(function() { item2.moveBelow(item1) }, [0,2,1]);
testMove(function() { item2.moveBelow(item2) }, [0,1,2]);
testMove(function() { item0.moveAbove(item0) }, [0,1,2]);
testMove(function() { item0.moveAbove(item1) }, [1,0,2]);
testMove(function() { item0.moveAbove(item2) }, [2,0,1]);
testMove(function() { item1.moveAbove(item0) }, [0,1,2]);
testMove(function() { item1.moveAbove(item1) }, [0,1,2]);
testMove(function() { item1.moveAbove(item2) }, [0,2,1]);
testMove(function() { item2.moveAbove(item0) }, [0,2,1]);
testMove(function() { item2.moveAbove(item1) }, [0,1,2]);
testMove(function() { item2.moveAbove(item2) }, [0,1,2]);
});

View file

@ -73,7 +73,7 @@ test('insertAbove / insertBelow', function() {
// move the layer above the path, inside the firstLayer:
secondLayer.insertAbove(path);
equals(function() {
return secondLayer.previousSibling == path;
return secondLayer.nextSibling == path;
}, true);
equals(function() {
return secondLayer.parent == firstLayer;

View file

@ -265,6 +265,14 @@ test('Path#reverse', function() {
equals(path.segments.toString(), '{ point: { x: 100, y: 130 }, handleIn: { x: -16.56854, y: 0 }, handleOut: { x: 16.56854, y: 0 } },{ point: { x: 130, y: 100 }, handleIn: { x: 0, y: 16.56854 }, handleOut: { x: 0, y: -16.56854 } },{ point: { x: 100, y: 70 }, handleIn: { x: 16.56854, y: 0 }, handleOut: { x: -16.56854, y: 0 } },{ point: { x: 70, y: 100 }, handleIn: { x: 0, y: -16.56854 }, handleOut: { x: 0, y: 16.56854 } }');
});
test('Path#reverse should adjust segment indices', function() {
var path = new Path([[0, 0], [10, 10], [20, 20]]);
path.reverse();
equals(path.segments[0].index, 0);
equals(path.segments[1].index, 1);
equals(path.segments[2].index, 2);
});
test('Path#fullySelected', function() {
var path = new Path.Circle([100, 100], 10);
path.fullySelected = true;
@ -272,4 +280,4 @@ test('Path#fullySelected', function() {
equals(function() {
return path.fullySelected;
}, false);
});
});

View file

@ -38,6 +38,12 @@ test('path.curves Synchronisation', function() {
path.removeSegments(1, 2);
equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }", "path.segments: path.add(new Point(100, 100));\npath.removeSegments(1, 2);");
equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }", "path.curves: path.add(new Point(100, 100));\npath.removeSegments(1, 2);");
// Transform the path, and the curves length should be invalidated (first, force-cache the first segment's length by accessing it
path.curves[0].length;
ok(path.curves[0]._length, 'Curve length does not appear to be cached');
path.scale(2, [0, 0]);
equals(path.curves[0].length, 200, 'Curve length should be updated when path is transformed');
});
test('path.flatten(maxDistance)', function() {
@ -53,4 +59,4 @@ test('path.flatten(maxDistance)', function() {
equals(function() {
return path.lastSegment.point.toString() != path.segments[path.segments.length - 2].point.toString();
}, true, 'The points of the last and before last segments should not be so close, that calling toString on them returns the same string value.');
});
});