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