log_state(state_a, &state_log);
+ /* A state created by SaveGraphics cannot be restored with EndContainer. */
+ GdipCreateFromHDC(hdc, &graphics1);
+ GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
+ stat = GdipSaveGraphics(graphics1, &state_a);
+ expect(Ok, stat);
+ GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
+ stat = GdipEndContainer(graphics1, state_a);
+ expect(Ok, stat);
+ GdipGetInterpolationMode(graphics1, &mode);
+ expect(InterpolationModeBicubic, mode);
+ stat = GdipRestoreGraphics(graphics1, state_a);
+ expect(Ok, stat);
+ GdipGetInterpolationMode(graphics1, &mode);
+ expect(InterpolationModeBilinear, mode);
+ GdipDeleteGraphics(graphics1);
+
+ log_state(state_a, &state_log);
+
+ /* A state created by BeginContainer cannot be restored with RestoreGraphics. */
+ GdipCreateFromHDC(hdc, &graphics1);
+ GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
+ stat = GdipBeginContainer2(graphics1, &state_a);
+ expect(Ok, stat);
+ GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
+ stat = GdipRestoreGraphics(graphics1, state_a);
+ expect(Ok, stat);
+ GdipGetInterpolationMode(graphics1, &mode);
+ expect(InterpolationModeBicubic, mode);
+ stat = GdipEndContainer(graphics1, state_a);
+ expect(Ok, stat);
+ GdipGetInterpolationMode(graphics1, &mode);
+ expect(InterpolationModeBilinear, mode);
+ GdipDeleteGraphics(graphics1);
+
+ log_state(state_a, &state_log);
+
+ /* BeginContainer and SaveGraphics use the same stack. */
+ GdipCreateFromHDC(hdc, &graphics1);
+ GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
+ stat = GdipBeginContainer2(graphics1, &state_a);
+ expect(Ok, stat);
+ GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
+ stat = GdipSaveGraphics(graphics1, &state_b);
+ expect(Ok, stat);
+ GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
+ stat = GdipEndContainer(graphics1, state_a);
+ expect(Ok, stat);
+ GdipGetInterpolationMode(graphics1, &mode);
+ expect(InterpolationModeBilinear, mode);
+ stat = GdipRestoreGraphics(graphics1, state_b);
+ expect(Ok, stat);
+ GdipGetInterpolationMode(graphics1, &mode);
+ expect(InterpolationModeBilinear, mode);
+ GdipDeleteGraphics(graphics1);
+
+ log_state(state_a, &state_log);
+ log_state(state_b, &state_log);
+
/* The same state value should never be returned twice. */
todo_wine
check_no_duplicates(state_log);
REAL res_x, res_y, scale;
GpUnit pen_unit, page_unit;
REAL pen_width;
- INT cx, cy;
+ INT cx, cy, path_cx, path_cy;
} td[] =
{
- { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 1.0, 1, 1 },
- { 10.0, 10.0, 3.0, UnitPixel, UnitPixel, 2.0, 2, 2 },
- { 10.0, 10.0, 30.0, UnitPixel, UnitInch, 1.0, 1, 1 },
- { 10.0, 10.0, 1.0, UnitWorld, UnitPixel, 1.0, 1, 1 },
- { 10.0, 10.0, 3.0, UnitWorld, UnitPixel, 2.0, 6, 6 },
- { 10.0, 10.0, 2.0, UnitWorld, UnitInch, 1.0, 20, 20 },
+ { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 1.0, 1, 1, 1, 1 },
+ { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 0.0, 0, 0, 1, 1 },
+ { 10.0, 10.0, 1.0, UnitPixel, UnitPixel, 0.1, 1, 1, 1, 1 },
+ { 10.0, 10.0, 3.0, UnitPixel, UnitPixel, 2.0, 2, 2, 2, 2 },
+ { 10.0, 10.0, 30.0, UnitPixel, UnitInch, 1.0, 1, 1, 1, 1 },
+ { 10.0, 10.0, 1.0, UnitWorld, UnitPixel, 1.0, 1, 1, 1, 1 },
+ { 10.0, 10.0, 1.0, UnitWorld, UnitPixel, 0.0, 1, 1, 1, 1 },
+ { 10.0, 10.0, 3.0, UnitWorld, UnitPixel, 2.0, 6, 6, 6, 6 },
+ { 10.0, 10.0, 2.0, UnitWorld, UnitInch, 1.0, 20, 20, 20, 20 },
};
GpStatus status;
int i, j;
} u;
GpPen *pen;
GpPointF corner;
+ GpPath *path;
BitmapData bd;
INT min, max, size;
status = GdipBitmapUnlockBits(u.bitmap, &bd);
expect(Ok, status);
+ status = GdipGraphicsClear(graphics, 0xff000000);
+ expect(Ok, status);
+
+ status = GdipCreatePath(FillModeAlternate, &path);
+ expect(Ok, status);
+
+ status = GdipAddPathLine(path, corner.X/2, 0, corner.X/2, corner.Y);
+ expect(Ok, status);
+
+ status = GdipClosePathFigure(path);
+ expect(Ok, status);
+
+ status = GdipAddPathLine(path, 0, corner.Y/2, corner.X, corner.Y/2);
+ expect(Ok, status);
+
+ status = GdipDrawPath(graphics, pen, path);
+ expect(Ok, status);
+
+ GdipDeletePath(path);
+
+ status = GdipBitmapLockBits(u.bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
+ expect(Ok, status);
+
+ min = -1;
+ max = -2;
+
+ for (j=0; j<100; j++)
+ {
+ if (((BYTE*)bd.Scan0)[j*3] == 0xff)
+ {
+ min = j;
+ break;
+ }
+ }
+
+ for (j=99; j>=0; j--)
+ {
+ if (((BYTE*)bd.Scan0)[j*3] == 0xff)
+ {
+ max = j;
+ break;
+ }
+ }
+
+ size = max-min+1;
+
+ ok(size == td[i].path_cx, "%u: expected %d, got %d\n", i, td[i].path_cx, size);
+
+ min = -1;
+ max = -2;
+
+ for (j=0; j<100; j++)
+ {
+ if (((BYTE*)bd.Scan0)[bd.Stride*j] == 0xff)
+ {
+ min = j;
+ break;
+ }
+ }
+
+ for (j=99; j>=0; j--)
+ {
+ if (((BYTE*)bd.Scan0)[bd.Stride*j] == 0xff)
+ {
+ max = j;
+ break;
+ }
+ }
+
+ size = max-min+1;
+
+ ok(size == td[i].path_cy, "%u: expected %d, got %d\n", i, td[i].path_cy, size);
+
+ status = GdipBitmapUnlockBits(u.bitmap, &bd);
+ expect(Ok, status);
+
GdipDeletePen(pen);
GdipDeleteGraphics(graphics);
GdipDisposeImage(u.image);
ReleaseDC(hwnd, dc);
}
+static void test_container_rects(void)
+{
+ GpStatus status;
+ GpGraphics *graphics;
+ HDC hdc = GetDC( hwnd );
+ GpRectF dstrect, srcrect;
+ GraphicsContainer state;
+ static const GpPointF test_points[3] = {{0.0,0.0}, {1.0,0.0}, {0.0,1.0}};
+ GpPointF points[3];
+ REAL dpix, dpiy;
+
+ status = GdipCreateFromHDC(hdc, &graphics);
+ expect(Ok, status);
+
+ dstrect.X = 0.0;
+ dstrect.Y = 0.0;
+ dstrect.Width = 1.0;
+ dstrect.Height = 1.0;
+ srcrect = dstrect;
+
+ status = GdipGetDpiX(graphics, &dpix);
+ expect(Ok, status);
+
+ status = GdipGetDpiY(graphics, &dpiy);
+ expect(Ok, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitWorld, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitDisplay, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitMillimeter+1, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(NULL, &dstrect, &srcrect, UnitPixel, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, NULL, &srcrect, UnitPixel, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, NULL, UnitPixel, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, -1, &state);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, NULL);
+ expect(InvalidParameter, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, &state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(0.0, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf(1.0, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(0.0, points[2].X);
+ expectf(1.0, points[2].Y);
+
+ status = GdipEndContainer(graphics, state);
+ expect(Ok, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(0.0, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf(1.0/dpix, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(0.0, points[2].X);
+ expectf(1.0/dpiy, points[2].Y);
+
+ status = GdipEndContainer(graphics, state);
+ expect(Ok, status);
+
+ status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
+ expect(Ok, status);
+
+ dstrect.X = 1.0;
+ dstrect.Height = 3.0;
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, &state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(2.0, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf(4.0, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(2.0, points[2].X);
+ expectf(6.0, points[2].Y);
+
+ status = GdipEndContainer(graphics, state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(0.0, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf(2.0, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(0.0, points[2].X);
+ expectf(2.0, points[2].Y);
+
+ status = GdipResetWorldTransform(graphics);
+ expect(Ok, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(1.0, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf((dpix+1.0)/dpix, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(1.0, points[2].X);
+ expectf(3.0/dpiy, points[2].Y);
+
+ status = GdipEndContainer(graphics, state);
+ expect(Ok, status);
+
+ status = GdipSetPageUnit(graphics, UnitInch);
+ expect(Ok, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitPixel, &state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(dpix, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf(dpix*2, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(dpix, points[2].X);
+ expectf(dpiy*3, points[2].Y);
+
+ status = GdipEndContainer(graphics, state);
+ expect(Ok, status);
+
+ status = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state);
+ expect(Ok, status);
+
+ memcpy(points, test_points, sizeof(points));
+ status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, points, 3);
+ expect(Ok, status);
+ expectf(dpix, points[0].X);
+ expectf(0.0, points[0].Y);
+ expectf(dpix+1.0, points[1].X);
+ expectf(0.0, points[1].Y);
+ expectf(dpix, points[2].X);
+ expectf(3.0, points[2].Y);
+
+ status = GdipEndContainer(graphics, state);
+ expect(Ok, status);
+
+ GdipDeleteGraphics(graphics);
+
+ ReleaseDC(hwnd, hdc);
+}
+
START_TEST(graphics)
{
struct GdiplusStartupInput gdiplusStartupInput;
test_bitmapfromgraphics();
test_GdipFillRectangles();
test_GdipGetVisibleClipBounds_memoryDC();
+ test_container_rects();
GdiplusShutdown(gdiplusToken);
DestroyWindow( hwnd );
DEFINE_GUID(RedEyeCorrectionEffectGuid, 0x74d29d05, 0x69a4, 0x4266, 0x95, 0x49, 0x3c, 0xc5, 0x28, 0x36, 0xb6, 0x32);
DEFINE_GUID(ColorCurveEffectGuid, 0xdd6a0022, 0x58e4, 0x4a67, 0x9d, 0x9b, 0xd4, 0x8e, 0xb8, 0x81, 0xa5, 0x3d);
+static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*);
+static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
+static GpStatus (WINAPI *pGdipImageSetAbort)(GpImage*,GdiplusAbort*);
+
+static GpStatus (WINGDIPAPI *pGdipInitializePalette)(ColorPalette*,PaletteType,INT,BOOL,GpBitmap*);
+
#define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
#define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
{
LPCWSTR mime;
const GUID *format;
- BOOL todo;
} td[] =
{
- { bmp_mimetype, &ImageFormatBMP, FALSE },
- { jpeg_mimetype, &ImageFormatJPEG, FALSE },
- { gif_mimetype, &ImageFormatGIF, TRUE },
- { tiff_mimetype, &ImageFormatTIFF, FALSE },
- { png_mimetype, &ImageFormatPNG, FALSE }
+ { bmp_mimetype, &ImageFormatBMP },
+ { jpeg_mimetype, &ImageFormatJPEG },
+ { gif_mimetype, &ImageFormatGIF },
+ { tiff_mimetype, &ImageFormatTIFF },
+ { png_mimetype, &ImageFormatPNG }
};
GUID format, clsid;
BOOL ret;
ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
- todo_wine_if (td[i].todo)
- ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
+ ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
IStream_Release(stream);
}
GdipDisposeImageAttributes(imageattributes);
}
+static void test_histogram(void)
+{
+ UINT ch0[256], ch1[256], ch2[256], ch3[256];
+ HistogramFormat test_formats[] =
+ {
+ HistogramFormatARGB,
+ HistogramFormatPARGB,
+ HistogramFormatRGB,
+ HistogramFormatGray,
+ HistogramFormatB,
+ HistogramFormatG,
+ HistogramFormatR,
+ HistogramFormatA,
+ };
+ const UINT WIDTH = 8, HEIGHT = 16;
+ UINT num, i, x;
+ GpStatus stat;
+ GpBitmap *bm;
+
+ if (!pGdipBitmapGetHistogramSize)
+ {
+ win_skip("GdipBitmapGetHistogramSize is not supported\n");
+ return;
+ }
+
+ stat = pGdipBitmapGetHistogramSize(HistogramFormatARGB, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogramSize(0xff, NULL);
+ expect(InvalidParameter, stat);
+
+ num = 123;
+ stat = pGdipBitmapGetHistogramSize(10, &num);
+ expect(Ok, stat);
+ expect(256, num);
+
+ for (i = 0; i < sizeof(test_formats)/sizeof(test_formats[0]); i++)
+ {
+ num = 0;
+ stat = pGdipBitmapGetHistogramSize(test_formats[i], &num);
+ expect(Ok, stat);
+ expect(256, num);
+ }
+
+ bm = NULL;
+ stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
+ expect(Ok, stat);
+
+ /* Three solid rgb rows, next three rows are rgb shades. */
+ for (x = 0; x < WIDTH; x++)
+ {
+ GdipBitmapSetPixel(bm, x, 0, 0xffff0000);
+ GdipBitmapSetPixel(bm, x, 1, 0xff00ff00);
+ GdipBitmapSetPixel(bm, x, 2, 0xff0000ff);
+
+ GdipBitmapSetPixel(bm, x, 3, 0xff010000);
+ GdipBitmapSetPixel(bm, x, 4, 0xff003f00);
+ GdipBitmapSetPixel(bm, x, 5, 0xff000020);
+ }
+
+ stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL);
+ expect(InvalidParameter, stat);
+
+ /* Requested format matches bitmap format */
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL);
+ expect(InvalidParameter, stat);
+
+ /* Channel 3 is not used, must be NULL */
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL);
+ expect(Ok, stat);
+
+ ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]);
+ ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]);
+ ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]);
+ ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]);
+ ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]);
+ ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]);
+
+ /* ARGB histogram from RGB data. */
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3);
+ expect(Ok, stat);
+
+ ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]);
+ ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]);
+ ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]);
+ ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]);
+ ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]);
+ ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]);
+
+ ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]);
+
+ /* Request grayscale histogram from RGB bitmap. */
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL);
+ expect(Ok, stat);
+
+ GdipDisposeImage((GpImage*)bm);
+}
+
+static void test_imageabort(void)
+{
+ GpStatus stat;
+ GpBitmap *bm;
+
+ if (!pGdipImageSetAbort)
+ {
+ win_skip("GdipImageSetAbort() is not supported.\n");
+ return;
+ }
+
+ bm = NULL;
+ stat = GdipCreateBitmapFromScan0(8, 8, 0, PixelFormat24bppRGB, NULL, &bm);
+ expect(Ok, stat);
+
+ stat = pGdipImageSetAbort(NULL, NULL);
+ expect(InvalidParameter, stat);
+
+ stat = pGdipImageSetAbort((GpImage*)bm, NULL);
+ expect(Ok, stat);
+
+ GdipDisposeImage((GpImage*)bm);
+}
+
/* RGB 24 bpp 1x1 pixel PNG image */
static const char png_1x1_data[] = {
0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a,
}
}
+static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride)
+{
+ BYTE *src;
+ UINT i, j, scale;
+
+ *width = 256;
+ *height = 256;
+ *stride = (*width * 3 + 3) & ~3;
+ trace("width %d, height %d, stride %d\n", *width, *height, *stride);
+
+ src = HeapAlloc(GetProcessHeap(), 0, *stride * *height);
+
+ scale = 256 / *width;
+ if (!scale) scale = 1;
+
+ for (i = 0; i < *height; i++)
+ {
+ for (j = 0; j < *width; j++)
+ {
+ src[i * *stride + j*3 + 0] = scale * i;
+ src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2);
+ src[i * *stride + j*3 + 2] = scale * j;
+ }
+ }
+
+ return src;
+}
+
+static void test_GdipInitializePalette(void)
+{
+ GpStatus status;
+ BYTE *data;
+ GpBitmap *bitmap;
+ ColorPalette *palette;
+ UINT width, height, stride;
+
+ pGdipInitializePalette = (void *)GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipInitializePalette");
+ if (!pGdipInitializePalette)
+ {
+ win_skip("GdipInitializePalette is not supported on this platform\n");
+ return;
+ }
+
+ data = init_bitmap(&width, &height, &stride);
+
+ status = GdipCreateBitmapFromScan0(width, height, stride, PixelFormat24bppRGB, data, &bitmap);
+ expect(Ok, status);
+
+ palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 255);
+
+ palette->Flags = 0;
+ palette->Count = 15;
+ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap);
+ expect(GenericError, status);
+
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, NULL);
+ expect(InvalidParameter, status);
+
+ memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeCustom, 16, FALSE, NULL);
+ expect(Ok, status);
+ expect(0, palette->Flags);
+ expect(256, palette->Count);
+ expect(0x11111111, palette->Entries[0]);
+ expect(0x11111111, palette->Entries[128]);
+ expect(0x11111111, palette->Entries[255]);
+
+ memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeFixedBW, 0, FALSE, bitmap);
+ expect(Ok, status);
+todo_wine
+ expect(0x200, palette->Flags);
+ expect(2, palette->Count);
+ expect(0xff000000, palette->Entries[0]);
+ expect(0xffffffff, palette->Entries[1]);
+
+ memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, NULL);
+ expect(Ok, status);
+todo_wine
+ expect(0x300, palette->Flags);
+ expect(16, palette->Count);
+ expect(0xff000000, palette->Entries[0]);
+ expect(0xffc0c0c0, palette->Entries[8]);
+ expect(0xff008080, palette->Entries[15]);
+
+ memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, bitmap);
+ expect(Ok, status);
+todo_wine
+ expect(0x300, palette->Flags);
+ expect(16, palette->Count);
+ expect(0xff000000, palette->Entries[0]);
+ expect(0xffc0c0c0, palette->Entries[8]);
+ expect(0xff008080, palette->Entries[15]);
+
+ memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone252, 1, FALSE, bitmap);
+ expect(Ok, status);
+todo_wine
+ expect(0x800, palette->Flags);
+ expect(252, palette->Count);
+ expect(0xff000000, palette->Entries[0]);
+ expect(0xff990066, palette->Entries[128]);
+ expect(0xffffffff, palette->Entries[251]);
+
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 1, FALSE, bitmap);
+ expect(InvalidParameter, status);
+
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 2, FALSE, bitmap);
+ expect(Ok, status);
+ expect(0, palette->Flags);
+ expect(2, palette->Count);
+
+ palette->Flags = 0;
+ palette->Count = 256;
+ status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap);
+ expect(Ok, status);
+ expect(0, palette->Flags);
+ expect(16, palette->Count);
+
+ /* passing invalid enumeration palette type crashes under most Windows versions */
+
+ GdipFree(palette);
+ GdipDisposeImage((GpImage *)bitmap);
+}
+
START_TEST(image)
{
+ HMODULE mod = GetModuleHandleA("gdiplus.dll");
struct GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
+ pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize");
+ pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram");
+ pGdipImageSetAbort = (void*)GetProcAddress(mod, "GdipImageSetAbort");
+
+ test_GdipInitializePalette();
test_png_color_formats();
test_supported_encoders();
test_CloneBitmapArea();
test_dispose();
test_createeffect();
test_getadjustedpalette();
+ test_histogram();
+ test_imageabort();
GdiplusShutdown(gdiplusToken);
}
#define expectf(expected, got) expectf_((expected), (got), 0.001)
static BOOL save_metafiles;
+static BOOL load_metafiles;
typedef struct emfplus_record
{
BOOL todo;
ULONG record_type;
BOOL playback_todo;
+ void (*playback_fn)(GpMetafile* metafile, EmfPlusRecordType record_type,
+ unsigned int flags, unsigned int dataSize, const unsigned char *pStr);
} emfplus_record;
typedef struct emfplus_check_state
emfplus_check_state *state = (emfplus_check_state*)userdata;
GpStatus stat;
- stat = GdipPlayMetafileRecord(state->metafile, record_type, flags, dataSize, pStr);
-
if (state->expected[state->count].record_type)
{
- todo_wine_if (state->expected[state->count].playback_todo)
- ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
+ BOOL match = (state->expected[state->count].record_type == record_type);
+
+ if (match && state->expected[state->count].playback_fn)
+ state->expected[state->count].playback_fn(state->metafile, record_type, flags, dataSize, pStr);
+ else
+ {
+ stat = GdipPlayMetafileRecord(state->metafile, record_type, flags, dataSize, pStr);
+ todo_wine_if (state->expected[state->count].playback_todo)
+ ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
+ }
+
+ todo_wine_if (state->expected[state->count].todo)
+ ok(state->expected[state->count].record_type == record_type,
+ "%s.%i: expected record type 0x%x, got 0x%x\n", state->desc, state->count,
+ state->expected[state->count].record_type, record_type);
state->count++;
}
else
{
todo_wine_if (state->expected[state->count].playback_todo)
- ok(0, "%s: too many records\n", state->desc);
+ ok(0, "%s: unexpected record 0x%x\n", state->desc, record_type);
return FALSE;
}
expect(Ok, stat);
}
-static void save_metafile(GpMetafile *metafile, const char *filename)
+/* When 'save' or 'load' is specified on the command line, save or
+ * load the specified filename. */
+static void sync_metafile(GpMetafile **metafile, const char *filename)
{
+ GpStatus stat;
if (save_metafiles)
{
GpMetafile *clone;
HENHMETAFILE hemf;
- GpStatus stat;
- stat = GdipCloneImage((GpImage*)metafile, (GpImage**)&clone);
+ stat = GdipCloneImage((GpImage*)*metafile, (GpImage**)&clone);
expect(Ok, stat);
stat = GdipGetHemfFromMetafile(clone, &hemf);
stat = GdipDisposeImage((GpImage*)clone);
expect(Ok, stat);
}
+ else if (load_metafiles)
+ {
+ HENHMETAFILE hemf;
+
+ stat = GdipDisposeImage((GpImage*)*metafile);
+ expect(Ok, stat);
+ *metafile = NULL;
+
+ hemf = GetEnhMetaFileA(filename);
+ ok(hemf != NULL, "%s could not be opened\n", filename);
+
+ stat = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
+ expect(Ok, stat);
+ }
}
static const emfplus_record empty_records[] = {
check_metafile(metafile, empty_records, "empty metafile", dst_points, &frame, UnitPixel);
- save_metafile(metafile, "empty.emf");
+ sync_metafile(&metafile, "empty.emf");
stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
expect(Ok, stat);
stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
expect(Ok, stat);
+ memset(&header, 0xaa, sizeof(header));
+ stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
+ expect(Ok, stat);
+ expect(MetafileTypeEmfPlusOnly, header.Type);
+ expect(U(header).EmfHeader.nBytes, header.Size);
+ ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
+ expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
+ expectf(xres, header.DpiX);
+ expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
+ expectf(yres, header.DpiY);
+ expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
+ expect(0, header.X);
+ expect(0, header.Y);
+ expect(100, header.Width);
+ expect(100, header.Height);
+ expect(28, header.EmfPlusHeaderSize);
+ expect(96, header.LogicalDpiX);
+ expect(96, header.LogicalDpiX);
+ expect(EMR_HEADER, U(header).EmfHeader.iType);
+ expect(0, U(header).EmfHeader.rclBounds.left);
+ expect(0, U(header).EmfHeader.rclBounds.top);
+ expect(-1, U(header).EmfHeader.rclBounds.right);
+ expect(-1, U(header).EmfHeader.rclBounds.bottom);
+ expect(0, U(header).EmfHeader.rclFrame.left);
+ expect(0, U(header).EmfHeader.rclFrame.top);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
+
stat = GdipGetHemfFromMetafile(metafile, &hemf);
expect(Ok, stat);
expect(Ok, stat);
expectf(header.DpiY, yres);
+ memset(&header, 0xaa, sizeof(header));
+ stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
+ expect(Ok, stat);
+ expect(MetafileTypeEmfPlusOnly, header.Type);
+ expect(U(header).EmfHeader.nBytes, header.Size);
+ ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
+ expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
+ expectf(xres, header.DpiX);
+ expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
+ expectf(yres, header.DpiY);
+ expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
+ expect(0, header.X);
+ expect(0, header.Y);
+ expect(100, header.Width);
+ expect(100, header.Height);
+ expect(28, header.EmfPlusHeaderSize);
+ expect(96, header.LogicalDpiX);
+ expect(96, header.LogicalDpiX);
+ expect(EMR_HEADER, U(header).EmfHeader.iType);
+ expect(0, U(header).EmfHeader.rclBounds.left);
+ expect(0, U(header).EmfHeader.rclBounds.top);
+ expect(-1, U(header).EmfHeader.rclBounds.right);
+ expect(-1, U(header).EmfHeader.rclBounds.bottom);
+ expect(0, U(header).EmfHeader.rclFrame.left);
+ expect(0, U(header).EmfHeader.rclFrame.top);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
+
stat = GdipDisposeImage((GpImage*)metafile);
expect(Ok, stat);
}
check_metafile(metafile, getdc_records, "getdc metafile", dst_points, &frame, UnitPixel);
- save_metafile(metafile, "getdc.emf");
+ sync_metafile(&metafile, "getdc.emf");
stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
expect(Ok, stat);
stat = GdipGetHemfFromMetafile(metafile, &hemf);
expect(InvalidParameter, stat);
+ memset(&header, 0xaa, sizeof(header));
+ stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
+ expect(Ok, stat);
+ expect(MetafileTypeEmf, header.Type);
+ ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
+ /* The rest is zeroed or seemingly random/uninitialized garbage. */
+
stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
expect(Ok, stat);
check_metafile(metafile, emfonly_records, "emfonly metafile", dst_points, &frame, UnitPixel);
- save_metafile(metafile, "emfonly.emf");
+ sync_metafile(&metafile, "emfonly.emf");
stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
expect(Ok, stat);
stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
expect(Ok, stat);
+ memset(&header, 0xaa, sizeof(header));
+ stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
+ expect(Ok, stat);
+ expect(MetafileTypeEmf, header.Type);
+ expect(U(header).EmfHeader.nBytes, header.Size);
+ /* For some reason a recoreded EMF Metafile has an EMF+ version. */
+ todo_wine ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
+ expect(0, header.EmfPlusFlags);
+ expectf(xres, header.DpiX);
+ expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
+ expectf(yres, header.DpiY);
+ expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
+ expect(0, header.X);
+ expect(0, header.Y);
+ expect(100, header.Width);
+ expect(100, header.Height);
+ expect(0, header.EmfPlusHeaderSize);
+ expect(0, header.LogicalDpiX);
+ expect(0, header.LogicalDpiX);
+ expect(EMR_HEADER, U(header).EmfHeader.iType);
+ expect(25, U(header).EmfHeader.rclBounds.left);
+ expect(25, U(header).EmfHeader.rclBounds.top);
+ expect(74, U(header).EmfHeader.rclBounds.right);
+ expect(74, U(header).EmfHeader.rclBounds.bottom);
+ expect(0, U(header).EmfHeader.rclFrame.left);
+ expect(0, U(header).EmfHeader.rclFrame.top);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
+
stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
expect(Ok, stat);
expect(Ok, stat);
expectf(header.DpiY, yres);
+ memset(&header, 0xaa, sizeof(header));
+ stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
+ expect(Ok, stat);
+ expect(MetafileTypeEmf, header.Type);
+ expect(U(header).EmfHeader.nBytes, header.Size);
+ expect(0x10000, header.Version);
+ expect(0, header.EmfPlusFlags);
+ expectf(xres, header.DpiX);
+ expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
+ expectf(yres, header.DpiY);
+ expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
+ expect(0, header.X);
+ expect(0, header.Y);
+ expect(100, header.Width);
+ expect(100, header.Height);
+ expect(0, header.EmfPlusHeaderSize);
+ expect(0, header.LogicalDpiX);
+ expect(0, header.LogicalDpiX);
+ expect(EMR_HEADER, U(header).EmfHeader.iType);
+ expect(25, U(header).EmfHeader.rclBounds.left);
+ expect(25, U(header).EmfHeader.rclBounds.top);
+ expect(74, U(header).EmfHeader.rclBounds.right);
+ expect(74, U(header).EmfHeader.rclBounds.bottom);
+ expect(0, U(header).EmfHeader.rclFrame.left);
+ expect(0, U(header).EmfHeader.rclFrame.top);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
+ expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
+
stat = GdipDisposeImage((GpImage*)metafile);
expect(Ok, stat);
}
check_metafile(metafile, fillrect_records, "fillrect metafile", dst_points, &frame, UnitPixel);
- save_metafile(metafile, "fillrect.emf");
+ sync_metafile(&metafile, "fillrect.emf");
stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
expect(Ok, stat);
stat = GdipDeleteGraphics(graphics);
expect(Ok, stat);
- save_metafile(metafile, "clear.emf");
+ sync_metafile(&metafile, "clear.emf");
stat = GdipCreateBitmapFromScan0(30, 30, 0, PixelFormat32bppRGB, NULL, &bitmap);
expect(Ok, stat);
check_metafile(metafile, pagetransform_records, "pagetransform metafile", dst_points, &frame, UnitPixel);
- save_metafile(metafile, "pagetransform.emf");
+ sync_metafile(&metafile, "pagetransform.emf");
stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
expect(Ok, stat);
{0, EmfPlusRecordTypeFillRects},
{0, EmfPlusRecordTypeResetWorldTransform},
{0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeMultiplyWorldTransform},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeRotateWorldTransform},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeSetWorldTransform},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeTranslateWorldTransform},
+ {0, EmfPlusRecordTypeFillRects},
{0, EmfPlusRecordTypeEndOfFile},
{0, EMR_EOF},
{0}
stat = GdipDeleteBrush(brush);
expect(Ok, stat);
+ /* multiply transform */
+ stat = GdipSetMatrixElements(transform, 2.0, 0.0, 0.0, 1.0, 0.0, 0.0);
+ expect(Ok, stat);
+
+ stat = GdipMultiplyWorldTransform(graphics, transform, MatrixOrderPrepend);
+ expect(Ok, stat);
+
+ stat = GdipGetWorldTransform(graphics, transform);
+ expect(Ok, stat);
+
+ stat = GdipGetMatrixElements(transform, elements);
+ expect(Ok, stat);
+ expectf(2.0, elements[0]);
+ expectf(0.0, elements[1]);
+ expectf(0.0, elements[2]);
+ expectf(1.0, elements[3]);
+ expectf(0.0, elements[4]);
+ expectf(0.0, elements[5]);
+
+ stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 0.5, 1.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ /* rotate transform */
+ stat = GdipRotateWorldTransform(graphics, 90.0, MatrixOrderAppend);
+ expect(Ok, stat);
+
+ stat = GdipGetWorldTransform(graphics, transform);
+ expect(Ok, stat);
+
+ stat = GdipGetMatrixElements(transform, elements);
+ expect(Ok, stat);
+ expectf(0.0, elements[0]);
+ expectf(2.0, elements[1]);
+ expectf(-1.0, elements[2]);
+ expectf(0.0, elements[3]);
+ expectf(0.0, elements[4]);
+ expectf(0.0, elements[5]);
+
+ stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 1.0, -1.0, 0.5, 1.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ /* set transform */
+ stat = GdipSetMatrixElements(transform, 1.0, 0.0, 0.0, 3.0, 0.0, 0.0);
+ expect(Ok, stat);
+
+ stat = GdipSetWorldTransform(graphics, transform);
+ expect(Ok, stat);
+
+ stat = GdipGetWorldTransform(graphics, transform);
+ expect(Ok, stat);
+
+ stat = GdipGetMatrixElements(transform, elements);
+ expect(Ok, stat);
+ expectf(1.0, elements[0]);
+ expectf(0.0, elements[1]);
+ expectf(0.0, elements[2]);
+ expectf(3.0, elements[3]);
+ expectf(0.0, elements[4]);
+ expectf(0.0, elements[5]);
+
+ stat = GdipCreateSolidFill((ARGB)0xffffff00, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 1.0, 1.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ /* translate transform */
+ stat = GdipTranslateWorldTransform(graphics, -1.0, 0.0, MatrixOrderAppend);
+ expect(Ok, stat);
+
+ stat = GdipGetWorldTransform(graphics, transform);
+ expect(Ok, stat);
+
+ stat = GdipGetMatrixElements(transform, elements);
+ expect(Ok, stat);
+ expectf(1.0, elements[0]);
+ expectf(0.0, elements[1]);
+ expectf(0.0, elements[2]);
+ expectf(3.0, elements[3]);
+ expectf(-1.0, elements[4]);
+ expectf(0.0, elements[5]);
+
+ stat = GdipCreateSolidFill((ARGB)0xffffffff, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 1.0, 1.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
stat = GdipDeleteMatrix(transform);
expect(Ok, stat);
check_metafile(metafile, worldtransform_records, "worldtransform metafile", dst_points, &frame, UnitPixel);
- save_metafile(metafile, "worldtransform.emf");
+ sync_metafile(&metafile, "worldtransform.emf");
stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
expect(Ok, stat);
expect(Ok, stat);
expect(0xff00ffff, color);
+ stat = GdipBitmapGetPixel(bitmap, 50, 30, &color);
+ expect(Ok, stat);
+ expect(0xffff0000, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 10, 50, &color);
+ expect(Ok, stat);
+ expect(0xffff00ff, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 30, 90, &color);
+ expect(Ok, stat);
+ expect(0xffffff00, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 10, 90, &color);
+ expect(Ok, stat);
+ expect(0xffffffff, color);
+
stat = GdipDeleteGraphics(graphics);
expect(Ok, stat);
expect(Ok, stat);
}
-START_TEST(metafile)
+static const emfplus_record container_records[] = {
+ {0, EMR_HEADER},
+ {0, EmfPlusRecordTypeHeader},
+ {0, EmfPlusRecordTypeBeginContainerNoParams},
+ {0, EmfPlusRecordTypeScaleWorldTransform},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeEndContainer},
+ {0, EmfPlusRecordTypeScaleWorldTransform},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeSave},
+ {0, EmfPlusRecordTypeRestore},
+ {0, EmfPlusRecordTypeScaleWorldTransform},
+ {0, EmfPlusRecordTypeBeginContainerNoParams},
+ {0, EmfPlusRecordTypeScaleWorldTransform},
+ {0, EmfPlusRecordTypeBeginContainerNoParams},
+ {0, EmfPlusRecordTypeEndContainer},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeBeginContainer},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeEndContainer},
+ {0, EmfPlusRecordTypeBeginContainerNoParams},
+ {0, EmfPlusRecordTypeEndOfFile},
+ {0, EMR_EOF},
+ {0}
+};
+
+static void test_containers(void)
{
- struct GdiplusStartupInput gdiplusStartupInput;
- ULONG_PTR gdiplusToken;
- int myARGC;
- char **myARGV;
+ GpStatus stat;
+ GpMetafile *metafile;
+ GpGraphics *graphics;
+ GpBitmap *bitmap;
+ GpBrush *brush;
+ ARGB color;
+ HDC hdc;
+ static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+ static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
+ static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+ GraphicsContainer state1, state2;
+ GpRectF srcrect, dstrect;
+ REAL dpix, dpiy;
- gdiplusStartupInput.GdiplusVersion = 1;
- gdiplusStartupInput.DebugEventCallback = NULL;
- gdiplusStartupInput.SuppressBackgroundThread = 0;
+ hdc = CreateCompatibleDC(0);
+
+ stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+ expect(Ok, stat);
+
+ DeleteDC(hdc);
+
+ if (stat != Ok)
+ return;
+
+ stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+ expect(Ok, stat);
+
+ /* Normal usage */
+ stat = GdipBeginContainer2(graphics, &state1);
+ expect(Ok, stat);
+
+ stat = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
+ expect(Ok, stat);
+
+ stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 5.0, 5.0, 5.0, 5.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ stat = GdipEndContainer(graphics, state1);
+ expect(Ok, stat);
+
+ stat = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
+ expect(Ok, stat);
+
+ stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 5.0, 5.0, 5.0, 5.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ stat = GdipSaveGraphics(graphics, &state1);
+ expect(Ok, stat);
+
+ stat = GdipRestoreGraphics(graphics, state1);
+ expect(Ok, stat);
+
+ /* Popping two states at once */
+ stat = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
+ expect(Ok, stat);
+
+ stat = GdipBeginContainer2(graphics, &state1);
+ expect(Ok, stat);
+
+ stat = GdipScaleWorldTransform(graphics, 4.0, 4.0, MatrixOrderPrepend);
+ expect(Ok, stat);
+
+ stat = GdipBeginContainer2(graphics, &state2);
+ expect(Ok, stat);
+
+ stat = GdipEndContainer(graphics, state1);
+ expect(Ok, stat);
+
+ stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 20.0, 20.0, 5.0, 5.0);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ /* With transform applied */
+ stat = GdipGetDpiX(graphics, &dpix);
+ expect(Ok, stat);
+
+ stat = GdipGetDpiY(graphics, &dpiy);
+ expect(Ok, stat);
+
+ srcrect.X = 0.0;
+ srcrect.Y = 0.0;
+ srcrect.Width = 1.0;
+ srcrect.Height = 1.0;
+
+ dstrect.X = 25.0;
+ dstrect.Y = 0.0;
+ dstrect.Width = 5.0;
+ dstrect.Height = 5.0;
+
+ stat = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state1);
+ expect(Ok, stat);
+
+ stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 0.0, 0.0, dpix, dpiy);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ stat = GdipEndContainer(graphics, state1);
+ expect(Ok, stat);
+
+ /* Restoring an invalid state seems to break the graphics object? */
+ if (0) {
+ stat = GdipEndContainer(graphics, state1);
+ expect(Ok, stat);
+ }
+
+ /* Ending metafile with a state open */
+ stat = GdipBeginContainer2(graphics, &state1);
+ expect(Ok, stat);
+
+ stat = GdipDeleteGraphics(graphics);
+ expect(Ok, stat);
+
+ check_metafile(metafile, container_records, "container metafile", dst_points, &frame, UnitPixel);
+
+ sync_metafile(&metafile, "container.emf");
+
+ stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
+ expect(Ok, stat);
+
+ stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
+ expect(Ok, stat);
+
+ play_metafile(metafile, graphics, container_records, "container playback", dst_points, &frame, UnitPixel);
+
+ stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
+ expect(Ok, stat);
+ expect(0, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 12, 12, &color);
+ expect(Ok, stat);
+ expect(0xff000000, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 8, 8, &color);
+ expect(Ok, stat);
+ expect(0xff0000ff, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 42, 42, &color);
+ expect(Ok, stat);
+ expect(0xff00ff00, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 55, 5, &color);
+ expect(Ok, stat);
+ expect(0xff00ffff, color);
+
+ stat = GdipDeleteGraphics(graphics);
+ expect(Ok, stat);
+
+ stat = GdipDisposeImage((GpImage*)bitmap);
+ expect(Ok, stat);
+
+ stat = GdipDisposeImage((GpImage*)metafile);
+ expect(Ok, stat);
+}
+
+static const emfplus_record clipping_records[] = {
+ {0, EMR_HEADER},
+ {0, EmfPlusRecordTypeHeader},
+ {0, EmfPlusRecordTypeSave},
+ {0, EmfPlusRecordTypeSetClipRect},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeRestore},
+ {0, EmfPlusRecordTypeSetClipRect},
+ {0, EmfPlusRecordTypeFillRects},
+ {0, EmfPlusRecordTypeEndOfFile},
+ {0, EMR_EOF},
+ {0}
+};
+
+static void test_clipping(void)
+{
+ GpStatus stat;
+ GpMetafile *metafile;
+ GpGraphics *graphics;
+ GpBitmap *bitmap;
+ GpBrush *brush;
+ ARGB color;
+ HDC hdc;
+ static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+ static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
+ static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+ GraphicsState state;
+
+ hdc = CreateCompatibleDC(0);
+
+ stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+ expect(Ok, stat);
+
+ DeleteDC(hdc);
+
+ if (stat != Ok)
+ return;
+
+ stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+ expect(Ok, stat);
+
+ stat = GdipSaveGraphics(graphics, &state);
+ expect(Ok, stat);
+
+ stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeReplace);
+ expect(Ok, stat);
+
+ stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 0, 0, 100, 100);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ stat = GdipRestoreGraphics(graphics, state);
+ expect(Ok, stat);
+
+ stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeXor);
+ expect(Ok, stat);
+
+ stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
+ expect(Ok, stat);
+
+ stat = GdipFillRectangle(graphics, brush, 30, 30, 20, 10);
+ expect(Ok, stat);
+
+ stat = GdipDeleteBrush(brush);
+ expect(Ok, stat);
+
+ stat = GdipDeleteGraphics(graphics);
+ expect(Ok, stat);
+
+ check_metafile(metafile, clipping_records, "clipping metafile", dst_points, &frame, UnitPixel);
+
+ sync_metafile(&metafile, "clipping.emf");
+
+ stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
+ expect(Ok, stat);
+
+ stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
+ expect(Ok, stat);
+
+ play_metafile(metafile, graphics, clipping_records, "clipping playback", dst_points, &frame, UnitPixel);
+
+ stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
+ expect(Ok, stat);
+ expect(0, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 35, 35, &color);
+ expect(Ok, stat);
+ expect(0xff000000, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 45, 35, &color);
+ expect(Ok, stat);
+ expect(0xff0000ff, color);
+
+ stat = GdipDeleteGraphics(graphics);
+ expect(Ok, stat);
+
+ stat = GdipDisposeImage((GpImage*)bitmap);
+ expect(Ok, stat);
+
+ stat = GdipDisposeImage((GpImage*)metafile);
+ expect(Ok, stat);
+}
+
+static void test_gditransform_cb(GpMetafile* metafile, EmfPlusRecordType record_type,
+ unsigned int flags, unsigned int dataSize, const unsigned char *pStr)
+{
+ static const XFORM xform = {0.5, 0, 0, 0.5, 0, 0};
+ static const RECTL rectangle = {0,0,100,100};
+ GpStatus stat;
+
+ stat = GdipPlayMetafileRecord(metafile, EMR_SETWORLDTRANSFORM, 0, sizeof(xform), (void*)&xform);
+ expect(Ok, stat);
+
+ stat = GdipPlayMetafileRecord(metafile, EMR_RECTANGLE, 0, sizeof(rectangle), (void*)&rectangle);
+ expect(Ok, stat);
+}
+
+static const emfplus_record gditransform_records[] = {
+ {0, EMR_HEADER},
+ {0, EMR_CREATEBRUSHINDIRECT},
+ {0, EMR_SELECTOBJECT},
+ {0, EMR_GDICOMMENT, 0, test_gditransform_cb},
+ {0, EMR_SELECTOBJECT},
+ {0, EMR_DELETEOBJECT},
+ {0, EMR_EOF},
+ {0}
+};
+
+static void test_gditransform(void)
+{
+ GpStatus stat;
+ GpMetafile *metafile;
+ GpGraphics *graphics;
+ HDC hdc, metafile_dc;
+ HENHMETAFILE hemf;
+ MetafileHeader header;
+ static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
+ static const GpPointF dst_points[3] = {{0.0,0.0},{40.0,0.0},{0.0,40.0}};
+ static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
+ HBRUSH hbrush, holdbrush;
+ GpBitmap *bitmap;
+ ARGB color;
+
+ hdc = CreateCompatibleDC(0);
+
+ stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
+ expect(Ok, stat);
+
+ DeleteDC(hdc);
+
+ if (stat != Ok)
+ return;
+
+ stat = GdipGetHemfFromMetafile(metafile, &hemf);
+ expect(InvalidParameter, stat);
+
+ memset(&header, 0xaa, sizeof(header));
+ stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
+ expect(Ok, stat);
+ expect(MetafileTypeEmf, header.Type);
+ ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
+
+ stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
+ expect(Ok, stat);
+
+ stat = GdipGetDC(graphics, &metafile_dc);
+ expect(Ok, stat);
+
+ if (stat != Ok)
+ {
+ GdipDeleteGraphics(graphics);
+ GdipDisposeImage((GpImage*)metafile);
+ return;
+ }
+
+ hbrush = CreateSolidBrush(0xff);
+
+ holdbrush = SelectObject(metafile_dc, hbrush);
+
+ GdiComment(metafile_dc, 8, (const BYTE*)"winetest");
+
+ SelectObject(metafile_dc, holdbrush);
+
+ DeleteObject(hbrush);
+
+ stat = GdipReleaseDC(graphics, metafile_dc);
+ expect(Ok, stat);
+
+ stat = GdipDeleteGraphics(graphics);
+ expect(Ok, stat);
+
+ check_metafile(metafile, gditransform_records, "gditransform metafile", dst_points, &frame, UnitPixel);
+
+ sync_metafile(&metafile, "gditransform.emf");
+
+ stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
+ expect(Ok, stat);
+
+ stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
+ expect(Ok, stat);
+
+ play_metafile(metafile, graphics, gditransform_records, "gditransform playback", dst_points, &frame, UnitPixel);
+
+ stat = GdipBitmapGetPixel(bitmap, 10, 10, &color);
+ expect(Ok, stat);
+ expect(0xffff0000, color);
+
+ stat = GdipBitmapGetPixel(bitmap, 30, 30, &color);
+ expect(Ok, stat);
+ expect(0x00000000, color);
+
+ stat = GdipDeleteGraphics(graphics);
+ expect(Ok, stat);
+
+ stat = GdipDisposeImage((GpImage*)bitmap);
+ expect(Ok, stat);
+
+ stat = GdipDisposeImage((GpImage*)metafile);
+ expect(Ok, stat);
+}
+
+START_TEST(metafile)
+{
+ struct GdiplusStartupInput gdiplusStartupInput;
+ ULONG_PTR gdiplusToken;
+ int myARGC;
+ char **myARGV;
+
+ gdiplusStartupInput.GdiplusVersion = 1;
+ gdiplusStartupInput.DebugEventCallback = NULL;
+ gdiplusStartupInput.SuppressBackgroundThread = 0;
gdiplusStartupInput.SuppressExternalCodecs = 0;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
myARGC = winetest_get_mainargs( &myARGV );
- if (myARGC >= 3 && !strcmp(myARGV[2], "save"))
- save_metafiles = TRUE;
+ if (myARGC >= 3)
+ {
+ if (!strcmp(myARGV[2], "save"))
+ save_metafiles = TRUE;
+ else if (!strcmp(myARGV[2], "load"))
+ load_metafiles = TRUE;
+ }
test_empty();
test_getdc();
test_worldtransform();
test_converttoemfplus();
test_frameunit();
+ test_containers();
+ test_clipping();
+ test_gditransform();
GdiplusShutdown(gdiplusToken);
}