gdi32: fix for GetCharacterPlacement[A/W] to handle NULL lpResults (with test)

Nikolay Sivov bunglehead at gmail.com
Mon Oct 6 17:57:56 CDT 2008


Changelog:
    - fixes GetCharacterPlacement to handle NULL lpResults (bug 13094)
    - fix some indentations

>From 3a538ef94155e07e4dc6c026fa629cb2ac2cfeec Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Tue, 7 Oct 2008 02:52:15 +0400
Subject: Fix for GetCharacterPlacement[A/W] for NULL lpResults pointer

---
 dlls/gdi32/font.c       |  135 ++++++++++++++++++++++++++---------------------
 dlls/gdi32/tests/font.c |   21 +++++++
 2 files changed, 95 insertions(+), 61 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 21d2ebb..189e009 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -2718,27 +2718,33 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
     WCHAR *lpStringW;
     INT uCountW;
     GCP_RESULTSW resultsW;
+    GCP_RESULTSW *presultsW = NULL;
     DWORD ret;
     UINT font_cp;
 
-    TRACE("%s, %d, %d, 0x%08x\n",
-          debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
+    TRACE("%s, %d, %d, %p, 0x%08x\n",
+          debugstr_an(lpString, uCount), uCount, nMaxExtent, lpResults, dwFlags);
 
-    /* both structs are equal in size */
-    memcpy(&resultsW, lpResults, sizeof(resultsW));
+    if(lpResults){
+        /* both structs are equal in size */
+        memcpy(&resultsW, lpResults, sizeof(resultsW));
+        presultsW = &resultsW;
+    }
 
     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
-    if(lpResults->lpOutString)
+    if(lpResults && lpResults->lpOutString)
         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
 
-    ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
+    ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, presultsW, dwFlags);
 
-    lpResults->nGlyphs = resultsW.nGlyphs;
-    lpResults->nMaxFit = resultsW.nMaxFit;
+    if(lpResults){
+        lpResults->nGlyphs = resultsW.nGlyphs;
+        lpResults->nMaxFit = resultsW.nMaxFit;
 
-    if(lpResults->lpOutString) {
-        WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
-                            lpResults->lpOutString, uCount, NULL, NULL );
+        if(lpResults->lpOutString) {
+            WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
+                                lpResults->lpOutString, uCount, NULL, NULL );
+        }
     }
 
     HeapFree(GetProcessHeap(), 0, lpStringW);
