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_editeng.hxx" 30 31 // include ---------------------------------------------------------------- 32 33 #include <vcl/outdev.hxx> 34 #include <vcl/print.hxx> 35 #include <tools/poly.hxx> 36 #include <unotools/charclass.hxx> 37 #include <editeng/unolingu.hxx> 38 #include <com/sun/star/i18n/KCharacterType.hpp> 39 40 #define _SVX_SVXFONT_CXX 41 42 #include <editeng/svxfont.hxx> 43 #include <editeng/escpitem.hxx> 44 45 // Minimum: Prozentwert fuers kernen 46 #define MINKERNPERCENT 5 47 48 // prop. Size of the small cap letters 49 #define KAPITAELCHENPROP 75 50 51 #ifndef REDUCEDSVXFONT 52 const sal_Unicode CH_BLANK = sal_Unicode(' '); // ' ' Leerzeichen 53 static sal_Char __READONLY_DATA sDoubleSpace[] = " "; 54 #endif 55 56 /************************************************************************* 57 * class SvxFont 58 *************************************************************************/ 59 60 SvxFont::SvxFont() 61 { 62 nKern = nEsc = 0; 63 nPropr = 100; 64 eCaseMap = SVX_CASEMAP_NOT_MAPPED; 65 eLang = LANGUAGE_SYSTEM; 66 } 67 68 SvxFont::SvxFont( const Font &rFont ) 69 : Font( rFont ) 70 { 71 nKern = nEsc = 0; 72 nPropr = 100; 73 eCaseMap = SVX_CASEMAP_NOT_MAPPED; 74 eLang = LANGUAGE_SYSTEM; 75 } 76 77 /************************************************************************* 78 * class SvxFont: Copy-Ctor 79 *************************************************************************/ 80 81 SvxFont::SvxFont( const SvxFont &rFont ) 82 : Font( rFont ) 83 { 84 nKern = rFont.GetFixKerning(); 85 nEsc = rFont.GetEscapement(); 86 nPropr = rFont.GetPropr(); 87 eCaseMap = rFont.GetCaseMap(); 88 eLang = rFont.GetLanguage(); 89 } 90 91 /************************************************************************* 92 * static SvxFont::DrawArrow 93 *************************************************************************/ 94 95 void SvxFont::DrawArrow( OutputDevice &rOut, const Rectangle& rRect, 96 const Size& rSize, const Color& rCol, sal_Bool bLeft ) 97 { 98 long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2; 99 long nRight = nLeft + rSize.Width(); 100 long nMid = ( rRect.Top() + rRect.Bottom() ) / 2; 101 long nTop = nMid - rSize.Height() / 2; 102 long nBottom = nTop + rSize.Height(); 103 if( nLeft < rRect.Left() ) 104 { 105 nLeft = rRect.Left(); 106 nRight = rRect.Right(); 107 } 108 if( nTop < rRect.Top() ) 109 { 110 nTop = rRect.Top(); 111 nBottom = rRect.Bottom(); 112 } 113 Polygon aPoly; 114 Point aTmp( bLeft ? nLeft : nRight, nMid ); 115 Point aNxt( bLeft ? nRight : nLeft, nTop ); 116 aPoly.Insert( 0, aTmp ); 117 aPoly.Insert( 0, aNxt ); 118 aNxt.Y() = nBottom; 119 aPoly.Insert( 0, aNxt ); 120 aPoly.Insert( 0, aTmp ); 121 Color aOldLineColor = rOut.GetLineColor(); 122 Color aOldFillColor = rOut.GetFillColor(); 123 rOut.SetFillColor( rCol ); 124 rOut.SetLineColor( Color( COL_BLACK ) ); 125 rOut.DrawPolygon( aPoly ); 126 rOut.DrawLine( aTmp, aNxt ); 127 rOut.SetLineColor( aOldLineColor ); 128 rOut.SetFillColor( aOldFillColor ); 129 } 130 131 /************************************************************************* 132 * SvxFont::CalcCaseMap 133 *************************************************************************/ 134 135 XubString SvxFont::CalcCaseMap( const XubString &rTxt ) const 136 { 137 if( !IsCaseMap() || !rTxt.Len() ) return rTxt; 138 XubString aTxt( rTxt ); 139 // Ich muss mir noch die Sprache besorgen 140 const LanguageType eLng = LANGUAGE_DONTKNOW == eLang 141 ? LANGUAGE_SYSTEM : eLang; 142 143 CharClass aCharClass( SvxCreateLocale( eLng ) ); 144 145 switch( eCaseMap ) 146 { 147 case SVX_CASEMAP_KAPITAELCHEN: 148 case SVX_CASEMAP_VERSALIEN: 149 { 150 aCharClass.toUpper( aTxt ); 151 break; 152 } 153 154 case SVX_CASEMAP_GEMEINE: 155 { 156 aCharClass.toLower( aTxt ); 157 break; 158 } 159 case SVX_CASEMAP_TITEL: 160 { 161 // Jeder Wortbeginn wird gross geschrieben, 162 // der Rest des Wortes wird unbesehen uebernommen. 163 // Bug: wenn das Attribut mitten im Wort beginnt. 164 sal_Bool bBlank = sal_True; 165 166 for( sal_uInt16 i = 0; i < aTxt.Len(); ++i ) 167 { 168 if( sal_Unicode(' ') == aTxt.GetChar(i) || sal_Unicode('\t') == aTxt.GetChar(i) ) 169 bBlank = sal_True; 170 else 171 { 172 if( bBlank ) 173 { 174 String aTemp( aTxt.GetChar( i ) ); 175 aCharClass.toUpper( aTemp ); 176 aTxt.Replace( i, 1, aTemp ); 177 } 178 bBlank = sal_False; 179 } 180 } 181 break; 182 } 183 default: 184 { 185 DBG_ASSERT(!this, "SvxFont::CaseMapTxt: unknown casemap"); 186 break; 187 } 188 } 189 return aTxt; 190 } 191 192 /************************************************************************* 193 * Hier beginnen die Methoden, die im Writer nicht benutzt werden koennen, 194 * deshalb kann man diesen Bereich durch setzen von REDUCEDSVXFONT ausklammern. 195 *************************************************************************/ 196 #ifndef REDUCEDSVXFONT 197 198 /************************************************************************* 199 * class SvxDoCapitals 200 * die virtuelle Methode Do wird von SvxFont::DoOnCapitals abwechselnd mit 201 * den "Gross-" und "Kleinbuchstaben"-Teilen aufgerufen. 202 * Die Ableitungen von SvxDoCapitals erfuellen diese Methode mit Leben. 203 *************************************************************************/ 204 205 class SvxDoCapitals 206 { 207 protected: 208 OutputDevice *pOut; 209 const XubString &rTxt; 210 const xub_StrLen nIdx; 211 const xub_StrLen nLen; 212 213 public: 214 SvxDoCapitals( OutputDevice *_pOut, const XubString &_rTxt, 215 const xub_StrLen _nIdx, const xub_StrLen _nLen ) 216 : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen) 217 { } 218 219 virtual void DoSpace( const sal_Bool bDraw ); 220 virtual void SetSpace(); 221 virtual void Do( const XubString &rTxt, 222 const xub_StrLen nIdx, const xub_StrLen nLen, 223 const sal_Bool bUpper ) = 0; 224 225 inline OutputDevice *GetOut() { return pOut; } 226 inline const XubString &GetTxt() const { return rTxt; } 227 xub_StrLen GetIdx() const { return nIdx; } 228 xub_StrLen GetLen() const { return nLen; } 229 }; 230 231 void SvxDoCapitals::DoSpace( const sal_Bool /*bDraw*/ ) { } 232 233 void SvxDoCapitals::SetSpace() { } 234 235 void SvxDoCapitals::Do( const XubString &/*_rTxt*/, const xub_StrLen /*_nIdx*/, 236 const xub_StrLen /*_nLen*/, const sal_Bool /*bUpper*/ ) { } 237 238 /************************************************************************* 239 * SvxFont::DoOnCapitals() const 240 * zerlegt den String in Gross- und Kleinbuchstaben und ruft jeweils die 241 * Methode SvxDoCapitals::Do( ) auf. 242 *************************************************************************/ 243 244 void SvxFont::DoOnCapitals(SvxDoCapitals &rDo, const xub_StrLen nPartLen) const 245 { 246 const XubString &rTxt = rDo.GetTxt(); 247 const xub_StrLen nIdx = rDo.GetIdx(); 248 const xub_StrLen nLen = STRING_LEN == nPartLen ? rDo.GetLen() : nPartLen; 249 250 const XubString aTxt( CalcCaseMap( rTxt ) ); 251 const sal_uInt16 nTxtLen = Min( rTxt.Len(), nLen ); 252 sal_uInt16 nPos = 0; 253 sal_uInt16 nOldPos = nPos; 254 255 // #108210# 256 // Test if string length differ between original and CaseMapped 257 sal_Bool bCaseMapLengthDiffers(aTxt.Len() != rTxt.Len()); 258 259 const LanguageType eLng = LANGUAGE_DONTKNOW == eLang 260 ? LANGUAGE_SYSTEM : eLang; 261 262 CharClass aCharClass( SvxCreateLocale( eLng ) ); 263 String aCharString; 264 265 while( nPos < nTxtLen ) 266 { 267 // Erst kommen die Upper-Chars dran 268 269 // 4251: Es gibt Zeichen, die Upper _und_ Lower sind (z.B. das Blank). 270 // Solche Zweideutigkeiten fuehren ins Chaos, deswegen werden diese 271 // Zeichen der Menge Lower zugeordnet ! 272 273 while( nPos < nTxtLen ) 274 { 275 aCharString = rTxt.GetChar( nPos + nIdx ); 276 sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 ); 277 if ( nCharacterType & ::com::sun::star::i18n::KCharacterType::LOWER ) 278 break; 279 if ( ! ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) ) 280 break; 281 ++nPos; 282 } 283 if( nOldPos != nPos ) 284 { 285 if(bCaseMapLengthDiffers) 286 { 287 // #108210# 288 // If strings differ work preparing the necessary snippet to address that 289 // potential difference 290 const XubString aSnippet(rTxt, nIdx + nOldPos, nPos-nOldPos); 291 XubString aNewText = CalcCaseMap(aSnippet); 292 293 rDo.Do( aNewText, 0, aNewText.Len(), sal_True ); 294 } 295 else 296 { 297 rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_True ); 298 } 299 300 nOldPos = nPos; 301 } 302 // Nun werden die Lower-Chars verarbeitet (ohne Blanks) 303 while( nPos < nTxtLen ) 304 { 305 sal_uInt32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 ); 306 if ( ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) ) 307 break; 308 if ( CH_BLANK == aCharString ) 309 break; 310 if( ++nPos < nTxtLen ) 311 aCharString = rTxt.GetChar( nPos + nIdx ); 312 } 313 if( nOldPos != nPos ) 314 { 315 if(bCaseMapLengthDiffers) 316 { 317 // #108210# 318 // If strings differ work preparing the necessary snippet to address that 319 // potential difference 320 const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos); 321 XubString aNewText = CalcCaseMap(aSnippet); 322 323 rDo.Do( aNewText, 0, aNewText.Len(), sal_False ); 324 } 325 else 326 { 327 rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_False ); 328 } 329 330 nOldPos = nPos; 331 } 332 // Nun werden die Blanks verarbeitet 333 while( nPos < nTxtLen && CH_BLANK == aCharString && ++nPos < nTxtLen ) 334 aCharString = rTxt.GetChar( nPos + nIdx ); 335 336 if( nOldPos != nPos ) 337 { 338 rDo.DoSpace( sal_False ); 339 340 if(bCaseMapLengthDiffers) 341 { 342 // #108210# 343 // If strings differ work preparing the necessary snippet to address that 344 // potential difference 345 const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos); 346 XubString aNewText = CalcCaseMap(aSnippet); 347 348 rDo.Do( aNewText, 0, aNewText.Len(), sal_False ); 349 } 350 else 351 { 352 rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, sal_False ); 353 } 354 355 nOldPos = nPos; 356 rDo.SetSpace(); 357 } 358 } 359 rDo.DoSpace( sal_True ); 360 } 361 362 /************************************************************************** 363 * SvxFont::SetPhysFont() 364 *************************************************************************/ 365 366 void SvxFont::SetPhysFont( OutputDevice *pOut ) const 367 { 368 const Font& rCurrentFont = pOut->GetFont(); 369 if ( nPropr == 100 ) 370 { 371 if ( !rCurrentFont.IsSameInstance( *this ) ) 372 pOut->SetFont( *this ); 373 } 374 else 375 { 376 Font aNewFont( *this ); 377 Size aSize( aNewFont.GetSize() ); 378 aNewFont.SetSize( Size( aSize.Width() * nPropr / 100L, 379 aSize.Height() * nPropr / 100L ) ); 380 if ( !rCurrentFont.IsSameInstance( aNewFont ) ) 381 pOut->SetFont( aNewFont ); 382 } 383 } 384 385 /************************************************************************* 386 * SvxFont::ChgPhysFont() 387 *************************************************************************/ 388 389 Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const 390 { 391 Font aOldFont( pOut->GetFont() ); 392 SetPhysFont( pOut ); 393 return aOldFont; 394 } 395 396 /************************************************************************* 397 * SvxFont::GetPhysTxtSize() 398 *************************************************************************/ 399 400 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt, 401 const xub_StrLen nIdx, const xub_StrLen nLen ) const 402 { 403 if ( !IsCaseMap() && !IsKern() ) 404 return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ), 405 pOut->GetTextHeight() ); 406 407 Size aTxtSize; 408 aTxtSize.setHeight( pOut->GetTextHeight() ); 409 if ( !IsCaseMap() ) 410 aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) ); 411 else 412 { 413 // #108210# 414 const XubString aNewText = CalcCaseMap(rTxt); 415 sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len()); 416 sal_Int32 nWidth(0L); 417 418 if(bCaseMapLengthDiffers) 419 { 420 // If strings differ work preparing the necessary snippet to address that 421 // potential difference 422 const XubString aSnippet(rTxt, nIdx, nLen); 423 XubString _aNewText = CalcCaseMap(aSnippet); 424 nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.Len() ); 425 } 426 else 427 { 428 nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen ); 429 } 430 431 aTxtSize.setWidth(nWidth); 432 } 433 434 if( IsKern() && ( nLen > 1 ) ) 435 aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) ); 436 437 return aTxtSize; 438 } 439 440 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt ) 441 { 442 if ( !IsCaseMap() && !IsKern() ) 443 return Size( pOut->GetTextWidth( rTxt ), pOut->GetTextHeight() ); 444 445 Size aTxtSize; 446 aTxtSize.setHeight( pOut->GetTextHeight() ); 447 if ( !IsCaseMap() ) 448 aTxtSize.setWidth( pOut->GetTextWidth( rTxt ) ); 449 else 450 aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( rTxt ) ) ); 451 452 if( IsKern() && ( rTxt.Len() > 1 ) ) 453 aTxtSize.Width() += ( ( rTxt.Len()-1 ) * long( nKern ) ); 454 455 return aTxtSize; 456 } 457 458 Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const XubString &rTxt, 459 const sal_uInt16 nIdx, const sal_uInt16 nLen, sal_Int32* pDXArray ) const 460 { 461 if ( !IsCaseMap() && !IsKern() ) 462 return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ), 463 pOut->GetTextHeight() ); 464 465 Size aTxtSize; 466 aTxtSize.setHeight( pOut->GetTextHeight() ); 467 if ( !IsCaseMap() ) 468 aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) ); 469 else 470 aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ), 471 pDXArray, nIdx, nLen ) ); 472 473 if( IsKern() && ( nLen > 1 ) ) 474 { 475 aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) ); 476 477 if ( pDXArray ) 478 { 479 for ( xub_StrLen i = 0; i < nLen; i++ ) 480 pDXArray[i] += ( (i+1) * long( nKern ) ); 481 // Der letzte ist um ein nKern zu gross: 482 pDXArray[nLen-1] -= nKern; 483 } 484 } 485 return aTxtSize; 486 } 487 488 /************************************************************************* 489 * SvxFont::GetTxtSize() 490 *************************************************************************/ 491 492 Size SvxFont::GetTxtSize( const OutputDevice *pOut, const XubString &rTxt, 493 const xub_StrLen nIdx, const xub_StrLen nLen ) 494 { 495 xub_StrLen nTmp = nLen; 496 if ( nTmp == STRING_LEN ) // schon initialisiert? 497 nTmp = rTxt.Len(); 498 Font aOldFont( ChgPhysFont((OutputDevice *)pOut) ); 499 Size aTxtSize; 500 if( IsCapital() && rTxt.Len() ) 501 { 502 aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp ); 503 } 504 else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp); 505 ((OutputDevice *)pOut)->SetFont( aOldFont ); 506 return aTxtSize; 507 } 508 509 /************************************************************************* 510 * SvxFont::DrawText() 511 *************************************************************************/ 512 513 void SvxFont::DrawText( OutputDevice *pOut, 514 const Point &rPos, const XubString &rTxt, 515 const xub_StrLen nIdx, const xub_StrLen nLen ) const 516 { 517 if( !nLen || !rTxt.Len() ) return; 518 xub_StrLen nTmp = nLen; 519 if ( nTmp == STRING_LEN ) // schon initialisiert? 520 nTmp = rTxt.Len(); 521 Point aPos( rPos ); 522 if ( nEsc ) 523 { 524 Size aSize = (this->GetSize()); 525 aPos.Y() -= ((nEsc*long(aSize.Height()))/ 100L); 526 } 527 Font aOldFont( ChgPhysFont( pOut ) ); 528 529 if ( IsCapital() ) 530 DrawCapital( pOut, aPos, rTxt, nIdx, nTmp ); 531 else 532 { 533 Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nTmp ); 534 535 if ( !IsCaseMap() ) 536 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp ); 537 else 538 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), 539 nIdx, nTmp ); 540 } 541 pOut->SetFont(aOldFont); 542 } 543 544 void SvxFont::QuickDrawText( OutputDevice *pOut, 545 const Point &rPos, const XubString &rTxt, 546 const xub_StrLen nIdx, const xub_StrLen nLen, const sal_Int32* pDXArray ) const 547 { 548 // Font muss ins OutputDevice selektiert sein... 549 if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() ) 550 { 551 pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen ); 552 return; 553 } 554 555 Point aPos( rPos ); 556 557 if ( nEsc ) 558 { 559 long nDiff = GetSize().Height(); 560 nDiff *= nEsc; 561 nDiff /= 100; 562 563 if ( !IsVertical() ) 564 aPos.Y() -= nDiff; 565 else 566 aPos.X() += nDiff; 567 } 568 569 if( IsCapital() ) 570 { 571 DBG_ASSERT( !pDXArray, "DrawCapital nicht fuer TextArray!" ); 572 DrawCapital( pOut, aPos, rTxt, nIdx, nLen ); 573 } 574 else 575 { 576 if ( IsKern() && !pDXArray ) 577 { 578 Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen ); 579 580 if ( !IsCaseMap() ) 581 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen ); 582 else 583 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen ); 584 } 585 else 586 { 587 if ( !IsCaseMap() ) 588 pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen ); 589 else 590 pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen ); 591 } 592 } 593 } 594 595 // ----------------------------------------------------------------------- 596 597 void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter, 598 const Point &rPos, const XubString &rTxt, 599 const xub_StrLen nIdx, const xub_StrLen nLen ) const 600 { 601 if ( !nLen || !rTxt.Len() ) 602 return; 603 xub_StrLen nTmp = nLen; 604 605 if ( nTmp == STRING_LEN ) // schon initialisiert? 606 nTmp = rTxt.Len(); 607 Point aPos( rPos ); 608 609 if ( nEsc ) 610 { 611 short nTmpEsc; 612 if( DFLT_ESC_AUTO_SUPER == nEsc ) 613 nTmpEsc = 33; 614 else if( DFLT_ESC_AUTO_SUB == nEsc ) 615 nTmpEsc = -20; 616 else 617 nTmpEsc = nEsc; 618 Size aSize = ( this->GetSize() ); 619 aPos.Y() -= ( ( nTmpEsc * long( aSize.Height() ) ) / 100L ); 620 } 621 Font aOldFont( ChgPhysFont( pOut ) ); 622 Font aOldPrnFont( ChgPhysFont( pPrinter ) ); 623 624 if ( IsCapital() ) 625 DrawCapital( pOut, aPos, rTxt, nIdx, nTmp ); 626 else 627 { 628 Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp ); 629 630 if ( !IsCaseMap() ) 631 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp ); 632 else 633 { 634 // #108210# 635 const XubString aNewText = CalcCaseMap(rTxt); 636 sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len()); 637 638 if(bCaseMapLengthDiffers) 639 { 640 // If strings differ work preparing the necessary snippet to address that 641 // potential difference 642 const XubString aSnippet(rTxt, nIdx, nTmp); 643 XubString _aNewText = CalcCaseMap(aSnippet); 644 645 pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.Len() ); 646 } 647 else 648 { 649 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp ); 650 } 651 } 652 } 653 pOut->SetFont(aOldFont); 654 pPrinter->SetFont( aOldPrnFont ); 655 } 656 657 // ----------------------------------------------------------------------- 658 659 SvxFont& SvxFont::operator=( const Font& rFont ) 660 { 661 Font::operator=( rFont ); 662 return *this; 663 } 664 665 SvxFont& SvxFont::operator=( const SvxFont& rFont ) 666 { 667 Font::operator=( rFont ); 668 eLang = rFont.eLang; 669 eCaseMap = rFont.eCaseMap; 670 nEsc = rFont.nEsc; 671 nPropr = rFont.nPropr; 672 nKern = rFont.nKern; 673 return *this; 674 } 675 676 677 /************************************************************************* 678 * class SvxDoGetCapitalSize 679 * wird von SvxFont::GetCapitalSize() zur Berechnung der TxtSize bei 680 * eingestellten Kapitaelchen benutzt. 681 *************************************************************************/ 682 683 class SvxDoGetCapitalSize : public SvxDoCapitals 684 { 685 protected: 686 SvxFont* pFont; 687 Size aTxtSize; 688 short nKern; 689 public: 690 SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut, 691 const XubString &_rTxt, const xub_StrLen _nIdx, 692 const xub_StrLen _nLen, const short _nKrn ) 693 : SvxDoCapitals( (OutputDevice*)_pOut, _rTxt, _nIdx, _nLen ), 694 pFont( _pFnt ), 695 nKern( _nKrn ) 696 { } 697 698 virtual void Do( const XubString &rTxt, const xub_StrLen nIdx, 699 const xub_StrLen nLen, const sal_Bool bUpper ); 700 701 inline const Size &GetSize() const { return aTxtSize; }; 702 }; 703 704 void SvxDoGetCapitalSize::Do( const XubString &_rTxt, const xub_StrLen _nIdx, 705 const xub_StrLen _nLen, const sal_Bool bUpper ) 706 { 707 Size aPartSize; 708 if ( !bUpper ) 709 { 710 sal_uInt8 nProp = pFont->GetPropr(); 711 pFont->SetProprRel( KAPITAELCHENPROP ); 712 pFont->SetPhysFont( pOut ); 713 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); 714 aPartSize.setHeight( pOut->GetTextHeight() ); 715 aTxtSize.Height() = aPartSize.Height(); 716 pFont->SetPropr( nProp ); 717 pFont->SetPhysFont( pOut ); 718 } 719 else 720 { 721 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); 722 aPartSize.setHeight( pOut->GetTextHeight() ); 723 } 724 aTxtSize.Width() += aPartSize.Width(); 725 aTxtSize.Width() += ( _nLen * long( nKern ) ); 726 } 727 728 /************************************************************************* 729 * SvxFont::GetCapitalSize() 730 * berechnet TxtSize, wenn Kapitaelchen eingestellt sind. 731 *************************************************************************/ 732 733 Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const XubString &rTxt, 734 const xub_StrLen nIdx, const xub_StrLen nLen) const 735 { 736 // Start: 737 SvxDoGetCapitalSize aDo( (SvxFont *)this, pOut, rTxt, nIdx, nLen, nKern ); 738 DoOnCapitals( aDo ); 739 Size aTxtSize( aDo.GetSize() ); 740 741 // End: 742 if( !aTxtSize.Height() ) 743 { 744 aTxtSize.setWidth( 0 ); 745 aTxtSize.setHeight( pOut->GetTextHeight() ); 746 } 747 return aTxtSize; 748 } 749 750 /************************************************************************* 751 * class SvxDoDrawCapital 752 * wird von SvxFont::DrawCapital zur Ausgabe von Kapitaelchen benutzt. 753 *************************************************************************/ 754 755 class SvxDoDrawCapital : public SvxDoCapitals 756 { 757 protected: 758 SvxFont *pFont; 759 Point aPos; 760 Point aSpacePos; 761 short nKern; 762 public: 763 SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const XubString &_rTxt, 764 const xub_StrLen _nIdx, const xub_StrLen _nLen, 765 const Point &rPos, const short nKrn ) 766 : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ), 767 pFont( pFnt ), 768 aPos( rPos ), 769 aSpacePos( rPos ), 770 nKern( nKrn ) 771 { } 772 virtual void DoSpace( const sal_Bool bDraw ); 773 virtual void SetSpace(); 774 virtual void Do( const XubString &rTxt, const xub_StrLen nIdx, 775 const xub_StrLen nLen, const sal_Bool bUpper ); 776 }; 777 778 void SvxDoDrawCapital::DoSpace( const sal_Bool bDraw ) 779 { 780 if ( bDraw || pFont->IsWordLineMode() ) 781 { 782 sal_uInt16 nDiff = (sal_uInt16)(aPos.X() - aSpacePos.X()); 783 if ( nDiff ) 784 { 785 sal_Bool bWordWise = pFont->IsWordLineMode(); 786 sal_Bool bTrans = pFont->IsTransparent(); 787 pFont->SetWordLineMode( sal_False ); 788 pFont->SetTransparent( sal_True ); 789 pFont->SetPhysFont( pOut ); 790 pOut->DrawStretchText( aSpacePos, nDiff, XubString( sDoubleSpace, 791 RTL_TEXTENCODING_MS_1252 ), 0, 2 ); 792 pFont->SetWordLineMode( bWordWise ); 793 pFont->SetTransparent( bTrans ); 794 pFont->SetPhysFont( pOut ); 795 } 796 } 797 } 798 799 void SvxDoDrawCapital::SetSpace() 800 { 801 if ( pFont->IsWordLineMode() ) 802 aSpacePos.X() = aPos.X(); 803 } 804 805 void SvxDoDrawCapital::Do( const XubString &_rTxt, const xub_StrLen _nIdx, 806 const xub_StrLen _nLen, const sal_Bool bUpper) 807 { 808 sal_uInt8 nProp = 0; 809 Size aPartSize; 810 811 // Einstellen der gewuenschten Fonts 812 FontUnderline eUnder = pFont->GetUnderline(); 813 FontStrikeout eStrike = pFont->GetStrikeout(); 814 pFont->SetUnderline( UNDERLINE_NONE ); 815 pFont->SetStrikeout( STRIKEOUT_NONE ); 816 if ( !bUpper ) 817 { 818 nProp = pFont->GetPropr(); 819 pFont->SetProprRel( KAPITAELCHENPROP ); 820 } 821 pFont->SetPhysFont( pOut ); 822 823 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); 824 aPartSize.setHeight( pOut->GetTextHeight() ); 825 long nWidth = aPartSize.Width(); 826 if ( nKern ) 827 { 828 aPos.X() += (nKern/2); 829 if ( _nLen ) nWidth += (_nLen*long(nKern)); 830 } 831 pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen); 832 833 // Font restaurieren 834 pFont->SetUnderline( eUnder ); 835 pFont->SetStrikeout( eStrike ); 836 if ( !bUpper ) 837 pFont->SetPropr( nProp ); 838 pFont->SetPhysFont( pOut ); 839 840 aPos.X() += nWidth-(nKern/2); 841 } 842 843 /************************************************************************* 844 * SvxFont::DrawCapital() gibt Kapitaelchen aus. 845 *************************************************************************/ 846 847 void SvxFont::DrawCapital( OutputDevice *pOut, 848 const Point &rPos, const XubString &rTxt, 849 const xub_StrLen nIdx, const xub_StrLen nLen ) const 850 { 851 SvxDoDrawCapital aDo( (SvxFont *)this,pOut,rTxt,nIdx,nLen,rPos,nKern ); 852 DoOnCapitals( aDo ); 853 } 854 855 #endif // !REDUCEDSVXFONT 856 857 858