diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e7cffba..128b3057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,12 +35,11 @@ contribute to the code. ### Changed - Significant overhaul and improvements of boolean path operations - `PathItem#unite()`, `#subtract()`, `#intersect()`, `#exclude()`, `#divide()` - (#936): + `PathItem#unite()`, `#subtract()`, `#intersect()`, `#exclude()`, `#divide()`: - Improve handling of self-intersecting paths and non-zero fill-rules. - Handle operations on identical paths. - Improve handling of near-collinear lines. - - Better handle self-intersecting paths that merely "touch" themselves. + - Handle self-intersecting paths that merely "touch" themselves. - Handle situations where all encountered intersections are part of overlaps. - Methods that accepted a `time` parameter or boolean second parameter causing the argument to be interpreted as curve-time instead of offset are now @@ -196,8 +195,6 @@ contribute to the code. (#453). - Don't block touch actions when using paper in JavaScript mode (#686). - Convert touch event coordinates to project coordinates (#633). -- Fix problems with group selection structures after `group#importJSON()` - (#785). - Fix exceptions when a top-level layer is selected. - Don't allow layers to turn up in hit-tests (#608). - Maintain `Raster#source` correctly on Node.js (#914). @@ -207,7 +204,6 @@ contribute to the code. when it is a child items array of a `CompoundPath`. - Correctly handle `#strokeScaling` in `Shape` hit-tests (#697). - Support clip-masks in hit-testing (#671). -- `#importJSON()` no longer generates callstack exceeded exceptions (#764). - Fix incorrect `#hitTest()` and `#contains()` cases (#819, #884). - Update documentation to note appropriate use for `#simplify()` (#920). - `#importSVG()` now supports percentage dimensions and @@ -226,6 +222,11 @@ contribute to the code. - `#importJSON()` and `#exportJSON()` now handle non-`Item` objects correctly (#392). - `#exportSVG()` now exports empty paths if used as a clip-mask. +- `#importJSON()` no longer generates callstack exceeded exceptions (#764). +- Fix problems with group selection structures after `Group#importJSON()` + (#785). +- Fix an issue in `Item#importJSON()` where `#parent` is `null` when calling it + on existing, already inserted items (#1041). - Correct issue when using paper-core in Node.js (#975). - Fix `event.delta` on mousedrag events (#981). - Improve handling of XML attribute namespaces for IE's XMLSerializer() (#984). diff --git a/src/core/Base.js b/src/core/Base.js index 2ce3e686..91c251c0 100644 --- a/src/core/Base.js +++ b/src/core/Base.js @@ -502,13 +502,7 @@ Base.inject(/** @lends Base# */{ var useTarget = isRoot && target && target.constructor === ctor, obj = useTarget ? target - : Base.create(ctor.prototype), - // When reusing an object, try to (re)initialize it - // through _initialize (Item), fall-back to - // initialize (Color & co), then _set. - init = useTarget - ? obj._initialize || obj.initialize || obj._set - : ctor; + : Base.create(ctor.prototype); // NOTE: We don't set insert false for layers since we // want these to be created on the fly in the active // project into which we're importing (except for if @@ -519,7 +513,9 @@ Base.inject(/** @lends Base# */{ if (Base.isPlainObject(arg)) arg.insert = false; } - init.apply(obj, args); + // When reusing an object, initialize it through #_set() + // instead of the constructor function: + (useTarget ? obj._set : ctor).apply(obj, args); // Clear target to only use it once. if (useTarget) target = null; diff --git a/src/path/PathItem.Boolean.js b/src/path/PathItem.Boolean.js index f5cef07d..9b170e81 100644 --- a/src/path/PathItem.Boolean.js +++ b/src/path/PathItem.Boolean.js @@ -1044,9 +1044,9 @@ Path.inject(/** @lends Path# */{ intercepts = []; for (var i = 0, l = curves.length; i < l; i++) { var values = curves[i].values; - if ((curves[i].winding === 1 + if (curves[i].winding === 1 && y > values[1] && y <= values[7] - || y >= values[7] && y < values[1])) { + || y >= values[7] && y < values[1]) { var count = Curve.solveCubic(values, 1, y, roots, 0, 1); for (var j = count - 1; j >= 0; j--) { intercepts.push(Curve.getPoint(values, roots[j]).x); diff --git a/src/style/Color.js b/src/style/Color.js index 4232bfdc..adf6cf6c 100644 --- a/src/style/Color.js +++ b/src/style/Color.js @@ -485,6 +485,7 @@ var Color = Base.extend(new function() { // We are storing color internally as an array of components var slice = Array.prototype.slice, args = arguments, + reading = this.__read, read = 0, type, components, @@ -508,7 +509,7 @@ var Color = Base.extend(new function() { alpha = args[2]; } else { // For deserialization, shift out and process normally. - if (this.__read) + if (reading) read = 1; // Will be increased below // Shift type out of the arguments, and process normally. args = slice.call(args, 1); @@ -536,10 +537,11 @@ var Color = Base.extend(new function() { : 'gray'; var length = types[type].length; alpha = values[length]; - if (this.__read) + if (reading) { read += values === arguments ? length + (alpha != null ? 1 : 0) : 1; + } if (values.length > length) values = slice.call(values, 0, length); } else if (argType === 'string') { @@ -601,7 +603,7 @@ var Color = Base.extend(new function() { alpha = arg.alpha; } } - if (this.__read && type) + if (reading && type) read = 1; } // Default fallbacks: rgb, black @@ -621,10 +623,13 @@ var Color = Base.extend(new function() { this._components = components; this._properties = types[this._type]; this._alpha = alpha; - if (this.__read) + if (reading) this.__read = read; }, + // Have #_set point to #initialize, as used by Base.importJSON() + _set: '#initialize', + _serialize: function(options, dictionary) { var components = this.getComponents(); return Base.serialize( diff --git a/test/tests/JSON.js b/test/tests/JSON.js index bd50f0d5..2124c638 100644 --- a/test/tests/JSON.js +++ b/test/tests/JSON.js @@ -245,3 +245,14 @@ test('Color#importJSON()', function() { return color.equals(path.fillColor); }, true); }); + +test('Path#importJSON()', function() { + var path = new Path(); + var layer = project.activeLayer; + equals(function() { return path.parent === layer; }, true); + path.importJSON('["Path",{"segments":[[[50,100],[0,27.61424],[0,-27.61424]],[[100,50],[-27.61424,0],[27.61424,0]],[[150,100],[0,-27.61424],[0,27.61424]],[[100,150],[27.61424,0],[-27.61424,0]]],"closed":true,"fillColor":[1,0,0]}]'); + equals(function() { return path.bounds; }, { x: 50, y: 50, width: 100, height: 100 }); + equals(function() { return path.fillColor; }, { red: 1, green: 0, blue: 0 }); + equals(function() { return layer.firstChild === path; }, true); + equals(function() { return path.parent === layer; }, true); +});