diff --git a/src/browser/js/bridge.zig b/src/browser/js/bridge.zig index 3a991313..7640d0a1 100644 --- a/src/browser/js/bridge.zig +++ b/src/browser/js/bridge.zig @@ -713,6 +713,7 @@ pub const JsApis = flattenTypes(&.{ @import("../webapi/css/CSSStyleRule.zig"), @import("../webapi/css/CSSStyleSheet.zig"), @import("../webapi/css/CSSStyleProperties.zig"), + @import("../webapi/css/FontFaceSet.zig"), @import("../webapi/css/MediaQueryList.zig"), @import("../webapi/css/StyleSheetList.zig"), @import("../webapi/Document.zig"), diff --git a/src/browser/tests/css/font_face_set.html b/src/browser/tests/css/font_face_set.html new file mode 100644 index 00000000..a860669e --- /dev/null +++ b/src/browser/tests/css/font_face_set.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index 85f9c35f..ddb4c79a 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -34,6 +34,7 @@ const DOMTreeWalker = @import("DOMTreeWalker.zig"); const DOMNodeIterator = @import("DOMNodeIterator.zig"); const DOMImplementation = @import("DOMImplementation.zig"); const StyleSheetList = @import("css/StyleSheetList.zig"); +const FontFaceSet = @import("css/FontFaceSet.zig"); const Selection = @import("Selection.zig"); pub const XMLDocument = @import("XMLDocument.zig"); @@ -52,6 +53,7 @@ _elements_by_id: std.StringHashMapUnmanaged(*Element) = .empty, _removed_ids: std.StringHashMapUnmanaged(void) = .empty, _active_element: ?*Element = null, _style_sheets: ?*StyleSheetList = null, +_fonts: ?*FontFaceSet = null, _write_insertion_point: ?*Node = null, _script_created_parser: ?Parser.Streaming = null, _adopted_style_sheets: ?js.Object.Global = null, @@ -430,6 +432,15 @@ pub fn getStyleSheets(self: *Document, page: *Page) !*StyleSheetList { return sheets; } +pub fn getFonts(self: *Document, page: *Page) !*FontFaceSet { + if (self._fonts) |fonts| { + return fonts; + } + const fonts = try FontFaceSet.init(page); + self._fonts = fonts; + return fonts; +} + pub fn adoptNode(_: *const Document, node: *Node, page: *Page) !*Node { if (node._type == .document) { return error.NotSupported; @@ -963,6 +974,7 @@ pub const JsApi = struct { pub const implementation = bridge.accessor(Document.getImplementation, null, .{}); pub const activeElement = bridge.accessor(Document.getActiveElement, null, .{}); pub const styleSheets = bridge.accessor(Document.getStyleSheets, null, .{}); + pub const fonts = bridge.accessor(Document.getFonts, null, .{}); pub const contentType = bridge.accessor(Document.getContentType, null, .{}); pub const domain = bridge.accessor(Document.getDomain, null, .{}); pub const createElement = bridge.function(Document.createElement, .{ .dom_exception = true }); diff --git a/src/browser/webapi/css/FontFaceSet.zig b/src/browser/webapi/css/FontFaceSet.zig new file mode 100644 index 00000000..cd3cf2b1 --- /dev/null +++ b/src/browser/webapi/css/FontFaceSet.zig @@ -0,0 +1,59 @@ +const std = @import("std"); +const js = @import("../../js/js.zig"); +const Page = @import("../../Page.zig"); + +const FontFaceSet = @This(); + +// Padding to avoid zero-size struct, which causes identity_map pointer collisions. +_pad: bool = false, + +pub fn init(page: *Page) !*FontFaceSet { + return page._factory.create(FontFaceSet{}); +} + +// FontFaceSet.ready - returns an already-resolved Promise. +// In a headless browser there is no font loading, so fonts are always ready. +pub fn getReady(_: *FontFaceSet, page: *Page) !js.Promise { + return page.js.local.?.resolvePromise({}); +} + +pub fn getStatus(_: *const FontFaceSet) []const u8 { + return "loaded"; +} + +pub fn getSize(_: *const FontFaceSet) u32 { + return 0; +} + +// check(font, text?) - always true; headless has no real fonts to check. +pub fn check(_: *const FontFaceSet, font: []const u8) bool { + _ = font; + return true; +} + +// load(font, text?) - resolves immediately with an empty array. +pub fn load(_: *FontFaceSet, font: []const u8, page: *Page) !js.Promise { + _ = font; + return page.js.local.?.resolvePromise({}); +} + +pub const JsApi = struct { + pub const bridge = js.Bridge(FontFaceSet); + + pub const Meta = struct { + pub const name = "FontFaceSet"; + pub const prototype_chain = bridge.prototypeChain(); + pub var class_id: bridge.ClassId = undefined; + }; + + pub const ready = bridge.accessor(FontFaceSet.getReady, null, .{}); + pub const status = bridge.accessor(FontFaceSet.getStatus, null, .{}); + pub const size = bridge.accessor(FontFaceSet.getSize, null, .{}); + pub const check = bridge.function(FontFaceSet.check, .{}); + pub const load = bridge.function(FontFaceSet.load, .{}); +}; + +const testing = @import("../../../testing.zig"); +test "WebApi: FontFaceSet" { + try testing.htmlRunner("css/font_face_set.html", .{}); +}