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 MAXTCIINDEX 32
20 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
22 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
23 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
24 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
25 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
26 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
27 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
28 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
29 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
30 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
31 /* reserved by ANSI */
32 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
33 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
34 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
35 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
36 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
37 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
38 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
40 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
41 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
42 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
43 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
44 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
45 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
46 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
52 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
53 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
54 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
55 /* reserved for system */
56 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
57 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
60 #define INITIAL_FAMILY_COUNT 64
62 /***********************************************************************
63 * TEXTMETRIC conversion functions.
65 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
67 ptmA
->tmHeight
= ptmW
->tmHeight
;
68 ptmA
->tmAscent
= ptmW
->tmAscent
;
69 ptmA
->tmDescent
= ptmW
->tmDescent
;
70 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
71 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
72 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
73 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
74 ptmA
->tmWeight
= ptmW
->tmWeight
;
75 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
76 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
77 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
78 ptmA
->tmFirstChar
= ptmW
->tmFirstChar
> 255 ? 255 : ptmW
->tmFirstChar
;
79 ptmA
->tmLastChar
= ptmW
->tmLastChar
> 255 ? 255 : ptmW
->tmLastChar
;
80 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
> 255 ? 255 : ptmW
->tmDefaultChar
;
81 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
> 255 ? 255 : ptmW
->tmBreakChar
;
82 ptmA
->tmItalic
= ptmW
->tmItalic
;
83 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
84 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
85 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
86 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
89 /***********************************************************************
92 * Returns a Unicode translation of str using the charset of the
93 * currently selected font in hdc. If count is -1 then str is assumed
94 * to be '\0' terminated, otherwise it contains the number of bytes to
95 * convert. If plenW is non-NULL, on return it will point to the
96 * number of WCHARs that have been written. If pCP is non-NULL, on
97 * return it will point to the codepage used in the conversion. The
98 * caller should free the returned LPWSTR from the process heap
101 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
103 UINT cp
= GdiGetCodePage( hdc
);
107 if(count
== -1) count
= strlen(str
);
108 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
109 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
110 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
111 DPRINT("mapped %s -> %S\n", str
, strW
);
112 if(plenW
) *plenW
= lenW
;
119 MetricsCharConvert(WCHAR w
, UCHAR
*b
)
121 UNICODE_STRING WString
;
135 RtlInitUnicodeString(&WString
, WBuf
);
138 RtlInitAnsiString(&AString
, ABuf
);
140 Status
= RtlUnicodeStringToAnsiString(&AString
, &WString
, FALSE
);
141 if (! NT_SUCCESS(Status
))
143 SetLastError(RtlNtStatusToDosError(Status
));
153 TextMetricW2A(TEXTMETRICA
*tma
, TEXTMETRICW
*tmw
)
155 UNICODE_STRING WString
;
162 tma
->tmHeight
= tmw
->tmHeight
;
163 tma
->tmAscent
= tmw
->tmAscent
;
164 tma
->tmDescent
= tmw
->tmDescent
;
165 tma
->tmInternalLeading
= tmw
->tmInternalLeading
;
166 tma
->tmExternalLeading
= tmw
->tmExternalLeading
;
167 tma
->tmAveCharWidth
= tmw
->tmAveCharWidth
;
168 tma
->tmMaxCharWidth
= tmw
->tmMaxCharWidth
;
169 tma
->tmWeight
= tmw
->tmWeight
;
170 tma
->tmOverhang
= tmw
->tmOverhang
;
171 tma
->tmDigitizedAspectX
= tmw
->tmDigitizedAspectX
;
172 tma
->tmDigitizedAspectY
= tmw
->tmDigitizedAspectY
;
174 /* The Unicode FirstChar/LastChar need not correspond to the ANSI
175 FirstChar/LastChar. For example, if the font contains glyphs for
176 letters A-Z and an accented version of the letter e, the Unicode
177 FirstChar would be A and the Unicode LastChar would be the accented
178 e. If you just translate those to ANSI, the range would become
179 letters A-E instead of A-Z.
180 We translate all possible ANSI chars to Unicode and find the first
181 and last translated character which fall into the Unicode FirstChar/
182 LastChar range and return the corresponding ANSI char. */
184 /* Setup an Ansi string containing all possible letters (note: skip '\0' at
185 the beginning since that would be interpreted as end-of-string, handle
186 '\0' special later */
187 for (Letter
= 1; Letter
< 256; Letter
++)
189 ABuf
[Letter
- 1] = (CHAR
) Letter
;
190 WBuf
[Letter
- 1] = L
' ';
194 RtlInitAnsiString(&AString
, ABuf
);
195 RtlInitUnicodeString(&WString
, WBuf
);
197 /* Find the corresponding Unicode characters */
198 Status
= RtlAnsiStringToUnicodeString(&WString
, &AString
, FALSE
);
199 if (! NT_SUCCESS(Status
))
201 SetLastError(RtlNtStatusToDosError(Status
));
205 /* Scan for the first ANSI character which maps to an Unicode character
207 tma
->tmFirstChar
= '\0';
208 if (L
'\0' != tmw
->tmFirstChar
)
210 for (Letter
= 1; Letter
< 256; Letter
++)
212 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
213 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
215 tma
->tmFirstChar
= (CHAR
) Letter
;
221 /* Scan for the last ANSI character which maps to an Unicode character
223 tma
->tmLastChar
= '\0';
224 if (L
'\0' != tmw
->tmLastChar
)
226 for (Letter
= 255; 0 < Letter
; Letter
--)
228 if (tmw
->tmFirstChar
<= WBuf
[Letter
- 1] &&
229 WBuf
[Letter
- 1] <= tmw
->tmLastChar
)
231 tma
->tmLastChar
= (CHAR
) Letter
;
237 if (! MetricsCharConvert(tmw
->tmDefaultChar
, &tma
->tmDefaultChar
) ||
238 ! MetricsCharConvert(tmw
->tmBreakChar
, &tma
->tmBreakChar
))
243 tma
->tmItalic
= tmw
->tmItalic
;
244 tma
->tmUnderlined
= tmw
->tmUnderlined
;
245 tma
->tmStruckOut
= tmw
->tmStruckOut
;
246 tma
->tmPitchAndFamily
= tmw
->tmPitchAndFamily
;
247 tma
->tmCharSet
= tmw
->tmCharSet
;
253 NewTextMetricW2A(NEWTEXTMETRICA
*tma
, NEWTEXTMETRICW
*tmw
)
255 if (! TextMetricW2A((TEXTMETRICA
*) tma
, (TEXTMETRICW
*) tmw
))
260 tma
->ntmFlags
= tmw
->ntmFlags
;
261 tma
->ntmSizeEM
= tmw
->ntmSizeEM
;
262 tma
->ntmCellHeight
= tmw
->ntmCellHeight
;
263 tma
->ntmAvgWidth
= tmw
->ntmAvgWidth
;
269 NewTextMetricExW2A(NEWTEXTMETRICEXA
*tma
, NEWTEXTMETRICEXW
*tmw
)
271 if (! NewTextMetricW2A(&tma
->ntmTm
, &tmw
->ntmTm
))
276 tma
->ntmFontSig
= tmw
->ntmFontSig
;
282 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
287 PFONTFAMILYINFO Info
;
290 ENUMLOGFONTEXA EnumLogFontExA
;
291 NEWTEXTMETRICEXA NewTextMetricExA
;
293 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
294 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
299 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
300 if (FontFamilyCount
< 0)
302 RtlFreeHeap(GetProcessHeap(), 0, Info
);
305 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
307 FontFamilySize
= FontFamilyCount
;
308 RtlFreeHeap(GetProcessHeap(), 0, Info
);
309 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
310 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
315 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
316 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
318 RtlFreeHeap(GetProcessHeap(), 0, Info
);
323 for (i
= 0; i
< FontFamilyCount
; i
++)
327 Ret
= ((FONTENUMPROCW
) EnumProc
)(
328 (VOID
*)&Info
[i
].EnumLogFontEx
,
329 (VOID
*)&Info
[i
].NewTextMetricEx
,
330 Info
[i
].FontType
, lParam
);
333 { // Could use EnumLogFontExW2A here?
334 LogFontW2A(&EnumLogFontExA
.elfLogFont
, &Info
[i
].EnumLogFontEx
.elfLogFont
);
335 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfFullName
, -1,
336 (LPSTR
)EnumLogFontExA
.elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
337 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfStyle
, -1,
338 (LPSTR
)EnumLogFontExA
.elfStyle
, LF_FACESIZE
, NULL
, NULL
);
339 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfScript
, -1,
340 (LPSTR
)EnumLogFontExA
.elfScript
, LF_FACESIZE
, NULL
, NULL
);
341 NewTextMetricExW2A(&NewTextMetricExA
,
342 &Info
[i
].NewTextMetricEx
);
343 Ret
= ((FONTENUMPROCA
) EnumProc
)(
344 (VOID
*)&EnumLogFontExA
,
345 (VOID
*)&NewTextMetricExA
,
346 Info
[i
].FontType
, lParam
);
350 RtlFreeHeap(GetProcessHeap(), 0, Info
);
359 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
360 LPARAM lParam
, DWORD dwFlags
)
362 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
, TRUE
);
370 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
375 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
376 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
377 if (NULL
!= lpszFamily
)
379 if (!*lpszFamily
) return 1;
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
)
394 LOGFONTW LogFontW
, *pLogFontW
;
398 LogFontA2W(&LogFontW
,lpLogfont
);
399 pLogFontW
= &LogFontW
;
401 else pLogFontW
= NULL
;
403 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
404 return IntEnumFontFamilies(hdc
, pLogFontW
, lpEnumFontFamExProc
, lParam
, FALSE
);
412 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
417 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
418 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
419 if (NULL
!= lpszFamily
)
421 if (!*lpszFamily
) return 1;
422 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
425 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, FALSE
);
433 GetCharacterPlacementW(
438 GCP_RESULTSW
*lpResults
,
445 DPRINT("GetCharacterPlacementW\n");
447 if(dwFlags
&(~GCP_REORDER
)) DPRINT("flags 0x%08lx ignored\n", dwFlags
);
448 if(lpResults
->lpClass
) DPRINT("classes not implemented\n");
449 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
450 DPRINT("Caret positions for complex scripts not implemented\n");
453 if(nSet
> lpResults
->nGlyphs
)
454 nSet
= lpResults
->nGlyphs
;
456 /* return number of initialized fields */
457 lpResults
->nGlyphs
= nSet
;
459 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
461 /* Treat the case where no special handling was requested in a fastpath way */
462 /* copy will do if the GCP_REORDER flag is not set */
463 if(lpResults
->lpOutString
)
464 lstrcpynW( lpResults
->lpOutString
, lpString
, nSet
);
466 if(lpResults
->lpGlyphs
)
467 lstrcpynW( lpResults
->lpGlyphs
, lpString
, nSet
);
469 if(lpResults
->lpOrder
)
471 for(i
= 0; i
< nSet
; i
++)
472 lpResults
->lpOrder
[i
] = i
;
476 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
477 nSet, lpResults->lpOrder );
480 /* FIXME: Will use the placement chars */
484 for (i
= 0; i
< nSet
; i
++)
486 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
487 lpResults
->lpDx
[i
]= c
;
491 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
495 lpResults
->lpCaretPos
[0] = 0;
496 for (i
= 1; i
< nSet
; i
++)
497 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
498 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
501 /*if(lpResults->lpGlyphs)
502 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
504 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
505 ret
= MAKELONG(size
.cx
, size
.cy
);
516 GetCharABCWidthsFloatW(HDC hdc
,
521 DPRINT("GetCharABCWidthsFloatW\n");
522 if ((!abcF
) || (FirstChar
> LastChar
))
524 SetLastError(ERROR_INVALID_PARAMETER
);
527 return NtGdiGetCharABCWidthsW( hdc
,
529 (ULONG
)(LastChar
- FirstChar
+ 1),
541 GetCharWidthFloatW(HDC hdc
,
546 DPRINT("GetCharWidthsFloatW\n");
547 if ((!pxBuffer
) || (iFirstChar
> iLastChar
))
549 SetLastError(ERROR_INVALID_PARAMETER
);
552 return NtGdiGetCharWidthW( hdc
,
554 (ULONG
)(iLastChar
- iFirstChar
+ 1),
566 GetCharWidthW(HDC hdc
,
571 DPRINT("GetCharWidthsW\n");
572 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
574 SetLastError(ERROR_INVALID_PARAMETER
);
577 return NtGdiGetCharWidthW( hdc
,
579 (ULONG
)(iLastChar
- iFirstChar
+ 1),
591 GetCharWidth32W(HDC hdc
,
596 DPRINT("GetCharWidths32W\n");
597 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
599 SetLastError(ERROR_INVALID_PARAMETER
);
602 return NtGdiGetCharWidthW( hdc
,
604 (ULONG
)(iLastChar
- iFirstChar
+ 1),
606 GCW_NOFLOAT
|GCW_WIN32
,
617 GetCharABCWidthsW(HDC hdc
,
622 DPRINT("GetCharABCWidthsW\n");
623 if ((!lpabc
) || (FirstChar
> LastChar
))
625 SetLastError(ERROR_INVALID_PARAMETER
);
628 return NtGdiGetCharABCWidthsW( hdc
,
630 (ULONG
)(LastChar
- FirstChar
+ 1),
648 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
653 DPRINT("GetCharWidthsA\n");
654 if(count
<= 0) return FALSE
;
656 str
= HeapAlloc(GetProcessHeap(), 0, count
+1);
660 for(i
= 0; i
< count
; i
++)
661 str
[i
] = (BYTE
)(iFirstChar
+ i
);
664 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
667 HeapFree(GetProcessHeap(), 0, str
);
671 ret
= NtGdiGetCharWidthW( hdc
,
678 HeapFree(GetProcessHeap(), 0, str
);
679 HeapFree(GetProcessHeap(), 0, wstr
);
696 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
701 DPRINT("GetCharWidths32A\n");
702 if(count
<= 0) return FALSE
;
704 str
= HeapAlloc(GetProcessHeap(), 0, count
+1);
707 for(i
= 0; i
< count
; i
++)
708 str
[i
] = (BYTE
)(iFirstChar
+ i
);
711 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
714 HeapFree(GetProcessHeap(), 0, str
);
718 ret
= NtGdiGetCharWidthW( hdc
,
722 GCW_NOFLOAT
|GCW_WIN32
,
725 HeapFree(GetProcessHeap(), 0, str
);
726 HeapFree(GetProcessHeap(), 0, wstr
);
743 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
748 DPRINT("GetCharWidthsFloatA\n");
749 if(count
<= 0) return FALSE
;
751 str
= HeapAlloc(GetProcessHeap(), 0, count
+1);
754 for(i
= 0; i
< count
; i
++)
755 str
[i
] = (BYTE
)(iFirstChar
+ i
);
758 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
761 HeapFree(GetProcessHeap(), 0, str
);
764 ret
= NtGdiGetCharWidthW( hdc
, wstr
[0], (ULONG
) count
, (PWCHAR
) wstr
, 0, (PVOID
) pxBuffer
);
766 HeapFree(GetProcessHeap(), 0, str
);
767 HeapFree(GetProcessHeap(), 0, wstr
);
784 INT i
, wlen
, count
= (INT
)(uLastChar
- uFirstChar
+ 1);
789 DPRINT("GetCharABCWidthsA\n");
790 if(count
<= 0) return FALSE
;
792 str
= HeapAlloc(GetProcessHeap(), 0, count
+1);
795 for(i
= 0; i
< count
; i
++)
796 str
[i
] = (BYTE
)(uFirstChar
+ i
);
799 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
802 HeapFree(GetProcessHeap(), 0, str
);
806 ret
= NtGdiGetCharABCWidthsW( hdc
,
813 HeapFree(GetProcessHeap(), 0, str
);
814 HeapFree(GetProcessHeap(), 0, wstr
);
824 GetCharABCWidthsFloatA(
831 INT i
, wlen
, count
= (INT
)(iLastChar
- iFirstChar
+ 1);
836 DPRINT("GetCharABCWidthsFloatA\n");
837 if (count
<= 0) return FALSE
;
839 str
= HeapAlloc(GetProcessHeap(), 0, count
+1);
843 for(i
= 0; i
< count
; i
++)
844 str
[i
] = (BYTE
)(iFirstChar
+ i
);
847 wstr
= FONT_mbtowc( hdc
, str
, count
+1, &wlen
, NULL
);
850 HeapFree( GetProcessHeap(), 0, str
);
853 ret
= NtGdiGetCharABCWidthsW( hdc
,wstr
[0],(ULONG
)count
, (PWCHAR
)wstr
, 0, (PVOID
)lpABCF
);
855 HeapFree( GetProcessHeap(), 0, str
);
856 HeapFree( GetProcessHeap(), 0, wstr
);
866 GetCharABCWidthsI(HDC hdc
,
872 DPRINT("GetCharABCWidthsI\n");
873 return NtGdiGetCharABCWidthsW( hdc
,
877 GCABCW_NOFLOAT
|GCABCW_INDICES
,
886 GetCharWidthI(HDC hdc
,
893 DPRINT("GetCharWidthsI\n");
894 if (!lpBuffer
|| (!pgi
&& (giFirst
== MAXUSHORT
))) // Cannot be at max.
896 SetLastError(ERROR_INVALID_PARAMETER
);
899 if (!cgi
) return TRUE
;
900 return NtGdiGetCharWidthW( hdc
,
904 GCW_INDICES
|GCW_NOFLOAT
|GCW_WIN32
,
917 DWORD Gcp
= 0, Ret
= 0;
920 Ret
= NtGdiGetTextCharsetInfo(hDc
, NULL
, 0);
921 if ((Ret
== ARABIC_CHARSET
) || (Ret
== HEBREW_CHARSET
))
922 Ret
= (GCP_KASHIDA
|GCP_DIACRITIC
|GCP_LIGATE
|GCP_GLYPHSHAPE
|GCP_REORDER
);
924 Gcp
= GetDCDWord(hDc
, GdiGetFontLanguageInfo
, GCP_ERROR
);
925 if ( Gcp
== GCP_ERROR
)
949 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
950 Ret
= NtGdiGetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
951 HeapFree(GetProcessHeap(), 0, lpstrW
);
974 DPRINT1("GetGlyphOutlineA uChar %x\n", uChar
);
975 if(!(uFormat
& GGO_GLYPH_INDEX
)) {
978 if(uChar
> 0xff) { /* but, 2 bytes character only */
980 mbchs
[0] = (uChar
& 0xff00) >> 8;
981 mbchs
[1] = (uChar
& 0xff);
984 mbchs
[0] = (uChar
& 0xff);
986 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
990 ret
= NtGdiGetGlyphOutline(hdc
, c
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
991 HeapFree(GetProcessHeap(), 0, p
);
1005 LPGLYPHMETRICS lpgm
,
1011 DPRINT("GetGlyphOutlineW uChar %x\n", uChar
);
1012 if (!lpgm
& !lpmat2
) return GDI_ERROR
;
1013 if (!lpvBuffer
) cbBuffer
= 0;
1014 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1023 GetOutlineTextMetricsA(
1026 LPOUTLINETEXTMETRICA lpOTM
1029 char buf
[512], *ptr
;
1031 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1032 OUTLINETEXTMETRICA
*output
= lpOTM
;
1035 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1037 if(ret
> sizeof(buf
))
1038 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1039 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1041 needed
= sizeof(OUTLINETEXTMETRICA
);
1042 if(lpOTMW
->otmpFamilyName
)
1043 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1044 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFamilyName
), -1,
1045 NULL
, 0, NULL
, NULL
);
1046 if(lpOTMW
->otmpFaceName
)
1047 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1048 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFaceName
), -1,
1049 NULL
, 0, NULL
, NULL
);
1050 if(lpOTMW
->otmpStyleName
)
1051 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1052 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpStyleName
), -1,
1053 NULL
, 0, NULL
, NULL
);
1054 if(lpOTMW
->otmpFullName
)
1055 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1056 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFullName
), -1,
1057 NULL
, 0, NULL
, NULL
);
1064 DPRINT("needed = %d\n", needed
);
1066 /* Since the supplied buffer isn't big enough, we'll alloc one
1067 that is and memcpy the first cbData bytes into the lpOTM at
1069 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1071 ret
= output
->otmSize
= min(needed
, cbData
);
1072 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1073 output
->otmFiller
= 0;
1074 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1075 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1076 output
->otmfsType
= lpOTMW
->otmfsType
;
1077 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1078 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1079 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1080 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1081 output
->otmAscent
= lpOTMW
->otmAscent
;
1082 output
->otmDescent
= lpOTMW
->otmDescent
;
1083 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1084 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1085 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1086 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1087 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1088 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1089 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1090 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1091 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1092 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1093 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1094 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1095 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1096 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1097 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1098 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1101 ptr
= (char*)(output
+ 1);
1102 left
= needed
- sizeof(*output
);
1104 if(lpOTMW
->otmpFamilyName
) {
1105 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1106 len
= WideCharToMultiByte(CP_ACP
, 0,
1107 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFamilyName
), -1,
1108 ptr
, left
, NULL
, NULL
);
1112 output
->otmpFamilyName
= 0;
1114 if(lpOTMW
->otmpFaceName
) {
1115 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1116 len
= WideCharToMultiByte(CP_ACP
, 0,
1117 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFaceName
), -1,
1118 ptr
, left
, NULL
, NULL
);
1122 output
->otmpFaceName
= 0;
1124 if(lpOTMW
->otmpStyleName
) {
1125 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1126 len
= WideCharToMultiByte(CP_ACP
, 0,
1127 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpStyleName
), -1,
1128 ptr
, left
, NULL
, NULL
);
1132 output
->otmpStyleName
= 0;
1134 if(lpOTMW
->otmpFullName
) {
1135 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1136 len
= WideCharToMultiByte(CP_ACP
, 0,
1137 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFullName
), -1,
1138 ptr
, left
, NULL
, NULL
);
1141 output
->otmpFullName
= 0;
1145 if(output
!= lpOTM
) {
1146 memcpy(lpOTM
, output
, cbData
);
1147 HeapFree(GetProcessHeap(), 0, output
);
1149 /* check if the string offsets really fit into the provided size */
1150 /* FIXME: should we check string length as well? */
1151 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1152 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1154 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1155 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1157 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1158 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1160 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1161 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1165 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1166 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1177 GetOutlineTextMetricsW(
1180 LPOUTLINETEXTMETRICW lpOTM
1183 TMDIFF Tmd
; // Should not be zero.
1185 return NtGdiGetOutlineTextMetricsInternalW(hdc
, cbData
, lpOTM
, &Tmd
);
1193 GetKerningPairsW(HDC hdc
,
1195 LPKERNINGPAIR pkpDst
)
1197 if ((cPairs
!= 0) || (pkpDst
== 0))
1199 return NtGdiGetKerningPairs(hdc
,cPairs
,pkpDst
);
1203 SetLastError(ERROR_INVALID_PARAMETER
);
1213 GetKerningPairsA( HDC hDC
,
1215 LPKERNINGPAIR kern_pairA
)
1220 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
1221 KERNINGPAIR
*kern_pairW
;
1223 if (!cPairs
&& kern_pairA
)
1225 SetLastError(ERROR_INVALID_PARAMETER
);
1229 charset
= GetTextCharset(hDC
);
1230 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
1232 DPRINT1("Can't find codepage for charset %d\n", charset
);
1235 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1236 * to fail on an invalid character for CP_SYMBOL.
1238 cpi
.DefaultChar
[0] = 0;
1239 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
1241 DPRINT1("Can't find codepage %u info\n", csi
.ciACP
);
1244 DPRINT("charset %d => codepage %u\n", charset
, csi
.ciACP
);
1246 total_kern_pairs
= NtGdiGetKerningPairs(hDC
, 0, NULL
);
1247 if (!total_kern_pairs
) return 0;
1249 if (!cPairs
&& !kern_pairA
) return total_kern_pairs
;
1251 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
1252 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
1254 for (i
= 0; i
< total_kern_pairs
; i
++)
1258 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
1261 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
1264 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
1269 if (kern_pairs_copied
>= cPairs
) break;
1271 kern_pairA
->wFirst
= (BYTE
)first
;
1272 kern_pairA
->wSecond
= (BYTE
)second
;
1273 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
1276 kern_pairs_copied
++;
1279 HeapFree(GetProcessHeap(), 0, kern_pairW
);
1281 return kern_pairs_copied
;
1291 CreateFontIndirectExA(const ENUMLOGFONTEXDVA
*elfexd
)
1295 ENUMLOGFONTEXDVW Logfont
;
1297 EnumLogFontExW2A( (LPENUMLOGFONTEXA
) elfexd
,
1298 &Logfont
.elfEnumLogfontEx
);
1300 RtlCopyMemory( &Logfont
.elfDesignVector
,
1301 (PVOID
) &elfexd
->elfDesignVector
,
1302 sizeof(DESIGNVECTOR
));
1304 return NtGdiHfontCreate( &Logfont
, 0, 0, 0, NULL
);
1315 CreateFontIndirectExW(const ENUMLOGFONTEXDVW
*elfexd
)
1317 /* Msdn: Note, this function ignores the elfDesignVector member in
1322 return NtGdiHfontCreate((PENUMLOGFONTEXDVW
) elfexd
, 0, 0, 0, NULL
);
1333 CreateFontIndirectA(
1334 CONST LOGFONTA
*lplf
1341 LogFontA2W(&tlf
, lplf
);
1342 return CreateFontIndirectW(&tlf
);
1353 CreateFontIndirectW(
1354 CONST LOGFONTW
*lplf
1359 ENUMLOGFONTEXDVW Logfont
;
1361 RtlCopyMemory( &Logfont
.elfEnumLogfontEx
.elfLogFont
, lplf
, sizeof(LOGFONTW
));
1362 // Need something other than just cleaning memory here.
1363 // Guess? Use caller data to determine the rest.
1364 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfFullName
,
1365 sizeof(Logfont
.elfEnumLogfontEx
.elfFullName
));
1366 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfStyle
,
1367 sizeof(Logfont
.elfEnumLogfontEx
.elfStyle
));
1368 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfScript
,
1369 sizeof(Logfont
.elfEnumLogfontEx
.elfScript
));
1371 Logfont
.elfDesignVector
.dvNumAxes
= 0; // No more than MM_MAX_NUMAXES
1373 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
1375 return CreateFontIndirectExW(&Logfont
);
1396 DWORD fdwOutputPrecision
,
1397 DWORD fdwClipPrecision
,
1399 DWORD fdwPitchAndFamily
,
1403 ANSI_STRING StringA
;
1404 UNICODE_STRING StringU
;
1407 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
1408 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
1410 ret
= CreateFontW(nHeight
,
1425 RtlFreeUnicodeString(&StringU
);
1446 DWORD fdwOutputPrecision
,
1447 DWORD fdwClipPrecision
,
1449 DWORD fdwPitchAndFamily
,
1455 logfont
.lfHeight
= nHeight
;
1456 logfont
.lfWidth
= nWidth
;
1457 logfont
.lfEscapement
= nEscapement
;
1458 logfont
.lfOrientation
= nOrientation
;
1459 logfont
.lfWeight
= nWeight
;
1460 logfont
.lfItalic
= fnItalic
;
1461 logfont
.lfUnderline
= fdwUnderline
;
1462 logfont
.lfStrikeOut
= fdwStrikeOut
;
1463 logfont
.lfCharSet
= fdwCharSet
;
1464 logfont
.lfOutPrecision
= fdwOutputPrecision
;
1465 logfont
.lfClipPrecision
= fdwClipPrecision
;
1466 logfont
.lfQuality
= fdwQuality
;
1467 logfont
.lfPitchAndFamily
= fdwPitchAndFamily
;
1469 if (NULL
!= lpszFace
)
1471 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
1472 wcsncpy((wchar_t *)logfont
.lfFaceName
, lpszFace
, Size
- 1);
1473 /* Be 101% sure to have '\0' at end of string */
1474 logfont
.lfFaceName
[Size
- 1] = '\0';
1478 logfont
.lfFaceName
[0] = L
'\0';
1481 return CreateFontIndirectW(&logfont
);
1490 CreateScalableFontResourceA(
1493 LPCSTR lpszFontFile
,
1494 LPCSTR lpszCurrentPath
1506 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1508 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1510 SetLastError( ERROR_INVALID_PARAMETER
);
1514 return GdiAddFontResourceW(lpszFilename
, fl
,0);
1523 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1529 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1531 SetLastError( ERROR_INVALID_PARAMETER
);
1535 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1536 if ( !NT_SUCCESS (Status
) )
1538 SetLastError (RtlNtStatusToDosError(Status
));
1542 rc
= GdiAddFontResourceW ( FilenameW
, fl
, 0 );
1543 HEAP_free ( FilenameW
);
1553 AddFontResourceA ( LPCSTR lpszFilename
)
1559 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1560 if ( !NT_SUCCESS (Status
) )
1562 SetLastError (RtlNtStatusToDosError(Status
));
1566 rc
= GdiAddFontResourceW ( FilenameW
, 0, 0);
1568 HEAP_free ( FilenameW
);
1579 AddFontResourceW ( LPCWSTR lpszFilename
)
1581 return GdiAddFontResourceW ( lpszFilename
, 0, 0 );
1590 RemoveFontResourceW(LPCWSTR lpFileName
)
1592 return RemoveFontResourceExW(lpFileName
,0,0);
1601 RemoveFontResourceA(LPCSTR lpFileName
)
1603 return RemoveFontResourceExA(lpFileName
,0,0);
1611 RemoveFontResourceExA(LPCSTR lpFileName
,
1619 /* FIXME the flags */
1621 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1623 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
1624 if (!NT_SUCCESS (Status
))
1625 SetLastError (RtlNtStatusToDosError(Status
));
1629 HEAP_free ( lpFileNameW
);
1640 RemoveFontResourceExW(LPCWSTR lpFileName
,
1644 /* FIXME the flags */
1646 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1651 /***********************************************************************
1652 * GdiGetCharDimensions
1654 * Gets the average width of the characters in the English alphabet.
1657 * hdc [I] Handle to the device context to measure on.
1658 * lptm [O] Pointer to memory to store the text metrics into.
1659 * height [O] On exit, the maximum height of characters in the English alphabet.
1662 * The average width of characters in the English alphabet.
1665 * This function is used by the dialog manager to get the size of a dialog
1666 * unit. It should also be used by other pieces of code that need to know
1667 * the size of a dialog unit in logical units without having access to the
1668 * window handle of the dialog.
1669 * Windows caches the font metrics from this function, but we don't and
1670 * there doesn't appear to be an immediate advantage to do so.
1673 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1675 * Despite most of MSDN insisting that the horizontal base unit is
1676 * tmAveCharWidth it isn't. Knowledge base article Q145994
1677 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1678 * says that we should take the average of the 52 English upper and lower
1686 GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
1690 static const WCHAR alphabet
[] = {
1691 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1692 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1693 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
1695 if(!GetTextMetricsW(hdc
, &tm
)) return 0;
1697 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
1699 if (lptm
) *lptm
= tm
;
1700 if (height
) *height
= tm
.tmHeight
;
1702 return (sz
.cx
/ 26 + 1) / 2;
1705 /*************************************************************************
1706 * TranslateCharsetInfo [GDI32.@]
1708 * Fills a CHARSETINFO structure for a character set, code page, or
1709 * font. This allows making the correspondance between different labelings
1710 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1711 * of the same encoding.
1713 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1714 * only one codepage should be set in *lpSrc.
1717 * TRUE on success, FALSE on failure.
1725 TranslateCharsetInfo(
1726 LPDWORD lpSrc
, /* [in]
1727 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1728 if flags == TCI_SRCCHARSET: a character set value
1729 if flags == TCI_SRCCODEPAGE: a code page value
1731 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
1732 DWORD flags
/* [in] determines interpretation of lpSrc */)
1736 case TCI_SRCFONTSIG
:
1737 while (!(*lpSrc
>>index
& 0x0001) && index
<MAXTCIINDEX
) index
++;
1739 case TCI_SRCCODEPAGE
:
1740 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
&& index
< MAXTCIINDEX
) index
++;
1742 case TCI_SRCCHARSET
:
1743 while (PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
&& index
< MAXTCIINDEX
) index
++;
1748 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
1749 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
1764 DWORD Ret
= GDI_ERROR
;
1767 if (GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_DC
)
1769 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_METADC
)
1770 return MFDRV_SetMapperFlags( hDC
, flags
);
1773 PLDC pLDC
= Dc_Attr
->pvLDC
;
1776 SetLastError(ERROR_INVALID_HANDLE
);
1779 if (pLDC
->iType
== LDC_EMFLDC
)
1781 return EMFDRV_SetMapperFlags( hDC
, flags
);
1786 if (!GdiGetHandleUserData((HGDIOBJ
) hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
) &Dc_Attr
)) return GDI_ERROR
;
1788 if (NtCurrentTeb()->GdiTebBatch
.HDC
== hDC
)
1790 if (Dc_Attr
->ulDirty_
& DC_FONTTEXT_DIRTY
)
1793 Dc_Attr
->ulDirty_
&= ~(DC_MODE_DIRTY
|DC_FONTTEXT_DIRTY
);
1798 SetLastError(ERROR_INVALID_PARAMETER
);
1801 Ret
= Dc_Attr
->flFontMapper
;
1802 Dc_Attr
->flFontMapper
= flags
;
1816 FONTENUMPROCW FontFunc
,
1821 return NtGdiEnumFonts ( hDC
, lpFaceName
, FontFunc
, lParam
);
1823 return EnumFontFamiliesW( hDC
, lpFaceName
, FontFunc
, lParam
);
1835 FONTENUMPROCA FontFunc
,
1844 Status
= HEAP_strdupA2W ( &lpFaceNameW
, lpFaceName
);
1845 if (!NT_SUCCESS (Status
))
1846 SetLastError (RtlNtStatusToDosError(Status
));
1849 rc
= NtGdiEnumFonts ( hDC
, lpFaceNameW
, FontFunc
, lParam
);
1851 HEAP_free ( lpFaceNameW
);
1855 return EnumFontFamiliesA( hDC
, lpFaceName
, FontFunc
, lParam
);
1859 #define EfdFontFamilies 3
1863 NewEnumFontFamiliesExW(
1865 LPLOGFONTW lpLogfont
,
1866 FONTENUMPROCW lpEnumFontFamExProcW
,
1870 ULONG_PTR idEnum
, cbDataSize
, cbRetSize
;
1871 PENUMFONTDATAW pEfdw
;
1876 /* Open enumeration handle and find out how much memory we need */
1877 idEnum
= NtGdiEnumFontOpen(hDC
,
1881 (lpLogfont
&& lpLogfont
->lfFaceName
[0])? lpLogfont
->lfFaceName
: NULL
,
1882 lpLogfont
? lpLogfont
->lfCharSet
: DEFAULT_CHARSET
,
1888 if (cbDataSize
== 0)
1890 NtGdiEnumFontClose(idEnum
);
1894 /* Allocate memory */
1895 pBuffer
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
1896 if (pBuffer
== NULL
)
1898 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1899 NtGdiEnumFontClose(idEnum
);
1903 /* Do the enumeration */
1904 if (!NtGdiEnumFontChunk(hDC
, idEnum
, cbDataSize
, &cbRetSize
, (PVOID
)pBuffer
))
1906 HeapFree(GetProcessHeap(), 0, pBuffer
);
1907 NtGdiEnumFontClose(idEnum
);
1911 /* Get start and end address */
1912 pEfdw
= (PENUMFONTDATAW
)pBuffer
;
1913 pMax
= pBuffer
+ cbDataSize
;
1915 /* Iterate through the structures */
1916 while ((PBYTE
)pEfdw
< pMax
&& ret
)
1918 PNTMW_INTERNAL pNtmwi
= (PNTMW_INTERNAL
)((ULONG_PTR
)pEfdw
+ pEfdw
->ulNtmwiOffset
);
1920 ret
= lpEnumFontFamExProcW((VOID
*)&pEfdw
->elfexdv
.elfEnumLogfontEx
,
1921 (VOID
*)&pNtmwi
->ntmw
,
1925 pEfdw
= (PENUMFONTDATAW
)((ULONG_PTR
)pEfdw
+ pEfdw
->cbSize
);
1928 /* Release the memory and close handle */
1929 HeapFree(GetProcessHeap(), 0, pBuffer
);
1930 NtGdiEnumFontClose(idEnum
);