2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/gdi32/object/font.c
16 * For TranslateCharsetInfo
18 #define MAXTCIINDEX 32
19 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.
67 FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
69 ptmA
->tmHeight
= ptmW
->tmHeight
;
70 ptmA
->tmAscent
= ptmW
->tmAscent
;
71 ptmA
->tmDescent
= ptmW
->tmDescent
;
72 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
73 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
74 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
75 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
76 ptmA
->tmWeight
= ptmW
->tmWeight
;
77 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
78 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
79 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
80 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
81 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
83 ptmA
->tmFirstChar
= 0x1e;
84 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
88 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
89 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
91 ptmA
->tmDefaultChar
= (CHAR
)ptmW
->tmDefaultChar
;
92 ptmA
->tmBreakChar
= (CHAR
)ptmW
->tmBreakChar
;
93 ptmA
->tmItalic
= ptmW
->tmItalic
;
94 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
95 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
96 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
97 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
100 /***********************************************************************
103 * Returns a Unicode translation of str using the charset of the
104 * currently selected font in hdc. If count is -1 then str is assumed
105 * to be '\0' terminated, otherwise it contains the number of bytes to
106 * convert. If plenW is non-NULL, on return it will point to the
107 * number of WCHARs that have been written. If pCP is non-NULL, on
108 * return it will point to the codepage used in the conversion. The
109 * caller should free the returned LPWSTR from the process heap
112 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
114 UINT cp
= GdiGetCodePage( hdc
);
118 if(count
== -1) count
= strlen(str
);
119 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
120 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
123 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
124 DPRINT("mapped %s -> %S\n", str
, strW
);
125 if(plenW
) *plenW
= lenW
;
130 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
132 INT i
, count
= lastChar
- firstChar
+ 1;
139 switch (GdiGetCodePage(hdc
))
146 if (lastChar
> 0xffff)
148 if ((firstChar
^ lastChar
) > 0xff)
157 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
161 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
164 str
[i
++] = (BYTE
)(c
>> 8);
175 NewTextMetricW2A(NEWTEXTMETRICA
*tma
, NEWTEXTMETRICW
*tmw
)
177 FONT_TextMetricWToA((TEXTMETRICW
*) tmw
, (TEXTMETRICA
*) tma
);
178 tma
->ntmFlags
= tmw
->ntmFlags
;
179 tma
->ntmSizeEM
= tmw
->ntmSizeEM
;
180 tma
->ntmCellHeight
= tmw
->ntmCellHeight
;
181 tma
->ntmAvgWidth
= tmw
->ntmAvgWidth
;
185 NewTextMetricExW2A(NEWTEXTMETRICEXA
*tma
, NEWTEXTMETRICEXW
*tmw
)
187 NewTextMetricW2A(&tma
->ntmTm
, &tmw
->ntmTm
);
188 tma
->ntmFontSig
= tmw
->ntmFontSig
;
192 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
197 PFONTFAMILYINFO Info
;
200 ENUMLOGFONTEXA EnumLogFontExA
;
201 NEWTEXTMETRICEXA NewTextMetricExA
;
204 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
205 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
213 lfW
.lfCharSet
= DEFAULT_CHARSET
;
214 lfW
.lfPitchAndFamily
= 0;
215 lfW
.lfFaceName
[0] = 0;
219 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
220 if (FontFamilyCount
< 0)
222 RtlFreeHeap(GetProcessHeap(), 0, Info
);
225 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
227 FontFamilySize
= FontFamilyCount
;
228 RtlFreeHeap(GetProcessHeap(), 0, Info
);
229 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
230 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
235 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
236 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
238 RtlFreeHeap(GetProcessHeap(), 0, Info
);
243 for (i
= 0; i
< FontFamilyCount
; i
++)
247 Ret
= ((FONTENUMPROCW
) EnumProc
)(
248 (VOID
*)&Info
[i
].EnumLogFontEx
,
249 (VOID
*)&Info
[i
].NewTextMetricEx
,
250 Info
[i
].FontType
, lParam
);
254 // Could use EnumLogFontExW2A here?
255 LogFontW2A(&EnumLogFontExA
.elfLogFont
, &Info
[i
].EnumLogFontEx
.elfLogFont
);
256 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfFullName
, -1,
257 (LPSTR
)EnumLogFontExA
.elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
258 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfStyle
, -1,
259 (LPSTR
)EnumLogFontExA
.elfStyle
, LF_FACESIZE
, NULL
, NULL
);
260 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfScript
, -1,
261 (LPSTR
)EnumLogFontExA
.elfScript
, LF_FACESIZE
, NULL
, NULL
);
262 NewTextMetricExW2A(&NewTextMetricExA
,
263 &Info
[i
].NewTextMetricEx
);
264 Ret
= ((FONTENUMPROCA
) EnumProc
)(
265 (VOID
*)&EnumLogFontExA
,
266 (VOID
*)&NewTextMetricExA
,
267 Info
[i
].FontType
, lParam
);
271 RtlFreeHeap(GetProcessHeap(), 0, Info
);
280 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
281 LPARAM lParam
, DWORD dwFlags
)
283 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
, TRUE
);
291 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
296 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
297 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
298 if (NULL
!= lpszFamily
)
300 if (!*lpszFamily
) return 1;
301 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
304 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, TRUE
);
312 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
313 LPARAM lParam
, DWORD dwFlags
)
315 LOGFONTW LogFontW
, *pLogFontW
;
319 LogFontA2W(&LogFontW
,lpLogfont
);
320 pLogFontW
= &LogFontW
;
322 else pLogFontW
= NULL
;
324 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
325 return IntEnumFontFamilies(hdc
, pLogFontW
, lpEnumFontFamExProc
, lParam
, FALSE
);
333 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
338 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
339 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
340 if (NULL
!= lpszFamily
)
342 if (!*lpszFamily
) return 1;
343 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
346 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, FALSE
);
355 GetCharacterPlacementA(
360 GCP_RESULTSA
*lpResults
,
365 GCP_RESULTSW resultsW
;
369 if ( !lpString
|| uCount
<= 0 || (nMaxExtent
< 0 && nMaxExtent
!= -1 ) )
371 SetLastError(ERROR_INVALID_PARAMETER
);
374 /* TRACE("%s, %d, %d, 0x%08x\n",
375 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
377 /* both structs are equal in size */
378 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
380 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
381 if (lpStringW
== NULL
)
385 if(lpResults
->lpOutString
)
387 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
388 if (resultsW
.lpOutString
== NULL
)
390 HeapFree(GetProcessHeap(), 0, lpStringW
);
395 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
397 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
398 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
400 if(lpResults
->lpOutString
)
402 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
403 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
406 HeapFree(GetProcessHeap(), 0, lpStringW
);
407 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
418 GetCharacterPlacementW(
423 GCP_RESULTSW
*lpResults
,
430 DPRINT("GetCharacterPlacementW\n");
432 if(dwFlags
&(~GCP_REORDER
)) DPRINT("flags 0x%08lx ignored\n", dwFlags
);
433 if(lpResults
->lpClass
) DPRINT("classes not implemented\n");
434 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
435 DPRINT("Caret positions for complex scripts not implemented\n");
438 if(nSet
> lpResults
->nGlyphs
)
439 nSet
= lpResults
->nGlyphs
;
441 /* return number of initialized fields */
442 lpResults
->nGlyphs
= nSet
;
444 /*if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
446 /* Treat the case where no special handling was requested in a fastpath way */
447 /* copy will do if the GCP_REORDER flag is not set */
448 if(lpResults
->lpOutString
)
449 lstrcpynW( lpResults
->lpOutString
, lpString
, nSet
);
451 if(lpResults
->lpGlyphs
)
452 lstrcpynW( lpResults
->lpGlyphs
, lpString
, nSet
);
454 if(lpResults
->lpOrder
)
456 for(i
= 0; i
< nSet
; i
++)
457 lpResults
->lpOrder
[i
] = i
;
461 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
462 nSet, lpResults->lpOrder );
465 /* FIXME: Will use the placement chars */
469 for (i
= 0; i
< nSet
; i
++)
471 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
472 lpResults
->lpDx
[i
]= c
;
476 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
480 lpResults
->lpCaretPos
[0] = 0;
481 for (i
= 1; i
< nSet
; i
++)
482 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
483 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
486 /*if(lpResults->lpGlyphs)
487 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);*/
489 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
490 ret
= MAKELONG(size
.cx
, size
.cy
);
497 NewGetCharacterPlacementW(
502 GCP_RESULTSW
*lpResults
,
509 if ( !lpString
|| uCount
<= 0 || (nMaxExtent
< 0 && nMaxExtent
!= -1 ) )
511 SetLastError(ERROR_INVALID_PARAMETER
);
517 if ( GetTextExtentPointW(hdc
, lpString
, uCount
, &Size
) )
519 return MAKELONG(Size
.cx
, Size
.cy
);
525 if ( nSet
> lpResults
->nGlyphs
)
526 nSet
= lpResults
->nGlyphs
;
528 return NtGdiGetCharacterPlacementW( hdc
,
542 GetCharABCWidthsFloatW(HDC hdc
,
547 DPRINT("GetCharABCWidthsFloatW\n");
548 if ((!abcF
) || (FirstChar
> LastChar
))
550 SetLastError(ERROR_INVALID_PARAMETER
);
553 return NtGdiGetCharABCWidthsW( hdc
,
555 (ULONG
)(LastChar
- FirstChar
+ 1),
567 GetCharWidthFloatW(HDC hdc
,
572 DPRINT("GetCharWidthsFloatW\n");
573 if ((!pxBuffer
) || (iFirstChar
> iLastChar
))
575 SetLastError(ERROR_INVALID_PARAMETER
);
578 return NtGdiGetCharWidthW( hdc
,
580 (ULONG
)(iLastChar
- iFirstChar
+ 1),
592 GetCharWidthW(HDC hdc
,
597 DPRINT("GetCharWidthsW\n");
598 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
600 SetLastError(ERROR_INVALID_PARAMETER
);
603 return NtGdiGetCharWidthW( hdc
,
605 (ULONG
)(iLastChar
- iFirstChar
+ 1),
617 GetCharWidth32W(HDC hdc
,
622 DPRINT("GetCharWidths32W\n");
623 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
625 SetLastError(ERROR_INVALID_PARAMETER
);
628 return NtGdiGetCharWidthW( hdc
,
630 (ULONG
)(iLastChar
- iFirstChar
+ 1),
632 GCW_NOFLOAT
|GCW_WIN32
,
643 GetCharABCWidthsW(HDC hdc
,
648 DPRINT("GetCharABCWidthsW\n");
649 if ((!lpabc
) || (FirstChar
> LastChar
))
651 SetLastError(ERROR_INVALID_PARAMETER
);
654 return NtGdiGetCharABCWidthsW( hdc
,
656 (ULONG
)(LastChar
- FirstChar
+ 1),
679 DPRINT("GetCharWidthsA\n");
681 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
685 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
688 HeapFree(GetProcessHeap(), 0, str
);
692 ret
= NtGdiGetCharWidthW( hdc
,
699 HeapFree(GetProcessHeap(), 0, str
);
700 HeapFree(GetProcessHeap(), 0, wstr
);
722 DPRINT("GetCharWidths32A\n");
724 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
728 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
731 HeapFree(GetProcessHeap(), 0, str
);
735 ret
= NtGdiGetCharWidthW( hdc
,
739 GCW_NOFLOAT
|GCW_WIN32
,
742 HeapFree(GetProcessHeap(), 0, str
);
743 HeapFree(GetProcessHeap(), 0, wstr
);
765 DPRINT("GetCharWidthsFloatA\n");
767 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
771 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
774 HeapFree(GetProcessHeap(), 0, str
);
777 ret
= NtGdiGetCharWidthW( hdc
, wstr
[0], (ULONG
) count
, (PWCHAR
) wstr
, 0, (PVOID
) pxBuffer
);
779 HeapFree(GetProcessHeap(), 0, str
);
780 HeapFree(GetProcessHeap(), 0, wstr
);
802 DPRINT("GetCharABCWidthsA\n");
804 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
808 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
811 HeapFree(GetProcessHeap(), 0, str
);
815 ret
= NtGdiGetCharABCWidthsW( hdc
,
822 HeapFree(GetProcessHeap(), 0, str
);
823 HeapFree(GetProcessHeap(), 0, wstr
);
833 GetCharABCWidthsFloatA(
845 DPRINT("GetCharABCWidthsFloatA\n");
847 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
851 wstr
= FONT_mbtowc( hdc
, str
, count
+1, &wlen
, NULL
);
854 HeapFree( GetProcessHeap(), 0, str
);
857 ret
= NtGdiGetCharABCWidthsW( hdc
,wstr
[0],(ULONG
)count
, (PWCHAR
)wstr
, 0, (PVOID
)lpABCF
);
859 HeapFree( GetProcessHeap(), 0, str
);
860 HeapFree( GetProcessHeap(), 0, wstr
);
870 GetCharABCWidthsI(HDC hdc
,
876 DPRINT("GetCharABCWidthsI\n");
877 return NtGdiGetCharABCWidthsW( hdc
,
881 GCABCW_NOFLOAT
|GCABCW_INDICES
,
890 GetCharWidthI(HDC hdc
,
897 DPRINT("GetCharWidthsI\n");
898 if (!lpBuffer
|| (!pgi
&& (giFirst
== MAXUSHORT
))) // Cannot be at max.
900 SetLastError(ERROR_INVALID_PARAMETER
);
903 if (!cgi
) return TRUE
;
904 return NtGdiGetCharWidthW( hdc
,
908 GCW_INDICES
|GCW_NOFLOAT
|GCW_WIN32
,
921 DWORD Gcp
= 0, Ret
= 0;
924 Ret
= NtGdiGetTextCharsetInfo(hDc
, NULL
, 0);
925 if ((Ret
== ARABIC_CHARSET
) || (Ret
== HEBREW_CHARSET
))
926 Ret
= (GCP_KASHIDA
|GCP_DIACRITIC
|GCP_LIGATE
|GCP_GLYPHSHAPE
|GCP_REORDER
);
928 Gcp
= GetDCDWord(hDc
, GdiGetFontLanguageInfo
, GCP_ERROR
);
929 if ( Gcp
== GCP_ERROR
)
953 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
958 Ret
= NtGdiGetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
959 HeapFree(GetProcessHeap(), 0, lpstrW
);
982 DPRINT("GetGlyphOutlineA uChar %x\n", uChar
);
983 if (!lpgm
|| !lpmat2
) return GDI_ERROR
;
984 if(!(uFormat
& GGO_GLYPH_INDEX
))
988 if(uChar
> 0xff) /* but, 2 bytes character only */
991 mbchs
[0] = (uChar
& 0xff00) >> 8;
992 mbchs
[1] = (uChar
& 0xff);
997 mbchs
[0] = (uChar
& 0xff);
999 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
1004 ret
= NtGdiGetGlyphOutline(hdc
, c
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1005 HeapFree(GetProcessHeap(), 0, p
);
1019 LPGLYPHMETRICS lpgm
,
1025 DPRINT("GetGlyphOutlineW uChar %x\n", uChar
);
1026 if (!lpgm
|| !lpmat2
) return GDI_ERROR
;
1027 if (!lpvBuffer
) cbBuffer
= 0;
1028 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1037 GetOutlineTextMetricsA(
1040 LPOUTLINETEXTMETRICA lpOTM
1043 char buf
[512], *ptr
;
1045 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1046 OUTLINETEXTMETRICA
*output
= lpOTM
;
1049 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1051 if(ret
> sizeof(buf
))
1053 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1059 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1061 needed
= sizeof(OUTLINETEXTMETRICA
);
1062 if(lpOTMW
->otmpFamilyName
)
1063 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1064 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFamilyName
), -1,
1065 NULL
, 0, NULL
, NULL
);
1066 if(lpOTMW
->otmpFaceName
)
1067 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1068 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFaceName
), -1,
1069 NULL
, 0, NULL
, NULL
);
1070 if(lpOTMW
->otmpStyleName
)
1071 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1072 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpStyleName
), -1,
1073 NULL
, 0, NULL
, NULL
);
1074 if(lpOTMW
->otmpFullName
)
1075 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1076 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFullName
), -1,
1077 NULL
, 0, NULL
, NULL
);
1085 DPRINT("needed = %u\n", needed
);
1088 /* Since the supplied buffer isn't big enough, we'll alloc one
1089 that is and memcpy the first cbData bytes into the lpOTM at
1091 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1098 ret
= output
->otmSize
= min(needed
, cbData
);
1099 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1100 output
->otmFiller
= 0;
1101 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1102 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1103 output
->otmfsType
= lpOTMW
->otmfsType
;
1104 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1105 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1106 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1107 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1108 output
->otmAscent
= lpOTMW
->otmAscent
;
1109 output
->otmDescent
= lpOTMW
->otmDescent
;
1110 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1111 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1112 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1113 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1114 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1115 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1116 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1117 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1118 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1119 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1120 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1121 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1122 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1123 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1124 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1125 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1128 ptr
= (char*)(output
+ 1);
1129 left
= needed
- sizeof(*output
);
1131 if(lpOTMW
->otmpFamilyName
)
1133 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1134 len
= WideCharToMultiByte(CP_ACP
, 0,
1135 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFamilyName
), -1,
1136 ptr
, left
, NULL
, NULL
);
1141 output
->otmpFamilyName
= 0;
1143 if(lpOTMW
->otmpFaceName
)
1145 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1146 len
= WideCharToMultiByte(CP_ACP
, 0,
1147 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFaceName
), -1,
1148 ptr
, left
, NULL
, NULL
);
1153 output
->otmpFaceName
= 0;
1155 if(lpOTMW
->otmpStyleName
)
1157 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1158 len
= WideCharToMultiByte(CP_ACP
, 0,
1159 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpStyleName
), -1,
1160 ptr
, left
, NULL
, NULL
);
1165 output
->otmpStyleName
= 0;
1167 if(lpOTMW
->otmpFullName
)
1169 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1170 len
= WideCharToMultiByte(CP_ACP
, 0,
1171 (WCHAR
*)((char*)lpOTMW
+ (int)lpOTMW
->otmpFullName
), -1,
1172 ptr
, left
, NULL
, NULL
);
1176 output
->otmpFullName
= 0;
1182 memcpy(lpOTM
, output
, cbData
);
1183 HeapFree(GetProcessHeap(), 0, output
);
1185 /* check if the string offsets really fit into the provided size */
1186 /* FIXME: should we check string length as well? */
1187 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1188 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1190 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1191 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1193 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1194 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1196 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1197 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1201 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1202 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1213 GetOutlineTextMetricsW(
1216 LPOUTLINETEXTMETRICW lpOTM
1219 TMDIFF Tmd
; // Should not be zero.
1221 return NtGdiGetOutlineTextMetricsInternalW(hdc
, cbData
, lpOTM
, &Tmd
);
1229 GetKerningPairsW(HDC hdc
,
1231 LPKERNINGPAIR pkpDst
)
1233 if ((cPairs
!= 0) || (pkpDst
== 0))
1235 return NtGdiGetKerningPairs(hdc
,cPairs
,pkpDst
);
1239 SetLastError(ERROR_INVALID_PARAMETER
);
1249 GetKerningPairsA( HDC hDC
,
1251 LPKERNINGPAIR kern_pairA
)
1256 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
1257 KERNINGPAIR
*kern_pairW
;
1259 if (!cPairs
&& kern_pairA
)
1261 SetLastError(ERROR_INVALID_PARAMETER
);
1265 charset
= GetTextCharset(hDC
);
1266 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
1268 DPRINT1("Can't find codepage for charset %d\n", charset
);
1271 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1272 * to fail on an invalid character for CP_SYMBOL.
1274 cpi
.DefaultChar
[0] = 0;
1275 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
1277 DPRINT1("Can't find codepage %u info\n", csi
.ciACP
);
1280 DPRINT("charset %d => codepage %u\n", charset
, csi
.ciACP
);
1282 total_kern_pairs
= NtGdiGetKerningPairs(hDC
, 0, NULL
);
1283 if (!total_kern_pairs
) return 0;
1285 if (!cPairs
&& !kern_pairA
) return total_kern_pairs
;
1287 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
1288 if (kern_pairW
== NULL
)
1292 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
1294 for (i
= 0; i
< total_kern_pairs
; i
++)
1298 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
1301 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
1304 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
1309 if (kern_pairs_copied
>= cPairs
) break;
1311 kern_pairA
->wFirst
= (BYTE
)first
;
1312 kern_pairA
->wSecond
= (BYTE
)second
;
1313 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
1316 kern_pairs_copied
++;
1319 HeapFree(GetProcessHeap(), 0, kern_pairW
);
1321 return kern_pairs_copied
;
1331 CreateFontIndirectExA(const ENUMLOGFONTEXDVA
*elfexd
)
1335 ENUMLOGFONTEXDVW Logfont
;
1337 EnumLogFontExW2A( (LPENUMLOGFONTEXA
) elfexd
,
1338 &Logfont
.elfEnumLogfontEx
);
1340 RtlCopyMemory( &Logfont
.elfDesignVector
,
1341 (PVOID
) &elfexd
->elfDesignVector
,
1342 sizeof(DESIGNVECTOR
));
1344 return NtGdiHfontCreate( &Logfont
, 0, 0, 0, NULL
);
1355 CreateFontIndirectExW(const ENUMLOGFONTEXDVW
*elfexd
)
1357 /* Msdn: Note, this function ignores the elfDesignVector member in
1362 return NtGdiHfontCreate((PENUMLOGFONTEXDVW
) elfexd
, 0, 0, 0, NULL
);
1373 CreateFontIndirectA(
1374 CONST LOGFONTA
*lplf
1381 LogFontA2W(&tlf
, lplf
);
1382 return CreateFontIndirectW(&tlf
);
1393 CreateFontIndirectW(
1394 CONST LOGFONTW
*lplf
1399 ENUMLOGFONTEXDVW Logfont
;
1401 RtlCopyMemory( &Logfont
.elfEnumLogfontEx
.elfLogFont
, lplf
, sizeof(LOGFONTW
));
1402 // Need something other than just cleaning memory here.
1403 // Guess? Use caller data to determine the rest.
1404 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfFullName
,
1405 sizeof(Logfont
.elfEnumLogfontEx
.elfFullName
));
1406 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfStyle
,
1407 sizeof(Logfont
.elfEnumLogfontEx
.elfStyle
));
1408 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfScript
,
1409 sizeof(Logfont
.elfEnumLogfontEx
.elfScript
));
1411 Logfont
.elfDesignVector
.dvNumAxes
= 0; // No more than MM_MAX_NUMAXES
1413 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
1415 return CreateFontIndirectExW(&Logfont
);
1436 DWORD fdwOutputPrecision
,
1437 DWORD fdwClipPrecision
,
1439 DWORD fdwPitchAndFamily
,
1443 ANSI_STRING StringA
;
1444 UNICODE_STRING StringU
;
1447 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
1448 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
1450 ret
= CreateFontW(nHeight
,
1465 RtlFreeUnicodeString(&StringU
);
1486 DWORD fdwOutputPrecision
,
1487 DWORD fdwClipPrecision
,
1489 DWORD fdwPitchAndFamily
,
1495 logfont
.lfHeight
= nHeight
;
1496 logfont
.lfWidth
= nWidth
;
1497 logfont
.lfEscapement
= nEscapement
;
1498 logfont
.lfOrientation
= nOrientation
;
1499 logfont
.lfWeight
= nWeight
;
1500 logfont
.lfItalic
= (BYTE
)fnItalic
;
1501 logfont
.lfUnderline
= (BYTE
)fdwUnderline
;
1502 logfont
.lfStrikeOut
= (BYTE
)fdwStrikeOut
;
1503 logfont
.lfCharSet
= (BYTE
)fdwCharSet
;
1504 logfont
.lfOutPrecision
= (BYTE
)fdwOutputPrecision
;
1505 logfont
.lfClipPrecision
= (BYTE
)fdwClipPrecision
;
1506 logfont
.lfQuality
= (BYTE
)fdwQuality
;
1507 logfont
.lfPitchAndFamily
= (BYTE
)fdwPitchAndFamily
;
1509 if (NULL
!= lpszFace
)
1511 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
1512 wcsncpy((wchar_t *)logfont
.lfFaceName
, lpszFace
, Size
- 1);
1513 /* Be 101% sure to have '\0' at end of string */
1514 logfont
.lfFaceName
[Size
- 1] = '\0';
1518 logfont
.lfFaceName
[0] = L
'\0';
1521 return CreateFontIndirectW(&logfont
);
1530 CreateScalableFontResourceA(
1533 LPCSTR lpszFontFile
,
1534 LPCSTR lpszCurrentPath
1546 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1548 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1550 SetLastError( ERROR_INVALID_PARAMETER
);
1554 return GdiAddFontResourceW(lpszFilename
, fl
,0);
1563 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1569 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1571 SetLastError( ERROR_INVALID_PARAMETER
);
1575 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1576 if ( !NT_SUCCESS (Status
) )
1578 SetLastError (RtlNtStatusToDosError(Status
));
1582 rc
= GdiAddFontResourceW ( FilenameW
, fl
, 0 );
1583 HEAP_free ( FilenameW
);
1593 AddFontResourceA ( LPCSTR lpszFilename
)
1599 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1600 if ( !NT_SUCCESS (Status
) )
1602 SetLastError (RtlNtStatusToDosError(Status
));
1606 rc
= GdiAddFontResourceW ( FilenameW
, 0, 0);
1608 HEAP_free ( FilenameW
);
1619 AddFontResourceW ( LPCWSTR lpszFilename
)
1621 return GdiAddFontResourceW ( lpszFilename
, 0, 0 );
1630 RemoveFontResourceW(LPCWSTR lpFileName
)
1632 return RemoveFontResourceExW(lpFileName
,0,0);
1641 RemoveFontResourceA(LPCSTR lpFileName
)
1643 return RemoveFontResourceExA(lpFileName
,0,0);
1651 RemoveFontResourceExA(LPCSTR lpFileName
,
1659 /* FIXME the flags */
1661 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1663 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
1664 if (!NT_SUCCESS (Status
))
1665 SetLastError (RtlNtStatusToDosError(Status
));
1669 HEAP_free ( lpFileNameW
);
1680 RemoveFontResourceExW(LPCWSTR lpFileName
,
1684 /* FIXME the flags */
1686 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1691 /***********************************************************************
1692 * GdiGetCharDimensions
1694 * Gets the average width of the characters in the English alphabet.
1697 * hdc [I] Handle to the device context to measure on.
1698 * lptm [O] Pointer to memory to store the text metrics into.
1699 * height [O] On exit, the maximum height of characters in the English alphabet.
1702 * The average width of characters in the English alphabet.
1705 * This function is used by the dialog manager to get the size of a dialog
1706 * unit. It should also be used by other pieces of code that need to know
1707 * the size of a dialog unit in logical units without having access to the
1708 * window handle of the dialog.
1709 * Windows caches the font metrics from this function, but we don't and
1710 * there doesn't appear to be an immediate advantage to do so.
1713 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1715 * Despite most of MSDN insisting that the horizontal base unit is
1716 * tmAveCharWidth it isn't. Knowledge base article Q145994
1717 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
1718 * says that we should take the average of the 52 English upper and lower
1726 GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
1730 static const WCHAR alphabet
[] =
1732 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
1733 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
1734 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0
1737 if(!GetTextMetricsW(hdc
, &tm
)) return 0;
1739 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
1741 if (lptm
) *lptm
= tm
;
1742 if (height
) *height
= tm
.tmHeight
;
1744 return (sz
.cx
/ 26 + 1) / 2;
1747 /*************************************************************************
1748 * TranslateCharsetInfo [GDI32.@]
1750 * Fills a CHARSETINFO structure for a character set, code page, or
1751 * font. This allows making the correspondance between different labelings
1752 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1753 * of the same encoding.
1755 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1756 * only one codepage should be set in *lpSrc.
1759 * TRUE on success, FALSE on failure.
1767 TranslateCharsetInfo(
1768 LPDWORD lpSrc
, /* [in]
1769 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1770 if flags == TCI_SRCCHARSET: a character set value
1771 if flags == TCI_SRCCODEPAGE: a code page value
1773 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
1774 DWORD flags
/* [in] determines interpretation of lpSrc */)
1779 case TCI_SRCFONTSIG
:
1780 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
1782 case TCI_SRCCODEPAGE
:
1783 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
1785 case TCI_SRCCHARSET
:
1786 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
1790 LCID lCid
= (LCID
)PtrToUlong(lpSrc
);
1791 LOCALESIGNATURE LocSig
;
1792 INT Ret
= GetLocaleInfoW(lCid
, LOCALE_FONTSIGNATURE
, (LPWSTR
)&LocSig
, 0);
1793 if ( GetLocaleInfoW(lCid
, LOCALE_FONTSIGNATURE
, (LPWSTR
)&LocSig
, Ret
))
1795 while (index
< MAXTCIINDEX
&& !(LocSig
.lsCsbDefault
[0]>>index
& 0x0001)) index
++;
1800 GdiSetLastError(ERROR_INVALID_PARAMETER
);
1803 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
1804 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n",
1805 index
,FONT_tci
[index
].ciCharset
,FONT_tci
[index
].ciACP
,FONT_tci
[index
].fs
.fsCsb
[0]);
1806 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
1821 DWORD Ret
= GDI_ERROR
;
1824 if (GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_DC
)
1826 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_METADC
)
1827 return MFDRV_SetMapperFlags( hDC
, flags
);
1830 PLDC pLDC
= Dc_Attr
->pvLDC
;
1833 SetLastError(ERROR_INVALID_HANDLE
);
1836 if (pLDC
->iType
== LDC_EMFLDC
)
1838 return EMFDRV_SetMapperFlags( hDC
, flags
);
1843 if (!GdiGetHandleUserData((HGDIOBJ
) hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
) &Dc_Attr
)) return GDI_ERROR
;
1845 if (NtCurrentTeb()->GdiTebBatch
.HDC
== hDC
)
1847 if (Dc_Attr
->ulDirty_
& DC_FONTTEXT_DIRTY
)
1850 Dc_Attr
->ulDirty_
&= ~(DC_MODE_DIRTY
|DC_FONTTEXT_DIRTY
);
1855 SetLastError(ERROR_INVALID_PARAMETER
);
1858 Ret
= Dc_Attr
->flFontMapper
;
1859 Dc_Attr
->flFontMapper
= flags
;
1873 FONTENUMPROCW FontFunc
,
1878 return NtGdiEnumFonts ( hDC
, lpFaceName
, FontFunc
, lParam
);
1880 return EnumFontFamiliesW( hDC
, lpFaceName
, FontFunc
, lParam
);
1892 FONTENUMPROCA FontFunc
,
1901 Status
= HEAP_strdupA2W ( &lpFaceNameW
, lpFaceName
);
1902 if (!NT_SUCCESS (Status
))
1903 SetLastError (RtlNtStatusToDosError(Status
));
1906 rc
= NtGdiEnumFonts ( hDC
, lpFaceNameW
, FontFunc
, lParam
);
1908 HEAP_free ( lpFaceNameW
);
1912 return EnumFontFamiliesA( hDC
, lpFaceName
, FontFunc
, lParam
);
1916 #define EfdFontFamilies 3
1920 NewEnumFontFamiliesExW(
1922 LPLOGFONTW lpLogfont
,
1923 FONTENUMPROCW lpEnumFontFamExProcW
,
1927 ULONG_PTR idEnum
, cbDataSize
, cbRetSize
;
1928 PENUMFONTDATAW pEfdw
;
1933 /* Open enumeration handle and find out how much memory we need */
1934 idEnum
= NtGdiEnumFontOpen(hDC
,
1938 (lpLogfont
&& lpLogfont
->lfFaceName
[0])? lpLogfont
->lfFaceName
: NULL
,
1939 lpLogfont
? lpLogfont
->lfCharSet
: DEFAULT_CHARSET
,
1945 if (cbDataSize
== 0)
1947 NtGdiEnumFontClose(idEnum
);
1951 /* Allocate memory */
1952 pBuffer
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
1953 if (pBuffer
== NULL
)
1955 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1956 NtGdiEnumFontClose(idEnum
);
1960 /* Do the enumeration */
1961 if (!NtGdiEnumFontChunk(hDC
, idEnum
, cbDataSize
, &cbRetSize
, (PVOID
)pBuffer
))
1963 HeapFree(GetProcessHeap(), 0, pBuffer
);
1964 NtGdiEnumFontClose(idEnum
);
1968 /* Get start and end address */
1969 pEfdw
= (PENUMFONTDATAW
)pBuffer
;
1970 pMax
= pBuffer
+ cbDataSize
;
1972 /* Iterate through the structures */
1973 while ((PBYTE
)pEfdw
< pMax
&& ret
)
1975 PNTMW_INTERNAL pNtmwi
= (PNTMW_INTERNAL
)((ULONG_PTR
)pEfdw
+ pEfdw
->ulNtmwiOffset
);
1977 ret
= lpEnumFontFamExProcW((VOID
*)&pEfdw
->elfexdv
.elfEnumLogfontEx
,
1978 (VOID
*)&pNtmwi
->ntmw
,
1982 pEfdw
= (PENUMFONTDATAW
)((ULONG_PTR
)pEfdw
+ pEfdw
->cbSize
);
1985 /* Release the memory and close handle */
1986 HeapFree(GetProcessHeap(), 0, pBuffer
);
1987 NtGdiEnumFontClose(idEnum
);