NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.29k stars 14.27k forks source link

`google-fonts` breaks Noto Color Emoji in Kitty #327846

Open Dioprz opened 4 months ago

Dioprz commented 4 months ago

Describe the bug

The installation of the package google-fonts breaks emoji usage via the Noto Color Emoji font in Kitty.

Steps To Reproduce

Steps to reproduce the behavior using home-manager:

  1. In home.nix

      fonts = {
        fontconfig = {
          enable = true;
          defaultFonts.emoji = [
            "Noto Color Emoji"
          ];
          defaultFonts.monospace = [ "Noto Sans Mono" ];
          defaultFonts.sansSerif = [ "Noto Sans" ];
          defaultFonts.serif = [ "Noto Serif" ];
        };
      };

    and add google-fonts in your installed packages.

  2. After make a home switch, launch kitty --debug-font-fallback and copy paste any emoji from the web. You will get an ending message like this one:

    [17,334] U+1f603 emoji_presentation Face(family=Noto Color Emoji, style=Regular, ps_name=NotoColorEmoji,
    path=/nix/store/i2pl6gqpiflr96xdpmjp6d9nfiwnfxqh-home-manager-path/share/fonts/truetype/NotoColorEmoji-Regular.ttf, 
    ttc_index=0, variation_index=0x0 is_scalable=True, has_color=True, ascender=950, descender=-250, height=1200, 
    underline_position=-102, underline_thickness=51, strikethrough_position=307, strikethrough_thickness=51)
    fast_data_types.FreeTypeError: Failed to load glyph_index=2273 load_type=1048580, with error: bad argument

    And your pasted emoji will look like this image (Yes, you can't see it.)

  3. Now, remove google-fonts from your packages, and install noto-fonts-color-emoji and noto-fonts. Make the home switch, and launch again kitty --debug-font-fallback. Copy-paste the emoji, and now the emoji is visible and works as expected. What is more, you can see in the ending logs something like this:

    [16,337] U+1f603 emoji_presentation Face(family=Noto Color Emoji, style=Regular, ps_name=NotoColorEmoji,
    path=/nix/store/66csfydaq6jq4izmb66whh0lmz39ljs4-home-manager-path/share/fonts/noto/NotoColorEmoji.ttf,
     ttc_index=0, variation_index=0x0 is_scalable=False, has_color=True, ascender=0, descender=0, height=0,
     underline_position=0, underline_thickness=0, strikethrough_position=530, strikethrough_thickness=102)

Please notice the differences between the font used (NotoColorEmoji vs NotoColorEmoji-Regular), as well as the parameters used on each one.

Expected behavior

Install google-fonts shouldn't break emoji usage.

Additional context

Workarounds:

  1. If you don't need the google-fonts package, just use the configuration on the step 3.
  2. If you need the google-fonts package, then add
      # in the fonts atrset
      defaultFonts.emoji = [
        "JoyPixels"
        "Noto Color Emoji"
      ];
      # in your home.nix
      nixpkgs.config.allowUnfreePredicate =
        pkg:
        builtins.elem (lib.getName pkg) [
          "joypixels"
        ];
      nixpkgs.config.joypixels.acceptLicense = true;

Warning: In some cases (I'm not sure when/why), even having the correct configuration (step 3), you can end with emojis looking like this:

image.

Try using the command fc-cache -f and check everything is working again with kitty --debug-font-fallback.

Possibly related:

https://github.com/NixOS/nixpkgs/issues/225541 and https://github.com/NixOS/nixpkgs/issues/230895

Notify maintainers

@manveru

Metadata

Please run nix-shell -p nix-info --run "nix-info -m" and paste the result.

[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.6.33, NixOS, 24.11 (Vicuna), 24.11.20240613.e9ee548`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.18.2`
 - nixpkgs: `/nix/store/qqwr649pc0qprc9lw2fmdsi1km6p7q2h-source`

Add a :+1: reaction to issues you find important.

kovidgoyal commented 4 months ago

It will be because google-fonts is installing the COLRv1 version of the NotoEmoji. As far as I can tell this doesnt render in FreeType, at all. Attached is a simple C program to demonstrate.


#define FONT_PATH  "/t/Noto-COLRv1.ttf"
#define CHARACTER 0x1f600

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BITMAP_H

int main() {
    FT_Library ft;
    if (FT_Init_FreeType(&ft)) {
        fprintf(stderr, "Could not init freetype library\n");
        return 1;
    }
    FT_Face face;
    if (FT_New_Face(ft, FONT_PATH, 0, &face)) {
        fprintf(stderr, "Could not open font\n");
        FT_Done_FreeType(ft);
        return 1;
    }
    FT_Set_Char_Size(face, 0, 48 * 64, 300, 300);
    FT_UInt glyph_index = FT_Get_Char_Index(face, CHARACTER);
    FT_Bitmap* bitmap = &face->glyph->bitmap;
    FT_Color*         palette;
    FT_LayerIterator  iterator = {0};

    FT_Bool  have_layers;
    FT_UInt  layer_glyph_index = 0;
    FT_UInt  layer_color_index = 0;
    FT_Error error = FT_Palette_Select( face, 0, &palette );
    if ( error ) { return 1; }
    have_layers = FT_Get_Color_Glyph_Layer(face, glyph_index, &layer_glyph_index, &layer_color_index, &iterator);
    printf("COLR information: have_layers: %d num_layers: %d\n", have_layers, iterator.num_layers);

    return 0;

}

Change the FONT_PATH at the top to the path to the NOTO ttf. Run with:

gcc -I/usr/include/freetype2 ft.c -o ft -lfreetype && ./ft

See output:

COLR information: have_layers: 0 num_layers: 0

FreeType thinks the glyph has no color layers when using the COLRv1 font and thus renders it blank.

kovidgoyal commented 4 months ago

And for reference: https://github.com/kovidgoyal/kitty/issues/7140

nixos-discourse commented 2 months ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/emojis-not-showing-in-kitty/51294/4