xref: /trunk/main/sw/source/core/layout/paintfrm.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <com/sun/star/text/HoriOrientation.hpp>
32 #include <hintids.hxx>
33 #include <vcl/sound.hxx>
34 #include <tools/poly.hxx>
35 #define _SVSTDARR_LONGS
36 #include <svl/svstdarr.hxx>
37 #include <svx/xoutbmp.hxx>
38 #include <sfx2/progress.hxx>
39 #include <editeng/brshitem.hxx>
40 #include <editeng/opaqitem.hxx>
41 #include <editeng/prntitem.hxx>
42 #include <editeng/boxitem.hxx>
43 #include <editeng/shaditem.hxx>
44 #include <svx/framelink.hxx>
45 #include <vcl/graph.hxx>
46 #include <svx/svdpagv.hxx>
47 #include <hintids.hxx>
48 #include <tgrditem.hxx>
49 #include <switerator.hxx>
50 #include <fmtsrnd.hxx>
51 #include <fmtclds.hxx>
52 #include <tools/shl.hxx>
53 #include <comcore.hrc>
54 #include <swmodule.hxx>
55 #include <rootfrm.hxx>
56 #include <pagefrm.hxx>
57 #include <cntfrm.hxx>
58 #include <viewsh.hxx>
59 #include <section.hxx>
60 #include <sectfrm.hxx>
61 #include <doc.hxx>
62 #include <viewimp.hxx>
63 #include <dflyobj.hxx>
64 #include <flyfrm.hxx>
65 #include <frmtool.hxx>
66 #include <viewopt.hxx>
67 #include <dview.hxx>
68 #include <dcontact.hxx>
69 #include <txtfrm.hxx>
70 #include <ftnfrm.hxx>
71 #include <tabfrm.hxx>
72 #include <rowfrm.hxx>
73 #include <cellfrm.hxx>
74 #include <notxtfrm.hxx>
75 #include <swregion.hxx>
76 #include <layact.hxx>
77 #include <pagedesc.hxx>
78 #include <ptqueue.hxx>
79 #include <noteurl.hxx>
80 #include <virtoutp.hxx>
81 #include <lineinfo.hxx>
82 #include <dbg_lay.hxx>
83 #include <accessibilityoptions.hxx>
84 #include <docsh.hxx>
85 #include <swtable.hxx>
86 #include <svx/svdogrp.hxx>
87 #include <sortedobjs.hxx>
88 #include <EnhancedPDFExportHelper.hxx>
89 // <--
90 // --> OD #i76669#
91 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
92 #include <svx/sdr/contact/viewobjectcontact.hxx>
93 #include <svx/sdr/contact/viewcontact.hxx>
94 // <--
95 
96 #include <ndole.hxx>
97 #include <svtools/chartprettypainter.hxx>
98 #include <PostItMgr.hxx>
99 #include <tools/color.hxx>
100 #include <vcl/svapp.hxx>
101 
102 #define COL_NOTES_SIDEPANE					RGB_COLORDATA(230,230,230)
103 #define COL_NOTES_SIDEPANE_BORDER			RGB_COLORDATA(200,200,200)
104 #define COL_NOTES_SIDEPANE_SCROLLAREA		RGB_COLORDATA(230,230,220)
105 
106 using namespace ::com::sun::star;
107 
108 #define GETOBJSHELL()		((SfxObjectShell*)rSh.GetDoc()->GetDocShell())
109 
110 //Tabellenhilfslinien an?
111 #define IS_SUBS_TABLE \
112     (pGlobalShell->GetViewOptions()->IsTable() && \
113     !pGlobalShell->GetViewOptions()->IsPagePreview()&&\
114     !pGlobalShell->GetViewOptions()->IsReadonly()&&\
115     !pGlobalShell->GetViewOptions()->IsFormView() &&\
116      SwViewOption::IsTableBoundaries())
117 //sonstige Hilfslinien an?
118 #define IS_SUBS (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
119         !pGlobalShell->GetViewOptions()->IsReadonly() && \
120         !pGlobalShell->GetViewOptions()->IsFormView() &&\
121          SwViewOption::IsDocBoundaries())
122 //Hilfslinien fuer Bereiche
123 #define IS_SUBS_SECTION (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
124                          !pGlobalShell->GetViewOptions()->IsReadonly()&&\
125                          !pGlobalShell->GetViewOptions()->IsFormView() &&\
126                           SwViewOption::IsSectionBoundaries())
127 #define IS_SUBS_FLYS (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
128                       !pGlobalShell->GetViewOptions()->IsReadonly()&&\
129                       !pGlobalShell->GetViewOptions()->IsFormView() &&\
130                        SwViewOption::IsObjectBoundaries())
131 
132 #define SW_MAXBORDERCACHE 20
133 
134 //Klassendeklarationen. Hier weil sie eben nur in diesem File benoetigt
135 //werden.
136 
137 #define SUBCOL_PAGE     0x01    //Helplines of the page
138 #define SUBCOL_BREAK    0x02    //Helpline for a page or column break
139 #define SUBCOL_TAB      0x08    //Helplines inside tables
140 #define SUBCOL_FLY      0x10    //Helplines inside fly frames
141 #define SUBCOL_SECT     0x20    //Helplines inside sections
142 
143 //----- Klassen zum Sammeln von Umrandungen und Hilfslinien ---
144 class SwLineRect : public SwRect
145 {
146 	const Color	   *pColor;
147 	const SwTabFrm *pTab;
148 		  sal_uInt8		nSubColor;  //Hilfslinien einfaerben
149 		  sal_Bool		bPainted;	//schon gepaintet?
150 		  sal_uInt8		nLock;		//Um die Linien zum Hell-Layer abzugrenzen.
151 public:
152 	SwLineRect( const SwRect &rRect, const Color *pCol,
153                 const SwTabFrm *pT , const sal_uInt8 nSCol );
154 
155 	const Color			*GetColor() const { return pColor;}
156 	const SwTabFrm		*GetTab()	const { return pTab;  }
157 	void  SetPainted()					  { bPainted = sal_True; }
158 	void  Lock( sal_Bool bLock )			  { if ( bLock )
159 												++nLock;
160 											else if ( nLock )
161 												--nLock;
162 										  }
163 	sal_Bool  IsPainted()				const { return bPainted; }
164 	sal_Bool  IsLocked()				const { return nLock != 0;  }
165 	sal_uInt8  GetSubColor()				const { return nSubColor;}
166 
167 	sal_Bool MakeUnion( const SwRect &rRect );
168 };
169 
170 SV_DECL_VARARR( SwLRects, SwLineRect, 100, 100 )
171 
172 class SwLineRects : public SwLRects
173 {
174 	sal_uInt16 nLastCount;	//unuetze Durchlaeufe im PaintLines verhindern.
175 public:
176 	SwLineRects() : nLastCount( 0 ) {}
177 	void AddLineRect( const SwRect& rRect,	const Color *pColor,
178                       const SwTabFrm *pTab, const sal_uInt8 nSCol );
179 	void ConnectEdges( OutputDevice *pOut );
180 	void PaintLines  ( OutputDevice *pOut );
181 	void LockLines( sal_Bool bLock );
182 
183     /// OD 13.08.2002 - correct type of function
184     sal_uInt16 Free() const { return nFree; }
185 };
186 
187 class SwSubsRects : public SwLineRects
188 {
189 	void RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects ); //;-)
190 public:
191 	void PaintSubsidiary( OutputDevice *pOut, const SwLineRects *pRects );
192 
193 	inline void Ins( const SwRect &rRect, const sal_uInt8 nSCol );
194 };
195 
196 //----------------- End Klassen Umrandungen ----------------------
197 
198 static ViewShell *pGlobalShell = 0;
199 
200 //Wenn durchsichtige FlyInCnts im PaintBackground gepainted werden so soll der
201 //Hintergrund nicht mehr retouchiert werden.
202 //static sal_Bool bLockFlyBackground = sal_False;
203 
204 //Wenn vom Fly ein Metafile abgezogen wird, so soll nur der FlyInhalt und vor
205 //nur hintergrund vom FlyInhalt gepaintet werden.
206 static sal_Bool bFlyMetafile = sal_False;
207 static OutputDevice *pFlyMetafileOut = 0;
208 
209 //Die Retouche fuer Durchsichtige Flys wird vom Hintergrund der Flys
210 //erledigt. Dabei darf der Fly selbst natuerlich nicht ausgespart werden.
211 //siehe PaintBackground und lcl_SubtractFlys()
212 static SwFlyFrm *pRetoucheFly  = 0;
213 static SwFlyFrm *pRetoucheFly2 = 0;
214 
215 //Groesse eines Pixel und die Haelfte davon. Wird jeweils bei Eintritt in
216 //SwRootFrm::Paint neu gesetzt.
217 static long nPixelSzW = 0, nPixelSzH = 0;
218 static long nHalfPixelSzW = 0, nHalfPixelSzH = 0;
219 static long nMinDistPixelW = 0, nMinDistPixelH = 0;
220 
221 //Aktueller Zoomfaktor
222 static double aScaleX = 1.0;
223 static double aScaleY = 1.0;
224 static double aMinDistScale = 0.73;
225 static double aEdgeScale = 0.5;
226 
227 
228 //In pLines werden Umrandungen waehrend des Paint gesammelt und soweit
229 //moeglich zusammengefasst.
230 //In pSubsLines werden Hilfslinien gesammelt und zusammengefasst. Diese
231 //werden vor der Ausgabe mit pLines abgeglichen, so dass moeglichst keine
232 //Umrandungen von den Hilfslinen verdeckt werden.
233 //bTablines ist waerend des Paints einer Tabelle sal_True.
234 static SwLineRects *pLines = 0;
235 static SwSubsRects *pSubsLines = 0;
236 // OD 18.11.2002 #99672# - global variable for sub-lines of body, header, footer,
237 // section and footnote frames.
238 static SwSubsRects *pSpecSubsLines = 0;
239 
240 static SfxProgress *pProgress = 0;
241 
242 static SwFlyFrm *pFlyOnlyDraw = 0;
243 
244 //Damit die Flys auch fuer den Hack richtig gepaintet werden koennen.
245 static sal_Bool bTableHack = sal_False;
246 
247 //Um das teure Ermitteln der RetoucheColor zu optimieren
248 Color aGlobalRetoucheColor;
249 
250 //Statics fuer Umrandungsalignment setzen.
251 // OD 05.05.2003 #107169# - adjustment for 'small' twip-to-pixel relations:
252 // For 'small' twip-to-pixel relations (less then 2:1)
253 // values of <nHalfPixelSzW> and <nHalfPixelSzH> are set to ZERO.
254 void SwCalcPixStatics( OutputDevice *pOut )
255 {
256     // OD 30.04.2003 #107169# - determine 'small' twip-to-pixel relation
257     sal_Bool bSmallTwipToPxRelW = sal_False;
258     sal_Bool bSmallTwipToPxRelH = sal_False;
259     {
260         Size aCheckTwipToPxRelSz( pOut->PixelToLogic( Size( 100, 100 )) );
261         if ( (aCheckTwipToPxRelSz.Width()/100.0) < 2.0 )
262         {
263             bSmallTwipToPxRelW = sal_True;
264         }
265         if ( (aCheckTwipToPxRelSz.Height()/100.0) < 2.0 )
266         {
267             bSmallTwipToPxRelH = sal_True;
268         }
269     }
270 
271     Size aSz( pOut->PixelToLogic( Size( 1,1 )) );
272 
273     nPixelSzW = aSz.Width();
274     if( !nPixelSzW )
275         nPixelSzW = 1;
276     nPixelSzH = aSz.Height();
277     if( !nPixelSzH )
278         nPixelSzH = 1;
279 
280     // OD 06.05.2003 #107169# - consider 'small' twip-to-pixel relations
281     if ( !bSmallTwipToPxRelW )
282     {
283         nHalfPixelSzW = nPixelSzW / 2 + 1;
284     }
285     else
286     {
287         nHalfPixelSzW = 0;
288     }
289     // OD 06.05.2003 #107169# - consider 'small' twip-to-pixel relations
290     if ( !bSmallTwipToPxRelH )
291     {
292         nHalfPixelSzH = nPixelSzH / 2 + 1;
293     }
294     else
295     {
296         nHalfPixelSzH = 0;
297     }
298 
299     nMinDistPixelW = nPixelSzW * 2 + 1;
300 	nMinDistPixelH = nPixelSzH * 2 + 1;
301 
302 	const MapMode &rMap = pOut->GetMapMode();
303 	aScaleX = rMap.GetScaleX();
304 	aScaleY = rMap.GetScaleY();
305 }
306 
307 //Zum Sichern der statics, damit das Paint (quasi) reentrant wird.
308 class SwSavePaintStatics
309 {
310 	sal_Bool			bSFlyMetafile,
311                         bSPageOnly;
312 	ViewShell		   *pSGlobalShell;
313 	OutputDevice	   *pSFlyMetafileOut;
314 	SwFlyFrm		   *pSRetoucheFly,
315 					   *pSRetoucheFly2,
316 					   *pSFlyOnlyDraw;
317 	SwLineRects		   *pSLines;
318 	SwSubsRects		   *pSSubsLines;
319     // --> OD 2005-07-04 #123196#
320     SwSubsRects*        pSSpecSubsLines;
321     // <--
322 	SfxProgress		   *pSProgress;
323 	long				nSPixelSzW,
324 						nSPixelSzH,
325 						nSHalfPixelSzW,
326 						nSHalfPixelSzH,
327 						nSMinDistPixelW,
328 						nSMinDistPixelH;
329 	Color				aSGlobalRetoucheColor;
330 	double				aSScaleX,
331 						aSScaleY;
332 public:
333 	SwSavePaintStatics();
334 	~SwSavePaintStatics();
335 };
336 
337 SwSavePaintStatics::SwSavePaintStatics() :
338 	bSFlyMetafile       ( bFlyMetafile      ),
339     pSGlobalShell       ( pGlobalShell      ),
340 	pSFlyMetafileOut    ( pFlyMetafileOut   ),
341 	pSRetoucheFly       ( pRetoucheFly      ),
342 	pSRetoucheFly2      ( pRetoucheFly2     ),
343 	pSFlyOnlyDraw       ( pFlyOnlyDraw      ),
344 	pSLines             ( pLines            ),
345 	pSSubsLines         ( pSubsLines        ),
346     // --> OD 2005-07-04 #123196#
347     pSSpecSubsLines     ( pSpecSubsLines    ),
348     // <--
349 	pSProgress          ( pProgress         ),
350 	nSPixelSzW          ( nPixelSzW         ),
351 	nSPixelSzH          ( nPixelSzH         ),
352 	nSHalfPixelSzW      ( nHalfPixelSzW     ),
353 	nSHalfPixelSzH      ( nHalfPixelSzH     ),
354 	nSMinDistPixelW     ( nMinDistPixelW    ),
355 	nSMinDistPixelH     ( nMinDistPixelH    ),
356 	aSGlobalRetoucheColor( aGlobalRetoucheColor ),
357 	aSScaleX            ( aScaleX           ),
358     aSScaleY            ( aScaleY           )
359 {
360     bFlyMetafile = sal_False;
361 	pFlyMetafileOut = 0;
362 	pRetoucheFly  = 0;
363 	pRetoucheFly2 = 0;
364 	nPixelSzW = nPixelSzH =
365 	nHalfPixelSzW = nHalfPixelSzH =
366 	nMinDistPixelW = nMinDistPixelH = 0;
367 	aScaleX = aScaleY = 1.0;
368 	aMinDistScale = 0.73;
369 	aEdgeScale = 0.5;
370 	pLines = 0;
371 	pSubsLines = 0;
372     // --> OD 2005-07-04 #123196#
373     pSpecSubsLines = 0L;
374     // <--
375 	pProgress = 0;
376 }
377 
378 SwSavePaintStatics::~SwSavePaintStatics()
379 {
380 	pGlobalShell	   = pSGlobalShell;
381 	bFlyMetafile       = bSFlyMetafile;
382     pFlyMetafileOut    = pSFlyMetafileOut;
383 	pRetoucheFly       = pSRetoucheFly;
384 	pRetoucheFly2      = pSRetoucheFly2;
385 	pFlyOnlyDraw       = pSFlyOnlyDraw;
386 	pLines             = pSLines;
387 	pSubsLines         = pSSubsLines;
388     // --> OD 2005-07-04 #123196#
389     pSpecSubsLines     = pSSpecSubsLines;
390     // <--
391     pProgress          = pSProgress;
392 	nPixelSzW          = nSPixelSzW;
393 	nPixelSzH          = nSPixelSzH;
394 	nHalfPixelSzW      = nSHalfPixelSzW;
395 	nHalfPixelSzH      = nSHalfPixelSzH;
396 	nMinDistPixelW     = nSMinDistPixelW;
397 	nMinDistPixelH     = nSMinDistPixelH;
398 	aGlobalRetoucheColor = aSGlobalRetoucheColor;
399 	aScaleX            = aSScaleX;
400 	aScaleY            = aSScaleY;
401 }
402 
403 //----------------- Implementierungen fuer Tabellenumrandung --------------
404 
405 SV_IMPL_VARARR( SwLRects, SwLineRect );
406 
407 
408 SwLineRect::SwLineRect( const SwRect &rRect, const Color *pCol,
409 						const SwTabFrm *pT, const sal_uInt8 nSCol ) :
410 	SwRect( rRect ),
411 	pColor( pCol ),
412 	pTab( pT ),
413     nSubColor( nSCol ),
414     bPainted( sal_False ),
415     nLock( 0 )
416 {
417 }
418 
419 sal_Bool SwLineRect::MakeUnion( const SwRect &rRect )
420 {
421 	//Es wurde bereits ausserhalb geprueft, ob die Rechtecke die gleiche
422 	//Ausrichtung (horizontal bzw. vertikal), Farbe usw. besitzen.
423 	if ( Height() > Width() ) //Vertikale Linie
424 	{
425 		if ( Left()  == rRect.Left() && Width() == rRect.Width() )
426 		{
427 			//Zusammenfassen wenn kein Luecke zwischen den Linien ist.
428 			const long nAdd = nPixelSzW + nHalfPixelSzW;
429 			if ( Bottom() + nAdd >= rRect.Top() &&
430 				 Top()	  - nAdd <= rRect.Bottom()	)
431 			{
432 				Bottom( Max( Bottom(), rRect.Bottom() ) );
433 				Top   ( Min( Top(),	   rRect.Top()	  ) );
434 				return sal_True;
435 			}
436 		}
437 	}
438 	else
439 	{
440 		if ( Top()	== rRect.Top() && Height() == rRect.Height() )
441 		{
442 			//Zusammenfassen wenn kein Luecke zwischen den Linien ist.
443 			const long nAdd = nPixelSzW + nHalfPixelSzW;
444 			if ( Right() + nAdd >= rRect.Left() &&
445                  Left()  - nAdd <= rRect.Right() )
446 			{
447 				Right( Max( Right(), rRect.Right() ) );
448 				Left ( Min( Left(),  rRect.Left()  ) );
449 				return sal_True;
450 			}
451 		}
452 	}
453 	return sal_False;
454 }
455 
456 void SwLineRects::AddLineRect( const SwRect &rRect, const Color *pCol,
457 							   const SwTabFrm *pTab, const sal_uInt8 nSCol )
458 {
459 	//Rueckwaerts durch, weil Linien die zusammengefasst werden koennen i.d.R.
460 	//im gleichen Kontext gepaintet werden.
461 	for ( sal_uInt16 i = Count(); i ; )
462 	{
463 		SwLineRect &rLRect = operator[](--i);
464 		//Pruefen von Ausrichtung, Farbe, Tabelle.
465 		if ( rLRect.GetTab() == pTab &&
466 			 !rLRect.IsPainted() && rLRect.GetSubColor() == nSCol &&
467 			 (rLRect.Height() > rLRect.Width()) == (rRect.Height() > rRect.Width()) &&
468 			 ((!rLRect.GetColor() && !pCol) ||
469 			  (rLRect.GetColor() && pCol && *rLRect.GetColor() == *pCol)) )
470 		{
471 			if ( rLRect.MakeUnion( rRect ) )
472 				return;
473 		}
474 	}
475 	Insert( SwLineRect( rRect, pCol, pTab, nSCol ), Count() );
476 }
477 
478 void SwLineRects::ConnectEdges( OutputDevice *pOut )
479 {
480 	if ( pOut->GetOutDevType() != OUTDEV_PRINTER )
481 	{
482 		//Fuer einen zu kleinen Zoom arbeite ich nicht.
483 		if ( aScaleX < aEdgeScale || aScaleY < aEdgeScale )
484 			return;
485 	}
486 
487 	static const long nAdd = 20;
488 
489 	SvPtrarr   aCheck( 64, 64 );
490 
491 	for ( int i = 0; i < (int)Count(); ++i )
492 	{
493 		SwLineRect &rL1 = operator[](sal_uInt16(i));
494 		if ( !rL1.GetTab() || rL1.IsPainted() || rL1.IsLocked() )
495 			continue;
496 
497 		aCheck.Remove( 0, aCheck.Count() );
498 
499 		const sal_Bool bVert = rL1.Height() > rL1.Width();
500 		long nL1a, nL1b, nL1c, nL1d;
501 
502 		if ( bVert )
503         {
504             nL1a = rL1.Top();   nL1b = rL1.Left();
505 			nL1c = rL1.Right(); nL1d = rL1.Bottom();
506 		}
507 		else
508         {
509             nL1a = rL1.Left();   nL1b = rL1.Top();
510 			nL1c = rL1.Bottom(); nL1d = rL1.Right();
511 		}
512 
513 		//Alle moeglicherweise mit i1 zu verbindenden Linien einsammeln.
514 		for ( sal_uInt16 i2 = 0; i2 < Count(); ++i2 )
515 		{
516 			SwLineRect &rL2 = operator[](i2);
517 			if ( rL2.GetTab() != rL1.GetTab() ||
518 				 rL2.IsPainted() 			  ||
519 				 rL2.IsLocked()				  ||
520 				 (bVert == (rL2.Height() > rL2.Width())) )
521 				continue;
522 
523 			long nL2a, nL2b, nL2c, nL2d;
524 			if ( bVert )
525             {
526                 nL2a = rL2.Top();   nL2b = rL2.Left();
527 				nL2c = rL2.Right(); nL2d = rL2.Bottom();
528 			}
529 			else
530             {
531                 nL2a = rL2.Left();   nL2b = rL2.Top();
532 				nL2c = rL2.Bottom(); nL2d = rL2.Right();
533 			}
534 
535 			if ( (nL1a - nAdd < nL2d && nL1d + nAdd > nL2a) &&
536 				  ((nL1b >	nL2b && nL1c		< nL2c) ||
537 				   (nL1c >= nL2c && nL1b - nAdd < nL2c) ||
538 				   (nL1b <= nL2b && nL1c + nAdd > nL2b)) )
539 			{
540 				SwLineRect *pMSC = &rL2;
541 				aCheck.Insert( pMSC, aCheck.Count() );
542 			}
543 		}
544 		if ( aCheck.Count() < 2 )
545 			continue;
546 
547 		sal_Bool bRemove = sal_False;
548 
549 		//Fuer jede Linie jede alle folgenden checken.
550 		for ( sal_uInt16 k = 0; !bRemove && k < aCheck.Count(); ++k )
551 		{
552 			SwLineRect &rR1 = (SwLineRect&)*(SwLineRect*)aCheck[k];
553 
554 			for ( sal_uInt16 k2 = k+1; !bRemove && k2 < aCheck.Count(); ++k2 )
555 			{
556 				SwLineRect &rR2 = (SwLineRect&)*(SwLineRect*)aCheck[k2];
557 				if ( bVert )
558 				{
559 					SwLineRect *pLA = 0;
560                     SwLineRect *pLB = 0;
561 					if ( rR1.Top() < rR2.Top() )
562 					{
563 						pLA = &rR1; pLB = &rR2;
564 					}
565 					else if ( rR1.Top() > rR2.Top() )
566 					{
567 						pLA = &rR2; pLB = &rR1;
568 					}
569 					//beschreiben k1 und k2 eine Doppellinie?
570 					if ( pLA && pLA->Bottom() + 60 > pLB->Top() )
571 					{
572 						if ( rL1.Top() < pLA->Top() )
573 						{
574 							if ( rL1.Bottom() == pLA->Bottom() )
575 								continue;	//kleiner Irrtum (woher?)
576 
577 							SwRect aIns( rL1 );
578 							aIns.Bottom( pLA->Bottom() );
579 							if ( !rL1.IsInside( aIns ) )
580 								continue;
581                             const sal_uInt16 nTmpFree = Free();
582 							Insert( SwLineRect( aIns, rL1.GetColor(),
583                                         rL1.GetTab(), SUBCOL_TAB ), Count() );
584                             if ( !nTmpFree )
585 							{
586 								--i;
587 								k = aCheck.Count();
588 								break;
589 							}
590 						}
591 
592 						if ( rL1.Bottom() > pLB->Bottom() )
593 							rL1.Top( pLB->Top() );	//i1 nach oben verlaengern
594 						else
595 							bRemove = sal_True;			//abbrechen, i1 entfernen
596 					}
597 				}
598 				else
599 				{
600 					SwLineRect *pLA = 0;
601                     SwLineRect *pLB = 0;
602 					if ( rR1.Left() < rR2.Left() )
603 					{
604 						pLA = &rR1; pLB = &rR2;
605 					}
606 					else if ( rR1.Left() > rR2.Left() )
607 					{
608 						pLA = &rR2; pLB = &rR1;
609 					}
610 					//Liegt eine 'doppellinie' vor?
611 					if ( pLA && pLA->Right() + 60 > pLB->Left() )
612 					{
613 						if ( rL1.Left() < pLA->Left() )
614 						{
615 							if ( rL1.Right() == pLA->Right() )
616 								continue;	//kleiner irrtum
617 
618 							SwRect aIns( rL1 );
619 							aIns.Right( pLA->Right() );
620 							if ( !rL1.IsInside( aIns ) )
621 								continue;
622                             const sal_uInt16 nTmpFree = Free();
623 							Insert( SwLineRect( aIns, rL1.GetColor(),
624                                         rL1.GetTab(), SUBCOL_TAB ), Count() );
625                             if ( !nTmpFree )
626 							{
627 								--i;
628 								k = aCheck.Count();
629 								break;
630 							}
631 						}
632 						if ( rL1.Right() > pLB->Right() )
633 							rL1.Left( pLB->Left() );
634 						else
635 							bRemove = sal_True;
636 					}
637 				}
638 			}
639 		}
640 		if ( bRemove )
641 		{
642 			Remove( static_cast<sal_uInt16>(i), 1 );
643 			--i;			//keinen auslassen!
644 		}
645 	}
646 }
647 
648 inline void SwSubsRects::Ins( const SwRect &rRect, const sal_uInt8 nSCol )
649 {
650 	//Linien die kuerzer als die breiteste Linienbreite sind werden
651 	//nicht aufgenommen.
652 	if ( rRect.Height() > DEF_LINE_WIDTH_4 || rRect.Width() > DEF_LINE_WIDTH_4 )
653 		Insert( SwLineRect( rRect, 0, 0, nSCol ), Count());
654 }
655 
656 void SwSubsRects::RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects )
657 {
658 	//Alle Hilfslinien, die sich mit irgendwelchen Umrandungen decken werden
659 	//entfernt bzw. zerstueckelt..
660 	for ( sal_uInt16 i = 0; i < Count(); ++i )
661 	{
662         // OD 18.11.2002 #99672# - get a copy instead of a reference, because
663         // an <insert> may destroy the object due to a necessary array resize.
664         const SwLineRect aSubsLineRect = SwLineRect( operator[](i) );
665 
666         // OD 19.12.2002 #106318# - add condition <aSubsLineRect.IsLocked()>
667         // in order to consider only border lines, which are *not* locked.
668         if ( aSubsLineRect.IsPainted() ||
669              aSubsLineRect.IsLocked() )
670 			continue;
671 
672         const bool bVerticalSubs = aSubsLineRect.Height() > aSubsLineRect.Width();
673         SwRect aSubsRect( aSubsLineRect );
674         if ( bVerticalSubs )
675 		{
676             aSubsRect.Left  ( aSubsRect.Left()  - (nPixelSzW+nHalfPixelSzW) );
677             aSubsRect.Right ( aSubsRect.Right() + (nPixelSzW+nHalfPixelSzW) );
678 		}
679 		else
680 		{
681             aSubsRect.Top   ( aSubsRect.Top()    - (nPixelSzH+nHalfPixelSzH) );
682             aSubsRect.Bottom( aSubsRect.Bottom() + (nPixelSzH+nHalfPixelSzH) );
683 		}
684 		for ( sal_uInt16 k = 0; k < rRects.Count(); ++k )
685 		{
686 			SwLineRect &rLine = rRects[k];
687 
688             // OD 20.12.2002 #106318# - do *not* consider painted or locked
689             // border lines.
690             // OD 20.01.2003 #i1837# - locked border lines have to be considered.
691             if ( rLine.IsLocked () )
692                 continue;
693 
694             if ( (!bVerticalSubs == (rLine.Height() > rLine.Width())) ) //gleiche Ausrichtung?
695 				continue;
696 
697             if ( aSubsRect.IsOver( rLine ) )
698 			{
699                 if ( bVerticalSubs ) //Vertikal?
700 				{
701                     if ( aSubsRect.Left()  <= rLine.Right() &&
702                          aSubsRect.Right() >= rLine.Left() )
703 					{
704 						long nTmp = rLine.Top()-(nPixelSzH+1);
705                         if ( aSubsLineRect.Top() < nTmp )
706 						{
707                             SwRect aNewSubsRect( aSubsLineRect );
708                             aNewSubsRect.Bottom( nTmp );
709                             Insert( SwLineRect( aNewSubsRect, 0, 0,
710                                                 aSubsLineRect.GetSubColor() ), Count());
711 						}
712 						nTmp = rLine.Bottom()+nPixelSzH+1;
713                         if ( aSubsLineRect.Bottom() > nTmp )
714 						{
715                             SwRect aNewSubsRect( aSubsLineRect );
716                             aNewSubsRect.Top( nTmp );
717                             Insert( SwLineRect( aNewSubsRect, 0, 0,
718                                                 aSubsLineRect.GetSubColor() ), Count());
719 						}
720 						Remove( i, 1 );
721 						--i;
722 						break;
723 					}
724 				}
725 				else									//Horizontal
726 				{
727                     if ( aSubsRect.Top() <= rLine.Bottom() &&
728                          aSubsRect.Bottom() >= rLine.Top() )
729 					{
730 						long nTmp = rLine.Left()-(nPixelSzW+1);
731                         if ( aSubsLineRect.Left() < nTmp )
732 						{
733                             SwRect aNewSubsRect( aSubsLineRect );
734                             aNewSubsRect.Right( nTmp );
735                             Insert( SwLineRect( aNewSubsRect, 0, 0,
736                                                 aSubsLineRect.GetSubColor() ), Count());
737 						}
738 						nTmp = rLine.Right()+nPixelSzW+1;
739                         if ( aSubsLineRect.Right() > nTmp )
740 						{
741                             SwRect aNewSubsRect( aSubsLineRect );
742                             aNewSubsRect.Left( nTmp );
743                             Insert( SwLineRect( aNewSubsRect, 0, 0,
744                                                 aSubsLineRect.GetSubColor() ), Count());
745 						}
746 						Remove( i, 1 );
747 						--i;
748 						break;
749 					}
750 				}
751 			}
752 		}
753 	}
754 }
755 
756 void SwLineRects::LockLines( sal_Bool bLock )
757 {
758 	for ( sal_uInt16 i = 0; i < Count(); ++i )
759 		operator[](i).Lock( bLock );
760 }
761 
762 void SwLineRects::PaintLines( OutputDevice *pOut )
763 {
764 	//Painten der Umrandungen. Leider muessen wir zweimal durch.
765 	//Einmal fuer die innenliegenden und einmal fuer die Aussenkanten
766 	//der Tabellen.
767 	if ( Count() != nLastCount )
768 	{
769         // --> FME 2004-06-24 #i16816# tagged pdf support
770         SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
771         // <--
772 
773         // OD 2004-04-23 #116347#
774         pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
775         pOut->SetLineColor();
776 		ConnectEdges( pOut );
777 		const Color *pLast = 0;
778 
779 		sal_Bool bPaint2nd = sal_False;
780 		sal_uInt16 nMinCount = Count();
781 		sal_uInt16 i;
782 
783 		for ( i = 0; i < Count(); ++i )
784 		{
785 			SwLineRect &rLRect = operator[](i);
786 
787 			if ( rLRect.IsPainted() )
788 				continue;
789 
790 			if ( rLRect.IsLocked() )
791 			{
792 				nMinCount = Min( nMinCount, i );
793 				continue;
794 			}
795 
796 			//Jetzt malen oder erst in der zweiten Runde?
797 			sal_Bool bPaint = sal_True;
798 			if ( rLRect.GetTab() )
799 			{
800 				if ( rLRect.Height() > rLRect.Width() )
801 				{
802 					//Senkrechte Kante, ueberlappt sie mit der TabellenKante?
803 					SwTwips nLLeft	= rLRect.Left()  - 30,
804 							nLRight = rLRect.Right() + 30,
805 							nTLeft	= rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Left(),
806 							nTRight = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Right();
807 					if ( (nTLeft >= nLLeft && nTLeft <= nLRight) ||
808 						 (nTRight>= nLLeft && nTRight<= nLRight) )
809 						bPaint = sal_False;
810 				}
811 				else
812 				{	//Waagerechte Kante, ueberlappt sie mit der Tabellenkante?
813 					SwTwips nLTop	 = rLRect.Top()    - 30,
814 							nLBottom = rLRect.Bottom() + 30,
815 							nTTop	 = rLRect.GetTab()->Frm().Top()  + rLRect.GetTab()->Prt().Top(),
816 							nTBottom = rLRect.GetTab()->Frm().Top()  + rLRect.GetTab()->Prt().Bottom();
817 					if ( (nTTop    >= nLTop && nTTop	  <= nLBottom) ||
818 						 (nTBottom >= nLTop && nTBottom <= nLBottom) )
819 						bPaint = sal_False;
820 				}
821 			}
822 			if ( bPaint )
823 			{
824                 if ( !pLast || *pLast != *rLRect.GetColor() )
825 				{
826 					pLast = rLRect.GetColor();
827 
828                     sal_uLong nOldDrawMode = pOut->GetDrawMode();
829                     if( pGlobalShell->GetWin() &&
830                         Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
831                         pOut->SetDrawMode( 0 );
832 
833 					pOut->SetFillColor( *pLast );
834                     pOut->SetDrawMode( nOldDrawMode );
835 				}
836                 if( !rLRect.IsEmpty() )
837                     pOut->DrawRect( rLRect.SVRect() );
838 				rLRect.SetPainted();
839 			}
840 			else
841 				bPaint2nd = sal_True;
842 		}
843 		if ( bPaint2nd )
844 			for ( i = 0; i < Count(); ++i )
845 			{
846 				SwLineRect &rLRect = operator[](i);
847 				if ( rLRect.IsPainted() )
848 					continue;
849 
850 				if ( rLRect.IsLocked() )
851 				{
852 					nMinCount = Min( nMinCount, i );
853 					continue;
854 				}
855 
856 				if ( !pLast || *pLast != *rLRect.GetColor() )
857 				{
858 					pLast = rLRect.GetColor();
859 
860                     sal_uLong nOldDrawMode = pOut->GetDrawMode();
861                     if( pGlobalShell->GetWin() &&
862                         Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
863                     {
864                         pOut->SetDrawMode( 0 );
865                     }
866 
867 					pOut->SetFillColor( *pLast );
868                     pOut->SetDrawMode( nOldDrawMode );
869 				}
870                 if( !rLRect.IsEmpty() )
871                     pOut->DrawRect( rLRect.SVRect() );
872 				rLRect.SetPainted();
873 			}
874 		nLastCount = nMinCount;
875 		pOut->Pop();
876 	}
877 }
878 
879 void SwSubsRects::PaintSubsidiary( OutputDevice *pOut,
880 								   const SwLineRects *pRects )
881 {
882 	if ( Count() )
883 	{
884         // --> FME 2004-06-24 #i16816# tagged pdf support
885         SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
886         // <--
887 
888 		//Alle Hilfslinien, die sich fast decken entfernen (Tabellen)
889 		for ( sal_uInt16 i = 0; i < Count(); ++i )
890 		{
891 			SwLineRect &rLi = operator[](i);
892             const bool bVerticalSubs = rLi.Height() > rLi.Width();
893 
894 			for ( sal_uInt16 k = i+1; k < Count(); ++k )
895 			{
896 				SwLineRect &rLk = operator[](k);
897 				if ( rLi.SSize() == rLk.SSize() )
898 				{
899                     if ( (bVerticalSubs == (rLk.Height() > rLk.Width())) )
900 					{
901                         if ( bVerticalSubs )
902 						{
903 							long nLi = rLi.Right();
904 							long nLk = rLk.Right();
905 							if ( rLi.Top() == rLk.Top() &&
906 								 ((nLi < rLk.Left() && nLi+21 > rLk.Left()) ||
907 								  (nLk < rLi.Left() && nLk+21 > rLi.Left())))
908 							{
909 								Remove( k, 1 );
910 								//Nicht mit der inneren Schleife weiter, weil
911 								//das Array schrumpfen koennte!
912 								--i; k = Count();
913 							}
914 						}
915 						else
916 						{
917 							long nLi = rLi.Bottom();
918 							long nLk = rLk.Bottom();
919 							if ( rLi.Left() == rLk.Left() &&
920 								 ((nLi < rLk.Top() && nLi+21 > rLk.Top()) ||
921 								  (nLk < rLi.Top() && nLk+21 > rLi.Top())))
922 							{
923 								Remove( k, 1 );
924 								--i; k = Count();
925 							}
926 						}
927 					}
928 				}
929 			}
930 		}
931 
932 
933 		if ( pRects && pRects->Count() )
934 			RemoveSuperfluousSubsidiaryLines( *pRects );
935 
936 		if ( Count() )
937 		{
938             // OD 2004-04-23 #116347#
939             pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
940             pOut->SetLineColor();
941 
942             // OD 14.01.2003 #106660# - reset draw mode in high contrast
943             // mode in order to get fill color set at output device.
944             // Recover draw mode after draw of lines.
945             // Necessary for the subsidiary lines painted by the fly frames.
946             sal_uLong nOldDrawMode = pOut->GetDrawMode();
947             if( pGlobalShell->GetWin() &&
948                 Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
949             {
950                 pOut->SetDrawMode( 0 );
951             }
952 
953             for ( sal_uInt16 i = 0; i < Count(); ++i )
954 			{
955 				SwLineRect &rLRect = operator[](i);
956                 // OD 19.12.2002 #106318# - add condition <!rLRect.IsLocked()>
957                 // to prevent paint of locked subsidiary lines.
958                 if ( !rLRect.IsPainted() &&
959                      !rLRect.IsLocked() )
960 				{
961                     const Color *pCol = 0;
962 					switch ( rLRect.GetSubColor() )
963 					{
964                         case SUBCOL_PAGE: pCol = &SwViewOption::GetDocBoundariesColor(); break;
965                         case SUBCOL_FLY: pCol = &SwViewOption::GetObjectBoundariesColor(); break;
966                         case SUBCOL_TAB: pCol = &SwViewOption::GetTableBoundariesColor(); break;
967                         case SUBCOL_SECT: pCol = &SwViewOption::GetSectionBoundColor(); break;
968                         case SUBCOL_BREAK:    pCol = &SwViewOption::GetPageBreakColor(); break;
969 					}
970 
971                     if ( pOut->GetFillColor() != *pCol )
972                         pOut->SetFillColor( *pCol );
973                     pOut->DrawRect( rLRect.SVRect() );
974 
975                     rLRect.SetPainted();
976 				}
977 			}
978 
979             // OD 14.01.2003 #106660# - recovering draw mode
980             pOut->SetDrawMode( nOldDrawMode );
981 
982             pOut->Pop();
983 		}
984 	}
985 }
986 
987 //-------------------------------------------------------------------------
988 //Diverse Functions die in diesem File so verwendet werden.
989 
990 // OD 20.02.2003 - Note: function <SwAlignRect(..)> also used outside this file.
991 // OD 29.04.2003 #107169# - correction: adjust rectangle on pixel level in order
992 //          to assure, that the border 'leaves its original pixel', if it has to.
993 //          No prior adjustments for odd relation between pixel and twip.
994 void MA_FASTCALL SwAlignRect( SwRect &rRect, ViewShell *pSh )
995 {
996     if( !rRect.HasArea() )
997         return;
998 
999     // OD 03.09.2002 #102450#
1000     // Assure that view shell (parameter <pSh>) exists, if the output device
1001     // is taken from this view shell --> no output device, no alignment.
1002     // Output device taken from view shell <pSh>, if <bFlyMetafile> not set.
1003     if ( !bFlyMetafile && !pSh )
1004     {
1005         return;
1006     }
1007 
1008     const OutputDevice *pOut = bFlyMetafile ?
1009 						pFlyMetafileOut : pSh->GetOut();
1010 
1011     // OD 28.04.2003 #107169# - hold original rectangle in pixel
1012     const Rectangle aOrgPxRect = pOut->LogicToPixel( rRect.SVRect() );
1013     // OD 29.04.2003 #107169# - determine pixel-center rectangle in twip
1014     const SwRect aPxCenterRect( pOut->PixelToLogic( aOrgPxRect ) );
1015 
1016     // OD 06.05.2003 #107169# - perform adjustments on pixel level.
1017     SwRect aAlignedPxRect( aOrgPxRect );
1018     if ( rRect.Top() > aPxCenterRect.Top() )
1019     {
1020         // 'leave pixel overlapping on top'
1021         aAlignedPxRect.Top( aAlignedPxRect.Top() + 1 );
1022     }
1023 
1024     if ( rRect.Bottom() < aPxCenterRect.Bottom() )
1025     {
1026         // 'leave pixel overlapping on bottom'
1027         aAlignedPxRect.Bottom( aAlignedPxRect.Bottom() - 1 );
1028     }
1029 
1030     if ( rRect.Left() > aPxCenterRect.Left() )
1031     {
1032         // 'leave pixel overlapping on left'
1033         aAlignedPxRect.Left( aAlignedPxRect.Left() + 1 );
1034     }
1035 
1036     if ( rRect.Right() < aPxCenterRect.Right() )
1037     {
1038         // 'leave pixel overlapping on right'
1039         aAlignedPxRect.Right( aAlignedPxRect.Right() - 1 );
1040     }
1041 
1042     // OD 11.10.2002 #103636# - consider negative width/height
1043     // check, if aligned SwRect has negative width/height.
1044     // If Yes, adjust it to width/height = 0 twip.
1045     // NOTE: A SwRect with negative width/height can occur, if the width/height
1046     //     of the given SwRect in twip was less than a pixel in twip and that
1047     //     the alignment calculates that the aligned SwRect should not contain
1048     //     the pixels the width/height is on.
1049     if ( aAlignedPxRect.Width() < 0 )
1050     {
1051         aAlignedPxRect.Width(0);
1052     }
1053     if ( aAlignedPxRect.Height() < 0 )
1054     {
1055         aAlignedPxRect.Height(0);
1056     }
1057     // OD 30.04.2003 #107169# - consider zero width/height
1058     // For converting a rectangle from pixel to logic it needs a width/height.
1059     // Thus, set width/height to one, if it's zero and correct this on the twip
1060     // level after the conversion.
1061     sal_Bool bZeroWidth = sal_False;
1062     if ( aAlignedPxRect.Width() == 0 )
1063     {
1064         aAlignedPxRect.Width(1);
1065         bZeroWidth = sal_True;
1066     }
1067     sal_Bool bZeroHeight = sal_False;
1068     if ( aAlignedPxRect.Height() == 0 )
1069     {
1070         aAlignedPxRect.Height(1);
1071         bZeroHeight = sal_True;
1072     }
1073 
1074     rRect = pOut->PixelToLogic( aAlignedPxRect.SVRect() );
1075 
1076     // OD 30.04.2003 #107169# - consider zero width/height and adjust calculated
1077     // aligned twip rectangle.
1078     // OD 19.05.2003 #109667# - reset width/height to zero; previous negative
1079     // width/height haven't to be considered.
1080     if ( bZeroWidth )
1081     {
1082         rRect.Width(0);
1083     }
1084     if ( bZeroHeight )
1085     {
1086         rRect.Height(0);
1087     }
1088 }
1089 
1090 /** OD 19.05.2003 #109667# - helper method for twip adjustments on pixel base
1091 
1092     method compares the x- or y-pixel position of two twip-point. If the x-/y-pixel
1093     positions are the same, the x-/y-pixel position of the second twip point is
1094     adjusted by a given amount of pixels.
1095 
1096     @author OD
1097 */
1098 void lcl_CompPxPosAndAdjustPos( const OutputDevice&  _rOut,
1099                                 const Point&         _rRefPt,
1100                                 Point&               _rCompPt,
1101                                 const sal_Bool       _bChkXPos,
1102                                 const sal_Int8       _nPxAdjustment )
1103 {
1104     const Point aRefPxPt = _rOut.LogicToPixel( _rRefPt );
1105     Point aCompPxPt = _rOut.LogicToPixel( _rCompPt );
1106 
1107     if ( _bChkXPos )
1108     {
1109         if ( aCompPxPt.X() == aRefPxPt.X() )
1110         {
1111             aCompPxPt.X() += _nPxAdjustment ;
1112             const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
1113             _rCompPt.X() = aAdjustedCompPt.X();
1114         }
1115     }
1116     else
1117     {
1118         if ( aCompPxPt.Y() == aRefPxPt.Y() )
1119         {
1120             aCompPxPt.Y() += _nPxAdjustment ;
1121             const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
1122             _rCompPt.Y() = aAdjustedCompPt.Y();
1123         }
1124     }
1125 }
1126 
1127 /** OD 25.09.2002 #99739# - method to pixel-align rectangle for drawing graphic object
1128 
1129     Because for drawing a graphic left-top-corner and size coordinations are
1130     used, these coordinations have to be determined on pixel level.
1131     Thus, convert rectangle to pixel and then convert left-top-corner and
1132     size of pixel rectangle back to logic.
1133     This calculation is necessary, because there exists a different between
1134     the convert from logic to pixel of a normal rectangle with its left-top-
1135     and right-bottom-corner and the same convert of the same rectangle
1136     with left-top-corner and size.
1137     Call this method before each <GraphicObject.Draw(...)>
1138 
1139     @author OD
1140 */
1141 void SwAlignGrfRect( SwRect *pGrfRect, const OutputDevice &rOut )
1142 {
1143     Rectangle aPxRect = rOut.LogicToPixel( pGrfRect->SVRect() );
1144     pGrfRect->Pos( rOut.PixelToLogic( aPxRect.TopLeft() ) );
1145     pGrfRect->SSize( rOut.PixelToLogic( aPxRect.GetSize() ) );
1146 }
1147 
1148 long MA_FASTCALL lcl_AlignWidth( const long nWidth )
1149 {
1150     if ( nWidth )
1151 	{
1152 		const long nW = nWidth % nPixelSzW;
1153 
1154 		if ( !nW || nW > nHalfPixelSzW )
1155 			return Max(1L, nWidth - nHalfPixelSzW);
1156 	}
1157 	return nWidth;
1158 }
1159 
1160 long MA_FASTCALL lcl_AlignHeight( const long nHeight )
1161 {
1162 	if ( nHeight )
1163 	{
1164 		const long nH = nHeight % nPixelSzH;
1165 
1166 		if ( !nH || nH > nHalfPixelSzH )
1167 			return Max(1L, nHeight - nHalfPixelSzH);
1168 	}
1169 	return nHeight;
1170 }
1171 
1172 long MA_FASTCALL lcl_MinHeightDist( const long nDist )
1173 {
1174 	if ( aScaleX < aMinDistScale || aScaleY < aMinDistScale )
1175 		return nDist;
1176 	return ::lcl_AlignHeight( Max( nDist, nMinDistPixelH ));
1177 }
1178 
1179 long MA_FASTCALL lcl_MinWidthDist( const long nDist )
1180 {
1181 	if ( aScaleX < aMinDistScale || aScaleY < aMinDistScale )
1182 		return nDist;
1183 	return ::lcl_AlignWidth( Max( nDist, nMinDistPixelW ));
1184 }
1185 
1186 
1187 //Ermittelt PrtArea plus Umrandung plus Schatten.
1188 void MA_FASTCALL lcl_CalcBorderRect( SwRect &rRect, const SwFrm *pFrm,
1189 										const SwBorderAttrs &rAttrs,
1190                                         const sal_Bool bShadow )
1191 {
1192     // OD 23.01.2003 #106386# - special handling for cell frames.
1193     // The printing area of a cell frame is completely enclosed in the frame area
1194     // and a cell frame has no shadow. Thus, for cell frames the calculated
1195     // area equals the frame area.
1196     // Notes: Borders of cell frames in R2L text direction will switch its side
1197     //        - left border is painted on the right; right border on the left.
1198     //        See <lcl_PaintLeftLine> and <lcl_PaintRightLine>.
1199     if( pFrm->IsSctFrm() )
1200     {
1201 		rRect = pFrm->Prt();
1202 		rRect.Pos() += pFrm->Frm().Pos();
1203     }
1204     else if ( pFrm->IsCellFrm() )
1205 		rRect = pFrm->Frm();
1206 	else
1207 	{
1208 		rRect = pFrm->Prt();
1209 		rRect.Pos() += pFrm->Frm().Pos();
1210 
1211 		if ( rAttrs.IsLine() || rAttrs.IsBorderDist() ||
1212 		 	(bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE) )
1213 		{
1214             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1215             SwRectFn fnRect = pFrm->IsVertical() ? ( pFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
1216 
1217 			const SvxBoxItem &rBox = rAttrs.GetBox();
1218             const sal_Bool bTop = 0 != (pFrm->*fnRect->fnGetTopMargin)();
1219 			if ( bTop )
1220 			{
1221                 SwTwips nDiff = rBox.GetTop() ?
1222                     rBox.CalcLineSpace( BOX_LINE_TOP ) :
1223                     ( rAttrs.IsBorderDist() ?
1224                       // OD 23.01.2003 #106386# - increase of distance by
1225                       // one twip is incorrect.
1226                       rBox.GetDistance( BOX_LINE_TOP ) : 0 );
1227                 if( nDiff )
1228                     (rRect.*fnRect->fnSubTop)( nDiff );
1229 			}
1230 
1231             const sal_Bool bBottom = 0 != (pFrm->*fnRect->fnGetBottomMargin)();
1232 			if ( bBottom )
1233 			{
1234                 SwTwips nDiff = 0;
1235                 // --> collapsing borders FME 2005-05-27 #i29550#
1236                 if ( pFrm->IsTabFrm() &&
1237                      ((SwTabFrm*)pFrm)->IsCollapsingBorders() )
1238                 {
1239                     // For collapsing borders, we have to add the height of
1240                     // the height of the last line
1241                     nDiff = ((SwTabFrm*)pFrm)->GetBottomLineSize();
1242                 }
1243                 // <-- collapsing
1244                 else
1245                 {
1246                     nDiff = rBox.GetBottom() ?
1247                     rBox.CalcLineSpace( BOX_LINE_BOTTOM ) :
1248                     ( rAttrs.IsBorderDist() ?
1249                       // OD 23.01.2003 #106386# - increase of distance by
1250                       // one twip is incorrect.
1251                       rBox.GetDistance( BOX_LINE_BOTTOM ) : 0 );
1252                 }
1253                 if( nDiff )
1254                     (rRect.*fnRect->fnAddBottom)( nDiff );
1255 			}
1256 
1257             if ( rBox.GetLeft() )
1258                 (rRect.*fnRect->fnSubLeft)( rBox.CalcLineSpace( BOX_LINE_LEFT ) );
1259 			else if ( rAttrs.IsBorderDist() )
1260                  // OD 23.01.2003 #106386# - increase of distance by one twip is incorrect.
1261                 (rRect.*fnRect->fnSubLeft)( rBox.GetDistance( BOX_LINE_LEFT ) );
1262 
1263 			if ( rBox.GetRight() )
1264                 (rRect.*fnRect->fnAddRight)( rBox.CalcLineSpace( BOX_LINE_RIGHT ) );
1265 			else if ( rAttrs.IsBorderDist() )
1266                  // OD 23.01.2003 #106386# - increase of distance by one twip is incorrect.
1267                 (rRect.*fnRect->fnAddRight)( rBox.GetDistance( BOX_LINE_RIGHT ) );
1268 
1269 			if ( bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
1270 			{
1271 				const SvxShadowItem &rShadow = rAttrs.GetShadow();
1272 				if ( bTop )
1273                     (rRect.*fnRect->fnSubTop)(rShadow.CalcShadowSpace(SHADOW_TOP));
1274                 (rRect.*fnRect->fnSubLeft)(rShadow.CalcShadowSpace(SHADOW_LEFT));
1275 				if ( bBottom )
1276                     (rRect.*fnRect->fnAddBottom)
1277                                     (rShadow.CalcShadowSpace( SHADOW_BOTTOM ));
1278                 (rRect.*fnRect->fnAddRight)(rShadow.CalcShadowSpace(SHADOW_RIGHT));
1279 			}
1280 		}
1281 	}
1282 
1283 	::SwAlignRect( rRect, pGlobalShell );
1284 }
1285 
1286 void MA_FASTCALL lcl_ExtendLeftAndRight( SwRect&                _rRect,
1287                                          const SwFrm&           _rFrm,
1288                                          const SwBorderAttrs&   _rAttrs,
1289                                          const SwRectFn&        _rRectFn )
1290 {
1291     // OD 21.05.2003 #108789# - extend left/right border/shadow rectangle to
1292     // bottom of previous frame/to top of next frame, if border/shadow is joined
1293     // with previous/next frame.
1294     if ( _rAttrs.JoinedWithPrev( _rFrm ) )
1295 	{
1296         const SwFrm* pPrevFrm = _rFrm.GetPrev();
1297         (_rRect.*_rRectFn->fnSetTop)( (pPrevFrm->*_rRectFn->fnGetPrtBottom)() );
1298 	}
1299     if ( _rAttrs.JoinedWithNext( _rFrm ) )
1300 	{
1301         const SwFrm* pNextFrm = _rFrm.GetNext();
1302         (_rRect.*_rRectFn->fnSetBottom)( (pNextFrm->*_rRectFn->fnGetPrtTop)() );
1303 	}
1304 }
1305 
1306 
1307 void MA_FASTCALL lcl_SubtractFlys( const SwFrm *pFrm, const SwPageFrm *pPage,
1308 						   const SwRect &rRect, SwRegionRects &rRegion )
1309 {
1310     const SwSortedObjs& rObjs = *pPage->GetSortedObjs();
1311     const SwFlyFrm* pSelfFly = pFrm->IsInFly() ? pFrm->FindFlyFrm() : pRetoucheFly2;
1312 	if ( !pRetoucheFly )
1313 		pRetoucheFly = pRetoucheFly2;
1314 
1315 	for ( sal_uInt16 j = 0; (j < rObjs.Count()) && rRegion.Count(); ++j )
1316 	{
1317         const SwAnchoredObject* pAnchoredObj = rObjs[j];
1318         const SdrObject* pSdrObj = pAnchoredObj->GetDrawObj();
1319 
1320         // OD 2004-01-15 #110582# - do not consider invisible objects
1321         if ( !pPage->GetFmt()->GetDoc()->IsVisibleLayerId( pSdrObj->GetLayer() ) )
1322             continue;
1323 
1324         if ( !pAnchoredObj->ISA(SwFlyFrm) )
1325             continue;
1326 
1327         const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
1328 
1329 		if ( pSelfFly == pFly || pRetoucheFly == pFly || !rRect.IsOver( pFly->Frm() ) )
1330 			continue;
1331 
1332 		if ( !pFly->GetFmt()->GetPrint().GetValue() &&
1333 				(OUTDEV_PRINTER == pGlobalShell->GetOut()->GetOutDevType() ||
1334 				pGlobalShell->IsPreView()))
1335 			continue;
1336 
1337         const sal_Bool bLowerOfSelf = pSelfFly && pFly->IsLowerOf( pSelfFly ) ?
1338 											sal_True : sal_False;
1339 
1340 		//Bei zeichengebundenem Fly nur diejenigen betrachten, in denen er
1341 		//nicht selbst verankert ist.
1342 		//#33429# Warum nur bei zeichengebundenen? Es macht doch nie Sinn
1343 		//Rahmen abzuziehen in denen er selbst verankert ist oder?
1344         if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
1345 			continue;
1346 
1347 		//#57194# Und warum gilt das nicht analog fuer den RetoucheFly?
1348         if ( pRetoucheFly && pRetoucheFly->IsLowerOf( pFly ) )
1349 			continue;
1350 
1351 
1352 #ifdef DBG_UTIL
1353 		//Flys, die innerhalb des eigenen verankert sind, muessen eine
1354 		//groessere OrdNum haben oder Zeichengebunden sein.
1355 		if ( pSelfFly && bLowerOfSelf )
1356 		{
1357 			ASSERT( pFly->IsFlyInCntFrm() ||
1358                     pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj()->GetOrdNumDirect(),
1359 					"Fly with wrong z-Order" );
1360 		}
1361 #endif
1362 
1363 		sal_Bool bStopOnHell = sal_True;
1364 		if ( pSelfFly )
1365 		{
1366 			const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
1367             if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
1368 			{
1369                 if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
1370 					//Im gleichen Layer werden nur obenliegende beachtet.
1371 					continue;
1372 			}
1373 			else
1374 			{
1375 				if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
1376 					//Aus anderem Layer interessieren uns nur nicht transparente
1377 					//oder innenliegende
1378 					continue;
1379 				bStopOnHell = sal_False;
1380 			}
1381 		}
1382 		if ( pRetoucheFly )
1383 		{
1384 			const SdrObject *pTmp = pRetoucheFly->GetVirtDrawObj();
1385             if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
1386 			{
1387                 if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
1388 					//Im gleichen Layer werden nur obenliegende beachtet.
1389 					continue;
1390 			}
1391 			else
1392 			{
1393                 if ( !pFly->IsLowerOf( pRetoucheFly ) && !pFly->GetFmt()->GetOpaque().GetValue() )
1394 					//Aus anderem Layer interessieren uns nur nicht transparente
1395 					//oder innenliegende
1396 					continue;
1397 				bStopOnHell = sal_False;
1398 			}
1399 		}
1400 
1401 		//Wenn der Inhalt des Fly Transparent ist, wird er nicht abgezogen, es sei denn
1402 		//er steht im Hell-Layer (#31941#)
1403         const IDocumentDrawModelAccess* pIDDMA = pFly->GetFmt()->getIDocumentDrawModelAccess();
1404         sal_Bool bHell = pSdrObj->GetLayer() == pIDDMA->GetHellId();
1405 		if ( (bStopOnHell && bHell) ||
1406              /// OD 05.08.2002 - change internal order of condition
1407              ///    first check "!bHell", then "..->Lower()" and "..->IsNoTxtFrm()"
1408              ///    have not to be performed, if frame is in "Hell"
1409              ( !bHell && pFly->Lower() && pFly->Lower()->IsNoTxtFrm() &&
1410                ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
1411                  ((SwNoTxtFrm*)pFly->Lower())->HasAnimation() ||
1412                  pFly->GetFmt()->GetSurround().IsContour()
1413                )
1414              )
1415            )
1416 			continue;
1417 
1418         // OD 08.10.2002 #103898#
1419         // Own if-statements for transparent background/shadow of fly frames
1420         // (#99657#) in order to handle special conditions.
1421         if ( pFly->IsBackgroundTransparent() )
1422         {
1423             // Background <pFly> is transparent drawn. Thus normally, its region
1424             // have not to be substracted from given region.
1425             // But, if method is called for a fly frame and
1426             // <pFly> is a direct lower of this fly frame and
1427             // <pFly> inherites its transparent background brush from its parent,
1428             // then <pFly> frame area have to be subtracted from given region.
1429             // NOTE: Because in Status Quo transparent backgrounds can only be
1430             //     assigned to fly frames, the handle of this special case
1431             //     avoids drawing of transparent areas more than once, if
1432             //     a fly frame inherites a transparent background from its
1433             //     parent fly frame.
1434             if ( pFrm->IsFlyFrm() &&
1435                  (pFly->GetAnchorFrm()->FindFlyFrm() == pFrm) &&
1436                  static_cast<const SwFlyFrmFmt*>(pFly->GetFmt())->IsBackgroundBrushInherited()
1437                )
1438             {
1439                 SwRect aRect;
1440                 SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFly );
1441                 const SwBorderAttrs &rAttrs = *aAccess.Get();
1442                 ::lcl_CalcBorderRect( aRect, pFly, rAttrs, sal_True );
1443                 rRegion -= aRect;
1444                 continue;
1445             }
1446             else
1447             {
1448                 continue;
1449             }
1450         }
1451         if ( pFly->IsShadowTransparent() )
1452         {
1453             continue;
1454         }
1455 
1456         if ( bHell && pFly->GetAnchorFrm()->IsInFly() )
1457 		{
1458 			//Damit die Umrandung nicht vom Hintergrund des anderen Flys
1459 			//zerlegt wird.
1460 			SwRect aRect;
1461 			SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFly );
1462 			const SwBorderAttrs &rAttrs = *aAccess.Get();
1463 			::lcl_CalcBorderRect( aRect, pFly, rAttrs, sal_True );
1464 			rRegion -= aRect;
1465 		}
1466 		else
1467 		{
1468 			SwRect aRect( pFly->Prt() );
1469 			aRect += pFly->Frm().Pos();
1470 			rRegion -= aRect;
1471 		}
1472 	}
1473 	if ( pRetoucheFly == pRetoucheFly2 )
1474 		pRetoucheFly = 0;
1475 }
1476 
1477 // --> OD 2008-05-16 #i84659# - no longer needed
1478 //inline sal_Bool IsShortCut( const SwRect &rRect, const SwRect &rFrmRect )
1479 //{
1480 //    //Wenn der Frm vollstaendig rechts neben bzw. unter dem
1481 //    //Rect sitzt ist's genug mit Painten.
1482 //        return rFrmRect.Top() > rRect.Bottom();
1483 //        // PAGES01 || (rFrmRect.Left() > rRect.Right()) );
1484 //}
1485 // <--
1486 
1487 //---------------- Ausgabe fuer das BrushItem ----------------
1488 
1489 /** lcl_DrawGraphicBackgrd - local help method to draw a background for a graphic
1490 
1491     OD 17.10.2002 #103876#
1492     Under certain circumstances we have to draw a background for a graphic.
1493     This method takes care of the conditions and draws the background with the
1494     corresponding color.
1495     Method introduced for bug fix #103876# in order to optimize drawing tiled
1496     background graphics. Previously, this code was integrated in method
1497     <lcl_DrawGraphic>.
1498     Method implemented as a inline, checking the conditions and calling method
1499     method <lcl_implDrawGraphicBackgrd(..)> for the intrinsic drawing.
1500 
1501     @author OD
1502 
1503     @param _rBackgrdBrush
1504     background brush contain the color the background has to be drawn.
1505 
1506     @param _pOut
1507     output device the background has to be drawn in.
1508 
1509     @param _rPaintRect
1510     paint retangle in the output device, which has to be drawn with the background.
1511     rectangle have to be aligned by method ::SwAlignRect
1512 
1513     @param _rGraphicObj
1514     graphic object, for which the background has to be drawn. Used for checking
1515     the transparency of its bitmap, its type and if the graphic is drawn transparent
1516 
1517     @param _bNumberingGraphic
1518     boolean indicating that graphic is used as a numbering.
1519 
1520     @param _bBackgrdAlreadyDrawn
1521     boolean (optional; default: false) indicating, if the background is already drawn.
1522 */
1523 void lcl_implDrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
1524                                  OutputDevice* _pOut,
1525                                  const SwRect& _rAlignedPaintRect,
1526                                  const GraphicObject& _rGraphicObj )
1527 {
1528     /// determine color of background
1529     ///     If color of background brush is not "no fill"/"auto fill" or
1530     ///     <bFlyMetafile> is set, use color of background brush, otherwise
1531     ///     use global retouche color.
1532     const Color aColor( ( (_rBackgrdBrush.GetColor() != COL_TRANSPARENT) || bFlyMetafile )
1533                         ? _rBackgrdBrush.GetColor()
1534                         : aGlobalRetoucheColor );
1535 
1536     /// determine, if background color have to be drawn transparent
1537     /// and calculate transparency percent value
1538     sal_Int8 nTransparencyPercent = 0;
1539     bool bDrawTransparent = false;
1540     if ( aColor.GetTransparency() != 0 )
1541     ///     background color is transparent --> draw transparent.
1542     {
1543         bDrawTransparent = true;
1544         nTransparencyPercent = (aColor.GetTransparency()*100 + 0x7F)/0xFF;
1545     }
1546     else if ( (_rGraphicObj.GetAttr().GetTransparency() != 0) &&
1547                 (_rBackgrdBrush.GetColor() == COL_TRANSPARENT) )
1548     ///     graphic is drawn transparent and background color is
1549     ///     "no fill"/"auto fill" --> draw transparent
1550     {
1551         bDrawTransparent = true;
1552         nTransparencyPercent = (_rGraphicObj.GetAttr().GetTransparency()*100 + 0x7F)/0xFF;
1553     }
1554 
1555     if ( bDrawTransparent )
1556     {
1557         /// draw background transparent
1558         if( _pOut->GetFillColor() != aColor.GetRGBColor() )
1559             _pOut->SetFillColor( aColor.GetRGBColor() );
1560         PolyPolygon aPoly( _rAlignedPaintRect.SVRect() );
1561         _pOut->DrawTransparent( aPoly, nTransparencyPercent );
1562     }
1563     else
1564     {
1565         /// draw background opaque
1566         if ( _pOut->GetFillColor() != aColor )
1567             _pOut->SetFillColor( aColor );
1568         _pOut->DrawRect( _rAlignedPaintRect.SVRect() );
1569     }
1570 }
1571 
1572 inline void lcl_DrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
1573                                     OutputDevice* _pOut,
1574                                     const SwRect& _rAlignedPaintRect,
1575                                     const GraphicObject& _rGraphicObj,
1576                                     bool _bNumberingGraphic,
1577                                     bool _bBackgrdAlreadyDrawn = false )
1578 {
1579     /// draw background with background color, if
1580     ///     (1) graphic is not used as a numbering AND
1581     ///     (2) background is not already drawn AND
1582     ///     (3) intrinsic graphic is transparent OR intrinsic graphic doesn't exists
1583     if ( !_bNumberingGraphic &&
1584          !_bBackgrdAlreadyDrawn &&
1585          ( _rGraphicObj.IsTransparent() || _rGraphicObj.GetType() == GRAPHIC_NONE  )
1586        )
1587     {
1588         lcl_implDrawGraphicBackgrd( _rBackgrdBrush, _pOut, _rAlignedPaintRect, _rGraphicObj );
1589     }
1590 }
1591 
1592 /// OD 06.08.2002 #99657# - Note: the transparency of the background graphic
1593 ///     is saved in SvxBrushItem.GetGraphicObject(<shell>).GetAttr().Set/GetTransparency()
1594 ///     and is considered in the drawing of the graphic.
1595 ///     Thus, to provide transparent background graphic for text frames nothing
1596 ///     has to be coded.
1597 /// OD 25.09.2002 #99739# - use align rectangle for drawing graphic
1598 /// OD 25.09.2002 #99739# - pixel-align coordinations for drawing graphic.
1599 /// OD 17.10.2002 #103876# - outsource code for drawing background of the graphic
1600 ///     with a background color in method <lcl_DrawGraphicBackgrd>
1601 ///     Also, change type of <bGrfNum> and <bClip> from <sal_Bool> to <bool>.
1602 void lcl_DrawGraphic( const SvxBrushItem& rBrush, OutputDevice *pOut,
1603 					  ViewShell &rSh, const SwRect &rGrf, const SwRect &rOut,
1604                       bool bClip, bool bGrfNum,
1605                       bool bBackgrdAlreadyDrawn = false )
1606                       /// OD 02.09.2002 #99657#
1607                       /// add parameter <bBackgrdAlreadyDrawn> to indicate
1608                       /// that the background is already drawn.
1609 {
1610     /// OD 25.09.2002 #99739# - calculate align rectangle from parameter <rGrf>
1611     ///     and use aligned rectangle <aAlignedGrfRect> in the following code
1612     SwRect aAlignedGrfRect = rGrf;
1613     ::SwAlignRect( aAlignedGrfRect, &rSh );
1614 
1615     /// OD 17.10.2002 #103876# - change type from <sal_Bool> to <bool>.
1616     const bool bNotInside = bClip && !rOut.IsInside( aAlignedGrfRect );
1617 	if ( bNotInside )
1618 	{
1619 		pOut->Push( PUSH_CLIPREGION );
1620 		pOut->IntersectClipRegion( rOut.SVRect() );
1621 	}
1622 
1623 	//Hier kein Link, wir wollen die Grafik synchron laden!
1624     ((SvxBrushItem&)rBrush).SetDoneLink( Link() );
1625 	GraphicObject *pGrf = (GraphicObject*)rBrush.GetGraphicObject();
1626 
1627     /// OD 17.10.2002 #103876# - outsourcing drawing of background with a background color.
1628     ::lcl_DrawGraphicBackgrd( rBrush, pOut, aAlignedGrfRect, *pGrf, bGrfNum, bBackgrdAlreadyDrawn );
1629 
1630     /// OD 25.09.2002 #99739# -
1631     /// Because for drawing a graphic left-top-corner and size coordinations are
1632     /// used, these coordinations have to be determined on pixel level.
1633     ::SwAlignGrfRect( &aAlignedGrfRect, *pOut );
1634     pGrf->DrawWithPDFHandling( *pOut, aAlignedGrfRect.Pos(), aAlignedGrfRect.SSize() );
1635 
1636 	if ( bNotInside )
1637 		pOut->Pop();
1638 } // end of method <lcl_DrawGraphic>
1639 
1640 void MA_FASTCALL DrawGraphic( const SvxBrushItem *pBrush,
1641                               OutputDevice *pOutDev,
1642                               const SwRect &rOrg,
1643                               const SwRect &rOut,
1644                               const sal_uInt8 nGrfNum,
1645                               const sal_Bool bConsiderBackgroundTransparency )
1646     /// OD 05.08.2002 #99657# - add 6th parameter to indicate that method should
1647     ///   consider background transparency, saved in the color of the brush item
1648 {
1649     ViewShell &rSh = *pGlobalShell;
1650     /// OD 17.10.2002 #103876# - change type from <sal_Bool> to <bool>
1651     bool bReplaceGrfNum = GRFNUM_REPLACE == nGrfNum;
1652     bool bGrfNum = GRFNUM_NO != nGrfNum;
1653 	Size aGrfSize;
1654 	SvxGraphicPosition ePos = GPOS_NONE;
1655 	if( pBrush && !bReplaceGrfNum )
1656 	{
1657 		if( rSh.GetViewOptions()->IsGraphic() )
1658 		{
1659             //#125488#: load graphic directly in PDF import
1660             // --> OD 2006-08-25 #i68953# - also during print load graphic directly.
1661             if ( (rSh).GetViewOptions()->IsPDFExport() ||
1662                  rSh.GetOut()->GetOutDevType() == OUTDEV_PRINTER )
1663             // <--
1664             {
1665                 ((SvxBrushItem*)pBrush)->PurgeMedium();
1666                 ((SvxBrushItem*)pBrush)->SetDoneLink( Link() );
1667             }
1668             else
1669                 ((SvxBrushItem*)pBrush)->SetDoneLink( STATIC_LINK(
1670                                     rSh.GetDoc(), SwDoc, BackgroundDone ) );
1671             //SfxObjectShell &rObjSh = *GETOBJSHELL();
1672 			const Graphic* pGrf = pBrush->GetGraphic();
1673 			if( pGrf && GRAPHIC_NONE != pGrf->GetType() )
1674 			{
1675 				ePos = pBrush->GetGraphicPos();
1676 				if( pGrf->IsSupportedGraphic() )
1677 					// don't the use the specific output device! Bug 94802
1678                     aGrfSize = ::GetGraphicSizeTwip( *pGrf, 0 );
1679 			}
1680 		}
1681 		else
1682 			bReplaceGrfNum = bGrfNum;
1683 	}
1684 
1685 	SwRect aGrf;
1686 	aGrf.SSize( aGrfSize );
1687 	sal_Bool bDraw = sal_True;
1688 	sal_Bool bRetouche = sal_True;
1689 	switch ( ePos )
1690 	{
1691 	case GPOS_LT:
1692 		aGrf.Pos() = rOrg.Pos();
1693 		break;
1694 
1695 	case GPOS_MT:
1696 		aGrf.Pos().Y() = rOrg.Top();
1697 		aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
1698 		break;
1699 
1700 	case GPOS_RT:
1701 		aGrf.Pos().Y() = rOrg.Top();
1702 		aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
1703 		break;
1704 
1705 	case GPOS_LM:
1706 		aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
1707 		aGrf.Pos().X() = rOrg.Left();
1708 		break;
1709 
1710 	case GPOS_MM:
1711 		aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
1712 		aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
1713 		break;
1714 
1715 	case GPOS_RM:
1716 		aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
1717 		aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
1718 		break;
1719 
1720 	case GPOS_LB:
1721 		aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
1722 		aGrf.Pos().X() = rOrg.Left();
1723 		break;
1724 
1725 	case GPOS_MB:
1726 		aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
1727 		aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
1728 		break;
1729 
1730 	case GPOS_RB:
1731 		aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
1732 		aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
1733 		break;
1734 
1735 	case GPOS_AREA:
1736 		aGrf = rOrg;
1737         /// OD 05.09.2002 #102912#
1738         /// In spite the fact that the background graphic have to fill the complete
1739         /// area, it has been checked, if the graphic will completely fill out
1740         /// the region to be painted <rOut> and thus, nothing has to be retouched.
1741         /// For example, this is the case for a fly frame without a background
1742         /// brush positioned on the border of the page and inherited the
1743         /// background brush from the page.
1744         bRetouche = !rOut.IsInside( aGrf );
1745 		break;
1746 
1747 	case GPOS_TILED:
1748 		{
1749             // OD 17.10.2002 #103876# - draw background of tiled graphic
1750             // before drawing tiled graphic in loop
1751             // determine graphic object
1752             GraphicObject* pGraphicObj = const_cast< GraphicObject* >(pBrush->GetGraphicObject());
1753             // calculate aligned paint rectangle
1754             SwRect aAlignedPaintRect = rOut;
1755             ::SwAlignRect( aAlignedPaintRect, &rSh );
1756             // OD 25.10.2002 #103876# - draw background color for aligned paint rectangle
1757             lcl_DrawGraphicBackgrd( *pBrush, pOutDev, aAlignedPaintRect, *pGraphicObj, bGrfNum );
1758 
1759             // set left-top-corner of background graphic to left-top-corner of the
1760             // area, from which the background brush is determined.
1761             aGrf.Pos() = rOrg.Pos();
1762             // setup clipping at output device
1763             pOutDev->Push( PUSH_CLIPREGION );
1764             pOutDev->IntersectClipRegion( rOut.SVRect() );
1765             // OD 28.10.2002 #103876# - use new method <GraphicObject::DrawTiled(::)>
1766             {
1767                 // calculate paint offset
1768                 Point aPaintOffset( aAlignedPaintRect.Pos() - aGrf.Pos() );
1769                 // draw background graphic tiled for aligned paint rectangle
1770                 // --> OD 2005-02-15 #i42643# - apply fix #104004# for Calc
1771                 // also for Writer - see /sc/source/view/printfun.cxx
1772                 // For PDF export, every draw operation for bitmaps takes a
1773                 // noticeable amount of place (~50 characters). Thus, optimize
1774                 // between tile bitmap size and number of drawing operations here.
1775                 //
1776                 //                  A_out
1777                 // n_chars = k1 *  ---------- + k2 * A_bitmap
1778                 //                  A_bitmap
1779                 //
1780                 // minimum n_chars is obtained for (derive for  A_bitmap,
1781                 // set to 0, take positive solution):
1782                 //                   k1
1783                 // A_bitmap = Sqrt( ---- A_out )
1784                 //                   k2
1785                 //
1786                 // where k1 is the number of chars per draw operation, and
1787                 // k2 is the number of chars per bitmap pixel.
1788                 // This is approximately 50 and 7 for current PDF writer, respectively.
1789                 //
1790                 const double    k1( 50 );
1791                 const double    k2( 7 );
1792                 const Size      aSize( aAlignedPaintRect.SSize() );
1793                 const double    Abitmap( k1/k2 * static_cast<double>(aSize.Width())*aSize.Height() );
1794 
1795                 pGraphicObj->DrawTiled( pOutDev,
1796                                         aAlignedPaintRect.SVRect(),
1797                                         aGrf.SSize(),
1798                                         Size( aPaintOffset.X(), aPaintOffset.Y() ),
1799                                         NULL, GRFMGR_DRAW_STANDARD,
1800                                         ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
1801                 // <--
1802             }
1803             // reset clipping at output device
1804             pOutDev->Pop();
1805             // set <bDraw> and <bRetouche> to false, indicating that background
1806             // graphic and background are already drawn.
1807             bDraw = bRetouche = sal_False;
1808 		}
1809 		break;
1810 
1811 	case GPOS_NONE:
1812 		bDraw = sal_False;
1813 		break;
1814 
1815     default: ASSERT( !pOutDev, "new Graphic position?" );
1816 	}
1817 
1818     /// OD 02.09.2002 #99657#
1819     /// init variable <bGrfBackgrdAlreadDrawn> to indicate, if background of
1820     /// graphic is already drawn or not.
1821     bool bGrfBackgrdAlreadyDrawn = false;
1822 	if ( bRetouche )
1823 	{
1824         // OD 2004-04-23 #116347#
1825         pOutDev->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
1826         pOutDev->SetLineColor();
1827 
1828         // OD 07.08.2002 #99657# #GetTransChg#
1829         //     check, if a existing background graphic (not filling the complete
1830         //     background) is transparent drawn and the background color is
1831         //     "no fill" respectively "auto fill", if background transparency
1832         //     has to be considered.
1833         //     If YES, memorise transparency of background graphic.
1834         //     check also, if background graphic bitmap is transparent.
1835         bool bTransparentGrfWithNoFillBackgrd = false;
1836         sal_Int32 nGrfTransparency = 0;
1837         bool bGrfIsTransparent = false;
1838         if ( (ePos != GPOS_NONE) &&
1839              (ePos != GPOS_TILED) && (ePos != GPOS_AREA)
1840            )
1841         {
1842             GraphicObject *pGrf = (GraphicObject*)pBrush->GetGraphicObject();
1843             if ( bConsiderBackgroundTransparency )
1844             {
1845                 GraphicAttr pGrfAttr = pGrf->GetAttr();
1846                 if ( (pGrfAttr.GetTransparency() != 0) &&
1847                      ( pBrush && (pBrush->GetColor() == COL_TRANSPARENT) )
1848                    )
1849                 {
1850                     bTransparentGrfWithNoFillBackgrd = true;
1851                     nGrfTransparency = pGrfAttr.GetTransparency();
1852                 }
1853             }
1854             if ( pGrf->IsTransparent() )
1855             {
1856                 bGrfIsTransparent = true;
1857             }
1858         }
1859 
1860         /// OD 06.08.2002 #99657# #GetTransChg# - to get color of brush,
1861         ///     check background color against COL_TRANSPARENT ("no fill"/"auto fill")
1862         ///     instead of checking, if transparency is not set.
1863         const Color aColor( pBrush &&
1864                             ( !(pBrush->GetColor() == COL_TRANSPARENT) ||
1865                               bFlyMetafile )
1866                     ? pBrush->GetColor()
1867                     : aGlobalRetoucheColor );
1868 
1869         /// OD 08.08.2002 #99657# - determine, if background region have to be
1870         ///     drawn transparent.
1871         ///     background region has to be drawn transparent, if
1872         ///         background transparency have to be considered
1873         ///     AND
1874         ///       ( background color is transparent OR
1875         ///         background graphic is transparent and background color is "no fill"
1876         ///       )
1877         sal_Bool bDrawTransparent = bConsiderBackgroundTransparency &&
1878                                 ( ( aColor.GetTransparency() != 0) ||
1879                                     bTransparentGrfWithNoFillBackgrd );
1880 
1881         // --> OD 2008-06-02 #i75614#
1882         // reset draw mode in high contrast mode in order to get fill color set
1883         const sal_uLong nOldDrawMode = pOutDev->GetDrawMode();
1884         if ( pGlobalShell->GetWin() &&
1885              Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1886         {
1887             pOutDev->SetDrawMode( 0 );
1888         }
1889         // <--
1890 
1891         /// OD 06.08.2002 #99657# - if background region have to be drawn
1892         ///     transparent, set only the RGB values of the background color as
1893         ///     the fill color for the output device.
1894         if ( bDrawTransparent )
1895         {
1896             if( pOutDev->GetFillColor() != aColor.GetRGBColor() )
1897                 pOutDev->SetFillColor( aColor.GetRGBColor() );
1898         }
1899         else
1900         {
1901             if( pOutDev->GetFillColor() != aColor )
1902                 pOutDev->SetFillColor( aColor );
1903         }
1904 
1905         // --> OD 2008-06-02 #i75614#
1906         // restore draw mode
1907         pOutDev->SetDrawMode( nOldDrawMode );
1908         // <--
1909 
1910         /// OD 02.09.2002 #99657#
1911         if ( bDrawTransparent )
1912         {
1913             /// background region have to be drawn transparent.
1914             /// Thus, create a poly-polygon from the region and draw it with
1915             /// the corresponding transparency precent.
1916             PolyPolygon aDrawPoly( rOut.SVRect() );
1917             if ( aGrf.HasArea() )
1918             {
1919                 if ( !bGrfIsTransparent )
1920                 {
1921                     /// substract area of background graphic from draw area
1922                     /// OD 08.10.2002 #103898# - consider only that part of the
1923                     ///     graphic area that is overlapping with draw area.
1924                     SwRect aTmpGrf = aGrf;
1925                     aTmpGrf.Intersection( rOut );
1926                     if ( aTmpGrf.HasArea() )
1927                     {
1928                         Polygon aGrfPoly( aTmpGrf.SVRect() );
1929                         aDrawPoly.Insert( aGrfPoly );
1930                     }
1931                 }
1932                 else
1933                     bGrfBackgrdAlreadyDrawn = true;
1934             }
1935             /// calculate transparency percent:
1936             /// ( <transparency value[0x01..0xFF]>*100 + 0x7F ) / 0xFF
1937             /// If there is a background graphic with a background color "no fill"/"auto fill",
1938             /// the transparency value is taken from the background graphic,
1939             /// otherwise take the transparency value from the color.
1940             sal_Int8 nTransparencyPercent = static_cast<sal_Int8>(
1941               (( bTransparentGrfWithNoFillBackgrd ? nGrfTransparency : aColor.GetTransparency()
1942                )*100 + 0x7F)/0xFF);
1943             /// draw poly-polygon transparent
1944             pOutDev->DrawTransparent( aDrawPoly, nTransparencyPercent );
1945         }
1946         else
1947         {
1948             SwRegionRects aRegion( rOut, 4 );
1949             if ( !bGrfIsTransparent )
1950                 aRegion -= aGrf;
1951             else
1952                 bGrfBackgrdAlreadyDrawn = true;
1953             /// loop rectangles of background region, which has to be drawn
1954             for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
1955             {
1956                 pOutDev->DrawRect( aRegion[i].SVRect() );
1957             }
1958         }
1959        pOutDev ->Pop();
1960 	}
1961 
1962     if( bDraw && aGrf.IsOver( rOut ) )
1963         /// OD 02.09.2002 #99657#
1964         /// add parameter <bGrfBackgrdAlreadyDrawn>
1965         lcl_DrawGraphic( *pBrush, pOutDev, rSh, aGrf, rOut, true, bGrfNum,
1966                          bGrfBackgrdAlreadyDrawn );
1967 
1968 	if( bReplaceGrfNum )
1969 	{
1970         const BitmapEx& rBmp = ViewShell::GetReplacementBitmap( false );
1971         Font aTmp( pOutDev->GetFont() );
1972         Graphic::DrawEx( pOutDev, aEmptyStr, aTmp, rBmp, rOrg.Pos(), rOrg.SSize() );
1973 	}
1974 }
1975 
1976 //------------------------------------------------------------------------
1977 
1978 /** local help method for SwRootFrm::Paint(..) - Adjust given rectangle to pixel size
1979 
1980     By OD at 27.09.2002 for #103636#
1981     In order to avoid paint errors caused by multiple alignments - e.g. method
1982     ::SwAlignRect(..) - and other changes to the rectangle to be painted,
1983     this method is called for the rectangle to be painted in order to
1984     adjust it to the pixel it is overlapping.
1985 
1986     @author OD
1987 */
1988 void lcl_AdjustRectToPixelSize( SwRect& io_aSwRect, const OutputDevice &aOut )
1989 {
1990     /// local constant object of class <Size> to determine number of Twips
1991     /// representing a pixel.
1992     const Size aTwipToPxSize( aOut.PixelToLogic( Size( 1,1 )) );
1993 
1994     /// local object of class <Rectangle> in Twip coordinates
1995     /// calculated from given rectangle aligned to pixel centers.
1996     const Rectangle aPxCenterRect = aOut.PixelToLogic(
1997             aOut.LogicToPixel( io_aSwRect.SVRect() ) );
1998 
1999     /// local constant object of class <Rectangle> representing given rectangle
2000     /// in pixel.
2001     const Rectangle aOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
2002 
2003     /// calculate adjusted rectangle from pixel centered rectangle.
2004     /// Due to rounding differences <aPxCenterRect> doesn't exactly represents
2005     /// the Twip-centers. Thus, adjust borders by half of pixel width/height plus 1.
2006     /// Afterwards, adjust calculated Twip-positions of the all borders.
2007     Rectangle aSizedRect = aPxCenterRect;
2008     aSizedRect.Left() -= (aTwipToPxSize.Width()/2 + 1);
2009     aSizedRect.Right() += (aTwipToPxSize.Width()/2 + 1);
2010     aSizedRect.Top() -= (aTwipToPxSize.Height()/2 + 1);
2011     aSizedRect.Bottom() += (aTwipToPxSize.Height()/2 + 1);
2012 
2013     /// adjust left()
2014     while ( (aOut.LogicToPixel(aSizedRect)).Left() < aOrgPxRect.Left() )
2015     {
2016         ++aSizedRect.Left();
2017     }
2018     /// adjust right()
2019     while ( (aOut.LogicToPixel(aSizedRect)).Right() > aOrgPxRect.Right() )
2020     {
2021         --aSizedRect.Right();
2022     }
2023     /// adjust top()
2024     while ( (aOut.LogicToPixel(aSizedRect)).Top() < aOrgPxRect.Top() )
2025     {
2026         ++aSizedRect.Top();
2027     }
2028     /// adjust bottom()
2029     while ( (aOut.LogicToPixel(aSizedRect)).Bottom() > aOrgPxRect.Bottom() )
2030     {
2031         --aSizedRect.Bottom();
2032     }
2033 
2034     io_aSwRect = SwRect( aSizedRect );
2035 
2036 #ifdef DBG_UTIL
2037     Rectangle aTestOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
2038     Rectangle aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2039     ASSERT( aTestOrgPxRect == aTestNewPxRect,
2040             "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size");
2041 #if OSL_DEBUG_LEVEL > 1
2042     Rectangle aTestNewRect( aSizedRect );
2043     /// check Left()
2044     --aSizedRect.Left();
2045     aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2046     ASSERT( aTestOrgPxRect.Left() >= (aTestNewPxRect.Left()+1),
2047             "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted");
2048     ++aSizedRect.Left();
2049     /// check Right()
2050     ++aSizedRect.Right();
2051     aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2052     ASSERT( aTestOrgPxRect.Right() <= (aTestNewPxRect.Right()-1),
2053             "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted");
2054     --aSizedRect.Right();
2055     /// check Top()
2056     --aSizedRect.Top();
2057     aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2058     ASSERT( aTestOrgPxRect.Top() >= (aTestNewPxRect.Top()+1),
2059             "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted");
2060     ++aSizedRect.Top();
2061     /// check Bottom()
2062     ++aSizedRect.Bottom();
2063     aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2064     ASSERT( aTestOrgPxRect.Bottom() <= (aTestNewPxRect.Bottom()-1),
2065             "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted");
2066     --aSizedRect.Bottom();
2067 #endif
2068 #endif
2069 }
2070 
2071 
2072 //
2073 // FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES START
2074 //
2075 
2076 struct SwLineEntry
2077 {
2078     SwTwips mnKey;
2079     SwTwips mnStartPos;
2080     SwTwips mnEndPos;
2081 
2082     svx::frame::Style maAttribute;
2083 
2084     enum OverlapType { NO_OVERLAP, OVERLAP1, OVERLAP2, OVERLAP3 };
2085 
2086 public:
2087     SwLineEntry( SwTwips nKey,
2088                  SwTwips nStartPos,
2089                  SwTwips nEndPos,
2090                  const svx::frame::Style& rAttribute );
2091 
2092     OverlapType Overlaps( const SwLineEntry& rComp ) const;
2093 };
2094 
2095 SwLineEntry::SwLineEntry( SwTwips nKey,
2096                           SwTwips nStartPos,
2097                           SwTwips nEndPos,
2098                           const svx::frame::Style& rAttribute )
2099     :   mnKey( nKey ),
2100         mnStartPos( nStartPos ),
2101         mnEndPos( nEndPos ),
2102         maAttribute( rAttribute )
2103 {
2104 }
2105 
2106 /*
2107 
2108  1. ----------    rOld
2109        ---------- rNew
2110 
2111  2. ----------    rOld
2112     ------------- rNew
2113 
2114  3.    -------    rOld
2115     ------------- rNew
2116 
2117  4. ------------- rOld
2118        ---------- rNew
2119 
2120  5. ----------    rOld
2121        ----       rNew
2122 
2123  6. ----------    rOld
2124     ----------    rNew
2125 
2126  7. ------------- rOld
2127     ----------    rNew
2128 
2129  8.    ---------- rOld
2130     ------------- rNew
2131 
2132  9.    ---------- rOld
2133     ----------    rNew
2134 */
2135 
2136 SwLineEntry::OverlapType SwLineEntry::Overlaps( const SwLineEntry& rNew )  const
2137 {
2138     SwLineEntry::OverlapType eRet = OVERLAP3;
2139 
2140     if ( mnStartPos >= rNew.mnEndPos || mnEndPos <= rNew.mnStartPos )
2141         eRet = NO_OVERLAP;
2142 
2143     // 1, 2, 3
2144     else if ( mnEndPos < rNew.mnEndPos )
2145         eRet = OVERLAP1;
2146 
2147     // 4, 5, 6, 7
2148     else if ( mnStartPos <= rNew.mnStartPos && mnEndPos >= rNew.mnEndPos )
2149         eRet = OVERLAP2;
2150 
2151     // 8, 9
2152     return eRet;
2153 }
2154 
2155 struct lt_SwLineEntry
2156 {
2157     bool operator()( const SwLineEntry& e1, const SwLineEntry& e2 ) const
2158     {
2159         return e1.mnStartPos < e2.mnStartPos;
2160     }
2161 };
2162 
2163 typedef std::set< SwLineEntry, lt_SwLineEntry > SwLineEntrySet;
2164 typedef std::set< SwLineEntry, lt_SwLineEntry >::iterator SwLineEntrySetIter;
2165 typedef std::set< SwLineEntry, lt_SwLineEntry >::const_iterator SwLineEntrySetConstIter;
2166 typedef std::map< SwTwips, SwLineEntrySet > SwLineEntryMap;
2167 typedef std::map< SwTwips, SwLineEntrySet >::iterator SwLineEntryMapIter;
2168 typedef std::map< SwTwips, SwLineEntrySet >::const_iterator SwLineEntryMapConstIter;
2169 
2170 class SwTabFrmPainter
2171 {
2172     SwLineEntryMap maVertLines;
2173     SwLineEntryMap maHoriLines;
2174     const SwTabFrm& mrTabFrm;
2175 
2176     void Insert( SwLineEntry&, bool bHori );
2177     void Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem );
2178     void HandleFrame( const SwLayoutFrm& rFrm );
2179     void FindStylesForLine( const Point&,
2180                             const Point&,
2181                             svx::frame::Style*,
2182                             bool bHori ) const;
2183 
2184 public:
2185     SwTabFrmPainter( const SwTabFrm& rTabFrm );
2186 
2187     void PaintLines( OutputDevice& rDev, const SwRect& rRect ) const;
2188 };
2189 
2190 SwTabFrmPainter::SwTabFrmPainter( const SwTabFrm& rTabFrm )
2191     : mrTabFrm( rTabFrm )
2192 {
2193     HandleFrame( rTabFrm );
2194 }
2195 
2196 void SwTabFrmPainter::HandleFrame( const SwLayoutFrm& rLayoutFrm )
2197 {
2198     // Add border lines of cell frames. Skip covered cells. Skip cells
2199     // in special row span row, which do not have a negative row span:
2200     if ( rLayoutFrm.IsCellFrm() && !rLayoutFrm.IsCoveredCell() )
2201     {
2202         const SwCellFrm* pThisCell = static_cast<const SwCellFrm*>(&rLayoutFrm);
2203         const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pThisCell->GetUpper());
2204         const long nRowSpan = pThisCell->GetTabBox()->getRowSpan();
2205         if ( !pRowFrm->IsRowSpanLine() || nRowSpan > 1 || nRowSpan < -1 )
2206         {
2207             SwBorderAttrAccess aAccess( SwFrm::GetCache(), &rLayoutFrm );
2208             const SwBorderAttrs& rAttrs = *aAccess.Get();
2209             const SvxBoxItem& rBox = rAttrs.GetBox();
2210             Insert( rLayoutFrm, rBox );
2211         }
2212     }
2213 
2214     // Recurse into lower layout frames, but do not recurse into lower tabframes.
2215     const SwFrm* pLower = rLayoutFrm.Lower();
2216     while ( pLower )
2217     {
2218         const SwLayoutFrm* pLowerLayFrm = dynamic_cast<const SwLayoutFrm*>(pLower);
2219         if ( pLowerLayFrm && !pLowerLayFrm->IsTabFrm() )
2220             HandleFrame( *pLowerLayFrm );
2221 
2222         pLower = pLower->GetNext();
2223     }
2224 }
2225 
2226 void SwTabFrmPainter::PaintLines( OutputDevice& rDev, const SwRect& rRect ) const
2227 {
2228     // --> FME 2004-06-24 #i16816# tagged pdf support
2229     SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, rDev );
2230     // <--
2231 
2232     const SwFrm* pTmpFrm = &mrTabFrm;
2233     const bool bVert = pTmpFrm->IsVertical();
2234 
2235     SwLineEntryMapConstIter aIter = maHoriLines.begin();
2236     bool bHori = true;
2237 
2238     // color for subsidiary lines:
2239     const Color& rCol( SwViewOption::GetTableBoundariesColor() );
2240 
2241     // high contrast mode:
2242     // overrides the color of non-subsidiary lines.
2243     const Color* pHCColor = 0;
2244     sal_uLong nOldDrawMode = rDev.GetDrawMode();
2245     if( pGlobalShell->GetWin() &&
2246         Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
2247     {
2248         pHCColor = &SwViewOption::GetFontColor();
2249         rDev.SetDrawMode( 0 );
2250     }
2251 
2252     // set clip region:
2253     rDev.Push( PUSH_CLIPREGION );
2254     Size aSize( rRect.SSize() );
2255     // Hack! Necessary, because the layout is not pixel aligned!
2256     aSize.Width() += nPixelSzW; aSize.Height() += nPixelSzH;
2257     rDev.SetClipRegion( Rectangle( rRect.Pos(), aSize ) );
2258 
2259     // The following stuff if necessary to have the new table borders fit
2260     // into a ::SwAlignRect adjusted world.
2261     const SwTwips nTwipXCorr =  bVert ? 0 : Max( 0L, nHalfPixelSzW - 2 );    // 1 < 2 < 3 ;-)
2262     const SwTwips nTwipYCorr = !bVert ? 0 : Max( 0L, nHalfPixelSzW - 2 );    // 1 < 2 < 3 ;-)
2263     const SwFrm* pUpper = mrTabFrm.GetUpper();
2264     SwRect aUpper( pUpper->Prt() );
2265     aUpper.Pos() += pUpper->Frm().Pos();
2266     SwRect aUpperAligned( aUpper );
2267     ::SwAlignRect( aUpperAligned, pGlobalShell );
2268 
2269     while ( true )
2270     {
2271         if ( bHori && aIter == maHoriLines.end() )
2272         {
2273             aIter = maVertLines.begin();
2274             bHori = false;
2275         }
2276 
2277         if ( !bHori && aIter == maVertLines.end() )
2278             break;
2279 
2280         const SwLineEntrySet& rEntrySet = (*aIter).second;
2281         SwLineEntrySetIter aSetIter = rEntrySet.begin();
2282         while ( aSetIter != rEntrySet.end() )
2283         {
2284             const SwLineEntry& rEntry = *aSetIter;
2285             const svx::frame::Style& rEntryStyle( (*aSetIter).maAttribute );
2286 
2287             Point aStart, aEnd;
2288             if ( bHori )
2289             {
2290                 aStart.X() = rEntry.mnStartPos;
2291                 aStart.Y() = rEntry.mnKey;
2292                 aEnd.X() = rEntry.mnEndPos;
2293                 aEnd.Y() = rEntry.mnKey;
2294             }
2295             else
2296             {
2297                 aStart.X() = rEntry.mnKey;
2298                 aStart.Y() = rEntry.mnStartPos;
2299                 aEnd.X() = rEntry.mnKey;
2300                 aEnd.Y() = rEntry.mnEndPos;
2301             }
2302 
2303             SwRect aRepaintRect( aStart, aEnd );
2304 
2305             // the repaint rectangle has to be moved a bit for the centered lines:
2306             SwTwips nRepaintRectSize = !rEntryStyle.GetWidth() ? 1 : rEntryStyle.GetWidth();
2307             if ( bHori )
2308             {
2309                 aRepaintRect.Height( 2 * nRepaintRectSize );
2310                 aRepaintRect.Pos().Y() -= nRepaintRectSize;
2311             }
2312             else
2313             {
2314                 aRepaintRect.Width( 2 * nRepaintRectSize );
2315                 aRepaintRect.Pos().X() -= nRepaintRectSize;
2316             }
2317 
2318             if ( rRect.IsOver( aRepaintRect ) )
2319             {
2320                 svx::frame::Style aStyles[ 7 ];
2321                 aStyles[ 0 ] = rEntryStyle;
2322                 FindStylesForLine( aStart, aEnd, aStyles, bHori );
2323 
2324                 // subsidiary lines
2325                 const Color* pTmpColor = 0;
2326                 if ( 0 == aStyles[ 0 ].GetWidth() )
2327                 {
2328                     if ( IS_SUBS_TABLE && pGlobalShell->GetWin() )
2329                         aStyles[ 0 ].Set( rCol, 1, 0, 0 );
2330                 }
2331                 else
2332                     pTmpColor = pHCColor;
2333 
2334                 // The line sizes stored in the line style have to be adjusted as well.
2335                 // This will guarantee that lines with the same twip size will have the
2336                 // same pixel size.
2337                 for ( int i = 0; i < 7; ++i )
2338                 {
2339                     sal_uInt16 nPrim = aStyles[ i ].Prim();
2340                     sal_uInt16 nDist = aStyles[ i ].Dist();
2341                     sal_uInt16 nSecn = aStyles[ i ].Secn();
2342 
2343                     if ( nPrim > 0 )
2344                         nPrim = (sal_uInt16)( Max( 1L, nPixelSzH * ( nPrim / nPixelSzH ) ) );
2345                     if ( nDist > 0 )
2346                         nDist = (sal_uInt16)( Max( 1L, nPixelSzH * ( nDist / nPixelSzH ) ) );
2347                     if ( nSecn > 0 )
2348                         nSecn = (sal_uInt16)( Max( 1L, nPixelSzH * ( nSecn / nPixelSzH ) ) );
2349 
2350                     aStyles[ i ].Set( nPrim, nDist, nSecn );
2351                 }
2352 
2353                 // The (twip) positions will be adjusted to meet these requirements:
2354                 // 1. The y coordinates are located in the middle of the pixel grid
2355                 // 2. The x coordinated are located at the beginning of the pixel grid
2356                 // This is done, because the horizontal lines are painted "at beginning",
2357                 // whereas the vertical lines are painted "centered". By making the line
2358                 // sizes a multiple of one pixel size, we can assure, that all lines having
2359                 // the same twip size have the same pixel size, independent of their position
2360                 // on the screen.
2361                 Point aPaintStart = rDev.PixelToLogic( rDev.LogicToPixel( aStart ) );
2362                 Point aPaintEnd = rDev.PixelToLogic( rDev.LogicToPixel( aEnd ) );
2363 
2364                 if( pGlobalShell->GetWin() )
2365                 {
2366                     // The table borders do not use SwAlignRect, but all the other frames do.
2367                     // Therefore we tweak the outer borders a bit to achieve that the outer
2368                     // borders match the subsidiary lines of the upper:
2369                     if ( aStart.X() == aUpper.Left() )
2370                         aPaintStart.X() = aUpperAligned.Left();
2371                     else if ( aStart.X() == aUpper._Right() )
2372                         aPaintStart.X() = aUpperAligned._Right();
2373                     if ( aStart.Y() == aUpper.Top() )
2374                         aPaintStart.Y() = aUpperAligned.Top();
2375                     else if ( aStart.Y() == aUpper._Bottom() )
2376                         aPaintStart.Y() = aUpperAligned._Bottom();
2377 
2378                     if ( aEnd.X() == aUpper.Left() )
2379                         aPaintEnd.X() = aUpperAligned.Left();
2380                     else if ( aEnd.X() == aUpper._Right() )
2381                         aPaintEnd.X() = aUpperAligned._Right();
2382                     if ( aEnd.Y() == aUpper.Top() )
2383                         aPaintEnd.Y() = aUpperAligned.Top();
2384                     else if ( aEnd.Y() == aUpper._Bottom() )
2385                         aPaintEnd.Y() = aUpperAligned._Bottom();
2386                 }
2387 
2388                 aPaintStart.X() -= nTwipXCorr; // nHalfPixelSzW - 2 to assure that we do not leave the pixel
2389                 aPaintEnd.X()   -= nTwipXCorr;
2390                 aPaintStart.Y() -= nTwipYCorr;
2391                 aPaintEnd.Y()   -= nTwipYCorr;
2392 
2393                 // Here comes the painting stuff: Thank you, DR, great job!!!
2394                 if ( bHori )
2395                 {
2396                     svx::frame::DrawHorFrameBorder
2397                     (
2398                         rDev,
2399                         aPaintStart,
2400                         aPaintEnd,
2401                         aStyles[ 0 ],   // current style
2402                         aStyles[ 1 ],   // aLFromT
2403                         aStyles[ 2 ],   // aLFromL
2404                         aStyles[ 3 ],   // aLFromB
2405                         aStyles[ 4 ],   // aRFromT
2406                         aStyles[ 5 ],   // aRFromR
2407                         aStyles[ 6 ],   // aRFromB
2408                         pTmpColor
2409                     );
2410                 }
2411                 else
2412                 {
2413                     svx::frame::DrawVerFrameBorder
2414                     (
2415                         rDev,
2416                         aPaintStart,
2417                         aPaintEnd,
2418                         aStyles[ 0 ],   // current style
2419                         aStyles[ 1 ],   // aTFromL
2420                         aStyles[ 2 ],   // aTFromT
2421                         aStyles[ 3 ],   // aTFromR
2422                         aStyles[ 4 ],   // aBFromL
2423                         aStyles[ 5 ],   // aBFromB
2424                         aStyles[ 6 ],   // aBFromR
2425                         pTmpColor
2426                     );
2427                 }
2428             }
2429 
2430             ++aSetIter;
2431         }
2432 
2433         ++aIter;
2434     }
2435 
2436     // restore output device:
2437     rDev.Pop();
2438     rDev.SetDrawMode( nOldDrawMode );
2439 }
2440 
2441 // Finds the lines that join the line defined by (StartPoint, EndPoint) in either
2442 // StartPoint or Endpoint. The styles of these lines are required for DR's magic
2443 // line painting functions.
2444 void SwTabFrmPainter::FindStylesForLine( const Point& rStartPoint,
2445                                          const Point& rEndPoint,
2446                                          svx::frame::Style* pStyles,
2447                                          bool bHori ) const
2448 {
2449     // pStyles[ 1 ] = bHori ? aLFromT : TFromL
2450     // pStyles[ 2 ] = bHori ? aLFromL : TFromT,
2451     // pStyles[ 3 ] = bHori ? aLFromB : TFromR,
2452     // pStyles[ 4 ] = bHori ? aRFromT : BFromL,
2453     // pStyles[ 5 ] = bHori ? aRFromR : BFromB,
2454     // pStyles[ 6 ] = bHori ? aRFromB : BFromR,
2455 
2456     SwLineEntryMapConstIter aMapIter = maVertLines.find( rStartPoint.X() );
2457     ASSERT( aMapIter != maVertLines.end(), "FindStylesForLine: Error" )
2458     const SwLineEntrySet& rVertSet = (*aMapIter).second;
2459     SwLineEntrySetConstIter aIter = rVertSet.begin();
2460 
2461     while ( aIter != rVertSet.end() )
2462     {
2463         const SwLineEntry& rEntry = *aIter;
2464         if ( bHori )
2465         {
2466             if ( rStartPoint.Y() == rEntry.mnStartPos )
2467                 pStyles[ 3 ] = rEntry.maAttribute;
2468             else if ( rStartPoint.Y() == rEntry.mnEndPos )
2469                 pStyles[ 1 ] = rEntry.maAttribute;
2470         }
2471         else
2472         {
2473             if ( rStartPoint.Y() == rEntry.mnEndPos )
2474                 pStyles[ 2 ] = rEntry.maAttribute;
2475             else if ( rEndPoint.Y() == rEntry.mnStartPos )
2476                 pStyles[ 5 ] = rEntry.maAttribute;
2477         }
2478         ++aIter;
2479     }
2480 
2481     aMapIter = maHoriLines.find( rStartPoint.Y() );
2482     ASSERT( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" )
2483     const SwLineEntrySet& rHoriSet = (*aMapIter).second;
2484     aIter = rHoriSet.begin();
2485 
2486     while ( aIter != rHoriSet.end() )
2487     {
2488         const SwLineEntry& rEntry = *aIter;
2489         if ( bHori )
2490         {
2491             if ( rStartPoint.X() == rEntry.mnEndPos )
2492                 pStyles[ 2 ] = rEntry.maAttribute;
2493             else if ( rEndPoint.X() == rEntry.mnStartPos )
2494                 pStyles[ 5 ] = rEntry.maAttribute;
2495         }
2496         else
2497         {
2498             if ( rStartPoint.X() == rEntry.mnEndPos )
2499                 pStyles[ 1 ] = rEntry.maAttribute;
2500             else if ( rStartPoint.X() == rEntry.mnStartPos )
2501                 pStyles[ 3 ] = rEntry.maAttribute;
2502         }
2503         ++aIter;
2504     }
2505 
2506     if ( bHori )
2507     {
2508         aMapIter = maVertLines.find( rEndPoint.X() );
2509         ASSERT( aMapIter != maVertLines.end(), "FindStylesForLine: Error" )
2510         const SwLineEntrySet& rVertSet2 = (*aMapIter).second;
2511         aIter = rVertSet2.begin();
2512 
2513         while ( aIter != rVertSet2.end() )
2514         {
2515             const SwLineEntry& rEntry = *aIter;
2516             if ( rEndPoint.Y() == rEntry.mnStartPos )
2517                 pStyles[ 6 ] = rEntry.maAttribute;
2518             else if ( rEndPoint.Y() == rEntry.mnEndPos )
2519                 pStyles[ 4 ] = rEntry.maAttribute;
2520             ++aIter;
2521         }
2522     }
2523     else
2524     {
2525         aMapIter = maHoriLines.find( rEndPoint.Y() );
2526         ASSERT( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" )
2527         const SwLineEntrySet& rHoriSet2 = (*aMapIter).second;
2528         aIter = rHoriSet2.begin();
2529 
2530         while ( aIter != rHoriSet2.end() )
2531         {
2532             const SwLineEntry& rEntry = *aIter;
2533             if ( rEndPoint.X() == rEntry.mnEndPos )
2534                 pStyles[ 4 ] = rEntry.maAttribute;
2535             else if ( rEndPoint.X() == rEntry.mnStartPos )
2536                 pStyles[ 6 ] = rEntry.maAttribute;
2537             ++aIter;
2538         }
2539     }
2540 }
2541 
2542 void SwTabFrmPainter::Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem )
2543 {
2544     std::vector< const SwFrm* > aTestVec;
2545     aTestVec.push_back( &rFrm );
2546     aTestVec.push_back( &rFrm );
2547     aTestVec.push_back( &rFrm );
2548 
2549     // build 4 line entries for the 4 borders:
2550     SwRect aBorderRect = rFrm.Frm();
2551     if ( rFrm.IsTabFrm() )
2552     {
2553         aBorderRect = rFrm.Prt();
2554         aBorderRect.Pos() += rFrm.Frm().Pos();
2555     }
2556 
2557     const SwTwips nLeft   = aBorderRect._Left();
2558     const SwTwips nRight  = aBorderRect._Right();
2559     const SwTwips nTop    = aBorderRect._Top();
2560     const SwTwips nBottom = aBorderRect._Bottom();
2561 
2562     svx::frame::Style aL( rBoxItem.GetLeft() );
2563     svx::frame::Style aR( rBoxItem.GetRight() );
2564     svx::frame::Style aT( rBoxItem.GetTop() );
2565     svx::frame::Style aB( rBoxItem.GetBottom() );
2566 
2567     aR.MirrorSelf();
2568     aB.MirrorSelf();
2569 
2570     bool bVert = mrTabFrm.IsVertical();
2571     bool bR2L  = mrTabFrm.IsRightToLeft();
2572 
2573     aL.SetRefMode( svx::frame::REFMODE_CENTERED );
2574     aR.SetRefMode( svx::frame::REFMODE_CENTERED );
2575     aT.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
2576     aB.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
2577 
2578     SwLineEntry aLeft  ( nLeft,   nTop,  nBottom, bVert ? aB : ( bR2L ? aR : aL ) );
2579     SwLineEntry aRight ( nRight,  nTop,  nBottom, bVert ? aT : ( bR2L ? aL : aR ) );
2580     SwLineEntry aTop   ( nTop,    nLeft, nRight,  bVert ? aL : aT );
2581     SwLineEntry aBottom( nBottom, nLeft, nRight,  bVert ? aR : aB );
2582 
2583     Insert( aLeft, false );
2584     Insert( aRight, false );
2585     Insert( aTop, true );
2586     Insert( aBottom, true );
2587 
2588     const SwRowFrm* pThisRowFrm = dynamic_cast<const SwRowFrm*>(rFrm.GetUpper());
2589 
2590     // special case: #i9860#
2591     // first line in follow table without repeated headlines
2592     if ( pThisRowFrm &&
2593          pThisRowFrm->GetUpper() == &mrTabFrm &&
2594          mrTabFrm.IsFollow() &&
2595         !mrTabFrm.GetTable()->GetRowsToRepeat() &&
2596         (!pThisRowFrm->GetPrev() || static_cast<const SwRowFrm*>(pThisRowFrm->GetPrev())->IsRowSpanLine()) &&
2597         !rBoxItem.GetTop() &&
2598          rBoxItem.GetBottom() )
2599     {
2600         SwLineEntry aFollowTop( !bVert ? nTop : nRight, !bVert ? nLeft : nTop, !bVert ? nRight : nBottom, aB );
2601         Insert( aFollowTop, !bVert );
2602     }
2603 }
2604 
2605 void SwTabFrmPainter::Insert( SwLineEntry& rNew, bool bHori )
2606 {
2607     // get all lines from structure, that have key entry of pLE
2608     SwLineEntryMap* pLine2 = bHori ? &maHoriLines : &maVertLines;
2609     const SwTwips nKey = rNew.mnKey;
2610     SwLineEntryMapIter aMapIter = pLine2->find( nKey );
2611 
2612     SwLineEntrySet* pLineSet = aMapIter != pLine2->end() ? &((*aMapIter).second) : 0;
2613     if ( !pLineSet )
2614     {
2615         SwLineEntrySet aNewSet;
2616         (*pLine2)[ nKey ] = aNewSet;
2617         pLineSet = &(*pLine2)[ nKey ];
2618     }
2619     SwLineEntrySetIter aIter = pLineSet->begin();
2620 
2621     while ( pLineSet && aIter != pLineSet->end() && rNew.mnStartPos < rNew.mnEndPos )
2622     {
2623         const SwLineEntry& rOld = *aIter;
2624         const SwLineEntry::OverlapType nOverlapType = rOld.Overlaps( rNew );
2625 
2626         const svx::frame::Style& rOldAttr = rOld.maAttribute;
2627         const svx::frame::Style& rNewAttr = rNew.maAttribute;
2628         const svx::frame::Style& rCmpAttr = rNewAttr > rOldAttr ? rNewAttr : rOldAttr;
2629 
2630         if ( SwLineEntry::OVERLAP1 == nOverlapType )
2631         {
2632             ASSERT( rNew.mnStartPos >= rOld.mnStartPos, "Overlap type 3? How this?" )
2633 
2634             // new left segment
2635             const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
2636 
2637             // new middle segment
2638             const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rOld.mnEndPos, rCmpAttr );
2639 
2640             // new right segment
2641             rNew.mnStartPos = rOld.mnEndPos;
2642 
2643             // update current lines set
2644             pLineSet->erase( aIter );
2645             if ( aLeft.mnStartPos   < aLeft.mnEndPos   ) pLineSet->insert( aLeft );
2646             if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
2647 
2648             aIter = pLineSet->begin();
2649 
2650             continue; // start over
2651         }
2652         else if ( SwLineEntry::OVERLAP2 == nOverlapType )
2653         {
2654             // new left segment
2655             const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
2656 
2657             // new middle segment
2658             const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rNew.mnEndPos, rCmpAttr );
2659 
2660             // new right segment
2661             const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
2662 
2663             // update current lines set
2664             pLineSet->erase( aIter );
2665             if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
2666             if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
2667             if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
2668 
2669             rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
2670 
2671             break; // we are finished
2672         }
2673         else if ( SwLineEntry::OVERLAP3 == nOverlapType )
2674         {
2675             // new left segment
2676             const SwLineEntry aLeft( nKey, rNew.mnStartPos, rOld.mnStartPos, rNewAttr );
2677 
2678             // new middle segment
2679             const SwLineEntry aMiddle( nKey, rOld.mnStartPos, rNew.mnEndPos, rCmpAttr );
2680 
2681             // new right segment
2682             const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
2683 
2684             // update current lines set
2685             pLineSet->erase( aIter );
2686             if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
2687             if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
2688             if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
2689 
2690             rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
2691 
2692             break; // we are finished
2693         }
2694 
2695         ++aIter;
2696     }
2697 
2698     if ( rNew.mnStartPos < rNew.mnEndPos ) // insert rest
2699         pLineSet->insert( rNew );
2700 }
2701 
2702 //
2703 // FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES END
2704 //
2705 
2706 // --> OD #i76669#
2707 namespace
2708 {
2709     class SwViewObjectContactRedirector : public ::sdr::contact::ViewObjectContactRedirector
2710     {
2711         private:
2712             const ViewShell& mrViewShell;
2713 
2714         public:
2715             SwViewObjectContactRedirector( const ViewShell& rSh )
2716                 : mrViewShell( rSh )
2717             {};
2718 
2719             virtual ~SwViewObjectContactRedirector()
2720             {}
2721 
2722             virtual drawinglayer::primitive2d::Primitive2DSequence createRedirectedPrimitive2DSequence(
2723                                     const sdr::contact::ViewObjectContact& rOriginal,
2724                                     const sdr::contact::DisplayInfo& rDisplayInfo)
2725             {
2726                 sal_Bool bPaint( sal_True );
2727 
2728                 SdrObject* pObj = rOriginal.GetViewContact().TryToGetSdrObject();
2729                 if ( pObj )
2730                 {
2731                     bPaint = SwFlyFrm::IsPaint( pObj, &mrViewShell );
2732                 }
2733 
2734                 if ( !bPaint )
2735                 {
2736                     return drawinglayer::primitive2d::Primitive2DSequence();
2737                 }
2738 
2739                 return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(
2740                                                         rOriginal, rDisplayInfo );
2741             }
2742     };
2743 
2744 } // end of anonymous namespace
2745 // <--
2746 
2747 /*************************************************************************
2748 |*
2749 |*	SwRootFrm::Paint()
2750 |*
2751 |*	Beschreibung
2752 |*		Fuer jede sichtbare Seite, die von Rect ber?hrt wird einmal Painten.
2753 |*		1. Umrandungen und Hintergruende Painten.
2754 |*		2. Den Draw Layer (Ramen und Zeichenobjekte) der unter dem Dokument
2755 |* 		   liegt painten (Hoelle).
2756 |*		3. Den Dokumentinhalt (Text) Painten.
2757 |*		4. Den Drawlayer der ueber dem Dokuemnt liegt painten.
2758 |*
2759 |*	Ersterstellung		MA 01. Jun. 92
2760 |*	Letzte Aenderung	MA 10. Oct. 97
2761 |*
2762 |*************************************************************************/
2763 
2764 void
2765 SwRootFrm::Paint(SwRect const& rRect, SwPrintData const*const pPrintData) const
2766 {
2767     ASSERT( Lower() && Lower()->IsPageFrm(), "Lower der Root keine Seite." );
2768 
2769 	PROTOCOL( this, PROT_FILE_INIT, 0, 0)
2770 
2771 	sal_Bool bResetRootPaint = sal_False;
2772 	ViewShell *pSh = pCurrShell;
2773 
2774 	if ( pSh->GetWin() )
2775 	{
2776 		if ( pSh->GetOut() == pSh->GetWin() && !pSh->GetWin()->IsVisible() )
2777 		{
2778 			return;
2779 		}
2780 		if ( SwRootFrm::bInPaint )
2781 		{
2782 			SwPaintQueue::Add( pSh, rRect );
2783 			return;
2784 		}
2785 	}
2786 	else
2787 		SwRootFrm::bInPaint = bResetRootPaint = sal_True;
2788 
2789 	SwSavePaintStatics *pStatics = 0;
2790 	if ( pGlobalShell )
2791 		pStatics = new SwSavePaintStatics();
2792 	pGlobalShell = pSh;
2793 
2794     if( !pSh->GetWin() )
2795 		pProgress = SfxProgress::GetActiveProgress( (SfxObjectShell*) pSh->GetDoc()->GetDocShell() );
2796 
2797 	::SwCalcPixStatics( pSh->GetOut() );
2798 	aGlobalRetoucheColor = pSh->Imp()->GetRetoucheColor();
2799 
2800 	//Ggf. eine Action ausloesen um klare Verhaeltnisse zu schaffen.
2801 	//Durch diesen Kunstgriff kann in allen Paints davon ausgegangen werden,
2802 	//das alle Werte gueltigt sind - keine Probleme, keine Sonderbehandlung(en).
2803     // --> OD 2008-10-07 #i92745#
2804     // Extend check on certain states of the 'current' <ViewShell> instance to
2805     // all existing <ViewShell> instances.
2806     bool bPerformLayoutAction( true );
2807     {
2808         ViewShell* pTmpViewShell = pSh;
2809         do {
2810             if ( pTmpViewShell->IsInEndAction() ||
2811                  pTmpViewShell->IsPaintInProgress() ||
2812                  ( pTmpViewShell->Imp()->IsAction() &&
2813                    pTmpViewShell->Imp()->GetLayAction().IsActionInProgress() ) )
2814             {
2815                 bPerformLayoutAction = false;
2816             }
2817 
2818             pTmpViewShell = static_cast<ViewShell*>(pTmpViewShell->GetNext());
2819         } while ( bPerformLayoutAction && pTmpViewShell != pSh );
2820     }
2821     if ( bPerformLayoutAction )
2822     // <--
2823     {
2824 		((SwRootFrm*)this)->ResetTurbo();
2825 		SwLayAction aAction( (SwRootFrm*)this, pSh->Imp() );
2826 		aAction.SetPaint( sal_False );
2827 		aAction.SetComplete( sal_False );
2828 		aAction.SetReschedule( pProgress ? sal_True : sal_False );
2829 		aAction.Action();
2830 		((SwRootFrm*)this)->ResetTurboFlag();
2831 		if ( !pSh->ActionPend() )
2832             pSh->Imp()->DelRegion();
2833 	}
2834 
2835 	SwRect aRect( rRect );
2836     aRect.Intersection( pSh->VisArea() );
2837 
2838     const sal_Bool bExtraData = ::IsExtraData( GetFmt()->GetDoc() );
2839 
2840 	pLines = new SwLineRects;	//Sammler fuer Umrandungen.
2841 
2842     // #104289#. During painting, something (OLE) can
2843     // load the linguistic, which in turn can cause a reformat
2844     // of the document. Dangerous! We better set this flag to
2845     // avoid the reformat.
2846     const sal_Bool bOldAction = IsCallbackActionEnabled();
2847     ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
2848 
2849 	const SwPageFrm *pPage = pSh->Imp()->GetFirstVisPage();
2850 
2851     const bool bBookMode = pGlobalShell->GetViewOptions()->IsViewLayoutBookMode();
2852     if ( bBookMode && pPage->GetPrev() && static_cast<const SwPageFrm*>(pPage->GetPrev())->IsEmptyPage() )
2853         pPage = static_cast<const SwPageFrm*>(pPage->GetPrev());
2854 
2855     const bool bLTR = IsLeftToRightViewLayout();
2856 
2857 	// #i68597#
2858 	const bool bGridPainting(pSh->GetWin() && pSh->Imp()->HasDrawView() && pSh->Imp()->GetDrawView()->IsGridVisible());
2859 
2860     // --> OD #i76669#
2861     SwViewObjectContactRedirector aSwRedirector( *pSh );
2862     // <--
2863 
2864     while ( pPage )
2865     {
2866         const bool bPaintRightShadow =  !bBookMode || (pPage == Lower()) || (!bLTR && !pPage->OnRightPage()) || (bLTR && pPage->OnRightPage());
2867         const bool bRightSidebar = pPage->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT;
2868 
2869         if ( !pPage->IsEmptyPage() )
2870         {
2871             SwRect aPaintRect;
2872             SwPageFrm::GetBorderAndShadowBoundRect( pPage->Frm(), pSh, aPaintRect, bRightSidebar );
2873 
2874             if ( aRect.IsOver( aPaintRect ) )
2875             {
2876                 if ( pSh->GetWin() )
2877                 {
2878                     pSubsLines = new SwSubsRects;
2879                     pSpecSubsLines = new SwSubsRects;
2880                 }
2881 
2882                 aPaintRect._Intersection( aRect );
2883 
2884                 // --> OD 2007-11-14 #i82616#
2885                 // Invalidate area for extra data (line numbers or change tracking
2886                 // marks), if painting on a window and the paint is trigger by an
2887                 // end action. The inefficient and simple enlargement of the
2888                 // paint area is replaced by this invalidation.
2889                 if ( bExtraData &&
2890                      pSh->GetWin() && pSh->IsInEndAction() )
2891                 {
2892                     // enlarge paint rectangle to complete page width, subtract
2893                     // current paint area and invalidate the resulting region.
2894                     SWRECTFN( pPage )
2895                     SwRect aPageRectTemp( aPaintRect );
2896                     (aPageRectTemp.*fnRect->fnSetLeftAndWidth)(
2897                          (pPage->Frm().*fnRect->fnGetLeft)(),
2898                          (pPage->Frm().*fnRect->fnGetWidth)() );
2899                     aPageRectTemp._Intersection( pSh->VisArea() );
2900                     Region aPageRectRegion( aPageRectTemp.SVRect() );
2901                     aPageRectRegion.Exclude( aPaintRect.SVRect() );
2902                     pSh->GetWin()->Invalidate( aPageRectRegion, INVALIDATE_CHILDREN );
2903                 }
2904                 // <--
2905 
2906                 // --> OD 2007-08-20 #i80793#
2907                 // enlarge paint rectangle for objects overlapping the same pixel
2908                 // in all cases and before the DrawingLayer overlay is initialized.
2909                 lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
2910                 // <--
2911 
2912                 // #i68597#
2913                 // moved paint pre-process for DrawingLayer overlay here since the above
2914                 // code dependent from bExtraData may expand the PaintRect
2915                 {
2916                     // #i75172# if called from ViewShell::ImplEndAction it sould no longer
2917                     // really be used but handled by ViewShell::ImplEndAction already
2918                     const Region aDLRegion(aPaintRect.SVRect());
2919                     pSh->DLPrePaint2(aDLRegion);
2920                 }
2921 
2922                 if(OUTDEV_WINDOW == pGlobalShell->GetOut()->GetOutDevType())
2923                 {
2924                     /// OD 27.09.2002 #103636# - changed method SwLayVout::Enter(..)
2925                     /// 2nd parameter is no longer <const> and will be set to the
2926                     /// rectangle the virtual output device is calculated from <aPaintRect>,
2927                     /// if the virtual output is used.
2928                     pVout->Enter( pSh, aPaintRect, !bNoVirDev );
2929 
2930                     /// OD 27.09.2002 #103636# - adjust paint rectangle to pixel size
2931                     /// Thus, all objects overlapping on pixel level with the unadjusted
2932                     /// paint rectangle will be considered in the paint.
2933                     lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
2934                 }
2935 
2936                 // maybe this can be put in the above scope. Since we are not sure, just leave it ATM
2937                 pVout->SetOrgRect( aPaintRect );
2938 
2939                 /// OD 29.08.2002 #102450#
2940                 /// determine background color of page for <PaintLayer> method
2941                 /// calls, paint <hell> or <heaven>
2942                 const Color aPageBackgrdColor = pPage->GetDrawBackgrdColor();
2943 
2944                 pPage->PaintBaBo( aPaintRect, pPage, sal_True );
2945 
2946                 if ( pSh->Imp()->HasDrawView() )
2947                 {
2948                     pLines->LockLines( sal_True );
2949                     const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
2950                     pSh->Imp()->PaintLayer( pIDDMA->GetHellId(),
2951                                             pPrintData,
2952                                             aPaintRect,
2953                                             &aPageBackgrdColor,
2954                                             (pPage->IsRightToLeft() ? true : false),
2955                                             &aSwRedirector );
2956                     pLines->PaintLines( pSh->GetOut() );
2957                     pLines->LockLines( sal_False );
2958                 }
2959 
2960                 if( pSh->GetWin() )
2961                 {
2962                     // collect sub-lines
2963                     pPage->RefreshSubsidiary( aPaintRect );
2964                     // paint special sub-lines
2965                     pSpecSubsLines->PaintSubsidiary( pSh->GetOut(), NULL );
2966                 }
2967 
2968                 pPage->Paint( aPaintRect );
2969 
2970                 // no paint of page border and shadow, if writer is in place mode.
2971                 if( pSh->GetWin() && pSh->GetDoc()->GetDocShell() &&
2972                     !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
2973                 {
2974                     SwPageFrm::PaintBorderAndShadow( pPage->Frm(), pSh, bPaintRightShadow, bRightSidebar );
2975                     SwPageFrm::PaintNotesSidebar( pPage->Frm(), pSh, pPage->GetPhyPageNum(), bRightSidebar);
2976                 }
2977 
2978                 pLines->PaintLines( pSh->GetOut() );
2979 
2980                 if ( pSh->Imp()->HasDrawView() )
2981                 {
2982                     /// OD 29.08.2002 #102450# - add 3rd parameter
2983                     // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
2984                     pSh->Imp()->PaintLayer( pSh->GetDoc()->GetHeavenId(),
2985                                             pPrintData,
2986                                             aPaintRect,
2987                                             &aPageBackgrdColor,
2988                                             (pPage->IsRightToLeft() ? true : false),
2989                                             &aSwRedirector );
2990                 }
2991 
2992                 if ( bExtraData )
2993                     pPage->RefreshExtraData( aPaintRect );
2994 
2995                 if ( pSh->GetWin() )
2996                 {
2997                     pSubsLines->PaintSubsidiary( pSh->GetOut(), pLines );
2998                     DELETEZ( pSubsLines );
2999                     DELETEZ( pSpecSubsLines );
3000                 }
3001                 pVout->Leave();
3002 
3003                 // #i68597#
3004                 // needed to move grid painting inside Begin/EndDrawLayer bounds and to change
3005                 // output rect for it accordingly
3006                 if(bGridPainting)
3007                 {
3008                     SdrPaintView* pPaintView = pSh->Imp()->GetDrawView();
3009                     SdrPageView* pPageView = pPaintView->GetSdrPageView();
3010                     pPageView->DrawPageViewGrid(*pSh->GetOut(), aPaintRect.SVRect(), SwViewOption::GetTextGridColor() );
3011                 }
3012 
3013                 // #i68597#
3014                 // moved paint post-process for DrawingLayer overlay here, see above
3015                 {
3016                     pSh->DLPostPaint2(true);
3017                 }
3018             }
3019         }
3020         else if ( bBookMode && pSh->GetWin() && !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
3021         {
3022             // paint empty page
3023             SwRect aPaintRect;
3024             SwRect aEmptyPageRect( pPage->Frm() );
3025 
3026             // code from vprint.cxx
3027             const SwPageFrm& rFormatPage = pPage->GetFormatPage();
3028             aEmptyPageRect.SSize() = rFormatPage.Frm().SSize();
3029 
3030             SwPageFrm::GetBorderAndShadowBoundRect( aEmptyPageRect, pSh, aPaintRect, bRightSidebar );
3031             aPaintRect._Intersection( aRect );
3032 
3033             if ( aRect.IsOver( aEmptyPageRect ) )
3034             {
3035                 // #i75172# if called from ViewShell::ImplEndAction it sould no longer
3036                 // really be used but handled by ViewShell::ImplEndAction already
3037                 {
3038                     const Region aDLRegion(aPaintRect.SVRect());
3039                     pSh->DLPrePaint2(aDLRegion);
3040                 }
3041 
3042                 if( pSh->GetOut()->GetFillColor() != aGlobalRetoucheColor )
3043                     pSh->GetOut()->SetFillColor( aGlobalRetoucheColor );
3044 
3045                 pSh->GetOut()->SetLineColor(); // OD 20.02.2003 #107369# - no line color
3046                 // OD 20.02.2003 #107369# - use aligned page rectangle
3047                 {
3048                     SwRect aTmpPageRect( aEmptyPageRect );
3049                     ::SwAlignRect( aTmpPageRect, pSh );
3050                     aEmptyPageRect = aTmpPageRect;
3051                 }
3052 
3053                 pSh->GetOut()->DrawRect( aEmptyPageRect.SVRect() );
3054 
3055                 // paint empty page text
3056                 const Font& rEmptyPageFont = SwPageFrm::GetEmptyPageFont();
3057                 const Font aOldFont( pSh->GetOut()->GetFont() );
3058 
3059                 pSh->GetOut()->SetFont( rEmptyPageFont );
3060                 pSh->GetOut()->DrawText( aEmptyPageRect.SVRect(), SW_RESSTR( STR_EMPTYPAGE ),
3061                                     TEXT_DRAW_VCENTER |
3062                                     TEXT_DRAW_CENTER |
3063                                     TEXT_DRAW_CLIP );
3064 
3065                 pSh->GetOut()->SetFont( aOldFont );
3066                 // paint shadow and border for empty page
3067                 // OD 19.02.2003 #107369# - use new method to paint page border and
3068                 // shadow
3069                 SwPageFrm::PaintBorderAndShadow( aEmptyPageRect, pSh, bPaintRightShadow, bRightSidebar );
3070                 SwPageFrm::PaintNotesSidebar( aEmptyPageRect, pSh, pPage->GetPhyPageNum(), bRightSidebar);
3071 
3072                 {
3073                     pSh->DLPostPaint2(true);
3074                 }
3075             }
3076         }
3077 
3078         ASSERT( !pPage->GetNext() || pPage->GetNext()->IsPageFrm(),
3079                 "Nachbar von Seite keine Seite." );
3080         pPage = (SwPageFrm*)pPage->GetNext();
3081     }
3082 
3083     DELETEZ( pLines );
3084 
3085 #ifdef FRANK_TEST
3086 	if ( pSh->GetWin() )
3087     {
3088         Rectangle aRect( aFrm.SVRect() );
3089         pSh->GetWin()->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
3090         pSh->GetWin()->SetFillColor();
3091         pSh->GetWin()->SetLineColor( COL_LIGHTRED );
3092         pSh->GetWin()->DrawRect( aRect );
3093         pSh->GetWin()->Pop();
3094     }
3095 #endif
3096 
3097 	if ( bResetRootPaint )
3098 		SwRootFrm::bInPaint = sal_False;
3099 	if ( pStatics )
3100 		delete pStatics;
3101 	else
3102 	{
3103 		pProgress = 0;
3104 		pGlobalShell = 0;
3105 	}
3106 
3107     ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
3108 }
3109 
3110 #ifdef LONG_TABLE_HACK
3111 
3112 /*************************************************************************
3113 |*
3114 |*	SwRootFrm::HackPrepareLongTblPaint()
3115 |*
3116 |*	Ersterstellung		MA 27. Sep. 96
3117 |*	Letzte Aenderung	MA 18. Nov. 97
3118 |*
3119 |*************************************************************************/
3120 
3121 void SwRootFrm::HackPrepareLongTblPaint( int nMode )
3122 {
3123 	switch ( nMode )
3124 	{
3125 		case HACK_TABLEMODE_INIT       : ASSERT( !pLines, "HackPrepare: already prepared" );
3126 										 pLines = new SwLineRects;
3127 										 ASSERT( !pGlobalShell, "old GlobalShell lost" );
3128 										 pGlobalShell = GetCurrShell();
3129 										 bTableHack = sal_True;
3130 										 break;
3131 		case HACK_TABLEMODE_LOCKLINES  : pLines->LockLines( sal_True ); break;
3132 		case HACK_TABLEMODE_PAINTLINES : pLines->PaintLines( GetShell()->GetOut() );
3133 										 break;
3134 		case HACK_TABLEMODE_UNLOCKLINES: pLines->LockLines( sal_False ); break;
3135 		case HACK_TABLEMODE_EXIT       : pLines->PaintLines( GetCurrShell()->GetOut() );
3136 										 DELETEZ( pLines );
3137 										 pGlobalShell = 0;
3138 										 bTableHack = sal_False;
3139 										 break;
3140 	}
3141 }
3142 
3143 #endif
3144 
3145 
3146 /*************************************************************************
3147 |*
3148 |*	SwLayoutFrm::Paint()
3149 |*
3150 |*	Ersterstellung		MA 19. May. 92
3151 |*	Letzte Aenderung	MA 19. Apr. 95
3152 |*
3153 |*************************************************************************/
3154 
3155 void MA_FASTCALL lcl_EmergencyFormatFtnCont( SwFtnContFrm *pCont )
3156 {
3157 	//Es kann sein, dass der Cont vernichtet wird.
3158 	SwCntntFrm *pCnt = pCont->ContainsCntnt();
3159 	while ( pCnt && pCnt->IsInFtn() )
3160 	{
3161 		pCnt->Calc();
3162 		pCnt = pCnt->GetNextCntntFrm();
3163 	}
3164 }
3165 
3166 class SwShortCut
3167 {
3168     SwRectDist fnCheck;
3169     long nLimit;
3170 public:
3171     SwShortCut( const SwFrm& rFrm, const SwRect& rRect );
3172     sal_Bool Stop( const SwRect& rRect ) const
3173         { return (rRect.*fnCheck)( nLimit ) > 0; }
3174 };
3175 
3176 SwShortCut::SwShortCut( const SwFrm& rFrm, const SwRect& rRect )
3177 {
3178     sal_Bool bVert = rFrm.IsVertical();
3179     sal_Bool bR2L = rFrm.IsRightToLeft();
3180     if( rFrm.IsNeighbourFrm() && bVert == bR2L )
3181     {
3182         if( bVert )
3183         {
3184             fnCheck = &SwRect::GetBottomDistance;
3185             nLimit = rRect.Top();
3186         }
3187         else
3188         {
3189             fnCheck = &SwRect::GetLeftDistance;
3190             nLimit = rRect.Left() + rRect.Width();
3191         }
3192     }
3193     else if( bVert == rFrm.IsNeighbourFrm() )
3194     {
3195         fnCheck = &SwRect::GetTopDistance;
3196         nLimit = rRect.Top() + rRect.Height();
3197     }
3198     else
3199     {
3200         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
3201         if ( rFrm.IsVertLR() )
3202 	    {
3203            	fnCheck = &SwRect::GetLeftDistance;
3204            	nLimit = rRect.Right();
3205         }
3206         else
3207         {
3208         	fnCheck = &SwRect::GetRightDistance;
3209         	nLimit = rRect.Left();
3210         }
3211     }
3212 }
3213 
3214 void SwLayoutFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
3215 {
3216     ViewShell *pSh = getRootFrm()->GetCurrShell();
3217 
3218     // --> FME 2004-06-24 #i16816# tagged pdf support
3219     Frm_Info aFrmInfo( *this );
3220     SwTaggedPDFHelper aTaggedPDFHelper( 0, &aFrmInfo, 0, *pSh->GetOut() );
3221     // <--
3222 
3223 	const SwFrm *pFrm = Lower();
3224 	if ( !pFrm )
3225 		return;
3226 
3227     SwShortCut aShortCut( *pFrm, rRect );
3228 	sal_Bool bCnt;
3229 	if ( sal_True == (bCnt = pFrm->IsCntntFrm()) )
3230 		pFrm->Calc();
3231 
3232 	if ( pFrm->IsFtnContFrm() )
3233     {
3234         ::lcl_EmergencyFormatFtnCont( (SwFtnContFrm*)pFrm );
3235 		pFrm = Lower();
3236 	}
3237 
3238 	const SwPageFrm *pPage = 0;
3239 	const sal_Bool bWin   = pGlobalShell->GetWin() ? sal_True : sal_False;
3240 
3241 	while ( IsAnLower( pFrm ) )
3242 	{
3243         SwRect aPaintRect( pFrm->PaintArea() );
3244         if( aShortCut.Stop( aPaintRect ) )
3245 			break;
3246 		if ( bCnt && pProgress )
3247 			pProgress->Reschedule();
3248 
3249 		//Wenn ein Frm es explizit will muss retouchiert werden.
3250 		//Erst die Retouche, denn selbige koennte die aligned'en Raender
3251 		//plaetten.
3252 		if ( pFrm->IsRetouche() )
3253 		{
3254 			if ( pFrm->IsRetoucheFrm() && bWin && !pFrm->GetNext() )
3255 			{	if ( !pPage )
3256 					pPage = FindPageFrm();
3257                pFrm->Retouche( pPage, rRect );
3258 			}
3259 			pFrm->ResetRetouche();
3260 		}
3261 
3262         if ( rRect.IsOver( aPaintRect ) )
3263 		{
3264 			if ( bCnt && pFrm->IsCompletePaint() &&
3265 				 !rRect.IsInside( aPaintRect ) && GetpApp()->AnyInput( INPUT_KEYBOARD ) )
3266 			{
3267 				//fix(8104): Es kann vorkommen, dass die Verarbeitung nicht
3268 				//vollstaendig war, aber trotzdem Teile des Absatzes gepaintet
3269 				//werden. In der Folge werden dann evtl. wiederum andere Teile
3270 				//des Absatzes garnicht mehr gepaintet. Einziger Ausweg scheint
3271 				//hier ein Invalidieren der Windows zu sein.
3272 				//Um es nicht alzu Heftig werden zu lassen versuche ich hier
3273 				//das Rechteck zu begrenzen indem der gewuenschte Teil gepaintet
3274 				//und nur die uebrigen Absatzanteile invalidiert werden.
3275 				if ( aPaintRect.Left()	== rRect.Left() &&
3276 					 aPaintRect.Right() == rRect.Right() )
3277 				{
3278 					aPaintRect.Bottom( rRect.Top() - 1 );
3279 					if ( aPaintRect.Height() > 0 )
3280 						pGlobalShell->InvalidateWindows(aPaintRect);
3281 					aPaintRect.Top( rRect.Bottom() + 1 );
3282 					aPaintRect.Bottom( pFrm->Frm().Bottom() );
3283 					if ( aPaintRect.Height() > 0 )
3284 						pGlobalShell->InvalidateWindows(aPaintRect);
3285 					aPaintRect.Top( pFrm->Frm().Top() );
3286 					aPaintRect.Bottom( pFrm->Frm().Bottom() );
3287 				}
3288 				else
3289 				{
3290 					pGlobalShell->InvalidateWindows( aPaintRect );
3291 					pFrm = pFrm->GetNext();
3292 					if ( pFrm && (sal_True == (bCnt = pFrm->IsCntntFrm())) )
3293 						pFrm->Calc();
3294 					continue;
3295 				}
3296 			}
3297 			pFrm->ResetCompletePaint();
3298 			aPaintRect._Intersection( rRect );
3299 
3300             pFrm->Paint( aPaintRect );
3301 
3302             if ( Lower() && Lower()->IsColumnFrm() )
3303 			{
3304 				//Ggf. die Spaltentrennlinien malen. Fuer den Seitenbody ist
3305 				//nicht der Upper sondern die Seite Zustaendig.
3306 				const SwFrmFmt *pFmt = GetUpper() && GetUpper()->IsPageFrm()
3307 											? GetUpper()->GetFmt()
3308 											: GetFmt();
3309 				const SwFmtCol &rCol = pFmt->GetCol();
3310 				if ( rCol.GetLineAdj() != COLADJ_NONE )
3311 				{
3312 					if ( !pPage )
3313 						pPage = pFrm->FindPageFrm();
3314 
3315                     PaintColLines( aPaintRect, rCol, pPage );
3316                 }
3317 			}
3318         }
3319 		if ( !bCnt && pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm() )
3320 			::lcl_EmergencyFormatFtnCont( (SwFtnContFrm*)pFrm->GetNext() );
3321 
3322 		pFrm = pFrm->GetNext();
3323 		if ( pFrm && (sal_True == (bCnt = pFrm->IsCntntFrm())) )
3324 			pFrm->Calc();
3325 	}
3326 }
3327 
3328 
3329 /** FlyFrm::IsBackgroundTransparent - for feature #99657#
3330 
3331     OD 12.08.2002
3332     determines, if background of fly frame has to be drawn transparent
3333     declaration found in /core/inc/flyfrm.cxx
3334     OD 08.10.2002 #103898# - If the background of the fly frame itself is not
3335     transparent and the background is inherited from its parent/grandparent,
3336     the background brush, used for drawing, has to be investigated for transparency.
3337 
3338     @author OD
3339 
3340     @return true, if background is transparent drawn.
3341 */
3342 sal_Bool SwFlyFrm::IsBackgroundTransparent() const
3343 {
3344     sal_Bool bBackgroundTransparent = GetFmt()->IsBackgroundTransparent();
3345     if ( !bBackgroundTransparent &&
3346          static_cast<const SwFlyFrmFmt*>(GetFmt())->IsBackgroundBrushInherited() )
3347     {
3348         const SvxBrushItem* pBackgrdBrush = 0;
3349         const Color* pSectionTOXColor = 0;
3350         SwRect aDummyRect;
3351         if ( GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false) )
3352         {
3353             if ( pSectionTOXColor &&
3354                  (pSectionTOXColor->GetTransparency() != 0) &&
3355                  (pSectionTOXColor->GetColor() != COL_TRANSPARENT) )
3356             {
3357                 bBackgroundTransparent = sal_True;
3358             }
3359             else if ( pBackgrdBrush )
3360             {
3361                 if ( (pBackgrdBrush->GetColor().GetTransparency() != 0) &&
3362                      (pBackgrdBrush->GetColor() != COL_TRANSPARENT) )
3363                 {
3364                     bBackgroundTransparent = sal_True;
3365                 }
3366                 else
3367                 {
3368                     const GraphicObject *pTmpGrf =
3369                             static_cast<const GraphicObject*>(pBackgrdBrush->GetGraphicObject());
3370                     if ( (pTmpGrf) &&
3371                          (pTmpGrf->GetAttr().GetTransparency() != 0)
3372                        )
3373                     {
3374                         bBackgroundTransparent = sal_True;
3375                     }
3376                 }
3377             }
3378         }
3379     }
3380 
3381     return bBackgroundTransparent;
3382 };
3383 
3384 /** FlyFrm::IsShadowTransparent - for feature #99657#
3385 
3386     OD 13.08.2002
3387     determine, if shadow color of fly frame has to be drawn transparent
3388     declaration found in /core/inc/flyfrm.cxx
3389 
3390     @author OD
3391 
3392     @return true, if shadow color is transparent.
3393 */
3394 sal_Bool SwFlyFrm::IsShadowTransparent() const
3395 {
3396     return GetFmt()->IsShadowTransparent();
3397 };
3398 
3399 /*************************************************************************
3400 |*
3401 |*	SwFlyFrm::IsPaint()
3402 |*
3403 |*	Ersterstellung		MA 16. Jan. 97
3404 |*	Letzte Aenderung	MA 16. Jan. 97
3405 |*
3406 |*************************************************************************/
3407 
3408 sal_Bool SwFlyFrm::IsPaint( SdrObject *pObj, const ViewShell *pSh )
3409 {
3410 	SdrObjUserCall *pUserCall;
3411 
3412 	if ( 0 == ( pUserCall = GetUserCall(pObj) ) )
3413 		return sal_True;
3414 
3415 	//Attributabhaengig nicht fuer Drucker oder PreView painten
3416 	sal_Bool bPaint =  pFlyOnlyDraw ||
3417 					   ((SwContact*)pUserCall)->GetFmt()->GetPrint().GetValue();
3418 	if ( !bPaint )
3419 		bPaint = pSh->GetWin() && !pSh->IsPreView();
3420 
3421 	if ( bPaint )
3422 	{
3423 		//Das Paint kann evtl. von von uebergeordneten Flys verhindert werden.
3424         SwFrm *pAnch = 0;
3425 		if ( pObj->ISA(SwVirtFlyDrawObj) )
3426 		{
3427 			SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
3428 			if ( pFlyOnlyDraw && pFlyOnlyDraw == pFly )
3429 				return sal_True;
3430 
3431 			//Die Anzeige eines Zwischenstadiums vermeiden, Flys die nicht mit
3432 			//der Seite auf der sie verankert sind ueberlappen werden auch
3433 			//nicht gepaintet.
3434 			//HACK: Ausnahme: Drucken von Rahmen in Tabellen, diese koennen
3435 			//bei uebergrossen Tabellen (HTML) schon mal auserhalb der Seite
3436 			//stehen.
3437 			SwPageFrm *pPage = pFly->FindPageFrm();
3438 			if ( pPage )
3439 			{
3440 				if ( pPage->Frm().IsOver( pFly->Frm() ) )
3441                     pAnch = pFly->AnchorFrm();
3442 				else if ( bTableHack &&
3443                           pFly->Frm().Top() >= pFly->GetAnchorFrm()->Frm().Top() &&
3444                           pFly->Frm().Top() < pFly->GetAnchorFrm()->Frm().Bottom() &&
3445                           long(pSh->GetOut()) ==
3446                           long(pSh->getIDocumentDeviceAccess()->getPrinter( false ) ) )
3447 				{
3448                     pAnch = pFly->AnchorFrm();
3449 				}
3450 			}
3451 
3452 		}
3453 		else
3454 		{
3455             // OD 13.10.2003 #i19919# - consider 'virtual' drawing objects
3456             // OD 2004-03-29 #i26791#
3457             pAnch = ((SwDrawContact*)pUserCall)->GetAnchorFrm( pObj );
3458 			if ( pAnch )
3459 			{
3460 				if ( !pAnch->GetValidPosFlag() )
3461 					pAnch = 0;
3462                 else if ( long(pSh->GetOut()) == long(pSh->getIDocumentDeviceAccess()->getPrinter( false )))
3463 				{
3464 					//HACK: fuer das Drucken muessen wir ein paar Objekte
3465 					//weglassen, da diese sonst doppelt gedruckt werden.
3466 					//Die Objekte sollen gedruckt werden, wenn der TableHack
3467 					//gerade greift. In der Folge duerfen sie nicht gedruckt werden
3468 					//wenn sie mit der Seite dran sind, ueber der sie von der
3469 					//Position her gerade schweben.
3470                     const SwPageFrm *pPage = pAnch->FindPageFrm();
3471 					if ( !bTableHack &&
3472 						 !pPage->Frm().IsOver( pObj->GetCurrentBoundRect() ) )
3473 						pAnch = 0;
3474 				}
3475 			}
3476             else
3477             {
3478                 // OD 02.07.2003 #108784# - debug assert
3479                 if ( !pObj->ISA(SdrObjGroup) )
3480                 {
3481                     ASSERT( false, "<SwFlyFrm::IsPaint(..)> - paint of drawing object without anchor frame!?" );
3482                 }
3483             }
3484 		}
3485 		if ( pAnch )
3486 		{
3487 			if ( pAnch->IsInFly() )
3488 				bPaint = SwFlyFrm::IsPaint( pAnch->FindFlyFrm()->GetVirtDrawObj(),
3489 											pSh );
3490 			else if ( pFlyOnlyDraw )
3491 				bPaint = sal_False;
3492 		}
3493 		else
3494 			bPaint = sal_False;
3495 	}
3496 	return bPaint;
3497 }
3498 
3499 /*************************************************************************
3500 |*  SwCellFrm::Paint( const SwRect& ) const
3501 |*************************************************************************/
3502 void SwCellFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
3503 {
3504     if ( GetLayoutRowSpan() >= 1 )
3505         SwLayoutFrm::Paint( rRect );
3506 }
3507 
3508 /*************************************************************************
3509 |*
3510 |*	SwFlyFrm::Paint()
3511 |*
3512 |*	Ersterstellung		MA ??
3513 |*	Letzte Aenderung	MA 16. Jan. 97
3514 |*
3515 |*************************************************************************/
3516 
3517 //Weiter unten definiert
3518 void MA_FASTCALL lcl_PaintLowerBorders( const SwLayoutFrm *pLay,
3519 							   const SwRect &rRect, const SwPageFrm *pPage );
3520 
3521 void SwFlyFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
3522 {
3523     //wegen der Ueberlappung von Rahmen und Zeichenobjekten muessen die
3524 	//Flys ihre Umrandung (und die der Innenliegenden) direkt ausgeben.
3525 	//z.B. #33066#
3526 	pLines->LockLines(sal_True);
3527 
3528     SwRect aRect( rRect );
3529 	aRect._Intersection( Frm() );
3530 
3531     OutputDevice* pOut = pGlobalShell->GetOut();
3532 	pOut->Push( PUSH_CLIPREGION );
3533 	pOut->SetClipRegion();
3534     const SwPageFrm* pPage = FindPageFrm();
3535 
3536 	const SwNoTxtFrm *pNoTxt = Lower() && Lower()->IsNoTxtFrm()
3537 												? (SwNoTxtFrm*)Lower() : 0;
3538 
3539     bool bIsChart = false; //#i102950# don't paint additional borders for charts
3540     //check whether we have a chart
3541     if(pNoTxt)
3542     {
3543         const SwNoTxtNode* pNoTNd = dynamic_cast<const SwNoTxtNode*>(pNoTxt->GetNode());
3544         if( pNoTNd )
3545         {
3546             SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTNd->GetOLENode());
3547             if( pOLENd && ChartPrettyPainter::IsChart( pOLENd->GetOLEObj().GetObject() ) )
3548                 bIsChart = true;
3549         }
3550     }
3551 
3552 	{
3553         bool bContour = GetFmt()->GetSurround().IsContour();
3554 		PolyPolygon aPoly;
3555 		if ( bContour )
3556         {
3557             // OD 16.04.2003 #i13147# - add 2nd parameter with value <sal_True>
3558             // to indicate that method is called for paint in order to avoid
3559             // load of the intrinsic graphic.
3560             bContour = GetContour( aPoly, sal_True );
3561         }
3562 
3563         // --> OD 2005-06-08 #i47804# - distinguish complete background paint
3564         // and margin paint.
3565         // paint complete background for Writer text fly frames
3566         bool bPaintCompleteBack( !pNoTxt );
3567         // <--
3568         // paint complete background for transparent graphic and contour,
3569         // if own background color exists.
3570         const bool bIsGraphicTransparent = pNoTxt ? pNoTxt->IsTransparent() : false;
3571         if ( !bPaintCompleteBack &&
3572              ( bIsGraphicTransparent|| bContour ) )
3573 		{
3574 			const SvxBrushItem &rBack = GetFmt()->GetBackground();
3575             // OD 07.08.2002 #99657# #GetTransChg#
3576             //     to determine, if background has to be painted, by checking, if
3577             //     background color is not COL_TRANSPARENT ("no fill"/"auto fill")
3578             //     or a background graphic exists.
3579             bPaintCompleteBack = !(rBack.GetColor() == COL_TRANSPARENT) ||
3580                                  rBack.GetGraphicPos() != GPOS_NONE;
3581 		}
3582         // paint of margin needed.
3583         const bool bPaintMarginOnly( !bPaintCompleteBack &&
3584                                      Prt().SSize() != Frm().SSize() );
3585 
3586         // --> OD 2005-06-08 #i47804# - paint background of parent fly frame
3587         // for transparent graphics in layer Hell, if parent fly frame isn't
3588         // in layer Hell. It's only painted the intersection between the
3589         // parent fly frame area and the paint area <aRect>
3590         const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
3591 
3592         if ( bIsGraphicTransparent &&
3593             GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() &&
3594             GetAnchorFrm()->FindFlyFrm() )
3595         {
3596             const SwFlyFrm* pParentFlyFrm = GetAnchorFrm()->FindFlyFrm();
3597             if ( pParentFlyFrm->GetDrawObj()->GetLayer() !=
3598                                             pIDDMA->GetHellId() )
3599             {
3600                 SwFlyFrm* pOldRet = pRetoucheFly2;
3601                 pRetoucheFly2 = const_cast<SwFlyFrm*>(this);
3602 
3603                 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pParentFlyFrm );
3604                 const SwBorderAttrs &rAttrs = *aAccess.Get();
3605                 SwRect aPaintRect( aRect );
3606                 aPaintRect._Intersection( pParentFlyFrm->Frm() );
3607                 pParentFlyFrm->PaintBackground( aPaintRect, pPage, rAttrs, sal_False, sal_False );
3608 
3609                 pRetoucheFly2 = pOldRet;
3610             }
3611         }
3612 
3613         if ( bPaintCompleteBack || bPaintMarginOnly )
3614 		{
3615 			//#24926# JP 01.02.96, PaintBaBo in teilen hier, damit PaintBorder
3616 			//das orig. Rect bekommt, aber PaintBackground das begrenzte.
3617 
3618             // OD 2004-04-23 #116347#
3619             pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
3620             pOut->SetLineColor();
3621 
3622 			pPage = FindPageFrm();
3623 
3624 			SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
3625 			const SwBorderAttrs &rAttrs = *aAccess.Get();
3626 
3627             // OD 06.08.2002 #99657# - paint border before painting background
3628             // paint border
3629             {
3630                 SwRect aTmp( rRect );
3631                 PaintBorder( aTmp, pPage, rAttrs );
3632             }
3633 
3634             // paint background
3635             {
3636                 SwRegionRects aRegion( aRect );
3637                 // --> OD 2007-12-13 #i80822#
3638                 // suppress painting of background in printing area for
3639                 // non-transparent graphics.
3640 //                if ( bPaintMarginOnly )
3641                 if ( bPaintMarginOnly ||
3642                      ( pNoTxt && !bIsGraphicTransparent ) )
3643                 // <--
3644                 {
3645                     //Was wir eigentlich Painten wollen ist der schmale Streifen
3646                     //zwischen PrtArea und aeusserer Umrandung.
3647                     SwRect aTmp( Prt() ); aTmp += Frm().Pos();
3648                     aRegion -= aTmp;
3649                 }
3650                 if ( bContour )
3651                 {
3652                     pOut->Push();
3653                     // --> OD 2007-12-13 #i80822#
3654                     // apply clip region under the same conditions, which are
3655                     // used in <SwNoTxtFrm::Paint(..)> to set the clip region
3656                     // for painting the graphic/OLE. Thus, the clip region is
3657                     // also applied for the PDF export.
3658 //                    if ( !pOut->GetConnectMetaFile() || pOut->GetOutDevType() == OUTDEV_PRINTER )
3659                 	ViewShell *pSh = getRootFrm()->GetCurrShell();
3660                     if ( !pOut->GetConnectMetaFile() || !pSh || !pSh->GetWin() )
3661                     // <--
3662                     {
3663                         pOut->SetClipRegion( aPoly );
3664                     }
3665                     for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
3666                         PaintBackground( aRegion[i], pPage, rAttrs, sal_False, sal_True );
3667                     pOut->Pop();
3668                 }
3669                 else
3670                     for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
3671                         PaintBackground( aRegion[i], pPage, rAttrs, sal_False, sal_True );
3672             }
3673 
3674 			pOut->Pop();
3675 		}
3676 	}
3677 
3678     // OD 19.12.2002 #106318# - fly frame will paint it's subsidiary lines and
3679     // the subsidiary lines of its lowers on its own, due to overlapping with
3680     // other fly frames or other objects.
3681     if( pGlobalShell->GetWin()
3682         && !bIsChart ) //#i102950# don't paint additional borders for charts
3683     {
3684         bool bSubsLineRectsCreated;
3685         if ( pSubsLines )
3686         {
3687             // Lock already existing subsidiary lines
3688             pSubsLines->LockLines( sal_True );
3689             bSubsLineRectsCreated = false;
3690         }
3691         else
3692         {
3693             // create new subsidiardy lines
3694             pSubsLines = new SwSubsRects;
3695             bSubsLineRectsCreated = true;
3696         }
3697 
3698         bool bSpecSubsLineRectsCreated;
3699         if ( pSpecSubsLines )
3700         {
3701             // Lock already existing special subsidiary lines
3702             pSpecSubsLines->LockLines( sal_True );
3703             bSpecSubsLineRectsCreated = false;
3704         }
3705         else
3706         {
3707             // create new special subsidiardy lines
3708             pSpecSubsLines = new SwSubsRects;
3709             bSpecSubsLineRectsCreated = true;
3710         }
3711         // Add subsidiary lines of fly frame and its lowers
3712         RefreshLaySubsidiary( pPage, aRect );
3713         // paint subsidiary lines of fly frame and its lowers
3714         pSpecSubsLines->PaintSubsidiary( pOut, NULL );
3715         pSubsLines->PaintSubsidiary( pOut, pLines );
3716         if ( !bSubsLineRectsCreated )
3717             // unlock subsidiary lines
3718             pSubsLines->LockLines( sal_False );
3719         else
3720             // delete created subsidiary lines container
3721             DELETEZ( pSubsLines );
3722 
3723         if ( !bSpecSubsLineRectsCreated )
3724             // unlock special subsidiary lines
3725             pSpecSubsLines->LockLines( sal_False );
3726         else
3727         {
3728             // delete created special subsidiary lines container
3729             DELETEZ( pSpecSubsLines );
3730         }
3731     }
3732 
3733     SwLayoutFrm::Paint( aRect );
3734 
3735     Validate();
3736 
3737     // OD 19.12.2002 #106318# - first paint lines added by fly frame paint
3738     // and then unlock other lines.
3739     pLines->PaintLines( pOut );
3740     pLines->LockLines( sal_False );
3741 
3742     pOut->Pop();
3743 
3744 	if ( pProgress && pNoTxt )
3745 		pProgress->Reschedule();
3746 }
3747 /*************************************************************************
3748 |*
3749 |*	  SwTabFrm::Paint()
3750 |*
3751 |*	  Ersterstellung	MA 11. May. 93
3752 |*	  Letzte Aenderung	MA 23. Mar. 95
3753 |*
3754 |*************************************************************************/
3755 
3756 void SwTabFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
3757 {
3758     if ( pGlobalShell->GetViewOptions()->IsTable() )
3759     {
3760         // --> collapsing borders FME 2005-05-27 #i29550#
3761         if ( IsCollapsingBorders() )
3762         {
3763             SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
3764             const SwBorderAttrs &rAttrs = *aAccess.Get();
3765 
3766             // paint shadow
3767             if ( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
3768             {
3769                 SwRect aRect;
3770                 ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_True );
3771                 PaintShadow( rRect, aRect, rAttrs );
3772             }
3773 
3774             // paint lines
3775             SwTabFrmPainter aHelper( *this );
3776             aHelper.PaintLines( *pGlobalShell->GetOut(), rRect );
3777         }
3778         // <-- collapsing
3779 
3780 		SwLayoutFrm::Paint( rRect );
3781     }
3782     // OD 10.01.2003 #i6467# - no light grey rectangle for page preview
3783     else if ( pGlobalShell->GetWin() && !pGlobalShell->IsPreView() )
3784 	{
3785         // OD 10.01.2003 #i6467# - intersect output rectangle with table frame
3786         SwRect aTabRect( Prt() );
3787         aTabRect.Pos() += Frm().Pos();
3788         SwRect aTabOutRect( rRect );
3789         aTabOutRect.Intersection( aTabRect );
3790         pGlobalShell->GetViewOptions()->
3791                 DrawRect( pGlobalShell->GetOut(), aTabOutRect, COL_LIGHTGRAY );
3792 	}
3793 	((SwTabFrm*)this)->ResetComplete();
3794 }
3795 
3796 /*************************************************************************
3797 |*
3798 |*	SwFrm::PaintShadow()
3799 |*
3800 |*	Beschreibung		Malt einen Schatten wenns das FrmFormat fordert.
3801 |* 		Der Schatten wird immer an den auesseren Rand des OutRect gemalt.
3802 |* 		Das OutRect wird ggf. so verkleinert, dass auf diesem das
3803 |* 		malen der Umrandung stattfinden kann.
3804 |*	Ersterstellung		MA 21. Dec. 92
3805 |*	Letzte Aenderung	MA 29. May. 97
3806 |*
3807 |*************************************************************************/
3808 /// OD 23.08.2002 #99657#
3809 ///     draw full shadow rectangle for frames with transparent drawn backgrounds.
3810 void SwFrm::PaintShadow( const SwRect& rRect, SwRect& rOutRect,
3811                          const SwBorderAttrs &rAttrs ) const
3812 {
3813 	const SvxShadowItem &rShadow = rAttrs.GetShadow();
3814 	const long nWidth  = ::lcl_AlignWidth ( rShadow.GetWidth() );
3815 	const long nHeight = ::lcl_AlignHeight( rShadow.GetWidth() );
3816 
3817 	SwRects aRegion( 2, 2 );
3818 	SwRect aOut( rOutRect );
3819 
3820 	const sal_Bool bCnt	   = IsCntntFrm();
3821     const sal_Bool bTop    = !bCnt || rAttrs.GetTopLine  ( *(this) ) ? sal_True : sal_False;
3822     const sal_Bool bBottom = !bCnt || rAttrs.GetBottomLine( *(this) ) ? sal_True : sal_False;
3823 
3824     SvxShadowLocation eLoc = rShadow.GetLocation();
3825 
3826     SWRECTFN( this )
3827     if( IsVertical() )
3828     {
3829         switch( eLoc )
3830         {
3831             case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT;  break;
3832             case SVX_SHADOW_TOPLEFT:     eLoc = SVX_SHADOW_TOPRIGHT;    break;
3833             case SVX_SHADOW_TOPRIGHT:    eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
3834             case SVX_SHADOW_BOTTOMLEFT:  eLoc = SVX_SHADOW_TOPLEFT;     break;
3835             default: break;
3836         }
3837     }
3838 
3839     /// OD 23.08.2002 #99657# - determine, if full shadow rectangle have to
3840     ///     be drawn or only two shadow rectangles beside the frame.
3841     ///     draw full shadow rectangle, if frame background is drawn transparent.
3842     ///     Status Quo:
3843     ///         SwLayoutFrm can have transparent drawn backgrounds. Thus,
3844     ///         "asked" their frame format.
3845     sal_Bool bDrawFullShadowRectangle =
3846             ( IsLayoutFrm() &&
3847               (static_cast<const SwLayoutFrm*>(this))->GetFmt()->IsBackgroundTransparent()
3848             );
3849     switch ( eLoc )
3850 	{
3851 		case SVX_SHADOW_BOTTOMRIGHT:
3852 			{
3853                 if ( bDrawFullShadowRectangle )
3854                 {
3855                     /// OD 06.08.2002 #99657# - draw full shadow rectangle
3856                     aOut.Top( aOut.Top() + nHeight );
3857                     aOut.Left( aOut.Left() + nWidth );
3858                     aRegion.Insert( aOut, aRegion.Count() );
3859                 }
3860                 else
3861                 {
3862                     aOut.Top ( aOut.Bottom() - nHeight );
3863                     aOut.Left( aOut.Left()   + nWidth );
3864                     if ( bBottom )
3865                         aRegion.Insert( aOut, aRegion.Count() );
3866                     aOut.Left( aOut.Right()   - nWidth );
3867                     aOut.Top ( rOutRect.Top() + nHeight );
3868                     if ( bBottom )
3869                         aOut.Bottom( aOut.Bottom() - nHeight );
3870                     if ( bCnt && (!bTop || !bBottom) )
3871                         ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
3872                     aRegion.Insert( aOut, aRegion.Count() );
3873                 }
3874 
3875 				rOutRect.Right ( rOutRect.Right() - nWidth );
3876 				rOutRect.Bottom( rOutRect.Bottom()- nHeight );
3877 			}
3878 			break;
3879 		case SVX_SHADOW_TOPLEFT:
3880 			{
3881                 if ( bDrawFullShadowRectangle )
3882                 {
3883                     /// OD 06.08.2002 #99657# - draw full shadow rectangle
3884                     aOut.Bottom( aOut.Bottom() - nHeight );
3885                     aOut.Right( aOut.Right() - nWidth );
3886                     aRegion.Insert( aOut, aRegion.Count() );
3887                 }
3888                 else
3889                 {
3890                     aOut.Bottom( aOut.Top()   + nHeight );
3891                     aOut.Right ( aOut.Right() - nWidth );
3892                     if ( bTop )
3893                         aRegion.Insert( aOut, aRegion.Count() );
3894                     aOut.Right ( aOut.Left() + nWidth );
3895                     aOut.Bottom( rOutRect.Bottom() - nHeight );
3896                     if ( bTop )
3897                         aOut.Top( aOut.Top() + nHeight );
3898                     if ( bCnt && (!bBottom || !bTop) )
3899                         ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
3900                     aRegion.Insert( aOut, aRegion.Count() );
3901                 }
3902 
3903 				rOutRect.Left( rOutRect.Left() + nWidth );
3904 				rOutRect.Top(  rOutRect.Top() + nHeight );
3905 			}
3906 			break;
3907 		case SVX_SHADOW_TOPRIGHT:
3908 			{
3909                 if ( bDrawFullShadowRectangle )
3910                 {
3911                     /// OD 06.08.2002 #99657# - draw full shadow rectangle
3912                     aOut.Bottom( aOut.Bottom() - nHeight);
3913                     aOut.Left( aOut.Left() + nWidth );
3914                     aRegion.Insert( aOut, aRegion.Count() );
3915                 }
3916                 else
3917                 {
3918                     aOut.Bottom( aOut.Top() + nHeight );
3919                     aOut.Left (  aOut.Left()+ nWidth );
3920                     if ( bTop )
3921                         aRegion.Insert( aOut, aRegion.Count() );
3922                     aOut.Left  ( aOut.Right() - nWidth );
3923                     aOut.Bottom( rOutRect.Bottom() - nHeight );
3924                     if ( bTop )
3925                         aOut.Top( aOut.Top() + nHeight );
3926                     if ( bCnt && (!bBottom || bTop) )
3927                         ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
3928                     aRegion.Insert( aOut, aRegion.Count() );
3929                 }
3930 
3931                 rOutRect.Right( rOutRect.Right() - nWidth );
3932 				rOutRect.Top( rOutRect.Top() + nHeight );
3933 			}
3934 			break;
3935 		case SVX_SHADOW_BOTTOMLEFT:
3936 			{
3937                 if ( bDrawFullShadowRectangle )
3938                 {
3939                     /// OD 06.08.2002 #99657# - draw full shadow rectangle
3940                     aOut.Top( aOut.Top() + nHeight );
3941                     aOut.Right( aOut.Right() - nWidth );
3942                     aRegion.Insert( aOut, aRegion.Count() );
3943                 }
3944                 else
3945                 {
3946                     aOut.Top  ( aOut.Bottom()- nHeight );
3947                     aOut.Right( aOut.Right() - nWidth );
3948                     if ( bBottom )
3949                         aRegion.Insert( aOut, aRegion.Count() );
3950                     aOut.Right( aOut.Left() + nWidth );
3951                     aOut.Top( rOutRect.Top() + nHeight );
3952                     if ( bBottom )
3953                         aOut.Bottom( aOut.Bottom() - nHeight );
3954                     if ( bCnt && (!bTop || !bBottom) )
3955                         ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
3956                     aRegion.Insert( aOut, aRegion.Count() );
3957                 }
3958 
3959 				rOutRect.Left( rOutRect.Left() + nWidth );
3960 				rOutRect.Bottom( rOutRect.Bottom() - nHeight );
3961 			}
3962 			break;
3963         default:
3964             ASSERT( !this, "new ShadowLocation() ?" )
3965             break;
3966     }
3967 
3968 	OutputDevice *pOut = pGlobalShell->GetOut();
3969 
3970     sal_uLong nOldDrawMode = pOut->GetDrawMode();
3971     Color aShadowColor( rShadow.GetColor() );
3972     if( aRegion.Count() && pGlobalShell->GetWin() &&
3973         Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
3974     {
3975         // Is heigh contrast mode, the output device has already set the
3976         // DRAWMODE_SETTINGSFILL flag. This causes the SetFillColor function
3977         // to ignore the setting of a new color. Therefore we have to reset
3978         // the drawing mode
3979         pOut->SetDrawMode( 0 );
3980         aShadowColor = SwViewOption::GetFontColor();
3981     }
3982 
3983     if ( pOut->GetFillColor() != aShadowColor )
3984         pOut->SetFillColor( aShadowColor );
3985 
3986     pOut->SetDrawMode( nOldDrawMode );
3987 
3988 	for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
3989 	{
3990 		SwRect &rOut = aRegion[i];
3991 		aOut = rOut;
3992         // OD 30.09.2002 #103636# - no SwAlign of shadow rectangle
3993         // no alignment necessary, because (1) <rRect> is already aligned
3994         // and because (2) paint of border and background will occur later.
3995         // Thus, (1) assures that no conflicts with neighbour object will occure
3996         // and (2) assures that border and background is not affected by the
3997         // shadow paint.
3998         /*
3999         ::SwAlignRect( aOut, pGlobalShell );
4000         */
4001 		if ( rRect.IsOver( aOut ) && aOut.Height() > 0 && aOut.Width() > 0 )
4002 		{
4003 			aOut._Intersection( rRect );
4004 			pOut->DrawRect( aOut.SVRect() );
4005 		}
4006 	}
4007 }
4008 
4009 /*************************************************************************
4010 |*
4011 |*	SwFrm::PaintBorderLine()
4012 |*
4013 |*	Ersterstellung		MA 22. Dec. 92
4014 |*	Letzte Aenderung	MA 22. Jan. 95
4015 |*
4016 |*************************************************************************/
4017 
4018 void SwFrm::PaintBorderLine( const SwRect& rRect,
4019 							 const SwRect& rOutRect,
4020 							 const SwPageFrm *pPage,
4021 							 const Color *pColor ) const
4022 {
4023 	if ( !rOutRect.IsOver( rRect ) )
4024 		return;
4025 
4026 	SwRect aOut( rOutRect );
4027 	aOut._Intersection( rRect );
4028 
4029 	const SwTabFrm *pTab = IsCellFrm() ? FindTabFrm() : 0;
4030     sal_uInt8 nSubCol = ( IsCellFrm() || IsRowFrm() ) ? SUBCOL_TAB :
4031                    ( IsInSct() ? SUBCOL_SECT :
4032                    ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
4033     if( pColor && pGlobalShell->GetWin() &&
4034         Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
4035     {
4036         pColor = &SwViewOption::GetFontColor();
4037     }
4038 
4039 	if ( pPage->GetSortedObjs() )
4040 	{
4041 		SwRegionRects aRegion( aOut, 4, 1 );
4042 		::lcl_SubtractFlys( this, pPage, aOut, aRegion );
4043 		for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
4044             pLines->AddLineRect( aRegion[i], pColor, pTab, nSubCol );
4045 	}
4046 	else
4047         pLines->AddLineRect( aOut, pColor, pTab, nSubCol );
4048 }
4049 
4050 /*************************************************************************
4051 |*
4052 |*	SwFrm::PaintBorderLines()
4053 |*
4054 |*	Beschreibung		Nur alle Linien einfach oder alle Linien doppelt!!!!
4055 |*	Ersterstellung		MA 22. Dec. 92
4056 |*	Letzte Aenderung	MA 22. Mar. 95
4057 |*
4058 |*************************************************************************/
4059 
4060 // OD 29.04.2003 #107169# - method called for left and right border rectangles.
4061 // For a printer output device perform adjustment for non-overlapping top and
4062 // bottom border rectangles. Thus, add parameter <_bPrtOutputDev> to indicate
4063 // printer output device.
4064 // NOTE: For printer output device left/right border rectangle <_iorRect>
4065 //       has to be already non-overlapping the outer top/bottom border rectangle.
4066 void MA_FASTCALL lcl_SubTopBottom( SwRect&              _iorRect,
4067                                    const SvxBoxItem&    _rBox,
4068                                    const SwBorderAttrs& _rAttrs,
4069                                    const SwFrm&         _rFrm,
4070                                    const SwRectFn&      _rRectFn,
4071                                    const sal_Bool       _bPrtOutputDev )
4072 {
4073     const sal_Bool bCnt = _rFrm.IsCntntFrm();
4074     if ( _rBox.GetTop() && _rBox.GetTop()->GetInWidth() &&
4075          ( !bCnt || _rAttrs.GetTopLine( _rFrm ) )
4076        )
4077 	{
4078         // substract distance between outer and inner line.
4079         SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetTop()->GetDistance() );
4080         // OD 19.05.2003 #109667# - non-overlapping border rectangles:
4081         // adjust x-/y-position, if inner top line is a hair line (width = 1)
4082         sal_Bool bIsInnerTopLineHairline = sal_False;
4083         if ( !_bPrtOutputDev )
4084         {
4085             // additionally substract width of top outer line
4086             // --> left/right inner/outer line doesn't overlap top outer line.
4087             nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetOutWidth() );
4088         }
4089         else
4090         {
4091             // OD 29.04.2003 #107169# - additionally substract width of top inner line
4092             // --> left/right inner/outer line doesn't overlap top inner line.
4093             nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetInWidth() );
4094             bIsInnerTopLineHairline = _rBox.GetTop()->GetInWidth() == 1;
4095         }
4096         (_iorRect.*_rRectFn->fnSubTop)( -nDist );
4097         // OD 19.05.2003 #109667# - adjust calculated border top, if inner top line
4098         // is a hair line
4099         if ( bIsInnerTopLineHairline )
4100         {
4101             if ( _rFrm.IsVertical() )
4102             {
4103                 // right of border rectangle has to be checked and adjusted
4104                 Point aCompPt( _iorRect.Right(), 0 );
4105                 Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
4106                 lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4107                                           aRefPt, aCompPt,
4108                                           sal_True, -1 );
4109                 _iorRect.Right( aCompPt.X() );
4110             }
4111             else
4112             {
4113                 // top of border rectangle has to be checked and adjusted
4114                 Point aCompPt( 0, _iorRect.Top() );
4115                 Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
4116                 lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4117                                           aRefPt, aCompPt,
4118                                           sal_False, +1 );
4119                 _iorRect.Top( aCompPt.Y() );
4120             }
4121         }
4122 	}
4123 
4124     if ( _rBox.GetBottom() && _rBox.GetBottom()->GetInWidth() &&
4125          ( !bCnt || _rAttrs.GetBottomLine( _rFrm ) )
4126        )
4127 	{
4128         // substract distance between outer and inner line.
4129         SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetBottom()->GetDistance() );
4130         // OD 19.05.2003 #109667# - non-overlapping border rectangles:
4131         // adjust x-/y-position, if inner bottom line is a hair line (width = 1)
4132         sal_Bool bIsInnerBottomLineHairline = sal_False;
4133         if ( !_bPrtOutputDev )
4134         {
4135             // additionally substract width of bottom outer line
4136             // --> left/right inner/outer line doesn't overlap bottom outer line.
4137             nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetOutWidth() );
4138         }
4139         else
4140         {
4141             // OD 29.04.2003 #107169# - additionally substract width of bottom inner line
4142             // --> left/right inner/outer line doesn't overlap bottom inner line.
4143             nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetInWidth() );
4144             bIsInnerBottomLineHairline = _rBox.GetBottom()->GetInWidth() == 1;
4145         }
4146         (_iorRect.*_rRectFn->fnAddBottom)( -nDist );
4147         // OD 19.05.2003 #109667# - adjust calculated border bottom, if inner
4148         // bottom line is a hair line.
4149         if ( bIsInnerBottomLineHairline )
4150         {
4151             if ( _rFrm.IsVertical() )
4152             {
4153                 // left of border rectangle has to be checked and adjusted
4154                 Point aCompPt( _iorRect.Left(), 0 );
4155                 Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
4156                 lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4157                                           aRefPt, aCompPt,
4158                                           sal_True, +1 );
4159                 _iorRect.Left( aCompPt.X() );
4160             }
4161             else
4162             {
4163                 // bottom of border rectangle has to be checked and adjusted
4164                 Point aCompPt( 0, _iorRect.Bottom() );
4165                 Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
4166                 lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4167                                           aRefPt, aCompPt,
4168                                           sal_False, -1 );
4169                 _iorRect.Bottom( aCompPt.Y() );
4170             }
4171         }
4172 	}
4173 }
4174 
4175 // method called for top and bottom border rectangles.
4176 void MA_FASTCALL lcl_SubLeftRight( SwRect&           rRect,
4177                                    const SvxBoxItem& rBox,
4178                                    const SwRectFn&   rRectFn )
4179 {
4180 	if ( rBox.GetLeft() && rBox.GetLeft()->GetInWidth() )
4181 	{
4182         const long nDist = ::lcl_MinWidthDist( rBox.GetLeft()->GetDistance() )
4183                            + ::lcl_AlignWidth( rBox.GetLeft()->GetOutWidth() );
4184         (rRect.*rRectFn->fnSubLeft)( -nDist );
4185 	}
4186 
4187 	if ( rBox.GetRight() && rBox.GetRight()->GetInWidth() )
4188 	{
4189         const long nDist = ::lcl_MinWidthDist( rBox.GetRight()->GetDistance() )
4190                            + ::lcl_AlignWidth( rBox.GetRight()->GetOutWidth() );
4191         (rRect.*rRectFn->fnAddRight)( -nDist );
4192 	}
4193 }
4194 
4195 // OD 19.05.2003 #109667# - merge <lcl_PaintLeftLine> and <lcl_PaintRightLine>
4196 // into new method <lcl_PaintLeftRightLine(..)>
4197 void lcl_PaintLeftRightLine( const sal_Bool         _bLeft,
4198                              const SwFrm&           _rFrm,
4199                              const SwPageFrm&       _rPage,
4200                              const SwRect&          _rOutRect,
4201                              const SwRect&          _rRect,
4202                              const SwBorderAttrs&   _rAttrs,
4203                              const SwRectFn&        _rRectFn )
4204 {
4205     const SvxBoxItem& rBox = _rAttrs.GetBox();
4206     const sal_Bool bR2L = _rFrm.IsCellFrm() && _rFrm.IsRightToLeft();
4207     const SvxBorderLine* pLeftRightBorder = 0;
4208     if ( _bLeft )
4209     {
4210         pLeftRightBorder = bR2L ? rBox.GetRight() : rBox.GetLeft();
4211     }
4212     else
4213     {
4214         pLeftRightBorder = bR2L ? rBox.GetLeft() : rBox.GetRight();
4215     }
4216     // OD 06.05.2003 #107169# - init boolean indicating printer output device.
4217     const sal_Bool bPrtOutputDev =
4218             ( OUTDEV_PRINTER == pGlobalShell->GetOut()->GetOutDevType() );
4219 
4220     if ( !pLeftRightBorder )
4221     {
4222         return;
4223     }
4224 
4225     SwRect aRect( _rOutRect );
4226     if ( _bLeft )
4227     {
4228         (aRect.*_rRectFn->fnAddRight)( ::lcl_AlignWidth( pLeftRightBorder->GetOutWidth() ) -
4229                                        (aRect.*_rRectFn->fnGetWidth)() );
4230     }
4231     else
4232     {
4233         (aRect.*_rRectFn->fnSubLeft)( ::lcl_AlignWidth( pLeftRightBorder->GetOutWidth() ) -
4234                                       (aRect.*_rRectFn->fnGetWidth)() );
4235     }
4236 
4237     const sal_Bool bCnt = _rFrm.IsCntntFrm();
4238 
4239     if ( bCnt )
4240     {
4241         ::lcl_ExtendLeftAndRight( aRect, _rFrm, _rAttrs, _rRectFn );
4242     }
4243 
4244     // OD 06.05.2003 #107169# - adjustments for printer output device
4245     if ( bPrtOutputDev )
4246     {
4247         // substract width of outer top line.
4248         if ( rBox.GetTop() && (!bCnt || _rAttrs.GetTopLine( _rFrm )) )
4249         {
4250             long nDist = ::lcl_AlignHeight( rBox.GetTop()->GetOutWidth() );
4251             (aRect.*_rRectFn->fnSubTop)( -nDist );
4252             // OD 19.05.2003 #109667# - If outer top line is hair line, calculated
4253             // top has to be adjusted.
4254             if ( nDist == 1 )
4255             {
4256                 if ( _rFrm.IsVertical() )
4257                 {
4258                     // right of border rectangle has to be checked and adjusted
4259                     Point aCompPt( aRect.Right(), 0 );
4260                     Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
4261                     lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4262                                               aRefPt, aCompPt,
4263                                               sal_True, -1 );
4264                     aRect.Right( aCompPt.X() );
4265                 }
4266                 else
4267                 {
4268                     // top of border rectangle has to be checked and adjusted
4269                     Point aCompPt( 0, aRect.Top() );
4270                     Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
4271                     lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4272                                               aRefPt, aCompPt,
4273                                               sal_False, +1 );
4274                     aRect.Top( aCompPt.Y() );
4275                 }
4276             }
4277         }
4278         // substract width of outer bottom line.
4279         if ( rBox.GetBottom() && (!bCnt || _rAttrs.GetBottomLine( _rFrm )) )
4280         {
4281             long nDist = ::lcl_AlignHeight( rBox.GetBottom()->GetOutWidth());
4282             (aRect.*_rRectFn->fnAddBottom)( -nDist );
4283             // OD 19.05.2003 #109667# - If outer bottom line is hair line, calculated
4284             // top has to be adjusted.
4285             if ( nDist == 1 )
4286             {
4287                 if ( _rFrm.IsVertical() )
4288                 {
4289                     // left of border rectangle has to be checked and adjusted
4290                     Point aCompPt( aRect.Left(), 0 );
4291                     Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
4292                     lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4293                                               aRefPt, aCompPt,
4294                                               sal_True, +1 );
4295                     aRect.Left( aCompPt.X() );
4296                 }
4297                 else
4298                 {
4299                     // bottom of border rectangle has to be checked and adjusted
4300                     Point aCompPt( 0, aRect.Bottom() );
4301                     Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
4302                     lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
4303                                               aRefPt, aCompPt,
4304                                               sal_False, -1 );
4305                     aRect.Bottom( aCompPt.Y() );
4306                 }
4307             }
4308         }
4309     }
4310 
4311     if ( !pLeftRightBorder->GetInWidth() )
4312     {
4313         // OD 06.05.2003 #107169# - add 6th parameter
4314         ::lcl_SubTopBottom( aRect, rBox, _rAttrs, _rFrm, _rRectFn, bPrtOutputDev );
4315     }
4316 
4317     // OD 29.04.2003 #107169# - paint SwAligned-rectangle
4318     {
4319         SwRect aPaintRect( aRect );
4320         ::SwAlignRect( aPaintRect, _rFrm.getRootFrm()->GetCurrShell() );
4321         // if <SwAlignRect> reveals rectangle with no width, adjust rectangle
4322         // to the prior left postion with width of one twip.
4323         if ( (aPaintRect.*_rRectFn->fnGetWidth)() == 0 )
4324         {
4325             if ( _bLeft )
4326             {
4327                 (aPaintRect.*_rRectFn->fnSetLeft)( (aRect.*_rRectFn->fnGetLeft)() );
4328                 (aPaintRect.*_rRectFn->fnSetRight)( (aRect.*_rRectFn->fnGetLeft)() );
4329                 (aPaintRect.*_rRectFn->fnAddRight)( 1 );
4330             }
4331             else
4332             {
4333                 (aPaintRect.*_rRectFn->fnSetLeft)( (aRect.*_rRectFn->fnGetRight)() - 1 );
4334                 (aPaintRect.*_rRectFn->fnSetRight)( (aRect.*_rRectFn->fnGetRight)() - 1 );
4335                 (aPaintRect.*_rRectFn->fnAddRight)( 1 );
4336             }
4337         }
4338         _rFrm.PaintBorderLine( _rRect, aPaintRect, &_rPage, &pLeftRightBorder->GetColor() );
4339     }
4340 
4341     if ( pLeftRightBorder->GetInWidth() )
4342     {
4343         const long nDist = ::lcl_MinWidthDist( pLeftRightBorder->GetDistance() );
4344         long nWidth = ::lcl_AlignWidth( pLeftRightBorder->GetInWidth() );
4345         if ( _bLeft )
4346         {
4347             (aRect.*_rRectFn->fnAddRight)( nDist + nWidth );
4348             (aRect.*_rRectFn->fnSubLeft)( nWidth - (aRect.*_rRectFn->fnGetWidth)() );
4349         }
4350         else
4351         {
4352             (aRect.*_rRectFn->fnSubLeft)( nDist + nWidth );
4353             (aRect.*_rRectFn->fnAddRight)( nWidth - (aRect.*_rRectFn->fnGetWidth)() );
4354         }
4355         // OD 06.05.2003 #107169# - add 6th parameter
4356         ::lcl_SubTopBottom( aRect, rBox, _rAttrs, _rFrm, _rRectFn, bPrtOutputDev );
4357         // OD 29.04.2003 #107169# - paint SwAligned-rectangle
4358         {
4359             SwRect aPaintRect( aRect );
4360             ::SwAlignRect( aPaintRect, _rFrm.getRootFrm()->GetCurrShell() );
4361             // if <SwAlignRect> reveals rectangle with no width, adjust
4362             // rectangle to the prior left postion with width of one twip.
4363             if ( (aPaintRect.*_rRectFn->fnGetWidth)() == 0 )
4364             {
4365                 if ( _bLeft )
4366                 {
4367                     (aPaintRect.*_rRectFn->fnSetLeft)( (aRect.*_rRectFn->fnGetLeft)() );
4368                     (aPaintRect.*_rRectFn->fnSetRight)( (aRect.*_rRectFn->fnGetLeft)() );
4369                     (aPaintRect.*_rRectFn->fnAddRight)( 1 );
4370                 }
4371                 else
4372                 {
4373                     (aPaintRect.*_rRectFn->fnSetLeft)( (aRect.*_rRectFn->fnGetRight)() - 1 );
4374                     (aPaintRect.*_rRectFn->fnSetRight)( (aRect.*_rRectFn->fnGetRight)() - 1 );
4375                     (aPaintRect.*_rRectFn->fnAddRight)( 1 );
4376                 }
4377             }
4378             _rFrm.PaintBorderLine( _rRect, aPaintRect, &_rPage, &pLeftRightBorder->GetColor() );
4379         }
4380     }
4381 }
4382 
4383 // OD 19.05.2003 #109667# - merge <lcl_PaintTopLine> and <lcl_PaintBottomLine>
4384 // into <lcl_PaintTopLine>
4385 void lcl_PaintTopBottomLine( const sal_Bool         _bTop,
4386                              const SwFrm&           _rFrm,
4387                              const SwPageFrm&       _rPage,
4388                              const SwRect&          _rOutRect,
4389                              const SwRect&          _rRect,
4390                              const SwBorderAttrs&   _rAttrs,
4391                              const SwRectFn&        _rRectFn )
4392 {
4393     const SvxBoxItem& rBox = _rAttrs.GetBox();
4394     const SvxBorderLine* pTopBottomBorder = 0;
4395     if ( _bTop )
4396     {
4397         pTopBottomBorder = rBox.GetTop();
4398     }
4399     else
4400     {
4401         pTopBottomBorder = rBox.GetBottom();
4402     }
4403 
4404     if ( !pTopBottomBorder )
4405     {
4406 		return;
4407     }
4408 
4409     SwRect aRect( _rOutRect );
4410     if ( _bTop )
4411     {
4412         (aRect.*_rRectFn->fnAddBottom)( ::lcl_AlignHeight( pTopBottomBorder->GetOutWidth() ) -
4413                                         (aRect.*_rRectFn->fnGetHeight)() );
4414     }
4415     else
4416     {
4417         (aRect.*_rRectFn->fnSubTop)( ::lcl_AlignHeight( pTopBottomBorder->GetOutWidth() ) -
4418                                      (aRect.*_rRectFn->fnGetHeight)() );
4419     }
4420 
4421     // OD 29.04.2003 #107169# - paint SwAligned-rectangle
4422     {
4423         SwRect aPaintRect( aRect );
4424         ::SwAlignRect( aPaintRect, _rFrm.getRootFrm()->GetCurrShell() );
4425         // if <SwAlignRect> reveals rectangle with no width, adjust rectangle
4426         // to the prior top postion with width of one twip.
4427         if ( (aPaintRect.*_rRectFn->fnGetHeight)() == 0 )
4428         {
4429             if ( _bTop )
4430             {
4431                 (aPaintRect.*_rRectFn->fnSetTop)( (aRect.*_rRectFn->fnGetTop)() );
4432                 (aPaintRect.*_rRectFn->fnSetBottom)( (aRect.*_rRectFn->fnGetTop)() );
4433                 (aPaintRect.*_rRectFn->fnAddBottom)( 1 );
4434             }
4435             else
4436             {
4437                 (aPaintRect.*_rRectFn->fnSetTop)( (aRect.*_rRectFn->fnGetBottom)() - 1 );
4438                 (aPaintRect.*_rRectFn->fnSetBottom)( (aRect.*_rRectFn->fnGetBottom)() - 1 );
4439                 (aPaintRect.*_rRectFn->fnAddBottom)( 1 );
4440             }
4441         }
4442         _rFrm.PaintBorderLine( _rRect, aPaintRect, &_rPage, &pTopBottomBorder->GetColor() );
4443     }
4444 
4445     if ( pTopBottomBorder->GetInWidth() )
4446 	{
4447         const long nDist = ::lcl_MinHeightDist( pTopBottomBorder->GetDistance() );
4448         const long nHeight = ::lcl_AlignHeight( pTopBottomBorder->GetInWidth() );
4449         if ( _bTop )
4450         {
4451             (aRect.*_rRectFn->fnAddBottom)( nDist + nHeight );
4452             (aRect.*_rRectFn->fnSubTop)( nHeight - (aRect.*_rRectFn->fnGetHeight)() );
4453         }
4454         else
4455         {
4456             (aRect.*_rRectFn->fnSubTop)( nDist + nHeight );
4457             (aRect.*_rRectFn->fnAddBottom)( nHeight -(aRect.*_rRectFn->fnGetHeight)() );
4458         }
4459         ::lcl_SubLeftRight( aRect, rBox, _rRectFn );
4460         // OD 29.04.2003 #107169# - paint SwAligned-rectangle
4461         {
4462             SwRect aPaintRect( aRect );
4463             ::SwAlignRect( aPaintRect, _rFrm.getRootFrm()->GetCurrShell() );
4464             // if <SwAlignRect> reveals rectangle with no width, adjust
4465             // rectangle to the prior top postion with width of one twip.
4466             if ( (aPaintRect.*_rRectFn->fnGetHeight)() == 0 )
4467             {
4468                 if ( _bTop )
4469                 {
4470                     (aPaintRect.*_rRectFn->fnSetTop)( (aRect.*_rRectFn->fnGetTop)() );
4471                     (aPaintRect.*_rRectFn->fnSetBottom)( (aRect.*_rRectFn->fnGetTop)() );
4472                     (aPaintRect.*_rRectFn->fnAddBottom)( 1 );
4473                 }
4474                 else
4475                 {
4476                     (aPaintRect.*_rRectFn->fnSetTop)( (aRect.*_rRectFn->fnGetBottom)() - 1 );
4477                     (aPaintRect.*_rRectFn->fnSetBottom)( (aRect.*_rRectFn->fnGetBottom)() - 1 );
4478                     (aPaintRect.*_rRectFn->fnAddBottom)( 1 );
4479                 }
4480             }
4481             _rFrm.PaintBorderLine( _rRect, aPaintRect, &_rPage, &pTopBottomBorder->GetColor() );
4482         }
4483 	}
4484 }
4485 
4486 
4487 /*************************************************************************
4488 |*
4489 |*  const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
4490 |*
4491 |* No comment. #i15844#
4492 |*
4493 |*************************************************************************/
4494 
4495 const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
4496 {
4497     ASSERT( rFrm.IsCellFrm(),
4498             "lcl_HasNextCell( const SwFrm& rFrm ) should be called with SwCellFrm" )
4499 
4500     const SwFrm* pTmpFrm = &rFrm;
4501     do
4502     {
4503         if ( pTmpFrm->GetNext() )
4504             return pTmpFrm->GetNext();
4505 
4506         pTmpFrm = pTmpFrm->GetUpper()->GetUpper();
4507     }
4508     while ( pTmpFrm->IsCellFrm() );
4509 
4510     return 0;
4511 }
4512 
4513 
4514 /*************************************************************************
4515 |*
4516 |*	SwFrm::PaintBorder()
4517 |*
4518 |*	Beschreibung		Malt Schatten und Umrandung
4519 |*	Ersterstellung		MA 23.01.92
4520 |*	Letzte Aenderung	MA 29. Jul. 96
4521 |*
4522 |*************************************************************************/
4523 
4524 /** local method to determine cell frame, from which the border attributes
4525     for paint of top/bottom border has to be used.
4526 
4527     OD 21.02.2003 #b4779636#, #107692#
4528 
4529     @author OD
4530 
4531 
4532     @param _pCellFrm
4533     input parameter - constant pointer to cell frame for which the cell frame
4534     for the border attributes has to be determined.
4535 
4536     @param _rCellBorderAttrs
4537     input parameter - constant reference to the border attributes of cell frame
4538     <_pCellFrm>.
4539 
4540     @param _bTop
4541     input parameter - boolean, that controls, if cell frame for top border or
4542     for bottom border has to be determined.
4543 
4544     @return constant pointer to cell frame, for which the border attributes has
4545     to be used
4546 */
4547 const SwFrm* lcl_GetCellFrmForBorderAttrs( const SwFrm*         _pCellFrm,
4548                                            const SwBorderAttrs& _rCellBorderAttrs,
4549                                            const bool           _bTop )
4550 {
4551     ASSERT( _pCellFrm, "No cell frame available, dying soon" )
4552 
4553     // determine, if cell frame is at bottom/top border of a table frame and
4554     // the table frame has/is a follow.
4555     const SwFrm* pTmpFrm = _pCellFrm;
4556     bool bCellAtBorder = true;
4557     bool bCellAtLeftBorder = !_pCellFrm->GetPrev();
4558     bool bCellAtRightBorder = !_pCellFrm->GetNext();
4559     while( !pTmpFrm->IsRowFrm() || !pTmpFrm->GetUpper()->IsTabFrm() )
4560     {
4561         pTmpFrm = pTmpFrm->GetUpper();
4562         if ( pTmpFrm->IsRowFrm() &&
4563              (_bTop ? pTmpFrm->GetPrev() : pTmpFrm->GetNext())
4564            )
4565         {
4566             bCellAtBorder = false;
4567         }
4568         if ( pTmpFrm->IsCellFrm() )
4569         {
4570             if ( pTmpFrm->GetPrev() )
4571             {
4572                 bCellAtLeftBorder = false;
4573             }
4574             if ( pTmpFrm->GetNext() )
4575             {
4576                 bCellAtRightBorder = false;
4577             }
4578         }
4579     }
4580     ASSERT( pTmpFrm && pTmpFrm->IsRowFrm(), "No RowFrm available" );
4581 
4582     const SwLayoutFrm* pParentRowFrm = static_cast<const SwLayoutFrm*>(pTmpFrm);
4583     const SwTabFrm* pParentTabFrm =
4584             static_cast<const SwTabFrm*>(pParentRowFrm->GetUpper());
4585 
4586     const bool bCellNeedsAttribute = bCellAtBorder &&
4587                                      ( _bTop ?
4588                                       // bCellInFirstRowWithMaster
4589                                        ( !pParentRowFrm->GetPrev() &&
4590                                          pParentTabFrm->IsFollow() &&
4591                                          0 == pParentTabFrm->GetTable()->GetRowsToRepeat() ) :
4592                                       // bCellInLastRowWithFollow
4593                                        ( !pParentRowFrm->GetNext() &&
4594                                          pParentTabFrm->GetFollow() )
4595                                      );
4596 
4597     const SwFrm* pRet = _pCellFrm;
4598     if ( bCellNeedsAttribute )
4599     {
4600         // determine, if cell frame has no borders inside the table.
4601         const SwFrm* pNextCell = 0;
4602         bool bNoBordersInside = false;
4603 
4604         if ( bCellAtLeftBorder && ( 0 != ( pNextCell = lcl_HasNextCell( *_pCellFrm ) ) ) )
4605         {
4606             SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNextCell );
4607             const SwBorderAttrs &rBorderAttrs = *aAccess.Get();
4608             const SvxBoxItem& rBorderBox = rBorderAttrs.GetBox();
4609             bCellAtRightBorder = !lcl_HasNextCell( *pNextCell );
4610             bNoBordersInside =
4611                 ( !rBorderBox.GetTop()    || !pParentRowFrm->GetPrev() ) &&
4612                   !rBorderBox.GetLeft() &&
4613                 ( !rBorderBox.GetRight()  || bCellAtRightBorder ) &&
4614                 ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
4615         }
4616         else
4617         {
4618             const SvxBoxItem& rBorderBox = _rCellBorderAttrs.GetBox();
4619             bNoBordersInside =
4620                 ( !rBorderBox.GetTop()    || !pParentRowFrm->GetPrev() ) &&
4621                 ( !rBorderBox.GetLeft()   || bCellAtLeftBorder ) &&
4622                 ( !rBorderBox.GetRight()  || bCellAtRightBorder ) &&
4623                 ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
4624         }
4625 
4626         if ( bNoBordersInside )
4627         {
4628             if ( _bTop && !_rCellBorderAttrs.GetBox().GetTop() )
4629             {
4630                 // #b4779636#-hack:
4631                 // Cell frame has no top border and no border inside the table, but
4632                 // it is at the top border of a table frame, which is a follow.
4633                 // Thus, use border attributes of cell frame in first row of complete table.
4634                 // First, determine first table frame of complete table.
4635                 SwTabFrm* pMasterTabFrm = pParentTabFrm->FindMaster( true );
4636                 // determine first row of complete table.
4637                 const SwFrm* pFirstRow = pMasterTabFrm->GetLower();
4638                 // return first cell in first row
4639                 SwFrm* pLowerCell = const_cast<SwFrm*>(pFirstRow->GetLower());
4640                 while ( !pLowerCell->IsCellFrm() ||
4641                         ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
4642                       )
4643                 {
4644                     pLowerCell = pLowerCell->GetLower();
4645                 }
4646                 ASSERT( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
4647                 pRet = pLowerCell;
4648             }
4649             else if ( !_bTop && !_rCellBorderAttrs.GetBox().GetBottom() )
4650             {
4651                 // #b4779636#-hack:
4652                 // Cell frame has no bottom border and no border inside the table,
4653                 // but it is at the bottom border of a table frame, which has a follow.
4654                 // Thus, use border attributes of cell frame in last row of complete table.
4655                 // First, determine last table frame of complete table.
4656                 SwTabFrm* pLastTabFrm = const_cast<SwTabFrm*>(pParentTabFrm->GetFollow());
4657                 while ( pLastTabFrm->GetFollow() )
4658                 {
4659                     pLastTabFrm = pLastTabFrm->GetFollow();
4660                 }
4661                 // determine last row of complete table.
4662                 SwFrm* pLastRow = pLastTabFrm->GetLastLower();
4663                 // return first bottom border cell in last row
4664                 SwFrm* pLowerCell = const_cast<SwFrm*>(pLastRow->GetLower());
4665                 while ( !pLowerCell->IsCellFrm() ||
4666                         ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
4667                       )
4668                 {
4669                     if ( pLowerCell->IsRowFrm() )
4670                     {
4671                         while ( pLowerCell->GetNext() )
4672                         {
4673                             pLowerCell = pLowerCell->GetNext();
4674                         }
4675                     }
4676                     pLowerCell = pLowerCell->GetLower();
4677                 }
4678                 ASSERT( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
4679                 pRet = pLowerCell;
4680             }
4681         }
4682     }
4683 
4684     return pRet;
4685 }
4686 
4687 void SwFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
4688 						 const SwBorderAttrs &rAttrs ) const
4689 {
4690     //fuer (Row,Body,Ftn,Root,Column,NoTxt) gibt's hier nix zu tun
4691     if ( (GetType() & 0x90C5) || (Prt().SSize() == Frm().SSize()) )
4692         return;
4693 
4694 	if ( (GetType() & 0x2000) && 	//Cell
4695 		 !pGlobalShell->GetViewOptions()->IsTable() )
4696 		return;
4697 
4698     // --> collapsing borders FME 2005-05-27 #i29550#
4699     if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
4700     {
4701         const SwTabFrm* pTabFrm = FindTabFrm();
4702         if ( pTabFrm->IsCollapsingBorders() )
4703             return;
4704 
4705         if ( pTabFrm->GetTable()->IsNewModel() && ( !IsCellFrm() || IsCoveredCell() ) )
4706             return;
4707     }
4708     // <--
4709 
4710     const bool bLine = rAttrs.IsLine() ? true : false;
4711     const bool bShadow = rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE;
4712 
4713     // OD 24.02.2003 #b4779636#, #107692# - flag to control,
4714     // if #b4779636#-hack has to be used.
4715     const bool bb4779636HackActive = true;
4716     // OD 21.02.2003 #b4779636#, #107692#
4717     const SwFrm* pCellFrmForBottomBorderAttrs = 0;
4718     const SwFrm* pCellFrmForTopBorderAttrs = 0;
4719     bool         bFoundCellForTopOrBorderAttrs = false;
4720     if ( bb4779636HackActive && IsCellFrm() )
4721     {
4722         pCellFrmForBottomBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, false );
4723         if ( pCellFrmForBottomBorderAttrs != this )
4724             bFoundCellForTopOrBorderAttrs = true;
4725         pCellFrmForTopBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, true );
4726         if ( pCellFrmForTopBorderAttrs != this )
4727             bFoundCellForTopOrBorderAttrs = true;
4728     }
4729 
4730     // OD 24.02.2003 #b4779636#, #107692# - add condition <bFoundCellForTopOrBorderAttrs>
4731     // for #b4779636#-hack
4732     if ( bLine || bShadow || bFoundCellForTopOrBorderAttrs )
4733 	{
4734 		//Wenn das Rechteck vollstandig innerhalb der PrtArea liegt,
4735 		//so braucht kein Rand gepainted werden.
4736 		//Fuer die PrtArea muss der Aligned'e Wert zugrunde gelegt werden,
4737 		//anderfalls wuerden u.U. Teile nicht verarbeitet.
4738 		SwRect aRect( Prt() );
4739 		aRect += Frm().Pos();
4740 		::SwAlignRect( aRect, pGlobalShell );
4741         // OD 27.09.2002 #103636# - new local boolean variable in order to
4742         // suspend border paint under special cases - see below.
4743         // NOTE: This is a fix for the implementation of feature #99657#.
4744         bool bDrawOnlyShadowForTransparentFrame = false;
4745         if ( aRect.IsInside( rRect ) )
4746         {
4747             // OD 27.09.2002 #103636# - paint shadow, if background is transparent.
4748             // Because of introduced transparent background for fly frame #99657#,
4749             // the shadow have to be drawn if the background is transparent,
4750             // in spite the fact that the paint rectangle <rRect> lies fully
4751             // in the printing area.
4752             // NOTE to chosen solution:
4753             //     On transparent background, continue processing, but suspend
4754             //     drawing of border by setting <bDrawOnlyShadowForTransparentFrame>
4755             //     to true.
4756             if ( IsLayoutFrm() &&
4757                  static_cast<const SwLayoutFrm*>(this)->GetFmt()->IsBackgroundTransparent() )
4758             {
4759                  bDrawOnlyShadowForTransparentFrame = true;
4760             }
4761             else
4762             {
4763                 return;
4764             }
4765         }
4766 
4767 		if ( !pPage )
4768 			pPage = FindPageFrm();
4769 
4770 		::lcl_CalcBorderRect( aRect, this, rAttrs, sal_True );
4771 		rAttrs.SetGetCacheLine( sal_True );
4772 		if ( bShadow )
4773             PaintShadow( rRect, aRect, rAttrs );
4774         // OD 27.09.2002 #103636# - suspend drawing of border
4775         // add condition < NOT bDrawOnlyShadowForTransparentFrame > - see above
4776         // OD 24.02.2003 #b4779636#, #107692# - add condition <bFoundCellForTopOrBorderAttrs>
4777         // for #b4779636#-hack.
4778         if ( ( bLine || bFoundCellForTopOrBorderAttrs ) &&
4779              !bDrawOnlyShadowForTransparentFrame )
4780 		{
4781             const SwFrm* pDirRefFrm = IsCellFrm() ? FindTabFrm() : this;
4782             SWRECTFN( pDirRefFrm )
4783             // OD 19.05.2003 #109667# - use new method <lcl_PaintLeftRightLine(..)>
4784             //::lcl_PaintLeftLine  ( this, pPage, aRect, rRect, rAttrs, fnRect );
4785             //::lcl_PaintRightLine ( this, pPage, aRect, rRect, rAttrs, fnRect );
4786             ::lcl_PaintLeftRightLine ( sal_True, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
4787             ::lcl_PaintLeftRightLine ( sal_False, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
4788             if ( !IsCntntFrm() || rAttrs.GetTopLine( *(this) ) )
4789             {
4790                 // OD 21.02.2003 #b4779636#, #107692# -
4791                 // #b4779636#-hack: If another cell frame for top border
4792                 // paint is found, paint its top border.
4793                 if ( IsCellFrm() && pCellFrmForTopBorderAttrs != this )
4794                 {
4795                     SwBorderAttrAccess aAccess( SwFrm::GetCache(),
4796                                                 pCellFrmForTopBorderAttrs );
4797                     const SwBorderAttrs &rTopAttrs = *aAccess.Get();
4798                     // OD 19.05.2003 #109667# - use new method <lcl_PaintTopBottomLine(..)>
4799                     //::lcl_PaintTopLine( this, pPage, aRect, rRect, rTopAttrs, fnRect );
4800                     ::lcl_PaintTopBottomLine( sal_True, *(this), *(pPage), aRect, rRect, rTopAttrs, fnRect );
4801                 }
4802                 else
4803                 {
4804                     // OD 19.05.2003 #109667# - use new method <lcl_PaintTopBottomLine(..)>
4805                     //::lcl_PaintTopLine( this, pPage, aRect, rRect, rAttrs, fnRect );
4806                     ::lcl_PaintTopBottomLine( sal_True, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
4807                 }
4808             }
4809             if ( !IsCntntFrm() || rAttrs.GetBottomLine( *(this) ) )
4810             {
4811                 // OD 21.02.2003 #b4779636#, #107692# -
4812                 // #b4779636#-hack: If another cell frame for bottom border
4813                 // paint is found, paint its bottom border.
4814                 if ( IsCellFrm() && pCellFrmForBottomBorderAttrs != this )
4815                 {
4816                     SwBorderAttrAccess aAccess( SwFrm::GetCache(),
4817                                                 pCellFrmForBottomBorderAttrs );
4818                     const SwBorderAttrs &rBottomAttrs = *aAccess.Get();
4819                     // OD 19.05.2003 #109667# - use new method <lcl_PaintTopBottomLine(..)>
4820                     //::lcl_PaintBottomLine(this, pPage, aRect, rRect, rBottomAttrs, fnRect);
4821                     ::lcl_PaintTopBottomLine(sal_False, *(this), *(pPage), aRect, rRect, rBottomAttrs, fnRect);
4822                 }
4823                 else
4824                 {
4825                     // OD 19.05.2003 #109667# - use new method <lcl_PaintTopBottomLine(..)>
4826                     //::lcl_PaintBottomLine(this, pPage, aRect, rRect, rAttrs, fnRect);
4827                     ::lcl_PaintTopBottomLine(sal_False, *(this), *(pPage), aRect, rRect, rAttrs, fnRect);
4828                 }
4829             }
4830 		}
4831 		rAttrs.SetGetCacheLine( sal_False );
4832 	}
4833 }
4834 /*************************************************************************
4835 |*
4836 |*	SwFtnContFrm::PaintBorder()
4837 |*
4838 |*	Beschreibung		Spezialimplementierung wg. der Fussnotenlinie.
4839 |* 		Derzeit braucht nur der obere Rand beruecksichtigt werden.
4840 |* 		Auf andere Linien und Schatten wird verzichtet.
4841 |*	Ersterstellung		MA 27. Feb. 93
4842 |*	Letzte Aenderung	MA 08. Sep. 93
4843 |*
4844 |*************************************************************************/
4845 
4846 void SwFtnContFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
4847 								const SwBorderAttrs & ) const
4848 {
4849 	//Wenn das Rechteck vollstandig innerhalb der PrtArea liegt, so gibt es
4850 	//keinen Rand zu painten.
4851 	SwRect aRect( Prt() );
4852 	aRect.Pos() += Frm().Pos();
4853 	if ( !aRect.IsInside( rRect ) )
4854 		PaintLine( rRect, pPage );
4855 }
4856 /*************************************************************************
4857 |*
4858 |*	SwFtnContFrm::PaintLine()
4859 |*
4860 |*	Beschreibung		Fussnotenline malen.
4861 |*	Ersterstellung		MA 02. Mar. 93
4862 |*	Letzte Aenderung	MA 28. Mar. 94
4863 |*
4864 |*************************************************************************/
4865 
4866 void SwFtnContFrm::PaintLine( const SwRect& rRect,
4867 							  const SwPageFrm *pPage ) const
4868 {
4869 	//Laenge der Linie ergibt sich aus der prozentualen Angabe am PageDesc.
4870 	//Die Position ist ebenfalls am PageDesc angegeben.
4871 	//Der Pen steht direkt im PageDesc.
4872 
4873 	if ( !pPage )
4874 		pPage = FindPageFrm();
4875 	const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
4876 
4877     SWRECTFN( this )
4878     SwTwips nPrtWidth = (Prt().*fnRect->fnGetWidth)();
4879     Fraction aFract( nPrtWidth, 1 );
4880 	const SwTwips nWidth = (long)(aFract *= rInf.GetWidth());
4881 
4882     SwTwips nX = (this->*fnRect->fnGetPrtLeft)();
4883 	switch ( rInf.GetAdj() )
4884 	{
4885 		case FTNADJ_CENTER:
4886             nX += nPrtWidth/2 - nWidth/2; break;
4887 		case FTNADJ_RIGHT:
4888             nX += nPrtWidth - nWidth; break;
4889 		case FTNADJ_LEFT:
4890 			/* do nothing */; break;
4891 		default:
4892 			ASSERT( !this, "Neues Adjustment fuer Fussnotenlinie?" );
4893 	}
4894     SwTwips nLineWidth = rInf.GetLineWidth();
4895     const SwRect aLineRect = bVert ?
4896         SwRect( Point(Frm().Left()+Frm().Width()-rInf.GetTopDist()-nLineWidth,
4897                       nX), Size( nLineWidth, nWidth ) )
4898             : SwRect( Point( nX, Frm().Pos().Y() + rInf.GetTopDist() ),
4899                             Size( nWidth, rInf.GetLineWidth()));
4900 	if ( aLineRect.HasArea() )
4901 		PaintBorderLine( rRect, aLineRect , pPage, &rInf.GetLineColor() );
4902 }
4903 
4904 /*************************************************************************
4905 |*
4906 |*	SwLayoutFrm::PaintColLines()
4907 |*
4908 |*	Beschreibung		Painted die Trennlinien fuer die innenliegenden
4909 |* 						Spalten.
4910 |*	Ersterstellung		MA 21. Jun. 93
4911 |*	Letzte Aenderung	MA 28. Mar. 94
4912 |*
4913 |*************************************************************************/
4914 
4915 void SwLayoutFrm::PaintColLines( const SwRect &rRect, const SwFmtCol &rFmtCol,
4916 								 const SwPageFrm *pPage ) const
4917 {
4918 	const SwFrm *pCol = Lower();
4919 	if ( !pCol || !pCol->IsColumnFrm() )
4920 		return;
4921 	//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
4922     SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
4923 
4924     SwRect aLineRect = Prt();
4925     aLineRect += Frm().Pos();
4926 
4927     SwTwips nTop = ((aLineRect.*fnRect->fnGetHeight)()*rFmtCol.GetLineHeight())
4928                    / 100 - (aLineRect.*fnRect->fnGetHeight)();
4929     SwTwips nBottom = 0;
4930 
4931 	switch ( rFmtCol.GetLineAdj() )
4932 	{
4933 		case COLADJ_CENTER:
4934             nBottom = nTop / 2; nTop -= nBottom; break;
4935 		case COLADJ_TOP:
4936             nBottom = nTop; nTop = 0; break;
4937 		case COLADJ_BOTTOM:
4938             break;
4939 		default:
4940 			ASSERT( !this, "Neues Adjustment fuer Spaltenlinie?" );
4941 	}
4942 
4943     if( nTop )
4944         (aLineRect.*fnRect->fnSubTop)( nTop );
4945     if( nBottom )
4946         (aLineRect.*fnRect->fnAddBottom)( nBottom );
4947 
4948     SwTwips nPenHalf = rFmtCol.GetLineWidth();
4949     (aLineRect.*fnRect->fnSetWidth)( nPenHalf );
4950     nPenHalf /= 2;
4951 
4952     //Damit uns nichts verlorengeht muessen wir hier etwas grosszuegiger sein.
4953 	SwRect aRect( rRect );
4954     (aRect.*fnRect->fnSubLeft)( nPenHalf + nPixelSzW );
4955     (aRect.*fnRect->fnAddRight)( nPenHalf + nPixelSzW );
4956     SwRectGet fnGetX = IsRightToLeft() ? fnRect->fnGetLeft : fnRect->fnGetRight;
4957 	while ( pCol->GetNext() )
4958 	{
4959         (aLineRect.*fnRect->fnSetPosX)
4960             ( (pCol->Frm().*fnGetX)() - nPenHalf );
4961 		if ( aRect.IsOver( aLineRect ) )
4962             PaintBorderLine( aRect, aLineRect , pPage, &rFmtCol.GetLineColor());
4963 		pCol = pCol->GetNext();
4964 	}
4965 }
4966 
4967 void SwPageFrm::PaintGrid( OutputDevice* pOut, SwRect &rRect ) const
4968 {
4969     if( !bHasGrid || pRetoucheFly || pRetoucheFly2 )
4970         return;
4971     GETGRID( this )
4972     if( pGrid && ( OUTDEV_PRINTER != pOut->GetOutDevType() ?
4973         pGrid->GetDisplayGrid() : pGrid->GetPrintGrid() ) )
4974     {
4975         const SwLayoutFrm* pBody = FindBodyCont();
4976         if( pBody )
4977         {
4978             SwRect aGrid( pBody->Prt() );
4979             aGrid += pBody->Frm().Pos();
4980 
4981             SwRect aInter( aGrid );
4982             aInter.Intersection( rRect );
4983             if( aInter.HasArea() )
4984             {
4985                 sal_Bool bGrid = pGrid->GetRubyTextBelow();
4986                 sal_Bool bCell = GRID_LINES_CHARS == pGrid->GetGridType();
4987                 long nGrid = pGrid->GetBaseHeight();
4988 				const SwDoc* pDoc = GetFmt()->GetDoc();
4989                 long nGridWidth = GETGRIDWIDTH(pGrid,pDoc); //for textgrid refactor
4990                 long nRuby = pGrid->GetRubyHeight();
4991                 long nSum = nGrid + nRuby;
4992                 const Color *pCol = &pGrid->GetColor();
4993 
4994                 SwTwips nRight = aInter.Left() + aInter.Width();
4995                 SwTwips nBottom = aInter.Top() + aInter.Height();
4996                 if( IsVertical() )
4997                 {
4998                     SwTwips nOrig = aGrid.Left() + aGrid.Width();
4999                     SwTwips nY = nOrig + nSum *
5000                                  ( ( nOrig - aInter.Left() ) / nSum );
5001                     SwRect aTmp( Point( nY, aInter.Top() ),
5002                                 Size( 1, aInter.Height() ) );
5003                     SwTwips nX = aGrid.Top() + nGrid *
5004                                 ( ( aInter.Top() - aGrid.Top() )/ nGrid );
5005                     if( nX < aInter.Top() )
5006                         nX += nGrid;
5007                     SwTwips nGridBottom = aGrid.Top() + aGrid.Height();
5008                     sal_Bool bLeft = aGrid.Top() >= aInter.Top();
5009                     sal_Bool bRight = nGridBottom <= nBottom;
5010                     sal_Bool bBorder = bLeft || bRight;
5011                     while( nY > nRight )
5012                     {
5013                         aTmp.Pos().X() = nY;
5014                         if( bGrid )
5015                         {
5016                             nY -= nGrid;
5017                             SwTwips nPosY = Max( aInter.Left(), nY );
5018                             SwTwips nHeight = Min(nRight, aTmp.Pos().X())-nPosY;
5019                             if( nHeight > 0 )
5020                             {
5021                                 if( bCell )
5022                                 {
5023                                     SwRect aVert( Point( nPosY, nX ),
5024                                                 Size( nHeight, 1 ) );
5025                                     while( aVert.Top() <= nBottom )
5026                                     {
5027                                         PaintBorderLine(rRect,aVert,this,pCol);
5028                                         aVert.Pos().Y() += nGrid;
5029                                     }
5030                                 }
5031                                 else if( bBorder )
5032                                 {
5033                                     SwRect aVert( Point( nPosY, aGrid.Top() ),
5034                                                   Size( nHeight, 1 ) );
5035                                     if( bLeft )
5036                                         PaintBorderLine(rRect,aVert,this,pCol);
5037                                     if( bRight )
5038                                     {
5039                                         aVert.Pos().Y() = nGridBottom;
5040                                         PaintBorderLine(rRect,aVert,this,pCol);
5041                                     }
5042                                 }
5043                             }
5044                         }
5045                         else
5046                         {
5047                             nY -= nRuby;
5048                             if( bBorder )
5049                             {
5050                                 SwTwips nPos = Max( aInter.Left(), nY );
5051                                 SwTwips nW = Min(nRight, aTmp.Pos().X()) - nPos;
5052                                 SwRect aVert( Point( nPos, aGrid.Top() ),
5053                                               Size( nW, 1 ) );
5054                                 if( nW > 0 )
5055                                 {
5056                                     if( bLeft )
5057                                         PaintBorderLine(rRect,aVert,this,pCol);
5058                                     if( bRight )
5059                                     {
5060                                         aVert.Pos().Y() = nGridBottom;
5061                                         PaintBorderLine(rRect,aVert,this,pCol);
5062                                     }
5063                                 }
5064                             }
5065                         }
5066                         bGrid = !bGrid;
5067                     }
5068                     while( nY >= aInter.Left() )
5069                     {
5070                         aTmp.Pos().X() = nY;
5071                         PaintBorderLine( rRect, aTmp, this, pCol);
5072                         if( bGrid )
5073                         {
5074                             nY -= nGrid;
5075                             SwTwips nHeight = aTmp.Pos().X()
5076                                               - Max(aInter.Left(), nY );
5077                             if( nHeight > 0 )
5078                             {
5079                                 if( bCell )
5080                                 {
5081                                     SwRect aVert( Point(aTmp.Pos().X()-nHeight,
5082                                                   nX ), Size( nHeight, 1 ) );
5083                                     while( aVert.Top() <= nBottom )
5084                                     {
5085                                         PaintBorderLine(rRect,aVert,this,pCol);
5086                                         aVert.Pos().Y() += nGrid;
5087                                     }
5088                                 }
5089                                 else if( bBorder )
5090                                 {
5091                                     SwRect aVert( Point(aTmp.Pos().X()-nHeight,
5092                                             aGrid.Top() ), Size( nHeight, 1 ) );
5093                                     if( bLeft )
5094                                         PaintBorderLine(rRect,aVert,this,pCol);
5095                                     if( bRight )
5096                                     {
5097                                         aVert.Pos().Y() = nGridBottom;
5098                                         PaintBorderLine(rRect,aVert,this,pCol);
5099                                     }
5100                                 }
5101                             }
5102                         }
5103                         else
5104                         {
5105                             nY -= nRuby;
5106                             if( bBorder )
5107                             {
5108                                 SwTwips nPos = Max( aInter.Left(), nY );
5109                                 SwTwips nW = Min(nRight, aTmp.Pos().X()) - nPos;
5110                                 SwRect aVert( Point( nPos, aGrid.Top() ),
5111                                               Size( nW, 1 ) );
5112                                 if( nW > 0 )
5113                                 {
5114                                     if( bLeft )
5115                                         PaintBorderLine(rRect,aVert,this,pCol);
5116                                     if( bRight )
5117                                     {
5118                                         aVert.Pos().Y() = nGridBottom;
5119                                         PaintBorderLine(rRect,aVert,this,pCol);
5120                                     }
5121                                 }
5122                             }
5123                         }
5124                         bGrid = !bGrid;
5125                     }
5126                 }
5127                 else
5128                 {
5129                     SwTwips nOrig = aGrid.Top();
5130                     SwTwips nY = nOrig + nSum *( (aInter.Top()-nOrig)/nSum );
5131                     SwRect aTmp( Point( aInter.Left(), nY ),
5132                                 Size( aInter.Width(), 1 ) );
5133                     //for textgrid refactor
5134                     SwTwips nX = aGrid.Left() + nGridWidth *
5135                         ( ( aInter.Left() - aGrid.Left() )/ nGridWidth );
5136                     if( nX < aInter.Left() )
5137                         nX += nGridWidth;
5138                     SwTwips nGridRight = aGrid.Left() + aGrid.Width();
5139                     sal_Bool bLeft = aGrid.Left() >= aInter.Left();
5140                     sal_Bool bRight = nGridRight <= nRight;
5141                     sal_Bool bBorder = bLeft || bRight;
5142                     while( nY < aInter.Top() )
5143                     {
5144                         aTmp.Pos().Y() = nY;
5145                         if( bGrid )
5146                         {
5147                             nY += nGrid;
5148                             SwTwips nPosY = Max( aInter.Top(), aTmp.Pos().Y() );
5149                             SwTwips nHeight = Min(nBottom, nY ) - nPosY;
5150                             if( nHeight )
5151                             {
5152                                 if( bCell )
5153                                 {
5154                                     SwRect aVert( Point( nX, nPosY ),
5155                                                 Size( 1, nHeight ) );
5156                                     while( aVert.Left() <= nRight )
5157                                     {
5158                                         PaintBorderLine(rRect,aVert,this,pCol);
5159                                         aVert.Pos().X() += nGridWidth;	//for textgrid refactor
5160                                     }
5161                                 }
5162                                 else if ( bBorder )
5163                                 {
5164                                     SwRect aVert( Point( aGrid.Left(), nPosY ),
5165                                                 Size( 1, nHeight ) );
5166                                     if( bLeft )
5167                                         PaintBorderLine(rRect,aVert,this,pCol);
5168                                     if( bRight )
5169                                     {
5170                                         aVert.Pos().X() = nGridRight;
5171                                         PaintBorderLine(rRect,aVert,this,pCol);
5172                                     }
5173                                 }
5174                             }
5175                         }
5176                         else
5177                         {
5178                             nY += nRuby;
5179                             if( bBorder )
5180                             {
5181                                 SwTwips nPos = Max(aInter.Top(),aTmp.Pos().Y());
5182                                 SwTwips nH = Min( nBottom, nY ) - nPos;
5183                                 SwRect aVert( Point( aGrid.Left(), nPos ),
5184                                             Size( 1, nH ) );
5185                                 if( nH > 0 )
5186                                 {
5187                                     if( bLeft )
5188                                         PaintBorderLine(rRect,aVert,this,pCol);
5189                                     if( bRight )
5190                                     {
5191                                         aVert.Pos().X() = nGridRight;
5192                                         PaintBorderLine(rRect,aVert,this,pCol);
5193                                     }
5194                                 }
5195                             }
5196                         }
5197                         bGrid = !bGrid;
5198                     }
5199                     while( nY <= nBottom )
5200                     {
5201                         aTmp.Pos().Y() = nY;
5202                         PaintBorderLine( rRect, aTmp, this, pCol);
5203                         if( bGrid )
5204                         {
5205                             nY += nGrid;
5206                             SwTwips nHeight = Min(nBottom, nY) - aTmp.Pos().Y();
5207                             if( nHeight )
5208                             {
5209                                 if( bCell )
5210                                 {
5211                                     SwRect aVert( Point( nX, aTmp.Pos().Y() ),
5212                                                 Size( 1, nHeight ) );
5213                                     while( aVert.Left() <= nRight )
5214                                     {
5215                                         PaintBorderLine( rRect, aVert, this, pCol);
5216                                         aVert.Pos().X() += nGridWidth;	//for textgrid refactor
5217                                     }
5218                                 }
5219                                 else if( bBorder )
5220                                 {
5221                                     SwRect aVert( Point( aGrid.Left(),
5222                                         aTmp.Pos().Y() ), Size( 1, nHeight ) );
5223                                     if( bLeft )
5224                                         PaintBorderLine(rRect,aVert,this,pCol);
5225                                     if( bRight )
5226                                     {
5227                                         aVert.Pos().X() = nGridRight;
5228                                         PaintBorderLine(rRect,aVert,this,pCol);
5229                                     }
5230                                 }
5231                             }
5232                         }
5233                         else
5234                         {
5235                             nY += nRuby;
5236                             if( bBorder )
5237                             {
5238                                 SwTwips nPos = Max(aInter.Top(),aTmp.Pos().Y());
5239                                 SwTwips nH = Min( nBottom, nY ) - nPos;
5240                                 SwRect aVert( Point( aGrid.Left(), nPos ),
5241                                             Size( 1, nH ) );
5242                                 if( nH > 0 )
5243                                 {
5244                                     if( bLeft )
5245                                         PaintBorderLine(rRect,aVert,this,pCol);
5246                                     if( bRight )
5247                                     {
5248                                         aVert.Pos().X() = nGridRight;
5249                                         PaintBorderLine(rRect,aVert,this,pCol);
5250                                     }
5251                                 }
5252                             }
5253                         }
5254                         bGrid = !bGrid;
5255                     }
5256                 }
5257             }
5258         }
5259     }
5260 }
5261 
5262 /** paint margin area of a page
5263 
5264     OD 20.11.2002 for #104598#:
5265     implement paint of margin area; margin area will be painted for a
5266     view shell with a window and if the document is not in online layout.
5267 
5268     @author OD
5269 
5270     @param _rOutputRect
5271     input parameter - constant instance reference of the rectangle, for
5272     which an output has to be generated.
5273 
5274     @param _pViewShell
5275     input parameter - instance of the view shell, on which the output
5276     has to be generated.
5277 */
5278 void SwPageFrm::PaintMarginArea( const SwRect& _rOutputRect,
5279                                  ViewShell* _pViewShell ) const
5280 {
5281     if (  _pViewShell->GetWin() &&
5282          !_pViewShell->GetViewOptions()->getBrowseMode() )
5283     {
5284         SwRect aPgPrtRect( Prt() );
5285         aPgPrtRect.Pos() += Frm().Pos();
5286         if ( !aPgPrtRect.IsInside( _rOutputRect ) )
5287         {
5288             SwRect aPgRect = Frm();
5289             aPgRect._Intersection( _rOutputRect );
5290             SwRegionRects aPgRegion( aPgRect );
5291             aPgRegion -= aPgPrtRect;
5292             const SwPageFrm* pPage = static_cast<const SwPageFrm*>(this);
5293             if ( pPage->GetSortedObjs() )
5294                 ::lcl_SubtractFlys( this, pPage, aPgRect, aPgRegion );
5295             if ( aPgRegion.Count() )
5296             {
5297                 OutputDevice *pOut = _pViewShell->GetOut();
5298                 if ( pOut->GetFillColor() != aGlobalRetoucheColor )
5299                     pOut->SetFillColor( aGlobalRetoucheColor );
5300 				for ( sal_uInt16 i = 0; i < aPgRegion.Count(); ++i )
5301                 {
5302                     if ( 1 < aPgRegion.Count() )
5303                     {
5304                         ::SwAlignRect( aPgRegion[i], pGlobalShell );
5305                         if( !aPgRegion[i].HasArea() )
5306                             continue;
5307                     }
5308 					pOut->DrawRect(aPgRegion[i].SVRect());
5309                 }
5310             }
5311         }
5312     }
5313 }
5314 
5315 // ----------------------------------------------------------------------
5316 //
5317 // const SwPageFrm::mnBorderPxWidth, const SwPageFrm::mnShadowPxWidth
5318 // SwPageFrm::GetBorderRect (..), SwPageFrm::GetRightShadowRect(..),
5319 // SwPageFrm::GetBottomShadowRect(..),
5320 // SwPageFrm::PaintBorderAndShadow(..),
5321 // SwPageFrm::GetBorderAndShadowBoundRect(..)
5322 //
5323 // OD 12.02.2003 for #i9719# and #105645#
5324 // ----------------------------------------------------------------------
5325 
5326 const sal_Int8 SwPageFrm::mnBorderPxWidth = 1;
5327 const sal_Int8 SwPageFrm::mnShadowPxWidth = 2;
5328 
5329 /** determine rectangle for page border
5330 
5331     OD 12.02.2003 for #i9719# and #105645#
5332 
5333     @author OD
5334 */
5335 /*static*/ void SwPageFrm::GetBorderRect( const SwRect& _rPageRect,
5336                                           ViewShell*    _pViewShell,
5337                                           SwRect& _orBorderRect,
5338                                           bool bRightSidebar )
5339 {
5340     SwRect aAlignedPageRect( _rPageRect );
5341     ::SwAlignRect( aAlignedPageRect, _pViewShell );
5342     Rectangle aBorderPxRect =
5343             _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
5344 
5345 	aBorderPxRect.Left() = aBorderPxRect.Left() - mnBorderPxWidth;
5346     aBorderPxRect.Top() = aBorderPxRect.Top() - mnBorderPxWidth;
5347     aBorderPxRect.Right() = aBorderPxRect.Right() + mnBorderPxWidth;
5348     aBorderPxRect.Bottom() = aBorderPxRect.Bottom() + mnBorderPxWidth;
5349 
5350 	AddSidebarBorders(aBorderPxRect,_pViewShell, bRightSidebar, true);
5351 
5352     _orBorderRect =
5353             SwRect( _pViewShell->GetOut()->PixelToLogic( aBorderPxRect ) );
5354 }
5355 
5356 /** determine rectangle for right page shadow
5357 
5358     OD 12.02.2003 for #i9719# and #105645#
5359 
5360     @author OD
5361 */
5362 /*static*/ void SwPageFrm::GetRightShadowRect( const SwRect& _rPageRect,
5363                                                ViewShell*    _pViewShell,
5364                                                SwRect&       _orRightShadowRect,
5365                                                bool bRightSidebar )
5366 {
5367     SwRect aAlignedPageRect( _rPageRect );
5368     ::SwAlignRect( aAlignedPageRect, _pViewShell );
5369     Rectangle aPagePxRect =
5370             _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
5371 
5372     Rectangle aRightShadowPxRect(
5373                     aPagePxRect.Right() + mnShadowPxWidth,
5374                     aPagePxRect.Top() + 1,
5375                     aPagePxRect.Right() + mnBorderPxWidth + mnShadowPxWidth,
5376                     aPagePxRect.Bottom() + mnBorderPxWidth + mnShadowPxWidth );
5377 
5378     if ( bRightSidebar )
5379 	    AddSidebarBorders(aRightShadowPxRect,_pViewShell, bRightSidebar, true);
5380 
5381     _orRightShadowRect =
5382             SwRect( _pViewShell->GetOut()->PixelToLogic( aRightShadowPxRect ) );
5383 }
5384 
5385 /** determine rectangle for bottom page shadow
5386 
5387     OD 12.02.2003 for #i9719# and #105645#
5388 
5389     @author OD
5390 */
5391 /*static*/ void SwPageFrm::GetBottomShadowRect( const SwRect& _rPageRect,
5392                                                 ViewShell*    _pViewShell,
5393                                                 SwRect&       _orBottomShadowRect,
5394                                                 bool bRightSidebar )
5395 {
5396     SwRect aAlignedPageRect( _rPageRect );
5397     ::SwAlignRect( aAlignedPageRect, _pViewShell );
5398     Rectangle aPagePxRect =
5399             _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
5400 
5401     Rectangle aBottomShadowPxRect(
5402                     aPagePxRect.Left() + 1,
5403                     aPagePxRect.Bottom() + mnShadowPxWidth,
5404                     aPagePxRect.Right() + mnBorderPxWidth + mnShadowPxWidth,
5405                     aPagePxRect.Bottom() + mnBorderPxWidth + mnShadowPxWidth );
5406 
5407 	AddSidebarBorders(aBottomShadowPxRect,_pViewShell, bRightSidebar, true);
5408 
5409     _orBottomShadowRect =
5410             SwRect( _pViewShell->GetOut()->PixelToLogic( aBottomShadowPxRect ) );
5411 }
5412 
5413 /** paint page border and shadow
5414 
5415     OD 12.02.2003 for #i9719# and #105645#
5416     implement paint of page border and shadow
5417 
5418     @author OD
5419 */
5420 /*static*/ void SwPageFrm::PaintBorderAndShadow( const SwRect& _rPageRect,
5421                                                  ViewShell*    _pViewShell,
5422                                                  bool bPaintRightShadow,
5423                                                  bool bRightSidebar )
5424 {
5425     // --> FME 2004-06-24 #i16816# tagged pdf support
5426     SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *_pViewShell->GetOut() );
5427     // <--
5428 
5429     // get color for page border and shadow paint
5430     const Color& rColor = SwViewOption::GetFontColor();
5431 
5432     // save current fill and line color of output device
5433     Color aFill( _pViewShell->GetOut()->GetFillColor() );
5434     Color aLine( _pViewShell->GetOut()->GetLineColor() );
5435 
5436     // paint page border
5437     _pViewShell->GetOut()->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
5438     _pViewShell->GetOut()->SetLineColor( rColor );
5439     SwRect aPaintRect;
5440     SwPageFrm::GetBorderRect( _rPageRect, _pViewShell, aPaintRect, bRightSidebar );
5441     _pViewShell->GetOut()->DrawRect( aPaintRect.SVRect() );
5442 
5443     // paint right shadow
5444     if ( bPaintRightShadow )
5445     {
5446         _pViewShell->GetOut()->SetFillColor( rColor );
5447         SwPageFrm::GetRightShadowRect( _rPageRect, _pViewShell, aPaintRect, bRightSidebar );
5448         _pViewShell->GetOut()->DrawRect( aPaintRect.SVRect() );
5449     }
5450 
5451     // paint bottom shadow
5452     SwPageFrm::GetBottomShadowRect( _rPageRect, _pViewShell, aPaintRect, bRightSidebar );
5453     _pViewShell->GetOut()->DrawRect( aPaintRect.SVRect() );
5454 
5455     _pViewShell->GetOut()->SetFillColor( aFill );
5456     _pViewShell->GetOut()->SetLineColor( aLine );
5457 }
5458 
5459 //mod #i6193# paint sidebar for notes
5460 //IMPORTANT: if you change the rects here, also change SwPostItMgr::ScrollbarHit
5461 /*static*/void SwPageFrm::PaintNotesSidebar(const SwRect& _rPageRect, ViewShell* _pViewShell, sal_uInt16 nPageNum, bool bRight)
5462 {
5463 	//TOOD: cut out scrollbar area and arrows out of sidepane rect, otherwise it could flicker when pressing arrow buttons
5464     if (!_pViewShell )
5465         return;
5466 
5467     SwRect aPageRect( _rPageRect );
5468     SwAlignRect( aPageRect, _pViewShell );
5469 
5470     const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr();
5471     if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())  // do not show anything in print preview
5472 	{
5473         sal_Int32 nScrollerHeight = pMgr->GetSidebarScrollerHeight();
5474         const Rectangle &aVisRect = _pViewShell->VisArea().SVRect();
5475         //draw border and sidepane
5476         _pViewShell->GetOut()->SetLineColor();
5477         if (!bRight)
5478         {
5479             _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
5480             _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height())))    ;
5481             if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
5482                 _pViewShell->GetOut()->SetFillColor(COL_BLACK);
5483             else
5484                 _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
5485             _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarWidth()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height())))  ;
5486         }
5487         else
5488         {
5489             _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
5490             SwRect aSidebarBorder(aPageRect.TopRight(),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()));
5491             _pViewShell->GetOut()->DrawRect(aSidebarBorder.SVRect());
5492             if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
5493                 _pViewShell->GetOut()->SetFillColor(COL_BLACK);
5494             else
5495                 _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
5496             SwRect aSidebar(Point(aPageRect.Right()+pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()));
5497             _pViewShell->GetOut()->DrawRect(aSidebar.SVRect());
5498         }
5499         if (pMgr->ShowScrollbar(nPageNum))
5500         {
5501             // draw scrollbar area and arrows
5502             Point aPointBottom;
5503             Point aPointTop;
5504             aPointBottom = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() - pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height()) :
5505                                     Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height());
5506             aPointTop = !bRight ?    Point(aPageRect.Left() - pMgr->GetSidebarWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height()) :
5507                                 Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height());
5508             Size aSize(pMgr->GetSidebarWidth() - _pViewShell->GetOut()->PixelToLogic(Size(4,0)).Width(), _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()) ;
5509             Rectangle aRectBottom(aPointBottom,aSize);
5510             Rectangle aRectTop(aPointTop,aSize);
5511 
5512             if (aRectBottom.IsOver(aVisRect))
5513             {
5514 
5515                 if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
5516                 {
5517                     _pViewShell->GetOut()->SetLineColor(COL_WHITE);
5518                     _pViewShell->GetOut()->SetFillColor(COL_BLACK);
5519                 }
5520                 else
5521                 {
5522                     _pViewShell->GetOut()->SetLineColor(COL_BLACK);
5523                     _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
5524                 }
5525                 _pViewShell->GetOut()->DrawRect(aRectBottom);
5526                 _pViewShell->GetOut()->DrawLine(aPointBottom + Point(pMgr->GetSidebarWidth()/3,0), aPointBottom + Point(pMgr->GetSidebarWidth()/3 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
5527 
5528                 _pViewShell->GetOut()->SetLineColor();
5529                 Point aMiddleFirst(aPointBottom + Point(pMgr->GetSidebarWidth()/6,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
5530                 Point aMiddleSecond(aPointBottom + Point(pMgr->GetSidebarWidth()/3*2,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
5531                 PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell,pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
5532             }
5533             if (aRectTop.IsOver(aVisRect))
5534             {
5535                 if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
5536                 {
5537                     _pViewShell->GetOut()->SetLineColor(COL_WHITE);
5538                     _pViewShell->GetOut()->SetFillColor(COL_BLACK);
5539                 }
5540                 else
5541                 {
5542                     _pViewShell->GetOut()->SetLineColor(COL_BLACK);
5543                     _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
5544                 }
5545                 _pViewShell->GetOut()->DrawRect(aRectTop);
5546                 _pViewShell->GetOut()->DrawLine(aPointTop + Point(pMgr->GetSidebarWidth()/3*2,0), aPointTop + Point(pMgr->GetSidebarWidth()/3*2 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
5547 
5548                 _pViewShell->GetOut()->SetLineColor();
5549                 Point aMiddleFirst(aPointTop + Point(pMgr->GetSidebarWidth()/3,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
5550                 Point aMiddleSecond(aPointTop + Point(pMgr->GetSidebarWidth()/6*5,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
5551                 PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell, pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
5552             }
5553         }
5554     }
5555 }
5556 
5557 /*static*/ void SwPageFrm::PaintNotesSidebarArrows(const Point &aMiddleFirst, const Point &aMiddleSecond, ViewShell* _pViewShell, const Color aColorUp, const Color aColorDown)
5558 {
5559 	Polygon aTriangleUp(3);
5560 	Polygon aTriangleDown(3);
5561 
5562 	aTriangleUp.SetPoint(aMiddleFirst + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
5563 	aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),1);
5564 	aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
5565 
5566 	aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
5567 	aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(+3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),1);
5568 	aTriangleDown.SetPoint(aMiddleSecond + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
5569 
5570 	_pViewShell->GetOut()->SetFillColor(aColorUp);
5571 	_pViewShell->GetOut()->DrawPolygon(aTriangleUp);
5572 	_pViewShell->GetOut()->SetFillColor(aColorDown);
5573 	_pViewShell->GetOut()->DrawPolygon(aTriangleDown);
5574 }
5575 
5576 /** get bound rectangle of border and shadow for repaints
5577 
5578     OD 12.02.2003 for #i9719# and #105645#
5579 
5580     author OD
5581 */
5582 /*static*/ void SwPageFrm::GetBorderAndShadowBoundRect( const SwRect& _rPageRect,
5583                                                         ViewShell*    _pViewShell,
5584                                                         SwRect& _orBorderAndShadowBoundRect,
5585                                                         bool bRightSidebar )
5586 {
5587     SwRect aTmpRect;
5588     SwPageFrm::GetBorderRect( _rPageRect, _pViewShell, _orBorderAndShadowBoundRect, bRightSidebar );
5589     SwPageFrm::GetRightShadowRect( _rPageRect, _pViewShell, aTmpRect, bRightSidebar );
5590     _orBorderAndShadowBoundRect.Union( aTmpRect );
5591     SwPageFrm::GetBottomShadowRect( _rPageRect, _pViewShell, aTmpRect, bRightSidebar );
5592     _orBorderAndShadowBoundRect.Union( aTmpRect );
5593 
5594 	AddSidebarBorders(_orBorderAndShadowBoundRect, _pViewShell, bRightSidebar, false);
5595 }
5596 
5597 /*static*/ void SwPageFrm::AddSidebarBorders(SwRect &aRect, ViewShell* _pViewShell, bool bRightSidebar, bool bPx)
5598 {
5599     const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
5600     if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
5601     {
5602         if (!bRightSidebar)
5603             aRect.SetLeftAndWidth(aRect.Left() - pMgr->GetSidebarWidth(bPx) - pMgr->GetSidebarBorderWidth(bPx), aRect.Width() + pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
5604         else
5605             aRect.AddRight(pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
5606     }
5607 }
5608 
5609 /*static*/ void SwPageFrm::AddSidebarBorders(Rectangle &aRect, ViewShell* _pViewShell, bool bRightSidebar, bool bPx)
5610 {
5611     const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
5612     if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
5613     {
5614         if (!bRightSidebar)
5615             aRect.Left() -= (pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
5616         else
5617             aRect.Right() += pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx);
5618     }
5619 }
5620 
5621 /*static*/ SwTwips SwPageFrm::GetSidebarBorderWidth( const ViewShell* _pViewShell )
5622 {
5623     const SwPostItMgr* pPostItMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
5624     const SwTwips nRet = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
5625     return nRet;
5626 }
5627 
5628 /*************************************************************************
5629 |*
5630 |*	SwFrm::PaintBaBo()
5631 |*
5632 |*	Ersterstellung		MA 22. Oct. 93
5633 |*	Letzte Aenderung	MA 19. Jun. 96
5634 |*
5635 |*************************************************************************/
5636 
5637 void SwFrm::PaintBaBo( const SwRect& rRect, const SwPageFrm *pPage,
5638 					   const sal_Bool bLowerBorder ) const
5639 {
5640 	if ( !pPage )
5641 		pPage = FindPageFrm();
5642 
5643 	OutputDevice *pOut = pGlobalShell->GetOut();
5644 
5645     // --> FME 2004-06-24 #i16816# tagged pdf support
5646     SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
5647     // <--
5648 
5649     // OD 2004-04-23 #116347#
5650     pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
5651     pOut->SetLineColor();
5652 
5653 	SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
5654 	const SwBorderAttrs &rAttrs = *aAccess.Get();
5655 
5656     // OD 20.11.2002 #104598# - take care of page margin area
5657     // Note: code move from <SwFrm::PaintBackground(..)> to new method
5658     // <SwPageFrm::Paintmargin(..)>.
5659     if ( IsPageFrm() )
5660     {
5661         static_cast<const SwPageFrm*>(this)->PaintMarginArea( rRect, pGlobalShell );
5662     }
5663 
5664     // OD 06.08.2002 #99657# - paint border before painting background
5665     // paint grid for page frame and paint border
5666     {
5667         SwRect aRect( rRect );
5668         if( IsPageFrm() )
5669             ((SwPageFrm*)this)->PaintGrid( pOut, aRect );
5670         PaintBorder( aRect, pPage, rAttrs );
5671     }
5672 
5673     // paint background
5674     {
5675         PaintBackground( rRect, pPage, rAttrs, sal_False, bLowerBorder );
5676     }
5677 
5678 	pOut->Pop();
5679 }
5680 
5681 /*************************************************************************
5682 |*
5683 |*	SwFrm::PaintBackground()
5684 |*
5685 |*	Ersterstellung		MA 04. Jan. 93
5686 |*	Letzte Aenderung	MA 06. Feb. 97
5687 |*
5688 |*************************************************************************/
5689 /// OD 05.09.2002 #102912#
5690 /// Do not paint background for fly frames without a background brush by
5691 /// calling <PaintBaBo> at the page or at the fly frame its anchored
5692 void SwFrm::PaintBackground( const SwRect &rRect, const SwPageFrm *pPage,
5693 						 	 const SwBorderAttrs & rAttrs,
5694 							 const sal_Bool bLowerMode,
5695 							 const sal_Bool bLowerBorder ) const
5696 {
5697     // OD 20.01.2003 #i1837# - no paint of table background, if corresponding
5698     // option is *not* set.
5699     if( IsTabFrm() &&
5700         !pGlobalShell->GetViewOptions()->IsTable() )
5701     {
5702         return;
5703     }
5704 
5705 	// nothing to do for covered table cells:
5706 	if( IsCellFrm() && IsCoveredCell() )
5707 		return;
5708 
5709     ViewShell *pSh = pGlobalShell;
5710 
5711     // --> FME 2004-06-24 #i16816# tagged pdf support
5712     SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
5713     // <--
5714 
5715     const SvxBrushItem* pItem;
5716     /// OD 05.09.2002 #102912#
5717     /// temporary background brush for a fly frame without a background brush
5718     SvxBrushItem* pTmpBackBrush = 0;
5719     const Color* pCol;
5720 	SwRect aOrigBackRect;
5721 	const sal_Bool bPageFrm = IsPageFrm();
5722 	sal_Bool bLowMode = sal_True;
5723 
5724     sal_Bool bBack = GetBackgroundBrush( pItem, pCol, aOrigBackRect, bLowerMode );
5725     //- Ausgabe wenn ein eigener Hintergrund mitgebracht wird.
5726     bool bNoFlyBackground = !bFlyMetafile && !bBack && IsFlyFrm();
5727     if ( bNoFlyBackground )
5728     {
5729         // OD 05.09.2002 #102912# - Fly frame has no background.
5730         // Try to find background brush at parents, if previous call of
5731         // <GetBackgroundBrush> disabled this option with the parameter <bLowerMode>
5732         if ( bLowerMode )
5733         {
5734             bBack = GetBackgroundBrush( pItem, pCol, aOrigBackRect, false );
5735         }
5736         // If still no background found for the fly frame, initialize the
5737         // background brush <pItem> with global retouche color and set <bBack>
5738         // to sal_True, that fly frame will paint its background using this color.
5739         if ( !bBack )
5740         {
5741             // OD 10.01.2003 #i6467# - on print output, pdf output and
5742             // in embedded mode not editing color COL_WHITE is used instead of
5743             // the global retouche color.
5744             if ( pSh->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
5745                  pSh->GetViewOptions()->IsPDFExport() ||
5746                  ( pSh->GetDoc()->GetDocShell()->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED &&
5747                    !pSh->GetDoc()->GetDocShell()->IsInPlaceActive()
5748                  )
5749                )
5750             {
5751                 pTmpBackBrush = new SvxBrushItem( Color( COL_WHITE ), RES_BACKGROUND );
5752             }
5753             else
5754             {
5755                 pTmpBackBrush = new SvxBrushItem( aGlobalRetoucheColor, RES_BACKGROUND);
5756             }
5757             pItem = pTmpBackBrush;
5758             bBack = true;
5759         }
5760     }
5761 
5762 	SwRect aPaintRect( Frm() );
5763 	if( IsTxtFrm() || IsSctFrm() )
5764 		aPaintRect = UnionFrm( sal_True );
5765 
5766 	if ( aPaintRect.IsOver( rRect ) )
5767 	{
5768         if ( bBack || bPageFrm || !bLowerMode )
5769         {
5770             const sal_Bool bBrowse = pSh->GetViewOptions()->getBrowseMode();
5771             SwRect aRect;
5772             if ( (bPageFrm && bBrowse) ||
5773                  (IsTxtFrm() && Prt().SSize() == Frm().SSize()) )
5774             {
5775                 aRect = Frm();
5776                 ::SwAlignRect( aRect, pGlobalShell );
5777             }
5778             else
5779             {
5780                 ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_False );
5781                 if ( (IsTxtFrm() || IsTabFrm()) && GetPrev() )
5782                 {
5783                     if ( GetPrev()->GetAttrSet()->GetBackground() ==
5784                          GetAttrSet()->GetBackground() )
5785                     {
5786                         aRect.Top( Frm().Top() );
5787                     }
5788                 }
5789             }
5790             aRect.Intersection( rRect );
5791 
5792             OutputDevice *pOut = pSh->GetOut();
5793 
5794             if ( aRect.HasArea() )
5795             {
5796                 SvxBrushItem* pNewItem = 0;
5797                 SwRegionRects aRegion( aRect );
5798                 if( pCol )
5799                 {
5800                     pNewItem = new SvxBrushItem( *pCol, RES_BACKGROUND );
5801                     pItem = pNewItem;
5802                 }
5803                 if ( pPage->GetSortedObjs() )
5804                     ::lcl_SubtractFlys( this, pPage, aRect, aRegion );
5805 
5806                 {
5807                     /// OD 06.08.2002 #99657# - determine, if background transparency
5808                     ///     have to be considered for drawing.
5809                     ///     --> Status Quo: background transparency have to be
5810                     ///        considered for fly frames
5811                     const sal_Bool bConsiderBackgroundTransparency = IsFlyFrm();
5812                     for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
5813                     {
5814                         if ( 1 < aRegion.Count() )
5815                         {
5816                             ::SwAlignRect( aRegion[i], pGlobalShell );
5817                             if( !aRegion[i].HasArea() )
5818                                 continue;
5819                         }
5820                         /// OD 06.08.2002 #99657# - add 6th parameter to indicate, if
5821                         ///     background transparency have to be considered
5822                         ///     Set missing 5th parameter to the default value GRFNUM_NO
5823                         ///         - see declaration in /core/inc/frmtool.hxx.
5824                         ::DrawGraphic( pItem, pOut, aOrigBackRect, aRegion[i], GRFNUM_NO,
5825                                 bConsiderBackgroundTransparency );
5826                     }
5827                 }
5828                 if( pCol )
5829                     delete pNewItem;
5830             }
5831         }
5832         else
5833             bLowMode = bLowerMode ? sal_True : sal_False;
5834 	}
5835 
5836     /// OD 05.09.2002 #102912#
5837     /// delete temporary background brush.
5838     delete pTmpBackBrush;
5839 
5840     //Jetzt noch Lower und dessen Nachbarn.
5841 	//Wenn ein Frn dabei die Kette verlaesst also nicht mehr Lower von mir ist
5842 	//so hoert der Spass auf.
5843 	const SwFrm *pFrm = GetLower();
5844     if ( pFrm )
5845 	{
5846 		SwRect aFrmRect;
5847 		SwRect aRect( PaintArea() );
5848 		aRect._Intersection( rRect );
5849 		SwRect aBorderRect( aRect );
5850         SwShortCut aShortCut( *pFrm, aBorderRect );
5851 		do
5852 		{   if ( pProgress )
5853 				pProgress->Reschedule();
5854 
5855 			aFrmRect = pFrm->PaintArea();
5856 			if ( aFrmRect.IsOver( aBorderRect ) )
5857 			{
5858 				SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFrm );
5859                 const SwBorderAttrs &rTmpAttrs = *aAccess.Get();
5860                 /// OD 06.08.2002 #99657# - paint border before painting background
5861                 if ( bLowerBorder )
5862                     pFrm->PaintBorder( aBorderRect, pPage, rTmpAttrs );
5863 				if ( ( pFrm->IsLayoutFrm() && bLowerBorder ) ||
5864 					 aFrmRect.IsOver( aRect ) )
5865                     pFrm->PaintBackground( aRect, pPage, rTmpAttrs, bLowMode,
5866 										   bLowerBorder );
5867 			}
5868 			pFrm = pFrm->GetNext();
5869 		} while ( pFrm && pFrm->GetUpper() == this &&
5870                   !aShortCut.Stop( aFrmRect ) );
5871 	}
5872 }
5873 
5874 /*************************************************************************
5875 |*
5876 |*	SwPageFrm::RefreshSubsidiary()
5877 |*
5878 |*	Beschreibung		Erneuert alle Hilfslinien der Seite.
5879 |*	Ersterstellung		MA 04. Nov. 92
5880 |*	Letzte Aenderung	MA 10. May. 95
5881 |*
5882 |*************************************************************************/
5883 
5884 void SwPageFrm::RefreshSubsidiary( const SwRect &rRect ) const
5885 {
5886     if ( IS_SUBS || IS_SUBS_TABLE || IS_SUBS_SECTION || IS_SUBS_FLYS )
5887 	{
5888 		SwRect aRect( rRect );
5889         // OD 18.02.2003 #104989# - Not necessary and incorrect alignment of
5890         // the output rectangle.
5891         //::SwAlignRect( aRect, pGlobalShell );
5892 		if ( aRect.HasArea() )
5893 		{
5894 			//Beim Paint ueber die Root wird das Array von dort gesteuert.
5895 			//Anderfalls kuemmern wir uns selbst darum.
5896 			sal_Bool bDelSubs = sal_False;
5897 			if ( !pSubsLines )
5898 			{
5899 				pSubsLines = new SwSubsRects;
5900                 // OD 20.12.2002 #106318# - create container for special subsidiary lines
5901                 pSpecSubsLines = new SwSubsRects;
5902                 bDelSubs = sal_True;
5903 			}
5904 
5905 			RefreshLaySubsidiary( this, aRect );
5906 
5907             if ( bDelSubs )
5908 			{
5909                 // OD 20.12.2002 #106318# - paint special subsidiary lines
5910                 // and delete its container
5911                 pSpecSubsLines->PaintSubsidiary( pGlobalShell->GetOut(), NULL );
5912                 DELETEZ( pSpecSubsLines );
5913 
5914                 pSubsLines->PaintSubsidiary( pGlobalShell->GetOut(), pLines );
5915 				DELETEZ( pSubsLines );
5916 			}
5917 		}
5918 	}
5919 }
5920 
5921 /*************************************************************************
5922 |*
5923 |*	SwLayoutFrm::RefreshLaySubsidiary()
5924 |*
5925 |*	Ersterstellung		MA 04. Nov. 92
5926 |*	Letzte Aenderung	MA 22. Jan. 95
5927 |*
5928 |*************************************************************************/
5929 void SwLayoutFrm::RefreshLaySubsidiary( const SwPageFrm *pPage,
5930                                         const SwRect &rRect ) const
5931 {
5932 	const sal_Bool bNoLowerColumn = !Lower() || !Lower()->IsColumnFrm();
5933 	const sal_Bool bSubsOpt	  = IS_SUBS;
5934     const sal_Bool bSubsTable = ((GetType() & (FRM_ROW | FRM_CELL)) && IS_SUBS_TABLE);
5935     const sal_Bool bSubsOther = (GetType() & (FRM_HEADER | FRM_FOOTER | FRM_FTN )) && bSubsOpt;
5936 	const sal_Bool bSubsSect  = IsSctFrm() &&
5937 								bNoLowerColumn &&
5938 								IS_SUBS_SECTION;
5939     const sal_Bool bSubsFly   = IS_SUBS_FLYS &&
5940                                 (GetType() & FRM_FLY) &&
5941                                 bNoLowerColumn &&
5942 								(!Lower() || !Lower()->IsNoTxtFrm() ||
5943 								 !((SwNoTxtFrm*)Lower())->HasAnimation());
5944 	sal_Bool bSubsBody = sal_False;
5945 	if ( GetType() & FRM_BODY )
5946 	{
5947 		if ( IsPageBodyFrm() )
5948 			bSubsBody = bSubsOpt && bNoLowerColumn;									//nur ohne Spalten
5949         else    //Spaltenbody
5950 		{
5951 			if ( GetUpper()->GetUpper()->IsSctFrm() )
5952 				bSubsBody = IS_SUBS_SECTION;
5953 			else
5954 				bSubsBody = bSubsOpt;
5955 		}
5956 	}
5957 
5958 	if ( bSubsOther || bSubsSect  || bSubsBody || bSubsTable || bSubsFly )
5959 		PaintSubsidiaryLines( pPage, rRect );
5960 
5961     const SwFrm *pLow = Lower();
5962     if( !pLow )
5963         return;
5964     SwShortCut aShortCut( *pLow, rRect );
5965     while( pLow && !aShortCut.Stop( pLow->Frm() ) )
5966     {
5967         if ( pLow->Frm().IsOver( rRect ) && pLow->Frm().HasArea() )
5968         {
5969             if ( pLow->IsLayoutFrm() )
5970                 ((const SwLayoutFrm*)pLow)->RefreshLaySubsidiary( pPage, rRect);
5971             else if ( pLow->GetDrawObjs() )
5972             {
5973                 const SwSortedObjs& rObjs = *(pLow->GetDrawObjs());
5974                 for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
5975                 {
5976                     const SwAnchoredObject* pAnchoredObj = rObjs[i];
5977                     if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
5978                                     pAnchoredObj->GetDrawObj()->GetLayer() ) &&
5979                          pAnchoredObj->ISA(SwFlyFrm) )
5980                     {
5981                         const SwFlyFrm *pFly =
5982                                     static_cast<const SwFlyFrm*>(pAnchoredObj);
5983                         if ( pFly->IsFlyInCntFrm() && pFly->Frm().IsOver( rRect ) )
5984                         {
5985                             if ( !pFly->Lower() || !pFly->Lower()->IsNoTxtFrm() ||
5986                                  !((SwNoTxtFrm*)pFly->Lower())->HasAnimation())
5987                                 pFly->RefreshLaySubsidiary( pPage, rRect );
5988                         }
5989                     }
5990                 }
5991             }
5992         }
5993         pLow = pLow->GetNext();
5994     }
5995 }
5996 
5997 /*************************************************************************
5998 |*
5999 |*	SwLayoutFrm::PaintSubsidiaryLines()
6000 |*
6001 |*	Beschreibung		Hilfslinien um die PrtAreas malen
6002 |* 		Nur die LayoutFrm's die direkt Cntnt enthalten.
6003 |*	Ersterstellung		MA 21. May. 92
6004 |*	Letzte Aenderung	MA 22. Jan. 95
6005 |*
6006 |*************************************************************************/
6007 
6008 //Malt die angegebene Linie, achtet darauf, dass keine Flys uebermalt werden.
6009 
6010 typedef long Size::* SizePtr;
6011 typedef long Point::* PointPtr;
6012 
6013 PointPtr pX = &Point::nA;
6014 PointPtr pY = &Point::nB;
6015 SizePtr pWidth = &Size::nA;
6016 SizePtr pHeight = &Size::nB;
6017 
6018 // OD 18.11.2002 #99672# - new parameter <_pSubsLines>
6019 void MA_FASTCALL lcl_RefreshLine( const SwLayoutFrm *pLay,
6020                                   const SwPageFrm *pPage,
6021                                   const Point &rP1,
6022                                   const Point &rP2,
6023                                   const sal_uInt8 nSubColor,
6024                                   SwLineRects* _pSubsLines )
6025 {
6026 	//In welche Richtung gehts? Kann nur Horizontal oder Vertikal sein.
6027 	ASSERT( ((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y())),
6028 			"Schraege Hilfslinien sind nicht erlaubt." );
6029     const PointPtr pDirPt = rP1.X() == rP2.X() ? pY : pX;
6030     const PointPtr pOthPt = pDirPt == pX ? pY : pX;
6031     const SizePtr pDirSz = pDirPt == pX ? pWidth : pHeight;
6032     const SizePtr pOthSz = pDirSz == pWidth ? pHeight : pWidth;
6033 	Point aP1( rP1 ),
6034 		  aP2( rP2 );
6035 
6036 	while ( aP1.*pDirPt < aP2.*pDirPt )
6037 	{	//Der Startpunkt wird jetzt, falls er in einem Fly sitzt, direkt
6038 		//hinter den Fly gesetzt.
6039 		//Wenn der Endpunkt in einem Fly sitzt oder zwischen Start und Endpunkt
6040 		//ein Fly sitzt, so wird der Endpunkt eben an den Start herangezogen.
6041 		//Auf diese art und weise wird eine Portion nach der anderen
6042 		//ausgegeben.
6043 
6044 		//Wenn ich selbst ein Fly bin, weiche ich nur denjenigen Flys aus,
6045 		//die 'ueber' mir sitzen; d.h. die in dem Array hinter mir stehen.
6046 		//Auch wenn ich in einem Fly sitze oder in einem Fly im Fly usw. weiche
6047 		//ich keinem dieser Flys aus.
6048 		SwOrderIter aIter( pPage );
6049 		const SwFlyFrm *pMyFly = pLay->FindFlyFrm();
6050 		if ( pMyFly )
6051 		{
6052 			aIter.Current( pMyFly->GetVirtDrawObj() );
6053             while ( 0 != (pMyFly = pMyFly->GetAnchorFrm()->FindFlyFrm()) )
6054 			{
6055 				if ( aIter()->GetOrdNum() > pMyFly->GetVirtDrawObj()->GetOrdNum() )
6056 					aIter.Current( pMyFly->GetVirtDrawObj() );
6057 			}
6058 		}
6059 		else
6060 			aIter.Bottom();
6061 
6062 		while ( aIter() )
6063 		{
6064 			const SwVirtFlyDrawObj *pObj = (SwVirtFlyDrawObj*)aIter();
6065 			const SwFlyFrm *pFly = pObj ? pObj->GetFlyFrm() : 0;
6066 
6067 			//Mir selbst weiche ich natuerlich nicht aus. Auch wenn ich
6068 			//_in_ dem Fly sitze weiche ich nicht aus.
6069 			if ( !pFly || (pFly == pLay || pFly->IsAnLower( pLay )) )
6070             {
6071                 aIter.Next();
6072 				continue;
6073 			}
6074 
6075             // OD 19.12.2002 #106318# - do *not* consider fly frames with
6076             // a transparent background.
6077             // OD 2004-02-12 #110582#-2 - do *not* consider fly frame, which
6078             // belongs to a invisible layer
6079             if ( pFly->IsBackgroundTransparent() ||
6080                  !pFly->GetFmt()->GetDoc()->IsVisibleLayerId( pObj->GetLayer() ) )
6081             {
6082                 aIter.Next();
6083                 continue;
6084             }
6085 
6086 			//Sitzt das Obj auf der Linie
6087 			const Rectangle &rBound = pObj->GetCurrentBoundRect();
6088 			const Point aDrPt( rBound.TopLeft() );
6089 			const Size  aDrSz( rBound.GetSize() );
6090 			if ( rP1.*pOthPt >= aDrPt.*pOthPt &&
6091 				 rP1.*pOthPt <= (aDrPt.*pOthPt + aDrSz.*pOthSz) )
6092 			{
6093 				if ( aP1.*pDirPt >= aDrPt.*pDirPt &&
6094 			  	  	 aP1.*pDirPt <= (aDrPt.*pDirPt + aDrSz.*pDirSz) )
6095 					aP1.*pDirPt = aDrPt.*pDirPt + aDrSz.*pDirSz;
6096 
6097 				if ( aP2.*pDirPt >= aDrPt.*pDirPt &&
6098 					 aP1.*pDirPt < (aDrPt.*pDirPt - 1) )
6099 					aP2.*pDirPt = aDrPt.*pDirPt - 1;
6100 			}
6101 			aIter.Next();
6102 		}
6103 
6104 		if ( aP1.*pDirPt < aP2.*pDirPt )
6105 		{
6106 			SwRect aRect( aP1, aP2 );
6107             // OD 18.11.2002 #99672# - use parameter <_pSubsLines> instead of
6108             // global variable <pSubsLines>.
6109             _pSubsLines->AddLineRect( aRect, 0, 0, nSubColor );
6110 		}
6111 		aP1 = aP2;
6112 		aP1.*pDirPt += 1;
6113 		aP2 = rP2;
6114 	}
6115 }
6116 
6117 void SwLayoutFrm::PaintSubsidiaryLines( const SwPageFrm *pPage,
6118 										const SwRect &rRect ) const
6119 {
6120     bool bNewTableModel = false;
6121 
6122     // --> collapsing borders FME 2005-05-27 #i29550#
6123     if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
6124     {
6125         const SwTabFrm* pTabFrm = FindTabFrm();
6126         if ( pTabFrm->IsCollapsingBorders() )
6127             return;
6128 
6129         bNewTableModel = pTabFrm->GetTable()->IsNewModel();
6130         // in the new table model, we have an early return for all cell-related
6131         // frames, except from non-covered table cells
6132         if ( bNewTableModel )
6133             if ( IsTabFrm() ||
6134                  IsRowFrm() ||
6135                  ( IsCellFrm() && IsCoveredCell() ) )
6136                 return;
6137     }
6138     // <-- collapsing
6139 
6140     const bool bFlys = pPage->GetSortedObjs() ? true : false;
6141 
6142     const bool bCell = IsCellFrm() ? true : false;
6143     // use frame area for cells
6144     // OD 13.02.2003 #i3662# - for section use also frame area
6145     const bool bUseFrmArea = bCell || IsSctFrm();
6146     SwRect aOriginal( bUseFrmArea ? Frm() : Prt() );
6147     if ( !bUseFrmArea )
6148         aOriginal.Pos() += Frm().Pos();
6149 
6150     // OD 13.02.2003 #i3662# - enlarge top of column body frame's printing area
6151     // in sections to top of section frame.
6152     const bool bColBodyInSection = IsBodyFrm() &&
6153                                    !IsPageBodyFrm() &&
6154                                    GetUpper()->GetUpper()->IsSctFrm();
6155     if ( bColBodyInSection )
6156     {
6157         if ( IsVertical() )
6158             aOriginal.Right( GetUpper()->GetUpper()->Frm().Right() );
6159         else
6160             aOriginal.Top( GetUpper()->GetUpper()->Frm().Top() );
6161     }
6162 
6163     ::SwAlignRect( aOriginal, pGlobalShell );
6164 
6165     if ( !aOriginal.IsOver( rRect ) )
6166 		return;
6167 
6168 	SwRect aOut( aOriginal );
6169 	aOut._Intersection( rRect );
6170     // OD 13.02.2003 #i3662# - do not intersect *enlarged* column body frame's
6171     // printing area with the paint area of the body frame. Otherwise enlargement
6172     // will get lost.
6173     if ( !bColBodyInSection )
6174     {
6175         aOut.Intersection( PaintArea() );
6176     }
6177 
6178 	const SwTwips nRight = aOut.Right();
6179 	const SwTwips nBottom= aOut.Bottom();
6180 
6181 	const Point aRT( nRight, aOut.Top() );
6182 	const Point aRB( nRight, nBottom );
6183 	const Point aLB( aOut.Left(), nBottom );
6184 
6185     sal_uInt8 nSubColor = ( bCell || IsRowFrm() ) ? SUBCOL_TAB :
6186                      ( IsInSct() ? SUBCOL_SECT :
6187                      ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
6188 
6189     // OD 05.11.2002 #102406# - body frames are responsible for page/column breaks.
6190     sal_Bool bBreak = sal_False;
6191     if ( IsBodyFrm() )
6192     {
6193         const SwCntntFrm *pCnt = ContainsCntnt();
6194         if ( pCnt )
6195         {
6196             // OD 05.11.2002 #102406# - adjust setting of <bBreak>.
6197             bBreak = pCnt->IsPageBreak( sal_True ) ||
6198                      ( IsColBodyFrm() && pCnt->IsColBreak( sal_True ) );
6199         }
6200     }
6201 
6202     // OD 18.11.2002 #99672# - collect body, header, footer, footnote and section
6203     // sub-lines in <pSpecSubsLine> array.
6204     const bool bSpecialSublines = IsBodyFrm() || IsHeaderFrm() || IsFooterFrm() ||
6205                                   IsFtnFrm() || IsSctFrm();
6206     SwLineRects* pUsedSubsLines = bSpecialSublines ? pSpecSubsLines : pSubsLines;
6207 
6208     // NOTE: for cell frames only left and right (horizontal layout) respectively
6209     //      top and bottom (vertical layout) lines painted.
6210     // NOTE2: this does not hold for the new table model!!! We paint the top border
6211     // of each non-covered table cell.
6212     const bool bVert = IsVertical() ? true : false;
6213     if ( bFlys )
6214 	{
6215         // OD 14.11.2002 #104822# - add control for drawing left and right lines
6216         if ( !bCell || bNewTableModel || !bVert )
6217         {
6218             if ( aOriginal.Left() == aOut.Left() )
6219                 ::lcl_RefreshLine( this, pPage, aOut.Pos(), aLB, nSubColor,
6220                                    pUsedSubsLines );
6221             // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
6222             if ( aOriginal.Right() == nRight )
6223                 ::lcl_RefreshLine( this, pPage, aRT, aRB,
6224                                    (bBreak && bVert) ? SUBCOL_BREAK : nSubColor,
6225                                    pUsedSubsLines );
6226         }
6227         // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
6228         if ( !bCell || bNewTableModel || bVert )
6229 		{
6230 			if ( aOriginal.Top() == aOut.Top() )
6231                 // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
6232 				::lcl_RefreshLine( this, pPage, aOut.Pos(), aRT,
6233                                    (bBreak && !bVert) ? SUBCOL_BREAK : nSubColor,
6234                                    pUsedSubsLines );
6235 			if ( aOriginal.Bottom() == nBottom )
6236                 ::lcl_RefreshLine( this, pPage, aLB, aRB, nSubColor,
6237                                    pUsedSubsLines );
6238 		}
6239 	}
6240 	else
6241 	{
6242         // OD 14.11.2002 #104822# - add control for drawing left and right lines
6243         if ( !bCell || bNewTableModel || !bVert )
6244         {
6245             if ( aOriginal.Left() == aOut.Left() )
6246             {
6247                 const SwRect aRect( aOut.Pos(), aLB );
6248                 pUsedSubsLines->AddLineRect( aRect, 0, 0, nSubColor );
6249             }
6250             // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
6251             if ( aOriginal.Right() == nRight )
6252             {
6253                 const SwRect aRect( aRT, aRB );
6254                 pUsedSubsLines->AddLineRect( aRect, 0, 0,
6255                         (bBreak && bVert) ? SUBCOL_BREAK : nSubColor );
6256             }
6257         }
6258         // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
6259         if ( !bCell || bNewTableModel || bVert )
6260         {
6261 			if ( aOriginal.Top() == aOut.Top() )
6262 			{
6263                 // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
6264 				const SwRect aRect( aOut.Pos(), aRT );
6265                 pUsedSubsLines->AddLineRect( aRect, 0, 0,
6266                         (bBreak && !bVert) ? SUBCOL_BREAK : nSubColor );
6267 			}
6268 			if ( aOriginal.Bottom() == nBottom )
6269 			{
6270 				const SwRect aRect( aLB, aRB );
6271                 pUsedSubsLines->AddLineRect( aRect, 0, 0, nSubColor );
6272 			}
6273         }
6274 	}
6275 }
6276 
6277 /*************************************************************************
6278 |*
6279 |*	SwPageFrm::RefreshExtraData(), SwLayoutFrm::RefreshExtraData()
6280 |*
6281 |*	Beschreibung		Erneuert alle Extradaten (Zeilennummern usw) der Seite.
6282 |* 						Grundsaetzlich sind nur diejenigen Objekte beruecksichtig,
6283 |* 						die in die seitliche Ausdehnung des Rects ragen.
6284 |*	Ersterstellung		MA 20. Jan. 98
6285 |*	Letzte Aenderung	MA 18. Feb. 98
6286 |*
6287 |*************************************************************************/
6288 
6289 void SwPageFrm::RefreshExtraData( const SwRect &rRect ) const
6290 {
6291 	const SwLineNumberInfo &rInfo = GetFmt()->GetDoc()->GetLineNumberInfo();
6292 	sal_Bool bLineInFly = (rInfo.IsPaintLineNumbers() && rInfo.IsCountInFlys())
6293         || (sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE;
6294 
6295 	SwRect aRect( rRect );
6296 	::SwAlignRect( aRect, pGlobalShell );
6297 	if ( aRect.HasArea() )
6298 	{
6299 		SwLayoutFrm::RefreshExtraData( aRect );
6300 
6301 		if ( bLineInFly && GetSortedObjs() )
6302 			for ( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
6303 			{
6304                 const SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
6305                 if ( pAnchoredObj->ISA(SwFlyFrm) )
6306 				{
6307                     const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
6308 					if ( pFly->Frm().Top() <= aRect.Bottom() &&
6309 						 pFly->Frm().Bottom() >= aRect.Top() )
6310 						pFly->RefreshExtraData( aRect );
6311 				}
6312 			}
6313 	}
6314 }
6315 
6316 void SwLayoutFrm::RefreshExtraData( const SwRect &rRect ) const
6317 {
6318 
6319 	const SwLineNumberInfo &rInfo = GetFmt()->GetDoc()->GetLineNumberInfo();
6320 	sal_Bool bLineInBody = rInfo.IsPaintLineNumbers(),
6321 			 bLineInFly  = bLineInBody && rInfo.IsCountInFlys(),
6322              bRedLine = (sal_Int16)SW_MOD()->GetRedlineMarkPos()!=text::HoriOrientation::NONE;
6323 
6324 	const SwCntntFrm *pCnt = ContainsCntnt();
6325 	while ( pCnt && IsAnLower( pCnt ) )
6326 	{
6327 		if ( pCnt->IsTxtFrm() && ( bRedLine ||
6328 			 ( !pCnt->IsInTab() &&
6329 			   ((bLineInBody && pCnt->IsInDocBody()) ||
6330 			   (bLineInFly  && pCnt->IsInFly())) ) ) &&
6331 			 pCnt->Frm().Top() <= rRect.Bottom() &&
6332 			 pCnt->Frm().Bottom() >= rRect.Top() )
6333 		{
6334 			((SwTxtFrm*)pCnt)->PaintExtraData( rRect );
6335 		}
6336 		if ( bLineInFly && pCnt->GetDrawObjs() )
6337             for ( sal_uInt32 i = 0; i < pCnt->GetDrawObjs()->Count(); ++i )
6338 			{
6339                 const SwAnchoredObject* pAnchoredObj = (*pCnt->GetDrawObjs())[i];
6340                 if ( pAnchoredObj->ISA(SwFlyFrm) )
6341                 {
6342                     const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
6343                     if ( pFly->IsFlyInCntFrm() &&
6344 						 pFly->Frm().Top() <= rRect.Bottom() &&
6345 						 pFly->Frm().Bottom() >= rRect.Top() )
6346 						pFly->RefreshExtraData( rRect );
6347 				}
6348 		}
6349 		pCnt = pCnt->GetNextCntntFrm();
6350 	}
6351 }
6352 
6353 /** SwPageFrm::GetDrawBackgrdColor - for #102450#
6354 
6355     determine the color, that is respectively will be drawn as background
6356     for the page frame.
6357     Using existing method SwFrm::GetBackgroundBrush to determine the color
6358     that is set at the page frame respectively is parent. If none is found
6359     return the global retouche color
6360 
6361     @author OD
6362 
6363     @return Color
6364 */
6365 const Color& SwPageFrm::GetDrawBackgrdColor() const
6366 {
6367     const SvxBrushItem* pBrushItem;
6368     const Color* pDummyColor;
6369     SwRect aDummyRect;
6370     if ( GetBackgroundBrush( pBrushItem, pDummyColor, aDummyRect, true) )
6371         return pBrushItem->GetColor();
6372     else
6373         return aGlobalRetoucheColor;
6374 }
6375 
6376 /*************************************************************************
6377 |*
6378 |*    SwPageFrm::GetEmptyPageFont()
6379 |*
6380 |*    create/return font used to paint the "empty page" string
6381 |*
6382 |*************************************************************************/
6383 
6384 const Font& SwPageFrm::GetEmptyPageFont()
6385 {
6386     static Font* pEmptyPgFont = 0;
6387     if ( 0 == pEmptyPgFont )
6388     {
6389         pEmptyPgFont = new Font;
6390         pEmptyPgFont->SetSize( Size( 0, 80 * 20 )); // == 80 pt
6391         pEmptyPgFont->SetWeight( WEIGHT_BOLD );
6392         pEmptyPgFont->SetStyleName( aEmptyStr );
6393         pEmptyPgFont->SetName( String::CreateFromAscii(
6394                 RTL_CONSTASCII_STRINGPARAM( "Helvetica" )) );
6395         pEmptyPgFont->SetFamily( FAMILY_SWISS );
6396         pEmptyPgFont->SetTransparent( sal_True );
6397         pEmptyPgFont->SetColor( COL_GRAY );
6398     }
6399 
6400     return *pEmptyPgFont;
6401 }
6402 
6403 /*************************************************************************
6404 |*
6405 |*	  SwFrm::Retouche
6406 |*
6407 |*	  Beschreibung		Retouche fuer einen Bereich.
6408 |*		Retouche wird nur dann durchgefuehrt, wenn der Frm der letzte seiner
6409 |* 		Kette ist. Der Gesamte Bereich des Upper unterhalb des Frm wird
6410 |* 		per PaintBackground gecleared.
6411 |*	  Ersterstellung	MA 13. Apr. 93
6412 |*	  Letzte Aenderung	MA 25. Jul. 96
6413 |*
6414 |*************************************************************************/
6415 
6416 void SwFrm::Retouche( const SwPageFrm * pPage, const SwRect &rRect ) const
6417 {
6418 	if ( bFlyMetafile )
6419 		return;
6420 
6421 	ASSERT( GetUpper(), "Retoucheversuch ohne Upper." );
6422 	ASSERT( getRootFrm()->GetCurrShell() && pGlobalShell->GetWin(), "Retouche auf dem Drucker?" );
6423 
6424 	SwRect aRetouche( GetUpper()->PaintArea() );
6425 	aRetouche.Top( Frm().Top() + Frm().Height() );
6426 	aRetouche.Intersection( pGlobalShell->VisArea() );
6427 
6428 	if ( aRetouche.HasArea() )
6429 	{
6430         //Uebergebenes Rect ausparen. Dafuer brauchen wir leider eine Region
6431 		//zum ausstanzen.
6432 		SwRegionRects aRegion( aRetouche );
6433 		aRegion -= rRect;
6434 		ViewShell *pSh = getRootFrm()->GetCurrShell();
6435 
6436         // --> FME 2004-06-24 #i16816# tagged pdf support
6437         SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
6438         // <--
6439 
6440 		for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
6441 		{
6442 			SwRect &rRetouche = aRegion[i];
6443 
6444 			GetUpper()->PaintBaBo( rRetouche, pPage, sal_True );
6445 
6446 			//Hoelle und Himmel muessen auch refreshed werden.
6447 			//Um Rekursionen zu vermeiden muss mein Retouche Flag zuerst
6448 			//zurueckgesetzt werden!
6449 			ResetRetouche();
6450             SwRect aRetouchePart( rRetouche );
6451             if ( aRetouchePart.HasArea() )
6452             {
6453                 const Color aPageBackgrdColor = pPage->GetDrawBackgrdColor();
6454                 const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
6455                 // --> OD #i76669#
6456                 SwViewObjectContactRedirector aSwRedirector( *pSh );
6457                 // <--
6458 
6459                 pSh->Imp()->PaintLayer( pIDDMA->GetHellId(), 0,
6460                                         aRetouchePart, &aPageBackgrdColor,
6461                                         (pPage->IsRightToLeft() ? true : false),
6462                                         &aSwRedirector );
6463                 pSh->Imp()->PaintLayer( pIDDMA->GetHeavenId(), 0,
6464                                         aRetouchePart, &aPageBackgrdColor,
6465                                         (pPage->IsRightToLeft() ? true : false),
6466                                         &aSwRedirector );
6467             }
6468 
6469 			SetRetouche();
6470 
6471 			//Da wir uns ausserhalb aller Paint-Bereiche begeben muessen hier
6472 			//leider die Hilfslinien erneuert werden.
6473             pPage->RefreshSubsidiary( aRetouchePart );
6474 		}
6475 	}
6476 	if ( ViewShell::IsLstEndAction() )
6477 		ResetRetouche();
6478 }
6479 
6480 /** SwFrm::GetBackgroundBrush
6481 
6482     @descr
6483     determine the background brush for the frame:
6484     the background brush is taken from it-self or from its parent (anchor/upper).
6485     Normally, the background brush is taken, which has no transparent color or
6486     which has a background graphic. But there are some special cases:
6487     (1) No background brush is taken from a page frame, if view option "IsPageBack"
6488         isn't set.
6489     (2) Background brush from a index section is taken under special conditions.
6490         In this case parameter <rpCol> is set to the index shading color.
6491     (3) New (OD 20.08.2002) - Background brush is taken, if on background drawing
6492         of the frame transparency is considered and its color is not "no fill"/"auto fill"
6493     ---- old description in german:
6494     Beschreibung        Liefert die Backgroundbrush fuer den Bereich des
6495         des Frm. Die Brush wird entweder von ihm selbst oder von einem
6496         Upper vorgegeben, die erste Brush wird benutzt.
6497         Ist fuer keinen Frm eine Brush angegeben, so wird sal_False zurueck-
6498         geliefert.
6499     Ersterstellung      MA 23. Dec. 92
6500     Letzte Aenderung    MA 04. Feb. 97
6501 
6502     @param rpBrush
6503     output parameter - constant reference pointer the found background brush
6504 
6505     @param rpCol
6506     output parameter - constant reference pointer to the color of the index shading
6507     set under special conditions, if background brush is taken from an index section.
6508 
6509     @param rOrigRect
6510     in-/output parameter - reference to the retangle the background brush is
6511     considered for - adjusted to the frame, from which the background brush is
6512     taken.
6513 
6514     @parem bLowerMode
6515     input parameter - boolean indicating, if background brush should *not* be
6516     taken from parent.
6517 
6518     @author MA
6519     @change 20.08.2002 by OD
6520     @docdate 20.08.2002
6521 
6522     @return true, if a background brush for the frame is found
6523 */
6524 sal_Bool SwFrm::GetBackgroundBrush( const SvxBrushItem* & rpBrush,
6525 								const Color*& rpCol,
6526 								SwRect &rOrigRect,
6527 								sal_Bool bLowerMode ) const
6528 {
6529 	const SwFrm *pFrm = this;
6530 	ViewShell *pSh = getRootFrm()->GetCurrShell();
6531 	const SwViewOption *pOpt = pSh->GetViewOptions();
6532 	rpBrush = 0;
6533 	rpCol = NULL;
6534 	do
6535 	{	if ( pFrm->IsPageFrm() && !pOpt->IsPageBack() )
6536 			return sal_False;
6537 
6538 		const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
6539 		if( pFrm->IsSctFrm() )
6540 		{
6541 			const SwSection* pSection = ((SwSectionFrm*)pFrm)->GetSection();
6542             /// OD 20.08.2002 #99657# #GetTransChg#
6543             ///     Note: If frame <pFrm> is a section of the index and
6544             ///         it its background color is "no fill"/"auto fill" and
6545             ///         it has no background graphic and
6546             ///         we are not in the page preview and
6547             ///         we are not in read-only mode and
6548             ///         option "index shadings" is set and
6549             ///         the output is not the printer
6550             ///         then set <rpCol> to the color of the index shading
6551             if( pSection && (   TOX_HEADER_SECTION == pSection->GetType() ||
6552                                 TOX_CONTENT_SECTION == pSection->GetType() ) &&
6553                 (rBack.GetColor() == COL_TRANSPARENT) &&
6554                 ///rBack.GetColor().GetTransparency() &&
6555                 rBack.GetGraphicPos() == GPOS_NONE &&
6556                 !pOpt->IsPagePreview() &&
6557                 !pOpt->IsReadonly() &&
6558                 // --> FME 2004-06-29 #114856# Formular view
6559                 !pOpt->IsFormView() &&
6560                 // <--
6561                 SwViewOption::IsIndexShadings() &&
6562                 !pOpt->IsPDFExport() &&
6563                 pSh->GetOut()->GetOutDevType() != OUTDEV_PRINTER )
6564             {
6565                 rpCol = &SwViewOption::GetIndexShadingsColor();
6566             }
6567         }
6568 
6569         /// OD 20.08.2002 #99657#
6570         ///     determine, if background draw of frame <pFrm> considers transparency
6571         ///     --> Status Quo: background transparency have to be
6572         ///                     considered for fly frames
6573         const sal_Bool bConsiderBackgroundTransparency = pFrm->IsFlyFrm();
6574         /// OD 20.08.2002 #99657#
6575         ///     add condition:
6576         ///     If <bConsiderBackgroundTransparency> is set - see above -,
6577         ///     return brush of frame <pFrm>, if its color is *not* "no fill"/"auto fill"
6578         if ( !rBack.GetColor().GetTransparency() ||
6579              rBack.GetGraphicPos() != GPOS_NONE ||
6580              rpCol ||
6581              (bConsiderBackgroundTransparency && (rBack.GetColor() != COL_TRANSPARENT))
6582            )
6583 		{
6584 			rpBrush = &rBack;
6585             if ( pFrm->IsPageFrm() &&
6586                  pSh->GetViewOptions()->getBrowseMode() )
6587 				rOrigRect = pFrm->Frm();
6588 			else
6589 			{
6590 				if ( pFrm->Frm().SSize() != pFrm->Prt().SSize() )
6591 				{
6592 					SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
6593 					const SwBorderAttrs &rAttrs = *aAccess.Get();
6594 					::lcl_CalcBorderRect( rOrigRect, pFrm, rAttrs, sal_False );
6595 				}
6596 				else
6597 				{
6598 					rOrigRect = pFrm->Prt();
6599 					rOrigRect += pFrm->Frm().Pos();
6600 				}
6601 			}
6602 			return sal_True;
6603 		}
6604 
6605         if ( bLowerMode )
6606             /// Do not try to get background brush from parent (anchor/upper)
6607 			return sal_False;
6608 
6609         /// get parent frame - anchor or upper - for next loop
6610 		if ( pFrm->IsFlyFrm() )
6611             /// OD 20.08.2002 - use "static_cast" instead of "old C-cast"
6612             pFrm = (static_cast<const SwFlyFrm*>(pFrm))->GetAnchorFrm();
6613             ///pFrm = ((SwFlyFrm*)pFrm)->GetAnchor();
6614 		else
6615 			pFrm = pFrm->GetUpper();
6616 
6617 	} while ( pFrm );
6618 
6619     return sal_False;
6620 }
6621 
6622 /*************************************************************************
6623 |*
6624 |*	SwFrmFmt::GetGraphic()
6625 |*
6626 |*	Ersterstellung		MA 23. Jul. 96
6627 |*	Letzte Aenderung	MA 23. Jul. 96
6628 |*
6629 |*************************************************************************/
6630 
6631 void SetOutDevAndWin( ViewShell *pSh, OutputDevice *pO,
6632 					  Window *pW, sal_uInt16 nZoom )
6633 {
6634 	pSh->pOut = pO;
6635 	pSh->pWin = pW;
6636 	pSh->pOpt->SetZoom( nZoom );
6637 }
6638 
6639 Graphic SwFrmFmt::MakeGraphic( ImageMap* )
6640 {
6641 	return Graphic();
6642 }
6643 
6644 Graphic SwFlyFrmFmt::MakeGraphic( ImageMap* pMap )
6645 {
6646 	Graphic aRet;
6647 	//irgendeinen Fly suchen!
6648 	SwIterator<SwFrm,SwFmt> aIter( *this );
6649     SwFrm *pFirst = aIter.First();
6650 	ViewShell *pSh;
6651     if ( pFirst && 0 != ( pSh = pFirst->getRootFrm()->GetCurrShell()) )
6652 	{
6653 		ViewShell *pOldGlobal = pGlobalShell;
6654 		pGlobalShell = pSh;
6655 
6656 		sal_Bool bNoteURL = pMap &&
6657 			SFX_ITEM_SET != GetAttrSet().GetItemState( RES_URL, sal_True );
6658 		if( bNoteURL )
6659 		{
6660 			ASSERT( !pNoteURL, "MakeGraphic: pNoteURL already used? " );
6661 			pNoteURL = new SwNoteURL;
6662 		}
6663 		SwFlyFrm *pFly = (SwFlyFrm*)pFirst;
6664 
6665 		OutputDevice *pOld = pSh->GetOut();
6666 		VirtualDevice aDev( *pOld );
6667 		aDev.EnableOutput( sal_False );
6668 
6669 		GDIMetaFile aMet;
6670 		MapMode aMap( pOld->GetMapMode().GetMapUnit() );
6671 		aDev.SetMapMode( aMap );
6672 		aMet.SetPrefMapMode( aMap );
6673 
6674 		::SwCalcPixStatics( pSh->GetOut() );
6675 		aMet.SetPrefSize( pFly->Frm().SSize() );
6676 
6677 		aMet.Record( &aDev );
6678 		aDev.SetLineColor();
6679 		aDev.SetFillColor();
6680 		aDev.SetFont( pOld->GetFont() );
6681 
6682 		//Rechteck ggf. ausdehnen, damit die Umrandunge mit aufgezeichnet werden.
6683 		SwRect aOut( pFly->Frm() );
6684 		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFly );
6685 		const SwBorderAttrs &rAttrs = *aAccess.Get();
6686 		if ( rAttrs.CalcRightLine() )
6687 			aOut.SSize().Width() += 2*nPixelSzW;
6688 		if ( rAttrs.CalcBottomLine() )
6689 			aOut.SSize().Height()+= 2*nPixelSzH;
6690 
6691 		// #i92711# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
6692 		const Region aRepaintRegion(aOut.SVRect());
6693     	pSh->DLPrePaint2(aRepaintRegion);
6694 
6695         Window *pWin = pSh->GetWin();
6696 		sal_uInt16 nZoom = pSh->GetViewOptions()->GetZoom();
6697 		::SetOutDevAndWin( pSh, &aDev, 0, 100 );
6698 		bFlyMetafile = sal_True;
6699 		pFlyMetafileOut = pWin;
6700 
6701 		SwViewImp *pImp = pSh->Imp();
6702 		pFlyOnlyDraw = pFly;
6703 		pLines = new SwLineRects;
6704 
6705         // OD 09.12.2002 #103045# - determine page, fly frame is on
6706         const SwPageFrm* pFlyPage = pFly->FindPageFrm();
6707         const Color aPageBackgrdColor = pFlyPage->GetDrawBackgrdColor();
6708         const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
6709         // --> OD #i76669#
6710         SwViewObjectContactRedirector aSwRedirector( *pSh );
6711         // <--
6712         pImp->PaintLayer( pIDDMA->GetHellId(), 0, aOut, &aPageBackgrdColor,
6713                           (pFlyPage->IsRightToLeft() ? true : false),
6714                           &aSwRedirector );
6715 		pLines->PaintLines( &aDev );
6716 		if ( pFly->IsFlyInCntFrm() )
6717 			pFly->Paint( aOut );
6718 		pLines->PaintLines( &aDev );
6719         /// OD 30.08.2002 #102450# - add 3rd parameter
6720         pImp->PaintLayer( pIDDMA->GetHeavenId(), 0, aOut, &aPageBackgrdColor,
6721                           (pFlyPage->IsRightToLeft() ? true : false),
6722                           &aSwRedirector );
6723 		pLines->PaintLines( &aDev );
6724 		DELETEZ( pLines );
6725 		pFlyOnlyDraw = 0;
6726 
6727 		pFlyMetafileOut = 0;
6728 		bFlyMetafile = sal_False;
6729 		::SetOutDevAndWin( pSh, pOld, pWin, nZoom );
6730 
6731 		// #i92711# end Pre/PostPaint encapsulation when pOut is back and content is painted
6732    		pSh->DLPostPaint2(true);
6733 
6734         aMet.Stop();
6735 		aMet.Move( -pFly->Frm().Left(), -pFly->Frm().Top() );
6736 		aRet = Graphic( aMet );
6737 
6738 		if( bNoteURL )
6739 		{
6740 			ASSERT( pNoteURL, "MakeGraphic: Good Bye, NoteURL." );
6741 			pNoteURL->FillImageMap( pMap, pFly->Frm().Pos(), aMap );
6742 			delete pNoteURL;
6743 			pNoteURL = NULL;
6744 		}
6745 		pGlobalShell = pOldGlobal;
6746 	}
6747 	return aRet;
6748 }
6749 
6750 Graphic SwDrawFrmFmt::MakeGraphic( ImageMap* )
6751 {
6752 	Graphic aRet;
6753     SdrModel *pMod = getIDocumentDrawModelAccess()->GetDrawModel();
6754 	if ( pMod )
6755 	{
6756 		SdrObject *pObj = FindSdrObject();
6757 		SdrView *pView = new SdrView( pMod );
6758 		SdrPageView *pPgView = pView->ShowSdrPage(pView->GetModel()->GetPage(0));
6759 		pView->MarkObj( pObj, pPgView );
6760 		aRet = pView->GetMarkedObjBitmap();
6761 		pView->HideSdrPage();
6762 		delete pView;
6763 	}
6764 	return aRet;
6765 }
6766 
6767 
6768