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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include "unotools/fontcfg.hxx" 28 29 #include "tools/stream.hxx" 30 #include "tools/vcompat.hxx" 31 #include "tools/debug.hxx" 32 33 #include "vcl/font.hxx" 34 35 #include "impfont.hxx" 36 #include "outfont.hxx" 37 #include "sft.hxx" 38 39 40 #include <algorithm> 41 42 using namespace vcl; 43 44 // ======================================================================= 45 46 DBG_NAME( Font ) 47 48 // ----------------------------------------------------------------------- 49 50 Impl_Font::Impl_Font() : 51 maColor( COL_TRANSPARENT ), 52 maFillColor( COL_TRANSPARENT ) 53 { 54 mnRefCount = 1; 55 meCharSet = RTL_TEXTENCODING_DONTKNOW; 56 meLanguage = LANGUAGE_DONTKNOW; 57 meCJKLanguage = LANGUAGE_DONTKNOW; 58 meFamily = FAMILY_DONTKNOW; 59 mePitch = PITCH_DONTKNOW; 60 meAlign = ALIGN_TOP; 61 meWeight = WEIGHT_DONTKNOW; 62 meWidthType = WIDTH_DONTKNOW; 63 meItalic = ITALIC_NONE; 64 meUnderline = UNDERLINE_NONE; 65 meOverline = UNDERLINE_NONE; 66 meStrikeout = STRIKEOUT_NONE; 67 meRelief = RELIEF_NONE; 68 meEmphasisMark = EMPHASISMARK_NONE; 69 mnOrientation = 0; 70 mnKerning = 0; 71 mbWordLine = false; 72 mbOutline = false; 73 mbShadow = false; 74 mbVertical = false; 75 mbTransparent = true; 76 mbConfigLookup = false; 77 } 78 79 // ----------------------------------------------------------------------- 80 81 Impl_Font::Impl_Font( const Impl_Font& rImplFont ) 82 : maFamilyName( rImplFont.maFamilyName ), 83 maStyleName( rImplFont.maStyleName ), 84 maSize( rImplFont.maSize ), 85 maColor( rImplFont.maColor ), 86 maFillColor( rImplFont.maFillColor ) 87 { 88 mnRefCount = 1; 89 meCharSet = rImplFont.meCharSet; 90 meLanguage = rImplFont.meLanguage; 91 meCJKLanguage = rImplFont.meCJKLanguage; 92 meFamily = rImplFont.meFamily; 93 mePitch = rImplFont.mePitch; 94 meAlign = rImplFont.meAlign; 95 meWeight = rImplFont.meWeight; 96 meWidthType = rImplFont.meWidthType; 97 meItalic = rImplFont.meItalic; 98 meUnderline = rImplFont.meUnderline; 99 meOverline = rImplFont.meOverline; 100 meStrikeout = rImplFont.meStrikeout; 101 meRelief = rImplFont.meRelief; 102 meEmphasisMark = rImplFont.meEmphasisMark; 103 mnOrientation = rImplFont.mnOrientation; 104 mnKerning = rImplFont.mnKerning; 105 mbWordLine = rImplFont.mbWordLine; 106 mbOutline = rImplFont.mbOutline; 107 mbShadow = rImplFont.mbShadow; 108 mbVertical = rImplFont.mbVertical; 109 mbTransparent = rImplFont.mbTransparent; 110 mbConfigLookup = rImplFont.mbConfigLookup; 111 } 112 113 // ----------------------------------------------------------------------- 114 115 bool Impl_Font::operator==( const Impl_Font& rOther ) const 116 { 117 // equality tests split up for easier debugging 118 if( (meWeight != rOther.meWeight) 119 || (meItalic != rOther.meItalic) 120 || (meFamily != rOther.meFamily) 121 || (mePitch != rOther.mePitch) ) 122 return false; 123 124 if( (meCharSet != rOther.meCharSet) 125 || (meLanguage != rOther.meLanguage) 126 || (meCJKLanguage != rOther.meCJKLanguage) 127 || (meAlign != rOther.meAlign) ) 128 return false; 129 130 if( (maSize != rOther.maSize) 131 || (mnOrientation != rOther.mnOrientation) 132 || (mbVertical != rOther.mbVertical) ) 133 return false; 134 135 if( (maFamilyName != rOther.maFamilyName) 136 || (maStyleName != rOther.maStyleName) ) 137 return false; 138 139 if( (maColor != rOther.maColor) 140 || (maFillColor != rOther.maFillColor) ) 141 return false; 142 143 if( (meUnderline != rOther.meUnderline) 144 || (meOverline != rOther.meOverline) 145 || (meStrikeout != rOther.meStrikeout) 146 || (meRelief != rOther.meRelief) 147 || (meEmphasisMark != rOther.meEmphasisMark) 148 || (mbWordLine != rOther.mbWordLine) 149 || (mbOutline != rOther.mbOutline) 150 || (mbShadow != rOther.mbShadow) 151 || (mnKerning != rOther.mnKerning) 152 || (mbTransparent != rOther.mbTransparent) ) 153 return false; 154 155 return true; 156 } 157 158 // ----------------------------------------------------------------------- 159 160 void Impl_Font::AskConfig() 161 { 162 if( mbConfigLookup ) 163 return; 164 165 mbConfigLookup = true; 166 167 // prepare the FontSubst configuration lookup 168 const utl::FontSubstConfiguration* pFontSubst = utl::FontSubstConfiguration::get(); 169 170 String aShortName; 171 String aFamilyName; 172 sal_uLong nType = 0; 173 FontWeight eWeight = WEIGHT_DONTKNOW; 174 FontWidth eWidthType = WIDTH_DONTKNOW; 175 String aMapName = maFamilyName; 176 GetEnglishSearchFontName( aMapName ); 177 utl::FontSubstConfiguration::getMapName( aMapName, 178 aShortName, aFamilyName, eWeight, eWidthType, nType ); 179 180 // lookup the font name in the configuration 181 const utl::FontNameAttr* pFontAttr = pFontSubst->getSubstInfo( aMapName ); 182 183 // if the direct lookup failed try again with an alias name 184 if ( !pFontAttr && (aShortName != aMapName) ) 185 pFontAttr = pFontSubst->getSubstInfo( aShortName ); 186 187 if( pFontAttr ) 188 { 189 // the font was found in the configuration 190 if( meFamily == FAMILY_DONTKNOW ) 191 { 192 if ( pFontAttr->Type & IMPL_FONT_ATTR_SERIF ) 193 meFamily = FAMILY_ROMAN; 194 else if ( pFontAttr->Type & IMPL_FONT_ATTR_SANSSERIF ) 195 meFamily = FAMILY_SWISS; 196 else if ( pFontAttr->Type & IMPL_FONT_ATTR_TYPEWRITER ) 197 meFamily = FAMILY_MODERN; 198 else if ( pFontAttr->Type & IMPL_FONT_ATTR_ITALIC ) 199 meFamily = FAMILY_SCRIPT; 200 else if ( pFontAttr->Type & IMPL_FONT_ATTR_DECORATIVE ) 201 meFamily = FAMILY_DECORATIVE; 202 } 203 204 if( mePitch == PITCH_DONTKNOW ) 205 { 206 if ( pFontAttr->Type & IMPL_FONT_ATTR_FIXED ) 207 mePitch = PITCH_FIXED; 208 } 209 } 210 211 // if some attributes are still unknown then use the FontSubst magic 212 if( meFamily == FAMILY_DONTKNOW ) 213 { 214 if( nType & IMPL_FONT_ATTR_SERIF ) 215 meFamily = FAMILY_ROMAN; 216 else if( nType & IMPL_FONT_ATTR_SANSSERIF ) 217 meFamily = FAMILY_SWISS; 218 else if( nType & IMPL_FONT_ATTR_TYPEWRITER ) 219 meFamily = FAMILY_MODERN; 220 else if( nType & IMPL_FONT_ATTR_ITALIC ) 221 meFamily = FAMILY_SCRIPT; 222 else if( nType & IMPL_FONT_ATTR_DECORATIVE ) 223 meFamily = FAMILY_DECORATIVE; 224 } 225 226 if( meWeight == WEIGHT_DONTKNOW ) 227 meWeight = eWeight; 228 if( meWidthType == WIDTH_DONTKNOW ) 229 meWidthType = eWidthType; 230 } 231 232 // ======================================================================= 233 234 void Font::MakeUnique() 235 { 236 // create a copy if others still reference it 237 if ( mpImplFont->mnRefCount != 1 ) 238 { 239 if ( mpImplFont->mnRefCount ) 240 mpImplFont->mnRefCount--; 241 mpImplFont = new Impl_Font( *mpImplFont ); 242 } 243 } 244 245 // ----------------------------------------------------------------------- 246 247 Font::Font() 248 { 249 DBG_CTOR( Font, NULL ); 250 251 static Impl_Font aStaticImplFont; 252 // RefCount is zero for static objects 253 aStaticImplFont.mnRefCount = 0; 254 mpImplFont = &aStaticImplFont; 255 } 256 257 // ----------------------------------------------------------------------- 258 259 Font::Font( const Font& rFont ) 260 { 261 DBG_CTOR( Font, NULL ); 262 DBG_CHKOBJ( &rFont, Font, NULL ); 263 DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" ); 264 265 mpImplFont = rFont.mpImplFont; 266 // do not count static objects (where RefCount is zero) 267 if ( mpImplFont->mnRefCount ) 268 mpImplFont->mnRefCount++; 269 } 270 271 // ----------------------------------------------------------------------- 272 273 Font::Font( const String& rFamilyName, const Size& rSize ) 274 { 275 DBG_CTOR( Font, NULL ); 276 277 mpImplFont = new Impl_Font; 278 mpImplFont->maFamilyName= rFamilyName; 279 mpImplFont->maSize = rSize; 280 } 281 282 // ----------------------------------------------------------------------- 283 284 Font::Font( const String& rFamilyName, const String& rStyleName, const Size& rSize ) 285 { 286 DBG_CTOR( Font, NULL ); 287 288 mpImplFont = new Impl_Font; 289 mpImplFont->maFamilyName= rFamilyName; 290 mpImplFont->maStyleName = rStyleName; 291 mpImplFont->maSize = rSize; 292 } 293 294 // ----------------------------------------------------------------------- 295 296 Font::Font( FontFamily eFamily, const Size& rSize ) 297 { 298 DBG_CTOR( Font, NULL ); 299 300 mpImplFont = new Impl_Font; 301 mpImplFont->meFamily = eFamily; 302 mpImplFont->maSize = rSize; 303 } 304 305 // ----------------------------------------------------------------------- 306 307 Font::~Font() 308 { 309 DBG_DTOR( Font, NULL ); 310 311 // decrement reference counter and delete if last reference 312 // if the object is not static (Refcounter==0) 313 if ( mpImplFont->mnRefCount ) 314 { 315 if ( mpImplFont->mnRefCount == 1 ) 316 delete mpImplFont; 317 else 318 mpImplFont->mnRefCount--; 319 } 320 } 321 322 // ----------------------------------------------------------------------- 323 324 void Font::SetColor( const Color& rColor ) 325 { 326 DBG_CHKTHIS( Font, NULL ); 327 328 if( mpImplFont->maColor != rColor ) 329 { 330 MakeUnique(); 331 mpImplFont->maColor = rColor; 332 } 333 } 334 335 // ----------------------------------------------------------------------- 336 337 void Font::SetFillColor( const Color& rColor ) 338 { 339 DBG_CHKTHIS( Font, NULL ); 340 341 MakeUnique(); 342 mpImplFont->maFillColor = rColor; 343 if ( rColor.GetTransparency() ) 344 mpImplFont->mbTransparent = true; 345 } 346 347 // ----------------------------------------------------------------------- 348 349 void Font::SetTransparent( sal_Bool bTransparent ) 350 { 351 DBG_CHKTHIS( Font, NULL ); 352 353 if( mpImplFont->mbTransparent != bTransparent ) 354 { 355 MakeUnique(); 356 mpImplFont->mbTransparent = bTransparent; 357 } 358 } 359 360 // ----------------------------------------------------------------------- 361 362 void Font::SetAlign( FontAlign eAlign ) 363 { 364 DBG_CHKTHIS( Font, NULL ); 365 366 if( mpImplFont->meAlign != eAlign ) 367 { 368 MakeUnique(); 369 mpImplFont->meAlign = eAlign; 370 } 371 } 372 373 // ----------------------------------------------------------------------- 374 375 void Font::SetName( const String& rFamilyName ) 376 { 377 DBG_CHKTHIS( Font, NULL ); 378 379 MakeUnique(); 380 mpImplFont->maFamilyName = rFamilyName; 381 } 382 383 // ----------------------------------------------------------------------- 384 385 void Font::SetStyleName( const String& rStyleName ) 386 { 387 DBG_CHKTHIS( Font, NULL ); 388 389 MakeUnique(); 390 mpImplFont->maStyleName = rStyleName; 391 } 392 393 // ----------------------------------------------------------------------- 394 395 void Font::SetSize( const Size& rSize ) 396 { 397 DBG_CHKTHIS( Font, NULL ); 398 399 if( mpImplFont->maSize != rSize ) 400 { 401 MakeUnique(); 402 mpImplFont->maSize = rSize; 403 } 404 } 405 406 // ----------------------------------------------------------------------- 407 408 void Font::SetFamily( FontFamily eFamily ) 409 { 410 DBG_CHKTHIS( Font, NULL ); 411 412 if( mpImplFont->meFamily != eFamily ) 413 { 414 MakeUnique(); 415 mpImplFont->meFamily = eFamily; 416 } 417 } 418 419 // ----------------------------------------------------------------------- 420 421 void Font::SetCharSet( CharSet eCharSet ) 422 { 423 DBG_CHKTHIS( Font, NULL ); 424 425 if( mpImplFont->meCharSet != eCharSet ) 426 { 427 MakeUnique(); 428 mpImplFont->meCharSet = eCharSet; 429 } 430 } 431 432 // ----------------------------------------------------------------------- 433 434 void Font::SetLanguage( LanguageType eLanguage ) 435 { 436 DBG_CHKTHIS( Font, NULL ); 437 438 if( mpImplFont->meLanguage != eLanguage ) 439 { 440 MakeUnique(); 441 mpImplFont->meLanguage = eLanguage; 442 } 443 } 444 445 // ----------------------------------------------------------------------- 446 447 void Font::SetCJKContextLanguage( LanguageType eLanguage ) 448 { 449 DBG_CHKTHIS( Font, NULL ); 450 451 if( mpImplFont->meCJKLanguage != eLanguage ) 452 { 453 MakeUnique(); 454 mpImplFont->meCJKLanguage = eLanguage; 455 } 456 } 457 458 // ----------------------------------------------------------------------- 459 460 void Font::SetPitch( FontPitch ePitch ) 461 { 462 DBG_CHKTHIS( Font, NULL ); 463 464 if( mpImplFont->mePitch != ePitch ) 465 { 466 MakeUnique(); 467 mpImplFont->mePitch = ePitch; 468 } 469 } 470 471 // ----------------------------------------------------------------------- 472 473 void Font::SetOrientation( short nOrientation ) 474 { 475 DBG_CHKTHIS( Font, NULL ); 476 477 if( mpImplFont->mnOrientation != nOrientation ) 478 { 479 MakeUnique(); 480 mpImplFont->mnOrientation = nOrientation; 481 } 482 } 483 484 // ----------------------------------------------------------------------- 485 486 void Font::SetVertical( sal_Bool bVertical ) 487 { 488 DBG_CHKTHIS( Font, NULL ); 489 490 if( mpImplFont->mbVertical != bVertical ) 491 { 492 MakeUnique(); 493 mpImplFont->mbVertical = bVertical; 494 } 495 } 496 497 // ----------------------------------------------------------------------- 498 499 void Font::SetKerning( FontKerning nKerning ) 500 { 501 DBG_CHKTHIS( Font, NULL ); 502 503 if( mpImplFont->mnKerning != nKerning ) 504 { 505 MakeUnique(); 506 mpImplFont->mnKerning = nKerning; 507 } 508 } 509 510 // ----------------------------------------------------------------------- 511 512 sal_Bool Font::IsKerning() const 513 { 514 return (mpImplFont->mnKerning & KERNING_FONTSPECIFIC) != 0; 515 } 516 517 // ----------------------------------------------------------------------- 518 519 void Font::SetWeight( FontWeight eWeight ) 520 { 521 DBG_CHKTHIS( Font, NULL ); 522 523 if( mpImplFont->meWeight != eWeight ) 524 { 525 MakeUnique(); 526 mpImplFont->meWeight = eWeight; 527 } 528 } 529 530 // ----------------------------------------------------------------------- 531 532 void Font::SetWidthType( FontWidth eWidth ) 533 { 534 DBG_CHKTHIS( Font, NULL ); 535 536 if( mpImplFont->meWidthType != eWidth ) 537 { 538 MakeUnique(); 539 mpImplFont->meWidthType = eWidth; 540 } 541 } 542 543 // ----------------------------------------------------------------------- 544 545 void Font::SetItalic( FontItalic eItalic ) 546 { 547 DBG_CHKTHIS( Font, NULL ); 548 549 if( mpImplFont->meItalic != eItalic ) 550 { 551 MakeUnique(); 552 mpImplFont->meItalic = eItalic; 553 } 554 } 555 556 // ----------------------------------------------------------------------- 557 558 void Font::SetOutline( sal_Bool bOutline ) 559 { 560 DBG_CHKTHIS( Font, NULL ); 561 562 if( mpImplFont->mbOutline != bOutline ) 563 { 564 MakeUnique(); 565 mpImplFont->mbOutline = bOutline; 566 } 567 } 568 569 // ----------------------------------------------------------------------- 570 571 void Font::SetShadow( sal_Bool bShadow ) 572 { 573 DBG_CHKTHIS( Font, NULL ); 574 575 if( mpImplFont->mbShadow != bShadow ) 576 { 577 MakeUnique(); 578 mpImplFont->mbShadow = bShadow; 579 } 580 } 581 582 // ----------------------------------------------------------------------- 583 584 void Font::SetUnderline( FontUnderline eUnderline ) 585 { 586 DBG_CHKTHIS( Font, NULL ); 587 588 if( mpImplFont->meUnderline != eUnderline ) 589 { 590 MakeUnique(); 591 mpImplFont->meUnderline = eUnderline; 592 } 593 } 594 595 // ----------------------------------------------------------------------- 596 597 void Font::SetOverline( FontUnderline eOverline ) 598 { 599 DBG_CHKTHIS( Font, NULL ); 600 601 if( mpImplFont->meOverline != eOverline ) 602 { 603 MakeUnique(); 604 mpImplFont->meOverline = eOverline; 605 } 606 } 607 608 // ----------------------------------------------------------------------- 609 610 void Font::SetStrikeout( FontStrikeout eStrikeout ) 611 { 612 DBG_CHKTHIS( Font, NULL ); 613 614 if( mpImplFont->meStrikeout != eStrikeout ) 615 { 616 MakeUnique(); 617 mpImplFont->meStrikeout = eStrikeout; 618 } 619 } 620 621 // ----------------------------------------------------------------------- 622 623 void Font::SetRelief( FontRelief eRelief ) 624 { 625 DBG_CHKTHIS( Font, NULL ); 626 627 if( mpImplFont->meRelief != eRelief ) 628 { 629 MakeUnique(); 630 mpImplFont->meRelief = eRelief; 631 } 632 } 633 634 // ----------------------------------------------------------------------- 635 636 void Font::SetEmphasisMark( FontEmphasisMark eEmphasisMark ) 637 { 638 DBG_CHKTHIS( Font, NULL ); 639 640 if( mpImplFont->meEmphasisMark != eEmphasisMark ) 641 { 642 MakeUnique(); 643 mpImplFont->meEmphasisMark = eEmphasisMark; 644 } 645 } 646 647 // ----------------------------------------------------------------------- 648 649 void Font::SetWordLineMode( sal_Bool bWordLine ) 650 { 651 DBG_CHKTHIS( Font, NULL ); 652 653 if( mpImplFont->mbWordLine != bWordLine ) 654 { 655 MakeUnique(); 656 mpImplFont->mbWordLine = bWordLine; 657 } 658 } 659 660 // ----------------------------------------------------------------------- 661 662 Font& Font::operator=( const Font& rFont ) 663 { 664 DBG_CHKTHIS( Font, NULL ); 665 DBG_CHKOBJ( &rFont, Font, NULL ); 666 DBG_ASSERT( rFont.mpImplFont->mnRefCount < 0xFFFE, "Font: RefCount overflow" ); 667 668 // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann 669 // RefCount == 0 fuer statische Objekte 670 if ( rFont.mpImplFont->mnRefCount ) 671 rFont.mpImplFont->mnRefCount++; 672 673 // Wenn es keine statischen ImplDaten sind, dann loeschen, wenn es 674 // die letzte Referenz ist, sonst Referenzcounter decrementieren 675 if ( mpImplFont->mnRefCount ) 676 { 677 if ( mpImplFont->mnRefCount == 1 ) 678 delete mpImplFont; 679 else 680 mpImplFont->mnRefCount--; 681 } 682 683 mpImplFont = rFont.mpImplFont; 684 685 return *this; 686 } 687 688 // ----------------------------------------------------------------------- 689 690 sal_Bool Font::operator==( const Font& rFont ) const 691 { 692 DBG_CHKTHIS( Font, NULL ); 693 DBG_CHKOBJ( &rFont, Font, NULL ); 694 695 if( mpImplFont == rFont.mpImplFont ) 696 return sal_True; 697 if( *mpImplFont == *rFont.mpImplFont ) 698 return sal_True; 699 700 return sal_False; 701 } 702 703 // ----------------------------------------------------------------------- 704 705 void Font::Merge( const Font& rFont ) 706 { 707 if ( rFont.GetName().Len() ) 708 { 709 SetName( rFont.GetName() ); 710 SetStyleName( rFont.GetStyleName() ); 711 SetCharSet( GetCharSet() ); 712 SetLanguage( rFont.GetLanguage() ); 713 SetCJKContextLanguage( rFont.GetCJKContextLanguage() ); 714 // don't use access methods here, might lead to AskConfig(), if DONTKNOW 715 SetFamily( rFont.mpImplFont->meFamily ); 716 SetPitch( rFont.mpImplFont->mePitch ); 717 } 718 719 // don't use access methods here, might lead to AskConfig(), if DONTKNOW 720 if ( rFont.mpImplFont->meWeight != WEIGHT_DONTKNOW ) 721 SetWeight( rFont.GetWeight() ); 722 if ( rFont.mpImplFont->meItalic != ITALIC_DONTKNOW ) 723 SetItalic( rFont.GetItalic() ); 724 if ( rFont.mpImplFont->meWidthType != WIDTH_DONTKNOW ) 725 SetWidthType( rFont.GetWidthType() ); 726 727 728 if ( rFont.GetSize().Height() ) 729 SetSize( rFont.GetSize() ); 730 if ( rFont.GetUnderline() != UNDERLINE_DONTKNOW ) 731 { 732 SetUnderline( rFont.GetUnderline() ); 733 SetWordLineMode( rFont.IsWordLineMode() ); 734 } 735 if ( rFont.GetOverline() != UNDERLINE_DONTKNOW ) 736 { 737 SetOverline( rFont.GetOverline() ); 738 SetWordLineMode( rFont.IsWordLineMode() ); 739 } 740 if ( rFont.GetStrikeout() != STRIKEOUT_DONTKNOW ) 741 { 742 SetStrikeout( rFont.GetStrikeout() ); 743 SetWordLineMode( rFont.IsWordLineMode() ); 744 } 745 746 // Defaults? 747 SetOrientation( rFont.GetOrientation() ); 748 SetVertical( rFont.IsVertical() ); 749 SetEmphasisMark( rFont.GetEmphasisMark() ); 750 SetKerning( rFont.IsKerning() ); 751 SetOutline( rFont.IsOutline() ); 752 SetShadow( rFont.IsShadow() ); 753 SetRelief( rFont.GetRelief() ); 754 } 755 756 void Font::GetFontAttributes( ImplFontAttributes& rAttrs ) const 757 { 758 // #i56788# Use members directly, don't risc config access. 759 rAttrs.maName = mpImplFont->maFamilyName; 760 rAttrs.maStyleName = mpImplFont->maStyleName; 761 rAttrs.meFamily = mpImplFont->meFamily; 762 rAttrs.mePitch = mpImplFont->mePitch; 763 rAttrs.meItalic = mpImplFont->meItalic; 764 rAttrs.meWeight = mpImplFont->meWeight; 765 rAttrs.meWidthType = WIDTH_DONTKNOW; 766 rAttrs.mbSymbolFlag= (mpImplFont->meCharSet == RTL_TEXTENCODING_SYMBOL); 767 } 768 769 770 // ----------------------------------------------------------------------- 771 772 SvStream& operator>>( SvStream& rIStm, Impl_Font& rImpl_Font ) 773 { 774 VersionCompat aCompat( rIStm, STREAM_READ ); 775 sal_uInt16 nTmp16; 776 sal_Bool bTmp; 777 sal_uInt8 nTmp8; 778 779 rIStm.ReadByteString( rImpl_Font.maFamilyName, rIStm.GetStreamCharSet() ); 780 rIStm.ReadByteString( rImpl_Font.maStyleName, rIStm.GetStreamCharSet() ); 781 rIStm >> rImpl_Font.maSize; 782 783 rIStm >> nTmp16; rImpl_Font.meCharSet = (rtl_TextEncoding) nTmp16; 784 rIStm >> nTmp16; rImpl_Font.meFamily = (FontFamily) nTmp16; 785 rIStm >> nTmp16; rImpl_Font.mePitch = (FontPitch) nTmp16; 786 rIStm >> nTmp16; rImpl_Font.meWeight = (FontWeight) nTmp16; 787 rIStm >> nTmp16; rImpl_Font.meUnderline = (FontUnderline) nTmp16; 788 rIStm >> nTmp16; rImpl_Font.meStrikeout = (FontStrikeout) nTmp16; 789 rIStm >> nTmp16; rImpl_Font.meItalic = (FontItalic) nTmp16; 790 rIStm >> nTmp16; rImpl_Font.meLanguage = (LanguageType) nTmp16; 791 rIStm >> nTmp16; rImpl_Font.meWidthType = (FontWidth) nTmp16; 792 793 rIStm >> rImpl_Font.mnOrientation; 794 795 rIStm >> bTmp; rImpl_Font.mbWordLine = bTmp; 796 rIStm >> bTmp; rImpl_Font.mbOutline = bTmp; 797 rIStm >> bTmp; rImpl_Font.mbShadow = bTmp; 798 rIStm >> nTmp8; rImpl_Font.mnKerning = nTmp8; 799 800 if( aCompat.GetVersion() >= 2 ) 801 { 802 rIStm >> nTmp8; rImpl_Font.meRelief = (FontRelief)nTmp8; 803 rIStm >> nTmp16; rImpl_Font.meCJKLanguage = (LanguageType)nTmp16; 804 rIStm >> bTmp; rImpl_Font.mbVertical = bTmp; 805 rIStm >> nTmp16; rImpl_Font.meEmphasisMark = (FontEmphasisMark)nTmp16; 806 } 807 if( aCompat.GetVersion() >= 3 ) 808 { 809 rIStm >> nTmp16; rImpl_Font.meOverline = (FontUnderline) nTmp16; 810 } 811 // Relief 812 // CJKContextLanguage 813 814 return rIStm; 815 } 816 817 // ----------------------------------------------------------------------- 818 819 SvStream& operator<<( SvStream& rOStm, const Impl_Font& rImpl_Font ) 820 { 821 VersionCompat aCompat( rOStm, STREAM_WRITE, 3 ); 822 rOStm.WriteByteString( rImpl_Font.maFamilyName, rOStm.GetStreamCharSet() ); 823 rOStm.WriteByteString( rImpl_Font.maStyleName, rOStm.GetStreamCharSet() ); 824 rOStm << rImpl_Font.maSize; 825 826 rOStm << (sal_uInt16) GetStoreCharSet( rImpl_Font.meCharSet ); 827 rOStm << (sal_uInt16) rImpl_Font.meFamily; 828 rOStm << (sal_uInt16) rImpl_Font.mePitch; 829 rOStm << (sal_uInt16) rImpl_Font.meWeight; 830 rOStm << (sal_uInt16) rImpl_Font.meUnderline; 831 rOStm << (sal_uInt16) rImpl_Font.meStrikeout; 832 rOStm << (sal_uInt16) rImpl_Font.meItalic; 833 rOStm << (sal_uInt16) rImpl_Font.meLanguage; 834 rOStm << (sal_uInt16) rImpl_Font.meWidthType; 835 836 rOStm << rImpl_Font.mnOrientation; 837 838 rOStm << (sal_Bool) rImpl_Font.mbWordLine; 839 rOStm << (sal_Bool) rImpl_Font.mbOutline; 840 rOStm << (sal_Bool) rImpl_Font.mbShadow; 841 rOStm << (sal_uInt8) rImpl_Font.mnKerning; 842 843 // new in version 2 844 rOStm << (sal_uInt8) rImpl_Font.meRelief; 845 rOStm << (sal_uInt16) rImpl_Font.meCJKLanguage; 846 rOStm << (sal_Bool) rImpl_Font.mbVertical; 847 rOStm << (sal_uInt16) rImpl_Font.meEmphasisMark; 848 849 // new in version 3 850 rOStm << (sal_uInt16) rImpl_Font.meOverline; 851 852 return rOStm; 853 } 854 855 // ----------------------------------------------------------------------- 856 857 SvStream& operator>>( SvStream& rIStm, Font& rFont ) 858 { 859 rFont.MakeUnique(); 860 return( rIStm >> *rFont.mpImplFont ); 861 } 862 863 // ----------------------------------------------------------------------- 864 865 SvStream& operator<<( SvStream& rOStm, const Font& rFont ) 866 { 867 return( rOStm << *rFont.mpImplFont ); 868 } 869 870 // ----------------------------------------------------------------------- 871 namespace 872 { 873 bool identifyTrueTypeFont( const void* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult ) 874 { 875 bool bResult = false; 876 TrueTypeFont* pTTF = NULL; 877 if( OpenTTFontBuffer( const_cast<void*>(i_pBuffer), i_nSize, 0, &pTTF ) == SF_OK ) 878 { 879 TTGlobalFontInfo aInfo; 880 GetTTGlobalFontInfo( pTTF, &aInfo ); 881 // most important: the family name 882 if( aInfo.ufamily ) 883 o_rResult.SetName( aInfo.ufamily ); 884 else if( aInfo.family ) 885 o_rResult.SetName( rtl::OStringToOUString( aInfo.family, RTL_TEXTENCODING_ASCII_US ) ); 886 // set weight 887 if( aInfo.weight ) 888 { 889 if( aInfo.weight < FW_EXTRALIGHT ) 890 o_rResult.SetWeight( WEIGHT_THIN ); 891 else if( aInfo.weight < FW_LIGHT ) 892 o_rResult.SetWeight( WEIGHT_ULTRALIGHT ); 893 else if( aInfo.weight < FW_NORMAL ) 894 o_rResult.SetWeight( WEIGHT_LIGHT ); 895 else if( aInfo.weight < FW_MEDIUM ) 896 o_rResult.SetWeight( WEIGHT_NORMAL ); 897 else if( aInfo.weight < FW_SEMIBOLD ) 898 o_rResult.SetWeight( WEIGHT_MEDIUM ); 899 else if( aInfo.weight < FW_BOLD ) 900 o_rResult.SetWeight( WEIGHT_SEMIBOLD ); 901 else if( aInfo.weight < FW_EXTRABOLD ) 902 o_rResult.SetWeight( WEIGHT_BOLD ); 903 else if( aInfo.weight < FW_BLACK ) 904 o_rResult.SetWeight( WEIGHT_ULTRABOLD ); 905 else 906 o_rResult.SetWeight( WEIGHT_BLACK ); 907 } 908 else 909 o_rResult.SetWeight( (aInfo.macStyle & 1) ? WEIGHT_BOLD : WEIGHT_NORMAL ); 910 // set width 911 if( aInfo.width ) 912 { 913 if( aInfo.width == FWIDTH_ULTRA_CONDENSED ) 914 o_rResult.SetWidth( WIDTH_ULTRA_CONDENSED ); 915 else if( aInfo.width == FWIDTH_EXTRA_CONDENSED ) 916 o_rResult.SetWidth( WIDTH_EXTRA_CONDENSED ); 917 else if( aInfo.width == FWIDTH_CONDENSED ) 918 o_rResult.SetWidth( WIDTH_CONDENSED ); 919 else if( aInfo.width == FWIDTH_SEMI_CONDENSED ) 920 o_rResult.SetWidth( WIDTH_SEMI_CONDENSED ); 921 else if( aInfo.width == FWIDTH_NORMAL ) 922 o_rResult.SetWidth( WIDTH_NORMAL ); 923 else if( aInfo.width == FWIDTH_SEMI_EXPANDED ) 924 o_rResult.SetWidth( WIDTH_SEMI_EXPANDED ); 925 else if( aInfo.width == FWIDTH_EXPANDED ) 926 o_rResult.SetWidth( WIDTH_EXPANDED ); 927 else if( aInfo.width == FWIDTH_EXTRA_EXPANDED ) 928 o_rResult.SetWidth( WIDTH_EXTRA_EXPANDED ); 929 else if( aInfo.width >= FWIDTH_ULTRA_EXPANDED ) 930 o_rResult.SetWidth( WIDTH_ULTRA_EXPANDED ); 931 } 932 // set italic 933 o_rResult.SetItalic( (aInfo.italicAngle != 0) ? ITALIC_NORMAL : ITALIC_NONE ); 934 935 // set pitch 936 o_rResult.SetPitch( (aInfo.pitch == 0) ? PITCH_VARIABLE : PITCH_FIXED ); 937 938 // set style name 939 if( aInfo.usubfamily ) 940 o_rResult.SetStyleName( rtl::OUString( aInfo.usubfamily ) ); 941 else if( aInfo.subfamily ) 942 o_rResult.SetStyleName( rtl::OUString::createFromAscii( aInfo.subfamily ) ); 943 944 // cleanup 945 CloseTTFont( pTTF ); 946 // success 947 bResult = true; 948 } 949 return bResult; 950 } 951 952 struct WeightSearchEntry 953 { 954 const char* string; 955 int string_len; 956 FontWeight weight; 957 958 bool operator<( const WeightSearchEntry& rRight ) const 959 { 960 return rtl_str_compareIgnoreAsciiCase_WithLength( string, string_len, rRight.string, rRight.string_len ) < 0; 961 } 962 } 963 weight_table[] = 964 { 965 { "black", 5, WEIGHT_BLACK }, 966 { "bold", 4, WEIGHT_BOLD }, 967 { "book", 4, WEIGHT_LIGHT }, 968 { "demi", 4, WEIGHT_SEMIBOLD }, 969 { "heavy", 5, WEIGHT_BLACK }, 970 { "light", 5, WEIGHT_LIGHT }, 971 { "medium", 6, WEIGHT_MEDIUM }, 972 { "regular", 7, WEIGHT_NORMAL }, 973 { "super", 5, WEIGHT_ULTRABOLD }, 974 { "thin", 4, WEIGHT_THIN } 975 }; 976 977 bool identifyType1Font( const char* i_pBuffer, sal_uInt32 i_nSize, Font& o_rResult ) 978 { 979 bool bResult = false; 980 // might be a type1, find eexec 981 const char* pStream = i_pBuffer; 982 const char* pExec = "eexec"; 983 const char* pExecPos = std::search( pStream, pStream+i_nSize, pExec, pExec+5 ); 984 if( pExecPos != pStream+i_nSize) 985 { 986 // find /FamilyName entry 987 static const char* pFam = "/FamilyName"; 988 const char* pFamPos = std::search( pStream, pExecPos, pFam, pFam+11 ); 989 if( pFamPos != pExecPos ) 990 { 991 // extract the string value behind /FamilyName 992 const char* pOpen = pFamPos+11; 993 while( pOpen < pExecPos && *pOpen != '(' ) 994 pOpen++; 995 const char* pClose = pOpen; 996 while( pClose < pExecPos && *pClose != ')' ) 997 pClose++; 998 if( pClose - pOpen > 1 ) 999 { 1000 o_rResult.SetName( rtl::OStringToOUString( rtl::OString( pOpen+1, pClose-pOpen-1 ), RTL_TEXTENCODING_ASCII_US ) ); 1001 } 1002 } 1003 1004 // parse /ItalicAngle 1005 static const char* pItalic = "/ItalicAngle"; 1006 const char* pItalicPos = std::search( pStream, pExecPos, pItalic, pItalic+12 ); 1007 if( pItalicPos != pExecPos ) 1008 { 1009 sal_Int32 nItalic = rtl_str_toInt32( pItalicPos+12, 10 ); 1010 o_rResult.SetItalic( (nItalic != 0) ? ITALIC_NORMAL : ITALIC_NONE ); 1011 } 1012 1013 // parse /Weight 1014 static const char* pWeight = "/Weight"; 1015 const char* pWeightPos = std::search( pStream, pExecPos, pWeight, pWeight+7 ); 1016 if( pWeightPos != pExecPos ) 1017 { 1018 // extract the string value behind /Weight 1019 const char* pOpen = pWeightPos+7; 1020 while( pOpen < pExecPos && *pOpen != '(' ) 1021 pOpen++; 1022 const char* pClose = pOpen; 1023 while( pClose < pExecPos && *pClose != ')' ) 1024 pClose++; 1025 if( pClose - pOpen > 1 ) 1026 { 1027 WeightSearchEntry aEnt; 1028 aEnt.string = pOpen+1; 1029 aEnt.string_len = (pClose-pOpen)-1; 1030 aEnt.weight = WEIGHT_NORMAL; 1031 const int nEnt = sizeof( weight_table ) / sizeof( weight_table[0] ); 1032 WeightSearchEntry* pFound = std::lower_bound( weight_table, weight_table+nEnt, aEnt ); 1033 if( pFound != (weight_table+nEnt) ) 1034 o_rResult.SetWeight( pFound->weight ); 1035 } 1036 } 1037 1038 // parse isFixedPitch 1039 static const char* pFixed = "/isFixedPitch"; 1040 const char* pFixedPos = std::search( pStream, pExecPos, pFixed, pFixed+13 ); 1041 if( pFixedPos != pExecPos ) 1042 { 1043 // skip whitespace 1044 while( pFixedPos < pExecPos-4 && 1045 ( *pFixedPos == ' ' || 1046 *pFixedPos == '\t' || 1047 *pFixedPos == '\r' || 1048 *pFixedPos == '\n' ) ) 1049 { 1050 pFixedPos++; 1051 } 1052 // find "true" value 1053 if( rtl_str_compareIgnoreAsciiCase_WithLength( pFixedPos, 4, "true", 4 ) == 0 ) 1054 o_rResult.SetPitch( PITCH_FIXED ); 1055 else 1056 o_rResult.SetPitch( PITCH_VARIABLE ); 1057 } 1058 } 1059 return bResult; 1060 } 1061 } 1062 1063 Font Font::identifyFont( const void* i_pBuffer, sal_uInt32 i_nSize ) 1064 { 1065 Font aResult; 1066 if( ! identifyTrueTypeFont( i_pBuffer, i_nSize, aResult ) ) 1067 { 1068 const char* pStream = reinterpret_cast<const char*>(i_pBuffer); 1069 if( pStream && i_nSize > 100 && 1070 *pStream == '%' && pStream[1] == '!' ) 1071 { 1072 identifyType1Font( pStream, i_nSize, aResult ); 1073 } 1074 } 1075 1076 return aResult; 1077 } 1078 1079 // the inlines from the font.hxx header are now instantiated for pImpl-ification 1080 // TODO: reformat 1081 const Color& Font::GetColor() const { return mpImplFont->maColor; } 1082 const Color& Font::GetFillColor() const { return mpImplFont->maFillColor; } 1083 sal_Bool Font::IsTransparent() const { return mpImplFont->mbTransparent; } 1084 FontAlign Font::GetAlign() const { return mpImplFont->meAlign; } 1085 const String& Font::GetName() const { return mpImplFont->maFamilyName; } 1086 const String& Font::GetStyleName() const { return mpImplFont->maStyleName; } 1087 const Size& Font::GetSize() const { return mpImplFont->maSize; } 1088 void Font::SetHeight( long nHeight ) { SetSize( Size( mpImplFont->maSize.Width(), nHeight ) ); } 1089 long Font::GetHeight() const { return mpImplFont->maSize.Height(); } 1090 void Font::SetWidth( long nWidth ) { SetSize( Size( nWidth, mpImplFont->maSize.Height() ) ); } 1091 long Font::GetWidth() const { return mpImplFont->maSize.Width(); } 1092 rtl_TextEncoding Font::GetCharSet() const { return mpImplFont->meCharSet; } 1093 LanguageType Font::GetLanguage() const { return mpImplFont->meLanguage; } 1094 LanguageType Font::GetCJKContextLanguage() const { return mpImplFont->meCJKLanguage; } 1095 short Font::GetOrientation() const { return mpImplFont->mnOrientation; } 1096 sal_Bool Font::IsVertical() const { return mpImplFont->mbVertical; } 1097 FontKerning Font::GetKerning() const { return mpImplFont->mnKerning; } 1098 FontPitch Font::GetPitch() const { return mpImplFont->GetPitch(); } 1099 FontWeight Font::GetWeight() const { return mpImplFont->GetWeight(); } 1100 FontWidth Font::GetWidthType() const { return mpImplFont->GetWidthType(); } 1101 FontItalic Font::GetItalic() const { return mpImplFont->GetItalic(); } 1102 FontFamily Font::GetFamily() const { return mpImplFont->GetFamily(); } 1103 sal_Bool Font::IsOutline() const { return mpImplFont->mbOutline; } 1104 sal_Bool Font::IsShadow() const { return mpImplFont->mbShadow; } 1105 FontRelief Font::GetRelief() const { return mpImplFont->meRelief; } 1106 FontUnderline Font::GetUnderline() const { return mpImplFont->meUnderline; } 1107 FontUnderline Font::GetOverline() const { return mpImplFont->meOverline; } 1108 FontStrikeout Font::GetStrikeout() const { return mpImplFont->meStrikeout; } 1109 FontEmphasisMark Font::GetEmphasisMark() const { return mpImplFont->meEmphasisMark; } 1110 sal_Bool Font::IsWordLineMode() const { return mpImplFont->mbWordLine; } 1111 sal_Bool Font::IsSameInstance( const Font& rFont ) const { return (mpImplFont == rFont.mpImplFont); } 1112