From 4daa49fe27c5aea0ebfec6fde757fa0e529760ec Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 28 May 2024 20:25:49 -0700 Subject: [PATCH] font/freetype: update to new presentation APIs --- pkg/freetype/face.zig | 6 ++++++ src/font/face/freetype.zig | 37 ++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/pkg/freetype/face.zig b/pkg/freetype/face.zig index 7b72d1b94..f4eaf24f0 100644 --- a/pkg/freetype/face.zig +++ b/pkg/freetype/face.zig @@ -26,6 +26,12 @@ pub const Face = struct { return c.FT_HAS_COLOR(self.handle); } + /// A macro that returns true whenever a face object contains an ‘sbix’ + /// OpenType table and outline glyphs. + pub fn hasSBIX(self: Face) bool { + return c.FT_HAS_SBIX(self.handle); + } + /// A macro that returns true whenever a face object contains some /// multiple masters. pub fn hasMultipleMasters(self: Face) bool { diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 33eca002c..6037f6c0c 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -15,7 +15,6 @@ const Allocator = std.mem.Allocator; const font = @import("../main.zig"); const Glyph = font.Glyph; const Library = font.Library; -const Presentation = font.Presentation; const convert = @import("freetype_convert.zig"); const fastmem = @import("../../fastmem.zig"); const quirks = @import("../../quirks.zig"); @@ -32,10 +31,6 @@ pub const Face = struct { /// Harfbuzz font corresponding to this face. hb_font: harfbuzz.Font, - /// The presentation for this font. This is a heuristic since fonts don't have - /// a way to declare this. We just assume a font with color is an emoji font. - presentation: Presentation, - /// Metrics for this font face. These are useful for renderers. metrics: font.face.Metrics, @@ -67,17 +62,10 @@ pub const Face = struct { .lib = lib.lib, .face = face, .hb_font = hb_font, - .presentation = if (face.hasColor()) .emoji else .text, .metrics = calcMetrics(face, opts.metric_modifiers), }; result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result); - // See coretext.zig which has a similar check for this. - if (result.presentation == .emoji and result.glyphIndex('🥸') == null) { - log.warn("font has colorized glyphs but isn't emoji, treating as text", .{}); - result.presentation = .text; - } - // In debug mode, we output information about available variation axes, // if they exist. if (comptime builtin.mode == .Debug) mm: { @@ -219,10 +207,29 @@ pub const Face = struct { /// Returns true if this font is colored. This can be used by callers to /// determine what kind of atlas to pass in. - fn hasColor(self: Face) bool { + pub fn hasColor(self: Face) bool { return self.face.hasColor(); } + /// Returns true if the given glyph ID is colorized. + pub fn isColorGlyph(self: *const Face, glyph_id: u32) bool { + // sbix table is always true for now + if (self.face.hasSBIX()) return true; + + // Otherwise, load the glyph and see what format it is in. + self.face.loadGlyph(glyph_id, .{ + .render = true, + .color = self.face.hasColor(), + .no_bitmap = !self.face.hasColor(), + }) catch return false; + + // If the glyph is SVG we assume colorized + const glyph = self.face.handle.*.glyph; + if (glyph.*.format == freetype.c.FT_GLYPH_FORMAT_SVG) return true; + + return false; + } + /// Render a glyph using the glyph index. The rendered glyph is stored in the /// given texture atlas. pub fn renderGlyph( @@ -655,8 +662,6 @@ test { ); defer ft_font.deinit(); - try testing.expectEqual(Presentation.text, ft_font.presentation); - // Generate all visible ASCII var i: u8 = 32; while (i < 127) : (i += 1) { @@ -691,8 +696,6 @@ test "color emoji" { ); defer ft_font.deinit(); - try testing.expectEqual(Presentation.emoji, ft_font.presentation); - _ = try ft_font.renderGlyph(alloc, &atlas, ft_font.glyphIndex('🥸').?, .{}); // resize