Github messages for voidlinux
 help / color / mirror / Atom feed
* [PR PATCH] libXft: update and include big fixes
@ 2021-08-12 12:24 vigoux
  2021-08-12 12:26 ` ericonr
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: vigoux @ 2021-08-12 12:24 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1810 bytes --]

There is a new pull request by vigoux against master on the void-packages repository

https://github.com/vigoux/void-packages libxft-fix
https://github.com/void-linux/void-packages/pull/32469

libXft: update and include big fixes
<!-- Mark items with [x] where applicable -->
#### General
- [ ] This is a new package and it conforms to the [quality requirements](https://github.com/void-linux/void-packages/blob/master/Manual.md#quality-requirements)

#### Have the results of the proposed changes been tested?
- [x] I use the packages affected by the proposed changes on a regular basis and confirm this PR works for me
- [ ] I generally don't use the affected packages but briefly tested this PR

<!--
If GitHub CI cannot be used to validate the build result (for example, if the
build is likely to take several hours), make sure to
[skip CI](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#continuous-integration).
When skipping CI, uncomment and fill out the following section.
Note: for builds that are likely to complete in less than 2 hours, it is not
acceptable to skip CI.
-->
#### Does it build and run successfully? 
(Please choose at least one native build and, if supported, at least one cross build. More are better.)
- [x] I built this PR locally for my native architecture, (x86_64-gnu)
- [ ] I built this PR locally for these architectures (if supported. mark crossbuilds):
  - [ ] aarch64-musl
  - [ ] armv7l
  - [ ] armv6l-musl

#### Other

This PR includes patches that are waiting to be merged upstream, and
fix a bug. Including these patched solved numerous issues with `st`,
where colored emojis caused a hard crash of the terminal emulator.


A patch file from https://github.com/void-linux/void-packages/pull/32469.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-libxft-fix-32469.patch --]
[-- Type: text/x-diff, Size: 29002 bytes --]

From b286302019c57dcf4ccabb05886ad5c02f2f4171 Mon Sep 17 00:00:00 2001
From: Thomas Vigouroux <tomvig38@gmail.com>
Date: Thu, 12 Aug 2021 14:17:53 +0200
Subject: [PATCH 1/2] libXft: update to 2.3.4

---
 srcpkgs/libXft/template | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/srcpkgs/libXft/template b/srcpkgs/libXft/template
index dd6263d3a420..1e86cd68fdc3 100644
--- a/srcpkgs/libXft/template
+++ b/srcpkgs/libXft/template
@@ -1,6 +1,6 @@
 # Template file for 'libXft'
 pkgname=libXft
-version=2.3.3
+version=2.3.4
 revision=1
 build_style=gnu-configure
 hostmakedepends="pkg-config"
@@ -10,7 +10,7 @@ maintainer="Orphaned <orphan@voidlinux.org>"
 license="MIT"
 homepage="$XORG_SITE"
 distfiles="${XORG_SITE}/lib/${pkgname}-${version}.tar.bz2"
-checksum=225c68e616dd29dbb27809e45e9eadf18e4d74c50be43020ef20015274529216
+checksum=57dedaab20914002146bdae0cb0c769ba3f75214c4c91bd2613d6ef79fc9abdd
 
 post_install() {
 	vlicense COPYING

From 9eddae8e7f5c7029b11ef2ebc4d8f2d785cb0fd1 Mon Sep 17 00:00:00 2001
From: Thomas Vigouroux <tomvig38@gmail.com>
Date: Thu, 12 Aug 2021 14:18:15 +0200
Subject: [PATCH 2/2] libXft: fix colored emoji bug

Include the patches from https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1
---
 ...-_XftCompositeString-helper-function.patch |  94 +++
 ...-a-_XftCompositeText-helper-function.patch | 123 ++++
 ...-for-BGRA-glyphs-display-and-scaling.patch | 642 ++++++++++++++++++
 3 files changed, 859 insertions(+)
 create mode 100644 srcpkgs/libXft/patches/0001-Introduce-a-_XftCompositeString-helper-function.patch
 create mode 100644 srcpkgs/libXft/patches/0002-Introduce-a-_XftCompositeText-helper-function.patch
 create mode 100644 srcpkgs/libXft/patches/0003-Add-support-for-BGRA-glyphs-display-and-scaling.patch

diff --git a/srcpkgs/libXft/patches/0001-Introduce-a-_XftCompositeString-helper-function.patch b/srcpkgs/libXft/patches/0001-Introduce-a-_XftCompositeString-helper-function.patch
new file mode 100644
index 000000000000..3ba3d72590b0
--- /dev/null
+++ b/srcpkgs/libXft/patches/0001-Introduce-a-_XftCompositeString-helper-function.patch
@@ -0,0 +1,94 @@
+From 723092ece088559f1af299236305911f4ee4d450 Mon Sep 17 00:00:00 2001
+From: Maxime Coste <mawww@kakoune.org>
+Date: Thu, 28 Jan 2021 19:59:10 +1100
+Subject: [PATCH 1/3] Introduce a _XftCompositeString helper function
+
+Dispatch to XRenderCompositeString{8,16,32} based off the given width.
+
+Signed-off-by: Maxime Coste <mawww@kakoune.org>
+---
+ src/xftrender.c | 61 ++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 43 insertions(+), 18 deletions(-)
+
+diff --git a/src/xftrender.c b/src/xftrender.c
+index a352737..181c27a 100644
+--- a/src/xftrender.c
++++ b/src/xftrender.c
+@@ -25,6 +25,47 @@
+ #define NUM_LOCAL	1024
+ #define NUM_ELT_LOCAL	128
+ 
++/*
++ * Dispatch glyph drawing to the correct XRenderCompositeString function
++ */
++static void
++_XftCompositeString (Display           *dpy,
++                     int               op,
++                     Picture           src,
++                     Picture           dst,
++                     XRenderPictFormat *format,
++                     GlyphSet          glyphset,
++                     int               srcx,
++                     int               srcy,
++                     int               dstx,
++                     int               dsty,
++                     int               charwidth,
++                     unsigned int      *chars,
++                     int               nchars)
++{
++    if (nchars == 0)
++        return;
++
++    switch (charwidth) {
++    case 1:
++    default:
++	XRenderCompositeString8 (dpy, op,
++				 src, dst, format, glyphset,
++				 srcx, srcy, dstx, dsty, (char*)chars, nchars);
++	break;
++    case 2:
++	XRenderCompositeString16(dpy, op,
++				 src, dst, format, glyphset,
++				 srcx, srcy, dstx, dsty, (unsigned short*)chars, nchars);
++	break;
++    case 4:
++	XRenderCompositeString32(dpy, op,
++				 src, dst, format, glyphset,
++				 srcx, srcy, dstx, dsty, (unsigned int*)chars, nchars);
++	break;
++    }
++}
++
+ /*
+  * Use the Render extension to draw the glyphs
+  */
+@@ -114,24 +155,8 @@ XftGlyphRender (Display		*dpy,
+ 	case 4: char32[i] = (unsigned int) wire; break;
+ 	}
+     }
+-    switch (width) {
+-    case 1:
+-    default:
+-	XRenderCompositeString8 (dpy, op,
+-				 src, dst, font->format, font->glyphset,
+-				 srcx, srcy, x, y, char8, nglyphs);
+-	break;
+-    case 2:
+-	XRenderCompositeString16(dpy, op,
+-				 src, dst, font->format, font->glyphset,
+-				 srcx, srcy, x, y, char16, nglyphs);
+-	break;
+-    case 4:
+-	XRenderCompositeString32(dpy, op,
+-				 src, dst, font->format, font->glyphset,
+-				 srcx, srcy, x, y, char32, nglyphs);
+-	break;
+-    }
++    _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset,
++                        srcx, srcy, x, y, width, chars, nglyphs);
+     if (chars != char_local)
+ 	free (chars);
+ bail1:
+-- 
+2.32.0
+
diff --git a/srcpkgs/libXft/patches/0002-Introduce-a-_XftCompositeText-helper-function.patch b/srcpkgs/libXft/patches/0002-Introduce-a-_XftCompositeText-helper-function.patch
new file mode 100644
index 000000000000..2112c39e4d8a
--- /dev/null
+++ b/srcpkgs/libXft/patches/0002-Introduce-a-_XftCompositeText-helper-function.patch
@@ -0,0 +1,123 @@
+From e0fc4ce7e87ab9c4b47e5c8e693f070dfd0d2f7b Mon Sep 17 00:00:00 2001
+From: Maxime Coste <mawww@kakoune.org>
+Date: Thu, 28 Jan 2021 20:05:13 +1100
+Subject: [PATCH 2/3] Introduce a _XftCompositeText helper function
+
+Dispatch to XRenderCompositeText{8,16,32} based off the given width.
+
+Signed-off-by: Maxime Coste <mawww@kakoune.org>
+---
+ src/xftrender.c | 83 +++++++++++++++++++++++++++++--------------------
+ 1 file changed, 49 insertions(+), 34 deletions(-)
+
+diff --git a/src/xftrender.c b/src/xftrender.c
+index 181c27a..5852b2e 100644
+--- a/src/xftrender.c
++++ b/src/xftrender.c
+@@ -164,6 +164,49 @@ bail1:
+ 	_XftFontManageMemory (dpy, pub);
+ }
+ 
++/*
++ * Dispatch glyph drawing to the correct XRenderCompositeText function
++ */
++static void
++_XftCompositeText (Display           *dpy,
++                   int               op,
++                   Picture           src,
++                   Picture           dst,
++                   XRenderPictFormat *format,
++                   int               srcx,
++                   int               srcy,
++                   int               dstx,
++                   int               dsty,
++                   int               eltwidth,
++                   XGlyphElt8        *elts,
++                   int               nelt)
++{
++    if (nelt == 0)
++        return;
++
++    switch (eltwidth) {
++    case 1:
++    default:
++	XRenderCompositeText8 (dpy, op,
++			       src, dst, format,
++			       srcx, srcy, dstx, dsty,
++	                       (XGlyphElt8*)elts, nelt);
++	break;
++    case 2:
++	XRenderCompositeText16(dpy, op,
++			       src, dst, format,
++			       srcx, srcy, dstx, dsty,
++	                       (XGlyphElt16*)elts, nelt);
++	break;
++    case 4:
++	XRenderCompositeText32(dpy, op,
++			       src, dst, format,
++			       srcx, srcy, dstx, dsty,
++	                       (XGlyphElt32*)elts, nelt);
++	break;
++    }
++}
++
+ _X_EXPORT void
+ XftGlyphSpecRender (Display		    *dpy,
+ 		    int			    op,
+@@ -345,23 +388,9 @@ XftGlyphSpecRender (Display		    *dpy,
+ 	elts[nelt].nchars = n;
+ 	nelt++;
+     }
+-    switch (width) {
+-    case 1:
+-	XRenderCompositeText8 (dpy, op, src, dst, font->format,
+-			       srcx, srcy, glyphs[0].x, glyphs[0].y,
+-			       elts, nelt);
+-	break;
+-    case 2:
+-	XRenderCompositeText16 (dpy, op, src, dst, font->format,
+-				srcx, srcy, glyphs[0].x, glyphs[0].y,
+-				(XGlyphElt16 *) elts, nelt);
+-	break;
+-    case 4:
+-	XRenderCompositeText32 (dpy, op, src, dst, font->format,
+-				srcx, srcy, glyphs[0].x, glyphs[0].y,
+-				(XGlyphElt32 *) elts, nelt);
+-	break;
+-    }
++    _XftCompositeText(dpy, op, src, dst, font->format,
++		      srcx, srcy, glyphs[0].x, glyphs[0].y,
++		      width, elts, nelt);
+ 
+     if (elts != elts_local)
+ 	free (elts);
+@@ -635,23 +664,9 @@ XftGlyphFontSpecRender (Display			    *dpy,
+ 	elts[nelt].nchars = n;
+ 	nelt++;
+     }
+-    switch (width) {
+-    case 1:
+-	XRenderCompositeText8 (dpy, op, src, dst, format,
+-			       srcx, srcy, glyphs[0].x, glyphs[0].y,
+-			       elts, nelt);
+-	break;
+-    case 2:
+-	XRenderCompositeText16 (dpy, op, src, dst, format,
+-				srcx, srcy, glyphs[0].x, glyphs[0].y,
+-				(XGlyphElt16 *) elts, nelt);
+-	break;
+-    case 4:
+-	XRenderCompositeText32 (dpy, op, src, dst, format,
+-				srcx, srcy, glyphs[0].x, glyphs[0].y,
+-				(XGlyphElt32 *) elts, nelt);
+-	break;
+-    }
++    _XftCompositeText(dpy, op, src, dst, format,
++		      srcx, srcy, glyphs[0].x, glyphs[0].y,
++		      width, elts, nelt);
+ 
+     if (elts != elts_local)
+ 	free (elts);
+-- 
+2.32.0
+
diff --git a/srcpkgs/libXft/patches/0003-Add-support-for-BGRA-glyphs-display-and-scaling.patch b/srcpkgs/libXft/patches/0003-Add-support-for-BGRA-glyphs-display-and-scaling.patch
new file mode 100644
index 000000000000..73a7842b6348
--- /dev/null
+++ b/srcpkgs/libXft/patches/0003-Add-support-for-BGRA-glyphs-display-and-scaling.patch
@@ -0,0 +1,642 @@
+From d385aa3e5320d18918413df0e8aef3a713a47e0b Mon Sep 17 00:00:00 2001
+From: Maxime Coste <mawww@kakoune.org>
+Date: Tue, 22 Oct 2019 22:46:49 +1100
+Subject: [PATCH 3/3] Add support for BGRA glyphs display and scaling
+
+Display is done using an XRender Picture, as XRender
+glyphs are incompatible with BGRA rendering due to
+their use of the glyph bitmap as a mask.
+
+Scaling is done by averaging all relevant pixel, which gives
+much better result than nearest pixel sampling while staying
+simple enough and not too computationally expensive.
+
+This enables color emoji rendering support.
+
+Fixes: #6
+
+Signed-off-by: Maxime Coste <mawww@kakoune.org>
+---
+ src/xftfreetype.c |  18 +++-
+ src/xftglyphs.c   | 234 +++++++++++++++++++++++++++++++++++++++++++---
+ src/xftint.h      |   2 +
+ src/xftrender.c   |  69 +++++++++++---
+ 4 files changed, 293 insertions(+), 30 deletions(-)
+
+diff --git a/src/xftfreetype.c b/src/xftfreetype.c
+index 1f79a81..4325d65 100644
+--- a/src/xftfreetype.c
++++ b/src/xftfreetype.c
+@@ -523,7 +523,7 @@ XftFontInfoFill (Display *dpy, _Xconst FcPattern *pattern, XftFontInfo *fi)
+     /*
+      * Compute glyph load flags
+      */
+-    fi->load_flags = FT_LOAD_DEFAULT;
++    fi->load_flags = FT_LOAD_DEFAULT | FT_LOAD_COLOR;
+ 
+ #ifndef XFT_EMBEDDED_BITMAP
+ #define XFT_EMBEDDED_BITMAP "embeddedbitmap"
+@@ -775,6 +775,7 @@ XftFontOpenInfo (Display	*dpy,
+     FcChar32		hash_value;
+     FcChar32		rehash_value;
+     FcBool		antialias;
++    FcBool		color;
+     int			max_glyph_memory;
+     int			alloc_size;
+     int			ascent, descent, height;
+@@ -831,12 +832,18 @@ XftFontOpenInfo (Display	*dpy,
+     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
+ 	antialias = FcFalse;
+ 
++    color = FT_HAS_COLOR(face) ? FcTrue : FcFalse;
++
+     /*
+      * Find the appropriate picture format
+      */
+     if (fi->render)
+     {
+-	if (antialias)
++	if (color)
++	{
++	    format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
++	}
++	else if (antialias)
+ 	{
+ 	    switch (fi->rgba) {
+ 	    case FC_RGBA_RGB:
+@@ -968,6 +975,13 @@ XftFontOpenInfo (Display	*dpy,
+      * which doesn't happen in XftFontInfoFill
+      */
+     font->info.antialias = antialias;
++
++    /*
++     * Set color value, which is only known once the
++     * font was loaded
++     */
++    font->info.color = color;
++
+     /*
+      * bump XftFile reference count
+      */
+diff --git a/src/xftglyphs.c b/src/xftglyphs.c
+index b536df4..e0bad10 100644
+--- a/src/xftglyphs.c
++++ b/src/xftglyphs.c
+@@ -26,6 +26,8 @@
+ 
+ #include FT_SYNTHESIS_H
+ 
++#include FT_GLYPH_H
++
+ /*
+  * Validate the memory info for a font
+  */
+@@ -78,9 +80,11 @@ _XftFontValidateMemory (Display *dpy, XftFont *public)
+ static int
+ _compute_xrender_bitmap_size( FT_Bitmap*	target,
+ 			      FT_GlyphSlot	slot,
+-			      FT_Render_Mode	mode )
++			      FT_Render_Mode	mode,
++			      FT_Matrix*        matrix )
+ {
+     FT_Bitmap*	ftbit;
++    FT_Vector	vector;
+     int		width, height, pitch;
+ 
+     if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
+@@ -91,6 +95,16 @@ _compute_xrender_bitmap_size( FT_Bitmap*	target,
+ 
+     width = (int)ftbit->width;
+     height = (int)ftbit->rows;
++
++    if ( matrix && mode == FT_RENDER_MODE_NORMAL )
++    {
++	vector.x = ftbit->width;
++	vector.y = ftbit->rows;
++	FT_Vector_Transform(&vector, matrix);
++
++	width = (int)vector.x;
++	height = (int)vector.y;
++    }
+     pitch = (width+3) & ~3;
+ 
+     switch ( ftbit->pixel_mode )
+@@ -112,6 +126,10 @@ _compute_xrender_bitmap_size( FT_Bitmap*	target,
+ 	}
+ 	break;
+ 
++    case FT_PIXEL_MODE_BGRA:
++	pitch = width * 4;
++	break;
++
+     case FT_PIXEL_MODE_LCD:
+ 	if ( mode != FT_RENDER_MODE_LCD )
+ 	    return -1;
+@@ -142,6 +160,105 @@ _compute_xrender_bitmap_size( FT_Bitmap*	target,
+     return pitch * height;
+ }
+ 
++/* this functions converts the glyph bitmap found in a FT_GlyphSlot
++ * into a different format while scaling by applying the given matrix
++ * (see _compute_xrender_bitmap_size)
++ *
++ * you should call this function after _compute_xrender_bitmap_size
++ *
++ * target :: target bitmap descriptor. Note that its 'buffer' pointer
++ *           must point to memory allocated by the caller
++ *
++ * source :: the source bitmap descriptor
++ *
++ * matrix :: the scaling matrix to apply
++ */
++static void
++_scaled_fill_xrender_bitmap( FT_Bitmap*	target,
++		             FT_Bitmap* source,
++                             const FT_Matrix* matrix )
++{
++    unsigned char*	src_buf	  = source->buffer;
++    unsigned char*	dst_line  = target->buffer;
++    int			src_pitch = source->pitch;
++    int			width     = target->width;
++    int			height    = target->rows;
++    int			pitch     = target->pitch;
++    int			h;
++    FT_Vector		vector;
++    FT_Matrix		inverse	  = *matrix;
++    int			sampling_width;
++    int			sampling_height;
++    int			sample_count;
++
++    if ( src_pitch < 0 )
++	src_buf -= src_pitch * (source->rows - 1);
++
++    FT_Matrix_Invert(&inverse);
++
++    /* compute how many source pixels a target pixel spans */
++    vector.x = 1;
++    vector.y = 1;
++    FT_Vector_Transform(&vector, &inverse);
++    sampling_width = vector.x / 2;
++    sampling_height = vector.y / 2;
++    sample_count = (2 * sampling_width + 1) * (2 * sampling_height + 1);
++
++    for	( h = height; h	> 0; h--, dst_line += pitch )
++    {
++	int x;
++
++	for ( x	= 0; x < width;	x++ )
++	{
++	    unsigned char* src;
++
++#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
++
++            /* compute target pixel location in source space */
++	    vector.x = (x            * 0x10000) + 0x10000 / 2;
++	    vector.y = ((height - h) * 0x10000) + 0x10000 / 2;
++	    FT_Vector_Transform(&vector, &inverse);
++	    vector.x = CLAMP(FT_RoundFix(vector.x) / 0x10000, 0, source->width - 1);
++	    vector.y = CLAMP(FT_RoundFix(vector.y) / 0x10000, 0, source->rows  - 1);
++
++	    switch ( source->pixel_mode	)
++	    {
++	    case FT_PIXEL_MODE_MONO: /* convert mono to 8-bit gray, scale using nearest pixel */
++		src = src_buf + (vector.y * src_pitch);
++		if ( src[(vector.x >> 3)] & (0x80 >> (vector.x & 7)) )
++		    dst_line[x] = 0xff;
++		break;
++
++	    case FT_PIXEL_MODE_GRAY: /* scale using nearest pixel */
++		src = src_buf + (vector.y * src_pitch);
++		dst_line[x] = src[vector.x];
++		break;
++
++	    case FT_PIXEL_MODE_BGRA: /* scale by averaging all relevant source pixels, keep BGRA format */
++	    {
++		int sample_x, sample_y;
++		int bgra[4] = {};
++		for (sample_y = - sampling_height; sample_y < sampling_height + 1; ++sample_y)
++		{
++		    int src_y = CLAMP(vector.y + sample_y, 0, source->rows - 1);
++		    src = src_buf + (src_y * src_pitch);
++		    for (sample_x = - sampling_width; sample_x < sampling_width + 1; ++sample_x)
++		    {
++			int src_x = CLAMP(vector.x + sample_x, 0, source->width - 1);
++			for (int i = 0; i < 4; ++i)
++			    bgra[i] += src[src_x * 4 + i];
++		    }
++		}
++
++		for (int i = 0; i < 4; ++i)
++		    dst_line[4 * x + i] = bgra[i] / sample_count;
++		break;
++	    }
++	    }
++	}
++    }
++}
++
+ /* this functions converts the glyph bitmap found in a FT_GlyphSlot
+  * into a different format (see _compute_xrender_bitmap_size)
+  *
+@@ -244,6 +361,11 @@ _fill_xrender_bitmap( FT_Bitmap*	target,
+ 	    }
+ 	    break;
+ 
++	case FT_PIXEL_MODE_BGRA: /* Preserve BGRA format */
++	    for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
++		memcpy( dstLine, srcLine, width * 4 );
++	    break;
++
+ 	case FT_PIXEL_MODE_LCD:
+ 	    if ( !bgr )
+ 	    {
+@@ -339,6 +461,55 @@ _fill_xrender_bitmap( FT_Bitmap*	target,
+     }
+ }
+ 
++/* This function creates a Picture for the given glyph on the default root window
++ * It will only work in Xinerama mode
++ * 
++ * dpy    :: target display
++ * 
++ * format :: target pixmap format
++ * 
++ * width  :: picture width
++ * 
++ * width  :: picture height
++ * 
++ * data   :: bitmap data
++ * 
++ */
++static Picture
++_create_glyph_bgra_picture (Display           *dpy,
++                            XRenderPictFormat *format,
++                            int               width,
++                            int               height,
++                            unsigned char     *data)
++{
++    XImage image = {
++        width, height, 0, ZPixmap, (char *)data,
++        dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32,
++        32, 0, 32,
++        0, 0, 0
++    };
++    Picture picture;
++    Pixmap pixmap;
++    GC gc;
++
++    pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 32);
++    if (!pixmap)
++        return None;
++
++    gc = XCreateGC(dpy, pixmap, 0, NULL);
++    if (!gc)
++        return None;
++
++    XInitImage(&image);
++    XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, width, height);
++    picture = XRenderCreatePicture(dpy, pixmap, format, 0, NULL);
++
++    XFreeGC(dpy, gc);
++    XFreePixmap(dpy, pixmap);
++
++    return picture;
++}
++
+ _X_EXPORT void
+ XftFontLoadGlyphs (Display	    *dpy,
+ 		   XftFont	    *pub,
+@@ -365,6 +536,8 @@ XftFontLoadGlyphs (Display	    *dpy,
+     FT_Vector	    vector;
+     FT_Face	    face;
+     FT_Render_Mode  mode = FT_RENDER_MODE_MONO;
++    FcBool	    transform;
++    FcBool	    glyph_transform;
+ 
+     if (!info)
+ 	return;
+@@ -374,6 +547,8 @@ XftFontLoadGlyphs (Display	    *dpy,
+     if (!face)
+ 	return;
+ 
++    if (font->info.color)
++        mode = FT_RENDER_MODE_NORMAL;
+     if (font->info.antialias)
+     {
+ 	switch (font->info.rgba) {
+@@ -390,6 +565,8 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 	}
+     }
+ 
++    transform = font->info.transform && mode != FT_RENDER_MODE_MONO;
++
+     while (nglyph--)
+     {
+ 	glyphindex = *glyphs++;
+@@ -440,7 +617,7 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 	/*
+ 	 * Compute glyph metrics from FreeType information
+ 	 */
+-	if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
++	if (transform)
+ 	{
+ 	    /*
+ 	     * calculate the true width by transforming all four corners.
+@@ -487,7 +664,7 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 	 * Clip charcell glyphs to the bounding box
+ 	 * XXX transformed?
+ 	 */
+-	if (font->info.spacing >= FC_CHARCELL && !font->info.transform)
++	if (font->info.spacing >= FC_CHARCELL && !transform)
+ 	{
+ 	    if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
+ 	    {
+@@ -519,18 +696,20 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 	    }
+ 	}
+ 
++	glyph_transform = transform;
+ 	if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
+ 	{
+ 	    error = FT_Render_Glyph( face->glyph, mode );
+ 	    if (error)
+ 		continue;
++	    glyph_transform = False;
+ 	}
+ 
+ 	FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
+ 
+ 	if (font->info.spacing >= FC_MONO)
+ 	{
+-	    if (font->info.transform)
++	    if (transform)
+ 	    {
+ 		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
+ 		{
+@@ -613,14 +792,27 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 	    }
+ 	}
+ 
+-	size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
++	size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL );
+ 	if ( size < 0 )
+ 	    continue;
+ 
+ 	xftg->metrics.width  = (unsigned short)local.width;
+ 	xftg->metrics.height = (unsigned short)local.rows;
+-	xftg->metrics.x      = (short)(- glyphslot->bitmap_left);
+-	xftg->metrics.y      = (short)(  glyphslot->bitmap_top);
++	if (transform)
++	{
++	    vector.x = - glyphslot->bitmap_left;
++	    vector.y =   glyphslot->bitmap_top;
++
++	    FT_Vector_Transform(&vector, &font->info.matrix);
++
++	    xftg->metrics.x = (short)vector.x;
++	    xftg->metrics.y = (short)vector.y;
++	}
++	else
++	{
++	    xftg->metrics.x = (short)(- glyphslot->bitmap_left);
++	    xftg->metrics.y = (short)(  glyphslot->bitmap_top);
++	}
+ 
+ 	/*
+ 	 * If the glyph is relatively large (> 1% of server memory),
+@@ -645,9 +837,12 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 
+ 	local.buffer = bufBitmap;
+ 
+-	_fill_xrender_bitmap( &local, glyphslot, mode,
+-			      (font->info.rgba == FC_RGBA_BGR ||
+-			       font->info.rgba == FC_RGBA_VBGR ) );
++        if (mode == FT_RENDER_MODE_NORMAL && glyph_transform)
++            _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, &font->info.matrix);
++        else
++	    _fill_xrender_bitmap( &local, glyphslot, mode,
++			          (font->info.rgba == FC_RGBA_BGR ||
++			           font->info.rgba == FC_RGBA_VBGR ) );
+ 
+ 	/*
+ 	 * Copy or convert into local buffer.
+@@ -662,6 +857,7 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 	 */
+ 	glyph = (Glyph) glyphindex;
+ 
++	xftg->picture = 0;
+ 	xftg->glyph_memory = (size_t)size + sizeof (XftGlyph);
+ 	if (font->format)
+ 	{
+@@ -685,15 +881,21 @@ XftFontLoadGlyphs (Display	    *dpy,
+ 		    }
+ 		}
+ 	    }
+-	    else if ( mode != FT_RENDER_MODE_NORMAL )
++	    else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL)
+ 	    {
+ 		/* invert ARGB <=> BGRA */
+ 		if (ImageByteOrder (dpy) != XftNativeByteOrder ())
+ 		    XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
+ 	    }
+-	    XRenderAddGlyphs (dpy, font->glyphset, &glyph,
+-			      &xftg->metrics, 1,
+-			      (char *) bufBitmap, size);
++
++	    if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
++    	        xftg->picture = _create_glyph_bgra_picture(dpy, font->format,
++    	                                                   local.width, local.rows,
++    	                                                   bufBitmap);
++	    else
++		XRenderAddGlyphs (dpy, font->glyphset, &glyph,
++				  &xftg->metrics, 1,
++				  (char *) bufBitmap, size);
+ 	}
+ 	else
+ 	{
+@@ -744,7 +946,9 @@ XftFontUnloadGlyphs (Display		*dpy,
+ 	{
+ 	    if (font->format)
+ 	    {
+-		if (font->glyphset)
++		if (xftg->picture)
++		    XRenderFreePicture(dpy, xftg->picture);
++		else if (font->glyphset)
+ 		{
+ 		    glyphBuf[nused++] = (Glyph) glyphindex;
+ 		    if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
+diff --git a/src/xftint.h b/src/xftint.h
+index ced9a02..1af40fe 100644
+--- a/src/xftint.h
++++ b/src/xftint.h
+@@ -85,6 +85,7 @@ typedef struct _XftGlyph {
+     XGlyphInfo	    metrics;
+     void	    *bitmap;
+     unsigned long   glyph_memory;
++    Picture         picture;
+ } XftGlyph;
+ 
+ /*
+@@ -134,6 +135,7 @@ struct _XftFontInfo {
+     FT_F26Dot6		xsize, ysize;	/* pixel size */
+     FcBool		antialias;	/* doing antialiasing */
+     FcBool		embolden;	/* force emboldening */
++    FcBool		color;		/* contains color glyphs */
+     int			rgba;		/* subpixel order */
+     int			lcd_filter;	/* lcd filter */
+     FT_Matrix		matrix;		/* glyph transformation matrix */
+diff --git a/src/xftrender.c b/src/xftrender.c
+index 5852b2e..bd001be 100644
+--- a/src/xftrender.c
++++ b/src/xftrender.c
+@@ -84,12 +84,14 @@ XftGlyphRender (Display		*dpy,
+ 		int		nglyphs)
+ {
+     XftFontInt	    *font = (XftFontInt *) pub;
+-    int		    i;
++    int		    i, j;
+     FT_UInt	    missing[XFT_NMISSING];
+     int		    nmissing;
+     FT_UInt	    g, max;
+     int		    size, width;
++    int		    dstx, dsty;
+     Glyph	    wire;
++    XftGlyph*       glyph;
+     char	    *char8;
+     unsigned short  *char16;
+     unsigned int    *char32;
+@@ -141,22 +143,46 @@ XftGlyphRender (Display		*dpy,
+ 	if (!chars)
+ 	    goto bail1;
+     }
++    dstx = x;
++    dsty = y;
+     char8 = (char *) chars;
+     char16 = (unsigned short *) chars;
+     char32 = (unsigned int *) chars;
+-    for (i = 0; i < nglyphs; i++)
++    for (i = 0, j = 0; i < nglyphs; i++)
+     {
+ 	wire = (Glyph) glyphs[i];
+ 	if (wire >= font->num_glyphs || !font->glyphs[wire])
+ 	    wire = 0;
+-	switch (width) {
+-	case 1: char8[i] = (char) wire; break;
+-	case 2: char16[i] = (unsigned short) wire; break;
+-	case 4: char32[i] = (unsigned int) wire; break;
++        glyph = font->glyphs[wire];
++	if (glyph->picture)
++	{
++	    _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset,
++	                        srcx, srcy, x, y, width, chars, j);
++	    XRenderComposite(dpy, PictOpOver, glyph->picture, None,
++	                     dst, 0, 0, 0, 0, dstx, dsty - glyph->metrics.y,
++	                     glyph->metrics.width, glyph->metrics.height);
++
++	    dstx += glyph->metrics.xOff;
++	    dsty += glyph->metrics.yOff;
++
++	    x = dstx;
++	    y = dsty;
++	    j = 0;
++	}
++	else
++	{
++	    switch (width) {
++	    case 1: char8[j] = (char) wire; break;
++	    case 2: char16[j] = (unsigned short) wire; break;
++	    case 4: char32[j] = (unsigned int) wire; break;
++	    }
++	    dstx += glyph->metrics.xOff;
++	    dsty += glyph->metrics.yOff;
++	    ++j;
+ 	}
+     }
+     _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset,
+-                        srcx, srcy, x, y, width, chars, nglyphs);
++                        srcx, srcy, x, y, width, chars, j);
+     if (chars != char_local)
+ 	free (chars);
+ bail1:
+@@ -319,9 +345,10 @@ XftGlyphSpecRender (Display		    *dpy,
+ 	    g = 0;
+ 	/*
+ 	 * check to see if the glyph is placed where it would
+-	 * fall using the normal spacing
++	 * fall using the normal spacing and if it would render
++	 * as a XRender glyph
+ 	 */
+-	if ((glyph = font->glyphs[g]))
++	if ((glyph = font->glyphs[g]) && !glyph->picture)
+ 	{
+ 	    if (x != glyphs[i].x || y != glyphs[i].y)
+ 	    {
+@@ -335,7 +362,7 @@ XftGlyphSpecRender (Display		    *dpy,
+     }
+ 
+     elts = elts_local;
+-    if (nelt > NUM_ELT_LOCAL)
++    if (!font->info.color && nelt > NUM_ELT_LOCAL)
+     {
+ 	elts = malloc ((size_t)nelt * sizeof (XGlyphElt8));
+ 	if (!elts)
+@@ -343,7 +370,7 @@ XftGlyphSpecRender (Display		    *dpy,
+     }
+ 
+     /*
+-     * Generate the list of glyph elts
++     * Generate the list of glyph elts or render color glyphs
+      */
+     nelt = 0;
+     x = y = 0;
+@@ -357,6 +384,14 @@ XftGlyphSpecRender (Display		    *dpy,
+ 	    g = 0;
+ 	if ((glyph = font->glyphs[g]))
+ 	{
++	    if (glyph->picture)
++	    {
++                XRenderComposite(dpy, PictOpOver, glyph->picture, None,
++                                 dst, 0, 0, 0, 0,
++                                 glyphs[i].x, glyphs[i].y - glyph->metrics.y,
++                                 glyph->metrics.width, glyph->metrics.height);
++                continue;
++	    }
+ 	    if (!i || x != glyphs[i].x || y != glyphs[i].y)
+ 	    {
+ 		if (n)
+@@ -589,7 +624,7 @@ XftGlyphFontSpecRender (Display			    *dpy,
+ 	 * check to see if the glyph is placed where it would
+ 	 * fall using the normal spacing
+ 	 */
+-	if ((glyph = font->glyphs[g]))
++	if ((glyph = font->glyphs[g]) && !glyph->picture)
+ 	{
+ 	    if (pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
+ 	    {
+@@ -614,7 +649,7 @@ XftGlyphFontSpecRender (Display			    *dpy,
+     }
+ 
+     /*
+-     * Generate the list of glyph elts
++     * Generate the list of glyph elts and render color glyphs
+      */
+     nelt = 0;
+     x = y = 0;
+@@ -632,6 +667,14 @@ XftGlyphFontSpecRender (Display			    *dpy,
+ 	    g = 0;
+ 	if ((glyph = font->glyphs[g]))
+ 	{
++	    if (glyph->picture)
++	    {
++                XRenderComposite(dpy, PictOpOver, glyph->picture, None,
++                                 dst, 0, 0, 0, 0,
++                                 glyphs[i].x, glyphs[i].y - glyph->metrics.y,
++                                 glyph->metrics.width, glyph->metrics.height);
++                continue;
++	    }
+ 	    if (!i || pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y)
+ 	    {
+ 		if (n)
+-- 
+2.32.0
+

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: libXft: update and include big fixes
  2021-08-12 12:24 [PR PATCH] libXft: update and include big fixes vigoux
@ 2021-08-12 12:26 ` ericonr
  2021-08-12 12:26 ` [PR PATCH] [Closed]: " ericonr
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: ericonr @ 2021-08-12 12:26 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 248 bytes --]

New comment by ericonr on void-packages repository

https://github.com/void-linux/void-packages/pull/32469#issuecomment-897596954

Comment:
Not an acceptable patch: https://github.com/void-linux/void-packages/pull/32371#pullrequestreview-724930578

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PR PATCH] [Closed]: libXft: update and include big fixes
  2021-08-12 12:24 [PR PATCH] libXft: update and include big fixes vigoux
  2021-08-12 12:26 ` ericonr
