mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 08:16:13 +03:00
font: wire up all the metric modifiers
This commit is contained in:
@ -228,7 +228,10 @@ pub fn init(
|
|||||||
group.metric_modifiers = set: {
|
group.metric_modifiers = set: {
|
||||||
var set: font.face.Metrics.ModifierSet = .{};
|
var set: font.face.Metrics.ModifierSet = .{};
|
||||||
errdefer set.deinit(alloc);
|
errdefer set.deinit(alloc);
|
||||||
break :set null;
|
if (config.@"adjust-cell-width") |m| try set.put(alloc, .cell_width, m);
|
||||||
|
if (config.@"adjust-cell-height") |m| try set.put(alloc, .cell_height, m);
|
||||||
|
if (config.@"adjust-font-baseline") |m| try set.put(alloc, .cell_baseline, m);
|
||||||
|
break :set set;
|
||||||
};
|
};
|
||||||
|
|
||||||
// If we have codepoint mappings, set those.
|
// If we have codepoint mappings, set those.
|
||||||
|
@ -154,13 +154,13 @@ pub fn name(self: DeferredFace, buf: []u8) ![]const u8 {
|
|||||||
pub fn load(
|
pub fn load(
|
||||||
self: *DeferredFace,
|
self: *DeferredFace,
|
||||||
lib: Library,
|
lib: Library,
|
||||||
size: font.face.DesiredSize,
|
opts: font.face.Options,
|
||||||
) !Face {
|
) !Face {
|
||||||
return switch (options.backend) {
|
return switch (options.backend) {
|
||||||
.fontconfig_freetype => try self.loadFontconfig(lib, size),
|
.fontconfig_freetype => try self.loadFontconfig(lib, opts),
|
||||||
.coretext => try self.loadCoreText(lib, size),
|
.coretext => try self.loadCoreText(lib, opts),
|
||||||
.coretext_freetype => try self.loadCoreTextFreetype(lib, size),
|
.coretext_freetype => try self.loadCoreTextFreetype(lib, opts),
|
||||||
.web_canvas => try self.loadWebCanvas(size),
|
.web_canvas => try self.loadWebCanvas(opts),
|
||||||
|
|
||||||
// Unreachable because we must be already loaded or have the
|
// Unreachable because we must be already loaded or have the
|
||||||
// proper configuration for one of the other deferred mechanisms.
|
// proper configuration for one of the other deferred mechanisms.
|
||||||
@ -171,7 +171,7 @@ pub fn load(
|
|||||||
fn loadFontconfig(
|
fn loadFontconfig(
|
||||||
self: *DeferredFace,
|
self: *DeferredFace,
|
||||||
lib: Library,
|
lib: Library,
|
||||||
size: font.face.DesiredSize,
|
opts: font.face.Options,
|
||||||
) !Face {
|
) !Face {
|
||||||
const fc = self.fc.?;
|
const fc = self.fc.?;
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ fn loadFontconfig(
|
|||||||
const filename = (try fc.pattern.get(.file, 0)).string;
|
const filename = (try fc.pattern.get(.file, 0)).string;
|
||||||
const face_index = (try fc.pattern.get(.index, 0)).integer;
|
const face_index = (try fc.pattern.get(.index, 0)).integer;
|
||||||
|
|
||||||
var face = try Face.initFile(lib, filename, face_index, size);
|
var face = try Face.initFile(lib, filename, face_index, opts);
|
||||||
errdefer face.deinit();
|
errdefer face.deinit();
|
||||||
try face.setVariations(fc.variations);
|
try face.setVariations(fc.variations);
|
||||||
return face;
|
return face;
|
||||||
@ -188,18 +188,17 @@ fn loadFontconfig(
|
|||||||
fn loadCoreText(
|
fn loadCoreText(
|
||||||
self: *DeferredFace,
|
self: *DeferredFace,
|
||||||
lib: Library,
|
lib: Library,
|
||||||
size: font.face.DesiredSize,
|
opts: font.face.Options,
|
||||||
) !Face {
|
) !Face {
|
||||||
_ = lib;
|
_ = lib;
|
||||||
const ct = self.ct.?;
|
const ct = self.ct.?;
|
||||||
// TODO: make options
|
return try Face.initFontCopy(ct.font, opts);
|
||||||
return try Face.initFontCopy(ct.font, .{ .size = size });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadCoreTextFreetype(
|
fn loadCoreTextFreetype(
|
||||||
self: *DeferredFace,
|
self: *DeferredFace,
|
||||||
lib: Library,
|
lib: Library,
|
||||||
size: font.face.DesiredSize,
|
opts: font.face.Options,
|
||||||
) !Face {
|
) !Face {
|
||||||
const ct = self.ct.?;
|
const ct = self.ct.?;
|
||||||
|
|
||||||
@ -232,15 +231,15 @@ fn loadCoreTextFreetype(
|
|||||||
// TODO: face index 0 is not correct long term and we should switch
|
// TODO: face index 0 is not correct long term and we should switch
|
||||||
// to using CoreText for rendering, too.
|
// to using CoreText for rendering, too.
|
||||||
//std.log.warn("path={s}", .{path_slice});
|
//std.log.warn("path={s}", .{path_slice});
|
||||||
return try Face.initFile(lib, buf[0..path_slice.len :0], 0, size);
|
return try Face.initFile(lib, buf[0..path_slice.len :0], 0, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadWebCanvas(
|
fn loadWebCanvas(
|
||||||
self: *DeferredFace,
|
self: *DeferredFace,
|
||||||
size: font.face.DesiredSize,
|
opts: font.face.Options,
|
||||||
) !Face {
|
) !Face {
|
||||||
const wc = self.wc.?;
|
const wc = self.wc.?;
|
||||||
return try Face.initNamed(wc.alloc, wc.font_str, size, wc.presentation);
|
return try Face.initNamed(wc.alloc, wc.font_str, opts, wc.presentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this face can satisfy the given codepoint and
|
/// Returns true if this face can satisfy the given codepoint and
|
||||||
|
@ -200,7 +200,7 @@ pub fn italicize(self: *Group) !void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Try to italicize it.
|
// Try to italicize it.
|
||||||
const face = try regular.italicize();
|
const face = try regular.italicize(self.faceOptions());
|
||||||
try italic_list.append(self.alloc, .{ .loaded = face });
|
try italic_list.append(self.alloc, .{ .loaded = face });
|
||||||
|
|
||||||
var buf: [128]u8 = undefined;
|
var buf: [128]u8 = undefined;
|
||||||
@ -215,17 +215,17 @@ pub fn setSize(self: *Group, size: font.face.DesiredSize) !void {
|
|||||||
// currently handle it in any meaningful way if one face can resize
|
// currently handle it in any meaningful way if one face can resize
|
||||||
// but another can't.
|
// but another can't.
|
||||||
|
|
||||||
|
// Set our size for future loads
|
||||||
|
self.size = size;
|
||||||
|
|
||||||
// Resize all our faces that are loaded
|
// Resize all our faces that are loaded
|
||||||
var it = self.faces.iterator();
|
var it = self.faces.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
for (entry.value.items) |*elem| switch (elem.*) {
|
for (entry.value.items) |*elem| switch (elem.*) {
|
||||||
.deferred => continue,
|
.deferred => continue,
|
||||||
.loaded => |*f| try f.setSize(.{ .size = size }),
|
.loaded => |*f| try f.setSize(self.faceOptions()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set our size for future loads
|
|
||||||
self.size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This represents a specific font in the group.
|
/// This represents a specific font in the group.
|
||||||
@ -471,7 +471,7 @@ pub fn faceFromIndex(self: *Group, index: FontIndex) !*Face {
|
|||||||
const item = &list.items[index.idx];
|
const item = &list.items[index.idx];
|
||||||
return switch (item.*) {
|
return switch (item.*) {
|
||||||
.deferred => |*d| deferred: {
|
.deferred => |*d| deferred: {
|
||||||
const face = try d.load(self.lib, self.size);
|
const face = try d.load(self.lib, self.faceOptions());
|
||||||
d.deinit();
|
d.deinit();
|
||||||
item.* = .{ .loaded = face };
|
item.* = .{ .loaded = face };
|
||||||
break :deferred &item.loaded;
|
break :deferred &item.loaded;
|
||||||
|
@ -69,22 +69,27 @@ pub const Face = struct {
|
|||||||
);
|
);
|
||||||
errdefer ct_font.release();
|
errdefer ct_font.release();
|
||||||
|
|
||||||
return try initFont(ct_font);
|
return try initFont(ct_font, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize a face with a CTFont. This will take ownership over
|
/// Initialize a face with a CTFont. This will take ownership over
|
||||||
/// the CTFont. This does NOT copy or retain the CTFont.
|
/// the CTFont. This does NOT copy or retain the CTFont.
|
||||||
pub fn initFont(ct_font: *macos.text.Font) !Face {
|
pub fn initFont(ct_font: *macos.text.Font, opts: font.face.Options) !Face {
|
||||||
var hb_font = try harfbuzz.coretext.createFont(ct_font);
|
var hb_font = try harfbuzz.coretext.createFont(ct_font);
|
||||||
errdefer hb_font.destroy();
|
errdefer hb_font.destroy();
|
||||||
|
|
||||||
const traits = ct_font.getSymbolicTraits();
|
const traits = ct_font.getSymbolicTraits();
|
||||||
|
const metrics = metrics: {
|
||||||
|
var metrics = try calcMetrics(ct_font);
|
||||||
|
if (opts.metric_modifiers) |v| metrics.apply(v.*);
|
||||||
|
break :metrics metrics;
|
||||||
|
};
|
||||||
|
|
||||||
var result: Face = .{
|
var result: Face = .{
|
||||||
.font = ct_font,
|
.font = ct_font,
|
||||||
.hb_font = hb_font,
|
.hb_font = hb_font,
|
||||||
.presentation = if (traits.color_glyphs) .emoji else .text,
|
.presentation = if (traits.color_glyphs) .emoji else .text,
|
||||||
.metrics = try calcMetrics(ct_font),
|
.metrics = metrics,
|
||||||
};
|
};
|
||||||
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
||||||
|
|
||||||
@ -144,10 +149,10 @@ pub const Face = struct {
|
|||||||
|
|
||||||
/// Return a new face that is the same as this but has a transformation
|
/// Return a new face that is the same as this but has a transformation
|
||||||
/// matrix applied to italicize it.
|
/// matrix applied to italicize it.
|
||||||
pub fn italicize(self: *const Face) !Face {
|
pub fn italicize(self: *const Face, opts: font.face.Options) !Face {
|
||||||
const ct_font = try self.font.copyWithAttributes(0.0, &italic_skew, null);
|
const ct_font = try self.font.copyWithAttributes(0.0, &italic_skew, null);
|
||||||
errdefer ct_font.release();
|
errdefer ct_font.release();
|
||||||
return try initFont(ct_font);
|
return try initFont(ct_font, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the font name. If allocation is required, buf will be used,
|
/// Returns the font name. If allocation is required, buf will be used,
|
||||||
|
Reference in New Issue
Block a user