[PATCH libxft] Add initial support for freetype 2.5 colored glyphs

dequis dx at dxzone.com.ar
Mon Aug 17 17:30:05 PDT 2015


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 <dx at dxzone.com.ar>
---
 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



More information about the xorg-devel mailing list