From bc2729683c2c9de992000f3a76f8882b13e00af0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrg=20Lehni?= <juerg@scratchdisk.com>
Date: Sun, 31 Jan 2016 16:52:51 +0100
Subject: [PATCH] Core: Renamed Symbol and PlacedSymbol classes and properties.

- Symbol -> SymbolDefinition
- PlacedSymbol -> SymbolItem
- Symbol#definition -> SymbolDefinition#item
- PlacedSymbol#symbol -> SymbolItem#definition
- Deprecate Project#symbols

Closes #770
---
 examples/Animated/Space.html                  |  2 +-
 examples/Games/Paperoids.html                 |  4 +-
 examples/JSON/Gradients.html                  |  2 +-
 examples/JSON/Symbols.html                    |  2 +-
 examples/Node.js/Tadpoles.pjs                 |  2 +-
 examples/Paperjs.org/NyanRainbow.html         |  2 +-
 examples/SVG Export/Symbols.html              |  2 +-
 examples/Scripts/BlendModes.html              |  4 +-
 src/export.js                                 |  5 +-
 src/item/HitResult.js                         |  2 +-
 src/item/Item.js                              | 10 +--
 src/{project => item}/Project.js              | 37 +++++++---
 src/item/Raster.js                            |  4 +-
 src/item/Shape.js                             |  2 +-
 .../Symbol.js => item/SymbolDefinition.js}    | 67 +++++++++---------
 src/item/{PlacedSymbol.js => SymbolItem.js}   | 68 ++++++++++---------
 src/paper.js                                  |  7 +-
 src/style/Style.js                            |  2 +-
 src/svg/SVGExport.js                          | 22 +++---
 src/svg/SVGImport.js                          | 21 +++---
 src/text/TextItem.js                          |  4 +-
 test/helpers.js                               | 29 ++++----
 test/tests/HitResult.js                       |  6 +-
 test/tests/Item.js                            |  3 +-
 test/tests/Item_Cloning.js                    | 23 +++----
 test/tests/JSON.js                            | 10 +--
 test/tests/{PlacedSymbol.js => SymbolItem.js} | 54 +++++++--------
 test/tests/load.js                            |  2 +-
 28 files changed, 212 insertions(+), 186 deletions(-)
 rename src/{project => item}/Project.js (97%)
 rename src/{project/Symbol.js => item/SymbolDefinition.js} (72%)
 rename src/item/{PlacedSymbol.js => SymbolItem.js} (62%)
 rename test/tests/{PlacedSymbol.js => SymbolItem.js} (70%)

diff --git a/examples/Animated/Space.html b/examples/Animated/Space.html
index e49cb59f..5bb52da8 100644
--- a/examples/Animated/Space.html
+++ b/examples/Animated/Space.html
@@ -17,7 +17,7 @@
         strokeColor: 'black'
     });
 
-    var symbol = new Symbol(path);
+    var symbol = new SymbolDefinition(path);
 
     // Place the instances of the symbol:
     for (var i = 0; i < count; i++) {
diff --git a/examples/Games/Paperoids.html b/examples/Games/Paperoids.html
index d5970e2a..08113832 100644
--- a/examples/Games/Paperoids.html
+++ b/examples/Games/Paperoids.html
@@ -103,7 +103,7 @@
             var explosionPath = new Path.Circle(new Point(), 1);
             explosionPath.fillColor = 'white';
             explosionPath.strokeColor = null;
-            return new Symbol(explosionPath);
+            return new SymbolDefinition(explosionPath);
         }
     };
 
@@ -322,7 +322,7 @@
 
         var rockSymbols = [];
         for (var i = 0; i < shapes.length; i++) {
-            rockSymbols[i] = new Symbol(shapes[i]);
+            rockSymbols[i] = new SymbolDefinition(shapes[i]);
         }
 
         var explosions = new Group();
diff --git a/examples/JSON/Gradients.html b/examples/JSON/Gradients.html
index f115312a..f01cd599 100644
--- a/examples/JSON/Gradients.html
+++ b/examples/JSON/Gradients.html
@@ -17,7 +17,7 @@
             destination: path.bounds.rightCenter
         }
 
-        var symbol = new Symbol(path);
+        var symbol = new SymbolDefinition(path);
         symbol.place(view.center);
 
         window._json = project.exportJSON();
diff --git a/examples/JSON/Symbols.html b/examples/JSON/Symbols.html
index a8bcb54b..0a545752 100644
--- a/examples/JSON/Symbols.html
+++ b/examples/JSON/Symbols.html
@@ -11,7 +11,7 @@
             to: [200, 100],
             fillColor: 'red'
         });
-        var symbol = new Symbol(ellipse);
+        var symbol = new SymbolDefinition(ellipse);
         var p1 = symbol.place([100, 100]);
         p1.rotate(45);
         var p2 = symbol.place([300, 200]);
diff --git a/examples/Node.js/Tadpoles.pjs b/examples/Node.js/Tadpoles.pjs
index 3b02c84d..b367ce82 100644
--- a/examples/Node.js/Tadpoles.pjs
+++ b/examples/Node.js/Tadpoles.pjs
@@ -12,7 +12,7 @@ new Path.Rectangle(view.bounds).fillColor = 'black';
 var head = new Path.Ellipse([0, 0], [13, 8]);
 head.fillColor = 'white';
 head.strokeColor = null;
-var headSymbol = new Symbol(head);
+var headSymbol = new SymbolDefinition(head);
 
 var size = view.size;
 
diff --git a/examples/Paperjs.org/NyanRainbow.html b/examples/Paperjs.org/NyanRainbow.html
index 83e68dd0..15f8cb15 100644
--- a/examples/Paperjs.org/NyanRainbow.html
+++ b/examples/Paperjs.org/NyanRainbow.html
@@ -53,7 +53,7 @@
                 strokeColor: 'black'
             });
 
