blob: c68d007f6c37ccd377f7a24bc1d7fe9a02d35c6c [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include "hintids.hxx"
#include "flyfrm.hxx" // SwFlyInCntFrm
#include "viewopt.hxx" // SwViewOptions
#include "errhdl.hxx"
#include "txtatr.hxx" // SwINetFmt
#include <tools/multisel.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/lrspitem.hxx>
#include <txtinet.hxx>
#include <fchrfmt.hxx>
#include <frmatr.hxx>
#include <sfx2/printer.hxx>
#include <fmtftn.hxx>
#include <fmtfld.hxx>
#include <fldbas.hxx> // SwField
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <pagedesc.hxx> // SwPageDesc
#include <tgrditem.hxx>
// --> FME 2004-06-08 #i12836# enhanced pdf export
#include <EnhancedPDFExportHelper.hxx>
// <--
#include "flyfrms.hxx"
#include "viewsh.hxx"
#include "txtcfg.hxx"
#include "itrpaint.hxx"
#include "txtfrm.hxx" // pFrm
#include "txtfly.hxx"
#include "swfont.hxx"
#include "txtpaint.hxx"
#include "portab.hxx" // SwTabPortion::IsFilled
#include "porfly.hxx" // SwFlyCntPortion
#include "porfld.hxx" // SwGrfNumPortion
#include "frmfmt.hxx" // LRSpace
#include "txatbase.hxx" // SwTxtAttr
#include "charfmt.hxx" // SwFmtCharFmt
#include "redlnitr.hxx" // SwRedlineItr
#include "porrst.hxx" // SwArrowPortion
#include "pormulti.hxx"
/*************************************************************************
* IsUnderlineBreak
*
* Returns, if we have an underline breaking situation
* Adding some more conditions here means you also have to change them
* in SwTxtPainter::CheckSpecialUnderline
*************************************************************************/
sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
{
return UNDERLINE_NONE == rFnt.GetUnderline() ||
rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
rPor.IsHolePortion() ||
( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
}
/*************************************************************************
* SwTxtPainter::CtorInitTxtPainter()
*************************************************************************/
void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
{
CtorInitTxtCursor( pNewFrm, pNewInf );
pInf = pNewInf;
SwFont *pMyFnt = GetFnt();
GetInfo().SetFont( pMyFnt );
#ifdef DBG_UTIL
if( ALIGN_BASELINE != pMyFnt->GetAlign() )
{
ASSERT( ALIGN_BASELINE == pMyFnt->GetAlign(),
"+SwTxtPainter::CTOR: font alignment revolution" );
pMyFnt->SetAlign( ALIGN_BASELINE );
}
#endif
bPaintDrop = sal_False;
}
/*************************************************************************
* SwTxtPainter::CalcPaintOfst()
*************************************************************************/
SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
{
SwLinePortion *pPor = pCurr->GetFirstPortion();
GetInfo().SetPaintOfst( 0 );
SwTwips nPaintOfst = rPaint.Left();
// nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
// nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
// const KSHORT nLeftMar = KSHORT(GetLeftMargin());
// 8310: painten von LineBreaks in leeren Zeilen.
if( nPaintOfst && pCurr->Width() )
{
SwLinePortion *pLast = 0;
// 7529 und 4757: nicht <= nPaintOfst
while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
< nPaintOfst )
{
DBG_LOOP;
if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
{
long nTmp = GetInfo().X() +pPor->Width() +
pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
if( nTmp + (pPor->Height()/2) >= nPaintOfst )
break;
GetInfo().X( nTmp );
GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
}
else
pPor->Move( GetInfo() );
pLast = pPor;
pPor = pPor->GetPortion();
}
// 7529: bei PostIts auch pLast returnen.
if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
{
pPor = pLast;
GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
}
}
return pPor;
}
/*************************************************************************
* SwTxtPainter::DrawTextLine()
*
* Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
* 1) DrawRect auf die ganze Zeile und die DrawText hinterher
* (objektiv schnell, subjektiv langsam).
* 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
* ausgefuehrt (objektiv langsam, subjektiv schnell).
* Da der User in der Regel subjektiv urteilt, wird die 2. Methode
* als Default eingestellt.
*************************************************************************/
void SwTxtPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
const sal_Bool bUnderSz )
{
#if OSL_DEBUG_LEVEL > 1
// sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
// sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
#endif
// Adjustierung ggf. nachholen
GetAdjusted();
GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
GetInfo().ResetSpaceIdx();
GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
GetInfo().ResetKanaIdx();
// Die Groesse des Frames
GetInfo().SetIdx( GetStart() );
GetInfo().SetPos( GetTopLeft() );
const sal_Bool bDrawInWindow = GetInfo().OnWin();
// 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
// Optimierung!
const SwTwips nMaxRight = Min( rPaint.Right(), Right() );
const SwTwips nTmpLeft = GetInfo().X();
if( !bEndPor && nTmpLeft >= nMaxRight )
return;
// DropCaps!
// 7538: natuerlich auch auf dem Drucker
if( !bPaintDrop )
{
// 8084: Optimierung, weniger Painten.
// AMA: Durch 8084 wurde 7538 wiederbelebt!
// bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
bPaintDrop = pPor == pCurr->GetFirstPortion()
&& GetDropLines() >= GetLineNr();
}
KSHORT nTmpHeight, nTmpAscent;
CalcAscentAndHeight( nTmpAscent, nTmpHeight );
// bClip entscheidet darueber, ob geclippt werden muss.
// Das Ganze muss vor der Retusche stehen
sal_Bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
if( bClip && pPor )
{
// Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
// muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
// in der folgenden Ausgabeschleife...
if( GetInfo().GetPos().X() < rPaint.Left() ||
GetInfo().GetPos().Y() < rPaint.Top() ||
GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
{
bClip = sal_False;
rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
}
#if OSL_DEBUG_LEVEL > 1
static sal_Bool bClipAlways = sal_False;
if( bClip && bClipAlways )
{ bClip = sal_False;
rClip.ChgClip( rPaint );
}
#endif
}
// Alignment:
sal_Bool bPlus = sal_False;
OutputDevice* pOut = GetInfo().GetOut();
Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
if ( aPnt1.X() < rPaint.Left() )
aPnt1.X() = rPaint.Left();
if ( aPnt1.Y() < rPaint.Top() )
aPnt1.Y() = rPaint.Top();
Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
GetInfo().GetPos().Y() + nTmpHeight );
if ( aPnt2.X() > rPaint.Right() )
aPnt2.X() = rPaint.Right();
if ( aPnt2.Y() > rPaint.Bottom() )
{
aPnt2.Y() = rPaint.Bottom();
bPlus = sal_True;
}
const SwRect aLineRect( aPnt1, aPnt2 );
if( pCurr->IsClipping() )
{
rClip.ChgClip( aLineRect, pFrm );
bClip = sal_False;
}
if( !pPor && !bEndPor )
{
#ifdef DBGTXT
aDbstream << "PAINTER: done nothing" << endl;
#endif
return;
}
// Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
// if no special vertical alignment is used,
// we calculate Y value for the whole line
GETGRID( GetTxtFrm()->FindPageFrm() )
const sal_Bool bAdjustBaseLine =
GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
( 0 != pGrid );
const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
if ( ! bAdjustBaseLine )
GetInfo().Y( nLineBaseLine );
// 7529: PostIts prepainten
if( GetInfo().OnWin() && pPor && !pPor->Width() )
{
SeekAndChg( GetInfo() );
if( bAdjustBaseLine )
{
const SwTwips nOldY = GetInfo().Y();
GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, 0,
GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
) );
pPor->PrePaint( GetInfo(), pPor );
GetInfo().Y( nOldY );
}
else
pPor->PrePaint( GetInfo(), pPor );
}
// 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
if( bEndPor )
SeekStartAndChg( GetInfo() );
sal_Bool bRest = pCurr->IsRest();
sal_Bool bFirst = sal_True;
SwArrowPortion *pArrow = NULL;
// Reference portion for the paragraph end portion
SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
while( pPor )
{
DBG_LOOP;
sal_Bool bSeeked = sal_True;
GetInfo().SetLen( pPor->GetLen() );
const SwTwips nOldY = GetInfo().Y();
if ( bAdjustBaseLine )
{
GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, pPor ) );
// we store the last portion, because a possible paragraph
// end character has the same font as this portion
// (only in special vertical alignment case, otherwise the first
// portion of the line is used)
if ( pPor->Width() && pPor->InTxtGrp() )
pEndTempl = pPor;
}
// Ein Sonderfall sind GluePortions, die Blanks ausgeben.
// 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
// Portion an, dies wird durch SeekAndChgBefore vermieden:
if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
SeekAndChgBefore( GetInfo() );
else if ( pPor->IsQuoVadisPortion() )
{
xub_StrLen nOffset = GetInfo().GetIdx();
SeekStartAndChg( GetInfo(), sal_True );
if( GetRedln() && pCurr->HasRedline() )
GetRedln()->Seek( *pFnt, nOffset, 0 );
}
else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
SeekAndChg( GetInfo() );
else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
{
// Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
// haben, es sei denn, es gibt Redlining in dem Absatz.
if( GetRedln() )
SeekAndChg( GetInfo() );
else
SeekAndChgBefore( GetInfo() );
}
else
bSeeked = sal_False;
// bRest = sal_False;
// Wenn das Ende der Portion hinausragt, wird geclippt.
// Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
// damit die TTF-"f" nicht im Seitenrand haengen...
if( bClip &&
GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
{
bClip = sal_False;
rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
}
// Portions, die "unter" dem Text liegen wie PostIts
SwLinePortion *pNext = pPor->GetPortion();
if( GetInfo().OnWin() && pNext && !pNext->Width() )
{
// Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
// Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
// durch bSeeked wird Last!=Owner vermieden.
if ( !bSeeked )
SeekAndChg( GetInfo() );
pNext->PrePaint( GetInfo(), pPor );
}
// We calculate a separate font for underlining.
CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
if ( pUnderLineFnt )
{
const Point aTmpPoint( GetInfo().X(),
bAdjustBaseLine ?
pUnderLineFnt->GetPos().Y() :
nLineBaseLine );
pUnderLineFnt->SetPos( aTmpPoint );
}
// in extended input mode we do not want a common underline font.
SwUnderlineFont* pOldUnderLineFnt = 0;
if ( GetRedln() && GetRedln()->ExtOn() )
{
pOldUnderLineFnt = GetInfo().GetUnderFnt();
GetInfo().SetUnderFnt( 0 );
}
{
// --> FME 2004-06-24 #i16816# tagged pdf support
Por_Info aPorInfo( *pPor, *this );
SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
// <--
if( pPor->IsMultiPortion() )
PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
else
pPor->Paint( GetInfo() );
}
// reset underline font
if ( pOldUnderLineFnt )
GetInfo().SetUnderFnt( pOldUnderLineFnt );
// reset (for special vertical alignment)
GetInfo().Y( nOldY );
if( GetFnt()->IsURL() && pPor->InTxtGrp() )
GetInfo().NotifyURL( *pPor );
bFirst &= !pPor->GetLen();
if( pNext || !pPor->IsMarginPortion() )
pPor->Move( GetInfo() );
if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
pArrow = (SwArrowPortion*)pPor;
pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
// --> FME 2004-06-24 #i16816# tagged pdf support
( GetInfo().GetVsh() &&
GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
pNext && pNext->IsHolePortion() ) ?
// <--
pNext :
0;
}
// delete underline font
delete GetInfo().GetUnderFnt();
GetInfo().SetUnderFnt( 0 );
// paint remaining stuff
if( bDrawInWindow )
{
// If special vertical alignment is enabled, GetInfo().Y() is the
// top of the current line. Therefore is has to be adjusted for
// the painting of the remaining stuff. We first store the old value.
const SwTwips nOldY = GetInfo().Y();
if( !GetNextLine() &&
GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
{
const SwTmpEndPortion aEnd( *pEndTempl );
GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
if ( bAdjustBaseLine )
GetInfo().Y( GetInfo().GetPos().Y()
+ AdjustBaseLine( *pCurr, &aEnd ) );
aEnd.Paint( GetInfo() );
GetInfo().Y( nOldY );
}
if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
{
const sal_Bool bNextUndersized =
( GetTxtFrm()->GetNext() &&
0 == GetTxtFrm()->GetNext()->Prt().Height() &&
GetTxtFrm()->GetNext()->IsTxtFrm() &&
((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
if( bUnderSz || bNextUndersized )
{
if ( bAdjustBaseLine )
GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
if( pArrow )
GetInfo().DrawRedArrow( *pArrow );
// GetInfo().Y() must be current baseline.
SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
if( ( nDiff > 0 &&
( GetEnd() < GetInfo().GetTxt().Len() ||
( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
(nDiff >= 0 && bNextUndersized) )
{
SwArrowPortion aArrow( GetInfo() );
GetInfo().DrawRedArrow( aArrow );
}
GetInfo().Y( nOldY );
}
}
}
if( pCurr->IsClipping() )
rClip.ChgClip( rPaint, pFrm );
}
void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
long nAdjustBaseLine )
{
// Check if common underline should not be continued.
if ( IsUnderlineBreak( *pPor, *pFnt ) )
{
// delete underline font
delete GetInfo().GetUnderFnt();
GetInfo().SetUnderFnt( 0 );
return;
}
// If current underline matches the common underline font, we continue
// to use the common underline font.
//Bug 120769:Color of underline display wrongly
Color aAutoCo(COL_AUTO);
if ( GetInfo().GetUnderFnt() &&
GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != aAutoCo )
return;
//Bug 120769(End)
// calculate the new common underline font
SwFont* pUnderlineFnt = 0;
Point aCommonBaseLine;
Range aRange( 0, GetInfo().GetTxt().Len() );
MultiSelection aUnderMulti( aRange );
ASSERT( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
"CheckSpecialUnderline without underlined font" )
const SwFont* pParaFnt = GetAttrHandler().GetFont();
if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
aUnderMulti.SelectAll();
SwTxtAttr* pTxtAttr;
if( HasHints() )
{
sal_Bool bUnder = sal_False;
MSHORT nTmp = 0;
while( nTmp < pHints->GetStartCount() )
{
pTxtAttr = pHints->GetStart( nTmp++ );
sal_Bool bUnderSelect = sal_False;
const SvxUnderlineItem* pItem =
static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));
if ( pItem )
{
bUnder = sal_True;
bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
}
if( bUnder )
{
xub_StrLen nSt = *pTxtAttr->GetStart();
xub_StrLen nEnd = *pTxtAttr->GetEnd();
if( nEnd > nSt )
{
Range aTmp( nSt, nEnd - 1 );
if( bUnder )
aUnderMulti.Select( aTmp, bUnderSelect );
}
bUnder = sal_False;
}
}
}
MSHORT i;
xub_StrLen nIndx = GetInfo().GetIdx();
long nUnderStart = 0;
long nUnderEnd = 0;
MSHORT nCnt = (MSHORT)aUnderMulti.GetRangeCount();
// find the underline range the current portion is contained in
for( i = 0; i < nCnt; ++i )
{
const Range& rRange = aUnderMulti.GetRange( i );
if( nUnderEnd == rRange.Min() )
nUnderEnd = rRange.Max();
else if( nIndx >= rRange.Min() )
{
nUnderStart = rRange.Min();
nUnderEnd = rRange.Max();
}
else
break;
}
// restrict start and end to current line
if ( GetStart() > nUnderStart )
nUnderStart = GetStart();
if ( GetEnd() && GetEnd() <= nUnderEnd )
nUnderEnd = GetEnd() - 1;
// check, if underlining is not isolated
if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
{
//
// here starts the algorithm for calculating the underline font
//
SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
rScriptInfo );
xub_StrLen nTmpIdx = nIndx;
sal_uLong nSumWidth = 0;
sal_uLong nSumHeight = 0;
sal_uLong nBold = 0;
sal_uInt16 nMaxBaseLineOfst = 0;
sal_uInt16 nNumberOfPortions = 0;
while( nTmpIdx <= nUnderEnd && pPor )
{
if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
pPor->IsHolePortion() ||
( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
break;
aIter.Seek( nTmpIdx );
if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
break;
if ( !aIter.GetFnt()->GetEscapement() )
{
nSumWidth += pPor->Width();
const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
// If we do not have a common baseline we take the baseline
// and the font of the lowest portion.
if ( nAdjustBaseLine )
{
sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
{
nMaxBaseLineOfst = nTmpBaseLineOfst;
nSumHeight = nFontHeight;
}
}
// in horizontal layout we build a weighted sum of the heights
else
nSumHeight += pPor->Width() * nFontHeight;
if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
nBold += pPor->Width();
}
++nNumberOfPortions;
nTmpIdx = nTmpIdx + pPor->GetLen();
pPor = pPor->GetPortion();
}
// resulting height
if ( nNumberOfPortions > 1 && nSumWidth )
{
const sal_uLong nNewFontHeight = nAdjustBaseLine ?
nSumHeight :
nSumHeight / nSumWidth;
pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
// font height
const sal_uInt8 nActual = pUnderlineFnt->GetActual();
pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
nNewFontHeight ), nActual );
// font weight
if ( 2 * nBold > nSumWidth )
pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
else
pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
// common base line
aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
}
}
// an escaped redlined portion should also have a special underlining
if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
GetRedln()->ChkSpecialUnderline() )
pUnderlineFnt = new SwFont( *pFnt );
delete GetInfo().GetUnderFnt();
if ( pUnderlineFnt )
{
pUnderlineFnt->SetProportion( 100 );
pUnderlineFnt->SetEscapement( 0 );
pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
pUnderlineFnt->SetOverline( UNDERLINE_NONE );
const Color aFillColor( COL_TRANSPARENT );
pUnderlineFnt->SetFillColor( aFillColor );
GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
aCommonBaseLine ) );
}
else
// I'm sorry, we do not have a special underlining font for you.
GetInfo().SetUnderFnt( 0 );
}