<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    
    <title>YesLogic</title>
    
    <link>https:&#x2F;&#x2F;yeslogic.com</link>
    <description>A software company established in 2002, based in Melbourne, Australia.</description>
    <generator>Zola</generator>
    <language>en</language>
    <managingEditor>support@princexml.com (YesLogic)</managingEditor>
    <webMaster>support@princexml.com (YesLogic)</webMaster>
    <atom:link href="https:&#x2F;&#x2F;yeslogic.com&#x2F;index.xml" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Tue, 25 Nov 2025 10:06:00 +1000</lastBuildDate>
    
    <item>
      <title>Allsorts Font Shaping Engine 0.16 Release</title>
      <pubDate>Tue, 25 Nov 2025 10:06:00 +1000</pubDate>
      <atom:published>2025-11-25T10:06:00+10:00</atom:published>
      
      <author>support@princexml.com (YesLogic)</author>
      <link>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-16-0&#x2F;</link>
      <guid>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-16-0&#x2F;</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Allsorts now supports shaping Myanmar script, Apple Advanced Typography &lt;code&gt;morx&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;kern&lt;&#x2F;code&gt; tables,
and COLRv0 &amp;amp; COLRv1 colour fonts.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts&lt;&#x2F;a&gt; is a Rust crate (library) that can parse OpenType, WOFF, and WOFF2
fonts, shape text, and subset fonts&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. We use it in &lt;a href=&quot;https:&#x2F;&#x2F;www.princexml.com&#x2F;&quot;&gt;Prince&lt;&#x2F;a&gt; for all font
parsing, shaping, and subsetting.&lt;&#x2F;p&gt;
&lt;p&gt;Allsorts 0.16 is another big release containing new features and improvements built
over the last 18 months.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;shaping-myanmar&quot;&gt;Shaping Myanmar&lt;&#x2F;h2&gt;
&lt;p&gt;Allsorts can now shape text that uses Myanmar script, such as Burmese.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;complex-myanmar.png&quot; width=&quot;233&quot;&gt;
  &lt;figcaption&gt;
      An extreme example of complex shaping of Myanmar script from the OpenType specification.
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;kerning-with-kern&quot;&gt;Kerning with &lt;code&gt;kern&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;kern&lt;&#x2F;code&gt; table, inherited from TrueType is an alternative to &lt;code&gt;GPOS&lt;&#x2F;code&gt; for kerning adjustments. It&#x27;s
most commonly encountered in older fonts, or fonts designed specifically for macOS, but some modern
fonts like previous versions of OpenSans also use it. Allsorts 0.16 will now make use of a &lt;code&gt;kern&lt;&#x2F;code&gt;
table if there is no kerning feature in the &lt;code&gt;GPOS&lt;&#x2F;code&gt; table. In addition to the &lt;code&gt;kern&lt;&#x2F;code&gt; format specified
by OpenType, Allsorts also supports &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;fonts&#x2F;TrueType-Reference-Manual&#x2F;RM06&#x2F;Chap6kern.html&quot;&gt;Apple&#x27;s extensions&lt;&#x2F;a&gt; for more sophisticated
&lt;code&gt;kern&lt;&#x2F;code&gt;-based kerning.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shaping-with-morx&quot;&gt;Shaping with &lt;code&gt;morx&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;fonts&#x2F;TrueType-Reference-Manual&#x2F;RM06&#x2F;Chap6morx.html&quot;&gt;extended glyph metamorphosis table (&lt;code&gt;morx&lt;&#x2F;code&gt;)&lt;&#x2F;a&gt; allows specifying a set of transformations
that can apply to the glyphs of a font. This is how shaping is achieved in Apple Advanced
Typography. It uses a state machine to implement the transformations. Where shaping with &lt;code&gt;GSUB&lt;&#x2F;code&gt;
typically requires the shaping engine to have some knowledge of the scripts it can shape, &lt;code&gt;morx&lt;&#x2F;code&gt;
allows a single implementation to implement almost any script. The drawback is that all the logic
must be encoded in every font instead of once in the shaping engine.&lt;&#x2F;p&gt;
&lt;p&gt;Allsorts now implements shaping with &lt;code&gt;morx&lt;&#x2F;code&gt; when the &lt;code&gt;GSUB&lt;&#x2F;code&gt; table is absent. Being an Apple
technology, &lt;code&gt;morx&lt;&#x2F;code&gt; is most commonly encountered in fonts shipped on Apple platforms. For example
Hoefler Text, and Zapfino.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;zapfino.png&quot; width=&quot;551&quot;&gt;
  &lt;figcaption&gt;
    Text set in the Zapfino font from macOS.
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;colr-fonts&quot;&gt;COLR Fonts&lt;&#x2F;h2&gt;
&lt;p&gt;One of the many mechanisms to achieve colour fonts is through the &lt;code&gt;COLR&lt;&#x2F;code&gt; table, and its companion
&lt;code&gt;CPAL&lt;&#x2F;code&gt;. This format is commonly encountered in recent versions of Noto Color Emoji, and Segoe UI
Emoji (the Windows emoji font). It uses regular glyph outlines (as opposed to bitmaps or SVG) and
colours them by applying paint operators such as fills, clips, and gradients. There are two &lt;code&gt;COLR&lt;&#x2F;code&gt;
formats: &lt;code&gt;COLRv0&lt;&#x2F;code&gt;, which allows basic colouring and layering of outlines, and the more
sophisticated &lt;code&gt;COLRv1&lt;&#x2F;code&gt; that adds many more operators as well as support for multiple types of
gradients.&lt;&#x2F;p&gt;
&lt;p&gt;Allsorts supports both formats and provides a generic mechanism for traversing the paint tree. The
emitted calls translate well into 2D graphics library APIs that have a PostScript-inspired model,
such as Cairo, or Quartz.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;nabla.png&quot; width=&quot;641&quot;&gt;
  &lt;figcaption&gt;
    The Nabla COLRv1 font with highlight and depth variation axes.
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;other-improvements-fixes&quot;&gt;Other Improvements &amp;amp; Fixes&lt;&#x2F;h2&gt;
&lt;p&gt;There were a number of other smaller fixes and improvements in this release, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Respecting the flip flag in &lt;code&gt;sbix&lt;&#x2F;code&gt; lookup.
&lt;ul&gt;
&lt;li&gt;This enables the right facing emoji in Apple Color Emoji to work
properly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Applying a maximum limit to GPOS substitutions.
&lt;ul&gt;
&lt;li&gt;This mitigates fonts using a &#x27;billion laughs&#x27; attack to exhaust resources.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Applying &lt;code&gt;GPOS&lt;&#x2F;code&gt; lookups in global order.
&lt;ul&gt;
&lt;li&gt;This improves compatibility with Segoe UI Emoji.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Implementing support for mark filtering sets.
&lt;ul&gt;
&lt;li&gt;This was required for some Myanmar script fonts.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Updating Unicode data to Unicode 16.&lt;&#x2F;li&gt;
&lt;li&gt;Providing access to bounding box of glyphs.
&lt;ul&gt;
&lt;li&gt;Glyphs can be traversed to calculate their bounding box.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Applying variations when visiting the outlines of &lt;code&gt;glyf&lt;&#x2F;code&gt; based fonts.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With all of these improvements Allsorts went from passing 432 of the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;unicode-org&#x2F;text-rendering-tests&quot;&gt;Unicode text-rendering-tests&lt;&#x2F;a&gt; to 540, leaving 212 failing tests
(mostly scripts that are not yet supported).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;project-showcase&quot;&gt;Project Showcase&lt;&#x2F;h2&gt;
&lt;p&gt;Before wrapping up I thought it would be nice to mention some of the other projects
that are using Allsorts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fschutt&#x2F;azul&quot;&gt;Azul&lt;&#x2F;a&gt; desktop GUI framework.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fschutt&#x2F;printpdf&quot;&gt;printpdf&lt;&#x2F;a&gt; Rust library for creating, reading, writing and rendering PDF documents.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Logicalshift&#x2F;flo_draw&quot;&gt;flo_draw&lt;&#x2F;a&gt; 2D rendering libraries for Rust.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nextjs.org&#x2F;&quot;&gt;next.js&lt;&#x2F;a&gt; React JS full-stack web framework.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Font shaping is the process of taking text in the form of Unicode codepoints
and a font, and laying out glyphs according to the text. This involves applying
kerning, ligatures, and substitutions specified by the font and performing
glyph reordering according to the OpenType rules specific to each complex
script.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
    </item>
    
    <item>
      <title>Allsorts Font Shaping Engine 0.15 Release</title>
      <pubDate>Wed, 12 Jun 2024 10:54:02 +1000</pubDate>
      <atom:published>2024-06-12T10:54:02+10:00</atom:published>
      
      <author>support@princexml.com (YesLogic)</author>
      <link>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-15-0&#x2F;</link>
      <guid>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-15-0&#x2F;</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Allsorts now supports variable fonts, CFF2, and can generate font specimen
