mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Enable bitmap font usage under CoreText (#4115)
macOS bitmap-only fonts are a poorly documented format, which are often distributed as `.dfont` or `.dfon` files. They use a 'bhed' table in place of the usual 'head', but the table format is byte-identical, so enabling the use of bitmap-only fonts only requires us to properly fetch this table while calculating metrics. ref: https://fontforge.org/docs/techref/bitmaponlysfnt.html Reverts #3550 for obvious reasons, and may close issue #2168 because this should now mean that bitmap fonts are properly supported under both font backends due to #3837 - unless `otb` fonts are still not properly supported under FreeType (they are not supported under CoreText because CoreText does not know how to handle them). I tested this change with the `.dfont` distribution of [Cozette](https://github.com/slavfox/Cozette) v1.25.2 and saw no visual issues.
This commit is contained in:
@ -362,16 +362,9 @@ pub const CoreText = struct {
|
|||||||
const list = set.createMatchingFontDescriptors();
|
const list = set.createMatchingFontDescriptors();
|
||||||
defer list.release();
|
defer list.release();
|
||||||
|
|
||||||
// Bring the list of descriptors in to zig land
|
|
||||||
var zig_list = try copyMatchingDescriptors(alloc, list);
|
|
||||||
errdefer alloc.free(zig_list);
|
|
||||||
|
|
||||||
// Filter them. We don't use `CTFontCollectionSetExclusionDescriptors`
|
|
||||||
// to do this because that requires a mutable collection. This way is
|
|
||||||
// much more straight forward.
|
|
||||||
zig_list = try alloc.realloc(zig_list, filterDescriptors(zig_list));
|
|
||||||
|
|
||||||
// Sort our descriptors
|
// Sort our descriptors
|
||||||
|
const zig_list = try copyMatchingDescriptors(alloc, list);
|
||||||
|
errdefer alloc.free(zig_list);
|
||||||
sortMatchingDescriptors(&desc, zig_list);
|
sortMatchingDescriptors(&desc, zig_list);
|
||||||
|
|
||||||
return DiscoverIterator{
|
return DiscoverIterator{
|
||||||
@ -558,47 +551,13 @@ pub const CoreText = struct {
|
|||||||
for (0..result.len) |i| {
|
for (0..result.len) |i| {
|
||||||
result[i] = list.getValueAtIndex(macos.text.FontDescriptor, i);
|
result[i] = list.getValueAtIndex(macos.text.FontDescriptor, i);
|
||||||
|
|
||||||
// We need to retain because once the list
|
// We need to retain becauseonce the list is freed it will
|
||||||
// is freed it will release all its members.
|
// release all its members.
|
||||||
result[i].retain();
|
result[i].retain();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Filter any descriptors out of the list that aren't acceptable for
|
|
||||||
/// some reason or another (e.g. the font isn't in a format we can handle).
|
|
||||||
///
|
|
||||||
/// Invalid descriptors are filled in from the end of
|
|
||||||
/// the list and the new length for the list is returned.
|
|
||||||
fn filterDescriptors(list: []*macos.text.FontDescriptor) usize {
|
|
||||||
var end = list.len;
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < end) {
|
|
||||||
if (validDescriptor(list[i])) {
|
|
||||||
i += 1;
|
|
||||||
} else {
|
|
||||||
list[i].release();
|
|
||||||
end -= 1;
|
|
||||||
list[i] = list[end];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Used by `filterDescriptors` to decide whether a descriptor is valid.
|
|
||||||
fn validDescriptor(desc: *macos.text.FontDescriptor) bool {
|
|
||||||
if (desc.copyAttribute(macos.text.FontAttribute.format)) |format| {
|
|
||||||
defer format.release();
|
|
||||||
var value: c_int = undefined;
|
|
||||||
assert(format.getValue(.int, &value));
|
|
||||||
|
|
||||||
// Bitmap fonts are not currently supported.
|
|
||||||
if (value == macos.text.c.kCTFontFormatBitmap) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sortMatchingDescriptors(
|
fn sortMatchingDescriptors(
|
||||||
desc: *const Descriptor,
|
desc: *const Descriptor,
|
||||||
list: []*macos.text.FontDescriptor,
|
list: []*macos.text.FontDescriptor,
|
||||||
|
@ -515,8 +515,17 @@ pub const Face = struct {
|
|||||||
fn calcMetrics(ct_font: *macos.text.Font) CalcMetricsError!font.face.Metrics {
|
fn calcMetrics(ct_font: *macos.text.Font) CalcMetricsError!font.face.Metrics {
|
||||||
// Read the 'head' table out of the font data.
|
// Read the 'head' table out of the font data.
|
||||||
const head: opentype.Head = head: {
|
const head: opentype.Head = head: {
|
||||||
const tag = macos.text.FontTableTag.init("head");
|
// macOS bitmap-only fonts use a 'bhed' tag rather than 'head', but
|
||||||
const data = ct_font.copyTable(tag) orelse return error.CopyTableError;
|
// the table format is byte-identical to the 'head' table, so if we
|
||||||
|
// can't find 'head' we try 'bhed' instead before failing.
|
||||||
|
//
|
||||||
|
// ref: https://fontforge.org/docs/techref/bitmaponlysfnt.html
|
||||||
|
const head_tag = macos.text.FontTableTag.init("head");
|
||||||
|
const bhed_tag = macos.text.FontTableTag.init("bhed");
|
||||||
|
const data =
|
||||||
|
ct_font.copyTable(head_tag) orelse
|
||||||
|
ct_font.copyTable(bhed_tag) orelse
|
||||||
|
return error.CopyTableError;
|
||||||
defer data.release();
|
defer data.release();
|
||||||
const ptr = data.getPointer();
|
const ptr = data.getPointer();
|
||||||
const len = data.getLength();
|
const len = data.getLength();
|
||||||
|
Reference in New Issue
Block a user