diff options
Diffstat (limited to 'sw/source/core/text/itrpaint.cxx')
-rw-r--r-- | sw/source/core/text/itrpaint.cxx | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx new file mode 100644 index 000000000000..2bd7a46ac09f --- /dev/null +++ b/sw/source/core/text/itrpaint.cxx @@ -0,0 +1,718 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 +// USHORT nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() ); +// USHORT 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. + if ( GetInfo().GetUnderFnt() && + GetInfo().GetUnderFnt()->GetFont().GetUnderline() == + GetFnt()->GetUnderline() ) + return; + + // 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; + ULONG nSumWidth = 0; + ULONG nSumHeight = 0; + ULONG nBold = 0; + USHORT nMaxBaseLineOfst = 0; + USHORT 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 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 ) + { + USHORT 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 ULONG nNewFontHeight = nAdjustBaseLine ? + nSumHeight : + nSumHeight / nSumWidth; + + pUnderlineFnt = new SwFont( *GetInfo().GetFont() ); + + // font height + const BYTE 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 ); +} |