skia-canvas 0.9.24 → 0.9.28
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.
- package/CHANGELOG.md +195 -0
- package/README.md +188 -84
- package/lib/index.d.ts +231 -0
- package/lib/index.js +72 -34
- package/package.json +14 -9
- package/Makefile +0 -60
- package/src/canvas.rs +0 -417
- package/src/context/api.rs +0 -1056
- package/src/context/mod.rs +0 -814
- package/src/gradient.rs +0 -174
- package/src/image.rs +0 -99
- package/src/lib.rs +0 -222
- package/src/path.rs +0 -520
- package/src/pattern.rs +0 -130
- package/src/texture.rs +0 -124
- package/src/typography.rs +0 -624
- package/src/utils.rs +0 -701
- package/test/assets/AmstelvarAlpha-VF.ttf +0 -0
- package/test/assets/blend-bg.png +0 -0
- package/test/assets/blend-fg.png +0 -0
- package/test/assets/checkers.png +0 -0
- package/test/assets/globe.jpg +0 -0
- package/test/assets/grayscale.jpg +0 -0
- package/test/assets/halved-1.jpeg +0 -0
- package/test/assets/halved-2.jpeg +0 -0
- package/test/assets/image/format.bmp +0 -0
- package/test/assets/image/format.gif +0 -0
- package/test/assets/image/format.ico +0 -0
- package/test/assets/image/format.jpg +0 -0
- package/test/assets/image/format.pdf +5 -1322
- package/test/assets/image/format.png +0 -0
- package/test/assets/path/effect-interpolate@2x.png +0 -0
- package/test/assets/path/effect-jitter@2x.png +0 -0
- package/test/assets/path/effect-points@2x.png +0 -0
- package/test/assets/path/effect-round@2x.png +0 -0
- package/test/assets/path/effect-simplify@2x.png +0 -0
- package/test/assets/path/effect-trim@2x.png +0 -0
- package/test/assets/path/effect-unwind@2x.png +0 -0
- package/test/assets/path/lineDashMarker@2x.png +0 -0
- package/test/assets/path/operation-none.svg +0 -6
- package/test/assets/path/operations@2x.png +0 -0
- package/test/assets/path/outlineText@2x.png +0 -0
- package/test/assets/pentagon-cmyk.jpg +0 -0
- package/test/assets/pentagon-grayscale.jpg +0 -0
- package/test/assets/pentagon.png +0 -0
- package/test/assets/quadrants.png +0 -0
- package/test/assets/star.png +0 -0
- package/test/assets/state.png +0 -0
- package/test/canvas.test.js +0 -490
- package/test/context2d.test.js +0 -738
- package/test/media.test.js +0 -204
- package/test/path2d.test.js +0 -614
- package/test/visual/index.html +0 -193
- package/test/visual/index.js +0 -68
- package/test/visual/tests.js +0 -2669
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
<!-- ## 🥚 ⟩ [Unreleased] -->
|
|
4
|
+
|
|
5
|
+
## 📦 ⟩ [v0.9.28] ⟩ Jan 12, 2022
|
|
6
|
+
|
|
7
|
+
### New Features
|
|
8
|
+
- Added TypeScript definitions for extensions to the DOM spec (contributed by [@cprecioso](https://github.com/cprecioso))
|
|
9
|
+
- Added 3D-perspective transformations via the new [createProjection()](https://github.com/samizdatco/skia-canvas#createprojectionquad-basis) context method
|
|
10
|
+
- Colors can now use the [hwb()](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hwb()) model
|
|
11
|
+
|
|
12
|
+
### Breaking Changes
|
|
13
|
+
- The **Canvas** [`.async`](https://github.com/samizdatco/skia-canvas#async) property has been **deprecated** and will be removed in a future release.
|
|
14
|
+
- The `saveAs`, `toBuffer`, and `toDataURL` methods will now be async-only (likewise the [shorthand properties](https://github.com/samizdatco/skia-canvas#pdf-svg-jpg-and-png)).
|
|
15
|
+
- Use their synchronous counterparts (`saveAsSync`, `toBufferSync`, and `toDataURLSync`) if you want to block execution while exporting images.
|
|
16
|
+
- The [ImageData](https://developer.mozilla.org/en-US/docs/Web/API/ImageData/ImageData) constructor now orders its arguments properly: the optional buffer/array argument now comes first
|
|
17
|
+
|
|
18
|
+
### Bugfixes
|
|
19
|
+
- Fixed a stack overflow that was occurring when images became too deeply nested for the default deallocator to handle (primarily due to many thousands of image exports from the same canvas)
|
|
20
|
+
- The `source-in`, `source-out`, `destination-atop`, and `copy` composite operations now work correctly for paths rather than rendering shapes without color (contributed by [@meihuanyu](https://github.com/meihuanyu))
|
|
21
|
+
- Shape primitives now behave consistently with browsers when being added to a non-empty path:
|
|
22
|
+
- `rect()` now issues an initial `moveTo` rather than extending the path, then leaves the ‘current’ point in its upper left corner
|
|
23
|
+
- `ellipse()` extends the current path rather than implicitly closing it (contributed by [@meihuanyu](https://github.com/meihuanyu))
|
|
24
|
+
- `arc()` also extends the current path rather than closing it
|
|
25
|
+
|
|
26
|
+
### Misc. Improvements
|
|
27
|
+
- Upgraded Skia to milestone 96
|
|
28
|
+
- Added workflow for creating docker build environments
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## 📦 ⟩ [v0.9.27] ⟩ Oct 23, 2021
|
|
32
|
+
|
|
33
|
+
### New Features
|
|
34
|
+
- Added pre-compiled binaries for Alpine Linux using the [musl](https://musl.libc.org) C library
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## 📦 ⟩ [v0.9.26] ⟩ Oct 18, 2021
|
|
38
|
+
|
|
39
|
+
### New Features
|
|
40
|
+
- Added pre-compiled binaries for 32-bit and 64-bit ARM on Linux (a.k.a. Raspberry Pi)
|
|
41
|
+
|
|
42
|
+
### Bugfixes
|
|
43
|
+
- Windows text rendering has been restored after failing due to changes involving the `icudtl.dat` file
|
|
44
|
+
- `FontLibrary.use` now reports an error if the specified font file doesn't exist
|
|
45
|
+
- Fixed a crash that could result from calling `measureText` with various unicode escapes
|
|
46
|
+
|
|
47
|
+
### Misc. Improvements
|
|
48
|
+
- Upgraded Skia to milestone 94
|
|
49
|
+
- Now embedding a more recent version of the FreeType library on Linux with support for more font formats
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## 📦 ⟩ [v0.9.25] ⟩ Aug 22, 2021
|
|
53
|
+
|
|
54
|
+
### Bugfixes
|
|
55
|
+
- Improved image scaling when a larger image is being shrunk down to a smaller size via [`drawImage()`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage)
|
|
56
|
+
- modified [`imageSmoothingQuality`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality) settings to provide a more meaningful range across `low`, `medium`, and `high`
|
|
57
|
+
- [`measureText()`](https://github.com/samizdatco/skia-canvas#measuretextstr-width) now returns correct metrics regardless of current `textAlign` setting
|
|
58
|
+
- Rolled back `icudtl.dat` changes on Windows (which suppressed the misleading warning message but required running as Administrator)
|
|
59
|
+
|
|
60
|
+
### Misc. Improvements
|
|
61
|
+
- Now using [Neon](https://github.com/neon-bindings/neon) v0.9 (with enhanced async event scheduling)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## 📦 ⟩ [v0.9.24] ⟩ Aug 18, 2021
|
|
65
|
+
|
|
66
|
+
### New Features
|
|
67
|
+
- **Path2D** objects now have a read/write [`d`](https://github.com/samizdatco/skia-canvas/#d) property with an [SVG representation](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands) of the path’s contours and an [`unwind()`](https://github.com/samizdatco/skia-canvas/#unwind) method for converting from even-odd to non-zero winding rules
|
|
68
|
+
- The [`createTexture()`](https://github.com/samizdatco/skia-canvas#createtexturespacing-path-line-color-angle-offset0) context method returns **CanvasTexture** objects which can be assigned to `fillStyle` or `strokeStyle`
|
|
69
|
+
- Textures draw either a parallel-lines pattern or one derived from the provided **Path2D** object and positioning parameters
|
|
70
|
+
- The marker used when `setLineDash` is active can now be customized by assigning a **Path2D** to the context’s [`lineDashMarker`](https://github.com/samizdatco/skia-canvas#linedashmarker) property (default dashing can be restored by assigning `null`)
|
|
71
|
+
- The marker’s orientation & shape relative to the path being stroked can be controlled by the [`lineDashFit`](https://github.com/samizdatco/skia-canvas#linedashfit) property which defaults to `"turn"` but can be set to `"move"` (which preserves orientation) or `"follow"` (which distorts the marker’s shape to match the contour)
|
|
72
|
+
|
|
73
|
+
### Bugfixes
|
|
74
|
+
|
|
75
|
+
- Removed use of the `??` operator which is unavailable prior to Node 14
|
|
76
|
+
- Prevented a spurious warning on windows incorrectly claiming that the `icudtl.dat` file could not be found
|
|
77
|
+
|
|
78
|
+
### Misc. Improvements
|
|
79
|
+
|
|
80
|
+
- The **Path2D** [`simplify()`](https://github.com/samizdatco/skia-canvas/#simplifyrulenonzero) method now takes an optional fill-rule argument
|
|
81
|
+
- Added support for versions of macOS starting with 10.13 (High Sierra)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## 📦 ⟩ [v0.9.23] ⟩ Jul 12, 2021
|
|
85
|
+
|
|
86
|
+
### New Features
|
|
87
|
+
|
|
88
|
+
- [Conic béziers][conic_bezier] can now be drawn to the context or a Path2D with the [`conicCurveTo()`][conic_curveto] method
|
|
89
|
+
- Text can be converted to a Path2D using the context’s new [`outlineText()`][outline_text] method
|
|
90
|
+
- Path2D objects can now report back on their internal geometry with:
|
|
91
|
+
- the [`edges`][edges] property which contains an array of line-drawing commands describing the path’s individual contours
|
|
92
|
+
- the [`contains()`][contains] method which tests whether a given point is on/within the path
|
|
93
|
+
- the [`points()`][points] method which returns an array of `[x, y]` pairs at the requested spacing along the curve’s periphery
|
|
94
|
+
- A modified copy of a source Path2D can now be created using:
|
|
95
|
+
- [`offset()`][offset] or [`transform()`][transform] to shift position or apply a DOMMatrix respectively
|
|
96
|
+
- [`jitter()`][jitter] to break the path into smaller sections and apply random noise to the segments’ positions
|
|
97
|
+
- [`round()`][round] to round off every sharp corner in a path to a particular radius
|
|
98
|
+
- [`trim()`][trim] to select a percentage-based subsection of the path
|
|
99
|
+
- Two similar paths can be ‘tweened’ into a proportional combination of their coordinates using the [`interpolate()`][interpolate] method
|
|
100
|
+
|
|
101
|
+
### Bugfixes
|
|
102
|
+
|
|
103
|
+
- Passing a Path2D argument to the `fill()` or `stroke()` method no longer disturbs the context’s ‘current’ path (if one has been created using `beginPath()`)
|
|
104
|
+
- The `filter` property will now accept percentage values greater than 999%
|
|
105
|
+
|
|
106
|
+
### Misc. Improvements
|
|
107
|
+
|
|
108
|
+
- The `newPage()` and `saveAs()` methods now work in the browser, including the ability to save image sequences to a zip archive. The browser’s canvas is still doing all the drawing however, so file export formats will be limited to PNG and JPEG and none of the other Skia-specific extensions will be available.
|
|
109
|
+
- The file-export methods now accept a [`matte`][matte] value in their options object which can be used to set the background color for any portions of the canvas that were left semi-transparent
|
|
110
|
+
- Canvas dimensions are no longer rounded-off to integer values (at least until a bitmap needs to be generated for export)
|
|
111
|
+
- Linux builds will now run on some older systems going back to glibc 2.24
|
|
112
|
+
|
|
113
|
+
[conic_bezier]: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/curves/beziers#the-conic-bézier-curve
|
|
114
|
+
[conic_curveto]: https://github.com/samizdatco/skia-canvas#coniccurvetocpx-cpy-x-y-weight
|
|
115
|
+
[outline_text]: https://github.com/samizdatco/skia-canvas#outlinetextstr
|
|
116
|
+
[matte]: https://github.com/samizdatco/skia-canvas#matte
|
|
117
|
+
|
|
118
|
+
[edges]: https://github.com/samizdatco/skia-canvas#edges
|
|
119
|
+
[contains]: https://github.com/samizdatco/skia-canvas#containsx-y
|
|
120
|
+
[points]: https://github.com/samizdatco/skia-canvas#pointsstep1
|
|
121
|
+
[offset]: https://github.com/samizdatco/skia-canvas#offsetdx-dy
|
|
122
|
+
[transform]: https://github.com/samizdatco/skia-canvas#transformmatrix-or-transforma-b-c-d-e-f
|
|
123
|
+
|
|
124
|
+
[interpolate]: https://github.com/samizdatco/skia-canvas#interpolateotherpath-weight
|
|
125
|
+
[jitter]: https://github.com/samizdatco/skia-canvas#jittersegmentlength-amount-seed0
|
|
126
|
+
[round]: https://github.com/samizdatco/skia-canvas#roundradius
|
|
127
|
+
[simplify]: https://github.com/samizdatco/skia-canvas#simplify
|
|
128
|
+
[trim]: https://github.com/samizdatco/skia-canvas#trimstart-end-inverted
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
## 📦 ⟩ [v0.9.22] ⟩ Jun 09, 2021
|
|
132
|
+
|
|
133
|
+
### New Features
|
|
134
|
+
|
|
135
|
+
- Rasterization and file i/o are now handled asynchronously in a background thread. See the discussion of Canvas’s new [`async`](https://github.com/samizdatco/skia-canvas#async) property for details.
|
|
136
|
+
- Output files can now be generated at pixel-ratios > 1 for High-DPI screens. `SaveAs` and the other canvas output functions all accept an optional [`density`](https://github.com/samizdatco/skia-canvas#density) argument which is an integer ≥1 and will upscale the image accordingly. The density can also be passed using the `filename` argument by ending the name with an ‘@’ suffix like `some-image@2x.png`.
|
|
137
|
+
- SVG exports can optionally convert text to paths by setting the [`outline`](https://github.com/samizdatco/skia-canvas#outline) argument to `true`.
|
|
138
|
+
|
|
139
|
+
### Breaking Changes
|
|
140
|
+
|
|
141
|
+
- The canvas functions dealing with rasterization (`toBuffer`, `toDataURL`, `png`, `jpg`, `pdf`, and `svg`) and file i/o (`saveAs`) are now asynchronous and return `Promise` objects. The old, synchronous behavior is still available on a canvas-by-canvas basis by setting its `async` property to `false`.
|
|
142
|
+
- The optional `quality` argument accepted by the output methods is now a float in the range 0–1 rather than an integer from 0–100. This is consistent with the [encoderOptions](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL) arg in the spec. Quality now defaults to 0.92 (again, as per the spec) rather than lossless.
|
|
143
|
+
|
|
144
|
+
### Bugfixes
|
|
145
|
+
|
|
146
|
+
- `measureText` was reporting zero when asked to measure a string that was entirely made of whitespace. This is still the case for ‘blank‘ lines when `textWrap` is set to `true` but in the default, single-line mode the metrics will now report the width of the whitespace.
|
|
147
|
+
- Changed the way text rendering was staged so that SVG exports didn’t *entirely omit(!)* text from their output. As a result, `Context2D`s now use an external `Typesetter` struct to manage layout and rendering.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
## 📦 ⟩ [v0.9.21] ⟩ May 22, 2021
|
|
151
|
+
|
|
152
|
+
### New Features
|
|
153
|
+
- Now runs on Windows and Apple Silicon Macs.
|
|
154
|
+
- Precompiled binaries support Node 10, 12, 14+.
|
|
155
|
+
- Image objects can be initialized from PNG, JPEG, GIF, BMP, or ICO data.
|
|
156
|
+
- Path2D objects can now be combined using [boolean operators](https://github.com/samizdatco/skia-canvas/#complement-difference-intersect-union-and-xor) and can measure their own [bounding boxes](https://github.com/samizdatco/skia-canvas/#bounds).
|
|
157
|
+
- Context objects now support [`createConicGradient()`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createConicGradient).
|
|
158
|
+
- Image objects now return a promise from their [`decode()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode) method allowing for async loading without the [`loadImage`](https://github.com/samizdatco/skia-canvas/#loadimage) helper.
|
|
159
|
+
|
|
160
|
+
### Bugfixes
|
|
161
|
+
- Calling `drawImage` with a `Canvas` object as the argument now uses a Skia `Pict` rather than a `Drawable` as the interchange format, meaning it can actually respect the canvas's current `globalAlpha` and `globalCompositeOperation` state (fixed #6).
|
|
162
|
+
- Improved some spurious error messages when trying to generate a graphics file from a canvas whose width and/or height was set to zero (fixed #5).
|
|
163
|
+
- `CanvasPattern`s now respect the `imageSmoothingEnabled` setting
|
|
164
|
+
- The `counterclockwise` arg to `ellipse` and `arc` is now correctly treated as optional.
|
|
165
|
+
|
|
166
|
+
### Misc. Improvements
|
|
167
|
+
- Made the `console.log` representations of the canvas-related objects friendlier.
|
|
168
|
+
- Added new test suites for `Path2D`, `Image`, and `Canvas`’s format support.
|
|
169
|
+
- Created [workflows](https://github.com/samizdatco/skia-canvas/tree/master/.github/workflows) to automate precompiled binary builds, testing, and npm package updating.
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
## 📦 ⟩ [v0.9.20] ⟩ Mar 27, 2021
|
|
173
|
+
|
|
174
|
+
### Bugfixes
|
|
175
|
+
- The `loadImage` helper can now handle `Buffer` arguments
|
|
176
|
+
|
|
177
|
+
### Misc. Improvements
|
|
178
|
+
- Improved documentation of compilation steps and use of line height with `ctx.font`
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
## 📦 ⟩ [v0.9.19] ⟩ Aug 30, 2020
|
|
182
|
+
|
|
183
|
+
**Initial public release** 🎉
|
|
184
|
+
|
|
185
|
+
[unreleased]: https://github.com/samizdatco/skia-canvas/compare/v0.9.28...HEAD
|
|
186
|
+
[v0.9.28]: https://github.com/samizdatco/skia-canvas/compare/v0.9.27...v0.9.28
|
|
187
|
+
[v0.9.27]: https://github.com/samizdatco/skia-canvas/compare/v0.9.26...v0.9.27
|
|
188
|
+
[v0.9.26]: https://github.com/samizdatco/skia-canvas/compare/v0.9.25...v0.9.26
|
|
189
|
+
[v0.9.25]: https://github.com/samizdatco/skia-canvas/compare/v0.9.24...v0.9.25
|
|
190
|
+
[v0.9.24]: https://github.com/samizdatco/skia-canvas/compare/v0.9.23...v0.9.24
|
|
191
|
+
[v0.9.23]: https://github.com/samizdatco/skia-canvas/compare/v0.9.22...v0.9.23
|
|
192
|
+
[v0.9.22]: https://github.com/samizdatco/skia-canvas/compare/v0.9.21...v0.9.22
|
|
193
|
+
[v0.9.21]: https://github.com/samizdatco/skia-canvas/compare/v0.9.20...v0.9.21
|
|
194
|
+
[v0.9.20]: https://github.com/samizdatco/skia-canvas/compare/v0.9.19...v0.9.20
|
|
195
|
+
[v0.9.19]: https://github.com/samizdatco/skia-canvas/compare/v0.9.15...v0.9.19
|
package/README.md
CHANGED
|
@@ -9,9 +9,10 @@ In particular, Skia Canvas:
|
|
|
9
9
|
- is fast and compact since all the heavy lifting is done by native code written in Rust and C++
|
|
10
10
|
- can generate output in both raster (JPEG & PNG) and vector (PDF & SVG) image formats
|
|
11
11
|
- can save images to [files][saveAs], return them as [Buffers][toBuffer], or encode [dataURL][toDataURL_ext] strings
|
|
12
|
-
- uses native threads and [
|
|
12
|
+
- uses native threads and [channels](https://docs.rs/neon/0.9.0/neon/event/struct.Channel.html) for asynchronous rendering and file I/O
|
|
13
13
|
- can create [multiple ‘pages’][newPage] on a given canvas and then [output][saveAs] them as a single, multi-page PDF or an image-sequence saved to multiple files
|
|
14
14
|
- can [simplify][p2d_simplify], [blunt][p2d_round], [combine][bool-ops], [excerpt][p2d_trim], and [atomize][p2d_points] bézier paths using [efficient](https://www.youtube.com/watch?v=OmfliNQsk88) boolean operations or point-by-point [interpolation][p2d_interpolate]
|
|
15
|
+
- can apply [3D perspective][createProjection()] transformations in addition to [scaling][scale()], [rotation][rotate()], and [translation][translate()]
|
|
15
16
|
- can fill shapes with vector-based [Textures][createTexture()] in addition to bitmap-based [Patterns][createPattern()] and supports line-drawing with custom [markers][lineDashMarker]
|
|
16
17
|
- fully supports the [CSS filter effects][filter] image processing operators
|
|
17
18
|
- offers rich typographic control including:
|
|
@@ -24,45 +25,6 @@ In particular, Skia Canvas:
|
|
|
24
25
|
- use of non-system fonts [loaded](#usefamilyname-fontpaths) from local files
|
|
25
26
|
|
|
26
27
|
|
|
27
|
-
### Basic Usage
|
|
28
|
-
```js
|
|
29
|
-
const {Canvas, loadImage} = require('skia-canvas'),
|
|
30
|
-
rand = n => Math.floor(n * Math.random());
|
|
31
|
-
|
|
32
|
-
let canvas = new Canvas(600, 600),
|
|
33
|
-
ctx = canvas.getContext("2d"),
|
|
34
|
-
{width, height} = canvas;
|
|
35
|
-
|
|
36
|
-
// draw a sea of blurred dots filling the canvas
|
|
37
|
-
ctx.filter = 'blur(12px) hue-rotate(20deg)'
|
|
38
|
-
for (let i=0; i<800; i++){
|
|
39
|
-
ctx.fillStyle = `hsl(${rand(40)}deg, 80%, 50%)`
|
|
40
|
-
ctx.beginPath()
|
|
41
|
-
ctx.arc(rand(width), rand(height), rand(20)+5, 0, 2*Math.PI)
|
|
42
|
-
ctx.fill()
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// mask all of the dots that don't overlap with the text
|
|
46
|
-
ctx.filter = 'none'
|
|
47
|
-
ctx.globalCompositeOperation = 'destination-in'
|
|
48
|
-
ctx.font='italic 480px Times, DejaVu Serif'
|
|
49
|
-
ctx.textAlign = 'center'
|
|
50
|
-
ctx.textBaseline = 'top'
|
|
51
|
-
ctx.fillText('¶', width/2, 0)
|
|
52
|
-
|
|
53
|
-
// draw a background behind the clipped text
|
|
54
|
-
ctx.globalCompositeOperation = 'destination-over'
|
|
55
|
-
ctx.fillStyle = '#182927'
|
|
56
|
-
ctx.fillRect(0,0, width,height)
|
|
57
|
-
|
|
58
|
-
// save the graphic...
|
|
59
|
-
canvas.saveAs("pilcrow.png")
|
|
60
|
-
// ...or use a shorthand for canvas.toBuffer("png")
|
|
61
|
-
fs.writeFileSync("pilcrow.png", canvas.png)
|
|
62
|
-
// ...or embed it in a string
|
|
63
|
-
console.log(`<img src="${canvas.toDataURL("png")}">`)
|
|
64
|
-
```
|
|
65
|
-
|
|
66
28
|
## Installation
|
|
67
29
|
|
|
68
30
|
If you’re running on a supported platform, installation should be as simple as:
|
|
@@ -72,13 +34,6 @@ $ npm install skia-canvas
|
|
|
72
34
|
|
|
73
35
|
This will download a pre-compiled library from the project’s most recent [release](https://github.com/samizdatco/skia-canvas/releases).
|
|
74
36
|
|
|
75
|
-
### Dependencies
|
|
76
|
-
|
|
77
|
-
Nearly everything you need is statically linked into the library.
|
|
78
|
-
|
|
79
|
-
A notable exception is the [Fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/) library (and its associated [FreeType](https://www.freetype.org) renderer) which must be installed separately if you’re running on Linux.
|
|
80
|
-
|
|
81
|
-
|
|
82
37
|
### Platform Support
|
|
83
38
|
|
|
84
39
|
The underlying Rust library uses [N-API](https://nodejs.org/api/n-api.html) v6 which allows it to run on Node.js versions:
|
|
@@ -88,13 +43,18 @@ The underlying Rust library uses [N-API](https://nodejs.org/api/n-api.html) v6 w
|
|
|
88
43
|
|
|
89
44
|
Pre-compiled binaries are available for:
|
|
90
45
|
|
|
91
|
-
- Linux (
|
|
92
|
-
- macOS (
|
|
93
|
-
- Windows (
|
|
46
|
+
- Linux (x64, arm64, & armhf)
|
|
47
|
+
- macOS (x64 & Apple silicon)
|
|
48
|
+
- Windows (x64)
|
|
49
|
+
|
|
50
|
+
Nearly everything you need is statically linked into the library. A notable exception is the [Fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/) library which must be installed separately if you’re running on Linux.
|
|
51
|
+
|
|
94
52
|
|
|
95
53
|
### Running in Docker
|
|
96
54
|
|
|
97
|
-
The library is compatible with Linux systems using glibc 2.24 or later
|
|
55
|
+
The library is compatible with Linux systems using [glibc](https://www.gnu.org/software/libc/) 2.24 or later as well as Alpine Linux (x64) and the [musl](https://musl.libc.org) C library it favors. In both cases, Fontconfig must be installed on the system for `skia-canvas` to operate correctly.
|
|
56
|
+
|
|
57
|
+
If you are setting up a [Dockerfile](https://nodejs.org/en/docs/guides/nodejs-docker-webapp/) that uses [`node`](https://hub.docker.com/_/node) as its basis, the simplest approach is to set your `FROM` image to one of the (Debian-derived) defaults like `node:16`, `node:14`, `node:12`, `node:buster`, `node:stretch`, or simply:
|
|
98
58
|
```dockerfile
|
|
99
59
|
FROM node
|
|
100
60
|
```
|
|
@@ -103,7 +63,14 @@ You can also use the ‘slim’ image if you manually install fontconfig:
|
|
|
103
63
|
|
|
104
64
|
```dockerfile
|
|
105
65
|
FROM node:slim
|
|
106
|
-
RUN apt-get update && apt-get install -y -q --no-install-recommends libfontconfig1
|
|
66
|
+
RUN apt-get update && apt-get install -y -q --no-install-recommends libfontconfig1
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
If you wish to use Alpine as the underlying distribution, you can start with something along the lines of:
|
|
70
|
+
|
|
71
|
+
```dockerfile
|
|
72
|
+
FROM node:alpine
|
|
73
|
+
RUN apk update && apk add fontconfig
|
|
107
74
|
```
|
|
108
75
|
|
|
109
76
|
### Compiling from Source
|
|
@@ -115,10 +82,57 @@ Start by installing:
|
|
|
115
82
|
1. The [Rust compiler](https://www.rust-lang.org/tools/install) and cargo package manager using [`rustup`](https://rust-lang.github.io/rustup/)
|
|
116
83
|
2. A C compiler toolchain like LLVM/Clang or MSVC
|
|
117
84
|
3. Python 2.7 (used by Skia's [build process](https://skia.org/docs/user/build/))
|
|
118
|
-
4. On Linux: Fontconfig
|
|
85
|
+
4. On Linux: Fontconfig and OpenSSL
|
|
119
86
|
|
|
120
87
|
[Detailed instructions](https://github.com/rust-skia/rust-skia#building) for setting up these dependencies on different operating systems can be found in the ‘Building’ section of the Rust Skia documentation. Once all the necessary compilers and libraries are present, running `npm run build` will give you a usable library (after a fairly lengthy compilation process).
|
|
121
88
|
|
|
89
|
+
## Example Usage
|
|
90
|
+
```js
|
|
91
|
+
const {Canvas, loadImage} = require('skia-canvas'),
|
|
92
|
+
rand = n => Math.floor(n * Math.random()),
|
|
93
|
+
fs = require('fs')
|
|
94
|
+
|
|
95
|
+
let canvas = new Canvas(600, 600),
|
|
96
|
+
ctx = canvas.getContext("2d"),
|
|
97
|
+
{width, height} = canvas;
|
|
98
|
+
|
|
99
|
+
// draw a sea of blurred dots filling the canvas
|
|
100
|
+
ctx.filter = 'blur(12px) hue-rotate(20deg)'
|
|
101
|
+
for (let i=0; i<800; i++){
|
|
102
|
+
ctx.fillStyle = `hsl(${rand(40)}deg, 80%, 50%)`
|
|
103
|
+
ctx.beginPath()
|
|
104
|
+
ctx.arc(rand(width), rand(height), rand(20)+5, 0, 2*Math.PI)
|
|
105
|
+
ctx.fill()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// mask all of the dots that don't overlap with the text
|
|
109
|
+
ctx.filter = 'none'
|
|
110
|
+
ctx.globalCompositeOperation = 'destination-in'
|
|
111
|
+
ctx.font='italic 480px Times, DejaVu Serif'
|
|
112
|
+
ctx.textAlign = 'center'
|
|
113
|
+
ctx.textBaseline = 'top'
|
|
114
|
+
ctx.fillText('¶', width/2, 0)
|
|
115
|
+
|
|
116
|
+
// draw a background behind the clipped text
|
|
117
|
+
ctx.globalCompositeOperation = 'destination-over'
|
|
118
|
+
ctx.fillStyle = '#182927'
|
|
119
|
+
ctx.fillRect(0,0, width,height)
|
|
120
|
+
|
|
121
|
+
// render to files using a background thread
|
|
122
|
+
async function render(){
|
|
123
|
+
// save the graphic...
|
|
124
|
+
await canvas.saveAs("pilcrow.png")
|
|
125
|
+
// ...or use a shorthand for canvas.toBuffer("png")
|
|
126
|
+
let pngData = await canvas.png
|
|
127
|
+
// ...or embed it in a string
|
|
128
|
+
console.log(`<img src="${await canvas.toDataURL("png")}">`)
|
|
129
|
+
}
|
|
130
|
+
render()
|
|
131
|
+
|
|
132
|
+
// ...or save the file synchronously from the main thread
|
|
133
|
+
canvas.saveAsSync("pilcrow.png")
|
|
134
|
+
```
|
|
135
|
+
|
|
122
136
|
|
|
123
137
|
|
|
124
138
|
# API Documentation
|
|
@@ -149,22 +163,22 @@ The Canvas object is a stand-in for the HTML `<canvas>` element. It defines imag
|
|
|
149
163
|
|
|
150
164
|
| Image Dimensions | Rendering Contexts | Output |
|
|
151
165
|
| -- | -- | -- |
|
|
152
|
-
| [**width**][canvas_width] | [**pages**][canvas_pages] ⚡ | [**async**][canvas_async] ⚡ |
|
|
166
|
+
| [**width**][canvas_width] | [**pages**][canvas_pages] ⚡ | ~~[**async**][canvas_async]~~ ⚡ |
|
|
153
167
|
| [**height**][canvas_height] | [getContext()][getContext] | [**pdf**, **png**, **svg**, **jpg**][shorthands] ⚡ |
|
|
154
|
-
| | [newPage()][newPage] ⚡ | [saveAs()][saveAs] ⚡ |
|
|
155
|
-
| | | [toBuffer()][toBuffer] ⚡ |
|
|
156
|
-
| | | [toDataURL()][
|
|
168
|
+
| | [newPage()][newPage] ⚡ | [saveAs()][saveAs] / [saveAsSync()][saveAs] ⚡ |
|
|
169
|
+
| | | [toBuffer()][toBuffer] / [toBufferSync()][toBuffer] ⚡ |
|
|
170
|
+
| | | [toDataURL()][toDataURL_ext] / [toDataURLSync()][toDataURL_ext] ⚡ |
|
|
157
171
|
|
|
158
172
|
[canvas_width]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/width
|
|
159
173
|
[canvas_height]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/height
|
|
160
174
|
[canvas_async]: #async
|
|
161
175
|
[canvas_pages]: #pages
|
|
162
176
|
[getContext]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
|
|
163
|
-
[saveAs]: #saveasfilename-page-format-density1-quality092-outlinefalse
|
|
164
|
-
[toBuffer]: #tobufferformat-page-density-quality-outline
|
|
177
|
+
[saveAs]: #saveasfilename-page-format-matte-density1-quality092-outlinefalse
|
|
178
|
+
[toBuffer]: #tobufferformat-page-matte-density-quality-outline
|
|
165
179
|
[newPage]: #newpagewidth-height
|
|
166
180
|
[toDataURL_mdn]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
|
|
167
|
-
[toDataURL_ext]: #todataurlformat-page-density-quality-outline
|
|
181
|
+
[toDataURL_ext]: #todataurlformat-page-matte-density-quality-outline
|
|
168
182
|
[shorthands]: #pdf-svg-jpg-and-png
|
|
169
183
|
|
|
170
184
|
#### Creating new `Canvas` objects
|
|
@@ -176,21 +190,24 @@ let defaultCanvas = new Canvas() // without arguments, defaults to 300 × 150 px
|
|
|
176
190
|
let squareCanvas = new Canvas(512, 512) // creates a 512 px square
|
|
177
191
|
```
|
|
178
192
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
#### `.async`
|
|
193
|
+
#### Saving graphics to files, buffers, and strings
|
|
182
194
|
|
|
183
|
-
When the canvas renders images and writes them to disk, it does so in a background thread so as not to block execution within your script. As a result you’ll generally want to deal with the canvas from within an `async` function and be sure to use the `await` keyword when accessing any of its output methods or shorthand properties:
|
|
195
|
+
When the canvas renders images and writes them to disk, it does so in a background thread so as not to block execution within your script. As a result you’ll generally want to deal with the canvas from within an `async` function and be sure to use the `await` keyword when accessing any of its output methods or shorthand properties (all of which return Promises):
|
|
184
196
|
- [`saveAs()`][saveAs]
|
|
185
197
|
- [`toBuffer()`][toBuffer]
|
|
186
198
|
- [`toDataURL()`][toDataURL_ext]
|
|
187
199
|
- [`.pdf`, `.svg`, `.jpg`, and `.png`][shorthands]
|
|
188
200
|
|
|
189
|
-
In cases where this is not the desired behavior, you can switch these methods into a synchronous mode for a particular canvas by setting its `async` property to `false`. For instance, both of the example functions below will generate PNG & PDF from the canvas, though the first will be more efficient (particularly for parallel contexts like request-handlers in an HTTP server or batch exports):
|
|
190
|
-
```js
|
|
191
201
|
|
|
202
|
+
In cases where this is not the desired behavior, you can use the synchronous equivalents for the primary export functions. They accept identical arguments to their async versions but block execution and return their values synchronously rather than wrapped in Promises. Also note that the [shorthand properties][shorthands] do not have synchronous versions:
|
|
203
|
+
- [`saveAsSync()`][saveAs]
|
|
204
|
+
- [`toBufferSync()`][toBuffer]
|
|
205
|
+
- [`toDataURLSync()`][toDataURL_ext]
|
|
206
|
+
|
|
207
|
+
For instance, both of the example functions below will generate PNG & PDF from the canvas, though the first will be more efficient (particularly for parallel contexts like request-handlers in an HTTP server or batch exports):
|
|
208
|
+
|
|
209
|
+
```js
|
|
192
210
|
let canvas = new Canvas()
|
|
193
|
-
console.log(canvas.async) // -> true by default
|
|
194
211
|
|
|
195
212
|
async function normal(){
|
|
196
213
|
let pngURL = await canvas.toDataURL("png")
|
|
@@ -198,14 +215,16 @@ async function normal(){
|
|
|
198
215
|
}
|
|
199
216
|
|
|
200
217
|
function synchronous(){
|
|
201
|
-
|
|
202
|
-
let
|
|
203
|
-
let pdfBuffer = canvas.pdf
|
|
218
|
+
let pngURL = canvas.toDataURLSync("png")
|
|
219
|
+
let pdfBuffer = canvas.toBufferSync("pdf")
|
|
204
220
|
}
|
|
205
221
|
```
|
|
206
222
|
|
|
223
|
+
##### PROPERTIES
|
|
207
224
|
|
|
225
|
+
#### ~~`.async`~~
|
|
208
226
|
|
|
227
|
+
**The async property has been deprecated** and will be removed in a future release. Use the [`saveAsSync()`][saveAs], [`toBufferSync()`][toBuffer], and [`toDataURLSync()`][toDataURL_ext] methods if the default, asynchronous versions aren't to your liking.
|
|
209
228
|
|
|
210
229
|
#### `.pages`
|
|
211
230
|
|
|
@@ -234,6 +253,10 @@ An integer can optionally be placed between the braces to indicate the number of
|
|
|
234
253
|
##### page
|
|
235
254
|
The optional `page` argument accepts an integer that allows for the individual selection of pages in a multi-page canvas. Note that page indexing starts with page 1 **not** 0. The page value can also be negative, counting from the end of the canvas’s `.pages` array. For instance, `.saveAs("currentPage.png", {page:-1})` is equivalent to omitting `page` since they both yield the canvas’s most recently added page.
|
|
236
255
|
|
|
256
|
+
##### format
|
|
257
|
+
|
|
258
|
+
The image format to generate, specified either as a mime-type string or file extension. The `format` argument will take precedence over the type specified through the `filename` argument’s extension, but is primarily useful when generating a file whose name cannot end with an extension for other reasons.
|
|
259
|
+
|
|
237
260
|
##### matte
|
|
238
261
|
The optional `matte` argument accepts a color-string specifying the background that should be drawn *behind* the canvas in the exported image. Any transparent portions of the image will be filled with the matte color.
|
|
239
262
|
|
|
@@ -251,11 +274,11 @@ The `quality` option is a number between 0 and 1.0 that controls the level of JP
|
|
|
251
274
|
##### outline
|
|
252
275
|
When generating SVG output containing text, you have two options for how to handle the fonts that were used. By default, SVG files will contain `<text>` elements that refer to the fonts by name in the embedded stylesheet. This requires that viewers of the SVG have the same fonts available on their system (or accessible as webfonts). Setting the optional `outline` argument to `true` will trace all the letterforms and ‘burn’ them into the file as bézier paths. This will result in a much larger file (and one in which the original text strings will be unrecoverable), but it will be viewable regardless of the specifics of the system it’s displayed on.
|
|
253
276
|
|
|
254
|
-
#### `toBuffer(format, {page, density, quality, outline})`
|
|
277
|
+
#### `toBuffer(format, {page, matte, density, quality, outline})`
|
|
255
278
|
|
|
256
279
|
Node [`Buffer`][Buffer] objects containing various image formats can be created by passing either a format string like `"svg"` or a mime-type like `"image/svg+xml"`. An ‘@’ suffix can be added to the format string to specify a pixel-density (for instance, `"jpg@2x"`). The optional arguments behave the same as in the `saveAs` method.
|
|
257
280
|
|
|
258
|
-
#### `toDataURL(format, {page, density, quality, outline})`
|
|
281
|
+
#### `toDataURL(format, {page, matte, density, quality, outline})`
|
|
259
282
|
|
|
260
283
|
This method accepts the same arguments and behaves similarly to `.toBuffer`. However instead of returning a Buffer, it returns a string of the form `"data:<mime-type>;base64,<image-data>"` which can be used as a `src` attribute in `<img>` tags, embedded into CSS, etc.
|
|
261
284
|
|
|
@@ -265,17 +288,32 @@ This method accepts the same arguments and behaves similarly to `.toBuffer`. How
|
|
|
265
288
|
Most of your interaction with the canvas will actually be directed toward its ‘rendering context’, a supporting object you can acquire by calling the canvas’s [getContext()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext) and [newPage()][newPage] methods.
|
|
266
289
|
|
|
267
290
|
|
|
268
|
-
| Canvas State | Drawing | Pattern & Color | Line Style | Transform
|
|
269
|
-
|
|
270
|
-
| [**canvas**][canvas_attr] ⧸[⚡](#canvas) | [clearRect()][clearRect()] | [**fillStyle**][fillStyle] | [**lineCap**][lineCap] | [**currentTransform**][currentTransform]
|
|
271
|
-
| [beginPath()][beginPath()] | [fillRect()][fillRect()] | [**strokeStyle**][strokeStyle] | [**lineDashFit** ⚡][lineDashFit] | [
|
|
272
|
-
| [isPointInPath()][isPointInPath()] | [strokeRect()][strokeRect()] | [createConicGradient()][createConicGradient()] | [**lineDashMarker** ⚡][lineDashMarker] | [
|
|
273
|
-
| [isPointInStroke()][isPointInStroke()] | [fillText()][fillText()] ⧸[⚡][drawText] | [createLinearGradient()][createLinearGradient()] | [**lineDashOffset**][lineDashOffset] | [
|
|
274
|
-
| [save()][save()] | [strokeText()][strokeText()] ⧸[⚡][drawText] | [createRadialGradient()][createRadialGradient()] | [**lineJoin**][lineJoin] | [
|
|
275
|
-
| [restore()][restore()] | [fill()][fill()] | [createPattern()][createPattern()] | [**lineWidth**][lineWidth] | [
|
|
276
|
-
| [clip()][clip()] | [stroke()][stroke()] | [createTexture() ⚡][createTexture()] | [**miterLimit**][miterLimit] | [
|
|
277
|
-
| | | | [getLineDash()][getLineDash()] | [
|
|
278
|
-
| | | | [setLineDash()][setLineDash()] |
|
|
291
|
+
| Canvas State | Drawing | Pattern & Color | Line Style | Transform |
|
|
292
|
+
|------------------------------------------|----------------------------------------------|---------------------------------------------------|-----------------------------------------|---------------------------------------------|
|
|
293
|
+
| [**canvas**][canvas_attr] ⧸[⚡](#canvas) | [clearRect()][clearRect()] | [**fillStyle**][fillStyle] | [**lineCap**][lineCap] | [**currentTransform**][currentTransform] |
|
|
294
|
+
| [beginPath()][beginPath()] | [fillRect()][fillRect()] | [**strokeStyle**][strokeStyle] | [**lineDashFit** ⚡][lineDashFit] | [createProjection() ⚡][createProjection()] |
|
|
295
|
+
| [isPointInPath()][isPointInPath()] | [strokeRect()][strokeRect()] | [createConicGradient()][createConicGradient()] | [**lineDashMarker** ⚡][lineDashMarker] | [getTransform()][getTransform()] |
|
|
296
|
+
| [isPointInStroke()][isPointInStroke()] | [fillText()][fillText()] ⧸[⚡][drawText] | [createLinearGradient()][createLinearGradient()] | [**lineDashOffset**][lineDashOffset] | [setTransform()][setTransform()] |
|
|
297
|
+
| [save()][save()] | [strokeText()][strokeText()] ⧸[⚡][drawText] | [createRadialGradient()][createRadialGradient()] | [**lineJoin**][lineJoin] | [resetTransform()][resetTransform()] |
|
|
298
|
+
| [restore()][restore()] | [fill()][fill()] | [createPattern()][createPattern()] | [**lineWidth**][lineWidth] | [transform()][transform()] |
|
|
299
|
+
| [clip()][clip()] | [stroke()][stroke()] | [createTexture() ⚡][createTexture()] | [**miterLimit**][miterLimit] | [translate()][translate()] |
|
|
300
|
+
| | | | [getLineDash()][getLineDash()] | [rotate()][rotate()] |
|
|
301
|
+
| | | | [setLineDash()][setLineDash()] | [scale()][scale()] |
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
279
317
|
|
|
280
318
|
|
|
281
319
|
| Bezier Paths | Typography | Images | Compositing Effects |
|
|
@@ -375,11 +413,76 @@ The `lineDashFit` attribute can be set to `"move"`, `"turn"`, or `"follow"` and
|
|
|
375
413
|
|
|
376
414
|
Adds a line segment connecting the current point to (*x, y*) but curving toward the control point (*cpx, cpy*) along the way. The `weight` argument controls how close the curve will come to the control point. If the weight is `0`, the result will be a straight line from the current point to (*x, y*). With a weight of `1.0`, the function is equivalent to calling `quadraticCurveTo()`. Weights greater than `1.0` will pull the line segment ever closer to the control point.
|
|
377
415
|
|
|
416
|
+
#### `createProjection(quad, [basis])`
|
|
417
|
+
|
|
418
|
+
This method returns a [DOMMatrix][DOMMatrix] object which can be used to simulate perspective effects or other distortions in which the four corners of the canvas are mapped to an arbitrary quadrilateral (four sided polygon). The matrix must be passed to the context's [setTransform][setTransform()] method for it take effect.
|
|
419
|
+
|
|
420
|
+
##### `quad`
|
|
421
|
+
|
|
422
|
+
The `quad` argument defines the **target** of the transformation. It specifies four points that establish where the four corners of the source coordinate space will be positioned within the viewport. If these points form a polygon other than a rectangle, lines drawn along the x & y axes of the source space will no longer be perpendicular—trapezoids allow for ‘vanishing point’ effects and parallelograms create ‘skew’.
|
|
423
|
+
|
|
424
|
+
The geometry of the quadrilateral should be described as an Array of either 8 or 4 numbers specifying an arbitrary polygon or rectangle respectively:
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
[x1, y1, x2, y2, x3, y3, x4, y4] // four corner points
|
|
428
|
+
[left, top, right, bottom] // four edges of a rectangle
|
|
429
|
+
|
|
430
|
+
// internal arrays for grouping are also allowed
|
|
431
|
+
[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
##### `basis`
|
|
435
|
+
|
|
436
|
+
The optional `basis` argument defines the **source** quadrilateral whose corners will be mapped to the positions defined by `quad`. If no `basis` is specified, the canvas's bounding box will be used (i.e., the rectangle from ⟨`0`, `0`⟩ to ⟨`canvas.width`, `canvas.height`⟩). Note that drawing commands that go outside of the `basis` region may well be visible—it only establishes the geometry of the projection, not the [clipping][clip()] path.
|
|
437
|
+
|
|
438
|
+
The `basis` polygon can be described using 2, 4, or 8 numbers, using the canvas dimensions to fill in the unspecified coordinates:
|
|
439
|
+
```js
|
|
440
|
+
[width, height] // rectangle from ⟨0, 0⟩ to ⟨width, height⟩
|
|
441
|
+
[left, top, right, bottom] // four edges of a rectangle
|
|
442
|
+
[x1, y1, x2, y2, x3, y3, x4, y4] // four corner points
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
----
|
|
446
|
+
|
|
447
|
+
The projection matrix will apply to all types of drawing: shapes, images, and text. This example transforms a white box and red `"@"` character into a trapezoid bounded by the vertical midline of the canvas and its left and right edges. Since no `basis` argument is provided, it will default to using the current canvas bounds as the rectangle to be mapped onto that trapezoid.
|
|
448
|
+
|
|
449
|
+
```js
|
|
450
|
+
let canvas = new Canvas(512, 512),
|
|
451
|
+
ctx = canvas.getContext("2d"),
|
|
452
|
+
{width:w, height:h} = canvas;
|
|
453
|
+
ctx.font = '900 480px Times'
|
|
454
|
+
ctx.textAlign = 'center'
|
|
455
|
+
ctx.fillStyle = '#aaa'
|
|
456
|
+
ctx.fillRect(0, 0, w, h)
|
|
457
|
+
|
|
458
|
+
let quad = [
|
|
459
|
+
w*.33, h/2, // upper left
|
|
460
|
+
w*.66, h/2, // upper right
|
|
461
|
+
w, h*.9, // bottom right
|
|
462
|
+
0, h*.9, // bottom left
|
|
463
|
+
]
|
|
464
|
+
|
|
465
|
+
let matrix = ctx.createProjection(quad) // use default basis
|
|
466
|
+
ctx.setTransform(matrix)
|
|
467
|
+
|
|
468
|
+
ctx.fillStyle = 'white'
|
|
469
|
+
ctx.fillRect(10, 10, w-20, h-20)
|
|
470
|
+
|
|
471
|
+
ctx.fillStyle = '#900'
|
|
472
|
+
ctx.fillText("@", w/2, h-40)
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
The results below show the image generated when the `createProjection()` call is omitted entirely, called (as above) with just a `quad` argument, or called with two different values for the optional `basis` argument:
|
|
477
|
+
|
|
478
|
+

|
|
479
|
+
|
|
480
|
+
|
|
378
481
|
#### `createTexture(spacing, {path, line, color, angle, offset=0})`
|
|
379
482
|
|
|
380
483
|
The `createTexture()` method returns a `CanvasTexture` object that can be assigned to the context’s `strokeStyle` or `fillStyle` property. Similar to a `CanvasPattern`, a `CanvasTexture` defines a repeating pattern that will be drawn instead of a flat color, but textures define their content using *vectors* rather than bitmaps.
|
|
381
484
|
|
|
382
|
-
Textures can be based on a user-provided Path2D object or will draw a stripe pattern of parallel lines if a path isn’t provided.
|
|
485
|
+
Textures can be based on a user-provided Path2D object or will draw a stripe pattern of parallel lines if a path isn’t provided.
|
|
383
486
|
|
|
384
487
|
##### `spacing`
|
|
385
488
|
|
|
@@ -816,6 +919,7 @@ Many thanks to the [`node-canvas`](https://github.com/Automattic/node-canvas) de
|
|
|
816
919
|
[conicCurveTo]: #coniccurvetocpx-cpy-x-y-weight
|
|
817
920
|
[outlineText()]: #outlinetextstr
|
|
818
921
|
[createTexture()]: #createtexturespacing-path-line-color-angle-offset0
|
|
922
|
+
[createProjection()]: #createprojectionquad-basis
|
|
819
923
|
[lineDashMarker]: #linedashmarker
|
|
820
924
|
[lineDashFit]: #linedashfit
|
|
821
925
|
|