From 27bb8a356f3aba82acdb42c8b8be146cd201010d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Mon, 11 May 2015 19:39:39 +0200 Subject: [PATCH] Implement unique ids, and fix issue with Base.deserialize() Gradient and Symbol were overriding each other in the dictionary, and dictionary entries could not contain references to other dictionary entries. Closes #690 --- examples/JSON/Gradients.html | 11 ++++++++--- src/core/Base.js | 31 ++++++++++++++++++------------- src/item/Item.js | 2 +- src/paper.js | 1 + src/path/CurveLocation.js | 3 +++ src/project/Symbol.js | 2 +- src/style/Color.js | 3 --- src/style/Gradient.js | 4 ++-- src/util/UID.js | 30 ++++++++++++++++++++++++++++++ 9 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 src/util/UID.js diff --git a/examples/JSON/Gradients.html b/examples/JSON/Gradients.html index bf14c15a..f115312a 100644 --- a/examples/JSON/Gradients.html +++ b/examples/JSON/Gradients.html @@ -6,15 +6,20 @@ diff --git a/src/core/Base.js b/src/core/Base.js index 05932ab0..b88f9f65 100644 --- a/src/core/Base.js +++ b/src/core/Base.js @@ -392,7 +392,7 @@ Base.inject(/** @lends Base# */{ * The passed json data is recoursively traversed and converted, leaves * first */ - deserialize: function(json, create, _data) { + deserialize: function(json, create, _data, _isDictionary) { var res = json, isRoot = !_data; // A _data side-car to deserialize that can hold any kind of @@ -405,22 +405,24 @@ Base.inject(/** @lends Base# */{ // deserialize all elements of the array. var type = json[0], // Handle stored dictionary specially, since we need to - // keep is a lookup table to retrieve referenced items from. + // keep a lookup table to retrieve referenced items from. isDictionary = type === 'dictionary'; - if (!isDictionary) { - // First see if this is perhaps a dictionary reference, and - // if so return its definition instead. - if (_data.dictionary && json.length == 1 && /^#/.test(type)) - return _data.dictionary[type]; - type = Base.exports[type]; - } + // First see if this is perhaps a dictionary reference, and + // if so return its definition instead. + if (json.length == 1 && /^#/.test(type)) + return _data.dictionary[type]; + type = Base.exports[type]; res = []; + // We need to set the dictionary object before further + // deserialization, because serialized symbols may contain + // references to serialized gradients + if (_isDictionary) + _data.dictionary = res; // Skip first type entry for arguments for (var i = type ? 1 : 0, l = json.length; i < l; i++) - res.push(Base.deserialize(json[i], create, _data)); - if (isDictionary) { - _data.dictionary = res[0]; - } else if (type) { + res.push(Base.deserialize(json[i], create, _data, + isDictionary)); + if (type) { // Create serialized type and pass collected arguments to // constructor(). var args = res; @@ -436,6 +438,9 @@ Base.inject(/** @lends Base# */{ } } else if (Base.isPlainObject(json)) { res = {}; + // See above why we have to set this before Base.deserialize() + if (_isDictionary) + _data.dictionary = res; for (var key in json) res[key] = Base.deserialize(json[key], create, _data); } diff --git a/src/item/Item.js b/src/item/Item.js index cd3ca661..6f2da27a 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -91,7 +91,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ // Allow setting another project than the currently active one. project = hasProps && props.project || paper.project; if (!internal) - this._id = Item._id = (Item._id || 0) + 1; + this._id = UID.get(); // Inherit the applyMatrix setting from paper.settings.applyMatrix this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix; // Handle matrix before everything else, to avoid issues with diff --git a/src/paper.js b/src/paper.js index 4368f234..2562d95f 100644 --- a/src/paper.js +++ b/src/paper.js @@ -51,6 +51,7 @@ var paper = new function(undefined) { /*#*/ include('util/Formatter.js'); /*#*/ include('util/Numerical.js'); +/*#*/ include('util/UID.js'); // Include Paper classes, which are later injected into PaperScope by setting // them on the 'this' object, e.g.: diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index 6c7c24bd..ea83c170 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -44,6 +44,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ initialize: function CurveLocation(curve, parameter, point, _curve2, _parameter2, _point2, _distance) { // Define this CurveLocation's unique id. + // NOTE: We do not use the same pool as the rest of the library here, + // since this is only required to be unique at runtime among other + // CurveLocation objects. this._id = CurveLocation._id = (CurveLocation._id || 0) + 1; this._curve = curve; // Also store references to segment1 and segment2, in case path diff --git a/src/project/Symbol.js b/src/project/Symbol.js index a75f407a..1fa2d4de 100644 --- a/src/project/Symbol.js +++ b/src/project/Symbol.js @@ -61,7 +61,7 @@ var Symbol = Base.extend(/** @lends Symbol# */{ */ initialize: function Symbol(item, dontCenter) { // Define this Symbols's unique id. - this._id = Symbol._id = (Symbol._id || 0) + 1; + this._id = UID.get(); this.project = paper.project; this.project.symbols.push(this); if (item) diff --git a/src/style/Color.js b/src/style/Color.js index 97ee5c1e..90d590c6 100644 --- a/src/style/Color.js +++ b/src/style/Color.js @@ -608,9 +608,6 @@ var Color = Base.extend(new function() { } // Default fallbacks: rgb, black this._type = type || 'rgb'; - // Define this gradient Color's unique id. - if (type === 'gradient') - this._id = Color._id = (Color._id || 0) + 1; if (!components) { // Produce a components array now, and parse values. Even if no // values are defined, parsers are still called to produce diff --git a/src/style/Gradient.js b/src/style/Gradient.js index 1f244f08..c739accc 100644 --- a/src/style/Gradient.js +++ b/src/style/Gradient.js @@ -66,8 +66,8 @@ var Gradient = Base.extend(/** @lends Gradient# */{ // DOCS: Document #initialize() initialize: function Gradient(stops, radial) { - // Define this Gradient's unique id. - this._id = Gradient._id = (Gradient._id || 0) + 1; + // Use UID here since Gradients are exported through dictionary.add(). + this._id = UID.get(); if (stops && this._set(stops)) stops = radial = null; if (!this._stops) diff --git a/src/util/UID.js b/src/util/UID.js new file mode 100644 index 00000000..22725bfe --- /dev/null +++ b/src/util/UID.js @@ -0,0 +1,30 @@ +/* + * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. + * http://paperjs.org/ + * + * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey + * http://scratchdisk.com/ & http://jonathanpuckey.com/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + */ + +/** + * @name UID + * @namespace + * @private + */ +var UID = { + _id: 1, + + /** + * Returns the next unique id. + * @method get + * @return {Number} The next unique id + * @static + **/ + get: function() { + return this._id++; + } +};