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
This commit is contained in:
Jürg Lehni 2015-05-11 19:39:39 +02:00
parent 783d1622b9
commit 27bb8a356f
9 changed files with 64 additions and 23 deletions

View file

@ -6,15 +6,20 @@
<link rel="stylesheet" href="../css/style.css"> <link rel="stylesheet" href="../css/style.css">
<script type="text/javascript" src="../../dist/paper-full.js"></script> <script type="text/javascript" src="../../dist/paper-full.js"></script>
<script type="text/paperscript" canvas="canvas1"> <script type="text/paperscript" canvas="canvas1">
var path = new Path.Circle(view.center, view.bounds.height * 0.4); var path = new Path.Circle({
center: view.center,
radius: view.bounds.height * 0.4
});
path.fillColor = { path.fillColor = {
// gradient: [['yellow', 'red', 'black'], true],
stops: ['yellow', 'red', 'black'], stops: ['yellow', 'red', 'black'],
radial: true, radial: true,
origin: path.position, origin: path.position,
destination: path.bounds.rightCenter destination: path.bounds.rightCenter
} }
path.strokeColor = 'black';
var symbol = new Symbol(path);
symbol.place(view.center);
window._json = project.exportJSON(); window._json = project.exportJSON();
console.log(window._json); console.log(window._json);
</script> </script>

View file

@ -392,7 +392,7 @@ Base.inject(/** @lends Base# */{
* The passed json data is recoursively traversed and converted, leaves * The passed json data is recoursively traversed and converted, leaves
* first * first
*/ */
deserialize: function(json, create, _data) { deserialize: function(json, create, _data, _isDictionary) {
var res = json, var res = json,
isRoot = !_data; isRoot = !_data;
// A _data side-car to deserialize that can hold any kind of // 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. // deserialize all elements of the array.
var type = json[0], var type = json[0],
// Handle stored dictionary specially, since we need to // 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'; isDictionary = type === 'dictionary';
if (!isDictionary) { // First see if this is perhaps a dictionary reference, and
// First see if this is perhaps a dictionary reference, and // if so return its definition instead.
// if so return its definition instead. if (json.length == 1 && /^#/.test(type))
if (_data.dictionary && json.length == 1 && /^#/.test(type)) return _data.dictionary[type];
return _data.dictionary[type]; type = Base.exports[type];
type = Base.exports[type];
}
res = []; 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 // Skip first type entry for arguments
for (var i = type ? 1 : 0, l = json.length; i < l; i++) for (var i = type ? 1 : 0, l = json.length; i < l; i++)
res.push(Base.deserialize(json[i], create, _data)); res.push(Base.deserialize(json[i], create, _data,
if (isDictionary) { isDictionary));
_data.dictionary = res[0]; if (type) {
} else if (type) {
// Create serialized type and pass collected arguments to // Create serialized type and pass collected arguments to
// constructor(). // constructor().
var args = res; var args = res;
@ -436,6 +438,9 @@ Base.inject(/** @lends Base# */{
} }
} else if (Base.isPlainObject(json)) { } else if (Base.isPlainObject(json)) {
res = {}; res = {};
// See above why we have to set this before Base.deserialize()
if (_isDictionary)
_data.dictionary = res;
for (var key in json) for (var key in json)
res[key] = Base.deserialize(json[key], create, _data); res[key] = Base.deserialize(json[key], create, _data);
} }

View file

@ -91,7 +91,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
// Allow setting another project than the currently active one. // Allow setting another project than the currently active one.
project = hasProps && props.project || paper.project; project = hasProps && props.project || paper.project;
if (!internal) if (!internal)
this._id = Item._id = (Item._id || 0) + 1; this._id = UID.get();
// Inherit the applyMatrix setting from paper.settings.applyMatrix // Inherit the applyMatrix setting from paper.settings.applyMatrix
this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix; this._applyMatrix = this._canApplyMatrix && paper.settings.applyMatrix;
// Handle matrix before everything else, to avoid issues with // Handle matrix before everything else, to avoid issues with

View file

@ -51,6 +51,7 @@ var paper = new function(undefined) {
/*#*/ include('util/Formatter.js'); /*#*/ include('util/Formatter.js');
/*#*/ include('util/Numerical.js'); /*#*/ include('util/Numerical.js');
/*#*/ include('util/UID.js');
// Include Paper classes, which are later injected into PaperScope by setting // Include Paper classes, which are later injected into PaperScope by setting
// them on the 'this' object, e.g.: // them on the 'this' object, e.g.:

View file

@ -44,6 +44,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
initialize: function CurveLocation(curve, parameter, point, _curve2, initialize: function CurveLocation(curve, parameter, point, _curve2,
_parameter2, _point2, _distance) { _parameter2, _point2, _distance) {
// Define this CurveLocation's unique id. // 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._id = CurveLocation._id = (CurveLocation._id || 0) + 1;
this._curve = curve; this._curve = curve;
// Also store references to segment1 and segment2, in case path // Also store references to segment1 and segment2, in case path

View file

@ -61,7 +61,7 @@ var Symbol = Base.extend(/** @lends Symbol# */{
*/ */
initialize: function Symbol(item, dontCenter) { initialize: function Symbol(item, dontCenter) {
// Define this Symbols's unique id. // Define this Symbols's unique id.
this._id = Symbol._id = (Symbol._id || 0) + 1; this._id = UID.get();
this.project = paper.project; this.project = paper.project;
this.project.symbols.push(this); this.project.symbols.push(this);
if (item) if (item)

View file

@ -608,9 +608,6 @@ var Color = Base.extend(new function() {
} }
// Default fallbacks: rgb, black // Default fallbacks: rgb, black
this._type = type || 'rgb'; this._type = type || 'rgb';
// Define this gradient Color's unique id.
if (type === 'gradient')
this._id = Color._id = (Color._id || 0) + 1;
if (!components) { if (!components) {
// Produce a components array now, and parse values. Even if no // Produce a components array now, and parse values. Even if no
// values are defined, parsers are still called to produce // values are defined, parsers are still called to produce

View file

@ -66,8 +66,8 @@ var Gradient = Base.extend(/** @lends Gradient# */{
// DOCS: Document #initialize() // DOCS: Document #initialize()
initialize: function Gradient(stops, radial) { initialize: function Gradient(stops, radial) {
// Define this Gradient's unique id. // Use UID here since Gradients are exported through dictionary.add().
this._id = Gradient._id = (Gradient._id || 0) + 1; this._id = UID.get();
if (stops && this._set(stops)) if (stops && this._set(stops))
stops = radial = null; stops = radial = null;
if (!this._stops) if (!this._stops)

30
src/util/UID.js Normal file
View file

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