LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/text - itrpaint.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 184 304 60.5 %
Date: 2012-12-27 Functions: 5 5 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"     // SwFlyInCntFrm
      22             : #include "viewopt.hxx"  // SwViewOptions
      23             : #include "txtatr.hxx"  // SwINetFmt
      24             : #include <tools/multisel.hxx>
      25             : #include <editeng/escpitem.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 <fmtftn.hxx>
      33             : #include <fmtfld.hxx>
      34             : #include <fldbas.hxx>      // SwField
      35             : #include <rootfrm.hxx>
      36             : #include <pagefrm.hxx>
      37             : #include <pagedesc.hxx> // SwPageDesc
      38             : #include <tgrditem.hxx>
      39             : 
      40             : // #i12836# enhanced pdf export
      41             : #include <EnhancedPDFExportHelper.hxx>
      42             : 
      43             : 
      44             : #include "flyfrms.hxx"
      45             : #include "viewsh.hxx"
      46             : #include "itrpaint.hxx"
      47             : #include "txtfrm.hxx"   // pFrm
      48             : #include "txtfly.hxx"
      49             : #include "swfont.hxx"
      50             : #include "txtpaint.hxx"
      51             : #include "portab.hxx"   // SwTabPortion::IsFilled
      52             : #include "porfly.hxx"     // SwFlyCntPortion
      53             : #include "porfld.hxx"   // SwGrfNumPortion
      54             : #include "frmfmt.hxx"   // LRSpace
      55             : #include "txatbase.hxx" // SwTxtAttr
      56             : #include "charfmt.hxx"  // SwFmtCharFmt
      57             : #include "redlnitr.hxx" // SwRedlineItr
      58             : #include "porrst.hxx"   // SwArrowPortion
      59             : #include "pormulti.hxx"
      60             : 
      61             : /*************************************************************************
      62             :  *                  IsUnderlineBreak
      63             :  *
      64             :  * Returns, if we have an underline breaking situation
      65             :  * Adding some more conditions here means you also have to change them
      66             :  * in SwTxtPainter::CheckSpecialUnderline
      67             :  *************************************************************************/
      68        1781 : sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
      69             : {
      70        1781 :     return UNDERLINE_NONE == rFnt.GetUnderline() ||
      71          48 :            rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
      72          48 :            rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
      73          24 :            rPor.IsHolePortion() ||
      74          24 :           ( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
      75          48 :            rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
      76        1973 :            SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
      77             : }
      78             : 
      79             : /*************************************************************************
      80             :  *                  SwTxtPainter::CtorInitTxtPainter()
      81             :  *************************************************************************/
      82        1169 : void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
      83             : {
      84        1169 :     CtorInitTxtCursor( pNewFrm, pNewInf );
      85        1169 :     pInf = pNewInf;
      86        1169 :     SwFont *pMyFnt = GetFnt();
      87        1169 :     GetInfo().SetFont( pMyFnt );
      88             : #if OSL_DEBUG_LEVEL > 1
      89             :     if( ALIGN_BASELINE != pMyFnt->GetAlign() )
      90             :     {
      91             :         OSL_ENSURE( ALIGN_BASELINE == pMyFnt->GetAlign(),
      92             :                 "+SwTxtPainter::CTOR: font alignment revolution" );
      93             :         pMyFnt->SetAlign( ALIGN_BASELINE );
      94             :     }
      95             : #endif
      96        1169 :     bPaintDrop = sal_False;
      97        1169 : }
      98             : 
      99             : 
     100             : /*************************************************************************
     101             :  *                    SwTxtPainter::CalcPaintOfst()
     102             :  *************************************************************************/
     103         512 : SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
     104             : {
     105         512 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
     106         512 :     GetInfo().SetPaintOfst( 0 );
     107         512 :     SwTwips nPaintOfst = rPaint.Left();
     108             : 
     109             :     // nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
     110             :     // nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
     111             :     // const KSHORT nLeftMar = KSHORT(GetLeftMargin());
     112             :     // 8310: painten von LineBreaks in leeren Zeilen.
     113         512 :     if( nPaintOfst && pCurr->Width() )
     114             :     {
     115         478 :         SwLinePortion *pLast = 0;
     116             :         // 7529 und 4757: nicht <= nPaintOfst
     117         956 :         while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
     118             :                        < nPaintOfst )
     119             :         {
     120           0 :             if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
     121             :             {
     122           0 :                 long nTmp = GetInfo().X() +pPor->Width() +
     123           0 :                     pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
     124           0 :                 if( nTmp + (pPor->Height()/2) >= nPaintOfst )
     125           0 :                     break;
     126           0 :                 GetInfo().X( nTmp );
     127           0 :                 GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
     128             :             }
     129             :             else
     130           0 :                 pPor->Move( GetInfo() );
     131           0 :             pLast = pPor;
     132           0 :             pPor = pPor->GetPortion();
     133             :         }
     134             : 
     135             :         // 7529: bei PostIts auch pLast returnen.
     136         478 :         if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
     137             :         {
     138           0 :             pPor = pLast;
     139           0 :             GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
     140             :         }
     141             :     }
     142         512 :     return pPor;
     143             : }
     144             : 
     145             : /*************************************************************************
     146             :  *                    SwTxtPainter::DrawTextLine()
     147             :  *
     148             :  * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
     149             :  * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
     150             :  *    (objektiv schnell, subjektiv langsam).
     151             :  * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
     152             :  *    ausgefuehrt (objektiv langsam, subjektiv schnell).
     153             :  * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
     154             :  * als Default eingestellt.
     155             :  *************************************************************************/
     156         512 : void SwTxtPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
     157             :                                  const sal_Bool bUnderSz )
     158             : {
     159             : #if OSL_DEBUG_LEVEL > 1
     160             : //    sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
     161             : //    sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
     162             : #endif
     163             : 
     164             :     // Adjustierung ggf. nachholen
     165         512 :     GetAdjusted();
     166         512 :     GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
     167         512 :     GetInfo().ResetSpaceIdx();
     168         512 :     GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
     169         512 :     GetInfo().ResetKanaIdx();
     170             :     // Die Groesse des Frames
     171         512 :     GetInfo().SetIdx( GetStart() );
     172         512 :     GetInfo().SetPos( GetTopLeft() );
     173             : 
     174         512 :     const bool bDrawInWindow = GetInfo().OnWin();
     175             : 
     176             :     // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
     177         512 :     const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
     178             : 
     179         512 :     SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
     180             : 
     181             :     // Optimierung!
     182         512 :     const SwTwips nMaxRight = Min( rPaint.Right(), Right() );
     183         512 :     const SwTwips nTmpLeft = GetInfo().X();
     184         512 :     if( !bEndPor && nTmpLeft >= nMaxRight )
     185             :         return;
     186             : 
     187             :     // DropCaps!
     188             :     // 7538: natuerlich auch auf dem Drucker
     189         512 :     if( !bPaintDrop )
     190             :     {
     191             :         // 8084: Optimierung, weniger Painten.
     192             :         // AMA: Durch 8084 wurde 7538 wiederbelebt!
     193             :         // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
     194         512 :         bPaintDrop = pPor == pCurr->GetFirstPortion()
     195         512 :                      && GetDropLines() >= GetLineNr();
     196             :     }
     197             : 
     198             :     KSHORT nTmpHeight, nTmpAscent;
     199         512 :     CalcAscentAndHeight( nTmpAscent, nTmpHeight );
     200             : 
     201             :     // bClip entscheidet darueber, ob geclippt werden muss.
     202             :     // Das Ganze muss vor der Retusche stehen
     203             : 
     204         512 :     bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
     205         512 :     if( bClip && pPor )
     206             :     {
     207             :         // Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
     208             :         // muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
     209             :         // in der folgenden Ausgabeschleife...
     210             : 
     211        1891 :         if( GetInfo().GetPos().X() < rPaint.Left() ||
     212         476 :             GetInfo().GetPos().Y() < rPaint.Top() ||
     213         938 :             GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
     214             :         {
     215          18 :             bClip = false;
     216          18 :             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
     217             :         }
     218             : #if OSL_DEBUG_LEVEL > 1
     219             :         static bool bClipAlways = false;
     220             :         if( bClip && bClipAlways )
     221             :         {   bClip = false;
     222             :             rClip.ChgClip( rPaint );
     223             :         }
     224             : #endif
     225             :     }
     226             : 
     227             :     // Alignment:
     228         512 :     OutputDevice* pOut = GetInfo().GetOut();
     229         512 :     Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
     230         512 :     if ( aPnt1.X() < rPaint.Left() )
     231           1 :         aPnt1.X() = rPaint.Left();
     232         512 :     if ( aPnt1.Y() < rPaint.Top() )
     233           8 :         aPnt1.Y() = rPaint.Top();
     234        1024 :     Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
     235        1536 :                  GetInfo().GetPos().Y() + nTmpHeight );
     236         512 :     if ( aPnt2.X() > rPaint.Right() )
     237           0 :         aPnt2.X() = rPaint.Right();
     238         512 :     if ( aPnt2.Y() > rPaint.Bottom() )
     239         448 :         aPnt2.Y() = rPaint.Bottom();
     240             : 
     241         512 :     const SwRect aLineRect( aPnt1, aPnt2 );
     242             : 
     243         512 :     if( pCurr->IsClipping() )
     244             :     {
     245           0 :         rClip.ChgClip( aLineRect, pFrm );
     246           0 :         bClip = false;
     247             :     }
     248             : 
     249         512 :     if( !pPor && !bEndPor )
     250             :         return;
     251             : 
     252             :     // Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
     253             :     // if no special vertical alignment is used,
     254             :     // we calculate Y value for the whole line
     255         512 :     GETGRID( GetTxtFrm()->FindPageFrm() )
     256             :     const bool bAdjustBaseLine =
     257         512 :         GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
     258         512 :         ( 0 != pGrid );
     259         512 :     const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
     260         512 :     if ( ! bAdjustBaseLine )
     261         512 :         GetInfo().Y( nLineBaseLine );
     262             : 
     263             :     // 7529: PostIts prepainten
     264         512 :     if( GetInfo().OnWin() && pPor && !pPor->Width() )
     265             :     {
     266          34 :         SeekAndChg( GetInfo() );
     267             : 
     268          34 :         if( bAdjustBaseLine )
     269             :         {
     270           0 :             const SwTwips nOldY = GetInfo().Y();
     271             : 
     272           0 :             GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, 0,
     273           0 :                 GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
     274           0 :                 GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
     275           0 :             ) );
     276             : 
     277           0 :             pPor->PrePaint( GetInfo(), pPor );
     278           0 :             GetInfo().Y( nOldY );
     279             :         }
     280             :         else
     281          34 :             pPor->PrePaint( GetInfo(), pPor );
     282             :     }
     283             : 
     284             :     // 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
     285         512 :     if( bEndPor )
     286           0 :         SeekStartAndChg( GetInfo() );
     287             : 
     288         512 :     sal_Bool bRest = pCurr->IsRest();
     289         512 :     sal_Bool bFirst = sal_True;
     290             : 
     291         512 :     SwArrowPortion *pArrow = NULL;
     292             :     // Reference portion for the paragraph end portion
     293         512 :     SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
     294             : 
     295        1799 :     while( pPor )
     296             :     {
     297         775 :         sal_Bool bSeeked = sal_True;
     298         775 :         GetInfo().SetLen( pPor->GetLen() );
     299             : 
     300         775 :         const SwTwips nOldY = GetInfo().Y();
     301             : 
     302         775 :         if ( bAdjustBaseLine )
     303             :         {
     304           0 :             GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, pPor ) );
     305             : 
     306             :             // we store the last portion, because a possible paragraph
     307             :             // end character has the same font as this portion
     308             :             // (only in special vertical alignment case, otherwise the first
     309             :             // portion of the line is used)
     310           0 :             if ( pPor->Width() && pPor->InTxtGrp() )
     311           0 :                 pEndTempl = pPor;
     312             :         }
     313             : 
     314             :         // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
     315             : 
     316             :         // 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
     317             :         // Portion an, dies wird durch SeekAndChgBefore vermieden:
     318         775 :         if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
     319          32 :             SeekAndChgBefore( GetInfo() );
     320         743 :         else if ( pPor->IsQuoVadisPortion() )
     321             :         {
     322           0 :             xub_StrLen nOffset = GetInfo().GetIdx();
     323           0 :             SeekStartAndChg( GetInfo(), sal_True );
     324           0 :             if( GetRedln() && pCurr->HasRedline() )
     325           0 :                 GetRedln()->Seek( *pFnt, nOffset, 0 );
     326             :         }
     327         743 :         else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
     328         511 :             SeekAndChg( GetInfo() );
     329         232 :         else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
     330             :         {
     331             :             // Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
     332             :             // haben, es sei denn, es gibt Redlining in dem Absatz.
     333           0 :             if( GetRedln() )
     334           0 :                 SeekAndChg( GetInfo() );
     335             :             else
     336           0 :                 SeekAndChgBefore( GetInfo() );
     337             :         }
     338             :         else
     339         232 :             bSeeked = sal_False;
     340             : 
     341             : //      bRest = sal_False;
     342             : 
     343             :         // Wenn das Ende der Portion hinausragt, wird geclippt.
     344             :         // Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
     345             :         // damit die TTF-"f" nicht im Seitenrand haengen...
     346        2143 :         if( bClip &&
     347        1368 :             GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
     348             :         {
     349          56 :             bClip = false;
     350          56 :             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
     351             :         }
     352             : 
     353             :         // Portions, die "unter" dem Text liegen wie PostIts
     354         775 :         SwLinePortion *pNext = pPor->GetPortion();
     355         775 :         if( GetInfo().OnWin() && pNext && !pNext->Width() )
     356             :         {
     357             :             // Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
     358             :             // Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
     359             :             // durch bSeeked wird Last!=Owner vermieden.
     360          25 :             if ( !bSeeked )
     361           8 :                 SeekAndChg( GetInfo() );
     362          25 :             pNext->PrePaint( GetInfo(), pPor );
     363             :         }
     364             : 
     365             :         // We calculate a separate font for underlining.
     366         775 :         CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
     367         775 :         SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
     368         775 :         if ( pUnderLineFnt )
     369             :         {
     370           0 :             const Point aTmpPoint( GetInfo().X(),
     371             :                                    bAdjustBaseLine ?
     372           0 :                                    pUnderLineFnt->GetPos().Y() :
     373           0 :                                    nLineBaseLine );
     374           0 :             pUnderLineFnt->SetPos( aTmpPoint );
     375             :         }
     376             : 
     377             : 
     378             :         // in extended input mode we do not want a common underline font.
     379         775 :         SwUnderlineFont* pOldUnderLineFnt = 0;
     380         775 :         if ( GetRedln() && GetRedln()->ExtOn() )
     381             :         {
     382           0 :             pOldUnderLineFnt = GetInfo().GetUnderFnt();
     383           0 :             GetInfo().SetUnderFnt( 0 );
     384             :         }
     385             : 
     386             :         {
     387             :             // #i16816# tagged pdf support
     388         775 :             Por_Info aPorInfo( *pPor, *this );
     389         775 :             SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
     390             : 
     391         775 :             if( pPor->IsMultiPortion() )
     392           2 :                 PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
     393             :             else
     394         773 :                 pPor->Paint( GetInfo() );
     395             :         }
     396             : 
     397             :         // reset underline font
     398         775 :         if ( pOldUnderLineFnt )
     399           0 :             GetInfo().SetUnderFnt( pOldUnderLineFnt );
     400             : 
     401             :         // reset (for special vertical alignment)
     402         775 :         GetInfo().Y( nOldY );
     403             : 
     404         775 :         if( GetFnt()->IsURL() && pPor->InTxtGrp() )
     405           0 :             GetInfo().NotifyURL( *pPor );
     406             : 
     407         775 :         bFirst &= !pPor->GetLen();
     408         775 :         if( pNext || !pPor->IsMarginPortion() )
     409         743 :             pPor->Move( GetInfo() );
     410         775 :         if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
     411           0 :             pArrow = (SwArrowPortion*)pPor;
     412             : 
     413           8 :         pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
     414             :                // #i16816# tagged pdf support
     415           0 :                ( GetInfo().GetVsh() &&
     416           0 :                  GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
     417           0 :                  pNext && pNext->IsHolePortion() ) ?
     418             :                pNext :
     419         783 :                0;
     420             :     }
     421             : 
     422             :     // delete underline font
     423         512 :     delete GetInfo().GetUnderFnt();
     424         512 :     GetInfo().SetUnderFnt( 0 );
     425             : 
     426             :     // paint remaining stuff
     427         512 :     if( bDrawInWindow )
     428             :     {
     429             :         // If special vertical alignment is enabled, GetInfo().Y() is the
     430             :         // top of the current line. Therefore is has to be adjusted for
     431             :         // the painting of the remaining stuff. We first store the old value.
     432         509 :         const SwTwips nOldY = GetInfo().Y();
     433             : 
     434        1907 :         if( !GetNextLine() &&
     435         932 :             GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
     436         466 :             GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
     437           0 :             GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
     438             :         {
     439           0 :             const SwTmpEndPortion aEnd( *pEndTempl );
     440           0 :             GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
     441             : 
     442           0 :             if ( bAdjustBaseLine )
     443           0 :                 GetInfo().Y( GetInfo().GetPos().Y()
     444           0 :                            + AdjustBaseLine( *pCurr, &aEnd ) );
     445             : 
     446           0 :             aEnd.Paint( GetInfo() );
     447           0 :             GetInfo().Y( nOldY );
     448             :         }
     449         509 :         if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
     450             :         {
     451             :             const sal_Bool bNextUndersized =
     452         509 :                 ( GetTxtFrm()->GetNext() &&
     453         186 :                   0 == GetTxtFrm()->GetNext()->Prt().Height() &&
     454           0 :                   GetTxtFrm()->GetNext()->IsTxtFrm() &&
     455         695 :                   ((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
     456             : 
     457         509 :             if( bUnderSz || bNextUndersized )
     458             :             {
     459           2 :                 if ( bAdjustBaseLine )
     460           0 :                     GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
     461             : 
     462           2 :                 if( pArrow )
     463           0 :                     GetInfo().DrawRedArrow( *pArrow );
     464             : 
     465             :                 // GetInfo().Y() must be current baseline.
     466           2 :                 SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
     467           4 :                 if( ( nDiff > 0 &&
     468           2 :                       ( GetEnd() < GetInfo().GetTxt().Len() ||
     469           0 :                         ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
     470             :                     (nDiff >= 0 && bNextUndersized) )
     471             : 
     472             :                 {
     473           0 :                     SwArrowPortion aArrow( GetInfo() );
     474           0 :                     GetInfo().DrawRedArrow( aArrow );
     475             :                 }
     476             : 
     477           2 :                 GetInfo().Y( nOldY );
     478             :             }
     479             :         }
     480             :     }
     481             : 
     482         512 :     if( pCurr->IsClipping() )
     483           0 :         rClip.ChgClip( rPaint, pFrm );
     484             : }
     485             : 
     486         777 : void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
     487             :                                           long nAdjustBaseLine )
     488             : {
     489             :     // Check if common underline should not be continued.
     490         777 :     if ( IsUnderlineBreak( *pPor, *pFnt ) )
     491             :     {
     492             :         // delete underline font
     493         768 :         delete GetInfo().GetUnderFnt();
     494         768 :         GetInfo().SetUnderFnt( 0 );
     495             :         return;
     496             :     }
     497             : 
     498             :     // If current underline matches the common underline font, we continue
     499             :     // to use the common underline font.
     500           9 :     if ( GetInfo().GetUnderFnt() &&
     501           0 :          GetInfo().GetUnderFnt()->GetFont().GetUnderline() ==
     502           0 :          GetFnt()->GetUnderline() )
     503             :          return;
     504             : 
     505             :     // calculate the new common underline font
     506           9 :     SwFont* pUnderlineFnt = 0;
     507           9 :     Point aCommonBaseLine;
     508             : 
     509           9 :     Range aRange( 0, GetInfo().GetTxt().Len() );
     510           9 :     MultiSelection aUnderMulti( aRange );
     511             : 
     512             :     OSL_ENSURE( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
     513             :             "CheckSpecialUnderline without underlined font" );
     514           9 :     const SwFont* pParaFnt = GetAttrHandler().GetFont();
     515           9 :     if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
     516           0 :         aUnderMulti.SelectAll();
     517             : 
     518             :     SwTxtAttr* pTxtAttr;
     519           9 :     if( HasHints() )
     520             :     {
     521           9 :         sal_Bool bUnder = sal_False;
     522           9 :         MSHORT nTmp = 0;
     523             : 
     524          38 :         while( nTmp < pHints->GetStartCount() )
     525             :         {
     526          20 :             pTxtAttr = pHints->GetStart( nTmp++ );
     527          20 :             sal_Bool bUnderSelect = sal_False;
     528             : 
     529             :             const SvxUnderlineItem* pItem =
     530          20 :                     static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));
     531             : 
     532          20 :             if ( pItem )
     533             :             {
     534          16 :                 bUnder = sal_True;
     535          16 :                 bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
     536             :             }
     537             : 
     538          20 :             if( bUnder )
     539             :             {
     540          16 :                 xub_StrLen nSt = *pTxtAttr->GetStart();
     541          16 :                 xub_StrLen nEnd = *pTxtAttr->GetEnd();
     542          16 :                 if( nEnd > nSt )
     543             :                 {
     544          16 :                     Range aTmp( nSt, nEnd - 1 );
     545          16 :                     if( bUnder )
     546          16 :                         aUnderMulti.Select( aTmp, bUnderSelect );
     547             :                 }
     548          16 :                 bUnder = sal_False;
     549             :             }
     550             :         }
     551             :     }
     552             : 
     553             :     MSHORT i;
     554           9 :     xub_StrLen nIndx = GetInfo().GetIdx();
     555           9 :     long nUnderStart = 0;
     556           9 :     long nUnderEnd = 0;
     557           9 :     MSHORT nCnt = (MSHORT)aUnderMulti.GetRangeCount();
     558             : 
     559             :     // find the underline range the current portion is contained in
     560          18 :     for( i = 0; i < nCnt; ++i )
     561             :     {
     562           9 :         const Range& rRange = aUnderMulti.GetRange( i );
     563           9 :         if( nUnderEnd == rRange.Min() )
     564           4 :             nUnderEnd = rRange.Max();
     565           5 :         else if( nIndx >= rRange.Min() )
     566             :         {
     567           5 :             nUnderStart = rRange.Min();
     568           5 :             nUnderEnd = rRange.Max();
     569             :         }
     570             :         else
     571           0 :             break;
     572             :     }
     573             : 
     574             :     // restrict start and end to current line
     575           9 :     if ( GetStart() > nUnderStart )
     576           0 :         nUnderStart = GetStart();
     577             : 
     578           9 :     if ( GetEnd() && GetEnd() <= nUnderEnd )
     579           0 :         nUnderEnd = GetEnd() - 1;
     580             : 
     581             : 
     582             :     // check, if underlining is not isolated
     583           9 :     if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
     584             :     {
     585             :         //
     586             :         // here starts the algorithm for calculating the underline font
     587             :         //
     588           0 :         SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
     589           0 :         SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
     590           0 :                           rScriptInfo );
     591             : 
     592           0 :         xub_StrLen nTmpIdx = nIndx;
     593           0 :         sal_uLong nSumWidth = 0;
     594           0 :         sal_uLong nSumHeight = 0;
     595           0 :         sal_uLong nBold = 0;
     596           0 :         sal_uInt16 nMaxBaseLineOfst = 0;
     597           0 :         sal_uInt16 nNumberOfPortions = 0;
     598             : 
     599           0 :         while( nTmpIdx <= nUnderEnd && pPor )
     600             :         {
     601           0 :             if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
     602           0 :                 pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
     603           0 :                 pPor->IsHolePortion() ||
     604           0 :                 ( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
     605           0 :                 break;
     606             : 
     607           0 :             aIter.Seek( nTmpIdx );
     608             : 
     609           0 :             if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
     610           0 :                  SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
     611           0 :                 break;
     612             : 
     613           0 :             if ( !aIter.GetFnt()->GetEscapement() )
     614             :             {
     615           0 :                 nSumWidth += pPor->Width();
     616           0 :                 const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
     617             : 
     618             :                 // If we do not have a common baseline we take the baseline
     619             :                 // and the font of the lowest portion.
     620           0 :                 if ( nAdjustBaseLine )
     621             :                 {
     622           0 :                     sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
     623           0 :                     if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
     624             :                     {
     625           0 :                         nMaxBaseLineOfst = nTmpBaseLineOfst;
     626           0 :                         nSumHeight = nFontHeight;
     627             :                     }
     628             :                 }
     629             :                 // in horizontal layout we build a weighted sum of the heights
     630             :                 else
     631           0 :                     nSumHeight += pPor->Width() * nFontHeight;
     632             : 
     633           0 :                 if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
     634           0 :                     nBold += pPor->Width();
     635             :             }
     636             : 
     637           0 :             ++nNumberOfPortions;
     638             : 
     639           0 :             nTmpIdx = nTmpIdx + pPor->GetLen();
     640           0 :             pPor = pPor->GetPortion();
     641             :         }
     642             : 
     643             :         // resulting height
     644           0 :         if ( nNumberOfPortions > 1 && nSumWidth )
     645             :         {
     646             :             const sal_uLong nNewFontHeight = nAdjustBaseLine ?
     647             :                                          nSumHeight :
     648           0 :                                          nSumHeight / nSumWidth;
     649             : 
     650           0 :             pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
     651             : 
     652             :             // font height
     653           0 :             const sal_uInt8 nActual = pUnderlineFnt->GetActual();
     654           0 :             pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
     655           0 :                                           nNewFontHeight ), nActual );
     656             : 
     657             :             // font weight
     658           0 :             if ( 2 * nBold > nSumWidth )
     659           0 :                 pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
     660             :             else
     661           0 :                 pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
     662             : 
     663             :             // common base line
     664           0 :             aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
     665           0 :         }
     666             :     }
     667             : 
     668             :     // an escaped redlined portion should also have a special underlining
     669           9 :     if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
     670           0 :         GetRedln()->ChkSpecialUnderline() )
     671           0 :         pUnderlineFnt = new SwFont( *pFnt );
     672             : 
     673           9 :     delete GetInfo().GetUnderFnt();
     674             : 
     675           9 :     if ( pUnderlineFnt )
     676             :     {
     677           0 :         pUnderlineFnt->SetProportion( 100 );
     678           0 :         pUnderlineFnt->SetEscapement( 0 );
     679           0 :         pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
     680           0 :         pUnderlineFnt->SetOverline( UNDERLINE_NONE );
     681           0 :         const Color aFillColor( COL_TRANSPARENT );
     682           0 :         pUnderlineFnt->SetFillColor( aFillColor );
     683             : 
     684           0 :         GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
     685           0 :                                                      aCommonBaseLine ) );
     686             :     }
     687             :     else
     688             :         // I'm sorry, we do not have a special underlining font for you.
     689           9 :         GetInfo().SetUnderFnt( 0 );
     690             : }
     691             : 
     692             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10