<!DOCTYPE html>
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Since the TypeCon meeting last week I've been preoccupied with a
      number of questions about the variable composite proposal.  I hope
      these are the good, potentially productive kind of question rather
      than the crabby, lets-just-not-do-this type, but they aren't
      small. I'm wondering if things might be significantly better with
      some significant changes.<br>
      <br>
      I've boiled these thoughts into two interrelated multi-part
      questions, which I have added as issues in the
      boring-expansion-spec GitHub repository and will reproduce here.
      The linked issues seem like good contexts for subsequent
      discussion.<br>
    </p>
    <h4>Should variable composites be in the glyf table, and why? (<a
href="https://github.com/harfbuzz/boring-expansion-spec/issues/103">#103</a>)<br>
    </h4>
    <p>I think I understand how we got to the current proposal. Roughly:<br>
    </p>
    <ol>
      <li>The variable composites specification extends the current glyf
        composites mechanism.</li>
      <li>Leaving variable composites in the glyf table saves some
        bytes, in that the offsets can remain in loca and you share the
        Tuple Variation Store offsets with gvar.</li>
    </ol>
    <p>However:<br>
    </p>
    <ol>
      <li>Maybe the overall variable composites system shouldn't be so
        directly derived from the glyf mechanism (see the other
        question).</li>
      <li>Everything proposed would seem to apply just as well to
        pulling outlines out of a CFF2 table.</li>
      <li>We already have a model for how to do this in an external
        table, that being COLR.</li>
    </ol>
    <p>Right now, a system that understands COLR starts by looking in
      that table for an entry. If it finds one, it pulls path data from
      either glyf or CFF(2). If it doesn't, it falls back to glyf or
      CFF(2).  All of this happens "below"/subsequent to shaping:<br>
      <br>
      (shaping) -> COLR -> (glyf | CFF(2))<br>
      <br>
      It seems like what "variable compositing" amounts to is an
      additional, simplified shaping step. Call it "intra-glyph
      shaping", which occurs here:<br>
      <br>
      (inter-glyph shaping) -> COLR -> (intra-glyph shaping) ->
      (glyf | CFF2)<br>
      <br>
      The only reason the system doesn't already look like this is that
      the compositing data is stored in the glyf table.<br>
    </p>
    <p>Set aside the question of other potential changes and just
      consider the current proposal: If one wanted to have this
      mechanism for CFF2 also, would it be substantially different? If
      it had to live inside the CFF2 table it would be formatted
      differently (with blends instead of a separate tuple variation
      store, perhaps using floats instead of fixed-point values of
      different scales, etc.) But would the meaning of the parameters be
      any different? Would other parameters be needed, or redundant, in
      the CFF2 case?  I don't see how, or why.<br>
      <br>
      So suppose the system worked this way instead:<br>
    </p>
    <ol>
      <li>Variable composite data is in its own table, call it "vcmp".
        It has some top-level mechanism for mapping data to GIDs
        analogous to that of COLR. The per-glyph tuple variation stores
        could be at an offset within the data.</li>
      <li>For the sake of argument, leave the per-glyph format exactly
        like it is now, except for an additional `hint flags` field in
        the component record (and minus the stuff needed to play nice in
        the glyf table, like `numberOfContours`).</li>
      <li>Prohibit the use of the existing `glyf` composite mechanism
        when using this separate table.</li>
      <li>Specify that when there is path data for a GID in the (glyf |
        CFF(2)) table, and that GID also has a composite entry, the path
        data is added with no transformation to the composite data.
        (This was asked for toward the end of the TypeCon meeting.)</li>
      <li>Specify that when there is hinting data for a GID in the (glyf
        | CFF(2)) table, (TrueType instructions or CFF stems) and that
        GID also has a composite entry, the relationship of the
        additional hinting data to the component hinting data is
        determined by the hint flags.</li>
    </ol>
    <p>The main thing to work out with this system would be the details
      of the hint flags, but those problems are analogous for the two
      path data sources.  Maybe you need different flags for glyf and
      for CFF2 — which could overlap, because one assumes mixing sources
      is off the table — but in each case the only thing to be worked
      out is how to reconcile the hinting data. (We know this because we
      already have COLR, so we already have implementations that grab
      data from the bottom-level tables, alter the points according to
      affine transformations, and render the results.)</p>
    <p>This change would have these cons:<br>
    </p>
    <ol>
      <li>A modest increase in size, due redundant loca/gvar/vcmp offset
        entries and duplication across the tuple variation stores
        (header, regions).</li>
      <li>?</li>
    </ol>
    <p>And these pros:<br>
    </p>
    <ol>
      <li>Assuming someone does the work of specifying the hinting
        behavior for CFF2, the system would work just as well with CFF2
        and glyf. This reduces pressure on glyf format changes. CFF2
        already goes above 64k glyphs, already supports cubics, and can
        already losslessly represent quadratics as cubics (at the cost
        of using floating point values in the conversion, when that
        precision is needed).</li>
      <li>If the composite system needs to do other things, its internal
        structure doesn't need to be so closely tied to the older glyf
        composite mechanism.</li>
    </ol>
    <p>Note: Although I can't make any promises, I've thought through
      some of what one would need to say about CFF2 hinting and variable
      components. It does seem like there could be a viable model here
      where overall hinting quality could approach that of the current
      system. ("Decompositing" to CFF (or CFF2) would involve some
      hinting compromises, but that's already true for CFF2 to CFF
      because of overlap.)</p>
    <h4>Variable Compositing is analogous to shaping. So what about
      substitution? (<a
href="https://github.com/harfbuzz/boring-expansion-spec/issues/104">#104</a>)<br>
    </h4>
    <p>I noted in the other question that "variable compositing" seems
      to amount to an additional, simplified shaping step. However, as
      specified the system only includes an analog of positioning, and
      lacks an analog of substitution.<br>
      <br>
      Let's consider a specific case.<br>
      <br>
      Suppose that you are working in a model that has three conceptual
      layers: atoms, molecules, and glyphs. Perhaps these are exposed by
      a font editor.<br>
      <br>
      For a given molecule, the designer decides she wants the outline
      of one atom to change within one sub-region of design space, and a
      different atom to change within a slightly different sub-region of
      design space. The molecule is used in 25 different glyphs. With
      the existing proposal it seems like there are two options:<br>
    </p>
    <ol>
      <li>Force the designer to play tricks with the masters so that all
        versions of the atom interpolate, and then position the masters
        in design space right next to each other for quick
        interpolations. This increases the burden on the designer.</li>
      <li>Allow the designer to specify different, non-interpolable
        versions of an atom in different subspaces of design space, and
        sort things out in the compiled font.</li>
    </ol>
    <p>In our example, it seems like the only option for 2 with the
      current proposal would be to use GSUB's `rvrn` or something
      similar. Given that the molecule has four versions (for each
      permutation of default and altered atom), you would need 100 GIDs
      to handle the 25 glyphs. You would also need to either duplicate
      the composite data for the other, always-present atoms across the
      four molecules, or add another "base molecule" layer into the
      hierarchy to collect that data together to avoid duplication.<br>
      <br>
      Now, of course, in *some* cases you'll need to do something like
      this anyway: mainly when swapping an atom affects the metrics of
      the ultimate glyph. But such cases seem like the exception rather
      than the rule.<br>
      <br>
      So:<br>
    </p>
    <ol>
      <li>Should there be some more targeted way of supporting this sort
        of case in a variable composite model?</li>
      <li>Does this suggest that the model should draw a little bit more
        from GSUB/GPOS and perhaps be less closely tied to the older
        glyf model? (For example, you might need distinct positioning
        data for the different atoms that can be substituted into a
        molecule, perhaps loosely analogous to distinct contextual
        positioning GPOS rules that could apply after a substitution.)</li>
    </ol>
    <p><br>
    </p>
  </body>
</html>