fonts: GetOutlineTextMetrics with a snall buffer

Huw D M Davies h.davies1 at physics.ox.ac.uk
Tue Nov 11 09:23:38 CST 2003


        Huw Davies <huw at codeweavers.com>
	If the buffer passed to GetOutlineTextMetrics isn't big enough then
	Windows fills it upto the supplied size rather than returning an error.
        
-- 
Huw Davies
huw at codeweavers.com
Index: objects/font.c
===================================================================
RCS file: /home/wine/wine/objects/font.c,v
retrieving revision 1.108
diff -u -r1.108 font.c
--- objects/font.c	11 Nov 2003 00:28:19 -0000	1.108
+++ objects/font.c	11 Nov 2003 15:21:26 -0000
@@ -324,7 +324,7 @@
 
 	    memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
 
-	    TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s => %p\n",
+	    TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
                   plf->lfHeight, plf->lfWidth,
                   plf->lfEscapement, plf->lfOrientation,
                   plf->lfPitchAndFamily,
@@ -332,7 +332,8 @@
 		  plf->lfQuality, plf->lfCharSet,
                   debugstr_w(plf->lfFaceName),
                   plf->lfWeight > 400 ? "Bold" : "",
-                  plf->lfItalic ? "Italic" : "", hFont);
+                  plf->lfItalic ? "Italic" : "",
+                  plf->lfUnderline ? "Underline" : "", hFont);
 
 	    if (plf->lfEscapement != plf->lfOrientation) {
 	      /* this should really depend on whether GM_ADVANCED is set */
@@ -1229,6 +1230,9 @@
  *		GetOutlineTextMetricsA (GDI32.@)
  * Gets metrics for TrueType fonts.
  *
+ * NOTES
+ *    If the supplied buffer isn't big enough Windows partially fills it up to
+ *    its given length and returns that length.
  *
  * RETURNS
  *    Success: Non-zero or size of required buffer
@@ -1242,14 +1246,14 @@
     char buf[512], *ptr;
     UINT ret, needed;
     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
+    OUTLINETEXTMETRICA *output = lpOTM;
     INT left, len;
 
-    if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
-        if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
-	    return 0;
+    if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
+        return 0;
+    if(ret > sizeof(buf))
 	lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
-	GetOutlineTextMetricsW(hdc, ret, lpOTMW);
-    }
+    GetOutlineTextMetricsW(hdc, ret, lpOTMW);
 
     needed = sizeof(OUTLINETEXTMETRICA);
     if(lpOTMW->otmpFamilyName)
@@ -1274,87 +1278,91 @@
 	goto end;
     }
 
-    if(needed > cbData) {
-        ret = 0;
-	goto end;
-    }
-
+    TRACE("needed = %d\n", needed);
+    if(needed > cbData)
+        /* Since the supplied buffer isn't big enough, we'll alloc one
+           that is and memcpy the first cbData bytes into the lpOTM at
+           the end. */
+        output = HeapAlloc(GetProcessHeap(), 0, needed);
+
+    ret = output->otmSize = min(needed, cbData);
+    FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
+    output->otmFiller = 0;
+    output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
+    output->otmfsSelection = lpOTMW->otmfsSelection;
+    output->otmfsType = lpOTMW->otmfsType;
+    output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
+    output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
+    output->otmItalicAngle = lpOTMW->otmItalicAngle;
+    output->otmEMSquare = lpOTMW->otmEMSquare;
+    output->otmAscent = lpOTMW->otmAscent;
+    output->otmDescent = lpOTMW->otmDescent;
+    output->otmLineGap = lpOTMW->otmLineGap;
+    output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
+    output->otmsXHeight = lpOTMW->otmsXHeight;
+    output->otmrcFontBox = lpOTMW->otmrcFontBox;
+    output->otmMacAscent = lpOTMW->otmMacAscent;
+    output->otmMacDescent = lpOTMW->otmMacDescent;
+    output->otmMacLineGap = lpOTMW->otmMacLineGap;
+    output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
+    output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
+    output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
+    output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
+    output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
+    output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
+    output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
+    output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
+    output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
 
-    lpOTM->otmSize = needed;
-    FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
-    lpOTM->otmFiller = 0;
-    lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
-    lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
-    lpOTM->otmfsType = lpOTMW->otmfsType;
-    lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
-    lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
-    lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
-    lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
-    lpOTM->otmAscent = lpOTMW->otmAscent;
-    lpOTM->otmDescent = lpOTMW->otmDescent;
-    lpOTM->otmLineGap = lpOTMW->otmLineGap;
-    lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
-    lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
-    lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
-    lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
-    lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
-    lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
-    lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
-    lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
-    lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
-    lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
-    lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
-    lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
-    lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
-    lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
-    lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
 
