File: | home/maarten/src/libreoffice/core/sw/source/core/layout/paintfrm.cxx |
Warning: | line 3853, column 57 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
| ||||||||
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
| ||||||||
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
| ||||||||
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: */ |
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 | #ifndef INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX |
21 | #define INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX |
22 | |
23 | #include <drawinglayer/primitive2d/baseprimitive2d.hxx> |
24 | #include <editeng/borderline.hxx> |
25 | #include <svl/poolitem.hxx> |
26 | #include <swtypes.hxx> |
27 | #include <swrect.hxx> |
28 | #include <calbck.hxx> |
29 | #include <svl/SfxBroadcaster.hxx> |
30 | #include <o3tl/typed_flags_set.hxx> |
31 | #include <com/sun/star/style/TabStop.hpp> |
32 | #include <basegfx/matrix/b2dhommatrix.hxx> |
33 | #include <vcl/outdev.hxx> |
34 | |
35 | #include <memory> |
36 | |
37 | namespace drawinglayer::processor2d { class BaseProcessor2D; } |
38 | |
39 | class SwLayoutFrame; |
40 | class SwRootFrame; |
41 | class SwPageFrame; |
42 | class SwBodyFrame; |
43 | class SwFlyFrame; |
44 | class SwSectionFrame; |
45 | class SwFootnoteFrame; |
46 | class SwFootnoteBossFrame; |
47 | class SwTabFrame; |
48 | class SwRowFrame; |
49 | class SwContentFrame; |
50 | class SwAttrSet; |
51 | class Color; |
52 | class SwBorderAttrs; |
53 | class SwCache; |
54 | class SvxBrushItem; |
55 | class SvxFormatBreakItem; |
56 | class SwFormatPageDesc; |
57 | class SwSelectionList; |
58 | struct SwPosition; |
59 | struct SwCursorMoveState; |
60 | class SwFormat; |
61 | class SwPrintData; |
62 | class SwSortedObjs; |
63 | class SwAnchoredObject; |
64 | enum class SvxFrameDirection; |
65 | class IDocumentDrawModelAccess; |
66 | |
67 | // Each FrameType is represented here as a bit. |
68 | // The bits must be set in a way that it can be determined with masking of |
69 | // which kind of FrameType an instance is _and_ from what classes it was derived. |
70 | // Each frame has in its base class a member that must be set by the |
71 | // constructors accordingly. |
72 | enum class SwFrameType |
73 | { |
74 | None = 0x0000, |
75 | Root = 0x0001, |
76 | Page = 0x0002, |
77 | Column = 0x0004, |
78 | Header = 0x0008, |
79 | Footer = 0x0010, |
80 | FtnCont = 0x0020, |
81 | Ftn = 0x0040, |
82 | Body = 0x0080, |
83 | Fly = 0x0100, |
84 | Section = 0x0200, |
85 | // UNUSED 0x0400 |
86 | Tab = 0x0800, |
87 | Row = 0x1000, |
88 | Cell = 0x2000, |
89 | Txt = 0x4000, |
90 | NoTxt = 0x8000, |
91 | }; |
92 | |
93 | namespace o3tl |
94 | { |
95 | template<> struct typed_flags<SwFrameType> : is_typed_flags<SwFrameType, 0xfbff> {}; |
96 | }; |
97 | |
98 | // for internal use some common combinations |
99 | #define FRM_LAYOUTSwFrameType(0x3bFF) SwFrameType(0x3bFF) |
100 | #define FRM_ALLSwFrameType(0xfbff) SwFrameType(0xfbff) |
101 | #define FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) (SwFrameType::Txt | SwFrameType::NoTxt) |
102 | #define FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column) (SwFrameType::Page | SwFrameType::Column) |
103 | #define FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType ::Tab | SwFrameType::Cell | SwFrameType::Txt) (SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType::Tab | SwFrameType::Cell | SwFrameType::Txt) |
104 | #define FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) (SwFrameType::Column | SwFrameType::Cell) |
105 | #define FRM_NOTE_VERT(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType ::Txt) (SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType::Txt) |
106 | #define FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) (SwFrameType::Header | SwFrameType::Footer) |
107 | #define FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body) (SwFrameType::FtnCont | SwFrameType::Body) |
108 | |
109 | // for GetNextLeaf/GetPrevLeaf. |
110 | enum MakePageType |
111 | { |
112 | MAKEPAGE_NONE, // do not create page/footnote |
113 | MAKEPAGE_APPEND, // only append page if needed |
114 | MAKEPAGE_INSERT, // add or append page if needed |
115 | MAKEPAGE_FTN, // add footnote if needed |
116 | MAKEPAGE_NOSECTION // Don't create section frames |
117 | }; |
118 | |
119 | namespace drawinglayer::attribute { |
120 | class SdrAllFillAttributesHelper; |
121 | typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr; |
122 | } |
123 | |
124 | /// Helper class to isolate geometry-defining members of SwFrame |
125 | /// and to control their accesses. Moved to own class to have no |
126 | /// hidden accesses to 'private' members anymore. |
127 | /// |
128 | /// Added most important flags about the state of this geometric |
129 | /// information and if it is valid or not |
130 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition |
131 | { |
132 | private: |
133 | friend void FriendHackInvalidateRowFrame(SwFrameAreaDefinition &); |
134 | |
135 | // The absolute position and size of the SwFrame in the document. |
136 | // This values are set by the layouter implementations |
137 | SwRect maFrameArea; |
138 | |
139 | // The 'inner' Frame Area defined by a SwRect relative to FrameArea: |
140 | // When identical to FrameArea, Pos() will be (0, 0) and Size identical. |
141 | SwRect maFramePrintArea; |
142 | |
143 | // bitfield |
144 | bool mbFrameAreaPositionValid : 1; |
145 | bool mbFrameAreaSizeValid : 1; |
146 | bool mbFramePrintAreaValid : 1; |
147 | |
148 | // #i65250# |
149 | // frame ID is now in general available - used for layout loop control |
150 | static sal_uInt32 mnLastFrameId; |
151 | const sal_uInt32 mnFrameId; |
152 | |
153 | protected: |
154 | // write access to mb*Valid flags |
155 | void setFrameAreaPositionValid(bool bNew); |
156 | void setFrameAreaSizeValid(bool bNew); |
157 | void setFramePrintAreaValid(bool bNew); |
158 | |
159 | public: |
160 | SwFrameAreaDefinition(); |
161 | virtual ~SwFrameAreaDefinition(); |
162 | |
163 | // read access to mb*Valid flags |
164 | bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; } |
165 | bool isFrameAreaSizeValid() const { return mbFrameAreaSizeValid; } |
166 | bool isFramePrintAreaValid() const { return mbFramePrintAreaValid; } |
167 | |
168 | // syntactic sugar: test whole FrameAreaDefinition |
169 | bool isFrameAreaDefinitionValid() const { return isFrameAreaPositionValid() && isFrameAreaSizeValid() && isFramePrintAreaValid(); } |
170 | |
171 | // #i65250# |
172 | sal_uInt32 GetFrameId() const { return mnFrameId; } |
173 | |
174 | // read accesses to FrameArea definitions - only const access allowed. |
175 | // Do *not* const_cast results, it is necessary to track changes. use |
176 | // the below offered WriteAccess helper classes instead |
177 | const SwRect& getFrameArea() const { return maFrameArea; } |
178 | const SwRect& getFramePrintArea() const { return maFramePrintArea; } |
179 | |
180 | // helper class(es) for FrameArea manipulation. These |
181 | // have to be used to apply changes to FrameAreas. They hold a copy of the |
182 | // SwRect for manipulation. It gets written back at destruction. Thus, this |
183 | // mechanism depends on scope usage, take care. It prevents errors using |
184 | // different instances of SwFrame in get/set methods which is more safe |
185 | class FrameAreaWriteAccess : public SwRect |
186 | { |
187 | private: |
188 | SwFrameAreaDefinition& mrTarget; |
189 | |
190 | FrameAreaWriteAccess(const FrameAreaWriteAccess&) = delete; |
191 | FrameAreaWriteAccess& operator=(const FrameAreaWriteAccess&) = delete; |
192 | |
193 | public: |
194 | FrameAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFrameArea()), mrTarget(rTarget) {} |
195 | ~FrameAreaWriteAccess(); |
196 | void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; } |
197 | }; |
198 | |
199 | // same helper for FramePrintArea |
200 | class FramePrintAreaWriteAccess : public SwRect |
201 | { |
202 | private: |
203 | SwFrameAreaDefinition& mrTarget; |
204 | |
205 | FramePrintAreaWriteAccess(const FramePrintAreaWriteAccess&) = delete; |
206 | FramePrintAreaWriteAccess& operator=(const FramePrintAreaWriteAccess&) = delete; |
207 | |
208 | public: |
209 | FramePrintAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFramePrintArea()), mrTarget(rTarget) {} |
210 | ~FramePrintAreaWriteAccess(); |
211 | void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; } |
212 | }; |
213 | |
214 | // RotateFlyFrame3 - Support for Transformations |
215 | // Hand out the Transformations for the current FrameAreaDefinition |
216 | // for the FrameArea and FramePrintArea. |
217 | // FramePrintArea is not relative to FrameArea in this |
218 | // transformation representation (to make it easier to use and understand). |
219 | // There is no 'set' method since SwFrame is a layout object. For |
220 | // some cases rotation will be included (used for SwGrfNode in inner |
221 | // SwFrame of a SwFlyFrame) |
222 | virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const; |
223 | virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; |
224 | |
225 | // RotateFlyFrame3 - Support for Transformations |
226 | // Modify current transformations by applying given translation |
227 | virtual void transform_translate(const Point& rOffset); |
228 | }; |
229 | |
230 | /// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate |
231 | /// transformable. It provides some tooling to do so. To use, add as member |
232 | /// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >') |
233 | class TransformableSwFrame |
234 | { |
235 | private: |
236 | // The SwFrameAreaDefinition to work on |
237 | SwFrameAreaDefinition& mrSwFrameAreaDefinition; |
238 | |
239 | // FrameAreaTransformation and FramePrintAreaTransformation |
240 | // !identity when needed (translate/scale is used (e.g. rotation)) |
241 | basegfx::B2DHomMatrix maFrameAreaTransformation; |
242 | basegfx::B2DHomMatrix maFramePrintAreaTransformation; |
243 | |
244 | public: |
245 | TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition) |
246 | : mrSwFrameAreaDefinition(rSwFrameAreaDefinition), |
247 | maFrameAreaTransformation(), |
248 | maFramePrintAreaTransformation() |
249 | { |
250 | } |
251 | |
252 | // get SwFrameArea in transformation form |
253 | const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const |
254 | { |
255 | return maFrameAreaTransformation; |
256 | } |
257 | |
258 | // get SwFramePrintArea in transformation form |
259 | const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const |
260 | { |
261 | return maFramePrintAreaTransformation; |
262 | } |
263 | |
264 | // Helpers to re-create the untransformed SwRect(s) originally |
265 | // in the SwFrameAreaDefinition, based on the current Transformations. |
266 | SwRect getUntransformedFrameArea() const; |
267 | SwRect getUntransformedFramePrintArea() const; |
268 | |
269 | // Helper method to re-create FrameAreaTransformations based on the |
270 | // current FrameAreaDefinition transformed by given rotation and Center |
271 | void createFrameAreaTransformations( |
272 | double fRotation, |
273 | const basegfx::B2DPoint& rCenter); |
274 | |
275 | // Tooling method to reset the SwRect(s) in the current |
276 | // SwFrameAreaDefinition which are already adapted to |
277 | // Transformation back to the untransformed state, using |
278 | // the getUntransformedFrame*Area calls above when needed. |
279 | // Only the SwRect(s) are changed back, not the transformations. |
280 | void restoreFrameAreas(); |
281 | |
282 | // Re-Creates the SwRect(s) as BoundAreas based on the current |
283 | // set Transformations. |
284 | void adaptFrameAreasToTransformations(); |
285 | |
286 | // Modify current definitions by applying the given transformation |
287 | void transform(const basegfx::B2DHomMatrix& aTransform); |
288 | }; |
289 | |
290 | /** |
291 | * Base class of the Writer layout elements. |
292 | * |
293 | * This includes not only fly frames, but everything down to the paragraph |
294 | * level: pages, headers, footers, etc. (Inside a paragraph SwLinePortion |
295 | * instances are used.) |
296 | */ |
297 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwFrame : public SwFrameAreaDefinition, public SwClient, public SfxBroadcaster |
298 | { |
299 | // the hidden Frame |
300 | friend class SwFlowFrame; |
301 | friend class SwLayoutFrame; |
302 | friend class SwLooping; |
303 | friend class SwDeletionChecker; // for GetDep() |
304 | |
305 | // voids lower during creation of a column |
306 | friend SwFrame *SaveContent( SwLayoutFrame *, SwFrame* pStart ); |
307 | friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling ); |
308 | |
309 | // for validating a mistakenly invalidated one in SwContentFrame::MakeAll |
310 | friend void ValidateSz( SwFrame *pFrame ); |
311 | // implemented in text/txtftn.cxx, prevents Footnote oscillation |
312 | friend void ValidateText( SwFrame *pFrame ); |
313 | |
314 | friend void MakeNxt( SwFrame *pFrame, SwFrame *pNxt ); |
315 | |
316 | // cache for (border) attributes |
317 | static SwCache *mpCache; |
318 | |
319 | SwRootFrame *mpRoot; |
320 | SwLayoutFrame *mpUpper; |
321 | SwFrame *mpNext; |
322 | SwFrame *mpPrev; |
323 | |
324 | // sw_redlinehide: hide these dangerous SwClient functions |
325 | using SwClient::GetRegisteredInNonConst; |
326 | using SwClient::GetRegisteredIn; |
327 | |
328 | SwFrame *FindNext_(); |
329 | SwFrame *FindPrev_(); |
330 | |
331 | /** method to determine next content frame in the same environment |
332 | for a flow frame (content frame, table frame, section frame) |
333 | |
334 | #i27138# - adding documentation: |
335 | Travelling downwards through the layout to determine the next content |
336 | frame in the same environment. There are several environments in a |
337 | document, which form a closed context regarding this function. These |
338 | environments are: |
339 | - Each page header |
340 | - Each page footer |
341 | - Each unlinked fly frame |
342 | - Each group of linked fly frames |
343 | - All footnotes |
344 | - All document body frames |
345 | #i27138# - adding parameter <_bInSameFootnote> |
346 | Its default value is <false>. If its value is <true>, the environment |
347 | 'All footnotes' is no longer treated. Instead each footnote is treated |
348 | as an own environment. |
349 | |
350 | @param _bInSameFootnote |
351 | input parameter - boolean indicating, that the found next content |
352 | frame has to be in the same footnote frame. This parameter is only |
353 | relevant for flow frames in footnotes. |
354 | |
355 | @return SwContentFrame* |
356 | pointer to the found next content frame. It's NULL, if none exists. |
357 | */ |
358 | SwContentFrame* FindNextCnt_( const bool _bInSameFootnote ); |
359 | |
360 | /** method to determine previous content frame in the same environment |
361 | for a flow frame (content frame, table frame, section frame) |
362 | |
363 | #i27138# |
364 | Travelling upwards through the layout to determine the previous content |
365 | frame in the same environment. There are several environments in a |
366 | document, which form a closed context regarding this function. These |
367 | environments are: |
368 | - Each page header |
369 | - Each page footer |
370 | - Each unlinked fly frame |
371 | - Each group of linked fly frames |
372 | - All footnotes |
373 | - All document body frames |
374 | #i27138# - adding parameter <_bInSameFootnote> |
375 | Its default value is <false>. If its value is <true>, the environment |
376 | 'All footnotes' is no longer treated. Instead each footnote is treated |
377 | as an own environment. |
378 | |
379 | The found previous content frame has to be in the same footnote frame. This is only |
380 | relevant for flow frames in footnotes. |
381 | |
382 | @return SwContentFrame* |
383 | pointer to the found previous content frame. It's NULL, if none exists. |
384 | */ |
385 | SwContentFrame* FindPrevCnt_(); |
386 | |
387 | void UpdateAttrFrame( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & ); |
388 | SwFrame* GetIndNext_(); |
389 | void SetDirFlags( bool bVert ); |
390 | |
391 | const SwLayoutFrame* ImplGetNextLayoutLeaf( bool bFwd ) const; |
392 | |
393 | SwPageFrame* ImplFindPageFrame(); |
394 | |
395 | protected: |
396 | std::unique_ptr<SwSortedObjs> m_pDrawObjs; // draw objects, can be null |
397 | SwFrameType mnFrameType; //Who am I? |
398 | |
399 | bool mbInDtor : 1; |
400 | bool mbInvalidR2L : 1; |
401 | bool mbDerivedR2L : 1; |
402 | bool mbRightToLeft : 1; |
403 | bool mbInvalidVert : 1; |
404 | bool mbDerivedVert : 1; |
405 | bool mbVertical : 1; |
406 | |
407 | bool mbVertLR : 1; |
408 | bool mbVertLRBT : 1; |
409 | |
410 | bool mbValidLineNum : 1; |
411 | bool mbFixSize : 1; |
412 | |
413 | // if true, frame will be painted completely even content was changed |
414 | // only partially. For ContentFrames a border (from Action) will exclusively |
415 | // painted if <mbCompletePaint> is true. |
416 | bool mbCompletePaint : 1; |
417 | |
418 | bool mbRetouche : 1; // frame is responsible for retouching |
419 | |
420 | bool mbInfInvalid : 1; // InfoFlags are invalid |
421 | bool mbInfBody : 1; // Frame is in document body |
422 | bool mbInfTab : 1; // Frame is in a table |
423 | bool mbInfFly : 1; // Frame is in a Fly |
424 | bool mbInfFootnote : 1; // Frame is in a footnote |
425 | bool mbInfSct : 1; // Frame is in a section |
426 | bool mbColLocked : 1; // lock Grow/Shrink for column-wise section |
427 | // or fly frames, will be set in Format |
428 | bool m_isInDestroy : 1; |
429 | bool mbForbidDelete : 1; |
430 | |
431 | void ColLock() { mbColLocked = true; } |
432 | void ColUnlock() { mbColLocked = false; } |
433 | |
434 | virtual void DestroyImpl(); |
435 | virtual ~SwFrame() override; |
436 | |
437 | // Only used by SwRootFrame Ctor to get 'this' into mpRoot... |
438 | void setRootFrame( SwRootFrame* pRoot ) { mpRoot = pRoot; } |
439 | |
440 | SwPageFrame *InsertPage( SwPageFrame *pSibling, bool bFootnote ); |
441 | void PrepareMake(vcl::RenderContext* pRenderContext); |
442 | void OptPrepareMake(); |
443 | virtual void MakePos(); |
444 | // Format next frame of table frame to assure keeping attributes. |
445 | // In case of nested tables method <SwFrame::MakeAll()> is called to |
446 | // avoid formatting of superior table frame. |
447 | friend SwFrame* sw_FormatNextContentForKeep( SwTabFrame* pTabFrame ); |
448 | |
449 | virtual void MakeAll(vcl::RenderContext* pRenderContext) = 0; |
450 | // adjust frames of a page |
451 | SwTwips AdjustNeighbourhood( SwTwips nDiff, bool bTst = false ); |
452 | |
453 | // change only frame size not the size of PrtArea |
454 | virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) = 0; |
455 | virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) = 0; |
456 | |
457 | /// use these so we can grep for SwFrame's GetRegisteredIn accesses |
458 | /// beware that SwTextFrame may return sw::WriterMultiListener |
459 | SwModify *GetDep() { return GetRegisteredInNonConst(); } |
460 | const SwModify *GetDep() const { return GetRegisteredIn(); } |
461 | |
462 | SwFrame( SwModify*, SwFrame* ); |
463 | |
464 | void CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse ); |
465 | |
466 | /** enumeration for the different invalidations |
467 | #i28701# |
468 | */ |
469 | enum InvalidationType |
470 | { |
471 | INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL |
472 | }; |
473 | |
474 | /** method to determine, if an invalidation is allowed. |
475 | #i28701 |
476 | */ |
477 | virtual bool InvalidationAllowed( const InvalidationType _nInvalid ) const; |
478 | |
479 | /** method to perform additional actions on an invalidation |
480 | |
481 | #i28701# |
482 | Method has *only* to contain actions, which has to be performed on |
483 | *every* assignment of the corresponding flag to <false>. |
484 | */ |
485 | virtual void ActionOnInvalidation( const InvalidationType _nInvalid ); |
486 | |
487 | // draw shadow and borders |
488 | void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const; |
489 | virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override; |
490 | |
491 | virtual const IDocumentDrawModelAccess& getIDocumentDrawModelAccess( ); |
492 | |
493 | public: |
494 | virtual css::uno::Sequence< css::style::TabStop > GetTabStopInfo( SwTwips ) |
495 | { |
496 | return css::uno::Sequence< css::style::TabStop >(); |
497 | } |
498 | |
499 | |
500 | SwFrameType GetType() const { return mnFrameType; } |
501 | |
502 | static SwCache &GetCache() { return *mpCache; } |
503 | static SwCache *GetCachePtr() { return mpCache; } |
504 | static void SetCache( SwCache *pNew ) { mpCache = pNew; } |
505 | |
506 | // change PrtArea size and FrameSize |
507 | SwTwips Shrink( SwTwips, bool bTst = false, bool bInfo = false ); |
508 | SwTwips Grow ( SwTwips, bool bTst = false, bool bInfo = false ); |
509 | |
510 | // different methods for inserting in layout tree (for performance reasons) |
511 | |
512 | // insert before pBehind or at the end of the chain below mpUpper |
513 | void InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind ); |
514 | // insert after pBefore or at the beginning of the chain below mpUpper |
515 | void InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore ); |
516 | // insert before pBehind or at the end of the chain while considering |
517 | // the siblings of pSct |
518 | bool InsertGroupBefore( SwFrame* pParent, SwFrame* pWhere, SwFrame* pSct ); |
519 | void RemoveFromLayout(); |
520 | |
521 | // For internal use only - who ignores this will be put in a sack and has |
522 | // to stay there for two days |
523 | // Does special treatment for Get_[Next|Prev]Leaf() (for tables). |
524 | SwLayoutFrame *GetLeaf( MakePageType eMakePage, bool bFwd ); |
525 | SwLayoutFrame *GetNextLeaf ( MakePageType eMakePage ); |
526 | SwLayoutFrame *GetNextFootnoteLeaf( MakePageType eMakePage ); |
527 | SwLayoutFrame *GetNextSctLeaf( MakePageType eMakePage ); |
528 | SwLayoutFrame *GetNextCellLeaf(); |
529 | SwLayoutFrame *GetPrevLeaf (); |
530 | SwLayoutFrame *GetPrevFootnoteLeaf( MakePageType eMakeFootnote ); |
531 | SwLayoutFrame *GetPrevSctLeaf(); |
532 | SwLayoutFrame *GetPrevCellLeaf(); |
533 | const SwLayoutFrame *GetLeaf ( MakePageType eMakePage, bool bFwd, |
534 | const SwFrame *pAnch ) const; |
535 | |
536 | bool WrongPageDesc( SwPageFrame* pNew ); |
537 | |
538 | //#i28701# - new methods to append/remove drawing objects |
539 | void AppendDrawObj( SwAnchoredObject& _rNewObj ); |
540 | void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj ); |
541 | |
542 | // work with chain of FlyFrames |
543 | void AppendFly( SwFlyFrame *pNew ); |
544 | void RemoveFly( SwFlyFrame *pToRemove ); |
545 | const SwSortedObjs *GetDrawObjs() const { return m_pDrawObjs.get(); } |
546 | SwSortedObjs *GetDrawObjs() { return m_pDrawObjs.get(); } |
547 | // #i28701# - change purpose of method and adjust its name |
548 | void InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs = true ); |
549 | |
550 | virtual void PaintSwFrameShadowAndBorder( |
551 | const SwRect&, |
552 | const SwPageFrame* pPage, |
553 | const SwBorderAttrs&) const; |
554 | void PaintBaBo( const SwRect&, const SwPageFrame *pPage, |
555 | const bool bOnlyTextBackground = false) const; |
556 | void PaintSwFrameBackground( const SwRect&, const SwPageFrame *pPage, |
557 | const SwBorderAttrs &, |
558 | const bool bLowerMode = false, |
559 | const bool bLowerBorder = false, |
560 | const bool bOnlyTextBackground = false ) const; |
561 | void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrame*, |
562 | const Color *pColor, |
563 | const SvxBorderLineStyle = SvxBorderLineStyle::SOLID ) const; |
564 | |
565 | std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> CreateProcessor2D( ) const; |
566 | void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const; |
567 | |
568 | // retouch, not in the area of the given Rect! |
569 | void Retouch( const SwPageFrame *pPage, const SwRect &rRect ) const; |
570 | |
571 | bool GetBackgroundBrush( |
572 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes, |
573 | const SvxBrushItem*& rpBrush, |
574 | const Color*& rpColor, |
575 | SwRect &rOrigRect, |
576 | bool bLowerMode, |
577 | bool bConsiderTextBox ) const; |
578 | |
579 | inline void SetCompletePaint() const; |
580 | inline void ResetCompletePaint() const; |
581 | bool IsCompletePaint() const { return mbCompletePaint; } |
582 | |
583 | inline void SetRetouche() const; |
584 | inline void ResetRetouche() const; |
585 | bool IsRetouche() const { return mbRetouche; } |
586 | |
587 | void SetInfFlags(); |
588 | void InvalidateInfFlags() { mbInfInvalid = true; } |
589 | inline bool IsInDocBody() const; // use InfoFlags, determine flags |
590 | inline bool IsInFootnote() const; // if necessary |
591 | inline bool IsInTab() const; |
592 | inline bool IsInFly() const; |
593 | inline bool IsInSct() const; |
594 | |
595 | // If frame is inside a split table row, this function returns |
596 | // the corresponding row frame in the follow table. |
597 | const SwRowFrame* IsInSplitTableRow() const; |
598 | |
599 | // If frame is inside a follow flow row, this function returns |
600 | // the corresponding row frame master table |
601 | const SwRowFrame* IsInFollowFlowRow() const; |
602 | |
603 | bool IsInBalancedSection() const; |
604 | |
605 | inline bool IsVertical() const; |
606 | inline bool IsVertLR() const; |
607 | inline bool IsVertLRBT() const; |
608 | |
609 | void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; } |
610 | void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; } |
611 | inline bool IsRightToLeft() const; |
612 | void SetDerivedR2L( bool bNew ) { mbDerivedR2L = bNew; } |
613 | |
614 | void CheckDirChange(); |
615 | // returns upper left frame position for LTR and |
616 | // upper right frame position for Asian / RTL frames |
617 | Point GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const; |
618 | |
619 | /** determine, if frame is moveable in given environment |
620 | |
621 | method replaced 'old' method <bool IsMoveable() const>. |
622 | Determines, if frame is moveable in given environment. if no environment |
623 | is given (parameter _pLayoutFrame == 0), the movability in the actual |
624 | environment (<GetUpper()) is checked. |
625 | |
626 | @param _pLayoutFrame |
627 | input parameter - given environment (layout frame), in which the movability |
628 | will be checked. If not set ( == 0 ), actual environment is taken. |
629 | |
630 | @return boolean, indicating, if frame is moveable in given environment |
631 | */ |
632 | bool IsMoveable( const SwLayoutFrame* _pLayoutFrame = nullptr ) const; |
633 | |
634 | // Is it permitted for the (Text)Frame to add a footnote in the current |
635 | // environment (not e.g. for repeating table headlines) |
636 | bool IsFootnoteAllowed() const; |
637 | |
638 | virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ); |
639 | |
640 | virtual void CheckDirection( bool bVert ); |
641 | |
642 | void ReinitializeFrameSizeAttrFlags(); |
643 | |
644 | /// WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for |
645 | /// SwTextFrame, use GetBreakItem()/GetPageDescItem() instead |
646 | const SwAttrSet *GetAttrSet() const; |
647 | virtual const SvxFormatBreakItem& GetBreakItem() const; |
648 | virtual const SwFormatPageDesc& GetPageDescItem() const; |
649 | |
650 | bool HasFixSize() const { return mbFixSize; } |
651 | |
652 | // check all pages (starting from the given) and correct them if needed |
653 | static void CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields = true, SwPageFrame** ppPrev = nullptr); |
654 | |
655 | // might return 0, with and without const |
656 | SwFrame *GetNext() { return mpNext; } |
657 | SwFrame *GetPrev() { return mpPrev; } |
658 | SwLayoutFrame *GetUpper() { return mpUpper; } |
659 | SwRootFrame *getRootFrame(){ return mpRoot; } |
660 | SwPageFrame *FindPageFrame() { return IsPageFrame() ? reinterpret_cast<SwPageFrame*>(this) : ImplFindPageFrame(); } |
661 | SwFrame *FindColFrame(); |
662 | SwRowFrame *FindRowFrame(); |
663 | SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnotes = false ); |
664 | SwTabFrame *ImplFindTabFrame(); |
665 | SwFootnoteFrame *ImplFindFootnoteFrame(); |
666 | SwFlyFrame *ImplFindFlyFrame(); |
667 | SwSectionFrame *ImplFindSctFrame(); |
668 | const SwBodyFrame *ImplFindBodyFrame() const; |
669 | SwFrame *FindFooterOrHeader(); |
670 | SwFrame *GetLower(); |
671 | const SwFrame *GetNext() const { return mpNext; } |
672 | const SwFrame *GetPrev() const { return mpPrev; } |
673 | const SwLayoutFrame *GetUpper() const { return mpUpper; } |
674 | const SwRootFrame *getRootFrame() const { return mpRoot; } |
675 | inline SwTabFrame *FindTabFrame(); |
676 | inline SwFootnoteFrame *FindFootnoteFrame(); |
677 | inline SwFlyFrame *FindFlyFrame(); |
678 | inline SwSectionFrame *FindSctFrame(); |
679 | inline SwFrame *FindNext(); |
680 | // #i27138# - add parameter <_bInSameFootnote> |
681 | SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ); |
682 | inline SwFrame *FindPrev(); |
683 | inline const SwPageFrame *FindPageFrame() const; |
684 | inline const SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnote = false ) const; |
685 | inline const SwFrame *FindColFrame() const; |
686 | inline const SwFrame *FindFooterOrHeader() const; |
687 | inline const SwTabFrame *FindTabFrame() const; |
688 | inline const SwFootnoteFrame *FindFootnoteFrame() const; |
689 | inline const SwFlyFrame *FindFlyFrame() const; |
690 | inline const SwSectionFrame *FindSctFrame() const; |
691 | inline const SwBodyFrame *FindBodyFrame() const; |
692 | inline const SwFrame *FindNext() const; |
693 | // #i27138# - add parameter <_bInSameFootnote> |
694 | const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const; |
695 | inline const SwFrame *FindPrev() const; |
696 | const SwFrame *GetLower() const; |
697 | |
698 | SwContentFrame* FindPrevCnt(); |
699 | |
700 | const SwContentFrame* FindPrevCnt() const; |
701 | |
702 | // #i79774# |
703 | SwFrame* GetIndPrev_() const; |
704 | SwFrame* GetIndPrev() const |
705 | { return ( mpPrev || !IsInSct() ) ? mpPrev : GetIndPrev_(); } |
706 | |
707 | SwFrame* GetIndNext() |
708 | { return ( mpNext || !IsInSct() ) ? mpNext : GetIndNext_(); } |
709 | const SwFrame* GetIndNext() const { return const_cast<SwFrame*>(this)->GetIndNext(); } |
710 | |
711 | sal_uInt16 GetPhyPageNum() const; // page number without offset |
712 | sal_uInt16 GetVirtPageNum() const; // page number with offset |
713 | bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; }; |
714 | bool WannaRightPage() const; |
715 | bool OnFirstPage() const; |
716 | |
717 | inline const SwLayoutFrame *GetPrevLayoutLeaf() const; |
718 | inline const SwLayoutFrame *GetNextLayoutLeaf() const; |
719 | inline SwLayoutFrame *GetPrevLayoutLeaf(); |
720 | inline SwLayoutFrame *GetNextLayoutLeaf(); |
721 | |
722 | virtual void Calc(vcl::RenderContext* pRenderContext) const; // here might be "formatted" |
723 | inline void OptCalc() const; // here we assume (for optimization) that |
724 | // the predecessors are already formatted |
725 | Point GetRelPos() const; |
726 | |
727 | // PaintArea is the area where content might be displayed. |
728 | // The margin of a page or the space between columns belongs to it. |
729 | SwRect GetPaintArea() const; |
730 | |
731 | // UnionFrame is the union of Frame- and PrtArea, normally identical |
732 | // to the FrameArea except in case of negative Prt margins. |
733 | SwRect UnionFrame( bool bBorder = false ) const; |
734 | |
735 | virtual Size ChgSize( const Size& aNewSize ); |
736 | |
737 | virtual void Cut() = 0; |
738 | virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) = 0; |
739 | |
740 | void ValidateLineNum() { mbValidLineNum = true; } |
741 | |
742 | bool GetValidLineNumFlag()const { return mbValidLineNum; } |
743 | |
744 | // Only invalidate Frame |
745 | // #i28701# - add call to method <ActionOnInvalidation(..)> |
746 | // for all invalidation methods. |
747 | // #i28701# - use method <InvalidationAllowed(..)> to |
748 | // decide, if invalidation will to be performed or not. |
749 | // #i26945# - no additional invalidation, if it's already |
750 | // invalidate. |
751 | void InvalidateSize_() |
752 | { |
753 | if ( isFrameAreaSizeValid() && InvalidationAllowed( INVALID_SIZE ) ) |
754 | { |
755 | setFrameAreaSizeValid(false); |
756 | ActionOnInvalidation( INVALID_SIZE ); |
757 | } |
758 | } |
759 | void InvalidatePrt_() |
760 | { |
761 | if ( isFramePrintAreaValid() && InvalidationAllowed( INVALID_PRTAREA ) ) |
762 | { |
763 | setFramePrintAreaValid(false); |
764 | ActionOnInvalidation( INVALID_PRTAREA ); |
765 | } |
766 | } |
767 | void InvalidatePos_() |
768 | { |
769 | if ( isFrameAreaPositionValid() && InvalidationAllowed( INVALID_POS ) ) |
770 | { |
771 | setFrameAreaPositionValid(false); |
772 | ActionOnInvalidation( INVALID_POS ); |
773 | } |
774 | } |
775 | void InvalidateLineNum_() |
776 | { |
777 | if ( mbValidLineNum && InvalidationAllowed( INVALID_LINENUM ) ) |
778 | { |
779 | mbValidLineNum = false; |
780 | ActionOnInvalidation( INVALID_LINENUM ); |
781 | } |
782 | } |
783 | void InvalidateAll_() |
784 | { |
785 | if ( ( isFrameAreaSizeValid() || isFramePrintAreaValid() || isFrameAreaPositionValid() ) && InvalidationAllowed( INVALID_ALL ) ) |
786 | { |
787 | setFrameAreaSizeValid(false); |
788 | setFrameAreaPositionValid(false); |
789 | setFramePrintAreaValid(false); |
790 | ActionOnInvalidation( INVALID_ALL ); |
791 | } |
792 | } |
793 | // also notify page at the same time |
794 | inline void InvalidateSize(); |
795 | inline void InvalidatePrt(); |
796 | inline void InvalidatePos(); |
797 | inline void InvalidateLineNum(); |
798 | inline void InvalidateAll(); |
799 | void ImplInvalidateSize(); |
800 | void ImplInvalidatePrt(); |
801 | void ImplInvalidatePos(); |
802 | void ImplInvalidateLineNum(); |
803 | |
804 | inline void InvalidateNextPos( bool bNoFootnote = false ); |
805 | void ImplInvalidateNextPos( bool bNoFootnote ); |
806 | |
807 | /** method to invalidate printing area of next frame |
808 | #i11859# |
809 | */ |
810 | void InvalidateNextPrtArea(); |
811 | |
812 | void InvalidatePage( const SwPageFrame *pPage = nullptr ) const; |
813 | |
814 | virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const; |
815 | |
816 | virtual bool GetModelPositionForViewPoint( SwPosition *, Point&, |
817 | SwCursorMoveState* = nullptr, bool bTestBackground = false ) const; |
818 | virtual bool GetCharRect( SwRect &, const SwPosition&, |
819 | SwCursorMoveState* = nullptr, bool bAllowFarAway = true ) const; |
820 | virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&, |
821 | SwPrintData const*const pPrintData = nullptr ) const; |
822 | |
823 | // HACK: shortcut between frame and formatting |
824 | // It's your own fault if you cast void* incorrectly! In any case check |
825 | // the void* for 0. |
826 | virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear, |
827 | const void *pVoid = nullptr, bool bNotify = true ); |
828 | |
829 | // true if it is the correct class, false otherwise |
830 | inline bool IsLayoutFrame() const; |
831 | inline bool IsRootFrame() const; |
832 | inline bool IsPageFrame() const; |
833 | inline bool IsColumnFrame() const; |
834 | inline bool IsFootnoteBossFrame() const; // footnote bosses might be PageFrames or ColumnFrames |
835 | inline bool IsHeaderFrame() const; |
836 | inline bool IsFooterFrame() const; |
837 | inline bool IsFootnoteContFrame() const; |
838 | inline bool IsFootnoteFrame() const; |
839 | inline bool IsBodyFrame() const; |
840 | inline bool IsColBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above ColumnFrame |
841 | inline bool IsPageBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above PageFrame |
842 | inline bool IsFlyFrame() const; |
843 | inline bool IsSctFrame() const; |
844 | inline bool IsTabFrame() const; |
845 | inline bool IsRowFrame() const; |
846 | inline bool IsCellFrame() const; |
847 | inline bool IsContentFrame() const; |
848 | inline bool IsTextFrame() const; |
849 | inline bool IsNoTextFrame() const; |
850 | // Frames where its PrtArea depends on their neighbors and that are |
851 | // positioned in the content flow |
852 | inline bool IsFlowFrame() const; |
853 | // Frames that are capable of retouching or that might need to retouch behind |
854 | // themselves |
855 | inline bool IsRetoucheFrame() const; |
856 | inline bool IsAccessibleFrame() const; |
857 | |
858 | void PrepareCursor(); // CursorShell is allowed to call this |
859 | |
860 | // Is the Frame (or the section containing it) protected? Same for Fly in |
861 | // Fly in ... and footnotes |
862 | bool IsProtected() const; |
863 | |
864 | bool IsColLocked() const { return mbColLocked; } |
865 | virtual bool IsDeleteForbidden() const { return mbForbidDelete; } |
866 | |
867 | /// this is the only way to delete a SwFrame instance |
868 | static void DestroyFrame(SwFrame *const pFrame); |
869 | |
870 | bool IsInDtor() const { return mbInDtor; } |
871 | |
872 | // No inline cause we need the function pointers |
873 | long GetTopMargin() const; |
874 | long GetBottomMargin() const; |
875 | long GetLeftMargin() const; |
876 | long GetRightMargin() const; |
877 | void SetTopBottomMargins( long, long ); |
878 | void SetLeftRightMargins( long, long ); |
879 | void SetRightLeftMargins( long, long ); |
880 | long GetPrtLeft() const; |
881 | long GetPrtBottom() const; |
882 | long GetPrtRight() const; |
883 | long GetPrtTop() const; |
884 | bool SetMinLeft( long ); |
885 | bool SetMaxBottom( long ); |
886 | bool SetMaxRight( long ); |
887 | void MakeBelowPos( const SwFrame*, const SwFrame*, bool ); |
888 | void MakeLeftPos( const SwFrame*, const SwFrame*, bool ); |
889 | void MakeRightPos( const SwFrame*, const SwFrame*, bool ); |
890 | bool IsNeighbourFrame() const |
891 | { return bool(GetType() & FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell)); } |
892 | |
893 | // NEW TABLES |
894 | // Some functions for covered/covering table cells. This way unnecessary |
895 | // includes can be avoided |
896 | virtual bool IsLeaveUpperAllowed() const; |
897 | virtual bool IsCoveredCell() const; |
898 | bool IsInCoveredCell() const; |
899 | |
900 | // #i81146# new loop control |
901 | bool KnowsFormat( const SwFormat& rFormat ) const; |
902 | void RegisterToFormat( SwFormat& rFormat ); |
903 | void ValidateThisAndAllLowers( const sal_uInt16 nStage ); |
904 | |
905 | void ForbidDelete() { mbForbidDelete = true; } |
906 | void AllowDelete() { mbForbidDelete = false; } |
907 | |
908 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const; |
909 | bool supportsFullDrawingLayerFillAttributeSet() const; |
910 | |
911 | public: |
912 | // if writer is NULL, dumps the layout structure as XML in layout.xml |
913 | virtual void dumpAsXml(xmlTextWriterPtr writer = nullptr) const; |
914 | void dumpTopMostAsXml(xmlTextWriterPtr writer = nullptr) const; |
915 | void dumpInfosAsXml(xmlTextWriterPtr writer) const; |
916 | virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const; |
917 | void dumpChildrenAsXml(xmlTextWriterPtr writer) const; |
918 | bool IsCollapse() const; |
919 | }; |
920 | |
921 | inline bool SwFrame::IsInDocBody() const |
922 | { |
923 | if ( mbInfInvalid ) |
924 | const_cast<SwFrame*>(this)->SetInfFlags(); |
925 | return mbInfBody; |
926 | } |
927 | inline bool SwFrame::IsInFootnote() const |
928 | { |
929 | if ( mbInfInvalid ) |
930 | const_cast<SwFrame*>(this)->SetInfFlags(); |
931 | return mbInfFootnote; |
932 | } |
933 | inline bool SwFrame::IsInTab() const |
934 | { |
935 | if ( mbInfInvalid ) |
936 | const_cast<SwFrame*>(this)->SetInfFlags(); |
937 | return mbInfTab; |
938 | } |
939 | inline bool SwFrame::IsInFly() const |
940 | { |
941 | if ( mbInfInvalid ) |
942 | const_cast<SwFrame*>(this)->SetInfFlags(); |
943 | return mbInfFly; |
944 | } |
945 | inline bool SwFrame::IsInSct() const |
946 | { |
947 | if ( mbInfInvalid ) |
948 | const_cast<SwFrame*>(this)->SetInfFlags(); |
949 | return mbInfSct; |
950 | } |
951 | bool SwFrame::IsVertical() const |
952 | { |
953 | if( mbInvalidVert ) |
954 | const_cast<SwFrame*>(this)->SetDirFlags( true ); |
955 | return mbVertical; |
956 | } |
957 | inline bool SwFrame::IsVertLR() const |
958 | { |
959 | return mbVertLR; |
960 | } |
961 | inline bool SwFrame::IsVertLRBT() const |
962 | { |
963 | return mbVertLRBT; |
964 | } |
965 | inline bool SwFrame::IsRightToLeft() const |
966 | { |
967 | if( mbInvalidR2L ) |
968 | const_cast<SwFrame*>(this)->SetDirFlags( false ); |
969 | return mbRightToLeft; |
970 | } |
971 | |
972 | inline void SwFrame::SetCompletePaint() const |
973 | { |
974 | const_cast<SwFrame*>(this)->mbCompletePaint = true; |
975 | } |
976 | inline void SwFrame::ResetCompletePaint() const |
977 | { |
978 | const_cast<SwFrame*>(this)->mbCompletePaint = false; |
979 | } |
980 | |
981 | inline void SwFrame::SetRetouche() const |
982 | { |
983 | const_cast<SwFrame*>(this)->mbRetouche = true; |
984 | } |
985 | inline void SwFrame::ResetRetouche() const |
986 | { |
987 | const_cast<SwFrame*>(this)->mbRetouche = false; |
988 | } |
989 | |
990 | inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf() |
991 | { |
992 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf()); |
993 | } |
994 | inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() |
995 | { |
996 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf()); |
997 | } |
998 | inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const |
999 | { |
1000 | return ImplGetNextLayoutLeaf( true ); |
1001 | } |
1002 | inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const |
1003 | { |
1004 | return ImplGetNextLayoutLeaf( false ); |
1005 | } |
1006 | |
1007 | inline void SwFrame::InvalidateSize() |
1008 | { |
1009 | if ( isFrameAreaSizeValid() ) |
1010 | { |
1011 | ImplInvalidateSize(); |
1012 | } |
1013 | } |
1014 | inline void SwFrame::InvalidatePrt() |
1015 | { |
1016 | if ( isFramePrintAreaValid() ) |
1017 | { |
1018 | ImplInvalidatePrt(); |
1019 | } |
1020 | } |
1021 | inline void SwFrame::InvalidatePos() |
1022 | { |
1023 | if ( isFrameAreaPositionValid() ) |
1024 | { |
1025 | ImplInvalidatePos(); |
1026 | } |
1027 | } |
1028 | inline void SwFrame::InvalidateLineNum() |
1029 | { |
1030 | if ( mbValidLineNum ) |
1031 | ImplInvalidateLineNum(); |
1032 | } |
1033 | inline void SwFrame::InvalidateAll() |
1034 | { |
1035 | if ( InvalidationAllowed( INVALID_ALL ) ) |
1036 | { |
1037 | if ( isFrameAreaDefinitionValid() ) |
1038 | { |
1039 | ImplInvalidatePos(); |
1040 | } |
1041 | |
1042 | setFrameAreaSizeValid(false); |
1043 | setFrameAreaPositionValid(false); |
1044 | setFramePrintAreaValid(false); |
1045 | |
1046 | // #i28701# |
1047 | ActionOnInvalidation( INVALID_ALL ); |
1048 | } |
1049 | } |
1050 | inline void SwFrame::InvalidateNextPos( bool bNoFootnote ) |
1051 | { |
1052 | if ( mpNext && !mpNext->IsSctFrame() ) |
1053 | mpNext->InvalidatePos(); |
1054 | else |
1055 | ImplInvalidateNextPos( bNoFootnote ); |
1056 | } |
1057 | |
1058 | inline void SwFrame::OptCalc() const |
1059 | { |
1060 | if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() ) |
1061 | { |
1062 | const_cast<SwFrame*>(this)->OptPrepareMake(); |
1063 | } |
1064 | } |
1065 | inline const SwPageFrame *SwFrame::FindPageFrame() const |
1066 | { |
1067 | return const_cast<SwFrame*>(this)->FindPageFrame(); |
1068 | } |
1069 | inline const SwFrame *SwFrame::FindColFrame() const |
1070 | { |
1071 | return const_cast<SwFrame*>(this)->FindColFrame(); |
1072 | } |
1073 | inline const SwFrame *SwFrame::FindFooterOrHeader() const |
1074 | { |
1075 | return const_cast<SwFrame*>(this)->FindFooterOrHeader(); |
1076 | } |
1077 | inline SwTabFrame *SwFrame::FindTabFrame() |
1078 | { |
1079 | return IsInTab() ? ImplFindTabFrame() : nullptr; |
1080 | } |
1081 | inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const |
1082 | { |
1083 | return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote ); |
1084 | } |
1085 | inline SwFootnoteFrame *SwFrame::FindFootnoteFrame() |
1086 | { |
1087 | return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr; |
1088 | } |
1089 | inline SwFlyFrame *SwFrame::FindFlyFrame() |
1090 | { |
1091 | return IsInFly() ? ImplFindFlyFrame() : nullptr; |
1092 | } |
1093 | inline SwSectionFrame *SwFrame::FindSctFrame() |
1094 | { |
1095 | return IsInSct() ? ImplFindSctFrame() : nullptr; |
1096 | } |
1097 | |
1098 | inline const SwBodyFrame *SwFrame::FindBodyFrame() const |
1099 | { |
1100 | return IsInDocBody() ? ImplFindBodyFrame() : nullptr; |
1101 | } |
1102 | |
1103 | inline const SwTabFrame *SwFrame::FindTabFrame() const |
1104 | { |
1105 | return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr; |
1106 | } |
1107 | inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const |
1108 | { |
1109 | return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr; |
1110 | } |
1111 | inline const SwFlyFrame *SwFrame::FindFlyFrame() const |
1112 | { |
1113 | return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr; |
1114 | } |
1115 | inline const SwSectionFrame *SwFrame::FindSctFrame() const |
1116 | { |
1117 | return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr; |
1118 | } |
1119 | inline SwFrame *SwFrame::FindNext() |
1120 | { |
1121 | if ( mpNext ) |
1122 | return mpNext; |
1123 | else |
1124 | return FindNext_(); |
1125 | } |
1126 | inline const SwFrame *SwFrame::FindNext() const |
1127 | { |
1128 | if ( mpNext ) |
1129 | return mpNext; |
1130 | else |
1131 | return const_cast<SwFrame*>(this)->FindNext_(); |
1132 | } |
1133 | inline SwFrame *SwFrame::FindPrev() |
1134 | { |
1135 | if ( mpPrev && !mpPrev->IsSctFrame() ) |
1136 | return mpPrev; |
1137 | else |
1138 | return FindPrev_(); |
1139 | } |
1140 | inline const SwFrame *SwFrame::FindPrev() const |
1141 | { |
1142 | if ( mpPrev && !mpPrev->IsSctFrame() ) |
1143 | return mpPrev; |
1144 | else |
1145 | return const_cast<SwFrame*>(this)->FindPrev_(); |
1146 | } |
1147 | |
1148 | inline bool SwFrame::IsLayoutFrame() const |
1149 | { |
1150 | return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF)); |
1151 | } |
1152 | inline bool SwFrame::IsRootFrame() const |
1153 | { |
1154 | return mnFrameType == SwFrameType::Root; |
1155 | } |
1156 | inline bool SwFrame::IsPageFrame() const |
1157 | { |
1158 | return mnFrameType == SwFrameType::Page; |
1159 | } |
1160 | inline bool SwFrame::IsColumnFrame() const |
1161 | { |
1162 | return mnFrameType == SwFrameType::Column; |
1163 | } |
1164 | inline bool SwFrame::IsFootnoteBossFrame() const |
1165 | { |
1166 | return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column)); |
1167 | } |
1168 | inline bool SwFrame::IsHeaderFrame() const |
1169 | { |
1170 | return mnFrameType == SwFrameType::Header; |
1171 | } |
1172 | inline bool SwFrame::IsFooterFrame() const |
1173 | { |
1174 | return mnFrameType == SwFrameType::Footer; |
1175 | } |
1176 | inline bool SwFrame::IsFootnoteContFrame() const |
1177 | { |
1178 | return mnFrameType == SwFrameType::FtnCont; |
1179 | } |
1180 | inline bool SwFrame::IsFootnoteFrame() const |
1181 | { |
1182 | return mnFrameType == SwFrameType::Ftn; |
1183 | } |
1184 | inline bool SwFrame::IsBodyFrame() const |
1185 | { |
1186 | return mnFrameType == SwFrameType::Body; |
1187 | } |
1188 | inline bool SwFrame::IsFlyFrame() const |
1189 | { |
1190 | return mnFrameType == SwFrameType::Fly; |
1191 | } |
1192 | inline bool SwFrame::IsSctFrame() const |
1193 | { |
1194 | return mnFrameType == SwFrameType::Section; |
1195 | } |
1196 | inline bool SwFrame::IsTabFrame() const |
1197 | { |
1198 | return mnFrameType == SwFrameType::Tab; |
1199 | } |
1200 | inline bool SwFrame::IsRowFrame() const |
1201 | { |
1202 | return mnFrameType == SwFrameType::Row; |
1203 | } |
1204 | inline bool SwFrame::IsCellFrame() const |
1205 | { |
1206 | return mnFrameType == SwFrameType::Cell; |
1207 | } |
1208 | inline bool SwFrame::IsContentFrame() const |
1209 | { |
1210 | return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)); |
1211 | } |
1212 | inline bool SwFrame::IsTextFrame() const |
1213 | { |
1214 | return mnFrameType == SwFrameType::Txt; |
1215 | } |
1216 | inline bool SwFrame::IsNoTextFrame() const |
1217 | { |
1218 | return mnFrameType == SwFrameType::NoTxt; |
1219 | } |
1220 | inline bool SwFrame::IsFlowFrame() const |
1221 | { |
1222 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section)); |
1223 | } |
1224 | inline bool SwFrame::IsRetoucheFrame() const |
1225 | { |
1226 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn)); |
1227 | } |
1228 | inline bool SwFrame::IsAccessibleFrame() const |
1229 | { |
1230 | return bool(GetType() & FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType ::Tab | SwFrameType::Cell | SwFrameType::Txt)); |
1231 | } |
1232 | |
1233 | //use this to protect a SwFrame for a given scope from getting deleted |
1234 | class SwFrameDeleteGuard |
1235 | { |
1236 | private: |
1237 | SwFrame *m_pForbidFrame; |
1238 | public: |
1239 | //Flag pFrame for SwFrameDeleteGuard lifetime that we shouldn't delete |
1240 | //it in e.g. SwSectionFrame::MergeNext etc because we will need it |
1241 | //again after the SwFrameDeleteGuard dtor |
1242 | explicit SwFrameDeleteGuard(SwFrame* pFrame) |
1243 | : m_pForbidFrame((pFrame && !pFrame->IsDeleteForbidden()) ? |
1244 | pFrame : nullptr) |
1245 | { |
1246 | if (m_pForbidFrame) |
1247 | m_pForbidFrame->ForbidDelete(); |
1248 | } |
1249 | |
1250 | SwFrameDeleteGuard(const SwFrameDeleteGuard&) =delete; |
1251 | |
1252 | ~SwFrameDeleteGuard() |
1253 | { |
1254 | if (m_pForbidFrame) |
1255 | m_pForbidFrame->AllowDelete(); |
1256 | } |
1257 | |
1258 | SwFrameDeleteGuard& operator=(const SwFrameDeleteGuard&) =delete; |
1259 | }; |
1260 | |
1261 | typedef long (SwFrame::*SwFrameGet)() const; |
1262 | typedef bool (SwFrame::*SwFrameMax)( long ); |
1263 | typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool ); |
1264 | typedef long (*SwOperator)( long, long ); |
1265 | typedef void (SwFrame::*SwFrameSet)( long, long ); |
1266 | |
1267 | struct SwRectFnCollection |
1268 | { |
1269 | SwRectGet fnGetTop; |
1270 | SwRectGet fnGetBottom; |
1271 | SwRectGet fnGetLeft; |
1272 | SwRectGet fnGetRight; |
1273 | SwRectGet fnGetWidth; |
1274 | SwRectGet fnGetHeight; |
1275 | SwRectPoint fnGetPos; |
1276 | SwRectSize fnGetSize; |
1277 | |
1278 | SwRectSet fnSetTop; |
1279 | SwRectSet fnSetBottom; |
1280 | SwRectSet fnSetLeft; |
1281 | SwRectSet fnSetRight; |
1282 | SwRectSet fnSetWidth; |
1283 | SwRectSet fnSetHeight; |
1284 | |
1285 | SwRectSet fnSubTop; |
1286 | SwRectSet fnAddBottom; |
1287 | SwRectSet fnSubLeft; |
1288 | SwRectSet fnAddRight; |
1289 | SwRectSet fnAddWidth; |
1290 | SwRectSet fnAddHeight; |
1291 | |
1292 | SwRectSet fnSetPosX; |
1293 | SwRectSet fnSetPosY; |
1294 | |
1295 | SwFrameGet fnGetTopMargin; |
1296 | SwFrameGet fnGetBottomMargin; |
1297 | SwFrameGet fnGetLeftMargin; |
1298 | SwFrameGet fnGetRightMargin; |
1299 | SwFrameSet fnSetXMargins; |
1300 | SwFrameSet fnSetYMargins; |
1301 | SwFrameGet fnGetPrtTop; |
1302 | SwFrameGet fnGetPrtBottom; |
1303 | SwFrameGet fnGetPrtLeft; |
1304 | SwFrameGet fnGetPrtRight; |
1305 | SwRectDist fnTopDist; |
1306 | SwRectDist fnBottomDist; |
1307 | SwRectDist fnLeftDist; |
1308 | SwRectDist fnRightDist; |
1309 | SwFrameMax fnSetLimit; |
1310 | SwRectMax fnOverStep; |
1311 | |
1312 | SwRectSetPos fnSetPos; |
1313 | SwFrameMakePos fnMakePos; |
1314 | SwOperator fnXDiff; |
1315 | SwOperator fnYDiff; |
1316 | SwOperator fnXInc; |
1317 | SwOperator fnYInc; |
1318 | |
1319 | SwRectSetTwice fnSetLeftAndWidth; |
1320 | SwRectSetTwice fnSetTopAndHeight; |
1321 | }; |
1322 | |
1323 | typedef SwRectFnCollection* SwRectFn; |
1324 | |
1325 | // This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical) |
1326 | extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T; |
1327 | class SwRectFnSet { |
1328 | public: |
1329 | explicit SwRectFnSet(const SwFrame *pFrame) |
1330 | : m_bVert(pFrame->IsVertical()) |
1331 | , m_bVertL2R(pFrame->IsVertLR()) |
1332 | , m_bVertL2RB2T(pFrame->IsVertLRBT()) |
1333 | { |
1334 | m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori; |
1335 | } |
1336 | |
1337 | void Refresh(const SwFrame *pFrame) |
1338 | { |
1339 | m_bVert = pFrame->IsVertical(); |
1340 | m_bVertL2R = pFrame->IsVertLR(); |
1341 | m_bVertL2RB2T = pFrame->IsVertLRBT(); |
1342 | m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori; |
1343 | } |
1344 | |
1345 | bool IsVert() const { return m_bVert; } |
1346 | bool IsVertL2R() const { return m_bVertL2R; } |
1347 | SwRectFn FnRect() const { return m_fnRect; } |
1348 | |
1349 | bool PosDiff(const SwRect &rRect1, const SwRect &rRect2) const |
1350 | { |
1351 | return ((rRect1.*m_fnRect->fnGetTop)() != (rRect2.*m_fnRect->fnGetTop)() |
1352 | || (rRect1.*m_fnRect->fnGetLeft)() != (rRect2.*m_fnRect->fnGetLeft)()); |
1353 | } |
1354 | |
1355 | long GetTop (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetTop) (); } |
1356 | long GetBottom(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetBottom)(); } |
1357 | long GetLeft (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetLeft) (); } |
1358 | long GetRight (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetRight) (); } |
1359 | long GetWidth (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetWidth) (); } |
1360 | long GetHeight(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetHeight)(); } |
1361 | Point GetPos (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetPos) (); } |
1362 | Size GetSize (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetSize) (); } |
1363 | |
1364 | void SetTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetTop) (nNew); } |
1365 | void SetBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetBottom)(nNew); } |
1366 | void SetLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetLeft) (nNew); } |
1367 | void SetRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetRight) (nNew); } |
1368 | void SetWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetWidth) (nNew); } |
1369 | void SetHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetHeight)(nNew); } |
1370 | |
1371 | void SubTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubTop) (nNew); } |
1372 | void AddBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddBottom)(nNew); } |
1373 | void SubLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubLeft) (nNew); } |
1374 | void AddRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddRight) (nNew); } |
1375 | void AddWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddWidth) (nNew); } |
1376 | void AddHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddHeight)(nNew); } |
1377 | |
1378 | void SetPosX(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosX)(nNew); } |
1379 | void SetPosY(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosY)(nNew); } |
1380 | |
1381 | long GetTopMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetTopMargin) (); } |
1382 | long GetBottomMargin(const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetBottomMargin)(); } |
1383 | long GetLeftMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetLeftMargin) (); } |
1384 | long GetRightMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetRightMargin) (); } |
1385 | void SetXMargins(SwFrame& rFrame, long nLeft, long nRight) const { (rFrame.*m_fnRect->fnSetXMargins)(nLeft, nRight); } |
1386 | void SetYMargins(SwFrame& rFrame, long nTop, long nBottom) const { (rFrame.*m_fnRect->fnSetYMargins)(nTop, nBottom); } |
1387 | long GetPrtTop (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtTop) (); } |
1388 | long GetPrtBottom (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtBottom) (); } |
1389 | long GetPrtLeft (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtLeft) (); } |
1390 | long GetPrtRight (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtRight) (); } |
1391 | long TopDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnTopDist) (nPos); } |
1392 | long BottomDist(const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnBottomDist) (nPos); } |
1393 | long LeftDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnLeftDist) (nPos); } |
1394 | long RightDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnRightDist) (nPos); } |
1395 | void SetLimit (SwFrame& rFrame, long nNew) const { (rFrame.*m_fnRect->fnSetLimit) (nNew); } |
1396 | bool OverStep (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnOverStep) (nPos); } |
1397 | |
1398 | void SetPos(SwRect& rRect, const Point& rNew) const { (rRect.*m_fnRect->fnSetPos)(rNew); } |
1399 | void MakePos(SwFrame& rFrame, const SwFrame* pUp, const SwFrame* pPrv, bool bNotify) const { (rFrame.*m_fnRect->fnMakePos)(pUp, pPrv, bNotify); } |
1400 | long XDiff(long n1, long n2) const { return (m_fnRect->fnXDiff) (n1, n2); } |
1401 | long YDiff(long n1, long n2) const { return (m_fnRect->fnYDiff) (n1, n2); } |
1402 | long XInc (long n1, long n2) const { return (m_fnRect->fnXInc) (n1, n2); } |
1403 | long YInc (long n1, long n2) const { return (m_fnRect->fnYInc) (n1, n2); } |
1404 | |
1405 | void SetLeftAndWidth(SwRect& rRect, long nLeft, long nWidth) const { (rRect.*m_fnRect->fnSetLeftAndWidth)(nLeft, nWidth); } |
1406 | void SetTopAndHeight(SwRect& rRect, long nTop, long nHeight) const { (rRect.*m_fnRect->fnSetTopAndHeight)(nTop, nHeight); } |
1407 | |
1408 | private: |
1409 | bool m_bVert; |
1410 | bool m_bVertL2R; |
1411 | bool m_bVertL2RB2T; |
1412 | SwRectFn m_fnRect; |
1413 | }; |
1414 | |
1415 | #endif |
1416 | |
1417 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |