Skip to content

Commit

Permalink
font: add stylistic variants for built-in font, fix naming convention
Browse files Browse the repository at this point in the history
Fixes #2364

This adds the bold, italic, and bold italic variants of JB Mono so it is
built-in. This also fixes up the naming convention for the embedded font
files across tests and removes redundant embedded font files.
  • Loading branch information
mitchellh committed Oct 2, 2024
1 parent 991cbce commit 759b46a
Show file tree
Hide file tree
Showing 21 changed files with 115 additions and 89 deletions.
5 changes: 0 additions & 5 deletions src/Surface.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4338,8 +4338,3 @@ fn presentSurface(self: *Surface) !void {
{},
);
}

pub const face_ttf = @embedFile("font/res/JetBrainsMono-Regular.ttf");
pub const face_bold_ttf = @embedFile("font/res/JetBrainsMono-Bold.ttf");
pub const face_emoji_ttf = @embedFile("font/res/NotoColorEmoji.ttf");
pub const face_emoji_text_ttf = @embedFile("font/res/NotoEmoji-Regular.ttf");
8 changes: 4 additions & 4 deletions src/font/CodepointResolver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,9 @@ const DescriptorCache = std.HashMapUnmanaged(
test getIndex {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testEmoji = @import("test.zig").fontEmoji;
const testEmojiText = @import("test.zig").fontEmojiText;
const testFont = font.embedded.regular;
const testEmoji = font.embedded.emoji;
const testEmojiText = font.embedded.emoji_text;

var lib = try Library.init();
defer lib.deinit();
Expand Down Expand Up @@ -456,7 +456,7 @@ test getIndex {
test "getIndex disabled font style" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var atlas_grayscale = try font.Atlas.init(alloc, 512, .grayscale);
defer atlas_grayscale.deinit(alloc);
Expand Down
24 changes: 12 additions & 12 deletions src/font/Collection.zig
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,11 @@ pub const CompleteError = Allocator.Error || error{
};

/// Ensure we have an option for all styles in the collection, such
/// as italic and bold.
/// as italic and bold by synthesizing them if necessary from the
/// first regular face that has text glyphs.
///
/// This requires that a regular font face is already loaded.
/// This is asserted. If a font style is missing, we will synthesize
/// it if possible. Otherwise, we will use the regular font style.
/// If there is no regular face that has text glyphs, then this
/// does nothing.
pub fn completeStyles(
self: *Collection,
alloc: Allocator,
Expand All @@ -229,7 +229,7 @@ pub fn completeStyles(
// if a user configures something like an Emoji font first.
const regular_entry: *Entry = entry: {
const list = self.faces.getPtr(.regular);
assert(list.count() > 0);
if (list.count() == 0) return;

// Find our first regular face that has text glyphs.
var it = list.iterator(0);
Expand Down Expand Up @@ -663,7 +663,7 @@ test init {
test "add full" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var lib = try Library.init();
defer lib.deinit();
Expand Down Expand Up @@ -709,7 +709,7 @@ test "add deferred without loading options" {
test getFace {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var lib = try Library.init();
defer lib.deinit();
Expand All @@ -733,7 +733,7 @@ test getFace {
test getIndex {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var lib = try Library.init();
defer lib.deinit();
Expand Down Expand Up @@ -764,7 +764,7 @@ test getIndex {
test completeStyles {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var lib = try Library.init();
defer lib.deinit();
Expand All @@ -791,7 +791,7 @@ test completeStyles {
test setSize {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var lib = try Library.init();
defer lib.deinit();
Expand All @@ -814,7 +814,7 @@ test setSize {
test hasCodepoint {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var lib = try Library.init();
defer lib.deinit();
Expand All @@ -838,7 +838,7 @@ test "hasCodepoint emoji default graphical" {

const testing = std.testing;
const alloc = testing.allocator;
const testEmoji = @import("test.zig").fontEmoji;
const testEmoji = font.embedded.emoji;

var lib = try Library.init();
defer lib.deinit();
Expand Down
2 changes: 1 addition & 1 deletion src/font/SharedGrid.zig
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ const GlyphKey = struct {
const TestMode = enum { normal };

fn testGrid(mode: TestMode, alloc: Allocator, lib: Library) !SharedGrid {
const testFont = @import("test.zig").fontRegular;
const testFont = font.embedded.regular;

var c = Collection.init();
c.load_options = .{ .library = lib };
Expand Down
48 changes: 36 additions & 12 deletions src/font/SharedGridSet.zig
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,46 @@ fn collection(
}
}

// Complete our styles to ensure we have something to satisfy every
// possible style request. We do this before adding our built-in font
// because we want to ensure our built-in styles are fallbacks to
// the configured styles.
try c.completeStyles(self.alloc, config.@"font-synthetic-style");

// Our built-in font will be used as a backup
_ = try c.add(
self.alloc,
.regular,
.{ .fallback_loaded = try Face.init(
self.font_lib,
face_ttf,
font.embedded.regular,
load_options.faceOptions(),
) },
);
_ = try c.add(
self.alloc,
.bold,
.{ .fallback_loaded = try Face.init(
self.font_lib,
font.embedded.bold,
load_options.faceOptions(),
) },
);
_ = try c.add(
self.alloc,
.italic,
.{ .fallback_loaded = try Face.init(
self.font_lib,
font.embedded.italic,
load_options.faceOptions(),
) },
);
_ = try c.add(
self.alloc,
.bold_italic,
.{ .fallback_loaded = try Face.init(
self.font_lib,
font.embedded.bold_italic,
load_options.faceOptions(),
) },
);
Expand Down Expand Up @@ -284,7 +317,7 @@ fn collection(
.regular,
.{ .fallback_loaded = try Face.init(
self.font_lib,
face_emoji_ttf,
font.embedded.emoji,
load_options.faceOptions(),
) },
);
Expand All @@ -293,16 +326,12 @@ fn collection(
.regular,
.{ .fallback_loaded = try Face.init(
self.font_lib,
face_emoji_text_ttf,
font.embedded.emoji_text,
load_options.faceOptions(),
) },
);
}

// Complete our styles to ensure we have something to satisfy every
// possible style request.
try c.completeStyles(self.alloc, config.@"font-synthetic-style");

return c;
}

Expand Down Expand Up @@ -633,11 +662,6 @@ pub const Key = struct {
}
};

const face_ttf = @embedFile("res/JetBrainsMono-Regular.ttf");
const face_bold_ttf = @embedFile("res/JetBrainsMono-Bold.ttf");
const face_emoji_ttf = @embedFile("res/NotoColorEmoji.ttf");
const face_emoji_text_ttf = @embedFile("res/NotoEmoji-Regular.ttf");

test "Key" {
const testing = std.testing;
const alloc = testing.allocator;
Expand Down
35 changes: 35 additions & 0 deletions src/font/embedded.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! Fonts that can be embedded with Ghostty. Note they are only actually
//! embedded in the binary if they are referenced by the code, so fonts
//! used for tests will not result in the final binary being larger.
//!
//! Be careful to ensure that any fonts you embed are licensed for
//! redistribution and include their license as necessary.

/// Default fonts that we prefer for Ghostty.
pub const regular = @embedFile("res/JetBrainsMonoNerdFont-Regular.ttf");
pub const bold = @embedFile("res/JetBrainsMonoNerdFont-Bold.ttf");
pub const italic = @embedFile("res/JetBrainsMonoNerdFont-Italic.ttf");
pub const bold_italic = @embedFile("res/JetBrainsMonoNerdFont-BoldItalic.ttf");
pub const emoji = @embedFile("res/NotoColorEmoji.ttf");
pub const emoji_text = @embedFile("res/NotoEmoji-Regular.ttf");

/// Fonts with general properties
pub const variable = @embedFile("res/Lilex-VF.ttf");

/// Font with nerd fonts embedded.
pub const nerd_font = @embedFile("res/JetBrainsMonoNerdFont-Regular.ttf");

/// Specific font families below:
pub const code_new_roman = @embedFile("res/CodeNewRoman-Regular.otf");
pub const inconsolata = @embedFile("res/Inconsolata-Regular.ttf");
pub const geist_mono = @embedFile("res/GeistMono-Regular.ttf");
pub const jetbrains_mono = @embedFile("res/JetBrainsMonoNoNF-Regular.ttf");
pub const julia_mono = @embedFile("res/JuliaMono-Regular.ttf");

/// Cozette is a unique font because it embeds some emoji characters
/// but has a text presentation.
pub const cozette = @embedFile("res/CozetteVector.ttf");

/// Monaspace has weird ligature behaviors we want to test in our shapers
/// so we embed it here.
pub const monaspace_neon = @embedFile("res/MonaspaceNeon-Regular.otf");
10 changes: 5 additions & 5 deletions src/font/face/coretext.zig
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ test "emoji" {
test "in-memory" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontRegular;
const testFont = font.embedded.regular;

var atlas = try font.Atlas.init(alloc, 512, .grayscale);
defer atlas.deinit(alloc);
Expand All @@ -820,7 +820,7 @@ test "in-memory" {
test "variable" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontVariable;
const testFont = font.embedded.variable;

var atlas = try font.Atlas.init(alloc, 512, .grayscale);
defer atlas.deinit(alloc);
Expand All @@ -842,7 +842,7 @@ test "variable" {
test "variable set variation" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontVariable;
const testFont = font.embedded.variable;

var atlas = try font.Atlas.init(alloc, 512, .grayscale);
defer atlas.deinit(alloc);
Expand All @@ -868,7 +868,7 @@ test "variable set variation" {
test "svg font table" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontJuliaMono;
const testFont = font.embedded.julia_mono;

var lib = try font.Library.init();
defer lib.deinit();
Expand All @@ -884,7 +884,7 @@ test "svg font table" {

test "glyphIndex colored vs text" {
const testing = std.testing;
const testFont = @import("../test.zig").fontJuliaMono;
const testFont = font.embedded.julia_mono;

var lib = try font.Library.init();
defer lib.deinit();
Expand Down
10 changes: 5 additions & 5 deletions src/font/face/freetype.zig
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ pub const Face = struct {
};

test {
const testFont = @import("../test.zig").fontRegular;
const testFont = font.embedded.regular;
const alloc = testing.allocator;

var lib = try Library.init();
Expand Down Expand Up @@ -777,7 +777,7 @@ test {

test "color emoji" {
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontEmoji;
const testFont = font.embedded.emoji;

var lib = try Library.init();
defer lib.deinit();
Expand Down Expand Up @@ -819,7 +819,7 @@ test "color emoji" {
}

test "metrics" {
const testFont = @import("../test.zig").fontRegular;
const testFont = font.embedded.regular;
const alloc = testing.allocator;

var lib = try Library.init();
Expand Down Expand Up @@ -860,7 +860,7 @@ test "metrics" {

test "mono to rgba" {
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontEmoji;
const testFont = font.embedded.emoji;

var lib = try Library.init();
defer lib.deinit();
Expand All @@ -877,7 +877,7 @@ test "mono to rgba" {

test "svg font table" {
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontJuliaMono;
const testFont = font.embedded.julia_mono;

var lib = try font.Library.init();
defer lib.deinit();
Expand Down
1 change: 1 addition & 0 deletions src/font/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const library = @import("library.zig");

pub const Atlas = @import("Atlas.zig");
pub const discovery = @import("discovery.zig");
pub const embedded = @import("embedded.zig");
pub const face = @import("face.zig");
pub const CodepointMap = @import("CodepointMap.zig");
pub const CodepointResolver = @import("CodepointResolver.zig");
Expand Down
2 changes: 1 addition & 1 deletion src/font/opentype/svg.zig
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub const SVG = struct {
test "SVG" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("../test.zig").fontJuliaMono;
const testFont = font.embedded.julia_mono;

var lib = try font.Library.init();
defer lib.deinit();
Expand Down
Binary file removed src/font/res/Inconsolata-Bold.ttf
Binary file not shown.
Binary file modified src/font/res/Inconsolata-Regular.ttf
Binary file not shown.
Binary file removed src/font/res/Inconsolata.ttf
Binary file not shown.
Binary file not shown.
Binary file added src/font/res/JetBrainsMonoNerdFont-BoldItalic.ttf
Binary file not shown.
Binary file not shown.
Binary file modified src/font/res/JetBrainsMonoNerdFont-Regular.ttf
Binary file not shown.
16 changes: 8 additions & 8 deletions src/font/shaper/coretext.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1732,15 +1732,15 @@ fn testShaper(alloc: Allocator) !TestShaper {
}

fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper {
const testEmoji = @import("../test.zig").fontEmoji;
const testEmojiText = @import("../test.zig").fontEmojiText;
const testEmoji = font.embedded.emoji;
const testEmojiText = font.embedded.emoji_text;
const testFont = switch (font_req) {
.code_new_roman => @import("../test.zig").fontCodeNewRoman,
.inconsolata => @import("../test.zig").fontRegular,
.geist_mono => @import("../test.zig").fontGeistMono,
.jetbrains_mono => @import("../test.zig").fontJetBrainsMono,
.monaspace_neon => @import("../test.zig").fontMonaspaceNeon,
.nerd_font => @import("../test.zig").fontNerdFont,
.code_new_roman => font.embedded.code_new_roman,
.inconsolata => font.embedded.inconsolata,
.geist_mono => font.embedded.geist_mono,
.jetbrains_mono => font.embedded.jetbrains_mono,
.monaspace_neon => font.embedded.monaspace_neon,
.nerd_font => font.embedded.nerd_font,
};

var lib = try Library.init();
Expand Down
8 changes: 4 additions & 4 deletions src/font/shaper/harfbuzz.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1197,11 +1197,11 @@ fn testShaper(alloc: Allocator) !TestShaper {
}

fn testShaperWithFont(alloc: Allocator, font_req: TestFont) !TestShaper {
const testEmoji = @import("../test.zig").fontEmoji;
const testEmojiText = @import("../test.zig").fontEmojiText;
const testEmoji = font.embedded.fontEmoji;
const testEmojiText = font.embedded.fontEmojiText;
const testFont = switch (font_req) {
.inconsolata => @import("../test.zig").fontRegular,
.monaspace_neon => @import("../test.zig").fontMonaspaceNeon,
.inconsolata => font.embedded.fontRegular,
.monaspace_neon => font.embedded.fontMonaspaceNeon,
};

var lib = try Library.init();
Expand Down
Loading

0 comments on commit 759b46a

Please sign in to comment.