Subject: Re: bug#73730: 31.0.50; Support for color fonts on MS-Windows

From: Cecilio Pardo <[email-masked]>
Date: Sat, 26 Oct 2024 22:13:57 +0200

>>> Thanks, I will review this shortly.  Meanwhile, could you please look
>>> at how Emacs with this patch displays some complex Emoji sequences?
>>> Some of them look incorrect to me.  For example, this sequence from
>>> admin/unidata/emoji-zwj-sequences.txt:
>>>
>>>     1F469 200D 1F469 200D 1F467 200D 1F466      ; RGI_Emoji_ZWJ_Sequence  ; family: woman, woman, girl, boy                                # E2.0   [1] (👩‍👩‍👧‍👦)
>>>
>>> when displayed using Segoe UI Emoji, is shown with the "boy" part
>>> overlapping the closing parenthesis, which looks incorrect to me.
>>> "C-u C-x =" claims all of the codepoints of the sequence were composed
>>> into a single grapheme cluster, but it doesn't look like that on
>>> display, and the cursor doesn't include the "boy" part.
>>
>> I dont's see that, but I do see that the individual glyphs are truncated
>> on the left side, even when removing color rendering.  Do you see
>> it?
> 
> Yes.
> 
>> I will investigate this first, in case the defects are related.

This patch fixes the left side glyph truncation, which happens when 
glyphs have negative left bearing.

About the problem you reported, I can't reproduce when building for 
64bit. It does show when building with mingw32 for 32bit. It also shows 
when building version 30.0.92. Maybe is the Harfbuzz version? I have 
2.4.0 for this build.

From 49e3534901b2b7b832ec15977d78962a62417789 Mon Sep 17 00:00:00 2001
From: Cecilio Pardo <[email-masked]>
Date: Sat, 26 Oct 2024 17:51:22 +0200
Subject: [PATCH] ; Fix problem with DirectWrite (MS-Windows)

Negative lbearings were not handled.

* src/w32dwrite.c (w32_dwrite_draw): Modified to handle negative
lbearing.
---
 src/w32dwrite.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/w32dwrite.c b/src/w32dwrite.c
index ecc33af5f3f..45be5b5beff 100644
--- a/src/w32dwrite.c
+++ b/src/w32dwrite.c
@@ -895,7 +895,9 @@ w32_dwrite_draw (HDC hdc, int x, int y, unsigned *glyphs, int len,
       return false;
     }
 
-  int bitmap_width = metrics.width + metrics.rbearing;
+  int left_margin = metrics.lbearing < 0 ? -metrics.lbearing : 0;
+
+  int bitmap_width = left_margin + metrics.width + metrics.rbearing;
   int bitmap_height = font->ascent + font->descent;
 
   /* We never release this, get_bitmap_render_target reuses it.  */
@@ -914,7 +916,7 @@ w32_dwrite_draw (HDC hdc, int x, int y, unsigned *glyphs, int len,
     = bitmap_render_target->lpVtbl->GetMemoryDC (bitmap_render_target);
 
   /* Copy the background pixel to the render target bitmap.  */
-  BitBlt (text_dc, 0, 0, bitmap_width, bitmap_height, hdc, x, y, SRCCOPY);
+  BitBlt (text_dc, 0, 0, bitmap_width, bitmap_height, hdc, x - left_margin, y, SRCCOPY);
 
   UINT16 *indices = SAFE_ALLOCA (len * sizeof (UINT16));
 
@@ -948,7 +950,7 @@ w32_dwrite_draw (HDC hdc, int x, int y, unsigned *glyphs, int len,
   IDWriteColorGlyphRunEnumerator *layers;
   /* This call will tell us if we have to handle any color glyphs.  */
   hr = dwrite_factory2->lpVtbl->TranslateColorGlyphRun (dwrite_factory2,
-							0, font->ascent,
+							left_margin, font->ascent,
 							&glyph_run,
 							NULL,
 							MEASURING_MODE,
@@ -959,7 +961,7 @@ w32_dwrite_draw (HDC hdc, int x, int y, unsigned *glyphs, int len,
   /* No color.  Just draw the GlyphRun.  */
   if (hr == DWRITE_E_NOCOLOR)
     bitmap_render_target->lpVtbl->DrawGlyphRun (bitmap_render_target,
-						0, font->ascent,
+						left_margin, font->ascent,
 						MEASURING_MODE,
 						&glyph_run,
 						rendering_params,
@@ -1024,7 +1026,7 @@ w32_dwrite_draw (HDC hdc, int x, int y, unsigned *glyphs, int len,
     }
 
   /* Finally, copy the rendered text back to the original DC.  */
-  BitBlt (hdc, x, y, bitmap_width, bitmap_height, text_dc, 0, 0, SRCCOPY);
+  BitBlt (hdc, x - left_margin, y, bitmap_width, bitmap_height, text_dc, 0, 0, SRCCOPY);
   SAFE_FREE ();
   return true;
 }
-- 
2.35.1.windows.2