[Gdiplus 2/2] Implement support for StringAlignment

Adam Petaccia adam at tpetaccia.com
Wed Jul 2 14:02:15 CDT 2008


This fixes bug 14244.
---
 dlls/gdiplus/graphics.c |   60 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index cd2b8cc..0f5c746 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -1563,11 +1563,15 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
     GpPointF pt[2], rectcpy[4];
     POINT corners[4];
     WCHAR* stringdup;
+    WCHAR* stringdup_current_line = NULL;
     REAL angle, ang_cos, ang_sin, rel_width, rel_height;
     INT sum = 0, height = 0, fit, fitcpy, save_state, i, j, lret, nwidth,
         nheight;
     SIZE size;
     RECT drawcoord;
+    StringAlignment alignment, line_alignment;
+    GpStringFormat* format_cpy = NULL;
+    RectF bounds;
 
     if(!graphics || !string || !font || !brush || !rect)
         return InvalidParameter;
@@ -1579,10 +1583,8 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
 
     if(format)
     {
-        if (format->align)
-            FIXME("Ignoring horizontal alignment: %d\n", format->align);
-        if (format->vertalign)
-            FIXME("Ignoring vertical alignment: %d\n", format->vertalign);
+        TRACE("Horizontal alignment: %d\n", format->align);
+        TRACE("Vertical alignment: %d\n", format->vertalign);
         /* FIXME: the following StringFormatsFlags are unimplemented:
          * DirectionRightToLeft, DirectionVertical, NoFitBlackBox,
          * DisplayFormatControl, NoFontFallback, MeasureTrailingSpaces,
@@ -1595,10 +1597,17 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
             FIXME("Ignoring some format flags: attr %x\n", format->attr);
     }
 
+    GdipCloneStringFormat(format, &format_cpy);
+    if (!format_cpy) return OutOfMemory;
+
     if(length == -1) length = lstrlenW(string);
 
     stringdup = GdipAlloc(length * sizeof(WCHAR));
-    if(!stringdup) return OutOfMemory;
+    if(!stringdup)
+    {
+        GdipFree(format_cpy);
+        return OutOfMemory;
+    }
 
     save_state = SaveDC(graphics->hdc);
     SetBkMode(graphics->hdc, TRANSPARENT);
@@ -1661,10 +1670,23 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
     stringdup[j] = 0;
     length = j;
 
+    ZeroMemory (&bounds, sizeof(RectF));
+    GdipGetStringFormatAlign(format_cpy, &alignment);
+    GdipGetStringFormatLineAlign(format_cpy, &line_alignment);
+
     while(sum < length){
         drawcoord.left = corners[0].x + roundr(ang_sin * (REAL) height);
         drawcoord.top = corners[0].y + roundr(ang_cos * (REAL) height);
 
+        /* If there's some sort of vertical alignment, calculate and apply */
+        if (line_alignment)
+        {
+            GdipMeasureString(graphics, stringdup, -1, font, rect, format, &bounds, NULL, NULL);
+            if (line_alignment == StringAlignmentFar)
+                drawcoord.top += (rect->Height - bounds.Height);
+            else if (line_alignment == StringAlignmentCenter)
+                drawcoord.top += (rect->Height - bounds.Height)/2;
+        }
         GetTextExtentExPointW(graphics->hdc, stringdup + sum, length - sum,
                               nwidth, &fit, NULL, &size);
         fitcpy = fit;
@@ -1699,6 +1721,31 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
                     }
                 }
         }
+
+        /* If alignment is something other than normal, calculate how
+         * much we'll have to adjust for this horizontal line of text */
+        if (alignment)
+        {
+            stringdup_current_line = GdipAlloc ((fit+ (lret < fitcpy ? 1 : 0)) *
+                    sizeof(WCHAR));
+            if (!stringdup_current_line)
+            {
+                GdipFree(format_cpy);
+                GdipFree(stringdup);
+                return OutOfMemory;
+            }
+            lstrcpynW(stringdup_current_line, stringdup + sum,
+                    (fit+ (lret < fitcpy ? 1: 0) * sizeof(WCHAR)));
+
+            GdipMeasureString(graphics, stringdup_current_line, -1, font, rect,
+                    format, &bounds, NULL, NULL);
+
+            if (alignment == StringAlignmentCenter)
+                drawcoord.left += (rect->Width - bounds.Width)/2;
+            else if (alignment == StringAlignmentFar)
+                drawcoord.left += (rect->Width - bounds.Width);
+        }
+
         DrawTextW(graphics->hdc, stringdup + sum, min(length - sum, fit),
                   &drawcoord, DT_NOCLIP | DT_EXPANDTABS);
 
@@ -1711,9 +1758,12 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
         /* Stop if this was a linewrap (but not if it was a linebreak). */
         if((lret == fitcpy) && format && (format->attr & StringFormatFlagsNoWrap))
             break;
+        if (stringdup_current_line)
+            GdipFree(stringdup_current_line);
     }
 
     GdipFree(stringdup);
+    GdipFree(format_cpy);
     DeleteObject(rgn);
     DeleteObject(gdifont);
 
-- 
1.5.4.3




More information about the wine-patches mailing list