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