@@ -2767,67 +2773,72 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
  */
 DWORD WINAPI
 GetCharacterPlacementW(
-		HDC hdc,		/* [in] Device context for which the rendering is to be done */
-		LPCWSTR lpString,	/* [in] The string for which information is to be returned */
-		INT uCount,		/* [in] Number of WORDS in string. */
-		INT nMaxExtent,		/* [in] Maximum extent the string is to take (in HDC logical units) */
+		HDC hdc,         /* [in] Device context for which the rendering is to be done */
+		LPCWSTR lpString,/* [in] The string for which information is to be returned */
+		INT uCount,      /* [in] Number of WORDS in string. */
+		INT nMaxExtent,  /* [in] Maximum extent the string is to take (in HDC logical units) */
 		GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
-		DWORD dwFlags 		/* [in] Flags specifying how to process the string */
+		DWORD dwFlags           /* [in] Flags specifying how to process the string */
 		)
 {
     DWORD ret=0;
     SIZE size;
     UINT i, nSet;
 
-    TRACE("%s, %d, %d, 0x%08x\n",
-          debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
+    TRACE("%s, %d, %d, %p, 0x%08x\n",
+          debugstr_wn(lpString, uCount), uCount, nMaxExtent, lpResults, dwFlags);
+
+    if(lpResults)
+        TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
+              "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
+               lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
+               lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
+               lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
 
-    TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
-          "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
-	    lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
-	    lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
-	    lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
+    if(dwFlags&(~GCP_REORDER))  FIXME("flags 0x%08x ignored\n", dwFlags);
 
-    if(dwFlags&(~GCP_REORDER))			FIXME("flags 0x%08x ignored\n", dwFlags);
-    if(lpResults->lpClass)	FIXME("classes not implemented\n");
+    /* with NULL lpResults return GetTextExtentPoint32 result */
+    if(!lpResults)  goto nullres;
+
+    if(lpResults->lpClass)  FIXME("classes not implemented\n");
     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
         FIXME("Caret positions for complex scripts not implemented\n");
 
-	nSet = (UINT)uCount;
-	if(nSet > lpResults->nGlyphs)
-		nSet = lpResults->nGlyphs;
+    nSet = (UINT)uCount;
+    if(nSet > lpResults->nGlyphs)
+        nSet = lpResults->nGlyphs;
 
-	/* return number of initialized fields */
-	lpResults->nGlyphs = nSet;
+    /* return number of initialized fields */
+    lpResults->nGlyphs = nSet;
 
-	if((dwFlags&GCP_REORDER)==0 )
-	{
-		/* Treat the case where no special handling was requested in a fastpath way */
+    if((dwFlags&GCP_REORDER)==0 )
+    {
+        /* Treat the case where no special handling was requested in a fastpath way */
 		/* copy will do if the GCP_REORDER flag is not set */
-		if(lpResults->lpOutString)
-                    memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
-
-		if(lpResults->lpOrder)
-		{
-			for(i = 0; i < nSet; i++)
-				lpResults->lpOrder[i] = i;
-		}
-	} else
-	{
-            BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
-                          nSet, lpResults->lpOrder );
-	}
+        if(lpResults->lpOutString)
+            memcpy(lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
 
-	/* FIXME: Will use the placement chars */
-	if (lpResults->lpDx)
-	{
-		int c;
-		for (i = 0; i < nSet; i++)
-		{
-			if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
-				lpResults->lpDx[i]= c;
-		}
-	}
+        if(lpResults->lpOrder)
+        {
+            for(i = 0; i < nSet; i++)
+                lpResults->lpOrder[i] = i;
+        }
+    } else
+    {
+        BIDI_Reorder(lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
+                     nSet, lpResults->lpOrder );
+    }
+
+    /* FIXME: Will use the placement chars */
+    if (lpResults->lpDx)
+    {
+        int c;
+        for (i = 0; i < nSet; i++)
+        {
+            if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
+                lpResults->lpDx[i]= c;
+        }
+    }
 
     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
     {
@@ -2838,9 +2849,11 @@ GetCharacterPlacementW(
             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
                 lpResults->lpCaretPos[i] = (pos += size.cx);
     }
-   
+
     if(lpResults->lpGlyphs)
-	GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
+        GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
+
+nullres:
 
     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
       ret = MAKELONG(size.cx, size.cy);
@@ -2952,9 +2965,9 @@ BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
 
 
 /***********************************************************************
- *								       *
- *           Font Resource API					       *
- *								       *
+ *                                                                     *
+ *           Font Resource API                                         *
+ *                                                                     *
  ***********************************************************************/
 
 /***********************************************************************
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index bbcdf0b..c3ebefa 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -2464,6 +2464,26 @@ static void test_orientation(void)
     DeleteDC(hdc);
 }
 
+static void test_GetCharacterPlacement(void)
+{
+    HDC hdc = GetDC(0);
+    CHAR str[] = "deadbeef";
+    WCHAR strW[] = {'d','e','a','d','b','e','e','f','\0'};
+    DWORD ret;
+    SIZE sz;
+
+    /* when lpResults == NULL return value equals to MAKELONG(sz.cx, sz.cy) */
+    ret = GetCharacterPlacementA(hdc, str, lstrlenA(str), 0, NULL, GCP_USEKERNING);
+    GetTextExtentPoint32A(hdc, str, lstrlen(str), &sz);
+    expect(MAKELONG(sz.cx, sz.cy), ret);
+
+    ret = GetCharacterPlacementW(hdc, strW, lstrlenW(strW), 0, NULL, GCP_USEKERNING);
+    GetTextExtentPoint32W(hdc, strW, lstrlenW(strW), &sz);
+    expect(MAKELONG(sz.cx, sz.cy), ret);
+
+    ReleaseDC(0, hdc);
+}
+
 START_TEST(font)
 {
     init();
@@ -2501,4 +2521,5 @@ START_TEST(font)
     test_GetTextMetrics();
     test_GdiRealizationInfo();
     test_GetTextFace();
+    test_GetCharacterPlacement();
 }
-- 
1.4.4.4






More information about the wine-patches mailing list