1b6cfa7296f9b4ba1f9c88bad78590792ec1b803
[reactos.git] / win32ss / gdi / gdi32 / objects / font.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: win32ss/gdi/gdi32/objects/font.c
5 * PURPOSE:
6 * PROGRAMMER:
7 *
8 */
9
10 #include <precomp.h>
11
12 #include <math.h>
13 #include <strsafe.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* Rounds a floating point number to integer. The world-to-viewport
19 * transformation process is done in floating point internally. This function
20 * is then used to round these coordinates to integer values.
21 */
22 static __inline INT GDI_ROUND(FLOAT val)
23 {
24 return (int)floor(val + 0.5);
25 }
26
27 /*
28 * For TranslateCharsetInfo
29 */
30 #define MAXTCIINDEX 32
31 static const CHARSETINFO FONT_tci[MAXTCIINDEX] =
32 {
33 /* ANSI */
34 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
35 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
36 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
37 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
38 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
39 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
40 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
41 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
42 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
43 /* reserved by ANSI */
44 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
45 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
46 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
47 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
48 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
49 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
50 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
51 /* ANSI and OEM */
52 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
53 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
54 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
55 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
56 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
57 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
58 /* reserved for alternate ANSI and OEM */
59 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
60 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
61 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
62 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
63 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
64 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
65 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
66 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
67 /* reserved for system */
68 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
69 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
70 };
71
72 #define INITIAL_FAMILY_COUNT 64
73
74 /***********************************************************************
75 * TEXTMETRIC conversion functions.
76 */
77 VOID
78 FASTCALL
79 FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
80 {
81 ptmA->tmHeight = ptmW->tmHeight;
82 ptmA->tmAscent = ptmW->tmAscent;
83 ptmA->tmDescent = ptmW->tmDescent;
84 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
85 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
86 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
87 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
88 ptmA->tmWeight = ptmW->tmWeight;
89 ptmA->tmOverhang = ptmW->tmOverhang;
90 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
91 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
92 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
93 if (ptmW->tmCharSet == SYMBOL_CHARSET)
94 {
95 ptmA->tmFirstChar = 0x1e;
96 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
97 }
98 else
99 {
100 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
101 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
102 }
103 ptmA->tmDefaultChar = (CHAR)ptmW->tmDefaultChar;
104 ptmA->tmBreakChar = (CHAR)ptmW->tmBreakChar;
105 ptmA->tmItalic = ptmW->tmItalic;
106 ptmA->tmUnderlined = ptmW->tmUnderlined;
107 ptmA->tmStruckOut = ptmW->tmStruckOut;
108 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
109 ptmA->tmCharSet = ptmW->tmCharSet;
110 }
111
112 /***********************************************************************
113 * FONT_mbtowc
114 *
115 * Returns a Unicode translation of str using the charset of the
116 * currently selected font in hdc. If count is -1 then str is assumed
117 * to be '\0' terminated, otherwise it contains the number of bytes to
118 * convert. If plenW is non-NULL, on return it will point to the
119 * number of WCHARs that have been written. If pCP is non-NULL, on
120 * return it will point to the codepage used in the conversion. The
121 * caller should free the returned LPWSTR from the process heap
122 * itself.
123 */
124 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
125 {
126 UINT cp = GdiGetCodePage( hdc );
127 INT lenW;
128 LPWSTR strW;
129
130 if(count == -1) count = strlen(str);
131 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
132 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
133 if (!strW)
134 return NULL;
135 if(!MultiByteToWideChar(cp, 0, str, count, strW, lenW))
136 {
137 HeapFree(GetProcessHeap(), 0, strW);
138 return NULL;
139 }
140 DPRINT("mapped %s -> %S\n", str, strW);
141 if(plenW) *plenW = lenW;
142 if(pCP) *pCP = cp;
143 return strW;
144 }
145
146 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
147 {
148 INT i, count = lastChar - firstChar + 1;
149 UINT c;
150 LPSTR str;
151
152 if (count <= 0)
153 return NULL;
154
155 switch (GdiGetCodePage(hdc))
156 {
157 case 932:
158 case 936:
159 case 949:
160 case 950:
161 case 1361:
162 if (lastChar > 0xffff)
163 return NULL;
164 if ((firstChar ^ lastChar) > 0xff)
165 return NULL;
166 break;
167 default:
168 if (lastChar > 0xff)
169 return NULL;
170 break;
171 }
172
173 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
174 if (str == NULL)
175 return NULL;
176
177 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
178 {
179 if (c > 0xff)
180 str[i++] = (BYTE)(c >> 8);
181 str[i] = (BYTE)c;
182 }
183 str[i] = '\0';
184
185 *pByteLen = i;
186
187 return str;
188 }
189
190 VOID FASTCALL
191 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw)
192 {
193 FONT_TextMetricWToA((TEXTMETRICW *) tmw, (TEXTMETRICA *) tma);
194 tma->ntmFlags = tmw->ntmFlags;
195 tma->ntmSizeEM = tmw->ntmSizeEM;
196 tma->ntmCellHeight = tmw->ntmCellHeight;
197 tma->ntmAvgWidth = tmw->ntmAvgWidth;
198 }
199
200 VOID FASTCALL
201 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
202 {
203 NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm);
204 tma->ntmFontSig = tmw->ntmFontSig;
205 }
206
207 // IntFontFamilyCompareEx's flags
208 #define IFFCX_CHARSET 1
209 #define IFFCX_STYLE 2
210
211 FORCEINLINE int FASTCALL
212 IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
213 const FONTFAMILYINFO *ffi2, DWORD dwCompareFlags)
214 {
215 const LOGFONTW *plf1 = &ffi1->EnumLogFontEx.elfLogFont;
216 const LOGFONTW *plf2 = &ffi2->EnumLogFontEx.elfLogFont;
217 ULONG WeightDiff1, WeightDiff2;
218 int cmp = _wcsicmp(plf1->lfFaceName, plf2->lfFaceName);
219 if (cmp)
220 return cmp;
221 if (dwCompareFlags & IFFCX_CHARSET)
222 {
223 if (plf1->lfCharSet < plf2->lfCharSet)
224 return -1;
225 if (plf1->lfCharSet > plf2->lfCharSet)
226 return 1;
227 }
228 if (dwCompareFlags & IFFCX_STYLE)
229 {
230 WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL);
231 WeightDiff2 = labs(plf2->lfWeight - FW_NORMAL);
232 if (WeightDiff1 < WeightDiff2)
233 return -1;
234 if (WeightDiff1 > WeightDiff2)
235 return 1;
236 if (plf1->lfItalic < plf2->lfItalic)
237 return -1;
238 if (plf1->lfItalic > plf2->lfItalic)
239 return 1;
240 }
241 return 0;
242 }
243
244 static int __cdecl
245 IntFontFamilyCompare(const void *ffi1, const void *ffi2)
246 {
247 return IntFontFamilyCompareEx(ffi1, ffi2, IFFCX_STYLE | IFFCX_CHARSET);
248 }
249
250 // IntEnumFontFamilies' flags:
251 #define IEFF_UNICODE 1
252 #define IEFF_EXTENDED 2
253
254 int FASTCALL
255 IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
256 const LOGFONTW *plf, DWORD dwFlags)
257 {
258 FONTFAMILYINFO *first, *last, *result;
259 DWORD dwCompareFlags = 0;
260
261 if (plf->lfFaceName[0])
262 dwCompareFlags |= IFFCX_STYLE;
263
264 if ((dwFlags & IEFF_EXTENDED) && plf->lfCharSet == DEFAULT_CHARSET)
265 dwCompareFlags |= IFFCX_CHARSET;
266
267 first = InfoList;
268 last = &InfoList[nCount];
269
270 /* std::unique(first, last, IntFontFamilyCompareEx); */
271 if (first == last)
272 return 0;
273
274 result = first;
275 while (++first != last)
276 {
277 if (IntFontFamilyCompareEx(result, first, dwCompareFlags) != 0)
278 {
279 *(++result) = *first;
280 }
281 }
282 nCount = (int)(++result - InfoList);
283
284 return nCount;
285 }
286
287 static int FASTCALL
288 IntEnumFontFamilies(HDC Dc, const LOGFONTW *LogFont, PVOID EnumProc, LPARAM lParam,
289 DWORD dwFlags)
290 {
291 int FontFamilyCount;
292 PFONTFAMILYINFO Info;
293 int Ret = 1;
294 int i;
295 ENUMLOGFONTEXA EnumLogFontExA;
296 NEWTEXTMETRICEXA NewTextMetricExA;
297 LOGFONTW lfW;
298 LONG InfoCount;
299 ULONG DataSize;
300 NTSTATUS Status;
301
302 DataSize = INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO);
303 Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
304 if (Info == NULL)
305 {
306 return 1;
307 }
308
309 /* Initialize the LOGFONT structure */
310 ZeroMemory(&lfW, sizeof(lfW));
311 if (!LogFont)
312 {
313 lfW.lfCharSet = DEFAULT_CHARSET;
314 }
315 else
316 {
317 lfW.lfCharSet = LogFont->lfCharSet;
318 lfW.lfPitchAndFamily = LogFont->lfPitchAndFamily;
319 StringCbCopyW(lfW.lfFaceName, sizeof(lfW.lfFaceName), LogFont->lfFaceName);
320 }
321
322 /* Retrieve the font information */
323 InfoCount = INITIAL_FAMILY_COUNT;
324 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
325 if (FontFamilyCount < 0)
326 {
327 RtlFreeHeap(GetProcessHeap(), 0, Info);
328 return 1;
329 }
330
331 /* Resize the buffer if the buffer is too small */
332 if (INITIAL_FAMILY_COUNT < InfoCount)
333 {
334 RtlFreeHeap(GetProcessHeap(), 0, Info);
335
336 Status = RtlULongMult(InfoCount, sizeof(FONTFAMILYINFO), &DataSize);
337 if (!NT_SUCCESS(Status) || DataSize > LONG_MAX)
338 {
339 DPRINT1("Overflowed.\n");
340 return 1;
341 }
342 Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize);
343 if (Info == NULL)
344 {
345 return 1;
346 }
347 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount);
348 if (FontFamilyCount < 0 || FontFamilyCount < InfoCount)
349 {
350 RtlFreeHeap(GetProcessHeap(), 0, Info);
351 return 1;
352 }
353 }
354
355 /* Sort and remove redundant information */
356 qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare);
357 FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, &lfW, dwFlags);
358
359 /* call the callback */
360 for (i = 0; i < FontFamilyCount; i++)
361 {
362 if (dwFlags & IEFF_UNICODE)
363 {
364 Ret = ((FONTENUMPROCW) EnumProc)(
365 (VOID*)&Info[i].EnumLogFontEx,
366 (VOID*)&Info[i].NewTextMetricEx,
367 Info[i].FontType, lParam);
368 }
369 else
370 {
371 // Could use EnumLogFontExW2A here?
372 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont);
373 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1,
374 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL);
375 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1,
376 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL);
377 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1,
378 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL);
379 NewTextMetricExW2A(&NewTextMetricExA,
380 &Info[i].NewTextMetricEx);
381 Ret = ((FONTENUMPROCA) EnumProc)(
382 (VOID*)&EnumLogFontExA,
383 (VOID*)&NewTextMetricExA,
384 Info[i].FontType, lParam);
385 }
386
387 if(Ret == 0)
388 break;
389 }
390
391 RtlFreeHeap(GetProcessHeap(), 0, Info);
392
393 return Ret;
394 }
395
396 /*
397 * @implemented
398 */
399 int WINAPI
400 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
401 LPARAM lParam, DWORD dwFlags)
402 {
403 if (lpLogfont)
404 {
405 DPRINT("EnumFontFamiliesExW(%p, %p(%S, %u, %u), %p, %p, 0x%08lX)\n",
406 hdc, lpLogfont, lpLogfont->lfFaceName, lpLogfont->lfCharSet,
407 lpLogfont->lfPitchAndFamily, lpEnumFontFamExProc, lParam, dwFlags);
408 }
409 else
410 {
411 DPRINT("EnumFontFamiliesExW(%p, NULL, %p, %p, 0x%08lX)\n",
412 hdc, lpEnumFontFamExProc, lParam, dwFlags);
413 }
414 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam,
415 IEFF_UNICODE | IEFF_EXTENDED);
416 }
417
418
419 /*
420 * @implemented
421 */
422 int WINAPI
423 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc,
424 LPARAM lParam)
425 {
426 LOGFONTW LogFont;
427
428 DPRINT("EnumFontFamiliesW(%p, %S, %p, %p)\n",
429 hdc, lpszFamily, lpEnumFontFamProc, lParam);
430
431 ZeroMemory(&LogFont, sizeof(LOGFONTW));
432 LogFont.lfCharSet = DEFAULT_CHARSET;
433 if (NULL != lpszFamily)
434 {
435 if (!*lpszFamily) return 1;
436 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
437 }
438
439 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, IEFF_UNICODE);
440 }
441
442
443 /*
444 * @implemented
445 */
446 int WINAPI
447 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc,
448 LPARAM lParam, DWORD dwFlags)
449 {
450 LOGFONTW LogFontW, *pLogFontW;
451
452 if (lpLogfont)
453 {
454 DPRINT("EnumFontFamiliesExA(%p, %p(%s, %u, %u), %p, %p, 0x%08lX)\n",
455 hdc, lpLogfont, lpLogfont->lfFaceName, lpLogfont->lfCharSet,
456 lpLogfont->lfPitchAndFamily, lpEnumFontFamExProc, lParam, dwFlags);
457 }
458 else
459 {
460 DPRINT("EnumFontFamiliesExA(%p, NULL, %p, %p, 0x%08lX)\n",
461 hdc, lpEnumFontFamExProc, lParam, dwFlags);
462 }
463
464 if (lpLogfont)
465 {
466 LogFontA2W(&LogFontW,lpLogfont);
467 pLogFontW = &LogFontW;
468 }
469 else pLogFontW = NULL;
470
471 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
472 return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, IEFF_EXTENDED);
473 }
474
475
476 /*
477 * @implemented
478 */
479 int WINAPI
480 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc,
481 LPARAM lParam)
482 {
483 LOGFONTW LogFont;
484
485 DPRINT("EnumFontFamiliesA(%p, %s, %p, %p)\n",
486 hdc, lpszFamily, lpEnumFontFamProc, lParam);
487
488 ZeroMemory(&LogFont, sizeof(LOGFONTW));
489 LogFont.lfCharSet = DEFAULT_CHARSET;
490 if (NULL != lpszFamily)
491 {
492 if (!*lpszFamily) return 1;
493 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE);
494 }
495
496 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, 0);
497 }
498
499
500 /*
501 * @implemented
502 */
503 DWORD
504 WINAPI
505 GetCharacterPlacementA(
506 HDC hdc,
507 LPCSTR lpString,
508 INT uCount,
509 INT nMaxExtent,
510 GCP_RESULTSA *lpResults,
511 DWORD dwFlags)
512 {
513 WCHAR *lpStringW;
514 INT uCountW;
515 GCP_RESULTSW resultsW;
516 DWORD ret;
517 UINT font_cp;
518
519 if ( !lpString || uCount <= 0 || !lpResults || (nMaxExtent < 0 && nMaxExtent != -1 ) )
520 {
521 SetLastError(ERROR_INVALID_PARAMETER);
522 return 0;
523 }
524 /* TRACE("%s, %d, %d, 0x%08x\n",
525 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
526 */
527 /* both structs are equal in size */
528 memcpy(&resultsW, lpResults, sizeof(resultsW));
529
530 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
531 if (lpStringW == NULL)
532 {
533 return 0;
534 }
535 if(lpResults->lpOutString)
536 {
537 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
538 if (resultsW.lpOutString == NULL)
539 {
540 HeapFree(GetProcessHeap(), 0, lpStringW);
541 return 0;
542 }
543 }
544
545 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
546
547 lpResults->nGlyphs = resultsW.nGlyphs;
548 lpResults->nMaxFit = resultsW.nMaxFit;
549
550 if(lpResults->lpOutString)
551 {
552 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
553 lpResults->lpOutString, uCount, NULL, NULL );
554 }
555
556 HeapFree(GetProcessHeap(), 0, lpStringW);
557 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
558
559 return ret;
560 }
561
562
563 /*
564 * @implemented
565 */
566 DWORD
567 WINAPI
568 GetCharacterPlacementW(
569 HDC hdc,
570 LPCWSTR lpString,
571 INT uCount,
572 INT nMaxExtent,
573 GCP_RESULTSW *lpResults,
574 DWORD dwFlags
575 )
576 {
577 DWORD ret=0;
578 SIZE size;
579 UINT i, nSet;
580 DPRINT("GetCharacterPlacementW\n");
581
582 if (dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags);
583 if (lpResults->lpClass) DPRINT("classes not implemented\n");
584
585 nSet = (UINT)uCount;
586 if (nSet > lpResults->nGlyphs)
587 nSet = lpResults->nGlyphs;
588
589 /* return number of initialized fields */
590 lpResults->nGlyphs = nSet;
591
592 if (dwFlags & GCP_REORDER)
593 {
594 if (LoadLPK(LPK_GCP))
595 return LpkGetCharacterPlacement(hdc, lpString, uCount, nMaxExtent, lpResults, dwFlags, 0);
596 }
597
598 /* Treat the case where no special handling was requested in a fastpath way */
599 /* copy will do if the GCP_REORDER flag is not set */
600 if (lpResults->lpOutString)
601 lstrcpynW( lpResults->lpOutString, lpString, nSet );
602
603 if (lpResults->lpOrder)
604 {
605 for (i = 0; i < nSet; i++)
606 lpResults->lpOrder[i] = i;
607 }
608
609 /* FIXME: Will use the placement chars */
610 if (lpResults->lpDx)
611 {
612 int c;
613 for (i = 0; i < nSet; i++)
614 {
615 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
616 lpResults->lpDx[i]= c;
617 }
618 }
619
620 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
621 {
622 int pos = 0;
623
624 lpResults->lpCaretPos[0] = 0;
625 for (i = 1; i < nSet; i++)
626 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
627 lpResults->lpCaretPos[i] = (pos += size.cx);
628 }
629
630 if (lpResults->lpGlyphs)
631 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
632
633 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
634 ret = MAKELONG(size.cx, size.cy);
635
636 return ret;
637 }
638
639 DWORD
640 WINAPI
641 NewGetCharacterPlacementW(
642 HDC hdc,
643 LPCWSTR lpString,
644 INT uCount,
645 INT nMaxExtent,
646 GCP_RESULTSW *lpResults,
647 DWORD dwFlags
648 )
649 {
650 ULONG nSet;
651 SIZE Size = {0,0};
652
653 if ( !lpString || uCount <= 0 || (nMaxExtent < 0 && nMaxExtent != -1 ) )
654 {
655 SetLastError(ERROR_INVALID_PARAMETER);
656 return 0;
657 }
658
659 if ( !lpResults )
660 {
661 if ( GetTextExtentPointW(hdc, lpString, uCount, &Size) )
662 {
663 return MAKELONG(Size.cx, Size.cy);
664 }
665 return 0;
666 }
667
668 nSet = uCount;
669 if ( nSet > lpResults->nGlyphs )
670 nSet = lpResults->nGlyphs;
671
672 return NtGdiGetCharacterPlacementW( hdc,
673 (LPWSTR)lpString,
674 nSet,
675 nMaxExtent,
676 lpResults,
677 dwFlags);
678 }
679
680 /*
681 * @implemented
682 *
683 */
684 BOOL
685 WINAPI
686 GetCharABCWidthsFloatW(HDC hdc,
687 UINT FirstChar,
688 UINT LastChar,
689 LPABCFLOAT abcF)
690 {
691 DPRINT("GetCharABCWidthsFloatW\n");
692 if ((!abcF) || (FirstChar > LastChar))
693 {
694 SetLastError(ERROR_INVALID_PARAMETER);
695 return FALSE;
696 }
697 return NtGdiGetCharABCWidthsW( hdc,
698 FirstChar,
699 (ULONG)(LastChar - FirstChar + 1),
700 (PWCHAR) NULL,
701 0,
702 (PVOID)abcF);
703 }
704
705 /*
706 * @implemented
707 *
708 */
709 BOOL
710 WINAPI
711 GetCharWidthFloatW(HDC hdc,
712 UINT iFirstChar,
713 UINT iLastChar,
714 PFLOAT pxBuffer)
715 {
716 DPRINT("GetCharWidthsFloatW\n");
717 if ((!pxBuffer) || (iFirstChar > iLastChar))
718 {
719 SetLastError(ERROR_INVALID_PARAMETER);
720 return FALSE;
721 }
722 return NtGdiGetCharWidthW( hdc,
723 iFirstChar,
724 (ULONG)(iLastChar - iFirstChar + 1),
725 (PWCHAR) NULL,
726 0,
727 (PVOID) pxBuffer);
728 }
729
730 /*
731 * @implemented
732 *
733 */
734 BOOL
735 WINAPI
736 GetCharWidthW(HDC hdc,
737 UINT iFirstChar,
738 UINT iLastChar,
739 LPINT lpBuffer)
740 {
741 DPRINT("GetCharWidthsW\n");
742 if ((!lpBuffer) || (iFirstChar > iLastChar))
743 {
744 SetLastError(ERROR_INVALID_PARAMETER);
745 return FALSE;
746 }
747 return NtGdiGetCharWidthW( hdc,
748 iFirstChar,
749 (ULONG)(iLastChar - iFirstChar + 1),
750 (PWCHAR) NULL,
751 GCW_NOFLOAT,
752 (PVOID) lpBuffer);
753 }
754
755 /*
756 * @implemented
757 *
758 */
759 BOOL
760 WINAPI
761 GetCharWidth32W(HDC hdc,
762 UINT iFirstChar,
763 UINT iLastChar,
764 LPINT lpBuffer)
765 {
766 DPRINT("GetCharWidths32W\n");
767 if ((!lpBuffer) || (iFirstChar > iLastChar))
768 {
769 SetLastError(ERROR_INVALID_PARAMETER);
770 return FALSE;
771 }
772 return NtGdiGetCharWidthW( hdc,
773 iFirstChar,
774 (ULONG)(iLastChar - iFirstChar + 1),
775 (PWCHAR) NULL,
776 GCW_NOFLOAT|GCW_WIN32,
777 (PVOID) lpBuffer);
778 }
779
780
781 /*
782 * @implemented
783 *
784 */
785 BOOL
786 WINAPI
787 GetCharABCWidthsW(HDC hdc,
788 UINT FirstChar,
789 UINT LastChar,
790 LPABC lpabc)
791 {
792 DPRINT("GetCharABCWidthsW\n");
793 if ((!lpabc) || (FirstChar > LastChar))
794 {
795 SetLastError(ERROR_INVALID_PARAMETER);
796 return FALSE;
797 }
798 return NtGdiGetCharABCWidthsW( hdc,
799 FirstChar,
800 (ULONG)(LastChar - FirstChar + 1),
801 (PWCHAR) NULL,
802 GCABCW_NOFLOAT,
803 (PVOID)lpabc);
804 }
805
806 /*
807 * @implemented
808 */
809 BOOL
810 WINAPI
811 GetCharWidthA(
812 HDC hdc,
813 UINT iFirstChar,
814 UINT iLastChar,
815 LPINT lpBuffer
816 )
817 {
818 INT wlen, count = 0;
819 LPSTR str;
820 LPWSTR wstr;
821 BOOL ret = TRUE;
822
823 DPRINT("GetCharWidthsA\n");
824
825 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
826 if (!str)
827 return FALSE;
828
829 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
830 if (!wstr)
831 {
832 HeapFree(GetProcessHeap(), 0, str);
833 return FALSE;
834 }
835
836 ret = NtGdiGetCharWidthW( hdc,
837 wstr[0],
838 (ULONG) count,
839 (PWCHAR) wstr,
840 GCW_NOFLOAT,
841 (PVOID) lpBuffer);
842
843 HeapFree(GetProcessHeap(), 0, str);
844 HeapFree(GetProcessHeap(), 0, wstr);
845
846 return ret;
847 }
848
849 /*
850 * @implemented
851 */
852 BOOL
853 WINAPI
854 GetCharWidth32A(
855 HDC hdc,
856 UINT iFirstChar,
857 UINT iLastChar,
858 LPINT lpBuffer
859 )
860 {
861 INT wlen, count = 0;
862 LPSTR str;
863 LPWSTR wstr;
864 BOOL ret = TRUE;
865
866 DPRINT("GetCharWidths32A\n");
867
868 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
869 if (!str)
870 return FALSE;
871
872 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
873 if (!wstr)
874 {
875 HeapFree(GetProcessHeap(), 0, str);
876 return FALSE;
877 }
878
879 ret = NtGdiGetCharWidthW( hdc,
880 wstr[0],
881 (ULONG) count,
882 (PWCHAR) wstr,
883 GCW_NOFLOAT|GCW_WIN32,
884 (PVOID) lpBuffer);
885
886 HeapFree(GetProcessHeap(), 0, str);
887 HeapFree(GetProcessHeap(), 0, wstr);
888
889 return ret;
890 }
891
892 /*
893 * @implemented
894 */
895 BOOL
896 APIENTRY
897 GetCharWidthFloatA(
898 HDC hdc,
899 UINT iFirstChar,
900 UINT iLastChar,
901 PFLOAT pxBuffer
902 )
903 {
904 INT wlen, count = 0;
905 LPSTR str;
906 LPWSTR wstr;
907 BOOL ret = TRUE;
908
909 DPRINT("GetCharWidthsFloatA\n");
910
911 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
912 if (!str)
913 return FALSE;
914
915 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
916 if (!wstr)
917 {
918 HeapFree(GetProcessHeap(), 0, str);
919 return FALSE;
920 }
921 ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer);
922
923 HeapFree(GetProcessHeap(), 0, str);
924 HeapFree(GetProcessHeap(), 0, wstr);
925
926 return ret;
927 }
928
929 /*
930 * @implemented
931 */
932 BOOL
933 APIENTRY
934 GetCharABCWidthsA(
935 HDC hdc,
936 UINT iFirstChar,
937 UINT iLastChar,
938 LPABC lpabc
939 )
940 {
941 INT wlen, count = 0;
942 LPSTR str;
943 LPWSTR wstr;
944 BOOL ret = TRUE;
945
946 DPRINT("GetCharABCWidthsA\n");
947
948 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
949 if (!str)
950 return FALSE;
951
952 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL);
953 if (!wstr)
954 {
955 HeapFree(GetProcessHeap(), 0, str);
956 return FALSE;
957 }
958
959 ret = NtGdiGetCharABCWidthsW( hdc,
960 wstr[0],
961 wlen - 1,
962 (PWCHAR)wstr,
963 GCABCW_NOFLOAT,
964 (PVOID)lpabc);
965
966 HeapFree(GetProcessHeap(), 0, str);
967 HeapFree(GetProcessHeap(), 0, wstr);
968
969 return ret;
970 }
971
972 /*
973 * @implemented
974 */
975 BOOL
976 APIENTRY
977 GetCharABCWidthsFloatA(
978 HDC hdc,
979 UINT iFirstChar,
980 UINT iLastChar,
981 LPABCFLOAT lpABCF
982 )
983 {
984 INT wlen, count = 0;
985 LPSTR str;
986 LPWSTR wstr;
987 BOOL ret = TRUE;
988
989 DPRINT("GetCharABCWidthsFloatA\n");
990
991 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count);
992 if (!str)
993 return FALSE;
994
995 wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL );
996 if (!wstr)
997 {
998 HeapFree( GetProcessHeap(), 0, str );
999 return FALSE;
1000 }
1001 ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF);
1002
1003 HeapFree( GetProcessHeap(), 0, str );
1004 HeapFree( GetProcessHeap(), 0, wstr );
1005
1006 return ret;
1007 }
1008
1009 /*
1010 * @implemented
1011 */
1012 BOOL
1013 WINAPI
1014 GetCharABCWidthsI(HDC hdc,
1015 UINT giFirst,
1016 UINT cgi,
1017 LPWORD pgi,
1018 LPABC lpabc)
1019 {
1020 DPRINT("GetCharABCWidthsI\n");
1021 return NtGdiGetCharABCWidthsW( hdc,
1022 giFirst,
1023 (ULONG) cgi,
1024 (PWCHAR) pgi,
1025 GCABCW_NOFLOAT|GCABCW_INDICES,
1026 (PVOID)lpabc);
1027 }
1028
1029 /*
1030 * @implemented
1031 */
1032 BOOL
1033 WINAPI
1034 GetCharWidthI(HDC hdc,
1035 UINT giFirst,
1036 UINT cgi,
1037 LPWORD pgi,
1038 LPINT lpBuffer
1039 )
1040 {
1041 DPRINT("GetCharWidthsI\n");
1042 if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max.
1043 {
1044 SetLastError(ERROR_INVALID_PARAMETER);
1045 return FALSE;
1046 }
1047 if (!cgi) return TRUE;
1048 return NtGdiGetCharWidthW( hdc,
1049 giFirst,
1050 cgi,
1051 (PWCHAR) pgi,
1052 GCW_INDICES|GCW_NOFLOAT|GCW_WIN32,
1053 (PVOID) lpBuffer );
1054 }
1055
1056 /*
1057 * @implemented
1058 */
1059 DWORD
1060 WINAPI
1061 GetFontLanguageInfo(
1062 HDC hDc
1063 )
1064 {
1065 DWORD Gcp = 0, Ret = 0;
1066 if (gbLpk)
1067 {
1068 Ret = NtGdiGetTextCharsetInfo(hDc, NULL, 0);
1069 if ((Ret == ARABIC_CHARSET) || (Ret == HEBREW_CHARSET))
1070 Ret = (GCP_KASHIDA|GCP_DIACRITIC|GCP_LIGATE|GCP_GLYPHSHAPE|GCP_REORDER);
1071 }
1072 Gcp = GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR);
1073 if ( Gcp == GCP_ERROR)
1074 return Gcp;
1075 else
1076 Ret = Gcp | Ret;
1077 return Ret;
1078 }
1079
1080 /*
1081 * @implemented
1082 */
1083 DWORD
1084 WINAPI
1085 GetGlyphIndicesA(
1086 HDC hdc,
1087 LPCSTR lpstr,
1088 INT count,
1089 LPWORD pgi,
1090 DWORD flags
1091 )
1092 {
1093 DWORD Ret;
1094 WCHAR *lpstrW;
1095 INT countW;
1096
1097 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1098
1099 if (lpstrW == NULL)
1100 return GDI_ERROR;
1101
1102 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1103 HeapFree(GetProcessHeap(), 0, lpstrW);
1104 return Ret;
1105 }
1106
1107 /*
1108 * @implemented
1109 */
1110 DWORD
1111 WINAPI
1112 GetGlyphOutlineA(
1113 HDC hdc,
1114 UINT uChar,
1115 UINT uFormat,
1116 LPGLYPHMETRICS lpgm,
1117 DWORD cbBuffer,
1118 LPVOID lpvBuffer,
1119 CONST MAT2 *lpmat2
1120 )
1121 {
1122
1123 LPWSTR p = NULL;
1124 DWORD ret;
1125 UINT c;
1126 DPRINT("GetGlyphOutlineA uChar %x\n", uChar);
1127 if (!lpgm || !lpmat2) return GDI_ERROR;
1128 if(!(uFormat & GGO_GLYPH_INDEX))
1129 {
1130 int len;
1131 char mbchs[2];
1132 if(uChar > 0xff) /* but, 2 bytes character only */
1133 {
1134 len = 2;
1135 mbchs[0] = (uChar & 0xff00) >> 8;
1136 mbchs[1] = (uChar & 0xff);
1137 }
1138 else
1139 {
1140 len = 1;
1141 mbchs[0] = (uChar & 0xff);
1142 }
1143 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
1144 if(!p)
1145 return GDI_ERROR;
1146 c = p[0];
1147 }
1148 else
1149 c = uChar;
1150 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
1151 HeapFree(GetProcessHeap(), 0, p);
1152 return ret;
1153 }
1154
1155
1156 /*
1157 * @implemented
1158 */
1159 DWORD
1160 WINAPI
1161 GetGlyphOutlineW(
1162 HDC hdc,
1163 UINT uChar,
1164 UINT uFormat,
1165 LPGLYPHMETRICS lpgm,
1166 DWORD cbBuffer,
1167 LPVOID lpvBuffer,
1168 CONST MAT2 *lpmat2
1169 )
1170 {
1171 DPRINT("GetGlyphOutlineW uChar %x\n", uChar);
1172 if (!lpgm || !lpmat2) return GDI_ERROR;
1173 if (!lpvBuffer) cbBuffer = 0;
1174 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE);
1175 }
1176
1177 /*
1178 * @unimplemented
1179 */
1180 DWORD
1181 WINAPI
1182 GetGlyphOutlineWow(
1183 DWORD a0,
1184 DWORD a1,
1185 DWORD a2,
1186 DWORD a3,
1187 DWORD a4,
1188 DWORD a5,
1189 DWORD a6
1190 )
1191 {
1192 UNIMPLEMENTED;
1193 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1194 return 0;
1195 }
1196
1197 /*
1198 * @implemented
1199 */
1200 UINT
1201 APIENTRY
1202 GetOutlineTextMetricsA(
1203 HDC hdc,
1204 UINT cbData,
1205 LPOUTLINETEXTMETRICA lpOTM
1206 )
1207 {
1208 char buf[512], *ptr;
1209 UINT ret, needed;
1210 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1211 OUTLINETEXTMETRICA *output = lpOTM;
1212 INT left, len;
1213
1214 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1215 return 0;
1216 if(ret > sizeof(buf))
1217 {
1218 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1219 if (lpOTMW == NULL)
1220 {
1221 return 0;
1222 }
1223 }
1224 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1225
1226 needed = sizeof(OUTLINETEXTMETRICA);
1227 if(lpOTMW->otmpFamilyName)
1228 needed += WideCharToMultiByte(CP_ACP, 0,
1229 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFamilyName), -1,
1230 NULL, 0, NULL, NULL);
1231 if(lpOTMW->otmpFaceName)
1232 needed += WideCharToMultiByte(CP_ACP, 0,
1233 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFaceName), -1,
1234 NULL, 0, NULL, NULL);
1235 if(lpOTMW->otmpStyleName)
1236 needed += WideCharToMultiByte(CP_ACP, 0,
1237 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpStyleName), -1,
1238 NULL, 0, NULL, NULL);
1239 if(lpOTMW->otmpFullName)
1240 needed += WideCharToMultiByte(CP_ACP, 0,
1241 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFullName), -1,
1242 NULL, 0, NULL, NULL);
1243
1244 if(!lpOTM)
1245 {
1246 ret = needed;
1247 goto end;
1248 }
1249
1250 DPRINT("needed = %u\n", needed);
1251 if(needed > cbData)
1252 {
1253 /* Since the supplied buffer isn't big enough, we'll alloc one
1254 that is and memcpy the first cbData bytes into the lpOTM at
1255 the end. */
1256 output = HeapAlloc(GetProcessHeap(), 0, needed);
1257 if (output == NULL)
1258 {
1259 goto end;
1260 }
1261 }
1262
1263 ret = output->otmSize = min(needed, cbData);
1264 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1265 output->otmFiller = 0;
1266 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1267 output->otmfsSelection = lpOTMW->otmfsSelection;
1268 output->otmfsType = lpOTMW->otmfsType;
1269 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1270 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1271 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1272 output->otmEMSquare = lpOTMW->otmEMSquare;
1273 output->otmAscent = lpOTMW->otmAscent;
1274 output->otmDescent = lpOTMW->otmDescent;
1275 output->otmLineGap = lpOTMW->otmLineGap;
1276 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1277 output->otmsXHeight = lpOTMW->otmsXHeight;
1278 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1279 output->otmMacAscent = lpOTMW->otmMacAscent;
1280 output->otmMacDescent = lpOTMW->otmMacDescent;
1281 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1282 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1283 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1284 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1285 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1286 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1287 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1288 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1289 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1290 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1291
1292
1293 ptr = (char*)(output + 1);
1294 left = needed - sizeof(*output);
1295
1296 if(lpOTMW->otmpFamilyName)
1297 {
1298 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1299 len = WideCharToMultiByte(CP_ACP, 0,
1300 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFamilyName), -1,
1301 ptr, left, NULL, NULL);
1302 left -= len;
1303 ptr += len;
1304 }
1305 else
1306 output->otmpFamilyName = 0;
1307
1308 if(lpOTMW->otmpFaceName)
1309 {
1310 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1311 len = WideCharToMultiByte(CP_ACP, 0,
1312 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFaceName), -1,
1313 ptr, left, NULL, NULL);
1314 left -= len;
1315 ptr += len;
1316 }
1317 else
1318 output->otmpFaceName = 0;
1319
1320 if(lpOTMW->otmpStyleName)
1321 {
1322 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1323 len = WideCharToMultiByte(CP_ACP, 0,
1324 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpStyleName), -1,
1325 ptr, left, NULL, NULL);
1326 left -= len;
1327 ptr += len;
1328 }
1329 else
1330 output->otmpStyleName = 0;
1331
1332 if(lpOTMW->otmpFullName)
1333 {
1334 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1335 len = WideCharToMultiByte(CP_ACP, 0,
1336 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFullName), -1,
1337 ptr, left, NULL, NULL);
1338 left -= len;
1339 }
1340 else
1341 output->otmpFullName = 0;
1342
1343 assert(left == 0);
1344
1345 if(output != lpOTM)
1346 {
1347 memcpy(lpOTM, output, cbData);
1348 HeapFree(GetProcessHeap(), 0, output);
1349
1350 /* check if the string offsets really fit into the provided size */
1351 /* FIXME: should we check string length as well? */
1352 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1353 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1354
1355 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1356 lpOTM->otmpFaceName = 0; /* doesn't fit */
1357
1358 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1359 lpOTM->otmpStyleName = 0; /* doesn't fit */
1360
1361 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1362 lpOTM->otmpFullName = 0; /* doesn't fit */
1363 }
1364
1365 end:
1366 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1367 HeapFree(GetProcessHeap(), 0, lpOTMW);
1368
1369 return ret;
1370 }
1371
1372 /* Performs a device to world transformation on the specified size (which
1373 * is in integer format).
1374 */
1375 static inline INT INTERNAL_YDSTOWS(XFORM *xForm, INT height)
1376 {
1377 double floatHeight;
1378
1379 /* Perform operation with floating point */
1380 floatHeight = (double)height * xForm->eM22;
1381 /* Round to integers */
1382 return GDI_ROUND(floatHeight);
1383 }
1384
1385 /* scale width and height but don't mirror them */
1386 static inline INT width_to_LP( XFORM *xForm, INT width )
1387 {
1388 return GDI_ROUND( (double)width * fabs( xForm->eM11));
1389 }
1390
1391 static inline INT height_to_LP( XFORM *xForm, INT height )
1392 {
1393 return GDI_ROUND( (double)height * fabs( xForm->eM22 ));
1394 }
1395
1396 /*
1397 * @implemented
1398 */
1399 UINT
1400 APIENTRY
1401 GetOutlineTextMetricsW(
1402 HDC hdc,
1403 UINT cbData,
1404 LPOUTLINETEXTMETRICW lpOTM
1405 )
1406 {
1407 TMDIFF Tmd; // Should not be zero.
1408 UINT Size, AvailableSize = 0, StringSize;
1409 XFORM DevToWorld;
1410 OUTLINETEXTMETRICW* LocalOTM;
1411 WCHAR* Str;
1412 BYTE* Ptr;
1413
1414 /* Get the structure */
1415 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, 0, NULL, &Tmd);
1416 if (!Size)
1417 return 0;
1418 if (!lpOTM || (cbData < sizeof(*lpOTM)))
1419 return Size;
1420
1421 LocalOTM = HeapAlloc(GetProcessHeap(), 0, Size);
1422 LocalOTM->otmSize = Size;
1423 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, Size, LocalOTM, &Tmd);
1424 if (!Size)
1425 {
1426 HeapFree(GetProcessHeap(), 0, LocalOTM);
1427 return 0;
1428 }
1429
1430 if (!NtGdiGetTransform(hdc, GdiDeviceSpaceToWorldSpace, &DevToWorld))
1431 {
1432 DPRINT1("NtGdiGetTransform failed!\n");
1433 HeapFree(GetProcessHeap(), 0, LocalOTM);
1434 SetLastError(ERROR_INVALID_HANDLE);
1435 return 0;
1436 }
1437
1438 /* Fill in DC specific data */
1439 LocalOTM->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1440 LocalOTM->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1441 LocalOTM->otmTextMetrics.tmHeight = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmHeight );
1442 LocalOTM->otmTextMetrics.tmAscent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAscent );
1443 LocalOTM->otmTextMetrics.tmDescent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmDescent );
1444 LocalOTM->otmTextMetrics.tmInternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmInternalLeading );
1445 LocalOTM->otmTextMetrics.tmExternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmExternalLeading );
1446 LocalOTM->otmTextMetrics.tmAveCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAveCharWidth );
1447 LocalOTM->otmTextMetrics.tmMaxCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmMaxCharWidth );
1448 LocalOTM->otmTextMetrics.tmOverhang = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmOverhang );
1449 LocalOTM->otmAscent = height_to_LP( &DevToWorld, LocalOTM->otmAscent);
1450 LocalOTM->otmDescent = height_to_LP( &DevToWorld, LocalOTM->otmDescent);
1451 LocalOTM->otmLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmLineGap));
1452 LocalOTM->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsCapEmHeight));
1453 LocalOTM->otmsXHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsXHeight));
1454 LocalOTM->otmrcFontBox.top = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.top);
1455 LocalOTM->otmrcFontBox.bottom = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.bottom);
1456 LocalOTM->otmrcFontBox.left = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.left);
1457 LocalOTM->otmrcFontBox.right = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.right);
1458 LocalOTM->otmMacAscent = height_to_LP( &DevToWorld, LocalOTM->otmMacAscent);
1459 LocalOTM->otmMacDescent = height_to_LP( &DevToWorld, LocalOTM->otmMacDescent);
1460 LocalOTM->otmMacLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmMacLineGap));
1461 LocalOTM->otmptSubscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.x);
1462 LocalOTM->otmptSubscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.y);
1463 LocalOTM->otmptSubscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.x);
1464 LocalOTM->otmptSubscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.y);
1465 LocalOTM->otmptSuperscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.x);
1466 LocalOTM->otmptSuperscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.y);
1467 LocalOTM->otmptSuperscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.x);
1468 LocalOTM->otmptSuperscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.y);
1469 LocalOTM->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsStrikeoutSize));
1470 LocalOTM->otmsStrikeoutPosition = height_to_LP( &DevToWorld, LocalOTM->otmsStrikeoutPosition);
1471 LocalOTM->otmsUnderscoreSize = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscoreSize);
1472 LocalOTM->otmsUnderscorePosition = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscorePosition);
1473
1474 /* Copy what we can */
1475 CopyMemory(lpOTM, LocalOTM, min(Size, cbData));
1476
1477 lpOTM->otmpFamilyName = NULL;
1478 lpOTM->otmpFaceName = NULL;
1479 lpOTM->otmpStyleName = NULL;
1480 lpOTM->otmpFullName = NULL;
1481
1482 Size = sizeof(*lpOTM);
1483 AvailableSize = cbData - Size;
1484 Ptr = (BYTE*)lpOTM + sizeof(*lpOTM);
1485
1486 /* Fix string values up */
1487 if (LocalOTM->otmpFamilyName)
1488 {
1489 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFamilyName);
1490 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1491 if (AvailableSize >= StringSize)
1492 {
1493 CopyMemory(Ptr, Str, StringSize);
1494 lpOTM->otmpFamilyName = (PSTR)(Ptr - (BYTE*)lpOTM);
1495 Ptr += StringSize;
1496 AvailableSize -= StringSize;
1497 Size += StringSize;
1498 }
1499 }
1500
1501 if (LocalOTM->otmpFaceName)
1502 {
1503 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFaceName);
1504 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1505 if (AvailableSize >= StringSize)
1506 {
1507 CopyMemory(Ptr, Str, StringSize);
1508 lpOTM->otmpFaceName = (PSTR)(Ptr - (BYTE*)lpOTM);
1509 Ptr += StringSize;
1510 AvailableSize -= StringSize;
1511 Size += StringSize;
1512 }
1513 }
1514
1515 if (LocalOTM->otmpStyleName)
1516 {
1517 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpStyleName);
1518 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1519 if (AvailableSize >= StringSize)
1520 {
1521 CopyMemory(Ptr, Str, StringSize);
1522 lpOTM->otmpStyleName = (PSTR)(Ptr - (BYTE*)lpOTM);
1523 Ptr += StringSize;
1524 AvailableSize -= StringSize;
1525 Size += StringSize;
1526 }
1527 }
1528
1529 if (LocalOTM->otmpFullName)
1530 {
1531 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFullName);
1532 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR);
1533 if (AvailableSize >= StringSize)
1534 {
1535 CopyMemory(Ptr, Str, StringSize);
1536 lpOTM->otmpFullName = (PSTR)(Ptr - (BYTE*)lpOTM);
1537 Ptr += StringSize;
1538 AvailableSize -= StringSize;
1539 Size += StringSize;
1540 }
1541 }
1542
1543 lpOTM->otmSize = Size;
1544
1545 HeapFree(GetProcessHeap(), 0, LocalOTM);
1546
1547 return Size;
1548 }
1549
1550 /*
1551 * @implemented
1552 */
1553 DWORD
1554 WINAPI
1555 GetKerningPairsW(HDC hdc,
1556 ULONG cPairs,
1557 LPKERNINGPAIR pkpDst)
1558 {
1559 if ((cPairs != 0) || (pkpDst == 0))
1560 {
1561 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst);
1562 }
1563 else
1564 {
1565 SetLastError(ERROR_INVALID_PARAMETER);
1566 return 0;
1567 }
1568 }
1569
1570 /*
1571 * @implemented
1572 */
1573 DWORD
1574 WINAPI
1575 GetKerningPairsA( HDC hDC,
1576 DWORD cPairs,
1577 LPKERNINGPAIR kern_pairA )
1578 {
1579 INT charset;
1580 CHARSETINFO csi;
1581 CPINFO cpi;
1582 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1583 KERNINGPAIR *kern_pairW;
1584
1585 if (!cPairs && kern_pairA)
1586 {
1587 SetLastError(ERROR_INVALID_PARAMETER);
1588 return 0;
1589 }
1590
1591 charset = GetTextCharset(hDC);
1592 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
1593 {
1594 DPRINT1("Can't find codepage for charset %d\n", charset);
1595 return 0;
1596 }
1597 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1598 * to fail on an invalid character for CP_SYMBOL.
1599 */
1600 cpi.DefaultChar[0] = 0;
1601 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
1602 {
1603 DPRINT1("Can't find codepage %u info\n", csi.ciACP);
1604 return 0;
1605 }
1606 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP);
1607
1608 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL);
1609 if (!total_kern_pairs) return 0;
1610
1611 if (!cPairs && !kern_pairA) return total_kern_pairs;
1612
1613 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
1614 if (kern_pairW == NULL)
1615 {
1616 return 0;
1617 }
1618 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
1619
1620 for (i = 0; i < total_kern_pairs; i++)
1621 {
1622 char first, second;
1623
1624 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
1625 continue;
1626
1627 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
1628 continue;
1629
1630 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1631 continue;
1632
1633 if (kern_pairA)
1634 {
1635 if (kern_pairs_copied >= cPairs) break;
1636
1637 kern_pairA->wFirst = (BYTE)first;
1638 kern_pairA->wSecond = (BYTE)second;
1639 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1640 kern_pairA++;
1641 }
1642 kern_pairs_copied++;
1643 }
1644
1645 HeapFree(GetProcessHeap(), 0, kern_pairW);
1646
1647 return kern_pairs_copied;
1648 }
1649
1650
1651
1652 /*
1653 * @implemented
1654 */
1655 HFONT
1656 WINAPI
1657 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd)
1658 {
1659 if (elfexd)
1660 {
1661 ENUMLOGFONTEXDVW Logfont;
1662
1663 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd,
1664 &Logfont.elfEnumLogfontEx );
1665
1666 RtlCopyMemory( &Logfont.elfDesignVector,
1667 (PVOID) &elfexd->elfDesignVector,
1668 sizeof(DESIGNVECTOR));
1669
1670 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL);
1671 }
1672 else return NULL;
1673 }
1674
1675
1676 /*
1677 * @implemented
1678 */
1679 HFONT
1680 WINAPI
1681 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd)
1682 {
1683 /* Msdn: Note, this function ignores the elfDesignVector member in
1684 ENUMLOGFONTEXDV.
1685 */
1686 if ( elfexd )
1687 {
1688 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL );
1689 }
1690 else return NULL;
1691 }
1692
1693
1694 /*
1695 * @implemented
1696 */
1697 HFONT
1698 WINAPI
1699 CreateFontIndirectA(
1700 CONST LOGFONTA *lplf
1701 )
1702 {
1703 if (lplf)
1704 {
1705 LOGFONTW tlf;
1706
1707 LogFontA2W(&tlf, lplf);
1708 return CreateFontIndirectW(&tlf);
1709 }
1710 else return NULL;
1711 }
1712
1713
1714 #if DBG
1715 VOID DumpFamilyInfo(const FONTFAMILYINFO *Info, LONG Count)
1716 {
1717 LONG i;
1718 const LOGFONTW *plf;
1719
1720 DPRINT1("---\n");
1721 DPRINT1("Count: %d\n", Count);
1722 for (i = 0; i < Count; ++i)
1723 {
1724 plf = &Info[i].EnumLogFontEx.elfLogFont;
1725 DPRINT1("%d: '%S',%u,'%S', %ld:%ld, %ld, %d, %d\n", i,
1726 plf->lfFaceName, plf->lfCharSet, Info[i].EnumLogFontEx.elfFullName,
1727 plf->lfHeight, plf->lfWidth, plf->lfWeight, plf->lfItalic, plf->lfPitchAndFamily);
1728 }
1729 }
1730
1731 VOID DoFontSystemUnittest(VOID)
1732 {
1733 LOGFONTW LogFont;
1734 FONTFAMILYINFO Info[4];
1735 UNICODE_STRING Str1, Str2;
1736 LONG ret, InfoCount;
1737
1738 //DumpFontInfo(TRUE);
1739
1740 /* L"" DEFAULT_CHARSET */
1741 RtlZeroMemory(&LogFont, sizeof(LogFont));
1742 LogFont.lfCharSet = DEFAULT_CHARSET;
1743 InfoCount = RTL_NUMBER_OF(Info);
1744 ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
1745 DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
1746 DumpFamilyInfo(Info, ret);
1747 ASSERT(ret == RTL_NUMBER_OF(Info));
1748 ASSERT(InfoCount > 32);
1749
1750 /* L"Microsoft Sans Serif" ANSI_CHARSET */
1751 RtlZeroMemory(&LogFont, sizeof(LogFont));
1752 LogFont.lfCharSet = ANSI_CHARSET;
1753 StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Microsoft Sans Serif");
1754 InfoCount = RTL_NUMBER_OF(Info);
1755 ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
1756 DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
1757 DumpFamilyInfo(Info, ret);
1758 ASSERT(ret != -1);
1759 ASSERT(InfoCount > 0);
1760 ASSERT(InfoCount < 16);
1761
1762 RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfLogFont.lfFaceName);
1763 RtlInitUnicodeString(&Str2, L"Microsoft Sans Serif");
1764 ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE);
1765 ASSERT(ret == 0);
1766
1767 RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfFullName);
1768 RtlInitUnicodeString(&Str2, L"Tahoma");
1769 ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE);
1770 ASSERT(ret == 0);
1771
1772 /* L"Non-Existent" DEFAULT_CHARSET */
1773 RtlZeroMemory(&LogFont, sizeof(LogFont));
1774 LogFont.lfCharSet = ANSI_CHARSET;
1775 StringCbCopyW(LogFont.lfFaceName, sizeof(LogFont.lfFaceName), L"Non-Existent");
1776 InfoCount = RTL_NUMBER_OF(Info);
1777 ret = NtGdiGetFontFamilyInfo(NULL, &LogFont, Info, &InfoCount);
1778 DPRINT1("ret: %ld, InfoCount: %ld\n", ret, InfoCount);
1779 DumpFamilyInfo(Info, ret);
1780 ASSERT(ret == 0);
1781 ASSERT(InfoCount == 0);
1782 }
1783 #endif
1784
1785 /* EOF */
1786 /*
1787 * @implemented
1788 */
1789 HFONT
1790 WINAPI
1791 CreateFontIndirectW(
1792 CONST LOGFONTW *lplf
1793 )
1794 {
1795 #if DBG
1796 static BOOL bDidTest = FALSE;
1797 if (!bDidTest)
1798 {
1799 DoFontSystemUnittest();
1800 bDidTest = TRUE;
1801 }
1802 #endif
1803 if (lplf)
1804 {
1805 ENUMLOGFONTEXDVW Logfont;
1806
1807 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW));
1808 // Need something other than just cleaning memory here.
1809 // Guess? Use caller data to determine the rest.
1810 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName,
1811 sizeof(Logfont.elfEnumLogfontEx.elfFullName));
1812 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle,
1813 sizeof(Logfont.elfEnumLogfontEx.elfStyle));
1814 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript,
1815 sizeof(Logfont.elfEnumLogfontEx.elfScript));
1816
1817 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES
1818
1819 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR));
1820
1821 return CreateFontIndirectExW(&Logfont);
1822 }
1823 else return NULL;
1824 }
1825
1826
1827 /*
1828 * @implemented
1829 */
1830 HFONT
1831 WINAPI
1832 CreateFontA(
1833 int nHeight,
1834 int nWidth,
1835 int nEscapement,
1836 int nOrientation,
1837 int fnWeight,
1838 DWORD fdwItalic,
1839 DWORD fdwUnderline,
1840 DWORD fdwStrikeOut,
1841 DWORD fdwCharSet,
1842 DWORD fdwOutputPrecision,
1843 DWORD fdwClipPrecision,
1844 DWORD fdwQuality,
1845 DWORD fdwPitchAndFamily,
1846 LPCSTR lpszFace
1847 )
1848 {
1849 ANSI_STRING StringA;
1850 UNICODE_STRING StringU;
1851 HFONT ret;
1852
1853 RtlInitAnsiString(&StringA, (LPSTR)lpszFace);
1854 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
1855
1856 ret = CreateFontW(nHeight,
1857 nWidth,
1858 nEscapement,
1859 nOrientation,
1860 fnWeight,
1861 fdwItalic,
1862 fdwUnderline,
1863 fdwStrikeOut,
1864 fdwCharSet,
1865 fdwOutputPrecision,
1866 fdwClipPrecision,
1867 fdwQuality,
1868 fdwPitchAndFamily,
1869 StringU.Buffer);
1870
1871 RtlFreeUnicodeString(&StringU);
1872
1873 return ret;
1874 }
1875
1876
1877 /*
1878 * @implemented
1879 */
1880 HFONT
1881 WINAPI
1882 CreateFontW(
1883 int nHeight,
1884 int nWidth,
1885 int nEscapement,
1886 int nOrientation,
1887 int nWeight,
1888 DWORD fnItalic,
1889 DWORD fdwUnderline,
1890 DWORD fdwStrikeOut,
1891 DWORD fdwCharSet,
1892 DWORD fdwOutputPrecision,
1893 DWORD fdwClipPrecision,
1894 DWORD fdwQuality,
1895 DWORD fdwPitchAndFamily,
1896 LPCWSTR lpszFace
1897 )
1898 {
1899 LOGFONTW logfont;
1900
1901 logfont.lfHeight = nHeight;
1902 logfont.lfWidth = nWidth;
1903 logfont.lfEscapement = nEscapement;
1904 logfont.lfOrientation = nOrientation;
1905 logfont.lfWeight = nWeight;
1906 logfont.lfItalic = (BYTE)fnItalic;
1907 logfont.lfUnderline = (BYTE)fdwUnderline;
1908 logfont.lfStrikeOut = (BYTE)fdwStrikeOut;
1909 logfont.lfCharSet = (BYTE)fdwCharSet;
1910 logfont.lfOutPrecision = (BYTE)fdwOutputPrecision;
1911 logfont.lfClipPrecision = (BYTE)fdwClipPrecision;
1912 logfont.lfQuality = (BYTE)fdwQuality;
1913 logfont.lfPitchAndFamily = (BYTE)fdwPitchAndFamily;
1914
1915 if (NULL != lpszFace)
1916 {
1917 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR);
1918 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1);
1919 /* Be 101% sure to have '\0' at end of string */
1920 logfont.lfFaceName[Size - 1] = '\0';
1921 }
1922 else
1923 {
1924 logfont.lfFaceName[0] = L'\0';
1925 }
1926
1927 return CreateFontIndirectW(&logfont);
1928 }
1929
1930
1931 /*
1932 * @unimplemented
1933 */
1934 BOOL
1935 WINAPI
1936 CreateScalableFontResourceA(
1937 DWORD fdwHidden,
1938 LPCSTR lpszFontRes,
1939 LPCSTR lpszFontFile,
1940 LPCSTR lpszCurrentPath
1941 )
1942 {
1943 return FALSE;
1944 }
1945
1946
1947 /*
1948 * @implemented
1949 */
1950 int
1951 WINAPI
1952 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
1953 {
1954 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1955 {
1956 SetLastError( ERROR_INVALID_PARAMETER );
1957 return 0;
1958 }
1959
1960 return GdiAddFontResourceW(lpszFilename, fl,0);
1961 }
1962
1963
1964 /*
1965 * @implemented
1966 */
1967 int
1968 WINAPI
1969 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
1970 {
1971 NTSTATUS Status;
1972 PWSTR FilenameW;
1973 int rc;
1974
1975 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
1976 {
1977 SetLastError( ERROR_INVALID_PARAMETER );
1978 return 0;
1979 }
1980
1981 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
1982 if ( !NT_SUCCESS (Status) )
1983 {
1984 SetLastError (RtlNtStatusToDosError(Status));
1985 return 0;
1986 }
1987
1988 rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
1989 HEAP_free ( FilenameW );
1990 return rc;
1991 }
1992
1993
1994 /*
1995 * @implemented
1996 */
1997 int
1998 WINAPI
1999 AddFontResourceA ( LPCSTR lpszFilename )
2000 {
2001 NTSTATUS Status;
2002 PWSTR FilenameW;
2003 int rc = 0;
2004
2005 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
2006 if ( !NT_SUCCESS (Status) )
2007 {
2008 SetLastError (RtlNtStatusToDosError(Status));
2009 }
2010 else
2011 {
2012 rc = GdiAddFontResourceW ( FilenameW, 0, 0);
2013
2014 HEAP_free ( FilenameW );
2015 }
2016 return rc;
2017 }
2018
2019
2020 /*
2021 * @implemented
2022 */
2023 int
2024 WINAPI
2025 AddFontResourceW ( LPCWSTR lpszFilename )
2026 {
2027 return GdiAddFontResourceW ( lpszFilename, 0, 0 );
2028 }
2029
2030
2031 /*
2032 * @implemented
2033 */
2034 BOOL
2035 WINAPI
2036 RemoveFontResourceW(LPCWSTR lpFileName)
2037 {
2038 return RemoveFontResourceExW(lpFileName,0,0);
2039 }
2040
2041
2042 /*
2043 * @implemented
2044 */
2045 BOOL
2046 WINAPI
2047 RemoveFontResourceA(LPCSTR lpFileName)
2048 {
2049 return RemoveFontResourceExA(lpFileName,0,0);
2050 }
2051
2052 /*
2053 * @unimplemented
2054 */
2055 BOOL
2056 WINAPI
2057 RemoveFontResourceExA(LPCSTR lpFileName,
2058 DWORD fl,
2059 PVOID pdv
2060 )
2061 {
2062 NTSTATUS Status;
2063 LPWSTR lpFileNameW;
2064
2065 /* FIXME the flags */
2066 /* FIXME the pdv */
2067 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
2068
2069 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName );
2070 if (!NT_SUCCESS (Status))
2071 SetLastError (RtlNtStatusToDosError(Status));
2072 else
2073 {
2074
2075 HEAP_free ( lpFileNameW );
2076 }
2077
2078 return 0;
2079 }
2080
2081 /*
2082 * @unimplemented
2083 */
2084 BOOL
2085 WINAPI
2086 RemoveFontResourceExW(LPCWSTR lpFileName,
2087 DWORD fl,
2088 PVOID pdv)
2089 {
2090 /* FIXME the flags */
2091 /* FIXME the pdv */
2092 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
2093 DPRINT("RemoveFontResourceExW\n");
2094 return 0;
2095 }
2096
2097
2098 /***********************************************************************
2099 * GdiGetCharDimensions
2100 *
2101 * Gets the average width of the characters in the English alphabet.
2102 *
2103 * PARAMS
2104 * hdc [I] Handle to the device context to measure on.
2105 * lptm [O] Pointer to memory to store the text metrics into.
2106 * height [O] On exit, the maximum height of characters in the English alphabet.
2107 *
2108 * RETURNS
2109 * The average width of characters in the English alphabet.
2110 *
2111 * NOTES
2112 * This function is used by the dialog manager to get the size of a dialog
2113 * unit. It should also be used by other pieces of code that need to know
2114 * the size of a dialog unit in logical units without having access to the
2115 * window handle of the dialog.
2116 * Windows caches the font metrics from this function, but we don't and
2117 * there doesn't appear to be an immediate advantage to do so.
2118 *
2119 * SEE ALSO
2120 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
2121 *
2122 * Despite most of MSDN insisting that the horizontal base unit is
2123 * tmAveCharWidth it isn't. Knowledge base article Q145994
2124 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
2125 * says that we should take the average of the 52 English upper and lower
2126 * case characters.
2127 */
2128 /*
2129 * @implemented
2130 */
2131 LONG
2132 WINAPI
2133 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
2134 {
2135 SIZE sz;
2136 TEXTMETRICW tm;
2137 static const WCHAR alphabet[] =
2138 {
2139 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2140 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2141 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0
2142 };
2143
2144 if(!GetTextMetricsW(hdc, &tm)) return 0;
2145
2146 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
2147
2148 if (lptm) *lptm = tm;
2149 if (height) *height = tm.tmHeight;
2150
2151 return (sz.cx / 26 + 1) / 2;
2152 }
2153
2154 /*************************************************************************
2155 * TranslateCharsetInfo [GDI32.@]
2156 *
2157 * Fills a CHARSETINFO structure for a character set, code page, or
2158 * font. This allows making the correspondance between different labelings
2159 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2160 * of the same encoding.
2161 *
2162 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2163 * only one codepage should be set in *lpSrc.
2164 *
2165 * RETURNS
2166 * TRUE on success, FALSE on failure.
2167 *
2168 */
2169 /*
2170 * @implemented
2171 */
2172 BOOL
2173 WINAPI
2174 TranslateCharsetInfo(
2175 LPDWORD lpSrc, /* [in]
2176 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2177 if flags == TCI_SRCCHARSET: a character set value
2178 if flags == TCI_SRCCODEPAGE: a code page value
2179 */
2180 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2181 DWORD flags /* [in] determines interpretation of lpSrc */)
2182 {
2183 int index = 0;
2184 switch (flags)
2185 {
2186 case TCI_SRCFONTSIG:
2187 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2188 break;
2189 case TCI_SRCCODEPAGE:
2190 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2191 break;
2192 case TCI_SRCCHARSET:
2193 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2194 break;
2195 case TCI_SRCLOCALE:
2196 {
2197 LCID lCid = (LCID)PtrToUlong(lpSrc);
2198 LOCALESIGNATURE LocSig;
2199 INT Ret = GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, 0);
2200 if ( GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, Ret))
2201 {
2202 while (index < MAXTCIINDEX && !(LocSig.lsCsbDefault[0]>>index & 0x0001)) index++;
2203 break;
2204 }
2205 }
2206 default:
2207 GdiSetLastError(ERROR_INVALID_PARAMETER);
2208 return FALSE;
2209 }
2210 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2211 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n",
2212 index,FONT_tci[index].ciCharset,FONT_tci[index].ciACP,FONT_tci[index].fs.fsCsb[0]);
2213 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2214 return TRUE;
2215 }
2216
2217
2218 /*
2219 * @implemented
2220 */
2221 DWORD
2222 WINAPI
2223 SetMapperFlags(
2224 HDC hDC,
2225 DWORD flags
2226 )
2227 {
2228 DWORD Ret = GDI_ERROR;
2229 PDC_ATTR Dc_Attr;
2230 #if 0
2231 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
2232 {
2233 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
2234 return MFDRV_SetMapperFlags( hDC, flags);
2235 else
2236 {
2237 PLDC pLDC = Dc_Attr->pvLDC;
2238 if ( !pLDC )
2239 {
2240 SetLastError(ERROR_INVALID_HANDLE);
2241 return GDI_ERROR;
2242 }
2243 if (pLDC->iType == LDC_EMFLDC)
2244 {
2245 return EMFDRV_SetMapperFlags( hDC, flags);
2246 }
2247 }
2248 }
2249 #endif
2250 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR;
2251
2252 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC)
2253 {
2254 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY)
2255 {
2256 NtGdiFlush();
2257 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
2258 }
2259 }
2260
2261 if ( flags & ~1 )
2262 SetLastError(ERROR_INVALID_PARAMETER);
2263 else
2264 {
2265 Ret = Dc_Attr->flFontMapper;
2266 Dc_Attr->flFontMapper = flags;
2267 }
2268 return Ret;
2269 }
2270
2271
2272 /*
2273 * @unimplemented
2274 */
2275 int
2276 WINAPI
2277 EnumFontsW(
2278 HDC hDC,
2279 LPCWSTR lpFaceName,
2280 FONTENUMPROCW FontFunc,
2281 LPARAM lParam
2282 )
2283 {
2284 #if 0
2285 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam );
2286 #else
2287 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam );
2288 #endif
2289 }
2290
2291 /*
2292 * @unimplemented
2293 */
2294 int
2295 WINAPI
2296 EnumFontsA (
2297 HDC hDC,
2298 LPCSTR lpFaceName,
2299 FONTENUMPROCA FontFunc,
2300 LPARAM lParam
2301 )
2302 {
2303 #if 0
2304 NTSTATUS Status;
2305 LPWSTR lpFaceNameW;
2306 int rc = 0;
2307
2308 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName );
2309 if (!NT_SUCCESS (Status))
2310 SetLastError (RtlNtStatusToDosError(Status));
2311 else
2312 {
2313 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam );
2314
2315 HEAP_free ( lpFaceNameW );
2316 }
2317 return rc;
2318 #else
2319 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam );
2320 #endif
2321 }
2322
2323 #define EfdFontFamilies 3
2324
2325 INT
2326 WINAPI
2327 NewEnumFontFamiliesExW(
2328 HDC hDC,
2329 LPLOGFONTW lpLogfont,
2330 FONTENUMPROCW lpEnumFontFamExProcW,
2331 LPARAM lParam,
2332 DWORD dwFlags)
2333 {
2334 ULONG_PTR idEnum;
2335 ULONG cbDataSize, cbRetSize;
2336 PENUMFONTDATAW pEfdw;
2337 PBYTE pBuffer;
2338 PBYTE pMax;
2339 INT ret = 1;
2340
2341 /* Open enumeration handle and find out how much memory we need */
2342 idEnum = NtGdiEnumFontOpen(hDC,
2343 EfdFontFamilies,
2344 0,
2345 LF_FACESIZE,
2346 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL,
2347 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET,
2348 &cbDataSize);
2349 if (idEnum == 0)
2350 {
2351 return 0;
2352 }
2353 if (cbDataSize == 0)
2354 {
2355 NtGdiEnumFontClose(idEnum);
2356 return 0;
2357 }
2358
2359 /* Allocate memory */
2360 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize);
2361 if (pBuffer == NULL)
2362 {
2363 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2364 NtGdiEnumFontClose(idEnum);
2365 return 0;
2366 }
2367
2368 /* Do the enumeration */
2369 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer))
2370 {
2371 HeapFree(GetProcessHeap(), 0, pBuffer);
2372 NtGdiEnumFontClose(idEnum);
2373 return 0;
2374 }
2375
2376 /* Get start and end address */
2377 pEfdw = (PENUMFONTDATAW)pBuffer;
2378 pMax = pBuffer + cbDataSize;
2379
2380 /* Iterate through the structures */
2381 while ((PBYTE)pEfdw < pMax && ret)
2382 {
2383 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset);
2384
2385 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx,
2386 (VOID*)&pNtmwi->ntmw,
2387 pEfdw->dwFontType,
2388 lParam);
2389
2390 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize);
2391 }
2392
2393 /* Release the memory and close handle */
2394 HeapFree(GetProcessHeap(), 0, pBuffer);
2395 NtGdiEnumFontClose(idEnum);
2396
2397 return ret;
2398 }
2399
2400 /*
2401 * @implemented
2402 */
2403 int
2404 WINAPI
2405 GdiAddFontResourceW(
2406 LPCWSTR lpszFilename,
2407 FLONG fl,
2408 DESIGNVECTOR *pdv)
2409 {
2410 INT Ret;
2411 WCHAR lpszBuffer[MAX_PATH];
2412 WCHAR lpszAbsPath[MAX_PATH];
2413 UNICODE_STRING NtAbsPath;
2414
2415 /* FIXME: We don't support multiple files passed in lpszFilename
2416 * as L"abcxxxxx.pfm|abcxxxxx.pfb"
2417 */
2418
2419 /* Does the file exist in CurrentDirectory or in the Absolute Path passed? */
2420 GetCurrentDirectoryW(MAX_PATH, lpszBuffer);
2421
2422 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL))
2423 {
2424 /* Nope. Then let's check Fonts folder */
2425 GetWindowsDirectoryW(lpszBuffer, MAX_PATH);
2426 StringCbCatW(lpszBuffer, sizeof(lpszBuffer), L"\\Fonts");
2427
2428 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL))
2429 {
2430 DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer, lpszFilename);
2431 return 0;
2432 }
2433 }
2434
2435 /* We found the font file so: */
2436 if (!RtlDosPathNameToNtPathName_U(lpszAbsPath, &NtAbsPath, NULL, NULL))
2437 {
2438 DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath);
2439 return 0;
2440 }
2441
2442 /* The Nt call expects a null-terminator included in cwc param. */
2443 ASSERT(NtAbsPath.Buffer[NtAbsPath.Length / sizeof(WCHAR)] == UNICODE_NULL);
2444 Ret = NtGdiAddFontResourceW(NtAbsPath.Buffer, NtAbsPath.Length / sizeof(WCHAR) + 1, 1, fl, 0, pdv);
2445
2446 RtlFreeUnicodeString(&NtAbsPath);
2447
2448 return Ret;
2449 }
2450
2451 /*
2452 * @implemented
2453 */
2454 HANDLE
2455 WINAPI
2456 AddFontMemResourceEx(
2457 PVOID pbFont,
2458 DWORD cbFont,
2459 PVOID pdv,
2460 DWORD *pcFonts
2461 )
2462 {
2463 if ( pbFont && cbFont && pcFonts)
2464 {
2465 return NtGdiAddFontMemResourceEx(pbFont, cbFont, NULL, 0, pcFonts);
2466 }
2467 SetLastError(ERROR_INVALID_PARAMETER);
2468 return NULL;
2469 }
2470
2471 /*
2472 * @implemented
2473 */
2474 BOOL
2475 WINAPI
2476 RemoveFontMemResourceEx(HANDLE fh)
2477 {
2478 if (fh)
2479 {
2480 return NtGdiRemoveFontMemResourceEx(fh);
2481 }
2482 SetLastError(ERROR_INVALID_PARAMETER);
2483 return FALSE;
2484 }
2485
2486
2487 /*
2488 * @unimplemented
2489 */
2490 int
2491 WINAPI
2492 AddFontResourceTracking(
2493 LPCSTR lpString,
2494 int unknown
2495 )
2496 {
2497 UNIMPLEMENTED;
2498 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2499 return 0;
2500 }
2501
2502 /*
2503 * @unimplemented
2504 */
2505 int
2506 WINAPI
2507 RemoveFontResourceTracking(LPCSTR lpString,int unknown)
2508 {
2509 UNIMPLEMENTED;
2510 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2511 return 0;
2512 }
2513
2514 BOOL
2515 WINAPI
2516 CreateScalableFontResourceW(
2517 DWORD fdwHidden,
2518 LPCWSTR lpszFontRes,
2519 LPCWSTR lpszFontFile,
2520 LPCWSTR lpszCurrentPath
2521 )
2522 {
2523 HANDLE f;
2524
2525 UNIMPLEMENTED;
2526
2527 /* fHidden=1 - only visible for the calling app, read-only, not
2528 * enumerated with EnumFonts/EnumFontFamilies
2529 * lpszCurrentPath can be NULL
2530 */
2531
2532 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2533 if ((f = CreateFileW(lpszFontRes, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
2534 {
2535 CloseHandle(f);
2536 SetLastError(ERROR_FILE_EXISTS);
2537 return FALSE;
2538 }
2539 return FALSE; /* create failed */
2540 }
2541
2542 /*
2543 * @unimplemented
2544 */
2545 BOOL
2546 WINAPI
2547 bInitSystemAndFontsDirectoriesW(LPWSTR *SystemDir,LPWSTR *FontsDir)
2548 {
2549 UNIMPLEMENTED;
2550 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2551 return 0;
2552 }
2553
2554 /*
2555 * @unimplemented
2556 */
2557 BOOL
2558 WINAPI
2559 EudcLoadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath,INT iPriority,INT iFontLinkType)
2560 {
2561 UNIMPLEMENTED;
2562 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2563 return 0;
2564 }
2565
2566 /*
2567 * @unimplemented
2568 */
2569 BOOL
2570 WINAPI
2571 EudcUnloadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath)
2572 {
2573 UNIMPLEMENTED;
2574 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2575 return 0;
2576 }
2577
2578 /*
2579 * @implemented
2580 */
2581 ULONG
2582 WINAPI
2583 GetEUDCTimeStamp(VOID)
2584 {
2585 return NtGdiGetEudcTimeStampEx(NULL,0,TRUE);
2586 }
2587
2588 /*
2589 * @implemented
2590 */
2591 DWORD
2592 WINAPI
2593 GetEUDCTimeStampExW(LPWSTR lpBaseFaceName)
2594 {
2595 DWORD retValue = 0;
2596
2597 if (!lpBaseFaceName)
2598 {
2599 retValue = NtGdiGetEudcTimeStampEx(NULL,0,FALSE);
2600 }
2601 else
2602 {
2603 retValue = NtGdiGetEudcTimeStampEx(lpBaseFaceName, wcslen(lpBaseFaceName), FALSE);
2604 }
2605
2606 return retValue;
2607 }
2608
2609 /*
2610 * @implemented
2611 */
2612 ULONG
2613 WINAPI
2614 GetFontAssocStatus(HDC hdc)
2615 {
2616 ULONG retValue = 0;
2617
2618 if (hdc)
2619 {
2620 retValue = NtGdiQueryFontAssocInfo(hdc);
2621 }
2622
2623 return retValue;
2624 }
2625
2626 /*
2627 * @unimplemented
2628 */
2629 DWORD
2630 WINAPI
2631 QueryFontAssocStatus(VOID)
2632 {
2633 UNIMPLEMENTED;
2634 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2635 return 0;
2636 }
2637
2638 /*
2639 * @unimplemented
2640 */
2641 VOID
2642 WINAPI
2643 UnloadNetworkFonts(DWORD unknown)
2644 {
2645 UNIMPLEMENTED;
2646 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2647 }
2648
2649 /*
2650 * @implemented
2651 *
2652 */
2653 DWORD
2654 WINAPI
2655 GetFontData(HDC hdc,
2656 DWORD dwTable,
2657 DWORD dwOffset,
2658 LPVOID lpvBuffer,
2659 DWORD cbData)
2660 {
2661 if (!lpvBuffer)
2662 {
2663 cbData = 0;
2664 }
2665 return NtGdiGetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData);
2666 }
2667
2668 DWORD
2669 WINAPI
2670 cGetTTFFromFOT(DWORD x1 ,DWORD x2 ,DWORD x3, DWORD x4, DWORD x5, DWORD x6, DWORD x7)
2671 {
2672 UNIMPLEMENTED;
2673 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2674 return 0;
2675 }
2676