3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/gdi32/object/font.c
17 * For TranslateCharsetInfo
19 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
20 #define MAXTCIINDEX 32
21 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
23 { ANSI_CHARSET
, 1252, FS(0)},
24 { EASTEUROPE_CHARSET
, 1250, FS(1)},
25 { RUSSIAN_CHARSET
, 1251, FS(2)},
26 { GREEK_CHARSET
, 1253, FS(3)},
27 { TURKISH_CHARSET
, 1254, FS(4)},
28 { HEBREW_CHARSET
, 1255, FS(5)},
29 { ARABIC_CHARSET
, 1256, FS(6)},
30 { BALTIC_CHARSET
, 1257, FS(7)},
31 { VIETNAMESE_CHARSET
, 1258, FS(8)},
32 /* reserved by ANSI */
33 { DEFAULT_CHARSET
, 0, FS(0)},
34 { DEFAULT_CHARSET
, 0, FS(0)},
35 { DEFAULT_CHARSET
, 0, FS(0)},
36 { DEFAULT_CHARSET
, 0, FS(0)},
37 { DEFAULT_CHARSET
, 0, FS(0)},
38 { DEFAULT_CHARSET
, 0, FS(0)},
39 { DEFAULT_CHARSET
, 0, FS(0)},
41 { THAI_CHARSET
, 874, FS(16)},
42 { SHIFTJIS_CHARSET
, 932, FS(17)},
43 { GB2312_CHARSET
, 936, FS(18)},
44 { HANGEUL_CHARSET
, 949, FS(19)},
45 { CHINESEBIG5_CHARSET
, 950, FS(20)},
46 { JOHAB_CHARSET
, 1361, FS(21)},
47 /* reserved for alternate ANSI and OEM */
48 { DEFAULT_CHARSET
, 0, FS(0)},
49 { DEFAULT_CHARSET
, 0, FS(0)},
50 { DEFAULT_CHARSET
, 0, FS(0)},
51 { DEFAULT_CHARSET
, 0, FS(0)},
52 { DEFAULT_CHARSET
, 0, FS(0)},
53 { DEFAULT_CHARSET
, 0, FS(0)},
54 { DEFAULT_CHARSET
, 0, FS(0)},
55 { DEFAULT_CHARSET
, 0, FS(0)},
56 /* reserved for system */
57 { DEFAULT_CHARSET
, 0, FS(0)},
58 { SYMBOL_CHARSET
, CP_SYMBOL
, FS(31)},
61 #define INITIAL_FAMILY_COUNT 64
63 /***********************************************************************
64 * TEXTMETRIC conversion functions.
66 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
68 ptmA
->tmHeight
= ptmW
->tmHeight
;
69 ptmA
->tmAscent
= ptmW
->tmAscent
;
70 ptmA
->tmDescent
= ptmW
->tmDescent
;
71 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
72 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
73 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
74 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
75 ptmA
->tmWeight
= ptmW
->tmWeight
;
76 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
77 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
78 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
79 ptmA
->tmFirstChar
= ptmW
->tmFirstChar
> 255 ? 255 : ptmW
->tmFirstChar
;
80 ptmA
->tmLastChar
= ptmW
->tmLastChar
> 255 ? 255 : ptmW
->tmLastChar
;
81 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
> 255 ? 255 : ptmW
->tmDefaultChar
;
82 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
> 255 ? 255 : ptmW
->tmBreakChar
;
83 ptmA
->tmItalic
= ptmW
->tmItalic
;
84 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
85 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
86 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
87 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
90 /***********************************************************************
93 * Returns a Unicode translation of str using the charset of the
94 * currently selected font in hdc. If count is -1 then str is assumed
95 * to be '\0' terminated, otherwise it contains the number of bytes to
96 * convert. If plenW is non-NULL, on return it will point to the
97 * number of WCHARs that have been written. If pCP is non-NULL, on
98 * return it will point to the codepage used in the conversion. The
99 * caller should free the returned LPWSTR from the process heap
102 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
104 UINT cp
= CP_ACP
; // GdiGetCodePage( hdc );
108 if(count
== -1) count
= strlen(str
);
109 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
110 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
111 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
112 DPRINT1("mapped %s -> %S\n", str
, strW
);
113 if(plenW
) *plenW
= lenW
;
120 MetricsCharConvert(WCHAR w
, UCHAR
*b
)
122 UNICODE_STRING WString
;
136 RtlInitUnicodeString(&WString
, WBuf
);
139 RtlInitAnsiString(&AString
, ABuf
);
141 Status
= RtlUnicodeStringToAnsiString(&AString
, &WString
, FALSE
);
142 if (! NT_SUCCESS(Status
))
144 SetLastError(RtlNtStatusToDosError(Status
));
154 TextMetricW2A(TEXTMETRICA
*tma
, TEXTMETRICW
*tmw
)
156 UNICODE_STRING WString
;
163 tma
->tmHeight
= tmw
->tmHeight
;
164 tma
->tmAscent
= tmw
->tmAscent
;
165 tma
->tmDescent
= tmw
->tmDescent
;
166 tma
->tmInternalLeading
= tmw
->tmInternalLeading
;
167 tma
->tmExternalLeading
= tmw
->tmExternalLeading
;
168 tma
->tmAveCharWidth
= tmw
->tmAveCharWidth
;
169 tma
->tmMaxCharWidth
= tmw
->tmMaxCharWidth
;
170 tma
->tmWeight
= tmw
->tmWeight
;
171 tma
->tmOverhang
= tmw
->tmOverhang
;
172 tma
->tmDigitizedAspectX
= tmw
->tmDigitizedAspectX
;
173 tma
->tmDigitizedAspectY
= tmw
->tmDigitizedAspectY
;
175 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
176 FirstChar/LastChar. For example, if the font contains glyphs for
177 letters A-Z and an accented version of the letter e, the Unicode
178 FirstChar would be A and the Unicode LastChar would be the accented
179 e. If you just translate those to ANSI, the range would become
180 letters A-E instead of A-Z.
181 We translate all possible ANSI chars to Unicode and find the first
182 and last translated character which fall into the Unicode FirstChar/
183 LastChar range and return the corresponding ANSI char. */
185 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
186 the beginning since that would be interpreted as end-of-string, handle
187 '\0' special later */
188 for (Letter
= 1; Letter
< 256; Letter
++)
190 ABuf
[Letter
- 1] = (CHAR
) Letter
;
191 WBuf
[Letter
- 1] = L
' ';
195 RtlInitAnsiString(&AString
, ABuf
);
196 RtlInitUnicodeString(&WString
, WBuf
);
198 /* Find the corresponding Unicode characters */
199 Status
= RtlAnsiStringToUnicodeString(&WString
, &AString
, FALSE
);
200 if (! NT_SUCCESS(Status
))
202 SetLastError(RtlNtStatusToDosError(Status
));
206 /* Scan for the first ANSI character which maps to an Unicode character
208 tma
->tmFirstChar
= '\0';
209 if (L
'\0' != tmw
->tmFirstChar
)
211 for (Letter
= 1; Letter
< 256; Letter
++)
213 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
214 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
216 tma
->tmFirstChar
= (CHAR
) Letter
;
222 /* Scan for the last ANSI character which maps to an Unicode character
224 tma
->tmLastChar
= '\0';
225 if (L
'\0' != tmw
->tmLastChar
)
227 for (Letter
= 255; 0 < Letter
; Letter
--)
229 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
230 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
232 tma
->tmLastChar
= (CHAR
) Letter
;
238 if (! MetricsCharConvert(tmw
->tmDefaultChar
, &tma
->tmDefaultChar
) ||
239 ! MetricsCharConvert(tmw
->tmBreakChar
, &tma
->tmBreakChar
))
244 tma
->tmItalic
= tmw
->tmItalic
;
245 tma
->tmUnderlined
= tmw
->tmUnderlined
;
246 tma
->tmStruckOut
= tmw
->tmStruckOut
;
247 tma
->tmPitchAndFamily
= tmw
->tmPitchAndFamily
;
248 tma
->tmCharSet
= tmw
->tmCharSet
;
254 NewTextMetricW2A(NEWTEXTMETRICA
*tma
, NEWTEXTMETRICW
*tmw
)
256 if (! TextMetricW2A((TEXTMETRICA
*) tma
, (TEXTMETRICW
*) tmw
))
261 tma
->ntmFlags
= tmw
->ntmFlags
;
262 tma
->ntmSizeEM
= tmw
->ntmSizeEM
;
263 tma
->ntmCellHeight
= tmw
->ntmCellHeight
;
264 tma
->ntmAvgWidth
= tmw
->ntmAvgWidth
;
270 NewTextMetricExW2A(NEWTEXTMETRICEXA
*tma
, NEWTEXTMETRICEXW
*tmw
)
272 if (! NewTextMetricW2A(&tma
->ntmTm
, &tmw
->ntmTm
))
277 tma
->ntmFontSig
= tmw
->ntmFontSig
;
283 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
288 PFONTFAMILYINFO Info
;
291 ENUMLOGFONTEXA EnumLogFontExA
;
292 NEWTEXTMETRICEXA NewTextMetricExA
;
294 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
295 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
300 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
301 if (FontFamilyCount
< 0)
303 RtlFreeHeap(GetProcessHeap(), 0, Info
);
306 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
308 FontFamilySize
= FontFamilyCount
;
309 RtlFreeHeap(GetProcessHeap(), 0, Info
);
310 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
311 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
316 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
317 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
319 RtlFreeHeap(GetProcessHeap(), 0, Info
);
324 for (i
= 0; i
< FontFamilyCount
; i
++)
328 Ret
= ((FONTENUMPROCW
) EnumProc
)(
329 &Info
[i
].EnumLogFontEx
,
330 &Info
[i
].NewTextMetricEx
,
331 Info
[i
].FontType
, lParam
);
334 { // Could use EnumLogFontExW2A here?
335 LogFontW2A(&EnumLogFontExA
.elfLogFont
, &Info
[i
].EnumLogFontEx
.elfLogFont
);
336 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfFullName
, -1,
337 (LPSTR
)EnumLogFontExA
.elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
338 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfStyle
, -1,
339 (LPSTR
)EnumLogFontExA
.elfStyle
, LF_FACESIZE
, NULL
, NULL
);
340 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfScript
, -1,
341 (LPSTR
)EnumLogFontExA
.elfScript
, LF_FACESIZE
, NULL
, NULL
);
342 NewTextMetricExW2A(&NewTextMetricExA
,
343 &Info
[i
].NewTextMetricEx
);
344 Ret
= ((FONTENUMPROCA
) EnumProc
)(
347 Info
[i
].FontType
, lParam
);
351 RtlFreeHeap(GetProcessHeap(), 0, Info
);
360 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
361 LPARAM lParam
, DWORD dwFlags
)
363 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
, TRUE
);
371 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
376 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
377 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
378 if (NULL
!= lpszFamily
)
380 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
383 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, TRUE
);
391 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
392 LPARAM lParam
, DWORD dwFlags
)
396 LogFontA2W(&LogFontW
, lpLogfont
);
398 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
399 return IntEnumFontFamilies(hdc
, &LogFontW
, lpEnumFontFamExProc
, lParam
, FALSE
);
407 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
412 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
413 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
414 if (NULL
!= lpszFamily
)
416 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
419 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, FALSE
);
427 GetCharacterPlacementW(
432 GCP_RESULTSW
*lpResults
,
439 DPRINT("GetCharacterPlacementW\n");
441 if(dwFlags
&(~GCP_REORDER
)) DPRINT("flags 0x%08lx ignored\n", dwFlags
);
442 if(lpResults
->lpClass
) DPRINT("classes not implemented\n");
443 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
444 DPRINT("Caret positions for complex scripts not implemented\n");
447 if(nSet
> lpResults
->nGlyphs
)
448 nSet
= lpResults
->nGlyphs
;
450 /* return number of initialized fields */
451 lpResults
->nGlyphs
= nSet
;
453 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
455 /* Treat the case where no special handling was requested in a fastpath way */
456 /* copy will do if the GCP_REORDER flag is not set */
457 if(lpResults
->lpOutString
)
458 lstrcpynW( lpResults
->lpOutString
, lpString
, nSet
);
460 if(lpResults
->lpGlyphs
)
461 lstrcpynW( lpResults
->lpGlyphs
, lpString
, nSet
);
463 if(lpResults
->lpOrder
)
465 for(i
= 0; i
< nSet
; i
++)
466 lpResults
->lpOrder
[i
] = i
;
470 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
471 nSet, lpResults->lpOrder );
474 /* FIXME: Will use the placement chars */
478 for (i
= 0; i
< nSet
; i
++)
480 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
481 lpResults
->lpDx
[i
]= c
;
485 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
489 lpResults
->lpCaretPos
[0] = 0;
490 for (i
= 1; i
< nSet
; i
++)
491 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
492 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
495 /*if(lpResults->lpGlyphs)
496 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
498 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
499 ret
= MAKELONG(size
.cx
, size
.cy
);
510 GetCharABCWidthsFloatW(HDC hdc
,
515 DPRINT("GetCharABCWidthsFloatW\n");
516 if ((!abcF
) || (FirstChar
> LastChar
))
518 SetLastError(ERROR_INVALID_PARAMETER
);
521 return NtGdiGetCharABCWidthsW( hdc
,
523 (ULONG
)(LastChar
- FirstChar
+ 1),
535 GetCharWidthFloatW(HDC hdc
,
540 DPRINT("GetCharWidthsFloatW\n");
541 if ((!pxBuffer
) || (iFirstChar
> iLastChar
))
543 SetLastError(ERROR_INVALID_PARAMETER
);
546 return NtGdiGetCharWidthW( hdc
,
548 (ULONG
)(iLastChar
- iFirstChar
+ 1),
560 GetCharWidthW(HDC hdc
,
565 DPRINT("GetCharWidthsW\n");
566 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
568 SetLastError(ERROR_INVALID_PARAMETER
);
571 return NtGdiGetCharWidthW( hdc
,
573 (ULONG
)(iLastChar
- iFirstChar
+ 1),
585 GetCharWidth32W(HDC hdc
,
590 DPRINT("GetCharWidths32W\n");
591 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
593 SetLastError(ERROR_INVALID_PARAMETER
);
596 return NtGdiGetCharWidthW( hdc
,
598 (ULONG
)(iLastChar
- iFirstChar
+ 1),
600 GCW_NOFLOAT
|GCW_WIN32
,
611 GetCharABCWidthsW(HDC hdc
,
616 DPRINT("GetCharABCWidthsW\n");
617 if ((!lpabc
) || (FirstChar
> LastChar
))
619 SetLastError(ERROR_INVALID_PARAMETER
);
622 return NtGdiGetCharABCWidthsW( hdc
,
624 (ULONG
)(LastChar
- FirstChar
+ 1),
642 DPRINT("GetCharWidthsA\n");
643 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
648 if(count
<= 0) return FALSE
;
650 str
= HeapAlloc(GetProcessHeap(), 0, count
);
651 for(i
= 0; i
< count
; i
++)
652 str
[i
] = (BYTE
)(iFirstChar
+ i
);
654 wstr
= FONT_mbtowc(NULL
, str
, count
, &wlen
, NULL
);
656 ret
= NtGdiGetCharWidthW( hdc
,
663 HeapFree(GetProcessHeap(), 0, str
);
664 HeapFree(GetProcessHeap(), 0, wstr
);
681 DPRINT("GetCharWidths32A\n");
682 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
687 if(count
<= 0) return FALSE
;
689 str
= HeapAlloc(GetProcessHeap(), 0, count
);
690 for(i
= 0; i
< count
; i
++)
691 str
[i
] = (BYTE
)(iFirstChar
+ i
);
693 wstr
= FONT_mbtowc(NULL
, str
, count
, &wlen
, NULL
);
695 ret
= NtGdiGetCharWidthW( hdc
,
699 GCW_NOFLOAT
|GCW_WIN32
,
702 HeapFree(GetProcessHeap(), 0, str
);
703 HeapFree(GetProcessHeap(), 0, wstr
);
720 DPRINT("GetCharWidthsFloatA\n");
721 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
726 if(count
<= 0) return FALSE
;
728 str
= HeapAlloc(GetProcessHeap(), 0, count
);
729 for(i
= 0; i
< count
; i
++)
730 str
[i
] = (BYTE
)(iFirstChar
+ i
);
732 wstr
= FONT_mbtowc(NULL
, str
, count
, &wlen
, NULL
);
734 ret
= NtGdiGetCharWidthW( hdc
, wstr
[0], (ULONG
) count
, (PWCHAR
) wstr
, 0, (PVOID
) pxBuffer
);
736 HeapFree(GetProcessHeap(), 0, str
);
737 HeapFree(GetProcessHeap(), 0, wstr
);
754 DPRINT("GetCharABCWidthsA\n");
755 INT i
, wlen
, count
= (INT
)(uLastChar
- uFirstChar
+ 1);
760 if(count
<= 0) return FALSE
;
762 str
= HeapAlloc(GetProcessHeap(), 0, count
);
763 for(i
= 0; i
< count
; i
++)
764 str
[i
] = (BYTE
)(uFirstChar
+ i
);
766 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
768 ret
= NtGdiGetCharABCWidthsW( hdc
,
775 HeapFree(GetProcessHeap(), 0, str
);
776 HeapFree(GetProcessHeap(), 0, wstr
);
786 GetCharABCWidthsFloatA(
793 DPRINT("GetCharABCWidthsFloatA\n");
794 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
799 if (count
<= 0) return FALSE
;
801 str
= HeapAlloc(GetProcessHeap(), 0, count
);
803 for(i
= 0; i
< count
; i
++)
804 str
[i
] = (BYTE
)(iFirstChar
+ i
);
806 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
808 ret
= NtGdiGetCharABCWidthsW( hdc
,wstr
[0],(ULONG
)count
, (PWCHAR
)wstr
, 0, (PVOID
)lpABCF
);
810 HeapFree( GetProcessHeap(), 0, str
);
811 HeapFree( GetProcessHeap(), 0, wstr
);
821 GetCharABCWidthsI(HDC hdc
,
827 DPRINT("GetCharABCWidthsI\n");
828 return NtGdiGetCharABCWidthsW( hdc
,
832 GCABCW_NOFLOAT
|GCABCW_INDICES
,
841 GetCharWidthI(HDC hdc
,
848 DPRINT("GetCharWidthsI\n");
849 if (!lpBuffer
|| (!pgi
&& (giFirst
== MAXUSHORT
))) // Cannot be at max.
851 SetLastError(ERROR_INVALID_PARAMETER
);
854 if (!cgi
) return TRUE
;
855 return NtGdiGetCharWidthW( hdc
,
859 GCW_INDICES
|GCW_NOFLOAT
|GCW_WIN32
,
880 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
881 Ret
= NtGdiGetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
882 HeapFree(GetProcessHeap(), 0, lpstrW
);
905 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar
);
906 if(!(uFormat
& GGO_GLYPH_INDEX
)) {
909 if(uChar
> 0xff) { /* but, 2 bytes character only */
911 mbchs
[0] = (uChar
& 0xff00) >> 8;
912 mbchs
[1] = (uChar
& 0xff);
915 mbchs
[0] = (uChar
& 0xff);
917 p
= FONT_mbtowc(NULL
, mbchs
, len
, NULL
, NULL
);
921 ret
= NtGdiGetGlyphOutline(hdc
, c
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
922 HeapFree(GetProcessHeap(), 0, p
);
942 DPRINT("GetGlyphOutlineW uChar %x\n", uChar
);
943 if (!lpgm
& !lpmat2
) return GDI_ERROR
;
944 if (!lpvBuffer
) cbBuffer
= 0;
945 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
954 GetOutlineTextMetricsA(
957 LPOUTLINETEXTMETRICA lpOTM
962 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
963 OUTLINETEXTMETRICA
*output
= lpOTM
;
966 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
968 if(ret
> sizeof(buf
))
969 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
970 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
972 needed
= sizeof(OUTLINETEXTMETRICA
);
973 if(lpOTMW
->otmpFamilyName
)
974 needed
+= WideCharToMultiByte(CP_ACP
, 0,
975 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFamilyName
), -1,
976 NULL
, 0, NULL
, NULL
);
977 if(lpOTMW
->otmpFaceName
)
978 needed
+= WideCharToMultiByte(CP_ACP
, 0,
979 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFaceName
), -1,
980 NULL
, 0, NULL
, NULL
);
981 if(lpOTMW
->otmpStyleName
)
982 needed
+= WideCharToMultiByte(CP_ACP
, 0,
983 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpStyleName
), -1,
984 NULL
, 0, NULL
, NULL
);
985 if(lpOTMW
->otmpFullName
)
986 needed
+= WideCharToMultiByte(CP_ACP
, 0,
987 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFullName
), -1,
988 NULL
, 0, NULL
, NULL
);
995 DPRINT("needed = %d\n", needed
);
997 /* Since the supplied buffer isn't big enough, we'll alloc one
998 that is and memcpy the first cbData bytes into the lpOTM at
1000 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1002 ret
= output
->otmSize
= min(needed
, cbData
);
1003 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1004 output
->otmFiller
= 0;
1005 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1006 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1007 output
->otmfsType
= lpOTMW
->otmfsType
;
1008 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1009 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1010 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1011 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1012 output
->otmAscent
= lpOTMW
->otmAscent
;
1013 output
->otmDescent
= lpOTMW
->otmDescent
;
1014 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1015 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1016 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1017 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1018 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1019 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1020 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1021 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1022 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1023 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1024 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1025 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1026 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1027 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1028 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1029 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1032 ptr
= (char*)(output
+ 1);
1033 left
= needed
- sizeof(*output
);
1035 if(lpOTMW
->otmpFamilyName
) {
1036 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1037 len
= WideCharToMultiByte(CP_ACP
, 0,
1038 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFamilyName
), -1,
1039 ptr
, left
, NULL
, NULL
);
1043 output
->otmpFamilyName
= 0;
1045 if(lpOTMW
->otmpFaceName
) {
1046 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1047 len
= WideCharToMultiByte(CP_ACP
, 0,
1048 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFaceName
), -1,
1049 ptr
, left
, NULL
, NULL
);
1053 output
->otmpFaceName
= 0;
1055 if(lpOTMW
->otmpStyleName
) {
1056 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1057 len
= WideCharToMultiByte(CP_ACP
, 0,
1058 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpStyleName
), -1,
1059 ptr
, left
, NULL
, NULL
);
1063 output
->otmpStyleName
= 0;
1065 if(lpOTMW
->otmpFullName
) {
1066 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1067 len
= WideCharToMultiByte(CP_ACP
, 0,
1068 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFullName
), -1,
1069 ptr
, left
, NULL
, NULL
);
1072 output
->otmpFullName
= 0;
1076 if(output
!= lpOTM
) {
1077 memcpy(lpOTM
, output
, cbData
);
1078 HeapFree(GetProcessHeap(), 0, output
);
1080 /* check if the string offsets really fit into the provided size */
1081 /* FIXME: should we check string length as well? */
1082 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1083 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1085 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1086 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1088 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1089 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1091 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1092 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1096 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1097 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1108 GetOutlineTextMetricsW(
1111 LPOUTLINETEXTMETRICW lpOTM
1114 TMDIFF Tmd
; // Should not be zero.
1116 return NtGdiGetOutlineTextMetricsInternalW(hdc
, cbData
, lpOTM
, &Tmd
);
1124 GetKerningPairsW(HDC hdc
,
1126 LPKERNINGPAIR pkpDst
)
1128 if ((cPairs
!= 0) || (pkpDst
== 0))
1130 return NtGdiGetKerningPairs(hdc
,cPairs
,pkpDst
);
1134 SetLastError(ERROR_INVALID_PARAMETER
);
1144 GetKerningPairsA( HDC hDC
,
1146 LPKERNINGPAIR kern_pairA
)
1151 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
1152 KERNINGPAIR
*kern_pairW
;
1154 if (!cPairs
&& kern_pairA
)
1156 SetLastError(ERROR_INVALID_PARAMETER
);
1160 charset
= GetTextCharset(hDC
);
1161 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
1163 DPRINT1("Can't find codepage for charset %d\n", charset
);
1166 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1167 * to fail on an invalid character for CP_SYMBOL.
1169 cpi
.DefaultChar
[0] = 0;
1170 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
1172 DPRINT1("Can't find codepage %u info\n", csi
.ciACP
);
1175 DPRINT("charset %d => codepage %u\n", charset
, csi
.ciACP
);
1177 total_kern_pairs
= NtGdiGetKerningPairs(hDC
, 0, NULL
);
1178 if (!total_kern_pairs
) return 0;
1180 if (!cPairs
&& !kern_pairA
) return total_kern_pairs
;
1182 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
1183 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
1185 for (i
= 0; i
< total_kern_pairs
; i
++)
1189 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
1192 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
1195 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
1200 if (kern_pairs_copied
>= cPairs
) break;
1202 kern_pairA
->wFirst
= (BYTE
)first
;
1203 kern_pairA
->wSecond
= (BYTE
)second
;
1204 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
1207 kern_pairs_copied
++;
1210 HeapFree(GetProcessHeap(), 0, kern_pairW
);
1212 return kern_pairs_copied
;
1222 CreateFontIndirectExA(const ENUMLOGFONTEXDVA
*elfexd
)
1226 ENUMLOGFONTEXDVW Logfont
;
1228 EnumLogFontExW2A( (LPENUMLOGFONTEXA
) elfexd
,
1229 &Logfont
.elfEnumLogfontEx
);
1231 RtlCopyMemory( &Logfont
.elfDesignVector
,
1232 (PVOID
) &elfexd
->elfDesignVector
,
1233 sizeof(DESIGNVECTOR
));
1235 return NtGdiHfontCreate( &Logfont
, 0, 0, 0, NULL
);
1246 CreateFontIndirectExW(const ENUMLOGFONTEXDVW
*elfexd
)
1248 /* Msdn: Note, this function ignores the elfDesignVector member in
1253 return NtGdiHfontCreate((PENUMLOGFONTEXDVW
) elfexd
, 0, 0, 0, NULL
);
1264 CreateFontIndirectA(
1265 CONST LOGFONTA
*lplf
1272 LogFontA2W(&tlf
, lplf
);
1273 return CreateFontIndirectW(&tlf
);
1284 CreateFontIndirectW(
1285 CONST LOGFONTW
*lplf
1290 ENUMLOGFONTEXDVW Logfont
;
1292 RtlCopyMemory( &Logfont
.elfEnumLogfontEx
.elfLogFont
, lplf
, sizeof(LOGFONTW
));
1293 // Need something other than just cleaning memory here.
1294 // Guess? Use caller data to determine the rest.
1295 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfFullName
,
1296 sizeof(Logfont
.elfEnumLogfontEx
.elfFullName
));
1297 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfStyle
,
1298 sizeof(Logfont
.elfEnumLogfontEx
.elfStyle
));
1299 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfScript
,
1300 sizeof(Logfont
.elfEnumLogfontEx
.elfScript
));
1302 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
1304 return CreateFontIndirectExW(&Logfont
);
1325 DWORD fdwOutputPrecision
,
1326 DWORD fdwClipPrecision
,
1328 DWORD fdwPitchAndFamily
,
1332 ANSI_STRING StringA
;
1333 UNICODE_STRING StringU
;
1336 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
1337 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
1339 ret
= CreateFontW(nHeight
,
1354 RtlFreeUnicodeString(&StringU
);
1375 DWORD fdwOutputPrecision
,
1376 DWORD fdwClipPrecision
,
1378 DWORD fdwPitchAndFamily
,
1384 logfont
.lfHeight
= nHeight
;
1385 logfont
.lfWidth
= nWidth
;
1386 logfont
.lfEscapement
= nEscapement
;
1387 logfont
.lfOrientation
= nOrientation
;
1388 logfont
.lfWeight
= nWeight
;
1389 logfont
.lfItalic
= fnItalic
;
1390 logfont
.lfUnderline
= fdwUnderline
;
1391 logfont
.lfStrikeOut
= fdwStrikeOut
;
1392 logfont
.lfCharSet
= fdwCharSet
;
1393 logfont
.lfOutPrecision
= fdwOutputPrecision
;
1394 logfont
.lfClipPrecision
= fdwClipPrecision
;
1395 logfont
.lfQuality
= fdwQuality
;
1396 logfont
.lfPitchAndFamily
= fdwPitchAndFamily
;
1398 if (NULL
!= lpszFace
)
1400 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
1401 wcsncpy((wchar_t *)logfont
.lfFaceName
, lpszFace
, Size
- 1);
1402 /* Be 101% sure to have '\0' at end of string */
1403 logfont
.lfFaceName
[Size
- 1] = '\0';
1407 logfont
.lfFaceName
[0] = L
'\0';
1410 return CreateFontIndirectW(&logfont
);
1419 CreateScalableFontResourceA(
1422 LPCSTR lpszFontFile
,
1423 LPCSTR lpszCurrentPath
1435 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1437 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1439 SetLastError( ERROR_INVALID_PARAMETER
);
1443 return GdiAddFontResourceW(lpszFilename
, fl
,0);
1452 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1458 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1460 SetLastError( ERROR_INVALID_PARAMETER
);
1464 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1465 if ( !NT_SUCCESS (Status
) )
1467 SetLastError (RtlNtStatusToDosError(Status
));
1471 rc
= GdiAddFontResourceW ( FilenameW
, fl
, 0 );
1472 HEAP_free ( FilenameW
);
1482 AddFontResourceA ( LPCSTR lpszFilename
)
1488 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1489 if ( !NT_SUCCESS (Status
) )
1491 SetLastError (RtlNtStatusToDosError(Status
));
1495 rc
= GdiAddFontResourceW ( FilenameW
, 0, 0);
1497 HEAP_free ( FilenameW
);
1508 AddFontResourceW ( LPCWSTR lpszFilename
)
1510 return GdiAddFontResourceW ( lpszFilename
, 0, 0 );
1519 RemoveFontResourceW(LPCWSTR lpFileName
)
1521 return RemoveFontResourceExW(lpFileName
,0,0);
1530 RemoveFontResourceA(LPCSTR lpFileName
)
1532 return RemoveFontResourceExA(lpFileName
,0,0);
1540 RemoveFontResourceExA(LPCSTR lpFileName
,
1548 /* FIXME the flags */
1550 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1552 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
1553 if (!NT_SUCCESS (Status
))
1554 SetLastError (RtlNtStatusToDosError(Status
));
1558 HEAP_free ( lpFileNameW
);
1569 RemoveFontResourceExW(LPCWSTR lpFileName
,
1573 /* FIXME the flags */
1575 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1580 /***********************************************************************
1581 * GdiGetCharDimensions
1583 * Gets the average width of the characters in the English alphabet.
1586 * hdc [I] Handle to the device context to measure on.
1587 * lptm [O] Pointer to memory to store the text metrics into.
1588 * height [O] On exit, the maximum height of characters in the English alphabet.
1591 * The average width of characters in the English alphabet.
1594 * This function is used by the dialog manager to get the size of a dialog
1595 * unit. It should also be used by other pieces of code that need to know
1596 * the size of a dialog unit in logical units without having access to the
1597 * window handle of the dialog.
1598 * Windows caches the font metrics from this function, but we don't and
1599 * there doesn't appear to be an immediate advantage to do so.
1602 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1604 * Despite most of MSDN insisting that the horizontal base unit is
1605 * tmAveCharWidth it isn't. Knowledge base article Q145994
1606 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1607 * says that we should take the average of the 52 English upper and lower
1615 GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
1618 static const WCHAR alphabet
[] = {
1619 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1620 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1621 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1623 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
1625 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
1627 if (height
) *height
= sz
.cy
;
1628 return (sz
.cx
/ 26 + 1) / 2;
1631 /*************************************************************************
1632 * TranslateCharsetInfo [GDI32.@]
1634 * Fills a CHARSETINFO structure for a character set, code page, or
1635 * font. This allows making the correspondance between different labelings
1636 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1637 * of the same encoding.
1639 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1640 * only one codepage should be set in *lpSrc.
1643 * TRUE on success, FALSE on failure.
1651 TranslateCharsetInfo(
1652 LPDWORD lpSrc
, /* [in]
1653 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1654 if flags == TCI_SRCCHARSET: a character set value
1655 if flags == TCI_SRCCODEPAGE: a code page value
1657 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
1658 DWORD flags
/* [in] determines interpretation of lpSrc */)
1662 case TCI_SRCFONTSIG
:
1663 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
1665 case TCI_SRCCODEPAGE
:
1666 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
1668 case TCI_SRCCHARSET
:
1669 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
1674 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
1675 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
1690 DWORD Ret
= GDI_ERROR
;
1693 if (GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_DC
)
1695 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_METADC
)
1696 return MFDRV_SetMapperFlags( hDC
, flags
);
1699 PLDC pLDC
= Dc_Attr
->pvLDC
;
1702 SetLastError(ERROR_INVALID_HANDLE
);
1705 if (pLDC
->iType
== LDC_EMFLDC
)
1707 return EMFDRV_SetMapperFlags( hDC
, flags
);
1712 if (!GdiGetHandleUserData((HGDIOBJ
) hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
) &Dc_Attr
)) return GDI_ERROR
;
1714 if (NtCurrentTeb()->GdiTebBatch
.HDC
== (ULONG
)hDC
)
1716 if (Dc_Attr
->ulDirty_
& DC_FONTTEXT_DIRTY
)
1719 Dc_Attr
->ulDirty_
&= ~(DC_MODE_DIRTY
|DC_FONTTEXT_DIRTY
);
1724 SetLastError(ERROR_INVALID_PARAMETER
);
1727 Ret
= Dc_Attr
->flFontMapper
;
1728 Dc_Attr
->flFontMapper
= flags
;
1742 FONTENUMPROCW FontFunc
,
1747 return NtGdiEnumFonts ( hDC
, lpFaceName
, FontFunc
, lParam
);
1749 return EnumFontFamiliesW( hDC
, lpFaceName
, FontFunc
, lParam
);
1761 FONTENUMPROCA FontFunc
,
1770 Status
= HEAP_strdupA2W ( &lpFaceNameW
, lpFaceName
);
1771 if (!NT_SUCCESS (Status
))
1772 SetLastError (RtlNtStatusToDosError(Status
));
1775 rc
= NtGdiEnumFonts ( hDC
, lpFaceNameW
, FontFunc
, lParam
);
1777 HEAP_free ( lpFaceNameW
);
1781 return EnumFontFamiliesA( hDC
, lpFaceName
, FontFunc
, lParam
);
1785 #define EfdFontFamilies 3
1789 NewEnumFontFamiliesExW(
1791 LPLOGFONTW lpLogfont
,
1792 FONTENUMPROCW lpEnumFontFamExProcW
,
1796 ULONG_PTR idEnum
, cbDataSize
, cbRetSize
;
1797 PENUMFONTDATAW pEfdw
;
1802 /* Open enumeration handle and find out how much memory we need */
1803 idEnum
= NtGdiEnumFontOpen(hDC
,
1807 (lpLogfont
&& lpLogfont
->lfFaceName
[0])? lpLogfont
->lfFaceName
: NULL
,
1808 lpLogfont
? lpLogfont
->lfCharSet
: DEFAULT_CHARSET
,
1814 if (cbDataSize
== 0)
1816 NtGdiEnumFontClose(idEnum
);
1820 /* Allocate memory */
1821 pBuffer
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
1822 if (pBuffer
== NULL
)
1824 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1825 NtGdiEnumFontClose(idEnum
);
1829 /* Do the enumeration */
1830 if (!NtGdiEnumFontChunk(hDC
, idEnum
, cbDataSize
, &cbRetSize
, (PVOID
)pBuffer
))
1832 HeapFree(GetProcessHeap(), 0, pBuffer
);
1833 NtGdiEnumFontClose(idEnum
);
1837 /* Get start and end address */
1838 pEfdw
= (PENUMFONTDATAW
)pBuffer
;
1839 pMax
= pBuffer
+ cbDataSize
;
1841 /* Iterate through the structures */
1842 while ((PBYTE
)pEfdw
< pMax
&& ret
)
1844 PNTMW_INTERNAL pNtmwi
= (PNTMW_INTERNAL
)((ULONG_PTR
)pEfdw
+ pEfdw
->ulNtmwiOffset
);
1846 ret
= lpEnumFontFamExProcW(&pEfdw
->elfexdv
.elfEnumLogfontEx
,
1851 pEfdw
= (PENUMFONTDATAW
)((ULONG_PTR
)pEfdw
+ pEfdw
->cbSize
);
1854 /* Release the memory and close handle */
1855 HeapFree(GetProcessHeap(), 0, pBuffer
);
1856 NtGdiEnumFontClose(idEnum
);