Merge branch 'develop'

This commit is contained in:
Jürg Lehni 2017-10-08 17:48:11 +02:00
commit f677cd37ea
19 changed files with 193 additions and 85 deletions

38
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,38 @@
<!--
Questions:
https://groups.google.com/group/paperjs
https://gitter.im/paperjs/paper.js
-->
# Description/Steps to reproduce
<!--
If feature: A description of the feature
If bug: Steps to reproduce
-->
# Link to reproduction test-case
<!--
Link to a test-case for reproduction
Note: Failure to provide a test-case for reproduction purposes will result in
the issue being closed.
-->
# Expected result
<!--
Also include actual results if bug
-->
# Additional information
<!--
Please include the versions of Operating System and Browser that the issue is
encountered on.
Examples:
macOS 10.12.6, Chrome 60.0.3112.113
Windows 10 Pro 10586.962, Edge 25.10586.672.0
-->

24
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,24 @@
### Description
#### Related issues
<!--
Please use the following link syntaxes:
- relates to #49 (to reference issues in the current repository)
-->
- relates to <link_to_referenced_issue>
### Checklist
<!--
- Please mark your choice with an "x" (i.e. [x], see
https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments)
- PR's without test coverage will be closed.
-->
- [ ] New tests added or existing tests modified to cover all changes
- [ ] Code conforms with the [style
guide](https://github.com/paperjs/paper.js/blob/develop/RULES.md)

View file

@ -1,5 +1,17 @@
# Change Log
## `0.11.5`
### Fixed
- Fix `Curve#isSelected()` to correctly reflect the state of `#handle1` (#1378).
- Key Events: Fix auto-filling issue on Chrome (#1358, #1365).
- Boolean: Check that overlaps are on the right path (#1321).
- Boolean: Add better filtering for invalid segments (#1385).
### Added
- Node.js: Add JPEG support to exportFrames() (#1166).
## `0.11.4`
### Changed

3
RULES.md Normal file
View file

@ -0,0 +1,3 @@
# Paper.js Style Guide
Coming *soon*.

48
dist/paper-core.js vendored
View file

@ -1,5 +1,5 @@
/*!
* Paper.js v0.11.4 - The Swiss Army Knife of Vector Graphics Scripting.
* Paper.js v0.11.5 - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
@ -9,7 +9,7 @@
*
* All rights reserved.
*
* Date: Wed Jun 7 16:56:44 2017 +0200
* Date: Thu Oct 5 16:16:29 2017 +0200
*
***
*
@ -778,7 +778,7 @@ var PaperScope = Base.extend({
}
},
version: "0.11.4",
version: "0.11.5",
getView: function() {
var project = this.project;
@ -6133,7 +6133,7 @@ var Curve = Base.extend({
isSelected: function() {
return this.getPoint1().isSelected()
&& this.getHandle2().isSelected()
&& this.getHandle1().isSelected()
&& this.getHandle2().isSelected()
&& this.getPoint2().isSelected();
},
@ -10350,16 +10350,20 @@ PathItem.inject(new function() {
function collect(inter, end) {
while (inter && inter !== end) {
var other = inter._segment,
path = other._path,
next = other.getNext() || path && path.getFirstSegment(),
nextInter = next && next._intersection;
if (other !== segment && (isStart(other) || isStart(next)
|| next && (isValid(other) && (isValid(next)
|| nextInter && isValid(nextInter._segment))))) {
crossings.push(other);
path = other && other._path;
if (path) {
var next = other.getNext() || path.getFirstSegment(),
nextInter = next._intersection;
if (other !== segment && (isStart(other)
|| isStart(next)
|| next && (isValid(other) && (isValid(next)
|| nextInter && isValid(nextInter._segment))))
) {
crossings.push(other);
}
if (collectStarts)
starts.push(other);
}
if (collectStarts)
starts.push(other);
inter = inter._next;
}
}
@ -10450,7 +10454,8 @@ PathItem.inject(new function() {
visited.length = 0;
do {
seg = branch && branch.crossings.shift();
if (!seg) {
if (!seg || !seg._path) {
seg = null;
branch = branches.pop();
if (branch) {
visited = branch.visited;
@ -10516,9 +10521,9 @@ PathItem.inject(new function() {
var children = this._children,
paths = children || [this];
function hasOverlap(seg) {
function hasOverlap(seg, path) {
var inter = seg && seg._intersection;
return inter && inter._overlap;
return inter && inter._overlap && inter._path === path;
}
var hasOverlaps = false,
@ -10534,10 +10539,12 @@ PathItem.inject(new function() {
return inter.hasOverlap();
}, clearCurves);
for (var i = overlaps.length - 1; i >= 0; i--) {
var seg = overlaps[i]._segment,
var overlap = overlaps[i],
path = overlap._path,
seg = overlap._segment,
prev = seg.getPrevious(),
next = seg.getNext();
if (hasOverlap(prev) && hasOverlap(next)) {
if (hasOverlap(prev, path) && hasOverlap(next, path)) {
seg.remove();
prev._handleOut._set(0, 0);
next._handleIn._set(0, 0);
@ -13083,8 +13090,9 @@ var Key = new function() {
key = /^U\+/.test(key)
? String.fromCharCode(parseInt(key.substr(2), 16))
: /^Arrow[A-Z]/.test(key) ? key.substr(5)
: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
: key;
: key === 'Unidentified' || key === undefined
? String.fromCharCode(event.keyCode)
: key;
return keyLookup[key] ||
(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
}

48
dist/paper-full.js vendored
View file

@ -1,5 +1,5 @@
/*!
* Paper.js v0.11.4 - The Swiss Army Knife of Vector Graphics Scripting.
* Paper.js v0.11.5 - The Swiss Army Knife of Vector Graphics Scripting.
* http://paperjs.org/
*
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
@ -9,7 +9,7 @@
*
* All rights reserved.
*
* Date: Wed Jun 7 16:56:44 2017 +0200
* Date: Thu Oct 5 16:16:29 2017 +0200
*
***
*
@ -778,7 +778,7 @@ var PaperScope = Base.extend({
}
},
version: "0.11.4",
version: "0.11.5",
getView: function() {
var project = this.project;
@ -6133,7 +6133,7 @@ var Curve = Base.extend({
isSelected: function() {
return this.getPoint1().isSelected()
&& this.getHandle2().isSelected()
&& this.getHandle1().isSelected()
&& this.getHandle2().isSelected()
&& this.getPoint2().isSelected();
},
@ -10350,16 +10350,20 @@ PathItem.inject(new function() {
function collect(inter, end) {
while (inter && inter !== end) {
var other = inter._segment,
path = other._path,
next = other.getNext() || path && path.getFirstSegment(),
nextInter = next && next._intersection;
if (other !== segment && (isStart(other) || isStart(next)
|| next && (isValid(other) && (isValid(next)
|| nextInter && isValid(nextInter._segment))))) {
crossings.push(other);
path = other && other._path;
if (path) {
var next = other.getNext() || path.getFirstSegment(),
nextInter = next._intersection;
if (other !== segment && (isStart(other)
|| isStart(next)
|| next && (isValid(other) && (isValid(next)
|| nextInter && isValid(nextInter._segment))))
) {
crossings.push(other);
}
if (collectStarts)
starts.push(other);
}
if (collectStarts)
starts.push(other);
inter = inter._next;
}
}
@ -10450,7 +10454,8 @@ PathItem.inject(new function() {
visited.length = 0;
do {
seg = branch && branch.crossings.shift();
if (!seg) {
if (!seg || !seg._path) {
seg = null;
branch = branches.pop();
if (branch) {
visited = branch.visited;
@ -10516,9 +10521,9 @@ PathItem.inject(new function() {
var children = this._children,
paths = children || [this];
function hasOverlap(seg) {
function hasOverlap(seg, path) {
var inter = seg && seg._intersection;
return inter && inter._overlap;
return inter && inter._overlap && inter._path === path;
}
var hasOverlaps = false,
@ -10534,10 +10539,12 @@ PathItem.inject(new function() {
return inter.hasOverlap();
}, clearCurves);
for (var i = overlaps.length - 1; i >= 0; i--) {
var seg = overlaps[i]._segment,
var overlap = overlaps[i],
path = overlap._path,
seg = overlap._segment,
prev = seg.getPrevious(),
next = seg.getNext();
if (hasOverlap(prev) && hasOverlap(next)) {
if (hasOverlap(prev, path) && hasOverlap(next, path)) {
seg.remove();
prev._handleOut._set(0, 0);
next._handleIn._set(0, 0);
@ -13083,8 +13090,9 @@ var Key = new function() {
key = /^U\+/.test(key)
? String.fromCharCode(parseInt(key.substr(2), 16))
: /^Arrow[A-Z]/.test(key) ? key.substr(5)
: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
: key;
: key === 'Unidentified' || key === undefined
? String.fromCharCode(event.keyCode)
: key;
return keyLookup[key] ||
(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());
}

View file

@ -24,7 +24,7 @@ http.createServer(function(request, response) {
intersection.translate(250, 0);
view.update();
}
var stream = canvas.createPNGStream();
var stream = canvas.pngStream();
stream.on('data', function(chunk) {
response.write(chunk);
});

View file

@ -17,7 +17,7 @@ raster.onLoad = function() {
// Saving the canvas to a file.
out = fs.createWriteStream(__dirname + '/canvas.png');
stream = canvas.createPNGStream();
stream = canvas.pngStream();
stream.on('data', function(chunk) {
out.write(chunk);

View file

@ -1,6 +1,6 @@
{
"name": "paper",
"version": "0.11.4",
"version": "0.11.5",
"description": "The Swiss Army Knife of Vector Graphics Scripting",
"license": "MIT",
"homepage": "http://paperjs.org",

@ -1 +1 @@
Subproject commit 167a945169b50bac5c709c4abb97b075085a5a16
Subproject commit afd2bbbf1cea00f1f94ff89c8a3dd370888ac705

@ -1 +1 @@
Subproject commit 5c2f0e0e816745a685d7f5367e4edcac75d8a66d
Subproject commit f6794e0749cfb65d5138f3512fc0eee755bc1829

View file

@ -81,8 +81,9 @@ var Key = new function() {
// Use short version for arrow keys: ArrowLeft -> Left
: /^Arrow[A-Z]/.test(key) ? key.substr(5)
// This is far from ideal, but what else can we do?
: key === 'Unidentified' ? String.fromCharCode(event.keyCode)
: key;
: key === 'Unidentified' || key === undefined
? String.fromCharCode(event.keyCode)
: key;
return keyLookup[key] ||
// Hyphenate camel-cased special keys, lower-case normal ones:
(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());

View file

@ -13,7 +13,7 @@
// Add some useful extensions to HTMLCanvasElement:
// - HTMLCanvasElement#type, so we can switch to a PDF canvas
// - Various Node-Canvas methods, routed through from HTMLCanvasElement:
// toBuffer, pngStream, createPNGStream, jpgStream, createJPGStream
// toBuffer, pngStream, createPNGStream, jpegStream, createJPEGStream
module.exports = function(self, requireName) {
var Canvas;
@ -55,11 +55,12 @@ module.exports = function(self, requireName) {
});
// Extend HTMLCanvasElement with useful methods from the underlying Canvas:
['toBuffer', 'pngStream', 'createPNGStream', 'jpgStream', 'createJPGStream']
.forEach(function(key) {
HTMLCanvasElement.prototype[key] = function() {
var canvas = idlUtils.implForWrapper(this)._canvas;
return canvas[key].apply(canvas, arguments);
};
});
var methods = ['toBuffer', 'pngStream', 'createPNGStream', 'jpegStream',
'createJPEGStream'];
methods.forEach(function(key) {
HTMLCanvasElement.prototype[key] = function() {
var canvas = idlUtils.implForWrapper(this)._canvas;
return canvas[key].apply(canvas, arguments);
};
});
};

View file

@ -67,7 +67,7 @@ module.exports = function(paper) {
},
/**
* @deprecated use use {@link #createCanvas(width, height)} instead.
* @deprecated, use use {@link #createCanvas(width, height)} instead.
*/
Canvas: '#createCanvas'
});
@ -87,9 +87,12 @@ module.exports = function(paper) {
fps: 30,
prefix: 'frame-',
amount: 1,
format: 'png' // Supported: 'png' or 'jpeg'
}, options);
if (!options.directory)
throw new Error('Missing options.directory');
if (options.format && !/^(jpeg|png)$/.test(options.format))
throw new Error('Unsupported format. Use "png" or "jpeg"');
var view = this,
count = 0,
frameDuration = 1 / options.fps,
@ -108,8 +111,9 @@ module.exports = function(paper) {
time: frameDuration * count,
count: count
}));
var file = path.join(options.directory, options.prefix +
(paddedStr + count).slice(-padding) + '.png');
var file = path.join(options.directory,
options.prefix + (paddedStr + count).slice(-padding)
+ '.' + options.format);
var out = view.exportImage(file, function() {
// Once the file has been closed, export the next fame:
var then = Date.now();
@ -140,8 +144,8 @@ module.exports = function(paper) {
exportImage: function(path, callback) {
this.update();
var out = fs.createWriteStream(path),
stream = this._element.createPNGStream();
// Pipe the png stream to the write stream:
format = /\.jp(e?)g$/.test(path) ? 'jpeg' : 'png',
stream = this._element[format + 'Stream']();
stream.pipe(out);
if (callback) {
out.on('close', callback);

View file

@ -17,7 +17,7 @@
// The paper.js version.
// NOTE: Adjust value here before calling `gulp publish`, which then updates and
// publishes the various JSON package files automatically.
var version = '0.11.4';
var version = '0.11.5';
// If this file is loaded in the browser, we're in load.js mode.
var load = typeof window === 'object';

View file

@ -341,7 +341,7 @@ var Curve = Base.extend(/** @lends Curve# */{
*/
isSelected: function() {
return this.getPoint1().isSelected()
&& this.getHandle2().isSelected()
&& this.getHandle1().isSelected()
&& this.getHandle2().isSelected()
&& this.getPoint2().isSelected();
},

View file

@ -825,21 +825,25 @@ PathItem.inject(new function() {
function collect(inter, end) {
while (inter && inter !== end) {
var other = inter._segment,
path = other._path,
next = other.getNext() || path && path.getFirstSegment(),
nextInter = next && next._intersection;
// See if this segment and the next are both not visited
// yet, or are bringing us back to the beginning, and are
// both valid, meaning they are part of the boolean result.
if (other !== segment && (isStart(other) || isStart(next)
|| next && (isValid(other) && (isValid(next)
// If the next segment isn't valid, its intersection
// to which we may switch might be, so check that.
|| nextInter && isValid(nextInter._segment))))) {
crossings.push(other);
path = other && other._path;
if (path) {
var next = other.getNext() || path.getFirstSegment(),
nextInter = next._intersection;
// See if this segment and the next are not visited yet,
// or are bringing us back to the start, and are both
// valid, meaning they're part of the boolean result.
if (other !== segment && (isStart(other)
|| isStart(next)
|| next && (isValid(other) && (isValid(next)
// If next segment isn't valid, its intersection
// to which we may switch may be, so check that.
|| nextInter && isValid(nextInter._segment))))
) {
crossings.push(other);
}
if (collectStarts)
starts.push(other);
}
if (collectStarts)
starts.push(other);
inter = inter._next;
}
}
@ -970,7 +974,8 @@ PathItem.inject(new function() {
// the list of crossings when the branch is created above.
do {
seg = branch && branch.crossings.shift();
if (!seg) {
if (!seg || !seg._path) {
seg = null;
// If there are no segments left, try previous
// branches until we find one that works.
branch = branches.pop();
@ -1145,9 +1150,9 @@ PathItem.inject(new function() {
// Support both path and compound-path items
paths = children || [this];
function hasOverlap(seg) {
function hasOverlap(seg, path) {
var inter = seg && seg._intersection;
return inter && inter._overlap;
return inter && inter._overlap && inter._path === path;
}
// First collect all overlaps and crossings while taking not of the
@ -1169,10 +1174,12 @@ PathItem.inject(new function() {
return inter.hasOverlap();
}, clearCurves);
for (var i = overlaps.length - 1; i >= 0; i--) {
var seg = overlaps[i]._segment,
var overlap = overlaps[i],
path = overlap._path,
seg = overlap._segment,
prev = seg.getPrevious(),
next = seg.getNext();
if (hasOverlap(prev) && hasOverlap(next)) {
if (hasOverlap(prev, path) && hasOverlap(next, path)) {
seg.remove();
prev._handleOut._set(0, 0);
next._handleIn._set(0, 0);

View file

@ -226,9 +226,6 @@ var comparePixels = function(actual, expected, message, options) {
ok = Math.abs(100 - identical) <= tolerance,
text = identical.toFixed(fixed) + '% identical',
detail = text;
if (!ok) {
console.log(actual, expected);
}
if (!ok &&
actual instanceof PathItem && expected instanceof PathItem) {
detail += '\nExpected:\n' + expected.pathData +

View file

@ -21,7 +21,6 @@ function testOperations(path1, path2, results) {
compareBoolean(function() { return path2.intersect(path1); }, results[3]);
compareBoolean(function() { return path1.exclude(path2); }, results[4]);
compareBoolean(function() { return path2.exclude(path1); }, results[4]);
}
test('Boolean operations without crossings', function() {
@ -935,6 +934,12 @@ test('#1261', function() {
'M933.13,1023.97l-516.19,-171.71l67.33,-11.27l0.0109,0.00363l539.7591,-90.30363z');
});
test('#1321', function() {
var path = PathItem.create('M24,38l2,1l-2,1l-2,-1z M26,39l2,1l-2,1l-2,-1z M28,40l2,1l-2,1l-2,-1z')
compareBoolean(function() { return path.unite(); },
'M24,38l6,3l-2,1l-6,-3z');
})
test('Selected edge-cases from @hari\'s boolean-test suite', function() {
var g = PathItem.create('M316.6,266.4Q332.6,266.4,343.8,272.8Q355,279.2,362,289.8Q369,300.4,372.2,313.6Q375.4,326.8,375.4,340.4Q375.4,354.8,372,369.2Q368.6,383.6,361.4,395Q354.2,406.4,342.4,413.4Q330.6,420.4,313.8,420.4Q297,420.4,285.8,413.4Q274.6,406.4,267.8,395Q261,383.6,258.2,369.6Q255.4,355.6,255.4,341.6Q255.4,326.8,258.8,313.2Q262.2,299.6,269.6,289.2Q277,278.8,288.6,272.6Q300.2,266.4,316.6,266.4Z M315,236.4Q288.2,236.4,269.8,246.6Q251.4,256.8,240.2,272.6Q229,288.4,224.2,307.8Q219.4,327.2,219.4,345.6Q219.4,366.8,225.2,385.8Q231,404.8,242.6,419Q254.2,433.2,271.4,441.6Q288.6,450,311.8,450Q331.8,450,349.6,441Q367.4,432,376.2,412.8L377,412.8L377,426.4Q377,443.6,373.6,458Q370.2,472.4,362.6,482.6Q355,492.8,343.4,498.6Q331.8,504.4,315,504.4Q306.6,504.4,297.4,502.6Q288.2,500.8,280.4,496.8Q272.6,492.8,267.2,486.4Q261.8,480,261.4,470.8L227.4,470.8Q228.2,487.6,236.2,499.2Q244.2,510.8,256.4,518Q268.6,525.2,283.6,528.4Q298.6,531.6,313,531.6Q362.6,531.6,385.8,506.4Q409,481.2,409,430.4L409,241.2L377,241.2L377,270.8L376.6,270.8Q367.4,253.6,351,245Q334.6,236.4,315,236.4Z');
var u = PathItem.create('M253,316.74Q242.25,316.74,232.77,318.39Q218.77,320.83,208.21,328.52Q197.65,336.21,191.32,349.4Q185,362.6,183.59,382.95Q182.01,405.69,189.83,423.08Q197.64,440.46,216.05,452.56L215.99,453.36L183.27,451.09L181.06,483.01L387.37,497.31L389.72,463.39L273.2,455.32Q259.23,454.35,247.72,449.74Q236.21,445.14,227.96,436.95Q219.7,428.76,215.7,417.05Q211.7,405.35,212.78,389.78Q214.14,370.23,226.09,359.83Q236.68,350.61,252.94,350.61Q255.02,350.61,257.19,350.76L396.85,360.44L399.2,326.52L263.53,317.12Q258.12,316.74,253,316.74Z');