[BUG] Variation Selector not honored in button text
Make sure you're on the latest stable or beta build
- [x] I have tested this on the latest stable or beta release
Is this a bug in companion itself or a module?
- [x] I believe this to be a bug in companion and not a specific module
Is there an existing issue for this?
- [x] I have searched the existing issues
Describe the bug
(This one's a bit esoteric but, hey, the default rendering looks a bit garish to me! and it doesn't honor text and bg color)
The character known as U+1F500 Twisted Rightwards Arrows (🔀) is supposed to turn monochrome when U+FE0E Variation Selector-15 is appended: 🔀︎ (that's a three-byte character).
The latter shows correctly in the Admin WebUI's input field:
but not in the button
Same applies for 🔁 U+1F501
(I imagine this one is either "easy" or "impossible" to fix...)
Steps To Reproduce
You should be able to cut-and-paste the character from the description, above.
Expected Behavior
See description
Environment (please complete the following information)
- OS: Windows 10
- Browser: Chrome (not relevant)
- Companion Version: v4.2.0+8448
Additional context
No response
My first guesses on this is
- Perhaps the font we use doesnt include this?
- The unicode segmenter could be getting the splitting wrong?
- The canvas library could be doing something wrong
So no concrete ideas, just that it could be anything 😆
Yeah, I'm pretty sure it's the third one. I did a little testing after posting and
- (Missing in font) Possibly. You're using a "strange" emoji font, but even with the official Google Noto font I couldn't get differentiation (esp. in part 3, below)
- (Unicode segmenter) When I track it in the debugger, the character going into the
fillTextcall still looks correct and is a 3-byte character, as expected. - (Canvas library) I wrote stub test programs using (a) node-canvas (i.e., the one known as 'canvas'), (b) "@napi-rs" canvas, and (c) skia-canvas. The two that work with loaded fonts don't differentiate between w/ and w/o the variation selector. Node-canvas couldn't render loaded fonts and with its built-in font couldn't render the character with a variation-selector but at least it acknowledged that there was a difference.
In a more flexible environment than Companion one might be able specify the monochrome font (NotoEmoji-Regular), though the glyph there is different again than what the Variation-Selector gives (it's a filled square with the glyph cut out of it, i.e. transparent).
I'm willing to classify this as "impossible" for now. In the end I just made PNG files which, while 1,000x larger than the unicode, does the job...
(Deleted previous comment -- it's a bit less clear than I had hoped... will rethink and repost as appropriate)
OK, I've confirmed that option 1: the monochrome variation is not in the font. (Method: define classes in CSS with font-family set to a custom-loaded font and with fallback to Adobe "NotDef" font, which maps everything else to a crossed-out box).
However, it's a bit more complicated: On the good news side: Chrome (on Windows) can differentiate between the emoji-character with and without the variation-selector, and defaults to Microsoft's Segoe UI Symbol for the monochrome version (i.e. with selector).
Unfortunately option 3 (the canvas library doing something wrong) may also be true: if I add the Segoe UI Symbol font to the end of Companion's DEFAULT_FONTS, it is ignored, i.e., the color-emoji is shown regardless. (If the Segoe comes first, it's glyph is correctly shown, but since the font itself use the same glyph w/ and w/o selector, it's not a solution, see screenshot, below.) So while I can't say if it would work correctly if we found a font that has both color and monochrome glyphs in it, it does seem that the napi-rs/canvas (and skia-canvas) either ignore the selector or don't look for a fallback font in the case of variation selectors. FWIW, node-canvas, aka canvas, sort-of does it right: if "Segoe UI Symbol" is anywhere in the font list, node-canvas will draw the monochrome glyph when the variation-selector is used, and a different glyph without the variation-selector. Technically this behavior is incorrect when the Segoe font is first in the list, but at least it works.
Here's a screenshot for the font part, rendered in Chrome on Windows 10 (notice, also, the transparency in the "Noto Emoji" font; also, fill color was set to gray so you can see which ones respond to the fill color):