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