font: Group will use the codepoint map for codepoint overrides

This commit is contained in:
Mitchell Hashimoto
2023-09-24 19:44:06 -07:00
parent 5c1c090f39
commit abd3e16ebd

View File

@ -43,7 +43,7 @@ const StyleArray = std.EnumArray(Style, std.ArrayListUnmanaged(GroupFace));
/// font is a rare case. /// font is a rare case.
const DescriptorCache = std.HashMapUnmanaged( const DescriptorCache = std.HashMapUnmanaged(
font.discovery.Descriptor, font.discovery.Descriptor,
FontIndex, ?FontIndex,
struct { struct {
const KeyType = font.discovery.Descriptor; const KeyType = font.discovery.Descriptor;
@ -278,6 +278,13 @@ pub fn indexForCodepoint(
style: Style, style: Style,
p: ?Presentation, p: ?Presentation,
) ?FontIndex { ) ?FontIndex {
// Codepoint overrides.
if (self.indexForCodepointOverride(cp)) |idx_| {
if (idx_) |idx| return idx;
} else |err| {
log.warn("codepoint override failed codepoint={} err={}", .{ cp, err });
}
// If we have sprite drawing enabled, check if our sprite face can // If we have sprite drawing enabled, check if our sprite face can
// handle this. // handle this.
if (self.sprite) |sprite| { if (self.sprite) |sprite| {
@ -353,6 +360,51 @@ fn indexForCodepointExact(self: Group, cp: u32, style: Style, p: ?Presentation)
return null; return null;
} }
/// Checks if the codepoint is in the map of codepoint overrides,
/// finds the override font, and returns it.
fn indexForCodepointOverride(self: *Group, cp: u32) !?FontIndex {
if (comptime font.Discover == void) return null;
const map = self.codepoint_map orelse return null;
// If we have a codepoint too large or isn't in the map, then we
// don't have an override.
const cp_u21 = std.math.cast(u21, cp) orelse return null;
const desc = map.get(cp_u21) orelse return null;
// Fast path: the descriptor is already loaded.
const idx_: ?FontIndex = self.descriptor_cache.get(desc) orelse idx: {
// Slow path: we have to find this descriptor and load the font
const discover = self.discover orelse return null;
var disco_it = try discover.discover(desc);
defer disco_it.deinit();
const face = (try disco_it.next()) orelse {
log.warn(
"font lookup for codepoint map failed codepoint={} err=FontNotFound",
.{cp},
);
// Add null to the cache so we don't do a lookup again later.
try self.descriptor_cache.put(self.alloc, desc, null);
return null;
};
// Add the font to our list of fonts so we can get an index for it,
// and ensure the index is stored in the descriptor cache for next time.
const idx = try self.addFace(.regular, .{ .deferred = face });
try self.descriptor_cache.put(self.alloc, desc, idx);
break :idx idx;
};
// The descriptor cache will populate null if the descriptor is not found
// to avoid expensive discoveries later.
const idx = idx_ orelse return null;
// We need to verify that this index has the codepoint we want.
return if (self.hasCodepoint(idx, cp, null)) idx else null;
}
/// Check if a specific font index has a specific codepoint. This does not /// Check if a specific font index has a specific codepoint. This does not
/// necessarily force the font to load. /// necessarily force the font to load.
pub fn hasCodepoint(self: *Group, index: FontIndex, cp: u32, p: ?Presentation) bool { pub fn hasCodepoint(self: *Group, index: FontIndex, cp: u32, p: ?Presentation) bool {