font: wire up all the metric modifiers

This commit is contained in:
Mitchell Hashimoto
2023-10-04 21:42:03 -07:00
parent 54b9b45a7f
commit 2563a195a1
4 changed files with 33 additions and 26 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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,