Move Path_Bounds tests to Item_Bounds.

And add a test for shape.strokeBounds without strokeScaling.
This commit is contained in:
Jürg Lehni 2016-02-02 13:55:36 +01:00
parent 21dce1a655
commit a02d7248c0
7 changed files with 761 additions and 368 deletions

View file

@ -100,3 +100,511 @@ test('text.bounds', function() {
});
equals(text.bounds, new Rectangle(50, 87.4, 76.25, 16.8), 'text.bounds', { tolerance: 1.0 });
});
QUnit.module('Path Bounds');
test('path.bounds', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74)),
new Segment(new Point(205, 420.94482421875), new Point(66.7890625, -12.72802734375), new Point(-79, 15.05517578125))
]);
// Test both closed and open paths, as the bounds for them differ
path.closed = false;
equals(path.bounds,
new Rectangle(121, 275.068, 149.49305, 145.87682),
'open path.bounds');
equals(path.position,
new Point(195.74653, 348.00641),
'open path.position');
// Test both closed and open paths, as the bounds for them differ
path.closed = true;
equals(path.bounds,
new Rectangle(114.82725, 275.068, 155.6658, 148.12773),
'closed path.bounds');
equals(path.position,
new Point(192.66015, 349.13186),
'closed path.position');
// Scale the path by 0.5 and check bounds
path.scale(0.5);
equals(path.bounds,
new Rectangle(153.7437, 312.09993, 77.8329, 74.06386),
'scaled path.bounds');
// Move the path to another position and check bounds
path.position = [100, 100];
equals(path.bounds,
new Rectangle(61.08355, 62.96807, 77.8329, 74.06386),
'moved path.bounds');
// Set new bounds and check segment list as result of resizing / positioning
path.bounds = { x: 100, y: 100, width: 200, height: 200 };
equals(path.segments.toString(),
'{ point: { x: 107.93077, y: 179.56917 }, handleIn: { x: -24.41127, y: 51.30707 }, handleOut: { x: 39.52904, y: -83.08194 } },{ point: { x: 271.10084, y: 160.66656 }, handleIn: { x: -53.96176, y: -99.91377 }, handleOut: { x: 53.96176, y: 99.91377 } },{ point: { x: 215.85428, y: 296.96086 }, handleIn: { x: 85.81084, y: -17.18521 }, handleOut: { x: -101.49949, y: 20.32729 } }',
'resized path.segments');
// Now rotate by 40 degrees and test bounds and segments again.
path.rotate(40);
equals(path.bounds,
new Rectangle(92.38102, 106.78972, 191.48071, 203.66876),
'rotated path.bounds');
equals(path.segments.toString(),
'{ point: { x: 142.60356, y: 125.16811 }, handleIn: { x: -51.67967, y: 23.61224 }, handleOut: { x: 83.68504, y: -38.23568 } },{ point: { x: 279.74945, y: 215.57158 }, handleIn: { x: 22.88623, y: -111.22434 }, handleOut: { x: -22.88623, y: 111.22434 } },{ point: { x: 149.81984, y: 284.46726 }, handleIn: { x: 76.78135, y: 41.99351 }, handleOut: { x: -90.81925, y: -49.67101 } }',
'roated path.segments');
});
test('path.strokeBounds on path without stroke', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74)),
new Segment(new Point(205, 420.94482421875), new Point(66.7890625, -12.72802734375), new Point(-79, 15.05517578125))
]);
equals(path.strokeBounds, new Rectangle(121, 275.068, 149.49305, 145.87682));
});
test('path.strokeBounds on path with single segment and stroke color', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625))
]);
path.strokeColor = 'black';
equals(path.strokeBounds, new Rectangle(121, 334, 0, 0));
});
test('path.strokeBounds on closed path with single segment and stroke color', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(19, 38), new Point(30.7666015625, -61.53369140625))
]);
path.strokeColor = 'black';
path.closed = true;
equals(path.strokeBounds, new Rectangle(120.44098, 312.88324 , 19.97544, 30.53977));
});
test('path.strokeBounds with corners and miter limit', function() {
var path = new Path({
pathData: 'M47,385c120,-100 120,-100 400,-40c-280,140 -280,140 -400,40z',
strokeWidth: 5,
strokeJoin: "miter",
strokeColor: "black"
});
equals(path.strokeBounds, new Rectangle(43.09488, 301.5525, 411.3977, 156.57543));
});
test('path.bounds & path.strokeBounds with stroke styles', function() {
function makePath() {
var path = new Path();
path.moveTo(200, 50);
path.lineTo(230, 100);
path.lineTo(250, 50);
path.lineTo(280, 110);
path.arcTo([250, 20], false);
path.rotate(-5);
path.strokeWidth = 30;
path.miterLimit = 3;
return path;
}
var path = makePath();
path.fullySelected = true;
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 16.78419, 113.50622, 90.96766),
'butt/round path.bounds');
equals(path.strokeBounds,
new Rectangle(186.87242, 1.78419, 140.64705, 120.96766),
'butt/round path.strokeBounds');
var path = makePath().translate(150, 0);
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 16.78419, 113.50622, 90.96766),
'butt/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(336.87242, 1.78419, 140.64705, 119.73034),
'butt/bevel path.strokeBounds');
var path = makePath().translate(300, 0);
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 16.78419, 113.50622, 90.96766),
'butt/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(486.87242, 1.78419, 140.64705, 133.64882),
'butt/miter path.strokeBounds');
var path = makePath().translate(0, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 166.78419, 113.50622, 90.96766),
'square/round path.bounds');
equals(path.strokeBounds,
new Rectangle(178.06332, 151.78419, 149.45615, 120.96766),
'square/strokeBounds path.bounds');
var path = makePath().translate(150, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 166.78419, 113.50622, 90.96766),
'square/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(328.06332, 151.78419, 149.45615, 119.73034),
'square/bevel path.strokeBounds');
var path = makePath().translate(300, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 166.78419, 113.50622, 90.96766),
'square/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(478.06332, 151.78419, 149.45615, 133.64882),
'square/miter path.strokeBounds');
var path = makePath().translate(0, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 316.78419, 113.50622, 90.96766),
'round/round path.bounds');
equals(path.strokeBounds,
new Rectangle(184.01325, 301.78419, 143.50622, 120.96766),
'round/round path.strokeBounds');
var path = makePath().translate(150, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 316.78419, 113.50622, 90.96766),
'round/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(334.01325, 301.78419, 143.50622, 119.73034),
'round/bevel path.strokeBounds');
var path = makePath().translate(300, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 316.78419, 113.50622, 90.96766),
'round/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(484.01325, 301.78419, 143.50622, 133.64882),
'round/miter path.strokeBounds');
});
test('path.strokeBounds with rectangles', function() {
var path = new paper.Path.Rectangle({
point: [100, 100],
size: [100, 100],
strokeWidth: 50,
strokeColor: 'black'
});
equals(path.strokeBounds,
new Rectangle(75, 75, 150, 150),
'path.strokeBounds');
});
test('path.strokeBounds without strokeScaling and zoomed view', function() {
var path = new Path.Circle({
center: [0, 0],
radius: 100,
strokeColor: 'black',
strokeWidth: 15,
strokeScaling: false
});
view.zoom = 2;
equals(path.strokeBounds,
new Rectangle(-103.75, -103.75, 207.5, 207.5),
'path.strokeBounds with zoomed view');
view.zoom = 1;
equals(path.strokeBounds,
new Rectangle(-107.5, -107.5, 215, 215),
'path.strokeBounds without zoomed view');
});
test('shape.strokeBounds without strokeScaling and zoomed view', function() {
var path = new Shape.Circle({
center: [0, 0],
radius: 100,
strokeColor: 'black',
strokeWidth: 15,
strokeScaling: false
});
view.zoom = 2;
equals(path.strokeBounds,
new Rectangle(-103.75, -103.75, 207.5, 207.5),
'path.strokeBounds with zoomed view');
view.zoom = 1;
equals(path.strokeBounds,
new Rectangle(-107.5, -107.5, 215, 215),
'path.strokeBounds without zoomed view');
});
test('path.bounds', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74)),
new Segment(new Point(205, 420.94482421875), new Point(66.7890625, -12.72802734375), new Point(-79, 15.05517578125))
]);
// Test both closed and open paths, as the bounds for them differ
path.closed = false;
equals(path.bounds,
new Rectangle(121, 275.068, 149.49305, 145.87682),
'open path.bounds');
equals(path.position,
new Point(195.74653, 348.00641),
'open path.position');
// Test both closed and open paths, as the bounds for them differ
path.closed = true;
equals(path.bounds,
new Rectangle(114.82725, 275.068, 155.6658, 148.12773),
'closed path.bounds');
equals(path.position,
new Point(192.66015, 349.13186),
'closed path.position');
// Scale the path by 0.5 and check bounds
path.scale(0.5);
equals(path.bounds,
new Rectangle(153.7437, 312.09993, 77.8329, 74.06386),
'scaled path.bounds');
// Move the path to another position and check bounds
path.position = [100, 100];
equals(path.bounds,
new Rectangle(61.08355, 62.96807, 77.8329, 74.06386),
'moved path.bounds');
// Set new bounds and check segment list as result of resizing / positioning
path.bounds = { x: 100, y: 100, width: 200, height: 200 };
equals(path.segments.toString(),
'{ point: { x: 107.93077, y: 179.56917 }, handleIn: { x: -24.41127, y: 51.30707 }, handleOut: { x: 39.52904, y: -83.08194 } },{ point: { x: 271.10084, y: 160.66656 }, handleIn: { x: -53.96176, y: -99.91377 }, handleOut: { x: 53.96176, y: 99.91377 } },{ point: { x: 215.85428, y: 296.96086 }, handleIn: { x: 85.81084, y: -17.18521 }, handleOut: { x: -101.49949, y: 20.32729 } }',
'resized path.segments');
// Now rotate by 40 degrees and test bounds and segments again.
path.rotate(40);
equals(path.bounds,
new Rectangle(92.38102, 106.78972, 191.48071, 203.66876),
'rotated path.bounds');
equals(path.segments.toString(),
'{ point: { x: 142.60356, y: 125.16811 }, handleIn: { x: -51.67967, y: 23.61224 }, handleOut: { x: 83.68504, y: -38.23568 } },{ point: { x: 279.74945, y: 215.57158 }, handleIn: { x: 22.88623, y: -111.22434 }, handleOut: { x: -22.88623, y: 111.22434 } },{ point: { x: 149.81984, y: 284.46726 }, handleIn: { x: 76.78135, y: 41.99351 }, handleOut: { x: -90.81925, y: -49.67101 } }',
'roated path.segments');
});
test('path.strokeBounds on path without stroke', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74)),
new Segment(new Point(205, 420.94482421875), new Point(66.7890625, -12.72802734375), new Point(-79, 15.05517578125))
]);
equals(path.strokeBounds, new Rectangle(121, 275.068, 149.49305, 145.87682));
});
test('path.strokeBounds on path with single segment and stroke color', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625))
]);
path.strokeColor = 'black';
equals(path.strokeBounds, new Rectangle(121, 334, 0, 0));
});
test('path.strokeBounds on closed path with single segment and stroke color', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(19, 38), new Point(30.7666015625, -61.53369140625))
]);
path.strokeColor = 'black';
path.closed = true;
equals(path.strokeBounds, new Rectangle(120.44098, 312.88324 , 19.97544, 30.53977));
});
test('path.strokeBounds with corners and miter limit', function() {
var path = new Path({
pathData: 'M47,385c120,-100 120,-100 400,-40c-280,140 -280,140 -400,40z',
strokeWidth: 5,
strokeJoin: "miter",
strokeColor: "black"
});
equals(path.strokeBounds, new Rectangle(43.09488, 301.5525, 411.3977, 156.57543));
});
test('path.bounds & path.strokeBounds with stroke styles', function() {
function makePath() {
var path = new Path();
path.moveTo(200, 50);
path.lineTo(230, 100);
path.lineTo(250, 50);
path.lineTo(280, 110);
path.arcTo([250, 20], false);
path.rotate(-5);
path.strokeWidth = 30;
path.miterLimit = 3;
return path;
}
var path = makePath();
path.fullySelected = true;
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 16.78419, 113.50622, 90.96766),
'butt/round path.bounds');
equals(path.strokeBounds,
new Rectangle(186.87242, 1.78419, 140.64705, 120.96766),
'butt/round path.strokeBounds');
var path = makePath().translate(150, 0);
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 16.78419, 113.50622, 90.96766),
'butt/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(336.87242, 1.78419, 140.64705, 119.73034),
'butt/bevel path.strokeBounds');
var path = makePath().translate(300, 0);
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 16.78419, 113.50622, 90.96766),
'butt/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(486.87242, 1.78419, 140.64705, 133.64882),
'butt/miter path.strokeBounds');
var path = makePath().translate(0, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 166.78419, 113.50622, 90.96766),
'square/round path.bounds');
equals(path.strokeBounds,
new Rectangle(178.06332, 151.78419, 149.45615, 120.96766),
'square/strokeBounds path.bounds');
var path = makePath().translate(150, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 166.78419, 113.50622, 90.96766),
'square/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(328.06332, 151.78419, 149.45615, 119.73034),
'square/bevel path.strokeBounds');
var path = makePath().translate(300, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 166.78419, 113.50622, 90.96766),
'square/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(478.06332, 151.78419, 149.45615, 133.64882),
'square/miter path.strokeBounds');
var path = makePath().translate(0, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 316.78419, 113.50622, 90.96766),
'round/round path.bounds');
equals(path.strokeBounds,
new Rectangle(184.01325, 301.78419, 143.50622, 120.96766),
'round/round path.strokeBounds');
var path = makePath().translate(150, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 316.78419, 113.50622, 90.96766),
'round/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(334.01325, 301.78419, 143.50622, 119.73034),
'round/bevel path.strokeBounds');
var path = makePath().translate(300, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 316.78419, 113.50622, 90.96766),
'round/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(484.01325, 301.78419, 143.50622, 133.64882),
'round/miter path.strokeBounds');
});
test('path.strokeBounds with rectangles', function() {
var path = new paper.Path.Rectangle({
point: [100, 100],
size: [100, 100],
strokeWidth: 50,
strokeColor: 'black'
});
equals(path.strokeBounds,
new Rectangle(75, 75, 150, 150),
'path.strokeBounds');
});
test('path.strokeBounds without strokeScaling and zoomed view', function() {
var path = new Path.Circle({
center: [0, 0],
radius: 100,
strokeColor: 'black',
strokeWidth: 15,
strokeScaling: false
});
view.zoom = 2;
new Path.Rectangle({
rectangle: path.strokeBounds,
strokeColor: 'red',
strokeScaling: false
});
equals(path.strokeBounds,
new Rectangle(-103.75, -103.75, 207.5, 207.5),
'path.strokeBounds with zoomed view');
view.zoom = 1;
equals(path.strokeBounds,
new Rectangle(-107.5, -107.5, 215, 215),
'path.strokeBounds without zoomed view');
});

