summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/font/Collection.zig23
-rw-r--r--src/font/face/coretext.zig184
-rw-r--r--src/font/face/freetype.zig188
3 files changed, 218 insertions, 177 deletions
diff --git a/src/font/Collection.zig b/src/font/Collection.zig
index 2b5f591a5..ad9590d70 100644
--- a/src/font/Collection.zig
+++ b/src/font/Collection.zig
@@ -92,7 +92,6 @@ pub const AddOptions = struct {
pub const AddError =
Allocator.Error ||
- Face.GetMetricsError ||
error{
/// There's no more room in the collection.
CollectionFull,
@@ -127,7 +126,7 @@ pub fn add(
// Scale factor to adjust the size of the added face.
const scale_factor = self.scaleFactor(
- try owned_face.getMetrics(),
+ owned_face.getMetrics(),
opts.size_adjustment,
);
@@ -225,7 +224,7 @@ fn getFaceFromEntry(
// entry now that we have a loaded face.
entry.scale_factor = .{
.scale = self.scaleFactor(
- try face.getMetrics(),
+ face.getMetrics(),
entry.scale_factor.adjustment,
),
};
@@ -592,7 +591,7 @@ fn scaleFactor(
@branchHint(.unlikely);
// If we can't load the primary face, just use 1.0 as the scale factor.
const primary_face = self.getFace(.{ .idx = 0 }) catch return 1.0;
- self.primary_face_metrics = primary_face.getMetrics() catch return 1.0;
+ self.primary_face_metrics = primary_face.getMetrics();
}
const primary_metrics = self.primary_face_metrics.?;
@@ -652,7 +651,7 @@ fn scaleFactor(
return primary_metric / face_metric;
}
-const UpdateMetricsError = font.Face.GetMetricsError || error{
+const UpdateMetricsError = error{
CannotLoadPrimaryFont,
};
@@ -663,7 +662,7 @@ const UpdateMetricsError = font.Face.GetMetricsError || error{
pub fn updateMetrics(self: *Collection) UpdateMetricsError!void {
const primary_face = self.getFace(.{ .idx = 0 }) catch return error.CannotLoadPrimaryFont;
- self.primary_face_metrics = try primary_face.getMetrics();
+ self.primary_face_metrics = primary_face.getMetrics();
var metrics = Metrics.calc(self.primary_face_metrics.?);
@@ -1288,8 +1287,8 @@ test "adjusted sizes" {
// The chosen metric should match.
{
- const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
- const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
+ const primary_metrics = (try c.getFace(.{ .idx = 0 })).getMetrics();
+ const fallback_metrics = (try c.getFace(fallback_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
@field(primary_metrics, metric).?,
@@ -1302,8 +1301,8 @@ test "adjusted sizes" {
// 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();
+ const primary_metrics = (try c.getFace(.{ .idx = 0 })).getMetrics();
+ const fallback_metrics = (try c.getFace(fallback_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
@field(primary_metrics, metric).?,
@@ -1359,8 +1358,8 @@ test "adjusted sizes" {
// Test fallback to lineHeight() (ex_height and cap_height not defined in symbols font).
{
- const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
- const symbol_metrics = try (try c.getFace(symbol_idx)).getMetrics();
+ const primary_metrics = (try c.getFace(.{ .idx = 0 })).getMetrics();
+ const symbol_metrics = (try c.getFace(symbol_idx)).getMetrics();
try std.testing.expectApproxEqAbs(
primary_metrics.lineHeight(),
diff --git a/src/font/face/coretext.zig b/src/font/face/coretext.zig
index a85c94430..2804ce2cb 100644
--- a/src/font/face/coretext.zig
+++ b/src/font/face/coretext.zig
@@ -574,19 +574,12 @@ pub const Face = struct {
};
}
- pub const GetMetricsError = error{
- CopyTableError,
- InvalidHeadTable,
- InvalidPostTable,
- InvalidHheaTable,
- };
-
/// Get the `FaceMetrics` for this face.
- pub fn getMetrics(self: *Face) GetMetricsError!font.Metrics.FaceMetrics {
+ pub fn getMetrics(self: *Face) font.Metrics.FaceMetrics {
const ct_font = self.font;
// Read the 'head' table out of the font data.
- const head: opentype.Head = head: {
+ const head_: ?opentype.Head = head: {
// macOS bitmap-only fonts use a 'bhed' tag rather than 'head', but
// the table format is byte-identical to the 'head' table, so if we
// can't find 'head' we try 'bhed' instead before failing.
@@ -597,29 +590,26 @@ pub const Face = struct {
const data =
ct_font.copyTable(head_tag) orelse
ct_font.copyTable(bhed_tag) orelse
- return error.CopyTableError;
+ break :head null;
defer data.release();
const ptr = data.getPointer();
const len = data.getLength();
break :head opentype.Head.init(ptr[0..len]) catch |err| {
- return switch (err) {
- error.EndOfStream,
- => error.InvalidHeadTable,
- };
+ log.warn("error parsing head table: {}", .{err});
+ break :head null;
};
};
// Read the 'post' table out of the font data.
- const post: opentype.Post = post: {
+ const post_: ?opentype.Post = post: {
const tag = macos.text.FontTableTag.init("post");
- const data = ct_font.copyTable(tag) orelse return error.CopyTableError;
+ const data = ct_font.copyTable(tag) orelse break :post null;
defer data.release();
const ptr = data.getPointer();
const len = data.getLength();
break :post opentype.Post.init(ptr[0..len]) catch |err| {
- return switch (err) {
- error.EndOfStream => error.InvalidPostTable,
- };
+ log.warn("error parsing post table: {}", .{err});
+ break :post null;
};
};
@@ -637,96 +627,114 @@ pub const Face = struct {
};
// Read the 'hhea' table out of the font data.
- const hhea: opentype.Hhea = hhea: {
+ const hhea_: ?opentype.Hhea = hhea: {
const tag = macos.text.FontTableTag.init("hhea");
- const data = ct_font.copyTable(tag) orelse return error.CopyTableError;
+ const data = ct_font.copyTable(tag) orelse break :hhea null;
defer data.release();
const ptr = data.getPointer();
const len = data.getLength();
break :hhea opentype.Hhea.init(ptr[0..len]) catch |err| {
- return switch (err) {
- error.EndOfStream => error.InvalidHheaTable,
- };
+ log.warn("error parsing hhea table: {}", .{err});
+ break :hhea null;
};
};
- const units_per_em: f64 = @floatFromInt(head.unitsPerEm);
+ const units_per_em: f64 =
+ if (head_) |head|
+ @floatFromInt(head.unitsPerEm)
+ else
+ @floatFromInt(self.font.getUnitsPerEm());
const px_per_em: f64 = ct_font.getSize();
const px_per_unit: f64 = px_per_em / units_per_em;
const ascent: f64, const descent: f64, const line_gap: f64 = vertical_metrics: {
- const hhea_ascent: f64 = @floatFromInt(hhea.ascender);
- const hhea_descent: f64 = @floatFromInt(hhea.descender);
- const hhea_line_gap: f64 = @floatFromInt(hhea.lineGap);
-
- if (os2_) |os2| {
- const os2_ascent: f64 = @floatFromInt(os2.sTypoAscender);
- const os2_descent: f64 = @floatFromInt(os2.sTypoDescender);
- const os2_line_gap: f64 = @floatFromInt(os2.sTypoLineGap);
-
- // If the font says to use typo metrics, trust it.
- if (os2.fsSelection.use_typo_metrics) break :vertical_metrics .{
- os2_ascent * px_per_unit,
- os2_descent * px_per_unit,
- os2_line_gap * px_per_unit,
- };
-
- // Otherwise we prefer the height metrics from 'hhea' if they
- // are available, or else OS/2 sTypo* metrics, and if all else
- // fails then we use OS/2 usWin* metrics.
- //
- // This is not "standard" behavior, but it's our best bet to
- // account for fonts being... just weird. It's pretty much what
- // FreeType does to get its generic ascent and descent metrics.
+ if (hhea_) |hhea| {
+ const hhea_ascent: f64 = @floatFromInt(hhea.ascender);
+ const hhea_descent: f64 = @floatFromInt(hhea.descender);
+ const hhea_line_gap: f64 = @floatFromInt(hhea.lineGap);
+
+ if (os2_) |os2| {
+ const os2_ascent: f64 = @floatFromInt(os2.sTypoAscender);
+ const os2_descent: f64 = @floatFromInt(os2.sTypoDescender);
+ const os2_line_gap: f64 = @floatFromInt(os2.sTypoLineGap);
+
+ // If the font says to use typo metrics, trust it.
+ if (os2.fsSelection.use_typo_metrics) break :vertical_metrics .{
+ os2_ascent * px_per_unit,
+ os2_descent * px_per_unit,
+ os2_line_gap * px_per_unit,
+ };
+
+ // Otherwise we prefer the height metrics from 'hhea' if they
+ // are available, or else OS/2 sTypo* metrics, and if all else
+ // fails then we use OS/2 usWin* metrics.
+ //
+ // This is not "standard" behavior, but it's our best bet to
+ // account for fonts being... just weird. It's pretty much what
+ // FreeType does to get its generic ascent and descent metrics.
+
+ if (hhea.ascender != 0 or hhea.descender != 0) break :vertical_metrics .{
+ hhea_ascent * px_per_unit,
+ hhea_descent * px_per_unit,
+ hhea_line_gap * px_per_unit,
+ };
+
+ if (os2_ascent != 0 or os2_descent != 0) break :vertical_metrics .{
+ os2_ascent * px_per_unit,
+ os2_descent * px_per_unit,
+ os2_line_gap * px_per_unit,
+ };
+
+ const win_ascent: f64 = @floatFromInt(os2.usWinAscent);
+ const win_descent: f64 = @floatFromInt(os2.usWinDescent);
+ break :vertical_metrics .{
+ win_ascent * px_per_unit,
+ // usWinDescent is *positive* -> down unlike sTypoDescender
+ // and hhea.Descender, so we flip its sign to fix this.
+ -win_descent * px_per_unit,
+ 0.0,
+ };
+ }
- if (hhea.ascender != 0 or hhea.descender != 0) break :vertical_metrics .{
+ // If our font has no OS/2 table, then we just
+ // blindly use the metrics from the hhea table.
+ break :vertical_metrics .{
hhea_ascent * px_per_unit,
hhea_descent * px_per_unit,
hhea_line_gap * px_per_unit,
};
-
- if (os2_ascent != 0 or os2_descent != 0) break :vertical_metrics .{
- os2_ascent * px_per_unit,
- os2_descent * px_per_unit,
- os2_line_gap * px_per_unit,
- };
-
- const win_ascent: f64 = @floatFromInt(os2.usWinAscent);
- const win_descent: f64 = @floatFromInt(os2.usWinDescent);
- break :vertical_metrics .{
- win_ascent * px_per_unit,
- // usWinDescent is *positive* -> down unlike sTypoDescender
- // and hhea.Descender, so we flip its sign to fix this.
- -win_descent * px_per_unit,
- 0.0,
- };
}
- // If our font has no OS/2 table, then we just
- // blindly use the metrics from the hhea table.
+ // If we couldn't get the hhea table, rely on metrics from CoreText.
break :vertical_metrics .{
- hhea_ascent * px_per_unit,
- hhea_descent * px_per_unit,
- hhea_line_gap * px_per_unit,
+ self.font.getAscent(),
+ -self.font.getDescent(),
+ self.font.getLeading(),
};
};
- // Some fonts have degenerate 'post' tables where the underline
- // thickness (and often position) are 0. We consider them null
- // if this is the case and use our own fallbacks when we calculate.
- const has_broken_underline = post.underlineThickness == 0;
+ const underline_position, const underline_thickness = ul: {
+ const post = post_ orelse break :ul .{ null, null };
- // If the underline position isn't 0 then we do use it,
- // even if the thickness is't properly specified.
- const underline_position: ?f64 = if (has_broken_underline and post.underlinePosition == 0)
- null
- else
- @as(f64, @floatFromInt(post.underlinePosition)) * px_per_unit;
+ // Some fonts have degenerate 'post' tables where the underline
+ // thickness (and often position) are 0. We consider them null
+ // if this is the case and use our own fallbacks when we calculate.
+ const has_broken_underline = post.underlineThickness == 0;
- const underline_thickness = if (has_broken_underline)
- null
- else
- @as(f64, @floatFromInt(post.underlineThickness)) * px_per_unit;
+ // If the underline position isn't 0 then we do use it,
+ // even if the thickness is't properly specified.
+ const pos: ?f64 = if (has_broken_underline and post.underlinePosition == 0)
+ null
+ else
+ @as(f64, @floatFromInt(post.underlinePosition)) * px_per_unit;
+
+ const thick: ?f64 = if (has_broken_underline)
+ null
+ else
+ @as(f64, @floatFromInt(post.underlineThickness)) * px_per_unit;
+
+ break :ul .{ pos, thick };
+ };
// Similar logic to the underline above.
const strikethrough_position, const strikethrough_thickness = st: {
@@ -989,7 +997,7 @@ test {
alloc,
&atlas,
face.glyphIndex(i).?,
- .{ .grid_metrics = font.Metrics.calc(try face.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(face.getMetrics()) },
);
}
}
@@ -1054,7 +1062,7 @@ test "in-memory" {
alloc,
&atlas,
face.glyphIndex(i).?,
- .{ .grid_metrics = font.Metrics.calc(try face.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(face.getMetrics()) },
);
}
}
@@ -1081,7 +1089,7 @@ test "variable" {
alloc,
&atlas,
face.glyphIndex(i).?,
- .{ .grid_metrics = font.Metrics.calc(try face.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(face.getMetrics()) },
);
}
}
@@ -1112,7 +1120,7 @@ test "variable set variation" {
alloc,
&atlas,
face.glyphIndex(i).?,
- .{ .grid_metrics = font.Metrics.calc(try face.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(face.getMetrics()) },
);
}
}
diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig
index 1d8d2efff..ef4275131 100644
--- a/src/font/face/freetype.zig
+++ b/src/font/face/freetype.zig
@@ -784,12 +784,8 @@ pub const Face = struct {
return @as(F26Dot6, @bitCast(@as(i32, @intCast(v)))).to(f64);
}
- pub const GetMetricsError = error{
- CopyTableError,
- };
-
/// Get the `FaceMetrics` for this face.
- pub fn getMetrics(self: *Face) GetMetricsError!font.Metrics.FaceMetrics {
+ pub fn getMetrics(self: *Face) font.Metrics.FaceMetrics {
const face = self.face;
const size_metrics = face.handle.*.size.*.metrics;
@@ -799,10 +795,10 @@ pub const Face = struct {
assert(size_metrics.x_ppem == size_metrics.y_ppem);
// Read the 'head' table out of the font data.
- const head = face.getSfntTable(.head) orelse return error.CopyTableError;
+ const head_ = face.getSfntTable(.head);
// Read the 'post' table out of the font data.
- const post = face.getSfntTable(.post) orelse return error.CopyTableError;
+ const post_ = face.getSfntTable(.post);
// Read the 'OS/2' table out of the font data.
const os2_: ?*freetype.c.TT_OS2 = os2: {
@@ -812,92 +808,130 @@ pub const Face = struct {
};
// Read the 'hhea' table out of the font data.
- const hhea = face.getSfntTable(.hhea) orelse return error.CopyTableError;
+ const hhea_ = face.getSfntTable(.hhea);
+
+ // Whether the font is in a scalable format. We need to know this
+ // because many of the metrics provided by FreeType are invalid for
+ // non-scalable fonts.
+ const is_scalable = face.handle.*.face_flags & freetype.c.FT_FACE_FLAG_SCALABLE != 0;
- const units_per_em = head.Units_Per_EM;
+ // We get the UPM from the head table.
+ //
+ // If we have no head, but it is a scalable face, take the UPM from
+ // FreeType's units_per_EM, otherwise we'll assume that UPM == PPEM.
+ const units_per_em: freetype.c.FT_UShort =
+ if (head_) |head|
+ head.Units_Per_EM
+ else if (is_scalable)
+ face.handle.*.units_per_EM
+ else
+ size_metrics.y_ppem;
const px_per_em: f64 = @floatFromInt(size_metrics.y_ppem);
const px_per_unit = px_per_em / @as(f64, @floatFromInt(units_per_em));
const ascent: f64, const descent: f64, const line_gap: f64 = vertical_metrics: {
- const hhea_ascent: f64 = @floatFromInt(hhea.Ascender);
- const hhea_descent: f64 = @floatFromInt(hhea.Descender);
- const hhea_line_gap: f64 = @floatFromInt(hhea.Line_Gap);
-
- if (os2_) |os2| {
- const os2_ascent: f64 = @floatFromInt(os2.sTypoAscender);
- const os2_descent: f64 = @floatFromInt(os2.sTypoDescender);
- const os2_line_gap: f64 = @floatFromInt(os2.sTypoLineGap);
-
- // If the font says to use typo metrics, trust it.
- // (The USE_TYPO_METRICS bit is bit 7)
- if (os2.fsSelection & (1 << 7) != 0) {
- break :vertical_metrics .{
- os2_ascent * px_per_unit,
- os2_descent * px_per_unit,
- os2_line_gap * px_per_unit,
- };
- }
+ if (hhea_) |hhea| {
+ const hhea_ascent: f64 = @floatFromInt(hhea.Ascender);
+ const hhea_descent: f64 = @floatFromInt(hhea.Descender);
+ const hhea_line_gap: f64 = @floatFromInt(hhea.Line_Gap);
+
+ if (os2_) |os2| {
+ const os2_ascent: f64 = @floatFromInt(os2.sTypoAscender);
+ const os2_descent: f64 = @floatFromInt(os2.sTypoDescender);
+ const os2_line_gap: f64 = @floatFromInt(os2.sTypoLineGap);
+
+ // If the font says to use typo metrics, trust it.
+ // (The USE_TYPO_METRICS bit is bit 7)
+ if (os2.fsSelection & (1 << 7) != 0) {
+ break :vertical_metrics .{
+ os2_ascent * px_per_unit,
+ os2_descent * px_per_unit,
+ os2_line_gap * px_per_unit,
+ };
+ }
- // Otherwise we prefer the height metrics from 'hhea' if they
- // are available, or else OS/2 sTypo* metrics, and if all else
- // fails then we use OS/2 usWin* metrics.
- //
- // This is not "standard" behavior, but it's our best bet to
- // account for fonts being... just weird. It's pretty much what
- // FreeType does to get its generic ascent and descent metrics.
+ // Otherwise we prefer the height metrics from 'hhea' if they
+ // are available, or else OS/2 sTypo* metrics, and if all else
+ // fails then we use OS/2 usWin* metrics.
+ //
+ // This is not "standard" behavior, but it's our best bet to
+ // account for fonts being... just weird. It's pretty much what
+ // FreeType does to get its generic ascent and descent metrics.
+
+ if (hhea.Ascender != 0 or hhea.Descender != 0) {
+ break :vertical_metrics .{
+ hhea_ascent * px_per_unit,
+ hhea_descent * px_per_unit,
+ hhea_line_gap * px_per_unit,
+ };
+ }
- if (hhea.Ascender != 0 or hhea.Descender != 0) {
- break :vertical_metrics .{
- hhea_ascent * px_per_unit,
- hhea_descent * px_per_unit,
- hhea_line_gap * px_per_unit,
- };
- }
+ if (os2_ascent != 0 or os2_descent != 0) {
+ break :vertical_metrics .{
+ os2_ascent * px_per_unit,
+ os2_descent * px_per_unit,
+ os2_line_gap * px_per_unit,
+ };
+ }
- if (os2_ascent != 0 or os2_descent != 0) {
+ const win_ascent: f64 = @floatFromInt(os2.usWinAscent);
+ const win_descent: f64 = @floatFromInt(os2.usWinDescent);
break :vertical_metrics .{
- os2_ascent * px_per_unit,
- os2_descent * px_per_unit,
- os2_line_gap * px_per_unit,
+ win_ascent * px_per_unit,
+ // usWinDescent is *positive* -> down unlike sTypoDescender
+ // and hhea.Descender, so we flip its sign to fix this.
+ -win_descent * px_per_unit,
+ 0.0,
};
}
- const win_ascent: f64 = @floatFromInt(os2.usWinAscent);
- const win_descent: f64 = @floatFromInt(os2.usWinDescent);
+ // If our font has no OS/2 table, then we just
+ // blindly use the metrics from the hhea table.
break :vertical_metrics .{
- win_ascent * px_per_unit,
- // usWinDescent is *positive* -> down unlike sTypoDescender
- // and hhea.Descender, so we flip its sign to fix this.
- -win_descent * px_per_unit,
- 0.0,
+ hhea_ascent * px_per_unit,
+ hhea_descent * px_per_unit,
+ hhea_line_gap * px_per_unit,
};
}
- // If our font has no OS/2 table, then we just
- // blindly use the metrics from the hhea table.
+ // If we couldn't get the hhea table, rely on metrics from FreeType.
+ const ascender = f26dot6ToF64(size_metrics.ascender);
+ const descender = f26dot6ToF64(size_metrics.descender);
+ const height = f26dot6ToF64(size_metrics.height);
break :vertical_metrics .{
- hhea_ascent * px_per_unit,
- hhea_descent * px_per_unit,
- hhea_line_gap * px_per_unit,
+ ascender,
+ descender,
+ // We compute the line gap by adding the (negative) descender
+ // and subtracting the (positive) ascender from the line height
+ // to get the remaining gap size.
+ //
+ // NOTE: This might always be 0... but it doesn't hurt to do.
+ height + descender - ascender,
};
};
- // Some fonts have degenerate 'post' tables where the underline
- // thickness (and often position) are 0. We consider them null
- // if this is the case and use our own fallbacks when we calculate.
- const has_broken_underline = post.underlineThickness == 0;
+ const underline_position: ?f64, const underline_thickness: ?f64 = ul: {
+ const post = post_ orelse break :ul .{ null, null };
+
+ // Some fonts have degenerate 'post' tables where the underline
+ // thickness (and often position) are 0. We consider them null
+ // if this is the case and use our own fallbacks when we calculate.
+ const has_broken_underline = post.underlineThickness == 0;
- // If the underline position isn't 0 then we do use it,
- // even if the thickness is't properly specified.
- const underline_position = if (has_broken_underline and post.underlinePosition == 0)
- null
- else
- @as(f64, @floatFromInt(post.underlinePosition)) * px_per_unit;
+ // If the underline position isn't 0 then we do use it,
+ // even if the thickness is't properly specified.
+ const pos: ?f64 = if (has_broken_underline and post.underlinePosition == 0)
+ null
+ else
+ @as(f64, @floatFromInt(post.underlinePosition)) * px_per_unit;
+
+ const thick: ?f64 = if (has_broken_underline)
+ null
+ else
+ @as(f64, @floatFromInt(post.underlineThickness)) * px_per_unit;
- const underline_thickness = if (has_broken_underline)
- null
- else
- @as(f64, @floatFromInt(post.underlineThickness)) * px_per_unit;
+ break :ul .{ pos, thick };
+ };
// Similar logic to the underline above.
const strikethrough_position, const strikethrough_thickness = st: {
@@ -1085,7 +1119,7 @@ test {
alloc,
&atlas,
ft_font.glyphIndex(i).?,
- .{ .grid_metrics = font.Metrics.calc(try ft_font.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
);
}
@@ -1095,7 +1129,7 @@ test {
alloc,
&atlas,
ft_font.glyphIndex('A').?,
- .{ .grid_metrics = font.Metrics.calc(try ft_font.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
);
try testing.expectEqual(@as(u32, 11), g1.height);
@@ -1104,7 +1138,7 @@ test {
alloc,
&atlas,
ft_font.glyphIndex('A').?,
- .{ .grid_metrics = font.Metrics.calc(try ft_font.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
);
try testing.expectEqual(@as(u32, 20), g2.height);
}
@@ -1131,7 +1165,7 @@ test "color emoji" {
alloc,
&atlas,
ft_font.glyphIndex('🥸').?,
- .{ .grid_metrics = font.Metrics.calc(try ft_font.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
);
// Make sure this glyph has color
@@ -1191,7 +1225,7 @@ test "mono to bgra" {
alloc,
&atlas,
3,
- .{ .grid_metrics = font.Metrics.calc(try ft_font.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
);
}
@@ -1255,7 +1289,7 @@ test "bitmap glyph" {
alloc,
&atlas,
77,
- .{ .grid_metrics = font.Metrics.calc(try ft_font.getMetrics()) },
+ .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
);
// should render crisp