1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #define INCL_GRE_STRINGS 25 #define INCL_GPI 26 #define INCL_DOS 27 28 #include <string.h> 29 //#include <stdlib.h> 30 //#include <math.h> 31 #include <svpm.h> 32 33 #include <vcl/sysdata.hxx> 34 #include "tools/svwin.h" 35 36 #include "os2/saldata.hxx" 37 #include "os2/salgdi.h" 38 39 #include "vcl/svapp.hxx" 40 #include "outfont.hxx" 41 #include "vcl/font.hxx" 42 #include "fontsubset.hxx" 43 #include "sallayout.hxx" 44 45 #include "rtl/logfile.hxx" 46 #include "rtl/tencinfo.h" 47 #include "rtl/textcvt.h" 48 #include "rtl/bootstrap.hxx" 49 50 51 #include "osl/module.h" 52 #include "osl/file.hxx" 53 #include "osl/thread.hxx" 54 #include "osl/process.h" 55 56 #include "tools/poly.hxx" 57 #include "tools/debug.hxx" 58 #include "tools/stream.hxx" 59 60 #include "basegfx/polygon/b2dpolygon.hxx" 61 #include "basegfx/polygon/b2dpolypolygon.hxx" 62 #include "basegfx/matrix/b2dhommatrix.hxx" 63 64 #ifndef __H_FT2LIB 65 #include <os2/wingdi.h> 66 #include <ft2lib.h> 67 #endif 68 69 #include "sft.hxx" 70 71 #ifdef GCP_KERN_HACK 72 #include <algorithm> 73 #endif 74 75 using namespace vcl; 76 77 // ----------- 78 // - Inlines - 79 // ----------- 80 81 82 inline W32FIXED FixedFromDouble( double d ) 83 { 84 const long l = (long) ( d * 65536. ); 85 return *(W32FIXED*) &l; 86 } 87 88 // ----------------------------------------------------------------------- 89 90 inline int IntTimes256FromFixed(W32FIXED f) 91 { 92 int nFixedTimes256 = (f.value << 8) + ((f.fract+0x80) >> 8); 93 return nFixedTimes256; 94 } 95 96 // ----------- 97 // - Defines - 98 // ----------- 99 100 // this is a special codepage code, used to identify OS/2 symbol font. 101 #define SYMBOL_CHARSET 65400 102 103 // ======================================================================= 104 105 UniString ImplSalGetUniString( const sal_Char* pStr, xub_StrLen nLen = STRING_LEN) 106 { 107 return UniString( pStr, nLen, gsl_getSystemTextEncoding(), 108 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT | 109 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT | 110 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT ); 111 } 112 113 // ======================================================================= 114 115 static USHORT ImplSalToCharSet( CharSet eCharSet ) 116 { 117 // !!! Fuer DBCS-Systeme muss dieser Code auskommentiert werden und 0 118 // !!! zurueckgegeben werden, solange die DBCS-Charsets nicht 119 // !!! durchgereicht werden 120 121 switch ( eCharSet ) 122 { 123 case RTL_TEXTENCODING_IBM_437: 124 return 437; 125 126 case RTL_TEXTENCODING_IBM_850: 127 return 850; 128 129 case RTL_TEXTENCODING_IBM_860: 130 return 860; 131 132 case RTL_TEXTENCODING_IBM_861: 133 return 861; 134 135 case RTL_TEXTENCODING_IBM_863: 136 return 863; 137 138 case RTL_TEXTENCODING_IBM_865: 139 return 865; 140 case RTL_TEXTENCODING_MS_1252: 141 return 1004; 142 case RTL_TEXTENCODING_SYMBOL: 143 return 65400; 144 } 145 146 return 0; 147 } 148 149 // ----------------------------------------------------------------------- 150 151 static CharSet ImplCharSetToSal( USHORT usCodePage ) 152 { 153 switch ( usCodePage ) 154 { 155 case 437: 156 return RTL_TEXTENCODING_IBM_437; 157 158 case 850: 159 return RTL_TEXTENCODING_IBM_850; 160 161 case 860: 162 return RTL_TEXTENCODING_IBM_860; 163 164 case 861: 165 return RTL_TEXTENCODING_IBM_861; 166 167 case 863: 168 return RTL_TEXTENCODING_IBM_863; 169 170 case 865: 171 return RTL_TEXTENCODING_IBM_865; 172 case 1004: 173 return RTL_TEXTENCODING_MS_1252; 174 case 65400: 175 return RTL_TEXTENCODING_SYMBOL; 176 } 177 178 return RTL_TEXTENCODING_DONTKNOW; 179 } 180 181 // ----------------------------------------------------------------------- 182 183 static FontFamily ImplFamilyToSal( PM_BYTE bFamilyType ) 184 { 185 switch ( bFamilyType ) 186 { 187 case 4: 188 return FAMILY_DECORATIVE; 189 case 3: 190 return FAMILY_SCRIPT; 191 } 192 193 return FAMILY_DONTKNOW; 194 } 195 196 // ----------------------------------------------------------------------- 197 198 static FontWeight ImplWeightToSal( USHORT nWeight ) 199 { 200 // Falls sich jemand an die alte Doku gehalten hat 201 if ( nWeight > 999 ) 202 nWeight /= 1000; 203 204 switch ( nWeight ) 205 { 206 case 1: 207 return WEIGHT_THIN; 208 209 case 2: 210 return WEIGHT_ULTRALIGHT; 211 212 case 3: 213 return WEIGHT_LIGHT; 214 215 case 4: 216 return WEIGHT_SEMILIGHT; 217 218 case 5: 219 return WEIGHT_NORMAL; 220 221 case 6: 222 return WEIGHT_SEMIBOLD; 223 224 case 7: 225 return WEIGHT_BOLD; 226 227 case 8: 228 return WEIGHT_ULTRABOLD; 229 230 case 9: 231 return WEIGHT_BLACK; 232 } 233 234 return WEIGHT_DONTKNOW; 235 } 236 237 // ----------------------------------------------------------------------- 238 239 static UniString ImpStyleNameToSal( const char* pFamilyName, 240 const char* pFaceName, 241 USHORT nLen ) 242 { 243 if ( !nLen ) 244 nLen = strlen(pFamilyName); 245 246 // strip FamilyName from FaceName 247 if ( strncmp( pFamilyName, pFaceName, nLen ) == 0 ) 248 { 249 USHORT nFaceLen = (USHORT)strlen( pFaceName+nLen ); 250 // Ist Facename laenger, schneiden wir den FamilyName ab 251 if ( nFaceLen > 1 ) 252 return UniString( pFaceName+(nLen+1), gsl_getSystemTextEncoding()); 253 else 254 return UniString(); 255 } 256 else 257 return UniString( pFaceName, gsl_getSystemTextEncoding()); 258 } 259 260 // ----------------------------------------------------------------------- 261 262 inline FontPitch ImplLogPitchToSal( PM_BYTE fsType ) 263 { 264 if ( fsType & FM_TYPE_FIXED ) 265 return PITCH_FIXED; 266 else 267 return PITCH_VARIABLE; 268 } 269 270 // ----------------------------------------------------------------------- 271 272 inline PM_BYTE ImplPitchToWin( FontPitch ePitch ) 273 { 274 if ( ePitch == PITCH_FIXED ) 275 return FM_TYPE_FIXED; 276 //else if ( ePitch == PITCH_VARIABLE ) 277 278 return 0; 279 } 280 281 // ----------------------------------------------------------------------- 282 283 static ImplDevFontAttributes Os2Font2DevFontAttributes( const PFONTMETRICS pFontMetric) 284 { 285 ImplDevFontAttributes aDFA; 286 287 // get font face attributes 288 aDFA.meFamily = ImplFamilyToSal( pFontMetric->panose.bFamilyType); 289 aDFA.meWidthType = WIDTH_DONTKNOW; 290 aDFA.meWeight = ImplWeightToSal( pFontMetric->usWeightClass); 291 aDFA.meItalic = (pFontMetric->fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE; 292 aDFA.mePitch = ImplLogPitchToSal( pFontMetric->fsType ); 293 aDFA.mbSymbolFlag = (pFontMetric->usCodePage == SYMBOL_CHARSET); 294 295 // get the font face name 296 // the maName field stores the font name without the style, so under OS/2 297 // we must use the family name 298 aDFA.maName = UniString( pFontMetric->szFamilyname, gsl_getSystemTextEncoding()); 299 300 aDFA.maStyleName = ImpStyleNameToSal( pFontMetric->szFamilyname, 301 pFontMetric->szFacename, 302 strlen( pFontMetric->szFamilyname) ); 303 304 // get device specific font attributes 305 aDFA.mbOrientation = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0; 306 aDFA.mbDevice = (pFontMetric->fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE; 307 308 aDFA.mbEmbeddable = false; 309 aDFA.mbSubsettable = false; 310 DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFamilyname); 311 if( fontType == FT2_FONTTYPE_TRUETYPE && !aDFA.mbDevice) 312 aDFA.mbSubsettable = true; 313 // for now we can only embed Type1 fonts 314 if( fontType == FT2_FONTTYPE_TYPE1 ) 315 aDFA.mbEmbeddable = true; 316 317 // heuristics for font quality 318 // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster 319 // - subsetting > embedding > none 320 aDFA.mnQuality = 0; 321 if( fontType == FT2_FONTTYPE_TRUETYPE ) 322 aDFA.mnQuality += 50; 323 if( aDFA.mbSubsettable ) 324 aDFA.mnQuality += 200; 325 else if( aDFA.mbEmbeddable ) 326 aDFA.mnQuality += 100; 327 328 // #i38665# prefer Type1 versions of the standard postscript fonts 329 if( aDFA.mbEmbeddable ) 330 { 331 if( aDFA.maName.EqualsAscii( "AvantGarde" ) 332 || aDFA.maName.EqualsAscii( "Bookman" ) 333 || aDFA.maName.EqualsAscii( "Courier" ) 334 || aDFA.maName.EqualsAscii( "Helvetica" ) 335 || aDFA.maName.EqualsAscii( "NewCenturySchlbk" ) 336 || aDFA.maName.EqualsAscii( "Palatino" ) 337 || aDFA.maName.EqualsAscii( "Symbol" ) 338 || aDFA.maName.EqualsAscii( "Times" ) 339 || aDFA.maName.EqualsAscii( "ZapfChancery" ) 340 || aDFA.maName.EqualsAscii( "ZapfDingbats" ) ) 341 aDFA.mnQuality += 500; 342 } 343 344 // TODO: add alias names 345 346 return aDFA; 347 } 348 349 // ======================================================================= 350 351 // raw font data with a scoped lifetime 352 class RawFontData 353 { 354 public: 355 explicit RawFontData( HDC, DWORD nTableTag=0 ); 356 ~RawFontData() { delete[] mpRawBytes; } 357 const unsigned char* get() const { return mpRawBytes; } 358 const unsigned char* steal() { unsigned char* p = mpRawBytes; mpRawBytes = NULL; return p; } 359 const int size() const { return mnByteCount; } 360 361 private: 362 unsigned char* mpRawBytes; 363 int mnByteCount; 364 }; 365 366 RawFontData::RawFontData( HPS hPS, DWORD nTableTag ) 367 : mpRawBytes( NULL ) 368 , mnByteCount( 0 ) 369 { 370 // get required size in bytes 371 mnByteCount = ::Ft2GetFontData( hPS, nTableTag, 0, NULL, 0 ); 372 if( mnByteCount == FT2_ERROR ) 373 return; 374 else if( !mnByteCount ) 375 return; 376 377 // allocate the array 378 mpRawBytes = new unsigned char[ mnByteCount ]; 379 380 // get raw data in chunks small enough for GetFontData() 381 int nRawDataOfs = 0; 382 DWORD nMaxChunkSize = 0x100000; 383 for(;;) 384 { 385 // calculate remaining raw data to get 386 DWORD nFDGet = mnByteCount - nRawDataOfs; 387 if( nFDGet <= 0 ) 388 break; 389 // #i56745# limit GetFontData requests 390 if( nFDGet > nMaxChunkSize ) 391 nFDGet = nMaxChunkSize; 392 const DWORD nFDGot = ::Ft2GetFontData( hPS, nTableTag, nRawDataOfs, 393 (void*)(mpRawBytes + nRawDataOfs), nFDGet ); 394 if( !nFDGot ) 395 break; 396 else if( nFDGot != FT2_ERROR ) 397 nRawDataOfs += nFDGot; 398 else 399 { 400 // was the chunk too big? reduce it 401 nMaxChunkSize /= 2; 402 if( nMaxChunkSize < 0x10000 ) 403 break; 404 } 405 } 406 407 // cleanup if the raw data is incomplete 408 if( nRawDataOfs != mnByteCount ) 409 { 410 delete[] mpRawBytes; 411 mpRawBytes = NULL; 412 } 413 } 414 415 // ----------------------------------------------------------------------- 416 417 // ======================================================================= 418 419 ImplOs2FontData::ImplOs2FontData( PFONTMETRICS _pFontMetric, 420 int nHeight, PM_BYTE nPitchAndFamily ) 421 : ImplFontData( Os2Font2DevFontAttributes(_pFontMetric), 0 ), 422 pFontMetric( _pFontMetric ), 423 meOs2CharSet( _pFontMetric->usCodePage), 424 mnPitchAndFamily( nPitchAndFamily ), 425 mpFontCharSets( NULL ), 426 mpUnicodeMap( NULL ), 427 mbDisableGlyphApi( false ), 428 mbHasKoreanRange( false ), 429 mbHasCJKSupport( false ), 430 mbAliasSymbolsLow( false ), 431 mbAliasSymbolsHigh( false ), 432 mnId( 0 ) 433 { 434 SetBitmapSize( 0, nHeight ); 435 } 436 437 // ----------------------------------------------------------------------- 438 439 ImplOs2FontData::~ImplOs2FontData() 440 { 441 delete[] mpFontCharSets; 442 443 if( mpUnicodeMap ) 444 mpUnicodeMap->DeReference(); 445 } 446 447 // ----------------------------------------------------------------------- 448 449 sal_IntPtr ImplOs2FontData::GetFontId() const 450 { 451 return mnId; 452 } 453 454 // ----------------------------------------------------------------------- 455 456 void ImplOs2FontData::UpdateFromHPS( HPS hPS ) const 457 { 458 // short circuit if already initialized 459 if( mpUnicodeMap != NULL ) 460 return; 461 462 ReadCmapTable( hPS ); 463 ReadOs2Table( hPS ); 464 465 // even if the font works some fonts have problems with the glyph API 466 // => the heuristic below tries to figure out which fonts have the problem 467 DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFacename); 468 if( fontType != FT2_FONTTYPE_TRUETYPE 469 && (pFontMetric->fsDefn & FM_DEFN_GENERIC) == 0) 470 mbDisableGlyphApi = true; 471 } 472 473 // ----------------------------------------------------------------------- 474 475 bool ImplOs2FontData::HasGSUBstitutions( HPS hPS ) const 476 { 477 if( !mbGsubRead ) 478 ReadGsubTable( hPS ); 479 return !maGsubTable.empty(); 480 } 481 482 // ----------------------------------------------------------------------- 483 484 bool ImplOs2FontData::IsGSUBstituted( sal_Ucs cChar ) const 485 { 486 return( maGsubTable.find( cChar ) != maGsubTable.end() ); 487 } 488 489 // ----------------------------------------------------------------------- 490 491 const ImplFontCharMap* ImplOs2FontData::GetImplFontCharMap() const 492 { 493 mpUnicodeMap->AddReference(); 494 return mpUnicodeMap; 495 } 496 497 // ----------------------------------------------------------------------- 498 499 static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} 500 static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);} 501 static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));} 502 static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); } 503 504 void ImplOs2FontData::ReadOs2Table( HPS hPS ) const 505 { 506 const DWORD Os2Tag = CalcTag( "OS/2" ); 507 DWORD nLength = Ft2GetFontData( hPS, Os2Tag, 0, NULL, 0 ); 508 if( (nLength == FT2_ERROR) || !nLength ) 509 return; 510 std::vector<unsigned char> aOS2map( nLength ); 511 unsigned char* pOS2map = &aOS2map[0]; 512 DWORD nRC = Ft2GetFontData( hPS, Os2Tag, 0, pOS2map, nLength ); 513 sal_uInt32 nVersion = GetUShort( pOS2map ); 514 if ( nVersion >= 0x0001 && nLength >= 58 ) 515 { 516 // We need at least version 0x0001 (TrueType rev 1.66) 517 // to have access to the needed struct members. 518 sal_uInt32 ulUnicodeRange1 = GetUInt( pOS2map + 42 ); 519 sal_uInt32 ulUnicodeRange2 = GetUInt( pOS2map + 46 ); 520 #if 0 521 sal_uInt32 ulUnicodeRange3 = GetUInt( pOS2map + 50 ); 522 sal_uInt32 ulUnicodeRange4 = GetUInt( pOS2map + 54 ); 523 #endif 524 525 // Check for CJK capabilities of the current font 526 mbHasCJKSupport = (ulUnicodeRange2 & 0x2DF00000); 527 mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000) 528 | (ulUnicodeRange2 & 0x01100000); 529 mbHasArabicSupport = (ulUnicodeRange1 & 0x00002000); 530 } 531 } 532 533 534 // ----------------------------------------------------------------------- 535 536 void ImplOs2FontData::ReadGsubTable( HPS hPS ) const 537 { 538 mbGsubRead = true; 539 540 // check the existence of a GSUB table 541 const DWORD GsubTag = CalcTag( "GSUB" ); 542 DWORD nRC = Ft2GetFontData( hPS, GsubTag, 0, NULL, 0 ); 543 if( (nRC == FT2_ERROR) || !nRC ) 544 return; 545 546 // parse the GSUB table through sft 547 // TODO: parse it directly 548 549 // sft needs the full font file data => get it 550 const RawFontData aRawFontData( hPS ); 551 if( !aRawFontData.get() ) 552 return; 553 554 // open font file 555 sal_uInt32 nFaceNum = 0; 556 if( !*aRawFontData.get() ) // TTC candidate 557 nFaceNum = ~0U; // indicate "TTC font extracts only" 558 559 TrueTypeFont* pTTFont = NULL; 560 ::OpenTTFontBuffer( (void*)aRawFontData.get(), aRawFontData.size(), nFaceNum, &pTTFont ); 561 if( !pTTFont ) 562 return; 563 564 // add vertically substituted characters to list 565 static const sal_Unicode aGSUBCandidates[] = { 566 0x0020, 0x0080, // ASCII 567 0x2000, 0x2600, // misc 568 0x3000, 0x3100, // CJK punctutation 569 0x3300, 0x3400, // squared words 570 0xFF00, 0xFFF0, // halfwidth|fullwidth forms 571 0 }; 572 573 for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 ) 574 for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar ) 575 if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) ) 576 maGsubTable.insert( cChar ); // insert GSUBbed unicodes 577 578 CloseTTFont( pTTFont ); 579 } 580 581 // ----------------------------------------------------------------------- 582 583 void ImplOs2FontData::ReadCmapTable( HPS hPS ) const 584 { 585 if( mpUnicodeMap != NULL ) 586 return; 587 588 bool bIsSymbolFont = (meOs2CharSet == SYMBOL_CHARSET); 589 // get the CMAP table from the font which is selected into the DC 590 const DWORD nCmapTag = CalcTag( "cmap" ); 591 const RawFontData aRawFontData( hPS, nCmapTag ); 592 // parse the CMAP table if available 593 if( aRawFontData.get() ) { 594 CmapResult aResult; 595 ParseCMAP( aRawFontData.get(), aRawFontData.size(), aResult ); 596 mbDisableGlyphApi |= aResult.mbRecoded; 597 aResult.mbSymbolic = bIsSymbolFont; 598 if( aResult.mnRangeCount > 0 ) 599 mpUnicodeMap = new ImplFontCharMap( aResult ); 600 } 601 602 if( !mpUnicodeMap ) 603 mpUnicodeMap = ImplFontCharMap::GetDefaultMap( bIsSymbolFont ); 604 } 605 606 // ======================================================================= 607 608 void Os2SalGraphics::SetTextColor( SalColor nSalColor ) 609 { 610 CHARBUNDLE cb; 611 612 cb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ), 613 SALCOLOR_GREEN( nSalColor ), 614 SALCOLOR_BLUE( nSalColor ) ); 615 616 // set default color attributes 617 Ft2SetAttrs( mhPS, 618 PRIM_CHAR, 619 CBB_COLOR, 620 0, 621 &cb ); 622 } 623 624 // ----------------------------------------------------------------------- 625 626 USHORT Os2SalGraphics::ImplDoSetFont( ImplFontSelectData* i_pFont, float& o_rFontScale, int nFallbackLevel) 627 { 628 629 #if OSL_DEBUG_LEVEL>10 630 debug_printf( "Os2SalGraphics::ImplDoSetFont mbPrinter=%d\n", mbPrinter); 631 #endif 632 633 ImplOs2FontData* pFontData = (ImplOs2FontData*)i_pFont->mpFontData; 634 PFONTMETRICS pFontMetric = NULL; 635 FATTRS aFAttrs; 636 PM_BOOL bOutline = FALSE; 637 APIRET rc; 638 639 memset( &aFAttrs, 0, sizeof( FATTRS ) ); 640 aFAttrs.usRecordLength = sizeof( FATTRS ); 641 642 aFAttrs.lMaxBaselineExt = i_pFont->mnHeight; 643 aFAttrs.lAveCharWidth = i_pFont->mnWidth; 644 645 // do we have a pointer to the FONTMETRICS of the selected font? -> use it! 646 if ( pFontData ) 647 { 648 pFontMetric = pFontData->GetFontMetrics(); 649 650 bOutline = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0; 651 652 // use match®istry fields to get correct match 653 aFAttrs.lMatch = pFontMetric->lMatch; 654 aFAttrs.idRegistry = pFontMetric->idRegistry; 655 aFAttrs.usCodePage = pFontMetric->usCodePage; 656 657 if ( bOutline ) 658 { 659 aFAttrs.fsFontUse |= FATTR_FONTUSE_OUTLINE; 660 if ( i_pFont->mnOrientation ) 661 aFAttrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE; 662 } 663 else 664 { 665 aFAttrs.lMaxBaselineExt = pFontMetric->lMaxBaselineExt; 666 aFAttrs.lAveCharWidth = pFontMetric->lAveCharWidth; 667 } 668 669 } 670 #if OSL_DEBUG_LEVEL>1 671 if (pFontMetric->szFacename[0] == 'D') { 672 rc = 0; // debugger breakpoint 673 } 674 #endif 675 676 // use family name for outline fonts 677 if ( mbPrinter ) { 678 // use font face name for printers because otherwise ft2lib will fail 679 // to select the correct font for GPI (ticket#117) 680 strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) ); 681 } else if ( !pFontMetric) { 682 // use OOo name if fontmetrics not available! 683 ByteString aName( i_pFont->maName.GetToken( 0 ), gsl_getSystemTextEncoding()); 684 strncpy( (char*)(aFAttrs.szFacename), aName.GetBuffer(), sizeof( aFAttrs.szFacename ) ); 685 } else if ( bOutline) { 686 // use fontmetric family name for outline fonts 687 strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFamilyname, sizeof( aFAttrs.szFacename ) ); 688 } else { 689 // use real font face name for bitmaps (WarpSans only) 690 strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) ); 691 } 692 693 if ( i_pFont->meItalic != ITALIC_NONE ) 694 aFAttrs.fsSelection |= FATTR_SEL_ITALIC; 695 if ( i_pFont->meWeight > WEIGHT_MEDIUM ) 696 aFAttrs.fsSelection |= FATTR_SEL_BOLD; 697 698 #if OSL_DEBUG_LEVEL>1 699 if (pFontMetric->szFacename[0] == 'A') { 700 debug_printf( "Os2SalGraphics::SetFont hps %x lMatch '%d'\n", mhPS, pFontMetric->lMatch); 701 debug_printf( "Os2SalGraphics::SetFont hps %x fontmetrics facename '%s'\n", mhPS, pFontMetric->szFacename); 702 debug_printf( "Os2SalGraphics::SetFont hps %x fattrs facename '%s'\n", mhPS, aFAttrs.szFacename); 703 debug_printf( "Os2SalGraphics::SetFont hps %x fattrs height '%d'\n", mhPS, aFAttrs.lMaxBaselineExt); 704 debug_printf( "Os2SalGraphics::SetFont hps %x fattrs width '%d'\n", mhPS, aFAttrs.lAveCharWidth); 705 } 706 #endif 707 708 // set default font 709 rc = Ft2SetCharSet( mhPS, LCID_DEFAULT); 710 // delete selected font 711 rc = Ft2DeleteSetId( mhPS, nFallbackLevel + LCID_BASE); 712 713 // create new logical font 714 if ( (rc=Ft2CreateLogFont( mhPS, NULL, nFallbackLevel + LCID_BASE, &aFAttrs)) == GPI_ERROR ) { 715 #if OSL_DEBUG_LEVEL>1 716 ERRORID nLastError = WinGetLastError( GetSalData()->mhAB ); 717 debug_printf( "Os2SalGraphics::SetFont hps %x Ft2CreateLogFont failed err %x\n", mhPS, nLastError ); 718 #endif 719 return SAL_SETFONT_REMOVEANDMATCHNEW; 720 } 721 722 #if OSL_DEBUG_LEVEL>1 723 // select new font 724 rc = Ft2SetCharSet( mhPS, nFallbackLevel + LCID_BASE); 725 726 // query fontmetric of new font 727 FONTMETRICS aOS2Metric = {0}; 728 rc = Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); 729 730 if (pFontMetric->szFacename[0] == 'D') { 731 debug_printf( "Os2SalGraphics::SetFont Ft2QueryFontMetrics fattrs facename '%s'\n", aOS2Metric.szFacename); 732 debug_printf( "Os2SalGraphics::SetFont Ft2QueryFontMetrics fattrs height '%d'\n", aOS2Metric.lMaxBaselineExt); 733 debug_printf( "Os2SalGraphics::SetFont Ft2QueryFontMetrics fattrs width '%d'\n", aOS2Metric.lAveCharWidth); 734 } 735 #endif 736 737 // apply font sizing, rotation 738 CHARBUNDLE aBundle; 739 740 ULONG nAttrsDefault = 0; 741 ULONG nAttrs = CBB_SET; 742 aBundle.usSet = nFallbackLevel + LCID_BASE; 743 744 if ( bOutline ) 745 { 746 nAttrs |= CBB_BOX; 747 aBundle.sizfxCell.cy = MAKEFIXED( i_pFont->mnHeight, 0 ); 748 749 if ( !i_pFont->mnWidth ) 750 { 751 LONG nXFontRes; 752 LONG nYFontRes; 753 LONG nHeight; 754 755 // Auf die Aufloesung achten, damit das Ergebnis auch auf 756 // Drucken mit 180*360 DPI stimmt. Ausserdem muss gerundet 757 // werden, da auf meinem OS2 beispielsweise als 758 // Bildschirmaufloesung 3618*3622 PixelPerMeter zurueck- 759 // gegeben wird 760 GetResolution( nXFontRes, nYFontRes ); 761 nHeight = i_pFont->mnHeight; 762 nHeight *= nXFontRes; 763 nHeight += nYFontRes/2; 764 nHeight /= nYFontRes; 765 aBundle.sizfxCell.cx = MAKEFIXED( nHeight, 0 ); 766 } 767 else 768 aBundle.sizfxCell.cx = MAKEFIXED( i_pFont->mnWidth, 0 ); 769 } 770 771 // set orientation for outlinefonts 772 if ( i_pFont->mnOrientation ) 773 { 774 if ( bOutline ) 775 { 776 nAttrs |= CBB_ANGLE; 777 double alpha = (double)(i_pFont->mnOrientation); 778 alpha *= 0.0017453292; // *PI / 1800 779 mnOrientationY = (long) (1000.0 * sin( alpha )); 780 mnOrientationX = (long) (1000.0 * cos( alpha )); 781 aBundle.ptlAngle.x = mnOrientationX; 782 aBundle.ptlAngle.y = mnOrientationY; 783 } 784 else 785 { 786 mnOrientationX = 1; 787 mnOrientationY = 0; 788 nAttrs |= CBB_ANGLE; 789 aBundle.ptlAngle.x = 1; 790 aBundle.ptlAngle.y = 0; 791 } 792 } 793 else 794 { 795 mnOrientationX = 1; 796 mnOrientationY = 0; 797 nAttrs |= CBB_ANGLE; 798 aBundle.ptlAngle.x = 1; 799 aBundle.ptlAngle.y = 0; 800 } 801 802 rc = Ft2SetAttrs( mhPS, PRIM_CHAR, nAttrs, nAttrsDefault, &aBundle ); 803 804 #if OSL_DEBUG_LEVEL>1 805 rc = Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); 806 if (pFontMetric->szFacename[0] == 'D') { 807 debug_printf( "Os2SalGraphics::SetFont Ft2QueryFontMetrics fattrs facename '%s'\n", aOS2Metric.szFacename); 808 debug_printf( "Os2SalGraphics::SetFont Ft2QueryFontMetrics fattrs height '%d'\n", aOS2Metric.lMaxBaselineExt); 809 debug_printf( "Os2SalGraphics::SetFont Ft2QueryFontMetrics fattrs width '%d'\n", aOS2Metric.lAveCharWidth); 810 } 811 #endif 812 813 return 0; 814 } 815 816 817 USHORT Os2SalGraphics::SetFont( ImplFontSelectData* pFont, int nFallbackLevel ) 818 { 819 820 // return early if there is no new font 821 if( !pFont ) 822 { 823 #if 0 824 // deselect still active font 825 if( mhDefFont ) 826 Ft2SetCharSet( mhPS, mhDefFont ); 827 // release no longer referenced font handles 828 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) 829 { 830 if( mhFonts[i] ) 831 Ft2DeleteSetId( mhPS, mhFonts[i] ); 832 mhFonts[ i ] = 0; 833 } 834 #endif 835 mhDefFont = 0; 836 return 0; 837 } 838 839 #if OSL_DEBUG_LEVEL>1 840 debug_printf( "Os2SalGraphics::SetFont\n"); 841 #endif 842 843 DBG_ASSERT( pFont->mpFontData, "WinSalGraphics mpFontData==NULL"); 844 mpOs2FontEntry[ nFallbackLevel ] = reinterpret_cast<ImplOs2FontEntry*>( pFont->mpFontEntry ); 845 mpOs2FontData[ nFallbackLevel ] = static_cast<const ImplOs2FontData*>( pFont->mpFontData ); 846 847 ImplDoSetFont( pFont, mfFontScale, nFallbackLevel); 848 849 if( !mhDefFont ) 850 { 851 // keep default font 852 mhDefFont = nFallbackLevel + LCID_BASE; 853 } 854 else 855 { 856 // release no longer referenced font handles 857 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) 858 { 859 if( mhFonts[i] ) 860 { 861 #if 0 862 Ft2DeleteSetId( mhPS, mhFonts[i] ); 863 #endif 864 mhFonts[i] = 0; 865 } 866 } 867 } 868 869 // store new font in correct layer 870 mhFonts[ nFallbackLevel ] = nFallbackLevel + LCID_BASE; 871 872 // now the font is live => update font face 873 if( mpOs2FontData[ nFallbackLevel ] ) 874 mpOs2FontData[ nFallbackLevel ]->UpdateFromHPS( mhPS ); 875 876 if( !nFallbackLevel ) 877 { 878 mbFontKernInit = TRUE; 879 if ( mpFontKernPairs ) 880 { 881 delete[] mpFontKernPairs; 882 mpFontKernPairs = NULL; 883 } 884 mnFontKernPairCount = 0; 885 } 886 887 // some printers have higher internal resolution, so their 888 // text output would be different from what we calculated 889 // => suggest DrawTextArray to workaround this problem 890 if ( mbPrinter ) 891 return SAL_SETFONT_USEDRAWTEXTARRAY; 892 else 893 return 0; 894 } 895 896 // ----------------------------------------------------------------------- 897 898 void Os2SalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel ) 899 { 900 FONTMETRICS aOS2Metric; 901 Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); 902 903 // @TODO sync , int nFallbackLevel in 340 904 905 #if OSL_DEBUG_LEVEL>1 906 debug_printf( "Os2SalGraphics::GetFontMetric hps %x\n", mhPS); 907 if (aOS2Metric.szFacename[0] == 'A') { 908 debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics facename '%s'\n", mhPS, aOS2Metric.szFacename); 909 debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics lMatch '%d'\n", mhPS, aOS2Metric.lMatch); 910 } 911 #endif 912 913 pMetric->maName = UniString( aOS2Metric.szFamilyname, gsl_getSystemTextEncoding()); 914 pMetric->maStyleName = ImpStyleNameToSal( aOS2Metric.szFamilyname, 915 aOS2Metric.szFacename, 916 strlen( aOS2Metric.szFamilyname ) ); 917 918 // device independent font attributes 919 pMetric->meFamily = ImplFamilyToSal( aOS2Metric.panose.bFamilyType); 920 pMetric->mbSymbolFlag = (aOS2Metric.usCodePage == SYMBOL_CHARSET); 921 pMetric->meWeight = ImplWeightToSal( aOS2Metric.usWeightClass ); 922 pMetric->mePitch = ImplLogPitchToSal( aOS2Metric.fsType ); 923 pMetric->meItalic = (aOS2Metric.fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE; 924 pMetric->mnSlant = 0; 925 926 // device dependend font attributes 927 pMetric->mbDevice = (aOS2Metric.fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE; 928 pMetric->mbScalableFont = (aOS2Metric.fsDefn & FM_DEFN_OUTLINE) ? true : false; 929 if( pMetric->mbScalableFont ) 930 { 931 // check if there are kern pairs 932 // TODO: does this work with GPOS kerning? 933 pMetric->mbKernableFont = (aOS2Metric.sKerningPairs > 0); 934 } 935 else 936 { 937 // bitmap fonts cannot be rotated directly 938 pMetric->mnOrientation = 0; 939 // bitmap fonts have no kerning 940 pMetric->mbKernableFont = false; 941 } 942 943 // transformation dependend font metrics 944 if ( aOS2Metric.fsDefn & FM_DEFN_OUTLINE ) 945 { 946 pMetric->mnWidth = aOS2Metric.lEmInc; 947 } 948 else 949 { 950 pMetric->mnWidth = aOS2Metric.lAveCharWidth; 951 pMetric->mnOrientation = 0; 952 } 953 pMetric->mnIntLeading = aOS2Metric.lInternalLeading; 954 pMetric->mnExtLeading = aOS2Metric.lExternalLeading; 955 pMetric->mnAscent = aOS2Metric.lMaxAscender; 956 pMetric->mnDescent = aOS2Metric.lMaxDescender; 957 958 // #107888# improved metric compatibility for Asian fonts... 959 // TODO: assess workaround below for CWS >= extleading 960 // TODO: evaluate use of aWinMetric.sTypo* members for CJK 961 if( mpOs2FontData[0] && mpOs2FontData[0]->SupportsCJK() ) 962 { 963 pMetric->mnIntLeading += pMetric->mnExtLeading; 964 965 // #109280# The line height for Asian fonts is too small. 966 // Therefore we add half of the external leading to the 967 // ascent, the other half is added to the descent. 968 const long nHalfTmpExtLeading = pMetric->mnExtLeading / 2; 969 const long nOtherHalfTmpExtLeading = pMetric->mnExtLeading - nHalfTmpExtLeading; 970 971 // #110641# external leading for Asian fonts. 972 // The factor 0.3 has been confirmed with experiments. 973 long nCJKExtLeading = static_cast<long>(0.30 * (pMetric->mnAscent + pMetric->mnDescent)); 974 nCJKExtLeading -= pMetric->mnExtLeading; 975 pMetric->mnExtLeading = (nCJKExtLeading > 0) ? nCJKExtLeading : 0; 976 977 pMetric->mnAscent += nHalfTmpExtLeading; 978 pMetric->mnDescent += nOtherHalfTmpExtLeading; 979 980 // #109280# HACK korean only: increase descent for wavelines and impr 981 // YD win9x only 982 } 983 984 } 985 986 // ----------------------------------------------------------------------- 987 988 ULONG Os2SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs ) 989 { 990 DBG_ASSERT( sizeof( KERNINGPAIRS ) == sizeof( ImplKernPairData ), 991 "Os2SalGraphics::GetKernPairs(): KERNINGPAIRS != ImplKernPairData" ); 992 993 if ( mbFontKernInit ) 994 { 995 if( mpFontKernPairs ) 996 { 997 delete[] mpFontKernPairs; 998 mpFontKernPairs = NULL; 999 } 1000 mnFontKernPairCount = 0; 1001 1002 { 1003 KERNINGPAIRS* pPairs = NULL; 1004 FONTMETRICS aOS2Metric; 1005 Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ); 1006 int nCount = aOS2Metric.sKerningPairs; 1007 if( nCount ) 1008 { 1009 #ifdef GCP_KERN_HACK 1010 pPairs = new KERNINGPAIRS[ nCount+1 ]; 1011 mpFontKernPairs = pPairs; 1012 mnFontKernPairCount = nCount; 1013 Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs ); 1014 #else // GCP_KERN_HACK 1015 pPairs = (KERNINGPAIRS*)pKernPairs; 1016 nCount = (nCount < nPairs) ? nCount : nPairs; 1017 Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs ); 1018 return nCount; 1019 #endif // GCP_KERN_HACK 1020 } 1021 } 1022 1023 mbFontKernInit = FALSE; 1024 1025 std::sort( mpFontKernPairs, mpFontKernPairs + mnFontKernPairCount, ImplCmpKernData ); 1026 } 1027 1028 if( !pKernPairs ) 1029 return mnFontKernPairCount; 1030 else if( mpFontKernPairs ) 1031 { 1032 if ( nPairs < mnFontKernPairCount ) 1033 nPairs = mnFontKernPairCount; 1034 memcpy( pKernPairs, mpFontKernPairs, 1035 nPairs*sizeof( ImplKernPairData ) ); 1036 return nPairs; 1037 } 1038 1039 return 0; 1040 } 1041 1042 1043 // ----------------------------------------------------------------------- 1044 1045 static const ImplFontCharMap* pOs2DefaultImplFontCharMap = NULL; 1046 static const sal_uInt32 pOs2DefaultRangeCodes[] = {0x0020,0x00FF}; 1047 1048 const ImplFontCharMap* Os2SalGraphics::GetImplFontCharMap() const 1049 { 1050 if( !mpOs2FontData[0] ) 1051 return ImplFontCharMap::GetDefaultMap(); 1052 return mpOs2FontData[0]->GetImplFontCharMap(); 1053 } 1054 1055 // ----------------------------------------------------------------------- 1056 1057 bool Os2SalGraphics::AddTempDevFont( ImplDevFontList* pFontList, 1058 const String& rFontFileURL, const String& rFontName ) 1059 { 1060 #if OSL_DEBUG_LEVEL>0 1061 debug_printf("Os2SalGraphics::AddTempDevFont\n"); 1062 #endif 1063 return false; 1064 } 1065 1066 // ----------------------------------------------------------------------- 1067 1068 void Os2SalGraphics::GetDevFontList( ImplDevFontList* pList ) 1069 { 1070 PFONTMETRICS pFontMetrics; 1071 ULONG nFontMetricCount; 1072 SalData* pSalData; 1073 1074 #if OSL_DEBUG_LEVEL>0 1075 debug_printf("Os2SalGraphics::GetDevFontList mbPrinter=%d\n", mbPrinter); 1076 #endif 1077 1078 // install OpenSymbol 1079 HMODULE hMod; 1080 ULONG ObjNum, Offset, rc; 1081 CHAR Buff[2*_MAX_PATH]; 1082 char drive[_MAX_DRIVE], dir[_MAX_DIR]; 1083 char fname[_MAX_FNAME], ext[_MAX_EXT]; 1084 // get module handle (and name) 1085 rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, 1086 &Offset, (ULONG)ImplSalGetUniString); 1087 DosQueryModuleName(hMod, sizeof(Buff), Buff); 1088 // replace module path with font path 1089 char* slash = strrchr( Buff, '\\'); 1090 *slash = '\0'; 1091 slash = strrchr( Buff, '\\'); 1092 *slash = '\0'; 1093 strcat( Buff, "\\FONTS\\OPENS___.TTF"); 1094 rc = GpiLoadPublicFonts( GetSalData()->mhAB, Buff); 1095 1096 if ( !mbPrinter ) 1097 { 1098 // Bei Bildschirm-Devices cachen wir die Liste global, da 1099 // dies im unabhaengigen Teil auch so gemacht wird und wir 1100 // ansonsten auf geloeschten Systemdaten arbeiten koennten 1101 pSalData = GetSalData(); 1102 nFontMetricCount = pSalData->mnFontMetricCount; 1103 pFontMetrics = pSalData->mpFontMetrics; 1104 // Bei Bildschirm-Devices holen wir uns die Fontliste jedesmal neu 1105 if ( pFontMetrics ) 1106 { 1107 delete pFontMetrics; 1108 pFontMetrics = NULL; 1109 nFontMetricCount = 0; 1110 } 1111 } 1112 else 1113 { 1114 nFontMetricCount = mnFontMetricCount; 1115 pFontMetrics = mpFontMetrics; 1116 } 1117 1118 // do we have to create the cached font list first? 1119 if ( !pFontMetrics ) 1120 { 1121 // query the number of fonts available 1122 LONG nTemp = 0; 1123 nFontMetricCount = Ft2QueryFonts( mhPS, 1124 QF_PUBLIC | QF_PRIVATE | QF_NO_DEVICE, 1125 NULL, &nTemp, 1126 sizeof( FONTMETRICS ), NULL ); 1127 1128 // procede only if at least one is available! 1129 if ( nFontMetricCount ) 1130 { 1131 // allocate memory for font list 1132 pFontMetrics = new FONTMETRICS[nFontMetricCount]; 1133 1134 // query font list 1135 Ft2QueryFonts( mhPS, 1136 QF_PUBLIC | QF_PRIVATE | QF_NO_DEVICE, 1137 NULL, 1138 (PLONG)&nFontMetricCount, 1139 (LONG) sizeof( FONTMETRICS ), 1140 pFontMetrics ); 1141 } 1142 1143 if ( !mbPrinter ) 1144 { 1145 pSalData->mnFontMetricCount = nFontMetricCount; 1146 pSalData->mpFontMetrics = pFontMetrics; 1147 } 1148 else 1149 { 1150 mnFontMetricCount = nFontMetricCount; 1151 mpFontMetrics = pFontMetrics; 1152 } 1153 } 1154 1155 // copy data from the font list 1156 for( ULONG i = 0; i < nFontMetricCount; i++ ) 1157 { 1158 PFONTMETRICS pFontMetric = &pFontMetrics[i]; 1159 1160 #if OSL_DEBUG_LEVEL>2 1161 debug_printf("Os2SalGraphics::GetDevFontList #%d,'%s'\n", i, pFontMetric->szFacename); 1162 #endif 1163 1164 // skip font starting with '@', this is an alias internally 1165 // used by truetype engine. 1166 if (pFontMetric->szFacename[0] == '@') 1167 continue; 1168 1169 // skip bitmap fonts (but keep WarpSans) 1170 if ( (pFontMetric->fsDefn & FM_DEFN_OUTLINE) == 0 1171 && strncmp( pFontMetric->szFacename, "WarpSans", 8) ) 1172 // Font nicht aufnehmen 1173 continue; 1174 1175 // replace '-' in facename with ' ' (for ft2lib) 1176 char* dash = pFontMetric->szFacename; 1177 while( (dash=strchr( dash, '-'))) 1178 *dash++ = ' '; 1179 1180 // create new font list element 1181 ImplOs2FontData* pData = new ImplOs2FontData( pFontMetric, 0, 0 ); 1182 1183 // ticket#80: font id field is used for pdf font cache code. 1184 pData->SetFontId( i); 1185 1186 // add font list element to font list 1187 pList->Add( pData ); 1188 1189 } 1190 } 1191 1192 // ---------------------------------------------------------------------------- 1193 1194 void Os2SalGraphics::GetDevFontSubstList( OutputDevice* pOutDev ) 1195 { 1196 } 1197 1198 // ----------------------------------------------------------------------- 1199 1200 sal_Bool Os2SalGraphics::GetGlyphBoundRect( long nIndex, Rectangle& rRect ) 1201 { 1202 // use unity matrix 1203 MAT2 aMat; 1204 aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 ); 1205 aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 ); 1206 1207 UINT nGGOFlags = GGO_METRICS; 1208 if( !(nIndex & GF_ISCHAR) ) 1209 nGGOFlags |= GGO_GLYPH_INDEX; 1210 nIndex &= GF_IDXMASK; 1211 1212 GLYPHMETRICS aGM; 1213 DWORD nSize = FT2_ERROR; 1214 nSize = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGM, 0, NULL, &aMat ); 1215 if( nSize == FT2_ERROR ) 1216 return false; 1217 1218 rRect = Rectangle( Point( +aGM.gmptGlyphOrigin.x, -aGM.gmptGlyphOrigin.y ), 1219 Size( aGM.gmBlackBoxX, aGM.gmBlackBoxY ) ); 1220 rRect.Left() = static_cast<int>( mfFontScale * rRect.Left() ); 1221 rRect.Right() = static_cast<int>( mfFontScale * rRect.Right() ); 1222 rRect.Top() = static_cast<int>( mfFontScale * rRect.Top() ); 1223 rRect.Bottom() = static_cast<int>( mfFontScale * rRect.Bottom() ); 1224 return true; 1225 } 1226 1227 // ----------------------------------------------------------------------- 1228 1229 sal_Bool Os2SalGraphics::GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& rB2DPolyPoly ) 1230 { 1231 #if OSL_DEBUG_LEVEL>0 1232 debug_printf("Os2SalGraphics::GetGlyphOutline\n"); 1233 #endif 1234 rB2DPolyPoly.clear(); 1235 1236 PM_BOOL bRet = FALSE; 1237 1238 // use unity matrix 1239 MAT2 aMat; 1240 aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 ); 1241 aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 ); 1242 1243 UINT nGGOFlags = GGO_NATIVE; 1244 if( !(nIndex & GF_ISCHAR) ) 1245 nGGOFlags |= GGO_GLYPH_INDEX; 1246 nIndex &= GF_IDXMASK; 1247 1248 GLYPHMETRICS aGlyphMetrics; 1249 DWORD nSize1 = FT2_ERROR; 1250 nSize1 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGlyphMetrics, 0, NULL, &aMat ); 1251 1252 if( !nSize1 ) // blank glyphs are ok 1253 bRet = TRUE; 1254 else if( nSize1 != FT2_ERROR ) 1255 { 1256 PM_BYTE* pData = new PM_BYTE[ nSize1 ]; 1257 ULONG nTotalCount = 0; 1258 DWORD nSize2; 1259 nSize2 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, 1260 &aGlyphMetrics, nSize1, pData, &aMat ); 1261 1262 if( nSize1 == nSize2 ) 1263 { 1264 bRet = TRUE; 1265 1266 int nPtSize = 512; 1267 Point* pPoints = new Point[ nPtSize ]; 1268 sal_uInt8* pFlags = new sal_uInt8[ nPtSize ]; 1269 1270 TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData; 1271 while( (PM_BYTE*)pHeader < pData+nSize2 ) 1272 { 1273 // only outline data is interesting 1274 if( pHeader->dwType != TT_POLYGON_TYPE ) 1275 break; 1276 1277 // get start point; next start points are end points 1278 // of previous segment 1279 int nPnt = 0; 1280 1281 long nX = IntTimes256FromFixed( pHeader->pfxStart.x ); 1282 long nY = IntTimes256FromFixed( pHeader->pfxStart.y ); 1283 pPoints[ nPnt ] = Point( nX, nY ); 1284 pFlags[ nPnt++ ] = POLY_NORMAL; 1285 1286 bool bHasOfflinePoints = false; 1287 TTPOLYCURVE* pCurve = (TTPOLYCURVE*)( pHeader + 1 ); 1288 pHeader = (TTPOLYGONHEADER*)( (PM_BYTE*)pHeader + pHeader->cb ); 1289 while( (PM_BYTE*)pCurve < (PM_BYTE*)pHeader ) 1290 { 1291 int nNeededSize = nPnt + 16 + 3 * pCurve->cpfx; 1292 if( nPtSize < nNeededSize ) 1293 { 1294 Point* pOldPoints = pPoints; 1295 sal_uInt8* pOldFlags = pFlags; 1296 nPtSize = 2 * nNeededSize; 1297 pPoints = new Point[ nPtSize ]; 1298 pFlags = new sal_uInt8[ nPtSize ]; 1299 for( int i = 0; i < nPnt; ++i ) 1300 { 1301 pPoints[ i ] = pOldPoints[ i ]; 1302 pFlags[ i ] = pOldFlags[ i ]; 1303 } 1304 delete[] pOldPoints; 1305 delete[] pOldFlags; 1306 } 1307 1308 int i = 0; 1309 if( TT_PRIM_LINE == pCurve->wType ) 1310 { 1311 while( i < pCurve->cpfx ) 1312 { 1313 nX = IntTimes256FromFixed( pCurve->apfx[ i ].x ); 1314 nY = IntTimes256FromFixed( pCurve->apfx[ i ].y ); 1315 ++i; 1316 pPoints[ nPnt ] = Point( nX, nY ); 1317 pFlags[ nPnt ] = POLY_NORMAL; 1318 ++nPnt; 1319 } 1320 } 1321 else if( TT_PRIM_QSPLINE == pCurve->wType ) 1322 { 1323 bHasOfflinePoints = true; 1324 while( i < pCurve->cpfx ) 1325 { 1326 // get control point of quadratic bezier spline 1327 nX = IntTimes256FromFixed( pCurve->apfx[ i ].x ); 1328 nY = IntTimes256FromFixed( pCurve->apfx[ i ].y ); 1329 ++i; 1330 Point aControlP( nX, nY ); 1331 1332 // calculate first cubic control point 1333 // P0 = 1/3 * (PBeg + 2 * PQControl) 1334 nX = pPoints[ nPnt-1 ].X() + 2 * aControlP.X(); 1335 nY = pPoints[ nPnt-1 ].Y() + 2 * aControlP.Y(); 1336 pPoints[ nPnt+0 ] = Point( (2*nX+3)/6, (2*nY+3)/6 ); 1337 pFlags[ nPnt+0 ] = POLY_CONTROL; 1338 1339 // calculate endpoint of segment 1340 nX = IntTimes256FromFixed( pCurve->apfx[ i ].x ); 1341 nY = IntTimes256FromFixed( pCurve->apfx[ i ].y ); 1342 1343 if ( i+1 >= pCurve->cpfx ) 1344 { 1345 // endpoint is either last point in segment => advance 1346 ++i; 1347 } 1348 else 1349 { 1350 // or endpoint is the middle of two control points 1351 nX += IntTimes256FromFixed( pCurve->apfx[ i-1 ].x ); 1352 nY += IntTimes256FromFixed( pCurve->apfx[ i-1 ].y ); 1353 nX = (nX + 1) / 2; 1354 nY = (nY + 1) / 2; 1355 // no need to advance, because the current point 1356 // is the control point in next bezier spline 1357 } 1358 1359 pPoints[ nPnt+2 ] = Point( nX, nY ); 1360 pFlags[ nPnt+2 ] = POLY_NORMAL; 1361 1362 // calculate second cubic control point 1363 // P1 = 1/3 * (PEnd + 2 * PQControl) 1364 nX = pPoints[ nPnt+2 ].X() + 2 * aControlP.X(); 1365 nY = pPoints[ nPnt+2 ].Y() + 2 * aControlP.Y(); 1366 pPoints[ nPnt+1 ] = Point( (2*nX+3)/6, (2*nY+3)/6 ); 1367 pFlags[ nPnt+1 ] = POLY_CONTROL; 1368 1369 nPnt += 3; 1370 } 1371 } 1372 1373 // next curve segment 1374 pCurve = (TTPOLYCURVE*)&pCurve->apfx[ i ]; 1375 } 1376 1377 // end point is start point for closed contour 1378 // disabled, because Polygon class closes the contour itself 1379 // pPoints[nPnt++] = pPoints[0]; 1380 // #i35928# 1381 // Added again, but add only when not yet closed 1382 if(pPoints[nPnt - 1] != pPoints[0]) 1383 { 1384 if( bHasOfflinePoints ) 1385 pFlags[nPnt] = pFlags[0]; 1386 1387 pPoints[nPnt++] = pPoints[0]; 1388 } 1389 1390 // convert y-coordinates W32 -> VCL 1391 for( int i = 0; i < nPnt; ++i ) 1392 pPoints[i].Y() = -pPoints[i].Y(); 1393 1394 // insert into polypolygon 1395 Polygon aPoly( nPnt, pPoints, (bHasOfflinePoints ? pFlags : NULL) ); 1396 // convert to B2DPolyPolygon 1397 // TODO: get rid of the intermediate PolyPolygon 1398 rB2DPolyPoly.append( aPoly.getB2DPolygon() ); 1399 } 1400 1401 delete[] pPoints; 1402 delete[] pFlags; 1403 } 1404 1405 delete[] pData; 1406 } 1407 1408 // rescaling needed for the PolyPolygon conversion 1409 if( rB2DPolyPoly.count() ) 1410 { 1411 ::basegfx::B2DHomMatrix aMatrix; 1412 aMatrix.scale( 1.0/256, 1.0/256 ); 1413 aMatrix.scale( mfFontScale, mfFontScale ); 1414 rB2DPolyPoly.transform( aMatrix ); 1415 } 1416 1417 return bRet; 1418 } 1419 1420 // ----------------------------------------------------------------------- 1421 1422 // TODO: Replace this class with boost::scoped_array 1423 class ScopedCharArray 1424 { 1425 public: 1426 inline explicit ScopedCharArray(char * pArray): m_pArray(pArray) {} 1427 1428 inline ~ScopedCharArray() { delete[] m_pArray; } 1429 1430 inline char * get() const { return m_pArray; } 1431 1432 private: 1433 char * m_pArray; 1434 }; 1435 1436 class ScopedFont 1437 { 1438 public: 1439 explicit ScopedFont(Os2SalGraphics & rData); 1440 1441 ~ScopedFont(); 1442 1443 private: 1444 Os2SalGraphics & m_rData; 1445 ULONG m_hOrigFont; 1446 }; 1447 1448 ScopedFont::ScopedFont(Os2SalGraphics & rData): m_rData(rData) 1449 { 1450 #if 0 1451 m_hOrigFont = m_rData.mhFonts[0]; 1452 m_rData.mhFonts[0] = 0; // avoid deletion of current font 1453 #endif 1454 } 1455 1456 ScopedFont::~ScopedFont() 1457 { 1458 #if 0 1459 if( m_hOrigFont ) 1460 { 1461 // restore original font, destroy temporary font 1462 HFONT hTempFont = m_rData.mhFonts[0]; 1463 m_rData.mhFonts[0] = m_hOrigFont; 1464 SelectObject( m_rData.mhDC, m_hOrigFont ); 1465 DeleteObject( hTempFont ); 1466 } 1467 #endif 1468 } 1469 1470 class ScopedTrueTypeFont 1471 { 1472 public: 1473 inline ScopedTrueTypeFont(): m_pFont(0) {} 1474 1475 ~ScopedTrueTypeFont(); 1476 1477 int open(void * pBuffer, sal_uInt32 nLen, sal_uInt32 nFaceNum); 1478 1479 inline TrueTypeFont * get() const { return m_pFont; } 1480 1481 private: 1482 TrueTypeFont * m_pFont; 1483 }; 1484 1485 ScopedTrueTypeFont::~ScopedTrueTypeFont() 1486 { 1487 if (m_pFont != 0) 1488 CloseTTFont(m_pFont); 1489 } 1490 1491 int ScopedTrueTypeFont::open(void * pBuffer, sal_uInt32 nLen, 1492 sal_uInt32 nFaceNum) 1493 { 1494 OSL_ENSURE(m_pFont == 0, "already open"); 1495 return OpenTTFontBuffer(pBuffer, nLen, nFaceNum, &m_pFont); 1496 } 1497 1498 sal_Bool Os2SalGraphics::CreateFontSubset( const rtl::OUString& rToFile, 1499 const ImplFontData* pFont, long* pGlyphIDs, sal_uInt8* pEncoding, 1500 sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo ) 1501 { 1502 // TODO: use more of the central font-subsetting code, move stuff there if needed 1503 1504 // create matching ImplFontSelectData 1505 // we need just enough to get to the font file data 1506 // use height=1000 for easier debugging (to match psprint's font units) 1507 ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false ); 1508 1509 // TODO: much better solution: move SetFont and restoration of old font to caller 1510 ScopedFont aOldFont(*this); 1511 SetFont( &aIFSD, 0 ); 1512 1513 ImplOs2FontData* pWinFontData = (ImplOs2FontData*)aIFSD.mpFontData; 1514 pWinFontData->UpdateFromHPS( mhPS ); 1515 const ImplFontCharMap* pImplFontCharMap = pWinFontData->GetImplFontCharMap(); 1516 1517 #if OSL_DEBUG_LEVEL > 100 1518 // get font metrics 1519 TEXTMETRICA aWinMetric; 1520 if( !::GetTextMetricsA( mhDC, &aWinMetric ) ) 1521 return FALSE; 1522 1523 DBG_ASSERT( !(aWinMetric.tmPitchAndFamily & TMPF_DEVICE), "cannot subset device font" ); 1524 DBG_ASSERT( aWinMetric.tmPitchAndFamily & TMPF_TRUETYPE, "can only subset TT font" ); 1525 #endif 1526 1527 rtl::OUString aSysPath; 1528 if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) ) 1529 return FALSE; 1530 const rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding(); 1531 const ByteString aToFile( aSysPath.getStr(), (xub_StrLen)aSysPath.getLength(), aThreadEncoding ); 1532 1533 // check if the font has a CFF-table 1534 const DWORD nCffTag = CalcTag( "CFF " ); 1535 const RawFontData aRawCffData( mhPS, nCffTag ); 1536 if( aRawCffData.get() ) 1537 { 1538 long nRealGlyphIds[ 256 ]; 1539 for( int i = 0; i < nGlyphCount; ++i ) 1540 { 1541 // TODO: remap notdef glyph if needed 1542 // TODO: use GDI's GetGlyphIndices instead? Does it handle GSUB properly? 1543 sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; 1544 if( pGlyphIDs[i] & GF_ISCHAR ) // remaining pseudo-glyphs need to be translated 1545 nGlyphIdx = pImplFontCharMap->GetGlyphIndex( nGlyphIdx ); 1546 if( (pGlyphIDs[i] & (GF_ROTMASK|GF_GSUB)) != 0) // TODO: vertical substitution 1547 {/*####*/} 1548 1549 nRealGlyphIds[i] = nGlyphIdx; 1550 } 1551 1552 // provide a font subset from the CFF-table 1553 FILE* pOutFile = fopen( aToFile.GetBuffer(), "wb" ); 1554 rInfo.LoadFont( FontSubsetInfo::CFF_FONT, aRawCffData.get(), aRawCffData.size() ); 1555 bool bRC = rInfo.CreateFontSubset( FontSubsetInfo::TYPE1_PFB, pOutFile, NULL, 1556 nRealGlyphIds, pEncoding, nGlyphCount, pGlyphWidths ); 1557 fclose( pOutFile ); 1558 return bRC; 1559 } 1560 1561 // get raw font file data 1562 const RawFontData xRawFontData( mhPS, NULL ); 1563 if( !xRawFontData.get() ) 1564 return FALSE; 1565 1566 // open font file 1567 sal_uInt32 nFaceNum = 0; 1568 if( !*xRawFontData.get() ) // TTC candidate 1569 nFaceNum = ~0U; // indicate "TTC font extracts only" 1570 1571 ScopedTrueTypeFont aSftTTF; 1572 int nRC = aSftTTF.open( (void*)xRawFontData.get(), xRawFontData.size(), nFaceNum ); 1573 if( nRC != SF_OK ) 1574 return FALSE; 1575 1576 TTGlobalFontInfo aTTInfo; 1577 ::GetTTGlobalFontInfo( aSftTTF.get(), &aTTInfo ); 1578 rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF; 1579 rInfo.m_aPSName = ImplSalGetUniString( aTTInfo.psname ); 1580 rInfo.m_nAscent = +aTTInfo.winAscent; 1581 rInfo.m_nDescent = -aTTInfo.winDescent; 1582 rInfo.m_aFontBBox = Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ), 1583 Point( aTTInfo.xMax, aTTInfo.yMax ) ); 1584 rInfo.m_nCapHeight = aTTInfo.yMax; // Well ... 1585 1586 // subset TTF-glyphs and get their properties 1587 // take care that subset fonts require the NotDef glyph in pos 0 1588 int nOrigCount = nGlyphCount; 1589 USHORT aShortIDs[ 256 ]; 1590 sal_uInt8 aTempEncs[ 256 ]; 1591 1592 int nNotDef=-1, i; 1593 for( i = 0; i < nGlyphCount; ++i ) 1594 { 1595 aTempEncs[i] = pEncoding[i]; 1596 sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK; 1597 if( pGlyphIDs[i] & GF_ISCHAR ) 1598 { 1599 sal_Unicode cChar = static_cast<sal_Unicode>(nGlyphIdx); // TODO: sal_UCS4 1600 const bool bVertical = ((pGlyphIDs[i] & (GF_ROTMASK|GF_GSUB)) != 0); 1601 nGlyphIdx = ::MapChar( aSftTTF.get(), cChar, bVertical ); 1602 if( (nGlyphIdx == 0) && pFont->IsSymbolFont() ) 1603 { 1604 // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX 1605 cChar = (cChar & 0xF000) ? (cChar & 0x00FF) : (cChar | 0xF000); 1606 nGlyphIdx = ::MapChar( aSftTTF.get(), cChar, bVertical ); 1607 } 1608 } 1609 aShortIDs[i] = static_cast<USHORT>( nGlyphIdx ); 1610 if( !nGlyphIdx ) 1611 if( nNotDef < 0 ) 1612 nNotDef = i; // first NotDef glyph found 1613 } 1614 1615 if( nNotDef != 0 ) 1616 { 1617 // add fake NotDef glyph if needed 1618 if( nNotDef < 0 ) 1619 nNotDef = nGlyphCount++; 1620 1621 // NotDef glyph must be in pos 0 => swap glyphids 1622 aShortIDs[ nNotDef ] = aShortIDs[0]; 1623 aTempEncs[ nNotDef ] = aTempEncs[0]; 1624 aShortIDs[0] = 0; 1625 aTempEncs[0] = 0; 1626 } 1627 DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" ); 1628 1629 // fill pWidth array 1630 TTSimpleGlyphMetrics* pMetrics = 1631 ::GetTTSimpleGlyphMetrics( aSftTTF.get(), aShortIDs, nGlyphCount, aIFSD.mbVertical ); 1632 if( !pMetrics ) 1633 return FALSE; 1634 sal_uInt16 nNotDefAdv = pMetrics[0].adv; 1635 pMetrics[0].adv = pMetrics[nNotDef].adv; 1636 pMetrics[nNotDef].adv = nNotDefAdv; 1637 for( i = 0; i < nOrigCount; ++i ) 1638 pGlyphWidths[i] = pMetrics[i].adv; 1639 free( pMetrics ); 1640 1641 // write subset into destination file 1642 nRC = ::CreateTTFromTTGlyphs( aSftTTF.get(), aToFile.GetBuffer(), aShortIDs, 1643 aTempEncs, nGlyphCount, 0, NULL, 0 ); 1644 return (nRC == SF_OK); 1645 } 1646 1647 //-------------------------------------------------------------------------- 1648 1649 const void* Os2SalGraphics::GetEmbedFontData( const ImplFontData* pFont, 1650 const sal_Ucs* pUnicodes, sal_Int32* pCharWidths, 1651 FontSubsetInfo& rInfo, long* pDataLen ) 1652 { 1653 // create matching ImplFontSelectData 1654 // we need just enough to get to the font file data 1655 ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false ); 1656 1657 // TODO: much better solution: move SetFont and restoration of old font to caller 1658 ScopedFont aOldFont(*this); 1659 SetFont( &aIFSD, 0 ); 1660 1661 // get the raw font file data 1662 RawFontData aRawFontData( mhPS ); 1663 *pDataLen = aRawFontData.size(); 1664 if( !aRawFontData.get() ) 1665 return NULL; 1666 1667 // get important font properties 1668 FONTMETRICS aOS2Metric; 1669 if (Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ) == GPI_ERROR) 1670 *pDataLen = 0; 1671 rInfo.m_nFontType = FontSubsetInfo::ANY_TYPE1; 1672 rInfo.m_aPSName = ImplSalGetUniString( aOS2Metric.szFacename ); 1673 rInfo.m_nAscent = +aOS2Metric.lMaxAscender; 1674 rInfo.m_nDescent = -aOS2Metric.lMaxDescender; 1675 rInfo.m_aFontBBox = Rectangle( Point( 0, -aOS2Metric.lMaxDescender ), 1676 Point( aOS2Metric.lMaxCharInc, aOS2Metric.lMaxAscender+aOS2Metric.lExternalLeading ) ); 1677 rInfo.m_nCapHeight = aOS2Metric.lMaxAscender; // Well ... 1678 1679 // get individual character widths 1680 for( int i = 0; i < 256; ++i ) 1681 { 1682 LONG nCharWidth = 0; 1683 const sal_Ucs cChar = pUnicodes[i]; 1684 if( !Ft2QueryStringWidthW( mhPS, (LPWSTR)&cChar, 1, &nCharWidth ) ) 1685 *pDataLen = 0; 1686 pCharWidths[i] = nCharWidth; 1687 } 1688 1689 if( !*pDataLen ) 1690 return NULL; 1691 1692 const unsigned char* pData = aRawFontData.steal(); 1693 return (void*)pData; 1694 } 1695 1696 //-------------------------------------------------------------------------- 1697 1698 void Os2SalGraphics::FreeEmbedFontData( const void* pData, long /*nLen*/ ) 1699 { 1700 delete[] reinterpret_cast<char*>(const_cast<void*>(pData)); 1701 } 1702 1703 const Ucs2SIntMap* Os2SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded ) 1704 { 1705 // TODO: even for builtin fonts we get here... why? 1706 if( !pFont->IsEmbeddable() ) 1707 return NULL; 1708 1709 // fill the encoding vector 1710 // currently no nonencoded vector 1711 if( pNonEncoded ) 1712 *pNonEncoded = NULL; 1713 1714 const ImplOs2FontData* pWinFontData = static_cast<const ImplOs2FontData*>(pFont); 1715 const Ucs2SIntMap* pEncoding = pWinFontData->GetEncodingVector(); 1716 if( pEncoding == NULL ) 1717 { 1718 Ucs2SIntMap* pNewEncoding = new Ucs2SIntMap; 1719 #if 0 1720 // TODO: get correct encoding vector 1721 GLYPHSET aGlyphSet; 1722 aGlyphSet.cbThis = sizeof(aGlyphSet); 1723 DWORD aW = ::GetFontUnicodeRanges( mhPS, &aGlyphSet); 1724 #else 1725 for( sal_Unicode i = 32; i < 256; ++i ) 1726 (*pNewEncoding)[i] = i; 1727 #endif 1728 pWinFontData->SetEncodingVector( pNewEncoding ); 1729 pEncoding = pNewEncoding; 1730 } 1731 1732 return pEncoding; 1733 } 1734 1735 //-------------------------------------------------------------------------- 1736 1737 void Os2SalGraphics::GetGlyphWidths( const ImplFontData* pFont, 1738 bool bVertical, 1739 Int32Vector& rWidths, 1740 Ucs2UIntMap& rUnicodeEnc ) 1741 { 1742 // create matching ImplFontSelectData 1743 // we need just enough to get to the font file data 1744 ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false ); 1745 1746 // TODO: much better solution: move SetFont and restoration of old font to caller 1747 ScopedFont aOldFont(*this); 1748 1749 float fScale = 0.0; 1750 ImplDoSetFont( &aIFSD, fScale, 0); 1751 1752 if( pFont->IsSubsettable() ) 1753 { 1754 // get raw font file data 1755 const RawFontData xRawFontData( mhPS ); 1756 if( !xRawFontData.get() ) 1757 return; 1758 1759 // open font file 1760 sal_uInt32 nFaceNum = 0; 1761 if( !*xRawFontData.get() ) // TTC candidate 1762 nFaceNum = ~0U; // indicate "TTC font extracts only" 1763 1764 ScopedTrueTypeFont aSftTTF; 1765 int nRC = aSftTTF.open( (void*)xRawFontData.get(), xRawFontData.size(), nFaceNum ); 1766 if( nRC != SF_OK ) 1767 return; 1768 1769 int nGlyphs = GetTTGlyphCount( aSftTTF.get() ); 1770 if( nGlyphs > 0 ) 1771 { 1772 rWidths.resize(nGlyphs); 1773 std::vector<sal_uInt16> aGlyphIds(nGlyphs); 1774 for( int i = 0; i < nGlyphs; i++ ) 1775 aGlyphIds[i] = sal_uInt16(i); 1776 TTSimpleGlyphMetrics* pMetrics = ::GetTTSimpleGlyphMetrics( aSftTTF.get(), 1777 &aGlyphIds[0], 1778 nGlyphs, 1779 bVertical ? 1 : 0 ); 1780 if( pMetrics ) 1781 { 1782 for( int i = 0; i< nGlyphs; i++ ) 1783 rWidths[i] = pMetrics[i].adv; 1784 free( pMetrics ); 1785 rUnicodeEnc.clear(); 1786 } 1787 const ImplOs2FontData* pWinFont = static_cast<const ImplOs2FontData*>(pFont); 1788 const ImplFontCharMap* pMap = pWinFont->GetImplFontCharMap(); 1789 DBG_ASSERT( pMap && pMap->GetCharCount(), "no map" ); 1790 1791 int nCharCount = pMap->GetCharCount(); 1792 sal_uInt32 nChar = pMap->GetFirstChar(); 1793 for( int i = 0; i < nCharCount; i++ ) 1794 { 1795 if( nChar < 0x00010000 ) 1796 { 1797 sal_uInt16 nGlyph = ::MapChar( aSftTTF.get(), 1798 static_cast<sal_uInt16>(nChar), 1799 bVertical ? 1 : 0 ); 1800 if( nGlyph ) 1801 rUnicodeEnc[ static_cast<sal_Unicode>(nChar) ] = nGlyph; 1802 } 1803 nChar = pMap->GetNextChar( nChar ); 1804 } 1805 } 1806 } 1807 else if( pFont->IsEmbeddable() ) 1808 { 1809 // get individual character widths 1810 rWidths.clear(); 1811 rUnicodeEnc.clear(); 1812 rWidths.reserve( 224 ); 1813 for( sal_Unicode i = 32; i < 256; ++i ) 1814 { 1815 int nCharWidth = 0; 1816 if( Ft2QueryStringWidthW( mhPS, (LPWSTR)&i, 1, (LONG*)&nCharWidth ) ) 1817 { 1818 rUnicodeEnc[ i ] = rWidths.size(); 1819 rWidths.push_back( nCharWidth ); 1820 } 1821 } 1822 } 1823 } 1824 1825 //-------------------------------------------------------------------------- 1826 1827 void Os2SalGraphics::DrawServerFontLayout( const ServerFontLayout& ) 1828 {} 1829 1830 //-------------------------------------------------------------------------- 1831 1832 SystemFontData Os2SalGraphics::GetSysFontData( int nFallbacklevel ) const 1833 { 1834 SystemFontData aSysFontData; 1835 1836 if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1; 1837 if (nFallbacklevel < 0 ) nFallbacklevel = 0; 1838 1839 aSysFontData.nSize = sizeof( SystemFontData ); 1840 aSysFontData.hFont = mhFonts[nFallbacklevel]; 1841 aSysFontData.bFakeBold = false; 1842 aSysFontData.bFakeItalic = false; 1843 aSysFontData.bAntialias = true; 1844 aSysFontData.bVerticalCharacterType = false; 1845 1846 return aSysFontData; 1847 } 1848 1849 //-------------------------------------------------------------------------- 1850