@gjsify/canvas2d-core 0.21.0 → 0.23.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.
- package/lib/esm/canvas-pattern.js +1 -1
- package/lib/esm/context/drawing.js +1 -1
- package/lib/esm/context/pixels.js +1 -1
- package/lib/esm/gdk-pixel-bridge.js +1 -0
- package/lib/esm/pixel-bridge.js +1 -0
- package/lib/types/dom-types.d.ts +9 -3
- package/lib/types/gdk-pixel-bridge.d.ts +3 -0
- package/lib/types/pixel-bridge.d.ts +62 -0
- package/lib/types/pixel-bridge.spec.d.ts +2 -0
- package/package.json +11 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{asCairoPattern as e}from"./cairo-types.js";import{isCanvasImageSource as t,isPixbufImageSource as n}from"./dom-types.js";import r
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{asCairoPattern as e}from"./cairo-types.js";import{isCanvasImageSource as t,isPixbufImageSource as n}from"./dom-types.js";import{getCanvasPixelBridge as r}from"./pixel-bridge.js";import i from"cairo";var a=class CanvasPattern{constructor(t,n){let r=e(new i.SurfacePattern(t));if(!r)throw TypeError(`CanvasPattern: cairo SurfacePattern is missing setExtend at runtime — incompatible Cairo binding`);switch(this._pattern=r,n){case`repeat`:case``:case null:r.setExtend(i.Extend.REPEAT);break;case`repeat-x`:case`repeat-y`:r.setExtend(i.Extend.REPEAT);break;case`no-repeat`:r.setExtend(i.Extend.NONE);break}}static create(e,a){if(n(e)){let t=e._pixbuf,n=t.get_width(),o=t.get_height(),s=new i.ImageSurface(i.Format.ARGB32,n,o),c=new i.Context(s);return r().setSourceImage(c,t,0,0),c.paint(),c.$dispose(),new CanvasPattern(s,a)}if(t(e)){let t=e.getContext(`2d`);if(t&&typeof t._getSurface==`function`){let e=t._getSurface(),n=e.getWidth(),r=e.getHeight(),o=new i.ImageSurface(i.Format.ARGB32,n,r),s=new i.Context(o);return s.setSourceSurface(e,0,0),s.paint(),s.$dispose(),new CanvasPattern(o,a)}}return null}_getCairoPattern(){return this._pattern}};export{a as CanvasPattern};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{asCairoPattern as e}from"../cairo-types.js";import{Path2D as t}from"../canvas-path.js";import{isCanvasImageSource as n,isPixbufImageSource as r}from"../dom-types.js";import i
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{asCairoPattern as e}from"../cairo-types.js";import{Path2D as t}from"../canvas-path.js";import{isCanvasImageSource as n,isPixbufImageSource as r}from"../dom-types.js";import{getCanvasPixelBridge as i}from"../pixel-bridge.js";import a from"cairo";function getDrawImageSource(e){if(r(e)){let t=e._pixbuf;return{pixbuf:t,imgWidth:t.get_width(),imgHeight:t.get_height()}}if(n(e)){let t=e.width??0,n=e.height??0;if(!Number.isFinite(t)||!Number.isFinite(n)||t<=0||n<=0)return null;let r=e.getContext(`2d`);if(r&&typeof r._getSurface==`function`){let e=r._getSurface();e.flush();let a=i().imageFromSurface(e,0,0,t,n);if(a)return{pixbuf:a,imgWidth:t,imgHeight:n}}}return null}const o={fill(e,n){this._ensureSurface(),this._applyCompositing(),this._applyFillStyle();let r;e instanceof t?(this._ctx.newPath(),e._replayOnCairo(this._ctx),r=n):r=e,this._ctx.setFillRule(r===`evenodd`?a.FillRule.EVEN_ODD:a.FillRule.WINDING),this._ctx.fillPreserve()},stroke(e){this._ensureSurface(),this._applyCompositing(),this._applyStrokeStyle(),this._applyLineStyle(),e instanceof t&&(this._ctx.newPath(),e._replayOnCairo(this._ctx)),this._ctx.strokePreserve()},fillRect(e,t,n,r){this._ensureSurface(),this._applyCompositing();let i=this._ctx.copyPath();this._hasShadow()&&this._renderShadow(()=>{this._ctx.newPath(),this._ctx.rectangle(e,t,n,r),this._ctx.fill()}),this._applyFillStyle(),this._ctx.newPath(),this._ctx.rectangle(e,t,n,r),this._ctx.fill(),this._ctx.newPath(),this._ctx.appendPath(i)},strokeRect(e,t,n,r){this._ensureSurface(),this._applyCompositing();let i=this._ctx.copyPath();this._hasShadow()&&this._renderShadow(()=>{this._ctx.newPath(),this._ctx.rectangle(e,t,n,r),this._ctx.stroke()}),this._applyStrokeStyle(),this._applyLineStyle(),this._ctx.newPath(),this._ctx.rectangle(e,t,n,r),this._ctx.stroke(),this._ctx.newPath(),this._ctx.appendPath(i)},clearRect(e,t,n,r){this._ensureSurface();let i=this._ctx.copyPath();this._ctx.save(),this._ctx.setOperator(a.Operator.CLEAR),this._ctx.newPath(),this._ctx.rectangle(e,t,n,r),this._ctx.fill(),this._ctx.restore(),this._ctx.newPath(),this._ctx.appendPath(i)},clip(e,n){this._ensureSurface();let r;e instanceof t?(this._ctx.newPath(),e._replayOnCairo(this._ctx),r=n):r=e,this._ctx.setFillRule(r===`evenodd`?a.FillRule.EVEN_ODD:a.FillRule.WINDING),this._ctx.clip()},isPointInPath(e,n,r,i){this._ensureSurface();let o,s,c;return e instanceof t?(this._ctx.newPath(),e._replayOnCairo(this._ctx),o=n,s=r,c=i):(o=e,s=n,c=r),this._ctx.setFillRule(c===`evenodd`?a.FillRule.EVEN_ODD:a.FillRule.WINDING),this._ctx.inFill(o,s)},isPointInStroke(e,n,r){return this._ensureSurface(),this._applyLineStyle(),e instanceof t?(this._ctx.newPath(),e._replayOnCairo(this._ctx),this._ctx.inStroke(n,r)):this._ctx.inStroke(e,n)},drawImage(t,n,r,o,s,c,l,u,d){this._ensureSurface(),this._applyCompositing();let f,p,m,h,g,_,v,y,b=getDrawImageSource(t);if(!b)return;let{pixbuf:x,imgWidth:S,imgHeight:C}=b;if(o===void 0?(f=0,p=0,m=S,h=C,g=n,_=r,v=S,y=C):c===void 0?(f=0,p=0,m=S,h=C,g=n,_=r,v=o,y=s):(f=n,p=r,m=o,h=s,g=c,_=l,v=u,y=d),!Number.isFinite(f)||!Number.isFinite(p)||!Number.isFinite(m)||!Number.isFinite(h)||!Number.isFinite(g)||!Number.isFinite(_)||!Number.isFinite(v)||!Number.isFinite(y)||m===0||h===0||v===0||y===0)return;this._ctx.save(),this._ctx.rectangle(g,_,v,y),this._ctx.clip(),this._ctx.translate(g,_),this._ctx.scale(v/m,y/h),this._ctx.translate(-f,-p),i().setSourceImage(this._ctx,x,0,0);let w=e(this._ctx.getSource?.());if(w){let e;e=this._state.imageSmoothingEnabled?this._state.imageSmoothingQuality===`high`?a.Filter.BEST:a.Filter.BILINEAR:a.Filter.NEAREST,w.setFilter(e)}this._state.globalAlpha<1?this._ctx.paintWithAlpha(this._state.globalAlpha):this._ctx.paint(),this._ctx.restore()}};function installDrawingMethods(e){Object.assign(e,o)}export{installDrawingMethods};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{getCanvasPixelBridge as e}from"../pixel-bridge.js";import{OurImageData as t}from"../image-data.js";import n from"cairo";const r={createImageData(e,n){return typeof e==`number`?new t(Math.abs(e),Math.abs(n)):new t(e.width,e.height)},getImageData(n,r,i,a){this._ensureSurface(),this._surface.flush();let o=e().imageFromSurface(this._surface,n,r,i,a);if(!o)return new t(i,a);let s=o.get_pixels(),c=o.get_has_alpha(),l=o.get_rowstride(),u=o.get_n_channels(),d=new Uint8ClampedArray(i*a*4);for(let e=0;e<a;e++)for(let t=0;t<i;t++){let n=e*l+t*u,r=(e*i+t)*4;d[r]=s[n],d[r+1]=s[n+1],d[r+2]=s[n+2],d[r+3]=c?s[n+3]:255}return new t(d,i,a)},putImageData(t,r,i,a,o,s,c){this._ensureSurface();let l=a??0,u=o??0,d=s??t.width,f=c??t.height,p=t.data,m=t.width,h=new Uint8Array(d*f*4);for(let e=0;e<f;e++)for(let t=0;t<d;t++){let n=((u+e)*m+(l+t))*4,r=(e*d+t)*4;h[r]=p[n],h[r+1]=p[n+1],h[r+2]=p[n+2],h[r+3]=p[n+3]}this._ctx.save(),this._ctx.setOperator(n.Operator.SOURCE),e().setSourcePixels(this._ctx,h,d,f,r+l,i+u),this._ctx.rectangle(r+l,i+u,d,f),this._ctx.fill(),this._ctx.restore()}};function installPixelMethods(e){Object.assign(e,r)}export{installPixelMethods};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{setCanvasPixelBridge as e}from"./pixel-bridge.js";import t from"gi://Gdk?version=4.0";import n from"gi://GdkPixbuf";const r={imageFromSurface(e,n,r,i,a){return t.pixbuf_get_from_surface(e,n,r,i,a)},setSourceImage(e,n,r,i){t.cairo_set_source_pixbuf(e,n,r,i)},setSourcePixels(e,r,i,a,o,s){let c=n.Pixbuf.new_from_bytes(r,n.Colorspace.RGB,!0,8,i,a,i*4);t.cairo_set_source_pixbuf(e,c,o,s)}};e(r);export{r as gdkPixelBridge};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";let e=null;function setCanvasPixelBridge(t){e=t}function hasCanvasPixelBridge(){return e!==null}function getCanvasPixelBridge(){if(!e)throw TypeError(`@gjsify/canvas2d-core: no pixel bridge registered — pixel operations (getImageData / putImageData / drawImage / createPattern) need a platform backend. On GJS, import '@gjsify/canvas2d-core/gdk' (or use '@gjsify/dom-elements' / '@gjsify/canvas2d', which register it for you).`);return e}export{getCanvasPixelBridge,hasCanvasPixelBridge,setCanvasPixelBridge};
|
package/lib/types/dom-types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type Cairo from 'cairo';
|
|
2
|
-
import type
|
|
2
|
+
import type { CanvasImageHandle } from './pixel-bridge.js';
|
|
3
3
|
/**
|
|
4
4
|
* The HTMLCanvasElement-shaped object passed into the
|
|
5
5
|
* `CanvasRenderingContext2D` constructor by the registered context factory.
|
|
@@ -21,8 +21,14 @@ export interface CanvasLike {
|
|
|
21
21
|
*/
|
|
22
22
|
export interface PixbufImageSource {
|
|
23
23
|
isPixbuf(): boolean;
|
|
24
|
-
/**
|
|
25
|
-
|
|
24
|
+
/**
|
|
25
|
+
* @internal — populated by HTMLImageElement once decoding completes.
|
|
26
|
+
*
|
|
27
|
+
* Typed as the platform-agnostic {@link CanvasImageHandle} (the readable
|
|
28
|
+
* slice of `GdkPixbuf.Pixbuf`) so the headless core needs no `gi://`
|
|
29
|
+
* import; a real `GdkPixbuf.Pixbuf` satisfies it structurally.
|
|
30
|
+
*/
|
|
31
|
+
_pixbuf: CanvasImageHandle;
|
|
26
32
|
}
|
|
27
33
|
/**
|
|
28
34
|
* Canvas-like image source carrying a 2D context whose backing surface can be
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type Cairo from 'cairo';
|
|
2
|
+
/**
|
|
3
|
+
* A decoded, readable platform image.
|
|
4
|
+
*
|
|
5
|
+
* Structurally the slice of `GdkPixbuf.Pixbuf` the core consumes — declared
|
|
6
|
+
* here rather than imported from `gi://GdkPixbuf` so the core carries no GI
|
|
7
|
+
* value *or* type dependency. Both the pixbufs produced by
|
|
8
|
+
* `@gjsify/dom-elements`' `HTMLImageElement` and the ones a
|
|
9
|
+
* {@link CanvasPixelBridge} reads back out of a Cairo surface satisfy it.
|
|
10
|
+
*/
|
|
11
|
+
export interface CanvasImageHandle {
|
|
12
|
+
get_width(): number;
|
|
13
|
+
get_height(): number;
|
|
14
|
+
get_pixels(): Uint8Array;
|
|
15
|
+
get_rowstride(): number;
|
|
16
|
+
get_n_channels(): number;
|
|
17
|
+
get_has_alpha(): boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The Cairo ⇄ pixel-buffer interop the headless core cannot implement itself.
|
|
21
|
+
*
|
|
22
|
+
* Implementations are platform code (today: GDK). Register one with
|
|
23
|
+
* {@link setCanvasPixelBridge}; every method is expected to behave exactly
|
|
24
|
+
* like the GDK original it mirrors.
|
|
25
|
+
*/
|
|
26
|
+
export interface CanvasPixelBridge {
|
|
27
|
+
/**
|
|
28
|
+
* Read a rectangular region of a Cairo surface into a readable image
|
|
29
|
+
* handle, un-premultiplying alpha (mirrors `Gdk.pixbuf_get_from_surface`).
|
|
30
|
+
*
|
|
31
|
+
* Returns `null` when the region cannot be read (out of bounds, an
|
|
32
|
+
* unsupported surface format, or a zero-sized rectangle).
|
|
33
|
+
*/
|
|
34
|
+
imageFromSurface(surface: Cairo.Surface, srcX: number, srcY: number, width: number, height: number): CanvasImageHandle | null;
|
|
35
|
+
/**
|
|
36
|
+
* Install a decoded image as the Cairo context's source pattern, with the
|
|
37
|
+
* image's top-left corner at (`x`, `y`) in user space (mirrors
|
|
38
|
+
* `Gdk.cairo_set_source_pixbuf`).
|
|
39
|
+
*/
|
|
40
|
+
setSourceImage(cr: Cairo.Context, image: CanvasImageHandle, x: number, y: number): void;
|
|
41
|
+
/**
|
|
42
|
+
* Install raw, NON-premultiplied RGBA bytes (8 bits per channel, tightly
|
|
43
|
+
* packed at `width * 4` bytes per row) as the Cairo context's source
|
|
44
|
+
* pattern, with the buffer's top-left corner at (`x`, `y`) in user space.
|
|
45
|
+
*/
|
|
46
|
+
setSourcePixels(cr: Cairo.Context, rgba: Uint8Array, width: number, height: number, x: number, y: number): void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Register the platform pixel bridge. Last registration wins, so an embedder
|
|
50
|
+
* can substitute its own implementation (e.g. a test double).
|
|
51
|
+
*/
|
|
52
|
+
export declare function setCanvasPixelBridge(implementation: CanvasPixelBridge): void;
|
|
53
|
+
/** Whether a pixel bridge has been registered. */
|
|
54
|
+
export declare function hasCanvasPixelBridge(): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* The registered pixel bridge.
|
|
57
|
+
*
|
|
58
|
+
* Throws — rather than silently degrading to blank pixels — when nothing has
|
|
59
|
+
* been registered, because the caller asked for a pixel operation that cannot
|
|
60
|
+
* be answered correctly without one.
|
|
61
|
+
*/
|
|
62
|
+
export declare function getCanvasPixelBridge(): CanvasPixelBridge;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/canvas2d-core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Cairo-backed Canvas 2D core (CanvasRenderingContext2D, Path2D, ImageData) — no GTK dependency",
|
|
3
|
+
"version": "0.23.0",
|
|
4
|
+
"description": "Cairo-backed Canvas 2D core (CanvasRenderingContext2D, Path2D, ImageData) — headless root entry, no GTK dependency",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
"types": "./lib/types/index.d.ts",
|
|
11
11
|
"default": "./lib/esm/index.js"
|
|
12
12
|
},
|
|
13
|
+
"./gdk": {
|
|
14
|
+
"types": "./lib/types/gdk-pixel-bridge.d.ts",
|
|
15
|
+
"default": "./lib/esm/gdk-pixel-bridge.js"
|
|
16
|
+
},
|
|
13
17
|
"./globals": "./globals.mjs"
|
|
14
18
|
},
|
|
15
19
|
"files": [
|
|
@@ -17,6 +21,8 @@
|
|
|
17
21
|
"globals.mjs"
|
|
18
22
|
],
|
|
19
23
|
"sideEffects": [
|
|
24
|
+
"./src/gdk-pixel-bridge.ts",
|
|
25
|
+
"./lib/esm/gdk-pixel-bridge.js",
|
|
20
26
|
"./globals.mjs"
|
|
21
27
|
],
|
|
22
28
|
"scripts": {
|
|
@@ -48,9 +54,9 @@
|
|
|
48
54
|
"@girs/pangocairo-1.0": "^4.1.0"
|
|
49
55
|
},
|
|
50
56
|
"devDependencies": {
|
|
51
|
-
"@gjsify/cli": "^0.
|
|
52
|
-
"@gjsify/dom-elements": "^0.
|
|
53
|
-
"@gjsify/unit": "^0.
|
|
57
|
+
"@gjsify/cli": "^0.23.0",
|
|
58
|
+
"@gjsify/dom-elements": "^0.23.0",
|
|
59
|
+
"@gjsify/unit": "^0.23.0",
|
|
54
60
|
"@types/node": "^25.9.2",
|
|
55
61
|
"typescript": "^6.0.3"
|
|
56
62
|
},
|