@gjsify/canvas2d 0.3.21 → 0.4.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/lib/esm/_virtual/_rolldown/runtime.js +1 -0
- package/lib/esm/cairo-utils.js +1 -1
- package/lib/esm/canvas-state.js +1 -1
- package/lib/esm/canvas2d-bridge.js +1 -1
- package/lib/esm/color.js +1 -1
- package/lib/esm/index.js +1 -1
- package/package.json +53 -49
- package/src/cairo-utils.ts +0 -243
- package/src/canvas-gradient.ts +0 -2
- package/src/canvas-path.ts +0 -2
- package/src/canvas-pattern.ts +0 -2
- package/src/canvas-rendering-context-2d.ts +0 -2
- package/src/canvas-state.ts +0 -77
- package/src/canvas2d-bridge.ts +0 -196
- package/src/color.ts +0 -125
- package/src/image-data.ts +0 -3
- package/src/index.spec.ts +0 -888
- package/src/index.ts +0 -42
- package/src/test.mts +0 -6
- package/tmp/.tsbuildinfo +0 -1
- package/tsconfig.json +0 -47
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.defineProperty,__name=(t,n)=>e(t,`name`,{value:n,configurable:!0});export{__name};
|
package/lib/esm/cairo-utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function quadraticToCubic(e,t,n,r,i,a){return{cp1x:e+2/3*(n-e),cp1y:t+2/3*(r-t),cp2x:i+2/3*(n-i),cp2y:a+2/3*(r-a)}}function computeArcTo(e,t,n,r,i,a,o){let s=e-n,c=t-r,l=i-n,u=a-r,d=Math.sqrt(s*s+c*c),f=Math.sqrt(l*l+u*u);if(d===0||f===0)return null;let p=s/d,m=c/d,h=l/f,g=u/f,_=p*g-m*h;if(Math.abs(_)<1e-10)return null;let v=p*h+m*g,y=Math.acos(Math.max(-1,Math.min(1,v)))/2,b=o/Math.tan(y),x=n+p*b,S=r+m*b,C=n+h*b,w=r+g*b,T=o/Math.sin(y),E=(p+h)/2,D=(m+g)/2,O=Math.sqrt(E*E+D*D),k=n+E/O*T,A=r+D/O*T;return{tx0:x,ty0:S,tx1:C,ty1:w,cx:k,cy:A,startAngle:Math.atan2(S-A,x-k),endAngle:Math.atan2(w-A,C-k),counterclockwise:_>0}}function cairoArcTo(e,t,n,r,i,a,o,s){let c=computeArcTo(t,n,r,i,a,o,s);if(!c){e.lineTo(r,i);return}let{tx0:l,ty0:u,cx:d,cy:f,startAngle:p,endAngle:m,counterclockwise:h}=c;e.lineTo(l,u),h?e.arcNegative(d,f,s,p,m):e.arc(d,f,s,p,m)}function cairoEllipse(e,t,n,r,i,a,o,s,c){e.save(),e.translate(t,n),e.rotate(a),e.scale(r,i),c?e.arcNegative(0,0,1,o,s):e.arc(0,0,1,o,s),e.restore()}function cairoRoundRect(e,t,n,r,i,a){let o,s,c,l;typeof a==`number`?o=s=c=l=a:a.length===1?o=s=c=l=a[0]:a.length===2?(o=c=a[0],s=l=a[1]):a.length===3?(o=a[0],s=l=a[1],c=a[2]):(o=a[0],s=a[1],c=a[2],l=a[3]);let u=Math.min(r/2,i/2);o=Math.min(o,u),s=Math.min(s,u),c=Math.min(c,u),l=Math.min(l,u);let d=Math.PI/2;e.newSubPath(),e.arc(t+o,n+o,o,Math.PI,Math.PI+d),e.arc(t+r-s,n+s,s,-d,0),e.arc(t+r-c,n+i-c,c,0,d),e.arc(t+l,n+i-l,l,d,Math.PI),e.closePath()}const e={"source-over":2,"source-in":5,"source-out":6,"source-atop":7,"destination-over":8,"destination-in":9,"destination-out":10,"destination-atop":11,lighter:12,copy:1,xor:13,multiply:14,screen:15,overlay:16,darken:17,lighten:18,"color-dodge":19,"color-burn":20,"hard-light":21,"soft-light":22,difference:23,exclusion:24,hue:25,saturation:26,color:27,luminosity:28},t={butt:0,round:1,square:2},n={miter:0,round:1,bevel:2};export{e as COMPOSITE_OP_MAP,t as LINE_CAP_MAP,n as LINE_JOIN_MAP,cairoArcTo,cairoEllipse,cairoRoundRect,computeArcTo,quadraticToCubic};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";function quadraticToCubic(e,t,n,r,i,a){return{cp1x:e+2/3*(n-e),cp1y:t+2/3*(r-t),cp2x:i+2/3*(n-i),cp2y:a+2/3*(r-a)}}function computeArcTo(e,t,n,r,i,a,o){let s=e-n,c=t-r,l=i-n,u=a-r,d=Math.sqrt(s*s+c*c),f=Math.sqrt(l*l+u*u);if(d===0||f===0)return null;let p=s/d,m=c/d,h=l/f,g=u/f,_=p*g-m*h;if(Math.abs(_)<1e-10)return null;let v=p*h+m*g,y=Math.acos(Math.max(-1,Math.min(1,v)))/2,b=o/Math.tan(y),x=n+p*b,S=r+m*b,C=n+h*b,w=r+g*b,T=o/Math.sin(y),E=(p+h)/2,D=(m+g)/2,O=Math.sqrt(E*E+D*D),k=n+E/O*T,A=r+D/O*T;return{tx0:x,ty0:S,tx1:C,ty1:w,cx:k,cy:A,startAngle:Math.atan2(S-A,x-k),endAngle:Math.atan2(w-A,C-k),counterclockwise:_>0}}function cairoArcTo(e,t,n,r,i,a,o,s){let c=computeArcTo(t,n,r,i,a,o,s);if(!c){e.lineTo(r,i);return}let{tx0:l,ty0:u,cx:d,cy:f,startAngle:p,endAngle:m,counterclockwise:h}=c;e.lineTo(l,u),h?e.arcNegative(d,f,s,p,m):e.arc(d,f,s,p,m)}function cairoEllipse(e,t,n,r,i,a,o,s,c){e.save(),e.translate(t,n),e.rotate(a),e.scale(r,i),c?e.arcNegative(0,0,1,o,s):e.arc(0,0,1,o,s),e.restore()}function cairoRoundRect(e,t,n,r,i,a){let o,s,c,l;typeof a==`number`?o=s=c=l=a:a.length===1?o=s=c=l=a[0]:a.length===2?(o=c=a[0],s=l=a[1]):a.length===3?(o=a[0],s=l=a[1],c=a[2]):(o=a[0],s=a[1],c=a[2],l=a[3]);let u=Math.min(r/2,i/2);o=Math.min(o,u),s=Math.min(s,u),c=Math.min(c,u),l=Math.min(l,u);let d=Math.PI/2;e.newSubPath(),e.arc(t+o,n+o,o,Math.PI,Math.PI+d),e.arc(t+r-s,n+s,s,-d,0),e.arc(t+r-c,n+i-c,c,0,d),e.arc(t+l,n+i-l,l,d,Math.PI),e.closePath()}const e={"source-over":2,"source-in":5,"source-out":6,"source-atop":7,"destination-over":8,"destination-in":9,"destination-out":10,"destination-atop":11,lighter:12,copy:1,xor:13,multiply:14,screen:15,overlay:16,darken:17,lighten:18,"color-dodge":19,"color-burn":20,"hard-light":21,"soft-light":22,difference:23,exclusion:24,hue:25,saturation:26,color:27,luminosity:28},t={butt:0,round:1,square:2},n={miter:0,round:1,bevel:2};export{e as COMPOSITE_OP_MAP,t as LINE_CAP_MAP,n as LINE_JOIN_MAP,cairoArcTo,cairoEllipse,cairoRoundRect,computeArcTo,quadraticToCubic};
|
package/lib/esm/canvas-state.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BLACK as e}from"./color.js";function createDefaultState(){return{fillStyle:`#000000`,fillColor:{...e},strokeStyle:`#000000`,strokeColor:{...e},lineWidth:1,lineCap:`butt`,lineJoin:`miter`,miterLimit:10,lineDash:[],lineDashOffset:0,globalAlpha:1,globalCompositeOperation:`source-over`,shadowColor:`rgba(0, 0, 0, 0)`,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,font:`10px sans-serif`,textAlign:`start`,textBaseline:`alphabetic`,direction:`ltr`,imageSmoothingEnabled:!0,imageSmoothingQuality:`low`}}function cloneState(e){return{...e,fillColor:{...e.fillColor},strokeColor:{...e.strokeColor},lineDash:[...e.lineDash]}}export{cloneState,createDefaultState};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{BLACK as e}from"./color.js";function createDefaultState(){return{fillStyle:`#000000`,fillColor:{...e},strokeStyle:`#000000`,strokeColor:{...e},lineWidth:1,lineCap:`butt`,lineJoin:`miter`,miterLimit:10,lineDash:[],lineDashOffset:0,globalAlpha:1,globalCompositeOperation:`source-over`,shadowColor:`rgba(0, 0, 0, 0)`,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,font:`10px sans-serif`,textAlign:`start`,textBaseline:`alphabetic`,direction:`ltr`,imageSmoothingEnabled:!0,imageSmoothingQuality:`low`}}function cloneState(e){return{...e,fillColor:{...e.fillColor},strokeColor:{...e.strokeColor},lineDash:[...e.lineDash]}}export{cloneState,createDefaultState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"gi://GObject";import t from"gi://GLib?version=2.0";import n from"gi://Gtk?version=4.0";import{HTMLCanvasElement as r}from"@gjsify/dom-elements";import{attachEventControllers as i}from"@gjsify/event-bridge";import{Event as a}from"@gjsify/dom-events";const o=e.registerClass({GTypeName:`GjsifyCanvas2DBridge`},class extends n.DrawingArea{constructor(e){super(e),this._canvas=null,this._ctx=null,this._readyCallbacks=[],this._resizeCallbacks=[],this._tickCallbackId=null,this._frameCallback=null,this._timeOrigin=t.get_monotonic_time(),this.set_draw_func(this._onDraw.bind(this)),i(this,()=>this._canvas,{captureKeys:!0}),this.connect(`unrealize`,()=>{this._tickCallbackId!==null&&(this.remove_tick_callback(this._tickCallbackId),this._tickCallbackId=null),this._ctx&&this._ctx._dispose(),this._canvas=null,this._ctx=null})}_onDraw(e,t,n,i){if(!this._canvas){if(this._canvas=new r,this._canvas.width=n,this._canvas.height=i,this._ctx=this._canvas.getContext(`2d`),this._ctx){for(let e of this._readyCallbacks)e(this._canvas,this._ctx);this._readyCallbacks=[]}}else if(this._canvas.width!==n||this._canvas.height!==i){this._canvas.width=n,this._canvas.height=i,this._canvas.dispatchEvent(new a(`resize`));for(let e of this._resizeCallbacks)e(n,i)}if(this._ctx){let e=this._ctx._getSurface();t.setSourceSurface(e,0,0),t.paint()}}get canvas(){return this._canvas}getContext(e){return this._ctx}onReady(e){if(this._canvas&&this._ctx){e(this._canvas,this._ctx);return}this._readyCallbacks.push(e)}onResize(e){this._resizeCallbacks.push(e)}requestAnimationFrame(e){return this._frameCallback=e,this._tickCallbackId===null&&(this._tickCallbackId=this.add_tick_callback((e,n)=>{this._tickCallbackId=null;let r=(n.get_frame_time()-this._timeOrigin)/1e3;return this._frameCallback?.(r),this.queue_draw(),t.SOURCE_REMOVE})),this.queue_draw(),0}installGlobals(){globalThis.requestAnimationFrame=e=>this.requestAnimationFrame(e);let e=this._timeOrigin;globalThis.performance={now:()=>(t.get_monotonic_time()-e)/1e3,timeOrigin:Date.now()}}});export{o as Canvas2DBridge};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import e from"gi://GObject";import t from"gi://GLib?version=2.0";import n from"gi://Gtk?version=4.0";import{HTMLCanvasElement as r}from"@gjsify/dom-elements";import{attachEventControllers as i}from"@gjsify/event-bridge";import{Event as a}from"@gjsify/dom-events";const o=e.registerClass({GTypeName:`GjsifyCanvas2DBridge`},class Canvas2DBridge extends n.DrawingArea{constructor(e){super(e),this._canvas=null,this._ctx=null,this._readyCallbacks=[],this._resizeCallbacks=[],this._tickCallbackId=null,this._frameCallback=null,this._timeOrigin=t.get_monotonic_time(),this.set_draw_func(this._onDraw.bind(this)),i(this,()=>this._canvas,{captureKeys:!0}),this.connect(`unrealize`,()=>{this._tickCallbackId!==null&&(this.remove_tick_callback(this._tickCallbackId),this._tickCallbackId=null),this._ctx&&this._ctx._dispose(),this._canvas=null,this._ctx=null})}_onDraw(e,t,n,i){if(!this._canvas){if(this._canvas=new r,this._canvas.width=n,this._canvas.height=i,this._ctx=this._canvas.getContext(`2d`),this._ctx){for(let e of this._readyCallbacks)e(this._canvas,this._ctx);this._readyCallbacks=[]}}else if(this._canvas.width!==n||this._canvas.height!==i){this._canvas.width=n,this._canvas.height=i,this._canvas.dispatchEvent(new a(`resize`));for(let e of this._resizeCallbacks)e(n,i)}if(this._ctx){let e=this._ctx._getSurface();t.setSourceSurface(e,0,0),t.paint()}}get canvas(){return this._canvas}getContext(e){return this._ctx}onReady(e){if(this._canvas&&this._ctx){e(this._canvas,this._ctx);return}this._readyCallbacks.push(e)}onResize(e){this._resizeCallbacks.push(e)}requestAnimationFrame(e){return this._frameCallback=e,this._tickCallbackId===null&&(this._tickCallbackId=this.add_tick_callback((e,n)=>{this._tickCallbackId=null;let r=(n.get_frame_time()-this._timeOrigin)/1e3;return this._frameCallback?.(r),this.queue_draw(),t.SOURCE_REMOVE})),this.queue_draw(),0}installGlobals(){globalThis.requestAnimationFrame=e=>this.requestAnimationFrame(e);let e=this._timeOrigin;globalThis.performance={now:()=>(t.get_monotonic_time()-e)/1e3,timeOrigin:Date.now()}}});export{o as Canvas2DBridge};
|
package/lib/esm/color.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`,transparent:`#00000000`};function parseColor(t){if(!t||typeof t!=`string`)return null;let n=t.trim().toLowerCase(),r=e[n];if(r)return parseHex(r);if(n.startsWith(`#`))return parseHex(n);let i=n.match(/^rgba?\(\s*(\d+(?:\.\d+)?%?)\s*[,\s]\s*(\d+(?:\.\d+)?%?)\s*[,\s]\s*(\d+(?:\.\d+)?%?)\s*(?:[,/]\s*(\d+(?:\.\d+)?%?))?\s*\)$/);return i?{r:parseComponent(i[1],255)/255,g:parseComponent(i[2],255)/255,b:parseComponent(i[3],255)/255,a:i[4]===void 0?1:parseComponent(i[4],1)}:null}function parseHex(e){let t=e.slice(1),n,r,i,a=1;if(t.length===3)n=parseInt(t[0]+t[0],16)/255,r=parseInt(t[1]+t[1],16)/255,i=parseInt(t[2]+t[2],16)/255;else if(t.length===4)n=parseInt(t[0]+t[0],16)/255,r=parseInt(t[1]+t[1],16)/255,i=parseInt(t[2]+t[2],16)/255,a=parseInt(t[3]+t[3],16)/255;else if(t.length===6)n=parseInt(t.slice(0,2),16)/255,r=parseInt(t.slice(2,4),16)/255,i=parseInt(t.slice(4,6),16)/255;else if(t.length===8)n=parseInt(t.slice(0,2),16)/255,r=parseInt(t.slice(2,4),16)/255,i=parseInt(t.slice(4,6),16)/255,a=parseInt(t.slice(6,8),16)/255;else return null;return{r:n,g:r,b:i,a}}function parseComponent(e,t){return e.endsWith(`%`)?parseFloat(e)/100*t:parseFloat(e)}const t={r:0,g:0,b:0,a:1},n={r:0,g:0,b:0,a:0};export{t as BLACK,n as TRANSPARENT,parseColor};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";const e={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,gold:`#ffd700`,goldenrod:`#daa520`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,lavender:`#e6e6fa`,lavenderblush:`#fff0f5`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`,transparent:`#00000000`};function parseColor(t){if(!t||typeof t!=`string`)return null;let n=t.trim().toLowerCase(),r=e[n];if(r)return parseHex(r);if(n.startsWith(`#`))return parseHex(n);let i=n.match(/^rgba?\(\s*(\d+(?:\.\d+)?%?)\s*[,\s]\s*(\d+(?:\.\d+)?%?)\s*[,\s]\s*(\d+(?:\.\d+)?%?)\s*(?:[,/]\s*(\d+(?:\.\d+)?%?))?\s*\)$/);return i?{r:parseComponent(i[1],255)/255,g:parseComponent(i[2],255)/255,b:parseComponent(i[3],255)/255,a:i[4]===void 0?1:parseComponent(i[4],1)}:null}function parseHex(e){let t=e.slice(1),n,r,i,a=1;if(t.length===3)n=parseInt(t[0]+t[0],16)/255,r=parseInt(t[1]+t[1],16)/255,i=parseInt(t[2]+t[2],16)/255;else if(t.length===4)n=parseInt(t[0]+t[0],16)/255,r=parseInt(t[1]+t[1],16)/255,i=parseInt(t[2]+t[2],16)/255,a=parseInt(t[3]+t[3],16)/255;else if(t.length===6)n=parseInt(t.slice(0,2),16)/255,r=parseInt(t.slice(2,4),16)/255,i=parseInt(t.slice(4,6),16)/255;else if(t.length===8)n=parseInt(t.slice(0,2),16)/255,r=parseInt(t.slice(2,4),16)/255,i=parseInt(t.slice(4,6),16)/255,a=parseInt(t.slice(6,8),16)/255;else return null;return{r:n,g:r,b:i,a}}function parseComponent(e,t){return e.endsWith(`%`)?parseFloat(e)/100*t:parseFloat(e)}const t={r:0,g:0,b:0,a:1},n={r:0,g:0,b:0,a:0};export{t as BLACK,n as TRANSPARENT,parseColor};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Canvas2DBridge as e}from"./canvas2d-bridge.js";import{CanvasGradient as t,CanvasPattern as n,CanvasRenderingContext2D as r,CanvasRenderingContext2D as i,ImageData as a,ImageData as o,Path2D as s,Path2D as c,parseColor as l}from"@gjsify/canvas2d-core";import{HTMLCanvasElement as u}from"@gjsify/dom-elements";const d=Symbol.for(`gjsify_canvas2d_context`);u.registerContextFactory(`2d`,(e,t)=>{let n=e[d];if(n)return n;let r=new i(e,t);return e[d]=r,r}),Object.defineProperty(globalThis,`CanvasRenderingContext2D`,{value:i,writable:!0,configurable:!0}),Object.defineProperty(globalThis,`ImageData`,{value:o,writable:!0,configurable:!0}),Object.defineProperty(globalThis,`Path2D`,{value:c,writable:!0,configurable:!0});export{e as Canvas2DBridge,t as CanvasGradient,n as CanvasPattern,r as CanvasRenderingContext2D,a as ImageData,s as Path2D,l as parseColor};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Canvas2DBridge as e}from"./canvas2d-bridge.js";import{CanvasGradient as t,CanvasPattern as n,CanvasRenderingContext2D as r,CanvasRenderingContext2D as i,ImageData as a,ImageData as o,Path2D as s,Path2D as c,parseColor as l}from"@gjsify/canvas2d-core";import{HTMLCanvasElement as u}from"@gjsify/dom-elements";const d=Symbol.for(`gjsify_canvas2d_context`);u.registerContextFactory(`2d`,(e,t)=>{let n=e[d];if(n)return n;let r=new i(e,t);return e[d]=r,r}),Object.defineProperty(globalThis,`CanvasRenderingContext2D`,{value:i,writable:!0,configurable:!0}),Object.defineProperty(globalThis,`ImageData`,{value:o,writable:!0,configurable:!0}),Object.defineProperty(globalThis,`Path2D`,{value:c,writable:!0,configurable:!0});export{e as Canvas2DBridge,t as CanvasGradient,n as CanvasPattern,r as CanvasRenderingContext2D,a as ImageData,s as Path2D,l as parseColor};
|
package/package.json
CHANGED
|
@@ -1,51 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
"name": "@gjsify/canvas2d",
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"description": "Canvas 2D rendering context for GJS, backed by Cairo",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "lib/esm/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/esm/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"lib"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"clear": "rm -rf lib tmp tsconfig.tsbuildinfo test.gjs.mjs || exit 0",
|
|
19
|
+
"check": "tsc --noEmit",
|
|
20
|
+
"build": "gjsify run build:gjsify && gjsify run build:types",
|
|
21
|
+
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
22
|
+
"build:types": "tsc",
|
|
23
|
+
"build:test": "gjsify run build:test:gjs",
|
|
24
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
25
|
+
"test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
|
|
26
|
+
"test:gjs": "gjsify run test.gjs.mjs"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"gjs",
|
|
30
|
+
"canvas",
|
|
31
|
+
"canvas2d",
|
|
32
|
+
"cairo"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@girs/gdk-4.0": "4.0.0-4.0.0-rc.15",
|
|
36
|
+
"@girs/gdkpixbuf-2.0": "2.0.0-4.0.0-rc.15",
|
|
37
|
+
"@girs/gjs": "4.0.0-rc.15",
|
|
38
|
+
"@girs/glib-2.0": "2.88.0-4.0.0-rc.15",
|
|
39
|
+
"@girs/gobject-2.0": "2.88.0-4.0.0-rc.15",
|
|
40
|
+
"@girs/gtk-4.0": "4.23.0-4.0.0-rc.15",
|
|
41
|
+
"@girs/pango-1.0": "1.57.1-4.0.0-rc.15",
|
|
42
|
+
"@girs/pangocairo-1.0": "1.0.0-4.0.0-rc.15",
|
|
43
|
+
"@gjsify/canvas2d-core": "workspace:^",
|
|
44
|
+
"@gjsify/dom-elements": "workspace:^",
|
|
45
|
+
"@gjsify/dom-events": "workspace:^",
|
|
46
|
+
"@gjsify/event-bridge": "workspace:^",
|
|
47
|
+
"@gjsify/utils": "workspace:^"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@gjsify/cli": "workspace:^",
|
|
51
|
+
"@gjsify/unit": "workspace:^",
|
|
52
|
+
"@types/node": "^25.6.2",
|
|
53
|
+
"typescript": "^6.0.3"
|
|
12
54
|
}
|
|
13
|
-
|
|
14
|
-
"scripts": {
|
|
15
|
-
"clear": "rm -rf lib tmp tsconfig.tsbuildinfo test.gjs.mjs || exit 0",
|
|
16
|
-
"check": "tsc --noEmit",
|
|
17
|
-
"build": "yarn build:gjsify && yarn build:types",
|
|
18
|
-
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
19
|
-
"build:types": "tsc",
|
|
20
|
-
"build:test": "yarn build:test:gjs",
|
|
21
|
-
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
22
|
-
"test": "yarn build:gjsify && yarn build:test && yarn test:gjs",
|
|
23
|
-
"test:gjs": "gjsify run test.gjs.mjs"
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"gjs",
|
|
27
|
-
"canvas",
|
|
28
|
-
"canvas2d",
|
|
29
|
-
"cairo"
|
|
30
|
-
],
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@girs/gdk-4.0": "4.0.0-4.0.0-rc.14",
|
|
33
|
-
"@girs/gdkpixbuf-2.0": "2.0.0-4.0.0-rc.14",
|
|
34
|
-
"@girs/gjs": "4.0.0-rc.14",
|
|
35
|
-
"@girs/glib-2.0": "2.88.0-4.0.0-rc.14",
|
|
36
|
-
"@girs/gobject-2.0": "2.88.0-4.0.0-rc.14",
|
|
37
|
-
"@girs/gtk-4.0": "4.23.0-4.0.0-rc.14",
|
|
38
|
-
"@girs/pango-1.0": "1.57.1-4.0.0-rc.14",
|
|
39
|
-
"@girs/pangocairo-1.0": "1.0.0-4.0.0-rc.14",
|
|
40
|
-
"@gjsify/canvas2d-core": "^0.3.21",
|
|
41
|
-
"@gjsify/dom-elements": "^0.3.21",
|
|
42
|
-
"@gjsify/event-bridge": "^0.3.21",
|
|
43
|
-
"@gjsify/utils": "^0.3.21"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@gjsify/cli": "^0.3.21",
|
|
47
|
-
"@gjsify/unit": "^0.3.21",
|
|
48
|
-
"@types/node": "^25.6.2",
|
|
49
|
-
"typescript": "^6.0.3"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
55
|
+
}
|
package/src/cairo-utils.ts
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
// Cairo utility helpers for Canvas 2D context
|
|
2
|
-
// Handles format conversions and path operations not directly available in Cairo.
|
|
3
|
-
|
|
4
|
-
import type Cairo from 'cairo';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Convert quadratic Bezier control point to cubic Bezier control points.
|
|
8
|
-
* Canvas 2D has quadraticCurveTo but Cairo only has cubic curveTo.
|
|
9
|
-
*
|
|
10
|
-
* Given current point (cx, cy), quadratic control point (cpx, cpy), and end (x, y):
|
|
11
|
-
* cp1 = current + 2/3 * (cp - current)
|
|
12
|
-
* cp2 = end + 2/3 * (cp - end)
|
|
13
|
-
*/
|
|
14
|
-
export function quadraticToCubic(
|
|
15
|
-
cx: number, cy: number,
|
|
16
|
-
cpx: number, cpy: number,
|
|
17
|
-
x: number, y: number,
|
|
18
|
-
): { cp1x: number; cp1y: number; cp2x: number; cp2y: number } {
|
|
19
|
-
return {
|
|
20
|
-
cp1x: cx + (2 / 3) * (cpx - cx),
|
|
21
|
-
cp1y: cy + (2 / 3) * (cpy - cy),
|
|
22
|
-
cp2x: x + (2 / 3) * (cpx - x),
|
|
23
|
-
cp2y: y + (2 / 3) * (cpy - y),
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Compute arcTo parameters.
|
|
29
|
-
* Canvas arcTo(x1,y1,x2,y2,radius) draws a line from current point to the tangent point,
|
|
30
|
-
* then an arc of the given radius tangent to both lines (current→p1 and p1→p2).
|
|
31
|
-
*
|
|
32
|
-
* Returns the two tangent points and arc center, or null if degenerate (collinear points).
|
|
33
|
-
*/
|
|
34
|
-
export function computeArcTo(
|
|
35
|
-
x0: number, y0: number,
|
|
36
|
-
x1: number, y1: number,
|
|
37
|
-
x2: number, y2: number,
|
|
38
|
-
radius: number,
|
|
39
|
-
): { tx0: number; ty0: number; tx1: number; ty1: number; cx: number; cy: number; startAngle: number; endAngle: number; counterclockwise: boolean } | null {
|
|
40
|
-
// Direction vectors
|
|
41
|
-
const dx0 = x0 - x1;
|
|
42
|
-
const dy0 = y0 - y1;
|
|
43
|
-
const dx1 = x2 - x1;
|
|
44
|
-
const dy1 = y2 - y1;
|
|
45
|
-
|
|
46
|
-
// Lengths
|
|
47
|
-
const len0 = Math.sqrt(dx0 * dx0 + dy0 * dy0);
|
|
48
|
-
const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
|
|
49
|
-
|
|
50
|
-
if (len0 === 0 || len1 === 0) return null;
|
|
51
|
-
|
|
52
|
-
// Normalize
|
|
53
|
-
const ux0 = dx0 / len0;
|
|
54
|
-
const uy0 = dy0 / len0;
|
|
55
|
-
const ux1 = dx1 / len1;
|
|
56
|
-
const uy1 = dy1 / len1;
|
|
57
|
-
|
|
58
|
-
// Cross product to determine direction
|
|
59
|
-
const cross = ux0 * uy1 - uy0 * ux1;
|
|
60
|
-
if (Math.abs(cross) < 1e-10) return null; // Collinear
|
|
61
|
-
|
|
62
|
-
// Half-angle between the two direction vectors
|
|
63
|
-
const dot = ux0 * ux1 + uy0 * uy1;
|
|
64
|
-
const halfAngle = Math.acos(Math.max(-1, Math.min(1, dot))) / 2;
|
|
65
|
-
|
|
66
|
-
// Distance from p1 to tangent point
|
|
67
|
-
const tanDist = radius / Math.tan(halfAngle);
|
|
68
|
-
|
|
69
|
-
// Tangent points
|
|
70
|
-
const tx0 = x1 + ux0 * tanDist;
|
|
71
|
-
const ty0 = y1 + uy0 * tanDist;
|
|
72
|
-
const tx1 = x1 + ux1 * tanDist;
|
|
73
|
-
const ty1 = y1 + uy1 * tanDist;
|
|
74
|
-
|
|
75
|
-
// Center of the arc circle: perpendicular to the bisector, distance = radius / sin(halfAngle)
|
|
76
|
-
const centerDist = radius / Math.sin(halfAngle);
|
|
77
|
-
const bisectX = (ux0 + ux1) / 2;
|
|
78
|
-
const bisectY = (uy0 + uy1) / 2;
|
|
79
|
-
const bisectLen = Math.sqrt(bisectX * bisectX + bisectY * bisectY);
|
|
80
|
-
const cx = x1 + (bisectX / bisectLen) * centerDist;
|
|
81
|
-
const cy = y1 + (bisectY / bisectLen) * centerDist;
|
|
82
|
-
|
|
83
|
-
// Start and end angles
|
|
84
|
-
const startAngle = Math.atan2(ty0 - cy, tx0 - cx);
|
|
85
|
-
const endAngle = Math.atan2(ty1 - cy, tx1 - cx);
|
|
86
|
-
|
|
87
|
-
// Counterclockwise if cross product is positive
|
|
88
|
-
const counterclockwise = cross > 0;
|
|
89
|
-
|
|
90
|
-
return { tx0, ty0, tx1, ty1, cx, cy, startAngle, endAngle, counterclockwise };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Apply an arcTo operation to a Cairo context.
|
|
95
|
-
*/
|
|
96
|
-
export function cairoArcTo(
|
|
97
|
-
ctx: Cairo.Context,
|
|
98
|
-
x0: number, y0: number,
|
|
99
|
-
x1: number, y1: number,
|
|
100
|
-
x2: number, y2: number,
|
|
101
|
-
radius: number,
|
|
102
|
-
): void {
|
|
103
|
-
const result = computeArcTo(x0, y0, x1, y1, x2, y2, radius);
|
|
104
|
-
if (!result) {
|
|
105
|
-
// Degenerate: just draw a line to (x1, y1)
|
|
106
|
-
ctx.lineTo(x1, y1);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const { tx0, ty0, cx, cy, startAngle, endAngle, counterclockwise } = result;
|
|
111
|
-
|
|
112
|
-
// Line from current point to first tangent point
|
|
113
|
-
ctx.lineTo(tx0, ty0);
|
|
114
|
-
|
|
115
|
-
// Arc
|
|
116
|
-
if (counterclockwise) {
|
|
117
|
-
ctx.arcNegative(cx, cy, radius, startAngle, endAngle);
|
|
118
|
-
} else {
|
|
119
|
-
ctx.arc(cx, cy, radius, startAngle, endAngle);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Draw an ellipse on a Cairo context.
|
|
125
|
-
* Canvas ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise)
|
|
126
|
-
* is implemented via save/translate/rotate/scale/arc/restore.
|
|
127
|
-
*/
|
|
128
|
-
export function cairoEllipse(
|
|
129
|
-
ctx: Cairo.Context,
|
|
130
|
-
x: number, y: number,
|
|
131
|
-
radiusX: number, radiusY: number,
|
|
132
|
-
rotation: number,
|
|
133
|
-
startAngle: number, endAngle: number,
|
|
134
|
-
counterclockwise: boolean,
|
|
135
|
-
): void {
|
|
136
|
-
ctx.save();
|
|
137
|
-
ctx.translate(x, y);
|
|
138
|
-
ctx.rotate(rotation);
|
|
139
|
-
ctx.scale(radiusX, radiusY);
|
|
140
|
-
|
|
141
|
-
if (counterclockwise) {
|
|
142
|
-
ctx.arcNegative(0, 0, 1, startAngle, endAngle);
|
|
143
|
-
} else {
|
|
144
|
-
ctx.arc(0, 0, 1, startAngle, endAngle);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
ctx.restore();
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Draw a rounded rectangle path on a Cairo context.
|
|
152
|
-
* Implements the Canvas roundRect(x, y, w, h, radii) method.
|
|
153
|
-
*/
|
|
154
|
-
export function cairoRoundRect(
|
|
155
|
-
ctx: Cairo.Context,
|
|
156
|
-
x: number, y: number,
|
|
157
|
-
w: number, h: number,
|
|
158
|
-
radii: number | number[],
|
|
159
|
-
): void {
|
|
160
|
-
// Normalize radii to [topLeft, topRight, bottomRight, bottomLeft]
|
|
161
|
-
let tl: number, tr: number, br: number, bl: number;
|
|
162
|
-
if (typeof radii === 'number') {
|
|
163
|
-
tl = tr = br = bl = radii;
|
|
164
|
-
} else if (radii.length === 1) {
|
|
165
|
-
tl = tr = br = bl = radii[0];
|
|
166
|
-
} else if (radii.length === 2) {
|
|
167
|
-
tl = br = radii[0];
|
|
168
|
-
tr = bl = radii[1];
|
|
169
|
-
} else if (radii.length === 3) {
|
|
170
|
-
tl = radii[0];
|
|
171
|
-
tr = bl = radii[1];
|
|
172
|
-
br = radii[2];
|
|
173
|
-
} else {
|
|
174
|
-
tl = radii[0];
|
|
175
|
-
tr = radii[1];
|
|
176
|
-
br = radii[2];
|
|
177
|
-
bl = radii[3];
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Clamp radii so they don't exceed half the width/height
|
|
181
|
-
const maxR = Math.min(w / 2, h / 2);
|
|
182
|
-
tl = Math.min(tl, maxR);
|
|
183
|
-
tr = Math.min(tr, maxR);
|
|
184
|
-
br = Math.min(br, maxR);
|
|
185
|
-
bl = Math.min(bl, maxR);
|
|
186
|
-
|
|
187
|
-
const PI_2 = Math.PI / 2;
|
|
188
|
-
|
|
189
|
-
ctx.newSubPath();
|
|
190
|
-
// Top-left corner
|
|
191
|
-
ctx.arc(x + tl, y + tl, tl, Math.PI, Math.PI + PI_2);
|
|
192
|
-
// Top-right corner
|
|
193
|
-
ctx.arc(x + w - tr, y + tr, tr, -PI_2, 0);
|
|
194
|
-
// Bottom-right corner
|
|
195
|
-
ctx.arc(x + w - br, y + h - br, br, 0, PI_2);
|
|
196
|
-
// Bottom-left corner
|
|
197
|
-
ctx.arc(x + bl, y + h - bl, bl, PI_2, Math.PI);
|
|
198
|
-
ctx.closePath();
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/** Map Canvas globalCompositeOperation to Cairo.Operator values */
|
|
202
|
-
export const COMPOSITE_OP_MAP: Record<string, number> = {
|
|
203
|
-
'source-over': 2, // OVER
|
|
204
|
-
'source-in': 5, // IN
|
|
205
|
-
'source-out': 6, // OUT
|
|
206
|
-
'source-atop': 7, // ATOP
|
|
207
|
-
'destination-over': 8, // DEST_OVER
|
|
208
|
-
'destination-in': 9, // DEST_IN
|
|
209
|
-
'destination-out': 10, // DEST_OUT
|
|
210
|
-
'destination-atop': 11,// DEST_ATOP
|
|
211
|
-
'lighter': 12, // ADD
|
|
212
|
-
'copy': 1, // SOURCE
|
|
213
|
-
'xor': 13, // XOR
|
|
214
|
-
'multiply': 14, // MULTIPLY
|
|
215
|
-
'screen': 15, // SCREEN
|
|
216
|
-
'overlay': 16, // OVERLAY
|
|
217
|
-
'darken': 17, // DARKEN
|
|
218
|
-
'lighten': 18, // LIGHTEN
|
|
219
|
-
'color-dodge': 19, // COLOR_DODGE
|
|
220
|
-
'color-burn': 20, // COLOR_BURN
|
|
221
|
-
'hard-light': 21, // HARD_LIGHT
|
|
222
|
-
'soft-light': 22, // SOFT_LIGHT
|
|
223
|
-
'difference': 23, // DIFFERENCE
|
|
224
|
-
'exclusion': 24, // EXCLUSION
|
|
225
|
-
'hue': 25, // HSL_HUE
|
|
226
|
-
'saturation': 26, // HSL_SATURATION
|
|
227
|
-
'color': 27, // HSL_COLOR
|
|
228
|
-
'luminosity': 28, // HSL_LUMINOSITY
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
/** Map Canvas lineCap to Cairo.LineCap values */
|
|
232
|
-
export const LINE_CAP_MAP: Record<string, number> = {
|
|
233
|
-
'butt': 0,
|
|
234
|
-
'round': 1,
|
|
235
|
-
'square': 2,
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
/** Map Canvas lineJoin to Cairo.LineJoin values */
|
|
239
|
-
export const LINE_JOIN_MAP: Record<string, number> = {
|
|
240
|
-
'miter': 0,
|
|
241
|
-
'round': 1,
|
|
242
|
-
'bevel': 2,
|
|
243
|
-
};
|
package/src/canvas-gradient.ts
DELETED
package/src/canvas-path.ts
DELETED
package/src/canvas-pattern.ts
DELETED
package/src/canvas-state.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
// Drawing state for Canvas 2D context save()/restore() stack.
|
|
2
|
-
// Each save() pushes a clone of the current state; restore() pops it.
|
|
3
|
-
|
|
4
|
-
import type { RGBA } from './color.js';
|
|
5
|
-
import { BLACK } from './color.js';
|
|
6
|
-
|
|
7
|
-
export interface CanvasState {
|
|
8
|
-
// Fill & stroke
|
|
9
|
-
fillStyle: string | CanvasGradient | CanvasPattern;
|
|
10
|
-
fillColor: RGBA;
|
|
11
|
-
strokeStyle: string | CanvasGradient | CanvasPattern;
|
|
12
|
-
strokeColor: RGBA;
|
|
13
|
-
|
|
14
|
-
// Line properties
|
|
15
|
-
lineWidth: number;
|
|
16
|
-
lineCap: CanvasLineCap;
|
|
17
|
-
lineJoin: CanvasLineJoin;
|
|
18
|
-
miterLimit: number;
|
|
19
|
-
lineDash: number[];
|
|
20
|
-
lineDashOffset: number;
|
|
21
|
-
|
|
22
|
-
// Compositing
|
|
23
|
-
globalAlpha: number;
|
|
24
|
-
globalCompositeOperation: GlobalCompositeOperation;
|
|
25
|
-
|
|
26
|
-
// Shadows (Phase 5 — tracked in state for save/restore correctness)
|
|
27
|
-
shadowColor: string;
|
|
28
|
-
shadowBlur: number;
|
|
29
|
-
shadowOffsetX: number;
|
|
30
|
-
shadowOffsetY: number;
|
|
31
|
-
|
|
32
|
-
// Text (Phase 4)
|
|
33
|
-
font: string;
|
|
34
|
-
textAlign: CanvasTextAlign;
|
|
35
|
-
textBaseline: CanvasTextBaseline;
|
|
36
|
-
direction: CanvasDirection;
|
|
37
|
-
|
|
38
|
-
// Image smoothing
|
|
39
|
-
imageSmoothingEnabled: boolean;
|
|
40
|
-
imageSmoothingQuality: ImageSmoothingQuality;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function createDefaultState(): CanvasState {
|
|
44
|
-
return {
|
|
45
|
-
fillStyle: '#000000',
|
|
46
|
-
fillColor: { ...BLACK },
|
|
47
|
-
strokeStyle: '#000000',
|
|
48
|
-
strokeColor: { ...BLACK },
|
|
49
|
-
lineWidth: 1,
|
|
50
|
-
lineCap: 'butt',
|
|
51
|
-
lineJoin: 'miter',
|
|
52
|
-
miterLimit: 10,
|
|
53
|
-
lineDash: [],
|
|
54
|
-
lineDashOffset: 0,
|
|
55
|
-
globalAlpha: 1,
|
|
56
|
-
globalCompositeOperation: 'source-over',
|
|
57
|
-
shadowColor: 'rgba(0, 0, 0, 0)',
|
|
58
|
-
shadowBlur: 0,
|
|
59
|
-
shadowOffsetX: 0,
|
|
60
|
-
shadowOffsetY: 0,
|
|
61
|
-
font: '10px sans-serif',
|
|
62
|
-
textAlign: 'start',
|
|
63
|
-
textBaseline: 'alphabetic',
|
|
64
|
-
direction: 'ltr',
|
|
65
|
-
imageSmoothingEnabled: true,
|
|
66
|
-
imageSmoothingQuality: 'low',
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function cloneState(state: CanvasState): CanvasState {
|
|
71
|
-
return {
|
|
72
|
-
...state,
|
|
73
|
-
fillColor: { ...state.fillColor },
|
|
74
|
-
strokeColor: { ...state.strokeColor },
|
|
75
|
-
lineDash: [...state.lineDash],
|
|
76
|
-
};
|
|
77
|
-
}
|