[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.com
• http://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