Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve/fix OpenMoji Colorfont (and Black) #93

Closed
b-g opened this issue Dec 2, 2019 · 50 comments · Fixed by #422
Closed

Improve/fix OpenMoji Colorfont (and Black) #93

b-g opened this issue Dec 2, 2019 · 50 comments · Fixed by #422

Comments

@b-g
Copy link
Member

b-g commented Dec 2, 2019

The OpenMoji colorfont is currently just a proof of concept and only works in Firefox.

We hope to improve this to proper colorfont in the near future (or at least in the long run). Sorry + stay tuned and follow this thread for updates!

@b-g
Copy link
Member Author

b-g commented Dec 2, 2019

#66 (comment)

@b-g
Copy link
Member Author

b-g commented Dec 2, 2019

This is to gather a few links.

Currently we use https://github.com/hfg-gmuend/openmoji/blob/master/font/README.md basically SVGinOT Color Font Builder a 3-4 year old and stale project. The resulting Colorfont seem just partly to support the standard. They just work in Firefox :(

Other links:

@bohnacker
Copy link
Member

To simplify the discussion:
Which format should we support? Right now, there are four:
PNG based: Google's CBDT/CBLC tables and Apple's SBIX table
Vector based: Microsoft's overlapped glyphs (COLR/CPAL tables) and Mozilla and Adobe’s SVG (SVG table)

