paper.js v0.10.0 Release Notes

  • Preamble

    ๐Ÿš€ This is a huge release for Paper.js as we aim for a version 1.0.0 release later this year. As of this version, all notable changes are documented in the ๐Ÿ”„ change-log following common CHANGELOG conventions. Paper.js now also adheres to Semantic Versioning.

    There are many items in the changelog (and many more items not in the changelog) so here a high-level overview to frame the long list of changes:

    • Boolean operations have been improved and overhauled for reliability and efficiency. These include the path functions to unite, intersect, subtract, exclude, and divide with another path.

    • โœ… There was a large amount of work implementing test coverage under QUnit.

    • Mouse and key handling has been re-engineered and extended to work with view. Many outstanding bugs have been fixed with mouse and key handling.

    • ๐Ÿ’ป Many SVG-handling enhancements and bug-fixes, including handling browser- specific interpretations of the SVG standard, have been added.

    • There are API name changes for more consistency as well as some required by changes in the EcmaScript 6 standard (e.g., Symbol โ†’ SymbolDefinition).

    • Even though it is not new, since version 0.9.22 Paper.js no longer resizes the canvas to match the view. The canvas must be resized independently.

    Thank you all for using Paper.js, submitting bugs and ideas, and all those that contribute to the code.

    ๐Ÿ”„ Changed

    • Significant overhaul and improvements of boolean path operations PathItem#unite(), #subtract(), #intersect(), #exclude(), #divide():
      • Improve handling of self-intersecting paths and non-zero fill-rules.
      • Handle operations on identical paths.
      • Improve handling of near-collinear lines.
      • Handle self-intersecting paths that merely "touch" themselves.
      • Handle situations where all encountered intersections are part of overlaps.
    • Methods that accepted a time parameter or boolean second parameter causing the argument to be interpreted as curve-time instead of offset are now separate functions with distinct names (#563):
      • Curve#getNormalAt(time, true) โ†’ #getNormalAtTime(true)
      • Curve#divide() โ†’ #divideAt(offset) / #divideAtTime(time)
      • Curve#split() โ†’ #splitAt(offset) / #splitAtTime(time)
      • Curve#getParameterAt(offset) โ†’ #getTimeAt(offset)
      • Curve#getParameterOf(point) โ†’ getTimeOf(point)
      • Curve#getPointAt(time, true) โ†’ #getPointAtTime(time)
      • Curve#getTangentAt(time, true) โ†’ #getTangentAtTime(time)
      • Curve#getNormalAt(time, true) โ†’ #getNormalAtTime(time)
      • Curve#getCurvatureAt(time, true) โ†’ #getCurvatureAtTime(time)
      • CurveLocation#parameter โ†’ #time
      • Path#split(offset/location) โ†’ #splitAt(offset/location)
    • Significant improvement of reliability of bezier fat-line clipping code in PathItem#getIntersections() and #getCrossings().
    • PathItem#smooth() now accepts an options.type string specifying which smoothing algorithm to use: 'asymmetric' (default), 'continuous', 'catmull-rom', and 'geometric' (#338).
    • PathItem#flatten(): argument has been changed from tolerance (maximum allowed distance between points) to flatness (maximum allowed error) (#618).
    • โšก๏ธ Update internal Acorn JavaScript parser to 0.5.0, the last small version.
    • ๐Ÿ— Transition to Gulp based build process.
    • โšก๏ธ Update QUnit to 1.20.0.
    • โšก๏ธ Update to JSDOM 8.3.0, to benefit from integrated image and canvas support.
    • ๐Ÿ”จ Complete refactoring of keyboard event handling to increase reliably when handling special keys.
    • ๐Ÿ”จ Complete refactoring of mouse-event handling on item and view, to better handle event propagation, default behavior and Item#removeOn() calls.
    • Simplify and streamline the mouse-handling code on Tool (#595).
    • Mouse handlers can to return false to call event.stop(), stopping event propagation and prevent the default browser behavior.
    • 0๏ธโƒฃ event.preventDefault() is called by default after any handled mouse mouse events, except 'mousemove', and only on a 'mousedown' event if the view or tool respond to 'mouseup'.
    • Switch to the new HTML5 Page Visibility API when detecting invisible documents and canvases.
    • ๐Ÿ’… Rename #windingRule to #fillRule on Item and Style.
    • Do not replace existing named child reference on Item#children with new one when the name is identical.
    • Limit the effects of #strokeScaling to PathItem and Shape (#721).
    • ๐Ÿ‘ป Throw an exception if arguments to #smooth() are segments or curves from incorrect paths.
    • ๐Ÿ“‡ Rename Matrix#concatenate() to #append() and preConcatenate() to #prepend().
    • ๐Ÿ‘‰ Make Matrix#shiftless() and #orNullIfIdentity() internal functions.
    • โšก๏ธ De-bounce internal View#update() calls to minimize the number of times a canvas is redrawn (#830, #925).
    • Symbol now clashes with ES6 definition of Symbol and has been changed (#770):
      • Symbol โ†’ SymbolDefinition
      • PlacedSymbol โ†’ SymbolItem
      • Symbol#definition โ†’ SymbolDefinition#item
      • PlacedSymbol#symbol โ†’ SymbolItem#definition
    • ๐Ÿ’… Don't serialize deprecated Style#font property.
    • ๐Ÿ’… Don't serialize text-styles in non-text items (#934).
    • ๐Ÿ’… Changed argument parameter to time for Postscript-style drawing commands.
    • 0๏ธโƒฃ Item#clone(): optional argument is now an options object with defaults {insert: true, deep: true}. insert controls whether the clone is inserted into the project and deep controls whether the item's children are cloned. The previous boolean optional argument is still interpreted as the insert option (#941).
    • Matrix properties #b and #c have been reversed to match common standard.
    • ๐Ÿ’… #importSVG(): improve handling of style inheritance for nested <defs>.
    • ๐Ÿšš Move PaperScript#execute() URL argument into options.url (#902).
    • PaperScript: Only translate == to equals() calls forPoint,Sizeand Color` (#1043).

    โž• Added

    • ๐Ÿ’ป Use unified code-base for browsers, Node.js, Electron, and anything in-between, and enable npm install for browser use (#739).
    • ๐Ÿš€ Start using automatic code testing and deployment of prebuilt versions through Travis CI.
    • ๐Ÿ‘• Reach JSHint compliance and include regular linting in Travis CI tests.
    • โœ… Use QUnit tests for leaked globals.
    • Define code format standards in .editorconfig file
    • โž• Add support for running without a canvas for Web Workers, Node.js (#561, #582, #634).
    • โž• Add support for all common mouse events to View.
    • โž• Add support for 'keydown' and 'keyup' events to View (#896).
    • โž• Add View#requestUpdate() function to minimize number of actual canvas redraw.
    • โž• Add View#matrix to allow matrix transformation to be accessed and modified directly on the view (#832).
    • Multiple additions to SVG export (#exportSVG()):
      • Support { precision: value } option.
      • Support #fillRule through the SVG fill-rule attribute.
      • Support #blendMode through the CSS mix-blend-mode attribute.
    • Various additions to #getItems() on Project and Item:
      • Add support for { recursive: false } as a way to prevent iterating over all children of children.
      • Add support for { match: function() {} }, so the match function can be passed in combination with other options.
    • โž• Add Item#copyAttributes() and Item#copyContent(), and use them in Item#clone().
    • โž• Add optional insert boolean argument to Path#toShape(), Shape#toPath(), Item#rasterize(). Default is to insert, set to false to prevent the created item from being inserted into the scene graph.
    • โž• Add visual item comparison to QUnit, through rasterization and Resemble.js diffing.
    • โž• Add many unit tests for known edge cases in boolean operations and curve intersections.
    • โž• Add Project#addLayer() and Project#insertLayer() (#903).
    • Layers may now be given names and be accessed through project.layers[name] (#491).
    • โž• Add Matrix#prepended() and #appended() to return copies of the modified matrix.
    • โœ… Shape#hitTest(): Add boolean option options.stroke (#911).
    • ๐Ÿ“„ Insert version number into docs.
    • ๐Ÿ‘Œ Support Raster#onLoad() events on Raster#setImage() now (#924).
    • โž• Add Raster#onError() event support (#849).
    • ๐Ÿ‘ Allow the control of automatic updating of the canvas through View#autoUpdate (default: true)(#921).
    • 0๏ธโƒฃ Set 1px default strokeWidth for SVG imports to fix IE/Edge default (#467).
    • ImportSVG() passes imported SVG data to onLoad callback as second parameter.
    • โž• Add #interpolate for Segment, Path, and CompoundPath (#624).
    • Implement CompoundPath#flatten(), #simplify(), #smooth() (#727).
    • โœ… Implement #hitTestAll() to return all items that were hit (#536).
    • #importSVG() implements option.onError callback (#969).
    • settings.insertItems controls whether newly created items are inserted or not (default: true).
    • โž• Add #importSVG() option.insert (default: true) to control insertion (#763).
    • โž• Add new options to #exportSVG() to control output bounds and transformation matrix (#972).
    • ๐Ÿ‘ Allow Item#position to be selected via Item#position.selected (#980).
    • โž• Add tolerance argument to Path#join(path, tolerance).
    • โž• Add Curve#getOffsetAtTime(time), as the reverse of Curve#getTimeAt(offset).
    • โž• Add Raster#loaded to reflect the loading state of its image.

    ๐Ÿ›  Fixed

    • ๐Ÿ›  Fix calculations of Item#strokeBounds for all possible combinations of Item#strokeScaling and Item#applyMatrix for Path, Shape and SymbolItem, along with correct handling of such strokes in Item#hitTest() (#697, #856, #1014).
    • ๐Ÿ’ป Make new code-base unified for Node.js/browser work with module bundlers like Webpack (#986).
    • ๐Ÿ‘Œ Improve hit-testing and #contains() checks on path with horizontal lines (#819).
    • ๐Ÿ‘Œ Improve reliability of Path#getInteriorPoint() in rare edge-cases.
    • โœ… Handle non-reversible matrices in Item#hitTest() (#617).
    • ๐Ÿ›  Fix various issues with adding and removing of segments in paths (#815).
    • ๐Ÿ‘Œ Support bubbling up of doubleclick events on Group (#834).
    • ๐Ÿ›  Fix wrong #key values in key-events that do not match character (#881).
    • ๐Ÿ›  Fix keyboard event handling of control and meta keyboard sequences and special character handling (#860).
    • ๐Ÿ Handle incorrect mouse event on ctrl-alt-del key sequence on Chrome/Windows (#800).
    • Do not rasterize items if the resulting raster will be empty (#828).
    • ๐Ÿ›  Fix SVG serialization in JSDOM 7.0.0 and newer (#821).
    • Correctly handle gradients in SVG import on Firefox (#666).
    • Consistently interpret curves as straight or not-straight (#838).
    • ๐ŸŽ Switch blendMode to 'lighter' in Candy Crash example for better performance (#453).
    • Don't block touch actions when using paper in JavaScript mode (#686).
    • Convert touch event coordinates to project coordinates (#633).
    • ๐Ÿ›  Fix exceptions when a top-level layer is selected.
    • โœ… Don't allow layers to turn up in hit-tests (#608).
    • Maintain Raster#source correctly on Node.js (#914).
    • Boolean operations correctly handle open Path items within CompoundPath (#912).
    • Don't modify an array of child items passed to CompoundPath#insertChildren() when it is a child items array of a CompoundPath.
    • โœ… Correctly handle #strokeScaling in Shape hit-tests (#697).
    • ๐Ÿ‘Œ Support clip-masks in hit-testing (#671).
    • ๐Ÿ›  Fix incorrect #hitTest() and #contains() cases (#819, #884).
    • ๐Ÿ“š Update documentation to note appropriate use for #simplify() (#920).
    • ๐Ÿ‘ #importSVG() now supports percentage dimensions and gradientUnits="objectBoundingBox". (#954, #650).
    • Group items with clip-masks now calculate correct bounding boxes (#956).
    • Calling event.stopPropagation() in 'mousedown' handler no longer prevents 'mousedrag' events (#952).
    • Draw Item shadows when #shadowBlur is zero (#955).
    • ๐Ÿ›  Fixes for web site examples (#967).
    • Prevent Item bounds from permanently collapsing to 0 when applying non- invertible transformations (#558).
    • ๐Ÿ’ป Scaling shadows now works correctly with browser- and view-zoom (#831).
    • Path#arcTo() correctly handles zero sizes.
    • #importSVG() handles onLoad and onError callbacks for string inputs that load external resources (#827).
    • #importJSON() and #exportJSON() now handle non-Item objects correctly (#392).
    • #exportSVG() now exports empty paths if used as a clip-mask.
    • #importJSON() no longer generates callstack exceeded exceptions (#764).
    • ๐Ÿ›  Fix problems with group selection structures after Group#importJSON() (#785).
    • ๐Ÿ›  Fix an issue in Item#importJSON() where #parent is null when calling it on existing, already inserted items (#1041).
    • Correct issue when using paper-core in Node.js (#975).
    • ๐Ÿ›  Fix event.delta on mousedrag events (#981).
    • ๐Ÿ‘Œ Improve handling of XML attribute namespaces for IE's XMLSerializer() (#984).
    • ๐Ÿšš Make sure Item#removeChildren() fully removes children (#991).
    • ๐Ÿ‘Œ Improve handling of event propagation on View and Item (#995).
    • #importSVG(): Improve handling of viewBox.
    • ๐Ÿ”€ Make sure all named item lookup structures are kept in sync (#1009).
    • Convert absolute local gradient URLs to relative ones (#1001).
    • ๐Ÿ›  Fix TypeError in Path#unite() (#1000).
    • ๐Ÿ‘ Allow the selection of a Path item's bounds without selecting the segments (#769).
    • ๐Ÿ›  Fix wrong indices in Item#insertChildren(), when inserting children that were previously inserted in the same parent (#1015).
    • โž• Add capability to PathItem#closePath() to handle imprecise SVG data due to rounding (#1045).
    • ๐Ÿ‘Œ Improve reliability of fat-line clipping for curves that are very similar (#904).
    • ๐Ÿ‘Œ Improve precision of Numerical.solveQuadratic() and Numerical.solveCubic() for edge-cases (#1085).

    โœ‚ Removed

    • Canvas attributes "resize" and "data-paper-resize" no longer cause paper to resize the canvas when the viewport size changes; Additional CSS styles are required since 0.9.22, e.g.:
      /* Scale canvas with resize attribute to full size */
      canvas[resize] {
          width: 100%;
          height: 100%;
      }
    
    • ๐Ÿšš Legacy Color constructors (removed in 0.9.25): GrayColor, RgbColor, HsbColor, HslColor, and GradientColor. These have been replaced with corresponding forms of the Color constructor.
    • Undocumented function Project#addChild() that added a layer to a project. It is replaced by Project#addLayer() and Project#insertLayer().

    ๐Ÿ—„ Deprecated

    • ๐Ÿ’… #windingRule on Item and Style โ†’ #fillRule
    • Curve#getNormalAt(time, true) โ†’ #getNormalAtTime(true)
    • Curve#divide() โ†’ #divideAt(offset) / #divideAtTime(time)
    • Curve#split() โ†’ #splitAt(offset) / #splitAtTime(time)
    • Curve#getParameterAt(offset) โ†’ #getTimeAt(offset)
    • Curve#getParameterOf(point) โ†’ getTimeOf(point)
    • Curve#getPointAt(time, true) โ†’ #getPointAtTime(time)
    • Curve#getTangentAt(time, true) โ†’ #getTangentAtTime(time)
    • Curve#getNormalAt(time, true) โ†’ #getNormalAtTime(time)
    • Curve#getCurvatureAt(time, true) โ†’ #getCurvatureAtTime(time)
    • CurveLocation#parameter โ†’ #time
    • Path#split(offset/location) โ†’ #splitAt(offset/location)
    • Symbol โ†’ SymbolDefinition
    • PlacedSymbol โ†’ SymbolItem
    • Symbol#definition โ†’ SymbolDefinition#item
    • PlacedSymbol#symbol โ†’ SymbolItem#definition
    • Project#symbols โ†’ #symbolDefinitions
    • Matrix#concatenate โ†’ #append
    • Matrix#preConcatenate โ†’ #prepend
    • Matrix#chain โ†’ #appended
    • GradientStop#rampPoint โ†’ #offset