-
-    ptr = (char*)(lpOTM + 1);
-    left = needed - sizeof(*lpOTM);
+    ptr = (char*)(output + 1);
+    left = needed - sizeof(*output);
 
     if(lpOTMW->otmpFamilyName) {
-        lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
+        output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
 	len = WideCharToMultiByte(CP_ACP, 0,
 	     (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
 				  ptr, left, NULL, NULL);
 	left -= len;
 	ptr += len;
     } else
-        lpOTM->otmpFamilyName = 0;
+        output->otmpFamilyName = 0;
 
     if(lpOTMW->otmpFaceName) {
-        lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
+        output->otmpFaceName = (LPSTR)(ptr - (char*)output);
 	len = WideCharToMultiByte(CP_ACP, 0,
 	     (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
 				  ptr, left, NULL, NULL);
 	left -= len;
 	ptr += len;
     } else
-        lpOTM->otmpFaceName = 0;
+        output->otmpFaceName = 0;
 
     if(lpOTMW->otmpStyleName) {
-        lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
+        output->otmpStyleName = (LPSTR)(ptr - (char*)output);
 	len = WideCharToMultiByte(CP_ACP, 0,
 	     (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
 				  ptr, left, NULL, NULL);
 	left -= len;
 	ptr += len;
     } else
-        lpOTM->otmpStyleName = 0;
+        output->otmpStyleName = 0;
 
     if(lpOTMW->otmpFullName) {
-        lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
+        output->otmpFullName = (LPSTR)(ptr - (char*)output);
 	len = WideCharToMultiByte(CP_ACP, 0,
 	     (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
 				  ptr, left, NULL, NULL);
 	left -= len;
     } else
-        lpOTM->otmpFullName = 0;
+        output->otmpFullName = 0;
 
     assert(left == 0);
 
-    ret = needed;
+    if(output != lpOTM) {
+        memcpy(lpOTM, output, cbData);
+        HeapFree(GetProcessHeap(), 0, output);
+    }
 
 end:
     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
@@ -1373,14 +1381,20 @@
     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
 {
     DC *dc = DC_GetDCPtr( hdc );
+    OUTLINETEXTMETRICW *output = lpOTM;
     UINT ret;
 
     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
     if(!dc) return 0;
 
     if(dc->gdiFont) {
-        ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
-	if(ret && ret <= cbData) {
+        ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
+        if(lpOTM && ret) {
+            if(ret > cbData) {
+                output = HeapAlloc(GetProcessHeap(), 0, ret);
+                WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
+            }
+
 #define WDPTOLP(x) ((x<0)?					\
 		(-abs(INTERNAL_XDSTOWS(dc, (x)))):		\
 		(abs(INTERNAL_XDSTOWS(dc, (x)))))
@@ -1388,40 +1402,45 @@
 		(-abs(INTERNAL_YDSTOWS(dc, (y)))):		\
 		(abs(INTERNAL_YDSTOWS(dc, (y)))))
 
-	    lpOTM->otmTextMetrics.tmHeight           = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
-	    lpOTM->otmTextMetrics.tmAscent           = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
-	    lpOTM->otmTextMetrics.tmDescent          = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
-	    lpOTM->otmTextMetrics.tmInternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
-	    lpOTM->otmTextMetrics.tmExternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
-	    lpOTM->otmTextMetrics.tmAveCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
-	    lpOTM->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
-	    lpOTM->otmTextMetrics.tmOverhang         = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
-	    lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
-	    lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
-	    lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
-	    lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
-	    lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
-	    lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
-	    lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
-	    lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
-	    lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
-	    lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
-	    lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
-	    lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
-	    lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
-	    lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
-	    lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
-	    lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
-	    lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
-	    lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
-	    lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
-	    lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
-	    lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
-	    lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
-	    lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
-	    lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
+	    output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
+	    output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
+	    output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
+	    output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
+	    output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
+	    output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
+	    output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
+	    output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
+	    output->otmAscent = HDPTOLP(output->otmAscent);
+	    output->otmDescent = HDPTOLP(output->otmDescent);
+	    output->otmLineGap = HDPTOLP(output->otmLineGap);
+	    output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
+	    output->otmsXHeight = HDPTOLP(output->otmsXHeight);
+	    output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
+	    output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
+	    output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
+	    output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
+	    output->otmMacAscent = HDPTOLP(output->otmMacAscent);
+	    output->otmMacDescent = HDPTOLP(output->otmMacDescent);
+	    output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
+	    output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
+	    output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
+	    output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
+	    output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
+	    output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
+	    output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
+	    output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
+	    output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
+	    output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
+	    output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
+	    output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
+	    output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
 #undef WDPTOLP
 #undef HDPTOLP
+            if(output != lpOTM) {
+                memcpy(lpOTM, output, cbData);
+                HeapFree(GetProcessHeap(), 0, output);
+                ret = cbData;
+            }
 	}
     }
 



More information about the wine-patches mailing list