From 2a386daa19e6647914690059e44a7ebbdb378d39 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 1 Apr 2024 12:49:32 -0700 Subject: [PATCH] font: GroupCacheSet.Key has metric modifiers --- src/Surface.zig | 21 ++------------------- src/font/GroupCacheSet.zig | 30 ++++++++++++++++++++++++++++++ src/font/face/Metrics.zig | 15 +++++++++++++++ 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 36d4c00a4..2efc23fdf 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -338,25 +338,8 @@ pub fn init( font_group.* = try font.GroupCache.init(alloc, group: { var group = try font.Group.init(alloc, font_lib, font_size); errdefer group.deinit(); - - // Setup our font metric modifiers if we have any. - 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; - } + group.metric_modifiers = font_group_key.metric_modifiers; + group.codepoint_map = font_group_key.codepoint_map; // Set our styles group.styles.set(.bold, config.@"font-style-bold" != .false); diff --git a/src/font/GroupCacheSet.zig b/src/font/GroupCacheSet.zig index c1d344947..867658627 100644 --- a/src/font/GroupCacheSet.zig +++ b/src/font/GroupCacheSet.zig @@ -19,6 +19,7 @@ const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; const fontpkg = @import("main.zig"); const Style = fontpkg.Style; +const Metrics = fontpkg.face.Metrics; const CodepointMap = fontpkg.CodepointMap; const discovery = @import("discovery.zig"); const configpkg = @import("../config.zig"); @@ -43,6 +44,9 @@ pub const Key = struct { /// The codepoint map configuration. codepoint_map: CodepointMap, + /// The metric modifier set configuration. + metric_modifiers: Metrics.ModifierSet, + const style_offsets_len = std.enums.directEnumArrayLen(Style, 0); const StyleOffsets = [style_offsets_len]usize; @@ -122,6 +126,19 @@ pub const Key = struct { 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 .{ .arena = arena, .descriptors = try descriptors.toOwnedSlice(), @@ -132,6 +149,7 @@ pub const Key = struct { config.@"font-family-bold-italic".list.items.len, }, .codepoint_map = codepoint_map, + .metric_modifiers = metric_modifiers, }; } @@ -157,6 +175,16 @@ pub const Key = struct { autoHash(hasher, self.descriptors.len); for (self.descriptors) |d| d.hash(hasher); 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 @@ -176,4 +204,6 @@ test "Key" { var k = try Key.init(alloc, &cfg); defer k.deinit(); + + try testing.expect(k.hashcode() > 0); } diff --git a/src/font/face/Metrics.zig b/src/font/face/Metrics.zig index e8f318d48..621f0ddbf 100644 --- a/src/font/face/Metrics.zig +++ b/src/font/face/Metrics.zig @@ -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" { const configpkg = @import("../../config.zig"); const testing = std.testing;