-            var symbol = new Symbol(path);
+            var symbol = new SymbolDefinition(path);
 
             // Place the instances of the symbol:
             for (var i = 0; i < count; i++) {
diff --git a/examples/SVG Export/Symbols.html b/examples/SVG Export/Symbols.html
index 4850c528..4e0a8830 100644
--- a/examples/SVG Export/Symbols.html	
+++ b/examples/SVG Export/Symbols.html	
@@ -13,7 +13,7 @@
             to: [200, 100],
             fillColor: 'red'
         });
-        var symbol = new Symbol(ellipse);
+        var symbol = new SymbolDefinition(ellipse);
         var p1 = symbol.place([100, 100]);
         p1.rotate(45);
         var p2 = symbol.place([300, 200]);
diff --git a/examples/Scripts/BlendModes.html b/examples/Scripts/BlendModes.html
index 1517ec37..d52db743 100644
--- a/examples/Scripts/BlendModes.html
+++ b/examples/Scripts/BlendModes.html
@@ -21,8 +21,8 @@
         var image = new Raster('ducky');
         image.fitBounds(background.bounds);
 
-        background = new Symbol(background);
-        image = new Symbol(image);
+        background = new SymbolDefinition(background);
+        image = new SymbolDefinition(image);
 
         var all = new Group();
         function makeExample(point, blendMode) {
diff --git a/src/export.js b/src/export.js
index d0f4695c..d6ab58db 100644
--- a/src/export.js
+++ b/src/export.js
@@ -26,7 +26,10 @@ paper = new (PaperScope.inject(Base.exports, {
     DomElement: DomElement,
     // Export jsdom document and window too, for Node.js
     document: document,
-    window: window
+    window: window,
+    // TODO: Remove in 2017 (deprecated January 2016):
+    Symbol: SymbolDefinition,
+    PlacedSymbol: SymbolItem
 }))();
 
 // If we're on node, require some additional functionality now before finishing:
diff --git a/src/item/HitResult.js b/src/item/HitResult.js
index 71fc85c4..69d4bd55 100644
--- a/src/item/HitResult.js
+++ b/src/item/HitResult.js
@@ -109,7 +109,7 @@ var HitResult = Base.extend(/** @lends HitResult# */{
         getOptions: function(options) {
             return new Base({
                 // Type of item, for instanceof check: Group, Layer, Path,
-                // CompoundPath, Shape, Raster, PlacedSymbol, ...
+                // CompoundPath, Shape, Raster, SymbolItem, ...
                 type: null,
                 // Tolerance
                 tolerance: paper.settings.hitTolerance,
diff --git a/src/item/Item.js b/src/item/Item.js
index 3b146b69..b7376cd3 100644
--- a/src/item/Item.js
+++ b/src/item/Item.js
@@ -46,7 +46,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
 
     _class: 'Item',
     // All items apply their matrix by default.
-    // Exceptions are Raster, PlacedSymbol, Clip and Shape.
+    // Exceptions are Raster, SymbolItem, Clip and Shape.
     _applyMatrix: true,
     _canApplyMatrix: true,
     _canScaleStroke: false,
@@ -267,7 +267,7 @@ new function() { // // Scope to inject various item event handlers
      * @name Item#className
      * @type String
      * @values 'Group', 'Layer', 'Path', 'CompoundPath', 'Shape', 'Raster',
-     *     'PlacedSymbol', 'PointText'
+     *     'SymbolItem', 'PointText'
      */
 
     /**
@@ -833,7 +833,7 @@ new function() { // // Scope to inject various item event handlers
     _getBounds: function(getter, matrix, cacheItem, internal) {
         // NOTE: We cannot cache these results here, since we do not get
         // _changed() notifications here for changing geometry in children.
-        // But cacheName is used in sub-classes such as PlacedSymbol and Raster.
+        // But cacheName is used in sub-classes such as SymbolItem and Raster.
         var children = this._children;
         // TODO: What to return if nothing is defined, e.g. empty Groups?
         // Scriptographer behaves weirdly then too.
@@ -1702,7 +1702,7 @@ new function() { // // Scope to inject various item event handlers
      *     {Number} the tolerance of the hit-test
      * @option options.class {Function} only hit-test again a certain item class
      *     and its sub-classes: {@values Group, Layer, Path, CompoundPath,
-     *     Shape, Raster, PlacedSymbol, PointText, ...}
+     *     Shape, Raster, SymbolItem, PointText, ...}
      * @option options.fill {Boolean} hit-test the fill of items
      * @option options.stroke {Boolean} hit-test the stroke of path and shape
      *     items, taking into account the setting of stroke color and width
@@ -3182,7 +3182,7 @@ new function() { // // Scope to inject various item event handlers
             _matrix.prepend(matrix);
         // Call #_transformContent() now, if we need to directly apply the
         // internal _matrix transformations to the item's content.
-        // Application is not possible on Raster, PointText, PlacedSymbol, since
+        // Application is not possible on Raster, PointText, SymbolItem, since
         // the matrix is where the actual transformation state is stored.
         if (applyMatrix = applyMatrix && this._transformContent(_matrix,
                     _applyRecursively, _setApplyMatrix)) {
diff --git a/src/project/Project.js b/src/item/Project.js
similarity index 97%
rename from src/project/Project.js
rename to src/item/Project.js
index 350c107d..2893b144 100644
--- a/src/project/Project.js
+++ b/src/item/Project.js
@@ -55,7 +55,6 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
         this._children = [];
         this._namedChildren = {};
         this._activeLayer = null;
-        this.symbols = [];
         this._currentStyle = new Style(null, null, this);
         // If no view is provided, we create a 1x1 px canvas view just so we
         // have something to do size calculations with.
@@ -121,14 +120,12 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
      */
 
     /**
-     * Clears the project by removing all {@link Project#layers} and
-     * {@link Project#symbols}.
+     * Clears the project by removing all {@link Project#layers}.
      */
     clear: function() {
         var children = this._children;
         for (var i = children.length - 1; i >= 0; i--)
             children[i].remove();
-        this.symbols = [];
     },
 
     /**
@@ -244,11 +241,35 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
     },
 
     /**
-     * The symbols contained within the project.
+     * The symbol definitions shared by all symbol items contained place ind
+     * project.
      *
-     * @name Project#symbols
-     * @type Symbol[]
+     * @bean
+     * @type SymbolDefinition[]
      */
+    getSymbolDefinitions: function() {
+        var definitions = [],
+            ids = {};
+        this.getItems({
+            class: SymbolItem,
+            match: function(item) {
+                var definition = item._definition,
+                    id = definition._id;
+                if (!ids[id]) {
+                    ids[id] = true;
+                    definitions.push(definition);
+                }
+                return false; // No need to collect them.
+            }
+        });
+        return definitions;
+    },
+
+    /**
+     * @bean
+     * @deprecated use {@link #getSymbolDefinitions()} instead.
+     */
+    getSymbols: 'getSymbolDefinitions',
 
     /**
      * The selected items contained within the project.
@@ -318,7 +339,7 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
      *     {Number} the tolerance of the hit-test
      * @option options.class {Function} only hit-test again a certain item class
      *     and its sub-classes: {@values Group, Layer, Path, CompoundPath,
-     *     Shape, Raster, PlacedSymbol, PointText, ...}
+     *     Shape, Raster, SymbolItem, PointText, ...}
      * @option options.fill {Boolean} hit-test the fill of items
      * @option options.stroke {Boolean} hit-test the stroke of path items,
      *     taking into account the setting of stroke color and width
diff --git a/src/item/Raster.js b/src/item/Raster.js
index 1070310a..4498d09c 100644
--- a/src/item/Raster.js
+++ b/src/item/Raster.js
@@ -31,7 +31,7 @@ var Raster = Item.extend(/** @lends Raster# */{
     },
 
     // TODO: Implement type, width, height.
-    // TODO: Have PlacedSymbol & Raster inherit from a shared class?
+    // TODO: Have SymbolItem & Raster inherit from a shared class?
     /**
      * Creates a new raster item from the passed argument, and places it in the
      * active layer. `object` can either be a DOM Image, a Canvas, or a string
@@ -206,7 +206,7 @@ var Raster = Item.extend(/** @lends Raster# */{
     /**
      * @private
      * @bean
-     * @deprecated use {@link #resolution} instead.
+     * @deprecated use {@link #getResolution()} instead.
      */
     getPpi: '#getResolution',
 
diff --git a/src/item/Shape.js b/src/item/Shape.js
index e95d6a2c..e0c824ac 100644
--- a/src/item/Shape.js
+++ b/src/item/Shape.js
@@ -64,7 +64,7 @@ var Shape = Item.extend(/** @lends Shape# */{
     /**
      * @private
      * @bean
-     * @deprecated use {@link #type} instead.
+     * @deprecated use {@link #getType()} instead.
      */
     getShape: '#getType',
     setShape: '#setType',
diff --git a/src/project/Symbol.js b/src/item/SymbolDefinition.js
similarity index 72%
rename from src/project/Symbol.js
rename to src/item/SymbolDefinition.js
index 663f1954..82db8d8b 100644
--- a/src/project/Symbol.js
+++ b/src/item/SymbolDefinition.js
@@ -11,7 +11,7 @@
  */
 
 /**
- * @name Symbol
+ * @name SymbolDefinition
  *
  * @class Symbols allow you to place multiple instances of an item in your
  * project. This can save memory, since all instances of a symbol simply refer
@@ -19,14 +19,14 @@
  * internal properties such as segment lists and gradient positions don't need
  * to be updated with every transformation.
  */
-var Symbol = Base.extend(/** @lends Symbol# */{
-    _class: 'Symbol',
+var SymbolDefinition = Base.extend(/** @lends SymbolDefinition# */{
+    _class: 'SymbolDefinition',
 
     /**
-     * Creates a Symbol item.
+     * Creates a Symbol definition.
      *
-     * @param {Item} item the source item which is copied as the definition of
-     * the symbol
+     * @param {Item} item the source item which is removed from the scene graph
+     *     and becomes the symbol's definition.
      * @param {Boolean} [dontCenter=false]
      *
      * @example {@paperscript split=true height=240}
@@ -37,16 +37,13 @@ var Symbol = Base.extend(/** @lends Symbol# */{
      *     strokeColor: 'black'
      * };
      *
-     * // Create a symbol from the path:
-     * var symbol = new Symbol(path);
+     * // Create a symbol definition from the path:
+     * var definition = new SymbolDefinition(path);
      *
-     * // Remove the path:
-     * path.remove();
-     *
-     * // Place 100 instances of the symbol:
+     * // Place 100 instances of the symbol definition:
      * for (var i = 0; i < 100; i++) {
-     *     // Place an instance of the symbol in the project:
-     *     var instance = symbol.place();
+     *     // Place an instance of the symbol definition in the project:
+     *     var instance = definition.place();
      *
      *     // Move the instance to a random position within the view:
      *     instance.position = Point.random() * view.size;
@@ -59,31 +56,26 @@ var Symbol = Base.extend(/** @lends Symbol# */{
      *     instance.scale(0.25 + Math.random() * 0.75);
      * }
      */
-    initialize: function Symbol(item, dontCenter) {
-        // Define this Symbols's unique id.
+    initialize: function SymbolDefinition(item, dontCenter) {
         this._id = UID.get();
         this.project = paper.project;
-        this.project.symbols.push(this);
         if (item)
-            this.setDefinition(item, dontCenter);
+            this.setItem(item, dontCenter);
     },
 
     _serialize: function(options, dictionary) {
         return dictionary.add(this, function() {
-            return Base.serialize([this._class, this._definition],
+            return Base.serialize([this._class, this._item],
                     options, false, dictionary);
         });
     },
 
-    // TODO: Symbol#remove()
-    // TODO: Symbol#name (accessible by name through project#symbols)
-
     /**
      * The project that this symbol belongs to.
      *
      * @type Project
      * @readonly
-     * @name Symbol#project
+     * @name SymbolDefinition#project
      */
 
     /**
@@ -101,23 +93,23 @@ var Symbol = Base.extend(/** @lends Symbol# */{
     },
 
     /**
-     * The symbol definition.
+     * The item used as the symbol's definition.
      *
      * @bean
      * @type Item
      */
-    getDefinition: function() {
-        return this._definition;
+    getItem: function() {
+        return this._item;
     },
 
-    setDefinition: function(item, _dontCenter) {
+    setItem: function(item, _dontCenter) {
         // Make sure we're not stealing another symbol's definition
         if (item._parentSymbol)
             item = item.clone();
         // Remove previous definition's reference to this symbol
-        if (this._definition)
-            this._definition._parentSymbol = null;
-        this._definition = item;
+        if (this._item)
+            this._item._parentSymbol = null;
+        this._item = item;
         // Remove item from DOM, as it's embedded in Symbol now.
         item.remove();
         item.setSelected(false);
@@ -128,14 +120,21 @@ var Symbol = Base.extend(/** @lends Symbol# */{
         this._changed(/*#=*/Change.GEOMETRY);
     },
 
+    /**
+     * @bean
+     * @deprecated use {@link #getItem()} instead.
+     */
+    getDefinition: '#getItem',
+    setDefinition: '#setItem',
+
     /**
      * Places in instance of the symbol in the project.
      *
      * @param {Point} [position] the position of the placed symbol
-     * @return {PlacedSymbol}
+     * @return {SymbolItem}
      */
     place: function(position) {
-        return new PlacedSymbol(this, position);
+        return new SymbolItem(this, position);
     },
 
     /**
@@ -144,7 +143,7 @@ var Symbol = Base.extend(/** @lends Symbol# */{
      * @return {Symbol}
      */
     clone: function() {
-        return new Symbol(this._definition.clone(false));
+        return new SymbolDefinition(this._item.clone(false));
     },
 
     /**
@@ -155,7 +154,7 @@ var Symbol = Base.extend(/** @lends Symbol# */{
      */
     equals: function(symbol) {
         return symbol === this
-                || symbol && this.definition.equals(symbol.definition)
+                || symbol && this._item.equals(symbol._item)
                 || false;
     }
 });
diff --git a/src/item/PlacedSymbol.js b/src/item/SymbolItem.js
similarity index 62%
rename from src/item/PlacedSymbol.js
rename to src/item/SymbolItem.js
index e56cdd64..c861562b 100644
--- a/src/item/PlacedSymbol.js
+++ b/src/item/SymbolItem.js
@@ -11,18 +11,18 @@
  */
 
 /**
- * @name PlacedSymbol
+ * @name SymbolItem
  *
- * @class A PlacedSymbol represents an instance of a symbol which has been
+ * @class A symbol item represents an instance of a symbol which has been
  * placed in a Paper.js project.
  *
  * @extends Item
  */
-var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
-    _class: 'PlacedSymbol',
+var SymbolItem = Item.extend(/** @lends SymbolItem# */{
+    _class: 'SymbolItem',
     _applyMatrix: false,
     _canApplyMatrix: false,
-    // PlacedSymbol uses strokeBounds for bounds
+    // SymbolItem uses strokeBounds for bounds
     _boundsGetter: { getBounds: 'getStrokeBounds' },
     _boundsSelected: true,
     _serializeFields: {
@@ -30,9 +30,9 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
     },
 
     /**
-     * Creates a new PlacedSymbol Item.
+     * Creates a new symbol item.
      *
-     * @param {Symbol} symbol the symbol to place
+     * @param {Symbol} definition the symbol definition to place
      * @param {Point} [point] the center point of the placed symbol
      *
      * @example {@paperscript split=true height=240}
@@ -47,16 +47,13 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
      *     strokeColor: 'black'
      * });
      *
-     * // Create a symbol from the path:
-     * var symbol = new Symbol(path);
-     *
-     * // Remove the path:
-     * path.remove();
+     * // Create a symbol definition from the path:
+     * var definition = new SymbolDefinition(path);
      *
      * // Place 100 instances of the symbol:
      * for (var i = 0; i < 100; i++) {
      *     // Place an instance of the symbol in the project:
-     *     var instance = new PlacedSymbol(symbol);
+     *     var instance = new SymbolItem(definition);
      *
      *     // Move the instance to a random position within the view:
      *     instance.position = Point.random() * view.size;
@@ -69,7 +66,7 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
      *     instance.scale(0.25 + Math.random() * 0.75);
      * }
      */
-    initialize: function PlacedSymbol(arg0, arg1) {
+    initialize: function SymbolItem(arg0, arg1) {
         // Support two forms of item initialization: Passing one object literal
         // describing all the different properties to be set, or a symbol (arg0)
         // and a point where it should be placed (arg1).
@@ -77,47 +74,56 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
         // Otherwise we need to set symbol from arg0.
         if (!this._initialize(arg0,
                 arg1 !== undefined && Point.read(arguments, 1)))
-            this.setSymbol(arg0 instanceof Symbol ? arg0 : new Symbol(arg0));
+            this.setDefinition(arg0 instanceof SymbolDefinition ?
+                    arg0 : new SymbolDefinition(arg0));
     },
 
     _equals: function(item) {
-        return this._symbol === item._symbol;
+        // TODO: Compare position too!
+        return this._definition === item._definition;
     },
 
     copyContent: function(source) {
-        this.setSymbol(source._symbol);
+        this.setDefinition(source._definition);
     },
 
     /**
-     * The symbol that the placed symbol refers to.
+     * The symbol definition that the placed symbol refers to.
      *
      * @bean
-     * @type Symbol
+     * @type SymbolDefinition
      */
-    getSymbol: function() {
-        return this._symbol;
+    getDefinition: function() {
+        return this._definition;
     },
 
-    setSymbol: function(symbol) {
-        this._symbol = symbol;
+    setDefinition: function(definition) {
+        this._definition = definition;
         this._changed(/*#=*/Change.GEOMETRY);
     },
 
+    /**
+     * @bean
+     * @deprecated use {@link #getDefinition()} instead.
+     */
+    getSymbol: '#getDefinition',
+    setSymbol: '#setDefinition',
+
     isEmpty: function() {
-        return this._symbol._definition.isEmpty();
+        return this._definition._item.isEmpty();
     },
 
 
     _getBounds: function(getter, matrix, cacheItem, internal) {
-        var definition = this.symbol._definition;
-        // Redirect the call to the symbol definition to calculate the bounds
-        return definition._getCachedBounds(getter,
-                matrix && matrix.appended(definition._matrix),
+        var item = this._definition._item;
+        // Redirect the call to the definition item to calculate the bounds.
+        return item._getCachedBounds(getter,
+                matrix && matrix.appended(item._matrix),
                 cacheItem, internal);
     },
 
     _hitTestSelf: function(point, options) {
-        var res = this._symbol._definition._hitTest(point, options);
+        var res = this._definition._item._hitTest(point, options);
         // TODO: When the symbol's definition is a path, should hitResult
         // contain information like HitResult#curve?
         if (res)
@@ -126,8 +132,8 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
     },
 
     _draw: function(ctx, param) {
-        this.symbol._definition.draw(ctx, param);
+        this._definition._item.draw(ctx, param);
     }
 
-    // TODO: PlacedSymbol#embed()
+    // TODO: SymbolItem#embed()
 });
diff --git a/src/paper.js b/src/paper.js
index c0d0626c..1bcbfa91 100644
--- a/src/paper.js
+++ b/src/paper.js
@@ -56,15 +56,14 @@ var paper = function(window, undefined) {
 /*#*/ include('basic/Matrix.js');
 /*#*/ include('basic/Line.js');
 
-/*#*/ include('project/Project.js');
-/*#*/ include('project/Symbol.js');
-
+/*#*/ include('item/Project.js');
 /*#*/ include('item/Item.js');
 /*#*/ include('item/Group.js');
 /*#*/ include('item/Layer.js');
 /*#*/ include('item/Shape.js');
 /*#*/ include('item/Raster.js');
-/*#*/ include('item/PlacedSymbol.js');
+/*#*/ include('item/SymbolItem.js');
+/*#*/ include('item/SymbolDefinition.js');
 /*#*/ include('item/HitResult.js');
 
 /*#*/ include('path/Segment.js');
diff --git a/src/style/Style.js b/src/style/Style.js
index e747a0f1..5080e66d 100644
--- a/src/style/Style.js
+++ b/src/style/Style.js
@@ -323,7 +323,7 @@ var Style = Base.extend(new function() {
     /**
      * @bean
      * @private
-     * @deprecated use {@link #fontFamily} instead.
+     * @deprecated use {@link #getFontFamily()} instead.
      */
     getFont: '#getFontFamily',
     setFont: '#setFontFamily',
diff --git a/src/svg/SVGExport.js b/src/svg/SVGExport.js
index 674430d2..76b4dce0 100644
--- a/src/svg/SVGExport.js
+++ b/src/svg/SVGExport.js
@@ -187,20 +187,20 @@ new function() {
         return createElement('path', attrs);
     }
 
-    function exportPlacedSymbol(item, options) {
+    function exportSymbolItem(item, options) {
         var attrs = getTransform(item._matrix, true),
-            symbol = item.getSymbol(),
-            symbolNode = getDefinition(symbol, 'symbol'),
-            definition = symbol.getDefinition(),
-            bounds = definition.getBounds();
-        if (!symbolNode) {
-            symbolNode = createElement('symbol', {
+            definition = item._definition,
+            node = getDefinition(definition, 'symbol'),
+            definitionItem = definition._item,
+            bounds = definitionItem.getBounds();
+        if (!node) {
+            node = createElement('symbol', {
                 viewBox: formatter.rectangle(bounds)
             });
-            symbolNode.appendChild(exportSVG(definition, options));
-            setDefinition(symbol, symbolNode, 'symbol');
+            node.appendChild(exportSVG(definitionItem, options));
+            setDefinition(definition, node, 'symbol');
         }
-        attrs.href = '#' + symbolNode.id;
+        attrs.href = '#' + node.id;
         attrs.x += bounds.x;
         attrs.y += bounds.y;
         attrs.width = formatter.number(bounds.width);
@@ -278,7 +278,7 @@ new function() {
         Path: exportPath,
         Shape: exportShape,
         CompoundPath: exportCompoundPath,
-        PlacedSymbol: exportPlacedSymbol,
+        SymbolItem: exportSymbolItem,
         PointText: exportText
     };
 
diff --git a/src/svg/SVGImport.js b/src/svg/SVGImport.js
index 52742be1..f9724638 100644
--- a/src/svg/SVGImport.js
+++ b/src/svg/SVGImport.js
@@ -102,7 +102,7 @@ new function() {
             if (childNode.nodeType === 1
                     && childNode.nodeName.toLowerCase() !== 'defs'
                     && (child = importSVG(childNode, options, false))
-                    && !(child instanceof Symbol))
+                    && !(child instanceof SymbolDefinition))
                 children.push(child);
         }
         item.addChildren(children);
@@ -246,8 +246,9 @@ new function() {
 
         // http://www.w3.org/TR/SVG/struct.html#SymbolElement
         symbol: function(node, type, options, isRoot) {
-            // Pass true for dontCenter:
-            return new Symbol(importGroup(node, type, options, isRoot), true);
+            return new SymbolDefinition(
+                    // Pass true for dontCenter:
+                    importGroup(node, type, options, isRoot), true);
         },
 
         // http://www.w3.org/TR/SVG/struct.html#DefsElement
@@ -259,13 +260,13 @@ new function() {
             // as a property on node.
             // TODO: Support overflow and width, height, in combination with
             // overflow: hidden. Paper.js currently does not support
-            // PlacedSymbol clipping, but perhaps it should?
+            // SymbolItem clipping, but perhaps it should?
             var id = (getValue(node, 'href', true) || '').substring(1),
                 definition = definitions[id],
                 point = getPoint(node, 'x', 'y');
             // Use place if we're dealing with a symbol:
             return definition
-                    ? definition instanceof Symbol
+                    ? definition instanceof SymbolDefinition
                         // When placing symbols, we nee to take both point and
                         // matrix into account. This just does the right thing:
                         ? definition.place(point)
@@ -459,7 +460,7 @@ new function() {
             // http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
             // TODO: implement preserveAspectRatio attribute
             // viewBox will be applied both to the group that's created for the
-            // content in Symbol.definition, and the Symbol itself.
+            // content in SymbolDefinition#item, and the SymbolItem itself.
             var rect = new Rectangle(convertValue(value, 'array')),
                 size = getSize(node, 'width', 'height', true);
             if (item instanceof Group) {
@@ -468,17 +469,17 @@ new function() {
                 var scale = size ? rect.getSize().divide(size) : 1,
                     matrix = new Matrix().translate(rect.getPoint()).scale(scale);
                 item.transform(matrix.invert());
-            } else if (item instanceof Symbol) {
+            } else if (item instanceof SymbolDefinition) {
                 // The symbol is wrapping a group. Note that viewBox was already
-                // applied to the group, and above code was executed for it.
-                // All that is left to handle here on the Symbol level is
+                // applied to the group, and the above code was executed for it.
+                // All that is left to handle here for SymbolDefinition is
                 // clipping. We can't do it at group level because
                 // applyAttributes() gets called for groups before their
                 // children are added, for styling reasons. See importGroup()
                 if (size)
                     rect.setSize(size);
                 var clip = getAttribute(node, 'overflow', styles) != 'visible',
-                    group = item._definition;
+                    group = item._item;
                 if (clip && !rect.contains(group.getBounds())) {
                     // Add a clip path at the top of this symbol's group
                     clip = new Shape.Rectangle(rect).transform(group._matrix);
diff --git a/src/text/TextItem.js b/src/text/TextItem.js
index 6ce7e684..4d5644d2 100644
--- a/src/text/TextItem.js
+++ b/src/text/TextItem.js
@@ -159,7 +159,7 @@ var TextItem = Item.extend(/** @lends TextItem# */{
     /**
      * @bean
      * @private
-     * @deprecated use {@link #style} instead.
+     * @deprecated use {@link #getStyle()} instead.
      */
     getCharacterStyle: '#getStyle',
     setCharacterStyle: '#setStyle',
@@ -167,7 +167,7 @@ var TextItem = Item.extend(/** @lends TextItem# */{
     /**
      * @bean
      * @private
-     * @deprecated use {@link #style} instead.
+     * @deprecated use {@link #getStyle()} instead.
      */
     getParagraphStyle: '#getStyle',
     setParagraphStyle: '#setStyle'
diff --git a/test/helpers.js b/test/helpers.js
index 396f8f92..355b1412 100644
--- a/test/helpers.js
+++ b/test/helpers.js
@@ -34,8 +34,7 @@ if (isNode) {
 }
 
 // The unit-tests expect the paper classes to be global.
-if (!('Base' in root))
-    paper.install(root);
+paper.install(root);
 
 // Override console.error, so that we can catch errors that are only logged to
 // the console.
@@ -109,7 +108,7 @@ var equals = function(actual, expected, message, options) {
 // A list of classes that should be identical after their owners were cloned.
 var identicalAfterCloning = {
     Gradient: true,
-    Symbol: true
+    SymbolDefinition: true
 };
 
 // Register a jsDump parser for Base.
@@ -337,11 +336,6 @@ var comparators = {
         }
     },
 
-    Symbol: function(actual, expected, message, options) {
-        equals(actual.definition, expected.definition, message + '.definition',
-                options);
-    },
-
     Segment: function(actual, expected, message, options) {
         compareProperties(actual, expected, ['handleIn', 'handleOut', 'point',
                 'selected'], message, options);
@@ -390,23 +384,28 @@ var comparators = {
                 ['shape', 'size', 'radius']);
     },
 
-    PlacedSymbol: function(actual, expected, message, options) {
+    PointText: function(actual, expected, message, options) {
+        compareItem(actual, expected, message, options,
+                ['content', 'point']);
+    },
+
+    SymbolItem: function(actual, expected, message, options) {
         compareItem(actual, expected, message,
-                // Cloning PlacedSymbols does not result in cloned Symbols
+                // Cloning SymbolItems does not result in cloned
+                // SymbolDefinitions
                 options && options.cloned
                         ? new Base(options, { cloned: false })
                         : options,
                 ['symbol']);
     },
 
-    PointText: function(actual, expected, message, options) {
-        compareItem(actual, expected, message, options,
-                ['content', 'point']);
+    SymbolDefinition: function(actual, expected, message, options) {
+        equals(actual.definition, expected.definition, message + '.definition',
+                options);
     },
 
     Project: function(actual, expected, message, options) {
-        compareProperties(actual, expected, ['symbols', 'layers'],
-                message, options);
+        compareProperties(actual, expected, ['layers'], message, options);
     }
 };
 
diff --git a/test/tests/HitResult.js b/test/tests/HitResult.js
index 52f5d34f..c5b30709 100644
--- a/test/tests/HitResult.js
+++ b/test/tests/HitResult.js
@@ -521,7 +521,7 @@ test('hit-testing of items that come after a transformed group.', function() {
         return hitResult && hitResult.item;
     }, path2, 'Hit testing project for point2 should give us path2.');
 
-    group.translate(delta)
+    group.translate(delta);
 
     hitResult = paper.project.hitTest(point1);
     equals(function() {
@@ -561,8 +561,8 @@ test('hit-testing of placed symbols.', function() {
 
     var path = new Path.Circle([0, 0], 20);
     path.fillColor = 'black';
-    var symbol = new Symbol(path);
-    var placedItem = symbol.place(point);
+    var definition = new SymbolDefinition(path);
+    var placedItem = definition.place(point);
     var hitResult = placedItem.hitTest(point);
     equals(function() {
         return hitResult && hitResult.item == placedItem;
diff --git a/test/tests/Item.js b/test/tests/Item.js
index 3e52abaf..71fd63d3 100644
--- a/test/tests/Item.js
+++ b/test/tests/Item.js
@@ -612,7 +612,8 @@ test('Item#className', function() {
     equals(new Path().className, 'Path');
     equals(new CompoundPath().className, 'CompoundPath');
     equals(new Raster().className, 'Raster');
-    equals(new PlacedSymbol().className, 'PlacedSymbol');
+    equals(new SymbolItem().className, 'SymbolItem');
+    equals(new PlacedSymbol().className, 'SymbolItem'); // deprecated
     equals(new PointText().className, 'PointText');
 });
 
diff --git a/test/tests/Item_Cloning.js b/test/tests/Item_Cloning.js
index c9009546..b3051744 100644
--- a/test/tests/Item_Cloning.js
+++ b/test/tests/Item_Cloning.js
@@ -113,13 +113,13 @@ test('PointText#clone()', function() {
     cloneAndCompare(pointText);
 });
 
-test('PlacedSymbol#clone()', function() {
+test('SymbolItem#clone()', function() {
     var path = new Path.Circle([150, 150], 60);
-    var symbol = new Symbol(path);
-    var placedSymbol = new PlacedSymbol(symbol);
-    placedSymbol.position = [100, 100];
-    placedSymbol.rotate(90);
-    cloneAndCompare(placedSymbol);
+    var definition = new SymbolDefinition(path);
+    var item = new SymbolItem(definition);
+    item.position = [100, 100];
+    item.rotate(90);
+    cloneAndCompare(item);
 });
 
 test('Symbol#clone()', function() {
@@ -134,14 +134,11 @@ test('Symbol#clone()', function() {
         miterLimit: 5
     };
     path.selected = true;
-    var symbol = new Symbol(path);
-    var copy = symbol.clone();
-    equals(symbol.definition, copy.definition, 'symbol.definition');
+    var definition = new SymbolDefinition(path);
+    var copy = definition.clone();
+    equals(definition.item, copy.item, 'definition.item');
     equals(function() {
-        return symbol.project == copy.project;
-    }, true);
-    equals(function() {
-        return paper.project.symbols.length == 2;
+        return definition.project == copy.project;
     }, true);
 });
 
diff --git a/test/tests/JSON.js b/test/tests/JSON.js
index bb93faba..0945a826 100644
--- a/test/tests/JSON.js
+++ b/test/tests/JSON.js
@@ -86,7 +86,7 @@ test('Rectangle testing', function() {
     path1.fillColor = 'red';
     path1.name = 'square1';
     path1.strokeCap = 'square';
-    path1.opacity = .1;
+    path1.opacity = 0.1;
     path1.dashArray = [5, 2];
     path1.dashOffset = 0;
 
@@ -121,10 +121,10 @@ test('Symbols', function() {
         to: [200, 100],
         fillColor: 'red'
     });
-    var symbol = new Symbol(ellipse);
-    var p1 = symbol.place([100, 100]);
+    var definition = new SymbolDefinition(ellipse);
+    var p1 = definition.place([100, 100]);
     p1.rotate(45);
-    var p2 = symbol.place([300, 200]);
+    var p2 = definition.place([300, 200]);
     p2.rotate(-30);
 
     testExportImportJSON(paper.project);
@@ -157,7 +157,7 @@ test('transform test 1', function() {
     for(var i = 0; i < clones; i++) {
         var clonedPath = circlePath.clone();
         clonedPath.rotate(angle * i, circlePath.bounds.topLeft);
-    };
+    }
     testExportImportJSON(paper.project);
 });
 
diff --git a/test/tests/PlacedSymbol.js b/test/tests/SymbolItem.js
similarity index 70%
rename from test/tests/PlacedSymbol.js
rename to test/tests/SymbolItem.js
index 466b7523..845d3f3c 100644
--- a/test/tests/PlacedSymbol.js
+++ b/test/tests/SymbolItem.js
@@ -12,7 +12,7 @@
 
 QUnit.module('Symbol & Placed Symbol');
 
-test('placedSymbol bounds', function() {
+test('SymbolItem#bounds', function() {
     var path = new Path.Circle([50, 50], 50);
     path.strokeColor = 'black';
     path.strokeWidth = 1;
@@ -21,30 +21,30 @@ test('placedSymbol bounds', function() {
     equals(path.strokeBounds,
         new Rectangle(-0.5, -0.5, 101, 101),
         'Path initial bounds');
-    var symbol = new Symbol(path);
-    var placedSymbol = new PlacedSymbol(symbol);
+    var definition = new SymbolDefinition(path);
+    var item = new SymbolItem(definition);
 
-    equals(placedSymbol.bounds,
+    equals(item.bounds,
         new Rectangle(-50.5, -50.5, 101, 101),
-        'PlacedSymbol initial bounds');
+        'SymbolItem initial bounds');
 
-    placedSymbol.scale(1, 0.5);
-    equals(placedSymbol.bounds,
+    item.scale(1, 0.5);
+    equals(item.bounds,
         new Rectangle(-50.5, -25.25, 101, 50.5),
         'Bounds after scale');
 
-    placedSymbol.rotate(40);
-    equals(placedSymbol.bounds,
+    item.rotate(40);
+    equals(item.bounds,
         new Rectangle(-41.96283, -37.79252, 83.92567, 75.58503),
         'Bounds after rotation');
 });
 
-test('bounds of group of symbol instances', function() {
+test('bounds of group of SymbolItem instances', function() {
     var path = new Path.Circle(new Point(), 10);
-    var symbol = new Symbol(path);
+    var definition = new SymbolDefinition(path);
     var instances = [];
     for (var i = 0; i < 10; i++) {
-        var instance = symbol.place(new Point(i * 20, 20));
+        var instance = definition.place(new Point(i * 20, 20));
         instances.push(instance);
     }
     var group = new Group(instances);
@@ -53,7 +53,7 @@ test('bounds of group of symbol instances', function() {
         'Group bounds');
 });
 
-test('bounds of a symbol that contains a group of items', function() {
+test('bounds of a SymbolItem that contains a group of items', function() {
     var path = new Path.Circle(new Point(), 10);
     var path2 = path.clone();
     path2.position.x += 20;
@@ -67,8 +67,8 @@ test('bounds of a symbol that contains a group of items', function() {
     equals(group.bounds,
         new Rectangle(-10, -10, 40, 20),
         'Group bounds');
-    var symbol = new Symbol(group);
-    var instance = symbol.place(new Point(50, 50));
+    var definition = new SymbolDefinition(group);
+    var instance = definition.place(new Point(50, 50));
     equals(instance.bounds,
         new Rectangle(30, 40, 40, 20),
         'Instance bounds');
@@ -77,16 +77,16 @@ test('bounds of a symbol that contains a group of items', function() {
 test('Changing the definition of a symbol should change the bounds of all instances of it.', function() {
     var path = new Path.Circle(new Point(), 10);
     var path2 = new Path.Circle(new Point(), 20);
-    var symbol = new Symbol(path);
-    var instance = symbol.place(new Point(0, 0));
+    var definition = new SymbolDefinition(path);
+    var instance = definition.place(new Point(0, 0));
     equals(instance.bounds,
         new Rectangle(-10, -10, 20, 20),
         'Initial bounds');
-    symbol.definition = path2;
+    definition.item = path2;
     equals(instance.bounds,
         new Rectangle(-20, -20, 40, 40),
         'Bounds after changing symbol definition');
-    symbol.definition.scale(0.5, 0.5);
+    definition.item.scale(0.5, 0.5);
     equals(instance.bounds,
         new Rectangle(-10, -10, 20, 20),
         'Bounds after modifying symbol definition');
@@ -95,25 +95,25 @@ test('Changing the definition of a symbol should change the bounds of all instan
 test('Symbol definition selection', function() {
     var path = new Path.Circle([50, 50], 50);
     path.selected = true;
-    var symbol = new Symbol(path);
+    var definition = new SymbolDefinition(path);
     equals(function() {
-        return symbol.definition.selected == false;
+        return definition.item.selected === false;
     }, true);
     equals(function() {
-        return paper.project.selectedItems.length == 0;
+        return paper.project.selectedItems.length === 0;
     }, true);
 });
 
 test('Symbol#place()', function() {
     var path = new Path.Circle([50, 50], 50);
-    var symbol = new Symbol(path);
-    var placedSymbol = symbol.place();
+    var definition = new SymbolDefinition(path);
+    var placedSymbol = definition.place();
     equals(function() {
         return placedSymbol.parent == paper.project.activeLayer;
     }, true);
 
     equals(function() {
-        return placedSymbol.symbol == symbol;
+        return placedSymbol.definition == definition;
     }, true);
 
     equals(function() {
@@ -123,8 +123,8 @@ test('Symbol#place()', function() {
 
 test('Symbol#place(position)', function() {
     var path = new Path.Circle([50, 50], 50);
-    var symbol = new Symbol(path);
-    var placedSymbol = symbol.place(new Point(100, 100));
+    var definition = new SymbolDefinition(path);
+    var placedSymbol = definition.place(new Point(100, 100));
     equals(function() {
         return placedSymbol.position.toString();
     }, '{ x: 100, y: 100 }');
diff --git a/test/tests/load.js b/test/tests/load.js
index 49f40fd3..4c3f55c2 100644
--- a/test/tests/load.js
+++ b/test/tests/load.js
@@ -51,7 +51,7 @@
 
 /*#*/ include('PathItem_Contains.js');
 
-/*#*/ include('PlacedSymbol.js');
+/*#*/ include('SymbolItem.js');
 
 /*#*/ include('Raster.js');