Slow EULA display patch

Daniel Steven Hipschman dsh at linux.ucla.edu
Sat Jul 1 00:44:31 CDT 2006


This patch fixes the slow EULA loading problem in
http://bugs.winehq.org/show_bug.cgi?id=5516
The problem was that GetTextExtentExPointW was using an order n-squared
algorithm to fill in the array of partial extents.  It computed the extent
of every prefix of the string using WineEngGetTextExtentPoint.  The fix
moves the filling in of the array into the lower level function
WineEngGetTextExtentExPoint, which can do this at the same time as when
it computes the complete extent.  The patch speeds up loading of the
EULA in Adobe's trial product
(http://www.adobe.com/products/acrobatpro/tryreg.html) from 7-8 minutes to
seconds on my system.

ChangeLog:
* Sped up GetTextExtentExPointW by adding a new freetype GDI font function
  WineEngGetTextExtentExPoint and a new DC function pGetTextExtentExPoint.
---
 dlls/gdi/enhmfdrv/init.c |    1 +
 dlls/gdi/font.c          |   68 ++++++++++++++++------------------------------
 dlls/gdi/freetype.c      |   48 ++++++++++++++++++++++++++------
 dlls/gdi/gdi_private.h   |    2 +
 dlls/gdi/mfdrv/init.c    |    1 +
 5 files changed, 66 insertions(+), 54 deletions(-)

diff --git a/dlls/gdi/enhmfdrv/init.c b/dlls/gdi/enhmfdrv/init.c
index 82f0222..4c64fae 100644
--- a/dlls/gdi/enhmfdrv/init.c
+++ b/dlls/gdi/enhmfdrv/init.c
@@ -80,6 +80,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs =
     NULL,                            /* pGetPixel */
     NULL,                            /* pGetPixelFormat */
     NULL,                            /* pGetSystemPaletteEntries */
+    NULL,                            /* pGetTextExtentExPoint */
     NULL,                            /* pGetTextExtentPoint */
     NULL,                            /* pGetTextMetrics */
     EMFDRV_IntersectClipRect,        /* pIntersectClipRect */
diff --git a/dlls/gdi/font.c b/dlls/gdi/font.c
index 33a03f6..37a0d34 100644
--- a/dlls/gdi/font.c
+++ b/dlls/gdi/font.c
@@ -1053,27 +1053,7 @@ BOOL WINAPI GetTextExtentPoint32W(
     INT count,   /* [in]  Number of characters in string */
     LPSIZE size) /* [out] Address of structure for string size */
 {
-    BOOL ret = FALSE;
-    DC * dc = DC_GetDCPtr( hdc );
-    if (!dc) return FALSE;
-
-    if(dc->gdiFont)
-        ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
-    else if(dc->funcs->pGetTextExtentPoint)
-        ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
-
-    if (ret)
-    {
-	size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
-	size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
-        size->cx += count * dc->charExtra + dc->breakRem;
-    }
-
-    GDI_ReleaseObj( hdc );
-
-    TRACE("(%p %s %d %p): returning %ld x %ld\n",
-          hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
-    return ret;
+    return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
 }
 
 /***********************************************************************
@@ -1205,36 +1185,36 @@ BOOL WINAPI GetTextExtentExPointW( HDC h
 				   INT maxExt, LPINT lpnFit,
 				   LPINT alpDx, LPSIZE size )
 {
-    int index, nFit, extent;
-    SIZE tSize;
+    INT nFit;
     BOOL ret = FALSE;
+    DC *dc;
+
+    TRACE("(%p, %s, %d)\n", hdc, debugstr_wn(str, count), maxExt);
+
+    dc = DC_GetDCPtr(hdc);
+    if (! dc)
+        return FALSE;
+
+    if (dc->gdiFont)
+        ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
+                                          maxExt, &nFit, alpDx, size);
+    else if (dc->funcs->pGetTextExtentPoint)
+        ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
+                                               maxExt, &nFit, alpDx, size);
 
-    TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
+    if (lpnFit)
+        *lpnFit = nFit;
 
-    size->cx = size->cy = nFit = extent = 0;
-    for(index = 0; index < count; index++)
+    if (ret)
     {
- 	if(!GetTextExtentPoint32W( hdc, str, index + 1, &tSize )) goto done;
-        /* GetTextExtentPoint includes intercharacter spacing. */
-        /* FIXME - justification needs doing yet.  Remember that the base
-         * data will not be in logical coordinates.
-         */
-	extent = tSize.cx;
-	if( !lpnFit || extent <= maxExt )
-        /* It is allowed to be equal. */
-        {
-	    nFit++;
-	    if( alpDx ) alpDx[index] = extent;
-        }
-	if( tSize.cy > size->cy ) size->cy = tSize.cy;
+        size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
+        size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
+        size->cx += count * dc->charExtra + dc->breakRem;
     }
-    size->cx = extent;
-    if(lpnFit) *lpnFit = nFit;
-    ret = TRUE;
 
-    TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
+    GDI_ReleaseObj( hdc );
 
-done:
+    TRACE("returning %d %ld x %ld\n", nFit, size->cx, size->cy);
     return ret;
 }
 
diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c
index 9f52e60..8b717b1 100644
--- a/dlls/gdi/freetype.c
+++ b/dlls/gdi/freetype.c
@@ -3849,36 +3849,57 @@ BOOL WineEngGetCharABCWidthsI(GdiFont fo
 }
 
 /*************************************************************
- * WineEngGetTextExtentPoint
+ * WineEngGetTextExtentExPoint
  *
  */
-BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
-			       LPSIZE size)
+BOOL WineEngGetTextExtentExPoint(GdiFont font, LPCWSTR wstr, INT count,
+                                 INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size)
 {
-    INT idx;
+    INT i, nfit = 0, ext;
     GLYPHMETRICS gm;
     TEXTMETRICW tm;
     FT_UInt glyph_index;
     GdiFont linked_font;
 
-    TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count,
-	  size);
+    TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count),
+          count, max_ext, size);
 
     size->cx = 0;
     WineEngGetTextMetrics(font, &tm);
     size->cy = tm.tmHeight;
 
-    for(idx = 0; idx < count; idx++) {
-        get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index);
+    for (i = 0; i < count; ++i)
+    {
+        get_glyph_index_linked(font, wstr[i], &linked_font, &glyph_index);
         WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
                                &gm, 0, NULL, NULL);
-	size->cx += linked_font->gm[glyph_index].adv;
+        ext = size->cx += linked_font->gm[glyph_index].adv;
+        if (! pnfit || ext <= max_ext)
+        {
+            ++nfit;
+            if (dxs)
+                dxs[i] = ext;
+        }
     }
-    TRACE("return %ld,%ld\n", size->cx, size->cy);
+
+    if (pnfit)
+        *pnfit = nfit;
+
+    TRACE("return %ld, %ld, %d\n", size->cx, size->cy, nfit);
     return TRUE;
 }
 
 /*************************************************************
+ * WineEngGetTextExtentPoint
+ *
+ */
+BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
+			       LPSIZE size)
+{
+    return WineEngGetTextExtentExPoint(font, wstr, count, 0, NULL, NULL, size);
+}
+
+/*************************************************************
  * WineEngGetTextExtentPointI
  *
  */
@@ -4149,6 +4170,13 @@ BOOL WineEngGetCharABCWidthsI(GdiFont fo
     return FALSE;
 }
 
+BOOL WineEngGetTextExtentExPoint(GdiFont font, LPCWSTR wstr, INT count,
+                                 INT max_ext, LPINT nfit, LPINT dx, LPSIZE size)
+{
+    ERR("called but we don't have FreeType\n");
+    return FALSE;
+}
+
 BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
 			       LPSIZE size)
 {
diff --git a/dlls/gdi/gdi_private.h b/dlls/gdi/gdi_private.h
index 610babb..74a967e 100644
--- a/dlls/gdi/gdi_private.h
+++ b/dlls/gdi/gdi_private.h
@@ -107,6 +107,7 @@ typedef struct tagDC_FUNCS
     COLORREF (*pGetPixel)(PHYSDEV,INT,INT);
     INT      (*pGetPixelFormat)(PHYSDEV);
     UINT     (*pGetSystemPaletteEntries)(PHYSDEV,UINT,UINT,LPPALETTEENTRY);
+    BOOL     (*pGetTextExtentExPoint)(PHYSDEV,LPCWSTR,INT,INT,LPINT,LPINT,LPSIZE);
     BOOL     (*pGetTextExtentPoint)(PHYSDEV,LPCWSTR,INT,LPSIZE);
     BOOL     (*pGetTextMetrics)(PHYSDEV,TEXTMETRICW*);
     INT      (*pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT);
@@ -380,6 +381,7 @@ extern BOOL WineEngGetLinkedHFont(DC *dc
 extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
 extern UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags);
 extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE);
+extern BOOL WineEngGetTextExtentExPoint(GdiFont, LPCWSTR, INT, INT, LPINT, LPINT, LPSIZE);
 extern BOOL WineEngGetTextExtentPointI(GdiFont, const WORD *, INT, LPSIZE);
 extern INT  WineEngGetTextFace(GdiFont, INT, LPWSTR);
 extern BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW);
diff --git a/dlls/gdi/mfdrv/init.c b/dlls/gdi/mfdrv/init.c
index bf964a7..c988119 100644
--- a/dlls/gdi/mfdrv/init.c
+++ b/dlls/gdi/mfdrv/init.c
@@ -80,6 +80,7 @@ static const DC_FUNCTIONS MFDRV_Funcs =
     NULL,                            /* pGetPixel */
     NULL,                            /* pGetPixelFormat */
     NULL,                            /* pGetSystemPaletteEntries */
+    NULL,                            /* pGetTextExtentExPoint */
     NULL,                            /* pGetTextExtentPoint */
     NULL,                            /* pGetTextMetrics */
     MFDRV_IntersectClipRect,         /* pIntersectClipRect */
-- 
1.4.0




More information about the wine-patches mailing list