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