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_CHARSET
)
223 if (plf1
->lfCharSet
< plf2
->lfCharSet
)
225 if (plf1
->lfCharSet
> plf2
->lfCharSet
)
228 if (dwCompareFlags
& IFFCX_STYLE
)
230 WeightDiff1
= labs(plf1
->lfWeight
- FW_NORMAL
);
231 WeightDiff2
= labs(plf2
->lfWeight
- FW_NORMAL
);
232 if (WeightDiff1
< WeightDiff2
)
234 if (WeightDiff1
> WeightDiff2
)
236 if (plf1
->lfItalic
< plf2
->lfItalic
)
238 if (plf1
->lfItalic
> plf2
->lfItalic
)
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
;
268 last
= &InfoList
[nCount
];
270 /* std::unique(first, last, IntFontFamilyCompareEx); */
275 while (++first
!= last
)
277 if (IntFontFamilyCompareEx(result
, first
, dwCompareFlags
) != 0)
279 *(++result
) = *first
;
282 nCount
= (int)(++result
- InfoList
);
288 IntEnumFontFamilies(HDC Dc
, const LOGFONTW
*LogFont
, PVOID EnumProc
, LPARAM lParam
,
292 PFONTFAMILYINFO Info
;
295 ENUMLOGFONTEXA EnumLogFontExA
;
296 NEWTEXTMETRICEXA NewTextMetricExA
;
302 DataSize
= INITIAL_FAMILY_COUNT
* sizeof(FONTFAMILYINFO
);
303 Info
= RtlAllocateHeap(GetProcessHeap(), 0, DataSize
);
309 /* Initialize the LOGFONT structure */
310 ZeroMemory(&lfW
, sizeof(lfW
));
313 lfW
.lfCharSet
= DEFAULT_CHARSET
;
317 lfW
.lfCharSet
= LogFont
->lfCharSet
;
318 lfW
.lfPitchAndFamily
= LogFont
->lfPitchAndFamily
;
319 StringCbCopyW(lfW
.lfFaceName
, sizeof(lfW
.lfFaceName
), LogFont
->lfFaceName
);
322 /* Retrieve the font information */
323 InfoCount
= INITIAL_FAMILY_COUNT
;
324 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, &lfW
, Info
, &InfoCount
);
325 if (FontFamilyCount
< 0)
327 RtlFreeHeap(GetProcessHeap(), 0, Info
);
331 /* Resize the buffer if the buffer is too small */
332 if (INITIAL_FAMILY_COUNT
< InfoCount
)
334 RtlFreeHeap(GetProcessHeap(), 0, Info
);
336 Status
= RtlULongMult(InfoCount
, sizeof(FONTFAMILYINFO
), &DataSize
);
337 if (!NT_SUCCESS(Status
) || DataSize
> LONG_MAX
)
339 DPRINT1("Overflowed.\n");
342 Info
= RtlAllocateHeap(GetProcessHeap(), 0, DataSize
);
347 FontFamilyCount
= NtGdiGetFontFamilyInfo(Dc
, &lfW
, Info
, &InfoCount
);
348 if (FontFamilyCount
< 0 || FontFamilyCount
< InfoCount
)
350 RtlFreeHeap(GetProcessHeap(), 0, Info
);
355 /* Sort and remove redundant information */
356 qsort(Info
, FontFamilyCount
, sizeof(*Info
), IntFontFamilyCompare
);
357 FontFamilyCount
= IntFontFamilyListUnique(Info
, FontFamilyCount
, &lfW
, dwFlags
);
359 /* call the callback */
360 for (i
= 0; i
< FontFamilyCount
; i
++)
362 if (dwFlags
& IEFF_UNICODE
)
364 Ret
= ((FONTENUMPROCW
) EnumProc
)(
365 (VOID
*)&Info
[i
].EnumLogFontEx
,
366 (VOID
*)&Info
[i
].NewTextMetricEx
,
367 Info
[i
].FontType
, lParam
);
371 // Could use EnumLogFontExW2A here?
372 LogFontW2A(&EnumLogFontExA
.elfLogFont
, &Info
[i
].EnumLogFontEx
.elfLogFont
);
373 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfFullName
, -1,
374 (LPSTR
)EnumLogFontExA
.elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
375 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfStyle
, -1,
376 (LPSTR
)EnumLogFontExA
.elfStyle
, LF_FACESIZE
, NULL
, NULL
);
377 WideCharToMultiByte(CP_THREAD_ACP
, 0, Info
[i
].EnumLogFontEx
.elfScript
, -1,
378 (LPSTR
)EnumLogFontExA
.elfScript
, LF_FACESIZE
, NULL
, NULL
);
379 NewTextMetricExW2A(&NewTextMetricExA
,
380 &Info
[i
].NewTextMetricEx
);
381 Ret
= ((FONTENUMPROCA
) EnumProc
)(
382 (VOID
*)&EnumLogFontExA
,
383 (VOID
*)&NewTextMetricExA
,
384 Info
[i
].FontType
, lParam
);
391 RtlFreeHeap(GetProcessHeap(), 0, Info
);
400 EnumFontFamiliesExW(HDC hdc
, LPLOGFONTW lpLogfont
, FONTENUMPROCW lpEnumFontFamExProc
,
401 LPARAM lParam
, DWORD dwFlags
)
405 DPRINT("EnumFontFamiliesExW(%p, %p(%S, %u, %u), %p, %p, 0x%08lX)\n",
406 hdc
, lpLogfont
, lpLogfont
->lfFaceName
, lpLogfont
->lfCharSet
,
407 lpLogfont
->lfPitchAndFamily
, lpEnumFontFamExProc
, lParam
, dwFlags
);
411 DPRINT("EnumFontFamiliesExW(%p, NULL, %p, %p, 0x%08lX)\n",
412 hdc
, lpEnumFontFamExProc
, lParam
, dwFlags
);
414 return IntEnumFontFamilies(hdc
, lpLogfont
, lpEnumFontFamExProc
, lParam
,
415 IEFF_UNICODE
| IEFF_EXTENDED
);
423 EnumFontFamiliesW(HDC hdc
, LPCWSTR lpszFamily
, FONTENUMPROCW lpEnumFontFamProc
,
428 DPRINT("EnumFontFamiliesW(%p, %S, %p, %p)\n",
429 hdc
, lpszFamily
, lpEnumFontFamProc
, lParam
);
431 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
432 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
433 if (NULL
!= lpszFamily
)
435 if (!*lpszFamily
) return 1;
436 lstrcpynW(LogFont
.lfFaceName
, lpszFamily
, LF_FACESIZE
);
439 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, IEFF_UNICODE
);
447 EnumFontFamiliesExA (HDC hdc
, LPLOGFONTA lpLogfont
, FONTENUMPROCA lpEnumFontFamExProc
,
448 LPARAM lParam
, DWORD dwFlags
)
450 LOGFONTW LogFontW
, *pLogFontW
;
454 DPRINT("EnumFontFamiliesExA(%p, %p(%s, %u, %u), %p, %p, 0x%08lX)\n",
455 hdc
, lpLogfont
, lpLogfont
->lfFaceName
, lpLogfont
->lfCharSet
,
456 lpLogfont
->lfPitchAndFamily
, lpEnumFontFamExProc
, lParam
, dwFlags
);
460 DPRINT("EnumFontFamiliesExA(%p, NULL, %p, %p, 0x%08lX)\n",
461 hdc
, lpEnumFontFamExProc
, lParam
, dwFlags
);
466 LogFontA2W(&LogFontW
,lpLogfont
);
467 pLogFontW
= &LogFontW
;
469 else pLogFontW
= NULL
;
471 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */
472 return IntEnumFontFamilies(hdc
, pLogFontW
, lpEnumFontFamExProc
, lParam
, IEFF_EXTENDED
);
480 EnumFontFamiliesA(HDC hdc
, LPCSTR lpszFamily
, FONTENUMPROCA lpEnumFontFamProc
,
485 DPRINT("EnumFontFamiliesA(%p, %s, %p, %p)\n",
486 hdc
, lpszFamily
, lpEnumFontFamProc
, lParam
);
488 ZeroMemory(&LogFont
, sizeof(LOGFONTW
));
489 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
490 if (NULL
!= lpszFamily
)
492 if (!*lpszFamily
) return 1;
493 MultiByteToWideChar(CP_THREAD_ACP
, 0, lpszFamily
, -1, LogFont
.lfFaceName
, LF_FACESIZE
);
496 return IntEnumFontFamilies(hdc
, &LogFont
, lpEnumFontFamProc
, lParam
, 0);
505 GetCharacterPlacementA(
510 GCP_RESULTSA
*lpResults
,
515 GCP_RESULTSW resultsW
;
519 if ( !lpString
|| uCount
<= 0 || !lpResults
|| (nMaxExtent
< 0 && nMaxExtent
!= -1 ) )
521 SetLastError(ERROR_INVALID_PARAMETER
);
524 /* TRACE("%s, %d, %d, 0x%08x\n",
525 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
527 /* both structs are equal in size */
528 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
530 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
531 if (lpStringW
== NULL
)
535 if(lpResults
->lpOutString
)
537 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
538 if (resultsW
.lpOutString
== NULL
)
540 HeapFree(GetProcessHeap(), 0, lpStringW
);
545 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
547 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
548 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
550 if(lpResults
->lpOutString
)
552 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
553 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
556 HeapFree(GetProcessHeap(), 0, lpStringW
);
557 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
568 GetCharacterPlacementW(
573 GCP_RESULTSW
*lpResults
,
580 DPRINT("GetCharacterPlacementW\n");
582 if (dwFlags
&(~GCP_REORDER
)) DPRINT("flags 0x%08lx ignored\n", dwFlags
);
583 if (lpResults
->lpClass
) DPRINT("classes not implemented\n");
586 if (nSet
> lpResults
->nGlyphs
)
587 nSet
= lpResults
->nGlyphs
;
589 /* return number of initialized fields */
590 lpResults
->nGlyphs
= nSet
;
592 if (dwFlags
& GCP_REORDER
)
594 if (LoadLPK(LPK_GCP
))
595 return LpkGetCharacterPlacement(hdc
, lpString
, uCount
, nMaxExtent
, lpResults
, dwFlags
, 0);
598 /* Treat the case where no special handling was requested in a fastpath way */
599 /* copy will do if the GCP_REORDER flag is not set */
600 if (lpResults
->lpOutString
)
601 lstrcpynW( lpResults
->lpOutString
, lpString
, nSet
);
603 if (lpResults
->lpOrder
)
605 for (i
= 0; i
< nSet
; i
++)
606 lpResults
->lpOrder
[i
] = i
;
609 /* FIXME: Will use the placement chars */
613 for (i
= 0; i
< nSet
; i
++)
615 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
616 lpResults
->lpDx
[i
]= c
;
620 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
624 lpResults
->lpCaretPos
[0] = 0;
625 for (i
= 1; i
< nSet
; i
++)
626 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
627 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
630 if (lpResults
->lpGlyphs
)
631 NtGdiGetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
633 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
634 ret
= MAKELONG(size
.cx
, size
.cy
);
641 NewGetCharacterPlacementW(
646 GCP_RESULTSW
*lpResults
,
653 if ( !lpString
|| uCount
<= 0 || (nMaxExtent
< 0 && nMaxExtent
!= -1 ) )
655 SetLastError(ERROR_INVALID_PARAMETER
);
661 if ( GetTextExtentPointW(hdc
, lpString
, uCount
, &Size
) )
663 return MAKELONG(Size
.cx
, Size
.cy
);
669 if ( nSet
> lpResults
->nGlyphs
)
670 nSet
= lpResults
->nGlyphs
;
672 return NtGdiGetCharacterPlacementW( hdc
,
686 GetCharABCWidthsFloatW(HDC hdc
,
691 DPRINT("GetCharABCWidthsFloatW\n");
692 if ((!abcF
) || (FirstChar
> LastChar
))
694 SetLastError(ERROR_INVALID_PARAMETER
);
697 return NtGdiGetCharABCWidthsW( hdc
,
699 (ULONG
)(LastChar
- FirstChar
+ 1),
711 GetCharWidthFloatW(HDC hdc
,
716 DPRINT("GetCharWidthsFloatW\n");
717 if ((!pxBuffer
) || (iFirstChar
> iLastChar
))
719 SetLastError(ERROR_INVALID_PARAMETER
);
722 return NtGdiGetCharWidthW( hdc
,
724 (ULONG
)(iLastChar
- iFirstChar
+ 1),
736 GetCharWidthW(HDC hdc
,
741 DPRINT("GetCharWidthsW\n");
742 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
744 SetLastError(ERROR_INVALID_PARAMETER
);
747 return NtGdiGetCharWidthW( hdc
,
749 (ULONG
)(iLastChar
- iFirstChar
+ 1),
761 GetCharWidth32W(HDC hdc
,
766 DPRINT("GetCharWidths32W\n");
767 if ((!lpBuffer
) || (iFirstChar
> iLastChar
))
769 SetLastError(ERROR_INVALID_PARAMETER
);
772 return NtGdiGetCharWidthW( hdc
,
774 (ULONG
)(iLastChar
- iFirstChar
+ 1),
776 GCW_NOFLOAT
|GCW_WIN32
,
787 GetCharABCWidthsW(HDC hdc
,
792 DPRINT("GetCharABCWidthsW\n");
793 if ((!lpabc
) || (FirstChar
> LastChar
))
795 SetLastError(ERROR_INVALID_PARAMETER
);
798 return NtGdiGetCharABCWidthsW( hdc
,
800 (ULONG
)(LastChar
- FirstChar
+ 1),
823 DPRINT("GetCharWidthsA\n");
825 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
829 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
832 HeapFree(GetProcessHeap(), 0, str
);
836 ret
= NtGdiGetCharWidthW( hdc
,
843 HeapFree(GetProcessHeap(), 0, str
);
844 HeapFree(GetProcessHeap(), 0, wstr
);
866 DPRINT("GetCharWidths32A\n");
868 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
872 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
875 HeapFree(GetProcessHeap(), 0, str
);
879 ret
= NtGdiGetCharWidthW( hdc
,
883 GCW_NOFLOAT
|GCW_WIN32
,
886 HeapFree(GetProcessHeap(), 0, str
);
887 HeapFree(GetProcessHeap(), 0, wstr
);
909 DPRINT("GetCharWidthsFloatA\n");
911 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
915 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
918 HeapFree(GetProcessHeap(), 0, str
);
921 ret
= NtGdiGetCharWidthW( hdc
, wstr
[0], (ULONG
) count
, (PWCHAR
) wstr
, 0, (PVOID
) pxBuffer
);
923 HeapFree(GetProcessHeap(), 0, str
);
924 HeapFree(GetProcessHeap(), 0, wstr
);
946 DPRINT("GetCharABCWidthsA\n");
948 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
952 wstr
= FONT_mbtowc(hdc
, str
, count
+1, &wlen
, NULL
);
955 HeapFree(GetProcessHeap(), 0, str
);
959 ret
= NtGdiGetCharABCWidthsW( hdc
,
966 HeapFree(GetProcessHeap(), 0, str
);
967 HeapFree(GetProcessHeap(), 0, wstr
);
977 GetCharABCWidthsFloatA(
989 DPRINT("GetCharABCWidthsFloatA\n");
991 str
= FONT_GetCharsByRangeA(hdc
, iFirstChar
, iLastChar
, &count
);
995 wstr
= FONT_mbtowc( hdc
, str
, count
+1, &wlen
, NULL
);
998 HeapFree( GetProcessHeap(), 0, str
);
1001 ret
= NtGdiGetCharABCWidthsW( hdc
,wstr
[0],(ULONG
)count
, (PWCHAR
)wstr
, 0, (PVOID
)lpABCF
);
1003 HeapFree( GetProcessHeap(), 0, str
);
1004 HeapFree( GetProcessHeap(), 0, wstr
);
1014 GetCharABCWidthsI(HDC hdc
,
1020 DPRINT("GetCharABCWidthsI\n");
1021 return NtGdiGetCharABCWidthsW( hdc
,
1025 GCABCW_NOFLOAT
|GCABCW_INDICES
,
1034 GetCharWidthI(HDC hdc
,
1041 DPRINT("GetCharWidthsI\n");
1042 if (!lpBuffer
|| (!pgi
&& (giFirst
== MAXUSHORT
))) // Cannot be at max.
1044 SetLastError(ERROR_INVALID_PARAMETER
);
1047 if (!cgi
) return TRUE
;
1048 return NtGdiGetCharWidthW( hdc
,
1052 GCW_INDICES
|GCW_NOFLOAT
|GCW_WIN32
,
1061 GetFontLanguageInfo(
1065 DWORD Gcp
= 0, Ret
= 0;
1068 Ret
= NtGdiGetTextCharsetInfo(hDc
, NULL
, 0);
1069 if ((Ret
== ARABIC_CHARSET
) || (Ret
== HEBREW_CHARSET
))
1070 Ret
= (GCP_KASHIDA
|GCP_DIACRITIC
|GCP_LIGATE
|GCP_GLYPHSHAPE
|GCP_REORDER
);
1072 Gcp
= GetDCDWord(hDc
, GdiGetFontLanguageInfo
, GCP_ERROR
);
1073 if ( Gcp
== GCP_ERROR
)
1097 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
1102 Ret
= NtGdiGetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
1103 HeapFree(GetProcessHeap(), 0, lpstrW
);
1116 LPGLYPHMETRICS lpgm
,
1126 DPRINT("GetGlyphOutlineA uChar %x\n", uChar
);
1127 if (!lpgm
|| !lpmat2
) return GDI_ERROR
;
1128 if(!(uFormat
& GGO_GLYPH_INDEX
))
1132 if(uChar
> 0xff) /* but, 2 bytes character only */
1135 mbchs
[0] = (uChar
& 0xff00) >> 8;
1136 mbchs
[1] = (uChar
& 0xff);
1141 mbchs
[0] = (uChar
& 0xff);
1143 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
1150 ret
= NtGdiGetGlyphOutline(hdc
, c
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1151 HeapFree(GetProcessHeap(), 0, p
);
1165 LPGLYPHMETRICS lpgm
,
1171 DPRINT("GetGlyphOutlineW uChar %x\n", uChar
);
1172 if (!lpgm
|| !lpmat2
) return GDI_ERROR
;
1173 if (!lpvBuffer
) cbBuffer
= 0;
1174 return NtGdiGetGlyphOutline ( hdc
, uChar
, uFormat
, lpgm
, cbBuffer
, lpvBuffer
, (CONST LPMAT2
)lpmat2
, TRUE
);
1193 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1202 GetOutlineTextMetricsA(
1205 LPOUTLINETEXTMETRICA lpOTM
1208 char buf
[512], *ptr
;
1210 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1211 OUTLINETEXTMETRICA
*output
= lpOTM
;
1214 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1216 if(ret
> sizeof(buf
))
1218 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1224 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1226 needed
= sizeof(OUTLINETEXTMETRICA
);
1227 if(lpOTMW
->otmpFamilyName
)
1228 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1229 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFamilyName
), -1,
1230 NULL
, 0, NULL
, NULL
);
1231 if(lpOTMW
->otmpFaceName
)
1232 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1233 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFaceName
), -1,
1234 NULL
, 0, NULL
, NULL
);
1235 if(lpOTMW
->otmpStyleName
)
1236 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1237 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpStyleName
), -1,
1238 NULL
, 0, NULL
, NULL
);
1239 if(lpOTMW
->otmpFullName
)
1240 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1241 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFullName
), -1,
1242 NULL
, 0, NULL
, NULL
);
1250 DPRINT("needed = %u\n", needed
);
1253 /* Since the supplied buffer isn't big enough, we'll alloc one
1254 that is and memcpy the first cbData bytes into the lpOTM at
1256 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1263 ret
= output
->otmSize
= min(needed
, cbData
);
1264 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1265 output
->otmFiller
= 0;
1266 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1267 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1268 output
->otmfsType
= lpOTMW
->otmfsType
;
1269 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1270 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1271 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1272 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1273 output
->otmAscent
= lpOTMW
->otmAscent
;
1274 output
->otmDescent
= lpOTMW
->otmDescent
;
1275 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1276 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1277 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1278 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1279 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1280 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1281 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1282 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1283 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1284 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1285 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1286 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1287 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1288 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1289 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1290 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1293 ptr
= (char*)(output
+ 1);
1294 left
= needed
- sizeof(*output
);
1296 if(lpOTMW
->otmpFamilyName
)
1298 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1299 len
= WideCharToMultiByte(CP_ACP
, 0,
1300 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFamilyName
), -1,
1301 ptr
, left
, NULL
, NULL
);
1306 output
->otmpFamilyName
= 0;
1308 if(lpOTMW
->otmpFaceName
)
1310 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1311 len
= WideCharToMultiByte(CP_ACP
, 0,
1312 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFaceName
), -1,
1313 ptr
, left
, NULL
, NULL
);
1318 output
->otmpFaceName
= 0;
1320 if(lpOTMW
->otmpStyleName
)
1322 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1323 len
= WideCharToMultiByte(CP_ACP
, 0,
1324 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpStyleName
), -1,
1325 ptr
, left
, NULL
, NULL
);
1330 output
->otmpStyleName
= 0;
1332 if(lpOTMW
->otmpFullName
)
1334 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1335 len
= WideCharToMultiByte(CP_ACP
, 0,
1336 (WCHAR
*)((char*)lpOTMW
+ (intptr_t)lpOTMW
->otmpFullName
), -1,
1337 ptr
, left
, NULL
, NULL
);
1341 output
->otmpFullName
= 0;
1347 memcpy(lpOTM
, output
, cbData
);
1348 HeapFree(GetProcessHeap(), 0, output
);
1350 /* check if the string offsets really fit into the provided size */
1351 /* FIXME: should we check string length as well? */
1352 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1353 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1355 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1356 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1358 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1359 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1361 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1362 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1366 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1367 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1372 /* Performs a device to world transformation on the specified size (which
1373 * is in integer format).
1375 static inline INT
INTERNAL_YDSTOWS(XFORM
*xForm
, INT height
)
1379 /* Perform operation with floating point */
1380 floatHeight
= (double)height
* xForm
->eM22
;
1381 /* Round to integers */
1382 return GDI_ROUND(floatHeight
);
1385 /* scale width and height but don't mirror them */
1386 static inline INT
width_to_LP( XFORM
*xForm
, INT width
)
1388 return GDI_ROUND( (double)width
* fabs( xForm
->eM11
));
1391 static inline INT
height_to_LP( XFORM
*xForm
, INT height
)
1393 return GDI_ROUND( (double)height
* fabs( xForm
->eM22
));
1401 GetOutlineTextMetricsW(
1404 LPOUTLINETEXTMETRICW lpOTM
1407 TMDIFF Tmd
; // Should not be zero.
1408 UINT Size
, AvailableSize
= 0, StringSize
;
1410 OUTLINETEXTMETRICW
* LocalOTM
;
1414 /* Get the structure */
1415 Size
= NtGdiGetOutlineTextMetricsInternalW(hdc
, 0, NULL
, &Tmd
);
1418 if (!lpOTM
|| (cbData
< sizeof(*lpOTM
)))
1421 LocalOTM
= HeapAlloc(GetProcessHeap(), 0, Size
);
1422 LocalOTM
->otmSize
= Size
;
1423 Size
= NtGdiGetOutlineTextMetricsInternalW(hdc
, Size
, LocalOTM
, &Tmd
);
1426 HeapFree(GetProcessHeap(), 0, LocalOTM
);
1430 if (!NtGdiGetTransform(hdc
, GdiDeviceSpaceToWorldSpace
, &DevToWorld
))
1432 DPRINT1("NtGdiGetTransform failed!\n");
1433 HeapFree(GetProcessHeap(), 0, LocalOTM
);
1434 SetLastError(ERROR_INVALID_HANDLE
);
1438 /* Fill in DC specific data */
1439 LocalOTM
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1440 LocalOTM
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1441 LocalOTM
->otmTextMetrics
.tmHeight
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmHeight
);
1442 LocalOTM
->otmTextMetrics
.tmAscent
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmAscent
);
1443 LocalOTM
->otmTextMetrics
.tmDescent
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmDescent
);
1444 LocalOTM
->otmTextMetrics
.tmInternalLeading
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmInternalLeading
);
1445 LocalOTM
->otmTextMetrics
.tmExternalLeading
= height_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmExternalLeading
);
1446 LocalOTM
->otmTextMetrics
.tmAveCharWidth
= width_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmAveCharWidth
);
1447 LocalOTM
->otmTextMetrics
.tmMaxCharWidth
= width_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmMaxCharWidth
);
1448 LocalOTM
->otmTextMetrics
.tmOverhang
= width_to_LP( &DevToWorld
, LocalOTM
->otmTextMetrics
.tmOverhang
);
1449 LocalOTM
->otmAscent
= height_to_LP( &DevToWorld
, LocalOTM
->otmAscent
);
1450 LocalOTM
->otmDescent
= height_to_LP( &DevToWorld
, LocalOTM
->otmDescent
);
1451 LocalOTM
->otmLineGap
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmLineGap
));
1452 LocalOTM
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmsCapEmHeight
));
1453 LocalOTM
->otmsXHeight
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmsXHeight
));
1454 LocalOTM
->otmrcFontBox
.top
= height_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.top
);
1455 LocalOTM
->otmrcFontBox
.bottom
= height_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.bottom
);
1456 LocalOTM
->otmrcFontBox
.left
= width_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.left
);
1457 LocalOTM
->otmrcFontBox
.right
= width_to_LP( &DevToWorld
, LocalOTM
->otmrcFontBox
.right
);
1458 LocalOTM
->otmMacAscent
= height_to_LP( &DevToWorld
, LocalOTM
->otmMacAscent
);
1459 LocalOTM
->otmMacDescent
= height_to_LP( &DevToWorld
, LocalOTM
->otmMacDescent
);
1460 LocalOTM
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmMacLineGap
));
1461 LocalOTM
->otmptSubscriptSize
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptSize
.x
);
1462 LocalOTM
->otmptSubscriptSize
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptSize
.y
);
1463 LocalOTM
->otmptSubscriptOffset
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptOffset
.x
);
1464 LocalOTM
->otmptSubscriptOffset
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSubscriptOffset
.y
);
1465 LocalOTM
->otmptSuperscriptSize
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptSize
.x
);
1466 LocalOTM
->otmptSuperscriptSize
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptSize
.y
);
1467 LocalOTM
->otmptSuperscriptOffset
.x
= width_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptOffset
.x
);
1468 LocalOTM
->otmptSuperscriptOffset
.y
= height_to_LP( &DevToWorld
, LocalOTM
->otmptSuperscriptOffset
.y
);
1469 LocalOTM
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(&DevToWorld
,LocalOTM
->otmsStrikeoutSize
));
1470 LocalOTM
->otmsStrikeoutPosition
= height_to_LP( &DevToWorld
, LocalOTM
->otmsStrikeoutPosition
);
1471 LocalOTM
->otmsUnderscoreSize
= height_to_LP( &DevToWorld
, LocalOTM
->otmsUnderscoreSize
);
1472 LocalOTM
->otmsUnderscorePosition
= height_to_LP( &DevToWorld
, LocalOTM
->otmsUnderscorePosition
);
1474 /* Copy what we can */
1475 CopyMemory(lpOTM
, LocalOTM
, min(Size
, cbData
));
1477 lpOTM
->otmpFamilyName
= NULL
;
1478 lpOTM
->otmpFaceName
= NULL
;
1479 lpOTM
->otmpStyleName
= NULL
;
1480 lpOTM
->otmpFullName
= NULL
;
1482 Size
= sizeof(*lpOTM
);
1483 AvailableSize
= cbData
- Size
;
1484 Ptr
= (BYTE
*)lpOTM
+ sizeof(*lpOTM
);
1486 /* Fix string values up */
1487 if (LocalOTM
->otmpFamilyName
)
1489 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpFamilyName
);
1490 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1491 if (AvailableSize
>= StringSize
)
1493 CopyMemory(Ptr
, Str
, StringSize
);
1494 lpOTM
->otmpFamilyName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1496 AvailableSize
-= StringSize
;
1501 if (LocalOTM
->otmpFaceName
)
1503 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpFaceName
);
1504 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1505 if (AvailableSize
>= StringSize
)
1507 CopyMemory(Ptr
, Str
, StringSize
);
1508 lpOTM
->otmpFaceName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1510 AvailableSize
-= StringSize
;
1515 if (LocalOTM
->otmpStyleName
)
1517 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpStyleName
);
1518 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1519 if (AvailableSize
>= StringSize
)
1521 CopyMemory(Ptr
, Str
, StringSize
);
1522 lpOTM
->otmpStyleName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1524 AvailableSize
-= StringSize
;
1529 if (LocalOTM
->otmpFullName
)
1531 Str
= (WCHAR
*)((char*)LocalOTM
+ (ptrdiff_t)LocalOTM
->otmpFullName
);
1532 StringSize
= (wcslen(Str
) + 1) * sizeof(WCHAR
);
1533 if (AvailableSize
>= StringSize
)
1535 CopyMemory(Ptr
, Str
, StringSize
);
1536 lpOTM
->otmpFullName
= (PSTR
)(Ptr
- (BYTE
*)lpOTM
);
1538 AvailableSize
-= StringSize
;
1543 lpOTM
->otmSize
= Size
;
1545 HeapFree(GetProcessHeap(), 0, LocalOTM
);
1555 GetKerningPairsW(HDC hdc
,
1557 LPKERNINGPAIR pkpDst
)
1559 if ((cPairs
!= 0) || (pkpDst
== 0))
1561 return NtGdiGetKerningPairs(hdc
,cPairs
,pkpDst
);
1565 SetLastError(ERROR_INVALID_PARAMETER
);
1575 GetKerningPairsA( HDC hDC
,
1577 LPKERNINGPAIR kern_pairA
)
1582 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
1583 KERNINGPAIR
*kern_pairW
;
1585 if (!cPairs
&& kern_pairA
)
1587 SetLastError(ERROR_INVALID_PARAMETER
);
1591 charset
= GetTextCharset(hDC
);
1592 if (!TranslateCharsetInfo(ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
))
1594 DPRINT1("Can't find codepage for charset %d\n", charset
);
1597 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1598 * to fail on an invalid character for CP_SYMBOL.
1600 cpi
.DefaultChar
[0] = 0;
1601 if (csi
.ciACP
!= CP_SYMBOL
&& !GetCPInfo(csi
.ciACP
, &cpi
))
1603 DPRINT1("Can't find codepage %u info\n", csi
.ciACP
);
1606 DPRINT("charset %d => codepage %u\n", charset
, csi
.ciACP
);
1608 total_kern_pairs
= NtGdiGetKerningPairs(hDC
, 0, NULL
);
1609 if (!total_kern_pairs
) return 0;
1611 if (!cPairs
&& !kern_pairA
) return total_kern_pairs
;
1613 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
1614 if (kern_pairW
== NULL
)
1618 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
1620 for (i
= 0; i
< total_kern_pairs
; i
++)
1624 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
1627 if (!WideCharToMultiByte(csi
.ciACP
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
1630 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
1635 if (kern_pairs_copied
>= cPairs
) break;
1637 kern_pairA
->wFirst
= (BYTE
)first
;
1638 kern_pairA
->wSecond
= (BYTE
)second
;
1639 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
1642 kern_pairs_copied
++;
1645 HeapFree(GetProcessHeap(), 0, kern_pairW
);
1647 return kern_pairs_copied
;
1657 CreateFontIndirectExA(const ENUMLOGFONTEXDVA
*elfexd
)
1661 ENUMLOGFONTEXDVW Logfont
;
1663 EnumLogFontExW2A( (LPENUMLOGFONTEXA
) elfexd
,
1664 &Logfont
.elfEnumLogfontEx
);
1666 RtlCopyMemory( &Logfont
.elfDesignVector
,
1667 (PVOID
) &elfexd
->elfDesignVector
,
1668 sizeof(DESIGNVECTOR
));
1670 return NtGdiHfontCreate( &Logfont
, 0, 0, 0, NULL
);
1681 CreateFontIndirectExW(const ENUMLOGFONTEXDVW
*elfexd
)
1683 /* Msdn: Note, this function ignores the elfDesignVector member in
1688 return NtGdiHfontCreate((PENUMLOGFONTEXDVW
) elfexd
, 0, 0, 0, NULL
);
1699 CreateFontIndirectA(
1700 CONST LOGFONTA
*lplf
1707 LogFontA2W(&tlf
, lplf
);
1708 return CreateFontIndirectW(&tlf
);
1715 VOID
DumpFamilyInfo(const FONTFAMILYINFO
*Info
, LONG Count
)
1718 const LOGFONTW
*plf
;
1721 DPRINT1("Count: %d\n", Count
);
1722 for (i
= 0; i
< Count
; ++i
)
1724 plf
= &Info
[i
].EnumLogFontEx
.elfLogFont
;
1725 DPRINT1("%d: '%S',%u,'%S', %ld:%ld, %ld, %d, %d\n", i
,
1726 plf
->lfFaceName
, plf
->lfCharSet
, Info
[i
].EnumLogFontEx
.elfFullName
,
1727 plf
->lfHeight
, plf
->lfWidth
, plf
->lfWeight
, plf
->lfItalic
, plf
->lfPitchAndFamily
);
1731 VOID
DoFontSystemUnittest(VOID
)
1733 #ifndef RTL_SOFT_ASSERT
1734 #define RTL_SOFT_ASSERT(exp) \
1736 DbgPrint("%s(%d): Soft assertion failed\n Expression: %s\n", __FILE__, __LINE__, #exp), FALSE : TRUE)
1737 #define RTL_SOFT_ASSERT_defined
1741 FONTFAMILYINFO Info
[4];
1742 UNICODE_STRING Str1
, Str2
;
1743 LONG ret
, InfoCount
;
1745 //DumpFontInfo(TRUE);
1747 /* L"" DEFAULT_CHARSET */
1748 RtlZeroMemory(&LogFont
, sizeof(LogFont
));
1749 LogFont
.lfCharSet
= DEFAULT_CHARSET
;
1750 InfoCount
= RTL_NUMBER_OF(Info
);
1751 ret
= NtGdiGetFontFamilyInfo(NULL
, &LogFont
, Info
, &InfoCount
);
1752 DPRINT1("ret: %ld, InfoCount: %ld\n", ret
, InfoCount
);
1753 DumpFamilyInfo(Info
, ret
);
1754 RTL_SOFT_ASSERT(ret
== RTL_NUMBER_OF(Info
));
1755 RTL_SOFT_ASSERT(InfoCount
> 32);
1757 /* L"Microsoft Sans Serif" ANSI_CHARSET */
1758 RtlZeroMemory(&LogFont
, sizeof(LogFont
));
1759 LogFont
.lfCharSet
= ANSI_CHARSET
;
1760 StringCbCopyW(LogFont
.lfFaceName
, sizeof(LogFont
.lfFaceName
), L
"Microsoft Sans Serif");
1761 InfoCount
= RTL_NUMBER_OF(Info
);
1762 ret
= NtGdiGetFontFamilyInfo(NULL
, &LogFont
, Info
, &InfoCount
);
1763 DPRINT1("ret: %ld, InfoCount: %ld\n", ret
, InfoCount
);
1764 DumpFamilyInfo(Info
, ret
);
1765 RTL_SOFT_ASSERT(ret
!= -1);
1766 RTL_SOFT_ASSERT(InfoCount
> 0);
1767 RTL_SOFT_ASSERT(InfoCount
< 16);
1769 RtlInitUnicodeString(&Str1
, Info
[0].EnumLogFontEx
.elfLogFont
.lfFaceName
);
1770 RtlInitUnicodeString(&Str2
, L
"Microsoft Sans Serif");
1771 ret
= RtlCompareUnicodeString(&Str1
, &Str2
, TRUE
);
1772 RTL_SOFT_ASSERT(ret
== 0);
1774 RtlInitUnicodeString(&Str1
, Info
[0].EnumLogFontEx
.elfFullName
);
1775 RtlInitUnicodeString(&Str2
, L
"Tahoma");
1776 ret
= RtlCompareUnicodeString(&Str1
, &Str2
, TRUE
);
1777 RTL_SOFT_ASSERT(ret
== 0);
1779 /* L"Non-Existent" DEFAULT_CHARSET */
1780 RtlZeroMemory(&LogFont
, sizeof(LogFont
));
1781 LogFont
.lfCharSet
= ANSI_CHARSET
;
1782 StringCbCopyW(LogFont
.lfFaceName
, sizeof(LogFont
.lfFaceName
), L
"Non-Existent");
1783 InfoCount
= RTL_NUMBER_OF(Info
);
1784 ret
= NtGdiGetFontFamilyInfo(NULL
, &LogFont
, Info
, &InfoCount
);
1785 DPRINT1("ret: %ld, InfoCount: %ld\n", ret
, InfoCount
);
1786 DumpFamilyInfo(Info
, ret
);
1787 RTL_SOFT_ASSERT(ret
== 0);
1788 RTL_SOFT_ASSERT(InfoCount
== 0);
1790 #ifdef RTL_SOFT_ASSERT_defined
1791 #undef RTL_SOFT_ASSERT_defined
1792 #undef RTL_SOFT_ASSERT
1803 CreateFontIndirectW(
1804 CONST LOGFONTW
*lplf
1808 static BOOL bDidTest
= FALSE
;
1812 DoFontSystemUnittest();
1817 ENUMLOGFONTEXDVW Logfont
;
1819 RtlCopyMemory( &Logfont
.elfEnumLogfontEx
.elfLogFont
, lplf
, sizeof(LOGFONTW
));
1820 // Need something other than just cleaning memory here.
1821 // Guess? Use caller data to determine the rest.
1822 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfFullName
,
1823 sizeof(Logfont
.elfEnumLogfontEx
.elfFullName
));
1824 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfStyle
,
1825 sizeof(Logfont
.elfEnumLogfontEx
.elfStyle
));
1826 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfScript
,
1827 sizeof(Logfont
.elfEnumLogfontEx
.elfScript
));
1829 Logfont
.elfDesignVector
.dvNumAxes
= 0; // No more than MM_MAX_NUMAXES
1831 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
1833 return CreateFontIndirectExW(&Logfont
);
1854 DWORD fdwOutputPrecision
,
1855 DWORD fdwClipPrecision
,
1857 DWORD fdwPitchAndFamily
,
1861 ANSI_STRING StringA
;
1862 UNICODE_STRING StringU
;
1865 RtlInitAnsiString(&StringA
, (LPSTR
)lpszFace
);
1866 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
1868 ret
= CreateFontW(nHeight
,
1883 RtlFreeUnicodeString(&StringU
);
1904 DWORD fdwOutputPrecision
,
1905 DWORD fdwClipPrecision
,
1907 DWORD fdwPitchAndFamily
,
1913 logfont
.lfHeight
= nHeight
;
1914 logfont
.lfWidth
= nWidth
;
1915 logfont
.lfEscapement
= nEscapement
;
1916 logfont
.lfOrientation
= nOrientation
;
1917 logfont
.lfWeight
= nWeight
;
1918 logfont
.lfItalic
= (BYTE
)fnItalic
;
1919 logfont
.lfUnderline
= (BYTE
)fdwUnderline
;
1920 logfont
.lfStrikeOut
= (BYTE
)fdwStrikeOut
;
1921 logfont
.lfCharSet
= (BYTE
)fdwCharSet
;
1922 logfont
.lfOutPrecision
= (BYTE
)fdwOutputPrecision
;
1923 logfont
.lfClipPrecision
= (BYTE
)fdwClipPrecision
;
1924 logfont
.lfQuality
= (BYTE
)fdwQuality
;
1925 logfont
.lfPitchAndFamily
= (BYTE
)fdwPitchAndFamily
;
1927 if (NULL
!= lpszFace
)
1929 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
1930 wcsncpy((wchar_t *)logfont
.lfFaceName
, lpszFace
, Size
- 1);
1931 /* Be 101% sure to have '\0' at end of string */
1932 logfont
.lfFaceName
[Size
- 1] = '\0';
1936 logfont
.lfFaceName
[0] = L
'\0';
1939 return CreateFontIndirectW(&logfont
);
1948 CreateScalableFontResourceA(
1951 LPCSTR lpszFontFile
,
1952 LPCSTR lpszCurrentPath
1964 AddFontResourceExW ( LPCWSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1966 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1968 SetLastError( ERROR_INVALID_PARAMETER
);
1972 return GdiAddFontResourceW(lpszFilename
, fl
,0);
1981 AddFontResourceExA ( LPCSTR lpszFilename
, DWORD fl
, PVOID pvReserved
)
1987 if (fl
& ~(FR_PRIVATE
| FR_NOT_ENUM
))
1989 SetLastError( ERROR_INVALID_PARAMETER
);
1993 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
1994 if ( !NT_SUCCESS (Status
) )
1996 SetLastError (RtlNtStatusToDosError(Status
));
2000 rc
= GdiAddFontResourceW ( FilenameW
, fl
, 0 );
2001 HEAP_free ( FilenameW
);
2011 AddFontResourceA ( LPCSTR lpszFilename
)
2017 Status
= HEAP_strdupA2W ( &FilenameW
, lpszFilename
);
2018 if ( !NT_SUCCESS (Status
) )
2020 SetLastError (RtlNtStatusToDosError(Status
));
2024 rc
= GdiAddFontResourceW ( FilenameW
, 0, 0);
2026 HEAP_free ( FilenameW
);
2037 AddFontResourceW ( LPCWSTR lpszFilename
)
2039 return GdiAddFontResourceW ( lpszFilename
, 0, 0 );
2048 RemoveFontResourceW(LPCWSTR lpFileName
)
2050 return RemoveFontResourceExW(lpFileName
,0,0);
2059 RemoveFontResourceA(LPCSTR lpFileName
)
2061 return RemoveFontResourceExA(lpFileName
,0,0);
2069 RemoveFontResourceExA(LPCSTR lpFileName
,
2077 /* FIXME the flags */
2079 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
2081 Status
= HEAP_strdupA2W ( &lpFileNameW
, lpFileName
);
2082 if (!NT_SUCCESS (Status
))
2083 SetLastError (RtlNtStatusToDosError(Status
));
2087 HEAP_free ( lpFileNameW
);
2098 RemoveFontResourceExW(LPCWSTR lpFileName
,
2102 /* FIXME the flags */
2104 /* FIXME NtGdiRemoveFontResource handle flags and pdv */
2105 DPRINT("RemoveFontResourceExW\n");
2110 /***********************************************************************
2111 * GdiGetCharDimensions
2113 * Gets the average width of the characters in the English alphabet.
2116 * hdc [I] Handle to the device context to measure on.
2117 * lptm [O] Pointer to memory to store the text metrics into.
2118 * height [O] On exit, the maximum height of characters in the English alphabet.
2121 * The average width of characters in the English alphabet.
2124 * This function is used by the dialog manager to get the size of a dialog
2125 * unit. It should also be used by other pieces of code that need to know
2126 * the size of a dialog unit in logical units without having access to the
2127 * window handle of the dialog.
2128 * Windows caches the font metrics from this function, but we don't and
2129 * there doesn't appear to be an immediate advantage to do so.
2132 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
2134 * Despite most of MSDN insisting that the horizontal base unit is
2135 * tmAveCharWidth it isn't. Knowledge base article Q145994
2136 * "HOWTO: Calculate Dialog Units When Not Using the System Font",
2137 * says that we should take the average of the 52 English upper and lower
2145 GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
2149 static const WCHAR alphabet
[] =
2151 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2152 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2153 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0
2156 if(!GetTextMetricsW(hdc
, &tm
)) return 0;
2158 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
2160 if (lptm
) *lptm
= tm
;
2161 if (height
) *height
= tm
.tmHeight
;
2163 return (sz
.cx
/ 26 + 1) / 2;
2166 /*************************************************************************
2167 * TranslateCharsetInfo [GDI32.@]
2169 * Fills a CHARSETINFO structure for a character set, code page, or
2170 * font. This allows making the correspondance between different labelings
2171 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2172 * of the same encoding.
2174 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2175 * only one codepage should be set in *lpSrc.
2178 * TRUE on success, FALSE on failure.
2186 TranslateCharsetInfo(
2187 LPDWORD lpSrc
, /* [in]
2188 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2189 if flags == TCI_SRCCHARSET: a character set value
2190 if flags == TCI_SRCCODEPAGE: a code page value
2192 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2193 DWORD flags
/* [in] determines interpretation of lpSrc */)
2198 case TCI_SRCFONTSIG
:
2199 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2201 case TCI_SRCCODEPAGE
:
2202 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2204 case TCI_SRCCHARSET
:
2205 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2209 LCID lCid
= (LCID
)PtrToUlong(lpSrc
);
2210 LOCALESIGNATURE LocSig
;
2211 INT Ret
= GetLocaleInfoW(lCid
, LOCALE_FONTSIGNATURE
, (LPWSTR
)&LocSig
, 0);
2212 if ( GetLocaleInfoW(lCid
, LOCALE_FONTSIGNATURE
, (LPWSTR
)&LocSig
, Ret
))
2214 while (index
< MAXTCIINDEX
&& !(LocSig
.lsCsbDefault
[0]>>index
& 0x0001)) index
++;
2219 GdiSetLastError(ERROR_INVALID_PARAMETER
);
2222 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2223 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n",
2224 index
,FONT_tci
[index
].ciCharset
,FONT_tci
[index
].ciACP
,FONT_tci
[index
].fs
.fsCsb
[0]);
2225 memcpy(lpCs
, &FONT_tci
[index
], sizeof(CHARSETINFO
));
2240 DWORD Ret
= GDI_ERROR
;
2243 /* Get the DC attribute */
2244 Dc_Attr
= GdiGetDcAttr(hDC
);
2245 if (Dc_Attr
== NULL
)
2247 SetLastError(ERROR_INVALID_PARAMETER
);
2251 if (NtCurrentTeb()->GdiTebBatch
.HDC
== hDC
)
2253 if (Dc_Attr
->ulDirty_
& DC_FONTTEXT_DIRTY
)
2256 Dc_Attr
->ulDirty_
&= ~(DC_MODE_DIRTY
|DC_FONTTEXT_DIRTY
);
2261 SetLastError(ERROR_INVALID_PARAMETER
);
2264 Ret
= Dc_Attr
->flFontMapper
;
2265 Dc_Attr
->flFontMapper
= flags
;
2279 FONTENUMPROCW FontFunc
,
2284 return NtGdiEnumFonts ( hDC
, lpFaceName
, FontFunc
, lParam
);
2286 return EnumFontFamiliesW( hDC
, lpFaceName
, FontFunc
, lParam
);
2298 FONTENUMPROCA FontFunc
,
2307 Status
= HEAP_strdupA2W ( &lpFaceNameW
, lpFaceName
);
2308 if (!NT_SUCCESS (Status
))
2309 SetLastError (RtlNtStatusToDosError(Status
));
2312 rc
= NtGdiEnumFonts ( hDC
, lpFaceNameW
, FontFunc
, lParam
);
2314 HEAP_free ( lpFaceNameW
);
2318 return EnumFontFamiliesA( hDC
, lpFaceName
, FontFunc
, lParam
);
2322 #define EfdFontFamilies 3
2326 NewEnumFontFamiliesExW(
2328 LPLOGFONTW lpLogfont
,
2329 FONTENUMPROCW lpEnumFontFamExProcW
,
2334 ULONG cbDataSize
, cbRetSize
;
2335 PENUMFONTDATAW pEfdw
;
2340 /* Open enumeration handle and find out how much memory we need */
2341 idEnum
= NtGdiEnumFontOpen(hDC
,
2345 (lpLogfont
&& lpLogfont
->lfFaceName
[0])? lpLogfont
->lfFaceName
: NULL
,
2346 lpLogfont
? lpLogfont
->lfCharSet
: DEFAULT_CHARSET
,
2352 if (cbDataSize
== 0)
2354 NtGdiEnumFontClose(idEnum
);
2358 /* Allocate memory */
2359 pBuffer
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
2360 if (pBuffer
== NULL
)
2362 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2363 NtGdiEnumFontClose(idEnum
);
2367 /* Do the enumeration */
2368 if (!NtGdiEnumFontChunk(hDC
, idEnum
, cbDataSize
, &cbRetSize
, (PVOID
)pBuffer
))
2370 HeapFree(GetProcessHeap(), 0, pBuffer
);
2371 NtGdiEnumFontClose(idEnum
);
2375 /* Get start and end address */
2376 pEfdw
= (PENUMFONTDATAW
)pBuffer
;
2377 pMax
= pBuffer
+ cbDataSize
;
2379 /* Iterate through the structures */
2380 while ((PBYTE
)pEfdw
< pMax
&& ret
)
2382 PNTMW_INTERNAL pNtmwi
= (PNTMW_INTERNAL
)((ULONG_PTR
)pEfdw
+ pEfdw
->ulNtmwiOffset
);
2384 ret
= lpEnumFontFamExProcW((VOID
*)&pEfdw
->elfexdv
.elfEnumLogfontEx
,
2385 (VOID
*)&pNtmwi
->ntmw
,
2389 pEfdw
= (PENUMFONTDATAW
)((ULONG_PTR
)pEfdw
+ pEfdw
->cbSize
);
2392 /* Release the memory and close handle */
2393 HeapFree(GetProcessHeap(), 0, pBuffer
);
2394 NtGdiEnumFontClose(idEnum
);
2404 GdiAddFontResourceW(
2405 LPCWSTR lpszFilename
,
2410 WCHAR lpszBuffer
[MAX_PATH
];
2411 WCHAR lpszAbsPath
[MAX_PATH
];
2412 UNICODE_STRING NtAbsPath
;
2414 /* FIXME: We don't support multiple files passed in lpszFilename
2415 * as L"abcxxxxx.pfm|abcxxxxx.pfb"
2418 /* Does the file exist in CurrentDirectory or in the Absolute Path passed? */
2419 GetCurrentDirectoryW(MAX_PATH
, lpszBuffer
);
2421 if (!SearchPathW(lpszBuffer
, lpszFilename
, NULL
, MAX_PATH
, lpszAbsPath
, NULL
))
2423 /* Nope. Then let's check Fonts folder */
2424 GetWindowsDirectoryW(lpszBuffer
, MAX_PATH
);
2425 StringCbCatW(lpszBuffer
, sizeof(lpszBuffer
), L
"\\Fonts");
2427 if (!SearchPathW(lpszBuffer
, lpszFilename
, NULL
, MAX_PATH
, lpszAbsPath
, NULL
))
2429 DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer
, lpszFilename
);
2434 /* We found the font file so: */
2435 if (!RtlDosPathNameToNtPathName_U(lpszAbsPath
, &NtAbsPath
, NULL
, NULL
))
2437 DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath
);
2441 /* The Nt call expects a null-terminator included in cwc param. */
2442 ASSERT(NtAbsPath
.Buffer
[NtAbsPath
.Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
2443 Ret
= NtGdiAddFontResourceW(NtAbsPath
.Buffer
, NtAbsPath
.Length
/ sizeof(WCHAR
) + 1, 1, fl
, 0, pdv
);
2445 RtlFreeUnicodeString(&NtAbsPath
);
2455 AddFontMemResourceEx(
2462 if ( pbFont
&& cbFont
&& pcFonts
)
2464 return NtGdiAddFontMemResourceEx(pbFont
, cbFont
, NULL
, 0, pcFonts
);
2466 SetLastError(ERROR_INVALID_PARAMETER
);
2475 RemoveFontMemResourceEx(HANDLE fh
)
2479 return NtGdiRemoveFontMemResourceEx(fh
);
2481 SetLastError(ERROR_INVALID_PARAMETER
);
2491 AddFontResourceTracking(
2497 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2506 RemoveFontResourceTracking(LPCSTR lpString
,int unknown
)
2509 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2515 CreateScalableFontResourceW(
2517 LPCWSTR lpszFontRes
,
2518 LPCWSTR lpszFontFile
,
2519 LPCWSTR lpszCurrentPath
2526 /* fHidden=1 - only visible for the calling app, read-only, not
2527 * enumerated with EnumFonts/EnumFontFamilies
2528 * lpszCurrentPath can be NULL
2531 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2532 if ((f
= CreateFileW(lpszFontRes
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
)
2535 SetLastError(ERROR_FILE_EXISTS
);
2538 return FALSE
; /* create failed */
2546 bInitSystemAndFontsDirectoriesW(LPWSTR
*SystemDir
,LPWSTR
*FontsDir
)
2549 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2558 EudcLoadLinkW(LPCWSTR pBaseFaceName
,LPCWSTR pEudcFontPath
,INT iPriority
,INT iFontLinkType
)
2561 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2570 EudcUnloadLinkW(LPCWSTR pBaseFaceName
,LPCWSTR pEudcFontPath
)
2573 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2582 GetEUDCTimeStamp(VOID
)
2584 return NtGdiGetEudcTimeStampEx(NULL
,0,TRUE
);
2592 GetEUDCTimeStampExW(LPWSTR lpBaseFaceName
)
2596 if (!lpBaseFaceName
)
2598 retValue
= NtGdiGetEudcTimeStampEx(NULL
,0,FALSE
);
2602 retValue
= NtGdiGetEudcTimeStampEx(lpBaseFaceName
, wcslen(lpBaseFaceName
), FALSE
);
2613 GetFontAssocStatus(HDC hdc
)
2619 retValue
= NtGdiQueryFontAssocInfo(hdc
);
2630 QueryFontAssocStatus(VOID
)
2633 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2642 UnloadNetworkFonts(DWORD unknown
)
2645 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2654 GetFontData(HDC hdc
,
2664 return NtGdiGetFontData(hdc
, dwTable
, dwOffset
, lpvBuffer
, cbData
);
2669 cGetTTFFromFOT(DWORD x1
,DWORD x2
,DWORD x3
, DWORD x4
, DWORD x5
, DWORD x6
, DWORD x7
)
2672 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);