Bug 206898 - Letter-spacing is applied before shaping in the fast text codepath
Summary: Letter-spacing is applied before shaping in the fast text codepath
Status: RESOLVED DUPLICATE of bug 214769
Alias: None
Product: WebKit
Classification: Unclassified
Component: Text (show other bugs)
Version: Safari Technology Preview
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-01-28 11:43 PST by Stephen Nixon
Modified: 2020-08-17 02:35 PDT (History)
2 users (show)

See Also:


Attachments
Issue first noticed in l.sans, which is subbed in for MONO = 0 styles (305.71 KB, image/png)
2020-01-28 11:43 PST, Stephen Nixon
no flags Details
Adding a font-feature-settings stylistic set will hack the spacing to work properly again (144.87 KB, image/gif)
2020-01-28 21:56 PST, Stephen Nixon
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stephen Nixon 2020-01-28 11:43:05 PST
Created attachment 389041 [details]
Issue first noticed in l.sans, which is subbed in for MONO = 0 styles

(Also posted  with additional screenshots at https://github.com/arrowtype/recursive/issues/307)

## Description of the problem

In Safari on macOS & iOS, some glyphs keep a fixed advance width even if `letter-spacing` is changed significantly (up or down). This problem does not occur in Chrome or Firefox. This problem is not changed by any combination of variable axis values (e.g. by placing non-registered axes above their min value). Rather, it is present whenever a glyph has been substituted with `rvrn` (Required Variation Alternates, https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-rvrn).

Examples in Recursive font:

- the lowercase `l` keeps same right margin in Sans & Mono styles (`MONO = 0 to 1`)
- lowercase `f`, `g`, `i`, `r` have fixed advance width in Mono styles (`MONO = 1`)
- Most lowercase glyphs have fixed advance width in slanted/Italic styles (`slnt < -7.49 or ital > 0.49`)

## To reproduce

- Download variable version of Recursive, e.g. [Recursive v1.035](https://github.com/arrowtype/recursive/tree/7333e9d9d6fc68a4f12fd4a33b909bf05c43eb0b/fonts_1.035/Variable_TTF)
- Drop into https://wakamaifondue.com using Safari web browser 
- Use test strings; try changing axis sliders to find various glyph substitutions

```
ala blb clc dld ele flf glg hlh ili jlj klk lll mlm nln olo plp qlq rlr sls tlt ulu vlv wlw xlx yly zlz
```


Useful long test string for italic styles:

```
aaa   bab   cac   dad   eae   faf   gag   hah   iai   jaj   kak   lal   mam   nan   oao   pap   qaq   rar   sas   tat   uau   vav   waw   xax   yay   zaz   aba   bbb   cbc   dbd   ebe   fbf   gbg   hbh   ibi   jbj   kbk   lbl   mbm   nbn   obo   pbp   qbq   rbr   sbs   tbt   ubu   vbv   wbw   xbx   yby   zbz   aca   bcb   ccc   dcd   ece   fcf   gcg   hch   ici   jcj   kck   lcl   mcm   ncn   oco   pcp   qcq   rcr   scs   tct   ucu   vcv   wcw   xcx   ycy   zcz   ada   bdb   cdc   ddd   ede   fdf   gdg   hdh   idi   jdj   kdk   ldl   mdm   ndn   odo   pdp   qdq   rdr   sds   tdt   udu   vdv   wdw   xdx   ydy   zdz   aea   beb   cec   ded   eee   fef   geg   heh   iei   jej   kek   lel   mem   nen   oeo   pep   qeq   rer   ses   tet   ueu   vev   wew   xex   yey   zez   afa   bfb   cfc   dfd   efe   fff   gfg   hfh   ifi   jfj   kfk   lfl   mfm   nfn   ofo   pfp   qfq   rfr   sfs   tft   ufu   vfv   wfw   xfx   yfy   zfz   aga   bgb   cgc   dgd   ege   fgf   ggg   hgh   igi   jgj   kgk   lgl   mgm   ngn   ogo   pgp   qgq   rgr   sgs   tgt   ugu   vgv   wgw   xgx   ygy   zgz   aha   bhb   chc   dhd   ehe   fhf   ghg   hhh   ihi   jhj   khk   lhl   mhm   nhn   oho   php   qhq   rhr   shs   tht   uhu   vhv   whw   xhx   yhy   zhz   aia   bib   cic   did   eie   fif   gig   hih   iii   jij   kik   lil   mim   nin   oio   pip   qiq   rir   sis   tit   uiu   viv   wiw   xix   yiy   ziz   aja   bjb   cjc   djd   eje   fjf   gjg   hjh   iji   jjj   kjk   ljl   mjm   njn   ojo   pjp   qjq   rjr   sjs   tjt   uju   vjv   wjw   xjx   yjy   zjz   aka   bkb   ckc   dkd   eke   fkf   gkg   hkh   iki   jkj   kkk   lkl   mkm   nkn   oko   pkp   qkq   rkr   sks   tkt   uku   vkv   wkw   xkx   yky   zkz   ala   blb   clc   dld   ele   flf   glg   hlh   ili   jlj   klk   lll   mlm   nln   olo   plp   qlq   rlr   sls   tlt   ulu   vlv   wlw   xlx   yly   zlz   ama   bmb   cmc   dmd   eme   fmf   gmg   hmh   imi   jmj   kmk   lml   mmm   nmn   omo   pmp   qmq   rmr   sms   tmt   umu   vmv   wmw   xmx   ymy   zmz   ana   bnb   cnc   dnd   ene   fnf   gng   hnh   ini   jnj   knk   lnl   mnm   nnn   ono   pnp   qnq   rnr   sns   tnt   unu   vnv   wnw   xnx   yny   znz   aoa   bob   coc   dod   eoe   fof   gog   hoh   ioi   joj   kok   lol   mom   non   ooo   pop   qoq   ror   sos   tot   uou   vov   wow   xox   yoy   zoz   apa   bpb   cpc   dpd   epe   fpf   gpg   hph   ipi   jpj   kpk   lpl   mpm   npn   opo   ppp   qpq   rpr   sps   tpt   upu   vpv   wpw   xpx   ypy   zpz   aqa   bqb   cqc   dqd   eqe   fqf   gqg   hqh   iqi   jqj   kqk   lql   mqm   nqn   oqo   pqp   qqq   rqr   sqs   tqt   uqu   vqv   wqw   xqx   yqy   zqz   ara   brb   crc   drd   ere   frf   grg   hrh   iri   jrj   krk   lrl   mrm   nrn   oro   prp   qrq   rrr   srs   trt   uru   vrv   wrw   xrx   yry   zrz   asa   bsb   csc   dsd   ese   fsf   gsg   hsh   isi   jsj   ksk   lsl   msm   nsn   oso   psp   qsq   rsr   sss   tst   usu   vsv   wsw   xsx   ysy   zsz   ata   btb   ctc   dtd   ete   ftf   gtg   hth   iti   jtj   ktk   ltl   mtm   ntn   oto   ptp   qtq   rtr   sts   ttt   utu   vtv   wtw   xtx   yty   ztz   aua   bub   cuc   dud   eue   fuf   gug   huh   iui   juj   kuk   lul   mum   nun   ouo   pup   quq   rur   sus   tut   uuu   vuv   wuw   xux   yuy   zuz   ava   bvb   cvc   dvd   eve   fvf   gvg   hvh   ivi   jvj   kvk   lvl   mvm   nvn   ovo   pvp   qvq   rvr   svs   tvt   uvu   vvv   wvw   xvx   yvy   zvz   awa   bwb   cwc   dwd   ewe   fwf   gwg   hwh   iwi   jwj   kwk   lwl   mwm   nwn   owo   pwp   qwq   rwr   sws   twt   uwu   vwv   www   xwx   ywy   zwz   axa   bxb   cxc   dxd   exe   fxf   gxg   hxh   ixi   jxj   kxk   lxl   mxm   nxn   oxo   pxp   qxq   rxr   sxs   txt   uxu   vxv   wxw   xxx   yxy   zxz   aya   byb   cyc   dyd   eye   fyf   gyg   hyh   iyi   jyj   kyk   lyl   mym   nyn   oyo   pyp   qyq   ryr   sys   tyt   uyu   vyv   wyw   xyx   yyy   zyz   aza   bzb   czc   dzd   eze   fzf   gzg   hzh   izi   jzj   kzk   lzl   mzm   nzn   ozo   pzp   qzq   rzr   szs   tzt   uzu   vzv   wzw   xzx   yzy   zzz
```

## Environment

- Platform: macOS 10.15.2 (Catalina), iOS 13.2
- Font version: v1.030, v1.034, v1.035

## Other details

Issue spotted in live websites & reproduced at wakamaifondue.com and axis-praxis.org.

Issue is not shown in static fonts, reinforcing the theory that this is a problem related to `rvrn`/GSUB.

Also happens in other variable fonts, such as Fraunces (which uses `rvrn` to sub-in alternate versions of glyphs like n, s, m.
Comment 1 Stephen Nixon 2020-01-28 21:54:50 PST
Observation:

Adding the CSS 'font-feature-settings' and any stylistic set makes the spacing respond as expected (even if the stylistic set doesn't affect the characters in a given piece of text).

Here is a GIF demonstrating this CSS hack:

https://www.dropbox.com/s/u40vn5cbxosg4f6/webkit-bug-report-css-hack_fix-206898.gif?dl=0

This leads me to believe that it might be something related to the text renderer used to render variable fonts ... perhaps a slower / more careful one should be used in text that includes rvrn substitutions? This is a total guess at what is happening and what might fix it, based on my understanding of a fix to an older problem with variable fonts in web browsers (contour overlaps were once rendered with faint hairlines – https://twitter.com/ThunderNixon/status/1009878237068001280?s=20).
Comment 2 Stephen Nixon 2020-01-28 21:56:00 PST
Created attachment 389104 [details]
Adding a font-feature-settings stylistic set will hack the spacing to work properly again

Adding a font-feature-settings stylistic set will hack the spacing to work properly again. This may be due to a different text renderer being activated by the "advanced" typographic CSS, or something similar.
Comment 3 Radar WebKit Bug Importer 2020-01-29 13:56:43 PST
<rdar://problem/59005499>
Comment 4 Myles C. Maxfield 2020-02-11 10:57:33 PST
I'm having trouble reproducing this bug. Do you think you could be a little more specific than "try changing axis sliders to find various glyph substitutions"?

It sounds like you're interested in content like:
"<div style="font: 48px 'Recursive'; letter-spacing: -10px;">abcd</div>"

Is there some other style I can apply that either A) is supposed to look identical to the one above, but doesn't, or B) is supposed to look different to the one above, but actually looks the same?

Sorry, I'm just struggling to find something specific to investigate.
Comment 5 Stephen Nixon 2020-02-12 08:27:49 PST
Thanks for taking a look at this, Miles!

Sorry, I could have been more clear.

Start with this example:

<div style="font: 25vw 'Recursive'; letter-spacing: -0.2em; font-variation-settings: 'ital' 1">ooaoo</div>

(also at https://codepen.io/thundernixon/pen/dyoYdaZ?editors=1100)

In Chrome or Firefox, all letters are touching. In Safari, the "a" has a huge gap to the right side. This is because it keeps its same "advance width", despite other letter spaces decreases as they should. By contrast, the overall spacing of “o” changes according to letter-spacing.

If you change 'ital' to 0, the “a” will change from its italic alternate to its two-story default shape. Now, its spacing will adjust properly with letter-spacing changes. At "letter-spacing: -0.2em;" all letters should touch. But, any alternates, like italic alts, that are subbed in with 'rvrn' (required variation alternates) are unaffected by letter-spacing.

You can hack around this by adding a style like:

font-feature-settings: 'ss17';

But obviously, this hack isn’t intentional, intuitive, or ideal.

In place of “a” you could use any glyph that has an italic alt, such as “b d e g h I j k m n u v w y” (if I’m remembering italic subs in the Sans styles correctly). “o” doesn’t have an alt, so it is unaffected.

I realize this is kind of deep in type details, so please let me know if I can clarify any better. Thanks again!
Comment 6 Myles C. Maxfield 2020-02-18 19:19:01 PST
Oh, this is because, in the fast text codepath, we apply letter-spacing before shaping, which is wrong. It just usually doesn't cause problems, so AFAIK this is the first bug filed about it.
Comment 7 Myles C. Maxfield 2020-08-17 02:35:06 PDT
I fixed this in https://bugs.webkit.org/show_bug.cgi?id=214769.

*** This bug has been marked as a duplicate of bug 214769 ***