Automattic / node-canvas

Node canvas is a Cairo backed Canvas implementation for NodeJS.
10.19k stars 1.17k forks source link

Any emoji support? #760

Open kevzettler opened 8 years ago

kevzettler commented 8 years ago

The following code gives me the follwing image output:

    var Canvas = require('canvas');
    var Image = Canvas.Image;
    var canvas = new Canvas(1200, 600);
    var ctx = canvas.getContext('2d');

    ctx.font = '80px HelveticaNeue';
    ctx.fillText('Start Here emoji ๐Ÿ”', 50, 100);

    res.setHeader('Content-Type', 'image/png');
    canvas.pngStream().pipe(res);

Not rendering the emoji. Is this possible?

tiltimage

mmiguerodriguez commented 3 years ago

Having the same issues, I attempted using 'node-canvas-with-twemoji-and-discord-emoji' package to fix this, and seemed to work. image image

I still have problems with unicode characters, when I render them on my local workstation they render correctly: image but on server side it looks like this image

Brooooooklyn commented 3 years ago

skr-canvas has supported emoji fonts: https://github.com/Brooooooklyn/canvas/pull/327

Produced in node:lts-apline docker container, 0 system dependencies and 0 postinstall scripts:

draw-emoji

motyar commented 3 years ago

skr-canvas has supported emoji fonts: Brooooooklyn/canvas#327

Produced in node:lts-apline docker container, 0 system dependencies and 0 postinstall scripts:

draw-emoji

How can we use it with fabricjs? Please provide example code.

alex-uspenskyi commented 3 years ago

Hey guys, any updates here?

fuchunhui commented 2 years ago

we need emojiโ˜๏ธ

avanavana commented 2 years ago

This has been driving me absolutely nuts, thought it was my code. I can't believe it's been years with regular browser canvas allowing emoji in text and we still can't do it in node-canvas :(

ArmorDarks commented 2 years ago

Cairo patch https://gitlab.freedesktop.org/cairo/cairo/-/issues/54 has been merged. I guess colored bitmap emoji should work now if we update Cairo?

tdurieux commented 2 years ago

I compiled the latest version of cairo but it does not seem to work at least on Linux. They have specific font management for mac and windows

rklf commented 2 years ago

Any news on it ?

mrsegev commented 1 year ago

Any news or a solid solution to this?

Elitex07 commented 1 year ago

@mrsegev You have to download the Segoe Emoji ttf from the Internet. Importing the downloaded file will make Windows emojis come on the canvas. Image below has the crown (๐Ÿ‘‘) emoji

image

mrsegev commented 1 year ago

Thanks @Elitex07 , What do you mean by importing the file?

Elitex07 commented 1 year ago

@mrsegev Use registerfont() function to import custom fonts.

registerFont('src/assets/fonts/Segoe/seguiemj.ttf', {family: 'Segoe'})
fabriziospadaro commented 1 year ago

My "dirty" solution was to use twemoji-parser to get the url of the correponding emoji svg and than draw it as a regular image inside the canvas.

neodesys commented 1 year ago

