├── .gitignore ├── assembly ├── util │ ├── index.ts │ └── TypedArray.ts ├── renderer │ ├── CanvasPattern.ts │ ├── index.ts │ ├── CanvasGradient.ts │ ├── Serializer.ts │ ├── CanvasRenderingContext2DSerializer.ts │ └── CanvasRenderingContext2D.ts ├── tsconfig.json ├── primitives │ ├── index.ts │ ├── Path2DElement.ts │ ├── ImageData.ts │ ├── TextureMap.ts │ ├── Image.ts │ ├── FillStrokeWhichValue.ts │ ├── Matrix.ts │ └── CanvasMap.ts ├── linked │ ├── index.ts │ └── util.ts ├── example.ts └── index.ts ├── .babelrc ├── src ├── shared │ ├── FillRule.ts │ ├── Direction.ts │ ├── LineCap.ts │ ├── LineJoin.ts │ ├── ImageSmoothingQuality.ts │ ├── CanvasPatternType.ts │ ├── TextAlign.ts │ ├── TextBaseline.ts │ ├── index.ts │ ├── GlobalCompositeOperation.ts │ └── CanvasInstruction.ts ├── interop │ ├── index.ts │ ├── canvasInterop.ts │ └── CanvasASInterop.ts ├── index.ts └── util │ ├── IStringIndex.ts │ ├── IImageBitmapIndex.ts │ ├── ICanvasGradientIndex.ts │ ├── ImageLoadedCallbacks.ts │ ├── ICanvasPatternIndex.ts │ ├── index.ts │ └── GlobalCompositeOperationLookup.ts ├── dist ├── interop │ ├── index.d.ts │ ├── index.js.map │ ├── index.d.ts.map │ ├── index.js │ ├── canvasInterop.d.ts.map │ ├── canvasInterop.d.ts │ ├── canvasInterop.js.map │ ├── CanvasASInterop.d.ts.map │ ├── canvasInterop.js │ ├── CanvasASInterop.d.ts │ ├── CanvasASInterop.js.map │ └── CanvasASInterop.js ├── index.d.ts ├── shared │ ├── FillRule.d.ts │ ├── LineCap.d.ts │ ├── CanvasInstruction.js │ ├── CanvasPatternType.js │ ├── Direction.d.ts │ ├── LineJoin.d.ts │ ├── CanvasInstruction.js.map │ ├── CanvasPatternType.js.map │ ├── FillRule.d.ts.map │ ├── ImageSmoothingQuality.d.ts │ ├── TextAlign.d.ts │ ├── LineCap.d.ts.map │ ├── LineJoin.d.ts.map │ ├── Direction.d.ts.map │ ├── CanvasPatternType.d.ts │ ├── TextBaseline.d.ts │ ├── TextAlign.d.ts.map │ ├── ImageSmoothingQuality.d.ts.map │ ├── CanvasPatternType.d.ts.map │ ├── FillRule.js.map │ ├── LineCap.js.map │ ├── LineJoin.js.map │ ├── TextBaseline.d.ts.map │ ├── Direction.js.map │ ├── TextAlign.js.map │ ├── ImageSmoothingQuality.js.map │ ├── TextBaseline.js.map │ ├── FillRule.js │ ├── LineCap.js │ ├── LineJoin.js │ ├── Direction.js │ ├── index.js.map │ ├── TextAlign.js │ ├── index.d.ts.map │ ├── ImageSmoothingQuality.js │ ├── index.d.ts │ ├── GlobalCompositeOperation.d.ts.map │ ├── TextBaseline.js │ ├── GlobalCompositeOperation.js.map │ ├── GlobalCompositeOperation.d.ts │ ├── CanvasInstruction.d.ts.map │ ├── index.js │ ├── CanvasInstruction.d.ts │ └── GlobalCompositeOperation.js ├── util │ ├── IStringIndex.d.ts │ ├── IStringIndex.js │ ├── IStringIndex.js.map │ ├── IImageBitmapIndex.js │ ├── index.js.map │ ├── ICanvasGradientIndex.js │ ├── IImageBitmapIndex.js.map │ ├── ImageLoadedCallbacks.js │ ├── IImageBitmapIndex.d.ts │ ├── ICanvasGradientIndex.js.map │ ├── ImageLoadedCallbacks.js.map │ ├── ICanvasGradientIndex.d.ts │ ├── IStringIndex.d.ts.map │ ├── IImageBitmapIndex.d.ts.map │ ├── ICanvasGradientIndex.d.ts.map │ ├── ImageLoadedCallbacks.d.ts │ ├── index.d.ts.map │ ├── ICanvasPatternIndex.d.ts.map │ ├── ICanvasPatternIndex.js.map │ ├── ICanvasPatternIndex.js │ ├── index.d.ts │ ├── ICanvasPatternIndex.d.ts │ ├── ImageLoadedCallbacks.d.ts.map │ ├── index.js │ ├── GlobalCompositeOperationLookup.d.ts.map │ ├── GlobalCompositeOperationLookup.js.map │ ├── GlobalCompositeOperationLookup.d.ts │ └── GlobalCompositeOperationLookup.js ├── index.js.map ├── index.d.ts.map ├── index.js └── bundle.js ├── demo-src ├── index.html └── index.js ├── rollup.config.js ├── LICENSE ├── package.json ├── tsconfig.json └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | demo 4 | .rts* -------------------------------------------------------------------------------- /assembly/util/index.ts: -------------------------------------------------------------------------------- 1 | export { copyTypedArray, doubleTypedArray } from "./TypedArray"; -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/typescript", 4 | "@babel/env" 5 | ] 6 | } -------------------------------------------------------------------------------- /src/shared/FillRule.ts: -------------------------------------------------------------------------------- 1 | export enum FillRule { 2 | nonzero = 0, 3 | evenodd = 1, 4 | } 5 | -------------------------------------------------------------------------------- /src/interop/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./CanvasASInterop"; 2 | export * from "./canvasInterop"; 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./interop"; 2 | export * from "./util"; 3 | export * from "./shared"; 4 | -------------------------------------------------------------------------------- /src/shared/Direction.ts: -------------------------------------------------------------------------------- 1 | export enum Direction { 2 | ltr = 0, 3 | rtl = 1, 4 | inherit = 2, 5 | } 6 | -------------------------------------------------------------------------------- /src/shared/LineCap.ts: -------------------------------------------------------------------------------- 1 | export enum LineCap { 2 | butt = 0, 3 | round = 1, 4 | square = 2, 5 | } 6 | -------------------------------------------------------------------------------- /src/shared/LineJoin.ts: -------------------------------------------------------------------------------- 1 | export enum LineJoin { 2 | bevel = 0, 3 | round = 1, 4 | miter = 2, 5 | } 6 | -------------------------------------------------------------------------------- /src/util/IStringIndex.ts: -------------------------------------------------------------------------------- 1 | export interface IStringIndex { 2 | [index: number]: string | null; 3 | } 4 | -------------------------------------------------------------------------------- /src/util/IImageBitmapIndex.ts: -------------------------------------------------------------------------------- 1 | export interface IImageBitmapIndex { 2 | [index: number]: ImageBitmap | null; 3 | } 4 | -------------------------------------------------------------------------------- /assembly/renderer/CanvasPattern.ts: -------------------------------------------------------------------------------- 1 | var id: i32 = 0; 2 | export class CanvasPattern { 3 | public _id: i32 = id++; 4 | } 5 | -------------------------------------------------------------------------------- /src/util/ICanvasGradientIndex.ts: -------------------------------------------------------------------------------- 1 | export interface ICanvasGradientIndex { 2 | [index: number]: CanvasGradient | null; 3 | } 4 | -------------------------------------------------------------------------------- /src/shared/ImageSmoothingQuality.ts: -------------------------------------------------------------------------------- 1 | export enum ImageSmoothingQuality { 2 | low = 0, 3 | medium = 1, 4 | high = 2, 5 | } 6 | -------------------------------------------------------------------------------- /dist/interop/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./CanvasASInterop"; 2 | export * from "./canvasInterop"; 3 | //# sourceMappingURL=index.d.ts.map -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./interop"; 2 | export * from "./util"; 3 | export * from "./shared"; 4 | //# sourceMappingURL=index.d.ts.map -------------------------------------------------------------------------------- /src/shared/CanvasPatternType.ts: -------------------------------------------------------------------------------- 1 | export const enum CanvasPatternType { 2 | repeat, 3 | repeat_x, 4 | repeat_y, 5 | no_repeat, 6 | } 7 | -------------------------------------------------------------------------------- /src/shared/TextAlign.ts: -------------------------------------------------------------------------------- 1 | export enum TextAlign { 2 | left = 0, 3 | right = 1, 4 | center = 2, 5 | start = 3, 6 | end = 4, 7 | } 8 | -------------------------------------------------------------------------------- /dist/shared/FillRule.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum FillRule { 2 | nonzero = 0, 3 | evenodd = 1 4 | } 5 | //# sourceMappingURL=FillRule.d.ts.map -------------------------------------------------------------------------------- /dist/util/IStringIndex.d.ts: -------------------------------------------------------------------------------- 1 | export interface IStringIndex { 2 | [index: number]: string | null; 3 | } 4 | //# sourceMappingURL=IStringIndex.d.ts.map -------------------------------------------------------------------------------- /dist/util/IStringIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=IStringIndex.js.map -------------------------------------------------------------------------------- /dist/util/IStringIndex.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"IStringIndex.js","sourceRoot":"","sources":["../../src/util/IStringIndex.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/shared/LineCap.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum LineCap { 2 | butt = 0, 3 | round = 1, 4 | square = 2 5 | } 6 | //# sourceMappingURL=LineCap.d.ts.map -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,+BAA0B;AAC1B,4BAAuB;AACvB,8BAAyB"} -------------------------------------------------------------------------------- /dist/shared/CanvasInstruction.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=CanvasInstruction.js.map -------------------------------------------------------------------------------- /dist/shared/CanvasPatternType.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=CanvasPatternType.js.map -------------------------------------------------------------------------------- /dist/shared/Direction.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum Direction { 2 | ltr = 0, 3 | rtl = 1, 4 | inherit = 2 5 | } 6 | //# sourceMappingURL=Direction.d.ts.map -------------------------------------------------------------------------------- /dist/shared/LineJoin.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum LineJoin { 2 | bevel = 0, 3 | round = 1, 4 | miter = 2 5 | } 6 | //# sourceMappingURL=LineJoin.d.ts.map -------------------------------------------------------------------------------- /dist/util/IImageBitmapIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=IImageBitmapIndex.js.map -------------------------------------------------------------------------------- /dist/util/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":";;;;;AAAA,sDAAiD;AAEjD,2CAAsC"} -------------------------------------------------------------------------------- /dist/interop/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/interop/index.ts"],"names":[],"mappings":";;;;;AAAA,uCAAkC;AAClC,qCAAgC"} -------------------------------------------------------------------------------- /dist/util/ICanvasGradientIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=ICanvasGradientIndex.js.map -------------------------------------------------------------------------------- /dist/util/IImageBitmapIndex.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"IImageBitmapIndex.js","sourceRoot":"","sources":["../../src/util/IImageBitmapIndex.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/util/ImageLoadedCallbacks.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=ImageLoadedCallbacks.js.map -------------------------------------------------------------------------------- /dist/shared/CanvasInstruction.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"CanvasInstruction.js","sourceRoot":"","sources":["../../src/shared/CanvasInstruction.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/shared/CanvasPatternType.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"CanvasPatternType.js","sourceRoot":"","sources":["../../src/shared/CanvasPatternType.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/util/IImageBitmapIndex.d.ts: -------------------------------------------------------------------------------- 1 | export interface IImageBitmapIndex { 2 | [index: number]: ImageBitmap | null; 3 | } 4 | //# sourceMappingURL=IImageBitmapIndex.d.ts.map -------------------------------------------------------------------------------- /dist/util/ICanvasGradientIndex.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ICanvasGradientIndex.js","sourceRoot":"","sources":["../../src/util/ICanvasGradientIndex.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/util/ImageLoadedCallbacks.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ImageLoadedCallbacks.js","sourceRoot":"","sources":["../../src/util/ImageLoadedCallbacks.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /src/shared/TextBaseline.ts: -------------------------------------------------------------------------------- 1 | export enum TextBaseline { 2 | top = 0, 3 | hanging = 1, 4 | middle = 2, 5 | alphabetic = 3, 6 | ideographic = 4, 7 | bottom = 5, 8 | } 9 | -------------------------------------------------------------------------------- /dist/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC"} -------------------------------------------------------------------------------- /dist/interop/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/interop/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"} -------------------------------------------------------------------------------- /dist/util/ICanvasGradientIndex.d.ts: -------------------------------------------------------------------------------- 1 | export interface ICanvasGradientIndex { 2 | [index: number]: CanvasGradient | null; 3 | } 4 | //# sourceMappingURL=ICanvasGradientIndex.d.ts.map -------------------------------------------------------------------------------- /dist/shared/FillRule.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"FillRule.d.ts","sourceRoot":"","sources":["../src/shared/FillRule.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAClB,OAAO,IAAI;IACX,OAAO,IAAI;CACZ"} -------------------------------------------------------------------------------- /dist/shared/ImageSmoothingQuality.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum ImageSmoothingQuality { 2 | low = 0, 3 | medium = 1, 4 | high = 2 5 | } 6 | //# sourceMappingURL=ImageSmoothingQuality.d.ts.map -------------------------------------------------------------------------------- /dist/shared/TextAlign.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum TextAlign { 2 | left = 0, 3 | right = 1, 4 | center = 2, 5 | start = 3, 6 | end = 4 7 | } 8 | //# sourceMappingURL=TextAlign.d.ts.map -------------------------------------------------------------------------------- /src/util/ImageLoadedCallbacks.ts: -------------------------------------------------------------------------------- 1 | export type ImageLoadedCallback = (imagePointer: number, width: number, height: number) => void; 2 | export type ImageUseCallback = (stringPointer: number) => number; 3 | -------------------------------------------------------------------------------- /assembly/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true 4 | }, 5 | "extends": "../node_modules/assemblyscript/std/assembly.json", 6 | "include": [ 7 | "./**/*.ts" 8 | ] 9 | } -------------------------------------------------------------------------------- /dist/shared/LineCap.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"LineCap.d.ts","sourceRoot":"","sources":["../src/shared/LineCap.ts"],"names":[],"mappings":"AAAA,oBAAY,OAAO;IACjB,IAAI,IAAI;IACR,KAAK,IAAI;IACT,MAAM,IAAI;CACX"} -------------------------------------------------------------------------------- /dist/shared/LineJoin.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"LineJoin.d.ts","sourceRoot":"","sources":["../src/shared/LineJoin.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,KAAK,IAAI;IACT,KAAK,IAAI;CACV"} -------------------------------------------------------------------------------- /dist/shared/Direction.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Direction.d.ts","sourceRoot":"","sources":["../src/shared/Direction.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,GAAG,IAAI;IACP,GAAG,IAAI;IACP,OAAO,IAAI;CACZ"} -------------------------------------------------------------------------------- /dist/shared/CanvasPatternType.d.ts: -------------------------------------------------------------------------------- 1 | export declare const enum CanvasPatternType { 2 | repeat = 0, 3 | repeat_x = 1, 4 | repeat_y = 2, 5 | no_repeat = 3 6 | } 7 | //# sourceMappingURL=CanvasPatternType.d.ts.map -------------------------------------------------------------------------------- /dist/util/IStringIndex.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"IStringIndex.d.ts","sourceRoot":"","sources":["../src/util/IStringIndex.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAChC"} -------------------------------------------------------------------------------- /dist/shared/TextBaseline.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum TextBaseline { 2 | top = 0, 3 | hanging = 1, 4 | middle = 2, 5 | alphabetic = 3, 6 | ideographic = 4, 7 | bottom = 5 8 | } 9 | //# sourceMappingURL=TextBaseline.d.ts.map -------------------------------------------------------------------------------- /dist/shared/TextAlign.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"TextAlign.d.ts","sourceRoot":"","sources":["../src/shared/TextAlign.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,IAAI;IACR,KAAK,IAAI;IACT,MAAM,IAAI;IACV,KAAK,IAAI;IACT,GAAG,IAAI;CACR"} -------------------------------------------------------------------------------- /dist/util/IImageBitmapIndex.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"IImageBitmapIndex.d.ts","sourceRoot":"","sources":["../src/util/IImageBitmapIndex.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;CACrC"} -------------------------------------------------------------------------------- /dist/shared/ImageSmoothingQuality.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ImageSmoothingQuality.d.ts","sourceRoot":"","sources":["../src/shared/ImageSmoothingQuality.ts"],"names":[],"mappings":"AAAA,oBAAY,qBAAqB;IAC/B,GAAG,IAAI;IACP,MAAM,IAAI;IACV,IAAI,IAAI;CACT"} -------------------------------------------------------------------------------- /dist/shared/CanvasPatternType.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"CanvasPatternType.d.ts","sourceRoot":"","sources":["../src/shared/CanvasPatternType.ts"],"names":[],"mappings":"AAAA,0BAAkB,iBAAiB;IACjC,MAAM,IAAA;IACN,QAAQ,IAAA;IACR,QAAQ,IAAA;IACR,SAAS,IAAA;CACV"} -------------------------------------------------------------------------------- /dist/shared/FillRule.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"FillRule.js","sourceRoot":"","sources":["../../src/shared/FillRule.ts"],"names":[],"mappings":";;AAAA,IAAY,QAGX;AAHD,WAAY,QAAQ;IAClB,6CAAW,CAAA;IACX,6CAAW,CAAA;AACb,CAAC,EAHW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAGnB"} -------------------------------------------------------------------------------- /dist/util/ICanvasGradientIndex.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ICanvasGradientIndex.d.ts","sourceRoot":"","sources":["../src/util/ICanvasGradientIndex.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;CACxC"} -------------------------------------------------------------------------------- /dist/shared/LineCap.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"LineCap.js","sourceRoot":"","sources":["../../src/shared/LineCap.ts"],"names":[],"mappings":";;AAAA,IAAY,OAIX;AAJD,WAAY,OAAO;IACjB,qCAAQ,CAAA;IACR,uCAAS,CAAA;IACT,yCAAU,CAAA;AACZ,CAAC,EAJW,OAAO,GAAP,eAAO,KAAP,eAAO,QAIlB"} -------------------------------------------------------------------------------- /dist/shared/LineJoin.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"LineJoin.js","sourceRoot":"","sources":["../../src/shared/LineJoin.ts"],"names":[],"mappings":";;AAAA,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,yCAAS,CAAA;IACT,yCAAS,CAAA;IACT,yCAAS,CAAA;AACX,CAAC,EAJW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAInB"} -------------------------------------------------------------------------------- /dist/shared/TextBaseline.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"TextBaseline.d.ts","sourceRoot":"","sources":["../src/shared/TextBaseline.ts"],"names":[],"mappings":"AAAA,oBAAY,YAAY;IACtB,GAAG,IAAI;IACP,OAAO,IAAI;IACX,MAAM,IAAI;IACV,UAAU,IAAI;IACd,WAAW,IAAI;IACf,MAAM,IAAI;CACX"} -------------------------------------------------------------------------------- /dist/util/ImageLoadedCallbacks.d.ts: -------------------------------------------------------------------------------- 1 | export declare type ImageLoadedCallback = (imagePointer: number, width: number, height: number) => void; 2 | export declare type ImageUseCallback = (stringPointer: number) => number; 3 | //# sourceMappingURL=ImageLoadedCallbacks.d.ts.map -------------------------------------------------------------------------------- /dist/util/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC"} -------------------------------------------------------------------------------- /dist/shared/Direction.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Direction.js","sourceRoot":"","sources":["../../src/shared/Direction.ts"],"names":[],"mappings":";;AAAA,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,uCAAO,CAAA;IACP,uCAAO,CAAA;IACP,+CAAW,CAAA;AACb,CAAC,EAJW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAIpB"} -------------------------------------------------------------------------------- /src/util/ICanvasPatternIndex.ts: -------------------------------------------------------------------------------- 1 | export interface ICanvasPatternIndex { 2 | [index: number]: CanvasPattern | null; 3 | } 4 | 5 | export const canvasPatternTypes = { 6 | "0": "repeat", 7 | "1": "repeat-x", 8 | "2": "repeat-y", 9 | "3": "no-repeat", 10 | }; 11 | -------------------------------------------------------------------------------- /src/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./GlobalCompositeOperationLookup"; 2 | export * from "./ICanvasGradientIndex"; 3 | export * from "./ICanvasPatternIndex"; 4 | export * from "./IImageBitmapIndex"; 5 | export * from "./ImageLoadedCallbacks"; 6 | export * from "./IStringIndex"; 7 | -------------------------------------------------------------------------------- /dist/util/ICanvasPatternIndex.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ICanvasPatternIndex.d.ts","sourceRoot":"","sources":["../src/util/ICanvasPatternIndex.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;CACvC;AAED,eAAO,MAAM,kBAAkB;;;;;CAK9B,CAAC"} -------------------------------------------------------------------------------- /dist/util/ICanvasPatternIndex.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ICanvasPatternIndex.js","sourceRoot":"","sources":["../../src/util/ICanvasPatternIndex.ts"],"names":[],"mappings":";;AAIa,QAAA,kBAAkB,GAAG;IAChC,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,WAAW;CACjB,CAAC"} -------------------------------------------------------------------------------- /dist/shared/TextAlign.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"TextAlign.js","sourceRoot":"","sources":["../../src/shared/TextAlign.ts"],"names":[],"mappings":";;AAAA,IAAY,SAMX;AAND,WAAY,SAAS;IACnB,yCAAQ,CAAA;IACR,2CAAS,CAAA;IACT,6CAAU,CAAA;IACV,2CAAS,CAAA;IACT,uCAAO,CAAA;AACT,CAAC,EANW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAMpB"} -------------------------------------------------------------------------------- /dist/util/ICanvasPatternIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.canvasPatternTypes = { 4 | "0": "repeat", 5 | "1": "repeat-x", 6 | "2": "repeat-y", 7 | "3": "no-repeat", 8 | }; 9 | //# sourceMappingURL=ICanvasPatternIndex.js.map -------------------------------------------------------------------------------- /dist/util/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./GlobalCompositeOperationLookup"; 2 | export * from "./ICanvasGradientIndex"; 3 | export * from "./ICanvasPatternIndex"; 4 | export * from "./IImageBitmapIndex"; 5 | export * from "./ImageLoadedCallbacks"; 6 | export * from "./IStringIndex"; 7 | //# sourceMappingURL=index.d.ts.map -------------------------------------------------------------------------------- /dist/shared/ImageSmoothingQuality.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ImageSmoothingQuality.js","sourceRoot":"","sources":["../../src/shared/ImageSmoothingQuality.ts"],"names":[],"mappings":";;AAAA,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,+DAAO,CAAA;IACP,qEAAU,CAAA;IACV,iEAAQ,CAAA;AACV,CAAC,EAJW,qBAAqB,GAArB,6BAAqB,KAArB,6BAAqB,QAIhC"} -------------------------------------------------------------------------------- /dist/util/ICanvasPatternIndex.d.ts: -------------------------------------------------------------------------------- 1 | export interface ICanvasPatternIndex { 2 | [index: number]: CanvasPattern | null; 3 | } 4 | export declare const canvasPatternTypes: { 5 | "0": string; 6 | "1": string; 7 | "2": string; 8 | "3": string; 9 | }; 10 | //# sourceMappingURL=ICanvasPatternIndex.d.ts.map -------------------------------------------------------------------------------- /dist/shared/TextBaseline.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"TextBaseline.js","sourceRoot":"","sources":["../../src/shared/TextBaseline.ts"],"names":[],"mappings":";;AAAA,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,6CAAO,CAAA;IACP,qDAAW,CAAA;IACX,mDAAU,CAAA;IACV,2DAAc,CAAA;IACd,6DAAe,CAAA;IACf,mDAAU,CAAA;AACZ,CAAC,EAPW,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QAOvB"} -------------------------------------------------------------------------------- /assembly/renderer/index.ts: -------------------------------------------------------------------------------- 1 | export { CanvasRenderingContext2D } from "./CanvasRenderingContext2D"; 2 | export { OptimizedCanvasRenderingContext2D } from "./OptimizedCanvasRenderingContext2D"; 3 | export { CanvasRenderingContext2DSerializer } from "./CanvasRenderingContext2DSerializer"; 4 | export { Serializer } from "./Serializer"; 5 | -------------------------------------------------------------------------------- /dist/interop/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./CanvasASInterop")); 7 | __export(require("./canvasInterop")); 8 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/util/ImageLoadedCallbacks.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"ImageLoadedCallbacks.d.ts","sourceRoot":"","sources":["../src/util/ImageLoadedCallbacks.ts"],"names":[],"mappings":"AAAA,oBAAY,mBAAmB,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAChG,oBAAY,gBAAgB,GAAG,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC"} -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./interop")); 7 | __export(require("./util")); 8 | __export(require("./shared")); 9 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/util/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./GlobalCompositeOperationLookup")); 7 | __export(require("./ICanvasPatternIndex")); 8 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /demo-src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Test 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /dist/shared/FillRule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var FillRule; 4 | (function (FillRule) { 5 | FillRule[FillRule["nonzero"] = 0] = "nonzero"; 6 | FillRule[FillRule["evenodd"] = 1] = "evenodd"; 7 | })(FillRule = exports.FillRule || (exports.FillRule = {})); 8 | //# sourceMappingURL=FillRule.js.map -------------------------------------------------------------------------------- /dist/shared/LineCap.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var LineCap; 4 | (function (LineCap) { 5 | LineCap[LineCap["butt"] = 0] = "butt"; 6 | LineCap[LineCap["round"] = 1] = "round"; 7 | LineCap[LineCap["square"] = 2] = "square"; 8 | })(LineCap = exports.LineCap || (exports.LineCap = {})); 9 | //# sourceMappingURL=LineCap.js.map -------------------------------------------------------------------------------- /assembly/renderer/CanvasGradient.ts: -------------------------------------------------------------------------------- 1 | import { add_color_stop, remove_gradient } from "../linked"; 2 | var id: i32 = 0; 3 | 4 | export class CanvasGradient { 5 | _id: i32 = id++; 6 | 7 | public addColorStop(point: f64, color: string): void { 8 | add_color_stop(this._id, point, color); 9 | } 10 | 11 | public dispose(): void { 12 | remove_gradient(this._id); 13 | } 14 | } -------------------------------------------------------------------------------- /dist/shared/LineJoin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var LineJoin; 4 | (function (LineJoin) { 5 | LineJoin[LineJoin["bevel"] = 0] = "bevel"; 6 | LineJoin[LineJoin["round"] = 1] = "round"; 7 | LineJoin[LineJoin["miter"] = 2] = "miter"; 8 | })(LineJoin = exports.LineJoin || (exports.LineJoin = {})); 9 | //# sourceMappingURL=LineJoin.js.map -------------------------------------------------------------------------------- /dist/shared/Direction.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var Direction; 4 | (function (Direction) { 5 | Direction[Direction["ltr"] = 0] = "ltr"; 6 | Direction[Direction["rtl"] = 1] = "rtl"; 7 | Direction[Direction["inherit"] = 2] = "inherit"; 8 | })(Direction = exports.Direction || (exports.Direction = {})); 9 | //# sourceMappingURL=Direction.js.map -------------------------------------------------------------------------------- /dist/shared/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":";;AAEA,yCAAwC;AAA/B,gCAAA,SAAS,CAAA;AAClB,uCAAsC;AAA7B,8BAAA,QAAQ,CAAA;AACjB,uEAAsE;AAA7D,8DAAA,wBAAwB,CAAA;AACjC,iEAAgE;AAAvD,wDAAA,qBAAqB,CAAA;AAC9B,qCAAoC;AAA3B,4BAAA,OAAO,CAAA;AAChB,uCAAsC;AAA7B,8BAAA,QAAQ,CAAA;AACjB,yCAAwC;AAA/B,gCAAA,SAAS,CAAA;AAClB,+CAA8C;AAArC,sCAAA,YAAY,CAAA"} -------------------------------------------------------------------------------- /assembly/primitives/index.ts: -------------------------------------------------------------------------------- 1 | export { TextureMap, use_image, image_loaded } from "./TextureMap"; 2 | export { Image } from "./Image"; 3 | export { Matrix } from "./Matrix"; 4 | export { Path2DElement } from "./Path2DElement"; 5 | export { FillStrokeWhichValue, FillStrokeWhich } from "./FillStrokeWhichValue"; 6 | export { CanvasMap, CanvasRenderingContext2DInitializer } from "./CanvasMap"; 7 | export { ImageData } from "./ImageData"; 8 | -------------------------------------------------------------------------------- /assembly/linked/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | add_color_stop, 3 | create_image, 4 | create_linear_gradient, 5 | create_pattern, 6 | create_radial_gradient, 7 | create_string, 8 | get_image_data, 9 | inspect, 10 | put_image_data, 11 | put_image_data_dirty, 12 | remove_image, 13 | remove_gradient, 14 | remove_pattern, 15 | render, 16 | report_image_loaded, 17 | report_use_canvas, 18 | report_use_image, 19 | log, 20 | } from "./util"; 21 | -------------------------------------------------------------------------------- /dist/shared/TextAlign.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var TextAlign; 4 | (function (TextAlign) { 5 | TextAlign[TextAlign["left"] = 0] = "left"; 6 | TextAlign[TextAlign["right"] = 1] = "right"; 7 | TextAlign[TextAlign["center"] = 2] = "center"; 8 | TextAlign[TextAlign["start"] = 3] = "start"; 9 | TextAlign[TextAlign["end"] = 4] = "end"; 10 | })(TextAlign = exports.TextAlign || (exports.TextAlign = {})); 11 | //# sourceMappingURL=TextAlign.js.map -------------------------------------------------------------------------------- /dist/shared/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/shared/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"} -------------------------------------------------------------------------------- /src/shared/index.ts: -------------------------------------------------------------------------------- 1 | export { CanvasInstruction } from "./CanvasInstruction"; 2 | export { CanvasPatternType } from "./CanvasPatternType"; 3 | export { Direction } from "./Direction"; 4 | export { FillRule } from "./FillRule"; 5 | export { GlobalCompositeOperation } from "./GlobalCompositeOperation"; 6 | export { ImageSmoothingQuality } from "./ImageSmoothingQuality"; 7 | export { LineCap } from "./LineCap"; 8 | export { LineJoin } from "./LineJoin"; 9 | export { TextAlign } from "./TextAlign"; 10 | export { TextBaseline } from "./TextBaseline"; 11 | -------------------------------------------------------------------------------- /dist/shared/ImageSmoothingQuality.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var ImageSmoothingQuality; 4 | (function (ImageSmoothingQuality) { 5 | ImageSmoothingQuality[ImageSmoothingQuality["low"] = 0] = "low"; 6 | ImageSmoothingQuality[ImageSmoothingQuality["medium"] = 1] = "medium"; 7 | ImageSmoothingQuality[ImageSmoothingQuality["high"] = 2] = "high"; 8 | })(ImageSmoothingQuality = exports.ImageSmoothingQuality || (exports.ImageSmoothingQuality = {})); 9 | //# sourceMappingURL=ImageSmoothingQuality.js.map -------------------------------------------------------------------------------- /assembly/primitives/Path2DElement.ts: -------------------------------------------------------------------------------- 1 | import { CanvasInstruction } from "../../src/shared"; 2 | 3 | export class Path2DElement { 4 | instruction: CanvasInstruction = CanvasInstruction.Commit; 5 | transformA: f64 = 1.0; 6 | transformB: f64 = 0.0; 7 | transformC: f64 = 0.0; 8 | transformD: f64 = 1.0; 9 | transformE: f64 = 0.0; 10 | transformF: f64 = 0.0; 11 | count: i32 = 0; 12 | updateTransform: bool = false; 13 | a: f64 = 0; 14 | b: f64 = 0; 15 | c: f64 = 0; 16 | d: f64 = 0; 17 | e: f64 = 0; 18 | f: f64 = 0; 19 | g: f64 = 0; 20 | h: f64 = 0; 21 | } 22 | -------------------------------------------------------------------------------- /dist/shared/index.d.ts: -------------------------------------------------------------------------------- 1 | export { CanvasInstruction } from "./CanvasInstruction"; 2 | export { CanvasPatternType } from "./CanvasPatternType"; 3 | export { Direction } from "./Direction"; 4 | export { FillRule } from "./FillRule"; 5 | export { GlobalCompositeOperation } from "./GlobalCompositeOperation"; 6 | export { ImageSmoothingQuality } from "./ImageSmoothingQuality"; 7 | export { LineCap } from "./LineCap"; 8 | export { LineJoin } from "./LineJoin"; 9 | export { TextAlign } from "./TextAlign"; 10 | export { TextBaseline } from "./TextBaseline"; 11 | //# sourceMappingURL=index.d.ts.map -------------------------------------------------------------------------------- /dist/shared/GlobalCompositeOperation.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"GlobalCompositeOperation.d.ts","sourceRoot":"","sources":["../src/shared/GlobalCompositeOperation.ts"],"names":[],"mappings":"AAAA,oBAAY,wBAAwB;IAClC,WAAW,IAAI;IACf,SAAS,IAAI;IACb,UAAU,IAAI;IACd,WAAW,IAAI;IACf,gBAAgB,IAAI;IACpB,cAAc,IAAI;IAClB,eAAe,IAAI;IACnB,gBAAgB,IAAI;IACpB,OAAO,IAAI;IACX,IAAI,IAAI;IACR,GAAG,KAAK;IACR,QAAQ,KAAK;IACb,MAAM,KAAK;IACX,OAAO,KAAK;IACZ,MAAM,KAAK;IACX,OAAO,KAAK;IACZ,WAAW,KAAK;IAChB,UAAU,KAAK;IACf,UAAU,KAAK;IACf,UAAU,KAAK;IACf,UAAU,KAAK;IACf,SAAS,KAAK;IACd,GAAG,KAAK;IACR,UAAU,KAAK;IACf,KAAK,KAAK;IACV,UAAU,KAAK;CAChB"} -------------------------------------------------------------------------------- /assembly/util/TypedArray.ts: -------------------------------------------------------------------------------- 1 | export function copyTypedArray(value: Float64Array): Float64Array { 2 | var copy: Float64Array = new Float64Array(value.length); 3 | for (var i = 0; i < copy.length; i++) 4 | copy[i] = value[i]; 5 | 6 | return copy; 7 | } 8 | 9 | export function doubleTypedArray(value: Float64Array): Float64Array { 10 | var copy: Float64Array = new Float64Array(value.length * 2); 11 | var i: i32; 12 | for (i = 0; i < copy.length; i++) 13 | copy[i] = value[i]; 14 | 15 | for (i = 0; i < copy.length; i++) 16 | copy[i + copy.length] = value[i]; 17 | 18 | return copy; 19 | } 20 | -------------------------------------------------------------------------------- /assembly/primitives/ImageData.ts: -------------------------------------------------------------------------------- 1 | export class ImageData { 2 | public data: Uint8ClampedArray | null; 3 | public width: i32; 4 | public height: i32; 5 | 6 | constructor(width: i32, height: i32, constructData: bool = true) { 7 | this.width = width; 8 | this.height = height; 9 | this.data = constructData ? new Uint8ClampedArray(width * height * 4) : null; 10 | } 11 | 12 | dispose(): void { 13 | if (this.data) { 14 | memory.free(changetype(this.data.buffer)); 15 | memory.free(changetype(this.data)); 16 | memory.free(changetype(this)); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dist/util/GlobalCompositeOperationLookup.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"GlobalCompositeOperationLookup.d.ts","sourceRoot":"","sources":["../src/util/GlobalCompositeOperationLookup.ts"],"names":[],"mappings":"AAAA,oBAAY,8BAA8B;IACxC,aAAa,IAAI;IACjB,WAAW,IAAI;IACf,YAAY,IAAI;IAChB,aAAa,IAAI;IACjB,kBAAkB,IAAI;IACtB,gBAAgB,IAAI;IACpB,iBAAiB,IAAI;IACrB,kBAAkB,IAAI;IACtB,SAAS,IAAI;IACb,MAAM,IAAI;IACV,KAAK,KAAK;IACV,UAAU,KAAK;IACf,QAAQ,KAAK;IACb,SAAS,KAAK;IACd,QAAQ,KAAK;IACb,SAAS,KAAK;IACd,aAAa,KAAK;IAClB,YAAY,KAAK;IACjB,YAAY,KAAK;IACjB,YAAY,KAAK;IACjB,YAAY,KAAK;IACjB,WAAW,KAAK;IAChB,KAAK,KAAK;IACV,YAAY,KAAK;IACjB,OAAO,KAAK;IACZ,YAAY,KAAK;CAClB"} -------------------------------------------------------------------------------- /assembly/primitives/TextureMap.ts: -------------------------------------------------------------------------------- 1 | import { Image } from "./Image"; 2 | import { report_use_image, report_image_loaded } from "../linked"; 3 | export var TextureMap: Map = new Map(); 4 | 5 | report_use_image(use_image); 6 | export function use_image(name: string): Image { 7 | var image: Image = new Image(); 8 | image._index = Image.index++; 9 | TextureMap.set(name, image); 10 | return image; 11 | } 12 | 13 | report_image_loaded(image_loaded); 14 | export function image_loaded(img: Image, width: i32, height: i32): void { 15 | img._loaded = 1; 16 | img.width = width; 17 | img.height = height; 18 | } 19 | -------------------------------------------------------------------------------- /dist/shared/TextBaseline.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var TextBaseline; 4 | (function (TextBaseline) { 5 | TextBaseline[TextBaseline["top"] = 0] = "top"; 6 | TextBaseline[TextBaseline["hanging"] = 1] = "hanging"; 7 | TextBaseline[TextBaseline["middle"] = 2] = "middle"; 8 | TextBaseline[TextBaseline["alphabetic"] = 3] = "alphabetic"; 9 | TextBaseline[TextBaseline["ideographic"] = 4] = "ideographic"; 10 | TextBaseline[TextBaseline["bottom"] = 5] = "bottom"; 11 | })(TextBaseline = exports.TextBaseline || (exports.TextBaseline = {})); 12 | //# sourceMappingURL=TextBaseline.js.map -------------------------------------------------------------------------------- /assembly/primitives/Image.ts: -------------------------------------------------------------------------------- 1 | import { create_image } from "../linked"; 2 | 3 | export class Image { 4 | public static index: i32 = 0; 5 | public _index: i32 = 0; 6 | public _loaded: i32 = 0; 7 | public width: i32 = 0; 8 | public height: i32 = 0; 9 | private _src: string = ""; 10 | 11 | public get src(): string { 12 | return this._src; 13 | } 14 | 15 | public set src(value: string) { 16 | if (this._src == value) return; 17 | this._index = Image.index++; 18 | create_image(this, value); 19 | this._src = value; 20 | } 21 | 22 | @inline 23 | get loaded(): bool { 24 | return this._loaded == 1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/shared/GlobalCompositeOperation.ts: -------------------------------------------------------------------------------- 1 | export enum GlobalCompositeOperation { 2 | source_over = 0, 3 | source_in = 1, 4 | source_out = 2, 5 | source_atop = 3, 6 | destination_over = 4, 7 | destination_in = 5, 8 | destination_out = 6, 9 | destination_atop = 7, 10 | lighter = 8, 11 | copy = 9, 12 | xor = 10, 13 | multiply = 11, 14 | screen = 12, 15 | overlay = 13, 16 | darken = 14, 17 | lighten = 15, 18 | color_dodge = 16, 19 | color_burn = 17, 20 | hard_light = 18, 21 | soft_light = 19, 22 | difference = 20, 23 | exclusion = 21, 24 | hue = 22, 25 | saturation = 23, 26 | color = 24, 27 | luminosity = 25, 28 | } 29 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import compiler from '@ampproject/rollup-plugin-closure-compiler'; 2 | import commonjs from "rollup-plugin-commonjs"; 3 | import nodeResolve from "rollup-plugin-node-resolve"; 4 | import typescript from "rollup-plugin-typescript2"; 5 | 6 | export default { 7 | input: 'src/index.ts', 8 | output: { 9 | file: 'dist/bundle.js', 10 | format: 'umd', 11 | name: "canvasas", 12 | }, 13 | plugins: [ 14 | nodeResolve({ 15 | extensions: [".ts", ".js"], 16 | }), 17 | commonjs(), 18 | typescript({ 19 | objectHashIgnoreUnknownHack: false, 20 | clean: true, 21 | }), 22 | compiler(), 23 | ], 24 | } 25 | -------------------------------------------------------------------------------- /dist/interop/canvasInterop.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"canvasInterop.d.ts","sourceRoot":"","sources":["../src/interop/canvasInterop.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,QAAQ,EACR,aAAa,EAIb,UAAU,EACV,qBAAqB,EACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,wBAAgB,WAAW,CAAC,CAAC,EAAE,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,GAAE,GAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,CAOpG;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,GAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,CAO9F;AAED,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAOvH;AAED,OAAO,EACL,MAAM,EACN,QAAQ,EACR,aAAa,EACb,UAAU,EACV,qBAAqB,GACtB,CAAA"} -------------------------------------------------------------------------------- /dist/shared/GlobalCompositeOperation.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"GlobalCompositeOperation.js","sourceRoot":"","sources":["../../src/shared/GlobalCompositeOperation.ts"],"names":[],"mappings":";;AAAA,IAAY,wBA2BX;AA3BD,WAAY,wBAAwB;IAClC,qFAAe,CAAA;IACf,iFAAa,CAAA;IACb,mFAAc,CAAA;IACd,qFAAe,CAAA;IACf,+FAAoB,CAAA;IACpB,2FAAkB,CAAA;IAClB,6FAAmB,CAAA;IACnB,+FAAoB,CAAA;IACpB,6EAAW,CAAA;IACX,uEAAQ,CAAA;IACR,sEAAQ,CAAA;IACR,gFAAa,CAAA;IACb,4EAAW,CAAA;IACX,8EAAY,CAAA;IACZ,4EAAW,CAAA;IACX,8EAAY,CAAA;IACZ,sFAAgB,CAAA;IAChB,oFAAe,CAAA;IACf,oFAAe,CAAA;IACf,oFAAe,CAAA;IACf,oFAAe,CAAA;IACf,kFAAc,CAAA;IACd,sEAAQ,CAAA;IACR,oFAAe,CAAA;IACf,0EAAU,CAAA;IACV,oFAAe,CAAA;AACjB,CAAC,EA3BW,wBAAwB,GAAxB,gCAAwB,KAAxB,gCAAwB,QA2BnC"} -------------------------------------------------------------------------------- /dist/interop/canvasInterop.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { ASUtil, demangle, ImportsObject, TypedArray, TypedArrayConstructor } from "assemblyscript/lib/loader"; 3 | import { CanvasASInterop } from "./CanvasASInterop"; 4 | export declare function instantiate(wasmmodule: WebAssembly.Module, imports?: any): CanvasASInterop; 5 | export declare function instantiateBuffer(buffer: Uint8Array, imports?: any): CanvasASInterop; 6 | export declare function instantiateStreaming(result: Promise, imports?: any): Promise>; 7 | export { ASUtil, demangle, ImportsObject, TypedArray, TypedArrayConstructor, }; 8 | //# sourceMappingURL=canvasInterop.d.ts.map -------------------------------------------------------------------------------- /dist/util/GlobalCompositeOperationLookup.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"GlobalCompositeOperationLookup.js","sourceRoot":"","sources":["../../src/util/GlobalCompositeOperationLookup.ts"],"names":[],"mappings":";;AAAA,IAAY,8BA2BX;AA3BD,WAAY,8BAA8B;IACxC,iGAAiB,CAAA;IACjB,6FAAe,CAAA;IACf,+FAAgB,CAAA;IAChB,iGAAiB,CAAA;IACjB,2GAAsB,CAAA;IACtB,uGAAoB,CAAA;IACpB,yGAAqB,CAAA;IACrB,2GAAsB,CAAA;IACtB,yFAAa,CAAA;IACb,mFAAU,CAAA;IACV,kFAAU,CAAA;IACV,4FAAe,CAAA;IACf,wFAAa,CAAA;IACb,0FAAc,CAAA;IACd,wFAAa,CAAA;IACb,0FAAc,CAAA;IACd,kGAAkB,CAAA;IAClB,gGAAiB,CAAA;IACjB,gGAAiB,CAAA;IACjB,gGAAiB,CAAA;IACjB,gGAAiB,CAAA;IACjB,8FAAgB,CAAA;IAChB,kFAAU,CAAA;IACV,gGAAiB,CAAA;IACjB,sFAAY,CAAA;IACZ,gGAAiB,CAAA;AACnB,CAAC,EA3BW,8BAA8B,GAA9B,sCAA8B,KAA9B,sCAA8B,QA2BzC"} -------------------------------------------------------------------------------- /src/util/GlobalCompositeOperationLookup.ts: -------------------------------------------------------------------------------- 1 | export enum GlobalCompositeOperationLookup { 2 | "source-over" = 0, 3 | "source-in" = 1, 4 | "source-out" = 2, 5 | "source-atop" = 3, 6 | "destination-over" = 4, 7 | "destination-in" = 5, 8 | "destination-out" = 6, 9 | "destination-atop" = 7, 10 | "lighter" = 8, 11 | "copy" = 9, 12 | "xor" = 10, 13 | "multiply" = 11, 14 | "screen" = 12, 15 | "overlay" = 13, 16 | "darken" = 14, 17 | "lighten" = 15, 18 | "color-dodge" = 16, 19 | "color-burn" = 17, 20 | "hard-light" = 18, 21 | "soft-light" = 19, 22 | "difference" = 20, 23 | "exclusion" = 21, 24 | "hue" = 22, 25 | "saturation" = 23, 26 | "color" = 24, 27 | "luminosity" = 25, 28 | } 29 | -------------------------------------------------------------------------------- /dist/shared/GlobalCompositeOperation.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum GlobalCompositeOperation { 2 | source_over = 0, 3 | source_in = 1, 4 | source_out = 2, 5 | source_atop = 3, 6 | destination_over = 4, 7 | destination_in = 5, 8 | destination_out = 6, 9 | destination_atop = 7, 10 | lighter = 8, 11 | copy = 9, 12 | xor = 10, 13 | multiply = 11, 14 | screen = 12, 15 | overlay = 13, 16 | darken = 14, 17 | lighten = 15, 18 | color_dodge = 16, 19 | color_burn = 17, 20 | hard_light = 18, 21 | soft_light = 19, 22 | difference = 20, 23 | exclusion = 21, 24 | hue = 22, 25 | saturation = 23, 26 | color = 24, 27 | luminosity = 25 28 | } 29 | //# sourceMappingURL=GlobalCompositeOperation.d.ts.map -------------------------------------------------------------------------------- /dist/util/GlobalCompositeOperationLookup.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum GlobalCompositeOperationLookup { 2 | "source-over" = 0, 3 | "source-in" = 1, 4 | "source-out" = 2, 5 | "source-atop" = 3, 6 | "destination-over" = 4, 7 | "destination-in" = 5, 8 | "destination-out" = 6, 9 | "destination-atop" = 7, 10 | "lighter" = 8, 11 | "copy" = 9, 12 | "xor" = 10, 13 | "multiply" = 11, 14 | "screen" = 12, 15 | "overlay" = 13, 16 | "darken" = 14, 17 | "lighten" = 15, 18 | "color-dodge" = 16, 19 | "color-burn" = 17, 20 | "hard-light" = 18, 21 | "soft-light" = 19, 22 | "difference" = 20, 23 | "exclusion" = 21, 24 | "hue" = 22, 25 | "saturation" = 23, 26 | "color" = 24, 27 | "luminosity" = 25 28 | } 29 | //# sourceMappingURL=GlobalCompositeOperationLookup.d.ts.map -------------------------------------------------------------------------------- /assembly/primitives/FillStrokeWhichValue.ts: -------------------------------------------------------------------------------- 1 | import { CanvasPattern } from "../renderer/CanvasPattern"; 2 | import { CanvasGradient } from "../renderer/CanvasGradient"; 3 | 4 | export const enum FillStrokeWhich { 5 | Style, 6 | Gradient, 7 | Pattern, 8 | } 9 | 10 | export class FillStrokeWhichValue { 11 | pattern: CanvasPattern | null = null; 12 | gradient: CanvasGradient | null = null; 13 | style: string | null = "#000"; 14 | which: FillStrokeWhich = FillStrokeWhich.Style; 15 | 16 | @operator("==") 17 | protected equals(value: FillStrokeWhichValue): bool { 18 | return this.which == value.which 19 | && this.pattern == value.pattern 20 | && this.gradient == value.gradient 21 | && this.style == value.style; 22 | } 23 | 24 | @inline 25 | public set(value: FillStrokeWhichValue): void { 26 | value.gradient = this.gradient; 27 | value.pattern = this.pattern; 28 | value.style = this.style; 29 | value.which = this.which; 30 | } 31 | } -------------------------------------------------------------------------------- /dist/shared/CanvasInstruction.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"CanvasInstruction.d.ts","sourceRoot":"","sources":["../src/shared/CanvasInstruction.ts"],"names":[],"mappings":"AAAA,0BAAkB,iBAAiB;IACjC,GAAG,IAAA;IACH,KAAK,IAAA;IACL,SAAS,IAAA;IACT,aAAa,IAAA;IACb,IAAI,IAAA;IACJ,SAAS,IAAA;IACT,MAAM,IAAA;IACN,SAAS,IAAA;IACT,SAAS,IAAA;IACT,iBAAiB,IAAA;IACjB,SAAS,KAAA;IACT,OAAO,KAAA;IACP,IAAI,KAAA;IACJ,YAAY,KAAA;IACZ,WAAW,KAAA;IACX,QAAQ,KAAA;IACR,SAAS,KAAA;IACT,QAAQ,KAAA;IACR,MAAM,KAAA;IACN,IAAI,KAAA;IACJ,WAAW,KAAA;IACX,wBAAwB,KAAA;IACxB,qBAAqB,KAAA;IACrB,qBAAqB,KAAA;IACrB,OAAO,KAAA;IACP,OAAO,KAAA;IACP,QAAQ,KAAA;IACR,cAAc,KAAA;IACd,QAAQ,KAAA;IACR,MAAM,KAAA;IACN,SAAS,KAAA;IACT,UAAU,KAAA;IACV,MAAM,KAAA;IACN,gBAAgB,KAAA;IAChB,IAAI,KAAA;IACJ,OAAO,KAAA;IACP,MAAM,KAAA;IACN,IAAI,KAAA;IACJ,KAAK,KAAA;IACL,YAAY,KAAA;IACZ,UAAU,KAAA;IACV,WAAW,KAAA;IACX,aAAa,KAAA;IACb,aAAa,KAAA;IACb,MAAM,KAAA;IACN,cAAc,KAAA;IACd,aAAa,KAAA;IACb,UAAU,KAAA;IACV,WAAW,KAAA;IACX,UAAU,KAAA;IACV,SAAS,KAAA;IACT,YAAY,KAAA;IACZ,SAAS,KAAA;IACT,SAAS,KAAA;CACV"} -------------------------------------------------------------------------------- /dist/shared/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var Direction_1 = require("./Direction"); 4 | exports.Direction = Direction_1.Direction; 5 | var FillRule_1 = require("./FillRule"); 6 | exports.FillRule = FillRule_1.FillRule; 7 | var GlobalCompositeOperation_1 = require("./GlobalCompositeOperation"); 8 | exports.GlobalCompositeOperation = GlobalCompositeOperation_1.GlobalCompositeOperation; 9 | var ImageSmoothingQuality_1 = require("./ImageSmoothingQuality"); 10 | exports.ImageSmoothingQuality = ImageSmoothingQuality_1.ImageSmoothingQuality; 11 | var LineCap_1 = require("./LineCap"); 12 | exports.LineCap = LineCap_1.LineCap; 13 | var LineJoin_1 = require("./LineJoin"); 14 | exports.LineJoin = LineJoin_1.LineJoin; 15 | var TextAlign_1 = require("./TextAlign"); 16 | exports.TextAlign = TextAlign_1.TextAlign; 17 | var TextBaseline_1 = require("./TextBaseline"); 18 | exports.TextBaseline = TextBaseline_1.TextBaseline; 19 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /src/shared/CanvasInstruction.ts: -------------------------------------------------------------------------------- 1 | export const enum CanvasInstruction { 2 | Arc, 3 | ArcTo, 4 | BeginPath, 5 | BezierCurveTo, 6 | Clip, 7 | ClosePath, 8 | Commit, 9 | ClearRect, 10 | Direction, 11 | DrawFocusIfNeeded, 12 | DrawImage, 13 | Ellipse, 14 | Fill, 15 | FillGradient, 16 | FillPattern, 17 | FillRect, 18 | FillStyle, 19 | FillText, 20 | Filter, 21 | Font, 22 | GlobalAlpha, 23 | GlobalCompositeOperation, 24 | ImageSmoothingEnabled, 25 | ImageSmoothingQuality, 26 | Inspect, 27 | LineCap, 28 | LineDash, 29 | LineDashOffset, 30 | LineJoin, 31 | LineTo, 32 | LineWidth, 33 | MiterLimit, 34 | MoveTo, 35 | QuadraticCurveTo, 36 | Rect, 37 | Restore, 38 | Rotate, 39 | Save, 40 | Scale, 41 | SetTransform, 42 | ShadowBlur, 43 | ShadowColor, 44 | ShadowOffsetX, 45 | ShadowOffsetY, 46 | Stroke, 47 | StrokeGradient, 48 | StrokePattern, 49 | StrokeRect, 50 | StrokeStyle, 51 | StrokeText, 52 | TextAlign, 53 | TextBaseline, 54 | Translate, 55 | Transform, 56 | } 57 | -------------------------------------------------------------------------------- /dist/interop/canvasInterop.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"canvasInterop.js","sourceRoot":"","sources":["../../src/interop/canvasInterop.ts"],"names":[],"mappings":";;AAAA,sDASmC;AAgCjC,mBAvCA,iBAAQ,CAuCA;AA/BV,uDAAoD;AAEpD,SAAgB,WAAW,CAAI,UAA8B,EAAE,UAAe,EAAE;IAC9E,IAAI,IAAgB,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,iCAAe,EAAK,CAAC;IACzC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,GAAG,oBAAiB,CAAI,UAAU,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IACpB,OAAO,OAAO,CAAC;AACjB,CAAC;AAPD,kCAOC;AAED,SAAgB,iBAAiB,CAAI,MAAkB,EAAE,UAAe,EAAE;IACxE,IAAI,IAAgB,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,iCAAe,EAAK,CAAC;IACzC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,GAAG,0BAAuB,CAAI,MAAM,EAAE,OAAO,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IACpB,OAAO,OAAO,CAAC;AACjB,CAAC;AAPD,8CAOC;AAEM,KAAK,UAAU,oBAAoB,CAAI,MAAyB,EAAE,UAAe,EAAE;IACxF,IAAI,IAAgB,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,iCAAe,EAAK,CAAC;IACzC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,GAAG,MAAM,6BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IACpB,OAAO,OAAO,CAAC;AACjB,CAAC;AAPD,oDAOC"} -------------------------------------------------------------------------------- /assembly/primitives/Matrix.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export class Matrix { 4 | @inline 5 | public static create(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64): Matrix { 6 | var result = new Matrix(); 7 | result.a = a; 8 | result.b = b; 9 | result.c = c; 10 | result.d = d; 11 | result.e = e; 12 | result.f = f; 13 | return result; 14 | } 15 | 16 | @inline 17 | public static set(left: Matrix, right: Matrix): void { 18 | left.a = right.a; 19 | left.b = right.b; 20 | left.c = right.c; 21 | left.d = right.d; 22 | left.e = right.e; 23 | left.f = right.f; 24 | } 25 | 26 | a: f64; 27 | b: f64; 28 | c: f64; 29 | d: f64; 30 | e: f64; 31 | f: f64; 32 | 33 | public clone(): Matrix { 34 | return Matrix.create(this.a, this.b, this.c, this.d, this.e, this.f); 35 | } 36 | 37 | @operator("==") @inline 38 | protected equals(value: Matrix): bool { 39 | return this.a == value.a 40 | && this.b == value.b 41 | && this.c == value.c 42 | && this.d == value.d 43 | && this.e == value.e 44 | && this.f == value.f; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Joshua Tenner 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /dist/interop/CanvasASInterop.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"CanvasASInterop.d.ts","sourceRoot":"","sources":["../src/interop/CanvasASInterop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAyB,MAAM,2BAA2B,CAAC;AAY1E,OAAO,EAEL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EAIrB,MAAM,SAAS,CAAC;AAIjB,qBAAa,eAAe,CAAC,CAAC;IACrB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAA+C;IAC9F,OAAO,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IACzC,MAAM,EAAE,iBAAiB,CAAM;IAC/B,QAAQ,EAAE,mBAAmB,CAAM;IACnC,SAAS,EAAE,oBAAoB,CAAM;IACrC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,UAAU,CAAa;;IAIxB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAQ/D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAiBtD,IAAI,IAAI,GAAG;IAuBlB,OAAO,CAAC,MAAM;IAySd,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;YAIT,UAAU;IAYxB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,OAAO;IAiOf,OAAO,CAAC,GAAG;CAGZ"} -------------------------------------------------------------------------------- /demo-src/index.js: -------------------------------------------------------------------------------- 1 | const regeneratorRuntime = require("regenerator-runtime"); 2 | window.regeneratorRuntime = regeneratorRuntime; 3 | const { Buffer } = require("buffer"); 4 | window.Buffer = Buffer; 5 | const { instantiateStreaming } = require("../src"); 6 | const canvas = document.querySelector("#main") || document.createElement("canvas"); 7 | canvas.id = "main"; 8 | 9 | canvas.width = 800; 10 | canvas.height = 600; 11 | if (!canvas.parentElement) { 12 | document.body.appendChild(canvas); 13 | } 14 | 15 | const ctx = canvas.getContext("2d"); 16 | const fs = require("fs"); 17 | const buff = fs.readFileSync("./build/optimized.wasm"); 18 | const blob = new Blob([buff], { type: "application/wasm" }); 19 | const url = URL.createObjectURL(blob); 20 | 21 | async function main() { 22 | const interop = await instantiateStreaming(fetch(url), {}); 23 | interop.useContext("main", ctx) 24 | .wasm 25 | .init(); 26 | function loop() { 27 | interop.wasm.tick(); 28 | } 29 | 30 | if (!window.loop) { 31 | requestAnimationFrame(function frame() { 32 | requestAnimationFrame(frame); 33 | window.loop(); 34 | }); 35 | } 36 | window.loop = loop; 37 | } 38 | 39 | main(); 40 | -------------------------------------------------------------------------------- /assembly/primitives/CanvasMap.ts: -------------------------------------------------------------------------------- 1 | import { report_use_canvas } from "../linked"; 2 | import { CanvasRenderingContext2D, OptimizedCanvasRenderingContext2D } from "../renderer"; 3 | 4 | export class CanvasRenderingContext2DInitializer { 5 | public used: string[] = new Array(0); 6 | 7 | public get(name: string): CanvasRenderingContext2D { 8 | if (this.used.includes(name)) { 9 | var ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(); 10 | ctx.init(); 11 | ctx._id = name; 12 | return ctx; 13 | } 14 | throw new Error("Invalid canvas get"); 15 | } 16 | 17 | public getOptimized(name: string): OptimizedCanvasRenderingContext2D { 18 | if (this.used.includes(name)) { 19 | var ctx: OptimizedCanvasRenderingContext2D = new OptimizedCanvasRenderingContext2D(); 20 | ctx.init(); 21 | ctx._id = name; 22 | return ctx; 23 | } 24 | throw new Error("Invalid canvas get"); 25 | } 26 | } 27 | 28 | export var CanvasMap: CanvasRenderingContext2DInitializer = new CanvasRenderingContext2DInitializer(); 29 | 30 | report_use_canvas(use_canvas); 31 | function use_canvas(name: string): void { 32 | CanvasMap.used.push(name); 33 | } 34 | -------------------------------------------------------------------------------- /dist/interop/canvasInterop.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const loader_1 = require("assemblyscript/lib/loader"); 4 | exports.demangle = loader_1.demangle; 5 | const CanvasASInterop_1 = require("./CanvasASInterop"); 6 | function instantiate(wasmmodule, imports = {}) { 7 | let wasm; 8 | const interop = new CanvasASInterop_1.CanvasASInterop(); 9 | imports.__as_interop = interop.init(); 10 | wasm = loader_1.instantiate(wasmmodule, imports); 11 | interop.wasm = wasm; 12 | return interop; 13 | } 14 | exports.instantiate = instantiate; 15 | function instantiateBuffer(buffer, imports = {}) { 16 | let wasm; 17 | const interop = new CanvasASInterop_1.CanvasASInterop(); 18 | imports.__as_interop = interop.init(); 19 | wasm = loader_1.instantiateBuffer(buffer, imports); 20 | interop.wasm = wasm; 21 | return interop; 22 | } 23 | exports.instantiateBuffer = instantiateBuffer; 24 | async function instantiateStreaming(result, imports = {}) { 25 | let wasm; 26 | const interop = new CanvasASInterop_1.CanvasASInterop(); 27 | imports.__as_interop = interop.init(); 28 | wasm = await loader_1.instantiateStreaming(result, imports); 29 | interop.wasm = wasm; 30 | return interop; 31 | } 32 | exports.instantiateStreaming = instantiateStreaming; 33 | //# sourceMappingURL=canvasInterop.js.map -------------------------------------------------------------------------------- /dist/interop/CanvasASInterop.d.ts: -------------------------------------------------------------------------------- 1 | import { ASUtil } from "assemblyscript/lib/loader"; 2 | import { IImageBitmapIndex, ICanvasPatternIndex, ICanvasGradientIndex } from "../util"; 3 | export declare class CanvasASInterop { 4 | contexts: Map; 5 | strings: { 6 | [hash: number]: string; 7 | }; 8 | images: IImageBitmapIndex; 9 | patterns: ICanvasPatternIndex; 10 | gradients: ICanvasGradientIndex; 11 | wasm: (ASUtil & T) | null; 12 | private image_loaded; 13 | private use_image; 14 | private use_canvas; 15 | constructor(); 16 | useContext(name: string, value: CanvasRenderingContext2D): this; 17 | useImage(name: string, value: Promise): this; 18 | init(): any; 19 | private render; 20 | private add_color_stop; 21 | private create_image; 22 | private create_linear_gradient; 23 | private create_pattern; 24 | private create_radial_gradient; 25 | private create_string; 26 | private get_image_data; 27 | private put_image_data; 28 | private put_image_data_dirty; 29 | private remove_image; 30 | private remove_pattern; 31 | private remove_gradient; 32 | private load_image; 33 | private report_use_image; 34 | private report_use_canvas; 35 | private report_image_loaded; 36 | private inspect; 37 | private log; 38 | } 39 | //# sourceMappingURL=CanvasASInterop.d.ts.map -------------------------------------------------------------------------------- /dist/shared/CanvasInstruction.d.ts: -------------------------------------------------------------------------------- 1 | export declare const enum CanvasInstruction { 2 | Arc = 0, 3 | ArcTo = 1, 4 | BeginPath = 2, 5 | BezierCurveTo = 3, 6 | Clip = 4, 7 | ClosePath = 5, 8 | Commit = 6, 9 | ClearRect = 7, 10 | Direction = 8, 11 | DrawFocusIfNeeded = 9, 12 | DrawImage = 10, 13 | Ellipse = 11, 14 | Fill = 12, 15 | FillGradient = 13, 16 | FillPattern = 14, 17 | FillRect = 15, 18 | FillStyle = 16, 19 | FillText = 17, 20 | Filter = 18, 21 | Font = 19, 22 | GlobalAlpha = 20, 23 | GlobalCompositeOperation = 21, 24 | ImageSmoothingEnabled = 22, 25 | ImageSmoothingQuality = 23, 26 | Inspect = 24, 27 | LineCap = 25, 28 | LineDash = 26, 29 | LineDashOffset = 27, 30 | LineJoin = 28, 31 | LineTo = 29, 32 | LineWidth = 30, 33 | MiterLimit = 31, 34 | MoveTo = 32, 35 | QuadraticCurveTo = 33, 36 | Rect = 34, 37 | Restore = 35, 38 | Rotate = 36, 39 | Save = 37, 40 | Scale = 38, 41 | SetTransform = 39, 42 | ShadowBlur = 40, 43 | ShadowColor = 41, 44 | ShadowOffsetX = 42, 45 | ShadowOffsetY = 43, 46 | Stroke = 44, 47 | StrokeGradient = 45, 48 | StrokePattern = 46, 49 | StrokeRect = 47, 50 | StrokeStyle = 48, 51 | StrokeText = 49, 52 | TextAlign = 50, 53 | TextBaseline = 51, 54 | Translate = 52, 55 | Transform = 53 56 | } 57 | //# sourceMappingURL=CanvasInstruction.d.ts.map -------------------------------------------------------------------------------- /src/interop/canvasInterop.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ASUtil, 3 | demangle, 4 | ImportsObject, 5 | instantiate as instantiateASUtil, 6 | instantiateBuffer as instantiateBufferASUtil, 7 | instantiateStreaming as instantiateStreamingASUtil, 8 | TypedArray, 9 | TypedArrayConstructor, 10 | } from "assemblyscript/lib/loader"; 11 | import { CanvasASInterop } from "./CanvasASInterop"; 12 | 13 | export function instantiate(wasmmodule: WebAssembly.Module, imports: any = {}): CanvasASInterop { 14 | let wasm: ASUtil & T; 15 | const interop = new CanvasASInterop(); 16 | imports.__as_interop = interop.init(); 17 | wasm = instantiateASUtil(wasmmodule, imports); 18 | interop.wasm = wasm; 19 | return interop; 20 | } 21 | 22 | export function instantiateBuffer(buffer: Uint8Array, imports: any = {}): CanvasASInterop { 23 | let wasm: ASUtil & T; 24 | const interop = new CanvasASInterop(); 25 | imports.__as_interop = interop.init(); 26 | wasm = instantiateBufferASUtil(buffer, imports); 27 | interop.wasm = wasm; 28 | return interop; 29 | } 30 | 31 | export async function instantiateStreaming(result: Promise, imports: any = {}): Promise> { 32 | let wasm: ASUtil & T; 33 | const interop = new CanvasASInterop(); 34 | imports.__as_interop = interop.init(); 35 | wasm = await instantiateStreamingASUtil(result, imports); 36 | interop.wasm = wasm; 37 | return interop; 38 | } 39 | 40 | export { 41 | ASUtil, 42 | demangle, 43 | ImportsObject, 44 | TypedArray, 45 | TypedArrayConstructor, 46 | } 47 | -------------------------------------------------------------------------------- /assembly/example.ts: -------------------------------------------------------------------------------- 1 | // You need to import your own allocator 2 | import "allocator/tlsf"; 3 | 4 | // import CanvasRenderingContext2D and Image 5 | import { 6 | OptimizedCanvasRenderingContext2D, 7 | CanvasRenderingContext2D, 8 | CanvasMap, 9 | } from "./index"; 10 | import { log } from "./linked"; 11 | 12 | class Star { 13 | x: f64; 14 | y: f64; 15 | } 16 | 17 | let ctx: OptimizedCanvasRenderingContext2D; 18 | let stars: Star[] = new Array(0); 19 | let size: i32 = 0; 20 | 21 | export function init(): void { 22 | var star: Star; 23 | ctx = CanvasMap.getOptimized("main"); 24 | for (var i = 0; i < 100; i++) { 25 | star = new Star(); 26 | star.x = Math.random() * 800.0; 27 | star.y = Math.random() * 600.0; 28 | stars.push(star); 29 | } 30 | } 31 | 32 | let pi2: f64 = Math.PI * 2; 33 | export function tick(): void { 34 | 35 | // perform some simple drawing calls 36 | ctx.fillStyle = "black"; 37 | ctx.fillRect(0.0, 0.0, 800.0, 600.0); 38 | 39 | ctx.save(true); 40 | ctx.beginPath(); 41 | ctx.rect(100.0, 100.0, 600.0, 400.0); 42 | ctx.clip(); 43 | 44 | 45 | var star: Star; 46 | for (var i = 0; i < stars.length; i++) { 47 | star = stars[i]; 48 | star.y += 1.0; 49 | if (star.y > 600.0) star.y -= 600.0; 50 | 51 | ctx.save(); 52 | ctx.fillStyle = "white"; 53 | ctx.translate(star.x, star.y); 54 | 55 | ctx.beginPath(); 56 | ctx.arc(0.0, 0.0, 1, 0, pi2); 57 | ctx.fill(); 58 | 59 | ctx.restore(); 60 | if (i % 50 == 0) ctx.commit(); 61 | } 62 | 63 | ctx.restore(); 64 | ctx.commit(); 65 | 66 | var nextSize: i32 = memory.size(); 67 | if (nextSize !== size) { 68 | log(size, nextSize); 69 | size = nextSize; 70 | } 71 | } 72 | 73 | export { memory } 74 | -------------------------------------------------------------------------------- /assembly/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | create_image, 3 | create_linear_gradient, 4 | create_pattern, 5 | create_radial_gradient, 6 | create_string, 7 | remove_image, 8 | remove_pattern, 9 | } from "./linked/util"; 10 | 11 | export { Image } from "./primitives/Image"; 12 | export { Matrix } from "./primitives/Matrix"; 13 | export { Path2DElement } from "./primitives/Path2DElement"; 14 | export { use_image, TextureMap } from "./primitives/TextureMap"; 15 | export { CanvasMap, CanvasRenderingContext2DInitializer } from "./primitives/CanvasMap"; 16 | export { ImageData } from "./primitives/ImageData"; 17 | 18 | export { CanvasGradient } from "./renderer/CanvasGradient"; 19 | export { CanvasPattern } from "./renderer/CanvasPattern"; 20 | export { CanvasRenderingContext2D } from "./renderer/CanvasRenderingContext2D"; 21 | export { CanvasRenderingContext2DSerializer } from "./renderer/CanvasRenderingContext2DSerializer"; 22 | export { OptimizedCanvasRenderingContext2D } from "./renderer/OptimizedCanvasRenderingContext2D"; 23 | export { Serializer } from "./renderer/Serializer"; 24 | 25 | export { CanvasInstruction } from "../src/shared/CanvasInstruction"; 26 | export { CanvasPatternType } from "../src/shared/CanvasPatternType"; 27 | export { Direction } from "../src/shared/Direction"; 28 | export { FillRule } from "../src/shared/FillRule"; 29 | export { GlobalCompositeOperation } from "../src/shared/GlobalCompositeOperation"; 30 | export { ImageSmoothingQuality } from "../src/shared/ImageSmoothingQuality"; 31 | export { LineCap } from "../src/shared/LineCap"; 32 | export { LineJoin } from "../src/shared/LineJoin"; 33 | export { TextAlign } from "../src/shared/TextAlign"; 34 | export { TextBaseline } from "../src/shared/TextBaseline"; 35 | 36 | export { copyTypedArray, doubleTypedArray } from "./util/TypedArray"; 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "canvas-as", 3 | "version": "1.0.0", 4 | "main": "dist/bundle.js", 5 | "types": "dist/index.d.ts", 6 | "license": "MIT", 7 | "devDependencies": { 8 | "@ampproject/rollup-plugin-closure-compiler": "^0.8.5", 9 | "@babel/core": "^7.2.2", 10 | "@babel/preset-env": "^7.2.0", 11 | "@babel/preset-typescript": "^7.1.0", 12 | "@types/webassembly-web-api": "^0.0.1", 13 | "http-server": "^0.11.1", 14 | "node-fetch": "^2.3.0", 15 | "npm-run-all": "^4.1.5", 16 | "onchange": "^5.2.0", 17 | "parcel-bundler": "^1.11.0", 18 | "regenerator-runtime": "^0.13.1", 19 | "rollup": "^1.0.1", 20 | "rollup-plugin-commonjs": "^9.2.0", 21 | "rollup-plugin-node-resolve": "^4.0.0", 22 | "rollup-plugin-typescript2": "^0.18.1", 23 | "ts-node": "^7.0.1", 24 | "tslint": "^5.11.0", 25 | "typescript": "^3.2.2" 26 | }, 27 | "scripts": { 28 | "start": "run-s asbuild:all canvas-as:watch", 29 | "build": "run-p asbuild:all build:glue", 30 | "build:glue": "rollup -c", 31 | "closure-compiler:glue": "node lib/closure-compiler.js", 32 | "http-server:demo": "http-server ./demo -c0 -p 1234", 33 | "canvas-as:watch": "run-p parcel:watch asbuild:watch http-server:demo", 34 | "parcel:watch": "parcel watch demo-src/index.html --public-url . --out-dir demo --no-cache", 35 | "asbuild:watch": "onchange \"assembly/**/*.ts\" -- npm run asbuild:all", 36 | "asbuild:untouched": "asc assembly/example.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --validate --debug --use Math=JSMath", 37 | "asbuild:optimized": "asc assembly/example.ts -b build/optimized.wasm -t build/optimized.wat --sourceMap --validate --optimize --use Math=JSMath", 38 | "asbuild:all": "run-p asbuild:untouched asbuild:optimized" 39 | }, 40 | "dependencies": { 41 | "assemblyscript": "github:assemblyscript/assemblyscript" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dist/shared/GlobalCompositeOperation.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var GlobalCompositeOperation; 4 | (function (GlobalCompositeOperation) { 5 | GlobalCompositeOperation[GlobalCompositeOperation["source_over"] = 0] = "source_over"; 6 | GlobalCompositeOperation[GlobalCompositeOperation["source_in"] = 1] = "source_in"; 7 | GlobalCompositeOperation[GlobalCompositeOperation["source_out"] = 2] = "source_out"; 8 | GlobalCompositeOperation[GlobalCompositeOperation["source_atop"] = 3] = "source_atop"; 9 | GlobalCompositeOperation[GlobalCompositeOperation["destination_over"] = 4] = "destination_over"; 10 | GlobalCompositeOperation[GlobalCompositeOperation["destination_in"] = 5] = "destination_in"; 11 | GlobalCompositeOperation[GlobalCompositeOperation["destination_out"] = 6] = "destination_out"; 12 | GlobalCompositeOperation[GlobalCompositeOperation["destination_atop"] = 7] = "destination_atop"; 13 | GlobalCompositeOperation[GlobalCompositeOperation["lighter"] = 8] = "lighter"; 14 | GlobalCompositeOperation[GlobalCompositeOperation["copy"] = 9] = "copy"; 15 | GlobalCompositeOperation[GlobalCompositeOperation["xor"] = 10] = "xor"; 16 | GlobalCompositeOperation[GlobalCompositeOperation["multiply"] = 11] = "multiply"; 17 | GlobalCompositeOperation[GlobalCompositeOperation["screen"] = 12] = "screen"; 18 | GlobalCompositeOperation[GlobalCompositeOperation["overlay"] = 13] = "overlay"; 19 | GlobalCompositeOperation[GlobalCompositeOperation["darken"] = 14] = "darken"; 20 | GlobalCompositeOperation[GlobalCompositeOperation["lighten"] = 15] = "lighten"; 21 | GlobalCompositeOperation[GlobalCompositeOperation["color_dodge"] = 16] = "color_dodge"; 22 | GlobalCompositeOperation[GlobalCompositeOperation["color_burn"] = 17] = "color_burn"; 23 | GlobalCompositeOperation[GlobalCompositeOperation["hard_light"] = 18] = "hard_light"; 24 | GlobalCompositeOperation[GlobalCompositeOperation["soft_light"] = 19] = "soft_light"; 25 | GlobalCompositeOperation[GlobalCompositeOperation["difference"] = 20] = "difference"; 26 | GlobalCompositeOperation[GlobalCompositeOperation["exclusion"] = 21] = "exclusion"; 27 | GlobalCompositeOperation[GlobalCompositeOperation["hue"] = 22] = "hue"; 28 | GlobalCompositeOperation[GlobalCompositeOperation["saturation"] = 23] = "saturation"; 29 | GlobalCompositeOperation[GlobalCompositeOperation["color"] = 24] = "color"; 30 | GlobalCompositeOperation[GlobalCompositeOperation["luminosity"] = 25] = "luminosity"; 31 | })(GlobalCompositeOperation = exports.GlobalCompositeOperation || (exports.GlobalCompositeOperation = {})); 32 | //# sourceMappingURL=GlobalCompositeOperation.js.map -------------------------------------------------------------------------------- /assembly/linked/util.ts: -------------------------------------------------------------------------------- 1 | import { Image, ImageData } from "../primitives"; 2 | import { CanvasPatternType } from "../../src/shared"; 3 | 4 | 5 | @external("__as_interop", "add_color_stop") 6 | export declare function add_color_stop(index: i32, point: f64, color: string): void; 7 | 8 | @external("__as_interop", "create_linear_gradient") 9 | export declare function create_linear_gradient(index: i32, x0: f64, y0: f64, x1: f64, y1: f64): void; 10 | 11 | @external("__as_interop", "create_pattern") 12 | export declare function create_pattern(index: i32, imageIndex: f64, patternType: CanvasPatternType): void; 13 | 14 | @external("__as_interop", "create_radial_gradient") 15 | export declare function create_radial_gradient(index: i32, x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64): void; 16 | 17 | @external("__as_interop", "create_string") 18 | export declare function create_string(index: f64, stringPointer: string): void; 19 | 20 | @external("__as_interop", "create_image") 21 | export declare function create_image(imagePointer: Image, source: string): void; 22 | 23 | @external("__as_interop", "put_image_data") 24 | export declare function put_image_data(id: string, data: ImageData, dx: i32, dy: i32): void; 25 | 26 | @external("__as_interop", "put_image_data_dirty") 27 | export declare function put_image_data_dirty(id: string, imagedata: ImageData, dx: i32, dy: i32, dirtyX: i32, dirtyY: i32, dirtyWidth: i32, dirtyHeight: i32): void; 28 | 29 | @external("__as_interop", "get_image_data") 30 | export declare function get_image_data(id: string, imageData: ImageData, sx: i32, sy: i32, sw: i32, sh: i32): void; 31 | 32 | @external("__as_interop", "remove_image") 33 | export declare function remove_image(index: i32): void; 34 | 35 | @external("__as_interop", "remove_pattern") 36 | export declare function remove_pattern(index: i32): void; 37 | 38 | @external("__as_interop", "remove_gradient") 39 | export declare function remove_gradient(index: i32): void; 40 | 41 | @external("__as_interop", "report_use_image") 42 | export declare function report_use_image(use: (input: string) => Image): void; 43 | 44 | @external("__as_interop", "report_image_loaded") 45 | export declare function report_image_loaded(loaded: (img: Image, width: f64, height: f64) => void): void; 46 | 47 | @external("__as_interop", "report_use_canvas") 48 | export declare function report_use_canvas(use: (name: string) => void): void; 49 | 50 | @external("__as_interop", "render") 51 | export declare function render(canvas: string, committed: Float64Array): void; 52 | 53 | @external("__as_interop", "log") 54 | export declare function log(a: i32, b: i32): void; 55 | 56 | @external("__as_interop", "inspect") 57 | export declare function inspect(data: Float64Array): void; 58 | -------------------------------------------------------------------------------- /dist/util/GlobalCompositeOperationLookup.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var GlobalCompositeOperationLookup; 4 | (function (GlobalCompositeOperationLookup) { 5 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["source-over"] = 0] = "source-over"; 6 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["source-in"] = 1] = "source-in"; 7 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["source-out"] = 2] = "source-out"; 8 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["source-atop"] = 3] = "source-atop"; 9 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["destination-over"] = 4] = "destination-over"; 10 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["destination-in"] = 5] = "destination-in"; 11 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["destination-out"] = 6] = "destination-out"; 12 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["destination-atop"] = 7] = "destination-atop"; 13 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["lighter"] = 8] = "lighter"; 14 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["copy"] = 9] = "copy"; 15 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["xor"] = 10] = "xor"; 16 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["multiply"] = 11] = "multiply"; 17 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["screen"] = 12] = "screen"; 18 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["overlay"] = 13] = "overlay"; 19 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["darken"] = 14] = "darken"; 20 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["lighten"] = 15] = "lighten"; 21 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["color-dodge"] = 16] = "color-dodge"; 22 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["color-burn"] = 17] = "color-burn"; 23 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["hard-light"] = 18] = "hard-light"; 24 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["soft-light"] = 19] = "soft-light"; 25 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["difference"] = 20] = "difference"; 26 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["exclusion"] = 21] = "exclusion"; 27 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["hue"] = 22] = "hue"; 28 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["saturation"] = 23] = "saturation"; 29 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["color"] = 24] = "color"; 30 | GlobalCompositeOperationLookup[GlobalCompositeOperationLookup["luminosity"] = 25] = "luminosity"; 31 | })(GlobalCompositeOperationLookup = exports.GlobalCompositeOperationLookup || (exports.GlobalCompositeOperationLookup = {})); 32 | //# sourceMappingURL=GlobalCompositeOperationLookup.js.map -------------------------------------------------------------------------------- /assembly/renderer/Serializer.ts: -------------------------------------------------------------------------------- 1 | import { log } from "../linked"; 2 | 3 | export class Serializer { 4 | index: i32 = 0; 5 | data: Float64Array = new Float64Array(8000); 6 | 7 | public init(): void { 8 | this.index = 0; 9 | } 10 | 11 | @inline 12 | protected write_zero(instruction: T): void { 13 | var next: i32 = this.index + 2; 14 | if (this.data.length <= next) this.grow(); 15 | this.write(instruction); 16 | this.write(next); 17 | } 18 | 19 | @inline 20 | protected write_one(instruction: T, value: f64): void { 21 | var next: i32 = this.index + 3; 22 | if (this.data.length <= next) this.grow(); 23 | this.write(instruction); 24 | this.write(next); 25 | this.write(value); 26 | } 27 | 28 | 29 | @inline 30 | protected write_two(instruction: T, a: f64, b: f64): void { 31 | var next: i32 = this.index + 4; 32 | if (this.data.length <= next) this.grow(); 33 | this.write(instruction); 34 | this.write(next); 35 | this.write(a); 36 | this.write(b); 37 | } 38 | 39 | @inline 40 | protected write_four(instruction: T, a: f64, b: f64, c: f64, d: f64): void { 41 | var next: i32 = this.index + 6; 42 | if (this.data.length <= next) this.grow(); 43 | this.write(instruction); 44 | this.write(next); 45 | this.write(a); 46 | this.write(b); 47 | this.write(c); 48 | this.write(d); 49 | } 50 | 51 | @inline 52 | protected write_five(instruction: T, a: f64, b: f64, c: f64, d: f64, e: f64): void { 53 | var next: i32 = this.index + 7; 54 | if (this.data.length <= next) this.grow(); 55 | this.write(instruction); 56 | this.write(next); 57 | this.write(a); 58 | this.write(b); 59 | this.write(c); 60 | this.write(d); 61 | this.write(e); 62 | } 63 | 64 | @inline 65 | protected write_six(instruction: T, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64): void { 66 | var next: i32 = this.index + 8; 67 | if (this.data.length <= next) this.grow(); 68 | this.write(instruction); 69 | this.write(next); 70 | this.write(a); 71 | this.write(b); 72 | this.write(c); 73 | this.write(d); 74 | this.write(e); 75 | this.write(f); 76 | } 77 | 78 | @inline 79 | protected write_eight(instruction: T, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64, g: f64, h: f64): void { 80 | var next: i32 = this.index + 10; 81 | if (this.data.length <= next) this.grow(); 82 | this.write(instruction); 83 | this.write(next); 84 | this.write(a); 85 | this.write(b); 86 | this.write(c); 87 | this.write(d); 88 | this.write(e); 89 | this.write(f); 90 | this.write(g); 91 | this.write(h); 92 | } 93 | 94 | @inline 95 | protected write_nine(instruction: T, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64, g: f64, h: f64, i: f64): void { 96 | var next: i32 = this.index + 11; 97 | if (this.data.length <= next) this.grow(); 98 | this.write(instruction); 99 | this.write(next); 100 | this.write(a); 101 | this.write(b); 102 | this.write(c); 103 | this.write(d); 104 | this.write(e); 105 | this.write(f); 106 | this.write(g); 107 | this.write(h); 108 | this.write(i); 109 | } 110 | 111 | @inline 112 | private write(value: f64): void { 113 | unchecked(this.data[this.index] = value); 114 | ++this.index; 115 | } 116 | 117 | @inline 118 | protected grow(): void { 119 | log(-1, this.data.length); 120 | log(-2, this.index); 121 | var data: Float64Array = new Float64Array(this.data.length + 8000); 122 | var length: i32 = this.data.length; 123 | var i: i32 = 0; 124 | while (i < length) { 125 | unchecked(data[i] = this.data[i]); 126 | ++i; 127 | } 128 | memory.free(changetype(this.data.buffer)); 129 | memory.free(changetype(this.data)); 130 | this.data = data; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "esnext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["dom", "es2018"], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "canvas-as.js", /* Concatenate and emit output to single file. */ 14 | "outDir": "./dist/", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | "strictNullChecks": true, /* Enable strict null checks. */ 27 | "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 29 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | 33 | /* Additional Checks */ 34 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | 39 | /* Module Resolution Options */ 40 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | // "typeRoots": [], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | }, 60 | "include": ["./src/**/*"] 61 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # canvas-as 2 | 3 | A small canvas rendering framerwork powered by `AssemblyScript` 🎉🎉🎉. 4 | 5 | ## About 6 | 7 | The `canvas-as` project was an experiemnt that lead to the development of a highly behavior tested version called [as2d](http://github.com/as2d/as2d). Since this project is not tested, and likely slower, I have deprecated it to be replaced by as2d. 8 | 9 | Thank you for your understanding. I have left this repo here for achival reasons. 10 | 11 | --------------- 12 | 13 | The `canvas-as` framework is a fun project that utilizes a lot of the hard work provided by the AssemblyScript project, which actually turned out to be quite performant! It avoids using repeated function calls over the wasm bridge, and compiles a set of canvas instructions to make drawing onto a canvas much easier from within `AssemblyScript`. 14 | 15 | ## Goal 16 | 17 | To provide a performant framework for utilizing the `CanvasRenderingContext2D`prototype in the browser, while following the javascript specification as closely as possible, and deviating where it makes sense. 18 | 19 | ## Current Compatibility 20 | 21 | Currently, `canvas-as` supports the following things: 22 | 23 | - Rendering and tracking canvas paths 24 | - Optimizing calls to setTransfrom and style properties via `OptimizedCanvasRenderingContext2D` 25 | - fillStyles and strokeStyles: strings, patterns, and gradients 26 | - Loading images from within the browser via the `Image#src` property 27 | - Virtual `ctx#save` and `ctx#restore` function calls which actually modify the assemblyscript canvas context itself 28 | 29 | On the roadmap, we plan to support: 30 | 31 | - Injecting image references into AssemblyScript (for image loading/preloading) 32 | - modifying style properties on the canvas 33 | - Garbage collection calls to the JS host to do memory cleanup (when AssemblyScript finally supports `@destructor`) 34 | - A declarative renderer (if AssemblyScript allows us to return `struct`s on the stack instead of on the heap via multi-valued parameters) 35 | 36 | # Usage 37 | 38 | ## Installation 39 | 40 | First, install `canvas-as` and `assemblyscript`: 41 | 42 | ``` 43 | npm install --save jtenner/canvas-as assemblyscript/assemblyscript 44 | ``` 45 | or... 46 | 47 | ``` 48 | yarn add jtenner/canvas-as assemblyscript/assemblyscript 49 | ``` 50 | 51 | ## Start Assemblyscript 52 | 53 | Then we need to create an `assemblyscript` project: 54 | 55 | ``` 56 | npx asinit . 57 | ``` 58 | 59 | or... 60 | 61 | ``` 62 | yarn asinit . 63 | ``` 64 | 65 | ## Create the AssemblyScript entry point 66 | 67 | A really great way to get started is create a module that looks something like this: 68 | 69 | ```ts 70 | // You need to import your own allocator 71 | import "allocator/tlsf"; 72 | 73 | // import CanvasRenderingContext2D and Image 74 | import { Image, CanvasMap } from "./index"; 75 | 76 | let kitten: Image = new Image(); 77 | let rotation: f64 = 0; 78 | let rotValue: f64 = Math.PI / 180.0; 79 | 80 | export function init(): void { 81 | // You cannot load an image until the wasm module has been completely loaded 82 | kitten.src = "https://placekitten.com/300/300"; 83 | // you can either get, or getOptimzed versions of the canvas context here 84 | ctx = CanvasMap.getOptimized("main"); 85 | } 86 | 87 | export function tick(): void { 88 | // update the world 89 | rotation += rotValue; 90 | 91 | // perform some simple drawing calls 92 | ctx.clearRect(0.0, 0.0, 800.0, 600.0); 93 | ctx.save(); 94 | ctx.translate(150.0, 150.0); 95 | ctx.rotate(rotation); 96 | ctx.translate(-150.0, -150.0); 97 | ctx.drawImagePosition(kitten, 0.0, 0.0); 98 | ctx.restore(); 99 | 100 | // calling commit() actually draws the canvas 101 | ctx.commit(); 102 | } 103 | 104 | export { memory } 105 | ``` 106 | 107 | ## Glue Code Setup 108 | 109 | The setup uses glue code provided by the `AssemblyScript` loader. Currently the only way to instantiate a `canvas-as` module is to use the constructor, and a fetch call. 110 | 111 | ```ts 112 | // import the canvas interop 113 | import { instantiateStreaming } from "canvas-as"; 114 | 115 | // create a context 116 | const ctx = document.querySelector("canvas").getContext("2d"); 117 | const imports: any = { 118 | // put your imports here 119 | }; 120 | 121 | // use an async function to load your module 122 | async function main(): Promise { 123 | // just need to wait for the module to instantiate 124 | const interop: CanvasASInterop = await instantiateStreaming(fetch("./my/module.wasm"), imports); 125 | 126 | // initialize the canvas context inside wasm 127 | interop.useContext("main", ctx); 128 | 129 | // call the init function yourself to help wasm get the reference it needs 130 | interop.wasm.init(); 131 | 132 | // setup a request animation frame loop 133 | requestAnimationFrame(function loop() { 134 | requestAnimationFrame(loop); 135 | 136 | // call tick() 137 | interop.tick(); 138 | }); 139 | } 140 | 141 | main(); 142 | ``` 143 | 144 | ## OptimizedCanvasRenderingContext2D 145 | 146 | This renderer is used when you want to minimize the number of javascript function calls. It's an exact drop in replacement for the `CanvasRenderingContext2D` class that only emits `setTransform`s and modified properties when they need to be modified. 147 | 148 | For instance, take the following example. 149 | 150 | ```ts 151 | var ctx = CanvasMap.getOptimized("main"); 152 | 153 | ctx.beginPath(); 154 | ctx.moveTo(10.0, 10.0); 155 | ctx.translate(100.0, 100.0); 156 | ctx.lineTo(100.0, 100.0); 157 | ctx.rotate(200.0); 158 | 159 | // the above instructions are effectively ignored, except for the `rotate` and `translate` functions 160 | ctx.beginPath(); 161 | ctx.rect(100.0, 100.0, 100.0, 100.0); 162 | ctx.stroke(); 163 | ``` 164 | 165 | In this case, the first path created with `beginPath()` gets effectively ignored by the browser. 166 | 167 | There is no reason to actually call those functions when `draw()` is called. 168 | 169 | Instead, the `OptimizedCanvasRenderingContext2D` emits *no* instructions and waits until a `fill()` or a `stroke()` is called. Thus when it gets to the `ctx.stroke()` call, it checks to see if the transform changed since the last time the `transform` property was updated, and emits a single `setTransform()` instruction, a `rect()` instruction, and a `stroke()` instruction. 170 | 171 | This costs more cpu power from within wasm, but doing cpu intensive things without garbage collection is what wasm does best! 172 | 173 | # Roadmap 174 | 175 | There are a bunch of problems that `canvas-as` currently does not solve. 176 | 177 | - Canvas mouse events 178 | - Canvas touch events 179 | - Canvas keyboard event 180 | - object lifetime management (managed object disposal and re-use with `@deconstructor` if and when AS supports it) 181 | - Canvas style management (changing the cursor, element size, etc) 182 | 183 | These things are all techincally possible with the exception of object lifetime management which is currently under development by the AssemblyScript team. Once destructors are supported, `canvas-as` will automatically perform memory management for you. 184 | 185 | As for all the other sort of canvas events and image injection, pull requests are 1000% welcome! Please feel free to contribute. 186 | 187 | ## Using Parcel? 188 | 189 | Note that when using `parcel-bundler`, you must use the `fs.readFileSync()` method to import your wasm into a buffer, since importing the wasm file directly bypasses the `assemblyscript` loader. The following glue code is unfortunately necessary: 190 | 191 | ```ts 192 | const fs = require("fs"); 193 | const buff = fs.readFileSync("./build/untouched.wasm"); 194 | const blob = new Blob([buff], { type: "application/wasm" }); 195 | const url = URL.createObjectURL(blob); 196 | const imports = {}; 197 | 198 | const interop = await instantiateStreaming(fetch(url)); 199 | interop.useContext("my-context", ctx); 200 | ``` 201 | 202 | Loading images using the canvas interop happens like this now: 203 | 204 | ```ts 205 | // ./src/index.ts 206 | var source: string = require("./path/to/image.png"); 207 | interop.useImage("image-name", fetch(source)); 208 | ``` 209 | 210 | Then inside your assemblyscript application: 211 | 212 | ```ts 213 | var ctx: CanvasRenderingContext2D = CanvasMap.get("my-context"); 214 | 215 | // ./assembly/index.ts 216 | if (TextureMap.has("image-name")) { 217 | // this image may not be loaded yet 218 | image = TextureMap.get("image-name"); 219 | } 220 | 221 | // always check to see if the image has been loaded 222 | if (image != null && image.loaded) { 223 | // do something with image 224 | } 225 | ``` 226 | 227 | ## License 228 | 229 | ``` 230 | Copyright (c) 2018 Joshua Tenner 231 | 232 | Permission is hereby granted, free of charge, to any person obtaining a copy 233 | of this software and associated documentation files (the "Software"), to deal 234 | in the Software without restriction, including without limitation the rights 235 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 236 | copies of the Software, and to permit persons to whom the Software is 237 | furnished to do so, subject to the following conditions: 238 | 239 | The above copyright notice and this permission notice shall be included in all 240 | copies or substantial portions of the Software. 241 | 242 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 243 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 244 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 245 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 246 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 247 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 248 | SOFTWARE. 249 | ``` 250 | -------------------------------------------------------------------------------- /assembly/renderer/CanvasRenderingContext2DSerializer.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CanvasInstruction, 3 | Direction, 4 | FillRule, 5 | GlobalCompositeOperation, 6 | ImageSmoothingQuality, 7 | LineCap, 8 | LineJoin, 9 | TextAlign, 10 | TextBaseline, 11 | } from "../../src/shared"; 12 | import { Serializer } from "./Serializer"; 13 | import { Image, ImageData } from "../primitives"; 14 | import { 15 | create_string, 16 | get_image_data, 17 | put_image_data, 18 | put_image_data_dirty, 19 | inspect, 20 | log, 21 | } from "../linked"; 22 | import { CanvasPattern } from "./CanvasPattern"; 23 | import { CanvasGradient } from "./CanvasGradient"; 24 | import { render } from "../linked"; 25 | 26 | const HEADER_SIZE = (offsetof() + 1) & ~1; 27 | const FNV_OFFSET: u32 = 2166136261; 28 | const FNV_PRIME: u32 = 16777619; 29 | 30 | function hashStr(key: string): u32 { 31 | var v = FNV_OFFSET; 32 | for (let i: usize = 0, k: usize = key.length << 1; i < k; ++i) { 33 | v = (v ^ load(changetype(key) + i, HEADER_SIZE)) * FNV_PRIME; 34 | } 35 | return v; 36 | } 37 | 38 | export class CanvasRenderingContext2DSerializer extends Serializer { 39 | public _id: string = ""; 40 | private _stringHashes: f64[] = new Array(0); 41 | private _stringHashIndex: i32 = 0; 42 | public init(): void { 43 | super.init(); 44 | } 45 | 46 | public commit(): void { 47 | if (super.index == 0) return; 48 | this.write_commit(); 49 | super.index = 0; 50 | for (var i = 0; i < this._stringHashes.length; i++) { 51 | unchecked(this._stringHashes[i] = 0.0); 52 | } 53 | render(this._id, this.data); 54 | } 55 | 56 | public inspect(): void { 57 | this.write_inspect(); 58 | inspect(this.data); 59 | } 60 | 61 | public getImageData(sx: i32, sy: i32, sw: i32, sh: i32): ImageData { 62 | var ref: ImageData = new ImageData(1, 2, false); 63 | get_image_data(this._id, ref, sx, sy, sw, sh); 64 | return ref; 65 | } 66 | 67 | public putImageData(imageData: ImageData, dx: i32, dy: i32): void { 68 | this.commit(); 69 | put_image_data(this._id, imageData, dx, dy); 70 | } 71 | 72 | public putImageDataDirty(imageData: ImageData, dx: i32, dy: i32, dirtyX: i32, dirtyY: i32, dirtyWidth: i32, dirtyHeight: i32): void { 73 | this.commit(); 74 | put_image_data_dirty(this._id, imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); 75 | } 76 | 77 | @inline 78 | protected write_arc(x: f64, y: f64, radius: f64, startAngle: f64, endAngle: f64, anticlockwise: bool): void { 79 | this.write_six( 80 | CanvasInstruction.Arc, 81 | x, 82 | y, 83 | radius, 84 | startAngle, 85 | endAngle, 86 | anticlockwise ? 1.0 : 0.0, 87 | ); 88 | } 89 | 90 | @inline 91 | protected write_arc_to(x1: f64, y1: f64, x2: f64, y2: f64, radius: f64): void { 92 | this.write_five( 93 | CanvasInstruction.ArcTo, 94 | x1, 95 | y1, 96 | x2, 97 | y2, 98 | radius, 99 | ); 100 | } 101 | 102 | @inline 103 | protected write_begin_path(): void { 104 | this.write_zero(CanvasInstruction.BeginPath); 105 | } 106 | 107 | @inline 108 | protected write_bezier_curve_to(cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64): void { 109 | this.write_six( 110 | CanvasInstruction.BezierCurveTo, 111 | cp1x, 112 | cp1y, 113 | cp2x, 114 | cp2y, 115 | x, 116 | y, 117 | ); 118 | } 119 | 120 | @inline 121 | protected write_clear_rect(x: f64, y: f64, width: f64, height: f64): void { 122 | this.write_four( 123 | CanvasInstruction.ClearRect, 124 | x, 125 | y, 126 | width, 127 | height, 128 | ); 129 | } 130 | 131 | @inline 132 | protected write_clip(fillRule: FillRule): void { 133 | this.write_one( 134 | CanvasInstruction.Clip, 135 | fillRule, 136 | ); 137 | } 138 | 139 | @inline 140 | protected write_close_path(): void { 141 | this.write_zero(CanvasInstruction.ClosePath); 142 | } 143 | 144 | @inline 145 | protected write_direction(value: Direction): void { 146 | this.write_one( 147 | CanvasInstruction.Direction, 148 | value, 149 | ); 150 | } 151 | 152 | @inline 153 | protected write_draw_focus_if_needed(): void { 154 | this.write_zero(CanvasInstruction.DrawFocusIfNeeded); 155 | } 156 | 157 | @inline 158 | protected write_draw_image(img: Image, sx: f64, sy: f64, swidth: f64, sheight: f64, x: f64, y: f64, width: f64, height: f64): void { 159 | this.write_nine( 160 | CanvasInstruction.DrawImage, 161 | img._index, 162 | sx, 163 | sy, 164 | swidth, 165 | sheight, 166 | x, 167 | y, 168 | width, 169 | height, 170 | ); 171 | } 172 | 173 | @inline 174 | protected write_ellipse(x: f64, y: f64, radiusX: f64, radiusY: f64, rotation: f64, startAngle: f64, endAngle: f64, anticlockwise: bool): void { 175 | this.write_eight( 176 | CanvasInstruction.Ellipse, 177 | x, 178 | y, 179 | radiusX, 180 | radiusY, 181 | rotation, 182 | startAngle, 183 | endAngle, 184 | anticlockwise ? 1.0 : 0.0, 185 | ); 186 | } 187 | 188 | @inline 189 | protected write_fill(fillRule: FillRule = FillRule.nonzero): void { 190 | this.write_one( 191 | CanvasInstruction.Fill, 192 | fillRule, 193 | ); 194 | } 195 | 196 | @inline 197 | protected write_fill_gradient(fillGradient: CanvasGradient): void { 198 | this.write_one( 199 | CanvasInstruction.FillGradient, 200 | fillGradient._id, 201 | ); 202 | } 203 | 204 | @inline 205 | protected write_fill_pattern(fillPattern: CanvasPattern): void { 206 | this.write_one( 207 | CanvasInstruction.FillPattern, 208 | fillPattern._id, 209 | ); 210 | } 211 | 212 | @inline 213 | protected write_fill_rect(x: f64, y: f64, width: f64, height: f64): void { 214 | this.write_four( 215 | CanvasInstruction.FillRect, 216 | x, 217 | y, 218 | width, 219 | height, 220 | ); 221 | } 222 | 223 | @inline 224 | protected write_fill_style(value: string): void { 225 | this.write_one( 226 | CanvasInstruction.FillStyle, 227 | this.send_string(value), 228 | ); 229 | } 230 | 231 | @inline 232 | protected write_fill_text(text: string, x: f64, y: f64, maxWidth: f64): void { 233 | this.write_four( 234 | CanvasInstruction.FillText, 235 | this.send_string(text), 236 | x, 237 | y, 238 | maxWidth, 239 | ); 240 | } 241 | 242 | @inline 243 | protected write_filter(value: string): void { 244 | this.write_one( 245 | CanvasInstruction.Filter, 246 | this.send_string(value), 247 | ); 248 | } 249 | 250 | @inline 251 | protected write_font(value: string): void { 252 | this.write_one( 253 | CanvasInstruction.Font, 254 | this.send_string(value), 255 | ) 256 | } 257 | 258 | @inline 259 | protected write_global_alpha(value: f64): void { 260 | this.write_one( 261 | CanvasInstruction.GlobalAlpha, 262 | value, 263 | ); 264 | } 265 | 266 | @inline 267 | protected write_global_composite_operation(value: GlobalCompositeOperation): void { 268 | this.write_one( 269 | CanvasInstruction.GlobalCompositeOperation, 270 | value, 271 | ) 272 | } 273 | 274 | @inline 275 | protected write_image_smoothing_enabled(value: bool): void { 276 | this.write_one( 277 | CanvasInstruction.ImageSmoothingEnabled, 278 | value ? 1.0 : 0.0, 279 | ); 280 | } 281 | 282 | @inline 283 | protected write_image_smoothing_quality(value: ImageSmoothingQuality): void { 284 | this.write_one( 285 | CanvasInstruction.ImageSmoothingQuality, 286 | value, 287 | ); 288 | } 289 | 290 | @inline 291 | protected write_inspect(): void { 292 | this.write_zero(CanvasInstruction.Inspect); 293 | } 294 | 295 | @inline 296 | protected write_line_cap(value: LineCap): void { 297 | this.write_one( 298 | CanvasInstruction.LineCap, 299 | value, 300 | ); 301 | } 302 | 303 | @inline 304 | protected write_line_dash(lineDash: Float64Array): void { 305 | this.write_one( 306 | CanvasInstruction.LineDash, 307 | changetype(lineDash), 308 | ); 309 | } 310 | 311 | @inline 312 | protected write_line_dash_offset(value: f64): void { 313 | this.write_one( 314 | CanvasInstruction.LineDashOffset, 315 | value, 316 | ); 317 | } 318 | 319 | @inline 320 | protected write_line_join(value: LineJoin): void { 321 | this.write_one( 322 | CanvasInstruction.LineJoin, 323 | value, 324 | ); 325 | } 326 | 327 | @inline 328 | protected write_line_to(x: f64, y: f64): void { 329 | this.write_two( 330 | CanvasInstruction.LineTo, 331 | x, 332 | y, 333 | ); 334 | } 335 | 336 | @inline 337 | protected write_line_width(value: f64): void { 338 | this.write_one( 339 | CanvasInstruction.LineWidth, 340 | value, 341 | ); 342 | } 343 | 344 | @inline 345 | protected write_miter_limit(value: f64): void { 346 | this.write_one( 347 | CanvasInstruction.MiterLimit, 348 | value, 349 | ); 350 | } 351 | 352 | @inline 353 | protected write_move_to(x: f64, y: f64): void { 354 | this.write_two( 355 | CanvasInstruction.MoveTo, 356 | x, 357 | y, 358 | ); 359 | } 360 | 361 | @inline 362 | protected write_quadratic_curve_to(cpx: f64, cpy: f64, x: f64, y: f64): void { 363 | this.write_four( 364 | CanvasInstruction.QuadraticCurveTo, 365 | cpx, 366 | cpy, 367 | x, 368 | y, 369 | ); 370 | } 371 | 372 | @inline 373 | protected write_rect(x: f64, y: f64, width: f64, height: f64): void { 374 | this.write_four( 375 | CanvasInstruction.Rect, 376 | x, 377 | y, 378 | width, 379 | height, 380 | ); 381 | } 382 | 383 | @inline 384 | protected write_restore(): void { 385 | this.write_zero(CanvasInstruction.Restore); 386 | } 387 | 388 | @inline 389 | protected write_rotate(angle: f64): void { 390 | this.write_one( 391 | CanvasInstruction.Rotate, 392 | angle, 393 | ); 394 | } 395 | 396 | @inline 397 | protected write_save(): void { 398 | this.write_zero(CanvasInstruction.Save); 399 | } 400 | 401 | @inline 402 | protected write_scale(x: f64, y: f64): void { 403 | this.write_two( 404 | CanvasInstruction.Scale, 405 | x, 406 | y, 407 | ); 408 | } 409 | 410 | @inline 411 | protected write_set_transform(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64 ): void { 412 | this.write_six( 413 | CanvasInstruction.SetTransform, 414 | a, 415 | b, 416 | c, 417 | d, 418 | e, 419 | f, 420 | ); 421 | } 422 | 423 | @inline 424 | protected write_shadow_blur(value: f64): void { 425 | this.write_one( 426 | CanvasInstruction.ShadowBlur, 427 | value, 428 | ); 429 | } 430 | 431 | @inline 432 | protected write_shadow_color(value: string): void { 433 | this.write_one( 434 | CanvasInstruction.ShadowColor, 435 | this.send_string(value), 436 | ); 437 | } 438 | 439 | @inline 440 | protected write_shadow_offset_x(value: f64): void { 441 | this.write_one( 442 | CanvasInstruction.ShadowOffsetX, 443 | value, 444 | ); 445 | } 446 | 447 | @inline 448 | protected write_shadow_offset_y(value: f64): void { 449 | this.write_one( 450 | CanvasInstruction.ShadowOffsetY, 451 | value, 452 | ); 453 | } 454 | 455 | @inline 456 | protected write_stroke(): void { 457 | this.write_zero(CanvasInstruction.Stroke); 458 | } 459 | 460 | @inline 461 | protected write_stroke_rect(x: f64, y: f64, width: f64, height: f64): void { 462 | this.write_four( 463 | CanvasInstruction.StrokeRect, 464 | x, 465 | y, 466 | width, 467 | height, 468 | ); 469 | } 470 | 471 | @inline 472 | protected write_stroke_gradient(strokeGradient: CanvasGradient): void { 473 | this.write_one( 474 | CanvasInstruction.StrokeGradient, 475 | strokeGradient._id, 476 | ); 477 | } 478 | 479 | @inline 480 | protected write_stroke_pattern(strokePattern: CanvasPattern): void { 481 | this.write_one( 482 | CanvasInstruction.StrokePattern, 483 | strokePattern._id, 484 | ); 485 | } 486 | 487 | @inline 488 | protected write_stroke_style(value: string): void { 489 | this.write_one( 490 | CanvasInstruction.StrokeStyle, 491 | this.send_string(value), 492 | ) 493 | } 494 | 495 | @inline 496 | protected write_stroke_text(text: string, x: f64, y: f64, maxWidth: f64): void { 497 | this.write_four( 498 | CanvasInstruction.StrokeText, 499 | this.send_string(text), 500 | x, 501 | y, 502 | maxWidth, 503 | ); 504 | } 505 | 506 | @inline 507 | protected write_text_align(value: TextAlign): void { 508 | this.write_one( 509 | CanvasInstruction.TextAlign, 510 | value, 511 | ); 512 | } 513 | 514 | @inline 515 | protected write_text_baseline(value: TextBaseline): void { 516 | this.write_one( 517 | CanvasInstruction.TextBaseline, 518 | value, 519 | ); 520 | } 521 | 522 | @inline 523 | protected write_transform(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64): void { 524 | this.write_six( 525 | CanvasInstruction.Transform, 526 | a, 527 | b, 528 | c, 529 | d, 530 | e, 531 | f, 532 | ); 533 | } 534 | 535 | @inline 536 | protected write_translate(x: f64, y: f64): void { 537 | this.write_two( 538 | CanvasInstruction.Translate, 539 | x, 540 | y, 541 | ); 542 | } 543 | 544 | @inline 545 | protected write_commit(): void { 546 | this.write_zero(CanvasInstruction.Commit); 547 | this.index = 0; 548 | } 549 | 550 | @inline 551 | protected send_string(value: string): f64 { 552 | var hash: f64 = hashStr(value); 553 | if (this._stringHashes.includes(hash)) return hash; 554 | 555 | if (this._stringHashIndex < this._stringHashes.length) { 556 | unchecked(this._stringHashes[this._stringHashIndex] = hash); 557 | } else { 558 | this._stringHashes.push(hash); 559 | } 560 | create_string(hash, value); 561 | return hash; 562 | } 563 | } 564 | -------------------------------------------------------------------------------- /dist/bundle.js: -------------------------------------------------------------------------------- 1 | 'use strict';(function(e,t){"object"===typeof exports&&"undefined"!==typeof module?t(exports):"function"===typeof define&&define.amd?define(["exports"],t):(e=e||self,t(e.canvasas={}))})(this,function(e){function t(a,c,b){var d=b+4>>>1;a=a[b>>>2];for(b=[];1024g?1023:1024;let e=c.subarray(d,d+=g);b.push(String.fromCharCode.apply(String,e));a-=g}return b.join("")+String.fromCharCode.apply(String,c.subarray(d,d+a))}function v(a){function c(a,b){if(!a)return""; 2 | a=a.buffer;return t(new Uint32Array(a),new Uint16Array(a),b)}var b={},d=a.env=a.env||{};d.abort=d.abort||function(a,e,k,l){var g=b.memory||d.memory;throw Error("abort: "+c(g,a)+" at "+c(g,e)+":"+k+":"+l);};d.trace=d.trace||function(a,e){console.log("trace: "+c(b.memory||d.memory,a)+(e?" ":"")+Array.prototype.slice.call(arguments,2,2+e).join(", "))};a.Math=a.Math||Math;a.Date=a.Date||Date;return b}function w(a,c){function b(){m!==d.buffer&&(m=d.buffer,z=new Int8Array(m),p=new Uint8Array(m),A=new Int16Array(m), 3 | x=new Uint16Array(m),q=new Int32Array(m),n=new Uint32Array(m),E&&(v=new BigInt64Array(m),w=new BigUint64Array(m)),r=new Float32Array(m),u=new Float64Array(m))}c=c.exports;var d=c.memory,g=c["memory.allocate"],e=c["memory.fill"],k=c["memory.free"],l=c.table,f=c._setargc||function(){},m,z,p,A,x,q,n,r,u,v,w;b();a.newString=function(a){var c=a.length,d=g(4+(c<<1)),e=4+d>>>1;b();n[d>>>2]=c;for(let b=0;b>>2]=p;n[l+4>>>2]=0;n[l+8>>>2]=k;n[p>>>2]=k;n[p+4>>>2]=0;a?((new f(m,p+8,c)).set(a),a.length>>2];return new a(m,n[c>>>2]+8+e,(n[c+ 5 | 8>>>2]-e)/d)};a.freeArray=function(a){b();k(n[a>>>2]);k(a)};a.newFunction=function(a){"function"===typeof a.original&&(a=a.original);var b=l.length;l.grow(1);l.set(b,a);return b};a.getFunction=function(a){return y(l.get(a),f)};a.memory=a.memory||d;a.table=a.table||l;return B(c,Object.defineProperties(a,{I8:{get:function(){b();return z}},U8:{get:function(){b();return p}},I16:{get:function(){b();return A}},U16:{get:function(){b();return x}},I32:{get:function(){b();return q}},U32:{get:function(){b(); 6 | return n}},I64:{get:function(){b();return v}},U64:{get:function(){b();return w}},F32:{get:function(){b();return r}},F64:{get:function(){b();return u}}}))}function y(a,c){var b=(...b)=>{c(b.length);return a(...b)};b.original=a;return b}function C(a,c){return w(v(c||(c={})),new WebAssembly.Instance(a,c))}function B(a,c){function b(a,b){return Object.prototype.hasOwnProperty.call(a,b)}c=c?Object.create(c):{};var d=a._setargc||function(){};for(let g in a){if(!b(a,g))continue;let l=a[g];var e=g.split("."); 7 | let f=c;for(;1Object.defineProperty(a,b,Object.getOwnPropertyDescriptor(k,b)));f[c]=a}e=e.substring(h+1);f=f[c].prototype;if(/^(get|set):/.test(e)){if(!b(f, 8 | e=e.substring(4))){let b=a[g.replace("set:","get:")],c=a[g.replace("get:","set:")];Object.defineProperty(f,e,{get:function(){return b(this[q])},set:function(a){c(this[q],a)},enumerable:!0})}}else"constructor"===e?f[e]=y(l,d):Object.defineProperty(f,e,{value:function(...a){d(a.length);return l(this[q],...a)}})}else/^(get|set):/.test(e)?b(f,e=e.substring(4))||Object.defineProperty(f,e,{get:a[g.replace("set:","get:")],set:a[g.replace("get:","set:")],enumerable:!0}):f[e]="function"===typeof l?y(l,d): 9 | l}return c}(function(a){a[a.ltr=0]="ltr";a[a.rtl=1]="rtl";a[a.inherit=2]="inherit"})(e.Direction||(e.Direction={}));(function(a){a[a.nonzero=0]="nonzero";a[a.evenodd=1]="evenodd"})(e.FillRule||(e.FillRule={}));(function(a){a[a.source_over=0]="source_over";a[a.source_in=1]="source_in";a[a.source_out=2]="source_out";a[a.source_atop=3]="source_atop";a[a.destination_over=4]="destination_over";a[a.destination_in=5]="destination_in";a[a.destination_out=6]="destination_out";a[a.destination_atop=7]="destination_atop"; 10 | a[a.lighter=8]="lighter";a[a.copy=9]="copy";a[a.xor=10]="xor";a[a.multiply=11]="multiply";a[a.screen=12]="screen";a[a.overlay=13]="overlay";a[a.darken=14]="darken";a[a.lighten=15]="lighten";a[a.color_dodge=16]="color_dodge";a[a.color_burn=17]="color_burn";a[a.hard_light=18]="hard_light";a[a.soft_light=19]="soft_light";a[a.difference=20]="difference";a[a.exclusion=21]="exclusion";a[a.hue=22]="hue";a[a.saturation=23]="saturation";a[a.color=24]="color";a[a.luminosity=25]="luminosity"})(e.GlobalCompositeOperation|| 11 | (e.GlobalCompositeOperation={}));(function(a){a[a.low=0]="low";a[a.medium=1]="medium";a[a.high=2]="high"})(e.ImageSmoothingQuality||(e.ImageSmoothingQuality={}));(function(a){a[a.butt=0]="butt";a[a.round=1]="round";a[a.square=2]="square"})(e.LineCap||(e.LineCap={}));(function(a){a[a.bevel=0]="bevel";a[a.round=1]="round";a[a.miter=2]="miter"})(e.LineJoin||(e.LineJoin={}));(function(a){a[a.left=0]="left";a[a.right=1]="right";a[a.center=2]="center";a[a.start=3]="start";a[a.end=4]="end"})(e.TextAlign|| 12 | (e.TextAlign={}));(function(a){a[a.top=0]="top";a[a.hanging=1]="hanging";a[a.middle=2]="middle";a[a.alphabetic=3]="alphabetic";a[a.ideographic=4]="ideographic";a[a.bottom=5]="bottom"})(e.TextBaseline||(e.TextBaseline={}));(function(a){a[a["source-over"]=0]="source-over";a[a["source-in"]=1]="source-in";a[a["source-out"]=2]="source-out";a[a["source-atop"]=3]="source-atop";a[a["destination-over"]=4]="destination-over";a[a["destination-in"]=5]="destination-in";a[a["destination-out"]=6]="destination-out"; 13 | a[a["destination-atop"]=7]="destination-atop";a[a.lighter=8]="lighter";a[a.copy=9]="copy";a[a.xor=10]="xor";a[a.multiply=11]="multiply";a[a.screen=12]="screen";a[a.overlay=13]="overlay";a[a.darken=14]="darken";a[a.lighten=15]="lighten";a[a["color-dodge"]=16]="color-dodge";a[a["color-burn"]=17]="color-burn";a[a["hard-light"]=18]="hard-light";a[a["soft-light"]=19]="soft-light";a[a.difference=20]="difference";a[a.exclusion=21]="exclusion";a[a.hue=22]="hue";a[a.saturation=23]="saturation";a[a.color=24]= 14 | "color";a[a.luminosity=25]="luminosity"})(e.GlobalCompositeOperationLookup||(e.GlobalCompositeOperationLookup={}));let D={0:"repeat",1:"repeat-x",2:"repeat-y",3:"no-repeat"},u=document.createElement("canvas").getContext("2d");class r{constructor(){this.contexts=new Map;this.strings={};this.images={};this.patterns={};this.gradients={};this.wasm=null;this.use_canvas=this.use_image=this.image_loaded=0}useContext(a,c){if(0===this.use_canvas)throw Error("CanvasASInterop hasn't loaded yet.");var b=this.wasm.getFunction(this.use_canvas); 15 | this.contexts.set(a,c);b(this.wasm.newString(a));return this}useImage(a,c){if(0===this.use_image)throw Error("CanvasASInterop hasn't loaded yet.");if(0===this.image_loaded)throw Error("CanvasASInterop hasn't loaded yet.");c.then((a)=>a.blob()).then((a)=>createImageBitmap(a)).then((b)=>{var c=this.wasm.newString(a);c=this.wasm.getFunction(this.use_image)(c);this.images[this.wasm.I32[c/Int32Array.BYTES_PER_ELEMENT]]=b;this.wasm.getFunction(this.image_loaded)(c,b.width,b.height)});return this}init(){return{add_color_stop:this.add_color_stop.bind(this), 16 | create_linear_gradient:this.create_linear_gradient.bind(this),create_pattern:this.create_pattern.bind(this),create_radial_gradient:this.create_radial_gradient.bind(this),create_string:this.create_string.bind(this),create_image:this.create_image.bind(this),get_image_data:this.get_image_data.bind(this),inspect:this.inspect.bind(this),remove_image:this.remove_image.bind(this),remove_pattern:this.remove_pattern.bind(this),remove_gradient:this.remove_gradient.bind(this),report_use_image:this.report_use_image.bind(this), 17 | report_image_loaded:this.report_image_loaded.bind(this),put_image_data:this.put_image_data.bind(this),put_image_data_dirty:this.put_image_data_dirty.bind(this),report_use_canvas:this.report_use_canvas.bind(this),render:this.render.bind(this),log:this.log.bind(this)}}render(a,c){var b=0,d=this.contexts.get(this.wasm.getString(a));if(!d)throw Error("Invalid context: "+a);for(a=this.wasm.getArray(Float64Array,c);b(0); 27 | private _fillStyle: FillStrokeWhichValue[] = new Array(0); 28 | private _filter: string[] = new Array(0); 29 | private _font: string[] = new Array(0); 30 | private _globalAlpha: f64[] = new Array(0); 31 | private _globalCompositeOperation: GlobalCompositeOperation[] = new Array(0); 32 | private _imageSmoothingEnabled: bool[] = new Array(0); 33 | private _imageSmoothingQuality: ImageSmoothingQuality[] = new Array(0); 34 | private _lineCap: LineCap[] = new Array(0); 35 | private _lineDash: Float64Array[] = new Array(0); 36 | private _lineDashOffset: f64[] = new Array(0); 37 | private _lineJoin: LineJoin[] = new Array(0); 38 | private _lineWidth: f64[] = new Array(0); 39 | private _miterLimit: f64[] = new Array(0); 40 | private _transformA: f64[] = new Array(0); 41 | private _transformB: f64[] = new Array(0); 42 | private _transformC: f64[] = new Array(0); 43 | private _transformD: f64[] = new Array(0); 44 | private _transformE: f64[] = new Array(0); 45 | private _transformF: f64[] = new Array(0); 46 | private _shadowBlur: f64[] = new Array(0); 47 | private _shadowColor: string[] = new Array(0); 48 | private _shadowOffsetX: f64[] = new Array(0); 49 | private _shadowOffsetY: f64[] = new Array(0); 50 | private _strokeStyle: FillStrokeWhichValue[] = new Array(0); 51 | private _textAlign: TextAlign[] = new Array(0); 52 | private _textBaseline: TextBaseline[] = new Array(0); 53 | private _stackIndex: i32 = 0; 54 | 55 | public init(): void { 56 | var i: i32 = 0; 57 | while (i < 100) { 58 | this._direction.push(Direction.inherit); 59 | this._fillStyle.push(new FillStrokeWhichValue()); 60 | this._filter.push("none"); 61 | this._font.push("none"); 62 | this._globalAlpha.push(1.0); 63 | this._globalCompositeOperation.push(GlobalCompositeOperation.source_over); 64 | this._imageSmoothingEnabled.push(true); 65 | this._imageSmoothingQuality.push(ImageSmoothingQuality.low); 66 | this._lineCap.push(LineCap.butt); 67 | this._lineDash.push(null); 68 | this._lineDashOffset.push(0.0); 69 | this._lineJoin.push(LineJoin.miter); 70 | this._lineWidth.push(1.0); 71 | this._miterLimit.push(10.0); 72 | this._transformA.push(1.0); 73 | this._transformB.push(0.0); 74 | this._transformC.push(0.0); 75 | this._transformD.push(1.0); 76 | this._transformE.push(0.0); 77 | this._transformF.push(0.0); 78 | this._shadowBlur.push(0.0); 79 | this._shadowColor.push("#000"); 80 | this._shadowOffsetX.push(0.0); 81 | this._shadowOffsetY.push(0.0); 82 | this._strokeStyle.push(new FillStrokeWhichValue()); 83 | this._textAlign.push(TextAlign.start); 84 | this._textBaseline.push(TextBaseline.alphabetic); 85 | i++; 86 | } 87 | this._lineDash[0] = new Float64Array(0); 88 | super.init(); 89 | } 90 | 91 | public save(): void { 92 | super.write_save(); 93 | var next: i32 = this._stackIndex + 1; 94 | this._direction[next] = this.direction; 95 | this._fillStyle[this._stackIndex].set(this._fillStyle[next]); 96 | this._filter[next] = this.filter; 97 | this._font[next] = this.font; 98 | this._globalAlpha[next] = this.globalAlpha; 99 | this._globalCompositeOperation[next] = this.globalCompositeOperation; 100 | this._imageSmoothingEnabled[next] = this.imageSmoothingEnabled; 101 | this._imageSmoothingQuality[next] = this.imageSmoothingQuality; 102 | this._lineCap[next] = this.lineCap; 103 | var nextLineDash: Float64Array = this._lineDash[next]; 104 | if (nextLineDash != null) { 105 | memory.free(changetype(this._lineDash[next].buffer)); 106 | memory.free(changetype(this._lineDash[next])); 107 | } 108 | this._lineDash[next] = null; 109 | this._lineDashOffset[next] = this.lineDashOffset; 110 | this._lineJoin[next] = this.lineJoin; 111 | this._lineWidth[next] = this.lineWidth; 112 | this._miterLimit[next] = this.miterLimit; 113 | this._transformA[next] = this._transformA[this._stackIndex]; 114 | this._transformB[next] = this._transformB[this._stackIndex]; 115 | this._transformC[next] = this._transformC[this._stackIndex]; 116 | this._transformD[next] = this._transformD[this._stackIndex]; 117 | this._transformE[next] = this._transformE[this._stackIndex]; 118 | this._transformF[next] = this._transformF[this._stackIndex]; 119 | this._shadowBlur[next] = this.shadowBlur; 120 | this._shadowColor[next] = this.shadowColor; 121 | this._shadowOffsetX[next] = this.shadowOffsetX; 122 | this._shadowOffsetY[next] = this.shadowOffsetY; 123 | this._strokeStyle[this._stackIndex].set(this._strokeStyle[next]); 124 | this._textAlign[next] = this.textAlign; 125 | this._textBaseline[next] = this.textBaseline; 126 | 127 | this._stackIndex = next; 128 | } 129 | 130 | public restore(): void { 131 | super.write_restore(); 132 | --this._stackIndex; 133 | } 134 | 135 | public arc(x: f64, y: f64, radius: f64, startAngle: f64, endAngle: f64, anticlockwise: bool = false): void { 136 | super.write_arc(x, y, radius, startAngle, endAngle, anticlockwise); 137 | } 138 | 139 | public arcTo(x1: f64, y1: f64, x2: f64, y2: f64, radius: f64): void { 140 | super.write_arc_to(x1, y1, x2, y2, radius); 141 | } 142 | 143 | public beginPath(): void { 144 | super.write_begin_path(); 145 | } 146 | 147 | public bezierCurveTo(cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64): void { 148 | super.write_bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y); 149 | } 150 | 151 | public clearRect(x: f64, y: f64, width: f64, height: f64): void { 152 | super.write_clear_rect(x, y, width, height); 153 | } 154 | 155 | public clip(fillRule: FillRule = FillRule.evenodd): void { 156 | super.write_clip(fillRule); 157 | } 158 | 159 | public closePath(): void { 160 | super.write_close_path(); 161 | } 162 | 163 | public createLinearGradient(x0: f64, y0: f64, x1: f64, y1: f64): CanvasGradient { 164 | var result: CanvasGradient = new CanvasGradient(); 165 | create_linear_gradient(result._id, x0, y0, x1, y1); 166 | return result; 167 | } 168 | 169 | public createPattern(image: Image, type: CanvasPatternType): CanvasPattern { 170 | var pattern = new CanvasPattern(); 171 | create_pattern(pattern._id, image._index, type); 172 | return pattern; 173 | } 174 | 175 | public createRadialGradient(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64): CanvasGradient { 176 | var result: CanvasGradient = new CanvasGradient(); 177 | create_radial_gradient(result._id, x0, y0, r0, x1, y1, r1); 178 | return result; 179 | } 180 | 181 | get currentTransform(): Matrix { 182 | return Matrix.create( 183 | this._transformA[this._stackIndex], 184 | this._transformB[this._stackIndex], 185 | this._transformC[this._stackIndex], 186 | this._transformD[this._stackIndex], 187 | this._transformE[this._stackIndex], 188 | this._transformF[this._stackIndex], 189 | ); 190 | } 191 | 192 | set currentTransform(value: Matrix) { 193 | this._transformA[this._stackIndex] = value.a; 194 | this._transformB[this._stackIndex] = value.b; 195 | this._transformC[this._stackIndex] = value.c; 196 | this._transformD[this._stackIndex] = value.d; 197 | this._transformE[this._stackIndex] = value.e; 198 | this._transformF[this._stackIndex] = value.f; 199 | super.write_set_transform(value.a, value.b, value.c, value.d, value.e, value.f); 200 | } 201 | 202 | get direction(): Direction { 203 | return this._direction[this._stackIndex]; 204 | } 205 | 206 | set direction(value: Direction) { 207 | this._direction[this._stackIndex] = value; 208 | super.write_direction(value); 209 | } 210 | 211 | public drawFocusedIfNeeded(): void { 212 | super.write_draw_focus_if_needed(); 213 | } 214 | 215 | public drawImage(img: Image, sx: f64, sy: f64, swidth: f64, sheight: f64, x: f64, y: f64, width: f64, height: f64): void { 216 | if (!img._loaded) return; 217 | super.write_draw_image(img, sx, sy, swidth, sheight, x, y, width, height); 218 | } 219 | 220 | public drawImagePosition(img: Image, x: f64, y: f64): void { 221 | if (!img._loaded) return; 222 | super.write_draw_image(img, 0.0, 0.0, img.width, img.height, x, y, img.width, img.height); 223 | } 224 | 225 | public drawImageSize(img: Image, x: f64, y: f64, width: f64, height: f64): void { 226 | if (!img._loaded) return; 227 | super.write_draw_image(img, 0.0, 0.0, img.width, img.height, x, y, width, height); 228 | } 229 | 230 | public ellipse(x: f64, y: f64, radiusX: f64, radiusY: f64, rotation: f64, startAngle: f64, endAngle: f64, anticlockwise: bool = false): void { 231 | super.write_ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise); 232 | } 233 | 234 | public fill(fillRule: FillRule = FillRule.nonzero): void { 235 | super.write_fill(fillRule); 236 | } 237 | 238 | public fillRect(x: f64, y: f64, width: f64, height: f64): void { 239 | super.write_fill_rect(x, y, width, height); 240 | } 241 | 242 | get fillGradient(): CanvasGradient | null { 243 | if (this._fillStyle[this._stackIndex].which != FillStrokeWhich.Gradient) return null; 244 | return this._fillStyle[this._stackIndex].gradient; 245 | } 246 | 247 | set fillGradient(value: CanvasGradient | null) { 248 | if (value == null) return; 249 | this._fillStyle[this._stackIndex].gradient = value; 250 | this._fillStyle[this._stackIndex].which = FillStrokeWhich.Gradient; 251 | super.write_fill_gradient(value); 252 | } 253 | 254 | get fillPattern(): CanvasPattern | null { 255 | if (this._fillStyle[this._stackIndex].which != FillStrokeWhich.Pattern) return null; 256 | return this._fillStyle[this._stackIndex].pattern; 257 | } 258 | 259 | set fillPattern(value: CanvasPattern | null) { 260 | if (value == null) return; 261 | this._fillStyle[this._stackIndex].pattern = value; 262 | this._fillStyle[this._stackIndex].which = FillStrokeWhich.Pattern; 263 | super.write_fill_pattern(value); 264 | } 265 | 266 | get fillStyle(): string | null { 267 | if (this._fillStyle[this._stackIndex].which != FillStrokeWhich.Style) return null; 268 | return this._fillStyle[this._stackIndex].style; 269 | } 270 | 271 | set fillStyle(value: string | null) { 272 | var result: string = value === null ? "#000" : value; 273 | this._fillStyle[this._stackIndex].style = result; 274 | this._fillStyle[this._stackIndex].which = FillStrokeWhich.Style; 275 | super.write_fill_style(result); 276 | } 277 | 278 | public fillText(text: string, x: f64, y: f64, maxWidth: f64 = -1.0): void { 279 | super.write_fill_text(text, x, y, maxWidth); 280 | } 281 | 282 | get filter(): string { 283 | return this._filter[this._stackIndex]; 284 | } 285 | 286 | set filter(value: string) { 287 | this._filter[this._stackIndex] = value; 288 | super.write_filter(value); 289 | } 290 | 291 | get font(): string { 292 | return this._font[this._stackIndex]; 293 | } 294 | 295 | set font(value: string) { 296 | this._font[this._stackIndex] = value; 297 | super.write_font(value); 298 | } 299 | 300 | get globalAlpha(): f64 { 301 | return this._globalAlpha[this._stackIndex]; 302 | } 303 | 304 | set globalAlpha(value: f64) { 305 | this._globalAlpha[this._stackIndex] = Math.min(0, Math.max(value, 1.0)); 306 | super.write_global_alpha(value); 307 | } 308 | 309 | get globalCompositeOperation(): GlobalCompositeOperation { 310 | return this._globalCompositeOperation[this._stackIndex]; 311 | } 312 | 313 | set globalCompositeOperation(value: GlobalCompositeOperation) { 314 | this._globalCompositeOperation[this._stackIndex] = value; 315 | super.write_global_composite_operation(value); 316 | } 317 | 318 | get imageSmoothingEnabled(): bool { 319 | return this._imageSmoothingEnabled[this._stackIndex]; 320 | } 321 | 322 | set imageSmoothingEnabled(value: bool) { 323 | this._imageSmoothingEnabled[this._stackIndex] = value; 324 | super.write_image_smoothing_enabled(value); 325 | } 326 | 327 | get imageSmoothingQuality(): ImageSmoothingQuality { 328 | return this._imageSmoothingQuality[this._stackIndex]; 329 | } 330 | 331 | set imageSmoothingQuality(value: ImageSmoothingQuality) { 332 | this._imageSmoothingQuality[this._stackIndex] = value; 333 | super.write_image_smoothing_quality(value); 334 | } 335 | 336 | get lineCap(): LineCap { 337 | return this._lineCap[this._stackIndex]; 338 | } 339 | 340 | set lineCap(value: LineCap) { 341 | this._lineCap[this._stackIndex] = value; 342 | super.write_line_cap(value); 343 | } 344 | 345 | public getLineDash(): Float64Array { 346 | var array: Float64Array | null = null; 347 | for (var i = this._stackIndex; i >= 0; --i) { 348 | if (this._lineDash[i] == null) continue; 349 | array = this._lineDash[i]; 350 | } 351 | if (array == null) throw new Error("Cannot get lineDash value. The lineDash stack is null."); 352 | return array; 353 | } 354 | 355 | public setLineDash(value: Float64Array): void { 356 | this._lineDash[this._stackIndex] = 357 | ((value.length & 1) == 1) 358 | ? doubleTypedArray(value) 359 | : copyTypedArray(value); 360 | super.write_line_dash(this._lineDash[this._stackIndex]); 361 | } 362 | 363 | get lineDashOffset(): f64 { 364 | return this._lineDashOffset[this._stackIndex]; 365 | } 366 | 367 | set lineDashOffset(value: f64) { 368 | this._lineDashOffset[this._stackIndex] = value; 369 | super.write_line_dash_offset(value); 370 | } 371 | 372 | get lineJoin(): LineJoin { 373 | return this._lineJoin[this._stackIndex]; 374 | } 375 | 376 | set lineJoin(value: LineJoin) { 377 | this._lineJoin[this._stackIndex] = value; 378 | super.write_line_join(value); 379 | } 380 | 381 | public lineTo(x: f64, y: f64): void { 382 | super.write_line_to(x, y); 383 | } 384 | 385 | get lineWidth(): f64 { 386 | return this._lineWidth[this._stackIndex]; 387 | } 388 | 389 | set lineWidth(value: f64) { 390 | this._lineWidth[this._stackIndex] = value; 391 | super.write_line_width(value); 392 | } 393 | 394 | get miterLimit(): f64 { 395 | return this._miterLimit[this._stackIndex]; 396 | } 397 | 398 | set miterLimit(value: f64) { 399 | this._miterLimit[this._stackIndex] = value; 400 | super.write_miter_limit(value); 401 | } 402 | 403 | public moveTo(x: f64, y: f64): void { 404 | super.write_move_to(x, y); 405 | } 406 | 407 | public quadraticCurveTo(cpx: f64, cpy: f64, x: f64, y: f64): void { 408 | super.write_quadratic_curve_to(cpx, cpy, x, y); 409 | } 410 | 411 | public rect(x: f64, y: f64, width: f64, height: f64): void { 412 | super.write_rect(x, y, width, height); 413 | } 414 | 415 | public rotate(angle: f64): void { 416 | var cos: f64 = Math.cos(angle); 417 | var sin: f64 = Math.sin(angle); 418 | 419 | var a: f64 = this._transformA[this._stackIndex]; 420 | var b: f64 = this._transformB[this._stackIndex]; 421 | var c: f64 = this._transformC[this._stackIndex]; 422 | var d: f64 = this._transformD[this._stackIndex]; 423 | this._transformA[this._stackIndex] = a * cos + c * sin; 424 | this._transformB[this._stackIndex] = b * cos + d * sin; 425 | this._transformC[this._stackIndex] = a * -sin + c * cos; 426 | this._transformD[this._stackIndex] = b * -sin + d * cos; 427 | super.write_rotate(angle); 428 | } 429 | 430 | public scale(x: f64, y: f64): void { 431 | this._transformA[this._stackIndex] *= x; 432 | this._transformB[this._stackIndex] *= x; 433 | this._transformC[this._stackIndex] *= y; 434 | this._transformD[this._stackIndex] *= y; 435 | super.write_scale(x, y); 436 | } 437 | 438 | public setTransform(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64): void { 439 | this._transformA[this._stackIndex] = a; 440 | this._transformB[this._stackIndex] = b; 441 | this._transformC[this._stackIndex] = c; 442 | this._transformD[this._stackIndex] = d; 443 | this._transformE[this._stackIndex] = e; 444 | this._transformF[this._stackIndex] = f; 445 | super.write_transform(a, b, c, d, e, f); 446 | } 447 | 448 | get shadowBlur(): f64 { 449 | return this._shadowBlur[this._stackIndex]; 450 | } 451 | 452 | set shadowBlur(value: f64) { 453 | this._shadowBlur[this._stackIndex] = value; 454 | super.write_shadow_blur(value); 455 | } 456 | 457 | get shadowColor(): string { 458 | return this._shadowColor[this._stackIndex]; 459 | } 460 | 461 | set shadowColor(value: string) { 462 | this._shadowColor[this._stackIndex] = value; 463 | super.write_shadow_color(value); 464 | } 465 | 466 | get shadowOffsetX(): f64 { 467 | return this._shadowOffsetX[this._stackIndex]; 468 | } 469 | 470 | set shadowOffsetX(value: f64) { 471 | this._shadowOffsetX[this._stackIndex] = value; 472 | super.write_shadow_offset_x(value); 473 | } 474 | 475 | get shadowOffsetY(): f64 { 476 | return this._shadowOffsetY[this._stackIndex]; 477 | } 478 | 479 | set shadowOffsetY(value: f64) { 480 | this._shadowOffsetY[this._stackIndex] = value; 481 | super.write_shadow_offset_y(value); 482 | } 483 | 484 | public stroke(): void { 485 | super.write_stroke(); 486 | } 487 | 488 | public strokeRect(x: f64, y: f64, width: f64, height: f64): void { 489 | super.write_stroke_rect(x, y, width, height); 490 | } 491 | 492 | get strokeStyle(): string | null { 493 | if (this._strokeStyle[this._stackIndex].which != FillStrokeWhich.Style) return null; 494 | return this._strokeStyle[this._stackIndex].style; 495 | } 496 | 497 | set strokeStyle(value: string | null) { 498 | var result: string = value === null ? "#000" : value; 499 | this._strokeStyle[this._stackIndex].style = result; 500 | this._strokeStyle[this._stackIndex].which = FillStrokeWhich.Style; 501 | super.write_stroke_style(result); 502 | } 503 | 504 | get strokeGradient(): CanvasGradient | null { 505 | if (this._strokeStyle[this._stackIndex].which != FillStrokeWhich.Gradient) return null; 506 | return this._strokeStyle[this._stackIndex].gradient; 507 | } 508 | 509 | set strokeGradient(value: CanvasGradient | null) { 510 | if (value == null) return; 511 | this._strokeStyle[this._stackIndex].gradient = value; 512 | this._strokeStyle[this._stackIndex].which = FillStrokeWhich.Gradient; 513 | super.write_stroke_gradient(value); 514 | } 515 | 516 | get strokePattern(): CanvasPattern | null { 517 | if (this._strokeStyle[this._stackIndex].which != FillStrokeWhich.Pattern) return null; 518 | return this._strokeStyle[this._stackIndex].pattern; 519 | } 520 | 521 | set strokePattern(value: CanvasPattern | null) { 522 | if (value == null) return; 523 | this._strokeStyle[this._stackIndex].pattern = value; 524 | this._strokeStyle[this._stackIndex].which = FillStrokeWhich.Pattern; 525 | super.write_stroke_pattern(value); 526 | } 527 | 528 | public strokeText(text: string, x: f64, y: f64, maxWidth: f64 = -1.0): void { 529 | super.write_stroke_text(text, x, y, maxWidth); 530 | } 531 | 532 | get textAlign(): TextAlign { 533 | return this._textAlign[this._stackIndex]; 534 | } 535 | 536 | set textAlign(value: TextAlign) { 537 | this._textAlign[this._stackIndex] = value; 538 | super.write_text_align(value); 539 | } 540 | 541 | get textBaseline(): TextBaseline { 542 | return this._textBaseline[this._stackIndex]; 543 | } 544 | 545 | set textBaseline(value: TextBaseline) { 546 | this._textBaseline[this._stackIndex] = value; 547 | super.write_text_baseline(value); 548 | } 549 | 550 | public transform(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64): void { 551 | var sa: f64 = this._transformA[this._stackIndex]; 552 | var sb: f64 = this._transformB[this._stackIndex]; 553 | var sc: f64 = this._transformC[this._stackIndex]; 554 | var sd: f64 = this._transformD[this._stackIndex]; 555 | var se: f64 = this._transformE[this._stackIndex]; 556 | var sf: f64 = this._transformF[this._stackIndex]; 557 | this._transformA[this._stackIndex] = sa * a + sc * b; 558 | this._transformB[this._stackIndex] = sb * a + sd * b; 559 | this._transformC[this._stackIndex] = sa * c + sc * d; 560 | this._transformD[this._stackIndex] = sb * c + sd * d; 561 | this._transformE[this._stackIndex] = sa * e + sc * f + se; 562 | this._transformF[this._stackIndex] = sb * e + sd * f + sf; 563 | super.write_transform(a, b, c, d, e, f); 564 | } 565 | 566 | public translate(x: f64, y: f64): void { 567 | this._transformE[this._stackIndex] += this._transformA[this._stackIndex] * x + this._transformC[this._stackIndex] * y; 568 | this._transformF[this._stackIndex] += this._transformB[this._stackIndex] * x + this._transformD[this._stackIndex] * y; 569 | super.write_translate(x, y); 570 | } 571 | } 572 | -------------------------------------------------------------------------------- /src/interop/CanvasASInterop.ts: -------------------------------------------------------------------------------- 1 | import { ASUtil, TypedArrayConstructor } from "assemblyscript/lib/loader"; 2 | import { 3 | CanvasPatternType, 4 | CanvasInstruction, 5 | Direction, 6 | FillRule, 7 | LineCap, 8 | LineJoin, 9 | ImageSmoothingQuality, 10 | TextAlign, 11 | TextBaseline, 12 | } from "../shared"; 13 | import { 14 | GlobalCompositeOperationLookup, 15 | IImageBitmapIndex, 16 | ICanvasPatternIndex, 17 | ICanvasGradientIndex, 18 | canvasPatternTypes, 19 | ImageLoadedCallback, 20 | ImageUseCallback, 21 | } from "../util"; 22 | 23 | const ctx = document.createElement("canvas").getContext("2d"); 24 | 25 | export class CanvasASInterop { 26 | public contexts: Map = new Map(); 27 | public strings: { [hash: number]: string } = {}; 28 | public images: IImageBitmapIndex = {}; 29 | public patterns: ICanvasPatternIndex = {}; 30 | public gradients: ICanvasGradientIndex = {}; 31 | public wasm: (ASUtil & T) | null = null; 32 | 33 | private image_loaded: number = 0; 34 | private use_image: number = 0; 35 | private use_canvas: number = 0; 36 | 37 | constructor() {} 38 | 39 | public useContext(name: string, value: CanvasRenderingContext2D): this { 40 | if (this.use_canvas === 0) throw new Error("CanvasASInterop hasn't loaded yet."); 41 | var func = this.wasm!.getFunction(this.use_canvas); 42 | this.contexts.set(name, value); 43 | func(this.wasm!.newString(name)); 44 | return this; 45 | } 46 | 47 | public useImage(name: string, value: Promise): this { 48 | if (this.use_image === 0) throw new Error("CanvasASInterop hasn't loaded yet."); 49 | if (this.image_loaded === 0) throw new Error("CanvasASInterop hasn't loaded yet."); 50 | value.then(e => e.blob()) 51 | .then(e => createImageBitmap(e)) 52 | .then(bitmap => { 53 | const strPtr: number = this.wasm!.newString(name); 54 | const useFunc = this.wasm!.getFunction(this.use_image) as ImageUseCallback; 55 | const imagePointer: number = useFunc(strPtr); 56 | const imageIndex: number = imagePointer / Int32Array.BYTES_PER_ELEMENT; 57 | this.images[this.wasm!.I32[imageIndex]] = bitmap; 58 | const loadedFunc = this.wasm!.getFunction(this.image_loaded) as ImageLoadedCallback; 59 | loadedFunc(imagePointer, bitmap.width, bitmap.height); 60 | }); 61 | return this; 62 | } 63 | 64 | public init(): any { 65 | return { 66 | add_color_stop: this.add_color_stop.bind(this), 67 | create_linear_gradient: this.create_linear_gradient.bind(this), 68 | create_pattern: this.create_pattern.bind(this), 69 | create_radial_gradient: this.create_radial_gradient.bind(this), 70 | create_string: this.create_string.bind(this), 71 | create_image: this.create_image.bind(this), 72 | get_image_data: this.get_image_data.bind(this), 73 | inspect: this.inspect.bind(this), 74 | remove_image: this.remove_image.bind(this), 75 | remove_pattern: this.remove_pattern.bind(this), 76 | remove_gradient: this.remove_gradient.bind(this), 77 | report_use_image: this.report_use_image.bind(this), 78 | report_image_loaded: this.report_image_loaded.bind(this), 79 | put_image_data: this.put_image_data.bind(this), 80 | put_image_data_dirty: this.put_image_data_dirty.bind(this), 81 | report_use_canvas: this.report_use_canvas.bind(this), 82 | render: this.render.bind(this), 83 | log: this.log.bind(this), 84 | }; 85 | } 86 | 87 | private render(name: number, dataPointer: number): void { 88 | var index: number = 0; 89 | var ctx: CanvasRenderingContext2D | undefined = this.contexts.get(this.wasm!.getString(name)); 90 | if (!ctx) throw new Error("Invalid context: " + name); 91 | var data: Float64Array = this.wasm!.getArray(Float64Array as any as TypedArrayConstructor, dataPointer); 92 | while (index < data.length) { 93 | if (data[index] === CanvasInstruction.Commit) { 94 | this.strings = {}; 95 | break; 96 | } 97 | switch(data[index]) { 98 | case CanvasInstruction.Arc: { 99 | ctx.arc( 100 | data[index + 2], 101 | data[index + 3], 102 | data[index + 4], 103 | data[index + 5], 104 | data[index + 6], 105 | data[index + 7] === 1, 106 | ); 107 | break; 108 | } 109 | case CanvasInstruction.ArcTo: { 110 | ctx.arcTo( 111 | data[index + 2], 112 | data[index + 3], 113 | data[index + 4], 114 | data[index + 5], 115 | data[index + 6], 116 | ); 117 | break; 118 | } 119 | case CanvasInstruction.BeginPath: { 120 | ctx.beginPath(); 121 | break; 122 | } 123 | case CanvasInstruction.BezierCurveTo: { 124 | ctx.bezierCurveTo( 125 | data[index + 2], 126 | data[index + 3], 127 | data[index + 4], 128 | data[index + 5], 129 | data[index + 6], 130 | data[index + 7], 131 | ); 132 | break; 133 | } 134 | case CanvasInstruction.ClearRect: { 135 | ctx.clearRect( 136 | data[index + 2], 137 | data[index + 3], 138 | data[index + 4], 139 | data[index + 5], 140 | ); 141 | break; 142 | } 143 | case CanvasInstruction.Clip: { 144 | ctx.clip(); 145 | break; 146 | } 147 | case CanvasInstruction.ClosePath: { 148 | ctx.closePath(); 149 | break; 150 | } 151 | case CanvasInstruction.Direction: { 152 | ctx.direction = Direction[data[index + 2]] as CanvasDirection; 153 | break; 154 | } 155 | case CanvasInstruction.DrawImage: { 156 | if (!this.images[data[index + 2]]) break; 157 | ctx.drawImage( 158 | this.images[data[index + 2]]!, 159 | data[index + 3], 160 | data[index + 4], 161 | data[index + 5], 162 | data[index + 6], 163 | data[index + 7], 164 | data[index + 8], 165 | data[index + 9], 166 | data[index + 10], 167 | ); 168 | break; 169 | } 170 | case CanvasInstruction.Ellipse: { 171 | ctx.ellipse( 172 | data[index + 2], 173 | data[index + 3], 174 | data[index + 4], 175 | data[index + 5], 176 | data[index + 6], 177 | data[index + 7], 178 | data[index + 8], 179 | data[index + 9] === 1.0, 180 | ); 181 | break; 182 | } 183 | case CanvasInstruction.Fill: { 184 | ctx.fill(FillRule[data[index + 2]] as CanvasFillRule); 185 | break; 186 | } 187 | case CanvasInstruction.FillGradient: { 188 | ctx.fillStyle = this.gradients[data[index + 2]]!; 189 | break; 190 | } 191 | case CanvasInstruction.FillPattern: { 192 | ctx.fillStyle = this.patterns[data[index + 2]]!; 193 | break; 194 | } 195 | case CanvasInstruction.FillRect: { 196 | ctx.fillRect( 197 | data[index + 2], 198 | data[index + 3], 199 | data[index + 4], 200 | data[index + 5], 201 | ); 202 | break; 203 | } 204 | case CanvasInstruction.FillStyle: { 205 | if (!this.strings[data[index + 2]]) break; 206 | ctx.fillStyle = this.strings[data[index + 2]]; 207 | break; 208 | } 209 | case CanvasInstruction.FillText: { 210 | if (!this.strings[data[index + 2]]) break; 211 | ctx.fillText( 212 | this.strings[data[index + 2]]!, 213 | data[index + 3], 214 | data[index + 4], 215 | data[index + 5] === -1 ? void 0 : data[index + 5], 216 | ); 217 | break; 218 | } 219 | case CanvasInstruction.Filter: { 220 | if (!this.strings[data[index + 1]]) break; 221 | ctx.filter = this.strings[data[index + 1]]!; 222 | break; 223 | } 224 | case CanvasInstruction.Font: { 225 | if (!this.strings[data[index + 2]]) break; 226 | ctx.font = this.strings[data[index + 1]]!; 227 | break; 228 | } 229 | case CanvasInstruction.GlobalAlpha: { 230 | ctx.globalAlpha = data[index + 2]; 231 | break; 232 | } 233 | case CanvasInstruction.GlobalCompositeOperation: { 234 | ctx.globalCompositeOperation = GlobalCompositeOperationLookup[data[index + 2]]; 235 | break; 236 | } 237 | case CanvasInstruction.ImageSmoothingEnabled: { 238 | ctx.imageSmoothingEnabled = data[index + 2] === 1.0; 239 | break; 240 | } 241 | case CanvasInstruction.ImageSmoothingQuality: { 242 | ctx.imageSmoothingQuality = ImageSmoothingQuality[data[index + 2]] as "high" | "low" | "medium"; 243 | break; 244 | } 245 | case CanvasInstruction.Inspect: { break; } 246 | case CanvasInstruction.LineCap: { 247 | ctx.lineCap = LineCap[data[index + 2]] as CanvasLineCap; 248 | break; 249 | } 250 | case CanvasInstruction.LineDash: { 251 | // setLineDash accepts a typed array instead of just a number[] 252 | ctx.setLineDash(this.wasm!.getArray(Float64Array as any, data[index + 2]) as any); 253 | break; 254 | } 255 | case CanvasInstruction.LineDashOffset: { 256 | ctx.lineDashOffset = data[index + 2]; 257 | break; 258 | } 259 | case CanvasInstruction.LineJoin: { 260 | ctx.lineJoin = LineJoin[data[index + 2]] as CanvasLineJoin; 261 | break; 262 | } 263 | case CanvasInstruction.LineTo: { 264 | ctx.lineTo(data[index + 2], data[index + 3]); 265 | break; 266 | } 267 | case CanvasInstruction.LineWidth: { 268 | ctx.lineWidth = data[index + 2]; 269 | break; 270 | } 271 | case CanvasInstruction.MiterLimit: { 272 | ctx.miterLimit = data[index + 2]; 273 | break; 274 | } 275 | case CanvasInstruction.MoveTo: { 276 | ctx.moveTo(data[index + 2], data[index + 3]); 277 | break; 278 | } 279 | case CanvasInstruction.QuadraticCurveTo: { 280 | ctx.quadraticCurveTo( 281 | data[index + 2], 282 | data[index + 3], 283 | data[index + 4], 284 | data[index + 5], 285 | ); 286 | break; 287 | } 288 | case CanvasInstruction.Rect: { 289 | ctx.rect( 290 | data[index + 2], 291 | data[index + 3], 292 | data[index + 4], 293 | data[index + 5], 294 | ); 295 | break; 296 | } 297 | case CanvasInstruction.Restore: { 298 | ctx.restore(); 299 | break; 300 | } 301 | case CanvasInstruction.Rotate: { 302 | ctx.rotate(data[index + 2]); 303 | break; 304 | } 305 | case CanvasInstruction.Save: { 306 | ctx.save(); 307 | break; 308 | } 309 | case CanvasInstruction.Scale: { 310 | ctx.scale(data[index + 2], data[index + 3]); 311 | break; 312 | } 313 | case CanvasInstruction.SetTransform: { 314 | ctx.setTransform( 315 | data[index + 2], 316 | data[index + 3], 317 | data[index + 4], 318 | data[index + 5], 319 | data[index + 6], 320 | data[index + 7], 321 | ); 322 | break; 323 | } 324 | case CanvasInstruction.ShadowBlur: { 325 | ctx.shadowBlur = data[index + 2]; 326 | break; 327 | } 328 | case CanvasInstruction.ShadowColor: { 329 | if (!this.strings[data[index + 2]]) break; 330 | ctx.shadowColor = this.strings[data[index + 1]]!; 331 | break; 332 | } 333 | case CanvasInstruction.ShadowOffsetX: { 334 | ctx.shadowOffsetX = data[index + 2]; 335 | break; 336 | } 337 | case CanvasInstruction.ShadowOffsetY: { 338 | ctx.shadowOffsetY = data[index + 2]; 339 | break; 340 | } 341 | case CanvasInstruction.StrokeStyle: { 342 | if (!this.strings[data[index + 2]]) break; 343 | ctx.fillStyle = this.strings[data[index + 1]]!; 344 | break; 345 | } 346 | case CanvasInstruction.StrokeGradient: { 347 | ctx.strokeStyle = this.gradients[data[index + 2]]!; 348 | break; 349 | } 350 | case CanvasInstruction.StrokePattern: { 351 | ctx.strokeStyle = this.patterns[data[index + 2]]!; 352 | break; 353 | } 354 | case CanvasInstruction.TextAlign: { 355 | ctx.textAlign = TextAlign[data[index + 2]] as CanvasTextAlign; 356 | break; 357 | } 358 | case CanvasInstruction.TextBaseline: { 359 | ctx.textBaseline = TextBaseline[data[index + 2]] as CanvasTextBaseline; 360 | break; 361 | } 362 | case CanvasInstruction.Transform: { 363 | ctx.transform( 364 | data[index + 2], 365 | data[index + 3], 366 | data[index + 4], 367 | data[index + 5], 368 | data[index + 6], 369 | data[index + 7], 370 | ); 371 | break; 372 | } 373 | case CanvasInstruction.Translate: { 374 | ctx.translate(data[index + 2], data[index + 3]); 375 | break; 376 | } 377 | default: 378 | throw new Error("Invalid canvas instruction type: " + data[index]); 379 | } 380 | index = data[index + 1]; 381 | } 382 | } 383 | 384 | private add_color_stop(index: number, point: number, color: number): void { 385 | this.gradients[index]!.addColorStop(point, this.wasm!.getString(color)); 386 | } 387 | 388 | private create_image(imagePointer: number, sourcePointer: number): void { 389 | this.load_image(imagePointer, sourcePointer); 390 | } 391 | 392 | private create_linear_gradient(index: number, x0: number, y0: number, x1: number, y1: number): void { 393 | this.gradients[index] = ctx!.createLinearGradient(x0, y0, x1, y1); 394 | } 395 | 396 | private create_pattern(index: number, imageIndex: number, patternType: CanvasPatternType): void { 397 | this.patterns[index] = ctx!.createPattern(this.images[imageIndex]!, canvasPatternTypes[patternType]); 398 | } 399 | 400 | private create_radial_gradient(index: number, x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): void { 401 | this.gradients[index] = ctx!.createRadialGradient(x0, y0, r0, x1, y1, r1); 402 | } 403 | 404 | private create_string(index: number, stringPointer: number): void { 405 | this.strings[index] = this.wasm!.getString(stringPointer); 406 | } 407 | 408 | private get_image_data(name: number, imageDataPointer: number, sx: number, sy: number, sw: number, sh: number): void { 409 | var imageDataIndex: number = imageDataPointer / Int32Array.BYTES_PER_ELEMENT; 410 | var contextName: string = this.wasm!.getString(name); 411 | if (!this.contexts.has(contextName)) throw new Error("Invalid context: " + contextName); 412 | var imageData: ImageData = this.contexts.get(contextName)!.getImageData(sx, sy, sw, sh); 413 | var { U32, I32 } = this.wasm!; 414 | U32[imageDataIndex] = this.wasm!.newArray(imageData.data as any); 415 | I32[imageDataIndex + 1] = imageData.width; 416 | I32[imageDataIndex + 2] = imageData.height; 417 | } 418 | 419 | private put_image_data(name: number, imageDataPointer: number, dx: number, dy: number): void { 420 | var contextName: string = this.wasm!.getString(name) 421 | if (!this.contexts.has(contextName)) throw new Error("Cannot find context: " + contextName); 422 | var context: CanvasRenderingContext2D = this.contexts.get(contextName)!; 423 | var imagePointerIndex = imageDataPointer / Int32Array.BYTES_PER_ELEMENT; 424 | var dataPointer: number = this.wasm!.I32[imagePointerIndex]; 425 | var width: number = this.wasm!.I32[imagePointerIndex + 1]; 426 | var height: number = this.wasm!.I32[imagePointerIndex + 2]; 427 | var imageData: ImageData = new ImageData(width, height); 428 | var data: Uint8ClampedArray = this.wasm!.getArray(Uint8ClampedArray as any, dataPointer) as any as Uint8ClampedArray; 429 | for (var i = 0; i < data.length; i++) { 430 | imageData.data[i] = data[i]; 431 | } 432 | context.putImageData(imageData, dx, dy); 433 | } 434 | 435 | private put_image_data_dirty(name: number, imageDataPointer: number, dx: number, dy: number, dirtyX: number, dirtyY: number, dirtyWidth: number, dirtyHeight: number): void { 436 | var { U32, I32 } = this.wasm!; 437 | var contextName: string = this.wasm!.getString(name) 438 | if (!this.contexts.has(contextName)) throw new Error("Cannot find context: " + contextName); 439 | var context: CanvasRenderingContext2D = this.contexts.get(contextName)!; 440 | var imagePointerIndex = imageDataPointer / Int32Array.BYTES_PER_ELEMENT; 441 | var dataPointer: number = U32[imagePointerIndex]; 442 | var width: number = I32[imagePointerIndex + 1]; 443 | var height: number = I32[imagePointerIndex + 2]; 444 | var imageData: ImageData = new ImageData(width, height); 445 | var data: Uint8ClampedArray = this.wasm!.getArray(Uint8ClampedArray as any, dataPointer) as any as Uint8ClampedArray; 446 | for (var i = 0; i < data.length; i++) { 447 | imageData.data[i] = data[i]; 448 | } 449 | context.putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); 450 | } 451 | 452 | private remove_image(index: number): void { 453 | this.images[index] = null; 454 | } 455 | 456 | private remove_pattern(index: number): void { 457 | this.patterns[index] = null; 458 | } 459 | 460 | private remove_gradient(index: number): void { 461 | this.gradients[index] = null; 462 | } 463 | 464 | private async load_image(imagePointer: number, sourcePointer: number): Promise { 465 | const source: string = this.wasm!.getString(sourcePointer); 466 | const res: Response = await fetch(source); 467 | const blob: Blob = await res.blob(); 468 | const img: ImageBitmap = await createImageBitmap(blob); 469 | 470 | const imageIndex: number = imagePointer / Int32Array.BYTES_PER_ELEMENT; 471 | this.images[this.wasm!.I32[imageIndex]] = img; 472 | const imageLoadedFunc = this.wasm!.getFunction(this.image_loaded) as ImageLoadedCallback; 473 | imageLoadedFunc(imagePointer, img.width, img.height); 474 | } 475 | 476 | private report_use_image(use_image: number): void { 477 | this.use_image = use_image; 478 | } 479 | 480 | private report_use_canvas(use_canvas: number): void { 481 | this.use_canvas = use_canvas; 482 | } 483 | 484 | private report_image_loaded(image_loaded: number): void { 485 | this.image_loaded = image_loaded; 486 | } 487 | 488 | private inspect(a: number): void { 489 | var results: string[] = []; 490 | var data: Float64Array = this.wasm!.getArray(Float64Array as any, a); 491 | var i: number = 0; 492 | while (i < data.length) { 493 | debugger; 494 | switch (data[i]) { 495 | case CanvasInstruction.Arc: { 496 | console.log("Arc"); 497 | break; 498 | } 499 | case CanvasInstruction.ArcTo: { 500 | console.log("ArcTo"); 501 | break; 502 | } 503 | case CanvasInstruction.BeginPath: { 504 | console.log("BeginPath"); 505 | break; 506 | } 507 | case CanvasInstruction.BezierCurveTo: { 508 | console.log("BezierCurveTo"); 509 | break; 510 | } 511 | case CanvasInstruction.Clip: { 512 | console.log("Clip"); 513 | break; 514 | } 515 | case CanvasInstruction.ClosePath: { 516 | console.log("ClosePath"); 517 | break; 518 | } 519 | case CanvasInstruction.Commit: { 520 | console.log("Commit"); 521 | break; 522 | } 523 | case CanvasInstruction.ClearRect: { 524 | console.log("ClearRect"); 525 | break; 526 | } 527 | case CanvasInstruction.Direction: { 528 | console.log("Direction"); 529 | break; 530 | } 531 | case CanvasInstruction.DrawFocusIfNeeded: { 532 | console.log("DrawFocusIfNeeded"); 533 | break; 534 | } 535 | case CanvasInstruction.DrawImage: { 536 | console.log("DrawImage"); 537 | break; 538 | } 539 | case CanvasInstruction.Ellipse: { 540 | console.log("Ellipse"); 541 | break; 542 | } 543 | case CanvasInstruction.Fill: { 544 | console.log("Fill"); 545 | break; 546 | } 547 | case CanvasInstruction.FillGradient: { 548 | console.log("FillGradient"); 549 | break; 550 | } 551 | case CanvasInstruction.FillPattern: { 552 | console.log("FillPattern"); 553 | break; 554 | } 555 | case CanvasInstruction.FillRect: { 556 | console.log("FillRect"); 557 | break; 558 | } 559 | case CanvasInstruction.FillStyle: { 560 | console.log("FillStyle"); 561 | break; 562 | } 563 | case CanvasInstruction.FillText: { 564 | console.log("FillText"); 565 | break; 566 | } 567 | case CanvasInstruction.Filter: { 568 | console.log("Filter"); 569 | break; 570 | } 571 | case CanvasInstruction.Font: { 572 | console.log("Font"); 573 | break; 574 | } 575 | case CanvasInstruction.GlobalAlpha: { 576 | console.log("GlobalAlpha"); 577 | break; 578 | } 579 | case CanvasInstruction.GlobalCompositeOperation: { 580 | console.log("GlobalCompositeOperation"); 581 | break; 582 | } 583 | case CanvasInstruction.ImageSmoothingEnabled: { 584 | console.log("ImageSmoothingEnabled"); 585 | break; 586 | } 587 | case CanvasInstruction.ImageSmoothingQuality: { 588 | console.log("ImageSmoothingQuality"); 589 | break; 590 | } 591 | case CanvasInstruction.LineCap: { 592 | console.log("LineCap"); 593 | break; 594 | } 595 | case CanvasInstruction.LineDash: { 596 | console.log("LineDash"); 597 | break; 598 | } 599 | case CanvasInstruction.LineDashOffset: { 600 | console.log("LineDashOffset"); 601 | break; 602 | } 603 | case CanvasInstruction.LineJoin: { 604 | console.log("LineJoin"); 605 | break; 606 | } 607 | case CanvasInstruction.LineTo: { 608 | console.log("LineTo"); 609 | break; 610 | } 611 | case CanvasInstruction.LineWidth: { 612 | console.log("LineWidth"); 613 | break; 614 | } 615 | case CanvasInstruction.MiterLimit: { 616 | console.log("MiterLimit"); 617 | break; 618 | } 619 | case CanvasInstruction.MoveTo: { 620 | console.log("MoveTo"); 621 | break; 622 | } 623 | case CanvasInstruction.QuadraticCurveTo: { 624 | console.log("QuadraticCurveTo"); 625 | break; 626 | } 627 | case CanvasInstruction.Rect: { 628 | console.log("Rect"); 629 | break; 630 | } 631 | case CanvasInstruction.Restore: { 632 | console.log("Restore"); 633 | break; 634 | } 635 | case CanvasInstruction.Rotate: { 636 | console.log("Rotate"); 637 | break; 638 | } 639 | case CanvasInstruction.Save: { 640 | console.log("Save"); 641 | break; 642 | } 643 | case CanvasInstruction.Scale: { 644 | console.log("Scale"); 645 | break; 646 | } 647 | case CanvasInstruction.SetTransform: { 648 | console.log("SetTransform"); 649 | break; 650 | } 651 | case CanvasInstruction.ShadowBlur: { 652 | console.log("ShadowBlur"); 653 | break; 654 | } 655 | case CanvasInstruction.ShadowColor: { 656 | console.log("ShadowColor"); 657 | break; 658 | } 659 | case CanvasInstruction.ShadowOffsetX: { 660 | console.log("ShadowOffsetX"); 661 | break; 662 | } 663 | case CanvasInstruction.ShadowOffsetY: { 664 | console.log("ShadowOffsetY"); 665 | break; 666 | } 667 | case CanvasInstruction.Stroke: { 668 | console.log("Stroke"); 669 | break; 670 | } 671 | case CanvasInstruction.StrokeGradient: { 672 | console.log("StrokeGradient"); 673 | break; 674 | } 675 | case CanvasInstruction.StrokePattern: { 676 | console.log("StrokePattern"); 677 | break; 678 | } 679 | case CanvasInstruction.StrokeRect: { 680 | console.log("StrokeRect"); 681 | break; 682 | } 683 | case CanvasInstruction.StrokeStyle: { 684 | console.log("StrokeStyle"); 685 | break; 686 | } 687 | case CanvasInstruction.StrokeText: { 688 | console.log("StrokeText"); 689 | break; 690 | } 691 | case CanvasInstruction.TextAlign: { 692 | console.log("TextAlign"); 693 | break; 694 | } 695 | case CanvasInstruction.TextBaseline: { 696 | console.log("TextBaseline"); 697 | break; 698 | } 699 | case CanvasInstruction.Translate: { 700 | console.log("Translate"); 701 | break; 702 | } 703 | case CanvasInstruction.Transform: { 704 | console.log("Transform"); 705 | break; 706 | } 707 | } 708 | if (data[i] === CanvasInstruction.Inspect) break; 709 | i = data[i + 1]; 710 | } 711 | } 712 | 713 | private log(a: number, b: number): void { 714 | console.log(a, b); 715 | } 716 | } -------------------------------------------------------------------------------- /dist/interop/CanvasASInterop.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const shared_1 = require("../shared"); 4 | const util_1 = require("../util"); 5 | const ctx = document.createElement("canvas").getContext("2d"); 6 | class CanvasASInterop { 7 | constructor() { 8 | this.contexts = new Map(); 9 | this.strings = new Map(); 10 | this.images = {}; 11 | this.patterns = {}; 12 | this.gradients = {}; 13 | this.wasm = null; 14 | this.image_loaded = 0; 15 | this.use_image = 0; 16 | this.use_canvas = 0; 17 | } 18 | useContext(name, value) { 19 | if (this.use_canvas === 0) 20 | throw new Error("CanvasASInterop hasn't loaded yet."); 21 | var func = this.wasm.getFunction(this.use_canvas); 22 | this.contexts.set(name, value); 23 | func(this.wasm.newString(name)); 24 | return this; 25 | } 26 | useImage(name, value) { 27 | if (this.use_image === 0) 28 | throw new Error("CanvasASInterop hasn't loaded yet."); 29 | if (this.image_loaded === 0) 30 | throw new Error("CanvasASInterop hasn't loaded yet."); 31 | value.then(e => e.blob()) 32 | .then(e => createImageBitmap(e)) 33 | .then(bitmap => { 34 | const strPtr = this.wasm.newString(name); 35 | const useFunc = this.wasm.getFunction(this.use_image); 36 | const imagePointer = useFunc(strPtr); 37 | const imageIndex = imagePointer / Int32Array.BYTES_PER_ELEMENT; 38 | this.images[this.wasm.I32[imageIndex]] = bitmap; 39 | const loadedFunc = this.wasm.getFunction(this.image_loaded); 40 | loadedFunc(imagePointer, bitmap.width, bitmap.height); 41 | }); 42 | return this; 43 | } 44 | init() { 45 | return { 46 | add_color_stop: this.add_color_stop.bind(this), 47 | create_linear_gradient: this.create_linear_gradient.bind(this), 48 | create_pattern: this.create_pattern.bind(this), 49 | create_radial_gradient: this.create_radial_gradient.bind(this), 50 | create_string: this.create_string.bind(this), 51 | create_image: this.create_image.bind(this), 52 | get_image_data: this.get_image_data.bind(this), 53 | inspect: this.inspect.bind(this), 54 | remove_image: this.remove_image.bind(this), 55 | remove_pattern: this.remove_pattern.bind(this), 56 | remove_gradient: this.remove_gradient.bind(this), 57 | report_use_image: this.report_use_image.bind(this), 58 | report_image_loaded: this.report_image_loaded.bind(this), 59 | put_image_data: this.put_image_data.bind(this), 60 | put_image_data_dirty: this.put_image_data_dirty.bind(this), 61 | report_use_canvas: this.report_use_canvas.bind(this), 62 | render: this.render.bind(this), 63 | log: this.log.bind(this), 64 | }; 65 | } 66 | render(name, dataPointer) { 67 | var index = 0; 68 | var ctx = this.contexts.get(this.wasm.getString(name)); 69 | if (!ctx) 70 | throw new Error("Invalid context: " + name); 71 | var data = this.wasm.getArray(Float64Array, dataPointer); 72 | while (index < data.length) { 73 | if (data[index] === 6 /* Commit */) { 74 | //this.strings.clear(); 75 | break; 76 | } 77 | switch (data[index]) { 78 | case 0 /* Arc */: { 79 | ctx.arc(data[index + 2], data[index + 3], data[index + 4], data[index + 5], data[index + 6], data[index + 7] === 1); 80 | break; 81 | } 82 | case 1 /* ArcTo */: { 83 | ctx.arcTo(data[index + 2], data[index + 3], data[index + 4], data[index + 5], data[index + 6]); 84 | break; 85 | } 86 | case 2 /* BeginPath */: { 87 | ctx.beginPath(); 88 | break; 89 | } 90 | case 3 /* BezierCurveTo */: { 91 | ctx.bezierCurveTo(data[index + 2], data[index + 3], data[index + 4], data[index + 5], data[index + 6], data[index + 7]); 92 | break; 93 | } 94 | case 7 /* ClearRect */: { 95 | ctx.clearRect(data[index + 2], data[index + 3], data[index + 4], data[index + 5]); 96 | break; 97 | } 98 | case 4 /* Clip */: { 99 | ctx.clip(); 100 | break; 101 | } 102 | case 5 /* ClosePath */: { 103 | ctx.closePath(); 104 | break; 105 | } 106 | case 8 /* Direction */: { 107 | ctx.direction = shared_1.Direction[data[index + 2]]; 108 | break; 109 | } 110 | case 10 /* DrawImage */: { 111 | if (!this.images[data[index + 2]]) 112 | break; 113 | ctx.drawImage(this.images[data[index + 2]], data[index + 3], data[index + 4], data[index + 5], data[index + 6], data[index + 7], data[index + 8], data[index + 9], data[index + 10]); 114 | break; 115 | } 116 | case 11 /* Ellipse */: { 117 | ctx.ellipse(data[index + 2], data[index + 3], data[index + 4], data[index + 5], data[index + 6], data[index + 7], data[index + 8], data[index + 9] === 1.0); 118 | break; 119 | } 120 | case 12 /* Fill */: { 121 | ctx.fill(shared_1.FillRule[data[index + 2]]); 122 | break; 123 | } 124 | case 13 /* FillGradient */: { 125 | ctx.fillStyle = this.gradients[data[index + 2]]; 126 | break; 127 | } 128 | case 14 /* FillPattern */: { 129 | ctx.fillStyle = this.patterns[data[index + 2]]; 130 | break; 131 | } 132 | case 15 /* FillRect */: { 133 | ctx.fillRect(data[index + 2], data[index + 3], data[index + 4], data[index + 5]); 134 | break; 135 | } 136 | case 16 /* FillStyle */: { 137 | if (!this.strings.has(data[index + 2])) 138 | continue; 139 | ctx.fillStyle = this.strings.get(data[index + 2]); 140 | break; 141 | } 142 | case 17 /* FillText */: { 143 | if (!this.strings.has(data[index + 2])) 144 | continue; 145 | ctx.fillText(this.strings.get(data[index + 2]), data[index + 3], data[index + 4], data[index + 5] === -1 ? void 0 : data[index + 5]); 146 | break; 147 | } 148 | case 18 /* Filter */: { 149 | if (!this.strings.has(data[index + 2])) 150 | continue; 151 | ctx.filter = this.strings.get(data[index + 2]); 152 | break; 153 | } 154 | case 19 /* Font */: { 155 | if (!this.strings.has(data[index + 2])) 156 | continue; 157 | ctx.font = this.strings.get(data[index + 2]); 158 | break; 159 | } 160 | case 20 /* GlobalAlpha */: { 161 | ctx.globalAlpha = data[index + 2]; 162 | break; 163 | } 164 | case 21 /* GlobalCompositeOperation */: { 165 | ctx.globalCompositeOperation = util_1.GlobalCompositeOperationLookup[data[index + 2]]; 166 | break; 167 | } 168 | case 22 /* ImageSmoothingEnabled */: { 169 | ctx.imageSmoothingEnabled = data[index + 2] === 1.0; 170 | break; 171 | } 172 | case 23 /* ImageSmoothingQuality */: { 173 | ctx.imageSmoothingQuality = shared_1.ImageSmoothingQuality[data[index + 2]]; 174 | break; 175 | } 176 | case 24 /* Inspect */: { 177 | break; 178 | } 179 | case 25 /* LineCap */: { 180 | ctx.lineCap = shared_1.LineCap[data[index + 2]]; 181 | break; 182 | } 183 | case 26 /* LineDash */: { 184 | // setLineDash accepts a typed array instead of just a number[] 185 | ctx.setLineDash(this.wasm.getArray(Float64Array, data[index + 2])); 186 | break; 187 | } 188 | case 27 /* LineDashOffset */: { 189 | ctx.lineDashOffset = data[index + 2]; 190 | break; 191 | } 192 | case 28 /* LineJoin */: { 193 | ctx.lineJoin = shared_1.LineJoin[data[index + 2]]; 194 | break; 195 | } 196 | case 29 /* LineTo */: { 197 | ctx.lineTo(data[index + 2], data[index + 3]); 198 | break; 199 | } 200 | case 30 /* LineWidth */: { 201 | ctx.lineWidth = data[index + 2]; 202 | break; 203 | } 204 | case 31 /* MiterLimit */: { 205 | ctx.miterLimit = data[index + 2]; 206 | break; 207 | } 208 | case 32 /* MoveTo */: { 209 | ctx.moveTo(data[index + 2], data[index + 3]); 210 | break; 211 | } 212 | case 33 /* QuadraticCurveTo */: { 213 | ctx.quadraticCurveTo(data[index + 2], data[index + 3], data[index + 4], data[index + 5]); 214 | break; 215 | } 216 | case 34 /* Rect */: { 217 | ctx.rect(data[index + 2], data[index + 3], data[index + 4], data[index + 5]); 218 | break; 219 | } 220 | case 35 /* Restore */: { 221 | ctx.restore(); 222 | break; 223 | } 224 | case 36 /* Rotate */: { 225 | ctx.rotate(data[index + 2]); 226 | break; 227 | } 228 | case 37 /* Save */: { 229 | ctx.save(); 230 | break; 231 | } 232 | case 38 /* Scale */: { 233 | ctx.scale(data[index + 2], data[index + 3]); 234 | break; 235 | } 236 | case 39 /* SetTransform */: { 237 | ctx.setTransform(data[index + 2], data[index + 3], data[index + 4], data[index + 5], data[index + 6], data[index + 7]); 238 | break; 239 | } 240 | case 40 /* ShadowBlur */: { 241 | ctx.shadowBlur = data[index + 2]; 242 | break; 243 | } 244 | case 41 /* ShadowColor */: { 245 | if (!this.strings.has(data[index + 2])) 246 | continue; 247 | ctx.shadowColor = this.strings.get(data[index + 2]); 248 | break; 249 | } 250 | case 42 /* ShadowOffsetX */: { 251 | ctx.shadowOffsetX = data[index + 2]; 252 | break; 253 | } 254 | case 43 /* ShadowOffsetY */: { 255 | ctx.shadowOffsetY = data[index + 2]; 256 | break; 257 | } 258 | case 48 /* StrokeStyle */: { 259 | if (!this.strings.has(data[index + 2])) 260 | ctx.fillStyle = this.strings.get(data[index + 2]); 261 | break; 262 | } 263 | case 45 /* StrokeGradient */: { 264 | ctx.strokeStyle = this.gradients[data[index + 2]]; 265 | break; 266 | } 267 | case 46 /* StrokePattern */: { 268 | ctx.strokeStyle = this.patterns[data[index + 2]]; 269 | break; 270 | } 271 | case 50 /* TextAlign */: { 272 | ctx.textAlign = shared_1.TextAlign[data[index + 2]]; 273 | break; 274 | } 275 | case 51 /* TextBaseline */: { 276 | ctx.textBaseline = shared_1.TextBaseline[data[index + 2]]; 277 | break; 278 | } 279 | case 53 /* Transform */: { 280 | ctx.transform(data[index + 2], data[index + 3], data[index + 4], data[index + 5], data[index + 6], data[index + 7]); 281 | break; 282 | } 283 | case 52 /* Translate */: { 284 | ctx.translate(data[index + 2], data[index + 3]); 285 | break; 286 | } 287 | default: 288 | throw new Error("Invalid canvas instruction type: " + data[index]); 289 | } 290 | index = data[index + 1]; 291 | } 292 | } 293 | add_color_stop(index, point, color) { 294 | this.gradients[index].addColorStop(point, this.wasm.getString(color)); 295 | } 296 | create_image(imagePointer, sourcePointer) { 297 | this.load_image(imagePointer, sourcePointer); 298 | } 299 | create_linear_gradient(index, x0, y0, x1, y1) { 300 | this.gradients[index] = ctx.createLinearGradient(x0, y0, x1, y1); 301 | } 302 | create_pattern(index, imageIndex, patternType) { 303 | this.patterns[index] = ctx.createPattern(this.images[imageIndex], util_1.canvasPatternTypes[patternType]); 304 | } 305 | create_radial_gradient(index, x0, y0, r0, x1, y1, r1) { 306 | this.gradients[index] = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); 307 | } 308 | create_string(index, stringPointer) { 309 | this.strings.set(index, this.wasm.getString(stringPointer)); 310 | } 311 | get_image_data(name, imageDataPointer, sx, sy, sw, sh) { 312 | var imageDataIndex = imageDataPointer / Int32Array.BYTES_PER_ELEMENT; 313 | var contextName = this.wasm.getString(name); 314 | if (!this.contexts.has(contextName)) 315 | throw new Error("Invalid context: " + contextName); 316 | var imageData = this.contexts.get(contextName).getImageData(sx, sy, sw, sh); 317 | var { U32, I32 } = this.wasm; 318 | U32[imageDataIndex] = this.wasm.newArray(imageData.data); 319 | I32[imageDataIndex + 1] = imageData.width; 320 | I32[imageDataIndex + 2] = imageData.height; 321 | } 322 | put_image_data(name, imageDataPointer, dx, dy) { 323 | var contextName = this.wasm.getString(name); 324 | if (!this.contexts.has(contextName)) 325 | throw new Error("Cannot find context: " + contextName); 326 | var context = this.contexts.get(contextName); 327 | var imagePointerIndex = imageDataPointer / Int32Array.BYTES_PER_ELEMENT; 328 | var dataPointer = this.wasm.I32[imagePointerIndex]; 329 | var width = this.wasm.I32[imagePointerIndex + 1]; 330 | var height = this.wasm.I32[imagePointerIndex + 2]; 331 | var imageData = new ImageData(width, height); 332 | var data = this.wasm.getArray(Uint8ClampedArray, dataPointer); 333 | for (var i = 0; i < data.length; i++) { 334 | imageData.data[i] = data[i]; 335 | } 336 | context.putImageData(imageData, dx, dy); 337 | } 338 | put_image_data_dirty(name, imageDataPointer, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) { 339 | var { U32, I32 } = this.wasm; 340 | var contextName = this.wasm.getString(name); 341 | if (!this.contexts.has(contextName)) 342 | throw new Error("Cannot find context: " + contextName); 343 | var context = this.contexts.get(contextName); 344 | var imagePointerIndex = imageDataPointer / Int32Array.BYTES_PER_ELEMENT; 345 | var dataPointer = U32[imagePointerIndex]; 346 | var width = I32[imagePointerIndex + 1]; 347 | var height = I32[imagePointerIndex + 2]; 348 | var imageData = new ImageData(width, height); 349 | var data = this.wasm.getArray(Uint8ClampedArray, dataPointer); 350 | for (var i = 0; i < data.length; i++) { 351 | imageData.data[i] = data[i]; 352 | } 353 | context.putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); 354 | } 355 | remove_image(index) { 356 | this.images[index] = null; 357 | } 358 | remove_pattern(index) { 359 | this.patterns[index] = null; 360 | } 361 | remove_gradient(index) { 362 | this.gradients[index] = null; 363 | } 364 | async load_image(imagePointer, sourcePointer) { 365 | const source = this.wasm.getString(sourcePointer); 366 | const res = await fetch(source); 367 | const blob = await res.blob(); 368 | const img = await createImageBitmap(blob); 369 | const imageIndex = imagePointer / Int32Array.BYTES_PER_ELEMENT; 370 | this.images[this.wasm.I32[imageIndex]] = img; 371 | const imageLoadedFunc = this.wasm.getFunction(this.image_loaded); 372 | imageLoadedFunc(imagePointer, img.width, img.height); 373 | } 374 | report_use_image(use_image) { 375 | this.use_image = use_image; 376 | } 377 | report_use_canvas(use_canvas) { 378 | this.use_canvas = use_canvas; 379 | } 380 | report_image_loaded(image_loaded) { 381 | this.image_loaded = image_loaded; 382 | } 383 | inspect(a) { 384 | var results = []; 385 | var data = this.wasm.getArray(Float64Array, a); 386 | var i = 0; 387 | while (i < data.length) { 388 | switch (data[i]) { 389 | case 0 /* Arc */: { 390 | results.push("Arc"); 391 | break; 392 | } 393 | case 1 /* ArcTo */: { 394 | results.push("ArcTo"); 395 | break; 396 | } 397 | case 2 /* BeginPath */: { 398 | results.push("BeginPath"); 399 | break; 400 | } 401 | case 3 /* BezierCurveTo */: { 402 | results.push("BezierCurveTo"); 403 | break; 404 | } 405 | case 4 /* Clip */: { 406 | results.push("Clip"); 407 | break; 408 | } 409 | case 5 /* ClosePath */: { 410 | results.push("ClosePath"); 411 | break; 412 | } 413 | case 6 /* Commit */: { 414 | results.push("Commit"); 415 | break; 416 | } 417 | case 7 /* ClearRect */: { 418 | results.push("ClearRect"); 419 | break; 420 | } 421 | case 8 /* Direction */: { 422 | results.push("Direction"); 423 | break; 424 | } 425 | case 9 /* DrawFocusIfNeeded */: { 426 | results.push("DrawFocusIfNeeded"); 427 | break; 428 | } 429 | case 10 /* DrawImage */: { 430 | results.push("DrawImage"); 431 | break; 432 | } 433 | case 11 /* Ellipse */: { 434 | results.push("Ellipse"); 435 | break; 436 | } 437 | case 12 /* Fill */: { 438 | results.push("Fill"); 439 | break; 440 | } 441 | case 13 /* FillGradient */: { 442 | results.push("FillGradient"); 443 | break; 444 | } 445 | case 14 /* FillPattern */: { 446 | results.push("FillPattern"); 447 | break; 448 | } 449 | case 15 /* FillRect */: { 450 | results.push("FillRect"); 451 | break; 452 | } 453 | case 16 /* FillStyle */: { 454 | results.push("FillStyle"); 455 | break; 456 | } 457 | case 17 /* FillText */: { 458 | results.push("FillText"); 459 | break; 460 | } 461 | case 18 /* Filter */: { 462 | results.push("Filter"); 463 | break; 464 | } 465 | case 19 /* Font */: { 466 | results.push("Font"); 467 | break; 468 | } 469 | case 20 /* GlobalAlpha */: { 470 | results.push("GlobalAlpha"); 471 | break; 472 | } 473 | case 21 /* GlobalCompositeOperation */: { 474 | results.push("GlobalCompositeOperation"); 475 | break; 476 | } 477 | case 22 /* ImageSmoothingEnabled */: { 478 | results.push("ImageSmoothingEnabled"); 479 | break; 480 | } 481 | case 23 /* ImageSmoothingQuality */: { 482 | results.push("ImageSmoothingQuality"); 483 | break; 484 | } 485 | case 25 /* LineCap */: { 486 | results.push("LineCap"); 487 | break; 488 | } 489 | case 26 /* LineDash */: { 490 | results.push("LineDash"); 491 | break; 492 | } 493 | case 27 /* LineDashOffset */: { 494 | results.push("LineDashOffset"); 495 | break; 496 | } 497 | case 28 /* LineJoin */: { 498 | results.push("LineJoin"); 499 | break; 500 | } 501 | case 29 /* LineTo */: { 502 | results.push("LineTo"); 503 | break; 504 | } 505 | case 30 /* LineWidth */: { 506 | results.push("LineWidth"); 507 | break; 508 | } 509 | case 31 /* MiterLimit */: { 510 | results.push("MiterLimit"); 511 | break; 512 | } 513 | case 32 /* MoveTo */: { 514 | results.push("MoveTo"); 515 | break; 516 | } 517 | case 33 /* QuadraticCurveTo */: { 518 | results.push("QuadraticCurveTo"); 519 | break; 520 | } 521 | case 34 /* Rect */: { 522 | results.push("Rect"); 523 | break; 524 | } 525 | case 35 /* Restore */: { 526 | results.push("Restore"); 527 | break; 528 | } 529 | case 36 /* Rotate */: { 530 | results.push("Rotate"); 531 | break; 532 | } 533 | case 37 /* Save */: { 534 | results.push("Save"); 535 | break; 536 | } 537 | case 38 /* Scale */: { 538 | results.push("Scale"); 539 | break; 540 | } 541 | case 39 /* SetTransform */: { 542 | results.push("SetTransform"); 543 | break; 544 | } 545 | case 40 /* ShadowBlur */: { 546 | results.push("ShadowBlur"); 547 | break; 548 | } 549 | case 41 /* ShadowColor */: { 550 | results.push("ShadowColor"); 551 | break; 552 | } 553 | case 42 /* ShadowOffsetX */: { 554 | results.push("ShadowOffsetX"); 555 | break; 556 | } 557 | case 43 /* ShadowOffsetY */: { 558 | results.push("ShadowOffsetY"); 559 | break; 560 | } 561 | case 44 /* Stroke */: { 562 | results.push("Stroke"); 563 | break; 564 | } 565 | case 45 /* StrokeGradient */: { 566 | results.push("StrokeGradient"); 567 | break; 568 | } 569 | case 46 /* StrokePattern */: { 570 | results.push("StrokePattern"); 571 | break; 572 | } 573 | case 47 /* StrokeRect */: { 574 | results.push("StrokeRect"); 575 | break; 576 | } 577 | case 48 /* StrokeStyle */: { 578 | results.push("StrokeStyle"); 579 | break; 580 | } 581 | case 49 /* StrokeText */: { 582 | results.push("StrokeText"); 583 | break; 584 | } 585 | case 50 /* TextAlign */: { 586 | results.push("TextAlign"); 587 | break; 588 | } 589 | case 51 /* TextBaseline */: { 590 | results.push("TextBaseline"); 591 | break; 592 | } 593 | case 52 /* Translate */: { 594 | results.push("Translate"); 595 | break; 596 | } 597 | case 53 /* Transform */: { 598 | results.push("Transform"); 599 | break; 600 | } 601 | } 602 | if (data[i] === 24 /* Inspect */) 603 | break; 604 | i = data[i + 1]; 605 | } 606 | console.log(results); 607 | } 608 | log(a, b) { 609 | console.log(a, b); 610 | } 611 | } 612 | exports.CanvasASInterop = CanvasASInterop; 613 | //# sourceMappingURL=CanvasASInterop.js.map --------------------------------------------------------------------------------