mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
font: more generic bearing adjustments
This generally adjusts the bearings of any glyph whose original advance was narrower than the cell, which helps a lot with proportional fallback glyphs so they aren't just left-aligned. This only applies to situations where the glyph was originally narrower than the cell, so that we don't mess up ligatures, and this centers the old advance width in the new one rather than adjusting proportionally, because otherwise we can mess up glyphs that are meant to align with others when placed vertically.
This commit is contained in:
@ -481,20 +481,42 @@ pub const Face = struct {
|
|||||||
// This should be the distance from the left of
|
// This should be the distance from the left of
|
||||||
// the cell to the left of the glyph's bounding box.
|
// the cell to the left of the glyph's bounding box.
|
||||||
const offset_x: i32 = offset_x: {
|
const offset_x: i32 = offset_x: {
|
||||||
var result: i32 = @intFromFloat(@round(x));
|
// If the glyph's advance is narrower than the cell width then we
|
||||||
|
// center the advance of the glyph within the cell width. At first
|
||||||
// If our cell was resized then we adjust our glyph's
|
// I implemented this to proportionally scale the center position
|
||||||
// position relative to the new center. This keeps glyphs
|
// of the glyph but that messes up glyphs that are meant to align
|
||||||
// centered in the cell whether it was made wider or narrower.
|
// vertically with others, so this is a compromise.
|
||||||
if (metrics.original_cell_width) |original_width| {
|
//
|
||||||
const before: i32 = @intCast(original_width);
|
// This makes it so that when the `adjust-cell-width` config is
|
||||||
const after: i32 = @intCast(metrics.cell_width);
|
// used, or when a fallback font with a different advance width
|
||||||
// Increase the offset by half of the difference
|
// is used, we don't get weirdly aligned glyphs.
|
||||||
// between the widths to keep things centered.
|
//
|
||||||
result += @divTrunc(after - before, 2);
|
// We don't do this if the constraint has a horizontal alignment,
|
||||||
|
// since in that case the position was already calculated with the
|
||||||
|
// new cell width in mind.
|
||||||
|
if (opts.constraint.align_horizontal == .none) {
|
||||||
|
var advances: [glyphs.len]macos.graphics.Size = undefined;
|
||||||
|
_ = self.font.getAdvancesForGlyphs(.horizontal, &glyphs, &advances);
|
||||||
|
const advance = advances[0].width;
|
||||||
|
const new_advance =
|
||||||
|
cell_width * @as(f64, @floatFromInt(opts.cell_width orelse 1));
|
||||||
|
// If the original advance is greater than the cell width then
|
||||||
|
// it's possible that this is a ligature or other glyph that is
|
||||||
|
// intended to overflow the cell to one side or the other, and
|
||||||
|
// adjusting the bearings could mess that up, so we just leave
|
||||||
|
// it alone if that's the case.
|
||||||
|
//
|
||||||
|
// We also don't want to do anything if the advance is zero or
|
||||||
|
// less, since this is used for stuff like combining characters.
|
||||||
|
if (advance > new_advance or advance <= 0.0) {
|
||||||
|
break :offset_x @intFromFloat(@round(x));
|
||||||
|
}
|
||||||
|
break :offset_x @intFromFloat(
|
||||||
|
@round(x + (new_advance - advance) / 2),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
break :offset_x @intFromFloat(@round(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
break :offset_x result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
|
@ -638,20 +638,40 @@ pub const Face = struct {
|
|||||||
// This should be the distance from the left of
|
// This should be the distance from the left of
|
||||||
// the cell to the left of the glyph's bounding box.
|
// the cell to the left of the glyph's bounding box.
|
||||||
const offset_x: i32 = offset_x: {
|
const offset_x: i32 = offset_x: {
|
||||||
var result: i32 = @intFromFloat(@floor(x));
|
// If the glyph's advance is narrower than the cell width then we
|
||||||
|
// center the advance of the glyph within the cell width. At first
|
||||||
// If our cell was resized then we adjust our glyph's
|
// I implemented this to proportionally scale the center position
|
||||||
// position relative to the new center. This keeps glyphs
|
// of the glyph but that messes up glyphs that are meant to align
|
||||||
// centered in the cell whether it was made wider or narrower.
|
// vertically with others, so this is a compromise.
|
||||||
if (metrics.original_cell_width) |original_width| {
|
//
|
||||||
const before: i32 = @intCast(original_width);
|
// This makes it so that when the `adjust-cell-width` config is
|
||||||
const after: i32 = @intCast(metrics.cell_width);
|
// used, or when a fallback font with a different advance width
|
||||||
// Increase the offset by half of the difference
|
// is used, we don't get weirdly aligned glyphs.
|
||||||
// between the widths to keep things centered.
|
//
|
||||||
result += @divTrunc(after - before, 2);
|
// We don't do this if the constraint has a horizontal alignment,
|
||||||
|
// since in that case the position was already calculated with the
|
||||||
|
// new cell width in mind.
|
||||||
|
if (opts.constraint.align_horizontal == .none) {
|
||||||
|
const advance = f26dot6ToFloat(glyph.*.advance.x);
|
||||||
|
const new_advance =
|
||||||
|
cell_width * @as(f64, @floatFromInt(opts.cell_width orelse 1));
|
||||||
|
// If the original advance is greater than the cell width then
|
||||||
|
// it's possible that this is a ligature or other glyph that is
|
||||||
|
// intended to overflow the cell to one side or the other, and
|
||||||
|
// adjusting the bearings could mess that up, so we just leave
|
||||||
|
// it alone if that's the case.
|
||||||
|
//
|
||||||
|
// We also don't want to do anything if the advance is zero or
|
||||||
|
// less, since this is used for stuff like combining characters.
|
||||||
|
if (advance > new_advance or advance <= 0.0) {
|
||||||
|
break :offset_x @intFromFloat(@floor(x));
|
||||||
|
}
|
||||||
|
break :offset_x @intFromFloat(
|
||||||
|
@floor(x + (new_advance - advance) / 2),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
break :offset_x @intFromFloat(@floor(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
break :offset_x result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Glyph{
|
return Glyph{
|
||||||
|
Reference in New Issue
Block a user