From 013fe56ea494cce36b741a54114b3ec98a48d205 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 19:35:26 +0200 Subject: [PATCH 1/8] Item#_clone: check if the item has a _pathStyle property before copying it. --- src/item/Item.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/item/Item.js b/src/item/Item.js index 6a838733..6fe3e944 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -33,8 +33,9 @@ var Item = this.Item = Base.extend({ }, _clone: function(copy) { - // Copy over style - copy.setStyle(this._style); + // If this item has a pathStyle, copy it: + if (this._style) + copy.setStyle(this._style); // If this item has children, clone and append each of them: if (this._children) { for (var i = 0, l = this._children.length; i < l; i++) From 8f5f5ee43c66b487a3a34f45dbaa5a75b948409a Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 19:39:12 +0200 Subject: [PATCH 2/8] Tests: add cloneAndCompare and compareItems helper functions. --- test/lib/helpers.js | 142 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/test/lib/helpers.js b/test/lib/helpers.js index b70aba0f..c7b97463 100644 --- a/test/lib/helpers.js +++ b/test/lib/helpers.js @@ -86,4 +86,146 @@ function compareGrayColors(color1, color2, message) { compareNumbers(color1.gray, color2.gray, (message || '') + ' gray'); +} + +function cloneAndCompare(item) { + var copy = item.clone(); + compareItems(item, copy); + // Remove the cloned item to restore the document: + copy.remove(); +} + +function compareItems(item, item2) { + equals(function() { + return item != item2; + }, true); + + var itemProperties = ['opacity', 'locked', 'visible', 'blendMode', 'name', + 'closed', 'selected']; + Base.each(itemProperties, function(key) { + equals(function() { + return item[key] == item2[key]; + }, true, 'item[\'' + key + '\'] == item2[\'' + key + '\']'); + }); + + equals(function() { + return item.id != item2.id; + }, true); + + if (item._matrix) { + equals(function() { + return item._matrix != item2._matrix; + }); + equals(item._matrix.toString(), item2._matrix.toString(), + 'item._matrix.toString() == item2._matrix.toString()'); + } + + if (item2.segments) { + equals(item.segments.toString(), item2.segments.toString(), + 'item.segments.toString() == item2.segments.toString()'); + } + + // Path specific + if (item instanceof PathItem) { + equals(function() { + return item._clockwise == item2._clockwise; + }, true); + } + + // Group specific + if (item instanceof Group) { + equals(function() { + return item._clipped == item2._clipped; + }, true); + } + + // Layer specific + if (item instanceof Layer) { + equals(function() { + return item.project == item2.project; + }, true); + } + + // PlacedSymbol specific + if (item instanceof PlacedSymbol) { + equals(function() { + return item.symbol == item2.symbol; + }, true); + } + + // TODO: Raster specific + + // TextItem specific: + if (item instanceof TextItem) { + equals(item.content, item2.content, 'item.content == item2.content'); + var characterStyleKeys = ['fontSize', 'font']; + Base.each(characterStyleKeys, function(key) { + equals(function() { + return item2.characterStyle[key]; + }, item.characterStyle[key], 'item.characterStyle[\'' + key + + '\'] == item2.characterStyle[\'' + key + '\']'); + }); + var paragraphStyleKeys = ['justification']; + Base.each(paragraphStyleKeys, function(key) { + equals(function() { + return item2.paragraphStyle[key]; + }, item.paragraphStyle[key], 'item.paragraphStyle[\'' + key + + '\'] == item2.paragraphStyle[\'' + key + '\']'); + }); + } + + // PointText specific: + if (item instanceof PointText) { + equals(item.point.toString(), item2.point.toString()); + } + + if (item._style) { + // Path Style + if (item.fillColor) { + // The fillColor should not point to the same color object: + equals(function() { + return item.fillColor != item2.fillColor; + }, true, 'The fillColor should not point to the same color object:'); + if (item.fillColor instanceof GradientColor) { + // TODO! + } else { + equals(item.fillColor.toString(), item2.fillColor.toString()); + } + } + + if (item.strokeColor) { + equals(function() { + return item.strokeColor != item2.strokeColor; + }, true, 'The strokeColor should not point to the same color object:'); + if (item.strokeColor instanceof GradientColor) { + // TODO + } else { + equals(item.strokeColor.toString(), item2.strokeColor.toString()); + } + } + + Base.each(['strokeCap', 'strokeJoin', 'dashOffset', 'miterLimit', + 'strokeOverprint', 'fillOverprint'], function(key) { + if (item[key]) { + equals(function() { + return item[key] == item2[key]; + }, true, 'item[\'' + key + '\'] == item2[\'' + key + '\']'); + } + }); + + if (item.dashArray) { + equals(item.dashArray.toString(), item2.dashArray.toString(), + 'item.dashArray.toString(), item2.dashArray.toString()'); + } + } + + // Check length of children and recursively compare them: + if (item.children) { + equals(function() { + return item.children.length == item2.children.length; + }, true); + for (var i = 0, l = item.children.length; i < l; i++) { + compareItems(item.children[i], item2.children[i]); + } + } } \ No newline at end of file From 64a142436b3b00da7117d1a3e0505bd8697f6d59 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 19:40:07 +0200 Subject: [PATCH 3/8] Tests: add item cloning tests. --- src/load.js | 1 + test/tests/Item_Cloning.js | 95 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/tests/Item_Cloning.js diff --git a/src/load.js b/src/load.js index dd50223f..f87a61d2 100644 --- a/src/load.js +++ b/src/load.js @@ -97,6 +97,7 @@ if (window.tests) { 'test/tests/Color.js', 'test/tests/Project.js', 'test/tests/Item.js', + 'test/tests/Item_Cloning.js', 'test/tests/Layer.js', 'test/tests/Group.js', 'test/tests/Segment.js', diff --git a/test/tests/Item_Cloning.js b/test/tests/Item_Cloning.js new file mode 100644 index 00000000..c16b6670 --- /dev/null +++ b/test/tests/Item_Cloning.js @@ -0,0 +1,95 @@ +test('Path#clone()', function() { + var proj = paper.project; + var path = new Path([10, 20], [30, 40]); + path.closed = true; + path.name = 'test'; + path.style = { + strokeCap: 'round', + strokeJoin: 'round', + dashOffset: 10, + dashArray: [10, 2, 10], + fillColor: new RGBColor(0, 0, 1), + strokeColor: new RGBColor(0, 0, 1), + miterLimit: 5 + }; + path.clockwise = false; + path.opacity = 0.5; + path.locked = true; + path.visible = false; + path.blendMode = 'blend'; + path._clipMask = true; + path.selected = true; + cloneAndCompare(path); +}); + +test('CompoundPath#clone()', function() { + var path1 = new Path.Rectangle([200, 200], [100, 100]); + var path2 = new Path.Rectangle([50, 50], [200, 200]); + var compound = new CompoundPath(path1, path2); + cloneAndCompare(compound); +}); + +test('Layer#clone()', function() { + var path = new Path.Rectangle([200, 200], [100, 100]); + cloneAndCompare(paper.project.activeLayer); +}); + +test('Group#clone()', function() { + var path = new Path.Circle([150, 150], 60); + path.style = { + strokeCap: 'round', + strokeJoin: 'round', + dashOffset: 10, + dashArray: [10, 2, 10], + fillColor: new RGBColor(0, 0, 1), + strokeColor: new RGBColor(0, 0, 1), + miterLimit: 5 + }; + var secondPath = new Path.Circle([175, 175], 85); + var group = new Group([path, secondPath]); + cloneAndCompare(group); +}); + +test('PointText#clone()', function() { + var pointText = new PointText(new Point(50, 50)); + pointText.content = 'test'; + pointText.position += 100; + pointText.characterStyle = { + font: 'serif', + fontSize: 20 + }; + pointText.paragraphStyle.justification = 'center'; + cloneAndCompare(pointText); +}); + +test('PlacedSymbol#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); +}); + +test('Symbol#clone()', function() { + var path = new Path.Circle([150, 150], 60); + path.style = { + strokeCap: 'round', + strokeJoin: 'round', + dashOffset: 10, + dashArray: [10, 2, 10], + fillColor: new RGBColor(0, 0, 1), + strokeColor: new RGBColor(0, 0, 1), + miterLimit: 5 + }; + path.selected = true; + var symbol = new Symbol(path); + var copy = symbol.clone(); + compareItems(symbol.definition, copy.definition); + equals(function() { + return symbol.project == copy.project; + }, true); + equals(function() { + return paper.project.symbols.length == 2; + }, true); +}); \ No newline at end of file From fc3833f15074876f0d9ed4f36d41f2d1fd7847fb Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 19:41:53 +0200 Subject: [PATCH 4/8] Fix PlacedSymbol#clone(). --- src/item/PlacedSymbol.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/item/PlacedSymbol.js b/src/item/PlacedSymbol.js index 8fbf4403..b05d10f3 100644 --- a/src/item/PlacedSymbol.js +++ b/src/item/PlacedSymbol.js @@ -28,7 +28,7 @@ var PlacedSymbol = this.PlacedSymbol = Item.extend({ }, clone: function() { - return this._clone(new PlacedSymbol(symbol, this.matrix.clone())); + return this._clone(new PlacedSymbol(this.symbol, this.matrix.clone())); }, _transform: function(matrix, flags) { From 2c94b4270a2d5582bd9a1c93466408a1a2f7ac92 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 21:29:47 +0200 Subject: [PATCH 5/8] Fix ParagraphStyle.create(item). --- src/text/ParagraphStyle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text/ParagraphStyle.js b/src/text/ParagraphStyle.js index 5381328b..6fcff771 100644 --- a/src/text/ParagraphStyle.js +++ b/src/text/ParagraphStyle.js @@ -23,7 +23,7 @@ var ParagraphStyle = this.ParagraphStyle = Base.extend({ statics: { create: function(item) { - var style = new CharacterStyle(CharacterStyle.dont); + var style = new ParagraphStyle(ParagraphStyle.dont); style._item = item; return style; } From f676cc026fae905af942e0f8682973150b1f9ae3 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 21:33:25 +0200 Subject: [PATCH 6/8] Add TextItem#_clone to copy over characterStyle and paragraphStyle. --- src/text/TextItem.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/text/TextItem.js b/src/text/TextItem.js index 6ebc6d19..0f6bc1d8 100644 --- a/src/text/TextItem.js +++ b/src/text/TextItem.js @@ -26,6 +26,12 @@ var TextItem = this.TextItem = Item.extend({ this.setParagraphStyle(); }, + _clone: function(copy) { + copy.setCharacterStyle(this._characterStyle); + copy.setParagraphStyle(this._paragraphStyle); + return this.base(copy); + }, + getCharacterStyle: function() { return this._characterStyle; }, From 8a1b1041cd27342914b7c7055ced185ffc242c95 Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 22:03:16 +0200 Subject: [PATCH 7/8] Make PointText#matrix 'private' by renaming to _matrix. --- src/text/PointText.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/text/PointText.js b/src/text/PointText.js index e48c63e6..d77898b5 100644 --- a/src/text/PointText.js +++ b/src/text/PointText.js @@ -21,18 +21,15 @@ var PointText = this.PointText = TextItem.extend({ this.base(); var point = Point.read(arguments); this.content = ''; - // TODO: Since we're exposing matrix, we actually need to extract _point - // from it each time getPoint is called, as it could be modified other - // than through PointText#transform(). this._point = LinkedPoint.create(this, 'setPoint', point.x, point.y); - this.matrix = new Matrix().translate(point); + this._matrix = new Matrix().translate(point); }, clone: function() { var copy = this._clone(new PointText(this._point)); copy.content = this.content; // Use Matrix#initialize to easily copy over values. - copy.matrix.initialize(this.matrix); + copy._matrix.initialize(this._matrix); return copy; }, @@ -56,7 +53,7 @@ var PointText = this.PointText = TextItem.extend({ }, _transform: function(matrix, flags) { - this.matrix.preConcatenate(matrix); + this._matrix.preConcatenate(matrix); // We need to transform the LinkedPoint, passing true for dontNotify so // chaning it won't trigger calls of setPoint(), leading to an endless // recursion. @@ -70,7 +67,7 @@ var PointText = this.PointText = TextItem.extend({ ctx.font = this._characterStyle.fontSize + 'pt ' + this._characterStyle.font; ctx.textAlign = this._paragraphStyle.justification; - this.matrix.applyToContext(ctx); + this._matrix.applyToContext(ctx); var fillColor = this.getFillColor(); var strokeColor = this.getStrokeColor(); From 682923301326a09e5c7238773e791ef74f278b7e Mon Sep 17 00:00:00 2001 From: Jonathan Puckey Date: Fri, 20 May 2011 22:03:46 +0200 Subject: [PATCH 8/8] Tests: Fix bug in compareItems helper function. --- test/lib/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/helpers.js b/test/lib/helpers.js index c7b97463..7b4d5549 100644 --- a/test/lib/helpers.js +++ b/test/lib/helpers.js @@ -115,7 +115,7 @@ function compareItems(item, item2) { if (item._matrix) { equals(function() { return item._matrix != item2._matrix; - }); + }, true); equals(item._matrix.toString(), item2._matrix.toString(), 'item._matrix.toString() == item2._matrix.toString()'); }