charming icon indicating copy to clipboard operation
charming copied to clipboard

some colour flag emojis are busted in chrome

Open ar1a opened this issue 9 months ago • 8 comments

Image

seems like the twemoji font we compile no longer renders colour emoji in chrome. works in firefox still

don't render (invisible/wrong): 🏳️‍⚧️ 🏳️‍🌈 🏳️🏴‍☠️ country flags all seem like they work fine, even wales so do family emojis, and different skin colour tones

seems like it's just the colour flags. interestingly all the ones i've found stem from either 🏳 or 🏴

ar1a avatar Mar 10 '25 06:03 ar1a

trying to bisect where it breaks

running content-shell with --no-sandbox https://charming.daz.cat/#1F3F3-FE0F-200D-26A7-FE0F

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1300012/ works

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1200026/ works

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1350005/ works

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1375017/ broken

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1362519/ works

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1368752/ works

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1371854/ uses system font

bisect between 1371854 and 1375017 for system font → broken

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1373408/ broken

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1372651/ broken

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1372221/ broken

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1372030/ uses system font

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1372158/ broken

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1372080/ broken

yet to be determined where it switches from using the font to using the system font, but for where it just stops rendering entirely seemed to happen between 1372030 and 1372080

bisect between 1368752 and 1371854 for works → system font

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1370350/ uses system font

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1369563/ uses system font

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1369149/ uses system font but gradients don't work? (possibly rendering as COLRv0?) gonna keep looking for the commit that stops working

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1368947/ uses system font with no gradients

https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/1368866/ uses system font with no gradients

ar1a avatar Mar 20 '25 02:03 ar1a

bisect between 1371854 and 1375017 for system font → broken

smallest gap between snapshots was 13720301372080. most likely culprit is 1372053:

Check for colour tables to identify if the font has coloured glyphs

Before we were using ignore vs state for system fallback fonts on
multiple platforms, since a lot of system fonts does not have cmap 14
subtable which we use to get a glyph for variation sequence. But that
state was not applied user specified system fonts (i.e. system font
families defined in `font-family` property). Maintaining the correct
state of `IsSystemFallbackStage` might be a bit messy, since we need to
update the state for each font in `FontFallbackIterator`.

In CL we are checking for the existence of colour tables in a font only
if we failed to find a glyph for a variation sequence, but found a glyph
for a base code point from emoji variation sequence. Based on the found
colour tables we make an assumption if font has coloured or a
monochromatic glyph for the base code point. This login will replace
ignore vs state for system fallback fonts logic.

This CL was testes on speedometer3 and blink_perf.layout, the results
below don't show significant loss.

Bug: 373551501
Change-Id: [If60540cf830d53608707cb01c88216a341a7f6ed](https://chromium-review.googlesource.com/#/q/If60540cf830d53608707cb01c88216a341a7f6ed)
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5937852
Commit-Queue: Munira Tursunova <[email protected]>
Reviewed-by: Dominik Röttsches <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1372053}

delan avatar Mar 20 '25 03:03 delan

bisect between 1368752 and 1371854 for works → system font

smallest gap between snapshots was 13687521368866.

1368791?

Make GlyphBoundsAccumulator faster by changing rect storage.

This stores rects by their edges, rather than as point and size, to make
union operations faster.

Note that this has an extremely subtle behavior difference that I'm
hoping is not important:  it doesn't retain the behavior in
RectF::UnionEvenIfEmpty that calls Size::SetToNextWidth/Height to
ensure that any floating point inaccuracy biases towards rounding the
right and bottom edges outwards.  This behavior could be readded here
(at lower cost than before) if needed.

This is a 1.5% win on the Editor-TipTap sub-benchmark of Speedometer3,
and might make a difference on other sub-benchmarks.

Change-Id: [Ie9352b67e6bf7acb19aa404abeffc116f763f056](https://chromium-review.googlesource.com/#/q/Ie9352b67e6bf7acb19aa404abeffc116f763f056)
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5922434
Commit-Queue: David Baron <[email protected]>
Reviewed-by: Koji Ishii <[email protected]>
Reviewed-by: Ian Kilpatrick <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1368791}

1368803?

[Fonts] Add early exit to LocalFontFaceSource::CreateFontData

Prior to 3b74af71bef301c7b29a1571d61cbb045602dde7,
`LocalFontFaceSource::CreateFontData` could potentially return
nullptr if `FontCache::Get().GetFontData` returns nullptr.

After that change, there is a dereference on the return value from
`FontCache::Get().GetFontData` without checking for nullptr.

This change adds a simple nullptr check and early return.
Unfortunately, OOM is not easy to simulate in unit tests, so no
tests are provided.

Bug: 373290673
Change-Id: [I39929c4d0a70234338b6e3a8009ba4479fb581ce](https://chromium-review.googlesource.com/#/q/I39929c4d0a70234338b6e3a8009ba4479fb581ce)
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5931265
Commit-Queue: Kurt Catti-Schmidt <[email protected]>
Reviewed-by: Dominik Röttsches <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1368803}

delan avatar Mar 20 '25 03:03 delan

some history. d43f2ff86e0ccd99a19db68f24d2996de7752514 ensures we only use the twemoji font when Emoji_Presentation=Yes. a5fc299c9d7ec8566945e7dafe8fc4d18c733f15 replaces @13rac1’s SVGinOT font with our own COLRv0 font built from the twemoji svg sources. 822222a628127ca065ebce11a8d7703322f3d8e1 handles Emoji_Presentation as part of our then-new support for sequences (#45).

in both cases, we handle Emoji_Presentation in the frontend via the data system, but 822222a628127ca065ebce11a8d7703322f3d8e1 also tries to make the font itself handle Emoji_Presentation correctly, even if they happen to be used outside of the charming frontend, by renaming input files like 2122.svg (™) to 2122-fe0f.svg (the dreaded ™️). our interpretation of uts #51 is that the fully-qualified encoding is “ideal” for emoji zwj sequences like 1f3f3-fe0f-200d-26a7-fe0f.svg (🏳️‍⚧️), even though minimally-qualified (1f3f3-fe0f-200d-26a7.svg) or unqualified (1f3f3-200d-26a7.svg) encodings are sometimes acceptable.


in googlefonts/nanoemoji#436, we learn that nanoemoji builds fonts that map unicode to glyphs with a cmap table plus ccmp substitutions in a GSUB table, using the codepoints given in the input filenames. interestingly this may yield blank glyphs for codepoints that are only used in emoji sequences, but that was not quite the cause of this bug.

in googlefonts/nanoemoji#449, we learn that ideally our color emoji font would accept any encoding of an emoji that would lead to emoji presentation, and that a good way to do this might be to use a cmap subtable with format 14 (0/5/14), for unicode variation sequences. with that approach, we would strip any vs16 (fe0f) out of the GSUB table, even for emoji characters where Emoji_Presentation=No.

unfortunately nanoemoji does neither of those things, because it was originally designed for the noto color emoji build process. over there, input filenames are stripped of vs16 (fe0f) before nanoemoji, and cmap 0/5/14 is generated after nanoemoji. in charming, we just use the ideal encoding in cmap and GSUB without generating cmap 0/5/14. this worked everywhere until fairly recently, but it’s not clear if this was Correct.

in crbug 383824583 (via element-hq/element-web#28500), we learn that CL:5961459, originally reviewed in CL:5937852 (rev 1372053), was indeed relevant. but as we’ve found, charming’s color emoji font was broken in chromium even earlier, between 1368752 and 1368866, just in a different way: our font was getting ignored in favour of the system emoji font. i have no idea why yet, because when i tried to bisect on my linux machine, i got strange results that contradicted @ar1a’s bisect of the windows snapshots.

i’m not yet sure what approach is best for fixing this bug. if we continue to use a webfont for color emoji, we ideally want to go the cmap 14 route, but the only existing impl i know of is colrv1_postproc.py. but we may be able to get away with throwing in some vs16-less encodings in the font without cmap 14, as long as we’re ok with the font handling Emoji_Presentation incorrectly outside of charming! see the “everything” row below.


Chrome 133.0.6943.126 (Official Build) on Linux:

Image

Firefox 135.0.1 on Linux:

Image

patched
$ ls helper/twemoji-15.1.0/assets/svg.patched
1f3f3-fe0f-200d-1f308.svg      1f3f3-fe0f.svg  26a7-fe0f.svg
1f3f3-fe0f-200d-26a7-fe0f.svg  2122-fe0f.svg   30-fe0f-20e3.svg

$ cat helper/build.patched/Font.fea
languagesystem DFLT dflt;
languagesystem latn dflt;

feature ccmp {
  sub g_30 fe0f g_20e3 by g_30_fe0f_20e3;
  sub g_2122 fe0f by g_2122_fe0f;
  sub g_26a7 fe0f by g_26a7_fe0f;
  sub g_1f3f3 fe0f by g_1f3f3_fe0f;
  sub g_1f3f3 fe0f g_200d g_26a7 fe0f by g_1f3f3_fe0f_200d_26a7_fe0f;
  sub g_1f3f3 fe0f g_200d g_1f308 by g_1f3f3_fe0f_200d_1f308;
} ccmp;
unpatched
$ ls helper/twemoji-15.1.0/assets/svg.unpatched
1f3f3-200d-1f308.svg  1f3f3-fe0f-200d-1f308.svg      1f3f3.svg  26a7.svg
1f3f3-200d-26a7.svg   1f3f3-fe0f-200d-26a7-fe0f.svg  2122.svg   30-20e3.svg

$ cat helper/build.unpatched/Font.fea
languagesystem DFLT dflt;
languagesystem latn dflt;

feature ccmp {
  sub g_30 g_20e3 by g_30_20e3;
  sub g_1f3f3 g_200d g_26a7 by g_1f3f3_200d_26a7;
  sub g_1f3f3 g_200d g_1f308 by g_1f3f3_200d_1f308;
  sub g_1f3f3 fe0f g_200d g_26a7 fe0f by g_1f3f3_fe0f_200d_26a7_fe0f;
  sub g_1f3f3 fe0f g_200d g_1f308 by g_1f3f3_fe0f_200d_1f308;
} ccmp;
notoish
$ ls helper/twemoji-15.1.0/assets/svg.notoish
1f3f3-200d-1f308.svg  1f3f3-200d-26a7.svg  1f3f3.svg  2122.svg  26a7.svg  30-20e3.svg

$ cat helper/build.notoish/Font.fea
languagesystem DFLT dflt;
languagesystem latn dflt;

feature ccmp {
  sub g_30 g_20e3 by g_30_20e3;
  sub g_1f3f3 g_200d g_26a7 by g_1f3f3_200d_26a7;
  sub g_1f3f3 g_200d g_1f308 by g_1f3f3_200d_1f308;
} ccmp;
everything
$ ls helper/twemoji-15.1.0/assets/svg.everything
1f3f3-200d-1f308.svg            1f3f3-fe0f-200d-1f308.svg      1f3f3.svg      26a7-fe0f.svg  30-fe0f-20e3.svg
1f3f3-200d-26a7.svg             1f3f3-fe0f-200d-26a7-fe0f.svg  2122-fe0f.svg  26a7.svg
1f3f3-fe0f-200d-1f308-fe0f.svg  1f3f3-fe0f.svg                 2122.svg       30-20e3.svg

$ cat helper/build.everything/Font.fea
languagesystem DFLT dflt;
languagesystem latn dflt;

feature ccmp {
  sub g_30 g_20e3 by g_30_20e3;
  sub g_30 fe0f g_20e3 by g_30_fe0f_20e3;
  sub g_2122 fe0f by g_2122_fe0f;
  sub g_26a7 fe0f by g_26a7_fe0f;
  sub g_1f3f3 g_200d g_26a7 by g_1f3f3_200d_26a7;
  sub g_1f3f3 g_200d g_1f308 by g_1f3f3_200d_1f308;
  sub g_1f3f3 fe0f by g_1f3f3_fe0f;
  sub g_1f3f3 fe0f g_200d g_26a7 fe0f by g_1f3f3_fe0f_200d_26a7_fe0f;
  sub g_1f3f3 fe0f g_200d g_1f308 by g_1f3f3_fe0f_200d_1f308;
  sub g_1f3f3 fe0f g_200d g_1f308 fe0f by g_1f3f3_fe0f_200d_1f308_fe0f;
} ccmp;

delan avatar Mar 20 '25 12:03 delan

as long as we’re ok with the font handling Emoji_Presentation incorrectly outside of charming

I think this is completely fine, we're not distributing a twemoji webfont for use, we're just using it In Our App. I think the way to go is the technically less correct approach, but only using the font when Emoji Presentation = Yes

ar1a avatar Mar 22 '25 04:03 ar1a

Looking at some potential nanoemoji alternatives, i instantly go check out rust.

there's write-fonts, which seems potentially useful, but it's also a dependency of fontc which i'm about to check out

the description of https://github.com/googlefonts/fontc/milestone/4?closed=1 leads me to see that they will declare some kind of .glyphs or .designspace, and then can compile from that down to a font. A .glyphs file looks like it's way too low level for what we want, and nanoemoji seems to generate a .glyphmap file (which is effectively just a csv), and a .fea file - neither of which it looks like fontc can handle.

fontc honestly seems extremely undocumented. maybe i should be looking at fontmake, their python original they're replacing with the rust fontc. fontmake seems to take in 3 different styles of input file. A source file for Glyphs^tmtmtm, a .ufo or .ufoz file, or a ".designspace" file, whatever that is

I wonder what nanoemoji does under the hood? Could we write our own custom twemoji compiler the Right^tmtmtm way with something like write-fonts?

hmmm, looks pretty intense. we might be able to hack something together to modify a nanoemoji-generated-font into something that's a bit more Correct. If we go down the path of wanting to modify the font to be more "Correct", i think this is the way to go. buuuut, i still think the Easier and Perfectly Fine option of my previous comment is the way to go, at least for now

ar1a avatar Mar 22 '25 05:03 ar1a

it sounds a lot like the fix is https://github.com/element-hq/element-web/issues/28500#issuecomment-2614730697 which has been working well for us. perhaps switch to using Element's twemoji fork?

ara4n avatar Apr 13 '25 19:04 ara4n

quite potentially! we found vaguely the same answer as you did, by removing the variation selectors. i will try using that font later and seeing how it goes - and check compatability on other systems

ar1a avatar Apr 14 '25 04:04 ar1a