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 static int FASTCALL 208 IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam, 209 BOOL Unicode) 210 { 211 int FontFamilyCount; 212 int FontFamilySize; 213 PFONTFAMILYINFO Info; 214 int Ret = 1; 215 int i; 216 ENUMLOGFONTEXA EnumLogFontExA; 217 NEWTEXTMETRICEXA NewTextMetricExA; 218 LOGFONTW lfW; 219 220 Info = RtlAllocateHeap(GetProcessHeap(), 0, 221 INITIAL_FAMILY_COUNT * sizeof(FONTFAMILYINFO)); 222 if (NULL == Info) 223 { 224 return 1; 225 } 226 227 if (!LogFont) 228 { 229 lfW.lfCharSet = DEFAULT_CHARSET; 230 lfW.lfPitchAndFamily = 0; 231 lfW.lfFaceName[0] = 0; 232 LogFont = &lfW; 233 } 234 235 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, INITIAL_FAMILY_COUNT); 236 if (FontFamilyCount < 0) 237 { 238 RtlFreeHeap(GetProcessHeap(), 0, Info); 239 return 1; 240 } 241 if (INITIAL_FAMILY_COUNT < FontFamilyCount) 242 { 243 FontFamilySize = FontFamilyCount; 244 RtlFreeHeap(GetProcessHeap(), 0, Info); 245 Info = RtlAllocateHeap(GetProcessHeap(), 0, 246 FontFamilyCount * sizeof(FONTFAMILYINFO)); 247 if (NULL == Info) 248 { 249 return 1; 250 } 251 FontFamilyCount = NtGdiGetFontFamilyInfo(Dc, LogFont, Info, FontFamilySize); 252 if (FontFamilyCount < 0 || FontFamilySize < FontFamilyCount) 253 { 254 RtlFreeHeap(GetProcessHeap(), 0, Info); 255 return 1; 256 } 257 } 258 259 for (i = 0; i < FontFamilyCount; i++) 260 { 261 if (Unicode) 262 { 263 Ret = ((FONTENUMPROCW) EnumProc)( 264 (VOID*)&Info[i].EnumLogFontEx, 265 (VOID*)&Info[i].NewTextMetricEx, 266 Info[i].FontType, lParam); 267 } 268 else 269 { 270 // Could use EnumLogFontExW2A here? 271 LogFontW2A(&EnumLogFontExA.elfLogFont, &Info[i].EnumLogFontEx.elfLogFont); 272 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfFullName, -1, 273 (LPSTR)EnumLogFontExA.elfFullName, LF_FULLFACESIZE, NULL, NULL); 274 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfStyle, -1, 275 (LPSTR)EnumLogFontExA.elfStyle, LF_FACESIZE, NULL, NULL); 276 WideCharToMultiByte(CP_THREAD_ACP, 0, Info[i].EnumLogFontEx.elfScript, -1, 277 (LPSTR)EnumLogFontExA.elfScript, LF_FACESIZE, NULL, NULL); 278 NewTextMetricExW2A(&NewTextMetricExA, 279 &Info[i].NewTextMetricEx); 280 Ret = ((FONTENUMPROCA) EnumProc)( 281 (VOID*)&EnumLogFontExA, 282 (VOID*)&NewTextMetricExA, 283 Info[i].FontType, lParam); 284 } 285 286 if(Ret == 0) 287 break; 288 } 289 290 RtlFreeHeap(GetProcessHeap(), 0, Info); 291 292 return Ret; 293 } 294 295 /* 296 * @implemented 297 */ 298 int WINAPI 299 EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc, 300 LPARAM lParam, DWORD dwFlags) 301 { 302 return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE); 303 } 304 305 306 /* 307 * @implemented 308 */ 309 int WINAPI 310 EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW lpEnumFontFamProc, 311 LPARAM lParam) 312 { 313 LOGFONTW LogFont; 314 315 ZeroMemory(&LogFont, sizeof(LOGFONTW)); 316 LogFont.lfCharSet = DEFAULT_CHARSET; 317 if (NULL != lpszFamily) 318 { 319 if (!*lpszFamily) return 1; 320 lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE); 321 } 322 323 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE); 324 } 325 326 327 /* 328 * @implemented 329 */ 330 int WINAPI 331 EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA lpEnumFontFamExProc, 332 LPARAM lParam, DWORD dwFlags) 333 { 334 LOGFONTW LogFontW, *pLogFontW; 335 336 if (lpLogfont) 337 { 338 LogFontA2W(&LogFontW,lpLogfont); 339 pLogFontW = &LogFontW; 340 } 341 else pLogFontW = NULL; 342 343 /* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only */ 344 return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, FALSE); 345 } 346 347 348 /* 349 * @implemented 350 */ 351 int WINAPI 352 EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA lpEnumFontFamProc, 353 LPARAM lParam) 354 { 355 LOGFONTW LogFont; 356 357 ZeroMemory(&LogFont, sizeof(LOGFONTW)); 358 LogFont.lfCharSet = DEFAULT_CHARSET; 359 if (NULL != lpszFamily) 360 { 361 if (!*lpszFamily) return 1; 362 MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName, LF_FACESIZE); 363 } 364 365 return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE); 366 } 367 368 369 /* 370 * @implemented 371 */ 372 DWORD 373 WINAPI 374 GetCharacterPlacementA( 375 HDC hdc, 376 LPCSTR lpString, 377 INT uCount, 378 INT nMaxExtent, 379 GCP_RESULTSA *lpResults, 380 DWORD dwFlags) 381 { 382 WCHAR *lpStringW; 383 INT uCountW; 384 GCP_RESULTSW resultsW; 385 DWORD ret; 386 UINT font_cp; 387 388 if ( !lpString || uCount <= 0 || !lpResults || (nMaxExtent < 0 && nMaxExtent != -1 ) ) 389 { 390 SetLastError(ERROR_INVALID_PARAMETER); 391 return 0; 392 } 393 /* TRACE("%s, %d, %d, 0x%08x\n", 394 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags); 395 */ 396 /* both structs are equal in size */ 397 memcpy(&resultsW, lpResults, sizeof(resultsW)); 398 399 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp); 400 if (lpStringW == NULL) 401 { 402 return 0; 403 } 404 if(lpResults->lpOutString) 405 { 406 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW); 407 if (resultsW.lpOutString == NULL) 408 { 409 HeapFree(GetProcessHeap(), 0, lpStringW); 410 return 0; 411 } 412 } 413 414 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags); 415 416 lpResults->nGlyphs = resultsW.nGlyphs; 417 lpResults->nMaxFit = resultsW.nMaxFit; 418 419 if(lpResults->lpOutString) 420 { 421 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW, 422 lpResults->lpOutString, uCount, NULL, NULL ); 423 } 424 425 HeapFree(GetProcessHeap(), 0, lpStringW); 426 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString); 427 428 return ret; 429 } 430 431 432 /* 433 * @implemented 434 */ 435 DWORD 436 WINAPI 437 GetCharacterPlacementW( 438 HDC hdc, 439 LPCWSTR lpString, 440 INT uCount, 441 INT nMaxExtent, 442 GCP_RESULTSW *lpResults, 443 DWORD dwFlags 444 ) 445 { 446 DWORD ret=0; 447 SIZE size; 448 UINT i, nSet; 449 DPRINT("GetCharacterPlacementW\n"); 450 451 if (dwFlags&(~GCP_REORDER)) DPRINT("flags 0x%08lx ignored\n", dwFlags); 452 if (lpResults->lpClass) DPRINT("classes not implemented\n"); 453 454 nSet = (UINT)uCount; 455 if (nSet > lpResults->nGlyphs) 456 nSet = lpResults->nGlyphs; 457 458 /* return number of initialized fields */ 459 lpResults->nGlyphs = nSet; 460 461 if (dwFlags & GCP_REORDER) 462 { 463 if (LoadLPK(LPK_GCP)) 464 return LpkGetCharacterPlacement(hdc, lpString, uCount, nMaxExtent, lpResults, dwFlags, 0); 465 } 466 467 /* Treat the case where no special handling was requested in a fastpath way */ 468 /* copy will do if the GCP_REORDER flag is not set */ 469 if (lpResults->lpOutString) 470 lstrcpynW( lpResults->lpOutString, lpString, nSet ); 471 472 if (lpResults->lpOrder) 473 { 474 for (i = 0; i < nSet; i++) 475 lpResults->lpOrder[i] = i; 476 } 477 478 /* FIXME: Will use the placement chars */ 479 if (lpResults->lpDx) 480 { 481 int c; 482 for (i = 0; i < nSet; i++) 483 { 484 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c)) 485 lpResults->lpDx[i]= c; 486 } 487 } 488 489 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER)) 490 { 491 int pos = 0; 492 493 lpResults->lpCaretPos[0] = 0; 494 for (i = 1; i < nSet; i++) 495 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size)) 496 lpResults->lpCaretPos[i] = (pos += size.cx); 497 } 498 499 if (lpResults->lpGlyphs) 500 NtGdiGetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0); 501 502 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size)) 503 ret = MAKELONG(size.cx, size.cy); 504 505 return ret; 506 } 507 508 DWORD 509 WINAPI 510 NewGetCharacterPlacementW( 511 HDC hdc, 512 LPCWSTR lpString, 513 INT uCount, 514 INT nMaxExtent, 515 GCP_RESULTSW *lpResults, 516 DWORD dwFlags 517 ) 518 { 519 ULONG nSet; 520 SIZE Size = {0,0}; 521 522 if ( !lpString || uCount <= 0 || (nMaxExtent < 0 && nMaxExtent != -1 ) ) 523 { 524 SetLastError(ERROR_INVALID_PARAMETER); 525 return 0; 526 } 527 528 if ( !lpResults ) 529 { 530 if ( GetTextExtentPointW(hdc, lpString, uCount, &Size) ) 531 { 532 return MAKELONG(Size.cx, Size.cy); 533 } 534 return 0; 535 } 536 537 nSet = uCount; 538 if ( nSet > lpResults->nGlyphs ) 539 nSet = lpResults->nGlyphs; 540 541 return NtGdiGetCharacterPlacementW( hdc, 542 (LPWSTR)lpString, 543 nSet, 544 nMaxExtent, 545 lpResults, 546 dwFlags); 547 } 548 549 /* 550 * @implemented 551 * 552 */ 553 BOOL 554 WINAPI 555 GetCharABCWidthsFloatW(HDC hdc, 556 UINT FirstChar, 557 UINT LastChar, 558 LPABCFLOAT abcF) 559 { 560 DPRINT("GetCharABCWidthsFloatW\n"); 561 if ((!abcF) || (FirstChar > LastChar)) 562 { 563 SetLastError(ERROR_INVALID_PARAMETER); 564 return FALSE; 565 } 566 return NtGdiGetCharABCWidthsW( hdc, 567 FirstChar, 568 (ULONG)(LastChar - FirstChar + 1), 569 (PWCHAR) NULL, 570 0, 571 (PVOID)abcF); 572 } 573 574 /* 575 * @implemented 576 * 577 */ 578 BOOL 579 WINAPI 580 GetCharWidthFloatW(HDC hdc, 581 UINT iFirstChar, 582 UINT iLastChar, 583 PFLOAT pxBuffer) 584 { 585 DPRINT("GetCharWidthsFloatW\n"); 586 if ((!pxBuffer) || (iFirstChar > iLastChar)) 587 { 588 SetLastError(ERROR_INVALID_PARAMETER); 589 return FALSE; 590 } 591 return NtGdiGetCharWidthW( hdc, 592 iFirstChar, 593 (ULONG)(iLastChar - iFirstChar + 1), 594 (PWCHAR) NULL, 595 0, 596 (PVOID) pxBuffer); 597 } 598 599 /* 600 * @implemented 601 * 602 */ 603 BOOL 604 WINAPI 605 GetCharWidthW(HDC hdc, 606 UINT iFirstChar, 607 UINT iLastChar, 608 LPINT lpBuffer) 609 { 610 DPRINT("GetCharWidthsW\n"); 611 if ((!lpBuffer) || (iFirstChar > iLastChar)) 612 { 613 SetLastError(ERROR_INVALID_PARAMETER); 614 return FALSE; 615 } 616 return NtGdiGetCharWidthW( hdc, 617 iFirstChar, 618 (ULONG)(iLastChar - iFirstChar + 1), 619 (PWCHAR) NULL, 620 GCW_NOFLOAT, 621 (PVOID) lpBuffer); 622 } 623 624 /* 625 * @implemented 626 * 627 */ 628 BOOL 629 WINAPI 630 GetCharWidth32W(HDC hdc, 631 UINT iFirstChar, 632 UINT iLastChar, 633 LPINT lpBuffer) 634 { 635 DPRINT("GetCharWidths32W\n"); 636 if ((!lpBuffer) || (iFirstChar > iLastChar)) 637 { 638 SetLastError(ERROR_INVALID_PARAMETER); 639 return FALSE; 640 } 641 return NtGdiGetCharWidthW( hdc, 642 iFirstChar, 643 (ULONG)(iLastChar - iFirstChar + 1), 644 (PWCHAR) NULL, 645 GCW_NOFLOAT|GCW_WIN32, 646 (PVOID) lpBuffer); 647 } 648 649 650 /* 651 * @implemented 652 * 653 */ 654 BOOL 655 WINAPI 656 GetCharABCWidthsW(HDC hdc, 657 UINT FirstChar, 658 UINT LastChar, 659 LPABC lpabc) 660 { 661 DPRINT("GetCharABCWidthsW\n"); 662 if ((!lpabc) || (FirstChar > LastChar)) 663 { 664 SetLastError(ERROR_INVALID_PARAMETER); 665 return FALSE; 666 } 667 return NtGdiGetCharABCWidthsW( hdc, 668 FirstChar, 669 (ULONG)(LastChar - FirstChar + 1), 670 (PWCHAR) NULL, 671 GCABCW_NOFLOAT, 672 (PVOID)lpabc); 673 } 674 675 /* 676 * @implemented 677 */ 678 BOOL 679 WINAPI 680 GetCharWidthA( 681 HDC hdc, 682 UINT iFirstChar, 683 UINT iLastChar, 684 LPINT lpBuffer 685 ) 686 { 687 INT wlen, count = 0; 688 LPSTR str; 689 LPWSTR wstr; 690 BOOL ret = TRUE; 691 692 DPRINT("GetCharWidthsA\n"); 693 694 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 695 if (!str) 696 return FALSE; 697 698 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 699 if (!wstr) 700 { 701 HeapFree(GetProcessHeap(), 0, str); 702 return FALSE; 703 } 704 705 ret = NtGdiGetCharWidthW( hdc, 706 wstr[0], 707 (ULONG) count, 708 (PWCHAR) wstr, 709 GCW_NOFLOAT, 710 (PVOID) lpBuffer); 711 712 HeapFree(GetProcessHeap(), 0, str); 713 HeapFree(GetProcessHeap(), 0, wstr); 714 715 return ret; 716 } 717 718 /* 719 * @implemented 720 */ 721 BOOL 722 WINAPI 723 GetCharWidth32A( 724 HDC hdc, 725 UINT iFirstChar, 726 UINT iLastChar, 727 LPINT lpBuffer 728 ) 729 { 730 INT wlen, count = 0; 731 LPSTR str; 732 LPWSTR wstr; 733 BOOL ret = TRUE; 734 735 DPRINT("GetCharWidths32A\n"); 736 737 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 738 if (!str) 739 return FALSE; 740 741 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 742 if (!wstr) 743 { 744 HeapFree(GetProcessHeap(), 0, str); 745 return FALSE; 746 } 747 748 ret = NtGdiGetCharWidthW( hdc, 749 wstr[0], 750 (ULONG) count, 751 (PWCHAR) wstr, 752 GCW_NOFLOAT|GCW_WIN32, 753 (PVOID) lpBuffer); 754 755 HeapFree(GetProcessHeap(), 0, str); 756 HeapFree(GetProcessHeap(), 0, wstr); 757 758 return ret; 759 } 760 761 /* 762 * @implemented 763 */ 764 BOOL 765 APIENTRY 766 GetCharWidthFloatA( 767 HDC hdc, 768 UINT iFirstChar, 769 UINT iLastChar, 770 PFLOAT pxBuffer 771 ) 772 { 773 INT wlen, count = 0; 774 LPSTR str; 775 LPWSTR wstr; 776 BOOL ret = TRUE; 777 778 DPRINT("GetCharWidthsFloatA\n"); 779 780 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 781 if (!str) 782 return FALSE; 783 784 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 785 if (!wstr) 786 { 787 HeapFree(GetProcessHeap(), 0, str); 788 return FALSE; 789 } 790 ret = NtGdiGetCharWidthW( hdc, wstr[0], (ULONG) count, (PWCHAR) wstr, 0, (PVOID) pxBuffer); 791 792 HeapFree(GetProcessHeap(), 0, str); 793 HeapFree(GetProcessHeap(), 0, wstr); 794 795 return ret; 796 } 797 798 /* 799 * @implemented 800 */ 801 BOOL 802 APIENTRY 803 GetCharABCWidthsA( 804 HDC hdc, 805 UINT iFirstChar, 806 UINT iLastChar, 807 LPABC lpabc 808 ) 809 { 810 INT wlen, count = 0; 811 LPSTR str; 812 LPWSTR wstr; 813 BOOL ret = TRUE; 814 815 DPRINT("GetCharABCWidthsA\n"); 816 817 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 818 if (!str) 819 return FALSE; 820 821 wstr = FONT_mbtowc(hdc, str, count+1, &wlen, NULL); 822 if (!wstr) 823 { 824 HeapFree(GetProcessHeap(), 0, str); 825 return FALSE; 826 } 827 828 ret = NtGdiGetCharABCWidthsW( hdc, 829 wstr[0], 830 wlen - 1, 831 (PWCHAR)wstr, 832 GCABCW_NOFLOAT, 833 (PVOID)lpabc); 834 835 HeapFree(GetProcessHeap(), 0, str); 836 HeapFree(GetProcessHeap(), 0, wstr); 837 838 return ret; 839 } 840 841 /* 842 * @implemented 843 */ 844 BOOL 845 APIENTRY 846 GetCharABCWidthsFloatA( 847 HDC hdc, 848 UINT iFirstChar, 849 UINT iLastChar, 850 LPABCFLOAT lpABCF 851 ) 852 { 853 INT wlen, count = 0; 854 LPSTR str; 855 LPWSTR wstr; 856 BOOL ret = TRUE; 857 858 DPRINT("GetCharABCWidthsFloatA\n"); 859 860 str = FONT_GetCharsByRangeA(hdc, iFirstChar, iLastChar, &count); 861 if (!str) 862 return FALSE; 863 864 wstr = FONT_mbtowc( hdc, str, count+1, &wlen, NULL ); 865 if (!wstr) 866 { 867 HeapFree( GetProcessHeap(), 0, str ); 868 return FALSE; 869 } 870 ret = NtGdiGetCharABCWidthsW( hdc,wstr[0],(ULONG)count, (PWCHAR)wstr, 0, (PVOID)lpABCF); 871 872 HeapFree( GetProcessHeap(), 0, str ); 873 HeapFree( GetProcessHeap(), 0, wstr ); 874 875 return ret; 876 } 877 878 /* 879 * @implemented 880 */ 881 BOOL 882 WINAPI 883 GetCharABCWidthsI(HDC hdc, 884 UINT giFirst, 885 UINT cgi, 886 LPWORD pgi, 887 LPABC lpabc) 888 { 889 DPRINT("GetCharABCWidthsI\n"); 890 return NtGdiGetCharABCWidthsW( hdc, 891 giFirst, 892 (ULONG) cgi, 893 (PWCHAR) pgi, 894 GCABCW_NOFLOAT|GCABCW_INDICES, 895 (PVOID)lpabc); 896 } 897 898 /* 899 * @implemented 900 */ 901 BOOL 902 WINAPI 903 GetCharWidthI(HDC hdc, 904 UINT giFirst, 905 UINT cgi, 906 LPWORD pgi, 907 LPINT lpBuffer 908 ) 909 { 910 DPRINT("GetCharWidthsI\n"); 911 if (!lpBuffer || (!pgi && (giFirst == MAXUSHORT))) // Cannot be at max. 912 { 913 SetLastError(ERROR_INVALID_PARAMETER); 914 return FALSE; 915 } 916 if (!cgi) return TRUE; 917 return NtGdiGetCharWidthW( hdc, 918 giFirst, 919 cgi, 920 (PWCHAR) pgi, 921 GCW_INDICES|GCW_NOFLOAT|GCW_WIN32, 922 (PVOID) lpBuffer ); 923 } 924 925 /* 926 * @implemented 927 */ 928 DWORD 929 WINAPI 930 GetFontLanguageInfo( 931 HDC hDc 932 ) 933 { 934 DWORD Gcp = 0, Ret = 0; 935 if (gbLpk) 936 { 937 Ret = NtGdiGetTextCharsetInfo(hDc, NULL, 0); 938 if ((Ret == ARABIC_CHARSET) || (Ret == HEBREW_CHARSET)) 939 Ret = (GCP_KASHIDA|GCP_DIACRITIC|GCP_LIGATE|GCP_GLYPHSHAPE|GCP_REORDER); 940 } 941 Gcp = GetDCDWord(hDc, GdiGetFontLanguageInfo, GCP_ERROR); 942 if ( Gcp == GCP_ERROR) 943 return Gcp; 944 else 945 Ret = Gcp | Ret; 946 return Ret; 947 } 948 949 /* 950 * @implemented 951 */ 952 DWORD 953 WINAPI 954 GetGlyphIndicesA( 955 HDC hdc, 956 LPCSTR lpstr, 957 INT count, 958 LPWORD pgi, 959 DWORD flags 960 ) 961 { 962 DWORD Ret; 963 WCHAR *lpstrW; 964 INT countW; 965 966 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL); 967 968 if (lpstrW == NULL) 969 return GDI_ERROR; 970 971 Ret = NtGdiGetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags); 972 HeapFree(GetProcessHeap(), 0, lpstrW); 973 return Ret; 974 } 975 976 /* 977 * @implemented 978 */ 979 DWORD 980 WINAPI 981 GetGlyphOutlineA( 982 HDC hdc, 983 UINT uChar, 984 UINT uFormat, 985 LPGLYPHMETRICS lpgm, 986 DWORD cbBuffer, 987 LPVOID lpvBuffer, 988 CONST MAT2 *lpmat2 989 ) 990 { 991 992 LPWSTR p = NULL; 993 DWORD ret; 994 UINT c; 995 DPRINT("GetGlyphOutlineA uChar %x\n", uChar); 996 if (!lpgm || !lpmat2) return GDI_ERROR; 997 if(!(uFormat & GGO_GLYPH_INDEX)) 998 { 999 int len; 1000 char mbchs[2]; 1001 if(uChar > 0xff) /* but, 2 bytes character only */ 1002 { 1003 len = 2; 1004 mbchs[0] = (uChar & 0xff00) >> 8; 1005 mbchs[1] = (uChar & 0xff); 1006 } 1007 else 1008 { 1009 len = 1; 1010 mbchs[0] = (uChar & 0xff); 1011 } 1012 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL); 1013 if(!p) 1014 return GDI_ERROR; 1015 c = p[0]; 1016 } 1017 else 1018 c = uChar; 1019 ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); 1020 HeapFree(GetProcessHeap(), 0, p); 1021 return ret; 1022 } 1023 1024 1025 /* 1026 * @implemented 1027 */ 1028 DWORD 1029 WINAPI 1030 GetGlyphOutlineW( 1031 HDC hdc, 1032 UINT uChar, 1033 UINT uFormat, 1034 LPGLYPHMETRICS lpgm, 1035 DWORD cbBuffer, 1036 LPVOID lpvBuffer, 1037 CONST MAT2 *lpmat2 1038 ) 1039 { 1040 DPRINT("GetGlyphOutlineW uChar %x\n", uChar); 1041 if (!lpgm || !lpmat2) return GDI_ERROR; 1042 if (!lpvBuffer) cbBuffer = 0; 1043 return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); 1044 } 1045 1046 /* 1047 * @unimplemented 1048 */ 1049 DWORD 1050 WINAPI 1051 GetGlyphOutlineWow( 1052 DWORD a0, 1053 DWORD a1, 1054 DWORD a2, 1055 DWORD a3, 1056 DWORD a4, 1057 DWORD a5, 1058 DWORD a6 1059 ) 1060 { 1061 UNIMPLEMENTED; 1062 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1063 return 0; 1064 } 1065 1066 /* 1067 * @implemented 1068 */ 1069 UINT 1070 APIENTRY 1071 GetOutlineTextMetricsA( 1072 HDC hdc, 1073 UINT cbData, 1074 LPOUTLINETEXTMETRICA lpOTM 1075 ) 1076 { 1077 char buf[512], *ptr; 1078 UINT ret, needed; 1079 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf; 1080 OUTLINETEXTMETRICA *output = lpOTM; 1081 INT left, len; 1082 1083 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0) 1084 return 0; 1085 if(ret > sizeof(buf)) 1086 { 1087 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret); 1088 if (lpOTMW == NULL) 1089 { 1090 return 0; 1091 } 1092 } 1093 GetOutlineTextMetricsW(hdc, ret, lpOTMW); 1094 1095 needed = sizeof(OUTLINETEXTMETRICA); 1096 if(lpOTMW->otmpFamilyName) 1097 needed += WideCharToMultiByte(CP_ACP, 0, 1098 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFamilyName), -1, 1099 NULL, 0, NULL, NULL); 1100 if(lpOTMW->otmpFaceName) 1101 needed += WideCharToMultiByte(CP_ACP, 0, 1102 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFaceName), -1, 1103 NULL, 0, NULL, NULL); 1104 if(lpOTMW->otmpStyleName) 1105 needed += WideCharToMultiByte(CP_ACP, 0, 1106 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpStyleName), -1, 1107 NULL, 0, NULL, NULL); 1108 if(lpOTMW->otmpFullName) 1109 needed += WideCharToMultiByte(CP_ACP, 0, 1110 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFullName), -1, 1111 NULL, 0, NULL, NULL); 1112 1113 if(!lpOTM) 1114 { 1115 ret = needed; 1116 goto end; 1117 } 1118 1119 DPRINT("needed = %u\n", needed); 1120 if(needed > cbData) 1121 { 1122 /* Since the supplied buffer isn't big enough, we'll alloc one 1123 that is and memcpy the first cbData bytes into the lpOTM at 1124 the end. */ 1125 output = HeapAlloc(GetProcessHeap(), 0, needed); 1126 if (output == NULL) 1127 { 1128 goto end; 1129 } 1130 } 1131 1132 ret = output->otmSize = min(needed, cbData); 1133 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics ); 1134 output->otmFiller = 0; 1135 output->otmPanoseNumber = lpOTMW->otmPanoseNumber; 1136 output->otmfsSelection = lpOTMW->otmfsSelection; 1137 output->otmfsType = lpOTMW->otmfsType; 1138 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise; 1139 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun; 1140 output->otmItalicAngle = lpOTMW->otmItalicAngle; 1141 output->otmEMSquare = lpOTMW->otmEMSquare; 1142 output->otmAscent = lpOTMW->otmAscent; 1143 output->otmDescent = lpOTMW->otmDescent; 1144 output->otmLineGap = lpOTMW->otmLineGap; 1145 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight; 1146 output->otmsXHeight = lpOTMW->otmsXHeight; 1147 output->otmrcFontBox = lpOTMW->otmrcFontBox; 1148 output->otmMacAscent = lpOTMW->otmMacAscent; 1149 output->otmMacDescent = lpOTMW->otmMacDescent; 1150 output->otmMacLineGap = lpOTMW->otmMacLineGap; 1151 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM; 1152 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize; 1153 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset; 1154 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize; 1155 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset; 1156 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize; 1157 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition; 1158 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize; 1159 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition; 1160 1161 1162 ptr = (char*)(output + 1); 1163 left = needed - sizeof(*output); 1164 1165 if(lpOTMW->otmpFamilyName) 1166 { 1167 output->otmpFamilyName = (LPSTR)(ptr - (char*)output); 1168 len = WideCharToMultiByte(CP_ACP, 0, 1169 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFamilyName), -1, 1170 ptr, left, NULL, NULL); 1171 left -= len; 1172 ptr += len; 1173 } 1174 else 1175 output->otmpFamilyName = 0; 1176 1177 if(lpOTMW->otmpFaceName) 1178 { 1179 output->otmpFaceName = (LPSTR)(ptr - (char*)output); 1180 len = WideCharToMultiByte(CP_ACP, 0, 1181 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFaceName), -1, 1182 ptr, left, NULL, NULL); 1183 left -= len; 1184 ptr += len; 1185 } 1186 else 1187 output->otmpFaceName = 0; 1188 1189 if(lpOTMW->otmpStyleName) 1190 { 1191 output->otmpStyleName = (LPSTR)(ptr - (char*)output); 1192 len = WideCharToMultiByte(CP_ACP, 0, 1193 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpStyleName), -1, 1194 ptr, left, NULL, NULL); 1195 left -= len; 1196 ptr += len; 1197 } 1198 else 1199 output->otmpStyleName = 0; 1200 1201 if(lpOTMW->otmpFullName) 1202 { 1203 output->otmpFullName = (LPSTR)(ptr - (char*)output); 1204 len = WideCharToMultiByte(CP_ACP, 0, 1205 (WCHAR*)((char*)lpOTMW + (intptr_t)lpOTMW->otmpFullName), -1, 1206 ptr, left, NULL, NULL); 1207 left -= len; 1208 } 1209 else 1210 output->otmpFullName = 0; 1211 1212 assert(left == 0); 1213 1214 if(output != lpOTM) 1215 { 1216 memcpy(lpOTM, output, cbData); 1217 HeapFree(GetProcessHeap(), 0, output); 1218 1219 /* check if the string offsets really fit into the provided size */ 1220 /* FIXME: should we check string length as well? */ 1221 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize) 1222 lpOTM->otmpFamilyName = 0; /* doesn't fit */ 1223 1224 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize) 1225 lpOTM->otmpFaceName = 0; /* doesn't fit */ 1226 1227 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize) 1228 lpOTM->otmpStyleName = 0; /* doesn't fit */ 1229 1230 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize) 1231 lpOTM->otmpFullName = 0; /* doesn't fit */ 1232 } 1233 1234 end: 1235 if(lpOTMW != (OUTLINETEXTMETRICW *)buf) 1236 HeapFree(GetProcessHeap(), 0, lpOTMW); 1237 1238 return ret; 1239 } 1240 1241 /* Performs a device to world transformation on the specified size (which 1242 * is in integer format). 1243 */ 1244 static inline INT INTERNAL_YDSTOWS(XFORM *xForm, INT height) 1245 { 1246 double floatHeight; 1247 1248 /* Perform operation with floating point */ 1249 floatHeight = (double)height * xForm->eM22; 1250 /* Round to integers */ 1251 return GDI_ROUND(floatHeight); 1252 } 1253 1254 /* scale width and height but don't mirror them */ 1255 static inline INT width_to_LP( XFORM *xForm, INT width ) 1256 { 1257 return GDI_ROUND( (double)width * fabs( xForm->eM11)); 1258 } 1259 1260 static inline INT height_to_LP( XFORM *xForm, INT height ) 1261 { 1262 return GDI_ROUND( (double)height * fabs( xForm->eM22 )); 1263 } 1264 1265 /* 1266 * @implemented 1267 */ 1268 UINT 1269 APIENTRY 1270 GetOutlineTextMetricsW( 1271 HDC hdc, 1272 UINT cbData, 1273 LPOUTLINETEXTMETRICW lpOTM 1274 ) 1275 { 1276 TMDIFF Tmd; // Should not be zero. 1277 UINT Size, AvailableSize = 0, StringSize; 1278 XFORM DevToWorld; 1279 OUTLINETEXTMETRICW* LocalOTM; 1280 WCHAR* Str; 1281 BYTE* Ptr; 1282 1283 /* Get the structure */ 1284 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, 0, NULL, &Tmd); 1285 if (!Size) 1286 return 0; 1287 if (!lpOTM || (cbData < sizeof(*lpOTM))) 1288 return Size; 1289 1290 LocalOTM = HeapAlloc(GetProcessHeap(), 0, Size); 1291 LocalOTM->otmSize = Size; 1292 Size = NtGdiGetOutlineTextMetricsInternalW(hdc, Size, LocalOTM, &Tmd); 1293 if (!Size) 1294 { 1295 HeapFree(GetProcessHeap(), 0, LocalOTM); 1296 return 0; 1297 } 1298 1299 if (!NtGdiGetTransform(hdc, GdiDeviceSpaceToWorldSpace, &DevToWorld)) 1300 { 1301 DPRINT1("NtGdiGetTransform failed!\n"); 1302 HeapFree(GetProcessHeap(), 0, LocalOTM); 1303 SetLastError(ERROR_INVALID_HANDLE); 1304 return 0; 1305 } 1306 1307 /* Fill in DC specific data */ 1308 LocalOTM->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX); 1309 LocalOTM->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY); 1310 LocalOTM->otmTextMetrics.tmHeight = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmHeight ); 1311 LocalOTM->otmTextMetrics.tmAscent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAscent ); 1312 LocalOTM->otmTextMetrics.tmDescent = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmDescent ); 1313 LocalOTM->otmTextMetrics.tmInternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmInternalLeading ); 1314 LocalOTM->otmTextMetrics.tmExternalLeading = height_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmExternalLeading ); 1315 LocalOTM->otmTextMetrics.tmAveCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmAveCharWidth ); 1316 LocalOTM->otmTextMetrics.tmMaxCharWidth = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmMaxCharWidth ); 1317 LocalOTM->otmTextMetrics.tmOverhang = width_to_LP( &DevToWorld, LocalOTM->otmTextMetrics.tmOverhang ); 1318 LocalOTM->otmAscent = height_to_LP( &DevToWorld, LocalOTM->otmAscent); 1319 LocalOTM->otmDescent = height_to_LP( &DevToWorld, LocalOTM->otmDescent); 1320 LocalOTM->otmLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmLineGap)); 1321 LocalOTM->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsCapEmHeight)); 1322 LocalOTM->otmsXHeight = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsXHeight)); 1323 LocalOTM->otmrcFontBox.top = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.top); 1324 LocalOTM->otmrcFontBox.bottom = height_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.bottom); 1325 LocalOTM->otmrcFontBox.left = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.left); 1326 LocalOTM->otmrcFontBox.right = width_to_LP( &DevToWorld, LocalOTM->otmrcFontBox.right); 1327 LocalOTM->otmMacAscent = height_to_LP( &DevToWorld, LocalOTM->otmMacAscent); 1328 LocalOTM->otmMacDescent = height_to_LP( &DevToWorld, LocalOTM->otmMacDescent); 1329 LocalOTM->otmMacLineGap = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmMacLineGap)); 1330 LocalOTM->otmptSubscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.x); 1331 LocalOTM->otmptSubscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptSize.y); 1332 LocalOTM->otmptSubscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.x); 1333 LocalOTM->otmptSubscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSubscriptOffset.y); 1334 LocalOTM->otmptSuperscriptSize.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.x); 1335 LocalOTM->otmptSuperscriptSize.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptSize.y); 1336 LocalOTM->otmptSuperscriptOffset.x = width_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.x); 1337 LocalOTM->otmptSuperscriptOffset.y = height_to_LP( &DevToWorld, LocalOTM->otmptSuperscriptOffset.y); 1338 LocalOTM->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(&DevToWorld,LocalOTM->otmsStrikeoutSize)); 1339 LocalOTM->otmsStrikeoutPosition = height_to_LP( &DevToWorld, LocalOTM->otmsStrikeoutPosition); 1340 LocalOTM->otmsUnderscoreSize = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscoreSize); 1341 LocalOTM->otmsUnderscorePosition = height_to_LP( &DevToWorld, LocalOTM->otmsUnderscorePosition); 1342 1343 /* Copy what we can */ 1344 CopyMemory(lpOTM, LocalOTM, min(Size, cbData)); 1345 1346 lpOTM->otmpFamilyName = NULL; 1347 lpOTM->otmpFaceName = NULL; 1348 lpOTM->otmpStyleName = NULL; 1349 lpOTM->otmpFullName = NULL; 1350 1351 Size = sizeof(*lpOTM); 1352 AvailableSize = cbData - Size; 1353 Ptr = (BYTE*)lpOTM + sizeof(*lpOTM); 1354 1355 /* Fix string values up */ 1356 if (LocalOTM->otmpFamilyName) 1357 { 1358 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFamilyName); 1359 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1360 if (AvailableSize >= StringSize) 1361 { 1362 CopyMemory(Ptr, Str, StringSize); 1363 lpOTM->otmpFamilyName = (PSTR)(Ptr - (BYTE*)lpOTM); 1364 Ptr += StringSize; 1365 AvailableSize -= StringSize; 1366 Size += StringSize; 1367 } 1368 } 1369 1370 if (LocalOTM->otmpFaceName) 1371 { 1372 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFaceName); 1373 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1374 if (AvailableSize >= StringSize) 1375 { 1376 CopyMemory(Ptr, Str, StringSize); 1377 lpOTM->otmpFaceName = (PSTR)(Ptr - (BYTE*)lpOTM); 1378 Ptr += StringSize; 1379 AvailableSize -= StringSize; 1380 Size += StringSize; 1381 } 1382 } 1383 1384 if (LocalOTM->otmpStyleName) 1385 { 1386 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpStyleName); 1387 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1388 if (AvailableSize >= StringSize) 1389 { 1390 CopyMemory(Ptr, Str, StringSize); 1391 lpOTM->otmpStyleName = (PSTR)(Ptr - (BYTE*)lpOTM); 1392 Ptr += StringSize; 1393 AvailableSize -= StringSize; 1394 Size += StringSize; 1395 } 1396 } 1397 1398 if (LocalOTM->otmpFullName) 1399 { 1400 Str = (WCHAR*)((char*)LocalOTM + (ptrdiff_t)LocalOTM->otmpFullName); 1401 StringSize = (wcslen(Str) + 1) * sizeof(WCHAR); 1402 if (AvailableSize >= StringSize) 1403 { 1404 CopyMemory(Ptr, Str, StringSize); 1405 lpOTM->otmpFullName = (PSTR)(Ptr - (BYTE*)lpOTM); 1406 Ptr += StringSize; 1407 AvailableSize -= StringSize; 1408 Size += StringSize; 1409 } 1410 } 1411 1412 lpOTM->otmSize = Size; 1413 1414 HeapFree(GetProcessHeap(), 0, LocalOTM); 1415 1416 return Size; 1417 } 1418 1419 /* 1420 * @implemented 1421 */ 1422 DWORD 1423 WINAPI 1424 GetKerningPairsW(HDC hdc, 1425 ULONG cPairs, 1426 LPKERNINGPAIR pkpDst) 1427 { 1428 if ((cPairs != 0) || (pkpDst == 0)) 1429 { 1430 return NtGdiGetKerningPairs(hdc,cPairs,pkpDst); 1431 } 1432 else 1433 { 1434 SetLastError(ERROR_INVALID_PARAMETER); 1435 return 0; 1436 } 1437 } 1438 1439 /* 1440 * @implemented 1441 */ 1442 DWORD 1443 WINAPI 1444 GetKerningPairsA( HDC hDC, 1445 DWORD cPairs, 1446 LPKERNINGPAIR kern_pairA ) 1447 { 1448 INT charset; 1449 CHARSETINFO csi; 1450 CPINFO cpi; 1451 DWORD i, total_kern_pairs, kern_pairs_copied = 0; 1452 KERNINGPAIR *kern_pairW; 1453 1454 if (!cPairs && kern_pairA) 1455 { 1456 SetLastError(ERROR_INVALID_PARAMETER); 1457 return 0; 1458 } 1459 1460 charset = GetTextCharset(hDC); 1461 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET)) 1462 { 1463 DPRINT1("Can't find codepage for charset %d\n", charset); 1464 return 0; 1465 } 1466 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed 1467 * to fail on an invalid character for CP_SYMBOL. 1468 */ 1469 cpi.DefaultChar[0] = 0; 1470 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi)) 1471 { 1472 DPRINT1("Can't find codepage %u info\n", csi.ciACP); 1473 return 0; 1474 } 1475 DPRINT("charset %d => codepage %u\n", charset, csi.ciACP); 1476 1477 total_kern_pairs = NtGdiGetKerningPairs(hDC, 0, NULL); 1478 if (!total_kern_pairs) return 0; 1479 1480 if (!cPairs && !kern_pairA) return total_kern_pairs; 1481 1482 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW)); 1483 if (kern_pairW == NULL) 1484 { 1485 return 0; 1486 } 1487 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW); 1488 1489 for (i = 0; i < total_kern_pairs; i++) 1490 { 1491 char first, second; 1492 1493 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL)) 1494 continue; 1495 1496 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL)) 1497 continue; 1498 1499 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0]) 1500 continue; 1501 1502 if (kern_pairA) 1503 { 1504 if (kern_pairs_copied >= cPairs) break; 1505 1506 kern_pairA->wFirst = (BYTE)first; 1507 kern_pairA->wSecond = (BYTE)second; 1508 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount; 1509 kern_pairA++; 1510 } 1511 kern_pairs_copied++; 1512 } 1513 1514 HeapFree(GetProcessHeap(), 0, kern_pairW); 1515 1516 return kern_pairs_copied; 1517 } 1518 1519 1520 1521 /* 1522 * @implemented 1523 */ 1524 HFONT 1525 WINAPI 1526 CreateFontIndirectExA(const ENUMLOGFONTEXDVA *elfexd) 1527 { 1528 if (elfexd) 1529 { 1530 ENUMLOGFONTEXDVW Logfont; 1531 1532 EnumLogFontExW2A( (LPENUMLOGFONTEXA) elfexd, 1533 &Logfont.elfEnumLogfontEx ); 1534 1535 RtlCopyMemory( &Logfont.elfDesignVector, 1536 (PVOID) &elfexd->elfDesignVector, 1537 sizeof(DESIGNVECTOR)); 1538 1539 return NtGdiHfontCreate( &Logfont, 0, 0, 0, NULL); 1540 } 1541 else return NULL; 1542 } 1543 1544 1545 /* 1546 * @implemented 1547 */ 1548 HFONT 1549 WINAPI 1550 CreateFontIndirectExW(const ENUMLOGFONTEXDVW *elfexd) 1551 { 1552 /* Msdn: Note, this function ignores the elfDesignVector member in 1553 ENUMLOGFONTEXDV. 1554 */ 1555 if ( elfexd ) 1556 { 1557 return NtGdiHfontCreate((PENUMLOGFONTEXDVW) elfexd, 0, 0, 0, NULL ); 1558 } 1559 else return NULL; 1560 } 1561 1562 1563 /* 1564 * @implemented 1565 */ 1566 HFONT 1567 WINAPI 1568 CreateFontIndirectA( 1569 CONST LOGFONTA *lplf 1570 ) 1571 { 1572 if (lplf) 1573 { 1574 LOGFONTW tlf; 1575 1576 LogFontA2W(&tlf, lplf); 1577 return CreateFontIndirectW(&tlf); 1578 } 1579 else return NULL; 1580 } 1581 1582 1583 /* 1584 * @implemented 1585 */ 1586 HFONT 1587 WINAPI 1588 CreateFontIndirectW( 1589 CONST LOGFONTW *lplf 1590 ) 1591 { 1592 if (lplf) 1593 { 1594 ENUMLOGFONTEXDVW Logfont; 1595 1596 RtlCopyMemory( &Logfont.elfEnumLogfontEx.elfLogFont, lplf, sizeof(LOGFONTW)); 1597 // Need something other than just cleaning memory here. 1598 // Guess? Use caller data to determine the rest. 1599 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfFullName, 1600 sizeof(Logfont.elfEnumLogfontEx.elfFullName)); 1601 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfStyle, 1602 sizeof(Logfont.elfEnumLogfontEx.elfStyle)); 1603 RtlZeroMemory( &Logfont.elfEnumLogfontEx.elfScript, 1604 sizeof(Logfont.elfEnumLogfontEx.elfScript)); 1605 1606 Logfont.elfDesignVector.dvNumAxes = 0; // No more than MM_MAX_NUMAXES 1607 1608 RtlZeroMemory( &Logfont.elfDesignVector, sizeof(DESIGNVECTOR)); 1609 1610 return CreateFontIndirectExW(&Logfont); 1611 } 1612 else return NULL; 1613 } 1614 1615 1616 /* 1617 * @implemented 1618 */ 1619 HFONT 1620 WINAPI 1621 CreateFontA( 1622 int nHeight, 1623 int nWidth, 1624 int nEscapement, 1625 int nOrientation, 1626 int fnWeight, 1627 DWORD fdwItalic, 1628 DWORD fdwUnderline, 1629 DWORD fdwStrikeOut, 1630 DWORD fdwCharSet, 1631 DWORD fdwOutputPrecision, 1632 DWORD fdwClipPrecision, 1633 DWORD fdwQuality, 1634 DWORD fdwPitchAndFamily, 1635 LPCSTR lpszFace 1636 ) 1637 { 1638 ANSI_STRING StringA; 1639 UNICODE_STRING StringU; 1640 HFONT ret; 1641 1642 RtlInitAnsiString(&StringA, (LPSTR)lpszFace); 1643 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); 1644 1645 ret = CreateFontW(nHeight, 1646 nWidth, 1647 nEscapement, 1648 nOrientation, 1649 fnWeight, 1650 fdwItalic, 1651 fdwUnderline, 1652 fdwStrikeOut, 1653 fdwCharSet, 1654 fdwOutputPrecision, 1655 fdwClipPrecision, 1656 fdwQuality, 1657 fdwPitchAndFamily, 1658 StringU.Buffer); 1659 1660 RtlFreeUnicodeString(&StringU); 1661 1662 return ret; 1663 } 1664 1665 1666 /* 1667 * @implemented 1668 */ 1669 HFONT 1670 WINAPI 1671 CreateFontW( 1672 int nHeight, 1673 int nWidth, 1674 int nEscapement, 1675 int nOrientation, 1676 int nWeight, 1677 DWORD fnItalic, 1678 DWORD fdwUnderline, 1679 DWORD fdwStrikeOut, 1680 DWORD fdwCharSet, 1681 DWORD fdwOutputPrecision, 1682 DWORD fdwClipPrecision, 1683 DWORD fdwQuality, 1684 DWORD fdwPitchAndFamily, 1685 LPCWSTR lpszFace 1686 ) 1687 { 1688 LOGFONTW logfont; 1689 1690 logfont.lfHeight = nHeight; 1691 logfont.lfWidth = nWidth; 1692 logfont.lfEscapement = nEscapement; 1693 logfont.lfOrientation = nOrientation; 1694 logfont.lfWeight = nWeight; 1695 logfont.lfItalic = (BYTE)fnItalic; 1696 logfont.lfUnderline = (BYTE)fdwUnderline; 1697 logfont.lfStrikeOut = (BYTE)fdwStrikeOut; 1698 logfont.lfCharSet = (BYTE)fdwCharSet; 1699 logfont.lfOutPrecision = (BYTE)fdwOutputPrecision; 1700 logfont.lfClipPrecision = (BYTE)fdwClipPrecision; 1701 logfont.lfQuality = (BYTE)fdwQuality; 1702 logfont.lfPitchAndFamily = (BYTE)fdwPitchAndFamily; 1703 1704 if (NULL != lpszFace) 1705 { 1706 int Size = sizeof(logfont.lfFaceName) / sizeof(WCHAR); 1707 wcsncpy((wchar_t *)logfont.lfFaceName, lpszFace, Size - 1); 1708 /* Be 101% sure to have '\0' at end of string */ 1709 logfont.lfFaceName[Size - 1] = '\0'; 1710 } 1711 else 1712 { 1713 logfont.lfFaceName[0] = L'\0'; 1714 } 1715 1716 return CreateFontIndirectW(&logfont); 1717 } 1718 1719 1720 /* 1721 * @unimplemented 1722 */ 1723 BOOL 1724 WINAPI 1725 CreateScalableFontResourceA( 1726 DWORD fdwHidden, 1727 LPCSTR lpszFontRes, 1728 LPCSTR lpszFontFile, 1729 LPCSTR lpszCurrentPath 1730 ) 1731 { 1732 return FALSE; 1733 } 1734 1735 1736 /* 1737 * @implemented 1738 */ 1739 int 1740 WINAPI 1741 AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved ) 1742 { 1743 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM)) 1744 { 1745 SetLastError( ERROR_INVALID_PARAMETER ); 1746 return 0; 1747 } 1748 1749 return GdiAddFontResourceW(lpszFilename, fl,0); 1750 } 1751 1752 1753 /* 1754 * @implemented 1755 */ 1756 int 1757 WINAPI 1758 AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved ) 1759 { 1760 NTSTATUS Status; 1761 PWSTR FilenameW; 1762 int rc; 1763 1764 if (fl & ~(FR_PRIVATE | FR_NOT_ENUM)) 1765 { 1766 SetLastError( ERROR_INVALID_PARAMETER ); 1767 return 0; 1768 } 1769 1770 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename ); 1771 if ( !NT_SUCCESS (Status) ) 1772 { 1773 SetLastError (RtlNtStatusToDosError(Status)); 1774 return 0; 1775 } 1776 1777 rc = GdiAddFontResourceW ( FilenameW, fl, 0 ); 1778 HEAP_free ( FilenameW ); 1779 return rc; 1780 } 1781 1782 1783 /* 1784 * @implemented 1785 */ 1786 int 1787 WINAPI 1788 AddFontResourceA ( LPCSTR lpszFilename ) 1789 { 1790 NTSTATUS Status; 1791 PWSTR FilenameW; 1792 int rc = 0; 1793 1794 Status = HEAP_strdupA2W ( &FilenameW, lpszFilename ); 1795 if ( !NT_SUCCESS (Status) ) 1796 { 1797 SetLastError (RtlNtStatusToDosError(Status)); 1798 } 1799 else 1800 { 1801 rc = GdiAddFontResourceW ( FilenameW, 0, 0); 1802 1803 HEAP_free ( FilenameW ); 1804 } 1805 return rc; 1806 } 1807 1808 1809 /* 1810 * @implemented 1811 */ 1812 int 1813 WINAPI 1814 AddFontResourceW ( LPCWSTR lpszFilename ) 1815 { 1816 return GdiAddFontResourceW ( lpszFilename, 0, 0 ); 1817 } 1818 1819 1820 /* 1821 * @implemented 1822 */ 1823 BOOL 1824 WINAPI 1825 RemoveFontResourceW(LPCWSTR lpFileName) 1826 { 1827 return RemoveFontResourceExW(lpFileName,0,0); 1828 } 1829 1830 1831 /* 1832 * @implemented 1833 */ 1834 BOOL 1835 WINAPI 1836 RemoveFontResourceA(LPCSTR lpFileName) 1837 { 1838 return RemoveFontResourceExA(lpFileName,0,0); 1839 } 1840 1841 /* 1842 * @unimplemented 1843 */ 1844 BOOL 1845 WINAPI 1846 RemoveFontResourceExA(LPCSTR lpFileName, 1847 DWORD fl, 1848 PVOID pdv 1849 ) 1850 { 1851 NTSTATUS Status; 1852 LPWSTR lpFileNameW; 1853 1854 /* FIXME the flags */ 1855 /* FIXME the pdv */ 1856 /* FIXME NtGdiRemoveFontResource handle flags and pdv */ 1857 1858 Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName ); 1859 if (!NT_SUCCESS (Status)) 1860 SetLastError (RtlNtStatusToDosError(Status)); 1861 else 1862 { 1863 1864 HEAP_free ( lpFileNameW ); 1865 } 1866 1867 return 0; 1868 } 1869 1870 /* 1871 * @unimplemented 1872 */ 1873 BOOL 1874 WINAPI 1875 RemoveFontResourceExW(LPCWSTR lpFileName, 1876 DWORD fl, 1877 PVOID pdv) 1878 { 1879 /* FIXME the flags */ 1880 /* FIXME the pdv */ 1881 /* FIXME NtGdiRemoveFontResource handle flags and pdv */ 1882 DPRINT("RemoveFontResourceExW\n"); 1883 return 0; 1884 } 1885 1886 1887 /*********************************************************************** 1888 * GdiGetCharDimensions 1889 * 1890 * Gets the average width of the characters in the English alphabet. 1891 * 1892 * PARAMS 1893 * hdc [I] Handle to the device context to measure on. 1894 * lptm [O] Pointer to memory to store the text metrics into. 1895 * height [O] On exit, the maximum height of characters in the English alphabet. 1896 * 1897 * RETURNS 1898 * The average width of characters in the English alphabet. 1899 * 1900 * NOTES 1901 * This function is used by the dialog manager to get the size of a dialog 1902 * unit. It should also be used by other pieces of code that need to know 1903 * the size of a dialog unit in logical units without having access to the 1904 * window handle of the dialog. 1905 * Windows caches the font metrics from this function, but we don't and 1906 * there doesn't appear to be an immediate advantage to do so. 1907 * 1908 * SEE ALSO 1909 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect. 1910 * 1911 * Despite most of MSDN insisting that the horizontal base unit is 1912 * tmAveCharWidth it isn't. Knowledge base article Q145994 1913 * "HOWTO: Calculate Dialog Units When Not Using the System Font", 1914 * says that we should take the average of the 52 English upper and lower 1915 * case characters. 1916 */ 1917 /* 1918 * @implemented 1919 */ 1920 LONG 1921 WINAPI 1922 GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height) 1923 { 1924 SIZE sz; 1925 TEXTMETRICW tm; 1926 static const WCHAR alphabet[] = 1927 { 1928 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', 1929 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H', 1930 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0 1931 }; 1932 1933 if(!GetTextMetricsW(hdc, &tm)) return 0; 1934 1935 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0; 1936 1937 if (lptm) *lptm = tm; 1938 if (height) *height = tm.tmHeight; 1939 1940 return (sz.cx / 26 + 1) / 2; 1941 } 1942 1943 /************************************************************************* 1944 * TranslateCharsetInfo [GDI32.@] 1945 * 1946 * Fills a CHARSETINFO structure for a character set, code page, or 1947 * font. This allows making the correspondance between different labelings 1948 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges) 1949 * of the same encoding. 1950 * 1951 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used, 1952 * only one codepage should be set in *lpSrc. 1953 * 1954 * RETURNS 1955 * TRUE on success, FALSE on failure. 1956 * 1957 */ 1958 /* 1959 * @implemented 1960 */ 1961 BOOL 1962 WINAPI 1963 TranslateCharsetInfo( 1964 LPDWORD lpSrc, /* [in] 1965 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE 1966 if flags == TCI_SRCCHARSET: a character set value 1967 if flags == TCI_SRCCODEPAGE: a code page value 1968 */ 1969 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */ 1970 DWORD flags /* [in] determines interpretation of lpSrc */) 1971 { 1972 int index = 0; 1973 switch (flags) 1974 { 1975 case TCI_SRCFONTSIG: 1976 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++; 1977 break; 1978 case TCI_SRCCODEPAGE: 1979 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++; 1980 break; 1981 case TCI_SRCCHARSET: 1982 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++; 1983 break; 1984 case TCI_SRCLOCALE: 1985 { 1986 LCID lCid = (LCID)PtrToUlong(lpSrc); 1987 LOCALESIGNATURE LocSig; 1988 INT Ret = GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, 0); 1989 if ( GetLocaleInfoW(lCid, LOCALE_FONTSIGNATURE, (LPWSTR)&LocSig, Ret)) 1990 { 1991 while (index < MAXTCIINDEX && !(LocSig.lsCsbDefault[0]>>index & 0x0001)) index++; 1992 break; 1993 } 1994 } 1995 default: 1996 GdiSetLastError(ERROR_INVALID_PARAMETER); 1997 return FALSE; 1998 } 1999 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE; 2000 DPRINT("Index %d Charset %u CodePage %u FontSig %lu\n", 2001 index,FONT_tci[index].ciCharset,FONT_tci[index].ciACP,FONT_tci[index].fs.fsCsb[0]); 2002 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO)); 2003 return TRUE; 2004 } 2005 2006 2007 /* 2008 * @implemented 2009 */ 2010 DWORD 2011 WINAPI 2012 SetMapperFlags( 2013 HDC hDC, 2014 DWORD flags 2015 ) 2016 { 2017 DWORD Ret = GDI_ERROR; 2018 PDC_ATTR Dc_Attr; 2019 #if 0 2020 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) 2021 { 2022 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) 2023 return MFDRV_SetMapperFlags( hDC, flags); 2024 else 2025 { 2026 PLDC pLDC = Dc_Attr->pvLDC; 2027 if ( !pLDC ) 2028 { 2029 SetLastError(ERROR_INVALID_HANDLE); 2030 return GDI_ERROR; 2031 } 2032 if (pLDC->iType == LDC_EMFLDC) 2033 { 2034 return EMFDRV_SetMapperFlags( hDC, flags); 2035 } 2036 } 2037 } 2038 #endif 2039 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return GDI_ERROR; 2040 2041 if (NtCurrentTeb()->GdiTebBatch.HDC == hDC) 2042 { 2043 if (Dc_Attr->ulDirty_ & DC_FONTTEXT_DIRTY) 2044 { 2045 NtGdiFlush(); 2046 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY); 2047 } 2048 } 2049 2050 if ( flags & ~1 ) 2051 SetLastError(ERROR_INVALID_PARAMETER); 2052 else 2053 { 2054 Ret = Dc_Attr->flFontMapper; 2055 Dc_Attr->flFontMapper = flags; 2056 } 2057 return Ret; 2058 } 2059 2060 2061 /* 2062 * @unimplemented 2063 */ 2064 int 2065 WINAPI 2066 EnumFontsW( 2067 HDC hDC, 2068 LPCWSTR lpFaceName, 2069 FONTENUMPROCW FontFunc, 2070 LPARAM lParam 2071 ) 2072 { 2073 #if 0 2074 return NtGdiEnumFonts ( hDC, lpFaceName, FontFunc, lParam ); 2075 #else 2076 return EnumFontFamiliesW( hDC, lpFaceName, FontFunc, lParam ); 2077 #endif 2078 } 2079 2080 /* 2081 * @unimplemented 2082 */ 2083 int 2084 WINAPI 2085 EnumFontsA ( 2086 HDC hDC, 2087 LPCSTR lpFaceName, 2088 FONTENUMPROCA FontFunc, 2089 LPARAM lParam 2090 ) 2091 { 2092 #if 0 2093 NTSTATUS Status; 2094 LPWSTR lpFaceNameW; 2095 int rc = 0; 2096 2097 Status = HEAP_strdupA2W ( &lpFaceNameW, lpFaceName ); 2098 if (!NT_SUCCESS (Status)) 2099 SetLastError (RtlNtStatusToDosError(Status)); 2100 else 2101 { 2102 rc = NtGdiEnumFonts ( hDC, lpFaceNameW, FontFunc, lParam ); 2103 2104 HEAP_free ( lpFaceNameW ); 2105 } 2106 return rc; 2107 #else 2108 return EnumFontFamiliesA( hDC, lpFaceName, FontFunc, lParam ); 2109 #endif 2110 } 2111 2112 #define EfdFontFamilies 3 2113 2114 INT 2115 WINAPI 2116 NewEnumFontFamiliesExW( 2117 HDC hDC, 2118 LPLOGFONTW lpLogfont, 2119 FONTENUMPROCW lpEnumFontFamExProcW, 2120 LPARAM lParam, 2121 DWORD dwFlags) 2122 { 2123 ULONG_PTR idEnum; 2124 ULONG cbDataSize, cbRetSize; 2125 PENUMFONTDATAW pEfdw; 2126 PBYTE pBuffer; 2127 PBYTE pMax; 2128 INT ret = 1; 2129 2130 /* Open enumeration handle and find out how much memory we need */ 2131 idEnum = NtGdiEnumFontOpen(hDC, 2132 EfdFontFamilies, 2133 0, 2134 LF_FACESIZE, 2135 (lpLogfont && lpLogfont->lfFaceName[0])? lpLogfont->lfFaceName : NULL, 2136 lpLogfont? lpLogfont->lfCharSet : DEFAULT_CHARSET, 2137 &cbDataSize); 2138 if (idEnum == 0) 2139 { 2140 return 0; 2141 } 2142 if (cbDataSize == 0) 2143 { 2144 NtGdiEnumFontClose(idEnum); 2145 return 0; 2146 } 2147 2148 /* Allocate memory */ 2149 pBuffer = HeapAlloc(GetProcessHeap(), 0, cbDataSize); 2150 if (pBuffer == NULL) 2151 { 2152 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2153 NtGdiEnumFontClose(idEnum); 2154 return 0; 2155 } 2156 2157 /* Do the enumeration */ 2158 if (!NtGdiEnumFontChunk(hDC, idEnum, cbDataSize, &cbRetSize, (PVOID)pBuffer)) 2159 { 2160 HeapFree(GetProcessHeap(), 0, pBuffer); 2161 NtGdiEnumFontClose(idEnum); 2162 return 0; 2163 } 2164 2165 /* Get start and end address */ 2166 pEfdw = (PENUMFONTDATAW)pBuffer; 2167 pMax = pBuffer + cbDataSize; 2168 2169 /* Iterate through the structures */ 2170 while ((PBYTE)pEfdw < pMax && ret) 2171 { 2172 PNTMW_INTERNAL pNtmwi = (PNTMW_INTERNAL)((ULONG_PTR)pEfdw + pEfdw->ulNtmwiOffset); 2173 2174 ret = lpEnumFontFamExProcW((VOID*)&pEfdw->elfexdv.elfEnumLogfontEx, 2175 (VOID*)&pNtmwi->ntmw, 2176 pEfdw->dwFontType, 2177 lParam); 2178 2179 pEfdw = (PENUMFONTDATAW)((ULONG_PTR)pEfdw + pEfdw->cbSize); 2180 } 2181 2182 /* Release the memory and close handle */ 2183 HeapFree(GetProcessHeap(), 0, pBuffer); 2184 NtGdiEnumFontClose(idEnum); 2185 2186 return ret; 2187 } 2188 2189 /* 2190 * @implemented 2191 */ 2192 int 2193 WINAPI 2194 GdiAddFontResourceW( 2195 LPCWSTR lpszFilename, 2196 FLONG fl, 2197 DESIGNVECTOR *pdv) 2198 { 2199 INT Ret; 2200 WCHAR lpszBuffer[MAX_PATH]; 2201 WCHAR lpszAbsPath[MAX_PATH]; 2202 UNICODE_STRING NtAbsPath; 2203 2204 /* FIXME: We don't support multiple files passed in lpszFilename 2205 * as L"abcxxxxx.pfm|abcxxxxx.pfb" 2206 */ 2207 2208 /* Does the file exist in CurrentDirectory or in the Absolute Path passed? */ 2209 GetCurrentDirectoryW(MAX_PATH, lpszBuffer); 2210 2211 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL)) 2212 { 2213 /* Nope. Then let's check Fonts folder */ 2214 GetWindowsDirectoryW(lpszBuffer, MAX_PATH); 2215 StringCbCatW(lpszBuffer, sizeof(lpszBuffer), L"\\Fonts"); 2216 2217 if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL)) 2218 { 2219 DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer, lpszFilename); 2220 return 0; 2221 } 2222 } 2223 2224 /* We found the font file so: */ 2225 if (!RtlDosPathNameToNtPathName_U(lpszAbsPath, &NtAbsPath, NULL, NULL)) 2226 { 2227 DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath); 2228 return 0; 2229 } 2230 2231 /* The Nt call expects a null-terminator included in cwc param. */ 2232 ASSERT(NtAbsPath.Buffer[NtAbsPath.Length / sizeof(WCHAR)] == UNICODE_NULL); 2233 Ret = NtGdiAddFontResourceW(NtAbsPath.Buffer, NtAbsPath.Length / sizeof(WCHAR) + 1, 1, fl, 0, pdv); 2234 2235 RtlFreeUnicodeString(&NtAbsPath); 2236 2237 return Ret; 2238 } 2239 2240 /* 2241 * @implemented 2242 */ 2243 HANDLE 2244 WINAPI 2245 AddFontMemResourceEx( 2246 PVOID pbFont, 2247 DWORD cbFont, 2248 PVOID pdv, 2249 DWORD *pcFonts 2250 ) 2251 { 2252 if ( pbFont && cbFont && pcFonts) 2253 { 2254 return NtGdiAddFontMemResourceEx(pbFont, cbFont, NULL, 0, pcFonts); 2255 } 2256 SetLastError(ERROR_INVALID_PARAMETER); 2257 return NULL; 2258 } 2259 2260 /* 2261 * @implemented 2262 */ 2263 BOOL 2264 WINAPI 2265 RemoveFontMemResourceEx(HANDLE fh) 2266 { 2267 if (fh) 2268 { 2269 return NtGdiRemoveFontMemResourceEx(fh); 2270 } 2271 SetLastError(ERROR_INVALID_PARAMETER); 2272 return FALSE; 2273 } 2274 2275 2276 /* 2277 * @unimplemented 2278 */ 2279 int 2280 WINAPI 2281 AddFontResourceTracking( 2282 LPCSTR lpString, 2283 int unknown 2284 ) 2285 { 2286 UNIMPLEMENTED; 2287 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2288 return 0; 2289 } 2290 2291 /* 2292 * @unimplemented 2293 */ 2294 int 2295 WINAPI 2296 RemoveFontResourceTracking(LPCSTR lpString,int unknown) 2297 { 2298 UNIMPLEMENTED; 2299 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2300 return 0; 2301 } 2302 2303 BOOL 2304 WINAPI 2305 CreateScalableFontResourceW( 2306 DWORD fdwHidden, 2307 LPCWSTR lpszFontRes, 2308 LPCWSTR lpszFontFile, 2309 LPCWSTR lpszCurrentPath 2310 ) 2311 { 2312 HANDLE f; 2313 2314 UNIMPLEMENTED; 2315 2316 /* fHidden=1 - only visible for the calling app, read-only, not 2317 * enumerated with EnumFonts/EnumFontFamilies 2318 * lpszCurrentPath can be NULL 2319 */ 2320 2321 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */ 2322 if ((f = CreateFileW(lpszFontRes, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) 2323 { 2324 CloseHandle(f); 2325 SetLastError(ERROR_FILE_EXISTS); 2326 return FALSE; 2327 } 2328 return FALSE; /* create failed */ 2329 } 2330 2331 /* 2332 * @unimplemented 2333 */ 2334 BOOL 2335 WINAPI 2336 bInitSystemAndFontsDirectoriesW(LPWSTR *SystemDir,LPWSTR *FontsDir) 2337 { 2338 UNIMPLEMENTED; 2339 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2340 return 0; 2341 } 2342 2343 /* 2344 * @unimplemented 2345 */ 2346 BOOL 2347 WINAPI 2348 EudcLoadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath,INT iPriority,INT iFontLinkType) 2349 { 2350 UNIMPLEMENTED; 2351 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2352 return 0; 2353 } 2354 2355 /* 2356 * @unimplemented 2357 */ 2358 BOOL 2359 WINAPI 2360 EudcUnloadLinkW(LPCWSTR pBaseFaceName,LPCWSTR pEudcFontPath) 2361 { 2362 UNIMPLEMENTED; 2363 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2364 return 0; 2365 } 2366 2367 /* 2368 * @implemented 2369 */ 2370 ULONG 2371 WINAPI 2372 GetEUDCTimeStamp(VOID) 2373 { 2374 return NtGdiGetEudcTimeStampEx(NULL,0,TRUE); 2375 } 2376 2377 /* 2378 * @implemented 2379 */ 2380 DWORD 2381 WINAPI 2382 GetEUDCTimeStampExW(LPWSTR lpBaseFaceName) 2383 { 2384 DWORD retValue = 0; 2385 2386 if (!lpBaseFaceName) 2387 { 2388 retValue = NtGdiGetEudcTimeStampEx(NULL,0,FALSE); 2389 } 2390 else 2391 { 2392 retValue = NtGdiGetEudcTimeStampEx(lpBaseFaceName, wcslen(lpBaseFaceName), FALSE); 2393 } 2394 2395 return retValue; 2396 } 2397 2398 /* 2399 * @implemented 2400 */ 2401 ULONG 2402 WINAPI 2403 GetFontAssocStatus(HDC hdc) 2404 { 2405 ULONG retValue = 0; 2406 2407 if (hdc) 2408 { 2409 retValue = NtGdiQueryFontAssocInfo(hdc); 2410 } 2411 2412 return retValue; 2413 } 2414 2415 /* 2416 * @unimplemented 2417 */ 2418 DWORD 2419 WINAPI 2420 QueryFontAssocStatus(VOID) 2421 { 2422 UNIMPLEMENTED; 2423 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2424 return 0; 2425 } 2426 2427 /* 2428 * @unimplemented 2429 */ 2430 VOID 2431 WINAPI 2432 UnloadNetworkFonts(DWORD unknown) 2433 { 2434 UNIMPLEMENTED; 2435 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2436 } 2437 2438 /* 2439 * @implemented 2440 * 2441 */ 2442 DWORD 2443 WINAPI 2444 GetFontData(HDC hdc, 2445 DWORD dwTable, 2446 DWORD dwOffset, 2447 LPVOID lpvBuffer, 2448 DWORD cbData) 2449 { 2450 if (!lpvBuffer) 2451 { 2452 cbData = 0; 2453 } 2454 return NtGdiGetFontData(hdc, dwTable, dwOffset, lpvBuffer, cbData); 2455 } 2456 2457 DWORD 2458 WINAPI 2459 cGetTTFFromFOT(DWORD x1 ,DWORD x2 ,DWORD x3, DWORD x4, DWORD x5, DWORD x6, DWORD x7) 2460 { 2461 UNIMPLEMENTED; 2462 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2463 return 0; 2464 } 2465 2466