mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-21 19:26:09 +03:00
Merge pull request #1740 from mitchellh/ct-rtl
coretext: force LTR font shaping
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
.{
|
.{
|
||||||
.name = "macos",
|
.name = "macos",
|
||||||
.version = "0.1.0",
|
.version = "0.1.0",
|
||||||
|
.paths = .{""},
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.apple_sdk = .{ .path = "../apple-sdk" },
|
.apple_sdk = .{ .path = "../apple-sdk" },
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,7 @@ pub usingnamespace @import("text/font_manager.zig");
|
|||||||
pub usingnamespace @import("text/frame.zig");
|
pub usingnamespace @import("text/frame.zig");
|
||||||
pub usingnamespace @import("text/framesetter.zig");
|
pub usingnamespace @import("text/framesetter.zig");
|
||||||
pub usingnamespace @import("text/line.zig");
|
pub usingnamespace @import("text/line.zig");
|
||||||
|
pub usingnamespace @import("text/paragraph_style.zig");
|
||||||
pub usingnamespace @import("text/run.zig");
|
pub usingnamespace @import("text/run.zig");
|
||||||
pub usingnamespace @import("text/stylized_strings.zig");
|
pub usingnamespace @import("text/stylized_strings.zig");
|
||||||
|
|
||||||
|
49
pkg/macos/text/paragraph_style.zig
Normal file
49
pkg/macos/text/paragraph_style.zig
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const foundation = @import("../foundation.zig");
|
||||||
|
const graphics = @import("../graphics.zig");
|
||||||
|
const text = @import("../text.zig");
|
||||||
|
const c = @import("c.zig");
|
||||||
|
|
||||||
|
// https://developer.apple.com/documentation/coretext/ctparagraphstyle?language=objc
|
||||||
|
pub const ParagraphStyle = opaque {
|
||||||
|
pub fn create(
|
||||||
|
settings: []const ParagraphStyleSetting,
|
||||||
|
) Allocator.Error!*ParagraphStyle {
|
||||||
|
return @ptrCast(@constCast(c.CTParagraphStyleCreate(
|
||||||
|
@ptrCast(settings.ptr),
|
||||||
|
settings.len,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn release(self: *ParagraphStyle) void {
|
||||||
|
foundation.CFRelease(self);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// https://developer.apple.com/documentation/coretext/ctparagraphstylesetting?language=objc
|
||||||
|
pub const ParagraphStyleSetting = extern struct {
|
||||||
|
spec: ParagraphStyleSpecifier,
|
||||||
|
value_size: usize,
|
||||||
|
value: *const anyopaque,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// https://developer.apple.com/documentation/coretext/ctparagraphstylespecifier?language=objc
|
||||||
|
pub const ParagraphStyleSpecifier = enum(c_uint) {
|
||||||
|
base_writing_direction = 13,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// https://developer.apple.com/documentation/uikit/nswritingdirectionattributename?language=objc
|
||||||
|
pub const WritingDirection = enum(c_int) {
|
||||||
|
natural = -1,
|
||||||
|
ltr = 0,
|
||||||
|
rtl = 1,
|
||||||
|
lro = 2,
|
||||||
|
rlo = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
test ParagraphStyle {
|
||||||
|
const p = try ParagraphStyle.create(&.{});
|
||||||
|
defer p.release();
|
||||||
|
}
|
@ -3,10 +3,14 @@ const c = @import("c.zig");
|
|||||||
|
|
||||||
pub const StringAttribute = enum {
|
pub const StringAttribute = enum {
|
||||||
font,
|
font,
|
||||||
|
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,
|
||||||
|
.writing_direction => c.kCTWritingDirectionAttributeName,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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();
|
||||||
|
Reference in New Issue
Block a user