{"id":25067009,"url":"https://github.com/shoyamanishi/sdfontapple","last_synced_at":"2025-05-07T21:34:23.045Z","repository":{"id":187800797,"uuid":"557045111","full_name":"ShoYamanishi/SDFontApple","owner":"ShoYamanishi","description":"A signed distant font generator and a runtime helper for MacOSX and iOS that utilize Metal and CoreText.","archived":false,"fork":false,"pushed_at":"2024-10-06T11:09:44.000Z","size":1532,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-31T14:18:03.350Z","etag":null,"topics":["font","ios","macos","metal"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ShoYamanishi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-25T01:31:22.000Z","updated_at":"2025-03-20T20:57:03.000Z","dependencies_parsed_at":"2025-03-31T14:18:10.929Z","dependency_job_id":"03dc82c7-427e-4836-9776-d000488c3d89","html_url":"https://github.com/ShoYamanishi/SDFontApple","commit_stats":null,"previous_names":["shoyamanishi/sdfontapple"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoYamanishi%2FSDFontApple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoYamanishi%2FSDFontApple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoYamanishi%2FSDFontApple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoYamanishi%2FSDFontApple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ShoYamanishi","download_url":"https://codeload.github.com/ShoYamanishi/SDFontApple/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252957781,"owners_count":21831550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["font","ios","macos","metal"],"created_at":"2025-02-06T20:29:02.565Z","updated_at":"2025-05-07T21:34:23.018Z","avatar_url":"https://github.com/ShoYamanishi.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SDFontApple\n\u003ca href=\"doc/drop_shadow.png\"\u003e \u003cimg src=\"doc/drop_shadow.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\nA signed distant font generator and a runtime helper for MacOSX and iOS that utilize [Metal](https://developer.apple.com/documentation/metal) and [CoreText](https://developer.apple.com/documentation/coretext).\nThis is a retake to my original [SDFont](https://github.com/ShoYamanishi/SDFont), which depends on [OpenGL](https://www.opengl.org/) \u0026 [FreeType](https://freetype.org/).\n\nSDFontApple comes with the following components:\n\n- **SDFont.xcframework**: The main framework for macos and iOS.\n- **sdfontgen**: The command-line font generator for macos.\n- **SWOpeningRoll**: A sample program for macos and iOS that shows the 3D opening roll of Star Wars film in the signed distance fonts.\n- **SWOpeningRollAR**: A sample program for iOS that shows the opening roll in the AR environment anchored to the tapped position in the space.\n\n\u003ca href=\"doc/StarWarsMacBanner.png\"\u003e \u003cimg src=\"doc/StarWarsMacBanner.png\" height=\"200\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/StarWarsARBanner.png\"\u003e \u003cimg src=\"doc/StarWarsARBanner.png\" height=\"200\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n[Demo Video 1](https://youtu.be/KLexTjHEyoY) : Video capture from the demo App SWOpeningRoll on Mac mini M1 2020.\n\n[Demo Video 2](https://youtube.com/shorts/o9dAm15HhKc) : Video capture from the demo App SWOpeningRollAR on iPhone 13 mini.\n\n[Demo Video 3](https://youtu.be/wMqBkdNkqu4) : Demo Video of Sticky Notes implemented in AR together with the built-in speech recognizer.\n\n# Table of Contents\n- [About Signed Distance Fonts](#about-signed-distance-fonts)\n- [Advantages of Signed Distance Fonts](#advantages-of-signed-distance-fonts)\n  - [Typographic Effects](#typographic-effects)\n- [Build \u0026 Instsall](#build--instsall)\n  - [SDFont Framework](#sdfont-framework)\n  - [Command-line generator: sdfontgen](#command-line-generator-sdfontgen)\n  - [Demo App: SWOpeningRoll](#demo-app-swopeningroll)\n  - [Demo App: SWOpeningRollAR](#demo-app-swopeningrollar)\n- [Usage](#usage)\n  - [Find the List of Available Fonts.](#find-the-list-of-available-fonts)\n  - [Generating Signed Distance Fonts on Mac Off-line.](#generating-signed-distance-fonts-on-mac-off-line)\n  - [Generating Signed Distance Fonts at Runtime.](#generating-signed-distance-fonts-at-runtime)\n  - [Using the Signed Distance Fonts for Rendering.](#using-the-signed-distance-fonts-for-rendering)\n- [License](#license)\n- [Contact](#contact)\n- [Background](#background)\n- [Acknowledgment](#acknowledgment)\n\n# About Signed Distance Fonts\nThis is an awesome technique to render typefaces by GPU. It was originally proposed by Chris Green of Valve at SIGGRAPH 2007\n[[PDF]](https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf).\nIn the normal font rendering by CPU, say, with [CoreText](https://developer.apple.com/documentation/coretext) or [FreeType](https://freetype.org/), the shapes of the glyphs are stored in the vector graphics format (Bezier curves), and at runtime, they are converted to a bitmap for a specific font size.\n\nOn the contrary, the signed distant fonts techinque generates a texture for the glyphs in the signed distance representation in which the value of each pixel represents the distance from the closest glyph boundary. The glyphs of the same typeface are usually packed into a single texture, and each glyph gets the corresponding rectangular bounding box in the texture coordinates. This texture generation is usually done as an off-line processing.\nAt runtime, the glyphs are rendered simply by quads specifying the bounding boxes in the texture uv-coordinates to the GPU.\n\nThe following image shows a sample signed distance texture. It shows the first 256 glyphs in Helvetica font with the inner and outer bounding boxes for each glyph. (Click to magnify.)\n\n\u003ca href=\"doc/Helvetica.png\"\u003e \u003cimg src=\"doc/Helvetica.png\" height=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n# Advantages of Signed Distance Fonts\n\n- ✅ Good visual quality for the wide range of font sizes with a single texture file. No noticeable jagged edges when magnified.\n- ✅ Little overhead for rendering at runtime. No need to convert the vector graphics to a bitmap, as the glyphs have been in a way already rendered to the texture.\n- ✅ Dynamic transformation of the typefaces at runtime. You can move, scale, rotate, sheer the typefaces just like the geometric transfomation for the other rendered objects.\n- ✅ Typographic effects by the fragment shader. They can be achieved by applying a function to the sampled value from the signed distance texture. In the following sub-section you can see some sample effects with their corresponding fragment functions.\n\n## Typographic Effects\nYou can change the appearance of the rendered typefaces by changing the output alpha value in the fragment shader.\nThe following shows some notable effects with their corresponding functions to alter the alpha value.\nPlease see [the fragment shader code](SWOpeningRoll/rendering/shaders/default_renderer.metal) for details.\n\n### Step\n\u003ca href=\"doc/step.png\"\u003e \u003cimg src=\"doc/step.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_step.png\"\u003e \u003cimg src=\"doc/plot_step.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Smooth Step\n\u003ca href=\"doc/smooth_step.png\"\u003e \u003cimg src=\"doc/smooth_step.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_smooth_step.png\"\u003e \u003cimg src=\"doc/plot_smooth_step.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Slope Step\n\u003ca href=\"doc/slope_step.png\"\u003e \u003cimg src=\"doc/slope_step.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_slope_step.png\"\u003e \u003cimg src=\"doc/plot_slope_step.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Pass-through\n\u003ca href=\"doc/pass_through.png\"\u003e \u003cimg src=\"doc/pass_through.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_pass_through.png\"\u003e \u003cimg src=\"doc/plot_pass_through.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Trapezoid\n\u003ca href=\"doc/trapezoid.png\"\u003e \u003cimg src=\"doc/trapezoid.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_trapezoid.png\"\u003e \u003cimg src=\"doc/plot_trapezoid.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Twin Peaks\n\u003ca href=\"doc/twin_peaks.png\"\u003e \u003cimg src=\"doc/twin_peaks.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_twin_peaks.png\"\u003e \u003cimg src=\"doc/plot_twin_peaks.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Halo Effect\n\u003ca href=\"doc/halo.png\"\u003e \u003cimg src=\"doc/halo.png\" width=\"500\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\u003ca href=\"doc/plot_halo.png\"\u003e \u003cimg src=\"doc/plot_halo.png\" width=\"300\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\n### Drop Shadow\n\u003ca href=\"doc/drop_shadow.png\"\u003e \u003cimg src=\"doc/drop_shadow.png\" width=\"800\" alt=\"Overview\"/\u003e\u003c/a\u003e\n\nA drop shadow can be implemented by two render passes. In the example above, the drop shadow is rendered first by the smooth step shader in black, and then the typeface is rendered by another smooth step shader with a narrower band in brown.\n\n# Build \u0026 Instsall\n\n## SDFont Framework\n1. Open `SDFontApple/SDFont/SDFont.xcodeproj`, go to the project `SDFont`, and select the target `SDFont`.\n2. Set Signing \u0026 Capabilities to your environment for your developer ID.\n3. Select the scheme `SDFont`, and the taret to your device (ex. My Mac or iPhone 13 mini), and build.\n\nAlternatively, after the signing \u0026 capabilities have been setup for you, you can also run the build process with the following batch script.\n1. Open a terminal\n2. `$ xcode-select -s \u003cpath/to/Xcode.app\u003e` first if necessary.\n3. `$ cd SDFontApple/SDFont`\n4. `$ ./build_all.sh`\n5. During the execution of the shell script you will be asked if you want to install the macos version to */Library/Frameworks*.\n```\nDo you wish to install SDFont.framework--macosx to this Mac under /Library/Frameworks?\n```\nAnswer Y/n.\n\nThis will create *build/SDFont.scframework*, *build/sdfontgen*, and *./SDFont.doccarchive*.\n\n## Command-line generator: sdfontgen\n1. Open `SDFontApple/SDFont/SDFont.xcodeproj`, go to the project `SDFont`, and select the target `sdfontgen`.\n2. Set Signing \u0026 Capabilities to your environment for your developer ID.\n3. Select the scheme `sdfontgen`, and the target to your device (ex. My Mac), and build.\n\n## Demo App: SWOpeningRoll\n1. Open `SDFontApple/SWOpeningRoll/SWOpeningRoll.xcodeproj`, go to the project `SWOpeningRoll`, and select the target `SWOpeningRollmacos` for macOS or the target 'SWOpeningRollios` for iOS.\n2. Set Signing \u0026 Capabilities to your environment for your developer ID.\n3. Adjust the path to the framework SDFont if necessary.\n4. Select the scheme `SWOpeningRollmacos` or `SWOpeningRollios`, and the target to your device (ex. My Mac or iPhone 13 mini), and build \u0026 run.\n\n## Demo App: SWOpeningRollAR\n1. Open `SDFontApple/SWOpeningRollAR/SWOpeningRollAR.xcodeproj`, go to the project `SWOpeningRollAR`, and select the target `SWOpeningRollAR`.\n2. Set Signing \u0026 Capabilities to your environment for your developer ID.\n3. Adjust the path to the framework SDFont if necessary.\n4. Select the scheme `SWOpeningRollAR`, and the target to your device (ex. iPhone 13 mini), and build \u0026 run.\n\n# Usage\nAn API reference is available in docc archive, which can be found in `SDFontApple/SDFont/SDFont.doccarchive` if you have run `SDFontApple/SDFont/build_all.sh`.\n\n## Find the List of Available Fonts.\nOn macos, run `sdfontgen -showfontlist`.\n```\nmrbean@Beans-Mini % pwd                      \n/Users/mrbean/repos/SDFontApple/SDFont/build\nmrbean@Beans-Mini % ./sdfontgen -showfontlist\n    [..SFCompactRounded-Regular]\n    [.AlBayanPUA]\n    [.AlBayanPUA-Bold]\n    [.AlNilePUA]\n...\n    [YuppySC-Regular]\n    [YuppyTC-Regular]\n    [ZapfDingbatsITC]\n    [Zapfino]\n```\n\nFor iOS and macos, you can get the list programatically by calling the following API function.\n```\nSDFontRuntimeHelper {\n    static func listAvailableFonts() -\u003e [String]\n}\n```\nPlease consult [https://developer.apple.com/fonts/](https://developer.apple.com/fonts/) for the official information from Apple.\n\n## Generating Signed Distance Fonts on Mac Off-line.\nYou can use the command-line tool `sdfontgen`.\n\n```\nmrbean@Beans-Mini % ./sdfontgen -h           \n\nsdfontgen : command-line signed distance font generator for macos.\n\noptions\n\n    -h/--help: show this message\n\n    -verbose: show INFO and WARNING messages\n\n    -showfontlist: show the list of the fonts in the system\n\n    -fontname \u003cfontname\u003e: name of the font, preferrably in Postscript name,\n        e.g. -fontname Helvetica\n\n    -glyphnumcutoff \u003cinteger num\u003e: maximum index of the glyphs to process.\n\n    -spread \u003creal num\u003e: specifies the margin around each glyph in the fraction\n        of the average glyph width and height. Usually within the range of [0.1,0.2].\n\n    -upsample \u003cinteger num\u003e: specifies the fontsize in the integer multiple to the original\n        font size, in order to sample the glyph bitmaps. The original fontsize\n        is determined as the best size to pack the glyphs to the output texture of\n        the specified size. For example if the side length of the output texture\n        is 2048, and the font is Helvecita with about 2000 glyphs, then the best\n        font size will be 43.0. If the upsample factor is 4, then the font size 172.0\n        is used to sample the glyph bitmap and to generate signed distance.\n        Usually within the range of [2,4].\n\n    -texturesize \u003cinteger num\u003e: the length of the sides in pixels of the output texture.\n        Usually within the range of [512,4096].\n\n    -outputpath \u003cpath\u003e: the path in which the output PNG and JSON files are stored.\n        If the outputpath is \"/path/to/output\", and fontname is \"Helvetica\",\n        then the output files will be /path/to/output/Helvetica.png and /path/to/output/Helvetica.json.\n\nNOTES on -glyphnumcutoff:\n  This is useful for example, if you want a small texture size for some games,\n  and you know you use only the first 256 glyphs. However, you should be careful\n  as the CoreText's typesetter may select a ligature glyph such as 'fi' and 'ff'\n  whose indices are above 255, even if you use only English alphabets.\n```\n\n### Sample Usage\nFor a Signed Distance font for Helvetica-Bold, the output texture size of 2048x2048:\n```\nmrbean@Beans-Mini % ./sdfontgen -verbose -fontname Helvetica-Bold -spread 0.2 -upsample 4 -texturesize 2048 -outputpath .\n\nsdfontgen : generating signed distance fonts with the following parameters.\n  font name: [Helvetica-Bold]\n  glyph number cut-off: [0]\n  spread: [0.2]\n  up-sample factor: [4]\n  texture size: [2048]\n  output path: [.]\nINFO: Number of glyphs in font Helvetica-Bold: [2252].\nINFO: Number of glyphs after cut-off: [2252].\nINFO: Reference Font size: [42.0].\nINFO: Spread in pixels: [5.122411719096914]\nINFO: Occupancy Rate: [0.7282965183258057]\nINFO: Up-sampled per-glyph texture side length: [288]\nINFO: Up-sampled font size: [168.0]\nINFO: Bounding box for glyph 1 is degenerate. Skipping.\n...\nINFO: Bounding box for glyph 1327 is degenerate. Skipping.\nINFO: Total processing time: 4.357048988342285 seconds. \nINFO: PNG file path to write [./Helvetica-Bold.png -- file:///Users/mrbean/repo/SDFontApple/SDFont/build/]: \nINFO: JSON file path to write [./Helvetica-Bold.json -- file:///Users/mrbean/repo/SDFontApple/SDFont/build/]: \nsdfontgen: finished processing.\n\nmrbean@Beans-Mini % ls -l Helvetica-Bold.*\n-rw-r--r--@ 1 mrbean museumstaff  243331 Oct 25 02:15 Helvetica-Bold.json\n-rw-r--r--  1 mrbean museumstaff  903737 Oct 25 02:15 Helvetica-Bold.png\n```\nThis will generate two files: *Helvetica-Bold.png* and *Helvetica-Bold.json*.\n\n## Generating Signed Distance Fonts at Runtime.\nYou can use the class `SDFontGenerator` as follows.\nFollowing is a gist of what you should do.\n```\nimport SDFont\nlet sdGenerator = SDFontGenerator(\n    device                             : MTLCreateSystemDefaultDevice()!,\n    fontName                           : \"Helvetica-Bold\",\n    outputTextureSideLen               : 2048\n    spreadFactor                       : 0.2,\n    upSamplingFactor                   : 4,\n    glyphNumCutoff                     : 0, // 0 means no limit\n    verbose                            : true\n    usePosixPath                       : false // for iOS and macOS GUI Apps, set it false. For macos commandline Apps, which has no access-limits/sand-boxing to the file system, set true.\n)\n```\nThis will generate types of data: a generated signed distance texture, and a list of bounding boxes.\n\nTo retrieve them, you can either save them to the specified files in PNG and JSON,\n```\nlet rtn1 = sdGenerator.writeToPNGFile(fileName: fontName, path: outputPath ) // This cannot be called, if generateMTLTexture() has been already called.\nif !rtn1 {\n    print (\"ERROR: cannot write PNG file [\\(outputPath)/\\(fontName).png]\")\n}\nlet rtn2 = sdGenerator.writeMetricsToJSONFile(fileName: fontName, path: outputPath )\nif !rtn2 {\n    print (\"ERROR: cannot write JSON file [\\(outputPath)/\\(fontName).json]\")\n}\n```\nor you can retrieve them as MTLTexture and [CGRect].\n```\nlet texture : MTLTexture? = sdGenerator.generateMTLTexture() // Generated signed distance texture.\nlet bounds : [CGRect] = sdGenerator.generateTextureBounds()  // List of bounding boxes for the glyphs.\n```\n\n## Using the Signed Distance Fonts for Rendering.\nYou can use the class `SDFontRuntimeHelper`.\nFollowing is a gist of what you should do.\n```\n// from the PNG/JSON file pair:\nlet helper = SDFontRuntimeHelper(\n    device       : MTLCreateSystemDefaultDevice()!,\n    fontName     : \"Helvecita-Bold\",\n    fontSize     : 12,\n    fileName     : \"Helvetica-Bold\",\n    path         : nil,\n    usePosixPath : false,\n    verbose      : Bool\n)\n\n// from the instance of SDFontGenerator\nlet helper = SDFontRuntimeHelper( generator: sdGenerator, fontSize: 12, verbose: true )\n```\nAfter instantiating the SDFontRuntimeHelper you can perform the following.\n```\n// get the signed distance texture in MTLTexture\nlet texture = helper.texture()\n\n// perform typesetting.\nlet bounds : [GlyphBound] = helper.typeset(\n    frameRect     : CGRectMake( -150, -150, 300, 300),\n    textPlain     : \"Gesha coffee, sometimes referred to as Geisha coffee, is a variety of coffee tree that originated in the Gori Gesha forest, Ethiopia.\"\n    lineAlignment : .left // CTTextAlignment\n)\n```\nThe typeset data are provied in the array of `GlyphBound`.\n```\nstruct GlyphBound {\n    let frameBound   : CGRect // The rectangular bounding box in the specified drawing area.\n    let textureBound : CGRect // The rectangular bounding box of the glyph in the texture coodinate space.\n}\n```\nEach glyph is represented by GlyphBound. Please note that there is no one-by-one mapping between the character sequence of the string you specified to `textPlain` and the glyph sequence in the list in `bounds'. The member `frameBound` is used to generate the coordinates for the quad (or two triangles), and 'textureBound' for their texture uv-coordinates.\n\nA sample for mesh generation and text rendering with Metal can be found in `SDTextPlane.generateVerticesAndIndices()`\nin [SWOpeningRoll/shared/SDTextPlane.swift](./SWOpeningRoll/shared/SDTextPlane.swift).\n\n\n# License\n\nGPL v3.\n\nCommercial use with proper attribution can be considered.\nEspecially for indy developers and small businesses owners a very reasonable licensing can be arranged.\n\n# Contact\nFor technical and commercial inquiries, please contact: Shoichiro Yamanishi\n\nyamanishi72@gmail.com\n\nEspecially if you are an indy develper, please feel free to contact me.\n\n# Background\nThis is a retake to my [SDFont](https://github.com/ShoYamanishi/SDFont), which depends on OpenGL \u0026 libfreetype.\n[SDFont](https://github.com/ShoYamanishi/SDFont) used to work for macOS but not anymore since Apple stopped supporting OpenGL.\nAlso, I wanted to port SDFont to iOS but I quickly found it was difficult to use FreeType on iOS as the font files are inaccessible to the user Apps.\nOn the other hand, Apple eco-system provides an excellent typesetting framework called CoreText, and a GPU computing facility called Metal Compute shaders. I wanted to utilize those Apple-specific technologies for signed distance fonts.\n\nThis lack of support for OpenGL and libfreetype and availability of CoreText and Metal have motivated me to develop another SDFont framework for the Apple eco-system.\n\n# Acknowledgment\nSpecial thanks to [Warren Moore](https://warrenmoore.net/) for [the accompanying sample code](https://github.com/metal-by-example/sample-code/tree/master/objc/12-TextRendering) to his excellent book [Metal by Example](https://metalbyexample.com) I purchased. I learned a lot about CoreText from his obj-c code, especially how the various coordinate systems in CoreText work together with CoreGraphics.\nHis signed font generator uses a dynamic-programming algorithm (essentially a variant of Dijkstra), which is difficult to parallelize. My implementation uses Metal Compute and a per-pixel brute-force vicinity search, which can be parallelized in GPU.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshoyamanishi%2Fsdfontapple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshoyamanishi%2Fsdfontapple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshoyamanishi%2Fsdfontapple/lists"}