gdiplus: Added GdipDrawString.
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 68ceb4b..3626217 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -23,6 +23,7 @@
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
+#include "wine/unicode.h"
#define COBJMACROS
#include "objbase.h"
@@ -1270,6 +1271,141 @@
return Ok;
}
+GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string,
+ INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect,
+ GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush)
+{
+ HRGN rgn;
+ HFONT gdifont;
+ LOGFONTW lfw;
+ TEXTMETRICW textmet;
+ GpPointF pt[2], rectcpy[4];
+ POINT corners[4];
+ WCHAR* stringdup;
+ REAL angle, ang_cos, ang_sin, rel_width, rel_height;
+ INT sum = 0, height = 0, fit, fitcpy, save_state, i, j, lret, nwidth;
+ SIZE size;
+
+ if(!graphics || !string || !font || !brush || !rect)
+ return InvalidParameter;
+
+ if(format || (brush->bt != BrushTypeSolidColor)){
+ FIXME("not implemented for given parameters\n");
+ return NotImplemented;
+ }
+
+ stringdup = GdipAlloc(length * sizeof(WCHAR));
+ if(!stringdup) return OutOfMemory;
+
+ save_state = SaveDC(graphics->hdc);
+ SetBkMode(graphics->hdc, TRANSPARENT);
+ SetTextColor(graphics->hdc, brush->lb.lbColor);
+
+ rectcpy[3].X = rectcpy[0].X = rect->X;
+ rectcpy[1].Y = rectcpy[0].Y = rect->Y;
+ rectcpy[2].X = rectcpy[1].X = rect->X + rect->Width;
+ rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
+ transform_and_round_points(graphics, corners, rectcpy, 4);
+ rel_width = sqrt((corners[1].x - corners[0].x) * (corners[1].x - corners[0].x) +
+ (corners[1].y - corners[0].y) * (corners[1].y - corners[0].y))
+ / rect->Width;
+ nwidth = roundr(rel_width * rect->Width);
+ rel_height = sqrt((corners[2].x - corners[1].x) * (corners[2].x - corners[1].x) +
+ (corners[2].y - corners[1].y) * (corners[2].y - corners[1].y))
+ / rect->Height;
+
+ rgn = CreatePolygonRgn(corners, 4, ALTERNATE);
+ SelectClipRgn(graphics->hdc, rgn);
+
+ /* Use gdi to find the font, then perform transformations on it (height,
+ * width, angle). */
+ SelectObject(graphics->hdc, CreateFontIndirectW(&font->lfw));
+ GetTextMetricsW(graphics->hdc, &textmet);
+ memcpy(&lfw, &font->lfw, sizeof(LOGFONTW));
+
+ lfw.lfHeight = roundr(((REAL)lfw.lfHeight) * rel_height);
+ lfw.lfWidth = roundr(textmet.tmAveCharWidth * rel_width);
+
+ pt[0].X = 0.0;
+ pt[0].Y = 0.0;
+ pt[1].X = 1.0;
+ pt[1].Y = 0.0;
+ GdipTransformMatrixPoints(graphics->worldtrans, pt, 2);
+ angle = gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X));
+ ang_cos = cos(angle);
+ ang_sin = sin(angle);
+ lfw.lfEscapement = lfw.lfOrientation = -roundr((angle / M_PI) * 1800.0);
+
+ gdifont = CreateFontIndirectW(&lfw);
+ DeleteObject(SelectObject(graphics->hdc, CreateFontIndirectW(&lfw)));
+
+ for(i = 0, j = 0; i < length; i++){
+ if(!isprintW(string[i]) && (string[i] != '\n'))
+ continue;
+
+ stringdup[j] = string[i];
+ j++;
+ }
+
+ stringdup[j] = 0;
+ length = j;
+
+ while(sum < length){
+ GetTextExtentExPointW(graphics->hdc, stringdup, length, nwidth,
+ &fit, NULL, &size);
+ fitcpy = fit;
+
+ if(fit == 0){
+ TabbedTextOutW(graphics->hdc,
+ corners[0].x + roundr(ang_sin * (REAL) height),
+ corners[0].y + roundr(ang_cos * (REAL) height),
+ stringdup + sum, 1, 0, 0, 0);
+ break;
+ }
+
+ for(lret = 0; lret < fit; lret++)
+ if(*(stringdup + sum + lret) == '\n')
+ break;
+
+ /* Line break code (may look strange, but it imitates windows). */
+ if(lret < fit)
+ fit = lret; /* this is not an off-by-one error */
+ else if(*(stringdup + sum + fit) == ' ')
+ while(*(stringdup + sum + fit) == ' ')
+ fit++;
+ else
+ while(*(stringdup + sum + fit - 1) != ' '){
+ fit--;
+
+ if(*(stringdup + sum + fit) == '\t')
+ break;
+
+ if(fit == 0){
+ fit = fitcpy;
+ break;
+ }
+ }
+
+ TabbedTextOutW(graphics->hdc,
+ corners[0].x - roundr(ang_sin * (REAL) height),
+ corners[0].y + roundr(ang_cos * (REAL) height),
+ stringdup + sum, min(length - sum, fit), 0, 0, 0);
+
+ sum += fit + (lret < fitcpy ? 1 : 0);
+ height += size.cy;
+
+ if(height > roundr(rect->Height * rel_height))
+ break;
+ }
+
+ DeleteObject(rgn);
+ DeleteObject(gdifont);
+
+ RestoreDC(graphics->hdc, save_state);
+
+ return Ok;
+}
+
GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *path)
{
INT save_state;