Module: wine Branch: master Commit: f7d27e00202a765ff2f8e6529b616f36d14c32af URL: http://source.winehq.org/git/wine.git/?a=commit;h=f7d27e00202a765ff2f8e6529b...
Author: Evan Stade estade@gmail.com Date: Tue Aug 14 18:58:39 2007 -0700
gdiplus: Added GdipDrawString.
---
dlls/gdiplus/gdiplus.spec | 2 +- dlls/gdiplus/graphics.c | 136 +++++++++++++++++++++++++++++++++++++++++++++ include/gdiplusflat.h | 3 + include/gdiplusgpstubs.h | 2 + 4 files changed, 142 insertions(+), 1 deletions(-)
diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 39253a5..c2189e9 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -198,7 +198,7 @@ @ stdcall GdipDrawRectangleI(ptr ptr long long long long) @ stdcall GdipDrawRectangles(ptr ptr ptr long) @ stub GdipDrawRectanglesI -@ stub GdipDrawString +@ stdcall GdipDrawString(ptr ptr long ptr ptr ptr ptr) @ stub GdipEmfToWmfBits @ stub GdipEndContainer @ stub GdipEnumerateMetafileDestPoint 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 @@ GpStatus WINGDIPAPI GdipDrawRectangles(GpGraphics *graphics, GpPen *pen, 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; diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index ba2a3ca..5883f09 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -76,6 +76,9 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics*,GpPen*,GpPath*); GpStatus WINGDIPAPI GdipDrawPie(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics*,GpPen*,INT,INT,INT,INT); GpStatus WINGDIPAPI GdipDrawRectangles(GpGraphics*,GpPen*,GpRectF*,INT); +GpStatus WINGDIPAPI GdipDrawString(GpGraphics*,GDIPCONST WCHAR*,INT, + GDIPCONST GpFont*,GDIPCONST RectF*, GDIPCONST GpStringFormat*, + GDIPCONST GpBrush*); GpStatus WINGDIPAPI GdipFillPath(GpGraphics*,GpBrush*,GpPath*); GpStatus WINGDIPAPI GdipFillPie(GpGraphics*,GpBrush*,REAL,REAL,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipFillPolygonI(GpGraphics*,GpBrush*,GDIPCONST GpPoint*,INT, diff --git a/include/gdiplusgpstubs.h b/include/gdiplusgpstubs.h index d0fc8c4..7b08538 100644 --- a/include/gdiplusgpstubs.h +++ b/include/gdiplusgpstubs.h @@ -37,6 +37,7 @@ class GpPathGradient : public GpBrush {}; class GpLineGradient : public GpBrush {}; class GpTexture : public GpBrush {}; class GpFont {}; +class GpStringFormat {};
#else /* end of c++ declarations */
@@ -56,6 +57,7 @@ typedef struct GpPathGradient GpPathGradient; typedef struct GpLineGradient GpLineGradient; typedef struct GpTexture GpTexture; typedef struct GpFont GpFont; +typedef struct GpStringFormat GpStringFormat;
#endif /* end of c declarations */