Implement Symbol clipping and handle positioning correctly.

Complicated stuff...
This commit is contained in:
Jürg Lehni 2013-03-01 11:19:47 -08:00
parent 2706c32924
commit bec61c6829
2 changed files with 28 additions and 13 deletions

View file

@ -58,12 +58,13 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
* instance.scale(0.25 + Math.random() * 0.75);
* }
*/
initialize: function(item) {
initialize: function(item, dontCenter) {
// Define this Symbols's unique id.
this._id = ++Base._uid;
this.project = paper.project;
this.project.symbols.push(this);
this.setDefinition(item);
if (item)
this.setDefinition(item, dontCenter);
// Hash to keep track of placed instances
this._instances = {};
},
@ -110,7 +111,7 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
return this._definition;
},
setDefinition: function(item) {
setDefinition: function(item /*, dontCenter */) {
// Make sure we're not steatling another symbol's definition
if (item._parentSymbol)
item = item.clone();
@ -122,7 +123,8 @@ var Symbol = this.Symbol = Base.extend(/** @lends Symbol# */{
item.remove();
item.setSelected(false);
// Move position to 0, 0, so it's centered when placed.
item.setPosition(new Point());
if (!arguments[1])
item.setPosition(new Point());
item._parentSymbol = this;
this._changed(/*#=*/ Change.GEOMETRY);
},

View file

@ -190,7 +190,8 @@ new function() {
// http://www.w3.org/TR/SVG/struct.html#SymbolElement
symbol: function(node, type) {
return new Symbol(importGroup(node, type));
// Pass true for dontCenter:
return new Symbol(importGroup(node, type), true);
},
// http://www.w3.org/TR/SVG/struct.html#DefsElement
@ -200,12 +201,15 @@ new function() {
use: function(node, type) {
// Note the namespaced xlink:href attribute is just called href
// as a property on node.
// TODO: Support overflow and width, height, in combination with
// overflow: hidden. Paper.js currently does not suport PlacedSymbol
// clipping, but perhaps it should?
var id = (getValue(node, 'href') || '').substring(1),
definition = definitions[id];
// Use place if we're dealing with a symbol:
return definition
? definition instanceof Symbol
? definition.place()
? definition.place(getPoint(node, 'x', 'y'))
: definition.clone()
: null;
},
@ -369,7 +373,7 @@ new function() {
item.setRampPoint(percentage ? percentage[1] / 100 : value);
},
viewBox: function(item, value, name, node) {
viewBox: function(item, value, name, node, styles) {
// http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
// TODO: implement preserveAspectRatio attribute
var values = convertValue(value, 'array'),
@ -377,17 +381,26 @@ new function() {
size = getSize(node, 'width', 'height', true),
scale = size ? rectangle.getSize().divide(size) : 1,
offset = rectangle.getPoint(),
matrix = new Matrix().translate(offset).scale(scale);
matrix = new Matrix().translate(offset).scale(scale),
clip = getAttribute(node, 'overflow', styles) != 'visible';
if (size)
rectangle.setSize(size);
if (item instanceof Symbol) {
matrix.translate(rectangle.getSize().divide(-2));
item._definition.transform(matrix);
var definition = item._definition;
definition.transform(matrix);
if (clip && !rectangle.contains(definition.getBounds())) {
// Pass true for dontCenter, since we don't want to change
// positioning of our definition again.
item.setDefinition(createClipGroup(definition,
new Path.Rectangle(rectangle).transform(
definition._matrix)), true);
}
} else {
item.transform(matrix.inverted());
rectangle.setPoint(0);
// TODO: the viewBox does not always need to be clipped
return createClipGroup(item, new Path.Rectangle(rectangle));
if (clip) {
rectangle.setPoint(0);
return createClipGroup(item, new Path.Rectangle(rectangle));
}
}
}
});