documents.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts&lt;&#x2F;a&gt; is a Rust crate (library) that can parse OpenType, WOFF, and WOFF2
fonts, shape text, and subset fonts&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. We use it in &lt;a href=&quot;https:&#x2F;&#x2F;www.princexml.com&#x2F;&quot;&gt;Prince&lt;&#x2F;a&gt; for all font
parsing, shaping, and subsetting.&lt;&#x2F;p&gt;
&lt;p&gt;A lot has happened since we last wrote about Allsorts all the way back in
2021. There have been 14 releases since then. In that time Allsorts
gained support for variable fonts, CFF2 outlines, and creating font specimen
documents, as well as a few bug fixes and improvements.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;variable-fonts&quot;&gt;Variable fonts&lt;&#x2F;h2&gt;
&lt;p&gt;With a history dating back to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;QuickDraw_GX&quot;&gt;QuickDraw GX&lt;&#x2F;a&gt; on classic Mac OS, variable
fonts have become popular since their addition to OpenType 1.8 in 2016. A
variable font contains one of more axes of variation: these may be dimensions
like weight or slant but can also be entirely custom. They provide many
benefits, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Continuous variation: instead of fixed instances like Light, Medium, Regular, Bold
a variable font allows an axis to support all values between a minimum and maximum.&lt;&#x2F;li&gt;
&lt;li&gt;More compact font files, only one file is needed instead of one for each style.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;cantarell-weights.png&quot; width=&quot;515&quot;&gt;
  &lt;figcaption&gt;
    Text in various weights of Cantarell.
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Allsorts has gained support for reading variation information as well as
applying it to font data to create a specific font instance. The star of the
variable-fonts show is the new &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&#x2F;0.15.0&#x2F;allsorts&#x2F;variations&#x2F;fn.instance.html&quot;&gt;instance function&lt;&#x2F;a&gt;, which given a
variable font and a collection of values for each axis produces a non-variable
font instance that can be embedded in a PDF or used as a regular font in other
code or applications.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cff2&quot;&gt;CFF2&lt;&#x2F;h2&gt;
&lt;p&gt;As the name implies, CFF2 is a second take on the support for CFF outlines in
OpenType. It eliminates many of the redundancies found in CFF in OpenType, in
addition to adding support for variable fonts. CFF2 fonts are presently most
likely to be encountered in fonts from Adobe but they are also used in other
places, for example the &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.gnome.org&#x2F;GNOME&#x2F;cantarell-fonts&quot;&gt;Cantarell&lt;&#x2F;a&gt; font used by the GNOME desktop environment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cff-subsetting&quot;&gt;CFF Subsetting&lt;&#x2F;h2&gt;
&lt;p&gt;In earlier versions of Allsorts only a limited amount of subsetting was applied
to CFF fonts. Now the CharStrings (glyph outlines) in CFF fonts are also subset
to eliminate unused operators, resulting in much smaller output. This feature
was based upon the CharString parser from &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RazrFalcon&#x2F;ttf-parser&quot;&gt;ttf-parser&lt;&#x2F;a&gt;, so thanks to RazrFalcon
for that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;font-specimens&quot;&gt;Font Specimens&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes you want to see what a font looks like and know some of the technical
details about it. To support this we added the ability to generate a HTML font
specimen containing sample text and information about the font. &lt;a href=&quot;https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-15-0&#x2F;cantarell.html&quot;&gt;This document
generated for Cantarell&lt;&#x2F;a&gt; is an example.&lt;&#x2F;p&gt;
&lt;p&gt;This feature is turned off by default. Enable the &lt;code&gt;specimen&lt;&#x2F;code&gt; Cargo feature
enable it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;allsorts-tools&quot;&gt;Allsorts Tools&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;Allsorts tools&lt;&#x2F;a&gt; as been enhanced to make use of the new Allsorts features.
There are three new sub-commands:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;variations&lt;&#x2F;code&gt; — list variation information about a font.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;instance&lt;&#x2F;code&gt; — create an instance of a variable font.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;specimen&lt;&#x2F;code&gt; — generate a font specimen for a font.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;variations&quot;&gt;variations&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;variations&lt;&#x2F;code&gt; lists variation axes in a font, their domain and any pre-defined
instances in the font. Example output:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;$ allsorts variations &#x2F;usr&#x2F;share&#x2F;fonts&#x2F;cantarell&#x2F;Cantarell-VF.otf
&lt;&#x2F;span&gt;&lt;span&gt;Axes: (1)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;- wght = min: 100, max: 800, default: 400
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Instances:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      Subfamily: Thin
&lt;&#x2F;span&gt;&lt;span&gt;    Coordinates: [100.0]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      Subfamily: Light
&lt;&#x2F;span&gt;&lt;span&gt;    Coordinates: [300.0]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      Subfamily: Regular
&lt;&#x2F;span&gt;&lt;span&gt;    Coordinates: [400.0]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      Subfamily: Bold
&lt;&#x2F;span&gt;&lt;span&gt;    Coordinates: [700.0]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      Subfamily: Extra Bold
&lt;&#x2F;span&gt;&lt;span&gt;    Coordinates: [800.0]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Style Attributes:
&lt;&#x2F;span&gt;&lt;span&gt;Thin
&lt;&#x2F;span&gt;&lt;span&gt;Light
&lt;&#x2F;span&gt;&lt;span&gt;Regular
&lt;&#x2F;span&gt;&lt;span&gt;Bold
&lt;&#x2F;span&gt;&lt;span&gt;Extra Bold
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;instance&quot;&gt;instance&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;instance&lt;&#x2F;code&gt; is used to produce a non-variable font instance from a variable font.
For example if we wanted an instance of Cantarell with a weight of 555 we&#x27;d run:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;allsorts instance -t 555 -o Cantarell555.otf &#x2F;usr&#x2F;share&#x2F;fonts&#x2F;cantarell&#x2F;Cantarell-VF.otf
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;specimen&quot;&gt;specimen&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;specimen&lt;&#x2F;code&gt; command generates a document in HTML format describing features of the
font along with some sample text set in the font. For example,&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span&gt;specimen &#x2F;usr&#x2F;share&#x2F;fonts&#x2F;cantarell&#x2F;Cantarell-VF.otf &amp;gt; cantarell.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-15-0&#x2F;cantarell.html&quot;&gt;View a font specimen for Cantarell&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Font shaping is the process of taking text in the form of Unicode codepoints
and a font, and laying out glyphs according to the text. This involves applying
kerning, ligatures, and substitutions specified by the font and performing
glyph reordering according to the OpenType rules specific to each complex
script.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</description>
    </item>
    
    <item>
      <title>Allsorts Font Shaping Engine 0.6 Release</title>
      <pubDate>Tue, 20 Jul 2021 13:59:22 +1000</pubDate>
      <atom:published>2021-07-20T13:59:22+10:00</atom:published>
      
      <author>support@princexml.com (YesLogic)</author>
      <link>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-6&#x2F;</link>
      <guid>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-0-6&#x2F;</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In the last six months we&#x27;ve added support for shaping new scripts, glyph
