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_sw.hxx" 30 31 32 #include <hintids.hxx> 33 #include <editeng/cmapitem.hxx> 34 35 #ifndef _OUTDEV_HXX //autogen 36 #include <vcl/outdev.hxx> 37 #endif 38 #ifndef _COM_SUN_STAR_I18N_CHARTYPE_HDL 39 #include <com/sun/star/i18n/CharType.hdl> 40 #endif 41 #ifndef _COM_SUN_STAR_I18N_WORDTYPE_HDL 42 #include <com/sun/star/i18n/WordType.hdl> 43 #endif 44 45 #ifndef _PRINT_HXX //autogen 46 #include <vcl/print.hxx> 47 #endif 48 #include <errhdl.hxx> 49 #include <fntcache.hxx> 50 #include <swfont.hxx> 51 #include <breakit.hxx> 52 #include <txtfrm.hxx> // SwTxtFrm 53 #include <scriptinfo.hxx> 54 55 using namespace ::com::sun::star::i18n; 56 57 58 #define KAPITAELCHENPROP 75 59 60 /************************************************************************* 61 * class SwCapitalInfo 62 * 63 * The information encapsulated in SwCapitalInfo is required 64 * by the ::Do functions. They contain the information about 65 * the original string, whereas rDo.GetInf() contains information 66 * about the display string. 67 *************************************************************************/ 68 69 class SwCapitalInfo 70 { 71 public: 72 explicit SwCapitalInfo( const XubString& rOrigText ) : 73 rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {}; 74 const XubString& rString; 75 xub_StrLen nIdx; 76 xub_StrLen nLen; 77 }; 78 79 /************************************************************************* 80 * xub_StrLen lcl_CalcCaseMap() 81 * 82 * rFnt: required for CalcCaseMap 83 * rOrigString: The original string 84 * nOfst: Position of the substring in rOrigString 85 * nLen: Length if the substring in rOrigString 86 * nIdx: Referes to a position in the display string and should be mapped 87 * to a position in rOrigString 88 *************************************************************************/ 89 90 xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt, 91 const XubString& rOrigString, 92 xub_StrLen nOfst, 93 xub_StrLen nLen, 94 xub_StrLen nIdx ) 95 { 96 int j = 0; 97 const xub_StrLen nEnd = nOfst + nLen; 98 ASSERT( nEnd <= rOrigString.Len(), "lcl_CalcCaseMap: Wrong parameters" ) 99 100 // special case for title case: 101 const bool bTitle = SVX_CASEMAP_TITEL == rFnt.GetCaseMap() && 102 pBreakIt->GetBreakIter().is(); 103 for ( xub_StrLen i = nOfst; i < nEnd; ++i ) 104 { 105 XubString aTmp( rOrigString, i, 1 ); 106 107 if ( !bTitle || 108 pBreakIt->GetBreakIter()->isBeginWord( 109 rOrigString, i, 110 pBreakIt->GetLocale( rFnt.GetLanguage() ), 111 WordType::ANYWORD_IGNOREWHITESPACES ) ) 112 aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp ); 113 114 j += aTmp.Len(); 115 116 if ( j > nIdx ) 117 return i; 118 } 119 120 return nOfst + nLen; 121 } 122 123 /************************************************************************* 124 * class SwDoCapitals 125 *************************************************************************/ 126 127 class SwDoCapitals 128 { 129 protected: 130 SwDrawTextInfo &rInf; 131 SwCapitalInfo* pCapInf; // referes to additional information 132 // required by the ::Do function 133 public: 134 SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( 0 ) { } 135 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0; 136 virtual void Do() = 0; 137 inline OutputDevice& GetOut() { return rInf.GetOut(); } 138 inline SwDrawTextInfo& GetInf() { return rInf; } 139 inline SwCapitalInfo* GetCapInf() const { return pCapInf; } 140 inline void SetCapInf( SwCapitalInfo& rNew ) { pCapInf = &rNew; } 141 }; 142 143 /************************************************************************* 144 * class SwDoGetCapitalSize 145 *************************************************************************/ 146 147 class SwDoGetCapitalSize : public SwDoCapitals 148 { 149 protected: 150 Size aTxtSize; 151 public: 152 SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { } 153 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); 154 virtual void Do(); 155 const Size &GetSize() const { return aTxtSize; } 156 }; 157 158 void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * ) 159 { 160 aTxtSize.Height() = 0; 161 aTxtSize.Width() = 0; 162 } 163 164 void SwDoGetCapitalSize::Do() 165 { 166 aTxtSize.Width() += rInf.GetSize().Width(); 167 if( rInf.GetUpper() ) 168 aTxtSize.Height() = rInf.GetSize().Height(); 169 } 170 171 /************************************************************************* 172 * SwSubFont::GetCapitalSize() 173 *************************************************************************/ 174 175 Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf ) 176 { 177 // Start: 178 const long nOldKern = rInf.GetKern(); 179 rInf.SetKern( CheckKerning() ); 180 Point aPos; 181 rInf.SetPos( aPos ); 182 rInf.SetSpace( 0 ); 183 rInf.SetDrawSpace( sal_False ); 184 SwDoGetCapitalSize aDo( rInf ); 185 DoOnCapitals( aDo ); 186 Size aTxtSize( aDo.GetSize() ); 187 188 // End: 189 if( !aTxtSize.Height() ) 190 { 191 SV_STAT( nGetTextSize ); 192 aTxtSize.Height() = short ( rInf.GetpOut()->GetTextHeight() ); 193 } 194 rInf.SetKern( nOldKern ); 195 return aTxtSize; 196 } 197 198 /************************************************************************* 199 * class SwDoGetCapitalBreak 200 *************************************************************************/ 201 202 class SwDoGetCapitalBreak : public SwDoCapitals 203 { 204 protected: 205 xub_StrLen *pExtraPos; 206 long nTxtWidth; 207 xub_StrLen nBreak; 208 public: 209 SwDoGetCapitalBreak( SwDrawTextInfo &rInfo, long nWidth, xub_StrLen *pExtra) 210 : SwDoCapitals ( rInfo ), pExtraPos( pExtra ), nTxtWidth( nWidth ), 211 nBreak( STRING_LEN ) 212 { } 213 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); 214 virtual void Do(); 215 xub_StrLen GetBreak() const { return nBreak; } 216 }; 217 218 void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * ) 219 { 220 } 221 222 void SwDoGetCapitalBreak::Do() 223 { 224 if ( nTxtWidth ) 225 { 226 if ( rInf.GetSize().Width() < nTxtWidth ) 227 nTxtWidth -= rInf.GetSize().Width(); 228 else 229 { 230 xub_StrLen nEnd = rInf.GetEnd(); 231 if( pExtraPos ) 232 { 233 nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth, '-', 234 *pExtraPos, rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() ); 235 if( *pExtraPos > nEnd ) 236 *pExtraPos = nEnd; 237 } 238 else 239 nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth, 240 rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() ); 241 242 if( nBreak > nEnd ) 243 nBreak = nEnd; 244 245 // nBreak may be relative to the display string. It has to be 246 // calculated relative to the original string: 247 if ( GetCapInf() ) 248 { 249 if ( GetCapInf()->nLen != rInf.GetLen() ) 250 nBreak = lcl_CalcCaseMap( *rInf.GetFont(), 251 GetCapInf()->rString, 252 GetCapInf()->nIdx, 253 GetCapInf()->nLen, nBreak ); 254 else 255 nBreak = nBreak + GetCapInf()->nIdx; 256 } 257 258 nTxtWidth = 0; 259 } 260 } 261 } 262 263 /************************************************************************* 264 * SwFont::GetCapitalBreak() 265 *************************************************************************/ 266 267 xub_StrLen SwFont::GetCapitalBreak( ViewShell* pSh, const OutputDevice* pOut, 268 const SwScriptInfo* pScript, const XubString& rTxt, long nTextWidth, 269 xub_StrLen *pExtra, const xub_StrLen nIdx, const xub_StrLen nLen ) 270 { 271 // Start: 272 Point aPos( 0, 0 ); 273 SwDrawTextInfo aInfo(pSh, *(OutputDevice*)pOut, pScript, rTxt, nIdx, nLen, 274 0, sal_False); 275 aInfo.SetPos( aPos ); 276 aInfo.SetSpace( 0 ); 277 aInfo.SetWrong( NULL ); 278 aInfo.SetGrammarCheck( NULL ); 279 aInfo.SetSmartTags( NULL ); // SMARTTAGS 280 aInfo.SetDrawSpace( sal_False ); 281 aInfo.SetKern( CheckKerning() ); 282 aInfo.SetKanaComp( pScript ? 0 : 100 ); 283 aInfo.SetFont( this ); 284 285 SwDoGetCapitalBreak aDo( aInfo, nTextWidth, pExtra ); 286 DoOnCapitals( aDo ); 287 return aDo.GetBreak(); 288 } 289 290 /************************************************************************* 291 * class SwDoDrawCapital 292 *************************************************************************/ 293 294 class SwDoDrawCapital : public SwDoCapitals 295 { 296 protected: 297 SwFntObj *pUpperFnt; 298 SwFntObj *pLowerFnt; 299 public: 300 SwDoDrawCapital( SwDrawTextInfo &rInfo ) : 301 SwDoCapitals( rInfo ) 302 { } 303 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); 304 virtual void Do(); 305 void DrawSpace( Point &rPos ); 306 }; 307 308 void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) 309 { 310 pUpperFnt = pUpperFont; 311 pLowerFnt = pLowerFont; 312 } 313 314 void SwDoDrawCapital::Do() 315 { 316 SV_STAT( nDrawText ); 317 sal_uInt16 nOrgWidth = rInf.GetWidth(); 318 rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) ); 319 if ( rInf.GetUpper() ) 320 pUpperFnt->DrawText( rInf ); 321 else 322 { 323 sal_Bool bOldBullet = rInf.GetBullet(); 324 rInf.SetBullet( sal_False ); 325 pLowerFnt->DrawText( rInf ); 326 rInf.SetBullet( bOldBullet ); 327 } 328 329 ASSERT( pUpperFnt, "No upper font, dying soon!"); 330 rInf.Shift( pUpperFnt->GetFont()->GetOrientation() ); 331 rInf.SetWidth( nOrgWidth ); 332 } 333 334 /************************************************************************* 335 * SwDoDrawCapital::DrawSpace() 336 *************************************************************************/ 337 338 void SwDoDrawCapital::DrawSpace( Point &rPos ) 339 { 340 static sal_Char __READONLY_DATA sDoubleSpace[] = " "; 341 342 long nDiff = rInf.GetPos().X() - rPos.X(); 343 344 Point aPos( rPos ); 345 const sal_Bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() && 346 ! rInf.IsIgnoreFrmRTL(); 347 348 349 if ( bSwitchL2R ) 350 rInf.GetFrm()->SwitchLTRtoRTL( aPos ); 351 352 const sal_uLong nMode = rInf.GetpOut()->GetLayoutMode(); 353 const sal_Bool bBidiPor = ( bSwitchL2R != 354 ( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) ); 355 356 if ( bBidiPor ) 357 nDiff = -nDiff; 358 359 if ( rInf.GetFrm()->IsVertical() ) 360 rInf.GetFrm()->SwitchHorizontalToVertical( aPos ); 361 362 if ( nDiff ) 363 { 364 rInf.ApplyAutoColor(); 365 GetOut().DrawStretchText( aPos, nDiff, 366 XubString( sDoubleSpace, RTL_TEXTENCODING_MS_1252 ), 0, 2 ); 367 } 368 rPos.X() = rInf.GetPos().X() + rInf.GetWidth(); 369 } 370 371 /************************************************************************* 372 * SwSubFont::DrawCapital() 373 *************************************************************************/ 374 375 void SwSubFont::DrawCapital( SwDrawTextInfo &rInf ) 376 { 377 // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist! 378 // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) ); 379 rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE || 380 GetOverline() != UNDERLINE_NONE || 381 GetStrikeout() != STRIKEOUT_NONE ); 382 SwDoDrawCapital aDo( rInf ); 383 DoOnCapitals( aDo ); 384 } 385 386 /************************************************************************* 387 * class SwDoDrawCapital 388 *************************************************************************/ 389 390 class SwDoCapitalCrsrOfst : public SwDoCapitals 391 { 392 protected: 393 SwFntObj *pUpperFnt; 394 SwFntObj *pLowerFnt; 395 xub_StrLen nCrsr; 396 sal_uInt16 nOfst; 397 public: 398 SwDoCapitalCrsrOfst( SwDrawTextInfo &rInfo, const sal_uInt16 nOfs ) : 399 SwDoCapitals( rInfo ), nCrsr( 0 ), nOfst( nOfs ) 400 { } 401 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); 402 virtual void Do(); 403 404 void DrawSpace( const Point &rPos ); 405 inline xub_StrLen GetCrsr(){ return nCrsr; } 406 }; 407 408 void SwDoCapitalCrsrOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) 409 { 410 pUpperFnt = pUpperFont; 411 pLowerFnt = pLowerFont; 412 } 413 414 void SwDoCapitalCrsrOfst::Do() 415 { 416 if ( nOfst ) 417 { 418 if ( nOfst > rInf.GetSize().Width() ) 419 { 420 nOfst = nOfst - sal_uInt16(rInf.GetSize().Width()); 421 nCrsr = nCrsr + rInf.GetLen(); 422 } 423 else 424 { 425 SwDrawTextInfo aDrawInf( rInf.GetShell(), *rInf.GetpOut(), 426 rInf.GetScriptInfo(), 427 rInf.GetText(), 428 rInf.GetIdx(), 429 rInf.GetLen(), 0, sal_False ); 430 aDrawInf.SetOfst( nOfst ); 431 aDrawInf.SetKern( rInf.GetKern() ); 432 aDrawInf.SetKanaComp( rInf.GetKanaComp() ); 433 aDrawInf.SetFrm( rInf.GetFrm() ); 434 aDrawInf.SetFont( rInf.GetFont() ); 435 436 if ( rInf.GetUpper() ) 437 { 438 aDrawInf.SetSpace( 0 ); 439 nCrsr = nCrsr + pUpperFnt->GetCrsrOfst( aDrawInf ); 440 } 441 else 442 { 443 aDrawInf.SetSpace( rInf.GetSpace() ); 444 nCrsr = nCrsr + pLowerFnt->GetCrsrOfst( aDrawInf ); 445 } 446 nOfst = 0; 447 } 448 } 449 } 450 451 /************************************************************************* 452 * SwSubFont::GetCapitalCrsrOfst() 453 *************************************************************************/ 454 455 xub_StrLen SwSubFont::GetCapitalCrsrOfst( SwDrawTextInfo& rInf ) 456 { 457 const long nOldKern = rInf.GetKern(); 458 rInf.SetKern( CheckKerning() ); 459 SwDoCapitalCrsrOfst aDo( rInf, rInf.GetOfst() ); 460 Point aPos; 461 rInf.SetPos( aPos ); 462 rInf.SetDrawSpace( sal_False ); 463 DoOnCapitals( aDo ); 464 rInf.SetKern( nOldKern ); 465 return aDo.GetCrsr(); 466 } 467 468 /************************************************************************* 469 * class SwDoDrawStretchCapital 470 *************************************************************************/ 471 472 class SwDoDrawStretchCapital : public SwDoDrawCapital 473 { 474 const xub_StrLen nStrLen; 475 const sal_uInt16 nCapWidth; 476 const sal_uInt16 nOrgWidth; 477 public: 478 virtual void Do(); 479 480 SwDoDrawStretchCapital( SwDrawTextInfo &rInfo, const sal_uInt16 nCapitalWidth ) 481 : SwDoDrawCapital( rInfo ), 482 nStrLen( rInfo.GetLen() ), 483 nCapWidth( nCapitalWidth ), 484 nOrgWidth( rInfo.GetWidth() ) 485 { } 486 }; 487 488 /************************************************************************* 489 * SwDoDrawStretchCapital 490 *************************************************************************/ 491 492 void SwDoDrawStretchCapital::Do() 493 { 494 SV_STAT( nDrawStretchText ); 495 sal_uInt16 nPartWidth = sal_uInt16(rInf.GetSize().Width()); 496 497 if( rInf.GetLen() ) 498 { 499 // 4023: Kapitaelchen und Kerning. 500 long nDiff = long(nOrgWidth) - long(nCapWidth); 501 if( nDiff ) 502 { 503 nDiff *= rInf.GetLen(); 504 nDiff /= (long) nStrLen; 505 nDiff += nPartWidth; 506 if( 0 < nDiff ) 507 nPartWidth = sal_uInt16(nDiff); 508 } 509 510 rInf.ApplyAutoColor(); 511 512 Point aPos( rInf.GetPos() ); 513 const sal_Bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() && 514 ! rInf.IsIgnoreFrmRTL(); 515 516 if ( bSwitchL2R ) 517 rInf.GetFrm()->SwitchLTRtoRTL( aPos ); 518 519 if ( rInf.GetFrm()->IsVertical() ) 520 rInf.GetFrm()->SwitchHorizontalToVertical( aPos ); 521 522 // Optimierung: 523 if( 1 >= rInf.GetLen() ) 524 GetOut().DrawText( aPos, rInf.GetText(), rInf.GetIdx(), 525 rInf.GetLen() ); 526 else 527 GetOut().DrawStretchText( aPos, nPartWidth, 528 rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ); 529 } 530 ((Point&)rInf.GetPos()).X() += nPartWidth; 531 } 532 533 /************************************************************************* 534 * SwSubFont::DrawStretchCapital() 535 *************************************************************************/ 536 537 void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf ) 538 { 539 // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist! 540 // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) ); 541 542 if( rInf.GetLen() == STRING_LEN ) 543 rInf.SetLen( rInf.GetText().Len() ); 544 545 const Point& rOldPos = rInf.GetPos(); 546 const sal_uInt16 nCapWidth = (sal_uInt16)( GetCapitalSize( rInf ).Width() ); 547 rInf.SetPos( rOldPos ); 548 549 rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE || 550 GetOverline() != UNDERLINE_NONE || 551 GetStrikeout() != STRIKEOUT_NONE ); 552 SwDoDrawStretchCapital aDo( rInf, nCapWidth ); 553 DoOnCapitals( aDo ); 554 } 555 556 /************************************************************************* 557 * SwSubFont::DoOnCapitals() const 558 *************************************************************************/ 559 560 // JP 22.8.2001 - global optimization off - Bug 91245 / 91223 561 #ifdef _MSC_VER 562 #pragma optimize("g",off) 563 #endif 564 565 void SwSubFont::DoOnCapitals( SwDoCapitals &rDo ) 566 { 567 ASSERT( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" ); 568 569 Size aPartSize; 570 long nKana = 0; 571 const XubString aTxt( CalcCaseMap( rDo.GetInf().GetText() ) ); 572 xub_StrLen nMaxPos = Min( sal_uInt16(rDo.GetInf().GetText().Len() 573 - rDo.GetInf().GetIdx()), rDo.GetInf().GetLen() ); 574 rDo.GetInf().SetLen( nMaxPos ); 575 576 const XubString& rOldText = rDo.GetInf().GetText(); 577 rDo.GetInf().SetText( aTxt ); 578 rDo.GetInf().SetSize( aPartSize ); 579 xub_StrLen nPos = rDo.GetInf().GetIdx(); 580 xub_StrLen nOldPos = nPos; 581 nMaxPos = nMaxPos + nPos; 582 583 // #107816# 584 // Look if the length of the original text and the ToUpper-converted 585 // text is different. If yes, do special handling. 586 XubString aNewText; 587 SwCapitalInfo aCapInf( rOldText ); 588 sal_Bool bCaseMapLengthDiffers( aTxt.Len() != rOldText.Len() ); 589 if ( bCaseMapLengthDiffers ) 590 rDo.SetCapInf( aCapInf ); 591 592 SwFntObj *pOldLast = pLastFont; 593 SwFntAccess *pBigFontAccess = NULL; 594 SwFntObj *pBigFont; 595 SwFntAccess *pSpaceFontAccess = NULL; 596 SwFntObj *pSpaceFont = NULL; 597 598 const void *pMagic2 = NULL; 599 sal_uInt16 nIndex2 = 0; 600 SwSubFont aFont( *this ); 601 Point aStartPos( rDo.GetInf().GetPos() ); 602 603 const sal_Bool bTextLines = aFont.GetUnderline() != UNDERLINE_NONE 604 || aFont.GetOverline() != UNDERLINE_NONE 605 || aFont.GetStrikeout() != STRIKEOUT_NONE; 606 const sal_Bool bWordWise = bTextLines && aFont.IsWordLineMode() && 607 rDo.GetInf().GetDrawSpace(); 608 const long nTmpKern = rDo.GetInf().GetKern(); 609 610 if ( bTextLines ) 611 { 612 if ( bWordWise ) 613 { 614 aFont.SetWordLineMode( sal_False ); 615 pSpaceFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont, 616 rDo.GetInf().GetShell() ); 617 pSpaceFont = pSpaceFontAccess->Get(); 618 } 619 else 620 pSpaceFont = pLastFont; 621 622 // Wir basteln uns einen Font fuer die Grossbuchstaben: 623 aFont.SetUnderline( UNDERLINE_NONE ); 624 aFont.SetOverline( UNDERLINE_NONE ); 625 aFont.SetStrikeout( STRIKEOUT_NONE ); 626 pMagic2 = NULL; 627 nIndex2 = 0; 628 pBigFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont, 629 rDo.GetInf().GetShell() ); 630 pBigFont = pBigFontAccess->Get(); 631 } 632 else 633 pBigFont = pLastFont; 634 635 // Hier entsteht der Kleinbuchstabenfont: 636 aFont.SetProportion( sal_uInt8( (aFont.GetPropr()*KAPITAELCHENPROP) / 100L) ); 637 pMagic2 = NULL; 638 nIndex2 = 0; 639 SwFntAccess *pSmallFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont, 640 rDo.GetInf().GetShell() ); 641 SwFntObj *pSmallFont = pSmallFontAccess->Get(); 642 643 rDo.Init( pBigFont, pSmallFont ); 644 OutputDevice* pOutSize = pSmallFont->GetPrt(); 645 if( !pOutSize ) 646 pOutSize = &rDo.GetOut(); 647 OutputDevice* pOldOut = &rDo.GetOut(); 648 649 const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage() 650 ? LANGUAGE_SYSTEM : GetLanguage(); 651 652 if( nPos < nMaxPos ) 653 { 654 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfCharBlock( rOldText, nPos, 655 pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER); 656 if( nPos == STRING_LEN ) 657 nPos = nOldPos; 658 else if( nPos > nMaxPos ) 659 nPos = nMaxPos; 660 } 661 662 while( nOldPos < nMaxPos ) 663 { 664 665 // The lower ones... 666 if( nOldPos != nPos ) 667 { 668 SV_STAT( nGetTextSize ); 669 pLastFont = pSmallFont; 670 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); 671 672 // #107816#, #i14820# 673 if( bCaseMapLengthDiffers ) 674 { 675 // Build an own 'changed' string for the given part of the 676 // source string and use it. That new string may differ in length 677 // from the source string. 678 const XubString aSnippet( rOldText, nOldPos, nPos - nOldPos); 679 aNewText = CalcCaseMap( aSnippet ); 680 aCapInf.nIdx = nOldPos; 681 aCapInf.nLen = nPos - nOldPos; 682 rDo.GetInf().SetIdx( 0 ); 683 rDo.GetInf().SetLen( aNewText.Len() ); 684 rDo.GetInf().SetText( aNewText ); 685 } 686 else 687 { 688 rDo.GetInf().SetIdx( nOldPos ); 689 rDo.GetInf().SetLen( nPos - nOldPos ); 690 } 691 692 rDo.GetInf().SetUpper( sal_False ); 693 rDo.GetInf().SetOut( *pOutSize ); 694 aPartSize = pSmallFont->GetTextSize( rDo.GetInf() ); 695 nKana += rDo.GetInf().GetKanaDiff(); 696 rDo.GetInf().SetOut( *pOldOut ); 697 if( nTmpKern && nPos < nMaxPos ) 698 aPartSize.Width() += nTmpKern; 699 rDo.Do(); 700 nOldPos = nPos; 701 } 702 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharBlock( rOldText, nPos, 703 pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER); 704 if( nPos == STRING_LEN || nPos > nMaxPos ) 705 nPos = nMaxPos; 706 ASSERT( nPos, "nextCharBlock not implemented?" ); 707 #ifdef DBG_UTIL 708 if( !nPos ) 709 nPos = nMaxPos; 710 #endif 711 // The upper ones... 712 if( nOldPos != nPos ) 713 { 714 const long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR; 715 716 do 717 { 718 rDo.GetInf().SetUpper( sal_True ); 719 pLastFont = pBigFont; 720 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); 721 xub_StrLen nTmp; 722 if( bWordWise ) 723 { 724 nTmp = nOldPos; 725 while( nTmp < nPos && CH_BLANK == rOldText.GetChar( nTmp ) ) 726 ++nTmp; 727 if( nOldPos < nTmp ) 728 { 729 pLastFont = pSpaceFont; 730 pLastFont->SetDevFont( rDo.GetInf().GetShell(), 731 rDo.GetOut() ); 732 ((SwDoDrawCapital&)rDo).DrawSpace( aStartPos ); 733 pLastFont = pBigFont; 734 pLastFont->SetDevFont( rDo.GetInf().GetShell(), 735 rDo.GetOut() ); 736 737 // #107816#, #i14820# 738 if( bCaseMapLengthDiffers ) 739 { 740 // Build an own 'changed' string for the given part of the 741 // source string and use it. That new string may differ in length 742 // from the source string. 743 const XubString aSnippet( rOldText, nOldPos, nTmp - nOldPos); 744 aNewText = CalcCaseMap( aSnippet ); 745 aCapInf.nIdx = nOldPos; 746 aCapInf.nLen = nTmp - nOldPos; 747 rDo.GetInf().SetIdx( 0 ); 748 rDo.GetInf().SetLen( aNewText.Len() ); 749 rDo.GetInf().SetText( aNewText ); 750 } 751 else 752 { 753 rDo.GetInf().SetIdx( nOldPos ); 754 rDo.GetInf().SetLen( nTmp - nOldPos ); 755 } 756 757 rDo.GetInf().SetOut( *pOutSize ); 758 aPartSize = pBigFont->GetTextSize( rDo.GetInf() ); 759 nKana += rDo.GetInf().GetKanaDiff(); 760 rDo.GetInf().SetOut( *pOldOut ); 761 if( nSpaceAdd ) 762 aPartSize.Width() += nSpaceAdd * ( nTmp - nOldPos ); 763 if( nTmpKern && nPos < nMaxPos ) 764 aPartSize.Width() += nTmpKern; 765 rDo.Do(); 766 aStartPos = rDo.GetInf().GetPos(); 767 nOldPos = nTmp; 768 } 769 770 while( nTmp < nPos && CH_BLANK != rOldText.GetChar( nTmp ) ) 771 ++nTmp; 772 } 773 else 774 nTmp = nPos; 775 if( nTmp > nOldPos ) 776 { 777 // #107816#, #i14820# 778 if( bCaseMapLengthDiffers ) 779 { 780 // Build an own 'changed' string for the given part of the 781 // source string and use it. That new string may differ in length 782 // from the source string. 783 const XubString aSnippet( rOldText, nOldPos, nTmp - nOldPos); 784 aNewText = CalcCaseMap( aSnippet ); 785 aCapInf.nIdx = nOldPos; 786 aCapInf.nLen = nTmp - nOldPos; 787 rDo.GetInf().SetIdx( 0 ); 788 rDo.GetInf().SetLen( aNewText.Len() ); 789 rDo.GetInf().SetText( aNewText ); 790 } 791 else 792 { 793 rDo.GetInf().SetIdx( nOldPos ); 794 rDo.GetInf().SetLen( nTmp - nOldPos ); 795 } 796 797 rDo.GetInf().SetOut( *pOutSize ); 798 aPartSize = pBigFont->GetTextSize( rDo.GetInf() ); 799 nKana += rDo.GetInf().GetKanaDiff(); 800 rDo.GetInf().SetOut( *pOldOut ); 801 if( !bWordWise && rDo.GetInf().GetSpace() ) 802 { 803 for( xub_StrLen nI = nOldPos; nI < nPos; ++nI ) 804 { 805 if( CH_BLANK == rOldText.GetChar( nI ) ) 806 aPartSize.Width() += nSpaceAdd; 807 } 808 } 809 if( nTmpKern && nPos < nMaxPos ) 810 aPartSize.Width() += nTmpKern; 811 rDo.Do(); 812 nOldPos = nTmp; 813 } 814 } while( nOldPos != nPos ); 815 } 816 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfCharBlock( rOldText, nPos, 817 pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER); 818 if( nPos == STRING_LEN || nPos > nMaxPos ) 819 nPos = nMaxPos; 820 ASSERT( nPos, "endOfCharBlock not implemented?" ); 821 #ifdef DBG_UTIL 822 if( !nPos ) 823 nPos = nMaxPos; 824 #endif 825 } 826 827 // Aufraeumen: 828 if( pBigFont != pOldLast ) 829 delete pBigFontAccess; 830 831 if( bTextLines ) 832 { 833 if( rDo.GetInf().GetDrawSpace() ) 834 { 835 pLastFont = pSpaceFont; 836 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); 837 ( (SwDoDrawCapital&) rDo ).DrawSpace( aStartPos ); 838 } 839 if ( bWordWise ) 840 delete pSpaceFontAccess; 841 } 842 pLastFont = pOldLast; 843 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); 844 845 delete pSmallFontAccess; 846 rDo.GetInf().SetText( rOldText ); 847 rDo.GetInf().SetKanaDiff( nKana ); 848 } 849 850 // JP 22.8.2001 - global optimization off - Bug 91245 / 91223 851 #ifdef _MSC_VER 852 #pragma optimize("g",on) 853 #endif 854 855 856