View file

@ -12,6 +12,29 @@
QUnit.module('Path');
test('path.length', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74))
]);
var length = path.length;
equals(length, 172.10112809179614, 'path.length');
var t = path.curves[0].getTimeAt(length / 4);
equals(t, 0.2255849553116685, 'path.curves[0].getTimeAt(length / 4)');
});
test('curve.getTimeAt() with straight curve', function() {
var path = new Path();
path.moveTo(100, 100);
path.lineTo(500, 500);
var curve = path.curves[0];
var length = curve.length;
var t = curve.getTimeAt(length / 3);
equals(t, 0.3869631475722452);
});
test('path.join(path)', function() {
var path = new Path();
path.add(0, 0);
@ -268,3 +291,227 @@ test('Simplifying a path with three segments of the same position should not thr
return path.segments.length;
}, 1);
});
QUnit.module('Path Curves');
test('path.curves synchronisation', function() {
var path = new Path();
path.add(new Point(100, 100));
equals(path.segments.toString(), "{ point: { x: 100, y: 100 } }", "path.segments: path.add(new Point(100, 100));");
equals(path.curves.toString(), "", "path.curves: path.add(new Point(100, 100));");
path.insert(0, new Point(0, 100));
equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }", "path.segments: path.insert(0, new Point(0, 100));");
equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } }", "path.curves: path.insert(0, new Point(0, 100));");
path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});
equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }", "path.segments: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});");
equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } }", "path.curves: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});");
path.closed = true;
equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }", "path.segments: path.closed = true;");
equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }", "path.curves: path.closed = true;");
path.removeSegments(2, 3);
equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } }", "path.segments: path.removeSegments(2, 3);");
equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 0, y: 100 } }", "path.curves: path.removeSegments(2, 3);");
path.add(new Point(100, 100));
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
var length = 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');
var points = [];
for (var i = 0; i < 40; i++)
points.push(Point.random());
var path = new Path(points);
equals(path.segments.length, 40, 'segments.length');
equals(path.curves.length, 39, 'curves.length');
path.removeSegments();
equals(path.segments.length, 0, 'segments.length');
equals(path.curves.length, 0, 'curves.length');
});
test('path.curves on closed paths', function() {
var path = new Path.Circle(new Point(100, 100) , 100);
equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle1: { x: 0, y: -55.22847 }, handle2: { x: -55.22847, y: 0 }, point2: { x: 100, y: 0 } },{ point1: { x: 100, y: 0 }, handle1: { x: 55.22847, y: 0 }, handle2: { x: 0, y: -55.22847 }, point2: { x: 200, y: 100 } },{ point1: { x: 200, y: 100 }, handle1: { x: 0, y: 55.22847 }, handle2: { x: 55.22847, y: 0 }, point2: { x: 100, y: 200 } },{ point1: { x: 100, y: 200 }, handle1: { x: -55.22847, y: 0 }, handle2: { x: 0, y: 55.22847 }, point2: { x: 0, y: 100 } }");
path.removeSegments(0, 1);
equals(path.curves.toString(), "{ point1: { x: 100, y: 0 }, handle1: { x: 55.22847, y: 0 }, handle2: { x: 0, y: -55.22847 }, point2: { x: 200, y: 100 } },{ point1: { x: 200, y: 100 }, handle1: { x: 0, y: 55.22847 }, handle2: { x: 55.22847, y: 0 }, point2: { x: 100, y: 200 } },{ point1: { x: 100, y: 200 }, handle1: { x: -55.22847, y: 0 }, handle2: { x: -55.22847, y: 0 }, point2: { x: 100, y: 0 } }");
});
test('path.flatten(maxDistance)', function() {
var path = new Path.Circle(new Size(80, 50), 35);
// Convert its curves to points, with a max distance of 20:
path.flatten(20);
equals(function() {
return path.lastSegment.point.equals(path.firstSegment.point);
}, false, 'The points of the last and first segments should not be the same.');
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.');
});
test('Curve list after removing a segment - 1', function() {
var path = new paper.Path([0, 0], [1, 1], [2, 2]);
var prevCurves = path.curves.slice();
equals(function() {
return path.curves.length;
}, 2, 'After creating a path with three segments, we should have two curves. By accessing path.curves we also make sure the curves are created internally.');
equals(function() {
return path.segments[1].remove();
}, true, 'Removing the paths second segment should be successful.');
equals(function() {
return path.curves.length;
}, 1, 'After removing the middle segment, we should be left with one curve.');
equals(function() {
return path.curves[0] === prevCurves[0];
}, true, 'The remaining curve should be the same as in the previous state of the curves array.');
equals(function() {
return path.curves[0].path === path;
}, true, 'The remaining curve should stay linked to the path.');
equals(function() {
return prevCurves[1].path === null;
}, true, 'The removed curve should not stay linked to the path.');
});
test('Curve list after removing a segment - 2', function() {
var path = new paper.Path([0, 0], [1, 1], [2, 2]);
equals(function() {
return path.curves.length;
}, 2, 'After creating a path with three segments, we should have two curves. By accessing path.curves we also make sure the curves are created internally.');
equals(function() {
return path.lastSegment.remove();
}, true, 'Removing the last segment should be successful.');
equals(function() {
return path.curves.length;
}, 1, 'After removing the last segment, we should be left with one curve.');
equals(function() {
return path.lastSegment.remove();
}, true, 'Removing last segment should be successful.');
equals(function() {
return path.curves.length;
}, 0, 'After removing the last segment, we should be left with no curves.');
equals(function() {
return path.lastSegment.remove();
}, true, 'Removing the final remaining segment should be successful.');
equals(function() {
return path.curves.length;
}, 0, 'After removing all segments, we should be left with no curves.');
path.addSegment([0, 0]);
path.addSegment([1, 1]);
equals(function() {
return path.curves.length;
}, 1, 'After adding two new segments, we should have one curve again.');
path.addSegment([2, 2]);
equals(function() {
return path.curves.length;
}, 2, 'After adding a new segment, we should have two curves again.');
equals(function() {
return path.curves[1].segment1 === path.curves[0].segment2;
}, true, "The newly created curve's first segment needs to be the same as the previous curve's second segment.");
path.addSegments([[3, 3], [4, 4]]);
equals(function() {
return path.curves.length;
}, 4, 'After adding two new segments at the end, we should have four curves now.');
});
test('Splitting a straight path should produce segments without handles', function() {
var path1 = new Path.Line([0, 0], [50, 50]);
var path2 = path1.split(0, 0.5);
equals(function() {
return !path1.lastSegment.hasHandles() && !path2.firstSegment.hasHandles();
}, true);
});
test('Splitting a path with one curve in the middle result in two paths of the same length with one curve each', function() {
var path1 = new Path.Line([0, 0], [100, 100]);
var path2 = path1.split(path1.getLocationAt(path1.length / 2));
equals(function() {
return path1.curves.length;
}, 1);
equals(function() {
return path2.curves.length;
}, 1);
equals(function() {
return path1.length === path2.length;
}, true);
});
QUnit.module('Path Drawing Commands');
test('path.lineTo(point);', function() {
var path = new Path();
path.moveTo([50, 50]);
path.lineTo([100, 100]);
equals(path.segments.toString(), '{ point: { x: 50, y: 50 } },{ point: { x: 100, y: 100 } }');
});
test('path.arcTo(from, through, to);', function() {
var path = new Path();
path.moveTo([0, 20]);
path.arcTo([75, 75], [100, 0]);
equals(path.segments.toString(), '{ point: { x: 0, y: 20 }, handleOut: { x: -2.62559, y: 23.01251 } },{ point: { x: 30.89325, y: 74.75812 }, handleIn: { x: -21.05455, y: -9.65273 }, handleOut: { x: 21.05455, y: 9.65273 } },{ point: { x: 92.54397, y: 62.42797 }, handleIn: { x: -15.72238, y: 17.00811 }, handleOut: { x: 15.72238, y: -17.00811 } },{ point: { x: 100, y: 0 }, handleIn: { x: 11.27458, y: 20.23247 } }');
});
test('path.arcTo(from, through, to); where from, through and to all share the same y position and through lies in between from and to', function() {
var path = new Path();
path.strokeColor = 'black';
path.add([40, 75]);
path.arcTo([50, 75], [100, 75]);
equals(path.lastSegment.point.toString(), '{ x: 100, y: 75 }', 'We expect the last segment point to be at the position where we wanted to draw the arc to.');
});
test('path.arcTo(from, through, to); where from, through and to all share the same y position and through lies to the right of to', function() {
var path = new Path();
path.strokeColor = 'black';
path.add([40, 75]);
var error = null;
try {
path.arcTo([150, 75], [100, 75]);
} catch (e) {
error = e;
}
equals(error != null, true, 'We expect this arcTo() command to throw an error');
});
test('path.arcTo(from, through, to); where from, through and to all share the same y position and through lies to the left of to', function() {
var path = new Path();
path.strokeColor = 'black';
path.add([40, 75]);
var error = null;
try {
path.arcTo([10, 75], [100, 75]);
} catch (e) {
error = e;
}
equals(error != null, true, 'We expect this arcTo() command to throw an error');
});

