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