Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: How to render in color emojis?  (Read 287 times)

0 Members and 1 Guest are viewing this topic.

dreadward07

  • Newbie
  • *
  • Posts: 2
    • View Profile
How to render in color emojis?
« on: December 10, 2023, 05:09:19 am »
Hello! I am trying to render an emoji on screen using Google's Noto font. However, it always either renders blank squares, or nothing at all. Here's a link to the download:
https://fonts.google.com/noto/specimen/Noto+Color+Emoji

And here's the small amount of code I've written to try and display it.

#include <SFML/Graphics.hpp>

int main()
{

        sf::RenderWindow window(sf::VideoMode(640, 480), "Emoji", sf::Style::Close);
        sf::Event event;
        sf::Clock clock;
        while (window.isOpen())
        {
                while(window.pollEvent(event))
                {
                        switch (event.type)
                        {
                        case(sf::Event::Closed):
                        {
                                window.close();
                        }
                        }
                }

                window.clear();

                sf::Font font;
                font.loadFromFile("NotoColorEmoji-Regular.ttf");
               
                sf::Text text;
                text.setFont(font);
                text.setString("Test Text");

                window.draw(text);

                window.display();
        }

        return 0;
}

What am I doing wrong? I'm pretty sure this font doesn't contain any standard characters, which makes sense, but if that's the case, how do I render anything at all? Do I use Unicode? Glyphs? If it's either, then how do I use them?
I'm VERY new to the concept of fonts and character encoding as a whole, so I understand if I've missed something completely obvious.

Thank you for your help!
« Last Edit: December 12, 2023, 03:14:38 pm by eXpl0it3r »

fallahn

  • Sr. Member
  • ****
  • Posts: 492
  • Buns.
    • View Profile
    • Trederia
Re: How to render in color emojis?
« Reply #1 on: December 10, 2023, 01:11:44 pm »
Short story: You can't; SFML doesn't support coloured fonts. However there is a monochrome version of the noto emoji font which might work: https://fonts.google.com/noto/specimen/Noto+Emoji

Long story: I've been through this experience recently with my own engine, which uses SFML fonts/text/string as a basis for text renderering. Here's a brief summary of what I've found:

As you point out one font won't contain all the emojis and text characters. You need to use multiple fonts with multiple strings/text which can make it difficult to mix emojis with text in SFML. DearImGui takes an interesting approach which allows assigning multiple fonts to different ranges of unicode - you can read about it here.

I used this approach to modify what was essentially SFML's font class to allow loading multiple ttf files into a single Font, mapping them to different character ranges. This would be a nice feature, I think, to add to SFML.

SFML's fonts don't support colour - however they *could* if the way the underlying freetype library is used was changed slightly. Again, this would be a nice addition to SFML. *HOWEVER* that being said, while this will apparently work with Windows built in emoji font (C:/Windows/Fonts/seguiemj.ttf - license forbids redistribution) it still doesn't work with the colour format used by Google's Noto colour font  ::)

To print emojis with sf::String is relatively easy, though you will probably have to use codepoints directly, rather than string literals
Code: [Select]
sf::String str(u8"🌙");
This might work for single codepoint emojis, but for multi-point emojis you'll need to combine them yourself:
Code: [Select]
sf::String str(0x2600);
str += sf::String(0xFE0F);

Emojipedia is a good reference source - the technical tab will list any codepoints you need to combine.

HTH

dreadward07

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: How to render in color emojis?
« Reply #2 on: December 10, 2023, 04:46:24 pm »
I tried using sf::String and the seguiemj font, as Noto also shows blank boxes

sf::Font font;
font.loadFromFile("C:/Windows/Fonts/seguiemj.ttf");

sf::Text text;
text.setFont(font);

text.setString(u8"🌙");

window.draw(text);

However this displays the following:
https://ibb.co/Lrx0YwB
« Last Edit: December 10, 2023, 08:40:21 pm by dreadward07 »

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to render in color emojis?
« Reply #3 on: December 10, 2023, 08:51:02 pm »
It doesn't look like sf::String takes a UTF-8 string as a parameter. It seems to presume any chains of 8-bit characters (e.g. an std::string) is an "ANSI string". This is not Unicode so you cannot pass Unicode to sf::String with UTF-8 in its constructor.

Maybe try UTF-16 (using a wide string) or UTF-32 (string of sf::Uint32).

That said, you can create an sf::String with fromUtf8 and then assign it to your actual string. e.g.:
std::string uStr{ u8"🌙" };
sf::String str{ sf::String::fromUtf8(uStr.begin(), uStr.end()) };
I'd expect that to work but I haven't tested it :P I'm 100% on if it'll accept those iterators.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*