These formats are supported as follows at the time (source: https://pixelambacht.nl/2014/multicolor-fonts/):
Bildschirmfoto 2019-12-03 um 19 30 53
Bildschirmfoto 2019-12-03 um 19 30 43

Checking with https://pixelambacht.nl/chromacheck/ there also seems to be supported SBIX in Chrome.

My opinion: there's no way around SVG because it's much more powerful than COLR. I guess, sooner or later all browsers will support SVG Color Fonts.

Our situation:
Bildschirmfoto 2019-12-03 um 19 23 40
From left to right: Chrome, Firefox, Safari (I'm on Mac, so no quick check for Edge, ...)

Safari should support SVG Color Fonts. So, that's a bug.

@b-g
Copy link
Member Author

b-g commented Dec 3, 2019

Hi @bohnacker, many thanks for putting this together. I'm agnostic and happy to support a single standard e.g. SVG properly ... just it should be 100%. Currently our colorfont is just rendered in Firefox, but should also usable in Safari, Adobe CC, Sketch, Affinity ... which is not the case. Also @dnlutz is strongly in favor of SVG ... Hence I think SVG is the best bet, however I couldn't find a good tooling for it back at the beginning of 2019. Also note: Google Noto Emoji tooling is PNG based.

@AndydeCleyre
Copy link

I don't know what joypixels (emojione) is doing, but their color font seems to display nicely in browsers and qt apps (including konsole) on Arch linux with the repo package, which fetches joypixels-android.ttf.

@danielleontiev
Copy link

The b/w font looks damaged as well for me in LaTeX:
uwSWqRS

@b-g b-g changed the title Improve/fix OpenMoji Colorfont Improve/fix OpenMoji Colorfont (and Black) Dec 9, 2019
@b-g
Copy link
Member Author

b-g commented Dec 9, 2019

Hi @bohnacker, https://www.glyphrstudio.com/online/ a free online font editor might be interesting in terms of debugging the black font. (But also no colorfont support currently glyphr-studio/Glyphr-Studio-1#270)

@b-g
Copy link
Member Author

b-g commented Dec 9, 2019

Related font issue from #96:

Not sure how valid this is but using the black openmoji font and vscode, it shows ones we support as a single character and others as multiple characters

However we do have a pirate flag emoji so maybe this is also an issue with the font that we haven't realised?

image

@b-g b-g added the bug label Dec 9, 2019
@bohnacker
Copy link
Member

bohnacker commented Jan 3, 2020

I checked a few things with our color and black fonts and compared it with the fonts "EmojiOne Color" and "Twitter Color Emoji". I chose those because they are not from a vendor of operating systems (Apple, Windows, Google). EmojiOne is an Opentype font while the one from Twitter is Truetype. Ours is Truetype too.

It appears that our fonts are not that bad in general, but there are quite some things to improve.

The following screenshot is made in InDesign on Mac and it seems to handle the Openmoji Color font perfectly. Openmoji Black has some problems. The conversion from SVG to Truetype glyphs ignores stroke-linecap="round" and stroke-linejoin="round" (most obvious on the smiley and the TM-sign). Also, overlapping paths are not converted well (hand, soccer ball, santa claus).
Screenshot InDesign Mac

For the black font I see two possible solutions:

  1. Remove all strokes from all our source emojis and convert it to filled areas.
  2. Find a better conversion algorithm.
    The first solution is not very practical and desirable. I think it's good to have line elements in the source files as much as possible. Otherwise improving the source emojis will be a hassle.

I found another problem with our fonts in InDesign. Ligatures sometimes are split into parts when text gets wrapped. It happend with the hand and the horse but not with the dark santa claus and the flags. I'll try to find out why.
Screenshot InDesign wrapping


Comparision of the behaviour in browsers:

Firefox (Mac and Windows):
Some problems with our color font shows up. Some strokes are not scaled correctly. I'm mot complete sure why. Maybe it's because there are elements on the color layer that have both a fill color and a stroke color. Or it has something to do with transforms that are still in some emojis. Edit: Quite sure it's the first guess... the hand with yellow skin is displayed correctly, all others not because they get a stroke color while building.
Screenshot Firefox Mac

Safari (Mac):
Only EmojiOne works (maybe because it's Opentype):
Screenshot Safari Mac

Edge (Windows):
Handles our color emojis perfectly.
Screenshot Edge Windows

@bohnacker
Copy link
Member

Maybe we could use some other libraries like this to convert all strokes in the black SVGs to areas before creating the truetype glyphs:
https://www.npmjs.com/package/js-clipper

It seems to support all we need (stroke-linecap="round" and stroke-linejoin="round"). The fact that it is not developed further on is not a problem in my opinion because it has no dependencies.

Or has anybody good experiences with other libraries for path operations?

@b-g
Copy link
Member Author

b-g commented Jan 5, 2020

Hi @bohnacker! A belated happy new year + many thanks for the investigation! That sounds a lot more promising than I've anticipated! Yay! A few comments/thoughts:

OpenMoji Black

  • I would vote to introduce a dedicated build process which converts all problematic strokes to shapes ... but not to alter the src svg files
  • Instead of js-clipper I would rather bet on paper.js (in node.js) with the paperjs-offset plugin. (See also the discussion on Parametrized stroke outlining / expanding / offsetting with paper.js)
  • Q: Would we have to convert every stroke or just the ones with stroke-linecap="round" and stroke-linejoin="round" attributes?

OpenMoji Color

  • Q: Is the issue with svgs which have both a fill color and a stroke color a Firefox bug only? If so ... should we simply ignore it?
  • Q: Should we ditch current color font generator or stick with it? I can offer to improve the generator "scfbuild" to support properly generating the two fonts without the current hustle ... but this makes only sense if the scfbuild is worth the invest. (I guess it won't be possible to generate a colorfont in opentype flavor with scfbuild, or?)

@bohnacker
Copy link
Member

Hi @b-g, some answers to your questions and suggestions:

I would vote to introduce a dedicated build process which converts all problematic strokes to shapes ... but not to alter the src svg files

Yes, I think so too. That's the only approach that makes sense.

Instead of js-clipper I would rather bet on paper.js (in node.js) with the paperjs-offset plugin. (See also the discussion on Parametrized stroke outlining / expanding / offsetting with paper.js)

I also agree. I had a look at js-clipper and found that it converts all curves to polygons. The result will be glyphs that will look bad when scaling them up a lot. Still we have to check if paperjs is doing everything correctly.

Would we have to convert every stroke or just the ones with stroke-linecap="round" and stroke-linejoin="round" attributes?

Best would be to convert every stroke beforehand because scfbuild (or whereever this is done) has also problems with paths that are crossing itself (see hand and soccer ball in the above examples). In the end (as a glyph) everything will be areas.

Q: Is the issue with svgs which have both a fill color and a stroke color a Firefox bug only? If so ... should we simply ignore it?

As far as I've seen, it's a Firefox only bug. Maybe we could ignore it and hope for a bug fix on the Firefox side.

Q: Should we ditch current color font generator or stick with it? I can offer to improve the generator "scfbuild" to support properly generating the two fonts without the current hustle ... but this makes only sense if the scfbuild is worth the invest. (I guess it won't be possible to generate a colorfont in opentype flavor with scfbuild, or?)

I think we could stick with scfbuild. In general it is doing a good job as far as I've seen. I don't know if it is possible to switch to opentype using scfbuild. I think the truetype glyph creation is done with the fontforge library which should also be capable of generating opentype glyphs. But there might still be a lot more things to change...

@mikemaccana
Copy link

Note this image is 5 years out of date (it's from 2014):

70079230-9e50d800-1604-11ea-843c-20e66e936bfe

COLR works fine in Chrome now

https://pixelambacht.nl/chromacheck/

@b-g
Copy link
Member Author

b-g commented Jan 7, 2020

@mikemaccana Thanks for the heads up! :)

@bohnacker Many thanks + agree! Should I go ahead and improve scfbuild with a dedicated --black-only flag so that we can streamline the font build process, or is this too earlier and currently not helpful?

@mikemaccana
Copy link

PS is there a webpage we can see openmoji rendered in COLR format, as a webfont?

@bohnacker
Copy link
Member

@b-g: If you want you can streamline the font building but it's not urgent from my side. I'll start testing paperjs stroke conversion and exploring the other bugs.

@mikemaccana: We haven't build the font in COLR format (and I'm quite sure that we can't do that in the near future). We concentrate on debugging the SVG color font.

@b-g
Copy link
Member Author

b-g commented Apr 6, 2020

via @carlinmack

The OpenMoji colour font kinda works! You can easily test this by

image

Note that Pinata is rendered in OpenMoji now. Yay!

@dnlutz
But it also shows that the size of the glyphs is way too small! We should tweak the size in https://github.com/hfg-gmuend/openmoji/blob/master/font/scfbuild-color.yml#L8. What size would you suggest?

@dnlutz
Copy link
Contributor

dnlutz commented Apr 24, 2020

I would suggest to scale the OpenMoji by factor 1.3
The Y-position is perfect in relation to the baseline.
color_font_scaling

@carlinmack
Copy link
Contributor

Looks good!

We should highlight where the baseline is in openmoji-template.svg

@b-g
Copy link
Member Author

b-g commented May 5, 2020

Done. Scaled up by 1.3.

Scale 1 / Scale 1
Screenshot 2020-05-05 at 08 20 18

Scale 1.3 / Scale 1
Screenshot 2020-05-05 at 08 35 22

Scale 1.3 / Scale 1.3
Screenshot 2020-05-05 at 08 54 33

cc @dnlutz

@dnlutz
Copy link
Contributor

dnlutz commented May 6, 2020

Tip top / thank you! These emoji sizes now work much better within "normal" text fonts.

@RobertWinslow
Copy link
Contributor

Here's an oddity I found. The line height of the font is too high when viewed in some browsers, namely Chrome or Safari on MacOS.
See this example screenshot:
openmoji-lineheight

This is caused by certain glyphs having elements placed far outside where they should be. The commonality between the broken glyphs is that in their SVG source, they have an element which is rotated around a point other than the origin. When certain browsers display these glyphs, they rotate those pieces around (0,0) instead of the point they are supposed to rotate them around. If the transform attribute is set using a matrix or a rotation about the origin, these browsers display the resulting glyphs fine.

I found that when using FontForge to build a vanilla ttf version of the font, the same glyphs were misrendered in the same way. So I suspect the ultimate source of the error lies in FontForge's SVG importation function.

@RobertWinslow
Copy link
Contributor

I am working on an implementation of the black font using FontForge's import tools.

I'd like some feedback on a couple minor implementation details:

  • All of the regional flags look the same in outline form. They are each just a blank rectangle. Would it would be sensible to exclude regional flag characters from the black ttf?

    • Simply excluding the characters would lead to a fallback glyph being used: likely some other emoji font, and worse case a blank square. This would be at least as informative to the user, and seems like the best option to me.
    • If Regional Indicator Symbol Letters were added to OpenMoji, as discussed in issue 351, then excluding regional flags from the font would result in the flags being rendered as a pair of letter glyphs. This would of course require extra work.
    • A third option, which would require substantially more work, is to include in each flag's source a "line-supplement" group which contains the region's indicator characters. This is similar to what some other color emoji fonts use as a monochrome fallback: screenshot of Microsoft's emoji font displaying flag fallbacks in Google Chrome
  • There are some characters which are present in Unicode in both emoji and non-emoji forms, distinguished by a variation selector FE0F. Should both codepoints be encoded into the font?

    • EG: "👁" has codepoint 1F441, while "👁️" has codepoint 1F441-FE0F. OpenMoji's data files only associate the eye emoji with the former codepoint. In many applications, these two codepoints are treated as the same. However, with my font in its current implementation, some applications will render the latter codepoint in the system's default emoji font because 1F441-FE0F isn't technically present in OpenMoji.
    • Looking at Unicode's emoji test file, it seems there are about 200 such characters.
    • If both codepoints are used, then I'm not sure where to put the list of such characters; I don't see a relevant data field in OpenMoji's data files. The easiest thing to do would just be to include a array of codepoints in my build script, but that's less future proof.

@b-g
Copy link
Member Author

b-g commented Mar 9, 2022

@RobertWinslow Many thanks for the thoughts! Super! Please gives a day to ponder on the questions and to double check once more the quality of the generated glyphs of OpenMoji-MonoChrome.ttf. Stay tuned.

@dnlutz
Copy link
Contributor

dnlutz commented Mar 10, 2022

Dear @RobertWinslow thank you for your work on the fonts! The overall curve quality looks really good (as good as it can get with our mixed quality source svgs ; )

However, the fonts are really a tough topic and I have discovered a some issues when checking the files in InDesign:

duplicates
Duplicates: Some glyphs appear multiple times in an untraceable order.

fill
Fillings: Some characters have areas completely filled with black.

Do you think these issues could be resolved by code? We try to avoid manual interventions during the font built process – the effort can quickly become unmanageable ; )

At the moment the width of the glyph equals the bounding box of the paths, all emoji should get a uniform with.

I hope I have not discouraged you and I don't know if all this is feasible – but the fonts are definitely a tough job (since the start of OpenMoji in 2018).

Many Greetings

Daniel

@RobertWinslow
Copy link
Contributor

@dnlutz

Duplicates: Some glyphs appear multiple times in an untraceable order.

I suspect this is related to the way I'm handling skin-tone variations. I'm planning to try another way of handling those, though I have no clue whether it will resolve this particular issue. Alternatively, the issue might lay in how TrueType handles ligatures. OpenType handles ligatures more gracefully, so switching from ttf to otf might resolve it.

I had considered leaving skin-tone variants out of the font (it's a monochrome font, after all), but this would cause problems for glyphs with mixed skin tones, as the skin-tone codepoint occurs in the middle of the ligature.

Fillings: Some characters have areas completely filled with black. Do you think these issues could be resolved by code?

Unfortunately, I'm not sure whether they can be. There used to be very many more of these errors, and I was able to resolve most of them by cleaning up the source files. That was the impetus behind this pull request. A lot of the remaining fill errors are bespoke to individual glyphs rather than systemic issues.

For example, I've spent a while looking at the leg of that orangutan: 🦧. The issue there is that the path for the leg loops back around and self-intersects without actually being closed with a z command. This causes FontForge to 'helpfully' interpret it as a solid shape before the expandStroke method has a chance to be called.

image

A very very similar, but not quite identical, problem plagues the handshake 🤝 glyph. And now looking at the gear
2699, its source also has one of these 'pseudo-closed' paths.

The 🦧 glyph in the font could be corrected by:

  • Altering the leg path in some way - Making it properly closed with a z command, or 'splitting' the path by inserting an m 0 0 command in between two other commands.
  • Or by using a different build process. What needs to be done for each glyph is: Load up the black svg, convert strokes to paths, merge all paths into a single element, and then import that element's outline as the outline of a glyph. That's exactly what I'm having FontForge do. It's clearly not doing it exactly as I'd like it to, but I wasn't able to find another easy-to-use tool to automate the process. And even if another tool were used, it might just introduce it's own new set of rendering errors. 'Better the devil you know' so they say.

All that said, some of those filled glyphs aren't actually mis-rendering. I recognize 'keyboard' E1D1 and ◭ 25ED. That's just the 'line-supplement' layer being drawn.

At the moment the width of the glyph equals the bounding box of the paths, all emoji should get a uniform with.

Okay. That's an easy change.

I hope I have not discouraged you and I don't know if all this is feasible – but the fonts are definitely a tough job

Haha, if I were that easily discouraged, I wouldn't have gotten this far along. Thanks for the feedback. Like you say, it's a tough project.

@RobertWinslow
Copy link
Contributor

@dnlutz

Could you take a look at this new version of the font, to see if the duplicate glyph issue has been resolved?
I changed the method I used to handle the skintone variants.

Re: Giving the glyphs a uniform width. If the glyphs are scaled up by a factor of 1.3, should the width also be set 30% bigger than normal? If yes, then the font ends up unusually wide. If no, some glyphs are so wide that either they will overflow their bounding box or they will need to be scaled back down a bit. See the eye (👁️ 1F441) for an example of a very wide vector source. In the script I used to generate the font file, I included multiple parameters to adjust the width of glyphs. I'm just not sure what they should be set to.

@dnlutz
Copy link
Contributor

dnlutz commented Apr 6, 2022

dear @RobertWinslow
there seem to be less duplicates now. but there are still some, for example "People Holding Hands" exists several times. also the fill bugs are still there:
220406 fill
metrics / scaling: it would be ideal when all the glyphs retained the 72 px bounding box from the source svgs (emoji + bounding box should be scaled in the same ratio). i hope this makes sense. many greetings daniel

@RobertWinslow
Copy link
Contributor

Minor update on the above mentioned duplicate-glyph issue. I thought I had fixed skintone variants showing up as duplicate glyphs. But actually, I had just accidentally removed many of the skintone variants. Further testing has fixed the latter issue, but I suspect the issue of "duplicate" glyphs might not be solvable. (They aren't actually duplicates, just identical.)

@shaurya1709
Copy link

The only color format I know of which is cross-browser compatible is COLR(v0). Chromium(and Chromium-based browsers) do support COLRv1 since chrome 98.

@dnlutz
Copy link
Contributor

dnlutz commented May 12, 2022

Is it possible for users to change the colors in COLRv1 fonts?

@dnlutz
Copy link
Contributor

dnlutz commented May 12, 2022

Okay … I just spotted this article: https://css-tricks.com/colrv1-and-css-font-palette-web-typography/
Maybe we should go all in with COLRv1 and dump all other font formats?

@mavit
Copy link
Contributor

mavit commented May 15, 2022

Maybe we should go all in with COLRv1 and dump all other font formats?

That would certainly simplify things if we can, but I thought COLR wasn't supported by Adobe Illustrator? Is that still true, and, if so, is it a showstopper?

JeppeKlitgaard pushed a commit to JeppeKlitgaard/openmoji that referenced this issue Nov 16, 2022
This is done via the container at https://gitlab.com/mavit/nanoemoji-container.

For me, the resulting COLR TTFs work in Firefox and in the Gnome desktop
on Fedora 32 (although they display rather small).

Caveats:
- It may be premature to replace `scfbuild` for SVG builds.  If we decide to go ahead without `scfbuild`, then we’ll want to remove the remaining files related to it.  If we decide to keep `scfbuild`, then we’ll want to revert those parts of this patch.  In either case we’ll want to update the readme to link to the new outputs.
- I’ve tested this with Podman, not Docker.

Relates to hfg-gmuend#93.
RobertWinslow added a commit to RobertWinslow/openmoji that referenced this issue Dec 3, 2022
This addresses one of the rendering errors mentioned here:
hfg-gmuend#93 (comment)

The cause of this rendering error was that the path which makes up the top of the swimsuit had a self-intersection near the left shoulder-strap. 
The fix was to very slightly adjust one of the coordinates in the curve to remove the self-intersection.
This change will very slightly change the appearance of the rendered image.
@RobertWinslow
Copy link
Contributor

@dnlutz

I've made another pass at improving the Black font. I've uploaded two versions of the font:
TwoVersionsOfOpenMojiBlackFont.zip

This zip contains two files: called OpenMoji-Black.ttf and OpenMoji-Black_sansSkintoneAndFlags.ttf. The latter excludes two sets of glyphs:

  • skintone variants
  • country flags

Skintone Variants: In a monochrome font, skintone variants appear identical to the base glyph. In OpenMoji-Black.ttf, I implemented the skintone variants as a pointer to their base glyph, as defined in the skintone_base_hexcode of openmoji.csv. This reduces file size and ensures proper rendering, but may be the cause of the strange 'duplicates' you identified previously.
Screen Shot 2022-12-03 at 12 36 36 PM

Country Flags: The country flags, with few exceptions, are depicted as identical black rectangles in the Black version of OpenMoji. With the recent addition of regional indicator letters, a monochrome font might be more useable if the country flags are excluded. If this is done, then the flags will be rendered as pairs of regional indicator letters
Screen Shot 2022-12-03 at 12 37 38 PM

I've set up a build script for the font so neither of these exclusions are implemented, but can be toggled on by changing a pair of global variables near the beginning of the file.

@dnlutz
Copy link
Contributor

dnlutz commented Dec 6, 2022

Thank you @RobertWinslow !

The paths look pretty neat now! There are still some black fillings, but i'm pretty sure that it's not the fault of your algorithms but our source svgs ; )

221206 openmoji_font_test_01

The two versions have pretty much the same file size. I would go for the Google Noto way:
OpenMoji-Black_sansSkintoneAndFlags.ttf

– Regional indicators for the flags
– No skintone indication

What do you think?

And could you please include an empy space sign (U+0020)? … and a hyphen would be neat (U+002D ; )

JeppeKlitgaard pushed a commit to JeppeKlitgaard/openmoji that referenced this issue Dec 6, 2022
This is done via the container at https://gitlab.com/mavit/nanoemoji-container.

For me, the resulting COLR TTFs work in Firefox and in the Gnome desktop
on Fedora 32 (although they display rather small).

Caveats:
- It may be premature to replace `scfbuild` for SVG builds.  If we decide to go ahead without `scfbuild`, then we’ll want to remove the remaining files related to it.  If we decide to keep `scfbuild`, then we’ll want to revert those parts of this patch.  In either case we’ll want to update the readme to link to the new outputs.
- I’ve tested this with Podman, not Docker.

Relates to hfg-gmuend#93.
JeppeKlitgaard pushed a commit to JeppeKlitgaard/openmoji that referenced this issue Dec 6, 2022
This is done via the container at https://gitlab.com/mavit/nanoemoji-container.

For me, the resulting COLR TTFs work in Firefox and in the Gnome desktop
on Fedora 32 (although they display rather small).

Caveats:
- It may be premature to replace `scfbuild` for SVG builds.  If we decide to go ahead without `scfbuild`, then we’ll want to remove the remaining files related to it.  If we decide to keep `scfbuild`, then we’ll want to revert those parts of this patch.  In either case we’ll want to update the readme to link to the new outputs.
- I’ve tested this with Podman, not Docker.

Relates to hfg-gmuend#93.
@RobertWinslow
Copy link
Contributor

@dnlutz If a hyphen is added, which of the following styles would be preferred?
002D 002D (2)

Or would it be better to duplicate the heavy minus sign?
2796

@dnlutz
Copy link
Contributor

dnlutz commented Dec 21, 2022

thank you! for the sake of consistency i would vote for the duplicated heavy minus sign.

RobertWinslow added a commit to RobertWinslow/openmoji that referenced this issue Dec 24, 2022
JeppeKlitgaard pushed a commit to JeppeKlitgaard/openmoji that referenced this issue Jan 6, 2023
This is done via the container at https://gitlab.com/mavit/nanoemoji-container.

For me, the resulting COLR TTFs work in Firefox and in the Gnome desktop
on Fedora 32 (although they display rather small).

Caveats:
- It may be premature to replace `scfbuild` for SVG builds.  If we decide to go ahead without `scfbuild`, then we’ll want to remove the remaining files related to it.  If we decide to keep `scfbuild`, then we’ll want to revert those parts of this patch.  In either case we’ll want to update the readme to link to the new outputs.
- I’ve tested this with Podman, not Docker.

Relates to hfg-gmuend#93.
@b-g b-g closed this as completed in #422 Jan 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.