Merge pull request #1786 from lightpanda-io/fontfaceset-load

FontFaceSet is now an EventTarget
This commit is contained in:
Karl Seguin
2026-03-12 06:36:22 +08:00
committed by GitHub
3 changed files with 52 additions and 5 deletions

View File

@@ -56,3 +56,25 @@
testing.expectEqual('FontFaceSet', document.fonts.constructor.name);
}
</script>
<script id="document_fonts_addEventListener">
{
let loading = false;
document.fonts.addEventListener('loading', function() {
loading = true;
});
let loadingdone = false;
document.fonts.addEventListener('loadingdone', function() {
loadingdone = true;
});
document.fonts.load("italic bold 16px Roboto");
testing.eventually(() => {
testing.expectEqual(true, loading);
testing.expectEqual(true, loadingdone);
});
testing.expectEqual(true, true);
}
</script>

View File

@@ -44,6 +44,7 @@ pub const Type = union(enum) {
screen_orientation: *@import("Screen.zig").Orientation,
visual_viewport: *@import("VisualViewport.zig"),
file_reader: *@import("FileReader.zig"),
font_face_set: *@import("css/FontFaceSet.zig"),
};
pub fn init(page: *Page) !*EventTarget {
@@ -139,6 +140,7 @@ pub fn format(self: *EventTarget, writer: *std.Io.Writer) !void {
.screen_orientation => writer.writeAll("<ScreenOrientation>"),
.visual_viewport => writer.writeAll("<VisualViewport>"),
.file_reader => writer.writeAll("<FileReader>"),
.font_face_set => writer.writeAll("<FontFaceSet>"),
};
}
@@ -157,6 +159,7 @@ pub fn toString(self: *EventTarget) []const u8 {
.screen_orientation => return "[object ScreenOrientation]",
.visual_viewport => return "[object VisualViewport]",
.file_reader => return "[object FileReader]",
.font_face_set => return "[object FontFaceSet]",
};
}

View File

@@ -21,28 +21,34 @@ const js = @import("../../js/js.zig");
const Page = @import("../../Page.zig");
const Session = @import("../../Session.zig");
const FontFace = @import("FontFace.zig");
const EventTarget = @import("../EventTarget.zig");
const Event = @import("../Event.zig");
const Allocator = std.mem.Allocator;
const FontFaceSet = @This();
_proto: *EventTarget,
_arena: Allocator,
pub fn init(page: *Page) !*FontFaceSet {
const arena = try page.getArena(.{ .debug = "FontFaceSet" });
errdefer page.releaseArena(arena);
const self = try arena.create(FontFaceSet);
self.* = .{
return page._factory.eventTargetWithAllocator(arena, FontFaceSet{
._proto = undefined,
._arena = arena,
};
return self;
});
}
pub fn deinit(self: *FontFaceSet, _: bool, session: *Session) void {
session.releaseArena(self._arena);
}
pub fn asEventTarget(self: *FontFaceSet) *EventTarget {
return self._proto;
}
// 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 {
@@ -56,8 +62,24 @@ pub fn check(_: *const FontFaceSet, font: []const u8) bool {
}
// load(font, text?) - resolves immediately with an empty array.
pub fn load(_: *FontFaceSet, font: []const u8, page: *Page) !js.Promise {
pub fn load(self: *FontFaceSet, font: []const u8, page: *Page) !js.Promise {
// TODO parse font to check if the font has been added before dispatching
// events.
_ = font;
// Dispatch loading event
const target = self.asEventTarget();
if (page._event_manager.hasDirectListeners(target, "loading", null)) {
const event = try Event.initTrusted(comptime .wrap("loading"), .{}, page);
try page._event_manager.dispatchDirect(target, event, null, .{ .context = "load font face set" });
}
// Dispatch loadingdone event
if (page._event_manager.hasDirectListeners(target, "loadingdone", null)) {
const event = try Event.initTrusted(comptime .wrap("loadingdone"), .{}, page);
try page._event_manager.dispatchDirect(target, event, null, .{ .context = "load font face set" });
}
return page.js.local.?.resolvePromise({});
}