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