2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: win32ss/gdi/gdi32/objects/font.c
18 /* Rounds a floating point number to integer. The world-to-viewport
19 * transformation process is done in floating point internally. This function
20 * is then used to round these coordinates to integer values.
22 static __inline INT
GDI_ROUND(FLOAT val
)
24 return (int)floor(val
+ 0.5);
28 * For TranslateCharsetInfo
30 #define MAXTCIINDEX 32
31 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] =
34 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
35 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
36 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
37 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
38 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
39 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
40 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
41 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
42 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
43 /* reserved by ANSI */
44 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
45 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
46 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
47 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
48 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
49 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
50 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
52 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
53 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
54 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
55 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
56 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
57 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
58 /* reserved for alternate ANSI and OEM */
59 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
60 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
61 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
62 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
63 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
64 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
65 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
66 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
67 /* reserved for system */
68 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
69 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
72 #define INITIAL_FAMILY_COUNT 64
74 /***********************************************************************
75 * TEXTMETRIC conversion functions.
79 FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
81 ptmA
->tmHeight
= ptmW
->tmHeight
;
82 ptmA
->tmAscent
= ptmW
->tmAscent
;
83 ptmA
->tmDescent
= ptmW
->tmDescent
;
84 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
85 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
86 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
87 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
88 ptmA
->tmWeight
= ptmW
->tmWeight
;
89 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
90 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
91 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
92 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
93 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
95 ptmA
->tmFirstChar
= 0x1e;
96 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
100 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
101 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
103 ptmA
->tmDefaultChar
= (CHAR
)ptmW
->tmDefaultChar
;
104 ptmA
->tmBreakChar
= (CHAR
)ptmW
->tmBreakChar
;
105 ptmA
->tmItalic
= ptmW
->tmItalic
;
106 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
107 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
108 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
109 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
112 /***********************************************************************
115 * Returns a Unicode translation of str using the charset of the
116 * currently selected font in hdc. If count is -1 then str is assumed
117 * to be '\0' terminated, otherwise it contains the number of bytes to
118 * convert. If plenW is non-NULL, on return it will point to the
119 * number of WCHARs that have been written. If pCP is non-NULL, on
120 * return it will point to the codepage used in the conversion. The
121 * caller should free the returned LPWSTR from the process heap
124 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
126 UINT cp
= GdiGetCodePage( hdc
);
130 if(count
== -1) count
= strlen(str
);
131 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
132 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
135 if(!MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
))
137 HeapFree(GetProcessHeap(), 0, strW
);
140 DPRINT("mapped %s -> %S\n", str
, strW
);
141 if(plenW
) *plenW
= lenW
;
146 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
148 INT i
, count
= lastChar
- firstChar
+ 1;
155 switch (GdiGetCodePage(hdc
))
162 if (lastChar
> 0xffff)
164 if ((firstChar
^ lastChar
) > 0xff)
173 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
177 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
180 str
[i
++] = (BYTE
)(c
>> 8);
191 NewTextMetricW2A(NEWTEXTMETRICA
*tma
, NEWTEXTMETRICW
*tmw
)
193 FONT_TextMetricWToA((TEXTMETRICW
*) tmw
, (TEXTMETRICA
*) tma
);
194 tma
->ntmFlags
= tmw
->ntmFlags
;
195 tma
->ntmSizeEM
= tmw
->ntmSizeEM
;
196 tma
->ntmCellHeight
= tmw
->ntmCellHeight
;
197 tma
->ntmAvgWidth
= tmw
->ntmAvgWidth
;
201 NewTextMetricExW2A(NEWTEXTMETRICEXA
*tma
, NEWTEXTMETRICEXW
*tmw
)
203 NewTextMetricW2A(&tma
->ntmTm
, &tmw
->ntmTm
);
204 tma
->ntmFontSig
= tmw
->ntmFontSig
;
207 // IntFontFamilyCompareEx's flags
208 #define IFFCX_CHARSET 1
209 #define IFFCX_STYLE 2
211 FORCEINLINE
int FASTCALL
212 IntFontFamilyCompareEx(const FONTFAMILYINFO
*ffi1
,
213 const FONTFAMILYINFO
*ffi2
, DWORD dwCompareFlags
)
215 const LOGFONTW
*plf1
= &ffi1
->EnumLogFontEx
.elfLogFont
;
216 const LOGFONTW
*plf2
= &ffi2
->EnumLogFontEx
.elfLogFont
;
217 ULONG WeightDiff1
, WeightDiff2
;
218 int cmp
= _wcsicmp(plf1
->lfFaceName
, plf2
->lfFaceName
);
221 if (dwCompareFlags
& IFFCX_STYLE
)
223 WeightDiff1
= labs(plf1
->lfWeight
- FW_NORMAL
);
224 WeightDiff2
= labs(plf2
->lfWeight
- FW_NORMAL
);
225 if (WeightDiff1
< WeightDiff2
)
227 if (WeightDiff1
> WeightDiff2
)
229 if (plf1
->lfItalic
< plf2
->lfItalic
)
231 if (plf1
->lfItalic
> plf2
->lfItalic
)
234 if (dwCompareFlags
& IFFCX_CHARSET
)
236 if (plf1
->lfCharSet
< plf2
->lfCharSet
)
238 if (plf1
->lfCharSet
> plf2
->lfCharSet
)
245 IntFontFamilyCompare(const void *ffi1
, const void *ffi2
)
247 return IntFontFamilyCompareEx(ffi1
, ffi2
, IFFCX_STYLE
| IFFCX_CHARSET
);
250 // IntEnumFontFamilies' flags:
251 #define IEFF_UNICODE 1
252 #define IEFF_EXTENDED 2
255 IntFontFamilyListUnique(FONTFAMILYINFO
*InfoList
, INT nCount
,
256 const LOGFONTW
*plf
, DWORD dwFlags
)
258 FONTFAMILYINFO
*first
, *last
, *result
;
259 DWORD dwCompareFlags
= 0;
261 if (plf
->lfFaceName
[0])
262 dwCompareFlags
|= IFFCX_STYLE
;
264 if ((dwFlags
& IEFF_EXTENDED
) && plf
->lfCharSet
== DEFAULT_CHARSET
)
265 dwCompareFlags
|= IFFCX_CHARSET
;
267 // std::unique(first, last, IntFontFamilyCompareEx);
271 result
= first
= InfoList
;
272 last
= &InfoList
[nCount
];
273 while (++first
!= last
)
275 if (IntFontFamilyCompareEx(result
, first
, dwCompareFlags
) != 0 &&
281 nCount
= (int)(++result
- InfoList
);
287 IntEnumFontFamilies(HDC Dc
, LPLOGFONTW LogFont
, PVOID EnumProc
, LPARAM lParam
,
292 PFONTFAMILYINFO Info
;
295 ENUMLOGFONTEXA EnumLogFontExA
;
296 NEWTEXTMETRICEXA NewTextMetricExA
;
299 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
300 INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
));
308 lfW
.lfCharSet
= DEFAULT_CHARSET
;
309 lfW
.lfPitchAndFamily
= 0;
310 lfW
.lfFaceName
[0] = 0;
314 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, INITIAL_FAMILY_COUNT
);
315 if (FontFamilyCount
< 0)
317 RtlFreeHeap(GetProcessHeap(), 0, Info
);
320 if (INITIAL_FAMILY_COUNT
< FontFamilyCount
)
322 FontFamilySize
= FontFamilyCount
;
323 RtlFreeHeap(GetProcessHeap(), 0, Info
);
324 Info
= RtlAllocateHeap(GetProcessHeap(), 0,
325 FontFamilyCount
* sizeof(FONTFAMILYINFO
));
330 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, LogFont
, Info
, FontFamilySize
);
331 if (FontFamilyCount
< 0 || FontFamilySize
< FontFamilyCount
)
333 RtlFreeHeap(GetProcessHeap(), 0, Info
);
339 qsort(Info
, FontFamilyCount
, sizeof(*Info
), IntFontFamilyCompare
);
340 DPRINT("qsort done\n");
341 FontFamilyCount
= IntFontFamilyListUnique(Info
, FontFamilyCount
, LogFont
, dwFlags
);
342 DPRINT("unique done\n");
344 for (i
= 0; i
< FontFamilyCount
; i
++)
346 if (dwFlags
& IEFF_UNICODE
)
348 Ret
= ((FONTENUMPROCW
) EnumProc
)(
349 (VOID
*)&Info
[i
].EnumLogFontEx
,
350 (VOID
*)&Info
[i
].NewTextMetricEx
,
351 Info
[i
].FontType
, lParam
);
355 // Could use EnumLogFontExW2A here?
356 LogFontW2A(&EnumLogFontExA
.elfLogFont
, &Info
[i
].EnumLogFontEx
.elfLogFont
);
357 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfFullName
, -1,
358 (LPSTR
)EnumLogFontExA
.elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
359 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfStyle
, -1,
360 (LPSTR
)EnumLogFontExA
.elfStyle
, LF_FACESIZE
, NULL
, NULL
);
361 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfScript
, -1,
362 (LPSTR
)EnumLogFontExA
.elfScript
, LF_FACESIZE
, NULL
, NULL
);
363 NewTextMetricExW2A(&NewTextMetricExA
,
364 &Info
[i
].NewTextMetricEx
);
365 Ret
= ((FONTENUMPROCA
) EnumProc
)(
366 (VOID
*)&EnumLogFontExA
,
367 (VOID
*)&NewTextMetricExA
,
368 Info
[i
].FontType
, lParam
);
375 RtlFreeHeap(GetProcessHeap(), 0, Info
);
384 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
385 LPARAM lParam
, DWORD dwFlags
)
387 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
,
388 IEFF_UNICODE
| IEFF_EXTENDED
);
396 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
401 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
402 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
403 if (NULL
!= lpszFamily
)
405 if (!*lpszFamily
) return 1;
406 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
409 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, IEFF_UNICODE
);
417 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
418 LPARAM lParam
, DWORD dwFlags
)
420 LOGFONTW LogFontW
, *pLogFontW
;
424 LogFontA2W(&LogFontW
,lpLogfont
);
425 pLogFontW
= &LogFontW
;
427 else pLogFontW
= NULL
;
429 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
430 return IntEnumFontFamilies(hdc
, pLogFontW
, lpEnumFontFamExProc
, lParam
, IEFF_EXTENDED
);
438 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
443 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
444 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
445 if (NULL
!= lpszFamily
)
447 if (!*lpszFamily
) return 1;
448 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
451 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, 0);
460 GetCharacterPlacementA(
465 GCP_RESULTSA
*lpResults
,
470 GCP_RESULTSW resultsW
;
474 if ( !lpString
|| uCount
<= 0 || !lpResults
|| (nMaxExtent
< 0 && nMaxExtent
!= -1 ) )
476 SetLastError(ERROR_INVALID_PARAMETER
);
479 /* TRACE("%s, %d, %d, 0x%08x\n",
480 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
482 /* both structs are equal in size */
483 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
485 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
486 if (lpStringW
== NULL
)
490 if(lpResults
->lpOutString
)
492 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
493 if (resultsW
.lpOutString
== NULL
)
495 HeapFree(GetProcessHeap(), 0, lpStringW
);
500 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
502 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
503 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
505 if(lpResults
->lpOutString
)
507 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
508 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
511 HeapFree(GetProcessHeap(), 0, lpStringW
);
512 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
523 GetCharacterPlacementW(
528 GCP_RESULTSW
*lpResults
,
535 DPRINT("GetCharacterPlacementW\n");
537 if (dwFlags
&(~GCP_REORDER
)) DPRINT("flags 0x%08lx ignored\n", dwFlags
);
538 if (lpResults
->lpClass
) DPRINT("classes not implemented\n");
541 if (nSet
> lpResults
->nGlyphs
)
542 nSet
= lpResults
->nGlyphs
;
544 /* return number of initialized fields */
545 lpResults
->nGlyphs
= nSet
;
547 if (dwFlags
& GCP_REORDER
)
549 if (LoadLPK(LPK_GCP
))
550 return LpkGetCharacterPlacement(hdc
, lpString
, uCount
, nMaxExtent
, lpResults
, dwFlags
, 0);
553 /* Treat the case where no special handling was requested in a fastpath way */
554 /* copy will do if the GCP_REORDER flag is not set */
555 if (lpResults
->lpOutString
)
556 lstrcpynW( lpResults
->lpOutString
, lpString
, nSet
);
558 if (lpResults
->lpOrder
)
560 for (i
= 0; i
< nSet
; i
++)
561 lpResults
->lpOrder
[i
] = i
;
564 /* FIXME: Will use the placement chars */
568 for (i
= 0; i
< nSet
; i
++)
570 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
571 lpResults
->lpDx
[i
]= c
;
575 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
579 lpResults
->lpCaretPos
[0] = 0;
580 for (i
= 1; i
< nSet
; i
++)
581 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
582 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
585 if (lpResults
->lpGlyphs
)
586 NtGdiGetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
588 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
589 ret
= MAKELONG(size
.cx
, size
.cy
);
596 NewGetCharacterPlacementW(
601 GCP_RESULTSW
*lpResults
,
608 if ( !lpString
|| uCount
<= 0 || (nMaxExtent
< 0 && nMaxExtent
!= -1 ) )
610 SetLastError(ERROR_INVALID_PARAMETER
);
616 if ( GetTextExtentPointW(hdc
, lpString
, uCount
, &Size
) )
618 return MAKELONG(Size
.cx
, Size
.cy
);
624 if ( nSet
> lpResults
->nGlyphs
)
625 nSet
= lpResults
->nGlyphs
;
627 return NtGdiGetCharacterPlacementW( hdc
,
641 GetCharABCWidthsFloatW(HDC hdc
,
646 DPRINT("GetCharABCWidthsFloatW\n");
647 if ((!abcF
) || (FirstChar
> LastChar
))
649 SetLastError(ERROR_INVALID_PARAMETER
);
652 return NtGdiGetCharABCWidthsW( hdc
,
654 (ULONG
)(LastChar
- FirstChar
+ 1),
666 GetCharWidthFloatW(HDC hdc
,
671 DPRINT("GetCharWidthsFloatW\n");
672 if ((!pxBuffer
) || (iFirstChar
> iLastChar
))
674 SetLastError(ERROR_INVALID_PARAMETER
);
677 return NtGdiGetCharWidthW( hdc
,
679 (ULONG
)(iLastChar
- iFirstChar
+ 1),
691 GetCharWidthW(HDC hdc
,
696 DPRINT("GetCharWidthsW\n");
697 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
699 SetLastError(ERROR_INVALID_PARAMETER
);
702 return NtGdiGetCharWidthW( hdc
,
704 (ULONG
)(iLastChar
- iFirstChar
+ 1),
716 GetCharWidth32W(HDC hdc
,
721 DPRINT("GetCharWidths32W\n");
722 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
724 SetLastError(ERROR_INVALID_PARAMETER
);
727 return NtGdiGetCharWidthW( hdc
,
729 (ULONG
)(iLastChar
- iFirstChar
+ 1),
731 GCW_NOFLOAT
|GCW_WIN32
,
742 GetCharABCWidthsW(HDC hdc
,
747 DPRINT("GetCharABCWidthsW\n");
748 if ((!lpabc
) || (FirstChar
> LastChar
))
750 SetLastError(ERROR_INVALID_PARAMETER
);
753 return NtGdiGetCharABCWidthsW( hdc
,
755 (ULONG
)(LastChar
- FirstChar
+ 1),
778 DPRINT("GetCharWidthsA\n");
780 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
784 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
787 HeapFree(GetProcessHeap(), 0, str
);
791 ret
= NtGdiGetCharWidthW( hdc
,
798 HeapFree(GetProcessHeap(), 0, str
);
799 HeapFree(GetProcessHeap(), 0, wstr
);
821 DPRINT("GetCharWidths32A\n");
823 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
827 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
830 HeapFree(GetProcessHeap(), 0, str
);
834 ret
= NtGdiGetCharWidthW( hdc
,
838 GCW_NOFLOAT
|GCW_WIN32
,
841 HeapFree(GetProcessHeap(), 0, str
);
842 HeapFree(GetProcessHeap(), 0, wstr
);
864 DPRINT("GetCharWidthsFloatA\n");
866 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
870 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
873 HeapFree(GetProcessHeap(), 0, str
);
876 ret
= NtGdiGetCharWidthW( hdc
, wstr
[0], (ULONG
) count
, (PWCHAR
) wstr
, 0, (PVOID
) pxBuffer
);
878 HeapFree(GetProcessHeap(), 0, str
);
879 HeapFree(GetProcessHeap(), 0, wstr
);
901 DPRINT("GetCharABCWidthsA\n");
903 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
907 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
910 HeapFree(GetProcessHeap(), 0, str
);
914 ret
= NtGdiGetCharABCWidthsW( hdc
,
921 HeapFree(GetProcessHeap(), 0, str
);
922 HeapFree(GetProcessHeap(), 0, wstr
);
932 GetCharABCWidthsFloatA(
944 DPRINT("GetCharABCWidthsFloatA\n");
946 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
950 wstr
= FONT_mbtowc( hdc
, str
, count
+1, &wlen
, NULL
);
953 HeapFree( GetProcessHeap(), 0, str
);
956 ret
= NtGdiGetCharABCWidthsW( hdc
,wstr
[0],(ULONG
)count
, (PWCHAR
)wstr
, 0, (PVOID
)lpABCF
);
958 HeapFree( GetProcessHeap(), 0, str
);
959 HeapFree( GetProcessHeap(), 0, wstr
);
969 GetCharABCWidthsI(HDC hdc
,
975 DPRINT("GetCharABCWidthsI\n");
976 return NtGdiGetCharABCWidthsW( hdc
,
980 GCABCW_NOFLOAT
|GCABCW_INDICES
,
989 GetCharWidthI(HDC hdc
,
996 DPRINT("GetCharWidthsI\n");
997 if (!lpBuffer
|| (!pgi
&& (giFirst
== MAXUSHORT
))) // Cannot be at max.
999 SetLastError(ERROR_INVALID_PARAMETER
);
1002 if (!cgi
) return TRUE
;
1003 return NtGdiGetCharWidthW( hdc
,
1007 GCW_INDICES
|GCW_NOFLOAT
|GCW_WIN32
,
1016 GetFontLanguageInfo(
1020 DWORD Gcp
= 0, Ret
= 0;
1023 Ret
= NtGdiGetTextCharsetInfo(hDc
, NULL
, 0);
1024 if ((Ret
== ARABIC_CHARSET
) || (Ret
== HEBREW_CHARSET
))
1025 Ret
= (GCP_KASHIDA
|GCP_DIACRITIC
|GCP_LIGATE
|GCP_GLYPHSHAPE
|GCP_REORDER
);
1027 Gcp
= GetDCDWord(hDc
, GdiGetFontLanguageInfo
, GCP_ERROR
);
1028 if ( Gcp
== GCP_ERROR
)
1052 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
1057 Ret
= NtGdiGetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
1058 HeapFree(GetProcessHeap(), 0, lpstrW
);
1071 LPGLYPHMETRICS lpgm
,
1081 DPRINT("GetGlyphOutlineA uChar %x\n", uChar
);
1082 if (!lpgm
|| !lpmat2
) return GDI_ERROR
;
1083 if(!(uFormat
& GGO_GLYPH_INDEX
))
1087 if(uChar
> 0xff) /* but, 2 bytes character only */
1090 mbchs
[0] = (uChar
& 0xff00) >> 8;
1091 mbchs
[1] = (uChar
& 0xff);
1096 mbchs
[0] = (uChar
& 0xff);
1098 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
1105 ret
= NtGdiGetGlyphOutline(hdc
, c
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1106 HeapFree(GetProcessHeap(), 0, p
);
1120 LPGLYPHMETRICS lpgm
,
1126 DPRINT("GetGlyphOutlineW uChar %x\n", uChar
);
1127 if (!lpgm
|| !lpmat2
) return GDI_ERROR
;
1128 if (!lpvBuffer
) cbBuffer
= 0;
1129 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1148 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1157 GetOutlineTextMetricsA(
1160 LPOUTLINETEXTMETRICA lpOTM
1163 char buf
[512], *ptr
;
1165 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1166 OUTLINETEXTMETRICA
*output
= lpOTM
;
1169 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1171 if(ret
> sizeof(buf
))
1173 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1179 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1181 needed
= sizeof(OUTLINETEXTMETRICA
);
1182 if(lpOTMW
->otmpFamilyName
)
1183 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1184 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFamilyName
), -1,
1185 NULL
, 0, NULL
, NULL
);
1186 if(lpOTMW
->otmpFaceName
)
1187 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1188 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFaceName
), -1,
1189 NULL
, 0, NULL
, NULL
);
1190 if(lpOTMW
->otmpStyleName
)
1191 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1192 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpStyleName
), -1,
1193 NULL
, 0, NULL
, NULL
);
1194 if(lpOTMW
->otmpFullName
)
1195 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1196 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFullName
), -1,
1197 NULL
, 0, NULL
, NULL
);
1205 DPRINT("needed = %u\n", needed
);
1208 /* Since the supplied buffer isn't big enough, we'll alloc one
1209 that is and memcpy the first cbData bytes into the lpOTM at
1211 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1218 ret
= output
->otmSize
= min(needed
, cbData
);
1219 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1220 output
->otmFiller
= 0;
1221 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1222 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1223 output
->otmfsType
= lpOTMW
->otmfsType
;
1224 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1225 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1226 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1227 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1228 output
->otmAscent
= lpOTMW
->otmAscent
;
1229 output
->otmDescent
= lpOTMW
->otmDescent
;
1230 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1231 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1232 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1233 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1234 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1235 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1236 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1237 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1238 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1239 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1240 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1241 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1242 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1243 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1244 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1245 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1248 ptr
= (char*)(output
+ 1);
1249 left
= needed
- sizeof(*output
);
1251 if(lpOTMW
->otmpFamilyName
)
1253 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1254 len
= WideCharToMultiByte(CP_ACP
, 0,
1255 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFamilyName
), -1,
1256 ptr
, left
, NULL
, NULL
);
1261 output
->otmpFamilyName
= 0;
1263 if(lpOTMW
->otmpFaceName
)
1265 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1266 len
= WideCharToMultiByte(CP_ACP
, 0,
1267 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFaceName
), -1,
1268 ptr
, left
, NULL
, NULL
);
1273 output
->otmpFaceName
= 0;
1275 if(lpOTMW
->otmpStyleName
)
1277 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1278 len
= WideCharToMultiByte(CP_ACP
, 0,
1279 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpStyleName
), -1,
1280 ptr
, left
, NULL
, NULL
);
1285 output
->otmpStyleName
= 0;
1287 if(lpOTMW
->otmpFullName
)
1289 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1290 len
= WideCharToMultiByte(CP_ACP
, 0,
1291 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFullName
), -1,
1292 ptr
, left
, NULL
, NULL
);
1296 output
->otmpFullName
= 0;
1302 memcpy(lpOTM
, output
, cbData
);
1303 HeapFree(GetProcessHeap(), 0, output
);
1305 /* check if the string offsets really fit into the provided size */
1306 /* FIXME: should we check string length as well? */
1307 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1308 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1310 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1311 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1313 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1314 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1316 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1317 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1321 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1322 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1327 /* Performs a device to world transformation on the specified size (which
1328 * is in integer format).
1330 static inline INT
INTERNAL_YDSTOWS(XFORM
*xForm
, INT height
)
1334 /* Perform operation with floating point */
1335 floatHeight
= (double)height
* xForm
->eM22
;
1336 /* Round to integers */
1337 return GDI_ROUND(floatHeight
);
1340 /* scale width and height but don't mirror them */
1341 static inline INT
width_to_LP( XFORM
*xForm
, INT width
)
1343 return GDI_ROUND( (double)width
* fabs( xForm
->eM11
));
1346 static inline INT
height_to_LP( XFORM
*xForm
, INT height
)
1348 return GDI_ROUND( (double)height
* fabs( xForm
->eM22
));
1356 GetOutlineTextMetricsW(
1359 LPOUTLINETEXTMETRICW lpOTM
1362 TMDIFF Tmd
; // Should not be zero.
1363 UINT Size
, AvailableSize
= 0, StringSize
;
1365 OUTLINETEXTMETRICW
* LocalOTM
;
1369 /* Get the structure */
1370 Size
= NtGdiGetOutlineTextMetricsInternalW(hdc
, 0, NULL
, &Tmd
);
1373 if (!lpOTM
|| (cbData
< sizeof(*lpOTM
)))
1376 LocalOTM
= HeapAlloc(GetProcessHeap(), 0, Size
);
1377 LocalOTM
->otmSize
= Size
;
1378 Size
= NtGdiGetOutlineTextMetricsInternalW(hdc
, Size
, LocalOTM
, &Tmd
);
1381 HeapFree(GetProcessHeap(), 0, LocalOTM
);
1385 if (!NtGdiGetTransform(hdc
, GdiDeviceSpaceToWorldSpace
, &DevToWorld
))
1387 DPRINT1("NtGdiGetTransform failed!\n");
1388 HeapFree(GetProcessHeap(), 0, LocalOTM
);
1389 SetLastError(ERROR_INVALID_HANDLE
);
1393 /* Fill in DC specific data */
1394 LocalOTM
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1395 LocalOTM
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1396 LocalOTM
->otmTextMetrics
.tmHeight
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmHeight
);
1397 LocalOTM
->otmTextMetrics
.tmAscent
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmAscent
);
1398 LocalOTM
->otmTextMetrics
.tmDescent
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmDescent
);
1399 LocalOTM
->otmTextMetrics
.tmInternalLeading
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmInternalLeading
);
1400 LocalOTM
->otmTextMetrics
.tmExternalLeading
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmExternalLeading
);
1401 LocalOTM
->otmTextMetrics
.tmAveCharWidth
= width_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmAveCharWidth
);
1402 LocalOTM
->otmTextMetrics
.tmMaxCharWidth
= width_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmMaxCharWidth
);
1403 LocalOTM
->otmTextMetrics
.tmOverhang
= width_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmOverhang
);
1404 LocalOTM
->otmAscent
= height_to_LP( &DevToWorld
, LocalOTM
->otmAscent
);
1405 LocalOTM
->otmDescent
= height_to_LP( &DevToWorld
, LocalOTM
->otmDescent
);
1406 LocalOTM
->otmLineGap
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmLineGap
));
1407 LocalOTM
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmsCapEmHeight
));
1408 LocalOTM
->otmsXHeight
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmsXHeight
));
1409 LocalOTM
->otmrcFontBox
.top
= height_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.top
);
1410 LocalOTM
->otmrcFontBox
.bottom
= height_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.bottom
);
1411 LocalOTM
->otmrcFontBox
.left
= width_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.left
);
1412 LocalOTM
->otmrcFontBox
.right
= width_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.right
);
1413 LocalOTM
->otmMacAscent
= height_to_LP( &DevToWorld
, LocalOTM
->otmMacAscent
);
1414 LocalOTM
->otmMacDescent
= height_to_LP( &DevToWorld
, LocalOTM
->otmMacDescent
);
1415 LocalOTM
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmMacLineGap
));
1416 LocalOTM
->otmptSubscriptSize
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptSize
.x
);
1417 LocalOTM
->otmptSubscriptSize
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptSize
.y
);
1418 LocalOTM
->otmptSubscriptOffset
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptOffset
.x
);
1419 LocalOTM
->otmptSubscriptOffset
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptOffset
.y
);
1420 LocalOTM
->otmptSuperscriptSize
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptSize
.x
);
1421 LocalOTM
->otmptSuperscriptSize
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptSize
.y
);
1422 LocalOTM
->otmptSuperscriptOffset
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptOffset
.x
);
1423 LocalOTM
->otmptSuperscriptOffset
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptOffset
.y
);
1424 LocalOTM
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmsStrikeoutSize
));
1425 LocalOTM
->otmsStrikeoutPosition
= height_to_LP( &DevToWorld
, LocalOTM
->otmsStrikeoutPosition
);
1426 LocalOTM
->otmsUnderscoreSize
= height_to_LP( &DevToWorld
, LocalOTM
->otmsUnderscoreSize
);
1427 LocalOTM
->otmsUnderscorePosition
= height_to_LP( &DevToWorld
, LocalOTM
->otmsUnderscorePosition
);
1429 /* Copy what we can */
1430 CopyMemory(lpOTM
, LocalOTM
, min(Size
, cbData
));
1432 lpOTM
->otmpFamilyName
= NULL
;
1433 lpOTM
->otmpFaceName
= NULL
;
1434 lpOTM
->otmpStyleName
= NULL
;
1435 lpOTM
->otmpFullName
= NULL
;
1437 Size
= sizeof(*lpOTM
);
1438 AvailableSize
= cbData
- Size
;
1439 Ptr
= (BYTE
*)lpOTM
+ sizeof(*lpOTM
);
1441 /* Fix string values up */
1442 if (LocalOTM
->otmpFamilyName
)
1444 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpFamilyName
);
1445 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1446 if (AvailableSize
>= StringSize
)
1448 CopyMemory(Ptr
, Str
, StringSize
);
1449 lpOTM
->otmpFamilyName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1451 AvailableSize
-= StringSize
;
1456 if (LocalOTM
->otmpFaceName
)
1458 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpFaceName
);
1459 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1460 if (AvailableSize
>= StringSize
)
1462 CopyMemory(Ptr
, Str
, StringSize
);
1463 lpOTM
->otmpFaceName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1465 AvailableSize
-= StringSize
;
1470 if (LocalOTM
->otmpStyleName
)
1472 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpStyleName
);
1473 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1474 if (AvailableSize
>= StringSize
)
1476 CopyMemory(Ptr
, Str
, StringSize
);
1477 lpOTM
->otmpStyleName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1479 AvailableSize
-= StringSize
;
1484 if (LocalOTM
->otmpFullName
)
1486 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpFullName
);
1487 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1488 if (AvailableSize
>= StringSize
)
1490 CopyMemory(Ptr
, Str
, StringSize
);
1491 lpOTM
->otmpFullName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1493 AvailableSize
-= StringSize
;
1498 lpOTM
->otmSize
= Size
;
1500 HeapFree(GetProcessHeap(), 0, LocalOTM
);
1510 GetKerningPairsW(HDC hdc
,
1512 LPKERNINGPAIR pkpDst
)
1514 if ((cPairs
!= 0) || (pkpDst
== 0))
1516 return NtGdiGetKerningPairs(hdc
,cPairs
,pkpDst
);
1520 SetLastError(ERROR_INVALID_PARAMETER
);
1530 GetKerningPairsA( HDC hDC
,
1532 LPKERNINGPAIR kern_pairA
)
1537 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
1538 KERNINGPAIR
*kern_pairW
;
1540 if (!cPairs
&& kern_pairA
)
1542 SetLastError(ERROR_INVALID_PARAMETER
);
1546 charset
= GetTextCharset(hDC
);
1547 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
1549 DPRINT1("Can't find codepage for charset %d\n", charset
);
1552 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1553 * to fail on an invalid character for CP_SYMBOL.
1555 cpi
.DefaultChar
[0] = 0;
1556 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
1558 DPRINT1("Can't find codepage %u info\n", csi
.ciACP
);
1561 DPRINT("charset %d => codepage %u\n", charset
, csi
.ciACP
);
1563 total_kern_pairs
= NtGdiGetKerningPairs(hDC
, 0, NULL
);
1564 if (!total_kern_pairs
) return 0;
1566 if (!cPairs
&& !kern_pairA
) return total_kern_pairs
;
1568 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
1569 if (kern_pairW
== NULL
)
1573 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
1575 for (i
= 0; i
< total_kern_pairs
; i
++)
1579 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
1582 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
1585 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
1590 if (kern_pairs_copied
>= cPairs
) break;
1592 kern_pairA
->wFirst
= (BYTE
)first
;
1593 kern_pairA
->wSecond
= (BYTE
)second
;
1594 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
1597 kern_pairs_copied
++;
1600 HeapFree(GetProcessHeap(), 0, kern_pairW
);
1602 return kern_pairs_copied
;
1612 CreateFontIndirectExA(const ENUMLOGFONTEXDVA
*elfexd
)
1616 ENUMLOGFONTEXDVW Logfont
;
1618 EnumLogFontExW2A( (LPENUMLOGFONTEXA
) elfexd
,
1619 &Logfont
.elfEnumLogfontEx
);
1621 RtlCopyMemory( &Logfont
.elfDesignVector
,
1622 (PVOID
) &elfexd
->elfDesignVector
,
1623 sizeof(DESIGNVECTOR
));
1625 return NtGdiHfontCreate( &Logfont
, 0, 0, 0, NULL
);
1636 CreateFontIndirectExW(const ENUMLOGFONTEXDVW
*elfexd
)
1638 /* Msdn: Note, this function ignores the elfDesignVector member in
1643 return NtGdiHfontCreate((PENUMLOGFONTEXDVW
) elfexd
, 0, 0, 0, NULL
);
1654 CreateFontIndirectA(
1655 CONST LOGFONTA
*lplf
1662 LogFontA2W(&tlf
, lplf
);
1663 return CreateFontIndirectW(&tlf
);
1674 CreateFontIndirectW(
1675 CONST LOGFONTW
*lplf
1680 ENUMLOGFONTEXDVW Logfont
;
1682 RtlCopyMemory( &Logfont
.elfEnumLogfontEx
.elfLogFont
, lplf
, sizeof(LOGFONTW
));
1683 // Need something other than just cleaning memory here.
1684 // Guess? Use caller data to determine the rest.
1685 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfFullName
,
1686 sizeof(Logfont
.elfEnumLogfontEx
.elfFullName
));
1687 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfStyle
,
1688 sizeof(Logfont
.elfEnumLogfontEx
.elfStyle
));
1689 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfScript
,
1690 sizeof(Logfont
.elfEnumLogfontEx
.elfScript
));
1692 Logfont
.elfDesignVector
.dvNumAxes
= 0; // No more than MM_MAX_NUMAXES
1694 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
1696 return CreateFontIndirectExW(&Logfont
);
1717 DWORD fdwOutputPrecision
,
1718 DWORD fdwClipPrecision
,
1720 DWORD fdwPitchAndFamily
,
1724 ANSI_STRING StringA
;
1725 UNICODE_STRING StringU
;
1728 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
1729 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
1731 ret
= CreateFontW(nHeight
,
1746 RtlFreeUnicodeString(&StringU
);
1767 DWORD fdwOutputPrecision
,
1768 DWORD fdwClipPrecision
,
1770 DWORD fdwPitchAndFamily
,
1776 logfont
.lfHeight
= nHeight
;
1777 logfont
.lfWidth
= nWidth
;
1778 logfont
.lfEscapement
= nEscapement
;
1779 logfont
.lfOrientation
= nOrientation
;
1780 logfont
.lfWeight
= nWeight
;
1781 logfont
.lfItalic
= (BYTE
)fnItalic
;
1782 logfont
.lfUnderline
= (BYTE
)fdwUnderline
;
1783 logfont
.lfStrikeOut
= (BYTE
)fdwStrikeOut
;
1784 logfont
.lfCharSet
= (BYTE
)fdwCharSet
;
1785 logfont
.lfOutPrecision
= (BYTE
)fdwOutputPrecision
;
1786 logfont
.lfClipPrecision
= (BYTE
)fdwClipPrecision
;
1787 logfont
.lfQuality
= (BYTE
)fdwQuality
;
1788 logfont
.lfPitchAndFamily
= (BYTE
)fdwPitchAndFamily
;
1790 if (NULL
!= lpszFace
)
1792 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
1793 wcsncpy((wchar_t *)logfont
.lfFaceName
, lpszFace
, Size
- 1);
1794 /* Be 101% sure to have '\0' at end of string */
1795 logfont
.lfFaceName
[Size
- 1] = '\0';
1799 logfont
.lfFaceName
[0] = L
'\0';
1802 return CreateFontIndirectW(&logfont
);
1811 CreateScalableFontResourceA(
1814 LPCSTR lpszFontFile
,
1815 LPCSTR lpszCurrentPath
1827 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1829 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1831 SetLastError( ERROR_INVALID_PARAMETER
);
1835 return GdiAddFontResourceW(lpszFilename
, fl
,0);
1844 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1850 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1852 SetLastError( ERROR_INVALID_PARAMETER
);
1856 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1857 if ( !NT_SUCCESS (Status
) )
1859 SetLastError (RtlNtStatusToDosError(Status
));
1863 rc
= GdiAddFontResourceW ( FilenameW
, fl
, 0 );
1864 HEAP_free ( FilenameW
);
1874 AddFontResourceA ( LPCSTR lpszFilename
)
1880 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1881 if ( !NT_SUCCESS (Status
) )
1883 SetLastError (RtlNtStatusToDosError(Status
));
1887 rc
= GdiAddFontResourceW ( FilenameW
, 0, 0);
1889 HEAP_free ( FilenameW
);
1900 AddFontResourceW ( LPCWSTR lpszFilename
)
1902 return GdiAddFontResourceW ( lpszFilename
, 0, 0 );
1911 RemoveFontResourceW(LPCWSTR lpFileName
)
1913 return RemoveFontResourceExW(lpFileName
,0,0);
1922 RemoveFontResourceA(LPCSTR lpFileName
)
1924 return RemoveFontResourceExA(lpFileName
,0,0);
1932 RemoveFontResourceExA(LPCSTR lpFileName
,
1940 /* FIXME the flags */
1942 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1944 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
1945 if (!NT_SUCCESS (Status
))
1946 SetLastError (RtlNtStatusToDosError(Status
));
1950 HEAP_free ( lpFileNameW
);
1961 RemoveFontResourceExW(LPCWSTR lpFileName
,
1965 /* FIXME the flags */
1967 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
1968 DPRINT("RemoveFontResourceExW\n");
1973 /***********************************************************************
1974 * GdiGetCharDimensions
1976 * Gets the average width of the characters in the English alphabet.
1979 * hdc [I] Handle to the device context to measure on.
1980 * lptm [O] Pointer to memory to store the text metrics into.
1981 * height [O] On exit, the maximum height of characters in the English alphabet.
1984 * The average width of characters in the English alphabet.
1987 * This function is used by the dialog manager to get the size of a dialog
1988 * unit. It should also be used by other pieces of code that need to know
1989 * the size of a dialog unit in logical units without having access to the
1990 * window handle of the dialog.
1991 * Windows caches the font metrics from this function, but we don't and
1992 * there doesn't appear to be an immediate advantage to do so.
1995 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
1997 * Despite most of MSDN insisting that the horizontal base unit is
1998 * tmAveCharWidth it isn't. Knowledge base article Q145994
1999 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
2000 * says that we should take the average of the 52 English upper and lower
2008 GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
2012 static const WCHAR alphabet
[] =
2014 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2015 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2016 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0
2019 if(!GetTextMetricsW(hdc
, &tm
)) return 0;
2021 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
2023 if (lptm
) *lptm
= tm
;
2024 if (height
) *height
= tm
.tmHeight
;
2026 return (sz
.cx
/ 26 + 1) / 2;
2029 /*************************************************************************
2030 * TranslateCharsetInfo [GDI32.@]
2032 * Fills a CHARSETINFO structure for a character set, code page, or
2033 * font. This allows making the correspondance between different labelings
2034 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2035 * of the same encoding.
2037 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2038 * only one codepage should be set in *lpSrc.
2041 * TRUE on success, FALSE on failure.
2049 TranslateCharsetInfo(
2050 LPDWORD lpSrc
, /* [in]
2051 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2052 if flags == TCI_SRCCHARSET: a character set value
2053 if flags == TCI_SRCCODEPAGE: a code page value
2055 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2056 DWORD flags
/* [in] determines interpretation of lpSrc */)
2061 case TCI_SRCFONTSIG
:
2062 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2064 case TCI_SRCCODEPAGE
:
2065 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2067 case TCI_SRCCHARSET
:
2068 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2072 LCID lCid
= (LCID
)PtrToUlong(lpSrc
);
2073 LOCALESIGNATURE LocSig
;
2074 INT Ret
= GetLocaleInfoW(lCid
, LOCALE_FONTSIGNATURE
, (LPWSTR
)&LocSig
, 0);
2075 if ( GetLocaleInfoW(lCid
, LOCALE_FONTSIGNATURE
, (LPWSTR
)&LocSig
, Ret
))
2077 while (index
< MAXTCIINDEX
&& !(LocSig
.lsCsbDefault
[0]>>index
& 0x0001)) index
++;
2082 GdiSetLastError(ERROR_INVALID_PARAMETER
);
2085 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2086 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n",
2087 index
,FONT_tci
[index
].ciCharset
,FONT_tci
[index
].ciACP
,FONT_tci
[index
].fs
.fsCsb
[0]);
2088 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2103 DWORD Ret
= GDI_ERROR
;
2106 if (GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_DC
)
2108 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_METADC
)
2109 return MFDRV_SetMapperFlags( hDC
, flags
);
2112 PLDC pLDC
= Dc_Attr
->pvLDC
;
2115 SetLastError(ERROR_INVALID_HANDLE
);
2118 if (pLDC
->iType
== LDC_EMFLDC
)
2120 return EMFDRV_SetMapperFlags( hDC
, flags
);
2125 if (!GdiGetHandleUserData((HGDIOBJ
) hDC
, GDI_OBJECT_TYPE_DC
, (PVOID
) &Dc_Attr
)) return GDI_ERROR
;
2127 if (NtCurrentTeb()->GdiTebBatch
.HDC
== hDC
)
2129 if (Dc_Attr
->ulDirty_
& DC_FONTTEXT_DIRTY
)
2132 Dc_Attr
->ulDirty_
&= ~(DC_MODE_DIRTY
|DC_FONTTEXT_DIRTY
);
2137 SetLastError(ERROR_INVALID_PARAMETER
);
2140 Ret
= Dc_Attr
->flFontMapper
;
2141 Dc_Attr
->flFontMapper
= flags
;
2155 FONTENUMPROCW FontFunc
,
2160 return NtGdiEnumFonts ( hDC
, lpFaceName
, FontFunc
, lParam
);
2162 return EnumFontFamiliesW( hDC
, lpFaceName
, FontFunc
, lParam
);
2174 FONTENUMPROCA FontFunc
,
2183 Status
= HEAP_strdupA2W ( &lpFaceNameW
, lpFaceName
);
2184 if (!NT_SUCCESS (Status
))
2185 SetLastError (RtlNtStatusToDosError(Status
));
2188 rc
= NtGdiEnumFonts ( hDC
, lpFaceNameW
, FontFunc
, lParam
);
2190 HEAP_free ( lpFaceNameW
);
2194 return EnumFontFamiliesA( hDC
, lpFaceName
, FontFunc
, lParam
);
2198 #define EfdFontFamilies 3
2202 NewEnumFontFamiliesExW(
2204 LPLOGFONTW lpLogfont
,
2205 FONTENUMPROCW lpEnumFontFamExProcW
,
2210 ULONG cbDataSize
, cbRetSize
;
2211 PENUMFONTDATAW pEfdw
;
2216 /* Open enumeration handle and find out how much memory we need */
2217 idEnum
= NtGdiEnumFontOpen(hDC
,
2221 (lpLogfont
&& lpLogfont
->lfFaceName
[0])? lpLogfont
->lfFaceName
: NULL
,
2222 lpLogfont
? lpLogfont
->lfCharSet
: DEFAULT_CHARSET
,
2228 if (cbDataSize
== 0)
2230 NtGdiEnumFontClose(idEnum
);
2234 /* Allocate memory */
2235 pBuffer
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
2236 if (pBuffer
== NULL
)
2238 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2239 NtGdiEnumFontClose(idEnum
);
2243 /* Do the enumeration */
2244 if (!NtGdiEnumFontChunk(hDC
, idEnum
, cbDataSize
, &cbRetSize
, (PVOID
)pBuffer
))
2246 HeapFree(GetProcessHeap(), 0, pBuffer
);
2247 NtGdiEnumFontClose(idEnum
);
2251 /* Get start and end address */
2252 pEfdw
= (PENUMFONTDATAW
)pBuffer
;
2253 pMax
= pBuffer
+ cbDataSize
;
2255 /* Iterate through the structures */
2256 while ((PBYTE
)pEfdw
< pMax
&& ret
)
2258 PNTMW_INTERNAL pNtmwi
= (PNTMW_INTERNAL
)((ULONG_PTR
)pEfdw
+ pEfdw
->ulNtmwiOffset
);
2260 ret
= lpEnumFontFamExProcW((VOID
*)&pEfdw
->elfexdv
.elfEnumLogfontEx
,
2261 (VOID
*)&pNtmwi
->ntmw
,
2265 pEfdw
= (PENUMFONTDATAW
)((ULONG_PTR
)pEfdw
+ pEfdw
->cbSize
);
2268 /* Release the memory and close handle */
2269 HeapFree(GetProcessHeap(), 0, pBuffer
);
2270 NtGdiEnumFontClose(idEnum
);
2280 GdiAddFontResourceW(
2281 LPCWSTR lpszFilename
,
2286 WCHAR lpszBuffer
[MAX_PATH
];
2287 WCHAR lpszAbsPath
[MAX_PATH
];
2288 UNICODE_STRING NtAbsPath
;
2290 /* FIXME: We don't support multiple files passed in lpszFilename
2291 * as L"abcxxxxx.pfm|abcxxxxx.pfb"
2294 /* Does the file exist in CurrentDirectory or in the Absolute Path passed? */
2295 GetCurrentDirectoryW(MAX_PATH
, lpszBuffer
);
2297 if (!SearchPathW(lpszBuffer
, lpszFilename
, NULL
, MAX_PATH
, lpszAbsPath
, NULL
))
2299 /* Nope. Then let's check Fonts folder */
2300 GetWindowsDirectoryW(lpszBuffer
, MAX_PATH
);
2301 StringCbCatW(lpszBuffer
, sizeof(lpszBuffer
), L
"\\Fonts");
2303 if (!SearchPathW(lpszBuffer
, lpszFilename
, NULL
, MAX_PATH
, lpszAbsPath
, NULL
))
2305 DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer
, lpszFilename
);
2310 /* We found the font file so: */
2311 if (!RtlDosPathNameToNtPathName_U(lpszAbsPath
, &NtAbsPath
, NULL
, NULL
))
2313 DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath
);
2317 /* The Nt call expects a null-terminator included in cwc param. */
2318 ASSERT(NtAbsPath
.Buffer
[NtAbsPath
.Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
2319 Ret
= NtGdiAddFontResourceW(NtAbsPath
.Buffer
, NtAbsPath
.Length
/ sizeof(WCHAR
) + 1, 1, fl
, 0, pdv
);
2321 RtlFreeUnicodeString(&NtAbsPath
);
2331 AddFontMemResourceEx(
2338 if ( pbFont
&& cbFont
&& pcFonts
)
2340 return NtGdiAddFontMemResourceEx(pbFont
, cbFont
, NULL
, 0, pcFonts
);
2342 SetLastError(ERROR_INVALID_PARAMETER
);
2351 RemoveFontMemResourceEx(HANDLE fh
)
2355 return NtGdiRemoveFontMemResourceEx(fh
);
2357 SetLastError(ERROR_INVALID_PARAMETER
);
2367 AddFontResourceTracking(
2373 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2382 RemoveFontResourceTracking(LPCSTR lpString
,int unknown
)
2385 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2391 CreateScalableFontResourceW(
2393 LPCWSTR lpszFontRes
,
2394 LPCWSTR lpszFontFile
,
2395 LPCWSTR lpszCurrentPath
2402 /* fHidden=1 - only visible for the calling app, read-only, not
2403 * enumerated with EnumFonts/EnumFontFamilies
2404 * lpszCurrentPath can be NULL
2407 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2408 if ((f
= CreateFileW(lpszFontRes
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
)
2411 SetLastError(ERROR_FILE_EXISTS
);
2414 return FALSE
; /* create failed */
2422 bInitSystemAndFontsDirectoriesW(LPWSTR
*SystemDir
,LPWSTR
*FontsDir
)
2425 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2434 EudcLoadLinkW(LPCWSTR pBaseFaceName
,LPCWSTR pEudcFontPath
,INT iPriority
,INT iFontLinkType
)
2437 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2446 EudcUnloadLinkW(LPCWSTR pBaseFaceName
,LPCWSTR pEudcFontPath
)
2449 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2458 GetEUDCTimeStamp(VOID
)
2460 return NtGdiGetEudcTimeStampEx(NULL
,0,TRUE
);
2468 GetEUDCTimeStampExW(LPWSTR lpBaseFaceName
)
2472 if (!lpBaseFaceName
)
2474 retValue
= NtGdiGetEudcTimeStampEx(NULL
,0,FALSE
);
2478 retValue
= NtGdiGetEudcTimeStampEx(lpBaseFaceName
, wcslen(lpBaseFaceName
), FALSE
);
2489 GetFontAssocStatus(HDC hdc
)
2495 retValue
= NtGdiQueryFontAssocInfo(hdc
);
2506 QueryFontAssocStatus(VOID
)
2509 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2518 UnloadNetworkFonts(DWORD unknown
)
2521 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2530 GetFontData(HDC hdc
,
2540 return NtGdiGetFontData(hdc
, dwTable
, dwOffset
, lpvBuffer
, cbData
);
2545 cGetTTFFromFOT(DWORD x1
,DWORD x2
,DWORD x3
, DWORD x4
, DWORD x5
, DWORD x6
, DWORD x7
)
2548 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);