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