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 <fmthbsh.hxx>
52 #include <rootfrm.hxx>
53 #include <pagefrm.hxx>
54 #include <pagedesc.hxx> // SwPageDesc
55 #include <tgrditem.hxx>
57 // --> FME 2004-06-08 #i12836# enhanced pdf export
58 #include <EnhancedPDFExportHelper.hxx>
62 #include "flyfrms.hxx"
65 #include "itrpaint.hxx"
66 #include "txtfrm.hxx" // pFrm
69 #include "txtpaint.hxx"
70 #include "portab.hxx" // SwTabPortion::IsFilled
71 #include "porfly.hxx" // SwFlyCntPortion
72 #include "porfld.hxx" // SwGrfNumPortion
73 #include "frmfmt.hxx" // LRSpace
74 #include "txatbase.hxx" // SwTxtAttr
75 #include "charfmt.hxx" // SwFmtCharFmt
76 #include "redlnitr.hxx" // SwRedlineItr
77 #include "porrst.hxx" // SwArrowPortion
78 #include "pormulti.hxx"
80 /*************************************************************************
83 * Returns, if we have an underline breaking situation
84 * Adding some more conditions here means you also have to change them
85 * in SwTxtPainter::CheckSpecialUnderline
86 *************************************************************************/
87 sal_Bool
IsUnderlineBreak( const SwLinePortion
& rPor
, const SwFont
& rFnt
)
89 return UNDERLINE_NONE
== rFnt
.GetUnderline() ||
90 rPor
.IsFlyPortion() || rPor
.IsFlyCntPortion() ||
91 rPor
.IsBreakPortion() || rPor
.IsMarginPortion() ||
92 rPor
.IsHolePortion() ||
93 ( rPor
.IsMultiPortion() && ! ((SwMultiPortion
&)rPor
).IsBidi() ) ||
94 rFnt
.GetEscapement() < 0 || rFnt
.IsWordLineMode() ||
95 SVX_CASEMAP_KAPITAELCHEN
== rFnt
.GetCaseMap();
98 /*************************************************************************
99 * SwTxtPainter::CtorInitTxtPainter()
100 *************************************************************************/
101 void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm
*pNewFrm
, SwTxtPaintInfo
*pNewInf
)
103 CtorInitTxtCursor( pNewFrm
, pNewInf
);
105 SwFont
*pMyFnt
= GetFnt();
106 GetInfo().SetFont( pMyFnt
);
108 if( ALIGN_BASELINE
!= pMyFnt
->GetAlign() )
110 ASSERT( ALIGN_BASELINE
== pMyFnt
->GetAlign(),
111 "+SwTxtPainter::CTOR: font alignment revolution" );
112 pMyFnt
->SetAlign( ALIGN_BASELINE
);
115 bPaintDrop
= sal_False
;
119 /*************************************************************************
120 * SwTxtPainter::CalcPaintOfst()
121 *************************************************************************/
122 SwLinePortion
*SwTxtPainter::CalcPaintOfst( const SwRect
&rPaint
)
124 SwLinePortion
*pPor
= pCurr
->GetFirstPortion();
125 GetInfo().SetPaintOfst( 0 );
126 SwTwips nPaintOfst
= rPaint
.Left();
128 // nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
129 // nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
130 // const KSHORT nLeftMar = KSHORT(GetLeftMargin());
131 // 8310: painten von LineBreaks in leeren Zeilen.
132 if( nPaintOfst
&& pCurr
->Width() )
134 SwLinePortion
*pLast
= 0;
135 // 7529 und 4757: nicht <= nPaintOfst
136 while( pPor
&& GetInfo().X() + pPor
->Width() + (pPor
->Height()/2)
140 if( pPor
->InSpaceGrp() && GetInfo().GetSpaceAdd() )
142 long nTmp
= GetInfo().X() +pPor
->Width() +
143 pPor
->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
144 if( nTmp
+ (pPor
->Height()/2) >= nPaintOfst
)
147 GetInfo().SetIdx( GetInfo().GetIdx() + pPor
->GetLen() );
150 pPor
->Move( GetInfo() );
152 pPor
= pPor
->GetPortion();
155 // 7529: bei PostIts auch pLast returnen.
156 if( pLast
&& !pLast
->Width() && pLast
->IsPostItsPortion() )
159 GetInfo().SetIdx( GetInfo().GetIdx() - pPor
->GetLen() );
165 /*************************************************************************
166 * SwTxtPainter::DrawTextLine()
168 * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
169 * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
170 * (objektiv schnell, subjektiv langsam).
171 * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
172 * ausgefuehrt (objektiv langsam, subjektiv schnell).
173 * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
174 * als Default eingestellt.
175 *************************************************************************/
176 void SwTxtPainter::DrawTextLine( const SwRect
&rPaint
, SwSaveClip
&rClip
,
177 const sal_Bool bUnderSz
)
179 #if OSL_DEBUG_LEVEL > 1
180 // USHORT nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
181 // USHORT nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
184 // Adjustierung ggf. nachholen
186 GetInfo().SetpSpaceAdd( pCurr
->GetpLLSpaceAdd() );
187 GetInfo().ResetSpaceIdx();
188 GetInfo().SetKanaComp( pCurr
->GetpKanaComp() );
189 GetInfo().ResetKanaIdx();
190 // Die Groesse des Frames
191 GetInfo().SetIdx( GetStart() );
192 GetInfo().SetPos( GetTopLeft() );
194 const sal_Bool bDrawInWindow
= GetInfo().OnWin();
196 // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
197 const sal_Bool bEndPor
= GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
199 SwLinePortion
*pPor
= bEndPor
? pCurr
->GetFirstPortion() : CalcPaintOfst( rPaint
);
202 const SwTwips nMaxRight
= Min( rPaint
.Right(), Right() );
203 const SwTwips nTmpLeft
= GetInfo().X();
204 if( !bEndPor
&& nTmpLeft
>= nMaxRight
)
208 // 7538: natuerlich auch auf dem Drucker
211 // 8084: Optimierung, weniger Painten.
212 // AMA: Durch 8084 wurde 7538 wiederbelebt!
213 // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
214 bPaintDrop
= pPor
== pCurr
->GetFirstPortion()
215 && GetDropLines() >= GetLineNr();
218 KSHORT nTmpHeight
, nTmpAscent
;
219 CalcAscentAndHeight( nTmpAscent
, nTmpHeight
);
221 // bClip entscheidet darueber, ob geclippt werden muss.
222 // Das Ganze muss vor der Retusche stehen
224 sal_Bool bClip
= ( bDrawInWindow
|| bUnderSz
) && !rClip
.IsChg();
227 // Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
228 // muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
229 // in der folgenden Ausgabeschleife...
231 if( GetInfo().GetPos().X() < rPaint
.Left() ||
232 GetInfo().GetPos().Y() < rPaint
.Top() ||
233 GetInfo().GetPos().Y() + nTmpHeight
> rPaint
.Top() + rPaint
.Height() )
236 rClip
.ChgClip( rPaint
, pFrm
, pCurr
->HasUnderscore() );
238 #if OSL_DEBUG_LEVEL > 1
239 static sal_Bool bClipAlways
= sal_False
;
240 if( bClip
&& bClipAlways
)
242 rClip
.ChgClip( rPaint
);
248 sal_Bool bPlus
= sal_False
;
249 OutputDevice
* pOut
= GetInfo().GetOut();
250 Point
aPnt1( nTmpLeft
, GetInfo().GetPos().Y() );
251 if ( aPnt1
.X() < rPaint
.Left() )
252 aPnt1
.X() = rPaint
.Left();
253 if ( aPnt1
.Y() < rPaint
.Top() )
254 aPnt1
.Y() = rPaint
.Top();
255 Point
aPnt2( GetInfo().GetPos().X() + nMaxRight
- GetInfo().X(),
256 GetInfo().GetPos().Y() + nTmpHeight
);
257 if ( aPnt2
.X() > rPaint
.Right() )
258 aPnt2
.X() = rPaint
.Right();
259 if ( aPnt2
.Y() > rPaint
.Bottom() )
261 aPnt2
.Y() = rPaint
.Bottom();
265 const SwRect
aLineRect( aPnt1
, aPnt2
);
267 if( pCurr
->IsClipping() )
269 rClip
.ChgClip( aLineRect
, pFrm
);
273 if( !pPor
&& !bEndPor
)
276 aDbstream
<< "PAINTER: done nothing" << endl
;
281 // Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
282 // if no special vertical alignment is used,
283 // we calculate Y value for the whole line
284 GETGRID( GetTxtFrm()->FindPageFrm() )
285 const sal_Bool bAdjustBaseLine
=
286 GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
288 const SwTwips nLineBaseLine
= GetInfo().GetPos().Y() + nTmpAscent
;
289 if ( ! bAdjustBaseLine
)
290 GetInfo().Y( nLineBaseLine
);
292 // 7529: PostIts prepainten
293 if( GetInfo().OnWin() && pPor
&& !pPor
->Width() )
295 SeekAndChg( GetInfo() );
297 if( bAdjustBaseLine
)
299 const SwTwips nOldY
= GetInfo().Y();
301 GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr
, 0,
302 GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut
),
303 GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut
)
306 pPor
->PrePaint( GetInfo(), pPor
);
307 GetInfo().Y( nOldY
);
310 pPor
->PrePaint( GetInfo(), pPor
);
313 // 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
315 SeekStartAndChg( GetInfo() );
317 sal_Bool bRest
= pCurr
->IsRest();
318 sal_Bool bFirst
= sal_True
;
320 SwArrowPortion
*pArrow
= NULL
;
321 // Reference portion for the paragraph end portion
322 SwLinePortion
* pEndTempl
= pCurr
->GetFirstPortion();
327 sal_Bool bSeeked
= sal_True
;
328 GetInfo().SetLen( pPor
->GetLen() );
330 const SwTwips nOldY
= GetInfo().Y();
332 if ( bAdjustBaseLine
)
334 GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr
, pPor
) );
336 // we store the last portion, because a possible paragraph
337 // end character has the same font as this portion
338 // (only in special vertical alignment case, otherwise the first
339 // portion of the line is used)
340 if ( pPor
->Width() && pPor
->InTxtGrp() )
344 // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
346 // 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
347 // Portion an, dies wird durch SeekAndChgBefore vermieden:
348 if( ( bRest
&& pPor
->InFldGrp() && !pPor
->GetLen() ) )
349 SeekAndChgBefore( GetInfo() );
350 else if ( pPor
->IsQuoVadisPortion() )
352 xub_StrLen nOffset
= GetInfo().GetIdx();
353 SeekStartAndChg( GetInfo(), sal_True
);
354 if( GetRedln() && pCurr
->HasRedline() )
355 GetRedln()->Seek( *pFnt
, nOffset
, 0 );
357 else if( pPor
->InTxtGrp() || pPor
->InFldGrp() || pPor
->InTabGrp() )
358 SeekAndChg( GetInfo() );
359 else if ( !bFirst
&& pPor
->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
361 // Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
362 // haben, es sei denn, es gibt Redlining in dem Absatz.
364 SeekAndChg( GetInfo() );
366 SeekAndChgBefore( GetInfo() );
371 // bRest = sal_False;
373 // Wenn das Ende der Portion hinausragt, wird geclippt.
374 // Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
375 // damit die TTF-"f" nicht im Seitenrand haengen...
377 GetInfo().X() + pPor
->Width() + ( pPor
->Height() / 2 ) > nMaxRight
)
380 rClip
.ChgClip( rPaint
, pFrm
, pCurr
->HasUnderscore() );
383 // Portions, die "unter" dem Text liegen wie PostIts
384 SwLinePortion
*pNext
= pPor
->GetPortion();
385 if( GetInfo().OnWin() && pNext
&& !pNext
->Width() )
387 // Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
388 // Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
389 // durch bSeeked wird Last!=Owner vermieden.
391 SeekAndChg( GetInfo() );
392 pNext
->PrePaint( GetInfo(), pPor
);
395 // We calculate a separate font for underlining.
396 CheckSpecialUnderline( pPor
, bAdjustBaseLine
? nOldY
: 0 );
397 SwUnderlineFont
* pUnderLineFnt
= GetInfo().GetUnderFnt();
400 const Point
aTmpPoint( GetInfo().X(),
402 pUnderLineFnt
->GetPos().Y() :
404 pUnderLineFnt
->SetPos( aTmpPoint
);
408 // in extended input mode we do not want a common underline font.
409 SwUnderlineFont
* pOldUnderLineFnt
= 0;
410 if ( GetRedln() && GetRedln()->ExtOn() )
412 pOldUnderLineFnt
= GetInfo().GetUnderFnt();
413 GetInfo().SetUnderFnt( 0 );
417 // --> FME 2004-06-24 #i16816# tagged pdf support
418 Por_Info
aPorInfo( *pPor
, *this );
419 SwTaggedPDFHelper
aTaggedPDFHelper( 0, 0, &aPorInfo
, *pOut
);
422 if( pPor
->IsMultiPortion() )
423 PaintMultiPortion( rPaint
, (SwMultiPortion
&)*pPor
);
425 pPor
->Paint( GetInfo() );
428 // reset underline font
429 if ( pOldUnderLineFnt
)
430 GetInfo().SetUnderFnt( pOldUnderLineFnt
);
432 // reset (for special vertical alignment)
433 GetInfo().Y( nOldY
);
435 if( GetFnt()->IsURL() && pPor
->InTxtGrp() )
436 GetInfo().NotifyURL( *pPor
);
438 bFirst
&= !pPor
->GetLen();
439 if( pNext
|| !pPor
->IsMarginPortion() )
440 pPor
->Move( GetInfo() );
441 if( pPor
->IsArrowPortion() && GetInfo().OnWin() && !pArrow
)
442 pArrow
= (SwArrowPortion
*)pPor
;
444 pPor
= bDrawInWindow
|| GetInfo().X() <= nMaxRight
||
445 // --> FME 2004-06-24 #i16816# tagged pdf support
446 ( GetInfo().GetVsh() &&
447 GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
448 pNext
&& pNext
->IsHolePortion() ) ?
454 // delete underline font
455 delete GetInfo().GetUnderFnt();
456 GetInfo().SetUnderFnt( 0 );
458 // paint remaining stuff
461 // If special vertical alignment is enabled, GetInfo().Y() is the
462 // top of the current line. Therefore is has to be adjusted for
463 // the painting of the remaining stuff. We first store the old value.
464 const SwTwips nOldY
= GetInfo().Y();
466 if( !GetNextLine() &&
467 GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
468 GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
469 GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
471 const SwTmpEndPortion
aEnd( *pEndTempl
);
472 GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut
);
474 if ( bAdjustBaseLine
)
475 GetInfo().Y( GetInfo().GetPos().Y()
476 + AdjustBaseLine( *pCurr
, &aEnd
) );
478 aEnd
.Paint( GetInfo() );
479 GetInfo().Y( nOldY
);
481 if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
483 const sal_Bool bNextUndersized
=
484 ( GetTxtFrm()->GetNext() &&
485 0 == GetTxtFrm()->GetNext()->Prt().Height() &&
486 GetTxtFrm()->GetNext()->IsTxtFrm() &&
487 ((SwTxtFrm
*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
489 if( bUnderSz
|| bNextUndersized
)
491 if ( bAdjustBaseLine
)
492 GetInfo().Y( GetInfo().GetPos().Y() + pCurr
->GetAscent() );
495 GetInfo().DrawRedArrow( *pArrow
);
497 // GetInfo().Y() must be current baseline.
498 SwTwips nDiff
= GetInfo().Y() + nTmpHeight
- nTmpAscent
- GetTxtFrm()->Frm().Bottom();
500 ( GetEnd() < GetInfo().GetTxt().Len() ||
501 ( nDiff
> nTmpHeight
/2 && GetPrevLine() ) ) ) ||
502 nDiff
>= 0 && bNextUndersized
)
505 SwArrowPortion
aArrow( GetInfo() );
506 GetInfo().DrawRedArrow( aArrow
);
509 GetInfo().Y( nOldY
);
514 if( pCurr
->IsClipping() )
515 rClip
.ChgClip( rPaint
, pFrm
);
518 void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion
* pPor
,
519 long nAdjustBaseLine
)
521 // Check if common underline should not be continued.
522 if ( IsUnderlineBreak( *pPor
, *pFnt
) )
524 // delete underline font
525 delete GetInfo().GetUnderFnt();
526 GetInfo().SetUnderFnt( 0 );
530 // If current underline matches the common underline font, we continue
531 // to use the common underline font.
532 if ( GetInfo().GetUnderFnt() &&
533 GetInfo().GetUnderFnt()->GetFont().GetUnderline() ==
534 GetFnt()->GetUnderline() )
537 // calculate the new common underline font
538 SwFont
* pUnderlineFnt
= 0;
539 Point aCommonBaseLine
;
541 Range
aRange( 0, GetInfo().GetTxt().Len() );
542 MultiSelection
aUnderMulti( aRange
);
544 ASSERT( GetFnt() && UNDERLINE_NONE
!= GetFnt()->GetUnderline(),
545 "CheckSpecialUnderline without underlined font" )
546 const SwFont
* pParaFnt
= GetAttrHandler().GetFont();
547 if( pParaFnt
&& pParaFnt
->GetUnderline() == GetFnt()->GetUnderline() )
548 aUnderMulti
.SelectAll();
553 sal_Bool bUnder
= sal_False
;
556 while( nTmp
< pHints
->GetStartCount() )
558 pTxtAttr
= pHints
->GetStart( nTmp
++ );
559 sal_Bool bUnderSelect
= sal_False
;
561 const SvxUnderlineItem
* pItem
=
562 static_cast<const SvxUnderlineItem
*>(CharFmt::GetItem( *pTxtAttr
, RES_CHRATR_UNDERLINE
));
567 bUnderSelect
= pFnt
->GetUnderline() == pItem
->GetLineStyle();
572 xub_StrLen nSt
= *pTxtAttr
->GetStart();
573 xub_StrLen nEnd
= *pTxtAttr
->GetEnd();
576 Range
aTmp( nSt
, nEnd
- 1 );
578 aUnderMulti
.Select( aTmp
, bUnderSelect
);
586 xub_StrLen nIndx
= GetInfo().GetIdx();
587 long nUnderStart
= 0;
589 MSHORT nCnt
= (MSHORT
)aUnderMulti
.GetRangeCount();
591 // find the underline range the current portion is contained in
592 for( i
= 0; i
< nCnt
; ++i
)
594 const Range
& rRange
= aUnderMulti
.GetRange( i
);
595 if( nUnderEnd
== rRange
.Min() )
596 nUnderEnd
= rRange
.Max();
597 else if( nIndx
>= rRange
.Min() )
599 nUnderStart
= rRange
.Min();
600 nUnderEnd
= rRange
.Max();
606 // restrict start and end to current line
607 if ( GetStart() > nUnderStart
)
608 nUnderStart
= GetStart();
610 if ( GetEnd() && GetEnd() <= nUnderEnd
)
611 nUnderEnd
= GetEnd() - 1;
614 // check, if underlining is not isolated
615 if ( nIndx
+ GetInfo().GetLen() < nUnderEnd
+ 1 )
618 // here starts the algorithm for calculating the underline font
620 SwScriptInfo
& rScriptInfo
= GetInfo().GetParaPortion()->GetScriptInfo();
621 SwAttrIter
aIter( *(SwTxtNode
*)GetInfo().GetTxtFrm()->GetTxtNode(),
624 xub_StrLen nTmpIdx
= nIndx
;
626 ULONG nSumHeight
= 0;
628 USHORT nMaxBaseLineOfst
= 0;
629 USHORT nNumberOfPortions
= 0;
631 while( nTmpIdx
<= nUnderEnd
&& pPor
)
633 if ( pPor
->IsFlyPortion() || pPor
->IsFlyCntPortion() ||
634 pPor
->IsBreakPortion() || pPor
->IsMarginPortion() ||
635 pPor
->IsHolePortion() ||
636 ( pPor
->IsMultiPortion() && ! ((SwMultiPortion
*)pPor
)->IsBidi() ) )
639 aIter
.Seek( nTmpIdx
);
641 if ( aIter
.GetFnt()->GetEscapement() < 0 || pFnt
->IsWordLineMode() ||
642 SVX_CASEMAP_KAPITAELCHEN
== pFnt
->GetCaseMap() )
645 if ( !aIter
.GetFnt()->GetEscapement() )
647 nSumWidth
+= pPor
->Width();
648 const ULONG nFontHeight
= aIter
.GetFnt()->GetHeight();
650 // If we do not have a common baseline we take the baseline
651 // and the font of the lowest portion.
652 if ( nAdjustBaseLine
)
654 USHORT nTmpBaseLineOfst
= AdjustBaseLine( *pCurr
, pPor
);
655 if ( nMaxBaseLineOfst
< nTmpBaseLineOfst
)
657 nMaxBaseLineOfst
= nTmpBaseLineOfst
;
658 nSumHeight
= nFontHeight
;
661 // in horizontal layout we build a weighted sum of the heights
663 nSumHeight
+= pPor
->Width() * nFontHeight
;
665 if ( WEIGHT_NORMAL
!= aIter
.GetFnt()->GetWeight() )
666 nBold
+= pPor
->Width();
671 nTmpIdx
= nTmpIdx
+ pPor
->GetLen();
672 pPor
= pPor
->GetPortion();
676 if ( nNumberOfPortions
> 1 && nSumWidth
)
678 const ULONG nNewFontHeight
= nAdjustBaseLine
?
680 nSumHeight
/ nSumWidth
;
682 pUnderlineFnt
= new SwFont( *GetInfo().GetFont() );
685 const BYTE nActual
= pUnderlineFnt
->GetActual();
686 pUnderlineFnt
->SetSize( Size( pUnderlineFnt
->GetSize( nActual
).Width(),
687 nNewFontHeight
), nActual
);
690 if ( 2 * nBold
> nSumWidth
)
691 pUnderlineFnt
->SetWeight( WEIGHT_BOLD
, nActual
);
693 pUnderlineFnt
->SetWeight( WEIGHT_NORMAL
, nActual
);
696 aCommonBaseLine
.Y() = nAdjustBaseLine
+ nMaxBaseLineOfst
;
700 // an escaped redlined portion should also have a special underlining
701 if( ! pUnderlineFnt
&& pFnt
->GetEscapement() > 0 && GetRedln() &&
702 GetRedln()->ChkSpecialUnderline() )
703 pUnderlineFnt
= new SwFont( *pFnt
);
705 delete GetInfo().GetUnderFnt();
709 pUnderlineFnt
->SetProportion( 100 );
710 pUnderlineFnt
->SetEscapement( 0 );
711 pUnderlineFnt
->SetStrikeout( STRIKEOUT_NONE
);
712 pUnderlineFnt
->SetOverline( UNDERLINE_NONE
);
713 const Color
aFillColor( COL_TRANSPARENT
);
714 pUnderlineFnt
->SetFillColor( aFillColor
);
716 GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt
,
720 // I'm sorry, we do not have a special underlining font for you.
721 GetInfo().SetUnderFnt( 0 );