xref: /aoo41x/main/sw/source/core/text/itrpaint.cxx (revision 70544ec4)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include "hintids.hxx"
29cdf0e10cSrcweir #include "flyfrm.hxx"	  // SwFlyInCntFrm
30cdf0e10cSrcweir #include "viewopt.hxx"	// SwViewOptions
31cdf0e10cSrcweir #include "errhdl.hxx"
32cdf0e10cSrcweir #include "txtatr.hxx"  // SwINetFmt
33cdf0e10cSrcweir #include <tools/multisel.hxx>
34cdf0e10cSrcweir #include <editeng/escpitem.hxx>
35cdf0e10cSrcweir #include <editeng/udlnitem.hxx>
36cdf0e10cSrcweir #include <editeng/lrspitem.hxx>
37cdf0e10cSrcweir #include <txtinet.hxx>
38cdf0e10cSrcweir #include <fchrfmt.hxx>
39cdf0e10cSrcweir #include <frmatr.hxx>
40cdf0e10cSrcweir #include <sfx2/printer.hxx>
41cdf0e10cSrcweir #include <fmtftn.hxx>
42cdf0e10cSrcweir #include <fmtfld.hxx>
43cdf0e10cSrcweir #include <fldbas.hxx>      // SwField
44cdf0e10cSrcweir #include <rootfrm.hxx>
45cdf0e10cSrcweir #include <pagefrm.hxx>
46cdf0e10cSrcweir #include <pagedesc.hxx> // SwPageDesc
47cdf0e10cSrcweir #include <tgrditem.hxx>
48cdf0e10cSrcweir 
49cdf0e10cSrcweir // --> FME 2004-06-08 #i12836# enhanced pdf export
50cdf0e10cSrcweir #include <EnhancedPDFExportHelper.hxx>
51cdf0e10cSrcweir // <--
52cdf0e10cSrcweir 
53cdf0e10cSrcweir 
54cdf0e10cSrcweir #include "flyfrms.hxx"
55cdf0e10cSrcweir #include "viewsh.hxx"
56cdf0e10cSrcweir #include "txtcfg.hxx"
57cdf0e10cSrcweir #include "itrpaint.hxx"
58cdf0e10cSrcweir #include "txtfrm.hxx"   // pFrm
59cdf0e10cSrcweir #include "txtfly.hxx"
60cdf0e10cSrcweir #include "swfont.hxx"
61cdf0e10cSrcweir #include "txtpaint.hxx"
62cdf0e10cSrcweir #include "portab.hxx"   // SwTabPortion::IsFilled
63cdf0e10cSrcweir #include "porfly.hxx"	  // SwFlyCntPortion
64cdf0e10cSrcweir #include "porfld.hxx"	// SwGrfNumPortion
65cdf0e10cSrcweir #include "frmfmt.hxx"	// LRSpace
66cdf0e10cSrcweir #include "txatbase.hxx" // SwTxtAttr
67cdf0e10cSrcweir #include "charfmt.hxx"  // SwFmtCharFmt
68cdf0e10cSrcweir #include "redlnitr.hxx" // SwRedlineItr
69cdf0e10cSrcweir #include "porrst.hxx"	// SwArrowPortion
70cdf0e10cSrcweir #include "pormulti.hxx"
71cdf0e10cSrcweir 
72cdf0e10cSrcweir /*************************************************************************
73cdf0e10cSrcweir  *                  IsUnderlineBreak
74cdf0e10cSrcweir  *
75cdf0e10cSrcweir  * Returns, if we have an underline breaking situation
76cdf0e10cSrcweir  * Adding some more conditions here means you also have to change them
77cdf0e10cSrcweir  * in SwTxtPainter::CheckSpecialUnderline
78cdf0e10cSrcweir  *************************************************************************/
IsUnderlineBreak(const SwLinePortion & rPor,const SwFont & rFnt)79cdf0e10cSrcweir sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
80cdf0e10cSrcweir {
81cdf0e10cSrcweir     return UNDERLINE_NONE == rFnt.GetUnderline() ||
82cdf0e10cSrcweir            rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
83cdf0e10cSrcweir            rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
84cdf0e10cSrcweir            rPor.IsHolePortion() ||
85cdf0e10cSrcweir           ( rPor.IsMultiPortion() && ! ((SwMultiPortion&)rPor).IsBidi() ) ||
86cdf0e10cSrcweir            rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
87cdf0e10cSrcweir            SVX_CASEMAP_KAPITAELCHEN == rFnt.GetCaseMap();
88cdf0e10cSrcweir }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir /*************************************************************************
91cdf0e10cSrcweir  *					SwTxtPainter::CtorInitTxtPainter()
92cdf0e10cSrcweir  *************************************************************************/
CtorInitTxtPainter(SwTxtFrm * pNewFrm,SwTxtPaintInfo * pNewInf)93cdf0e10cSrcweir void SwTxtPainter::CtorInitTxtPainter( SwTxtFrm *pNewFrm, SwTxtPaintInfo *pNewInf )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir     CtorInitTxtCursor( pNewFrm, pNewInf );
96cdf0e10cSrcweir 	pInf = pNewInf;
97cdf0e10cSrcweir     SwFont *pMyFnt = GetFnt();
98cdf0e10cSrcweir     GetInfo().SetFont( pMyFnt );
99cdf0e10cSrcweir #ifdef DBG_UTIL
100cdf0e10cSrcweir     if( ALIGN_BASELINE != pMyFnt->GetAlign() )
101cdf0e10cSrcweir 	{
102cdf0e10cSrcweir         ASSERT( ALIGN_BASELINE == pMyFnt->GetAlign(),
103cdf0e10cSrcweir 				"+SwTxtPainter::CTOR: font alignment revolution" );
104cdf0e10cSrcweir         pMyFnt->SetAlign( ALIGN_BASELINE );
105cdf0e10cSrcweir 	}
106cdf0e10cSrcweir #endif
107cdf0e10cSrcweir 	bPaintDrop = sal_False;
108cdf0e10cSrcweir }
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 
111cdf0e10cSrcweir /*************************************************************************
112cdf0e10cSrcweir  *					  SwTxtPainter::CalcPaintOfst()
113cdf0e10cSrcweir  *************************************************************************/
CalcPaintOfst(const SwRect & rPaint)114cdf0e10cSrcweir SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
115cdf0e10cSrcweir {
116cdf0e10cSrcweir 	SwLinePortion *pPor = pCurr->GetFirstPortion();
117cdf0e10cSrcweir 	GetInfo().SetPaintOfst( 0 );
118cdf0e10cSrcweir 	SwTwips nPaintOfst = rPaint.Left();
119cdf0e10cSrcweir 
120cdf0e10cSrcweir 	// nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
121cdf0e10cSrcweir 	// nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
122cdf0e10cSrcweir 	// const KSHORT nLeftMar = KSHORT(GetLeftMargin());
123cdf0e10cSrcweir 	// 8310: painten von LineBreaks in leeren Zeilen.
124cdf0e10cSrcweir 	if( nPaintOfst && pCurr->Width() )
125cdf0e10cSrcweir 	{
126cdf0e10cSrcweir 		SwLinePortion *pLast = 0;
127cdf0e10cSrcweir 		// 7529 und 4757: nicht <= nPaintOfst
128cdf0e10cSrcweir 		while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
129cdf0e10cSrcweir 					   < nPaintOfst )
130cdf0e10cSrcweir 		{
131cdf0e10cSrcweir 			DBG_LOOP;
132cdf0e10cSrcweir 			if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
133cdf0e10cSrcweir 			{
134cdf0e10cSrcweir 				long nTmp = GetInfo().X() +pPor->Width() +
135cdf0e10cSrcweir 					pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
136cdf0e10cSrcweir 				if( nTmp + (pPor->Height()/2) >= nPaintOfst )
137cdf0e10cSrcweir 					break;
138cdf0e10cSrcweir 				GetInfo().X( nTmp );
139cdf0e10cSrcweir 				GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
140cdf0e10cSrcweir 			}
141cdf0e10cSrcweir 			else
142cdf0e10cSrcweir 				pPor->Move( GetInfo() );
143cdf0e10cSrcweir 			pLast = pPor;
144cdf0e10cSrcweir 			pPor = pPor->GetPortion();
145cdf0e10cSrcweir 		}
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 		// 7529: bei PostIts auch pLast returnen.
148cdf0e10cSrcweir 		if( pLast && !pLast->Width() &&	pLast->IsPostItsPortion() )
149cdf0e10cSrcweir 		{
150cdf0e10cSrcweir 			pPor = pLast;
151cdf0e10cSrcweir 			GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
152cdf0e10cSrcweir 		}
153cdf0e10cSrcweir 	}
154cdf0e10cSrcweir 	return pPor;
155cdf0e10cSrcweir }
156cdf0e10cSrcweir 
157cdf0e10cSrcweir /*************************************************************************
158cdf0e10cSrcweir  *                    SwTxtPainter::DrawTextLine()
159cdf0e10cSrcweir  *
160cdf0e10cSrcweir  * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
161cdf0e10cSrcweir  * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
162cdf0e10cSrcweir  *	  (objektiv schnell, subjektiv langsam).
163cdf0e10cSrcweir  * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
164cdf0e10cSrcweir  *	  ausgefuehrt (objektiv langsam, subjektiv schnell).
165cdf0e10cSrcweir  * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
166cdf0e10cSrcweir  * als Default eingestellt.
167cdf0e10cSrcweir  *************************************************************************/
DrawTextLine(const SwRect & rPaint,SwSaveClip & rClip,const sal_Bool bUnderSz)168cdf0e10cSrcweir void SwTxtPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
169cdf0e10cSrcweir 								 const sal_Bool bUnderSz )
170cdf0e10cSrcweir {
171cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
172cdf0e10cSrcweir //    sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
173cdf0e10cSrcweir //    sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
174cdf0e10cSrcweir #endif
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     // Adjustierung ggf. nachholen
177cdf0e10cSrcweir 	GetAdjusted();
178cdf0e10cSrcweir     GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
179cdf0e10cSrcweir 	GetInfo().ResetSpaceIdx();
180cdf0e10cSrcweir     GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
181cdf0e10cSrcweir     GetInfo().ResetKanaIdx();
182cdf0e10cSrcweir 	// Die Groesse des Frames
183cdf0e10cSrcweir 	GetInfo().SetIdx( GetStart() );
184cdf0e10cSrcweir 	GetInfo().SetPos( GetTopLeft() );
185cdf0e10cSrcweir 
186cdf0e10cSrcweir 	const sal_Bool bDrawInWindow = GetInfo().OnWin();
187cdf0e10cSrcweir 
188cdf0e10cSrcweir 	// 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
189cdf0e10cSrcweir 	const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
190cdf0e10cSrcweir 
191cdf0e10cSrcweir 	SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 	// Optimierung!
194cdf0e10cSrcweir 	const SwTwips nMaxRight = Min( rPaint.Right(), Right() );
195cdf0e10cSrcweir 	const SwTwips nTmpLeft = GetInfo().X();
196cdf0e10cSrcweir 	if( !bEndPor && nTmpLeft >= nMaxRight )
197cdf0e10cSrcweir 		return;
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 	// DropCaps!
200cdf0e10cSrcweir 	// 7538: natuerlich auch auf dem Drucker
201cdf0e10cSrcweir 	if( !bPaintDrop )
202cdf0e10cSrcweir 	{
203cdf0e10cSrcweir 		// 8084: Optimierung, weniger Painten.
204cdf0e10cSrcweir 		// AMA: Durch 8084 wurde 7538 wiederbelebt!
205cdf0e10cSrcweir 		// bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
206cdf0e10cSrcweir 		bPaintDrop = pPor == pCurr->GetFirstPortion()
207cdf0e10cSrcweir 					 && GetDropLines() >= GetLineNr();
208cdf0e10cSrcweir 	}
209cdf0e10cSrcweir 
210cdf0e10cSrcweir 	KSHORT nTmpHeight, nTmpAscent;
211cdf0e10cSrcweir 	CalcAscentAndHeight( nTmpAscent, nTmpHeight );
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 	// bClip entscheidet darueber, ob geclippt werden muss.
214cdf0e10cSrcweir 	// Das Ganze muss vor der Retusche stehen
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 	sal_Bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
217cdf0e10cSrcweir 	if( bClip && pPor )
218cdf0e10cSrcweir 	{
219cdf0e10cSrcweir 		// Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
220cdf0e10cSrcweir 		// muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
221cdf0e10cSrcweir 		// in der folgenden Ausgabeschleife...
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 		if( GetInfo().GetPos().X() < rPaint.Left() ||
224cdf0e10cSrcweir 			GetInfo().GetPos().Y() < rPaint.Top() ||
225cdf0e10cSrcweir 			GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
226cdf0e10cSrcweir 		{
227cdf0e10cSrcweir 			bClip = sal_False;
228cdf0e10cSrcweir             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
229cdf0e10cSrcweir 		}
230cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
231cdf0e10cSrcweir 		static sal_Bool bClipAlways = sal_False;
232cdf0e10cSrcweir 		if( bClip && bClipAlways )
233cdf0e10cSrcweir 		{	bClip = sal_False;
234cdf0e10cSrcweir 			rClip.ChgClip( rPaint );
235cdf0e10cSrcweir 		}
236cdf0e10cSrcweir #endif
237cdf0e10cSrcweir 	}
238cdf0e10cSrcweir 
239cdf0e10cSrcweir 	// Alignment:
240cdf0e10cSrcweir 	sal_Bool bPlus = sal_False;
241cdf0e10cSrcweir     OutputDevice* pOut = GetInfo().GetOut();
242cdf0e10cSrcweir 	Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
243cdf0e10cSrcweir 	if ( aPnt1.X() < rPaint.Left() )
244cdf0e10cSrcweir 		aPnt1.X() = rPaint.Left();
245cdf0e10cSrcweir 	if ( aPnt1.Y() < rPaint.Top() )
246cdf0e10cSrcweir 		aPnt1.Y() = rPaint.Top();
247cdf0e10cSrcweir 	Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
248cdf0e10cSrcweir 				 GetInfo().GetPos().Y() + nTmpHeight );
249cdf0e10cSrcweir 	if ( aPnt2.X() > rPaint.Right() )
250cdf0e10cSrcweir 		aPnt2.X() = rPaint.Right();
251cdf0e10cSrcweir 	if ( aPnt2.Y() > rPaint.Bottom() )
252cdf0e10cSrcweir 	{
253cdf0e10cSrcweir 		aPnt2.Y() = rPaint.Bottom();
254cdf0e10cSrcweir 		bPlus = sal_True;
255cdf0e10cSrcweir 	}
256cdf0e10cSrcweir 
257cdf0e10cSrcweir 	const SwRect aLineRect( aPnt1, aPnt2 );
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	if( pCurr->IsClipping() )
260cdf0e10cSrcweir 	{
261cdf0e10cSrcweir         rClip.ChgClip( aLineRect, pFrm );
262cdf0e10cSrcweir 		bClip = sal_False;
263cdf0e10cSrcweir 	}
264cdf0e10cSrcweir 
265cdf0e10cSrcweir 	if( !pPor && !bEndPor )
266cdf0e10cSrcweir 	{
267cdf0e10cSrcweir #ifdef DBGTXT
268cdf0e10cSrcweir 		aDbstream << "PAINTER: done nothing" << endl;
269cdf0e10cSrcweir #endif
270cdf0e10cSrcweir 		return;
271cdf0e10cSrcweir 	}
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 	// Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
274cdf0e10cSrcweir     // if no special vertical alignment is used,
275cdf0e10cSrcweir     // we calculate Y value for the whole line
276cdf0e10cSrcweir     GETGRID( GetTxtFrm()->FindPageFrm() )
277cdf0e10cSrcweir     const sal_Bool bAdjustBaseLine =
278cdf0e10cSrcweir         GetLineInfo().HasSpecialAlign( GetTxtFrm()->IsVertical() ) ||
279cdf0e10cSrcweir         ( 0 != pGrid );
280cdf0e10cSrcweir     const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
281cdf0e10cSrcweir     if ( ! bAdjustBaseLine )
282cdf0e10cSrcweir         GetInfo().Y( nLineBaseLine );
283cdf0e10cSrcweir 
284cdf0e10cSrcweir 	// 7529: PostIts prepainten
285cdf0e10cSrcweir 	if( GetInfo().OnWin() && pPor && !pPor->Width() )
286cdf0e10cSrcweir 	{
287cdf0e10cSrcweir 		SeekAndChg( GetInfo() );
288cdf0e10cSrcweir 
289cdf0e10cSrcweir         if( bAdjustBaseLine )
290cdf0e10cSrcweir         {
291cdf0e10cSrcweir             const SwTwips nOldY = GetInfo().Y();
292cdf0e10cSrcweir 
293cdf0e10cSrcweir             GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, 0,
294cdf0e10cSrcweir                 GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
295cdf0e10cSrcweir                 GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
296cdf0e10cSrcweir             ) );
297cdf0e10cSrcweir 
298cdf0e10cSrcweir             pPor->PrePaint( GetInfo(), pPor );
299cdf0e10cSrcweir             GetInfo().Y( nOldY );
300cdf0e10cSrcweir         }
301cdf0e10cSrcweir         else
302cdf0e10cSrcweir             pPor->PrePaint( GetInfo(), pPor );
303cdf0e10cSrcweir 	}
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 	// 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
306cdf0e10cSrcweir 	if( bEndPor )
307cdf0e10cSrcweir 		SeekStartAndChg( GetInfo() );
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 	sal_Bool bRest = pCurr->IsRest();
310cdf0e10cSrcweir 	sal_Bool bFirst = sal_True;
311cdf0e10cSrcweir 
312cdf0e10cSrcweir 	SwArrowPortion *pArrow = NULL;
313cdf0e10cSrcweir     // Reference portion for the paragraph end portion
314cdf0e10cSrcweir     SwLinePortion* pEndTempl = pCurr->GetFirstPortion();
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 	while( pPor )
317cdf0e10cSrcweir 	{
318cdf0e10cSrcweir 		DBG_LOOP;
319cdf0e10cSrcweir 		sal_Bool bSeeked = sal_True;
320cdf0e10cSrcweir 		GetInfo().SetLen( pPor->GetLen() );
321cdf0e10cSrcweir 
322cdf0e10cSrcweir         const SwTwips nOldY = GetInfo().Y();
323cdf0e10cSrcweir 
324cdf0e10cSrcweir         if ( bAdjustBaseLine )
325cdf0e10cSrcweir         {
326cdf0e10cSrcweir             GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *pCurr, pPor ) );
327cdf0e10cSrcweir 
328cdf0e10cSrcweir             // we store the last portion, because a possible paragraph
329cdf0e10cSrcweir             // end character has the same font as this portion
330cdf0e10cSrcweir             // (only in special vertical alignment case, otherwise the first
331cdf0e10cSrcweir             // portion of the line is used)
332cdf0e10cSrcweir             if ( pPor->Width() && pPor->InTxtGrp() )
333cdf0e10cSrcweir                 pEndTempl = pPor;
334cdf0e10cSrcweir         }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 		// Ein Sonderfall sind GluePortions, die Blanks ausgeben.
337cdf0e10cSrcweir 
338cdf0e10cSrcweir 		// 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
339cdf0e10cSrcweir 		// Portion an, dies wird durch SeekAndChgBefore vermieden:
340cdf0e10cSrcweir 		if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
341cdf0e10cSrcweir 			SeekAndChgBefore( GetInfo() );
342cdf0e10cSrcweir 		else if ( pPor->IsQuoVadisPortion() )
343cdf0e10cSrcweir 		{
344cdf0e10cSrcweir 			xub_StrLen nOffset = GetInfo().GetIdx();
345cdf0e10cSrcweir 			SeekStartAndChg( GetInfo(), sal_True );
346cdf0e10cSrcweir 			if( GetRedln() && pCurr->HasRedline() )
347cdf0e10cSrcweir 				GetRedln()->Seek( *pFnt, nOffset, 0 );
348cdf0e10cSrcweir 		}
349cdf0e10cSrcweir 		else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
350cdf0e10cSrcweir 			SeekAndChg( GetInfo() );
351cdf0e10cSrcweir 		else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
352cdf0e10cSrcweir 		{
353cdf0e10cSrcweir 			// Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
354cdf0e10cSrcweir 			// haben, es sei denn, es gibt Redlining in dem Absatz.
355cdf0e10cSrcweir 			if( GetRedln() )
356cdf0e10cSrcweir 				SeekAndChg( GetInfo() );
357cdf0e10cSrcweir 			else
358cdf0e10cSrcweir 				SeekAndChgBefore( GetInfo() );
359cdf0e10cSrcweir 		}
360cdf0e10cSrcweir 		else
361cdf0e10cSrcweir 			bSeeked = sal_False;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir //		bRest = sal_False;
364cdf0e10cSrcweir 
365cdf0e10cSrcweir 		// Wenn das Ende der Portion hinausragt, wird geclippt.
366cdf0e10cSrcweir 		// Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
367cdf0e10cSrcweir 		// damit die TTF-"f" nicht im Seitenrand haengen...
368cdf0e10cSrcweir         if( bClip &&
369cdf0e10cSrcweir             GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
370cdf0e10cSrcweir         {
371cdf0e10cSrcweir             bClip = sal_False;
372cdf0e10cSrcweir             rClip.ChgClip( rPaint, pFrm, pCurr->HasUnderscore() );
373cdf0e10cSrcweir 		}
374cdf0e10cSrcweir 
375cdf0e10cSrcweir 		// Portions, die "unter" dem Text liegen wie PostIts
376cdf0e10cSrcweir 		SwLinePortion *pNext = pPor->GetPortion();
377cdf0e10cSrcweir         if( GetInfo().OnWin() && pNext && !pNext->Width() )
378cdf0e10cSrcweir 		{
379cdf0e10cSrcweir 			// Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
380cdf0e10cSrcweir 			// Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
381cdf0e10cSrcweir 			// durch bSeeked wird Last!=Owner vermieden.
382cdf0e10cSrcweir 			if ( !bSeeked )
383cdf0e10cSrcweir 				SeekAndChg( GetInfo() );
384cdf0e10cSrcweir             pNext->PrePaint( GetInfo(), pPor );
385cdf0e10cSrcweir 		}
386cdf0e10cSrcweir 
387cdf0e10cSrcweir         // We calculate a separate font for underlining.
388cdf0e10cSrcweir         CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
389cdf0e10cSrcweir         SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
390cdf0e10cSrcweir         if ( pUnderLineFnt )
391cdf0e10cSrcweir         {
392cdf0e10cSrcweir             const Point aTmpPoint( GetInfo().X(),
393cdf0e10cSrcweir                                    bAdjustBaseLine ?
394cdf0e10cSrcweir                                    pUnderLineFnt->GetPos().Y() :
395cdf0e10cSrcweir                                    nLineBaseLine );
396cdf0e10cSrcweir             pUnderLineFnt->SetPos( aTmpPoint );
397cdf0e10cSrcweir         }
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 
400cdf0e10cSrcweir         // in extended input mode we do not want a common underline font.
401cdf0e10cSrcweir         SwUnderlineFont* pOldUnderLineFnt = 0;
402cdf0e10cSrcweir         if ( GetRedln() && GetRedln()->ExtOn() )
403cdf0e10cSrcweir         {
404cdf0e10cSrcweir             pOldUnderLineFnt = GetInfo().GetUnderFnt();
405cdf0e10cSrcweir             GetInfo().SetUnderFnt( 0 );
406cdf0e10cSrcweir         }
407cdf0e10cSrcweir 
408cdf0e10cSrcweir         {
409cdf0e10cSrcweir             // --> FME 2004-06-24 #i16816# tagged pdf support
410cdf0e10cSrcweir             Por_Info aPorInfo( *pPor, *this );
411cdf0e10cSrcweir             SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, &aPorInfo, *pOut );
412cdf0e10cSrcweir             // <--
413cdf0e10cSrcweir 
414cdf0e10cSrcweir             if( pPor->IsMultiPortion() )
415cdf0e10cSrcweir                 PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor );
416cdf0e10cSrcweir             else
417cdf0e10cSrcweir                 pPor->Paint( GetInfo() );
418cdf0e10cSrcweir         }
419cdf0e10cSrcweir 
420cdf0e10cSrcweir         // reset underline font
421cdf0e10cSrcweir         if ( pOldUnderLineFnt )
422cdf0e10cSrcweir             GetInfo().SetUnderFnt( pOldUnderLineFnt );
423cdf0e10cSrcweir 
424cdf0e10cSrcweir         // reset (for special vertical alignment)
425cdf0e10cSrcweir         GetInfo().Y( nOldY );
426cdf0e10cSrcweir 
427cdf0e10cSrcweir         if( GetFnt()->IsURL() && pPor->InTxtGrp() )
428cdf0e10cSrcweir 			GetInfo().NotifyURL( *pPor );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 		bFirst &= !pPor->GetLen();
431cdf0e10cSrcweir 		if( pNext || !pPor->IsMarginPortion() )
432cdf0e10cSrcweir 			pPor->Move( GetInfo() );
433cdf0e10cSrcweir 		if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
434cdf0e10cSrcweir 			pArrow = (SwArrowPortion*)pPor;
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
437cdf0e10cSrcweir                // --> FME 2004-06-24 #i16816# tagged pdf support
438cdf0e10cSrcweir                ( GetInfo().GetVsh() &&
439cdf0e10cSrcweir                  GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
440cdf0e10cSrcweir                  pNext && pNext->IsHolePortion() ) ?
441cdf0e10cSrcweir                // <--
442cdf0e10cSrcweir                pNext :
443cdf0e10cSrcweir                0;
444cdf0e10cSrcweir 	}
445cdf0e10cSrcweir 
446cdf0e10cSrcweir     // delete underline font
447cdf0e10cSrcweir     delete GetInfo().GetUnderFnt();
448cdf0e10cSrcweir     GetInfo().SetUnderFnt( 0 );
449cdf0e10cSrcweir 
450cdf0e10cSrcweir     // paint remaining stuff
451cdf0e10cSrcweir 	if( bDrawInWindow )
452cdf0e10cSrcweir 	{
453cdf0e10cSrcweir         // If special vertical alignment is enabled, GetInfo().Y() is the
454cdf0e10cSrcweir         // top of the current line. Therefore is has to be adjusted for
455cdf0e10cSrcweir         // the painting of the remaining stuff. We first store the old value.
456cdf0e10cSrcweir         const SwTwips nOldY = GetInfo().Y();
457cdf0e10cSrcweir 
458cdf0e10cSrcweir         if( !GetNextLine() &&
459cdf0e10cSrcweir 			GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
460cdf0e10cSrcweir 			GetInfo().GetOpt().IsParagraph() &&	!GetTxtFrm()->GetFollow() &&
461cdf0e10cSrcweir 			GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
462cdf0e10cSrcweir 		{
463cdf0e10cSrcweir             const SwTmpEndPortion aEnd( *pEndTempl );
464cdf0e10cSrcweir             GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
465cdf0e10cSrcweir 
466cdf0e10cSrcweir             if ( bAdjustBaseLine )
467cdf0e10cSrcweir                 GetInfo().Y( GetInfo().GetPos().Y()
468cdf0e10cSrcweir                            + AdjustBaseLine( *pCurr, &aEnd ) );
469cdf0e10cSrcweir 
470cdf0e10cSrcweir             aEnd.Paint( GetInfo() );
471cdf0e10cSrcweir             GetInfo().Y( nOldY );
472cdf0e10cSrcweir         }
473cdf0e10cSrcweir         if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
474cdf0e10cSrcweir         {
475cdf0e10cSrcweir             const sal_Bool bNextUndersized =
476cdf0e10cSrcweir                 ( GetTxtFrm()->GetNext() &&
477cdf0e10cSrcweir                   0 == GetTxtFrm()->GetNext()->Prt().Height() &&
478cdf0e10cSrcweir                   GetTxtFrm()->GetNext()->IsTxtFrm() &&
479cdf0e10cSrcweir                   ((SwTxtFrm*)GetTxtFrm()->GetNext())->IsUndersized() ) ;
480cdf0e10cSrcweir 
481cdf0e10cSrcweir             if( bUnderSz || bNextUndersized )
482cdf0e10cSrcweir 			{
483cdf0e10cSrcweir                 if ( bAdjustBaseLine )
484cdf0e10cSrcweir                     GetInfo().Y( GetInfo().GetPos().Y() + pCurr->GetAscent() );
485cdf0e10cSrcweir 
486cdf0e10cSrcweir                 if( pArrow )
487cdf0e10cSrcweir                     GetInfo().DrawRedArrow( *pArrow );
488cdf0e10cSrcweir 
489cdf0e10cSrcweir                 // GetInfo().Y() must be current baseline.
490cdf0e10cSrcweir                 SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
491cdf0e10cSrcweir                 if( ( nDiff > 0 &&
492cdf0e10cSrcweir                       ( GetEnd() < GetInfo().GetTxt().Len() ||
493cdf0e10cSrcweir                         ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
494cdf0e10cSrcweir                     (nDiff >= 0 && bNextUndersized) )
495cdf0e10cSrcweir 
496cdf0e10cSrcweir                 {
497cdf0e10cSrcweir                     SwArrowPortion aArrow( GetInfo() );
498cdf0e10cSrcweir                     GetInfo().DrawRedArrow( aArrow );
499cdf0e10cSrcweir                 }
500cdf0e10cSrcweir 
501cdf0e10cSrcweir                 GetInfo().Y( nOldY );
502cdf0e10cSrcweir 			}
503cdf0e10cSrcweir 		}
504cdf0e10cSrcweir 	}
505cdf0e10cSrcweir 
506cdf0e10cSrcweir     if( pCurr->IsClipping() )
507cdf0e10cSrcweir         rClip.ChgClip( rPaint, pFrm );
508cdf0e10cSrcweir }
509cdf0e10cSrcweir 
CheckSpecialUnderline(const SwLinePortion * pPor,long nAdjustBaseLine)510cdf0e10cSrcweir void SwTxtPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
511cdf0e10cSrcweir                                           long nAdjustBaseLine )
512cdf0e10cSrcweir {
513cdf0e10cSrcweir     // Check if common underline should not be continued.
514cdf0e10cSrcweir     if ( IsUnderlineBreak( *pPor, *pFnt ) )
515cdf0e10cSrcweir     {
516cdf0e10cSrcweir         // delete underline font
517cdf0e10cSrcweir         delete GetInfo().GetUnderFnt();
518cdf0e10cSrcweir         GetInfo().SetUnderFnt( 0 );
519cdf0e10cSrcweir         return;
520cdf0e10cSrcweir     }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     // If current underline matches the common underline font, we continue
523cdf0e10cSrcweir     // to use the common underline font.
524*70544ec4SJian Hong Cheng 	//Bug 120769:Color of underline display wrongly
525*70544ec4SJian Hong Cheng 		Color aAutoCo(COL_AUTO);
526cdf0e10cSrcweir     if ( GetInfo().GetUnderFnt() &&
527*70544ec4SJian Hong Cheng 		GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
528*70544ec4SJian Hong Cheng         GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != aAutoCo )
529*70544ec4SJian Hong Cheng 		return;
530*70544ec4SJian Hong Cheng 	//Bug 120769(End)
531cdf0e10cSrcweir     // calculate the new common underline font
532cdf0e10cSrcweir     SwFont* pUnderlineFnt = 0;
533cdf0e10cSrcweir     Point aCommonBaseLine;
534cdf0e10cSrcweir 
535cdf0e10cSrcweir     Range aRange( 0, GetInfo().GetTxt().Len() );
536cdf0e10cSrcweir     MultiSelection aUnderMulti( aRange );
537cdf0e10cSrcweir 
538cdf0e10cSrcweir     ASSERT( GetFnt() && UNDERLINE_NONE != GetFnt()->GetUnderline(),
539cdf0e10cSrcweir             "CheckSpecialUnderline without underlined font" )
540cdf0e10cSrcweir     const SwFont* pParaFnt = GetAttrHandler().GetFont();
541cdf0e10cSrcweir     if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
542cdf0e10cSrcweir         aUnderMulti.SelectAll();
543cdf0e10cSrcweir 
544cdf0e10cSrcweir     SwTxtAttr* pTxtAttr;
545cdf0e10cSrcweir     if( HasHints() )
546cdf0e10cSrcweir 	{
547cdf0e10cSrcweir         sal_Bool bUnder = sal_False;
548cdf0e10cSrcweir 		MSHORT nTmp = 0;
549cdf0e10cSrcweir 
550cdf0e10cSrcweir         while( nTmp < pHints->GetStartCount() )
551cdf0e10cSrcweir 		{
552cdf0e10cSrcweir 			pTxtAttr = pHints->GetStart( nTmp++ );
553cdf0e10cSrcweir             sal_Bool bUnderSelect = sal_False;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir             const SvxUnderlineItem* pItem =
556cdf0e10cSrcweir                     static_cast<const SvxUnderlineItem*>(CharFmt::GetItem( *pTxtAttr, RES_CHRATR_UNDERLINE ));
557cdf0e10cSrcweir 
558cdf0e10cSrcweir             if ( pItem )
559cdf0e10cSrcweir             {
560cdf0e10cSrcweir                 bUnder = sal_True;
561cdf0e10cSrcweir                 bUnderSelect = pFnt->GetUnderline() == pItem->GetLineStyle();
562cdf0e10cSrcweir             }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir             if( bUnder )
565cdf0e10cSrcweir 			{
566cdf0e10cSrcweir 				xub_StrLen nSt = *pTxtAttr->GetStart();
567cdf0e10cSrcweir 				xub_StrLen nEnd = *pTxtAttr->GetEnd();
568cdf0e10cSrcweir 				if( nEnd > nSt )
569cdf0e10cSrcweir 				{
570cdf0e10cSrcweir 					Range aTmp( nSt, nEnd - 1 );
571cdf0e10cSrcweir 					if( bUnder )
572cdf0e10cSrcweir 						aUnderMulti.Select( aTmp, bUnderSelect );
573cdf0e10cSrcweir 				}
574cdf0e10cSrcweir 				bUnder = sal_False;
575cdf0e10cSrcweir 			}
576cdf0e10cSrcweir 		}
577cdf0e10cSrcweir     }
578cdf0e10cSrcweir 
579cdf0e10cSrcweir     MSHORT i;
580cdf0e10cSrcweir     xub_StrLen nIndx = GetInfo().GetIdx();
581cdf0e10cSrcweir     long nUnderStart = 0;
582cdf0e10cSrcweir     long nUnderEnd = 0;
583cdf0e10cSrcweir     MSHORT nCnt = (MSHORT)aUnderMulti.GetRangeCount();
584cdf0e10cSrcweir 
585cdf0e10cSrcweir     // find the underline range the current portion is contained in
586cdf0e10cSrcweir     for( i = 0; i < nCnt; ++i )
587cdf0e10cSrcweir     {
588cdf0e10cSrcweir         const Range& rRange = aUnderMulti.GetRange( i );
589cdf0e10cSrcweir         if( nUnderEnd == rRange.Min() )
590cdf0e10cSrcweir             nUnderEnd = rRange.Max();
591cdf0e10cSrcweir         else if( nIndx >= rRange.Min() )
592cdf0e10cSrcweir         {
593cdf0e10cSrcweir             nUnderStart = rRange.Min();
594cdf0e10cSrcweir             nUnderEnd = rRange.Max();
595cdf0e10cSrcweir         }
596cdf0e10cSrcweir         else
597cdf0e10cSrcweir             break;
598cdf0e10cSrcweir     }
599cdf0e10cSrcweir 
600cdf0e10cSrcweir     // restrict start and end to current line
601cdf0e10cSrcweir     if ( GetStart() > nUnderStart )
602cdf0e10cSrcweir         nUnderStart = GetStart();
603cdf0e10cSrcweir 
604cdf0e10cSrcweir     if ( GetEnd() && GetEnd() <= nUnderEnd )
605cdf0e10cSrcweir         nUnderEnd = GetEnd() - 1;
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 
608cdf0e10cSrcweir     // check, if underlining is not isolated
609cdf0e10cSrcweir     if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
610cdf0e10cSrcweir     {
611cdf0e10cSrcweir         //
612cdf0e10cSrcweir         // here starts the algorithm for calculating the underline font
613cdf0e10cSrcweir         //
614cdf0e10cSrcweir         SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
615cdf0e10cSrcweir         SwAttrIter aIter( *(SwTxtNode*)GetInfo().GetTxtFrm()->GetTxtNode(),
616cdf0e10cSrcweir                           rScriptInfo );
617cdf0e10cSrcweir 
618cdf0e10cSrcweir         xub_StrLen nTmpIdx = nIndx;
619cdf0e10cSrcweir         sal_uLong nSumWidth = 0;
620cdf0e10cSrcweir         sal_uLong nSumHeight = 0;
621cdf0e10cSrcweir         sal_uLong nBold = 0;
622cdf0e10cSrcweir         sal_uInt16 nMaxBaseLineOfst = 0;
623cdf0e10cSrcweir         sal_uInt16 nNumberOfPortions = 0;
624cdf0e10cSrcweir 
625cdf0e10cSrcweir         while( nTmpIdx <= nUnderEnd && pPor )
626cdf0e10cSrcweir         {
627cdf0e10cSrcweir             if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
628cdf0e10cSrcweir                 pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
629cdf0e10cSrcweir                 pPor->IsHolePortion() ||
630cdf0e10cSrcweir                 ( pPor->IsMultiPortion() && ! ((SwMultiPortion*)pPor)->IsBidi() ) )
631cdf0e10cSrcweir                 break;
632cdf0e10cSrcweir 
633cdf0e10cSrcweir             aIter.Seek( nTmpIdx );
634cdf0e10cSrcweir 
635cdf0e10cSrcweir             if ( aIter.GetFnt()->GetEscapement() < 0 || pFnt->IsWordLineMode() ||
636cdf0e10cSrcweir                  SVX_CASEMAP_KAPITAELCHEN == pFnt->GetCaseMap() )
637cdf0e10cSrcweir                 break;
638cdf0e10cSrcweir 
639cdf0e10cSrcweir             if ( !aIter.GetFnt()->GetEscapement() )
640cdf0e10cSrcweir             {
641cdf0e10cSrcweir                 nSumWidth += pPor->Width();
642cdf0e10cSrcweir                 const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
643cdf0e10cSrcweir 
644cdf0e10cSrcweir                 // If we do not have a common baseline we take the baseline
645cdf0e10cSrcweir                 // and the font of the lowest portion.
646cdf0e10cSrcweir                 if ( nAdjustBaseLine )
647cdf0e10cSrcweir                 {
648cdf0e10cSrcweir                     sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *pCurr, pPor );
649cdf0e10cSrcweir                     if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
650cdf0e10cSrcweir                     {
651cdf0e10cSrcweir                         nMaxBaseLineOfst = nTmpBaseLineOfst;
652cdf0e10cSrcweir                         nSumHeight = nFontHeight;
653cdf0e10cSrcweir                     }
654cdf0e10cSrcweir                 }
655cdf0e10cSrcweir                 // in horizontal layout we build a weighted sum of the heights
656cdf0e10cSrcweir                 else
657cdf0e10cSrcweir                     nSumHeight += pPor->Width() * nFontHeight;
658cdf0e10cSrcweir 
659cdf0e10cSrcweir                 if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
660cdf0e10cSrcweir                     nBold += pPor->Width();
661cdf0e10cSrcweir             }
662cdf0e10cSrcweir 
663cdf0e10cSrcweir             ++nNumberOfPortions;
664cdf0e10cSrcweir 
665cdf0e10cSrcweir             nTmpIdx = nTmpIdx + pPor->GetLen();
666cdf0e10cSrcweir             pPor = pPor->GetPortion();
667cdf0e10cSrcweir         }
668cdf0e10cSrcweir 
669cdf0e10cSrcweir         // resulting height
670cdf0e10cSrcweir         if ( nNumberOfPortions > 1 && nSumWidth )
671cdf0e10cSrcweir         {
672cdf0e10cSrcweir             const sal_uLong nNewFontHeight = nAdjustBaseLine ?
673cdf0e10cSrcweir                                          nSumHeight :
674cdf0e10cSrcweir                                          nSumHeight / nSumWidth;
675cdf0e10cSrcweir 
676cdf0e10cSrcweir             pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
677cdf0e10cSrcweir 
678cdf0e10cSrcweir             // font height
679cdf0e10cSrcweir             const sal_uInt8 nActual = pUnderlineFnt->GetActual();
680cdf0e10cSrcweir             pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
681cdf0e10cSrcweir                                           nNewFontHeight ), nActual );
682cdf0e10cSrcweir 
683cdf0e10cSrcweir             // font weight
684cdf0e10cSrcweir             if ( 2 * nBold > nSumWidth )
685cdf0e10cSrcweir                 pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
686cdf0e10cSrcweir             else
687cdf0e10cSrcweir                 pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
688cdf0e10cSrcweir 
689cdf0e10cSrcweir             // common base line
690cdf0e10cSrcweir             aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
691cdf0e10cSrcweir         }
692cdf0e10cSrcweir     }
693cdf0e10cSrcweir 
694cdf0e10cSrcweir     // an escaped redlined portion should also have a special underlining
695cdf0e10cSrcweir     if( ! pUnderlineFnt && pFnt->GetEscapement() > 0 && GetRedln() &&
696cdf0e10cSrcweir         GetRedln()->ChkSpecialUnderline() )
697cdf0e10cSrcweir         pUnderlineFnt = new SwFont( *pFnt );
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     delete GetInfo().GetUnderFnt();
700cdf0e10cSrcweir 
701cdf0e10cSrcweir     if ( pUnderlineFnt )
702cdf0e10cSrcweir     {
703cdf0e10cSrcweir         pUnderlineFnt->SetProportion( 100 );
704cdf0e10cSrcweir         pUnderlineFnt->SetEscapement( 0 );
705cdf0e10cSrcweir         pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
706cdf0e10cSrcweir         pUnderlineFnt->SetOverline( UNDERLINE_NONE );
707cdf0e10cSrcweir         const Color aFillColor( COL_TRANSPARENT );
708cdf0e10cSrcweir         pUnderlineFnt->SetFillColor( aFillColor );
709cdf0e10cSrcweir 
710cdf0e10cSrcweir         GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt,
711cdf0e10cSrcweir                                                      aCommonBaseLine ) );
712cdf0e10cSrcweir     }
713cdf0e10cSrcweir     else
714cdf0e10cSrcweir         // I'm sorry, we do not have a special underlining font for you.
715cdf0e10cSrcweir         GetInfo().SetUnderFnt( 0 );
716cdf0e10cSrcweir }
717