font/coretext: force LTR shaping

This commit is contained in:
Mitchell Hashimoto
2024-05-08 10:11:57 -07:00
parent eeb7f7aa02
commit 1cb70d6e40
3 changed files with 47 additions and 7 deletions

View File

@@ -34,10 +34,13 @@ pub const ParagraphStyleSpecifier = enum(c_uint) {
base_writing_direction = 13, base_writing_direction = 13,
}; };
pub const WritingDirection = enum(i8) { /// https://developer.apple.com/documentation/uikit/nswritingdirectionattributename?language=objc
pub const WritingDirection = enum(c_int) {
natural = -1, natural = -1,
left_to_right = 0, ltr = 0,
right_to_left = 1, rtl = 1,
lro = 2,
rlo = 3,
}; };
test ParagraphStyle { test ParagraphStyle {

View File

@@ -4,11 +4,13 @@ const c = @import("c.zig");
pub const StringAttribute = enum { pub const StringAttribute = enum {
font, font,
paragraph_style, paragraph_style,
writing_direction,
pub fn key(self: StringAttribute) *foundation.String { pub fn key(self: StringAttribute) *foundation.String {
return @ptrFromInt(@intFromPtr(switch (self) { return @ptrFromInt(@intFromPtr(switch (self) {
.font => c.kCTFontAttributeName, .font => c.kCTFontAttributeName,
.paragraph_style => c.kCTParagraphStyleAttributeName, .paragraph_style => c.kCTParagraphStyleAttributeName,
.writing_direction => c.kCTWritingDirectionAttributeName,
})); }));
} }
}; };

View File

@@ -44,6 +44,11 @@ pub const Shaper = struct {
/// The shared memory used for shaping results. /// The shared memory used for shaping results.
cell_buf: CellBuf, cell_buf: CellBuf,
/// The cached writing direction value for shaping. This isn't
/// configurable we just use this as a cache to avoid creating
/// and releasing many objects when shaping.
writing_direction: *macos.foundation.Array,
const CellBuf = std.ArrayListUnmanaged(font.shape.Cell); const CellBuf = std.ArrayListUnmanaged(font.shape.Cell);
const CodepointList = std.ArrayListUnmanaged(Codepoint); const CodepointList = std.ArrayListUnmanaged(Codepoint);
const Codepoint = struct { const Codepoint = struct {
@@ -172,14 +177,37 @@ pub const Shaper = struct {
for (hardcoded_features) |name| try feats.append(name); for (hardcoded_features) |name| try feats.append(name);
for (opts.features) |name| try feats.append(name); for (opts.features) |name| try feats.append(name);
const run_state = try RunState.init(); var run_state = try RunState.init();
errdefer run_state.deinit(); errdefer run_state.deinit(alloc);
// For now we only support LTR text. If we shape RTL text then
// rendering will be very wrong so we need to explicitly force
// LTR no matter what.
//
// See: https://github.com/mitchellh/ghostty/issues/1737
// See: https://github.com/mitchellh/ghostty/issues/1442
const writing_direction = array: {
const dir: macos.text.WritingDirection = .lro;
const num = try macos.foundation.Number.create(
.int,
&@intFromEnum(dir),
);
defer num.release();
var arr_init = [_]*const macos.foundation.Number{num};
break :array try macos.foundation.Array.create(
macos.foundation.Number,
&arr_init,
);
};
errdefer writing_direction.release();
return Shaper{ return Shaper{
.alloc = alloc, .alloc = alloc,
.cell_buf = .{}, .cell_buf = .{},
.run_state = run_state, .run_state = run_state,
.features = feats, .features = feats,
.writing_direction = writing_direction,
}; };
} }
@@ -187,6 +215,7 @@ pub const Shaper = struct {
self.cell_buf.deinit(self.alloc); self.cell_buf.deinit(self.alloc);
self.run_state.deinit(self.alloc); self.run_state.deinit(self.alloc);
self.features.deinit(); self.features.deinit();
self.writing_direction.release();
} }
pub fn runIterator( pub fn runIterator(
@@ -276,8 +305,14 @@ pub const Shaper = struct {
// Get our font and use that get the attributes to set for the // Get our font and use that get the attributes to set for the
// attributed string so the whole string uses the same font. // attributed string so the whole string uses the same font.
const attr_dict = dict: { const attr_dict = dict: {
var keys = [_]?*const anyopaque{macos.text.StringAttribute.font.key()}; var keys = [_]?*const anyopaque{
var values = [_]?*const anyopaque{run_font}; macos.text.StringAttribute.font.key(),
macos.text.StringAttribute.writing_direction.key(),
};
var values = [_]?*const anyopaque{
run_font,
self.writing_direction,
};
break :dict try macos.foundation.Dictionary.create(&keys, &values); break :dict try macos.foundation.Dictionary.create(&keys, &values);
}; };
defer attr_dict.release(); defer attr_dict.release();