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