From 2b78ac4382c12686fa4aed7871db18256b48934c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 16 Dec 2024 12:29:10 -0800 Subject: [PATCH] font: style edits for #2985 --- src/font/face/coretext.zig | 92 +++++++++++++++++--------------------- src/font/face/freetype.zig | 31 +++++++------ 2 files changed, 57 insertions(+), 66 deletions(-) diff --git a/src/font/face/coretext.zig b/src/font/face/coretext.zig index 6389ba67e..e1fd74298 100644 --- a/src/font/face/coretext.zig +++ b/src/font/face/coretext.zig @@ -568,14 +568,14 @@ pub const Face = struct { }; // Read the 'OS/2' table out of the font data if it's available. - const maybe_os2: ?opentype.OS2 = os2: { + const os2_: ?opentype.OS2 = os2: { const tag = macos.text.FontTableTag.init("OS/2"); const data = ct_font.copyTable(tag) orelse break :os2 null; defer data.release(); const ptr = data.getPointer(); const len = data.getLength(); break :os2 opentype.OS2.init(ptr[0..len]) catch |err| { - log.warn("Error parsing OS/2 table: {any}", .{err}); + log.warn("error parsing OS/2 table: {}", .{err}); break :os2 null; }; }; @@ -603,19 +603,17 @@ pub const Face = struct { const hhea_descent: f64 = @floatFromInt(hhea.descender); const hhea_line_gap: f64 = @floatFromInt(hhea.lineGap); - if (maybe_os2) |os2| { + 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, - }; - } + 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 @@ -625,21 +623,17 @@ pub const Face = struct { // 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) 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); @@ -680,44 +674,42 @@ pub const Face = struct { // Similar logic to the underline above. const strikethrough_position, const strikethrough_thickness = st: { - if (maybe_os2) |os2| { - const has_broken_strikethrough = os2.yStrikeoutSize == 0; + const os2 = os2_ orelse break :st .{ null, null }; - const pos: ?f64 = if (has_broken_strikethrough and os2.yStrikeoutPosition == 0) - null - else - @as(f64, @floatFromInt(os2.yStrikeoutPosition)) * px_per_unit; + const has_broken_strikethrough = os2.yStrikeoutSize == 0; - const thick: ?f64 = if (has_broken_strikethrough) - null - else - @as(f64, @floatFromInt(os2.yStrikeoutSize)) * px_per_unit; + const pos: ?f64 = if (has_broken_strikethrough and os2.yStrikeoutPosition == 0) + null + else + @as(f64, @floatFromInt(os2.yStrikeoutPosition)) * px_per_unit; - break :st .{ pos, thick }; - } + const thick: ?f64 = if (has_broken_strikethrough) + null + else + @as(f64, @floatFromInt(os2.yStrikeoutSize)) * px_per_unit; - break :st .{ null, null }; + break :st .{ pos, thick }; }; // We fall back to whatever CoreText does if the // OS/2 table doesn't specify a cap or ex height. const cap_height: f64, const ex_height: f64 = heights: { - if (maybe_os2) |os2| { - break :heights .{ - if (os2.sCapHeight) |sCapHeight| - @as(f64, @floatFromInt(sCapHeight)) * px_per_unit - else - ct_font.getCapHeight(), - if (os2.sxHeight) |sxHeight| - @as(f64, @floatFromInt(sxHeight)) * px_per_unit - else - ct_font.getXHeight(), - }; - } - break :heights .{ + const os2 = os2_ orelse break :heights .{ ct_font.getCapHeight(), ct_font.getXHeight(), }; + + break :heights .{ + if (os2.sCapHeight) |sCapHeight| + @as(f64, @floatFromInt(sCapHeight)) * px_per_unit + else + ct_font.getCapHeight(), + + if (os2.sxHeight) |sxHeight| + @as(f64, @floatFromInt(sxHeight)) * px_per_unit + else + ct_font.getXHeight(), + }; }; // Cell width is calculated by calculating the widest width of the diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 186ad9e10..f5ec9e7ec 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -628,7 +628,7 @@ pub const Face = struct { const post = face.getSfntTable(.post) orelse return error.CopyTableError; // Read the 'OS/2' table out of the font data. - const maybe_os2: ?*freetype.c.TT_OS2 = os2: { + const os2_: ?*freetype.c.TT_OS2 = os2: { const os2 = face.getSfntTable(.os2) orelse break :os2 null; if (os2.version == 0xFFFF) break :os2 null; break :os2 os2; @@ -646,7 +646,7 @@ pub const Face = struct { const hhea_descent: f64 = @floatFromInt(hhea.Descender); const hhea_line_gap: f64 = @floatFromInt(hhea.Line_Gap); - if (maybe_os2) |os2| { + 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); @@ -724,23 +724,21 @@ pub const Face = struct { // Similar logic to the underline above. const strikethrough_position, const strikethrough_thickness = st: { - if (maybe_os2) |os2| { - const has_broken_strikethrough = os2.yStrikeoutSize == 0; + const os2 = os2_ orelse break :st .{ null, null }; - const pos: ?f64 = if (has_broken_strikethrough and os2.yStrikeoutPosition == 0) - null - else - @as(f64, @floatFromInt(os2.yStrikeoutPosition)) * px_per_unit; + const has_broken_strikethrough = os2.yStrikeoutSize == 0; - const thick: ?f64 = if (has_broken_strikethrough) - null - else - @as(f64, @floatFromInt(os2.yStrikeoutSize)) * px_per_unit; + const pos: ?f64 = if (has_broken_strikethrough and os2.yStrikeoutPosition == 0) + null + else + @as(f64, @floatFromInt(os2.yStrikeoutPosition)) * px_per_unit; - break :st .{ pos, thick }; - } + const thick: ?f64 = if (has_broken_strikethrough) + null + else + @as(f64, @floatFromInt(os2.yStrikeoutSize)) * px_per_unit; - break :st .{ null, null }; + break :st .{ pos, thick }; }; // Cell width is calculated by calculating the widest width of the @@ -774,7 +772,7 @@ pub const Face = struct { // We use the cap and ex heights specified by the font if they're // available, otherwise we try to measure the `H` and `x` glyphs. const cap_height: ?f64, const ex_height: ?f64 = heights: { - if (maybe_os2) |os2| { + if (os2_) |os2| { // The OS/2 table does not include these metrics in version 1. if (os2.version >= 2) { break :heights .{ @@ -783,6 +781,7 @@ pub const Face = struct { }; } } + break :heights .{ cap: { if (face.getCharIndex('H')) |glyph_index| {