mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge pull request #2626 from nfejzic/freetype-load-flags
feat: implement configurable freetype load flags
This commit is contained in:
@ -12,7 +12,7 @@ pub const fish_completions = comptimeGenerateFishCompletions();
|
|||||||
|
|
||||||
fn comptimeGenerateFishCompletions() []const u8 {
|
fn comptimeGenerateFishCompletions() []const u8 {
|
||||||
comptime {
|
comptime {
|
||||||
@setEvalBranchQuota(17000);
|
@setEvalBranchQuota(18000);
|
||||||
var counter = std.io.countingWriter(std.io.null_writer);
|
var counter = std.io.countingWriter(std.io.null_writer);
|
||||||
try writeFishCompletions(&counter.writer());
|
try writeFishCompletions(&counter.writer());
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ pub fn genConfig(writer: anytype, cli: bool) !void {
|
|||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
@setEvalBranchQuota(2000);
|
@setEvalBranchQuota(3000);
|
||||||
inline for (@typeInfo(Config).Struct.fields) |field| {
|
inline for (@typeInfo(Config).Struct.fields) |field| {
|
||||||
if (field.name[0] == '_') continue;
|
if (field.name[0] == '_') continue;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ pub const CopyOnSelect = Config.CopyOnSelect;
|
|||||||
pub const CustomShaderAnimation = Config.CustomShaderAnimation;
|
pub const CustomShaderAnimation = Config.CustomShaderAnimation;
|
||||||
pub const FontSyntheticStyle = Config.FontSyntheticStyle;
|
pub const FontSyntheticStyle = Config.FontSyntheticStyle;
|
||||||
pub const FontStyle = Config.FontStyle;
|
pub const FontStyle = Config.FontStyle;
|
||||||
|
pub const FreetypeLoadFlags = Config.FreetypeLoadFlags;
|
||||||
pub const Keybinds = Config.Keybinds;
|
pub const Keybinds = Config.Keybinds;
|
||||||
pub const MouseShiftCapture = Config.MouseShiftCapture;
|
pub const MouseShiftCapture = Config.MouseShiftCapture;
|
||||||
pub const NonNativeFullscreen = Config.NonNativeFullscreen;
|
pub const NonNativeFullscreen = Config.NonNativeFullscreen;
|
||||||
|
@ -287,6 +287,29 @@ const c = @cImport({
|
|||||||
/// terminals. Only new terminals will use the new configuration.
|
/// terminals. Only new terminals will use the new configuration.
|
||||||
@"grapheme-width-method": GraphemeWidthMethod = .unicode,
|
@"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
|
||||||
|
/// explicitly disable flags you don't want. You can also use `true` or `false`
|
||||||
|
/// to turn all flags on or off.
|
||||||
|
///
|
||||||
|
/// This configuration only applies to Ghostty builds that use FreeType.
|
||||||
|
/// This is usually the case only for Linux builds. macOS uses CoreText
|
||||||
|
/// and does not have an equivalent configuration.
|
||||||
|
///
|
||||||
|
/// Available flags:
|
||||||
|
///
|
||||||
|
/// * `hinting` - Enable or disable hinting, 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-flags": FreetypeLoadFlags = .{},
|
||||||
|
|
||||||
/// A theme to use. If the theme is an absolute pathname, Ghostty will attempt
|
/// 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,
|
/// 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.
|
/// an error will be logged and no other directories will be searched.
|
||||||
@ -4565,6 +4588,17 @@ pub const GraphemeWidthMethod = enum {
|
|||||||
unicode,
|
unicode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// See freetype-load-flag
|
||||||
|
pub const FreetypeLoadFlags = packed struct {
|
||||||
|
// The defaults here at the time of writing this match the defaults
|
||||||
|
// for Freetype itself. Ghostty hasn't made any opinionated changes
|
||||||
|
// to these defaults.
|
||||||
|
hinting: bool = true,
|
||||||
|
@"force-autohint": bool = true,
|
||||||
|
monochrome: bool = true,
|
||||||
|
autohint: bool = true,
|
||||||
|
};
|
||||||
|
|
||||||
/// See linux-cgroup
|
/// See linux-cgroup
|
||||||
pub const LinuxCgroup = enum {
|
pub const LinuxCgroup = enum {
|
||||||
never,
|
never,
|
||||||
|
@ -452,6 +452,12 @@ pub const LoadOptions = struct {
|
|||||||
/// for this is owned by the user and is not freed by the collection.
|
/// for this is owned by the user and is not freed by the collection.
|
||||||
metric_modifiers: Metrics.ModifierSet = .{},
|
metric_modifiers: Metrics.ModifierSet = .{},
|
||||||
|
|
||||||
|
/// Freetype Load Flags to use when loading glyphs. This is a list of
|
||||||
|
/// bitfield constants that controls operations to perform during glyph
|
||||||
|
/// loading. Only a subset is exposed for configuration, for the whole set
|
||||||
|
/// of flags see `pkg.freetype.face.LoadFlags`.
|
||||||
|
freetype_load_flags: font.face.FreetypeLoadFlags = font.face.freetype_load_flags_default,
|
||||||
|
|
||||||
pub fn deinit(self: *LoadOptions, alloc: Allocator) void {
|
pub fn deinit(self: *LoadOptions, alloc: Allocator) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = alloc;
|
_ = alloc;
|
||||||
@ -462,6 +468,7 @@ pub const LoadOptions = struct {
|
|||||||
return .{
|
return .{
|
||||||
.size = self.size,
|
.size = self.size,
|
||||||
.metric_modifiers = &self.metric_modifiers,
|
.metric_modifiers = &self.metric_modifiers,
|
||||||
|
.freetype_load_flags = self.freetype_load_flags,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -168,6 +168,7 @@ fn collection(
|
|||||||
.library = self.font_lib,
|
.library = self.font_lib,
|
||||||
.size = size,
|
.size = size,
|
||||||
.metric_modifiers = key.metric_modifiers,
|
.metric_modifiers = key.metric_modifiers,
|
||||||
|
.freetype_load_flags = key.freetype_load_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
var c = Collection.init();
|
var c = Collection.init();
|
||||||
@ -427,6 +428,7 @@ pub const DerivedConfig = struct {
|
|||||||
@"adjust-strikethrough-position": ?Metrics.Modifier,
|
@"adjust-strikethrough-position": ?Metrics.Modifier,
|
||||||
@"adjust-strikethrough-thickness": ?Metrics.Modifier,
|
@"adjust-strikethrough-thickness": ?Metrics.Modifier,
|
||||||
@"adjust-cursor-thickness": ?Metrics.Modifier,
|
@"adjust-cursor-thickness": ?Metrics.Modifier,
|
||||||
|
@"freetype-load-flags": font.face.FreetypeLoadFlags,
|
||||||
|
|
||||||
/// Initialize a DerivedConfig. The config should be either a
|
/// Initialize a DerivedConfig. The config should be either a
|
||||||
/// config.Config or another DerivedConfig to clone from.
|
/// config.Config or another DerivedConfig to clone from.
|
||||||
@ -461,6 +463,7 @@ pub const DerivedConfig = struct {
|
|||||||
.@"adjust-strikethrough-position" = config.@"adjust-strikethrough-position",
|
.@"adjust-strikethrough-position" = config.@"adjust-strikethrough-position",
|
||||||
.@"adjust-strikethrough-thickness" = config.@"adjust-strikethrough-thickness",
|
.@"adjust-strikethrough-thickness" = config.@"adjust-strikethrough-thickness",
|
||||||
.@"adjust-cursor-thickness" = config.@"adjust-cursor-thickness",
|
.@"adjust-cursor-thickness" = config.@"adjust-cursor-thickness",
|
||||||
|
.@"freetype-load-flags" = if (font.face.FreetypeLoadFlags != void) config.@"freetype-load-flags" else {},
|
||||||
|
|
||||||
// This must be last so the arena contains all our allocations
|
// This must be last so the arena contains all our allocations
|
||||||
// from above since Zig does assignment in order.
|
// from above since Zig does assignment in order.
|
||||||
@ -500,6 +503,10 @@ pub const Key = struct {
|
|||||||
/// font grid.
|
/// font grid.
|
||||||
font_size: DesiredSize = .{ .points = 12 },
|
font_size: DesiredSize = .{ .points = 12 },
|
||||||
|
|
||||||
|
/// The freetype load flags configuration, only non-void if the
|
||||||
|
/// freetype backend is enabled.
|
||||||
|
freetype_load_flags: font.face.FreetypeLoadFlags = font.face.freetype_load_flags_default,
|
||||||
|
|
||||||
const style_offsets_len = std.enums.directEnumArrayLen(Style, 0);
|
const style_offsets_len = std.enums.directEnumArrayLen(Style, 0);
|
||||||
const StyleOffsets = [style_offsets_len]usize;
|
const StyleOffsets = [style_offsets_len]usize;
|
||||||
|
|
||||||
@ -618,6 +625,10 @@ pub const Key = struct {
|
|||||||
.codepoint_map = codepoint_map,
|
.codepoint_map = codepoint_map,
|
||||||
.metric_modifiers = metric_modifiers,
|
.metric_modifiers = metric_modifiers,
|
||||||
.font_size = font_size,
|
.font_size = font_size,
|
||||||
|
.freetype_load_flags = if (font.face.FreetypeLoadFlags != void)
|
||||||
|
config.@"freetype-load-flags"
|
||||||
|
else
|
||||||
|
font.face.freetype_load_flags_default,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,6 +658,7 @@ pub const Key = struct {
|
|||||||
for (self.descriptors) |d| d.hash(hasher);
|
for (self.descriptors) |d| d.hash(hasher);
|
||||||
self.codepoint_map.hash(hasher);
|
self.codepoint_map.hash(hasher);
|
||||||
autoHash(hasher, self.metric_modifiers.count());
|
autoHash(hasher, self.metric_modifiers.count());
|
||||||
|
autoHash(hasher, self.freetype_load_flags);
|
||||||
if (self.metric_modifiers.count() > 0) {
|
if (self.metric_modifiers.count() > 0) {
|
||||||
inline for (@typeInfo(Metrics.Key).Enum.fields) |field| {
|
inline for (@typeInfo(Metrics.Key).Enum.fields) |field| {
|
||||||
const key = @field(Metrics.Key, field.name);
|
const key = @field(Metrics.Key, field.name);
|
||||||
|
@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const options = @import("main.zig").options;
|
const options = @import("main.zig").options;
|
||||||
pub const Metrics = @import("face/Metrics.zig");
|
pub const Metrics = @import("face/Metrics.zig");
|
||||||
|
const config = @import("../config.zig");
|
||||||
const freetype = @import("face/freetype.zig");
|
const freetype = @import("face/freetype.zig");
|
||||||
const coretext = @import("face/coretext.zig");
|
const coretext = @import("face/coretext.zig");
|
||||||
pub const web_canvas = @import("face/web_canvas.zig");
|
pub const web_canvas = @import("face/web_canvas.zig");
|
||||||
@ -26,10 +27,19 @@ pub const Face = switch (options.backend) {
|
|||||||
/// using whatever platform method you can.
|
/// using whatever platform method you can.
|
||||||
pub const default_dpi = if (builtin.os.tag == .macos) 72 else 96;
|
pub const default_dpi = if (builtin.os.tag == .macos) 72 else 96;
|
||||||
|
|
||||||
|
/// These are the flags to customize how freetype loads fonts. This is
|
||||||
|
/// only non-void if the freetype backend is enabled.
|
||||||
|
pub const FreetypeLoadFlags = if (options.backend.hasFreetype())
|
||||||
|
config.FreetypeLoadFlags
|
||||||
|
else
|
||||||
|
void;
|
||||||
|
pub const freetype_load_flags_default = if (FreetypeLoadFlags != void) .{} else {};
|
||||||
|
|
||||||
/// Options for initializing a font face.
|
/// Options for initializing a font face.
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
size: DesiredSize,
|
size: DesiredSize,
|
||||||
metric_modifiers: ?*const Metrics.ModifierSet = null,
|
metric_modifiers: ?*const Metrics.ModifierSet = null,
|
||||||
|
freetype_load_flags: FreetypeLoadFlags = freetype_load_flags_default,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The desired size for loading a font.
|
/// The desired size for loading a font.
|
||||||
|
@ -18,10 +18,16 @@ const Library = font.Library;
|
|||||||
const convert = @import("freetype_convert.zig");
|
const convert = @import("freetype_convert.zig");
|
||||||
const fastmem = @import("../../fastmem.zig");
|
const fastmem = @import("../../fastmem.zig");
|
||||||
const quirks = @import("../../quirks.zig");
|
const quirks = @import("../../quirks.zig");
|
||||||
|
const config = @import("../../config.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.font_face);
|
const log = std.log.scoped(.font_face);
|
||||||
|
|
||||||
pub const Face = struct {
|
pub const Face = struct {
|
||||||
|
comptime {
|
||||||
|
// If we have the freetype backend, we should have load flags.
|
||||||
|
assert(font.face.FreetypeLoadFlags != void);
|
||||||
|
}
|
||||||
|
|
||||||
/// Our freetype library
|
/// Our freetype library
|
||||||
lib: freetype.Library,
|
lib: freetype.Library,
|
||||||
|
|
||||||
@ -34,6 +40,9 @@ pub const Face = struct {
|
|||||||
/// Metrics for this font face. These are useful for renderers.
|
/// Metrics for this font face. These are useful for renderers.
|
||||||
metrics: font.face.Metrics,
|
metrics: font.face.Metrics,
|
||||||
|
|
||||||
|
/// Freetype load flags for this font face.
|
||||||
|
load_flags: font.face.FreetypeLoadFlags,
|
||||||
|
|
||||||
/// Set quirks.disableDefaultFontFeatures
|
/// Set quirks.disableDefaultFontFeatures
|
||||||
quirks_disable_default_font_features: bool = false,
|
quirks_disable_default_font_features: bool = false,
|
||||||
|
|
||||||
@ -77,6 +86,7 @@ pub const Face = struct {
|
|||||||
.face = face,
|
.face = face,
|
||||||
.hb_font = hb_font,
|
.hb_font = hb_font,
|
||||||
.metrics = calcMetrics(face, opts.metric_modifiers),
|
.metrics = calcMetrics(face, opts.metric_modifiers),
|
||||||
|
.load_flags = opts.freetype_load_flags,
|
||||||
};
|
};
|
||||||
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
||||||
|
|
||||||
@ -319,6 +329,12 @@ pub const Face = struct {
|
|||||||
// This must be enabled for color faces though because those are
|
// This must be enabled for color faces though because those are
|
||||||
// often colored bitmaps, which we support.
|
// often colored bitmaps, which we support.
|
||||||
.no_bitmap = !self.face.hasColor(),
|
.no_bitmap = !self.face.hasColor(),
|
||||||
|
|
||||||
|
// use options from config
|
||||||
|
.no_hinting = !self.load_flags.hinting,
|
||||||
|
.force_autohint = !self.load_flags.@"force-autohint",
|
||||||
|
.monochrome = !self.load_flags.monochrome,
|
||||||
|
.no_autohint = !self.load_flags.autohint,
|
||||||
});
|
});
|
||||||
const glyph = self.face.handle.*.glyph;
|
const glyph = self.face.handle.*.glyph;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user