font: further improve ul/st position calculations

This commit is contained in:
Qwerasd
2024-09-23 22:10:43 -06:00
parent 49a3008919
commit 7a1d304fa9
2 changed files with 30 additions and 28 deletions

View File

@ -594,7 +594,10 @@ pub const Face = struct {
// All of these metrics are based on our layout above. // All of these metrics are based on our layout above.
const cell_height = @ceil(layout_metrics.height); const cell_height = @ceil(layout_metrics.height);
const cell_baseline = @ceil(layout_metrics.height - layout_metrics.ascent); const cell_baseline = @ceil(layout_metrics.height - layout_metrics.ascent);
const underline_thickness = @ceil(@as(f32, @floatCast(ct_font.getUnderlineThickness()))); const underline_thickness = @ceil(@as(f32, @floatCast(ct_font.getUnderlineThickness())));
const strikethrough_thickness = underline_thickness;
const strikethrough_position = strikethrough_position: { const strikethrough_position = strikethrough_position: {
// This is the height of lower case letters in our font. // This is the height of lower case letters in our font.
const ex_height = ct_font.getXHeight(); const ex_height = ct_font.getXHeight();
@ -608,20 +611,21 @@ pub const Face = struct {
// is the distance from the top down to the baseline, then // is the distance from the top down to the baseline, then
// we subtract half of the ex height to go back up to the // we subtract half of the ex height to go back up to the
// correct height that should evenly split lowercase text. // correct height that should evenly split lowercase text.
const pos = layout_metrics.ascent - ex_height * 0.5 + 1; const pos = layout_metrics.ascent -
ex_height * 0.5 +
strikethrough_thickness * 0.5 +
1;
break :strikethrough_position @ceil(pos); break :strikethrough_position @ceil(pos);
}; };
const strikethrough_thickness = underline_thickness;
// Underline position reported is usually something like "-1" to // Underline position reported is usually something like "-1" to
// represent the amount under the baseline. We add this to our real // represent the amount under the baseline. We add this to our real
// baseline to get the actual value from the bottom (+y is up). // baseline to get the actual value from the bottom (+y is up).
// The final underline position is +y from the TOP (confusing) // The final underline position is +y from the TOP (confusing)
// so we have to subtract from the cell height. // so we have to subtract from the cell height.
const underline_position = cell_height - const underline_position = @ceil(layout_metrics.ascent -
(cell_baseline + @ceil(@as(f32, @floatCast(ct_font.getUnderlinePosition())))) + @as(f32, @floatCast(ct_font.getUnderlinePosition())) + 1);
1;
// Note: is this useful? // Note: is this useful?
// const units_per_em = ct_font.getUnitsPerEm(); // const units_per_em = ct_font.getUnitsPerEm();

View File

@ -660,52 +660,50 @@ pub const Face = struct {
// is reversed. // is reversed.
const cell_baseline = -1 * f26dot6ToFloat(size_metrics.descender); const cell_baseline = -1 * f26dot6ToFloat(size_metrics.descender);
const underline_thickness = @max(@as(f32, 1), fontUnitsToPxY(
face,
face.handle.*.underline_thickness,
));
// The underline position. This is a value from the top where the // The underline position. This is a value from the top where the
// underline should go. // underline should go.
const underline_position: f32 = underline_pos: { const underline_position: f32 = underline_pos: {
// The ascender is already scaled for scalable fonts, but the const declared_px = @as(f32, @floatFromInt(freetype.mulFix(
// underline position is not.
const ascender_px = @as(i32, @intCast(size_metrics.ascender)) >> 6;
const declared_px = freetype.mulFix(
face.handle.*.underline_position, face.handle.*.underline_position,
@intCast(face.handle.*.size.*.metrics.y_scale), @intCast(face.handle.*.size.*.metrics.y_scale),
) >> 6; ))) / 64;
// We use the declared underline position if its available // We use the declared underline position if its available
const declared = ascender_px - declared_px; const declared = cell_height - cell_baseline - declared_px;
if (declared > 0) if (declared > 0)
break :underline_pos @floatFromInt(declared); break :underline_pos declared;
// If we have no declared underline position, we go slightly under the // If we have no declared underline position, we go slightly under the
// cell height (mainly: non-scalable fonts, i.e. emoji) // cell height (mainly: non-scalable fonts, i.e. emoji)
break :underline_pos cell_height - 1; break :underline_pos cell_height - 1;
}; };
const underline_thickness = @max(@as(f32, 1), fontUnitsToPxY(
face,
face.handle.*.underline_thickness,
));
// The strikethrough position. We use the position provided by the // The strikethrough position. We use the position provided by the
// font if it exists otherwise we calculate a best guess. // font if it exists otherwise we calculate a best guess.
const strikethrough: struct { const strikethrough: struct {
pos: f32, pos: f32,
thickness: f32, thickness: f32,
} = if (face.getSfntTable(.os2)) |os2| .{ } = if (face.getSfntTable(.os2)) |os2| st: {
.pos = pos: { const thickness = @max(@as(f32, 1), fontUnitsToPxY(face, os2.yStrikeoutSize));
// Ascender is scaled, strikeout pos is not
const ascender_px = @as(i32, @intCast(size_metrics.ascender)) >> 6; const pos = @as(f32, @floatFromInt(freetype.mulFix(
const declared_px = freetype.mulFix(
os2.yStrikeoutPosition, os2.yStrikeoutPosition,
@as(i32, @intCast(face.handle.*.size.*.metrics.y_scale)), @as(i32, @intCast(face.handle.*.size.*.metrics.y_scale)),
) >> 6; ))) / 64;
break :pos @floatFromInt(ascender_px - declared_px); break :st .{
}, .pos = @ceil(cell_height - cell_baseline - pos + thickness + 1),
.thickness = @max(@as(f32, 1), fontUnitsToPxY(face, os2.yStrikeoutSize)), .thickness = thickness,
};
} else .{ } else .{
// Exactly 50% of the ex height so that our strikethrough is // Exactly 50% of the ex height so that our strikethrough is
// centered through lowercase text. This is a common choice. // centered through lowercase text. This is a common choice.
.pos = cell_baseline - ex_height * 0.5 + 1, .pos = @ceil(cell_height - cell_baseline - ex_height * 0.5 + underline_thickness),
.thickness = underline_thickness, .thickness = underline_thickness,
}; };