Vincent Povirk : gdiplus: Implement GdipMeasureDriverString.

Alexandre Julliard julliard at winehq.org
Tue Jun 28 17:25:19 CDT 2011


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Jun 27 13:24:39 2011 -0500

gdiplus: Implement GdipMeasureDriverString.

---

 dlls/gdiplus/graphics.c       |  108 ++++++++++++++++++++++++++++++++++++++++-
 dlls/gdiplus/tests/graphics.c |   34 ++++++------
 2 files changed, 123 insertions(+), 19 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 8c6a042..d756c0b 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -5624,8 +5624,112 @@ GpStatus WINGDIPAPI GdipMeasureDriverString(GpGraphics *graphics, GDIPCONST UINT
                                             GDIPCONST GpFont *font, GDIPCONST PointF *positions,
                                             INT flags, GDIPCONST GpMatrix *matrix, RectF *boundingBox)
 {
-    FIXME("(%p %p %d %p %p %d %p %p): stub\n", graphics, text, length, font, positions, flags, matrix, boundingBox);
-    return NotImplemented;
+    static const INT unsupported_flags = ~(DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance);
+    HFONT hfont;
+    HDC hdc;
+    REAL min_x, min_y, max_x, max_y, x, y;
+    int i;
+    TEXTMETRICW textmetric;
+    const WORD *glyph_indices;
+    WORD *dynamic_glyph_indices=NULL;
+    REAL rel_width, rel_height, ascent, descent;
+    GpPointF pt[3];
+
+    TRACE("(%p %p %d %p %p %d %p %p)\n", graphics, text, length, font, positions, flags, matrix, boundingBox);
+
+    if (!graphics || !text || !font || !positions || !boundingBox)
+        return InvalidParameter;
+
+    if (length == -1)
+        length = strlenW(text);
+
+    if (length == 0)
+    {
+        boundingBox->X = 0.0;
+        boundingBox->Y = 0.0;
+        boundingBox->Width = 0.0;
+        boundingBox->Height = 0.0;
+    }
+
+    if (flags & unsupported_flags)
+        FIXME("Ignoring flags %x\n", flags & unsupported_flags);
+
+    if (matrix)
+        FIXME("Ignoring matrix\n");
+
+    get_font_hfont(graphics, font, &hfont);
+
+    hdc = CreateCompatibleDC(0);
+    SelectObject(hdc, hfont);
+
+    GetTextMetricsW(hdc, &textmetric);
+
+    pt[0].X = 0.0;
+    pt[0].Y = 0.0;
+    pt[1].X = 1.0;
+    pt[1].Y = 0.0;
+    pt[2].X = 0.0;
+    pt[2].Y = 1.0;
+    GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 3);
+    rel_width = sqrt((pt[1].Y-pt[0].Y)*(pt[1].Y-pt[0].Y)+
+                     (pt[1].X-pt[0].X)*(pt[1].X-pt[0].X));
+    rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
+                      (pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
+
+    if (flags & DriverStringOptionsCmapLookup)
+    {
+        glyph_indices = dynamic_glyph_indices = GdipAlloc(sizeof(WORD) * length);
+        if (!glyph_indices)
+        {
+            DeleteDC(hdc);
+            DeleteObject(hfont);
+            return OutOfMemory;
+        }
+
+        GetGlyphIndicesW(hdc, text, length, dynamic_glyph_indices, 0);
+    }
+    else
+        glyph_indices = text;
+
+    min_x = max_x = x = positions[0].X;
+    min_y = max_y = y = positions[0].Y;
+
+    ascent = textmetric.tmAscent / rel_height;
+    descent = textmetric.tmDescent / rel_height;
+
+    for (i=0; i<length; i++)
+    {
+        int char_width;
+        ABC abc;
+
+        if (!(flags & DriverStringOptionsRealizedAdvance))
+        {
+            x = positions[i].X;
+            y = positions[i].Y;
+        }
+
+        GetCharABCWidthsW(hdc, glyph_indices[i], glyph_indices[i], &abc);
+        char_width = abc.abcA + abc.abcB + abc.abcB;
+
+        if (min_y > y - ascent) min_y = y - ascent;
+        if (max_y < y + descent) max_y = y + descent;
+        if (min_x > x) min_x = x;
+
+        x += char_width / rel_width;
+
+        if (max_x < x) max_x = x;
+    }
+
+    GdipFree(dynamic_glyph_indices);
+    DeleteDC(hdc);
+    DeleteObject(hfont);
+
+    boundingBox->X = min_x;
+    boundingBox->Y = min_y;
+    boundingBox->Width = max_x - min_x;
+    boundingBox->Height = max_y - min_y;
+
+    return Ok;
 }
 
 static GpStatus GDI32_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UINT16 *text, INT length,
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index 0ab570d..bbca69f 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -3048,36 +3048,36 @@ static void test_string_functions(void)
     status = GdipMeasureDriverString(NULL, teststring, 6, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(InvalidParameter, status);
+    expect(InvalidParameter, status);
 
     status = GdipMeasureDriverString(graphics, NULL, 6, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(InvalidParameter, status);
+    expect(InvalidParameter, status);
 
     status = GdipMeasureDriverString(graphics, teststring, 6, NULL, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(InvalidParameter, status);
+    expect(InvalidParameter, status);
 
     status = GdipMeasureDriverString(graphics, teststring, 6, font, NULL,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(InvalidParameter, status);
+    expect(InvalidParameter, status);
 
     status = GdipMeasureDriverString(graphics, teststring, 6, font, &position,
         0x100, identity, &rc);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     status = GdipMeasureDriverString(graphics, teststring, 6, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         NULL, &rc);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     status = GdipMeasureDriverString(graphics, teststring, 6, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, NULL);
-    todo_wine expect(InvalidParameter, status);
+    expect(InvalidParameter, status);
 
     rc.X = 0;
     rc.Y = 0;
@@ -3086,12 +3086,12 @@ static void test_string_functions(void)
     status = GdipMeasureDriverString(graphics, teststring, 6, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     expectf(0.0, rc.X);
-    todo_wine ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
-    todo_wine ok(rc.Width > 0.0, "unexpected Width %0.2f\n", rc.Width);
-    todo_wine ok(rc.Height > 0.0, "unexpected Y %0.2f\n", rc.Y);
+    ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
+    ok(rc.Width > 0.0, "unexpected Width %0.2f\n", rc.Width);
+    ok(rc.Height > 0.0, "unexpected Y %0.2f\n", rc.Y);
 
     char_width = rc.Width;
     char_height = rc.Height;
@@ -3103,11 +3103,11 @@ static void test_string_functions(void)
     status = GdipMeasureDriverString(graphics, teststring, 4, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     expectf(0.0, rc.X);
-    todo_wine ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
-    todo_wine ok(rc.Width < char_width, "got Width %0.2f, expecting less than %0.2f\n", rc.Width, char_width);
+    ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
+    ok(rc.Width < char_width, "got Width %0.2f, expecting less than %0.2f\n", rc.Width, char_width);
     expectf(char_height, rc.Height);
 
     rc.X = 0;
@@ -3117,11 +3117,11 @@ static void test_string_functions(void)
     status = GdipMeasureDriverString(graphics, teststring2, 1, font, &position,
         DriverStringOptionsCmapLookup|DriverStringOptionsRealizedAdvance,
         identity, &rc);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     expectf(rc.X, 0.0);
-    todo_wine ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
-    todo_wine ok(rc.Width > 0, "unexpected Width %0.2f\n", rc.Width);
+    ok(rc.Y < 0.0, "unexpected Y %0.2f\n", rc.Y);
+    ok(rc.Width > 0, "unexpected Width %0.2f\n", rc.Width);
     expectf(rc.Height, char_height);
 
     GdipDeleteMatrix(identity);




More information about the wine-cvs mailing list