1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itrpaint.cxx,v $
10 * $Revision: 1.47.210.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include "hintids.hxx"
36 #include "flyfrm.hxx" // SwFlyInCntFrm
37 #include "viewopt.hxx" // SwViewOptions
39 #include "txtatr.hxx" // SwINetFmt
40 #include <tools/multisel.hxx>
41 #include <svx/escpitem.hxx>
42 #include <svx/udlnitem.hxx>
43 #include <svx/lrspitem.hxx>
44 #include <txtinet.hxx>
45 #include <fchrfmt.hxx>
47 #include <sfx2/printer.hxx>
50 #include <fldbas.hxx> // SwField
51 #include <rootfrm.hxx>
52 #include <pagefrm.hxx>
53 #include <pagedesc.hxx> // SwPageDesc
54 #include <tgrditem.hxx>
56 // --> FME 2004-06-08 #i12836# enhanced pdf export
57 #include <EnhancedPDFExportHelper.hxx>
61 #include "flyfrms.hxx"
64 #include "itrpaint.hxx"
65 #include "txtfrm.hxx" // pFrm
68 #include "txtpaint.hxx"
69 #include "portab.hxx" // SwTabPortion::IsFilled
70 #include "porfly.hxx" // SwFlyCntPortion
71 #include "porfld.hxx" // SwGrfNumPortion
72 #include "frmfmt.hxx" // LRSpace
73 #include "txatbase.hxx" // SwTxtAttr
74 #include "charfmt.hxx" // SwFmtCharFmt
75 #include "redlnitr.hxx" // SwRedlineItr
76 #include "porrst.hxx" // SwArrowPortion
77 #include "pormulti.hxx"
79 /*************************************************************************
82 * Returns, if we have an underline breaking situation
83 * Adding some more conditions here means you also have to change them
84 * in SwTxtPainter::CheckSpecialUnderline
85 *************************************************************************/
86 sal_Bool
IsUnderlineBreak( const SwLinePortion
& rPor
, const SwFont
& rFnt
)
88 return UNDERLINE_NONE
== rFnt
.GetUnderline() ||
89 rPor
.IsFlyPortion() || rPor
.IsFlyCntPortion() ||
90 rPor
.IsBreakPortion() || rPor
.IsMarginPortion() ||
91 rPor
.IsHolePortion() ||
92 ( rPor
.IsMultiPortion() && ! ((SwMultiPortion
&)rPor
).IsBidi() ) ||
93 rFnt
.GetEscapement() < 0 || rFnt
.IsWordLineMode() ||
94 SVX_CASEMAP_KAPITAELCHEN
== rFnt
.GetCaseMap();
97 /*************************************************************************
98 * SwTxtPainter::CtorInitTxtPainter()
99 *************************************************************************/
100 void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm
*pNewFrm
, SwTxtPaintInfo
*pNewInf
)
102 CtorInitTxtCursor( pNewFrm
, pNewInf
);
104 SwFont
*pMyFnt
= GetFnt();
105 GetInfo().SetFont( pMyFnt
);
107 if( ALIGN_BASELINE
!= pMyFnt
->GetAlign() )
109 ASSERT( ALIGN_BASELINE
== pMyFnt
->GetAlign(),
110 "+SwTxtPainter::CTOR: font alignment revolution" );
111 pMyFnt
->SetAlign( ALIGN_BASELINE
);
114 bPaintDrop
= sal_False
;
118 /*************************************************************************
119 * SwTxtPainter::CalcPaintOfst()
120 *************************************************************************/
121 SwLinePortion
*SwTxtPainter::CalcPaintOfst( const SwRect
&rPaint
)
123 SwLinePortion
*pPor
= pCurr
->GetFirstPortion();
124 GetInfo().SetPaintOfst( 0 );
125 SwTwips nPaintOfst
= rPaint
.Left();
127 // nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
128 // nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
129 // const KSHORT nLeftMar = KSHORT(GetLeftMargin());
130 // 8310: painten von LineBreaks in leeren Zeilen.
131 if( nPaintOfst
&& pCurr
->Width() )
133 SwLinePortion
*pLast
= 0;
134 // 7529 und 4757: nicht <= nPaintOfst
135 while( pPor
&& GetInfo().X() + pPor
->Width() + (pPor
->Height()/2)
139 if( pPor
->InSpaceGrp() && GetInfo().GetSpaceAdd() )
141 long nTmp
= GetInfo().X() +pPor
->Width() +
142 pPor
->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
143 if( nTmp
+ (pPor
->Height()/2) >= nPaintOfst
)
146 GetInfo().SetIdx( GetInfo().GetIdx() + pPor
->GetLen() );
149 pPor
->Move( GetInfo() );
151 pPor
= pPor
->GetPortion();
154 // 7529: bei PostIts auch pLast returnen.
155 if( pLast
&& !pLast
->Width() && pLast
->IsPostItsPortion() )
158 GetInfo().SetIdx( GetInfo().GetIdx() - pPor
->GetLen() );
164 /*************************************************************************
165 * SwTxtPainter::DrawTextLine()
167 * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
168 * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
169 * (objektiv schnell, subjektiv langsam).
170 * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
171 * ausgefuehrt (objektiv langsam, subjektiv schnell).
172 * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
173 * als Default eingestellt.
174 *************************************************************************/
175 void SwTxtPainter::DrawTextLine( const SwRect
&rPaint
, SwSaveClip
&rClip
,
176 const sal_Bool bUnderSz
)
178 #if OSL_DEBUG_LEVEL > 1
179 // USHORT nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
180 // USHORT nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
183 // Adjustierung ggf. nachholen
185 GetInfo().SetpSpaceAdd( pCurr
->GetpLLSpaceAdd() );
186 GetInfo().ResetSpaceIdx();
187 GetInfo().SetKanaComp( pCurr
->GetpKanaComp() );
188 GetInfo().ResetKanaIdx();
189 // Die Groesse des Frames
190 GetInfo().SetIdx( GetStart() );
191 GetInfo().SetPos( GetTopLeft() );
193 const sal_Bool bDrawInWindow
= GetInfo().OnWin();
195 // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
196 const sal_Bool bEndPor
= GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
198 SwLinePortion
*pPor
= bEndPor
? pCurr
->GetFirstPortion() : CalcPaintOfst( rPaint
);
201 const SwTwips nMaxRight
= Min( rPaint
.Right(), Right() );
202 const SwTwips nTmpLeft
= GetInfo().X();
203 if( !bEndPor
&& nTmpLeft
>= nMaxRight
)
207 // 7538: natuerlich auch auf dem Drucker
210 // 8084: Optimierung, weniger Painten.
211 // AMA: Durch 8084 wurde 7538 wiederbelebt!
212 // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
213 bPaintDrop
= pPor
== pCurr
->GetFirstPortion()
214 && GetDropLines() >= GetLineNr();
217 KSHORT nTmpHeight
, nTmpAscent
;
218 CalcAscentAndHeight( nTmpAscent
, nTmpHeight
);
220 // bClip entscheidet darueber, ob geclippt werden muss.
221 // Das Ganze muss vor der Retusche stehen
223 sal_Bool bClip
= ( bDrawInWindow
|| bUnderSz
) && !rClip
.IsChg();
226 // Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
227 // muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
228 // in der folgenden Ausgabeschleife...
230 if( GetInfo().GetPos().X() < rPaint
.Left() ||
231 GetInfo().GetPos().Y() < rPaint
.Top() ||
232 GetInfo().GetPos().Y() + nTmpHeight
> rPaint
.Top() + rPaint
.Height() )
235 rClip
.ChgClip( rPaint
, pFrm
, pCurr
->HasUnderscore() );
237 #if OSL_DEBUG_LEVEL > 1
238 static sal_Bool bClipAlways
= sal_False
;
239 if( bClip
&& bClipAlways
)
241 rClip
.ChgClip( rPaint
);
247 sal_Bool bPlus
= sal_False
;
248 OutputDevice
* pOut
= GetInfo().GetOut();
249 Point
aPnt1( nTmpLeft
, GetInfo().GetPos().Y() );
250 if ( aPnt1
.X() < rPaint
.Left() )
251 aPnt1
.X() = rPaint
.Left();
252 if ( aPnt1
.Y() < rPaint
.Top() )
253 aPnt1
.Y() = rPaint
.Top();
254 Point
aPnt2( GetInfo().GetPos().X() + nMaxRight
- GetInfo().X(),
255 GetInfo().GetPos().Y() + nTmpHeight
);
256 if ( aPnt2
.X() > rPaint
.Right() )
257 aPnt2
.X() = rPaint
.Right();
258 if ( aPnt2
.Y() > rPaint
.Bottom() )
260 aPnt2
.Y() = rPaint
.Bottom();
264 const SwRect
aLineRect( aPnt1
, aPnt2
);
266 if( pCurr
->IsClipping() )
268 rClip
.ChgClip( aLineRect
, pFrm
);
272 if( !pPor
&& !bEndPor
)
275 aDbstream
<< "PAINTER: done nothing" << endl
;
280 // Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
281 // if no special vertical alignment is used,
282 // we calculate Y value for the whole line
283 GETGRID( GetTxtFrm()->FindPageFrm() )
284 const sal_Bool bAdjustBaseLine
=
285 GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
287 const SwTwips nLineBaseLine
= GetInfo().GetPos().Y() + nTmpAscent
;
288 if ( ! bAdjustBaseLine
)
289 GetInfo().Y( nLineBaseLine
);
291 // 7529: PostIts prepainten
292 if( GetInfo().OnWin() && pPor
&& !pPor
->Width() )
294 SeekAndChg( GetInfo() );
296 if( bAdjustBaseLine
)
298 const SwTwips nOldY
= GetInfo().Y();
300 GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr
, 0,
301 GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut
),
302 GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut
)
305 pPor
->PrePaint( GetInfo(), pPor
);
306 GetInfo().Y( nOldY
);
309 pPor
->PrePaint( GetInfo(), pPor
);
312 // 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
314 SeekStartAndChg( GetInfo() );
316 sal_Bool bRest
= pCurr
->IsRest();
317 sal_Bool bFirst
= sal_True
;
319 SwArrowPortion
*pArrow
= NULL
;
320 // Reference portion for the paragraph end portion
321 SwLinePortion
* pEndTempl
= pCurr
->GetFirstPortion();
326 sal_Bool bSeeked
= sal_True
;
327 GetInfo().SetLen( pPor
->GetLen() );
329 const SwTwips nOldY
= GetInfo().Y();
331 if ( bAdjustBaseLine
)
333 GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr
, pPor
) );
335 // we store the last portion, because a possible paragraph
336 // end character has the same font as this portion
337 // (only in special vertical alignment case, otherwise the first
338 // portion of the line is used)
339 if ( pPor
->Width() && pPor
->InTxtGrp() )
343 // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
345 // 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
346 // Portion an, dies wird durch SeekAndChgBefore vermieden:
347 if( ( bRest
&& pPor
->InFldGrp() && !pPor
->GetLen() ) )
348 SeekAndChgBefore( GetInfo() );
349 else if ( pPor
->IsQuoVadisPortion() )
351 xub_StrLen nOffset
= GetInfo().GetIdx();
352 SeekStartAndChg( GetInfo(), sal_True
);
353 if( GetRedln() && pCurr
->HasRedline() )
354 GetRedln()->Seek( *pFnt
, nOffset
, 0 );
356 else if( pPor
->InTxtGrp() || pPor
->InFldGrp() || pPor
->InTabGrp() )
357 SeekAndChg( GetInfo() );
358 else if ( !bFirst
&& pPor
->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
360 // Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
361 // haben, es sei denn, es gibt Redlining in dem Absatz.
363 SeekAndChg( GetInfo() );
365 SeekAndChgBefore( GetInfo() );
370 // bRest = sal_False;
372 // Wenn das Ende der Portion hinausragt, wird geclippt.
373 // Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
374 // damit die TTF-"f" nicht im Seitenrand haengen...
376 GetInfo().X() + pPor
->Width() + ( pPor
->Height() / 2 ) > nMaxRight
)
379 rClip
.ChgClip( rPaint
, pFrm
, pCurr
->HasUnderscore() );
382 // Portions, die "unter" dem Text liegen wie PostIts
383 SwLinePortion
*pNext
= pPor
->GetPortion();
384 if( GetInfo().OnWin() && pNext
&& !pNext
->Width() )
386 // Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
387 // Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
388 // durch bSeeked wird Last!=Owner vermieden.
390 SeekAndChg( GetInfo() );
391 pNext
->PrePaint( GetInfo(), pPor
);
394 // We calculate a separate font for underlining.
395 CheckSpecialUnderline( pPor
, bAdjustBaseLine
? nOldY
: 0 );
396 SwUnderlineFont
* pUnderLineFnt
= GetInfo().GetUnderFnt();
399 const Point
aTmpPoint( GetInfo().X(),
401 pUnderLineFnt
->GetPos().Y() :
403 pUnderLineFnt
->SetPos( aTmpPoint
);
407 // in extended input mode we do not want a common underline font.
408 SwUnderlineFont
* pOldUnderLineFnt
= 0;
409 if ( GetRedln() && GetRedln()->ExtOn() )
411 pOldUnderLineFnt
= GetInfo().GetUnderFnt();
412 GetInfo().SetUnderFnt( 0 );
416 // --> FME 2004-06-24 #i16816# tagged pdf support
417 Por_Info
aPorInfo( *pPor
, *this );
418 SwTaggedPDFHelper
aTaggedPDFHelper( 0, 0, &aPorInfo
, *pOut
);
421 if( pPor
->IsMultiPortion() )
422 PaintMultiPortion( rPaint
, (SwMultiPortion
&)*pPor
);
424 pPor
->Paint( GetInfo() );
427 // reset underline font
428 if ( pOldUnderLineFnt
)
429 GetInfo().SetUnderFnt( pOldUnderLineFnt
);
431 // reset (for special vertical alignment)
432 GetInfo().Y( nOldY
);
434 if( GetFnt()->IsURL() && pPor
->InTxtGrp() )
435 GetInfo().NotifyURL( *pPor
);
437 bFirst
&= !pPor
->GetLen();
438 if( pNext
|| !pPor
->IsMarginPortion() )
439 pPor
->Move( GetInfo() );
440 if( pPor
->IsArrowPortion() && GetInfo().OnWin() && !pArrow
)
441 pArrow
= (SwArrowPortion
*)pPor
;
443 pPor
= bDrawInWindow
|| GetInfo().X() <= nMaxRight
||
444 // --> FME 2004-06-24 #i16816# tagged pdf support
445 ( GetInfo().GetVsh() &&
446 GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
447 pNext
&& pNext
->IsHolePortion() ) ?
453 // delete underline font
454 delete GetInfo().GetUnderFnt();
455 GetInfo().SetUnderFnt( 0 );
457 // paint remaining stuff
460 // If special vertical alignment is enabled, GetInfo().Y() is the
461 // top of the current line. Therefore is has to be adjusted for
462 // the painting of the remaining stuff. We first store the old value.
463 const SwTwips nOldY
= GetInfo().Y();
465 if( !GetNextLine() &&
466 GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
467 GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
468 GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
470 const SwTmpEndPortion
aEnd( *pEndTempl
);
471 GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut
);
473 if ( bAdjustBaseLine
)
474 GetInfo().Y( GetInfo().GetPos().Y()
475 + AdjustBaseLine( *pCurr
, &aEnd
) );
477 aEnd
.Paint( GetInfo() );
478 GetInfo().Y( nOldY
);
480 if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
482 const sal_Bool bNextUndersized
=
483 ( GetTxtFrm()->GetNext() &&
484 0 == GetTxtFrm()->GetNext()->Prt().Height() &&
485 GetTxtFrm()->GetNext()->IsTxtFrm() &&
486 ((SwTxtFrm
*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
488 if( bUnderSz
|| bNextUndersized
)
490 if ( bAdjustBaseLine
)
491 GetInfo().Y( GetInfo().GetPos().Y() + pCurr
->GetAscent() );
494 GetInfo().DrawRedArrow( *pArrow
);
496 // GetInfo().Y() must be current baseline.
497 SwTwips nDiff
= GetInfo().Y() + nTmpHeight
- nTmpAscent
- GetTxtFrm()->Frm().Bottom();
499 ( GetEnd() < GetInfo().GetTxt().Len() ||
500 ( nDiff
> nTmpHeight
/2 && GetPrevLine() ) ) ) ||
501 nDiff
>= 0 && bNextUndersized
)
504 SwArrowPortion
aArrow( GetInfo() );
505 GetInfo().DrawRedArrow( aArrow
);
508 GetInfo().Y( nOldY
);
513 if( pCurr
->IsClipping() )
514 rClip
.ChgClip( rPaint
, pFrm
);
517 void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion
* pPor
,
518 long nAdjustBaseLine
)
520 // Check if common underline should not be continued.
521 if ( IsUnderlineBreak( *pPor
, *pFnt
) )
523 // delete underline font
524 delete GetInfo().GetUnderFnt();
525 GetInfo().SetUnderFnt( 0 );
529 // If current underline matches the common underline font, we continue
530 // to use the common underline font.
531 if ( GetInfo().GetUnderFnt() &&
532 GetInfo().GetUnderFnt()->GetFont().GetUnderline() ==
533 GetFnt()->GetUnderline() )
536 // calculate the new common underline font
537 SwFont
* pUnderlineFnt
= 0;
538 Point aCommonBaseLine
;
540 Range
aRange( 0, GetInfo().GetTxt().Len() );
541 MultiSelection
aUnderMulti( aRange
);
543 ASSERT( GetFnt() && UNDERLINE_NONE
!= GetFnt()->GetUnderline(),
544 "CheckSpecialUnderline without underlined font" )
545 const SwFont
* pParaFnt
= GetAttrHandler().GetFont();
546 if( pParaFnt
&& pParaFnt
->GetUnderline() == GetFnt()->GetUnderline() )
547 aUnderMulti
.SelectAll();
552 sal_Bool bUnder
= sal_False
;
555 while( nTmp
< pHints
->GetStartCount() )
557 pTxtAttr
= pHints
->GetStart( nTmp
++ );
558 sal_Bool bUnderSelect
= sal_False
;
560 const SvxUnderlineItem
* pItem
=
561 static_cast<const SvxUnderlineItem
*>(CharFmt::GetItem( *pTxtAttr
, RES_CHRATR_UNDERLINE
));
566 bUnderSelect
= pFnt
->GetUnderline() == pItem
->GetLineStyle();
571 xub_StrLen nSt
= *pTxtAttr
->GetStart();
572 xub_StrLen nEnd
= *pTxtAttr
->GetEnd();
575 Range
aTmp( nSt
, nEnd
- 1 );
577 aUnderMulti
.Select( aTmp
, bUnderSelect
);
585 xub_StrLen nIndx
= GetInfo().GetIdx();
586 long nUnderStart
= 0;
588 MSHORT nCnt
= (MSHORT
)aUnderMulti
.GetRangeCount();
590 // find the underline range the current portion is contained in
591 for( i
= 0; i
< nCnt
; ++i
)
593 const Range
& rRange
= aUnderMulti
.GetRange( i
);
594 if( nUnderEnd
== rRange
.Min() )
595 nUnderEnd
= rRange
.Max();
596 else if( nIndx
>= rRange
.Min() )
598 nUnderStart
= rRange
.Min();
599 nUnderEnd
= rRange
.Max();
605 // restrict start and end to current line
606 if ( GetStart() > nUnderStart
)
607 nUnderStart
= GetStart();
609 if ( GetEnd() && GetEnd() <= nUnderEnd
)
610 nUnderEnd
= GetEnd() - 1;
613 // check, if underlining is not isolated
614 if ( nIndx
+ GetInfo().GetLen() < nUnderEnd
+ 1 )
617 // here starts the algorithm for calculating the underline font
619 SwScriptInfo
& rScriptInfo
= GetInfo().GetParaPortion()->GetScriptInfo();
620 SwAttrIter
aIter( *(SwTxtNode
*)GetInfo().GetTxtFrm()->GetTxtNode(),
623 xub_StrLen nTmpIdx
= nIndx
;
625 ULONG nSumHeight
= 0;
627 USHORT nMaxBaseLineOfst
= 0;
628 USHORT nNumberOfPortions
= 0;
630 while( nTmpIdx
<= nUnderEnd
&& pPor
)
632 if ( pPor
->IsFlyPortion() || pPor
->IsFlyCntPortion() ||
633 pPor
->IsBreakPortion() || pPor
->IsMarginPortion() ||
634 pPor
->IsHolePortion() ||
635 ( pPor
->IsMultiPortion() && ! ((SwMultiPortion
*)pPor
)->IsBidi() ) )
638 aIter
.Seek( nTmpIdx
);
640 if ( aIter
.GetFnt()->GetEscapement() < 0 || pFnt
->IsWordLineMode() ||
641 SVX_CASEMAP_KAPITAELCHEN
== pFnt
->GetCaseMap() )
644 if ( !aIter
.GetFnt()->GetEscapement() )
646 nSumWidth
+= pPor
->Width();
647 const ULONG nFontHeight
= aIter
.GetFnt()->GetHeight();
649 // If we do not have a common baseline we take the baseline
650 // and the font of the lowest portion.
651 if ( nAdjustBaseLine
)
653 USHORT nTmpBaseLineOfst
= AdjustBaseLine( *pCurr
, pPor
);
654 if ( nMaxBaseLineOfst
< nTmpBaseLineOfst
)
656 nMaxBaseLineOfst
= nTmpBaseLineOfst
;
657 nSumHeight
= nFontHeight
;
660 // in horizontal layout we build a weighted sum of the heights
662 nSumHeight
+= pPor
->Width() * nFontHeight
;
664 if ( WEIGHT_NORMAL
!= aIter
.GetFnt()->GetWeight() )
665 nBold
+= pPor
->Width();
670 nTmpIdx
= nTmpIdx
+ pPor
->GetLen();
671 pPor
= pPor
->GetPortion();
675 if ( nNumberOfPortions
> 1 && nSumWidth
)
677 const ULONG nNewFontHeight
= nAdjustBaseLine
?
679 nSumHeight
/ nSumWidth
;
681 pUnderlineFnt
= new SwFont( *GetInfo().GetFont() );
684 const BYTE nActual
= pUnderlineFnt
->GetActual();
685 pUnderlineFnt
->SetSize( Size( pUnderlineFnt
->GetSize( nActual
).Width(),
686 nNewFontHeight
), nActual
);
689 if ( 2 * nBold
> nSumWidth
)
690 pUnderlineFnt
->SetWeight( WEIGHT_BOLD
, nActual
);
692 pUnderlineFnt
->SetWeight( WEIGHT_NORMAL
, nActual
);
695 aCommonBaseLine
.Y() = nAdjustBaseLine
+ nMaxBaseLineOfst
;
699 // an escaped redlined portion should also have a special underlining
700 if( ! pUnderlineFnt
&& pFnt
->GetEscapement() > 0 && GetRedln() &&
701 GetRedln()->ChkSpecialUnderline() )
702 pUnderlineFnt
= new SwFont( *pFnt
);
704 delete GetInfo().GetUnderFnt();
708 pUnderlineFnt
->SetProportion( 100 );
709 pUnderlineFnt
->SetEscapement( 0 );
710 pUnderlineFnt
->SetStrikeout( STRIKEOUT_NONE
);
711 pUnderlineFnt
->SetOverline( UNDERLINE_NONE
);
712 const Color
aFillColor( COL_TRANSPARENT
);
713 pUnderlineFnt
->SetFillColor( aFillColor
);
715 GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt
,
719 // I'm sorry, we do not have a special underlining font for you.
720 GetInfo().SetUnderFnt( 0 );