View file

@ -1,258 +0,0 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
* http://scratchdisk.com/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
QUnit.module('Path Bounds');
test('path.bounds', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74)),
new Segment(new Point(205, 420.94482421875), new Point(66.7890625, -12.72802734375), new Point(-79, 15.05517578125))
]);
// Test both closed and open paths, as the bounds for them differ
path.closed = false;
equals(path.bounds,
new Rectangle(121, 275.068, 149.49305, 145.87682),
'open path.bounds');
equals(path.position,
new Point(195.74653, 348.00641),
'open path.position');
// Test both closed and open paths, as the bounds for them differ
path.closed = true;
equals(path.bounds,
new Rectangle(114.82725, 275.068, 155.6658, 148.12773),
'closed path.bounds');
equals(path.position,
new Point(192.66015, 349.13186),
'closed path.position');
// Scale the path by 0.5 and check bounds
path.scale(0.5);
equals(path.bounds,
new Rectangle(153.7437, 312.09993, 77.8329, 74.06386),
'scaled path.bounds');
// Move the path to another position and check bounds
path.position = [100, 100];
equals(path.bounds,
new Rectangle(61.08355, 62.96807, 77.8329, 74.06386),
'moved path.bounds');
// Set new bounds and check segment list as result of resizing / positioning
path.bounds = { x: 100, y: 100, width: 200, height: 200 };
equals(path.segments.toString(),
'{ point: { x: 107.93077, y: 179.56917 }, handleIn: { x: -24.41127, y: 51.30707 }, handleOut: { x: 39.52904, y: -83.08194 } },{ point: { x: 271.10084, y: 160.66656 }, handleIn: { x: -53.96176, y: -99.91377 }, handleOut: { x: 53.96176, y: 99.91377 } },{ point: { x: 215.85428, y: 296.96086 }, handleIn: { x: 85.81084, y: -17.18521 }, handleOut: { x: -101.49949, y: 20.32729 } }',
'resized path.segments');
// Now rotate by 40 degrees and test bounds and segments again.
path.rotate(40);
equals(path.bounds,
new Rectangle(92.38102, 106.78972, 191.48071, 203.66876),
'rotated path.bounds');
equals(path.segments.toString(),
'{ point: { x: 142.60356, y: 125.16811 }, handleIn: { x: -51.67967, y: 23.61224 }, handleOut: { x: 83.68504, y: -38.23568 } },{ point: { x: 279.74945, y: 215.57158 }, handleIn: { x: 22.88623, y: -111.22434 }, handleOut: { x: -22.88623, y: 111.22434 } },{ point: { x: 149.81984, y: 284.46726 }, handleIn: { x: 76.78135, y: 41.99351 }, handleOut: { x: -90.81925, y: -49.67101 } }',
'roated path.segments');
});
test('path.strokeBounds on path without stroke', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74)),
new Segment(new Point(205, 420.94482421875), new Point(66.7890625, -12.72802734375), new Point(-79, 15.05517578125))
]);
equals(path.strokeBounds, new Rectangle(121, 275.068, 149.49305, 145.87682));
});
test('path.strokeBounds on path with single segment and stroke color', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625))
]);
path.strokeColor = 'black';
equals(path.strokeBounds, new Rectangle(121, 334, 0, 0));
});
test('path.strokeBounds on closed path with single segment and stroke color', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(19, 38), new Point(30.7666015625, -61.53369140625))
]);
path.strokeColor = 'black';
path.closed = true;
equals(path.strokeBounds, new Rectangle(120.44098, 312.88324 , 19.97544, 30.53977));
});
test('path.strokeBounds with corners and miter limit', function() {
var path = new Path({
pathData: 'M47,385c120,-100 120,-100 400,-40c-280,140 -280,140 -400,40z',
strokeWidth: 5,
strokeJoin: "miter",
strokeColor: "black"
});
equals(path.strokeBounds, new Rectangle(43.09488, 301.5525, 411.3977, 156.57543));
});
test('path.bounds & path.strokeBounds with stroke styles', function() {
function makePath() {
var path = new Path();
path.moveTo(200, 50);
path.lineTo(230, 100);
path.lineTo(250, 50);
path.lineTo(280, 110);
path.arcTo([250, 20], false);
path.rotate(-5);
path.strokeWidth = 30;
path.miterLimit = 3;
return path;
}
var path = makePath();
path.fullySelected = true;
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 16.78419, 113.50622, 90.96766),
'butt/round path.bounds');
equals(path.strokeBounds,
new Rectangle(186.87242, 1.78419, 140.64705, 120.96766),
'butt/round path.strokeBounds');
var path = makePath().translate(150, 0);
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 16.78419, 113.50622, 90.96766),
'butt/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(336.87242, 1.78419, 140.64705, 119.73034),
'butt/bevel path.strokeBounds');
var path = makePath().translate(300, 0);
path.strokeColor = 'black';
path.strokeCap = 'butt';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 16.78419, 113.50622, 90.96766),
'butt/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(486.87242, 1.78419, 140.64705, 133.64882),
'butt/miter path.strokeBounds');
var path = makePath().translate(0, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 166.78419, 113.50622, 90.96766),
'square/round path.bounds');
equals(path.strokeBounds,
new Rectangle(178.06332, 151.78419, 149.45615, 120.96766),
'square/strokeBounds path.bounds');
var path = makePath().translate(150, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 166.78419, 113.50622, 90.96766),
'square/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(328.06332, 151.78419, 149.45615, 119.73034),
'square/bevel path.strokeBounds');
var path = makePath().translate(300, 150);
path.strokeColor = 'black';
path.strokeCap = 'square';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 166.78419, 113.50622, 90.96766),
'square/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(478.06332, 151.78419, 149.45615, 133.64882),
'square/miter path.strokeBounds');
var path = makePath().translate(0, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'round';
equals(path.bounds,
new Rectangle(199.01325, 316.78419, 113.50622, 90.96766),
'round/round path.bounds');
equals(path.strokeBounds,
new Rectangle(184.01325, 301.78419, 143.50622, 120.96766),
'round/round path.strokeBounds');
var path = makePath().translate(150, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'bevel';
equals(path.bounds,
new Rectangle(349.01325, 316.78419, 113.50622, 90.96766),
'round/bevel path.bounds');
equals(path.strokeBounds,
new Rectangle(334.01325, 301.78419, 143.50622, 119.73034),
'round/bevel path.strokeBounds');
var path = makePath().translate(300, 300);
path.strokeColor = 'black';
path.strokeCap = 'round';
path.strokeJoin = 'miter';
equals(path.bounds,
new Rectangle(499.01325, 316.78419, 113.50622, 90.96766),
'round/miter path.bounds');
equals(path.strokeBounds,
new Rectangle(484.01325, 301.78419, 143.50622, 133.64882),
'round/miter path.strokeBounds');
});
test('path.strokeBounds with rectangles', function() {
var path = new paper.Path.Rectangle({
point: [100, 100],
size: [100, 100],
strokeWidth: 50,
strokeColor: 'black'
});
equals(path.strokeBounds,
new Rectangle(75, 75, 150, 150),
'path.strokeBounds');
});
test('path.strokeBounds without strokeScaling and zoomed view', function() {
var path = new Path.Circle({
center: [0, 0],
radius: 100,
strokeColor: 'black',
strokeWidth: 15,
strokeScaling: false
});
view.zoom = 2;
new Path.Rectangle({
rectangle: path.strokeBounds,
strokeColor: 'red',
strokeScaling: false
});
equals(path.strokeBounds,
new Rectangle(-103.75, -103.75, 207.5, 207.5),
'path.strokeBounds with zoomed view');
view.zoom = 1;
equals(path.strokeBounds,
new Rectangle(-107.5, -107.5, 215, 215),
'path.strokeBounds without zoomed view');
});

View file

@ -10,7 +10,7 @@
* All rights reserved.
*/
QUnit.module('Predefined Path Shapes');
QUnit.module('Path Constructors');
test('new Path.Rectangle([50, 50], [100, 100])', function() {
var path = new Path.Rectangle([50, 50], [100, 100]);
@ -36,13 +36,13 @@ test('new Path.Circle({ center: [100, 100], radius: 50 })', function() {
});
test('new Path.Ellipse(rect)', function() {
var rect = new Rectangle([500, 500], [1000, 750])
var rect = new Rectangle([500, 500], [1000, 750]);
var path = new Path.Ellipse(rect);
equals(path.segments.toString(), '{ point: { x: 500, y: 875 }, handleIn: { x: 0, y: 207.10678 }, handleOut: { x: 0, y: -207.10678 } },{ point: { x: 1000, y: 500 }, handleIn: { x: -276.14237, y: 0 }, handleOut: { x: 276.14237, y: 0 } },{ point: { x: 1500, y: 875 }, handleIn: { x: 0, y: -207.10678 }, handleOut: { x: 0, y: 207.10678 } },{ point: { x: 1000, y: 1250 }, handleIn: { x: 276.14237, y: 0 }, handleOut: { x: -276.14237, y: 0 } }');
});
test('new Path.Rectangle(rectangle, radius)', function() {
var rectangle = new Rectangle([50, 50], [200, 100])
var rectangle = new Rectangle([50, 50], [200, 100]);
var path = new Path.Rectangle(rectangle, 20);
equals(path.segments.toString(), '{ point: { x: 70, y: 150 }, handleOut: { x: -11.04569, y: 0 } },{ point: { x: 50, y: 130 }, handleIn: { x: 0, y: 11.04569 } },{ point: { x: 50, y: 70 }, handleOut: { x: 0, y: -11.04569 } },{ point: { x: 70, y: 50 }, handleIn: { x: -11.04569, y: 0 } },{ point: { x: 230, y: 50 }, handleOut: { x: 11.04569, y: 0 } },{ point: { x: 250, y: 70 }, handleIn: { x: 0, y: -11.04569 } },{ point: { x: 250, y: 130 }, handleOut: { x: 0, y: 11.04569 } },{ point: { x: 230, y: 150 }, handleIn: { x: 11.04569, y: 0 } }');
});
@ -60,7 +60,7 @@ test('new Path.Rectangle({ rectangle: rectangle, radius: radius })', function()
});
test('new Path.Rectangle(rect, size) - too large size', function() {
var rect = new Rectangle([50, 50], [200, 100])
var rect = new Rectangle([50, 50], [200, 100]);
var path = new Path.Rectangle(rect, 200);
equals(path.segments.toString(), '{ point: { x: 150, y: 150 }, handleOut: { x: -55.22847, y: 0 } },{ point: { x: 50, y: 100 }, handleIn: { x: 0, y: 27.61424 } },{ point: { x: 50, y: 100 }, handleOut: { x: 0, y: -27.61424 } },{ point: { x: 150, y: 50 }, handleIn: { x: -55.22847, y: 0 } },{ point: { x: 150, y: 50 }, handleOut: { x: 55.22847, y: 0 } },{ point: { x: 250, y: 100 }, handleIn: { x: 0, y: -27.61424 } },{ point: { x: 250, y: 100 }, handleOut: { x: 0, y: 27.61424 } },{ point: { x: 150, y: 150 }, handleIn: { x: 55.22847, y: 0 } }');
});

View file

@ -1,64 +0,0 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
* http://scratchdisk.com/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
QUnit.module('Path Drawing Commands');
test('path.lineTo(point);', function() {
var path = new Path();
path.moveTo([50, 50]);
path.lineTo([100, 100]);
equals(path.segments.toString(), '{ point: { x: 50, y: 50 } },{ point: { x: 100, y: 100 } }');
});
test('path.arcTo(from, through, to);', function() {
var path = new Path();
path.moveTo([0, 20]);
path.arcTo([75, 75], [100, 0]);
equals(path.segments.toString(), '{ point: { x: 0, y: 20 }, handleOut: { x: -2.62559, y: 23.01251 } },{ point: { x: 30.89325, y: 74.75812 }, handleIn: { x: -21.05455, y: -9.65273 }, handleOut: { x: 21.05455, y: 9.65273 } },{ point: { x: 92.54397, y: 62.42797 }, handleIn: { x: -15.72238, y: 17.00811 }, handleOut: { x: 15.72238, y: -17.00811 } },{ point: { x: 100, y: 0 }, handleIn: { x: 11.27458, y: 20.23247 } }');
});
test('path.arcTo(from, through, to); where from, through and to all share the same y position and through lies in between from and to', function() {
var path = new Path();
path.strokeColor = 'black';
path.add([40, 75]);
path.arcTo([50, 75], [100, 75]);
equals(path.lastSegment.point.toString(), '{ x: 100, y: 75 }', 'We expect the last segment point to be at the position where we wanted to draw the arc to.');
});
test('path.arcTo(from, through, to); where from, through and to all share the same y position and through lies to the right of to', function() {
var path = new Path();
path.strokeColor = 'black';
path.add([40, 75]);
var error = null;
try {
path.arcTo([150, 75], [100, 75]);
} catch (e) {
error = e;
}
equals(error != null, true, 'We expect this arcTo() command to throw an error');
});
test('path.arcTo(from, through, to); where from, through and to all share the same y position and through lies to the left of to', function() {
var path = new Path();
path.strokeColor = 'black';
path.add([40, 75]);
var error = null;
try {
path.arcTo([10, 75], [100, 75]);
} catch (e) {
error = e;
}
equals(error != null, true, 'We expect this arcTo() command to throw an error');
});

View file

@ -1,36 +0,0 @@
/*
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
* http://scratchdisk.com/ & http://jonathanpuckey.com/
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
QUnit.module('Path Length');
test('path.length', function() {
var path = new Path([
new Segment(new Point(121, 334), new Point(-19, 38), new Point(30.7666015625, -61.53369140625)),
new Segment(new Point(248, 320), new Point(-42, -74), new Point(42, 74))
]);
var length = path.length;
equals(length, 172.10112809179614, 'path.length');
var t = path.curves[0].getTimeAt(length / 4);
equals(t, 0.2255849553116685, 'path.curves[0].getTimeAt(length / 4)');
});
test('curve.getTimeAt() with straight curve', function() {
var path = new Path();
path.moveTo(100, 100);
path.lineTo(500, 500);
var curve = path.curves[0];
var length = curve.length;
var t = curve.getTimeAt(length / 3);
equals(t, 0.3869631475722452);
});

View file

@ -32,13 +32,11 @@
/*#*/ include('Segment.js');
/*#*/ include('Path.js');
/*#*/ include('Path_Shapes.js');
/*#*/ include('Path_Drawing_Commands.js');
/*#*/ include('Path_Constructors.js');
/*#*/ include('Path_Curves.js');
/*#*/ include('Path_Bounds.js');
/*#*/ include('Path_Length.js');
/*#*/ include('Path_Intersections.js');
/*#*/ include('Path_Boolean.js');
/*#*/ include('PathItem_Contains.js');
/*#*/ include('Shape.js');
@ -49,8 +47,6 @@
/*#*/ include('CompoundPath.js');
/*#*/ include('PathItem_Contains.js');
/*#*/ include('SymbolItem.js');
/*#*/ include('Raster.js');