font: Group can enable/disable styles

This commit is contained in:
Mitchell Hashimoto
2023-09-26 08:36:45 -07:00
parent 4b791f3ee1
commit 6b913bc6bb

View File

@ -33,6 +33,9 @@ const log = std.log.scoped(.font_group);
// to the user so we can change this later. // to the user so we can change this later.
const StyleArray = std.EnumArray(Style, std.ArrayListUnmanaged(GroupFace)); const StyleArray = std.EnumArray(Style, std.ArrayListUnmanaged(GroupFace));
/// Packed array of booleans to indicate if a style is enabled or not.
const StyleStatus = std.EnumArray(Style, bool);
/// Map of descriptors to faces. This is used with manual codepoint maps /// Map of descriptors to faces. This is used with manual codepoint maps
/// to ensure that we don't load the same font multiple times. /// to ensure that we don't load the same font multiple times.
/// ///
@ -72,6 +75,12 @@ size: font.face.DesiredSize,
/// Instead, use the functions available on Group. /// Instead, use the functions available on Group.
faces: StyleArray, faces: StyleArray,
/// The set of statuses and whether they're enabled or not. This defaults
/// to true. This can be changed at runtime with no ill effect. If you
/// change this at runtime and are using a GroupCache, the GroupCache
/// must be reset.
styles: StyleStatus = StyleStatus.initFill(true),
/// If discovery is available, we'll look up fonts where we can't find /// If discovery is available, we'll look up fonts where we can't find
/// the codepoint. This can be set after initialization. /// the codepoint. This can be set after initialization.
discover: ?*font.Discover = null, discover: ?*font.Discover = null,
@ -150,13 +159,6 @@ pub fn addFace(self: *Group, style: Style, face: GroupFace) !FontIndex {
return .{ .style = style, .idx = @intCast(idx) }; return .{ .style = style, .idx = @intCast(idx) };
} }
/// Returns true if we have a face for the given style, though the face may
/// not be loaded yet.
pub fn hasFaceForStyle(self: Group, style: Style) bool {
const list = self.faces.get(style);
return list.items.len > 0;
}
/// This will automatically create an italicized font from the regular /// This will automatically create an italicized font from the regular
/// font face if we don't have any italicized fonts. /// font face if we don't have any italicized fonts.
pub fn italicize(self: *Group) !void { pub fn italicize(self: *Group) !void {
@ -278,6 +280,11 @@ pub fn indexForCodepoint(
style: Style, style: Style,
p: ?Presentation, p: ?Presentation,
) ?FontIndex { ) ?FontIndex {
// If we've disabled a font style, then fall back to regular.
if (style != .regular and !self.styles.get(style)) {
return self.indexForCodepoint(cp, .regular, p);
}
// Codepoint overrides. // Codepoint overrides.
if (self.indexForCodepointOverride(cp)) |idx_| { if (self.indexForCodepointOverride(cp)) |idx_| {
if (idx_) |idx| return idx; if (idx_) |idx| return idx;
@ -669,6 +676,50 @@ test {
} }
} }
test "disabled font style" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = @import("test.zig").fontRegular;
var atlas_greyscale = try font.Atlas.init(alloc, 512, .greyscale);
defer atlas_greyscale.deinit(alloc);
var lib = try Library.init();
defer lib.deinit();
var group = try init(alloc, lib, .{ .points = 12 });
defer group.deinit();
// Disable bold
group.styles.set(.bold, false);
// Same font but we can test the style in the index
_ = try group.addFace(.regular, .{ .loaded = try Face.init(lib, testFont, .{ .points = 12 }) });
_ = try group.addFace(.bold, .{ .loaded = try Face.init(lib, testFont, .{ .points = 12 }) });
_ = try group.addFace(.italic, .{ .loaded = try Face.init(lib, testFont, .{ .points = 12 }) });
// Regular should work fine
{
const idx = group.indexForCodepoint('A', .regular, null).?;
try testing.expectEqual(Style.regular, idx.style);
try testing.expectEqual(@as(FontIndex.IndexInt, 0), idx.idx);
}
// Bold should go to regular
{
const idx = group.indexForCodepoint('A', .bold, null).?;
try testing.expectEqual(Style.regular, idx.style);
try testing.expectEqual(@as(FontIndex.IndexInt, 0), idx.idx);
}
// Italic should still work
{
const idx = group.indexForCodepoint('A', .italic, null).?;
try testing.expectEqual(Style.italic, idx.style);
try testing.expectEqual(@as(FontIndex.IndexInt, 0), idx.idx);
}
}
test "face count limit" { test "face count limit" {
const testing = std.testing; const testing = std.testing;
const alloc = testing.allocator; const alloc = testing.allocator;