[WINESYNC] Add GDI+ winetests

This commit is contained in:
Maj Soklič 2024-04-29 22:50:17 +02:00
parent e83bb30af0
commit d6b3bc40a4
14 changed files with 3543 additions and 394 deletions

View file

@ -18,13 +18,22 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <math.h>
#include "objbase.h"
#include "gdiplus.h"
#include "wine/test.h"
#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
#ifdef __REACTOS__
#include "ole2.h"
#endif
#define expect(expected,got) expect_(__LINE__, expected, got)
static inline void expect_(unsigned line, DWORD expected, DWORD got)
{
ok_(__FILE__, line)(expected == got, "Expected %.8ld, got %.8ld\n", expected, got);
}
#define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
static HWND hwnd;
@ -274,6 +283,37 @@ static void test_transform(void)
GpPointF start, end;
GpRectF rectf;
REAL elements[6];
UINT buf[15];
HBITMAP hbmp,old;
HDC dcmem;
BITMAP bm;
GpImage *image;
IStream *stream;
HGLOBAL hglob;
VOID *data;
HRESULT hr;
LONG size;
/* 3*5 bmp 32bit*/
static const unsigned char bmpimage[] = {
0x42,0x4d,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,
0x00,0x00,0x28,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x05,0x00,
0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,
0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0x11,0xff,0x00,0xff,0x11,0xff,0x00,0xff,0x11,0xff,0x00,
0xff,0x33,0xff,0x00,0xff,0x33,0xff,0x00,0xff,0x33,0xff,0x00,
0xff,0x55,0xff,0x00,0xff,0x55,0xff,0x00,0xff,0x55,0xff,0x00,
0xff,0xaa,0xff,0x00,0xff,0xaa,0xff,0x00,0xff,0xaa,0xff,0x00,
0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,
0x00,0x00,0x00,0x00};
static const UINT buf_rotate_180[15] = {
0xffffffff, 0xffffffff, 0xffffffff,
0xffff11ff, 0xffff11ff, 0xffff11ff,
0xffff33ff, 0xffff33ff, 0xffff33ff,
0xffff55ff, 0xffff55ff, 0xffff55ff,
0xffffaaff, 0xffffaaff, 0xffffaaff};
/* GpTexture */
status = GdipCreateMatrix2(2.0, 0.0, 0.0, 0.0, 0.0, 0.0, &m);
@ -556,6 +596,38 @@ static void test_transform(void)
expect(Ok, status);
status = GdipDeleteBrush((GpBrush*)line);
expect(Ok,status);
GdipDeleteGraphics(graphics);
dcmem = CreateCompatibleDC(hdc);
hbmp = CreateBitmap(3, 5, 1, 32, NULL);
old = SelectObject(dcmem, hbmp);
status = GdipCreateFromHDC(dcmem, &graphics);
expect(Ok, status);
hglob = GlobalAlloc(0, sizeof(bmpimage));
data = GlobalLock (hglob);
memcpy(data, bmpimage, sizeof(bmpimage));
GlobalUnlock(hglob);
hr = CreateStreamOnHGlobal(hglob, TRUE, &stream);
expect(S_OK, hr);
status = GdipLoadImageFromStream(stream, &image);
expect(Ok, status);
status = GdipCreateTexture(image, WrapModeTile, &texture);
expect(Ok, status);
status = GdipRotateTextureTransform(texture, 180.0f, MatrixOrderPrepend);
expect(Ok, status);
status = GdipFillRectangle(graphics, (GpBrush*)texture, .0f, .0f, (REAL)3, (REAL)5);
expect(Ok, status);
GdipDeleteBrush((GpBrush*)texture);
GdipDisposeImage(image);
GdipDeleteGraphics(graphics);
IStream_Release(stream);
hbmp = SelectObject(dcmem, old);
GetObjectW(hbmp, sizeof(bm), &bm);
size = GetBitmapBits(hbmp, sizeof(buf), buf);
expect(sizeof(buf), size);
DeleteObject(hbmp);
DeleteDC(dcmem);
ok(!memcmp(buf, buf_rotate_180, sizeof(buf)), "Failed to rotate image.\n");
if(0){
/* enable to visually compare with Windows */
@ -1299,6 +1371,7 @@ static void test_pathgradientcenterpoint(void)
{
static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
GpStatus status;
GpPath* path;
GpPathGradient *grad;
GpPointF point;
@ -1341,8 +1414,28 @@ static void test_pathgradientcenterpoint(void)
status = GdipGetPathGradientCenterPoint(grad, &point);
expect(Ok, status);
todo_wine expectf(1.0, point.X);
todo_wine expectf(4.0/3.0, point.Y);
expectf(1.0, point.X);
expectf(4.0/3.0, point.Y);
status = GdipDeleteBrush((GpBrush*)grad);
expect(Ok, status);
status = GdipCreatePath(FillModeWinding, &path);
expect(Ok, status);
status = GdipAddPathEllipse(path, 0, 0, 100, 50);
expect(Ok, status);
status = GdipCreatePathGradientFromPath(path, &grad);
expect(Ok, status);
status = GdipGetPathGradientCenterPoint(grad, &point);
expect(Ok, status);
expectf(700.0/13.0, point.X);
expectf(25.0, point.Y);
status = GdipDeletePath(path);
expect(Ok, status);
status = GdipDeleteBrush((GpBrush*)grad);
expect(Ok, status);
@ -1613,6 +1706,239 @@ static void test_getHatchStyle(void)
GdipDeleteBrush((GpBrush *)brush);
}
static ARGB COLORREF2ARGB(COLORREF color)
{
return 0xff000000 |
(color & 0xff) << 16 |
(color & 0xff00) |
(color & 0xff0000) >> 16;
}
extern BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff);
static void test_hatchBrushStyles(void)
{
static const struct
{
short pattern[8];
GpHatchStyle hs;
}
styles[] =
{
{ {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff}, HatchStyleHorizontal },
{ {0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000}, HatchStyleVertical },
{ {0x4006, 0x0019, 0x0064, 0x0190, 0x0640, 0x1900, 0x6400, 0x9001}, HatchStyleForwardDiagonal },
{ {0x9001, 0x6400, 0x1900, 0x0640, 0x0190, 0x0064, 0x0019, 0x4006}, HatchStyleBackwardDiagonal },
{ {0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xffff}, HatchStyleCross },
{ {0x9006, 0x6419, 0x1964, 0x0690, 0x0690, 0x1964, 0x6419, 0x9006}, HatchStyleDiagonalCross },
{ {0x0000, 0x0000, 0x0000, 0x00c0, 0x0000, 0x0000, 0x0000, 0xc000}, HatchStyle05Percent },
{ {0x0000, 0x00c0, 0x0000, 0xc000, 0x0000, 0x00c0, 0x0000, 0xc000}, HatchStyle10Percent },
{ {0x0000, 0x0c0c, 0x0000, 0xc0c0, 0x0000, 0x0c0c, 0x0000, 0xc0c0}, HatchStyle20Percent },
{ {0x0c0c, 0xc0c0, 0x0c0c, 0xc0c0, 0x0c0c, 0xc0c0, 0x0c0c, 0xc0c0}, HatchStyle25Percent },
{ {0x0303, 0xcccc, 0x3030, 0xcccc, 0x0303, 0xcccc, 0x3030, 0xcccc}, HatchStyle30Percent },
{ {0x0333, 0xcccc, 0x3333, 0xcccc, 0x3303, 0xcccc, 0x3333, 0xcccc}, HatchStyle40Percent },
{ {0x3333, 0xcccc, 0x3333, 0xcccc, 0x3333, 0xcccc, 0x3333, 0xcccc}, HatchStyle50Percent },
{ {0x3333, 0xcfcf, 0x3333, 0xfcfc, 0x3333, 0xcfcf, 0x3333, 0xfcfc}, HatchStyle60Percent },
{ {0xf3f3, 0x3f3f, 0xf3f3, 0x3f3f, 0xf3f3, 0x3f3f, 0xf3f3, 0x3f3f}, HatchStyle70Percent },
{ {0xffff, 0xf3f3, 0xffff, 0x3f3f, 0xffff, 0xf3f3, 0xffff, 0x3f3f}, HatchStyle75Percent },
{ {0xffff, 0xfffc, 0xffff, 0xfcff, 0xffff, 0xfffc, 0xffff, 0xfcff}, HatchStyle80Percent },
{ {0x3fff, 0xffff, 0xffff, 0xffff, 0xff3f, 0xffff, 0xffff, 0xffff}, HatchStyle90Percent },
{ {0x0303, 0x0c0c, 0x3030, 0xc0c0, 0x0303, 0x0c0c, 0x3030, 0xc0c0}, HatchStyleLightDownwardDiagonal },
{ {0xc0c0, 0x3030, 0x0c0c, 0x0303, 0xc0c0, 0x3030, 0x0c0c, 0x0303}, HatchStyleLightUpwardDiagonal },
{ {0xc3c3, 0x0f0f, 0x3c3c, 0xf0f0, 0xc3c3, 0x0f0f, 0x3c3c, 0xf0f0}, HatchStyleDarkDownwardDiagonal },
{ {0xc3c3, 0xf0f0, 0x3c3c, 0x0f0f, 0xc3c3, 0xf0f0, 0x3c3c, 0x0f0f}, HatchStyleDarkUpwardDiagonal },
{ {0xc00f, 0x003f, 0x00fc, 0x03f0, 0x0fc0, 0x3f00, 0xfc00, 0xf003}, HatchStyleWideDownwardDiagonal },
{ {0xf003, 0xfc00, 0x3f00, 0x0fc0, 0x03f0, 0x00fc, 0x003f, 0xc00f}, HatchStyleWideUpwardDiagonal },
{ {0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0}, HatchStyleLightVertical },
{ {0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0xffff}, HatchStyleLightHorizontal },
{ {0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333}, HatchStyleNarrowVertical },
{ {0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff}, HatchStyleNarrowHorizontal },
{ {0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0}, HatchStyleDarkVertical },
{ {0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff}, HatchStyleDarkHorizontal },
{ {0x0000, 0x0000, 0x0303, 0x0c0c, 0x3030, 0xc0c0, 0x0000, 0x0000}, HatchStyleDashedDownwardDiagonal },
{ {0x0000, 0x0000, 0xc0c0, 0x3030, 0x0c0c, 0x0303, 0x0000, 0x0000}, HatchStyleDashedUpwardDiagonal },
{ {0x0000, 0x0000, 0x0000, 0x00ff, 0x0000, 0x0000, 0x0000, 0xff00}, HatchStyleDashedHorizontal },
{ {0x00c0, 0x00c0, 0x00c0, 0x00c0, 0xc000, 0xc000, 0xc000, 0xc000}, HatchStyleDashedVertical },
{ {0x0030, 0x0c00, 0x0003, 0x0300, 0x000c, 0x3000, 0x00c0, 0xc000}, HatchStyleSmallConfetti },
{ {0xc0f3, 0x00f0, 0xf000, 0xf3c0, 0x03cf, 0x000f, 0x0f00, 0xcf03}, HatchStyleLargeConfetti },
{ {0x03c0, 0x0c30, 0x300c, 0xc003, 0x03c0, 0x0c30, 0x300c, 0xc003}, HatchStyleZigZag },
{ {0xf000, 0x0c33, 0x03c0, 0x0000, 0xf000, 0x0c33, 0x03c0, 0x0000}, HatchStyleWave },
{ {0xc003, 0x300c, 0x0c30, 0x03c0, 0x00c0, 0x0030, 0x000c, 0x0003}, HatchStyleDiagonalBrick },
{ {0x00c0, 0x00c0, 0x00c0, 0xffff, 0xc000, 0xc000, 0xc000, 0xffff}, HatchStyleHorizontalBrick },
{ {0x3303, 0x0c0c, 0x0330, 0xc0c0, 0x3033, 0x0c0c, 0x3330, 0xc0c0}, HatchStyleWeave },
{ {0xff00, 0xff00, 0xff00, 0xff00, 0x3333, 0xcccc, 0x3333, 0xcccc}, HatchStylePlaid },
{ {0xc000, 0x0003, 0xc000, 0x0000, 0x0300, 0x00c0, 0x0300, 0x0000}, HatchStyleDivot },
{ {0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xcccc}, HatchStyleDottedGrid },
{ {0x0000, 0x0c0c, 0x0000, 0x00c0, 0x0000, 0x0c0c, 0x0000, 0xc000}, HatchStyleDottedDiamond },
{ {0x0003, 0x0003, 0x000c, 0x00f0, 0x0f00, 0x30c0, 0xc030, 0x000f}, HatchStyleShingle },
{ {0xc3c3, 0xffff, 0x3c3c, 0xffff, 0xc3c3, 0xffff, 0x3c3c, 0xffff}, HatchStyleTrellis },
{ {0xffc0, 0xffc0, 0xc3c0, 0x3f3f, 0xc0ff, 0xc0ff, 0xc0c3, 0x3f3f}, HatchStyleSphere },
{ {0xc0c0, 0xc0c0, 0xc0c0, 0xffff, 0xc0c0, 0xc0c0, 0xc0c0, 0xffff}, HatchStyleSmallGrid },
{ {0xc3c3, 0x3c3c, 0x3c3c, 0xc3c3, 0xc3c3, 0x3c3c, 0x3c3c, 0xc3c3}, HatchStyleSmallCheckerBoard },
{ {0x00ff, 0x00ff, 0x00ff, 0x00ff, 0xff00, 0xff00, 0xff00, 0xff00}, HatchStyleLargeCheckerBoard },
{ {0x0003, 0xc00c, 0x3030, 0x0cc0, 0x0300, 0x0cc0, 0x3030, 0xc00c}, HatchStyleOutlinedDiamond },
{ {0x0000, 0x0300, 0x0fc0, 0x3ff0, 0xfffc, 0x3ff0, 0x0fc0, 0x0300}, HatchStyleSolidDiamond },
};
static const ARGB exp_colors[] = { 0xffffffff, 0xffbfbfbf, 0xff151515, 0xff000000 };
static const ARGB fore_color = 0xff000000;
static const ARGB back_color = 0xffffffff;
static const int width = 16, height = 16;
GpStatus status;
HDC hdc;
GpGraphics *graphics_hdc;
GpGraphics *graphics_image;
GpBitmap *bitmap;
GpHatch *brush = NULL;
BOOL match_hdc;
BOOL match_image;
int x, y;
int i;
hdc = GetDC(hwnd);
status = GdipCreateFromHDC(hdc, &graphics_hdc);
expect(Ok, status);
ok(graphics_hdc != NULL, "Expected the graphics context to be initialized.\n");
status = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppRGB, NULL, &bitmap);
expect(Ok, status);
status = GdipGetImageGraphicsContext((GpImage *)bitmap, &graphics_image);
expect(Ok, status);
ok(graphics_image != NULL, "Expected the graphics context to be initialized.\n");
for (i = 0; i < ARRAY_SIZE(styles); i++)
{
status = GdipCreateHatchBrush(styles[i].hs, fore_color, back_color, &brush);
expect(Ok, status);
ok(brush != NULL, "Expected the brush to be initialized.\n");
status = GdipFillRectangleI(graphics_hdc, (GpBrush *)brush, 0, 0, width, height);
expect(Ok, status);
status = GdipFillRectangleI(graphics_image, (GpBrush *)brush, 0, 0, width, height);
expect(Ok, status);
status = GdipDeleteBrush((GpBrush *)brush);
expect(Ok, status);
brush = NULL;
match_hdc = TRUE;
match_image = TRUE;
for(y = 0; y < width && (match_hdc || match_image); y++)
{
for(x = 0; x < height && (match_hdc || match_image); x++)
{
ARGB color;
int cindex = (styles[i].pattern[7-(y%8)] >> (2*(7-(x%8)))) & 3;
color = COLORREF2ARGB(GetPixel(hdc, x, y));
if (!color_match(color, exp_colors[cindex], 1))
match_hdc = FALSE;
GdipBitmapGetPixel(bitmap, x, y, &color);
if (!color_match(color, exp_colors[cindex], 1))
match_image = FALSE;
}
}
ok(match_hdc, "Unexpected pattern for hatch style %#x with hdc.\n", styles[i].hs);
ok(match_image, "Unexpected pattern for hatch style %#x with image.\n", styles[i].hs);
}
status = GdipDeleteGraphics(graphics_image);
expect(Ok, status);
status = GdipDisposeImage((GpImage*)bitmap);
expect(Ok, status);
status = GdipDeleteGraphics(graphics_hdc);
expect(Ok, status);
ReleaseDC(hwnd, hdc);
}
static void test_renderingOrigin(void)
{
static const int width = 8, height = 8;
GpStatus status;
HDC hdc;
GpBitmap *bitmap;
GpGraphics *graphics_hdc;
GpGraphics *graphics_image;
GpHatch *brush;
BOOL match_hdc;
BOOL match_image;
static const INT tests[][2] = {{3, 6}, {-7, -4}};
static const ARGB fore_color = 0xff000000;
static const ARGB back_color = 0xffffffff;
INT x, y;
int i;
hdc = GetDC(hwnd);
GdipCreateFromHDC(hdc, &graphics_hdc);
GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppRGB, NULL, &bitmap);
GdipGetImageGraphicsContext((GpImage *)bitmap, &graphics_image);
GdipCreateHatchBrush(HatchStyleCross, fore_color, back_color, &brush);
x = y = 0xdeadbeef;
status = GdipGetRenderingOrigin(graphics_image, &x, &y);
expect(Ok, status);
ok(x == 0 && y == 0, "Expected (%d, %d) got (%d, %d)\n", 0, 0, x, y);
x = y = 0xdeadbeef;
status = GdipGetRenderingOrigin(graphics_image, &x, &y);
expect(Ok, status);
ok(x == 0 && y == 0, "Expected (%d, %d) got (%d, %d)\n", 0, 0, x, y);
for (i = 0; i < ARRAY_SIZE(tests); i++)
{
const INT exp_x = tests[i][0] & 7;
const INT exp_y = tests[i][1] & 7;
status = GdipSetRenderingOrigin(graphics_image, tests[i][0], tests[i][1]);
expect(Ok, status);
status = GdipSetRenderingOrigin(graphics_hdc, tests[i][0], tests[i][1]);
expect(Ok, status);
status = GdipGetRenderingOrigin(graphics_image, &x, &y);
expect(Ok, status);
ok(x == tests[i][0] && y == tests[i][1], "Expected (%d, %d) got (%d, %d)\n",
tests[i][0], tests[i][1], x, y);
status = GdipGetRenderingOrigin(graphics_image, &x, &y);
expect(Ok, status);
ok(x == tests[i][0] && y == tests[i][1], "Expected (%d, %d) got (%d, %d)\n",
tests[i][0], tests[i][1], x, y);
GdipFillRectangleI(graphics_image, (GpBrush *)brush, 0, 0, width, height);
GdipFillRectangleI(graphics_hdc, (GpBrush *)brush, 0, 0, width, height);
match_hdc = TRUE;
match_image = TRUE;
for (y = 0; y < height && (match_hdc || match_image); y++)
{
for (x = 0; x < width && (match_hdc || match_image); x++)
{
ARGB color;
const ARGB exp_color = (x == exp_x || y == exp_y) ? fore_color : back_color;
color = COLORREF2ARGB(GetPixel(hdc, x, y));
if (color != exp_color)
match_hdc = FALSE;
GdipBitmapGetPixel(bitmap, x, y, &color);
if (color != exp_color)
match_image = FALSE;
}
}
ok(match_hdc, "Hatch brush rendered incorrectly on hdc with rendering origin (%d, %d).\n",
tests[i][0], tests[i][1]);
ok(match_image, "Hatch brush rendered incorrectly on image with rendering origin (%d, %d).\n",
tests[i][0], tests[i][1]);
}
GdipDeleteBrush((GpBrush *)brush);
GdipDeleteGraphics(graphics_image);
GdipDisposeImage((GpImage*)bitmap);
GdipDeleteGraphics(graphics_hdc);
ReleaseDC(hwnd, hdc);
}
START_TEST(brush)
{
struct GdiplusStartupInput gdiplusStartupInput;
@ -1665,6 +1991,8 @@ START_TEST(brush)
test_pathgradientpresetblend();
test_pathgradientblend();
test_getHatchStyle();
test_hatchBrushStyles();
test_renderingOrigin();
GdiplusShutdown(gdiplusToken);
DestroyWindow(hwnd);

View file

@ -283,12 +283,12 @@ static void test_create_adjustable_cap(void)
ok(base == LineCapTriangle, "Unexpected base cap %d\n", base);
stat = GdipSetCustomLineCapBaseCap((GpCustomLineCap*)cap, LineCapSquare);
todo_wine
todo_wine
ok(stat == Ok, "Unexpected return code, %d\n", stat);
stat = GdipGetCustomLineCapBaseCap((GpCustomLineCap*)cap, &base);
ok(stat == Ok, "Unexpected return code, %d\n", stat);
todo_wine
todo_wine
ok(base == LineCapSquare, "Unexpected base cap %d\n", base);
/* Base inset */

View file

@ -25,16 +25,16 @@
#include "gdiplus.h"
#include "wine/test.h"
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
#define expect_(expected, got, precision) ok(abs((expected) - (got)) <= (precision), "Expected %d, got %d\n", (expected), (got))
#define expect(expected,got) expect_inline(__LINE__, expected, got)
static inline void expect_inline(unsigned line, DWORD expected, DWORD got)
{
ok_(__FILE__, line)(expected == got, "Expected %ld, got %ld\n", expected, got);
}
#define expect_(expected, got, precision) ok(abs((expected) - (got)) <= (precision), "Expected %d, got %ld\n", (expected), (got))
#define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
#define expectf(expected, got) expectf_((expected), (got), 0.001)
static const WCHAR nonexistent[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'};
static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
static const WCHAR Tahoma[] = {'T','a','h','o','m','a',0};
static void set_rect_empty(RectF *rc)
{
rc->X = 0.0;
@ -54,7 +54,7 @@ static void create_testfontfile(const WCHAR *filename, int resource, WCHAR pathW
lstrcatW(pathW, filename);
file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW), GetLastError());
ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %ld\n", wine_dbgstr_w(pathW), GetLastError());
res = FindResourceA(GetModuleHandleA(NULL), MAKEINTRESOURCEA(resource), (LPCSTR)RT_RCDATA);
ok(res != 0, "couldn't find resource\n");
@ -68,24 +68,23 @@ static void create_testfontfile(const WCHAR *filename, int resource, WCHAR pathW
static void _delete_testfontfile(const WCHAR *filename, int line)
{
BOOL ret = DeleteFileW(filename);
ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError());
ok_(__FILE__,line)(ret, "failed to delete file %s, error %ld\n", wine_dbgstr_w(filename), GetLastError());
}
static void test_long_name(void)
{
WCHAR path[MAX_PATH];
static const WCHAR path_longname[] = {'w','i','n','e','_','l','o','n','g','n','a','m','e','.','t','t','f',0};
GpStatus stat;
GpFontCollection *fonts;
INT num_families;
GpFontFamily *family;
GpFontFamily *family, *cloned_family;
WCHAR family_name[LF_FACESIZE];
GpFont *font;
stat = GdipNewPrivateFontCollection(&fonts);
ok(stat == Ok, "GdipNewPrivateFontCollection failed: %d\n", stat);
create_testfontfile(path_longname, 1, path);
create_testfontfile(L"wine_longname.ttf", 1, path);
stat = GdipPrivateAddFontFile(fonts, path);
ok(stat == Ok, "GdipPrivateAddFontFile failed: %d\n", stat);
@ -104,6 +103,10 @@ static void test_long_name(void)
stat = GdipCreateFont(family, 256.0, FontStyleRegular, UnitPixel, &font);
ok(stat == Ok, "GdipCreateFont failed: %d\n", stat);
stat = GdipCloneFontFamily(family, &cloned_family);
ok(stat == Ok, "GdipCloneFontFamily failed: %d\n", stat);
ok(family == cloned_family, "GdipCloneFontFamily returned new object\n");
/* Cleanup */
stat = GdipDeleteFont(font);
@ -112,6 +115,13 @@ static void test_long_name(void)
stat = GdipDeletePrivateFontCollection(&fonts);
ok(stat == Ok, "GdipDeletePrivateFontCollection failed: %d\n", stat);
/* Cloned family survives after collection is deleted */
stat = GdipGetFamilyName(cloned_family, family_name, LANG_NEUTRAL);
ok(stat == Ok, "GdipGetFamilyName failed: %d\n", stat);
stat = GdipDeleteFontFamily(cloned_family);
ok(stat == Ok, "GdipDeleteFontFamily failed: %d\n", stat);
DELETE_FONTFILE(path);
}
@ -125,11 +135,11 @@ static void test_createfont(void)
REAL size;
WCHAR familyname[LF_FACESIZE];
stat = GdipCreateFontFamilyFromName(nonexistent, NULL, &fontfamily);
stat = GdipCreateFontFamilyFromName(L"ThisFontShouldNotExist", NULL, &fontfamily);
expect (FontFamilyNotFound, stat);
stat = GdipDeleteFont(font);
expect (InvalidParameter, stat);
stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
stat = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &fontfamily);
expect (Ok, stat);
stat = GdipCreateFont(fontfamily, 12, FontStyleRegular, UnitPoint, &font);
expect (Ok, stat);
@ -141,7 +151,8 @@ static void test_createfont(void)
expect(Ok, stat);
stat = GdipGetFamilyName(fontfamily2, familyname, 0);
expect(Ok, stat);
ok (lstrcmpiW(Tahoma, familyname) == 0, "Expected Tahoma, got %s\n",
ok (fontfamily == fontfamily2, "Unexpected family instance.\n");
ok (lstrcmpiW(L"Tahoma", familyname) == 0, "Expected Tahoma, got %s\n",
wine_dbgstr_w(familyname));
stat = GdipDeleteFontFamily(fontfamily2);
expect(Ok, stat);
@ -299,6 +310,56 @@ static void test_logfont(void)
GdipDeleteFontFamily(family);
GdipDeleteFont(font);
font = NULL;
/* The next test must be done with a font where tmHeight -
tmInternalLeading != tmAscent. Times New Roman is such a font,
so make sure we really have it before continuing. */
memset(&lfa, 0, sizeof(lfa));
lstrcpyA(lfa.lfFaceName, "Times New Roman");
stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
expect(Ok, stat);
memset(&lfa2, 0, sizeof(lfa2));
stat = GdipGetLogFontA(font, graphics, &lfa2);
expect(Ok, stat);
GdipDeleteFont(font);
font = NULL;
if (!lstrlenA(lfa.lfFaceName) || lstrcmpA(lfa.lfFaceName, lfa2.lfFaceName))
{
skip("Times New Roman not installed\n");
}
else
{
static const struct
{
INT input;
REAL expected;
} test_sizes[] = {{12, 9.0}, {36, 32.0}, {48, 42.0}, {72, 63.0}, {144, 127.0}};
UINT i;
memset(&lfa, 0, sizeof(lfa));
lstrcpyA(lfa.lfFaceName, "Times New Roman");
for (i = 0; i < ARRAY_SIZE(test_sizes); ++i)
{
lfa.lfHeight = test_sizes[i].input;
stat = GdipCreateFontFromLogfontA(hdc, &lfa, &font);
expect(Ok, stat);
stat = GdipGetFontSize(font, &rval);
expect(Ok, stat);
expectf(test_sizes[i].expected, rval);
GdipDeleteFont(font);
font = NULL;
}
}
GdipDeleteGraphics(graphics);
ReleaseDC(0, hdc);
@ -311,42 +372,40 @@ static void test_fontfamily (void)
GpStatus stat;
/* FontFamily cannot be NULL */
stat = GdipCreateFontFamilyFromName (Tahoma , NULL, NULL);
stat = GdipCreateFontFamilyFromName (L"Tahoma" , NULL, NULL);
expect (InvalidParameter, stat);
/* FontFamily must be able to actually find the family.
* If it can't, any subsequent calls should fail.
*/
stat = GdipCreateFontFamilyFromName (nonexistent, NULL, &family);
stat = GdipCreateFontFamilyFromName (L"ThisFontShouldNotExist", NULL, &family);
expect (FontFamilyNotFound, stat);
/* Bitmap fonts are not found */
stat = GdipCreateFontFamilyFromName (MSSansSerif, NULL, &family);
stat = GdipCreateFontFamilyFromName (L"MS Sans Serif", NULL, &family);
expect (FontFamilyNotFound, stat);
if(stat == Ok) GdipDeleteFontFamily(family);
stat = GdipCreateFontFamilyFromName (Tahoma, NULL, &family);
stat = GdipCreateFontFamilyFromName (L"Tahoma", NULL, &family);
expect (Ok, stat);
stat = GdipGetFamilyName (family, itsName, LANG_NEUTRAL);
expect (Ok, stat);
expect (0, lstrcmpiW(itsName, Tahoma));
expect (0, lstrcmpiW(itsName, L"Tahoma"));
if (0)
{
/* Crashes on Windows XP SP2, Vista, and so Wine as well */
stat = GdipGetFamilyName (family, NULL, LANG_NEUTRAL);
expect (Ok, stat);
}
/* Crashes on Windows XP SP2 and Vista */
stat = GdipGetFamilyName (family, NULL, LANG_NEUTRAL);
expect (Ok, stat);
/* Make sure we don't read old data */
ZeroMemory (itsName, sizeof(itsName));
stat = GdipCloneFontFamily(family, &clonedFontFamily);
expect (Ok, stat);
ok (family == clonedFontFamily, "Unexpected family instance.\n");
GdipDeleteFontFamily(family);
stat = GdipGetFamilyName(clonedFontFamily, itsName, LANG_NEUTRAL);
expect(Ok, stat);
expect(0, lstrcmpiW(itsName, Tahoma));
expect(0, lstrcmpiW(itsName, L"Tahoma"));
GdipDeleteFontFamily(clonedFontFamily);
}
@ -357,7 +416,7 @@ static void test_fontfamily_properties (void)
GpStatus stat;
UINT16 result = 0;
stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &FontFamily);
stat = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &FontFamily);
expect(Ok, stat);
stat = GdipGetLineSpacing(FontFamily, FontStyleRegular, &result);
@ -377,7 +436,7 @@ static void test_fontfamily_properties (void)
ok(result == 423, "Expected 423, got %d\n", result);
GdipDeleteFontFamily(FontFamily);
stat = GdipCreateFontFamilyFromName(TimesNewRoman, NULL, &FontFamily);
stat = GdipCreateFontFamilyFromName(L"Times New Roman", NULL, &FontFamily);
if(stat == FontFamilyNotFound)
skip("Times New Roman not installed\n");
else
@ -481,7 +540,7 @@ static void test_heightgivendpi(void)
REAL height;
Unit unit;
stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &fontfamily);
stat = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &fontfamily);
expect(Ok, stat);
stat = GdipCreateFont(fontfamily, 30, FontStyleRegular, UnitPixel, &font);
@ -682,7 +741,7 @@ static void test_font_metrics(void)
memset(&lf, 0, sizeof(lf));
/* Tahoma,-13 */
lstrcpyW(lf.lfFaceName, Tahoma);
lstrcpyW(lf.lfFaceName, L"Tahoma");
lf.lfHeight = -13;
stat = GdipCreateFontFromLogfontW(hdc, &lf, &font);
expect(Ok, stat);
@ -693,14 +752,14 @@ static void test_font_metrics(void)
gdip_get_font_metrics(font, &fm_gdip);
trace("gdiplus:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
fm_gdip.font_height, fm_gdip.font_size);
gdi_get_font_metrics(&lf, &fm_gdi);
trace("gdi:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
fm_gdi.font_height, fm_gdi.font_size);
@ -709,10 +768,10 @@ static void test_font_metrics(void)
stat = GdipGetLogFontW(font, graphics, &lf);
expect(Ok, stat);
ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %ld\n", lf.lfHeight);
gdi_get_font_metrics(&lf, &fm_gdi);
trace("gdi:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
fm_gdi.font_height, fm_gdi.font_size);
@ -723,7 +782,7 @@ static void test_font_metrics(void)
GdipDeleteFont(font);
/* Tahoma,13 */
lstrcpyW(lf.lfFaceName, Tahoma);
lstrcpyW(lf.lfFaceName, L"Tahoma");
lf.lfHeight = 13;
stat = GdipCreateFontFromLogfontW(hdc, &lf, &font);
expect(Ok, stat);
@ -734,14 +793,14 @@ static void test_font_metrics(void)
gdip_get_font_metrics(font, &fm_gdip);
trace("gdiplus:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
fm_gdip.font_height, fm_gdip.font_size);
gdi_get_font_metrics(&lf, &fm_gdi);
trace("gdi:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
fm_gdi.font_height, fm_gdi.font_size);
@ -750,10 +809,10 @@ static void test_font_metrics(void)
stat = GdipGetLogFontW(font, graphics, &lf);
expect(Ok, stat);
ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %ld\n", lf.lfHeight);
gdi_get_font_metrics(&lf, &fm_gdi);
trace("gdi:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
fm_gdi.font_height, fm_gdi.font_size);
@ -763,7 +822,7 @@ static void test_font_metrics(void)
GdipDeleteFont(font);
stat = GdipCreateFontFamilyFromName(Tahoma, NULL, &family);
stat = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, stat);
/* Tahoma,13 */
@ -772,17 +831,17 @@ static void test_font_metrics(void)
gdip_get_font_metrics(font, &fm_gdip);
trace("gdiplus:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdip.em_height, fm_gdip.line_spacing, fm_gdip.ascent, fm_gdip.descent,
fm_gdip.font_height, fm_gdip.font_size);
stat = GdipGetLogFontW(font, graphics, &lf);
expect(Ok, stat);
ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %d\n", lf.lfHeight);
ok(lf.lfHeight < 0, "lf.lfHeight should be negative, got %ld\n", lf.lfHeight);
gdi_get_font_metrics(&lf, &fm_gdi);
trace("gdi:\n");
trace("%s,%d: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
trace("%s,%ld: EmHeight %u, LineSpacing %u, CellAscent %u, CellDescent %u, FontHeight %f, FontSize %f\n",
wine_dbgstr_w(lf.lfFaceName), lf.lfHeight,
fm_gdi.em_height, fm_gdi.line_spacing, fm_gdi.ascent, fm_gdi.descent,
fm_gdi.font_height, fm_gdi.font_size);
@ -806,52 +865,43 @@ static void test_font_metrics(void)
static void test_font_substitution(void)
{
WCHAR ms_shell_dlg[LF_FACESIZE];
char fallback_font[LF_FACESIZE];
HDC hdc;
HFONT hfont;
LOGFONTA lf;
GpStatus status;
GpGraphics *graphics;
GpFont *font;
GpFontFamily *family;
int ret;
hdc = CreateCompatibleDC(0);
status = GdipCreateFromHDC(hdc, &graphics);
expect(Ok, status);
hfont = GetStockObject(DEFAULT_GUI_FONT);
ok(hfont != 0, "GetStockObject(DEFAULT_GUI_FONT) failed\n");
memset(&lf, 0xfe, sizeof(lf));
ret = GetObjectA(hfont, sizeof(lf), &lf);
ok(ret == sizeof(lf), "GetObject failed\n");
ok(!lstrcmpA(lf.lfFaceName, "MS Shell Dlg"), "wrong face name %s\n", lf.lfFaceName);
MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, -1, ms_shell_dlg, LF_FACESIZE);
memset(&lf, 0, sizeof(lf));
lstrcpyA(lf.lfFaceName, "MS Shell Dlg");
status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
expect(Ok, status);
memset(&lf, 0xfe, sizeof(lf));
status = GdipGetLogFontA(font, graphics, &lf);
expect(Ok, status);
ok(!lstrcmpA(lf.lfFaceName, "Microsoft Sans Serif") ||
!lstrcmpA(lf.lfFaceName, "Tahoma"), "wrong face name %s\n", lf.lfFaceName);
ok(lstrcmpA(lf.lfFaceName, "MS Shell Dlg") != 0, "expected substitution of MS Shell Dlg\n");
GdipDeleteFont(font);
status = GdipCreateFontFamilyFromName(ms_shell_dlg, NULL, &family);
family = NULL;
status = GdipCreateFontFamilyFromName(L"MS Shell Dlg", NULL, &family);
expect(Ok, status);
font = NULL;
status = GdipCreateFont(family, 12, FontStyleRegular, UnitPoint, &font);
expect(Ok, status);
memset(&lf, 0xfe, sizeof(lf));
status = GdipGetLogFontA(font, graphics, &lf);
expect(Ok, status);
ok(!lstrcmpA(lf.lfFaceName, "Microsoft Sans Serif") ||
!lstrcmpA(lf.lfFaceName, "Tahoma"), "wrong face name %s\n", lf.lfFaceName);
ok(lstrcmpA(lf.lfFaceName, "MS Shell Dlg") != 0, "expected substitution of MS Shell Dlg\n");
GdipDeleteFont(font);
GdipDeleteFontFamily(family);
status = GdipCreateFontFamilyFromName(nonexistent, NULL, &family);
status = GdipCreateFontFamilyFromName(L"ThisFontShouldNotExist", NULL, &family);
ok(status == FontFamilyNotFound, "expected FontFamilyNotFound, got %d\n", status);
/* nonexistent fonts fallback to Arial, or something else if it's missing */
@ -889,7 +939,7 @@ static void test_font_substitution(void)
lstrcpyA(lf.lfFaceName, "ThisFontShouldNotExist");
font = NULL;
status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
todo_wine
todo_wine
ok(status == NotTrueTypeFont || broken(status == FileNotFound), /* before XP */
"expected NotTrueTypeFont, got %d\n", status);
/* FIXME: remove when wine is fixed */
@ -899,7 +949,7 @@ todo_wine
lf.lfFaceName[0] = 0;
font = NULL;
status = GdipCreateFontFromLogfontA(hdc, &lf, &font);
todo_wine
todo_wine
ok(status == NotTrueTypeFont || broken(status == FileNotFound), /* before XP */
"expected NotTrueTypeFont, got %d\n", status);
/* FIXME: remove when wine is fixed */
@ -911,7 +961,7 @@ todo_wine
static void test_font_transform(void)
{
static const WCHAR string[] = { 'A',0 };
static const WCHAR string[] = L"A";
GpStatus status;
HDC hdc;
LOGFONTA lf;
@ -964,7 +1014,7 @@ static void test_font_transform(void)
expect(Ok, status);
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf(height + margin_y, bounds.Height);
set_rect_empty(&rect);
set_rect_empty(&bounds);
@ -1008,7 +1058,7 @@ todo_wine
expect(Ok, status);
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf(height + margin_y, bounds.Height);
set_rect_empty(&rect);
set_rect_empty(&bounds);
@ -1029,9 +1079,9 @@ todo_wine
DriverStringOptionsCmapLookup, matrix, &bounds);
expect(Ok, status);
expectf(0.0, bounds.X);
todo_wine
todo_wine
expectf_(-300.0, bounds.Y, 0.15);
todo_wine
todo_wine
expectf(height * 3.0, bounds.Height);
/* scale + ratate matrix */
@ -1054,7 +1104,7 @@ todo_wine
expect(Ok, status);
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf(height + margin_y, bounds.Height);
set_rect_empty(&rect);
set_rect_empty(&bounds);
@ -1074,11 +1124,11 @@ todo_wine
status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
DriverStringOptionsCmapLookup, matrix, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(-43.814377, bounds.X, 0.05);
todo_wine
todo_wine
expectf_(-212.235611, bounds.Y, 0.05);
todo_wine
todo_wine
expectf_(340.847534, bounds.Height, 0.05);
/* scale + ratate + shear matrix */
@ -1088,7 +1138,7 @@ todo_wine
expect(Ok, status);
status = GdipGetLogFontA(font, graphics, &lf);
expect(Ok, status);
todo_wine
todo_wine
expect(1032, lf.lfHeight);
expect(0, lf.lfWidth);
expect_(3099, lf.lfEscapement, 1);
@ -1102,7 +1152,7 @@ todo_wine
expect(Ok, status);
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf(height + margin_y, bounds.Height);
set_rect_empty(&rect);
set_rect_empty(&bounds);
@ -1122,11 +1172,11 @@ todo_wine
status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
DriverStringOptionsCmapLookup, matrix, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(-636.706848, bounds.X, 0.05);
todo_wine
todo_wine
expectf_(-175.257523, bounds.Y, 0.05);
todo_wine
todo_wine
expectf_(1532.984985, bounds.Height, 0.05);
/* scale + ratate + shear + translate matrix */
@ -1136,7 +1186,7 @@ todo_wine
expect(Ok, status);
status = GdipGetLogFontA(font, graphics, &lf);
expect(Ok, status);
todo_wine
todo_wine
expect(1032, lf.lfHeight);
expect(0, lf.lfWidth);
expect_(3099, lf.lfEscapement, 1);
@ -1150,7 +1200,7 @@ todo_wine
expect(Ok, status);
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf(height + margin_y, bounds.Height);
set_rect_empty(&rect);
set_rect_empty(&bounds);
@ -1170,11 +1220,11 @@ todo_wine
status = GdipMeasureDriverString(graphics, (const UINT16 *)string, -1, font, pos,
DriverStringOptionsCmapLookup, matrix, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(-626.706848, bounds.X, 0.05);
todo_wine
todo_wine
expectf_(-155.257523, bounds.Y, 0.05);
todo_wine
todo_wine
expectf_(1532.984985, bounds.Height, 0.05);
GdipDeleteMatrix(matrix);
@ -1187,8 +1237,9 @@ todo_wine
static void test_GdipGetFontCollectionFamilyList(void)
{
GpFontFamily *family, *family2;
GpFontFamily *family, *family2, **families;
GpFontCollection *collection;
UINT i;
INT found, count;
GpStatus status;
@ -1228,15 +1279,31 @@ static void test_GdipGetFontCollectionFamilyList(void)
ok(found == 1, "Unexpected list count %d.\n", found);
ok(family != NULL, "Expected family instance.\n");
family = NULL;
family2 = NULL;
found = 0;
status = GdipGetFontCollectionFamilyList(collection, 1, &family2, &found);
ok(status == Ok, "Failed to get family list, status %d.\n", status);
ok(found == 1, "Unexpected list count %d.\n", found);
ok(family2 != family, "Unexpected family instance.\n");
ok(family2 == family, "Unexpected family instance.\n");
GdipDeleteFontFamily(family);
GdipDeleteFontFamily(family2);
status = GdipDeleteFontFamily(family);
expect(Ok, status);
status = GdipDeleteFontFamily(family2);
expect(Ok, status);
families = GdipAlloc((count + 1) * sizeof(*families));
found = 0;
status = GdipGetFontCollectionFamilyList(collection, count + 1, families, &found);
ok(status == Ok, "Failed to get family list, status %d.\n", status);
ok(found == count, "Unexpected list count %d, extected %d.\n", found, count);
for (i = 0; i < found; i++)
{
status = GdipDeleteFontFamily(families[i]);
expect(Ok, status);
}
GdipFree(families);
}
static void test_GdipGetFontCollectionFamilyCount(void)
@ -1260,6 +1327,107 @@ static void test_GdipGetFontCollectionFamilyCount(void)
ok(status == InvalidParameter, "Unexpected status %d.\n", status);
}
static BOOL is_family_in_collection(GpFontCollection *collection, GpFontFamily *family)
{
GpStatus status;
GpFontFamily **list;
int count, i;
BOOL found = FALSE;
status = GdipGetFontCollectionFamilyCount(collection, &count);
expect(Ok, status);
list = GdipAlloc(count * sizeof(GpFontFamily *));
status = GdipGetFontCollectionFamilyList(collection, count, list, &count);
expect(Ok, status);
for (i = 0; i < count; i++)
{
if (list[i] == family)
{
found = TRUE;
break;
}
}
GdipFree(list);
return found;
}
static void test_CloneFont(void)
{
GpStatus status;
GpFontCollection *collection, *collection2;
GpFont *font, *font2;
GpFontFamily *family, *family2;
REAL height;
Unit unit;
int style;
BOOL ret;
status = GdipNewInstalledFontCollection(&collection);
expect(Ok, status);
status = GdipNewInstalledFontCollection(&collection2);
expect(Ok, status);
ok(collection == collection2, "got %p\n", collection2);
status = GdipCreateFontFamilyFromName(L"ThisFontShouldNotExist", NULL, &family);
expect(FontFamilyNotFound, status);
status = GdipCreateFontFamilyFromName(L"ThisFontShouldNotExist", collection, &family);
expect(FontFamilyNotFound, status);
status = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, status);
ret = is_family_in_collection(collection, family);
ok(ret, "family is not in collection\n");
status = GdipCreateFont(family, 30.0f, FontStyleRegular, UnitPixel, &font);
expect(Ok, status);
status = GdipGetFontUnit(font, &unit);
expect(Ok, status);
ok(unit == UnitPixel, "got %u\n", unit);
status = GdipGetFontSize(font, &height);
expect(Ok, status);
ok(height == 30.0f, "got %f\n", height);
status = GdipGetFontStyle(font, &style);
expect(Ok, status);
ok(style == FontStyleRegular, "got %d\n", style);
status = GdipGetFamily(font, &family2);
expect(Ok, status);
ok(family == family2, "got %p\n", family2);
status = GdipCloneFont(font, &font2);
expect(Ok, status);
status = GdipGetFontUnit(font2, &unit);
expect(Ok, status);
ok(unit == UnitPixel, "got %u\n", unit);
status = GdipGetFontSize(font2, &height);
expect(Ok, status);
ok(height == 30.0f, "got %f\n", height);
status = GdipGetFontStyle(font2, &style);
expect(Ok, status);
ok(style == FontStyleRegular, "got %d\n", style);
status = GdipGetFamily(font2, &family2);
expect(Ok, status);
ok(family == family2, "got %p\n", family2);
GdipDeleteFont(font2);
GdipDeleteFont(font);
GdipDeleteFontFamily(family);
}
START_TEST(font)
{
struct GdiplusStartupInput gdiplusStartupInput;
@ -1279,6 +1447,7 @@ START_TEST(font)
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
test_CloneFont();
test_long_name();
test_font_transform();
test_font_substitution();

View file

@ -23,6 +23,7 @@
#include "objbase.h"
#include "gdiplus.h"
#include "winspool.h"
#include "wine/test.h"
#define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (INT)(expected), (INT)(got))
@ -1312,21 +1313,20 @@ static void test_GdipDrawImagePointsRect(void)
GpGraphics *graphics = NULL;
GpPointF ptf[4];
GpBitmap *bm = NULL;
BYTE rbmi[sizeof(BITMAPINFOHEADER)];
BYTE buff[400];
BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
BITMAPINFOHEADER bmihdr;
HDC hdc = GetDC( hwnd );
if (!hdc)
return;
memset(rbmi, 0, sizeof(rbmi));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = 10;
bmi->bmiHeader.biHeight = 10;
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biBitCount = 32;
bmi->bmiHeader.biCompression = BI_RGB;
status = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
memset(&bmihdr, 0, sizeof(bmihdr));
bmihdr.biSize = sizeof(BITMAPINFOHEADER);
bmihdr.biWidth = 10;
bmihdr.biHeight = 10;
bmihdr.biPlanes = 1;
bmihdr.biBitCount = 32;
bmihdr.biCompression = BI_RGB;
status = GdipCreateBitmapFromGdiDib((BITMAPINFO*)&bmihdr, buff, &bm);
expect(Ok, status);
ok(NULL != bm, "Expected bitmap to be initialized\n");
status = GdipCreateFromHDC(hdc, &graphics);
@ -2279,7 +2279,7 @@ static void test_GdipDrawString(void)
GpBrush *brush;
LOGFONTA logfont;
HDC hdc = GetDC( hwnd );
static const WCHAR string[] = {'T','e','s','t',0};
static const WCHAR string[] = L"Test";
static const PointF positions[4] = {{0,0}, {1,1}, {2,2}, {3,3}};
GpMatrix *matrix;
@ -3178,7 +3178,7 @@ static void test_GdipGetNearestColor(void)
todo_wine
ok(color == 0xffa8b8e8 ||
broken(color == 0xffa0b8e0), /* Win98/WinMe */
"Expected ffa8b8e8, got %.8x\n", color);
"Expected ffa8b8e8, got %.8lx\n", color);
GdipDeleteGraphics(graphics);
GdipDisposeImage((GpImage*)bitmap);
@ -3195,9 +3195,8 @@ static void test_string_functions(void)
GpBrush *brush;
ARGB color = 0xff000000;
HDC hdc = GetDC( hwnd );
const WCHAR fontname[] = {'T','a','h','o','m','a',0};
const WCHAR teststring[] = {'M','M',' ','M','\n','M',0};
const WCHAR teststring2[] = {'j',0};
const WCHAR teststring[] = L"MM M\nM";
const WCHAR teststring2[] = L"j";
REAL char_width, char_height;
INT codepointsfitted, linesfilled;
GpStringFormat *format;
@ -3213,7 +3212,7 @@ static void test_string_functions(void)
expect(Ok, status);
ok(graphics != NULL, "Expected graphics to be initialized\n");
status = GdipCreateFontFamilyFromName(fontname, NULL, &family);
status = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, status);
status = GdipCreateFont(family, 10.0, FontStyleRegular, UnitPixel, &font);
@ -3744,8 +3743,7 @@ static void test_GdipMeasureString(void)
{ 200.0, 600.0, 1.0, UnitPixel },
{ 200.0, 600.0, 2.0, UnitPixel },
};
static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
static const WCHAR string[] = { '1','2','3','4','5','6','7',0 };
static const WCHAR string[] = L"1234567";
GpStatus status;
GpGraphics *graphics;
GpFontFamily *family;
@ -3761,7 +3759,7 @@ static void test_GdipMeasureString(void)
status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
expect(Ok, status);
status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
status = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, status);
/* font size in pixels */
@ -3786,7 +3784,7 @@ static void test_GdipMeasureString(void)
height = units_to_pixels(font_size, td[i].unit, td[i].res_y);
if (td[i].unit != UnitDisplay)
height *= td[i].page_scale;
ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %ld (%f), got %ld\n",
i, (LONG)(height + 0.5), height, lf.lfHeight);
height = font_size + 2.0 * font_size / 6.0;
@ -3804,7 +3802,7 @@ static void test_GdipMeasureString(void)
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf_(height, bounds.Height, height / 100.0);
expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
expect(7, chars);
@ -3821,7 +3819,7 @@ todo_wine
expect(Ok, status);
expectf(50.0, bounds.X);
expectf(50.0, bounds.Y);
todo_wine
todo_wine
expectf_(height, bounds.Height, height / 100.0);
expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
expect(7, chars);
@ -3867,7 +3865,7 @@ todo_wine
else
height = units_to_pixels(font_size, font_unit, td[i].res_y);
/*trace("%.1f font units = %f pixels with %.1f dpi, page_scale %.1f\n", font_size, height, td[i].res_y, td[i].page_scale);*/
ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %d (%f), got %d\n",
ok(-lf.lfHeight == (LONG)(height + 0.5), "%u: expected %ld (%f), got %ld\n",
i, (LONG)(height + 0.5), height, lf.lfHeight);
if (td[i].unit == UnitDisplay || td[i].unit == UnitPixel)
@ -3893,7 +3891,7 @@ todo_wine
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
todo_wine
todo_wine
expectf_(height, bounds.Height, height / 85.0);
expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
expect(7, chars);
@ -3910,7 +3908,7 @@ todo_wine
expect(Ok, status);
expectf(50.0, bounds.X);
expectf(50.0, bounds.Y);
todo_wine
todo_wine
expectf_(height, bounds.Height, height / 85.0);
expectf_(bounds.Height / base_cy, bounds.Width / base_cx, 0.1);
expect(7, chars);
@ -3922,7 +3920,7 @@ todo_wine
height *= td[i].page_scale;
/*trace("%u: unit %u, %.1fx%.1f dpi, scale %.1f, height %f, pixels %f\n",
i, td[i].unit, td[i].res_x, td[i].res_y, td[i].page_scale, bounds.Height, height);*/
todo_wine
todo_wine
expectf_(100.0, height, 1.1);
status = GdipDeleteGraphics(graphics);
@ -3957,7 +3955,7 @@ todo_wine
lf.lfHeight = 0xdeadbeef;
status = GdipGetLogFontW(font, graphics, &lf);
expect(Ok, status);
ok(lf.lfHeight == -100, "%u: expected -100, got %d\n", i, lf.lfHeight);
ok(lf.lfHeight == -100, "%u: expected -100, got %ld\n", i, lf.lfHeight);
set_rect_empty(&rc);
set_rect_empty(&bounds);
@ -4141,7 +4139,7 @@ static void test_pen_thickness(void)
size = max-min+1;
ok(size == td[i].cx, "%u: expected %d, got %d\n", i, td[i].cx, size);
ok(size == td[i].cx || broken (i == 1 && size == 1), "%u: expected %d, got %d\n", i, td[i].cx, size);
min = -1;
max = -2;
@ -4166,7 +4164,7 @@ static void test_pen_thickness(void)
size = max-min+1;
ok(size == td[i].cy, "%u: expected %d, got %d\n", i, td[i].cy, size);
ok(size == td[i].cy || broken (i == 1 && size == 1), "%u: expected %d, got %d\n", i, td[i].cy, size);
status = GdipBitmapUnlockBits(u.bitmap, &bd);
expect(Ok, status);
@ -4259,8 +4257,7 @@ static void test_pen_thickness(void)
*/
static void test_font_height_scaling(void)
{
static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
static const WCHAR string[] = { '1','2','3','4','5','6','7',0 };
static const WCHAR string[] = L"1234567";
HDC hdc;
GpStringFormat *format;
CharacterRange range = { 0, 7 };
@ -4281,7 +4278,7 @@ static void test_font_height_scaling(void)
status = GdipCreateRegion(&region);
expect(Ok, status);
status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
status = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, status);
hdc = CreateCompatibleDC(0);
@ -4360,7 +4357,6 @@ static void test_font_height_scaling(void)
/* UnitPixel = 2, UnitPoint = 3, UnitInch = 4, UnitDocument = 5, UnitMillimeter = 6 */
for (gfx_unit = 2; gfx_unit <= 6; gfx_unit++)
{
static const WCHAR doubleW[2] = { 'W','W' };
RectF bounds_1, bounds_2;
REAL margin, margin_y, font_height;
int match;
@ -4379,7 +4375,7 @@ static void test_font_height_scaling(void)
status = GdipMeasureString(graphics, string, -1, font, &rect, format, &bounds, NULL, NULL);
expect(Ok, status);
/*trace("bounds: %f,%f,%f,%f\n", bounds.X, bounds.Y, bounds.Width, bounds.Height);*/
todo_wine
todo_wine
expectf_(font_height + margin_y, bounds.Height, 0.005);
ptf.X = 0;
@ -4387,25 +4383,25 @@ todo_wine
status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &ptf, 1);
expect(Ok, status);
match = fabs(100.0 - ptf.Y) <= 1.0;
todo_wine
todo_wine
ok(match, "Expected 100.0, got %f\n", ptf.Y);
/* verify the result */
ptf.Y = units_to_pixels(bounds.Height, gfx_unit, dpi);
ptf.Y /= 100.0;
match = fabs(100.0 - ptf.Y) <= 1.0;
todo_wine
todo_wine
ok(match, "Expected 100.0, got %f\n", ptf.Y);
/* bounds.width of 1 glyph: [margin]+[width]+[margin] */
set_rect_empty(&rect);
set_rect_empty(&bounds_1);
status = GdipMeasureString(graphics, doubleW, 1, font, &rect, format, &bounds_1, NULL, NULL);
status = GdipMeasureString(graphics, L"W", 1, font, &rect, format, &bounds_1, NULL, NULL);
expect(Ok, status);
/* bounds.width of 2 identical glyphs: [margin]+[width]+[width]+[margin] */
set_rect_empty(&rect);
set_rect_empty(&bounds_2);
status = GdipMeasureString(graphics, doubleW, 2, font, &rect, format, &bounds_2, NULL, NULL);
status = GdipMeasureString(graphics, L"WW", 2, font, &rect, format, &bounds_2, NULL, NULL);
expect(Ok, status);
/* margin = [bounds.width of 1] - [bounds.width of 2] / 2*/
@ -4447,10 +4443,10 @@ cleanup:
static void test_measure_string(void)
{
static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
static const WCHAR string[] = { 'A','0','1',0 };
static const WCHAR string[] = L"A01";
static const WCHAR string2[] = L"M MM";
HDC hdc;
GpStringFormat *format;
GpStringFormat *format, *format_no_wrap;
CharacterRange range;
GpRegion *region;
GpGraphics *graphics;
@ -4458,7 +4454,7 @@ static void test_measure_string(void)
GpFont *font;
GpStatus status;
RectF bounds, rect;
REAL width, height, width_1, width_2;
REAL width, height, width_1, width_2, width_MM, width_M_M;
REAL margin_x, margin_y, width_rgn, height_rgn;
int lines, glyphs;
@ -4469,7 +4465,7 @@ static void test_measure_string(void)
status = GdipCreateRegion(&region);
expect(Ok, status);
status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
status = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, status);
hdc = CreateCompatibleDC(0);
@ -4502,7 +4498,7 @@ static void test_measure_string(void)
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
expectf(width, bounds.Width);
todo_wine
todo_wine
expectf(height / 2.0, bounds.Height);
range.First = 0;
@ -4522,7 +4518,7 @@ todo_wine
expectf_(5.0 + margin_x, bounds.X, 1.0);
expectf(5.0, bounds.Y);
expectf_(width - margin_x*2.0, bounds.Width, 1.0);
todo_wine
todo_wine
expectf_(height - margin_y, bounds.Height, 1.0);
width_rgn = bounds.Width;
@ -4578,7 +4574,7 @@ todo_wine
expectf_(5.0 + margin_x, bounds.X, 1.0);
expectf(5.0, bounds.Y);
expectf_(width_1, bounds.Width, 1.0);
todo_wine
todo_wine
expectf_(height - margin_y, bounds.Height, 1.0);
status = GdipSetStringFormatFlags(format, StringFormatFlagsNoWrap | StringFormatFlagsNoClip);
@ -4621,7 +4617,7 @@ todo_wine
expectf(0.0, bounds.X);
expectf(0.0, bounds.Y);
expectf_(width, bounds.Width, 0.01);
todo_wine
todo_wine
expectf(height, bounds.Height);
set_rect_empty(&rect);
@ -4714,7 +4710,7 @@ todo_wine
expectf_(5.0 + margin_x, bounds.X, 1.0);
expectf(5.0, bounds.Y);
expectf_(width - margin_x*2.0, bounds.Width, 1.0);
todo_wine
todo_wine
expectf_(height - margin_y, bounds.Height, 1.0);
width_rgn = bounds.Width;
@ -4733,9 +4729,9 @@ todo_wine
expect(Ok, status);
expect(3, glyphs);
expect(1, lines);
todo_wine
todo_wine
expectf_(5.0 + width/2.0, bounds.X, 0.01);
todo_wine
todo_wine
expectf(5.0 + height/2.0, bounds.Y);
expectf_(width, bounds.Width, 0.01);
expectf(height, bounds.Height);
@ -4749,9 +4745,9 @@ todo_wine
expect(Ok, status);
expect(3, glyphs);
expect(1, lines);
todo_wine
todo_wine
expectf_(5.0 - width/2.0, bounds.X, 0.01);
todo_wine
todo_wine
expectf(5.0 - height/2.0, bounds.Y);
expectf_(width, bounds.Width, 0.01);
expectf(height, bounds.Height);
@ -4765,9 +4761,9 @@ todo_wine
set_rect_empty(&bounds);
status = GdipGetRegionBounds(region, graphics, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(5.0 + width_rgn/2.0, bounds.X, 1.0);
todo_wine
todo_wine
expectf_(5.0 + height_rgn/2.0, bounds.Y, 1.0);
expectf_(width_rgn, bounds.Width, 1.0);
expectf_(height_rgn, bounds.Height, 1.0);
@ -4781,9 +4777,9 @@ todo_wine
set_rect_empty(&bounds);
status = GdipGetRegionBounds(region, graphics, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(5.0 - width_rgn/2.0, bounds.X, 1.0);
todo_wine
todo_wine
expectf_(5.0 - height_rgn/2.0, bounds.Y, 1.0);
expectf_(width_rgn, bounds.Width, 1.0);
expectf_(height_rgn, bounds.Height, 1.0);
@ -4801,9 +4797,9 @@ todo_wine
expect(Ok, status);
expect(3, glyphs);
expect(1, lines);
todo_wine
todo_wine
expectf_(5.0 + width, bounds.X, 0.01);
todo_wine
todo_wine
expectf(5.0 + height, bounds.Y);
expectf_(width, bounds.Width, 0.01);
expectf(height, bounds.Height);
@ -4817,9 +4813,9 @@ todo_wine
expect(Ok, status);
expect(3, glyphs);
expect(1, lines);
todo_wine
todo_wine
expectf_(5.0 - width, bounds.X, 0.01);
todo_wine
todo_wine
expectf(5.0 - height, bounds.Y);
expectf_(width, bounds.Width, 0.01);
expectf(height, bounds.Height);
@ -4833,9 +4829,9 @@ todo_wine
set_rect_empty(&bounds);
status = GdipGetRegionBounds(region, graphics, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(5.0 + width_rgn, bounds.X, 2.0);
todo_wine
todo_wine
expectf_(5.0 + height_rgn, bounds.Y, 1.0);
expectf_(width_rgn, bounds.Width, 1.0);
expectf_(height_rgn, bounds.Height, 1.0);
@ -4849,13 +4845,60 @@ todo_wine
set_rect_empty(&bounds);
status = GdipGetRegionBounds(region, graphics, &bounds);
expect(Ok, status);
todo_wine
todo_wine
expectf_(5.0 - width_rgn, bounds.X, 2.0);
todo_wine
todo_wine
expectf_(5.0 - height_rgn, bounds.Y, 1.0);
expectf_(width_rgn, bounds.Width, 1.0);
expectf_(height_rgn, bounds.Height, 1.0);
/* Measure "MM" */
rect.X = 5.0;
rect.Y = 5.0;
rect.Width = 32000.0;
rect.Height = 32000.0;
status = GdipMeasureString(graphics, string2 + 2, 2, font, &rect, NULL, &bounds, &glyphs, &lines);
expect(Ok, status);
expect(2, glyphs);
expect(1, lines);
width_MM = bounds.Width;
/* Measure "M M" */
rect.X = 5.0;
rect.Y = 5.0;
rect.Width = 32000.0;
rect.Height = 32000.0;
status = GdipMeasureString(graphics, string2, 3, font, &rect, NULL, &bounds, &glyphs, &lines);
expect(Ok, status);
expect(3, glyphs);
expect(1, lines);
width_M_M = bounds.Width;
/* With wrap */
rect.X = 5.0;
rect.Y = 5.0;
rect.Width = width_M_M;
rect.Height = 32000.0;
status = GdipMeasureString(graphics, string2, -1, font, &rect, NULL, &bounds, &glyphs, &lines);
expect(Ok, status);
expectf_(width_MM, bounds.Width, 0.1);
expect(4, glyphs);
expect(2, lines);
/* Without wrap */
status = GdipCreateStringFormat(StringFormatFlagsNoWrap, LANG_NEUTRAL, &format_no_wrap);
expect(Ok, status);
rect.X = 5.0;
rect.Y = 5.0;
rect.Width = width_M_M;
rect.Height = 32000.0;
status = GdipMeasureString(graphics, string2, -1, font, &rect, format_no_wrap, &bounds, &glyphs, &lines);
expect(Ok, status);
expectf_(width_M_M, bounds.Width, 0.1);
expect(3, glyphs);
expect(1, lines);
status = GdipDeleteFont(font);
expect(Ok, status);
@ -4866,12 +4909,11 @@ todo_wine
GdipDeleteFontFamily(family);
GdipDeleteRegion(region);
GdipDeleteStringFormat(format);
GdipDeleteStringFormat(format_no_wrap);
}
static void test_measured_extra_space(void)
{
static const WCHAR tahomaW[] = { 'T','a','h','o','m','a',0 };
static const WCHAR string[2] = { 'W','W' };
GpStringFormat *format;
HDC hdc;
GpGraphics *graphics;
@ -4885,7 +4927,7 @@ static void test_measured_extra_space(void)
status = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
expect(Ok, status);
status = GdipCreateFontFamilyFromName(tahomaW, NULL, &family);
status = GdipCreateFontFamilyFromName(L"Tahoma", NULL, &family);
expect(Ok, status);
hdc = CreateCompatibleDC(0);
status = GdipCreateFromHDC(hdc, &graphics);
@ -4915,12 +4957,12 @@ static void test_measured_extra_space(void)
/* bounds.width of 1 glyph: [margin]+[width]+[margin] */
set_rect_empty(&rect);
set_rect_empty(&bounds_1);
status = GdipMeasureString(graphics, string, 1, font, &rect, format, &bounds_1, NULL, NULL);
status = GdipMeasureString(graphics, L"W", 1, font, &rect, format, &bounds_1, NULL, NULL);
expect(Ok, status);
/* bounds.width of 2 identical glyphs: [margin]+[width]+[width]+[margin] */
set_rect_empty(&rect);
set_rect_empty(&bounds_2);
status = GdipMeasureString(graphics, string, 2, font, &rect, format, &bounds_2, NULL, NULL);
status = GdipMeasureString(graphics, L"WW", 2, font, &rect, format, &bounds_2, NULL, NULL);
expect(Ok, status);
/* margin = [bounds.width of 1] - [bounds.width of 2] / 2*/
@ -5071,6 +5113,7 @@ static void test_clipping(void)
GpRegion *region, *region100x100;
GpMatrix *matrix;
GpRectF rect;
GpRect recti;
GpPointF ptf[4];
GpUnit unit;
HRGN hrgn;
@ -5107,6 +5150,11 @@ static void test_clipping(void)
ok(rect.X == 100.0 && rect.Y == 100.0 && rect.Width == 100.0 && rect.Height == 100.0,
"expected 100.0,100.0-100.0,100.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
status = GdipGetClipBoundsI(graphics, &recti);
expect(Ok, status);
ok(recti.X == 100 && recti.Y == 100 && recti.Width == 100 && recti.Height == 100,
"expected 100,100-100,100, got %i,%i-%i,%i\n", recti.X, recti.Y, recti.Width, recti.Height);
/* Clip region does not account for changes to gdi32 transform */
SetViewportOrgEx(hdc, 10, 10, NULL);
@ -5149,6 +5197,11 @@ static void test_clipping(void)
ok(rect.X == 45.0 && rect.Y == 20.0 && rect.Width == 50.0 && rect.Height == 25.0,
"expected 45.0,20.0-50.0,25.0, got %.2f,%.2f-%.2f,%.2f\n", rect.X, rect.Y, rect.Width, rect.Height);
status = GdipGetClipBoundsI(graphics, &recti);
expect(Ok, status);
ok(recti.X == 45 && recti.Y == 20 && recti.Width == 50 && recti.Height == 25,
"expected 45,20-50,25, got %i,%i-%i,%i\n", recti.X, recti.Y, recti.Width, recti.Height);
status = GdipSetEmpty(region);
expect(Ok, status);
status = GdipGetClip(graphics, region);
@ -6368,7 +6421,7 @@ static DWORD* GetBitmapPixelBuffer(HDC hdc, HBITMAP hbmp, int width, int height)
bi.biClrImportant = 0;
lines = GetDIBits(hdc, hbmp, 0, height, buffer, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
ok(lines == height, "Expected GetDIBits:%p,%d->%d,%d\n", buffer, height, lines, GetLastError());
ok(lines == height, "Expected GetDIBits:%p,%d->%d,%ld\n", buffer, height, lines, GetLastError());
return buffer;
}
@ -6792,6 +6845,385 @@ static void test_hdc_caching(void)
DeleteObject(hbm);
}
static void test_gdi_interop_bitmap(void)
{
GpBitmap *bitmap;
GpGraphics *graphics;
GpMatrix *transform;
GpBrush *brush;
GpStatus stat;
HDC hdc;
HBRUSH hbrush, holdbrush;
ARGB color;
stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
expect(Ok, stat);
stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
expect(Ok, stat);
stat = GdipCreateMatrix(&transform);
expect(Ok, stat);
stat = GdipSetMatrixElements(transform, 1.0, 0.0, 0.0, 1.0, 50.0, 50.0);
expect(Ok, stat);
/* GDI+: Set world transform. Should not matter to GDI. */
stat = GdipSetWorldTransform(graphics, transform);
expect(Ok, stat);
stat = GdipGetDC(graphics, &hdc);
expect(Ok, stat);
hbrush = CreateSolidBrush(0xff0000);
holdbrush = SelectObject(hdc, hbrush);
/* GDI: Draw a rectangle at physical coords (5, 5) to (12, 10). */
Rectangle(hdc, 5, 5, 12, 10);
holdbrush = SelectObject(hdc, holdbrush);
/* GDI: Set view port origin. Should not matter to GDI+. */
SetViewportOrgEx(hdc, 20, 20, NULL);
GdipReleaseDC(graphics, hdc);
stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
expect(Ok, stat);
/* GDI+: Draw a rectangle at physical coords (85, 85) to (88, 95). */
stat = GdipFillRectangleI(graphics, brush, 35, 35, 3, 10);
expect(Ok, stat);
stat = GdipDeleteBrush(brush);
expect(Ok, stat);
stat = GdipGetDC(graphics, &hdc);
expect(Ok, stat);
holdbrush = SelectObject(hdc, hbrush);
/* GDI: Draw a rectangle at physical coords (25, 25) to (30, 34).
Updated view port origin should still be in effect. */
Rectangle(hdc, 5, 5, 10, 14);
SelectObject(hdc, holdbrush);
DeleteObject(hbrush);
stat = GdipReleaseDC(graphics, hdc);
expect(Ok, stat);
stat = GdipDeleteMatrix(transform);
expect(Ok, stat);
stat = GdipBitmapGetPixel(bitmap, 6, 6, &color);
expect(Ok, stat);
expect(0xff0000ff, color);
stat = GdipBitmapGetPixel(bitmap, 26, 26, &color);
expect(Ok, stat);
expect(0xff0000ff, color);
stat = GdipBitmapGetPixel(bitmap, 86, 86, &color);
expect(Ok, stat);
expect(0xff0000ff, color);
stat = GdipDeleteGraphics(graphics);
expect(Ok, stat);
stat = GdipDisposeImage((GpImage*)bitmap);
expect(Ok, stat);
}
static void test_gdi_interop_hdc(void)
{
BITMAPINFO bmi;
GpBrush *brush;
GpGraphics *graphics;
GpMatrix *transform;
GpStatus stat;
HBITMAP hbm;
HBRUSH hbrush, holdbrush;
HDC gdi_hdc;
HDC src_hdc;
ULONG *bits;
XFORM xform = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
src_hdc = CreateCompatibleDC(0);
ok(src_hdc != NULL, "CreateCompatibleDC failed\n");
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biHeight = -100;
bmi.bmiHeader.biWidth = 100;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
hbm = CreateDIBSection(src_hdc, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
ok(hbm != NULL, "CreateDIBSection failed\n");
SelectObject(src_hdc, hbm);
SetGraphicsMode(src_hdc, GM_ADVANCED);
xform.eDx = 10.0;
xform.eDy = 10.0;
SetWorldTransform(src_hdc, &xform);
stat = GdipCreateFromHDC(src_hdc, &graphics);
expect(Ok, stat);
stat = GdipCreateMatrix(&transform);
expect(Ok, stat);
stat = GdipSetMatrixElements(transform, 1.0, 0.0, 0.0, 1.0, 40.0, 40.0);
expect(Ok, stat);
/* GDI+: Set world transform. Should not matter to GDI. */
stat = GdipSetWorldTransform(graphics, transform);
expect(Ok, stat);
stat = GdipGetDC(graphics, &gdi_hdc);
expect(Ok, stat);
ok( gdi_hdc == src_hdc, "wrong dc\n" );
/* GDI: Set GDI transform back to (0, 0).
Should not matter to GDI+. */
xform.eDx = 0.0;
xform.eDy = 0.0;
SetWorldTransform(gdi_hdc, &xform);
hbrush = CreateSolidBrush(0xff00aa);
holdbrush = SelectObject(gdi_hdc, hbrush);
/* GDI: Draw a rectangle at physical coords (5, 5) to (12, 10). */
Rectangle(gdi_hdc, 5, 5, 12, 10);
holdbrush = SelectObject(gdi_hdc, holdbrush);
/* GDI: Set GDI transform to translate (+20, +20).
Should not matter to GDI+. */
xform.eDx = 20.0;
xform.eDy = 20.0;
SetWorldTransform(gdi_hdc, &xform);
GdipReleaseDC(graphics, gdi_hdc);
/* GDI world transform should still be intact, even when back
in GDI+ mode. */
stat = GetWorldTransform(src_hdc, &xform);
expect(TRUE, stat);
expect(20.0, xform.eDx);
expect(20.0, xform.eDy);
stat = GdipCreateSolidFill((ARGB)0xffaa00ff, (GpSolidFill**)&brush);
expect(Ok, stat);
/* GDI+: Draw a rectangle at physical coords (85, 85) to (88, 95).
The fact that the GDI world transform has been updated should
not influence the GDI+ world transform. GDI+ should still apply
the world transform from the when HDC backed graphics object was
instantiated. */
stat = GdipFillRectangleI(graphics, brush, 35, 35, 3, 10);
expect(Ok, stat);
stat = GdipDeleteBrush(brush);
expect(Ok, stat);
stat = GdipGetDC(graphics, &gdi_hdc);
expect(Ok, stat);
holdbrush = SelectObject(gdi_hdc, hbrush);
/* GDI: Draw a rectangle at physical coords (25, 25) to (30, 34).
Updated transform should still be in effect. */
Rectangle(gdi_hdc, 5, 5, 10, 14);
SelectObject(gdi_hdc, holdbrush);
stat = GdipReleaseDC(graphics, gdi_hdc);
expect(Ok, stat);
GdipDeleteGraphics(graphics);
stat = GdipDeleteMatrix(transform);
expect(Ok, stat);
holdbrush = SelectObject(src_hdc, hbrush);
/* GDI: Draw a rectangle at physical coords (35, 35) to (40, 38).
Updated transform should still be in effect on src_hdc. */
Rectangle(gdi_hdc, 15, 15, 20, 18);
SelectObject(gdi_hdc, holdbrush);
DeleteObject(hbrush);
expect(0x00aa00ff, bits[6 * 100 + 6]);
expect(0x00aa00ff, bits[26 * 100 + 26]);
expect(0x00aa00ff, bits[36 * 100 + 36]);
expect(0xffaa00ff, bits[86 * 100 + 86]);
DeleteDC(src_hdc);
DeleteObject(hbm);
}
static HDC create_printer_dc(void)
{
char buffer[260];
DWORD len;
PRINTER_INFO_2A *pbuf = NULL;
DRIVER_INFO_3A *dbuf = NULL;
HANDLE hprn = 0;
HDC hdc = 0;
HMODULE winspool = LoadLibraryA("winspool.drv");
BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
BOOL (WINAPI *pClosePrinter)(HANDLE);
pGetDefaultPrinterA = (void *)GetProcAddress(winspool, "GetDefaultPrinterA");
pOpenPrinterA = (void *)GetProcAddress(winspool, "OpenPrinterA");
pGetPrinterA = (void *)GetProcAddress(winspool, "GetPrinterA");
pGetPrinterDriverA = (void *)GetProcAddress(winspool, "GetPrinterDriverA");
pClosePrinter = (void *)GetProcAddress(winspool, "ClosePrinter");
if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
goto done;
len = sizeof(buffer);
if (!pGetDefaultPrinterA(buffer, &len)) goto done;
if (!pOpenPrinterA(buffer, &hprn, NULL)) goto done;
pGetPrinterA(hprn, 2, NULL, 0, &len);
pbuf = HeapAlloc(GetProcessHeap(), 0, len);
if (!pGetPrinterA(hprn, 2, (LPBYTE)pbuf, len, &len)) goto done;
pGetPrinterDriverA(hprn, NULL, 3, NULL, 0, &len);
dbuf = HeapAlloc(GetProcessHeap(), 0, len);
if (!pGetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, len, &len)) goto done;
hdc = CreateDCA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode);
trace("hdc %p for driver '%s' printer '%s' port '%s'\n", hdc,
dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
done:
HeapFree(GetProcessHeap(), 0, dbuf);
HeapFree(GetProcessHeap(), 0, pbuf);
if (hprn) pClosePrinter(hprn);
if (winspool) FreeLibrary(winspool);
return hdc;
}
static BOOL check_rect_pixels(const DWORD *pixel, const RectF *rect, UINT width, DWORD expected, Point *failed)
{
UINT x, y;
BOOL ret = TRUE;
for (y = (UINT)rect->Y; y < (UINT)(rect->Y + rect->Height); y++)
{
for (x = (UINT)rect->X; x < (UINT)(rect->X + rect->Width); x++)
{
if (pixel[x + y * width] != expected)
{
ret = FALSE;
goto done;
}
}
}
done:
if (!ret)
{
failed->X = x;
failed->Y = y;
}
else
{
failed->X = 0;
failed->Y = 0;
}
return ret;
}
static void test_printer_dc(void)
{
HDC hdc_printer, hdc;
Status status;
GpGraphics *graphics;
REAL dpi_x, dpi_y, pixel_per_unit_x, pixel_per_unit_y;
HBITMAP bitmap;
UINT width = 16, height = 16;
GpUnit unit;
GpSolidFill *brush;
DWORD *pixel;
BOOL match;
RectF rect;
Point pt;
hdc_printer = create_printer_dc();
if (!hdc_printer)
{
skip("could not create a DC for the default printer\n");
return;
}
hdc = CreateCompatibleDC(hdc_printer);
bitmap = CreateCompatibleBitmap(hdc, width, height);
SelectObject(hdc, bitmap);
status = GdipCreateFromHDC(hdc, &graphics);
expect(Ok, status);
GdipGetPageUnit(graphics, &unit);
expect(UnitDisplay, unit);
GdipGetDpiX(graphics, &dpi_x);
GdipGetDpiY(graphics, &dpi_y);
expectf((REAL)GetDeviceCaps(hdc, LOGPIXELSX), dpi_x);
expectf((REAL)GetDeviceCaps(hdc, LOGPIXELSY), dpi_y);
/* For graphics created from printer DC, UnitDisplay specifies that a unit is 1/100 inch */
pixel_per_unit_x = dpi_x / 100.0;
pixel_per_unit_y = dpi_y / 100.0;
status = GdipCreateSolidFill((ARGB)0xffffffff, &brush);
expect(Ok, status);
status = GdipFillRectangleI(graphics, (GpBrush *)brush, 1, 1, 1, 1);
expect(Ok, status);
pixel = GetBitmapPixelBuffer(hdc, bitmap, width, height);
/* pixels at (0, 0) should all be 0 */
rect.X = 0;
rect.Y = 0;
rect.Width = pixel_per_unit_x;
rect.Height = pixel_per_unit_y;
match = check_rect_pixels(pixel, &rect, width, 0, &pt);
ok(match, "Expected pixel (%u, %u) to be %08x, got %08lx\n",
pt.X, pt.Y, 0, pixel[pt.X + pt.Y * width]);
/* pixels at (1, 1) should all be 0x00ffffff */
rect.X = pixel_per_unit_x;
rect.Y = pixel_per_unit_y;
rect.Width = pixel_per_unit_x;
rect.Height = pixel_per_unit_y;
match = check_rect_pixels(pixel, &rect, width, 0x00ffffff, &pt);
ok(match, "Expected pixel (%u, %u) to be %08x, got %08lx\n",
pt.X, pt.Y, 0x00ffffff, pixel[pt.X + pt.Y * width]);
GdipFree(pixel);
GdipDeleteBrush((GpBrush *)brush);
GdipDeleteGraphics(graphics);
DeleteObject(bitmap);
DeleteDC(hdc);
DeleteDC(hdc_printer);
}
START_TEST(graphics)
{
struct GdiplusStartupInput gdiplusStartupInput;
@ -6885,6 +7317,9 @@ START_TEST(graphics)
test_GdipGraphicsSetAbort();
test_cliphrgn_transform();
test_hdc_caching();
test_gdi_interop_bitmap();
test_gdi_interop_hdc();
test_printer_dc();
GdiplusShutdown(gdiplusToken);
DestroyWindow( hwnd );

View file

@ -75,7 +75,10 @@ typedef struct
int todo;
} path_test_t;
static void ok_path(GpPath* path, const path_test_t *expected, INT expected_size, BOOL todo_size)
#define ok_path(a,b,c,d) _ok_path_fudge(a,b,c,d,2.0,__LINE__)
#define ok_path_fudge(a,b,c,d,e) _ok_path_fudge(a,b,c,d,e,__LINE__)
static void _ok_path_fudge(GpPath* path, const path_test_t *expected, INT expected_size,
BOOL todo_size, REAL fudge, int line)
{
BYTE * types;
INT size, idx = 0, eidx = 0, numskip;
@ -88,7 +91,7 @@ static void ok_path(GpPath* path, const path_test_t *expected, INT expected_size
}
todo_wine_if (todo_size)
ok(size == expected_size, "Path size %d does not match expected size %d\n",
ok_(__FILE__,line)(size == expected_size, "Path size %d does not match expected size %d\n",
size, expected_size);
points = HeapAlloc(GetProcessHeap(), 0, size * sizeof(GpPointF));
@ -104,14 +107,14 @@ static void ok_path(GpPath* path, const path_test_t *expected, INT 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;
fabs(points[idx].X - expected[eidx].X) <= fudge &&
fabs(points[idx].Y - expected[eidx].Y) <= fudge;
stringify_point_type(expected[eidx].type, ename);
stringify_point_type(types[idx], name);
todo_wine_if (expected[eidx].todo || numskip)
ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
ok_(__FILE__,line)(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);
@ -173,6 +176,115 @@ static void test_getpathdata(void)
GdipDeletePath(path);
}
static void test_createpath2(void)
{
GpStatus status;
GpPath* path = NULL;
GpPathData data;
INT i, count, expect_count;
PointF test_line_points[] = {{1.0,1.0}, {2.0,1.0}, {2.0,2.0}};
BYTE test_line_types[] = {PathPointTypeStart, PathPointTypeLine, PathPointTypeStart};
PointF test_bez_points[] = {{1.0,1.0}, {2.0,1.0}, {3.0,1.0}, {4.0,1.0},
{5.0,1.0}, {6.0,1.0}, {7.0,1.0}};
BYTE test_bez_types[] = {PathPointTypeStart, PathPointTypeBezier,
PathPointTypeBezier, PathPointTypeBezier, PathPointTypeBezier,
PathPointTypeBezier, PathPointTypeBezier};
status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, &path);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
expect(2, count);
GdipDeletePath(path);
status = GdipCreatePath2(test_line_points, test_line_types, 1, FillModeAlternate, &path);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
expect(1, count);
GdipDeletePath(path);
path = (void *)0xdeadbeef;
status = GdipCreatePath2(test_line_points, test_line_types, 0, FillModeAlternate, &path);
expect(OutOfMemory, status);
ok(!path, "Expected NULL, got %p\n", path);
if(path && path != (void *)0xdeadbeef)
GdipDeletePath(path);
path = (void *)0xdeadbeef;
status = GdipCreatePath2(test_line_points, test_line_types, -1, FillModeAlternate, &path);
expect(OutOfMemory, status);
ok(!path, "Expected NULL, got %p\n", path);
if(path && path != (void *)0xdeadbeef)
GdipDeletePath(path);
path = (void *)0xdeadbeef;
status = GdipCreatePath2(NULL, test_line_types, 2, FillModeAlternate, &path);
expect(InvalidParameter, status);
ok(path == (void *)0xdeadbeef, "Expected %p, got %p\n", (void *)0xdeadbeef, path);
if(path && path != (void *)0xdeadbeef)
GdipDeletePath(path);
path = (void *)0xdeadbeef;
status = GdipCreatePath2(test_line_points, NULL, 2, FillModeAlternate, &path);
expect(InvalidParameter, status);
ok(path == (void *)0xdeadbeef, "Expected %p, got %p\n", (void *)0xdeadbeef, path);
if(path && path != (void *)0xdeadbeef)
GdipDeletePath(path);
status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, NULL);
expect(InvalidParameter, status);
/* Multi-point paths should not end with Start */
status = GdipCreatePath2(test_line_points, test_line_types, 3, FillModeAlternate, &path);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
expect(0, count);
GdipDeletePath(path);
/* Zero-length line points do not get altered */
test_line_points[1].X = test_line_points[0].X;
test_line_points[1].Y = test_line_points[0].Y;
status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, &path);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
expect(2, count);
GdipDeletePath(path);
/* The type of the first point is always converted to PathPointTypeStart */
test_line_types[0] = PathPointTypeLine;
status = GdipCreatePath2(test_line_points, test_line_types, 1, FillModeAlternate, &path);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
expect(1, count);
data.Count = count;
data.Types = GdipAlloc(sizeof(BYTE) * count);
data.Points = GdipAlloc(sizeof(PointF) * count);
status = GdipGetPathData(path, &data);
expect(Ok, status);
expect((data.Points[0].X == 1.0) && (data.Points[0].Y == 1.0), TRUE);
expect(data.Types[0], PathPointTypeStart);
GdipFree(data.Points);
GdipFree(data.Types);
GdipDeletePath(path);
/* Bezier points must come in groups of three */
for(i = 2; i <= 7; i++) {
expect_count = (i % 3 == 1) ? i : 0;
status = GdipCreatePath2(test_bez_points, test_bez_types, i, FillModeAlternate, &path);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
expect(expect_count, count);
GdipDeletePath(path);
}
}
static path_test_t line2_path[] = {
{0.0, 50.0, PathPointTypeStart, 0, 0}, /*0*/
{5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/
@ -198,6 +310,16 @@ static void test_line2(void)
}
GdipCreatePath(FillModeAlternate, &path);
status = GdipAddPathLine2(NULL, line2_points, 2);
expect(InvalidParameter, status);
status = GdipAddPathLine2(path, NULL, 2);
expect(InvalidParameter, status);
status = GdipAddPathLine2(path, line2_points, 0);
expect(InvalidParameter, status);
status = GdipAddPathLine2(path, line2_points, -1);
expect(InvalidParameter, status);
status = GdipAddPathLine2(path, line2_points, 3);
expect(Ok, status);
status = GdipAddPathLine2(path, &(line2_points[3]), 3);
@ -209,6 +331,69 @@ static void test_line2(void)
ok_path(path, line2_path, ARRAY_SIZE(line2_path), FALSE);
GdipResetPath(path);
status = GdipAddPathLine2(path, line2_points, 3);
expect(Ok, status);
status = GdipAddPathLine2(path, &(line2_points[2]), 3);
expect(Ok, status);
ok_path(path, line2_path, 5, FALSE);
GdipDeletePath(path);
}
static path_test_t bezier_path[] = {
{10.0, 10.0, PathPointTypeStart, 0, 0}, /*0*/
{20.0, 10.0, PathPointTypeBezier, 0, 0}, /*1*/
{20.0, 20.0, PathPointTypeBezier, 0, 0}, /*2*/
{30.0, 20.0, PathPointTypeBezier, 0, 0}, /*3*/
{40.0, 20.0, PathPointTypeBezier, 0, 0}, /*4*/
{40.0, 30.0, PathPointTypeBezier, 0, 0}, /*5*/
{50.0, 30.0, PathPointTypeBezier, 0, 0}, /*6*/
{50.0, 10.0, PathPointTypeLine, 0, 0}, /*7*/
{60.0, 10.0, PathPointTypeBezier, 0, 0}, /*8*/
{60.0, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
{70.0, 20.0, PathPointTypeBezier, 0, 0} /*10*/
};
static void test_bezier(void)
{
GpStatus status;
GpPath* path;
GdipCreatePath(FillModeAlternate, &path);
status = GdipAddPathBezier(path, 10.0, 10.0, 20.0, 10.0, 20.0, 20.0, 30.0, 20.0);
expect(Ok, status);
status = GdipAddPathBezier(path, 30.0, 20.0, 40.0, 20.0, 40.0, 30.0, 50.0, 30.0);
expect(Ok, status);
status = GdipAddPathBezier(path, 50.0, 10.0, 60.0, 10.0, 60.0, 20.0, 70.0, 20.0);
expect(Ok, status);
ok_path(path, bezier_path, ARRAY_SIZE(bezier_path), FALSE);
GdipDeletePath(path);
}
static void test_beziers(void)
{
GpStatus status;
GpPath* path;
PointF bezier_points1[] = {{10.0,10.0}, {20.0,10.0}, {20.0,20.0}, {30.0,20.0}};
PointF bezier_points2[] = {{30.0,20.0}, {40.0,20.0}, {40.0,30.0}, {50.0,30.0}};
PointF bezier_points3[] = {{50.0,10.0}, {60.0,10.0}, {60.0,20.0}, {70.0,20.0}};
GdipCreatePath(FillModeAlternate, &path);
status = GdipAddPathBeziers(path, bezier_points1, 4);
expect(Ok, status);
status = GdipAddPathBeziers(path, bezier_points2, 4);
expect(Ok, status);
status = GdipAddPathBeziers(path, bezier_points3, 4);
expect(Ok, status);
ok_path(path, bezier_path, ARRAY_SIZE(bezier_path), FALSE);
GdipDeletePath(path);
}
@ -252,6 +437,13 @@ static path_test_t arc_path[] = {
{450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/
{540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/
};
static path_test_t arc_path2[] = {
{1.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
{1.0, 0.5, PathPointTypeLine, 0, 0}, /*1*/
{1.0, 0.776142, PathPointTypeBezier, 0, 0}, /*2*/
{0.776142, 1.0, PathPointTypeBezier, 0, 0}, /*3*/
{0.5, 1.0, PathPointTypeBezier, 0, 0} /*4*/
};
static void test_arc(void)
{
@ -280,6 +472,13 @@ static void test_arc(void)
ok_path(path, arc_path, ARRAY_SIZE(arc_path), FALSE);
GdipResetPath(path);
GdipAddPathLine(path, 1.0, 0.0, 1.0, 0.5);
status = GdipAddPathArc(path, 0.0, 0.0, 1.0, 1.0, 0.0, 90.0);
expect(Ok, status);
ok_path_fudge(path, arc_path2, ARRAY_SIZE(arc_path2), FALSE, 0.000005);
GdipDeletePath(path);
}
@ -547,7 +746,8 @@ static path_test_t linei_path[] = {
{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*/
{36.00, 38.00, PathPointTypeLine, 0, 0}, /*12*/
{39.00, 40.00, PathPointTypeLine, 0, 0} /*13*/
};
static void test_linei(void)
@ -564,6 +764,8 @@ static void test_linei(void)
GdipClosePathFigure(path);
status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
expect(Ok, status);
status = GdipAddPathLineI(path, 36, 38, 39, 40);
expect(Ok, status);
ok_path(path, linei_path, ARRAY_SIZE(linei_path), FALSE);
@ -1076,6 +1278,13 @@ static path_test_t widenline_dash_path[] = {
{45.0, 10.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
};
static path_test_t widenline_unit_path[] = {
{5.0, 9.5, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 9.5, PathPointTypeLine, 0, 0}, /*1*/
{50.0, 10.5, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 10.5, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
};
static void test_widen(void)
{
GpStatus status;
@ -1238,13 +1447,313 @@ static void test_widen(void)
status = GdipGetPointCount(path, &count);
expect(Ok, status);
todo_wine expect(0, count);
ok(count == 0 || broken(count == 4), "expected 0, got %i\n", count);
/* pen width = 0 pixels, UnitWorld - result is a path 1 unit wide */
GdipDeletePen(pen);
status = GdipCreatePen1(0xffffffff, 0.0, UnitWorld, &pen);
expect(Ok, status);
status = GdipResetPath(path);
expect(Ok, status);
status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
expect(Ok, status);
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
status = GdipGetPointCount(path, &count);
expect(Ok, status);
ok_path_fudge(path, widenline_unit_path, ARRAY_SIZE(widenline_unit_path), FALSE, 0.000005);
GdipDeleteMatrix(m);
GdipDeletePen(pen);
GdipDeletePath(path);
}
static path_test_t widenline_capflat_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
};
static path_test_t widenline_capsquare_path[] = {
{0.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{55.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{55.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{0.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
};
static path_test_t widenline_capround_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{52.761421, 5.0, PathPointTypeBezier, 0, 0}, /*2*/
{55.0, 7.238576, PathPointTypeBezier, 0, 0}, /*3*/
{55.0, 10.0, PathPointTypeBezier, 0, 0}, /*4*/
{55.0, 12.761423, PathPointTypeBezier, 0, 0}, /*5*/
{52.761421, 15.0, PathPointTypeBezier, 0, 0}, /*6*/
{50.0, 15.0, PathPointTypeBezier, 0, 0}, /*7*/
{5.0, 15.0, PathPointTypeLine, 0, 0}, /*8*/
{2.238576, 15.0, PathPointTypeBezier, 0, 0}, /*9*/
{0.0, 12.761423, PathPointTypeBezier, 0, 0}, /*10*/
{0.0, 10.0, PathPointTypeBezier, 0, 0}, /*11*/
{0.0, 7.238576, PathPointTypeBezier, 0, 0}, /*12*/
{2.238576, 5.0, PathPointTypeBezier, 0, 0}, /*13*/
{5.0, 5.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*14*/
};
static path_test_t widenline_captriangle_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{55.0, 10.0, PathPointTypeLine, 0, 0}, /*2*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*3*/
{5.0, 15.0, PathPointTypeLine, 0, 0}, /*4*/
{0.0, 10.0, PathPointTypeLine, 0, 0}, /*5*/
{5.0, 5.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*6*/
};
static path_test_t widenline_capsquareanchor_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
{12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*4*/
{12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*5*/
{-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*6*/
{-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
{42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*8*/
{42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*9*/
{57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*10*/
{57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
};
static path_test_t widenline_caproundanchor_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
{5.0, 20.0, PathPointTypeStart, 0, 0}, /*4*/
{-0.522847, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
{-5.0, 15.522846, PathPointTypeBezier, 0, 0}, /*6*/
{-5.0, 10.0, PathPointTypeBezier, 0, 0}, /*7*/
{-5.0, 4.477152, PathPointTypeBezier, 0, 0}, /*8*/
{-0.522847, 0.0, PathPointTypeBezier, 0, 0}, /*9*/
{5.0, 0.0, PathPointTypeBezier, 0, 0}, /*10*/
{10.522847, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
{15.0, 4.477152, PathPointTypeBezier, 0, 0}, /*12*/
{15.0, 10.0, PathPointTypeBezier, 0, 0}, /*13*/
{15.0, 15.522846, PathPointTypeBezier, 0, 0}, /*14*/
{10.522847, 20.0, PathPointTypeBezier, 0, 0}, /*15*/
{5.0, 20.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*16*/
{50.0, 0.0, PathPointTypeStart, 0, 0}, /*17*/
{55.522846, 0.0, PathPointTypeBezier, 0, 0}, /*18*/
{60.0, 4.477153, PathPointTypeBezier, 0, 0}, /*19*/
{60.0, 10.0, PathPointTypeBezier, 0, 0}, /*20*/
{60.0, 15.522847, PathPointTypeBezier, 0, 0}, /*21*/
{55.522846, 20.0, PathPointTypeBezier, 0, 0}, /*22*/
{50.0, 20.0, PathPointTypeBezier, 0, 0}, /*23*/
{44.477150, 20.0, PathPointTypeBezier, 0, 0}, /*24*/
{40.0, 15.522847, PathPointTypeBezier, 0, 0}, /*25*/
{40.0, 10.0, PathPointTypeBezier, 0, 0}, /*26*/
{40.0, 4.477153, PathPointTypeBezier, 0, 0}, /*27*/
{44.477150, 0.0, PathPointTypeBezier, 0, 0}, /*28*/
{50.0, 0.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*29*/
};
static path_test_t widenline_capdiamondanchor_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
{-5.0, 10.0, PathPointTypeStart, 0, 0}, /*4*/
{5.0, 0.0, PathPointTypeLine, 0, 0}, /*5*/
{15.0, 10.0, PathPointTypeLine, 0, 0}, /*6*/
{5.0, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
{60.0, 10.0, PathPointTypeStart, 0, 0}, /*8*/
{50.0, 20.0, PathPointTypeLine, 0, 0}, /*9*/
{40.0, 10.0, PathPointTypeLine, 0, 0}, /*10*/
{50.0, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
};
static path_test_t widenline_caparrowanchor_path[] = {
{15.0, 5.0, PathPointTypeStart, 0, 1}, /*0*/
{40.0, 5.0, PathPointTypeLine, 0, 1}, /*1*/
{40.0, 15.0, PathPointTypeLine, 0, 1}, /*2*/
{15.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 1}, /*3*/
{5.0, 10.0, PathPointTypeStart, 0, 0}, /*4*/
{22.320507, 0.0, PathPointTypeLine, 0, 0}, /*5*/
{22.320507, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*6*/
{50.0, 10.0, PathPointTypeStart, 0, 0}, /*7*/
{32.679489, 20.0, PathPointTypeLine, 0, 0}, /*8*/
{32.679489, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*9*/
};
static path_test_t widenline_capsquareanchor_thin_path[] = {
{6.414213, 8.585786, PathPointTypeStart, 0, 0}, /*0*/
{6.414213, 11.414213, PathPointTypeLine, 0, 0}, /*1*/
{3.585786, 11.414213, PathPointTypeLine, 0, 0}, /*2*/
{3.585786, 8.585786, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
{48.585785, 11.414213, PathPointTypeStart, 0, 0}, /*4*/
{48.585785, 8.585786, PathPointTypeLine, 0, 0}, /*5*/
{51.414211, 8.585786, PathPointTypeLine, 0, 0}, /*6*/
{51.414211, 11.414213, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
};
static path_test_t widenline_capsquareanchor_dashed_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{35.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{35.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
{45.0, 5.0, PathPointTypeStart, 0, 0}, /*4*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*5*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*6*/
{45.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
{12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*8*/
{12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*9*/
{-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*10*/
{-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
{42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*12*/
{42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*13*/
{57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*14*/
{57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*15*/
};
static path_test_t widenline_capsquareanchor_multifigure_path[] = {
{5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
{25.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
{25.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
{5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
{30.0, 5.0, PathPointTypeStart, 0, 0}, /*4*/
{50.0, 5.0, PathPointTypeLine, 0, 0}, /*5*/
{50.0, 15.0, PathPointTypeLine, 0, 0}, /*6*/
{30.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
{12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*8*/
{12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*9*/
{-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*10*/
{-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
{17.928930, 17.071068, PathPointTypeStart, 0, 0}, /*12*/
{17.928930, 2.928932, PathPointTypeLine, 0, 0}, /*13*/
{32.071068, 2.928932, PathPointTypeLine, 0, 0}, /*14*/
{32.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*15*/
{37.071068, 2.928932, PathPointTypeStart, 0, 0}, /*16*/
{37.071068, 17.071066, PathPointTypeLine, 0, 0}, /*17*/
{22.928930, 17.071066, PathPointTypeLine, 0, 0}, /*18*/
{22.928930, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*19*/
{42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*20*/
{42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*21*/
{57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*22*/
{57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*23*/
};
static void test_widen_cap(void)
{
struct
{
LineCap type;
REAL line_width;
const path_test_t *expected;
INT expected_size;
BOOL dashed;
BOOL todo_size;
}
caps[] =
{
{ LineCapFlat, 10.0, widenline_capflat_path,
ARRAY_SIZE(widenline_capflat_path) },
{ LineCapSquare, 10.0, widenline_capsquare_path,
ARRAY_SIZE(widenline_capsquare_path) },
{ LineCapRound, 10.0, widenline_capround_path,
ARRAY_SIZE(widenline_capround_path) },
{ LineCapTriangle, 10.0, widenline_captriangle_path,
ARRAY_SIZE(widenline_captriangle_path) },
{ LineCapNoAnchor, 10.0, widenline_capflat_path,
ARRAY_SIZE(widenline_capflat_path) },
{ LineCapSquareAnchor, 10.0, widenline_capsquareanchor_path,
ARRAY_SIZE(widenline_capsquareanchor_path) },
{ LineCapRoundAnchor, 10.0, widenline_caproundanchor_path,
ARRAY_SIZE(widenline_caproundanchor_path) },
{ LineCapDiamondAnchor, 10.0, widenline_capdiamondanchor_path,
ARRAY_SIZE(widenline_capdiamondanchor_path) },
{ LineCapArrowAnchor, 10.0, widenline_caparrowanchor_path,
ARRAY_SIZE(widenline_caparrowanchor_path), FALSE, TRUE },
{ LineCapSquareAnchor, 0.0, widenline_capsquareanchor_thin_path,
ARRAY_SIZE(widenline_capsquareanchor_thin_path) },
{ LineCapSquareAnchor, 10.0, widenline_capsquareanchor_dashed_path,
ARRAY_SIZE(widenline_capsquareanchor_dashed_path), TRUE },
};
GpStatus status;
GpPath *path;
GpPen *pen;
int i;
status = GdipCreatePath(FillModeAlternate, &path);
expect(Ok, status);
for (i = 0; i < ARRAY_SIZE(caps); i++)
{
status = GdipCreatePen1(0xffffffff, caps[i].line_width, UnitPixel, &pen);
expect(Ok, status);
if (caps[i].dashed)
{
status = GdipSetPenDashStyle(pen, DashStyleDash);
expect(Ok, status);
}
status = GdipResetPath(path);
expect(Ok, status);
status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
expect(Ok, status);
status = GdipSetPenStartCap(pen, caps[i].type);
expect(Ok, status);
status = GdipSetPenEndCap(pen, caps[i].type);
expect(Ok, status);
status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
expect(Ok, status);
if (i == 9)
{
INT size;
status = GdipGetPointCount(path, &size);
expect(Ok, status);
ok(size == caps[i].expected_size || broken(size == 12), "unexpected path size %i\n", size);
if (size == 12)
{
GdipDeletePen(pen);
continue;
}
}
ok_path_fudge(path, caps[i].expected, caps[i].expected_size, caps[i].todo_size, 0.000005);
GdipDeletePen(pen);
}
status = GdipCreatePen1(0xffffffff, 10.0, UnitPixel, &pen);
expect(Ok, status);
status = GdipResetPath(path);
expect(Ok, status);
status = GdipAddPathLine(path, 5.0, 10.0, 25.0, 10.0);
expect(Ok, status);
status = GdipStartPathFigure(path);
expect(Ok, status);
status = GdipAddPathLine(path, 30.0, 10.0, 50.0, 10.0);
expect(Ok, status);
status = GdipSetPenStartCap(pen, LineCapSquareAnchor);
expect(Ok, status);
status = GdipSetPenEndCap(pen, LineCapSquareAnchor);
expect(Ok, status);
status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
expect(Ok, status);
ok_path_fudge(path, widenline_capsquareanchor_multifigure_path,
ARRAY_SIZE(widenline_capsquareanchor_multifigure_path), FALSE, 0.000005);
GdipDeletePen(pen);
GdipDeletePath(path);
}
static void test_isvisible(void)
{
GpPath *path;
@ -1370,7 +1879,10 @@ START_TEST(graphicspath)
test_constructor_destructor();
test_getpathdata();
test_createpath2();
test_line2();
test_bezier();
test_beziers();
test_arc();
test_worldbounds();
test_pathpath();
@ -1385,6 +1897,7 @@ START_TEST(graphicspath)
test_addpie();
test_flatten();
test_widen();
test_widen_cap();
test_isvisible();
test_empty_rect();

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,11 @@
#include "gdiplus.h"
#include "wine/test.h"
#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
#define expect(expected,got) expect_(__LINE__, expected, got)
static inline void expect_(unsigned line, DWORD expected, DWORD got)
{
ok_(__FILE__, line)(expected == got, "Expected %.8ld, got %.8ld\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)
@ -175,7 +179,7 @@ static void test_dasharray(void)
dashes[4] = 14.0;
dashes[5] = -100.0;
dashes[6] = -100.0;
dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 0.0;
dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 1.0;
/* setting the array sets the type to custom */
GdipGetPenDashStyle(pen, &style);
@ -218,10 +222,13 @@ static void test_dasharray(void)
/* Some invalid array values. */
status = GdipSetPenDashArray(pen, &dashes[7], 5);
expect(InvalidParameter, status);
expect(Ok, status);
dashes[9] = -1.0;
status = GdipSetPenDashArray(pen, &dashes[7], 5);
expect(InvalidParameter, status);
dashes[9] = 0.0;
status = GdipSetPenDashArray(pen, &dashes[7], 5);
expect(InvalidParameter, status);
/* Try to set with count = 0. */
GdipSetPenDashStyle(pen, DashStyleDot);

View file

@ -33,11 +33,15 @@
#define RGNDATA_MAGIC 0xdbc01001
#define RGNDATA_MAGIC2 0xdbc01002
#define expect(expected, got) ok((got) == (expected), "Expected %.8x, got %.8x\n", (expected), (got))
#define expect(expected,got) expect_(__LINE__, expected, got)
static inline void expect_(unsigned line, DWORD expected, DWORD got)
{
ok_(__FILE__, line)(expected == got, "Expected %ld, got %ld\n", expected, got);
}
#define expectf_(expected, got, precision) ok(fabs((expected) - (got)) < (precision), "Expected %f, got %f\n", (expected), (got))
#define expectf(expected, got) expectf_((expected), (got), 0.001)
#define expect_magic(value) ok(broken(*(value) == RGNDATA_MAGIC) || *(value) == RGNDATA_MAGIC2, "Expected a known magic value, got %8x\n", *(value))
#define expect_magic(value) ok(broken(*(value) == RGNDATA_MAGIC) || *(value) == RGNDATA_MAGIC2, "Expected a known magic value, got %8lx\n", *(value))
#define expect_dword(value, expected) expect((expected), *(value))
#define expect_float(value, expected) expectf((expected), *(FLOAT *)(value))
@ -59,19 +63,19 @@ static void verify_region(HRGN hrgn, const RECT *rc)
ret = GetRegionData(hrgn, 0, NULL);
if (IsRectEmpty(rc))
ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %lu\n", ret);
else
ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %lu\n", ret);
if (!ret) return;
ret = GetRegionData(hrgn, sizeof(rgn), &rgn.data);
if (IsRectEmpty(rc))
ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %lu\n", ret);
else
ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %lu\n", ret);
trace("size %u, type %u, count %u, rgn size %u, bound %s\n",
trace("size %lu, type %lu, count %lu, rgn size %lu, bound %s\n",
rgn.data.rdh.dwSize, rgn.data.rdh.iType,
rgn.data.rdh.nCount, rgn.data.rdh.nRgnSize,
wine_dbgstr_rect(&rgn.data.rdh.rcBound));
@ -83,17 +87,17 @@ static void verify_region(HRGN hrgn, const RECT *rc)
wine_dbgstr_rect(rc), wine_dbgstr_rect(rect));
}
ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", rgn.data.rdh.dwSize);
ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn.data.rdh.iType);
ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %lu\n", rgn.data.rdh.dwSize);
ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %lu\n", rgn.data.rdh.iType);
if (IsRectEmpty(rc))
{
ok(rgn.data.rdh.nCount == 0, "expected 0, got %u\n", rgn.data.rdh.nCount);
ok(rgn.data.rdh.nRgnSize == 0, "expected 0, got %u\n", rgn.data.rdh.nRgnSize);
ok(rgn.data.rdh.nCount == 0, "expected 0, got %lu\n", rgn.data.rdh.nCount);
ok(rgn.data.rdh.nRgnSize == 0, "expected 0, got %lu\n", rgn.data.rdh.nRgnSize);
}
else
{
ok(rgn.data.rdh.nCount == 1, "expected 1, got %u\n", rgn.data.rdh.nCount);
ok(rgn.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn.data.rdh.nRgnSize);
ok(rgn.data.rdh.nCount == 1, "expected 1, got %lu\n", rgn.data.rdh.nCount);
ok(rgn.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %lu\n", rgn.data.rdh.nRgnSize);
}
ok(EqualRect(&rgn.data.rdh.rcBound, rc), "expected %s, got %s\n",
wine_dbgstr_rect(rc), wine_dbgstr_rect(&rgn.data.rdh.rcBound));
@ -142,11 +146,11 @@ static void test_region_data(DWORD *data, UINT size, INT line)
for (i = 0; i < size - 1; i++)
{
if (i == 1) continue; /* data[1] never matches */
ok_(__FILE__, line)(data[i] == buf[i], "off %u: %#x != %#x\n", i, data[i], buf[i]);
ok_(__FILE__, line)(data[i] == buf[i], "off %u: %#lx != %#lx\n", i, data[i], buf[i]);
}
/* some Windows versions fail to properly clear the aligned DWORD */
ok_(__FILE__, line)(data[size - 1] == buf[size - 1] || broken(data[size - 1] != buf[size - 1]),
"off %u: %#x != %#x\n", size - 1, data[size - 1], buf[size - 1]);
"off %u: %#lx != %#lx\n", size - 1, data[size - 1], buf[size - 1]);
GdipDeleteRegion(region);
}
@ -187,7 +191,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
@ -205,7 +209,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_EMPTY_RECT);
@ -223,7 +227,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
@ -248,7 +252,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(36, needed);
expect_dword(buf, 28);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_RECT);
@ -304,7 +308,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(156, needed);
expect_dword(buf, 148);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 10);
expect_dword(buf + 4, CombineModeExclude);
@ -367,7 +371,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(72, needed);
expect_dword(buf, 64);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -402,7 +406,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(96, needed);
expect_dword(buf, 88);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 2);
expect_dword(buf + 4, CombineModeIntersect);
@ -447,7 +451,7 @@ static void test_getregiondata(void)
expect(Ok, status);
expect(36, needed);
expect_dword(buf, 28);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -457,7 +461,7 @@ static void test_getregiondata(void)
expect_dword(buf + 7, 0);
/* flags 0 means that a path is an array of FLOATs */
ok(*(buf + 8) == 0x4000 /* before win7 */ || *(buf + 8) == 0,
"expected 0x4000 or 0, got %08x\n", *(buf + 8));
"expected 0x4000 or 0, got %08lx\n", *(buf + 8));
expect_dword(buf + 10, 0xeeeeeeee);
test_region_data(buf, needed, __LINE__);
@ -489,7 +493,7 @@ static void test_getregiondata(void)
expect(Ok, status);
expect(56, needed);
expect_dword(buf, 48);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3 , 0);
expect_dword(buf + 4 , RGNDATA_PATH);
@ -563,7 +567,7 @@ static void test_getregiondata(void)
expect(Ok, status);
expect(72, needed);
expect_dword(buf, 64);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -614,7 +618,7 @@ static void test_getregiondata(void)
expect(Ok, status);
expect(116, needed);
expect_dword(buf, 108);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 2);
expect_dword(buf + 4, CombineModeUnion);
@ -641,8 +645,8 @@ static void test_getregiondata(void)
expect_float(buf + 25, 50.0);
expect_float(buf + 26, 70.2);
expect_dword(buf + 27, 0x01010100);
ok(*(buf + 28) == 0x00000101 || *(buf + 28) == 0x43050101 /* Win 7 */,
"expected 00000101 or 43050101 got %08x\n", *(buf + 28));
ok((*(buf + 28) & 0xffff) == 0x0101,
"expected ????0101 got %08lx\n", *(buf + 28));
expect_dword(buf + 29, 0xeeeeeeee);
test_region_data(buf, needed, __LINE__);
@ -668,7 +672,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(56, needed);
expect_dword(buf, 48);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -712,7 +716,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(72, needed);
expect_dword(buf, 64);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -758,7 +762,7 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(136, needed);
expect_dword(buf, 128);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -791,9 +795,8 @@ static void test_getregiondata(void)
expect_float(buf + 30, 789.799561);
expect_dword(buf + 31, 0x03030300);
expect_dword(buf + 32, 0x03030301);
ok(*(buf + 33) == 0x00030303 /* before win7 */ ||
*(buf + 33) == 0x43030303 /* 32-bit win7 */ || *(buf + 33) == 0x4c030303 /* 64-bit win7 */,
"expected 0x00030303 or 0x43030303 or 0x4c030303 got %08x\n", *(buf + 33));
ok((*(buf + 33) & 0xffffff) == 0x030303,
"expected 0x??030303 got %08lx\n", *(buf + 33));
expect_dword(buf + 34, 0xeeeeeeee);
test_region_data(buf, needed, __LINE__);
@ -921,7 +924,7 @@ static void test_combinereplace(void)
expect(Ok, status);
expect(36, needed);
expect_dword(buf, 28);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_RECT);
@ -941,7 +944,7 @@ static void test_combinereplace(void)
expect(Ok, status);
expect(156, needed);
expect_dword(buf, 148);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_PATH);
@ -960,7 +963,7 @@ static void test_combinereplace(void)
expect(Ok, status);
expect(20, needed);
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
@ -987,7 +990,7 @@ static void test_combinereplace(void)
expect(Ok, status);
expect(180, needed);
expect_dword(buf, 172);
trace("buf[1] = %08x\n", buf[1]);
trace("buf[1] = %08lx\n", buf[1]);
expect_magic(buf + 2);
expect_dword(buf + 3, 2);
expect_dword(buf + 4, CombineModeUnion);
@ -1446,14 +1449,14 @@ static void test_translate(void)
static DWORD get_region_type(GpRegion *region)
{
DWORD *data;
DWORD size;
UINT size;
DWORD result;
DWORD status;
status = GdipGetRegionDataSize(region, &size);
expect(Ok, status);
data = GdipAlloc(size);
status = GdipGetRegionData(region, (BYTE*)data, size, NULL);
ok(status == Ok || status == InsufficientBuffer, "unexpected status 0x%x\n", status);
ok(status == Ok || status == InsufficientBuffer, "unexpected status 0x%lx\n", status);
result = data[4];
GdipFree(data);
return result;
@ -1594,7 +1597,7 @@ static void test_scans(void)
GpMatrix *matrix;
GpRectF rectf;
GpStatus status;
ULONG count=80085;
UINT count=80085;
INT icount;
GpRectF scans[2];
GpRect scansi[2];

View file

@ -20,3 +20,6 @@
/* @makedep: wine_longname.ttf */
1 RCDATA wine_longname.ttf
/* @makedep: wine_testfont0.ttf */
2 RCDATA wine_testfont0.ttf

View file

@ -0,0 +1,69 @@
SplineFontDB: 3.0
FontName: winegdiptestfont0
FullName: Wine GDI+ Test Font 0
FamilyName: winegdiptestfont
Weight: Regular
Copyright: Copyright (c) 2020, Shawn M. Chapla
UComments: "2020-7-15: Created with FontForge (http://fontforge.org)"
Version: 001.000
ItalicAngle: 0
UnderlinePosition: -100
UnderlineWidth: 50
Ascent: 800
Descent: 200
InvalidEm: 0
LayerCount: 2
Layer: 0 0 "Back" 1
Layer: 1 0 "Fore" 0
XUID: [1021 445 409452897 2998051]
StyleMap: 0x0000
FSType: 0
OS2Version: 0
OS2_WeightWidthSlopeOnly: 0
OS2_UseTypoMetrics: 1
CreationTime: 1594833132
ModificationTime: 1594833348
OS2TypoAscent: 0
OS2TypoAOffset: 1
OS2TypoDescent: 0
OS2TypoDOffset: 1
OS2TypoLinegap: 90
OS2WinAscent: 0
OS2WinAOffset: 1
OS2WinDescent: 0
OS2WinDOffset: 1
HheadAscent: 0
HheadAOffset: 1
HheadDescent: 0
HheadDOffset: 1
MarkAttachClasses: 1
DEI: 91125
Encoding: ISO8859-1
UnicodeInterp: none
NameList: AGL For New Fonts
DisplaySize: -48
AntiAlias: 1
FitToEm: 0
WinInfo: 0 16 4
BeginPrivate: 0
EndPrivate
BeginChars: 256 1
StartChar: uni0000
Encoding: 0 0 0
Width: 2977
VWidth: 0
Flags: HWO
LayerCount: 2
Fore
SplineSet
247 690 m 5
748 690 l 5
748 72 l 5
247 72 l 5
247 690 l 5
EndSplineSet
Validated: 1
EndChar
EndChars
EndSplineFont

Binary file not shown.

View file

@ -1103,6 +1103,8 @@ extern "C"
GpStatus WINGDIPAPI
GdipGetMetafileHeaderFromStream(IStream *, MetafileHeader *);
GpStatus WINGDIPAPI
GdipGetMetafileDownLevelRasterizationLimit(GDIPCONST GpMetafile*,UINT*);
GpStatus WINGDIPAPI
GdipGetMetafileHeaderFromWmf(HMETAFILE, GDIPCONST WmfPlaceableFileHeader *, MetafileHeader *);
/* Notification */

View file

@ -0,0 +1,5 @@
directories:
dlls/gdiplus/tests: modules/rostests/winetests/gdiplus
files: null
tags:
wine: 7abca9742a9410447636e0222e36d214449c90dd