To render emojis with colors on Linux, you need to take into account different aspects:

  1. you should use the "glyph" drawing mode for text: ctx.textDrawingMode = "glyph";. In the default path mode only the outline of the glyph is drawn, so it will always be using one unique color. In glyph mode, the rendering of the glyph is delegated to Pango/Cairo (and Freetype) that know about the glyph colors and can draw it correctly.
  2. you should configure correctly fontconfig. Even if node-canvas provides recent binaries for Pango, Cairo, Freetype and FontConfig, the latter will still read your configuration files from /etc/fonts/conf.d/. In particular, on recent Linux distributions, emojis fonts configurations are grouped into 45-generic.conf and 60-generic.conf files (see below).
  3. all emojis fonts cannot be rendered with colors under Linux. In particular the ones with OpenType-SVG format (like https://github.com/13rac1/twemoji-color-font). The SVG support in Freetype is very recent (version 2.12.0 https://freetype.org/) and has not been implemented in Pango/Cairo yet. You should use CBDT fonts to have colored emojis under Linux.

As far as fontconfig emojis configuration is concerned here are the details you need to enable colored emojis (from: 45-generic.conf and 60-generic.conf files):

        <!-- System emoji -->
        <alias binding="same">
                <family>Noto Color Emoji</family> <!-- Google -->
                <default><family>emoji</family></default>
        </alias>
        <alias binding="same">
                <family>Apple Color Emoji</family> <!-- Apple -->
                <default><family>emoji</family></default>
        </alias>
        <alias binding="same">
                <family>Segoe UI Emoji</family> <!-- Microsoft -->
                <default><family>emoji</family></default>
        </alias>
        <alias binding="same">
                <family>Twitter Color Emoji</family> <!-- Twitter -->
                <default><family>emoji</family></default>
        </alias>
        <alias binding="same">
                <family>EmojiOne Mozilla</family> <!-- Mozilla -->
                <default><family>emoji</family></default>
        </alias>
        <!-- Third-party emoji -->
        <alias binding="same">
                <family>Emoji Two</family>
                <default><family>emoji</family></default>
        </alias>
        <alias binding="same">
                <family>Emoji One</family>
                <default><family>emoji</family></default>
        </alias>
        <!-- B&W -->
        <alias binding="same">
                <family>Noto Emoji</family> <!-- Google -->
                <default><family>emoji</family></default>
        </alias>
        <alias binding="same">
                <family>Android Emoji</family> <!-- Google -->
                <default><family>emoji</family></default>
        </alias>

        <!-- Add language for emoji, to match other emoji fonts. -->
        <match>
                <test name="family">
                        <string>emoji</string>
                </test>
                <edit name="lang" mode="prepend">
                        <string>und-zsye</string>
                </edit>
        </match>

        <match>
                <test name="lang">
                        <string>und-zsye</string>
                </test>
                <test qual="all" name="family" compare="not_eq">
                        <string>emoji</string>
                </test>

                <!-- Add generic family. -->
                <edit name="family" mode="append" binding="strong">
                        <string>emoji</string>
                </edit>
        </match>

and

<!-- Emoji -->

        <!-- Prefer to match color emoji font. -->
        <match>
                <test name="lang">
                        <string>und-zsye</string>
                </test>
                <test qual="all" name="color" compare="not_eq">
                        <bool>true</bool>
                </test>
                <test qual="all" name="color" compare="not_eq">
                        <bool>false</bool>
                </test>
                <edit name="color" mode="append">
                        <bool>true</bool>
                </edit>
        </match>

        <!-- TODO
         ! Match on "color" and alias B&W ones first if no color is requested.
         ! That's "hard" because <alias> doesn't work in match and needs to be
         ! expanded to its non-sugar form.
         !-->
        <alias binding="same">
                <family>emoji</family>
                <prefer>
                        <!-- System fonts -->
                        <family>Noto Color Emoji</family> <!-- Google -->
                        <family>Apple Color Emoji</family> <!-- Apple -->
                        <family>Segoe UI Emoji</family> <!-- Microsoft -->
                        <family>Twitter Color Emoji</family> <!-- Twitter -->
                        <family>EmojiOne Mozilla</family> <!-- Mozilla -->
                        <!-- Third-Party fonts -->
                        <family>Emoji Two</family>
                        <family>Emoji One</family>
                        <!-- Non-color -->
                        <family>Noto Emoji</family> <!-- Google -->
                        <family>Android Emoji</family> <!-- Google -->
                </prefer>
        </alias>

In particular, the list provided after <!-- System fonts --> comment is very important to determine the preferred emojis font when you have more than one installed on your system. If you want to select a particular emojis font, you should change this list order, or install/load only one emoji font. To be more concrete, if Noto Color Emoji font is installed on your system, loading Apple Color Emoji using registerFont() in node-canvas will do nothing as in fontconfig configuration Noto Color Emoji will take precedence over Apple Color Emoji.

00Prime commented 1 year ago

@mrsegev Use registerfont() function to import custom fonts.

Not sure if I am using it correctly but it still does not show correct emoji?

registerFont('src/assets/fonts/Segoe/seguiemj.ttf', {family: 'Segoe'})
import { createCanvas, registerFont } from "canvas";

registerFont("../seguiemj.ttf", { family: "Segoe" });
const canvas = createCanvas(100, 100);
const ctx = canvas.getContext("2d");
ctx.font = "20px sans-serif";

const emojis = ["๐Ÿ˜€"];

emojis.forEach((emoji, i) => {
  ctx.fillText(emoji, 8 * (i + 1), 8);
});

console.log(canvas.toDataURL());
starrin commented 1 year ago

@00Prime You need to set the font family correctly.

import { createCanvas, registerFont } from "canvas";

registerFont("../seguiemj.ttf", { family: "Segoe UI Emoji" });
const canvas = createCanvas(100, 100);
const ctx = canvas.getContext("2d");
ctx.textDrawingMode = "glyph"
ctx.font = "20px 'Segoe UI Emoji'";

const emojis = ["๐Ÿ˜€"];

emojis.forEach((emoji, i) => {
  ctx.fillText(emoji, 8 * (i + 1), 50);
});

console.log(canvas.toDataURL());

Works for me.

weirui88888 commented 11 months ago

I donโ€™t know if emoji is already supported๐Ÿ˜ญ

mrskiro commented 11 months ago

How do I display in native color? For example, for apple color emoji.

Depending on the fillStyle, the color of the emoji will change along with the text ๐Ÿ˜”.

EduVencovsky commented 10 months ago

After a crazy amount of time trying to render emojis with node-canvas, I figured a very unconventional way to render it.

I'm using fontkit to convert the emoji into an image and then render that image with node-canvas.

ggolda commented 10 months ago

any update for this?

orenlwsc commented 6 months ago

Anyone stumbling upon this issue, and need fabric js to support apple emoji - follow my setup on the dockerfile as described in this issue.

Make sure the text data doesn't include objectCaching: true.

Made by node-canvas + fabric js:

image
FPG-Alan commented 5 months ago

I'm not certain if this will be beneficial for others, but I wanted to share my experience working with fabric.js. After spending an entire day experimenting with different approaches, I discovered that simply changing the textDrawingMode to glyph resolved the issues I was experiencing:

this.canvas = new fabric.StaticCanvas(null, {
      width,
      height,
      backgroundColor: "#000",
});
this.canvas.getContext().textDrawingMode = "glyph";

image

Before making this alteration, I ensured that the noto-color-emoji font was properly installed.

Borodin commented 3 months ago

Currently, using color Emoji in canvas is quite straightforward.

  1. You need to have a font that supports color Emoji, such as AppleColorEmoji.ttf. Here is how you can download it on Ubuntu:

    wget -O /usr/share/fonts/AppleColorEmoji.ttf https://github.com/samuelngs/apple-emoji-linux/releases/latest/download/AppleColorEmoji.ttf
  2. Set the textDrawingMode to "glyph" to ensure the emojis are rendered in color:

    ctx.textDrawingMode = "glyph";

This approach should allow you to display colored emojis within the canvas.

Fripine commented 2 months ago

Any news or solution today? I drew two emojis("๐Ÿฎโ˜ž") using the function fillText() , one is correctly drawn and the other is presented by its unicode hex value directly. I am certain that the font I registered in node-canvas supports these two emojis. 5f65569845b8128780e6b549de630c0e