paper 0.12.19 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +250 -0
  2. package/README.md +34 -27
  3. package/dist/docs/assets/js/paper.js +791 -366
  4. package/dist/docs/classes/Color.html +63 -47
  5. package/dist/docs/classes/CompoundPath.html +162 -59
  6. package/dist/docs/classes/Curve.html +9 -7
  7. package/dist/docs/classes/CurveLocation.html +1 -1
  8. package/dist/docs/classes/Event.html +1 -1
  9. package/dist/docs/classes/Gradient.html +1 -1
  10. package/dist/docs/classes/GradientStop.html +1 -1
  11. package/dist/docs/classes/Group.html +63 -24
  12. package/dist/docs/classes/HitResult.html +1 -1
  13. package/dist/docs/classes/Item.html +63 -24
  14. package/dist/docs/classes/Key.html +1 -1
  15. package/dist/docs/classes/KeyEvent.html +1 -1
  16. package/dist/docs/classes/Layer.html +63 -24
  17. package/dist/docs/classes/Matrix.html +1 -1
  18. package/dist/docs/classes/MouseEvent.html +1 -1
  19. package/dist/docs/classes/PaperScope.html +87 -1
  20. package/dist/docs/classes/PaperScript.html +1 -1
  21. package/dist/docs/classes/Path.html +174 -68
  22. package/dist/docs/classes/PathItem.html +280 -177
  23. package/dist/docs/classes/Point.html +143 -21
  24. package/dist/docs/classes/PointText.html +94 -24
  25. package/dist/docs/classes/Project.html +14 -8
  26. package/dist/docs/classes/Raster.html +93 -35
  27. package/dist/docs/classes/Rectangle.html +12 -11
  28. package/dist/docs/classes/Segment.html +1 -1
  29. package/dist/docs/classes/Shape.html +63 -24
  30. package/dist/docs/classes/Size.html +81 -21
  31. package/dist/docs/classes/Style.html +34 -2
  32. package/dist/docs/classes/SymbolDefinition.html +1 -1
  33. package/dist/docs/classes/SymbolItem.html +64 -25
  34. package/dist/docs/classes/TextItem.html +94 -24
  35. package/dist/docs/classes/Tool.html +2 -1
  36. package/dist/docs/classes/ToolEvent.html +27 -1
  37. package/dist/docs/classes/Tween.html +1 -1
  38. package/dist/docs/classes/View.html +203 -10
  39. package/dist/docs/classes/global.html +1 -1
  40. package/dist/docs/classes/index.html +2 -2
  41. package/dist/docs/index.html +1 -1
  42. package/dist/node/canvas.js +10 -8
  43. package/dist/node/self.js +13 -4
  44. package/dist/paper-core.js +772 -355
  45. package/dist/paper-core.min.js +3 -3
  46. package/dist/paper-full.js +791 -366
  47. package/dist/paper-full.min.js +3 -3
  48. package/dist/paper.d.ts +324 -73
  49. package/examples/Rasters/Smoothing.html +1 -1
  50. package/package.json +5 -11
  51. package/dist/node/xml.js +0 -40
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Paper.js v0.12.19 - The Swiss Army Knife of Vector Graphics Scripting.
2
+ * Paper.js v0.13.0 - The Swiss Army Knife of Vector Graphics Scripting.
3
3
  * http://paperjs.org/
4
4
  *
5
5
  * Copyright (c) 2011 - 2020, Jürg Lehni & Jonathan Puckey
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * All rights reserved.
11
11
  *
12
- * Date: Sun Oct 18 13:05:31 2026 +0200
12
+ * Date: Mon Oct 19 15:31:53 2026 +0200
13
13
  *
14
14
  ***
15
15
  *
@@ -36,6 +36,9 @@ self = self || require('./node/self.js');
36
36
  var window = self.window,
37
37
  document = self.document;
38
38
 
39
+ if (window && !document.createElement('canvas').getContext('2d'))
40
+ window = null;
41
+
39
42
  var Base = new function() {
40
43
  var hidden = /^(statics|enumerable|beans|preserve)$/,
41
44
  array = [],
@@ -821,7 +824,7 @@ var PaperScope = Base.extend({
821
824
  }
822
825
  },
823
826
 
824
- version: "0.12.19",
827
+ version: "0.13.0",
825
828
 
826
829
  getView: function() {
827
830
  var project = this.project;
@@ -1649,6 +1652,16 @@ var Point = Base.extend({
1649
1652
  );
1650
1653
  },
1651
1654
 
1655
+ clamp: function() {
1656
+ var args = arguments,
1657
+ min = Point.read(args),
1658
+ max = Point.read(args);
1659
+ return new Point(
1660
+ Numerical.clamp(this.x, min.x, max.x),
1661
+ Numerical.clamp(this.y, min.y, max.y)
1662
+ );
1663
+ },
1664
+
1652
1665
  statics: {
1653
1666
  min: function() {
1654
1667
  var args = arguments,
@@ -1930,10 +1943,11 @@ var Rectangle = Base.extend({
1930
1943
  arg0.width || 0, arg0.height || 0);
1931
1944
  read = 1;
1932
1945
  } else if (arg0.from === undefined && arg0.to === undefined) {
1933
- this._set(0, 0, 0, 0);
1934
- if (Base.readSupported(args, this)) {
1946
+ var builder = new RectangleBuilder();
1947
+ if (Base.readSupported(args, builder)) {
1935
1948
  read = 1;
1936
1949
  }
1950
+ this._set(builder.x, builder.y, builder.width, builder.height);
1937
1951
  }
1938
1952
  }
1939
1953
  if (read === undefined) {
@@ -2028,24 +2042,10 @@ var Rectangle = Base.extend({
2028
2042
  return new ctor(this.width, this.height, this, 'setSize');
2029
2043
  },
2030
2044
 
2031
- _fw: 1,
2032
- _fh: 1,
2033
-
2034
2045
  setSize: function() {
2035
- var size = Size.read(arguments),
2036
- sx = this._sx,
2037
- sy = this._sy,
2038
- w = size.width,
2039
- h = size.height;
2040
- if (sx) {
2041
- this.x += (this.width - w) * sx;
2042
- }
2043
- if (sy) {
2044
- this.y += (this.height - h) * sy;
2045
- }
2046
- this.width = w;
2047
- this.height = h;
2048
- this._fw = this._fh = 1;
2046
+ var size = Size.read(arguments);
2047
+ this.width = size.width;
2048
+ this.height = size.height;
2049
2049
  },
2050
2050
 
2051
2051
  getLeft: function() {
@@ -2053,12 +2053,8 @@ var Rectangle = Base.extend({
2053
2053
  },
2054
2054
 
2055
2055
  setLeft: function(left) {
2056
- if (!this._fw) {
2057
- var amount = left - this.x;
2058
- this.width -= this._sx === 0.5 ? amount * 2 : amount;
2059
- }
2056
+ this.width -= left - this.x;
2060
2057
  this.x = left;
2061
- this._sx = this._fw = 0;
2062
2058
  },
2063
2059
 
2064
2060
  getTop: function() {
@@ -2066,12 +2062,8 @@ var Rectangle = Base.extend({
2066
2062
  },
2067
2063
 
2068
2064
  setTop: function(top) {
2069
- if (!this._fh) {
2070
- var amount = top - this.y;
2071
- this.height -= this._sy === 0.5 ? amount * 2 : amount;
2072
- }
2065
+ this.height -= top - this.y;
2073
2066
  this.y = top;
2074
- this._sy = this._fh = 0;
2075
2067
  },
2076
2068
 
2077
2069
  getRight: function() {
@@ -2079,13 +2071,7 @@ var Rectangle = Base.extend({
2079
2071
  },
2080
2072
 
2081
2073
  setRight: function(right) {
2082
- if (!this._fw) {
2083
- var amount = right - this.x;
2084
- this.width = this._sx === 0.5 ? amount * 2 : amount;
2085
- }
2086
- this.x = right - this.width;
2087
- this._sx = 1;
2088
- this._fw = 0;
2074
+ this.width = right - this.x;
2089
2075
  },
2090
2076
 
2091
2077
  getBottom: function() {
@@ -2093,13 +2079,7 @@ var Rectangle = Base.extend({
2093
2079
  },
2094
2080
 
2095
2081
  setBottom: function(bottom) {
2096
- if (!this._fh) {
2097
- var amount = bottom - this.y;
2098
- this.height = this._sy === 0.5 ? amount * 2 : amount;
2099
- }
2100
- this.y = bottom - this.height;
2101
- this._sy = 1;
2102
- this._fh = 0;
2082
+ this.height = bottom - this.y;
2103
2083
  },
2104
2084
 
2105
2085
  getCenterX: function() {
@@ -2107,16 +2087,7 @@ var Rectangle = Base.extend({
2107
2087
  },
2108
2088
 
2109
2089
  setCenterX: function(x) {
2110
- if (this._fw || this._sx === 0.5) {
2111
- this.x = x - this.width / 2;
2112
- } else {
2113
- if (this._sx) {
2114
- this.x += (x - this.x) * 2 * this._sx;
2115
- }
2116
- this.width = (x - this.x) * 2;
2117
- }
2118
- this._sx = 0.5;
2119
- this._fw = 0;
2090
+ this.x = x - this.width / 2;
2120
2091
  },
2121
2092
 
2122
2093
  getCenterY: function() {
@@ -2124,16 +2095,7 @@ var Rectangle = Base.extend({
2124
2095
  },
2125
2096
 
2126
2097
  setCenterY: function(y) {
2127
- if (this._fh || this._sy === 0.5) {
2128
- this.y = y - this.height / 2;
2129
- } else {
2130
- if (this._sy) {
2131
- this.y += (y - this.y) * 2 * this._sy;
2132
- }
2133
- this.height = (y - this.y) * 2;
2134
- }
2135
- this._sy = 0.5;
2136
- this._fh = 0;
2098
+ this.y = y - this.height / 2;
2137
2099
  },
2138
2100
 
2139
2101
  getCenter: function(_dontLink) {
@@ -2319,6 +2281,94 @@ new function() {
2319
2281
  );
2320
2282
  });
2321
2283
 
2284
+ var RectangleBuilder = Rectangle.extend({
2285
+ beans: true,
2286
+
2287
+ _fw: 1,
2288
+ _fh: 1,
2289
+
2290
+ setSize: function() {
2291
+ var size = Size.read(arguments),
2292
+ sx = this._sx,
2293
+ sy = this._sy,
2294
+ w = size.width,
2295
+ h = size.height;
2296
+ if (sx) {
2297
+ this.x += (this.width - w) * sx;
2298
+ }
2299
+ if (sy) {
2300
+ this.y += (this.height - h) * sy;
2301
+ }
2302
+ this.width = w;
2303
+ this.height = h;
2304
+ this._fw = this._fh = 1;
2305
+ },
2306
+
2307
+ setLeft: function(left) {
2308
+ if (!this._fw) {
2309
+ var amount = left - this.x;
2310
+ this.width -= this._sx === 0.5 ? amount * 2 : amount;
2311
+ }
2312
+ this.x = left;
2313
+ this._sx = this._fw = 0;
2314
+ },
2315
+
2316
+ setTop: function(top) {
2317
+ if (!this._fh) {
2318
+ var amount = top - this.y;
2319
+ this.height -= this._sy === 0.5 ? amount * 2 : amount;
2320
+ }
2321
+ this.y = top;
2322
+ this._sy = this._fh = 0;
2323
+ },
2324
+
2325
+ setRight: function(right) {
2326
+ if (!this._fw) {
2327
+ var amount = right - this.x;
2328
+ this.width = this._sx === 0.5 ? amount * 2 : amount;
2329
+ }
2330
+ this.x = right - this.width;
2331
+ this._sx = 1;
2332
+ this._fw = 0;
2333
+ },
2334
+
2335
+ setBottom: function(bottom) {
2336
+ if (!this._fh) {
2337
+ var amount = bottom - this.y;
2338
+ this.height = this._sy === 0.5 ? amount * 2 : amount;
2339
+ }
2340
+ this.y = bottom - this.height;
2341
+ this._sy = 1;
2342
+ this._fh = 0;
2343
+ },
2344
+
2345
+ setCenterX: function(x) {
2346
+ if (this._fw || this._sx === 0.5) {
2347
+ this.x = x - this.width / 2;
2348
+ } else {
2349
+ if (this._sx) {
2350
+ this.x += (x - this.x) * 2 * this._sx;
2351
+ }
2352
+ this.width = (x - this.x) * 2;
2353
+ }
2354
+ this._sx = 0.5;
2355
+ this._fw = 0;
2356
+ },
2357
+
2358
+ setCenterY: function(y) {
2359
+ if (this._fh || this._sy === 0.5) {
2360
+ this.y = y - this.height / 2;
2361
+ } else {
2362
+ if (this._sy) {
2363
+ this.y += (y - this.y) * 2 * this._sy;
2364
+ }
2365
+ this.height = (y - this.y) * 2;
2366
+ }
2367
+ this._sy = 0.5;
2368
+ this._fh = 0;
2369
+ }
2370
+ });
2371
+
2322
2372
  var Matrix = Base.extend({
2323
2373
  _class: 'Matrix',
2324
2374
 
@@ -2870,8 +2920,10 @@ var Line = Base.extend({
2870
2920
  : vy === 0 ? (vx < 0 ? y - py : py - y)
2871
2921
  : ((x - px) * vy - (y - py) * vx) / (
2872
2922
  vy > vx
2873
- ? vy * Math.sqrt(1 + (vx * vx) / (vy * vy))
2874
- : vx * Math.sqrt(1 + (vy * vy) / (vx * vx))
2923
+ ? Math.abs(vy)
2924
+ * Math.sqrt(1 + (vx * vx) / (vy * vy))
2925
+ : Math.abs(vx)
2926
+ * Math.sqrt(1 + (vy * vy) / (vx * vx))
2875
2927
  );
2876
2928
  },
2877
2929
 
@@ -3008,10 +3060,10 @@ var Project = PaperScopeItem.extend({
3008
3060
  return items;
3009
3061
  },
3010
3062
 
3011
- _updateSelection: function(item) {
3063
+ _updateSelection: function(item, remove) {
3012
3064
  var id = item._id,
3013
3065
  selectionItems = this._selectionItems;
3014
- if (item._selection) {
3066
+ if (item._selection && !remove && item.isInserted()) {
3015
3067
  if (selectionItems[id] !== item) {
3016
3068
  this._selectionCount++;
3017
3069
  selectionItems[id] = item;
@@ -3120,7 +3172,7 @@ var Project = PaperScopeItem.extend({
3120
3172
 
3121
3173
  if (this._selectionCount > 0) {
3122
3174
  ctx.save();
3123
- ctx.strokeWidth = 1;
3175
+ ctx.lineWidth = 1;
3124
3176
  var items = this._selectionItems,
3125
3177
  size = this._scope.settings.handleSize,
3126
3178
  version = this._updateVersion;
@@ -3183,11 +3235,13 @@ new function() {
3183
3235
  function(name) {
3184
3236
  this._events[name] = {
3185
3237
  install: function(type) {
3186
- this.getView()._countItemEvent(type, 1);
3238
+ if (this.isInserted())
3239
+ this.getView()._countItemEvent(type, 1);
3187
3240
  },
3188
3241
 
3189
3242
  uninstall: function(type) {
3190
- this.getView()._countItemEvent(type, -1);
3243
+ if (this.isInserted())
3244
+ this.getView()._countItemEvent(type, -1);
3191
3245
  }
3192
3246
  };
3193
3247
  }, {
@@ -3496,8 +3550,8 @@ new function() {
3496
3550
  bounds = this.getBounds();
3497
3551
  }
3498
3552
  matrix.scale(
3499
- bounds.width !== 0 ? rect.width / bounds.width : 0,
3500
- bounds.height !== 0 ? rect.height / bounds.height : 0);
3553
+ bounds.width !== 0 ? rect.width / bounds.width : 1,
3554
+ bounds.height !== 0 ? rect.height / bounds.height : 1);
3501
3555
  }
3502
3556
  center = bounds.getCenter();
3503
3557
  matrix.translate(-center.x, -center.y);
@@ -3521,14 +3575,18 @@ new function() {
3521
3575
  },
3522
3576
 
3523
3577
  _getCachedBounds: function(matrix, options, noInternal) {
3524
- matrix = matrix && matrix._orNullIfIdentity();
3525
3578
  var internal = options.internal && !noInternal,
3526
3579
  cacheItem = options.cacheItem,
3527
- _matrix = internal ? null : this._matrix._orNullIfIdentity(),
3528
- cacheKey = cacheItem && (!matrix || matrix.equals(_matrix))
3580
+ _matrix = internal ? null : this._matrix._orNullIfIdentity();
3581
+ matrix = matrix ? matrix._orNullIfIdentity() : _matrix;
3582
+ var cacheKey = cacheItem && (matrix ? matrix.equals(_matrix) : !_matrix)
3529
3583
  && this._getBoundsCacheKey(options, internal),
3584
+ isIntermediate = cacheKey && cacheItem !== this
3585
+ && (this._children || this._definition),
3530
3586
  bounds = this._bounds;
3531
3587
  Item._updateBoundsCache(this._parent || this._symbol, cacheItem);
3588
+ if (isIntermediate)
3589
+ Item._updateBoundsCache(this, cacheItem);
3532
3590
  if (cacheKey && bounds && cacheKey in bounds) {
3533
3591
  var cached = bounds[cacheKey];
3534
3592
  return {
@@ -3536,7 +3594,9 @@ new function() {
3536
3594
  nonscaling: cached.nonscaling
3537
3595
  };
3538
3596
  }
3539
- var res = this._getBounds(matrix || _matrix, options),
3597
+ var res = this._getBounds(matrix, isIntermediate
3598
+ ? Base.set({}, options, { cacheItem: this })
3599
+ : options),
3540
3600
  rect = res.rect || res,
3541
3601
  style = this._style,
3542
3602
  nonscaling = res.nonscaling || style.hasStroke()
@@ -3700,27 +3760,14 @@ new function() {
3700
3760
  },
3701
3761
 
3702
3762
  getGlobalMatrix: function(_dontClone) {
3703
- var matrix = this._globalMatrix;
3704
- if (matrix) {
3705
- var parent = this._parent;
3706
- var parents = [];
3707
- while (parent) {
3708
- if (!parent._globalMatrix) {
3709
- matrix = null;
3710
- for (var i = 0, l = parents.length; i < l; i++) {
3711
- parents[i]._globalMatrix = null;
3712
- }
3713
- break;
3714
- }
3715
- parents.push(parent);
3716
- parent = parent._parent;
3717
- }
3718
- }
3719
- if (!matrix) {
3763
+ var parent = this._parent,
3764
+ parentMatrix = parent && parent.getGlobalMatrix(true),
3765
+ matrix = this._globalMatrix;
3766
+ if (!matrix || this._parentGlobalMatrix !== parentMatrix) {
3720
3767
  matrix = this._globalMatrix = this._matrix.clone();
3721
- var parent = this._parent;
3722
- if (parent)
3723
- matrix.prepend(parent.getGlobalMatrix(true));
3768
+ if (parentMatrix)
3769
+ matrix.prepend(parentMatrix);
3770
+ this._parentGlobalMatrix = parentMatrix;
3724
3771
  }
3725
3772
  return _dontClone ? matrix : matrix.clone();
3726
3773
  },
@@ -3747,13 +3794,10 @@ new function() {
3747
3794
 
3748
3795
  _setProject: function(project, installEvents) {
3749
3796
  if (this._project !== project) {
3750
- if (this._project)
3751
- this._installEvents(false);
3752
3797
  this._project = project;
3753
3798
  var children = this._children;
3754
3799
  for (var i = 0, l = children && children.length; i < l; i++)
3755
3800
  children[i]._setProject(project);
3756
- installEvents = true;
3757
3801
  }
3758
3802
  if (installEvents)
3759
3803
  this._installEvents(true);
@@ -3765,6 +3809,8 @@ new function() {
3765
3809
 
3766
3810
  _installEvents: function _installEvents(install) {
3767
3811
  _installEvents.base.call(this, install);
3812
+ if (this._selection)
3813
+ this._project._updateSelection(this, !install);
3768
3814
  var children = this._children;
3769
3815
  for (var i = 0, l = children && children.length; i < l; i++)
3770
3816
  children[i]._installEvents(install);
@@ -3852,7 +3898,8 @@ new function() {
3852
3898
  var copy = new this.constructor(Item.NO_INSERT),
3853
3899
  children = this._children,
3854
3900
  insert = Base.pick(options ? options.insert : undefined,
3855
- options === undefined || options === true),
3901
+ typeof options === 'boolean' ? options
3902
+ : paper.settings.insertItems),
3856
3903
  deep = Base.pick(options ? options.deep : undefined, true);
3857
3904
  if (children)
3858
3905
  copy.copyAttributes(this);
@@ -3940,7 +3987,7 @@ new function() {
3940
3987
  .translate(topLeft.add(boundsSize.divide(2)))
3941
3988
  .scale(1 / scale)
3942
3989
  );
3943
- if (insert === undefined || insert) {
3990
+ if (Base.pick(insert, paper.settings.insertItems)) {
3944
3991
  raster.insertAbove(this);
3945
3992
  }
3946
3993
  return raster;
@@ -3973,6 +4020,7 @@ new function() {
3973
4020
  _asPathItem: function() {
3974
4021
  return new Path.Rectangle({
3975
4022
  rectangle: this.getInternalBounds(),
4023
+ applyMatrix: false,
3976
4024
  matrix: this._matrix,
3977
4025
  insert: false,
3978
4026
  });
@@ -4036,14 +4084,16 @@ new function() {
4036
4084
  }
4037
4085
 
4038
4086
  var matrix = this._matrix,
4087
+ pointMatrix = parentViewMatrix ? matrix : this.getGlobalMatrix(),
4039
4088
  viewMatrix = parentViewMatrix
4040
4089
  ? parentViewMatrix.appended(matrix)
4041
- : this.getGlobalMatrix().prepend(this.getView()._matrix),
4090
+ : pointMatrix.prepended(this.getView()._matrix),
4042
4091
  tolerance = Math.max(options.tolerance, 1e-12),
4043
4092
  tolerancePadding = options._tolerancePadding = new Size(
4044
- Path._getStrokePadding(tolerance,
4045
- matrix._shiftless().invert()));
4046
- point = matrix._inverseTransform(point);
4093
+ Path._getStrokePadding(tolerance, viewMatrix
4094
+ .prepended(this.getView()._matrix.inverted())
4095
+ ._shiftless().invert()));
4096
+ point = pointMatrix._inverseTransform(point);
4047
4097
  if (!point || !this._children &&
4048
4098
  !this.getBounds({ internal: true, stroke: true, handle: true })
4049
4099
  .expand(tolerancePadding.multiply(2))._containsPoint(point)) {
@@ -4108,7 +4158,7 @@ new function() {
4108
4158
  || null;
4109
4159
  }
4110
4160
  if (res && res.point) {
4111
- res.point = matrix.transform(res.point);
4161
+ res.point = pointMatrix.transform(res.point);
4112
4162
  }
4113
4163
  return res;
4114
4164
  },
@@ -4188,7 +4238,7 @@ new function() {
4188
4238
  rect = bounds && Rectangle.read([bounds]);
4189
4239
  param = {
4190
4240
  items: [],
4191
- recursive: obj && obj.recursive !== false,
4241
+ recursive: !obj || obj.recursive !== false,
4192
4242
  inside: !!inside,
4193
4243
  overlapping: !!overlapping,
4194
4244
  rect: rect,
@@ -4382,13 +4432,13 @@ new function() {
4382
4432
  if (owner) {
4383
4433
  if (this._name)
4384
4434
  this._removeNamed();
4435
+ this._installEvents(false);
4385
4436
  if (index != null) {
4386
4437
  if (project._activeLayer === this)
4387
4438
  project._activeLayer = this.getNextSibling()
4388
4439
  || this.getPreviousSibling();
4389
4440
  Base.splice(owner._children, null, index, 1);
4390
4441
  }
4391
- this._installEvents(false);
4392
4442
  if (notifySelf && project._changes)
4393
4443
  this._changed(5);
4394
4444
  if (notifyParent)
@@ -4647,30 +4697,46 @@ new function() {
4647
4697
  return this._matrix._transformPoint(Point.read(arguments));
4648
4698
  },
4649
4699
 
4650
- fitBounds: function(rectangle, fill) {
4700
+ fitBounds: function(rectangle, fit) {
4651
4701
  rectangle = Rectangle.read(arguments);
4652
- fill = Base.read(arguments);
4702
+ fit = Base.read(arguments);
4703
+ if (fit === true)
4704
+ fit = 'cover';
4653
4705
  var bounds = this.getBounds(),
4654
- itemRatio = bounds.height / bounds.width,
4655
- rectRatio = rectangle.height / rectangle.width,
4656
- scale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)
4657
- ? rectangle.width / bounds.width
4658
- : rectangle.height / bounds.height,
4659
- newBounds = new Rectangle(new Point(),
4660
- new Size(bounds.width * scale, bounds.height * scale));
4661
- newBounds.setCenter(rectangle.getCenter());
4662
- this.setBounds(newBounds);
4706
+ hor = rectangle.width / bounds.width,
4707
+ ver = rectangle.height / bounds.height,
4708
+ size;
4709
+
4710
+ function isScaling(ratio) {
4711
+ return ratio > 0 && isFinite(ratio);
4712
+ }
4713
+
4714
+ if (fit === 'fill') {
4715
+ size = new Size(
4716
+ isScaling(hor) ? rectangle.width : bounds.width,
4717
+ isScaling(ver) ? rectangle.height : bounds.height);
4718
+ } else {
4719
+ var ratios = [hor, ver].filter(isScaling),
4720
+ scale = !ratios.length ? 1
4721
+ : fit === 'cover' ? Math.max.apply(Math, ratios)
4722
+ : Math.min.apply(Math, ratios);
4723
+ size = bounds.getSize().multiply(scale);
4724
+ }
4725
+ this.setBounds(new Rectangle(new Point(), size)
4726
+ .setCenter(rectangle.getCenter()));
4663
4727
  }
4664
4728
  }), {
4665
4729
 
4666
- _setStyles: function(ctx, param, viewMatrix) {
4730
+ _setStyles: function(ctx, param, viewMatrix, strokeMatrix) {
4667
4731
  var style = this._style,
4668
4732
  matrix = this._matrix;
4669
4733
  if (style.hasFill()) {
4670
- ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx, matrix);
4734
+ ctx.fillStyle = style.getFillColor().toCanvasStyle(ctx, matrix,
4735
+ strokeMatrix);
4671
4736
  }
4672
4737
  if (style.hasStroke()) {
4673
- ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx, matrix);
4738
+ ctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx,
4739
+ matrix, strokeMatrix);
4674
4740
  ctx.lineWidth = style.getStrokeWidth();
4675
4741
  var strokeJoin = style.getStrokeJoin(),
4676
4742
  strokeCap = style.getStrokeCap(),
@@ -4715,7 +4781,8 @@ new function() {
4715
4781
  var matrices = param.matrices,
4716
4782
  viewMatrix = param.viewMatrix,
4717
4783
  matrix = this._matrix,
4718
- globalMatrix = matrices[matrices.length - 1].appended(matrix);
4784
+ parentMatrix = matrices[matrices.length - 1],
4785
+ globalMatrix = parentMatrix.appended(matrix);
4719
4786
  if (!globalMatrix.isInvertible())
4720
4787
  return;
4721
4788
 
@@ -4725,6 +4792,7 @@ new function() {
4725
4792
  matrices.push(globalMatrix);
4726
4793
  if (param.updateMatrix) {
4727
4794
  this._globalMatrix = globalMatrix;
4795
+ this._parentGlobalMatrix = this._parent && parentMatrix;
4728
4796
  }
4729
4797
 
4730
4798
  var blendMode = this._blendMode,
@@ -4739,8 +4807,23 @@ new function() {
4739
4807
  pixelRatio = param.pixelRatio || 1,
4740
4808
  mainCtx, itemOffset, prevOffset;
4741
4809
  if (!direct) {
4742
- var bounds = this.getStrokeBounds(viewMatrix);
4743
- if (!bounds.width || !bounds.height) {
4810
+ var bounds = this.getStrokeBounds(viewMatrix),
4811
+ style = this._style;
4812
+ if (style.getShadowColor(true)) {
4813
+ var mx = viewMatrix._shiftless(),
4814
+ blur = mx.transform(
4815
+ new Point(style.getShadowBlur(true), 0)),
4816
+ offset = mx.transform(style.getShadowOffset(true));
4817
+ bounds = bounds.unite(
4818
+ new Rectangle(bounds.getPoint().add(offset),
4819
+ bounds.getSize()).expand(blur.getLength() * 3));
4820
+ }
4821
+ var canvas = ctx.canvas;
4822
+ bounds = bounds.intersect(
4823
+ new Rectangle(new Point(param.offset),
4824
+ new Size(canvas.width, canvas.height)
4825
+ .divide(pixelRatio)));
4826
+ if (bounds.width <= 0 || bounds.height <= 0) {
4744
4827
  matrices.pop();
4745
4828
  return;
4746
4829
  }
@@ -4766,11 +4849,16 @@ new function() {
4766
4849
  } else if (transform) {
4767
4850
  ctx.translate(-itemOffset.x, -itemOffset.y);
4768
4851
  }
4769
- if (transform) {
4770
- (direct ? matrix : viewMatrix).applyToContext(ctx);
4771
- }
4772
4852
  if (clip) {
4773
- param.clipItem.draw(ctx, param.extend({ clip: true }));
4853
+ (param.viewMatrix ? param.viewMatrix.appended(parentMatrix)
4854
+ : parentMatrix).applyToContext(ctx);
4855
+ param.clipItem.draw(ctx, param.extend({
4856
+ clip: true,
4857
+ matrices: matrices.slice(0, -1)
4858
+ }));
4859
+ matrix.applyToContext(ctx);
4860
+ } else if (transform) {
4861
+ (direct ? matrix : viewMatrix).applyToContext(ctx);
4774
4862
  }
4775
4863
  if (strokeMatrix) {
4776
4864
  ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
@@ -4814,7 +4902,7 @@ new function() {
4814
4902
  if (!this._drawSelected)
4815
4903
  itemSelected = false;
4816
4904
  if ((itemSelected || boundsSelected || positionSelected)
4817
- && this._isUpdated(updateVersion)) {
4905
+ && this._isUpdated(updateVersion) && this.isInserted()) {
4818
4906
  var layer,
4819
4907
  color = this.getSelectedColor(true) || (layer = this.getLayer())
4820
4908
  && layer.getSelectedColor(true),
@@ -4985,10 +5073,21 @@ var Group = Item.extend({
4985
5073
  clipItem);
4986
5074
  },
4987
5075
 
5076
+ _hitTestSelf: function(point, options, viewMatrix) {
5077
+ if (options.match || options.class || options.type || options.all) {
5078
+ var res = this._hitTestChildren(point, options.extend({
5079
+ all: null, match: null, class: null, type: null
5080
+ }), viewMatrix);
5081
+ if (res)
5082
+ res.item = this;
5083
+ return res;
5084
+ }
5085
+ },
5086
+
4988
5087
  _draw: function(ctx, param) {
4989
5088
  var clip = param.clip,
4990
- clipItem = !clip && this._getClipItem();
4991
- param = param.extend({ clipItem: clipItem, clip: false });
5089
+ clipItem = this._getClipItem();
5090
+ param = param.extend({ clipItem: !clip && clipItem, clip: false });
4992
5091
  if (clip) {
4993
5092
  ctx.beginPath();
4994
5093
  param.dontStart = param.dontFinish = true;
@@ -5037,6 +5136,7 @@ var Shape = Item.extend({
5037
5136
  size: null,
5038
5137
  radius: null
5039
5138
  },
5139
+ _prioritize: ['type'],
5040
5140
 
5041
5141
  initialize: function Shape(props, point) {
5042
5142
  this._initialize(props, point);
@@ -5134,16 +5234,10 @@ var Shape = Item.extend({
5134
5234
  },
5135
5235
 
5136
5236
  toPath: function(insert) {
5137
- var path = new Path[Base.capitalize(this._type)]({
5138
- center: new Point(),
5139
- size: this._size,
5140
- radius: this._radius,
5141
- insert: false
5142
- });
5143
- path.copyAttributes(this);
5237
+ var path = this._asPathItem();
5144
5238
  if (paper.settings.applyMatrix)
5145
5239
  path.setApplyMatrix(true);
5146
- if (insert === undefined || insert)
5240
+ if (Base.pick(insert, paper.settings.insertItems))
5147
5241
  path.insertAbove(this);
5148
5242
  return path;
5149
5243
  },
@@ -5151,7 +5245,14 @@ var Shape = Item.extend({
5151
5245
  toShape: '#clone',
5152
5246
 
5153
5247
  _asPathItem: function() {
5154
- return this.toPath(false);
5248
+ var path = new Path[Base.capitalize(this._type)]({
5249
+ center: new Point(),
5250
+ size: this._size,
5251
+ radius: this._radius,
5252
+ insert: false
5253
+ });
5254
+ path.copyAttributes(this);
5255
+ return path;
5155
5256
  },
5156
5257
 
5157
5258
  _draw: function(ctx, param, viewMatrix, strokeMatrix) {
@@ -5218,7 +5319,7 @@ var Shape = Item.extend({
5218
5319
  ctx.closePath();
5219
5320
  }
5220
5321
  if (!dontPaint && (hasFill || hasStroke)) {
5221
- this._setStyles(ctx, param, viewMatrix);
5322
+ this._setStyles(ctx, param, viewMatrix, strokeMatrix);
5222
5323
  if (hasFill) {
5223
5324
  ctx.fill(style.getFillRule());
5224
5325
  ctx.shadowColor = 'rgba(0,0,0,0)';
@@ -5233,12 +5334,25 @@ var Shape = Item.extend({
5233
5334
  },
5234
5335
 
5235
5336
  _getBounds: function(matrix, options) {
5236
- var rect = new Rectangle(this._size).setCenter(0, 0),
5337
+ var size = this._size,
5338
+ rect = new Rectangle(size).setCenter(0, 0),
5237
5339
  style = this._style,
5238
5340
  strokeWidth = options.stroke && style.hasStroke()
5239
5341
  && style.getStrokeWidth();
5240
- if (matrix)
5241
- rect = matrix._transformBounds(rect);
5342
+ if (matrix) {
5343
+ if (this._type === 'rectangle') {
5344
+ rect = matrix._transformBounds(rect);
5345
+ } else {
5346
+ var rx = size.width / 2,
5347
+ ry = size.height / 2,
5348
+ dx = Math.sqrt(Math.pow(matrix._a * rx, 2)
5349
+ + Math.pow(matrix._c * ry, 2)),
5350
+ dy = Math.sqrt(Math.pow(matrix._b * rx, 2)
5351
+ + Math.pow(matrix._d * ry, 2));
5352
+ rect = new Rectangle(matrix._tx - dx, matrix._ty - dy,
5353
+ 2 * dx, 2 * dy);
5354
+ }
5355
+ }
5242
5356
  return strokeWidth
5243
5357
  ? rect.expand(Path._getStrokePadding(strokeWidth,
5244
5358
  this._getStrokeMatrix(matrix, options)))
@@ -5780,7 +5894,12 @@ var Raster = Item.extend({
5780
5894
 
5781
5895
  _draw: function(ctx, param, viewMatrix) {
5782
5896
  var element = this.getElement();
5783
- if (element && element.width > 0 && element.height > 0) {
5897
+ if (param.dontFinish || param.clip) {
5898
+ var rect = this.getInternalBounds();
5899
+ if (!param.dontStart)
5900
+ ctx.beginPath();
5901
+ ctx.rect(rect.x, rect.y, rect.width, rect.height);
5902
+ } else if (element && element.width > 0 && element.height > 0) {
5784
5903
  ctx.globalAlpha = Numerical.clamp(this._opacity, 0, 1);
5785
5904
 
5786
5905
  this._setStyles(ctx, param, viewMatrix);
@@ -5849,7 +5968,9 @@ var SymbolItem = Item.extend({
5849
5968
  },
5850
5969
 
5851
5970
  _hitTestSelf: function(point, options, viewMatrix) {
5852
- var opts = options.extend({ all: false });
5971
+ var opts = options.extend({
5972
+ all: false, match: null, class: null, type: null
5973
+ });
5853
5974
  var res = this._definition._item._hitTest(point, opts, viewMatrix);
5854
5975
  if (res)
5855
5976
  res.item = this;
@@ -5857,7 +5978,7 @@ var SymbolItem = Item.extend({
5857
5978
  },
5858
5979
 
5859
5980
  _draw: function(ctx, param) {
5860
- this._definition._item.draw(ctx, param);
5981
+ this._definition._item.draw(ctx, param.extend({ updateMatrix: false }));
5861
5982
  }
5862
5983
 
5863
5984
  });
@@ -6889,7 +7010,7 @@ statics: {
6889
7010
  }
6890
7011
  }
6891
7012
  }}, Base.each(
6892
- ['getBounds', 'getStrokeBounds', 'getHandleBounds'],
7013
+ ['getBounds', 'getStrokeBounds'],
6893
7014
  function(name) {
6894
7015
  this[name] = function() {
6895
7016
  if (!this._bounds)
@@ -6904,6 +7025,15 @@ statics: {
6904
7025
  },
6905
7026
  {
6906
7027
 
7028
+ getHandleBounds: function() {
7029
+ var v = this.getValues(),
7030
+ x1 = Math.min(v[0], v[2], v[4], v[6]),
7031
+ y1 = Math.min(v[1], v[3], v[5], v[7]),
7032
+ x2 = Math.max(v[0], v[2], v[4], v[6]),
7033
+ y2 = Math.max(v[1], v[3], v[5], v[7]);
7034
+ return new Rectangle(x1, y1, x2 - x1, y2 - y1);
7035
+ },
7036
+
6907
7037
  }), Base.each({
6908
7038
  isStraight: function(p1, h1, h2, p2) {
6909
7039
  if (h1.isZero() && h2.isZero()) {
@@ -7696,8 +7826,8 @@ new function() {
7696
7826
  den = 2 * ax * ty - 2 * ay * tx,
7697
7827
  times = [];
7698
7828
  if (Math.abs(den) < Numerical.CURVETIME_EPSILON) {
7699
- var num = ax * cy - ay * cx,
7700
- den = ax * by - ay * bx;
7829
+ var num = cx * ty - cy * tx,
7830
+ den = bx * ty - by * tx;
7701
7831
  if (den != 0) {
7702
7832
  var t = -num / den;
7703
7833
  if (t >= 0 && t <= 1) times.push(t);
@@ -8146,7 +8276,12 @@ var PathItem = Item.extend({
8146
8276
  previous,
8147
8277
  control,
8148
8278
  current = new Point(),
8149
- start = new Point();
8279
+ start = new Point(),
8280
+ number = '([+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?)',
8281
+ numbers = new RegExp(number, 'g'),
8282
+ flag = '([01])',
8283
+ arcs = new RegExp([number, number, number, flag, flag, number,
8284
+ number].join('[\\s,]*'), 'g');
8150
8285
 
8151
8286
  function getCoord(index, coord) {
8152
8287
  var val = +coords[index];
@@ -8168,7 +8303,7 @@ var PathItem = Item.extend({
8168
8303
  var part = parts[i],
8169
8304
  command = part[0],
8170
8305
  lower = command.toLowerCase();
8171
- coords = part.match(/[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g);
8306
+ coords = part.match(numbers);
8172
8307
  var length = coords && coords.length;
8173
8308
  relative = command === lower;
8174
8309
  if (previous === 'z' && !/[mz]/.test(lower))
@@ -8233,10 +8368,10 @@ var PathItem = Item.extend({
8233
8368
  }
8234
8369
  break;
8235
8370
  case 'a':
8236
- for (var j = 0; j < length; j += 7) {
8237
- this.arcTo(current = getPoint(j + 5),
8238
- new Size(+coords[j], +coords[j + 1]),
8239
- +coords[j + 2], +coords[j + 4], +coords[j + 3]);
8371
+ while (coords = arcs.exec(part)) {
8372
+ this.arcTo(current = getPoint(6),
8373
+ new Size(+coords[1], +coords[2]),
8374
+ +coords[3], +coords[5], +coords[4]);
8240
8375
  }
8241
8376
  break;
8242
8377
  case 'z':
@@ -8670,6 +8805,9 @@ var Path = PathItem.extend({
8670
8805
  removeSegments: function(start, end, _includeCurves) {
8671
8806
  start = start || 0;
8672
8807
  end = Base.pick(end, this._segments.length);
8808
+ if (start > end && this._closed)
8809
+ return this.removeSegments(start).concat(
8810
+ this.removeSegments(0, end));
8673
8811
  var segments = this._segments,
8674
8812
  curves = this._curves,
8675
8813
  count = segments.length,
@@ -8798,7 +8936,7 @@ var Path = PathItem.extend({
8798
8936
  time = 0;
8799
8937
  }
8800
8938
  var curves = this.getCurves();
8801
- if (index >= 0 && index < curves.length) {
8939
+ if (loc && index < curves.length) {
8802
8940
  if (time >= tMin) {
8803
8941
  curves[index++].divideAtTime(time);
8804
8942
  }
@@ -9110,7 +9248,7 @@ var Path = PathItem.extend({
9110
9248
  shape.copyAttributes(this, true);
9111
9249
  shape._matrix.prepend(this._matrix);
9112
9250
  shape.rotate(topCenter.subtract(center).getAngle() + 90);
9113
- if (insert === undefined || insert)
9251
+ if (Base.pick(insert, paper.settings.insertItems))
9114
9252
  shape.insertAbove(this);
9115
9253
  return shape;
9116
9254
  }
@@ -9251,7 +9389,7 @@ var Path = PathItem.extend({
9251
9389
  Path._addBevelJoin(segment, join, strokeRadius,
9252
9390
  miterLimit, null, strokeMatrix, addToArea, true);
9253
9391
  }
9254
- } else if (cap === 'square') {
9392
+ } else {
9255
9393
  Path._addSquareCap(segment, cap, strokeRadius, null,
9256
9394
  strokeMatrix, addToArea, true);
9257
9395
  }
@@ -9504,7 +9642,7 @@ new function() {
9504
9642
  }
9505
9643
 
9506
9644
  if (!dontPaint && (hasFill || hasStroke)) {
9507
- this._setStyles(ctx, param, viewMatrix);
9645
+ this._setStyles(ctx, param, viewMatrix, strokeMatrix);
9508
9646
  if (hasFill) {
9509
9647
  ctx.fill(style.getFillRule());
9510
9648
  ctx.shadowColor = 'rgba(0,0,0,0)';
@@ -9884,18 +10022,12 @@ statics: {
9884
10022
  _getStrokePadding: function(radius, matrix) {
9885
10023
  if (!matrix)
9886
10024
  return [radius, radius];
9887
- var hor = new Point(radius, 0).transform(matrix),
9888
- ver = new Point(0, radius).transform(matrix),
9889
- phi = hor.getAngleInRadians(),
9890
- a = hor.getLength(),
9891
- b = ver.getLength();
9892
- var sin = Math.sin(phi),
9893
- cos = Math.cos(phi),
9894
- tan = Math.tan(phi),
9895
- tx = Math.atan2(b * tan, a),
9896
- ty = Math.atan2(b, tan * a);
9897
- return [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),
9898
- Math.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];
10025
+ var a = matrix._a,
10026
+ b = matrix._b,
10027
+ c = matrix._c,
10028
+ d = matrix._d;
10029
+ return [radius * Math.sqrt(a * a + c * c),
10030
+ radius * Math.sqrt(b * b + d * d)];
9899
10031
  },
9900
10032
 
9901
10033
  _addBevelJoin: function(segment, join, radius, miterLimit, matrix,
@@ -9903,44 +10035,42 @@ statics: {
9903
10035
  var curve2 = segment.getCurve(),
9904
10036
  curve1 = curve2.getPrevious(),
9905
10037
  point = curve2.getPoint1().transform(matrix),
9906
- normal1 = curve1.getNormalAtTime(1).multiply(radius)
9907
- .transform(strokeMatrix),
9908
- normal2 = curve2.getNormalAtTime(0).multiply(radius)
9909
- .transform(strokeMatrix),
9910
- angle = normal1.getDirectedAngle(normal2);
10038
+ normal1 = curve1.getNormalAtTime(1).multiply(radius),
10039
+ normal2 = curve2.getNormalAtTime(0).multiply(radius),
10040
+ angle = normal1.getDirectedAngle(normal2);
9911
10041
  if (angle < 0 || angle >= 180) {
9912
10042
  normal1 = normal1.negate();
9913
10043
  normal2 = normal2.negate();
9914
10044
  }
9915
10045
  if (isArea)
9916
10046
  addPoint(point);
9917
- addPoint(point.add(normal1));
10047
+ addPoint(point.add(normal1.transform(strokeMatrix)));
9918
10048
  if (join === 'miter') {
9919
- var corner = new Line(point.add(normal1),
10049
+ var corner = new Line(normal1,
9920
10050
  new Point(-normal1.y, normal1.x), true
9921
- ).intersect(new Line(point.add(normal2),
10051
+ ).intersect(new Line(normal2,
9922
10052
  new Point(-normal2.y, normal2.x), true
9923
10053
  ), true);
9924
- if (corner && point.getDistance(corner) <= miterLimit * radius) {
9925
- addPoint(corner);
10054
+ if (corner && corner.getLength() <= miterLimit * radius) {
10055
+ addPoint(point.add(corner.transform(strokeMatrix)));
9926
10056
  }
9927
10057
  }
9928
- addPoint(point.add(normal2));
10058
+ addPoint(point.add(normal2.transform(strokeMatrix)));
9929
10059
  },
9930
10060
 
9931
10061
  _addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,
9932
10062
  addPoint, isArea) {
9933
10063
  var point = segment._point.transform(matrix),
9934
10064
  loc = segment.getLocation(),
9935
- normal = loc.getNormal()
9936
- .multiply(loc.getTime() === 0 ? radius : -radius)
9937
- .transform(strokeMatrix);
10065
+ vector = loc.getNormal()
10066
+ .multiply(loc.getTime() === 0 ? radius : -radius),
10067
+ normal = vector.transform(strokeMatrix);
9938
10068
  if (cap === 'square') {
9939
10069
  if (isArea) {
9940
10070
  addPoint(point.subtract(normal));
9941
10071
  addPoint(point.add(normal));
9942
10072
  }
9943
- point = point.add(normal.rotate(-90));
10073
+ point = point.add(vector.rotate(-90).transform(strokeMatrix));
9944
10074
  }
9945
10075
  addPoint(point.add(normal));
9946
10076
  addPoint(point.subtract(normal));
@@ -10002,14 +10132,14 @@ Path.inject({ statics: new function() {
10002
10132
 
10003
10133
  function createPath(segments, closed, args) {
10004
10134
  var props = Base.getNamed(args),
10005
- path = new Path(props && (
10006
- props.insert == true ? Item.INSERT
10007
- : props.insert == false ? Item.NO_INSERT
10008
- : null
10009
- ));
10135
+ path = new Path(props && {
10136
+ insert: props.insert,
10137
+ project: props.project,
10138
+ parent: props.parent
10139
+ });
10010
10140
  path._add(segments);
10011
10141
  path._closed = closed;
10012
- return path.set(props, Item.INSERT);
10142
+ return path.set(props, { insert: true, project: true, parent: true });
10013
10143
  }
10014
10144
 
10015
10145
  function createEllipse(center, radius, args) {
@@ -10278,7 +10408,7 @@ var CompoundPath = PathItem.extend({
10278
10408
  children[i].draw(ctx, param, strokeMatrix);
10279
10409
 
10280
10410
  if (!param.clip) {
10281
- this._setStyles(ctx, param, viewMatrix);
10411
+ this._setStyles(ctx, param, viewMatrix, strokeMatrix);
10282
10412
  var style = this._style;
10283
10413
  if (style.hasFill()) {
10284
10414
  ctx.fill(style.getFillRule());
@@ -10391,7 +10521,7 @@ PathItem.inject(new function() {
10391
10521
  var result = new CompoundPath(Item.NO_INSERT);
10392
10522
  result.addChildren(paths, true);
10393
10523
  result = result.reduce({ simplify: simplify });
10394
- if (!(options && options.insert == false)) {
10524
+ if (Base.pick(options && options.insert, paper.settings.insertItems)) {
10395
10525
  result.insertAbove(path2 && path1.isSibling(path2)
10396
10526
  && path1.getIndex() < path2.getIndex() ? path2 : path1);
10397
10527
  }
@@ -10406,7 +10536,7 @@ PathItem.inject(new function() {
10406
10536
  function traceBoolean(path1, path2, operation, options) {
10407
10537
  if (options && (options.trace == false || options.stroke) &&
10408
10538
  /^(subtract|intersect)$/.test(operation))
10409
- return splitBoolean(path1, path2, operation);
10539
+ return splitBoolean(path1, path2, operation, options);
10410
10540
  var _path1 = preparePath(path1, true),
10411
10541
  _path2 = path2 && path1 !== path2 && preparePath(path2, true),
10412
10542
  operator = operators[operation];
@@ -10486,7 +10616,7 @@ PathItem.inject(new function() {
10486
10616
  return createResult(paths, true, path1, path2, options);
10487
10617
  }
10488
10618
 
10489
- function splitBoolean(path1, path2, operation) {
10619
+ function splitBoolean(path1, path2, operation, options) {
10490
10620
  var _path1 = preparePath(path1),
10491
10621
  _path2 = preparePath(path2),
10492
10622
  crossings = _path1.getIntersections(_path2, filterIntersection),
@@ -10513,7 +10643,7 @@ PathItem.inject(new function() {
10513
10643
  }
10514
10644
  }
10515
10645
  addPath(_path1);
10516
- return createResult(paths, false, path1, path2);
10646
+ return createResult(paths, false, path1, path2, options);
10517
10647
  }
10518
10648
 
10519
10649
  function linkIntersections(from, to) {
@@ -11100,7 +11230,7 @@ PathItem.inject(new function() {
11100
11230
 
11101
11231
  divide: function(path, options) {
11102
11232
  return options && (options.trace == false || options.stroke)
11103
- ? splitBoolean(this, path, 'divide')
11233
+ ? splitBoolean(this, path, 'divide', options)
11104
11234
  : createResult([
11105
11235
  this.subtract(path, options),
11106
11236
  this.intersect(path, options)
@@ -11568,7 +11698,7 @@ var TextItem = Item.extend({
11568
11698
  _serializeFields: {
11569
11699
  content: null
11570
11700
  },
11571
- _boundsOptions: { stroke: false, handle: false },
11701
+ _boundsOptions: { handle: false },
11572
11702
 
11573
11703
  initialize: function TextItem(arg) {
11574
11704
  this._content = '';
@@ -11625,27 +11755,33 @@ var PointText = TextItem.extend({
11625
11755
  },
11626
11756
 
11627
11757
  _draw: function(ctx, param, viewMatrix) {
11628
- if (!this._content)
11629
- return;
11630
- this._setStyles(ctx, param, viewMatrix);
11631
- var lines = this._lines,
11632
- style = this._style,
11633
- hasFill = style.hasFill(),
11634
- hasStroke = style.hasStroke(),
11635
- leading = style.getLeading(),
11636
- shadowColor = ctx.shadowColor;
11637
- ctx.font = style.getFontStyle();
11638
- ctx.textAlign = style.getJustification();
11639
- for (var i = 0, l = lines.length; i < l; i++) {
11640
- ctx.shadowColor = shadowColor;
11641
- var line = lines[i];
11642
- if (hasFill) {
11643
- ctx.fillText(line, 0, 0);
11644
- ctx.shadowColor = 'rgba(0,0,0,0)';
11758
+ if (param.dontFinish || param.clip) {
11759
+ var rect = this.getInternalBounds();
11760
+ if (!param.dontStart)
11761
+ ctx.beginPath();
11762
+ ctx.rect(rect.x, rect.y, rect.width, rect.height);
11763
+ } else if (this._content) {
11764
+ this._setStyles(ctx, param, viewMatrix);
11765
+ var lines = this._lines,
11766
+ style = this._style,
11767
+ hasFill = style.hasFill(),
11768
+ hasStroke = style.hasStroke(),
11769
+ leading = style.getLeading(),
11770
+ shadowColor = ctx.shadowColor;
11771
+ ctx.font = style.getFontStyle();
11772
+ ctx.textAlign = style.getJustification();
11773
+ ctx.letterSpacing = style.getTrackingStyle();
11774
+ for (var i = 0, l = lines.length; i < l; i++) {
11775
+ ctx.shadowColor = shadowColor;
11776
+ var line = lines[i];
11777
+ if (hasFill) {
11778
+ ctx.fillText(line, 0, 0);
11779
+ ctx.shadowColor = 'rgba(0,0,0,0)';
11780
+ }
11781
+ if (hasStroke)
11782
+ ctx.strokeText(line, 0, 0);
11783
+ ctx.translate(0, leading);
11645
11784
  }
11646
- if (hasStroke)
11647
- ctx.strokeText(line, 0, 0);
11648
- ctx.translate(0, leading);
11649
11785
  }
11650
11786
  },
11651
11787
 
@@ -11655,14 +11791,28 @@ var PointText = TextItem.extend({
11655
11791
  numLines = lines.length,
11656
11792
  justification = style.getJustification(),
11657
11793
  leading = style.getLeading(),
11658
- width = this.getView().getTextWidth(style.getFontStyle(), lines),
11794
+ width = this.getView().getTextWidth(style.getFontStyle(), lines,
11795
+ style.getTrackingStyle()),
11659
11796
  x = 0;
11660
11797
  if (justification !== 'left')
11661
11798
  x -= width / (justification === 'center' ? 2: 1);
11662
11799
  var rect = new Rectangle(x,
11663
11800
  numLines ? - 0.75 * leading : 0,
11664
11801
  width, numLines * leading);
11802
+ if (options.stroke && style.hasStroke())
11803
+ rect = rect.expand(style.getStrokeWidth());
11665
11804
  return matrix ? matrix._transformBounds(rect, rect) : rect;
11805
+ },
11806
+
11807
+ _hitTestSelf: function(point, options) {
11808
+ if (options.fill && this.hasFill()) {
11809
+ var bounds = this.getInternalBounds(),
11810
+ closest = point.clamp(bounds.getTopLeft(true),
11811
+ bounds.getBottomRight(true));
11812
+ if (point.subtract(closest).divide(options._tolerancePadding)
11813
+ .getLength() <= 1)
11814
+ return new HitResult('fill', this);
11815
+ }
11666
11816
  }
11667
11817
  });
11668
11818
 
@@ -11723,13 +11873,14 @@ var Color = Base.extend(new function() {
11723
11873
  } else {
11724
11874
  var color = namedColors[string];
11725
11875
  if (!color) {
11726
- if (window) {
11727
- if (!colorCtx) {
11728
- colorCtx = CanvasProvider.getContext(1, 1, {
11729
- willReadFrequently: true
11730
- });
11876
+ if (!colorCtx) {
11877
+ colorCtx = CanvasProvider.getContext(1, 1, {
11878
+ willReadFrequently: true
11879
+ });
11880
+ if (colorCtx)
11731
11881
  colorCtx.globalCompositeOperation = 'copy';
11732
- }
11882
+ }
11883
+ if (colorCtx) {
11733
11884
  colorCtx.fillStyle = 'rgba(0,0,0,0)';
11734
11885
  colorCtx.fillStyle = string;
11735
11886
  colorCtx.fillRect(0, 0, 1, 1);
@@ -12136,8 +12287,9 @@ var Color = Base.extend(new function() {
12136
12287
  + components.join(',') + ')';
12137
12288
  },
12138
12289
 
12139
- toCanvasStyle: function(ctx, matrix) {
12140
- if (this._canvasStyle)
12290
+ toCanvasStyle: function(ctx, matrix, strokeMatrix) {
12291
+ var isCacheable = !(this._type === 'gradient' && strokeMatrix);
12292
+ if (this._canvasStyle && isCacheable)
12141
12293
  return this._canvasStyle;
12142
12294
  if (this._type !== 'gradient')
12143
12295
  return this._canvasStyle = this.toCSS();
@@ -12155,6 +12307,12 @@ var Color = Base.extend(new function() {
12155
12307
  if (highlight)
12156
12308
  highlight = inverse._transformPoint(highlight);
12157
12309
  }
12310
+ if (strokeMatrix) {
12311
+ origin = strokeMatrix._transformPoint(origin);
12312
+ destination = strokeMatrix._transformPoint(destination);
12313
+ if (highlight)
12314
+ highlight = strokeMatrix._transformPoint(highlight);
12315
+ }
12158
12316
  if (gradient._radial) {
12159
12317
  var radius = destination.getDistance(origin);
12160
12318
  if (highlight) {
@@ -12176,7 +12334,9 @@ var Color = Base.extend(new function() {
12176
12334
  offset == null ? i / (l - 1) : offset,
12177
12335
  stop._color.toCanvasStyle());
12178
12336
  }
12179
- return this._canvasStyle = canvasGradient;
12337
+ if (isCacheable)
12338
+ this._canvasStyle = canvasGradient;
12339
+ return canvasGradient;
12180
12340
  },
12181
12341
 
12182
12342
  transform: function(matrix) {
@@ -12440,6 +12600,7 @@ var Style = Base.extend(new function() {
12440
12600
  fontWeight: 'normal',
12441
12601
  fontSize: 12,
12442
12602
  leading: null,
12603
+ tracking: 0,
12443
12604
  justification: 'left'
12444
12605
  }),
12445
12606
  textDefaults = Base.set({}, groupDefaults, {
@@ -12456,6 +12617,7 @@ var Style = Base.extend(new function() {
12456
12617
  fontSize: 9,
12457
12618
  font: 9,
12458
12619
  leading: 9,
12620
+ tracking: 9,
12459
12621
  justification: 9
12460
12622
  },
12461
12623
  item = {
@@ -12500,7 +12662,7 @@ var Style = Base.extend(new function() {
12500
12662
  var old = this._values[key];
12501
12663
  if (old !== value) {
12502
12664
  if (isColor) {
12503
- if (old) {
12665
+ if (old && old.constructor === Color) {
12504
12666
  Color._setOwner(old, null);
12505
12667
  old._canvasStyle = null;
12506
12668
  }
@@ -12646,6 +12808,10 @@ var Style = Base.extend(new function() {
12646
12808
  + this.getFontFamily();
12647
12809
  },
12648
12810
 
12811
+ getTrackingStyle: function() {
12812
+ return this.getTracking() / 1000 + 'em';
12813
+ },
12814
+
12649
12815
  getFont: '#getFontFamily',
12650
12816
  setFont: '#setFontFamily',
12651
12817
 
@@ -12722,6 +12888,18 @@ var DomElement = new function() {
12722
12888
  return DomElement.getBounds(el, true).getSize();
12723
12889
  },
12724
12890
 
12891
+ getInsets: function(el, start) {
12892
+ var style = DomElement.getStyles(el);
12893
+ function get(side) {
12894
+ return parseFloat(style['padding' + side])
12895
+ + parseFloat(style['border' + side + 'Width']);
12896
+ }
12897
+ return start
12898
+ ? new Size(get('Left'), get('Top'))
12899
+ : new Size(get('Left') + get('Right'),
12900
+ get('Top') + get('Bottom'));
12901
+ },
12902
+
12725
12903
  isInvisible: function(el) {
12726
12904
  return DomElement.getSize(el).equals(new Size(0, 0));
12727
12905
  },
@@ -12780,12 +12958,20 @@ var DomEvent = {
12780
12958
  }
12781
12959
  },
12782
12960
 
12783
- getPoint: function(event) {
12784
- var pos = event.targetTouches
12785
- ? event.targetTouches.length
12786
- ? event.targetTouches[0]
12787
- : event.changedTouches[0]
12788
- : event;
12961
+ getPoint: function(event, target) {
12962
+ function find(touches) {
12963
+ for (var i = 0, l = touches.length; i < l; i++) {
12964
+ if (touches[i].target === target)
12965
+ return touches[i];
12966
+ }
12967
+ }
12968
+
12969
+ var touches = event.targetTouches,
12970
+ pos = event;
12971
+ if (touches) {
12972
+ pos = find(event.touches) || find(event.changedTouches)
12973
+ || (touches.length ? touches[0] : event.changedTouches[0]);
12974
+ }
12789
12975
  return new Point(
12790
12976
  pos.pageX || pos.clientX + document.documentElement.scrollLeft,
12791
12977
  pos.pageY || pos.clientY + document.documentElement.scrollTop
@@ -12801,8 +12987,9 @@ var DomEvent = {
12801
12987
  },
12802
12988
 
12803
12989
  getOffset: function(event, target) {
12804
- return DomEvent.getPoint(event).subtract(DomElement.getOffset(
12805
- target || DomEvent.getTarget(event)));
12990
+ target = target || DomEvent.getTarget(event);
12991
+ return DomEvent.getPoint(event, target).subtract(
12992
+ DomElement.getOffset(target));
12806
12993
  }
12807
12994
  };
12808
12995
 
@@ -12848,7 +13035,7 @@ var View = Base.extend(Emitter, {
12848
13035
  var size = DomElement.getSize(element);
12849
13036
  return size.isNaN() || size.isZero()
12850
13037
  ? new Size(getSize('width'), getSize('height'))
12851
- : size;
13038
+ : size.subtract(DomElement.getInsets(element));
12852
13039
  }
12853
13040
 
12854
13041
  var size;
@@ -12961,7 +13148,7 @@ var View = Base.extend(Emitter, {
12961
13148
  this.requestUpdate();
12962
13149
  },
12963
13150
 
12964
- update: function() {
13151
+ update: function(force) {
12965
13152
  },
12966
13153
 
12967
13154
  draw: function() {
@@ -13049,6 +13236,10 @@ var View = Base.extend(Emitter, {
13049
13236
  return this._element;
13050
13237
  },
13051
13238
 
13239
+ getProject: function() {
13240
+ return this._project;
13241
+ },
13242
+
13052
13243
  getPixelRatio: function() {
13053
13244
  return this._pixelRatio;
13054
13245
  },
@@ -13154,12 +13345,14 @@ var View = Base.extend(Emitter, {
13154
13345
 
13155
13346
  getZoom: function() {
13156
13347
  var scaling = this._decompose().scaling;
13157
- return (scaling.x + scaling.y) / 2;
13348
+ return (Math.abs(scaling.x) + Math.abs(scaling.y)) / 2;
13158
13349
  },
13159
13350
 
13160
13351
  setZoom: function(zoom) {
13161
- this.transform(new Matrix().scale(zoom / this.getZoom(),
13162
- this.getCenter()));
13352
+ if (zoom > 0 && isFinite(zoom)) {
13353
+ this.transform(new Matrix().scale(zoom / this.getZoom(),
13354
+ this.getCenter()));
13355
+ }
13163
13356
  },
13164
13357
 
13165
13358
  getRotation: function() {
@@ -13169,7 +13362,8 @@ var View = Base.extend(Emitter, {
13169
13362
  setRotation: function(rotation) {
13170
13363
  var current = this.getRotation();
13171
13364
  if (current != null && rotation != null) {
13172
- this.rotate(rotation - current);
13365
+ this._matrix.prepend(new Matrix().rotate(rotation - current,
13366
+ this.projectToView(this.getCenter())));
13173
13367
  }
13174
13368
  },
13175
13369
 
@@ -13199,6 +13393,31 @@ var View = Base.extend(Emitter, {
13199
13393
  this._matrix.append(matrix);
13200
13394
  },
13201
13395
 
13396
+ fitBounds: function(rectangle, fit) {
13397
+ rectangle = Rectangle.read(arguments);
13398
+ fit = Base.read(arguments);
13399
+ var matrix = this._matrix,
13400
+ size = this._viewSize,
13401
+ bounds = matrix._transformBounds(rectangle),
13402
+ scaleX = new Point(matrix._a, matrix._c).getLength(),
13403
+ scaleY = new Point(matrix._b, matrix._d).getLength(),
13404
+ ratios = [
13405
+ size.width / bounds.width * scaleX,
13406
+ size.height / bounds.height * scaleY
13407
+ ].filter(function(ratio) {
13408
+ return ratio > 0 && isFinite(ratio);
13409
+ });
13410
+ this.setCenter(rectangle.getCenter());
13411
+ if (ratios.length) {
13412
+ var amount = fit === 'cover'
13413
+ ? Math.max.apply(Math, ratios)
13414
+ : Math.min.apply(Math, ratios);
13415
+ matrix.prepend(new Matrix().scale(
13416
+ new Point(amount / scaleX, amount / scaleY),
13417
+ size.divide(2)));
13418
+ }
13419
+ },
13420
+
13202
13421
  scrollBy: function() {
13203
13422
  this.translate(Point.read(arguments).negate());
13204
13423
  }
@@ -13213,7 +13432,17 @@ var View = Base.extend(Emitter, {
13213
13432
  },
13214
13433
 
13215
13434
  getEventPoint: function(event) {
13216
- return this.viewToProject(DomEvent.getOffset(event, this._element));
13435
+ var element = this._element,
13436
+ offset = DomEvent.getOffset(event, element),
13437
+ size = DomElement.getSize(element);
13438
+ if (!size.isZero()) {
13439
+ var cssSize = new Size(element.offsetWidth, element.offsetHeight);
13440
+ offset = offset.multiply(cssSize.divide(size))
13441
+ .subtract(DomElement.getInsets(element, true))
13442
+ .multiply(this.getViewSize().divide(
13443
+ cssSize.subtract(DomElement.getInsets(element))));
13444
+ }
13445
+ return this.viewToProject(offset);
13217
13446
  },
13218
13447
 
13219
13448
  }, {
@@ -13283,16 +13512,8 @@ new function() {
13283
13512
  mouseout: function(event) {
13284
13513
  var view = View._focused,
13285
13514
  target = DomEvent.getRelatedTarget(event);
13286
- if (view && (!target || target.nodeName === 'HTML')) {
13287
- var offset = DomEvent.getOffset(event, view._element),
13288
- x = offset.x,
13289
- abs = Math.abs,
13290
- ax = abs(x),
13291
- max = 1 << 25,
13292
- diff = ax - max;
13293
- offset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;
13294
- handleMouseMove(view, event, view.viewToProject(offset));
13295
- }
13515
+ if (view && (!target || target.nodeName === 'HTML'))
13516
+ handleMouseMove(view, event);
13296
13517
  },
13297
13518
 
13298
13519
  scroll: updateFocus
@@ -13487,9 +13708,12 @@ new function() {
13487
13708
  if (mouse.down && inView || mouse.up && downPoint) {
13488
13709
  emitMouseEvents(this, hitItem, type, event, point, downPoint);
13489
13710
  if (mouse.down) {
13490
- dblClick = hitItem === clickItem
13491
- && (Date.now() - clickTime < 300);
13711
+ var time = Date.now();
13712
+ dblClick = !dblClick && hitItem === clickItem
13713
+ && time - clickTime < 300
13714
+ && point.getDistance(downPoint) < 3;
13492
13715
  downItem = clickItem = hitItem;
13716
+ clickTime = time;
13493
13717
  if (!prevented && hitItem) {
13494
13718
  var item = hitItem;
13495
13719
  while (item && !item.responds('mousedrag'))
@@ -13500,10 +13724,8 @@ new function() {
13500
13724
  downPoint = point;
13501
13725
  } else if (mouse.up) {
13502
13726
  if (!prevented && hitItem === downItem) {
13503
- clickTime = Date.now();
13504
13727
  emitMouseEvents(this, hitItem, dblClick ? 'doubleclick'
13505
13728
  : 'click', event, point, downPoint);
13506
- dblClick = false;
13507
13729
  }
13508
13730
  downItem = dragItem = null;
13509
13731
  }
@@ -13605,9 +13827,13 @@ var CanvasView = View.extend({
13605
13827
  var element = this._element,
13606
13828
  ctx = this._context;
13607
13829
  if (!PaperScope.hasAttribute(element, 'resize')) {
13608
- var style = element.style;
13609
- style.width = width + 'px';
13610
- style.height = height + 'px';
13830
+ var style = element.style,
13831
+ insets = DomElement.getStyles(element).boxSizing
13832
+ === 'border-box'
13833
+ ? DomElement.getInsets(element)
13834
+ : new Size();
13835
+ style.width = (width + insets.width) + 'px';
13836
+ style.height = (height + insets.height) + 'px';
13611
13837
  }
13612
13838
  ctx.restore();
13613
13839
  ctx.save();
@@ -13634,19 +13860,22 @@ var CanvasView = View.extend({
13634
13860
  return pixels;
13635
13861
  },
13636
13862
 
13637
- getTextWidth: function(font, lines) {
13863
+ getTextWidth: function(font, lines, letterSpacing) {
13638
13864
  var ctx = this._context,
13639
13865
  prevFont = ctx.font,
13866
+ prevLetterSpacing = ctx.letterSpacing,
13640
13867
  width = 0;
13641
13868
  ctx.font = font;
13869
+ ctx.letterSpacing = letterSpacing;
13642
13870
  for (var i = 0, l = lines.length; i < l; i++)
13643
13871
  width = Math.max(width, ctx.measureText(lines[i]).width);
13644
13872
  ctx.font = prevFont;
13873
+ ctx.letterSpacing = prevLetterSpacing;
13645
13874
  return width;
13646
13875
  },
13647
13876
 
13648
- update: function() {
13649
- if (!this._needsUpdate)
13877
+ update: function(force) {
13878
+ if (!this._needsUpdate && !force)
13650
13879
  return false;
13651
13880
  var project = this._project,
13652
13881
  ctx = this._context,
@@ -13717,6 +13946,7 @@ var Key = new function() {
13717
13946
  var keyLookup = {
13718
13947
  '\t': 'tab',
13719
13948
  ' ': 'space',
13949
+ '\xA0': 'space',
13720
13950
  '\b': 'backspace',
13721
13951
  '\x7f': 'delete',
13722
13952
  'Spacebar': 'space',
@@ -13771,6 +14001,7 @@ var Key = new function() {
13771
14001
  }
13772
14002
 
13773
14003
  function handleKey(down, key, character, event) {
14004
+ View.updateFocus();
13774
14005
  var type = down ? 'keydown' : 'keyup',
13775
14006
  view = View._focused,
13776
14007
  name;
@@ -13805,11 +14036,9 @@ var Key = new function() {
13805
14036
 
13806
14037
  DomEvent.add(document, {
13807
14038
  keydown: function(event) {
13808
- var key = getKey(event),
13809
- agent = paper && paper.agent;
13810
- if (key.length > 1 || agent && (agent.chrome && (event.altKey
13811
- || agent.mac && event.metaKey
13812
- || !agent.mac && event.ctrlKey))) {
14039
+ var key = getKey(event);
14040
+ if (key.length > 1 || event.ctrlKey || event.altKey
14041
+ || event.metaKey) {
13813
14042
  handleKey(true, key,
13814
14043
  charLookup[key] || (key.length > 1 ? '' : key), event);
13815
14044
  } else {
@@ -14143,6 +14372,48 @@ var Tween = Base.extend(Emitter, {
14143
14372
  return t < 0.5
14144
14373
  ? 16 * t * t * t * t * t
14145
14374
  : 1 + 16 * (--t) * t * t * t * t;
14375
+ },
14376
+
14377
+ easeInSine: function(t) {
14378
+ return 1 - Math.cos(t * Math.PI / 2);
14379
+ },
14380
+
14381
+ easeOutSine: function(t) {
14382
+ return Math.sin(t * Math.PI / 2);
14383
+ },
14384
+
14385
+ easeInOutSine: function(t) {
14386
+ return (1 - Math.cos(t * Math.PI)) / 2;
14387
+ },
14388
+
14389
+ easeInExpo: function(t) {
14390
+ return t === 0 ? 0 : Math.pow(2, 10 * t - 10);
14391
+ },
14392
+
14393
+ easeOutExpo: function(t) {
14394
+ return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
14395
+ },
14396
+
14397
+ easeInOutExpo: function(t) {
14398
+ return t === 0 || t === 1
14399
+ ? t
14400
+ : t < 0.5
14401
+ ? Math.pow(2, 20 * t - 10) / 2
14402
+ : 1 - Math.pow(2, 10 - 20 * t) / 2;
14403
+ },
14404
+
14405
+ easeInCirc: function(t) {
14406
+ return 1 - Math.sqrt(1 - t * t);
14407
+ },
14408
+
14409
+ easeOutCirc: function(t) {
14410
+ return Math.sqrt(1 - (--t) * t);
14411
+ },
14412
+
14413
+ easeInOutCirc: function(t) {
14414
+ return t < 0.5
14415
+ ? (1 - Math.sqrt(1 - 4 * t * t)) / 2
14416
+ : (1 + Math.sqrt(1 - 4 * (--t) * t)) / 2;
14146
14417
  }
14147
14418
  })
14148
14419
  },
@@ -14363,7 +14634,7 @@ var CanvasProvider = Base.exports.CanvasProvider = {
14363
14634
  canvases: [],
14364
14635
 
14365
14636
  getCanvas: function(width, height, options) {
14366
- if (!window)
14637
+ if (!window && !self.OffscreenCanvas)
14367
14638
  return null;
14368
14639
  var canvas,
14369
14640
  clear = true;
@@ -14374,7 +14645,9 @@ var CanvasProvider = Base.exports.CanvasProvider = {
14374
14645
  if (this.canvases.length) {
14375
14646
  canvas = this.canvases.pop();
14376
14647
  } else {
14377
- canvas = document.createElement('canvas');
14648
+ canvas = window
14649
+ ? document.createElement('canvas')
14650
+ : new self.OffscreenCanvas(width, height);
14378
14651
  clear = false;
14379
14652
  }
14380
14653
  var ctx = canvas.getContext('2d', options || {});
@@ -14578,6 +14851,12 @@ var BlendMode = new function() {
14578
14851
  db = (bb + sb) / 2;
14579
14852
  },
14580
14853
 
14854
+ 'pin-light': function() {
14855
+ dr = sr < 128 ? min(br, 2 * sr) : max(br, 2 * sr - 255);
14856
+ dg = sg < 128 ? min(bg, 2 * sg) : max(bg, 2 * sg - 255);
14857
+ db = sb < 128 ? min(bb, 2 * sb) : max(bb, 2 * sb - 255);
14858
+ },
14859
+
14581
14860
  negation: function() {
14582
14861
  dr = 255 - abs(255 - sr - br);
14583
14862
  dg = 255 - abs(255 - sg - bg);
@@ -14676,7 +14955,8 @@ var SvgElement = new function() {
14676
14955
  function get(node, name) {
14677
14956
  var namespace = attributeNamespace[name],
14678
14957
  value = namespace
14679
- ? node.getAttributeNS(namespace, name)
14958
+ ? node.getAttribute(name)
14959
+ || node.getAttributeNS(namespace, name)
14680
14960
  : node.getAttribute(name);
14681
14961
  return value === 'null' ? null : value;
14682
14962
  }
@@ -14729,6 +15009,7 @@ var SvgStyles = Base.each({
14729
15009
  fontFamily: ['font-family', 'string'],
14730
15010
  fontWeight: ['font-weight', 'string'],
14731
15011
  fontSize: ['font-size', 'number'],
15012
+ tracking: ['letter-spacing', 'tracking'],
14732
15013
  justification: ['text-anchor', 'lookup', {
14733
15014
  left: 'start',
14734
15015
  center: 'middle',
@@ -14754,7 +15035,8 @@ var SvgStyles = Base.each({
14754
15035
  }, {});
14755
15036
 
14756
15037
  new function() {
14757
- var formatter;
15038
+ var formatter,
15039
+ parentStyles;
14758
15040
 
14759
15041
  function getTransform(matrix, coordinates, center) {
14760
15042
  var attrs = new Base(),
@@ -14803,34 +15085,72 @@ new function() {
14803
15085
  var node = SvgElement.create('g', attrs, formatter);
14804
15086
  for (var i = 0, l = children.length; i < l; i++) {
14805
15087
  var child = children[i];
14806
- var childNode = exportSVG(child, options);
14807
- if (childNode) {
14808
- if (child.isClipMask()) {
14809
- var clip = SvgElement.create('clipPath');
14810
- clip.appendChild(childNode);
14811
- setDefinition(child, clip, 'clip');
14812
- SvgElement.set(node, {
14813
- 'clip-path': 'url(#' + clip.id + ')'
14814
- });
14815
- } else {
15088
+ if (child.isClipMask()) {
15089
+ var clip = exportClip(child, options);
15090
+ setDefinition(child, clip, 'clip', options);
15091
+ SvgElement.set(node, {
15092
+ 'clip-path': 'url(#' + clip.id + ')'
15093
+ });
15094
+ } else {
15095
+ var childNode = exportSVG(child, options);
15096
+ if (childNode)
14816
15097
  node.appendChild(childNode);
14817
- }
14818
15098
  }
14819
15099
  }
14820
15100
  return node;
14821
15101
  }
14822
15102
 
15103
+ function exportClip(item, options) {
15104
+ var clip = SvgElement.create('clipPath');
15105
+
15106
+ function addItem(item) {
15107
+ if (item instanceof Group) {
15108
+ var children = item._children;
15109
+ for (var i = 0, l = children.length; i < l; i++) {
15110
+ if (!children[i]._clipMask)
15111
+ addItem(children[i]);
15112
+ }
15113
+ } else {
15114
+ var node = exportSVG(item, options);
15115
+ if (node)
15116
+ clip.appendChild(node);
15117
+ }
15118
+ }
15119
+
15120
+ if (item instanceof Group) {
15121
+ item = item.clone({ insert: false });
15122
+ item.matrix.apply(true, true);
15123
+ }
15124
+ addItem(item);
15125
+ return clip;
15126
+ }
15127
+
14823
15128
  function exportRaster(item, options) {
14824
15129
  var attrs = getTransform(item._matrix, true),
14825
15130
  size = item.getSize(),
14826
- image = item.getImage();
15131
+ image = item.getImage(),
15132
+ href = options.embedImages == false && image && image.src
15133
+ || item.toDataURL();
14827
15134
  attrs.x -= size.width / 2;
14828
15135
  attrs.y -= size.height / 2;
14829
- attrs.width = size.width;
14830
- attrs.height = size.height;
14831
- attrs.href = options.embedImages == false && image && image.src
14832
- || item.toDataURL();
14833
- return SvgElement.create('image', attrs, formatter);
15136
+ if (options.reuseImages) {
15137
+ var node = getDefinition(href, 'image');
15138
+ if (!node) {
15139
+ node = SvgElement.create('image', {
15140
+ width: size.width,
15141
+ height: size.height,
15142
+ href: href
15143
+ }, formatter);
15144
+ setDefinition(href, node, 'image', options);
15145
+ }
15146
+ attrs.href = '#' + node.id;
15147
+ return SvgElement.create('use', attrs, formatter);
15148
+ } else {
15149
+ attrs.width = size.width;
15150
+ attrs.height = size.height;
15151
+ attrs.href = href;
15152
+ return SvgElement.create('image', attrs, formatter);
15153
+ }
14834
15154
  }
14835
15155
 
14836
15156
  function exportPath(item, options) {
@@ -14916,7 +15236,7 @@ new function() {
14916
15236
  viewBox: formatter.rectangle(bounds)
14917
15237
  });
14918
15238
  node.appendChild(exportSVG(definitionItem, options));
14919
- setDefinition(definition, node, 'symbol');
15239
+ setDefinition(definition, node, 'symbol', options);
14920
15240
  }
14921
15241
  attrs.href = '#' + node.id;
14922
15242
  attrs.x += bounds.x;
@@ -14927,7 +15247,7 @@ new function() {
14927
15247
  return SvgElement.create('use', attrs, formatter);
14928
15248
  }
14929
15249
 
14930
- function exportGradient(color) {
15250
+ function exportGradient(color, options) {
14931
15251
  var gradientNode = getDefinition(color, 'color');
14932
15252
  if (!gradientNode) {
14933
15253
  var gradient = color.getGradient(),
@@ -14973,15 +15293,28 @@ new function() {
14973
15293
  gradientNode.appendChild(
14974
15294
  SvgElement.create('stop', attrs, formatter));
14975
15295
  }
14976
- setDefinition(color, gradientNode, 'color');
15296
+ setDefinition(color, gradientNode, 'color', options);
14977
15297
  }
14978
15298
  return 'url(#' + gradientNode.id + ')';
14979
15299
  }
14980
15300
 
14981
15301
  function exportText(item) {
14982
- var node = SvgElement.create('text', getTransform(item._matrix, true),
14983
- formatter);
14984
- node.textContent = item._content;
15302
+ var attrs = getTransform(item._matrix, true),
15303
+ node = SvgElement.create('text', attrs, formatter),
15304
+ lines = item._lines;
15305
+ if (lines.length > 1) {
15306
+ var leading = item._style.getLeading();
15307
+ for (var i = 0, l = lines.length; i < l; i++) {
15308
+ var span = SvgElement.create('tspan', {
15309
+ x: attrs.x,
15310
+ y: attrs.y + i * leading
15311
+ }, formatter);
15312
+ span.textContent = lines[i];
15313
+ node.appendChild(span);
15314
+ }
15315
+ } else {
15316
+ node.textContent = item._content;
15317
+ }
14985
15318
  return node;
14986
15319
  }
14987
15320
 
@@ -14999,6 +15332,8 @@ new function() {
14999
15332
  function applyStyle(item, node, options, isRoot) {
15000
15333
  var attrs = {},
15001
15334
  parent = !isRoot && item.getParent(),
15335
+ parentStyle = parent && (parentStyles[parent._id] =
15336
+ parentStyles[parent._id] || {}),
15002
15337
  style = [];
15003
15338
 
15004
15339
  if (item._name != null)
@@ -15008,10 +15343,12 @@ new function() {
15008
15343
  var get = entry.get,
15009
15344
  type = entry.type,
15010
15345
  value = item[get]();
15011
- if (entry.exportFilter
15346
+ if (parent && !(get in parentStyle))
15347
+ parentStyle[get] = parent[get]();
15348
+ if (value !== undefined && (entry.exportFilter
15012
15349
  ? entry.exportFilter(item, value)
15013
15350
  : options.reduceAttributes == false
15014
- || !parent || !Base.equals(parent[get](), value)) {
15351
+ || !parent || !Base.equals(parentStyle[get], value))) {
15015
15352
  if (type === 'color' && value != null) {
15016
15353
  var alpha = value.getAlpha();
15017
15354
  if (alpha < 1)
@@ -15022,10 +15359,11 @@ new function() {
15022
15359
  } else {
15023
15360
  attrs[entry.attribute] = value == null ? 'none'
15024
15361
  : type === 'color' ? value.gradient
15025
- ? exportGradient(value, item)
15362
+ ? exportGradient(value, options)
15026
15363
  : value.toCSS(true)
15027
15364
  : type === 'array' ? value.join(',')
15028
15365
  : type === 'lookup' ? entry.toSVG[value]
15366
+ : type === 'tracking' ? value && value / 1000 + 'em'
15029
15367
  : value;
15030
15368
  }
15031
15369
  }
@@ -15047,16 +15385,20 @@ new function() {
15047
15385
  function getDefinition(item, type) {
15048
15386
  if (!definitions)
15049
15387
  definitions = { ids: {}, svgs: {} };
15050
- return item && definitions.svgs[type + '-'
15051
- + (item._id || item.__id || (item.__id = UID.get('svg')))];
15388
+ return item && definitions.svgs[getDefinitionKey(item, type)];
15052
15389
  }
15053
15390
 
15054
- function setDefinition(item, node, type) {
15391
+ function setDefinition(item, node, type, options) {
15055
15392
  if (!definitions)
15056
15393
  getDefinition();
15057
15394
  var typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;
15058
- node.id = type + '-' + typeId;
15059
- definitions.svgs[type + '-' + (item._id || item.__id)] = node;
15395
+ node.id = (options.idPrefix || '') + type + '-' + typeId;
15396
+ definitions.svgs[getDefinitionKey(item, type)] = node;
15397
+ }
15398
+
15399
+ function getDefinitionKey(item, type) {
15400
+ return type + '-' + (typeof item === 'string' ? item
15401
+ : item._id || item.__id || (item.__id = UID.get('svg')));
15060
15402
  }
15061
15403
 
15062
15404
  function exportDefinitions(node, options) {
@@ -15077,6 +15419,7 @@ new function() {
15077
15419
  }
15078
15420
  definitions = null;
15079
15421
  }
15422
+ parentStyles = null;
15080
15423
  return options.asString
15081
15424
  ? new self.XMLSerializer().serializeToString(svg)
15082
15425
  : svg;
@@ -15100,6 +15443,7 @@ new function() {
15100
15443
  if (!options)
15101
15444
  options = {};
15102
15445
  formatter = new Formatter(options.precision);
15446
+ parentStyles = {};
15103
15447
  return options;
15104
15448
  }
15105
15449
 
@@ -15152,7 +15496,14 @@ new function() {
15152
15496
  new function() {
15153
15497
 
15154
15498
  var definitions = {},
15155
- rootSize;
15499
+ rootSize,
15500
+ units = { 'in': 96, pt: 96 / 72, pc: 96 / 6, cm: 96 / 2.54,
15501
+ mm: 96 / 25.4 };
15502
+
15503
+ function parseLength(value) {
15504
+ var unit = /(in|pt|pc|cm|mm)\s*$/.exec(value);
15505
+ return parseFloat(value) * (unit ? units[unit[1]] : 1);
15506
+ }
15156
15507
 
15157
15508
  function getValue(node, name, isString, allowNull, allowPercent,
15158
15509
  defaultValue) {
@@ -15163,7 +15514,7 @@ new function() {
15163
15514
  : isString ? '' : 0
15164
15515
  : isString
15165
15516
  ? value
15166
- : parseFloat(value);
15517
+ : parseLength(value);
15167
15518
  return /%\s*$/.test(value)
15168
15519
  ? (res / 100) * (allowPercent ? 1
15169
15520
  : rootSize[/x|^width/.test(name) ? 'width' : 'height'])
@@ -15184,12 +15535,12 @@ new function() {
15184
15535
  : new Size(w, h);
15185
15536
  }
15186
15537
 
15187
- function convertValue(value, type, lookup) {
15538
+ function convertValue(value, type, lookup, options) {
15188
15539
  return value === 'none' ? null
15189
- : type === 'number' ? parseFloat(value)
15540
+ : type === 'number' ? parseLength(value)
15190
15541
  : type === 'array' ?
15191
- value ? value.split(/[\s,]+/g).map(parseFloat) : []
15192
- : type === 'color' ? getDefinition(value) || value
15542
+ value ? value.split(/[\s,]+/g).map(parseLength) : []
15543
+ : type === 'color' ? getDefinition(value, options) || value
15193
15544
  : type === 'lookup' ? lookup[value]
15194
15545
  : value;
15195
15546
  }
@@ -15201,11 +15552,17 @@ new function() {
15201
15552
  item = new Group(),
15202
15553
  project = item._project,
15203
15554
  currentStyle = project._currentStyle,
15555
+ parentSize = rootSize,
15204
15556
  children = [];
15205
15557
  if (!isClip && !isDefs) {
15206
- item = applyAttributes(item, node, isRoot);
15558
+ item = applyAttributes(item, node, options, isRoot);
15207
15559
  project._currentStyle = item._style.clone();
15208
15560
  }
15561
+ if (type === 'svg' && !isRoot) {
15562
+ rootSize = new Size(
15563
+ getValue(node, 'width', false, false, false, '100%'),
15564
+ getValue(node, 'height', false, false, false, '100%'));
15565
+ }
15209
15566
  if (isRoot) {
15210
15567
  var defs = node.querySelectorAll('defs');
15211
15568
  for (var i = 0, l = defs.length; i < l; i++) {
@@ -15223,8 +15580,9 @@ new function() {
15223
15580
  }
15224
15581
  item.addChildren(children);
15225
15582
  if (isClip)
15226
- item = applyAttributes(item.reduce(), node, isRoot);
15583
+ item = applyAttributes(item.reduce(), node, options, isRoot);
15227
15584
  project._currentStyle = currentStyle;
15585
+ rootSize = parentSize;
15228
15586
  if (isClip || isDefs) {
15229
15587
  item.remove();
15230
15588
  item = null;
@@ -15250,12 +15608,13 @@ new function() {
15250
15608
  return PathItem.create(node.getAttribute('d'));
15251
15609
  }
15252
15610
 
15253
- function importGradient(node, type) {
15611
+ function importGradient(node, type, options) {
15254
15612
  var id = (getValue(node, 'href', true) || '').substring(1),
15613
+ definition = getDefinitionById(id, options),
15255
15614
  radial = type === 'radialgradient',
15256
15615
  gradient;
15257
- if (id) {
15258
- gradient = definitions[id].getGradient();
15616
+ if (definition) {
15617
+ gradient = definition.getGradient();
15259
15618
  if (gradient._radial ^ radial) {
15260
15619
  gradient = gradient.clone();
15261
15620
  gradient._radial = radial;
@@ -15266,7 +15625,8 @@ new function() {
15266
15625
  for (var i = 0, l = nodes.length; i < l; i++) {
15267
15626
  var child = nodes[i];
15268
15627
  if (child.nodeType === 1)
15269
- stops.push(applyAttributes(new GradientStop(), child));
15628
+ stops.push(applyAttributes(new GradientStop(), child,
15629
+ options));
15270
15630
  }
15271
15631
  gradient = new Gradient(stops, radial);
15272
15632
  }
@@ -15286,7 +15646,8 @@ new function() {
15286
15646
  '100%', '0%');
15287
15647
  }
15288
15648
  var color = applyAttributes(
15289
- new Color(gradient, origin, destination, highlight), node);
15649
+ new Color(gradient, origin, destination, highlight), node,
15650
+ options);
15290
15651
  color._scaleToBounds = scaleToBounds;
15291
15652
  return null;
15292
15653
  }
@@ -15309,13 +15670,30 @@ new function() {
15309
15670
  lineargradient: importGradient,
15310
15671
  radialgradient: importGradient,
15311
15672
 
15312
- image: function (node) {
15313
- var raster = new Raster(getValue(node, 'href', true));
15673
+ image: function (node, type, options) {
15674
+ var raster = new Raster({
15675
+ crossOrigin: options.crossOrigin,
15676
+ source: getValue(node, 'href', true)
15677
+ }),
15678
+ align = /none|x(Min|Mid|Max)Y(Min|Mid|Max)/.exec(
15679
+ getValue(node, 'preserveAspectRatio', true))
15680
+ || [null, 'Mid', 'Mid'];
15314
15681
  raster.on('load', function() {
15315
- var size = getSize(node);
15316
- this.setSize(size);
15317
- var center = getPoint(node).add(size.divide(2));
15318
- this._matrix.append(new Matrix().translate(center));
15682
+ var imageSize = this.getSize(),
15683
+ size = getSize(node, null, null, true) || imageSize,
15684
+ point = getPoint(node);
15685
+ if (align[0] !== 'none') {
15686
+ var factors = { Min: 0, Mid: 0.5, Max: 1 },
15687
+ fitted = imageSize.multiply(Math.min(
15688
+ size.width / imageSize.width,
15689
+ size.height / imageSize.height));
15690
+ point = point.add(size.subtract(fitted).multiply(
15691
+ [factors[align[1]], factors[align[2]]]));
15692
+ size = fitted;
15693
+ }
15694
+ var center = point.add(size.divide(2));
15695
+ this._matrix.append(new Matrix().translate(center)
15696
+ .scale(size.divide(imageSize)));
15319
15697
  });
15320
15698
  return raster;
15321
15699
  },
@@ -15327,13 +15705,17 @@ new function() {
15327
15705
 
15328
15706
  defs: importGroup,
15329
15707
 
15330
- use: function(node) {
15708
+ use: function(node, type, options) {
15331
15709
  var id = (getValue(node, 'href', true) || '').substring(1),
15332
- definition = definitions[id],
15710
+ definition = getDefinitionById(id, options),
15333
15711
  point = getPoint(node);
15334
15712
  return definition
15335
15713
  ? definition instanceof SymbolDefinition
15336
15714
  ? definition.place(point)
15715
+ : definition instanceof Raster
15716
+ ? importNode(getSandbox().ownerDocument
15717
+ .getElementById(id), options, false)
15718
+ .translate(point)
15337
15719
  : definition.clone().translate(point)
15338
15720
  : null;
15339
15721
  },
@@ -15352,11 +15734,16 @@ new function() {
15352
15734
  },
15353
15735
 
15354
15736
  rect: function(node) {
15737
+ var rx = getValue(node, 'rx', false, true),
15738
+ ry = getValue(node, 'ry', false, true);
15355
15739
  return new Shape.Rectangle(new Rectangle(
15356
15740
  getPoint(node),
15357
15741
  getSize(node)
15358
- ), getSize(node, 'rx', 'ry'));
15359
- },
15742
+ ), new Size(
15743
+ rx == null ? ry || 0 : rx,
15744
+ ry == null ? rx || 0 : ry
15745
+ ));
15746
+ },
15360
15747
 
15361
15748
  line: function(node) {
15362
15749
  return new Path.Line(
@@ -15366,8 +15753,14 @@ new function() {
15366
15753
 
15367
15754
  text: function(node) {
15368
15755
  var text = new PointText(getPoint(node).add(
15369
- getPoint(node, 'dx', 'dy')));
15370
- text.setContent(node.textContent.trim() || '');
15756
+ getPoint(node, 'dx', 'dy'))),
15757
+ lines = Base.each(node.childNodes, function(child) {
15758
+ if (/^tspan$/i.test(child.nodeName)
15759
+ && child.hasAttribute('y'))
15760
+ this.push(child.textContent.trim());
15761
+ }, []);
15762
+ text.setContent(lines.length > 1 ? lines.join('\n')
15763
+ : node.textContent.trim());
15371
15764
  return text;
15372
15765
  },
15373
15766
 
@@ -15421,9 +15814,11 @@ new function() {
15421
15814
  }
15422
15815
 
15423
15816
  var attributes = Base.set(Base.each(SvgStyles, function(entry) {
15424
- this[entry.attribute] = function(item, value) {
15817
+ this[entry.attribute] = function(item, value, name, node, styles,
15818
+ options) {
15425
15819
  if (item[entry.set]) {
15426
- item[entry.set](convertValue(value, entry.type, entry.fromSVG));
15820
+ item[entry.set](convertValue(value, entry.type, entry.fromSVG,
15821
+ options));
15427
15822
  if (entry.type === 'color') {
15428
15823
  var color = item[entry.get]();
15429
15824
  if (color) {
@@ -15440,12 +15835,12 @@ new function() {
15440
15835
  }, {}), {
15441
15836
  id: function(item, value) {
15442
15837
  definitions[value] = item;
15443
- if (item.setName)
15838
+ if (item.setName && value !== (+value) + '')
15444
15839
  item.setName(value);
15445
15840
  },
15446
15841
 
15447
- 'clip-path': function(item, value) {
15448
- var clip = getDefinition(value);
15842
+ 'clip-path': function(item, value, name, node, styles, options) {
15843
+ var clip = getDefinition(value, options);
15449
15844
  if (clip) {
15450
15845
  clip = clip.clone();
15451
15846
  clip.setClipMask(true);
@@ -15473,6 +15868,14 @@ new function() {
15473
15868
  item.setVisible(value !== null);
15474
15869
  },
15475
15870
 
15871
+ 'letter-spacing': function(item, value) {
15872
+ if (item.setTracking) {
15873
+ var amount = parseFloat(value) || 0;
15874
+ item.setTracking(1000 * (/em$/.test(value) ? amount
15875
+ : amount / parseFloat(item.getFontSize())));
15876
+ }
15877
+ },
15878
+
15476
15879
  'stop-color': function(item, value) {
15477
15880
  if (item.setColor)
15478
15881
  item.setColor(value);
@@ -15518,12 +15921,13 @@ new function() {
15518
15921
  });
15519
15922
 
15520
15923
  function getAttribute(node, name, styles) {
15521
- var attr = node.attributes[name],
15924
+ var style = Base.camelize(name),
15925
+ value = node.style && node.style[style];
15926
+ if (!value) {
15927
+ var attr = node.attributes[name];
15522
15928
  value = attr && attr.value;
15523
- if (!value && node.style) {
15524
- var style = Base.camelize(name);
15525
- value = node.style[style];
15526
- if (!value && styles.node[style] !== styles.parent[style])
15929
+ if (!value && node.style
15930
+ && styles.node[style] !== styles.parent[style])
15527
15931
  value = styles.node[style];
15528
15932
  }
15529
15933
  return !value ? undefined
@@ -15531,27 +15935,38 @@ new function() {
15531
15935
  : value;
15532
15936
  }
15533
15937
 
15534
- function applyAttributes(item, node, isRoot) {
15938
+ function applyAttributes(item, node, options, isRoot) {
15535
15939
  var parent = node.parentNode,
15536
15940
  styles = {
15537
15941
  node: DomElement.getStyles(node) || {},
15538
15942
  parent: !isRoot && !/^defs$/i.test(parent.tagName)
15539
15943
  && DomElement.getStyles(parent) || {}
15540
15944
  };
15945
+ if (isRoot && !styles.node.fill && item.setFillColor)
15946
+ item.setFillColor('black');
15541
15947
  Base.each(attributes, function(apply, name) {
15542
15948
  var value = getAttribute(node, name, styles);
15543
15949
  item = value !== undefined
15544
- && apply(item, value, name, node, styles) || item;
15950
+ && apply(item, value, name, node, styles, options) || item;
15545
15951
  });
15546
15952
  return item;
15547
15953
  }
15548
15954
 
15549
- function getDefinition(value) {
15955
+ function getDefinitionById(id, options) {
15956
+ if (id && !definitions[id]) {
15957
+ var node = getSandbox().ownerDocument.getElementById(id);
15958
+ if (node)
15959
+ importNode(node, options, false);
15960
+ }
15961
+ return definitions[id];
15962
+ }
15963
+
15964
+ function getDefinition(value, options) {
15550
15965
  var match = value && value.match(/\((?:["'#]*)([^"')]+)/),
15551
15966
  name = match && match[1],
15552
- res = name && definitions[window
15967
+ res = name && getDefinitionById(window
15553
15968
  ? name.replace(window.location.href.split('#')[0] + '#', '')
15554
- : name];
15969
+ : name, options);
15555
15970
  if (res && res._scaleToBounds) {
15556
15971
  res = res.clone();
15557
15972
  res._scaleToBounds = true;
@@ -15597,12 +16012,12 @@ new function() {
15597
16012
  var settings = paper.settings,
15598
16013
  applyMatrix = settings.applyMatrix,
15599
16014
  insertItems = settings.insertItems,
16015
+ importer = importers[type],
15600
16016
  item;
15601
16017
  try {
15602
16018
  settings.applyMatrix = false;
15603
16019
  settings.insertItems = false;
15604
16020
  try {
15605
- var importer = importers[type];
15606
16021
  item = importer && importer(node, type, options, isRoot)
15607
16022
  || null;
15608
16023
  } finally {
@@ -15610,8 +16025,8 @@ new function() {
15610
16025
  settings.applyMatrix = applyMatrix;
15611
16026
  }
15612
16027
  if (item) {
15613
- if (isElement && !(item instanceof Group))
15614
- item = applyAttributes(item, node, isRoot);
16028
+ if (isElement && importer !== importGroup)
16029
+ item = applyAttributes(item, node, options, isRoot);
15615
16030
  var onImport = options.onImport,
15616
16031
  data = isElement && node.getAttribute('data-paper-data');
15617
16032
  if (onImport)
@@ -15727,8 +16142,7 @@ new function() {
15727
16142
  };
15728
16143
 
15729
16144
  Base.exports.PaperScript = function() {
15730
- var global = this,
15731
- acorn = global.acorn;
16145
+ var acorn = self.acorn;
15732
16146
  if (!acorn && typeof require !== 'undefined') {
15733
16147
  try { acorn = require('acorn'); } catch(e) {}
15734
16148
  }
@@ -17050,7 +17464,7 @@ Base.exports.PaperScript = function() {
17050
17464
  }
17051
17465
 
17052
17466
  function parse(code, options) {
17053
- return (global.acorn || acorn).parse(code, options);
17467
+ return (self.acorn || acorn).parse(code, options);
17054
17468
  }
17055
17469
 
17056
17470
  var binaryOperators = {
@@ -17306,9 +17720,12 @@ Base.exports.PaperScript = function() {
17306
17720
  if (agent.node) {
17307
17721
  offset -= 2;
17308
17722
  } else if (window && url && !window.location.href.indexOf(url)) {
17309
- var html = document.getElementsByTagName('html')[0].innerHTML;
17310
- offset = html.substr(0, html.indexOf(code) + 1).match(
17311
- lineBreaks).length + 1;
17723
+ var html = document.getElementsByTagName('html')[0].innerHTML,
17724
+ index = html.indexOf(code);
17725
+ if (index >= 0) {
17726
+ offset = html.substr(0, index + 1).match(
17727
+ lineBreaks).length + 1;
17728
+ }
17312
17729
  }
17313
17730
  offsetCode = offset > 0 && !(
17314
17731
  agent.chrome && version >= 36 ||
@@ -17343,7 +17760,8 @@ Base.exports.PaperScript = function() {
17343
17760
  code = new Array(offset + 1).join('\n') + code;
17344
17761
  }
17345
17762
  if (/^(inline|both)$/.test(sourceMaps)) {
17346
- code += "\n//# sourceMappingURL=data:application/json;base64,"
17763
+ code += "\n//# " + "sourceMappingURL="
17764
+ + "data:application/json;base64,"
17347
17765
  + self.btoa(unescape(encodeURIComponent(
17348
17766
  JSON.stringify(map))));
17349
17767
  }
@@ -17453,11 +17871,17 @@ Base.exports.PaperScript = function() {
17453
17871
  async: async,
17454
17872
  mimeType: 'text/plain',
17455
17873
  onLoad: function(code) {
17456
- execute(code, scope, src);
17874
+ execute(code, scope, {
17875
+ url: src,
17876
+ sourceMaps: 'inline'
17877
+ });
17457
17878
  }
17458
17879
  });
17459
17880
  } else {
17460
- execute(script.innerHTML, scope, script.baseURI);
17881
+ execute(script.innerHTML, scope, {
17882
+ url: script.baseURI,
17883
+ sourceMaps: 'inline'
17884
+ });
17461
17885
  }
17462
17886
  script.setAttribute('data-paper-ignore', 'true');
17463
17887
  return scope;
@@ -17489,8 +17913,7 @@ Base.exports.PaperScript = function() {
17489
17913
  calculateBinary: __$__,
17490
17914
  calculateUnary: $__
17491
17915
  };
17492
-
17493
- }.call(this);
17916
+ }();
17494
17917
 
17495
17918
  var paper = new (PaperScope.inject(Base.exports, {
17496
17919
  Base: Base,
@@ -17500,8 +17923,10 @@ var paper = new (PaperScope.inject(Base.exports, {
17500
17923
  DomElement: DomElement,
17501
17924
  document: document,
17502
17925
  window: window,
17503
- Symbol: SymbolDefinition,
17504
17926
  PlacedSymbol: SymbolItem
17927
+ }).inject({
17928
+ enumerable: false,
17929
+ Symbol: SymbolDefinition
17505
17930
  }))();
17506
17931
 
17507
17932
  if (paper.agent.node) {
@@ -17515,4 +17940,4 @@ if (typeof define === 'function' && define.amd) {
17515
17940
  }
17516
17941
 
17517
17942
  return paper;
17518
- }.call(this, typeof self === 'object' ? self : null);
17943
+ }(typeof self === 'object' ? self : null);