Also known as colored emoji, which freetype supports using google's
approach (CBDT/CBLC opentype tables)

This means:

- Getting the FC_COLOR value from fontconfig
- Enabling the FT_LOAD_COLOR load flag
- Stopping it from setting FT_LOAD_NO_BITMAP
- Setting ARGB32 picture format in XRender
- Supporting FT_PIXEL_MODE_BGRA in the XRender bitmap functions

There's some overlap between this and antialias, which also uses ARGB32
pixel modes, which meant that most code was already written, it just
needed to stop treating all bitmap fonts as mono ("not antialiased")

Despite the name, the FT_PIXEL_MODE_BGRA implementation in
_fill_xrender_bitmap() didn't seem to need any byteswapping, so a
direct memcpy worked. Not sure if that's supposed to be a platform
specific detail.

This was tested with:

- The suckless "st" terminal (the only software I know that uses xft and
  handles fontconfig fallbacks decently)
- A variant of the "Noto Color Emoji" font modified to have 12x12
  glyphs[1][2], since the original font has 128x128 embedded PNGs.
  Freetype doesn't scale bitmaps, and neither does this patch, yet.

A later patch should address the scaling issue. I'm not sure yet what's
the best way to do this, since it seems XRender scaling operations can't
be used on glyphs before they are created.

[1] https://github.com/dequis/noto-emoji
[2] http://dequis.org/NotoColorEmoji-12x12.ttf

Signed-off-by: dequis <[email protected]>
---
 src/xftfreetype.c | 20 ++++++++++++++++++--
 src/xftglyphs.c   | 15 ++++++++++++---
 src/xftint.h      |  1 +
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/src/xftfreetype.c b/src/xftfreetype.c
index a3b8332..6e5d128 100644
--- a/src/xftfreetype.c
+++ b/src/xftfreetype.c
@@ -512,6 +512,19 @@ XftFontInfoFill (Display *dpy, _Xconst FcPattern *pattern, 
XftFontInfo *fi)
        fi->render = FcFalse;
 
     /*
+     * Get color value
+     */
+    switch (FcPatternGetBool (pattern, FC_COLOR, 0, &fi->color)) {
+    case FcResultNoMatch:
+       fi->color = FcFalse;
+       break;
+    case FcResultMatch:
+       break;
+    default:
+       goto bail1;
+    }
+
+    /*
      * Compute glyph load flags
      */
     fi->load_flags = FT_LOAD_DEFAULT;
@@ -530,8 +543,11 @@ XftFontInfoFill (Display *dpy, _Xconst FcPattern *pattern, 
XftFontInfo *fi)
        goto bail1;
     }
 
+    if (fi->color)
+       fi->load_flags |= FT_LOAD_COLOR;
+
     /* disable bitmaps when anti-aliasing or transforming glyphs */
-    if ((!bitmap && fi->antialias) || fi->transform)
+    else if ((!bitmap && fi->antialias) || fi->transform)
        fi->load_flags |= FT_LOAD_NO_BITMAP;
 
     /* disable hinting if requested */
@@ -827,7 +843,7 @@ XftFontOpenInfo (Display    *dpy,
      */
     if (fi->render)
     {
-       if (antialias)
+       if (antialias || fi->color)
        {
            switch (fi->rgba) {
            case FC_RGBA_RGB:
diff --git a/src/xftglyphs.c b/src/xftglyphs.c
index 4b5fb82..e4df855 100644
--- a/src/xftglyphs.c
+++ b/src/xftglyphs.c
@@ -130,6 +130,10 @@ _compute_xrender_bitmap_size( FT_Bitmap*   target,
        pitch = width*4;
        break;
 
+    case FT_PIXEL_MODE_BGRA:
+       pitch = width*4;
+       break;
+
     default:  /* unsupported source format */
        return -1;
     }
@@ -291,7 +295,7 @@ _fill_xrender_bitmap( FT_Bitmap*    target,
            }
            break;
 
-       default:  /* FT_PIXEL_MODE_LCD_V */
+       case FT_PIXEL_MODE_LCD_V:
            /* convert vertical RGB into ARGB32 */
            if ( !bgr )
            {
@@ -335,6 +339,11 @@ _fill_xrender_bitmap( FT_Bitmap*   target,
                    }
                }
            }
+           break;
+
+       case FT_PIXEL_MODE_BGRA:
+           memcpy( dstLine, srcLine, height * pitch );
+           break;
        }
     }
 }
@@ -374,7 +383,7 @@ XftFontLoadGlyphs (Display      *dpy,
     if (!face)
        return;
 
-    if (font->info.antialias)
+    if (font->info.antialias || font->info.color)
     {
        switch (font->info.rgba) {
        case FC_RGBA_RGB:
@@ -593,7 +602,7 @@ XftFontLoadGlyphs (Display      *dpy,
 
                for (y = 0; y < height; y++)
                {
-                   if (font->info.antialias)
+                   if (mode != FT_RENDER_MODE_MONO)
                    {
                        static const char    den[] = { " .:;=+*#" };
                        for (x = 0; x < width; x++)
diff --git a/src/xftint.h b/src/xftint.h
index c06ac3c..5908334 100644
--- a/src/xftint.h
+++ b/src/xftint.h
@@ -133,6 +133,7 @@ struct _XftFontInfo {
      */
     FT_F26Dot6         xsize, ysize;   /* pixel size */
     FcBool             antialias;      /* doing antialiasing */
+    FcBool             color;          /* colored glyph */
     FcBool             embolden;       /* force emboldening */
     int                        rgba;           /* subpixel order */
     int                        lcd_filter;     /* lcd filter */
-- 
2.0.0+fc2

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to