positioning, accessing glyph contours, improved performance, and more.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts&lt;&#x2F;a&gt; is a Rust crate (library) that can parse OpenType, WOFF, and WOFF2
fonts, shape text, and subset fonts&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. We use it in &lt;a href=&quot;https:&#x2F;&#x2F;www.princexml.com&#x2F;&quot;&gt;Prince&lt;&#x2F;a&gt; for all font
parsing, shaping, and subsetting.&lt;&#x2F;p&gt;
&lt;p&gt;Since the Allsorts 0.5 release in Dec 2020 we&#x27;ve continued to improve Allsorts
and expand its capabilities. The 0.6 release adds support for shaping Khmer,
Lao, Thai, and Sinhala scripts; laying out glyphs and obtaining their
positions; accessing glyph contours; improved performance; and a few bug fixes
as well.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;new-scripts&quot;&gt;New Scripts&lt;&#x2F;h2&gt;
&lt;p&gt;We continue to expand the scripts Allsorts can shape and have added support for
Khmer, Lao, Thai, and Sinhala scripts. Each new script is accompanied by
extensive corpus-based tests with text extracted from real-world sources like
Wikipedia.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;khmer.png&quot; width=&quot;568&quot;&gt;
  &lt;figcaption&gt;
    Extract from the
    &lt;a href=&quot;https:&#x2F;&#x2F;omniglot.com&#x2F;babel&#x2F;khmer.htm&quot;&gt;Khmer translation of The Tower of Babel&lt;&#x2F;a&gt;
    shaped in Prince
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;lao.png&quot; width=&quot;568&quot;&gt;
  &lt;figcaption&gt;
    Extract from the
    &lt;a href=&quot;https:&#x2F;&#x2F;omniglot.com&#x2F;babel&#x2F;lao.htm&quot;&gt;Lao translation of The Tower of Babel&lt;&#x2F;a&gt;
    shaped in Prince
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;thai.png&quot; width=&quot;568&quot;&gt;
  &lt;figcaption&gt;
    Extract from the
    &lt;a href=&quot;https:&#x2F;&#x2F;omniglot.com&#x2F;babel&#x2F;thai.htm&quot;&gt;Thai translation of The Tower of Babel&lt;&#x2F;a&gt;
    shaped in Prince
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;sinhala.png&quot; width=&quot;568&quot;&gt;
  &lt;figcaption&gt;
    Extract from the
    &lt;a href=&quot;https:&#x2F;&#x2F;omniglot.com&#x2F;babel&#x2F;sinhala.htm&quot;&gt;Sinhala translation of The Tower of Babel&lt;&#x2F;a&gt;
    shaped in Prince
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;glyph-positioning-and-contours&quot;&gt;Glyph Positioning and Contours&lt;&#x2F;h2&gt;
&lt;p&gt;You can now layout glyphs and obtain their positions as well as access glyph
contours. This makes it possible to draw text by pairing Allsorts with any
vector graphics library that supports move to, line to,
quadratic curve to, cubic curve to, and close path
operations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&#x2F;0.6.0&#x2F;allsorts&#x2F;glyph_position&#x2F;struct.GlyphLayout.html&quot;&gt;GlyphLayout&lt;&#x2F;a&gt; is used to obtain the positions for a collection of shaped
glyphs. The position for each glyph includes its horizontal and vertical
advance as well as any &lt;code&gt;(x, y)&lt;&#x2F;code&gt; offset from the origin. Horizontal layout in
left-to-right and right-to-left directions is supported. Basic (but incomplete)
support for vertical text is present too.&lt;&#x2F;p&gt;
&lt;p&gt;The position of a series of glyphs is determined from an initial pen position
(that the application using Allsorts maintains) that is incremented by the
advance of each glyph as they are processed. The position of a particular glyph
is the current pen position plus X and Y offset.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&#x2F;0.6.0&#x2F;allsorts&#x2F;outline&#x2F;index.html&quot;&gt;outline module&lt;&#x2F;a&gt; provides access to the contours of glyphs as a series of
&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&#x2F;0.6.0&#x2F;allsorts&#x2F;outline&#x2F;trait.OutlineSink.html&quot;&gt;foundational drawing instruction callbacks&lt;&#x2F;a&gt;. Currently we support
reading glyph contours from &lt;code&gt;glyf&lt;&#x2F;code&gt; and &lt;code&gt;CFF&lt;&#x2F;code&gt; tables. The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;allsorts
tool&lt;&#x2F;a&gt; has been extended to make use of this in order to
generate an SVGs of glyphs.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center figure-no-border&quot;&gt;
  &lt;img src=&quot;glyphs.svg&quot; width=&quot;320&quot;&gt;
  &lt;figcaption&gt;
    SVG generated with the
    &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;allsorts CLI tool&lt;&#x2F;a&gt;
    presenting glyphs from
    &lt;a href=&quot;http:&#x2F;&#x2F;www.gust.org.pl&#x2F;projects&#x2F;e-foundry&#x2F;tex-gyre&#x2F;termes&quot;&gt;TeX Gyre Termes&lt;&#x2F;a&gt;.
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;In turn, we used this SVG generation ability to hook Allsorts up to the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;unicode-org&#x2F;text-rendering-tests&quot;&gt;Unicode text rendering tests&lt;&#x2F;a&gt;. Allsorts passes the
tests for features that we support. We hope to integrate Allsorts into the
upstream text rendering tests project soon.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;text-rendering-test-example.png&quot; width=&quot;622&quot;&gt;
  &lt;figcaption&gt;
    Sample test from the
    &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;unicode-org&#x2F;text-rendering-tests&quot;&gt;Unicode text rendering tests&lt;&#x2F;a&gt;
    showing Allsort produces the expected output.
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;performance-improvements&quot;&gt;Performance Improvements&lt;&#x2F;h2&gt;
&lt;p&gt;Various improvements have been made to make some code paths more efficient
leading to mild speed ups in our tests:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Optimised GPOS duplicate lookup removal.&lt;&#x2F;li&gt;
&lt;li&gt;Optimised handling of CFF fonts with custom characters sets.&lt;&#x2F;li&gt;
&lt;li&gt;Fixing a mistake that resulted in &lt;code&gt;vmtx&lt;&#x2F;code&gt; table being repeatedly cloned.&lt;&#x2F;li&gt;
&lt;li&gt;Avoid some allocations when working with glyphs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;miscellaneous-improvements-and-fixes&quot;&gt;Miscellaneous Improvements and Fixes&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;API improvements:
&lt;ul&gt;
&lt;li&gt;Combine &lt;code&gt;gpos::Info&lt;&#x2F;code&gt; and &lt;code&gt;gpos::Attachment&lt;&#x2F;code&gt; into &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&#x2F;0.6.0&#x2F;allsorts&#x2F;gpos&#x2F;enum.Placement.html&quot;&gt;gpos::Placement&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Allow extra &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_typographic_features#OpenType_typographic_features&quot;&gt;OpenType features&lt;&#x2F;a&gt; to be supplied to &lt;code&gt;Font::shape&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Replaced &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;rental&quot;&gt;rental&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;ouroboros&quot;&gt;ouroboros&lt;&#x2F;a&gt; as rental was no longer maintained. (Thanks &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&#x2F;pull&#x2F;47&quot;&gt;@est31&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Handle &lt;code&gt;post&lt;&#x2F;code&gt; tables that map more than one glyph to the same name index.&lt;&#x2F;li&gt;
&lt;li&gt;Apply Unicode mark reordering to more scripts, not just Arabic and Indic
scripts.&lt;&#x2F;li&gt;
&lt;li&gt;Always apply default shaping for complex scripts.&lt;&#x2F;li&gt;
&lt;li&gt;Handle non-adjacent cursive connections in &lt;code&gt;GPOS&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Support version 1.1 &lt;code&gt;GPOS&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;GSUB&lt;&#x2F;code&gt; tables.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;allsorts&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;img.shields.io&#x2F;crates&#x2F;v&#x2F;allsorts.svg&quot; alt=&quot;Crate&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;allsorts&#x2F;badge.svg&quot; alt=&quot;Documentation&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;Allsorts CLI tool&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Font shaping is the process of taking text in the form of Unicode codepoints
and a font, and laying out glyphs according to the text. This involves
honouring kerning, ligatures, and substitutions specified by the font and
performing glyph reordering according to the script-specific OpenType rules.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Font subsetting refers to decreasing the size of a font by only including the data
for a reduced set of glyphs.&lt;&#x2F;p&gt;
</description>
    </item>
    
    <item>
      <title>Allsorts Font Shaping Engine Year in Review</title>
      <pubDate>Fri, 18 Dec 2020 10:06:35 +1100</pubDate>
      <atom:published>2020-12-18T10:06:35+11:00</atom:published>
      
      <author>support@princexml.com (YesLogic)</author>
      <link>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-2020-review&#x2F;</link>
      <guid>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine-2020-review&#x2F;</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A year ago YesLogic open-sourced the Allsorts font parser, shaping engine,
