1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: win32ss/gdi/gdi32/objects/font.c 5 * PURPOSE: 6 * PROGRAMMER: 7 * 8 */ 9 10 #include <precomp.h> 11 12 #include <math.h> 13 #include <strsafe.h> 14 15 #define NDEBUG 16 #include <debug.h> 17 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. 21 */ 22 static __inline INT GDI_ROUND(FLOAT val) 23 { 24 return (int)floor(val + 0.5); 25 } 26 27 /* 28 * For TranslateCharsetInfo 29 */ 30 #define MAXTCIINDEX 32 31 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = 32 { 33 /* ANSI */ 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}} }, 51 /* ANSI and OEM */ 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}} } 70 }; 71 72 #define INITIAL_FAMILY_COUNT 64 73 74 /*********************************************************************** 75 * TEXTMETRIC conversion functions. 76 */ 77 VOID 78 FASTCALL 79 FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA ) 80 { 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) 94 { 95 ptmA->tmFirstChar = 0x1e; 96 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */ 97 } 98 else 99 { 100 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1; 101 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff); 102 } 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; 110 } 111 112 /*********************************************************************** 113 * FONT_mbtowc 114 * 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 122 * itself. 123 */ 124 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP) 125 { 126 UINT cp = GdiGetCodePage( hdc ); 127 INT lenW; 128 LPWSTR strW; 129 130 if(count == -1) count = strlen(str); 131 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0); 132 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR)); 133 if (!strW) 134 return NULL; 135 if(!MultiByteToWideChar(cp, 0, str, count, strW, lenW)) 136 { 137 HeapFree(GetProcessHeap(), 0, strW); 138 return NULL; 139 } 140 DPRINT("mapped %s -> %S\n", str, strW); 141 if(plenW) *plenW = lenW; 142 if(pCP) *pCP = cp; 143 return strW; 144 } 145 146 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen) 147 { 148 INT i, count = lastChar - firstChar + 1; 149 UINT c; 150 LPSTR str; 151 152 if (count <= 0) 153 return NULL; 154 155 switch (GdiGetCodePage(hdc)) 156 { 157 case 932: 158 case 936: 159 case 949: 160 case 950: 161 case 1361: 162 if (lastChar > 0xffff) 163 return NULL; 164 if ((firstChar ^ lastChar) > 0xff) 165 return NULL; 166 break; 167 default: 168 if (lastChar > 0xff) 169 return NULL; 170 break; 171 } 172 173 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1); 174 if (str == NULL) 175 return NULL; 176 177 for(i = 0, c = firstChar; c <= lastChar; i++, c++) 178 { 179 if (c > 0xff) 180 str[i++] = (BYTE)(c >> 8); 181 str[i] = (BYTE)c; 182 } 183 str[i] = '\0'; 184 185 *pByteLen = i; 186 187 return str; 188 } 189 190 VOID FASTCALL 191 NewTextMetricW2A(NEWTEXTMETRICA *tma, NEWTEXTMETRICW *tmw) 192 { 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; 198 } 199 200 VOID FASTCALL 201 NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw) 202 { 203 NewTextMetricW2A(&tma->ntmTm, &tmw->ntmTm); 204 tma->ntmFontSig = tmw->ntmFontSig; 205 } 206 207 // IntFontFamilyCompareEx's flags 208 #define IFFCX_CHARSET 1 209 #define IFFCX_STYLE 2 210 211 FORCEINLINE int FASTCALL 212 IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1, 213 const FONTFAMILYINFO *ffi2, DWORD dwCompareFlags) 214 { 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); 219 if (cmp) 220 return cmp; 221 if (dwCompareFlags & IFFCX_CHARSET) 222 { 223 if (plf1->lfCharSet < plf2->lfCharSet) 224 return -1; 225 if (plf1->lfCharSet > plf2->lfCharSet) 226 return 1; 227 } 228 if (dwCompareFlags & IFFCX_STYLE) 229 { 230 WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL); 231 WeightDiff2 = labs(plf2->lfWeight - FW_NORMAL); 232 if (WeightDiff1 < WeightDiff2) 233 return -1; 234 if (WeightDiff1 > WeightDiff2) 235 return 1; 236 if (plf1->lfItalic < plf2->lfItalic) 237 return -1; 238 if (plf1->lfItalic > plf2->lfItalic) 239 return 1; 240 } 241 return 0; 242 } 243 244 static int __cdecl 245 IntFontFamilyCompare(const void *ffi1, const void *ffi2) 246 { 247 return IntFontFamilyCompareEx(ffi1, ffi2, IFFCX_STYLE | IFFCX_CHARSET); 248 } 249 250 // IntEnumFontFamilies' flags: 251 #define IEFF_UNICODE 1 252 #define IEFF_EXTENDED 2 253 254 int FASTCALL 255 IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount, 256 const LOGFONTW *plf, DWORD dwFlags) 257 { 258 FONTFAMILYINFO *first, *last, *result; 259 DWORD dwCompareFlags = 0; 260 261 if (plf->lfFaceName[0]) 262 dwCompareFlags |= IFFCX_STYLE; 263 264 if ((dwFlags & IEFF_EXTENDED) && plf->lfCharSet == DEFAULT_CHARSET) 265 dwCompareFlags |= IFFCX_CHARSET; 266 267 first = InfoList; 268 last = &InfoList[nCount]; 269 270 /* std::unique(first, last, IntFontFamilyCompareEx); */ 271 if (first == last) 272 return 0; 273 274 result = first; 275 while (++first != last) 276 { 277 if (IntFontFamilyCompareEx(result, first, dwCompareFlags) != 0) 278 { 279 *(++result) = *first; 280 } 281 } 282 nCount = (int)(++result - InfoList); 283 284 return nCount; 285 } 286 287 static int FASTCALL 288 IntEnumFontFamilies(HDC Dc, const LOGFONTW *LogFont, PVOID EnumProc, LPARAM lParam, 289 DWORD dwFlags) 290 { 291 int FontFamilyCount; 292 PFONTFAMILYINFO Info; 293 int Ret = 1; 294 int i; 295 ENUMLOGFONTEXA EnumLogFontExA; 296 NEWTEXTMETRICEXA NewTextMetricExA; 297 LOGFONTW lfW; 298 LONG InfoCount; 299 ULONG DataSize; 300 NTSTATUS Status; 301 302 DataSize = INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO); 303 Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize); 304 if (Info == NULL) 305 { 306 return 1; 307 } 308 309 /* Initialize the LOGFONT structure */ 310 ZeroMemory(&lfW, sizeof(lfW)); 311 if (!LogFont) 312 { 313 lfW.lfCharSet = DEFAULT_CHARSET; 314 } 315 else 316 { 317 lfW.lfCharSet = LogFont->lfCharSet; 318 lfW.lfPitchAndFamily = LogFont->lfPitchAndFamily; 319 StringCbCopyW(lfW.lfFaceName, sizeof(lfW.lfFaceName), LogFont->lfFaceName); 320 } 321 322 /* Retrieve the font information */ 323 InfoCount = INITIAL_FAMILY_COUNT; 324 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount); 325 if (FontFamilyCount < 0) 326 { 327 RtlFreeHeap(GetProcessHeap(), 0, Info); 328 return 1; 329 } 330 331 /* Resize the buffer if the buffer is too small */ 332 if (INITIAL_FAMILY_COUNT < InfoCount) 333 { 334 RtlFreeHeap(GetProcessHeap(), 0, Info); 335 336 Status = RtlULongMult(InfoCount, sizeof(FONTFAMILYINFO), &DataSize); 337 if (!NT_SUCCESS(Status) || DataSize > LONG_MAX) 338 { 339 DPRINT1("Overflowed.\n"); 340 return 1; 341 } 342 Info = RtlAllocateHeap(GetProcessHeap(), 0, DataSize); 343 if (Info == NULL) 344 { 345 return 1; 346 } 347 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, &lfW, Info, &InfoCount); 348 if (FontFamilyCount < 0 || FontFamilyCount < InfoCount) 349 { 350 RtlFreeHeap(GetProcessHeap(), 0, Info); 351 return 1; 352 } 353 } 354 355 /* Sort and remove redundant information */ 356 qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare); 357 FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, &lfW, dwFlags); 358 359 /* call the callback */ 360 for (i = 0; i < FontFamilyCount; i++) 361 { 362 if (dwFlags & IEFF_UNICODE) 363 { 364 Ret = ((FONTENUMPROCW) EnumProc)( 365 (VOID*)&Info[i].EnumLogFontEx, 366 (VOID*)&Info[i].NewTextMetricEx, 367 Info[i].FontType, lParam); 368 } 369 else 370 { 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); 385 } 386 387 if(Ret == 0) 388 break; 389 } 390 391 RtlFreeHeap(GetProcessHeap(), 0, Info); 392 393 return Ret; 394 } 395 396 /* 397 * @implemented 398 */ 399 int WINAPI 400 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc, 401 LPARAM lParam, DWORD dwFlags) 402 { 403 if (lpLogfont) 404 { 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); 408 } 409 else 410 { 411 DPRINT("EnumFontFamiliesExW(%p, NULL, %p, %p, 0x%08lX)\n", 412 hdc, lpEnumFontFamExProc, lParam, dwFlags); 413 } 414 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, 415 IEFF_UNICODE | IEFF_EXTENDED); 416 } 417 418 419 /* 420 * @implemented 421 */ 422 int WINAPI 423 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc, 424 LPARAM lParam) 425 { 426 LOGFONTW LogFont; 427 428 DPRINT("EnumFontFamiliesW(%p, %S, %p, %p)\n", 429 hdc, lpszFamily, lpEnumFontFamProc, lParam); 430 431 ZeroMemory(&LogFont, sizeof(LOGFONTW)); 432 LogFont.lfCharSet = DEFAULT_CHARSET; 433 if (NULL != lpszFamily) 434 { 435 if (!*lpszFamily) return 1; 436 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE); 437 } 438 439 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, IEFF_UNICODE); 440 } 441 442 443 /* 444 * @implemented 445 */ 446 int WINAPI 447 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc, 448 LPARAM lParam, DWORD dwFlags) 449 { 450 LOGFONTW LogFontW, *pLogFontW; 451 452 if (lpLogfont) 453 { 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); 457 } 458 else 459 { 460 DPRINT("EnumFontFamiliesExA(%p, NULL, %p, %p, 0x%08lX)\n", 461 hdc, lpEnumFontFamExProc, lParam, dwFlags); 462 } 463 464 if (lpLogfont) 465 { 466 LogFontA2W(&LogFontW,lpLogfont); 467 pLogFontW = &LogFontW; 468 } 469 else pLogFontW = NULL; 470 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); 473 } 474 475 476 /* 477 * @implemented 478 */ 479 int WINAPI 480 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc, 481 LPARAM lParam) 482 { 483 LOGFONTW LogFont; 484 485 DPRINT("EnumFontFamiliesA(%p, %s, %p, %p)\n", 486 hdc, lpszFamily, lpEnumFontFamProc, lParam); 487 488 ZeroMemory(&LogFont, sizeof(LOGFONTW)); 489 LogFont.lfCharSet = DEFAULT_CHARSET; 490 if (NULL != lpszFamily) 491 { 492 if (!*lpszFamily) return 1; 493 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE); 494 } 495 496 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, 0); 497 } 498 499 500 /* 501 * @implemented 502 */ 503 DWORD 504 WINAPI 505 GetCharacterPlacementA( 506 HDC hdc, 507 LPCSTR lpString, 508 INT uCount, 509 INT nMaxExtent, 510 GCP_RESULTSA *lpResults, 511 DWORD dwFlags) 512 { 513 WCHAR *lpStringW; 514 INT uCountW; 515 GCP_RESULTSW resultsW; 516 DWORD ret; 517 UINT font_cp; 518 519 if ( !lpString || uCount <= 0 || !lpResults || (nMaxExtent < 0 && nMaxExtent != -1 ) ) 520 { 521 SetLastError(ERROR_INVALID_PARAMETER); 522 return 0; 523 } 524 /* TRACE("%s, %d, %d, 0x%08x\n", 525 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags); 526 */ 527 /* both structs are equal in size */ 528 memcpy(&resultsW, lpResults, sizeof(resultsW)); 529 530 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp); 531 if (lpStringW == NULL) 532 { 533 return 0; 534 } 535 if(lpResults->lpOutString) 536 { 537 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW); 538 if (resultsW.lpOutString == NULL) 539 { 540 HeapFree(GetProcessHeap(), 0, lpStringW); 541 return 0; 542 } 543 } 544 545 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags); 546 547 lpResults->nGlyphs = resultsW.nGlyphs; 548 lpResults->nMaxFit = resultsW.nMaxFit; 549 550 if(lpResults->lpOutString) 551 { 552 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW, 553 lpResults->lpOutString, uCount, NULL, NULL ); 554 } 555 556 HeapFree(GetProcessHeap(), 0, lpStringW); 557 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString); 558 559 return ret; 560 } 561 562 563 /* 564 * @implemented 565 */ 566 DWORD 567 WINAPI 568 GetCharacterPlacementW( 569 HDC hdc, 570 LPCWSTR lpString, 571 INT uCount, 572 INT nMaxExtent, 573 GCP_RESULTSW *lpResults, 574 DWORD dwFlags 575 ) 576 { 577 DWORD ret=0; 578 SIZE size; 579 UINT i, nSet; 580 DPRINT("GetCharacterPlacementW\n"); 581 582 if (dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags); 583 if (lpResults->lpClass) DPRINT("classes not implemented\n"); 584 585 nSet = (UINT)uCount; 586 if (nSet > lpResults->nGlyphs) 587 nSet = lpResults->nGlyphs; 588 589 /* return number of initialized fields */ 590 lpResults->nGlyphs = nSet; 591 592 if (dwFlags & GCP_REORDER) 593 { 594 if (LoadLPK(LPK_GCP)) 595 return LpkGetCharacterPlacement(hdc, lpString, uCount, nMaxExtent, lpResults, dwFlags, 0); 596 } 597 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 ); 602 603 if (lpResults->lpOrder) 604 { 605 for (i = 0; i < nSet; i++) 606 lpResults->lpOrder[i] = i; 607 } 608 609 /* FIXME: Will use the placement chars */ 610 if (lpResults->lpDx) 611 { 612 int c; 613 for (i = 0; i < nSet; i++) 614 { 615 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c)) 616 lpResults->lpDx[i]= c; 617 } 618 } 619 620 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER)) 621 { 622 int pos = 0; 623 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); 628 } 629 630 if (lpResults->lpGlyphs) 631 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0); 632 633 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size)) 634 ret = MAKELONG(size.cx, size.cy); 635 636 return ret; 637 } 638 639 DWORD 640 WINAPI 641 NewGetCharacterPlacementW( 642 HDC hdc, 643 LPCWSTR lpString, 644 INT uCount, 645 INT nMaxExtent, 646 GCP_RESULTSW *lpResults, 647 DWORD dwFlags 648 ) 649 { 650 ULONG nSet; 651 SIZE Size = {0,0}; 652 653 if ( !lpString || uCount <= 0 || (nMaxExtent < 0 && nMaxExtent != -1 ) ) 654 { 655 SetLastError(ERROR_INVALID_PARAMETER); 656 return 0; 657 } 658 659 if ( !lpResults ) 660 { 661 if ( GetTextExtentPointW(hdc, lpString, uCount, &Size) ) 662 { 663 return MAKELONG(Size.cx, Size.cy); 664 } 665 return 0; 666 } 667 668 nSet = uCount; 669 if ( nSet > lpResults->nGlyphs ) 670 nSet = lpResults->nGlyphs; 671 672 return NtGdiGetCharacterPlacementW( hdc, 673 (LPWSTR)lpString, 674 nSet, 675 nMaxExtent, 676 lpResults, 677 dwFlags); 678 } 679 680 /* 681 * @implemented 682 * 683 */ 684 BOOL 685 WINAPI 686 GetCharABCWidthsFloatW(HDC hdc, 687 UINT FirstChar, 688 UINT LastChar, 689 LPABCFLOAT abcF) 690 { 691 DPRINT("GetCharABCWidthsFloatW\n"); 692 if ((!abcF) || (FirstChar > LastChar)) 693 { 694 SetLastError(ERROR_INVALID_PARAMETER); 695 return FALSE; 696 } 697 return NtGdiGetCharABCWidthsW( hdc, 698 FirstChar, 699 (ULONG)(LastChar - FirstChar + 1), 700 (PWCHAR) NULL, 701 0, 702 (PVOID)abcF); 703 } 704 705 /* 706 * @implemented 707 * 708 */ 709 BOOL 710 WINAPI 711 GetCharWidthFloatW(HDC hdc, 712 UINT iFirstChar, 713 UINT iLastChar, 714 PFLOAT pxBuffer) 715 { 716 DPRINT("GetCharWidthsFloatW\n"); 717 if ((!pxBuffer) || (iFirstChar > iLastChar)) 718 { 719 SetLastError(ERROR_INVALID_PARAMETER); 720 return FALSE; 721 } 722 return NtGdiGetCharWidthW( hdc, 723 iFirstChar, 724 (ULONG)(iLastChar - iFirstChar + 1), 725 (PWCHAR) NULL, 726 0, 727 (PVOID) pxBuffer); 728 } 729 730 /* 731 * @implemented 732 * 733 */ 734 BOOL 735 WINAPI 736 GetCharWidthW(HDC hdc, 737 UINT iFirstChar, 738 UINT iLastChar, 739 LPINT lpBuffer) 740 { 741 DPRINT("GetCharWidthsW\n"); 742 if ((!lpBuffer) || (iFirstChar > iLastChar)) 743 { 744 SetLastError(ERROR_INVALID_PARAMETER); 745 return FALSE; 746 } 747 return NtGdiGetCharWidthW( hdc, 748 iFirstChar, 749 (ULONG)(iLastChar - iFirstChar + 1), 750 (PWCHAR) NULL, 751 GCW_NOFLOAT, 752 (PVOID) lpBuffer); 753 } 754 755 /* 756 * @implemented 757 * 758 */ 759 BOOL 760 WINAPI 761 GetCharWidth32W(HDC hdc, 762 UINT iFirstChar, 763 UINT iLastChar, 764 LPINT lpBuffer) 765 { 766 DPRINT("GetCharWidths32W\n"); 767 if ((!lpBuffer) || (iFirstChar > iLastChar)) 768 { 769 SetLastError(ERROR_INVALID_PARAMETER); 770 return FALSE; 771 } 772 return NtGdiGetCharWidthW( hdc, 773 iFirstChar, 774 (ULONG)(iLastChar - iFirstChar + 1), 775 (PWCHAR) NULL, 776 GCW_NOFLOAT|GCW_WIN32, 777 (PVOID) lpBuffer); 778 } 779 780 781 /* 782 * @implemented 783 * 784 */ 785 BOOL 786 WINAPI 787 GetCharABCWidthsW(HDC hdc, 788 UINT FirstChar, 789 UINT LastChar, 790 LPABC lpabc) 791 { 792 DPRINT("GetCharABCWidthsW\n"); 793 if ((!lpabc) || (FirstChar > LastChar)) 794 { 795 SetLastError(ERROR_INVALID_PARAMETER); 796 return FALSE; 797 } 798 return NtGdiGetCharABCWidthsW( hdc, 799 FirstChar, 800 (ULONG)(LastChar - FirstChar + 1), 801 (PWCHAR) NULL, 802 GCABCW_NOFLOAT, 803 (PVOID)lpabc); 804 } 805 806 /* 807 * @implemented 808 */ 809 BOOL 810 WINAPI 811 GetCharWidthA( 812 HDC hdc, 813 UINT iFirstChar, 814 UINT iLastChar, 815 LPINT lpBuffer 816 ) 817 { 818 INT wlen, count = 0; 819 LPSTR str; 820 LPWSTR wstr; 821 BOOL ret = TRUE; 822 823 DPRINT("GetCharWidthsA\n"); 824 825 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 826 if (!str) 827 return FALSE; 828 829 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 830 if (!wstr) 831 { 832 HeapFree(GetProcessHeap(), 0, str); 833 return FALSE; 834 } 835 836 ret = NtGdiGetCharWidthW( hdc, 837 wstr[0], 838 (ULONG) count, 839 (PWCHAR) wstr, 840 GCW_NOFLOAT, 841 (PVOID) lpBuffer); 842 843 HeapFree(GetProcessHeap(), 0, str); 844 HeapFree(GetProcessHeap(), 0, wstr); 845 846 return ret; 847 } 848 849 /* 850 * @implemented 851 */ 852 BOOL 853 WINAPI 854 GetCharWidth32A( 855 HDC hdc, 856 UINT iFirstChar, 857 UINT iLastChar, 858 LPINT lpBuffer 859 ) 860 { 861 INT wlen, count = 0; 862 LPSTR str; 863 LPWSTR wstr; 864 BOOL ret = TRUE; 865 866 DPRINT("GetCharWidths32A\n"); 867 868 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 869 if (!str) 870 return FALSE; 871 872 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 873 if (!wstr) 874 { 875 HeapFree(GetProcessHeap(), 0, str); 876 return FALSE; 877 } 878 879 ret = NtGdiGetCharWidthW( hdc, 880 wstr[0], 881 (ULONG) count, 882 (PWCHAR) wstr, 883 GCW_NOFLOAT|GCW_WIN32, 884 (PVOID) lpBuffer); 885 886 HeapFree(GetProcessHeap(), 0, str); 887 HeapFree(GetProcessHeap(), 0, wstr); 888 889 return ret; 890 } 891 892 /* 893 * @implemented 894 */ 895 BOOL 896 APIENTRY 897 GetCharWidthFloatA( 898 HDC hdc, 899 UINT iFirstChar, 900 UINT iLastChar, 901 PFLOAT pxBuffer 902 ) 903 { 904 INT wlen, count = 0; 905 LPSTR str; 906 LPWSTR wstr; 907 BOOL ret = TRUE; 908 909 DPRINT("GetCharWidthsFloatA\n"); 910 911 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 912 if (!str) 913 return FALSE; 914 915 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 916 if (!wstr) 917 { 918 HeapFree(GetProcessHeap(), 0, str); 919 return FALSE; 920 } 921 ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer); 922 923 HeapFree(GetProcessHeap(), 0, str); 924 HeapFree(GetProcessHeap(), 0, wstr); 925 926 return ret; 927 } 928 929 /* 930 * @implemented 931 */ 932 BOOL 933 APIENTRY 934 GetCharABCWidthsA( 935 HDC hdc, 936 UINT iFirstChar, 937 UINT iLastChar, 938 LPABC lpabc 939 ) 940 { 941 INT wlen, count = 0; 942 LPSTR str; 943 LPWSTR wstr; 944 BOOL ret = TRUE; 945 946 DPRINT("GetCharABCWidthsA\n"); 947 948 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 949 if (!str) 950 return FALSE; 951 952 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 953 if (!wstr) 954 { 955 HeapFree(GetProcessHeap(), 0, str); 956 return FALSE; 957 } 958 959 ret = NtGdiGetCharABCWidthsW( hdc, 960 wstr[0], 961 wlen - 1, 962 (PWCHAR)wstr, 963 GCABCW_NOFLOAT, 964 (PVOID)lpabc); 965 966 HeapFree(GetProcessHeap(), 0, str); 967 HeapFree(GetProcessHeap(), 0, wstr); 968 969 return ret; 970 } 971 972 /* 973 * @implemented 974 */ 975 BOOL 976 APIENTRY 977 GetCharABCWidthsFloatA( 978 HDC hdc, 979 UINT iFirstChar, 980 UINT iLastChar, 981 LPABCFLOAT lpABCF 982 ) 983 { 984 INT wlen, count = 0; 985 LPSTR str; 986 LPWSTR wstr; 987 BOOL ret = TRUE; 988 989 DPRINT("GetCharABCWidthsFloatA\n"); 990 991 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 992 if (!str) 993 return FALSE; 994 995 wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL ); 996 if (!wstr) 997 { 998 HeapFree( GetProcessHeap(), 0, str ); 999 return FALSE; 1000 } 1001 ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF); 1002 1003 HeapFree( GetProcessHeap(), 0, str ); 1004 HeapFree( GetProcessHeap(), 0, wstr ); 1005 1006 return ret; 1007 } 1008 1009 /* 1010 * @implemented 1011 */ 1012 BOOL 1013 WINAPI 1014 GetCharABCWidthsI(HDC hdc, 1015 UINT giFirst, 1016 UINT cgi, 1017 LPWORD pgi, 1018 LPABC lpabc) 1019 { 1020 DPRINT("GetCharABCWidthsI\n"); 1021 return NtGdiGetCharABCWidthsW( hdc, 1022 giFirst, 1023 (ULONG) cgi, 1024 (PWCHAR) pgi, 1025 GCABCW_NOFLOAT|GCABCW_INDICES, 1026 (PVOID)lpabc); 1027 } 1028 1029 /* 1030 * @implemented 1031 */ 1032 BOOL 1033 WINAPI 1034 GetCharWidthI(HDC hdc, 1035 UINT giFirst, 1036 UINT cgi, 1037 LPWORD pgi, 1038 LPINT lpBuffer 1039 ) 1040 { 1041 DPRINT("GetCharWidthsI\n"); 1042 if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max. 1043 { 1044 SetLastError(ERROR_INVALID_PARAMETER); 1045 return FALSE; 1046 } 1047 if (!cgi) return TRUE; 1048 return NtGdiGetCharWidthW( hdc, 1049 giFirst, 1050 cgi, 1051 (PWCHAR) pgi, 1052 GCW_INDICES|GCW_NOFLOAT|GCW_WIN32, 1053 (PVOID) lpBuffer ); 1054 } 1055 1056 /* 1057 * @implemented 1058 */ 1059 DWORD 1060 WINAPI 1061 GetFontLanguageInfo( 1062 HDC hDc 1063 ) 1064 { 1065 DWORD Gcp = 0, Ret = 0; 1066 if (gbLpk) 1067 { 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); 1071 } 1072 Gcp = GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR); 1073 if ( Gcp == GCP_ERROR) 1074 return Gcp; 1075 else 1076 Ret = Gcp | Ret; 1077 return Ret; 1078 } 1079 1080 /* 1081 * @implemented 1082 */ 1083 DWORD 1084 WINAPI 1085 GetGlyphIndicesA( 1086 HDC hdc, 1087 LPCSTR lpstr, 1088 INT count, 1089 LPWORD pgi, 1090 DWORD flags 1091 ) 1092 { 1093 DWORD Ret; 1094 WCHAR *lpstrW; 1095 INT countW; 1096 1097 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL); 1098 1099 if (lpstrW == NULL) 1100 return GDI_ERROR; 1101 1102 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags); 1103 HeapFree(GetProcessHeap(), 0, lpstrW); 1104 return Ret; 1105 } 1106 1107 /* 1108 * @implemented 1109 */ 1110 DWORD 1111 WINAPI 1112 GetGlyphOutlineA( 1113 HDC hdc, 1114 UINT uChar, 1115 UINT uFormat, 1116 LPGLYPHMETRICS lpgm, 1117 DWORD cbBuffer, 1118 LPVOID lpvBuffer, 1119 CONST MAT2 *lpmat2 1120 ) 1121 { 1122 1123 LPWSTR p = NULL; 1124 DWORD ret; 1125 UINT c; 1126 DPRINT("GetGlyphOutlineA uChar %x\n", uChar); 1127 if (!lpgm || !lpmat2) return GDI_ERROR; 1128 if(!(uFormat & GGO_GLYPH_INDEX)) 1129 { 1130 int len; 1131 char mbchs[2]; 1132 if(uChar > 0xff) /* but, 2 bytes character only */ 1133 { 1134 len = 2; 1135 mbchs[0] = (uChar & 0xff00) >> 8; 1136 mbchs[1] = (uChar & 0xff); 1137 } 1138 else 1139 { 1140 len = 1; 1141 mbchs[0] = (uChar & 0xff); 1142 } 1143 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL); 1144 if(!p) 1145 return GDI_ERROR; 1146 c = p[0]; 1147 } 1148 else 1149 c = uChar; 1150 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); 1151 HeapFree(GetProcessHeap(), 0, p); 1152 return ret; 1153 } 1154 1155 1156 /* 1157 * @implemented 1158 */ 1159 DWORD 1160 WINAPI 1161 GetGlyphOutlineW( 1162 HDC hdc, 1163 UINT uChar, 1164 UINT uFormat, 1165 LPGLYPHMETRICS lpgm, 1166 DWORD cbBuffer, 1167 LPVOID lpvBuffer, 1168 CONST MAT2 *lpmat2 1169 ) 1170 { 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); 1175 } 1176 1177 /* 1178 * @unimplemented 1179 */ 1180 DWORD 1181 WINAPI 1182 GetGlyphOutlineWow( 1183 DWORD a0, 1184 DWORD a1, 1185 DWORD a2, 1186 DWORD a3, 1187 DWORD a4, 1188 DWORD a5, 1189 DWORD a6 1190 ) 1191 { 1192 UNIMPLEMENTED; 1193 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1194 return 0; 1195 } 1196 1197 /* 1198 * @implemented 1199 */ 1200 UINT 1201 APIENTRY 1202 GetOutlineTextMetricsA( 1203 HDC hdc, 1204 UINT cbData, 1205 LPOUTLINETEXTMETRICA lpOTM 1206 ) 1207 { 1208 char buf[512], *ptr; 1209 UINT ret, needed; 1210 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf; 1211 OUTLINETEXTMETRICA *output = lpOTM; 1212 INT left, len; 1213 1214 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0) 1215 return 0; 1216 if(ret > sizeof(buf)) 1217 { 1218 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret); 1219 if (lpOTMW == NULL) 1220 { 1221 return 0; 1222 } 1223 } 1224 GetOutlineTextMetricsW(hdc, ret, lpOTMW); 1225 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); 1243 1244 if(!lpOTM) 1245 { 1246 ret = needed; 1247 goto end; 1248 } 1249 1250 DPRINT("needed = %u\n", needed); 1251 if(needed > cbData) 1252 { 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 1255 the end. */ 1256 output = HeapAlloc(GetProcessHeap(), 0, needed); 1257 if (output == NULL) 1258 { 1259 goto end; 1260 } 1261 } 1262 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; 1291 1292 1293 ptr = (char*)(output + 1); 1294 left = needed - sizeof(*output); 1295 1296 if(lpOTMW->otmpFamilyName) 1297 { 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); 1302 left -= len; 1303 ptr += len; 1304 } 1305 else 1306 output->otmpFamilyName = 0; 1307 1308 if(lpOTMW->otmpFaceName) 1309 { 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); 1314 left -= len; 1315 ptr += len; 1316 } 1317 else 1318 output->otmpFaceName = 0; 1319 1320 if(lpOTMW->otmpStyleName) 1321 { 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); 1326 left -= len; 1327 ptr += len; 1328 } 1329 else 1330 output->otmpStyleName = 0; 1331 1332 if(lpOTMW->otmpFullName) 1333 { 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); 1338 left -= len; 1339 } 1340 else 1341 output->otmpFullName = 0; 1342 1343 ASSERT(left == 0); 1344 1345 if(output != lpOTM) 1346 { 1347 memcpy(lpOTM, output, cbData); 1348 HeapFree(GetProcessHeap(), 0, output); 1349 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 */ 1354 1355 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize) 1356 lpOTM->otmpFaceName = 0; /* doesn't fit */ 1357 1358 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize) 1359 lpOTM->otmpStyleName = 0; /* doesn't fit */ 1360 1361 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize) 1362 lpOTM->otmpFullName = 0; /* doesn't fit */ 1363 } 1364 1365 end: 1366 if(lpOTMW != (OUTLINETEXTMETRICW *)buf) 1367 HeapFree(GetProcessHeap(), 0, lpOTMW); 1368 1369 return ret; 1370 } 1371 1372 /* Performs a device to world transformation on the specified size (which 1373 * is in integer format). 1374 */ 1375 static inline INT INTERNAL_YDSTOWS(XFORM *xForm, INT height) 1376 { 1377 double floatHeight; 1378 1379 /* Perform operation with floating point */ 1380 floatHeight = (double)height * xForm->eM22; 1381 /* Round to integers */ 1382 return GDI_ROUND(floatHeight); 1383 } 1384 1385 /* scale width and height but don't mirror them */ 1386 static inline INT width_to_LP( XFORM *xForm, INT width ) 1387 { 1388 return GDI_ROUND( (double)width * fabs( xForm->eM11)); 1389 } 1390 1391 static inline INT height_to_LP( XFORM *xForm, INT height ) 1392 { 1393 return GDI_ROUND( (double)height * fabs( xForm->eM22 )); 1394 } 1395 1396 /* 1397 * @implemented 1398 */ 1399 UINT 1400 APIENTRY 1401 GetOutlineTextMetricsW( 1402 HDC hdc, 1403 UINT cbData, 1404 LPOUTLINETEXTMETRICW lpOTM 1405 ) 1406 { 1407 TMDIFF Tmd; // Should not be zero. 1408 UINT Size, AvailableSize = 0, StringSize; 1409 XFORM DevToWorld; 1410 OUTLINETEXTMETRICW* LocalOTM; 1411 WCHAR* Str; 1412 BYTE* Ptr; 1413 1414 /* Get the structure */ 1415 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, 0, NULL, &Tmd); 1416 if (!Size) 1417 return 0; 1418 if (!lpOTM || (cbData < sizeof(*lpOTM))) 1419 return Size; 1420 1421 LocalOTM = HeapAlloc(GetProcessHeap(), 0, Size); 1422 LocalOTM->otmSize = Size; 1423 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, Size, LocalOTM, &Tmd); 1424 if (!Size) 1425 { 1426 HeapFree(GetProcessHeap(), 0, LocalOTM); 1427 return 0; 1428 } 1429 1430 if (!NtGdiGetTransform(hdc, GdiDeviceSpaceToWorldSpace, &DevToWorld)) 1431 { 1432 DPRINT1("NtGdiGetTransform failed!\n"); 1433 HeapFree(GetProcessHeap(), 0, LocalOTM); 1434 SetLastError(ERROR_INVALID_HANDLE); 1435 return 0; 1436 } 1437 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); 1473 1474 /* Copy what we can */ 1475 CopyMemory(lpOTM, LocalOTM, min(Size, cbData)); 1476 1477 lpOTM->otmpFamilyName = NULL; 1478 lpOTM->otmpFaceName = NULL; 1479 lpOTM->otmpStyleName = NULL; 1480 lpOTM->otmpFullName = NULL; 1481 1482 Size = sizeof(*lpOTM); 1483 AvailableSize = cbData - Size; 1484 Ptr = (BYTE*)lpOTM + sizeof(*lpOTM); 1485 1486 /* Fix string values up */ 1487 if (LocalOTM->otmpFamilyName) 1488 { 1489 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFamilyName); 1490 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1491 if (AvailableSize >= StringSize) 1492 { 1493 CopyMemory(Ptr, Str, StringSize); 1494 lpOTM->otmpFamilyName = (PSTR)(Ptr - (BYTE*)lpOTM); 1495 Ptr += StringSize; 1496 AvailableSize -= StringSize; 1497 Size += StringSize; 1498 } 1499 } 1500 1501 if (LocalOTM->otmpFaceName) 1502 { 1503 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFaceName); 1504 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1505 if (AvailableSize >= StringSize) 1506 { 1507 CopyMemory(Ptr, Str, StringSize); 1508 lpOTM->otmpFaceName = (PSTR)(Ptr - (BYTE*)lpOTM); 1509 Ptr += StringSize; 1510 AvailableSize -= StringSize; 1511 Size += StringSize; 1512 } 1513 } 1514 1515 if (LocalOTM->otmpStyleName) 1516 { 1517 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpStyleName); 1518 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1519 if (AvailableSize >= StringSize) 1520 { 1521 CopyMemory(Ptr, Str, StringSize); 1522 lpOTM->otmpStyleName = (PSTR)(Ptr - (BYTE*)lpOTM); 1523 Ptr += StringSize; 1524 AvailableSize -= StringSize; 1525 Size += StringSize; 1526 } 1527 } 1528 1529 if (LocalOTM->otmpFullName) 1530 { 1531 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFullName); 1532 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1533 if (AvailableSize >= StringSize) 1534 { 1535 CopyMemory(Ptr, Str, StringSize); 1536 lpOTM->otmpFullName = (PSTR)(Ptr - (BYTE*)lpOTM); 1537 Ptr += StringSize; 1538 AvailableSize -= StringSize; 1539 Size += StringSize; 1540 } 1541 } 1542 1543 lpOTM->otmSize = Size; 1544 1545 HeapFree(GetProcessHeap(), 0, LocalOTM); 1546 1547 return Size; 1548 } 1549 1550 /* 1551 * @implemented 1552 */ 1553 DWORD 1554 WINAPI 1555 GetKerningPairsW(HDC hdc, 1556 ULONG cPairs, 1557 LPKERNINGPAIR pkpDst) 1558 { 1559 if ((cPairs != 0) || (pkpDst == 0)) 1560 { 1561 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst); 1562 } 1563 else 1564 { 1565 SetLastError(ERROR_INVALID_PARAMETER); 1566 return 0; 1567 } 1568 } 1569 1570 /* 1571 * @implemented 1572 */ 1573 DWORD 1574 WINAPI 1575 GetKerningPairsA( HDC hDC, 1576 DWORD cPairs, 1577 LPKERNINGPAIR kern_pairA ) 1578 { 1579 INT charset; 1580 CHARSETINFO csi; 1581 CPINFO cpi; 1582 DWORD i, total_kern_pairs, kern_pairs_copied = 0; 1583 KERNINGPAIR *kern_pairW; 1584 1585 if (!cPairs && kern_pairA) 1586 { 1587 SetLastError(ERROR_INVALID_PARAMETER); 1588 return 0; 1589 } 1590 1591 charset = GetTextCharset(hDC); 1592 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET)) 1593 { 1594 DPRINT1("Can't find codepage for charset %d\n", charset); 1595 return 0; 1596 } 1597 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed 1598 * to fail on an invalid character for CP_SYMBOL. 1599 */ 1600 cpi.DefaultChar[0] = 0; 1601 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi)) 1602 { 1603 DPRINT1("Can't find codepage %u info\n", csi.ciACP); 1604 return 0; 1605 } 1606 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP); 1607 1608 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL); 1609 if (!total_kern_pairs) return 0; 1610 1611 if (!cPairs && !kern_pairA) return total_kern_pairs; 1612 1613 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW)); 1614 if (kern_pairW == NULL) 1615 { 1616 return 0; 1617 } 1618 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW); 1619 1620 for (i = 0; i < total_kern_pairs; i++) 1621 { 1622 char first, second; 1623 1624 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL)) 1625 continue; 1626 1627 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL)) 1628 continue; 1629 1630 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0]) 1631 continue; 1632 1633 if (kern_pairA) 1634 { 1635 if (kern_pairs_copied >= cPairs) break; 1636 1637 kern_pairA->wFirst = (BYTE)first; 1638 kern_pairA->wSecond = (BYTE)second; 1639 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount; 1640 kern_pairA++; 1641 } 1642 kern_pairs_copied++; 1643 } 1644 1645 HeapFree(GetProcessHeap(), 0, kern_pairW); 1646 1647 return kern_pairs_copied; 1648 } 1649 1650 1651 1652 /* 1653 * @implemented 1654 */ 1655 HFONT 1656 WINAPI 1657 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd) 1658 { 1659 if (elfexd) 1660 { 1661 ENUMLOGFONTEXDVW Logfont; 1662 1663 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd, 1664 &Logfont.elfEnumLogfontEx ); 1665 1666 RtlCopyMemory( &Logfont.elfDesignVector, 1667 (PVOID) &elfexd->elfDesignVector, 1668 sizeof(DESIGNVECTOR)); 1669 1670 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL); 1671 } 1672 else return NULL; 1673 } 1674 1675 1676 /* 1677 * @implemented 1678 */ 1679 HFONT 1680 WINAPI 1681 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd) 1682 { 1683 /* Msdn: Note, this function ignores the elfDesignVector member in 1684 ENUMLOGFONTEXDV. 1685 */ 1686 if ( elfexd ) 1687 { 1688 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL ); 1689 } 1690 else return NULL; 1691 } 1692 1693 1694 /* 1695 * @implemented 1696 */ 1697 HFONT 1698 WINAPI 1699 CreateFontIndirectA( 1700 CONST LOGFONTA *lplf 1701 ) 1702 { 1703 if (lplf) 1704 { 1705 LOGFONTW tlf; 1706 1707 LogFontA2W(&tlf, lplf); 1708 return CreateFontIndirectW(&tlf); 1709 } 1710 else return NULL; 1711 } 1712 1713 1714 #if DBG 1715 VOID DumpFamilyInfo(const FONTFAMILYINFO *Info, LONG Count) 1716 { 1717 LONG i; 1718 const LOGFONTW *plf; 1719 1720 DPRINT1("---\n"); 1721 DPRINT1("Count: %d\n", Count); 1722 for (i = 0; i < Count; ++i) 1723 { 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); 1728 } 1729 } 1730 1731 VOID DoFontSystemUnittest(VOID) 1732 { 1733 #ifndef RTL_SOFT_ASSERT 1734 #define RTL_SOFT_ASSERT(exp) \ 1735 (void)((!(exp)) ? \ 1736 DbgPrint("%s(%d): Soft assertion failed\n Expression: %s\n", __FILE__, __LINE__, #exp), FALSE : TRUE) 1737 #define RTL_SOFT_ASSERT_defined 1738 #endif 1739 1740 LOGFONTW LogFont; 1741 FONTFAMILYINFO Info[4]; 1742 UNICODE_STRING Str1, Str2; 1743 LONG ret, InfoCount; 1744 1745 //DumpFontInfo(TRUE); 1746 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); 1756 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); 1768 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); 1773 1774 RtlInitUnicodeString(&Str1, Info[0].EnumLogFontEx.elfFullName); 1775 RtlInitUnicodeString(&Str2, L"Tahoma"); 1776 ret = RtlCompareUnicodeString(&Str1, &Str2, TRUE); 1777 RTL_SOFT_ASSERT(ret == 0); 1778 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); 1789 1790 #ifdef RTL_SOFT_ASSERT_defined 1791 #undef RTL_SOFT_ASSERT_defined 1792 #undef RTL_SOFT_ASSERT 1793 #endif 1794 } 1795 #endif 1796 1797 /* EOF */ 1798 /* 1799 * @implemented 1800 */ 1801 HFONT 1802 WINAPI 1803 CreateFontIndirectW( 1804 CONST LOGFONTW *lplf 1805 ) 1806 { 1807 #if 0 1808 static BOOL bDidTest = FALSE; 1809 if (!bDidTest) 1810 { 1811 bDidTest = TRUE; 1812 DoFontSystemUnittest(); 1813 } 1814 #endif 1815 if (lplf) 1816 { 1817 ENUMLOGFONTEXDVW Logfont; 1818 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)); 1828 1829 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES 1830 1831 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR)); 1832 1833 return CreateFontIndirectExW(&Logfont); 1834 } 1835 else return NULL; 1836 } 1837 1838 1839 /* 1840 * @implemented 1841 */ 1842 HFONT 1843 WINAPI 1844 CreateFontA( 1845 int nHeight, 1846 int nWidth, 1847 int nEscapement, 1848 int nOrientation, 1849 int fnWeight, 1850 DWORD fdwItalic, 1851 DWORD fdwUnderline, 1852 DWORD fdwStrikeOut, 1853 DWORD fdwCharSet, 1854 DWORD fdwOutputPrecision, 1855 DWORD fdwClipPrecision, 1856 DWORD fdwQuality, 1857 DWORD fdwPitchAndFamily, 1858 LPCSTR lpszFace 1859 ) 1860 { 1861 ANSI_STRING StringA; 1862 UNICODE_STRING StringU; 1863 HFONT ret; 1864 1865 RtlInitAnsiString(&StringA, (LPSTR)lpszFace); 1866 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); 1867 1868 ret = CreateFontW(nHeight, 1869 nWidth, 1870 nEscapement, 1871 nOrientation, 1872 fnWeight, 1873 fdwItalic, 1874 fdwUnderline, 1875 fdwStrikeOut, 1876 fdwCharSet, 1877 fdwOutputPrecision, 1878 fdwClipPrecision, 1879 fdwQuality, 1880 fdwPitchAndFamily, 1881 StringU.Buffer); 1882 1883 RtlFreeUnicodeString(&StringU); 1884 1885 return ret; 1886 } 1887 1888 1889 /* 1890 * @implemented 1891 */ 1892 HFONT 1893 WINAPI 1894 CreateFontW( 1895 int nHeight, 1896 int nWidth, 1897 int nEscapement, 1898 int nOrientation, 1899 int nWeight, 1900 DWORD fnItalic, 1901 DWORD fdwUnderline, 1902 DWORD fdwStrikeOut, 1903 DWORD fdwCharSet, 1904 DWORD fdwOutputPrecision, 1905 DWORD fdwClipPrecision, 1906 DWORD fdwQuality, 1907 DWORD fdwPitchAndFamily, 1908 LPCWSTR lpszFace 1909 ) 1910 { 1911 LOGFONTW logfont; 1912 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; 1926 1927 if (NULL != lpszFace) 1928 { 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'; 1933 } 1934 else 1935 { 1936 logfont.lfFaceName[0] = L'\0'; 1937 } 1938 1939 return CreateFontIndirectW(&logfont); 1940 } 1941 1942 1943 /* 1944 * @unimplemented 1945 */ 1946 BOOL 1947 WINAPI 1948 CreateScalableFontResourceA( 1949 DWORD fdwHidden, 1950 LPCSTR lpszFontRes, 1951 LPCSTR lpszFontFile, 1952 LPCSTR lpszCurrentPath 1953 ) 1954 { 1955 return FALSE; 1956 } 1957 1958 1959 /* 1960 * @implemented 1961 */ 1962 int 1963 WINAPI 1964 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved ) 1965 { 1966 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM)) 1967 { 1968 SetLastError( ERROR_INVALID_PARAMETER ); 1969 return 0; 1970 } 1971 1972 return GdiAddFontResourceW(lpszFilename, fl,0); 1973 } 1974 1975 1976 /* 1977 * @implemented 1978 */ 1979 int 1980 WINAPI 1981 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved ) 1982 { 1983 NTSTATUS Status; 1984 PWSTR FilenameW; 1985 int rc; 1986 1987 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM)) 1988 { 1989 SetLastError( ERROR_INVALID_PARAMETER ); 1990 return 0; 1991 } 1992 1993 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename ); 1994 if ( !NT_SUCCESS (Status) ) 1995 { 1996 SetLastError (RtlNtStatusToDosError(Status)); 1997 return 0; 1998 } 1999 2000 rc = GdiAddFontResourceW ( FilenameW, fl, 0 ); 2001 HEAP_free ( FilenameW ); 2002 return rc; 2003 } 2004 2005 2006 /* 2007 * @implemented 2008 */ 2009 int 2010 WINAPI 2011 AddFontResourceA ( LPCSTR lpszFilename ) 2012 { 2013 NTSTATUS Status; 2014 PWSTR FilenameW; 2015 int rc = 0; 2016 2017 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename ); 2018 if ( !NT_SUCCESS (Status) ) 2019 { 2020 SetLastError (RtlNtStatusToDosError(Status)); 2021 } 2022 else 2023 { 2024 rc = GdiAddFontResourceW ( FilenameW, 0, 0); 2025 2026 HEAP_free ( FilenameW ); 2027 } 2028 return rc; 2029 } 2030 2031 2032 /* 2033 * @implemented 2034 */ 2035 int 2036 WINAPI 2037 AddFontResourceW ( LPCWSTR lpszFilename ) 2038 { 2039 return GdiAddFontResourceW ( lpszFilename, 0, 0 ); 2040 } 2041 2042 2043 /* 2044 * @implemented 2045 */ 2046 BOOL 2047 WINAPI 2048 RemoveFontResourceW(LPCWSTR lpFileName) 2049 { 2050 return RemoveFontResourceExW(lpFileName,0,0); 2051 } 2052 2053 2054 /* 2055 * @implemented 2056 */ 2057 BOOL 2058 WINAPI 2059 RemoveFontResourceA(LPCSTR lpFileName) 2060 { 2061 return RemoveFontResourceExA(lpFileName,0,0); 2062 } 2063 2064 /* 2065 * @unimplemented 2066 */ 2067 BOOL 2068 WINAPI 2069 RemoveFontResourceExA(LPCSTR lpFileName, 2070 DWORD fl, 2071 PVOID pdv 2072 ) 2073 { 2074 NTSTATUS Status; 2075 LPWSTR lpFileNameW; 2076 2077 /* FIXME the flags */ 2078 /* FIXME the pdv */ 2079 /* FIXME NtGdiRemoveFontResource handle flags and pdv */ 2080 2081 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName ); 2082 if (!NT_SUCCESS (Status)) 2083 SetLastError (RtlNtStatusToDosError(Status)); 2084 else 2085 { 2086 2087 HEAP_free ( lpFileNameW ); 2088 } 2089 2090 return 0; 2091 } 2092 2093 /* 2094 * @unimplemented 2095 */ 2096 BOOL 2097 WINAPI 2098 RemoveFontResourceExW(LPCWSTR lpFileName, 2099 DWORD fl, 2100 PVOID pdv) 2101 { 2102 /* FIXME the flags */ 2103 /* FIXME the pdv */ 2104 /* FIXME NtGdiRemoveFontResource handle flags and pdv */ 2105 DPRINT("RemoveFontResourceExW\n"); 2106 return 0; 2107 } 2108 2109 2110 /*********************************************************************** 2111 * GdiGetCharDimensions 2112 * 2113 * Gets the average width of the characters in the English alphabet. 2114 * 2115 * PARAMS 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. 2119 * 2120 * RETURNS 2121 * The average width of characters in the English alphabet. 2122 * 2123 * NOTES 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. 2130 * 2131 * SEE ALSO 2132 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect. 2133 * 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 2138 * case characters. 2139 */ 2140 /* 2141 * @implemented 2142 */ 2143 LONG 2144 WINAPI 2145 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height) 2146 { 2147 SIZE sz; 2148 TEXTMETRICW tm; 2149 static const WCHAR alphabet[] = 2150 { 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 2154 }; 2155 2156 if(!GetTextMetricsW(hdc, &tm)) return 0; 2157 2158 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0; 2159 2160 if (lptm) *lptm = tm; 2161 if (height) *height = tm.tmHeight; 2162 2163 return (sz.cx / 26 + 1) / 2; 2164 } 2165 2166 /************************************************************************* 2167 * TranslateCharsetInfo [GDI32.@] 2168 * 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. 2173 * 2174 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used, 2175 * only one codepage should be set in *lpSrc. 2176 * 2177 * RETURNS 2178 * TRUE on success, FALSE on failure. 2179 * 2180 */ 2181 /* 2182 * @implemented 2183 */ 2184 BOOL 2185 WINAPI 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 2191 */ 2192 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */ 2193 DWORD flags /* [in] determines interpretation of lpSrc */) 2194 { 2195 int index = 0; 2196 switch (flags) 2197 { 2198 case TCI_SRCFONTSIG: 2199 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++; 2200 break; 2201 case TCI_SRCCODEPAGE: 2202 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++; 2203 break; 2204 case TCI_SRCCHARSET: 2205 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++; 2206 break; 2207 case TCI_SRCLOCALE: 2208 { 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)) 2213 { 2214 while (index < MAXTCIINDEX && !(LocSig.lsCsbDefault[0]>>index & 0x0001)) index++; 2215 break; 2216 } 2217 } 2218 default: 2219 GdiSetLastError(ERROR_INVALID_PARAMETER); 2220 return FALSE; 2221 } 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)); 2226 return TRUE; 2227 } 2228 2229 2230 /* 2231 * @implemented 2232 */ 2233 DWORD 2234 WINAPI 2235 SetMapperFlags( 2236 HDC hDC, 2237 DWORD flags 2238 ) 2239 { 2240 DWORD Ret = GDI_ERROR; 2241 PDC_ATTR Dc_Attr; 2242 2243 /* Get the DC attribute */ 2244 Dc_Attr = GdiGetDcAttr(hDC); 2245 if (Dc_Attr == NULL) 2246 { 2247 SetLastError(ERROR_INVALID_PARAMETER); 2248 return GDI_ERROR; 2249 } 2250 2251 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC) 2252 { 2253 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY) 2254 { 2255 NtGdiFlush(); 2256 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY); 2257 } 2258 } 2259 2260 if ( flags & ~1 ) 2261 SetLastError(ERROR_INVALID_PARAMETER); 2262 else 2263 { 2264 Ret = Dc_Attr->flFontMapper; 2265 Dc_Attr->flFontMapper = flags; 2266 } 2267 return Ret; 2268 } 2269 2270 2271 /* 2272 * @unimplemented 2273 */ 2274 int 2275 WINAPI 2276 EnumFontsW( 2277 HDC hDC, 2278 LPCWSTR lpFaceName, 2279 FONTENUMPROCW FontFunc, 2280 LPARAM lParam 2281 ) 2282 { 2283 #if 0 2284 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam ); 2285 #else 2286 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam ); 2287 #endif 2288 } 2289 2290 /* 2291 * @unimplemented 2292 */ 2293 int 2294 WINAPI 2295 EnumFontsA ( 2296 HDC hDC, 2297 LPCSTR lpFaceName, 2298 FONTENUMPROCA FontFunc, 2299 LPARAM lParam 2300 ) 2301 { 2302 #if 0 2303 NTSTATUS Status; 2304 LPWSTR lpFaceNameW; 2305 int rc = 0; 2306 2307 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName ); 2308 if (!NT_SUCCESS (Status)) 2309 SetLastError (RtlNtStatusToDosError(Status)); 2310 else 2311 { 2312 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam ); 2313 2314 HEAP_free ( lpFaceNameW ); 2315 } 2316 return rc; 2317 #else 2318 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam ); 2319 #endif 2320 } 2321 2322 #define EfdFontFamilies 3 2323 2324 INT 2325 WINAPI 2326 NewEnumFontFamiliesExW( 2327 HDC hDC, 2328 LPLOGFONTW lpLogfont, 2329 FONTENUMPROCW lpEnumFontFamExProcW, 2330 LPARAM lParam, 2331 DWORD dwFlags) 2332 { 2333 ULONG_PTR idEnum; 2334 ULONG cbDataSize, cbRetSize; 2335 PENUMFONTDATAW pEfdw; 2336 PBYTE pBuffer; 2337 PBYTE pMax; 2338 INT ret = 1; 2339 2340 /* Open enumeration handle and find out how much memory we need */ 2341 idEnum = NtGdiEnumFontOpen(hDC, 2342 EfdFontFamilies, 2343 0, 2344 LF_FACESIZE, 2345 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL, 2346 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET, 2347 &cbDataSize); 2348 if (idEnum == 0) 2349 { 2350 return 0; 2351 } 2352 if (cbDataSize == 0) 2353 { 2354 NtGdiEnumFontClose(idEnum); 2355 return 0; 2356 } 2357 2358 /* Allocate memory */ 2359 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize); 2360 if (pBuffer == NULL) 2361 { 2362 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2363 NtGdiEnumFontClose(idEnum); 2364 return 0; 2365 } 2366 2367 /* Do the enumeration */ 2368 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer)) 2369 { 2370 HeapFree(GetProcessHeap(), 0, pBuffer); 2371 NtGdiEnumFontClose(idEnum); 2372 return 0; 2373 } 2374 2375 /* Get start and end address */ 2376 pEfdw = (PENUMFONTDATAW)pBuffer; 2377 pMax = pBuffer + cbDataSize; 2378 2379 /* Iterate through the structures */ 2380 while ((PBYTE)pEfdw < pMax && ret) 2381 { 2382 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset); 2383 2384 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx, 2385 (VOID*)&pNtmwi->ntmw, 2386 pEfdw->dwFontType, 2387 lParam); 2388 2389 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize); 2390 } 2391 2392 /* Release the memory and close handle */ 2393 HeapFree(GetProcessHeap(), 0, pBuffer); 2394 NtGdiEnumFontClose(idEnum); 2395 2396 return ret; 2397 } 2398 2399 /* 2400 * @implemented 2401 */ 2402 int 2403 WINAPI 2404 GdiAddFontResourceW( 2405 LPCWSTR lpszFilename, 2406 FLONG fl, 2407 DESIGNVECTOR *pdv) 2408 { 2409 INT Ret; 2410 WCHAR lpszBuffer[MAX_PATH]; 2411 WCHAR lpszAbsPath[MAX_PATH]; 2412 UNICODE_STRING NtAbsPath; 2413 2414 /* FIXME: We don't support multiple files passed in lpszFilename 2415 * as L"abcxxxxx.pfm|abcxxxxx.pfb" 2416 */ 2417 2418 /* Does the file exist in CurrentDirectory or in the Absolute Path passed? */ 2419 GetCurrentDirectoryW(MAX_PATH, lpszBuffer); 2420 2421 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL)) 2422 { 2423 /* Nope. Then let's check Fonts folder */ 2424 GetWindowsDirectoryW(lpszBuffer, MAX_PATH); 2425 StringCbCatW(lpszBuffer, sizeof(lpszBuffer), L"\\Fonts"); 2426 2427 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL)) 2428 { 2429 DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer, lpszFilename); 2430 return 0; 2431 } 2432 } 2433 2434 /* We found the font file so: */ 2435 if (!RtlDosPathNameToNtPathName_U(lpszAbsPath, &NtAbsPath, NULL, NULL)) 2436 { 2437 DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath); 2438 return 0; 2439 } 2440 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); 2444 2445 RtlFreeUnicodeString(&NtAbsPath); 2446 2447 return Ret; 2448 } 2449 2450 /* 2451 * @implemented 2452 */ 2453 HANDLE 2454 WINAPI 2455 AddFontMemResourceEx( 2456 PVOID pbFont, 2457 DWORD cbFont, 2458 PVOID pdv, 2459 DWORD *pcFonts 2460 ) 2461 { 2462 if ( pbFont && cbFont && pcFonts) 2463 { 2464 return NtGdiAddFontMemResourceEx(pbFont, cbFont, NULL, 0, pcFonts); 2465 } 2466 SetLastError(ERROR_INVALID_PARAMETER); 2467 return NULL; 2468 } 2469 2470 /* 2471 * @implemented 2472 */ 2473 BOOL 2474 WINAPI 2475 RemoveFontMemResourceEx(HANDLE fh) 2476 { 2477 if (fh) 2478 { 2479 return NtGdiRemoveFontMemResourceEx(fh); 2480 } 2481 SetLastError(ERROR_INVALID_PARAMETER); 2482 return FALSE; 2483 } 2484 2485 2486 /* 2487 * @unimplemented 2488 */ 2489 int 2490 WINAPI 2491 AddFontResourceTracking( 2492 LPCSTR lpString, 2493 int unknown 2494 ) 2495 { 2496 UNIMPLEMENTED; 2497 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2498 return 0; 2499 } 2500 2501 /* 2502 * @unimplemented 2503 */ 2504 int 2505 WINAPI 2506 RemoveFontResourceTracking(LPCSTR lpString,int unknown) 2507 { 2508 UNIMPLEMENTED; 2509 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2510 return 0; 2511 } 2512 2513 BOOL 2514 WINAPI 2515 CreateScalableFontResourceW( 2516 DWORD fdwHidden, 2517 LPCWSTR lpszFontRes, 2518 LPCWSTR lpszFontFile, 2519 LPCWSTR lpszCurrentPath 2520 ) 2521 { 2522 HANDLE f; 2523 2524 UNIMPLEMENTED; 2525 2526 /* fHidden=1 - only visible for the calling app, read-only, not 2527 * enumerated with EnumFonts/EnumFontFamilies 2528 * lpszCurrentPath can be NULL 2529 */ 2530 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) 2533 { 2534 CloseHandle(f); 2535 SetLastError(ERROR_FILE_EXISTS); 2536 return FALSE; 2537 } 2538 return FALSE; /* create failed */ 2539 } 2540 2541 /* 2542 * @unimplemented 2543 */ 2544 BOOL 2545 WINAPI 2546 bInitSystemAndFontsDirectoriesW(LPWSTR *SystemDir,LPWSTR *FontsDir) 2547 { 2548 UNIMPLEMENTED; 2549 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2550 return 0; 2551 } 2552 2553 /* 2554 * @unimplemented 2555 */ 2556 BOOL 2557 WINAPI 2558 EudcLoadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath,INT iPriority,INT iFontLinkType) 2559 { 2560 UNIMPLEMENTED; 2561 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2562 return 0; 2563 } 2564 2565 /* 2566 * @unimplemented 2567 */ 2568 BOOL 2569 WINAPI 2570 EudcUnloadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath) 2571 { 2572 UNIMPLEMENTED; 2573 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2574 return 0; 2575 } 2576 2577 /* 2578 * @implemented 2579 */ 2580 ULONG 2581 WINAPI 2582 GetEUDCTimeStamp(VOID) 2583 { 2584 return NtGdiGetEudcTimeStampEx(NULL,0,TRUE); 2585 } 2586 2587 /* 2588 * @implemented 2589 */ 2590 DWORD 2591 WINAPI 2592 GetEUDCTimeStampExW(LPWSTR lpBaseFaceName) 2593 { 2594 DWORD retValue = 0; 2595 2596 if (!lpBaseFaceName) 2597 { 2598 retValue = NtGdiGetEudcTimeStampEx(NULL,0,FALSE); 2599 } 2600 else 2601 { 2602 retValue = NtGdiGetEudcTimeStampEx(lpBaseFaceName, wcslen(lpBaseFaceName), FALSE); 2603 } 2604 2605 return retValue; 2606 } 2607 2608 /* 2609 * @implemented 2610 */ 2611 ULONG 2612 WINAPI 2613 GetFontAssocStatus(HDC hdc) 2614 { 2615 ULONG retValue = 0; 2616 2617 if (hdc) 2618 { 2619 retValue = NtGdiQueryFontAssocInfo(hdc); 2620 } 2621 2622 return retValue; 2623 } 2624 2625 /* 2626 * @unimplemented 2627 */ 2628 DWORD 2629 WINAPI 2630 QueryFontAssocStatus(VOID) 2631 { 2632 UNIMPLEMENTED; 2633 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2634 return 0; 2635 } 2636 2637 /* 2638 * @unimplemented 2639 */ 2640 VOID 2641 WINAPI 2642 UnloadNetworkFonts(DWORD unknown) 2643 { 2644 UNIMPLEMENTED; 2645 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2646 } 2647 2648 /* 2649 * @implemented 2650 * 2651 */ 2652 DWORD 2653 WINAPI 2654 GetFontData(HDC hdc, 2655 DWORD dwTable, 2656 DWORD dwOffset, 2657 LPVOID lpvBuffer, 2658 DWORD cbData) 2659 { 2660 if (!lpvBuffer) 2661 { 2662 cbData = 0; 2663 } 2664 return NtGdiGetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData); 2665 } 2666 2667 DWORD 2668 WINAPI 2669 cGetTTFFromFOT(DWORD x1 ,DWORD x2 ,DWORD x3, DWORD x4, DWORD x5, DWORD x6, DWORD x7) 2670 { 2671 UNIMPLEMENTED; 2672 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2673 return 0; 2674 } 2675 2676