unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* Emacs 22.3 Windows Draw/Redraw Issues
@ 2008-09-19 18:00 Ng, Andrew
  2008-09-19 21:06 ` Jason Rumney
  0 siblings, 1 reply; 2+ messages in thread
From: Ng, Andrew @ 2008-09-19 18:00 UTC (permalink / raw)
  To: emacs-devel, bug-gnu-emacs

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

I have come across various draw/redraw problems with Emacs on Windows,
particular since ClearType support was enabled. These problems annoyed
me sufficiently that I decided to fix them myself. I have tried to get
these fixes submitted previously, but with no success thus far.

I've included two test files that show some of these issues. If you run
a plain "emacs -Q" and load in "test.html" and then move the cursor
right over the text, you will see problems with the italic text as the
cursor is moved to the right. It's particularly noticeable on the 'W'
and 'H' characters.

Load in the "test.txt" file and you will notice the same problem with
italic text. If you shrink the Emacs window such that the buffer is 3
lines high and then page up and down, you will sometimes get a stray
pixel appear in the top left hand corner of the 'C' character.

The issues described above happen both with or without ClearType
enabled. Using a font such as "Lucida Console" with
"w32-enable-synthesized-fonts" enabled further highlights some of the
issues. The issues will vary depending on the font used.

I've included diffs for the files that I have modified based on the
current source from the "EMACS_22_BASE" branch. There are quite a few
changes, so I expect this won't be a straightforward submission, if it
is accepted. I have already signed and returned all appropriate
paperwork to allow my changes to be accepted.

Thanks.

Regards,

Andrew Ng


[-- Attachment #2: diffs --]
[-- Type: application/octet-stream, Size: 11052 bytes --]

Index: dispnew.c
===================================================================
RCS file: /sources/emacs/emacs/src/dispnew.c,v
retrieving revision 1.392.2.3
diff -u -r1.392.2.3 dispnew.c
--- dispnew.c	5 Mar 2008 00:50:06 -0000	1.392.2.3
+++ dispnew.c	19 Sep 2008 17:21:53 -0000
@@ -4522,9 +4522,7 @@
 		 taken care of by draw_glyphs.  */
 	      if (overlapping_glyphs_p
 		  && i > 0
-		  && i < current_row->used[TEXT_AREA]
-		  && (current_row->used[TEXT_AREA]
-		      != desired_row->used[TEXT_AREA]))
+		  && i < current_row->used[TEXT_AREA])
 		{
 		  int left, right;
 
Index: macterm.c
===================================================================
RCS file: /sources/emacs/emacs/src/Attic/macterm.c,v
retrieving revision 1.214.2.31
diff -u -r1.214.2.31 macterm.c
--- macterm.c	2 Sep 2008 08:19:06 -0000	1.214.2.31
+++ macterm.c	19 Sep 2008 17:21:58 -0000
@@ -2774,6 +2774,8 @@
       XCharStruct cs;
 
       mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
+      if (s->face->overstrike)
+        cs.rbearing++;
       s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
       s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
     }
@@ -2789,6 +2791,8 @@
       TextFace (font->mac_fontface);
 
       QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
+      if (s->face->overstrike)
+        r.right++;
 
       mac_end_clip (s->f, NULL);
 
Index: w32term.c
===================================================================
RCS file: /sources/emacs/emacs/src/w32term.c,v
retrieving revision 1.259.2.12
diff -u -r1.259.2.12 w32term.c
--- w32term.c	1 Aug 2008 15:10:50 -0000	1.259.2.12
+++ w32term.c	19 Sep 2008 17:22:01 -0000
@@ -146,6 +146,10 @@
 /* Flag to enable Cleartype hack for font metrics.  */
 static int cleartype_active;
 
+/* Dynamic linking to GetCharABCWidthsFloat (not available on 95, 98, ME).  */
+BOOL (PASCAL *pfnGetCharABCWidthsFloatW) (HDC hdc, UINT iFirstChar, UINT iLastChar, LPABCFLOAT lpABCF);
+BOOL (PASCAL *pfnGetCharABCWidthsFloatA) (HDC hdc, UINT iFirstChar, UINT iLastChar, LPABCFLOAT lpABCF);
+
 DWORD dwWindowsThreadId = 0;
 HANDLE hWindowsThread = NULL;
 DWORD dwMainThreadId = 0;
@@ -881,7 +885,39 @@
 
   old_font = SelectObject (hdc, font->hfont);
 
-  if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
+  if (pfnGetCharABCWidthsFloatW && pfnGetCharABCWidthsFloatA)
+    {
+      ABCFLOAT char_widths;
+
+      if (font_type == UNICODE_FONT)
+	retval = pfnGetCharABCWidthsFloatW (hdc, *char2b, *char2b, &char_widths);
+      else
+	retval = pfnGetCharABCWidthsFloatA (hdc, *char2b, *char2b, &char_widths);
+
+      if (retval)
+	{
+	  if (cleartype_active
+              && ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
+              && (*char2b != ' '))
+	    {
+	      /* Cleartype antialiasing can cause characters to overhang
+		 by a pixel on each side compared with what GetCharABCWidths
+		 reports.  */
+	      char_widths.abcfA -= 1;
+	      char_widths.abcfC -= 1;
+	      char_widths.abcfB += 2;
+	    }
+
+	  pcm->width = (short) (char_widths.abcfA + char_widths.abcfB + char_widths.abcfC);
+
+	  pcm->lbearing = (short) char_widths.abcfA;
+	  pcm->rbearing = (short) (char_widths.abcfA + char_widths.abcfB);
+	  pcm->ascent = FONT_BASE (font);
+	  pcm->descent = FONT_DESCENT (font);
+	}
+    }
+
+  if (!retval && ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0))
     {
       ABC char_widths;
 
@@ -901,9 +937,9 @@
 	  int real_width;
 	  GetCharWidth (hdc, *char2b, *char2b, &real_width);
 #endif
-	  if (cleartype_active)
+	  if (cleartype_active && (*char2b != ' '))
 	    {
-	      /* Cleartype antialiasing causes characters to overhang
+	      /* Cleartype antialiasing can cause characters to overhang
 		 by a pixel on each side compared with what GetCharABCWidths
 		 reports.  */
 	      char_widths.abcA -= 1;
@@ -947,15 +983,14 @@
 
       if (retval)
 	{
-	  pcm->width = sz.cx - font->tm.tmOverhang;
-	  pcm->rbearing = sz.cx;
+	  pcm->width = sz.cx;
+	  pcm->rbearing = sz.cx + font->tm.tmOverhang;
 	  pcm->lbearing = 0;
 	  pcm->ascent = FONT_BASE (font);
 	  pcm->descent = FONT_DESCENT (font);
 	}
     }
 
-
   if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
     {
       retval = FALSE;
@@ -1038,29 +1073,25 @@
     }
   else
     {
-      if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
-          /* Some fonts (eg DBCS fonts) are marked as fixed width even
-             though they contain characters of different widths. */
-          || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
-	{
-	  /* Font is not fixed pitch, so cache per_char info for the
-             ASCII characters.  It would be much more work, and probably
-             not worth it, to cache other chars, since we may change
-             between using Unicode and ANSI text drawing functions at
-             run-time.  */
-	  int i;
-
-	  font->per_char = xmalloc (128 * sizeof(XCharStruct));
-	  for (i = 0; i < 128; i++)
-	    {
-	      char2b = i;
-	      w32_native_per_char_metric (font, &char2b, ANSI_FONT,
-					  &font->per_char[i]);
-	    }
-	}
+      /* Check for fixed width, not vector and not truetype fonts. */
+      if (((font->tm.tmPitchAndFamily & (TMPF_FIXED_PITCH | TMPF_VECTOR | TMPF_TRUETYPE)) == 0)
+          && (font->tm.tmMaxCharWidth == font->tm.tmAveCharWidth))
+        {
+          w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+                                      &font->max_bounds);   
+        }
       else
-	w32_native_per_char_metric (font, &char2b, ANSI_FONT,
-				    &font->max_bounds);
+        {
+          int i;
+
+          font->per_char = xmalloc (128 * sizeof(XCharStruct));
+          for (i = 0; i < 128; ++i)
+            {
+              char2b = i;
+              w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+                                          &font->per_char[i]);
+            }
+        }
     }
 }
 
@@ -1437,9 +1468,47 @@
 w32_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  /* TODO: Windows does not appear to have a method for
-     getting this info without getting the ABC widths for each
-     individual character and working it out manually. */
+  if (s->cmp == NULL
+      && s->first_glyph->type == CHAR_GLYPH
+      && s->nchars > 0)
+    {
+      XFontStruct *font = s->font;
+      const int    font_type = s->first_glyph->font_type;
+
+      wchar_t  *ws = s->char2b;
+      const int nc = s->nchars;
+      int       i, pos, mn, mx;
+      if (nc == 1)
+        {
+          XCharStruct *pcm = w32_per_char_metric (font, ws, font_type);
+          short        rbearing = pcm->rbearing;
+          if (s->face->overstrike)
+            ++rbearing;
+          s->right_overhang = rbearing > pcm->width ? rbearing - pcm->width : 0;
+          s->left_overhang  = pcm->lbearing < 0 ? -pcm->lbearing : 0;
+          return;
+        }
+
+      pos = mn = mx = 0;
+      for (i = 0; i < nc; ++i, ++ws)
+        {
+          XCharStruct *pcm = w32_per_char_metric (font, ws, font_type);
+
+          const int rp = pos + pcm->rbearing;
+          const int lp = pos + pcm->lbearing;
+
+          if (rp > mx) mx = rp;
+          if (lp < mn) mn = lp;
+
+          pos += pcm->width;
+        }
+
+      if (s->face->overstrike)
+          ++mx;
+
+      s->right_overhang = mx > pos ? mx - pos : 0;
+      s->left_overhang  = mn < 0 ? -mn : 0;
+    }
 }
 
 
@@ -6476,7 +6545,7 @@
   w32_destroy_fringe_bitmap,
   w32_per_char_metric,
   w32_encode_char,
-  NULL, /* w32_compute_glyph_string_overhangs */
+  w32_compute_glyph_string_overhangs,
   x_draw_glyph_string,
   w32_define_frame_cursor,
   w32_clear_frame_area,
@@ -6574,6 +6643,17 @@
     UINT smoothing_type;
     BOOL smoothing_enabled;
 
+    HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
+
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
+
+    LOAD_PROC (gdi_lib, GetCharABCWidthsFloatW);
+    LOAD_PROC (gdi_lib, GetCharABCWidthsFloatA);
+
+#undef LOAD_PROC
+
+    FreeLibrary (gdi_lib);
+
     /* If using proportional scroll bars, ensure handle is at least 5 pixels;
        otherwise use the fixed height.  */
     vertical_scroll_bar_min_handle = 5;
@@ -6600,10 +6680,10 @@
        compensate for the "sub-pixels" that are not counted by the
        system APIs. */
     cleartype_active =
-      SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0)
-      && smoothing_enabled
-      && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)
-      && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE;
+        (SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0)
+         && smoothing_enabled
+         && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)
+         && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE);
   }
 }
 
Index: xdisp.c
===================================================================
RCS file: /sources/emacs/emacs/src/xdisp.c,v
retrieving revision 1.1149.2.33
diff -u -r1.1149.2.33 xdisp.c
--- xdisp.c	26 Aug 2008 11:11:46 -0000	1.1149.2.33
+++ xdisp.c	19 Sep 2008 17:22:06 -0000
@@ -19207,8 +19207,11 @@
       if (font  /* ++KFS: Should this be font_info ?  */
 	  && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
 	{
-	  if (pcm->rbearing > pcm->width)
-	    *right = pcm->rbearing - pcm->width;
+          short rbearing = pcm->rbearing;
+          if (face->overstrike)
+            ++rbearing;
+	  if (rbearing > pcm->width)
+	    *right = rbearing - pcm->width;
 	  if (pcm->lbearing < 0)
 	    *left = -pcm->lbearing;
 	}
@@ -20617,7 +20620,7 @@
 	      /* If characters with lbearing or rbearing are displayed
 		 in this line, record that fact in a flag of the
 		 glyph row.  This is used to optimize X output code.  */
-	      if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
+	      if (pcm && (pcm->lbearing < 0 || (face->overstrike ? (pcm->rbearing + 1) : pcm->rbearing) > pcm->width))
 		it->glyph_row->contains_overlapping_glyphs_p = 1;
 	    }
 	}
@@ -20762,7 +20765,7 @@
 	      it->phys_descent = pcm->descent - boff;
 	      if (it->glyph_row
 		  && (pcm->lbearing < 0
-		      || pcm->rbearing > pcm->width))
+		      || (face->overstrike ? (pcm->rbearing + 1) : pcm->rbearing) > pcm->width))
 		it->glyph_row->contains_overlapping_glyphs_p = 1;
 	    }
 	  it->nglyphs = 1;
Index: xterm.c
===================================================================
RCS file: /sources/emacs/emacs/src/xterm.c,v
retrieving revision 1.943.2.16
diff -u -r1.943.2.16 xterm.c
--- xterm.c	21 Aug 2008 19:40:29 -0000	1.943.2.16
+++ xterm.c	19 Sep 2008 17:22:08 -0000
@@ -1191,6 +1191,8 @@
       int direction, font_ascent, font_descent;
       XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
 		      &font_ascent, &font_descent, &cs);
+      if (s->face->overstrike)
+        cs.rbearing++;
       s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
       s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
     }

[-- Attachment #3: test.html --]
[-- Type: text/html, Size: 30 bytes --]

[-- Attachment #4: test.txt --]
[-- Type: text/plain, Size: 1321 bytes --]

Content-Type: text/enriched
Text-Width: 70

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|<bold>W</bold>d<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L

|Cd<bold><italic>W</italic></bold>L


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

* Re: Emacs 22.3 Windows Draw/Redraw Issues
  2008-09-19 18:00 Emacs 22.3 Windows Draw/Redraw Issues Ng, Andrew
@ 2008-09-19 21:06 ` Jason Rumney
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Rumney @ 2008-09-19 21:06 UTC (permalink / raw)
  To: Ng, Andrew; +Cc: bug-gnu-emacs, emacs-devel

Ng, Andrew wrote:
> I have come across various draw/redraw problems with Emacs on Windows,
> particular since ClearType support was enabled. These problems annoyed
> me sufficiently that I decided to fix them myself. I have tried to get
> these fixes submitted previously, but with no success thus far.
>   

Hi Andrew,

I did apply a minimum subset of the patches you submitted that was 
required to eliminate all bugs reported before the date I applied the 
patch. This was done at the last minute before 22.2 was released (thus 
the reason why I tried to reduce the impact of your changes), and since 
there were no reports after 22.2 was released, this was never revisited. 
The Emacs 22 branch is effectively dead with the release of 22.3 AFAIK, 
and the font handling in Emacs 23 is completely different, so if patches 
are still required, they are likely to be completely different.





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

end of thread, other threads:[~2008-09-19 21:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-19 18:00 Emacs 22.3 Windows Draw/Redraw Issues Ng, Andrew
2008-09-19 21:06 ` Jason Rumney

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).