mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
Merge pull request #2123 from ghostty-org/ct-thicken
font/coretext: font-thicken renders with additional padding on context
This commit is contained in:
@ -1174,6 +1174,8 @@ fn setCellSize(self: *Surface, size: renderer.CellSize) !void {
|
|||||||
///
|
///
|
||||||
/// This can only be called from the main thread.
|
/// This can only be called from the main thread.
|
||||||
pub fn setFontSize(self: *Surface, size: font.face.DesiredSize) !void {
|
pub fn setFontSize(self: *Surface, size: font.face.DesiredSize) !void {
|
||||||
|
log.debug("set font size size={}", .{size.points});
|
||||||
|
|
||||||
// Update our font size so future changes work
|
// Update our font size so future changes work
|
||||||
self.font_size = size;
|
self.font_size = size;
|
||||||
|
|
||||||
|
@ -300,6 +300,14 @@ pub const Face = struct {
|
|||||||
.advance_x = 0,
|
.advance_x = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If we're doing thicken, then getBoundsForGlyphs does not take
|
||||||
|
// into account the anti-aliasing that will be added to the glyph.
|
||||||
|
// We need to add some padding to allow that to happen. A padding of
|
||||||
|
// 2 is usually enough for anti-aliasing.
|
||||||
|
const padding_ctx: u32 = if (opts.thicken) 2 else 0;
|
||||||
|
const padded_width: u32 = width + (padding_ctx * 2);
|
||||||
|
const padded_height: u32 = height + (padding_ctx * 2);
|
||||||
|
|
||||||
// Settings that are specific to if we are rendering text or emoji.
|
// Settings that are specific to if we are rendering text or emoji.
|
||||||
const color: struct {
|
const color: struct {
|
||||||
color: bool,
|
color: bool,
|
||||||
@ -334,17 +342,17 @@ pub const Face = struct {
|
|||||||
// usually stabilizes pretty quickly and is very infrequent so I think
|
// usually stabilizes pretty quickly and is very infrequent so I think
|
||||||
// the allocation overhead is acceptable compared to the cost of
|
// the allocation overhead is acceptable compared to the cost of
|
||||||
// caching it forever or having to deal with a cache lifetime.
|
// caching it forever or having to deal with a cache lifetime.
|
||||||
const buf = try alloc.alloc(u8, width * height * color.depth);
|
const buf = try alloc.alloc(u8, padded_width * padded_height * color.depth);
|
||||||
defer alloc.free(buf);
|
defer alloc.free(buf);
|
||||||
@memset(buf, 0);
|
@memset(buf, 0);
|
||||||
|
|
||||||
const context = macos.graphics.BitmapContext.context;
|
const context = macos.graphics.BitmapContext.context;
|
||||||
const ctx = try macos.graphics.BitmapContext.create(
|
const ctx = try macos.graphics.BitmapContext.create(
|
||||||
buf,
|
buf,
|
||||||
width,
|
padded_width,
|
||||||
height,
|
padded_height,
|
||||||
8,
|
8,
|
||||||
width * color.depth,
|
padded_width * color.depth,
|
||||||
color.space,
|
color.space,
|
||||||
color.context_opts,
|
color.context_opts,
|
||||||
);
|
);
|
||||||
@ -359,8 +367,8 @@ pub const Face = struct {
|
|||||||
context.fillRect(ctx, .{
|
context.fillRect(ctx, .{
|
||||||
.origin = .{ .x = 0, .y = 0 },
|
.origin = .{ .x = 0, .y = 0 },
|
||||||
.size = .{
|
.size = .{
|
||||||
.width = @floatFromInt(width),
|
.width = @floatFromInt(padded_width),
|
||||||
.height = @floatFromInt(height),
|
.height = @floatFromInt(padded_height),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -386,10 +394,11 @@ pub const Face = struct {
|
|||||||
// are offset by bearings, so we have to undo those bearings in order
|
// are offset by bearings, so we have to undo those bearings in order
|
||||||
// to get them to 0,0. We also add the padding so that they render
|
// to get them to 0,0. We also add the padding so that they render
|
||||||
// slightly off the edge of the bitmap.
|
// slightly off the edge of the bitmap.
|
||||||
|
const padding_ctx_f64: f64 = @floatFromInt(padding_ctx);
|
||||||
self.font.drawGlyphs(&glyphs, &.{
|
self.font.drawGlyphs(&glyphs, &.{
|
||||||
.{
|
.{
|
||||||
.x = -1 * render_x,
|
.x = -1 * (render_x - padding_ctx_f64),
|
||||||
.y = render_y,
|
.y = render_y + padding_ctx_f64,
|
||||||
},
|
},
|
||||||
}, ctx);
|
}, ctx);
|
||||||
|
|
||||||
@ -401,8 +410,8 @@ pub const Face = struct {
|
|||||||
// Get the full padded region
|
// Get the full padded region
|
||||||
var region = try atlas.reserve(
|
var region = try atlas.reserve(
|
||||||
alloc,
|
alloc,
|
||||||
width + (padding * 2), // * 2 because left+right
|
padded_width + (padding * 2), // * 2 because left+right
|
||||||
height + (padding * 2), // * 2 because top+bottom
|
padded_height + (padding * 2), // * 2 because top+bottom
|
||||||
);
|
);
|
||||||
|
|
||||||
// Modify the region so that we remove the padding so that
|
// Modify the region so that we remove the padding so that
|
||||||
@ -427,11 +436,15 @@ pub const Face = struct {
|
|||||||
// ADD here because CoreText y is UP.
|
// ADD here because CoreText y is UP.
|
||||||
const baseline_with_offset = baseline_from_bottom + glyph_ascent;
|
const baseline_with_offset = baseline_from_bottom + glyph_ascent;
|
||||||
|
|
||||||
break :offset_y @intFromFloat(@ceil(baseline_with_offset));
|
// Add our context padding we may have created.
|
||||||
|
const baseline_with_padding = baseline_with_offset + padding_ctx_f64;
|
||||||
|
|
||||||
|
break :offset_y @intFromFloat(@ceil(baseline_with_padding));
|
||||||
};
|
};
|
||||||
|
|
||||||
const offset_x: i32 = offset_x: {
|
const offset_x: i32 = offset_x: {
|
||||||
var result: i32 = @intFromFloat(render_x);
|
// Don't forget to apply our context padding if we have one
|
||||||
|
var result: i32 = @intFromFloat(render_x - padding_ctx_f64);
|
||||||
|
|
||||||
// If our cell was resized to be wider then we center our
|
// If our cell was resized to be wider then we center our
|
||||||
// glyph in the cell.
|
// glyph in the cell.
|
||||||
@ -462,8 +475,8 @@ pub const Face = struct {
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.width = width,
|
.width = padded_width,
|
||||||
.height = height,
|
.height = padded_height,
|
||||||
.offset_x = offset_x,
|
.offset_x = offset_x,
|
||||||
.offset_y = offset_y,
|
.offset_y = offset_y,
|
||||||
.atlas_x = region.x,
|
.atlas_x = region.x,
|
||||||
|
Reference in New Issue
Block a user