mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge pull request #1741 from qwerasd205/non-integer-point-size
feat(font): Non-integer point sizes
This commit is contained in:
@ -379,7 +379,7 @@ typedef struct {
|
||||
ghostty_platform_u platform;
|
||||
void* userdata;
|
||||
double scale_factor;
|
||||
uint8_t font_size;
|
||||
float font_size;
|
||||
const char* working_directory;
|
||||
const char* command;
|
||||
} ghostty_surface_config_s;
|
||||
|
@ -252,7 +252,7 @@ extension Ghostty {
|
||||
/// libghostty, usually from the Ghostty configuration.
|
||||
struct SurfaceConfiguration {
|
||||
/// Explicit font size to use in points
|
||||
var fontSize: UInt8? = nil
|
||||
var fontSize: Float32? = nil
|
||||
|
||||
/// Explicit working directory to set
|
||||
var workingDirectory: String? = nil
|
||||
|
@ -41,7 +41,11 @@ pub fn build(b: *std.Build) !void {
|
||||
try apple_sdk.addPaths(b, module);
|
||||
}
|
||||
|
||||
const freetype_dep = b.dependency("freetype", .{ .target = target, .optimize = optimize });
|
||||
const freetype_dep = b.dependency("freetype", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"enable-libpng" = true,
|
||||
});
|
||||
lib.linkLibrary(freetype_dep.artifact("freetype"));
|
||||
module.addIncludePath(freetype_dep.builder.dependency("freetype", .{}).path("include"));
|
||||
|
||||
|
@ -194,7 +194,7 @@ const DerivedConfig = struct {
|
||||
arena: ArenaAllocator,
|
||||
|
||||
/// For docs for these, see the associated config they are derived from.
|
||||
original_font_size: u8,
|
||||
original_font_size: f32,
|
||||
keybind: configpkg.Keybinds,
|
||||
clipboard_read: configpkg.ClipboardAccess,
|
||||
clipboard_write: configpkg.ClipboardAccess,
|
||||
@ -3008,18 +3008,25 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||
),
|
||||
|
||||
.increase_font_size => |delta| {
|
||||
log.debug("increase font size={}", .{delta});
|
||||
// Max delta is somewhat arbitrary.
|
||||
const clamped_delta = @max(0, @min(255, delta));
|
||||
|
||||
log.debug("increase font size={}", .{clamped_delta});
|
||||
|
||||
var size = self.font_size;
|
||||
size.points +|= delta;
|
||||
// Max point size is somewhat arbitrary.
|
||||
size.points = @min(size.points + clamped_delta, 255);
|
||||
try self.setFontSize(size);
|
||||
},
|
||||
|
||||
.decrease_font_size => |delta| {
|
||||
log.debug("decrease font size={}", .{delta});
|
||||
// Max delta is somewhat arbitrary.
|
||||
const clamped_delta = @max(0, @min(255, delta));
|
||||
|
||||
log.debug("decrease font size={}", .{clamped_delta});
|
||||
|
||||
var size = self.font_size;
|
||||
size.points = @max(1, size.points -| delta);
|
||||
size.points = @max(1, size.points - clamped_delta);
|
||||
try self.setFontSize(size);
|
||||
},
|
||||
|
||||
|
@ -314,7 +314,7 @@ pub const Surface = struct {
|
||||
scale_factor: f64 = 1,
|
||||
|
||||
/// The font size to inherit. If 0, default font size will be used.
|
||||
font_size: u8 = 0,
|
||||
font_size: f32 = 0,
|
||||
|
||||
/// The working directory to load into.
|
||||
working_directory: [*:0]const u8 = "",
|
||||
@ -1049,7 +1049,7 @@ pub const Surface = struct {
|
||||
}
|
||||
|
||||
fn newSurfaceOptions(self: *const Surface) apprt.Surface.Options {
|
||||
const font_size: u8 = font_size: {
|
||||
const font_size: f32 = font_size: {
|
||||
if (!self.app.config.@"window-inherit-font-size") break :font_size 0;
|
||||
break :font_size self.core_surface.font_size.points;
|
||||
};
|
||||
|
@ -250,8 +250,10 @@ fn parseIntoField(
|
||||
0,
|
||||
) catch return error.InvalidValue,
|
||||
|
||||
f64 => std.fmt.parseFloat(
|
||||
f32,
|
||||
f64,
|
||||
=> |Float| std.fmt.parseFloat(
|
||||
Float,
|
||||
value orelse return error.ValueRequired,
|
||||
) catch return error.InvalidValue,
|
||||
|
||||
|
@ -99,8 +99,12 @@ const c = @cImport({
|
||||
/// separate repetitive entries in your config).
|
||||
@"font-feature": RepeatableString = .{},
|
||||
|
||||
/// Font size in points
|
||||
@"font-size": u8 = switch (builtin.os.tag) {
|
||||
/// Font size in points. This value can be a non-integer and the nearest integer
|
||||
/// pixel size will be selected. If you have a high dpi display where 1pt = 2px
|
||||
/// then you can get an odd numbered pixel size by specifying a half point.
|
||||
///
|
||||
/// For example, 13.5pt @ 2px/pt = 27px
|
||||
@"font-size": f32 = switch (builtin.os.tag) {
|
||||
// On macOS we default a little bigger since this tends to look better. This
|
||||
// is purely subjective but this is easy to modify.
|
||||
.macos => 13,
|
||||
|
@ -42,8 +42,8 @@ fn getValue(ptr_raw: *anyopaque, value: anytype) bool {
|
||||
ptr.* = @intCast(value);
|
||||
},
|
||||
|
||||
f32, f64 => {
|
||||
const ptr: *f64 = @ptrCast(@alignCast(ptr_raw));
|
||||
f32, f64 => |Float| {
|
||||
const ptr: *Float = @ptrCast(@alignCast(ptr_raw));
|
||||
ptr.* = @floatCast(value);
|
||||
},
|
||||
|
||||
@ -102,9 +102,9 @@ test "u8" {
|
||||
defer c.deinit();
|
||||
c.@"font-size" = 24;
|
||||
|
||||
var cval: c_uint = undefined;
|
||||
var cval: f32 = undefined;
|
||||
try testing.expect(get(&c, .@"font-size", &cval));
|
||||
try testing.expectEqual(@as(c_uint, 24), cval);
|
||||
try testing.expectEqual(@as(f32, 24), cval);
|
||||
}
|
||||
|
||||
test "enum" {
|
||||
|
@ -371,7 +371,7 @@ pub const Wasm = struct {
|
||||
}
|
||||
}
|
||||
|
||||
export fn deferred_face_load(self: *DeferredFace, pts: u16) void {
|
||||
export fn deferred_face_load(self: *DeferredFace, pts: f32) void {
|
||||
self.load(.{}, .{ .points = pts }) catch |err| {
|
||||
log.warn("error loading deferred face err={}", .{err});
|
||||
return;
|
||||
|
@ -575,7 +575,9 @@ pub const Key = struct {
|
||||
/// Hash the key with the given hasher.
|
||||
pub fn hash(self: Key, hasher: anytype) void {
|
||||
const autoHash = std.hash.autoHash;
|
||||
autoHash(hasher, self.font_size);
|
||||
autoHash(hasher, @as(u32, @bitCast(self.font_size.points)));
|
||||
autoHash(hasher, self.font_size.xdpi);
|
||||
autoHash(hasher, self.font_size.ydpi);
|
||||
autoHash(hasher, self.descriptors.len);
|
||||
for (self.descriptors) |d| d.hash(hasher);
|
||||
self.codepoint_map.hash(hasher);
|
||||
|
@ -49,7 +49,7 @@ pub const Descriptor = struct {
|
||||
/// Font size in points that the font should support. For conversion
|
||||
/// to pixels, we will use 72 DPI for Mac and 96 DPI for everything else.
|
||||
/// (If pixel conversion is necessary, i.e. emoji fonts)
|
||||
size: u16 = 0,
|
||||
size: f32 = 0,
|
||||
|
||||
/// True if we want to search specifically for a font that supports
|
||||
/// specific styles.
|
||||
@ -69,7 +69,7 @@ pub const Descriptor = struct {
|
||||
autoHashStrat(hasher, self.family, .Deep);
|
||||
autoHashStrat(hasher, self.style, .Deep);
|
||||
autoHash(hasher, self.codepoint);
|
||||
autoHash(hasher, self.size);
|
||||
autoHash(hasher, @as(u32, @bitCast(self.size)));
|
||||
autoHash(hasher, self.bold);
|
||||
autoHash(hasher, self.italic);
|
||||
autoHash(hasher, self.monospace);
|
||||
@ -125,7 +125,7 @@ pub const Descriptor = struct {
|
||||
}
|
||||
if (self.size > 0) assert(pat.add(
|
||||
.size,
|
||||
.{ .integer = self.size },
|
||||
.{ .integer = @intFromFloat(@round(self.size)) },
|
||||
false,
|
||||
));
|
||||
if (self.bold) assert(pat.add(
|
||||
@ -183,7 +183,7 @@ pub const Descriptor = struct {
|
||||
|
||||
// Set our size attribute if set
|
||||
if (self.size > 0) {
|
||||
const size32 = @as(i32, @intCast(self.size));
|
||||
const size32: i32 = @intFromFloat(@round(self.size));
|
||||
const size = try macos.foundation.Number.create(
|
||||
.sint32,
|
||||
&size32,
|
||||
|
@ -35,7 +35,7 @@ pub const Options = struct {
|
||||
/// The desired size for loading a font.
|
||||
pub const DesiredSize = struct {
|
||||
// Desired size in points
|
||||
points: u8,
|
||||
points: f32,
|
||||
|
||||
// The DPI of the screen so we can convert points to pixels.
|
||||
xdpi: u16 = default_dpi,
|
||||
@ -44,8 +44,7 @@ pub const DesiredSize = struct {
|
||||
// Converts points to pixels
|
||||
pub fn pixels(self: DesiredSize) u16 {
|
||||
// 1 point = 1/72 inch
|
||||
const points_u16: u16 = @intCast(self.points);
|
||||
return (points_u16 * self.ydpi) / 72;
|
||||
return @intFromFloat(@round((self.points * @as(f32, @floatFromInt(self.ydpi))) / 72));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,7 +137,7 @@ pub const Face = struct {
|
||||
// to what the user requested. Otherwise, we can choose an arbitrary
|
||||
// pixel size.
|
||||
if (face.isScalable()) {
|
||||
const size_26dot6 = @as(i32, @intCast(size.points)) << 6; // mult by 64
|
||||
const size_26dot6: i32 = @intFromFloat(@round(size.points * 64));
|
||||
try face.setCharSize(0, size_26dot6, size.xdpi, size.ydpi);
|
||||
} else try selectSizeNearest(face, size.pixels());
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ pub const Wasm = struct {
|
||||
return face_new_(ptr, len, pts, p) catch null;
|
||||
}
|
||||
|
||||
fn face_new_(ptr: [*]const u8, len: usize, pts: u16, presentation: u16) !*Face {
|
||||
fn face_new_(ptr: [*]const u8, len: usize, pts: f32, presentation: u16) !*Face {
|
||||
var face = try Face.initNamed(
|
||||
alloc,
|
||||
ptr[0..len],
|
||||
|
@ -158,8 +158,8 @@ pub const Action = union(enum) {
|
||||
paste_from_selection: void,
|
||||
|
||||
/// Increase/decrease the font size by a certain amount.
|
||||
increase_font_size: u8,
|
||||
decrease_font_size: u8,
|
||||
increase_font_size: f32,
|
||||
decrease_font_size: f32,
|
||||
|
||||
/// Reset the font size to the original configured size.
|
||||
reset_font_size: void,
|
||||
|
Reference in New Issue
Block a user