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