summaryrefslogtreecommitdiff
path: root/src/font
diff options
context:
space:
mode:
authorMitchell Hashimoto <m@mitchellh.com>2024-08-23 10:28:58 -0700
committerMitchell Hashimoto <m@mitchellh.com>2024-08-23 14:31:29 -0700
commitc183e71a92bf80ca19da02186486b4cc2dcb68c2 (patch)
tree7bdba8c2f1b2cb9485577736c0c64a12e12196f5 /src/font
parente49c4707a1e40094d181af78c1e42cd4a2365366 (diff)
font: support aliased entries in the font collection style table
Diffstat (limited to 'src/font')
-rw-r--r--src/font/Collection.zig57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/font/Collection.zig b/src/font/Collection.zig
index 86231b839..08d5c81c3 100644
--- a/src/font/Collection.zig
+++ b/src/font/Collection.zig
@@ -16,6 +16,7 @@
const Collection = @This();
const std = @import("std");
+const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const font = @import("main.zig");
const options = font.options;
@@ -104,7 +105,21 @@ pub fn add(
pub fn getFace(self: *Collection, index: Index) !*Face {
if (index.special() != null) return error.SpecialHasNoFace;
const list = self.faces.getPtr(index.style);
- const item = &list.items[index.idx];
+ const item: *Entry = item: {
+ var item = &list.items[index.idx];
+ switch (item.*) {
+ .alias => |ptr| item = ptr,
+
+ .deferred,
+ .fallback_deferred,
+ .loaded,
+ .fallback_loaded,
+ => {},
+ }
+ assert(item.* != .alias);
+ break :item item;
+ };
+
return switch (item.*) {
inline .deferred, .fallback_deferred => |*d, tag| deferred: {
const opts = self.load_options orelse
@@ -125,6 +140,10 @@ pub fn getFace(self: *Collection, index: Index) !*Face {
},
.loaded, .fallback_loaded => |*f| f,
+
+ // When setting `item` above, we ensure we don't end up with
+ // an alias.
+ .alias => unreachable,
};
}
@@ -168,6 +187,23 @@ pub fn hasCodepoint(
return list.items[index.idx].hasCodepoint(cp, p_mode);
}
+/// Ensure we have an option for all styles in the collection, such
+/// as italic and bold.
+///
+/// This requires that a regular font face is already loaded.
+/// This is asserted. If a font style is missing, we will synthesize
+/// it if possible. Otherwise, we will use the regular font style.
+pub fn completeStyles(self: *Collection, alloc: Allocator) !void {
+ const regular_list = self.faces.getPtr(.regular);
+ assert(regular_list.items.len > 0);
+
+ // If we don't have bold, use the regular font.
+ const bold_list = self.faces.getPtr(.bold);
+ if (bold_list.items.len == 0) {}
+
+ _ = alloc;
+}
+
/// Automatically create an italicized font from the regular
/// font face if we don't have one already. If we already have
/// an italicized font face, this does nothing.
@@ -243,10 +279,16 @@ pub fn setSize(self: *Collection, size: DesiredSize) !void {
var it = self.faces.iterator();
while (it.next()) |entry| {
for (entry.value.items) |*elem| switch (elem.*) {
- .deferred, .fallback_deferred => continue,
.loaded, .fallback_loaded => |*f| try f.setSize(
opts.faceOptions(),
),
+
+ // Deferred aren't loaded so we don't need to set their size.
+ // The size for when they're loaded is set since `opts` changed.
+ .deferred, .fallback_deferred => continue,
+
+ // Alias faces don't own their size.
+ .alias => continue,
};
}
}
@@ -318,6 +360,10 @@ pub const Entry = union(enum) {
fallback_deferred: DeferredFace,
fallback_loaded: Face,
+ // An alias to another entry. This is used to share the same face,
+ // avoid memory duplication. An alias must point to a non-alias entry.
+ alias: *Entry,
+
pub fn deinit(self: *Entry) void {
switch (self.*) {
inline .deferred,
@@ -325,6 +371,10 @@ pub const Entry = union(enum) {
.fallback_deferred,
.fallback_loaded,
=> |*v| v.deinit(),
+
+ // Aliased fonts are not owned by this entry so we let them
+ // be deallocated by the owner.
+ .alias => {},
}
}
@@ -333,6 +383,7 @@ pub const Entry = union(enum) {
return switch (self) {
.deferred, .fallback_deferred => true,
.loaded, .fallback_loaded => false,
+ .alias => |v| v.isDeferred(),
};
}
@@ -343,6 +394,8 @@ pub const Entry = union(enum) {
p_mode: PresentationMode,
) bool {
return switch (self) {
+ .alias => |v| v.hasCodepoint(cp, p_mode),
+
// Non-fallback fonts require explicit presentation matching but
// otherwise don't care about presentation
.deferred => |v| switch (p_mode) {