and subsetter. In this post we cover how Allsorts has worked out in &lt;a href=&quot;https:&#x2F;&#x2F;www.princexml.com&#x2F;&quot;&gt;Prince&lt;&#x2F;a&gt;,
what&#x27;s improved over the past year, and what we&#x27;re working on next.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts&lt;&#x2F;a&gt; is a Rust crate (library) that can parse OpenType, WOFF, and WOFF2
fonts, shape text, and subset fonts&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;At YesLogic we&#x27;ve been using Allsorts to power all font parsing, shaping of
supported scripts, and subsetting in Prince since version 13 was released in November
2019. Aside from the odd small bug revealed by real-world usage and exposure to
new fonts it has proven to be capable and reliable.&lt;&#x2F;p&gt;
&lt;p&gt;Over the past year we&#x27;ve continued to work on Allsorts, adding support for
additional scripts, bitmap and SVG fonts, and refined the
API to make it easier to use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;new-scripts&quot;&gt;New Scripts&lt;&#x2F;h2&gt;
&lt;p&gt;Allsorts can now shape the Arabic and Syriac scripts giving us even more coverage of the
world&#x27;s scripts.&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-rtl&quot;&gt;
  &lt;img src=&quot;arabic.png&quot; width=&quot;554&quot;&gt;
  &lt;figcaption&gt;
    Extract from the
    &lt;a href=&quot;https:&#x2F;&#x2F;omniglot.com&#x2F;babel&#x2F;arabic.htm&quot;&gt;Arabic translation of The Tower of Babel&lt;&#x2F;a&gt;
    shaped in Prince
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;figure class=&quot;figure-rtl&quot;&gt;
  &lt;img src=&quot;syriac.png&quot; width=&quot;750&quot;&gt;
  &lt;figcaption&gt;
    Extract from the
    &lt;a href=&quot;https:&#x2F;&#x2F;omniglot.com&#x2F;babel&#x2F;syriac.htm&quot;&gt;Syriac translation of The Tower of Babel&lt;&#x2F;a&gt;
    shaped in Prince
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;bitmap-and-svg-fonts&quot;&gt;Bitmap and SVG Fonts&lt;&#x2F;h2&gt;
&lt;p&gt;We can now parse OpenType font tables containing bitmaps and SVGs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;typography&#x2F;opentype&#x2F;spec&#x2F;cblc&quot;&gt;&lt;code&gt;CBDT&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;CBLC&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;code&gt;EBDT&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;EBLC&lt;&#x2F;code&gt;, as used by &lt;a href=&quot;https:&#x2F;&#x2F;www.google.com&#x2F;get&#x2F;noto&#x2F;help&#x2F;emoji&#x2F;&quot;&gt;Noto Color Emoji&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;typography&#x2F;opentype&#x2F;spec&#x2F;sbix&quot;&gt;&lt;code&gt;sbix&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, as used by &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Apple_Color_Emoji&quot;&gt;Apple Color Emoji&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;typography&#x2F;opentype&#x2F;spec&#x2F;svg&quot;&gt;&lt;code&gt;SVG&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, as used by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;eosrei&#x2F;twemoji-color-font&quot;&gt;Twitter Color Emoji&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We implemented a unified API that supports retrieving the image for a glyph
independent of the tables it originates from.&lt;&#x2F;p&gt;
&lt;p&gt;The bitmap and SVG support has allowed us to bring emoji and colour SVG font
support to Prince 14:&lt;&#x2F;p&gt;
&lt;figure class=&quot;figure-center&quot;&gt;
  &lt;img src=&quot;fattern-colour-svg.png&quot; width=&quot;355&quot;&gt;
  &lt;figcaption&gt;Text set in the &lt;a href=&quot;https:&#x2F;&#x2F;www.fontspace.com&#x2F;fattern-font-f48474&quot;&gt;Fattern colour SVG font&lt;&#x2F;a&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;improved-api&quot;&gt;Improved API&lt;&#x2F;h2&gt;
