font: add test for size adjustment, fix small bug in resize

Previously produced very wrong values when calling Collection.setSize,
since it was assuming that the provided face had the same point size as
the primary face, which isn't true during resize-- so instead we just
have faces keep track of their set size, this is generally useful.
This commit is contained in:
Qwerasd
2025-07-06 22:45:13 -06:00
parent d33161ad66
commit 08fd1688ff
3 changed files with 71 additions and 2 deletions

View File

@ -129,7 +129,6 @@ pub const AdjustSizeError = font.Face.GetMetricsError;
//
// This returns null if load options is null or if self.load_options is null.
//
//
// This is very much like the `font-size-adjust` CSS property in how it works.
// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust
//
@ -199,8 +198,10 @@ pub fn adjustedSize(
primary_ex / face_ex,
);
// Make a copy of our load options and multiply the size by our scale.
// Make a copy of our load options, set the size to the size of
// the provided face, and then multiply that by our scaling factor.
var opts = load_options;
opts.size = face.size;
opts.size.points *= @as(f32, @floatCast(scale));
return opts;
@ -1089,3 +1090,62 @@ test "metrics" {
.cursor_height = 34,
}, c.metrics);
}
// TODO: Also test CJK fallback sizing, we don't currently have a CJK test font.
test "adjusted sizes" {
const testing = std.testing;
const alloc = testing.allocator;
const testFont = font.embedded.inconsolata;
const fallback = font.embedded.monaspace_neon;
var lib = try Library.init(alloc);
defer lib.deinit();
var c = init();
defer c.deinit(alloc);
const size: DesiredSize = .{ .points = 12, .xdpi = 96, .ydpi = 96 };
c.load_options = .{ .library = lib, .size = size };
// Add our primary face.
_ = try c.add(alloc, .regular, .{ .loaded = try .init(
lib,
testFont,
.{ .size = size },
) });
try c.updateMetrics();
// Add the fallback face.
const fallback_idx = try c.add(alloc, .regular, .{ .loaded = try .init(
lib,
fallback,
.{ .size = size },
) });
// The ex heights should match.
{
const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
primary_metrics.ex_height.?,
fallback_metrics.ex_height.?,
// We accept anything within half a pixel.
0.5,
);
}
// Resize should keep that relationship.
try c.setSize(.{ .points = 37, .xdpi = 96, .ydpi = 96 });
{
const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
primary_metrics.ex_height.?,
fallback_metrics.ex_height.?,
// We accept anything within half a pixel.
0.5,
);
}
}

View File

@ -31,6 +31,9 @@ pub const Face = struct {
/// tables).
color: ?ColorState = null,
/// The current size this font is set to.
size: font.face.DesiredSize,
/// True if our build is using Harfbuzz. If we're not, we can avoid
/// some Harfbuzz-specific code paths.
const harfbuzz_shaper = font.options.backend.hasHarfbuzz();
@ -106,6 +109,7 @@ pub const Face = struct {
.font = ct_font,
.hb_font = hb_font,
.color = color,
.size = opts.size,
};
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);

View File

@ -59,6 +59,9 @@ pub const Face = struct {
bold: bool = false,
} = .{},
/// The current size this font is set to.
size: font.face.DesiredSize,
/// Initialize a new font face with the given source in-memory.
pub fn initFile(
lib: Library,
@ -107,6 +110,7 @@ pub const Face = struct {
.hb_font = hb_font,
.ft_mutex = ft_mutex,
.load_flags = opts.freetype_load_flags,
.size = opts.size,
};
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
@ -203,6 +207,7 @@ pub const Face = struct {
/// for clearing any glyph caches, font atlas data, etc.
pub fn setSize(self: *Face, opts: font.face.Options) !void {
try setSize_(self.face, opts.size);
self.size = opts.size;
}
fn setSize_(face: freetype.Face, size: font.face.DesiredSize) !void {