Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <vcl/lazydelete.hxx>
21 : #include <sfx2/docfile.hxx>
22 : #include <sfx2/progress.hxx>
23 : #include <editeng/brushitem.hxx>
24 : #include <editeng/prntitem.hxx>
25 : #include <editeng/boxitem.hxx>
26 : #include <editeng/shaditem.hxx>
27 : #include <svx/framelink.hxx>
28 : #include <drawdoc.hxx>
29 : #include <tgrditem.hxx>
30 : #include <calbck.hxx>
31 : #include <fmtsrnd.hxx>
32 : #include <fmtclds.hxx>
33 : #include <comcore.hrc>
34 : #include <swmodule.hxx>
35 : #include <rootfrm.hxx>
36 : #include <pagefrm.hxx>
37 : #include <section.hxx>
38 : #include <sectfrm.hxx>
39 : #include <viewimp.hxx>
40 : #include <dflyobj.hxx>
41 : #include <flyfrm.hxx>
42 : #include <viewopt.hxx>
43 : #include <dview.hxx>
44 : #include <dcontact.hxx>
45 : #include <txtfrm.hxx>
46 : #include <ftnfrm.hxx>
47 : #include <tabfrm.hxx>
48 : #include <rowfrm.hxx>
49 : #include <cellfrm.hxx>
50 : #include <notxtfrm.hxx>
51 : #include <layact.hxx>
52 : #include <pagedesc.hxx>
53 : #include <ptqueue.hxx>
54 : #include <noteurl.hxx>
55 : #include <virtoutp.hxx>
56 : #include <lineinfo.hxx>
57 : #include <dbg_lay.hxx>
58 : #include <docsh.hxx>
59 : #include <svx/svdogrp.hxx>
60 : #include <sortedobjs.hxx>
61 : #include <EnhancedPDFExportHelper.hxx>
62 : #include <bodyfrm.hxx>
63 : #include <hffrm.hxx>
64 : #include <colfrm.hxx>
65 : #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
66 : #include <svx/sdr/contact/viewobjectcontact.hxx>
67 : #include <svx/sdr/contact/viewcontact.hxx>
68 : #include <DocumentSettingManager.hxx>
69 : #include <IDocumentDeviceAccess.hxx>
70 :
71 : #include <ndole.hxx>
72 : #include <PostItMgr.hxx>
73 : #include <vcl/settings.hxx>
74 :
75 : #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
76 : #include <drawinglayer/processor2d/processor2dtools.hxx>
77 :
78 : #include <svtools/borderhelper.hxx>
79 :
80 : #include "pagefrm.hrc"
81 : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
82 : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
83 : #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
84 : #include <drawinglayer/primitive2d/discreteshadowprimitive2d.hxx>
85 : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
86 : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
87 : #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
88 : #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
89 : #include <svx/unoapi.hxx>
90 : #include <comphelper/sequence.hxx>
91 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
92 : #include <basegfx/color/bcolortools.hxx>
93 :
94 : #include <vector>
95 : #include <algorithm>
96 : #include <wrtsh.hxx>
97 : #include <edtwin.hxx>
98 : #include <view.hxx>
99 : #include <paintfrm.hxx>
100 :
101 : #define COL_NOTES_SIDEPANE RGB_COLORDATA(230,230,230)
102 : #define COL_NOTES_SIDEPANE_BORDER RGB_COLORDATA(200,200,200)
103 : #define COL_NOTES_SIDEPANE_SCROLLAREA RGB_COLORDATA(230,230,220)
104 :
105 : using namespace ::editeng;
106 : using namespace ::com::sun::star;
107 : using ::drawinglayer::primitive2d::BorderLinePrimitive2D;
108 : using ::std::pair;
109 : using ::std::make_pair;
110 :
111 : struct SwPaintProperties;
112 :
113 : //other subsidiary lines enabled?
114 : #define IS_SUBS (!gProp.pSGlobalShell->GetViewOptions()->IsPagePreview() && \
115 : !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() && \
116 : !gProp.pSGlobalShell->GetViewOptions()->IsFormView() &&\
117 : SwViewOption::IsDocBoundaries())
118 : //subsidiary lines for sections
119 : #define IS_SUBS_SECTION (!gProp.pSGlobalShell->GetViewOptions()->IsPagePreview() && \
120 : !gProp.pSGlobalShell->GetViewOptions()->IsReadonly()&&\
121 : !gProp.pSGlobalShell->GetViewOptions()->IsFormView() &&\
122 : SwViewOption::IsSectionBoundaries())
123 : #define IS_SUBS_FLYS (!gProp.pSGlobalShell->GetViewOptions()->IsPagePreview() && \
124 : !gProp.pSGlobalShell->GetViewOptions()->IsReadonly()&&\
125 : !gProp.pSGlobalShell->GetViewOptions()->IsFormView() &&\
126 : SwViewOption::IsObjectBoundaries())
127 :
128 : //Class declaration; here because they are only used in this file
129 :
130 : #define SUBCOL_PAGE 0x01 //Helplines of the page
131 : #define SUBCOL_TAB 0x08 //Helplines inside tables
132 : #define SUBCOL_FLY 0x10 //Helplines inside fly frames
133 : #define SUBCOL_SECT 0x20 //Helplines inside sections
134 :
135 : // Classes collecting the border lines and help lines
136 3664 : class SwLineRect : public SwRect
137 : {
138 : Color aColor;
139 : SvxBorderStyle nStyle;
140 : const SwTabFrm *pTab;
141 : sal_uInt8 nSubColor; //colorize subsidiary lines
142 : bool bPainted; //already painted?
143 : sal_uInt8 nLock; //To distinguish the line and the hell layer.
144 : public:
145 : SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyle,
146 : const SwTabFrm *pT , const sal_uInt8 nSCol );
147 :
148 2 : const Color& GetColor() const { return aColor;}
149 2 : SvxBorderStyle GetStyle() const { return nStyle; }
150 8101 : const SwTabFrm *GetTab() const { return pTab; }
151 1889 : void SetPainted() { bPainted = true; }
152 2530 : void Lock( bool bLock ) { if ( bLock )
153 1044 : ++nLock;
154 1486 : else if ( nLock )
155 1042 : --nLock;
156 2530 : }
157 11483 : bool IsPainted() const { return bPainted; }
158 2677 : bool IsLocked() const { return nLock != 0; }
159 8857 : sal_uInt8 GetSubColor() const { return nSubColor;}
160 :
161 : bool MakeUnion( const SwRect &rRect, SwPaintProperties &properties );
162 : };
163 :
164 : #ifdef IOS
165 : static void dummy_function()
166 : {
167 : pid_t pid = getpid();
168 : (void) pid;
169 : }
170 : #endif
171 :
172 27525 : class SwLineRects
173 : {
174 : public:
175 : std::vector< SwLineRect > aLineRects;
176 : typedef std::vector< SwLineRect >::const_iterator const_iterator;
177 : typedef std::vector< SwLineRect >::iterator iterator;
178 : typedef std::vector< SwLineRect >::reverse_iterator reverse_iterator;
179 : typedef std::vector< SwLineRect >::size_type size_type;
180 : size_t nLastCount; //avoid unnecessary cycles in PaintLines
181 27525 : SwLineRects() : nLastCount( 0 )
182 : {
183 : #ifdef IOS
184 : // Work around what is either a compiler bug in Xcode 5.1.1,
185 : // or some unknown problem in this file. If I ifdef out this
186 : // call, I get a crash in SwSubsRects::PaintSubsidiary: the
187 : // address of the rLi reference variable is claimed to be
188 : // 0x4000000!
189 : dummy_function();
190 : #endif
191 27525 : }
192 : void AddLineRect( const SwRect& rRect, const Color *pColor, const SvxBorderStyle nStyle,
193 : const SwTabFrm *pTab, const sal_uInt8 nSCol, SwPaintProperties &properties );
194 : void ConnectEdges( OutputDevice *pOut, SwPaintProperties &properties );
195 : void PaintLines ( OutputDevice *pOut, SwPaintProperties &properties );
196 : void LockLines( bool bLock );
197 :
198 : //Limit lines to 100
199 0 : bool isFull() const { return aLineRects.size()>100; }
200 : };
201 :
202 36548 : class SwSubsRects : public SwLineRects
203 : {
204 : void RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects, SwPaintProperties &properties );
205 : public:
206 : void PaintSubsidiary( OutputDevice *pOut, const SwLineRects *pRects, SwPaintProperties &properties );
207 : };
208 :
209 19388 : class BorderLines
210 : {
211 : typedef ::std::vector<
212 : ::rtl::Reference<BorderLinePrimitive2D> > Lines_t;
213 : Lines_t m_Lines;
214 : public:
215 : void AddBorderLine(::rtl::Reference<BorderLinePrimitive2D> const& xLine, SwPaintProperties& properties);
216 9694 : drawinglayer::primitive2d::Primitive2DSequence GetBorderLines_Clear()
217 : {
218 : ::std::vector<
219 9694 : ::drawinglayer::primitive2d::Primitive2DReference> lines;
220 10301 : for (Lines_t::const_iterator it = m_Lines.begin(); it != m_Lines.end();
221 : ++it)
222 : {
223 607 : lines.push_back(it->get());
224 : }
225 9694 : m_Lines.clear();
226 9694 : return comphelper::containerToSequence(lines);
227 : }
228 : };
229 :
230 : // Default zoom factor
231 : const static double aMinDistScale = 0.73;
232 : const static double aEdgeScale = 0.5;
233 :
234 : //To optimize the expensive RetouchColor determination
235 59 : Color aGlobalRetoucheColor;
236 :
237 : /**
238 : * Container for static properties
239 : */
240 59 : struct SwPaintProperties {
241 : // Only repaint the Fly content as well as the background of the Fly content if
242 : // a metafile is taken of the Fly.
243 : bool bSFlyMetafile;
244 : VclPtr<OutputDevice> pSFlyMetafileOut;
245 : SwViewShell *pSGlobalShell;
246 :
247 : // Retouch for transparent Flys is done by the background of the Flys.
248 : // The Fly itself should certainly not be spared out. See PaintBackground and
249 : // lcl_SubtractFlys()
250 : SwFlyFrm *pSRetoucheFly;
251 : SwFlyFrm *pSRetoucheFly2;
252 : SwFlyFrm *pSFlyOnlyDraw;
253 :
254 : // The borders will be collected in pSLines during the Paint and later
255 : // possibly merge them.
256 : // The help lines will be collected and merged in gProp.pSSubsLines. These will
257 : // be compared with pSLines before the work in order to avoid help lines
258 : // to hide borders.
259 : BorderLines *pBLines;
260 : SwLineRects *pSLines;
261 : SwSubsRects *pSSubsLines;
262 :
263 : // global variable for sub-lines of body, header, footer, section and footnote frames.
264 : SwSubsRects *pSSpecSubsLines;
265 : SfxProgress *pSProgress;
266 :
267 : // Sizes of a pixel and the corresponding halves. Will be reset when
268 : // entering SwRootFrm::Paint
269 : long nSPixelSzW;
270 : long nSPixelSzH;
271 : long nSHalfPixelSzW;
272 : long nSHalfPixelSzH;
273 : long nSMinDistPixelW;
274 : long nSMinDistPixelH;
275 :
276 : Color aSGlobalRetoucheColor;
277 :
278 : // Current zoom factor
279 : double aSScaleX;
280 : double aSScaleY;
281 :
282 59 : SwPaintProperties()
283 : : bSFlyMetafile(false)
284 : , pSFlyMetafileOut(0)
285 : , pSGlobalShell(0)
286 : , pSRetoucheFly(0)
287 : , pSRetoucheFly2(0)
288 : , pSFlyOnlyDraw(0)
289 : , pBLines(0)
290 : , pSLines(0)
291 : , pSSubsLines(0)
292 : , pSSpecSubsLines(0)
293 : , pSProgress(0)
294 : , nSPixelSzW(0)
295 : , nSPixelSzH(0)
296 : , nSHalfPixelSzW(0)
297 : , nSHalfPixelSzH(0)
298 : , nSMinDistPixelW(0)
299 : , nSMinDistPixelH(0)
300 : , aSScaleX(1)
301 59 : , aSScaleY(1)
302 : {
303 59 : }
304 :
305 : };
306 :
307 59 : static SwPaintProperties gProp;
308 :
309 : namespace {
310 :
311 646 : bool isTableBoundariesEnabled()
312 : {
313 646 : if (!gProp.pSGlobalShell->GetViewOptions()->IsTable())
314 15 : return false;
315 :
316 631 : if (gProp.pSGlobalShell->GetViewOptions()->IsPagePreview())
317 0 : return false;
318 :
319 631 : if (gProp.pSGlobalShell->GetViewOptions()->IsReadonly())
320 5 : return false;
321 :
322 626 : if (gProp.pSGlobalShell->GetViewOptions()->IsFormView())
323 0 : return false;
324 :
325 626 : return SwViewOption::IsTableBoundaries();
326 : }
327 :
328 : }
329 :
330 : /**
331 : * Set borders alignment statics
332 : * Adjustment for 'small' twip-to-pixel relations:
333 : * For 'small' twip-to-pixel relations (less then 2:1)
334 : * values of <gProp.nSHalfPixelSzW> and <gProp.nSHalfPixelSzH> are set to ZERO
335 : */
336 62629 : void SwCalcPixStatics( vcl::RenderContext *pOut )
337 : {
338 : // determine 'small' twip-to-pixel relation
339 62629 : bool bSmallTwipToPxRelW = false;
340 62629 : bool bSmallTwipToPxRelH = false;
341 : {
342 62629 : Size aCheckTwipToPxRelSz( pOut->PixelToLogic( Size( 100, 100 )) );
343 62629 : if ( (aCheckTwipToPxRelSz.Width()/100.0) < 2.0 )
344 : {
345 43 : bSmallTwipToPxRelW = true;
346 : }
347 62629 : if ( (aCheckTwipToPxRelSz.Height()/100.0) < 2.0 )
348 : {
349 43 : bSmallTwipToPxRelH = true;
350 : }
351 : }
352 :
353 62629 : Size aSz( pOut->PixelToLogic( Size( 1,1 )) );
354 :
355 62629 : gProp.nSPixelSzW = aSz.Width();
356 62629 : if( !gProp.nSPixelSzW )
357 0 : gProp.nSPixelSzW = 1;
358 62629 : gProp.nSPixelSzH = aSz.Height();
359 62629 : if( !gProp.nSPixelSzH )
360 0 : gProp.nSPixelSzH = 1;
361 :
362 : // consider 'small' twip-to-pixel relations
363 62629 : if ( !bSmallTwipToPxRelW )
364 : {
365 62586 : gProp.nSHalfPixelSzW = gProp.nSPixelSzW / 2 + 1;
366 : }
367 : else
368 : {
369 43 : gProp.nSHalfPixelSzW = 0;
370 : }
371 : // consider 'small' twip-to-pixel relations
372 62629 : if ( !bSmallTwipToPxRelH )
373 : {
374 62586 : gProp.nSHalfPixelSzH = gProp.nSPixelSzH / 2 + 1;
375 : }
376 : else
377 : {
378 43 : gProp.nSHalfPixelSzH = 0;
379 : }
380 :
381 62629 : gProp.nSMinDistPixelW = gProp.nSPixelSzW * 2 + 1;
382 62629 : gProp.nSMinDistPixelH = gProp.nSPixelSzH * 2 + 1;
383 :
384 62629 : const MapMode &rMap = pOut->GetMapMode();
385 62629 : gProp.aSScaleX = rMap.GetScaleX();
386 62629 : gProp.aSScaleY = rMap.GetScaleY();
387 62629 : }
388 :
389 : /**
390 : * To be able to save the statics so the paint is more or less reentrant
391 : */
392 : class SwSavePaintStatics : public SwPaintProperties
393 : {
394 : public:
395 : SwSavePaintStatics();
396 : ~SwSavePaintStatics();
397 : };
398 :
399 0 : SwSavePaintStatics::SwSavePaintStatics()
400 : {
401 : // Saving globales
402 0 : bSFlyMetafile = gProp.bSFlyMetafile;
403 0 : pSGlobalShell = gProp.pSGlobalShell;
404 0 : pSFlyMetafileOut = gProp.pSFlyMetafileOut;
405 0 : pSRetoucheFly = gProp.pSRetoucheFly;
406 0 : pSRetoucheFly2 = gProp.pSRetoucheFly2;
407 0 : pSFlyOnlyDraw = gProp.pSFlyOnlyDraw;
408 0 : pBLines = gProp.pBLines;
409 0 : pSLines = gProp.pSLines;
410 0 : pSSubsLines = gProp.pSSubsLines;
411 0 : pSSpecSubsLines = gProp.pSSpecSubsLines;
412 0 : pSProgress = gProp.pSProgress;
413 0 : nSPixelSzW = gProp.nSPixelSzW;
414 0 : nSPixelSzH = gProp.nSPixelSzH;
415 0 : nSHalfPixelSzW = gProp.nSHalfPixelSzW;
416 0 : nSHalfPixelSzH = gProp.nSHalfPixelSzH;
417 0 : nSMinDistPixelW = gProp.nSMinDistPixelW;
418 0 : nSMinDistPixelH = gProp.nSMinDistPixelH ;
419 0 : aSGlobalRetoucheColor = aGlobalRetoucheColor;
420 0 : aSScaleX = gProp.aSScaleX;
421 0 : aSScaleY = gProp.aSScaleY;
422 :
423 : // Restoring globales to default
424 0 : gProp.bSFlyMetafile = false;
425 0 : gProp.pSFlyMetafileOut = 0;
426 0 : gProp.pSRetoucheFly = 0;
427 0 : gProp.pSRetoucheFly2 = 0;
428 : gProp.nSPixelSzW = gProp.nSPixelSzH =
429 : gProp.nSHalfPixelSzW = gProp.nSHalfPixelSzH =
430 0 : gProp.nSMinDistPixelW = gProp.nSMinDistPixelH = 0;
431 0 : gProp.aSScaleX = gProp.aSScaleY = 1.0;
432 0 : gProp.pBLines = 0;
433 0 : gProp.pSLines = 0;
434 0 : gProp.pSSubsLines = 0;
435 0 : gProp.pSSpecSubsLines = 0L;
436 0 : gProp.pSProgress = 0;
437 0 : }
438 :
439 0 : SwSavePaintStatics::~SwSavePaintStatics()
440 : {
441 : // Restoring globales to saved one
442 0 : gProp.pSGlobalShell = pSGlobalShell;
443 0 : gProp.bSFlyMetafile = bSFlyMetafile;
444 0 : gProp.pSFlyMetafileOut = pSFlyMetafileOut;
445 0 : gProp.pSRetoucheFly = pSRetoucheFly;
446 0 : gProp.pSRetoucheFly2 = pSRetoucheFly2;
447 0 : gProp.pSFlyOnlyDraw = pSFlyOnlyDraw;
448 0 : gProp.pBLines = pBLines;
449 0 : gProp.pSLines = pSLines;
450 0 : gProp.pSSubsLines = pSSubsLines;
451 0 : gProp.pSSpecSubsLines = pSSpecSubsLines;
452 0 : gProp.pSProgress = pSProgress;
453 0 : gProp.nSPixelSzW = nSPixelSzW;
454 0 : gProp.nSPixelSzH = nSPixelSzH;
455 0 : gProp.nSHalfPixelSzW = nSHalfPixelSzW;
456 0 : gProp.nSHalfPixelSzH = nSHalfPixelSzH;
457 0 : gProp.nSMinDistPixelW = nSMinDistPixelW;
458 0 : gProp.nSMinDistPixelH = nSMinDistPixelH;
459 0 : aGlobalRetoucheColor = aSGlobalRetoucheColor;
460 0 : gProp.aSScaleX = aSScaleX;
461 0 : gProp.aSScaleY = aSScaleY;
462 0 : }
463 :
464 : /**
465 : * Check whether the two primitve can be merged
466 : *
467 : * @param[in] mergeA A primitive start and end position
468 : * @param[in] mergeB B primitive start and end position
469 : * @return 1 if A and B can be merged to a primite staring with A, ending with B
470 : * 2 if A and B can be merged to a primite staring with B, ending with A
471 : * 0 if A and B can't be merged
472 : **/
473 46 : static sal_uInt8 lcl_TryMergeLines(
474 : pair<double, double> const& mergeA,
475 : pair<double, double> const& mergeB,
476 : SwPaintProperties& properties)
477 : {
478 46 : double const fMergeGap(properties.nSPixelSzW + properties.nSHalfPixelSzW); // NOT static!
479 : // A is above/before B
480 88 : if( mergeA.second <= mergeB.second &&
481 42 : mergeA.second + fMergeGap >= mergeB.first )
482 : {
483 33 : return 1;
484 : }
485 : // B is above/before A
486 17 : else if( mergeB.second <= mergeA.second &&
487 4 : mergeB.second + fMergeGap >= mergeA.first )
488 : {
489 4 : return 2;
490 : }
491 9 : return 0;
492 : }
493 :
494 : /**
495 : * Make a new primitive from the two input borderline primitive
496 : *
497 : * @param[in] rLine starting primitive
498 : * @param[in] rOther ending primitive
499 : * @param[in] rStart starting point of merged primitive
500 : * @param[in] rEnd ending point of merged primitive
501 : * @return merged primitive
502 : **/
503 : static ::rtl::Reference<BorderLinePrimitive2D>
504 37 : lcl_MergeBorderLines(
505 : BorderLinePrimitive2D const& rLine, BorderLinePrimitive2D const& rOther,
506 : basegfx::B2DPoint const& rStart, basegfx::B2DPoint const& rEnd)
507 : {
508 : return new BorderLinePrimitive2D(rStart, rEnd,
509 : rLine.getLeftWidth(),
510 : rLine.getDistance(),
511 : rLine.getRightWidth(),
512 : rLine.getExtendLeftStart(),
513 : rOther.getExtendLeftEnd(),
514 : rLine.getExtendRightStart(),
515 : rOther.getExtendRightEnd(),
516 : rLine.getRGBColorLeft(),
517 : rLine.getRGBColorGap(),
518 : rLine.getRGBColorRight(),
519 37 : rLine.hasGapColor(),
520 74 : rLine.getStyle());
521 : }
522 :
523 : /**
524 : * Merge the two borderline if possible.
525 : *
526 : * @param[in] rThis one borderline primitive
527 : * @param[in] rOther other borderline primitive
528 : * @return merged borderline including the two input primitive, if they can be merged
529 : * 0, otherwise
530 : **/
531 : static ::rtl::Reference<BorderLinePrimitive2D>
532 1444 : lcl_TryMergeBorderLine(BorderLinePrimitive2D const& rThis,
533 : BorderLinePrimitive2D const& rOther,
534 : SwPaintProperties& properties)
535 : {
536 : assert(rThis.getEnd().getX() >= rThis.getStart().getX());
537 : assert(rThis.getEnd().getY() >= rThis.getStart().getY());
538 : assert(rOther.getEnd().getX() >= rOther.getStart().getX());
539 : assert(rOther.getEnd().getY() >= rOther.getStart().getY());
540 1444 : double thisHeight = rThis.getEnd().getY() - rThis.getStart().getY();
541 1444 : double thisWidth = rThis.getEnd().getX() - rThis.getStart().getX();
542 1444 : double otherHeight = rOther.getEnd().getY() - rOther.getStart().getY();
543 1444 : double otherWidth = rOther.getEnd().getX() - rOther.getStart().getX();
544 : // check for same orientation, same line width, same style and matching colors
545 2888 : if ( ((thisHeight > thisWidth) == (otherHeight > otherWidth))
546 594 : && (rThis.getLeftWidth() == rOther.getLeftWidth())
547 445 : && (rThis.getDistance() == rOther.getDistance())
548 405 : && (rThis.getRightWidth() == rOther.getRightWidth())
549 405 : && (rThis.getStyle() == rOther.getStyle())
550 401 : && (rThis.getRGBColorLeft() == rOther.getRGBColorLeft())
551 401 : && (rThis.getRGBColorRight() == rOther.getRGBColorRight())
552 401 : && (rThis.hasGapColor() == rOther.hasGapColor())
553 1845 : && (!rThis.hasGapColor() ||
554 0 : (rThis.getRGBColorGap() == rOther.getRGBColorGap())))
555 : {
556 401 : int nRet = 0;
557 401 : if (thisHeight > thisWidth) // vertical line
558 : {
559 182 : if (rThis.getStart().getX() == rOther.getStart().getX())
560 : {
561 : assert(rThis.getEnd().getX() == rOther.getEnd().getX());
562 : nRet = lcl_TryMergeLines(
563 44 : make_pair(rThis.getStart().getY(), rThis.getEnd().getY()),
564 44 : make_pair(rOther.getStart().getY(),rOther.getEnd().getY()),
565 66 : properties);
566 : }
567 : }
568 : else // horizontal line
569 : {
570 219 : if (rThis.getStart().getY() == rOther.getStart().getY())
571 : {
572 : assert(rThis.getEnd().getY() == rOther.getEnd().getY());
573 : nRet = lcl_TryMergeLines(
574 48 : make_pair(rThis.getStart().getX(), rThis.getEnd().getX()),
575 48 : make_pair(rOther.getStart().getX(),rOther.getEnd().getX()),
576 72 : properties);
577 : }
578 : }
579 :
580 : // The merged primitive starts with rThis and ends with rOther
581 401 : if (nRet == 1)
582 : {
583 : basegfx::B2DPoint const start(
584 33 : rThis.getStart().getX(), rThis.getStart().getY());
585 : basegfx::B2DPoint const end(
586 66 : rOther.getEnd().getX(), rOther.getEnd().getY());
587 66 : return lcl_MergeBorderLines(rThis, rOther, start, end);
588 : }
589 : // The merged primitive starts with rOther and ends with rThis
590 368 : else if(nRet == 2)
591 : {
592 : basegfx::B2DPoint const start(
593 4 : rOther.getStart().getX(), rOther.getStart().getY());
594 : basegfx::B2DPoint const end(
595 8 : rThis.getEnd().getX(), rThis.getEnd().getY());
596 8 : return lcl_MergeBorderLines(rOther, rThis, start, end);
597 : }
598 : }
599 1407 : return 0;
600 : }
601 :
602 644 : void BorderLines::AddBorderLine(
603 : rtl::Reference<BorderLinePrimitive2D> const& xLine, SwPaintProperties& properties)
604 : {
605 2051 : for (Lines_t::reverse_iterator it = m_Lines.rbegin(); it != m_Lines.rend();
606 : ++it)
607 : {
608 : ::rtl::Reference<BorderLinePrimitive2D> const xMerged =
609 1444 : lcl_TryMergeBorderLine(**it, *xLine, properties);
610 1444 : if (xMerged.is())
611 : {
612 37 : *it = xMerged; // replace existing line with merged
613 681 : return;
614 : }
615 1407 : }
616 607 : m_Lines.push_back(xLine);
617 : }
618 :
619 1905 : SwLineRect::SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyl,
620 : const SwTabFrm *pT, const sal_uInt8 nSCol ) :
621 : SwRect( rRect ),
622 : nStyle( nStyl ),
623 : pTab( pT ),
624 : nSubColor( nSCol ),
625 : bPainted( false ),
626 1905 : nLock( 0 )
627 : {
628 1905 : if ( pCol != NULL )
629 2 : aColor = *pCol;
630 1905 : }
631 :
632 0 : bool SwLineRect::MakeUnion( const SwRect &rRect, SwPaintProperties& properties)
633 : {
634 : // It has already been tested outside, whether the rectangles have
635 : // the same orientation (horizontal or vertical), color, etc.
636 0 : if ( Height() > Width() ) //Vertical line
637 : {
638 0 : if ( Left() == rRect.Left() && Width() == rRect.Width() )
639 : {
640 : // Merge when there is no gap between the lines
641 0 : const long nAdd = properties.nSPixelSzW + properties.nSHalfPixelSzW;
642 0 : if ( Bottom() + nAdd >= rRect.Top() &&
643 0 : Top() - nAdd <= rRect.Bottom() )
644 : {
645 0 : Bottom( std::max( Bottom(), rRect.Bottom() ) );
646 0 : Top ( std::min( Top(), rRect.Top() ) );
647 0 : return true;
648 : }
649 : }
650 : }
651 : else
652 : {
653 0 : if ( Top() == rRect.Top() && Height() == rRect.Height() )
654 : {
655 : // Merge when there is no gap between the lines
656 0 : const long nAdd = properties.nSPixelSzW + properties.nSHalfPixelSzW;
657 0 : if ( Right() + nAdd >= rRect.Left() &&
658 0 : Left() - nAdd <= rRect.Right() )
659 : {
660 0 : Right( std::max( Right(), rRect.Right() ) );
661 0 : Left ( std::min( Left(), rRect.Left() ) );
662 0 : return true;
663 : }
664 : }
665 : }
666 0 : return false;
667 : }
668 :
669 1905 : void SwLineRects::AddLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyle,
670 : const SwTabFrm *pTab, const sal_uInt8 nSCol, SwPaintProperties& properties )
671 : {
672 : // Loop backwards because lines which can be combined, can usually be painted
673 : // in the same context
674 10000 : for (reverse_iterator it = aLineRects.rbegin(); it != aLineRects.rend();
675 : ++it)
676 : {
677 8095 : SwLineRect &rLRect = (*it);
678 : // Test for the orientation, color, table
679 24285 : if ( rLRect.GetTab() == pTab &&
680 22035 : !rLRect.IsPainted() && rLRect.GetSubColor() == nSCol &&
681 18100 : (rLRect.Height() > rLRect.Width()) == (rRect.Height() > rRect.Width()) &&
682 0 : (pCol && rLRect.GetColor() == *pCol) )
683 : {
684 0 : if ( rLRect.MakeUnion( rRect, properties ) )
685 1905 : return;
686 : }
687 : }
688 3810 : aLineRects.push_back( SwLineRect( rRect, pCol, nStyle, pTab, nSCol ) );
689 : }
690 :
691 4 : void SwLineRects::ConnectEdges( OutputDevice *pOut, SwPaintProperties& properties )
692 : {
693 4 : if ( pOut->GetOutDevType() != OUTDEV_PRINTER )
694 : {
695 : // I'm not doing anything for a too small zoom
696 4 : if ( properties.aSScaleX < aEdgeScale || properties.aSScaleY < aEdgeScale )
697 4 : return;
698 : }
699 :
700 : static const long nAdd = 20;
701 :
702 4 : std::vector<SwLineRect*> aCheck;
703 :
704 8 : for (size_t i = 0; i < aLineRects.size(); ++i)
705 : {
706 4 : SwLineRect &rL1 = aLineRects[i];
707 4 : if ( !rL1.GetTab() || rL1.IsPainted() || rL1.IsLocked() )
708 4 : continue;
709 :
710 0 : aCheck.clear();
711 :
712 0 : const bool bVert = rL1.Height() > rL1.Width();
713 : long nL1a, nL1b, nL1c, nL1d;
714 :
715 0 : if ( bVert )
716 : {
717 0 : nL1a = rL1.Top(); nL1b = rL1.Left();
718 0 : nL1c = rL1.Right(); nL1d = rL1.Bottom();
719 : }
720 : else
721 : {
722 0 : nL1a = rL1.Left(); nL1b = rL1.Top();
723 0 : nL1c = rL1.Bottom(); nL1d = rL1.Right();
724 : }
725 :
726 : // Collect all lines to possibly link with i1
727 0 : for (iterator it2 = aLineRects.begin(); it2 != aLineRects.end(); ++it2)
728 : {
729 0 : SwLineRect &rL2 = (*it2);
730 0 : if ( rL2.GetTab() != rL1.GetTab() ||
731 0 : rL2.IsPainted() ||
732 0 : rL2.IsLocked() ||
733 0 : (bVert == (rL2.Height() > rL2.Width())) )
734 0 : continue;
735 :
736 : long nL2a, nL2b, nL2c, nL2d;
737 0 : if ( bVert )
738 : {
739 0 : nL2a = rL2.Top(); nL2b = rL2.Left();
740 0 : nL2c = rL2.Right(); nL2d = rL2.Bottom();
741 : }
742 : else
743 : {
744 0 : nL2a = rL2.Left(); nL2b = rL2.Top();
745 0 : nL2c = rL2.Bottom(); nL2d = rL2.Right();
746 : }
747 :
748 0 : if ( (nL1a - nAdd < nL2d && nL1d + nAdd > nL2a) &&
749 0 : ((nL1b > nL2b && nL1c < nL2c) ||
750 0 : (nL1c >= nL2c && nL1b - nAdd < nL2c) ||
751 0 : (nL1b <= nL2b && nL1c + nAdd > nL2b)) )
752 : {
753 0 : aCheck.push_back( &rL2 );
754 : }
755 : }
756 0 : if ( aCheck.size() < 2 )
757 0 : continue;
758 :
759 0 : bool bRemove = false;
760 :
761 : // For each line test all following ones.
762 0 : for ( size_t k = 0; !bRemove && k < aCheck.size(); ++k )
763 : {
764 0 : SwLineRect &rR1 = *aCheck[k];
765 :
766 0 : for ( size_t k2 = k+1; !bRemove && k2 < aCheck.size(); ++k2 )
767 : {
768 0 : SwLineRect &rR2 = *aCheck[k2];
769 0 : if ( bVert )
770 : {
771 0 : SwLineRect *pLA = 0;
772 0 : SwLineRect *pLB = 0;
773 0 : if ( rR1.Top() < rR2.Top() )
774 : {
775 0 : pLA = &rR1; pLB = &rR2;
776 : }
777 0 : else if ( rR1.Top() > rR2.Top() )
778 : {
779 0 : pLA = &rR2; pLB = &rR1;
780 : }
781 : // are k1 and k2 describing a double line?
782 0 : if ( pLA && pLA->Bottom() + 60 > pLB->Top() )
783 : {
784 0 : if ( rL1.Top() < pLA->Top() )
785 : {
786 0 : if ( rL1.Bottom() == pLA->Bottom() )
787 0 : continue; //Small mistake (where?)
788 :
789 0 : SwRect aIns( rL1 );
790 0 : aIns.Bottom( pLA->Bottom() );
791 0 : if ( !rL1.IsInside( aIns ) )
792 0 : continue;
793 0 : aLineRects.push_back( SwLineRect( aIns, &rL1.GetColor(),
794 : table::BorderLineStyle::SOLID,
795 0 : rL1.GetTab(), SUBCOL_TAB ) );
796 0 : if ( isFull() )
797 : {
798 0 : --i;
799 0 : k = aCheck.size();
800 0 : break;
801 : }
802 : }
803 :
804 0 : if ( rL1.Bottom() > pLB->Bottom() )
805 0 : rL1.Top( pLB->Top() ); // extend i1 on the top
806 : else
807 0 : bRemove = true; //stopping, remove i1
808 : }
809 : }
810 : else
811 : {
812 0 : SwLineRect *pLA = 0;
813 0 : SwLineRect *pLB = 0;
814 0 : if ( rR1.Left() < rR2.Left() )
815 : {
816 0 : pLA = &rR1; pLB = &rR2;
817 : }
818 0 : else if ( rR1.Left() > rR2.Left() )
819 : {
820 0 : pLA = &rR2; pLB = &rR1;
821 : }
822 : // Is it double line?
823 0 : if ( pLA && pLA->Right() + 60 > pLB->Left() )
824 : {
825 0 : if ( rL1.Left() < pLA->Left() )
826 : {
827 0 : if ( rL1.Right() == pLA->Right() )
828 0 : continue; //small error
829 :
830 0 : SwRect aIns( rL1 );
831 0 : aIns.Right( pLA->Right() );
832 0 : if ( !rL1.IsInside( aIns ) )
833 0 : continue;
834 0 : aLineRects.push_back( SwLineRect( aIns, &rL1.GetColor(),
835 : table::BorderLineStyle::SOLID,
836 0 : rL1.GetTab(), SUBCOL_TAB ) );
837 0 : if ( isFull() )
838 : {
839 0 : --i;
840 0 : k = aCheck.size();
841 0 : break;
842 : }
843 : }
844 0 : if ( rL1.Right() > pLB->Right() )
845 0 : rL1.Left( pLB->Left() );
846 : else
847 0 : bRemove = true;
848 : }
849 : }
850 : }
851 : }
852 0 : if ( bRemove )
853 : {
854 0 : aLineRects.erase(aLineRects.begin() + i);
855 0 : --i;
856 : }
857 4 : }
858 : }
859 :
860 2 : void SwSubsRects::RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects, SwPaintProperties& properties )
861 : {
862 : // All help lines that are covered by any border will be removed or split
863 18 : for (size_t i = 0; i < aLineRects.size(); ++i)
864 : {
865 : // get a copy instead of a reference, because an <insert> may destroy
866 : // the object due to a necessary array resize.
867 16 : const SwLineRect aSubsLineRect = SwLineRect(aLineRects[i]);
868 :
869 : // add condition <aSubsLineRect.IsLocked()> in order to consider only
870 : // border lines, which are *not* locked.
871 28 : if ( aSubsLineRect.IsPainted() ||
872 12 : aSubsLineRect.IsLocked() )
873 8 : continue;
874 :
875 8 : const bool bVerticalSubs = aSubsLineRect.Height() > aSubsLineRect.Width();
876 8 : SwRect aSubsRect( aSubsLineRect );
877 8 : if ( bVerticalSubs )
878 : {
879 4 : aSubsRect.Left ( aSubsRect.Left() - (properties.nSPixelSzW+properties.nSHalfPixelSzW) );
880 4 : aSubsRect.Right ( aSubsRect.Right() + (properties.nSPixelSzW+properties.nSHalfPixelSzW) );
881 : }
882 : else
883 : {
884 4 : aSubsRect.Top ( aSubsRect.Top() - (properties.nSPixelSzH+properties.nSHalfPixelSzH) );
885 4 : aSubsRect.Bottom( aSubsRect.Bottom() + (properties.nSPixelSzH+properties.nSHalfPixelSzH) );
886 : }
887 16 : for (const_iterator itK = rRects.aLineRects.begin(); itK != rRects.aLineRects.end(); ++itK)
888 : {
889 8 : const SwLineRect &rLine = *itK;
890 :
891 : // do *not* consider painted or locked border lines.
892 : // #i1837# - locked border lines have to be considered.
893 8 : if ( rLine.IsLocked () )
894 4 : continue;
895 :
896 4 : if ( !bVerticalSubs == ( rLine.Height() > rLine.Width() ) ) //same direction?
897 2 : continue;
898 :
899 2 : if ( aSubsRect.IsOver( rLine ) )
900 : {
901 0 : if ( bVerticalSubs ) // Vertical?
902 : {
903 0 : if ( aSubsRect.Left() <= rLine.Right() &&
904 0 : aSubsRect.Right() >= rLine.Left() )
905 : {
906 0 : long nTmp = rLine.Top()-(properties.nSPixelSzH+1);
907 0 : if ( aSubsLineRect.Top() < nTmp )
908 : {
909 0 : SwRect aNewSubsRect( aSubsLineRect );
910 0 : aNewSubsRect.Bottom( nTmp );
911 0 : aLineRects.push_back( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
912 0 : aSubsLineRect.GetSubColor() ) );
913 : }
914 0 : nTmp = rLine.Bottom()+properties.nSPixelSzH+1;
915 0 : if ( aSubsLineRect.Bottom() > nTmp )
916 : {
917 0 : SwRect aNewSubsRect( aSubsLineRect );
918 0 : aNewSubsRect.Top( nTmp );
919 0 : aLineRects.push_back( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
920 0 : aSubsLineRect.GetSubColor() ) );
921 : }
922 0 : aLineRects.erase(aLineRects.begin() + i);
923 0 : --i;
924 0 : break;
925 : }
926 : }
927 : else // Horizontal
928 : {
929 0 : if ( aSubsRect.Top() <= rLine.Bottom() &&
930 0 : aSubsRect.Bottom() >= rLine.Top() )
931 : {
932 0 : long nTmp = rLine.Left()-(properties.nSPixelSzW+1);
933 0 : if ( aSubsLineRect.Left() < nTmp )
934 : {
935 0 : SwRect aNewSubsRect( aSubsLineRect );
936 0 : aNewSubsRect.Right( nTmp );
937 0 : aLineRects.push_back( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
938 0 : aSubsLineRect.GetSubColor() ) );
939 : }
940 0 : nTmp = rLine.Right()+properties.nSPixelSzW+1;
941 0 : if ( aSubsLineRect.Right() > nTmp )
942 : {
943 0 : SwRect aNewSubsRect( aSubsLineRect );
944 0 : aNewSubsRect.Left( nTmp );
945 0 : aLineRects.push_back( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
946 0 : aSubsLineRect.GetSubColor() ) );
947 : }
948 0 : aLineRects.erase(aLineRects.begin() + i);
949 0 : --i;
950 0 : break;
951 : }
952 : }
953 : }
954 : }
955 : }
956 2 : }
957 :
958 19860 : void SwLineRects::LockLines( bool bLock )
959 : {
960 22390 : for (iterator it = aLineRects.begin(); it != aLineRects.end(); ++it)
961 2530 : (*it).Lock( bLock );
962 19860 : }
963 :
964 2 : static void lcl_DrawDashedRect( OutputDevice * pOut, SwLineRect & rLRect )
965 : {
966 2 : double nHalfLWidth = rLRect.Height( );
967 2 : if ( nHalfLWidth > 1 )
968 : {
969 2 : nHalfLWidth = nHalfLWidth / 2;
970 : }
971 : else
972 : {
973 0 : nHalfLWidth = 1;
974 : }
975 :
976 2 : long startX = rLRect.Left( );
977 2 : long startY = rLRect.Top( ) + static_cast<long>(nHalfLWidth);
978 2 : long endX = rLRect.Left( ) + rLRect.Width( );
979 2 : long endY = rLRect.Top( ) + static_cast<long>(nHalfLWidth);
980 :
981 2 : if ( rLRect.Height( ) > rLRect.Width( ) )
982 : {
983 0 : nHalfLWidth = rLRect.Width( );
984 0 : if ( nHalfLWidth > 1 )
985 : {
986 0 : nHalfLWidth = nHalfLWidth / 2;
987 : }
988 : else
989 : {
990 0 : nHalfLWidth = 1;
991 : }
992 0 : startX = rLRect.Left( ) + static_cast<long>(nHalfLWidth);
993 0 : startY = rLRect.Top( );
994 0 : endX = rLRect.Left( ) + static_cast<long>(nHalfLWidth);
995 0 : endY = rLRect.Top( ) + rLRect.Height( );
996 : }
997 :
998 : svtools::DrawLine( *pOut, Point( startX, startY ), Point( endX, endY ),
999 2 : sal_uInt32( nHalfLWidth * 2 ), rLRect.GetStyle( ) );
1000 2 : }
1001 :
1002 18943 : void SwLineRects::PaintLines( OutputDevice *pOut, SwPaintProperties &properties )
1003 : {
1004 : // Paint the borders. Sadly two passes are needed.
1005 : // Once for the inside and once for the outside edges of tables
1006 18943 : if ( aLineRects.size() != nLastCount )
1007 : {
1008 : // #i16816# tagged pdf support
1009 4 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
1010 :
1011 4 : pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
1012 4 : pOut->SetFillColor();
1013 4 : pOut->SetLineColor();
1014 4 : ConnectEdges( pOut, properties );
1015 4 : const Color *pLast = 0;
1016 :
1017 4 : bool bPaint2nd = false;
1018 4 : size_t nMinCount = aLineRects.size();
1019 :
1020 8 : for ( size_t i = 0; i < aLineRects.size(); ++i )
1021 : {
1022 4 : SwLineRect &rLRect = aLineRects[i];
1023 :
1024 4 : if ( rLRect.IsPainted() )
1025 0 : continue;
1026 :
1027 4 : if ( rLRect.IsLocked() )
1028 : {
1029 2 : nMinCount = std::min( nMinCount, i );
1030 2 : continue;
1031 : }
1032 :
1033 : // Paint it now or in the second pass?
1034 2 : bool bPaint = true;
1035 2 : if ( rLRect.GetTab() )
1036 : {
1037 0 : if ( rLRect.Height() > rLRect.Width() )
1038 : {
1039 : // Vertical edge, overlapping with the table edge?
1040 0 : SwTwips nLLeft = rLRect.Left() - 30,
1041 0 : nLRight = rLRect.Right() + 30,
1042 0 : nTLeft = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Left(),
1043 0 : nTRight = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Right();
1044 0 : if ( (nTLeft >= nLLeft && nTLeft <= nLRight) ||
1045 0 : (nTRight>= nLLeft && nTRight<= nLRight) )
1046 0 : bPaint = false;
1047 : }
1048 : else
1049 : {
1050 : // Horizontal edge, overlapping with the table edge?
1051 0 : SwTwips nLTop = rLRect.Top() - 30,
1052 0 : nLBottom = rLRect.Bottom() + 30,
1053 0 : nTTop = rLRect.GetTab()->Frm().Top() + rLRect.GetTab()->Prt().Top(),
1054 0 : nTBottom = rLRect.GetTab()->Frm().Top() + rLRect.GetTab()->Prt().Bottom();
1055 0 : if ( (nTTop >= nLTop && nTTop <= nLBottom) ||
1056 0 : (nTBottom >= nLTop && nTBottom <= nLBottom) )
1057 0 : bPaint = false;
1058 : }
1059 : }
1060 2 : if ( bPaint )
1061 : {
1062 2 : if ( !pLast || *pLast != rLRect.GetColor() )
1063 : {
1064 2 : pLast = &rLRect.GetColor();
1065 :
1066 2 : DrawModeFlags nOldDrawMode = pOut->GetDrawMode();
1067 4 : if( properties.pSGlobalShell->GetWin() &&
1068 2 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1069 0 : pOut->SetDrawMode( DrawModeFlags::Default );
1070 :
1071 2 : pOut->SetLineColor( *pLast );
1072 2 : pOut->SetFillColor( *pLast );
1073 2 : pOut->SetDrawMode( nOldDrawMode );
1074 : }
1075 :
1076 2 : if( !rLRect.IsEmpty() )
1077 2 : lcl_DrawDashedRect( pOut, rLRect );
1078 2 : rLRect.SetPainted();
1079 : }
1080 : else
1081 0 : bPaint2nd = true;
1082 : }
1083 4 : if ( bPaint2nd )
1084 : {
1085 0 : for ( size_t i = 0; i < aLineRects.size(); ++i )
1086 : {
1087 0 : SwLineRect &rLRect = aLineRects[i];
1088 0 : if ( rLRect.IsPainted() )
1089 0 : continue;
1090 :
1091 0 : if ( rLRect.IsLocked() )
1092 : {
1093 0 : nMinCount = std::min( nMinCount, i );
1094 0 : continue;
1095 : }
1096 :
1097 0 : if ( !pLast || *pLast != rLRect.GetColor() )
1098 : {
1099 0 : pLast = &rLRect.GetColor();
1100 :
1101 0 : DrawModeFlags nOldDrawMode = pOut->GetDrawMode();
1102 0 : if( properties.pSGlobalShell->GetWin() &&
1103 0 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1104 : {
1105 0 : pOut->SetDrawMode( DrawModeFlags::Default );
1106 : }
1107 :
1108 0 : pOut->SetFillColor( *pLast );
1109 0 : pOut->SetDrawMode( nOldDrawMode );
1110 : }
1111 0 : if( !rLRect.IsEmpty() )
1112 0 : lcl_DrawDashedRect( pOut, rLRect );
1113 0 : rLRect.SetPainted();
1114 : }
1115 : }
1116 4 : nLastCount = nMinCount;
1117 4 : pOut->Pop();
1118 : }
1119 18943 : }
1120 :
1121 18510 : void SwSubsRects::PaintSubsidiary( OutputDevice *pOut,
1122 : const SwLineRects *pRects,
1123 : SwPaintProperties& properties )
1124 : {
1125 18510 : if ( !aLineRects.empty() )
1126 : {
1127 : // #i16816# tagged pdf support
1128 485 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
1129 :
1130 : // Remove all help line that are almost covered (tables)
1131 3869 : for (size_type i = 0; i != aLineRects.size(); ++i)
1132 : {
1133 3384 : SwLineRect &rLi = aLineRects[i];
1134 3384 : const bool bVerticalSubs = rLi.Height() > rLi.Width();
1135 :
1136 32549 : for (size_type k = i + 1; k != aLineRects.size(); ++k)
1137 : {
1138 29181 : SwLineRect &rLk = aLineRects[k];
1139 29181 : if ( rLi.SSize() == rLk.SSize() )
1140 : {
1141 5923 : if ( bVerticalSubs == ( rLk.Height() > rLk.Width() ) )
1142 : {
1143 5923 : if ( bVerticalSubs )
1144 : {
1145 3883 : long nLi = rLi.Right();
1146 3883 : long nLk = rLk.Right();
1147 6664 : if ( rLi.Top() == rLk.Top() &&
1148 7414 : ((nLi < rLk.Left() && nLi+21 > rLk.Left()) ||
1149 3270 : (nLk < rLi.Left() && nLk+21 > rLi.Left())))
1150 : {
1151 1 : aLineRects.erase(aLineRects.begin() + k);
1152 : // don't continue with inner loop any more:
1153 : // the array may shrink!
1154 1 : --i;
1155 1 : break;
1156 : }
1157 : }
1158 : else
1159 : {
1160 2040 : long nLi = rLi.Bottom();
1161 2040 : long nLk = rLk.Bottom();
1162 3787 : if ( rLi.Left() == rLk.Left() &&
1163 4554 : ((nLi < rLk.Top() && nLi+21 > rLk.Top()) ||
1164 1929 : (nLk < rLi.Top() && nLk+21 > rLi.Top())))
1165 : {
1166 15 : aLineRects.erase(aLineRects.begin() + k);
1167 : // don't continue with inner loop any more:
1168 : // the array may shrink!
1169 15 : --i;
1170 15 : break;
1171 : }
1172 : }
1173 : }
1174 : }
1175 : }
1176 : }
1177 :
1178 485 : if ( pRects && (!pRects->aLineRects.empty()) )
1179 2 : RemoveSuperfluousSubsidiaryLines( *pRects, properties );
1180 :
1181 485 : if ( !aLineRects.empty() )
1182 : {
1183 485 : pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
1184 485 : pOut->SetLineColor();
1185 :
1186 : // Reset draw mode in high contrast mode in order to get fill color
1187 : // set at output device. Recover draw mode after draw of lines.
1188 : // Necessary for the subsidiary lines painted by the fly frames.
1189 485 : DrawModeFlags nOldDrawMode = pOut->GetDrawMode();
1190 970 : if( gProp.pSGlobalShell->GetWin() &&
1191 485 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1192 : {
1193 0 : pOut->SetDrawMode( DrawModeFlags::Default );
1194 : }
1195 :
1196 3853 : for (SwSubsRects::iterator it = aLineRects.begin(); it != aLineRects.end();
1197 : ++it)
1198 : {
1199 3368 : SwLineRect &rLRect = (*it);
1200 : // Add condition <!rLRect.IsLocked()> to prevent paint of locked subsidiary lines.
1201 6021 : if ( !rLRect.IsPainted() &&
1202 2653 : !rLRect.IsLocked() )
1203 : {
1204 1887 : const Color *pCol = 0;
1205 1887 : switch ( rLRect.GetSubColor() )
1206 : {
1207 0 : case SUBCOL_PAGE: pCol = &SwViewOption::GetDocBoundariesColor(); break;
1208 1660 : case SUBCOL_FLY: pCol = &SwViewOption::GetObjectBoundariesColor(); break;
1209 6 : case SUBCOL_TAB: pCol = &SwViewOption::GetTableBoundariesColor(); break;
1210 221 : case SUBCOL_SECT: pCol = &SwViewOption::GetSectionBoundColor(); break;
1211 : }
1212 :
1213 1887 : if (pCol && pOut->GetFillColor() != *pCol)
1214 464 : pOut->SetFillColor( *pCol );
1215 1887 : pOut->DrawRect( rLRect.SVRect() );
1216 :
1217 1887 : rLRect.SetPainted();
1218 : }
1219 : }
1220 :
1221 485 : pOut->SetDrawMode( nOldDrawMode );
1222 :
1223 485 : pOut->Pop();
1224 485 : }
1225 : }
1226 18510 : }
1227 :
1228 : // Various functions that are use in this file.
1229 :
1230 : /**
1231 : * Function <SwAlignRect(..)> is also used outside this file
1232 : *
1233 : * Correction: adjust rectangle on pixel level in order to make sure,
1234 : * that the border "leaves its original pixel", if it has to
1235 : * No prior adjustments for odd relation between pixel and twip
1236 : */
1237 243803 : void SwAlignRect( SwRect &rRect, const SwViewShell *pSh )
1238 : {
1239 243803 : if( !rRect.HasArea() )
1240 1152 : return;
1241 :
1242 : // Make sure that view shell (parameter <pSh>) exists, if the output device
1243 : // is taken from this view shell --> no output device, no alignment
1244 : // Output device taken from view shell <pSh>, if <gProp.bSFlyMetafile> not set
1245 243227 : if ( !gProp.bSFlyMetafile && !pSh )
1246 : {
1247 0 : return;
1248 : }
1249 :
1250 : const vcl::RenderContext *pOut = gProp.bSFlyMetafile ?
1251 243227 : gProp.pSFlyMetafileOut.get() : pSh->GetOut();
1252 :
1253 : // Hold original rectangle in pixel
1254 243227 : const Rectangle aOrgPxRect = pOut->LogicToPixel( rRect.SVRect() );
1255 : // Determine pixel-center rectangle in twip
1256 243227 : const SwRect aPxCenterRect( pOut->PixelToLogic( aOrgPxRect ) );
1257 :
1258 : // Perform adjustments on pixel level.
1259 243227 : SwRect aAlignedPxRect( aOrgPxRect );
1260 243227 : if ( rRect.Top() > aPxCenterRect.Top() )
1261 : {
1262 : // 'leave pixel overlapping on top'
1263 49037 : aAlignedPxRect.Top( aAlignedPxRect.Top() + 1 );
1264 : }
1265 :
1266 243227 : if ( rRect.Bottom() < aPxCenterRect.Bottom() )
1267 : {
1268 : // 'leave pixel overlapping on bottom'
1269 110778 : aAlignedPxRect.Bottom( aAlignedPxRect.Bottom() - 1 );
1270 : }
1271 :
1272 243227 : if ( rRect.Left() > aPxCenterRect.Left() )
1273 : {
1274 : // 'leave pixel overlapping on left'
1275 31327 : aAlignedPxRect.Left( aAlignedPxRect.Left() + 1 );
1276 : }
1277 :
1278 243227 : if ( rRect.Right() < aPxCenterRect.Right() )
1279 : {
1280 : // 'leave pixel overlapping on right'
1281 186917 : aAlignedPxRect.Right( aAlignedPxRect.Right() - 1 );
1282 : }
1283 :
1284 : // Consider negative width/height check, if aligned SwRect has negative width/height.
1285 : // If Yes, adjust it to width/height = 0 twip.
1286 : // NOTE: A SwRect with negative width/height can occur, if the width/height
1287 : // of the given SwRect in twip was less than a pixel in twip and that
1288 : // the alignment calculates that the aligned SwRect should not contain
1289 : // the pixels the width/height is on.
1290 243227 : if ( aAlignedPxRect.Width() < 0 )
1291 : {
1292 20 : aAlignedPxRect.Width(0);
1293 : }
1294 243227 : if ( aAlignedPxRect.Height() < 0 )
1295 : {
1296 16 : aAlignedPxRect.Height(0);
1297 : }
1298 : // Consider zero width/height for converting a rectangle from
1299 : // pixel to logic it needs a width/height. Thus, set width/height
1300 : // to one, if it's zero and correct this on the twip level after the conversion.
1301 243227 : bool bZeroWidth = false;
1302 243227 : if ( aAlignedPxRect.Width() == 0 )
1303 : {
1304 52232 : aAlignedPxRect.Width(1);
1305 52232 : bZeroWidth = true;
1306 : }
1307 243227 : bool bZeroHeight = false;
1308 243227 : if ( aAlignedPxRect.Height() == 0 )
1309 : {
1310 36 : aAlignedPxRect.Height(1);
1311 36 : bZeroHeight = true;
1312 : }
1313 :
1314 243227 : rRect = pOut->PixelToLogic( aAlignedPxRect.SVRect() );
1315 :
1316 : // Consider zero width/height and adjust calculated aligned twip rectangle.
1317 : // Reset width/height to zero; previous negative width/height haven't to be considered.
1318 243227 : if ( bZeroWidth )
1319 : {
1320 52232 : rRect.Width(0);
1321 : }
1322 243227 : if ( bZeroHeight )
1323 : {
1324 36 : rRect.Height(0);
1325 : }
1326 : }
1327 :
1328 : /**
1329 : * Helper for twip adjustments on pixel base
1330 : *
1331 : * This method compares the x- or y-pixel position of two twip-points.
1332 : * If the x-/y-pixel positions are the same, the x-/y-pixel position of
1333 : * the second twip point is adjusted by a given amount of pixels
1334 : */
1335 0 : static void lcl_CompPxPosAndAdjustPos( const vcl::RenderContext& _rOut,
1336 : const Point& _rRefPt,
1337 : Point& _rCompPt,
1338 : const bool _bChkXPos,
1339 : const sal_Int8 _nPxAdjustment )
1340 : {
1341 0 : const Point aRefPxPt = _rOut.LogicToPixel( _rRefPt );
1342 0 : Point aCompPxPt = _rOut.LogicToPixel( _rCompPt );
1343 :
1344 0 : if ( _bChkXPos )
1345 : {
1346 0 : if ( aCompPxPt.X() == aRefPxPt.X() )
1347 : {
1348 0 : aCompPxPt.X() += _nPxAdjustment ;
1349 0 : const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
1350 0 : _rCompPt.X() = aAdjustedCompPt.X();
1351 : }
1352 : }
1353 : else
1354 : {
1355 0 : if ( aCompPxPt.Y() == aRefPxPt.Y() )
1356 : {
1357 0 : aCompPxPt.Y() += _nPxAdjustment ;
1358 0 : const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
1359 0 : _rCompPt.Y() = aAdjustedCompPt.Y();
1360 : }
1361 : }
1362 0 : }
1363 :
1364 : /**
1365 : * Method to pixel-align rectangle for drawing graphic object
1366 : *
1367 : * Because we are drawing graphics from the left-top-corner in conjunction
1368 : * with size coordinates, these coordinates have to be calculated at a pixel
1369 : * level.
1370 : * Thus, we convert the rectangle to pixel and then convert to left-top-corner
1371 : * and then get size of pixel rectangle back to logic.
1372 : * This calculation is necessary, because there's a different between
1373 : * the conversion from logic to pixel of a normal rectangle with its left-top-
1374 : * and right-bottom-corner and the same conversion of the same rectangle
1375 : * with left-top-corner and size.
1376 : *
1377 : * NOTE: Call this method before each <GraphicObject.Draw(...)>
1378 : */
1379 128 : void SwAlignGrfRect( SwRect *pGrfRect, const vcl::RenderContext &rOut )
1380 : {
1381 128 : Rectangle aPxRect = rOut.LogicToPixel( pGrfRect->SVRect() );
1382 128 : pGrfRect->Pos( rOut.PixelToLogic( aPxRect.TopLeft() ) );
1383 128 : pGrfRect->SSize( rOut.PixelToLogic( aPxRect.GetSize() ) );
1384 128 : }
1385 :
1386 998 : static long lcl_AlignWidth( const long nWidth, SwPaintProperties& properties )
1387 : {
1388 998 : if ( nWidth )
1389 : {
1390 882 : const long nW = nWidth % properties.nSPixelSzW;
1391 :
1392 882 : if ( !nW || nW > properties.nSHalfPixelSzW )
1393 184 : return std::max(1L, nWidth - properties.nSHalfPixelSzW);
1394 : }
1395 814 : return nWidth;
1396 : }
1397 :
1398 983 : static long lcl_AlignHeight( const long nHeight, SwPaintProperties& properties )
1399 : {
1400 983 : if ( nHeight )
1401 : {
1402 927 : const long nH = nHeight % properties.nSPixelSzH;
1403 :
1404 927 : if ( !nH || nH > properties.nSHalfPixelSzH )
1405 215 : return std::max(1L, nHeight - properties.nSHalfPixelSzH);
1406 : }
1407 768 : return nHeight;
1408 : }
1409 :
1410 0 : static long lcl_MinHeightDist( const long nDist, SwPaintProperties& properties )
1411 : {
1412 0 : if ( properties.aSScaleX < aMinDistScale || properties.aSScaleY < aMinDistScale )
1413 0 : return nDist;
1414 0 : return ::lcl_AlignHeight( std::max( nDist, properties.nSMinDistPixelH ), properties);
1415 : }
1416 :
1417 : /**
1418 : * Calculate PrtArea plus surrounding plus shadow
1419 : */
1420 14393 : static void lcl_CalcBorderRect( SwRect &rRect, const SwFrm *pFrm,
1421 : const SwBorderAttrs &rAttrs,
1422 : const bool bShadow,
1423 : SwPaintProperties& properties)
1424 : {
1425 : // Special handling for cell frames.
1426 : // The printing area of a cell frame is completely enclosed in the frame area
1427 : // and a cell frame has no shadow. Thus, for cell frames the calculated
1428 : // area equals the frame area.
1429 : // Notes: Borders of cell frames in R2L text direction will switch its side
1430 : // - left border is painted on the right; right border on the left.
1431 : // See <lcl_PaintLeftLine> and <lcl_PaintRightLine>.
1432 14393 : if( pFrm->IsSctFrm() )
1433 : {
1434 97 : rRect = pFrm->Prt();
1435 97 : rRect.Pos() += pFrm->Frm().Pos();
1436 : }
1437 14296 : else if ( pFrm->IsCellFrm() )
1438 3274 : rRect = pFrm->Frm();
1439 : else
1440 : {
1441 11022 : rRect = pFrm->Prt();
1442 11022 : rRect.Pos() += pFrm->Frm().Pos();
1443 :
1444 11444 : if ( rAttrs.IsLine() || rAttrs.IsBorderDist() ||
1445 4 : (bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE) )
1446 : {
1447 422 : SwRectFn fnRect = pFrm->IsVertical() ? ( pFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
1448 :
1449 422 : const SvxBoxItem &rBox = rAttrs.GetBox();
1450 422 : const bool bTop = 0 != (pFrm->*fnRect->fnGetTopMargin)();
1451 422 : if ( bTop )
1452 : {
1453 353 : SwTwips nDiff = rBox.GetTop() ?
1454 340 : rBox.CalcLineSpace( SvxBoxItemLine::TOP ) :
1455 13 : ( rAttrs.IsBorderDist() ?
1456 : // Increase of distance by one twip is incorrect.
1457 706 : rBox.GetDistance( SvxBoxItemLine::TOP ) : 0 );
1458 353 : if( nDiff )
1459 340 : (rRect.*fnRect->fnSubTop)( nDiff );
1460 : }
1461 :
1462 422 : const bool bBottom = 0 != (pFrm->*fnRect->fnGetBottomMargin)();
1463 422 : if ( bBottom )
1464 : {
1465 392 : SwTwips nDiff = 0;
1466 : // #i29550#
1467 392 : if ( pFrm->IsTabFrm() &&
1468 0 : static_cast<const SwTabFrm*>(pFrm)->IsCollapsingBorders() )
1469 : {
1470 : // For collapsing borders, we have to add the height of
1471 : // the height of the last line
1472 0 : nDiff = static_cast<const SwTabFrm*>(pFrm)->GetBottomLineSize();
1473 : }
1474 : else
1475 : {
1476 392 : nDiff = rBox.GetBottom() ?
1477 388 : rBox.CalcLineSpace( SvxBoxItemLine::BOTTOM ) :
1478 4 : ( rAttrs.IsBorderDist() ?
1479 : // Increase of distance by one twip is incorrect.
1480 784 : rBox.GetDistance( SvxBoxItemLine::BOTTOM ) : 0 );
1481 : }
1482 392 : if( nDiff )
1483 376 : (rRect.*fnRect->fnAddBottom)( nDiff );
1484 : }
1485 :
1486 422 : if ( rBox.GetLeft() )
1487 360 : (rRect.*fnRect->fnSubLeft)( rBox.CalcLineSpace( SvxBoxItemLine::LEFT ) );
1488 62 : else if ( rAttrs.IsBorderDist() )
1489 : // Increase of distance by one twip is incorrect.
1490 0 : (rRect.*fnRect->fnSubLeft)( rBox.GetDistance( SvxBoxItemLine::LEFT ) );
1491 :
1492 422 : if ( rBox.GetRight() )
1493 360 : (rRect.*fnRect->fnAddRight)( rBox.CalcLineSpace( SvxBoxItemLine::RIGHT ) );
1494 62 : else if ( rAttrs.IsBorderDist() )
1495 : // Increase of distance by one twip is incorrect.
1496 0 : (rRect.*fnRect->fnAddRight)( rBox.GetDistance( SvxBoxItemLine::RIGHT ) );
1497 :
1498 422 : if ( bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
1499 : {
1500 11 : const SvxShadowItem &rShadow = rAttrs.GetShadow();
1501 11 : if ( bTop )
1502 3 : (rRect.*fnRect->fnSubTop)(rShadow.CalcShadowSpace(SvxShadowItemSide::TOP));
1503 11 : (rRect.*fnRect->fnSubLeft)(rShadow.CalcShadowSpace(SvxShadowItemSide::LEFT));
1504 11 : if ( bBottom )
1505 : (rRect.*fnRect->fnAddBottom)
1506 11 : (rShadow.CalcShadowSpace( SvxShadowItemSide::BOTTOM ));
1507 11 : (rRect.*fnRect->fnAddRight)(rShadow.CalcShadowSpace(SvxShadowItemSide::RIGHT));
1508 : }
1509 : }
1510 : }
1511 :
1512 14393 : ::SwAlignRect( rRect, properties.pSGlobalShell );
1513 14393 : }
1514 :
1515 : /**
1516 : * Extend left/right border/shadow rectangle to bottom of previous frame/to
1517 : * top of next frame, if border/shadow is joined with previous/next frame
1518 : */
1519 57 : static void lcl_ExtendLeftAndRight( SwRect& _rRect,
1520 : const SwFrm& _rFrm,
1521 : const SwBorderAttrs& _rAttrs,
1522 : const SwRectFn& _rRectFn )
1523 : {
1524 57 : if ( _rAttrs.JoinedWithPrev( _rFrm ) )
1525 : {
1526 14 : const SwFrm* pPrevFrm = _rFrm.GetPrev();
1527 14 : (_rRect.*_rRectFn->fnSetTop)( (pPrevFrm->*_rRectFn->fnGetPrtBottom)() );
1528 : }
1529 57 : if ( _rAttrs.JoinedWithNext( _rFrm ) )
1530 : {
1531 14 : const SwFrm* pNextFrm = _rFrm.GetNext();
1532 14 : (_rRect.*_rRectFn->fnSetBottom)( (pNextFrm->*_rRectFn->fnGetPrtTop)() );
1533 : }
1534 57 : }
1535 :
1536 362 : static void lcl_SubtractFlys( const SwFrm *pFrm, const SwPageFrm *pPage,
1537 : const SwRect &rRect, SwRegionRects &rRegion, SwPaintProperties & rProperties)
1538 : {
1539 362 : const SwSortedObjs& rObjs = *pPage->GetSortedObjs();
1540 362 : const SwFlyFrm* pSelfFly = pFrm->IsInFly() ? pFrm->FindFlyFrm() : gProp.pSRetoucheFly2;
1541 362 : if (!gProp.pSRetoucheFly)
1542 362 : gProp.pSRetoucheFly = gProp.pSRetoucheFly2;
1543 :
1544 2350 : for (size_t j = 0; (j < rObjs.size()) && !rRegion.empty(); ++j)
1545 : {
1546 1988 : const SwAnchoredObject* pAnchoredObj = rObjs[j];
1547 1988 : const SdrObject* pSdrObj = pAnchoredObj->GetDrawObj();
1548 :
1549 : // Do not consider invisible objects
1550 1988 : if (!pPage->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId(pSdrObj->GetLayer()))
1551 0 : continue;
1552 :
1553 1988 : if (!pAnchoredObj->ISA(SwFlyFrm))
1554 1155 : continue;
1555 :
1556 833 : const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
1557 :
1558 833 : if (pSelfFly == pFly || gProp.pSRetoucheFly == pFly || !rRect.IsOver(pFly->Frm()))
1559 748 : continue;
1560 :
1561 85 : if (!pFly->GetFormat()->GetPrint().GetValue() &&
1562 0 : (OUTDEV_PRINTER == gProp.pSGlobalShell->GetOut()->GetOutDevType() ||
1563 0 : gProp.pSGlobalShell->IsPreview()))
1564 0 : continue;
1565 :
1566 85 : const bool bLowerOfSelf = pSelfFly && pFly->IsLowerOf( pSelfFly );
1567 :
1568 : //For character bound Flys only examine those Flys in which it is not
1569 : //anchored itself.
1570 : //Why only for character bound ones you may ask? It never makes sense to
1571 : //subtract frames in which it is anchored itself right?
1572 85 : if (pSelfFly && pSelfFly->IsLowerOf(pFly))
1573 0 : continue;
1574 :
1575 : //Any why does it not apply for the RetoucheFly too?
1576 85 : if (gProp.pSRetoucheFly && gProp.pSRetoucheFly->IsLowerOf(pFly))
1577 0 : continue;
1578 :
1579 : #if OSL_DEBUG_LEVEL > 0
1580 : //Flys who are anchored inside their own one, must have a bigger OrdNum
1581 : //or be character bound.
1582 : if (pSelfFly && bLowerOfSelf)
1583 : {
1584 : OSL_ENSURE( pFly->IsFlyInCntFrm() ||
1585 : pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj()->GetOrdNumDirect(),
1586 : "Fly with wrong z-Order" );
1587 : }
1588 : #endif
1589 :
1590 85 : bool bStopOnHell = true;
1591 85 : if (pSelfFly)
1592 : {
1593 4 : const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
1594 4 : if (pSdrObj->GetLayer() == pTmp->GetLayer())
1595 : {
1596 4 : if (pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect())
1597 : //In the same layer we only observe those that are above.
1598 2 : continue;
1599 : }
1600 : else
1601 : {
1602 0 : if (!bLowerOfSelf && !pFly->GetFormat()->GetOpaque().GetValue())
1603 : //From other layers we are only interested in non
1604 : //transparent ones or those that are internal
1605 0 : continue;
1606 0 : bStopOnHell = false;
1607 : }
1608 : }
1609 83 : if (gProp.pSRetoucheFly)
1610 : {
1611 0 : const SdrObject *pTmp = gProp.pSRetoucheFly->GetVirtDrawObj();
1612 0 : if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
1613 : {
1614 0 : if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
1615 : //In the same layer we only observe those that are above.
1616 0 : continue;
1617 : }
1618 : else
1619 : {
1620 0 : if (!pFly->IsLowerOf( gProp.pSRetoucheFly ) && !pFly->GetFormat()->GetOpaque().GetValue())
1621 : //From other layers we are only interested in non
1622 : //transparent ones or those that are internal
1623 0 : continue;
1624 0 : bStopOnHell = false;
1625 : }
1626 : }
1627 :
1628 : //If the content of the Fly is transparent, we subtract it only if it's
1629 : //contained in the hell layer.
1630 83 : const IDocumentDrawModelAccess* pIDDMA = pFly->GetFormat()->getIDocumentDrawModelAccess();
1631 83 : bool bHell = pSdrObj->GetLayer() == pIDDMA->GetHellId();
1632 175 : if ( (bStopOnHell && bHell) ||
1633 : /// Change internal order of condition
1634 : /// first check "!bHell", then "..->Lower()" and "..->IsNoTextFrm()"
1635 : /// have not to be performed, if frame is in "Hell"
1636 185 : ( !bHell && pFly->Lower() && pFly->Lower()->IsNoTextFrm() &&
1637 29 : (static_cast<SwNoTextFrm const*>(pFly->Lower())->IsTransparent() ||
1638 20 : static_cast<SwNoTextFrm const*>(pFly->Lower())->HasAnimation() ||
1639 10 : pFly->GetFormat()->GetSurround().IsContour()
1640 : )
1641 : )
1642 : )
1643 9 : continue;
1644 :
1645 : // Own if-statements for transparent background/shadow of fly frames
1646 : // in order to handle special conditions.
1647 74 : if (pFly->IsBackgroundTransparent())
1648 : {
1649 : // Background <pFly> is transparent drawn. Thus normally, its region
1650 : // have not to be subtracted from given region.
1651 : // But, if method is called for a fly frame and
1652 : // <pFly> is a direct lower of this fly frame and
1653 : // <pFly> inherites its transparent background brush from its parent,
1654 : // then <pFly> frame area have to be subtracted from given region.
1655 : // NOTE: Because in Status Quo transparent backgrounds can only be
1656 : // assigned to fly frames, the handle of this special case
1657 : // avoids drawing of transparent areas more than once, if
1658 : // a fly frame inherites a transparent background from its
1659 : // parent fly frame.
1660 19 : if (pFrm->IsFlyFrm() &&
1661 9 : (pFly->GetAnchorFrm()->FindFlyFrm() == pFrm) &&
1662 0 : static_cast<const SwFlyFrameFormat*>(pFly->GetFormat())->IsBackgroundBrushInherited()
1663 : )
1664 : {
1665 0 : SwRect aRect;
1666 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), static_cast<SwFrm const *>(pFly) );
1667 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1668 0 : ::lcl_CalcBorderRect( aRect, pFly, rAttrs, true, rProperties );
1669 0 : rRegion -= aRect;
1670 0 : continue;
1671 : }
1672 : else
1673 : {
1674 9 : continue;
1675 : }
1676 : }
1677 :
1678 65 : if (bHell && pFly->GetAnchorFrm()->IsInFly())
1679 : {
1680 : //So the border won't get dismantled by the background of the other
1681 : //Fly.
1682 0 : SwRect aRect;
1683 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), static_cast<SwFrm const *>(pFly) );
1684 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1685 0 : ::lcl_CalcBorderRect( aRect, pFly, rAttrs, true, rProperties );
1686 0 : rRegion -= aRect;
1687 : }
1688 : else
1689 : {
1690 65 : SwRect aRect( pFly->Prt() );
1691 65 : aRect += pFly->Frm().Pos();
1692 65 : rRegion -= aRect;
1693 : }
1694 : }
1695 362 : if (gProp.pSRetoucheFly == gProp.pSRetoucheFly2)
1696 362 : gProp.pSRetoucheFly = 0;
1697 362 : }
1698 :
1699 0 : static void lcl_implDrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
1700 : vcl::RenderContext* _pOut,
1701 : const SwRect& _rAlignedPaintRect,
1702 : const GraphicObject& _rGraphicObj,
1703 : SwPaintProperties& properties)
1704 : {
1705 : /// determine color of background
1706 : /// If color of background brush is not "no fill"/"auto fill" or
1707 : /// <SwPaintProperties.bSFlyMetafile> is set, use color of background brush, otherwise
1708 : /// use global retouche color.
1709 0 : const Color aColor( ( (_rBackgrdBrush.GetColor() != COL_TRANSPARENT) || properties.bSFlyMetafile )
1710 : ? _rBackgrdBrush.GetColor()
1711 0 : : aGlobalRetoucheColor );
1712 :
1713 : /// determine, if background color have to be drawn transparent
1714 : /// and calculate transparency percent value
1715 0 : sal_Int8 nTransparencyPercent = 0;
1716 0 : bool bDrawTransparent = false;
1717 0 : if ( aColor.GetTransparency() != 0 )
1718 : /// background color is transparent --> draw transparent.
1719 : {
1720 0 : bDrawTransparent = true;
1721 0 : nTransparencyPercent = (aColor.GetTransparency()*100 + 0x7F)/0xFF;
1722 : }
1723 0 : else if ( (_rGraphicObj.GetAttr().GetTransparency() != 0) &&
1724 0 : (_rBackgrdBrush.GetColor() == COL_TRANSPARENT) )
1725 : /// graphic is drawn transparent and background color is
1726 : /// "no fill"/"auto fill" --> draw transparent
1727 : {
1728 0 : bDrawTransparent = true;
1729 0 : nTransparencyPercent = (_rGraphicObj.GetAttr().GetTransparency()*100 + 0x7F)/0xFF;
1730 : }
1731 :
1732 0 : if ( bDrawTransparent )
1733 : {
1734 : /// draw background transparent
1735 0 : if( _pOut->GetFillColor() != aColor.GetRGBColor() )
1736 0 : _pOut->SetFillColor( aColor.GetRGBColor() );
1737 0 : tools::PolyPolygon aPoly( _rAlignedPaintRect.SVRect() );
1738 0 : _pOut->DrawTransparent( aPoly, nTransparencyPercent );
1739 : }
1740 : else
1741 : {
1742 : /// draw background opaque
1743 0 : if ( _pOut->GetFillColor() != aColor )
1744 0 : _pOut->SetFillColor( aColor );
1745 0 : _pOut->DrawRect( _rAlignedPaintRect.SVRect() );
1746 : }
1747 0 : }
1748 :
1749 : /**
1750 : * This is a local help method to draw a background for a graphic
1751 : *
1752 : * Under certain circumstances we have to draw a background for a graphic.
1753 : * This method takes care of the conditions and draws the background with the
1754 : * corresponding color.
1755 : * Method introduced for bug fix #103876# in order to optimize drawing tiled
1756 : * background graphics. Previously, this code was integrated in method
1757 : * <lcl_DrawGraphic>.
1758 : * Method implemented as a inline, checking the conditions and calling method
1759 : * method <lcl_implDrawGraphicBackgrd(..)> for the intrinsic drawing.
1760 : *
1761 : * @param _rBackgrdBrush
1762 : * background brush contain the color the background has to be drawn.
1763 : *
1764 : * @param _pOut
1765 : * output device the background has to be drawn in.
1766 : *
1767 : * @param _rAlignedPaintRect
1768 : * paint rectangle in the output device, which has to be drawn with the background.
1769 : * rectangle have to be aligned by method ::SwAlignRect
1770 : *
1771 : * @param _rGraphicObj
1772 : * graphic object, for which the background has to be drawn. Used for checking
1773 : * the transparency of its bitmap, its type and if the graphic is drawn transparent
1774 : *
1775 : * @param _bNumberingGraphic
1776 : * boolean indicating that graphic is used as a numbering.
1777 : *
1778 : * @param _bBackgrdAlreadyDrawn
1779 : * boolean (optional; default: false) indicating, if the background is already drawn.
1780 : */
1781 0 : static inline void lcl_DrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
1782 : OutputDevice* _pOut,
1783 : const SwRect& _rAlignedPaintRect,
1784 : const GraphicObject& _rGraphicObj,
1785 : bool _bNumberingGraphic,
1786 : SwPaintProperties& properties,
1787 : bool _bBackgrdAlreadyDrawn = false)
1788 : {
1789 : // draw background with background color, if
1790 : // (1) graphic is not used as a numbering AND
1791 : // (2) background is not already drawn AND
1792 : // (3) intrinsic graphic is transparent OR intrinsic graphic doesn't exists
1793 0 : if ( !_bNumberingGraphic &&
1794 0 : !_bBackgrdAlreadyDrawn &&
1795 0 : ( _rGraphicObj.IsTransparent() || _rGraphicObj.GetType() == GRAPHIC_NONE )
1796 : )
1797 : {
1798 0 : lcl_implDrawGraphicBackgrd( _rBackgrdBrush, _pOut, _rAlignedPaintRect, _rGraphicObj, properties );
1799 : }
1800 0 : }
1801 :
1802 : /**
1803 : * NNOTE: the transparency of the background graphic is saved in
1804 : * SvxBrushItem.GetGraphicObject(<shell>).GetAttr().Set/GetTransparency()
1805 : * and is considered in the drawing of the graphic
1806 : *
1807 : * Thus, to provide transparent background graphic for text frames nothing
1808 : * has to be coded
1809 : *
1810 : * Use align rectangle for drawing graphic Pixel-align coordinates for
1811 : * drawing graphic
1812 : * Outsource code for drawing background of the graphic
1813 : * with a background color in method <lcl_DrawGraphicBackgrd>
1814 : *
1815 : * Also, change type of <bGrfNum> and <bClip> from <bool> to <bool>
1816 : */
1817 0 : static void lcl_DrawGraphic( const SvxBrushItem& rBrush, vcl::RenderContext *pOut,
1818 : SwViewShell &rSh, const SwRect &rGrf, const SwRect &rOut,
1819 : bool bClip, bool bGrfNum,
1820 : SwPaintProperties& properties,
1821 : bool bBackgrdAlreadyDrawn = false )
1822 : // add parameter <bBackgrdAlreadyDrawn> to indicate
1823 : // that the background is already drawn.
1824 : {
1825 : // Calculate align rectangle from parameter <rGrf> and use aligned
1826 : // rectangle <aAlignedGrfRect> in the following code
1827 0 : SwRect aAlignedGrfRect = rGrf;
1828 0 : ::SwAlignRect( aAlignedGrfRect, &rSh );
1829 :
1830 : // Change type from <bool> to <bool>.
1831 0 : const bool bNotInside = bClip && !rOut.IsInside( aAlignedGrfRect );
1832 0 : if ( bNotInside )
1833 : {
1834 0 : pOut->Push( PushFlags::CLIPREGION );
1835 0 : pOut->IntersectClipRegion( rOut.SVRect() );
1836 : }
1837 :
1838 : // No Link here, we want to load the graphic synchronously!
1839 0 : const_cast<SvxBrushItem&>(rBrush).SetDoneLink( Link<>() );
1840 0 : GraphicObject *pGrf = const_cast<GraphicObject*>(rBrush.GetGraphicObject());
1841 :
1842 : // Outsource drawing of background with a background color
1843 0 : ::lcl_DrawGraphicBackgrd( rBrush, pOut, aAlignedGrfRect, *pGrf, bGrfNum, properties, bBackgrdAlreadyDrawn );
1844 :
1845 : // Because for drawing a graphic left-top-corner and size coordinates are
1846 : // used, these coordinates have to be determined on pixel level.
1847 0 : ::SwAlignGrfRect( &aAlignedGrfRect, *pOut );
1848 :
1849 : paintGraphicUsingPrimitivesHelper(*pOut,
1850 0 : *pGrf, pGrf->GetAttr(), aAlignedGrfRect);
1851 :
1852 0 : if ( bNotInside )
1853 0 : pOut->Pop();
1854 0 : }
1855 :
1856 474 : bool DrawFillAttributes(
1857 : const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
1858 : const SwRect& rOriginalLayoutRect,
1859 : const SwRegionRects& rPaintRegion,
1860 : vcl::RenderContext& rOut)
1861 : {
1862 474 : if(rFillAttributes.get() && rFillAttributes->isUsed())
1863 : {
1864 : basegfx::B2DRange aPaintRange(
1865 474 : rPaintRegion.GetOrigin().Left(),
1866 474 : rPaintRegion.GetOrigin().Top(),
1867 474 : rPaintRegion.GetOrigin().Right(),
1868 1896 : rPaintRegion.GetOrigin().Bottom());
1869 :
1870 1896 : if (!aPaintRange.isEmpty() &&
1871 1422 : !rPaintRegion.empty() &&
1872 3792 : !basegfx::fTools::equalZero(aPaintRange.getWidth()) &&
1873 1422 : !basegfx::fTools::equalZero(aPaintRange.getHeight()))
1874 : {
1875 471 : const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
1876 :
1877 : //UUUU need to expand for correct AAed and non-AAed visualization as primitive.
1878 : // This must probably be removed again when we will be able to get all Writer visualization
1879 : // as primitives and Writer prepares all it's stuff in high precision coordinates (also
1880 : // needs to avoid moving boundaries around to better show overlapping stuff...)
1881 471 : if(aSvtOptionsDrawinglayer.IsAntiAliasing())
1882 : {
1883 : // if AAed in principle expand by 0.5 in all directions. Since painting edges of
1884 : // AAed regions does not add to no transparence (0.5 opacity covered by 0.5 opacity
1885 : // is not full opacity but 0.75 opacity) we need some overlap here to avoid paint
1886 : // artifacts. Checked experimentally - a little bit more in Y is needed, probably
1887 : // due to still existing integer alignment and cruncing in writer.
1888 : static double fExpandX = 0.55;
1889 : static double fExpandY = 0.70;
1890 0 : const basegfx::B2DVector aSingleUnit(rOut.GetInverseViewTransformation() * basegfx::B2DVector(fExpandX, fExpandY));
1891 :
1892 0 : aPaintRange.expand(aPaintRange.getMinimum() - aSingleUnit);
1893 0 : aPaintRange.expand(aPaintRange.getMaximum() + aSingleUnit);
1894 : }
1895 : else
1896 : {
1897 : // if not AAed expand by one unit to bottom right due to the missing unit
1898 : // from SwRect/Rectangle integer handling
1899 471 : const basegfx::B2DVector aSingleUnit(rOut.GetInverseViewTransformation() * basegfx::B2DVector(1.0, 1.0));
1900 :
1901 471 : aPaintRange.expand(aPaintRange.getMaximum() + aSingleUnit);
1902 : }
1903 :
1904 : const basegfx::B2DRange aDefineRange(
1905 471 : rOriginalLayoutRect.Left(),
1906 471 : rOriginalLayoutRect.Top(),
1907 471 : rOriginalLayoutRect.Right(),
1908 1884 : rOriginalLayoutRect.Bottom());
1909 :
1910 : const drawinglayer::primitive2d::Primitive2DSequence& rSequence = rFillAttributes->getPrimitive2DSequence(
1911 : aPaintRange,
1912 471 : aDefineRange);
1913 :
1914 471 : if(rSequence.getLength())
1915 : {
1916 : drawinglayer::primitive2d::Primitive2DSequence const*
1917 471 : pPrimitives(&rSequence);
1918 471 : drawinglayer::primitive2d::Primitive2DSequence primitives;
1919 : // tdf#86578 the awful lcl_SubtractFlys hack
1920 471 : if (rPaintRegion.size() > 1 || rPaintRegion[0] != rPaintRegion.GetOrigin())
1921 : {
1922 1 : tools::PolyPolygon tempRegion;
1923 4 : for (size_t i = 0; i < rPaintRegion.size(); ++i)
1924 : {
1925 3 : tempRegion.Insert(Polygon(rPaintRegion[i].SVRect()));
1926 : }
1927 : basegfx::B2DPolyPolygon const maskRegion(
1928 2 : tempRegion.getB2DPolyPolygon());
1929 1 : primitives.realloc(1);
1930 2 : primitives[0] = new drawinglayer::primitive2d::MaskPrimitive2D(
1931 2 : maskRegion, rSequence);
1932 2 : pPrimitives = &primitives;
1933 : }
1934 : assert(pPrimitives && pPrimitives->getLength());
1935 :
1936 : const drawinglayer::geometry::ViewInformation2D aViewInformation2D(
1937 : basegfx::B2DHomMatrix(),
1938 : rOut.GetViewTransformation(),
1939 : aPaintRange,
1940 : 0,
1941 : 0.0,
1942 471 : uno::Sequence< beans::PropertyValue >());
1943 : drawinglayer::processor2d::BaseProcessor2D* pProcessor = drawinglayer::processor2d::createProcessor2DFromOutputDevice(
1944 : rOut,
1945 471 : aViewInformation2D);
1946 :
1947 471 : if(pProcessor)
1948 : {
1949 471 : pProcessor->process(*pPrimitives);
1950 :
1951 471 : delete pProcessor;
1952 :
1953 471 : return true;
1954 0 : }
1955 0 : }
1956 : }
1957 : }
1958 :
1959 3 : return false;
1960 : }
1961 :
1962 10886 : void DrawGraphic(
1963 : const SvxBrushItem *pBrush,
1964 : vcl::RenderContext *pOutDev,
1965 : const SwRect &rOrg,
1966 : const SwRect &rOut,
1967 : const sal_uInt8 nGrfNum,
1968 : const bool bConsiderBackgroundTransparency )
1969 : // Add 6th parameter to indicate that method should
1970 : // consider background transparency, saved in the color of the brush item
1971 : {
1972 10886 : SwViewShell &rSh = *gProp.pSGlobalShell;
1973 10886 : bool bReplaceGrfNum = GRFNUM_REPLACE == nGrfNum;
1974 10886 : bool bGrfNum = GRFNUM_NO != nGrfNum;
1975 10886 : Size aGrfSize;
1976 10886 : SvxGraphicPosition ePos = GPOS_NONE;
1977 10886 : if( pBrush && !bReplaceGrfNum )
1978 : {
1979 1643 : if( rSh.GetViewOptions()->IsGraphic() )
1980 : {
1981 : // load graphic directly in PDF import
1982 : // #i68953# - also during print load graphic directly.
1983 3286 : if ( (rSh).GetViewOptions()->IsPDFExport() ||
1984 1643 : rSh.GetOut()->GetOutDevType() == OUTDEV_PRINTER )
1985 : {
1986 0 : pBrush->PurgeMedium();
1987 0 : const_cast<SvxBrushItem*>(pBrush)->SetDoneLink( Link<>() );
1988 : }
1989 : else
1990 1643 : const_cast<SvxBrushItem*>(pBrush)->SetDoneLink( LINK(
1991 1643 : rSh.GetDoc(), SwDoc, BackgroundDone ) );
1992 1643 : OUString referer;
1993 1643 : SfxObjectShell * sh = rSh.GetDoc()->GetPersist();
1994 1643 : if (sh != 0 && sh->HasName()) {
1995 1599 : referer = sh->GetMedium()->GetName();
1996 : }
1997 1643 : const Graphic* pGrf = pBrush->GetGraphic(referer);
1998 1643 : if( pGrf && GRAPHIC_NONE != pGrf->GetType() )
1999 : {
2000 0 : ePos = pBrush->GetGraphicPos();
2001 0 : if( pGrf->IsSupportedGraphic() )
2002 : // don't the use the specific output device! Bug 94802
2003 0 : aGrfSize = ::GetGraphicSizeTwip( *pGrf, 0 );
2004 1643 : }
2005 : }
2006 : else
2007 0 : bReplaceGrfNum = bGrfNum;
2008 : }
2009 :
2010 10886 : SwRect aGrf;
2011 10886 : aGrf.SSize( aGrfSize );
2012 10886 : bool bDraw = true;
2013 10886 : bool bRetouche = true;
2014 10886 : switch ( ePos )
2015 : {
2016 : case GPOS_LT:
2017 0 : aGrf.Pos() = rOrg.Pos();
2018 0 : break;
2019 :
2020 : case GPOS_MT:
2021 0 : aGrf.Pos().Y() = rOrg.Top();
2022 0 : aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
2023 0 : break;
2024 :
2025 : case GPOS_RT:
2026 0 : aGrf.Pos().Y() = rOrg.Top();
2027 0 : aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
2028 0 : break;
2029 :
2030 : case GPOS_LM:
2031 0 : aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
2032 0 : aGrf.Pos().X() = rOrg.Left();
2033 0 : break;
2034 :
2035 : case GPOS_MM:
2036 0 : aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
2037 0 : aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
2038 0 : break;
2039 :
2040 : case GPOS_RM:
2041 0 : aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
2042 0 : aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
2043 0 : break;
2044 :
2045 : case GPOS_LB:
2046 0 : aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
2047 0 : aGrf.Pos().X() = rOrg.Left();
2048 0 : break;
2049 :
2050 : case GPOS_MB:
2051 0 : aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
2052 0 : aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
2053 0 : break;
2054 :
2055 : case GPOS_RB:
2056 0 : aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
2057 0 : aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
2058 0 : break;
2059 :
2060 : case GPOS_AREA:
2061 0 : aGrf = rOrg;
2062 : // Despite the fact that the background graphic has to fill the complete
2063 : // area, we already checked, whether the graphic will completely fill out
2064 : // the region the <rOut> that is to be painted. Thus, nothing has to be
2065 : // touched again.
2066 : // E.g. this is the case for a Fly Frame without a background
2067 : // brush positioned on the border of the page which inherited the background
2068 : // brush from the page.
2069 0 : bRetouche = !rOut.IsInside( aGrf );
2070 0 : break;
2071 :
2072 : case GPOS_TILED:
2073 : {
2074 : // draw background of tiled graphic before drawing tiled graphic in loop
2075 : // determine graphic object
2076 0 : GraphicObject* pGraphicObj = const_cast< GraphicObject* >(pBrush->GetGraphicObject());
2077 : // calculate aligned paint rectangle
2078 0 : SwRect aAlignedPaintRect = rOut;
2079 0 : ::SwAlignRect( aAlignedPaintRect, &rSh );
2080 : // draw background color for aligned paint rectangle
2081 0 : lcl_DrawGraphicBackgrd( *pBrush, pOutDev, aAlignedPaintRect, *pGraphicObj, bGrfNum, gProp );
2082 :
2083 : // set left-top-corner of background graphic to left-top-corner of the
2084 : // area, from which the background brush is determined.
2085 0 : aGrf.Pos() = rOrg.Pos();
2086 : // setup clipping at output device
2087 0 : pOutDev->Push( PushFlags::CLIPREGION );
2088 0 : pOutDev->IntersectClipRegion( rOut.SVRect() );
2089 : // use new method <GraphicObject::DrawTiled(::)>
2090 : {
2091 : // calculate paint offset
2092 0 : Point aPaintOffset( aAlignedPaintRect.Pos() - aGrf.Pos() );
2093 : // draw background graphic tiled for aligned paint rectangle
2094 : // #i42643#
2095 : // For PDF export, every draw operation for bitmaps takes a
2096 : // noticeable amount of place (~50 characters). Thus, optimize
2097 : // between tile bitmap size and number of drawing operations here.
2098 :
2099 : // A_out
2100 : // n_chars = k1 * ---------- + k2 * A_bitmap
2101 : // A_bitmap
2102 :
2103 : // minimum n_chars is obtained for (derive for A_bitmap,
2104 : // set to 0, take positive solution):
2105 : // k1
2106 : // A_bitmap = Sqrt( ---- A_out )
2107 : // k2
2108 :
2109 : // where k1 is the number of chars per draw operation, and
2110 : // k2 is the number of chars per bitmap pixel.
2111 : // This is approximately 50 and 7 for current PDF writer, respectively.
2112 :
2113 0 : const double k1( 50 );
2114 0 : const double k2( 7 );
2115 0 : const Size aSize( aAlignedPaintRect.SSize() );
2116 0 : const double Abitmap( k1/k2 * static_cast<double>(aSize.Width())*aSize.Height() );
2117 :
2118 : pGraphicObj->DrawTiled( pOutDev,
2119 : aAlignedPaintRect.SVRect(),
2120 0 : aGrf.SSize(),
2121 0 : Size( aPaintOffset.X(), aPaintOffset.Y() ),
2122 : NULL, GraphicManagerDrawFlags::STANDARD,
2123 0 : ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
2124 : }
2125 : // reset clipping at output device
2126 0 : pOutDev->Pop();
2127 : // set <bDraw> and <bRetouche> to false, indicating that background
2128 : // graphic and background are already drawn.
2129 0 : bDraw = bRetouche = false;
2130 : }
2131 0 : break;
2132 :
2133 : case GPOS_NONE:
2134 10886 : bDraw = false;
2135 10886 : break;
2136 :
2137 : default: OSL_ENSURE( !pOutDev, "new Graphic position?" );
2138 : }
2139 :
2140 : /// init variable <bGrfBackgrdAlreadDrawn> to indicate, if background of
2141 : /// graphic is already drawn or not.
2142 10886 : bool bGrfBackgrdAlreadyDrawn = false;
2143 10886 : if ( bRetouche )
2144 : {
2145 10886 : pOutDev->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
2146 10886 : pOutDev->SetLineColor();
2147 :
2148 : // check, if a existing background graphic (not filling the complete
2149 : // background) is transparent drawn and the background color is
2150 : // "no fill" respectively "auto fill", if background transparency
2151 : // has to be considered.
2152 : // If YES, memorise transparency of background graphic.
2153 : // check also, if background graphic bitmap is transparent.
2154 10886 : bool bTransparentGrfWithNoFillBackgrd = false;
2155 10886 : sal_Int32 nGrfTransparency = 0;
2156 10886 : bool bGrfIsTransparent = false;
2157 10886 : if ( (ePos != GPOS_NONE) &&
2158 0 : (ePos != GPOS_TILED) && (ePos != GPOS_AREA)
2159 : )
2160 : {
2161 0 : GraphicObject *pGrf = const_cast<GraphicObject*>(pBrush->GetGraphicObject());
2162 0 : if ( bConsiderBackgroundTransparency )
2163 : {
2164 0 : GraphicAttr pGrfAttr = pGrf->GetAttr();
2165 0 : if ( (pGrfAttr.GetTransparency() != 0) &&
2166 0 : (pBrush->GetColor() == COL_TRANSPARENT)
2167 : )
2168 : {
2169 0 : bTransparentGrfWithNoFillBackgrd = true;
2170 0 : nGrfTransparency = pGrfAttr.GetTransparency();
2171 0 : }
2172 : }
2173 0 : if ( pGrf->IsTransparent() )
2174 : {
2175 0 : bGrfIsTransparent = true;
2176 : }
2177 : }
2178 :
2179 : // to get color of brush, check background color against COL_TRANSPARENT ("no fill"/"auto fill")
2180 : // instead of checking, if transparency is not set.
2181 3286 : const Color aColor( pBrush &&
2182 15818 : ( !(pBrush->GetColor() == COL_TRANSPARENT) ||
2183 : gProp.bSFlyMetafile )
2184 : ? pBrush->GetColor()
2185 21769 : : aGlobalRetoucheColor );
2186 :
2187 : // determine, if background region have to be
2188 : // drawn transparent.
2189 : // background region has to be drawn transparent, if
2190 : // background transparency have to be considered
2191 : // AND
2192 : // ( background color is transparent OR
2193 : // background graphic is transparent and background color is "no fill"
2194 : // )
2195 :
2196 : enum DrawStyle {
2197 : Default,
2198 : Transparent,
2199 10886 : } eDrawStyle = Default;
2200 :
2201 10902 : if (bConsiderBackgroundTransparency &&
2202 11 : ( ( aColor.GetTransparency() != 0) ||
2203 : bTransparentGrfWithNoFillBackgrd ) )
2204 : {
2205 7 : eDrawStyle = Transparent;
2206 : }
2207 :
2208 : // #i75614# reset draw mode in high contrast mode in order to get fill color set
2209 10886 : const DrawModeFlags nOldDrawMode = pOutDev->GetDrawMode();
2210 21375 : if ( gProp.pSGlobalShell->GetWin() &&
2211 10489 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
2212 : {
2213 0 : pOutDev->SetDrawMode( DrawModeFlags::Default );
2214 : }
2215 :
2216 : // OD 06.08.2002 #99657# - if background region has to be drawn
2217 : // transparent, set only the RGB values of the background color as
2218 : // the fill color for the output device.
2219 10886 : switch (eDrawStyle)
2220 : {
2221 : case Transparent:
2222 : {
2223 7 : if( pOutDev->GetFillColor() != aColor.GetRGBColor() )
2224 7 : pOutDev->SetFillColor( aColor.GetRGBColor() );
2225 7 : break;
2226 : }
2227 : default:
2228 : {
2229 10879 : if( pOutDev->GetFillColor() != aColor )
2230 824 : pOutDev->SetFillColor( aColor );
2231 10879 : break;
2232 : }
2233 : }
2234 :
2235 : // #i75614#
2236 : // restore draw mode
2237 10886 : pOutDev->SetDrawMode( nOldDrawMode );
2238 :
2239 : // OD 02.09.2002 #99657#
2240 10886 : switch (eDrawStyle)
2241 : {
2242 : case Transparent:
2243 : {
2244 : // background region have to be drawn transparent.
2245 : // Thus, create a poly-polygon from the region and draw it with
2246 : // the corresponding transparency precent.
2247 7 : tools::PolyPolygon aDrawPoly( rOut.SVRect() );
2248 7 : if ( aGrf.HasArea() )
2249 : {
2250 0 : if ( !bGrfIsTransparent )
2251 : {
2252 : // subtract area of background graphic from draw area
2253 : // OD 08.10.2002 #103898# - consider only that part of the
2254 : // graphic area that is overlapping with draw area.
2255 0 : SwRect aTmpGrf = aGrf;
2256 0 : aTmpGrf.Intersection( rOut );
2257 0 : if ( aTmpGrf.HasArea() )
2258 : {
2259 0 : Polygon aGrfPoly( aTmpGrf.SVRect() );
2260 0 : aDrawPoly.Insert( aGrfPoly );
2261 : }
2262 : }
2263 : else
2264 0 : bGrfBackgrdAlreadyDrawn = true;
2265 : }
2266 : // calculate transparency percent:
2267 : // ( <transparency value[0x01..0xFF]>*100 + 0x7F ) / 0xFF
2268 : // If there is a background graphic with a background color "no fill"/"auto fill",
2269 : // the transparency value is taken from the background graphic,
2270 : // otherwise take the transparency value from the color.
2271 : sal_Int8 nTransparencyPercent = static_cast<sal_Int8>(
2272 7 : (( bTransparentGrfWithNoFillBackgrd ? nGrfTransparency : aColor.GetTransparency()
2273 14 : )*100 + 0x7F)/0xFF);
2274 : // draw poly-polygon transparent
2275 7 : pOutDev->DrawTransparent( aDrawPoly, nTransparencyPercent );
2276 :
2277 7 : break;
2278 : }
2279 : case Default:
2280 : default:
2281 : {
2282 10879 : SwRegionRects aRegion( rOut, 4 );
2283 10879 : if ( !bGrfIsTransparent )
2284 10879 : aRegion -= aGrf;
2285 : else
2286 0 : bGrfBackgrdAlreadyDrawn = true;
2287 : // loop rectangles of background region, which has to be drawn
2288 21758 : for( size_t i = 0; i < aRegion.size(); ++i )
2289 : {
2290 10879 : pOutDev->DrawRect( aRegion[i].SVRect() );
2291 10879 : }
2292 : }
2293 : }
2294 10886 : pOutDev ->Pop();
2295 : }
2296 :
2297 10886 : if( bDraw && aGrf.IsOver( rOut ) )
2298 : // OD 02.09.2002 #99657#
2299 : // add parameter <bGrfBackgrdAlreadyDrawn>
2300 : lcl_DrawGraphic( *pBrush, pOutDev, rSh, aGrf, rOut, true, bGrfNum, gProp,
2301 0 : bGrfBackgrdAlreadyDrawn );
2302 :
2303 10886 : if( bReplaceGrfNum )
2304 : {
2305 0 : const BitmapEx& rBmp = SwViewShell::GetReplacementBitmap( false );
2306 0 : vcl::Font aTmp( pOutDev->GetFont() );
2307 0 : Graphic::DrawEx( pOutDev, aEmptyOUStr, aTmp, rBmp, rOrg.Pos(), rOrg.SSize() );
2308 : }
2309 10886 : }
2310 :
2311 : /**
2312 : * Local helper for SwRootFrm::Paint(..) - Adjust given rectangle to pixel size
2313 : *
2314 : * By OD at 27.09.2002 for #103636#
2315 : * In order to avoid paint errors caused by multiple alignments (e.g. ::SwAlignRect(..))
2316 : * and other changes to the to be painted rectangle, this method is called for the
2317 : * rectangle to be painted in order to adjust it to the pixel it is overlapping
2318 : */
2319 9249 : static void lcl_AdjustRectToPixelSize( SwRect& io_aSwRect, const vcl::RenderContext &aOut )
2320 : {
2321 : // local constant object of class <Size> to determine number of Twips
2322 : // representing a pixel.
2323 9249 : const Size aTwipToPxSize( aOut.PixelToLogic( Size( 1,1 )) );
2324 :
2325 : // local object of class <Rectangle> in Twip coordinates
2326 : // calculated from given rectangle aligned to pixel centers.
2327 : const Rectangle aPxCenterRect = aOut.PixelToLogic(
2328 9249 : aOut.LogicToPixel( io_aSwRect.SVRect() ) );
2329 :
2330 : // local constant object of class <Rectangle> representing given rectangle
2331 : // in pixel.
2332 9249 : const Rectangle aOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
2333 :
2334 : // calculate adjusted rectangle from pixel centered rectangle.
2335 : // Due to rounding differences <aPxCenterRect> doesn't exactly represents
2336 : // the Twip-centers. Thus, adjust borders by half of pixel width/height plus 1.
2337 : // Afterwards, adjust calculated Twip-positions of the all borders.
2338 9249 : Rectangle aSizedRect = aPxCenterRect;
2339 9249 : aSizedRect.Left() -= (aTwipToPxSize.Width()/2 + 1);
2340 9249 : aSizedRect.Right() += (aTwipToPxSize.Width()/2 + 1);
2341 9249 : aSizedRect.Top() -= (aTwipToPxSize.Height()/2 + 1);
2342 9249 : aSizedRect.Bottom() += (aTwipToPxSize.Height()/2 + 1);
2343 :
2344 : // adjust left()
2345 27822 : while ( (aOut.LogicToPixel(aSizedRect)).Left() < aOrgPxRect.Left() )
2346 : {
2347 9324 : ++aSizedRect.Left();
2348 : }
2349 : // adjust right()
2350 27878 : while ( (aOut.LogicToPixel(aSizedRect)).Right() > aOrgPxRect.Right() )
2351 : {
2352 9380 : --aSizedRect.Right();
2353 : }
2354 : // adjust top()
2355 27846 : while ( (aOut.LogicToPixel(aSizedRect)).Top() < aOrgPxRect.Top() )
2356 : {
2357 9348 : ++aSizedRect.Top();
2358 : }
2359 : // adjust bottom()
2360 27882 : while ( (aOut.LogicToPixel(aSizedRect)).Bottom() > aOrgPxRect.Bottom() )
2361 : {
2362 9384 : --aSizedRect.Bottom();
2363 : }
2364 :
2365 9249 : io_aSwRect = SwRect( aSizedRect );
2366 :
2367 : #if OSL_DEBUG_LEVEL > 0
2368 : Rectangle aTestOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
2369 : Rectangle aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2370 : OSL_ENSURE( aTestOrgPxRect == aTestNewPxRect,
2371 : "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size");
2372 : // check Left()
2373 : --aSizedRect.Left();
2374 : aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2375 : OSL_ENSURE( aTestOrgPxRect.Left() >= (aTestNewPxRect.Left()+1),
2376 : "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted");
2377 : ++aSizedRect.Left();
2378 : // check Right()
2379 : ++aSizedRect.Right();
2380 : aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2381 : OSL_ENSURE( aTestOrgPxRect.Right() <= (aTestNewPxRect.Right()-1),
2382 : "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted");
2383 : --aSizedRect.Right();
2384 : // check Top()
2385 : --aSizedRect.Top();
2386 : aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2387 : OSL_ENSURE( aTestOrgPxRect.Top() >= (aTestNewPxRect.Top()+1),
2388 : "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted");
2389 : ++aSizedRect.Top();
2390 : // check Bottom()
2391 : ++aSizedRect.Bottom();
2392 : aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
2393 : OSL_ENSURE( aTestOrgPxRect.Bottom() <= (aTestNewPxRect.Bottom()-1),
2394 : "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted");
2395 : --aSizedRect.Bottom();
2396 : #endif
2397 9249 : }
2398 :
2399 : // FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES START
2400 :
2401 : struct SwLineEntry
2402 : {
2403 : SwTwips mnKey;
2404 : SwTwips mnStartPos;
2405 : SwTwips mnEndPos;
2406 : SwTwips mnOffset;
2407 :
2408 : bool mbOffsetPerp;
2409 : bool mbOffsetStart;
2410 : bool mbOffsetEnd;
2411 :
2412 : svx::frame::Style maAttribute;
2413 :
2414 : enum OverlapType { NO_OVERLAP, OVERLAP1, OVERLAP2, OVERLAP3 };
2415 :
2416 : public:
2417 : SwLineEntry( SwTwips nKey,
2418 : SwTwips nStartPos,
2419 : SwTwips nEndPos,
2420 : const svx::frame::Style& rAttribute );
2421 :
2422 : OverlapType Overlaps( const SwLineEntry& rComp ) const;
2423 : };
2424 :
2425 50640 : SwLineEntry::SwLineEntry( SwTwips nKey,
2426 : SwTwips nStartPos,
2427 : SwTwips nEndPos,
2428 : const svx::frame::Style& rAttribute )
2429 : : mnKey( nKey ),
2430 : mnStartPos( nStartPos ),
2431 : mnEndPos( nEndPos ),
2432 : mnOffset( 0 ),
2433 : mbOffsetPerp(false),
2434 : mbOffsetStart(false),
2435 : mbOffsetEnd(false),
2436 50640 : maAttribute( rAttribute )
2437 : {
2438 50640 : }
2439 :
2440 : /*
2441 :
2442 : 1. ---------- rOld
2443 : ---------- rNew
2444 :
2445 : 2. ---------- rOld
2446 : ------------- rNew
2447 :
2448 : 3. ------- rOld
2449 : ------------- rNew
2450 :
2451 : 4. ------------- rOld
2452 : ---------- rNew
2453 :
2454 : 5. ---------- rOld
2455 : ---- rNew
2456 :
2457 : 6. ---------- rOld
2458 : ---------- rNew
2459 :
2460 : 7. ------------- rOld
2461 : ---------- rNew
2462 :
2463 : 8. ---------- rOld
2464 : ------------- rNew
2465 :
2466 : 9. ---------- rOld
2467 : ---------- rNew
2468 : */
2469 :
2470 59460 : SwLineEntry::OverlapType SwLineEntry::Overlaps( const SwLineEntry& rNew ) const
2471 : {
2472 59460 : SwLineEntry::OverlapType eRet = OVERLAP3;
2473 :
2474 59460 : if ( mnStartPos >= rNew.mnEndPos || mnEndPos <= rNew.mnStartPos )
2475 50650 : eRet = NO_OVERLAP;
2476 :
2477 : // 1, 2, 3
2478 8810 : else if ( mnEndPos < rNew.mnEndPos )
2479 158 : eRet = OVERLAP1;
2480 :
2481 : // 4, 5, 6, 7
2482 8652 : else if ( mnStartPos <= rNew.mnStartPos && mnEndPos >= rNew.mnEndPos )
2483 8650 : eRet = OVERLAP2;
2484 :
2485 : // 8, 9
2486 59460 : return eRet;
2487 : }
2488 :
2489 : struct lt_SwLineEntry
2490 : {
2491 83451 : bool operator()( const SwLineEntry& e1, const SwLineEntry& e2 ) const
2492 : {
2493 83451 : return e1.mnStartPos < e2.mnStartPos;
2494 : }
2495 : };
2496 :
2497 : typedef std::set< SwLineEntry, lt_SwLineEntry > SwLineEntrySet;
2498 : typedef std::set< SwLineEntry, lt_SwLineEntry >::iterator SwLineEntrySetIter;
2499 : typedef std::set< SwLineEntry, lt_SwLineEntry >::const_iterator SwLineEntrySetConstIter;
2500 : typedef std::map< SwTwips, SwLineEntrySet > SwLineEntryMap;
2501 : typedef std::map< SwTwips, SwLineEntrySet >::iterator SwLineEntryMapIter;
2502 : typedef std::map< SwTwips, SwLineEntrySet >::const_iterator SwLineEntryMapConstIter;
2503 :
2504 525 : class SwTabFrmPainter
2505 : {
2506 : SwLineEntryMap maVertLines;
2507 : SwLineEntryMap maHoriLines;
2508 : const SwTabFrm& mrTabFrm;
2509 :
2510 : void Insert( SwLineEntry&, bool bHori );
2511 : void Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem );
2512 : void HandleFrame( const SwLayoutFrm& rFrm );
2513 : void FindStylesForLine( const Point&,
2514 : const Point&,
2515 : svx::frame::Style*,
2516 : bool bHori ) const;
2517 :
2518 : void AdjustTopLeftFrames();
2519 :
2520 : public:
2521 : explicit SwTabFrmPainter( const SwTabFrm& rTabFrm );
2522 :
2523 : void PaintLines( OutputDevice& rDev, const SwRect& rRect ) const;
2524 : };
2525 :
2526 525 : SwTabFrmPainter::SwTabFrmPainter( const SwTabFrm& rTabFrm )
2527 525 : : mrTabFrm( rTabFrm )
2528 : {
2529 525 : HandleFrame( rTabFrm );
2530 525 : AdjustTopLeftFrames();
2531 525 : }
2532 :
2533 8804 : void SwTabFrmPainter::HandleFrame( const SwLayoutFrm& rLayoutFrm )
2534 : {
2535 : // Add border lines of cell frames. Skip covered cells. Skip cells
2536 : // in special row span row, which do not have a negative row span:
2537 8804 : if ( rLayoutFrm.IsCellFrm() && !rLayoutFrm.IsCoveredCell() )
2538 : {
2539 6092 : const SwCellFrm* pThisCell = static_cast<const SwCellFrm*>(&rLayoutFrm);
2540 6092 : const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pThisCell->GetUpper());
2541 6092 : const long nRowSpan = pThisCell->GetTabBox()->getRowSpan();
2542 6092 : if ( !pRowFrm->IsRowSpanLine() || nRowSpan > 1 || nRowSpan < -1 )
2543 : {
2544 6092 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), &rLayoutFrm );
2545 6092 : const SwBorderAttrs& rAttrs = *aAccess.Get();
2546 6092 : const SvxBoxItem& rBox = rAttrs.GetBox();
2547 6092 : Insert( rLayoutFrm, rBox );
2548 : }
2549 : }
2550 :
2551 : // Recurse into lower layout frames, but do not recurse into lower tabframes.
2552 8804 : const SwFrm* pLower = rLayoutFrm.Lower();
2553 32614 : while ( pLower )
2554 : {
2555 15006 : const SwLayoutFrm* pLowerLayFrm = dynamic_cast<const SwLayoutFrm*>(pLower);
2556 15006 : if ( pLowerLayFrm && !pLowerLayFrm->IsTabFrm() )
2557 8279 : HandleFrame( *pLowerLayFrm );
2558 :
2559 15006 : pLower = pLower->GetNext();
2560 : }
2561 8804 : }
2562 :
2563 525 : void SwTabFrmPainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) const
2564 : {
2565 : // #i16816# tagged pdf support
2566 525 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, rDev );
2567 :
2568 525 : SwLineEntryMapConstIter aIter = maHoriLines.begin();
2569 525 : bool bHori = true;
2570 :
2571 : // color for subsidiary lines:
2572 525 : const Color& rCol( SwViewOption::GetTableBoundariesColor() );
2573 :
2574 : // high contrast mode:
2575 : // overrides the color of non-subsidiary lines.
2576 525 : const Color* pHCColor = 0;
2577 525 : DrawModeFlags nOldDrawMode = rDev.GetDrawMode();
2578 1049 : if( gProp.pSGlobalShell->GetWin() &&
2579 524 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
2580 : {
2581 0 : pHCColor = &SwViewOption::GetFontColor();
2582 0 : rDev.SetDrawMode( DrawModeFlags::Default );
2583 : }
2584 :
2585 525 : const SwFrm* pUpper = mrTabFrm.GetUpper();
2586 525 : SwRect aUpper( pUpper->Prt() );
2587 525 : aUpper.Pos() += pUpper->Frm().Pos();
2588 525 : SwRect aUpperAligned( aUpper );
2589 525 : ::SwAlignRect( aUpperAligned, gProp.pSGlobalShell );
2590 :
2591 : while ( true )
2592 : {
2593 5279 : if ( bHori && aIter == maHoriLines.end() )
2594 : {
2595 525 : aIter = maVertLines.begin();
2596 525 : bHori = false;
2597 : }
2598 :
2599 5279 : if ( !bHori && aIter == maVertLines.end() )
2600 525 : break;
2601 :
2602 4754 : const SwLineEntrySet& rEntrySet = (*aIter).second;
2603 62004 : for (SwLineEntrySetConstIter aSetIter = rEntrySet.begin();
2604 41336 : aSetIter != rEntrySet.end(); ++aSetIter)
2605 : {
2606 15914 : const SwLineEntry& rEntry = *aSetIter;
2607 15914 : const svx::frame::Style& rEntryStyle( (*aSetIter).maAttribute );
2608 :
2609 15914 : Point aStart, aEnd;
2610 15914 : if ( bHori )
2611 : {
2612 7651 : aStart.X() = rEntry.mnStartPos;
2613 7651 : aStart.Y() = rEntry.mnKey;
2614 7651 : aEnd.X() = rEntry.mnEndPos;
2615 7651 : aEnd.Y() = rEntry.mnKey;
2616 : }
2617 : else
2618 : {
2619 8263 : aStart.X() = rEntry.mnKey;
2620 8263 : aStart.Y() = rEntry.mnStartPos;
2621 8263 : aEnd.X() = rEntry.mnKey;
2622 8263 : aEnd.Y() = rEntry.mnEndPos;
2623 : }
2624 :
2625 15914 : svx::frame::Style aStyles[ 7 ];
2626 15914 : aStyles[ 0 ] = rEntryStyle;
2627 15914 : FindStylesForLine( aStart, aEnd, aStyles, bHori );
2628 :
2629 : // Account for double line thicknesses for the top- and left-most borders.
2630 15914 : if (rEntry.mnOffset)
2631 : {
2632 18 : if (bHori)
2633 : {
2634 14 : if (rEntry.mbOffsetPerp)
2635 : {
2636 : // Apply offset in perpendicular direction.
2637 14 : aStart.Y() -= rEntry.mnOffset;
2638 14 : aEnd.Y() -= rEntry.mnOffset;
2639 : }
2640 14 : if (rEntry.mbOffsetStart)
2641 : // Apply offset at the start of a border.
2642 4 : aStart.X() -= rEntry.mnOffset;
2643 14 : if (rEntry.mbOffsetEnd)
2644 : // Apply offset at the end of a border.
2645 4 : aEnd.X() += rEntry.mnOffset;
2646 : }
2647 : else
2648 : {
2649 4 : if (rEntry.mbOffsetPerp)
2650 : {
2651 : // Apply offset in perpendicular direction.
2652 4 : aStart.X() -= rEntry.mnOffset;
2653 4 : aEnd.X() -= rEntry.mnOffset;
2654 : }
2655 4 : if (rEntry.mbOffsetStart)
2656 : // Apply offset at the start of a border.
2657 2 : aStart.Y() -= rEntry.mnOffset;
2658 4 : if (rEntry.mbOffsetEnd)
2659 : // Apply offset at the end of a border.
2660 2 : aEnd.Y() += rEntry.mnOffset;
2661 : }
2662 : }
2663 :
2664 15914 : SwRect aRepaintRect( aStart, aEnd );
2665 :
2666 : // the repaint rectangle has to be moved a bit for the centered lines:
2667 15914 : SwTwips nRepaintRectSize = !rEntryStyle.GetWidth() ? 1 : rEntryStyle.GetWidth();
2668 15914 : if ( bHori )
2669 : {
2670 7651 : aRepaintRect.Height( 2 * nRepaintRectSize );
2671 7651 : aRepaintRect.Pos().Y() -= nRepaintRectSize;
2672 : }
2673 : else
2674 : {
2675 8263 : aRepaintRect.Width( 2 * nRepaintRectSize );
2676 8263 : aRepaintRect.Pos().X() -= nRepaintRectSize;
2677 : }
2678 :
2679 15914 : if (!rRect.IsOver(aRepaintRect))
2680 : {
2681 6846 : continue;
2682 : }
2683 :
2684 : // subsidiary lines
2685 9068 : const Color* pTmpColor = 0;
2686 9068 : if (0 == aStyles[ 0 ].GetWidth())
2687 : {
2688 611 : if (isTableBoundariesEnabled() && gProp.pSGlobalShell->GetWin())
2689 611 : aStyles[ 0 ].Set( rCol, rCol, rCol, false, 1, 0, 0 );
2690 : else
2691 0 : aStyles[0].SetType(table::BorderLineStyle::NONE);
2692 : }
2693 : else
2694 8457 : pTmpColor = pHCColor;
2695 :
2696 : // The (twip) positions will be adjusted to meet these requirements:
2697 : // 1. The y coordinates are located in the middle of the pixel grid
2698 : // 2. The x coordinated are located at the beginning of the pixel grid
2699 : // This is done, because the horizontal lines are painted "at
2700 : // beginning", whereas the vertical lines are painted "centered".
2701 : // By making the line sizes a multiple of one pixel size, we can
2702 : // assure that all lines having the same twip size have the same
2703 : // pixel size, independent of their position on the screen.
2704 9068 : Point aPaintStart = rDev.PixelToLogic( rDev.LogicToPixel(aStart) );
2705 9068 : Point aPaintEnd = rDev.PixelToLogic( rDev.LogicToPixel(aEnd) );
2706 :
2707 9068 : if (gProp.pSGlobalShell->GetWin())
2708 : {
2709 : // The table borders do not use SwAlignRect, but all the other frames do.
2710 : // Therefore we tweak the outer borders a bit to achieve that the outer
2711 : // borders match the subsidiary lines of the upper:
2712 9063 : if (aStart.X() == aUpper.Left())
2713 1533 : aPaintStart.X() = aUpperAligned.Left();
2714 7530 : else if (aStart.X() == aUpper._Right())
2715 69 : aPaintStart.X() = aUpperAligned._Right();
2716 9063 : if (aStart.Y() == aUpper.Top())
2717 1457 : aPaintStart.Y() = aUpperAligned.Top();
2718 7606 : else if (aStart.Y() == aUpper._Bottom())
2719 10 : aPaintStart.Y() = aUpperAligned._Bottom();
2720 :
2721 9063 : if (aEnd.X() == aUpper.Left())
2722 633 : aPaintEnd.X() = aUpperAligned.Left();
2723 8430 : else if (aEnd.X() == aUpper._Right())
2724 654 : aPaintEnd.X() = aUpperAligned._Right();
2725 9063 : if (aEnd.Y() == aUpper.Top())
2726 562 : aPaintEnd.Y() = aUpperAligned.Top();
2727 8501 : else if (aEnd.Y() == aUpper._Bottom())
2728 22 : aPaintEnd.Y() = aUpperAligned._Bottom();
2729 : }
2730 :
2731 : // logically vertical lines are painted centered on the line,
2732 : // logically horizontal lines are painted "below" the line
2733 9068 : bool const isBelow((mrTabFrm.IsVertical()) ? !bHori : bHori);
2734 : double const offsetStart = (isBelow)
2735 4625 : ? aStyles[0].GetWidth() / 2.0
2736 4443 : : std::max<double>(aStyles[1].GetWidth(),
2737 18136 : aStyles[3].GetWidth()) / 2.0;
2738 : double const offsetEnd = (isBelow)
2739 4625 : ? aStyles[0].GetWidth() / 2.0
2740 4443 : : std::max<double>(aStyles[4].GetWidth(),
2741 18136 : aStyles[6].GetWidth()) / 2.0;
2742 9068 : if (mrTabFrm.IsVertical())
2743 : {
2744 0 : aPaintStart.X() -= static_cast<long>(offsetStart + 0.5);
2745 0 : aPaintEnd.X() -= static_cast<long>(offsetEnd + 0.5);
2746 : }
2747 : else
2748 : {
2749 9068 : aPaintStart.Y() += static_cast<long>(offsetStart + 0.5);
2750 9068 : aPaintEnd.Y() += static_cast<long>(offsetEnd + 0.5);
2751 : }
2752 :
2753 9068 : if (bHori)
2754 : {
2755 : mrTabFrm.ProcessPrimitives( svx::frame::CreateBorderPrimitives(
2756 : aPaintStart,
2757 : aPaintEnd,
2758 : aStyles[ 0 ], // current style
2759 : aStyles[ 1 ], // aLFromT
2760 : aStyles[ 2 ], // aLFromL
2761 : aStyles[ 3 ], // aLFromB
2762 : aStyles[ 4 ], // aRFromT
2763 : aStyles[ 5 ], // aRFromR
2764 : aStyles[ 6 ], // aRFromB
2765 : pTmpColor)
2766 4625 : );
2767 : }
2768 : else
2769 : {
2770 : mrTabFrm.ProcessPrimitives( svx::frame::CreateBorderPrimitives(
2771 : aPaintEnd,
2772 : aPaintStart,
2773 : aStyles[ 0 ], // current style
2774 : aStyles[ 4 ], // aBFromL
2775 : aStyles[ 5 ], // aBFromB
2776 : aStyles[ 6 ], // aBFromR
2777 : aStyles[ 1 ], // aTFromL
2778 : aStyles[ 2 ], // aTFromT
2779 : aStyles[ 3 ], // aTFromR
2780 : pTmpColor)
2781 4443 : );
2782 : }
2783 : }
2784 :
2785 4754 : ++aIter;
2786 : }
2787 :
2788 : // restore output device:
2789 525 : rDev.SetDrawMode( nOldDrawMode );
2790 525 : }
2791 :
2792 : /**
2793 : * Finds the lines that join the line defined by (StartPoint, EndPoint) in either
2794 : * StartPoint or Endpoint. The styles of these lines are required for DR's magic
2795 : * line painting functions
2796 : */
2797 15914 : void SwTabFrmPainter::FindStylesForLine( const Point& rStartPoint,
2798 : const Point& rEndPoint,
2799 : svx::frame::Style* pStyles,
2800 : bool bHori ) const
2801 : {
2802 : // pStyles[ 1 ] = bHori ? aLFromT : TFromL
2803 : // pStyles[ 2 ] = bHori ? aLFromL : TFromT,
2804 : // pStyles[ 3 ] = bHori ? aLFromB : TFromR,
2805 : // pStyles[ 4 ] = bHori ? aRFromT : BFromL,
2806 : // pStyles[ 5 ] = bHori ? aRFromR : BFromB,
2807 : // pStyles[ 6 ] = bHori ? aRFromB : BFromR,
2808 :
2809 15914 : SwLineEntryMapConstIter aMapIter = maVertLines.find( rStartPoint.X() );
2810 : OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" );
2811 15914 : const SwLineEntrySet& rVertSet = (*aMapIter).second;
2812 15914 : SwLineEntrySetConstIter aIter = rVertSet.begin();
2813 :
2814 134670 : while ( aIter != rVertSet.end() )
2815 : {
2816 102842 : const SwLineEntry& rEntry = *aIter;
2817 102842 : if ( bHori )
2818 : {
2819 46425 : if ( rStartPoint.Y() == rEntry.mnStartPos )
2820 6094 : pStyles[ 3 ] = rEntry.maAttribute;
2821 40331 : else if ( rStartPoint.Y() == rEntry.mnEndPos )
2822 6096 : pStyles[ 1 ] = rEntry.maAttribute;
2823 : }
2824 : else
2825 : {
2826 56417 : if ( rStartPoint.Y() == rEntry.mnEndPos )
2827 6181 : pStyles[ 2 ] = rEntry.maAttribute;
2828 50236 : else if ( rEndPoint.Y() == rEntry.mnStartPos )
2829 6181 : pStyles[ 5 ] = rEntry.maAttribute;
2830 : }
2831 102842 : ++aIter;
2832 : }
2833 :
2834 15914 : aMapIter = maHoriLines.find( rStartPoint.Y() );
2835 : OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" );
2836 15914 : const SwLineEntrySet& rHoriSet = (*aMapIter).second;
2837 15914 : aIter = rHoriSet.begin();
2838 :
2839 89459 : while ( aIter != rHoriSet.end() )
2840 : {
2841 57631 : const SwLineEntry& rEntry = *aIter;
2842 57631 : if ( bHori )
2843 : {
2844 28775 : if ( rStartPoint.X() == rEntry.mnEndPos )
2845 4957 : pStyles[ 2 ] = rEntry.maAttribute;
2846 23818 : else if ( rEndPoint.X() == rEntry.mnStartPos )
2847 4957 : pStyles[ 5 ] = rEntry.maAttribute;
2848 : }
2849 : else
2850 : {
2851 28856 : if ( rStartPoint.X() == rEntry.mnEndPos )
2852 6094 : pStyles[ 1 ] = rEntry.maAttribute;
2853 22762 : else if ( rStartPoint.X() == rEntry.mnStartPos )
2854 6094 : pStyles[ 3 ] = rEntry.maAttribute;
2855 : }
2856 57631 : ++aIter;
2857 : }
2858 :
2859 15914 : if ( bHori )
2860 : {
2861 7651 : aMapIter = maVertLines.find( rEndPoint.X() );
2862 : OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" );
2863 7651 : const SwLineEntrySet& rVertSet2 = (*aMapIter).second;
2864 7651 : aIter = rVertSet2.begin();
2865 :
2866 61738 : while ( aIter != rVertSet2.end() )
2867 : {
2868 46436 : const SwLineEntry& rEntry = *aIter;
2869 46436 : if ( rEndPoint.Y() == rEntry.mnStartPos )
2870 6094 : pStyles[ 6 ] = rEntry.maAttribute;
2871 40342 : else if ( rEndPoint.Y() == rEntry.mnEndPos )
2872 6094 : pStyles[ 4 ] = rEntry.maAttribute;
2873 46436 : ++aIter;
2874 : }
2875 : }
2876 : else
2877 : {
2878 8263 : aMapIter = maHoriLines.find( rEndPoint.Y() );
2879 : OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" );
2880 8263 : const SwLineEntrySet& rHoriSet2 = (*aMapIter).second;
2881 8263 : aIter = rHoriSet2.begin();
2882 :
2883 45513 : while ( aIter != rHoriSet2.end() )
2884 : {
2885 28987 : const SwLineEntry& rEntry = *aIter;
2886 28987 : if ( rEndPoint.X() == rEntry.mnEndPos )
2887 6094 : pStyles[ 4 ] = rEntry.maAttribute;
2888 22893 : else if ( rEndPoint.X() == rEntry.mnStartPos )
2889 6096 : pStyles[ 6 ] = rEntry.maAttribute;
2890 28987 : ++aIter;
2891 : }
2892 : }
2893 15914 : }
2894 :
2895 : namespace {
2896 :
2897 1050 : void calcOffsetForDoubleLine( SwLineEntryMap& rLines )
2898 : {
2899 1050 : SwLineEntryMap aNewLines;
2900 1050 : SwLineEntryMap::iterator it = rLines.begin(), itEnd = rLines.end();
2901 1050 : bool bFirst = true;
2902 5804 : for (; it != itEnd; ++it)
2903 : {
2904 4754 : if (bFirst)
2905 : {
2906 : // First line needs to be offset to account for double line thickness.
2907 1050 : SwLineEntrySet aNewSet;
2908 1050 : const SwLineEntrySet& rSet = it->second;
2909 1050 : SwLineEntrySet::iterator itSet = rSet.begin(), itSetEnd = rSet.end();
2910 1050 : size_t nEntryCount = rSet.size();
2911 4579 : for (size_t i = 0; itSet != itSetEnd; ++itSet, ++i)
2912 : {
2913 3529 : SwLineEntry aLine = *itSet;
2914 3529 : if (aLine.maAttribute.Secn())
2915 : {
2916 : // Apply offset only for double lines.
2917 18 : aLine.mnOffset = static_cast<SwTwips>(aLine.maAttribute.Dist());
2918 18 : aLine.mbOffsetPerp = true;
2919 :
2920 18 : if (i == 0)
2921 6 : aLine.mbOffsetStart = true;
2922 18 : if (i == nEntryCount - 1)
2923 6 : aLine.mbOffsetEnd = true;
2924 : }
2925 :
2926 3529 : aNewSet.insert(aLine);
2927 : }
2928 :
2929 1050 : aNewLines.insert(SwLineEntryMap::value_type(it->first, aNewSet));
2930 : }
2931 : else
2932 3704 : aNewLines.insert(SwLineEntryMap::value_type(it->first, it->second));
2933 :
2934 4754 : bFirst = false;
2935 : }
2936 1050 : rLines.swap(aNewLines);
2937 1050 : }
2938 :
2939 : }
2940 :
2941 525 : void SwTabFrmPainter::AdjustTopLeftFrames()
2942 : {
2943 525 : calcOffsetForDoubleLine(maHoriLines);
2944 525 : calcOffsetForDoubleLine(maVertLines);
2945 525 : }
2946 :
2947 : /**
2948 : * Special case: #i9860#
2949 : * first line in follow table without repeated headlines
2950 : */
2951 6092 : static bool lcl_IsFirstRowInFollowTableWithoutRepeatedHeadlines(
2952 : SwTabFrm const& rTabFrm, SwFrm const& rFrm, SvxBoxItem const& rBoxItem)
2953 : {
2954 : SwRowFrm const*const pThisRowFrm =
2955 6092 : dynamic_cast<const SwRowFrm*>(rFrm.GetUpper());
2956 : return (pThisRowFrm
2957 6092 : && (pThisRowFrm->GetUpper() == &rTabFrm)
2958 6092 : && rTabFrm.IsFollow()
2959 69 : && !rTabFrm.GetTable()->GetRowsToRepeat()
2960 69 : && ( !pThisRowFrm->GetPrev()
2961 120 : || static_cast<const SwRowFrm*>(pThisRowFrm->GetPrev())
2962 60 : ->IsRowSpanLine())
2963 9 : && !rBoxItem.GetTop()
2964 6100 : && rBoxItem.GetBottom());
2965 : }
2966 :
2967 6092 : void SwTabFrmPainter::Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem )
2968 : {
2969 : // build 4 line entries for the 4 borders:
2970 6092 : SwRect aBorderRect = rFrm.Frm();
2971 6092 : if ( rFrm.IsTabFrm() )
2972 : {
2973 0 : aBorderRect = rFrm.Prt();
2974 0 : aBorderRect.Pos() += rFrm.Frm().Pos();
2975 : }
2976 :
2977 : bool const bBottomAsTop(lcl_IsFirstRowInFollowTableWithoutRepeatedHeadlines(
2978 6092 : mrTabFrm, rFrm, rBoxItem));
2979 6092 : bool const bVert = mrTabFrm.IsVertical();
2980 6092 : bool const bR2L = mrTabFrm.IsRightToLeft();
2981 :
2982 6092 : SwViewShell* pViewShell = mrTabFrm.getRootFrm()->GetCurrShell();
2983 6092 : OutputDevice* pOutDev = pViewShell->GetOut();
2984 6092 : const MapMode& rMapMode = pOutDev->GetMapMode();
2985 6092 : const Fraction& rFracX = rMapMode.GetScaleX();
2986 6092 : const Fraction& rFracY = rMapMode.GetScaleY();
2987 :
2988 6092 : svx::frame::Style aL(rBoxItem.GetLeft());
2989 6092 : aL.SetPatternScale(rFracY);
2990 6092 : svx::frame::Style aR(rBoxItem.GetRight());
2991 6092 : aR.SetPatternScale(rFracY);
2992 6092 : svx::frame::Style aT(rBoxItem.GetTop());
2993 6092 : aT.SetPatternScale(rFracX);
2994 6092 : svx::frame::Style aB(rBoxItem.GetBottom());
2995 6092 : aB.SetPatternScale(rFracX);
2996 :
2997 6092 : aR.MirrorSelf();
2998 6092 : aB.MirrorSelf();
2999 :
3000 6092 : const SwTwips nLeft = aBorderRect._Left();
3001 6092 : const SwTwips nRight = aBorderRect._Right();
3002 6092 : const SwTwips nTop = aBorderRect._Top();
3003 6092 : const SwTwips nBottom = aBorderRect._Bottom();
3004 :
3005 6092 : aL.SetRefMode( svx::frame::REFMODE_CENTERED );
3006 6092 : aR.SetRefMode( svx::frame::REFMODE_CENTERED );
3007 6092 : aT.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
3008 6092 : aB.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
3009 :
3010 : SwLineEntry aLeft (nLeft, nTop, nBottom,
3011 6092 : (bVert) ? aB : ((bR2L) ? aR : aL));
3012 : SwLineEntry aRight (nRight, nTop, nBottom,
3013 6092 : (bVert) ? ((bBottomAsTop) ? aB : aT) : ((bR2L) ? aL : aR));
3014 : SwLineEntry aTop (nTop, nLeft, nRight,
3015 6092 : (bVert) ? aL : ((bBottomAsTop) ? aB : aT));
3016 : SwLineEntry aBottom(nBottom, nLeft, nRight,
3017 6092 : (bVert) ? aR : aB);
3018 :
3019 6092 : Insert( aLeft, false );
3020 6092 : Insert( aRight, false );
3021 6092 : Insert( aTop, true );
3022 6092 : Insert( aBottom, true );
3023 6092 : }
3024 :
3025 24368 : void SwTabFrmPainter::Insert( SwLineEntry& rNew, bool bHori )
3026 : {
3027 : // get all lines from structure, that have key entry of pLE
3028 24368 : SwLineEntryMap* pLine2 = bHori ? &maHoriLines : &maVertLines;
3029 24368 : const SwTwips nKey = rNew.mnKey;
3030 24368 : SwLineEntryMapIter aMapIter = pLine2->find( nKey );
3031 :
3032 24368 : SwLineEntrySet* pLineSet = aMapIter != pLine2->end() ? &((*aMapIter).second) : 0;
3033 24368 : if ( !pLineSet )
3034 : {
3035 4754 : SwLineEntrySet aNewSet;
3036 4754 : (*pLine2)[ nKey ] = aNewSet;
3037 4754 : pLineSet = &(*pLine2)[ nKey ];
3038 : }
3039 24368 : SwLineEntrySetIter aIter = pLineSet->begin();
3040 :
3041 99544 : while ( aIter != pLineSet->end() && rNew.mnStartPos < rNew.mnEndPos )
3042 : {
3043 59460 : const SwLineEntry& rOld = *aIter;
3044 59460 : const SwLineEntry::OverlapType nOverlapType = rOld.Overlaps( rNew );
3045 :
3046 59460 : const svx::frame::Style& rOldAttr = rOld.maAttribute;
3047 59460 : const svx::frame::Style& rNewAttr = rNew.maAttribute;
3048 59460 : const svx::frame::Style& rCmpAttr = rNewAttr > rOldAttr ? rNewAttr : rOldAttr;
3049 :
3050 59460 : if ( SwLineEntry::OVERLAP1 == nOverlapType )
3051 : {
3052 : OSL_ENSURE( rNew.mnStartPos >= rOld.mnStartPos, "Overlap type 3? How this?" );
3053 :
3054 : // new left segment
3055 158 : const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
3056 :
3057 : // new middle segment
3058 158 : const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rOld.mnEndPos, rCmpAttr );
3059 :
3060 : // new right segment
3061 158 : rNew.mnStartPos = rOld.mnEndPos;
3062 :
3063 : // update current lines set
3064 158 : pLineSet->erase( aIter );
3065 158 : if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
3066 158 : if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
3067 :
3068 158 : aIter = pLineSet->begin();
3069 :
3070 158 : continue; // start over
3071 : }
3072 59302 : else if ( SwLineEntry::OVERLAP2 == nOverlapType )
3073 : {
3074 : // new left segment
3075 8650 : const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
3076 :
3077 : // new middle segment
3078 8650 : const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rNew.mnEndPos, rCmpAttr );
3079 :
3080 : // new right segment
3081 8650 : const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
3082 :
3083 : // update current lines set
3084 8650 : pLineSet->erase( aIter );
3085 8650 : if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
3086 8650 : if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
3087 8650 : if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
3088 :
3089 8650 : rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
3090 :
3091 8650 : break; // we are finished
3092 : }
3093 50652 : else if ( SwLineEntry::OVERLAP3 == nOverlapType )
3094 : {
3095 : // new left segment
3096 2 : const SwLineEntry aLeft( nKey, rNew.mnStartPos, rOld.mnStartPos, rNewAttr );
3097 :
3098 : // new middle segment
3099 2 : const SwLineEntry aMiddle( nKey, rOld.mnStartPos, rNew.mnEndPos, rCmpAttr );
3100 :
3101 : // new right segment
3102 2 : const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
3103 :
3104 : // update current lines set
3105 2 : pLineSet->erase( aIter );
3106 2 : if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
3107 2 : if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
3108 2 : if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
3109 :
3110 2 : rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
3111 :
3112 2 : break; // we are finished
3113 : }
3114 :
3115 50650 : ++aIter;
3116 : }
3117 :
3118 24368 : if ( rNew.mnStartPos < rNew.mnEndPos ) // insert rest
3119 15716 : pLineSet->insert( rNew );
3120 24368 : }
3121 :
3122 : /**
3123 : * FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES END
3124 : * --> OD #i76669#
3125 : */
3126 : namespace
3127 : {
3128 : class SwViewObjectContactRedirector : public sdr::contact::ViewObjectContactRedirector
3129 : {
3130 : private:
3131 : const SwViewShell& mrViewShell;
3132 :
3133 : public:
3134 9288 : explicit SwViewObjectContactRedirector( const SwViewShell& rSh )
3135 9288 : : mrViewShell( rSh )
3136 9288 : {};
3137 :
3138 9288 : virtual ~SwViewObjectContactRedirector()
3139 9288 : {}
3140 :
3141 2447 : virtual drawinglayer::primitive2d::Primitive2DSequence createRedirectedPrimitive2DSequence(
3142 : const sdr::contact::ViewObjectContact& rOriginal,
3143 : const sdr::contact::DisplayInfo& rDisplayInfo) SAL_OVERRIDE
3144 : {
3145 2447 : bool bPaint( true );
3146 :
3147 2447 : SdrObject* pObj = rOriginal.GetViewContact().TryToGetSdrObject();
3148 2447 : if ( pObj )
3149 : {
3150 2447 : bPaint = SwFlyFrm::IsPaint( pObj, &mrViewShell );
3151 : }
3152 :
3153 2447 : if ( !bPaint )
3154 : {
3155 239 : return drawinglayer::primitive2d::Primitive2DSequence();
3156 : }
3157 :
3158 : return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(
3159 2208 : rOriginal, rDisplayInfo );
3160 : }
3161 : };
3162 :
3163 : } // end of anonymous namespace
3164 : // <--
3165 :
3166 : /**
3167 : * Paint once for every visible page which is touched by Rect
3168 : *
3169 : * 1. Paint borders and backgrounds
3170 : * 2. Paint the draw layer (frames and drawing objects) that is
3171 : * below the document (hell)
3172 : * 3. Paint the document content (text)
3173 : * 4. Paint the draw layer that is above the document
3174 : |*/
3175 9251 : void SwRootFrm::Paint(SwRect const& rRect, SwPrintData const*const pPrintData) const
3176 : {
3177 : OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Lower of root is no page." );
3178 :
3179 : PROTOCOL( this, PROT_FILE_INIT, 0, 0)
3180 :
3181 9251 : bool bResetRootPaint = false;
3182 9251 : SwViewShell *pSh = mpCurrShell;
3183 :
3184 9251 : if ( pSh->GetWin() )
3185 : {
3186 8903 : if ( pSh->GetOut() == pSh->GetWin() && !pSh->GetWin()->IsVisible() )
3187 : {
3188 0 : return;
3189 : }
3190 8903 : if ( SwRootFrm::mbInPaint )
3191 : {
3192 0 : SwPaintQueue::Add( pSh, rRect );
3193 0 : return;
3194 : }
3195 : }
3196 : else
3197 348 : SwRootFrm::mbInPaint = bResetRootPaint = true;
3198 :
3199 9251 : SwSavePaintStatics *pStatics = 0;
3200 9251 : if ( gProp.pSGlobalShell )
3201 0 : pStatics = new SwSavePaintStatics();
3202 9251 : gProp.pSGlobalShell = pSh;
3203 :
3204 9251 : if( !pSh->GetWin() )
3205 348 : gProp.pSProgress = SfxProgress::GetActiveProgress( static_cast<SfxObjectShell*>(pSh->GetDoc()->GetDocShell()) );
3206 :
3207 9251 : ::SwCalcPixStatics( pSh->GetOut() );
3208 9251 : aGlobalRetoucheColor = pSh->Imp()->GetRetoucheColor();
3209 :
3210 : //Trigger an action to clear things up if needed.
3211 : //Using this trick we can ensure that all values are valid in all paints -
3212 : //no problems, no special case(s).
3213 : // #i92745#
3214 : // Extend check on certain states of the 'current' <SwViewShell> instance to
3215 : // all existing <SwViewShell> instances.
3216 9251 : bool bPerformLayoutAction( true );
3217 : {
3218 9666 : for(SwViewShell& rTmpViewShell : pSh->GetRingContainer())
3219 : {
3220 23740 : if ( rTmpViewShell.IsInEndAction() ||
3221 18636 : rTmpViewShell.IsPaintInProgress() ||
3222 415 : ( rTmpViewShell.Imp()->IsAction() &&
3223 0 : rTmpViewShell.Imp()->GetLayAction().IsActionInProgress() ) )
3224 : {
3225 8903 : bPerformLayoutAction = false;
3226 : }
3227 :
3228 9318 : if(!bPerformLayoutAction)
3229 8903 : break;
3230 : }
3231 : }
3232 9251 : if ( bPerformLayoutAction )
3233 : {
3234 348 : const_cast<SwRootFrm*>(this)->ResetTurbo();
3235 348 : SwLayAction aAction( const_cast<SwRootFrm*>(this), pSh->Imp() );
3236 348 : aAction.SetPaint( false );
3237 348 : aAction.SetComplete( false );
3238 348 : aAction.SetReschedule( gProp.pSProgress != nullptr );
3239 348 : aAction.Action();
3240 348 : ResetTurboFlag();
3241 348 : if ( !pSh->ActionPend() )
3242 348 : pSh->Imp()->DelRegion();
3243 : }
3244 :
3245 9251 : SwRect aRect( rRect );
3246 9251 : aRect.Intersection( pSh->VisArea() );
3247 :
3248 9251 : const bool bExtraData = ::IsExtraData( GetFormat()->GetDoc() );
3249 :
3250 9251 : gProp.pSLines = new SwLineRects; //Container for borders.
3251 :
3252 : // #104289#. During painting, something (OLE) can
3253 : // load the linguistic, which in turn can cause a reformat
3254 : // of the document. Dangerous! We better set this flag to
3255 : // avoid the reformat.
3256 9251 : const bool bOldAction = IsCallbackActionEnabled();
3257 9251 : const_cast<SwRootFrm*>(this)->SetCallbackActionEnabled( false );
3258 :
3259 9251 : const SwPageFrm *pPage = pSh->Imp()->GetFirstVisPage();
3260 9251 : if ( pPage->GetPrev() )
3261 961 : pPage = static_cast<const SwPageFrm*>(pPage->GetPrev());
3262 9251 : const bool bBookMode = gProp.pSGlobalShell->GetViewOptions()->IsViewLayoutBookMode();
3263 9251 : if ( bBookMode && pPage->GetPrev() && static_cast<const SwPageFrm*>(pPage->GetPrev())->IsEmptyPage() )
3264 0 : pPage = static_cast<const SwPageFrm*>(pPage->GetPrev());
3265 :
3266 : // #i68597#
3267 9251 : const bool bGridPainting(pSh->GetWin() && pSh->Imp()->HasDrawView() && pSh->Imp()->GetDrawView()->IsGridVisible());
3268 :
3269 : // Hide all page break controls before showing them again
3270 9251 : SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell );
3271 9251 : if ( pWrtSh )
3272 : {
3273 8903 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
3274 8903 : SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager();
3275 8903 : const SwPageFrm* pHiddenPage = pPage;
3276 19866 : while ( pHiddenPage->GetPrev() != NULL )
3277 : {
3278 2060 : pHiddenPage = static_cast< const SwPageFrm* >( pHiddenPage->GetPrev() );
3279 2060 : SwFrameControlPtr pControl = rMngr.GetControl( PageBreak, pHiddenPage );
3280 2060 : if ( pControl.get() )
3281 2 : pControl->ShowAll( false );
3282 2060 : }
3283 : }
3284 :
3285 : // #i76669#
3286 9251 : SwViewObjectContactRedirector aSwRedirector( *pSh );
3287 :
3288 29803 : while ( pPage )
3289 : {
3290 11301 : const bool bPaintRightShadow = pPage->IsRightShadowNeeded();
3291 11301 : const bool bPaintLeftShadow = pPage->IsLeftShadowNeeded();
3292 11301 : const bool bRightSidebar = pPage->SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT;
3293 :
3294 11301 : if ( !pPage->IsEmptyPage() )
3295 : {
3296 11267 : SwRect aPaintRect;
3297 11267 : SwPageFrm::GetBorderAndShadowBoundRect( pPage->Frm(), pSh, aPaintRect,
3298 22534 : bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
3299 :
3300 11267 : if ( aRect.IsOver( aPaintRect ) )
3301 : {
3302 9249 : if ( pSh->GetWin() )
3303 : {
3304 8901 : gProp.pSSubsLines = new SwSubsRects;
3305 8901 : gProp.pSSpecSubsLines = new SwSubsRects;
3306 : }
3307 9249 : gProp.pBLines = new BorderLines;
3308 :
3309 9249 : aPaintRect._Intersection( aRect );
3310 :
3311 9521 : if ( bExtraData &&
3312 9521 : pSh->GetWin() && pSh->IsInEndAction() )
3313 : {
3314 : // enlarge paint rectangle to complete page width, subtract
3315 : // current paint area and invalidate the resulting region.
3316 262 : SWRECTFN( pPage )
3317 262 : SwRect aPageRectTemp( aPaintRect );
3318 : (aPageRectTemp.*fnRect->fnSetLeftAndWidth)(
3319 524 : (pPage->Frm().*fnRect->fnGetLeft)(),
3320 786 : (pPage->Frm().*fnRect->fnGetWidth)() );
3321 262 : aPageRectTemp._Intersection( pSh->VisArea() );
3322 262 : vcl::Region aPageRectRegion( aPageRectTemp.SVRect() );
3323 262 : aPageRectRegion.Exclude( aPaintRect.SVRect() );
3324 262 : pSh->GetWin()->Invalidate( aPageRectRegion, InvalidateFlags::Children );
3325 : }
3326 :
3327 : // #i80793#
3328 : // enlarge paint rectangle for objects overlapping the same pixel
3329 : // in all cases and before the DrawingLayer overlay is initialized.
3330 9249 : lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
3331 :
3332 : // #i68597#
3333 : // moved paint pre-process for DrawingLayer overlay here since the above
3334 : // code dependent from bExtraData may expand the PaintRect
3335 : {
3336 : // #i75172# if called from SwViewShell::ImplEndAction it should no longer
3337 : // really be used but handled by SwViewShell::ImplEndAction already
3338 9249 : const vcl::Region aDLRegion(aPaintRect.SVRect());
3339 9249 : pSh->DLPrePaint2(aDLRegion);
3340 : }
3341 :
3342 9249 : if(OUTDEV_WINDOW == gProp.pSGlobalShell->GetOut()->GetOutDevType())
3343 : {
3344 : // OD 27.09.2002 #103636# - changed method SwLayVout::Enter(..)
3345 : // 2nd parameter is no longer <const> and will be set to the
3346 : // rectangle the virtual output device is calculated from <aPaintRect>,
3347 : // if the virtual output is used.
3348 0 : mpVout->Enter( pSh, aPaintRect, !mbNoVirDev );
3349 :
3350 : // OD 27.09.2002 #103636# - adjust paint rectangle to pixel size
3351 : // Thus, all objects overlapping on pixel level with the unadjusted
3352 : // paint rectangle will be considered in the paint.
3353 0 : lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
3354 : }
3355 :
3356 : // maybe this can be put in the above scope. Since we are not sure, just leave it ATM
3357 9249 : mpVout->SetOrgRect( aPaintRect );
3358 :
3359 : // OD 29.08.2002 #102450#
3360 : // determine background color of page for <PaintLayer> method
3361 : // calls, paint <hell> or <heaven>
3362 9249 : const Color aPageBackgrdColor(pPage->GetDrawBackgrdColor());
3363 :
3364 9249 : pPage->PaintBaBo( aPaintRect, pPage, true );
3365 :
3366 9249 : if ( pSh->Imp()->HasDrawView() )
3367 : {
3368 9249 : gProp.pSLines->LockLines( true );
3369 9249 : const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
3370 9249 : pSh->Imp()->PaintLayer( pIDDMA->GetHellId(),
3371 : pPrintData,
3372 9249 : pPage->Frm(),
3373 : &aPageBackgrdColor,
3374 9249 : pPage->IsRightToLeft(),
3375 18498 : &aSwRedirector );
3376 9249 : gProp.pSLines->PaintLines( pSh->GetOut(), gProp );
3377 9249 : gProp.pSLines->LockLines( false );
3378 : }
3379 :
3380 9249 : if ( pSh->GetDoc()->GetDocumentSettingManager().get( DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS ) )
3381 779 : pPage->PaintBaBo( aPaintRect, pPage, true, /*bOnlyTextBackground=*/true );
3382 :
3383 9249 : if( pSh->GetWin() )
3384 : {
3385 : // collect sub-lines
3386 8901 : pPage->RefreshSubsidiary( aPaintRect );
3387 : // paint special sub-lines
3388 8901 : gProp.pSSpecSubsLines->PaintSubsidiary( pSh->GetOut(), NULL, gProp );
3389 : }
3390 :
3391 9249 : pPage->Paint( aPaintRect );
3392 :
3393 : // no paint of page border and shadow, if writer is in place mode.
3394 18150 : if( pSh->GetWin() && pSh->GetDoc()->GetDocShell() &&
3395 8901 : !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
3396 : {
3397 8901 : SwPageFrm::PaintBorderAndShadow( pPage->Frm(), pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
3398 8901 : SwPageFrm::PaintNotesSidebar( pPage->Frm(), pSh, pPage->GetPhyPageNum(), bRightSidebar);
3399 : }
3400 :
3401 9249 : gProp.pSLines->PaintLines( pSh->GetOut(), gProp );
3402 9249 : if ( pSh->GetWin() )
3403 : {
3404 8901 : gProp.pSSubsLines->PaintSubsidiary( pSh->GetOut(), gProp.pSLines, gProp );
3405 8901 : DELETEZ( gProp.pSSubsLines );
3406 8901 : DELETEZ( gProp.pSSpecSubsLines );
3407 : }
3408 : // fdo#42750: delay painting these until after subsidiary lines
3409 : // fdo#45562: delay painting these until after hell layer
3410 : // fdo#47717: but do it before heaven layer
3411 9249 : ProcessPrimitives(gProp.pBLines->GetBorderLines_Clear());
3412 :
3413 9249 : if ( pSh->Imp()->HasDrawView() )
3414 : {
3415 : // OD 29.08.2002 #102450# - add 3rd parameter
3416 : // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
3417 9249 : pSh->Imp()->PaintLayer( pSh->GetDoc()->getIDocumentDrawModelAccess().GetHeavenId(),
3418 : pPrintData,
3419 9249 : pPage->Frm(),
3420 : &aPageBackgrdColor,
3421 9249 : pPage->IsRightToLeft(),
3422 18498 : &aSwRedirector );
3423 : }
3424 :
3425 9249 : if ( bExtraData )
3426 272 : pPage->RefreshExtraData( aPaintRect );
3427 :
3428 9249 : DELETEZ(gProp.pBLines);
3429 9249 : mpVout->Leave();
3430 :
3431 : // #i68597#
3432 : // needed to move grid painting inside Begin/EndDrawLayer bounds and to change
3433 : // output rect for it accordingly
3434 9249 : if(bGridPainting)
3435 : {
3436 40 : SdrPaintView* pPaintView = pSh->Imp()->GetDrawView();
3437 40 : SdrPageView* pPageView = pPaintView->GetSdrPageView();
3438 40 : pPageView->DrawPageViewGrid(*pSh->GetOut(), aPaintRect.SVRect(), SwViewOption::GetTextGridColor() );
3439 : }
3440 :
3441 : // #i68597#
3442 : // moved paint post-process for DrawingLayer overlay here, see above
3443 : {
3444 9249 : pSh->DLPostPaint2(true);
3445 : }
3446 : }
3447 :
3448 11267 : pPage->PaintDecorators( );
3449 11267 : pPage->PaintBreak();
3450 : }
3451 34 : else if ( bBookMode && pSh->GetWin() && !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
3452 : {
3453 : // paint empty page
3454 0 : SwRect aPaintRect;
3455 0 : SwRect aEmptyPageRect( pPage->Frm() );
3456 :
3457 : // code from vprint.cxx
3458 0 : const SwPageFrm& rFormatPage = pPage->GetFormatPage();
3459 0 : aEmptyPageRect.SSize() = rFormatPage.Frm().SSize();
3460 :
3461 : SwPageFrm::GetBorderAndShadowBoundRect( aEmptyPageRect, pSh, aPaintRect,
3462 0 : bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
3463 0 : aPaintRect._Intersection( aRect );
3464 :
3465 0 : if ( aRect.IsOver( aEmptyPageRect ) )
3466 : {
3467 : // #i75172# if called from SwViewShell::ImplEndAction it should no longer
3468 : // really be used but handled by SwViewShell::ImplEndAction already
3469 : {
3470 0 : const vcl::Region aDLRegion(aPaintRect.SVRect());
3471 0 : pSh->DLPrePaint2(aDLRegion);
3472 : }
3473 :
3474 0 : if( pSh->GetOut()->GetFillColor() != aGlobalRetoucheColor )
3475 0 : pSh->GetOut()->SetFillColor( aGlobalRetoucheColor );
3476 :
3477 0 : pSh->GetOut()->SetLineColor(); // OD 20.02.2003 #107369# - no line color
3478 : // OD 20.02.2003 #107369# - use aligned page rectangle
3479 : {
3480 0 : SwRect aTmpPageRect( aEmptyPageRect );
3481 0 : ::SwAlignRect( aTmpPageRect, pSh );
3482 0 : aEmptyPageRect = aTmpPageRect;
3483 : }
3484 :
3485 0 : pSh->GetOut()->DrawRect( aEmptyPageRect.SVRect() );
3486 :
3487 : // paint empty page text
3488 0 : const vcl::Font& rEmptyPageFont = SwPageFrm::GetEmptyPageFont();
3489 0 : const vcl::Font aOldFont( pSh->GetOut()->GetFont() );
3490 :
3491 0 : pSh->GetOut()->SetFont( rEmptyPageFont );
3492 : pSh->GetOut()->DrawText( aEmptyPageRect.SVRect(), SW_RESSTR( STR_EMPTYPAGE ),
3493 : DrawTextFlags::VCenter |
3494 0 : DrawTextFlags::Center |
3495 0 : DrawTextFlags::Clip );
3496 :
3497 0 : pSh->GetOut()->SetFont( aOldFont );
3498 : // paint shadow and border for empty page
3499 : // OD 19.02.2003 #107369# - use new method to paint page border and
3500 : // shadow
3501 0 : SwPageFrm::PaintBorderAndShadow( aEmptyPageRect, pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
3502 0 : SwPageFrm::PaintNotesSidebar( aEmptyPageRect, pSh, pPage->GetPhyPageNum(), bRightSidebar);
3503 :
3504 : {
3505 0 : pSh->DLPostPaint2(true);
3506 0 : }
3507 : }
3508 : }
3509 :
3510 : OSL_ENSURE( !pPage->GetNext() || pPage->GetNext()->IsPageFrm(),
3511 : "Neighbour of page is not a page." );
3512 11301 : pPage = static_cast<const SwPageFrm*>(pPage->GetNext());
3513 : }
3514 :
3515 9251 : DELETEZ( gProp.pSLines );
3516 :
3517 9251 : if ( bResetRootPaint )
3518 348 : SwRootFrm::mbInPaint = false;
3519 9251 : if ( pStatics )
3520 0 : delete pStatics;
3521 : else
3522 : {
3523 9251 : gProp.pSProgress = 0;
3524 9251 : gProp.pSGlobalShell = 0;
3525 : }
3526 :
3527 9251 : const_cast<SwRootFrm*>(this)->SetCallbackActionEnabled( bOldAction );
3528 : }
3529 :
3530 108 : static void lcl_EmergencyFormatFootnoteCont( SwFootnoteContFrm *pCont )
3531 : {
3532 : //It's possible that the Cont will get destroyed.
3533 108 : SwContentFrm *pCnt = pCont->ContainsContent();
3534 371 : while ( pCnt && pCnt->IsInFootnote() )
3535 : {
3536 155 : pCnt->Calc();
3537 155 : pCnt = pCnt->GetNextContentFrm();
3538 : }
3539 108 : }
3540 :
3541 : class SwShortCut
3542 : {
3543 : SwRectDist fnCheck;
3544 : long nLimit;
3545 : public:
3546 : SwShortCut( const SwFrm& rFrm, const SwRect& rRect );
3547 97596 : bool Stop( const SwRect& rRect ) const
3548 97596 : { return (rRect.*fnCheck)( nLimit ) > 0; }
3549 : };
3550 :
3551 81572 : SwShortCut::SwShortCut( const SwFrm& rFrm, const SwRect& rRect )
3552 : {
3553 81572 : bool bVert = rFrm.IsVertical();
3554 81572 : bool bR2L = rFrm.IsRightToLeft();
3555 81572 : if( rFrm.IsNeighbourFrm() && bVert == bR2L )
3556 : {
3557 6754 : if( bVert )
3558 : {
3559 0 : fnCheck = &SwRect::GetBottomDistance;
3560 0 : nLimit = rRect.Top();
3561 : }
3562 : else
3563 : {
3564 6754 : fnCheck = &SwRect::GetLeftDistance;
3565 6754 : nLimit = rRect.Left() + rRect.Width();
3566 : }
3567 : }
3568 74818 : else if( bVert == rFrm.IsNeighbourFrm() )
3569 : {
3570 74818 : fnCheck = &SwRect::GetTopDistance;
3571 74818 : nLimit = rRect.Top() + rRect.Height();
3572 : }
3573 : else
3574 : {
3575 0 : if ( rFrm.IsVertLR() )
3576 : {
3577 0 : fnCheck = &SwRect::GetLeftDistance;
3578 0 : nLimit = rRect.Right();
3579 : }
3580 : else
3581 : {
3582 0 : fnCheck = &SwRect::GetRightDistance;
3583 0 : nLimit = rRect.Left();
3584 : }
3585 : }
3586 81572 : }
3587 :
3588 26311 : void SwLayoutFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
3589 : {
3590 26311 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
3591 :
3592 : // #i16816# tagged pdf support
3593 26311 : Frm_Info aFrmInfo( *this );
3594 26311 : SwTaggedPDFHelper aTaggedPDFHelper( 0, &aFrmInfo, 0, *pSh->GetOut() );
3595 :
3596 26311 : const SwFrm *pFrm = Lower();
3597 26311 : if ( !pFrm )
3598 26331 : return;
3599 :
3600 26291 : SwShortCut aShortCut( *pFrm, rRect );
3601 : bool bCnt;
3602 26291 : if ( (bCnt = pFrm->IsContentFrm()) )
3603 13740 : pFrm->Calc();
3604 :
3605 26291 : if ( pFrm->IsFootnoteContFrm() )
3606 : {
3607 0 : ::lcl_EmergencyFormatFootnoteCont( const_cast<SwFootnoteContFrm*>(static_cast<const SwFootnoteContFrm*>(pFrm)) );
3608 0 : pFrm = Lower();
3609 : }
3610 :
3611 26291 : const SwPageFrm *pPage = 0;
3612 26291 : const bool bWin = gProp.pSGlobalShell->GetWin() != nullptr;
3613 :
3614 91805 : while ( IsAnLower( pFrm ) )
3615 : {
3616 40780 : SwRect aPaintRect( pFrm->PaintArea() );
3617 40780 : if( aShortCut.Stop( aPaintRect ) )
3618 1557 : break;
3619 39223 : if ( bCnt && gProp.pSProgress )
3620 0 : gProp.pSProgress->Reschedule();
3621 :
3622 : //We need to retouch if a frame explicitly requests it.
3623 : //First do the retouch, because this could flatten the borders.
3624 39223 : if ( pFrm->IsRetouche() )
3625 : {
3626 5336 : if ( pFrm->IsRetoucheFrm() && bWin && !pFrm->GetNext() )
3627 2454 : { if ( !pPage )
3628 2454 : pPage = FindPageFrm();
3629 2454 : pFrm->Retouche( pPage, rRect );
3630 : }
3631 5336 : pFrm->ResetRetouche();
3632 : }
3633 :
3634 39223 : if ( rRect.IsOver( aPaintRect ) )
3635 : {
3636 58478 : if ( bCnt && pFrm->IsCompletePaint() &&
3637 44448 : !rRect.IsInside( aPaintRect ) && Application::AnyInput( VclInputFlags::KEYBOARD ) )
3638 : {
3639 : //fix(8104): It may happen, that the processing wasn't complete
3640 : //but some parts of the paragraph were still repainted.
3641 : //This could lead to the situation, that other parts of the
3642 : //paragraph won't be repainted at all. The only solution seems
3643 : //to be an invalidation of the window.
3644 : //To not make it too severe the rectangle is limited by
3645 : //painting the desired part and only invalidating the
3646 : //remaining paragraph parts.
3647 0 : if ( aPaintRect.Left() == rRect.Left() &&
3648 0 : aPaintRect.Right() == rRect.Right() )
3649 : {
3650 0 : aPaintRect.Bottom( rRect.Top() - 1 );
3651 0 : if ( aPaintRect.Height() > 0 )
3652 0 : gProp.pSGlobalShell->InvalidateWindows(aPaintRect);
3653 0 : aPaintRect.Top( rRect.Bottom() + 1 );
3654 0 : aPaintRect.Bottom( pFrm->Frm().Bottom() );
3655 0 : if ( aPaintRect.Height() > 0 )
3656 0 : gProp.pSGlobalShell->InvalidateWindows(aPaintRect);
3657 0 : aPaintRect.Top( pFrm->Frm().Top() );
3658 0 : aPaintRect.Bottom( pFrm->Frm().Bottom() );
3659 : }
3660 : else
3661 : {
3662 0 : gProp.pSGlobalShell->InvalidateWindows( aPaintRect );
3663 0 : pFrm = pFrm->GetNext();
3664 0 : if ( pFrm && (bCnt = pFrm->IsContentFrm()) )
3665 0 : pFrm->Calc();
3666 0 : continue;
3667 : }
3668 : }
3669 34492 : pFrm->ResetCompletePaint();
3670 34492 : aPaintRect._Intersection( rRect );
3671 :
3672 34492 : pFrm->Paint( aPaintRect );
3673 :
3674 34492 : if ( Lower() && Lower()->IsColumnFrm() )
3675 : {
3676 : //Paint the column separator line if needed. The page is
3677 : //responsible for the page frame - not the upper.
3678 106 : const SwFrameFormat *pFormat = GetUpper() && GetUpper()->IsPageFrm()
3679 0 : ? GetUpper()->GetFormat()
3680 53 : : GetFormat();
3681 53 : const SwFormatCol &rCol = pFormat->GetCol();
3682 53 : if ( rCol.GetLineAdj() != COLADJ_NONE )
3683 : {
3684 0 : if ( !pPage )
3685 0 : pPage = pFrm->FindPageFrm();
3686 :
3687 0 : PaintColLines( aPaintRect, rCol, pPage );
3688 : }
3689 : }
3690 : }
3691 39223 : if ( !bCnt && pFrm->GetNext() && pFrm->GetNext()->IsFootnoteContFrm() )
3692 108 : ::lcl_EmergencyFormatFootnoteCont( const_cast<SwFootnoteContFrm*>(static_cast<const SwFootnoteContFrm*>(pFrm->GetNext())) );
3693 :
3694 39223 : pFrm = pFrm->GetNext();
3695 :
3696 39223 : if ( pFrm && (bCnt = pFrm->IsContentFrm()) )
3697 8167 : pFrm->Calc();
3698 26291 : }
3699 : }
3700 :
3701 16 : static drawinglayer::primitive2d::Primitive2DSequence lcl_CreateDashedIndicatorPrimitive(
3702 : const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd,
3703 : basegfx::BColor aColor )
3704 : {
3705 16 : drawinglayer::primitive2d::Primitive2DSequence aSeq( 1 );
3706 :
3707 32 : std::vector< double > aStrokePattern;
3708 32 : basegfx::B2DPolygon aLinePolygon;
3709 16 : aLinePolygon.append(rStart);
3710 16 : aLinePolygon.append(rEnd);
3711 :
3712 16 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
3713 16 : if ( rSettings.GetHighContrastMode( ) )
3714 : {
3715 : // Only a solid line in high contrast mode
3716 0 : aColor = rSettings.GetDialogTextColor().getBColor();
3717 : }
3718 : else
3719 : {
3720 : // Get a color for the contrast
3721 16 : basegfx::BColor aHslLine = basegfx::tools::rgb2hsl( aColor );
3722 16 : double nLuminance = aHslLine.getZ() * 2.5;
3723 16 : if ( nLuminance == 0 )
3724 0 : nLuminance = 0.5;
3725 16 : else if ( nLuminance >= 1.0 )
3726 0 : nLuminance = aHslLine.getZ() * 0.4;
3727 16 : aHslLine.setZ( nLuminance );
3728 32 : const basegfx::BColor aOtherColor = basegfx::tools::hsl2rgb( aHslLine );
3729 :
3730 : // Compute the plain line
3731 : drawinglayer::primitive2d::PolygonHairlinePrimitive2D * pPlainLine =
3732 : new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
3733 16 : aLinePolygon, aOtherColor );
3734 :
3735 16 : aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( pPlainLine );
3736 :
3737 : // Dashed line in twips
3738 16 : aStrokePattern.push_back( 40 );
3739 16 : aStrokePattern.push_back( 40 );
3740 :
3741 32 : aSeq.realloc( 2 );
3742 : }
3743 :
3744 : // Compute the dashed line primitive
3745 : drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D * pLine =
3746 : new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D (
3747 : basegfx::B2DPolyPolygon( aLinePolygon ),
3748 : drawinglayer::attribute::LineAttribute( aColor ),
3749 16 : drawinglayer::attribute::StrokeAttribute( aStrokePattern ) );
3750 :
3751 16 : aSeq[ aSeq.getLength( ) - 1 ] = drawinglayer::primitive2d::Primitive2DReference( pLine );
3752 :
3753 32 : return aSeq;
3754 : }
3755 :
3756 11267 : void SwPageFrm::PaintBreak( ) const
3757 : {
3758 33801 : if ( gProp.pSGlobalShell->GetOut()->GetOutDevType() != OUTDEV_PRINTER &&
3759 22533 : !gProp.pSGlobalShell->GetViewOptions()->IsPDFExport() &&
3760 33794 : !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() &&
3761 11261 : !gProp.pSGlobalShell->IsPreview() )
3762 : {
3763 11261 : const SwFrm* pBodyFrm = Lower();
3764 23219 : while ( pBodyFrm && !pBodyFrm->IsBodyFrm() )
3765 697 : pBodyFrm = pBodyFrm->GetNext();
3766 :
3767 11261 : if ( pBodyFrm )
3768 : {
3769 11261 : const SwLayoutFrm* pLayBody = static_cast< const SwLayoutFrm* >( pBodyFrm );
3770 11261 : const SwFlowFrm *pFlowFrm = pLayBody->ContainsContent();
3771 :
3772 : // Test if the first node is a table
3773 11261 : const SwFrm* pFirstFrm = pLayBody->Lower();
3774 11261 : if ( pFirstFrm && pFirstFrm->IsTabFrm() )
3775 506 : pFlowFrm = static_cast< const SwTabFrm* >( pFirstFrm );
3776 :
3777 11261 : SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell );
3778 11261 : if ( pWrtSh )
3779 : {
3780 10891 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
3781 10891 : SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager();
3782 :
3783 10891 : if ( pFlowFrm && pFlowFrm->IsPageBreak( true ) )
3784 392 : rMngr.SetPageBreakControl( this );
3785 : else
3786 10499 : rMngr.RemoveControlsByType( PageBreak, this );
3787 : }
3788 : }
3789 11261 : SwLayoutFrm::PaintBreak( );
3790 : }
3791 11267 : }
3792 :
3793 83 : void SwColumnFrm::PaintBreak( ) const
3794 : {
3795 249 : if ( gProp.pSGlobalShell->GetOut()->GetOutDevType() != OUTDEV_PRINTER &&
3796 166 : !gProp.pSGlobalShell->GetViewOptions()->IsPDFExport() &&
3797 249 : !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() &&
3798 83 : !gProp.pSGlobalShell->IsPreview() )
3799 : {
3800 83 : const SwFrm* pBodyFrm = Lower();
3801 166 : while ( pBodyFrm && !pBodyFrm->IsBodyFrm() )
3802 0 : pBodyFrm = pBodyFrm->GetNext();
3803 :
3804 83 : if ( pBodyFrm )
3805 : {
3806 83 : const SwContentFrm *pCnt = static_cast< const SwLayoutFrm* >( pBodyFrm )->ContainsContent();
3807 83 : if ( pCnt && pCnt->IsColBreak( true ) )
3808 : {
3809 : // Paint the break only if:
3810 : // * Not in header footer edition, to avoid conflicts with the
3811 : // header/footer marker
3812 : // * Non-printing characters are shown, as this is more consistent
3813 : // with other formatting marks
3814 32 : if ( !gProp.pSGlobalShell->IsShowHeaderFooterSeparator( Header ) &&
3815 16 : !gProp.pSGlobalShell->IsShowHeaderFooterSeparator( Footer ) )
3816 : {
3817 16 : SwRect aRect( pCnt->Prt() );
3818 16 : aRect.Pos() += pCnt->Frm().Pos();
3819 :
3820 : // Draw the line
3821 16 : basegfx::B2DPoint aStart( double( aRect.Left() ), aRect.Top() );
3822 32 : basegfx::B2DPoint aEnd( double( aRect.Right() ), aRect.Top() );
3823 16 : double nWidth = aRect.Width();
3824 16 : if ( IsVertical( ) )
3825 : {
3826 0 : aStart = basegfx::B2DPoint( double( aRect.Right() ), double( aRect.Top() ) );
3827 0 : aEnd = basegfx::B2DPoint( double( aRect.Right() ), double( aRect.Bottom() ) );
3828 0 : nWidth = aRect.Height();
3829 : }
3830 :
3831 32 : basegfx::BColor aLineColor = SwViewOption::GetPageBreakColor().getBColor();
3832 :
3833 : drawinglayer::primitive2d::Primitive2DSequence aSeq =
3834 32 : lcl_CreateDashedIndicatorPrimitive( aStart, aEnd, aLineColor );
3835 16 : aSeq.realloc( aSeq.getLength( ) + 1 );
3836 :
3837 : // Add the text above
3838 32 : OUString aBreakText = SW_RESSTR(STR_COLUMN_BREAK);
3839 :
3840 32 : basegfx::B2DVector aFontSize;
3841 16 : OutputDevice* pOut = gProp.pSGlobalShell->GetOut();
3842 32 : vcl::Font aFont = pOut->GetSettings().GetStyleSettings().GetToolFont();
3843 16 : aFont.SetHeight( 8 * 20 );
3844 16 : pOut->SetFont( aFont );
3845 : drawinglayer::attribute::FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont(
3846 32 : aFontSize, aFont, false, false );
3847 :
3848 16 : Rectangle aTextRect;
3849 16 : pOut->GetTextBoundRect( aTextRect, aBreakText );
3850 16 : long nTextOff = ( nWidth - aTextRect.GetWidth() ) / 2;
3851 :
3852 : basegfx::B2DHomMatrix aTextMatrix( basegfx::tools::createScaleTranslateB2DHomMatrix(
3853 : aFontSize.getX(), aFontSize.getY(),
3854 32 : aRect.Left() + nTextOff, aRect.Top() ) );
3855 16 : if ( IsVertical() )
3856 : {
3857 0 : aTextMatrix = basegfx::B2DHomMatrix( basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix (
3858 : aFontSize.getX(), aFontSize.getY(), 0.0, M_PI_2,
3859 0 : aRect.Right(), aRect.Top() + nTextOff ) );
3860 : }
3861 :
3862 : drawinglayer::primitive2d::TextSimplePortionPrimitive2D * pText =
3863 : new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
3864 : aTextMatrix,
3865 : aBreakText, 0, aBreakText.getLength(),
3866 : std::vector< double >(),
3867 : aFontAttr,
3868 : lang::Locale(),
3869 16 : aLineColor );
3870 16 : aSeq[ aSeq.getLength() - 1 ] = drawinglayer::primitive2d::Primitive2DReference( pText );
3871 :
3872 32 : ProcessPrimitives( aSeq );
3873 : }
3874 : }
3875 : }
3876 : }
3877 83 : }
3878 :
3879 42476 : void SwLayoutFrm::PaintBreak( ) const
3880 : {
3881 42476 : const SwFrm* pFrm = Lower();
3882 168360 : while ( pFrm )
3883 : {
3884 83408 : if ( pFrm->IsLayoutFrm() )
3885 31298 : static_cast< const SwLayoutFrm*>( pFrm )->PaintBreak( );
3886 83408 : pFrm = pFrm->GetNext();
3887 : }
3888 42476 : }
3889 :
3890 11267 : void SwPageFrm::PaintDecorators( ) const
3891 : {
3892 11267 : SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell );
3893 11267 : if ( pWrtSh )
3894 : {
3895 10896 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
3896 :
3897 10896 : const SwLayoutFrm* pBody = FindBodyCont();
3898 10896 : if ( pBody )
3899 : {
3900 10896 : SwRect aBodyRect( pBody->Frm() );
3901 :
3902 32688 : if ( gProp.pSGlobalShell->GetOut()->GetOutDevType() != OUTDEV_PRINTER &&
3903 21792 : !gProp.pSGlobalShell->GetViewOptions()->IsPDFExport() &&
3904 21792 : !gProp.pSGlobalShell->IsPreview() &&
3905 21787 : !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() &&
3906 32589 : !gProp.pSGlobalShell->GetViewOptions()->getBrowseMode() &&
3907 21604 : ( gProp.pSGlobalShell->IsShowHeaderFooterSeparator( Header ) ||
3908 10802 : gProp.pSGlobalShell->IsShowHeaderFooterSeparator( Footer ) ) )
3909 : {
3910 0 : bool bRtl = AllSettings::GetLayoutRTL();
3911 0 : const SwRect& rVisArea = gProp.pSGlobalShell->VisArea();
3912 0 : long nXOff = std::min( aBodyRect.Right(), rVisArea.Right() );
3913 0 : if ( bRtl )
3914 0 : nXOff = std::max( aBodyRect.Left(), rVisArea.Left() );
3915 :
3916 : // Header
3917 0 : if ( gProp.pSGlobalShell->IsShowHeaderFooterSeparator( Header ) )
3918 : {
3919 0 : const SwFrm* pHeaderFrm = Lower();
3920 0 : if ( !pHeaderFrm->IsHeaderFrm() )
3921 0 : pHeaderFrm = NULL;
3922 :
3923 0 : long nHeaderYOff = aBodyRect.Top();
3924 0 : Point nOutputOff = rEditWin.LogicToPixel( Point( nXOff, nHeaderYOff ) );
3925 0 : rEditWin.GetFrameControlsManager().SetHeaderFooterControl( this, Header, nOutputOff );
3926 : }
3927 :
3928 : // Footer
3929 0 : if ( gProp.pSGlobalShell->IsShowHeaderFooterSeparator( Footer ) )
3930 : {
3931 0 : const SwFrm* pFootnoteContFrm = Lower();
3932 0 : while ( pFootnoteContFrm )
3933 : {
3934 0 : if ( pFootnoteContFrm->IsFootnoteContFrm() )
3935 0 : aBodyRect.AddBottom( pFootnoteContFrm->Frm().Bottom() - aBodyRect.Bottom() );
3936 0 : pFootnoteContFrm = pFootnoteContFrm->GetNext();
3937 : }
3938 :
3939 0 : long nFooterYOff = aBodyRect.Bottom();
3940 0 : Point nOutputOff = rEditWin.LogicToPixel( Point( nXOff, nFooterYOff ) );
3941 0 : rEditWin.GetFrameControlsManager().SetHeaderFooterControl( this, Footer, nOutputOff );
3942 : }
3943 : }
3944 : }
3945 : }
3946 11267 : }
3947 :
3948 : /**
3949 : * For feature #99657#
3950 : *
3951 : * OD 12.08.2002
3952 : * determines, if background of fly frame has to be drawn transparent
3953 : * declaration found in /core/inc/flyfrm.cxx
3954 : *
3955 : * OD 08.10.2002 #103898# - If the background of the fly frame itself is not
3956 : * transparent and the background is inherited from its parent/grandparent,
3957 : * the background brush, used for drawing, has to be investigated for transparency.
3958 : *
3959 : * @return true, if background is transparent drawn
3960 : */
3961 5830 : bool SwFlyFrm::IsBackgroundTransparent() const
3962 : {
3963 5830 : bool bBackgroundTransparent = GetFormat()->IsBackgroundTransparent();
3964 7838 : if ( !bBackgroundTransparent &&
3965 2008 : static_cast<const SwFlyFrameFormat*>(GetFormat())->IsBackgroundBrushInherited() )
3966 : {
3967 1993 : const SvxBrushItem* pBackgrdBrush = 0;
3968 1993 : const Color* pSectionTOXColor = 0;
3969 1993 : SwRect aDummyRect;
3970 : //UUUU
3971 1993 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
3972 :
3973 1993 : if ( GetBackgroundBrush( aFillAttributes, pBackgrdBrush, pSectionTOXColor, aDummyRect, false) )
3974 : {
3975 4 : if ( pSectionTOXColor &&
3976 4 : (pSectionTOXColor->GetTransparency() != 0) &&
3977 0 : (pSectionTOXColor->GetColor() != COL_TRANSPARENT) )
3978 : {
3979 0 : bBackgroundTransparent = true;
3980 : }
3981 4 : else if(aFillAttributes.get() && aFillAttributes->isUsed()) //UUUU
3982 : {
3983 0 : bBackgroundTransparent = aFillAttributes->isTransparent();
3984 : }
3985 4 : else if ( pBackgrdBrush )
3986 : {
3987 12 : if ( (pBackgrdBrush->GetColor().GetTransparency() != 0) &&
3988 4 : (pBackgrdBrush->GetColor() != COL_TRANSPARENT) )
3989 : {
3990 0 : bBackgroundTransparent = true;
3991 : }
3992 : else
3993 : {
3994 : const GraphicObject *pTmpGrf =
3995 4 : static_cast<const GraphicObject*>(pBackgrdBrush->GetGraphicObject());
3996 4 : if ( (pTmpGrf) &&
3997 0 : (pTmpGrf->GetAttr().GetTransparency() != 0)
3998 : )
3999 : {
4000 0 : bBackgroundTransparent = true;
4001 : }
4002 : }
4003 : }
4004 1993 : }
4005 : }
4006 :
4007 5830 : return bBackgroundTransparent;
4008 : };
4009 :
4010 3290 : bool SwFlyFrm::IsPaint( SdrObject *pObj, const SwViewShell *pSh )
4011 : {
4012 : SdrObjUserCall *pUserCall;
4013 :
4014 3290 : if ( 0 == ( pUserCall = GetUserCall(pObj) ) )
4015 0 : return true;
4016 :
4017 : //Attribute dependent, don't paint for printer or Preview
4018 6580 : bool bPaint = gProp.pSFlyOnlyDraw ||
4019 6580 : static_cast<SwContact*>(pUserCall)->GetFormat()->GetPrint().GetValue();
4020 3290 : if ( !bPaint )
4021 0 : bPaint = pSh->GetWin() && !pSh->IsPreview();
4022 :
4023 3290 : if ( bPaint )
4024 : {
4025 : //The paint may be prevented by the superior Flys.
4026 3290 : SwFrm *pAnch = 0;
4027 3290 : if ( pObj->ISA(SwFlyDrawObj) ) // i#117962#
4028 : {
4029 0 : bPaint = false;
4030 : }
4031 3290 : if ( pObj->ISA(SwVirtFlyDrawObj) )
4032 : {
4033 2336 : SwFlyFrm *pFly = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrm();
4034 2336 : if ( gProp.pSFlyOnlyDraw && gProp.pSFlyOnlyDraw == pFly )
4035 0 : return true;
4036 :
4037 : //Try to avoid displaying the intermediate stage, Flys which don't
4038 : //overlap with the page on which they are anchored won't be
4039 : //painted.
4040 : //HACK: exception: printing of frames in tables, those can overlap
4041 : //a page once in a while when dealing with oversized tables (HTML).
4042 2336 : SwPageFrm *pPage = pFly->FindPageFrm();
4043 2336 : if ( pPage && pPage->Frm().IsOver( pFly->Frm() ) )
4044 : {
4045 2099 : pAnch = pFly->AnchorFrm();
4046 : }
4047 :
4048 : }
4049 : else
4050 : {
4051 : // OD 13.10.2003 #i19919# - consider 'virtual' drawing objects
4052 : // OD 2004-03-29 #i26791#
4053 954 : SwDrawContact* pDrawContact = dynamic_cast<SwDrawContact*>(pUserCall);
4054 954 : pAnch = pDrawContact ? pDrawContact->GetAnchorFrm(pObj) : NULL;
4055 954 : if ( pAnch )
4056 : {
4057 954 : if ( !pAnch->GetValidPosFlag() )
4058 2 : pAnch = 0;
4059 952 : else if ( sal_IntPtr(pSh->GetOut()) == sal_IntPtr(pSh->getIDocumentDeviceAccess()->getPrinter( false )))
4060 : {
4061 : //HACK: we have to omit some of the objects for printing,
4062 : //otherwise they would be printed twice.
4063 : //The objects should get printed if the TableHack is active
4064 : //right now. Afterwards they must not be printed if the
4065 : //page over which they float position wise gets printed.
4066 0 : const SwPageFrm *pPage = pAnch->FindPageFrm();
4067 0 : if ( !pPage->Frm().IsOver( pObj->GetCurrentBoundRect() ) )
4068 0 : pAnch = 0;
4069 : }
4070 : }
4071 : else
4072 : {
4073 : // OD 02.07.2003 #108784# - debug assert
4074 0 : if ( !pObj->ISA(SdrObjGroup) )
4075 : {
4076 : OSL_FAIL( "<SwFlyFrm::IsPaint(..)> - paint of drawing object without anchor frame!?" );
4077 : }
4078 : }
4079 : }
4080 3290 : if ( pAnch )
4081 : {
4082 3051 : if ( pAnch->IsInFly() )
4083 271 : bPaint = SwFlyFrm::IsPaint( pAnch->FindFlyFrm()->GetVirtDrawObj(),
4084 271 : pSh );
4085 2780 : else if ( gProp.pSFlyOnlyDraw )
4086 0 : bPaint = false;
4087 : }
4088 : else
4089 239 : bPaint = false;
4090 : }
4091 3290 : return bPaint;
4092 : }
4093 :
4094 4293 : void SwCellFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
4095 : {
4096 4293 : if ( GetLayoutRowSpan() >= 1 )
4097 4279 : SwLayoutFrm::Paint( rRect );
4098 4293 : }
4099 :
4100 : struct BorderLinesGuard
4101 : {
4102 445 : explicit BorderLinesGuard() : m_pBorderLines(gProp.pBLines)
4103 : {
4104 445 : gProp.pBLines = new BorderLines;
4105 445 : }
4106 445 : ~BorderLinesGuard()
4107 : {
4108 445 : delete gProp.pBLines;
4109 445 : gProp.pBLines = m_pBorderLines;
4110 445 : }
4111 : private:
4112 : BorderLines *const m_pBorderLines;
4113 : };
4114 :
4115 445 : void SwFlyFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
4116 : {
4117 : //optimize thumbnail generation and store procedure to improve odt saving performance, #i120030#
4118 445 : SwViewShell *pShell = getRootFrm()->GetCurrShell();
4119 445 : if (pShell && pShell->GetDoc() && pShell->GetDoc()->GetDocShell())
4120 : {
4121 445 : bool bInGenerateThumbnail = pShell->GetDoc()->GetDocShell()->IsInGenerateAndStoreThumbnail();
4122 445 : if (bInGenerateThumbnail)
4123 : {
4124 77 : SwRect aVisRect = pShell->VisArea();
4125 77 : if (!aVisRect.IsOver(Frm()))
4126 445 : return;
4127 : }
4128 : }
4129 :
4130 : //because of the overlapping of frames and drawing objects the flys have to
4131 : //paint their borders (and those of the internal ones) directly.
4132 : //e.g. #33066#
4133 445 : gProp.pSLines->LockLines(true);
4134 445 : BorderLinesGuard blg; // this should not paint borders added from PaintBaBo
4135 :
4136 445 : SwRect aRect( rRect );
4137 445 : aRect._Intersection( Frm() );
4138 :
4139 445 : OutputDevice* pOut = gProp.pSGlobalShell->GetOut();
4140 445 : pOut->Push( PushFlags::CLIPREGION );
4141 445 : pOut->SetClipRegion();
4142 445 : const SwPageFrm* pPage = FindPageFrm();
4143 :
4144 890 : const SwNoTextFrm *pNoText = Lower() && Lower()->IsNoTextFrm()
4145 591 : ? static_cast<const SwNoTextFrm*>(Lower()) : 0;
4146 :
4147 445 : bool bIsChart = false; //#i102950# don't paint additional borders for charts
4148 : //check whether we have a chart
4149 445 : if(pNoText)
4150 : {
4151 146 : const SwNoTextNode* pNoTNd = dynamic_cast<const SwNoTextNode*>(pNoText->GetNode());
4152 146 : if( pNoTNd )
4153 : {
4154 146 : SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTNd->GetOLENode());
4155 146 : if( pOLENd && pOLENd->GetOLEObj().GetObject().IsChart() )
4156 18 : bIsChart = true;
4157 : }
4158 : }
4159 :
4160 : {
4161 445 : bool bContour = GetFormat()->GetSurround().IsContour();
4162 445 : tools::PolyPolygon aPoly;
4163 445 : if ( bContour )
4164 : {
4165 : // OD 16.04.2003 #i13147# - add 2nd parameter with value <true>
4166 : // to indicate that method is called for paint in order to avoid
4167 : // load of the intrinsic graphic.
4168 0 : bContour = GetContour( aPoly, true );
4169 : }
4170 :
4171 : // #i47804# - distinguish complete background paint
4172 : // and margin paint.
4173 : // paint complete background for Writer text fly frames
4174 445 : bool bPaintCompleteBack( !pNoText );
4175 : // paint complete background for transparent graphic and contour,
4176 : // if own background color exists.
4177 445 : const bool bIsGraphicTransparent = pNoText && pNoText->IsTransparent();
4178 445 : if ( !bPaintCompleteBack &&
4179 36 : ( bIsGraphicTransparent|| bContour ) )
4180 : {
4181 110 : const SwFrameFormat* pSwFrameFormat = dynamic_cast< const SwFrameFormat* >(GetFormat());
4182 :
4183 110 : if (pSwFrameFormat && pSwFrameFormat->supportsFullDrawingLayerFillAttributeSet())
4184 : {
4185 : //UUUU check for transparency
4186 110 : const drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(pSwFrameFormat->getSdrAllFillAttributesHelper());
4187 :
4188 : // check if the new fill attributes are used
4189 110 : if(aFillAttributes.get() && aFillAttributes->isUsed())
4190 : {
4191 1 : bPaintCompleteBack = true;
4192 110 : }
4193 : }
4194 : else
4195 : {
4196 0 : SvxBrushItem aBack = GetFormat()->makeBackgroundBrushItem();
4197 : // OD 07.08.2002 #99657# #GetTransChg#
4198 : // to determine, if background has to be painted, by checking, if
4199 : // background color is not COL_TRANSPARENT ("no fill"/"auto fill")
4200 : // or a background graphic exists.
4201 0 : bPaintCompleteBack = !(aBack.GetColor() == COL_TRANSPARENT) ||
4202 0 : aBack.GetGraphicPos() != GPOS_NONE;
4203 : }
4204 : }
4205 : // paint of margin needed.
4206 590 : const bool bPaintMarginOnly( !bPaintCompleteBack &&
4207 590 : Prt().SSize() != Frm().SSize() );
4208 :
4209 : // #i47804# - paint background of parent fly frame
4210 : // for transparent graphics in layer Hell, if parent fly frame isn't
4211 : // in layer Hell. It's only painted the intersection between the
4212 : // parent fly frame area and the paint area <aRect>
4213 445 : const IDocumentDrawModelAccess* pIDDMA = GetFormat()->getIDocumentDrawModelAccess();
4214 :
4215 555 : if (bIsGraphicTransparent &&
4216 126 : GetFormat()->GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS) &&
4217 461 : GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() &&
4218 0 : GetAnchorFrm()->FindFlyFrm() )
4219 : {
4220 0 : const SwFlyFrm* pParentFlyFrm = GetAnchorFrm()->FindFlyFrm();
4221 0 : if ( pParentFlyFrm->GetDrawObj()->GetLayer() !=
4222 0 : pIDDMA->GetHellId() )
4223 : {
4224 0 : SwFlyFrm* pOldRet = gProp.pSRetoucheFly2;
4225 0 : gProp.pSRetoucheFly2 = const_cast<SwFlyFrm*>(this);
4226 :
4227 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pParentFlyFrm );
4228 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
4229 0 : SwRect aPaintRect( aRect );
4230 0 : aPaintRect._Intersection( pParentFlyFrm->Frm() );
4231 0 : pParentFlyFrm->PaintBackground( aPaintRect, pPage, rAttrs, false, false );
4232 :
4233 0 : gProp.pSRetoucheFly2 = pOldRet;
4234 : }
4235 : }
4236 :
4237 445 : if ( bPaintCompleteBack || bPaintMarginOnly )
4238 : {
4239 : //#24926# JP 01.02.96, PaintBaBo is here partially so PaintBorder
4240 : //receives the original Rect but PaintBackground only the limited
4241 : //one.
4242 :
4243 : // OD 2004-04-23 #116347#
4244 304 : pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
4245 304 : pOut->SetLineColor();
4246 :
4247 304 : pPage = FindPageFrm();
4248 :
4249 304 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), static_cast<SwFrm const *>(this) );
4250 304 : const SwBorderAttrs &rAttrs = *aAccess.Get();
4251 :
4252 : // paint background
4253 : {
4254 304 : SwRegionRects aRegion( aRect );
4255 : // #i80822#
4256 : // suppress painting of background in printing area for
4257 : // non-transparent graphics.
4258 304 : if ( bPaintMarginOnly ||
4259 1 : ( pNoText && !bIsGraphicTransparent ) )
4260 : {
4261 : //What we actually want to paint is the small stripe between
4262 : //PrtArea and outer border.
4263 4 : SwRect aTmp( Prt() ); aTmp += Frm().Pos();
4264 4 : aRegion -= aTmp;
4265 : }
4266 304 : if ( bContour )
4267 : {
4268 0 : pOut->Push();
4269 : // #i80822#
4270 : // apply clip region under the same conditions, which are
4271 : // used in <SwNoTextFrm::Paint(..)> to set the clip region
4272 : // for painting the graphic/OLE. Thus, the clip region is
4273 : // also applied for the PDF export.
4274 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
4275 0 : if ( !pOut->GetConnectMetaFile() || !pSh || !pSh->GetWin() )
4276 : {
4277 0 : pOut->SetClipRegion(vcl::Region(aPoly));
4278 : }
4279 0 : for ( size_t i = 0; i < aRegion.size(); ++i )
4280 0 : PaintBackground( aRegion[i], pPage, rAttrs, false, true );
4281 0 : pOut->Pop();
4282 : }
4283 : else
4284 609 : for ( size_t i = 0; i < aRegion.size(); ++i )
4285 609 : PaintBackground( aRegion[i], pPage, rAttrs, false, true );
4286 : }
4287 :
4288 : // OD 06.08.2002 #99657# - paint border before painting background
4289 : // paint border
4290 : {
4291 304 : SwRect aTmp( rRect );
4292 304 : PaintBorder( aTmp, pPage, rAttrs );
4293 : }
4294 :
4295 304 : pOut->Pop();
4296 445 : }
4297 : }
4298 :
4299 : // OD 19.12.2002 #106318# - fly frame will paint it's subsidiary lines and
4300 : // the subsidiary lines of its lowers on its own, due to overlapping with
4301 : // other fly frames or other objects.
4302 890 : if( gProp.pSGlobalShell->GetWin()
4303 445 : && !bIsChart ) //#i102950# don't paint additional borders for charts
4304 : {
4305 : bool bSubsLineRectsCreated;
4306 351 : if ( gProp.pSSubsLines )
4307 : {
4308 : // Lock already existing subsidiary lines
4309 118 : gProp.pSSubsLines->LockLines( true );
4310 118 : bSubsLineRectsCreated = false;
4311 : }
4312 : else
4313 : {
4314 : // create new subsidiary lines
4315 233 : gProp.pSSubsLines = new SwSubsRects;
4316 233 : bSubsLineRectsCreated = true;
4317 : }
4318 :
4319 : bool bSpecSubsLineRectsCreated;
4320 351 : if ( gProp.pSSpecSubsLines )
4321 : {
4322 : // Lock already existing special subsidiary lines
4323 118 : gProp.pSSpecSubsLines->LockLines( true );
4324 118 : bSpecSubsLineRectsCreated = false;
4325 : }
4326 : else
4327 : {
4328 : // create new special subsidiary lines
4329 233 : gProp.pSSpecSubsLines = new SwSubsRects;
4330 233 : bSpecSubsLineRectsCreated = true;
4331 : }
4332 : // Add subsidiary lines of fly frame and its lowers
4333 351 : RefreshLaySubsidiary( pPage, aRect );
4334 : // paint subsidiary lines of fly frame and its lowers
4335 351 : gProp.pSSpecSubsLines->PaintSubsidiary( pOut, NULL, gProp );
4336 351 : gProp.pSSubsLines->PaintSubsidiary( pOut, gProp.pSLines, gProp );
4337 351 : if ( !bSubsLineRectsCreated )
4338 : // unlock subsidiary lines
4339 118 : gProp.pSSubsLines->LockLines( false );
4340 : else
4341 : // delete created subsidiary lines container
4342 233 : DELETEZ( gProp.pSSubsLines );
4343 :
4344 351 : if ( !bSpecSubsLineRectsCreated )
4345 : // unlock special subsidiary lines
4346 118 : gProp.pSSpecSubsLines->LockLines( false );
4347 : else
4348 : {
4349 : // delete created special subsidiary lines container
4350 233 : DELETEZ( gProp.pSSpecSubsLines );
4351 : }
4352 : }
4353 :
4354 445 : SwLayoutFrm::Paint( aRect );
4355 :
4356 445 : Validate();
4357 :
4358 : // OD 19.12.2002 #106318# - first paint lines added by fly frame paint
4359 : // and then unlock other lines.
4360 445 : gProp.pSLines->PaintLines( pOut, gProp );
4361 445 : gProp.pSLines->LockLines( false );
4362 : // have to paint frame borders added in heaven layer here...
4363 445 : ProcessPrimitives(gProp.pBLines->GetBorderLines_Clear());
4364 :
4365 445 : pOut->Pop();
4366 :
4367 445 : if ( gProp.pSProgress && pNoText )
4368 0 : gProp.pSProgress->Reschedule();
4369 : }
4370 :
4371 526 : void SwTabFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
4372 : {
4373 526 : const SwViewOption* pViewOption = gProp.pSGlobalShell->GetViewOptions();
4374 526 : if (pViewOption->IsTable())
4375 : {
4376 : // #i29550#
4377 526 : if ( IsCollapsingBorders() )
4378 : {
4379 525 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), static_cast<SwFrm const *>(this) );
4380 525 : const SwBorderAttrs &rAttrs = *aAccess.Get();
4381 :
4382 : // paint shadow
4383 525 : if ( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
4384 : {
4385 0 : SwRect aRect;
4386 0 : ::lcl_CalcBorderRect( aRect, this, rAttrs, true, gProp );
4387 0 : PaintShadow( rRect, aRect, rAttrs );
4388 : }
4389 :
4390 1050 : SwTabFrmPainter aHelper(*this);
4391 1050 : aHelper.PaintLines(*gProp.pSGlobalShell->GetOut(), rRect);
4392 : }
4393 :
4394 526 : SwLayoutFrm::Paint( rRect );
4395 : }
4396 : // OD 10.01.2003 #i6467# - no light grey rectangle for page preview
4397 0 : else if ( gProp.pSGlobalShell->GetWin() && !gProp.pSGlobalShell->IsPreview() )
4398 : {
4399 : // OD 10.01.2003 #i6467# - intersect output rectangle with table frame
4400 0 : SwRect aTabRect( Prt() );
4401 0 : aTabRect.Pos() += Frm().Pos();
4402 0 : SwRect aTabOutRect( rRect );
4403 0 : aTabOutRect.Intersection( aTabRect );
4404 0 : SwViewOption::DrawRect( gProp.pSGlobalShell->GetOut(), aTabOutRect, COL_LIGHTGRAY );
4405 : }
4406 526 : const_cast<SwTabFrm*>(this)->ResetComplete();
4407 526 : }
4408 :
4409 : /**
4410 : * Paint border shadow
4411 : *
4412 : * @param[in] rRect aligned rect to clip the result
4413 : * @param[in,out] rOutRect full painting area as input
4414 : * painting area reduced by shadow space for border and background as output
4415 : * @param[in] rShadow includes shadow attributes
4416 : * @param[in] bDrawFullShadowRectangle paint full rect of shadow
4417 : * @param[in] bTop paint top part of the shadow
4418 : * @param[in] bBottom paint bottom part of the shadow
4419 : * @param[in] bLeft paint left part of the shadow
4420 : * @param[in] bRight paint right part of the shadow
4421 : **/
4422 16 : static void lcl_PaintShadow( const SwRect& rRect, SwRect& rOutRect,
4423 : const SvxShadowItem& rShadow, const bool bDrawFullShadowRectangle,
4424 : const bool bTop, const bool bBottom,
4425 : const bool bLeft, const bool bRight,
4426 : SwPaintProperties& properties)
4427 : {
4428 16 : const long nWidth = ::lcl_AlignWidth ( rShadow.GetWidth(), properties );
4429 16 : const long nHeight = ::lcl_AlignHeight( rShadow.GetWidth(), properties );
4430 :
4431 16 : SwRects aRegion( 2 );
4432 16 : SwRect aOut( rOutRect );
4433 :
4434 16 : switch ( rShadow.GetLocation() )
4435 : {
4436 : case SVX_SHADOW_BOTTOMRIGHT:
4437 : {
4438 14 : if ( bDrawFullShadowRectangle )
4439 : {
4440 : // OD 06.08.2002 #99657# - draw full shadow rectangle
4441 0 : aOut.Top( rOutRect.Top() + nHeight );
4442 0 : aOut.Left( rOutRect.Left() + nWidth );
4443 0 : aRegion.push_back( aOut );
4444 : }
4445 : else
4446 : {
4447 14 : if( bBottom )
4448 : {
4449 14 : aOut.Top( rOutRect.Bottom() - nHeight );
4450 14 : if( bLeft )
4451 14 : aOut.Left( rOutRect.Left() + nWidth );
4452 14 : aRegion.push_back( aOut );
4453 : }
4454 14 : if( bRight )
4455 : {
4456 14 : aOut.Left( rOutRect.Right() - nWidth );
4457 14 : if( bTop )
4458 14 : aOut.Top( rOutRect.Top() + nHeight );
4459 : else
4460 0 : aOut.Top( rOutRect.Top() );
4461 14 : if( bBottom )
4462 14 : aOut.Bottom( rOutRect.Bottom() - nHeight );
4463 14 : aRegion.push_back( aOut );
4464 : }
4465 : }
4466 :
4467 14 : if( bRight )
4468 14 : rOutRect.Right( rOutRect.Right() - nWidth );
4469 14 : if( bBottom )
4470 14 : rOutRect.Bottom( rOutRect.Bottom()- nHeight );
4471 : }
4472 14 : break;
4473 : case SVX_SHADOW_TOPLEFT:
4474 : {
4475 0 : if ( bDrawFullShadowRectangle )
4476 : {
4477 : // OD 06.08.2002 #99657# - draw full shadow rectangle
4478 0 : aOut.Bottom( rOutRect.Bottom() - nHeight );
4479 0 : aOut.Right( rOutRect.Right() - nWidth );
4480 0 : aRegion.push_back( aOut );
4481 : }
4482 : else
4483 : {
4484 0 : if( bTop )
4485 : {
4486 0 : aOut.Bottom( rOutRect.Top() + nHeight );
4487 0 : if( bRight )
4488 0 : aOut.Right( rOutRect.Right() - nWidth );
4489 0 : aRegion.push_back( aOut );
4490 : }
4491 0 : if( bLeft )
4492 : {
4493 0 : aOut.Right( rOutRect.Left() + nWidth );
4494 0 : if( bBottom )
4495 0 : aOut.Bottom( rOutRect.Bottom() - nHeight );
4496 : else
4497 0 : aOut.Bottom( rOutRect.Bottom() );
4498 0 : if( bTop )
4499 0 : aOut.Top( rOutRect.Top() + nHeight );
4500 0 : aRegion.push_back( aOut );
4501 : }
4502 : }
4503 :
4504 0 : if( bLeft )
4505 0 : rOutRect.Left( rOutRect.Left() + nWidth );
4506 0 : if( bTop )
4507 0 : rOutRect.Top( rOutRect.Top() + nHeight );
4508 : }
4509 0 : break;
4510 : case SVX_SHADOW_TOPRIGHT:
4511 : {
4512 1 : if ( bDrawFullShadowRectangle )
4513 : {
4514 : // OD 06.08.2002 #99657# - draw full shadow rectangle
4515 0 : aOut.Bottom( rOutRect.Bottom() - nHeight);
4516 0 : aOut.Left( rOutRect.Left() + nWidth );
4517 0 : aRegion.push_back( aOut );
4518 : }
4519 : else
4520 : {
4521 1 : if( bTop )
4522 : {
4523 1 : aOut.Bottom( rOutRect.Top() + nHeight );
4524 1 : if( bLeft )
4525 1 : aOut.Left( rOutRect.Left() + nWidth );
4526 1 : aRegion.push_back( aOut );
4527 : }
4528 1 : if( bRight )
4529 : {
4530 1 : aOut.Left( rOutRect.Right() - nWidth );
4531 1 : if( bBottom )
4532 1 : aOut.Bottom( rOutRect.Bottom() - nHeight );
4533 : else
4534 0 : aOut.Bottom( rOutRect.Bottom() );
4535 1 : if( bTop )
4536 1 : aOut.Top( rOutRect.Top() + nHeight );
4537 1 : aRegion.push_back( aOut );
4538 : }
4539 : }
4540 :
4541 1 : if( bRight )
4542 1 : rOutRect.Right( rOutRect.Right() - nWidth );
4543 1 : if( bTop )
4544 1 : rOutRect.Top( rOutRect.Top() + nHeight );
4545 : }
4546 1 : break;
4547 : case SVX_SHADOW_BOTTOMLEFT:
4548 : {
4549 1 : if ( bDrawFullShadowRectangle )
4550 : {
4551 : // OD 06.08.2002 #99657# - draw full shadow rectangle
4552 0 : aOut.Top( rOutRect.Top() + nHeight );
4553 0 : aOut.Right( rOutRect.Right() - nWidth );
4554 0 : aRegion.push_back( aOut );
4555 : }
4556 : else
4557 : {
4558 1 : if( bBottom )
4559 : {
4560 1 : aOut.Top( rOutRect.Bottom()- nHeight );
4561 1 : if( bRight )
4562 1 : aOut.Right( rOutRect.Right() - nWidth );
4563 1 : aRegion.push_back( aOut );
4564 : }
4565 1 : if( bLeft )
4566 : {
4567 1 : aOut.Right( rOutRect.Left() + nWidth );
4568 1 : if( bTop )
4569 1 : aOut.Top( rOutRect.Top() + nHeight );
4570 : else
4571 0 : aOut.Top( rOutRect.Top() );
4572 1 : if( bBottom )
4573 1 : aOut.Bottom( rOutRect.Bottom() - nHeight );
4574 1 : aRegion.push_back( aOut );
4575 : }
4576 : }
4577 :
4578 1 : if( bLeft )
4579 1 : rOutRect.Left( rOutRect.Left() + nWidth );
4580 1 : if( bBottom )
4581 1 : rOutRect.Bottom( rOutRect.Bottom() - nHeight );
4582 : }
4583 1 : break;
4584 : default:
4585 : assert(false);
4586 0 : break;
4587 : }
4588 :
4589 16 : vcl::RenderContext *pOut = properties.pSGlobalShell->GetOut();
4590 :
4591 16 : DrawModeFlags nOldDrawMode = pOut->GetDrawMode();
4592 16 : Color aShadowColor( rShadow.GetColor().GetRGBColor() );
4593 27 : if( !aRegion.empty() && properties.pSGlobalShell->GetWin() &&
4594 11 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
4595 : {
4596 : // In high contrast mode, the output device has already set the
4597 : // DrawModeFlags::SettingsFill flag. This causes the SetFillColor function
4598 : // to ignore the setting of a new color. Therefore we have to reset
4599 : // the drawing mode
4600 0 : pOut->SetDrawMode( DrawModeFlags::Default );
4601 0 : aShadowColor = SwViewOption::GetFontColor();
4602 : }
4603 :
4604 16 : if ( pOut->GetFillColor() != aShadowColor )
4605 16 : pOut->SetFillColor( aShadowColor );
4606 :
4607 16 : pOut->SetLineColor();
4608 :
4609 16 : pOut->SetDrawMode( nOldDrawMode );
4610 :
4611 80 : for ( size_t i = 0; i < aRegion.size(); ++i )
4612 : {
4613 64 : SwRect &rOut = aRegion[i];
4614 64 : aOut = rOut;
4615 64 : if ( rRect.IsOver( aOut ) && aOut.Height() > 0 && aOut.Width() > 0 )
4616 : {
4617 21 : aOut._Intersection( rRect );
4618 21 : pOut->DrawRect( aOut.SVRect() );
4619 : }
4620 16 : }
4621 16 : }
4622 :
4623 : /**
4624 : * Paints a shadow if the format requests so.
4625 : *
4626 : * The shadow is always painted on the outer edge of the OutRect.
4627 : * If needed, the OutRect is shrunk so the painting of the border can be
4628 : * done on it.
4629 : *
4630 : * @note: draw full shadow rectangle for frames with transparent drawn backgrounds (OD 23.08.2002 #99657#)
4631 : */
4632 11 : void SwFrm::PaintShadow( const SwRect& rRect, SwRect& rOutRect,
4633 : const SwBorderAttrs &rAttrs ) const
4634 : {
4635 11 : SvxShadowItem rShadow = rAttrs.GetShadow();
4636 :
4637 11 : const bool bCnt = IsContentFrm();
4638 11 : const bool bTop = !bCnt || rAttrs.GetTopLine ( *(this) );
4639 11 : const bool bBottom = !bCnt || rAttrs.GetBottomLine( *(this) );
4640 :
4641 11 : if( IsVertical() )
4642 : {
4643 0 : switch( rShadow.GetLocation() )
4644 : {
4645 0 : case SVX_SHADOW_BOTTOMRIGHT: rShadow.SetLocation(SVX_SHADOW_BOTTOMLEFT); break;
4646 0 : case SVX_SHADOW_TOPLEFT: rShadow.SetLocation(SVX_SHADOW_TOPRIGHT); break;
4647 0 : case SVX_SHADOW_TOPRIGHT: rShadow.SetLocation(SVX_SHADOW_BOTTOMRIGHT); break;
4648 0 : case SVX_SHADOW_BOTTOMLEFT: rShadow.SetLocation(SVX_SHADOW_TOPLEFT); break;
4649 0 : default: break;
4650 : }
4651 : }
4652 :
4653 : // OD 23.08.2002 #99657# - determine, if full shadow rectangle have to
4654 : // be drawn or only two shadow rectangles beside the frame.
4655 : // draw full shadow rectangle, if frame background is drawn transparent.
4656 : // Status Quo:
4657 : // SwLayoutFrm can have transparent drawn backgrounds. Thus,
4658 : // "asked" their frame format.
4659 : const bool bDrawFullShadowRectangle =
4660 22 : ( IsLayoutFrm() &&
4661 11 : (static_cast<const SwLayoutFrm*>(this))->GetFormat()->IsBackgroundTransparent()
4662 11 : );
4663 :
4664 11 : SWRECTFN( this );
4665 11 : ::lcl_ExtendLeftAndRight( rOutRect, *(this), rAttrs, fnRect );
4666 :
4667 11 : lcl_PaintShadow(rRect, rOutRect, rShadow, bDrawFullShadowRectangle, bTop, bBottom, true, true, gProp);
4668 11 : }
4669 :
4670 2 : void SwFrm::PaintBorderLine( const SwRect& rRect,
4671 : const SwRect& rOutRect,
4672 : const SwPageFrm * pPage,
4673 : const Color *pColor,
4674 : const SvxBorderStyle nStyle ) const
4675 : {
4676 2 : if ( !rOutRect.IsOver( rRect ) )
4677 2 : return;
4678 :
4679 2 : SwRect aOut( rOutRect );
4680 2 : aOut._Intersection( rRect );
4681 :
4682 2 : const SwTabFrm *pTab = IsCellFrm() ? FindTabFrm() : 0;
4683 4 : sal_uInt8 nSubCol = ( IsCellFrm() || IsRowFrm() ) ? SUBCOL_TAB :
4684 2 : ( IsInSct() ? SUBCOL_SECT :
4685 4 : ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
4686 4 : if( pColor && gProp.pSGlobalShell->GetWin() &&
4687 2 : Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
4688 : {
4689 0 : pColor = &SwViewOption::GetFontColor();
4690 : }
4691 :
4692 2 : if (pPage->GetSortedObjs() &&
4693 0 : pPage->GetFormat()->GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS))
4694 : {
4695 0 : SwRegionRects aRegion( aOut, 4 );
4696 0 : ::lcl_SubtractFlys( this, pPage, aOut, aRegion, gProp );
4697 0 : for ( size_t i = 0; i < aRegion.size(); ++i )
4698 0 : gProp.pSLines->AddLineRect( aRegion[i], pColor, nStyle, pTab, nSubCol, gProp );
4699 : }
4700 : else
4701 2 : gProp.pSLines->AddLineRect( aOut, pColor, nStyle, pTab, nSubCol, gProp );
4702 : }
4703 :
4704 : /**
4705 : * @note Only all lines once or all lines twice!
4706 : *
4707 : * OD 29.04.2003 #107169# - method called for left and right border rectangles.
4708 : * For a printer output device perform adjustment for non-overlapping top and
4709 : * bottom border rectangles. Thus, add parameter <_bPrtOutputDev> to indicate
4710 : * printer output device.
4711 : * NOTE: For printer output device left/right border rectangle <_iorRect>
4712 : * has to be already non-overlapping the outer top/bottom border rectangle.
4713 : */
4714 296 : static void lcl_SubTopBottom( SwRect& _iorRect,
4715 : const SvxBoxItem& _rBox,
4716 : const SwBorderAttrs& _rAttrs,
4717 : const SwFrm& _rFrm,
4718 : const SwRectFn& _rRectFn,
4719 : const bool _bPrtOutputDev,
4720 : SwPaintProperties& properties )
4721 : {
4722 296 : const bool bCnt = _rFrm.IsContentFrm();
4723 296 : if ( _rBox.GetTop() && _rBox.GetTop()->GetInWidth() &&
4724 0 : ( !bCnt || _rAttrs.GetTopLine( _rFrm ) )
4725 : )
4726 : {
4727 : // subtract distance between outer and inner line.
4728 0 : SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetTop()->GetDistance(), properties );
4729 : // OD 19.05.2003 #109667# - non-overlapping border rectangles:
4730 : // adjust x-/y-position, if inner top line is a hair line (width = 1)
4731 0 : bool bIsInnerTopLineHairline = false;
4732 0 : if ( !_bPrtOutputDev )
4733 : {
4734 : // additionally subtract width of top outer line
4735 : // --> left/right inner/outer line doesn't overlap top outer line.
4736 0 : nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetOutWidth(), properties );
4737 : }
4738 : else
4739 : {
4740 : // OD 29.04.2003 #107169# - additionally subtract width of top inner line
4741 : // --> left/right inner/outer line doesn't overlap top inner line.
4742 0 : nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetInWidth(), properties );
4743 0 : bIsInnerTopLineHairline = _rBox.GetTop()->GetInWidth() == 1;
4744 : }
4745 0 : (_iorRect.*_rRectFn->fnSubTop)( -nDist );
4746 : // OD 19.05.2003 #109667# - adjust calculated border top, if inner top line
4747 : // is a hair line
4748 0 : if ( bIsInnerTopLineHairline )
4749 : {
4750 0 : if ( _rFrm.IsVertical() )
4751 : {
4752 : // right of border rectangle has to be checked and adjusted
4753 0 : Point aCompPt( _iorRect.Right(), 0 );
4754 0 : Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
4755 0 : lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
4756 : aRefPt, aCompPt,
4757 0 : true, -1 );
4758 0 : _iorRect.Right( aCompPt.X() );
4759 : }
4760 : else
4761 : {
4762 : // top of border rectangle has to be checked and adjusted
4763 0 : Point aCompPt( 0, _iorRect.Top() );
4764 0 : Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
4765 0 : lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
4766 : aRefPt, aCompPt,
4767 0 : false, +1 );
4768 0 : _iorRect.Top( aCompPt.Y() );
4769 : }
4770 : }
4771 : }
4772 :
4773 296 : if ( _rBox.GetBottom() && _rBox.GetBottom()->GetInWidth() &&
4774 0 : ( !bCnt || _rAttrs.GetBottomLine( _rFrm ) )
4775 : )
4776 : {
4777 : // subtract distance between outer and inner line.
4778 0 : SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetBottom()->GetDistance(), properties );
4779 : // OD 19.05.2003 #109667# - non-overlapping border rectangles:
4780 : // adjust x-/y-position, if inner bottom line is a hair line (width = 1)
4781 0 : bool bIsInnerBottomLineHairline = false;
4782 0 : if ( !_bPrtOutputDev )
4783 : {
4784 : // additionally subtract width of bottom outer line
4785 : // --> left/right inner/outer line doesn't overlap bottom outer line.
4786 0 : nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetOutWidth(), properties );
4787 : }
4788 : else
4789 : {
4790 : // OD 29.04.2003 #107169# - additionally subtract width of bottom inner line
4791 : // --> left/right inner/outer line doesn't overlap bottom inner line.
4792 0 : nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetInWidth(), properties );
4793 0 : bIsInnerBottomLineHairline = _rBox.GetBottom()->GetInWidth() == 1;
4794 : }
4795 0 : (_iorRect.*_rRectFn->fnAddBottom)( -nDist );
4796 : // OD 19.05.2003 #109667# - adjust calculated border bottom, if inner
4797 : // bottom line is a hair line.
4798 0 : if ( bIsInnerBottomLineHairline )
4799 : {
4800 0 : if ( _rFrm.IsVertical() )
4801 : {
4802 : // left of border rectangle has to be checked and adjusted
4803 0 : Point aCompPt( _iorRect.Left(), 0 );
4804 0 : Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
4805 0 : lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
4806 : aRefPt, aCompPt,
4807 0 : true, +1 );
4808 0 : _iorRect.Left( aCompPt.X() );
4809 : }
4810 : else
4811 : {
4812 : // bottom of border rectangle has to be checked and adjusted
4813 0 : Point aCompPt( 0, _iorRect.Bottom() );
4814 0 : Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
4815 0 : lcl_CompPxPosAndAdjustPos( *(properties.pSGlobalShell->GetOut()),
4816 : aRefPt, aCompPt,
4817 0 : false, -1 );
4818 0 : _iorRect.Bottom( aCompPt.Y() );
4819 : }
4820 : }
4821 : }
4822 296 : }
4823 :
4824 4906 : static sal_uInt16 lcl_GetLineWidth( const SvxBorderLine* pLine )
4825 : {
4826 4906 : if ( pLine != NULL )
4827 4770 : return pLine->GetScaledWidth();
4828 :
4829 136 : return 0;
4830 : }
4831 :
4832 2576 : static double lcl_GetExtent( const SvxBorderLine* pSideLine, const SvxBorderLine* pOppositeLine )
4833 : {
4834 2576 : double nExtent = 0.0;
4835 :
4836 2576 : if ( pSideLine && !pSideLine->isEmpty() )
4837 1152 : nExtent = -lcl_GetLineWidth( pSideLine ) / 2.0;
4838 1424 : else if ( pOppositeLine )
4839 1152 : nExtent = lcl_GetLineWidth( pOppositeLine ) / 2.0;
4840 :
4841 2576 : return nExtent;
4842 : }
4843 :
4844 648 : static void lcl_MakeBorderLine(SwRect const& rRect,
4845 : bool const isVerticalInModel,
4846 : bool const isLeftOrTopBorderInModel,
4847 : bool const isVertical,
4848 : SvxBorderLine const& rBorder,
4849 : SvxBorderLine const*const pLeftOrTopNeighbour,
4850 : SvxBorderLine const*const pRightOrBottomNeighbour,
4851 : SwPaintProperties& properties)
4852 : {
4853 : bool const isLeftOrTopBorder((isVerticalInModel == isVertical)
4854 : ? isLeftOrTopBorderInModel
4855 648 : : (isLeftOrTopBorderInModel != isVertical));
4856 : SvxBorderLine const*const pStartNeighbour(
4857 983 : (!isVertical && isVerticalInModel)
4858 648 : ? pRightOrBottomNeighbour : pLeftOrTopNeighbour);
4859 : SvxBorderLine const*const pEndNeighbour(
4860 : (pStartNeighbour == pLeftOrTopNeighbour)
4861 648 : ? pRightOrBottomNeighbour : pLeftOrTopNeighbour);
4862 :
4863 648 : basegfx::B2DPoint aStart;
4864 1292 : basegfx::B2DPoint aEnd;
4865 648 : if (isVertical)
4866 : { // fdo#38635: always from outer edge
4867 : double const fStartX( (isLeftOrTopBorder)
4868 155 : ? rRect.Left() + (rRect.Width() / 2.0)
4869 468 : : rRect.Right() - (rRect.Width() / 2.0));
4870 313 : aStart.setX(fStartX);
4871 313 : aStart.setY(rRect.Top() +
4872 313 : lcl_AlignHeight(lcl_GetLineWidth(pStartNeighbour), properties)/2.0);
4873 313 : aEnd.setX(fStartX);
4874 313 : aEnd.setY(rRect.Bottom() -
4875 313 : lcl_AlignHeight(lcl_GetLineWidth(pEndNeighbour), properties)/2.0);
4876 : }
4877 : else
4878 : { // fdo#38635: always from outer edge
4879 : double const fStartY( (isLeftOrTopBorder)
4880 146 : ? rRect.Top() + (rRect.Height() / 2.0)
4881 481 : : rRect.Bottom() - (rRect.Height() / 2.0));
4882 335 : aStart.setX(rRect.Left() +
4883 335 : lcl_AlignWidth(lcl_GetLineWidth(pStartNeighbour), properties)/2.0);
4884 335 : aStart.setY(fStartY);
4885 335 : aEnd.setX(rRect.Right() -
4886 335 : lcl_AlignWidth(lcl_GetLineWidth(pEndNeighbour), properties)/2.0);
4887 335 : aEnd.setY(fStartY);
4888 : }
4889 :
4890 : // When rendering to very small (virtual) devices, like when producing
4891 : // page thumbnails in a mobile device app, the line geometry can end up
4892 : // bogus (negative width or height), so just ignore such border lines.
4893 : // Otherwise we will run into assertions later in lcl_TryMergeBorderLine()
4894 : // at least.
4895 1296 : if (aEnd.getX() < aStart.getX() ||
4896 648 : aEnd.getY() < aStart.getY())
4897 652 : return;
4898 :
4899 : double const nExtentLeftStart = (isLeftOrTopBorder == isVertical)
4900 : ? lcl_GetExtent(pStartNeighbour, 0)
4901 644 : : lcl_GetExtent(0, pStartNeighbour);
4902 : double const nExtentLeftEnd = (isLeftOrTopBorder == isVertical)
4903 : ? lcl_GetExtent(pEndNeighbour, 0)
4904 644 : : lcl_GetExtent(0, pEndNeighbour);
4905 : double const nExtentRightStart = (isLeftOrTopBorder == isVertical)
4906 : ? lcl_GetExtent(0, pStartNeighbour)
4907 644 : : lcl_GetExtent(pStartNeighbour, 0);
4908 : double const nExtentRightEnd = (isLeftOrTopBorder == isVertical)
4909 : ? lcl_GetExtent(0, pEndNeighbour)
4910 644 : : lcl_GetExtent(pEndNeighbour, 0);
4911 :
4912 644 : double const nLeftWidth = rBorder.GetOutWidth();
4913 644 : double const nRightWidth = rBorder.GetInWidth();
4914 644 : Color const aLeftColor = rBorder.GetColorOut(isLeftOrTopBorder);
4915 644 : Color const aRightColor = rBorder.GetColorIn(isLeftOrTopBorder);
4916 :
4917 : ::rtl::Reference<BorderLinePrimitive2D> const xLine =
4918 : new BorderLinePrimitive2D(
4919 644 : aStart, aEnd, nLeftWidth, rBorder.GetDistance(), nRightWidth,
4920 : nExtentLeftStart, nExtentLeftEnd,
4921 : nExtentRightStart, nExtentRightEnd,
4922 : aLeftColor.getBColor(), aRightColor.getBColor(),
4923 644 : rBorder.GetColorGap().getBColor(), rBorder.HasGapColor(),
4924 1932 : rBorder.GetBorderLineStyle() );
4925 1288 : properties.pBLines->AddBorderLine(xLine, properties);
4926 : }
4927 :
4928 : /**
4929 : * OD 19.05.2003 #109667# - merge <lcl_PaintLeftLine> and <lcl_PaintRightLine>
4930 : * into new method <lcl_PaintLeftRightLine(..)>
4931 : */
4932 410 : static void lcl_PaintLeftRightLine( const bool _bLeft,
4933 : const SwFrm& _rFrm,
4934 : const SwPageFrm& /*_rPage*/,
4935 : const SwRect& _rOutRect,
4936 : const SwRect& /*_rRect*/,
4937 : const SwBorderAttrs& _rAttrs,
4938 : const SwRectFn& _rRectFn,
4939 : SwPaintProperties& properties)
4940 : {
4941 410 : const SvxBoxItem& rBox = _rAttrs.GetBox();
4942 410 : const bool bR2L = _rFrm.IsCellFrm() && _rFrm.IsRightToLeft();
4943 410 : const SvxBorderLine* pLeftRightBorder = 0;
4944 410 : const SvxBorderLine* pTopBorder = rBox.GetTop();
4945 410 : const SvxBorderLine* pBottomBorder = rBox.GetBottom();
4946 :
4947 410 : if ( _bLeft )
4948 : {
4949 205 : pLeftRightBorder = bR2L ? rBox.GetRight() : rBox.GetLeft();
4950 : }
4951 : else
4952 : {
4953 205 : pLeftRightBorder = bR2L ? rBox.GetLeft() : rBox.GetRight();
4954 : }
4955 :
4956 410 : if ( !pLeftRightBorder )
4957 : {
4958 508 : return;
4959 : }
4960 :
4961 312 : SwRect aRect( _rOutRect );
4962 312 : if ( _bLeft )
4963 : {
4964 156 : (aRect.*_rRectFn->fnAddRight)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ), properties ) -
4965 312 : (aRect.*_rRectFn->fnGetWidth)() );
4966 :
4967 : // Shift the left border to the left.
4968 156 : Point aCurPos = aRect.Pos();
4969 156 : const sal_uInt16 nOffset = pLeftRightBorder->GetDistance();
4970 156 : aCurPos.X() -= nOffset;
4971 156 : aCurPos.Y() -= nOffset;
4972 156 : aRect.Pos(aCurPos);
4973 156 : Size aCurSize = aRect.SSize();
4974 156 : aCurSize.Height() += nOffset * 2;
4975 156 : aRect.SSize(aCurSize);
4976 : }
4977 : else
4978 : {
4979 156 : (aRect.*_rRectFn->fnSubLeft)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ), properties ) -
4980 312 : (aRect.*_rRectFn->fnGetWidth)() );
4981 : }
4982 :
4983 312 : if ( _rFrm.IsContentFrm() )
4984 : {
4985 46 : ::lcl_ExtendLeftAndRight( aRect, _rFrm, _rAttrs, _rRectFn );
4986 :
4987 : // No Top / bottom borders for joint borders
4988 46 : if ( _rAttrs.JoinedWithPrev( _rFrm ) ) pTopBorder = NULL;
4989 46 : if ( _rAttrs.JoinedWithNext( _rFrm ) ) pBottomBorder = NULL;
4990 : }
4991 :
4992 312 : if ( !pLeftRightBorder->GetInWidth() )
4993 : {
4994 : // OD 06.05.2003 #107169# - init boolean indicating printer output device.
4995 : const bool bPrtOutputDev =
4996 296 : ( OUTDEV_PRINTER == properties.pSGlobalShell->GetOut()->GetOutDevType() );
4997 :
4998 : // OD 06.05.2003 #107169# - add 6th parameter
4999 296 : ::lcl_SubTopBottom( aRect, rBox, _rAttrs, _rFrm, _rRectFn, bPrtOutputDev, properties);
5000 : }
5001 :
5002 312 : if ( lcl_GetLineWidth( pLeftRightBorder ) > 0 )
5003 : {
5004 : lcl_MakeBorderLine(
5005 294 : aRect, true, _bLeft, aRect.Height() > aRect.Width(),
5006 294 : *pLeftRightBorder, pTopBorder, pBottomBorder, properties);
5007 : }
5008 : }
5009 :
5010 : /**
5011 : * OD 19.05.2003 #109667# - merge <lcl_PaintTopLine> and <lcl_PaintBottomLine>
5012 : * into <lcl_PaintTopLine>
5013 : */
5014 344 : static void lcl_PaintTopBottomLine( const bool _bTop,
5015 : const SwFrm& ,
5016 : const SwPageFrm& /*_rPage*/,
5017 : const SwRect& _rOutRect,
5018 : const SwRect& /*_rRect*/,
5019 : const SwBorderAttrs& _rAttrs,
5020 : const SwRectFn& _rRectFn,
5021 : SwPaintProperties& properties)
5022 : {
5023 344 : const SvxBoxItem& rBox = _rAttrs.GetBox();
5024 344 : const SvxBorderLine* pTopBottomBorder = 0;
5025 :
5026 344 : if ( _bTop )
5027 : {
5028 154 : pTopBottomBorder = rBox.GetTop();
5029 : }
5030 : else
5031 : {
5032 190 : pTopBottomBorder = rBox.GetBottom();
5033 : }
5034 :
5035 344 : if ( !pTopBottomBorder )
5036 : {
5037 347 : return;
5038 : }
5039 :
5040 341 : SwRect aRect( _rOutRect );
5041 341 : if ( _bTop )
5042 : {
5043 151 : (aRect.*_rRectFn->fnAddBottom)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ), properties ) -
5044 302 : (aRect.*_rRectFn->fnGetHeight)() );
5045 :
5046 : // Push the top border up a bit.
5047 151 : const sal_uInt16 nOffset = pTopBottomBorder->GetDistance();
5048 151 : Point aCurPos = aRect.Pos();
5049 151 : aCurPos.X() -= nOffset;
5050 151 : aCurPos.Y() -= nOffset;
5051 151 : aRect.Pos(aCurPos);
5052 151 : Size aCurSize = aRect.SSize();
5053 151 : aCurSize.Width() += nOffset * 2;
5054 151 : aRect.SSize(aCurSize);
5055 : }
5056 : else
5057 : {
5058 190 : (aRect.*_rRectFn->fnSubTop)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ), properties ) -
5059 380 : (aRect.*_rRectFn->fnGetHeight)() );
5060 : }
5061 :
5062 341 : if ( lcl_GetLineWidth( pTopBottomBorder ) > 0 )
5063 : {
5064 : lcl_MakeBorderLine(
5065 323 : aRect, false, _bTop, aRect.Height() > aRect.Width(),
5066 646 : *pTopBottomBorder, rBox.GetLeft(), rBox.GetRight(), properties);
5067 : }
5068 : }
5069 :
5070 20770 : void PaintCharacterBorder(
5071 : const SwFont& rFont,
5072 : const SwRect& rPaintArea,
5073 : const bool bVerticalLayout,
5074 : const bool bJoinWithPrev,
5075 : const bool bJoinWithNext )
5076 : {
5077 20770 : SwRect aAlignedRect(rPaintArea);
5078 20770 : SwAlignRect(aAlignedRect, gProp.pSGlobalShell);
5079 :
5080 20770 : bool bTop = true;
5081 20770 : bool bBottom = true;
5082 20770 : bool bLeft = true;
5083 20770 : bool bRight = true;
5084 :
5085 20770 : switch( rFont.GetOrientation(bVerticalLayout) )
5086 : {
5087 : case 0 :
5088 20769 : bLeft = !bJoinWithPrev;
5089 20769 : bRight = !bJoinWithNext;
5090 20769 : break;
5091 : case 900 :
5092 1 : bBottom = !bJoinWithPrev;
5093 1 : bTop = !bJoinWithNext;
5094 1 : break;
5095 : case 1800 :
5096 0 : bRight = !bJoinWithPrev;
5097 0 : bLeft = !bJoinWithNext;
5098 0 : break;
5099 : case 2700 :
5100 0 : bTop = !bJoinWithPrev;
5101 0 : bBottom = !bJoinWithNext;
5102 0 : break;
5103 : }
5104 :
5105 : // Paint shadow (reduce painting rect)
5106 : {
5107 : const SvxShadowItem aShadow(
5108 41540 : 0, &rFont.GetShadowColor(), rFont.GetShadowWidth(),
5109 62310 : rFont.GetAbsShadowLocation(bVerticalLayout));
5110 :
5111 20770 : if( aShadow.GetLocation() != SVX_SHADOW_NONE )
5112 : {
5113 : lcl_PaintShadow( SwRect(aAlignedRect), aAlignedRect, aShadow,
5114 5 : false, bTop, bBottom, bLeft, bRight, gProp);
5115 20770 : }
5116 : }
5117 :
5118 : // Init borders, after this initialization top, bottom, right and left means the
5119 : // absolute position
5120 : boost::optional<editeng::SvxBorderLine> aTopBorder =
5121 20770 : (bTop ? rFont.GetAbsTopBorder(bVerticalLayout) : boost::none);
5122 : boost::optional<editeng::SvxBorderLine> aBottomBorder =
5123 41540 : (bBottom ? rFont.GetAbsBottomBorder(bVerticalLayout) : boost::none);
5124 : boost::optional<editeng::SvxBorderLine> aLeftBorder =
5125 41540 : (bLeft ? rFont.GetAbsLeftBorder(bVerticalLayout) : boost::none);
5126 : boost::optional<editeng::SvxBorderLine> aRightBorder =
5127 41540 : (bRight ? rFont.GetAbsRightBorder(bVerticalLayout) : boost::none);
5128 :
5129 20770 : if( aTopBorder )
5130 : {
5131 8 : const sal_uInt16 nOffset = aTopBorder->GetDistance();
5132 :
5133 : Point aLeftTop(
5134 8 : aAlignedRect.Left() - nOffset,
5135 16 : aAlignedRect.Top() - nOffset);
5136 : Point aRightBottom(
5137 8 : aAlignedRect.Right() + nOffset,
5138 16 : aAlignedRect.Top() - nOffset + aTopBorder->GetScaledWidth());
5139 :
5140 : lcl_MakeBorderLine(
5141 : SwRect(aLeftTop, aRightBottom),
5142 : false, true, false,
5143 8 : aTopBorder.get(),
5144 8 : aLeftBorder.get_ptr(),
5145 8 : aRightBorder.get_ptr(),
5146 8 : gProp);
5147 : }
5148 :
5149 20770 : if( aBottomBorder )
5150 : {
5151 8 : if( aBottomBorder->isDouble() )
5152 1 : aBottomBorder->SetMirrorWidths(true);
5153 :
5154 : Point aLeftTop(
5155 : aAlignedRect.Left(),
5156 8 : aAlignedRect.Bottom() - aBottomBorder.get().GetScaledWidth());
5157 : Point aRightBottom(
5158 : aAlignedRect.Right(),
5159 8 : aAlignedRect.Bottom());
5160 :
5161 : lcl_MakeBorderLine(
5162 : SwRect(aLeftTop, aRightBottom),
5163 : false, false, false,
5164 8 : aBottomBorder.get(),
5165 8 : aLeftBorder.get_ptr(),
5166 8 : aRightBorder.get_ptr(),
5167 8 : gProp );
5168 : }
5169 :
5170 20770 : if( aLeftBorder )
5171 : {
5172 8 : const sal_uInt16 nOffset = aLeftBorder->GetDistance();
5173 :
5174 : Point aLeftTop(
5175 8 : aAlignedRect.Left() - nOffset,
5176 16 : aAlignedRect.Top() - nOffset);
5177 : Point aRightBottom(
5178 8 : aAlignedRect.Left() - nOffset + aLeftBorder->GetScaledWidth(),
5179 16 : aAlignedRect.Bottom() + nOffset);
5180 :
5181 : lcl_MakeBorderLine(
5182 : SwRect(aLeftTop, aRightBottom),
5183 : true, true, true,
5184 8 : aLeftBorder.get(),
5185 8 : aTopBorder.get_ptr(),
5186 8 : aBottomBorder.get_ptr(),
5187 8 : gProp );
5188 : }
5189 :
5190 20770 : if( aRightBorder )
5191 : {
5192 7 : if( aRightBorder->isDouble() )
5193 0 : aRightBorder->SetMirrorWidths(true);
5194 :
5195 : Point aLeftTop(
5196 7 : aAlignedRect.Right() - aRightBorder.get().GetScaledWidth(),
5197 14 : aAlignedRect.Top());
5198 : Point aRightBottom(
5199 : aAlignedRect.Right(),
5200 7 : aAlignedRect.Bottom());
5201 :
5202 : lcl_MakeBorderLine(
5203 : SwRect(aLeftTop, aRightBottom),
5204 : true, false, true,
5205 7 : aRightBorder.get(),
5206 7 : aTopBorder.get_ptr(),
5207 7 : aBottomBorder.get_ptr(),
5208 7 : gProp );
5209 20770 : }
5210 20770 : }
5211 :
5212 : /// #i15844#
5213 0 : static const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
5214 : {
5215 : OSL_ENSURE( rFrm.IsCellFrm(),
5216 : "lcl_HasNextCell( const SwFrm& rFrm ) should be called with SwCellFrm" );
5217 :
5218 0 : const SwFrm* pTmpFrm = &rFrm;
5219 0 : do
5220 : {
5221 0 : if ( pTmpFrm->GetNext() )
5222 0 : return pTmpFrm->GetNext();
5223 :
5224 0 : pTmpFrm = pTmpFrm->GetUpper()->GetUpper();
5225 : }
5226 : while ( pTmpFrm->IsCellFrm() );
5227 :
5228 0 : return 0;
5229 : }
5230 :
5231 : /**
5232 : * Determine cell frame, from which the border attributes
5233 : * for paint of top/bottom border has to be used.
5234 : *
5235 : * OD 21.02.2003 #b4779636#, #107692#
5236 : *
5237 : * @param _pCellFrm
5238 : * input parameter - constant pointer to cell frame for which the cell frame
5239 : * for the border attributes has to be determined.
5240 : *
5241 : * @param _rCellBorderAttrs
5242 : * input parameter - constant reference to the border attributes of cell frame
5243 : * <_pCellFrm>.
5244 : *
5245 : * @param _bTop
5246 : * input parameter - boolean, that controls, if cell frame for top border or
5247 : * for bottom border has to be determined.
5248 : *
5249 : * @return constant pointer to cell frame, for which the border attributes has
5250 : * to be used
5251 : */
5252 4 : static const SwFrm* lcl_GetCellFrmForBorderAttrs( const SwFrm* _pCellFrm,
5253 : const SwBorderAttrs& _rCellBorderAttrs,
5254 : const bool _bTop )
5255 : {
5256 : OSL_ENSURE( _pCellFrm, "No cell frame available, dying soon" );
5257 :
5258 : // determine, if cell frame is at bottom/top border of a table frame and
5259 : // the table frame has/is a follow.
5260 4 : const SwFrm* pTmpFrm = _pCellFrm;
5261 4 : bool bCellAtBorder = true;
5262 4 : bool bCellAtLeftBorder = !_pCellFrm->GetPrev();
5263 4 : bool bCellAtRightBorder = !_pCellFrm->GetNext();
5264 12 : while( !pTmpFrm->IsRowFrm() || !pTmpFrm->GetUpper()->IsTabFrm() )
5265 : {
5266 4 : pTmpFrm = pTmpFrm->GetUpper();
5267 6 : if ( pTmpFrm->IsRowFrm() &&
5268 4 : (_bTop ? pTmpFrm->GetPrev() : pTmpFrm->GetNext())
5269 : )
5270 : {
5271 0 : bCellAtBorder = false;
5272 : }
5273 4 : if ( pTmpFrm->IsCellFrm() )
5274 : {
5275 0 : if ( pTmpFrm->GetPrev() )
5276 : {
5277 0 : bCellAtLeftBorder = false;
5278 : }
5279 0 : if ( pTmpFrm->GetNext() )
5280 : {
5281 0 : bCellAtRightBorder = false;
5282 : }
5283 : }
5284 : }
5285 : OSL_ENSURE( pTmpFrm && pTmpFrm->IsRowFrm(), "No RowFrm available" );
5286 :
5287 4 : const SwLayoutFrm* pParentRowFrm = static_cast<const SwLayoutFrm*>(pTmpFrm);
5288 : const SwTabFrm* pParentTabFrm =
5289 4 : static_cast<const SwTabFrm*>(pParentRowFrm->GetUpper());
5290 :
5291 8 : const bool bCellNeedsAttribute = bCellAtBorder &&
5292 : ( _bTop ?
5293 : // bCellInFirstRowWithMaster
5294 4 : ( !pParentRowFrm->GetPrev() &&
5295 2 : pParentTabFrm->IsFollow() &&
5296 0 : 0 == pParentTabFrm->GetTable()->GetRowsToRepeat() ) :
5297 : // bCellInLastRowWithFollow
5298 4 : ( !pParentRowFrm->GetNext() &&
5299 2 : pParentTabFrm->GetFollow() )
5300 4 : );
5301 :
5302 4 : const SwFrm* pRet = _pCellFrm;
5303 4 : if ( bCellNeedsAttribute )
5304 : {
5305 : // determine, if cell frame has no borders inside the table.
5306 0 : const SwFrm* pNextCell = 0;
5307 0 : bool bNoBordersInside = false;
5308 :
5309 0 : if ( bCellAtLeftBorder && ( 0 != ( pNextCell = lcl_HasNextCell( *_pCellFrm ) ) ) )
5310 : {
5311 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNextCell );
5312 0 : const SwBorderAttrs &rBorderAttrs = *aAccess.Get();
5313 0 : const SvxBoxItem& rBorderBox = rBorderAttrs.GetBox();
5314 0 : bCellAtRightBorder = !lcl_HasNextCell( *pNextCell );
5315 : bNoBordersInside =
5316 0 : ( !rBorderBox.GetTop() || !pParentRowFrm->GetPrev() ) &&
5317 0 : !rBorderBox.GetLeft() &&
5318 0 : ( !rBorderBox.GetRight() || bCellAtRightBorder ) &&
5319 0 : ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
5320 : }
5321 : else
5322 : {
5323 0 : const SvxBoxItem& rBorderBox = _rCellBorderAttrs.GetBox();
5324 : bNoBordersInside =
5325 0 : ( !rBorderBox.GetTop() || !pParentRowFrm->GetPrev() ) &&
5326 0 : ( !rBorderBox.GetLeft() || bCellAtLeftBorder ) &&
5327 0 : ( !rBorderBox.GetRight() || bCellAtRightBorder ) &&
5328 0 : ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
5329 : }
5330 :
5331 0 : if ( bNoBordersInside )
5332 : {
5333 0 : if ( _bTop && !_rCellBorderAttrs.GetBox().GetTop() )
5334 : {
5335 : //-hack
5336 : // Cell frame has no top border and no border inside the table, but
5337 : // it is at the top border of a table frame, which is a follow.
5338 : // Thus, use border attributes of cell frame in first row of complete table.
5339 : // First, determine first table frame of complete table.
5340 0 : SwTabFrm* pMasterTabFrm = pParentTabFrm->FindMaster( true );
5341 : // determine first row of complete table.
5342 0 : const SwFrm* pFirstRow = pMasterTabFrm->GetLower();
5343 : // return first cell in first row
5344 0 : SwFrm* pLowerCell = const_cast<SwFrm*>(pFirstRow->GetLower());
5345 0 : while ( !pLowerCell->IsCellFrm() ||
5346 0 : ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
5347 : )
5348 : {
5349 0 : pLowerCell = pLowerCell->GetLower();
5350 : }
5351 : OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
5352 0 : pRet = pLowerCell;
5353 : }
5354 0 : else if ( !_bTop && !_rCellBorderAttrs.GetBox().GetBottom() )
5355 : {
5356 : //-hack
5357 : // Cell frame has no bottom border and no border inside the table,
5358 : // but it is at the bottom border of a table frame, which has a follow.
5359 : // Thus, use border attributes of cell frame in last row of complete table.
5360 : // First, determine last table frame of complete table.
5361 0 : SwTabFrm* pLastTabFrm = const_cast<SwTabFrm*>(pParentTabFrm->GetFollow());
5362 0 : while ( pLastTabFrm->GetFollow() )
5363 : {
5364 0 : pLastTabFrm = pLastTabFrm->GetFollow();
5365 : }
5366 : // determine last row of complete table.
5367 0 : SwFrm* pLastRow = pLastTabFrm->GetLastLower();
5368 : // return first bottom border cell in last row
5369 0 : SwFrm* pLowerCell = pLastRow->GetLower();
5370 0 : while ( !pLowerCell->IsCellFrm() ||
5371 0 : ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
5372 : )
5373 : {
5374 0 : if ( pLowerCell->IsRowFrm() )
5375 : {
5376 0 : while ( pLowerCell->GetNext() )
5377 : {
5378 0 : pLowerCell = pLowerCell->GetNext();
5379 : }
5380 : }
5381 0 : pLowerCell = pLowerCell->GetLower();
5382 : }
5383 : OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
5384 0 : pRet = pLowerCell;
5385 : }
5386 : }
5387 : }
5388 :
5389 4 : return pRet;
5390 : }
5391 :
5392 27728 : drawinglayer::processor2d::BaseProcessor2D * SwFrm::CreateProcessor2D( ) const
5393 : {
5394 27728 : basegfx::B2DRange aViewRange;
5395 :
5396 27728 : SdrPage *pDrawPage = getRootFrm()->GetCurrShell()->Imp()->GetPageView()->GetPage();
5397 : const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
5398 : basegfx::B2DHomMatrix( ),
5399 : getRootFrm()->GetCurrShell()->GetOut()->GetViewTransformation(),
5400 : aViewRange,
5401 : GetXDrawPageForSdrPage( pDrawPage ),
5402 : 0.0,
5403 27728 : uno::Sequence< beans::PropertyValue >() );
5404 :
5405 : return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
5406 27728 : *getRootFrm()->GetCurrShell()->GetOut(),
5407 27728 : aNewViewInfos );
5408 : }
5409 :
5410 27728 : void SwFrm::ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DSequence& rSequence ) const
5411 : {
5412 27728 : drawinglayer::processor2d::BaseProcessor2D * pProcessor2D = CreateProcessor2D();
5413 :
5414 27728 : if ( pProcessor2D )
5415 : {
5416 27728 : pProcessor2D->process( rSequence );
5417 27728 : delete pProcessor2D;
5418 : }
5419 27728 : }
5420 :
5421 : /// Paints shadows and borders
5422 50346 : void SwFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
5423 : const SwBorderAttrs &rAttrs ) const
5424 : {
5425 : // There's nothing (Row,Body,Footnote,Root,Column,NoText) need to do here
5426 50346 : if ((GetType() & (FRM_NOTXT|FRM_ROW|FRM_BODY|FRM_FTN|FRM_COLUMN|FRM_ROOT)))
5427 12960 : return;
5428 :
5429 37386 : if (IsCellFrm() && !gProp.pSGlobalShell->GetViewOptions()->IsTable())
5430 0 : return;
5431 :
5432 : // #i29550#
5433 37386 : if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
5434 : {
5435 6224 : const SwTabFrm* pTabFrm = FindTabFrm();
5436 6224 : if ( pTabFrm->IsCollapsingBorders() )
5437 6221 : return;
5438 :
5439 3 : if ( pTabFrm->GetTable()->IsNewModel() && ( !IsCellFrm() || IsCoveredCell() ) )
5440 1 : return;
5441 : }
5442 :
5443 31164 : const bool bLine = rAttrs.IsLine();
5444 31164 : const bool bShadow = rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE;
5445 :
5446 : // - flag to control,
5447 : //-hack has to be used.
5448 31164 : const bool bb4779636HackActive = true;
5449 :
5450 31164 : const SwFrm* pCellFrmForBottomBorderAttrs = 0;
5451 31164 : const SwFrm* pCellFrmForTopBorderAttrs = 0;
5452 31164 : bool bFoundCellForTopOrBorderAttrs = false;
5453 31164 : if ( bb4779636HackActive && IsCellFrm() )
5454 : {
5455 2 : pCellFrmForBottomBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, false );
5456 2 : if ( pCellFrmForBottomBorderAttrs != this )
5457 0 : bFoundCellForTopOrBorderAttrs = true;
5458 2 : pCellFrmForTopBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, true );
5459 2 : if ( pCellFrmForTopBorderAttrs != this )
5460 0 : bFoundCellForTopOrBorderAttrs = true;
5461 : }
5462 :
5463 : // - add condition <bFoundCellForTopOrBorderAttrs>
5464 : //-hack
5465 31164 : if ( bLine || bShadow || bFoundCellForTopOrBorderAttrs )
5466 : {
5467 : //If the rectangle is completely inside the PrtArea, no border needs to
5468 : //be painted.
5469 : //For the PrtArea the aligned value needs to be used, otherwise it could
5470 : //happen, that some parts won't be processed.
5471 209 : SwRect aRect( Prt() );
5472 209 : aRect += Frm().Pos();
5473 209 : ::SwAlignRect( aRect, gProp.pSGlobalShell );
5474 : // OD 27.09.2002 #103636# - new local boolean variable in order to
5475 : // suspend border paint under special cases - see below.
5476 : // NOTE: This is a fix for the implementation of feature #99657#.
5477 209 : bool bDrawOnlyShadowForTransparentFrame = false;
5478 209 : if ( aRect.IsInside( rRect ) )
5479 : {
5480 : // OD 27.09.2002 #103636# - paint shadow, if background is transparent.
5481 : // Because of introduced transparent background for fly frame #99657#,
5482 : // the shadow have to be drawn if the background is transparent,
5483 : // in spite the fact that the paint rectangle <rRect> lies fully
5484 : // in the printing area.
5485 : // NOTE to chosen solution:
5486 : // On transparent background, continue processing, but suspend
5487 : // drawing of border by setting <bDrawOnlyShadowForTransparentFrame>
5488 : // to true.
5489 0 : if ( IsLayoutFrm() &&
5490 0 : static_cast<const SwLayoutFrm*>(this)->GetFormat()->IsBackgroundTransparent() )
5491 : {
5492 0 : bDrawOnlyShadowForTransparentFrame = true;
5493 : }
5494 : else
5495 : {
5496 0 : return;
5497 : }
5498 : }
5499 :
5500 209 : if ( !pPage )
5501 0 : pPage = FindPageFrm();
5502 :
5503 209 : ::lcl_CalcBorderRect( aRect, this, rAttrs, true, gProp );
5504 209 : rAttrs.SetGetCacheLine( true );
5505 209 : if ( bShadow )
5506 11 : PaintShadow( rRect, aRect, rAttrs );
5507 : // OD 27.09.2002 #103636# - suspend drawing of border
5508 : // add condition < NOT bDrawOnlyShadowForTransparentFrame > - see above
5509 : // - add condition <bFoundCellForTopOrBorderAttrs>
5510 : //-hack.
5511 414 : if ( ( bLine || bFoundCellForTopOrBorderAttrs ) &&
5512 205 : !bDrawOnlyShadowForTransparentFrame )
5513 : {
5514 205 : const SwFrm* pDirRefFrm = IsCellFrm() ? FindTabFrm() : this;
5515 205 : SWRECTFN( pDirRefFrm )
5516 205 : ::lcl_PaintLeftRightLine ( true, *(this), *(pPage), aRect, rRect, rAttrs, fnRect, gProp);
5517 205 : ::lcl_PaintLeftRightLine ( false, *(this), *(pPage), aRect, rRect, rAttrs, fnRect, gProp);
5518 205 : if ( !IsContentFrm() || rAttrs.GetTopLine( *(this) ) )
5519 : {
5520 : // -
5521 : //-hack
5522 : // paint is found, paint its top border.
5523 154 : if ( IsCellFrm() && pCellFrmForTopBorderAttrs != this )
5524 : {
5525 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(),
5526 0 : pCellFrmForTopBorderAttrs );
5527 0 : const SwBorderAttrs &rTopAttrs = *aAccess.Get();
5528 0 : ::lcl_PaintTopBottomLine( true, *(this), *(pPage), aRect, rRect, rTopAttrs, fnRect, gProp);
5529 : }
5530 : else
5531 : {
5532 154 : ::lcl_PaintTopBottomLine( true, *(this), *(pPage), aRect, rRect, rAttrs, fnRect, gProp );
5533 : }
5534 : }
5535 205 : if ( !IsContentFrm() || rAttrs.GetBottomLine( *(this) ) )
5536 : {
5537 : // -
5538 : //-hack
5539 : // paint is found, paint its bottom border.
5540 190 : if ( IsCellFrm() && pCellFrmForBottomBorderAttrs != this )
5541 : {
5542 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(),
5543 0 : pCellFrmForBottomBorderAttrs );
5544 0 : const SwBorderAttrs &rBottomAttrs = *aAccess.Get();
5545 0 : ::lcl_PaintTopBottomLine(false, *(this), *(pPage), aRect, rRect, rBottomAttrs, fnRect, gProp);
5546 : }
5547 : else
5548 : {
5549 190 : ::lcl_PaintTopBottomLine(false, *(this), *(pPage), aRect, rRect, rAttrs, fnRect, gProp);
5550 : }
5551 : }
5552 : }
5553 209 : rAttrs.SetGetCacheLine( false );
5554 : }
5555 : }
5556 :
5557 : /**
5558 : * Special implementation because of the footnote line
5559 : *
5560 : * Currently only the top frame needs to be taken into account
5561 : * Other lines and shadows are set aside
5562 : */
5563 7 : void SwFootnoteContFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
5564 : const SwBorderAttrs & ) const
5565 : {
5566 : //If the rectangle is completely inside the PrtArea, no border needs to
5567 : //be painted.
5568 7 : SwRect aRect( Prt() );
5569 7 : aRect.Pos() += Frm().Pos();
5570 7 : if ( !aRect.IsInside( rRect ) )
5571 7 : PaintLine( rRect, pPage );
5572 7 : }
5573 :
5574 : /// Paint footnote lines.
5575 7 : void SwFootnoteContFrm::PaintLine( const SwRect& rRect,
5576 : const SwPageFrm *pPage ) const
5577 : {
5578 : //The length of the line is derived from the percentual indication on the
5579 : //PageDesc. The position is also stated on the PageDesc.
5580 : //The pen can directly be taken from the PageDesc.
5581 :
5582 7 : if ( !pPage )
5583 0 : pPage = FindPageFrm();
5584 7 : const SwPageFootnoteInfo &rInf = pPage->GetPageDesc()->GetFootnoteInfo();
5585 :
5586 7 : SWRECTFN( this )
5587 7 : SwTwips nPrtWidth = (Prt().*fnRect->fnGetWidth)();
5588 7 : Fraction aFract( nPrtWidth, 1 );
5589 7 : const SwTwips nWidth = (long)(aFract *= rInf.GetWidth());
5590 :
5591 7 : SwTwips nX = (this->*fnRect->fnGetPrtLeft)();
5592 7 : switch ( rInf.GetAdj() )
5593 : {
5594 : case FTNADJ_CENTER:
5595 0 : nX += nPrtWidth/2 - nWidth/2; break;
5596 : case FTNADJ_RIGHT:
5597 0 : nX += nPrtWidth - nWidth; break;
5598 : case FTNADJ_LEFT:
5599 7 : /* do nothing */; break;
5600 : default:
5601 : OSL_ENSURE( false, "New adjustment for footnote lines?" );
5602 : }
5603 7 : SwTwips nLineWidth = rInf.GetLineWidth();
5604 : const SwRect aLineRect = bVert ?
5605 0 : SwRect( Point(Frm().Left()+Frm().Width()-rInf.GetTopDist()-nLineWidth,
5606 : nX), Size( nLineWidth, nWidth ) )
5607 7 : : SwRect( Point( nX, Frm().Pos().Y() + rInf.GetTopDist() ),
5608 14 : Size( nWidth, rInf.GetLineWidth()));
5609 7 : if ( aLineRect.HasArea() )
5610 2 : PaintBorderLine( rRect, aLineRect , pPage, &rInf.GetLineColor(),
5611 4 : rInf.GetLineStyle() );
5612 7 : }
5613 :
5614 : /// Paints the separator line for inside columns
5615 0 : void SwLayoutFrm::PaintColLines( const SwRect &rRect, const SwFormatCol &rFormatCol,
5616 : const SwPageFrm *pPage ) const
5617 : {
5618 0 : const SwFrm *pCol = Lower();
5619 0 : if ( !pCol || !pCol->IsColumnFrm() )
5620 0 : return;
5621 :
5622 0 : SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
5623 :
5624 0 : SwRect aLineRect = Prt();
5625 0 : aLineRect += Frm().Pos();
5626 :
5627 0 : SwTwips nTop = ((aLineRect.*fnRect->fnGetHeight)()*rFormatCol.GetLineHeight())
5628 0 : / 100 - (aLineRect.*fnRect->fnGetHeight)();
5629 0 : SwTwips nBottom = 0;
5630 :
5631 0 : switch ( rFormatCol.GetLineAdj() )
5632 : {
5633 : case COLADJ_CENTER:
5634 0 : nBottom = nTop / 2; nTop -= nBottom; break;
5635 : case COLADJ_TOP:
5636 0 : nBottom = nTop; nTop = 0; break;
5637 : case COLADJ_BOTTOM:
5638 0 : break;
5639 : default:
5640 : OSL_ENSURE( false, "New adjustment for column lines?" );
5641 : }
5642 :
5643 0 : if( nTop )
5644 0 : (aLineRect.*fnRect->fnSubTop)( nTop );
5645 0 : if( nBottom )
5646 0 : (aLineRect.*fnRect->fnAddBottom)( nBottom );
5647 :
5648 0 : SwTwips nPenHalf = rFormatCol.GetLineWidth();
5649 0 : (aLineRect.*fnRect->fnSetWidth)( nPenHalf );
5650 0 : nPenHalf /= 2;
5651 :
5652 : //We need to be a bit generous here, to not lose something.
5653 0 : SwRect aRect( rRect );
5654 0 : (aRect.*fnRect->fnSubLeft)( nPenHalf + gProp.nSPixelSzW );
5655 0 : (aRect.*fnRect->fnAddRight)( nPenHalf + gProp.nSPixelSzW );
5656 0 : SwRectGet fnGetX = IsRightToLeft() ? fnRect->fnGetLeft : fnRect->fnGetRight;
5657 0 : while ( pCol->GetNext() )
5658 : {
5659 : (aLineRect.*fnRect->fnSetPosX)
5660 0 : ( (pCol->Frm().*fnGetX)() - nPenHalf );
5661 0 : if ( aRect.IsOver( aLineRect ) )
5662 0 : PaintBorderLine( aRect, aLineRect , pPage, &rFormatCol.GetLineColor(),
5663 0 : rFormatCol.GetLineStyle() );
5664 0 : pCol = pCol->GetNext();
5665 : }
5666 : }
5667 :
5668 9249 : void SwPageFrm::PaintGrid( OutputDevice* pOut, SwRect &rRect ) const
5669 : {
5670 9249 : if( !bHasGrid || gProp.pSRetoucheFly || gProp.pSRetoucheFly2 )
5671 18491 : return;
5672 7 : SwTextGridItem const*const pGrid(GetGridItem(this));
5673 14 : if( pGrid && ( OUTDEV_PRINTER != pOut->GetOutDevType() ?
5674 7 : pGrid->GetDisplayGrid() : pGrid->GetPrintGrid() ) )
5675 : {
5676 0 : const SwLayoutFrm* pBody = FindBodyCont();
5677 0 : if( pBody )
5678 : {
5679 0 : SwRect aGrid( pBody->Prt() );
5680 0 : aGrid += pBody->Frm().Pos();
5681 :
5682 0 : SwRect aInter( aGrid );
5683 0 : aInter.Intersection( rRect );
5684 0 : if( aInter.HasArea() )
5685 : {
5686 0 : bool bGrid = pGrid->GetRubyTextBelow();
5687 0 : bool bCell = GRID_LINES_CHARS == pGrid->GetGridType();
5688 0 : long nGrid = pGrid->GetBaseHeight();
5689 0 : const SwDoc* pDoc = GetFormat()->GetDoc();
5690 0 : long nGridWidth = GetGridWidth(*pGrid, *pDoc);
5691 0 : long nRuby = pGrid->GetRubyHeight();
5692 0 : long nSum = nGrid + nRuby;
5693 0 : const Color *pCol = &pGrid->GetColor();
5694 :
5695 0 : SwTwips nRight = aInter.Left() + aInter.Width();
5696 0 : SwTwips nBottom = aInter.Top() + aInter.Height();
5697 0 : if( IsVertical() )
5698 : {
5699 0 : SwTwips nOrig = aGrid.Left() + aGrid.Width();
5700 0 : SwTwips nY = nOrig + nSum *
5701 0 : ( ( nOrig - aInter.Left() ) / nSum );
5702 : SwRect aTmp( Point( nY, aInter.Top() ),
5703 0 : Size( 1, aInter.Height() ) );
5704 0 : SwTwips nX = aGrid.Top() + nGrid *
5705 0 : ( ( aInter.Top() - aGrid.Top() )/ nGrid );
5706 0 : if( nX < aInter.Top() )
5707 0 : nX += nGrid;
5708 0 : SwTwips nGridBottom = aGrid.Top() + aGrid.Height();
5709 0 : bool bLeft = aGrid.Top() >= aInter.Top();
5710 0 : bool bRight = nGridBottom <= nBottom;
5711 0 : bool bBorder = bLeft || bRight;
5712 0 : while( nY > nRight )
5713 : {
5714 0 : aTmp.Pos().X() = nY;
5715 0 : if( bGrid )
5716 : {
5717 0 : nY -= nGrid;
5718 0 : SwTwips nPosY = std::max( aInter.Left(), nY );
5719 0 : SwTwips nHeight = std::min(nRight, aTmp.Pos().X())-nPosY;
5720 0 : if( nHeight > 0 )
5721 : {
5722 0 : if( bCell )
5723 : {
5724 : SwRect aVert( Point( nPosY, nX ),
5725 0 : Size( nHeight, 1 ) );
5726 0 : while( aVert.Top() <= nBottom )
5727 : {
5728 0 : PaintBorderLine(rRect,aVert,this,pCol);
5729 0 : aVert.Pos().Y() += nGrid;
5730 : }
5731 : }
5732 0 : else if( bBorder )
5733 : {
5734 : SwRect aVert( Point( nPosY, aGrid.Top() ),
5735 0 : Size( nHeight, 1 ) );
5736 0 : if( bLeft )
5737 0 : PaintBorderLine(rRect,aVert,this,pCol);
5738 0 : if( bRight )
5739 : {
5740 0 : aVert.Pos().Y() = nGridBottom;
5741 0 : PaintBorderLine(rRect,aVert,this,pCol);
5742 : }
5743 : }
5744 : }
5745 : }
5746 : else
5747 : {
5748 0 : nY -= nRuby;
5749 0 : if( bBorder )
5750 : {
5751 0 : SwTwips nPos = std::max( aInter.Left(), nY );
5752 0 : SwTwips nW = std::min(nRight, aTmp.Pos().X()) - nPos;
5753 : SwRect aVert( Point( nPos, aGrid.Top() ),
5754 0 : Size( nW, 1 ) );
5755 0 : if( nW > 0 )
5756 : {
5757 0 : if( bLeft )
5758 0 : PaintBorderLine(rRect,aVert,this,pCol);
5759 0 : if( bRight )
5760 : {
5761 0 : aVert.Pos().Y() = nGridBottom;
5762 0 : PaintBorderLine(rRect,aVert,this,pCol);
5763 : }
5764 : }
5765 : }
5766 : }
5767 0 : bGrid = !bGrid;
5768 : }
5769 0 : while( nY >= aInter.Left() )
5770 : {
5771 0 : aTmp.Pos().X() = nY;
5772 0 : PaintBorderLine( rRect, aTmp, this, pCol);
5773 0 : if( bGrid )
5774 : {
5775 0 : nY -= nGrid;
5776 0 : SwTwips nHeight = aTmp.Pos().X()
5777 0 : - std::max(aInter.Left(), nY );
5778 0 : if( nHeight > 0 )
5779 : {
5780 0 : if( bCell )
5781 : {
5782 0 : SwRect aVert( Point(aTmp.Pos().X()-nHeight,
5783 0 : nX ), Size( nHeight, 1 ) );
5784 0 : while( aVert.Top() <= nBottom )
5785 : {
5786 0 : PaintBorderLine(rRect,aVert,this,pCol);
5787 0 : aVert.Pos().Y() += nGrid;
5788 : }
5789 : }
5790 0 : else if( bBorder )
5791 : {
5792 0 : SwRect aVert( Point(aTmp.Pos().X()-nHeight,
5793 0 : aGrid.Top() ), Size( nHeight, 1 ) );
5794 0 : if( bLeft )
5795 0 : PaintBorderLine(rRect,aVert,this,pCol);
5796 0 : if( bRight )
5797 : {
5798 0 : aVert.Pos().Y() = nGridBottom;
5799 0 : PaintBorderLine(rRect,aVert,this,pCol);
5800 : }
5801 : }
5802 : }
5803 : }
5804 : else
5805 : {
5806 0 : nY -= nRuby;
5807 0 : if( bBorder )
5808 : {
5809 0 : SwTwips nPos = std::max( aInter.Left(), nY );
5810 0 : SwTwips nW = std::min(nRight, aTmp.Pos().X()) - nPos;
5811 : SwRect aVert( Point( nPos, aGrid.Top() ),
5812 0 : Size( nW, 1 ) );
5813 0 : if( nW > 0 )
5814 : {
5815 0 : if( bLeft )
5816 0 : PaintBorderLine(rRect,aVert,this,pCol);
5817 0 : if( bRight )
5818 : {
5819 0 : aVert.Pos().Y() = nGridBottom;
5820 0 : PaintBorderLine(rRect,aVert,this,pCol);
5821 : }
5822 : }
5823 : }
5824 : }
5825 0 : bGrid = !bGrid;
5826 : }
5827 : }
5828 : else
5829 : {
5830 0 : SwTwips nOrig = aGrid.Top();
5831 0 : SwTwips nY = nOrig + nSum *( (aInter.Top()-nOrig)/nSum );
5832 : SwRect aTmp( Point( aInter.Left(), nY ),
5833 0 : Size( aInter.Width(), 1 ) );
5834 : //for textgrid refactor
5835 0 : SwTwips nX = aGrid.Left() + nGridWidth *
5836 0 : ( ( aInter.Left() - aGrid.Left() )/ nGridWidth );
5837 0 : if( nX < aInter.Left() )
5838 0 : nX += nGridWidth;
5839 0 : SwTwips nGridRight = aGrid.Left() + aGrid.Width();
5840 0 : bool bLeft = aGrid.Left() >= aInter.Left();
5841 0 : bool bRight = nGridRight <= nRight;
5842 0 : bool bBorder = bLeft || bRight;
5843 0 : while( nY < aInter.Top() )
5844 : {
5845 0 : aTmp.Pos().setY(nY);
5846 0 : if( bGrid )
5847 : {
5848 0 : nY += nGrid;
5849 0 : SwTwips nPosY = std::max( aInter.Top(), aTmp.Pos().getY() );
5850 0 : SwTwips nHeight = std::min(nBottom, nY ) - nPosY;
5851 0 : if( nHeight )
5852 : {
5853 0 : if( bCell )
5854 : {
5855 : SwRect aVert( Point( nX, nPosY ),
5856 0 : Size( 1, nHeight ) );
5857 0 : while( aVert.Left() <= nRight )
5858 : {
5859 0 : PaintBorderLine(rRect,aVert,this,pCol);
5860 0 : aVert.Pos().X() += nGridWidth; //for textgrid refactor
5861 : }
5862 : }
5863 0 : else if ( bBorder )
5864 : {
5865 : SwRect aVert( Point( aGrid.Left(), nPosY ),
5866 0 : Size( 1, nHeight ) );
5867 0 : if( bLeft )
5868 0 : PaintBorderLine(rRect,aVert,this,pCol);
5869 0 : if( bRight )
5870 : {
5871 0 : aVert.Pos().X() = nGridRight;
5872 0 : PaintBorderLine(rRect,aVert,this,pCol);
5873 : }
5874 : }
5875 : }
5876 : }
5877 : else
5878 : {
5879 0 : nY += nRuby;
5880 0 : if( bBorder )
5881 : {
5882 0 : SwTwips nPos = std::max(aInter.Top(),aTmp.Pos().getY());
5883 0 : SwTwips nH = std::min( nBottom, nY ) - nPos;
5884 : SwRect aVert( Point( aGrid.Left(), nPos ),
5885 0 : Size( 1, nH ) );
5886 0 : if( nH > 0 )
5887 : {
5888 0 : if( bLeft )
5889 0 : PaintBorderLine(rRect,aVert,this,pCol);
5890 0 : if( bRight )
5891 : {
5892 0 : aVert.Pos().setX(nGridRight);
5893 0 : PaintBorderLine(rRect,aVert,this,pCol);
5894 : }
5895 : }
5896 : }
5897 : }
5898 0 : bGrid = !bGrid;
5899 : }
5900 0 : while( nY <= nBottom )
5901 : {
5902 0 : aTmp.Pos().setY(nY);
5903 0 : PaintBorderLine( rRect, aTmp, this, pCol);
5904 0 : if( bGrid )
5905 : {
5906 0 : nY += nGrid;
5907 0 : SwTwips nHeight = std::min(nBottom, nY) - aTmp.Pos().getY();
5908 0 : if( nHeight )
5909 : {
5910 0 : if( bCell )
5911 : {
5912 0 : SwRect aVert( Point( nX, aTmp.Pos().getY() ),
5913 0 : Size( 1, nHeight ) );
5914 0 : while( aVert.Left() <= nRight )
5915 : {
5916 0 : PaintBorderLine( rRect, aVert, this, pCol);
5917 0 : aVert.Pos().setX(aVert.Pos().getX() + nGridWidth); //for textgrid refactor
5918 : }
5919 : }
5920 0 : else if( bBorder )
5921 : {
5922 : SwRect aVert( Point( aGrid.Left(),
5923 0 : aTmp.Pos().getY() ), Size( 1, nHeight ) );
5924 0 : if( bLeft )
5925 0 : PaintBorderLine(rRect,aVert,this,pCol);
5926 0 : if( bRight )
5927 : {
5928 0 : aVert.Pos().setX(nGridRight);
5929 0 : PaintBorderLine(rRect,aVert,this,pCol);
5930 : }
5931 : }
5932 : }
5933 : }
5934 : else
5935 : {
5936 0 : nY += nRuby;
5937 0 : if( bBorder )
5938 : {
5939 0 : SwTwips nPos = std::max(aInter.Top(),aTmp.Pos().Y());
5940 0 : SwTwips nH = std::min( nBottom, nY ) - nPos;
5941 : SwRect aVert( Point( aGrid.Left(), nPos ),
5942 0 : Size( 1, nH ) );
5943 0 : if( nH > 0 )
5944 : {
5945 0 : if( bLeft )
5946 0 : PaintBorderLine(rRect,aVert,this,pCol);
5947 0 : if( bRight )
5948 : {
5949 0 : aVert.Pos().setX(nGridRight);
5950 0 : PaintBorderLine(rRect,aVert,this,pCol);
5951 : }
5952 : }
5953 : }
5954 : }
5955 0 : bGrid = !bGrid;
5956 : }
5957 : }
5958 : }
5959 : }
5960 : }
5961 : }
5962 :
5963 : /**
5964 : * Paint margin area of a page
5965 : *
5966 : * OD 20.11.2002 for #104598#:
5967 : * implement paint of margin area; margin area will be painted for a
5968 : * view shell with a window and if the document is not in online layout.
5969 : *
5970 : * @param _rOutputRect
5971 : * input parameter - constant instance reference of the rectangle, for
5972 : * which an output has to be generated.
5973 : *
5974 : * @param _pViewShell
5975 : * input parameter - instance of the view shell, on which the output
5976 : * has to be generated.
5977 : */
5978 9249 : void SwPageFrm::PaintMarginArea( const SwRect& _rOutputRect,
5979 : SwViewShell* _pViewShell ) const
5980 : {
5981 9249 : if ( _pViewShell->GetWin() && !_pViewShell->GetViewOptions()->getBrowseMode() )
5982 : {
5983 : //UUUU Simplified paint with DrawingLayer FillStyle
5984 8812 : SwRect aPgRect = Frm();
5985 8812 : aPgRect._Intersection( _rOutputRect );
5986 :
5987 8812 : if(!aPgRect.IsEmpty())
5988 : {
5989 8812 : OutputDevice *pOut = _pViewShell->GetOut();
5990 :
5991 8812 : if(pOut->GetFillColor() != aGlobalRetoucheColor)
5992 : {
5993 8002 : pOut->SetFillColor(aGlobalRetoucheColor);
5994 : }
5995 :
5996 8812 : pOut->DrawRect(aPgRect.SVRect());
5997 : }
5998 : }
5999 9249 : }
6000 :
6001 : const sal_Int8 SwPageFrm::mnShadowPxWidth = 9;
6002 :
6003 51871 : bool SwPageFrm::IsRightShadowNeeded() const
6004 : {
6005 51871 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
6006 51871 : const bool bIsLTR = getRootFrm()->IsLeftToRightViewLayout();
6007 :
6008 : // We paint the right shadow if we're not in book mode
6009 : // or if we've no sibling or are the last page of the "row"
6010 51871 : return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetNext()
6011 0 : || (this == Lower()) || (bIsLTR && OnRightPage())
6012 51871 : || (!bIsLTR && !OnRightPage());
6013 :
6014 : }
6015 :
6016 51871 : bool SwPageFrm::IsLeftShadowNeeded() const
6017 : {
6018 51871 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
6019 51871 : const bool bIsLTR = getRootFrm()->IsLeftToRightViewLayout();
6020 :
6021 : // We paint the left shadow if we're not in book mode
6022 : // or if we've no sibling or are the last page of the "row"
6023 51871 : return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetPrev()
6024 0 : || (bIsLTR && !OnRightPage())
6025 51871 : || (!bIsLTR && OnRightPage());
6026 : }
6027 :
6028 : /**
6029 : * Determine rectangle for bottom page shadow
6030 : * OD 12.02.2003 for #i9719# and #105645#
6031 : */
6032 60738 : /*static*/ void SwPageFrm::GetHorizontalShadowRect( const SwRect& _rPageRect,
6033 : const SwViewShell* _pViewShell,
6034 : SwRect& _orHorizontalShadowRect,
6035 : bool bPaintLeftShadow,
6036 : bool bPaintRightShadow,
6037 : bool bRightSidebar )
6038 : {
6039 60738 : const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr();
6040 60738 : SwRect aAlignedPageRect( _rPageRect );
6041 60738 : ::SwAlignRect( aAlignedPageRect, _pViewShell );
6042 : SwRect aPagePxRect =
6043 60738 : _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
6044 :
6045 60738 : long lShadowAdjustment = mnShadowPxWidth - 1; // TODO: extract this
6046 :
6047 : _orHorizontalShadowRect.Chg(
6048 60738 : Point( aPagePxRect.Left() + (bPaintLeftShadow ? lShadowAdjustment : 0), 0 ),
6049 60738 : Size( aPagePxRect.Width() - ( (bPaintLeftShadow ? lShadowAdjustment : 0) + (bPaintRightShadow ? lShadowAdjustment : 0) ),
6050 121476 : mnShadowPxWidth ) );
6051 :
6052 60738 : if(pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
6053 : {
6054 : // Notes are displayed, we've to extend borders
6055 679 : SwTwips aSidebarTotalWidth = pMgr->GetSidebarWidth(true) + pMgr->GetSidebarBorderWidth(true);
6056 679 : if(bRightSidebar)
6057 679 : _orHorizontalShadowRect.Right( _orHorizontalShadowRect.Right() + aSidebarTotalWidth );
6058 : else
6059 0 : _orHorizontalShadowRect.Left( _orHorizontalShadowRect.Left() - aSidebarTotalWidth );
6060 : }
6061 60738 : }
6062 :
6063 : enum PaintArea {LEFT, RIGHT, TOP, BOTTOM};
6064 :
6065 : /// Wrapper around pOut->DrawBitmapEx.
6066 35604 : static void lcl_paintBitmapExToRect(vcl::RenderContext *pOut, const Point& aPoint, const Size& aSize, const BitmapEx& rBitmapEx, PaintArea eArea)
6067 : {
6068 : // The problem is that if we get called multiple times and the color is
6069 : // partly transparent, then the result will get darker and darker. To avoid
6070 : // this, always paint the background color before doing the real paint.
6071 35604 : Rectangle aRect(aPoint, aSize);
6072 :
6073 35604 : switch (eArea)
6074 : {
6075 8901 : case LEFT: aRect.Left() = aRect.Right() - 1; break;
6076 8901 : case RIGHT: aRect.Right() = aRect.Left() + 1; break;
6077 8901 : case TOP: aRect.Top() = aRect.Bottom() - 1; break;
6078 8901 : case BOTTOM: aRect.Bottom() = aRect.Top() + 1; break;
6079 : }
6080 :
6081 35604 : pOut->SetFillColor( SwViewOption::GetAppBackgroundColor());
6082 35604 : pOut->SetLineColor();
6083 35604 : pOut->DrawRect(pOut->PixelToLogic(aRect));
6084 :
6085 : pOut->DrawBitmapEx(pOut->PixelToLogic(aPoint), pOut->PixelToLogic(aSize),
6086 : Point(0, 0), aSize,
6087 35604 : rBitmapEx);
6088 35604 : }
6089 :
6090 : /**
6091 : * Paint page border and shadow
6092 : *
6093 : * OD 12.02.2003 for #i9719# and #105645#
6094 : * implement paint of page border and shadow
6095 : */
6096 8901 : /*static*/ void SwPageFrm::PaintBorderAndShadow( const SwRect& _rPageRect,
6097 : const SwViewShell* _pViewShell,
6098 : bool bPaintLeftShadow,
6099 : bool bPaintRightShadow,
6100 : bool bRightSidebar )
6101 : {
6102 : // No shadow in prefs
6103 8901 : if (!SwViewOption::IsShadow())
6104 8901 : return;
6105 :
6106 : // #i16816# tagged pdf support
6107 8901 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *_pViewShell->GetOut() );
6108 :
6109 : static vcl::DeleteOnDeinit< drawinglayer::primitive2d::DiscreteShadow > shadowMaskObj
6110 8901 : ( new drawinglayer::primitive2d::DiscreteShadow( SW_RES( BMP_PAGE_SHADOW_MASK ) ));
6111 8901 : static drawinglayer::primitive2d::DiscreteShadow& shadowMask = *shadowMaskObj.get();
6112 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageTopRightShadowObj( new BitmapEx );
6113 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageBottomRightShadowObj( new BitmapEx );
6114 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageBottomLeftShadowObj( new BitmapEx );
6115 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageBottomShadowBaseObj( new BitmapEx );
6116 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageRightShadowBaseObj( new BitmapEx );
6117 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageTopShadowBaseObj( new BitmapEx );
6118 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageTopLeftShadowObj( new BitmapEx );
6119 8901 : static vcl::DeleteOnDeinit< BitmapEx > aPageLeftShadowBaseObj( new BitmapEx );
6120 8901 : static BitmapEx& aPageTopRightShadow = *aPageTopRightShadowObj.get();
6121 8901 : static BitmapEx& aPageBottomRightShadow = *aPageBottomRightShadowObj.get();
6122 8901 : static BitmapEx& aPageBottomLeftShadow = *aPageBottomLeftShadowObj.get();
6123 8901 : static BitmapEx& aPageBottomShadow = *aPageBottomShadowBaseObj.get();
6124 8901 : static BitmapEx& aPageRightShadow = *aPageRightShadowBaseObj.get();
6125 8901 : static BitmapEx& aPageTopShadow = *aPageTopShadowBaseObj.get();
6126 8901 : static BitmapEx& aPageTopLeftShadow = *aPageTopLeftShadowObj.get();
6127 8901 : static BitmapEx& aPageLeftShadow = *aPageLeftShadowBaseObj.get();
6128 8901 : static Color aShadowColor( COL_AUTO );
6129 :
6130 8901 : SwRect aAlignedPageRect( _rPageRect );
6131 8901 : ::SwAlignRect( aAlignedPageRect, _pViewShell );
6132 8901 : SwRect aPagePxRect = _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
6133 :
6134 8901 : if (aShadowColor != SwViewOption::GetShadowColor())
6135 : {
6136 50 : aShadowColor = SwViewOption::GetShadowColor();
6137 :
6138 50 : AlphaMask aMask( shadowMask.getBottomRight().GetBitmap() );
6139 100 : Bitmap aFilledSquare( aMask.GetSizePixel(), 24 );
6140 50 : aFilledSquare.Erase( aShadowColor );
6141 50 : aPageBottomRightShadow = BitmapEx( aFilledSquare, aMask );
6142 :
6143 50 : aMask = AlphaMask( shadowMask.getBottomLeft().GetBitmap() );
6144 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6145 50 : aFilledSquare.Erase( aShadowColor );
6146 50 : aPageBottomLeftShadow = BitmapEx( aFilledSquare, aMask );
6147 :
6148 50 : aMask = AlphaMask( shadowMask.getBottom().GetBitmap() );
6149 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6150 50 : aFilledSquare.Erase( aShadowColor );
6151 50 : aPageBottomShadow = BitmapEx( aFilledSquare, aMask );
6152 :
6153 50 : aMask = AlphaMask( shadowMask.getTop().GetBitmap() );
6154 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6155 50 : aFilledSquare.Erase( aShadowColor );
6156 50 : aPageTopShadow = BitmapEx( aFilledSquare, aMask );
6157 :
6158 50 : aMask = AlphaMask( shadowMask.getTopRight().GetBitmap() );
6159 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6160 50 : aFilledSquare.Erase( aShadowColor );
6161 50 : aPageTopRightShadow = BitmapEx( aFilledSquare, aMask );
6162 :
6163 50 : aMask = AlphaMask( shadowMask.getRight().GetBitmap() );
6164 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6165 50 : aFilledSquare.Erase( aShadowColor );
6166 50 : aPageRightShadow = BitmapEx( aFilledSquare, aMask );
6167 :
6168 50 : aMask = AlphaMask( shadowMask.getTopLeft().GetBitmap() );
6169 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6170 50 : aFilledSquare.Erase( aShadowColor );
6171 50 : aPageTopLeftShadow = BitmapEx( aFilledSquare, aMask );
6172 :
6173 50 : aMask = AlphaMask( shadowMask.getLeft().GetBitmap() );
6174 50 : aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
6175 50 : aFilledSquare.Erase( aShadowColor );
6176 100 : aPageLeftShadow = BitmapEx( aFilledSquare, aMask );
6177 : }
6178 :
6179 8901 : SwRect aPaintRect;
6180 8901 : OutputDevice *pOut = _pViewShell->GetOut();
6181 :
6182 8901 : SwPageFrm::GetHorizontalShadowRect( _rPageRect, _pViewShell, aPaintRect, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
6183 :
6184 : // Right shadow & corners
6185 8901 : if ( bPaintRightShadow )
6186 : {
6187 17802 : pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right(), aPagePxRect.Bottom() + 1 - (aPageBottomRightShadow.GetSizePixel().Height() - mnShadowPxWidth) ) ),
6188 17802 : aPageBottomRightShadow );
6189 17802 : pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right(), aPagePxRect.Top() - mnShadowPxWidth ) ),
6190 17802 : aPageTopRightShadow );
6191 :
6192 8901 : if (aPagePxRect.Height() > 2 * mnShadowPxWidth)
6193 : {
6194 8901 : const long nWidth = aPageRightShadow.GetSizePixel().Width();
6195 8901 : const long nHeight = aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1);
6196 8901 : if (aPageRightShadow.GetSizePixel().Height() < nHeight)
6197 72 : aPageRightShadow.Scale(Size(nWidth, nHeight), BmpScaleFlag::Fast);
6198 :
6199 : lcl_paintBitmapExToRect(pOut,
6200 17802 : Point(aPaintRect.Right() + mnShadowPxWidth, aPagePxRect.Top() + mnShadowPxWidth - 1),
6201 : Size(nWidth, nHeight),
6202 26703 : aPageRightShadow, RIGHT);
6203 : }
6204 : }
6205 :
6206 : // Left shadows and corners
6207 8901 : if(bPaintLeftShadow)
6208 : {
6209 8901 : const long lLeft = aPaintRect.Left() - aPageBottomLeftShadow.GetSizePixel().Width();
6210 : pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft,
6211 8901 : aPagePxRect.Bottom() + 1 + mnShadowPxWidth - aPageBottomLeftShadow.GetSizePixel().Height() ) ), aPageBottomLeftShadow );
6212 8901 : pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, aPagePxRect.Top() - mnShadowPxWidth ) ), aPageTopLeftShadow );
6213 8901 : if (aPagePxRect.Height() > 2 * mnShadowPxWidth)
6214 : {
6215 8901 : const long nWidth = aPageLeftShadow.GetSizePixel().Width();
6216 8901 : const long nHeight = aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1);
6217 8901 : if (aPageLeftShadow.GetSizePixel().Height() < nHeight)
6218 72 : aPageLeftShadow.Scale(Size(nWidth, nHeight), BmpScaleFlag::Fast);
6219 :
6220 : lcl_paintBitmapExToRect(pOut,
6221 8901 : Point(lLeft, aPagePxRect.Top() + mnShadowPxWidth - 1),
6222 : Size(nWidth, nHeight),
6223 17802 : aPageLeftShadow, LEFT);
6224 : }
6225 : }
6226 :
6227 : // Bottom shadow
6228 8901 : const long nBottomHeight = aPageBottomShadow.GetSizePixel().Height();
6229 8901 : if (aPageBottomShadow.GetSizePixel().Width() < aPaintRect.Width())
6230 70 : aPageBottomShadow.Scale(Size(aPaintRect.Width(), nBottomHeight), BmpScaleFlag::Fast);
6231 :
6232 : lcl_paintBitmapExToRect(pOut,
6233 8901 : Point(aPaintRect.Left(), aPagePxRect.Bottom() + 2),
6234 : Size(aPaintRect.Width(), nBottomHeight),
6235 17802 : aPageBottomShadow, BOTTOM);
6236 :
6237 : // Top shadow
6238 8901 : const long nTopHeight = aPageTopShadow.GetSizePixel().Height();
6239 8901 : if (aPageTopShadow.GetSizePixel().Width() < aPaintRect.Width())
6240 70 : aPageTopShadow.Scale(Size(aPaintRect.Width(), nTopHeight), BmpScaleFlag::Fast);
6241 :
6242 : lcl_paintBitmapExToRect(pOut,
6243 8901 : Point(aPaintRect.Left(), aPagePxRect.Top() - mnShadowPxWidth),
6244 : Size(aPaintRect.Width(), nTopHeight),
6245 17802 : aPageTopShadow, TOP);
6246 : }
6247 :
6248 : /**
6249 : * mod #i6193# paint sidebar for notes
6250 : * IMPORTANT: if you change the rects here, also change SwPostItMgr::ScrollbarHit
6251 : */
6252 8901 : /*static*/void SwPageFrm::PaintNotesSidebar(const SwRect& _rPageRect, SwViewShell* _pViewShell, sal_uInt16 nPageNum, bool bRight)
6253 : {
6254 : //TODO: cut out scrollbar area and arrows out of sidepane rect, otherwise it could flicker when pressing arrow buttons
6255 8901 : if (!_pViewShell )
6256 8901 : return;
6257 :
6258 8901 : SwRect aPageRect( _rPageRect );
6259 8901 : SwAlignRect( aPageRect, _pViewShell );
6260 :
6261 8901 : const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr();
6262 8901 : if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes()) // do not show anything in print preview
6263 : {
6264 11 : sal_Int32 nScrollerHeight = pMgr->GetSidebarScrollerHeight();
6265 11 : const Rectangle &aVisRect = _pViewShell->VisArea().SVRect();
6266 : //draw border and sidepane
6267 11 : _pViewShell->GetOut()->SetLineColor();
6268 11 : if (!bRight)
6269 : {
6270 0 : _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
6271 0 : _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()))) ;
6272 0 : if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
6273 0 : _pViewShell->GetOut()->SetFillColor(COL_BLACK);
6274 : else
6275 0 : _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
6276 0 : _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarWidth()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()))) ;
6277 : }
6278 : else
6279 : {
6280 11 : _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
6281 11 : SwRect aSidebarBorder(aPageRect.TopRight(),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()));
6282 11 : _pViewShell->GetOut()->DrawRect(aSidebarBorder.SVRect());
6283 11 : if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
6284 0 : _pViewShell->GetOut()->SetFillColor(COL_BLACK);
6285 : else
6286 11 : _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
6287 11 : SwRect aSidebar(Point(aPageRect.Right()+pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()));
6288 11 : _pViewShell->GetOut()->DrawRect(aSidebar.SVRect());
6289 : }
6290 11 : if (pMgr->ShowScrollbar(nPageNum))
6291 : {
6292 : // draw scrollbar area and arrows
6293 0 : Point aPointBottom;
6294 0 : Point aPointTop;
6295 0 : 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()) :
6296 0 : Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height());
6297 0 : aPointTop = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height()) :
6298 0 : Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height());
6299 0 : Size aSize(pMgr->GetSidebarWidth() - _pViewShell->GetOut()->PixelToLogic(Size(4,0)).Width(), _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()) ;
6300 0 : Rectangle aRectBottom(aPointBottom,aSize);
6301 0 : Rectangle aRectTop(aPointTop,aSize);
6302 :
6303 0 : if (aRectBottom.IsOver(aVisRect))
6304 : {
6305 :
6306 0 : if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
6307 : {
6308 0 : _pViewShell->GetOut()->SetLineColor(COL_WHITE);
6309 0 : _pViewShell->GetOut()->SetFillColor(COL_BLACK);
6310 : }
6311 : else
6312 : {
6313 0 : _pViewShell->GetOut()->SetLineColor(COL_BLACK);
6314 0 : _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
6315 : }
6316 0 : _pViewShell->GetOut()->DrawRect(aRectBottom);
6317 0 : _pViewShell->GetOut()->DrawLine(aPointBottom + Point(pMgr->GetSidebarWidth()/3,0), aPointBottom + Point(pMgr->GetSidebarWidth()/3 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
6318 :
6319 0 : _pViewShell->GetOut()->SetLineColor();
6320 0 : Point aMiddleFirst(aPointBottom + Point(pMgr->GetSidebarWidth()/6,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
6321 0 : Point aMiddleSecond(aPointBottom + Point(pMgr->GetSidebarWidth()/3*2,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
6322 0 : PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell,pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
6323 : }
6324 0 : if (aRectTop.IsOver(aVisRect))
6325 : {
6326 0 : if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
6327 : {
6328 0 : _pViewShell->GetOut()->SetLineColor(COL_WHITE);
6329 0 : _pViewShell->GetOut()->SetFillColor(COL_BLACK);
6330 : }
6331 : else
6332 : {
6333 0 : _pViewShell->GetOut()->SetLineColor(COL_BLACK);
6334 0 : _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
6335 : }
6336 0 : _pViewShell->GetOut()->DrawRect(aRectTop);
6337 0 : _pViewShell->GetOut()->DrawLine(aPointTop + Point(pMgr->GetSidebarWidth()/3*2,0), aPointTop + Point(pMgr->GetSidebarWidth()/3*2 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
6338 :
6339 0 : _pViewShell->GetOut()->SetLineColor();
6340 0 : Point aMiddleFirst(aPointTop + Point(pMgr->GetSidebarWidth()/3,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
6341 0 : Point aMiddleSecond(aPointTop + Point(pMgr->GetSidebarWidth()/6*5,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
6342 0 : PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell, pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
6343 : }
6344 : }
6345 : }
6346 : }
6347 :
6348 0 : /*static*/ void SwPageFrm::PaintNotesSidebarArrows(const Point &aMiddleFirst, const Point &aMiddleSecond, SwViewShell* _pViewShell, const Color& rColorUp, const Color& rColorDown)
6349 : {
6350 0 : Polygon aTriangleUp(3);
6351 0 : Polygon aTriangleDown(3);
6352 :
6353 0 : aTriangleUp.SetPoint(aMiddleFirst + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
6354 0 : aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),1);
6355 0 : aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
6356 :
6357 0 : aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
6358 0 : aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(+3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),1);
6359 0 : aTriangleDown.SetPoint(aMiddleSecond + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
6360 :
6361 0 : _pViewShell->GetOut()->SetFillColor(rColorUp);
6362 0 : _pViewShell->GetOut()->DrawPolygon(aTriangleUp);
6363 0 : _pViewShell->GetOut()->SetFillColor(rColorDown);
6364 0 : _pViewShell->GetOut()->DrawPolygon(aTriangleDown);
6365 0 : }
6366 :
6367 : /**
6368 : * Get bound rectangle of border and shadow for repaints
6369 : *
6370 : * OD 12.02.2003 for #i9719# and #105645#
6371 : */
6372 51837 : /*static*/ void SwPageFrm::GetBorderAndShadowBoundRect( const SwRect& _rPageRect,
6373 : const SwViewShell* _pViewShell,
6374 : SwRect& _orBorderAndShadowBoundRect,
6375 : bool bLeftShadow,
6376 : bool bRightShadow,
6377 : bool bRightSidebar
6378 : )
6379 : {
6380 51837 : SwRect aAlignedPageRect( _rPageRect );
6381 51837 : ::SwAlignRect( aAlignedPageRect, _pViewShell );
6382 : SwRect aPagePxRect =
6383 51837 : _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
6384 51837 : aPagePxRect.Bottom( aPagePxRect.Bottom() + mnShadowPxWidth + 1 );
6385 51837 : aPagePxRect.Top( aPagePxRect.Top() - mnShadowPxWidth - 1 );
6386 :
6387 51837 : SwRect aTmpRect;
6388 :
6389 : // Always ask for full shadow since we want a bounding rect
6390 : // including at least the page frame
6391 51837 : SwPageFrm::GetHorizontalShadowRect( _rPageRect, _pViewShell, aTmpRect, false, false, bRightSidebar );
6392 :
6393 51837 : if(bLeftShadow) aPagePxRect.Left( aTmpRect.Left() - mnShadowPxWidth - 1);
6394 51837 : if(bRightShadow) aPagePxRect.Right( aTmpRect.Right() + mnShadowPxWidth + 1);
6395 :
6396 51837 : _orBorderAndShadowBoundRect = _pViewShell->GetOut()->PixelToLogic( aPagePxRect.SVRect() );
6397 51837 : }
6398 :
6399 39802 : SwRect SwPageFrm::GetBoundRect() const
6400 : {
6401 39802 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
6402 39802 : SwRect aPageRect( Frm() );
6403 39802 : SwRect aResult;
6404 :
6405 39802 : if(!pSh) {
6406 0 : return SwRect( Point(0, 0), Size(0, 0) );
6407 : }
6408 :
6409 : SwPageFrm::GetBorderAndShadowBoundRect( aPageRect, pSh, aResult,
6410 39802 : IsLeftShadowNeeded(), IsRightShadowNeeded(), SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT );
6411 39802 : return aResult;
6412 : }
6413 :
6414 13926 : /*static*/ SwTwips SwPageFrm::GetSidebarBorderWidth( const SwViewShell* _pViewShell )
6415 : {
6416 13926 : const SwPostItMgr* pPostItMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
6417 13926 : const SwTwips nRet = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
6418 13926 : return nRet;
6419 : }
6420 :
6421 10065 : void SwFrm::PaintBaBo( const SwRect& rRect, const SwPageFrm *pPage,
6422 : const bool bLowerBorder, const bool bOnlyTextBackground ) const
6423 : {
6424 10065 : if ( !pPage )
6425 0 : pPage = FindPageFrm();
6426 :
6427 10065 : OutputDevice *pOut = gProp.pSGlobalShell->GetOut();
6428 :
6429 : // #i16816# tagged pdf support
6430 10065 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
6431 :
6432 : // OD 2004-04-23 #116347#
6433 10065 : pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
6434 10065 : pOut->SetLineColor();
6435 :
6436 20130 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
6437 10065 : const SwBorderAttrs &rAttrs = *aAccess.Get();
6438 :
6439 : // OD 20.11.2002 #104598# - take care of page margin area
6440 : // Note: code move from <SwFrm::PaintBackground(..)> to new method
6441 : // <SwPageFrm::Paintmargin(..)>.
6442 10065 : if ( IsPageFrm() && !bOnlyTextBackground)
6443 : {
6444 9249 : static_cast<const SwPageFrm*>(this)->PaintMarginArea( rRect, gProp.pSGlobalShell );
6445 : }
6446 :
6447 : // paint background
6448 : {
6449 10065 : PaintBackground( rRect, pPage, rAttrs, false, bLowerBorder, bOnlyTextBackground );
6450 : }
6451 :
6452 : // OD 06.08.2002 #99657# - paint border before painting background
6453 : // paint grid for page frame and paint border
6454 10065 : if (!bOnlyTextBackground)
6455 : {
6456 9286 : SwRect aRect( rRect );
6457 9286 : if( IsPageFrm() )
6458 9249 : static_cast<const SwPageFrm*>(this)->PaintGrid( pOut, aRect );
6459 9286 : PaintBorder( aRect, pPage, rAttrs );
6460 : }
6461 :
6462 20130 : pOut->Pop();
6463 10065 : }
6464 :
6465 106 : static bool lcl_compareFillAttributes(const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& pA, const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& pB)
6466 : {
6467 106 : if (pA == pB)
6468 0 : return true;
6469 106 : if (!pA || !pB)
6470 0 : return false;
6471 106 : return pA->getFillAttribute() == pB->getFillAttribute();
6472 : }
6473 :
6474 : /// OD 05.09.2002 #102912#
6475 : /// Do not paint background for fly frames without a background brush by
6476 : /// calling <PaintBaBo> at the page or at the fly frame its anchored
6477 51133 : void SwFrm::PaintBackground( const SwRect &rRect, const SwPageFrm *pPage,
6478 : const SwBorderAttrs & rAttrs,
6479 : const bool bLowerMode,
6480 : const bool bLowerBorder,
6481 : const bool bOnlyTextBackground ) const
6482 : {
6483 : // OD 20.01.2003 #i1837# - no paint of table background, if corresponding
6484 : // option is *not* set.
6485 51819 : if( IsTabFrm() &&
6486 686 : !gProp.pSGlobalShell->GetViewOptions()->IsTable() )
6487 : {
6488 23 : return;
6489 : }
6490 :
6491 : // nothing to do for covered table cells:
6492 51133 : if( IsCellFrm() && IsCoveredCell() )
6493 23 : return;
6494 :
6495 51110 : SwViewShell *pSh = gProp.pSGlobalShell;
6496 :
6497 : // #i16816# tagged pdf support
6498 51110 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
6499 :
6500 : const SvxBrushItem* pItem;
6501 : // OD 05.09.2002 #102912#
6502 : // temporary background brush for a fly frame without a background brush
6503 51110 : SvxBrushItem* pTmpBackBrush = 0;
6504 : const Color* pCol;
6505 51110 : SwRect aOrigBackRect;
6506 51110 : const bool bPageFrm = IsPageFrm();
6507 51110 : bool bLowMode = true;
6508 :
6509 : //UUUU
6510 102220 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
6511 :
6512 51110 : bool bBack = GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, bLowerMode );
6513 : //- Output if a separate background is used.
6514 51110 : bool bNoFlyBackground = !gProp.bSFlyMetafile && !bBack && IsFlyFrm();
6515 51110 : if ( bNoFlyBackground )
6516 : {
6517 : // OD 05.09.2002 #102912# - Fly frame has no background.
6518 : // Try to find background brush at parents, if previous call of
6519 : // <GetBackgroundBrush> disabled this option with the parameter <bLowerMode>
6520 172 : if ( bLowerMode )
6521 : {
6522 0 : bBack = GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false );
6523 : }
6524 : // If still no background found for the fly frame, initialize the
6525 : // background brush <pItem> with global retouche color and set <bBack>
6526 : // to true, that fly frame will paint its background using this color.
6527 172 : if ( !bBack )
6528 : {
6529 : // OD 10.01.2003 #i6467# - on print output, pdf output and
6530 : // in embedded mode not editing color COL_WHITE is used instead of
6531 : // the global retouche color.
6532 516 : if ( pSh->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
6533 344 : pSh->GetViewOptions()->IsPDFExport() ||
6534 172 : ( pSh->GetDoc()->GetDocShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
6535 0 : !pSh->GetDoc()->GetDocShell()->IsInPlaceActive()
6536 : )
6537 : )
6538 : {
6539 0 : pTmpBackBrush = new SvxBrushItem( Color( COL_WHITE ), RES_BACKGROUND );
6540 :
6541 : //UUU
6542 0 : aFillAttributes.reset(new drawinglayer::attribute::SdrAllFillAttributesHelper(Color( COL_WHITE )));
6543 : }
6544 : else
6545 : {
6546 172 : pTmpBackBrush = new SvxBrushItem( aGlobalRetoucheColor, RES_BACKGROUND);
6547 :
6548 : //UUU
6549 172 : aFillAttributes.reset(new drawinglayer::attribute::SdrAllFillAttributesHelper(aGlobalRetoucheColor));
6550 : }
6551 :
6552 172 : pItem = pTmpBackBrush;
6553 172 : bBack = true;
6554 : }
6555 : }
6556 :
6557 51110 : SwRect aPaintRect( Frm() );
6558 51110 : if( IsTextFrm() || IsSctFrm() )
6559 21185 : aPaintRect = UnionFrm( true );
6560 :
6561 51110 : if ( aPaintRect.IsOver( rRect ) )
6562 : {
6563 50277 : if ( bBack || bPageFrm || !bLowerMode )
6564 : {
6565 12108 : const bool bBrowse = pSh->GetViewOptions()->getBrowseMode();
6566 12108 : SwRect aRect;
6567 24217 : if ( (bPageFrm && bBrowse) ||
6568 12150 : (IsTextFrm() && Prt().SSize() == Frm().SSize()) )
6569 : {
6570 90 : aRect = Frm();
6571 90 : ::SwAlignRect( aRect, gProp.pSGlobalShell );
6572 : }
6573 : else
6574 : {
6575 12018 : ::lcl_CalcBorderRect( aRect, this, rAttrs, false, gProp);
6576 12018 : if ( (IsTextFrm() || IsTabFrm()) && GetPrev() )
6577 : {
6578 542 : if ( GetPrev()->GetAttrSet()->GetBackground() == GetAttrSet()->GetBackground() &&
6579 534 : lcl_compareFillAttributes(GetPrev()->getSdrAllFillAttributesHelper(), getSdrAllFillAttributesHelper()))
6580 : {
6581 84 : aRect.Top( Frm().Top() );
6582 : }
6583 : }
6584 : }
6585 12108 : aRect.Intersection( rRect );
6586 :
6587 12108 : OutputDevice *pOut = pSh->GetOut();
6588 :
6589 12108 : if ( aRect.HasArea() )
6590 : {
6591 12040 : SvxBrushItem* pNewItem = 0;
6592 :
6593 12040 : if( pCol )
6594 : {
6595 38 : pNewItem = new SvxBrushItem( *pCol, RES_BACKGROUND );
6596 38 : pItem = pNewItem;
6597 :
6598 : //UUUU
6599 38 : aFillAttributes.reset(new drawinglayer::attribute::SdrAllFillAttributesHelper(*pCol));
6600 : }
6601 :
6602 12040 : SwRegionRects aRegion( aRect );
6603 12962 : if (pPage->GetSortedObjs() &&
6604 922 : pSh->GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS))
6605 : {
6606 362 : ::lcl_SubtractFlys( this, pPage, aRect, aRegion, gProp );
6607 : }
6608 :
6609 : // OD 06.08.2002 #99657# - determine, if background transparency
6610 : // have to be considered for drawing.
6611 : // --> Status Quo: background transparency have to be
6612 : // considered for fly frames
6613 12040 : const bool bConsiderBackgroundTransparency = IsFlyFrm();
6614 12040 : bool bDone(false);
6615 :
6616 : // #i125189# We are also done when the new DrawingLayer FillAttributes are used
6617 : // or the FillStyle is set (different from drawing::FillStyle_NONE)
6618 12040 : if(pOut && aFillAttributes.get())
6619 : {
6620 10414 : if(aFillAttributes->isUsed())
6621 : {
6622 : // check if really something is painted
6623 474 : bDone = DrawFillAttributes(aFillAttributes, aOrigBackRect, aRegion, *pOut);
6624 : }
6625 :
6626 10414 : if(!bDone)
6627 : {
6628 : // if not, still a FillStyle could be set but the transparency is at 100%,
6629 : // thus need to check the model data itself for FillStyle (do not rely on
6630 : // SdrAllFillAttributesHelper since it already contains optimized information,
6631 : // e.g. transparency leads to no fill)
6632 9943 : const drawing::FillStyle eFillStyle(static_cast< const XFillStyleItem& >(GetAttrSet()->Get(XATTR_FILLSTYLE)).GetValue());
6633 :
6634 9943 : if(drawing::FillStyle_NONE != eFillStyle)
6635 : {
6636 0 : bDone = true;
6637 : }
6638 : }
6639 : }
6640 :
6641 12040 : if(!bDone)
6642 : {
6643 23231 : for (size_t i = 0; i < aRegion.size(); ++i)
6644 : {
6645 11662 : if (1 < aRegion.size())
6646 : {
6647 114 : ::SwAlignRect( aRegion[i], gProp.pSGlobalShell );
6648 114 : if( !aRegion[i].HasArea() )
6649 0 : continue;
6650 : }
6651 : // OD 06.08.2002 #99657# - add 6th parameter to indicate, if
6652 : // background transparency have to be considered
6653 : // Set missing 5th parameter to the default value GRFNUM_NO
6654 : // - see declaration in /core/inc/frmtool.hxx.
6655 11662 : if (IsTextFrm() || !bOnlyTextBackground)
6656 : ::DrawGraphic(
6657 : pItem,
6658 : pOut,
6659 : aOrigBackRect,
6660 10886 : aRegion[i],
6661 : GRFNUM_NO,
6662 21772 : bConsiderBackgroundTransparency );
6663 : }
6664 : }
6665 12040 : if( pCol )
6666 38 : delete pNewItem;
6667 12108 : }
6668 : }
6669 : else
6670 38169 : bLowMode = bLowerMode;
6671 : }
6672 :
6673 : // OD 05.09.2002 #102912#
6674 : // delete temporary background brush.
6675 51110 : delete pTmpBackBrush;
6676 :
6677 : //Now process lower and his neighbour.
6678 : //We end this as soon as a Frm leaves the chain and therefore is not a lower
6679 : //of me anymore
6680 51110 : const SwFrm *pFrm = GetLower();
6681 51110 : if ( pFrm )
6682 : {
6683 30065 : SwRect aFrmRect;
6684 30065 : SwRect aRect( PaintArea() );
6685 30065 : aRect._Intersection( rRect );
6686 30065 : SwRect aBorderRect( aRect );
6687 30065 : SwShortCut aShortCut( *pFrm, aBorderRect );
6688 47655 : do
6689 47655 : { if ( gProp.pSProgress )
6690 0 : gProp.pSProgress->Reschedule();
6691 :
6692 47655 : aFrmRect = pFrm->PaintArea();
6693 47655 : if ( aFrmRect.IsOver( aBorderRect ) )
6694 : {
6695 40763 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
6696 40763 : const SwBorderAttrs &rTmpAttrs = *aAccess.Get();
6697 61783 : if ( ( pFrm->IsLayoutFrm() && bLowerBorder ) ||
6698 21020 : aFrmRect.IsOver( aRect ) )
6699 : pFrm->PaintBackground( aRect, pPage, rTmpAttrs, bLowMode,
6700 40763 : bLowerBorder );
6701 40763 : if ( bLowerBorder )
6702 40763 : pFrm->PaintBorder( aBorderRect, pPage, rTmpAttrs );
6703 : }
6704 47655 : pFrm = pFrm->GetNext();
6705 65787 : } while ( pFrm && pFrm->GetUpper() == this &&
6706 18132 : !aShortCut.Stop( aFrmRect ) );
6707 51110 : }
6708 : }
6709 :
6710 : /// Refreshes all subsidiary lines of a page.
6711 8938 : void SwPageFrm::RefreshSubsidiary( const SwRect &rRect ) const
6712 : {
6713 8938 : if ( IS_SUBS || isTableBoundariesEnabled() || IS_SUBS_SECTION || IS_SUBS_FLYS )
6714 : {
6715 8933 : SwRect aRect( rRect );
6716 8933 : if ( aRect.HasArea() )
6717 : {
6718 : //During paint using the root, the array is controlled from there.
6719 : //Otherwise we'll handle it for our self.
6720 8933 : bool bDelSubs = false;
6721 8933 : if ( !gProp.pSSubsLines )
6722 : {
6723 3 : gProp.pSSubsLines = new SwSubsRects;
6724 : // OD 20.12.2002 #106318# - create container for special subsidiary lines
6725 3 : gProp.pSSpecSubsLines = new SwSubsRects;
6726 3 : bDelSubs = true;
6727 : }
6728 :
6729 8933 : RefreshLaySubsidiary( this, aRect );
6730 :
6731 8933 : if ( bDelSubs )
6732 : {
6733 : // OD 20.12.2002 #106318# - paint special subsidiary lines
6734 : // and delete its container
6735 3 : gProp.pSSpecSubsLines->PaintSubsidiary( gProp.pSGlobalShell->GetOut(), NULL, gProp );
6736 3 : DELETEZ( gProp.pSSpecSubsLines );
6737 :
6738 3 : gProp.pSSubsLines->PaintSubsidiary( gProp.pSGlobalShell->GetOut(), gProp.pSLines, gProp );
6739 3 : DELETEZ( gProp.pSSubsLines );
6740 : }
6741 : }
6742 : }
6743 8938 : }
6744 :
6745 25227 : void SwLayoutFrm::RefreshLaySubsidiary( const SwPageFrm *pPage,
6746 : const SwRect &rRect ) const
6747 : {
6748 25227 : const bool bSubsOpt = IS_SUBS;
6749 25227 : if ( bSubsOpt )
6750 25167 : PaintSubsidiaryLines( pPage, rRect );
6751 :
6752 25227 : const SwFrm *pLow = Lower();
6753 25227 : if( !pLow )
6754 25238 : return;
6755 25216 : SwShortCut aShortCut( *pLow, rRect );
6756 87551 : while( pLow && !aShortCut.Stop( pLow->Frm() ) )
6757 : {
6758 37119 : if ( pLow->Frm().IsOver( rRect ) && pLow->Frm().HasArea() )
6759 : {
6760 33080 : if ( pLow->IsLayoutFrm() )
6761 15837 : static_cast<const SwLayoutFrm*>(pLow)->RefreshLaySubsidiary( pPage, rRect);
6762 17243 : else if ( pLow->GetDrawObjs() )
6763 : {
6764 4153 : const SwSortedObjs& rObjs = *(pLow->GetDrawObjs());
6765 12530 : for ( size_t i = 0; i < rObjs.size(); ++i )
6766 : {
6767 8377 : const SwAnchoredObject* pAnchoredObj = rObjs[i];
6768 25131 : if ( pPage->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId(
6769 41885 : pAnchoredObj->GetDrawObj()->GetLayer() ) &&
6770 8377 : pAnchoredObj->ISA(SwFlyFrm) )
6771 : {
6772 : const SwFlyFrm *pFly =
6773 428 : static_cast<const SwFlyFrm*>(pAnchoredObj);
6774 428 : if ( pFly->IsFlyInCntFrm() && pFly->Frm().IsOver( rRect ) )
6775 : {
6776 190 : if ( !pFly->Lower() || !pFly->Lower()->IsNoTextFrm() ||
6777 84 : !static_cast<const SwNoTextFrm*>(pFly->Lower())->HasAnimation())
6778 106 : pFly->RefreshLaySubsidiary( pPage, rRect );
6779 : }
6780 : }
6781 : }
6782 : }
6783 : }
6784 37119 : pLow = pLow->GetNext();
6785 : }
6786 : }
6787 :
6788 : /**
6789 : * Subsidiary lines to paint the PrtAreas
6790 : * Only the LayoutFrms which directly contain Content
6791 : * Paints the desired line and pays attention to not overpaint any flys
6792 : */
6793 1313 : static void lcl_RefreshLine( const SwLayoutFrm *pLay,
6794 : const SwPageFrm *pPage,
6795 : const Point &rP1,
6796 : const Point &rP2,
6797 : const sal_uInt8 nSubColor,
6798 : SwLineRects* pSubsLines )
6799 : {
6800 : //In which direction do we loop? Can only be horizontal or vertical.
6801 : OSL_ENSURE( ((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y())),
6802 : "Sloped subsidiary lines are not allowed." );
6803 :
6804 1313 : const bool bHori = rP1.Y() == rP2.Y();
6805 :
6806 : // use pointers to member function in order to unify flow
6807 : typedef long& (Point:: *pmfPt)();
6808 1313 : const pmfPt pmfPtX = &Point::X;
6809 1313 : const pmfPt pmfPtY = &Point::Y;
6810 1313 : const pmfPt pDirPt = bHori ? pmfPtX : pmfPtY;
6811 :
6812 1313 : Point aP1( rP1 );
6813 1313 : Point aP2( rP2 );
6814 :
6815 3932 : while ( (aP1.*pDirPt)() < (aP2.*pDirPt)() )
6816 : {
6817 : //If the starting point lies in a fly, it is directly set behind the
6818 : //fly.
6819 : //The end point moves to the start if the end point lies in a fly or we
6820 : //have a fly between starting point and end point.
6821 : // In this way, every position is output one by one.
6822 :
6823 : //If I'm a fly I'll only avoid those flys which are places 'above' me;
6824 : //this means those who are behind me in the array.
6825 : //Even if I'm inside a fly or inside a fly inside a fly a.s.o I won't
6826 : //avoid any of those flys.
6827 1306 : SwOrderIter aIter( pPage );
6828 1306 : const SwFlyFrm *pMyFly = pLay->FindFlyFrm();
6829 1306 : if ( pMyFly )
6830 : {
6831 1234 : aIter.Current( pMyFly->GetVirtDrawObj() );
6832 2516 : while ( 0 != (pMyFly = pMyFly->GetAnchorFrm()->FindFlyFrm()) )
6833 : {
6834 48 : if ( aIter()->GetOrdNum() > pMyFly->GetVirtDrawObj()->GetOrdNum() )
6835 48 : aIter.Current( pMyFly->GetVirtDrawObj() );
6836 : }
6837 : }
6838 : else
6839 72 : aIter.Bottom();
6840 :
6841 9436 : while ( aIter() )
6842 : {
6843 6824 : const SwVirtFlyDrawObj *pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
6844 6824 : const SwFlyFrm *pFly = pObj ? pObj->GetFlyFrm() : 0;
6845 :
6846 : //I certainly won't avoid myself, even if I'm placed _inside_ the
6847 : //fly I won't avoid it.
6848 6824 : if ( !pFly || (pFly == pLay || pFly->IsAnLower( pLay )) )
6849 : {
6850 1234 : aIter.Next();
6851 6260 : continue;
6852 : }
6853 :
6854 : // OD 19.12.2002 #106318# - do *not* consider fly frames with
6855 : // a transparent background.
6856 : // OD 2004-02-12 #110582#-2 - do *not* consider fly frame, which
6857 : // belongs to a invisible layer
6858 18568 : if ( pFly->IsBackgroundTransparent() ||
6859 10984 : !pFly->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( pObj->GetLayer() ) )
6860 : {
6861 3792 : aIter.Next();
6862 3792 : continue;
6863 : }
6864 :
6865 : //Is the Obj placed on the line
6866 1798 : const long nP1OthPt = !bHori ? rP1.X() : rP1.Y();
6867 1798 : const Rectangle &rBound = pObj->GetCurrentBoundRect();
6868 1798 : const Point aDrPt( rBound.TopLeft() );
6869 1798 : const long nDrOthPt = !bHori ? aDrPt.X() : aDrPt.Y();
6870 1798 : const Size aDrSz( rBound.GetSize() );
6871 1798 : const long nDrOthSz = !bHori ? aDrSz.Width() : aDrSz.Height();
6872 :
6873 1798 : if ( nP1OthPt >= nDrOthPt && nP1OthPt <= nDrOthPt + nDrOthSz )
6874 : {
6875 461 : const long nDrDirPt = bHori ? aDrPt.X() : aDrPt.Y();
6876 461 : const long nDrDirSz = bHori ? aDrSz.Width() : aDrSz.Height();
6877 :
6878 461 : if ( (aP1.*pDirPt)() >= nDrDirPt && (aP1.*pDirPt)() <= nDrDirPt + nDrDirSz )
6879 131 : (aP1.*pDirPt)() = nDrDirPt + nDrDirSz;
6880 :
6881 461 : if ( (aP2.*pDirPt)() >= nDrDirPt && (aP1.*pDirPt)() < (nDrDirPt - 1) )
6882 9 : (aP2.*pDirPt)() = nDrDirPt - 1;
6883 : }
6884 1798 : aIter.Next();
6885 : }
6886 :
6887 1306 : if ( (aP1.*pDirPt)() < (aP2.*pDirPt)() )
6888 : {
6889 1203 : SwRect aRect( aP1, aP2 );
6890 : // OD 18.11.2002 #99672# - use parameter <pSubsLines> instead of
6891 : // global variable <gProp.pSSubsLines>.
6892 : pSubsLines->AddLineRect( aRect, 0, table::BorderLineStyle::SOLID,
6893 1203 : 0, nSubColor, gProp );
6894 : }
6895 1306 : aP1 = aP2;
6896 1306 : (aP1.*pDirPt)() += 1;
6897 1306 : aP2 = rP2;
6898 : }
6899 1313 : }
6900 :
6901 8876 : static drawinglayer::primitive2d::Primitive2DSequence lcl_CreatePageAreaDelimiterPrimitives(
6902 : const SwRect& rRect )
6903 : {
6904 8876 : drawinglayer::primitive2d::Primitive2DSequence aSeq( 4 );
6905 :
6906 17752 : basegfx::BColor aLineColor = SwViewOption::GetDocBoundariesColor().getBColor();
6907 8876 : double nLineLength = 200.0; // in Twips
6908 :
6909 8876 : Point aPoints[] = { rRect.TopLeft(), rRect.TopRight(), rRect.BottomRight(), rRect.BottomLeft() };
6910 8876 : double aXOffDirs[] = { -1.0, 1.0, 1.0, -1.0 };
6911 8876 : double aYOffDirs[] = { -1.0, -1.0, 1.0, 1.0 };
6912 :
6913 : // Actually loop over the corners to create the two lines
6914 44380 : for ( int i = 0; i < 4; i++ )
6915 : {
6916 35504 : basegfx::B2DVector aHorizVector( aXOffDirs[i], 0.0 );
6917 71008 : basegfx::B2DVector aVertVector( 0.0, aYOffDirs[i] );
6918 :
6919 71008 : basegfx::B2DPoint aBPoint( aPoints[i].getX(), aPoints[i].getY() );
6920 :
6921 71008 : basegfx::B2DPolygon aPolygon;
6922 35504 : aPolygon.append( aBPoint + aHorizVector * nLineLength );
6923 35504 : aPolygon.append( aBPoint );
6924 35504 : aPolygon.append( aBPoint + aVertVector * nLineLength );
6925 :
6926 : drawinglayer::primitive2d::PolygonHairlinePrimitive2D* pLine =
6927 : new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
6928 35504 : aPolygon, aLineColor );
6929 35504 : aSeq[i] = drawinglayer::primitive2d::Primitive2DReference( pLine );
6930 35504 : }
6931 :
6932 17752 : return aSeq;
6933 : }
6934 :
6935 27 : static drawinglayer::primitive2d::Primitive2DSequence lcl_CreateRectangleDelimiterPrimitives (
6936 : const SwRect& rRect )
6937 : {
6938 27 : drawinglayer::primitive2d::Primitive2DSequence aSeq( 1 );
6939 54 : basegfx::BColor aLineColor = SwViewOption::GetDocBoundariesColor().getBColor();
6940 :
6941 54 : basegfx::B2DPolygon aPolygon;
6942 27 : aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Top() ) );
6943 27 : aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Top() ) );
6944 27 : aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Bottom() ) );
6945 27 : aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Bottom() ) );
6946 27 : aPolygon.setClosed( true );
6947 :
6948 : drawinglayer::primitive2d::PolygonHairlinePrimitive2D* pLine =
6949 : new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
6950 27 : aPolygon, aLineColor );
6951 27 : aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( pLine );
6952 :
6953 54 : return aSeq;
6954 : }
6955 :
6956 47 : static drawinglayer::primitive2d::Primitive2DSequence lcl_CreateColumnAreaDelimiterPrimitives(
6957 : const SwRect& rRect )
6958 : {
6959 47 : drawinglayer::primitive2d::Primitive2DSequence aSeq( 4 );
6960 :
6961 94 : basegfx::BColor aLineColor = SwViewOption::GetDocBoundariesColor().getBColor();
6962 47 : double nLineLength = 100.0; // in Twips
6963 :
6964 47 : Point aPoints[] = { rRect.TopLeft(), rRect.TopRight(), rRect.BottomRight(), rRect.BottomLeft() };
6965 47 : double aXOffDirs[] = { 1.0, -1.0, -1.0, 1.0 };
6966 47 : double aYOffDirs[] = { 1.0, 1.0, -1.0, -1.0 };
6967 :
6968 : // Actually loop over the corners to create the two lines
6969 235 : for ( int i = 0; i < 4; i++ )
6970 : {
6971 188 : basegfx::B2DVector aHorizVector( aXOffDirs[i], 0.0 );
6972 376 : basegfx::B2DVector aVertVector( 0.0, aYOffDirs[i] );
6973 :
6974 376 : basegfx::B2DPoint aBPoint( aPoints[i].getX(), aPoints[i].getY() );
6975 :
6976 376 : basegfx::B2DPolygon aPolygon;
6977 188 : aPolygon.append( aBPoint + aHorizVector * nLineLength );
6978 188 : aPolygon.append( aBPoint );
6979 188 : aPolygon.append( aBPoint + aVertVector * nLineLength );
6980 :
6981 : drawinglayer::primitive2d::PolygonHairlinePrimitive2D* pLine =
6982 : new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
6983 188 : aPolygon, aLineColor );
6984 188 : aSeq[i] = drawinglayer::primitive2d::Primitive2DReference( pLine );
6985 188 : }
6986 :
6987 94 : return aSeq;
6988 : }
6989 :
6990 8903 : void SwPageFrm::PaintSubsidiaryLines( const SwPageFrm *,
6991 : const SwRect & ) const
6992 : {
6993 8903 : if ( !gProp.pSGlobalShell->IsHeaderFooterEdit() )
6994 : {
6995 8903 : const SwFrm* pLay = Lower();
6996 8903 : const SwFrm* pFootnoteCont = NULL;
6997 8903 : const SwFrm* pPageBody = NULL;
6998 27341 : while ( pLay && !( pFootnoteCont && pPageBody ) )
6999 : {
7000 9535 : if ( pLay->IsFootnoteContFrm( ) )
7001 107 : pFootnoteCont = pLay;
7002 9535 : if ( pLay->IsBodyFrm() )
7003 8903 : pPageBody = pLay;
7004 9535 : pLay = pLay->GetNext();
7005 : }
7006 :
7007 8903 : SwRect aArea( pPageBody->Frm() );
7008 8903 : if ( pFootnoteCont )
7009 107 : aArea.AddBottom( pFootnoteCont->Frm().Bottom() - aArea.Bottom() );
7010 :
7011 8903 : if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) )
7012 8876 : ProcessPrimitives( lcl_CreatePageAreaDelimiterPrimitives( aArea ) );
7013 : else
7014 27 : ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) );
7015 : }
7016 8903 : }
7017 :
7018 47 : void SwColumnFrm::PaintSubsidiaryLines( const SwPageFrm *,
7019 : const SwRect & ) const
7020 : {
7021 47 : const SwFrm* pLay = Lower();
7022 47 : const SwFrm* pFootnoteCont = NULL;
7023 47 : const SwFrm* pColBody = NULL;
7024 142 : while ( pLay && !( pFootnoteCont && pColBody ) )
7025 : {
7026 48 : if ( pLay->IsFootnoteContFrm( ) )
7027 1 : pFootnoteCont = pLay;
7028 48 : if ( pLay->IsBodyFrm() )
7029 47 : pColBody = pLay;
7030 48 : pLay = pLay->GetNext();
7031 : }
7032 :
7033 47 : SwRect aArea( pColBody->Frm() );
7034 :
7035 : // #i3662# - enlarge top of column body frame's printing area
7036 : // in sections to top of section frame.
7037 47 : const bool bColInSection = GetUpper()->IsSctFrm();
7038 47 : if ( bColInSection )
7039 : {
7040 47 : if ( IsVertical() )
7041 0 : aArea.Right( GetUpper()->Frm().Right() );
7042 : else
7043 47 : aArea.Top( GetUpper()->Frm().Top() );
7044 : }
7045 :
7046 47 : if ( pFootnoteCont )
7047 1 : aArea.AddBottom( pFootnoteCont->Frm().Bottom() - aArea.Bottom() );
7048 :
7049 47 : ::SwAlignRect( aArea, gProp.pSGlobalShell );
7050 :
7051 47 : if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) )
7052 47 : ProcessPrimitives( lcl_CreateColumnAreaDelimiterPrimitives( aArea ) );
7053 : else
7054 0 : ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) );
7055 47 : }
7056 :
7057 96 : void SwSectionFrm::PaintSubsidiaryLines( const SwPageFrm * pPage,
7058 : const SwRect & rRect ) const
7059 : {
7060 96 : const bool bNoLowerColumn = !Lower() || !Lower()->IsColumnFrm();
7061 96 : if ( bNoLowerColumn )
7062 : {
7063 75 : SwLayoutFrm::PaintSubsidiaryLines( pPage, rRect );
7064 : }
7065 96 : }
7066 :
7067 : /**
7068 : * The SwBodyFrm doesn't print any subsidiary line: it's bounds are painted
7069 : * either by the parent page or the parent column frame.
7070 : */
7071 8836 : void SwBodyFrm::PaintSubsidiaryLines( const SwPageFrm *,
7072 : const SwRect & ) const
7073 : {
7074 8836 : }
7075 :
7076 249 : void SwHeadFootFrm::PaintSubsidiaryLines( const SwPageFrm *, const SwRect & ) const
7077 : {
7078 249 : if ( gProp.pSGlobalShell->IsHeaderFooterEdit() )
7079 : {
7080 0 : SwRect aArea( Prt() );
7081 0 : aArea.Pos() += Frm().Pos();
7082 0 : if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) )
7083 0 : ProcessPrimitives( lcl_CreatePageAreaDelimiterPrimitives( aArea ) );
7084 : else
7085 0 : ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) );
7086 : }
7087 249 : }
7088 :
7089 : /**
7090 : * This method is overridden in order to have no subsidiary lines
7091 : * around the footnotes.
7092 : */
7093 8 : void SwFootnoteFrm::PaintSubsidiaryLines( const SwPageFrm *,
7094 : const SwRect & ) const
7095 : {
7096 8 : }
7097 :
7098 : /**
7099 : * This method is overridden in order to have no subsidiary lines
7100 : * around the footnotes containers.
7101 : */
7102 7 : void SwFootnoteContFrm::PaintSubsidiaryLines( const SwPageFrm *,
7103 : const SwRect & ) const
7104 : {
7105 7 : }
7106 :
7107 7096 : void SwLayoutFrm::PaintSubsidiaryLines( const SwPageFrm *pPage,
7108 : const SwRect &rRect ) const
7109 : {
7110 7096 : bool bNewTableModel = false;
7111 :
7112 : // #i29550#
7113 7096 : if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
7114 : {
7115 6564 : const SwTabFrm* pTabFrm = FindTabFrm();
7116 6564 : if ( pTabFrm->IsCollapsingBorders() )
7117 13123 : return;
7118 :
7119 4 : bNewTableModel = pTabFrm->GetTable()->IsNewModel();
7120 : // in the new table model, we have an early return for all cell-related
7121 : // frames, except from non-covered table cells
7122 4 : if ( bNewTableModel )
7123 11 : if ( IsTabFrm() ||
7124 8 : IsRowFrm() ||
7125 4 : ( IsCellFrm() && IsCoveredCell() ) )
7126 2 : return;
7127 : }
7128 :
7129 534 : const bool bFlys = pPage->GetSortedObjs() != nullptr;
7130 :
7131 534 : const bool bCell = IsCellFrm();
7132 : // use frame area for cells
7133 : // OD 13.02.2003 #i3662# - for section use also frame area
7134 534 : const bool bUseFrmArea = bCell || IsSctFrm();
7135 534 : SwRect aOriginal( bUseFrmArea ? Frm() : Prt() );
7136 534 : if ( !bUseFrmArea )
7137 457 : aOriginal.Pos() += Frm().Pos();
7138 :
7139 534 : ::SwAlignRect( aOriginal, gProp.pSGlobalShell );
7140 :
7141 534 : if ( !aOriginal.IsOver( rRect ) )
7142 1 : return;
7143 :
7144 533 : SwRect aOut( aOriginal );
7145 533 : aOut._Intersection( rRect );
7146 :
7147 533 : const SwTwips nRight = aOut.Right();
7148 533 : const SwTwips nBottom= aOut.Bottom();
7149 :
7150 533 : const Point aRT( nRight, aOut.Top() );
7151 533 : const Point aRB( nRight, nBottom );
7152 533 : const Point aLB( aOut.Left(), nBottom );
7153 :
7154 1064 : sal_uInt8 nSubColor = ( bCell || IsRowFrm() ) ? SUBCOL_TAB :
7155 531 : ( IsInSct() ? SUBCOL_SECT :
7156 1064 : ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
7157 :
7158 : // OD 18.11.2002 #99672# - collect body, header, footer, footnote and section
7159 : // sub-lines in <pSpecSubsLine> array.
7160 1599 : const bool bSpecialSublines = IsBodyFrm() || IsHeaderFrm() || IsFooterFrm() ||
7161 1599 : IsFootnoteFrm() || IsSctFrm();
7162 533 : SwLineRects* pUsedSubsLines = bSpecialSublines ? gProp.pSSpecSubsLines : gProp.pSSubsLines;
7163 :
7164 : // NOTE: for cell frames only left and right (horizontal layout) respectively
7165 : // top and bottom (vertical layout) lines painted.
7166 : // NOTE2: this does not hold for the new table model!!! We paint the top border
7167 : // of each non-covered table cell.
7168 533 : const bool bVert = IsVertical();
7169 533 : if ( bFlys )
7170 : {
7171 : // OD 14.11.2002 #104822# - add control for drawing left and right lines
7172 333 : if ( !bCell || bNewTableModel || !bVert )
7173 : {
7174 333 : if ( aOriginal.Left() == aOut.Left() )
7175 333 : ::lcl_RefreshLine( this, pPage, aOut.Pos(), aLB, nSubColor, pUsedSubsLines );
7176 : // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
7177 333 : if ( aOriginal.Right() == nRight )
7178 322 : ::lcl_RefreshLine( this, pPage, aRT, aRB, nSubColor, pUsedSubsLines );
7179 : }
7180 : // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
7181 333 : if ( !bCell || bNewTableModel || bVert )
7182 : {
7183 333 : if ( aOriginal.Top() == aOut.Top() )
7184 : // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
7185 333 : ::lcl_RefreshLine( this, pPage, aOut.Pos(), aRT, nSubColor, pUsedSubsLines );
7186 333 : if ( aOriginal.Bottom() == nBottom )
7187 : ::lcl_RefreshLine( this, pPage, aLB, aRB, nSubColor,
7188 325 : pUsedSubsLines );
7189 : }
7190 : }
7191 : else
7192 : {
7193 : // OD 14.11.2002 #104822# - add control for drawing left and right lines
7194 200 : if ( !bCell || bNewTableModel || !bVert )
7195 : {
7196 200 : if ( aOriginal.Left() == aOut.Left() )
7197 : {
7198 196 : const SwRect aRect( aOut.Pos(), aLB );
7199 : pUsedSubsLines->AddLineRect( aRect, 0,
7200 196 : table::BorderLineStyle::SOLID, 0, nSubColor, gProp );
7201 : }
7202 : // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
7203 200 : if ( aOriginal.Right() == nRight )
7204 : {
7205 135 : const SwRect aRect( aRT, aRB );
7206 : pUsedSubsLines->AddLineRect( aRect, 0,
7207 135 : table::BorderLineStyle::SOLID, 0, nSubColor, gProp );
7208 : }
7209 : }
7210 : // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
7211 200 : if ( !bCell || bNewTableModel || bVert )
7212 : {
7213 200 : if ( aOriginal.Top() == aOut.Top() )
7214 : {
7215 : // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
7216 195 : const SwRect aRect( aOut.Pos(), aRT );
7217 : pUsedSubsLines->AddLineRect( aRect, 0,
7218 195 : table::BorderLineStyle::SOLID, 0, nSubColor, gProp );
7219 : }
7220 200 : if ( aOriginal.Bottom() == nBottom )
7221 : {
7222 174 : const SwRect aRect( aLB, aRB );
7223 : pUsedSubsLines->AddLineRect( aRect, 0,
7224 174 : table::BorderLineStyle::SOLID, 0, nSubColor, gProp );
7225 : }
7226 : }
7227 : }
7228 : }
7229 :
7230 : /**
7231 : * Refreshes all extra data (line breaks a.s.o) of the page. Basically only those objects
7232 : * are considered which horizontally overlap the Rect.
7233 : */
7234 272 : void SwPageFrm::RefreshExtraData( const SwRect &rRect ) const
7235 : {
7236 272 : const SwLineNumberInfo &rInfo = GetFormat()->GetDoc()->GetLineNumberInfo();
7237 307 : bool bLineInFly = (rInfo.IsPaintLineNumbers() && rInfo.IsCountInFlys())
7238 544 : || (sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE;
7239 :
7240 272 : SwRect aRect( rRect );
7241 272 : ::SwAlignRect( aRect, gProp.pSGlobalShell );
7242 272 : if ( aRect.HasArea() )
7243 : {
7244 272 : SwLayoutFrm::RefreshExtraData( aRect );
7245 :
7246 272 : if ( bLineInFly && GetSortedObjs() )
7247 6 : for ( size_t i = 0; i < GetSortedObjs()->size(); ++i )
7248 : {
7249 3 : const SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
7250 3 : if ( pAnchoredObj->ISA(SwFlyFrm) )
7251 : {
7252 3 : const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
7253 3 : if ( pFly->Frm().Top() <= aRect.Bottom() &&
7254 0 : pFly->Frm().Bottom() >= aRect.Top() )
7255 0 : pFly->RefreshExtraData( aRect );
7256 : }
7257 : }
7258 : }
7259 272 : }
7260 :
7261 272 : void SwLayoutFrm::RefreshExtraData( const SwRect &rRect ) const
7262 : {
7263 :
7264 272 : const SwLineNumberInfo &rInfo = GetFormat()->GetDoc()->GetLineNumberInfo();
7265 272 : bool bLineInBody = rInfo.IsPaintLineNumbers(),
7266 272 : bLineInFly = bLineInBody && rInfo.IsCountInFlys(),
7267 272 : bRedLine = (sal_Int16)SW_MOD()->GetRedlineMarkPos()!=text::HoriOrientation::NONE;
7268 :
7269 272 : const SwContentFrm *pCnt = ContainsContent();
7270 2385 : while ( pCnt && IsAnLower( pCnt ) )
7271 : {
7272 5523 : if ( pCnt->IsTextFrm() && ( bRedLine ||
7273 0 : ( !pCnt->IsInTab() &&
7274 0 : ((bLineInBody && pCnt->IsInDocBody()) ||
7275 1841 : (bLineInFly && pCnt->IsInFly())) ) ) &&
7276 5094 : pCnt->Frm().Top() <= rRect.Bottom() &&
7277 1412 : pCnt->Frm().Bottom() >= rRect.Top() )
7278 : {
7279 1398 : static_cast<const SwTextFrm*>(pCnt)->PaintExtraData( rRect );
7280 : }
7281 1841 : if ( bLineInFly && pCnt->GetDrawObjs() )
7282 0 : for ( size_t i = 0; i < pCnt->GetDrawObjs()->size(); ++i )
7283 : {
7284 0 : const SwAnchoredObject* pAnchoredObj = (*pCnt->GetDrawObjs())[i];
7285 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
7286 : {
7287 0 : const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
7288 0 : if ( pFly->IsFlyInCntFrm() &&
7289 0 : pFly->Frm().Top() <= rRect.Bottom() &&
7290 0 : pFly->Frm().Bottom() >= rRect.Top() )
7291 0 : pFly->RefreshExtraData( rRect );
7292 : }
7293 : }
7294 1841 : pCnt = pCnt->GetNextContentFrm();
7295 : }
7296 272 : }
7297 :
7298 : /**
7299 : * For #102450#
7300 : * Determine the color, that is respectively will be drawn as background
7301 : * for the page frame.
7302 : * Using existing method SwFrm::GetBackgroundBrush to determine the color
7303 : * that is set at the page frame respectively is parent. If none is found
7304 : * return the global retouche color
7305 : *
7306 : * @return Color
7307 : */
7308 9288 : const Color SwPageFrm::GetDrawBackgrdColor() const
7309 : {
7310 : const SvxBrushItem* pBrushItem;
7311 : const Color* pDummyColor;
7312 9288 : SwRect aDummyRect;
7313 :
7314 : //UUUU
7315 9288 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
7316 :
7317 9288 : if ( GetBackgroundBrush( aFillAttributes, pBrushItem, pDummyColor, aDummyRect, true) )
7318 : {
7319 16 : if(aFillAttributes.get() && aFillAttributes->isUsed()) //UUUU
7320 : {
7321 : // let SdrAllFillAttributesHelper do the average color calculation
7322 16 : return Color(aFillAttributes->getAverageColor(aGlobalRetoucheColor.getBColor()));
7323 : }
7324 0 : else if(pBrushItem)
7325 : {
7326 0 : OUString referer;
7327 0 : SwViewShell * sh1 = getRootFrm()->GetCurrShell();
7328 0 : if (sh1 != 0) {
7329 0 : SfxObjectShell * sh2 = sh1->GetDoc()->GetPersist();
7330 0 : if (sh2 != 0 && sh2->HasName()) {
7331 0 : referer = sh2->GetMedium()->GetName();
7332 : }
7333 : }
7334 0 : const Graphic* pGraphic = pBrushItem->GetGraphic(referer);
7335 :
7336 0 : if(pGraphic)
7337 : {
7338 : // #29105# when a graphic is set, it may be possible to calculate a single
7339 : // color which looks good in all places of the graphic. Since it is
7340 : // planned to have text edit on the overlay one day and the fallback
7341 : // to aGlobalRetoucheColor returns something useful, just use that
7342 : // for now.
7343 : }
7344 : else
7345 : {
7346 : // not a graphic, use (hopefully) initialized color
7347 0 : return pBrushItem->GetColor();
7348 0 : }
7349 : }
7350 : }
7351 :
7352 9272 : return aGlobalRetoucheColor;
7353 : }
7354 :
7355 : /// create/return font used to paint the "empty page" string
7356 0 : const vcl::Font& SwPageFrm::GetEmptyPageFont()
7357 : {
7358 : static vcl::Font* pEmptyPgFont = 0;
7359 0 : if ( 0 == pEmptyPgFont )
7360 : {
7361 0 : pEmptyPgFont = new vcl::Font;
7362 0 : pEmptyPgFont->SetSize( Size( 0, 80 * 20 )); // == 80 pt
7363 0 : pEmptyPgFont->SetWeight( WEIGHT_BOLD );
7364 0 : pEmptyPgFont->SetStyleName( aEmptyOUStr );
7365 0 : pEmptyPgFont->SetName(OUString("Helvetica"));
7366 0 : pEmptyPgFont->SetFamily( FAMILY_SWISS );
7367 0 : pEmptyPgFont->SetTransparent( true );
7368 0 : pEmptyPgFont->SetColor( COL_GRAY );
7369 : }
7370 :
7371 0 : return *pEmptyPgFont;
7372 : }
7373 :
7374 : /**
7375 : * Retouch for a section
7376 : *
7377 : * Retouch will only be done, if the Frm is the last one in his chain.
7378 : * The whole area of the upper which is located below the Frm will be
7379 : * cleared using PaintBackground.
7380 : */
7381 2454 : void SwFrm::Retouche( const SwPageFrm * pPage, const SwRect &rRect ) const
7382 : {
7383 2454 : if ( gProp.bSFlyMetafile )
7384 2454 : return;
7385 :
7386 : OSL_ENSURE( GetUpper(), "Retouche try without Upper." );
7387 : OSL_ENSURE( getRootFrm()->GetCurrShell() && gProp.pSGlobalShell->GetWin(), "Retouche on a printer?" );
7388 :
7389 2454 : SwRect aRetouche( GetUpper()->PaintArea() );
7390 2454 : aRetouche.Top( Frm().Top() + Frm().Height() );
7391 2454 : aRetouche.Intersection( gProp.pSGlobalShell->VisArea() );
7392 :
7393 2454 : if ( aRetouche.HasArea() )
7394 : {
7395 : //Omit the passed Rect. To do this, we unfortunately need a region to
7396 : //cut out.
7397 1933 : SwRegionRects aRegion( aRetouche );
7398 1933 : aRegion -= rRect;
7399 1933 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
7400 :
7401 : // #i16816# tagged pdf support
7402 3866 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
7403 :
7404 1970 : for ( size_t i = 0; i < aRegion.size(); ++i )
7405 : {
7406 37 : SwRect &rRetouche = aRegion[i];
7407 :
7408 37 : GetUpper()->PaintBaBo( rRetouche, pPage, true );
7409 :
7410 : //Hell and Heaven need to be refreshed too.
7411 : //To avoid recursion my retouch flag needs to be reset first!
7412 37 : ResetRetouche();
7413 37 : SwRect aRetouchePart( rRetouche );
7414 37 : if ( aRetouchePart.HasArea() )
7415 : {
7416 37 : const Color aPageBackgrdColor(pPage->GetDrawBackgrdColor());
7417 37 : const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
7418 : // --> OD #i76669#
7419 37 : SwViewObjectContactRedirector aSwRedirector( *pSh );
7420 : // <--
7421 :
7422 37 : pSh->Imp()->PaintLayer( pIDDMA->GetHellId(), 0,
7423 : aRetouchePart, &aPageBackgrdColor,
7424 37 : pPage->IsRightToLeft(),
7425 74 : &aSwRedirector );
7426 37 : pSh->Imp()->PaintLayer( pIDDMA->GetHeavenId(), 0,
7427 : aRetouchePart, &aPageBackgrdColor,
7428 37 : pPage->IsRightToLeft(),
7429 74 : &aSwRedirector );
7430 : }
7431 :
7432 37 : SetRetouche();
7433 :
7434 : //Because we leave all paint areas, we need to refresh the
7435 : //subsidiary lines.
7436 37 : pPage->RefreshSubsidiary( aRetouchePart );
7437 1933 : }
7438 : }
7439 2454 : if ( SwViewShell::IsLstEndAction() )
7440 2454 : ResetRetouche();
7441 : }
7442 :
7443 : /**
7444 : * Determine the background brush for the frame:
7445 : * the background brush is taken from it-self or from its parent (anchor/upper).
7446 : * Normally, the background brush is taken, which has no transparent color or
7447 : * which has a background graphic. But there are some special cases:
7448 : * (1) No background brush is taken from a page frame, if view option "IsPageBack"
7449 : * isn't set.
7450 : * (2) Background brush from a index section is taken under special conditions.
7451 : * In this case parameter <rpCol> is set to the index shading color.
7452 : * (3) New (OD 20.08.2002) - Background brush is taken, if on background drawing
7453 : * of the frame transparency is considered and its color is not "no fill"/"auto fill"
7454 : *
7455 : * Old description in German:
7456 : * Returns the Backgroundbrush for the area of the Frm.
7457 : * The Brush is defined by the Frm or by an upper, the first Brush is
7458 : * used. If no Brush is defined for a Frm, false is returned.
7459 : *
7460 : * @param rpBrush
7461 : * output parameter - constant reference pointer the found background brush
7462 : *
7463 : * @param rpFillStyle
7464 : * output parameter - constant reference pointer the found background fill style
7465 : *
7466 : * @param rpFillGradient
7467 : * output parameter - constant reference pointer the found background fill gradient
7468 : *
7469 : * @param rpCol
7470 : * output parameter - constant reference pointer to the color of the index shading
7471 : * set under special conditions, if background brush is taken from an index section.
7472 : *
7473 : * @param rOrigRect
7474 : * in-/output parameter - reference to the rectangle the background brush is
7475 : * considered for - adjusted to the frame, from which the background brush is
7476 : * taken.
7477 : *
7478 : * @parem bLowerMode
7479 : * input parameter - boolean indicating, if background brush should *not* be
7480 : * taken from parent.
7481 : *
7482 : * @return true, if a background brush for the frame is found
7483 : */
7484 80588 : bool SwFrm::GetBackgroundBrush(
7485 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
7486 : const SvxBrushItem* & rpBrush,
7487 : const Color*& rpCol,
7488 : SwRect &rOrigRect,
7489 : bool bLowerMode ) const
7490 : {
7491 80588 : const SwFrm *pFrm = this;
7492 80588 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
7493 80588 : const SwViewOption *pOpt = pSh->GetViewOptions();
7494 80588 : rpBrush = 0;
7495 80588 : rpCol = NULL;
7496 105281 : do
7497 156365 : { if ( pFrm->IsPageFrm() && !pOpt->IsPageBack() )
7498 0 : return false;
7499 :
7500 : //UUUU
7501 156365 : if (pFrm->supportsFullDrawingLayerFillAttributeSet())
7502 144741 : rFillAttributes = pFrm->getSdrAllFillAttributesHelper();
7503 156365 : const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
7504 :
7505 156365 : if( pFrm->IsSctFrm() )
7506 : {
7507 2274 : const SwSection* pSection = static_cast<const SwSectionFrm*>(pFrm)->GetSection();
7508 : // OD 20.08.2002 #99657# #GetTransChg#
7509 : // Note: If frame <pFrm> is a section of the index and
7510 : // it its background color is "no fill"/"auto fill" and
7511 : // it has no background graphic and
7512 : // we are not in the page preview and
7513 : // we are not in read-only mode and
7514 : // option "index shadings" is set and
7515 : // the output is not the printer
7516 : // then set <rpCol> to the color of the index shading
7517 10897 : if( pSection && ( TOX_HEADER_SECTION == pSection->GetType() ||
7518 3166 : TOX_CONTENT_SECTION == pSection->GetType() ) &&
7519 4086 : (rBack.GetColor() == COL_TRANSPARENT) &&
7520 893 : rBack.GetGraphicPos() == GPOS_NONE &&
7521 892 : !pOpt->IsPagePreview() &&
7522 892 : !pOpt->IsReadonly() &&
7523 : // #114856# Formular view
7524 892 : !pOpt->IsFormView() &&
7525 892 : SwViewOption::IsIndexShadings() &&
7526 3166 : !pOpt->IsPDFExport() &&
7527 446 : pSh->GetOut()->GetOutDevType() != OUTDEV_PRINTER )
7528 : {
7529 446 : rpCol = &SwViewOption::GetIndexShadingsColor();
7530 : }
7531 : }
7532 :
7533 : // OD 20.08.2002 #99657#
7534 : // determine, if background draw of frame <pFrm> considers transparency
7535 : // --> Status Quo: background transparency have to be
7536 : // considered for fly frames
7537 156365 : const bool bConsiderBackgroundTransparency = pFrm->IsFlyFrm();
7538 :
7539 : // #i125189# Do not base the decision for using the parent's fill style for this
7540 : // frame when the new DrawingLayer FillAttributes are used on the SdrAllFillAttributesHelper
7541 : // information. There the data is already optimized to no fill in the case that the
7542 : // transparence is at 100% while no fill is the criteria for derivation
7543 156365 : bool bNewDrawingLayerFillStyleIsUsedAndNotNoFill(false);
7544 :
7545 156365 : if(rFillAttributes.get())
7546 : {
7547 : // the new DrawingLayer FillStyle is used
7548 147219 : if(rFillAttributes->isUsed())
7549 : {
7550 : // it's not drawing::FillStyle_NONE
7551 675 : bNewDrawingLayerFillStyleIsUsedAndNotNoFill = true;
7552 : }
7553 : else
7554 : {
7555 : // maybe optimized already when 100% transparency is used somewhere, need to test
7556 : // XFillStyleItem directly from the model data
7557 146544 : const drawing::FillStyle eFillStyle(static_cast< const XFillStyleItem& >(pFrm->GetAttrSet()->Get(XATTR_FILLSTYLE)).GetValue());
7558 :
7559 146544 : if(drawing::FillStyle_NONE != eFillStyle)
7560 : {
7561 0 : bNewDrawingLayerFillStyleIsUsedAndNotNoFill = true;
7562 : }
7563 : }
7564 : }
7565 :
7566 : // OD 20.08.2002 #99657#
7567 : // add condition:
7568 : // If <bConsiderBackgroundTransparency> is set - see above -,
7569 : // return brush of frame <pFrm>, if its color is *not* "no fill"/"auto fill"
7570 466667 : if (
7571 : // #i125189# Done when the new DrawingLayer FillAttributes are used and
7572 : // not drawing::FillStyle_NONE (see above)
7573 155690 : bNewDrawingLayerFillStyleIsUsedAndNotNoFill ||
7574 :
7575 : // done when SvxBrushItem is used
7576 309663 : !rBack.GetColor().GetTransparency() || rBack.GetGraphicPos() != GPOS_NONE ||
7577 :
7578 : // done when direct color is forced
7579 312756 : rpCol ||
7580 :
7581 : // done when consider BG transparency and color is not completely transparent
7582 161221 : (bConsiderBackgroundTransparency && (rBack.GetColor() != COL_TRANSPARENT))
7583 : )
7584 : {
7585 2879 : rpBrush = &rBack;
7586 2879 : if ( pFrm->IsPageFrm() && pSh->GetViewOptions()->getBrowseMode() )
7587 : {
7588 0 : rOrigRect = pFrm->Frm();
7589 : }
7590 : else
7591 : {
7592 2879 : if ( pFrm->Frm().SSize() != pFrm->Prt().SSize() )
7593 : {
7594 2166 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
7595 2166 : const SwBorderAttrs &rAttrs = *aAccess.Get();
7596 2166 : ::lcl_CalcBorderRect( rOrigRect, pFrm, rAttrs, false, gProp );
7597 : }
7598 : else
7599 : {
7600 713 : rOrigRect = pFrm->Prt();
7601 713 : rOrigRect += pFrm->Frm().Pos();
7602 : }
7603 : }
7604 :
7605 2879 : return true;
7606 : }
7607 :
7608 153486 : if ( bLowerMode )
7609 : {
7610 : // Do not try to get background brush from parent (anchor/upper)
7611 48205 : return false;
7612 : }
7613 :
7614 : // get parent frame - anchor or upper - for next loop
7615 105281 : if ( pFrm->IsFlyFrm() )
7616 : {
7617 : // OD 20.08.2002 - use "static_cast" instead of "old C-cast"
7618 2402 : pFrm = (static_cast<const SwFlyFrm*>(pFrm))->GetAnchorFrm();
7619 : }
7620 : else
7621 : {
7622 102879 : pFrm = pFrm->GetUpper();
7623 : }
7624 : } while ( pFrm );
7625 :
7626 29504 : return false;
7627 : }
7628 :
7629 0 : void SetOutDevAndWin( SwViewShell *pSh, OutputDevice *pO,
7630 : vcl::Window *pW, sal_uInt16 nZoom )
7631 : {
7632 0 : pSh->mpOut = pO;
7633 0 : pSh->mpWin = pW;
7634 0 : pSh->mpOpt->SetZoom( nZoom );
7635 0 : }
7636 :
7637 0 : Graphic SwFrameFormat::MakeGraphic( ImageMap* )
7638 : {
7639 0 : return Graphic();
7640 : }
7641 :
7642 0 : Graphic SwFlyFrameFormat::MakeGraphic( ImageMap* pMap )
7643 : {
7644 0 : Graphic aRet;
7645 : //search any Fly!
7646 0 : SwIterator<SwFrm,SwFormat> aIter( *this );
7647 0 : SwFrm *pFirst = aIter.First();
7648 : SwViewShell *pSh;
7649 0 : if ( pFirst && 0 != ( pSh = pFirst->getRootFrm()->GetCurrShell()) )
7650 : {
7651 0 : SwViewShell *pOldGlobal = gProp.pSGlobalShell;
7652 0 : gProp.pSGlobalShell = pSh;
7653 :
7654 0 : bool bNoteURL = pMap &&
7655 0 : SfxItemState::SET != GetAttrSet().GetItemState( RES_URL, true );
7656 0 : if( bNoteURL )
7657 : {
7658 : OSL_ENSURE( !pNoteURL, "MakeGraphic: pNoteURL already used? " );
7659 0 : pNoteURL = new SwNoteURL;
7660 : }
7661 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pFirst);
7662 :
7663 0 : OutputDevice *pOld = pSh->GetOut();
7664 0 : ScopedVclPtrInstance< VirtualDevice > pDev( *pOld );
7665 0 : pDev->EnableOutput( false );
7666 :
7667 0 : GDIMetaFile aMet;
7668 0 : MapMode aMap( pOld->GetMapMode().GetMapUnit() );
7669 0 : pDev->SetMapMode( aMap );
7670 0 : aMet.SetPrefMapMode( aMap );
7671 :
7672 0 : ::SwCalcPixStatics( pSh->GetOut() );
7673 0 : aMet.SetPrefSize( pFly->Frm().SSize() );
7674 :
7675 0 : aMet.Record( pDev.get() );
7676 0 : pDev->SetLineColor();
7677 0 : pDev->SetFillColor();
7678 0 : pDev->SetFont( pOld->GetFont() );
7679 :
7680 : //Enlarge the rectangle if needed, so the border is painted too.
7681 0 : SwRect aOut( pFly->Frm() );
7682 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFly );
7683 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
7684 0 : if ( rAttrs.CalcRightLine() )
7685 0 : aOut.SSize().Width() += 2*gProp.nSPixelSzW;
7686 0 : if ( rAttrs.CalcBottomLine() )
7687 0 : aOut.SSize().Height()+= 2*gProp.nSPixelSzH;
7688 :
7689 : // #i92711# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
7690 0 : const vcl::Region aRepaintRegion(aOut.SVRect());
7691 0 : pSh->DLPrePaint2(aRepaintRegion);
7692 :
7693 0 : vcl::Window *pWin = pSh->GetWin();
7694 0 : sal_uInt16 nZoom = pSh->GetViewOptions()->GetZoom();
7695 0 : ::SetOutDevAndWin( pSh, pDev, 0, 100 );
7696 0 : gProp.bSFlyMetafile = true;
7697 0 : gProp.pSFlyMetafileOut = pWin;
7698 :
7699 0 : SwViewShellImp *pImp = pSh->Imp();
7700 0 : gProp.pSFlyOnlyDraw = pFly;
7701 0 : gProp.pSLines = new SwLineRects;
7702 :
7703 : // OD 09.12.2002 #103045# - determine page, fly frame is on
7704 0 : const SwPageFrm* pFlyPage = pFly->FindPageFrm();
7705 0 : const Color aPageBackgrdColor(pFlyPage->GetDrawBackgrdColor());
7706 0 : const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
7707 : // --> OD #i76669#
7708 0 : SwViewObjectContactRedirector aSwRedirector( *pSh );
7709 : // <--
7710 0 : pImp->PaintLayer( pIDDMA->GetHellId(), 0, aOut, &aPageBackgrdColor,
7711 0 : pFlyPage->IsRightToLeft(),
7712 0 : &aSwRedirector );
7713 0 : gProp.pSLines->PaintLines( pDev, gProp );
7714 0 : if ( pFly->IsFlyInCntFrm() )
7715 0 : pFly->Paint( aOut );
7716 0 : gProp.pSLines->PaintLines( pDev, gProp );
7717 : // OD 30.08.2002 #102450# - add 3rd parameter
7718 0 : pImp->PaintLayer( pIDDMA->GetHeavenId(), 0, aOut, &aPageBackgrdColor,
7719 0 : pFlyPage->IsRightToLeft(),
7720 0 : &aSwRedirector );
7721 0 : gProp.pSLines->PaintLines( pDev, gProp );
7722 0 : DELETEZ( gProp.pSLines );
7723 0 : gProp.pSFlyOnlyDraw = 0;
7724 :
7725 0 : gProp.pSFlyMetafileOut = 0;
7726 0 : gProp.bSFlyMetafile = false;
7727 0 : ::SetOutDevAndWin( pSh, pOld, pWin, nZoom );
7728 :
7729 : // #i92711# end Pre/PostPaint encapsulation when pOut is back and content is painted
7730 0 : pSh->DLPostPaint2(true);
7731 :
7732 0 : aMet.Stop();
7733 0 : aMet.Move( -pFly->Frm().Left(), -pFly->Frm().Top() );
7734 0 : aRet = Graphic( aMet );
7735 :
7736 0 : if( bNoteURL )
7737 : {
7738 : OSL_ENSURE( pNoteURL, "MakeGraphic: Good Bye, NoteURL." );
7739 0 : pNoteURL->FillImageMap( pMap, pFly->Frm().Pos(), aMap );
7740 0 : delete pNoteURL;
7741 0 : pNoteURL = NULL;
7742 : }
7743 0 : gProp.pSGlobalShell = pOldGlobal;
7744 : }
7745 0 : return aRet;
7746 : }
7747 :
7748 0 : Graphic SwDrawFrameFormat::MakeGraphic( ImageMap* )
7749 : {
7750 0 : Graphic aRet;
7751 0 : SwDrawModel* pMod = getIDocumentDrawModelAccess()->GetDrawModel();
7752 0 : if ( pMod )
7753 : {
7754 0 : SdrObject *pObj = FindSdrObject();
7755 0 : SdrView *pView = new SdrView( pMod );
7756 0 : SdrPageView *pPgView = pView->ShowSdrPage(pView->GetModel()->GetPage(0));
7757 0 : pView->MarkObj( pObj, pPgView );
7758 0 : aRet = pView->GetMarkedObjBitmapEx();
7759 0 : pView->HideSdrPage();
7760 0 : delete pView;
7761 : }
7762 0 : return aRet;
7763 177 : }
7764 :
7765 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|