&lt;p&gt;Prior to Allsorts 0.5 it was a fairly involved affair to shape some text. You
had to read the font, do glyph mapping, apply glyph substitution (GSUB), and
apply glyph positioning (GPOS) in individual steps which amounted to quite a
bit of code.&lt;&#x2F;p&gt;
&lt;p&gt;Now it&#x27;s only a few lines. You read the font and construct an instance of the
&lt;code&gt;Font&lt;&#x2F;code&gt; type, turn text into glyphs with a call to &lt;code&gt;map_glyphs&lt;&#x2F;code&gt;, then shape the
text with a call to &lt;code&gt;shape&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Read and parse font
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; buffer = std::fs::read(&amp;amp;opts.font)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; scope = ReadScope::new(&amp;amp;buffer);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; font_file = scope.read::&amp;lt;FontData&amp;lt;&amp;#39;_&amp;gt;&amp;gt;()?;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Construct Font instance
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; provider = font_file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;table_provider&lt;&#x2F;span&gt;&lt;span&gt;(opts.index)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; font = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match &lt;&#x2F;span&gt;&lt;span&gt;Font::new(provider)?
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;unable to find suitable cmap subtable&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Map glyphs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; glyphs = font.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map_glyphs&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;some text&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, MatchingPresentation::NotRequired);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#65737e;&quot;&gt;&#x2F;&#x2F; Shape glyphs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; script = tag::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LATN&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; lang = tag::from_string(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;ENG &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)?;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; shaped_glyphs = font.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;shape&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;    glyphs,
&lt;&#x2F;span&gt;&lt;span&gt;    script,
&lt;&#x2F;span&gt;&lt;span&gt;    Some(lang),
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;Features::Mask(GsubFeatureMask::default()),
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;)?;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also renamed a number of types and methods to make their function more
obvious and accurate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;miscellaneous-improvements-and-fixes&quot;&gt;Miscellaneous Improvements and Fixes&lt;&#x2F;h2&gt;
&lt;p&gt;Throughout the year we made several other improvements and fixes, including:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Extended our glyph substitution support, implementing &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;typography&#x2F;opentype&#x2F;spec&#x2F;gpos#lookuptype-8-chained-contexts-positioning-subtable&quot;&gt;GSUB Lookup Type
8&lt;&#x2F;a&gt; (Reverse Chaining Contextual Single Substitution), which gains us
support for &lt;a href=&quot;https:&#x2F;&#x2F;blog.janestreet.com&#x2F;commas-in-big-numbers-everywhere&#x2F;&quot;&gt;Tristan Hume&#x27;s Numderline font&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;numderline.png&quot; width=&quot;586&quot;&gt;
  &lt;figcaption&gt;Text set in the &lt;a href=&quot;https:&#x2F;&#x2F;thume.ca&#x2F;numderline&#x2F;&quot;&gt;Numderline font&lt;&#x2F;a&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Fixed a few bugs and handled some quirks revealed by exposing the code to
