[GDI32] Test case for SetTextJustification(), GetTextExtentExPointW(), and TabbedTextOut()

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


I'm resending this test case, having added a small test to check
whether GetTextExtentExPointW() returns the proper width after a call
to SetTextJustification() sets the text to be justified.

Test description:

This test is based on the results of my traces of Lotus Notes R5: in
order to get a long string linewrapped and justified, it first uses
GetTextExtent32() to get the word sequences that fit in a single line
(the paragraph extents); then it calls SetTextJustification() to
disable justification and then again GetTextExtent32(),  in order to
compare this width to the width of the container and get the total
extra space — which should be divided as evenly as possible among the
break characters found in the extent, which is done with a new call to
SetTextJustification() with breakExtra and breakCount. That way, as
expected, a subsequent call to TabbedTextOut() (which in turn calls
ExtTextOutW()) will result in that the text will be rendered
justified, that is, with its break characters widened so that its
width is equal to that of the client area.

The test suceeds if all the extents, except for the last one, which is
likely to be too short to reach the opposite margin, are output with
the same width as the client area.

About me, again: my name is Pedro Araújo and I work for Banco do Brasil; I
was assigned the task of improving the execution under Wine of
applications used by the bank employees — Lotus Notes R5, in the case
of this patch.

Regards,
Pedro Araújo.
-------------- next part --------------
---
 dlls/gdi32/tests/font.c |  127 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 670ec36..10e9e7d 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -817,6 +817,132 @@ static void test_GetOutlineTextMetrics(v
     ReleaseDC(0, hdc);
 }
 
+void testJustification(HDC hdc, PSTR str, RECT *clientArea)
+{
+    INT         x, y,
+                breakCount,
+                outputWidth = 0,    /* to test TabbedTextOut() */
+                justifiedWidth = 0, /* to test GetTextExtentExPointW() */
+                areaWidth = clientArea->right - clientArea->left,
+                nErrors = 0, e;
+    BOOL        lastExtent = FALSE;
+    PSTR        pFirstChar, pLastChar;
+    SIZE        size;
+    TEXTMETRICA tm;
+    struct err
+    {
+        char extent[100];
+        int  GetTextExtentExPointWWidth;
+        int  TabbedTextOutWidth;
+    } error[10];
+
+    GetTextMetricsA(hdc, &tm);
+    y = clientArea->top;
+    do {
+        breakCount = 0;
+        while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
+        pFirstChar = str;
+
+        do {
+            pLastChar = str;
+
+            /* if not at the end of the string, ... */
+            if (*str == '\0') break;
+            /* ... add the next word to the current extent */
+            while (*str != '\0' && *str++ != tm.tmBreakChar);
+            breakCount++;
+            SetTextJustification(hdc, 0, 0);
+            GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
+        } while ((int) size.cx < areaWidth);
+
+        /* ignore trailing break chars */
+        breakCount--;
+        while (*(pLastChar - 1) == tm.tmBreakChar)
+        {
+            pLastChar--;
+            breakCount--;
+        }
+
+        if (*str == '\0' || breakCount <= 0) pLastChar = str;
+
+        SetTextJustification(hdc, 0, 0);
+        GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
+
+        /* do not justify the last extent */
+        if (*str != '\0' && breakCount > 0)
+        {
+            SetTextJustification(hdc, areaWidth - size.cx, breakCount);
+            GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
+            justifiedWidth = size.cx;
+        }
+        else lastExtent = TRUE;
+
+        x = clientArea->left;
+
+        outputWidth = LOWORD(TabbedTextOut(
+                             hdc, x, y, pFirstChar, pLastChar - pFirstChar,
+                             0, NULL, 0));
+        /* catch errors and report them */
+        if (!lastExtent && ((outputWidth != areaWidth) || (justifiedWidth != areaWidth)))
+        {
+            memset(error[nErrors].extent, 0, 100);
+            memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
+            error[nErrors].TabbedTextOutWidth = outputWidth;
+            error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
+            nErrors++;
+        }
+
+        y += size.cy;
+        str = pLastChar;
+    } while (*str && y < clientArea->bottom);
+
+    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);
+        /* The width returned by GetTextExtentPoint32() is exactly the same
+           returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
+        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);
+}
+    }
+}
+
+void test_SetTextJustification()
+{
+    HDC hdc = GetDC(0);
+    RECT clientArea = {0, 0, 400, 400};
+    LOGFONTA lf;
+    HFONT hfont;
+    static char testText[] =
+            "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
+            "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
+            "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
+            "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
+            "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
+            "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
+            "sunt in culpa qui officia deserunt mollit anim id est laborum.";
+
+    memset(&lf, 0, sizeof lf);
+    lf.lfCharSet = ANSI_CHARSET;
+    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+    lf.lfWeight = FW_DONTCARE;
+    lf.lfHeight = 20;
+    lf.lfQuality = DEFAULT_QUALITY;
+    lstrcpyA(lf.lfFaceName, "Times New Roman");
+    hfont = create_font("Times New Roman", &lf);
+    SelectObject(hdc, hfont);
+
+    testJustification(hdc, testText, &clientArea);
+
+    DeleteObject(hfont);
+    ReleaseDC(0, hdc);
+}
+
 START_TEST(font)
 {
     test_logfont();
@@ -828,4 +954,5 @@ START_TEST(font)
     test_GetGlyphIndices();
     test_GetKerningPairs();
     test_GetOutlineTextMetrics();
+    test_SetTextJustification();
 }
-- 
1.4.1


More information about the wine-patches mailing list