/************************************************************** * * 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 #include #include #include #include #include #include #include #include #include #include // SwField #include #include #include // SwPageDesc #include // --> FME 2004-06-08 #i12836# enhanced pdf export #include // <-- #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(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 ); }