LCOV - code coverage report
Current view: top level - sw/source/core/text - itrpaint.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 253 297 85.2 %
Date: 2015-06-13 12:38:46 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "hintids.hxx"
      21             : #include "flyfrm.hxx"
      22             : #include "viewopt.hxx"
      23             : #include "txtatr.hxx"
      24             : #include <tools/multisel.hxx>
      25             : #include <editeng/escapementitem.hxx>
      26             : #include <editeng/udlnitem.hxx>
      27             : #include <editeng/lrspitem.hxx>
      28             : #include <txtinet.hxx>
      29             : #include <fchrfmt.hxx>
      30             : #include <frmatr.hxx>
      31             : #include <sfx2/printer.hxx>
      32             : #include <fmtfld.hxx>
      33             : #include <fldbas.hxx>
      34             : #include <rootfrm.hxx>
      35             : #include <pagefrm.hxx>
      36             : #include <pagedesc.hxx>
      37             : #include <tgrditem.hxx>
      38             : 
      39             : #include <EnhancedPDFExportHelper.hxx>
      40             : 
      41             : #include "flyfrms.hxx"
      42             : #include "viewsh.hxx"
      43             : #include "itrpaint.hxx"
      44             : #include "txtfrm.hxx"
      45             : #include "txtfly.hxx"
      46             : #include "swfont.hxx"
      47             : #include "txtpaint.hxx"
      48             : #include "portab.hxx"
      49             : #include "porfly.hxx"
      50             : #include "porfld.hxx"
      51             : #include "frmfmt.hxx"
      52             : #include "txatbase.hxx"
      53             : #include "charfmt.hxx"
      54             : #include "redlnitr.hxx"
      55             : #include "porrst.hxx"
      56             : #include "pormulti.hxx"
      57             : 
      58             : // Returns, if we have an underline breaking situation
      59             : // Adding some more conditions here means you also have to change them
      60             : // in SwTextPainter::CheckSpecialUnderline
      61      165313 : bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
      62             : {
      63      173435 :     return UNDERLINE_NONE == rFnt.GetUnderline() ||
      64       24216 :            rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
      65       23522 :            rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
      66       15186 :            rPor.IsHolePortion() ||
      67       15186 :           ( rPor.IsMultiPortion() && ! static_cast<const SwMultiPortion&>(rPor).IsBidi() ) ||
      68      187422 :            rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
      69      172386 :            SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
      70             : }
      71             : 
      72       69633 : void SwTextPainter::CtorInitTextPainter( SwTextFrm *pNewFrm, SwTextPaintInfo *pNewInf )
      73             : {
      74       69633 :     CtorInitTextCursor( pNewFrm, pNewInf );
      75       69633 :     pInf = pNewInf;
      76       69633 :     SwFont *pMyFnt = GetFnt();
      77       69633 :     GetInfo().SetFont( pMyFnt );
      78             : #if OSL_DEBUG_LEVEL > 1
      79             :     if( ALIGN_BASELINE != pMyFnt->GetAlign() )
      80             :     {
      81             :         OSL_ENSURE( ALIGN_BASELINE == pMyFnt->GetAlign(),
      82             :                 "+SwTextPainter::CTOR: font alignment revolution" );
      83             :         pMyFnt->SetAlign( ALIGN_BASELINE );
      84             :     }
      85             : #endif
      86       69633 :     bPaintDrop = false;
      87       69633 : }
      88             : 
      89       21486 : SwLinePortion *SwTextPainter::CalcPaintOfst( const SwRect &rPaint )
      90             : {
      91       21486 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
      92       21486 :     GetInfo().SetPaintOfst( 0 );
      93       21486 :     SwTwips nPaintOfst = rPaint.Left();
      94             : 
      95             :     // nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
      96             :     // nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
      97             :     // const sal_uInt16 nLeftMar = sal_uInt16(GetLeftMargin());
      98             :     // 8310: painten von LineBreaks in leeren Zeilen.
      99       21486 :     if( nPaintOfst && pCurr->Width() )
     100             :     {
     101       20532 :         SwLinePortion *pLast = 0;
     102             :         // 7529 und 4757: nicht <= nPaintOfst
     103       41097 :         while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
     104             :                        < nPaintOfst )
     105             :         {
     106          33 :             if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
     107             :             {
     108           0 :                 long nTmp = GetInfo().X() +pPor->Width() +
     109           0 :                     pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
     110           0 :                 if( nTmp + (pPor->Height()/2) >= nPaintOfst )
     111           0 :                     break;
     112           0 :                 GetInfo().X( nTmp );
     113           0 :                 GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
     114             :             }
     115             :             else
     116          33 :                 pPor->Move( GetInfo() );
     117          33 :             pLast = pPor;
     118          33 :             pPor = pPor->GetPortion();
     119             :         }
     120             : 
     121             :         // 7529: bei PostIts auch pLast returnen.
     122       20532 :         if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
     123             :         {
     124           0 :             pPor = pLast;
     125           0 :             GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
     126             :         }
     127             :     }
     128       21486 :     return pPor;
     129             : }
     130             : 
     131             : // Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
     132             : // 1) DrawRect auf die ganze Zeile und die DrawText hinterher
     133             : //    (objektiv schnell, subjektiv langsam).
     134             : // 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
     135             : //    ausgefuehrt (objektiv langsam, subjektiv schnell).
     136             : // Da der User in der Regel subjektiv urteilt, wird die 2. Methode
     137             : // als Default eingestellt.
     138       21486 : void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
     139             :                                  const bool bUnderSz )
     140             : {
     141             : #if OSL_DEBUG_LEVEL > 1
     142             : //    sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
     143             : //    sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
     144             : #endif
     145             : 
     146             :     // Adjustierung ggf. nachholen
     147       21486 :     GetAdjusted();
     148       21486 :     GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
     149       21486 :     GetInfo().ResetSpaceIdx();
     150       21486 :     GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
     151       21486 :     GetInfo().ResetKanaIdx();
     152             :     // The size of the frame
     153       21486 :     GetInfo().SetIdx( GetStart() );
     154       21486 :     GetInfo().SetPos( GetTopLeft() );
     155             : 
     156       21486 :     const bool bDrawInWindow = GetInfo().OnWin();
     157             : 
     158             :     // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
     159       21486 :     const bool bEndPor = GetInfo().GetOpt().IsParagraph() && GetInfo().GetText().isEmpty();
     160             : 
     161       21486 :     SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
     162             : 
     163             :     // Optimization!
     164       21486 :     const SwTwips nMaxRight = std::min( rPaint.Right(), Right() );
     165       21486 :     const SwTwips nTmpLeft = GetInfo().X();
     166       21486 :     if( !bEndPor && nTmpLeft >= nMaxRight )
     167         105 :         return;
     168             : 
     169             :     // DropCaps!
     170             :     // 7538: of course for the printer, too
     171       21436 :     if( !bPaintDrop )
     172             :     {
     173             :         // 8084: Optimization, less painting
     174             :         // AMA: By 8084 7538 has been revived
     175             :         // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
     176       21436 :         bPaintDrop = pPor == pCurr->GetFirstPortion()
     177       21436 :                      && GetDropLines() >= GetLineNr();
     178             :     }
     179             : 
     180             :     sal_uInt16 nTmpHeight, nTmpAscent;
     181       21436 :     CalcAscentAndHeight( nTmpAscent, nTmpHeight );
     182             : 
     183             :     // bClip decides if there's a need to clip
     184             :     // Das Ganze muss vor der Retusche stehen
     185             : 
     186       21436 :     bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
     187       21436 :     if( bClip && pPor )
     188             :     {
     189             :         // Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
     190             :         // muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
     191             :         // in der folgenden Ausgabeschleife...
     192             : 
     193       48994 :         if( GetInfo().GetPos().X() < rPaint.Left() ||
     194       27984 :             GetInfo().GetPos().Y() < rPaint.Top() ||
     195       11515 :             GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
     196             :         {
     197        5791 :             bClip = false;
     198        5791 :             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
     199             :         }
     200             : #if OSL_DEBUG_LEVEL > 1
     201             :         static bool bClipAlways = false;
     202             :         if( bClip && bClipAlways )
     203             :         {   bClip = false;
     204             :             rClip.ChgClip( rPaint );
     205             :         }
     206             : #endif
     207             :     }
     208             : 
     209             :     // Alignment
     210       21436 :     OutputDevice* pOut = GetInfo().GetOut();
     211       21436 :     Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
     212       21436 :     if ( aPnt1.X() < rPaint.Left() )
     213         641 :         aPnt1.X() = rPaint.Left();
     214       21436 :     if ( aPnt1.Y() < rPaint.Top() )
     215        4762 :         aPnt1.Y() = rPaint.Top();
     216       21436 :     Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
     217       42872 :                  GetInfo().GetPos().Y() + nTmpHeight );
     218       21436 :     if ( aPnt2.X() > rPaint.Right() )
     219           0 :         aPnt2.X() = rPaint.Right();
     220       21436 :     if ( aPnt2.Y() > rPaint.Bottom() )
     221       12495 :         aPnt2.Y() = rPaint.Bottom();
     222             : 
     223       21436 :     const SwRect aLineRect( aPnt1, aPnt2 );
     224             : 
     225       21436 :     if( pCurr->IsClipping() )
     226             :     {
     227         151 :         rClip.ChgClip( aLineRect, pFrm );
     228         151 :         bClip = false;
     229             :     }
     230             : 
     231       21436 :     if( !pPor && !bEndPor )
     232           5 :         return;
     233             : 
     234             :     // Baseline-Ausgabe auch bei nicht-TextPortions (vgl. TabPor mit Fill)
     235             :     // if no special vertical alignment is used,
     236             :     // we calculate Y value for the whole line
     237       21431 :     SwTextGridItem const*const pGrid(GetGridItem(GetTextFrm()->FindPageFrm()));
     238             :     const bool bAdjustBaseLine =
     239       21431 :         GetLineInfo().HasSpecialAlign( GetTextFrm()->IsVertical() ) ||
     240       21431 :         ( 0 != pGrid );
     241       21431 :     const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
     242       21431 :     if ( ! bAdjustBaseLine )
     243       21342 :         GetInfo().Y( nLineBaseLine );
     244             : 
     245             :     // 7529: Pre-paint post-its
     246       21431 :     if( GetInfo().OnWin() && pPor && !pPor->Width() )
     247             :     {
     248         929 :         SeekAndChg( GetInfo() );
     249             : 
     250         929 :         if( bAdjustBaseLine )
     251             :         {
     252           0 :             const SwTwips nOldY = GetInfo().Y();
     253             : 
     254           0 :             GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, 0,
     255           0 :                 GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
     256           0 :                 GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
     257           0 :             ) );
     258             : 
     259           0 :             pPor->PrePaint( GetInfo(), pPor );
     260           0 :             GetInfo().Y( nOldY );
     261             :         }
     262             :         else
     263         929 :             pPor->PrePaint( GetInfo(), pPor );
     264             :     }
     265             : 
     266             :     // 7923: EndPortions output chars, too, that's why we change the font
     267       21431 :     if( bEndPor )
     268           0 :         SeekStartAndChg( GetInfo() );
     269             : 
     270       21431 :     const bool bRest = pCurr->IsRest();
     271       21431 :     bool bFirst = true;
     272             : 
     273       21431 :     SwArrowPortion *pArrow = NULL;
     274             :     // Reference portion for the paragraph end portion
     275       21431 :     SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
     276             : 
     277       77098 :     while( pPor )
     278             :     {
     279       34236 :         bool bSeeked = true;
     280       34236 :         GetInfo().SetLen( pPor->GetLen() );
     281             : 
     282       34236 :         const SwTwips nOldY = GetInfo().Y();
     283             : 
     284       34236 :         if ( bAdjustBaseLine )
     285             :         {
     286         371 :             GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, pPor ) );
     287             : 
     288             :             // we store the last portion, because a possible paragraph
     289             :             // end character has the same font as this portion
     290             :             // (only in special vertical alignment case, otherwise the first
     291             :             // portion of the line is used)
     292         371 :             if ( pPor->Width() && pPor->InTextGrp() )
     293         270 :                 pEndTempl = pPor;
     294             :         }
     295             : 
     296             :         // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
     297             : 
     298             :         // 6168: Der Rest einer FieldPortion zog sich die Attribute der naechsten
     299             :         // Portion an, dies wird durch SeekAndChgBefore vermieden:
     300       34236 :         if( ( bRest && pPor->InFieldGrp() && !pPor->GetLen() ) )
     301         193 :             SeekAndChgBefore( GetInfo() );
     302       34043 :         else if ( pPor->IsQuoVadisPortion() )
     303             :         {
     304           0 :             sal_Int32 nOffset = GetInfo().GetIdx();
     305           0 :             SeekStartAndChg( GetInfo(), true );
     306           0 :             if( GetRedln() && pCurr->HasRedline() )
     307           0 :                 GetRedln()->Seek( *pFnt, nOffset, 0 );
     308             :         }
     309       34043 :         else if( pPor->InTextGrp() || pPor->InFieldGrp() || pPor->InTabGrp() )
     310       21748 :             SeekAndChg( GetInfo() );
     311       12295 :         else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
     312             :         {
     313             :             // Paragraph symbols should have the same fon as the paragraph in fron of them,
     314             :             // except for the case that there's redlining in the paragraph
     315           0 :             if( GetRedln() )
     316           0 :                 SeekAndChg( GetInfo() );
     317             :             else
     318           0 :                 SeekAndChgBefore( GetInfo() );
     319             :         }
     320             :         else
     321       12295 :             bSeeked = false;
     322             : 
     323             :         // bRest = false;
     324             : 
     325             :         // Wenn das Ende der Portion hinausragt, wird geclippt.
     326             :         // Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
     327             :         // damit die TTF-"f" nicht im Seitenrand haengen...
     328       50689 :         if( bClip &&
     329       16453 :             GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
     330             :         {
     331        1619 :             bClip = false;
     332        1619 :             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
     333             :         }
     334             : 
     335             :         // Portions, which lay "below" the text like post-its
     336       34236 :         SwLinePortion *pNext = pPor->GetPortion();
     337       34236 :         if( GetInfo().OnWin() && pNext && !pNext->Width() )
     338             :         {
     339             :             // Fix 11289: Fields were omitted here because of Last!=Owner during
     340             :             // loading Brief.sdw. Now the fields are allowed again,
     341             :             // by bSeeked Last!=Owner is being avoided.
     342        3224 :             if ( !bSeeked )
     343        1346 :                 SeekAndChg( GetInfo() );
     344        3224 :             pNext->PrePaint( GetInfo(), pPor );
     345             :         }
     346             : 
     347             :         // We calculate a separate font for underlining.
     348       34236 :         CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
     349       34236 :         SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
     350       34236 :         if ( pUnderLineFnt )
     351             :         {
     352          65 :             const Point aTmpPoint( GetInfo().X(),
     353             :                                    bAdjustBaseLine ?
     354          12 :                                    pUnderLineFnt->GetPos().Y() :
     355         142 :                                    nLineBaseLine );
     356          65 :             pUnderLineFnt->SetPos( aTmpPoint );
     357             :         }
     358             : 
     359             :         // in extended input mode we do not want a common underline font.
     360       34236 :         SwUnderlineFont* pOldUnderLineFnt = 0;
     361       34236 :         if ( GetRedln() && GetRedln()->ExtOn() )
     362             :         {
     363           0 :             pOldUnderLineFnt = GetInfo().GetUnderFnt();
     364           0 :             GetInfo().SetUnderFnt( 0 );
     365             :         }
     366             : 
     367             :         {
     368             :             // #i16816# tagged pdf support
     369       34236 :             Por_Info aPorInfo( *pPor, *this );
     370       34236 :             SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
     371             : 
     372       34236 :             if( pPor->IsMultiPortion() )
     373         169 :                 PaintMultiPortion( rPaint, static_cast<SwMultiPortion&>(*pPor) );
     374             :             else
     375       34067 :                 pPor->Paint( GetInfo() );
     376             :         }
     377             : 
     378             :         // reset underline font
     379       34236 :         if ( pOldUnderLineFnt )
     380           0 :             GetInfo().SetUnderFnt( pOldUnderLineFnt );
     381             : 
     382             :         // reset (for special vertical alignment)
     383       34236 :         GetInfo().Y( nOldY );
     384             : 
     385       34236 :         if( GetFnt()->IsURL() && pPor->InTextGrp() )
     386           0 :             GetInfo().NotifyURL( *pPor );
     387             : 
     388       34236 :         bFirst &= !pPor->GetLen();
     389       34236 :         if( pNext || !pPor->IsMarginPortion() )
     390       32462 :             pPor->Move( GetInfo() );
     391       34236 :         if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
     392           0 :             pArrow = static_cast<SwArrowPortion*>(pPor);
     393             : 
     394         549 :         pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
     395             :                // #i16816# tagged pdf support
     396           2 :                ( GetInfo().GetVsh() &&
     397           1 :                  GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
     398           0 :                  pNext && pNext->IsHolePortion() ) ?
     399             :                pNext :
     400       68471 :                0;
     401             :     }
     402             : 
     403             :     // delete underline font
     404       21431 :     delete GetInfo().GetUnderFnt();
     405       21431 :     GetInfo().SetUnderFnt( 0 );
     406             : 
     407             :     // paint remaining stuff
     408       21431 :     if( bDrawInWindow )
     409             :     {
     410             :         // If special vertical alignment is enabled, GetInfo().Y() is the
     411             :         // top of the current line. Therefore is has to be adjusted for
     412             :         // the painting of the remaining stuff. We first store the old value.
     413       21053 :         const SwTwips nOldY = GetInfo().Y();
     414             : 
     415       54037 :         if( !GetNextLine() &&
     416       35793 :             GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() &&
     417       32984 :             GetInfo().GetOpt().IsParagraph() && !GetTextFrm()->GetFollow() &&
     418           0 :             GetInfo().GetIdx() >= GetInfo().GetText().getLength() )
     419             :         {
     420           0 :             const SwTmpEndPortion aEnd( *pEndTempl );
     421           0 :             GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
     422             : 
     423           0 :             if ( bAdjustBaseLine )
     424           0 :                 GetInfo().Y( GetInfo().GetPos().Y()
     425           0 :                            + AdjustBaseLine( *pCurr, &aEnd ) );
     426             : 
     427           0 :             aEnd.Paint( GetInfo() );
     428           0 :             GetInfo().Y( nOldY );
     429             :         }
     430       21053 :         if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() )
     431             :         {
     432             :             const bool bNextUndersized =
     433       27821 :                 ( GetTextFrm()->GetNext() &&
     434        6774 :                   0 == GetTextFrm()->GetNext()->Prt().Height() &&
     435       21065 :                   GetTextFrm()->GetNext()->IsTextFrm() &&
     436       21059 :                   static_cast<SwTextFrm*>(GetTextFrm()->GetNext())->IsUndersized() ) ;
     437             : 
     438       21053 :             if( bUnderSz || bNextUndersized )
     439             :             {
     440          64 :                 if ( bAdjustBaseLine )
     441           0 :                     GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
     442             : 
     443          64 :                 if( pArrow )
     444           0 :                     GetInfo().DrawRedArrow( *pArrow );
     445             : 
     446             :                 // GetInfo().Y() must be current baseline
     447          64 :                 SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTextFrm()->Frm().Bottom();
     448          96 :                 if( ( nDiff > 0 &&
     449          64 :                       ( GetEnd() < GetInfo().GetText().getLength() ||
     450         111 :                         ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
     451          32 :                     (nDiff >= 0 && bNextUndersized) )
     452             : 
     453             :                 {
     454           6 :                     SwArrowPortion aArrow( GetInfo() );
     455           6 :                     GetInfo().DrawRedArrow( aArrow );
     456             :                 }
     457             : 
     458          64 :                 GetInfo().Y( nOldY );
     459             :             }
     460             :         }
     461             :     }
     462             : 
     463       21431 :     if( pCurr->IsClipping() )
     464         151 :         rClip.ChgClip( rPaint, pFrm );
     465             : }
     466             : 
     467       34688 : void SwTextPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
     468             :                                           long nAdjustBaseLine )
     469             : {
     470             :     // Check if common underline should not be continued
     471       34688 :     if ( IsUnderlineBreak( *pPor, *pFnt ) )
     472             :     {
     473             :         // delete underline font
     474       34065 :         delete GetInfo().GetUnderFnt();
     475       34065 :         GetInfo().SetUnderFnt( 0 );
     476       34065 :         return;
     477             :     }
     478             : 
     479             :     // If current underline matches the common underline font, we continue
     480             :     // to use the common underline font.
     481             :     // Bug 120769:Color of underline display wrongly
     482        2492 :     if ( GetInfo().GetUnderFnt() &&
     483         134 :         GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
     484        2070 :         GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != Color(COL_AUTO) )
     485           0 :         return;
     486             :     //Bug 120769(End)
     487             : 
     488             :     OSL_ENSURE( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
     489             :             "CheckSpecialUnderline without underlined font" );
     490         623 :     MultiSelection aUnderMulti( Range( 0, GetInfo().GetText().getLength() ) );
     491         623 :     const SwFont* pParaFnt = GetAttrHandler().GetFont();
     492         623 :     if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
     493          83 :         aUnderMulti.SelectAll();
     494             : 
     495         623 :     if( HasHints() )
     496             :     {
     497        2436 :         for ( size_t nTmp = 0; nTmp < pHints->GetStartCount(); ++nTmp )
     498             :         {
     499        1929 :             SwTextAttr* const pTextAttr = pHints->GetStart( nTmp );
     500             : 
     501             :             const SvxUnderlineItem* pItem =
     502        1929 :                     static_cast<const SvxUnderlineItem*>(CharFormat::GetItem( *pTextAttr, RES_CHRATR_UNDERLINE ));
     503             : 
     504        1929 :             if ( pItem )
     505             :             {
     506         837 :                 const sal_Int32 nSt = pTextAttr->GetStart();
     507         837 :                 const sal_Int32 nEnd = *pTextAttr->GetEnd();
     508         837 :                 if( nEnd > nSt )
     509             :                 {
     510         805 :                     const bool bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
     511         805 :                     aUnderMulti.Select( Range( nSt, nEnd - 1 ), bUnderSelect );
     512             :                 }
     513             :             }
     514             :         }
     515             :     }
     516             : 
     517         623 :     const sal_Int32 nIndx = GetInfo().GetIdx();
     518         623 :     long nUnderEnd = 0;
     519         623 :     const size_t nCnt = aUnderMulti.GetRangeCount();
     520             : 
     521             :     // find the underline range the current portion is contained in
     522        1097 :     for( size_t i = 0; i < nCnt; ++i )
     523             :     {
     524         508 :         const Range& rRange = aUnderMulti.GetRange( i );
     525         508 :         if( nUnderEnd == rRange.Min() )
     526         270 :             nUnderEnd = rRange.Max();
     527         238 :         else if( nIndx >= rRange.Min() )
     528             :         {
     529         204 :             nUnderEnd = rRange.Max();
     530             :         }
     531             :         else
     532          34 :             break;
     533             :     }
     534             : 
     535         623 :     if ( GetEnd() && GetEnd() <= nUnderEnd )
     536          54 :         nUnderEnd = GetEnd() - 1;
     537             : 
     538             :     // calculate the new common underline font
     539         623 :     SwFont* pUnderlineFnt = 0;
     540         623 :     Point aCommonBaseLine;
     541             : 
     542             :     // check, if underlining is not isolated
     543         623 :     if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
     544             :     {
     545             :         // here starts the algorithm for calculating the underline font
     546         147 :         SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
     547         147 :         SwAttrIter aIter( *GetInfo().GetTextFrm()->GetTextNode(),
     548         147 :                           rScriptInfo );
     549             : 
     550         147 :         sal_Int32 nTmpIdx = nIndx;
     551         147 :         sal_uLong nSumWidth = 0;
     552         147 :         sal_uLong nSumHeight = 0;
     553         147 :         sal_uLong nBold = 0;
     554         147 :         sal_uInt16 nMaxBaseLineOfst = 0;
     555         147 :         int nNumberOfPortions = 0;
     556             : 
     557         586 :         while( nTmpIdx <= nUnderEnd && pPor )
     558             :         {
     559        1392 :             if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
     560         997 :                 pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
     561        1006 :                 pPor->IsHolePortion() ||
     562         310 :                 ( pPor->IsMultiPortion() && ! static_cast<const SwMultiPortion*>(pPor)->IsBidi() ) )
     563          56 :                 break;
     564             : 
     565         292 :             aIter.Seek( nTmpIdx );
     566             : 
     567         584 :             if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
     568         292 :                  SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
     569           0 :                 break;
     570             : 
     571         292 :             if ( !aIter.GetFnt()->GetEscapement() )
     572             :             {
     573         246 :                 nSumWidth += pPor->Width();
     574         246 :                 const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
     575             : 
     576             :                 // If we do not have a common baseline we take the baseline
     577             :                 // and the font of the lowest portion.
     578         246 :                 if ( nAdjustBaseLine )
     579             :                 {
     580          42 :                     const sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
     581          42 :                     if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
     582             :                     {
     583          12 :                         nMaxBaseLineOfst = nTmpBaseLineOfst;
     584          12 :                         nSumHeight = nFontHeight;
     585             :                     }
     586             :                 }
     587             :                 // in horizontal layout we build a weighted sum of the heights
     588             :                 else
     589         204 :                     nSumHeight += pPor->Width() * nFontHeight;
     590             : 
     591         246 :                 if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
     592          20 :                     nBold += pPor->Width();
     593             :             }
     594             : 
     595         292 :             ++nNumberOfPortions;
     596             : 
     597         292 :             nTmpIdx += pPor->GetLen();
     598         292 :             pPor = pPor->GetPortion();
     599             :         }
     600             : 
     601             :         // resulting height
     602         147 :         if ( nNumberOfPortions > 1 && nSumWidth )
     603             :         {
     604             :             const sal_uLong nNewFontHeight = nAdjustBaseLine ?
     605             :                                          nSumHeight :
     606          67 :                                          nSumHeight / nSumWidth;
     607             : 
     608          67 :             pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
     609             : 
     610             :             // font height
     611          67 :             const sal_uInt8 nActual = pUnderlineFnt->GetActual();
     612          67 :             pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
     613         134 :                                           nNewFontHeight ), nActual );
     614             : 
     615             :             // font weight
     616          67 :             if ( 2 * nBold > nSumWidth )
     617           1 :                 pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
     618             :             else
     619          66 :                 pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
     620             : 
     621             :             // common base line
     622          67 :             aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
     623         147 :         }
     624             :     }
     625             : 
     626             :     // an escaped redlined portion should also have a special underlining
     627         623 :     if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
     628           0 :         GetRedln()->ChkSpecialUnderline() )
     629           0 :         pUnderlineFnt = new SwFont( *pFnt );
     630             : 
     631         623 :     delete GetInfo().GetUnderFnt();
     632             : 
     633         623 :     if ( pUnderlineFnt )
     634             :     {
     635          67 :         pUnderlineFnt->SetProportion( 100 );
     636          67 :         pUnderlineFnt->SetEscapement( 0 );
     637          67 :         pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
     638          67 :         pUnderlineFnt->SetOverline( UNDERLINE_NONE );
     639          67 :         const Color aFillColor( COL_TRANSPARENT );
     640          67 :         pUnderlineFnt->SetFillColor( aFillColor );
     641             : 
     642          67 :         GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
     643         134 :                                                      aCommonBaseLine ) );
     644             :     }
     645             :     else
     646             :         // I'm sorry, we do not have a special underlining font for you.
     647         556 :         GetInfo().SetUnderFnt( 0 );
     648         177 : }
     649             : 
     650             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11