Merge pull request #1799 from mitchellh/mixed-font

font: treated fonts with mixed color/non-color glyphs as text
This commit is contained in:
Mitchell Hashimoto
2024-05-26 15:24:54 -07:00
committed by GitHub
6 changed files with 45 additions and 0 deletions

View File

@ -81,6 +81,14 @@ pub const Font = opaque {
); );
} }
pub fn createPathForGlyph(self: *Font, glyph: graphics.Glyph) ?*graphics.Path {
return @constCast(@ptrCast(c.CTFontCreatePathForGlyph(
@ptrCast(self),
glyph,
null,
)));
}
pub fn drawGlyphs( pub fn drawGlyphs(
self: *Font, self: *Font,
glyphs: []const graphics.Glyph, glyphs: []const graphics.Glyph,

View File

@ -102,6 +102,20 @@ pub const Face = struct {
}; };
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result); result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
// If our presentation is emoji, we also check for the presence of
// emoji codepoints. This forces fonts with colorized glyphs that aren't
// emoji font to be treated as text. Long term, this isn't what we want
// but this fixes some bugs in the short term. See:
// https://github.com/mitchellh/ghostty/issues/1768
//
// Longer term, we'd like to detect mixed color/non-color fonts and
// handle them correctly by rendering the color glyphs as color and the
// non-color glyphs as text.
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, // In debug mode, we output information about available variation axes,
// if they exist. // if they exist.
if (comptime builtin.mode == .Debug) { if (comptime builtin.mode == .Debug) {
@ -700,3 +714,16 @@ test "variable set variation" {
_ = try face.renderGlyph(alloc, &atlas, face.glyphIndex(i).?, .{}); _ = try face.renderGlyph(alloc, &atlas, face.glyphIndex(i).?, .{});
} }
} }
test "mixed color/non-color font treated as text" {
const testing = std.testing;
const testFont = @import("../test.zig").fontJuliaMono;
var lib = try font.Library.init();
defer lib.deinit();
var face = try Face.init(lib, testFont, .{ .size = .{ .points = 12 } });
defer face.deinit();
try testing.expect(face.presentation == .text);
}

View File

@ -72,6 +72,12 @@ pub const Face = struct {
}; };
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result); 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, // In debug mode, we output information about available variation axes,
// if they exist. // if they exist.
if (comptime builtin.mode == .Debug) mm: { if (comptime builtin.mode == .Debug) mm: {

Binary file not shown.

View File

@ -18,6 +18,7 @@ pub const fontNerdFont = @embedFile("res/JetBrainsMonoNerdFont-Regular.ttf");
/// Specific font families below: /// Specific font families below:
pub const fontGeistMono = @embedFile("res/GeistMono-Regular.ttf"); pub const fontGeistMono = @embedFile("res/GeistMono-Regular.ttf");
pub const fontJetBrainsMono = @embedFile("res/JetBrainsMonoNoNF-Regular.ttf"); pub const fontJetBrainsMono = @embedFile("res/JetBrainsMonoNoNF-Regular.ttf");
pub const fontJuliaMono = @embedFile("res/JuliaMono-Regular.ttf");
/// Cozette is a unique font because it embeds some emoji characters /// Cozette is a unique font because it embeds some emoji characters
/// but has a text presentation. /// but has a text presentation.

View File

@ -22,8 +22,11 @@ pub fn disableDefaultFontFeatures(face: *const font.Face) bool {
// CodeNewRoman, Menlo and Monaco both have a default ligature of "fi" that // CodeNewRoman, Menlo and Monaco both have a default ligature of "fi" that
// looks really bad in terminal grids, so we want to disable ligatures // looks really bad in terminal grids, so we want to disable ligatures
// by default for these faces. // by default for these faces.
//
// JuliaMono has a default ligature of "st" that looks bad.
return std.mem.eql(u8, name, "CodeNewRoman") or return std.mem.eql(u8, name, "CodeNewRoman") or
std.mem.eql(u8, name, "CodeNewRoman Nerd Font") or std.mem.eql(u8, name, "CodeNewRoman Nerd Font") or
std.mem.eql(u8, name, "JuliaMono") or
std.mem.eql(u8, name, "Menlo") or std.mem.eql(u8, name, "Menlo") or
std.mem.eql(u8, name, "Monaco"); std.mem.eql(u8, name, "Monaco");
} }