[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