From 7184a91c950c96fa9847bef9c1a373090e572415 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Fri, 9 Jan 2026 19:46:11 +0300 Subject: [PATCH] finalize canvas backport --- .../tests/canvas/webgl_rendering_context.html | 8 +- .../canvas/CanvasRenderingContext2D.zig | 132 ++++++++++++-- .../webapi/canvas/WebGLRenderingContext.zig | 71 ++++++-- src/browser/webapi/element/html/Canvas.zig | 166 ++---------------- 4 files changed, 200 insertions(+), 177 deletions(-) diff --git a/src/browser/tests/canvas/webgl_rendering_context.html b/src/browser/tests/canvas/webgl_rendering_context.html index 5858ee92..24bad4fd 100644 --- a/src/browser/tests/canvas/webgl_rendering_context.html +++ b/src/browser/tests/canvas/webgl_rendering_context.html @@ -66,8 +66,12 @@ const rendererInfo = ctx.getExtension("WEBGL_debug_renderer_info"); testing.expectEqual(true, rendererInfo instanceof WEBGL_debug_renderer_info); - testing.expectEqual(rendererInfo.UNMASKED_VENDOR_WEBGL, 0x9245); - testing.expectEqual(rendererInfo.UNMASKED_RENDERER_WEBGL, 0x9246); + const { UNMASKED_VENDOR_WEBGL, UNMASKED_RENDERER_WEBGL } = rendererInfo; + testing.expectEqual(UNMASKED_VENDOR_WEBGL, 0x9245); + testing.expectEqual(UNMASKED_RENDERER_WEBGL, 0x9246); + + testing.expectEqual("", ctx.getParameter(UNMASKED_VENDOR_WEBGL)); + testing.expectEqual("", ctx.getParameter(UNMASKED_RENDERER_WEBGL)); } // WEBGL_lose_context diff --git a/src/browser/webapi/canvas/CanvasRenderingContext2D.zig b/src/browser/webapi/canvas/CanvasRenderingContext2D.zig index e13c3d64..c7b7bde6 100644 --- a/src/browser/webapi/canvas/CanvasRenderingContext2D.zig +++ b/src/browser/webapi/canvas/CanvasRenderingContext2D.zig @@ -31,20 +31,6 @@ const CanvasRenderingContext2D = @This(); /// TODO: Add support for `CanvasGradient` and `CanvasPattern`. fill_style: color.RGBA = color.RGBA.Named.black, -pub fn fillRect( - self: *const CanvasRenderingContext2D, - x: f64, - y: f64, - width: f64, - height: f64, -) void { - _ = self; - _ = x; - _ = y; - _ = width; - _ = height; -} - pub fn getFillStyle(self: *const CanvasRenderingContext2D, page: *Page) ![]const u8 { var w = std.Io.Writer.Allocating.init(page.call_arena); try self.fill_style.format(&w.writer); @@ -59,6 +45,82 @@ pub fn setFillStyle( self.fill_style = color.RGBA.parse(value) catch self.fill_style; } +pub fn getGlobalAlpha(_: *const CanvasRenderingContext2D) f64 { + return 1.0; +} + +pub fn getGlobalCompositeOperation(_: *const CanvasRenderingContext2D) []const u8 { + return "source-over"; +} + +pub fn getStrokeStyle(_: *const CanvasRenderingContext2D) []const u8 { + return "#000000"; +} + +pub fn getLineWidth(_: *const CanvasRenderingContext2D) f64 { + return 1.0; +} + +pub fn getLineCap(_: *const CanvasRenderingContext2D) []const u8 { + return "butt"; +} + +pub fn getLineJoin(_: *const CanvasRenderingContext2D) []const u8 { + return "miter"; +} + +pub fn getMiterLimit(_: *const CanvasRenderingContext2D) f64 { + return 10.0; +} + +pub fn getFont(_: *const CanvasRenderingContext2D) []const u8 { + return "10px sans-serif"; +} + +pub fn getTextAlign(_: *const CanvasRenderingContext2D) []const u8 { + return "start"; +} + +pub fn getTextBaseline(_: *const CanvasRenderingContext2D) []const u8 { + return "alphabetic"; +} + +pub fn save(_: *CanvasRenderingContext2D) void {} +pub fn restore(_: *CanvasRenderingContext2D) void {} +pub fn scale(_: *CanvasRenderingContext2D, _: f64, _: f64) void {} +pub fn rotate(_: *CanvasRenderingContext2D, _: f64) void {} +pub fn translate(_: *CanvasRenderingContext2D, _: f64, _: f64) void {} +pub fn transform(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: f64) void {} +pub fn setTransform(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: f64) void {} +pub fn resetTransform(_: *CanvasRenderingContext2D) void {} +pub fn setGlobalAlpha(_: *CanvasRenderingContext2D, _: f64) void {} +pub fn setGlobalCompositeOperation(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn setStrokeStyle(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn setLineWidth(_: *CanvasRenderingContext2D, _: f64) void {} +pub fn setLineCap(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn setLineJoin(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn setMiterLimit(_: *CanvasRenderingContext2D, _: f64) void {} +pub fn clearRect(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} +pub fn fillRect(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} +pub fn strokeRect(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} +pub fn beginPath(_: *CanvasRenderingContext2D) void {} +pub fn closePath(_: *CanvasRenderingContext2D) void {} +pub fn moveTo(_: *CanvasRenderingContext2D, _: f64, _: f64) void {} +pub fn lineTo(_: *CanvasRenderingContext2D, _: f64, _: f64) void {} +pub fn quadraticCurveTo(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} +pub fn bezierCurveTo(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: f64) void {} +pub fn arc(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: ?bool) void {} +pub fn arcTo(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64) void {} +pub fn rect(_: *CanvasRenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} +pub fn fill(_: *CanvasRenderingContext2D) void {} +pub fn stroke(_: *CanvasRenderingContext2D) void {} +pub fn clip(_: *CanvasRenderingContext2D) void {} +pub fn setFont(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn setTextAlign(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn setTextBaseline(_: *CanvasRenderingContext2D, _: []const u8) void {} +pub fn fillText(_: *CanvasRenderingContext2D, _: []const u8, _: f64, _: f64, _: ?f64) void {} +pub fn strokeText(_: *CanvasRenderingContext2D, _: []const u8, _: f64, _: f64, _: ?f64) void {} + pub const JsApi = struct { pub const bridge = js.Bridge(CanvasRenderingContext2D); @@ -69,8 +131,50 @@ pub const JsApi = struct { pub var class_id: bridge.ClassId = undefined; }; + pub const save = bridge.function(CanvasRenderingContext2D.save, .{}); + pub const restore = bridge.function(CanvasRenderingContext2D.restore, .{}); + + pub const scale = bridge.function(CanvasRenderingContext2D.scale, .{}); + pub const rotate = bridge.function(CanvasRenderingContext2D.rotate, .{}); + pub const translate = bridge.function(CanvasRenderingContext2D.translate, .{}); + pub const transform = bridge.function(CanvasRenderingContext2D.transform, .{}); + pub const setTransform = bridge.function(CanvasRenderingContext2D.setTransform, .{}); + pub const resetTransform = bridge.function(CanvasRenderingContext2D.resetTransform, .{}); + + pub const globalAlpha = bridge.accessor(CanvasRenderingContext2D.getGlobalAlpha, CanvasRenderingContext2D.setGlobalAlpha, .{}); + pub const globalCompositeOperation = bridge.accessor(CanvasRenderingContext2D.getGlobalCompositeOperation, CanvasRenderingContext2D.setGlobalCompositeOperation, .{}); + pub const fillStyle = bridge.accessor(CanvasRenderingContext2D.getFillStyle, CanvasRenderingContext2D.setFillStyle, .{}); + pub const strokeStyle = bridge.accessor(CanvasRenderingContext2D.getStrokeStyle, CanvasRenderingContext2D.setStrokeStyle, .{}); + + pub const lineWidth = bridge.accessor(CanvasRenderingContext2D.getLineWidth, CanvasRenderingContext2D.setLineWidth, .{}); + pub const lineCap = bridge.accessor(CanvasRenderingContext2D.getLineCap, CanvasRenderingContext2D.setLineCap, .{}); + pub const lineJoin = bridge.accessor(CanvasRenderingContext2D.getLineJoin, CanvasRenderingContext2D.setLineJoin, .{}); + pub const miterLimit = bridge.accessor(CanvasRenderingContext2D.getMiterLimit, CanvasRenderingContext2D.setMiterLimit, .{}); + + pub const clearRect = bridge.function(CanvasRenderingContext2D.clearRect, .{}); pub const fillRect = bridge.function(CanvasRenderingContext2D.fillRect, .{}); + pub const strokeRect = bridge.function(CanvasRenderingContext2D.strokeRect, .{}); + + pub const beginPath = bridge.function(CanvasRenderingContext2D.beginPath, .{}); + pub const closePath = bridge.function(CanvasRenderingContext2D.closePath, .{}); + pub const moveTo = bridge.function(CanvasRenderingContext2D.moveTo, .{}); + pub const lineTo = bridge.function(CanvasRenderingContext2D.lineTo, .{}); + pub const quadraticCurveTo = bridge.function(CanvasRenderingContext2D.quadraticCurveTo, .{}); + pub const bezierCurveTo = bridge.function(CanvasRenderingContext2D.bezierCurveTo, .{}); + pub const arc = bridge.function(CanvasRenderingContext2D.arc, .{}); + pub const arcTo = bridge.function(CanvasRenderingContext2D.arcTo, .{}); + pub const rect = bridge.function(CanvasRenderingContext2D.rect, .{}); + + pub const fill = bridge.function(CanvasRenderingContext2D.fill, .{}); + pub const stroke = bridge.function(CanvasRenderingContext2D.stroke, .{}); + pub const clip = bridge.function(CanvasRenderingContext2D.clip, .{}); + + pub const font = bridge.accessor(CanvasRenderingContext2D.getFont, CanvasRenderingContext2D.setFont, .{}); + pub const textAlign = bridge.accessor(CanvasRenderingContext2D.getTextAlign, CanvasRenderingContext2D.setTextAlign, .{}); + pub const textBaseline = bridge.accessor(CanvasRenderingContext2D.getTextBaseline, CanvasRenderingContext2D.setTextBaseline, .{}); + pub const fillText = bridge.function(CanvasRenderingContext2D.fillText, .{}); + pub const strokeText = bridge.function(CanvasRenderingContext2D.strokeText, .{}); }; const testing = @import("../../../testing.zig"); diff --git a/src/browser/webapi/canvas/WebGLRenderingContext.zig b/src/browser/webapi/canvas/WebGLRenderingContext.zig index bdafce3a..2e3ac485 100644 --- a/src/browser/webapi/canvas/WebGLRenderingContext.zig +++ b/src/browser/webapi/canvas/WebGLRenderingContext.zig @@ -19,12 +19,15 @@ const std = @import("std"); const js = @import("../../js/js.zig"); +const Page = @import("../../Page.zig"); pub fn registerTypes() []const type { return &.{ WebGLRenderingContext, - //Extension.Type.WEBGL_debug_renderer_info, - //Extension.Type.WEBGL_lose_context, + // Extension types should be runtime generated. We might want + // to revisit this. + Extension.Type.WEBGL_debug_renderer_info, + Extension.Type.WEBGL_lose_context, }; } @@ -66,11 +69,11 @@ pub const Extension = union(enum) { WEBGL_compressed_texture_pvrtc: void, WEBGL_compressed_texture_s3tc: void, WEBGL_compressed_texture_s3tc_srgb: void, - WEBGL_debug_renderer_info: Type.WEBGL_debug_renderer_info, + WEBGL_debug_renderer_info: *Type.WEBGL_debug_renderer_info, WEBGL_debug_shaders: void, WEBGL_depth_texture: void, WEBGL_draw_buffers: void, - WEBGL_lose_context: Type.WEBGL_lose_context, + WEBGL_lose_context: *Type.WEBGL_lose_context, WEBGL_multi_draw: void, WEBGL_polygon_mode: void, @@ -115,35 +118,76 @@ pub const Extension = union(enum) { /// Extension types. pub const Type = struct { pub const WEBGL_debug_renderer_info = struct { + _: u8 = 0, pub const UNMASKED_VENDOR_WEBGL: u64 = 0x9245; pub const UNMASKED_RENDERER_WEBGL: u64 = 0x9246; - pub fn get_UNMASKED_VENDOR_WEBGL() u64 { + pub fn getUnmaskedVendorWebGL(_: *const WEBGL_debug_renderer_info) u64 { return UNMASKED_VENDOR_WEBGL; } - pub fn get_UNMASKED_RENDERER_WEBGL() u64 { + pub fn getUnmaskedRendererWebGL(_: *const WEBGL_debug_renderer_info) u64 { return UNMASKED_RENDERER_WEBGL; } + + pub const JsApi = struct { + pub const bridge = js.Bridge(WEBGL_debug_renderer_info); + + pub const Meta = struct { + pub const name = "WEBGL_debug_renderer_info"; + + pub const prototype_chain = bridge.prototypeChain(); + pub var class_id: bridge.ClassId = undefined; + }; + + pub const UNMASKED_VENDOR_WEBGL = bridge.accessor(WEBGL_debug_renderer_info.getUnmaskedVendorWebGL, null, .{}); + pub const UNMASKED_RENDERER_WEBGL = bridge.accessor(WEBGL_debug_renderer_info.getUnmaskedRendererWebGL, null, .{}); + }; }; pub const WEBGL_lose_context = struct { _: u8 = 0, - pub fn _loseContext(_: *const WEBGL_lose_context) void {} - pub fn _restoreContext(_: *const WEBGL_lose_context) void {} + pub fn loseContext(_: *const WEBGL_lose_context) void {} + pub fn restoreContext(_: *const WEBGL_lose_context) void {} + + pub const JsApi = struct { + pub const bridge = js.Bridge(WEBGL_lose_context); + + pub const Meta = struct { + pub const name = "WEBGL_lose_context"; + + pub const prototype_chain = bridge.prototypeChain(); + pub var class_id: bridge.ClassId = undefined; + }; + + pub const loseContext = bridge.function(WEBGL_lose_context.loseContext, .{}); + pub const restoreContext = bridge.function(WEBGL_lose_context.restoreContext, .{}); + }; }; }; }; -/// Enables a WebGL extension. -pub fn getExtension(self: *const WebGLRenderingContext, name: []const u8) ?Extension { - _ = self; +/// This actually takes "GLenum" which, in fact, is a fancy way to say number. +/// Return value also depends on what's being passed as `pname`; we don't really +/// support any though. +pub fn getParameter(_: *const WebGLRenderingContext, pname: u32) []const u8 { + _ = pname; + return ""; +} +/// Enables a WebGL extension. +pub fn getExtension(_: *const WebGLRenderingContext, name: []const u8, page: *Page) !?Extension { const tag = Extension.find(name) orelse return null; return switch (tag) { - .WEBGL_debug_renderer_info => @unionInit(Extension, "WEBGL_debug_renderer_info", .{}), - .WEBGL_lose_context => @unionInit(Extension, "WEBGL_lose_context", .{}), + .WEBGL_debug_renderer_info => { + const info = try page._factory.create(Extension.Type.WEBGL_debug_renderer_info{}); + return .{ .WEBGL_debug_renderer_info = info }; + }, + .WEBGL_lose_context => { + const ctx = try page._factory.create(Extension.Type.WEBGL_lose_context{}); + return .{ .WEBGL_lose_context = ctx }; + }, inline else => |comptime_enum| @unionInit(Extension, @tagName(comptime_enum), {}), }; } @@ -163,6 +207,7 @@ pub const JsApi = struct { pub var class_id: bridge.ClassId = undefined; }; + pub const getParameter = bridge.function(WebGLRenderingContext.getParameter, .{}); pub const getExtension = bridge.function(WebGLRenderingContext.getExtension, .{}); pub const getSupportedExtensions = bridge.function(WebGLRenderingContext.getSupportedExtensions, .{}); }; diff --git a/src/browser/webapi/element/html/Canvas.zig b/src/browser/webapi/element/html/Canvas.zig index eb60befd..8e973e09 100644 --- a/src/browser/webapi/element/html/Canvas.zig +++ b/src/browser/webapi/element/html/Canvas.zig @@ -23,151 +23,12 @@ const Node = @import("../../Node.zig"); const Element = @import("../../Element.zig"); const HtmlElement = @import("../Html.zig"); -pub fn registerTypes() []const type { - return &.{ - Canvas, - RenderingContext2D, - }; -} +const CanvasRenderingContext2D = @import("../../canvas/CanvasRenderingContext2D.zig"); +const WebGLRenderingContext = @import("../../canvas/WebGLRenderingContext.zig"); const Canvas = @This(); _proto: *HtmlElement, -pub const RenderingContext2D = struct { - pub fn save(_: *RenderingContext2D) void {} - pub fn restore(_: *RenderingContext2D) void {} - - pub fn scale(_: *RenderingContext2D, _: f64, _: f64) void {} - pub fn rotate(_: *RenderingContext2D, _: f64) void {} - pub fn translate(_: *RenderingContext2D, _: f64, _: f64) void {} - pub fn transform(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: f64) void {} - pub fn setTransform(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: f64) void {} - pub fn resetTransform(_: *RenderingContext2D) void {} - - pub fn getGlobalAlpha(_: *const RenderingContext2D) f64 { - return 1.0; - } - pub fn setGlobalAlpha(_: *RenderingContext2D, _: f64) void {} - pub fn getGlobalCompositeOperation(_: *const RenderingContext2D) []const u8 { - return "source-over"; - } - pub fn setGlobalCompositeOperation(_: *RenderingContext2D, _: []const u8) void {} - - pub fn getFillStyle(_: *const RenderingContext2D) []const u8 { - return "#000000"; - } - pub fn setFillStyle(_: *RenderingContext2D, _: []const u8) void {} - pub fn getStrokeStyle(_: *const RenderingContext2D) []const u8 { - return "#000000"; - } - pub fn setStrokeStyle(_: *RenderingContext2D, _: []const u8) void {} - - pub fn getLineWidth(_: *const RenderingContext2D) f64 { - return 1.0; - } - pub fn setLineWidth(_: *RenderingContext2D, _: f64) void {} - pub fn getLineCap(_: *const RenderingContext2D) []const u8 { - return "butt"; - } - pub fn setLineCap(_: *RenderingContext2D, _: []const u8) void {} - pub fn getLineJoin(_: *const RenderingContext2D) []const u8 { - return "miter"; - } - pub fn setLineJoin(_: *RenderingContext2D, _: []const u8) void {} - pub fn getMiterLimit(_: *const RenderingContext2D) f64 { - return 10.0; - } - pub fn setMiterLimit(_: *RenderingContext2D, _: f64) void {} - - pub fn clearRect(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} - pub fn fillRect(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} - pub fn strokeRect(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} - - pub fn beginPath(_: *RenderingContext2D) void {} - pub fn closePath(_: *RenderingContext2D) void {} - pub fn moveTo(_: *RenderingContext2D, _: f64, _: f64) void {} - pub fn lineTo(_: *RenderingContext2D, _: f64, _: f64) void {} - pub fn quadraticCurveTo(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} - pub fn bezierCurveTo(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: f64) void {} - pub fn arc(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64, _: ?bool) void {} - pub fn arcTo(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64, _: f64) void {} - pub fn rect(_: *RenderingContext2D, _: f64, _: f64, _: f64, _: f64) void {} - - pub fn fill(_: *RenderingContext2D) void {} - pub fn stroke(_: *RenderingContext2D) void {} - pub fn clip(_: *RenderingContext2D) void {} - - pub fn getFont(_: *const RenderingContext2D) []const u8 { - return "10px sans-serif"; - } - pub fn setFont(_: *RenderingContext2D, _: []const u8) void {} - pub fn getTextAlign(_: *const RenderingContext2D) []const u8 { - return "start"; - } - pub fn setTextAlign(_: *RenderingContext2D, _: []const u8) void {} - pub fn getTextBaseline(_: *const RenderingContext2D) []const u8 { - return "alphabetic"; - } - pub fn setTextBaseline(_: *RenderingContext2D, _: []const u8) void {} - pub fn fillText(_: *RenderingContext2D, _: []const u8, _: f64, _: f64, _: ?f64) void {} - pub fn strokeText(_: *RenderingContext2D, _: []const u8, _: f64, _: f64, _: ?f64) void {} - - pub const JsApi = struct { - pub const bridge = js.Bridge(RenderingContext2D); - - pub const Meta = struct { - pub const name = "CanvasRenderingContext2D"; - pub const prototype_chain = bridge.prototypeChain(); - pub var class_id: bridge.ClassId = undefined; - }; - - pub const save = bridge.function(RenderingContext2D.save, .{}); - pub const restore = bridge.function(RenderingContext2D.restore, .{}); - - pub const scale = bridge.function(RenderingContext2D.scale, .{}); - pub const rotate = bridge.function(RenderingContext2D.rotate, .{}); - pub const translate = bridge.function(RenderingContext2D.translate, .{}); - pub const transform = bridge.function(RenderingContext2D.transform, .{}); - pub const setTransform = bridge.function(RenderingContext2D.setTransform, .{}); - pub const resetTransform = bridge.function(RenderingContext2D.resetTransform, .{}); - - pub const globalAlpha = bridge.accessor(RenderingContext2D.getGlobalAlpha, RenderingContext2D.setGlobalAlpha, .{}); - pub const globalCompositeOperation = bridge.accessor(RenderingContext2D.getGlobalCompositeOperation, RenderingContext2D.setGlobalCompositeOperation, .{}); - - pub const fillStyle = bridge.accessor(RenderingContext2D.getFillStyle, RenderingContext2D.setFillStyle, .{}); - pub const strokeStyle = bridge.accessor(RenderingContext2D.getStrokeStyle, RenderingContext2D.setStrokeStyle, .{}); - - pub const lineWidth = bridge.accessor(RenderingContext2D.getLineWidth, RenderingContext2D.setLineWidth, .{}); - pub const lineCap = bridge.accessor(RenderingContext2D.getLineCap, RenderingContext2D.setLineCap, .{}); - pub const lineJoin = bridge.accessor(RenderingContext2D.getLineJoin, RenderingContext2D.setLineJoin, .{}); - pub const miterLimit = bridge.accessor(RenderingContext2D.getMiterLimit, RenderingContext2D.setMiterLimit, .{}); - - pub const clearRect = bridge.function(RenderingContext2D.clearRect, .{}); - pub const fillRect = bridge.function(RenderingContext2D.fillRect, .{}); - pub const strokeRect = bridge.function(RenderingContext2D.strokeRect, .{}); - - pub const beginPath = bridge.function(RenderingContext2D.beginPath, .{}); - pub const closePath = bridge.function(RenderingContext2D.closePath, .{}); - pub const moveTo = bridge.function(RenderingContext2D.moveTo, .{}); - pub const lineTo = bridge.function(RenderingContext2D.lineTo, .{}); - pub const quadraticCurveTo = bridge.function(RenderingContext2D.quadraticCurveTo, .{}); - pub const bezierCurveTo = bridge.function(RenderingContext2D.bezierCurveTo, .{}); - pub const arc = bridge.function(RenderingContext2D.arc, .{}); - pub const arcTo = bridge.function(RenderingContext2D.arcTo, .{}); - pub const rect = bridge.function(RenderingContext2D.rect, .{}); - - pub const fill = bridge.function(RenderingContext2D.fill, .{}); - pub const stroke = bridge.function(RenderingContext2D.stroke, .{}); - pub const clip = bridge.function(RenderingContext2D.clip, .{}); - - pub const font = bridge.accessor(RenderingContext2D.getFont, RenderingContext2D.setFont, .{}); - pub const textAlign = bridge.accessor(RenderingContext2D.getTextAlign, RenderingContext2D.setTextAlign, .{}); - pub const textBaseline = bridge.accessor(RenderingContext2D.getTextBaseline, RenderingContext2D.setTextBaseline, .{}); - pub const fillText = bridge.function(RenderingContext2D.fillText, .{}); - pub const strokeText = bridge.function(RenderingContext2D.strokeText, .{}); - }; -}; - pub fn asElement(self: *Canvas) *Element { return self._proto._proto; } @@ -198,16 +59,25 @@ pub fn setHeight(self: *Canvas, value: u32, page: *Page) !void { try self.asElement().setAttributeSafe("height", str, page); } -pub fn getContext(self: *Canvas, context_type: []const u8, page: *Page) !?*RenderingContext2D { - _ = self; +/// Since there's no base class rendering contextes inherit from, +/// we're using tagged union. +const DrawingContext = union(enum) { + @"2d": *CanvasRenderingContext2D, + webgl: *WebGLRenderingContext, +}; - if (!std.mem.eql(u8, context_type, "2d")) { - return null; +pub fn getContext(_: *Canvas, context_type: []const u8, page: *Page) !?DrawingContext { + if (std.mem.eql(u8, context_type, "2d")) { + const ctx = try page._factory.create(CanvasRenderingContext2D{}); + return .{ .@"2d" = ctx }; } - const ctx = try page.arena.create(RenderingContext2D); - ctx.* = .{}; - return ctx; + if (std.mem.eql(u8, context_type, "webgl") or std.mem.eql(u8, context_type, "experimental-webgl")) { + const ctx = try page._factory.create(WebGLRenderingContext{}); + return .{ .webgl = ctx }; + } + + return null; } pub const JsApi = struct {