[GDI32] Fix for GetTextExtentExPointW() and ExtTextOutW() - Fixes Bug 50

Pedro Araujo Chaves Jr. inckie at gmail.com
Thu Feb 8 09:12:08 CST 2007


Out of distraction, I forgot to attach the patch; thanks, Paul!

On 2/8/07, Pedro Araujo Chaves Jr. <inckie at gmail.com> wrote:
> Attached is my proposed patch for Bug #50; the test case was attached
> in my previous message.
> --
> Patch description:
>
> This patch fixes Wine's Bug #50: "PrgWin95: Text justification needs
> beefing up".
>
> What it does: first, it takes in consideration that not always the
> number of extra pixels will be a multiple of the number of break
> characters in a given extent of a given string that should be
> justified, and so the integer division of extra by breaks in
> SetTextJustification() is likely to leave a remainder (which the
> latter function addresses, of course, but ExtTextOutW() seems to
> overlook — that's the reason for the changes at lines 1788 (breakRem),
> and 1901 and 1922 (dc->breakExtra || breakRem), which prevent some
> lines from being ignored in the justification).
>
> That fixed, if there remained any pixels indeed, their number
> shouldn't be greater than dc->breakCount; then the first breakRem
> break characters in that given extent are widened by one pixel (lines
> 1925-1929 added).
>
> GetTextExtentExPointW() is also fixed so that it now returns the
> expected width of the text when it is to be justified. This has the
> good side effect that TabbedTextOut() now also returns the proper
> width when called after SetTextJustification(). What the patch does
> here is that GetTextExtentExPointW() now calculates the extra width
> only when (breakExtra || breakRem) resolves TRUE , and corrects the
> extra space additions by applying them only to break characters. What
> was broken before is that it always added extra space, regardless of
> whether it was measuring a single character or a full string, or
> whether it was a break character or not. (Lines added: 1191, 1199,
> 1227, 1229, 1236-1245, 1254-1268).
>
> This patch is copyrighted by Banco do Brasil under the LGPL.
>
> --
> Regards,
> Pedro Araújo.
>


-- 
- Pedro.
• http://rascunhares.blogspot.comhttp://www.google.com/reader/shared/00213802817312894568

"Ubuntu [...] is a serious user-friendly OS, but, like all in its
gang, not idiot-friendly."
(Alexandru Bradescu-Popa)
-------------- next part --------------
---
 dlls/gdi32/font.c       |   53 ++++++++++++++++++++++++++++++++++++++++-------
 dlls/gdi32/tests/font.c |    3 ---
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index ee57ba8..fe16cb5 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -1188,6 +1188,7 @@ BOOL WINAPI GetTextExtentExPointW( HDC h
     LPINT dxs = NULL;
     DC *dc;
     BOOL ret = FALSE;
+    TEXTMETRICW tm;
 
     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
 
@@ -1195,6 +1196,8 @@ BOOL WINAPI GetTextExtentExPointW( HDC h
     if (! dc)
         return FALSE;
 
+    GetTextMetricsW(hdc, &tm);
+
     /* If we need to calculate nFit, then we need the partial extents even if
        the user hasn't provided us with an array.  */
     if (lpnFit)
@@ -1220,22 +1223,49 @@ BOOL WINAPI GetTextExtentExPointW( HDC h
     /* Perform device size to world size transformations.  */
     if (ret)
     {
-	INT extra = dc->charExtra, breakRem = dc->breakRem;
+	INT extra      = dc->charExtra,
+        breakExtra = dc->breakExtra,
+        breakRem   = dc->breakRem,
+        i;
 
 	if (dxs)
 	{
-	    INT i;
 	    for (i = 0; i < count; ++i)
 	    {
 		dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
-		dxs[i] += (i+1) * extra + breakRem;
+		dxs[i] += (i+1) * extra;
+                if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
+                {
+                    dxs[i] += breakExtra;
+                    if (breakRem > 0)
+                    {
+                        breakRem--;
+                        dxs[i]++;
+                    }
+                }
 		if (dxs[i] <= maxExt)
 		    ++nFit;
 	    }
+            breakRem = dc->breakRem;
 	}
 	size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
 	size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
-	size->cx += count * extra + breakRem;
+
+        if (!dxs && count > 1 && (breakExtra || breakRem))
+        {
+            for (i = 0; i < count; i++)
+            {
+                if (str[i] == tm.tmBreakChar)
+                {
+                    size->cx += breakExtra;
+                    if (breakRem > 0)
+                    {
+                        breakRem--;
+                        (size->cx)++;
+                    }
+                }
+            }
+        }
     }
 
     if (lpnFit)
@@ -1768,12 +1798,15 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
     SIZE sz;
     RECT rc;
     BOOL done_extents = FALSE;
-    INT width, xwidth = 0, ywidth = 0;
+    INT width = 0, xwidth = 0, ywidth = 0;
     DWORD type;
     DC * dc = DC_GetDCUpdate( hdc );
+    INT breakRem;
 
     if (!dc) return FALSE;
 
+    breakRem = dc->breakRem;
+
     if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
 
@@ -1883,8 +1916,7 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
     y = pt.y;
 
     char_extra = GetTextCharacterExtra(hdc);
-    width = 0;
-    if(char_extra || dc->breakExtra || lpDx)
+    if(char_extra || dc->breakExtra || breakRem || lpDx)
     {
         UINT i;
         SIZE tmpsz;
@@ -1905,9 +1937,14 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x,
                 deltas[i] = tmpsz.cx;
             }
             
-            if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
+            if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
             {
                 deltas[i] = deltas[i] + dc->breakExtra;
+                if (breakRem > 0)
+                {
+                    breakRem--;
+                    deltas[i]++;
+                }
             }
             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
             width += deltas[i];
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 10e9e7d..5e73ce3 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -898,8 +898,6 @@ void testJustification(HDC hdc, PSTR str
 
     for (e = 0; e < nErrors; e++)
     {
-todo_wine
-{
         ok(error[e].TabbedTextOutWidth == areaWidth,
             "The output text (\"%s\") width should be %d, not %d.\n",
             error[e].extent, areaWidth, error[e].TabbedTextOutWidth);
@@ -908,7 +906,6 @@ todo_wine
         ok(error[e].GetTextExtentExPointWWidth == areaWidth,
             "GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
             error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
-}
     }
 }
 
-- 
1.4.1


More information about the wine-patches mailing list