a variety of real world fonts.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Improved performance through:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GSUB caching in Arabic, Syriac, and Indic.&lt;&#x2F;li&gt;
&lt;li&gt;Restructuring to avoid unnecessary bounds checks and allocations.&lt;&#x2F;li&gt;
&lt;li&gt;Using &lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;tinyvec&quot;&gt;tinyvec&lt;&#x2F;a&gt; to store codepoints on glyphs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Added support for more OpenType features in GSUB:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Standard ligatures (&lt;code&gt;liga&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Discretionary ligatures (&lt;code&gt;dlig&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Historical ligatures (&lt;code&gt;hlig&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Contextual ligatures (&lt;code&gt;clig&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Small caps (&lt;code&gt;smcp&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Small capitals from capitals (&lt;code&gt;c2sc&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Lining figures (&lt;code&gt;lnum&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Oldstyle figures (&lt;code&gt;onum&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Proportional figures (&lt;code&gt;pnum&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Tabular figures (&lt;code&gt;tnum&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Diagonal fractions (&lt;code&gt;frac&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Stacked fractions (&lt;code&gt;afrc&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Ordinals (&lt;code&gt;ordn&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Slashed zero (&lt;code&gt;zero&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Language-specific OpenType shaping (&lt;code&gt;locl&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Support fonts with Big5 encoded cmap subtables.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;future-plans&quot;&gt;Future Plans&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re currently implementing the following features to make Allsorts
better suited for use cases outside our own:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Expose glyph positioning information in shaping output so you don&#x27;t have to
calculate it yourself.&lt;&#x2F;li&gt;
&lt;li&gt;Retrieve glyph contours as a series of basic drawing operations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After those we hope to look into:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Text segmentation by script to allow a chunk of text to be supplied to
Allsorts without having to detect and segment it by script first.&lt;&#x2F;li&gt;
&lt;li&gt;Glyph caching.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Other items on our radar are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Performance measurement and optimisation to make it competitive with other
shaping libraries.&lt;&#x2F;li&gt;
&lt;li&gt;Support additional scripts such as Sinhala, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;n8willis&#x2F;opentype-shaping-documents&#x2F;blob&#x2F;master&#x2F;opentype-shaping-use.md&quot;&gt;Indic 3&#x2F;Universal Shaping
Engine&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Unicode normalisation.&lt;&#x2F;li&gt;
&lt;li&gt;Being able to map shaping output back to the source text.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;Allsorts Example Tools&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;yeslogic&quot;&gt;YesLogic on Twitter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;prince_xml&quot;&gt;PrinceXML on Twitter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;&#x2F;h2&gt;
&lt;p&gt;Thanks to Adrian, Alfie, Michael, Paul, and Peter for helping me write this
post.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Font shaping is the process of taking text in the form of Unicode codepoints
and a font, and laying out glyphs according to the text. This involves
honouring kerning, ligatures, substitutions, and reordering specified by the
font.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Font subsetting refers to decreasing the size of a font by only including the data
for a reduced set of glyphs.&lt;&#x2F;p&gt;
</description>
    </item>
    
    <item>
      <title>Announcing the Allsorts Font Shaping Engine</title>
      <pubDate>Wed, 20 Nov 2019 09:00:00 +1100</pubDate>
      <atom:published>2019-11-20T09:00:00+11:00</atom:published>
      
      <author>support@princexml.com (YesLogic)</author>
      <link>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine&#x2F;</link>
      <guid>https:&#x2F;&#x2F;yeslogic.com&#x2F;blog&#x2F;allsorts-rust-font-shaping-engine&#x2F;</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Today YesLogic is open-sourcing the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts&lt;&#x2F;a&gt; font parser, shaping engine, and subsetter for OpenType, WOFF, and WOFF2 under the Apache 2.0 license. Allsorts was extracted from the &lt;a href=&quot;https:&#x2F;&#x2F;www.princexml.com&#x2F;&quot;&gt;Prince&lt;&#x2F;a&gt; HTML to PDF typesetting and layout tool and is implemented in Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.princexml.com&#x2F;&quot;&gt;Prince&lt;&#x2F;a&gt; is a tool that converts HTML and CSS into well laid out PDFs. Our customers use it to produce books, restaurant menus, invoices, business cards, and much more. Two years ago YesLogic set out to improve the font parsing and shaping in Prince.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Font shaping is the process of laying out the glyphs of a font in order to represent some input text. Rasterisation of the glyphs is a separate process. Font shaping for Latin text is quite simple. For some scripts, like those used by &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Indo-Aryan_languages&quot;&gt;Indic languages&lt;&#x2F;a&gt;, it is quite complex and requires reordering and substituting the glyphs in each syllable to produce the final output. There are only three main font shaping engines in use today: &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;directwrite&#x2F;direct-write-portal&quot;&gt;DirectWrite&lt;&#x2F;a&gt; on Windows, &lt;a href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;library&#x2F;archive&#x2F;documentation&#x2F;StringsTextFonts&#x2F;Conceptual&#x2F;CoreText_Programming&#x2F;Introduction&#x2F;Introduction.html&quot;&gt;CoreText&lt;&#x2F;a&gt; on macOS and iOS, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;harfbuzz&#x2F;harfbuzz&quot;&gt;HarfBuzz&lt;&#x2F;a&gt; on open-source operating systems and some web-browsers. Of these, only HarfBuzz is open source.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately there is no complete specification of how to perform font shaping for complex scripts, so determining the desired behaviour often comes down to observing what the other font shaping engines do and implementing that. In the hope of improving this situation we have been supporting Nathan Willis in an effort to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;n8willis&#x2F;opentype-shaping-documents&#x2F;&quot;&gt;document the OpenType shaping behaviour&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Prince is mostly written in the &lt;a href=&quot;http:&#x2F;&#x2F;www.mercurylang.org&#x2F;&quot;&gt;Mercury logic programming language&lt;&#x2F;a&gt; but when it came to building the new font parsing and shaping engine we chose Rust. The reasons include a growing community and ecosystem, good interoperability with C (Mercury compiles to C), strong memory safety guarantees, high performance, minimal runtime, and cross-platform support (we build Prince binaries for FreeBSD, Linux, macOS, and Windows).&lt;&#x2F;p&gt;
