File: | home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx |
Warning: | line 6715, column 19 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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/printer.hxx> | |||
23 | #include <sfx2/progress.hxx> | |||
24 | #include <editeng/brushitem.hxx> | |||
25 | #include <editeng/prntitem.hxx> | |||
26 | #include <editeng/boxitem.hxx> | |||
27 | #include <editeng/shaditem.hxx> | |||
28 | #include <svx/framelink.hxx> | |||
29 | #include <drawdoc.hxx> | |||
30 | #include <tgrditem.hxx> | |||
31 | #include <calbck.hxx> | |||
32 | #include <fmtsrnd.hxx> | |||
33 | #include <fmtclds.hxx> | |||
34 | #include <strings.hrc> | |||
35 | #include <swmodule.hxx> | |||
36 | #include <rootfrm.hxx> | |||
37 | #include <pagefrm.hxx> | |||
38 | #include <section.hxx> | |||
39 | #include <sectfrm.hxx> | |||
40 | #include <viewimp.hxx> | |||
41 | #include <dflyobj.hxx> | |||
42 | #include <flyfrm.hxx> | |||
43 | #include <frmatr.hxx> | |||
44 | #include <frmtool.hxx> | |||
45 | #include <viewopt.hxx> | |||
46 | #include <dview.hxx> | |||
47 | #include <dcontact.hxx> | |||
48 | #include <txtfrm.hxx> | |||
49 | #include <ftnfrm.hxx> | |||
50 | #include <tabfrm.hxx> | |||
51 | #include <rowfrm.hxx> | |||
52 | #include <cellfrm.hxx> | |||
53 | #include <notxtfrm.hxx> | |||
54 | #include <layact.hxx> | |||
55 | #include <pagedesc.hxx> | |||
56 | #include <ptqueue.hxx> | |||
57 | #include <noteurl.hxx> | |||
58 | #include "virtoutp.hxx" | |||
59 | #include <lineinfo.hxx> | |||
60 | #include <dbg_lay.hxx> | |||
61 | #include <docsh.hxx> | |||
62 | #include <svx/svdogrp.hxx> | |||
63 | #include <sortedobjs.hxx> | |||
64 | #include <EnhancedPDFExportHelper.hxx> | |||
65 | #include <bodyfrm.hxx> | |||
66 | #include <hffrm.hxx> | |||
67 | #include <colfrm.hxx> | |||
68 | #include <sw_primitivetypes2d.hxx> | |||
69 | #include <swfont.hxx> | |||
70 | ||||
71 | #include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx> | |||
72 | #include <svx/sdr/contact/viewobjectcontactredirector.hxx> | |||
73 | #include <svx/sdr/contact/viewobjectcontact.hxx> | |||
74 | #include <svx/sdr/contact/viewcontact.hxx> | |||
75 | #include <DocumentSettingManager.hxx> | |||
76 | #include <IDocumentDeviceAccess.hxx> | |||
77 | #include <IDocumentDrawModelAccess.hxx> | |||
78 | ||||
79 | #include <ndole.hxx> | |||
80 | #include <PostItMgr.hxx> | |||
81 | #include <FrameControlsManager.hxx> | |||
82 | #include <vcl/settings.hxx> | |||
83 | ||||
84 | #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> | |||
85 | #include <drawinglayer/processor2d/processor2dtools.hxx> | |||
86 | ||||
87 | #include <svtools/borderhelper.hxx> | |||
88 | ||||
89 | #include <bitmaps.hlst> | |||
90 | #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> | |||
91 | #include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx> | |||
92 | #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> | |||
93 | #include <drawinglayer/primitive2d/discreteshadowprimitive2d.hxx> | |||
94 | #include <drawinglayer/primitive2d/maskprimitive2d.hxx> | |||
95 | #include <drawinglayer/primitive2d/textprimitive2d.hxx> | |||
96 | #include <drawinglayer/primitive2d/textlayoutdevice.hxx> | |||
97 | #include <drawinglayer/processor2d/baseprocessor2d.hxx> | |||
98 | #include <drawinglayer/processor2d/processorfromoutputdevice.hxx> | |||
99 | #include <svx/unoapi.hxx> | |||
100 | #include <svx/svdpagv.hxx> | |||
101 | #include <svx/xfillit0.hxx> | |||
102 | #include <basegfx/matrix/b2dhommatrixtools.hxx> | |||
103 | #include <basegfx/color/bcolortools.hxx> | |||
104 | #include <basegfx/utils/b2dclipstate.hxx> | |||
105 | #include <sal/log.hxx> | |||
106 | ||||
107 | #include <memory> | |||
108 | #include <vector> | |||
109 | #include <algorithm> | |||
110 | #include <wrtsh.hxx> | |||
111 | #include <edtwin.hxx> | |||
112 | #include <view.hxx> | |||
113 | #include <paintfrm.hxx> | |||
114 | #include <textboxhelper.hxx> | |||
115 | #include <o3tl/typed_flags_set.hxx> | |||
116 | ||||
117 | #include <vcl/BitmapTools.hxx> | |||
118 | #include <comphelper/lok.hxx> | |||
119 | ||||
120 | #define COL_NOTES_SIDEPANEColor(230,230,230) Color(230,230,230) | |||
121 | #define COL_NOTES_SIDEPANE_BORDERColor(200,200,200) Color(200,200,200) | |||
122 | #define COL_NOTES_SIDEPANE_SCROLLAREAColor(230,230,220) Color(230,230,220) | |||
123 | ||||
124 | using namespace ::editeng; | |||
125 | using namespace ::com::sun::star; | |||
126 | ||||
127 | namespace { | |||
128 | ||||
129 | struct SwPaintProperties; | |||
130 | ||||
131 | //Class declaration; here because they are only used in this file | |||
132 | enum class SubColFlags { | |||
133 | Page = 0x01, //Helplines of the page | |||
134 | Tab = 0x08, //Helplines inside tables | |||
135 | Fly = 0x10, //Helplines inside fly frames | |||
136 | Sect = 0x20, //Helplines inside sections | |||
137 | }; | |||
138 | ||||
139 | } | |||
140 | ||||
141 | namespace o3tl { | |||
142 | template<> struct typed_flags<SubColFlags> : is_typed_flags<SubColFlags, 0x39> {}; | |||
143 | } | |||
144 | ||||
145 | namespace { | |||
146 | ||||
147 | // Classes collecting the border lines and help lines | |||
148 | class SwLineRect : public SwRect | |||
149 | { | |||
150 | Color aColor; | |||
151 | SvxBorderLineStyle nStyle; | |||
152 | const SwTabFrame *pTab; | |||
153 | SubColFlags nSubColor; //colorize subsidiary lines | |||
154 | bool bPainted; //already painted? | |||
155 | sal_uInt8 nLock; //To distinguish the line and the hell layer. | |||
156 | public: | |||
157 | SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderLineStyle nStyle, | |||
158 | const SwTabFrame *pT , const SubColFlags nSCol ); | |||
159 | ||||
160 | const Color& GetColor() const { return aColor;} | |||
161 | SvxBorderLineStyle GetStyle() const { return nStyle; } | |||
162 | const SwTabFrame *GetTab() const { return pTab; } | |||
163 | void SetPainted() { bPainted = true; } | |||
164 | void Lock( bool bLock ) { if ( bLock ) | |||
165 | ++nLock; | |||
166 | else if ( nLock ) | |||
167 | --nLock; | |||
168 | } | |||
169 | bool IsPainted() const { return bPainted; } | |||
170 | bool IsLocked() const { return nLock != 0; } | |||
171 | SubColFlags GetSubColor() const { return nSubColor;} | |||
172 | ||||
173 | bool MakeUnion( const SwRect &rRect, SwPaintProperties const &properties ); | |||
174 | }; | |||
175 | ||||
176 | } | |||
177 | ||||
178 | #ifdef IOS | |||
179 | static void dummy_function() | |||
180 | { | |||
181 | pid_t pid = getpid(); | |||
182 | (void) pid; | |||
183 | } | |||
184 | #endif | |||
185 | ||||
186 | namespace { | |||
187 | ||||
188 | class SwLineRects | |||
189 | { | |||
190 | public: | |||
191 | std::vector< SwLineRect > aLineRects; | |||
192 | typedef std::vector< SwLineRect >::const_iterator const_iterator; | |||
193 | typedef std::vector< SwLineRect >::iterator iterator; | |||
194 | typedef std::vector< SwLineRect >::reverse_iterator reverse_iterator; | |||
195 | typedef std::vector< SwLineRect >::size_type size_type; | |||
196 | size_t nLastCount; //avoid unnecessary cycles in PaintLines | |||
197 | SwLineRects() : nLastCount( 0 ) | |||
198 | { | |||
199 | #ifdef IOS | |||
200 | // Work around what is either a compiler bug in Xcode 5.1.1, | |||
201 | // or some unknown problem in this file. If I ifdef out this | |||
202 | // call, I get a crash in SwSubsRects::PaintSubsidiary: the | |||
203 | // address of the rLi reference variable is claimed to be | |||
204 | // 0x4000000! | |||
205 | dummy_function(); | |||
206 | #endif | |||
207 | } | |||
208 | void AddLineRect( const SwRect& rRect, const Color *pColor, const SvxBorderLineStyle nStyle, | |||
209 | const SwTabFrame *pTab, const SubColFlags nSCol, SwPaintProperties const &properties ); | |||
210 | void ConnectEdges( OutputDevice const *pOut, SwPaintProperties const &properties ); | |||
211 | void PaintLines ( OutputDevice *pOut, SwPaintProperties const &properties ); | |||
212 | void LockLines( bool bLock ); | |||
213 | ||||
214 | //Limit lines to 100 | |||
215 | bool isFull() const { return aLineRects.size()>100; } | |||
216 | }; | |||
217 | ||||
218 | class SwSubsRects : public SwLineRects | |||
219 | { | |||
220 | void RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects, SwPaintProperties const &properties ); | |||
221 | public: | |||
222 | void PaintSubsidiary( OutputDevice *pOut, const SwLineRects *pRects, SwPaintProperties const &properties ); | |||
223 | }; | |||
224 | ||||
225 | class BorderLines | |||
226 | { | |||
227 | drawinglayer::primitive2d::Primitive2DContainer m_Lines; | |||
228 | public: | |||
229 | void AddBorderLines(const drawinglayer::primitive2d::Primitive2DContainer& rContainer); | |||
230 | drawinglayer::primitive2d::Primitive2DContainer GetBorderLines_Clear() | |||
231 | { | |||
232 | drawinglayer::primitive2d::Primitive2DContainer lines; | |||
233 | lines.swap(m_Lines); | |||
234 | return lines; | |||
235 | } | |||
236 | }; | |||
237 | ||||
238 | } | |||
239 | ||||
240 | // Default zoom factor | |||
241 | const double aEdgeScale = 0.5; | |||
242 | ||||
243 | //To optimize the expensive RetouchColor determination | |||
244 | Color aGlobalRetoucheColor; | |||
245 | ||||
246 | namespace sw | |||
247 | { | |||
248 | Color* GetActiveRetoucheColor() | |||
249 | { | |||
250 | return &aGlobalRetoucheColor; | |||
251 | } | |||
252 | } | |||
253 | ||||
254 | namespace { | |||
255 | ||||
256 | /** | |||
257 | * Container for static properties | |||
258 | */ | |||
259 | struct SwPaintProperties { | |||
260 | // Only repaint the Fly content as well as the background of the Fly content if | |||
261 | // a metafile is taken of the Fly. | |||
262 | bool bSFlyMetafile; | |||
263 | VclPtr<OutputDevice> pSFlyMetafileOut; | |||
264 | SwViewShell *pSGlobalShell; | |||
265 | ||||
266 | // Retouch for transparent Flys is done by the background of the Flys. | |||
267 | // The Fly itself should certainly not be spared out. See PaintSwFrameBackground and | |||
268 | // lcl_SubtractFlys() | |||
269 | SwFlyFrame *pSRetoucheFly; | |||
270 | SwFlyFrame *pSRetoucheFly2; | |||
271 | SwFlyFrame *pSFlyOnlyDraw; | |||
272 | ||||
273 | // The borders will be collected in pSLines during the Paint and later | |||
274 | // possibly merge them. | |||
275 | // The help lines will be collected and merged in gProp.pSSubsLines. These will | |||
276 | // be compared with pSLines before the work in order to avoid help lines | |||
277 | // to hide borders. | |||
278 | std::unique_ptr<BorderLines> pBLines; | |||
279 | std::unique_ptr<SwLineRects> pSLines; | |||
280 | std::unique_ptr<SwSubsRects> pSSubsLines; | |||
281 | ||||
282 | // global variable for sub-lines of body, header, footer, section and footnote frames. | |||
283 | std::unique_ptr<SwSubsRects> pSSpecSubsLines; | |||
284 | SfxProgress *pSProgress; | |||
285 | ||||
286 | // Sizes of a pixel and the corresponding halves. Will be reset when | |||
287 | // entering SwRootFrame::PaintSwFrame | |||
288 | long nSPixelSzW; | |||
289 | long nSPixelSzH; | |||
290 | long nSHalfPixelSzW; | |||
291 | long nSHalfPixelSzH; | |||
292 | long nSMinDistPixelW; | |||
293 | long nSMinDistPixelH; | |||
294 | ||||
295 | Color aSGlobalRetoucheColor; | |||
296 | ||||
297 | // Current zoom factor | |||
298 | double aSScaleX; | |||
299 | double aSScaleY; | |||
300 | ||||
301 | SwPaintProperties() | |||
302 | : bSFlyMetafile(false) | |||
303 | , pSFlyMetafileOut(nullptr) | |||
304 | , pSGlobalShell(nullptr) | |||
305 | , pSRetoucheFly(nullptr) | |||
306 | , pSRetoucheFly2(nullptr) | |||
307 | , pSFlyOnlyDraw(nullptr) | |||
308 | , pSProgress(nullptr) | |||
309 | , nSPixelSzW(0) | |||
310 | , nSPixelSzH(0) | |||
311 | , nSHalfPixelSzW(0) | |||
312 | , nSHalfPixelSzH(0) | |||
313 | , nSMinDistPixelW(0) | |||
314 | , nSMinDistPixelH(0) | |||
315 | , aSScaleX(1) | |||
316 | , aSScaleY(1) | |||
317 | { | |||
318 | } | |||
319 | ||||
320 | }; | |||
321 | ||||
322 | } | |||
323 | ||||
324 | static SwPaintProperties gProp; | |||
325 | ||||
326 | static bool isSubsidiaryLinesFlysEnabled() | |||
327 | { | |||
328 | return !gProp.pSGlobalShell->GetViewOptions()->IsPagePreview() && | |||
329 | !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() && | |||
330 | !gProp.pSGlobalShell->GetViewOptions()->IsFormView() && | |||
331 | SwViewOption::IsObjectBoundaries(); | |||
332 | } | |||
333 | //other subsidiary lines enabled? | |||
334 | static bool isSubsidiaryLinesEnabled() | |||
335 | { | |||
336 | return !gProp.pSGlobalShell->GetViewOptions()->IsPagePreview() && | |||
337 | !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() && | |||
338 | !gProp.pSGlobalShell->GetViewOptions()->IsFormView() && | |||
339 | !gProp.pSGlobalShell->GetViewOptions()->IsWhitespaceHidden() && | |||
340 | SwViewOption::IsDocBoundaries(); | |||
341 | } | |||
342 | //subsidiary lines for sections | |||
343 | static bool isSubsidiaryLinesForSectionsEnabled() | |||
344 | { | |||
345 | return !gProp.pSGlobalShell->GetViewOptions()->IsPagePreview() && | |||
346 | !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() && | |||
347 | !gProp.pSGlobalShell->GetViewOptions()->IsFormView() && | |||
348 | SwViewOption::IsSectionBoundaries(); | |||
349 | } | |||
350 | ||||
351 | ||||
352 | namespace { | |||
353 | ||||
354 | bool isTableBoundariesEnabled() | |||
355 | { | |||
356 | if (!gProp.pSGlobalShell->GetViewOptions()->IsTable()) | |||
357 | return false; | |||
358 | ||||
359 | if (gProp.pSGlobalShell->GetViewOptions()->IsPagePreview()) | |||
360 | return false; | |||
361 | ||||
362 | if (gProp.pSGlobalShell->GetViewOptions()->IsReadonly()) | |||
363 | return false; | |||
364 | ||||
365 | if (gProp.pSGlobalShell->GetViewOptions()->IsFormView()) | |||
366 | return false; | |||
367 | ||||
368 | return SwViewOption::IsTableBoundaries(); | |||
369 | } | |||
370 | ||||
371 | } | |||
372 | ||||
373 | /** | |||
374 | * Set borders alignment statics | |||
375 | * Adjustment for 'small' twip-to-pixel relations: | |||
376 | * For 'small' twip-to-pixel relations (less than 2:1) | |||
377 | * values of <gProp.nSHalfPixelSzW> and <gProp.nSHalfPixelSzH> are set to ZERO | |||
378 | */ | |||
379 | void SwCalcPixStatics( vcl::RenderContext const *pOut ) | |||
380 | { | |||
381 | // determine 'small' twip-to-pixel relation | |||
382 | bool bSmallTwipToPxRelW = false; | |||
383 | bool bSmallTwipToPxRelH = false; | |||
384 | { | |||
385 | Size aCheckTwipToPxRelSz( pOut->PixelToLogic( Size( 100, 100 )) ); | |||
386 | if ( (aCheckTwipToPxRelSz.Width()/100.0) < 2.0 ) | |||
387 | { | |||
388 | bSmallTwipToPxRelW = true; | |||
389 | } | |||
390 | if ( (aCheckTwipToPxRelSz.Height()/100.0) < 2.0 ) | |||
391 | { | |||
392 | bSmallTwipToPxRelH = true; | |||
393 | } | |||
394 | } | |||
395 | ||||
396 | Size aSz( pOut->PixelToLogic( Size( 1,1 )) ); | |||
397 | ||||
398 | gProp.nSPixelSzW = aSz.Width(); | |||
399 | if( !gProp.nSPixelSzW ) | |||
400 | gProp.nSPixelSzW = 1; | |||
401 | gProp.nSPixelSzH = aSz.Height(); | |||
402 | if( !gProp.nSPixelSzH ) | |||
403 | gProp.nSPixelSzH = 1; | |||
404 | ||||
405 | // consider 'small' twip-to-pixel relations | |||
406 | if ( !bSmallTwipToPxRelW ) | |||
407 | { | |||
408 | gProp.nSHalfPixelSzW = gProp.nSPixelSzW / 2 + 1; | |||
409 | } | |||
410 | else | |||
411 | { | |||
412 | gProp.nSHalfPixelSzW = 0; | |||
413 | } | |||
414 | // consider 'small' twip-to-pixel relations | |||
415 | if ( !bSmallTwipToPxRelH ) | |||
416 | { | |||
417 | gProp.nSHalfPixelSzH = gProp.nSPixelSzH / 2 + 1; | |||
418 | } | |||
419 | else | |||
420 | { | |||
421 | gProp.nSHalfPixelSzH = 0; | |||
422 | } | |||
423 | ||||
424 | gProp.nSMinDistPixelW = gProp.nSPixelSzW * 2 + 1; | |||
425 | gProp.nSMinDistPixelH = gProp.nSPixelSzH * 2 + 1; | |||
426 | ||||
427 | const MapMode &rMap = pOut->GetMapMode(); | |||
428 | gProp.aSScaleX = double(rMap.GetScaleX()); | |||
429 | gProp.aSScaleY = double(rMap.GetScaleY()); | |||
430 | } | |||
431 | ||||
432 | namespace { | |||
433 | ||||
434 | /** | |||
435 | * To be able to save the statics so the paint is more or less reentrant | |||
436 | */ | |||
437 | class SwSavePaintStatics : public SwPaintProperties | |||
438 | { | |||
439 | public: | |||
440 | SwSavePaintStatics(); | |||
441 | ~SwSavePaintStatics(); | |||
442 | }; | |||
443 | ||||
444 | } | |||
445 | ||||
446 | SwSavePaintStatics::SwSavePaintStatics() | |||
447 | { | |||
448 | // Saving globales | |||
449 | bSFlyMetafile = gProp.bSFlyMetafile; | |||
450 | pSGlobalShell = gProp.pSGlobalShell; | |||
451 | pSFlyMetafileOut = gProp.pSFlyMetafileOut; | |||
452 | pSRetoucheFly = gProp.pSRetoucheFly; | |||
453 | pSRetoucheFly2 = gProp.pSRetoucheFly2; | |||
454 | pSFlyOnlyDraw = gProp.pSFlyOnlyDraw; | |||
455 | pBLines = std::move(gProp.pBLines); | |||
456 | pSLines = std::move(gProp.pSLines); | |||
457 | pSSubsLines = std::move(gProp.pSSubsLines); | |||
458 | pSSpecSubsLines = std::move(gProp.pSSpecSubsLines); | |||
459 | pSProgress = gProp.pSProgress; | |||
460 | nSPixelSzW = gProp.nSPixelSzW; | |||
461 | nSPixelSzH = gProp.nSPixelSzH; | |||
462 | nSHalfPixelSzW = gProp.nSHalfPixelSzW; | |||
463 | nSHalfPixelSzH = gProp.nSHalfPixelSzH; | |||
464 | nSMinDistPixelW = gProp.nSMinDistPixelW; | |||
465 | nSMinDistPixelH = gProp.nSMinDistPixelH ; | |||
466 | aSGlobalRetoucheColor = aGlobalRetoucheColor; | |||
467 | aSScaleX = gProp.aSScaleX; | |||
468 | aSScaleY = gProp.aSScaleY; | |||
469 | ||||
470 | // Restoring globales to default | |||
471 | gProp.bSFlyMetafile = false; | |||
472 | gProp.pSFlyMetafileOut = nullptr; | |||
473 | gProp.pSRetoucheFly = nullptr; | |||
474 | gProp.pSRetoucheFly2 = nullptr; | |||
475 | gProp.nSPixelSzW = gProp.nSPixelSzH = | |||
476 | gProp.nSHalfPixelSzW = gProp.nSHalfPixelSzH = | |||
477 | gProp.nSMinDistPixelW = gProp.nSMinDistPixelH = 0; | |||
478 | gProp.aSScaleX = gProp.aSScaleY = 1.0; | |||
479 | gProp.pSProgress = nullptr; | |||
480 | } | |||
481 | ||||
482 | SwSavePaintStatics::~SwSavePaintStatics() | |||
483 | { | |||
484 | // Restoring globales to saved one | |||
485 | gProp.pSGlobalShell = pSGlobalShell; | |||
486 | gProp.bSFlyMetafile = bSFlyMetafile; | |||
487 | gProp.pSFlyMetafileOut = pSFlyMetafileOut; | |||
488 | gProp.pSRetoucheFly = pSRetoucheFly; | |||
489 | gProp.pSRetoucheFly2 = pSRetoucheFly2; | |||
490 | gProp.pSFlyOnlyDraw = pSFlyOnlyDraw; | |||
491 | gProp.pBLines = std::move(pBLines); | |||
492 | gProp.pSLines = std::move(pSLines); | |||
493 | gProp.pSSubsLines = std::move(pSSubsLines); | |||
494 | gProp.pSSpecSubsLines = std::move(pSSpecSubsLines); | |||
495 | gProp.pSProgress = pSProgress; | |||
496 | gProp.nSPixelSzW = nSPixelSzW; | |||
497 | gProp.nSPixelSzH = nSPixelSzH; | |||
498 | gProp.nSHalfPixelSzW = nSHalfPixelSzW; | |||
499 | gProp.nSHalfPixelSzH = nSHalfPixelSzH; | |||
500 | gProp.nSMinDistPixelW = nSMinDistPixelW; | |||
501 | gProp.nSMinDistPixelH = nSMinDistPixelH; | |||
502 | aGlobalRetoucheColor = aSGlobalRetoucheColor; | |||
503 | gProp.aSScaleX = aSScaleX; | |||
504 | gProp.aSScaleY = aSScaleY; | |||
505 | } | |||
506 | ||||
507 | void BorderLines::AddBorderLines(const drawinglayer::primitive2d::Primitive2DContainer& rContainer) | |||
508 | { | |||
509 | if(!rContainer.empty()) | |||
510 | { | |||
511 | m_Lines.append(rContainer); | |||
512 | } | |||
513 | } | |||
514 | ||||
515 | SwLineRect::SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderLineStyle nStyl, | |||
516 | const SwTabFrame *pT, const SubColFlags nSCol ) : | |||
517 | SwRect( rRect ), | |||
518 | nStyle( nStyl ), | |||
519 | pTab( pT ), | |||
520 | nSubColor( nSCol ), | |||
521 | bPainted( false ), | |||
522 | nLock( 0 ) | |||
523 | { | |||
524 | if ( pCol != nullptr ) | |||
525 | aColor = *pCol; | |||
526 | } | |||
527 | ||||
528 | bool SwLineRect::MakeUnion( const SwRect &rRect, SwPaintProperties const & properties) | |||
529 | { | |||
530 | // It has already been tested outside, whether the rectangles have | |||
531 | // the same orientation (horizontal or vertical), color, etc. | |||
532 | if ( Height() > Width() ) //Vertical line | |||
533 | { | |||
534 | if ( Left() == rRect.Left() && Width() == rRect.Width() ) | |||
535 | { | |||
536 | // Merge when there is no gap between the lines | |||
537 | const long nAdd = properties.nSPixelSzW + properties.nSHalfPixelSzW; | |||
538 | if ( Bottom() + nAdd >= rRect.Top() && | |||
539 | Top() - nAdd <= rRect.Bottom() ) | |||
540 | { | |||
541 | Bottom( std::max( Bottom(), rRect.Bottom() ) ); | |||
542 | Top ( std::min( Top(), rRect.Top() ) ); | |||
543 | return true; | |||
544 | } | |||
545 | } | |||
546 | } | |||
547 | else | |||
548 | { | |||
549 | if ( Top() == rRect.Top() && Height() == rRect.Height() ) | |||
550 | { | |||
551 | // Merge when there is no gap between the lines | |||
552 | const long nAdd = properties.nSPixelSzW + properties.nSHalfPixelSzW; | |||
553 | if ( Right() + nAdd >= rRect.Left() && | |||
554 | Left() - nAdd <= rRect.Right() ) | |||
555 | { | |||
556 | Right( std::max( Right(), rRect.Right() ) ); | |||
557 | Left ( std::min( Left(), rRect.Left() ) ); | |||
558 | return true; | |||
559 | } | |||
560 | } | |||
561 | } | |||
562 | return false; | |||
563 | } | |||
564 | ||||
565 | void SwLineRects::AddLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderLineStyle nStyle, | |||
566 | const SwTabFrame *pTab, const SubColFlags nSCol, SwPaintProperties const & properties ) | |||
567 | { | |||
568 | // Loop backwards because lines which can be combined, can usually be painted | |||
569 | // in the same context | |||
570 | for (reverse_iterator it = aLineRects.rbegin(); it != aLineRects.rend(); | |||
571 | ++it) | |||
572 | { | |||
573 | SwLineRect &rLRect = *it; | |||
574 | // Test for the orientation, color, table | |||
575 | if ( rLRect.GetTab() == pTab && | |||
576 | !rLRect.IsPainted() && rLRect.GetSubColor() == nSCol && | |||
577 | (rLRect.Height() > rLRect.Width()) == (rRect.Height() > rRect.Width()) && | |||
578 | (pCol && rLRect.GetColor() == *pCol) ) | |||
579 | { | |||
580 | if ( rLRect.MakeUnion( rRect, properties ) ) | |||
581 | return; | |||
582 | } | |||
583 | } | |||
584 | aLineRects.emplace_back( rRect, pCol, nStyle, pTab, nSCol ); | |||
585 | } | |||
586 | ||||
587 | void SwLineRects::ConnectEdges( OutputDevice const *pOut, SwPaintProperties const & properties ) | |||
588 | { | |||
589 | if ( pOut->GetOutDevType() != OUTDEV_PRINTER ) | |||
590 | { | |||
591 | // I'm not doing anything for a too small zoom | |||
592 | if ( properties.aSScaleX < aEdgeScale || properties.aSScaleY < aEdgeScale ) | |||
593 | return; | |||
594 | } | |||
595 | ||||
596 | static const long nAdd = 20; | |||
597 | ||||
598 | std::vector<SwLineRect*> aCheck; | |||
599 | ||||
600 | for (size_t i = 0; i < aLineRects.size(); ++i) | |||
601 | { | |||
602 | SwLineRect &rL1 = aLineRects[i]; | |||
603 | if ( !rL1.GetTab() || rL1.IsPainted() || rL1.IsLocked() ) | |||
604 | continue; | |||
605 | ||||
606 | aCheck.clear(); | |||
607 | ||||
608 | const bool bVert = rL1.Height() > rL1.Width(); | |||
609 | long nL1a, nL1b, nL1c, nL1d; | |||
610 | ||||
611 | if ( bVert ) | |||
612 | { | |||
613 | nL1a = rL1.Top(); nL1b = rL1.Left(); | |||
614 | nL1c = rL1.Right(); nL1d = rL1.Bottom(); | |||
615 | } | |||
616 | else | |||
617 | { | |||
618 | nL1a = rL1.Left(); nL1b = rL1.Top(); | |||
619 | nL1c = rL1.Bottom(); nL1d = rL1.Right(); | |||
620 | } | |||
621 | ||||
622 | // Collect all lines to possibly link with i1 | |||
623 | for (iterator it2 = aLineRects.begin(); it2 != aLineRects.end(); ++it2) | |||
624 | { | |||
625 | SwLineRect &rL2 = *it2; | |||
626 | if ( rL2.GetTab() != rL1.GetTab() || | |||
627 | rL2.IsPainted() || | |||
628 | rL2.IsLocked() || | |||
629 | (bVert == (rL2.Height() > rL2.Width())) ) | |||
630 | continue; | |||
631 | ||||
632 | long nL2a, nL2b, nL2c, nL2d; | |||
633 | if ( bVert ) | |||
634 | { | |||
635 | nL2a = rL2.Top(); nL2b = rL2.Left(); | |||
636 | nL2c = rL2.Right(); nL2d = rL2.Bottom(); | |||
637 | } | |||
638 | else | |||
639 | { | |||
640 | nL2a = rL2.Left(); nL2b = rL2.Top(); | |||
641 | nL2c = rL2.Bottom(); nL2d = rL2.Right(); | |||
642 | } | |||
643 | ||||
644 | if ( (nL1a - nAdd < nL2d && nL1d + nAdd > nL2a) && | |||
645 | ((nL1b > nL2b && nL1c < nL2c) || | |||
646 | (nL1c >= nL2c && nL1b - nAdd < nL2c) || | |||
647 | (nL1b <= nL2b && nL1c + nAdd > nL2b)) ) | |||
648 | { | |||
649 | aCheck.push_back( &rL2 ); | |||
650 | } | |||
651 | } | |||
652 | if ( aCheck.size() < 2 ) | |||
653 | continue; | |||
654 | ||||
655 | bool bRemove = false; | |||
656 | ||||
657 | // For each line test all following ones. | |||
658 | for ( size_t k = 0; !bRemove && k < aCheck.size(); ++k ) | |||
659 | { | |||
660 | SwLineRect &rR1 = *aCheck[k]; | |||
661 | ||||
662 | for ( size_t k2 = k+1; !bRemove && k2 < aCheck.size(); ++k2 ) | |||
663 | { | |||
664 | SwLineRect &rR2 = *aCheck[k2]; | |||
665 | if ( bVert ) | |||
666 | { | |||
667 | SwLineRect *pLA = nullptr; | |||
668 | SwLineRect *pLB = nullptr; | |||
669 | if ( rR1.Top() < rR2.Top() ) | |||
670 | { | |||
671 | pLA = &rR1; pLB = &rR2; | |||
672 | } | |||
673 | else if ( rR1.Top() > rR2.Top() ) | |||
674 | { | |||
675 | pLA = &rR2; pLB = &rR1; | |||
676 | } | |||
677 | // are k1 and k2 describing a double line? | |||
678 | if ( pLA && pLA->Bottom() + 60 > pLB->Top() ) | |||
679 | { | |||
680 | if ( rL1.Top() < pLA->Top() ) | |||
681 | { | |||
682 | if ( rL1.Bottom() == pLA->Bottom() ) | |||
683 | continue; //Small mistake (where?) | |||
684 | ||||
685 | SwRect aIns( rL1 ); | |||
686 | aIns.Bottom( pLA->Bottom() ); | |||
687 | if ( !rL1.IsInside( aIns ) ) | |||
688 | continue; | |||
689 | aLineRects.emplace_back( aIns, &rL1.GetColor(), | |||
690 | SvxBorderLineStyle::SOLID, | |||
691 | rL1.GetTab(), SubColFlags::Tab ); | |||
692 | if ( isFull() ) | |||
693 | { | |||
694 | --i; | |||
695 | k = aCheck.size(); | |||
696 | break; | |||
697 | } | |||
698 | } | |||
699 | ||||
700 | if ( rL1.Bottom() > pLB->Bottom() ) | |||
701 | rL1.Top( pLB->Top() ); // extend i1 on the top | |||
702 | else | |||
703 | bRemove = true; //stopping, remove i1 | |||
704 | } | |||
705 | } | |||
706 | else | |||
707 | { | |||
708 | SwLineRect *pLA = nullptr; | |||
709 | SwLineRect *pLB = nullptr; | |||
710 | if ( rR1.Left() < rR2.Left() ) | |||
711 | { | |||
712 | pLA = &rR1; pLB = &rR2; | |||
713 | } | |||
714 | else if ( rR1.Left() > rR2.Left() ) | |||
715 | { | |||
716 | pLA = &rR2; pLB = &rR1; | |||
717 | } | |||
718 | // Is it double line? | |||
719 | if ( pLA && pLA->Right() + 60 > pLB->Left() ) | |||
720 | { | |||
721 | if ( rL1.Left() < pLA->Left() ) | |||
722 | { | |||
723 | if ( rL1.Right() == pLA->Right() ) | |||
724 | continue; //small error | |||
725 | ||||
726 | SwRect aIns( rL1 ); | |||
727 | aIns.Right( pLA->Right() ); | |||
728 | if ( !rL1.IsInside( aIns ) ) | |||
729 | continue; | |||
730 | aLineRects.emplace_back( aIns, &rL1.GetColor(), | |||
731 | SvxBorderLineStyle::SOLID, | |||
732 | rL1.GetTab(), SubColFlags::Tab ); | |||
733 | if ( isFull() ) | |||
734 | { | |||
735 | --i; | |||
736 | k = aCheck.size(); | |||
737 | break; | |||
738 | } | |||
739 | } | |||
740 | if ( rL1.Right() > pLB->Right() ) | |||
741 | rL1.Left( pLB->Left() ); | |||
742 | else | |||
743 | bRemove = true; | |||
744 | } | |||
745 | } | |||
746 | } | |||
747 | } | |||
748 | if ( bRemove ) | |||
749 | { | |||
750 | aLineRects.erase(aLineRects.begin() + i); | |||
751 | --i; | |||
752 | } | |||
753 | } | |||
754 | } | |||
755 | ||||
756 | void SwSubsRects::RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects, SwPaintProperties const & properties ) | |||
757 | { | |||
758 | // All help lines that are covered by any border will be removed or split | |||
759 | for (size_t i = 0; i < aLineRects.size(); ++i) | |||
760 | { | |||
761 | // get a copy instead of a reference, because an <insert> may destroy | |||
762 | // the object due to a necessary array resize. | |||
763 | const SwLineRect aSubsLineRect(aLineRects[i]); | |||
764 | ||||
765 | // add condition <aSubsLineRect.IsLocked()> in order to consider only | |||
766 | // border lines, which are *not* locked. | |||
767 | if ( aSubsLineRect.IsPainted() || | |||
768 | aSubsLineRect.IsLocked() ) | |||
769 | continue; | |||
770 | ||||
771 | const bool bVerticalSubs = aSubsLineRect.Height() > aSubsLineRect.Width(); | |||
772 | SwRect aSubsRect( aSubsLineRect ); | |||
773 | if ( bVerticalSubs ) | |||
774 | { | |||
775 | aSubsRect.AddLeft ( - (properties.nSPixelSzW+properties.nSHalfPixelSzW) ); | |||
776 | aSubsRect.AddRight ( properties.nSPixelSzW+properties.nSHalfPixelSzW ); | |||
777 | } | |||
778 | else | |||
779 | { | |||
780 | aSubsRect.AddTop ( - (properties.nSPixelSzH+properties.nSHalfPixelSzH) ); | |||
781 | aSubsRect.AddBottom( properties.nSPixelSzH+properties.nSHalfPixelSzH ); | |||
782 | } | |||
783 | for (const_iterator itK = rRects.aLineRects.begin(); itK != rRects.aLineRects.end(); ++itK) | |||
784 | { | |||
785 | const SwLineRect &rLine = *itK; | |||
786 | ||||
787 | // do *not* consider painted or locked border lines. | |||
788 | // #i1837# - locked border lines have to be considered. | |||
789 | if ( rLine.IsLocked () ) | |||
790 | continue; | |||
791 | ||||
792 | if ( !bVerticalSubs == ( rLine.Height() > rLine.Width() ) ) //same direction? | |||
793 | continue; | |||
794 | ||||
795 | if ( aSubsRect.IsOver( rLine ) ) | |||
796 | { | |||
797 | if ( bVerticalSubs ) // Vertical? | |||
798 | { | |||
799 | if ( aSubsRect.Left() <= rLine.Right() && | |||
800 | aSubsRect.Right() >= rLine.Left() ) | |||
801 | { | |||
802 | long nTmp = rLine.Top()-(properties.nSPixelSzH+1); | |||
803 | if ( aSubsLineRect.Top() < nTmp ) | |||
804 | { | |||
805 | SwRect aNewSubsRect( aSubsLineRect ); | |||
806 | aNewSubsRect.Bottom( nTmp ); | |||
807 | aLineRects.emplace_back( aNewSubsRect, nullptr, aSubsLineRect.GetStyle(), nullptr, | |||
808 | aSubsLineRect.GetSubColor() ); | |||
809 | } | |||
810 | nTmp = rLine.Bottom()+properties.nSPixelSzH+1; | |||
811 | if ( aSubsLineRect.Bottom() > nTmp ) | |||
812 | { | |||
813 | SwRect aNewSubsRect( aSubsLineRect ); | |||
814 | aNewSubsRect.Top( nTmp ); | |||
815 | aLineRects.emplace_back( aNewSubsRect, nullptr, aSubsLineRect.GetStyle(), nullptr, | |||
816 | aSubsLineRect.GetSubColor() ); | |||
817 | } | |||
818 | aLineRects.erase(aLineRects.begin() + i); | |||
819 | --i; | |||
820 | break; | |||
821 | } | |||
822 | } | |||
823 | else // Horizontal | |||
824 | { | |||
825 | if ( aSubsRect.Top() <= rLine.Bottom() && | |||
826 | aSubsRect.Bottom() >= rLine.Top() ) | |||
827 | { | |||
828 | long nTmp = rLine.Left()-(properties.nSPixelSzW+1); | |||
829 | if ( aSubsLineRect.Left() < nTmp ) | |||
830 | { | |||
831 | SwRect aNewSubsRect( aSubsLineRect ); | |||
832 | aNewSubsRect.Right( nTmp ); | |||
833 | aLineRects.emplace_back( aNewSubsRect, nullptr, aSubsLineRect.GetStyle(), nullptr, | |||
834 | aSubsLineRect.GetSubColor() ); | |||
835 | } | |||
836 | nTmp = rLine.Right()+properties.nSPixelSzW+1; | |||
837 | if ( aSubsLineRect.Right() > nTmp ) | |||
838 | { | |||
839 | SwRect aNewSubsRect( aSubsLineRect ); | |||
840 | aNewSubsRect.Left( nTmp ); | |||
841 | aLineRects.emplace_back( aNewSubsRect, nullptr, aSubsLineRect.GetStyle(), nullptr, | |||
842 | aSubsLineRect.GetSubColor() ); | |||
843 | } | |||
844 | aLineRects.erase(aLineRects.begin() + i); | |||
845 | --i; | |||
846 | break; | |||
847 | } | |||
848 | } | |||
849 | } | |||
850 | } | |||
851 | } | |||
852 | } | |||
853 | ||||
854 | void SwLineRects::LockLines( bool bLock ) | |||
855 | { | |||
856 | for (SwLineRect& rLRect : aLineRects) | |||
857 | rLRect.Lock( bLock ); | |||
858 | } | |||
859 | ||||
860 | static void lcl_DrawDashedRect( OutputDevice * pOut, SwLineRect const & rLRect ) | |||
861 | { | |||
862 | long startX = rLRect.Left( ), endX; | |||
863 | long startY = rLRect.Top( ), endY; | |||
864 | ||||
865 | // Discriminate vertically stretched rect from horizontally stretched | |||
866 | // and restrict minimum nHalfLWidth to 1 | |||
867 | long nHalfLWidth = std::max( static_cast<long>(std::min( rLRect.Width( ), rLRect.Height( ) ) / 2), 1L ); | |||
868 | ||||
869 | if ( rLRect.Height( ) > rLRect.Width( ) ) | |||
870 | { | |||
871 | startX += nHalfLWidth; | |||
872 | endX = startX; | |||
873 | endY = startY + rLRect.Height( ); | |||
874 | } | |||
875 | else | |||
876 | { | |||
877 | startY += nHalfLWidth; | |||
878 | endY = startY; | |||
879 | endX = startX + rLRect.Width( ); | |||
880 | } | |||
881 | ||||
882 | svtools::DrawLine( *pOut, Point( startX, startY ), Point( endX, endY ), | |||
883 | sal_uInt32( nHalfLWidth * 2 ), rLRect.GetStyle( ) ); | |||
884 | } | |||
885 | ||||
886 | void SwLineRects::PaintLines( OutputDevice *pOut, SwPaintProperties const &properties ) | |||
887 | { | |||
888 | // Paint the borders. Sadly two passes are needed. | |||
889 | // Once for the inside and once for the outside edges of tables | |||
890 | if ( aLineRects.size() == nLastCount ) | |||
891 | return; | |||
892 | ||||
893 | // #i16816# tagged pdf support | |||
894 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pOut ); | |||
895 | ||||
896 | pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR ); | |||
897 | pOut->SetFillColor(); | |||
898 | pOut->SetLineColor(); | |||
899 | ConnectEdges( pOut, properties ); | |||
900 | const Color *pLast = nullptr; | |||
901 | ||||
902 | bool bPaint2nd = false; | |||
903 | size_t nMinCount = aLineRects.size(); | |||
904 | ||||
905 | for ( size_t i = 0; i < aLineRects.size(); ++i ) | |||
906 | { | |||
907 | SwLineRect &rLRect = aLineRects[i]; | |||
908 | ||||
909 | if ( rLRect.IsPainted() ) | |||
910 | continue; | |||
911 | ||||
912 | if ( rLRect.IsLocked() ) | |||
913 | { | |||
914 | nMinCount = std::min( nMinCount, i ); | |||
915 | continue; | |||
916 | } | |||
917 | ||||
918 | // Paint it now or in the second pass? | |||
919 | bool bPaint = true; | |||
920 | if ( rLRect.GetTab() ) | |||
921 | { | |||
922 | if ( rLRect.Height() > rLRect.Width() ) | |||
923 | { | |||
924 | // Vertical edge, overlapping with the table edge? | |||
925 | SwTwips nLLeft = rLRect.Left() - 30, | |||
926 | nLRight = rLRect.Right() + 30, | |||
927 | nTLeft = rLRect.GetTab()->getFrameArea().Left() + rLRect.GetTab()->getFramePrintArea().Left(), | |||
928 | nTRight = rLRect.GetTab()->getFrameArea().Left() + rLRect.GetTab()->getFramePrintArea().Right(); | |||
929 | if ( (nTLeft >= nLLeft && nTLeft <= nLRight) || | |||
930 | (nTRight>= nLLeft && nTRight<= nLRight) ) | |||
931 | bPaint = false; | |||
932 | } | |||
933 | else | |||
934 | { | |||
935 | // Horizontal edge, overlapping with the table edge? | |||
936 | SwTwips nLTop = rLRect.Top() - 30, | |||
937 | nLBottom = rLRect.Bottom() + 30, | |||
938 | nTTop = rLRect.GetTab()->getFrameArea().Top() + rLRect.GetTab()->getFramePrintArea().Top(), | |||
939 | nTBottom = rLRect.GetTab()->getFrameArea().Top() + rLRect.GetTab()->getFramePrintArea().Bottom(); | |||
940 | if ( (nTTop >= nLTop && nTTop <= nLBottom) || | |||
941 | (nTBottom >= nLTop && nTBottom <= nLBottom) ) | |||
942 | bPaint = false; | |||
943 | } | |||
944 | } | |||
945 | if ( bPaint ) | |||
946 | { | |||
947 | if ( !pLast || *pLast != rLRect.GetColor() ) | |||
948 | { | |||
949 | pLast = &rLRect.GetColor(); | |||
950 | ||||
951 | DrawModeFlags nOldDrawMode = pOut->GetDrawMode(); | |||
952 | if( properties.pSGlobalShell->GetWin() && | |||
953 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
954 | pOut->SetDrawMode( DrawModeFlags::Default ); | |||
955 | ||||
956 | pOut->SetLineColor( *pLast ); | |||
957 | pOut->SetFillColor( *pLast ); | |||
958 | pOut->SetDrawMode( nOldDrawMode ); | |||
959 | } | |||
960 | ||||
961 | if( !rLRect.IsEmpty() ) | |||
962 | lcl_DrawDashedRect( pOut, rLRect ); | |||
963 | rLRect.SetPainted(); | |||
964 | } | |||
965 | else | |||
966 | bPaint2nd = true; | |||
967 | } | |||
968 | if ( bPaint2nd ) | |||
969 | { | |||
970 | for ( size_t i = 0; i < aLineRects.size(); ++i ) | |||
971 | { | |||
972 | SwLineRect &rLRect = aLineRects[i]; | |||
973 | if ( rLRect.IsPainted() ) | |||
974 | continue; | |||
975 | ||||
976 | if ( rLRect.IsLocked() ) | |||
977 | { | |||
978 | nMinCount = std::min( nMinCount, i ); | |||
979 | continue; | |||
980 | } | |||
981 | ||||
982 | if ( !pLast || *pLast != rLRect.GetColor() ) | |||
983 | { | |||
984 | pLast = &rLRect.GetColor(); | |||
985 | ||||
986 | DrawModeFlags nOldDrawMode = pOut->GetDrawMode(); | |||
987 | if( properties.pSGlobalShell->GetWin() && | |||
988 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
989 | { | |||
990 | pOut->SetDrawMode( DrawModeFlags::Default ); | |||
991 | } | |||
992 | ||||
993 | pOut->SetFillColor( *pLast ); | |||
994 | pOut->SetDrawMode( nOldDrawMode ); | |||
995 | } | |||
996 | if( !rLRect.IsEmpty() ) | |||
997 | lcl_DrawDashedRect( pOut, rLRect ); | |||
998 | rLRect.SetPainted(); | |||
999 | } | |||
1000 | } | |||
1001 | nLastCount = nMinCount; | |||
1002 | pOut->Pop(); | |||
1003 | ||||
1004 | } | |||
1005 | ||||
1006 | void SwSubsRects::PaintSubsidiary( OutputDevice *pOut, | |||
1007 | const SwLineRects *pRects, | |||
1008 | SwPaintProperties const & properties ) | |||
1009 | { | |||
1010 | if ( aLineRects.empty() ) | |||
1011 | return; | |||
1012 | ||||
1013 | // #i16816# tagged pdf support | |||
1014 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pOut ); | |||
1015 | ||||
1016 | // Remove all help line that are almost covered (tables) | |||
1017 | for (size_type i = 0; i != aLineRects.size(); ++i) | |||
1018 | { | |||
1019 | SwLineRect &rLi = aLineRects[i]; | |||
1020 | const bool bVerticalSubs = rLi.Height() > rLi.Width(); | |||
1021 | ||||
1022 | for (size_type k = i + 1; k != aLineRects.size(); ++k) | |||
1023 | { | |||
1024 | SwLineRect &rLk = aLineRects[k]; | |||
1025 | if ( rLi.SSize() == rLk.SSize() ) | |||
1026 | { | |||
1027 | if ( bVerticalSubs == ( rLk.Height() > rLk.Width() ) ) | |||
1028 | { | |||
1029 | if ( bVerticalSubs ) | |||
1030 | { | |||
1031 | long nLi = rLi.Right(); | |||
1032 | long nLk = rLk.Right(); | |||
1033 | if ( rLi.Top() == rLk.Top() && | |||
1034 | ((nLi < rLk.Left() && nLi+21 > rLk.Left()) || | |||
1035 | (nLk < rLi.Left() && nLk+21 > rLi.Left()))) | |||
1036 | { | |||
1037 | aLineRects.erase(aLineRects.begin() + i); | |||
1038 | // don't continue with inner loop any more: | |||
1039 | // the array may shrink! | |||
1040 | --i; | |||
1041 | break; | |||
1042 | } | |||
1043 | } | |||
1044 | else | |||
1045 | { | |||
1046 | long nLi = rLi.Bottom(); | |||
1047 | long nLk = rLk.Bottom(); | |||
1048 | if ( rLi.Left() == rLk.Left() && | |||
1049 | ((nLi < rLk.Top() && nLi+21 > rLk.Top()) || | |||
1050 | (nLk < rLi.Top() && nLk+21 > rLi.Top()))) | |||
1051 | { | |||
1052 | aLineRects.erase(aLineRects.begin() + i); | |||
1053 | // don't continue with inner loop any more: | |||
1054 | // the array may shrink! | |||
1055 | --i; | |||
1056 | break; | |||
1057 | } | |||
1058 | } | |||
1059 | } | |||
1060 | } | |||
1061 | } | |||
1062 | } | |||
1063 | ||||
1064 | if ( pRects && (!pRects->aLineRects.empty()) ) | |||
1065 | RemoveSuperfluousSubsidiaryLines( *pRects, properties ); | |||
1066 | ||||
1067 | if ( aLineRects.empty() ) | |||
1068 | return; | |||
1069 | ||||
1070 | pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR ); | |||
1071 | pOut->SetLineColor(); | |||
1072 | ||||
1073 | // Reset draw mode in high contrast mode in order to get fill color | |||
1074 | // set at output device. Recover draw mode after draw of lines. | |||
1075 | // Necessary for the subsidiary lines painted by the fly frames. | |||
1076 | DrawModeFlags nOldDrawMode = pOut->GetDrawMode(); | |||
1077 | if( gProp.pSGlobalShell->GetWin() && | |||
1078 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
1079 | { | |||
1080 | pOut->SetDrawMode( DrawModeFlags::Default ); | |||
1081 | } | |||
1082 | ||||
1083 | for (SwLineRect& rLRect : aLineRects) | |||
1084 | { | |||
1085 | // Add condition <!rLRect.IsLocked()> to prevent paint of locked subsidiary lines. | |||
1086 | if ( !rLRect.IsPainted() && | |||
1087 | !rLRect.IsLocked() ) | |||
1088 | { | |||
1089 | const Color *pCol = nullptr; | |||
1090 | switch ( rLRect.GetSubColor() ) | |||
1091 | { | |||
1092 | case SubColFlags::Page: pCol = &SwViewOption::GetDocBoundariesColor(); break; | |||
1093 | case SubColFlags::Fly: pCol = &SwViewOption::GetObjectBoundariesColor(); break; | |||
1094 | case SubColFlags::Tab: pCol = &SwViewOption::GetTableBoundariesColor(); break; | |||
1095 | case SubColFlags::Sect: pCol = &SwViewOption::GetSectionBoundColor(); break; | |||
1096 | } | |||
1097 | ||||
1098 | if (pCol && pOut->GetFillColor() != *pCol) | |||
1099 | pOut->SetFillColor( *pCol ); | |||
1100 | pOut->DrawRect( rLRect.SVRect() ); | |||
1101 | ||||
1102 | rLRect.SetPainted(); | |||
1103 | } | |||
1104 | } | |||
1105 | ||||
1106 | pOut->SetDrawMode( nOldDrawMode ); | |||
1107 | ||||
1108 | pOut->Pop(); | |||
1109 | } | |||
1110 | ||||
1111 | // Various functions that are use in this file. | |||
1112 | ||||
1113 | /** | |||
1114 | * Function <SwAlignRect(..)> is also used outside this file | |||
1115 | * | |||
1116 | * Correction: adjust rectangle on pixel level in order to make sure, | |||
1117 | * that the border "leaves its original pixel", if it has to | |||
1118 | * No prior adjustments for odd relation between pixel and twip | |||
1119 | */ | |||
1120 | void SwAlignRect( SwRect &rRect, const SwViewShell *pSh, const vcl::RenderContext* pRenderContext ) | |||
1121 | { | |||
1122 | if( !rRect.HasArea() ) | |||
1123 | return; | |||
1124 | ||||
1125 | // Make sure that view shell (parameter <pSh>) exists, if the output device | |||
1126 | // is taken from this view shell --> no output device, no alignment | |||
1127 | // Output device taken from view shell <pSh>, if <gProp.bSFlyMetafile> not set | |||
1128 | if ( !gProp.bSFlyMetafile && !pSh ) | |||
1129 | { | |||
1130 | return; | |||
1131 | } | |||
1132 | ||||
1133 | const vcl::RenderContext *pOut = gProp.bSFlyMetafile ? | |||
1134 | gProp.pSFlyMetafileOut.get() : pRenderContext; | |||
1135 | ||||
1136 | // Hold original rectangle in pixel | |||
1137 | const tools::Rectangle aOrgPxRect = pOut->LogicToPixel( rRect.SVRect() ); | |||
1138 | // Determine pixel-center rectangle in twip | |||
1139 | const SwRect aPxCenterRect( pOut->PixelToLogic( aOrgPxRect ) ); | |||
1140 | ||||
1141 | // Perform adjustments on pixel level. | |||
1142 | SwRect aAlignedPxRect( aOrgPxRect ); | |||
1143 | if ( rRect.Top() > aPxCenterRect.Top() ) | |||
1144 | { | |||
1145 | // 'leave pixel overlapping on top' | |||
1146 | aAlignedPxRect.AddTop( 1 ); | |||
1147 | } | |||
1148 | ||||
1149 | if ( rRect.Bottom() < aPxCenterRect.Bottom() ) | |||
1150 | { | |||
1151 | // 'leave pixel overlapping on bottom' | |||
1152 | aAlignedPxRect.AddBottom( - 1 ); | |||
1153 | } | |||
1154 | ||||
1155 | if ( rRect.Left() > aPxCenterRect.Left() ) | |||
1156 | { | |||
1157 | // 'leave pixel overlapping on left' | |||
1158 | aAlignedPxRect.AddLeft( 1 ); | |||
1159 | } | |||
1160 | ||||
1161 | if ( rRect.Right() < aPxCenterRect.Right() ) | |||
1162 | { | |||
1163 | // 'leave pixel overlapping on right' | |||
1164 | aAlignedPxRect.AddRight( - 1 ); | |||
1165 | } | |||
1166 | ||||
1167 | // Consider negative width/height check, if aligned SwRect has negative width/height. | |||
1168 | // If Yes, adjust it to width/height = 0 twip. | |||
1169 | // NOTE: A SwRect with negative width/height can occur, if the width/height | |||
1170 | // of the given SwRect in twip was less than a pixel in twip and that | |||
1171 | // the alignment calculates that the aligned SwRect should not contain | |||
1172 | // the pixels the width/height is on. | |||
1173 | if ( aAlignedPxRect.Width() < 0 ) | |||
1174 | { | |||
1175 | aAlignedPxRect.Width(0); | |||
1176 | } | |||
1177 | if ( aAlignedPxRect.Height() < 0 ) | |||
1178 | { | |||
1179 | aAlignedPxRect.Height(0); | |||
1180 | } | |||
1181 | // Consider zero width/height for converting a rectangle from | |||
1182 | // pixel to logic it needs a width/height. Thus, set width/height | |||
1183 | // to one, if it's zero and correct this on the twip level after the conversion. | |||
1184 | bool bZeroWidth = false; | |||
1185 | if ( aAlignedPxRect.Width() == 0 ) | |||
1186 | { | |||
1187 | aAlignedPxRect.Width(1); | |||
1188 | bZeroWidth = true; | |||
1189 | } | |||
1190 | bool bZeroHeight = false; | |||
1191 | if ( aAlignedPxRect.Height() == 0 ) | |||
1192 | { | |||
1193 | aAlignedPxRect.Height(1); | |||
1194 | bZeroHeight = true; | |||
1195 | } | |||
1196 | ||||
1197 | rRect = pOut->PixelToLogic( aAlignedPxRect.SVRect() ); | |||
1198 | ||||
1199 | // Consider zero width/height and adjust calculated aligned twip rectangle. | |||
1200 | // Reset width/height to zero; previous negative width/height haven't to be considered. | |||
1201 | if ( bZeroWidth ) | |||
1202 | { | |||
1203 | rRect.Width(0); | |||
1204 | } | |||
1205 | if ( bZeroHeight ) | |||
1206 | { | |||
1207 | rRect.Height(0); | |||
1208 | } | |||
1209 | } | |||
1210 | ||||
1211 | /** | |||
1212 | * Method to pixel-align rectangle for drawing graphic object | |||
1213 | * | |||
1214 | * Because we are drawing graphics from the left-top-corner in conjunction | |||
1215 | * with size coordinates, these coordinates have to be calculated at a pixel | |||
1216 | * level. | |||
1217 | * Thus, we convert the rectangle to pixel and then convert to left-top-corner | |||
1218 | * and then get size of pixel rectangle back to logic. | |||
1219 | * This calculation is necessary, because there's a different between | |||
1220 | * the conversion from logic to pixel of a normal rectangle with its left-top- | |||
1221 | * and right-bottom-corner and the same conversion of the same rectangle | |||
1222 | * with left-top-corner and size. | |||
1223 | * | |||
1224 | * NOTE: Call this method before each <GraphicObject.Draw(...)> | |||
1225 | */ | |||
1226 | void SwAlignGrfRect( SwRect *pGrfRect, const vcl::RenderContext &rOut ) | |||
1227 | { | |||
1228 | tools::Rectangle aPxRect = rOut.LogicToPixel( pGrfRect->SVRect() ); | |||
1229 | pGrfRect->Pos( rOut.PixelToLogic( aPxRect.TopLeft() ) ); | |||
1230 | pGrfRect->SSize( rOut.PixelToLogic( aPxRect.GetSize() ) ); | |||
1231 | } | |||
1232 | ||||
1233 | static long lcl_AlignWidth( const long nWidth, SwPaintProperties const & properties ) | |||
1234 | { | |||
1235 | if ( nWidth ) | |||
1236 | { | |||
1237 | const long nW = nWidth % properties.nSPixelSzW; | |||
1238 | ||||
1239 | if ( !nW || nW > properties.nSHalfPixelSzW ) | |||
1240 | return std::max(1L, nWidth - properties.nSHalfPixelSzW); | |||
1241 | } | |||
1242 | return nWidth; | |||
1243 | } | |||
1244 | ||||
1245 | static long lcl_AlignHeight( const long nHeight, SwPaintProperties const & properties ) | |||
1246 | { | |||
1247 | if ( nHeight ) | |||
1248 | { | |||
1249 | const long nH = nHeight % properties.nSPixelSzH; | |||
1250 | ||||
1251 | if ( !nH || nH > properties.nSHalfPixelSzH ) | |||
1252 | return std::max(1L, nHeight - properties.nSHalfPixelSzH); | |||
1253 | } | |||
1254 | return nHeight; | |||
1255 | } | |||
1256 | ||||
1257 | /** | |||
1258 | * Calculate PrtArea plus surrounding plus shadow | |||
1259 | */ | |||
1260 | static void lcl_CalcBorderRect( SwRect &rRect, const SwFrame *pFrame, | |||
1261 | const SwBorderAttrs &rAttrs, | |||
1262 | const bool bShadow, | |||
1263 | SwPaintProperties const & properties) | |||
1264 | { | |||
1265 | // Special handling for cell frames. | |||
1266 | // The printing area of a cell frame is completely enclosed in the frame area | |||
1267 | // and a cell frame has no shadow. Thus, for cell frames the calculated | |||
1268 | // area equals the frame area. | |||
1269 | // Notes: Borders of cell frames in R2L text direction will switch its side | |||
1270 | // - left border is painted on the right; right border on the left. | |||
1271 | // See <lcl_PaintLeftLine> and <lcl_PaintRightLine>. | |||
1272 | if( pFrame->IsSctFrame() ) | |||
1273 | { | |||
1274 | rRect = pFrame->getFramePrintArea(); | |||
1275 | rRect.Pos() += pFrame->getFrameArea().Pos(); | |||
1276 | } | |||
1277 | else if ( pFrame->IsCellFrame() ) | |||
1278 | rRect = pFrame->getFrameArea(); | |||
1279 | else | |||
1280 | { | |||
1281 | rRect = pFrame->getFramePrintArea(); | |||
1282 | rRect.Pos() += pFrame->getFrameArea().Pos(); | |||
1283 | ||||
1284 | SwRectFn fnRect = pFrame->IsVertical() ? ( pFrame->IsVertLR() ? (pFrame->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; | |||
1285 | ||||
1286 | const SvxBoxItem &rBox = rAttrs.GetBox(); | |||
1287 | const bool bTop = 0 != (pFrame->*fnRect->fnGetTopMargin)(); | |||
1288 | if ( bTop ) | |||
1289 | { | |||
1290 | SwTwips nDiff = rBox.GetTop() ? | |||
1291 | rBox.CalcLineSpace( SvxBoxItemLine::TOP ) : | |||
1292 | rBox.GetDistance( SvxBoxItemLine::TOP ); | |||
1293 | if( nDiff ) | |||
1294 | (rRect.*fnRect->fnSubTop)( nDiff ); | |||
1295 | } | |||
1296 | ||||
1297 | const bool bBottom = 0 != (pFrame->*fnRect->fnGetBottomMargin)(); | |||
1298 | if ( bBottom ) | |||
1299 | { | |||
1300 | SwTwips nDiff = 0; | |||
1301 | // #i29550# | |||
1302 | if ( pFrame->IsTabFrame() && | |||
1303 | static_cast<const SwTabFrame*>(pFrame)->IsCollapsingBorders() ) | |||
1304 | { | |||
1305 | // For collapsing borders, we have to add the height of | |||
1306 | // the height of the last line | |||
1307 | nDiff = static_cast<const SwTabFrame*>(pFrame)->GetBottomLineSize(); | |||
1308 | } | |||
1309 | else | |||
1310 | { | |||
1311 | nDiff = rBox.GetBottom() ? | |||
1312 | rBox.CalcLineSpace( SvxBoxItemLine::BOTTOM ) : | |||
1313 | rBox.GetDistance( SvxBoxItemLine::BOTTOM ); | |||
1314 | } | |||
1315 | if( nDiff ) | |||
1316 | (rRect.*fnRect->fnAddBottom)( nDiff ); | |||
1317 | } | |||
1318 | ||||
1319 | if ( rBox.GetLeft() ) | |||
1320 | (rRect.*fnRect->fnSubLeft)( rBox.CalcLineSpace( SvxBoxItemLine::LEFT ) ); | |||
1321 | else | |||
1322 | (rRect.*fnRect->fnSubLeft)( rBox.GetDistance( SvxBoxItemLine::LEFT ) ); | |||
1323 | ||||
1324 | if ( rBox.GetRight() ) | |||
1325 | (rRect.*fnRect->fnAddRight)( rBox.CalcLineSpace( SvxBoxItemLine::RIGHT ) ); | |||
1326 | else | |||
1327 | (rRect.*fnRect->fnAddRight)( rBox.GetDistance( SvxBoxItemLine::RIGHT ) ); | |||
1328 | ||||
1329 | if ( bShadow && rAttrs.GetShadow().GetLocation() != SvxShadowLocation::NONE ) | |||
1330 | { | |||
1331 | const SvxShadowItem &rShadow = rAttrs.GetShadow(); | |||
1332 | if ( bTop ) | |||
1333 | (rRect.*fnRect->fnSubTop)(rShadow.CalcShadowSpace(SvxShadowItemSide::TOP)); | |||
1334 | (rRect.*fnRect->fnSubLeft)(rShadow.CalcShadowSpace(SvxShadowItemSide::LEFT)); | |||
1335 | if ( bBottom ) | |||
1336 | (rRect.*fnRect->fnAddBottom) | |||
1337 | (rShadow.CalcShadowSpace( SvxShadowItemSide::BOTTOM )); | |||
1338 | (rRect.*fnRect->fnAddRight)(rShadow.CalcShadowSpace(SvxShadowItemSide::RIGHT)); | |||
1339 | } | |||
1340 | } | |||
1341 | ||||
1342 | ::SwAlignRect( rRect, properties.pSGlobalShell, properties.pSGlobalShell ? properties.pSGlobalShell->GetOut() : nullptr ); | |||
1343 | } | |||
1344 | ||||
1345 | /** | |||
1346 | * Extend left/right border/shadow rectangle to bottom of previous frame/to | |||
1347 | * top of next frame, if border/shadow is joined with previous/next frame | |||
1348 | */ | |||
1349 | static void lcl_ExtendLeftAndRight( SwRect& _rRect, | |||
1350 | const SwFrame& _rFrame, | |||
1351 | const SwBorderAttrs& _rAttrs, | |||
1352 | const SwRectFn& _rRectFn ) | |||
1353 | { | |||
1354 | if ( _rAttrs.JoinedWithPrev( _rFrame ) ) | |||
1355 | { | |||
1356 | const SwFrame* pPrevFrame = _rFrame.GetPrev(); | |||
1357 | (_rRect.*_rRectFn->fnSetTop)( (pPrevFrame->*_rRectFn->fnGetPrtBottom)() ); | |||
1358 | } | |||
1359 | if ( _rAttrs.JoinedWithNext( _rFrame ) ) | |||
1360 | { | |||
1361 | const SwFrame* pNextFrame = _rFrame.GetNext(); | |||
1362 | (_rRect.*_rRectFn->fnSetBottom)( (pNextFrame->*_rRectFn->fnGetPrtTop)() ); | |||
1363 | } | |||
1364 | } | |||
1365 | ||||
1366 | /// Returns a range suitable for subtraction when lcl_SubtractFlys() is used. | |||
1367 | /// Otherwise DrawFillAttributes() expands the clip path itself. | |||
1368 | static basegfx::B2DRange lcl_ShrinkFly(const SwRect& rRect) | |||
1369 | { | |||
1370 | static MapMode aMapMode(MapUnit::MapTwip); | |||
1371 | static const Size aSingleUnit = Application::GetDefaultDevice()->PixelToLogic(Size(1, 1), aMapMode); | |||
1372 | ||||
1373 | double x1 = rRect.Left() + aSingleUnit.getWidth(); | |||
1374 | double y1 = rRect.Top() + aSingleUnit.getHeight(); | |||
1375 | double x2 = rRect.Right() - aSingleUnit.getWidth(); | |||
1376 | double y2 = rRect.Bottom() - aSingleUnit.getHeight(); | |||
1377 | ||||
1378 | return basegfx::B2DRange(x1, y1, x2, y2); | |||
1379 | } | |||
1380 | ||||
1381 | static void lcl_SubtractFlys( const SwFrame *pFrame, const SwPageFrame *pPage, | |||
1382 | const SwRect &rRect, SwRegionRects &rRegion, basegfx::utils::B2DClipState& rClipState, SwPaintProperties const & rProperties) | |||
1383 | { | |||
1384 | const SwSortedObjs& rObjs = *pPage->GetSortedObjs(); | |||
1385 | const SwFlyFrame* pSelfFly = pFrame->IsInFly() ? pFrame->FindFlyFrame() : gProp.pSRetoucheFly2; | |||
1386 | if (!gProp.pSRetoucheFly) | |||
1387 | gProp.pSRetoucheFly = gProp.pSRetoucheFly2; | |||
1388 | ||||
1389 | for (size_t j = 0; (j < rObjs.size()) && !rRegion.empty(); ++j) | |||
1390 | { | |||
1391 | const SwAnchoredObject* pAnchoredObj = rObjs[j]; | |||
1392 | const SdrObject* pSdrObj = pAnchoredObj->GetDrawObj(); | |||
1393 | ||||
1394 | // Do not consider invisible objects | |||
1395 | if (!pPage->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId(pSdrObj->GetLayer())) | |||
1396 | continue; | |||
1397 | ||||
1398 | if (dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr) | |||
1399 | continue; | |||
1400 | ||||
1401 | const SwFlyFrame *pFly = static_cast<const SwFlyFrame*>(pAnchoredObj); | |||
1402 | ||||
1403 | if (pSelfFly == pFly || gProp.pSRetoucheFly == pFly || !rRect.IsOver(pFly->getFrameArea())) | |||
1404 | continue; | |||
1405 | ||||
1406 | if (!pFly->GetFormat()->GetPrint().GetValue() && | |||
1407 | (OUTDEV_PRINTER == gProp.pSGlobalShell->GetOut()->GetOutDevType() || | |||
1408 | gProp.pSGlobalShell->IsPreview())) | |||
1409 | continue; | |||
1410 | ||||
1411 | const bool bLowerOfSelf = pSelfFly && pFly->IsLowerOf( pSelfFly ); | |||
1412 | ||||
1413 | //For character bound Flys only examine those Flys in which it is not | |||
1414 | //anchored itself. | |||
1415 | //Why only for character bound ones you may ask? It never makes sense to | |||
1416 | //subtract frames in which it is anchored itself right? | |||
1417 | if (pSelfFly && pSelfFly->IsLowerOf(pFly)) | |||
1418 | continue; | |||
1419 | ||||
1420 | //Any why does it not apply for the RetoucheFly too? | |||
1421 | if (gProp.pSRetoucheFly && gProp.pSRetoucheFly->IsLowerOf(pFly)) | |||
1422 | continue; | |||
1423 | ||||
1424 | #if OSL_DEBUG_LEVEL1 > 0 | |||
1425 | //Flys who are anchored inside their own one, must have a bigger OrdNum | |||
1426 | //or be character bound. | |||
1427 | if (pSelfFly && bLowerOfSelf) | |||
1428 | { | |||
1429 | OSL_ENSURE( pFly->IsFlyInContentFrame() ||do { if (true && (!(pFly->IsFlyInContentFrame() || pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj ()->GetOrdNumDirect()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "1431" ": "), "%s", "Fly with wrong z-Order"); } } while (false) | |||
1430 | pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj()->GetOrdNumDirect(),do { if (true && (!(pFly->IsFlyInContentFrame() || pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj ()->GetOrdNumDirect()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "1431" ": "), "%s", "Fly with wrong z-Order"); } } while (false) | |||
1431 | "Fly with wrong z-Order" )do { if (true && (!(pFly->IsFlyInContentFrame() || pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj ()->GetOrdNumDirect()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "1431" ": "), "%s", "Fly with wrong z-Order"); } } while (false); | |||
1432 | } | |||
1433 | #endif | |||
1434 | ||||
1435 | bool bStopOnHell = true; | |||
1436 | if (pSelfFly) | |||
1437 | { | |||
1438 | const SdrObject *pTmp = pSelfFly->GetVirtDrawObj(); | |||
1439 | if (pSdrObj->GetLayer() == pTmp->GetLayer()) | |||
1440 | { | |||
1441 | if (pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect()) | |||
1442 | //In the same layer we only observe those that are above. | |||
1443 | continue; | |||
1444 | } | |||
1445 | else | |||
1446 | { | |||
1447 | if (!bLowerOfSelf && !pFly->GetFormat()->GetOpaque().GetValue()) | |||
1448 | //From other layers we are only interested in non | |||
1449 | //transparent ones or those that are internal | |||
1450 | continue; | |||
1451 | bStopOnHell = false; | |||
1452 | } | |||
1453 | } | |||
1454 | if (gProp.pSRetoucheFly) | |||
1455 | { | |||
1456 | const SdrObject *pTmp = gProp.pSRetoucheFly->GetVirtDrawObj(); | |||
1457 | if ( pSdrObj->GetLayer() == pTmp->GetLayer() ) | |||
1458 | { | |||
1459 | if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() ) | |||
1460 | //In the same layer we only observe those that are above. | |||
1461 | continue; | |||
1462 | } | |||
1463 | else | |||
1464 | { | |||
1465 | if (!pFly->IsLowerOf( gProp.pSRetoucheFly ) && !pFly->GetFormat()->GetOpaque().GetValue()) | |||
1466 | //From other layers we are only interested in non | |||
1467 | //transparent ones or those that are internal | |||
1468 | continue; | |||
1469 | bStopOnHell = false; | |||
1470 | } | |||
1471 | } | |||
1472 | ||||
1473 | //If the content of the Fly is transparent, we subtract it only if it's | |||
1474 | //contained in the hell layer. | |||
1475 | const IDocumentDrawModelAccess& rIDDMA = pFly->GetFormat()->getIDocumentDrawModelAccess(); | |||
1476 | bool bHell = pSdrObj->GetLayer() == rIDDMA.GetHellId(); | |||
1477 | if ( (bStopOnHell && bHell) || | |||
1478 | /// Change internal order of condition | |||
1479 | /// first check "!bHell", then "..->Lower()" and "..->IsNoTextFrame()" | |||
1480 | /// have not to be performed, if frame is in "Hell" | |||
1481 | ( !bHell && pFly->Lower() && pFly->Lower()->IsNoTextFrame() && | |||
1482 | (static_cast<SwNoTextFrame const*>(pFly->Lower())->IsTransparent() || | |||
1483 | static_cast<SwNoTextFrame const*>(pFly->Lower())->HasAnimation() || | |||
1484 | pFly->GetFormat()->GetSurround().IsContour() | |||
1485 | ) | |||
1486 | ) | |||
1487 | ) | |||
1488 | continue; | |||
1489 | ||||
1490 | // Own if-statements for transparent background/shadow of fly frames | |||
1491 | // in order to handle special conditions. | |||
1492 | if (pFly->IsBackgroundTransparent()) | |||
1493 | { | |||
1494 | // Background <pFly> is transparent drawn. Thus normally, its region | |||
1495 | // have not to be subtracted from given region. | |||
1496 | // But, if method is called for a fly frame and | |||
1497 | // <pFly> is a direct lower of this fly frame and | |||
1498 | // <pFly> inherites its transparent background brush from its parent, | |||
1499 | // then <pFly> frame area have to be subtracted from given region. | |||
1500 | // NOTE: Because in Status Quo transparent backgrounds can only be | |||
1501 | // assigned to fly frames, the handle of this special case | |||
1502 | // avoids drawing of transparent areas more than once, if | |||
1503 | // a fly frame inherites a transparent background from its | |||
1504 | // parent fly frame. | |||
1505 | if (pFrame->IsFlyFrame() && | |||
1506 | (pFly->GetAnchorFrame()->FindFlyFrame() == pFrame) && | |||
1507 | pFly->GetFormat()->IsBackgroundBrushInherited() | |||
1508 | ) | |||
1509 | { | |||
1510 | SwRect aRect; | |||
1511 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), static_cast<SwFrame const *>(pFly) ); | |||
1512 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
1513 | ::lcl_CalcBorderRect( aRect, pFly, rAttrs, true, rProperties ); | |||
1514 | rRegion -= aRect; | |||
1515 | rClipState.subtractRange(lcl_ShrinkFly(aRect)); | |||
1516 | continue; | |||
1517 | } | |||
1518 | else | |||
1519 | { | |||
1520 | continue; | |||
1521 | } | |||
1522 | } | |||
1523 | ||||
1524 | if (bHell && pFly->GetAnchorFrame()->IsInFly()) | |||
1525 | { | |||
1526 | //So the border won't get dismantled by the background of the other | |||
1527 | //Fly. | |||
1528 | SwRect aRect; | |||
1529 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), static_cast<SwFrame const *>(pFly) ); | |||
1530 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
1531 | ::lcl_CalcBorderRect( aRect, pFly, rAttrs, true, rProperties ); | |||
1532 | rRegion -= aRect; | |||
1533 | rClipState.subtractRange(lcl_ShrinkFly(aRect)); | |||
1534 | } | |||
1535 | else | |||
1536 | { | |||
1537 | SwRect aRect( pFly->getFramePrintArea() ); | |||
1538 | aRect += pFly->getFrameArea().Pos(); | |||
1539 | rRegion -= aRect; | |||
1540 | rClipState.subtractRange(lcl_ShrinkFly(aRect)); | |||
1541 | } | |||
1542 | } | |||
1543 | if (gProp.pSRetoucheFly == gProp.pSRetoucheFly2) | |||
1544 | gProp.pSRetoucheFly = nullptr; | |||
1545 | } | |||
1546 | ||||
1547 | static void lcl_implDrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush, | |||
1548 | vcl::RenderContext* _pOut, | |||
1549 | const SwRect& _rAlignedPaintRect, | |||
1550 | const GraphicObject& _rGraphicObj, | |||
1551 | SwPaintProperties const & properties) | |||
1552 | { | |||
1553 | /// determine color of background | |||
1554 | /// If color of background brush is not "no fill"/"auto fill" or | |||
1555 | /// <SwPaintProperties.bSFlyMetafile> is set, use color of background brush, otherwise | |||
1556 | /// use global retouche color. | |||
1557 | const Color aColor( ( (_rBackgrdBrush.GetColor() != COL_TRANSPARENT) || properties.bSFlyMetafile ) | |||
1558 | ? _rBackgrdBrush.GetColor() | |||
1559 | : aGlobalRetoucheColor ); | |||
1560 | ||||
1561 | /// determine, if background color have to be drawn transparent | |||
1562 | /// and calculate transparency percent value | |||
1563 | sal_Int8 nTransparencyPercent = 0; | |||
1564 | bool bDrawTransparent = false; | |||
1565 | if ( aColor.GetTransparency() != 0 ) | |||
1566 | /// background color is transparent --> draw transparent. | |||
1567 | { | |||
1568 | bDrawTransparent = true; | |||
1569 | nTransparencyPercent = (aColor.GetTransparency()*100 + 0x7F)/0xFF; | |||
1570 | } | |||
1571 | else if ( (_rGraphicObj.GetAttr().GetTransparency() != 0) && | |||
1572 | (_rBackgrdBrush.GetColor() == COL_TRANSPARENT) ) | |||
1573 | /// graphic is drawn transparent and background color is | |||
1574 | /// "no fill"/"auto fill" --> draw transparent | |||
1575 | { | |||
1576 | bDrawTransparent = true; | |||
1577 | nTransparencyPercent = (_rGraphicObj.GetAttr().GetTransparency()*100 + 0x7F)/0xFF; | |||
1578 | } | |||
1579 | ||||
1580 | if ( bDrawTransparent ) | |||
1581 | { | |||
1582 | /// draw background transparent | |||
1583 | if( _pOut->GetFillColor() != aColor.GetRGBColor() ) | |||
1584 | _pOut->SetFillColor( aColor.GetRGBColor() ); | |||
1585 | tools::PolyPolygon aPoly( _rAlignedPaintRect.SVRect() ); | |||
1586 | _pOut->DrawTransparent( aPoly, nTransparencyPercent ); | |||
1587 | } | |||
1588 | else | |||
1589 | { | |||
1590 | /// draw background opaque | |||
1591 | if ( _pOut->GetFillColor() != aColor ) | |||
1592 | _pOut->SetFillColor( aColor ); | |||
1593 | _pOut->DrawRect( _rAlignedPaintRect.SVRect() ); | |||
1594 | } | |||
1595 | } | |||
1596 | ||||
1597 | /** | |||
1598 | * This is a local help method to draw a background for a graphic | |||
1599 | * | |||
1600 | * Under certain circumstances we have to draw a background for a graphic. | |||
1601 | * This method takes care of the conditions and draws the background with the | |||
1602 | * corresponding color. | |||
1603 | * Method introduced for bug fix #103876# in order to optimize drawing tiled | |||
1604 | * background graphics. Previously, this code was integrated in method | |||
1605 | * <lcl_DrawGraphic>. | |||
1606 | * Method implemented as an inline, checking the conditions and calling method | |||
1607 | * method <lcl_implDrawGraphicBackgrd(..)> for the intrinsic drawing. | |||
1608 | * | |||
1609 | * @param _rBackgrdBrush | |||
1610 | * background brush contain the color the background has to be drawn. | |||
1611 | * | |||
1612 | * @param _pOut | |||
1613 | * output device the background has to be drawn in. | |||
1614 | * | |||
1615 | * @param _rAlignedPaintRect | |||
1616 | * paint rectangle in the output device, which has to be drawn with the background. | |||
1617 | * rectangle have to be aligned by method ::SwAlignRect | |||
1618 | * | |||
1619 | * @param _rGraphicObj | |||
1620 | * graphic object, for which the background has to be drawn. Used for checking | |||
1621 | * the transparency of its bitmap, its type and if the graphic is drawn transparent | |||
1622 | * | |||
1623 | * @param _bNumberingGraphic | |||
1624 | * boolean indicating that graphic is used as a numbering. | |||
1625 | * | |||
1626 | * @param _bBackgrdAlreadyDrawn | |||
1627 | * boolean (optional; default: false) indicating, if the background is already drawn. | |||
1628 | */ | |||
1629 | static void lcl_DrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush, | |||
1630 | OutputDevice* _pOut, | |||
1631 | const SwRect& _rAlignedPaintRect, | |||
1632 | const GraphicObject& _rGraphicObj, | |||
1633 | bool _bNumberingGraphic, | |||
1634 | SwPaintProperties const & properties, | |||
1635 | bool _bBackgrdAlreadyDrawn = false) | |||
1636 | { | |||
1637 | // draw background with background color, if | |||
1638 | // (1) graphic is not used as a numbering AND | |||
1639 | // (2) background is not already drawn AND | |||
1640 | // (3) intrinsic graphic is transparent OR intrinsic graphic doesn't exists | |||
1641 | if ( !_bNumberingGraphic && | |||
1642 | !_bBackgrdAlreadyDrawn && | |||
1643 | ( _rGraphicObj.IsTransparent() || _rGraphicObj.GetType() == GraphicType::NONE ) | |||
1644 | ) | |||
1645 | { | |||
1646 | lcl_implDrawGraphicBackgrd( _rBackgrdBrush, _pOut, _rAlignedPaintRect, _rGraphicObj, properties ); | |||
1647 | } | |||
1648 | } | |||
1649 | ||||
1650 | /** | |||
1651 | * NNOTE: the transparency of the background graphic is saved in | |||
1652 | * SvxBrushItem.GetGraphicObject(<shell>).GetAttr().Set/GetTransparency() | |||
1653 | * and is considered in the drawing of the graphic | |||
1654 | * | |||
1655 | * Thus, to provide transparent background graphic for text frames nothing | |||
1656 | * has to be coded | |||
1657 | * | |||
1658 | * Use align rectangle for drawing graphic Pixel-align coordinates for | |||
1659 | * drawing graphic | |||
1660 | * Outsource code for drawing background of the graphic | |||
1661 | * with a background color in method <lcl_DrawGraphicBackgrd> | |||
1662 | * | |||
1663 | * Also, change type of <bGrfNum> and <bClip> from <bool> to <bool> | |||
1664 | */ | |||
1665 | static void lcl_DrawGraphic( const SvxBrushItem& rBrush, vcl::RenderContext *pOut, | |||
1666 | SwViewShell &rSh, const SwRect &rGrf, const SwRect &rOut, | |||
1667 | bool bGrfNum, | |||
1668 | SwPaintProperties const & properties, | |||
1669 | bool bBackgrdAlreadyDrawn ) | |||
1670 | // add parameter <bBackgrdAlreadyDrawn> to indicate | |||
1671 | // that the background is already drawn. | |||
1672 | { | |||
1673 | // Calculate align rectangle from parameter <rGrf> and use aligned | |||
1674 | // rectangle <aAlignedGrfRect> in the following code | |||
1675 | SwRect aAlignedGrfRect = rGrf; | |||
1676 | ::SwAlignRect( aAlignedGrfRect, &rSh, pOut ); | |||
1677 | ||||
1678 | // Change type from <bool> to <bool>. | |||
1679 | const bool bNotInside = !rOut.IsInside( aAlignedGrfRect ); | |||
1680 | if ( bNotInside ) | |||
1681 | { | |||
1682 | pOut->Push( PushFlags::CLIPREGION ); | |||
1683 | pOut->IntersectClipRegion( rOut.SVRect() ); | |||
1684 | } | |||
1685 | ||||
1686 | GraphicObject *pGrf = const_cast<GraphicObject*>(rBrush.GetGraphicObject()); | |||
1687 | ||||
1688 | // Outsource drawing of background with a background color | |||
1689 | ::lcl_DrawGraphicBackgrd( rBrush, pOut, aAlignedGrfRect, *pGrf, bGrfNum, properties, bBackgrdAlreadyDrawn ); | |||
1690 | ||||
1691 | // Because for drawing a graphic left-top-corner and size coordinates are | |||
1692 | // used, these coordinates have to be determined on pixel level. | |||
1693 | ::SwAlignGrfRect( &aAlignedGrfRect, *pOut ); | |||
1694 | ||||
1695 | const basegfx::B2DHomMatrix aGraphicTransform( | |||
1696 | basegfx::utils::createScaleTranslateB2DHomMatrix( | |||
1697 | aAlignedGrfRect.Width(), aAlignedGrfRect.Height(), | |||
1698 | aAlignedGrfRect.Left(), aAlignedGrfRect.Top())); | |||
1699 | ||||
1700 | paintGraphicUsingPrimitivesHelper( | |||
1701 | *pOut, | |||
1702 | *pGrf, | |||
1703 | pGrf->GetAttr(), | |||
1704 | aGraphicTransform, | |||
1705 | OUString(), | |||
1706 | OUString(), | |||
1707 | OUString()); | |||
1708 | ||||
1709 | if ( bNotInside ) | |||
1710 | pOut->Pop(); | |||
1711 | } | |||
1712 | ||||
1713 | bool DrawFillAttributes( | |||
1714 | const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes, | |||
1715 | const SwRect& rOriginalLayoutRect, | |||
1716 | const SwRegionRects& rPaintRegion, | |||
1717 | const basegfx::utils::B2DClipState& rClipState, | |||
1718 | vcl::RenderContext& rOut) | |||
1719 | { | |||
1720 | if(rFillAttributes && rFillAttributes->isUsed()) | |||
1721 | { | |||
1722 | basegfx::B2DRange aPaintRange( | |||
1723 | rPaintRegion.GetOrigin().Left(), | |||
1724 | rPaintRegion.GetOrigin().Top(), | |||
1725 | rPaintRegion.GetOrigin().Right(), | |||
1726 | rPaintRegion.GetOrigin().Bottom()); | |||
1727 | ||||
1728 | if (!aPaintRange.isEmpty() && | |||
1729 | !rPaintRegion.empty() && | |||
1730 | !basegfx::fTools::equalZero(aPaintRange.getWidth()) && | |||
1731 | !basegfx::fTools::equalZero(aPaintRange.getHeight())) | |||
1732 | { | |||
1733 | const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; | |||
1734 | ||||
1735 | // need to expand for correct AAed and non-AAed visualization as primitive. | |||
1736 | // This must probably be removed again when we will be able to get all Writer visualization | |||
1737 | // as primitives and Writer prepares all it's stuff in high precision coordinates (also | |||
1738 | // needs to avoid moving boundaries around to better show overlapping stuff...) | |||
1739 | if(aSvtOptionsDrawinglayer.IsAntiAliasing()) | |||
1740 | { | |||
1741 | // if AAed in principle expand by 0.5 in all directions. Since painting edges of | |||
1742 | // AAed regions does not add to no transparence (0.5 opacity covered by 0.5 opacity | |||
1743 | // is not full opacity but 0.75 opacity) we need some overlap here to avoid paint | |||
1744 | // artifacts. Checked experimentally - a little bit more in Y is needed, probably | |||
1745 | // due to still existing integer alignment and crunching in writer. | |||
1746 | static const double fExpandX = 0.55; | |||
1747 | static const double fExpandY = 0.70; | |||
1748 | const basegfx::B2DVector aSingleUnit(rOut.GetInverseViewTransformation() * basegfx::B2DVector(fExpandX, fExpandY)); | |||
1749 | ||||
1750 | aPaintRange.expand(aPaintRange.getMinimum() - aSingleUnit); | |||
1751 | aPaintRange.expand(aPaintRange.getMaximum() + aSingleUnit); | |||
1752 | } | |||
1753 | else | |||
1754 | { | |||
1755 | // if not AAed expand by one unit to bottom right due to the missing unit | |||
1756 | // from SwRect/Rectangle integer handling | |||
1757 | const basegfx::B2DVector aSingleUnit(rOut.GetInverseViewTransformation() * basegfx::B2DVector(1.0, 1.0)); | |||
1758 | ||||
1759 | aPaintRange.expand(aPaintRange.getMaximum() + aSingleUnit); | |||
1760 | } | |||
1761 | ||||
1762 | const basegfx::B2DRange aDefineRange( | |||
1763 | rOriginalLayoutRect.Left(), | |||
1764 | rOriginalLayoutRect.Top(), | |||
1765 | rOriginalLayoutRect.Right(), | |||
1766 | rOriginalLayoutRect.Bottom()); | |||
1767 | ||||
1768 | const drawinglayer::primitive2d::Primitive2DContainer& rSequence = rFillAttributes->getPrimitive2DSequence( | |||
1769 | aPaintRange, | |||
1770 | aDefineRange); | |||
1771 | ||||
1772 | if(rSequence.size()) | |||
1773 | { | |||
1774 | drawinglayer::primitive2d::Primitive2DContainer const* | |||
1775 | pPrimitives(&rSequence); | |||
1776 | drawinglayer::primitive2d::Primitive2DContainer primitives; | |||
1777 | // tdf#86578 the awful lcl_SubtractFlys hack | |||
1778 | if (rPaintRegion.size() > 1 || rPaintRegion[0] != rPaintRegion.GetOrigin()) | |||
1779 | { | |||
1780 | basegfx::B2DPolyPolygon const& maskRegion(rClipState.getClipPoly()); | |||
1781 | primitives.resize(1); | |||
1782 | primitives[0] = new drawinglayer::primitive2d::MaskPrimitive2D( | |||
1783 | maskRegion, rSequence); | |||
1784 | pPrimitives = &primitives; | |||
1785 | } | |||
1786 | assert(pPrimitives && pPrimitives->size())(static_cast <bool> (pPrimitives && pPrimitives ->size()) ? void (0) : __assert_fail ("pPrimitives && pPrimitives->size()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" , 1786, __extension__ __PRETTY_FUNCTION__)); | |||
1787 | ||||
1788 | const drawinglayer::geometry::ViewInformation2D aViewInformation2D( | |||
1789 | basegfx::B2DHomMatrix(), | |||
1790 | rOut.GetViewTransformation(), | |||
1791 | aPaintRange, | |||
1792 | nullptr, | |||
1793 | 0.0, | |||
1794 | uno::Sequence< beans::PropertyValue >()); | |||
1795 | std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice( | |||
1796 | rOut, | |||
1797 | aViewInformation2D) ); | |||
1798 | if(pProcessor) | |||
1799 | { | |||
1800 | pProcessor->process(*pPrimitives); | |||
1801 | return true; | |||
1802 | } | |||
1803 | } | |||
1804 | } | |||
1805 | } | |||
1806 | ||||
1807 | return false; | |||
1808 | } | |||
1809 | ||||
1810 | void DrawGraphic( | |||
1811 | const SvxBrushItem *pBrush, | |||
1812 | vcl::RenderContext *pOutDev, | |||
1813 | const SwRect &rOrg, | |||
1814 | const SwRect &rOut, | |||
1815 | const sal_uInt8 nGrfNum, | |||
1816 | const bool bConsiderBackgroundTransparency ) | |||
1817 | // Add 6th parameter to indicate that method should | |||
1818 | // consider background transparency, saved in the color of the brush item | |||
1819 | { | |||
1820 | SwViewShell &rSh = *gProp.pSGlobalShell; | |||
1821 | bool bReplaceGrfNum = GRFNUM_REPLACE2 == nGrfNum; | |||
1822 | bool bGrfNum = GRFNUM_NO0 != nGrfNum; | |||
1823 | Size aGrfSize; | |||
1824 | SvxGraphicPosition ePos = GPOS_NONE; | |||
1825 | if( pBrush && !bReplaceGrfNum ) | |||
1826 | { | |||
1827 | if( rSh.GetViewOptions()->IsGraphic() ) | |||
1828 | { | |||
1829 | OUString referer; | |||
1830 | SfxObjectShell * sh = rSh.GetDoc()->GetPersist(); | |||
1831 | if (sh != nullptr && sh->HasName()) { | |||
1832 | referer = sh->GetMedium()->GetName(); | |||
1833 | } | |||
1834 | const Graphic* pGrf = pBrush->GetGraphic(referer); | |||
1835 | if( pGrf && GraphicType::NONE != pGrf->GetType() ) | |||
1836 | { | |||
1837 | ePos = pBrush->GetGraphicPos(); | |||
1838 | if( pGrf->IsSupportedGraphic() ) | |||
1839 | // don't the use the specific output device! Bug 94802 | |||
1840 | aGrfSize = ::GetGraphicSizeTwip( *pGrf, nullptr ); | |||
1841 | } | |||
1842 | } | |||
1843 | else | |||
1844 | bReplaceGrfNum = bGrfNum; | |||
1845 | } | |||
1846 | ||||
1847 | SwRect aGrf; | |||
1848 | aGrf.SSize( aGrfSize ); | |||
1849 | bool bDraw = true; | |||
1850 | bool bRetouche = true; | |||
1851 | switch ( ePos ) | |||
1852 | { | |||
1853 | case GPOS_LT: | |||
1854 | aGrf.Pos() = rOrg.Pos(); | |||
1855 | break; | |||
1856 | ||||
1857 | case GPOS_MT: | |||
1858 | aGrf.Pos().setY( rOrg.Top() ); | |||
1859 | aGrf.Pos().setX( rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2 ); | |||
1860 | break; | |||
1861 | ||||
1862 | case GPOS_RT: | |||
1863 | aGrf.Pos().setY( rOrg.Top() ); | |||
1864 | aGrf.Pos().setX( rOrg.Right() - aGrfSize.Width() ); | |||
1865 | break; | |||
1866 | ||||
1867 | case GPOS_LM: | |||
1868 | aGrf.Pos().setY( rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2 ); | |||
1869 | aGrf.Pos().setX( rOrg.Left() ); | |||
1870 | break; | |||
1871 | ||||
1872 | case GPOS_MM: | |||
1873 | aGrf.Pos().setY( rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2 ); | |||
1874 | aGrf.Pos().setX( rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2 ); | |||
1875 | break; | |||
1876 | ||||
1877 | case GPOS_RM: | |||
1878 | aGrf.Pos().setY( rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2 ); | |||
1879 | aGrf.Pos().setX( rOrg.Right() - aGrfSize.Width() ); | |||
1880 | break; | |||
1881 | ||||
1882 | case GPOS_LB: | |||
1883 | aGrf.Pos().setY( rOrg.Bottom() - aGrfSize.Height() ); | |||
1884 | aGrf.Pos().setX( rOrg.Left() ); | |||
1885 | break; | |||
1886 | ||||
1887 | case GPOS_MB: | |||
1888 | aGrf.Pos().setY( rOrg.Bottom() - aGrfSize.Height() ); | |||
1889 | aGrf.Pos().setX( rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2 ); | |||
1890 | break; | |||
1891 | ||||
1892 | case GPOS_RB: | |||
1893 | aGrf.Pos().setY( rOrg.Bottom() - aGrfSize.Height() ); | |||
1894 | aGrf.Pos().setX( rOrg.Right() - aGrfSize.Width() ); | |||
1895 | break; | |||
1896 | ||||
1897 | case GPOS_AREA: | |||
1898 | aGrf = rOrg; | |||
1899 | // Despite the fact that the background graphic has to fill the complete | |||
1900 | // area, we already checked, whether the graphic will completely fill out | |||
1901 | // the region the <rOut> that is to be painted. Thus, nothing has to be | |||
1902 | // touched again. | |||
1903 | // E.g. this is the case for a Fly Frame without a background | |||
1904 | // brush positioned on the border of the page which inherited the background | |||
1905 | // brush from the page. | |||
1906 | bRetouche = !rOut.IsInside( aGrf ); | |||
1907 | break; | |||
1908 | ||||
1909 | case GPOS_TILED: | |||
1910 | { | |||
1911 | // draw background of tiled graphic before drawing tiled graphic in loop | |||
1912 | // determine graphic object | |||
1913 | GraphicObject* pGraphicObj = const_cast< GraphicObject* >(pBrush->GetGraphicObject()); | |||
1914 | // calculate aligned paint rectangle | |||
1915 | SwRect aAlignedPaintRect = rOut; | |||
1916 | ::SwAlignRect( aAlignedPaintRect, &rSh, pOutDev ); | |||
1917 | // draw background color for aligned paint rectangle | |||
1918 | lcl_DrawGraphicBackgrd( *pBrush, pOutDev, aAlignedPaintRect, *pGraphicObj, bGrfNum, gProp ); | |||
1919 | ||||
1920 | // set left-top-corner of background graphic to left-top-corner of the | |||
1921 | // area, from which the background brush is determined. | |||
1922 | aGrf.Pos() = rOrg.Pos(); | |||
1923 | // setup clipping at output device | |||
1924 | pOutDev->Push( PushFlags::CLIPREGION ); | |||
1925 | pOutDev->IntersectClipRegion( rOut.SVRect() ); | |||
1926 | // use new method <GraphicObject::DrawTiled(::)> | |||
1927 | { | |||
1928 | // calculate paint offset | |||
1929 | Point aPaintOffset( aAlignedPaintRect.Pos() - aGrf.Pos() ); | |||
1930 | // draw background graphic tiled for aligned paint rectangle | |||
1931 | // #i42643# | |||
1932 | // For PDF export, every draw operation for bitmaps takes a | |||
1933 | // noticeable amount of place (~50 characters). Thus, optimize | |||
1934 | // between tile bitmap size and number of drawing operations here. | |||
1935 | ||||
1936 | // A_out | |||
1937 | // n_chars = k1 * ---------- + k2 * A_bitmap | |||
1938 | // A_bitmap | |||
1939 | ||||
1940 | // minimum n_chars is obtained for (derive for A_bitmap, | |||
1941 | // set to 0, take positive solution): | |||
1942 | // k1 | |||
1943 | // A_bitmap = Sqrt( ---- A_out ) | |||
1944 | // k2 | |||
1945 | ||||
1946 | // where k1 is the number of chars per draw operation, and | |||
1947 | // k2 is the number of chars per bitmap pixel. | |||
1948 | // This is approximately 50 and 7 for current PDF writer, respectively. | |||
1949 | ||||
1950 | const double k1( 50 ); | |||
1951 | const double k2( 7 ); | |||
1952 | const Size aSize( aAlignedPaintRect.SSize() ); | |||
1953 | const double Abitmap( k1/k2 * static_cast<double>(aSize.Width())*aSize.Height() ); | |||
1954 | ||||
1955 | pGraphicObj->DrawTiled( pOutDev, | |||
1956 | aAlignedPaintRect.SVRect(), | |||
1957 | aGrf.SSize(), | |||
1958 | Size( aPaintOffset.X(), aPaintOffset.Y() ), | |||
1959 | std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) ); | |||
1960 | } | |||
1961 | // reset clipping at output device | |||
1962 | pOutDev->Pop(); | |||
1963 | // set <bDraw> and <bRetouche> to false, indicating that background | |||
1964 | // graphic and background are already drawn. | |||
1965 | bDraw = bRetouche = false; | |||
1966 | } | |||
1967 | break; | |||
1968 | ||||
1969 | case GPOS_NONE: | |||
1970 | bDraw = false; | |||
1971 | break; | |||
1972 | ||||
1973 | default: OSL_ENSURE( !pOutDev, "new Graphic position?" )do { if (true && (!(!pOutDev))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "1973" ": "), "%s", "new Graphic position?"); } } while ( false); | |||
1974 | } | |||
1975 | ||||
1976 | /// init variable <bGrfBackgrdAlreadDrawn> to indicate, if background of | |||
1977 | /// graphic is already drawn or not. | |||
1978 | bool bGrfBackgrdAlreadyDrawn = false; | |||
1979 | if ( bRetouche ) | |||
1980 | { | |||
1981 | pOutDev->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR ); | |||
1982 | pOutDev->SetLineColor(); | |||
1983 | ||||
1984 | // check, if an existing background graphic (not filling the complete | |||
1985 | // background) is transparent drawn and the background color is | |||
1986 | // "no fill" respectively "auto fill", if background transparency | |||
1987 | // has to be considered. | |||
1988 | // If YES, memorize transparency of background graphic. | |||
1989 | // check also, if background graphic bitmap is transparent. | |||
1990 | bool bTransparentGrfWithNoFillBackgrd = false; | |||
1991 | sal_Int32 nGrfTransparency = 0; | |||
1992 | bool bGrfIsTransparent = false; | |||
1993 | if ( (ePos != GPOS_NONE) && | |||
1994 | (ePos != GPOS_TILED) && (ePos != GPOS_AREA) | |||
1995 | ) | |||
1996 | { | |||
1997 | GraphicObject *pGrf = const_cast<GraphicObject*>(pBrush->GetGraphicObject()); | |||
1998 | if ( bConsiderBackgroundTransparency ) | |||
1999 | { | |||
2000 | GraphicAttr aGrfAttr = pGrf->GetAttr(); | |||
2001 | if ( (aGrfAttr.GetTransparency() != 0) && | |||
2002 | (pBrush->GetColor() == COL_TRANSPARENT) | |||
2003 | ) | |||
2004 | { | |||
2005 | bTransparentGrfWithNoFillBackgrd = true; | |||
2006 | nGrfTransparency = aGrfAttr.GetTransparency(); | |||
2007 | } | |||
2008 | } | |||
2009 | if ( pGrf->IsTransparent() ) | |||
2010 | { | |||
2011 | bGrfIsTransparent = true; | |||
2012 | } | |||
2013 | } | |||
2014 | ||||
2015 | // to get color of brush, check background color against COL_TRANSPARENT ("no fill"/"auto fill") | |||
2016 | // instead of checking, if transparency is not set. | |||
2017 | const Color aColor( pBrush && | |||
2018 | ( (pBrush->GetColor() != COL_TRANSPARENT) || | |||
2019 | gProp.bSFlyMetafile ) | |||
2020 | ? pBrush->GetColor() | |||
2021 | : aGlobalRetoucheColor ); | |||
2022 | ||||
2023 | // determine, if background region have to be | |||
2024 | // drawn transparent. | |||
2025 | // background region has to be drawn transparent, if | |||
2026 | // background transparency have to be considered | |||
2027 | // AND | |||
2028 | // ( background color is transparent OR | |||
2029 | // background graphic is transparent and background color is "no fill" | |||
2030 | // ) | |||
2031 | ||||
2032 | enum DrawStyle { | |||
2033 | Default, | |||
2034 | Transparent, | |||
2035 | } eDrawStyle = Default; | |||
2036 | ||||
2037 | if (bConsiderBackgroundTransparency && | |||
2038 | ( ( aColor.GetTransparency() != 0) || | |||
2039 | bTransparentGrfWithNoFillBackgrd ) ) | |||
2040 | { | |||
2041 | eDrawStyle = Transparent; | |||
2042 | } | |||
2043 | ||||
2044 | // #i75614# reset draw mode in high contrast mode in order to get fill color set | |||
2045 | const DrawModeFlags nOldDrawMode = pOutDev->GetDrawMode(); | |||
2046 | if ( gProp.pSGlobalShell->GetWin() && | |||
2047 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
2048 | { | |||
2049 | pOutDev->SetDrawMode( DrawModeFlags::Default ); | |||
2050 | } | |||
2051 | ||||
2052 | // If background region has to be drawn transparent, set only the RGB values of the background color as | |||
2053 | // the fill color for the output device. | |||
2054 | switch (eDrawStyle) | |||
2055 | { | |||
2056 | case Transparent: | |||
2057 | { | |||
2058 | if( pOutDev->GetFillColor() != aColor.GetRGBColor() ) | |||
2059 | pOutDev->SetFillColor( aColor.GetRGBColor() ); | |||
2060 | break; | |||
2061 | } | |||
2062 | default: | |||
2063 | { | |||
2064 | if( pOutDev->GetFillColor() != aColor ) | |||
2065 | pOutDev->SetFillColor( aColor ); | |||
2066 | break; | |||
2067 | } | |||
2068 | } | |||
2069 | ||||
2070 | // #i75614# | |||
2071 | // restore draw mode | |||
2072 | pOutDev->SetDrawMode( nOldDrawMode ); | |||
2073 | ||||
2074 | switch (eDrawStyle) | |||
2075 | { | |||
2076 | case Transparent: | |||
2077 | { | |||
2078 | // background region have to be drawn transparent. | |||
2079 | // Thus, create a poly-polygon from the region and draw it with | |||
2080 | // the corresponding transparency percent. | |||
2081 | tools::PolyPolygon aDrawPoly( rOut.SVRect() ); | |||
2082 | if ( aGrf.HasArea() ) | |||
2083 | { | |||
2084 | if ( !bGrfIsTransparent ) | |||
2085 | { | |||
2086 | // subtract area of background graphic from draw area | |||
2087 | // Consider only that part of the graphic area that is overlapping with draw area. | |||
2088 | SwRect aTmpGrf = aGrf; | |||
2089 | aTmpGrf.Intersection( rOut ); | |||
2090 | if ( aTmpGrf.HasArea() ) | |||
2091 | { | |||
2092 | tools::Polygon aGrfPoly( aTmpGrf.SVRect() ); | |||
2093 | aDrawPoly.Insert( aGrfPoly ); | |||
2094 | } | |||
2095 | } | |||
2096 | else | |||
2097 | bGrfBackgrdAlreadyDrawn = true; | |||
2098 | } | |||
2099 | // calculate transparency percent: | |||
2100 | // ( <transparency value[0x01..0xFF]>*100 + 0x7F ) / 0xFF | |||
2101 | // If there is a background graphic with a background color "no fill"/"auto fill", | |||
2102 | // the transparency value is taken from the background graphic, | |||
2103 | // otherwise take the transparency value from the color. | |||
2104 | sal_Int8 nTransparencyPercent = static_cast<sal_Int8>( | |||
2105 | (( bTransparentGrfWithNoFillBackgrd ? nGrfTransparency : aColor.GetTransparency() | |||
2106 | )*100 + 0x7F)/0xFF); | |||
2107 | // draw poly-polygon transparent | |||
2108 | pOutDev->DrawTransparent( aDrawPoly, nTransparencyPercent ); | |||
2109 | ||||
2110 | break; | |||
2111 | } | |||
2112 | case Default: | |||
2113 | default: | |||
2114 | { | |||
2115 | SwRegionRects aRegion( rOut, 4 ); | |||
2116 | if ( !bGrfIsTransparent ) | |||
2117 | aRegion -= aGrf; | |||
2118 | else | |||
2119 | bGrfBackgrdAlreadyDrawn = true; | |||
2120 | // loop rectangles of background region, which has to be drawn | |||
2121 | for( size_t i = 0; i < aRegion.size(); ++i ) | |||
2122 | { | |||
2123 | pOutDev->DrawRect( aRegion[i].SVRect() ); | |||
2124 | } | |||
2125 | } | |||
2126 | } | |||
2127 | pOutDev ->Pop(); | |||
2128 | } | |||
2129 | ||||
2130 | if( bDraw && aGrf.IsOver( rOut ) ) | |||
2131 | lcl_DrawGraphic( *pBrush, pOutDev, rSh, aGrf, rOut, bGrfNum, gProp, | |||
2132 | bGrfBackgrdAlreadyDrawn ); | |||
2133 | ||||
2134 | if( bReplaceGrfNum ) | |||
2135 | { | |||
2136 | const BitmapEx& rBmp = rSh.GetReplacementBitmap(false); | |||
2137 | vcl::Font aTmp( pOutDev->GetFont() ); | |||
2138 | Graphic::DrawEx(pOutDev, OUString(), aTmp, rBmp, rOrg.Pos(), rOrg.SSize()); | |||
2139 | } | |||
2140 | } | |||
2141 | ||||
2142 | /** | |||
2143 | * Local helper for SwRootFrame::PaintSwFrame(..) - Adjust given rectangle to pixel size | |||
2144 | * | |||
2145 | * By OD at 27.09.2002 for #103636# | |||
2146 | * In order to avoid paint errors caused by multiple alignments (e.g. ::SwAlignRect(..)) | |||
2147 | * and other changes to the to be painted rectangle, this method is called for the | |||
2148 | * rectangle to be painted in order to adjust it to the pixel it is overlapping | |||
2149 | */ | |||
2150 | static void lcl_AdjustRectToPixelSize( SwRect& io_aSwRect, const vcl::RenderContext &aOut ) | |||
2151 | { | |||
2152 | // local constant object of class <Size> to determine number of Twips | |||
2153 | // representing a pixel. | |||
2154 | const Size aTwipToPxSize( aOut.PixelToLogic( Size( 1,1 )) ); | |||
2155 | ||||
2156 | // local object of class <Rectangle> in Twip coordinates | |||
2157 | // calculated from given rectangle aligned to pixel centers. | |||
2158 | const tools::Rectangle aPxCenterRect = aOut.PixelToLogic( | |||
2159 | aOut.LogicToPixel( io_aSwRect.SVRect() ) ); | |||
2160 | ||||
2161 | // local constant object of class <Rectangle> representing given rectangle | |||
2162 | // in pixel. | |||
2163 | const tools::Rectangle aOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() ); | |||
2164 | ||||
2165 | // calculate adjusted rectangle from pixel centered rectangle. | |||
2166 | // Due to rounding differences <aPxCenterRect> doesn't exactly represents | |||
2167 | // the Twip-centers. Thus, adjust borders by half of pixel width/height plus 1. | |||
2168 | // Afterwards, adjust calculated Twip-positions of the all borders. | |||
2169 | tools::Rectangle aSizedRect = aPxCenterRect; | |||
2170 | aSizedRect.AdjustLeft( -(aTwipToPxSize.Width()/2 + 1) ); | |||
2171 | aSizedRect.AdjustRight( aTwipToPxSize.Width()/2 + 1 ); | |||
2172 | aSizedRect.AdjustTop( -(aTwipToPxSize.Height()/2 + 1) ); | |||
2173 | aSizedRect.AdjustBottom(aTwipToPxSize.Height()/2 + 1); | |||
2174 | ||||
2175 | // adjust left() | |||
2176 | while ( aOut.LogicToPixel(aSizedRect).Left() < aOrgPxRect.Left() ) | |||
2177 | { | |||
2178 | aSizedRect.AdjustLeft( 1 ); | |||
2179 | } | |||
2180 | // adjust right() | |||
2181 | while ( aOut.LogicToPixel(aSizedRect).Right() > aOrgPxRect.Right() ) | |||
2182 | { | |||
2183 | aSizedRect.AdjustRight( -1 ); | |||
2184 | } | |||
2185 | // adjust top() | |||
2186 | while ( aOut.LogicToPixel(aSizedRect).Top() < aOrgPxRect.Top() ) | |||
2187 | { | |||
2188 | aSizedRect.AdjustTop( 1 ); | |||
2189 | } | |||
2190 | // adjust bottom() | |||
2191 | while ( aOut.LogicToPixel(aSizedRect).Bottom() > aOrgPxRect.Bottom() ) | |||
2192 | { | |||
2193 | aSizedRect.AdjustBottom( -1 ); | |||
2194 | } | |||
2195 | ||||
2196 | io_aSwRect = SwRect( aSizedRect ); | |||
2197 | ||||
2198 | #if OSL_DEBUG_LEVEL1 > 0 | |||
2199 | tools::Rectangle aTestOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() ); | |||
2200 | tools::Rectangle aTestNewPxRect = aOut.LogicToPixel( aSizedRect ); | |||
2201 | OSL_ENSURE( aTestOrgPxRect == aTestNewPxRect,do { if (true && (!(aTestOrgPxRect == aTestNewPxRect) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2202" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size" ); } } while (false) | |||
2202 | "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size")do { if (true && (!(aTestOrgPxRect == aTestNewPxRect) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2202" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size" ); } } while (false); | |||
2203 | // check Left() | |||
2204 | aSizedRect.AdjustLeft( -1 ); | |||
2205 | aTestNewPxRect = aOut.LogicToPixel( aSizedRect ); | |||
2206 | OSL_ENSURE( aTestOrgPxRect.Left() >= (aTestNewPxRect.Left()+1),do { if (true && (!(aTestOrgPxRect.Left() >= (aTestNewPxRect .Left()+1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2207" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted" ); } } while (false) | |||
2207 | "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted")do { if (true && (!(aTestOrgPxRect.Left() >= (aTestNewPxRect .Left()+1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2207" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted" ); } } while (false); | |||
2208 | aSizedRect.AdjustLeft( 1 ); | |||
2209 | // check Right() | |||
2210 | aSizedRect.AdjustRight( 1 ); | |||
2211 | aTestNewPxRect = aOut.LogicToPixel( aSizedRect ); | |||
2212 | OSL_ENSURE( aTestOrgPxRect.Right() <= (aTestNewPxRect.Right()-1),do { if (true && (!(aTestOrgPxRect.Right() <= (aTestNewPxRect .Right()-1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2213" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted" ); } } while (false) | |||
2213 | "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted")do { if (true && (!(aTestOrgPxRect.Right() <= (aTestNewPxRect .Right()-1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2213" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted" ); } } while (false); | |||
2214 | aSizedRect.AdjustRight( -1 ); | |||
2215 | // check Top() | |||
2216 | aSizedRect.AdjustTop( -1 ); | |||
2217 | aTestNewPxRect = aOut.LogicToPixel( aSizedRect ); | |||
2218 | OSL_ENSURE( aTestOrgPxRect.Top() >= (aTestNewPxRect.Top()+1),do { if (true && (!(aTestOrgPxRect.Top() >= (aTestNewPxRect .Top()+1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2219" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted" ); } } while (false) | |||
2219 | "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted")do { if (true && (!(aTestOrgPxRect.Top() >= (aTestNewPxRect .Top()+1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2219" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted" ); } } while (false); | |||
2220 | aSizedRect.AdjustTop( 1 ); | |||
2221 | // check Bottom() | |||
2222 | aSizedRect.AdjustBottom( 1 ); | |||
2223 | aTestNewPxRect = aOut.LogicToPixel( aSizedRect ); | |||
2224 | OSL_ENSURE( aTestOrgPxRect.Bottom() <= (aTestNewPxRect.Bottom()-1),do { if (true && (!(aTestOrgPxRect.Bottom() <= (aTestNewPxRect .Bottom()-1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2225" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted" ); } } while (false) | |||
2225 | "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted")do { if (true && (!(aTestOrgPxRect.Bottom() <= (aTestNewPxRect .Bottom()-1)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2225" ": "), "%s", "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted" ); } } while (false); | |||
2226 | aSizedRect.AdjustBottom( -1 ); | |||
2227 | #endif | |||
2228 | } | |||
2229 | ||||
2230 | // FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES START | |||
2231 | ||||
2232 | namespace { | |||
2233 | ||||
2234 | struct SwLineEntry | |||
2235 | { | |||
2236 | SwTwips mnKey; | |||
2237 | SwTwips mnStartPos; | |||
2238 | SwTwips mnEndPos; | |||
2239 | ||||
2240 | svx::frame::Style maAttribute; | |||
2241 | ||||
2242 | enum OverlapType { NO_OVERLAP, OVERLAP1, OVERLAP2, OVERLAP3 }; | |||
2243 | ||||
2244 | public: | |||
2245 | SwLineEntry( SwTwips nKey, | |||
2246 | SwTwips nStartPos, | |||
2247 | SwTwips nEndPos, | |||
2248 | const svx::frame::Style& rAttribute ); | |||
2249 | ||||
2250 | OverlapType Overlaps( const SwLineEntry& rComp ) const; | |||
2251 | }; | |||
2252 | ||||
2253 | } | |||
2254 | ||||
2255 | SwLineEntry::SwLineEntry( SwTwips nKey, | |||
2256 | SwTwips nStartPos, | |||
2257 | SwTwips nEndPos, | |||
2258 | const svx::frame::Style& rAttribute ) | |||
2259 | : mnKey( nKey ), | |||
2260 | mnStartPos( nStartPos ), | |||
2261 | mnEndPos( nEndPos ), | |||
2262 | maAttribute( rAttribute ) | |||
2263 | { | |||
2264 | } | |||
2265 | ||||
2266 | /* | |||
2267 | ||||
2268 | 1. ---------- rOld | |||
2269 | ---------- rNew | |||
2270 | ||||
2271 | 2. ---------- rOld | |||
2272 | ------------- rNew | |||
2273 | ||||
2274 | 3. ------- rOld | |||
2275 | ------------- rNew | |||
2276 | ||||
2277 | 4. ------------- rOld | |||
2278 | ---------- rNew | |||
2279 | ||||
2280 | 5. ---------- rOld | |||
2281 | ---- rNew | |||
2282 | ||||
2283 | 6. ---------- rOld | |||
2284 | ---------- rNew | |||
2285 | ||||
2286 | 7. ------------- rOld | |||
2287 | ---------- rNew | |||
2288 | ||||
2289 | 8. ---------- rOld | |||
2290 | ------------- rNew | |||
2291 | ||||
2292 | 9. ---------- rOld | |||
2293 | ---------- rNew | |||
2294 | */ | |||
2295 | ||||
2296 | SwLineEntry::OverlapType SwLineEntry::Overlaps( const SwLineEntry& rNew ) const | |||
2297 | { | |||
2298 | SwLineEntry::OverlapType eRet = OVERLAP3; | |||
2299 | ||||
2300 | if ( mnStartPos >= rNew.mnEndPos || mnEndPos <= rNew.mnStartPos ) | |||
2301 | eRet = NO_OVERLAP; | |||
2302 | ||||
2303 | // 1, 2, 3 | |||
2304 | else if ( mnEndPos < rNew.mnEndPos ) | |||
2305 | eRet = OVERLAP1; | |||
2306 | ||||
2307 | // 4, 5, 6, 7 | |||
2308 | else if (mnStartPos <= rNew.mnStartPos) | |||
2309 | eRet = OVERLAP2; | |||
2310 | ||||
2311 | // 8, 9 | |||
2312 | return eRet; | |||
2313 | } | |||
2314 | ||||
2315 | namespace { | |||
2316 | ||||
2317 | struct lt_SwLineEntry | |||
2318 | { | |||
2319 | bool operator()( const SwLineEntry& e1, const SwLineEntry& e2 ) const | |||
2320 | { | |||
2321 | return e1.mnStartPos < e2.mnStartPos; | |||
2322 | } | |||
2323 | }; | |||
2324 | ||||
2325 | } | |||
2326 | ||||
2327 | typedef std::set< SwLineEntry, lt_SwLineEntry > SwLineEntrySet; | |||
2328 | typedef std::map< SwTwips, SwLineEntrySet > SwLineEntryMap; | |||
2329 | ||||
2330 | namespace { | |||
2331 | ||||
2332 | class SwTabFramePainter | |||
2333 | { | |||
2334 | SwLineEntryMap maVertLines; | |||
2335 | SwLineEntryMap maHoriLines; | |||
2336 | const SwTabFrame& mrTabFrame; | |||
2337 | ||||
2338 | void Insert( SwLineEntry&, bool bHori ); | |||
2339 | void Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, const SwRect &rPaintArea); | |||
2340 | void HandleFrame(const SwLayoutFrame& rFrame, const SwRect& rPaintArea); | |||
2341 | void FindStylesForLine( const Point&, | |||
2342 | const Point&, | |||
2343 | svx::frame::Style*, | |||
2344 | bool bHori ) const; | |||
2345 | ||||
2346 | public: | |||
2347 | explicit SwTabFramePainter( const SwTabFrame& rTabFrame ); | |||
2348 | ||||
2349 | void PaintLines( OutputDevice& rDev, const SwRect& rRect ) const; | |||
2350 | }; | |||
2351 | ||||
2352 | } | |||
2353 | ||||
2354 | SwTabFramePainter::SwTabFramePainter( const SwTabFrame& rTabFrame ) | |||
2355 | : mrTabFrame( rTabFrame ) | |||
2356 | { | |||
2357 | SwRect aPaintArea = rTabFrame.GetUpper()->GetPaintArea(); | |||
2358 | HandleFrame(rTabFrame, aPaintArea); | |||
2359 | } | |||
2360 | ||||
2361 | void SwTabFramePainter::HandleFrame(const SwLayoutFrame& rLayoutFrame, const SwRect& rPaintArea) | |||
2362 | { | |||
2363 | // Add border lines of cell frames. Skip covered cells. Skip cells | |||
2364 | // in special row span row, which do not have a negative row span: | |||
2365 | if ( rLayoutFrame.IsCellFrame() && !rLayoutFrame.IsCoveredCell() ) | |||
2366 | { | |||
2367 | const SwCellFrame* pThisCell = static_cast<const SwCellFrame*>(&rLayoutFrame); | |||
2368 | const SwRowFrame* pRowFrame = static_cast<const SwRowFrame*>(pThisCell->GetUpper()); | |||
2369 | const long nRowSpan = pThisCell->GetTabBox()->getRowSpan(); | |||
2370 | if ( !pRowFrame->IsRowSpanLine() || nRowSpan > 1 || nRowSpan < -1 ) | |||
2371 | { | |||
2372 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), &rLayoutFrame ); | |||
2373 | const SwBorderAttrs& rAttrs = *aAccess.Get(); | |||
2374 | const SvxBoxItem& rBox = rAttrs.GetBox(); | |||
2375 | Insert(rLayoutFrame, rBox, rPaintArea); | |||
2376 | } | |||
2377 | } | |||
2378 | ||||
2379 | // Recurse into lower layout frames, but do not recurse into lower tabframes. | |||
2380 | const SwFrame* pLower = rLayoutFrame.Lower(); | |||
2381 | while ( pLower ) | |||
2382 | { | |||
2383 | const SwLayoutFrame* pLowerLayFrame = dynamic_cast<const SwLayoutFrame*>(pLower); | |||
2384 | if ( pLowerLayFrame && !pLowerLayFrame->IsTabFrame() ) | |||
2385 | HandleFrame(*pLowerLayFrame, rPaintArea); | |||
2386 | ||||
2387 | pLower = pLower->GetNext(); | |||
2388 | } | |||
2389 | } | |||
2390 | ||||
2391 | void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) const | |||
2392 | { | |||
2393 | // #i16816# tagged pdf support | |||
2394 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, rDev ); | |||
2395 | ||||
2396 | SwLineEntryMap::const_iterator aIter = maHoriLines.begin(); | |||
2397 | bool bHori = true; | |||
2398 | ||||
2399 | // color for subsidiary lines: | |||
2400 | const Color& rCol( SwViewOption::GetTableBoundariesColor() ); | |||
2401 | ||||
2402 | // high contrast mode: | |||
2403 | // overrides the color of non-subsidiary lines. | |||
2404 | const Color* pHCColor = nullptr; | |||
2405 | DrawModeFlags nOldDrawMode = rDev.GetDrawMode(); | |||
2406 | if( gProp.pSGlobalShell->GetWin() && | |||
2407 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
2408 | { | |||
2409 | pHCColor = &SwViewOption::GetFontColor(); | |||
2410 | rDev.SetDrawMode( DrawModeFlags::Default ); | |||
2411 | } | |||
2412 | ||||
2413 | const SwFrame* pUpper = mrTabFrame.GetUpper(); | |||
2414 | SwRect aUpper( pUpper->getFramePrintArea() ); | |||
2415 | aUpper.Pos() += pUpper->getFrameArea().Pos(); | |||
2416 | SwRect aUpperAligned( aUpper ); | |||
2417 | ::SwAlignRect( aUpperAligned, gProp.pSGlobalShell, &rDev ); | |||
2418 | ||||
2419 | // prepare SdrFrameBorderDataVector | |||
2420 | std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData( | |||
2421 | std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>()); | |||
2422 | ||||
2423 | while ( true ) | |||
2424 | { | |||
2425 | if ( bHori && aIter == maHoriLines.end() ) | |||
2426 | { | |||
2427 | aIter = maVertLines.begin(); | |||
2428 | bHori = false; | |||
2429 | } | |||
2430 | ||||
2431 | if ( !bHori && aIter == maVertLines.end() ) | |||
2432 | break; | |||
2433 | ||||
2434 | const SwLineEntrySet& rEntrySet = (*aIter).second; | |||
2435 | for (const SwLineEntry& rEntry : rEntrySet) | |||
2436 | { | |||
2437 | const svx::frame::Style& rEntryStyle( rEntry.maAttribute ); | |||
2438 | ||||
2439 | Point aStart, aEnd; | |||
2440 | if ( bHori ) | |||
2441 | { | |||
2442 | aStart.setX( rEntry.mnStartPos ); | |||
2443 | aStart.setY( rEntry.mnKey ); | |||
2444 | aEnd.setX( rEntry.mnEndPos ); | |||
2445 | aEnd.setY( rEntry.mnKey ); | |||
2446 | } | |||
2447 | else | |||
2448 | { | |||
2449 | aStart.setX( rEntry.mnKey ); | |||
2450 | aStart.setY( rEntry.mnStartPos ); | |||
2451 | aEnd.setX( rEntry.mnKey ); | |||
2452 | aEnd.setY( rEntry.mnEndPos ); | |||
2453 | } | |||
2454 | ||||
2455 | svx::frame::Style aStyles[ 7 ]; | |||
2456 | aStyles[ 0 ] = rEntryStyle; | |||
2457 | FindStylesForLine( aStart, aEnd, aStyles, bHori ); | |||
2458 | SwRect aRepaintRect( aStart, aEnd ); | |||
2459 | ||||
2460 | // the repaint rectangle has to be moved a bit for the centered lines: | |||
2461 | SwTwips nRepaintRectSize = !rEntryStyle.GetWidth() ? 1 : rEntryStyle.GetWidth(); | |||
2462 | if ( bHori ) | |||
2463 | { | |||
2464 | aRepaintRect.Height( 2 * nRepaintRectSize ); | |||
2465 | aRepaintRect.Pos().AdjustY( -nRepaintRectSize ); | |||
2466 | ||||
2467 | // To decide on visibility it is also necessary to expand the RepaintRect | |||
2468 | // to left/right according existing BorderLine overlap matchings, else there | |||
2469 | // will be repaint errors when scrolling in e.t TripleLine BorderLines. | |||
2470 | // aStyles[1] == aLFromT, aStyles[3] == aLFromB, aStyles[4] == aRFromT, aStyles[6] == aRFromB | |||
2471 | if(aStyles[1].IsUsed() || aStyles[3].IsUsed() || aStyles[4].IsUsed() || aStyles[6].IsUsed()) | |||
2472 | { | |||
2473 | const double fLineWidthMaxLeft(std::max(aStyles[1].GetWidth(), aStyles[3].GetWidth())); | |||
2474 | const double fLineWidthMaxRight(std::max(aStyles[4].GetWidth(), aStyles[6].GetWidth())); | |||
2475 | aRepaintRect.Width(aRepaintRect.Width() + (fLineWidthMaxLeft + fLineWidthMaxRight)); | |||
2476 | aRepaintRect.Pos().AdjustX( -fLineWidthMaxLeft ); | |||
2477 | } | |||
2478 | } | |||
2479 | else | |||
2480 | { | |||
2481 | aRepaintRect.Width( 2 * nRepaintRectSize ); | |||
2482 | aRepaintRect.Pos().AdjustX( -nRepaintRectSize ); | |||
2483 | ||||
2484 | // Accordingly to horizontal case, but for top/bottom | |||
2485 | // aStyles[3] == aTFromR, aStyles[1] == aTFromL, aStyles[6] == aBFromR, aStyles[4] == aBFromL | |||
2486 | if(aStyles[3].IsUsed() || aStyles[1].IsUsed() || aStyles[6].IsUsed() || aStyles[4].IsUsed()) | |||
2487 | { | |||
2488 | const double fLineWidthMaxTop(std::max(aStyles[3].GetWidth(), aStyles[1].GetWidth())); | |||
2489 | const double fLineWidthMaxBottom(std::max(aStyles[6].GetWidth(), aStyles[4].GetWidth())); | |||
2490 | aRepaintRect.Height(aRepaintRect.Height() + (fLineWidthMaxTop + fLineWidthMaxBottom)); | |||
2491 | aRepaintRect.Pos().AdjustY( -fLineWidthMaxTop ); | |||
2492 | } | |||
2493 | } | |||
2494 | ||||
2495 | if (!rRect.IsOver(aRepaintRect)) | |||
2496 | { | |||
2497 | continue; | |||
2498 | } | |||
2499 | ||||
2500 | // subsidiary lines | |||
2501 | const Color* pTmpColor = nullptr; | |||
2502 | if (0 == aStyles[ 0 ].GetWidth()) | |||
2503 | { | |||
2504 | if (isTableBoundariesEnabled() && gProp.pSGlobalShell->GetWin()) | |||
2505 | aStyles[ 0 ].Set( rCol, rCol, rCol, false, 1, 0, 0 ); | |||
2506 | else | |||
2507 | aStyles[0].SetType(SvxBorderLineStyle::NONE); | |||
2508 | } | |||
2509 | else | |||
2510 | pTmpColor = pHCColor; | |||
2511 | ||||
2512 | // The (twip) positions will be adjusted to meet these requirements: | |||
2513 | // 1. The y coordinates are located in the middle of the pixel grid | |||
2514 | // 2. The x coordinated are located at the beginning of the pixel grid | |||
2515 | // This is done, because the horizontal lines are painted "at | |||
2516 | // beginning", whereas the vertical lines are painted "centered". | |||
2517 | // By making the line sizes a multiple of one pixel size, we can | |||
2518 | // assure that all lines having the same twip size have the same | |||
2519 | // pixel size, independent of their position on the screen. | |||
2520 | Point aPaintStart = rDev.PixelToLogic( rDev.LogicToPixel(aStart) ); | |||
2521 | Point aPaintEnd = rDev.PixelToLogic( rDev.LogicToPixel(aEnd) ); | |||
2522 | ||||
2523 | if (gProp.pSGlobalShell->GetWin()) | |||
2524 | { | |||
2525 | // The table borders do not use SwAlignRect, but all the other frames do. | |||
2526 | // Therefore we tweak the outer borders a bit to achieve that the outer | |||
2527 | // borders match the subsidiary lines of the upper: | |||
2528 | if (aStart.X() == aUpper.Left()) | |||
2529 | aPaintStart.setX( aUpperAligned.Left() ); | |||
2530 | else if (aStart.X() == aUpper.Right_()) | |||
2531 | aPaintStart.setX( aUpperAligned.Right_() ); | |||
2532 | if (aStart.Y() == aUpper.Top()) | |||
2533 | aPaintStart.setY( aUpperAligned.Top() ); | |||
2534 | else if (aStart.Y() == aUpper.Bottom_()) | |||
2535 | aPaintStart.setY( aUpperAligned.Bottom_() ); | |||
2536 | ||||
2537 | if (aEnd.X() == aUpper.Left()) | |||
2538 | aPaintEnd.setX( aUpperAligned.Left() ); | |||
2539 | else if (aEnd.X() == aUpper.Right_()) | |||
2540 | aPaintEnd.setX( aUpperAligned.Right_() ); | |||
2541 | if (aEnd.Y() == aUpper.Top()) | |||
2542 | aPaintEnd.setY( aUpperAligned.Top() ); | |||
2543 | else if (aEnd.Y() == aUpper.Bottom_()) | |||
2544 | aPaintEnd.setY( aUpperAligned.Bottom_() ); | |||
2545 | } | |||
2546 | ||||
2547 | if(aStyles[0].IsUsed()) | |||
2548 | { | |||
2549 | if (bHori) | |||
2550 | { | |||
2551 | const basegfx::B2DPoint aOrigin(aPaintStart.X(), aPaintStart.Y()); | |||
2552 | const basegfx::B2DVector aX(basegfx::B2DPoint(aPaintEnd.X(), aPaintEnd.Y()) - aOrigin); | |||
2553 | ||||
2554 | if(!aX.equalZero()) | |||
2555 | { | |||
2556 | const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX)); | |||
2557 | aData->emplace_back( | |||
2558 | aOrigin, | |||
2559 | aX, | |||
2560 | aStyles[0], | |||
2561 | pTmpColor); | |||
2562 | drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back()); | |||
2563 | ||||
2564 | rInstance.addSdrConnectStyleData(true, aStyles[1], -aY, true); // aLFromT | |||
2565 | rInstance.addSdrConnectStyleData(true, aStyles[2], -aX, true); // aLFromL | |||
2566 | rInstance.addSdrConnectStyleData(true, aStyles[3], aY, false); // aLFromB | |||
2567 | ||||
2568 | rInstance.addSdrConnectStyleData(false, aStyles[4], -aY, true); // aRFromT | |||
2569 | rInstance.addSdrConnectStyleData(false, aStyles[5], aX, false); // aRFromR | |||
2570 | rInstance.addSdrConnectStyleData(false, aStyles[6], aY, false); // aRFromB | |||
2571 | } | |||
2572 | } | |||
2573 | else // vertical | |||
2574 | { | |||
2575 | const basegfx::B2DPoint aOrigin(aPaintStart.X(), aPaintStart.Y()); | |||
2576 | const basegfx::B2DVector aX(basegfx::B2DPoint(aPaintEnd.X(), aPaintEnd.Y()) - aOrigin); | |||
2577 | ||||
2578 | if(!aX.equalZero()) | |||
2579 | { | |||
2580 | const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX)); | |||
2581 | aData->emplace_back( | |||
2582 | aOrigin, | |||
2583 | aX, | |||
2584 | aStyles[0], | |||
2585 | pTmpColor); | |||
2586 | drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back()); | |||
2587 | ||||
2588 | rInstance.addSdrConnectStyleData(true, aStyles[3], -aY, false); // aTFromR | |||
2589 | rInstance.addSdrConnectStyleData(true, aStyles[2], -aX, true); // aTFromT | |||
2590 | rInstance.addSdrConnectStyleData(true, aStyles[1], aY, true); // aTFromL | |||
2591 | ||||
2592 | rInstance.addSdrConnectStyleData(false, aStyles[6], -aY, false); // aBFromR | |||
2593 | rInstance.addSdrConnectStyleData(false, aStyles[5], aX, false); // aBFromB | |||
2594 | rInstance.addSdrConnectStyleData(false, aStyles[4], aY, true); // aBFromL | |||
2595 | } | |||
2596 | } | |||
2597 | } | |||
2598 | } | |||
2599 | ++aIter; | |||
2600 | } | |||
2601 | ||||
2602 | // create instance of SdrFrameBorderPrimitive2D if | |||
2603 | // SdrFrameBorderDataVector is used | |||
2604 | if(!aData->empty()) | |||
2605 | { | |||
2606 | drawinglayer::primitive2d::Primitive2DContainer aSequence; | |||
2607 | aSequence.append( | |||
2608 | drawinglayer::primitive2d::Primitive2DReference( | |||
2609 | new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D( | |||
2610 | aData, | |||
2611 | true))); // force visualization to minimal one discrete unit (pixel) | |||
2612 | // paint | |||
2613 | mrTabFrame.ProcessPrimitives(aSequence); | |||
2614 | } | |||
2615 | ||||
2616 | // restore output device: | |||
2617 | rDev.SetDrawMode( nOldDrawMode ); | |||
2618 | } | |||
2619 | ||||
2620 | /** | |||
2621 | * Finds the lines that join the line defined by (StartPoint, EndPoint) in either | |||
2622 | * StartPoint or Endpoint. The styles of these lines are required for DR's magic | |||
2623 | * line painting functions | |||
2624 | */ | |||
2625 | void SwTabFramePainter::FindStylesForLine( const Point& rStartPoint, | |||
2626 | const Point& rEndPoint, | |||
2627 | svx::frame::Style* pStyles, | |||
2628 | bool bHori ) const | |||
2629 | { | |||
2630 | // pStyles[ 1 ] = bHori ? aLFromT : TFromL | |||
2631 | // pStyles[ 2 ] = bHori ? aLFromL : TFromT, | |||
2632 | // pStyles[ 3 ] = bHori ? aLFromB : TFromR, | |||
2633 | // pStyles[ 4 ] = bHori ? aRFromT : BFromL, | |||
2634 | // pStyles[ 5 ] = bHori ? aRFromR : BFromB, | |||
2635 | // pStyles[ 6 ] = bHori ? aRFromB : BFromR, | |||
2636 | ||||
2637 | SwLineEntryMap::const_iterator aMapIter = maVertLines.find( rStartPoint.X() ); | |||
2638 | OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" )do { if (true && (!(aMapIter != maVertLines.end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2638" ": "), "%s", "FindStylesForLine: Error"); } } while (false); | |||
2639 | const SwLineEntrySet& rVertSet = (*aMapIter).second; | |||
2640 | ||||
2641 | for ( const SwLineEntry& rEntry : rVertSet ) | |||
2642 | { | |||
2643 | if ( bHori ) | |||
2644 | { | |||
2645 | if ( rStartPoint.Y() == rEntry.mnStartPos ) | |||
2646 | pStyles[ 3 ] = rEntry.maAttribute; | |||
2647 | else if ( rStartPoint.Y() == rEntry.mnEndPos ) | |||
2648 | pStyles[ 1 ] = rEntry.maAttribute; | |||
2649 | } | |||
2650 | else | |||
2651 | { | |||
2652 | if ( rStartPoint.Y() == rEntry.mnEndPos ) | |||
2653 | pStyles[ 2 ] = rEntry.maAttribute; | |||
2654 | else if ( rEndPoint.Y() == rEntry.mnStartPos ) | |||
2655 | pStyles[ 5 ] = rEntry.maAttribute; | |||
2656 | } | |||
2657 | } | |||
2658 | ||||
2659 | aMapIter = maHoriLines.find( rStartPoint.Y() ); | |||
2660 | OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" )do { if (true && (!(aMapIter != maHoriLines.end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2660" ": "), "%s", "FindStylesForLine: Error"); } } while (false); | |||
2661 | const SwLineEntrySet& rHoriSet = (*aMapIter).second; | |||
2662 | ||||
2663 | for ( const SwLineEntry& rEntry : rHoriSet ) | |||
2664 | { | |||
2665 | if ( bHori ) | |||
2666 | { | |||
2667 | if ( rStartPoint.X() == rEntry.mnEndPos ) | |||
2668 | pStyles[ 2 ] = rEntry.maAttribute; | |||
2669 | else if ( rEndPoint.X() == rEntry.mnStartPos ) | |||
2670 | pStyles[ 5 ] = rEntry.maAttribute; | |||
2671 | } | |||
2672 | else | |||
2673 | { | |||
2674 | if ( rStartPoint.X() == rEntry.mnEndPos ) | |||
2675 | pStyles[ 1 ] = rEntry.maAttribute; | |||
2676 | else if ( rStartPoint.X() == rEntry.mnStartPos ) | |||
2677 | pStyles[ 3 ] = rEntry.maAttribute; | |||
2678 | } | |||
2679 | } | |||
2680 | ||||
2681 | if ( bHori ) | |||
2682 | { | |||
2683 | aMapIter = maVertLines.find( rEndPoint.X() ); | |||
2684 | OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" )do { if (true && (!(aMapIter != maVertLines.end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2684" ": "), "%s", "FindStylesForLine: Error"); } } while (false); | |||
2685 | const SwLineEntrySet& rVertSet2 = (*aMapIter).second; | |||
2686 | ||||
2687 | for ( const SwLineEntry& rEntry : rVertSet2 ) | |||
2688 | { | |||
2689 | if ( rEndPoint.Y() == rEntry.mnStartPos ) | |||
2690 | pStyles[ 6 ] = rEntry.maAttribute; | |||
2691 | else if ( rEndPoint.Y() == rEntry.mnEndPos ) | |||
2692 | pStyles[ 4 ] = rEntry.maAttribute; | |||
2693 | } | |||
2694 | } | |||
2695 | else | |||
2696 | { | |||
2697 | aMapIter = maHoriLines.find( rEndPoint.Y() ); | |||
2698 | OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" )do { if (true && (!(aMapIter != maHoriLines.end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2698" ": "), "%s", "FindStylesForLine: Error"); } } while (false); | |||
2699 | const SwLineEntrySet& rHoriSet2 = (*aMapIter).second; | |||
2700 | ||||
2701 | for ( const SwLineEntry& rEntry : rHoriSet2 ) | |||
2702 | { | |||
2703 | if ( rEndPoint.X() == rEntry.mnEndPos ) | |||
2704 | pStyles[ 4 ] = rEntry.maAttribute; | |||
2705 | else if ( rEndPoint.X() == rEntry.mnStartPos ) | |||
2706 | pStyles[ 6 ] = rEntry.maAttribute; | |||
2707 | } | |||
2708 | } | |||
2709 | } | |||
2710 | ||||
2711 | /** | |||
2712 | * Special case: #i9860# | |||
2713 | * first line in follow table without repeated headlines | |||
2714 | */ | |||
2715 | static bool lcl_IsFirstRowInFollowTableWithoutRepeatedHeadlines( | |||
2716 | SwTabFrame const& rTabFrame, SwFrame const& rFrame, SvxBoxItem const& rBoxItem) | |||
2717 | { | |||
2718 | SwRowFrame const*const pThisRowFrame = | |||
2719 | dynamic_cast<const SwRowFrame*>(rFrame.GetUpper()); | |||
2720 | return (pThisRowFrame | |||
2721 | && (pThisRowFrame->GetUpper() == &rTabFrame) | |||
2722 | && rTabFrame.IsFollow() | |||
2723 | && !rTabFrame.GetTable()->GetRowsToRepeat() | |||
2724 | && ( !pThisRowFrame->GetPrev() | |||
2725 | || static_cast<const SwRowFrame*>(pThisRowFrame->GetPrev()) | |||
2726 | ->IsRowSpanLine()) | |||
2727 | && !rBoxItem.GetTop() | |||
2728 | && rBoxItem.GetBottom()); | |||
2729 | } | |||
2730 | ||||
2731 | void SwTabFramePainter::Insert(const SwFrame& rFrame, const SvxBoxItem& rBoxItem, const SwRect& rPaintArea) | |||
2732 | { | |||
2733 | // build 4 line entries for the 4 borders: | |||
2734 | SwRect aBorderRect = rFrame.getFrameArea(); | |||
2735 | ||||
2736 | aBorderRect.Intersection(rPaintArea); | |||
2737 | ||||
2738 | bool const bBottomAsTop(lcl_IsFirstRowInFollowTableWithoutRepeatedHeadlines( | |||
2739 | mrTabFrame, rFrame, rBoxItem)); | |||
2740 | bool const bVert = mrTabFrame.IsVertical(); | |||
2741 | bool const bR2L = mrTabFrame.IsRightToLeft(); | |||
2742 | ||||
2743 | bool bWordTableCell = false; | |||
2744 | SwViewShell* pShell = rFrame.getRootFrame()->GetCurrShell(); | |||
2745 | if (pShell) | |||
2746 | { | |||
2747 | const IDocumentSettingAccess& rIDSA = pShell->GetDoc()->getIDocumentSettingAccess(); | |||
2748 | bWordTableCell = rIDSA.get(DocumentSettingId::TABLE_ROW_KEEP); | |||
2749 | } | |||
2750 | ||||
2751 | // no scaling needed, it's all in the primitives and the target device | |||
2752 | svx::frame::Style aL(rBoxItem.GetLeft(), 1.0); | |||
2753 | aL.SetWordTableCell(bWordTableCell); | |||
2754 | svx::frame::Style aR(rBoxItem.GetRight(), 1.0); | |||
2755 | aR.SetWordTableCell(bWordTableCell); | |||
2756 | svx::frame::Style aT(rBoxItem.GetTop(), 1.0); | |||
2757 | aT.SetWordTableCell(bWordTableCell); | |||
2758 | svx::frame::Style aB(rBoxItem.GetBottom(), 1.0); | |||
2759 | aB.SetWordTableCell(bWordTableCell); | |||
2760 | ||||
2761 | aR.MirrorSelf(); | |||
2762 | aB.MirrorSelf(); | |||
2763 | ||||
2764 | const SwTwips nLeft = aBorderRect.Left_(); | |||
2765 | const SwTwips nRight = aBorderRect.Right_(); | |||
2766 | const SwTwips nTop = aBorderRect.Top_(); | |||
2767 | const SwTwips nBottom = aBorderRect.Bottom_(); | |||
2768 | ||||
2769 | aL.SetRefMode( svx::frame::RefMode::Centered ); | |||
2770 | aR.SetRefMode( svx::frame::RefMode::Centered ); | |||
2771 | aT.SetRefMode( !bVert ? svx::frame::RefMode::Begin : svx::frame::RefMode::End ); | |||
2772 | aB.SetRefMode( !bVert ? svx::frame::RefMode::Begin : svx::frame::RefMode::End ); | |||
2773 | ||||
2774 | SwLineEntry aLeft (nLeft, nTop, nBottom, | |||
2775 | bVert ? aB : (bR2L ? aR : aL)); | |||
2776 | SwLineEntry aRight (nRight, nTop, nBottom, | |||
2777 | bVert ? (bBottomAsTop ? aB : aT) : (bR2L ? aL : aR)); | |||
2778 | SwLineEntry aTop (nTop, nLeft, nRight, | |||
2779 | bVert ? aL : (bBottomAsTop ? aB : aT)); | |||
2780 | SwLineEntry aBottom(nBottom, nLeft, nRight, | |||
2781 | bVert ? aR : aB); | |||
2782 | ||||
2783 | Insert( aLeft, false ); | |||
2784 | Insert( aRight, false ); | |||
2785 | Insert( aTop, true ); | |||
2786 | Insert( aBottom, true ); | |||
2787 | } | |||
2788 | ||||
2789 | void SwTabFramePainter::Insert( SwLineEntry& rNew, bool bHori ) | |||
2790 | { | |||
2791 | // get all lines from structure, that have key entry of pLE | |||
2792 | SwLineEntryMap* pLine2 = bHori ? &maHoriLines : &maVertLines; | |||
2793 | const SwTwips nKey = rNew.mnKey; | |||
2794 | SwLineEntryMap::iterator aMapIter = pLine2->find( nKey ); | |||
2795 | ||||
2796 | SwLineEntrySet* pLineSet = aMapIter != pLine2->end() ? &((*aMapIter).second) : nullptr; | |||
2797 | if ( !pLineSet ) | |||
2798 | { | |||
2799 | SwLineEntrySet aNewSet; | |||
2800 | (*pLine2)[ nKey ] = aNewSet; | |||
2801 | pLineSet = &(*pLine2)[ nKey ]; | |||
2802 | } | |||
2803 | SwLineEntrySet::iterator aIter = pLineSet->begin(); | |||
2804 | ||||
2805 | while ( aIter != pLineSet->end() && rNew.mnStartPos < rNew.mnEndPos ) | |||
2806 | { | |||
2807 | const SwLineEntry& rOld = *aIter; | |||
2808 | const SwLineEntry::OverlapType nOverlapType = rOld.Overlaps( rNew ); | |||
2809 | ||||
2810 | const svx::frame::Style& rOldAttr = rOld.maAttribute; | |||
2811 | const svx::frame::Style& rNewAttr = rNew.maAttribute; | |||
2812 | const svx::frame::Style& rCmpAttr = std::max(rNewAttr, rOldAttr); | |||
2813 | ||||
2814 | if ( SwLineEntry::OVERLAP1 == nOverlapType ) | |||
2815 | { | |||
2816 | OSL_ENSURE( rNew.mnStartPos >= rOld.mnStartPos, "Overlap type 3? How this?" )do { if (true && (!(rNew.mnStartPos >= rOld.mnStartPos ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2816" ": "), "%s", "Overlap type 3? How this?"); } } while (false); | |||
2817 | ||||
2818 | // new left segment | |||
2819 | const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr ); | |||
2820 | ||||
2821 | // new middle segment | |||
2822 | const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rOld.mnEndPos, rCmpAttr ); | |||
2823 | ||||
2824 | // new right segment | |||
2825 | rNew.mnStartPos = rOld.mnEndPos; | |||
2826 | ||||
2827 | // update current lines set | |||
2828 | pLineSet->erase( aIter ); | |||
2829 | if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft ); | |||
2830 | if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle ); | |||
2831 | ||||
2832 | aIter = pLineSet->begin(); | |||
2833 | ||||
2834 | continue; // start over | |||
2835 | } | |||
2836 | else if ( SwLineEntry::OVERLAP2 == nOverlapType ) | |||
2837 | { | |||
2838 | // new left segment | |||
2839 | const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr ); | |||
2840 | ||||
2841 | // new middle segment | |||
2842 | const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rNew.mnEndPos, rCmpAttr ); | |||
2843 | ||||
2844 | // new right segment | |||
2845 | const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr ); | |||
2846 | ||||
2847 | // update current lines set | |||
2848 | pLineSet->erase( aIter ); | |||
2849 | if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft ); | |||
2850 | if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle ); | |||
2851 | if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight ); | |||
2852 | ||||
2853 | rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted! | |||
2854 | ||||
2855 | break; // we are finished | |||
2856 | } | |||
2857 | else if ( SwLineEntry::OVERLAP3 == nOverlapType ) | |||
2858 | { | |||
2859 | // new left segment | |||
2860 | const SwLineEntry aLeft( nKey, rNew.mnStartPos, rOld.mnStartPos, rNewAttr ); | |||
2861 | ||||
2862 | // new middle segment | |||
2863 | const SwLineEntry aMiddle( nKey, rOld.mnStartPos, rNew.mnEndPos, rCmpAttr ); | |||
2864 | ||||
2865 | // new right segment | |||
2866 | const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr ); | |||
2867 | ||||
2868 | // update current lines set | |||
2869 | pLineSet->erase( aIter ); | |||
2870 | if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft ); | |||
2871 | if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle ); | |||
2872 | if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight ); | |||
2873 | ||||
2874 | rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted! | |||
2875 | ||||
2876 | break; // we are finished | |||
2877 | } | |||
2878 | ||||
2879 | ++aIter; | |||
2880 | } | |||
2881 | ||||
2882 | if ( rNew.mnStartPos < rNew.mnEndPos ) // insert rest | |||
2883 | pLineSet->insert( rNew ); | |||
2884 | } | |||
2885 | ||||
2886 | /** | |||
2887 | * FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES END | |||
2888 | * --> OD #i76669# | |||
2889 | */ | |||
2890 | namespace | |||
2891 | { | |||
2892 | class SwViewObjectContactRedirector : public sdr::contact::ViewObjectContactRedirector | |||
2893 | { | |||
2894 | private: | |||
2895 | const SwViewShell& mrViewShell; | |||
2896 | ||||
2897 | public: | |||
2898 | explicit SwViewObjectContactRedirector( const SwViewShell& rSh ) | |||
2899 | : mrViewShell( rSh ) | |||
2900 | {}; | |||
2901 | ||||
2902 | virtual drawinglayer::primitive2d::Primitive2DContainer createRedirectedPrimitive2DSequence( | |||
2903 | const sdr::contact::ViewObjectContact& rOriginal, | |||
2904 | const sdr::contact::DisplayInfo& rDisplayInfo) override | |||
2905 | { | |||
2906 | bool bPaint( true ); | |||
2907 | ||||
2908 | SdrObject* pObj = rOriginal.GetViewContact().TryToGetSdrObject(); | |||
2909 | if ( pObj ) | |||
2910 | { | |||
2911 | bPaint = SwFlyFrame::IsPaint( pObj, &mrViewShell ); | |||
2912 | } | |||
2913 | ||||
2914 | if ( !bPaint ) | |||
2915 | { | |||
2916 | return drawinglayer::primitive2d::Primitive2DContainer(); | |||
2917 | } | |||
2918 | ||||
2919 | return sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence( | |||
2920 | rOriginal, rDisplayInfo ); | |||
2921 | } | |||
2922 | }; | |||
2923 | ||||
2924 | } // end of anonymous namespace | |||
2925 | // <-- | |||
2926 | ||||
2927 | /** | |||
2928 | * Paint once for every visible page which is touched by Rect | |||
2929 | * | |||
2930 | * 1. Paint borders and backgrounds | |||
2931 | * 2. Paint the draw layer (frames and drawing objects) that is | |||
2932 | * below the document (hell) | |||
2933 | * 3. Paint the document content (text) | |||
2934 | * 4. Paint the draw layer that is above the document | |||
2935 | |*/ | |||
2936 | void SwRootFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const pPrintData) const | |||
2937 | { | |||
2938 | OSL_ENSURE( Lower() && Lower()->IsPageFrame(), "Lower of root is no page." )do { if (true && (!(Lower() && Lower()->IsPageFrame ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "2938" ": "), "%s", "Lower of root is no page."); } } while (false); | |||
2939 | ||||
2940 | PROTOCOL( this, PROT::FileInit, DbgAction::NONE, nullptr) | |||
2941 | ||||
2942 | bool bResetRootPaint = false; | |||
2943 | SwViewShell *pSh = mpCurrShell; | |||
2944 | ||||
2945 | if ( pSh->GetWin() ) | |||
2946 | { | |||
2947 | if ( pSh->GetOut() == pSh->GetWin() && !pSh->GetWin()->IsVisible() ) | |||
2948 | { | |||
2949 | return; | |||
2950 | } | |||
2951 | if (SwRootFrame::s_isInPaint) | |||
2952 | { | |||
2953 | SwPaintQueue::Add( pSh, rRect ); | |||
2954 | return; | |||
2955 | } | |||
2956 | } | |||
2957 | else | |||
2958 | SwRootFrame::s_isInPaint = bResetRootPaint = true; | |||
2959 | ||||
2960 | std::unique_ptr<SwSavePaintStatics> pStatics; | |||
2961 | if ( gProp.pSGlobalShell ) | |||
2962 | pStatics.reset(new SwSavePaintStatics()); | |||
2963 | gProp.pSGlobalShell = pSh; | |||
2964 | ||||
2965 | if( !pSh->GetWin() ) | |||
2966 | gProp.pSProgress = SfxProgress::GetActiveProgress( static_cast<SfxObjectShell*>(pSh->GetDoc()->GetDocShell()) ); | |||
2967 | ||||
2968 | ::SwCalcPixStatics( pSh->GetOut() ); | |||
2969 | aGlobalRetoucheColor = pSh->Imp()->GetRetoucheColor(); | |||
2970 | ||||
2971 | // Copy rRect; for one, rRect could become dangling during the below action, and for another it | |||
2972 | // needs to be copied to aRect anyway as that is modified further down below: | |||
2973 | SwRect aRect( rRect ); | |||
2974 | ||||
2975 | //Trigger an action to clear things up if needed. | |||
2976 | //Using this trick we can ensure that all values are valid in all paints - | |||
2977 | //no problems, no special case(s). | |||
2978 | // #i92745# | |||
2979 | // Extend check on certain states of the 'current' <SwViewShell> instance to | |||
2980 | // all existing <SwViewShell> instances. | |||
2981 | bool bPerformLayoutAction( true ); | |||
2982 | { | |||
2983 | for(SwViewShell& rTmpViewShell : pSh->GetRingContainer()) | |||
2984 | { | |||
2985 | if ( rTmpViewShell.IsInEndAction() || | |||
2986 | rTmpViewShell.IsPaintInProgress() || | |||
2987 | ( rTmpViewShell.Imp()->IsAction() && | |||
2988 | rTmpViewShell.Imp()->GetLayAction().IsActionInProgress() ) ) | |||
2989 | { | |||
2990 | bPerformLayoutAction = false; | |||
2991 | } | |||
2992 | ||||
2993 | if(!bPerformLayoutAction) | |||
2994 | break; | |||
2995 | } | |||
2996 | } | |||
2997 | if ( bPerformLayoutAction ) | |||
2998 | { | |||
2999 | const_cast<SwRootFrame*>(this)->ResetTurbo(); | |||
3000 | SwLayAction aAction( const_cast<SwRootFrame*>(this), pSh->Imp() ); | |||
3001 | aAction.SetPaint( false ); | |||
3002 | aAction.SetComplete( false ); | |||
3003 | aAction.SetReschedule( gProp.pSProgress != nullptr ); | |||
3004 | aAction.Action(&rRenderContext); | |||
3005 | ResetTurboFlag(); | |||
3006 | if ( !pSh->ActionPend() ) | |||
3007 | pSh->Imp()->DelRegion(); | |||
3008 | } | |||
3009 | ||||
3010 | aRect.Intersection( pSh->VisArea() ); | |||
3011 | ||||
3012 | const bool bExtraData = ::IsExtraData( GetFormat()->GetDoc() ); | |||
3013 | ||||
3014 | gProp.pSLines.reset(new SwLineRects); // Container for borders. | |||
3015 | ||||
3016 | // #104289#. During painting, something (OLE) can | |||
3017 | // load the linguistic, which in turn can cause a reformat | |||
3018 | // of the document. Dangerous! We better set this flag to | |||
3019 | // avoid the reformat. | |||
3020 | const bool bOldAction = IsCallbackActionEnabled(); | |||
3021 | const_cast<SwRootFrame*>(this)->SetCallbackActionEnabled( false ); | |||
3022 | ||||
3023 | const SwPageFrame *pPage = pSh->Imp()->GetFirstVisPage(&rRenderContext); | |||
3024 | ||||
3025 | // #126222. The positions of headers and footers of the previous | |||
3026 | // pages have to be updated, else these headers and footers could | |||
3027 | // get visible at a wrong position. | |||
3028 | const SwPageFrame *pPageDeco = static_cast<const SwPageFrame*>(pPage->GetPrev()); | |||
3029 | while (pPageDeco) | |||
3030 | { | |||
3031 | pPageDeco->PaintDecorators(); | |||
3032 | OSL_ENSURE(!pPageDeco->GetPrev() || pPageDeco->GetPrev()->IsPageFrame(),do { if (true && (!(!pPageDeco->GetPrev() || pPageDeco ->GetPrev()->IsPageFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "3033" ": "), "%s", "Neighbour of page is not a page."); } } while (false) | |||
3033 | "Neighbour of page is not a page.")do { if (true && (!(!pPageDeco->GetPrev() || pPageDeco ->GetPrev()->IsPageFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "3033" ": "), "%s", "Neighbour of page is not a page."); } } while (false); | |||
3034 | pPageDeco = static_cast<const SwPageFrame*>(pPageDeco->GetPrev()); | |||
3035 | } | |||
3036 | ||||
3037 | const bool bBookMode = gProp.pSGlobalShell->GetViewOptions()->IsViewLayoutBookMode(); | |||
3038 | if ( bBookMode && pPage->GetPrev() && static_cast<const SwPageFrame*>(pPage->GetPrev())->IsEmptyPage() ) | |||
3039 | pPage = static_cast<const SwPageFrame*>(pPage->GetPrev()); | |||
3040 | ||||
3041 | // #i68597# | |||
3042 | const bool bGridPainting(pSh->GetWin() && pSh->Imp()->HasDrawView() && pSh->Imp()->GetDrawView()->IsGridVisible()); | |||
3043 | ||||
3044 | // Hide all page break controls before showing them again | |||
3045 | SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell ); | |||
3046 | if ( pWrtSh ) | |||
3047 | { | |||
3048 | SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); | |||
3049 | SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); | |||
3050 | const SwPageFrame* pHiddenPage = pPage; | |||
3051 | while ( pHiddenPage->GetPrev() != nullptr ) | |||
3052 | { | |||
3053 | pHiddenPage = static_cast< const SwPageFrame* >( pHiddenPage->GetPrev() ); | |||
3054 | SwFrameControlPtr pControl = rMngr.GetControl( FrameControlType::PageBreak, pHiddenPage ); | |||
3055 | if ( pControl ) | |||
3056 | pControl->ShowAll( false ); | |||
3057 | } | |||
3058 | } | |||
3059 | ||||
3060 | // #i76669# | |||
3061 | SwViewObjectContactRedirector aSwRedirector( *pSh ); | |||
3062 | ||||
3063 | while ( pPage ) | |||
3064 | { | |||
3065 | const bool bPaintRightShadow = pPage->IsRightShadowNeeded(); | |||
3066 | const bool bPaintLeftShadow = pPage->IsLeftShadowNeeded(); | |||
3067 | const bool bRightSidebar = pPage->SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT; | |||
3068 | ||||
3069 | if ( !pPage->IsEmptyPage() ) | |||
3070 | { | |||
3071 | SwRect aPaintRect; | |||
3072 | SwPageFrame::GetBorderAndShadowBoundRect( pPage->getFrameArea(), pSh, &rRenderContext, aPaintRect, | |||
3073 | bPaintLeftShadow, bPaintRightShadow, bRightSidebar ); | |||
3074 | ||||
3075 | if ( aRect.IsOver( aPaintRect ) ) | |||
3076 | { | |||
3077 | if ( pSh->GetWin() ) | |||
3078 | { | |||
3079 | gProp.pSSubsLines.reset(new SwSubsRects); | |||
3080 | gProp.pSSpecSubsLines.reset(new SwSubsRects); | |||
3081 | } | |||
3082 | gProp.pBLines.reset(new BorderLines); | |||
3083 | ||||
3084 | aPaintRect.Intersection_( aRect ); | |||
3085 | ||||
3086 | if ( bExtraData && | |||
3087 | pSh->GetWin() && pSh->IsInEndAction() ) | |||
3088 | { | |||
3089 | // enlarge paint rectangle to complete page width, subtract | |||
3090 | // current paint area and invalidate the resulting region. | |||
3091 | SwRectFnSet aRectFnSet(pPage); | |||
3092 | SwRect aPageRectTemp( aPaintRect ); | |||
3093 | aRectFnSet.SetLeftAndWidth( aPageRectTemp, | |||
3094 | aRectFnSet.GetLeft(pPage->getFrameArea()), | |||
3095 | aRectFnSet.GetWidth(pPage->getFrameArea()) ); | |||
3096 | aPageRectTemp.Intersection_( pSh->VisArea() ); | |||
3097 | vcl::Region aPageRectRegion( aPageRectTemp.SVRect() ); | |||
3098 | aPageRectRegion.Exclude( aPaintRect.SVRect() ); | |||
3099 | pSh->GetWin()->Invalidate( aPageRectRegion, InvalidateFlags::Children ); | |||
3100 | } | |||
3101 | ||||
3102 | // #i80793# | |||
3103 | // enlarge paint rectangle for objects overlapping the same pixel | |||
3104 | // in all cases and before the DrawingLayer overlay is initialized. | |||
3105 | lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) ); | |||
3106 | ||||
3107 | // #i68597# | |||
3108 | // moved paint pre-process for DrawingLayer overlay here since the above | |||
3109 | // code dependent from bExtraData may expand the PaintRect | |||
3110 | { | |||
3111 | // #i75172# if called from SwViewShell::ImplEndAction it should no longer | |||
3112 | // really be used but handled by SwViewShell::ImplEndAction already | |||
3113 | const vcl::Region aDLRegion(aPaintRect.SVRect()); | |||
3114 | pSh->DLPrePaint2(aDLRegion); | |||
3115 | } | |||
3116 | ||||
3117 | if(OUTDEV_WINDOW == gProp.pSGlobalShell->GetOut()->GetOutDevType()) | |||
3118 | { | |||
3119 | // changed method SwLayVout::Enter(..) | |||
3120 | // 2nd parameter is no longer <const> and will be set to the | |||
3121 | // rectangle the virtual output device is calculated from <aPaintRect>, | |||
3122 | // if the virtual output is used. | |||
3123 | s_pVout->Enter(pSh, aPaintRect, !s_isNoVirDev); | |||
3124 | ||||
3125 | // Adjust paint rectangle to pixel size | |||
3126 | // Thus, all objects overlapping on pixel level with the unadjusted | |||
3127 | // paint rectangle will be considered in the paint. | |||
3128 | lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) ); | |||
3129 | } | |||
3130 | ||||
3131 | // maybe this can be put in the above scope. Since we are not sure, just leave it ATM | |||
3132 | s_pVout->SetOrgRect( aPaintRect ); | |||
3133 | ||||
3134 | // determine background color of page for <PaintLayer> method | |||
3135 | // calls, paint <hell> or <heaven> | |||
3136 | const Color aPageBackgrdColor(pPage->GetDrawBackgrdColor()); | |||
3137 | ||||
3138 | pPage->PaintBaBo( aPaintRect, pPage ); | |||
3139 | ||||
3140 | if ( pSh->Imp()->HasDrawView() ) | |||
3141 | { | |||
3142 | gProp.pSLines->LockLines( true ); | |||
3143 | const IDocumentDrawModelAccess& rIDDMA = pSh->getIDocumentDrawModelAccess(); | |||
3144 | pSh->Imp()->PaintLayer( rIDDMA.GetHellId(), | |||
3145 | pPrintData, | |||
3146 | *pPage, pPage->getFrameArea(), | |||
3147 | &aPageBackgrdColor, | |||
3148 | pPage->IsRightToLeft(), | |||
3149 | &aSwRedirector ); | |||
3150 | gProp.pSLines->PaintLines( pSh->GetOut(), gProp ); | |||
3151 | gProp.pSLines->LockLines( false ); | |||
3152 | } | |||
3153 | ||||
3154 | if ( pSh->GetDoc()->GetDocumentSettingManager().get( DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS ) ) | |||
3155 | pPage->PaintBaBo( aPaintRect, pPage, /*bOnlyTextBackground=*/true ); | |||
3156 | ||||
3157 | if( pSh->GetWin() ) | |||
3158 | { | |||
3159 | // collect sub-lines | |||
3160 | pPage->RefreshSubsidiary( aPaintRect ); | |||
3161 | // paint special sub-lines | |||
3162 | gProp.pSSpecSubsLines->PaintSubsidiary( pSh->GetOut(), nullptr, gProp ); | |||
3163 | } | |||
3164 | ||||
3165 | pPage->PaintSwFrame( rRenderContext, aPaintRect ); | |||
3166 | ||||
3167 | // no paint of page border and shadow, if writer is in place mode. | |||
3168 | if( pSh->GetWin() && pSh->GetDoc()->GetDocShell() && | |||
3169 | !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() ) | |||
3170 | { | |||
3171 | SwPageFrame::PaintBorderAndShadow( pPage->getFrameArea(), pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar ); | |||
3172 | SwPageFrame::PaintNotesSidebar( pPage->getFrameArea(), pSh, pPage->GetPhyPageNum(), bRightSidebar); | |||
3173 | } | |||
3174 | ||||
3175 | gProp.pSLines->PaintLines( pSh->GetOut(), gProp ); | |||
3176 | if ( pSh->GetWin() ) | |||
3177 | { | |||
3178 | gProp.pSSubsLines->PaintSubsidiary( pSh->GetOut(), gProp.pSLines.get(), gProp ); | |||
3179 | gProp.pSSubsLines.reset(); | |||
3180 | gProp.pSSpecSubsLines.reset(); | |||
3181 | } | |||
3182 | // fdo#42750: delay painting these until after subsidiary lines | |||
3183 | // fdo#45562: delay painting these until after hell layer | |||
3184 | // fdo#47717: but do it before heaven layer | |||
3185 | ProcessPrimitives(gProp.pBLines->GetBorderLines_Clear()); | |||
3186 | ||||
3187 | if ( pSh->Imp()->HasDrawView() ) | |||
3188 | { | |||
3189 | pSh->Imp()->PaintLayer( pSh->GetDoc()->getIDocumentDrawModelAccess().GetHeavenId(), | |||
3190 | pPrintData, | |||
3191 | *pPage, pPage->getFrameArea(), | |||
3192 | &aPageBackgrdColor, | |||
3193 | pPage->IsRightToLeft(), | |||
3194 | &aSwRedirector ); | |||
3195 | } | |||
3196 | ||||
3197 | if ( bExtraData ) | |||
3198 | pPage->RefreshExtraData( aPaintRect ); | |||
3199 | ||||
3200 | gProp.pBLines.reset(); | |||
3201 | s_pVout->Leave(); | |||
3202 | ||||
3203 | // #i68597# | |||
3204 | // needed to move grid painting inside Begin/EndDrawLayer bounds and to change | |||
3205 | // output rect for it accordingly | |||
3206 | if(bGridPainting) | |||
3207 | { | |||
3208 | SdrPaintView* pPaintView = pSh->Imp()->GetDrawView(); | |||
3209 | SdrPageView* pPageView = pPaintView->GetSdrPageView(); | |||
3210 | pPageView->DrawPageViewGrid(*pSh->GetOut(), aPaintRect.SVRect(), SwViewOption::GetTextGridColor() ); | |||
3211 | } | |||
3212 | ||||
3213 | // #i68597# | |||
3214 | // moved paint post-process for DrawingLayer overlay here, see above | |||
3215 | { | |||
3216 | pSh->DLPostPaint2(true); | |||
3217 | } | |||
3218 | } | |||
3219 | ||||
3220 | pPage->PaintDecorators( ); | |||
3221 | pPage->PaintBreak(); | |||
3222 | } | |||
3223 | else if ( bBookMode && pSh->GetWin() && !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() ) | |||
3224 | { | |||
3225 | // paint empty page | |||
3226 | SwRect aPaintRect; | |||
3227 | SwRect aEmptyPageRect( pPage->getFrameArea() ); | |||
3228 | ||||
3229 | // code from vprint.cxx | |||
3230 | const SwPageFrame& rFormatPage = pPage->GetFormatPage(); | |||
3231 | aEmptyPageRect.SSize( rFormatPage.getFrameArea().SSize() ); | |||
3232 | ||||
3233 | SwPageFrame::GetBorderAndShadowBoundRect( aEmptyPageRect, pSh, &rRenderContext, aPaintRect, | |||
3234 | bPaintLeftShadow, bPaintRightShadow, bRightSidebar ); | |||
3235 | aPaintRect.Intersection_( aRect ); | |||
3236 | ||||
3237 | if ( aRect.IsOver( aEmptyPageRect ) ) | |||
3238 | { | |||
3239 | // #i75172# if called from SwViewShell::ImplEndAction it should no longer | |||
3240 | // really be used but handled by SwViewShell::ImplEndAction already | |||
3241 | { | |||
3242 | const vcl::Region aDLRegion(aPaintRect.SVRect()); | |||
3243 | pSh->DLPrePaint2(aDLRegion); | |||
3244 | } | |||
3245 | ||||
3246 | if( pSh->GetOut()->GetFillColor() != aGlobalRetoucheColor ) | |||
3247 | pSh->GetOut()->SetFillColor( aGlobalRetoucheColor ); | |||
3248 | // No line color | |||
3249 | pSh->GetOut()->SetLineColor(); | |||
3250 | // Use aligned page rectangle | |||
3251 | { | |||
3252 | SwRect aTmpPageRect( aEmptyPageRect ); | |||
3253 | ::SwAlignRect( aTmpPageRect, pSh, &rRenderContext ); | |||
3254 | aEmptyPageRect = aTmpPageRect; | |||
3255 | } | |||
3256 | ||||
3257 | pSh->GetOut()->DrawRect( aEmptyPageRect.SVRect() ); | |||
3258 | ||||
3259 | // paint empty page text | |||
3260 | const vcl::Font& rEmptyPageFont = SwPageFrame::GetEmptyPageFont(); | |||
3261 | const vcl::Font aOldFont( pSh->GetOut()->GetFont() ); | |||
3262 | ||||
3263 | pSh->GetOut()->SetFont( rEmptyPageFont ); | |||
3264 | pSh->GetOut()->DrawText( aEmptyPageRect.SVRect(), SwResId( STR_EMPTYPAGEreinterpret_cast<char const *>("STR_EMPTYPAGE" "\004" u8"blank page" ) ), | |||
3265 | DrawTextFlags::VCenter | | |||
3266 | DrawTextFlags::Center | | |||
3267 | DrawTextFlags::Clip ); | |||
3268 | ||||
3269 | pSh->GetOut()->SetFont( aOldFont ); | |||
3270 | // paint shadow and border for empty page | |||
3271 | SwPageFrame::PaintBorderAndShadow( aEmptyPageRect, pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar ); | |||
3272 | SwPageFrame::PaintNotesSidebar( aEmptyPageRect, pSh, pPage->GetPhyPageNum(), bRightSidebar); | |||
3273 | ||||
3274 | { | |||
3275 | pSh->DLPostPaint2(true); | |||
3276 | } | |||
3277 | } | |||
3278 | } | |||
3279 | ||||
3280 | OSL_ENSURE( !pPage->GetNext() || pPage->GetNext()->IsPageFrame(),do { if (true && (!(!pPage->GetNext() || pPage-> GetNext()->IsPageFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "3281" ": "), "%s", "Neighbour of page is not a page."); } } while (false) | |||
3281 | "Neighbour of page is not a page." )do { if (true && (!(!pPage->GetNext() || pPage-> GetNext()->IsPageFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "3281" ": "), "%s", "Neighbour of page is not a page."); } } while (false); | |||
3282 | pPage = static_cast<const SwPageFrame*>(pPage->GetNext()); | |||
3283 | } | |||
3284 | ||||
3285 | gProp.pSLines.reset(); | |||
3286 | ||||
3287 | if ( bResetRootPaint ) | |||
3288 | SwRootFrame::s_isInPaint = false; | |||
3289 | if ( pStatics ) | |||
3290 | pStatics.reset(); | |||
3291 | else | |||
3292 | { | |||
3293 | gProp.pSProgress = nullptr; | |||
3294 | gProp.pSGlobalShell = nullptr; | |||
3295 | } | |||
3296 | ||||
3297 | const_cast<SwRootFrame*>(this)->SetCallbackActionEnabled( bOldAction ); | |||
3298 | } | |||
3299 | ||||
3300 | static void lcl_EmergencyFormatFootnoteCont( SwFootnoteContFrame *pCont ) | |||
3301 | { | |||
3302 | vcl::RenderContext* pRenderContext = pCont->getRootFrame()->GetCurrShell()->GetOut(); | |||
3303 | ||||
3304 | //It's possible that the Cont will get destroyed. | |||
3305 | SwContentFrame *pCnt = pCont->ContainsContent(); | |||
3306 | while ( pCnt && pCnt->IsInFootnote() ) | |||
3307 | { | |||
3308 | pCnt->Calc(pRenderContext); | |||
3309 | pCnt = pCnt->GetNextContentFrame(); | |||
3310 | } | |||
3311 | } | |||
3312 | ||||
3313 | namespace { | |||
3314 | ||||
3315 | class SwShortCut | |||
3316 | { | |||
3317 | SwRectDist fnCheck; | |||
3318 | long nLimit; | |||
3319 | public: | |||
3320 | SwShortCut( const SwFrame& rFrame, const SwRect& rRect ); | |||
3321 | bool Stop( const SwRect& rRect ) const | |||
3322 | { return (rRect.*fnCheck)( nLimit ) > 0; } | |||
3323 | }; | |||
3324 | ||||
3325 | } | |||
3326 | ||||
3327 | SwShortCut::SwShortCut( const SwFrame& rFrame, const SwRect& rRect ) | |||
3328 | { | |||
3329 | bool bVert = rFrame.IsVertical(); | |||
3330 | bool bR2L = rFrame.IsRightToLeft(); | |||
3331 | if( rFrame.IsNeighbourFrame() && bVert == bR2L ) | |||
3332 | { | |||
3333 | if( bVert ) | |||
3334 | { | |||
3335 | fnCheck = &SwRect::GetBottomDistance; | |||
3336 | nLimit = rRect.Top(); | |||
3337 | } | |||
3338 | else | |||
3339 | { | |||
3340 | fnCheck = &SwRect::GetLeftDistance; | |||
3341 | nLimit = rRect.Left() + rRect.Width(); | |||
3342 | } | |||
3343 | } | |||
3344 | else if( bVert == rFrame.IsNeighbourFrame() ) | |||
3345 | { | |||
3346 | fnCheck = &SwRect::GetTopDistance; | |||
3347 | nLimit = rRect.Top() + rRect.Height(); | |||
3348 | } | |||
3349 | else | |||
3350 | { | |||
3351 | if ( rFrame.IsVertLR() ) | |||
3352 | { | |||
3353 | fnCheck = &SwRect::GetLeftDistance; | |||
3354 | nLimit = rRect.Right(); | |||
3355 | } | |||
3356 | else | |||
3357 | { | |||
3358 | fnCheck = &SwRect::GetRightDistance; | |||
3359 | nLimit = rRect.Left(); | |||
3360 | } | |||
3361 | } | |||
3362 | } | |||
3363 | ||||
3364 | void SwLayoutFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const | |||
3365 | { | |||
3366 | // #i16816# tagged pdf support | |||
3367 | Frame_Info aFrameInfo( *this ); | |||
3368 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, &aFrameInfo, nullptr, rRenderContext ); | |||
3369 | ||||
3370 | const SwFrame *pFrame = Lower(); | |||
3371 | if ( !pFrame ) | |||
3372 | return; | |||
3373 | ||||
3374 | SwFrameDeleteGuard g(const_cast<SwLayoutFrame*>(this)); // lock because Calc() and recursion | |||
3375 | SwShortCut aShortCut( *pFrame, rRect ); | |||
3376 | bool bCnt = pFrame->IsContentFrame(); | |||
3377 | if ( bCnt ) | |||
3378 | pFrame->Calc(&rRenderContext); | |||
3379 | ||||
3380 | if ( pFrame->IsFootnoteContFrame() ) | |||
3381 | { | |||
3382 | ::lcl_EmergencyFormatFootnoteCont( const_cast<SwFootnoteContFrame*>(static_cast<const SwFootnoteContFrame*>(pFrame)) ); | |||
3383 | pFrame = Lower(); | |||
3384 | } | |||
3385 | ||||
3386 | const SwPageFrame *pPage = nullptr; | |||
3387 | bool bWin = gProp.pSGlobalShell->GetWin() != nullptr; | |||
3388 | if (comphelper::LibreOfficeKit::isTiledPainting()) | |||
3389 | // Tiled rendering is similar to printing in this case: painting transparently multiple | |||
3390 | // times will result in darker colors: avoid that. | |||
3391 | bWin = false; | |||
3392 | ||||
3393 | while ( IsAnLower( pFrame ) ) | |||
3394 | { | |||
3395 | SwRect aPaintRect( pFrame->GetPaintArea() ); | |||
3396 | if( aShortCut.Stop( aPaintRect ) ) | |||
3397 | break; | |||
3398 | if ( bCnt && gProp.pSProgress ) | |||
3399 | SfxProgress::Reschedule(); | |||
3400 | ||||
3401 | //We need to retouch if a frame explicitly requests it. | |||
3402 | //First do the retouch, because this could flatten the borders. | |||
3403 | if ( pFrame->IsRetouche() ) | |||
3404 | { | |||
3405 | if ( pFrame->IsRetoucheFrame() && bWin && !pFrame->GetNext() ) | |||
3406 | { | |||
3407 | if ( !pPage ) | |||
3408 | pPage = FindPageFrame(); | |||
3409 | pFrame->Retouch( pPage, rRect ); | |||
3410 | } | |||
3411 | pFrame->ResetRetouche(); | |||
3412 | } | |||
3413 | ||||
3414 | if ( rRect.IsOver( aPaintRect ) ) | |||
3415 | { | |||
3416 | if ( bCnt && pFrame->IsCompletePaint() && | |||
3417 | !rRect.IsInside( aPaintRect ) && Application::AnyInput( VclInputFlags::KEYBOARD ) ) | |||
3418 | { | |||
3419 | //fix(8104): It may happen, that the processing wasn't complete | |||
3420 | //but some parts of the paragraph were still repainted. | |||
3421 | //This could lead to the situation, that other parts of the | |||
3422 | //paragraph won't be repainted at all. The only solution seems | |||
3423 | //to be an invalidation of the window. | |||
3424 | //To not make it too severe the rectangle is limited by | |||
3425 | //painting the desired part and only invalidating the | |||
3426 | //remaining paragraph parts. | |||
3427 | if ( aPaintRect.Left() == rRect.Left() && | |||
3428 | aPaintRect.Right() == rRect.Right() ) | |||
3429 | { | |||
3430 | aPaintRect.Bottom( rRect.Top() - 1 ); | |||
3431 | if ( aPaintRect.Height() > 0 ) | |||
3432 | gProp.pSGlobalShell->InvalidateWindows(aPaintRect); | |||
3433 | aPaintRect.Top( rRect.Bottom() + 1 ); | |||
3434 | aPaintRect.Bottom( pFrame->getFrameArea().Bottom() ); | |||
3435 | if ( aPaintRect.Height() > 0 ) | |||
3436 | gProp.pSGlobalShell->InvalidateWindows(aPaintRect); | |||
3437 | aPaintRect.Top( pFrame->getFrameArea().Top() ); | |||
3438 | aPaintRect.Bottom( pFrame->getFrameArea().Bottom() ); | |||
3439 | } | |||
3440 | else | |||
3441 | { | |||
3442 | gProp.pSGlobalShell->InvalidateWindows( aPaintRect ); | |||
3443 | pFrame = pFrame->GetNext(); | |||
3444 | if ( pFrame ) | |||
3445 | { | |||
3446 | bCnt = pFrame->IsContentFrame(); | |||
3447 | if ( bCnt ) | |||
3448 | pFrame->Calc(&rRenderContext); | |||
3449 | } | |||
3450 | continue; | |||
3451 | } | |||
3452 | } | |||
3453 | pFrame->ResetCompletePaint(); | |||
3454 | aPaintRect.Intersection_( rRect ); | |||
3455 | ||||
3456 | pFrame->PaintSwFrame( rRenderContext, aPaintRect ); | |||
3457 | ||||
3458 | if ( Lower() && Lower()->IsColumnFrame() ) | |||
3459 | { | |||
3460 | //Paint the column separator line if needed. The page is | |||
3461 | //responsible for the page frame - not the upper. | |||
3462 | const SwFrameFormat *pFormat = GetUpper() && GetUpper()->IsPageFrame() | |||
3463 | ? GetUpper()->GetFormat() | |||
3464 | : GetFormat(); | |||
3465 | const SwFormatCol &rCol = pFormat->GetCol(); | |||
3466 | if ( rCol.GetLineAdj() != COLADJ_NONE ) | |||
3467 | { | |||
3468 | if ( !pPage ) | |||
3469 | pPage = pFrame->FindPageFrame(); | |||
3470 | ||||
3471 | PaintColLines( aPaintRect, rCol, pPage ); | |||
3472 | } | |||
3473 | } | |||
3474 | } | |||
3475 | if ( !bCnt && pFrame->GetNext() && pFrame->GetNext()->IsFootnoteContFrame() ) | |||
3476 | ::lcl_EmergencyFormatFootnoteCont( const_cast<SwFootnoteContFrame*>(static_cast<const SwFootnoteContFrame*>(pFrame->GetNext())) ); | |||
3477 | ||||
3478 | pFrame = pFrame->GetNext(); | |||
3479 | ||||
3480 | if ( pFrame ) | |||
3481 | { | |||
3482 | bCnt = pFrame->IsContentFrame(); | |||
3483 | if ( bCnt ) | |||
3484 | pFrame->Calc(&rRenderContext); | |||
3485 | } | |||
3486 | } | |||
3487 | } | |||
3488 | ||||
3489 | static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateDashedIndicatorPrimitive( | |||
3490 | const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd, | |||
3491 | basegfx::BColor aColor ) | |||
3492 | { | |||
3493 | drawinglayer::primitive2d::Primitive2DContainer aSeq( 1 ); | |||
3494 | ||||
3495 | std::vector< double > aStrokePattern; | |||
3496 | basegfx::B2DPolygon aLinePolygon; | |||
3497 | aLinePolygon.append(rStart); | |||
3498 | aLinePolygon.append(rEnd); | |||
3499 | ||||
3500 | const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); | |||
3501 | if ( rSettings.GetHighContrastMode( ) ) | |||
3502 | { | |||
3503 | // Only a solid line in high contrast mode | |||
3504 | aColor = rSettings.GetDialogTextColor().getBColor(); | |||
3505 | } | |||
3506 | else | |||
3507 | { | |||
3508 | // Get a color for the contrast | |||
3509 | basegfx::BColor aHslLine = basegfx::utils::rgb2hsl( aColor ); | |||
3510 | double nLuminance = aHslLine.getZ() * 2.5; | |||
3511 | if ( nLuminance == 0 ) | |||
3512 | nLuminance = 0.5; | |||
3513 | else if ( nLuminance >= 1.0 ) | |||
3514 | nLuminance = aHslLine.getZ() * 0.4; | |||
3515 | aHslLine.setZ( nLuminance ); | |||
3516 | const basegfx::BColor aOtherColor = basegfx::utils::hsl2rgb( aHslLine ); | |||
3517 | ||||
3518 | // Compute the plain line | |||
3519 | drawinglayer::primitive2d::PolygonHairlinePrimitive2D * pPlainLine = | |||
3520 | new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( | |||
3521 | aLinePolygon, aOtherColor ); | |||
3522 | ||||
3523 | aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( pPlainLine ); | |||
3524 | ||||
3525 | // Dashed line in twips | |||
3526 | aStrokePattern.push_back( 40 ); | |||
3527 | aStrokePattern.push_back( 40 ); | |||
3528 | ||||
3529 | aSeq.resize( 2 ); | |||
3530 | } | |||
3531 | ||||
3532 | // Compute the dashed line primitive | |||
3533 | drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D * pLine = | |||
3534 | new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D ( | |||
3535 | basegfx::B2DPolyPolygon( aLinePolygon ), | |||
3536 | drawinglayer::attribute::LineAttribute( aColor ), | |||
3537 | drawinglayer::attribute::StrokeAttribute( aStrokePattern ) ); | |||
3538 | ||||
3539 | aSeq[ aSeq.size( ) - 1 ] = drawinglayer::primitive2d::Primitive2DReference( pLine ); | |||
3540 | ||||
3541 | return aSeq; | |||
3542 | } | |||
3543 | ||||
3544 | void SwPageFrame::PaintBreak( ) const | |||
3545 | { | |||
3546 | if ( gProp.pSGlobalShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER || | |||
3547 | gProp.pSGlobalShell->GetViewOptions()->IsPDFExport() || | |||
3548 | gProp.pSGlobalShell->GetViewOptions()->IsReadonly() || | |||
3549 | gProp.pSGlobalShell->IsPreview() ) | |||
3550 | return; | |||
3551 | ||||
3552 | const SwFrame* pBodyFrame = Lower(); | |||
3553 | while ( pBodyFrame && !pBodyFrame->IsBodyFrame() ) | |||
3554 | pBodyFrame = pBodyFrame->GetNext(); | |||
3555 | ||||
3556 | if ( pBodyFrame ) | |||
3557 | { | |||
3558 | const SwLayoutFrame* pLayBody = static_cast< const SwLayoutFrame* >( pBodyFrame ); | |||
3559 | const SwFlowFrame *pFlowFrame = pLayBody->ContainsContent(); | |||
3560 | ||||
3561 | // Test if the first node is a table | |||
3562 | const SwFrame* pFirstFrame = pLayBody->Lower(); | |||
3563 | if ( pFirstFrame && pFirstFrame->IsTabFrame() ) | |||
3564 | pFlowFrame = static_cast< const SwTabFrame* >( pFirstFrame ); | |||
3565 | ||||
3566 | SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell ); | |||
3567 | if ( pWrtSh ) | |||
3568 | { | |||
3569 | SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); | |||
3570 | SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); | |||
3571 | ||||
3572 | if ( pFlowFrame && pFlowFrame->IsPageBreak( true ) ) | |||
3573 | rMngr.SetPageBreakControl( this ); | |||
3574 | else | |||
3575 | rMngr.RemoveControlsByType( FrameControlType::PageBreak, this ); | |||
3576 | } | |||
3577 | } | |||
3578 | SwLayoutFrame::PaintBreak( ); | |||
3579 | } | |||
3580 | ||||
3581 | void SwColumnFrame::PaintBreak( ) const | |||
3582 | { | |||
3583 | if ( gProp.pSGlobalShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER || | |||
3584 | gProp.pSGlobalShell->GetViewOptions()->IsPDFExport() || | |||
3585 | gProp.pSGlobalShell->GetViewOptions()->IsReadonly() || | |||
3586 | gProp.pSGlobalShell->IsPreview() ) | |||
3587 | return; | |||
3588 | ||||
3589 | const SwFrame* pBodyFrame = Lower(); | |||
3590 | while ( pBodyFrame && !pBodyFrame->IsBodyFrame() ) | |||
3591 | pBodyFrame = pBodyFrame->GetNext(); | |||
3592 | ||||
3593 | if ( !pBodyFrame ) | |||
3594 | return; | |||
3595 | ||||
3596 | const SwContentFrame *pCnt = static_cast< const SwLayoutFrame* >( pBodyFrame )->ContainsContent(); | |||
3597 | if ( !(pCnt && pCnt->IsColBreak( true )) ) | |||
3598 | return; | |||
3599 | ||||
3600 | // Paint the break only if: | |||
3601 | // * Not in header footer edition, to avoid conflicts with the | |||
3602 | // header/footer marker | |||
3603 | // * Non-printing characters are shown, as this is more consistent | |||
3604 | // with other formatting marks | |||
3605 | if ( !(!gProp.pSGlobalShell->IsShowHeaderFooterSeparator( FrameControlType::Header ) && | |||
3606 | !gProp.pSGlobalShell->IsShowHeaderFooterSeparator( FrameControlType::Footer ) && | |||
3607 | gProp.pSGlobalShell->GetViewOptions()->IsLineBreak()) ) | |||
3608 | return; | |||
3609 | ||||
3610 | SwRect aRect( pCnt->getFramePrintArea() ); | |||
3611 | aRect.Pos() += pCnt->getFrameArea().Pos(); | |||
3612 | ||||
3613 | // Draw the line | |||
3614 | basegfx::B2DPoint aStart( double( aRect.Left() ), aRect.Top() ); | |||
3615 | basegfx::B2DPoint aEnd( double( aRect.Right() ), aRect.Top() ); | |||
3616 | double nWidth = aRect.Width(); | |||
3617 | if ( IsVertical( ) ) | |||
3618 | { | |||
3619 | aStart = basegfx::B2DPoint( double( aRect.Right() ), double( aRect.Top() ) ); | |||
3620 | aEnd = basegfx::B2DPoint( double( aRect.Right() ), double( aRect.Bottom() ) ); | |||
3621 | nWidth = aRect.Height(); | |||
3622 | } | |||
3623 | ||||
3624 | basegfx::BColor aLineColor = SwViewOption::GetPageBreakColor().getBColor(); | |||
3625 | ||||
3626 | drawinglayer::primitive2d::Primitive2DContainer aSeq = | |||
3627 | lcl_CreateDashedIndicatorPrimitive( aStart, aEnd, aLineColor ); | |||
3628 | ||||
3629 | // Add the text above | |||
3630 | OUString aBreakText = SwResId(STR_COLUMN_BREAKreinterpret_cast<char const *>("STR_COLUMN_BREAK" "\004" u8"Manual Column Break")); | |||
3631 | ||||
3632 | basegfx::B2DVector aFontSize; | |||
3633 | OutputDevice* pOut = gProp.pSGlobalShell->GetOut(); | |||
3634 | vcl::Font aFont = pOut->GetSettings().GetStyleSettings().GetToolFont(); | |||
3635 | aFont.SetFontHeight( 8 * 20 ); | |||
3636 | pOut->SetFont( aFont ); | |||
3637 | drawinglayer::attribute::FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont( | |||
3638 | aFontSize, aFont, IsRightToLeft(), false ); | |||
3639 | ||||
3640 | tools::Rectangle aTextRect; | |||
3641 | pOut->GetTextBoundRect( aTextRect, aBreakText ); | |||
3642 | long nTextOff = ( nWidth - aTextRect.GetWidth() ) / 2; | |||
3643 | ||||
3644 | basegfx::B2DHomMatrix aTextMatrix( basegfx::utils::createScaleTranslateB2DHomMatrix( | |||
3645 | aFontSize.getX(), aFontSize.getY(), | |||
3646 | aRect.Left() + nTextOff, aRect.Top() ) ); | |||
3647 | if ( IsVertical() ) | |||
3648 | { | |||
3649 | aTextMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix ( | |||
3650 | aFontSize.getX(), aFontSize.getY(), 0.0, M_PI_21.57079632679489661923, | |||
3651 | aRect.Right(), aRect.Top() + nTextOff ); | |||
3652 | } | |||
3653 | ||||
3654 | drawinglayer::primitive2d::TextSimplePortionPrimitive2D * pText = | |||
3655 | new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( | |||
3656 | aTextMatrix, | |||
3657 | aBreakText, 0, aBreakText.getLength(), | |||
3658 | std::vector< double >(), | |||
3659 | aFontAttr, | |||
3660 | lang::Locale(), | |||
3661 | aLineColor ); | |||
3662 | aSeq.push_back( drawinglayer::primitive2d::Primitive2DReference( pText ) ); | |||
3663 | ||||
3664 | ProcessPrimitives( aSeq ); | |||
3665 | } | |||
3666 | ||||
3667 | void SwLayoutFrame::PaintBreak( ) const | |||
3668 | { | |||
3669 | const SwFrame* pFrame = Lower(); | |||
3670 | while ( pFrame ) | |||
3671 | { | |||
3672 | if ( pFrame->IsLayoutFrame() ) | |||
3673 | static_cast< const SwLayoutFrame*>( pFrame )->PaintBreak( ); | |||
3674 | pFrame = pFrame->GetNext(); | |||
3675 | } | |||
3676 | } | |||
3677 | ||||
3678 | void SwPageFrame::PaintDecorators( ) const | |||
3679 | { | |||
3680 | SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell ); | |||
3681 | if ( !pWrtSh ) | |||
3682 | return; | |||
3683 | ||||
3684 | SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin(); | |||
3685 | ||||
3686 | const SwLayoutFrame* pBody = FindBodyCont(); | |||
3687 | if ( !pBody ) | |||
3688 | return; | |||
3689 | ||||
3690 | SwRect aBodyRect( pBody->getFrameArea() ); | |||
3691 | ||||
3692 | if ( !(gProp.pSGlobalShell->GetOut()->GetOutDevType() != OUTDEV_PRINTER && | |||
3693 | !gProp.pSGlobalShell->GetViewOptions()->IsPDFExport() && | |||
3694 | !gProp.pSGlobalShell->IsPreview() && | |||
3695 | !gProp.pSGlobalShell->GetViewOptions()->IsReadonly() && | |||
3696 | !gProp.pSGlobalShell->GetViewOptions()->getBrowseMode() && | |||
3697 | ( gProp.pSGlobalShell->IsShowHeaderFooterSeparator( FrameControlType::Header ) || | |||
3698 | gProp.pSGlobalShell->IsShowHeaderFooterSeparator( FrameControlType::Footer ) )) ) | |||
3699 | return; | |||
3700 | ||||
3701 | bool bRtl = AllSettings::GetLayoutRTL(); | |||
3702 | const SwRect& rVisArea = gProp.pSGlobalShell->VisArea(); | |||
3703 | long nXOff = std::min( aBodyRect.Right(), rVisArea.Right() ); | |||
3704 | if ( bRtl ) | |||
3705 | nXOff = std::max( aBodyRect.Left(), rVisArea.Left() ); | |||
3706 | ||||
3707 | // Header | |||
3708 | if ( gProp.pSGlobalShell->IsShowHeaderFooterSeparator( FrameControlType::Header ) ) | |||
3709 | { | |||
3710 | const SwFrame* pHeaderFrame = Lower(); | |||
3711 | if ( !pHeaderFrame->IsHeaderFrame() ) | |||
3712 | pHeaderFrame = nullptr; | |||
3713 | ||||
3714 | long nHeaderYOff = aBodyRect.Top(); | |||
3715 | Point nOutputOff = rEditWin.LogicToPixel( Point( nXOff, nHeaderYOff ) ); | |||
3716 | rEditWin.GetFrameControlsManager().SetHeaderFooterControl( this, FrameControlType::Header, nOutputOff ); | |||
3717 | } | |||
3718 | ||||
3719 | // Footer | |||
3720 | if ( !gProp.pSGlobalShell->IsShowHeaderFooterSeparator( FrameControlType::Footer ) ) | |||
3721 | return; | |||
3722 | ||||
3723 | const SwFrame* pFootnoteContFrame = Lower(); | |||
3724 | while ( pFootnoteContFrame ) | |||
3725 | { | |||
3726 | if ( pFootnoteContFrame->IsFootnoteContFrame() ) | |||
3727 | aBodyRect.AddBottom( pFootnoteContFrame->getFrameArea().Bottom() - aBodyRect.Bottom() ); | |||
3728 | pFootnoteContFrame = pFootnoteContFrame->GetNext(); | |||
3729 | } | |||
3730 | ||||
3731 | long nFooterYOff = aBodyRect.Bottom(); | |||
3732 | Point nOutputOff = rEditWin.LogicToPixel( Point( nXOff, nFooterYOff ) ); | |||
3733 | rEditWin.GetFrameControlsManager().SetHeaderFooterControl( this, FrameControlType::Footer, nOutputOff ); | |||
3734 | } | |||
3735 | ||||
3736 | /** | |||
3737 | * For feature #99657# | |||
3738 | * | |||
3739 | * OD 12.08.2002 | |||
3740 | * determines, if background of fly frame has to be drawn transparent | |||
3741 | * declaration found in /core/inc/flyfrm.cxx | |||
3742 | * | |||
3743 | * OD 08.10.2002 #103898# - If the background of the fly frame itself is not | |||
3744 | * transparent and the background is inherited from its parent/grandparent, | |||
3745 | * the background brush, used for drawing, has to be investigated for transparency. | |||
3746 | * | |||
3747 | * @return true, if background is transparent drawn | |||
3748 | */ | |||
3749 | bool SwFlyFrame::IsBackgroundTransparent() const | |||
3750 | { | |||
3751 | bool bBackgroundTransparent = GetFormat()->IsBackgroundTransparent(); | |||
3752 | if ( !bBackgroundTransparent && | |||
3753 | GetFormat()->IsBackgroundBrushInherited() ) | |||
3754 | { | |||
3755 | const SvxBrushItem* pBackgrdBrush = nullptr; | |||
3756 | const Color* pSectionTOXColor = nullptr; | |||
3757 | SwRect aDummyRect; | |||
3758 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes; | |||
3759 | ||||
3760 | if ( GetBackgroundBrush( aFillAttributes, pBackgrdBrush, pSectionTOXColor, aDummyRect, false, /*bConsiderTextBox=*/false) ) | |||
3761 | { | |||
3762 | if ( pSectionTOXColor && | |||
3763 | (pSectionTOXColor->GetTransparency() != 0) && | |||
3764 | (*pSectionTOXColor != COL_TRANSPARENT) ) | |||
3765 | { | |||
3766 | bBackgroundTransparent = true; | |||
3767 | } | |||
3768 | else if(aFillAttributes && aFillAttributes->isUsed()) | |||
3769 | { | |||
3770 | bBackgroundTransparent = aFillAttributes->isTransparent(); | |||
3771 | } | |||
3772 | else if ( pBackgrdBrush ) | |||
3773 | { | |||
3774 | if ( (pBackgrdBrush->GetColor().GetTransparency() != 0) && | |||
3775 | (pBackgrdBrush->GetColor() != COL_TRANSPARENT) ) | |||
3776 | { | |||
3777 | bBackgroundTransparent = true; | |||
3778 | } | |||
3779 | else | |||
3780 | { | |||
3781 | const GraphicObject *pTmpGrf = | |||
3782 | pBackgrdBrush->GetGraphicObject(); | |||
3783 | if ( pTmpGrf && | |||
3784 | (pTmpGrf->GetAttr().GetTransparency() != 0) | |||
3785 | ) | |||
3786 | { | |||
3787 | bBackgroundTransparent = true; | |||
3788 | } | |||
3789 | } | |||
3790 | } | |||
3791 | } | |||
3792 | } | |||
3793 | ||||
3794 | return bBackgroundTransparent; | |||
3795 | }; | |||
3796 | ||||
3797 | bool SwFlyFrame::IsPaint( SdrObject *pObj, const SwViewShell *pSh ) | |||
3798 | { | |||
3799 | SdrObjUserCall *pUserCall = GetUserCall(pObj); | |||
3800 | ||||
3801 | if ( nullptr == pUserCall ) | |||
3802 | return true; | |||
3803 | ||||
3804 | //Attribute dependent, don't paint for printer or Preview | |||
3805 | bool bPaint = gProp.pSFlyOnlyDraw || | |||
3806 | static_cast<SwContact*>(pUserCall)->GetFormat()->GetPrint().GetValue(); | |||
3807 | if ( !bPaint ) | |||
3808 | bPaint = pSh->GetWin() && !pSh->IsPreview(); | |||
3809 | ||||
3810 | if ( bPaint ) | |||
3811 | { | |||
3812 | //The paint may be prevented by the superior Flys. | |||
3813 | SwFrame *pAnch = nullptr; | |||
3814 | if ( dynamic_cast< const SwFlyDrawObj *>( pObj ) != nullptr ) // i#117962# | |||
3815 | { | |||
3816 | bPaint = false; | |||
3817 | } | |||
3818 | if ( dynamic_cast< const SwVirtFlyDrawObj *>( pObj ) != nullptr ) | |||
3819 | { | |||
3820 | SwFlyFrame *pFly = static_cast<SwVirtFlyDrawObj*>(pObj)->GetFlyFrame(); | |||
3821 | if ( gProp.pSFlyOnlyDraw && gProp.pSFlyOnlyDraw == pFly ) | |||
3822 | return true; | |||
3823 | ||||
3824 | //Try to avoid displaying the intermediate stage, Flys which don't | |||
3825 | //overlap with the page on which they are anchored won't be | |||
3826 | //painted. | |||
3827 | //HACK: exception: printing of frames in tables, those can overlap | |||
3828 | //a page once in a while when dealing with oversized tables (HTML). | |||
3829 | SwPageFrame *pPage = pFly->FindPageFrame(); | |||
3830 | if ( pPage && pPage->getFrameArea().IsOver( pFly->getFrameArea() ) ) | |||
3831 | { | |||
3832 | pAnch = pFly->AnchorFrame(); | |||
3833 | } | |||
3834 | ||||
3835 | } | |||
3836 | else | |||
3837 | { | |||
3838 | // Consider 'virtual' drawing objects | |||
3839 | SwDrawContact* pDrawContact = dynamic_cast<SwDrawContact*>(pUserCall); | |||
3840 | pAnch = pDrawContact ? pDrawContact->GetAnchorFrame(pObj) : nullptr; | |||
3841 | if ( pAnch ) | |||
3842 | { | |||
3843 | if ( !pAnch->isFrameAreaPositionValid() ) | |||
3844 | pAnch = nullptr; | |||
3845 | else if ( pSh->GetOut() == pSh->getIDocumentDeviceAccess().getPrinter( false )) | |||
3846 | { | |||
3847 | //HACK: we have to omit some of the objects for printing, | |||
3848 | //otherwise they would be printed twice. | |||
3849 | //The objects should get printed if the TableHack is active | |||
3850 | //right now. Afterwards they must not be printed if the | |||
3851 | //page over which they float position wise gets printed. | |||
3852 | const SwPageFrame *pPage = pAnch->FindPageFrame(); | |||
3853 | if ( !pPage->getFrameArea().IsOver( pObj->GetCurrentBoundRect() ) ) | |||
3854 | pAnch = nullptr; | |||
3855 | } | |||
3856 | } | |||
3857 | else | |||
3858 | { | |||
3859 | if ( dynamic_cast< const SdrObjGroup *>( pObj ) == nullptr ) | |||
3860 | { | |||
3861 | OSL_FAIL( "<SwFlyFrame::IsPaint(..)> - paint of drawing object without anchor frame!?" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "3861" ": "), "%s", "<SwFlyFrame::IsPaint(..)> - paint of drawing object without anchor frame!?" ); } } while (false); | |||
3862 | } | |||
3863 | } | |||
3864 | } | |||
3865 | if ( pAnch ) | |||
3866 | { | |||
3867 | if ( pAnch->IsInFly() ) | |||
3868 | bPaint = SwFlyFrame::IsPaint( pAnch->FindFlyFrame()->GetVirtDrawObj(), | |||
3869 | pSh ); | |||
3870 | else if ( gProp.pSFlyOnlyDraw ) | |||
3871 | bPaint = false; | |||
3872 | } | |||
3873 | else | |||
3874 | bPaint = false; | |||
3875 | } | |||
3876 | return bPaint; | |||
3877 | } | |||
3878 | ||||
3879 | void SwCellFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const | |||
3880 | { | |||
3881 | if ( GetLayoutRowSpan() >= 1 ) | |||
3882 | SwLayoutFrame::PaintSwFrame( rRenderContext, rRect ); | |||
3883 | } | |||
3884 | ||||
3885 | namespace { | |||
3886 | ||||
3887 | struct BorderLinesGuard | |||
3888 | { | |||
3889 | explicit BorderLinesGuard() : m_pBorderLines(std::move(gProp.pBLines)) | |||
3890 | { | |||
3891 | gProp.pBLines.reset(new BorderLines); | |||
3892 | } | |||
3893 | ~BorderLinesGuard() | |||
3894 | { | |||
3895 | gProp.pBLines = std::move(m_pBorderLines); | |||
3896 | } | |||
3897 | private: | |||
3898 | std::unique_ptr<BorderLines> m_pBorderLines; | |||
3899 | }; | |||
3900 | ||||
3901 | } | |||
3902 | ||||
3903 | void SwFlyFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const | |||
3904 | { | |||
3905 | //optimize thumbnail generation and store procedure to improve odt saving performance, #i120030# | |||
3906 | SwViewShell *pShell = getRootFrame()->GetCurrShell(); | |||
3907 | if (pShell && pShell->GetDoc() && pShell->GetDoc()->GetDocShell()) | |||
3908 | { | |||
3909 | bool bInGenerateThumbnail = pShell->GetDoc()->GetDocShell()->IsInGenerateAndStoreThumbnail(); | |||
3910 | if (bInGenerateThumbnail) | |||
3911 | { | |||
3912 | const SwRect& aVisRect = pShell->VisArea(); | |||
3913 | if (!aVisRect.IsOver(getFrameArea())) | |||
3914 | return; | |||
3915 | } | |||
3916 | } | |||
3917 | ||||
3918 | //because of the overlapping of frames and drawing objects the flys have to | |||
3919 | //paint their borders (and those of the internal ones) directly. | |||
3920 | //e.g. #33066# | |||
3921 | gProp.pSLines->LockLines(true); | |||
3922 | BorderLinesGuard blg; // this should not paint borders added from PaintBaBo | |||
3923 | ||||
3924 | SwRect aRect( rRect ); | |||
3925 | aRect.Intersection_( getFrameArea() ); | |||
3926 | ||||
3927 | rRenderContext.Push( PushFlags::CLIPREGION ); | |||
3928 | rRenderContext.SetClipRegion(); | |||
3929 | const SwPageFrame* pPage = FindPageFrame(); | |||
3930 | ||||
3931 | const SwNoTextFrame *pNoText = Lower() && Lower()->IsNoTextFrame() | |||
3932 | ? static_cast<const SwNoTextFrame*>(Lower()) : nullptr; | |||
3933 | ||||
3934 | bool bIsChart = false; //#i102950# don't paint additional borders for charts | |||
3935 | //check whether we have a chart | |||
3936 | if(pNoText) | |||
3937 | { | |||
3938 | const SwNoTextNode* pNoTNd = dynamic_cast<const SwNoTextNode*>(pNoText->GetNode()); | |||
3939 | if( pNoTNd ) | |||
3940 | { | |||
3941 | SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTNd->GetOLENode()); | |||
3942 | if( pOLENd && pOLENd->GetOLEObj().GetObject().IsChart() ) | |||
3943 | bIsChart = true; | |||
3944 | } | |||
3945 | } | |||
3946 | ||||
3947 | { | |||
3948 | bool bContour = GetFormat()->GetSurround().IsContour(); | |||
3949 | tools::PolyPolygon aPoly; | |||
3950 | if ( bContour ) | |||
3951 | { | |||
3952 | // add 2nd parameter with value <true> | |||
3953 | // to indicate that method is called for paint in order to avoid | |||
3954 | // load of the intrinsic graphic. | |||
3955 | bContour = GetContour( aPoly, true ); | |||
3956 | } | |||
3957 | ||||
3958 | // #i47804# - distinguish complete background paint | |||
3959 | // and margin paint. | |||
3960 | // paint complete background for Writer text fly frames | |||
3961 | bool bPaintCompleteBack( !pNoText ); | |||
3962 | // paint complete background for transparent graphic and contour, | |||
3963 | // if own background color exists. | |||
3964 | const bool bIsGraphicTransparent = pNoText && pNoText->IsTransparent(); | |||
3965 | if ( !bPaintCompleteBack && | |||
3966 | ( bIsGraphicTransparent|| bContour ) ) | |||
3967 | { | |||
3968 | const SwFrameFormat* pSwFrameFormat = dynamic_cast< const SwFrameFormat* >(GetFormat()); | |||
3969 | ||||
3970 | if (pSwFrameFormat && pSwFrameFormat->supportsFullDrawingLayerFillAttributeSet()) | |||
3971 | { | |||
3972 | // check for transparency | |||
3973 | const drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(pSwFrameFormat->getSdrAllFillAttributesHelper()); | |||
3974 | ||||
3975 | // check if the new fill attributes are used | |||
3976 | if(aFillAttributes && aFillAttributes->isUsed()) | |||
3977 | { | |||
3978 | bPaintCompleteBack = true; | |||
3979 | } | |||
3980 | } | |||
3981 | else | |||
3982 | { | |||
3983 | std::unique_ptr<SvxBrushItem> aBack = GetFormat()->makeBackgroundBrushItem(); | |||
3984 | // to determine, if background has to be painted, by checking, if | |||
3985 | // background color is not COL_TRANSPARENT ("no fill"/"auto fill") | |||
3986 | // or a background graphic exists. | |||
3987 | bPaintCompleteBack = aBack && | |||
3988 | ((aBack->GetColor() != COL_TRANSPARENT) || | |||
3989 | aBack->GetGraphicPos() != GPOS_NONE); | |||
3990 | } | |||
3991 | } | |||
3992 | // paint of margin needed. | |||
3993 | const bool bPaintMarginOnly( !bPaintCompleteBack && | |||
3994 | getFramePrintArea().SSize() != getFrameArea().SSize() ); | |||
3995 | ||||
3996 | // #i47804# - paint background of parent fly frame | |||
3997 | // for transparent graphics in layer Hell, if parent fly frame isn't | |||
3998 | // in layer Hell. It's only painted the intersection between the | |||
3999 | // parent fly frame area and the paint area <aRect> | |||
4000 | const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess(); | |||
4001 | ||||
4002 | if (bIsGraphicTransparent && | |||
4003 | GetFormat()->GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS) && | |||
4004 | GetVirtDrawObj()->GetLayer() == rIDDMA.GetHellId() && | |||
4005 | GetAnchorFrame()->FindFlyFrame() ) | |||
4006 | { | |||
4007 | const SwFlyFrame* pParentFlyFrame = GetAnchorFrame()->FindFlyFrame(); | |||
4008 | if ( pParentFlyFrame->GetDrawObj()->GetLayer() != | |||
4009 | rIDDMA.GetHellId() ) | |||
4010 | { | |||
4011 | SwFlyFrame* pOldRet = gProp.pSRetoucheFly2; | |||
4012 | gProp.pSRetoucheFly2 = const_cast<SwFlyFrame*>(this); | |||
4013 | ||||
4014 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), pParentFlyFrame ); | |||
4015 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
4016 | SwRect aPaintRect( aRect ); | |||
4017 | aPaintRect.Intersection_( pParentFlyFrame->getFrameArea() ); | |||
4018 | pParentFlyFrame->PaintSwFrameBackground( aPaintRect, pPage, rAttrs ); | |||
4019 | ||||
4020 | gProp.pSRetoucheFly2 = pOldRet; | |||
4021 | } | |||
4022 | } | |||
4023 | ||||
4024 | if ( bPaintCompleteBack || bPaintMarginOnly ) | |||
4025 | { | |||
4026 | //#24926# JP 01.02.96, PaintBaBo is here partially so PaintSwFrameShadowAndBorder | |||
4027 | //receives the original Rect but PaintSwFrameBackground only the limited | |||
4028 | //one. | |||
4029 | ||||
4030 | rRenderContext.Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR ); | |||
4031 | rRenderContext.SetLineColor(); | |||
4032 | ||||
4033 | pPage = FindPageFrame(); | |||
4034 | ||||
4035 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), static_cast<SwFrame const *>(this) ); | |||
4036 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
4037 | ||||
4038 | // paint background | |||
4039 | { | |||
4040 | SwRegionRects aRegion( aRect ); | |||
4041 | // #i80822# | |||
4042 | // suppress painting of background in printing area for | |||
4043 | // non-transparent graphics. | |||
4044 | if ( bPaintMarginOnly || | |||
4045 | ( pNoText && !bIsGraphicTransparent ) ) | |||
4046 | { | |||
4047 | //What we actually want to paint is the small stripe between | |||
4048 | //PrtArea and outer border. | |||
4049 | SwRect aTmp( getFramePrintArea() ); aTmp += getFrameArea().Pos(); | |||
4050 | aRegion -= aTmp; | |||
4051 | } | |||
4052 | if ( bContour ) | |||
4053 | { | |||
4054 | rRenderContext.Push(); | |||
4055 | // #i80822# | |||
4056 | // apply clip region under the same conditions, which are | |||
4057 | // used in <SwNoTextFrame::PaintSwFrame(..)> to set the clip region | |||
4058 | // for painting the graphic/OLE. Thus, the clip region is | |||
4059 | // also applied for the PDF export. | |||
4060 | SwViewShell *pSh = getRootFrame()->GetCurrShell(); | |||
4061 | ||||
4062 | if ( !rRenderContext.GetConnectMetaFile() || !pSh || !pSh->GetWin() ) | |||
4063 | { | |||
4064 | rRenderContext.SetClipRegion(vcl::Region(aPoly)); | |||
4065 | } | |||
4066 | ||||
4067 | for ( size_t i = 0; i < aRegion.size(); ++i ) | |||
4068 | { | |||
4069 | PaintSwFrameBackground( aRegion[i], pPage, rAttrs, false, true ); | |||
4070 | } | |||
4071 | ||||
4072 | rRenderContext.Pop(); | |||
4073 | } | |||
4074 | else | |||
4075 | { | |||
4076 | for ( size_t i = 0; i < aRegion.size(); ++i ) | |||
4077 | { | |||
4078 | PaintSwFrameBackground( aRegion[i], pPage, rAttrs, false, true ); | |||
4079 | } | |||
4080 | } | |||
4081 | } | |||
4082 | ||||
4083 | // paint border before painting background | |||
4084 | PaintSwFrameShadowAndBorder(rRect, pPage, rAttrs); | |||
4085 | ||||
4086 | rRenderContext.Pop(); | |||
4087 | } | |||
4088 | } | |||
4089 | ||||
4090 | // fly frame will paint it's subsidiary lines and | |||
4091 | // the subsidiary lines of its lowers on its own, due to overlapping with | |||
4092 | // other fly frames or other objects. | |||
4093 | if( gProp.pSGlobalShell->GetWin() | |||
4094 | && !bIsChart ) //#i102950# don't paint additional borders for charts | |||
4095 | { | |||
4096 | bool bSubsLineRectsCreated; | |||
4097 | if ( gProp.pSSubsLines ) | |||
4098 | { | |||
4099 | // Lock already existing subsidiary lines | |||
4100 | gProp.pSSubsLines->LockLines( true ); | |||
4101 | bSubsLineRectsCreated = false; | |||
4102 | } | |||
4103 | else | |||
4104 | { | |||
4105 | // create new subsidiary lines | |||
4106 | gProp.pSSubsLines.reset(new SwSubsRects); | |||
4107 | bSubsLineRectsCreated = true; | |||
4108 | } | |||
4109 | ||||
4110 | bool bSpecSubsLineRectsCreated; | |||
4111 | if ( gProp.pSSpecSubsLines ) | |||
4112 | { | |||
4113 | // Lock already existing special subsidiary lines | |||
4114 | gProp.pSSpecSubsLines->LockLines( true ); | |||
4115 | bSpecSubsLineRectsCreated = false; | |||
4116 | } | |||
4117 | else | |||
4118 | { | |||
4119 | // create new special subsidiary lines | |||
4120 | gProp.pSSpecSubsLines.reset(new SwSubsRects); | |||
4121 | bSpecSubsLineRectsCreated = true; | |||
4122 | } | |||
4123 | // Add subsidiary lines of fly frame and its lowers | |||
4124 | RefreshLaySubsidiary( pPage, aRect ); | |||
4125 | // paint subsidiary lines of fly frame and its lowers | |||
4126 | gProp.pSSpecSubsLines->PaintSubsidiary( &rRenderContext, nullptr, gProp ); | |||
4127 | gProp.pSSubsLines->PaintSubsidiary(&rRenderContext, gProp.pSLines.get(), gProp); | |||
4128 | if ( !bSubsLineRectsCreated ) | |||
4129 | // unlock subsidiary lines | |||
4130 | gProp.pSSubsLines->LockLines( false ); | |||
4131 | else | |||
4132 | { | |||
4133 | // delete created subsidiary lines container | |||
4134 | gProp.pSSubsLines.reset(); | |||
4135 | } | |||
4136 | ||||
4137 | if ( !bSpecSubsLineRectsCreated ) | |||
4138 | // unlock special subsidiary lines | |||
4139 | gProp.pSSpecSubsLines->LockLines( false ); | |||
4140 | else | |||
4141 | { | |||
4142 | // delete created special subsidiary lines container | |||
4143 | gProp.pSSpecSubsLines.reset(); | |||
4144 | } | |||
4145 | } | |||
4146 | ||||
4147 | SwLayoutFrame::PaintSwFrame( rRenderContext, aRect ); | |||
4148 | ||||
4149 | Validate(); | |||
4150 | ||||
4151 | // first paint lines added by fly frame paint | |||
4152 | // and then unlock other lines. | |||
4153 | gProp.pSLines->PaintLines( &rRenderContext, gProp ); | |||
4154 | gProp.pSLines->LockLines( false ); | |||
4155 | // have to paint frame borders added in heaven layer here... | |||
4156 | ProcessPrimitives(gProp.pBLines->GetBorderLines_Clear()); | |||
4157 | ||||
4158 | PaintDecorators(); | |||
4159 | ||||
4160 | rRenderContext.Pop(); | |||
4161 | ||||
4162 | if ( gProp.pSProgress && pNoText ) | |||
4163 | SfxProgress::Reschedule(); | |||
4164 | } | |||
4165 | ||||
4166 | void SwFlyFrame::PaintDecorators() const | |||
4167 | { | |||
4168 | // Show the un-float button | |||
4169 | SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( gProp.pSGlobalShell ); | |||
4170 | if ( pWrtSh ) | |||
4171 | { | |||
4172 | UpdateUnfloatButton(pWrtSh, IsShowUnfloatButton(pWrtSh)); | |||
4173 | } | |||
4174 | } | |||
4175 | ||||
4176 | void SwTabFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const& rRect, SwPrintData const*const) const | |||
4177 | { | |||
4178 | const SwViewOption* pViewOption = gProp.pSGlobalShell->GetViewOptions(); | |||
4179 | if (pViewOption->IsTable()) | |||
4180 | { | |||
4181 | // #i29550# | |||
4182 | if ( IsCollapsingBorders() ) | |||
4183 | { | |||
4184 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), static_cast<SwFrame const *>(this) ); | |||
4185 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
4186 | ||||
4187 | // paint shadow | |||
4188 | if ( rAttrs.GetShadow().GetLocation() != SvxShadowLocation::NONE ) | |||
4189 | { | |||
4190 | SwRect aRect; | |||
4191 | ::lcl_CalcBorderRect( aRect, this, rAttrs, true, gProp ); | |||
4192 | PaintShadow( rRect, aRect, rAttrs ); | |||
4193 | } | |||
4194 | ||||
4195 | SwTabFramePainter aHelper(*this); | |||
4196 | aHelper.PaintLines(rRenderContext, rRect); | |||
4197 | } | |||
4198 | ||||
4199 | SwLayoutFrame::PaintSwFrame( rRenderContext, rRect ); | |||
4200 | } | |||
4201 | // #i6467# - no light grey rectangle for page preview | |||
4202 | else if ( gProp.pSGlobalShell->GetWin() && !gProp.pSGlobalShell->IsPreview() ) | |||
4203 | { | |||
4204 | // #i6467# - intersect output rectangle with table frame | |||
4205 | SwRect aTabRect( getFramePrintArea() ); | |||
4206 | aTabRect.Pos() += getFrameArea().Pos(); | |||
4207 | SwRect aTabOutRect( rRect ); | |||
4208 | aTabOutRect.Intersection( aTabRect ); | |||
4209 | SwViewOption::DrawRect( &rRenderContext, aTabOutRect, COL_LIGHTGRAY ); | |||
4210 | } | |||
4211 | const_cast<SwTabFrame*>(this)->ResetComplete(); | |||
4212 | } | |||
4213 | ||||
4214 | /** | |||
4215 | * Paint border shadow | |||
4216 | * | |||
4217 | * @param[in] rRect aligned rect to clip the result | |||
4218 | * @param[in,out] rOutRect full painting area as input | |||
4219 | * painting area reduced by shadow space for border and background as output | |||
4220 | * @param[in] rShadow includes shadow attributes | |||
4221 | * @param[in] bDrawFullShadowRectangle paint full rect of shadow | |||
4222 | * @param[in] bTop paint top part of the shadow | |||
4223 | * @param[in] bBottom paint bottom part of the shadow | |||
4224 | * @param[in] bLeft paint left part of the shadow | |||
4225 | * @param[in] bRight paint right part of the shadow | |||
4226 | **/ | |||
4227 | static void lcl_PaintShadow( const SwRect& rRect, SwRect& rOutRect, | |||
4228 | const SvxShadowItem& rShadow, const bool bDrawFullShadowRectangle, | |||
4229 | const bool bTop, const bool bBottom, | |||
4230 | const bool bLeft, const bool bRight, | |||
4231 | SwPaintProperties const & properties) | |||
4232 | { | |||
4233 | const long nWidth = ::lcl_AlignWidth ( rShadow.GetWidth(), properties ); | |||
4234 | const long nHeight = ::lcl_AlignHeight( rShadow.GetWidth(), properties ); | |||
4235 | ||||
4236 | SwRects aRegion; | |||
4237 | SwRect aOut( rOutRect ); | |||
4238 | ||||
4239 | switch ( rShadow.GetLocation() ) | |||
4240 | { | |||
4241 | case SvxShadowLocation::BottomRight: | |||
4242 | { | |||
4243 | if ( bDrawFullShadowRectangle ) | |||
4244 | { | |||
4245 | // draw full shadow rectangle | |||
4246 | aOut.Top( rOutRect.Top() + nHeight ); | |||
4247 | aOut.Left( rOutRect.Left() + nWidth ); | |||
4248 | aRegion.push_back( aOut ); | |||
4249 | } | |||
4250 | else | |||
4251 | { | |||
4252 | if( bBottom ) | |||
4253 | { | |||
4254 | aOut.Top( rOutRect.Bottom() - nHeight ); | |||
4255 | if( bLeft ) | |||
4256 | aOut.Left( rOutRect.Left() + nWidth ); | |||
4257 | aRegion.push_back( aOut ); | |||
4258 | } | |||
4259 | if( bRight ) | |||
4260 | { | |||
4261 | aOut.Left( rOutRect.Right() - nWidth ); | |||
4262 | if( bTop ) | |||
4263 | aOut.Top( rOutRect.Top() + nHeight ); | |||
4264 | else | |||
4265 | aOut.Top( rOutRect.Top() ); | |||
4266 | if( bBottom ) | |||
4267 | aOut.Bottom( rOutRect.Bottom() - nHeight ); | |||
4268 | aRegion.push_back( aOut ); | |||
4269 | } | |||
4270 | } | |||
4271 | ||||
4272 | if( bRight ) | |||
4273 | rOutRect.AddRight(- nWidth ); | |||
4274 | if( bBottom ) | |||
4275 | rOutRect.AddBottom(- nHeight ); | |||
4276 | } | |||
4277 | break; | |||
4278 | case SvxShadowLocation::TopLeft: | |||
4279 | { | |||
4280 | if ( bDrawFullShadowRectangle ) | |||
4281 | { | |||
4282 | // draw full shadow rectangle | |||
4283 | aOut.Bottom( rOutRect.Bottom() - nHeight ); | |||
4284 | aOut.Right( rOutRect.Right() - nWidth ); | |||
4285 | aRegion.push_back( aOut ); | |||
4286 | } | |||
4287 | else | |||
4288 | { | |||
4289 | if( bTop ) | |||
4290 | { | |||
4291 | aOut.Bottom( rOutRect.Top() + nHeight ); | |||
4292 | if( bRight ) | |||
4293 | aOut.Right( rOutRect.Right() - nWidth ); | |||
4294 | aRegion.push_back( aOut ); | |||
4295 | } | |||
4296 | if( bLeft ) | |||
4297 | { | |||
4298 | aOut.Right( rOutRect.Left() + nWidth ); | |||
4299 | if( bBottom ) | |||
4300 | aOut.Bottom( rOutRect.Bottom() - nHeight ); | |||
4301 | else | |||
4302 | aOut.Bottom( rOutRect.Bottom() ); | |||
4303 | if( bTop ) | |||
4304 | aOut.Top( rOutRect.Top() + nHeight ); | |||
4305 | aRegion.push_back( aOut ); | |||
4306 | } | |||
4307 | } | |||
4308 | ||||
4309 | if( bLeft ) | |||
4310 | rOutRect.AddLeft( nWidth ); | |||
4311 | if( bTop ) | |||
4312 | rOutRect.AddTop( nHeight ); | |||
4313 | } | |||
4314 | break; | |||
4315 | case SvxShadowLocation::TopRight: | |||
4316 | { | |||
4317 | if ( bDrawFullShadowRectangle ) | |||
4318 | { | |||
4319 | // draw full shadow rectangle | |||
4320 | aOut.Bottom( rOutRect.Bottom() - nHeight); | |||
4321 | aOut.Left( rOutRect.Left() + nWidth ); | |||
4322 | aRegion.push_back( aOut ); | |||
4323 | } | |||
4324 | else | |||
4325 | { | |||
4326 | if( bTop ) | |||
4327 | { | |||
4328 | aOut.Bottom( rOutRect.Top() + nHeight ); | |||
4329 | if( bLeft ) | |||
4330 | aOut.Left( rOutRect.Left() + nWidth ); | |||
4331 | aRegion.push_back( aOut ); | |||
4332 | } | |||
4333 | if( bRight ) | |||
4334 | { | |||
4335 | aOut.Left( rOutRect.Right() - nWidth ); | |||
4336 | if( bBottom ) | |||
4337 | aOut.Bottom( rOutRect.Bottom() - nHeight ); | |||
4338 | else | |||
4339 | aOut.Bottom( rOutRect.Bottom() ); | |||
4340 | if( bTop ) | |||
4341 | aOut.Top( rOutRect.Top() + nHeight ); | |||
4342 | aRegion.push_back( aOut ); | |||
4343 | } | |||
4344 | } | |||
4345 | ||||
4346 | if( bRight ) | |||
4347 | rOutRect.AddRight( - nWidth ); | |||
4348 | if( bTop ) | |||
4349 | rOutRect.AddTop( nHeight ); | |||
4350 | } | |||
4351 | break; | |||
4352 | case SvxShadowLocation::BottomLeft: | |||
4353 | { | |||
4354 | if ( bDrawFullShadowRectangle ) | |||
4355 | { | |||
4356 | // draw full shadow rectangle | |||
4357 | aOut.Top( rOutRect.Top() + nHeight ); | |||
4358 | aOut.Right( rOutRect.Right() - nWidth ); | |||
4359 | aRegion.push_back( aOut ); | |||
4360 | } | |||
4361 | else | |||
4362 | { | |||
4363 | if( bBottom ) | |||
4364 | { | |||
4365 | aOut.Top( rOutRect.Bottom()- nHeight ); | |||
4366 | if( bRight ) | |||
4367 | aOut.Right( rOutRect.Right() - nWidth ); | |||
4368 | aRegion.push_back( aOut ); | |||
4369 | } | |||
4370 | if( bLeft ) | |||
4371 | { | |||
4372 | aOut.Right( rOutRect.Left() + nWidth ); | |||
4373 | if( bTop ) | |||
4374 | aOut.Top( rOutRect.Top() + nHeight ); | |||
4375 | else | |||
4376 | aOut.Top( rOutRect.Top() ); | |||
4377 | if( bBottom ) | |||
4378 | aOut.Bottom( rOutRect.Bottom() - nHeight ); | |||
4379 | aRegion.push_back( aOut ); | |||
4380 | } | |||
4381 | } | |||
4382 | ||||
4383 | if( bLeft ) | |||
4384 | rOutRect.AddLeft( nWidth ); | |||
4385 | if( bBottom ) | |||
4386 | rOutRect.AddBottom( - nHeight ); | |||
4387 | } | |||
4388 | break; | |||
4389 | default: | |||
4390 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" , 4390, __extension__ __PRETTY_FUNCTION__)); | |||
4391 | break; | |||
4392 | } | |||
4393 | ||||
4394 | vcl::RenderContext *pOut = properties.pSGlobalShell->GetOut(); | |||
4395 | ||||
4396 | DrawModeFlags nOldDrawMode = pOut->GetDrawMode(); | |||
4397 | Color aShadowColor( rShadow.GetColor().GetRGBColor() ); | |||
4398 | if( !aRegion.empty() && properties.pSGlobalShell->GetWin() && | |||
4399 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
4400 | { | |||
4401 | // In high contrast mode, the output device has already set the | |||
4402 | // DrawModeFlags::SettingsFill flag. This causes the SetFillColor function | |||
4403 | // to ignore the setting of a new color. Therefore we have to reset | |||
4404 | // the drawing mode | |||
4405 | pOut->SetDrawMode( DrawModeFlags::Default ); | |||
4406 | aShadowColor = SwViewOption::GetFontColor(); | |||
4407 | } | |||
4408 | ||||
4409 | if ( pOut->GetFillColor() != aShadowColor ) | |||
4410 | pOut->SetFillColor( aShadowColor ); | |||
4411 | ||||
4412 | pOut->SetLineColor(); | |||
4413 | ||||
4414 | pOut->SetDrawMode( nOldDrawMode ); | |||
4415 | ||||
4416 | for (const SwRect & rOut : aRegion) | |||
4417 | { | |||
4418 | aOut = rOut; | |||
4419 | if ( rRect.IsOver( aOut ) && aOut.Height() > 0 && aOut.Width() > 0 ) | |||
4420 | { | |||
4421 | aOut.Intersection_( rRect ); | |||
4422 | pOut->DrawRect( aOut.SVRect() ); | |||
4423 | } | |||
4424 | } | |||
4425 | } | |||
4426 | ||||
4427 | /** | |||
4428 | * Paints a shadow if the format requests so. | |||
4429 | * | |||
4430 | * The shadow is always painted on the outer edge of the OutRect. | |||
4431 | * If needed, the OutRect is shrunk so the painting of the border can be | |||
4432 | * done on it. | |||
4433 | * | |||
4434 | * @note: draw full shadow rectangle for frames with transparent drawn backgrounds (OD 23.08.2002 #99657#) | |||
4435 | */ | |||
4436 | void SwFrame::PaintShadow( const SwRect& rRect, SwRect& rOutRect, | |||
4437 | const SwBorderAttrs &rAttrs ) const | |||
4438 | { | |||
4439 | SvxShadowItem rShadow = rAttrs.GetShadow(); | |||
4440 | ||||
4441 | const bool bCnt = IsContentFrame(); | |||
4442 | const bool bTop = !bCnt || rAttrs.GetTopLine ( *(this) ); | |||
4443 | const bool bBottom = !bCnt || rAttrs.GetBottomLine( *(this) ); | |||
4444 | ||||
4445 | if( IsVertical() ) | |||
4446 | { | |||
4447 | switch( rShadow.GetLocation() ) | |||
4448 | { | |||
4449 | case SvxShadowLocation::BottomRight: rShadow.SetLocation(SvxShadowLocation::BottomLeft); break; | |||
4450 | case SvxShadowLocation::TopLeft: rShadow.SetLocation(SvxShadowLocation::TopRight); break; | |||
4451 | case SvxShadowLocation::TopRight: rShadow.SetLocation(SvxShadowLocation::BottomRight); break; | |||
4452 | case SvxShadowLocation::BottomLeft: rShadow.SetLocation(SvxShadowLocation::TopLeft); break; | |||
4453 | default: break; | |||
4454 | } | |||
4455 | } | |||
4456 | ||||
4457 | // determine, if full shadow rectangle have to be drawn or only two shadow rectangles beside the frame. | |||
4458 | // draw full shadow rectangle, if frame background is drawn transparent. | |||
4459 | // Status Quo: | |||
4460 | // SwLayoutFrame can have transparent drawn backgrounds. Thus, | |||
4461 | // "asked" their frame format. | |||
4462 | const bool bDrawFullShadowRectangle = | |||
4463 | ( IsLayoutFrame() && | |||
4464 | static_cast<const SwLayoutFrame*>(this)->GetFormat()->IsBackgroundTransparent() | |||
4465 | ); | |||
4466 | ||||
4467 | SwRectFnSet aRectFnSet(this); | |||
4468 | ::lcl_ExtendLeftAndRight( rOutRect, *(this), rAttrs, aRectFnSet.FnRect() ); | |||
4469 | ||||
4470 | lcl_PaintShadow(rRect, rOutRect, rShadow, bDrawFullShadowRectangle, bTop, bBottom, true, true, gProp); | |||
4471 | } | |||
4472 | ||||
4473 | void SwFrame::PaintBorderLine( const SwRect& rRect, | |||
4474 | const SwRect& rOutRect, | |||
4475 | const SwPageFrame * pPage, | |||
4476 | const Color *pColor, | |||
4477 | const SvxBorderLineStyle nStyle ) const | |||
4478 | { | |||
4479 | if ( !rOutRect.IsOver( rRect ) ) | |||
4480 | return; | |||
4481 | ||||
4482 | SwRect aOut( rOutRect ); | |||
4483 | aOut.Intersection_( rRect ); | |||
4484 | ||||
4485 | const SwTabFrame *pTab = IsCellFrame() ? FindTabFrame() : nullptr; | |||
4486 | SubColFlags nSubCol = ( IsCellFrame() || IsRowFrame() ) | |||
4487 | ? SubColFlags::Tab | |||
4488 | : ( IsInSct() | |||
4489 | ? SubColFlags::Sect | |||
4490 | : ( IsInFly() ? SubColFlags::Fly : SubColFlags::Page ) ); | |||
4491 | if( pColor && gProp.pSGlobalShell->GetWin() && | |||
4492 | Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
4493 | { | |||
4494 | pColor = &SwViewOption::GetFontColor(); | |||
4495 | } | |||
4496 | ||||
4497 | if (pPage->GetSortedObjs() && | |||
4498 | pPage->GetFormat()->GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS)) | |||
4499 | { | |||
4500 | SwRegionRects aRegion( aOut, 4 ); | |||
4501 | basegfx::utils::B2DClipState aClipState; | |||
4502 | ::lcl_SubtractFlys( this, pPage, aOut, aRegion, aClipState, gProp ); | |||
4503 | for ( size_t i = 0; i < aRegion.size(); ++i ) | |||
4504 | gProp.pSLines->AddLineRect( aRegion[i], pColor, nStyle, pTab, nSubCol, gProp ); | |||
4505 | } | |||
4506 | else | |||
4507 | gProp.pSLines->AddLineRect( aOut, pColor, nStyle, pTab, nSubCol, gProp ); | |||
4508 | } | |||
4509 | ||||
4510 | namespace drawinglayer::primitive2d | |||
4511 | { | |||
4512 | namespace { | |||
4513 | ||||
4514 | class SwBorderRectanglePrimitive2D : public BufferedDecompositionPrimitive2D | |||
4515 | { | |||
4516 | private: | |||
4517 | /// the transformation defining the geometry of this BorderRectangle | |||
4518 | basegfx::B2DHomMatrix maB2DHomMatrix; | |||
4519 | ||||
4520 | /// the four styles to be used | |||
4521 | svx::frame::Style maStyleTop; | |||
4522 | svx::frame::Style maStyleRight; | |||
4523 | svx::frame::Style maStyleBottom; | |||
4524 | svx::frame::Style maStyleLeft; | |||
4525 | ||||
4526 | protected: | |||
4527 | /// local decomposition. | |||
4528 | virtual void create2DDecomposition( | |||
4529 | Primitive2DContainer& rContainer, | |||
4530 | const geometry::ViewInformation2D& rViewInformation) const override; | |||
4531 | ||||
4532 | public: | |||
4533 | /// constructor | |||
4534 | SwBorderRectanglePrimitive2D( | |||
4535 | const basegfx::B2DHomMatrix& rB2DHomMatrix, | |||
4536 | const svx::frame::Style& rStyleTop, | |||
4537 | const svx::frame::Style& rStyleRight, | |||
4538 | const svx::frame::Style& rStyleBottom, | |||
4539 | const svx::frame::Style& rStyleLeft); | |||
4540 | ||||
4541 | /// data read access | |||
4542 | const basegfx::B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; } | |||
4543 | const svx::frame::Style& getStyleTop() const { return maStyleTop; } | |||
4544 | const svx::frame::Style& getStyleRight() const { return maStyleRight; } | |||
4545 | const svx::frame::Style& getStyleBottom() const { return maStyleBottom; } | |||
4546 | const svx::frame::Style& getStyleLeft() const { return maStyleLeft; } | |||
4547 | ||||
4548 | /// compare operator | |||
4549 | virtual bool operator==(const BasePrimitive2D& rPrimitive) const override; | |||
4550 | ||||
4551 | /// get range | |||
4552 | virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override; | |||
4553 | ||||
4554 | /// provide unique ID | |||
4555 | virtual sal_uInt32 getPrimitive2DID() const override; | |||
4556 | }; | |||
4557 | ||||
4558 | } | |||
4559 | ||||
4560 | void SwBorderRectanglePrimitive2D::create2DDecomposition( | |||
4561 | Primitive2DContainer& rContainer, | |||
4562 | const geometry::ViewInformation2D& /*rViewInformation*/) const | |||
4563 | { | |||
4564 | basegfx::B2DPoint aTopLeft(getB2DHomMatrix() * basegfx::B2DPoint(0.0, 0.0)); | |||
4565 | basegfx::B2DPoint aTopRight(getB2DHomMatrix() * basegfx::B2DPoint(1.0, 0.0)); | |||
4566 | basegfx::B2DPoint aBottomLeft(getB2DHomMatrix() * basegfx::B2DPoint(0.0, 1.0)); | |||
4567 | basegfx::B2DPoint aBottomRight(getB2DHomMatrix() * basegfx::B2DPoint(1.0, 1.0)); | |||
4568 | ||||
4569 | // prepare SdrFrameBorderDataVector | |||
4570 | std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData( | |||
4571 | std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>()); | |||
4572 | ||||
4573 | if(getStyleTop().IsUsed()) | |||
4574 | { | |||
4575 | // move top left/right inwards half border width | |||
4576 | basegfx::B2DVector aDown(getB2DHomMatrix() * basegfx::B2DVector(0.0, 1.0)); | |||
4577 | aDown.setLength(getStyleTop().GetWidth() * 0.5); | |||
4578 | aTopLeft += aDown; | |||
4579 | aTopRight += aDown; | |||
4580 | } | |||
4581 | ||||
4582 | if(getStyleBottom().IsUsed()) | |||
4583 | { | |||
4584 | // move bottom left/right inwards half border width | |||
4585 | basegfx::B2DVector aUp(getB2DHomMatrix() * basegfx::B2DVector(0.0, -1.0)); | |||
4586 | aUp.setLength(getStyleBottom().GetWidth() * 0.5); | |||
4587 | aBottomLeft += aUp; | |||
4588 | aBottomRight += aUp; | |||
4589 | } | |||
4590 | ||||
4591 | if(getStyleLeft().IsUsed()) | |||
4592 | { | |||
4593 | // move left top/bottom inwards half border width | |||
4594 | basegfx::B2DVector aRight(getB2DHomMatrix() * basegfx::B2DVector(1.0, 0.0)); | |||
4595 | aRight.setLength(getStyleLeft().GetWidth() * 0.5); | |||
4596 | aTopLeft += aRight; | |||
4597 | aBottomLeft += aRight; | |||
4598 | } | |||
4599 | ||||
4600 | if(getStyleRight().IsUsed()) | |||
4601 | { | |||
4602 | // move right top/bottom inwards half border width | |||
4603 | basegfx::B2DVector aLeft(getB2DHomMatrix() * basegfx::B2DVector(-1.0, 0.0)); | |||
4604 | aLeft.setLength(getStyleRight().GetWidth() * 0.5); | |||
4605 | aTopRight += aLeft; | |||
4606 | aBottomRight += aLeft; | |||
4607 | } | |||
4608 | ||||
4609 | // go round-robin, from TopLeft to TopRight, down, left and back up. That | |||
4610 | // way, the borders will not need to be mirrored in any way | |||
4611 | if(getStyleTop().IsUsed()) | |||
4612 | { | |||
4613 | // create BorderPrimitive(s) for top border | |||
4614 | const basegfx::B2DVector aVector(aTopRight - aTopLeft); | |||
4615 | aData->emplace_back( | |||
4616 | aTopLeft, | |||
4617 | aVector, | |||
4618 | getStyleTop(), | |||
4619 | nullptr); | |||
4620 | drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back()); | |||
4621 | ||||
4622 | if(getStyleLeft().IsUsed()) | |||
4623 | { | |||
4624 | rInstance.addSdrConnectStyleData(true, getStyleLeft(), basegfx::B2DVector(aBottomLeft - aTopLeft), false); | |||
4625 | } | |||
4626 | ||||
4627 | if(getStyleRight().IsUsed()) | |||
4628 | { | |||
4629 | rInstance.addSdrConnectStyleData(false, getStyleRight(), basegfx::B2DVector(aBottomRight - aTopRight), false); | |||
4630 | } | |||
4631 | } | |||
4632 | ||||
4633 | if(getStyleRight().IsUsed()) | |||
4634 | { | |||
4635 | // create BorderPrimitive(s) for right border | |||
4636 | const basegfx::B2DVector aVector(aBottomRight - aTopRight); | |||
4637 | aData->emplace_back( | |||
4638 | aTopRight, | |||
4639 | aVector, | |||
4640 | getStyleRight(), | |||
4641 | nullptr); | |||
4642 | drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back()); | |||
4643 | ||||
4644 | if(getStyleTop().IsUsed()) | |||
4645 | { | |||
4646 | rInstance.addSdrConnectStyleData(true, getStyleTop(), basegfx::B2DVector(aTopLeft - aTopRight), false); | |||
4647 | } | |||
4648 | ||||
4649 | if(getStyleBottom().IsUsed()) | |||
4650 | { | |||
4651 | rInstance.addSdrConnectStyleData(false, getStyleBottom(), basegfx::B2DVector(aBottomLeft - aBottomRight), false); | |||
4652 | } | |||
4653 | } | |||
4654 | ||||
4655 | if(getStyleBottom().IsUsed()) | |||
4656 | { | |||
4657 | // create BorderPrimitive(s) for bottom border | |||
4658 | const basegfx::B2DVector aVector(aBottomLeft - aBottomRight); | |||
4659 | aData->emplace_back( | |||
4660 | aBottomRight, | |||
4661 | aVector, | |||
4662 | getStyleBottom(), | |||
4663 | nullptr); | |||
4664 | drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back()); | |||
4665 | ||||
4666 | if(getStyleRight().IsUsed()) | |||
4667 | { | |||
4668 | rInstance.addSdrConnectStyleData(true, getStyleRight(), basegfx::B2DVector(aTopRight - aBottomRight), false); | |||
4669 | } | |||
4670 | ||||
4671 | if(getStyleLeft().IsUsed()) | |||
4672 | { | |||
4673 | rInstance.addSdrConnectStyleData(false, getStyleLeft(), basegfx::B2DVector(aTopLeft - aBottomLeft), false); | |||
4674 | } | |||
4675 | } | |||
4676 | ||||
4677 | if(getStyleLeft().IsUsed()) | |||
4678 | { | |||
4679 | // create BorderPrimitive(s) for left border | |||
4680 | const basegfx::B2DVector aVector(aTopLeft - aBottomLeft); | |||
4681 | aData->emplace_back( | |||
4682 | aBottomLeft, | |||
4683 | aVector, | |||
4684 | getStyleLeft(), | |||
4685 | nullptr); | |||
4686 | drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back()); | |||
4687 | ||||
4688 | if(getStyleBottom().IsUsed()) | |||
4689 | { | |||
4690 | rInstance.addSdrConnectStyleData(true, getStyleBottom(), basegfx::B2DVector(aBottomRight - aBottomLeft), false); | |||
4691 | } | |||
4692 | ||||
4693 | if(getStyleTop().IsUsed()) | |||
4694 | { | |||
4695 | rInstance.addSdrConnectStyleData(false, getStyleTop(), basegfx::B2DVector(aTopRight - aTopLeft), false); | |||
4696 | } | |||
4697 | } | |||
4698 | ||||
4699 | // create instance of SdrFrameBorderPrimitive2D if | |||
4700 | // SdrFrameBorderDataVector is used | |||
4701 | if(!aData->empty()) | |||
4702 | { | |||
4703 | rContainer.append( | |||
4704 | drawinglayer::primitive2d::Primitive2DReference( | |||
4705 | new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D( | |||
4706 | aData, | |||
4707 | true))); // force visualization to minimal one discrete unit (pixel) | |||
4708 | } | |||
4709 | } | |||
4710 | ||||
4711 | SwBorderRectanglePrimitive2D::SwBorderRectanglePrimitive2D( | |||
4712 | const basegfx::B2DHomMatrix& rB2DHomMatrix, | |||
4713 | const svx::frame::Style& rStyleTop, | |||
4714 | const svx::frame::Style& rStyleRight, | |||
4715 | const svx::frame::Style& rStyleBottom, | |||
4716 | const svx::frame::Style& rStyleLeft) | |||
4717 | : BufferedDecompositionPrimitive2D(), | |||
4718 | maB2DHomMatrix(rB2DHomMatrix), | |||
4719 | maStyleTop(rStyleTop), | |||
4720 | maStyleRight(rStyleRight), | |||
4721 | maStyleBottom(rStyleBottom), | |||
4722 | maStyleLeft(rStyleLeft) | |||
4723 | { | |||
4724 | } | |||
4725 | ||||
4726 | bool SwBorderRectanglePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const | |||
4727 | { | |||
4728 | if(BasePrimitive2D::operator==(rPrimitive)) | |||
4729 | { | |||
4730 | const SwBorderRectanglePrimitive2D& rCompare = static_cast<const SwBorderRectanglePrimitive2D&>(rPrimitive); | |||
4731 | ||||
4732 | return (getB2DHomMatrix() == rCompare.getB2DHomMatrix() && | |||
4733 | getStyleTop() == rCompare.getStyleTop() && | |||
4734 | getStyleRight() == rCompare.getStyleRight() && | |||
4735 | getStyleBottom() == rCompare.getStyleBottom() && | |||
4736 | getStyleLeft() == rCompare.getStyleLeft()); | |||
4737 | } | |||
4738 | ||||
4739 | return false; | |||
4740 | } | |||
4741 | ||||
4742 | basegfx::B2DRange SwBorderRectanglePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const | |||
4743 | { | |||
4744 | basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); | |||
4745 | ||||
4746 | aRetval.transform(getB2DHomMatrix()); | |||
4747 | return aRetval; | |||
4748 | } | |||
4749 | ||||
4750 | // provide unique ID | |||
4751 | ImplPrimitive2DIDBlock(SwBorderRectanglePrimitive2D, PRIMITIVE2D_ID_SWBORDERRECTANGLERIMITIVE)sal_uInt32 SwBorderRectanglePrimitive2D::getPrimitive2DID() const { return ((3 << 16)| 3); } | |||
4752 | ||||
4753 | } // end of namespace drawinglayer::primitive2d | |||
4754 | ||||
4755 | namespace { | |||
4756 | ||||
4757 | editeng::SvxBorderLine const * get_ptr(std::optional<editeng::SvxBorderLine> const & opt) { | |||
4758 | return opt ? &*opt : nullptr; | |||
4759 | } | |||
4760 | ||||
4761 | } | |||
4762 | ||||
4763 | void PaintCharacterBorder( | |||
4764 | const SwFont& rFont, | |||
4765 | const SwRect& rPaintArea, | |||
4766 | const bool bVerticalLayout, | |||
4767 | const bool bVerticalLayoutLRBT, | |||
4768 | const bool bJoinWithPrev, | |||
4769 | const bool bJoinWithNext ) | |||
4770 | { | |||
4771 | SwRect aAlignedRect(rPaintArea); | |||
4772 | SwAlignRect(aAlignedRect, gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut()); | |||
4773 | ||||
4774 | bool bTop = true; | |||
4775 | bool bBottom = true; | |||
4776 | bool bLeft = true; | |||
4777 | bool bRight = true; | |||
4778 | ||||
4779 | switch (rFont.GetOrientation(bVerticalLayout, bVerticalLayoutLRBT)) | |||
4780 | { | |||
4781 | case 0 : | |||
4782 | bLeft = !bJoinWithPrev; | |||
4783 | bRight = !bJoinWithNext; | |||
4784 | break; | |||
4785 | case 900 : | |||
4786 | bBottom = !bJoinWithPrev; | |||
4787 | bTop = !bJoinWithNext; | |||
4788 | break; | |||
4789 | case 1800 : | |||
4790 | bRight = !bJoinWithPrev; | |||
4791 | bLeft = !bJoinWithNext; | |||
4792 | break; | |||
4793 | case 2700 : | |||
4794 | bTop = !bJoinWithPrev; | |||
4795 | bBottom = !bJoinWithNext; | |||
4796 | break; | |||
4797 | } | |||
4798 | ||||
4799 | // Paint shadow (reduce painting rect) | |||
4800 | { | |||
4801 | const SvxShadowItem aShadow( | |||
4802 | 0, &rFont.GetShadowColor(), rFont.GetShadowWidth(), | |||
4803 | rFont.GetAbsShadowLocation(bVerticalLayout, bVerticalLayoutLRBT)); | |||
4804 | ||||
4805 | if( aShadow.GetLocation() != SvxShadowLocation::NONE ) | |||
4806 | { | |||
4807 | lcl_PaintShadow( rPaintArea, aAlignedRect, aShadow, | |||
4808 | false, bTop, bBottom, bLeft, bRight, gProp); | |||
4809 | } | |||
4810 | } | |||
4811 | ||||
4812 | const basegfx::B2DHomMatrix aBorderTransform( | |||
4813 | basegfx::utils::createScaleTranslateB2DHomMatrix( | |||
4814 | aAlignedRect.Width(), aAlignedRect.Height(), | |||
4815 | aAlignedRect.Left(), aAlignedRect.Top())); | |||
4816 | const svx::frame::Style aStyleTop( | |||
4817 | bTop ? get_ptr(rFont.GetAbsTopBorder(bVerticalLayout, bVerticalLayoutLRBT)) : nullptr, | |||
4818 | 1.0); | |||
4819 | const svx::frame::Style aStyleRight( | |||
4820 | bRight ? get_ptr(rFont.GetAbsRightBorder(bVerticalLayout, bVerticalLayoutLRBT)) : nullptr, | |||
4821 | 1.0); | |||
4822 | const svx::frame::Style aStyleBottom( | |||
4823 | bBottom ? get_ptr(rFont.GetAbsBottomBorder(bVerticalLayout, bVerticalLayoutLRBT)) | |||
4824 | : nullptr, | |||
4825 | 1.0); | |||
4826 | const svx::frame::Style aStyleLeft( | |||
4827 | bLeft ? get_ptr(rFont.GetAbsLeftBorder(bVerticalLayout, bVerticalLayoutLRBT)) : nullptr, | |||
4828 | 1.0); | |||
4829 | drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget; | |||
4830 | ||||
4831 | aBorderLineTarget.append( | |||
4832 | drawinglayer::primitive2d::Primitive2DReference( | |||
4833 | new drawinglayer::primitive2d::SwBorderRectanglePrimitive2D( | |||
4834 | aBorderTransform, | |||
4835 | aStyleTop, | |||
4836 | aStyleRight, | |||
4837 | aStyleBottom, | |||
4838 | aStyleLeft))); | |||
4839 | gProp.pBLines->AddBorderLines(aBorderLineTarget); | |||
4840 | } | |||
4841 | ||||
4842 | /// #i15844# | |||
4843 | static const SwFrame* lcl_HasNextCell( const SwFrame& rFrame ) | |||
4844 | { | |||
4845 | OSL_ENSURE( rFrame.IsCellFrame(),do { if (true && (!(rFrame.IsCellFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "4846" ": "), "%s", "lcl_HasNextCell( const SwFrame& rFrame ) should be called with SwCellFrame" ); } } while (false) | |||
4846 | "lcl_HasNextCell( const SwFrame& rFrame ) should be called with SwCellFrame" )do { if (true && (!(rFrame.IsCellFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "4846" ": "), "%s", "lcl_HasNextCell( const SwFrame& rFrame ) should be called with SwCellFrame" ); } } while (false); | |||
4847 | ||||
4848 | const SwFrame* pTmpFrame = &rFrame; | |||
4849 | do | |||
4850 | { | |||
4851 | if ( pTmpFrame->GetNext() ) | |||
4852 | return pTmpFrame->GetNext(); | |||
4853 | ||||
4854 | pTmpFrame = pTmpFrame->GetUpper()->GetUpper(); | |||
4855 | } | |||
4856 | while ( pTmpFrame->IsCellFrame() ); | |||
4857 | ||||
4858 | return nullptr; | |||
4859 | } | |||
4860 | ||||
4861 | /** | |||
4862 | * Determine cell frame, from which the border attributes | |||
4863 | * for paint of top/bottom border has to be used. | |||
4864 | * | |||
4865 | * OD 21.02.2003 #b4779636#, #107692# | |||
4866 | * | |||
4867 | * @param _pCellFrame | |||
4868 | * input parameter - constant pointer to cell frame for which the cell frame | |||
4869 | * for the border attributes has to be determined. | |||
4870 | * | |||
4871 | * @param _rCellBorderAttrs | |||
4872 | * input parameter - constant reference to the border attributes of cell frame | |||
4873 | * <_pCellFrame>. | |||
4874 | * | |||
4875 | * @param _bTop | |||
4876 | * input parameter - boolean, that controls, if cell frame for top border or | |||
4877 | * for bottom border has to be determined. | |||
4878 | * | |||
4879 | * @return constant pointer to cell frame, for which the border attributes has | |||
4880 | * to be used | |||
4881 | */ | |||
4882 | static const SwFrame* lcl_GetCellFrameForBorderAttrs( const SwFrame* _pCellFrame, | |||
4883 | const SwBorderAttrs& _rCellBorderAttrs, | |||
4884 | const bool _bTop ) | |||
4885 | { | |||
4886 | OSL_ENSURE( _pCellFrame, "No cell frame available, dying soon" )do { if (true && (!(_pCellFrame))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "4886" ": "), "%s", "No cell frame available, dying soon" ); } } while (false); | |||
4887 | ||||
4888 | // determine, if cell frame is at bottom/top border of a table frame and | |||
4889 | // the table frame has/is a follow. | |||
4890 | const SwFrame* pTmpFrame = _pCellFrame; | |||
4891 | bool bCellAtBorder = true; | |||
4892 | bool bCellAtLeftBorder = !_pCellFrame->GetPrev(); | |||
4893 | bool bCellAtRightBorder = !_pCellFrame->GetNext(); | |||
4894 | while( !pTmpFrame->IsRowFrame() || !pTmpFrame->GetUpper()->IsTabFrame() ) | |||
4895 | { | |||
4896 | pTmpFrame = pTmpFrame->GetUpper(); | |||
4897 | if ( pTmpFrame->IsRowFrame() && | |||
4898 | (_bTop ? pTmpFrame->GetPrev() : pTmpFrame->GetNext()) | |||
4899 | ) | |||
4900 | { | |||
4901 | bCellAtBorder = false; | |||
4902 | } | |||
4903 | if ( pTmpFrame->IsCellFrame() ) | |||
4904 | { | |||
4905 | if ( pTmpFrame->GetPrev() ) | |||
4906 | { | |||
4907 | bCellAtLeftBorder = false; | |||
4908 | } | |||
4909 | if ( pTmpFrame->GetNext() ) | |||
4910 | { | |||
4911 | bCellAtRightBorder = false; | |||
4912 | } | |||
4913 | } | |||
4914 | } | |||
4915 | OSL_ENSURE( pTmpFrame && pTmpFrame->IsRowFrame(), "No RowFrame available" )do { if (true && (!(pTmpFrame && pTmpFrame-> IsRowFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "4915" ": "), "%s", "No RowFrame available"); } } while ( false); | |||
4916 | ||||
4917 | const SwLayoutFrame* pParentRowFrame = static_cast<const SwLayoutFrame*>(pTmpFrame); | |||
4918 | const SwTabFrame* pParentTabFrame = | |||
4919 | static_cast<const SwTabFrame*>(pParentRowFrame->GetUpper()); | |||
4920 | ||||
4921 | const bool bCellNeedsAttribute = bCellAtBorder && | |||
4922 | ( _bTop ? | |||
4923 | // bCellInFirstRowWithMaster | |||
4924 | ( !pParentRowFrame->GetPrev() && | |||
4925 | pParentTabFrame->IsFollow() && | |||
4926 | 0 == pParentTabFrame->GetTable()->GetRowsToRepeat() ) : | |||
4927 | // bCellInLastRowWithFollow | |||
4928 | ( !pParentRowFrame->GetNext() && | |||
4929 | pParentTabFrame->GetFollow() ) | |||
4930 | ); | |||
4931 | ||||
4932 | const SwFrame* pRet = _pCellFrame; | |||
4933 | if ( bCellNeedsAttribute ) | |||
4934 | { | |||
4935 | // determine, if cell frame has no borders inside the table. | |||
4936 | const SwFrame* pNextCell = nullptr; | |||
4937 | bool bNoBordersInside = false; | |||
4938 | ||||
4939 | if ( bCellAtLeftBorder && ( nullptr != ( pNextCell = lcl_HasNextCell( *_pCellFrame ) ) ) ) | |||
4940 | { | |||
4941 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), pNextCell ); | |||
4942 | const SwBorderAttrs &rBorderAttrs = *aAccess.Get(); | |||
4943 | const SvxBoxItem& rBorderBox = rBorderAttrs.GetBox(); | |||
4944 | bCellAtRightBorder = !lcl_HasNextCell( *pNextCell ); | |||
4945 | bNoBordersInside = | |||
4946 | ( !rBorderBox.GetTop() || !pParentRowFrame->GetPrev() ) && | |||
4947 | !rBorderBox.GetLeft() && | |||
4948 | ( !rBorderBox.GetRight() || bCellAtRightBorder ) && | |||
4949 | ( !rBorderBox.GetBottom() || !pParentRowFrame->GetNext() ); | |||
4950 | } | |||
4951 | else | |||
4952 | { | |||
4953 | const SvxBoxItem& rBorderBox = _rCellBorderAttrs.GetBox(); | |||
4954 | bNoBordersInside = | |||
4955 | ( !rBorderBox.GetTop() || !pParentRowFrame->GetPrev() ) && | |||
4956 | ( !rBorderBox.GetLeft() || bCellAtLeftBorder ) && | |||
4957 | ( !rBorderBox.GetRight() || bCellAtRightBorder ) && | |||
4958 | ( !rBorderBox.GetBottom() || !pParentRowFrame->GetNext() ); | |||
4959 | } | |||
4960 | ||||
4961 | if ( bNoBordersInside ) | |||
4962 | { | |||
4963 | if ( _bTop && !_rCellBorderAttrs.GetBox().GetTop() ) | |||
4964 | { | |||
4965 | //-hack | |||
4966 | // Cell frame has no top border and no border inside the table, but | |||
4967 | // it is at the top border of a table frame, which is a follow. | |||
4968 | // Thus, use border attributes of cell frame in first row of complete table. | |||
4969 | // First, determine first table frame of complete table. | |||
4970 | SwTabFrame* pMasterTabFrame = pParentTabFrame->FindMaster( true ); | |||
4971 | // determine first row of complete table. | |||
4972 | const SwFrame* pFirstRow = pMasterTabFrame->GetLower(); | |||
4973 | // return first cell in first row | |||
4974 | SwFrame* pLowerCell = const_cast<SwFrame*>(pFirstRow->GetLower()); | |||
4975 | while ( !pLowerCell->IsCellFrame() || | |||
4976 | ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrame() ) | |||
4977 | ) | |||
4978 | { | |||
4979 | pLowerCell = pLowerCell->GetLower(); | |||
4980 | } | |||
4981 | OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrame(), "No CellFrame available" )do { if (true && (!(pLowerCell && pLowerCell-> IsCellFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "4981" ": "), "%s", "No CellFrame available"); } } while (false); | |||
4982 | pRet = pLowerCell; | |||
4983 | } | |||
4984 | else if ( !_bTop && !_rCellBorderAttrs.GetBox().GetBottom() ) | |||
4985 | { | |||
4986 | //-hack | |||
4987 | // Cell frame has no bottom border and no border inside the table, | |||
4988 | // but it is at the bottom border of a table frame, which has a follow. | |||
4989 | // Thus, use border attributes of cell frame in last row of complete table. | |||
4990 | // First, determine last table frame of complete table. | |||
4991 | SwTabFrame* pLastTabFrame = const_cast<SwTabFrame*>(pParentTabFrame->GetFollow()); | |||
4992 | while ( pLastTabFrame->GetFollow() ) | |||
4993 | { | |||
4994 | pLastTabFrame = pLastTabFrame->GetFollow(); | |||
4995 | } | |||
4996 | // determine last row of complete table. | |||
4997 | SwFrame* pLastRow = pLastTabFrame->GetLastLower(); | |||
4998 | // return first bottom border cell in last row | |||
4999 | SwFrame* pLowerCell = pLastRow->GetLower(); | |||
5000 | while ( !pLowerCell->IsCellFrame() || | |||
5001 | ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrame() ) | |||
5002 | ) | |||
5003 | { | |||
5004 | if ( pLowerCell->IsRowFrame() ) | |||
5005 | { | |||
5006 | while ( pLowerCell->GetNext() ) | |||
5007 | { | |||
5008 | pLowerCell = pLowerCell->GetNext(); | |||
5009 | } | |||
5010 | } | |||
5011 | pLowerCell = pLowerCell->GetLower(); | |||
5012 | } | |||
5013 | OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrame(), "No CellFrame available" )do { if (true && (!(pLowerCell && pLowerCell-> IsCellFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "5013" ": "), "%s", "No CellFrame available"); } } while (false); | |||
5014 | pRet = pLowerCell; | |||
5015 | } | |||
5016 | } | |||
5017 | } | |||
5018 | ||||
5019 | return pRet; | |||
5020 | } | |||
5021 | ||||
5022 | std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> SwFrame::CreateProcessor2D( ) const | |||
5023 | { | |||
5024 | basegfx::B2DRange aViewRange; | |||
5025 | ||||
5026 | SdrPage *pDrawPage = getRootFrame()->GetCurrShell()->Imp()->GetPageView()->GetPage(); | |||
5027 | const drawinglayer::geometry::ViewInformation2D aNewViewInfos( | |||
5028 | basegfx::B2DHomMatrix( ), | |||
5029 | getRootFrame()->GetCurrShell()->GetOut()->GetViewTransformation(), | |||
5030 | aViewRange, | |||
5031 | GetXDrawPageForSdrPage( pDrawPage ), | |||
5032 | 0.0, | |||
5033 | uno::Sequence< beans::PropertyValue >() ); | |||
5034 | ||||
5035 | return drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice( | |||
5036 | *getRootFrame()->GetCurrShell()->GetOut(), | |||
5037 | aNewViewInfos ); | |||
5038 | } | |||
5039 | ||||
5040 | void SwFrame::ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const | |||
5041 | { | |||
5042 | std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D = CreateProcessor2D(); | |||
5043 | if ( pProcessor2D ) | |||
5044 | { | |||
5045 | pProcessor2D->process( rSequence ); | |||
5046 | } | |||
5047 | } | |||
5048 | ||||
5049 | /// Paints shadows and borders | |||
5050 | void SwFrame::PaintSwFrameShadowAndBorder( | |||
5051 | const SwRect& rRect, | |||
5052 | const SwPageFrame* /*pPage*/, | |||
5053 | const SwBorderAttrs& rAttrs) const | |||
5054 | { | |||
5055 | // There's nothing (Row,Body,Footnote,Root,Column,NoText) need to do here | |||
5056 | if (GetType() & (SwFrameType::NoTxt|SwFrameType::Row|SwFrameType::Body|SwFrameType::Ftn|SwFrameType::Column|SwFrameType::Root)) | |||
5057 | return; | |||
5058 | ||||
5059 | if (IsCellFrame() && !gProp.pSGlobalShell->GetViewOptions()->IsTable()) | |||
5060 | return; | |||
5061 | ||||
5062 | // #i29550# | |||
5063 | if ( IsTabFrame() || IsCellFrame() || IsRowFrame() ) | |||
5064 | { | |||
5065 | const SwTabFrame* pTabFrame = FindTabFrame(); | |||
5066 | if ( pTabFrame->IsCollapsingBorders() ) | |||
5067 | return; | |||
5068 | ||||
5069 | if ( pTabFrame->GetTable()->IsNewModel() && ( !IsCellFrame() || IsCoveredCell() ) ) | |||
5070 | return; | |||
5071 | } | |||
5072 | ||||
5073 | const bool bLine = rAttrs.IsLine(); | |||
5074 | const bool bShadow = rAttrs.GetShadow().GetLocation() != SvxShadowLocation::NONE; | |||
5075 | ||||
5076 | // - flag to control, | |||
5077 | //-hack has to be used. | |||
5078 | const bool bb4779636HackActive = true; | |||
5079 | ||||
5080 | const SwFrame* pCellFrameForBottomBorderAttrs = nullptr; | |||
5081 | const SwFrame* pCellFrameForTopBorderAttrs = nullptr; | |||
5082 | bool bFoundCellForTopOrBorderAttrs = false; | |||
5083 | if ( bb4779636HackActive && IsCellFrame() ) | |||
5084 | { | |||
5085 | pCellFrameForBottomBorderAttrs = lcl_GetCellFrameForBorderAttrs( this, rAttrs, false ); | |||
5086 | if ( pCellFrameForBottomBorderAttrs != this ) | |||
5087 | bFoundCellForTopOrBorderAttrs = true; | |||
5088 | pCellFrameForTopBorderAttrs = lcl_GetCellFrameForBorderAttrs( this, rAttrs, true ); | |||
5089 | if ( pCellFrameForTopBorderAttrs != this ) | |||
5090 | bFoundCellForTopOrBorderAttrs = true; | |||
5091 | } | |||
5092 | ||||
5093 | // - add condition <bFoundCellForTopOrBorderAttrs> | |||
5094 | //-hack | |||
5095 | if ( !(bLine || bShadow || bFoundCellForTopOrBorderAttrs) ) | |||
5096 | return; | |||
5097 | ||||
5098 | //If the rectangle is completely inside the PrtArea, no border needs to | |||
5099 | //be painted. | |||
5100 | //For the PrtArea the aligned value needs to be used, otherwise it could | |||
5101 | //happen, that some parts won't be processed. | |||
5102 | SwRect aRect( getFramePrintArea() ); | |||
5103 | aRect += getFrameArea().Pos(); | |||
5104 | ::SwAlignRect( aRect, gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut() ); | |||
5105 | // new local boolean variable in order to | |||
5106 | // suspend border paint under special cases - see below. | |||
5107 | // NOTE: This is a fix for the implementation of feature #99657#. | |||
5108 | bool bDrawOnlyShadowForTransparentFrame = false; | |||
5109 | if ( aRect.IsInside( rRect ) ) | |||
5110 | { | |||
5111 | // paint shadow, if background is transparent. | |||
5112 | // Because of introduced transparent background for fly frame #99657#, | |||
5113 | // the shadow have to be drawn if the background is transparent, | |||
5114 | // in spite the fact that the paint rectangle <rRect> lies fully | |||
5115 | // in the printing area. | |||
5116 | // NOTE to chosen solution: | |||
5117 | // On transparent background, continue processing, but suspend | |||
5118 | // drawing of border by setting <bDrawOnlyShadowForTransparentFrame> | |||
5119 | // to true. | |||
5120 | if ( IsLayoutFrame() && | |||
5121 | static_cast<const SwLayoutFrame*>(this)->GetFormat()->IsBackgroundTransparent() ) | |||
5122 | { | |||
5123 | bDrawOnlyShadowForTransparentFrame = true; | |||
5124 | } | |||
5125 | else | |||
5126 | { | |||
5127 | return; | |||
5128 | } | |||
5129 | } | |||
5130 | ||||
5131 | ::lcl_CalcBorderRect( aRect, this, rAttrs, true, gProp ); | |||
5132 | rAttrs.SetGetCacheLine( true ); | |||
5133 | ||||
5134 | if(bShadow) | |||
5135 | { | |||
5136 | PaintShadow(rRect, aRect, rAttrs); | |||
5137 | } | |||
5138 | ||||
5139 | // suspend drawing of border | |||
5140 | // add condition < NOT bDrawOnlyShadowForTransparentFrame > - see above | |||
5141 | // - add condition <bFoundCellForTopOrBorderAttrs> | |||
5142 | //-hack. | |||
5143 | if((bLine || bFoundCellForTopOrBorderAttrs) && !bDrawOnlyShadowForTransparentFrame) | |||
5144 | { | |||
5145 | // define SvxBorderLine(s) to use | |||
5146 | const SvxBoxItem& rBox(rAttrs.GetBox()); | |||
5147 | const SvxBorderLine* pLeftBorder(rBox.GetLeft()); | |||
5148 | const SvxBorderLine* pRightBorder(rBox.GetRight()); | |||
5149 | const SvxBorderLine* pTopBorder(rBox.GetTop()); | |||
5150 | const SvxBorderLine* pBottomBorder(rBox.GetBottom()); | |||
5151 | ||||
5152 | // if R2L, exchange Right/Left | |||
5153 | const bool bR2L(IsCellFrame() && IsRightToLeft()); | |||
5154 | ||||
5155 | if(bR2L) | |||
5156 | { | |||
5157 | std::swap(pLeftBorder, pRightBorder); | |||
5158 | } | |||
5159 | ||||
5160 | // if ContentFrame and joined Prev/Next, reset top/bottom as needed | |||
5161 | if(IsContentFrame()) | |||
5162 | { | |||
5163 | const SwFrame* pDirRefFrame(IsCellFrame() ? FindTabFrame() : this); | |||
5164 | const SwRectFnSet aRectFnSet(pDirRefFrame); | |||
5165 | const SwRectFn& _rRectFn(aRectFnSet.FnRect()); | |||
5166 | ||||
5167 | if(rAttrs.JoinedWithPrev(*this)) | |||
5168 | { | |||
5169 | // tdf#115296 re-add adaptation of vert distance to close the evtl. | |||
5170 | // existing gap to previous frame | |||
5171 | const SwFrame* pPrevFrame(GetPrev()); | |||
5172 | (aRect.*_rRectFn->fnSetTop)( (pPrevFrame->*_rRectFn->fnGetPrtBottom)() ); | |||
5173 | ||||
5174 | // ...and disable top border paint/creation | |||
5175 | pTopBorder = nullptr; | |||
5176 | } | |||
5177 | ||||
5178 | if(rAttrs.JoinedWithNext(*this)) | |||
5179 | { | |||
5180 | // tdf#115296 re-add adaptation of vert distance to close the evtl. | |||
5181 | // existing gap to next frame | |||
5182 | const SwFrame* pNextFrame(GetNext()); | |||
5183 | (aRect.*_rRectFn->fnSetBottom)( (pNextFrame->*_rRectFn->fnGetPrtTop)() ); | |||
5184 | ||||
5185 | // ...and disable bottom border paint/creation | |||
5186 | pBottomBorder = nullptr; | |||
5187 | } | |||
5188 | } | |||
5189 | ||||
5190 | // necessary to replace TopBorder? | |||
5191 | if((!IsContentFrame() || rAttrs.GetTopLine(*this)) && IsCellFrame() && pCellFrameForTopBorderAttrs != this) | |||
5192 | { | |||
5193 | SwBorderAttrAccess aAccess(SwFrame::GetCache(), pCellFrameForTopBorderAttrs); | |||
5194 | pTopBorder = aAccess.Get()->GetBox().GetTop(); | |||
5195 | } | |||
5196 | ||||
5197 | // necessary to replace BottomBorder? | |||
5198 | if((!IsContentFrame() || rAttrs.GetBottomLine(*this)) && IsCellFrame() && pCellFrameForBottomBorderAttrs != this) | |||
5199 | { | |||
5200 | SwBorderAttrAccess aAccess(SwFrame::GetCache(), pCellFrameForBottomBorderAttrs); | |||
5201 | pBottomBorder = aAccess.Get()->GetBox().GetBottom(); | |||
5202 | } | |||
5203 | ||||
5204 | if(nullptr != pLeftBorder || nullptr != pRightBorder || nullptr != pTopBorder || nullptr != pBottomBorder) | |||
5205 | { | |||
5206 | // now we have all SvxBorderLine(s) sorted out, create geometry | |||
5207 | const basegfx::B2DHomMatrix aBorderTransform( | |||
5208 | basegfx::utils::createScaleTranslateB2DHomMatrix( | |||
5209 | aRect.Width(), aRect.Height(), | |||
5210 | aRect.Left(), aRect.Top())); | |||
5211 | const svx::frame::Style aStyleTop(pTopBorder, 1.0); | |||
5212 | const svx::frame::Style aStyleRight(pRightBorder, 1.0); | |||
5213 | const svx::frame::Style aStyleBottom(pBottomBorder, 1.0); | |||
5214 | const svx::frame::Style aStyleLeft(pLeftBorder, 1.0); | |||
5215 | drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget; | |||
5216 | ||||
5217 | aBorderLineTarget.append( | |||
5218 | drawinglayer::primitive2d::Primitive2DReference( | |||
5219 | new drawinglayer::primitive2d::SwBorderRectanglePrimitive2D( | |||
5220 | aBorderTransform, | |||
5221 | aStyleTop, | |||
5222 | aStyleRight, | |||
5223 | aStyleBottom, | |||
5224 | aStyleLeft))); | |||
5225 | gProp.pBLines->AddBorderLines(aBorderLineTarget); | |||
5226 | } | |||
5227 | } | |||
5228 | ||||
5229 | rAttrs.SetGetCacheLine( false ); | |||
5230 | } | |||
5231 | ||||
5232 | /** | |||
5233 | * Special implementation because of the footnote line | |||
5234 | * | |||
5235 | * Currently only the top frame needs to be taken into account | |||
5236 | * Other lines and shadows are set aside | |||
5237 | */ | |||
5238 | void SwFootnoteContFrame::PaintSwFrameShadowAndBorder( | |||
5239 | const SwRect& rRect, | |||
5240 | const SwPageFrame* pPage, | |||
5241 | const SwBorderAttrs&) const | |||
5242 | { | |||
5243 | //If the rectangle is completely inside the PrtArea, no border needs to | |||
5244 | //be painted. | |||
5245 | SwRect aRect( getFramePrintArea() ); | |||
5246 | aRect.Pos() += getFrameArea().Pos(); | |||
5247 | if ( !aRect.IsInside( rRect ) ) | |||
5248 | PaintLine( rRect, pPage ); | |||
5249 | } | |||
5250 | ||||
5251 | /// Paint footnote lines. | |||
5252 | void SwFootnoteContFrame::PaintLine( const SwRect& rRect, | |||
5253 | const SwPageFrame *pPage ) const | |||
5254 | { | |||
5255 | //The length of the line is derived from the percentual indication on the | |||
5256 | //PageDesc. The position is also stated on the PageDesc. | |||
5257 | //The pen can directly be taken from the PageDesc. | |||
5258 | ||||
5259 | if ( !pPage ) | |||
5260 | pPage = FindPageFrame(); | |||
5261 | const SwPageFootnoteInfo &rInf = pPage->GetPageDesc()->GetFootnoteInfo(); | |||
5262 | ||||
5263 | SwRectFnSet aRectFnSet(this); | |||
5264 | SwTwips nPrtWidth = aRectFnSet.GetWidth(getFramePrintArea()); | |||
5265 | Fraction aFract( nPrtWidth, 1 ); | |||
5266 | aFract *= rInf.GetWidth(); | |||
5267 | const SwTwips nWidth = static_cast<long>(aFract); | |||
5268 | ||||
5269 | SwTwips nX = aRectFnSet.GetPrtLeft(*this); | |||
5270 | switch ( rInf.GetAdj() ) | |||
5271 | { | |||
5272 | case css::text::HorizontalAdjust_CENTER: | |||
5273 | nX += nPrtWidth/2 - nWidth/2; break; | |||
5274 | case css::text::HorizontalAdjust_RIGHT: | |||
5275 | nX += nPrtWidth - nWidth; break; | |||
5276 | case css::text::HorizontalAdjust_LEFT: | |||
5277 | /* do nothing */; break; | |||
5278 | default: | |||
5279 | SAL_WARN("sw.core", "New adjustment for footnote lines?")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.core")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "New adjustment for footnote lines?" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "5279" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "New adjustment for footnote lines?" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "New adjustment for footnote lines?"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "5279" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "New adjustment for footnote lines?") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "5279" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "New adjustment for footnote lines?" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "New adjustment for footnote lines?"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.core"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "5279" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
5280 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", "/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" , 5280, __extension__ __PRETTY_FUNCTION__)); | |||
5281 | } | |||
5282 | SwTwips nLineWidth = rInf.GetLineWidth(); | |||
5283 | const SwRect aLineRect = aRectFnSet.IsVert() ? | |||
5284 | SwRect( Point(getFrameArea().Left()+getFrameArea().Width()-rInf.GetTopDist()-nLineWidth, | |||
5285 | nX), Size( nLineWidth, nWidth ) ) | |||
5286 | : SwRect( Point( nX, getFrameArea().Pos().Y() + rInf.GetTopDist() ), | |||
5287 | Size( nWidth, rInf.GetLineWidth())); | |||
5288 | if ( aLineRect.HasArea() && rInf.GetLineStyle() != SvxBorderLineStyle::NONE) | |||
5289 | PaintBorderLine( rRect, aLineRect , pPage, &rInf.GetLineColor(), | |||
5290 | rInf.GetLineStyle() ); | |||
5291 | } | |||
5292 | ||||
5293 | /// Paints the separator line for inside columns | |||
5294 | void SwLayoutFrame::PaintColLines( const SwRect &rRect, const SwFormatCol &rFormatCol, | |||
5295 | const SwPageFrame *pPage ) const | |||
5296 | { | |||
5297 | const SwFrame *pCol = Lower(); | |||
5298 | if ( !pCol || !pCol->IsColumnFrame() ) | |||
5299 | return; | |||
5300 | ||||
5301 | SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? (pCol->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; | |||
5302 | ||||
5303 | SwRect aLineRect = getFramePrintArea(); | |||
5304 | aLineRect += getFrameArea().Pos(); | |||
5305 | ||||
5306 | SwTwips nTop = ((aLineRect.*fnRect->fnGetHeight)()*rFormatCol.GetLineHeight()) | |||
5307 | / 100 - (aLineRect.*fnRect->fnGetHeight)(); | |||
5308 | SwTwips nBottom = 0; | |||
5309 | ||||
5310 | switch ( rFormatCol.GetLineAdj() ) | |||
5311 | { | |||
5312 | case COLADJ_CENTER: | |||
5313 | nBottom = nTop / 2; nTop -= nBottom; break; | |||
5314 | case COLADJ_TOP: | |||
5315 | nBottom = nTop; nTop = 0; break; | |||
5316 | case COLADJ_BOTTOM: | |||
5317 | break; | |||
5318 | default: | |||
5319 | OSL_ENSURE( false, "New adjustment for column lines?" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "5319" ": "), "%s", "New adjustment for column lines?"); } } while (false); | |||
5320 | } | |||
5321 | ||||
5322 | if( nTop ) | |||
5323 | (aLineRect.*fnRect->fnSubTop)( nTop ); | |||
5324 | if( nBottom ) | |||
5325 | (aLineRect.*fnRect->fnAddBottom)( nBottom ); | |||
5326 | ||||
5327 | SwTwips nPenHalf = rFormatCol.GetLineWidth(); | |||
5328 | (aLineRect.*fnRect->fnSetWidth)( nPenHalf ); | |||
5329 | nPenHalf /= 2; | |||
5330 | ||||
5331 | //We need to be a bit generous here, to not lose something. | |||
5332 | SwRect aRect( rRect ); | |||
5333 | (aRect.*fnRect->fnSubLeft)( nPenHalf + gProp.nSPixelSzW ); | |||
5334 | (aRect.*fnRect->fnAddRight)( nPenHalf + gProp.nSPixelSzW ); | |||
5335 | SwRectGet fnGetX = IsRightToLeft() ? fnRect->fnGetLeft : fnRect->fnGetRight; | |||
5336 | while ( pCol->GetNext() ) | |||
5337 | { | |||
5338 | (aLineRect.*fnRect->fnSetPosX) | |||
5339 | ( (pCol->getFrameArea().*fnGetX)() - nPenHalf ); | |||
5340 | if ( aRect.IsOver( aLineRect ) ) | |||
5341 | PaintBorderLine( aRect, aLineRect , pPage, &rFormatCol.GetLineColor(), | |||
5342 | rFormatCol.GetLineStyle() ); | |||
5343 | pCol = pCol->GetNext(); | |||
5344 | } | |||
5345 | } | |||
5346 | ||||
5347 | void SwPageFrame::PaintGrid( OutputDevice const * pOut, SwRect const &rRect ) const | |||
5348 | { | |||
5349 | if( !m_bHasGrid || gProp.pSRetoucheFly || gProp.pSRetoucheFly2 ) | |||
5350 | return; | |||
5351 | SwTextGridItem const*const pGrid(GetGridItem(this)); | |||
5352 | if( !(pGrid && ( OUTDEV_PRINTER != pOut->GetOutDevType() ? | |||
5353 | pGrid->GetDisplayGrid() : pGrid->GetPrintGrid() )) ) | |||
5354 | return; | |||
5355 | ||||
5356 | const SwLayoutFrame* pBody = FindBodyCont(); | |||
5357 | if( !pBody ) | |||
5358 | return; | |||
5359 | ||||
5360 | SwRect aGrid( pBody->getFramePrintArea() ); | |||
5361 | aGrid += pBody->getFrameArea().Pos(); | |||
5362 | ||||
5363 | SwRect aInter( aGrid ); | |||
5364 | aInter.Intersection( rRect ); | |||
5365 | if( !aInter.HasArea() ) | |||
5366 | return; | |||
5367 | ||||
5368 | bool bGrid = pGrid->GetRubyTextBelow(); | |||
5369 | bool bCell = GRID_LINES_CHARS == pGrid->GetGridType(); | |||
5370 | long nGrid = pGrid->GetBaseHeight(); | |||
5371 | const SwDoc* pDoc = GetFormat()->GetDoc(); | |||
5372 | long nGridWidth = GetGridWidth(*pGrid, *pDoc); | |||
5373 | long nRuby = pGrid->GetRubyHeight(); | |||
5374 | long nSum = nGrid + nRuby; | |||
5375 | const Color *pCol = &pGrid->GetColor(); | |||
5376 | ||||
5377 | SwTwips nRight = aInter.Left() + aInter.Width(); | |||
5378 | SwTwips nBottom = aInter.Top() + aInter.Height(); | |||
5379 | if( IsVertical() ) | |||
5380 | { | |||
5381 | SwTwips nOrig = aGrid.Left() + aGrid.Width(); | |||
5382 | SwTwips nY = nOrig + nSum * | |||
5383 | ( ( nOrig - aInter.Left() ) / nSum ); | |||
5384 | SwRect aTmp( Point( nY, aInter.Top() ), | |||
5385 | Size( 1, aInter.Height() ) ); | |||
5386 | SwTwips nX = aGrid.Top() + nGrid * | |||
5387 | ( ( aInter.Top() - aGrid.Top() )/ nGrid ); | |||
5388 | if( nX < aInter.Top() ) | |||
5389 | nX += nGrid; | |||
5390 | SwTwips nGridBottom = aGrid.Top() + aGrid.Height(); | |||
5391 | bool bLeft = aGrid.Top() >= aInter.Top(); | |||
5392 | bool bRight = nGridBottom <= nBottom; | |||
5393 | bool bBorder = bLeft || bRight; | |||
5394 | while( nY > nRight ) | |||
5395 | { | |||
5396 | aTmp.Pos().setX( nY ); | |||
5397 | if( bGrid ) | |||
5398 | { | |||
5399 | nY -= nGrid; | |||
5400 | SwTwips nPosY = std::max( aInter.Left(), nY ); | |||
5401 | SwTwips nHeight = std::min(nRight, aTmp.Pos().X())-nPosY; | |||
5402 | if( nHeight > 0 ) | |||
5403 | { | |||
5404 | if( bCell ) | |||
5405 | { | |||
5406 | SwRect aVert( Point( nPosY, nX ), | |||
5407 | Size( nHeight, 1 ) ); | |||
5408 | while( aVert.Top() <= nBottom ) | |||
5409 | { | |||
5410 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5411 | aVert.Pos().AdjustY(nGrid ); | |||
5412 | } | |||
5413 | } | |||
5414 | else if( bBorder ) | |||
5415 | { | |||
5416 | SwRect aVert( Point( nPosY, aGrid.Top() ), | |||
5417 | Size( nHeight, 1 ) ); | |||
5418 | if( bLeft ) | |||
5419 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5420 | if( bRight ) | |||
5421 | { | |||
5422 | aVert.Pos().setY( nGridBottom ); | |||
5423 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5424 | } | |||
5425 | } | |||
5426 | } | |||
5427 | } | |||
5428 | else | |||
5429 | { | |||
5430 | nY -= nRuby; | |||
5431 | if( bBorder ) | |||
5432 | { | |||
5433 | SwTwips nPos = std::max( aInter.Left(), nY ); | |||
5434 | SwTwips nW = std::min(nRight, aTmp.Pos().X()) - nPos; | |||
5435 | SwRect aVert( Point( nPos, aGrid.Top() ), | |||
5436 | Size( nW, 1 ) ); | |||
5437 | if( nW > 0 ) | |||
5438 | { | |||
5439 | if( bLeft ) | |||
5440 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5441 | if( bRight ) | |||
5442 | { | |||
5443 | aVert.Pos().setY( nGridBottom ); | |||
5444 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5445 | } | |||
5446 | } | |||
5447 | } | |||
5448 | } | |||
5449 | bGrid = !bGrid; | |||
5450 | } | |||
5451 | while( nY >= aInter.Left() ) | |||
5452 | { | |||
5453 | aTmp.Pos().setX( nY ); | |||
5454 | PaintBorderLine( rRect, aTmp, this, pCol); | |||
5455 | if( bGrid ) | |||
5456 | { | |||
5457 | nY -= nGrid; | |||
5458 | SwTwips nHeight = aTmp.Pos().X() | |||
5459 | - std::max(aInter.Left(), nY ); | |||
5460 | if( nHeight > 0 ) | |||
5461 | { | |||
5462 | if( bCell ) | |||
5463 | { | |||
5464 | SwRect aVert( Point(aTmp.Pos().X()-nHeight, | |||
5465 | nX ), Size( nHeight, 1 ) ); | |||
5466 | while( aVert.Top() <= nBottom ) | |||
5467 | { | |||
5468 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5469 | aVert.Pos().AdjustY(nGrid ); | |||
5470 | } | |||
5471 | } | |||
5472 | else if( bBorder ) | |||
5473 | { | |||
5474 | SwRect aVert( Point(aTmp.Pos().X()-nHeight, | |||
5475 | aGrid.Top() ), Size( nHeight, 1 ) ); | |||
5476 | if( bLeft ) | |||
5477 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5478 | if( bRight ) | |||
5479 | { | |||
5480 | aVert.Pos().setY( nGridBottom ); | |||
5481 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5482 | } | |||
5483 | } | |||
5484 | } | |||
5485 | } | |||
5486 | else | |||
5487 | { | |||
5488 | nY -= nRuby; | |||
5489 | if( bBorder ) | |||
5490 | { | |||
5491 | SwTwips nPos = std::max( aInter.Left(), nY ); | |||
5492 | SwTwips nW = std::min(nRight, aTmp.Pos().X()) - nPos; | |||
5493 | SwRect aVert( Point( nPos, aGrid.Top() ), | |||
5494 | Size( nW, 1 ) ); | |||
5495 | if( nW > 0 ) | |||
5496 | { | |||
5497 | if( bLeft ) | |||
5498 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5499 | if( bRight ) | |||
5500 | { | |||
5501 | aVert.Pos().setY( nGridBottom ); | |||
5502 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5503 | } | |||
5504 | } | |||
5505 | } | |||
5506 | } | |||
5507 | bGrid = !bGrid; | |||
5508 | } | |||
5509 | } | |||
5510 | else | |||
5511 | { | |||
5512 | SwTwips nOrig = aGrid.Top(); | |||
5513 | SwTwips nY = nOrig + nSum *( (aInter.Top()-nOrig)/nSum ); | |||
5514 | SwRect aTmp( Point( aInter.Left(), nY ), | |||
5515 | Size( aInter.Width(), 1 ) ); | |||
5516 | //for textgrid refactor | |||
5517 | SwTwips nX = aGrid.Left() + nGridWidth * | |||
5518 | ( ( aInter.Left() - aGrid.Left() )/ nGridWidth ); | |||
5519 | if( nX < aInter.Left() ) | |||
5520 | nX += nGridWidth; | |||
5521 | SwTwips nGridRight = aGrid.Left() + aGrid.Width(); | |||
5522 | bool bLeft = aGrid.Left() >= aInter.Left(); | |||
5523 | bool bRight = nGridRight <= nRight; | |||
5524 | bool bBorder = bLeft || bRight; | |||
5525 | while( nY < aInter.Top() ) | |||
5526 | { | |||
5527 | aTmp.Pos().setY(nY); | |||
5528 | if( bGrid ) | |||
5529 | { | |||
5530 | nY += nGrid; | |||
5531 | SwTwips nPosY = std::max( aInter.Top(), aTmp.Pos().getY() ); | |||
5532 | SwTwips nHeight = std::min(nBottom, nY ) - nPosY; | |||
5533 | if( nHeight ) | |||
5534 | { | |||
5535 | if( bCell ) | |||
5536 | { | |||
5537 | SwRect aVert( Point( nX, nPosY ), | |||
5538 | Size( 1, nHeight ) ); | |||
5539 | while( aVert.Left() <= nRight ) | |||
5540 | { | |||
5541 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5542 | aVert.Pos().AdjustX(nGridWidth ); //for textgrid refactor | |||
5543 | } | |||
5544 | } | |||
5545 | else if ( bBorder ) | |||
5546 | { | |||
5547 | SwRect aVert( Point( aGrid.Left(), nPosY ), | |||
5548 | Size( 1, nHeight ) ); | |||
5549 | if( bLeft ) | |||
5550 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5551 | if( bRight ) | |||
5552 | { | |||
5553 | aVert.Pos().setX( nGridRight ); | |||
5554 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5555 | } | |||
5556 | } | |||
5557 | } | |||
5558 | } | |||
5559 | else | |||
5560 | { | |||
5561 | nY += nRuby; | |||
5562 | if( bBorder ) | |||
5563 | { | |||
5564 | SwTwips nPos = std::max(aInter.Top(),aTmp.Pos().getY()); | |||
5565 | SwTwips nH = std::min( nBottom, nY ) - nPos; | |||
5566 | SwRect aVert( Point( aGrid.Left(), nPos ), | |||
5567 | Size( 1, nH ) ); | |||
5568 | if( nH > 0 ) | |||
5569 | { | |||
5570 | if( bLeft ) | |||
5571 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5572 | if( bRight ) | |||
5573 | { | |||
5574 | aVert.Pos().setX(nGridRight); | |||
5575 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5576 | } | |||
5577 | } | |||
5578 | } | |||
5579 | } | |||
5580 | bGrid = !bGrid; | |||
5581 | } | |||
5582 | while( nY <= nBottom ) | |||
5583 | { | |||
5584 | aTmp.Pos().setY(nY); | |||
5585 | PaintBorderLine( rRect, aTmp, this, pCol); | |||
5586 | if( bGrid ) | |||
5587 | { | |||
5588 | nY += nGrid; | |||
5589 | SwTwips nHeight = std::min(nBottom, nY) - aTmp.Pos().getY(); | |||
5590 | if( nHeight ) | |||
5591 | { | |||
5592 | if( bCell ) | |||
5593 | { | |||
5594 | SwRect aVert( Point( nX, aTmp.Pos().getY() ), | |||
5595 | Size( 1, nHeight ) ); | |||
5596 | while( aVert.Left() <= nRight ) | |||
5597 | { | |||
5598 | PaintBorderLine( rRect, aVert, this, pCol); | |||
5599 | aVert.Pos().setX(aVert.Pos().getX() + nGridWidth); //for textgrid refactor | |||
5600 | } | |||
5601 | } | |||
5602 | else if( bBorder ) | |||
5603 | { | |||
5604 | SwRect aVert( Point( aGrid.Left(), | |||
5605 | aTmp.Pos().getY() ), Size( 1, nHeight ) ); | |||
5606 | if( bLeft ) | |||
5607 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5608 | if( bRight ) | |||
5609 | { | |||
5610 | aVert.Pos().setX(nGridRight); | |||
5611 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5612 | } | |||
5613 | } | |||
5614 | } | |||
5615 | } | |||
5616 | else | |||
5617 | { | |||
5618 | nY += nRuby; | |||
5619 | if( bBorder ) | |||
5620 | { | |||
5621 | SwTwips nPos = std::max(aInter.Top(),aTmp.Pos().Y()); | |||
5622 | SwTwips nH = std::min( nBottom, nY ) - nPos; | |||
5623 | SwRect aVert( Point( aGrid.Left(), nPos ), | |||
5624 | Size( 1, nH ) ); | |||
5625 | if( nH > 0 ) | |||
5626 | { | |||
5627 | if( bLeft ) | |||
5628 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5629 | if( bRight ) | |||
5630 | { | |||
5631 | aVert.Pos().setX(nGridRight); | |||
5632 | PaintBorderLine(rRect,aVert,this,pCol); | |||
5633 | } | |||
5634 | } | |||
5635 | } | |||
5636 | } | |||
5637 | bGrid = !bGrid; | |||
5638 | } | |||
5639 | } | |||
5640 | } | |||
5641 | ||||
5642 | /** | |||
5643 | * Paint margin area of a page | |||
5644 | * | |||
5645 | * OD 20.11.2002 for #104598#: | |||
5646 | * implement paint of margin area; margin area will be painted for a | |||
5647 | * view shell with a window and if the document is not in online layout. | |||
5648 | * | |||
5649 | * @param _rOutputRect | |||
5650 | * input parameter - constant instance reference of the rectangle, for | |||
5651 | * which an output has to be generated. | |||
5652 | * | |||
5653 | * @param _pViewShell | |||
5654 | * input parameter - instance of the view shell, on which the output | |||
5655 | * has to be generated. | |||
5656 | */ | |||
5657 | void SwPageFrame::PaintMarginArea( const SwRect& _rOutputRect, | |||
5658 | SwViewShell const * _pViewShell ) const | |||
5659 | { | |||
5660 | if ( !_pViewShell->GetWin() || _pViewShell->GetViewOptions()->getBrowseMode() ) | |||
5661 | return; | |||
5662 | ||||
5663 | // Simplified paint with DrawingLayer FillStyle | |||
5664 | SwRect aPgRect = getFrameArea(); | |||
5665 | aPgRect.Intersection_( _rOutputRect ); | |||
5666 | ||||
5667 | if(!aPgRect.IsEmpty()) | |||
5668 | { | |||
5669 | OutputDevice *pOut = _pViewShell->GetOut(); | |||
5670 | ||||
5671 | if(pOut->GetFillColor() != aGlobalRetoucheColor) | |||
5672 | { | |||
5673 | pOut->SetFillColor(aGlobalRetoucheColor); | |||
5674 | } | |||
5675 | ||||
5676 | pOut->DrawRect(aPgRect.SVRect()); | |||
5677 | } | |||
5678 | } | |||
5679 | ||||
5680 | const sal_Int8 SwPageFrame::mnShadowPxWidth = 9; | |||
5681 | ||||
5682 | bool SwPageFrame::IsRightShadowNeeded() const | |||
5683 | { | |||
5684 | const SwViewShell *pSh = getRootFrame()->GetCurrShell(); | |||
5685 | const bool bIsLTR = getRootFrame()->IsLeftToRightViewLayout(); | |||
5686 | ||||
5687 | // We paint the right shadow if we're not in book mode | |||
5688 | // or if we've no sibling or are the last page of the "row" | |||
5689 | return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetNext() | |||
5690 | || (this == Lower()) || (bIsLTR && OnRightPage()) | |||
5691 | || (!bIsLTR && !OnRightPage()); | |||
5692 | ||||
5693 | } | |||
5694 | ||||
5695 | bool SwPageFrame::IsLeftShadowNeeded() const | |||
5696 | { | |||
5697 | const SwViewShell *pSh = getRootFrame()->GetCurrShell(); | |||
5698 | const bool bIsLTR = getRootFrame()->IsLeftToRightViewLayout(); | |||
5699 | ||||
5700 | // We paint the left shadow if we're not in book mode | |||
5701 | // or if we've no sibling or are the last page of the "row" | |||
5702 | return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetPrev() | |||
5703 | || (bIsLTR && !OnRightPage()) | |||
5704 | || (!bIsLTR && OnRightPage()); | |||
5705 | } | |||
5706 | ||||
5707 | /** | |||
5708 | * Determine rectangle for bottom page shadow | |||
5709 | * for #i9719# | |||
5710 | */ | |||
5711 | /*static*/ void SwPageFrame::GetHorizontalShadowRect( const SwRect& _rPageRect, | |||
5712 | const SwViewShell* _pViewShell, | |||
5713 | OutputDevice const * pRenderContext, | |||
5714 | SwRect& _orHorizontalShadowRect, | |||
5715 | bool bPaintLeftShadow, | |||
5716 | bool bPaintRightShadow, | |||
5717 | bool bRightSidebar ) | |||
5718 | { | |||
5719 | const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr(); | |||
5720 | SwRect aAlignedPageRect( _rPageRect ); | |||
5721 | ::SwAlignRect( aAlignedPageRect, _pViewShell, pRenderContext ); | |||
5722 | SwRect aPagePxRect = pRenderContext->LogicToPixel( aAlignedPageRect.SVRect() ); | |||
5723 | ||||
5724 | long lShadowAdjustment = mnShadowPxWidth - 1; // TODO: extract this | |||
5725 | ||||
5726 | _orHorizontalShadowRect.Chg( | |||
5727 | Point( aPagePxRect.Left() + (bPaintLeftShadow ? lShadowAdjustment : 0), 0 ), | |||
5728 | Size( aPagePxRect.Width() - ( (bPaintLeftShadow ? lShadowAdjustment : 0) + (bPaintRightShadow ? lShadowAdjustment : 0) ), | |||
5729 | mnShadowPxWidth ) ); | |||
5730 | ||||
5731 | if(pMgr && pMgr->ShowNotes() && pMgr->HasNotes()) | |||
5732 | { | |||
5733 | // Notes are displayed, we've to extend borders | |||
5734 | SwTwips aSidebarTotalWidth = pMgr->GetSidebarWidth(true) + pMgr->GetSidebarBorderWidth(true); | |||
5735 | if(bRightSidebar) | |||
5736 | _orHorizontalShadowRect.AddRight( aSidebarTotalWidth ); | |||
5737 | else | |||
5738 | _orHorizontalShadowRect.AddLeft( - aSidebarTotalWidth ); | |||
5739 | } | |||
5740 | } | |||
5741 | ||||
5742 | namespace { | |||
5743 | ||||
5744 | enum PaintArea {LEFT, RIGHT, TOP, BOTTOM}; | |||
5745 | ||||
5746 | } | |||
5747 | ||||
5748 | #define BORDER_TILE_SIZE512 512 | |||
5749 | ||||
5750 | /// Wrapper around pOut->DrawBitmapEx. | |||
5751 | static void lcl_paintBitmapExToRect(vcl::RenderContext *pOut, const Point& aPoint, const Size& aSize, const BitmapEx& rBitmapEx, PaintArea eArea) | |||
5752 | { | |||
5753 | // The problem is that if we get called multiple times and the color is | |||
5754 | // partly transparent, then the result will get darker and darker. To avoid | |||
5755 | // this, always paint the background color before doing the real paint. | |||
5756 | tools::Rectangle aRect(aPoint, aSize); | |||
5757 | ||||
5758 | if (!aRect.IsEmpty()) | |||
5759 | { | |||
5760 | switch (eArea) | |||
5761 | { | |||
5762 | case LEFT: aRect.SetLeft( aRect.Right() - 1 ); break; | |||
5763 | case RIGHT: aRect.SetRight( aRect.Left() + 1 ); break; | |||
5764 | case TOP: aRect.SetTop( aRect.Bottom() - 1 ); break; | |||
5765 | case BOTTOM: aRect.SetBottom( aRect.Top() + 1 ); break; | |||
5766 | } | |||
5767 | } | |||
5768 | ||||
5769 | pOut->SetFillColor(SwViewOption::GetAppBackgroundColor()); | |||
5770 | pOut->SetLineColor(); | |||
5771 | pOut->DrawRect(pOut->PixelToLogic(aRect)); | |||
5772 | ||||
5773 | // Tiled render if necessary | |||
5774 | tools::Rectangle aComplete(aPoint, aSize); | |||
5775 | Size aTileSize(BORDER_TILE_SIZE512, BORDER_TILE_SIZE512); | |||
5776 | ||||
5777 | long iterX = eArea != RIGHT && eArea != LEFT ? BORDER_TILE_SIZE512 : 0; | |||
5778 | long iterY = eArea == RIGHT || eArea == LEFT ? BORDER_TILE_SIZE512 : 0; | |||
5779 | ||||
5780 | for (tools::Rectangle aTile(aPoint, aTileSize); true; aTile.Move(iterX, iterY)) | |||
5781 | { | |||
5782 | tools::Rectangle aRender = aComplete.GetIntersection(aTile); | |||
5783 | if (aRender.IsEmpty()) | |||
5784 | break; | |||
5785 | pOut->DrawBitmapEx(pOut->PixelToLogic(aRender.TopLeft()), | |||
5786 | pOut->PixelToLogic(aRender.GetSize()), | |||
5787 | Point(0, 0), aRender.GetSize(), | |||
5788 | rBitmapEx); | |||
5789 | } | |||
5790 | ||||
5791 | } | |||
5792 | ||||
5793 | /** | |||
5794 | * Paint page border and shadow | |||
5795 | * | |||
5796 | * for #i9719# | |||
5797 | * implement paint of page border and shadow | |||
5798 | */ | |||
5799 | /*static*/ void SwPageFrame::PaintBorderAndShadow( const SwRect& _rPageRect, | |||
5800 | const SwViewShell* _pViewShell, | |||
5801 | bool bPaintLeftShadow, | |||
5802 | bool bPaintRightShadow, | |||
5803 | bool bRightSidebar ) | |||
5804 | { | |||
5805 | // No shadow in prefs | |||
5806 | if (!SwViewOption::IsShadow()) | |||
5807 | return; | |||
5808 | ||||
5809 | // #i16816# tagged pdf support | |||
5810 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *_pViewShell->GetOut() ); | |||
5811 | ||||
5812 | static vcl::DeleteOnDeinit<drawinglayer::primitive2d::DiscreteShadow> shadowMaskObj( | |||
5813 | new drawinglayer::primitive2d::DiscreteShadow( | |||
5814 | vcl::bitmap::loadFromName(BMP_PAGE_SHADOW_MASK"sw/res/page-shadow-mask.png", | |||
5815 | ImageLoadFlags::IgnoreDarkTheme | ImageLoadFlags::IgnoreScalingFactor))); | |||
5816 | ||||
5817 | drawinglayer::primitive2d::DiscreteShadow& shadowMask = *shadowMaskObj.get(); | |||
5818 | static vcl::DeleteOnDeinit< BitmapEx > aPageTopRightShadowObj( new BitmapEx ); | |||
5819 | static vcl::DeleteOnDeinit< BitmapEx > aPageBottomRightShadowObj( new BitmapEx ); | |||
5820 | static vcl::DeleteOnDeinit< BitmapEx > aPageBottomLeftShadowObj( new BitmapEx ); | |||
5821 | static vcl::DeleteOnDeinit< BitmapEx > aPageBottomShadowBaseObj( new BitmapEx ); | |||
5822 | static vcl::DeleteOnDeinit< BitmapEx > aPageRightShadowBaseObj( new BitmapEx ); | |||
5823 | static vcl::DeleteOnDeinit< BitmapEx > aPageTopShadowBaseObj( new BitmapEx ); | |||
5824 | static vcl::DeleteOnDeinit< BitmapEx > aPageTopLeftShadowObj( new BitmapEx ); | |||
5825 | static vcl::DeleteOnDeinit< BitmapEx > aPageLeftShadowBaseObj( new BitmapEx ); | |||
5826 | BitmapEx& aPageTopRightShadow = *aPageTopRightShadowObj.get(); | |||
5827 | BitmapEx& aPageBottomRightShadow = *aPageBottomRightShadowObj.get(); | |||
5828 | BitmapEx& aPageBottomLeftShadow = *aPageBottomLeftShadowObj.get(); | |||
5829 | BitmapEx& aPageBottomShadow = *aPageBottomShadowBaseObj.get(); | |||
5830 | BitmapEx& aPageRightShadow = *aPageRightShadowBaseObj.get(); | |||
5831 | BitmapEx& aPageTopShadow = *aPageTopShadowBaseObj.get(); | |||
5832 | BitmapEx& aPageTopLeftShadow = *aPageTopLeftShadowObj.get(); | |||
5833 | BitmapEx& aPageLeftShadow = *aPageLeftShadowBaseObj.get(); | |||
5834 | static Color aShadowColor( COL_AUTO ); | |||
5835 | ||||
5836 | SwRect aAlignedPageRect( _rPageRect ); | |||
5837 | ::SwAlignRect( aAlignedPageRect, _pViewShell, _pViewShell->GetOut() ); | |||
5838 | SwRect aPagePxRect = _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() ); | |||
5839 | ||||
5840 | if (aShadowColor != SwViewOption::GetShadowColor()) | |||
5841 | { | |||
5842 | aShadowColor = SwViewOption::GetShadowColor(); | |||
5843 | ||||
5844 | AlphaMask aMask( shadowMask.getBottomRight().GetBitmap() ); | |||
5845 | Bitmap aFilledSquare( aMask.GetSizePixel(), 24 ); | |||
5846 | aFilledSquare.Erase( aShadowColor ); | |||
5847 | aPageBottomRightShadow = BitmapEx( aFilledSquare, aMask ); | |||
5848 | ||||
5849 | aMask = AlphaMask( shadowMask.getBottomLeft().GetBitmap() ); | |||
5850 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5851 | aFilledSquare.Erase( aShadowColor ); | |||
5852 | aPageBottomLeftShadow = BitmapEx( aFilledSquare, aMask ); | |||
5853 | ||||
5854 | aMask = AlphaMask( shadowMask.getBottom().GetBitmap() ); | |||
5855 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5856 | aFilledSquare.Erase( aShadowColor ); | |||
5857 | aPageBottomShadow = BitmapEx( aFilledSquare, aMask ); | |||
5858 | ||||
5859 | aMask = AlphaMask( shadowMask.getTop().GetBitmap() ); | |||
5860 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5861 | aFilledSquare.Erase( aShadowColor ); | |||
5862 | aPageTopShadow = BitmapEx( aFilledSquare, aMask ); | |||
5863 | ||||
5864 | aMask = AlphaMask( shadowMask.getTopRight().GetBitmap() ); | |||
5865 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5866 | aFilledSquare.Erase( aShadowColor ); | |||
5867 | aPageTopRightShadow = BitmapEx( aFilledSquare, aMask ); | |||
5868 | ||||
5869 | aMask = AlphaMask( shadowMask.getRight().GetBitmap() ); | |||
5870 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5871 | aFilledSquare.Erase( aShadowColor ); | |||
5872 | aPageRightShadow = BitmapEx( aFilledSquare, aMask ); | |||
5873 | ||||
5874 | aMask = AlphaMask( shadowMask.getTopLeft().GetBitmap() ); | |||
5875 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5876 | aFilledSquare.Erase( aShadowColor ); | |||
5877 | aPageTopLeftShadow = BitmapEx( aFilledSquare, aMask ); | |||
5878 | ||||
5879 | aMask = AlphaMask( shadowMask.getLeft().GetBitmap() ); | |||
5880 | aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 ); | |||
5881 | aFilledSquare.Erase( aShadowColor ); | |||
5882 | aPageLeftShadow = BitmapEx( aFilledSquare, aMask ); | |||
5883 | } | |||
5884 | ||||
5885 | SwRect aPaintRect; | |||
5886 | OutputDevice *pOut = _pViewShell->GetOut(); | |||
5887 | ||||
5888 | SwPageFrame::GetHorizontalShadowRect( _rPageRect, _pViewShell, pOut, aPaintRect, bPaintLeftShadow, bPaintRightShadow, bRightSidebar ); | |||
5889 | ||||
5890 | // Right shadow & corners | |||
5891 | if ( bPaintRightShadow ) | |||
5892 | { | |||
5893 | pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right(), aPagePxRect.Bottom() + 1 - (aPageBottomRightShadow.GetSizePixel().Height() - mnShadowPxWidth) ) ), | |||
5894 | aPageBottomRightShadow ); | |||
5895 | pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right(), aPagePxRect.Top() - mnShadowPxWidth ) ), | |||
5896 | aPageTopRightShadow ); | |||
5897 | ||||
5898 | if (aPagePxRect.Height() > 2 * mnShadowPxWidth) | |||
5899 | { | |||
5900 | const long nWidth = aPageRightShadow.GetSizePixel().Width(); | |||
5901 | const long nHeight = aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1); | |||
5902 | if (aPageRightShadow.GetSizePixel().Height() < BORDER_TILE_SIZE512) | |||
5903 | aPageRightShadow.Scale(Size(nWidth, BORDER_TILE_SIZE512), BmpScaleFlag::Fast); | |||
5904 | ||||
5905 | lcl_paintBitmapExToRect(pOut, | |||
5906 | Point(aPaintRect.Right() + mnShadowPxWidth, aPagePxRect.Top() + mnShadowPxWidth - 1), | |||
5907 | Size(nWidth, nHeight), | |||
5908 | aPageRightShadow, RIGHT); | |||
5909 | } | |||
5910 | } | |||
5911 | ||||
5912 | // Left shadows and corners | |||
5913 | if(bPaintLeftShadow) | |||
5914 | { | |||
5915 | const long lLeft = aPaintRect.Left() - aPageBottomLeftShadow.GetSizePixel().Width(); | |||
5916 | pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, | |||
5917 | aPagePxRect.Bottom() + 1 + mnShadowPxWidth - aPageBottomLeftShadow.GetSizePixel().Height() ) ), aPageBottomLeftShadow ); | |||
5918 | pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, aPagePxRect.Top() - mnShadowPxWidth ) ), aPageTopLeftShadow ); | |||
5919 | if (aPagePxRect.Height() > 2 * mnShadowPxWidth) | |||
5920 | { | |||
5921 | const long nWidth = aPageLeftShadow.GetSizePixel().Width(); | |||
5922 | const long nHeight = aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1); | |||
5923 | if (aPageLeftShadow.GetSizePixel().Height() < BORDER_TILE_SIZE512) | |||
5924 | aPageLeftShadow.Scale(Size(nWidth, BORDER_TILE_SIZE512), BmpScaleFlag::Fast); | |||
5925 | ||||
5926 | lcl_paintBitmapExToRect(pOut, | |||
5927 | Point(lLeft, aPagePxRect.Top() + mnShadowPxWidth - 1), | |||
5928 | Size(nWidth, nHeight), | |||
5929 | aPageLeftShadow, LEFT); | |||
5930 | } | |||
5931 | } | |||
5932 | ||||
5933 | // Bottom shadow | |||
5934 | const long nBottomHeight = aPageBottomShadow.GetSizePixel().Height(); | |||
5935 | if (aPageBottomShadow.GetSizePixel().Width() < BORDER_TILE_SIZE512) | |||
5936 | aPageBottomShadow.Scale(Size(BORDER_TILE_SIZE512, nBottomHeight), BmpScaleFlag::Fast); | |||
5937 | ||||
5938 | lcl_paintBitmapExToRect(pOut, | |||
5939 | Point(aPaintRect.Left(), aPagePxRect.Bottom() + 2), | |||
5940 | Size(aPaintRect.Width(), nBottomHeight), | |||
5941 | aPageBottomShadow, BOTTOM); | |||
5942 | ||||
5943 | // Top shadow | |||
5944 | const long nTopHeight = aPageTopShadow.GetSizePixel().Height(); | |||
5945 | if (aPageTopShadow.GetSizePixel().Width() < BORDER_TILE_SIZE512) | |||
5946 | aPageTopShadow.Scale(Size(BORDER_TILE_SIZE512, nTopHeight), BmpScaleFlag::Fast); | |||
5947 | ||||
5948 | lcl_paintBitmapExToRect(pOut, | |||
5949 | Point(aPaintRect.Left(), aPagePxRect.Top() - mnShadowPxWidth), | |||
5950 | Size(aPaintRect.Width(), nTopHeight), | |||
5951 | aPageTopShadow, TOP); | |||
5952 | } | |||
5953 | ||||
5954 | /** | |||
5955 | * mod #i6193# paint sidebar for notes | |||
5956 | * IMPORTANT: if you change the rects here, also change SwPostItMgr::ScrollbarHit | |||
5957 | */ | |||
5958 | /*static*/void SwPageFrame::PaintNotesSidebar(const SwRect& _rPageRect, SwViewShell* _pViewShell, sal_uInt16 nPageNum, bool bRight) | |||
5959 | { | |||
5960 | //TODO: cut out scrollbar area and arrows out of sidepane rect, otherwise it could flicker when pressing arrow buttons | |||
5961 | if (!_pViewShell ) | |||
5962 | return; | |||
5963 | ||||
5964 | SwRect aPageRect( _rPageRect ); | |||
5965 | SwAlignRect( aPageRect, _pViewShell, _pViewShell->GetOut() ); | |||
5966 | ||||
5967 | const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr(); | |||
5968 | if (!(pMgr && pMgr->ShowNotes() && pMgr->HasNotes())) // do not show anything in print preview | |||
5969 | return; | |||
5970 | ||||
5971 | sal_Int32 nScrollerHeight = pMgr->GetSidebarScrollerHeight(); | |||
5972 | const tools::Rectangle &aVisRect = _pViewShell->VisArea().SVRect(); | |||
5973 | //draw border and sidepane | |||
5974 | _pViewShell->GetOut()->SetLineColor(); | |||
5975 | if (!bRight) | |||
5976 | { | |||
5977 | _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDERColor(200,200,200)); | |||
5978 | _pViewShell->GetOut()->DrawRect(tools::Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()))) ; | |||
5979 | if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
5980 | _pViewShell->GetOut()->SetFillColor(COL_BLACK); | |||
5981 | else | |||
5982 | _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANEColor(230,230,230)); | |||
5983 | _pViewShell->GetOut()->DrawRect(tools::Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarWidth()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()))) ; | |||
5984 | } | |||
5985 | else | |||
5986 | { | |||
5987 | _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDERColor(200,200,200)); | |||
5988 | SwRect aSidebarBorder(aPageRect.TopRight(),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height())); | |||
5989 | _pViewShell->GetOut()->DrawRect(aSidebarBorder.SVRect()); | |||
5990 | if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
5991 | _pViewShell->GetOut()->SetFillColor(COL_BLACK); | |||
5992 | else | |||
5993 | _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANEColor(230,230,230)); | |||
5994 | SwRect aSidebar(Point(aPageRect.Right()+pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height())); | |||
5995 | _pViewShell->GetOut()->DrawRect(aSidebar.SVRect()); | |||
5996 | } | |||
5997 | if (!pMgr->ShowScrollbar(nPageNum)) | |||
5998 | return; | |||
5999 | ||||
6000 | // draw scrollbar area and arrows | |||
6001 | Point aPointBottom; | |||
6002 | Point aPointTop; | |||
6003 | 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()) : | |||
6004 | Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height()); | |||
6005 | aPointTop = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height()) : | |||
6006 | Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height()); | |||
6007 | Size aSize(pMgr->GetSidebarWidth() - _pViewShell->GetOut()->PixelToLogic(Size(4,0)).Width(), _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()) ; | |||
6008 | tools::Rectangle aRectBottom(aPointBottom,aSize); | |||
6009 | tools::Rectangle aRectTop(aPointTop,aSize); | |||
6010 | ||||
6011 | if (aRectBottom.IsOver(aVisRect)) | |||
6012 | { | |||
6013 | ||||
6014 | if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
6015 | { | |||
6016 | _pViewShell->GetOut()->SetLineColor(COL_WHITE); | |||
6017 | _pViewShell->GetOut()->SetFillColor(COL_BLACK); | |||
6018 | } | |||
6019 | else | |||
6020 | { | |||
6021 | _pViewShell->GetOut()->SetLineColor(COL_BLACK); | |||
6022 | _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREAColor(230,230,220)); | |||
6023 | } | |||
6024 | _pViewShell->GetOut()->DrawRect(aRectBottom); | |||
6025 | _pViewShell->GetOut()->DrawLine(aPointBottom + Point(pMgr->GetSidebarWidth()/3,0), aPointBottom + Point(pMgr->GetSidebarWidth()/3 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height())); | |||
6026 | ||||
6027 | _pViewShell->GetOut()->SetLineColor(); | |||
6028 | Point aMiddleFirst(aPointBottom + Point(pMgr->GetSidebarWidth()/6,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2)); | |||
6029 | Point aMiddleSecond(aPointBottom + Point(pMgr->GetSidebarWidth()/3*2,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2)); | |||
6030 | PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell,pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum)); | |||
6031 | } | |||
6032 | if (!aRectTop.IsOver(aVisRect)) | |||
6033 | return; | |||
6034 | ||||
6035 | if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) | |||
6036 | { | |||
6037 | _pViewShell->GetOut()->SetLineColor(COL_WHITE); | |||
6038 | _pViewShell->GetOut()->SetFillColor(COL_BLACK); | |||
6039 | } | |||
6040 | else | |||
6041 | { | |||
6042 | _pViewShell->GetOut()->SetLineColor(COL_BLACK); | |||
6043 | _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREAColor(230,230,220)); | |||
6044 | } | |||
6045 | _pViewShell->GetOut()->DrawRect(aRectTop); | |||
6046 | _pViewShell->GetOut()->DrawLine(aPointTop + Point(pMgr->GetSidebarWidth()/3*2,0), aPointTop + Point(pMgr->GetSidebarWidth()/3*2 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height())); | |||
6047 | ||||
6048 | _pViewShell->GetOut()->SetLineColor(); | |||
6049 | Point aMiddleFirst(aPointTop + Point(pMgr->GetSidebarWidth()/3,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2)); | |||
6050 | Point aMiddleSecond(aPointTop + Point(pMgr->GetSidebarWidth()/6*5,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2)); | |||
6051 | PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell, pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum)); | |||
6052 | } | |||
6053 | ||||
6054 | /*static*/ void SwPageFrame::PaintNotesSidebarArrows(const Point &aMiddleFirst, const Point &aMiddleSecond, SwViewShell const * _pViewShell, const Color& rColorUp, const Color& rColorDown) | |||
6055 | { | |||
6056 | tools::Polygon aTriangleUp(3); | |||
6057 | tools::Polygon aTriangleDown(3); | |||
6058 | ||||
6059 | aTriangleUp.SetPoint(aMiddleFirst + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0); | |||
6060 | aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),1); | |||
6061 | aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2); | |||
6062 | ||||
6063 | aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0); | |||
6064 | aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(+3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),1); | |||
6065 | aTriangleDown.SetPoint(aMiddleSecond + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2); | |||
6066 | ||||
6067 | _pViewShell->GetOut()->SetFillColor(rColorUp); | |||
6068 | _pViewShell->GetOut()->DrawPolygon(aTriangleUp); | |||
6069 | _pViewShell->GetOut()->SetFillColor(rColorDown); | |||
6070 | _pViewShell->GetOut()->DrawPolygon(aTriangleDown); | |||
6071 | } | |||
6072 | ||||
6073 | /** | |||
6074 | * Get bound rectangle of border and shadow for repaints | |||
6075 | * | |||
6076 | * for #i9719# | |||
6077 | */ | |||
6078 | /*static*/ void SwPageFrame::GetBorderAndShadowBoundRect( const SwRect& _rPageRect, | |||
6079 | const SwViewShell* _pViewShell, | |||
6080 | OutputDevice const * pRenderContext, | |||
6081 | SwRect& _orBorderAndShadowBoundRect, | |||
6082 | bool bLeftShadow, | |||
6083 | bool bRightShadow, | |||
6084 | bool bRightSidebar | |||
6085 | ) | |||
6086 | { | |||
6087 | SwRect aAlignedPageRect( _rPageRect ); | |||
6088 | ::SwAlignRect( aAlignedPageRect, _pViewShell, pRenderContext ); | |||
6089 | SwRect aPagePxRect = pRenderContext->LogicToPixel( aAlignedPageRect.SVRect() ); | |||
6090 | aPagePxRect.AddBottom( mnShadowPxWidth + 1 ); | |||
6091 | aPagePxRect.AddTop( - mnShadowPxWidth - 1 ); | |||
6092 | ||||
6093 | SwRect aTmpRect; | |||
6094 | ||||
6095 | // Always ask for full shadow since we want a bounding rect | |||
6096 | // including at least the page frame | |||
6097 | SwPageFrame::GetHorizontalShadowRect( _rPageRect, _pViewShell, pRenderContext, aTmpRect, false, false, bRightSidebar ); | |||
6098 | ||||
6099 | if(bLeftShadow) aPagePxRect.Left( aTmpRect.Left() - mnShadowPxWidth - 1); | |||
6100 | if(bRightShadow) aPagePxRect.Right( aTmpRect.Right() + mnShadowPxWidth + 1); | |||
6101 | ||||
6102 | _orBorderAndShadowBoundRect = pRenderContext->PixelToLogic( aPagePxRect.SVRect() ); | |||
6103 | } | |||
6104 | ||||
6105 | SwRect SwPageFrame::GetBoundRect(OutputDevice const * pOutputDevice) const | |||
6106 | { | |||
6107 | const SwViewShell *pSh = getRootFrame()->GetCurrShell(); | |||
6108 | SwRect aPageRect( getFrameArea() ); | |||
6109 | SwRect aResult; | |||
6110 | ||||
6111 | if(!pSh) { | |||
6112 | return SwRect( Point(0, 0), Size(0, 0) ); | |||
6113 | } | |||
6114 | ||||
6115 | SwPageFrame::GetBorderAndShadowBoundRect( aPageRect, pSh, pOutputDevice, aResult, | |||
6116 | IsLeftShadowNeeded(), IsRightShadowNeeded(), SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT ); | |||
6117 | return aResult; | |||
6118 | } | |||
6119 | ||||
6120 | /*static*/ SwTwips SwPageFrame::GetSidebarBorderWidth( const SwViewShell* _pViewShell ) | |||
6121 | { | |||
6122 | const SwPostItMgr* pPostItMgr = _pViewShell ? _pViewShell->GetPostItMgr() : nullptr; | |||
6123 | const SwTwips nRet = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0; | |||
6124 | return nRet; | |||
6125 | } | |||
6126 | ||||
6127 | void SwFrame::PaintBaBo( const SwRect& rRect, const SwPageFrame *pPage, | |||
6128 | const bool bOnlyTextBackground ) const | |||
6129 | { | |||
6130 | if ( !pPage ) | |||
6131 | pPage = FindPageFrame(); | |||
6132 | ||||
6133 | OutputDevice *pOut = gProp.pSGlobalShell->GetOut(); | |||
6134 | ||||
6135 | // #i16816# tagged pdf support | |||
6136 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pOut ); | |||
6137 | ||||
6138 | pOut->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR ); | |||
6139 | pOut->SetLineColor(); | |||
6140 | ||||
6141 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); | |||
6142 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
6143 | ||||
6144 | // take care of page margin area | |||
6145 | // Note: code move from <SwFrame::PaintSwFrameBackground(..)> to new method | |||
6146 | // <SwPageFrame::Paintmargin(..)>. | |||
6147 | if ( IsPageFrame() && !bOnlyTextBackground) | |||
6148 | { | |||
6149 | static_cast<const SwPageFrame*>(this)->PaintMarginArea( rRect, gProp.pSGlobalShell ); | |||
6150 | } | |||
6151 | ||||
6152 | // paint background | |||
6153 | { | |||
6154 | PaintSwFrameBackground( rRect, pPage, rAttrs, false, true/*bLowerBorder*/, bOnlyTextBackground ); | |||
6155 | } | |||
6156 | ||||
6157 | // paint border before painting background | |||
6158 | // paint grid for page frame and paint border | |||
6159 | if (!bOnlyTextBackground) | |||
6160 | { | |||
6161 | SwRect aRect( rRect ); | |||
6162 | ||||
6163 | if( IsPageFrame() ) | |||
6164 | { | |||
6165 | static_cast<const SwPageFrame*>(this)->PaintGrid( pOut, aRect ); | |||
6166 | } | |||
6167 | ||||
6168 | PaintSwFrameShadowAndBorder(aRect, pPage, rAttrs); | |||
6169 | } | |||
6170 | ||||
6171 | pOut->Pop(); | |||
6172 | } | |||
6173 | ||||
6174 | static bool lcl_compareFillAttributes(const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& pA, const drawinglayer::attribute::SdrAllFillAttributesHelperPtr& pB) | |||
6175 | { | |||
6176 | if (pA == pB) | |||
6177 | return true; | |||
6178 | if (!pA || !pB) | |||
6179 | return false; | |||
6180 | return pA->getFillAttribute() == pB->getFillAttribute(); | |||
6181 | } | |||
6182 | ||||
6183 | /// Do not paint background for fly frames without a background brush by | |||
6184 | /// calling <PaintBaBo> at the page or at the fly frame its anchored | |||
6185 | void SwFrame::PaintSwFrameBackground( const SwRect &rRect, const SwPageFrame *pPage, | |||
6186 | const SwBorderAttrs & rAttrs, | |||
6187 | const bool bLowerMode, | |||
6188 | const bool bLowerBorder, | |||
6189 | const bool bOnlyTextBackground ) const | |||
6190 | { | |||
6191 | // #i1837# - no paint of table background, if corresponding option is *not* set. | |||
6192 | if( IsTabFrame() && | |||
6193 | !gProp.pSGlobalShell->GetViewOptions()->IsTable() ) | |||
6194 | { | |||
6195 | return; | |||
6196 | } | |||
6197 | ||||
6198 | SwViewShell *pSh = gProp.pSGlobalShell; | |||
6199 | ||||
6200 | // #i16816# tagged pdf support | |||
6201 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pSh->GetOut() ); | |||
6202 | ||||
6203 | const SvxBrushItem* pItem; | |||
6204 | // temporary background brush for a fly frame without a background brush | |||
6205 | std::unique_ptr<SvxBrushItem> pTmpBackBrush; | |||
6206 | const Color* pCol; | |||
6207 | SwRect aOrigBackRect; | |||
6208 | const bool bPageFrame = IsPageFrame(); | |||
6209 | bool bLowMode = true; | |||
6210 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes; | |||
6211 | ||||
6212 | bool bBack = GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, bLowerMode, /*bConsiderTextBox=*/false ); | |||
6213 | //- Output if a separate background is used. | |||
6214 | bool bNoFlyBackground = !gProp.bSFlyMetafile && !bBack && IsFlyFrame(); | |||
6215 | if ( bNoFlyBackground ) | |||
6216 | { | |||
6217 | // Fly frame has no background. | |||
6218 | // Try to find background brush at parents, if previous call of | |||
6219 | // <GetBackgroundBrush> disabled this option with the parameter <bLowerMode> | |||
6220 | if ( bLowerMode ) | |||
6221 | { | |||
6222 | bBack = GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false, /*bConsiderTextBox=*/false ); | |||
6223 | } | |||
6224 | // If still no background found for the fly frame, initialize the | |||
6225 | // background brush <pItem> with global retouche color and set <bBack> | |||
6226 | // to true, that fly frame will paint its background using this color. | |||
6227 | if ( !bBack ) | |||
6228 | { | |||
6229 | // #i6467# - on print output, pdf output and in embedded mode not editing color COL_WHITE is used | |||
6230 | // instead of the global retouche color. | |||
6231 | if ( pSh->GetOut()->GetOutDevType() == OUTDEV_PRINTER || | |||
6232 | pSh->GetViewOptions()->IsPDFExport() || | |||
6233 | ( pSh->GetDoc()->GetDocShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED && | |||
6234 | !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() | |||
6235 | ) | |||
6236 | ) | |||
6237 | { | |||
6238 | pTmpBackBrush.reset(new SvxBrushItem( COL_WHITE, RES_BACKGROUND )); | |||
6239 | ||||
6240 | //UUU | |||
6241 | aFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(COL_WHITE); | |||
6242 | } | |||
6243 | else | |||
6244 | { | |||
6245 | pTmpBackBrush.reset(new SvxBrushItem( aGlobalRetoucheColor, RES_BACKGROUND)); | |||
6246 | ||||
6247 | //UUU | |||
6248 | aFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(aGlobalRetoucheColor); | |||
6249 | } | |||
6250 | ||||
6251 | pItem = pTmpBackBrush.get(); | |||
6252 | bBack = true; | |||
6253 | } | |||
6254 | } | |||
6255 | ||||
6256 | SwRect aPaintRect( getFrameArea() ); | |||
6257 | if( IsTextFrame() || IsSctFrame() ) | |||
6258 | aPaintRect = UnionFrame( true ); | |||
6259 | ||||
6260 | // bOnlyTextBackground means background that's on top of background shapes, | |||
6261 | // this includes both text and cell frames. | |||
6262 | if ( (!bOnlyTextBackground || IsTextFrame() || IsCellFrame()) && aPaintRect.IsOver( rRect ) ) | |||
6263 | { | |||
6264 | if ( bBack || bPageFrame || !bLowerMode ) | |||
6265 | { | |||
6266 | const bool bBrowse = pSh->GetViewOptions()->getBrowseMode(); | |||
6267 | SwRect aRect; | |||
6268 | if ( (bPageFrame && bBrowse) || | |||
6269 | (IsTextFrame() && getFramePrintArea().SSize() == getFrameArea().SSize()) ) | |||
6270 | { | |||
6271 | aRect = getFrameArea(); | |||
6272 | ::SwAlignRect( aRect, gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut() ); | |||
6273 | } | |||
6274 | else | |||
6275 | { | |||
6276 | if ( bPageFrame ) | |||
6277 | { | |||
6278 | aRect = getFrameArea(); | |||
6279 | } | |||
6280 | else | |||
6281 | { | |||
6282 | ::lcl_CalcBorderRect( aRect, this, rAttrs, false, gProp); | |||
6283 | } | |||
6284 | ||||
6285 | if ( (IsTextFrame() || IsTabFrame()) && GetPrev() ) | |||
6286 | { | |||
6287 | if ( GetPrev()->GetAttrSet()->GetBackground() == GetAttrSet()->GetBackground() && | |||
6288 | lcl_compareFillAttributes(GetPrev()->getSdrAllFillAttributesHelper(), getSdrAllFillAttributesHelper())) | |||
6289 | { | |||
6290 | aRect.Top( getFrameArea().Top() ); | |||
6291 | } | |||
6292 | } | |||
6293 | } | |||
6294 | aRect.Intersection( rRect ); | |||
6295 | ||||
6296 | OutputDevice *pOut = pSh->GetOut(); | |||
6297 | ||||
6298 | if ( aRect.HasArea() ) | |||
6299 | { | |||
6300 | std::unique_ptr<SvxBrushItem> pNewItem; | |||
6301 | ||||
6302 | if( pCol ) | |||
6303 | { | |||
6304 | pNewItem.reset(new SvxBrushItem( *pCol, RES_BACKGROUND )); | |||
6305 | pItem = pNewItem.get(); | |||
6306 | aFillAttributes = std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>(*pCol); | |||
6307 | } | |||
6308 | ||||
6309 | SwRegionRects aRegion( aRect ); | |||
6310 | basegfx::B2DPolygon aB2DPolygon{tools::Polygon(aRect.SVRect()).getB2DPolygon()}; | |||
6311 | basegfx::utils::B2DClipState aClipState{basegfx::B2DPolyPolygon(aB2DPolygon)}; | |||
6312 | if (pPage->GetSortedObjs() && | |||
6313 | pSh->GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS)) | |||
6314 | { | |||
6315 | ::lcl_SubtractFlys( this, pPage, aRect, aRegion, aClipState, gProp ); | |||
6316 | } | |||
6317 | ||||
6318 | // Determine, if background transparency | |||
6319 | // have to be considered for drawing. | |||
6320 | // Status Quo: background transparency have to be | |||
6321 | // considered for fly frames | |||
6322 | const bool bConsiderBackgroundTransparency = IsFlyFrame(); | |||
6323 | bool bDone(false); | |||
6324 | ||||
6325 | // #i125189# We are also done when the new DrawingLayer FillAttributes are used | |||
6326 | // or the FillStyle is set (different from drawing::FillStyle_NONE) | |||
6327 | if(pOut && aFillAttributes) | |||
6328 | { | |||
6329 | if(aFillAttributes->isUsed()) | |||
6330 | { | |||
6331 | // check if really something is painted | |||
6332 | bDone = DrawFillAttributes(aFillAttributes, aOrigBackRect, aRegion, aClipState, *pOut); | |||
6333 | } | |||
6334 | ||||
6335 | if(!bDone) | |||
6336 | { | |||
6337 | // if not, still a FillStyle could be set but the transparency is at 100%, | |||
6338 | // thus need to check the model data itself for FillStyle (do not rely on | |||
6339 | // SdrAllFillAttributesHelper since it already contains optimized information, | |||
6340 | // e.g. transparency leads to no fill) | |||
6341 | const drawing::FillStyle eFillStyle(GetAttrSet()->Get(XATTR_FILLSTYLE).GetValue()); | |||
6342 | ||||
6343 | if(drawing::FillStyle_NONE != eFillStyle) | |||
6344 | { | |||
6345 | bDone = true; | |||
6346 | } | |||
6347 | } | |||
6348 | } | |||
6349 | ||||
6350 | if(!bDone) | |||
6351 | { | |||
6352 | for (size_t i = 0; i < aRegion.size(); ++i) | |||
6353 | { | |||
6354 | if (1 < aRegion.size()) | |||
6355 | { | |||
6356 | ::SwAlignRect( aRegion[i], gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut() ); | |||
6357 | if( !aRegion[i].HasArea() ) | |||
6358 | continue; | |||
6359 | } | |||
6360 | // add 6th parameter to indicate, if background transparency have to be considered | |||
6361 | // Set missing 5th parameter to the default value GRFNUM_NO | |||
6362 | // - see declaration in /core/inc/frmtool.hxx. | |||
6363 | ::DrawGraphic( | |||
6364 | pItem, | |||
6365 | pOut, | |||
6366 | aOrigBackRect, | |||
6367 | aRegion[i], | |||
6368 | GRFNUM_NO0, | |||
6369 | bConsiderBackgroundTransparency ); | |||
6370 | } | |||
6371 | } | |||
6372 | } | |||
6373 | } | |||
6374 | else | |||
6375 | bLowMode = bLowerMode; | |||
6376 | } | |||
6377 | ||||
6378 | // delete temporary background brush. | |||
6379 | pTmpBackBrush.reset(); | |||
6380 | ||||
6381 | //Now process lower and his neighbour. | |||
6382 | //We end this as soon as a Frame leaves the chain and therefore is not a lower | |||
6383 | //of me anymore | |||
6384 | const SwFrame *pFrame = GetLower(); | |||
6385 | if ( !pFrame ) | |||
6386 | return; | |||
6387 | ||||
6388 | SwRect aFrameRect; | |||
6389 | SwRect aRect( GetPaintArea() ); | |||
6390 | aRect.Intersection_( rRect ); | |||
6391 | SwRect aBorderRect( aRect ); | |||
6392 | SwShortCut aShortCut( *pFrame, aBorderRect ); | |||
6393 | do | |||
6394 | { if ( gProp.pSProgress ) | |||
6395 | SfxProgress::Reschedule(); | |||
6396 | ||||
6397 | aFrameRect = pFrame->GetPaintArea(); | |||
6398 | if ( aFrameRect.IsOver( aBorderRect ) ) | |||
6399 | { | |||
6400 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), pFrame ); | |||
6401 | const SwBorderAttrs &rTmpAttrs = *aAccess.Get(); | |||
6402 | if ( ( pFrame->IsLayoutFrame() && bLowerBorder ) || aFrameRect.IsOver( aRect ) ) | |||
6403 | { | |||
6404 | pFrame->PaintSwFrameBackground( aRect, pPage, rTmpAttrs, bLowMode, | |||
6405 | bLowerBorder, bOnlyTextBackground ); | |||
6406 | } | |||
6407 | ||||
6408 | if ( bLowerBorder ) | |||
6409 | { | |||
6410 | pFrame->PaintSwFrameShadowAndBorder( aBorderRect, pPage, rTmpAttrs ); | |||
6411 | } | |||
6412 | } | |||
6413 | pFrame = pFrame->GetNext(); | |||
6414 | } while ( pFrame && pFrame->GetUpper() == this && | |||
6415 | !aShortCut.Stop( aFrameRect ) ); | |||
6416 | } | |||
6417 | ||||
6418 | /// Refreshes all subsidiary lines of a page. | |||
6419 | void SwPageFrame::RefreshSubsidiary( const SwRect &rRect ) const | |||
6420 | { | |||
6421 | if ( !(isSubsidiaryLinesEnabled() || isTableBoundariesEnabled() | |||
6422 | || isSubsidiaryLinesForSectionsEnabled() || isSubsidiaryLinesFlysEnabled()) ) | |||
6423 | return; | |||
6424 | ||||
6425 | if ( !rRect.HasArea() ) | |||
6426 | return; | |||
6427 | ||||
6428 | //During paint using the root, the array is controlled from there. | |||
6429 | //Otherwise we'll handle it for our self. | |||
6430 | bool bDelSubs = false; | |||
6431 | if ( !gProp.pSSubsLines ) | |||
6432 | { | |||
6433 | gProp.pSSubsLines.reset(new SwSubsRects); | |||
6434 | // create container for special subsidiary lines | |||
6435 | gProp.pSSpecSubsLines.reset(new SwSubsRects); | |||
6436 | bDelSubs = true; | |||
6437 | } | |||
6438 | ||||
6439 | RefreshLaySubsidiary( this, rRect ); | |||
6440 | ||||
6441 | if ( bDelSubs ) | |||
6442 | { | |||
6443 | // paint special subsidiary lines and delete its container | |||
6444 | gProp.pSSpecSubsLines->PaintSubsidiary( gProp.pSGlobalShell->GetOut(), nullptr, gProp ); | |||
6445 | gProp.pSSpecSubsLines.reset(); | |||
6446 | ||||
6447 | gProp.pSSubsLines->PaintSubsidiary(gProp.pSGlobalShell->GetOut(), gProp.pSLines.get(), gProp); | |||
6448 | gProp.pSSubsLines.reset(); | |||
6449 | } | |||
6450 | } | |||
6451 | ||||
6452 | void SwLayoutFrame::RefreshLaySubsidiary( const SwPageFrame *pPage, | |||
6453 | const SwRect &rRect ) const | |||
6454 | { | |||
6455 | const bool bSubsOpt = isSubsidiaryLinesEnabled(); | |||
6456 | if ( bSubsOpt ) | |||
6457 | PaintSubsidiaryLines( pPage, rRect ); | |||
6458 | ||||
6459 | const SwFrame *pLow = Lower(); | |||
6460 | if( !pLow ) | |||
6461 | return; | |||
6462 | SwShortCut aShortCut( *pLow, rRect ); | |||
6463 | while( pLow && !aShortCut.Stop( pLow->getFrameArea() ) ) | |||
6464 | { | |||
6465 | if ( pLow->getFrameArea().IsOver( rRect ) && pLow->getFrameArea().HasArea() ) | |||
6466 | { | |||
6467 | if ( pLow->IsLayoutFrame() ) | |||
6468 | static_cast<const SwLayoutFrame*>(pLow)->RefreshLaySubsidiary( pPage, rRect); | |||
6469 | else if ( pLow->GetDrawObjs() ) | |||
6470 | { | |||
6471 | const SwSortedObjs& rObjs = *(pLow->GetDrawObjs()); | |||
6472 | for (SwAnchoredObject* pAnchoredObj : rObjs) | |||
6473 | { | |||
6474 | if ( pPage->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( | |||
6475 | pAnchoredObj->GetDrawObj()->GetLayer() ) && | |||
6476 | dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr ) | |||
6477 | { | |||
6478 | const SwFlyFrame *pFly = | |||
6479 | static_cast<const SwFlyFrame*>(pAnchoredObj); | |||
6480 | if ( pFly->IsFlyInContentFrame() && pFly->getFrameArea().IsOver( rRect ) ) | |||
6481 | { | |||
6482 | if ( !pFly->Lower() || !pFly->Lower()->IsNoTextFrame() || | |||
6483 | !static_cast<const SwNoTextFrame*>(pFly->Lower())->HasAnimation()) | |||
6484 | pFly->RefreshLaySubsidiary( pPage, rRect ); | |||
6485 | } | |||
6486 | } | |||
6487 | } | |||
6488 | } | |||
6489 | } | |||
6490 | pLow = pLow->GetNext(); | |||
6491 | } | |||
6492 | } | |||
6493 | ||||
6494 | /** | |||
6495 | * Subsidiary lines to paint the PrtAreas | |||
6496 | * Only the LayoutFrames which directly contain Content | |||
6497 | * Paints the desired line and pays attention to not overpaint any flys | |||
6498 | */ | |||
6499 | static void lcl_RefreshLine( const SwLayoutFrame *pLay, | |||
6500 | const SwPageFrame *pPage, | |||
6501 | const Point &rP1, | |||
6502 | const Point &rP2, | |||
6503 | const SubColFlags nSubColor, | |||
6504 | SwLineRects* pSubsLines ) | |||
6505 | { | |||
6506 | //In which direction do we loop? Can only be horizontal or vertical. | |||
6507 | OSL_ENSURE( ((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y())),do { if (true && (!(((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y()))))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "6508" ": "), "%s", "Sloped subsidiary lines are not allowed." ); } } while (false) | |||
6508 | "Sloped subsidiary lines are not allowed." )do { if (true && (!(((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y()))))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "6508" ": "), "%s", "Sloped subsidiary lines are not allowed." ); } } while (false); | |||
6509 | ||||
6510 | const bool bHori = rP1.Y() == rP2.Y(); | |||
6511 | ||||
6512 | // use pointers to member function in order to unify flow | |||
6513 | typedef long (Point::*pmfPtGet)() const; | |||
6514 | typedef void (Point::*pmfPtSet)(long); | |||
6515 | const pmfPtGet pDirPtX = &Point::X; | |||
6516 | const pmfPtGet pDirPtY = &Point::Y; | |||
6517 | const pmfPtGet pDirPt = bHori ? pDirPtX : pDirPtY; | |||
6518 | const pmfPtSet pDirPtSetX = &Point::setX; | |||
6519 | const pmfPtSet pDirPtSetY = &Point::setY; | |||
6520 | const pmfPtSet pDirPtSet = bHori ? pDirPtSetX : pDirPtSetY; | |||
6521 | ||||
6522 | Point aP1( rP1 ); | |||
6523 | Point aP2( rP2 ); | |||
6524 | ||||
6525 | while ( (aP1.*pDirPt)() < (aP2.*pDirPt)() ) | |||
6526 | { | |||
6527 | //If the starting point lies in a fly, it is directly set behind the | |||
6528 | //fly. | |||
6529 | //The end point moves to the start if the end point lies in a fly or we | |||
6530 | //have a fly between starting point and end point. | |||
6531 | // In this way, every position is output one by one. | |||
6532 | ||||
6533 | //If I'm a fly I'll only avoid those flys which are places 'above' me; | |||
6534 | //this means those who are behind me in the array. | |||
6535 | //Even if I'm inside a fly or inside a fly inside a fly a.s.o I won't | |||
6536 | //avoid any of those flys. | |||
6537 | SwOrderIter aIter( pPage ); | |||
6538 | const SwFlyFrame *pMyFly = pLay->FindFlyFrame(); | |||
6539 | if ( pMyFly ) | |||
6540 | { | |||
6541 | aIter.Current( pMyFly->GetVirtDrawObj() ); | |||
6542 | while ( nullptr != (pMyFly = pMyFly->GetAnchorFrame()->FindFlyFrame()) ) | |||
6543 | { | |||
6544 | if ( aIter()->GetOrdNum() > pMyFly->GetVirtDrawObj()->GetOrdNum() ) | |||
6545 | aIter.Current( pMyFly->GetVirtDrawObj() ); | |||
6546 | } | |||
6547 | } | |||
6548 | else | |||
6549 | aIter.Bottom(); | |||
6550 | ||||
6551 | while ( aIter() ) | |||
6552 | { | |||
6553 | const SwVirtFlyDrawObj *pObj = static_cast<const SwVirtFlyDrawObj*>(aIter()); | |||
6554 | const SwFlyFrame *pFly = pObj ? pObj->GetFlyFrame() : nullptr; | |||
6555 | ||||
6556 | //I certainly won't avoid myself, even if I'm placed _inside_ the | |||
6557 | //fly I won't avoid it. | |||
6558 | if ( !pFly || (pFly == pLay || pFly->IsAnLower( pLay )) ) | |||
6559 | { | |||
6560 | aIter.Next(); | |||
6561 | continue; | |||
6562 | } | |||
6563 | ||||
6564 | // do *not* consider fly frames with a transparent background. | |||
6565 | // do *not* consider fly frame, which belongs to an invisible layer | |||
6566 | if ( pFly->IsBackgroundTransparent() || | |||
6567 | !pFly->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( pObj->GetLayer() ) ) | |||
6568 | { | |||
6569 | aIter.Next(); | |||
6570 | continue; | |||
6571 | } | |||
6572 | ||||
6573 | //Is the Obj placed on the line | |||
6574 | const long nP1OthPt = !bHori ? rP1.X() : rP1.Y(); | |||
6575 | const tools::Rectangle &rBound = pObj->GetCurrentBoundRect(); | |||
6576 | const Point aDrPt( rBound.TopLeft() ); | |||
6577 | const long nDrOthPt = !bHori ? aDrPt.X() : aDrPt.Y(); | |||
6578 | const Size aDrSz( rBound.GetSize() ); | |||
6579 | const long nDrOthSz = !bHori ? aDrSz.Width() : aDrSz.Height(); | |||
6580 | ||||
6581 | if ( nP1OthPt >= nDrOthPt && nP1OthPt <= nDrOthPt + nDrOthSz ) | |||
6582 | { | |||
6583 | const long nDrDirPt = bHori ? aDrPt.X() : aDrPt.Y(); | |||
6584 | const long nDrDirSz = bHori ? aDrSz.Width() : aDrSz.Height(); | |||
6585 | ||||
6586 | if ( (aP1.*pDirPt)() >= nDrDirPt && (aP1.*pDirPt)() <= nDrDirPt + nDrDirSz ) | |||
6587 | (aP1.*pDirPtSet)( nDrDirPt + nDrDirSz ); | |||
6588 | ||||
6589 | if ( (aP2.*pDirPt)() >= nDrDirPt && (aP1.*pDirPt)() < (nDrDirPt - 1) ) | |||
6590 | (aP2.*pDirPtSet)( nDrDirPt - 1 ); | |||
6591 | } | |||
6592 | aIter.Next(); | |||
6593 | } | |||
6594 | ||||
6595 | if ( (aP1.*pDirPt)() < (aP2.*pDirPt)() ) | |||
6596 | { | |||
6597 | SwRect aRect( aP1, aP2 ); | |||
6598 | // use parameter <pSubsLines> instead of global variable <gProp.pSSubsLines>. | |||
6599 | pSubsLines->AddLineRect( aRect, nullptr, SvxBorderLineStyle::SOLID, | |||
6600 | nullptr, nSubColor, gProp ); | |||
6601 | } | |||
6602 | aP1 = aP2; | |||
6603 | (aP1.*pDirPtSet)( (aP1.*pDirPt)() + 1 ); | |||
6604 | aP2 = rP2; | |||
6605 | } | |||
6606 | } | |||
6607 | ||||
6608 | static drawinglayer::primitive2d::Primitive2DContainer lcl_CreatePageAreaDelimiterPrimitives( | |||
6609 | const SwRect& rRect ) | |||
6610 | { | |||
6611 | drawinglayer::primitive2d::Primitive2DContainer aSeq( 4 ); | |||
6612 | ||||
6613 | basegfx::BColor aLineColor = SwViewOption::GetDocBoundariesColor().getBColor(); | |||
6614 | double nLineLength = 200.0; // in Twips | |||
6615 | ||||
6616 | Point aPoints[] = { rRect.TopLeft(), rRect.TopRight(), rRect.BottomRight(), rRect.BottomLeft() }; | |||
6617 | double const aXOffDirs[] = { -1.0, 1.0, 1.0, -1.0 }; | |||
6618 | double const aYOffDirs[] = { -1.0, -1.0, 1.0, 1.0 }; | |||
6619 | ||||
6620 | // Actually loop over the corners to create the two lines | |||
6621 | for ( int i = 0; i < 4; i++ ) | |||
6622 | { | |||
6623 | basegfx::B2DVector aHorizVector( aXOffDirs[i], 0.0 ); | |||
6624 | basegfx::B2DVector aVertVector( 0.0, aYOffDirs[i] ); | |||
6625 | ||||
6626 | basegfx::B2DPoint aBPoint( aPoints[i].getX(), aPoints[i].getY() ); | |||
6627 | ||||
6628 | basegfx::B2DPolygon aPolygon; | |||
6629 | aPolygon.append( aBPoint + aHorizVector * nLineLength ); | |||
6630 | aPolygon.append( aBPoint ); | |||
6631 | aPolygon.append( aBPoint + aVertVector * nLineLength ); | |||
6632 | ||||
6633 | drawinglayer::primitive2d::PolygonHairlinePrimitive2D* pLine = | |||
6634 | new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( | |||
6635 | aPolygon, aLineColor ); | |||
6636 | aSeq[i] = drawinglayer::primitive2d::Primitive2DReference( pLine ); | |||
6637 | } | |||
6638 | ||||
6639 | return aSeq; | |||
6640 | } | |||
6641 | ||||
6642 | static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateRectangleDelimiterPrimitives ( | |||
6643 | const SwRect& rRect ) | |||
6644 | { | |||
6645 | drawinglayer::primitive2d::Primitive2DContainer aSeq( 1 ); | |||
6646 | basegfx::BColor aLineColor = SwViewOption::GetDocBoundariesColor().getBColor(); | |||
6647 | ||||
6648 | basegfx::B2DPolygon aPolygon; | |||
6649 | aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Top() ) ); | |||
6650 | aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Top() ) ); | |||
6651 | aPolygon.append( basegfx::B2DPoint( rRect.Right(), rRect.Bottom() ) ); | |||
6652 | aPolygon.append( basegfx::B2DPoint( rRect.Left(), rRect.Bottom() ) ); | |||
6653 | aPolygon.setClosed( true ); | |||
6654 | ||||
6655 | drawinglayer::primitive2d::PolygonHairlinePrimitive2D* pLine = | |||
6656 | new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( | |||
6657 | aPolygon, aLineColor ); | |||
6658 | aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( pLine ); | |||
6659 | ||||
6660 | return aSeq; | |||
6661 | } | |||
6662 | ||||
6663 | static drawinglayer::primitive2d::Primitive2DContainer lcl_CreateColumnAreaDelimiterPrimitives( | |||
6664 | const SwRect& rRect ) | |||
6665 | { | |||
6666 | drawinglayer::primitive2d::Primitive2DContainer aSeq( 4 ); | |||
6667 | ||||
6668 | basegfx::BColor aLineColor = SwViewOption::GetDocBoundariesColor().getBColor(); | |||
6669 | double nLineLength = 100.0; // in Twips | |||
6670 | ||||
6671 | Point aPoints[] = { rRect.TopLeft(), rRect.TopRight(), rRect.BottomRight(), rRect.BottomLeft() }; | |||
6672 | double const aXOffDirs[] = { 1.0, -1.0, -1.0, 1.0 }; | |||
6673 | double const aYOffDirs[] = { 1.0, 1.0, -1.0, -1.0 }; | |||
6674 | ||||
6675 | // Actually loop over the corners to create the two lines | |||
6676 | for ( int i = 0; i < 4; i++ ) | |||
6677 | { | |||
6678 | basegfx::B2DVector aHorizVector( aXOffDirs[i], 0.0 ); | |||
6679 | basegfx::B2DVector aVertVector( 0.0, aYOffDirs[i] ); | |||
6680 | ||||
6681 | basegfx::B2DPoint aBPoint( aPoints[i].getX(), aPoints[i].getY() ); | |||
6682 | ||||
6683 | basegfx::B2DPolygon aPolygon; | |||
6684 | aPolygon.append( aBPoint + aHorizVector * nLineLength ); | |||
6685 | aPolygon.append( aBPoint ); | |||
6686 | aPolygon.append( aBPoint + aVertVector * nLineLength ); | |||
6687 | ||||
6688 | drawinglayer::primitive2d::PolygonHairlinePrimitive2D* pLine = | |||
6689 | new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( | |||
6690 | aPolygon, aLineColor ); | |||
6691 | aSeq[i] = drawinglayer::primitive2d::Primitive2DReference( pLine ); | |||
6692 | } | |||
6693 | ||||
6694 | return aSeq; | |||
6695 | } | |||
6696 | ||||
6697 | void SwPageFrame::PaintSubsidiaryLines( const SwPageFrame *, | |||
6698 | const SwRect & ) const | |||
6699 | { | |||
6700 | if ( gProp.pSGlobalShell->IsHeaderFooterEdit() ) | |||
| ||||
6701 | return; | |||
6702 | ||||
6703 | const SwFrame* pLay = Lower(); | |||
6704 | const SwFrame* pFootnoteCont = nullptr; | |||
6705 | const SwFrame* pPageBody = nullptr; | |||
6706 | while ( pLay && !( pFootnoteCont && pPageBody ) ) | |||
6707 | { | |||
6708 | if ( pLay->IsFootnoteContFrame( ) ) | |||
6709 | pFootnoteCont = pLay; | |||
6710 | if ( pLay->IsBodyFrame() ) | |||
6711 | pPageBody = pLay; | |||
6712 | pLay = pLay->GetNext(); | |||
6713 | } | |||
6714 | ||||
6715 | SwRect aArea( pPageBody->getFrameArea() ); | |||
| ||||
6716 | if ( pFootnoteCont ) | |||
6717 | aArea.AddBottom( pFootnoteCont->getFrameArea().Bottom() - aArea.Bottom() ); | |||
6718 | ||||
6719 | if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) ) | |||
6720 | ProcessPrimitives( lcl_CreatePageAreaDelimiterPrimitives( aArea ) ); | |||
6721 | else | |||
6722 | ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) ); | |||
6723 | } | |||
6724 | ||||
6725 | void SwColumnFrame::PaintSubsidiaryLines( const SwPageFrame *, | |||
6726 | const SwRect & ) const | |||
6727 | { | |||
6728 | const SwFrame* pLay = Lower(); | |||
6729 | const SwFrame* pFootnoteCont = nullptr; | |||
6730 | const SwFrame* pColBody = nullptr; | |||
6731 | while ( pLay && !( pFootnoteCont && pColBody ) ) | |||
6732 | { | |||
6733 | if ( pLay->IsFootnoteContFrame( ) ) | |||
6734 | pFootnoteCont = pLay; | |||
6735 | if ( pLay->IsBodyFrame() ) | |||
6736 | pColBody = pLay; | |||
6737 | pLay = pLay->GetNext(); | |||
6738 | } | |||
6739 | ||||
6740 | SwRect aArea( pColBody->getFrameArea() ); | |||
6741 | ||||
6742 | // #i3662# - enlarge top of column body frame's printing area | |||
6743 | // in sections to top of section frame. | |||
6744 | const bool bColInSection = GetUpper()->IsSctFrame(); | |||
6745 | if ( bColInSection ) | |||
6746 | { | |||
6747 | if ( IsVertical() ) | |||
6748 | aArea.Right( GetUpper()->getFrameArea().Right() ); | |||
6749 | else | |||
6750 | aArea.Top( GetUpper()->getFrameArea().Top() ); | |||
6751 | } | |||
6752 | ||||
6753 | if ( pFootnoteCont ) | |||
6754 | aArea.AddBottom( pFootnoteCont->getFrameArea().Bottom() - aArea.Bottom() ); | |||
6755 | ||||
6756 | ::SwAlignRect( aArea, gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut() ); | |||
6757 | ||||
6758 | if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) ) | |||
6759 | ProcessPrimitives( lcl_CreateColumnAreaDelimiterPrimitives( aArea ) ); | |||
6760 | else | |||
6761 | ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) ); | |||
6762 | } | |||
6763 | ||||
6764 | void SwSectionFrame::PaintSubsidiaryLines( const SwPageFrame * pPage, | |||
6765 | const SwRect & rRect ) const | |||
6766 | { | |||
6767 | const bool bNoLowerColumn = !Lower() || !Lower()->IsColumnFrame(); | |||
6768 | if ( bNoLowerColumn ) | |||
6769 | { | |||
6770 | SwLayoutFrame::PaintSubsidiaryLines( pPage, rRect ); | |||
6771 | } | |||
6772 | } | |||
6773 | ||||
6774 | /** | |||
6775 | * The SwBodyFrame doesn't print any subsidiary line: it's bounds are painted | |||
6776 | * either by the parent page or the parent column frame. | |||
6777 | */ | |||
6778 | void SwBodyFrame::PaintSubsidiaryLines( const SwPageFrame *, | |||
6779 | const SwRect & ) const | |||
6780 | { | |||
6781 | } | |||
6782 | ||||
6783 | void SwHeadFootFrame::PaintSubsidiaryLines( const SwPageFrame *, const SwRect & ) const | |||
6784 | { | |||
6785 | if ( gProp.pSGlobalShell->IsHeaderFooterEdit() ) | |||
6786 | { | |||
6787 | SwRect aArea( getFramePrintArea() ); | |||
6788 | aArea.Pos() += getFrameArea().Pos(); | |||
6789 | if ( !gProp.pSGlobalShell->GetViewOptions()->IsViewMetaChars( ) ) | |||
6790 | ProcessPrimitives( lcl_CreatePageAreaDelimiterPrimitives( aArea ) ); | |||
6791 | else | |||
6792 | ProcessPrimitives( lcl_CreateRectangleDelimiterPrimitives( aArea ) ); | |||
6793 | } | |||
6794 | } | |||
6795 | ||||
6796 | /** | |||
6797 | * This method is overridden in order to have no subsidiary lines | |||
6798 | * around the footnotes. | |||
6799 | */ | |||
6800 | void SwFootnoteFrame::PaintSubsidiaryLines( const SwPageFrame *, | |||
6801 | const SwRect & ) const | |||
6802 | { | |||
6803 | } | |||
6804 | ||||
6805 | /** | |||
6806 | * This method is overridden in order to have no subsidiary lines | |||
6807 | * around the footnotes containers. | |||
6808 | */ | |||
6809 | void SwFootnoteContFrame::PaintSubsidiaryLines( const SwPageFrame *, | |||
6810 | const SwRect & ) const | |||
6811 | { | |||
6812 | } | |||
6813 | ||||
6814 | void SwLayoutFrame::PaintSubsidiaryLines( const SwPageFrame *pPage, | |||
6815 | const SwRect &rRect ) const | |||
6816 | { | |||
6817 | bool bNewTableModel = false; | |||
6818 | ||||
6819 | // #i29550# | |||
6820 | if ( IsTabFrame() || IsCellFrame() || IsRowFrame() ) | |||
6821 | { | |||
6822 | const SwTabFrame* pTabFrame = FindTabFrame(); | |||
6823 | if ( pTabFrame->IsCollapsingBorders() ) | |||
6824 | return; | |||
6825 | ||||
6826 | bNewTableModel = pTabFrame->GetTable()->IsNewModel(); | |||
6827 | // in the new table model, we have an early return for all cell-related | |||
6828 | // frames, except from non-covered table cells | |||
6829 | if ( bNewTableModel ) | |||
6830 | if ( IsTabFrame() || | |||
6831 | IsRowFrame() || | |||
6832 | ( IsCellFrame() && IsCoveredCell() ) ) | |||
6833 | return; | |||
6834 | } | |||
6835 | ||||
6836 | const bool bFlys = pPage->GetSortedObjs() != nullptr; | |||
6837 | ||||
6838 | const bool bCell = IsCellFrame(); | |||
6839 | // #i3662# - use frame area for cells for section use also frame area | |||
6840 | const bool bUseFrameArea = bCell || IsSctFrame(); | |||
6841 | SwRect aOriginal( bUseFrameArea ? getFrameArea() : getFramePrintArea() ); | |||
6842 | if ( !bUseFrameArea ) | |||
6843 | aOriginal.Pos() += getFrameArea().Pos(); | |||
6844 | ||||
6845 | ::SwAlignRect( aOriginal, gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut() ); | |||
6846 | ||||
6847 | if ( !aOriginal.IsOver( rRect ) ) | |||
6848 | return; | |||
6849 | ||||
6850 | SwRect aOut( aOriginal ); | |||
6851 | aOut.Intersection_( rRect ); | |||
6852 | ||||
6853 | const SwTwips nRight = aOut.Right(); | |||
6854 | const SwTwips nBottom= aOut.Bottom(); | |||
6855 | ||||
6856 | const Point aRT( nRight, aOut.Top() ); | |||
6857 | const Point aRB( nRight, nBottom ); | |||
6858 | const Point aLB( aOut.Left(), nBottom ); | |||
6859 | ||||
6860 | SubColFlags nSubColor = ( bCell || IsRowFrame() ) | |||
6861 | ? SubColFlags::Tab | |||
6862 | : ( IsInSct() | |||
6863 | ? SubColFlags::Sect | |||
6864 | : ( IsInFly() ? SubColFlags::Fly : SubColFlags::Page ) ); | |||
6865 | ||||
6866 | // collect body, header, footer, footnote and section | |||
6867 | // sub-lines in <pSpecSubsLine> array. | |||
6868 | const bool bSpecialSublines = IsBodyFrame() || IsHeaderFrame() || IsFooterFrame() || | |||
6869 | IsFootnoteFrame() || IsSctFrame(); | |||
6870 | SwLineRects *const pUsedSubsLines = bSpecialSublines | |||
6871 | ? gProp.pSSpecSubsLines.get() : gProp.pSSubsLines.get(); | |||
6872 | ||||
6873 | // NOTE: for cell frames only left and right (horizontal layout) respectively | |||
6874 | // top and bottom (vertical layout) lines painted. | |||
6875 | // NOTE2: this does not hold for the new table model!!! We paint the top border | |||
6876 | // of each non-covered table cell. | |||
6877 | const bool bVert = IsVertical(); | |||
6878 | if ( bFlys ) | |||
6879 | { | |||
6880 | // add control for drawing left and right lines | |||
6881 | if ( !bCell || bNewTableModel || !bVert ) | |||
6882 | { | |||
6883 | if ( aOriginal.Left() == aOut.Left() ) | |||
6884 | ::lcl_RefreshLine( this, pPage, aOut.Pos(), aLB, nSubColor, pUsedSubsLines ); | |||
6885 | // in vertical layout set page/column break at right | |||
6886 | if ( aOriginal.Right() == nRight ) | |||
6887 | ::lcl_RefreshLine( this, pPage, aRT, aRB, nSubColor, pUsedSubsLines ); | |||
6888 | } | |||
6889 | // adjust control for drawing top and bottom lines | |||
6890 | if ( !bCell || bNewTableModel || bVert ) | |||
6891 | { | |||
6892 | if ( aOriginal.Top() == aOut.Top() ) | |||
6893 | // in horizontal layout set page/column break at top | |||
6894 | ::lcl_RefreshLine( this, pPage, aOut.Pos(), aRT, nSubColor, pUsedSubsLines ); | |||
6895 | if ( aOriginal.Bottom() == nBottom ) | |||
6896 | ::lcl_RefreshLine( this, pPage, aLB, aRB, nSubColor, | |||
6897 | pUsedSubsLines ); | |||
6898 | } | |||
6899 | } | |||
6900 | else | |||
6901 | { | |||
6902 | // add control for drawing left and right lines | |||
6903 | if ( !bCell || bNewTableModel || !bVert ) | |||
6904 | { | |||
6905 | if ( aOriginal.Left() == aOut.Left() ) | |||
6906 | { | |||
6907 | const SwRect aRect( aOut.Pos(), aLB ); | |||
6908 | pUsedSubsLines->AddLineRect( aRect, nullptr, | |||
6909 | SvxBorderLineStyle::SOLID, nullptr, nSubColor, gProp ); | |||
6910 | } | |||
6911 | // in vertical layout set page/column break at right | |||
6912 | if ( aOriginal.Right() == nRight ) | |||
6913 | { | |||
6914 | const SwRect aRect( aRT, aRB ); | |||
6915 | pUsedSubsLines->AddLineRect( aRect, nullptr, | |||
6916 | SvxBorderLineStyle::SOLID, nullptr, nSubColor, gProp ); | |||
6917 | } | |||
6918 | } | |||
6919 | // adjust control for drawing top and bottom lines | |||
6920 | if ( !bCell || bNewTableModel || bVert ) | |||
6921 | { | |||
6922 | if ( aOriginal.Top() == aOut.Top() ) | |||
6923 | { | |||
6924 | // in horizontal layout set page/column break at top | |||
6925 | const SwRect aRect( aOut.Pos(), aRT ); | |||
6926 | pUsedSubsLines->AddLineRect( aRect, nullptr, | |||
6927 | SvxBorderLineStyle::SOLID, nullptr, nSubColor, gProp ); | |||
6928 | } | |||
6929 | if ( aOriginal.Bottom() == nBottom ) | |||
6930 | { | |||
6931 | const SwRect aRect( aLB, aRB ); | |||
6932 | pUsedSubsLines->AddLineRect( aRect, nullptr, | |||
6933 | SvxBorderLineStyle::SOLID, nullptr, nSubColor, gProp ); | |||
6934 | } | |||
6935 | } | |||
6936 | } | |||
6937 | } | |||
6938 | ||||
6939 | /** | |||
6940 | * Refreshes all extra data (line breaks a.s.o) of the page. Basically only those objects | |||
6941 | * are considered which horizontally overlap the Rect. | |||
6942 | */ | |||
6943 | void SwPageFrame::RefreshExtraData( const SwRect &rRect ) const | |||
6944 | { | |||
6945 | const SwLineNumberInfo &rInfo = GetFormat()->GetDoc()->GetLineNumberInfo(); | |||
6946 | bool bLineInFly = (rInfo.IsPaintLineNumbers() && rInfo.IsCountInFlys()) | |||
6947 | || static_cast<sal_Int16>(SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule ::Writer)))->GetRedlineMarkPos()) != text::HoriOrientation::NONE; | |||
6948 | ||||
6949 | SwRect aRect( rRect ); | |||
6950 | ::SwAlignRect( aRect, gProp.pSGlobalShell, gProp.pSGlobalShell->GetOut() ); | |||
6951 | if ( !aRect.HasArea() ) | |||
6952 | return; | |||
6953 | ||||
6954 | SwLayoutFrame::RefreshExtraData( aRect ); | |||
6955 | ||||
6956 | if ( bLineInFly && GetSortedObjs() ) | |||
6957 | for (SwAnchoredObject* pAnchoredObj : *GetSortedObjs()) | |||
6958 | { | |||
6959 | if ( auto pFly = dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) ) | |||
6960 | { | |||
6961 | if ( pFly->getFrameArea().Top() <= aRect.Bottom() && | |||
6962 | pFly->getFrameArea().Bottom() >= aRect.Top() ) | |||
6963 | pFly->RefreshExtraData( aRect ); | |||
6964 | } | |||
6965 | } | |||
6966 | } | |||
6967 | ||||
6968 | void SwLayoutFrame::RefreshExtraData( const SwRect &rRect ) const | |||
6969 | { | |||
6970 | ||||
6971 | const SwLineNumberInfo &rInfo = GetFormat()->GetDoc()->GetLineNumberInfo(); | |||
6972 | bool bLineInBody = rInfo.IsPaintLineNumbers(), | |||
6973 | bLineInFly = bLineInBody && rInfo.IsCountInFlys(), | |||
6974 | bRedLine = static_cast<sal_Int16>(SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule ::Writer)))->GetRedlineMarkPos())!=text::HoriOrientation::NONE; | |||
6975 | ||||
6976 | const SwContentFrame *pCnt = ContainsContent(); | |||
6977 | while ( pCnt && IsAnLower( pCnt ) ) | |||
6978 | { | |||
6979 | if ( pCnt->IsTextFrame() && ( bRedLine || | |||
6980 | ( !pCnt->IsInTab() && | |||
6981 | ((bLineInBody && pCnt->IsInDocBody()) || | |||
6982 | (bLineInFly && pCnt->IsInFly())) ) ) && | |||
6983 | pCnt->getFrameArea().Top() <= rRect.Bottom() && | |||
6984 | pCnt->getFrameArea().Bottom() >= rRect.Top() ) | |||
6985 | { | |||
6986 | static_cast<const SwTextFrame*>(pCnt)->PaintExtraData( rRect ); | |||
6987 | } | |||
6988 | if ( bLineInFly && pCnt->GetDrawObjs() ) | |||
6989 | for (SwAnchoredObject* pAnchoredObj : *pCnt->GetDrawObjs()) | |||
6990 | { | |||
6991 | if ( auto pFly = dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) ) | |||
6992 | { | |||
6993 | if ( pFly->IsFlyInContentFrame() && | |||
6994 | pFly->getFrameArea().Top() <= rRect.Bottom() && | |||
6995 | pFly->getFrameArea().Bottom() >= rRect.Top() ) | |||
6996 | pFly->RefreshExtraData( rRect ); | |||
6997 | } | |||
6998 | } | |||
6999 | pCnt = pCnt->GetNextContentFrame(); | |||
7000 | } | |||
7001 | } | |||
7002 | ||||
7003 | /** | |||
7004 | * For #102450# | |||
7005 | * Determine the color, that is respectively will be drawn as background | |||
7006 | * for the page frame. | |||
7007 | * Using existing method SwFrame::GetBackgroundBrush to determine the color | |||
7008 | * that is set at the page frame respectively is parent. If none is found | |||
7009 | * return the global retouche color | |||
7010 | * | |||
7011 | * @return Color | |||
7012 | */ | |||
7013 | Color SwPageFrame::GetDrawBackgrdColor() const | |||
7014 | { | |||
7015 | const SvxBrushItem* pBrushItem; | |||
7016 | const Color* pDummyColor; | |||
7017 | SwRect aDummyRect; | |||
7018 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes; | |||
7019 | ||||
7020 | if ( GetBackgroundBrush( aFillAttributes, pBrushItem, pDummyColor, aDummyRect, true, /*bConsiderTextBox=*/false) ) | |||
7021 | { | |||
7022 | if(aFillAttributes && aFillAttributes->isUsed()) | |||
7023 | { | |||
7024 | // let SdrAllFillAttributesHelper do the average color calculation | |||
7025 | return Color(aFillAttributes->getAverageColor(aGlobalRetoucheColor.getBColor())); | |||
7026 | } | |||
7027 | else if(pBrushItem) | |||
7028 | { | |||
7029 | OUString referer; | |||
7030 | SwViewShell * sh1 = getRootFrame()->GetCurrShell(); | |||
7031 | if (sh1 != nullptr) { | |||
7032 | SfxObjectShell * sh2 = sh1->GetDoc()->GetPersist(); | |||
7033 | if (sh2 != nullptr && sh2->HasName()) { | |||
7034 | referer = sh2->GetMedium()->GetName(); | |||
7035 | } | |||
7036 | } | |||
7037 | const Graphic* pGraphic = pBrushItem->GetGraphic(referer); | |||
7038 | ||||
7039 | if(pGraphic) | |||
7040 | { | |||
7041 | // #29105# when a graphic is set, it may be possible to calculate a single | |||
7042 | // color which looks good in all places of the graphic. Since it is | |||
7043 | // planned to have text edit on the overlay one day and the fallback | |||
7044 | // to aGlobalRetoucheColor returns something useful, just use that | |||
7045 | // for now. | |||
7046 | } | |||
7047 | else | |||
7048 | { | |||
7049 | // not a graphic, use (hopefully) initialized color | |||
7050 | return pBrushItem->GetColor(); | |||
7051 | } | |||
7052 | } | |||
7053 | } | |||
7054 | ||||
7055 | return aGlobalRetoucheColor; | |||
7056 | } | |||
7057 | ||||
7058 | /// create/return font used to paint the "empty page" string | |||
7059 | const vcl::Font& SwPageFrame::GetEmptyPageFont() | |||
7060 | { | |||
7061 | static vcl::Font aEmptyPgFont = [&]() | |||
7062 | { | |||
7063 | vcl::Font tmp; | |||
7064 | tmp.SetFontSize( Size( 0, 80 * 20 )); // == 80 pt | |||
7065 | tmp.SetWeight( WEIGHT_BOLD ); | |||
7066 | tmp.SetStyleName(OUString()); | |||
7067 | tmp.SetFamilyName("Helvetica"); | |||
7068 | tmp.SetFamily( FAMILY_SWISS ); | |||
7069 | tmp.SetTransparent( true ); | |||
7070 | tmp.SetColor( COL_GRAY ); | |||
7071 | return tmp; | |||
7072 | }(); | |||
7073 | ||||
7074 | return aEmptyPgFont; | |||
7075 | } | |||
7076 | ||||
7077 | /** | |||
7078 | * Retouch for a section | |||
7079 | * | |||
7080 | * Retouch will only be done, if the Frame is the last one in his chain. | |||
7081 | * The whole area of the upper which is located below the Frame will be | |||
7082 | * cleared using PaintSwFrameBackground. | |||
7083 | */ | |||
7084 | void SwFrame::Retouch( const SwPageFrame * pPage, const SwRect &rRect ) const | |||
7085 | { | |||
7086 | if ( gProp.bSFlyMetafile ) | |||
7087 | return; | |||
7088 | ||||
7089 | OSL_ENSURE( GetUpper(), "Retouche try without Upper." )do { if (true && (!(GetUpper()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "7089" ": "), "%s", "Retouche try without Upper."); } } while (false); | |||
7090 | OSL_ENSURE( getRootFrame()->GetCurrShell() && gProp.pSGlobalShell->GetWin(), "Retouche on a printer?" )do { if (true && (!(getRootFrame()->GetCurrShell() && gProp.pSGlobalShell->GetWin()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "7090" ": "), "%s", "Retouche on a printer?"); } } while (false); | |||
7091 | ||||
7092 | SwRect aRetouche( GetUpper()->GetPaintArea() ); | |||
7093 | aRetouche.Top( getFrameArea().Top() + getFrameArea().Height() ); | |||
7094 | aRetouche.Intersection( gProp.pSGlobalShell->VisArea() ); | |||
7095 | ||||
7096 | if ( aRetouche.HasArea() ) | |||
7097 | { | |||
7098 | //Omit the passed Rect. To do this, we unfortunately need a region to | |||
7099 | //cut out. | |||
7100 | SwRegionRects aRegion( aRetouche ); | |||
7101 | aRegion -= rRect; | |||
7102 | SwViewShell *pSh = getRootFrame()->GetCurrShell(); | |||
7103 | ||||
7104 | // #i16816# tagged pdf support | |||
7105 | SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, nullptr, *pSh->GetOut() ); | |||
7106 | ||||
7107 | for ( size_t i = 0; i < aRegion.size(); ++i ) | |||
7108 | { | |||
7109 | const SwRect &rRetouche = aRegion[i]; | |||
7110 | ||||
7111 | GetUpper()->PaintBaBo( rRetouche, pPage ); | |||
7112 | ||||
7113 | //Hell and Heaven need to be refreshed too. | |||
7114 | //To avoid recursion my retouch flag needs to be reset first! | |||
7115 | ResetRetouche(); | |||
7116 | if ( rRetouche.HasArea() ) | |||
7117 | { | |||
7118 | const Color aPageBackgrdColor(pPage->GetDrawBackgrdColor()); | |||
7119 | const IDocumentDrawModelAccess& rIDDMA = pSh->getIDocumentDrawModelAccess(); | |||
7120 | // --> OD #i76669# | |||
7121 | SwViewObjectContactRedirector aSwRedirector( *pSh ); | |||
7122 | // <-- | |||
7123 | ||||
7124 | pSh->Imp()->PaintLayer( rIDDMA.GetHellId(), nullptr, | |||
7125 | *pPage, rRetouche, &aPageBackgrdColor, | |||
7126 | pPage->IsRightToLeft(), | |||
7127 | &aSwRedirector ); | |||
7128 | pSh->Imp()->PaintLayer( rIDDMA.GetHeavenId(), nullptr, | |||
7129 | *pPage, rRetouche, &aPageBackgrdColor, | |||
7130 | pPage->IsRightToLeft(), | |||
7131 | &aSwRedirector ); | |||
7132 | } | |||
7133 | ||||
7134 | SetRetouche(); | |||
7135 | ||||
7136 | //Because we leave all paint areas, we need to refresh the | |||
7137 | //subsidiary lines. | |||
7138 | pPage->RefreshSubsidiary( rRetouche ); | |||
7139 | } | |||
7140 | } | |||
7141 | if ( SwViewShell::IsLstEndAction() ) | |||
7142 | ResetRetouche(); | |||
7143 | } | |||
7144 | ||||
7145 | /** | |||
7146 | * Determine the background brush for the frame: | |||
7147 | * the background brush is taken from it-self or from its parent (anchor/upper). | |||
7148 | * Normally, the background brush is taken, which has no transparent color or | |||
7149 | * which has a background graphic. But there are some special cases: | |||
7150 | * (1) No background brush is taken from a page frame, if view option "IsPageBack" | |||
7151 | * isn't set. | |||
7152 | * (2) Background brush from an index section is taken under special conditions. | |||
7153 | * In this case parameter <rpCol> is set to the index shading color. | |||
7154 | * (3) New (OD 20.08.2002) - Background brush is taken, if on background drawing | |||
7155 | * of the frame transparency is considered and its color is not "no fill"/"auto fill" | |||
7156 | * | |||
7157 | * Old description in German: | |||
7158 | * Returns the Backgroundbrush for the area of the Frame. | |||
7159 | * The Brush is defined by the Frame or by an upper, the first Brush is | |||
7160 | * used. If no Brush is defined for a Frame, false is returned. | |||
7161 | * | |||
7162 | * @param rpBrush | |||
7163 | * output parameter - constant reference pointer the found background brush | |||
7164 | * | |||
7165 | * @param rpFillStyle | |||
7166 | * output parameter - constant reference pointer the found background fill style | |||
7167 | * | |||
7168 | * @param rpFillGradient | |||
7169 | * output parameter - constant reference pointer the found background fill gradient | |||
7170 | * | |||
7171 | * @param rpCol | |||
7172 | * output parameter - constant reference pointer to the color of the index shading | |||
7173 | * set under special conditions, if background brush is taken from an index section. | |||
7174 | * | |||
7175 | * @param rOrigRect | |||
7176 | * in-/output parameter - reference to the rectangle the background brush is | |||
7177 | * considered for - adjusted to the frame, from which the background brush is | |||
7178 | * taken. | |||
7179 | * | |||
7180 | * @parem bLowerMode | |||
7181 | * input parameter - boolean indicating, if background brush should *not* be | |||
7182 | * taken from parent. | |||
7183 | * | |||
7184 | * @param bConsiderTextBox | |||
7185 | * consider the TextBox of this fly frame (if there is any) when determining | |||
7186 | * the background color, useful for automatic font color. | |||
7187 | * | |||
7188 | * @return true, if a background brush for the frame is found | |||
7189 | */ | |||
7190 | bool SwFrame::GetBackgroundBrush( | |||
7191 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes, | |||
7192 | const SvxBrushItem* & rpBrush, | |||
7193 | const Color*& rpCol, | |||
7194 | SwRect &rOrigRect, | |||
7195 | bool bLowerMode, | |||
7196 | bool bConsiderTextBox ) const | |||
7197 | { | |||
7198 | const SwFrame *pFrame = this; | |||
7199 | SwViewShell *pSh = getRootFrame()->GetCurrShell(); | |||
7200 | const SwViewOption *pOpt = pSh->GetViewOptions(); | |||
7201 | rpBrush = nullptr; | |||
7202 | rpCol = nullptr; | |||
7203 | do | |||
7204 | { | |||
7205 | if ( pFrame->IsPageFrame() && !pOpt->IsPageBack() ) | |||
7206 | return false; | |||
7207 | ||||
7208 | if (pFrame->supportsFullDrawingLayerFillAttributeSet()) | |||
7209 | { | |||
7210 | bool bHandledTextBox = false; | |||
7211 | if (pFrame->IsFlyFrame() && bConsiderTextBox) | |||
7212 | { | |||
7213 | const SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrame*>(pFrame); | |||
7214 | SwFrameFormat* pShape | |||
7215 | = SwTextBoxHelper::getOtherTextBoxFormat(pFlyFrame->GetFormat(), RES_FLYFRMFMT); | |||
7216 | if (pShape) | |||
7217 | { | |||
7218 | SdrObject* pObject = pShape->FindRealSdrObject(); | |||
7219 | if (pObject) | |||
7220 | { | |||
7221 | // Work with the fill attributes of the shape of the fly frame. | |||
7222 | rFillAttributes = | |||
7223 | std::make_shared<drawinglayer::attribute::SdrAllFillAttributesHelper>( | |||
7224 | pObject->GetMergedItemSet()); | |||
7225 | bHandledTextBox = true; | |||
7226 | } | |||
7227 | } | |||
7228 | } | |||
7229 | ||||
7230 | if (!bHandledTextBox) | |||
7231 | rFillAttributes = pFrame->getSdrAllFillAttributesHelper(); | |||
7232 | } | |||
7233 | const SvxBrushItem &rBack = pFrame->GetAttrSet()->GetBackground(); | |||
7234 | ||||
7235 | if( pFrame->IsSctFrame() ) | |||
7236 | { | |||
7237 | const SwSection* pSection = static_cast<const SwSectionFrame*>(pFrame)->GetSection(); | |||
7238 | // Note: If frame <pFrame> is a section of the index and | |||
7239 | // it its background color is "no fill"/"auto fill" and | |||
7240 | // it has no background graphic and | |||
7241 | // we are not in the page preview and | |||
7242 | // we are not in read-only mode and | |||
7243 | // option "index shadings" is set and | |||
7244 | // the output is not the printer | |||
7245 | // then set <rpCol> to the color of the index shading | |||
7246 | if( pSection && ( SectionType::ToxHeader == pSection->GetType() || | |||
7247 | SectionType::ToxContent == pSection->GetType() ) && | |||
7248 | (rBack.GetColor() == COL_TRANSPARENT) && | |||
7249 | rBack.GetGraphicPos() == GPOS_NONE && | |||
7250 | !pOpt->IsPagePreview() && | |||
7251 | !pOpt->IsReadonly() && | |||
7252 | // #114856# Form view | |||
7253 | !pOpt->IsFormView() && | |||
7254 | SwViewOption::IsIndexShadings() && | |||
7255 | !pOpt->IsPDFExport() && | |||
7256 | pSh->GetOut()->GetOutDevType() != OUTDEV_PRINTER ) | |||
7257 | { | |||
7258 | rpCol = &SwViewOption::GetIndexShadingsColor(); | |||
7259 | } | |||
7260 | } | |||
7261 | ||||
7262 | // determine, if background draw of frame <pFrame> considers transparency | |||
7263 | // Status Quo: background transparency have to be | |||
7264 | // considered for fly frames | |||
7265 | const bool bConsiderBackgroundTransparency = pFrame->IsFlyFrame(); | |||
7266 | ||||
7267 | // #i125189# Do not base the decision for using the parent's fill style for this | |||
7268 | // frame when the new DrawingLayer FillAttributes are used on the SdrAllFillAttributesHelper | |||
7269 | // information. There the data is already optimized to no fill in the case that the | |||
7270 | // transparence is at 100% while no fill is the criteria for derivation | |||
7271 | bool bNewDrawingLayerFillStyleIsUsedAndNotNoFill(false); | |||
7272 | ||||
7273 | if(rFillAttributes) | |||
7274 | { | |||
7275 | // the new DrawingLayer FillStyle is used | |||
7276 | if(rFillAttributes->isUsed()) | |||
7277 | { | |||
7278 | // it's not drawing::FillStyle_NONE | |||
7279 | bNewDrawingLayerFillStyleIsUsedAndNotNoFill = true; | |||
7280 | } | |||
7281 | else | |||
7282 | { | |||
7283 | // maybe optimized already when 100% transparency is used somewhere, need to test | |||
7284 | // XFillStyleItem directly from the model data | |||
7285 | const drawing::FillStyle eFillStyle(pFrame->GetAttrSet()->Get(XATTR_FILLSTYLE).GetValue()); | |||
7286 | ||||
7287 | if(drawing::FillStyle_NONE != eFillStyle) | |||
7288 | { | |||
7289 | bNewDrawingLayerFillStyleIsUsedAndNotNoFill = true; | |||
7290 | } | |||
7291 | } | |||
7292 | } | |||
7293 | ||||
7294 | // add condition: | |||
7295 | // If <bConsiderBackgroundTransparency> is set - see above -, | |||
7296 | // return brush of frame <pFrame>, if its color is *not* "no fill"/"auto fill" | |||
7297 | if ( | |||
7298 | // #i125189# Done when the new DrawingLayer FillAttributes are used and | |||
7299 | // not drawing::FillStyle_NONE (see above) | |||
7300 | bNewDrawingLayerFillStyleIsUsedAndNotNoFill || | |||
7301 | ||||
7302 | // done when SvxBrushItem is used | |||
7303 | !rBack.GetColor().GetTransparency() || rBack.GetGraphicPos() != GPOS_NONE || | |||
7304 | ||||
7305 | // done when direct color is forced | |||
7306 | rpCol || | |||
7307 | ||||
7308 | // done when consider BG transparency and color is not completely transparent | |||
7309 | (bConsiderBackgroundTransparency && (rBack.GetColor() != COL_TRANSPARENT)) | |||
7310 | ) | |||
7311 | { | |||
7312 | rpBrush = &rBack; | |||
7313 | if ( pFrame->IsPageFrame() && pSh->GetViewOptions()->getBrowseMode() ) | |||
7314 | { | |||
7315 | rOrigRect = pFrame->getFrameArea(); | |||
7316 | } | |||
7317 | else | |||
7318 | { | |||
7319 | if ( pFrame->getFrameArea().SSize() != pFrame->getFramePrintArea().SSize() ) | |||
7320 | { | |||
7321 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), pFrame ); | |||
7322 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
7323 | ::lcl_CalcBorderRect( rOrigRect, pFrame, rAttrs, false, gProp ); | |||
7324 | } | |||
7325 | else | |||
7326 | { | |||
7327 | rOrigRect = pFrame->getFramePrintArea(); | |||
7328 | rOrigRect += pFrame->getFrameArea().Pos(); | |||
7329 | } | |||
7330 | } | |||
7331 | ||||
7332 | return true; | |||
7333 | } | |||
7334 | ||||
7335 | if ( bLowerMode ) | |||
7336 | { | |||
7337 | // Do not try to get background brush from parent (anchor/upper) | |||
7338 | return false; | |||
7339 | } | |||
7340 | ||||
7341 | // get parent frame - anchor or upper - for next loop | |||
7342 | if ( pFrame->IsFlyFrame() ) | |||
7343 | { | |||
7344 | pFrame = static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame(); | |||
7345 | } | |||
7346 | else | |||
7347 | { | |||
7348 | pFrame = pFrame->GetUpper(); | |||
7349 | } | |||
7350 | } while ( pFrame ); | |||
7351 | ||||
7352 | return false; | |||
7353 | } | |||
7354 | ||||
7355 | void SetOutDevAndWin( SwViewShell *pSh, OutputDevice *pO, | |||
7356 | vcl::Window *pW, sal_uInt16 nZoom ) | |||
7357 | { | |||
7358 | pSh->mpOut = pO; | |||
7359 | pSh->mpWin = pW; | |||
7360 | pSh->mpOpt->SetZoom( nZoom ); | |||
7361 | } | |||
7362 | ||||
7363 | Graphic SwFrameFormat::MakeGraphic( ImageMap* ) | |||
7364 | { | |||
7365 | return Graphic(); | |||
7366 | } | |||
7367 | ||||
7368 | Graphic SwFlyFrameFormat::MakeGraphic( ImageMap* pMap ) | |||
7369 | { | |||
7370 | Graphic aRet; | |||
7371 | //search any Fly! | |||
7372 | SwIterator<SwFrame,SwFormat> aIter( *this ); | |||
7373 | SwFrame *pFirst = aIter.First(); | |||
7374 | SwViewShell *const pSh = | |||
7375 | pFirst ? pFirst->getRootFrame()->GetCurrShell() : nullptr; | |||
7376 | if (nullptr != pSh) | |||
7377 | { | |||
7378 | SwViewShell *pOldGlobal = gProp.pSGlobalShell; | |||
7379 | gProp.pSGlobalShell = pSh; | |||
7380 | ||||
7381 | bool bNoteURL = pMap && | |||
7382 | SfxItemState::SET != GetAttrSet().GetItemState( RES_URL ); | |||
7383 | if( bNoteURL ) | |||
7384 | { | |||
7385 | OSL_ENSURE( !pNoteURL, "MakeGraphic: pNoteURL already used? " )do { if (true && (!(!pNoteURL))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "7385" ": "), "%s", "MakeGraphic: pNoteURL already used? " ); } } while (false); | |||
7386 | pNoteURL = new SwNoteURL; | |||
7387 | } | |||
7388 | SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pFirst); | |||
7389 | ||||
7390 | OutputDevice *pOld = pSh->GetOut(); | |||
7391 | ScopedVclPtrInstance< VirtualDevice > pDev( *pOld ); | |||
7392 | pDev->EnableOutput( false ); | |||
7393 | ||||
7394 | GDIMetaFile aMet; | |||
7395 | MapMode aMap( pOld->GetMapMode().GetMapUnit() ); | |||
7396 | pDev->SetMapMode( aMap ); | |||
7397 | aMet.SetPrefMapMode( aMap ); | |||
7398 | ||||
7399 | ::SwCalcPixStatics( pSh->GetOut() ); | |||
7400 | aMet.SetPrefSize( pFly->getFrameArea().SSize() ); | |||
7401 | ||||
7402 | aMet.Record( pDev.get() ); | |||
7403 | pDev->SetLineColor(); | |||
7404 | pDev->SetFillColor(); | |||
7405 | pDev->SetFont( pOld->GetFont() ); | |||
7406 | ||||
7407 | //Enlarge the rectangle if needed, so the border is painted too. | |||
7408 | SwRect aOut( pFly->getFrameArea() ); | |||
7409 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), pFly ); | |||
7410 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
7411 | if ( rAttrs.CalcRightLine() ) | |||
7412 | aOut.AddWidth(2*gProp.nSPixelSzW ); | |||
7413 | if ( rAttrs.CalcBottomLine() ) | |||
7414 | aOut.AddHeight(2*gProp.nSPixelSzH ); | |||
7415 | ||||
7416 | // #i92711# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev | |||
7417 | const vcl::Region aRepaintRegion(aOut.SVRect()); | |||
7418 | pSh->DLPrePaint2(aRepaintRegion); | |||
7419 | ||||
7420 | vcl::Window *pWin = pSh->GetWin(); | |||
7421 | sal_uInt16 nZoom = pSh->GetViewOptions()->GetZoom(); | |||
7422 | ::SetOutDevAndWin( pSh, pDev, nullptr, 100 ); | |||
7423 | gProp.bSFlyMetafile = true; | |||
7424 | gProp.pSFlyMetafileOut = pWin; | |||
7425 | ||||
7426 | SwViewShellImp *pImp = pSh->Imp(); | |||
7427 | gProp.pSFlyOnlyDraw = pFly; | |||
7428 | gProp.pSLines.reset(new SwLineRects); | |||
7429 | ||||
7430 | // determine page, fly frame is on | |||
7431 | const SwPageFrame* pFlyPage = pFly->FindPageFrame(); | |||
7432 | const Color aPageBackgrdColor(pFlyPage->GetDrawBackgrdColor()); | |||
7433 | const IDocumentDrawModelAccess& rIDDMA = pSh->getIDocumentDrawModelAccess(); | |||
7434 | // --> OD #i76669# | |||
7435 | SwViewObjectContactRedirector aSwRedirector( *pSh ); | |||
7436 | // <-- | |||
7437 | pImp->PaintLayer( rIDDMA.GetHellId(), nullptr, | |||
7438 | *pFlyPage, aOut, &aPageBackgrdColor, | |||
7439 | pFlyPage->IsRightToLeft(), | |||
7440 | &aSwRedirector ); | |||
7441 | gProp.pSLines->PaintLines( pDev, gProp ); | |||
7442 | if ( pFly->IsFlyInContentFrame() ) | |||
7443 | pFly->PaintSwFrame( *pDev, aOut ); | |||
7444 | gProp.pSLines->PaintLines( pDev, gProp ); | |||
7445 | pImp->PaintLayer( rIDDMA.GetHeavenId(), nullptr, | |||
7446 | *pFlyPage, aOut, &aPageBackgrdColor, | |||
7447 | pFlyPage->IsRightToLeft(), | |||
7448 | &aSwRedirector ); | |||
7449 | gProp.pSLines->PaintLines( pDev, gProp ); | |||
7450 | gProp.pSLines.reset(); | |||
7451 | gProp.pSFlyOnlyDraw = nullptr; | |||
7452 | ||||
7453 | gProp.pSFlyMetafileOut = nullptr; | |||
7454 | gProp.bSFlyMetafile = false; | |||
7455 | ::SetOutDevAndWin( pSh, pOld, pWin, nZoom ); | |||
7456 | ||||
7457 | // #i92711# end Pre/PostPaint encapsulation when pOut is back and content is painted | |||
7458 | pSh->DLPostPaint2(true); | |||
7459 | ||||
7460 | aMet.Stop(); | |||
7461 | aMet.Move( -pFly->getFrameArea().Left(), -pFly->getFrameArea().Top() ); | |||
7462 | aRet = Graphic( aMet ); | |||
7463 | ||||
7464 | if( bNoteURL ) | |||
7465 | { | |||
7466 | OSL_ENSURE( pNoteURL, "MakeGraphic: Good Bye, NoteURL." )do { if (true && (!(pNoteURL))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx" ":" "7466" ": "), "%s", "MakeGraphic: Good Bye, NoteURL."); } } while (false); | |||
7467 | delete pNoteURL; | |||
7468 | pNoteURL = nullptr; | |||
7469 | } | |||
7470 | gProp.pSGlobalShell = pOldGlobal; | |||
7471 | } | |||
7472 | return aRet; | |||
7473 | } | |||
7474 | ||||
7475 | Graphic SwDrawFrameFormat::MakeGraphic( ImageMap* ) | |||
7476 | { | |||
7477 | Graphic aRet; | |||
7478 | SwDrawModel* pMod = getIDocumentDrawModelAccess().GetDrawModel(); | |||
7479 | if ( pMod ) | |||
7480 | { | |||
7481 | SdrObject *pObj = FindSdrObject(); | |||
7482 | std::unique_ptr<SdrView> pView( new SdrView( *pMod ) ); | |||
7483 | SdrPageView *pPgView = pView->ShowSdrPage(pView->GetModel()->GetPage(0)); | |||
7484 | pView->MarkObj( pObj, pPgView ); | |||
7485 | aRet = pView->GetMarkedObjBitmapEx(); | |||
7486 | pView->HideSdrPage(); | |||
7487 | } | |||
7488 | return aRet; | |||
7489 | } | |||
7490 | ||||
7491 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |