{"id":52246,"date":"2026-06-12T15:34:17","date_gmt":"2026-06-12T19:34:17","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=52246"},"modified":"2026-06-16T12:55:29","modified_gmt":"2026-06-16T16:55:29","slug":"rewriting-apples-truetype-hinting-interpreter-in-swift","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2026\/06\/12\/rewriting-apples-truetype-hinting-interpreter-in-swift\/","title":{"rendered":"Rewriting Apple&rsquo;s TrueType Hinting Interpreter in Swift"},"content":{"rendered":"<p><a href=\"https:\/\/xoxo.zone\/@numist\/116716469017975106\">Scott Perry<\/a>:<\/p>\n<blockquote cite=\"https:\/\/xoxo.zone\/@numist\/116716469017975106\">\n<p>My team rewrote Apple&rsquo;s TrueType hinting interpreter in Swift, ask me anything.<\/p>\n<p>[&#8230;]<\/p>\n<p>I feel like naming just one would be a disservices to all of the features that made this effort possible (C interop, generics, noncopyable\/nonescapable types) but at the end of the day I think the star of the show was the optimizer; despite being faster than the code it replaced, the new code is super readable and that was only possible because the optimizer was able to completely eliminate all of our abstractions.<\/p>\n<\/blockquote>\n\n<p>The new version is faster, but the main motivation was security concerns.<\/p>\n\n<p><a href=\"https:\/\/mastodon.online\/@dmitry_vk\/116716571822155164\">Dmitrii Kalianov<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.online\/@dmitry_vk\/116716571822155164\">\n<p>Is hinting useful\/being used in the days of hi-dpi displays? I was under impression that Apple switched to grayscale anti-aliasing and ditched hinting.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/xoxo.zone\/@numist\/116716601962175503\">Scott Perry<\/a>:<\/p>\n<blockquote cite=\"https:\/\/xoxo.zone\/@numist\/116716601962175503\">\n<p>For the most part hinting isn&rsquo;t really necessary anymore, but thanks to being Turing-complete it has been Hyrum&rsquo;s law-ed by at least one CJK font that uses hinting to lay out strokes in its characters.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.online\/@alexr\/116716796743064373\">Alex Rosenberg<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.online\/@alexr\/116716796743064373\">\n<p>There were three major TrueType implementations at Apple IIRC:<\/p>\n<ul>\n<li>The original 68K one<\/li>\n<li>A rewrite for Copland that lived with ATS\/ATSUI after Copland was cancelled<\/li>\n<li>iPhone shipped one derived from heavily-modified FreeType that was current until today<\/li>\n<\/ul>\n<\/blockquote>\n\n<p><a href=\"https:\/\/xoxo.zone\/@numist\/116717742689971429\">Scott Perry<\/a>:<\/p>\n<blockquote cite=\"https:\/\/xoxo.zone\/@numist\/116717742689971429\">\n<p>One of the axioms for this project was that I wanted my team to write the most boring code possible&mdash;nearly identical structurally to the code it was replacing, because to do otherwise would introduce binary compatibility risk. The other axiom was 100% test coverage for all new code as it landed, with the same units testing both interpreters.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@rosyna\/116716518907236633\">Rosyna Keller<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@rosyna\/116716518907236633\">\n<p>Is the font parsing code itself still C++?<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/xoxo.zone\/@numist\/116716585366522657\">Scott Perry<\/a>:<\/p>\n<blockquote cite=\"https:\/\/xoxo.zone\/@numist\/116716585366522657\">\n<p>There is also a &ldquo;Safe Font Parser&rdquo; for WebKit <a href=\"https:\/\/webkit.org\/blog\/17333\/webkit-features-in-safari-26-0\/#lockdown-mode\">in Lockdown Mode<\/a>, but it supports a subset of all the myriad features provided by font formats.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2026\/06\/09\/glow-leopard\/\">Glow Leopard<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/06\/25\/llama-ttf\/\">llama.ttf<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/06\/29\/a-year-of-windows-kernel-font-fuzzing\/\">A Year of Windows Kernel Font Fuzzing<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/03\/11\/emoji-fonts-use-undocumented-features\/\">Emoji Fonts Use Undocumented Features<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2015\/07\/15\/font-parsing-vulnerabilities\/\">Font Parsing Vulnerabilities<\/a><\/li>\n<\/ul>\n\n<p id=\"rewriting-apples-truetype-hinting-interpreter-in-swift-update-2026-06-16\">Update (<a href=\"#rewriting-apples-truetype-hinting-interpreter-in-swift-update-2026-06-16\">2026-06-16<\/a>): <a href=\"https:\/\/www.swift.org\/blog\/migrating-truetype-hinting-to-swift\/\">Scott Perry<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=48508726\">Hacker News<\/a>):<\/p>\n<blockquote cite=\"https:\/\/www.swift.org\/blog\/migrating-truetype-hinting-to-swift\/\">\n<p>Font parsers process data from untrusted sources, making the TrueType hinting interpreter a security-critical attack surface. To make the format more resilient on Apple platforms, we rewrote its hinting interpreter from C to <a href=\"https:\/\/docs.swift.org\/compiler\/documentation\/diagnostics\/strict-memory-safety\/\">memory-safe<\/a> Swift for the Fall 2025 releases. In addition to memory safety, we also improved performance: on average, our Swift interpreter runs 13% faster than the C interpreter it replaced.<\/p>\n<p>[&#8230;]<\/p>\n<p>Binary compatibility was crucial for this project to succeed: existing programs had to continue to function the same as they did before, effectively unaware that a new implementation was in place. This means not just interface compatibility but pixel-identical glyph rendering as well, relative to the C implementation.<\/p>\n<p>[&#8230;]<\/p>\n<p>To ensure correctness, we developed two test suites. The first was a unit test suite that can target both implementations, providing exhaustive (99.7%) code coverage for both. This suite is included with the open source release of the Swift interpreter.<\/p>\n<p>Then, to represent real-world workloads, we used a fuzzer to minimize a corpus of 10 million PDF files down to 4,200 without any loss of code coverage.<\/p>\n<p>[&#8230;]<\/p>\n<p>Following WebKit&rsquo;s <a href=\"https:\/\/github.com\/WebKit\/WebKit\/wiki\/Safer-Swift-Guidelines\">Safer Swift Guidelines<\/a>, the example below demonstrates how to wrap a bridged structure from C in a projection type that uses <a href=\"https:\/\/github.com\/apple\/swift-collections\/blob\/main\/Sources\/ContainersPreview\/Types\/Ref.swift\"><code>Ref<\/code><\/a> for lifetime safety, brokers bounds-safe access to the underlying data, and returns idiomatic Swift types to its callers.<\/p>\n<\/blockquote>\n\n<p>The interpreter source is <a href=\"https:\/\/github.com\/apple\/truetype-hinting-interpreter-example\">on GitHub<\/a>.<\/p>\n\n<p><a href=\"https:\/\/x.com\/krzyzanowskim\/status\/2065784084236771716\">Marcin Krzyzanowski<\/a>:<\/p>\n<blockquote cite=\"https:\/\/x.com\/krzyzanowskim\/status\/2065784084236771716\">\n<p><code>@_lifetime(copy code, copy twilightZone, copy glyphZone)<\/code><\/p>\n<\/blockquote>\n\n<p>See also: Phillip Tennen&rsquo;s <a href=\"https:\/\/axleos.com\/writing-a-truetype-font-renderer\/\">Writing a TrueType font renderer<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=38833747\">Hacker News<\/a>).<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2025\/03\/19\/lifetime-dependencies-in-swift-6-2-and-beyond\/\">Lifetime Dependencies in Swift 6.2 and Beyond<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Scott Perry: My team rewrote Apple&rsquo;s TrueType hinting interpreter in Swift, ask me anything. [&#8230;] I feel like naming just one would be a disservices to all of the features that made this effort possible (C interop, generics, noncopyable\/nonescapable types) but at the end of the day I think the star of the show was [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2026-06-12T19:34:22Z","apple_news_api_id":"36024eb8-6379-4393-a847-5e3f02fba175","apple_news_api_modified_at":"2026-06-16T16:55:34Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/ANgJOuGN5Q5OoR14_AvuhdQ","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[55,104,2817,31,2887,30,2784,571,74,138,270,71,48,2074,901,134],"class_list":["post-52246","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-arc","tag-fontsmoothing","tag-interpreter","tag-ios","tag-ios-27","tag-mac","tag-macos-27","tag-memory-management","tag-opensource","tag-optimization","tag-parser","tag-programming","tag-security","tag-software-rewrite","tag-swift-programming-language","tag-typography"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/52246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=52246"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/52246\/revisions"}],"predecessor-version":[{"id":52261,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/52246\/revisions\/52261"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=52246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=52246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=52246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}