LibreOffice 5.3.0 adds OpenType Layout feature support

2»

Comments

  • David Perry
    David Perry Posts: 23
    Is there a complete list of the switches one can use with Graphite or OT formatting?  I know the common ones but wasn't aware of [:1]; there may be others available.  Internet searching didn't find anything.

    Further developing the Typography Toolbar to support more OT features would be very helpful!
  • Khaled Hosny
    Khaled Hosny Posts: 289
    edited May 2017
    It is the same syntax used by hb-view, but separated by ampersand instead of comma:

    $ hb-view --help-features
    Usage:
      hb-view [OPTION?] [FONT-FILE] [TEXT]

    Features options:
      --features=list                       Comma-separated list of font features

        Features can be enabled or disabled, either globally or limited to
        specific character ranges.  The format for specifying feature settings
        follows.  All valid CSS font-feature-settings values other than 'normal'
        and 'inherited' are also accepted, though, not documented below.

        The range indices refer to the positions between Unicode characters,
        unless the --utf8-clusters is provided, in which case range indices
        refer to UTF-8 byte indices. The position before the first character
        is always 0.

        The format is Python-esque.  Here is how it all works:

          Syntax:       Value:    Start:    End:

        Setting value:
          "kern"        1         0         ?         # Turn feature on
          "+kern"       1         0         ?         # Turn feature on
          "-kern"       0         0         ?         # Turn feature off
          "kern=0"      0         0         ?         # Turn feature off
          "kern=1"      1         0         ?         # Turn feature on
          "aalt=2"      2         0         ?         # Choose 2nd alternate

        Setting index:
          "kern[]"      1         0         ?         # Turn feature on
          "kern[:]"     1         0         ?         # Turn feature on
          "kern[5:]"    1         5         ?         # Turn feature on, partial
          "kern[:5]"    1         0         5         # Turn feature on, partial
          "kern[3:5]"   1         3         5         # Turn feature on, range
          "kern[3]"     1         3         3+1       # Turn feature on, single char

        Mixing it all:

          "aalt[3:5]=2" 2         3         5         # Turn 2nd alternate on for range

  • Khaled Hosny
    Khaled Hosny Posts: 289
    I have been thinking the other day, and one solution that came to mind (in terms of HarfBuzz API) is to treat script and language like user features; i.e. instead of splitting the runs on script/language change, keep the text intact and pass language and script as ranges and HarfBuzz would first collect the features applied to each character based on the script and language and then apply these features like it does now with user features. This should work in theory, but I don’t know how much change in needed for HarfBuzz, or possible breakage this might cause.
  • David Perry
    David Perry Posts: 23
    Thank you for the feature settings!
  • Adam Twardoch
    Adam Twardoch Posts: 515
    Khaled,

    that won't help because in OpenType, features have their separate implementations per script and languagesystem. In OT, "liga" for "latn/DFLT" may be implemented via Lookup1 and for "cyrl/DFLT" via Lookup2 and Lookup3. There is no way of knowing which lookups should be executed at the boundary of scripts and languagesystems. For user features it's easier because you just execute the lookups defined for a given feature on the smaller run and then continue executing the other lookups on the larger run. The lookups defined for one script and languagesystem are designed to work together, in an additive fashion, bit those for different scripts or languagesystems may be mutually exclusive.
  • Khaled Hosny
    Khaled Hosny Posts: 289
    I’d assume that DFLT/dflt be used for anything that is not language system specific which would then allow across language and script boundaries. For example a “Wα” kerning lookup would be under DFLT/dflt, and after the engine determined collected the lookups to apply on each character, both will have the same kerning lookup so I assume it would just work. I obviously haven’t thought about this thoroughly so I might be wrong, and I need to consult HarfBuzz code to see how it collects and applies the lookups.

  • Adam Twardoch
    Adam Twardoch Posts: 515
    edited May 2017
    As I wrote before, I have a feeling that for GPOS, the script/languagesystem organization does more harm than good. I think it was a deficiency of the original OT concept. For GSUB, it does make sense because each script-specific shaping engine applies certain GSUB features in an "automagical" way.

    But for GPOS, I don't see any need for script-specific processing (I may be wrong so I'd be open for any pointers where script-specific GPOS is needed). For GSUB, the linguistic identity of glyphs matters, but for GPOS, it very likely doesn't. 

    So your suggestion is somewhat right — ideally, all script-itemized "microruns" should be merged after GSUB is done, and GPOS should be applied on "macroruns", possibly just using the DFLT script. 

    But my point is also that, given the advances of math layout and variable fonts, and given the known deficiencies of the current GPOS model, a completely new spacing paradigm might be desired. 
  • Adam Twardoch
    Adam Twardoch Posts: 515
    Also: note that positioning via multiple lookups is tricky because the results are cumulative. So in case of something like "AWЛЭ" there may be weird results of you try to do some "clever" stuff like overlapping the microruns (those itemized per script). I.e. AW via latn, WЛ via DFLT and ЛЭ via cyrl. Also, lookups even for kerning may be contextual, and it'll be tricky to determine the context scope. Either way, trying to haphazardly mingle with the way GPOS is done today may lead to very odd results in edge cases. 
  • Thomas Phinney
    Thomas Phinney Posts: 2,871
    I've gone and commented on the bug. While there are other things to worry about, it is so brain-dead a behavior that I had to comment. Kerning across text that is formatted with different OT features is such an incredibly common use case! Has nobody seen an initial cap followed by small caps?
  • Khaled Hosny
    Khaled Hosny Posts: 289
    Has nobody seen an initial cap followed by small caps?

    That shouldn’t be an issue if one is using “smcp” feature, since you can activate it for the whole string but it will only apply to lowercase characters (it would be an issue if one is using “c2sc”, though).

  • Thomas Phinney
    Thomas Phinney Posts: 2,871
    True... but there are many other use cases. Swash applied to only the first or last letter of the word is another.
  • Adam Twardoch
    Adam Twardoch Posts: 515
    Also all kinds of manually-applied superscripts and subscripts, but probably most importantly switching on single glyphs to their ssXX or cvXX variants in the middle of text. 
  • John Hudson
    John Hudson Posts: 3,177
    Yes, failing to kern super- and subscript variants with preceding full size f, for example, can be a real disaster.

    Basically, any time two glyphs are in proximity to each other, their positioning may need to be adjusted, so splitting runs is inherently problematic. Splitting runs based on layout features applied seems to me particularly stupid, since the whole point of run itemisation in OTL is to determine the minimum range of glyphs across which lookups should be applied. If one then starts further subdividing that run, such that lookups are no longer applied, then one has broken the layout model.
  • Adam Twardoch
    Adam Twardoch Posts: 515
    edited May 2017
    But even that is underdefined.

    1. If I have the word "Zeitgeist" and I enable the "cwsh" (contextual swash) feature, or any feature that is implemented using contextual lookups, for the "gei" portion, and the lookups that are supposed to be applied on that portion of text use 2-glyph backtracks and 2-glyph lookaheads — what should be the context when the "e" glyph inside "gei" gets processed? (And: where is this behavior described?)
  • Adam Twardoch
    Adam Twardoch Posts: 515
    2. If I have the word "office" and I enable the "liga" feature on the "ff" portion, yet the font also includes an f f i -> ffi ligature substitution, what should happen? 

    3. What if in the above example the font has a Cambria-store contextual substitution of an f -> f.short if followed by an f or an i — what then? 

  • John Hudson
    John Hudson Posts: 3,177
    edited May 2017
    If a user is making a specific selection of characters from within the string that constitutes the larger glyph run and applying a specific features only to that selection, then I would expect any lookups for that feature to be applied only to that selection, and not to the larger run. And yes, this may produce unexpected, unwanted or, indeed, no result, depending on the selection.

    That's a different scenario from a layout engine creating an entirely new and separate glyph run on the basis of a feature being applied to only part of the whole run, such that no further features can apply across the new run boundaries. I think we should maintain clarity about the difference in these situations, and probably discuss them separately.

    I think the answer to your liga question (2) is pretty obvious: only the ligature that has coverage within the selection gets applied, i.e. /f_f/ and not /f_f_i/.

    The question about contextual lookups is interesting, though. Personally, I think a strong case can be made for considering the whole run — i.e. the glyphs beyond the selection — when seeking a contextual match for a substitution within the selection. Put it another way, I would consider the coverage for a GSUB lookup to be the input for the actual substitution — does that occur within the selection — and the context to apply to the whole run. To be honest, I'm not entirely sure what the various layout engines do in this regard. Won't it be fun if they're inconsistent!