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