-
Notifications
You must be signed in to change notification settings - Fork 489
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
Support multi-character emoji #511
Comments
It seems like notoEmojiFont.substitution.getFeature("ccmp") // Array(3640) The feature tag is If |
Looking at #443 I thought this was worth a try: notoEmojiFont.substitution.add(
"ccmp",
notoEmojiFont.substitution.getFeature('ccmp')
); but got:
|
In addition to the |
Im also looking for a workaround for this. |
Here's my workaround. // Opentype.js doesn't actually support these substitutions, so we'll have to
// search them manually
const substitutions = font.substitution.getFeature("ccmp");
function emojiToGlyph (emojiString) {
const glyphs = font
.stringToGlyphs(emojiString)
// Discarding these makes the substitution search work for emoji sequences
// with variation selectors
// https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block)
.filter((glyph) => glyph.index <= 1850);
let glyph;
if (glyphs.length === 1) {
glyph = glyphs[0];
} else if (glyphs.length > 1) {
const indexes = glyphs.map((glyph) => glyph.index);
const sub = substitutions.find((substitution) => equals(substitution.sub, indexes));
if (sub) {
glyph = font.glyphs.get(sub.by);
}
}
if (glyph) {
return glyph;
} else {
throw new Error(`${emojiString} - couldn't find a glyph :(`);
}
}
emojiToGlyph("👨👩👧👦"); /** Custom equals function that can also check lists. */
function equals(a, b) {
if (a === b) {
return true;
} else if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i += 1) {
if (!equals(a[i], b[i])) {
return false;
}
}
return true;
} else {
return false;
}
} Caveats: This only works for one emoji. To replace the glyphs in an arbitrary string, we would also need tokenizer logic. Only tested with Noto Emoji. |
here's the different options: https://medium.com/making-faces-and-other-emoji/emoji-fonts-technically-40f3fdc0869e |
ccmp looks like an enforcement feature. It's not display in feature list, but always runs before decode a text. |
This issue with monochrome Noto Emoji is distinct from the color emoji issue (#193).
#338 added support for non-Basic-Multilingual-Plane (BMP) characters, but uses
Array.from
, which doesn't account for combined emoji.It seems that Opentype.js has the glyph information needed, but the initial text-to-glyph translation is the issue:
https://opentype.js.org/glyph-inspector.html
Expected Behavior
Calling
notoEmojiFont.draw(context, "👨👩👧👦")
should renderCurrent Behavior
Calling
notoEmojiFont.draw(context, "👨👩👧👦")
rendersPossible Solution
If "ccmp" is not supported yet and would cover this, this issue can be closed as a duplicate of Consider adding support to more GSUB tags? #443.
Intl.Segmenter is a native solution, but isn't supported by Firefox yet.
graphemer is a library-based solution. (It is a fairly big library.)
twemoji-parser is focused on parsing emoji sequences, so it's smaller than graphemer.
Steps to Reproduce (for bugs)
Live demo: https://gm69qn.csb.app
notoEmojiFont.stringToGlyphs("👨👩👧👦")
and get glyphs for "👨👩👧👦" interspersed with the combiner ("uni200D"
) instead of the one glyph for the combined family.Context
We're adding support for emoji to Cuttle CAD, which can render various fonts as vectors for laser cutting, etc.
Your Environment
The text was updated successfully, but these errors were encountered: