Prevent crash when no URL is specified.
[wine] / dlls / gdi / tests / gdiobj.c
1 /*
2  * Unit test suite for GDI objects
3  *
4  * Copyright 2002 Mike McCormack
5  * Copyright 2004 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdarg.h>
23 #include <assert.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29
30 #include "wine/test.h"
31
32 static void test_logfont(void)
33 {
34     LOGFONTA lf, lfout;
35     HFONT hfont;
36     int ret;
37
38     memset(&lf, 0, sizeof lf);
39
40     lf.lfCharSet = ANSI_CHARSET;
41     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
42     lf.lfWeight = FW_DONTCARE;
43     lf.lfHeight = 16;
44     lf.lfWidth = 16;
45     lf.lfQuality = DEFAULT_QUALITY;
46     lstrcpyA(lf.lfFaceName, "Arial");
47
48     hfont = CreateFontIndirectA(&lf);
49     ok(hfont != 0, "CreateFontIndirect failed\n");
50
51     ret = GetObjectA(hfont, sizeof(lfout), &lfout);
52     ok(ret == sizeof(lfout),
53        "GetObject returned %d expected %d\n", ret, sizeof(lfout));
54
55     ok(!memcmp(&lfout, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "fonts don't match\n");
56     ok(!lstrcmpA(lfout.lfFaceName, lf.lfFaceName),
57        "font names don't match: %s != %s\n", lfout.lfFaceName, lf.lfFaceName);
58
59     DeleteObject(hfont);
60
61     memset(&lf, 'A', sizeof(lf));
62     hfont = CreateFontIndirectA(&lf);
63     ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n");
64
65     ok(GetObjectA(hfont, sizeof(lfout), NULL) == sizeof(lfout),
66        "GetObjectA with NULL failed\n");
67
68     ok(GetObjectA(hfont, sizeof(lfout), &lfout) == sizeof(lfout),
69        "GetObjectA failed\n");
70     ok(!memcmp(&lfout, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "fonts don't match\n");
71     lf.lfFaceName[LF_FACESIZE - 1] = 0;
72     ok(!lstrcmpA(lfout.lfFaceName, lf.lfFaceName),
73        "font names don't match: %s != %s\n", lfout.lfFaceName, lf.lfFaceName);
74
75     DeleteObject(hfont);
76 }
77
78 static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
79 {
80     if (type & RASTER_FONTTYPE)
81     {
82         LOGFONT *lf = (LOGFONT *)lParam;
83         *lf = *elf;
84         return 0; /* stop enumeration */
85     }
86
87     return 1; /* continue enumeration */
88 }
89
90 static void test_font_metrics(HDC hdc, HFONT hfont, const char *test_str,
91                               INT test_str_len, const TEXTMETRICA *tm_orig,
92                               const SIZE *size_orig, INT width_orig,
93                               INT scale_x, INT scale_y)
94 {
95     HFONT old_hfont;
96     TEXTMETRICA tm;
97     SIZE size;
98     INT width;
99
100     old_hfont = SelectObject(hdc, hfont);
101
102     GetTextMetricsA(hdc, &tm);
103
104     ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y);
105     ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y);
106     ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y);
107     ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
108
109     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
110
111     ok(size.cx == size_orig->cx * scale_x, "%ld != %ld\n", size.cx, size_orig->cx * scale_x);
112     ok(size.cy == size_orig->cy * scale_y, "%ld != %ld\n", size.cy, size_orig->cy * scale_y);
113
114     GetCharWidthA(hdc, 'A', 'A', &width);
115
116     ok(width == width_orig * scale_x, "%d != %d\n", width, width_orig * scale_x);
117
118     SelectObject(hdc, old_hfont);
119 }
120
121 /* see whether GDI scales bitmap font metrics */
122 static void test_bitmap_font(void)
123 {
124     static const char test_str[11] = "Test String";
125     HDC hdc;
126     LOGFONTA bitmap_lf, lf;
127     HFONT hfont, old_hfont;
128     TEXTMETRICA tm_orig;
129     SIZE size_orig;
130     INT ret, i, width_orig, height_orig;
131
132     hdc = GetDC(0);
133
134     /* "System" has only 1 pixel size defined, otherwise the test breaks */
135     ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf);
136     if (ret)
137     {
138         ReleaseDC(0, hdc);
139         trace("no bitmap fonts were found, skipping the test\n");
140         return;
141     }
142
143     trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight);
144
145     height_orig = bitmap_lf.lfHeight;
146     hfont = CreateFontIndirectA(&bitmap_lf);
147     assert(hfont);
148
149     old_hfont = SelectObject(hdc, hfont);
150     ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n");
151     ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n");
152     ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n");
153     SelectObject(hdc, old_hfont);
154     DeleteObject(hfont);
155
156     /* test fractional scaling */
157     for (i = 1; i < height_orig; i++)
158     {
159         bitmap_lf.lfHeight = i;
160         hfont = CreateFontIndirectA(&bitmap_lf);
161         assert(hfont);
162
163         ret = GetObject(hfont, sizeof(lf), &lf);
164         ok(ret == sizeof(lf), "GetObject failed: %d\n", ret);
165         ok(!memcmp(&bitmap_lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "fonts don't match\n");
166         ok(!lstrcmpA(bitmap_lf.lfFaceName, lf.lfFaceName),
167            "font names don't match: %s != %s\n", bitmap_lf.lfFaceName, lf.lfFaceName);
168
169         test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1);
170         DeleteObject(hfont);
171     }
172
173     /* test integer scaling 3x2 */
174     bitmap_lf.lfHeight = height_orig * 2;
175     bitmap_lf.lfWidth *= 3;
176     hfont = CreateFontIndirectA(&bitmap_lf);
177     assert(hfont);
178
179     ret = GetObject(hfont, sizeof(lf), &lf);
180     ok(ret == sizeof(lf), "GetObject failed: %d\n", ret);
181     ok(!memcmp(&bitmap_lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "fonts don't match\n");
182     ok(!lstrcmpA(bitmap_lf.lfFaceName, lf.lfFaceName),
183        "font names don't match: %s != %s\n", bitmap_lf.lfFaceName, lf.lfFaceName);
184 todo_wine
185 {
186     test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2);
187 }
188     DeleteObject(hfont);
189
190     /* test integer scaling 3x3 */
191     bitmap_lf.lfHeight = height_orig * 3;
192     bitmap_lf.lfWidth = 0;
193     hfont = CreateFontIndirectA(&bitmap_lf);
194     assert(hfont);
195
196     ret = GetObject(hfont, sizeof(lf), &lf);
197     ok(ret == sizeof(lf), "GetObject failed: %d\n", ret);
198     ok(!memcmp(&bitmap_lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "fonts don't match\n");
199     ok(!lstrcmpA(bitmap_lf.lfFaceName, lf.lfFaceName),
200        "font names don't match: %s != %s\n", bitmap_lf.lfFaceName, lf.lfFaceName);
201 todo_wine
202 {
203     test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3);
204 }
205     DeleteObject(hfont);
206
207     ReleaseDC(0, hdc);
208 }
209
210 static void test_gdi_objects(void)
211 {
212     BYTE buff[256];
213     HDC hdc = GetDC(NULL);
214     HPEN hp;
215     int i;
216     BOOL ret;
217
218     /* SelectObject() with a NULL DC returns 0 and sets ERROR_INVALID_HANDLE.
219      * Note: Under XP at least invalid ptrs can also be passed, not just NULL;
220      *       Don't test that here in case it crashes earlier win versions.
221      */
222     SetLastError(0);
223     hp = SelectObject(NULL, GetStockObject(BLACK_PEN));
224     ok(!hp && GetLastError() == ERROR_INVALID_HANDLE,
225        "SelectObject(NULL DC) expected 0, ERROR_INVALID_HANDLE, got %p, 0x%08lx\n",
226        hp, GetLastError());
227
228     /* With a valid DC and a NULL object, the call returns 0 but does not SetLastError() */
229     SetLastError(0);
230     hp = SelectObject(hdc, NULL);
231     ok(!hp && !GetLastError(),
232        "SelectObject(NULL obj) expected 0, NO_ERROR, got %p, 0x%08lx\n",
233        hp, GetLastError());
234
235     /* The DC is unaffected by the NULL SelectObject */
236     SetLastError(0);
237     hp = SelectObject(hdc, GetStockObject(BLACK_PEN));
238     ok(hp && !GetLastError(),
239        "SelectObject(post NULL) expected non-null, NO_ERROR, got %p, 0x%08lx\n",
240        hp, GetLastError());
241
242     /* GetCurrentObject does not SetLastError() on a null object */
243     SetLastError(0);
244     hp = GetCurrentObject(NULL, OBJ_PEN);
245     ok(!hp && !GetLastError(),
246        "GetCurrentObject(NULL DC) expected 0, NO_ERROR, got %p, 0x%08lx\n",
247        hp, GetLastError());
248
249     /* DeleteObject does not SetLastError() on a null object */
250     ret = DeleteObject(NULL);
251     ok( !ret && !GetLastError(),
252        "DeleteObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n",
253        ret, GetLastError());
254
255     /* GetObject does not SetLastError() on a null object */
256     SetLastError(0);
257     i = GetObjectA(NULL, sizeof(buff), buff);
258     ok (!i && !GetLastError(),
259         "GetObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n",
260         i, GetLastError());
261
262     /* GetObjectType does SetLastError() on a null object */
263     SetLastError(0);
264     i = GetObjectType(NULL);
265     ok (!i && GetLastError() == ERROR_INVALID_HANDLE,
266         "GetObjectType(NULL obj), expected 0, ERROR_INVALID_HANDLE, got %d, 0x%08lx\n",
267         i, GetLastError());
268
269     /* UnrealizeObject does not SetLastError() on a null object */
270     SetLastError(0);
271     i = UnrealizeObject(NULL);
272     ok (!i && !GetLastError(),
273         "UnrealizeObject(NULL obj), expected 0, NO_ERROR, got %d, 0x%08lx\n",
274         i, GetLastError());
275
276     ReleaseDC(NULL, hdc);
277 }
278
279 START_TEST(gdiobj)
280 {
281     test_logfont();
282     test_bitmap_font();
283     test_gdi_objects();
284 }