1 #include <assert.h>
2 #include <float.h>
3 #include <math.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 
8 #if !defined(_WIN32)
9 #include <unistd.h>
10 #endif
11 
12 #define STARTUP \
13     ULONG_PTR gdiplusToken; \
14     GdiplusStartupInput gdiplusStartupInput; \
15     gdiplusStartupInput.GdiplusVersion = 1; \
16     gdiplusStartupInput.DebugEventCallback = NULL; \
17     gdiplusStartupInput.SuppressBackgroundThread = FALSE; \
18     gdiplusStartupInput.SuppressExternalCodecs = FALSE; \
19     GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, NULL); \
20 
21 #define SHUTDOWN GdiplusShutdown (gdiplusToken);
22 
23 #if !defined(__has_attribute)
24 #define __has_attribute(x) 0
25 #endif
26 
27 #if __has_attribute(used) || defined(__GNUC__)
28 #define ATTRIBUTE_USED __attribute__((used))
29 #else
30 #define ATTRIBUTE_USED
31 #endif
32 
33 #define ARRAY_SIZE(x) sizeof (x) / sizeof (*x)
34 
floatsEqual(float v1,float v2)35 ATTRIBUTE_USED static BOOL floatsEqual(float v1, float v2)
36 {
37     if (isnan (v1))
38         return isnan (v2);
39 
40     if (isinf (v1))
41         return isinf (v2);
42 
43     return fabs (v1 - v2) < 0.0001;
44 }
45 
46 #if !defined(USE_WINDOWS_GDIPLUS)
47 #define createWchar(c) g_utf8_to_utf16 (c, -1, NULL, NULL, NULL)
48 #define freeWchar(c) g_free(c)
49 #define wcharFromChar(c) createWchar(c)
50 #define charFromWchar(c) g_utf16_to_utf8 (c, -1, NULL, NULL, NULL)
51 #define freeChar(c) g_free(c)
52 #else
wcharFromChar(const char * c)53 ATTRIBUTE_USED static WCHAR* wcharFromChar(const char *c)
54 {
55     size_t length = strlen (c);
56 
57     WCHAR *wc = (WCHAR *)malloc ((length + 1) * sizeof(WCHAR));
58     for (size_t i = 0; i < length; i++) {
59         wc[i] = (WCHAR) c[i];
60     }
61     wc[length] = 0;
62 
63     return wc;
64 }
65 
charFromWchar(const wchar_t * wc)66 ATTRIBUTE_USED static char* charFromWchar(const wchar_t *wc)
67 {
68     size_t length = lstrlenW (wc);
69 
70     char *c = (char *)malloc ((length + 1) * sizeof(char));
71     for (size_t i = 0; i < length; i++) {
72         c[i] = (char) wc[i];
73     }
74     c[length] = 0;
75 
76     return c;
77 }
78 
79 #define createWchar(c) (WCHAR *) L ##c
80 #define freeWchar(c)
81 #define freeChar(c) free(c);
82 #endif
83 
printFailure(const char * file,const char * function,int line)84 ATTRIBUTE_USED static void printFailure(const char *file, const char *function, int line)
85 {
86     fprintf (stderr, "Assertion failure: file %s in %s, line %d\n", file, function, line);
87 }
88 
assertEqualIntImpl(INT actual,INT expected,const char * message,const char * file,const char * function,int line)89 ATTRIBUTE_USED static void assertEqualIntImpl (INT actual, INT expected, const char *message, const char *file, const char *function, int line)
90 {
91     if (actual != expected)
92     {
93         if (message)
94             fprintf (stderr, "%s\n", message);
95 
96         printFailure (file, function, line);
97         fprintf (stderr, "Expected: %d\n", expected);
98         fprintf (stderr, "Actual:   %d\n", actual);
99         abort();
100     }
101 }
102 
103 #define assertEqualInt(actual, expected) assertEqualIntImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
104 
assertEqualFloatImpl(REAL actual,REAL expected,const char * message,const char * file,const char * function,int line)105 ATTRIBUTE_USED static void assertEqualFloatImpl (REAL actual, REAL expected, const char *message, const char *file, const char *function, int line)
106 {
107     if (!floatsEqual (actual, expected))
108     {
109         if (message)
110             fprintf (stderr, "%s\n", message);
111 
112         printFailure (file, function, line);
113         fprintf (stderr, "Expected: %f\n", expected);
114         fprintf (stderr, "Actual:   %f\n", actual);
115         abort ();
116     }
117 }
118 
119 #define assertEqualFloat(actual, expected) assertEqualFloatImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
120 
assertSimilarFloatImpl(REAL actual,REAL expected,REAL tolerance,const char * message,const char * file,const char * function,int line)121 ATTRIBUTE_USED static void assertSimilarFloatImpl (REAL actual, REAL expected, REAL tolerance, const char *message, const char *file, const char *function, int line)
122 {
123     if (fabs(actual - expected) > fabs(tolerance)) {
124         if (message)
125             fprintf (stderr, "%s\n", message);
126 
127         printFailure (file, function, line);
128         fprintf (stderr, "Expected %f +/- %f\n", expected, tolerance);
129         fprintf (stderr, "Actual:   %f\n", actual);
130         abort ();
131     }
132 }
133 
134 #define assertSimilarFloat(actual, expected, tolerance) assertSimilarFloatImpl (actual, expected, tolerance, NULL, __FILE__, __func__, __LINE__)
135 
stringsEqual(const WCHAR * actual,const char * expected)136 ATTRIBUTE_USED static BOOL stringsEqual (const WCHAR *actual, const char *expected)
137 {
138     int i = 0;
139     while (TRUE) {
140         if (expected[i] == '\0') {
141             return actual[i] == '\0';
142         }
143 
144         if (expected[i] != (char)actual[i])
145             return FALSE;
146 
147         i++;
148     }
149 
150     return TRUE;
151 }
152 
assertEqualStringImpl(const WCHAR * actual,const char * expected,const char * message,const char * file,const char * function,int line)153 ATTRIBUTE_USED static void assertEqualStringImpl(const WCHAR *actual, const char * expected, const char *message, const char *file, const char *function, int line)
154 {
155     if (!stringsEqual (actual, expected))
156     {
157         char *actualA = charFromWchar (actual);
158 
159         if (message)
160             fprintf (stderr, "%s\n", message);
161 
162         printFailure (file, function, line);
163         fprintf (stderr, "Expected: %s\n", expected);
164         fprintf (stderr, "Actual:   %s\n", actualA);
165 
166         freeChar (actualA);
167         abort();
168     }
169 }
170 
171 #define assertEqualString(actual, expected) assertEqualStringImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
172 
assertEqualRectImpl(GpRectF actual,GpRectF expected,const char * message,const char * file,const char * function,int line)173 ATTRIBUTE_USED static void assertEqualRectImpl (GpRectF actual, GpRectF expected, const char *message, const char *file, const char *function, int line)
174 {
175     if (!floatsEqual (actual.X, expected.X) || !floatsEqual (actual.Y, expected.Y) || !floatsEqual (actual.Width, expected.Width) || !floatsEqual (actual.Height, expected.Height))
176     {
177         if (message)
178             fprintf (stderr, "%s\n", message);
179 
180         printFailure (file, function, line);
181         fprintf (stderr, "Expected: {%g, %g, %g, %g}\n", expected.X, expected.Y, expected.Width, expected.Height);
182         fprintf (stderr, "Actual:   {%g, %g, %g, %g}\n", actual.X, actual.Y, actual.Width, actual.Height);
183         abort ();
184     }
185 }
186 
187 #define assertEqualRect(actual, expected) assertEqualRectImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
188 
assertEqualPointImpl(Point actual,Point expected,const char * message,const char * file,const char * function,int line)189 ATTRIBUTE_USED static void assertEqualPointImpl (Point actual, Point expected, const char *message, const char *file, const char *function, int line)
190 {
191 	if (actual.X != expected.X || actual.X != expected.X)
192 	{
193 		if (message)
194 			fprintf(stderr, "%s\n", message);
195 
196 		printFailure(file, function, line);
197 		fprintf(stderr, "Expected: {%d, %d}\n", expected.X, expected.Y);
198 		fprintf(stderr, "Actual:   {%d, %d}\n", actual.X, actual.Y);
199 		abort();
200 	}
201 }
202 
203 #define assertEqualPoint(actual, expected) assertEqualPointImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
204 
assertEqualPointsImpl(const Point * actual,const Point * expected,INT count,const char * file,const char * function,int line)205 ATTRIBUTE_USED static void assertEqualPointsImpl (const Point *actual, const Point *expected, INT count, const char *file, const char *function, int line)
206 {
207 	for (int i = 0; i < count; i++)
208 	{
209 		char iChar = i + '0';
210 		assertEqualPointImpl (actual[i], expected[i], &iChar, file, function, line);
211 	}
212 }
213 
214 #define assertEqualPoints(actual, expected, count) assertEqualPointsImpl (actual, expected, count, __FILE__, __func__, __LINE__)
215 
assertEqualPointFImpl(PointF actual,PointF expected,const char * message,const char * file,const char * function,int line)216 ATTRIBUTE_USED static void assertEqualPointFImpl (PointF actual, PointF expected, const char *message, const char *file, const char *function, int line)
217 {
218 	if (!floatsEqual(actual.X, expected.X) || !floatsEqual(actual.Y, expected.Y))
219 	{
220 		if (message)
221 			fprintf(stderr, "%s\n", message);
222 
223 		printFailure(file, function, line);
224 		fprintf(stderr, "Expected: {%g, %g}\n", expected.X, expected.Y);
225 		fprintf(stderr, "Actual:   {%g, %g}\n", actual.X, actual.Y);
226 		abort();
227 	}
228 }
229 
230 #define assertEqualPointF(actual, expected) assertEqualPointFImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
231 
assertEqualPointsFImpl(const PointF * actual,const PointF * expected,INT count,const char * file,const char * function,int line)232 ATTRIBUTE_USED static void assertEqualPointsFImpl (const PointF *actual, const PointF *expected, INT count, const char *file, const char *function, int line)
233 {
234 	for (int i = 0; i < count; i++)
235 	{
236 		char iChar = i + '0';
237 		assertEqualPointFImpl (actual[i], expected[i], &iChar, file, function, line);
238 	}
239 }
240 
241 #define assertEqualPointsF(actual, expected, count) assertEqualPointsFImpl (actual, expected, count, __FILE__, __func__, __LINE__)
242 
dumpBytes(const BYTE * bytes,int length)243 ATTRIBUTE_USED static void dumpBytes (const BYTE *bytes, int length)
244 {
245     printf ("%u\n", length);
246     for (int i = 0; i < length; i++) {
247         printf ("0x%02X", bytes[i]);
248         if (i != length - 1) {
249             printf (", ");
250         }
251     }
252 
253     printf("\n\n");
254 }
255 
assertEqualBytesImpl(const BYTE * actual,const BYTE * expected,int length,const char * message,const char * file,const char * function,int line)256 ATTRIBUTE_USED static void assertEqualBytesImpl (const BYTE *actual, const BYTE *expected, int length, const char *message, const char *file, const char *function, int line)
257 {
258     for (int i = 0; i < length; i++)
259     {
260         if (actual[i] != expected[i])
261         {
262             if (message)
263                 fprintf (stderr, "%s\n", message);
264 
265             printFailure (file, function, line);
266             fprintf (stderr, "Expected[%d]: 0x%02X\n", i, (BYTE) expected[i]);
267             fprintf (stderr, "Actual[%d]:   0x%02X\n", i, (BYTE) actual[i]);
268             fprintf (stderr, "-- Actual --\n");
269             dumpBytes (actual, length);
270 
271             abort();
272         }
273     }
274 }
275 
276 #define assertEqualBytes(actual, expected, length) assertEqualBytesImpl (actual, expected, length, NULL, __FILE__, __func__, __LINE__)
277 
assertEqualGuidImpl(GUID actual,GUID expected,const char * message,const char * file,const char * function,int line)278 ATTRIBUTE_USED static void assertEqualGuidImpl (GUID actual, GUID expected, const char *message, const char *file, const char *function, int line)
279 {
280     if (memcmp ((void *) &actual, (void *) &expected, sizeof (GUID)) != 0)
281     {
282         if (message)
283             fprintf (stderr, "%s\n", message);
284 
285         printFailure (file, function, line);
286         fprintf (stderr, "Expected: {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}\n", (unsigned long) expected.Data1, expected.Data2, expected.Data3, expected.Data4[0], expected.Data4[1], expected.Data4[2], expected.Data4[3], expected.Data4[4], expected.Data4[5], expected.Data4[6], expected.Data4[7]);
287         fprintf (stderr, "Actual:   {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}\n", (unsigned long) actual.Data1, actual.Data2, actual.Data3, actual.Data4[0], actual.Data4[1], actual.Data4[2], actual.Data4[3], actual.Data4[4], actual.Data4[5], actual.Data4[6], actual.Data4[7]);
288         abort();
289     }
290 }
291 
292 #define assertEqualGuid(actual, expected) assertEqualGuidImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
293 
verifyMatrixImpl(GpMatrix * matrix,REAL e1,REAL e2,REAL e3,REAL e4,REAL e5,REAL e6,const char * file,const char * function,int line)294 ATTRIBUTE_USED static void verifyMatrixImpl(GpMatrix *matrix, REAL e1, REAL e2, REAL e3, REAL e4, REAL e5, REAL e6, const char *file, const char *function, int line)
295 {
296     GpStatus status;
297     REAL elements[6];
298 
299     status = GdipGetMatrixElements(matrix, elements);
300     assertEqualInt (status, Ok);
301 
302     if (!floatsEqual (elements[0], e1) ||
303         !floatsEqual (elements[1], e2) ||
304         !floatsEqual (elements[2], e3) ||
305         !floatsEqual (elements[3], e4) ||
306         !floatsEqual (elements[4], e5) ||
307         !floatsEqual (elements[5], e6)) {
308 
309         printFailure (file, function, line);
310         fprintf (stderr, "Expected: %f, %f, %f, %f, %f, %f\n", e1, e2, e3, e4, e5, e6);
311         fprintf (stderr, "Actual:   %f, %f, %f, %f, %f, %f\n\n", elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
312 
313         abort ();
314     }
315 }
316 
317 #define verifyMatrix(matrix, e1, e2, e3, e4, e5, e6) verifyMatrixImpl (matrix, e1, e2, e3, e4, e5, e6, __FILE__, __func__, __LINE__)
318 
verifyRegionImpl(GpRegion * region,float expectedX,float expectedY,float expectedWidth,float expectedHeight,BOOL expectedIsEmpty,BOOL expectedIsInfinite,const char * file,const char * function,int line)319 ATTRIBUTE_USED static void verifyRegionImpl(GpRegion *region, float expectedX, float expectedY, float expectedWidth, float expectedHeight, BOOL expectedIsEmpty, BOOL expectedIsInfinite, const char *file, const char *function, int line)
320 {
321     GpImage *image;
322     GpGraphics *graphics;
323     GpStatus status;
324     GpRectF bounds;
325     BOOL isEmpty;
326     BOOL isInfinite;
327     RectF expectedBounds = {expectedX, expectedY, expectedWidth, expectedHeight};
328 
329 	GdipCreateBitmapFromScan0 (10, 10, 0, PixelFormat32bppRGB, NULL, (GpBitmap **) &image);
330 	GdipGetImageGraphicsContext (image, &graphics);
331 
332     status = GdipGetRegionBounds (region, graphics, &bounds);
333     assertEqualIntImpl (status, Ok, NULL, file, function, line);
334     assertEqualRectImpl (bounds, expectedBounds, "Bounds", file, function, line);
335 
336     status = GdipIsEmptyRegion (region, graphics, &isEmpty);
337     assertEqualIntImpl (status, Ok, NULL, file, function, line);
338     assertEqualIntImpl (isEmpty, expectedIsEmpty, "IsEmpty", file, function, line);
339 
340     status = GdipIsInfiniteRegion (region, graphics, &isInfinite);
341     assertEqualIntImpl (status, Ok, NULL, file, function, line);
342     assertEqualIntImpl (isInfinite, expectedIsInfinite, "IsInfinite", file, function, line);
343 
344 	GdipDisposeImage (image);
345 	GdipDeleteGraphics (graphics);
346 }
347 
348 #define verifyRegion(region, expectedX, expectedY, expectedWidth, expectedHeight, expectedIsEmpty, expectedIsInfinite) \
349 	verifyRegionImpl (region, expectedX, expectedY, expectedWidth, expectedHeight, expectedIsEmpty, expectedIsInfinite, __FILE__, __func__, __LINE__)
350 
351 ATTRIBUTE_USED static GpRectF infiniteScans[] = {{-4194304, -4194304, 8388608, 8388608}};
352 
353 ATTRIBUTE_USED static GpRectF *emptyScans = NULL;
354 
verifyRegionScansImpl(GpRegion * region,RectF * expectedScans,INT expectedCount,const char * file,const char * function,int line)355 ATTRIBUTE_USED static void verifyRegionScansImpl (GpRegion *region, RectF *expectedScans, INT expectedCount, const char *file, const char *function, int line)
356 {
357 	GpStatus status;
358 	GpMatrix *matrix;
359 	INT count;
360 	GpRectF *scans;
361 	GdipCreateMatrix (&matrix);
362 
363 	status = GdipGetRegionScans (region, NULL, &count, matrix);
364 	assertEqualIntImpl (status, Ok, NULL, file, function, line);
365 	assertEqualIntImpl (count, expectedCount / sizeof (GpRectF), "ScansCount", file, function, line);
366 	scans = (GpRectF *) malloc (count * sizeof (GpRectF));
367 
368 	status = GdipGetRegionScans (region, scans, &count, matrix);
369 	assertEqualIntImpl (status, Ok, NULL, file, function, line);
370 #if 0
371 	for (int i = 0; i < count; i++)
372 	{
373 		printf("{%.0f, %.0f, %.0f, %.0f}", scans[i].X, scans[i].Y, scans[i].Width, scans[i].Height);
374 		if (i != count - 1)
375 			printf (",");
376 
377 		printf("\n");
378 	}
379 	printf("\n");
380 #endif
381 	for (int i = 0; i < count; i++)
382 	{
383 		char iChar[] = {'S', 'c', 'a', 'n', ' ', (char) (i + '0'), 0};
384 		assertEqualRectImpl (scans[i], expectedScans[i], iChar, file, function, line);
385 	}
386 
387 	GdipDeleteMatrix (matrix);
388 }
389 
390 #define verifyRegionScans(region, expectedScans, expectedCount) \
391 	verifyRegionScansImpl (region, expectedScans, expectedCount, __FILE__, __func__, __LINE__)
392 
393 ATTRIBUTE_USED static BYTE infiniteRegionData[] = {
394 	/* --RegionHeader-- */
395 	/* Size */          0x0C, 0x00, 0x00, 0x00,
396 	/* Checksum */      0x9B, 0x34, 0x22, 0xA3,
397 	/* Magic */         0x02, 0x10, 0xC0, 0xDB,
398 	/* Combining Ops */ 0x00, 0x00, 0x00, 0x00,
399 
400 	/* -- Entry -- */
401 	/* Type */ 0x03, 0x00, 0x00, 0x10
402 };
403 
404 ATTRIBUTE_USED static BYTE emptyRegionData[] = {
405 	/* --RegionHeader-- */
406 	/* Size */          0x0C, 0x00, 0x00, 0x00,
407 	/* Checksum */      0xFE, 0x53, 0x9E, 0x1B,
408 	/* Magic */         0x02, 0x10, 0xC0, 0xDB,
409 	/* Combining Ops */ 0x00, 0x00, 0x00, 0x00,
410 
411 	/* -- Entry -- */
412 	/* Type */ 0x02, 0x00, 0x00, 0x10
413 };
414 
verifyRegionDataImpl(GpRegion * region,BYTE * expected,INT expectedCount,const char * file,const char * function,int line)415 ATTRIBUTE_USED static void verifyRegionDataImpl (GpRegion *region, BYTE *expected, INT expectedCount, const char *file, const char *function, int line)
416 {
417 	BYTE buffer[1024];
418 
419 	GpStatus status;
420 	UINT dataSize;
421 	UINT sizeFilled;
422 	status = GdipGetRegionDataSize (region, &dataSize);
423 	assertEqualIntImpl (status, Ok, NULL, file, function, line);
424 	assertEqualIntImpl (dataSize, expectedCount, "Region Data Count", file, function, line);
425 
426 	status = GdipGetRegionData (region, buffer, dataSize, &sizeFilled);
427 	assertEqualIntImpl (status, Ok, NULL, file, function, line);
428 	assertEqualBytesImpl (buffer, expected, expectedCount, "Region Data", file, function, line);
429 	assertEqualIntImpl (sizeFilled, expectedCount, "Region Data Size Filled", file, function, line);
430 }
431 
432 #define verifyRegionData(region, expectedData) \
433 	verifyRegionDataImpl (region, expectedData, sizeof (expectedData), __FILE__, __func__, __LINE__)
434 
verifyEmptyRegionImpl(GpRegion * region,const char * file,const char * function,int line)435 ATTRIBUTE_USED static void verifyEmptyRegionImpl (GpRegion *region, const char *file, const char *function, int line)
436 {
437     verifyRegionImpl (region, 0, 0, 0, 0, TRUE, FALSE, file, function, line);
438     verifyRegionScansImpl (region, emptyScans, sizeof (emptyScans), file, function, line);
439 	verifyRegionDataImpl (region, emptyRegionData, sizeof (emptyRegionData), file, function, line);
440 }
441 
442 #define verifyEmptyRegion(region) \
443 	verifyEmptyRegionImpl (region, __FILE__, __func__, __LINE__)
444 
verifyInfiniteRegionImpl(GpRegion * region,const char * file,const char * function,int line)445 ATTRIBUTE_USED static void verifyInfiniteRegionImpl (GpRegion *region, const char *file, const char *function, int line)
446 {
447     verifyRegionImpl (region, -4194304.0f, -4194304.0f, 8388608.0f, 8388608.0f, FALSE, TRUE, file, function, line);
448     verifyRegionScansImpl (region, infiniteScans, sizeof (infiniteScans), file, function, line);
449 	verifyRegionDataImpl (region, infiniteRegionData, sizeof (infiniteRegionData), file, function, line);
450 }
451 
452 #define verifyInfiniteRegion(region) \
453 	verifyInfiniteRegionImpl (region, __FILE__, __func__, __LINE__)
454 
455 ATTRIBUTE_USED static CLSID bmpEncoderClsid = { 0x557cf400, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
456 ATTRIBUTE_USED static CLSID tifEncoderClsid = { 0x557cf405, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
457 ATTRIBUTE_USED static CLSID gifEncoderClsid = { 0x557cf402, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
458 ATTRIBUTE_USED static CLSID pngEncoderClsid = { 0x557cf406, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
459 ATTRIBUTE_USED static CLSID jpegEncoderClsid = { 0x557cf401, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
460 ATTRIBUTE_USED static CLSID icoEncoderClsid = { 0x557cf407, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
461 ATTRIBUTE_USED static CLSID wmfEncoderClsid = { 0x557cf404, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
462 ATTRIBUTE_USED static CLSID emfEncoderClsid = { 0x557cf403, 0x1a04, 0x11d3,{ 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
463 
464 ATTRIBUTE_USED static GUID memoryBmpRawFormat = { 0xb96b3caaU, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
465 ATTRIBUTE_USED static GUID bmpRawFormat = { 0xb96b3cabU, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
466 ATTRIBUTE_USED static GUID tifRawFormat = { 0xb96b3cb1U, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
467 ATTRIBUTE_USED static GUID gifRawFormat = { 0xb96b3cb0U, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
468 ATTRIBUTE_USED static GUID pngRawFormat = { 0xb96b3cafU, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
469 ATTRIBUTE_USED static GUID jpegRawFormat = { 0xb96b3caeU, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
470 ATTRIBUTE_USED static GUID icoRawFormat = { 0xb96b3cb5U, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
471 ATTRIBUTE_USED static GUID wmfRawFormat = { 0xb96b3cadU, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
472 ATTRIBUTE_USED static GUID emfRawFormat = { 0xb96b3cacU, 0x0728U, 0x11d3U,{ 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
473 
is_32bit()474 ATTRIBUTE_USED static BOOL is_32bit()
475 {
476     return sizeof(int *) == 4;
477 }
478 
479 #if defined(USE_WINDOWS_GDIPLUS)
480 #define WINDOWS_GDIPLUS 1
481 #else
482 #define WINDOWS_GDIPLUS 0
483 #endif
484 
485 #define verifyBitmap(image, expectedRawFormat, expectedPixelFormat, expectedWidth, expectedHeight, expectedFlags, expectedPropertyCount, checkFlags) \
486     verifyImage((GpBitmap *) image, ImageTypeBitmap, expectedRawFormat, expectedPixelFormat, 0, 0, expectedWidth, expectedHeight, (REAL)expectedWidth, (REAL)expectedHeight, (REAL)expectedWidth, (REAL)expectedHeight, expectedFlags, expectedPropertyCount, checkFlags)
487 
488 #define verifyMetafile(image, expectedRawFormat, expectedX, expectedY, expectedWidth, expectedHeight, expectedDimensionWidth, expectedDimensionHeight) \
489     verifyImage(image, ImageTypeMetafile, expectedRawFormat, PixelFormat32bppRGB, expectedX, expectedY, expectedWidth, expectedHeight, (REAL)expectedWidth, (REAL)expectedHeight, expectedDimensionWidth, expectedDimensionHeight, 327683, 0, TRUE)
490 
491 #define verifyImage(image, expectedType, expectedRawFormat, expectedPixelFormat, expectedX, expectedY, expectedWidth, expectedHeight, expectedBoundsWidth, expectedBoundsHeight, expectedDimensionWidth, expectedDimensionHeight, expectedFlags, expectedPropertyCount, checkFlags) \
492 { \
493     GpStatus status; \
494     ImageType type; \
495     GUID rawFormat; \
496     PixelFormat pixelFormat; \
497     UINT width; \
498     UINT height; \
499     GpRectF bounds; \
500     GpUnit unit; \
501     REAL dimensionWidth; \
502     REAL dimensionHeight; \
503     UINT flags; \
504     UINT propertyCount; \
505  \
506     status = GdipGetImageType (image, &type); \
507     assertEqualInt (status, Ok); \
508     assertEqualInt (type, expectedType); \
509  \
510     status = GdipGetImageRawFormat (image, &rawFormat); \
511     assertEqualInt (status, Ok); \
512     assertEqualGuid (rawFormat, expectedRawFormat); \
513  \
514     status = GdipGetImagePixelFormat (image, &pixelFormat); \
515     assertEqualInt (status, Ok); \
516     assertEqualInt (pixelFormat, expectedPixelFormat); \
517  \
518     status = GdipGetImageWidth (image, &width); \
519     assertEqualInt (status, Ok); \
520     assertEqualInt (width, expectedWidth); \
521  \
522     status = GdipGetImageHeight (image, &height); \
523     assertEqualInt (status, Ok); \
524     assertEqualInt (height, expectedHeight); \
525  \
526     status = GdipGetImageBounds (image, &bounds, &unit); \
527     assertEqualInt (status, Ok); \
528     assertEqualFloat (bounds.X, expectedX); \
529     assertEqualFloat (bounds.Y, expectedY); \
530     assertEqualFloat (bounds.Width, expectedBoundsWidth); \
531     assertEqualFloat (bounds.Height, expectedBoundsHeight); \
532     assertEqualInt (unit, UnitPixel); \
533  \
534     /* Libgdiplus and GDI+ have different exact degrees of accuracy. */ \
535     /* Typically they differ by +-0.02. */ \
536     /* This is an acceptable difference. */ \
537     status = GdipGetImageDimension (image, &dimensionWidth, &dimensionHeight); \
538     assertEqualInt (status, Ok); \
539     if (fabsf (dimensionWidth - expectedDimensionWidth) > 0.05) \
540         assertEqualFloat (dimensionWidth, expectedDimensionWidth); \
541     if (fabsf (dimensionHeight - expectedDimensionHeight) > 0.05) \
542         assertEqualFloat (dimensionHeight, expectedDimensionHeight); \
543  \
544     /* FIXME: libgdiplus and GDI+ have different results for bitmap images. */ \
545     if (checkFlags || WINDOWS_GDIPLUS) \
546     { \
547         status = GdipGetImageFlags (image, &flags); \
548         assertEqualInt (status, Ok); \
549         assertEqualInt (flags, (expectedFlags)); \
550     } \
551  \
552     status = GdipGetPropertyCount (image, &propertyCount); \
553     assertEqualInt (status, Ok); \
554     /* FIXME: libgdiplus returns 0 for each image. */ \
555     if (WINDOWS_GDIPLUS) \
556     { \
557         assertEqualInt (propertyCount, expectedPropertyCount); \
558     } \
559 }
560 
561 
assertEqualARGBImpl(ARGB actual,ARGB expected,const char * message,const char * file,const char * function,int line)562 ATTRIBUTE_USED static void assertEqualARGBImpl (ARGB actual, ARGB expected, const char *message, const char *file, const char *function, int line)
563 {
564     if (actual != expected)
565     {
566         if (message)
567             fprintf (stderr, "%s\n", message);
568 
569         printFailure (file, function, line);
570         fprintf (stderr, "Expected: 0x%08X\n", expected);
571         fprintf (stderr, "Actual:   0x%08X\n", actual);
572         abort();
573     }
574 }
575 
576 #define assertEqualARGB(actual, expected) assertEqualARGBImpl (actual, expected, NULL, __FILE__, __func__, __LINE__)
577 
578 #define verifyPixels(image, expectedPixels) \
579 { \
580     GpStatus status; \
581     UINT width; \
582     UINT height; \
583     GdipGetImageWidth ((GpBitmap *) image, &width); \
584     GdipGetImageHeight ((GpBitmap *) image, &height); \
585  \
586     for (UINT y = 0; y < height; y++) \
587     { \
588         for (UINT x = 0; x < width; x++) \
589         { \
590             ARGB expected = expectedPixels[x + y * width]; \
591             ARGB actual; \
592             status = GdipBitmapGetPixel ((GpBitmap *) image, x, y, &actual); \
593             assertEqualInt (status, Ok); \
594             if (actual != expected) \
595             { \
596                 fprintf (stderr, "Pixel [%u, %u]\n", x, y); \
597                 fprintf (stderr, "Expected: 0x%08X\n", expected); \
598                 fprintf (stderr, "Actual:   0x%08X\n", actual);   \
599                 dumpPixels (image); \
600                 assert (expected == actual); \
601             } \
602         } \
603     } \
604 }
605 
606 #define verifyPalette(image, flags, entries) \
607 { \
608     GpStatus status; \
609     INT size; \
610     ColorPalette *palette; \
611  \
612     status = GdipGetImagePaletteSize (image, &size); \
613     assertEqualInt (status, Ok); \
614  \
615     palette = (ColorPalette *) GdipAlloc (size); \
616     status = GdipGetImagePalette (image, palette, size); \
617     assertEqualInt (status, Ok); \
618  \
619     assertEqualInt (palette->Flags, flags); \
620     assertEqualInt (palette->Count, (int) (sizeof (entries) / sizeof (ARGB))); \
621  \
622     for (UINT i = 0; i < palette->Count; i++) \
623     { \
624         if (palette->Entries[i] != entries[i]) \
625         { \
626             fprintf (stderr, "Index [%u]\n", i); \
627             fprintf (stderr, "Expected: 0x%08X\n", entries[i]); \
628             fprintf (stderr, "Actual:   0x%08X\n", palette->Entries[i]);   \
629             dumpPalette (palette); \
630             assert (entries[i] == palette->Entries[i]); \
631         } \
632     } \
633  \
634     GdipFree (palette); \
635 }
636 
637 #define verifyNoPalette(image, flags) \
638 { \
639     GpStatus status; \
640     INT size; \
641     ColorPalette *palette; \
642  \
643     status = GdipGetImagePaletteSize (image, &size); \
644     assertEqualInt (status, Ok); \
645  \
646     palette = (ColorPalette *) GdipAlloc (size); \
647     memset (palette, 0, sizeof (ColorPalette)); \
648     palette->Entries[0] = 0x123; \
649     status = GdipGetImagePalette (image, palette, size); \
650     assertEqualInt (status, Ok); \
651     assertEqualInt (size, sizeof (ColorPalette)); \
652  \
653     assertEqualInt (palette->Flags, flags); \
654     assertEqualInt (palette->Count, 0); \
655     assertEqualInt (palette->Entries[0], 0x123); \
656  \
657     GdipFree (palette); \
658 }
659 
660 #define HEX__(n) 0x##n##LU
661 #define B8__(x) ((x&0x0000000FLU)?1:0) \
662 + ((x&0x000000F0LU)?2:0)               \
663 + ((x&0x00000F00LU)?4:0)               \
664 + ((x&0x0000F000LU)?8:0)               \
665 + ((x&0x000F0000LU)?16:0)              \
666 + ((x&0x00F00000LU)?32:0)              \
667 + ((x&0x0F000000LU)?64:0)              \
668 + ((x&0xF0000000LU)?128:0)
669 
670 #define B8(d) ((BYTE)B8__(HEX__(d)))
671 
672 // A utility for dumping pixel arrays to the console for debugging purposes.
dumpPixels(GpImage * image)673 ATTRIBUTE_USED static void dumpPixels (GpImage *image)
674 {
675     UINT width;
676     UINT height;
677     GdipGetImageWidth (image, &width);
678     GdipGetImageHeight (image, &height);
679 
680     for (UINT y = 0; y < height; y++)
681     {
682         for (UINT x = 0; x < width; x++)
683         {
684             ARGB pixel;
685             GdipBitmapGetPixel ((GpBitmap *) image, x, y, &pixel);
686             printf ("0x%08X", pixel);
687             if (x != width - 1)
688             {
689                 printf(", ");
690             }
691             else if (y != height - 1)
692             {
693                 printf(",");
694             }
695         }
696 
697         printf("\n");
698     }
699 }
700 
deleteFile(const char * file)701 ATTRIBUTE_USED static void deleteFile(const char *file)
702 {
703 #if !defined(_WIN32)
704     unlink (file);
705 #else
706     remove (file);
707 #endif
708 }
709 
dumpPalette(ColorPalette * palette)710 ATTRIBUTE_USED static void dumpPalette (ColorPalette *palette)
711 {
712     for (UINT i = 0; i < palette->Count; i++)
713     {
714         printf ("0x%08X", palette->Entries[i]);
715         if (i != palette->Count - 1)
716         {
717             printf(", ");
718         }
719     }
720 
721     printf("\n");
722 }
723 
724 // A utility for dumping an image and displaying it for debugging purposes.
dumpImage(GpImage * image)725 ATTRIBUTE_USED static void dumpImage (GpImage *image)
726 {
727 	const WCHAR *wImage = createWchar("test-image.png");
728 	GpStatus status = GdipSaveImageToFile (image, wImage, &pngEncoderClsid, NULL);
729 	assertEqualInt (status, Ok);
730 	int systemResult = system ("test-image.png");
731 	(void) systemResult;
732 }
733