LCOV - code coverage report
Current view: top level - sw/source/core/text - itrpaint.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 255 301 84.7 %
Date: 2014-11-03 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 SwTxtPainter::CheckSpecialUnderline
      61      267061 : bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
      62             : {
      63      282755 :     return UNDERLINE_NONE == rFnt.GetUnderline() ||
      64       46782 :            rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
      65       45458 :            rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
      66       29400 :            rPor.IsHolePortion() ||
      67       29400 :           ( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
      68      309397 :            rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
      69      280465 :            SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
      70             : }
      71             : 
      72      119602 : void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
      73             : {
      74      119602 :     CtorInitTxtCursor( pNewFrm, pNewInf );
      75      119602 :     pInf = pNewInf;
      76      119602 :     SwFont *pMyFnt = GetFnt();
      77      119602 :     GetInfo().SetFont( pMyFnt );
      78             : #if OSL_DEBUG_LEVEL > 1
      79             :     if( ALIGN_BASELINE != pMyFnt->GetAlign() )
      80             :     {
      81             :         OSL_ENSURE( ALIGN_BASELINE == pMyFnt->GetAlign(),
      82             :                 "+SwTxtPainter::CTOR: font alignment revolution" );
      83             :         pMyFnt->SetAlign( ALIGN_BASELINE );
      84             :     }
      85             : #endif
      86      119602 :     bPaintDrop = false;
      87      119602 : }
      88             : 
      89       44922 : SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
      90             : {
      91       44922 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
      92       44922 :     GetInfo().SetPaintOfst( 0 );
      93       44922 :     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       44922 :     if( nPaintOfst && pCurr->Width() )
     100             :     {
     101       42483 :         SwLinePortion *pLast = 0;
     102             :         // 7529 und 4757: nicht <= nPaintOfst
     103       86860 :         while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
     104             :                        < nPaintOfst )
     105             :         {
     106        1894 :             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        1894 :                 pPor->Move( GetInfo() );
     117        1894 :             pLast = pPor;
     118        1894 :             pPor = pPor->GetPortion();
     119             :         }
     120             : 
     121             :         // 7529: bei PostIts auch pLast returnen.
     122       42483 :         if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
     123             :         {
     124           0 :             pPor = pLast;
     125           0 :             GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
     126             :         }
     127             :     }
     128       44922 :     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       44922 : void SwTxtPainter::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       44922 :     GetAdjusted();
     148       44922 :     GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
     149       44922 :     GetInfo().ResetSpaceIdx();
     150       44922 :     GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
     151       44922 :     GetInfo().ResetKanaIdx();
     152             :     // The size of the frame
     153       44922 :     GetInfo().SetIdx( GetStart() );
     154       44922 :     GetInfo().SetPos( GetTopLeft() );
     155             : 
     156       44922 :     const bool bDrawInWindow = GetInfo().OnWin();
     157             : 
     158             :     // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
     159       44922 :     const bool bEndPor = GetInfo().GetOpt().IsParagraph() && GetInfo().GetTxt().isEmpty();
     160             : 
     161       44922 :     SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
     162             : 
     163             :     // Optimization!
     164       44922 :     const SwTwips nMaxRight = std::min( rPaint.Right(), Right() );
     165       44922 :     const SwTwips nTmpLeft = GetInfo().X();
     166       44922 :     if( !bEndPor && nTmpLeft >= nMaxRight )
     167        2204 :         return;
     168             : 
     169             :     // DropCaps!
     170             :     // 7538: of course for the printer, too
     171       44698 :     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       44698 :         bPaintDrop = pPor == pCurr->GetFirstPortion()
     177       44698 :                      && GetDropLines() >= GetLineNr();
     178             :     }
     179             : 
     180             :     sal_uInt16 nTmpHeight, nTmpAscent;
     181       44698 :     CalcAscentAndHeight( nTmpAscent, nTmpHeight );
     182             : 
     183             :     // bClip decides if there's a need to clip
     184             :     // Das Ganze muss vor der Retusche stehen
     185             : 
     186       44698 :     bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
     187       44698 :     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       54622 :         if( GetInfo().GetPos().X() < rPaint.Left() ||
     194       32343 :             GetInfo().GetPos().Y() < rPaint.Top() ||
     195       12445 :             GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
     196             :         {
     197        8534 :             bClip = false;
     198        8534 :             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       44698 :     OutputDevice* pOut = GetInfo().GetOut();
     211       44698 :     Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
     212       44698 :     if ( aPnt1.X() < rPaint.Left() )
     213       21591 :         aPnt1.X() = rPaint.Left();
     214       44698 :     if ( aPnt1.Y() < rPaint.Top() )
     215        4589 :         aPnt1.Y() = rPaint.Top();
     216       44698 :     Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
     217       89396 :                  GetInfo().GetPos().Y() + nTmpHeight );
     218       44698 :     if ( aPnt2.X() > rPaint.Right() )
     219           0 :         aPnt2.X() = rPaint.Right();
     220       44698 :     if ( aPnt2.Y() > rPaint.Bottom() )
     221       19576 :         aPnt2.Y() = rPaint.Bottom();
     222             : 
     223       44698 :     const SwRect aLineRect( aPnt1, aPnt2 );
     224             : 
     225       44698 :     if( pCurr->IsClipping() )
     226             :     {
     227         216 :         rClip.ChgClip( aLineRect, pFrm );
     228         216 :         bClip = false;
     229             :     }
     230             : 
     231       44698 :     if( !pPor && !bEndPor )
     232        1756 :         return;
     233             : 
     234             :     // Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
     235             :     // if no special vertical alignment is used,
     236             :     // we calculate Y value for the whole line
     237       42942 :     SwTextGridItem const*const pGrid(GetGridItem(GetTxtFrm()->FindPageFrm()));
     238             :     const bool bAdjustBaseLine =
     239       42942 :         GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
     240       42942 :         ( 0 != pGrid );
     241       42942 :     const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
     242       42942 :     if ( ! bAdjustBaseLine )
     243       42876 :         GetInfo().Y( nLineBaseLine );
     244             : 
     245             :     // 7529: Pre-paint post-its
     246       42942 :     if( GetInfo().OnWin() && pPor && !pPor->Width() )
     247             :     {
     248        2319 :         SeekAndChg( GetInfo() );
     249             : 
     250        2319 :         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        2319 :             pPor->PrePaint( GetInfo(), pPor );
     264             :     }
     265             : 
     266             :     // 7923: EndPortions output chars, too, that's why we change the font
     267       42942 :     if( bEndPor )
     268           0 :         SeekStartAndChg( GetInfo() );
     269             : 
     270       42942 :     const bool bRest = pCurr->IsRest();
     271       42942 :     bool bFirst = true;
     272             : 
     273       42942 :     SwArrowPortion *pArrow = NULL;
     274             :     // Reference portion for the paragraph end portion
     275       42942 :     SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
     276             : 
     277      144984 :     while( pPor )
     278             :     {
     279       59100 :         bool bSeeked = true;
     280       59100 :         GetInfo().SetLen( pPor->GetLen() );
     281             : 
     282       59100 :         const SwTwips nOldY = GetInfo().Y();
     283             : 
     284       59100 :         if ( bAdjustBaseLine )
     285             :         {
     286         306 :             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         306 :             if ( pPor->Width() && pPor->InTxtGrp() )
     293         216 :                 pEndTempl = pPor;
     294             :         }
     295             : 
     296             :         // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
     297             : 
     298             :         // 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
     299             :         // Portion an, dies wird durch SeekAndChgBefore vermieden:
     300       59100 :         if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
     301         144 :             SeekAndChgBefore( GetInfo() );
     302       58956 :         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       58956 :         else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
     310       45858 :             SeekAndChg( GetInfo() );
     311       13098 :         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       13098 :             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       77695 :         if( bClip &&
     329       18595 :             GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
     330             :         {
     331        4001 :             bClip = false;
     332        4001 :             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
     333             :         }
     334             : 
     335             :         // Portions, which lay "below" the text like post-its
     336       59100 :         SwLinePortion *pNext = pPor->GetPortion();
     337       59100 :         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        5202 :             if ( !bSeeked )
     343        1984 :                 SeekAndChg( GetInfo() );
     344        5202 :             pNext->PrePaint( GetInfo(), pPor );
     345             :         }
     346             : 
     347             :         // We calculate a separate font for underlining.
     348       59100 :         CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
     349       59100 :         SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
     350       59100 :         if ( pUnderLineFnt )
     351             :         {
     352         124 :             const Point aTmpPoint( GetInfo().X(),
     353             :                                    bAdjustBaseLine ?
     354          24 :                                    pUnderLineFnt->GetPos().Y() :
     355         272 :                                    nLineBaseLine );
     356         124 :             pUnderLineFnt->SetPos( aTmpPoint );
     357             :         }
     358             : 
     359             :         // in extended input mode we do not want a common underline font.
     360       59100 :         SwUnderlineFont* pOldUnderLineFnt = 0;
     361       59100 :         if ( GetRedln() && GetRedln()->ExtOn() )
     362             :         {
     363           0 :             pOldUnderLineFnt = GetInfo().GetUnderFnt();
     364           0 :             GetInfo().SetUnderFnt( 0 );
     365             :         }
     366             : 
     367             :         {
     368             :             // #i16816# tagged pdf support
     369       59100 :             Por_Info aPorInfo( *pPor, *this );
     370       59100 :             SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
     371             : 
     372       59100 :             if( pPor->IsMultiPortion() )
     373         380 :                 PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
     374             :             else
     375       58720 :                 pPor->Paint( GetInfo() );
     376             :         }
     377             : 
     378             :         // reset underline font
     379       59100 :         if ( pOldUnderLineFnt )
     380           0 :             GetInfo().SetUnderFnt( pOldUnderLineFnt );
     381             : 
     382             :         // reset (for special vertical alignment)
     383       59100 :         GetInfo().Y( nOldY );
     384             : 
     385       59100 :         if( GetFnt()->IsURL() && pPor->InTxtGrp() )
     386           0 :             GetInfo().NotifyURL( *pPor );
     387             : 
     388       59100 :         bFirst &= !pPor->GetLen();
     389       59100 :         if( pNext || !pPor->IsMarginPortion() )
     390       56284 :             pPor->Move( GetInfo() );
     391       59100 :         if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
     392           0 :             pArrow = (SwArrowPortion*)pPor;
     393             : 
     394         562 :         pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
     395             :                // #i16816# tagged pdf support
     396           0 :                ( GetInfo().GetVsh() &&
     397           0 :                  GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
     398           0 :                  pNext && pNext->IsHolePortion() ) ?
     399             :                pNext :
     400      118200 :                0;
     401             :     }
     402             : 
     403             :     // delete underline font
     404       42942 :     delete GetInfo().GetUnderFnt();
     405       42942 :     GetInfo().SetUnderFnt( 0 );
     406             : 
     407             :     // paint remaining stuff
     408       42942 :     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       42538 :         const SwTwips nOldY = GetInfo().Y();
     414             : 
     415      103018 :         if( !GetNextLine() &&
     416       53826 :             GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() &&
     417       60480 :             GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
     418           0 :             GetInfo().GetIdx() >= GetInfo().GetTxt().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       42538 :         if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() )
     431             :         {
     432             :             const bool bNextUndersized =
     433       57664 :                 ( GetTxtFrm()->GetNext() &&
     434       15138 :                   0 == GetTxtFrm()->GetNext()->Prt().Height() &&
     435       42562 :                   GetTxtFrm()->GetNext()->IsTxtFrm() &&
     436       42550 :                   ((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
     437             : 
     438       42538 :             if( bUnderSz || bNextUndersized )
     439             :             {
     440         566 :                 if ( bAdjustBaseLine )
     441           0 :                     GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
     442             : 
     443         566 :                 if( pArrow )
     444           0 :                     GetInfo().DrawRedArrow( *pArrow );
     445             : 
     446             :                 // GetInfo().Y() must be current baseline
     447         566 :                 SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
     448         690 :                 if( ( nDiff > 0 &&
     449         236 :                       ( GetEnd() < GetInfo().GetTxt().getLength() ||
     450         704 :                         ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
     451         112 :                     (nDiff >= 0 && bNextUndersized) )
     452             : 
     453             :                 {
     454          24 :                     SwArrowPortion aArrow( GetInfo() );
     455          24 :                     GetInfo().DrawRedArrow( aArrow );
     456             :                 }
     457             : 
     458         566 :                 GetInfo().Y( nOldY );
     459             :             }
     460             :         }
     461             :     }
     462             : 
     463       42942 :     if( pCurr->IsClipping() )
     464         216 :         rClip.ChgClip( rPaint, pFrm );
     465             : }
     466             : 
     467       60138 : void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
     468             :                                           long nAdjustBaseLine )
     469             : {
     470             :     // Check if common underline should not be continued
     471       60138 :     if ( IsUnderlineBreak( *pPor, *pFnt ) )
     472             :     {
     473             :         // delete underline font
     474       59006 :         delete GetInfo().GetUnderFnt();
     475       59006 :         GetInfo().SetUnderFnt( 0 );
     476       59006 :         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        4528 :     if ( GetInfo().GetUnderFnt() &&
     483         256 :         GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
     484        3780 :         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        1132 :     MultiSelection aUnderMulti( Range( 0, GetInfo().GetTxt().getLength() ) );
     491        1132 :     const SwFont* pParaFnt = GetAttrHandler().GetFont();
     492        1132 :     if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
     493         154 :         aUnderMulti.SelectAll();
     494             : 
     495        1132 :     if( HasHints() )
     496             :     {
     497        4502 :         for ( size_t nTmp = 0; nTmp < pHints->GetStartCount(); ++nTmp )
     498             :         {
     499        3602 :             SwTxtAttr* const pTxtAttr = pHints->GetStart( nTmp );
     500             : 
     501             :             const SvxUnderlineItem* pItem =
     502        3602 :                     static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));
     503             : 
     504        3602 :             if ( pItem )
     505             :             {
     506        1630 :                 const sal_Int32 nSt = pTxtAttr->GetStart();
     507        1630 :                 const sal_Int32 nEnd = *pTxtAttr->GetEnd();
     508        1630 :                 if( nEnd > nSt )
     509             :                 {
     510        1566 :                     const bool bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
     511        1566 :                     aUnderMulti.Select( Range( nSt, nEnd - 1 ), bUnderSelect );
     512             :                 }
     513             :             }
     514             :         }
     515             :     }
     516             : 
     517        1132 :     const sal_Int32 nIndx = GetInfo().GetIdx();
     518        1132 :     long nUnderStart = 0;
     519        1132 :     long nUnderEnd = 0;
     520        1132 :     const size_t nCnt = aUnderMulti.GetRangeCount();
     521             : 
     522             :     // find the underline range the current portion is contained in
     523        2038 :     for( size_t i = 0; i < nCnt; ++i )
     524             :     {
     525         974 :         const Range& rRange = aUnderMulti.GetRange( i );
     526         974 :         if( nUnderEnd == rRange.Min() )
     527         518 :             nUnderEnd = rRange.Max();
     528         456 :         else if( nIndx >= rRange.Min() )
     529             :         {
     530         388 :             nUnderStart = rRange.Min();
     531         388 :             nUnderEnd = rRange.Max();
     532             :         }
     533             :         else
     534          68 :             break;
     535             :     }
     536             : 
     537             :     // restrict start and end to current line
     538        1132 :     if ( GetStart() > nUnderStart )
     539          68 :         nUnderStart = GetStart();
     540             : 
     541        1132 :     if ( GetEnd() && GetEnd() <= nUnderEnd )
     542         114 :         nUnderEnd = GetEnd() - 1;
     543             : 
     544             :     // calculate the new common underline font
     545        1132 :     SwFont* pUnderlineFnt = 0;
     546        1132 :     Point aCommonBaseLine;
     547             : 
     548             :     // check, if underlining is not isolated
     549        1132 :     if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
     550             :     {
     551             :         // here starts the algorithm for calculating the underline font
     552         270 :         SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
     553         270 :         SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
     554         270 :                           rScriptInfo );
     555             : 
     556         270 :         sal_Int32 nTmpIdx = nIndx;
     557         270 :         sal_uLong nSumWidth = 0;
     558         270 :         sal_uLong nSumHeight = 0;
     559         270 :         sal_uLong nBold = 0;
     560         270 :         sal_uInt16 nMaxBaseLineOfst = 0;
     561         270 :         int nNumberOfPortions = 0;
     562             : 
     563        1088 :         while( nTmpIdx <= nUnderEnd && pPor )
     564             :         {
     565        2568 :             if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
     566        1850 :                 pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
     567        1868 :                 pPor->IsHolePortion() ||
     568         584 :                 ( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
     569          94 :                 break;
     570             : 
     571         548 :             aIter.Seek( nTmpIdx );
     572             : 
     573        1096 :             if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
     574         548 :                  SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
     575           0 :                 break;
     576             : 
     577         548 :             if ( !aIter.GetFnt()->GetEscapement() )
     578             :             {
     579         474 :                 nSumWidth += pPor->Width();
     580         474 :                 const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
     581             : 
     582             :                 // If we do not have a common baseline we take the baseline
     583             :                 // and the font of the lowest portion.
     584         474 :                 if ( nAdjustBaseLine )
     585             :                 {
     586          84 :                     const sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
     587          84 :                     if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
     588             :                     {
     589          24 :                         nMaxBaseLineOfst = nTmpBaseLineOfst;
     590          24 :                         nSumHeight = nFontHeight;
     591             :                     }
     592             :                 }
     593             :                 // in horizontal layout we build a weighted sum of the heights
     594             :                 else
     595         390 :                     nSumHeight += pPor->Width() * nFontHeight;
     596             : 
     597         474 :                 if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
     598          40 :                     nBold += pPor->Width();
     599             :             }
     600             : 
     601         548 :             ++nNumberOfPortions;
     602             : 
     603         548 :             nTmpIdx += pPor->GetLen();
     604         548 :             pPor = pPor->GetPortion();
     605             :         }
     606             : 
     607             :         // resulting height
     608         270 :         if ( nNumberOfPortions > 1 && nSumWidth )
     609             :         {
     610             :             const sal_uLong nNewFontHeight = nAdjustBaseLine ?
     611             :                                          nSumHeight :
     612         128 :                                          nSumHeight / nSumWidth;
     613             : 
     614         128 :             pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
     615             : 
     616             :             // font height
     617         128 :             const sal_uInt8 nActual = pUnderlineFnt->GetActual();
     618         128 :             pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
     619         256 :                                           nNewFontHeight ), nActual );
     620             : 
     621             :             // font weight
     622         128 :             if ( 2 * nBold > nSumWidth )
     623           2 :                 pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
     624             :             else
     625         126 :                 pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
     626             : 
     627             :             // common base line
     628         128 :             aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
     629         270 :         }
     630             :     }
     631             : 
     632             :     // an escaped redlined portion should also have a special underlining
     633        1132 :     if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
     634           0 :         GetRedln()->ChkSpecialUnderline() )
     635           0 :         pUnderlineFnt = new SwFont( *pFnt );
     636             : 
     637        1132 :     delete GetInfo().GetUnderFnt();
     638             : 
     639        1132 :     if ( pUnderlineFnt )
     640             :     {
     641         128 :         pUnderlineFnt->SetProportion( 100 );
     642         128 :         pUnderlineFnt->SetEscapement( 0 );
     643         128 :         pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
     644         128 :         pUnderlineFnt->SetOverline( UNDERLINE_NONE );
     645         128 :         const Color aFillColor( COL_TRANSPARENT );
     646         128 :         pUnderlineFnt->SetFillColor( aFillColor );
     647             : 
     648         128 :         GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
     649         256 :                                                      aCommonBaseLine ) );
     650             :     }
     651             :     else
     652             :         // I'm sorry, we do not have a special underlining font for you.
     653        1004 :         GetInfo().SetUnderFnt( 0 );
     654         270 : }
     655             : 
     656             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10