Evan Stade : gdiplus: Added GdipDrawString.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Aug 15 04:34:12 CDT 2007


Module: wine
Branch: master
Commit: f7d27e00202a765ff2f8e6529b616f36d14c32af
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f7d27e00202a765ff2f8e6529b616f36d14c32af

Author: Evan Stade <estade at 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 */
 




More information about the wine-cvs mailing list