font: GroupCacheSet.Key has metric modifiers

This commit is contained in:
Mitchell Hashimoto
2024-04-01 12:49:32 -07:00
parent 9d8da8fcc7
commit 2a386daa19
3 changed files with 47 additions and 19 deletions

View File

@ -338,25 +338,8 @@ pub fn init(
font_group.* = try font.GroupCache.init(alloc, group: { font_group.* = try font.GroupCache.init(alloc, group: {
var group = try font.Group.init(alloc, font_lib, font_size); var group = try font.Group.init(alloc, font_lib, font_size);
errdefer group.deinit(); errdefer group.deinit();
group.metric_modifiers = font_group_key.metric_modifiers;
// Setup our font metric modifiers if we have any. group.codepoint_map = font_group_key.codepoint_map;
group.metric_modifiers = set: {
var set: font.face.Metrics.ModifierSet = .{};
errdefer set.deinit(alloc);
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);
if (config.@"adjust-underline-position") |m| try set.put(alloc, .underline_position, m);
if (config.@"adjust-underline-thickness") |m| try set.put(alloc, .underline_thickness, m);
if (config.@"adjust-strikethrough-position") |m| try set.put(alloc, .strikethrough_position, m);
if (config.@"adjust-strikethrough-thickness") |m| try set.put(alloc, .strikethrough_thickness, m);
break :set set;
};
// If we have codepoint mappings, set those.
if (font_group_key.codepoint_map.list.len > 0) {
group.codepoint_map = font_group_key.codepoint_map;
}
// Set our styles // Set our styles
group.styles.set(.bold, config.@"font-style-bold" != .false); group.styles.set(.bold, config.@"font-style-bold" != .false);

View File

@ -19,6 +19,7 @@ const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const fontpkg = @import("main.zig"); const fontpkg = @import("main.zig");
const Style = fontpkg.Style; const Style = fontpkg.Style;
const Metrics = fontpkg.face.Metrics;
const CodepointMap = fontpkg.CodepointMap; const CodepointMap = fontpkg.CodepointMap;
const discovery = @import("discovery.zig"); const discovery = @import("discovery.zig");
const configpkg = @import("../config.zig"); const configpkg = @import("../config.zig");
@ -43,6 +44,9 @@ pub const Key = struct {
/// The codepoint map configuration. /// The codepoint map configuration.
codepoint_map: CodepointMap, codepoint_map: CodepointMap,
/// The metric modifier set configuration.
metric_modifiers: Metrics.ModifierSet,
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;
@ -122,6 +126,19 @@ pub const Key = struct {
break :map clone.map; break :map clone.map;
}; };
// Metric modifiers
const metric_modifiers: Metrics.ModifierSet = set: {
var set: Metrics.ModifierSet = .{};
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);
if (config.@"adjust-underline-position") |m| try set.put(alloc, .underline_position, m);
if (config.@"adjust-underline-thickness") |m| try set.put(alloc, .underline_thickness, m);
if (config.@"adjust-strikethrough-position") |m| try set.put(alloc, .strikethrough_position, m);
if (config.@"adjust-strikethrough-thickness") |m| try set.put(alloc, .strikethrough_thickness, m);
break :set set;
};
return .{ return .{
.arena = arena, .arena = arena,
.descriptors = try descriptors.toOwnedSlice(), .descriptors = try descriptors.toOwnedSlice(),
@ -132,6 +149,7 @@ pub const Key = struct {
config.@"font-family-bold-italic".list.items.len, config.@"font-family-bold-italic".list.items.len,
}, },
.codepoint_map = codepoint_map, .codepoint_map = codepoint_map,
.metric_modifiers = metric_modifiers,
}; };
} }
@ -157,6 +175,16 @@ pub const Key = struct {
autoHash(hasher, self.descriptors.len); autoHash(hasher, self.descriptors.len);
for (self.descriptors) |d| d.hash(hasher); for (self.descriptors) |d| d.hash(hasher);
autoHash(hasher, self.codepoint_map); autoHash(hasher, self.codepoint_map);
autoHash(hasher, self.metric_modifiers.count());
if (self.metric_modifiers.count() > 0) {
inline for (@typeInfo(Metrics.Key).Enum.fields) |field| {
const key = @field(Metrics.Key, field.name);
if (self.metric_modifiers.get(key)) |value| {
autoHash(hasher, key);
value.hash(hasher);
}
}
}
} }
/// Returns a hash code that can be used to uniquely identify this /// Returns a hash code that can be used to uniquely identify this
@ -176,4 +204,6 @@ test "Key" {
var k = try Key.init(alloc, &cfg); var k = try Key.init(alloc, &cfg);
defer k.deinit(); defer k.deinit();
try testing.expect(k.hashcode() > 0);
} }

View File

@ -169,6 +169,21 @@ pub const Modifier = union(enum) {
}; };
} }
/// Hash using the hasher.
pub fn hash(self: Modifier, hasher: anytype) void {
const autoHash = std.hash.autoHash;
autoHash(hasher, std.meta.activeTag(self));
switch (self) {
// floats can't be hashed directly so we round it to the
// nearest int and then hash that. This is not perfect but
// hash collisions due to the modifier being wrong are really
// rare so we should fix this up later.
// TODO(fontmem): make better
.percent => |v| autoHash(hasher, @as(i64, @intFromFloat(v))),
.absolute => |v| autoHash(hasher, v),
}
}
test "formatConfig percent" { test "formatConfig percent" {
const configpkg = @import("../../config.zig"); const configpkg = @import("../../config.zig");
const testing = std.testing; const testing = std.testing;