1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         Test for World Transformation and font rendering
5  * PROGRAMMERS:     Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #include "precomp.h"
9 
10 typedef struct tagBITMAPINFOEX
11 {
12     BITMAPINFOHEADER bmiHeader;
13     RGBQUAD          bmiColors[256];
14 } BITMAPINFOEX, FAR *LPBITMAPINFOEX;
15 
16 #if 1
17     #define SaveBitmapToFile(f, h)
18 #else
19 static BOOL SaveBitmapToFile(LPCWSTR pszFileName, HBITMAP hbm)
20 {
21     BOOL f;
22     BITMAPFILEHEADER bf;
23     BITMAPINFOEX bmi;
24     BITMAPINFOHEADER *pbmih;
25     DWORD cb, cbColors;
26     HDC hDC;
27     HANDLE hFile;
28     LPVOID pBits;
29     BITMAP bm;
30 
31     if (!GetObjectW(hbm, sizeof(BITMAP), &bm))
32         return FALSE;
33 
34     pbmih = &bmi.bmiHeader;
35     ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER));
36     pbmih->biSize             = sizeof(BITMAPINFOHEADER);
37     pbmih->biWidth            = bm.bmWidth;
38     pbmih->biHeight           = bm.bmHeight;
39     pbmih->biPlanes           = 1;
40     pbmih->biBitCount         = bm.bmBitsPixel;
41     pbmih->biCompression      = BI_RGB;
42     pbmih->biSizeImage        = bm.bmWidthBytes * bm.bmHeight;
43 
44     if (bm.bmBitsPixel < 16)
45         cbColors = (1 << bm.bmBitsPixel) * sizeof(RGBQUAD);
46     else
47         cbColors = 0;
48 
49     bf.bfType = 0x4d42;
50     bf.bfReserved1 = 0;
51     bf.bfReserved2 = 0;
52     cb = sizeof(BITMAPFILEHEADER) + pbmih->biSize + cbColors;
53     bf.bfOffBits = cb;
54     bf.bfSize = cb + pbmih->biSizeImage;
55 
56     pBits = HeapAlloc(GetProcessHeap(), 0, pbmih->biSizeImage);
57     if (pBits == NULL)
58         return FALSE;
59 
60     f = FALSE;
61     hDC = CreateCompatibleDC(NULL);
62     if (hDC)
63     {
64         if (GetDIBits(hDC, hbm, 0, bm.bmHeight, pBits, (BITMAPINFO *)&bmi,
65                       DIB_RGB_COLORS))
66         {
67             hFile = CreateFileW(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
68                                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL |
69                                 FILE_FLAG_WRITE_THROUGH, NULL);
70             if (hFile != INVALID_HANDLE_VALUE)
71             {
72                 f = WriteFile(hFile, &bf, sizeof(BITMAPFILEHEADER), &cb, NULL) &&
73                     WriteFile(hFile, &bmi, sizeof(BITMAPINFOHEADER), &cb, NULL) &&
74                     WriteFile(hFile, bmi.bmiColors, cbColors, &cb, NULL) &&
75                     WriteFile(hFile, pBits, pbmih->biSizeImage, &cb, NULL);
76                 CloseHandle(hFile);
77 
78                 if (!f)
79                     DeleteFileW(pszFileName);
80             }
81         }
82         DeleteDC(hDC);
83     }
84     HeapFree(GetProcessHeap(), 0, pBits);
85     return f;
86 }
87 #endif
88 
89 typedef struct TEST_ENTRY
90 {
91     INT line;               // line number
92     INT GraphicsMode;       // GM_COMPATIBLE or GM_ADVANCED
93     POINT ptRef;            // reference point
94     INT TextAlign;
95     XFORM xform;
96     BOOL xform_ok;
97     LPCWSTR filename;
98     INT cWhitePoints;       // number of white points
99     POINT WhitePoints[4];
100     INT cBlackPoints;       // number of black points
101     POINT BlackPoints[4];
102 } TEST_ENTRY;
103 
104 #define WIDTH 400
105 #define HEIGHT 400
106 #define XCENTER (WIDTH / 2)
107 #define YCENTER (HEIGHT / 2)
108 #define BLACK RGB(0, 0, 0)
109 #define WHITE RGB(255, 255, 255)
110 #define LFHEIGHT -100
111 
112 static const RECT s_rc = {0, 0, WIDTH, HEIGHT};
113 static HBRUSH s_hWhiteBrush = NULL;
114 static HPEN s_hRedPen = NULL;
115 
116 #define POS(ix, iy) {XCENTER + (ix) * WIDTH/8, YCENTER + (iy) * HEIGHT/8}
117 
118 #define NO_TRANS_1 \
119     3, {POS(1, 1), POS(-1, 1), POS(-1, -1)}, 1, {POS(1, -1)}
120 
121 #define NO_TRANS_2 \
122     3, {POS(1, -1), POS(-1, 1), POS(-1, -1)}, 1, {POS(1, 1)}
123 
124 static const TEST_ENTRY s_entries[] =
125 {
126     // GM_COMPATIBLE TA_BOTTOM
127     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 0, 0, 1, 0, 0}, FALSE, L"000.bmp", NO_TRANS_1},
128     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1.5, 0, 0, 1, 0, 0}, FALSE, L"001.bmp", NO_TRANS_1},
129     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 0, 0, 1.5, 0, 0}, FALSE, L"002.bmp", NO_TRANS_1},
130     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {-1, 0, 0, 1, 0, 0}, FALSE, L"003.bmp", NO_TRANS_1},
131     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 0, 0, -1, 0, 0}, FALSE, L"004.bmp", NO_TRANS_1},
132     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 1, 1, 0, 0, 0}, FALSE, L"005.bmp", NO_TRANS_1},
133     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, -1, 1, 0, 0, 0}, FALSE, L"006.bmp", NO_TRANS_1},
134     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 1, -1, 0, 0, 0}, FALSE, L"007.bmp", NO_TRANS_1},
135     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, -1, -1, 0, 0, 0}, FALSE, L"009.bmp", NO_TRANS_1},
136     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 1, 0, 1, 0, 0}, FALSE, L"009.bmp", NO_TRANS_1},
137     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 1, 1, 1, 0, 0}, FALSE, L"010.bmp", NO_TRANS_1},
138     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 0, 0, 0, 0, 0}, FALSE, L"011.bmp", NO_TRANS_1},
139     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 0, 0, 0, 1000, 0}, FALSE, L"012.bmp", NO_TRANS_1},
140     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 0, 0, 0, 0, 1000}, FALSE, L"013.bmp", NO_TRANS_1},
141 
142     // GM_COMPATIBLE TA_TOP
143     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {1, 0, 0, 1, 0, 0}, FALSE, L"100.bmp", NO_TRANS_2},
144     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {1.5, 0, 0, 1, 0, 0}, FALSE, L"101.bmp", NO_TRANS_2},
145     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {1, 0, 0, 1.5, 0, 0}, FALSE, L"102.bmp", NO_TRANS_2},
146     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {-1, 0, 0, 1, 0, 0}, FALSE, L"103.bmp", NO_TRANS_2},
147     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {1, 0, 0, -1, 0, 0}, FALSE, L"104.bmp", NO_TRANS_2},
148     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, 1, 1, 0, 0, 0}, FALSE, L"105.bmp", NO_TRANS_2},
149     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, -1, 1, 0, 0, 0}, FALSE, L"106.bmp", NO_TRANS_2},
150     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, 1, -1, 0, 0, 0}, FALSE, L"107.bmp", NO_TRANS_2},
151     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, -1, -1, 0, 0, 0}, FALSE, L"109.bmp", NO_TRANS_2},
152     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, 1, 0, 1, 0, 0}, FALSE, L"109.bmp", NO_TRANS_2},
153     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {1, 1, 1, 1, 0, 0}, FALSE, L"110.bmp", NO_TRANS_2},
154     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, 0, 0, 0, 0, 0}, FALSE, L"111.bmp", NO_TRANS_2},
155     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, 0, 0, 0, 1000, 0}, FALSE, L"112.bmp", NO_TRANS_2},
156     {__LINE__, GM_COMPATIBLE, {XCENTER, YCENTER}, TA_LEFT | TA_TOP, {0, 0, 0, 0, 0, 1000}, FALSE, L"113.bmp", NO_TRANS_2},
157 
158     // GM_ADVANCED TA_LEFT TA_BOTTOM
159     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 0, 0, 1, 0, 0}, TRUE, L"200.bmp", NO_TRANS_1},
160     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1.5, 0, 0, 1, 0, 0}, TRUE, L"201.bmp",
161         4, {POS(-1, -1), POS(1, -1), POS(-1, 1), POS(1, 1)}, 1, {POS(3, -1)}},
162     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 0, 0, 1.5, 0, 0}, TRUE, L"202.bmp",
163         3, {POS(-1, -1), POS(-1, 1), POS(1, -1)}, 1, {POS(1, 1)}},
164     {__LINE__, GM_ADVANCED, {-XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {-1, 0, 0, 1, 0, 0}, TRUE, L"203.bmp",
165         3, {POS(1, -1), POS(-1, 1), POS(1, -1)}, 1, {POS(-1, -1)}},
166     {__LINE__, GM_ADVANCED, {XCENTER, -YCENTER}, TA_LEFT | TA_BOTTOM, {1, 0, 0, -1, 0, 0}, TRUE, L"204.bmp",
167         3, {POS(-1, -1), POS(-1, 1), POS(1, -1)}, 1, {POS(1, 1)}},
168     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 1, 1, 0, 0, 0}, TRUE, L"205.bmp",
169         3, {POS(-1, -1), POS(1, 1), POS(1, -1)}, 1, {POS(-1, 1)}},
170     {__LINE__, GM_ADVANCED, {-XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, -1, 1, 0, 0, 0}, TRUE, L"206.bmp",
171         3, {POS(-1, 1), POS(1, 1), POS(1, -1)}, 1, {POS(-1, -1)}},
172     {__LINE__, GM_ADVANCED, {XCENTER, -YCENTER}, TA_LEFT | TA_BOTTOM, {0, 1, -1, 0, 0, 0}, TRUE, L"207.bmp",
173         3, {POS(-1, 1), POS(-1, -1), POS(1, -1)}, 1, {POS(1, 1)}},
174     {__LINE__, GM_ADVANCED, {-XCENTER, -YCENTER}, TA_LEFT | TA_BOTTOM, {0, -1, -1, 0, 0, 0}, TRUE, L"208.bmp",
175         3, {POS(-1, 1), POS(-1, -1), POS(1, 1)}, 1, {POS(1, -1)}},
176     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 1, 0, 1, 0, 0}, FALSE, L"209.bmp", NO_TRANS_1},
177     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {1, 1, 1, 1, 0, 0}, FALSE, L"210.bmp", NO_TRANS_1},
178     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 0, 0, 0, 0, 0}, FALSE, L"211.bmp", NO_TRANS_1},
179     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 0, 0, 0, 1000, 0}, FALSE, L"212.bmp", NO_TRANS_1},
180     {__LINE__, GM_ADVANCED, {XCENTER, YCENTER}, TA_LEFT | TA_BOTTOM, {0, 0, 0, 0, 0, 1000}, FALSE, L"213.bmp", NO_TRANS_1},
181 
182     // GM_ADVANCED TA_LEFT TA_TOP
183     {__LINE__, GM_ADVANCED, {0, 0}, TA_LEFT | TA_TOP, {2, 0, 0, 1, 0, 0}, TRUE, L"300.bmp",
184         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -3), POS(-1, -3)}},
185     {__LINE__, GM_ADVANCED, {0, 0}, TA_LEFT | TA_TOP, {1, 0, 0, 2, 0, 0}, TRUE, L"301.bmp",
186         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -3), POS(-3, -1)}},
187     {__LINE__, GM_ADVANCED, {0, 0}, TA_LEFT | TA_TOP, {2, 0, 0, 1, WIDTH/4, 0}, TRUE, L"302.bmp",
188         3, {POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, -3), POS(1, -3)}},
189     {__LINE__, GM_ADVANCED, {0, 0}, TA_LEFT | TA_TOP, {1, 0, 0, 2, WIDTH/4, 0}, TRUE, L"303.bmp",
190         3, {POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, -3), POS(-1, -1)}},
191     {__LINE__, GM_ADVANCED, {0, 0}, TA_LEFT | TA_TOP, {2, 0, 0, 1, 0, HEIGHT/4}, TRUE, L"304.bmp",
192         3, {POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -1), POS(-1, -1)}},
193     {__LINE__, GM_ADVANCED, {0, 0}, TA_LEFT | TA_TOP, {1, 0, 0, 2, 0, HEIGHT/4}, TRUE, L"305.bmp",
194         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -1), POS(-3, 1)}},
195     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_LEFT | TA_TOP, {2, 0, 0, 1, 0, 0}, TRUE, L"306.bmp",
196         3, {POS(-1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, 1), POS(-1, 1)}},
197     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_LEFT | TA_TOP, {1, 0, 0, 2, 0, -HEIGHT/2}, TRUE, L"307.bmp",
198         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, 3), POS(-3, 1)}},
199     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_LEFT | TA_TOP, {2, 0, 0, 1, WIDTH/4, 0}, TRUE, L"308.bmp",
200         2, {POS(-1, -1), POS(1, -1)}, 2, {POS(-1, 1), POS(1, 1)}},
201     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_LEFT | TA_TOP, {1, 0, 0, 2, WIDTH/4, -HEIGHT/2}, TRUE, L"309.bmp",
202         3, {POS(-1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, 1), POS(-1, 3)}},
203     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_LEFT | TA_TOP, {2, 0, 0, 1, 0, HEIGHT/4}, TRUE, L"310.bmp",
204         4, {POS(-1, -1), POS(1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, 3), POS(-1, 3)}},
205     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_LEFT | TA_TOP, {1, 0, 0, 2, 0, -HEIGHT/2}, TRUE, L"311.bmp",
206         4, {POS(-1, -1), POS(1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, 3), POS(-3, 1)}},
207 
208     // GM_ADVANCED TA_CENTER TA_TOP
209     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_CENTER | TA_TOP, {2, 0, 0, 1, -WIDTH/4, 0}, TRUE, L"400.bmp",
210         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(1, -3), POS(3, -3)}},
211     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_CENTER | TA_TOP, {1, 0, 0, 2, WIDTH/8, 0}, TRUE, L"401.bmp",
212         3, {POS(-1, -1), POS(-1, 1), POS(1, 1)}, 2, {POS(1, -3), POS(1, -1)}},
213     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_CENTER | TA_TOP, {2, 0, 0, 2, -WIDTH/4, HEIGHT/4}, TRUE, L"402.bmp",
214         2, {POS(-1, 1), POS(-1, -1)}, 4, {POS(1, -1), POS(3, -1), POS(1, 1), POS(3, 1)}},
215     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_CENTER | TA_TOP, {1, 0, 0, 2, WIDTH/8, 0}, TRUE, L"403.bmp",
216         3, {POS(-1, -1), POS(-1, 1), POS(1, 1)}, 2, {POS(1, -1), POS(1, -3)}},
217     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_CENTER | TA_TOP, {2, 0, 0, 1, -WIDTH/4, HEIGHT/4}, TRUE, L"404.bmp",
218         2, {POS(-1, 1), POS(1, 1)}, 2, {POS(1, -1), POS(3, -1)}},
219     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_CENTER | TA_TOP, {1, 0, 0, 2, WIDTH/8, HEIGHT/4}, TRUE, L"405.bmp",
220         2, {POS(-1, -1), POS(-1, 1)}, 2, {POS(1, -1), POS(1, 1)}},
221     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_CENTER | TA_TOP, {1, 0, 0, 2, WIDTH/8, -HEIGHT/2}, TRUE, L"406.bmp",
222         4, {POS(-1, -1), POS(1, -1), POS(-1, 1), POS(1, 1)}, 2, {POS(-3, 1), POS(-3, 3)}},
223     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_CENTER | TA_TOP, {2, 0, 0, 1, WIDTH/4, -HEIGHT/2}, TRUE, L"407.bmp",
224         4, {POS(-1, -1), POS(1, -1), POS(-1, 1), POS(1, 1)}, 2, {POS(-3, -3), POS(-1, -3)}},
225     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_CENTER | TA_TOP, {2, 0, 0, 2, WIDTH/4, -HEIGHT/2}, TRUE, L"408.bmp",
226         3, {POS(-1, -1), POS(1, -1), POS(1, 1)}, 4, {POS(-3, 3), POS(-3, 1), POS(-3, 1), POS(-1, 1)}},
227     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_CENTER | TA_TOP, {1, 0, 0, 2, WIDTH/8, -HEIGHT/2}, TRUE, L"409.bmp",
228         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, 3), POS(-3, 1)}},
229     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_CENTER | TA_TOP, {2, 0, 0, 1, WIDTH/4, -HEIGHT/2}, TRUE, L"410.bmp",
230         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -3), POS(-1, -3)}},
231     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_CENTER | TA_TOP, {1, 0, 0, 2, WIDTH/8, -HEIGHT/2}, TRUE, L"411.bmp",
232         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, 1), POS(-3, 3)}},
233 
234     // GM_ADVANCED TA_RIGHT TA_TOP
235     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_RIGHT | TA_TOP, {2, 0, 0, 1, -WIDTH/4, 0}, TRUE, L"500.bmp",
236         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, -3), POS(1, -3)}},
237     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_RIGHT | TA_TOP, {1, 0, 0, 2, WIDTH/4, 0}, TRUE, L"501.bmp",
238         3, {POS(-1, -1), POS(-1, 1), POS(1, 1)}, 2, {POS(1, -3), POS(1, -1)}},
239     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_RIGHT | TA_TOP, {2, 0, 0, 2, -WIDTH/4, HEIGHT/4}, TRUE, L"502.bmp",
240         0, {POS(0, 0)}, 4, {POS(-1, -1), POS(1, -1), POS(1, -1), POS(-1, -1)}},
241     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_RIGHT | TA_TOP, {1, 0, 0, 2, WIDTH/4, 0}, TRUE, L"503.bmp",
242         3, {POS(-1, 1), POS(1, 1), POS(-1, -1)}, 2, {POS(1, -1), POS(1, -3)}},
243     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_RIGHT | TA_TOP, {2, 0, 0, 1, -WIDTH/4, HEIGHT/4}, TRUE, L"504.bmp",
244         2, {POS(-1, 1), POS(1, 1)}, 2, {POS(-1, -1), POS(1, -1)}},
245     {__LINE__, GM_ADVANCED, {XCENTER, 0}, TA_RIGHT | TA_TOP, {1, 0, 0, 2, WIDTH/4, HEIGHT/4}, TRUE, L"505.bmp",
246         2, {POS(-1, -1), POS(-1, 1)}, 2, {POS(1, -1), POS(1, 1)}},
247     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_RIGHT | TA_TOP, {2, 0, 0, 1, WIDTH/2, -HEIGHT/2}, TRUE, L"506.bmp",
248         4, {POS(-1, -1), POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -3), POS(-1, -3)}},
249     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_RIGHT | TA_TOP, {1, 0, 0, 2, WIDTH/2, -HEIGHT/2}, TRUE, L"507.bmp",
250         3, {POS(-1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, 3), POS(-1, 1)}},
251     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_RIGHT | TA_TOP, {2, 0, 0, 2, WIDTH, -HEIGHT/2}, TRUE, L"508.bmp",
252         3, {POS(-1, -1), POS(-1, 1), POS(1, -1)}, 4, {POS(1, 1), POS(3, 1), POS(1, 3), POS(3, 3)}},
253     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_RIGHT | TA_TOP, {1, 0, 0, 2, WIDTH/2, -HEIGHT/2}, TRUE, L"509.bmp",
254         3, {POS(-1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, 1), POS(-1, 3)}},
255     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_RIGHT | TA_TOP, {2, 0, 0, 1, WIDTH/2, -HEIGHT/4}, TRUE, L"510.bmp",
256         3, {POS(-1, 1), POS(1, -1), POS(1, 1)}, 2, {POS(-3, -1), POS(-1, -1)}},
257     {__LINE__, GM_ADVANCED, {0, YCENTER}, TA_RIGHT | TA_TOP, {1, 0, 0, 2, WIDTH/2, -HEIGHT/2}, TRUE, L"511.bmp",
258         3, {POS(-1, -1), POS(1, -1), POS(1, 1)}, 2, {POS(-1, 1), POS(-1, 3)}},
259 };
260 static const INT s_entry_count = (INT)(sizeof(s_entries) / sizeof(s_entries[0]));
261 
262 static void DoTestEntry(const TEST_ENTRY *entry, HDC hDC, HBITMAP hbm)
263 {
264     HGDIOBJ hbmOld, hPenOld;
265     INT i;
266     COLORREF rgb;
267     BOOL ret;
268     static const WCHAR s_chBlackBox = L'g';
269 
270     SetGraphicsMode(hDC, entry->GraphicsMode);
271 
272     hbmOld = SelectObject(hDC, hbm);
273     {
274         ModifyWorldTransform(hDC, NULL, MWT_IDENTITY);
275 
276         FillRect(hDC, &s_rc, s_hWhiteBrush);
277 
278         hPenOld = SelectObject(hDC, s_hRedPen);
279         {
280             MoveToEx(hDC, XCENTER / 2, 0, NULL);
281             LineTo(hDC, XCENTER / 2, HEIGHT);
282 
283             MoveToEx(hDC, XCENTER, 0, NULL);
284             LineTo(hDC, XCENTER, HEIGHT);
285 
286             MoveToEx(hDC, XCENTER * 3 / 2, 0, NULL);
287             LineTo(hDC, XCENTER * 3 / 2, HEIGHT);
288 
289             MoveToEx(hDC, 0, YCENTER / 2, NULL);
290             LineTo(hDC, WIDTH, YCENTER / 2);
291 
292             MoveToEx(hDC, 0, YCENTER, NULL);
293             LineTo(hDC, WIDTH, YCENTER);
294 
295             MoveToEx(hDC, 0, YCENTER * 3 / 2, NULL);
296             LineTo(hDC, WIDTH, YCENTER * 3 / 2);
297         }
298         SelectObject(hDC, hPenOld);
299 
300         ret = SetWorldTransform(hDC, &entry->xform);
301         ok(ret == entry->xform_ok, "Line %d: SetWorldTransform returned %d\n", entry->line, ret);
302 
303         SetTextAlign(hDC, entry->TextAlign);
304 
305         TextOutW(hDC, entry->ptRef.x, entry->ptRef.y, &s_chBlackBox, 1);
306 
307         ModifyWorldTransform(hDC, NULL, MWT_IDENTITY);
308 
309         for (i = 0; i < entry->cWhitePoints; ++i)
310         {
311             rgb = GetPixel(hDC, entry->WhitePoints[i].x, entry->WhitePoints[i].y);
312             ok(rgb == WHITE, "Line %d: %d: (%ld, %ld) is not white\n", entry->line, i,
313                entry->WhitePoints[i].x, entry->WhitePoints[i].y);
314         }
315 
316         for (i = 0; i < entry->cBlackPoints; ++i)
317         {
318             rgb = GetPixel(hDC, entry->BlackPoints[i].x, entry->BlackPoints[i].y);
319             ok(rgb == BLACK, "Line %d: %d: (%ld, %ld) is not black\n", entry->line, i,
320                entry->BlackPoints[i].x, entry->BlackPoints[i].y);
321         }
322     }
323     SelectObject(hDC, hbmOld);
324 
325     SaveBitmapToFile(entry->filename, hbm);
326 }
327 
328 START_TEST(TextTransform)
329 {
330     HDC hDC;
331     BITMAPINFO bmi;
332     LPVOID pvBits;
333     HBITMAP hbm;
334     LOGFONTA lf;
335     HFONT hFont;
336     HGDIOBJ hFontOld;
337     INT i;
338 
339     s_hWhiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
340     s_hRedPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
341 
342     hDC = CreateCompatibleDC(NULL);
343     ok(hDC != NULL, "hDC was NULL.\n");
344 
345     SetBkMode(hDC, TRANSPARENT);
346     SetMapMode(hDC, MM_ANISOTROPIC);
347 
348     ZeroMemory(&bmi, sizeof(bmi));
349     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
350     bmi.bmiHeader.biWidth = WIDTH;
351     bmi.bmiHeader.biHeight = HEIGHT;
352     bmi.bmiHeader.biPlanes = 1;
353     bmi.bmiHeader.biBitCount = 24;
354     hbm = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0);
355     ok(hbm != NULL, "hbm was NULL.\n");
356 
357     ZeroMemory(&lf, sizeof(lf));
358     lf.lfHeight = LFHEIGHT;
359     lf.lfCharSet = DEFAULT_CHARSET;
360     lstrcpyA(lf.lfFaceName, "Marlett");
361     hFont = CreateFontIndirectA(&lf);
362     ok(hFont != NULL, "hFont was NULL.\n");
363 
364     hFontOld = SelectObject(hDC, hFont);
365     for (i = 0; i < s_entry_count; ++i)
366     {
367         DoTestEntry(&s_entries[i], hDC, hbm);
368     }
369     SelectObject(hDC, hFontOld);
370 
371     DeleteObject(hFont);
372     DeleteObject(hbm);
373 
374     DeleteObject(s_hWhiteBrush);
375     DeleteObject(s_hRedPen);
376 
377     DeleteDC(hDC);
378 }
379