diff --git a/src/build/fish_completions.zig b/src/build/fish_completions.zig index 0ff0a2163..64fbea44e 100644 --- a/src/build/fish_completions.zig +++ b/src/build/fish_completions.zig @@ -12,7 +12,7 @@ pub const fish_completions = comptimeGenerateFishCompletions(); fn comptimeGenerateFishCompletions() []const u8 { comptime { - @setEvalBranchQuota(17000); + @setEvalBranchQuota(18000); var counter = std.io.countingWriter(std.io.null_writer); try writeFishCompletions(&counter.writer()); diff --git a/src/build/mdgen/mdgen.zig b/src/build/mdgen/mdgen.zig index 2e2884f1a..7e05596d7 100644 --- a/src/build/mdgen/mdgen.zig +++ b/src/build/mdgen/mdgen.zig @@ -26,7 +26,7 @@ pub fn genConfig(writer: anytype, cli: bool) !void { \\ ); - @setEvalBranchQuota(2000); + @setEvalBranchQuota(3000); inline for (@typeInfo(Config).Struct.fields) |field| { if (field.name[0] == '_') continue; diff --git a/src/config/Config.zig b/src/config/Config.zig index e6b9d35ab..908935a5d 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -287,6 +287,26 @@ const c = @cImport({ /// terminals. Only new terminals will use the new configuration. @"grapheme-width-method": GraphemeWidthMethod = .unicode, +/// Freetype load flags to enable. The format of this is a list of flags to +/// enable separated by commas. If you prefix a flag with `no-` then it is +/// disabled. If you omit a flag, it's default value is used, so you must +/// explicitely disable flags you don't want. You can also use `true` or `false` +/// to turn all flags on or off. +/// +/// Available flags: +/// +/// * `hinting` - Enable or disable hinting, enabled by default. +/// * `bitmap` - Enable or disable loading of any pre-rendered bitmap strikes, +/// enabled by default +/// * `force-autohint` - Use the freetype auto-hinter rather than the font's +/// native hinter. Enabled by default. +/// * `monochrome` - Instructs renderer to use 1-bit monochrome rendering. +/// This option doesn't impact the hinter. Enabled by default. +/// * `autohint` - Use the freetype auto-hinter. Enabled by default. +/// +/// Example: `hinting`, `no-hinting`, `force-autohint`, `no-force-autohint` +@"freetype-load-flag": FreetypeLoadFlags = .{}, + /// A theme to use. If the theme is an absolute pathname, Ghostty will attempt /// to load that file as a theme. If that file does not exist or is inaccessible, /// an error will be logged and no other directories will be searched. @@ -4565,6 +4585,15 @@ pub const GraphemeWidthMethod = enum { unicode, }; +/// See freetype-load-flag +pub const FreetypeLoadFlags = packed struct { + hinting: bool = true, + bitmap: bool = true, + @"force-autohint": bool = false, + monochrome: bool = false, + autohint: bool = true, +}; + /// See linux-cgroup pub const LinuxCgroup = enum { never, diff --git a/src/font/face.zig b/src/font/face.zig index 8bcfb8209..77fb9e45b 100644 --- a/src/font/face.zig +++ b/src/font/face.zig @@ -2,6 +2,7 @@ const std = @import("std"); const builtin = @import("builtin"); const options = @import("main.zig").options; pub const Metrics = @import("face/Metrics.zig"); +const FreetypeLoadFlags = @import("../config/Config.zig").FreetypeLoadFlags; const freetype = @import("face/freetype.zig"); const coretext = @import("face/coretext.zig"); pub const web_canvas = @import("face/web_canvas.zig"); @@ -90,6 +91,8 @@ pub const RenderOptions = struct { /// /// This only works with CoreText currently. thicken: bool = false, + + load_flags: FreetypeLoadFlags, }; test { diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 7bb9ecbab..e3ad5322b 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -318,7 +318,13 @@ pub const Face = struct { // // This must be enabled for color faces though because those are // often colored bitmaps, which we support. - .no_bitmap = !self.face.hasColor(), + .no_bitmap = !self.face.hasColor() or !opts.load_flags.bitmap, + + // use options from config + .no_hinting = !opts.load_flags.hinting, + .force_autohint = !opts.load_flags.@"force-autohint", + .monochrome = !opts.load_flags.monochrome, + .no_autohint = !opts.load_flags.autohint, }); const glyph = self.face.handle.*.glyph; diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 742dfbcd4..561168b90 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -354,6 +354,7 @@ pub const DerivedConfig = struct { font_thicken: bool, font_features: std.ArrayListUnmanaged([:0]const u8), font_styles: font.CodepointResolver.StyleStatus, + load_flags: configpkg.Config.FreetypeLoadFlags, cursor_color: ?terminal.color.RGB, cursor_invert: bool, cursor_opacity: f64, @@ -399,11 +400,14 @@ pub const DerivedConfig = struct { const cursor_invert = config.@"cursor-invert-fg-bg"; + const load_flags = config.@"freetype-load-flag"; + return .{ .background_opacity = @max(0, @min(1, config.@"background-opacity")), .font_thicken = config.@"font-thicken", .font_features = font_features, .font_styles = font_styles, + .load_flags = load_flags, .cursor_color = if (!cursor_invert and config.@"cursor-color" != null) config.@"cursor-color".?.toTerminalRGB() @@ -2719,6 +2723,7 @@ fn addUnderline( .{ .cell_width = 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ); @@ -2751,6 +2756,7 @@ fn addOverline( .{ .cell_width = 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ); @@ -2783,6 +2789,7 @@ fn addStrikethrough( .{ .cell_width = 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ); @@ -2822,6 +2829,7 @@ fn addGlyph( .{ .grid_metrics = self.grid_metrics, .thicken = self.config.font_thicken, + .load_flags = self.config.load_flags, }, ); @@ -2901,6 +2909,7 @@ fn addCursor( .{ .cell_width = if (wide) 2 else 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ) catch |err| { log.warn("error rendering cursor glyph err={}", .{err}); @@ -2916,6 +2925,7 @@ fn addCursor( .{ .cell_width = if (wide) 2 else 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ) catch |err| { log.warn("error rendering cursor glyph err={}", .{err}); @@ -2956,7 +2966,7 @@ fn addPreeditCell( @intCast(cp.codepoint), .regular, .text, - .{ .grid_metrics = self.grid_metrics }, + .{ .grid_metrics = self.grid_metrics, .load_flags = self.config.load_flags }, ) catch |err| { log.warn("error rendering preedit glyph err={}", .{err}); return; diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 5313315b1..7cb391bcc 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -11,6 +11,7 @@ const ArenaAllocator = std.heap.ArenaAllocator; const link = @import("link.zig"); const isCovering = @import("cell.zig").isCovering; const fgMode = @import("cell.zig").fgMode; +const freetype = @import("freetype").Face; const shadertoy = @import("shadertoy.zig"); const apprt = @import("../apprt.zig"); const configpkg = @import("../config.zig"); @@ -288,6 +289,7 @@ pub const DerivedConfig = struct { font_thicken: bool, font_features: std.ArrayListUnmanaged([:0]const u8), font_styles: font.CodepointResolver.StyleStatus, + load_flags: configpkg.Config.FreetypeLoadFlags, cursor_color: ?terminal.color.RGB, cursor_invert: bool, cursor_text: ?terminal.color.RGB, @@ -332,11 +334,14 @@ pub const DerivedConfig = struct { const cursor_invert = config.@"cursor-invert-fg-bg"; + const load_flags = config.@"freetype-load-flag"; + return .{ .background_opacity = @max(0, @min(1, config.@"background-opacity")), .font_thicken = config.@"font-thicken", .font_features = font_features, .font_styles = font_styles, + .load_flags = load_flags, .cursor_color = if (!cursor_invert and config.@"cursor-color" != null) config.@"cursor-color".?.toTerminalRGB() @@ -1765,7 +1770,7 @@ fn addPreeditCell( @intCast(cp.codepoint), .regular, .text, - .{ .grid_metrics = self.grid_metrics }, + .{ .grid_metrics = self.grid_metrics, .load_flags = self.config.load_flags }, ) catch |err| { log.warn("error rendering preedit glyph err={}", .{err}); return; @@ -1866,6 +1871,7 @@ fn addCursor( .{ .cell_width = if (wide) 2 else 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ) catch |err| { log.warn("error rendering cursor glyph err={}", .{err}); @@ -1881,6 +1887,7 @@ fn addCursor( .{ .cell_width = if (wide) 2 else 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ) catch |err| { log.warn("error rendering cursor glyph err={}", .{err}); @@ -1943,6 +1950,7 @@ fn addUnderline( .{ .cell_width = 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ); @@ -1984,6 +1992,7 @@ fn addOverline( .{ .cell_width = 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ); @@ -2025,6 +2034,7 @@ fn addStrikethrough( .{ .cell_width = 1, .grid_metrics = self.grid_metrics, + .load_flags = self.config.load_flags, }, ); @@ -2073,6 +2083,7 @@ fn addGlyph( .{ .grid_metrics = self.grid_metrics, .thicken = self.config.font_thicken, + .load_flags = self.config.load_flags, }, );