var CompoundPath = this.CompoundPath = PathItem.extend({ initialize: function(items) { this.base(); this.children = []; if (items) { for (var i = 0, l = items.length; i < l; i++) { this.appendTop(items[i]); } } }, // TODO: have getBounds of Group / Layer / CompoundPath use the same // code (from a utility script?) getBounds: function() { if (this.children.length) { var rect = this.children[0].bounds; var x1 = rect.x; var y1 = rect.y; var x2 = rect.x + rect.width; var y2 = rect.y + rect.height; for (var i = 1, l = this.children.length; i < l; i++) { var rect2 = this.children[i].bounds; x1 = Math.min(rect2.x, x1); y1 = Math.min(rect2.y, y1); x2 = Math.max(rect2.x + rect2.width, x1 + x2 - x1); y2 = Math.max(rect2.y + rect2.height, y1 + y2 - y1); } } return new Rectangle(x1, y1, x2 - x1, y2 - y1); }, /** * If this is a compound path with only one path inside, * the path is moved outside and the compound path is erased. * Otherwise, the compound path is returned unmodified. * * @return the simplified compound path. */ simplify: function() { if (this.children.length == 1) { var child = this.children[0]; child.moveAbove(this); this.remove(); return child; } return this; }, smooth: function() { for (var i = 0, l = this.children.length; i < l; i++) { this.children[i].smooth(); } }, moveTo: function() { var path = new Path(); this.appendTop(path); path.moveTo.apply(path, arguments); }, draw: function(ctx, param) { var firstChild = this.children[0]; ctx.beginPath(); param.compound = true; for (var i = 0, l = this.children.length; i < l; i++) { Item.draw(this.children[i], ctx, param); } firstChild.setCtxStyles(ctx); if (firstChild.fillColor) { ctx.fillStyle = firstChild.fillColor.toCssString(); ctx.fill(); } if (firstChild.strokeColor) { ctx.strokeStyle = firstChild.strokeColor.toCssString(); ctx.stroke(); } } }, new function() { function getCurrentPath(that) { if (that.children.length) { return that.children[that.children.length - 1]; } else { throw new Error('Use a moveTo() command first'); } } var fields = { moveBy: function() { var point = arguments.length ? Point.read(arguments) : new Point(); var path = getCurrentPath(this); var current = path.segments[path.segments.length - 1].point; this.moveTo(current.add(point)); }, closePath: function() { var path = getCurrentPath(this); path.setClosed(true); } }; Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo', 'arcTo', 'lineBy', 'curveBy', 'arcBy'], function(key) { fields[key] = function() { var path = getCurrentPath(this); path[key].apply(path, arguments); }; }); return fields; });