1 /*
2 * PROJECT:         ReactOS api tests
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * PURPOSE:         Test for GetGlyphIndices
5 * PROGRAMMERS:     Ged Murphy
6 */
7 
8 #include "precomp.h"
9 
10 #define ok_lasterrornotchanged() \
11     ok_err(0x12345)
12 
13 #define MAX_BMP_GLYPHS 0xFFFF
14 
15 static LPVOID GetResource(LPCWSTR FontName, LPDWORD Size)
16 {
17     HRSRC hRsrc;
18     LPVOID Data;
19 
20     hRsrc = FindResourceW(GetModuleHandleW(NULL), FontName, (LPCWSTR)RT_RCDATA);
21     if (!hRsrc) return NULL;
22 
23     Data = LockResource(LoadResource(GetModuleHandleW(NULL), hRsrc));
24     if (!Data) return NULL;
25 
26     *Size = SizeofResource(GetModuleHandleW(NULL), hRsrc);
27     if (*Size == 0) return NULL;
28 
29     return Data;
30 }
31 
32 static BOOL ExtractTTFFile(LPCWSTR FontName, LPWSTR TempFile)
33 {
34     WCHAR TempPath[MAX_PATH];
35     HANDLE hFile;
36     void *Data;
37     DWORD Size;
38     BOOL ret;
39 
40     Data = GetResource(FontName, &Size);
41     if (!Data) return FALSE;
42 
43     GetTempPathW(MAX_PATH, TempPath);
44     GetTempFileNameW(TempPath, L"ttf", 0, TempFile);
45 
46     hFile = CreateFileW(TempFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
47     if (hFile == INVALID_HANDLE_VALUE) return FALSE;
48 
49     ret = WriteFile(hFile, Data, Size, &Size, NULL);
50 
51     CloseHandle(hFile);
52     return ret;
53 }
54 
55 static BOOL InstallTempFont(LPWSTR TempFile)
56 {
57     if (ExtractTTFFile(L"ReactOSTestTahoma.ttf", TempFile))
58     {
59         if (AddFontResourceExW(TempFile, FR_PRIVATE, 0) > 0)
60         {
61             return TRUE;
62         }
63     }
64 
65     return FALSE;
66 }
67 
68 static VOID RemoveTempFont(LPWSTR TempFile)
69 {
70     BOOL Success;
71     Success = RemoveFontResourceExW(TempFile, FR_PRIVATE, 0);
72     ok(Success, "RemoveFontResourceEx() failed, we're leaving fonts installed : %lu\n", GetLastError());
73     DeleteFileW(TempFile);
74 }
75 
76 static HFONT IntCreateFont(LPWSTR FontName)
77 {
78     LOGFONTW Font = { 0 };
79     Font.lfCharSet = DEFAULT_CHARSET;
80     wcsncpy(Font.lfFaceName, FontName, sizeof(Font.lfFaceName) / sizeof(Font.lfFaceName[0]));
81     return CreateFontIndirectW(&Font);
82 }
83 
84 START_TEST(GetGlyphIndices)
85 {
86     WCHAR Glyphs[MAX_BMP_GLYPHS];
87     WORD Indices[MAX_BMP_GLYPHS];
88     WCHAR Single[2] = { L' ', UNICODE_NULL };
89     WCHAR TempTTFFile[MAX_PATH];
90     HFONT hFont;
91     HDC hdc;
92     int i;
93     DWORD ret;
94     static const WCHAR s_invalids[] = {0xFEFE, 0xFEFF, 0xFFFE, 0};
95 
96     if (!InstallTempFont(TempTTFFile))
97     {
98         skip("Failed to create ttf file for testing\n");
99         return;
100     }
101 
102     hdc = CreateCompatibleDC(NULL);
103     ok(hdc != 0, "CreateCompatibleDC failed, skipping tests.\n");
104     if (!hdc) return;
105 
106     hFont = IntCreateFont(L"ReactOSTestTahoma");
107     ok(hFont != NULL, "Failed to open the test font");
108     SelectObject(hdc, hFont);
109 
110     SetLastError(0x12345);
111 
112     /* Test NULL DC */
113     ok_int(GetGlyphIndicesW(NULL, Single, 1, Indices, 0), GDI_ERROR);
114     ok_lasterrornotchanged();
115 
116     /* Test invalid DC */
117     ok_int(GetGlyphIndicesW((HDC)(ULONG_PTR)0x12345, Single, 1, Indices, 0), GDI_ERROR);
118     ok_lasterrornotchanged();
119 
120     /* Test invalid params */
121     ok_int(GetGlyphIndicesW(hdc, NULL, 1, NULL, 0), GDI_ERROR);
122     ok_lasterrornotchanged();
123     ok_int(GetGlyphIndicesW(hdc, NULL, 32, NULL, 0), GDI_ERROR);
124     ok_lasterrornotchanged();
125     ok_int(GetGlyphIndicesW(hdc, NULL, 0, Indices, 0), GDI_ERROR);
126     ok_lasterrornotchanged();
127     ok_int(GetGlyphIndicesW(hdc, NULL, 1, Indices, 0), GDI_ERROR);
128     ok_lasterrornotchanged();
129     ok_int(GetGlyphIndicesW(hdc, NULL, 32, Indices, 0), GDI_ERROR);
130     ok_lasterrornotchanged();
131     ok_int(GetGlyphIndicesW(hdc, Single, 0, NULL, 0), GDI_ERROR);
132     ok_lasterrornotchanged();
133     ok_int(GetGlyphIndicesW(hdc, Single, 1, NULL, 0), GDI_ERROR);
134     ok_lasterrornotchanged();
135     ok_int(GetGlyphIndicesW(hdc, Glyphs, 32, NULL, 0), GDI_ERROR);
136     ok_lasterrornotchanged();
137     ok_int(GetGlyphIndicesW(hdc, Single, 0, Indices, 0), GDI_ERROR);
138     ok_lasterrornotchanged();
139     ok_int(GetGlyphIndicesW(hdc, Single, 1, Indices, 0xFFFFFFFF), 1);
140     ok_lasterrornotchanged();
141 
142     /* Test an exceptional case that does not seem to return an error */
143     /* In this case, it returns the number of glyphs */
144     ret = GetGlyphIndicesW(hdc, NULL, 0, NULL, 0);
145     ok(ret == 988,
146        "GetGlyphIndicesW(hdc, NULL, 0, NULL, 0) return expected 988, but got %ld\n", ret);
147     ok_lasterrornotchanged();
148 
149     /* Test a single valid char */
150     Single[0] = L'a';
151     ok_int(GetGlyphIndicesW(hdc, Single, 1, Indices, 0), 1);
152     ok_lasterrornotchanged();
153     ok_int(Indices[0], 68);
154 
155     /* Setup an array of all possible BMP glyphs */
156     for (i = 0; i < 4; i++)
157         Glyphs[i] = (WCHAR)i;
158 
159     /* Test a string of valid chars */
160     StringCchCopyW(Glyphs, MAX_BMP_GLYPHS, L"0123");
161     ok_int(GetGlyphIndicesW(hdc, Glyphs, 4, Indices, 0), 4);
162     ok_lasterrornotchanged();
163     ok_int(Indices[0], 19);
164     ok_int(Indices[1], 20);
165     ok_int(Indices[2], 21);
166     ok_int(Indices[3], 22);
167 
168     ok_int(GetGlyphIndicesW(hdc, s_invalids, 3, Indices, 0), 3);
169     ok_lasterrornotchanged();
170     ok_int(Indices[0], 0);
171     ok_int(Indices[1], 0);
172     ok_int(Indices[2], 0);
173 
174     ok_int(GetGlyphIndicesW(hdc, s_invalids, 3, Indices, GGI_MARK_NONEXISTING_GLYPHS), 3);
175     ok_lasterrornotchanged();
176     ok_int(Indices[0], 0xFFFF);
177     ok_int(Indices[1], 0xFFFF);
178     ok_int(Indices[2], 0xFFFF);
179 
180     /* Setup an array of all possible BMP glyphs */
181     for (i = 0; i < MAX_BMP_GLYPHS; i++)
182         Glyphs[i] = (WCHAR)i;
183 
184     /* Get all the glyphs */
185     ok_int(GetGlyphIndicesW(hdc,
186                             Glyphs,
187                             MAX_BMP_GLYPHS,
188                             Indices,
189                             GGI_MARK_NONEXISTING_GLYPHS), MAX_BMP_GLYPHS);
190 
191     /* The first 32 are invalid and should contain 0xffff */
192     for (i = 0; i < 32; i++)
193         ok_int(Indices[i], 0xffff);
194 
195     /* These are the first 2 valid chars */
196     ok(Indices[32] != 0xffff, "ascii char ' ' should be a valid char");
197     ok(Indices[33] != 0xffff, "ascii char '!' should be a valid char");
198 
199     RemoveTempFont(TempTTFFile);
200 }
201 
202