@gjsify/canvas2d-core 0.4.21 → 0.4.22

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.
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{asCairoPattern as e}from"./cairo-types.js";import{COMPOSITE_OP_MAP as t,LINE_CAP_MAP as n,LINE_JOIN_MAP as r,cairoArcTo as i,cairoEllipse as a,cairoRoundRect as o,quadraticToCubic as s}from"./cairo-utils.js";import{parseColor as c}from"./color.js";import{CanvasGradient as l}from"./canvas-gradient.js";import{Path2D as u}from"./canvas-path.js";import{isCanvasImageSource as d,isPixbufImageSource as f}from"./dom-types.js";import{CanvasPattern as p}from"./canvas-pattern.js";import{cloneState as m,createDefaultState as h}from"./canvas-state.js";import{OurImageData as g}from"./image-data.js";import _ from"cairo";import v from"gi://Gdk?version=4.0";import y from"gi://GdkPixbuf";import b from"gi://Pango";import x from"gi://PangoCairo";var CanvasRenderingContext2D=class{constructor(e,t){this._stateStack=[],this.canvas=e,this._surfaceWidth=e.width||300,this._surfaceHeight=e.height||150,this._surface=new _.ImageSurface(_.Format.ARGB32,this._surfaceWidth,this._surfaceHeight),this._ctx=new _.Context(this._surface),this._state=h()}_ensureSurface(){let e=this.canvas.width||300,t=this.canvas.height||150;(e!==this._surfaceWidth||t!==this._surfaceHeight)&&(this._ctx.$dispose(),this._surface.finish(),this._surfaceWidth=e,this._surfaceHeight=t,this._surface=new _.ImageSurface(_.Format.ARGB32,e,t),this._ctx=new _.Context(this._surface),this._stateStack=[])}_resetState(){this._state=h(),this._stateStack=[]}_applyFillStyle(){let e=this._state.fillStyle;if(typeof e==`string`){let e=this._state.fillColor,t=e.a*this._state.globalAlpha;this._ctx.setSourceRGBA(e.r,e.g,e.b,t)}else e instanceof l?this._ctx.setSource(e._getCairoPattern()):e instanceof p&&(this._ctx.setSource(e._getCairoPattern()),this._applyPatternFilter())}_applyStrokeStyle(){let e=this._state.strokeStyle;if(typeof e==`string`){let e=this._state.strokeColor,t=e.a*this._state.globalAlpha;this._ctx.setSourceRGBA(e.r,e.g,e.b,t)}else e instanceof l?this._ctx.setSource(e._getCairoPattern()):e instanceof p&&(this._ctx.setSource(e._getCairoPattern()),this._applyPatternFilter())}_applyPatternFilter(){let t=e(this._ctx.getSource?.());if(!t)return;let n;n=this._state.imageSmoothingEnabled?this._state.imageSmoothingQuality===`high`?_.Filter.BEST:_.Filter.BILINEAR:_.Filter.NEAREST,t.setFilter(n)}_applyLineStyle(){this._ctx.setLineWidth(this._state.lineWidth),this._ctx.setLineCap(n[this._state.lineCap]),this._ctx.setLineJoin(r[this._state.lineJoin]),this._ctx.setMiterLimit(this._state.miterLimit),this._ctx.setDash(this._state.lineDash,this._state.lineDashOffset)}_applyCompositing(){let e=t[this._state.globalCompositeOperation];e!==void 0&&this._ctx.setOperator(e)}_getSurface(){return this._surface}_hasShadow(){if(this._state.shadowBlur===0&&this._state.shadowOffsetX===0&&this._state.shadowOffsetY===0)return!1;let e=c(this._state.shadowColor);return e!==null&&e.a>0}_deviceToUserDistance(e,t){let n=this._ctx.userToDevice(0,0),r=this._ctx.userToDevice(1,0),i=this._ctx.userToDevice(0,1),a=(r[0]??0)-(n[0]??0),o=(r[1]??0)-(n[1]??0),s=(i[0]??0)-(n[0]??0),c=(i[1]??0)-(n[1]??0),l=a*c-o*s;return Math.abs(l)<1e-10?[e,t]:[(c*e-s*t)/l,(-o*e+a*t)/l]}_renderShadow(e){}save(){this._ensureSurface(),this._stateStack.push(m(this._state)),this._ctx.save()}restore(){this._ensureSurface();let e=this._stateStack.pop();e&&(this._state=e,this._ctx.restore())}translate(e,t){this._ensureSurface(),this._ctx.translate(e,t)}rotate(e){this._ensureSurface(),this._ctx.rotate(e)}scale(e,t){this._ensureSurface(),this._ctx.scale(e,t)}transform(e,t,n,r,i,a){if(this._ensureSurface(),!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(i)||!Number.isFinite(a))return;let o=i,s=a,c=Math.hypot(e,t),l=Math.hypot(n,r),u=Math.atan2(t,e);this._ctx.translate(o,s),u!==0&&this._ctx.rotate(u),(c!==1||l!==1)&&this._ctx.scale(c,l)}setTransform(e,t,n,r,i,a){if(this._ensureSurface(),typeof e==`object`&&e){let t=e;this._ctx.identityMatrix(),this.transform(t.a??t.m11??1,t.b??t.m12??0,t.c??t.m21??0,t.d??t.m22??1,t.e??t.m41??0,t.f??t.m42??0)}else typeof e==`number`?(this._ctx.identityMatrix(),this.transform(e,t,n,r,i,a)):this._ctx.identityMatrix()}getTransform(){let e=this._ctx.userToDevice(0,0),t=this._ctx.userToDevice(1,0),n=this._ctx.userToDevice(0,1),r=e[0]??0,i=e[1]??0,a=(t[0]??0)-r,o=(t[1]??0)-i,s=(n[0]??0)-r,c=(n[1]??0)-i,l=globalThis.DOMMatrix;return typeof l==`function`?new l([a,o,s,c,r,i]):{a,b:o,c:s,d:c,e:r,f:i,m11:a,m12:o,m13:0,m14:0,m21:s,m22:c,m23:0,m24:0,m31:0,m32:0,m33:1,m34:0,m41:r,m42:i,m43:0,m44:1,is2D:!0,isIdentity:a===1&&o===0&&s===0&&c===1&&r===0&&i===0}}resetTransform(){this._ensureSurface(),this._ctx.identityMatrix()}get fillStyle(){return this._state.fillStyle}set fillStyle(e){if(typeof e==`string`){let t=c(e);t&&(this._state.fillStyle=e,this._state.fillColor=t)}else this._state.fillStyle=e}get strokeStyle(){return this._state.strokeStyle}set strokeStyle(e){if(typeof e==`string`){let t=c(e);t&&(this._state.strokeStyle=e,this._state.strokeColor=t)}else this._state.strokeStyle=e}get lineWidth(){return this._state.lineWidth}set lineWidth(e){e>0&&isFinite(e)&&(this._state.lineWidth=e)}get lineCap(){return this._state.lineCap}set lineCap(e){(e===`butt`||e===`round`||e===`square`)&&(this._state.lineCap=e)}get lineJoin(){return this._state.lineJoin}set lineJoin(e){(e===`miter`||e===`round`||e===`bevel`)&&(this._state.lineJoin=e)}get miterLimit(){return this._state.miterLimit}set miterLimit(e){e>0&&isFinite(e)&&(this._state.miterLimit=e)}get globalAlpha(){return this._state.globalAlpha}set globalAlpha(e){e>=0&&e<=1&&isFinite(e)&&(this._state.globalAlpha=e)}get globalCompositeOperation(){return this._state.globalCompositeOperation}set globalCompositeOperation(e){t[e]!==void 0&&(this._state.globalCompositeOperation=e)}get imageSmoothingEnabled(){return this._state.imageSmoothingEnabled}set imageSmoothingEnabled(e){this._state.imageSmoothingEnabled=!!e}get imageSmoothingQuality(){return this._state.imageSmoothingQuality}set imageSmoothingQuality(e){(e===`low`||e===`medium`||e===`high`)&&(this._state.imageSmoothingQuality=e)}setLineDash(e){e.some(e=>e<0||!isFinite(e))||(this._state.lineDash=[...e])}getLineDash(){return[...this._state.lineDash]}get lineDashOffset(){return this._state.lineDashOffset}set lineDashOffset(e){isFinite(e)&&(this._state.lineDashOffset=e)}get shadowColor(){return this._state.shadowColor}set shadowColor(e){this._state.shadowColor=e}get shadowBlur(){return this._state.shadowBlur}set shadowBlur(e){e>=0&&isFinite(e)&&(this._state.shadowBlur=e)}get shadowOffsetX(){return this._state.shadowOffsetX}set shadowOffsetX(e){isFinite(e)&&(this._state.shadowOffsetX=e)}get shadowOffsetY(){return this._state.shadowOffsetY}set shadowOffsetY(e){isFinite(e)&&(this._state.shadowOffsetY=e)}get font(){return this._state.font}set font(e){this._state.font=e}get textAlign(){return this._state.textAlign}set textAlign(e){this._state.textAlign=e}get textBaseline(){return this._state.textBaseline}set textBaseline(e){this._state.textBaseline=e}get direction(){return this._state.direction}set direction(e){this._state.direction=e}beginPath(){this._ensureSurface(),this._ctx.newPath()}moveTo(e,t){this._ensureSurface(),this._ctx.moveTo(e,t)}lineTo(e,t){this._ensureSurface(),this._ctx.lineTo(e,t)}closePath(){this._ensureSurface(),this._ctx.closePath()}bezierCurveTo(e,t,n,r,i,a){this._ensureSurface(),this._ctx.curveTo(e,t,n,r,i,a)}quadraticCurveTo(e,t,n,r){this._ensureSurface();let i,a;this._ctx.hasCurrentPoint()?[i,a]=this._ctx.getCurrentPoint():(i=e,a=t);let{cp1x:o,cp1y:c,cp2x:l,cp2y:u}=s(i,a,e,t,n,r);this._ctx.curveTo(o,c,l,u,n,r)}arc(e,t,n,r,i,a=!1){if(this._ensureSurface(),Math.abs(i-r)>=2*Math.PI){this._ctx.arc(e,t,n,0,2*Math.PI);return}a?this._ctx.arcNegative(e,t,n,r,i):this._ctx.arc(e,t,n,r,i)}arcTo(e,t,n,r,a){this._ensureSurface();let o,s;this._ctx.hasCurrentPoint()?[o,s]=this._ctx.getCurrentPoint():(o=e,s=t,this._ctx.moveTo(e,t)),i(this._ctx,o,s,e,t,n,r,a)}ellipse(e,t,n,r,i,o,s,c=!1){if(this._ensureSurface(),n<0||r<0)throw RangeError(`The radii provided are negative`);a(this._ctx,e,t,n,r,i,o,s,c)}rect(e,t,n,r){this._ensureSurface(),this._ctx.rectangle(e,t,n,r)}roundRect(e,t,n,r,i=0){this._ensureSurface(),o(this._ctx,e,t,n,r,i)}fill(e,t){this._ensureSurface(),this._applyCompositing(),this._applyFillStyle();let n;e instanceof u?(this._ctx.newPath(),e._replayOnCairo(this._ctx),n=t):n=e,this._ctx.setFillRule(n===`evenodd`?_.FillRule.EVEN_ODD:_.FillRule.WINDING),this._ctx.fillPreserve()}stroke(e){this._ensureSurface(),this._applyCompositing(),this._applyStrokeStyle(),this._applyLineStyle(),e instanceof u&&(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(_.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,t){this._ensureSurface();let n;e instanceof u?(this._ctx.newPath(),e._replayOnCairo(this._ctx),n=t):n=e,this._ctx.setFillRule(n===`evenodd`?_.FillRule.EVEN_ODD:_.FillRule.WINDING),this._ctx.clip()}isPointInPath(e,t,n,r){this._ensureSurface();let i,a,o;return e instanceof u?(this._ctx.newPath(),e._replayOnCairo(this._ctx),i=t,a=n,o=r):(i=e,a=t,o=n),this._ctx.setFillRule(o===`evenodd`?_.FillRule.EVEN_ODD:_.FillRule.WINDING),this._ctx.inFill(i,a)}isPointInStroke(e,t,n){return this._ensureSurface(),this._applyLineStyle(),e instanceof u?(this._ctx.newPath(),e._replayOnCairo(this._ctx),this._ctx.inStroke(t,n)):this._ctx.inStroke(e,t)}createLinearGradient(e,t,n,r){return new l(`linear`,e,t,n,r)}createRadialGradient(e,t,n,r,i,a){return new l(`radial`,e,t,r,i,n,a)}createPattern(e,t){return p.create(e,t)}createImageData(e,t){return typeof e==`number`?new g(Math.abs(e),Math.abs(t)):new g(e.width,e.height)}getImageData(e,t,n,r){this._ensureSurface(),this._surface.flush();let i=v.pixbuf_get_from_surface(this._surface,e,t,n,r);if(!i)return new g(n,r);let a=i.get_pixels(),o=i.get_has_alpha(),s=i.get_rowstride(),c=i.get_n_channels(),l=new Uint8ClampedArray(n*r*4);for(let e=0;e<r;e++)for(let t=0;t<n;t++){let r=e*s+t*c,i=(e*n+t)*4;l[i]=a[r],l[i+1]=a[r+1],l[i+2]=a[r+2],l[i+3]=o?a[r+3]:255}return new g(l,n,r)}putImageData(e,t,n,r,i,a,o){this._ensureSurface();let s=r??0,c=i??0,l=a??e.width,u=o??e.height,d=e.data,f=e.width,p=new Uint8Array(l*u*4);for(let e=0;e<u;e++)for(let t=0;t<l;t++){let n=((c+e)*f+(s+t))*4,r=(e*l+t)*4;p[r]=d[n],p[r+1]=d[n+1],p[r+2]=d[n+2],p[r+3]=d[n+3]}let m=y.Pixbuf.new_from_bytes(p,y.Colorspace.RGB,!0,8,l,u,l*4);this._ctx.save(),this._ctx.setOperator(_.Operator.SOURCE),v.cairo_set_source_pixbuf(this._ctx,m,t+s,n+c),this._ctx.rectangle(t+s,n+c,l,u),this._ctx.fill(),this._ctx.restore()}drawImage(t,n,r,i,a,o,s,c,l){this._ensureSurface(),this._applyCompositing();let u,d,f,p,m,h,g,y,b=this._getDrawImageSource(t);if(!b)return;let{pixbuf:x,imgWidth:S,imgHeight:C}=b;if(i===void 0?(u=0,d=0,f=S,p=C,m=n,h=r,g=S,y=C):o===void 0?(u=0,d=0,f=S,p=C,m=n,h=r,g=i,y=a):(u=n,d=r,f=i,p=a,m=o,h=s,g=c,y=l),!Number.isFinite(u)||!Number.isFinite(d)||!Number.isFinite(f)||!Number.isFinite(p)||!Number.isFinite(m)||!Number.isFinite(h)||!Number.isFinite(g)||!Number.isFinite(y)||f===0||p===0||g===0||y===0)return;this._ctx.save(),this._ctx.rectangle(m,h,g,y),this._ctx.clip(),this._ctx.translate(m,h),this._ctx.scale(g/f,y/p),this._ctx.translate(-u,-d),v.cairo_set_source_pixbuf(this._ctx,x,0,0);let w=e(this._ctx.getSource?.());if(w){let e;e=this._state.imageSmoothingEnabled?this._state.imageSmoothingQuality===`high`?_.Filter.BEST:_.Filter.BILINEAR:_.Filter.NEAREST,w.setFilter(e)}this._state.globalAlpha<1?this._ctx.paintWithAlpha(this._state.globalAlpha):this._ctx.paint(),this._ctx.restore()}_getDrawImageSource(e){if(f(e)){let t=e._pixbuf;return{pixbuf:t,imgWidth:t.get_width(),imgHeight:t.get_height()}}if(d(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 i=v.pixbuf_get_from_surface(e,0,0,t,n);if(i)return{pixbuf:i,imgWidth:t,imgHeight:n}}}return null}_createTextLayout(e){let t=x.create_layout(this._ctx);t.set_text(e,-1),t.get_context().set_base_dir(b.Direction.LTR),t.context_changed();let n=this._parseFontToDescription(this._state.font);return t.set_font_description(n),t}_parseFontToDescription(e){let t=e.match(/^\s*(italic|oblique|normal)?\s*(small-caps|normal)?\s*(bold|bolder|lighter|[1-9]00|normal)?\s*(\d+(?:\.\d+)?)(px|pt|em|rem|%)?\s*(?:\/\S+)?\s*(.+)?$/i);if(!t)return b.font_description_from_string(e);let n=t[1]||``,r=t[3]||``,i=parseFloat(t[4])||10,a=(t[5]||`px`).toLowerCase(),o=(t[6]||`sans-serif`).replace(/['"]/g,``).trim();a===`pt`?i=i*96/72:a===`em`||a===`rem`?i*=16:a===`%`&&(i=i/100*16);let s=o;n===`italic`?s+=` Italic`:n===`oblique`&&(s+=` Oblique`),r===`bold`||r===`bolder`||parseInt(r)>=600?s+=` Bold`:(r===`lighter`||parseInt(r)>0&&parseInt(r)<=300)&&(s+=` Light`);let c=b.font_description_from_string(s);return c.set_absolute_size(i*b.SCALE),c}_getTextAlignOffset(e){let[,t]=e.get_pixel_extents(),n=t.width;switch(this._state.textAlign){case`center`:return-n/2;case`right`:case`end`:return-n;default:return 0}}_getTextBaselineOffset(e){let t=e.get_font_description()||this._parseFontToDescription(this._state.font),n=e.get_context().get_metrics(t,null),r=n.get_ascent()/b.SCALE,i=n.get_descent()/b.SCALE,a=r+i;switch(this._state.textBaseline){case`top`:return 0;case`hanging`:return-(r*.2);case`middle`:return-(a/2);case`alphabetic`:return-r;case`ideographic`:return-(r+i*.5);case`bottom`:return-a;default:return-r}}fillText(e,t,n,r){this._ensureSurface(),this._applyCompositing();let i=this._createTextLayout(e),a=this._getTextAlignOffset(i),o=this._getTextBaselineOffset(i);if(this._hasShadow()){let e=c(this._state.shadowColor);if(e){let[r,s]=this._deviceToUserDistance(this._state.shadowOffsetX,this._state.shadowOffsetY),c=this._state.shadowBlur,l;if(c>0){let[t]=this._deviceToUserDistance(c,0),[,n]=this._deviceToUserDistance(0,c);l=[[r,s,e.a],[r+t,s,e.a*.5],[r-t,s,e.a*.5],[r,s+n,e.a*.5],[r,s-n,e.a*.5]]}else l=[[r,s,e.a]];let u=this._state.imageSmoothingEnabled?_.Antialias.DEFAULT:_.Antialias.NONE;for(let[r,s,c]of l)this._ctx.save(),this._ctx.setAntialias(u),this._ctx.setSourceRGBA(e.r,e.g,e.b,c),this._ctx.moveTo(t+a+r,n+o+s),x.show_layout(this._ctx,i),this._ctx.restore()}}this._applyFillStyle(),this._ctx.save(),this._ctx.setAntialias(this._state.imageSmoothingEnabled?_.Antialias.DEFAULT:_.Antialias.NONE),this._ctx.moveTo(t+a,n+o),x.show_layout(this._ctx,i),this._ctx.restore()}strokeText(e,t,n,r){this._ensureSurface(),this._applyCompositing(),this._applyStrokeStyle(),this._applyLineStyle();let i=this._createTextLayout(e),a=this._getTextAlignOffset(i),o=this._getTextBaselineOffset(i);this._ctx.save(),this._ctx.setAntialias(this._state.imageSmoothingEnabled?_.Antialias.DEFAULT:_.Antialias.NONE),this._ctx.moveTo(t+a,n+o),x.layout_path(this._ctx,i),this._ctx.stroke(),this._ctx.restore()}measureText(e){this._ensureSurface();let t=this._createTextLayout(e),[n,r]=t.get_pixel_extents(),i=t.get_baseline()/b.SCALE,a=Math.max(0,i-n.y),o=Math.max(0,n.y+n.height-i),s=t.get_font_description()||this._parseFontToDescription(this._state.font),c=t.get_context().get_metrics(s,null),l=c.get_ascent()/b.SCALE,u=c.get_descent()/b.SCALE;return{width:r.width,actualBoundingBoxAscent:a,actualBoundingBoxDescent:o,actualBoundingBoxLeft:Math.max(0,-n.x),actualBoundingBoxRight:n.x+n.width,fontBoundingBoxAscent:l,fontBoundingBoxDescent:u,alphabeticBaseline:0,emHeightAscent:l,emHeightDescent:u,hangingBaseline:l*.8,ideographicBaseline:-u}}_toDataURL(e,t){this._surface.flush();let n=imports.gi.Gio,r=imports.gi.GLib,[,i]=r.file_open_tmp(`canvas-XXXXXX.png`);try{this._surface.writeToPNG(i);let[,e]=n.File.new_for_path(i).load_contents(null);return`data:image/png;base64,${r.base64_encode(e)}`}finally{try{r.unlink(i)}catch{}}}_dispose(){this._ctx.$dispose(),this._surface.finish()}};export{CanvasRenderingContext2D};
1
+ import"./_virtual/_rolldown/runtime.js";import{asCairoPattern as e}from"./cairo-types.js";import{COMPOSITE_OP_MAP as t,LINE_CAP_MAP as n,LINE_JOIN_MAP as r}from"./cairo-utils.js";import{parseColor as i}from"./color.js";import{CanvasGradient as a}from"./canvas-gradient.js";import{CanvasPattern as o}from"./canvas-pattern.js";import{installAllContextMethods as s}from"./context/index.js";import{cloneState as c,createDefaultState as l}from"./canvas-state.js";import u from"cairo";var CanvasRenderingContext2D=class{constructor(e,t){this._stateStack=[],this.canvas=e,this._surfaceWidth=e.width||300,this._surfaceHeight=e.height||150,this._surface=new u.ImageSurface(u.Format.ARGB32,this._surfaceWidth,this._surfaceHeight),this._ctx=new u.Context(this._surface),this._state=l()}_ensureSurface(){let e=this.canvas.width||300,t=this.canvas.height||150;(e!==this._surfaceWidth||t!==this._surfaceHeight)&&(this._ctx.$dispose(),this._surface.finish(),this._surfaceWidth=e,this._surfaceHeight=t,this._surface=new u.ImageSurface(u.Format.ARGB32,e,t),this._ctx=new u.Context(this._surface),this._stateStack=[])}_resetState(){this._state=l(),this._stateStack=[]}_applyFillStyle(){let e=this._state.fillStyle;if(typeof e==`string`){let e=this._state.fillColor,t=e.a*this._state.globalAlpha;this._ctx.setSourceRGBA(e.r,e.g,e.b,t)}else e instanceof a?this._ctx.setSource(e._getCairoPattern()):e instanceof o&&(this._ctx.setSource(e._getCairoPattern()),this._applyPatternFilter())}_applyStrokeStyle(){let e=this._state.strokeStyle;if(typeof e==`string`){let e=this._state.strokeColor,t=e.a*this._state.globalAlpha;this._ctx.setSourceRGBA(e.r,e.g,e.b,t)}else e instanceof a?this._ctx.setSource(e._getCairoPattern()):e instanceof o&&(this._ctx.setSource(e._getCairoPattern()),this._applyPatternFilter())}_applyPatternFilter(){let t=e(this._ctx.getSource?.());if(!t)return;let n;n=this._state.imageSmoothingEnabled?this._state.imageSmoothingQuality===`high`?u.Filter.BEST:u.Filter.BILINEAR:u.Filter.NEAREST,t.setFilter(n)}_applyLineStyle(){this._ctx.setLineWidth(this._state.lineWidth),this._ctx.setLineCap(n[this._state.lineCap]),this._ctx.setLineJoin(r[this._state.lineJoin]),this._ctx.setMiterLimit(this._state.miterLimit),this._ctx.setDash(this._state.lineDash,this._state.lineDashOffset)}_applyCompositing(){let e=t[this._state.globalCompositeOperation];e!==void 0&&this._ctx.setOperator(e)}_getSurface(){return this._surface}_hasShadow(){if(this._state.shadowBlur===0&&this._state.shadowOffsetX===0&&this._state.shadowOffsetY===0)return!1;let e=i(this._state.shadowColor);return e!==null&&e.a>0}_deviceToUserDistance(e,t){let n=this._ctx.userToDevice(0,0),r=this._ctx.userToDevice(1,0),i=this._ctx.userToDevice(0,1),a=(r[0]??0)-(n[0]??0),o=(r[1]??0)-(n[1]??0),s=(i[0]??0)-(n[0]??0),c=(i[1]??0)-(n[1]??0),l=a*c-o*s;return Math.abs(l)<1e-10?[e,t]:[(c*e-s*t)/l,(-o*e+a*t)/l]}_renderShadow(e){}save(){this._ensureSurface(),this._stateStack.push(c(this._state)),this._ctx.save()}restore(){this._ensureSurface();let e=this._stateStack.pop();e&&(this._state=e,this._ctx.restore())}get fillStyle(){return this._state.fillStyle}set fillStyle(e){if(typeof e==`string`){let t=i(e);t&&(this._state.fillStyle=e,this._state.fillColor=t)}else this._state.fillStyle=e}get strokeStyle(){return this._state.strokeStyle}set strokeStyle(e){if(typeof e==`string`){let t=i(e);t&&(this._state.strokeStyle=e,this._state.strokeColor=t)}else this._state.strokeStyle=e}get lineWidth(){return this._state.lineWidth}set lineWidth(e){e>0&&isFinite(e)&&(this._state.lineWidth=e)}get lineCap(){return this._state.lineCap}set lineCap(e){(e===`butt`||e===`round`||e===`square`)&&(this._state.lineCap=e)}get lineJoin(){return this._state.lineJoin}set lineJoin(e){(e===`miter`||e===`round`||e===`bevel`)&&(this._state.lineJoin=e)}get miterLimit(){return this._state.miterLimit}set miterLimit(e){e>0&&isFinite(e)&&(this._state.miterLimit=e)}get globalAlpha(){return this._state.globalAlpha}set globalAlpha(e){e>=0&&e<=1&&isFinite(e)&&(this._state.globalAlpha=e)}get globalCompositeOperation(){return this._state.globalCompositeOperation}set globalCompositeOperation(e){t[e]!==void 0&&(this._state.globalCompositeOperation=e)}get imageSmoothingEnabled(){return this._state.imageSmoothingEnabled}set imageSmoothingEnabled(e){this._state.imageSmoothingEnabled=!!e}get imageSmoothingQuality(){return this._state.imageSmoothingQuality}set imageSmoothingQuality(e){(e===`low`||e===`medium`||e===`high`)&&(this._state.imageSmoothingQuality=e)}setLineDash(e){e.some(e=>e<0||!isFinite(e))||(this._state.lineDash=[...e])}getLineDash(){return[...this._state.lineDash]}get lineDashOffset(){return this._state.lineDashOffset}set lineDashOffset(e){isFinite(e)&&(this._state.lineDashOffset=e)}get shadowColor(){return this._state.shadowColor}set shadowColor(e){this._state.shadowColor=e}get shadowBlur(){return this._state.shadowBlur}set shadowBlur(e){e>=0&&isFinite(e)&&(this._state.shadowBlur=e)}get shadowOffsetX(){return this._state.shadowOffsetX}set shadowOffsetX(e){isFinite(e)&&(this._state.shadowOffsetX=e)}get shadowOffsetY(){return this._state.shadowOffsetY}set shadowOffsetY(e){isFinite(e)&&(this._state.shadowOffsetY=e)}get font(){return this._state.font}set font(e){this._state.font=e}get textAlign(){return this._state.textAlign}set textAlign(e){this._state.textAlign=e}get textBaseline(){return this._state.textBaseline}set textBaseline(e){this._state.textBaseline=e}get direction(){return this._state.direction}set direction(e){this._state.direction=e}_toDataURL(e,t){this._surface.flush();let n=imports.gi.Gio,r=imports.gi.GLib,[,i]=r.file_open_tmp(`canvas-XXXXXX.png`);try{this._surface.writeToPNG(i);let[,e]=n.File.new_for_path(i).load_contents(null);return`data:image/png;base64,${r.base64_encode(e)}`}finally{try{r.unlink(i)}catch{}}}_dispose(){this._ctx.$dispose(),this._surface.finish()}};s(CanvasRenderingContext2D.prototype);export{CanvasRenderingContext2D};
@@ -0,0 +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 from"cairo";import a from"gi://Gdk?version=4.0";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 i=a.pixbuf_get_from_surface(e,0,0,t,n);if(i)return{pixbuf:i,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`?i.FillRule.EVEN_ODD:i.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 a=this._ctx.copyPath();this._ctx.save(),this._ctx.setOperator(i.Operator.CLEAR),this._ctx.newPath(),this._ctx.rectangle(e,t,n,r),this._ctx.fill(),this._ctx.restore(),this._ctx.newPath(),this._ctx.appendPath(a)},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`?i.FillRule.EVEN_ODD:i.FillRule.WINDING),this._ctx.clip()},isPointInPath(e,n,r,a){this._ensureSurface();let o,s,c;return e instanceof t?(this._ctx.newPath(),e._replayOnCairo(this._ctx),o=n,s=r,c=a):(o=e,s=n,c=r),this._ctx.setFillRule(c===`evenodd`?i.FillRule.EVEN_ODD:i.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),a.cairo_set_source_pixbuf(this._ctx,x,0,0);let w=e(this._ctx.getSource?.());if(w){let e;e=this._state.imageSmoothingEnabled?this._state.imageSmoothingQuality===`high`?i.Filter.BEST:i.Filter.BILINEAR:i.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};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{CanvasGradient as e}from"../canvas-gradient.js";import{CanvasPattern as t}from"../canvas-pattern.js";const n={createLinearGradient(t,n,r,i){return new e(`linear`,t,n,r,i)},createRadialGradient(t,n,r,i,a,o){return new e(`radial`,t,n,i,a,r,o)},createPattern(e,n){return t.create(e,n)}};function installFactoryMethods(e){Object.assign(e,n)}export{installFactoryMethods};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{installTransformMethods as e}from"./transforms.js";import{installPathMethods as t}from"./path-ops.js";import{installDrawingMethods as n}from"./drawing.js";import{installPixelMethods as r}from"./pixels.js";import{installTextMethods as i}from"./text-rendering.js";import{installFactoryMethods as a}from"./factories.js";function installAllContextMethods(o){e(o),t(o),n(o),r(o),i(o),a(o)}export{installAllContextMethods};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{cairoArcTo as e,cairoEllipse as t,cairoRoundRect as n,quadraticToCubic as r}from"../cairo-utils.js";const i={beginPath(){this._ensureSurface(),this._ctx.newPath()},moveTo(e,t){this._ensureSurface(),this._ctx.moveTo(e,t)},lineTo(e,t){this._ensureSurface(),this._ctx.lineTo(e,t)},closePath(){this._ensureSurface(),this._ctx.closePath()},bezierCurveTo(e,t,n,r,i,a){this._ensureSurface(),this._ctx.curveTo(e,t,n,r,i,a)},quadraticCurveTo(e,t,n,i){this._ensureSurface();let a,o;this._ctx.hasCurrentPoint()?[a,o]=this._ctx.getCurrentPoint():(a=e,o=t);let{cp1x:s,cp1y:c,cp2x:l,cp2y:u}=r(a,o,e,t,n,i);this._ctx.curveTo(s,c,l,u,n,i)},arc(e,t,n,r,i,a=!1){if(this._ensureSurface(),Math.abs(i-r)>=2*Math.PI){this._ctx.arc(e,t,n,0,2*Math.PI);return}a?this._ctx.arcNegative(e,t,n,r,i):this._ctx.arc(e,t,n,r,i)},arcTo(t,n,r,i,a){this._ensureSurface();let o,s;this._ctx.hasCurrentPoint()?[o,s]=this._ctx.getCurrentPoint():(o=t,s=n,this._ctx.moveTo(t,n)),e(this._ctx,o,s,t,n,r,i,a)},ellipse(e,n,r,i,a,o,s,c=!1){if(this._ensureSurface(),r<0||i<0)throw RangeError(`The radii provided are negative`);t(this._ctx,e,n,r,i,a,o,s,c)},rect(e,t,n,r){this._ensureSurface(),this._ctx.rectangle(e,t,n,r)},roundRect(e,t,r,i,a=0){this._ensureSurface(),n(this._ctx,e,t,r,i,a)}};function installPathMethods(e){Object.assign(e,i)}export{installPathMethods};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{OurImageData as e}from"../image-data.js";import t from"cairo";import n from"gi://Gdk?version=4.0";import r from"gi://GdkPixbuf";const i={createImageData(t,n){return typeof t==`number`?new e(Math.abs(t),Math.abs(n)):new e(t.width,t.height)},getImageData(t,r,i,a){this._ensureSurface(),this._surface.flush();let o=n.pixbuf_get_from_surface(this._surface,t,r,i,a);if(!o)return new e(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 e(d,i,a)},putImageData(e,i,a,o,s,c,l){this._ensureSurface();let u=o??0,d=s??0,f=c??e.width,p=l??e.height,m=e.data,h=e.width,g=new Uint8Array(f*p*4);for(let e=0;e<p;e++)for(let t=0;t<f;t++){let n=((d+e)*h+(u+t))*4,r=(e*f+t)*4;g[r]=m[n],g[r+1]=m[n+1],g[r+2]=m[n+2],g[r+3]=m[n+3]}let _=r.Pixbuf.new_from_bytes(g,r.Colorspace.RGB,!0,8,f,p,f*4);this._ctx.save(),this._ctx.setOperator(t.Operator.SOURCE),n.cairo_set_source_pixbuf(this._ctx,_,i+u,a+d),this._ctx.rectangle(i+u,a+d,f,p),this._ctx.fill(),this._ctx.restore()}};function installPixelMethods(e){Object.assign(e,i)}export{installPixelMethods};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{parseColor as e}from"../color.js";import t from"cairo";import n from"gi://Pango";import r from"gi://PangoCairo";function parseFontToDescription(e){let t=e.match(/^\s*(italic|oblique|normal)?\s*(small-caps|normal)?\s*(bold|bolder|lighter|[1-9]00|normal)?\s*(\d+(?:\.\d+)?)(px|pt|em|rem|%)?\s*(?:\/\S+)?\s*(.+)?$/i);if(!t)return n.font_description_from_string(e);let r=t[1]||``,i=t[3]||``,a=parseFloat(t[4])||10,o=(t[5]||`px`).toLowerCase(),s=(t[6]||`sans-serif`).replace(/['"]/g,``).trim();o===`pt`?a=a*96/72:o===`em`||o===`rem`?a*=16:o===`%`&&(a=a/100*16);let c=s;r===`italic`?c+=` Italic`:r===`oblique`&&(c+=` Oblique`),i===`bold`||i===`bolder`||parseInt(i)>=600?c+=` Bold`:(i===`lighter`||parseInt(i)>0&&parseInt(i)<=300)&&(c+=` Light`);let l=n.font_description_from_string(c);return l.set_absolute_size(a*n.SCALE),l}function createTextLayout(e,t){let i=r.create_layout(e._ctx);i.set_text(t,-1),i.get_context().set_base_dir(n.Direction.LTR),i.context_changed();let a=parseFontToDescription(e._state.font);return i.set_font_description(a),i}function getTextAlignOffset(e,t){let[,n]=t.get_pixel_extents(),r=n.width;switch(e._state.textAlign){case`center`:return-r/2;case`right`:case`end`:return-r;default:return 0}}function getTextBaselineOffset(e,t){let r=t.get_font_description()||parseFontToDescription(e._state.font),i=t.get_context().get_metrics(r,null),a=i.get_ascent()/n.SCALE,o=i.get_descent()/n.SCALE,s=a+o;switch(e._state.textBaseline){case`top`:return 0;case`hanging`:return-(a*.2);case`middle`:return-(s/2);case`alphabetic`:return-a;case`ideographic`:return-(a+o*.5);case`bottom`:return-s;default:return-a}}const i={fillText(n,i,a,o){this._ensureSurface(),this._applyCompositing();let s=createTextLayout(this,n),c=getTextAlignOffset(this,s),l=getTextBaselineOffset(this,s);if(this._hasShadow()){let n=e(this._state.shadowColor);if(n){let[e,o]=this._deviceToUserDistance(this._state.shadowOffsetX,this._state.shadowOffsetY),u=this._state.shadowBlur,d;if(u>0){let[t]=this._deviceToUserDistance(u,0),[,r]=this._deviceToUserDistance(0,u);d=[[e,o,n.a],[e+t,o,n.a*.5],[e-t,o,n.a*.5],[e,o+r,n.a*.5],[e,o-r,n.a*.5]]}else d=[[e,o,n.a]];let f=this._state.imageSmoothingEnabled?t.Antialias.DEFAULT:t.Antialias.NONE;for(let[e,t,o]of d)this._ctx.save(),this._ctx.setAntialias(f),this._ctx.setSourceRGBA(n.r,n.g,n.b,o),this._ctx.moveTo(i+c+e,a+l+t),r.show_layout(this._ctx,s),this._ctx.restore()}}this._applyFillStyle(),this._ctx.save(),this._ctx.setAntialias(this._state.imageSmoothingEnabled?t.Antialias.DEFAULT:t.Antialias.NONE),this._ctx.moveTo(i+c,a+l),r.show_layout(this._ctx,s),this._ctx.restore()},strokeText(e,n,i,a){this._ensureSurface(),this._applyCompositing(),this._applyStrokeStyle(),this._applyLineStyle();let o=createTextLayout(this,e),s=getTextAlignOffset(this,o),c=getTextBaselineOffset(this,o);this._ctx.save(),this._ctx.setAntialias(this._state.imageSmoothingEnabled?t.Antialias.DEFAULT:t.Antialias.NONE),this._ctx.moveTo(n+s,i+c),r.layout_path(this._ctx,o),this._ctx.stroke(),this._ctx.restore()},measureText(e){this._ensureSurface();let t=createTextLayout(this,e),[r,i]=t.get_pixel_extents(),a=t.get_baseline()/n.SCALE,o=Math.max(0,a-r.y),s=Math.max(0,r.y+r.height-a),c=t.get_font_description()||parseFontToDescription(this._state.font),l=t.get_context().get_metrics(c,null),u=l.get_ascent()/n.SCALE,d=l.get_descent()/n.SCALE;return{width:i.width,actualBoundingBoxAscent:o,actualBoundingBoxDescent:s,actualBoundingBoxLeft:Math.max(0,-r.x),actualBoundingBoxRight:r.x+r.width,fontBoundingBoxAscent:u,fontBoundingBoxDescent:d,alphabeticBaseline:0,emHeightAscent:u,emHeightDescent:d,hangingBaseline:u*.8,ideographicBaseline:-d}}};function installTextMethods(e){Object.assign(e,i)}export{installTextMethods};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";const e={translate(e,t){this._ensureSurface(),this._ctx.translate(e,t)},rotate(e){this._ensureSurface(),this._ctx.rotate(e)},scale(e,t){this._ensureSurface(),this._ctx.scale(e,t)},transform(e,t,n,r,i,a){if(this._ensureSurface(),!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(i)||!Number.isFinite(a))return;let o=i,s=a,c=Math.hypot(e,t),l=Math.hypot(n,r),u=Math.atan2(t,e);this._ctx.translate(o,s),u!==0&&this._ctx.rotate(u),(c!==1||l!==1)&&this._ctx.scale(c,l)},setTransform(e,t,n,r,i,a){if(this._ensureSurface(),typeof e==`object`&&e){let t=e;this._ctx.identityMatrix(),this.transform(t.a??t.m11??1,t.b??t.m12??0,t.c??t.m21??0,t.d??t.m22??1,t.e??t.m41??0,t.f??t.m42??0)}else typeof e==`number`?(this._ctx.identityMatrix(),this.transform(e,t,n,r,i,a)):this._ctx.identityMatrix()},getTransform(){let e=this._ctx.userToDevice(0,0),t=this._ctx.userToDevice(1,0),n=this._ctx.userToDevice(0,1),r=e[0]??0,i=e[1]??0,a=(t[0]??0)-r,o=(t[1]??0)-i,s=(n[0]??0)-r,c=(n[1]??0)-i,l=globalThis.DOMMatrix;return typeof l==`function`?new l([a,o,s,c,r,i]):{a,b:o,c:s,d:c,e:r,f:i,m11:a,m12:o,m13:0,m14:0,m21:s,m22:c,m23:0,m24:0,m31:0,m32:0,m33:1,m34:0,m41:r,m42:i,m43:0,m44:1,is2D:!0,isIdentity:a===1&&o===0&&s===0&&c===1&&r===0&&i===0}},resetTransform(){this._ensureSurface(),this._ctx.identityMatrix()}};function installTransformMethods(t){Object.assign(t,e)}export{installTransformMethods};
@@ -1,6 +1,7 @@
1
1
  import Cairo from 'cairo';
2
- import { type CanvasLike } from './dom-types.js';
3
- import { Path2D } from './canvas-path.js';
2
+ import './context/index.js';
3
+ import type { CanvasLike } from './dom-types.js';
4
+ import { type CanvasState } from './canvas-state.js';
4
5
  /**
5
6
  * Options bag passed through the `getContext('2d', options)` factory. Mirrors
6
7
  * the WHATWG `CanvasRenderingContext2DSettings` dictionary; fields are
@@ -18,36 +19,36 @@ export interface CanvasRenderingContext2DInit {
18
19
  */
19
20
  export declare class CanvasRenderingContext2D {
20
21
  readonly canvas: CanvasLike;
21
- private _surface;
22
- private _ctx;
23
- private _state;
24
- private _stateStack;
25
- private _surfaceWidth;
26
- private _surfaceHeight;
22
+ _surface: Cairo.ImageSurface;
23
+ _ctx: Cairo.Context;
24
+ _state: CanvasState;
25
+ _stateStack: CanvasState[];
26
+ _surfaceWidth: number;
27
+ _surfaceHeight: number;
27
28
  constructor(canvas: CanvasLike, _options?: CanvasRenderingContext2DInit);
28
29
  /** Ensure the surface matches the current canvas dimensions. Recreate if resized. */
29
- private _ensureSurface;
30
+ _ensureSurface(): void;
30
31
  /** Reset drawing state to defaults (called when canvas dimensions are explicitly reset). */
31
32
  _resetState(): void;
32
33
  /** Apply the current fill style (color, gradient, or pattern) to the Cairo context. */
33
- private _applyFillStyle;
34
+ _applyFillStyle(): void;
34
35
  /** Apply the current stroke style to the Cairo context. */
35
- private _applyStrokeStyle;
36
+ _applyStrokeStyle(): void;
36
37
  /**
37
38
  * Apply the current imageSmoothingEnabled + imageSmoothingQuality state
38
39
  * to the currently installed Cairo source pattern. Per Canvas 2D spec,
39
40
  * the filter is read from the context at *draw* time, not at pattern
40
41
  * creation — so we re-apply it on every fill/stroke.
41
42
  */
42
- private _applyPatternFilter;
43
+ _applyPatternFilter(): void;
43
44
  /** Apply line properties to the Cairo context. */
44
- private _applyLineStyle;
45
+ _applyLineStyle(): void;
45
46
  /** Apply compositing operator. */
46
- private _applyCompositing;
47
+ _applyCompositing(): void;
47
48
  /** Get the Cairo ImageSurface (used by other contexts like drawImage). */
48
49
  _getSurface(): Cairo.ImageSurface;
49
50
  /** Check if shadow rendering is needed. */
50
- private _hasShadow;
51
+ _hasShadow(): boolean;
51
52
  /**
52
53
  * Convert a distance from device pixels to Cairo user space by inverting
53
54
  * the linear part of the current CTM (translation doesn't affect distances).
@@ -57,7 +58,7 @@ export declare class CanvasRenderingContext2D {
57
58
  * that `ctx.moveTo(x + sdx, y + sdy)` produces the correct pixel offset
58
59
  * regardless of any ctx.scale() or ctx.rotate() in effect.
59
60
  */
60
- private _deviceToUserDistance;
61
+ _deviceToUserDistance(dx: number, dy: number): [number, number];
61
62
  /**
62
63
  * Shadow rendering is intentionally a no-op.
63
64
  *
@@ -73,29 +74,9 @@ export declare class CanvasRenderingContext2D {
73
74
  * affect the showcase. A correct implementation is tracked as a
74
75
  * separate Canvas 2D Phase-5 enhancement.
75
76
  */
76
- private _renderShadow;
77
+ _renderShadow(_drawOp: () => void): void;
77
78
  save(): void;
78
79
  restore(): void;
79
- translate(x: number, y: number): void;
80
- rotate(angle: number): void;
81
- scale(x: number, y: number): void;
82
- /**
83
- * Multiply the current transformation matrix by the given values.
84
- * Matrix: [a c e]
85
- * [b d f]
86
- * [0 0 1]
87
- */
88
- transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
89
- /**
90
- * Reset the transform to identity, then apply the given matrix.
91
- */
92
- setTransform(matrix?: DOMMatrix2DInit): void;
93
- setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
94
- /**
95
- * Return the current transformation matrix as a DOMMatrix-like object.
96
- */
97
- getTransform(): DOMMatrix;
98
- resetTransform(): void;
99
80
  get fillStyle(): string | CanvasGradient | CanvasPattern;
100
81
  set fillStyle(value: string | CanvasGradient | CanvasPattern);
101
82
  get strokeStyle(): string | CanvasGradient | CanvasPattern;
@@ -136,63 +117,6 @@ export declare class CanvasRenderingContext2D {
136
117
  set textBaseline(value: CanvasTextBaseline);
137
118
  get direction(): CanvasDirection;
138
119
  set direction(value: CanvasDirection);
139
- beginPath(): void;
140
- moveTo(x: number, y: number): void;
141
- lineTo(x: number, y: number): void;
142
- closePath(): void;
143
- bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
144
- quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
145
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
146
- arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
147
- ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
148
- rect(x: number, y: number, w: number, h: number): void;
149
- roundRect(x: number, y: number, w: number, h: number, radii?: number | number[]): void;
150
- fill(fillRule?: CanvasFillRule): void;
151
- fill(path: Path2D, fillRule?: CanvasFillRule): void;
152
- stroke(): void;
153
- stroke(path: Path2D): void;
154
- fillRect(x: number, y: number, w: number, h: number): void;
155
- strokeRect(x: number, y: number, w: number, h: number): void;
156
- clearRect(x: number, y: number, w: number, h: number): void;
157
- clip(fillRule?: CanvasFillRule): void;
158
- clip(path: Path2D, fillRule?: CanvasFillRule): void;
159
- isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;
160
- isPointInPath(path: Path2D, x: number, y: number, fillRule?: CanvasFillRule): boolean;
161
- isPointInStroke(x: number, y: number): boolean;
162
- isPointInStroke(path: Path2D, x: number, y: number): boolean;
163
- createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
164
- createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
165
- createPattern(image: unknown, repetition: string | null): CanvasPattern | null;
166
- createImageData(sw: number, sh: number): ImageData;
167
- createImageData(imagedata: ImageData): ImageData;
168
- getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;
169
- putImageData(imageData: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;
170
- drawImage(image: unknown, dx: number, dy: number): void;
171
- drawImage(image: unknown, dx: number, dy: number, dw: number, dh: number): void;
172
- drawImage(image: unknown, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
173
- private _getDrawImageSource;
174
- /** Create a PangoCairo layout configured with current font/text settings. */
175
- private _createTextLayout;
176
- /** Parse a CSS font string (e.g. "bold 16px Arial") into a Pango.FontDescription. */
177
- private _parseFontToDescription;
178
- /**
179
- * Compute the x-offset for text alignment relative to the given x coordinate.
180
- */
181
- private _getTextAlignOffset;
182
- /**
183
- * Compute the y-offset for text baseline positioning.
184
- *
185
- * PangoCairo.show_layout() places the layout TOP-LEFT at the current Cairo point
186
- * (not the baseline). Within the layout, the first line's baseline is at
187
- * approximately `ascent` pixels below the layout top.
188
- *
189
- * For CSS textBaseline semantics, we shift the current point UP (negative offset)
190
- * so the layout top lands at the right position relative to the user's y coordinate.
191
- */
192
- private _getTextBaselineOffset;
193
- fillText(text: string, x: number, y: number, _maxWidth?: number): void;
194
- strokeText(text: string, x: number, y: number, _maxWidth?: number): void;
195
- measureText(text: string): TextMetrics;
196
120
  /**
197
121
  * Write the canvas surface to a PNG file and return as data URL.
198
122
  * Used by HTMLCanvasElement.toDataURL() when a '2d' context is active.
@@ -0,0 +1,25 @@
1
+ import { Path2D } from '../canvas-path.js';
2
+ export interface DrawingMethods {
3
+ fill(fillRule?: CanvasFillRule): void;
4
+ fill(path: Path2D, fillRule?: CanvasFillRule): void;
5
+ stroke(): void;
6
+ stroke(path: Path2D): void;
7
+ fillRect(x: number, y: number, w: number, h: number): void;
8
+ strokeRect(x: number, y: number, w: number, h: number): void;
9
+ clearRect(x: number, y: number, w: number, h: number): void;
10
+ clip(fillRule?: CanvasFillRule): void;
11
+ clip(path: Path2D, fillRule?: CanvasFillRule): void;
12
+ isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;
13
+ isPointInPath(path: Path2D, x: number, y: number, fillRule?: CanvasFillRule): boolean;
14
+ isPointInStroke(x: number, y: number): boolean;
15
+ isPointInStroke(path: Path2D, x: number, y: number): boolean;
16
+ drawImage(image: unknown, dx: number, dy: number): void;
17
+ drawImage(image: unknown, dx: number, dy: number, dw: number, dh: number): void;
18
+ drawImage(image: unknown, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
19
+ }
20
+ declare module '../canvas-rendering-context-2d.js' {
21
+ interface CanvasRenderingContext2D extends DrawingMethods {
22
+ }
23
+ }
24
+ /** Install drawing methods on CanvasRenderingContext2D.prototype. */
25
+ export declare function installDrawingMethods(proto: object): void;
@@ -0,0 +1,11 @@
1
+ export interface FactoryMethods {
2
+ createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;
3
+ createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;
4
+ createPattern(image: unknown, repetition: string | null): CanvasPattern | null;
5
+ }
6
+ declare module '../canvas-rendering-context-2d.js' {
7
+ interface CanvasRenderingContext2D extends FactoryMethods {
8
+ }
9
+ }
10
+ /** Install gradient / pattern factory methods on CanvasRenderingContext2D.prototype. */
11
+ export declare function installFactoryMethods(proto: object): void;
@@ -0,0 +1,7 @@
1
+ export type { TransformMethods } from './transforms.js';
2
+ export type { PathMethods } from './path-ops.js';
3
+ export type { DrawingMethods } from './drawing.js';
4
+ export type { PixelMethods } from './pixels.js';
5
+ export type { TextMethods } from './text-rendering.js';
6
+ export type { FactoryMethods } from './factories.js';
7
+ export declare function installAllContextMethods(proto: object): void;
@@ -0,0 +1,19 @@
1
+ export interface PathMethods {
2
+ beginPath(): void;
3
+ moveTo(x: number, y: number): void;
4
+ lineTo(x: number, y: number): void;
5
+ closePath(): void;
6
+ bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
7
+ quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
8
+ arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
9
+ arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
10
+ ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
11
+ rect(x: number, y: number, w: number, h: number): void;
12
+ roundRect(x: number, y: number, w: number, h: number, radii?: number | number[]): void;
13
+ }
14
+ declare module '../canvas-rendering-context-2d.js' {
15
+ interface CanvasRenderingContext2D extends PathMethods {
16
+ }
17
+ }
18
+ /** Install path-construction methods on CanvasRenderingContext2D.prototype. */
19
+ export declare function installPathMethods(proto: object): void;
@@ -0,0 +1,12 @@
1
+ export interface PixelMethods {
2
+ createImageData(sw: number, sh: number): ImageData;
3
+ createImageData(imagedata: ImageData): ImageData;
4
+ getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;
5
+ putImageData(imageData: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;
6
+ }
7
+ declare module '../canvas-rendering-context-2d.js' {
8
+ interface CanvasRenderingContext2D extends PixelMethods {
9
+ }
10
+ }
11
+ /** Install pixel-ops (ImageData) methods on CanvasRenderingContext2D.prototype. */
12
+ export declare function installPixelMethods(proto: object): void;
@@ -0,0 +1,11 @@
1
+ export interface TextMethods {
2
+ fillText(text: string, x: number, y: number, maxWidth?: number): void;
3
+ strokeText(text: string, x: number, y: number, maxWidth?: number): void;
4
+ measureText(text: string): TextMetrics;
5
+ }
6
+ declare module '../canvas-rendering-context-2d.js' {
7
+ interface CanvasRenderingContext2D extends TextMethods {
8
+ }
9
+ }
10
+ /** Install text-rendering methods on CanvasRenderingContext2D.prototype. */
11
+ export declare function installTextMethods(proto: object): void;
@@ -0,0 +1,16 @@
1
+ export interface TransformMethods {
2
+ translate(x: number, y: number): void;
3
+ rotate(angle: number): void;
4
+ scale(x: number, y: number): void;
5
+ transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
6
+ setTransform(matrix?: DOMMatrix2DInit): void;
7
+ setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
8
+ getTransform(): DOMMatrix;
9
+ resetTransform(): void;
10
+ }
11
+ declare module '../canvas-rendering-context-2d.js' {
12
+ interface CanvasRenderingContext2D extends TransformMethods {
13
+ }
14
+ }
15
+ /** Install transform methods on CanvasRenderingContext2D.prototype. */
16
+ export declare function installTransformMethods(proto: object): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/canvas2d-core",
3
- "version": "0.4.21",
3
+ "version": "0.4.22",
4
4
  "description": "Cairo-backed Canvas 2D core (CanvasRenderingContext2D, Path2D, ImageData) — no GTK dependency",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -34,19 +34,19 @@
34
34
  "offscreen"
35
35
  ],
36
36
  "dependencies": {
37
- "@girs/gdk-4.0": "4.0.0-4.0.0-rc.15",
38
- "@girs/gdkpixbuf-2.0": "2.0.0-4.0.0-rc.15",
39
- "@girs/gjs": "4.0.0-rc.15",
40
- "@girs/glib-2.0": "2.88.0-4.0.0-rc.15",
41
- "@girs/gobject-2.0": "2.88.0-4.0.0-rc.15",
42
- "@girs/pango-1.0": "1.57.1-4.0.0-rc.15",
43
- "@girs/pangocairo-1.0": "1.0.0-4.0.0-rc.15"
37
+ "@girs/gdk-4.0": "4.0.0-4.0.1",
38
+ "@girs/gdkpixbuf-2.0": "2.0.0-4.0.1",
39
+ "@girs/gjs": "4.0.1",
40
+ "@girs/glib-2.0": "2.88.0-4.0.1",
41
+ "@girs/gobject-2.0": "2.88.0-4.0.1",
42
+ "@girs/pango-1.0": "1.57.1-4.0.1",
43
+ "@girs/pangocairo-1.0": "1.0.0-4.0.1"
44
44
  },
45
45
  "devDependencies": {
46
- "@gjsify/cli": "^0.4.21",
47
- "@gjsify/dom-elements": "^0.4.21",
48
- "@gjsify/unit": "^0.4.21",
49
- "@types/node": "^25.6.2",
46
+ "@gjsify/cli": "^0.4.22",
47
+ "@gjsify/dom-elements": "^0.4.22",
48
+ "@gjsify/unit": "^0.4.22",
49
+ "@types/node": "^25.9.1",
50
50
  "typescript": "^6.0.3"
51
51
  }
52
52
  }