@ 2021-08-12 12:26 ` ericonr
  2021-08-12 12:32 ` ericonr
  2021-08-12 12:32 ` ericonr
  3 siblings, 0 replies; 5+ messages in thread
From: ericonr @ 2021-08-12 12:26 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1658 bytes --]

There's a closed pull request on the void-packages repository

libXft: update and include big fixes
https://github.com/void-linux/void-packages/pull/32469

Description:
<!-- Mark items with [x] where applicable -->
#### General
- [ ] This is a new package and it conforms to the [quality requirements](https://github.com/void-linux/void-packages/blob/master/Manual.md#quality-requirements)

#### Have the results of the proposed changes been tested?
- [x] I use the packages affected by the proposed changes on a regular basis and confirm this PR works for me
- [ ] I generally don't use the affected packages but briefly tested this PR

<!--
If GitHub CI cannot be used to validate the build result (for example, if the
build is likely to take several hours), make sure to
[skip CI](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#continuous-integration).
When skipping CI, uncomment and fill out the following section.
Note: for builds that are likely to complete in less than 2 hours, it is not
acceptable to skip CI.
-->
#### Does it build and run successfully? 
(Please choose at least one native build and, if supported, at least one cross build. More are better.)
- [x] I built this PR locally for my native architecture, (x86_64-gnu)
- [ ] I built this PR locally for these architectures (if supported. mark crossbuilds):
  - [ ] aarch64-musl
  - [ ] armv7l
  - [ ] armv6l-musl

#### Other

This PR includes patches that are waiting to be merged upstream, and
fix a bug. Including these patched solved numerous issues with `st`,
where colored emojis caused a hard crash of the terminal emulator.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: libXft: update and include big fixes
  2021-08-12 12:24 [PR PATCH] libXft: update and include big fixes vigoux
  2021-08-12 12:26 ` ericonr
  2021-08-12 12:26 ` [PR PATCH] [Closed]: " ericonr
@ 2021-08-12 12:32 ` ericonr
  2021-08-12 12:32 ` ericonr
  3 siblings, 0 replies; 5+ messages in thread
From: ericonr @ 2021-08-12 12:32 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 319 bytes --]

New comment by ericonr on void-packages repository

https://github.com/void-linux/void-packages/pull/32469#issuecomment-897600631

Comment:
https://github.com/void-linux/void-packages/pull/32452 was handling the update already.

Sorry if the answer was too brisk, I'm trying to keep the PR queue down where possible.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: libXft: update and include big fixes
  2021-08-12 12:24 [PR PATCH] libXft: update and include big fixes vigoux
                   ` (2 preceding siblings ...)
  2021-08-12 12:32 ` ericonr
@ 2021-08-12 12:32 ` ericonr
  3 siblings, 0 replies; 5+ messages in thread
From: ericonr @ 2021-08-12 12:32 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 224 bytes --]

New comment by ericonr on void-packages repository

https://github.com/void-linux/void-packages/pull/32469#issuecomment-897601145

Comment:
I'm hopeful that if a proper solution appears, it will be merged into mainstream :/

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-08-12 12:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-12 12:24 [PR PATCH] libXft: update and include big fixes vigoux
2021-08-12 12:26 ` ericonr
2021-08-12 12:26 ` [PR PATCH] [Closed]: " ericonr
2021-08-12 12:32 ` ericonr
2021-08-12 12:32 ` ericonr

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).