lecodes-web-canvas 2.0.2 → 2.0.3

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/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "lecodes-web-canvas",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "The tree UI of LeCodes' web renderers: the runtime's HostUI in TypeScript (TreeUI) + the render tree, painted to a 2D canvas — in the browser (web/renderer) or headless (lecodes-headless)",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "main": "src/runtime/TreeUI.ts",
8
8
  "dependencies": {
9
- "lecodes-sdk": "2.0.2",
10
- "lecodes-web-runtime": "2.0.2",
11
- "lecodes-web-shared": "2.0.2"
9
+ "lecodes-sdk": "2.0.3",
10
+ "lecodes-web-runtime": "2.0.3",
11
+ "lecodes-web-shared": "2.0.3"
12
12
  },
13
13
  "devDependencies": {
14
14
  "typescript": "~5.8.3",
@@ -212,14 +212,15 @@ export class Canvas2DPainter implements Painter {
212
212
  drawImage(image: ImageInfo, srcRect: Rect | null, dst: Rect, opts: DrawImageOpts) {
213
213
  if (!image.handle) return
214
214
  // An explicit crop fills the box; otherwise resolve object-fit.
215
- const { src, dst: d } = srcRect
215
+ const fit = srcRect
216
216
  ? { src: srcRect, dst }
217
217
  : computeObjectFit(image.naturalWidth, image.naturalHeight, dst, opts.fit)
218
+ const d = fit.dst
219
+ let src = fit.src
218
220
  // The destination in DEVICE pixels: what a vector source rasterizes at, and the tint scratch's
219
221
  // size — the frame is painted under the dpr transform, so a CSS-px scratch would be upscaled.
220
222
  const dw = Math.max(1, Math.ceil(d.width * this.dpr))
221
223
  const dh = Math.max(1, Math.ceil(d.height * this.dpr))
222
- const handle = (image.rasterize ? image.rasterize(dw, dh) : image.handle) as CanvasImageSource
223
224
 
224
225
  // When we're drawing the WHOLE image (no atlas crop, not a cover-crop) draw it WITHOUT a source
225
226
  // rect. A viewBox-only SVG `<img>` has the browser's default 300×150 raster, so a source crop
@@ -228,6 +229,21 @@ export class Canvas2DPainter implements Painter {
228
229
  // and keeps the working tinted/scratch path consistent with the direct path).
229
230
  const whole = !srcRect && opts.fit !== "cover"
230
231
 
232
+ let handle = image.handle as CanvasImageSource
233
+ if (image.rasterize) {
234
+ if (whole) handle = image.rasterize(dw, dh) as CanvasImageSource
235
+ else {
236
+ // A crop is in the source's NATURAL units: the vector is rasterized whole at the scale the
237
+ // crop is drawn at, and the crop is taken in that raster's pixels.
238
+ const k = Math.max(dw / src.width, dh / src.height)
239
+ const rw = Math.max(1, Math.ceil(image.naturalWidth * k))
240
+ const rh = Math.max(1, Math.ceil(image.naturalHeight * k))
241
+ handle = image.rasterize(rw, rh) as CanvasImageSource
242
+ const kx = rw / image.naturalWidth, ky = rh / image.naturalHeight
243
+ src = { x: src.x * kx, y: src.y * ky, width: src.width * kx, height: src.height * ky }
244
+ }
245
+ }
246
+
231
247
  if (opts.tint === undefined) {
232
248
  if (whole) this.ctx.drawImage(handle, d.x, d.y, d.width, d.height)
233
249
  else this.ctx.drawImage(handle, src.x, src.y, src.width, src.height, d.x, d.y, d.width, d.height)