From: Dmitry Chapyshev Date: Sun, 8 Jun 2008 09:47:47 +0000 (+0000) Subject: - Add wine test for gdiplus X-Git-Tag: ReactOS-0.3.5~213 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=077d26906914da1a390447c6534ceb2ca8d41e0d - Add wine test for gdiplus svn path=/trunk/; revision=33897 --- diff --git a/rostests/winetests/directory.rbuild b/rostests/winetests/directory.rbuild index f35fb77eb6a..99192fce6f8 100644 --- a/rostests/winetests/directory.rbuild +++ b/rostests/winetests/directory.rbuild @@ -25,6 +25,9 @@ + + + diff --git a/rostests/winetests/gdiplus/brush.c b/rostests/winetests/gdiplus/brush.c new file mode 100644 index 00000000000..70eac03ef8d --- /dev/null +++ b/rostests/winetests/gdiplus/brush.c @@ -0,0 +1,74 @@ +/* + * Unit test suite for brushes + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) + +static void test_constructor_destructor(void) +{ + GpStatus status; + GpSolidFill *brush = NULL; + + status = GdipCreateSolidFill((ARGB)0xdeadbeef, &brush); + expect(Ok, status); + ok(brush != NULL, "Expected brush to be initialized\n"); + + status = GdipDeleteBrush(NULL); + expect(InvalidParameter, status); + + status = GdipDeleteBrush((GpBrush*) brush); + expect(Ok, status); +} + +static void test_type(void) +{ + GpStatus status; + GpBrushType bt; + GpSolidFill *brush = NULL; + + GdipCreateSolidFill((ARGB)0xdeadbeef, &brush); + + status = GdipGetBrushType((GpBrush*)brush, &bt); + expect(status, Ok); + expect(bt, BrushTypeSolidColor); + + GdipDeleteBrush((GpBrush*) brush); +} + +START_TEST(brush) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor_destructor(); + test_type(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/font.c b/rostests/winetests/gdiplus/font.c new file mode 100644 index 00000000000..71e6f9a7bf2 --- /dev/null +++ b/rostests/winetests/gdiplus/font.c @@ -0,0 +1,112 @@ +/* + * Unit test suite for fonts + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) + +static WCHAR arial[] = {'A','r','i','a','l','\0'}; + +static void test_logfont(void) +{ + LOGFONTW lfw, lfw2; + GpFont *font; + GpStatus stat; + GpGraphics *graphics; + HDC hdc = GetDC(0); + + GdipCreateFromHDC(hdc, &graphics); + memset(&lfw, 0, sizeof(LOGFONTW)); + memset(&lfw2, 0xff, sizeof(LOGFONTW)); + memcpy(&lfw.lfFaceName, arial, 6 * sizeof(WCHAR)); + + stat = GdipCreateFontFromLogfontW(hdc, &lfw, &font); + expect(Ok, stat); + stat = GdipGetLogFontW(font, graphics, &lfw2); + expect(Ok, stat); + + ok(lfw2.lfHeight < 0, "Expected negative height\n"); + expect(0, lfw2.lfWidth); + expect(0, lfw2.lfEscapement); + expect(0, lfw2.lfOrientation); + ok((lfw2.lfWeight >= 100) && (lfw2.lfWeight <= 900), "Expected weight to be set\n"); + expect(0, lfw2.lfItalic); + expect(0, lfw2.lfUnderline); + expect(0, lfw2.lfStrikeOut); + expect(0, lfw2.lfCharSet); + expect(0, lfw2.lfOutPrecision); + expect(0, lfw2.lfClipPrecision); + expect(0, lfw2.lfQuality); + expect(0, lfw2.lfPitchAndFamily); + + GdipDeleteFont(font); + + memset(&lfw, 0, sizeof(LOGFONTW)); + lfw.lfHeight = 25; + lfw.lfWidth = 25; + lfw.lfEscapement = lfw.lfOrientation = 50; + lfw.lfItalic = lfw.lfUnderline = lfw.lfStrikeOut = TRUE; + + memset(&lfw2, 0xff, sizeof(LOGFONTW)); + memcpy(&lfw.lfFaceName, arial, 6 * sizeof(WCHAR)); + + stat = GdipCreateFontFromLogfontW(hdc, &lfw, &font); + expect(Ok, stat); + stat = GdipGetLogFontW(font, graphics, &lfw2); + expect(Ok, stat); + + ok(lfw2.lfHeight < 0, "Expected negative height\n"); + expect(0, lfw2.lfWidth); + expect(0, lfw2.lfEscapement); + expect(0, lfw2.lfOrientation); + ok((lfw2.lfWeight >= 100) && (lfw2.lfWeight <= 900), "Expected weight to be set\n"); + expect(TRUE, lfw2.lfItalic); + expect(TRUE, lfw2.lfUnderline); + expect(TRUE, lfw2.lfStrikeOut); + expect(0, lfw2.lfCharSet); + expect(0, lfw2.lfOutPrecision); + expect(0, lfw2.lfClipPrecision); + expect(0, lfw2.lfQuality); + expect(0, lfw2.lfPitchAndFamily); + + GdipDeleteFont(font); + + GdipDeleteGraphics(graphics); + ReleaseDC(0, hdc); +} + +START_TEST(font) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_logfont(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/gdiplus.rbuild b/rostests/winetests/gdiplus/gdiplus.rbuild new file mode 100644 index 00000000000..06a12420a88 --- /dev/null +++ b/rostests/winetests/gdiplus/gdiplus.rbuild @@ -0,0 +1,22 @@ + + . + + 0x600 + 0x501 + 0x501 + wine + gdiplus + user32 + gdi32 + kernel32 + ntdll + brush.c + font.c + graphics.c + graphicspath.c + image.c + matrix.c + pen.c + stringformat.c + testlist.c + \ No newline at end of file diff --git a/rostests/winetests/gdiplus/graphics.c b/rostests/winetests/gdiplus/graphics.c new file mode 100644 index 00000000000..168eae35523 --- /dev/null +++ b/rostests/winetests/gdiplus/graphics.c @@ -0,0 +1,476 @@ +/* + * Unit test suite for graphics objects + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "gdiplus.h" +#include "wingdi.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define TABLE_LEN (23) + +static void test_constructor_destructor(void) +{ + GpStatus stat; + GpGraphics *graphics = NULL; + HDC hdc = GetDC(0); + + stat = GdipCreateFromHDC(NULL, &graphics); + expect(OutOfMemory, stat); + stat = GdipDeleteGraphics(graphics); + expect(InvalidParameter, stat); + + stat = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, stat); + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + + stat = GdipCreateFromHWND(NULL, &graphics); + expect(Ok, stat); + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + + stat = GdipCreateFromHWNDICM(NULL, &graphics); + expect(Ok, stat); + stat = GdipDeleteGraphics(graphics); + expect(Ok, stat); + + stat = GdipDeleteGraphics(NULL); + expect(InvalidParameter, stat); + ReleaseDC(0, hdc); +} + +typedef struct node{ + GraphicsState data; + struct node * next; +} node; + +/* Linked list prepend function. */ +static void log_state(GraphicsState data, node ** log) +{ + node * new_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(node)); + + new_entry->data = data; + new_entry->next = *log; + *log = new_entry; +} + +/* Checks if there are duplicates in the list, and frees it. */ +static void check_no_duplicates(node * log) +{ + INT dups = 0; + node * temp = NULL; + node * temp2 = NULL; + node * orig = log; + + if(!log) + goto end; + + do{ + temp = log; + while((temp = temp->next)){ + if(log->data == temp->data){ + dups++; + break; + } + if(dups > 0) + break; + } + }while((log = log->next)); + + temp = orig; + do{ + temp2 = temp->next; + HeapFree(GetProcessHeap(), 0, temp); + temp = temp2; + }while(temp); + +end: + expect(0, dups); +} + +static void test_save_restore(void) +{ + GpStatus stat; + GraphicsState state_a, state_b, state_c; + InterpolationMode mode; + GpGraphics *graphics1, *graphics2; + node * state_log = NULL; + HDC hdc = GetDC(0); + state_a = state_b = state_c = 0xdeadbeef; + + /* Invalid saving. */ + GdipCreateFromHDC(hdc, &graphics1); + stat = GdipSaveGraphics(graphics1, NULL); + expect(InvalidParameter, stat); + stat = GdipSaveGraphics(NULL, &state_a); + expect(InvalidParameter, stat); + GdipDeleteGraphics(graphics1); + + log_state(state_a, &state_log); + + /* Basic save/restore. */ + GdipCreateFromHDC(hdc, &graphics1); + GdipSetInterpolationMode(graphics1, InterpolationModeBilinear); + stat = GdipSaveGraphics(graphics1, &state_a); + todo_wine + expect(Ok, stat); + GdipSetInterpolationMode(graphics1, InterpolationModeBicubic); + stat = GdipRestoreGraphics(graphics1, state_a); + todo_wine + expect(Ok, stat); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBilinear, mode); + GdipDeleteGraphics(graphics1); + + log_state(state_a, &state_log); + + /* Restoring garbage doesn't affect saves. */ + GdipCreateFromHDC(hdc, &graphics1); + GdipSetInterpolationMode(graphics1, InterpolationModeBilinear); + GdipSaveGraphics(graphics1, &state_a); + GdipSetInterpolationMode(graphics1, InterpolationModeBicubic); + GdipSaveGraphics(graphics1, &state_b); + GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor); + stat = GdipRestoreGraphics(graphics1, 0xdeadbeef); + todo_wine + expect(Ok, stat); + GdipRestoreGraphics(graphics1, state_b); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBicubic, mode); + GdipRestoreGraphics(graphics1, state_a); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBilinear, mode); + GdipDeleteGraphics(graphics1); + + log_state(state_a, &state_log); + log_state(state_b, &state_log); + + /* Restoring older state invalidates newer saves (but not older saves). */ + GdipCreateFromHDC(hdc, &graphics1); + GdipSetInterpolationMode(graphics1, InterpolationModeBilinear); + GdipSaveGraphics(graphics1, &state_a); + GdipSetInterpolationMode(graphics1, InterpolationModeBicubic); + GdipSaveGraphics(graphics1, &state_b); + GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor); + GdipSaveGraphics(graphics1, &state_c); + GdipSetInterpolationMode(graphics1, InterpolationModeHighQualityBilinear); + GdipRestoreGraphics(graphics1, state_b); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBicubic, mode); + GdipRestoreGraphics(graphics1, state_c); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBicubic, mode); + GdipRestoreGraphics(graphics1, state_a); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBilinear, mode); + GdipDeleteGraphics(graphics1); + + log_state(state_a, &state_log); + log_state(state_b, &state_log); + log_state(state_c, &state_log); + + /* Restoring older save from one graphics object does not invalidate + * newer save from other graphics object. */ + GdipCreateFromHDC(hdc, &graphics1); + GdipCreateFromHDC(hdc, &graphics2); + GdipSetInterpolationMode(graphics1, InterpolationModeBilinear); + GdipSaveGraphics(graphics1, &state_a); + GdipSetInterpolationMode(graphics2, InterpolationModeBicubic); + GdipSaveGraphics(graphics2, &state_b); + GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor); + GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor); + GdipRestoreGraphics(graphics1, state_a); + GdipGetInterpolationMode(graphics1, &mode); + todo_wine + expect(InterpolationModeBilinear, mode); + GdipRestoreGraphics(graphics2, state_b); + GdipGetInterpolationMode(graphics2, &mode); + todo_wine + expect(InterpolationModeBicubic, mode); + GdipDeleteGraphics(graphics1); + GdipDeleteGraphics(graphics2); + + /* You can't restore a state to a graphics object that didn't save it. */ + GdipCreateFromHDC(hdc, &graphics1); + GdipCreateFromHDC(hdc, &graphics2); + GdipSetInterpolationMode(graphics1, InterpolationModeBilinear); + GdipSaveGraphics(graphics1, &state_a); + GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor); + GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor); + GdipRestoreGraphics(graphics2, state_a); + GdipGetInterpolationMode(graphics2, &mode); + expect(InterpolationModeNearestNeighbor, mode); + GdipDeleteGraphics(graphics1); + GdipDeleteGraphics(graphics2); + + log_state(state_a, &state_log); + + /* The same state value should never be returned twice. */ + todo_wine + check_no_duplicates(state_log); + + ReleaseDC(0, hdc); +} + +static void test_GdipDrawArc(void) +{ + GpStatus status; + GpGraphics *graphics = NULL; + GpPen *pen = NULL; + HDC hdc = GetDC(0); + + /* make a graphics object and pen object */ + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(hdc != NULL, "Expected HDC to be initialized\n"); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(graphics != NULL, "Expected graphics to be initialized\n"); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */ + status = GdipDrawArc(NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + expect(InvalidParameter, status); + + status = GdipDrawArc(graphics, NULL, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0); + expect(InvalidParameter, status); + + status = GdipDrawArc(NULL, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0); + expect(InvalidParameter, status); + + status = GdipDrawArc(graphics, pen, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0); + expect(InvalidParameter, status); + + status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); + expect(InvalidParameter, status); + + /* successful case */ + status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0); + expect(Ok, status); + + GdipDeletePen(pen); + ReleaseDC(0, hdc); +} + +static void test_GdipDrawArcI(void) +{ + GpStatus status; + GpGraphics *graphics = NULL; + GpPen *pen = NULL; + HDC hdc = GetDC(0); + + /* make a graphics object and pen object */ + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(hdc != NULL, "Expected HDC to be initialized\n"); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(graphics != NULL, "Expected graphics to be initialized\n"); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */ + status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0); + expect(InvalidParameter, status); + + /* successful case */ + status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0); + expect(Ok, status); + + GdipDeletePen(pen); + ReleaseDC(0, hdc); +} + +static void test_GdipDrawBezierI(void) +{ + GpStatus status; + GpGraphics *graphics = NULL; + GpPen *pen = NULL; + HDC hdc = GetDC(0); + + /* make a graphics object and pen object */ + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(hdc != NULL, "Expected HDC to be initialized\n"); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(graphics != NULL, "Expected graphics to be initialized\n"); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + /* InvalidParameter cases: null graphics, null pen */ + status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0); + expect(InvalidParameter, status); + + /* successful case */ + status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0); + expect(Ok, status); + + GdipDeletePen(pen); + ReleaseDC(0, hdc); +} + +static void test_GdipDrawLineI(void) +{ + GpStatus status; + GpGraphics *graphics = NULL; + GpPen *pen = NULL; + HDC hdc = GetDC(0); + + /* make a graphics object and pen object */ + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(hdc != NULL, "Expected HDC to be initialized\n"); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(graphics != NULL, "Expected graphics to be initialized\n"); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + /* InvalidParameter cases: null graphics, null pen */ + status = GdipDrawLineI(NULL, NULL, 0, 0, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawLineI(graphics, NULL, 0, 0, 0, 0); + expect(InvalidParameter, status); + + status = GdipDrawLineI(NULL, pen, 0, 0, 0, 0); + expect(InvalidParameter, status); + + /* successful case */ + status = GdipDrawLineI(graphics, pen, 0, 0, 0, 0); + expect(Ok, status); + + GdipDeletePen(pen); + ReleaseDC(0, hdc); +} + +static void test_GdipDrawLinesI(void) +{ + GpStatus status; + GpGraphics *graphics = NULL; + GpPen *pen = NULL; + GpPoint *ptf = NULL; + HDC hdc = GetDC(0); + + /* make a graphics object and pen object */ + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(hdc != NULL, "Expected HDC to be initialized\n"); + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + ok(graphics != NULL, "Expected graphics to be initialized\n"); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + /* make some arbitrary valid points*/ + ptf = GdipAlloc(2 * sizeof(GpPointF)); + + ptf[0].X = 1; + ptf[0].Y = 1; + + ptf[1].X = 2; + ptf[1].Y = 2; + + /* InvalidParameter cases: null graphics, null pen, null points, count < 2*/ + status = GdipDrawLinesI(NULL, NULL, NULL, 0); + expect(InvalidParameter, status); + + status = GdipDrawLinesI(graphics, pen, ptf, 0); + expect(InvalidParameter, status); + + status = GdipDrawLinesI(graphics, NULL, ptf, 2); + expect(InvalidParameter, status); + + status = GdipDrawLinesI(NULL, pen, ptf, 2); + expect(InvalidParameter, status); + + /* successful case */ + status = GdipDrawLinesI(graphics, pen, ptf, 2); + expect(Ok, status); + + GdipFree(ptf); + GdipDeletePen(pen); + ReleaseDC(0, hdc); +} + +START_TEST(graphics) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor_destructor(); + test_save_restore(); + test_GdipDrawBezierI(); + test_GdipDrawArc(); + test_GdipDrawArcI(); + test_GdipDrawLineI(); + test_GdipDrawLinesI(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/graphicspath.c b/rostests/winetests/gdiplus/graphicspath.c new file mode 100644 index 00000000000..e797b444df4 --- /dev/null +++ b/rostests/winetests/gdiplus/graphicspath.c @@ -0,0 +1,598 @@ +/* + * Unit test suite for paths + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" +#include + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define expectf(expected, got) ok(fabs(expected - got) < 2.0, "Expected %.2f, got %.2f\n", expected, got) +#define POINT_TYPE_MAX_LEN (75) + +static void stringify_point_type(PathPointType type, char * name) +{ + *name = '\0'; + + switch(type & PathPointTypePathTypeMask){ + case PathPointTypeStart: + strcat(name, "PathPointTypeStart"); + break; + case PathPointTypeLine: + strcat(name, "PathPointTypeLine"); + break; + case PathPointTypeBezier: + strcat(name, "PathPointTypeBezier"); + break; + default: + strcat(name, "Unknown type"); + return; + } + + type &= ~PathPointTypePathTypeMask; + if(type & ~((PathPointTypePathMarker | PathPointTypeCloseSubpath))){ + *name = '\0'; + strcat(name, "Unknown type"); + return; + } + + if(type & PathPointTypePathMarker) + strcat(name, " | PathPointTypePathMarker"); + if(type & PathPointTypeCloseSubpath) + strcat(name, " | PathPointTypeCloseSubpath"); +} + +/* this helper structure and function modeled after gdi path.c test */ +typedef struct +{ + REAL X, Y; + BYTE type; + + /* How many extra entries before this one only on wine + * but not on native? */ + int wine_only_entries_preceding; + + /* 0 - This entry matches on wine. + * 1 - This entry corresponds to a single entry on wine that does not match the native entry. + * 2 - This entry is currently skipped on wine but present on native. */ + int todo; +} path_test_t; + +static void ok_path(GpPath* path, const path_test_t *expected, INT expected_size, BOOL todo_size) +{ + BYTE * types; + INT size, idx = 0, eidx = 0, numskip; + GpPointF * points; + char ename[POINT_TYPE_MAX_LEN], name[POINT_TYPE_MAX_LEN]; + + if(GdipGetPointCount(path, &size) != Ok){ + skip("Cannot perform path comparisons due to failure to retrieve path.\n"); + return; + } + + if(todo_size) todo_wine + ok(size == expected_size, "Path size %d does not match expected size %d\n", + size, expected_size); + else + ok(size == expected_size, "Path size %d does not match expected size %d\n", + size, expected_size); + + points = HeapAlloc(GetProcessHeap(), 0, size * sizeof(GpPointF)); + types = HeapAlloc(GetProcessHeap(), 0, size); + + if(GdipGetPathPoints(path, points, size) != Ok || GdipGetPathTypes(path, types, size) != Ok){ + skip("Cannot perform path comparisons due to failure to retrieve path.\n"); + goto end; + } + + numskip = expected_size ? expected[eidx].wine_only_entries_preceding : 0; + while (idx < size && eidx < expected_size){ + /* We allow a few pixels fudge in matching X and Y coordinates to account for imprecision in + * floating point to integer conversion */ + BOOL match = (types[idx] == expected[eidx].type) && + fabs(points[idx].X - expected[eidx].X) <= 2.0 && + fabs(points[idx].Y - expected[eidx].Y) <= 2.0; + + stringify_point_type(expected[eidx].type, ename); + stringify_point_type(types[idx], name); + + if (expected[eidx].todo || numskip) todo_wine + ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx, + ename, expected[eidx].X, expected[eidx].Y, + name, points[idx].X, points[idx].Y); + else + ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx, + ename, expected[eidx].X, expected[eidx].Y, + name, points[idx].X, points[idx].Y); + + if (match || expected[eidx].todo != 2) + idx++; + if (match || !numskip--) + numskip = expected[++eidx].wine_only_entries_preceding; + } + +end: + HeapFree(GetProcessHeap(), 0, types); + HeapFree(GetProcessHeap(), 0, points); +} + +static void test_constructor_destructor(void) +{ + GpStatus status; + GpPath* path = NULL; + + status = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, status); + ok(path != NULL, "Expected path to be initialized\n"); + + status = GdipDeletePath(NULL); + expect(InvalidParameter, status); + + status = GdipDeletePath(path); + expect(Ok, status); +} + +static path_test_t line2_path[] = { + {0.0, 50.0, PathPointTypeStart, 0, 0}, /*0*/ + {5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/ + {0.0, 40.0, PathPointTypeLine, 0, 0}, /*2*/ + {15.0, 35.0, PathPointTypeLine, 0, 0}, /*3*/ + {0.0, 30.0, PathPointTypeLine, 0, 0}, /*4*/ + {25.0, 25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*5*/ + {0.0, 20.0, PathPointTypeStart, 0, 0}, /*6*/ + {35.0, 15.0, PathPointTypeLine, 0, 0}, /*7*/ + {0.0, 10.0, PathPointTypeLine, 0, 0} /*8*/ + }; + +static void test_line2(void) +{ + GpStatus status; + GpPath* path; + int i; + GpPointF line2_points[9]; + + for(i = 0; i < 9; i ++){ + line2_points[i].X = i * 5.0 * (REAL)(i % 2); + line2_points[i].Y = 50.0 - i * 5.0; + } + + GdipCreatePath(FillModeAlternate, &path); + status = GdipAddPathLine2(path, line2_points, 3); + expect(Ok, status); + status = GdipAddPathLine2(path, &(line2_points[3]), 3); + expect(Ok, status); + status = GdipClosePathFigure(path); + expect(Ok, status); + status = GdipAddPathLine2(path, &(line2_points[6]), 3); + expect(Ok, status); + + ok_path(path, line2_path, sizeof(line2_path)/sizeof(path_test_t), FALSE); +} + +static path_test_t arc_path[] = { + {600.0, 450.0, PathPointTypeStart, 0, 0}, /*0*/ + {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*1*/ + {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*2*/ + {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*3*/ + {600.0, 450.0, PathPointTypeLine, 0, 0}, /*4*/ + {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*5*/ + {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*6*/ + {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*7*/ + {329.8, 800.0, PathPointTypeBezier, 0, 0}, /*8*/ + {309.7, 796.6, PathPointTypeBezier, 0, 0}, /*9*/ + {290.1, 789.8, PathPointTypeBezier, 0, 0}, /*10*/ + {409.9, 110.2, PathPointTypeLine, 0, 0}, /*11*/ + {544.0, 156.5, PathPointTypeBezier, 0, 0}, /*12*/ + {625.8, 346.2, PathPointTypeBezier, 0, 0}, /*13*/ + {592.7, 533.9, PathPointTypeBezier, 0, 0}, /*14*/ + {592.5, 535.3, PathPointTypeBezier, 0, 0}, /*15*/ + {592.2, 536.7, PathPointTypeBezier, 0, 0}, /*16*/ + {592.0, 538.1, PathPointTypeBezier, 0, 0}, /*17*/ + {409.9, 789.8, PathPointTypeLine, 0, 0}, /*18*/ + {544.0, 743.5, PathPointTypeBezier, 0, 0}, /*19*/ + {625.8, 553.8, PathPointTypeBezier, 0, 0}, /*20*/ + {592.7, 366.1, PathPointTypeBezier, 0, 0}, /*21*/ + {592.5, 364.7, PathPointTypeBezier, 0, 0}, /*22*/ + {592.2, 363.3, PathPointTypeBezier, 0, 0}, /*23*/ + {592.0, 361.9, PathPointTypeBezier, 0, 0}, /*24*/ + {540.4, 676.9, PathPointTypeLine, 0, 0}, /*25*/ + {629.9, 529.7, PathPointTypeBezier, 0, 0}, /*26*/ + {617.2, 308.8, PathPointTypeBezier, 0, 0}, /*27*/ + {512.1, 183.5, PathPointTypeBezier, 0, 0}, /*28*/ + {406.9, 58.2, PathPointTypeBezier, 0, 0}, /*29*/ + {249.1, 75.9, PathPointTypeBezier, 0, 0}, /*30*/ + {159.6, 223.1, PathPointTypeBezier, 0, 0}, /*31*/ + {70.1, 370.3, PathPointTypeBezier, 0, 0}, /*32*/ + {82.8, 591.2, PathPointTypeBezier, 0, 0}, /*33*/ + {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/ + {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/ + {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/ + {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/ + }; + +static void test_arc(void) +{ + GpStatus status; + GpPath* path; + + GdipCreatePath(FillModeAlternate, &path); + /* Exactly 90 degrees */ + status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0); + expect(Ok, status); + /* Over 90 degrees */ + status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0); + expect(Ok, status); + /* Negative start angle */ + status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0); + expect(Ok, status); + /* Negative sweep angle */ + status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 80.0, -100.0); + expect(Ok, status); + /* More than a full revolution */ + status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, -400.0); + expect(Ok, status); + /* 0 sweep angle */ + status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0); + expect(Ok, status); + + ok_path(path, arc_path, sizeof(arc_path)/sizeof(path_test_t), FALSE); +} + +static void test_worldbounds(void) +{ + GpStatus status; + GpPath *path; + GpPen *pen; + GpMatrix *matrix; + GpRectF bounds; + GpPointF line2_points[10]; + int i; + + for(i = 0; i < 10; i ++){ + line2_points[i].X = 200.0 + i * 50.0 * (i % 2); + line2_points[i].Y = 200.0 + i * 50.0 * !(i % 2); + } + GdipCreatePen1((ARGB)0xdeadbeef, 20.0, UnitWorld, &pen); + GdipSetPenEndCap(pen, LineCapSquareAnchor); + GdipCreateMatrix2(1.5, 0.0, 1.0, 1.2, 10.4, 10.2, &matrix); + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0); + GdipAddPathLine2(path, &(line2_points[0]), 10); + status = GdipGetPathWorldBounds(path, &bounds, NULL, NULL); + expect(Ok, status); + GdipDeletePath(path); + + expectf(200.0, bounds.X); + expectf(200.0, bounds.Y); + expectf(450.0, bounds.Width); + expectf(600.0, bounds.Height); + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0); + GdipAddPathLine2(path, &(line2_points[0]), 10); + status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL); + expect(Ok, status); + GdipDeletePath(path); + + expectf(510.4, bounds.X); + expectf(250.2, bounds.Y); + expectf(1275.0, bounds.Width); + expectf(720.0, bounds.Height); + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0); + GdipAddPathLine2(path, &(line2_points[0]), 10); + status = GdipGetPathWorldBounds(path, &bounds, NULL, pen); + expect(Ok, status); + GdipDeletePath(path); + + expectf(100.0, bounds.X); + expectf(100.0, bounds.Y); + expectf(650.0, bounds.Width); + expectf(800.0, bounds.Height); + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathLine2(path, &(line2_points[0]), 2); + status = GdipGetPathWorldBounds(path, &bounds, NULL, pen); + expect(Ok, status); + GdipDeletePath(path); + + expectf(156.0, bounds.X); + expectf(156.0, bounds.Y); + expectf(138.0, bounds.Width); + expectf(88.0, bounds.Height); + + line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X; + line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y; + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathLine2(path, &(line2_points[0]), 3); + status = GdipGetPathWorldBounds(path, &bounds, NULL, pen); + expect(Ok, status); + GdipDeletePath(path); + + expectf(100.0, bounds.X); + expectf(100.0, bounds.Y); + expectf(300.0, bounds.Width); + expectf(200.0, bounds.Height); + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 45.0, 20.0); + status = GdipGetPathWorldBounds(path, &bounds, NULL, pen); + expect(Ok, status); + GdipDeletePath(path); + + expectf(386.7, bounds.X); + expectf(553.4, bounds.Y); + expectf(266.8, bounds.Width); + expectf(289.6, bounds.Height); + + GdipCreatePath(FillModeAlternate, &path); + status = GdipGetPathWorldBounds(path, &bounds, matrix, pen); + expect(Ok, status); + GdipDeletePath(path); + + expectf(0.0, bounds.X); + expectf(0.0, bounds.Y); + expectf(0.0, bounds.Width); + expectf(0.0, bounds.Height); + + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathLine2(path, &(line2_points[0]), 2); + status = GdipGetPathWorldBounds(path, &bounds, matrix, pen); + expect(Ok, status); + GdipDeletePath(path); + + todo_wine{ + expectf(427.9, bounds.X); + expectf(167.7, bounds.Y); + expectf(239.9, bounds.Width); + expectf(164.9, bounds.Height); + } + + GdipDeleteMatrix(matrix); + GdipCreateMatrix2(0.9, -0.5, -0.5, -1.2, 10.4, 10.2, &matrix); + GdipCreatePath(FillModeAlternate, &path); + GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0); + GdipAddPathLine2(path, &(line2_points[0]), 10); + status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL); + expect(Ok, status); + GdipDeletePath(path); + + expectf(-209.6, bounds.X); + expectf(-1274.8, bounds.Y); + expectf(705.0, bounds.Width); + expectf(945.0, bounds.Height); +} + +static path_test_t pathpath_path[] = { + {600.00, 450.00, PathPointTypeStart, 0, 0}, /*0*/ + {600.00, 643.30, PathPointTypeBezier, 0, 0}, /*1*/ + {488.07, 800.00, PathPointTypeBezier, 0, 0}, /*2*/ + {350.00, 800.00, PathPointTypeBezier, 0, 0}, /*3*/ + {319.61, 797.40, PathPointTypeStart, 0, 0}, /*4*/ + {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*5*/ + {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*6*/ + {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*7*/ + {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*8*/ + {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*9*/ + {104.46, 384.21, PathPointTypeBezier, 0, 0}, /*10*/ + {409.92, 110.20, PathPointTypeLine, 0, 0}, /*11*/ + {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*12*/ + {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*13*/ + {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*14*/ + {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*15*/ + {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*16*/ + {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*17*/ + {319.61, 797.40, PathPointTypeLine, 0, 0}, /*18*/ + {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*19*/ + {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*20*/ + {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*21*/ + {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*22*/ + {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*23*/ + {104.46, 384.21, PathPointTypeBezier, 0, 0} /*24*/ + }; + +static void test_pathpath(void) +{ + GpStatus status; + GpPath* path1, *path2; + + GdipCreatePath(FillModeAlternate, &path2); + GdipAddPathArc(path2, 100.0, 100.0, 500.0, 700.0, 95.0, 100.0); + + GdipCreatePath(FillModeAlternate, &path1); + GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0); + status = GdipAddPathPath(path1, path2, FALSE); + expect(Ok, status); + GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0); + status = GdipAddPathPath(path1, path2, TRUE); + expect(Ok, status); + + ok_path(path1, pathpath_path, sizeof(pathpath_path)/sizeof(path_test_t), FALSE); + + GdipDeletePath(path1); + GdipDeletePath(path2); +} + +static path_test_t ellipse_path[] = { + {30.00, 125.25, PathPointTypeStart, 0, 0}, /*0*/ + {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/ + {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/ + {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/ + {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/ + {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/ + {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/ + {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/ + {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/ + {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/ + {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/ + {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/ + {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/ + {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/ + {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/ + {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/ + {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/ + {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/ + {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/ + {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/ + {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/ + {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/ + {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/ + {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/ + {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/ + {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/ + {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/ + {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/ + {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/ + {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/ + {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/ + {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/ + {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/ + {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/ + {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/ + {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/ + {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/ + {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/ + {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/ + {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/ + {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/ + }; + +static void test_ellipse(void) +{ + GpStatus status; + GpPath *path; + GpPointF points[2]; + + points[0].X = 7.0; + points[0].Y = 11.0; + points[1].X = 13.0; + points[1].Y = 17.0; + + GdipCreatePath(FillModeAlternate, &path); + status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5); + expect(Ok, status); + GdipAddPathLine2(path, points, 2); + status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0); + expect(Ok, status); + GdipClosePathFigure(path); + status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0); + expect(Ok, status); + + ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE); + + GdipDeletePath(path); +} + +static path_test_t linei_path[] = { + {5.00, 5.00, PathPointTypeStart, 0, 0}, /*0*/ + {6.00, 8.00, PathPointTypeLine, 0, 0}, /*1*/ + {409.92, 110.20, PathPointTypeLine, 0, 0}, /*2*/ + {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*3*/ + {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*4*/ + {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*5*/ + {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*6*/ + {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*7*/ + {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*8*/ + {15.00, 15.00, PathPointTypeLine, 0, 0}, /*9*/ + {26.00, 28.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*10*/ + {35.00, 35.00, PathPointTypeStart, 0, 0}, /*11*/ + {36.00, 38.00, PathPointTypeLine, 0, 0} /*12*/ + }; + +static void test_linei(void) +{ + GpStatus status; + GpPath *path; + GpPointF points[2]; + + points[0].X = 7.0; + points[0].Y = 11.0; + points[1].X = 13.0; + points[1].Y = 17.0; + + GdipCreatePath(FillModeAlternate, &path); + status = GdipAddPathLineI(path, 5.0, 5.0, 6.0, 8.0); + expect(Ok, status); + GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0); + status = GdipAddPathLineI(path, 15.0, 15.0, 26.0, 28.0); + expect(Ok, status); + GdipClosePathFigure(path); + status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0); + expect(Ok, status); + + ok_path(path, linei_path, sizeof(linei_path)/sizeof(path_test_t), FALSE); + + GdipDeletePath(path); +} + +static path_test_t rect_path[] = { + {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/ + {105.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/ + {105.0, 55.0, PathPointTypeLine, 0, 0}, /*2*/ + {5.0, 55.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*3*/ + + {100.0, 50.0, PathPointTypeStart, 0, 0}, /*4*/ + {220.0, 50.0, PathPointTypeLine, 0, 0}, /*5*/ + {220.0, 80.0, PathPointTypeLine, 0, 0}, /*6*/ + {100.0, 80.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*7*/ + }; + +static void test_rect(void) +{ + GpStatus status; + GpPath *path; + + GdipCreatePath(FillModeAlternate, &path); + status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0); + expect(Ok, status); + status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0); + expect(Ok, status); + + ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE); + + GdipDeletePath(path); +} + +START_TEST(graphicspath) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor_destructor(); + test_line2(); + test_arc(); + test_worldbounds(); + test_pathpath(); + test_ellipse(); + test_linei(); + test_rect(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/image.c b/rostests/winetests/gdiplus/image.c new file mode 100644 index 00000000000..a3e76762f06 --- /dev/null +++ b/rostests/winetests/gdiplus/image.c @@ -0,0 +1,477 @@ +/* + * Unit test suite for images + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" +#include +#include "wingdi.h" + +#define expect(expected, got) ok(((UINT)got) == ((UINT)expected), "Expected %.8x, got %.8x\n", (UINT)expected, (UINT)got) + +static void test_Scan0(void) +{ + GpBitmap *bm; + GpStatus stat; + BYTE buff[360]; + + bm = NULL; + stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + ok(NULL != bm, "Expected bitmap to be initialized\n"); + if (stat == Ok) + GdipDisposeImage((GpImage*)bm); + + bm = (GpBitmap*)0xdeadbeef; + stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm); + expect(InvalidParameter, stat); + + expect(NULL, bm); + + bm = (GpBitmap*)0xdeadbeef; + stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm); + expect(InvalidParameter, stat); + + expect(NULL, bm); + + bm = (GpBitmap*)0xdeadbeef; + stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm); + expect(InvalidParameter, stat); + + expect(NULL, bm); + + bm = NULL; + stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm); + expect(Ok, stat); + ok(NULL != bm, "Expected bitmap to be initialized\n"); + if (stat == Ok) + GdipDisposeImage((GpImage*)bm); + + bm = (GpBitmap*) 0xdeadbeef; + stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm); + expect(InvalidParameter, stat); + expect(NULL, bm); + + bm = (GpBitmap*)0xdeadbeef; + stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm); + expect(InvalidParameter, stat); + expect(0xdeadbeef, bm); +} + +static void test_GetImageDimension(void) +{ + GpBitmap *bm; + GpStatus stat; + const REAL WIDTH = 10.0, HEIGHT = 20.0; + REAL w,h; + + bm = (GpBitmap*)0xdeadbeef; + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm); + expect(Ok,stat); + ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n"); + ok(NULL != bm, "Expected bitmap to not be NULL\n"); + + stat = GdipGetImageDimension(NULL,&w,&h); + expect(InvalidParameter, stat); + + stat = GdipGetImageDimension((GpImage*)bm,NULL,&h); + expect(InvalidParameter, stat); + + stat = GdipGetImageDimension((GpImage*)bm,&w,NULL); + expect(InvalidParameter, stat); + + w = -1; + h = -1; + stat = GdipGetImageDimension((GpImage*)bm,&w,&h); + expect(Ok, stat); + ok(fabs(WIDTH - w) < 0.0001, "Width wrong\n"); + ok(fabs(HEIGHT - h) < 0.0001, "Height wrong\n"); + GdipDisposeImage((GpImage*)bm); +} + +static void test_LoadingImages(void) +{ + GpStatus stat; + + stat = GdipCreateBitmapFromFile(0, 0); + expect(InvalidParameter, stat); + + stat = GdipCreateBitmapFromFile(0, (GpBitmap**)0xdeadbeef); + expect(InvalidParameter, stat); + + stat = GdipLoadImageFromFile(0, 0); + expect(InvalidParameter, stat); + + stat = GdipLoadImageFromFile(0, (GpImage**)0xdeadbeef); + expect(InvalidParameter, stat); + + stat = GdipLoadImageFromFileICM(0, 0); + expect(InvalidParameter, stat); + + stat = GdipLoadImageFromFileICM(0, (GpImage**)0xdeadbeef); + expect(InvalidParameter, stat); +} + +static void test_SavingImages(void) +{ + GpStatus stat; + GpBitmap *bm; + UINT n; + UINT s; + const REAL WIDTH = 10.0, HEIGHT = 20.0; + REAL w, h; + ImageCodecInfo *codecs; + static const WCHAR filename[] = { 'a','.','b','m','p',0 }; + + codecs = NULL; + + stat = GdipSaveImageToFile(0, 0, 0, 0); + expect(InvalidParameter, stat); + + bm = NULL; + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + if (!bm) + return; + + /* invalid params */ + stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0); + expect(InvalidParameter, stat); + + stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0); + expect(InvalidParameter, stat); + + /* encoder tests should succeed -- already tested */ + stat = GdipGetImageEncodersSize(&n, &s); + if (stat != Ok || n == 0) goto cleanup; + + codecs = GdipAlloc(s); + if (!codecs) goto cleanup; + + stat = GdipGetImageEncoders(n, s, codecs); + if (stat != Ok) goto cleanup; + + stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0); + expect(stat, Ok); + + GdipDisposeImage((GpImage*)bm); + bm = 0; + + /* re-load and check image stats */ + stat = GdipLoadImageFromFile(filename, (GpImage**)&bm); + expect(stat, Ok); + if (stat != Ok) goto cleanup; + + stat = GdipGetImageDimension((GpImage*)bm, &w, &h); + if (stat != Ok) goto cleanup; + + ok((fabs(w - WIDTH) < 0.01) && (fabs(h - HEIGHT) < 0.01), + "Saved image dimensions are different!\n"); + + cleanup: + GdipFree(codecs); + if (bm) + GdipDisposeImage((GpImage*)bm); + ok(DeleteFileW(filename), "Delete failed.\n"); +} + +static void test_encoders(void) +{ + GpStatus stat; + UINT n; + UINT s; + ImageCodecInfo *codecs; + int i; + int bmp_found; + + static const WCHAR bmp_format[] = {'B', 'M', 'P', 0}; + + stat = GdipGetImageEncodersSize(&n, &s); + expect(stat, Ok); + + codecs = GdipAlloc(s); + if (!codecs) + return; + + stat = GdipGetImageEncoders(n, s, NULL); + expect(GenericError, stat); + + stat = GdipGetImageEncoders(0, s, codecs); + expect(GenericError, stat); + + stat = GdipGetImageEncoders(n, s-1, codecs); + expect(GenericError, stat); + + stat = GdipGetImageEncoders(n, s+1, codecs); + expect(GenericError, stat); + + stat = GdipGetImageEncoders(n, s, codecs); + expect(stat, Ok); + + bmp_found = FALSE; + for (i = 0; i < n; i++) + { + if (CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, + codecs[i].FormatDescription, -1, + bmp_format, -1) == CSTR_EQUAL) { + bmp_found = TRUE; + break; + } + } + if (!bmp_found) + ok(FALSE, "No BMP codec found.\n"); + + GdipFree(codecs); +} + +static void test_LockBits(void) +{ + GpStatus stat; + GpBitmap *bm; + GpRect rect; + BitmapData bd; + const INT WIDTH = 10, HEIGHT = 20; + + bm = NULL; + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + + rect.X = 2; + rect.Y = 3; + rect.Width = 4; + rect.Height = 5; + + /* read-only */ + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + + if (stat == Ok) { + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + } + + /* read-only, with NULL rect -> whole bitmap lock */ + stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + expect(bd.Width, WIDTH); + expect(bd.Height, HEIGHT); + + if (stat == Ok) { + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + } + + /* read-only, consecutive */ + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + + if (stat == Ok) { + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + } + + stat = GdipDisposeImage((GpImage*)bm); + expect(Ok, stat); + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + + /* read x2 */ + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); + expect(WrongState, stat); + + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + + stat = GdipDisposeImage((GpImage*)bm); + expect(Ok, stat); + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + + /* write, no modification */ + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + + if (stat == Ok) { + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + } + + /* write, consecutive */ + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + + if (stat == Ok) { + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + } + + stat = GdipDisposeImage((GpImage*)bm); + expect(Ok, stat); + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + + /* write, modify */ + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + + if (stat == Ok) { + if (bd.Scan0) + ((char*)bd.Scan0)[2] = 0xff; + + stat = GdipBitmapUnlockBits(bm, &bd); + expect(Ok, stat); + } + + stat = GdipDisposeImage((GpImage*)bm); + expect(Ok, stat); + + /* dispose locked */ + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); + expect(Ok, stat); + stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); + expect(Ok, stat); + stat = GdipDisposeImage((GpImage*)bm); + expect(Ok, stat); +} + +static void test_GdipCreateBitmapFromHBITMAP(void) +{ + GpBitmap* gpbm = NULL; + HBITMAP hbm = NULL; + HPALETTE hpal = NULL; + GpStatus stat; + BYTE buff[1000]; + LOGPALETTE* LogPal = NULL; + REAL width, height; + const REAL WIDTH1 = 5; + const REAL HEIGHT1 = 15; + const REAL WIDTH2 = 10; + const REAL HEIGHT2 = 20; + HDC hdc; + BITMAPINFO bmi; + + stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL); + expect(InvalidParameter, stat); + + hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL); + stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL); + expect(InvalidParameter, stat); + + stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); + expect(Ok, stat); + expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height)); + ok(fabs(WIDTH1 - width) < .0001, "width wrong\n"); + ok(fabs(HEIGHT1 - height) < .0001, "height wrong\n"); + if (stat == Ok) + GdipDisposeImage((GpImage*)gpbm); + GlobalFree(hbm); + + hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff); + stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); + expect(Ok, stat); + expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height)); + ok(fabs(WIDTH2 - width) < .0001, "width wrong\n"); + ok(fabs(HEIGHT2 - height) < .0001, "height wrong\n"); + if (stat == Ok) + GdipDisposeImage((GpImage*)gpbm); + GlobalFree(hbm); + + hdc = CreateCompatibleDC(0); + ok(hdc != NULL, "CreateCompatibleDC failed\n"); + bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); + bmi.bmiHeader.biHeight = HEIGHT1; + bmi.bmiHeader.biWidth = WIDTH1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biCompression = BI_RGB; + + hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0); + ok(hbm != NULL, "CreateDIBSection failed\n"); + + stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); + expect(Ok, stat); + expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height)); + ok(fabs(WIDTH1 - width) < .0001, "width wrong\n"); + ok(fabs(HEIGHT1 - height) < .0001, "height wrong\n"); + if (stat == Ok) + GdipDisposeImage((GpImage*)gpbm); + + LogPal = GdipAlloc(sizeof(LOGPALETTE)); + ok(LogPal != NULL, "unable to allocate LOGPALETTE\n"); + LogPal->palVersion = 0x300; + hpal = CreatePalette((const LOGPALETTE*) LogPal); + ok(hpal != NULL, "CreatePalette failed\n"); + GdipFree(LogPal); + + stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm); + todo_wine + { + expect(Ok, stat); + } + if (stat == Ok) + GdipDisposeImage((GpImage*)gpbm); + + GlobalFree(hpal); + GlobalFree(hbm); +} + +static void test_GdipGetImageFlags(void) +{ + GpImage *img; + GpStatus stat; + UINT flags; + + img = (GpImage*)0xdeadbeef; + + stat = GdipGetImageFlags(NULL, NULL); + expect(InvalidParameter, stat); + + stat = GdipGetImageFlags(NULL, &flags); + expect(InvalidParameter, stat); + + stat = GdipGetImageFlags(img, NULL); + expect(InvalidParameter, stat); +} + +START_TEST(image) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_Scan0(); + test_GetImageDimension(); + test_LoadingImages(); + test_SavingImages(); + test_encoders(); + test_LockBits(); + test_GdipCreateBitmapFromHBITMAP(); + test_GdipGetImageFlags(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/matrix.c b/rostests/winetests/gdiplus/matrix.c new file mode 100644 index 00000000000..cc5348879f1 --- /dev/null +++ b/rostests/winetests/gdiplus/matrix.c @@ -0,0 +1,108 @@ +/* + * Unit test suite for matrices + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) + +static void test_constructor_destructor(void) +{ + GpStatus status; + GpMatrix *matrix = NULL; + + status = GdipCreateMatrix2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, &matrix); + expect(Ok, status); + ok(matrix != NULL, "Expected matrix to be initialized\n"); + + status = GdipDeleteMatrix(NULL); + expect(InvalidParameter, status); + + status = GdipDeleteMatrix(matrix); + expect(Ok, status); +} + +typedef struct{ + REAL X; + REAL Y; +} real_point; + +static real_point transform_points[] = { + {1000.00, 2600.00}, /*0*/ + {855.00, 2390.00}, /*1*/ + {700.00, 2200.00}, /*2*/ + {565.00, 1970.00}, /*3*/ + {400.00, 1800.00}, /*4*/ + {275.00, 1550.00}, /*5*/ + {100.00, 1400.00}, /*6*/ + {-15.00, 1130.00}, /*7*/ + {-200.00, 1000.00}, /*8*/ + {-305.00, 710.00} /*9*/ + }; + +static void test_transform(void) +{ + GpStatus status; + GpMatrix *matrix = NULL; + GpPointF pts[10]; + INT i; + BOOL match; + + for(i = 0; i < 10; i ++){ + pts[i].X = i * 5.0 * (REAL)(i % 2); + pts[i].Y = 50.0 - i * 5.0; + } + + GdipCreateMatrix2(1.0, -2.0, 30.0, 40.0, -500.0, 600.0, &matrix); + + status = GdipTransformMatrixPoints(matrix, pts, 10); + expect(Ok, status); + + for(i = 0; i < 10; i ++){ + match = fabs(transform_points[i].X - pts[i].X) < 2.0 + && fabs(transform_points[i].Y - pts[i].Y) < 2.0; + + ok(match, "Expected #%d to be (%.2f, %.2f) but got (%.2f, %.2f)\n", i, + transform_points[i].X, transform_points[i].Y, pts[i].X, pts[i].Y); + } + + GdipDeleteMatrix(matrix); +} + +START_TEST(matrix) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor_destructor(); + test_transform(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/pen.c b/rostests/winetests/gdiplus/pen.c new file mode 100644 index 00000000000..ad484ce4776 --- /dev/null +++ b/rostests/winetests/gdiplus/pen.c @@ -0,0 +1,249 @@ +/* + * Unit test suite for pens (and init) + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define expectf(expected, got) ok(fabs(got - expected) < 0.1, "Expected %.2f, got %.2f\n", expected, got) + +static void test_startup(void) +{ + GpPen *pen = NULL; + Status status; + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + expect(Ok, status); + GdiplusShutdown(gdiplusToken); + + gdiplusStartupInput.GdiplusVersion = 2; + + status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + expect(UnsupportedGdiplusVersion, status); + GdiplusShutdown(gdiplusToken); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + + todo_wine + expect(GdiplusNotInitialized, status); + + GdipDeletePen(pen); +} + +static void test_constructor_destructor(void) +{ + GpStatus status; + GpPen *pen = NULL; + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, NULL); + expect(InvalidParameter, status); + ok(pen == NULL, "Expected pen to be NULL\n"); + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + status = GdipDeletePen(NULL); + expect(InvalidParameter, status); + + status = GdipDeletePen(pen); + expect(Ok, status); +} + +static void test_constructor_destructor2(void) +{ + GpStatus status; + GpPen *pen = NULL; + GpBrush *brush = NULL; + GpPointF points[2]; + + status = GdipCreatePen2(NULL, 10.0f, UnitPixel, &pen); + expect(InvalidParameter, status); + ok(pen == NULL, "Expected pen to be NULL\n"); + + points[0].X = 7.0; + points[0].Y = 11.0; + points[1].X = 13.0; + points[1].Y = 17.0; + + status = GdipCreateLineBrush(&points[0], &points[1], (ARGB)0xffff00ff, + (ARGB)0xff0000ff, WrapModeTile, (GpLineGradient **)&brush); + expect(Ok, status); + ok(brush != NULL, "Expected brush to be initialized\n"); + + status = GdipCreatePen2(brush, 10.0f, UnitPixel, &pen); + expect(Ok, status); + ok(pen != NULL, "Expected pen to be initialized\n"); + + status = GdipDeletePen(pen); + expect(Ok, status); + + status = GdipDeleteBrush(brush); + expect(Ok, status); +} + +static void test_brushfill(void) +{ + GpStatus status; + GpPen *pen; + GpBrush *brush, *brush2; + GpBrushType type; + ARGB color = 0; + + /* default solid */ + GdipCreatePen1(0xdeadbeef, 4.5, UnitWorld, &pen); + status = GdipGetPenBrushFill(pen, &brush); + expect(Ok, status); + GdipGetBrushType(brush, &type); + expect(BrushTypeSolidColor, type); + GdipGetPenColor(pen, &color); + expect(0xdeadbeef, color); + GdipDeleteBrush(brush); + + /* color controlled by brush */ + GdipCreateSolidFill(0xabaddeed, (GpSolidFill**)&brush); + status = GdipSetPenBrushFill(pen, brush); + expect(Ok, status); + GdipGetPenColor(pen, &color); + expect(0xabaddeed, color); + GdipDeleteBrush(brush); + color = 0; + + /* get returns a clone, not a reference */ + GdipGetPenBrushFill(pen, &brush); + GdipSetSolidFillColor((GpSolidFill*)brush, 0xbeadfeed); + GdipGetPenBrushFill(pen, &brush2); + ok(brush != brush2, "Expected to get a clone, not a copy of the reference\n"); + GdipGetSolidFillColor((GpSolidFill*)brush2, &color); + expect(0xabaddeed, color); + GdipDeleteBrush(brush); + GdipDeleteBrush(brush2); + + /* brush cannot be NULL */ + status = GdipSetPenBrushFill(pen, NULL); + expect(InvalidParameter, status); + + GdipDeletePen(pen); +} + +static void test_dasharray(void) +{ + GpPen *pen; + GpDashStyle style; + GpStatus status; + REAL dashes[12]; + + GdipCreatePen1(0xdeadbeef, 10.0, UnitWorld, &pen); + dashes[0] = 10.0; + dashes[1] = 11.0; + dashes[2] = 12.0; + dashes[3] = 13.0; + dashes[4] = 14.0; + dashes[5] = -100.0; + dashes[6] = -100.0; + dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 0.0; + + /* setting the array sets the type to custom */ + GdipGetPenDashStyle(pen, &style); + expect(DashStyleSolid, style); + status = GdipSetPenDashArray(pen, dashes, 2); + expect(Ok, status); + GdipGetPenDashStyle(pen, &style); + expect(DashStyleCustom, style); + + /* Getting the array on a non-custom pen returns invalid parameter (unless + * you are getting 0 elements).*/ + GdipSetPenDashStyle(pen, DashStyleSolid); + status = GdipGetPenDashArray(pen, &dashes[5], 2); + expect(InvalidParameter, status); + status = GdipGetPenDashArray(pen, &dashes[5], 0); + expect(Ok, status); + + /* What does setting DashStyleCustom do to the array length? */ + GdipSetPenDashArray(pen, dashes, 2); + GdipSetPenDashStyle(pen, DashStyleCustom); + status = GdipGetPenDashArray(pen, &dashes[5], 2); + expect(Ok, status); + expectf(10.0, dashes[5]); + expectf(11.0, dashes[6]); + + /* Set the array, then get with different sized buffers. */ + status = GdipSetPenDashArray(pen, dashes, 5); + expect(Ok, status); + dashes[5] = -100.0; + dashes[6] = -100.0; + status = GdipGetPenDashArray(pen, &dashes[5], 1); + expect(Ok, status); /* not InsufficientBuffer! */ + expectf(10.0, dashes[5]); + expectf(-100.0, dashes[6]); + dashes[5] = -100.0; + status = GdipGetPenDashArray(pen, &dashes[5], 6); + expect(InvalidParameter, status); /* not Ok! */ + expectf(-100.0, dashes[5]); + expectf(-100.0, dashes[6]); + + /* Some invalid array values. */ + status = GdipSetPenDashArray(pen, &dashes[7], 5); + expect(InvalidParameter, status); + dashes[9] = -1.0; + status = GdipSetPenDashArray(pen, &dashes[7], 5); + expect(InvalidParameter, status); + + /* Try to set with count = 0. */ + GdipSetPenDashStyle(pen, DashStyleDot); + status = GdipSetPenDashArray(pen, dashes, 0); + expect(OutOfMemory, status); + GdipGetPenDashStyle(pen, &style); + expect(DashStyleDot, style); + + GdipDeletePen(pen); +} + +START_TEST(pen) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + test_startup(); + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor_destructor(); + test_constructor_destructor2(); + test_brushfill(); + test_dasharray(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/stringformat.c b/rostests/winetests/gdiplus/stringformat.c new file mode 100644 index 00000000000..9cf46a43297 --- /dev/null +++ b/rostests/winetests/gdiplus/stringformat.c @@ -0,0 +1,67 @@ +/* + * Unit test suite for string format + * + * Copyright (C) 2007 Google (Evan Stade) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "gdiplus.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) + +static void test_constructor(void) +{ + GpStringFormat *format; + GpStatus stat; + INT n; + StringAlignment align, valign; + StringTrimming trimming; + + stat = GdipCreateStringFormat(0, 0, &format); + expect(Ok, stat); + + GdipGetStringFormatAlign(format, &align); + GdipGetStringFormatLineAlign(format, &valign); + GdipGetStringFormatHotkeyPrefix(format, &n); + GdipGetStringFormatTrimming(format, &trimming); + + expect(HotkeyPrefixNone, n); + expect(StringAlignmentNear, align); + expect(StringAlignmentNear, align); + expect(StringTrimmingCharacter, trimming); + + stat = GdipDeleteStringFormat(format); + expect(Ok, stat); +} + +START_TEST(stringformat) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/rostests/winetests/gdiplus/testlist.c b/rostests/winetests/gdiplus/testlist.c new file mode 100644 index 00000000000..dfb3f46ffa4 --- /dev/null +++ b/rostests/winetests/gdiplus/testlist.c @@ -0,0 +1,29 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define WIN32_LEAN_AND_MEAN +#include + +#define STANDALONE +#include "wine/test.h" + +extern void func_brush(void); +extern void func_graphics(void); +extern void func_graphicspath(void); +extern void func_image(void); +extern void func_matrix(void); +extern void func_pen(void); +extern void func_stringformat(void); +extern void func_font(void); + +const struct test winetest_testlist[] = +{ + { "brush", func_brush }, + { "graphics", func_graphics }, + { "graphicspath", func_graphicspath }, + { "font", func_font }, + { "image", func_image }, + { "matrix", func_matrix }, + { "stringformat", func_stringformat }, + { "pen", func_pen }, + { 0, 0 } +};