&lt;p&gt;Rust’s memory safety was especially important as it helps avoid programming errors when parsing binary data (such as fonts) and performing shaping. These types of errors have been a source of security issues in other implementations&lt;sup&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2017-13825&quot;&gt;1&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2017-13849&quot;&gt;2&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2017-13849&quot;&gt;3&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2019-1127&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;aside&gt;
  &lt;p&gt;The two images below compare a paragraph of text from the Wikipedia page on the Chandas font in Firefox and a PDF generated in Prince (viewed in &lt;a href=&quot;https:&#x2F;&#x2F;wiki.gnome.org&#x2F;Apps&#x2F;Evince&quot;&gt;Evince&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
  &lt;figure&gt;
    &lt;img src=&quot;chandas-firefox.png&quot; width=&quot;348&quot;&gt;
    &lt;figcaption&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hi.wikipedia.org&#x2F;wiki&#x2F;%E0%A4%9B%E0%A4%A8%E0%A5%8D%E0%A4%A6%E0%A4%B8_%E0%A4%AB%E0%A5%89%E0%A4%A3%E0%A5%8D%E0%A4%9F&quot;&gt;Chandas Wikipedia page&lt;&#x2F;a&gt; in Firefox 70.0.1&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;
  &lt;figure&gt;
    &lt;img src=&quot;chandas-prince.png&quot; width=&quot;348&quot;&gt;
    &lt;figcaption&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hi.wikipedia.org&#x2F;wiki&#x2F;%E0%A4%9B%E0%A4%A8%E0%A5%8D%E0%A4%A6%E0%A4%B8_%E0%A4%AB%E0%A5%89%E0%A4%A3%E0%A5%8D%E0%A4%9F&quot;&gt;Chandas Wikipedia page&lt;&#x2F;a&gt; in Prince 13&lt;&#x2F;figcaption&gt;
  &lt;&#x2F;figure&gt;
&lt;&#x2F;aside&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;images&#x2F;allsorts.svg&quot; alt=&quot;&quot; width=&quot;16&quot;&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts&lt;&#x2F;a&gt; — a reference to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Sort_(typesetting)&quot;&gt;typographic sorts&lt;&#x2F;a&gt;, and a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Liquorice_allsorts&quot;&gt;licorice confectionery&lt;&#x2F;a&gt; — is the result of this two year effort. It has been extracted from Prince and open sourced under the Apache 2.0 license. The initial release has been published to &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;allsorts&quot;&gt;crates.io&lt;&#x2F;a&gt;. We’ve also published some &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;example tools&lt;&#x2F;a&gt; that use Allsorts to dump font information, shape text, and subset fonts.&lt;&#x2F;p&gt;
&lt;p&gt;The support for Indic scripts in Allsorts was based on Nathan’s new specification. We tested it by comparing Allsorts output to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;harfbuzz&#x2F;harfbuzz&quot;&gt;HarfBuzz&lt;&#x2F;a&gt; on a large corpus of real world text in each of the supported Indic languages.&lt;&#x2F;p&gt;
&lt;p&gt;Allsorts supports parsing OpenType (TrueType and CFF variants), WOFF, and WOFF2 fonts. It can also serialise and subset these formats in a manner suitable for inclusion in PDF documents. It supports shaping of many scripts, including Chinese, Japanese, Korean, Indic scripts, and Latin. Indic layout supports Indic2 font layout.&lt;&#x2F;p&gt;
&lt;p&gt;Font parsing in Allsorts uses an approach designed to be amenable to machine generation by our work-in-progress &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;ddl&quot;&gt;declarative data definition language&lt;&#x2F;a&gt;. The DDL aims to allow formally specifying binary data formats such as fonts. For more information on this work, see &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=L9TubiWkBZ8&quot;&gt;Brendan’s talk at the Melbourne Compose Conference&lt;&#x2F;a&gt; earlier this year.&lt;&#x2F;p&gt;
&lt;p&gt;We’re using Allsorts to power all font parsing, shaping of supported scripts, and subsetting in Prince 13. Allsorts is faster than the previous Mercury&#x2F;C font parsing and shaping implementation used in Prince. We have not yet done a detailed performance comparison to other font shaping engines as we are still focusing on correctness before beginning performance optimisation.&lt;&#x2F;p&gt;
&lt;p&gt;Being a new project Allsorts does have some limitations: the crate is only lightly documented, and it doesn’t support shaping Arabic (Prince still uses its own Mercury implementation for this), Khmer, Tibetan, and Mongolian yet.&lt;&#x2F;p&gt;
&lt;p&gt;We’re excited to publish this release and it’s our hope that Allsorts sees use in many different applications in the future. In the near term we look forward to integrating it more into the ecosystem of font handling in Rust and hope that it becomes a popular choice for pure Rust font handling and shaping.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;links&quot;&gt;Links&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts&quot;&gt;Allsorts on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yeslogic&#x2F;allsorts-tools&quot;&gt;Allsorts Example Tools&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;n8willis&#x2F;opentype-shaping-documents&#x2F;&quot;&gt;Nathan’s Font Shaping Documents&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
    </item>
    
  </channel>
</rss>
