Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx
Warning:line 1458, column 12
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pagepreviewlayout.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx
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 <pagepreviewlayout.hxx>
21#include <prevwpage.hxx>
22
23#include <algorithm>
24#include <tools/fract.hxx>
25#include <vcl/window.hxx>
26#include <vcl/settings.hxx>
27
28#include <rootfrm.hxx>
29#include <pagefrm.hxx>
30#include <viewsh.hxx>
31#include <viewimp.hxx>
32#include <viewopt.hxx>
33#include <swregion.hxx>
34#include <strings.hrc>
35#include <frmtool.hxx>
36#include <sfx2/zoomitem.hxx>
37#include <printdata.hxx>
38#include <paintfrm.hxx>
39
40#include <IDocumentDeviceAccess.hxx>
41
42// methods to initialize page preview layout
43
44SwPagePreviewLayout::SwPagePreviewLayout( SwViewShell& _rParentViewShell,
45 const SwRootFrame& _rLayoutRootFrame )
46 : mrParentViewShell( _rParentViewShell ),
47 mrLayoutRootFrame ( _rLayoutRootFrame )
48{
49 Clear_();
50
51 mbBookPreview = false;
52 mbBookPreviewModeToggled = false;
53
54 mbPrintEmptyPages = mrParentViewShell.getIDocumentDeviceAccess().getPrintData().IsPrintEmptyPages();
55}
56
57void SwPagePreviewLayout::Clear_()
58{
59 mbLayoutInfoValid = mbLayoutSizesValid = mbPaintInfoValid = false;
60
61 maWinSize.setWidth( 0 );
62 maWinSize.setHeight( 0 );
63 mnCols = mnRows = 0;
64
65 ClearPreviewLayoutSizes();
66
67 mbDoesLayoutRowsFitIntoWindow = false;
68 mbDoesLayoutColsFitIntoWindow = false;
69
70 mnPaintPhyStartPageNum = 0;
71 mnPaintStartCol = mnPaintStartRow = 0;
72 mbNoPageVisible = false;
73 maPaintStartPageOffset.setX( 0 );
74 maPaintStartPageOffset.setY( 0 );
75 maPaintPreviewDocOffset.setX( 0 );
76 maPaintPreviewDocOffset.setY( 0 );
77 maAdditionalPaintOffset.setX( 0 );
78 maAdditionalPaintOffset.setY( 0 );
79 maPaintedPreviewDocRect.SetLeft( 0 );
80 maPaintedPreviewDocRect.SetTop( 0 );
81 maPaintedPreviewDocRect.SetRight( 0 );
82 maPaintedPreviewDocRect.SetBottom( 0 );
83 mnSelectedPageNum = 0;
84 ClearPreviewPageData();
85
86 mbInPaint = false;
87 mbNewLayoutDuringPaint = false;
88}
89
90void SwPagePreviewLayout::ClearPreviewLayoutSizes()
91{
92 mnPages = 0;
93
94 maMaxPageSize.setWidth( 0 );
95 maMaxPageSize.setHeight( 0 );
96 maPreviewDocRect.SetLeft( 0 );
97 maPreviewDocRect.SetTop( 0 );
98 maPreviewDocRect.SetRight( 0 );
99 maPreviewDocRect.SetBottom( 0 );
100 mnColWidth = mnRowHeight = 0;
101 mnPreviewLayoutWidth = mnPreviewLayoutHeight = 0;
102}
103
104void SwPagePreviewLayout::ClearPreviewPageData()
105{
106 maPreviewPages.clear();
107}
108
109/** calculate page preview layout sizes
110
111*/
112void SwPagePreviewLayout::CalcPreviewLayoutSizes()
113{
114 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
115 // calculate maximal page size; calculate also number of pages
116
117 const SwPageFrame* pPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
118 while ( pPage )
119 {
120 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
121 {
122 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
123 continue;
124 }
125
126 ++mnPages;
127 pPage->Calc(pRenderContext);
128 const Size& rPageSize = pPage->getFrameArea().SSize();
129 if ( rPageSize.Width() > maMaxPageSize.Width() )
130 maMaxPageSize.setWidth( rPageSize.Width() );
131 if ( rPageSize.Height() > maMaxPageSize.Height() )
132 maMaxPageSize.setHeight( rPageSize.Height() );
133 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
134 }
135 // calculate and set column width and row height
136 mnColWidth = maMaxPageSize.Width() + gnXFree;
137 mnRowHeight = maMaxPageSize.Height() + gnYFree;
138
139 // calculate and set preview layout width and height
140 mnPreviewLayoutWidth = mnCols * mnColWidth + gnXFree;
141 mnPreviewLayoutHeight = mnRows * mnRowHeight + gnYFree;
142
143 // calculate document rectangle in preview layout
144 {
145 Size aDocSize;
146 // document width
147 aDocSize.setWidth( mnPreviewLayoutWidth );
148
149 // document height
150 // determine number of rows needed for <nPages> in preview layout
151 // use method <GetRowOfPage(..)>.
152 const sal_uInt16 nDocRows = GetRowOfPage( mnPages );
153 aDocSize.setHeight( nDocRows * maMaxPageSize.Height() +
154 (nDocRows+1) * gnYFree );
155 maPreviewDocRect.SetPos( Point( 0, 0 ) );
156 maPreviewDocRect.SetSize( aDocSize );
157 }
158}
159
160/** init page preview layout
161
162 initialize the page preview settings for a given layout.
163
164 side effects:
165 (1) If parameter <_bCalcScale> is true, mapping mode with calculated
166 scaling is set at the output device and the zoom at the view options of
167 the given view shell is set with the calculated scaling.
168*/
169void SwPagePreviewLayout::Init( const sal_uInt16 _nCols,
170 const sal_uInt16 _nRows,
171 const Size& _rPxWinSize
172 )
173{
174 // check environment and parameters
175 {
176 bool bColsRowsValid = (_nCols != 0) && (_nRows != 0);
177 OSL_ENSURE( bColsRowsValid, "preview layout parameters not correct - preview layout can *not* be initialized" )do { if (true && (!(bColsRowsValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "177" ": "), "%s", "preview layout parameters not correct - preview layout can *not* be initialized"
); } } while (false)
;
178 if ( !bColsRowsValid )
179 return;
180
181 bool bPxWinSizeValid = (_rPxWinSize.Width() >= 0) &&
182 (_rPxWinSize.Height() >= 0);
183 OSL_ENSURE( bPxWinSizeValid, "no window size - preview layout can *not* be initialized" )do { if (true && (!(bPxWinSizeValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "183" ": "), "%s", "no window size - preview layout can *not* be initialized"
); } } while (false)
;
184 if ( !bPxWinSizeValid )
185 return;
186 }
187
188 // environment and parameters ok
189
190 // clear existing preview settings
191 Clear_();
192
193 // set layout information columns and rows
194 mnCols = _nCols;
195 mnRows = _nRows;
196
197 CalcPreviewLayoutSizes();
198
199 // validate layout information
200 mbLayoutInfoValid = true;
201
202 // calculate scaling
203 MapMode aMapMode( MapUnit::MapTwip );
204 Size aWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize, aMapMode );
205 Fraction aXScale( aWinSize.Width(), mnPreviewLayoutWidth );
206 Fraction aYScale( aWinSize.Height(), mnPreviewLayoutHeight );
207 if( aXScale < aYScale )
208 aYScale = aXScale;
209 {
210 // adjust scaling for Drawing layer.
211 aYScale *= Fraction( 1000, 1 );
212 long nNewNuminator = aYScale.operator long();
213 if( nNewNuminator < 1 )
214 nNewNuminator = 1;
215 aYScale = Fraction( nNewNuminator, 1000 );
216 // propagate scaling as zoom percentage to view options for font cache
217 ApplyNewZoomAtViewShell( static_cast<sal_uInt8>(nNewNuminator/10) );
218
219 aMapMode.SetScaleY( aYScale );
220 aMapMode.SetScaleX( aYScale );
221 // set created mapping mode with calculated scaling at output device.
222 mrParentViewShell.GetOut()->SetMapMode( aMapMode );
223 // update statics for paint.
224 ::SwCalcPixStatics( mrParentViewShell.GetOut() );
225 }
226
227 // set window size in twips
228 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
229 // validate layout sizes
230 mbLayoutSizesValid = true;
231}
232
233/** apply new zoom at given view shell */
234void SwPagePreviewLayout::ApplyNewZoomAtViewShell( sal_uInt8 _aNewZoom )
235{
236 SwViewOption aNewViewOptions = *(mrParentViewShell.GetViewOptions());
237 if ( aNewViewOptions.GetZoom() != _aNewZoom )
238 {
239 aNewViewOptions.SetZoom( _aNewZoom );
240 //#i19975# - consider zoom type.
241 aNewViewOptions.SetZoomType( SvxZoomType::PERCENT );
242 mrParentViewShell.ApplyViewOptions( aNewViewOptions );
243 }
244}
245
246/** method to adjust page preview layout to document changes
247
248*/
249void SwPagePreviewLayout::ReInit()
250{
251 // check environment and parameters
252 {
253 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
254 OSL_ENSURE( bLayoutSettingsValid,do { if (true && (!(bLayoutSettingsValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "255" ": "), "%s", "no valid preview layout info/sizes - no re-init of page preview layout"
); } } while (false)
255 "no valid preview layout info/sizes - no re-init of page preview layout")do { if (true && (!(bLayoutSettingsValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "255" ": "), "%s", "no valid preview layout info/sizes - no re-init of page preview layout"
); } } while (false)
;
256 if ( !bLayoutSettingsValid )
257 return;
258 }
259
260 ClearPreviewLayoutSizes();
261 CalcPreviewLayoutSizes();
262}
263
264// methods to prepare paint of page preview
265
266/** prepare paint of page preview
267
268 delete parameter _onStartPageVirtNum
269
270 @note _nProposedStartPageNum, _onStartPageNum are absolute
271*/
272bool SwPagePreviewLayout::Prepare( const sal_uInt16 _nProposedStartPageNum,
273 const Point& rProposedStartPos,
274 const Size& _rPxWinSize,
275 sal_uInt16& _onStartPageNum,
276 tools::Rectangle& _orDocPreviewPaintRect,
277 const bool _bStartWithPageAtFirstCol
278 )
279{
280 sal_uInt16 nProposedStartPageNum = ConvertAbsoluteToRelativePageNum( _nProposedStartPageNum );
281 // check environment and parameters
282 {
283 bool bLayoutSettingsValid = mbLayoutInfoValid && mbLayoutSizesValid;
284 OSL_ENSURE( bLayoutSettingsValid,do { if (true && (!(bLayoutSettingsValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "285" ": "), "%s", "no valid preview layout info/sizes - no prepare of preview paint"
); } } while (false)
285 "no valid preview layout info/sizes - no prepare of preview paint")do { if (true && (!(bLayoutSettingsValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "285" ": "), "%s", "no valid preview layout info/sizes - no prepare of preview paint"
); } } while (false)
;
286 if ( !bLayoutSettingsValid )
287 return false;
288
289 bool bStartPageRangeValid = nProposedStartPageNum <= mnPages;
290 OSL_ENSURE( bStartPageRangeValid,do { if (true && (!(bStartPageRangeValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "291" ": "), "%s", "proposed start page not existing - no prepare of preview paint"
); } } while (false)
291 "proposed start page not existing - no prepare of preview paint")do { if (true && (!(bStartPageRangeValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "291" ": "), "%s", "proposed start page not existing - no prepare of preview paint"
); } } while (false)
;
292 if ( !bStartPageRangeValid )
293 return false;
294
295 bool bStartPosRangeValid =
296 rProposedStartPos.X() >= 0 && rProposedStartPos.Y() >= 0 &&
297 rProposedStartPos.X() <= maPreviewDocRect.Right() &&
298 rProposedStartPos.Y() <= maPreviewDocRect.Bottom();
299 OSL_ENSURE( bStartPosRangeValid,do { if (true && (!(bStartPosRangeValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "300" ": "), "%s", "proposed start position out of range - no prepare of preview paint"
); } } while (false)
300 "proposed start position out of range - no prepare of preview paint")do { if (true && (!(bStartPosRangeValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "300" ": "), "%s", "proposed start position out of range - no prepare of preview paint"
); } } while (false)
;
301 if ( !bStartPosRangeValid )
302 return false;
303
304 bool bWinSizeValid = !_rPxWinSize.IsEmpty();
305 OSL_ENSURE( bWinSizeValid, "no window size - no prepare of preview paint")do { if (true && (!(bWinSizeValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "305" ": "), "%s", "no window size - no prepare of preview paint"
); } } while (false)
;
306 if ( !bWinSizeValid )
307 return false;
308
309 bool bStartInfoValid = _nProposedStartPageNum > 0 ||
310 rProposedStartPos != Point(0,0);
311 if ( !bStartInfoValid )
312 nProposedStartPageNum = 1;
313 }
314
315 // environment and parameter ok
316
317 // update window size at preview setting data
318 maWinSize = mrParentViewShell.GetOut()->PixelToLogic( _rPxWinSize );
319
320 mbNoPageVisible = false;
321 if ( nProposedStartPageNum > 0 )
322 {
323 // determine column and row of proposed start page in virtual preview layout
324 const sal_uInt16 nColOfProposed = GetColOfPage( nProposedStartPageNum );
325 const sal_uInt16 nRowOfProposed = GetRowOfPage( nProposedStartPageNum );
326 // determine start page
327 if ( _bStartWithPageAtFirstCol )
328 {
329 // leaving left-top-corner blank is
330 // controlled by <mbBookPreview>.
331 if ( mbBookPreview &&
332 ( nProposedStartPageNum == 1 || nRowOfProposed == 1 )
333 )
334 mnPaintPhyStartPageNum = 1;
335 else
336 mnPaintPhyStartPageNum = nProposedStartPageNum - (nColOfProposed-1);
337 }
338 else
339 mnPaintPhyStartPageNum = nProposedStartPageNum;
340
341 mnPaintPhyStartPageNum = ConvertRelativeToAbsolutePageNum( mnPaintPhyStartPageNum );
342
343 // set starting column
344 if ( _bStartWithPageAtFirstCol )
345 mnPaintStartCol = 1;
346 else
347 mnPaintStartCol = nColOfProposed;
348 // set starting row
349 mnPaintStartRow = nRowOfProposed;
350 // page offset == (-1,-1), indicating no offset and paint of free space.
351 maPaintStartPageOffset.setX( -1 );
352 maPaintStartPageOffset.setY( -1 );
353 // virtual preview document offset.
354 if ( _bStartWithPageAtFirstCol )
355 maPaintPreviewDocOffset.setX( 0 );
356 else
357 maPaintPreviewDocOffset.setX( (nColOfProposed-1) * mnColWidth );
358 maPaintPreviewDocOffset.setY( (nRowOfProposed-1) * mnRowHeight );
359 }
360 else
361 {
362 // determine column and row of proposed start position.
363 // Note: paint starts at point (0,0)
364 const sal_uInt16 nColOfProposed =
365 static_cast<sal_uInt16>(rProposedStartPos.X() / mnColWidth) + 1;
366 const sal_uInt16 nRowOfProposed =
367 static_cast<sal_uInt16>(rProposedStartPos.Y() / mnRowHeight) + 1;
368 // determine start page == page at proposed start position
369 // leaving left-top-corner blank is
370 // controlled by <mbBookPreview>.
371 if ( mbBookPreview &&
372 ( nRowOfProposed == 1 && nColOfProposed == 1 )
373 )
374 mnPaintPhyStartPageNum = 1;
375 else
376 {
377 // leaving left-top-corner blank is
378 // controlled by <mbBookPreview>.
379 mnPaintPhyStartPageNum = (nRowOfProposed-1) * mnCols + nColOfProposed;
380 if ( mbBookPreview )
381 --mnPaintPhyStartPageNum;
382 if ( mnPaintPhyStartPageNum > mnPages )
383 {
384 // no page will be visible, because shown part of document
385 // preview is the last row to the right of the last page
386 mnPaintPhyStartPageNum = mnPages;
387 mbNoPageVisible = true;
388 }
389 }
390 // set starting column and starting row
391 mnPaintStartCol = nColOfProposed;
392 mnPaintStartRow = nRowOfProposed;
393 // page offset
394 maPaintStartPageOffset.setX(
395 (rProposedStartPos.X() % mnColWidth) - gnXFree );
396 maPaintStartPageOffset.setY(
397 (rProposedStartPos.Y() % mnRowHeight) - gnYFree );
398 // virtual preview document offset.
399 maPaintPreviewDocOffset = rProposedStartPos;
400 }
401
402 // determine additional paint offset, if preview layout fits into window.
403 CalcAdditionalPaintOffset();
404
405 // determine rectangle to be painted from document preview
406 CalcDocPreviewPaintRect();
407 _orDocPreviewPaintRect = maPaintedPreviewDocRect;
408
409 // shift visible preview document area to the left,
410 // if on the right is an area left blank.
411 if ( !mbDoesLayoutColsFitIntoWindow &&
412 maPaintedPreviewDocRect.GetWidth() < maWinSize.Width() )
413 {
414 maPaintedPreviewDocRect.Move(
415 -(maWinSize.Width() - maPaintedPreviewDocRect.GetWidth()), 0 );
416 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
417 _rPxWinSize, _onStartPageNum,
418 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
419 }
420
421 // shift visible preview document area to the top,
422 // if on the bottom is an area left blank.
423 if ( mbBookPreviewModeToggled &&
424 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom() &&
425 maPaintedPreviewDocRect.GetHeight() < maWinSize.Height() )
426 {
427 if ( mbDoesLayoutRowsFitIntoWindow )
428 {
429 if ( maPaintedPreviewDocRect.GetHeight() < mnPreviewLayoutHeight)
430 {
431 maPaintedPreviewDocRect.Move(
432 0, -(mnPreviewLayoutHeight - maPaintedPreviewDocRect.GetHeight()) );
433 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
434 _rPxWinSize, _onStartPageNum,
435 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
436 }
437 }
438 else
439 {
440 maPaintedPreviewDocRect.Move(
441 0, -(maWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) );
442 Prepare( 0, maPaintedPreviewDocRect.TopLeft(),
443 _rPxWinSize, _onStartPageNum,
444 _orDocPreviewPaintRect, _bStartWithPageAtFirstCol );
445 }
446 }
447
448 // determine preview pages - visible pages with needed data for paint and
449 // accessible pages with needed data.
450 CalcPreviewPages();
451
452 // OD 07.11.2003 #i22014# - indicate new layout, if print preview is in paint
453 if ( mbInPaint )
454 {
455 mbNewLayoutDuringPaint = true;
456 }
457
458 // validate paint data
459 mbPaintInfoValid = true;
460
461 // return start page
462 _onStartPageNum = mnPaintPhyStartPageNum;
463
464 return true;
465}
466
467/** calculate additional paint offset
468
469*/
470void SwPagePreviewLayout::CalcAdditionalPaintOffset()
471{
472 if ( mnPreviewLayoutWidth <= maWinSize.Width() &&
473 maPaintStartPageOffset.X() <= 0 )
474 {
475 mbDoesLayoutColsFitIntoWindow = true;
476 maAdditionalPaintOffset.setX( (maWinSize.Width() - mnPreviewLayoutWidth) / 2 );
477 }
478 else
479 {
480 mbDoesLayoutColsFitIntoWindow = false;
481 maAdditionalPaintOffset.setX( 0 );
482 }
483
484 if ( mnPreviewLayoutHeight <= maWinSize.Height() &&
485 maPaintStartPageOffset.Y() <= 0 )
486 {
487 mbDoesLayoutRowsFitIntoWindow = true;
488 maAdditionalPaintOffset.setY( (maWinSize.Height() - mnPreviewLayoutHeight) / 2 );
489 }
490 else
491 {
492 mbDoesLayoutRowsFitIntoWindow = false;
493 maAdditionalPaintOffset.setY( 0 );
494 }
495}
496
497/** calculate painted preview document rectangle
498
499*/
500void SwPagePreviewLayout::CalcDocPreviewPaintRect()
501{
502 Point aTopLeftPos = maPaintPreviewDocOffset;
503 maPaintedPreviewDocRect.SetPos( aTopLeftPos );
504
505 Size aSize;
506 if ( mbDoesLayoutColsFitIntoWindow )
507 aSize.setWidth( std::min( mnPreviewLayoutWidth,
508 maPreviewDocRect.GetWidth() - aTopLeftPos.X() ) );
509 else
510 aSize.setWidth( std::min( maPreviewDocRect.GetWidth() - aTopLeftPos.X(),
511 maWinSize.Width() - maAdditionalPaintOffset.X() ) );
512 if ( mbDoesLayoutRowsFitIntoWindow )
513 aSize.setHeight( std::min( mnPreviewLayoutHeight,
514 maPreviewDocRect.GetHeight() - aTopLeftPos.Y() ) );
515 else
516 aSize.setHeight( std::min( maPreviewDocRect.GetHeight() - aTopLeftPos.Y(),
517 maWinSize.Height() - maAdditionalPaintOffset.Y() ) );
518 maPaintedPreviewDocRect.SetSize( aSize );
519}
520
521/** calculate preview pages
522
523*/
524void SwPagePreviewLayout::CalcPreviewPages()
525{
526 vcl::RenderContext* pRenderContext = mrParentViewShell.GetOut();
527 ClearPreviewPageData();
528
529 if ( mbNoPageVisible )
530 return;
531
532 // determine start page frame
533 const SwPageFrame* pStartPage = mrLayoutRootFrame.GetPageByPageNum( mnPaintPhyStartPageNum );
534
535 // calculate initial paint offset
536 Point aInitialPaintOffset;
537 /// check whether RTL interface or not
538 if(!AllSettings::GetLayoutRTL()){
539 if ( maPaintStartPageOffset != Point( -1, -1 ) )
540 aInitialPaintOffset = Point(0,0) - maPaintStartPageOffset;
541 else
542 aInitialPaintOffset = Point( gnXFree, gnYFree );
543 }
544 else {
545 if ( maPaintStartPageOffset != Point( -1, -1 ) )
546 aInitialPaintOffset = Point(0 + ((SwPagePreviewLayout::mnCols-1)*mnColWidth),0) - maPaintStartPageOffset;
547 else
548 aInitialPaintOffset = Point( gnXFree + ((SwPagePreviewLayout::mnCols-1)*mnColWidth), gnYFree );
549 }
550 aInitialPaintOffset += maAdditionalPaintOffset;
551
552 // prepare loop data
553 const SwPageFrame* pPage = pStartPage;
554 sal_uInt16 nCurrCol = mnPaintStartCol;
555 sal_uInt16 nConsideredRows = 0;
556 Point aCurrPaintOffset = aInitialPaintOffset;
557 // loop on pages to determine preview background rectangles
558 while ( pPage &&
559 (!mbDoesLayoutRowsFitIntoWindow || nConsideredRows < mnRows) &&
560 aCurrPaintOffset.Y() < maWinSize.Height()
561 )
562 {
563 if ( !mbBookPreview && !mbPrintEmptyPages && pPage->IsEmptyPage() )
564 {
565 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
566 continue;
567 }
568
569 pPage->Calc(pRenderContext);
570
571 // consider only pages, which have to be painted.
572 if ( nCurrCol < mnPaintStartCol )
573 {
574 // calculate data of unvisible page needed for accessibility
575 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
576 Point aCurrAccOffset = aCurrPaintOffset -
577 Point( (mnPaintStartCol-nCurrCol) * mnColWidth, 0 );
578 CalcPreviewDataForPage( *pPage, aCurrAccOffset, pPreviewPage.get() );
579 pPreviewPage->bVisible = false;
580 maPreviewPages.push_back( std::move(pPreviewPage) );
581 // continue with next page and next column
582 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
583 ++nCurrCol;
584 continue;
585 }
586 if ( aCurrPaintOffset.X() < maWinSize.Width() )
587 {
588 // leaving left-top-corner blank is
589 // controlled by <mbBookPreview>.
590 if ( mbBookPreview && pPage->GetPhyPageNum() == 1 && mnCols != 1 && nCurrCol == 1
591 )
592 {
593 // first page in 2nd column
594 // --> continue with increased paint offset and next column
595 /// check whether RTL interface or not
596 if(!AllSettings::GetLayoutRTL())
597 aCurrPaintOffset.AdjustX(mnColWidth );
598 else aCurrPaintOffset.AdjustX( -mnColWidth );
599 ++nCurrCol;
600 continue;
601 }
602
603 // calculate data of visible page
604 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
605 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
606 pPreviewPage->bVisible = true;
607 maPreviewPages.push_back( std::move(pPreviewPage) );
608 }
609 else
610 {
611 // calculate data of unvisible page needed for accessibility
612 std::unique_ptr<PreviewPage> pPreviewPage(new PreviewPage);
613 CalcPreviewDataForPage( *pPage, aCurrPaintOffset, pPreviewPage.get() );
614 pPreviewPage->bVisible = false;
615 maPreviewPages.push_back( std::move(pPreviewPage) );
616 }
617
618 // prepare data for next loop
619 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
620
621 /// check whether RTL interface or not
622 if(!AllSettings::GetLayoutRTL())
623 aCurrPaintOffset.AdjustX(mnColWidth );
624 else aCurrPaintOffset.AdjustX( -mnColWidth );
625 ++nCurrCol;
626 if ( nCurrCol > mnCols )
627 {
628 ++nConsideredRows;
629 aCurrPaintOffset.setX( aInitialPaintOffset.X() );
630 nCurrCol = 1;
631 aCurrPaintOffset.AdjustY(mnRowHeight );
632 }
633 }
634}
635
636/** determines preview data for a given page and a given preview offset
637
638 OD 13.12.2002 #103492#
639*/
640void SwPagePreviewLayout::CalcPreviewDataForPage( const SwPageFrame& _rPage,
641 const Point& _rPreviewOffset,
642 PreviewPage* _opPreviewPage )
643{
644 // page frame
645 _opPreviewPage->pPage = &_rPage;
646 // size of page frame
647 if ( _rPage.IsEmptyPage() )
648 {
649 if ( _rPage.GetPhyPageNum() % 2 == 0 )
650 _opPreviewPage->aPageSize = _rPage.GetPrev()->getFrameArea().SSize();
651 else
652 _opPreviewPage->aPageSize = _rPage.GetNext()->getFrameArea().SSize();
653 }
654 else
655 _opPreviewPage->aPageSize = _rPage.getFrameArea().SSize();
656 // position of page in preview window
657 Point aPreviewWinOffset( _rPreviewOffset );
658 if ( _opPreviewPage->aPageSize.Width() < maMaxPageSize.Width() )
659 aPreviewWinOffset.AdjustX(( maMaxPageSize.Width() - _opPreviewPage->aPageSize.Width() ) / 2 );
660 if ( _opPreviewPage->aPageSize.Height() < maMaxPageSize.Height() )
661 aPreviewWinOffset.AdjustY(( maMaxPageSize.Height() - _opPreviewPage->aPageSize.Height() ) / 2 );
662 _opPreviewPage->aPreviewWinPos = aPreviewWinOffset;
663 // logic position of page and mapping offset for paint
664 if ( _rPage.IsEmptyPage() )
665 {
666 _opPreviewPage->aLogicPos = _opPreviewPage->aPreviewWinPos;
667 _opPreviewPage->aMapOffset = Point( 0, 0 );
668 }
669 else
670 {
671 _opPreviewPage->aLogicPos = _rPage.getFrameArea().Pos();
672 _opPreviewPage->aMapOffset = _opPreviewPage->aPreviewWinPos - _opPreviewPage->aLogicPos;
673 }
674}
675
676/** enable/disable book preview
677
678 OD 2004-03-04 #i18143#
679*/
680bool SwPagePreviewLayout::SetBookPreviewMode( const bool _bEnableBookPreview,
681 sal_uInt16& _onStartPageNum,
682 tools::Rectangle& _orDocPreviewPaintRect )
683{
684 if ( mbBookPreview != _bEnableBookPreview)
685 {
686 mbBookPreview = _bEnableBookPreview;
687 // re-initialize page preview layout
688 ReInit();
689 // re-prepare page preview layout
690 {
691 mbBookPreviewModeToggled = true;
692 Point aProposedStartPos( maPaintPreviewDocOffset );
693 // if proposed start position is below virtual preview document
694 // bottom, adjust it to the virtual preview document bottom
695 if ( aProposedStartPos.Y() > maPreviewDocRect.Bottom() )
696 {
697 aProposedStartPos.setY( maPreviewDocRect.Bottom() );
698 }
699 Prepare( 0, aProposedStartPos,
700 mrParentViewShell.GetOut()->LogicToPixel( maWinSize ),
701 _onStartPageNum, _orDocPreviewPaintRect );
702 mbBookPreviewModeToggled = false;
703 }
704
705 return true;
706 }
707
708 return false;
709}
710
711// methods to determine new data for changing the current shown part of the
712// document preview.
713
714/** calculate start position for new scale
715
716*/
717Point SwPagePreviewLayout::GetPreviewStartPosForNewScale(
718 const Fraction& _aNewScale,
719 const Fraction& _aOldScale,
720 const Size& _aNewWinSize ) const
721{
722 Point aNewPaintStartPos = maPaintedPreviewDocRect.TopLeft();
723 if ( _aNewScale < _aOldScale )
724 {
725 // increase paint width by moving start point to left.
726 if ( mnPreviewLayoutWidth < _aNewWinSize.Width() )
727 aNewPaintStartPos.setX( 0 );
728 else if ( maPaintedPreviewDocRect.GetWidth() < _aNewWinSize.Width() )
729 {
730 aNewPaintStartPos.AdjustX( -(
731 (_aNewWinSize.Width() - maPaintedPreviewDocRect.GetWidth()) / 2) );
732 if ( aNewPaintStartPos.X() < 0)
733 aNewPaintStartPos.setX( 0 );
734 }
735
736 if ( !mbDoesLayoutRowsFitIntoWindow )
737 {
738 // increase paint height by moving start point to top.
739 if ( mnPreviewLayoutHeight < _aNewWinSize.Height() )
740 {
741 aNewPaintStartPos.setY(
742 (mnPaintStartRow - 1) * mnRowHeight );
743 }
744 else if ( maPaintedPreviewDocRect.GetHeight() < _aNewWinSize.Height() )
745 {
746 aNewPaintStartPos.AdjustY( -(
747 (_aNewWinSize.Height() - maPaintedPreviewDocRect.GetHeight()) / 2) );
748 if ( aNewPaintStartPos.Y() < 0)
749 aNewPaintStartPos.setY( 0 );
750 }
751 }
752 }
753 else
754 {
755 // decrease paint width by moving start point to right
756 if ( maPaintedPreviewDocRect.GetWidth() > _aNewWinSize.Width() )
757 aNewPaintStartPos.AdjustX(
758 (maPaintedPreviewDocRect.GetWidth() - _aNewWinSize.Width()) / 2 );
759 // decrease paint height by moving start point to bottom
760 if ( maPaintedPreviewDocRect.GetHeight() > _aNewWinSize.Height() )
761 {
762 aNewPaintStartPos.AdjustY(
763 (maPaintedPreviewDocRect.GetHeight() - _aNewWinSize.Height()) / 2 );
764 // check, if new y-position is outside document preview
765 if ( aNewPaintStartPos.Y() > maPreviewDocRect.Bottom() )
766 aNewPaintStartPos.setY(
767 std::max( 0L, maPreviewDocRect.Bottom() - mnPreviewLayoutHeight ) );
768 }
769 }
770
771 return aNewPaintStartPos;
772}
773
774/** determines, if page with given page number is visible in preview
775
776 @note _nPageNum is absolute
777*/
778bool SwPagePreviewLayout::IsPageVisible( const sal_uInt16 _nPageNum ) const
779{
780 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
781 return pPreviewPage && pPreviewPage->bVisible;
782}
783
784/** calculate data to bring new selected page into view.
785
786 @note IN/OUT parameters are absolute page numbers!!!
787*/
788void SwPagePreviewLayout::CalcStartValuesForSelectedPageMove(
789 const sal_Int16 _nHoriMove,
790 const sal_Int16 _nVertMove,
791 sal_uInt16& _orNewSelectedPage,
792 sal_uInt16& _orNewStartPage,
793 Point& _orNewStartPos ) const
794{
795 // determine position of current selected page
796 sal_uInt16 nTmpRelSelPageNum = ConvertAbsoluteToRelativePageNum( mnSelectedPageNum );
1
Calling 'SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum'
8
Returning from 'SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum'
797 sal_uInt16 nNewRelSelectedPageNum = nTmpRelSelPageNum;
798
799 const sal_uInt16 nCurrRow = GetRowOfPage(nTmpRelSelPageNum);
800
801 // determine new selected page number
802 {
803 if ( _nHoriMove != 0 )
9
Assuming '_nHoriMove' is equal to 0
10
Taking false branch
804 {
805 if ( (nNewRelSelectedPageNum + _nHoriMove) < 1 )
806 nNewRelSelectedPageNum = 1;
807 else if ( (nNewRelSelectedPageNum + _nHoriMove) > mnPages )
808 nNewRelSelectedPageNum = mnPages;
809 else
810 nNewRelSelectedPageNum = nNewRelSelectedPageNum + _nHoriMove;
811 }
812 if ( _nVertMove != 0 )
11
Assuming '_nVertMove' is equal to 0
12
Taking false branch
813 {
814 if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) < 1 )
815 nNewRelSelectedPageNum = 1;
816 else if ( (nNewRelSelectedPageNum + (_nVertMove * mnCols)) > mnPages )
817 nNewRelSelectedPageNum = mnPages;
818 else
819 nNewRelSelectedPageNum += ( _nVertMove * mnCols );
820 }
821 }
822
823 sal_uInt16 nNewStartPage = mnPaintPhyStartPageNum;
824 Point aNewStartPos(0,0);
825
826 const sal_uInt16 nNewAbsSelectedPageNum = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
13
Calling 'SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum'
827 if ( !IsPageVisible( nNewAbsSelectedPageNum ) )
828 {
829 if ( _nHoriMove != 0 && _nVertMove != 0 )
830 {
831 OSL_FAIL( "missing implementation for moving preview selected page horizontal AND vertical")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "831" ": "), "%s", "missing implementation for moving preview selected page horizontal AND vertical"
); } } while (false)
;
832 return;
833 }
834
835 // new selected page has to be brought into view considering current
836 // visible preview.
837 const sal_uInt16 nTotalRows = GetRowOfPage( mnPages );
838 if ( (_nHoriMove > 0 || _nVertMove > 0) &&
839 mbDoesLayoutRowsFitIntoWindow &&
840 mbDoesLayoutColsFitIntoWindow &&
841 nCurrRow > nTotalRows - mnRows )
842 {
843 // new proposed start page = left-top-corner of last possible
844 // preview page.
845 nNewStartPage = (nTotalRows - mnRows) * mnCols + 1;
846 // leaving left-top-corner blank is controlled
847 // by <mbBookPreview>.
848 if ( mbBookPreview )
849 {
850 // Note: decrease new proposed start page number by one,
851 // because of blank left-top-corner
852 --nNewStartPage;
853 }
854 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewStartPage );
855 }
856 else
857 {
858 // new proposed start page = new selected page.
859 nNewStartPage = ConvertRelativeToAbsolutePageNum( nNewRelSelectedPageNum );
860 }
861 }
862
863 _orNewSelectedPage = nNewAbsSelectedPageNum;
864 _orNewStartPage = nNewStartPage;
865 _orNewStartPos = aNewStartPos;
866}
867
868namespace {
869
870/** checks, if given position is inside a shown document page */
871struct PreviewPosInsidePagePred
872{
873 const Point mnPreviewPos;
874 explicit PreviewPosInsidePagePred(const Point& rPreviewPos)
875 : mnPreviewPos( rPreviewPos )
876 {}
877 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
878 {
879 if ( _pPreviewPage->bVisible )
880 {
881 tools::Rectangle aPreviewPageRect( _pPreviewPage->aPreviewWinPos, _pPreviewPage->aPageSize );
882 return aPreviewPageRect.IsInside( mnPreviewPos );
883 }
884 return false;
885 }
886};
887
888}
889
890bool SwPagePreviewLayout::IsPreviewPosInDocPreviewPage( const Point& rPreviewPos,
891 Point& _orDocPos,
892 bool& _obPosInEmptyPage,
893 sal_uInt16& _onPageNum ) const
894{
895 // initialize variable parameter values.
896 _orDocPos.setX( 0 );
897 _orDocPos.setY( 0 );
898 _obPosInEmptyPage = false;
899 _onPageNum = 0;
900
901 auto aFoundPreviewPageIter =
902 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
903 PreviewPosInsidePagePred( rPreviewPos ) );
904
905 if ( aFoundPreviewPageIter != maPreviewPages.end() )
906 {
907 // given preview position is inside a document page.
908 _onPageNum = (*aFoundPreviewPageIter)->pPage->GetPhyPageNum();
909 _obPosInEmptyPage = (*aFoundPreviewPageIter)->pPage->IsEmptyPage();
910 if ( !_obPosInEmptyPage )
911 {
912 // given preview position inside a normal page
913 _orDocPos = rPreviewPos -
914 (*aFoundPreviewPageIter)->aPreviewWinPos +
915 (*aFoundPreviewPageIter)->aLogicPos;
916 return true;
917 }
918 }
919
920 return false;
921}
922
923/** determine window page scroll amount */
924SwTwips SwPagePreviewLayout::GetWinPagesScrollAmount(
925 const sal_Int16 _nWinPagesToScroll ) const
926{
927 SwTwips nScrollAmount;
928 if ( mbDoesLayoutRowsFitIntoWindow )
929 {
930 nScrollAmount = (mnPreviewLayoutHeight - gnYFree) * _nWinPagesToScroll;
931 }
932 else
933 nScrollAmount = _nWinPagesToScroll * maPaintedPreviewDocRect.GetHeight();
934
935 // check, if preview layout size values are valid.
936 // If not, the checks for an adjustment of the scroll amount aren't useful.
937 if ( mbLayoutSizesValid )
938 {
939 if ( (maPaintedPreviewDocRect.Top() + nScrollAmount) <= 0 )
940 nScrollAmount = -maPaintedPreviewDocRect.Top();
941
942 // correct scroll amount
943 if ( nScrollAmount > 0 &&
944 maPaintedPreviewDocRect.Bottom() == maPreviewDocRect.Bottom()
945 )
946 {
947 nScrollAmount = 0;
948 }
949 else
950 {
951 while ( (maPaintedPreviewDocRect.Top() + nScrollAmount + gnYFree) >= maPreviewDocRect.GetHeight() )
952 {
953 nScrollAmount -= mnRowHeight;
954 }
955 }
956 }
957
958 return nScrollAmount;
959}
960
961// methods to paint page preview layout
962
963namespace
964{
965/// Similar to RenderContextGuard, but does not touch the draw view.
966class PreviewRenderContextGuard
967{
968 VclPtr<vcl::RenderContext> m_pOriginalValue;
969 SwViewShell& m_rShell;
970
971public:
972 PreviewRenderContextGuard(SwViewShell& rShell, vcl::RenderContext* pValue)
973 : m_pOriginalValue(rShell.GetOut()),
974 m_rShell(rShell)
975 {
976 m_rShell.SetOut(pValue);
977 }
978
979 ~PreviewRenderContextGuard()
980 {
981 m_rShell.SetOut(m_pOriginalValue);
982 }
983};
984}
985
986/** paint prepared preview
987
988*/
989bool SwPagePreviewLayout::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rOutRect) const
990{
991 PreviewRenderContextGuard aGuard(mrParentViewShell, &rRenderContext);
992 // check environment and parameters
993 {
994 if (!mrParentViewShell.GetWin() && !mrParentViewShell.GetOut()->GetConnectMetaFile())
995 {
996 return false;
997 }
998
999 OSL_ENSURE(mbPaintInfoValid, "invalid preview settings - no paint of preview")do { if (true && (!(mbPaintInfoValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "999" ": "), "%s", "invalid preview settings - no paint of preview"
); } } while (false)
;
1000 if (!mbPaintInfoValid)
1001 return false;
1002 }
1003
1004 // OD 17.11.2003 #i22014# - no paint, if <superfluous> flag is set at layout
1005 if (mrLayoutRootFrame.IsSuperfluous())
1006 {
1007 return true;
1008 }
1009
1010 // environment and parameter ok
1011
1012 if (mbInPaint)
1013 {
1014 return false;
1015 }
1016 mbInPaint = true;
1017
1018 OutputDevice* pOutputDev = &rRenderContext;
1019
1020 // prepare paint
1021 if ( !maPreviewPages.empty() )
1022 {
1023 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1024 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1025 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1026 }
1027
1028 // paint preview background
1029 {
1030 SwRegionRects aPreviewBackgrdRegion(rOutRect);
1031 // calculate preview background rectangles
1032 for ( auto & rpPreviewPage : maPreviewPages )
1033 {
1034 if ( rpPreviewPage->bVisible )
1035 {
1036 aPreviewBackgrdRegion -=
1037 SwRect( rpPreviewPage->aPreviewWinPos, rpPreviewPage->aPageSize );
1038 }
1039 }
1040 // paint preview background rectangles
1041 mrParentViewShell.PaintDesktop_(aPreviewBackgrdRegion);
1042 }
1043
1044 // prepare data for paint of pages
1045 const tools::Rectangle aPxOutRect( pOutputDev->LogicToPixel(rOutRect) );
1046
1047 MapMode aMapMode( pOutputDev->GetMapMode() );
1048 MapMode aSavedMapMode = aMapMode;
1049
1050 const vcl::Font& rEmptyPgFont = SwPageFrame::GetEmptyPageFont();
1051
1052 for ( auto & rpPreviewPage : maPreviewPages )
1053 {
1054 if ( !rpPreviewPage->bVisible )
1055 continue;
1056
1057 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1058 aMapMode.SetOrigin( rpPreviewPage->aMapOffset );
1059 pOutputDev->SetMapMode( aMapMode );
1060 tools::Rectangle aPxPaintRect = pOutputDev->LogicToPixel( aPageRect );
1061 if ( aPxOutRect.IsOver( aPxPaintRect) )
1062 {
1063 const SwPageFrame* pPage = rpPreviewPage->pPage;
1064
1065 if (pPage->IsEmptyPage())
1066 {
1067 const Color aRetouche( mrParentViewShell.Imp()->GetRetoucheColor() );
1068 if( pOutputDev->GetFillColor() != aRetouche )
1069 pOutputDev->SetFillColor( aRetouche );
1070 pOutputDev->SetLineColor(); // no line color
1071 // use aligned page rectangle
1072 {
1073 SwRect aTmpPageRect( aPageRect );
1074 ::SwAlignRect( aTmpPageRect, &mrParentViewShell, &rRenderContext );
1075 aPageRect = aTmpPageRect.SVRect();
1076 }
1077 pOutputDev->DrawRect( aPageRect );
1078
1079 // paint empty page text
1080 vcl::Font aOldFont( pOutputDev->GetFont() );
1081 pOutputDev->SetFont( rEmptyPgFont );
1082 pOutputDev->DrawText( aPageRect, SwResId( STR_EMPTYPAGEreinterpret_cast<char const *>("STR_EMPTYPAGE" "\004" u8"blank page"
)
),
1083 DrawTextFlags::VCenter |
1084 DrawTextFlags::Center |
1085 DrawTextFlags::Clip );
1086 pOutputDev->SetFont( aOldFont );
1087 // paint shadow and border for empty page
1088 // use new method to paint page border and shadow
1089 SwPageFrame::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
1090 }
1091 else
1092 {
1093 const bool bIsLeftShadowed = pPage->IsLeftShadowNeeded();
1094 const bool bIsRightShadowed = pPage->IsRightShadowNeeded();
1095
1096 mrParentViewShell.maVisArea = aPageRect;
1097 aPxPaintRect.Intersection( aPxOutRect );
1098 tools::Rectangle aPaintRect = pOutputDev->PixelToLogic( aPxPaintRect );
1099 mrParentViewShell.Paint(rRenderContext, aPaintRect);
1100
1101 // --> OD 2007-08-15 #i80691#
1102 // paint page border and shadow
1103 {
1104 SwRect aPageBorderRect;
1105 SwPageFrame::GetBorderAndShadowBoundRect( SwRect( aPageRect ), &mrParentViewShell, &rRenderContext, aPageBorderRect,
1106 bIsLeftShadowed, bIsRightShadowed, true );
1107 const vcl::Region aDLRegion(aPageBorderRect.SVRect());
1108 mrParentViewShell.DLPrePaint2(aDLRegion);
1109 SwPageFrame::PaintBorderAndShadow( aPageRect, &mrParentViewShell, true, false, true );
1110 mrParentViewShell.DLPostPaint2(true);
1111 }
1112 // <--
1113 }
1114 // OD 07.11.2003 #i22014# - stop painting, because new print
1115 // preview layout is created during paint.
1116 if ( mbNewLayoutDuringPaint )
1117 {
1118 break;
1119 }
1120
1121 if (pPage->GetPhyPageNum() == mnSelectedPageNum)
1122 {
1123 PaintSelectMarkAtPage(rRenderContext, rpPreviewPage.get());
1124 }
1125 }
1126 }
1127
1128 // OD 17.11.2003 #i22014# - no update of accessible preview, if a new
1129 // print preview layout is created during paint.
1130 if ( !mbNewLayoutDuringPaint )
1131 {
1132 // update at accessibility interface
1133 mrParentViewShell.Imp()->UpdateAccessiblePreview(
1134 maPreviewPages,
1135 aMapMode.GetScaleX(),
1136 mrLayoutRootFrame.GetPageByPageNum( mnSelectedPageNum ),
1137 maWinSize );
1138 }
1139
1140 pOutputDev->SetMapMode( aSavedMapMode );
1141 mrParentViewShell.maVisArea.Clear();
1142
1143 // OD 07.11.2003 #i22014#
1144 mbInPaint = false;
1145 mbNewLayoutDuringPaint = false;
1146
1147 return true;
1148}
1149
1150/** repaint pages on page preview
1151
1152 OD 18.12.2002 #103492#
1153*/
1154void SwPagePreviewLayout::Repaint( const tools::Rectangle& rInvalidCoreRect ) const
1155{
1156 // check environment and parameters
1157 {
1158 if ( !mrParentViewShell.GetWin() &&
1159 !mrParentViewShell.GetOut()->GetConnectMetaFile() )
1160 return;
1161
1162 OSL_ENSURE( mbPaintInfoValid,do { if (true && (!(mbPaintInfoValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "1163" ": "), "%s", "invalid preview settings - no paint of preview"
); } } while (false)
1163 "invalid preview settings - no paint of preview" )do { if (true && (!(mbPaintInfoValid))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "1163" ": "), "%s", "invalid preview settings - no paint of preview"
); } } while (false)
;
1164 if ( !mbPaintInfoValid )
1165 return;
1166 }
1167
1168 // environment and parameter ok
1169
1170 // prepare paint
1171 if ( !maPreviewPages.empty() )
1172 {
1173 mrParentViewShell.Imp()->m_bFirstPageInvalid = false;
1174 mrParentViewShell.Imp()->m_pFirstVisiblePage =
1175 const_cast<SwPageFrame*>(maPreviewPages[0]->pPage);
1176 }
1177
1178 // invalidate visible pages, which overlap the invalid core rectangle
1179 for ( auto & rpPreviewPage : maPreviewPages )
1180 {
1181 if ( !rpPreviewPage->bVisible )
1182 continue;
1183
1184 tools::Rectangle aPageRect( rpPreviewPage->aLogicPos, rpPreviewPage->aPageSize );
1185 if ( rInvalidCoreRect.IsOver( aPageRect ) )
1186 {
1187 aPageRect.Intersection(rInvalidCoreRect);
1188 tools::Rectangle aInvalidPreviewRect = aPageRect;
1189 aInvalidPreviewRect.SetPos( aInvalidPreviewRect.TopLeft() -
1190 rpPreviewPage->aLogicPos +
1191 rpPreviewPage->aPreviewWinPos );
1192 mrParentViewShell.GetWin()->Invalidate( aInvalidPreviewRect );
1193 }
1194 }
1195}
1196
1197/** paint selection mark at page
1198
1199 OD 17.12.2002 #103492#
1200*/
1201void SwPagePreviewLayout::PaintSelectMarkAtPage(vcl::RenderContext& rRenderContext,
1202 const PreviewPage* _aSelectedPreviewPage ) const
1203{
1204 OutputDevice* pOutputDev = &rRenderContext;
1205 MapMode aMapMode( pOutputDev->GetMapMode() );
1206 // save mapping mode of output device
1207 MapMode aSavedMapMode = aMapMode;
1208 // save fill and line color of output device
1209 Color aFill( pOutputDev->GetFillColor() );
1210 Color aLine( pOutputDev->GetLineColor() );
1211
1212 // determine selection mark color
1213 Color aSelPgLineColor(117, 114, 106);
1214 const StyleSettings& rSettings =
1215 mrParentViewShell.GetWin()->GetSettings().GetStyleSettings();
1216 if ( rSettings.GetHighContrastMode() )
1217 aSelPgLineColor = rSettings.GetHighlightTextColor();
1218
1219 // set needed mapping mode at output device
1220 aMapMode.SetOrigin( _aSelectedPreviewPage->aMapOffset );
1221 pOutputDev->SetMapMode( aMapMode );
1222
1223 // calculate page rectangle in pixel coordinates
1224 SwRect aPageRect( _aSelectedPreviewPage->aLogicPos,
1225 _aSelectedPreviewPage->aPageSize );
1226 // OD 19.02.2003 #107369# - use aligned page rectangle, as it is used for
1227 // page border and shadow paint - see <SwPageFrame::PaintBorderAndShadow(..)>
1228 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1229 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1230
1231 // draw two rectangle
1232 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1233 tools::Rectangle aRect( aPxPageRect.Left(), aPxPageRect.Top(),
1234 aPxPageRect.Right(), aPxPageRect.Bottom() );
1235 aRect = pOutputDev->PixelToLogic( aRect );
1236 pOutputDev->SetFillColor(); // OD 20.02.2003 #107369# - no fill color
1237 pOutputDev->SetLineColor( aSelPgLineColor );
1238 pOutputDev->DrawRect( aRect );
1239 // OD 19.02.2003 #107369# - adjust position of select mark rectangle
1240 aRect = tools::Rectangle( aPxPageRect.Left()+1, aPxPageRect.Top()+1,
1241 aPxPageRect.Right()-1, aPxPageRect.Bottom()-1 );
1242 aRect = pOutputDev->PixelToLogic( aRect );
1243 pOutputDev->DrawRect( aRect );
1244
1245 // reset fill and line color of output device
1246 pOutputDev->SetFillColor( aFill );
1247 pOutputDev->SetLineColor( aLine );
1248
1249 // reset mapping mode of output device
1250 pOutputDev->SetMapMode( aSavedMapMode );
1251}
1252
1253/** paint to mark new selected page
1254
1255 OD 17.12.2002 #103492#
1256 Perform paint for current selected page in order to unmark it.
1257 Set new selected page and perform paint to mark this page.
1258
1259 @note _nSelectedPage, mnSelectedPage are absolute
1260*/
1261void SwPagePreviewLayout::MarkNewSelectedPage( const sal_uInt16 _nSelectedPage )
1262{
1263 const sal_uInt16 nOldSelectedPageNum = mnSelectedPageNum;
1264 mnSelectedPageNum = _nSelectedPage;
1265
1266 // re-paint for current selected page in order to unmark it.
1267 const PreviewPage* pOldSelectedPreviewPage = GetPreviewPageByPageNum( nOldSelectedPageNum );
1268 OutputDevice* pOutputDev = mrParentViewShell.GetOut();
1269 if ( pOldSelectedPreviewPage && pOldSelectedPreviewPage->bVisible )
1270 {
1271 // OD 20.02.2003 #107369# - invalidate only areas of selection mark.
1272 SwRect aPageRect( pOldSelectedPreviewPage->aPreviewWinPos,
1273 pOldSelectedPreviewPage->aPageSize );
1274 ::SwAlignRect( aPageRect, &mrParentViewShell, pOutputDev );
1275 tools::Rectangle aPxPageRect = pOutputDev->LogicToPixel( aPageRect.SVRect() );
1276 // invalidate top mark line
1277 tools::Rectangle aInvalPxRect( aPxPageRect.Left(), aPxPageRect.Top(),
1278 aPxPageRect.Right(), aPxPageRect.Top()+1 );
1279 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1280 // invalidate right mark line
1281 aInvalPxRect = tools::Rectangle( aPxPageRect.Right()-1, aPxPageRect.Top(),
1282 aPxPageRect.Right(), aPxPageRect.Bottom() );
1283 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1284 // invalidate bottom mark line
1285 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Bottom()-1,
1286 aPxPageRect.Right(), aPxPageRect.Bottom() );
1287 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1288 // invalidate left mark line
1289 aInvalPxRect = tools::Rectangle( aPxPageRect.Left(), aPxPageRect.Top(),
1290 aPxPageRect.Left()+1, aPxPageRect.Bottom() );
1291 mrParentViewShell.GetWin()->Invalidate( pOutputDev->PixelToLogic( aInvalPxRect ) );
1292 }
1293
1294 // re-paint for new selected page in order to mark it.
1295 const PreviewPage* pNewSelectedPreviewPage = GetPreviewPageByPageNum( _nSelectedPage );
1296 if ( pNewSelectedPreviewPage && pNewSelectedPreviewPage->bVisible )
1297 {
1298 const PreviewPage* pSelectedPreviewPage = GetPreviewPageByPageNum(mnSelectedPageNum);
1299 SwRect aPageRect(pSelectedPreviewPage->aPreviewWinPos, pSelectedPreviewPage->aPageSize);
1300 ::SwAlignRect(aPageRect, &mrParentViewShell, pOutputDev);
1301 mrParentViewShell.GetWin()->Invalidate(aPageRect.SVRect());
1302 }
1303}
1304
1305// helper methods
1306
1307namespace {
1308
1309/** get preview page by physical page number
1310
1311 OD 17.12.2002 #103492#
1312*/
1313struct EqualsPageNumPred
1314{
1315 const sal_uInt16 mnPageNum;
1316 explicit EqualsPageNumPred(const sal_uInt16 _nPageNum)
1317 : mnPageNum( _nPageNum )
1318 {}
1319 bool operator() ( const std::unique_ptr<PreviewPage> & _pPreviewPage )
1320 {
1321 return _pPreviewPage->pPage->GetPhyPageNum() == mnPageNum;
1322 }
1323};
1324
1325}
1326
1327const PreviewPage* SwPagePreviewLayout::GetPreviewPageByPageNum( const sal_uInt16 _nPageNum ) const
1328{
1329 auto aFoundPreviewPageIter =
1330 std::find_if( maPreviewPages.begin(), maPreviewPages.end(),
1331 EqualsPageNumPred( _nPageNum ) );
1332
1333 if ( aFoundPreviewPageIter == maPreviewPages.end() )
1334 return nullptr;
1335
1336 return aFoundPreviewPageIter->get();
1337}
1338
1339/** determine row the page with the given number is in
1340
1341 OD 17.01.2003 #103492#
1342
1343 @note _nPageNum is relative
1344*/
1345sal_uInt16 SwPagePreviewLayout::GetRowOfPage( sal_uInt16 _nPageNum ) const
1346{
1347 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1348 // by <mbBookPreview>.
1349 if ( mbBookPreview )
1350 {
1351 // Note: increase given physical page number by one, because left-top-corner
1352 // in the preview layout is left blank.
1353 ++_nPageNum;
1354 }
1355
1356 return _nPageNum / mnCols + ((_nPageNum % mnCols)>0 ? 1 : 0);
1357}
1358
1359/** determine column the page with the given number is in
1360
1361 OD 17.01.2003 #103492#
1362
1363 @note _nPageNum is relative
1364*/
1365sal_uInt16 SwPagePreviewLayout::GetColOfPage( sal_uInt16 _nPageNum ) const
1366{
1367 // OD 19.02.2003 #107369# - leaving left-top-corner blank is controlled
1368 // by <mbBookPreview>.
1369 if ( mbBookPreview )
1370 {
1371 // Note: increase given physical page number by one, because left-top-corner
1372 // in the preview layout is left blank.
1373 ++_nPageNum;
1374 }
1375
1376 const sal_uInt16 nCol = _nPageNum % mnCols;
1377 return nCol ? nCol : mnCols;
1378}
1379
1380Size SwPagePreviewLayout::GetPreviewDocSize() const
1381{
1382 OSL_ENSURE( PreviewLayoutValid(), "PagePreviewLayout not valid" )do { if (true && (!(PreviewLayoutValid()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/view/pagepreviewlayout.cxx"
":" "1382" ": "), "%s", "PagePreviewLayout not valid"); } } while
(false)
;
1383 return maPreviewDocRect.GetSize();
1384}
1385
1386/** get size of a preview page by its physical page number
1387
1388 OD 15.01.2003 #103492#
1389*/
1390Size SwPagePreviewLayout::GetPreviewPageSizeByPageNum( sal_uInt16 _nPageNum ) const
1391{
1392 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1393 if ( pPreviewPage )
1394 {
1395 return pPreviewPage->aPageSize;
1396 }
1397 return Size( 0, 0 );
1398}
1399
1400/** get virtual page number by its physical page number
1401
1402 OD 21.03.2003 #108282#
1403*/
1404sal_uInt16 SwPagePreviewLayout::GetVirtPageNumByPageNum( sal_uInt16 _nPageNum ) const
1405{
1406 const PreviewPage* pPreviewPage = GetPreviewPageByPageNum( _nPageNum );
1407 if ( pPreviewPage )
1408 {
1409 return pPreviewPage->pPage->GetVirtPageNum();
1410 }
1411 return 0;
1412}
1413
1414/** Convert absolute to relative page numbers (see PrintEmptyPages) */
1415sal_uInt16 SwPagePreviewLayout::ConvertAbsoluteToRelativePageNum( sal_uInt16 _nAbsPageNum ) const
1416{
1417 if ( mbBookPreview || mbPrintEmptyPages || !_nAbsPageNum )
2
Assuming field 'mbBookPreview' is false
3
Assuming field 'mbPrintEmptyPages' is false
4
Assuming '_nAbsPageNum' is not equal to 0
5
Taking false branch
1418 {
1419 return _nAbsPageNum;
1420 }
1421
1422 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1423
1424 sal_uInt16 nRet = 1;
1425
1426 while ( pTmpPage && pTmpPage->GetPhyPageNum() != _nAbsPageNum )
6
Assuming 'pTmpPage' is null
1427 {
1428 if ( !pTmpPage->IsEmptyPage() )
1429 ++nRet;
1430
1431 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1432 }
1433
1434 return nRet;
7
Returning the value 1 (loaded from 'nRet'), which participates in a condition later
1435}
1436
1437/** Convert relative to absolute page numbers (see PrintEmptyPages) */
1438sal_uInt16 SwPagePreviewLayout::ConvertRelativeToAbsolutePageNum( sal_uInt16 _nRelPageNum ) const
1439{
1440 if ( mbBookPreview
13.1
Field 'mbBookPreview' is false
|| mbPrintEmptyPages
13.2
Field 'mbPrintEmptyPages' is false
|| !_nRelPageNum
13.3
'_nRelPageNum' is 1
)
14
Taking false branch
1441 {
1442 return _nRelPageNum;
1443 }
1444
1445 const SwPageFrame* pTmpPage = static_cast<const SwPageFrame*>(mrLayoutRootFrame.Lower());
1446 const SwPageFrame* pRet = nullptr;
15
'pRet' initialized to a null pointer value
1447
1448 sal_uInt16 i = 0;
1449 while( pTmpPage
15.1
'pTmpPage' is null
&& i != _nRelPageNum )
1450 {
1451 if ( !pTmpPage->IsEmptyPage() )
1452 ++i;
1453
1454 pRet = pTmpPage;
1455 pTmpPage = static_cast<const SwPageFrame*>( pTmpPage->GetNext() );
1456 }
1457
1458 return pRet->GetPhyPageNum();
16
Called C++ object pointer is null
1459}
1460
1461/* vim:set shiftwidth=4 softtabstop=4 expandtab: */