From 62990bb33e8c87938f3795a8f4123c59dd53b047 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Dec 2022 20:52:03 -0800 Subject: [PATCH] font: Group is now wasm-compatible --- example/app.ts | 19 ++++++++--- src/font/Group.zig | 81 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/example/app.ts b/example/app.ts index 5dcd949be..85eee4d5b 100644 --- a/example/app.ts +++ b/example/app.ts @@ -32,6 +32,11 @@ fetch(url.href).then(response => deferred_face_free, deferred_face_load, deferred_face_face, + group_new, + group_free, + group_add_face, + group_index_for_codepoint, + group_render_glyph, atlas_new, atlas_free, atlas_debug_canvas, @@ -53,22 +58,28 @@ fetch(url.href).then(response => // Initialize our deferred face const df = deferred_face_new(font_ptr, font.byteLength); - deferred_face_load(df, 72 /* size */); - const face = deferred_face_face(df); + //deferred_face_load(df, 72 /* size */); + //const face = deferred_face_face(df); // Initialize our font face //const face = face_new(font_ptr, font.byteLength, 72 /* size in px */); free(font_ptr); + // Create our group + const group = group_new(72 /* size */); + group_add_face(group, 0, df); + // Render a glyph for (let i = 33; i <= 126; i++) { - face_render_glyph(face, atlas, i); + const font_idx = group_index_for_codepoint(group, i, 0, -1); + group_render_glyph(group, atlas, font_idx, i, 0); + //face_render_glyph(face, atlas, i); } //face_render_glyph(face, atlas, "橋".codePointAt(0)); //face_render_glyph(face, atlas, "p".codePointAt(0)); // Debug our canvas - face_debug_canvas(face); + //face_debug_canvas(face); // Debug our atlas canvas const id = atlas_debug_canvas(atlas); diff --git a/src/font/Group.zig b/src/font/Group.zig index 92fbf7100..dbe9cd499 100644 --- a/src/font/Group.zig +++ b/src/font/Group.zig @@ -119,7 +119,7 @@ pub fn setSize(self: *Group, size: font.face.DesiredSize) !void { } /// This represents a specific font in the group. -pub const FontIndex = packed struct { +pub const FontIndex = packed struct(u8) { /// The number of bits we use for the index. const idx_bits = 8 - @typeInfo(@typeInfo(Style).Enum.tag_type).Int.bits; pub const IndexInt = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = idx_bits } }); @@ -272,13 +272,16 @@ pub fn renderGlyph( max_height: ?u16, ) !Glyph { // Special-case fonts are rendered directly. - if (index.special()) |sp| switch (sp) { - .sprite => return try self.sprite.?.renderGlyph( - alloc, - atlas, - glyph_index, - ), - }; + // TODO: web_canvas + if (options.backend != .web_canvas) { + if (index.special()) |sp| switch (sp) { + .sprite => return try self.sprite.?.renderGlyph( + alloc, + atlas, + glyph_index, + ), + }; + } const face = &self.faces.get(index.style).items[@intCast(usize, index.idx)]; try face.load(self.lib, self.size); @@ -303,6 +306,68 @@ pub const Wasm = struct { result.* = group; return result; } + + export fn group_free(ptr: ?*Group) void { + if (ptr) |v| { + v.deinit(); + alloc.destroy(v); + } + } + + export fn group_add_face(self: *Group, style: u16, face: *font.DeferredFace) void { + return self.addFace(alloc, @intToEnum(Style, style), face.*) catch |err| { + log.warn("error adding face to group err={}", .{err}); + return; + }; + } + + export fn group_set_size(self: *Group, size: u16) void { + return self.setSize(.{ .points = size }) catch |err| { + log.warn("error setting group size err={}", .{err}); + return; + }; + } + + /// Presentation is negative for doesn't matter. + export fn group_index_for_codepoint(self: *Group, cp: u32, style: u16, p: i16) i16 { + const presentation = if (p < 0) null else @intToEnum(Presentation, p); + const idx = self.indexForCodepoint( + cp, + @intToEnum(Style, style), + presentation, + ) orelse return -1; + return @intCast(i16, @bitCast(u8, idx)); + } + + export fn group_render_glyph( + self: *Group, + atlas: *font.Atlas, + idx: i16, + cp: u32, + max_height: u16, + ) ?*Glyph { + return group_render_glyph_(self, atlas, idx, cp, max_height) catch |err| { + log.warn("error rendering group glyph err={}", .{err}); + return null; + }; + } + + fn group_render_glyph_( + self: *Group, + atlas: *font.Atlas, + idx_: i16, + cp: u32, + max_height_: u16, + ) !*Glyph { + const idx = @bitCast(FontIndex, @intCast(u8, idx_)); + const max_height = if (max_height_ <= 0) null else max_height_; + const glyph = try self.renderGlyph(alloc, atlas, idx, cp, max_height); + + var result = try alloc.create(Glyph); + errdefer alloc.destroy(result); + result.* = glyph; + return result; + } }; test {