mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
font: modify font compiles for freetype
This commit is contained in:
@ -181,7 +181,7 @@ fn loadFontconfig(
|
|||||||
|
|
||||||
var face = try Face.initFile(lib, filename, face_index, opts);
|
var face = try Face.initFile(lib, filename, face_index, opts);
|
||||||
errdefer face.deinit();
|
errdefer face.deinit();
|
||||||
try face.setVariations(fc.variations);
|
try face.setVariations(fc.variations, opts);
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +400,7 @@ test "fontconfig" {
|
|||||||
try testing.expect(n.len > 0);
|
try testing.expect(n.len > 0);
|
||||||
|
|
||||||
// Load it and verify it works
|
// Load it and verify it works
|
||||||
const face = try def.load(lib, .{ .points = 12 });
|
const face = try def.load(lib, .{ .size = .{ .points = 12 } });
|
||||||
try testing.expect(face.glyphIndex(' ') != null);
|
try testing.expect(face.glyphIndex(' ') != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,22 +43,22 @@ pub const Face = struct {
|
|||||||
quirks_disable_default_font_features: bool = false,
|
quirks_disable_default_font_features: bool = false,
|
||||||
|
|
||||||
/// Initialize a new font face with the given source in-memory.
|
/// Initialize a new font face with the given source in-memory.
|
||||||
pub fn initFile(lib: Library, path: [:0]const u8, index: i32, size: font.face.DesiredSize) !Face {
|
pub fn initFile(lib: Library, path: [:0]const u8, index: i32, opts: font.face.Options) !Face {
|
||||||
const face = try lib.lib.initFace(path, index);
|
const face = try lib.lib.initFace(path, index);
|
||||||
errdefer face.deinit();
|
errdefer face.deinit();
|
||||||
return try initFace(lib, face, size);
|
return try initFace(lib, face, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize a new font face with the given source in-memory.
|
/// Initialize a new font face with the given source in-memory.
|
||||||
pub fn init(lib: Library, source: [:0]const u8, size: font.face.DesiredSize) !Face {
|
pub fn init(lib: Library, source: [:0]const u8, opts: font.face.Options) !Face {
|
||||||
const face = try lib.lib.initMemoryFace(source, 0);
|
const face = try lib.lib.initMemoryFace(source, 0);
|
||||||
errdefer face.deinit();
|
errdefer face.deinit();
|
||||||
return try initFace(lib, face, size);
|
return try initFace(lib, face, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initFace(lib: Library, face: freetype.Face, size: font.face.DesiredSize) !Face {
|
fn initFace(lib: Library, face: freetype.Face, opts: font.face.Options) !Face {
|
||||||
try face.selectCharmap(.unicode);
|
try face.selectCharmap(.unicode);
|
||||||
try setSize_(face, size);
|
try setSize_(face, opts.size);
|
||||||
|
|
||||||
var hb_font = try harfbuzz.freetype.createFont(face.handle);
|
var hb_font = try harfbuzz.freetype.createFont(face.handle);
|
||||||
errdefer hb_font.destroy();
|
errdefer hb_font.destroy();
|
||||||
@ -68,7 +68,7 @@ pub const Face = struct {
|
|||||||
.face = face,
|
.face = face,
|
||||||
.hb_font = hb_font,
|
.hb_font = hb_font,
|
||||||
.presentation = if (face.hasColor()) .emoji else .text,
|
.presentation = if (face.hasColor()) .emoji else .text,
|
||||||
.metrics = calcMetrics(face),
|
.metrics = calcMetrics(face, opts.metric_modifiers),
|
||||||
};
|
};
|
||||||
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
||||||
|
|
||||||
@ -127,9 +127,9 @@ pub const Face = struct {
|
|||||||
|
|
||||||
/// Resize the font in-place. If this succeeds, the caller is responsible
|
/// Resize the font in-place. If this succeeds, the caller is responsible
|
||||||
/// for clearing any glyph caches, font atlas data, etc.
|
/// for clearing any glyph caches, font atlas data, etc.
|
||||||
pub fn setSize(self: *Face, size: font.face.DesiredSize) !void {
|
pub fn setSize(self: *Face, opts: font.face.Options) !void {
|
||||||
try setSize_(self.face, size);
|
try setSize_(self.face, opts.size);
|
||||||
self.metrics = calcMetrics(self.face);
|
self.metrics = calcMetrics(self.face, opts.metric_modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setSize_(face: freetype.Face, size: font.face.DesiredSize) !void {
|
fn setSize_(face: freetype.Face, size: font.face.DesiredSize) !void {
|
||||||
@ -165,6 +165,7 @@ pub const Face = struct {
|
|||||||
pub fn setVariations(
|
pub fn setVariations(
|
||||||
self: *Face,
|
self: *Face,
|
||||||
vs: []const font.face.Variation,
|
vs: []const font.face.Variation,
|
||||||
|
opts: font.face.Options,
|
||||||
) !void {
|
) !void {
|
||||||
// If this font doesn't support variations, we can't do anything.
|
// If this font doesn't support variations, we can't do anything.
|
||||||
if (!self.face.hasMultipleMasters() or vs.len == 0) return;
|
if (!self.face.hasMultipleMasters() or vs.len == 0) return;
|
||||||
@ -201,7 +202,7 @@ pub const Face = struct {
|
|||||||
try self.face.setVarDesignCoordinates(coords);
|
try self.face.setVarDesignCoordinates(coords);
|
||||||
|
|
||||||
// We need to recalculate font metrics which may have changed.
|
// We need to recalculate font metrics which may have changed.
|
||||||
self.metrics = calcMetrics(self.face);
|
self.metrics = calcMetrics(self.face, opts.metric_modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the glyph index for the given Unicode code point. If this
|
/// Returns the glyph index for the given Unicode code point. If this
|
||||||
@ -470,7 +471,10 @@ pub const Face = struct {
|
|||||||
/// the faces with DeferredFaces and reload on demand. A Face can't be converted
|
/// the faces with DeferredFaces and reload on demand. A Face can't be converted
|
||||||
/// into a DeferredFace but a Face that comes from a DeferredFace can be
|
/// into a DeferredFace but a Face that comes from a DeferredFace can be
|
||||||
/// deinitialized anytime and reloaded with the deferred face.
|
/// deinitialized anytime and reloaded with the deferred face.
|
||||||
fn calcMetrics(face: freetype.Face) font.face.Metrics {
|
fn calcMetrics(
|
||||||
|
face: freetype.Face,
|
||||||
|
modifiers: ?*const font.face.Metrics.ModifierSet,
|
||||||
|
) font.face.Metrics {
|
||||||
const size_metrics = face.handle.*.size.*.metrics;
|
const size_metrics = face.handle.*.size.*.metrics;
|
||||||
|
|
||||||
// Cell width is calculated by preferring to use 'M' as the width of a
|
// Cell width is calculated by preferring to use 'M' as the width of a
|
||||||
@ -574,7 +578,7 @@ pub const Face = struct {
|
|||||||
.thickness = underline_thickness,
|
.thickness = underline_thickness,
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = font.face.Metrics{
|
var result = font.face.Metrics{
|
||||||
.cell_width = @intFromFloat(cell_width),
|
.cell_width = @intFromFloat(cell_width),
|
||||||
.cell_height = @intFromFloat(cell_height),
|
.cell_height = @intFromFloat(cell_height),
|
||||||
.cell_baseline = @intFromFloat(cell_baseline),
|
.cell_baseline = @intFromFloat(cell_baseline),
|
||||||
@ -583,6 +587,7 @@ pub const Face = struct {
|
|||||||
.strikethrough_position = @intFromFloat(strikethrough.pos),
|
.strikethrough_position = @intFromFloat(strikethrough.pos),
|
||||||
.strikethrough_thickness = @intFromFloat(strikethrough.thickness),
|
.strikethrough_thickness = @intFromFloat(strikethrough.thickness),
|
||||||
};
|
};
|
||||||
|
if (modifiers) |m| result.apply(m.*);
|
||||||
|
|
||||||
// std.log.warn("font metrics={}", .{result});
|
// std.log.warn("font metrics={}", .{result});
|
||||||
|
|
||||||
@ -607,7 +612,11 @@ test {
|
|||||||
var atlas = try font.Atlas.init(alloc, 512, .greyscale);
|
var atlas = try font.Atlas.init(alloc, 512, .greyscale);
|
||||||
defer atlas.deinit(alloc);
|
defer atlas.deinit(alloc);
|
||||||
|
|
||||||
var ft_font = try Face.init(lib, testFont, .{ .points = 12, .xdpi = 96, .ydpi = 96 });
|
var ft_font = try Face.init(
|
||||||
|
lib,
|
||||||
|
testFont,
|
||||||
|
.{ .size = .{ .points = 12, .xdpi = 96, .ydpi = 96 } },
|
||||||
|
);
|
||||||
defer ft_font.deinit();
|
defer ft_font.deinit();
|
||||||
|
|
||||||
try testing.expectEqual(Presentation.text, ft_font.presentation);
|
try testing.expectEqual(Presentation.text, ft_font.presentation);
|
||||||
@ -623,7 +632,7 @@ test {
|
|||||||
const g1 = try ft_font.renderGlyph(alloc, &atlas, ft_font.glyphIndex('A').?, .{});
|
const g1 = try ft_font.renderGlyph(alloc, &atlas, ft_font.glyphIndex('A').?, .{});
|
||||||
try testing.expectEqual(@as(u32, 11), g1.height);
|
try testing.expectEqual(@as(u32, 11), g1.height);
|
||||||
|
|
||||||
try ft_font.setSize(.{ .points = 24, .xdpi = 96, .ydpi = 96 });
|
try ft_font.setSize(.{ .size = .{ .points = 24, .xdpi = 96, .ydpi = 96 } });
|
||||||
const g2 = try ft_font.renderGlyph(alloc, &atlas, ft_font.glyphIndex('A').?, .{});
|
const g2 = try ft_font.renderGlyph(alloc, &atlas, ft_font.glyphIndex('A').?, .{});
|
||||||
try testing.expectEqual(@as(u32, 21), g2.height);
|
try testing.expectEqual(@as(u32, 21), g2.height);
|
||||||
}
|
}
|
||||||
@ -639,7 +648,11 @@ test "color emoji" {
|
|||||||
var atlas = try font.Atlas.init(alloc, 512, .rgba);
|
var atlas = try font.Atlas.init(alloc, 512, .rgba);
|
||||||
defer atlas.deinit(alloc);
|
defer atlas.deinit(alloc);
|
||||||
|
|
||||||
var ft_font = try Face.init(lib, testFont, .{ .points = 12, .xdpi = 96, .ydpi = 96 });
|
var ft_font = try Face.init(
|
||||||
|
lib,
|
||||||
|
testFont,
|
||||||
|
.{ .size = .{ .points = 12, .xdpi = 96, .ydpi = 96 } },
|
||||||
|
);
|
||||||
defer ft_font.deinit();
|
defer ft_font.deinit();
|
||||||
|
|
||||||
try testing.expectEqual(Presentation.emoji, ft_font.presentation);
|
try testing.expectEqual(Presentation.emoji, ft_font.presentation);
|
||||||
@ -665,7 +678,11 @@ test "metrics" {
|
|||||||
var atlas = try font.Atlas.init(alloc, 512, .greyscale);
|
var atlas = try font.Atlas.init(alloc, 512, .greyscale);
|
||||||
defer atlas.deinit(alloc);
|
defer atlas.deinit(alloc);
|
||||||
|
|
||||||
var ft_font = try Face.init(lib, testFont, .{ .points = 12, .xdpi = 96, .ydpi = 96 });
|
var ft_font = try Face.init(
|
||||||
|
lib,
|
||||||
|
testFont,
|
||||||
|
.{ .size = .{ .points = 12, .xdpi = 96, .ydpi = 96 } },
|
||||||
|
);
|
||||||
defer ft_font.deinit();
|
defer ft_font.deinit();
|
||||||
|
|
||||||
try testing.expectEqual(font.face.Metrics{
|
try testing.expectEqual(font.face.Metrics{
|
||||||
@ -679,7 +696,7 @@ test "metrics" {
|
|||||||
}, ft_font.metrics);
|
}, ft_font.metrics);
|
||||||
|
|
||||||
// Resize should change metrics
|
// Resize should change metrics
|
||||||
try ft_font.setSize(.{ .points = 24, .xdpi = 96, .ydpi = 96 });
|
try ft_font.setSize(.{ .size = .{ .points = 24, .xdpi = 96, .ydpi = 96 } });
|
||||||
try testing.expectEqual(font.face.Metrics{
|
try testing.expectEqual(font.face.Metrics{
|
||||||
.cell_width = 16,
|
.cell_width = 16,
|
||||||
.cell_height = 35,
|
.cell_height = 35,
|
||||||
@ -701,7 +718,7 @@ test "mono to rgba" {
|
|||||||
var atlas = try font.Atlas.init(alloc, 512, .rgba);
|
var atlas = try font.Atlas.init(alloc, 512, .rgba);
|
||||||
defer atlas.deinit(alloc);
|
defer atlas.deinit(alloc);
|
||||||
|
|
||||||
var ft_font = try Face.init(lib, testFont, .{ .points = 12 });
|
var ft_font = try Face.init(lib, testFont, .{ .size = .{ .points = 12 } });
|
||||||
defer ft_font.deinit();
|
defer ft_font.deinit();
|
||||||
|
|
||||||
// glyph 3 is mono in Noto
|
// glyph 3 is mono in Noto
|
||||||
|
Reference in New Issue
Block a user