LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/core/text - itrpaint.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 257 311 82.6 %
Date: 2013-07-09 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"     // SwFlyInCntFrm
      22             : #include "viewopt.hxx"  // SwViewOptions
      23             : #include "txtatr.hxx"  // SwINetFmt
      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 <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       43078 : sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
      69             : {
      70       44623 :     return UNDERLINE_NONE == rFnt.GetUnderline() ||
      71        4635 :            rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
      72        4252 :            rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
      73        2324 :            rPor.IsHolePortion() ||
      74        2324 :           ( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
      75       45602 :            rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
      76       43520 :            SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
      77             : }
      78             : 
      79             : /*************************************************************************
      80             :  *                  SwTxtPainter::CtorInitTxtPainter()
      81             :  *************************************************************************/
      82       14294 : void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
      83             : {
      84       14294 :     CtorInitTxtCursor( pNewFrm, pNewInf );
      85       14294 :     pInf = pNewInf;
      86       14294 :     SwFont *pMyFnt = GetFnt();
      87       14294 :     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       14294 :     bPaintDrop = sal_False;
      97       14294 : }
      98             : 
      99             : 
     100             : /*************************************************************************
     101             :  *                    SwTxtPainter::CalcPaintOfst()
     102             :  *************************************************************************/
     103       12829 : SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
     104             : {
     105       12829 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
     106       12829 :     GetInfo().SetPaintOfst( 0 );
     107       12829 :     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       12829 :     if( nPaintOfst && pCurr->Width() )
     114             :     {
     115       12047 :         SwLinePortion *pLast = 0;
     116             :         // 7529 und 4757: nicht <= nPaintOfst
     117       24105 :         while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
     118             :                        < nPaintOfst )
     119             :         {
     120          11 :             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          11 :                 pPor->Move( GetInfo() );
     131          11 :             pLast = pPor;
     132          11 :             pPor = pPor->GetPortion();
     133             :         }
     134             : 
     135             :         // 7529: bei PostIts auch pLast returnen.
     136       12047 :         if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
     137             :         {
     138           0 :             pPor = pLast;
     139           0 :             GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
     140             :         }
     141             :     }
     142       12829 :     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       12829 : 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       12829 :     GetAdjusted();
     166       12829 :     GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
     167       12829 :     GetInfo().ResetSpaceIdx();
     168       12829 :     GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
     169       12829 :     GetInfo().ResetKanaIdx();
     170             :     // Die Groesse des Frames
     171       12829 :     GetInfo().SetIdx( GetStart() );
     172       12829 :     GetInfo().SetPos( GetTopLeft() );
     173             : 
     174       12829 :     const bool bDrawInWindow = GetInfo().OnWin();
     175             : 
     176             :     // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
     177       12829 :     const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && GetInfo().GetTxt().isEmpty();
     178             : 
     179       12829 :     SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
     180             : 
     181             :     // Optimierung!
     182       12829 :     const SwTwips nMaxRight = std::min( rPaint.Right(), Right() );
     183       12829 :     const SwTwips nTmpLeft = GetInfo().X();
     184       12829 :     if( !bEndPor && nTmpLeft >= nMaxRight )
     185         208 :         return;
     186             : 
     187             :     // DropCaps!
     188             :     // 7538: natuerlich auch auf dem Drucker
     189       12727 :     if( !bPaintDrop )
     190             :     {
     191             :         // 8084: Optimierung, weniger Painten.
     192             :         // AMA: Durch 8084 wurde 7538 wiederbelebt!
     193             :         // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
     194       12727 :         bPaintDrop = pPor == pCurr->GetFirstPortion()
     195       12727 :                      && GetDropLines() >= GetLineNr();
     196             :     }
     197             : 
     198             :     KSHORT nTmpHeight, nTmpAscent;
     199       12727 :     CalcAscentAndHeight( nTmpAscent, nTmpHeight );
     200             : 
     201             :     // bClip entscheidet darueber, ob geclippt werden muss.
     202             :     // Das Ganze muss vor der Retusche stehen
     203             : 
     204       12727 :     bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
     205       12727 :     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       27140 :         if( GetInfo().GetPos().X() < rPaint.Left() ||
     212       15457 :             GetInfo().GetPos().Y() < rPaint.Top() ||
     213        6265 :             GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
     214             :         {
     215        3532 :             bClip = false;
     216        3532 :             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       12727 :     OutputDevice* pOut = GetInfo().GetOut();
     229       12727 :     Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
     230       12727 :     if ( aPnt1.X() < rPaint.Left() )
     231         727 :         aPnt1.X() = rPaint.Left();
     232       12727 :     if ( aPnt1.Y() < rPaint.Top() )
     233        2788 :         aPnt1.Y() = rPaint.Top();
     234       12727 :     Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
     235       25454 :                  GetInfo().GetPos().Y() + nTmpHeight );
     236       12727 :     if ( aPnt2.X() > rPaint.Right() )
     237           0 :         aPnt2.X() = rPaint.Right();
     238       12727 :     if ( aPnt2.Y() > rPaint.Bottom() )
     239        6361 :         aPnt2.Y() = rPaint.Bottom();
     240             : 
     241       12727 :     const SwRect aLineRect( aPnt1, aPnt2 );
     242             : 
     243       12727 :     if( pCurr->IsClipping() )
     244             :     {
     245           3 :         rClip.ChgClip( aLineRect, pFrm );
     246           3 :         bClip = false;
     247             :     }
     248             : 
     249       12727 :     if( !pPor && !bEndPor )
     250           4 :         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       12723 :     GETGRID( GetTxtFrm()->FindPageFrm() )
     256             :     const bool bAdjustBaseLine =
     257       12723 :         GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
     258       12723 :         ( 0 != pGrid );
     259       12723 :     const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
     260       12723 :     if ( ! bAdjustBaseLine )
     261       12723 :         GetInfo().Y( nLineBaseLine );
     262             : 
     263             :     // 7529: PostIts prepainten
     264       12723 :     if( GetInfo().OnWin() && pPor && !pPor->Width() )
     265             :     {
     266         743 :         SeekAndChg( GetInfo() );
     267             : 
     268         743 :         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         743 :             pPor->PrePaint( GetInfo(), pPor );
     282             :     }
     283             : 
     284             :     // 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
     285       12723 :     if( bEndPor )
     286           0 :         SeekStartAndChg( GetInfo() );
     287             : 
     288       12723 :     sal_Bool bRest = pCurr->IsRest();
     289       12723 :     sal_Bool bFirst = sal_True;
     290             : 
     291       12723 :     SwArrowPortion *pArrow = NULL;
     292             :     // Reference portion for the paragraph end portion
     293       12723 :     SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
     294             : 
     295       42185 :     while( pPor )
     296             :     {
     297       16739 :         sal_Bool bSeeked = sal_True;
     298       16739 :         GetInfo().SetLen( pPor->GetLen() );
     299             : 
     300       16739 :         const SwTwips nOldY = GetInfo().Y();
     301             : 
     302       16739 :         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       16739 :         if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
     319           8 :             SeekAndChgBefore( GetInfo() );
     320       16731 :         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       16731 :         else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
     328       11584 :             SeekAndChg( GetInfo() );
     329        5147 :         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        5147 :             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       24400 :         if( bClip &&
     347        7661 :             GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
     348             :         {
     349         779 :             bClip = false;
     350         779 :             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
     351             :         }
     352             : 
     353             :         // Portions, die "unter" dem Text liegen wie PostIts
     354       16739 :         SwLinePortion *pNext = pPor->GetPortion();
     355       16739 :         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        1001 :             if ( !bSeeked )
     361         485 :                 SeekAndChg( GetInfo() );
     362        1001 :             pNext->PrePaint( GetInfo(), pPor );
     363             :         }
     364             : 
     365             :         // We calculate a separate font for underlining.
     366       16739 :         CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
     367       16739 :         SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
     368       16739 :         if ( pUnderLineFnt )
     369             :         {
     370          41 :             const Point aTmpPoint( GetInfo().X(),
     371             :                                    bAdjustBaseLine ?
     372           0 :                                    pUnderLineFnt->GetPos().Y() :
     373          82 :                                    nLineBaseLine );
     374          41 :             pUnderLineFnt->SetPos( aTmpPoint );
     375             :         }
     376             : 
     377             : 
     378             :         // in extended input mode we do not want a common underline font.
     379       16739 :         SwUnderlineFont* pOldUnderLineFnt = 0;
     380       16739 :         if ( GetRedln() && GetRedln()->ExtOn() )
     381             :         {
     382           0 :             pOldUnderLineFnt = GetInfo().GetUnderFnt();
     383           0 :             GetInfo().SetUnderFnt( 0 );
     384             :         }
     385             : 
     386             :         {
     387             :             // #i16816# tagged pdf support
     388       16739 :             Por_Info aPorInfo( *pPor, *this );
     389       16739 :             SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
     390             : 
     391       16739 :             if( pPor->IsMultiPortion() )
     392         183 :                 PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
     393             :             else
     394       16556 :                 pPor->Paint( GetInfo() );
     395             :         }
     396             : 
     397             :         // reset underline font
     398       16739 :         if ( pOldUnderLineFnt )
     399           0 :             GetInfo().SetUnderFnt( pOldUnderLineFnt );
     400             : 
     401             :         // reset (for special vertical alignment)
     402       16739 :         GetInfo().Y( nOldY );
     403             : 
     404       16739 :         if( GetFnt()->IsURL() && pPor->InTxtGrp() )
     405           0 :             GetInfo().NotifyURL( *pPor );
     406             : 
     407       16739 :         bFirst &= !pPor->GetLen();
     408       16739 :         if( pNext || !pPor->IsMarginPortion() )
     409       16225 :             pPor->Move( GetInfo() );
     410       16739 :         if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
     411           0 :             pArrow = (SwArrowPortion*)pPor;
     412             : 
     413         160 :         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       33478 :                0;
     420             :     }
     421             : 
     422             :     // delete underline font
     423       12723 :     delete GetInfo().GetUnderFnt();
     424       12723 :     GetInfo().SetUnderFnt( 0 );
     425             : 
     426             :     // paint remaining stuff
     427       12723 :     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       12618 :         const SwTwips nOldY = GetInfo().Y();
     433             : 
     434       31242 :         if( !GetNextLine() &&
     435       18018 :             GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
     436       18624 :             GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
     437           0 :             GetInfo().GetIdx() >= GetInfo().GetTxt().getLength() )
     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       12618 :         if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
     450             :         {
     451             :             const sal_Bool bNextUndersized =
     452       15353 :                 ( GetTxtFrm()->GetNext() &&
     453        2739 :                   0 == GetTxtFrm()->GetNext()->Prt().Height() &&
     454       12626 :                   GetTxtFrm()->GetNext()->IsTxtFrm() &&
     455       12622 :                   ((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
     456             : 
     457       12618 :             if( bUnderSz || bNextUndersized )
     458             :             {
     459         270 :                 if ( bAdjustBaseLine )
     460           0 :                     GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
     461             : 
     462         270 :                 if( pArrow )
     463           0 :                     GetInfo().DrawRedArrow( *pArrow );
     464             : 
     465             :                 // GetInfo().Y() must be current baseline.
     466         270 :                 SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
     467         283 :                 if( ( nDiff > 0 &&
     468          21 :                       ( GetEnd() < GetInfo().GetTxt().getLength() ||
     469         291 :                         ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
     470           8 :                     (nDiff >= 0 && bNextUndersized) )
     471             : 
     472             :                 {
     473           9 :                     SwArrowPortion aArrow( GetInfo() );
     474           9 :                     GetInfo().DrawRedArrow( aArrow );
     475             :                 }
     476             : 
     477         270 :                 GetInfo().Y( nOldY );
     478             :             }
     479             :         }
     480             :     }
     481             : 
     482       12723 :     if( pCurr->IsClipping() )
     483           3 :         rClip.ChgClip( rPaint, pFrm );
     484             : }
     485             : 
     486       17273 : void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
     487             :                                           long nAdjustBaseLine )
     488             : {
     489             :     // Check if common underline should not be continued.
     490       17273 :     if ( IsUnderlineBreak( *pPor, *pFnt ) )
     491             :     {
     492             :         // delete underline font
     493       17067 :         delete GetInfo().GetUnderFnt();
     494       17067 :         GetInfo().SetUnderFnt( 0 );
     495       17067 :         return;
     496             :     }
     497             : 
     498             :     // If current underline matches the common underline font, we continue
     499             :     // to use the common underline font.
     500             :     //Bug 120769:Color of underline display wrongly
     501         206 :         Color aAutoCo(COL_AUTO);
     502         455 :     if ( GetInfo().GetUnderFnt() &&
     503          86 :         GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
     504         292 :         GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != aAutoCo )
     505           0 :         return;
     506             :     //Bug 120769(End)
     507             :     // calculate the new common underline font
     508         206 :     SwFont* pUnderlineFnt = 0;
     509         206 :     Point aCommonBaseLine;
     510             : 
     511         206 :     Range aRange( 0, GetInfo().GetTxt().getLength() );
     512         206 :     MultiSelection aUnderMulti( aRange );
     513             : 
     514             :     OSL_ENSURE( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
     515             :             "CheckSpecialUnderline without underlined font" );
     516         206 :     const SwFont* pParaFnt = GetAttrHandler().GetFont();
     517         206 :     if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
     518          74 :         aUnderMulti.SelectAll();
     519             : 
     520             :     SwTxtAttr* pTxtAttr;
     521         206 :     if( HasHints() )
     522             :     {
     523         137 :         sal_Bool bUnder = sal_False;
     524         137 :         MSHORT nTmp = 0;
     525             : 
     526         951 :         while( nTmp < pHints->GetStartCount() )
     527             :         {
     528         677 :             pTxtAttr = pHints->GetStart( nTmp++ );
     529         677 :             sal_Bool bUnderSelect = sal_False;
     530             : 
     531             :             const SvxUnderlineItem* pItem =
     532         677 :                     static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));
     533             : 
     534         677 :             if ( pItem )
     535             :             {
     536         397 :                 bUnder = sal_True;
     537         397 :                 bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
     538             :             }
     539             : 
     540         677 :             if( bUnder )
     541             :             {
     542         397 :                 xub_StrLen nSt = *pTxtAttr->GetStart();
     543         397 :                 xub_StrLen nEnd = *pTxtAttr->GetEnd();
     544         397 :                 if( nEnd > nSt )
     545             :                 {
     546         392 :                     Range aTmp( nSt, nEnd - 1 );
     547         392 :                     if( bUnder )
     548         392 :                         aUnderMulti.Select( aTmp, bUnderSelect );
     549             :                 }
     550         397 :                 bUnder = sal_False;
     551             :             }
     552             :         }
     553             :     }
     554             : 
     555             :     MSHORT i;
     556         206 :     xub_StrLen nIndx = GetInfo().GetIdx();
     557         206 :     long nUnderStart = 0;
     558         206 :     long nUnderEnd = 0;
     559         206 :     MSHORT nCnt = (MSHORT)aUnderMulti.GetRangeCount();
     560             : 
     561             :     // find the underline range the current portion is contained in
     562         445 :     for( i = 0; i < nCnt; ++i )
     563             :     {
     564         265 :         const Range& rRange = aUnderMulti.GetRange( i );
     565         265 :         if( nUnderEnd == rRange.Min() )
     566         130 :             nUnderEnd = rRange.Max();
     567         135 :         else if( nIndx >= rRange.Min() )
     568             :         {
     569         109 :             nUnderStart = rRange.Min();
     570         109 :             nUnderEnd = rRange.Max();
     571             :         }
     572             :         else
     573          26 :             break;
     574             :     }
     575             : 
     576             :     // restrict start and end to current line
     577         206 :     if ( GetStart() > nUnderStart )
     578           1 :         nUnderStart = GetStart();
     579             : 
     580         206 :     if ( GetEnd() && GetEnd() <= nUnderEnd )
     581          33 :         nUnderEnd = GetEnd() - 1;
     582             : 
     583             : 
     584             :     // check, if underlining is not isolated
     585         206 :     if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
     586             :     {
     587             :         //
     588             :         // here starts the algorithm for calculating the underline font
     589             :         //
     590         121 :         SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
     591         121 :         SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
     592         121 :                           rScriptInfo );
     593             : 
     594         121 :         xub_StrLen nTmpIdx = nIndx;
     595         121 :         sal_uLong nSumWidth = 0;
     596         121 :         sal_uLong nSumHeight = 0;
     597         121 :         sal_uLong nBold = 0;
     598         121 :         sal_uInt16 nMaxBaseLineOfst = 0;
     599         121 :         sal_uInt16 nNumberOfPortions = 0;
     600             : 
     601         444 :         while( nTmpIdx <= nUnderEnd && pPor )
     602             :         {
     603        1028 :             if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
     604         725 :                 pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
     605         734 :                 pPor->IsHolePortion() ||
     606         220 :                 ( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
     607          55 :                 break;
     608             : 
     609         202 :             aIter.Seek( nTmpIdx );
     610             : 
     611         404 :             if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
     612         202 :                  SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
     613           0 :                 break;
     614             : 
     615         202 :             if ( !aIter.GetFnt()->GetEscapement() )
     616             :             {
     617         156 :                 nSumWidth += pPor->Width();
     618         156 :                 const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
     619             : 
     620             :                 // If we do not have a common baseline we take the baseline
     621             :                 // and the font of the lowest portion.
     622         156 :                 if ( nAdjustBaseLine )
     623             :                 {
     624           0 :                     sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
     625           0 :                     if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
     626             :                     {
     627           0 :                         nMaxBaseLineOfst = nTmpBaseLineOfst;
     628           0 :                         nSumHeight = nFontHeight;
     629             :                     }
     630             :                 }
     631             :                 // in horizontal layout we build a weighted sum of the heights
     632             :                 else
     633         156 :                     nSumHeight += pPor->Width() * nFontHeight;
     634             : 
     635         156 :                 if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
     636           6 :                     nBold += pPor->Width();
     637             :             }
     638             : 
     639         202 :             ++nNumberOfPortions;
     640             : 
     641         202 :             nTmpIdx = nTmpIdx + pPor->GetLen();
     642         202 :             pPor = pPor->GetPortion();
     643             :         }
     644             : 
     645             :         // resulting height
     646         121 :         if ( nNumberOfPortions > 1 && nSumWidth )
     647             :         {
     648             :             const sal_uLong nNewFontHeight = nAdjustBaseLine ?
     649             :                                          nSumHeight :
     650          43 :                                          nSumHeight / nSumWidth;
     651             : 
     652          43 :             pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
     653             : 
     654             :             // font height
     655          43 :             const sal_uInt8 nActual = pUnderlineFnt->GetActual();
     656          43 :             pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
     657          86 :                                           nNewFontHeight ), nActual );
     658             : 
     659             :             // font weight
     660          43 :             if ( 2 * nBold > nSumWidth )
     661           3 :                 pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
     662             :             else
     663          40 :                 pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
     664             : 
     665             :             // common base line
     666          43 :             aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
     667         121 :         }
     668             :     }
     669             : 
     670             :     // an escaped redlined portion should also have a special underlining
     671         206 :     if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
     672           0 :         GetRedln()->ChkSpecialUnderline() )
     673           0 :         pUnderlineFnt = new SwFont( *pFnt );
     674             : 
     675         206 :     delete GetInfo().GetUnderFnt();
     676             : 
     677         206 :     if ( pUnderlineFnt )
     678             :     {
     679          43 :         pUnderlineFnt->SetProportion( 100 );
     680          43 :         pUnderlineFnt->SetEscapement( 0 );
     681          43 :         pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
     682          43 :         pUnderlineFnt->SetOverline( UNDERLINE_NONE );
     683          43 :         const Color aFillColor( COL_TRANSPARENT );
     684          43 :         pUnderlineFnt->SetFillColor( aFillColor );
     685             : 
     686          43 :         GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
     687          86 :                                                      aCommonBaseLine ) );
     688             :     }
     689             :     else
     690             :         // I'm sorry, we do not have a special underlining font for you.
     691         163 :         GetInfo().SetUnderFnt( 0 );
     692          99 : }
     693             : 
     694             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10