mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 01:06:08 +03:00
Merge pull request #1799 from mitchellh/mixed-font
font: treated fonts with mixed color/non-color glyphs as text
This commit is contained in:
@ -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,
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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: {
|
||||||
|
BIN
src/font/res/JuliaMono-Regular.ttf
Normal file
BIN
src/font/res/JuliaMono-Regular.ttf
Normal file
Binary file not shown.
@ -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.
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user