Fix Item#importJSON() to preserve #parent on existing, already inserted items.

Closes #1041
This commit is contained in:
Jürg Lehni 2016-06-10 17:45:02 +02:00
parent e7f7d7c5d1
commit ed3e283802
5 changed files with 33 additions and 20 deletions

View file

@ -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).

View file

@ -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;

View file

@ -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);

View file

@ -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(

View file

@ -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);
});