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