summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorQwerasd <qwerasd205@users.noreply.github.com>2025-10-02 15:01:44 -0600
committerQwerasd <qwerasd205@users.noreply.github.com>2025-10-02 15:32:21 -0600
commitefc6e0d6738d3ff070422db1512eb1b9f91b278f (patch)
tree881e0432a420bf3c383c51876e09450434c5a693 /pkg
parentd6063428bd9b58ca377b576eb0638be72afaa933 (diff)
fix(font/coretext): always prevent shaper from emitting rtl
The solution we had before worked in most cases but there were some which caused problems still. This is what HarfBuzz's CoreText shaper backend does, it uses a CTTypesetter with the forced embedding level attribute. This fixes the failure case I found that was causing non- monotonic outputs which can have all sorts of unexpected results, and causes a crash in Debug modes because we assert the monotonicity while rendering.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/macos/text.zig2
-rw-r--r--pkg/macos/text/typesetter.zig36
2 files changed, 38 insertions, 0 deletions
diff --git a/pkg/macos/text.zig b/pkg/macos/text.zig
index 0589f8692..bfaa388b3 100644
--- a/pkg/macos/text.zig
+++ b/pkg/macos/text.zig
@@ -4,6 +4,7 @@ const font_descriptor = @import("text/font_descriptor.zig");
const font_manager = @import("text/font_manager.zig");
const frame = @import("text/frame.zig");
const framesetter = @import("text/framesetter.zig");
+const typesetter = @import("text/typesetter.zig");
const line = @import("text/line.zig");
const paragraph_style = @import("text/paragraph_style.zig");
const run = @import("text/run.zig");
@@ -23,6 +24,7 @@ pub const createFontDescriptorsFromData = font_manager.createFontDescriptorsFrom
pub const createFontDescriptorFromData = font_manager.createFontDescriptorFromData;
pub const Frame = frame.Frame;
pub const Framesetter = framesetter.Framesetter;
+pub const Typesetter = typesetter.Typesetter;
pub const Line = line.Line;
pub const ParagraphStyle = paragraph_style.ParagraphStyle;
pub const ParagraphStyleSetting = paragraph_style.ParagraphStyleSetting;
diff --git a/pkg/macos/text/typesetter.zig b/pkg/macos/text/typesetter.zig
new file mode 100644
index 000000000..dc07df980
--- /dev/null
+++ b/pkg/macos/text/typesetter.zig
@@ -0,0 +1,36 @@
+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").c;
+
+pub const Typesetter = opaque {
+ pub fn createWithAttributedStringAndOptions(
+ str: *foundation.AttributedString,
+ opts: *foundation.Dictionary,
+ ) Allocator.Error!*Typesetter {
+ return @as(
+ ?*Typesetter,
+ @ptrFromInt(@intFromPtr(c.CTTypesetterCreateWithAttributedStringAndOptions(
+ @ptrCast(str),
+ @ptrCast(opts),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Typesetter) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn createLine(
+ self: *Typesetter,
+ range: foundation.c.CFRange,
+ ) *text.Line {
+ return @ptrFromInt(@intFromPtr(c.CTTypesetterCreateLine(
+ @ptrCast(self),
+ range,
+ )));
+ }
+};