1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <o3tl/unit_conversion.hxx>
23 #include <svx/svdoutl.hxx>
24 #include <svx/svdpagv.hxx>
25 #include <svx/svdview.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <osl/diagnose.h>
31 #include <drwlayer.hxx>
32 #include <document.hxx>
33 #include <tabvwsh.hxx>
35 #include <svx/fmview.hxx>
36 #include <svx/sdrpaintwindow.hxx>
37 #include <svx/sdrpagewindow.hxx>
40 Point
ScOutputData::PrePrintDrawingLayer(tools::Long nLogStX
, tools::Long nLogStY
)
42 tools::Rectangle aRect
;
45 tools::Long
nLayoutSign(bLayoutRTL
? -1 : 1);
47 for (nCol
=0; nCol
<nX1
; nCol
++)
48 aOffset
.AdjustX( -(mpDoc
->GetColWidth( nCol
, nTab
) * nLayoutSign
) );
49 aOffset
.AdjustY( -sal_Int32(mpDoc
->GetRowHeight( 0, nY1
-1, nTab
)) );
51 tools::Long nDataWidth
= 0;
52 for (nCol
=nX1
; nCol
<=nX2
; nCol
++)
53 nDataWidth
+= mpDoc
->GetColWidth( nCol
, nTab
);
56 aOffset
.AdjustX(nDataWidth
);
58 aRect
.SetLeft( -aOffset
.X() );
59 aRect
.SetRight( -aOffset
.X() );
60 aRect
.SetTop( -aOffset
.Y() );
61 aRect
.SetBottom( -aOffset
.Y() );
63 Point
aMMOffset( aOffset
);
64 aMMOffset
.setX(o3tl::convert(aMMOffset
.X(), o3tl::Length::twip
, o3tl::Length::mm100
));
65 aMMOffset
.setY(o3tl::convert(aMMOffset
.Y(), o3tl::Length::twip
, o3tl::Length::mm100
));
68 aMMOffset
+= Point( nLogStX
, nLogStY
);
70 for (nCol
=nX1
; nCol
<=nX2
; nCol
++)
71 aRect
.AdjustRight(mpDoc
->GetColWidth( nCol
, nTab
) );
72 aRect
.AdjustBottom(mpDoc
->GetRowHeight( nY1
, nY2
, nTab
) );
74 aRect
.SetLeft(o3tl::convert(aRect
.Left(), o3tl::Length::twip
, o3tl::Length::mm100
));
75 aRect
.SetTop(o3tl::convert(aRect
.Top(), o3tl::Length::twip
, o3tl::Length::mm100
));
76 aRect
.SetRight(o3tl::convert(aRect
.Right(), o3tl::Length::twip
, o3tl::Length::mm100
));
77 aRect
.SetBottom(o3tl::convert(aRect
.Bottom(), o3tl::Length::twip
, o3tl::Length::mm100
));
79 if(pViewShell
|| pDrawView
)
81 SdrView
* pLocalDrawView
= pDrawView
? pDrawView
: pViewShell
->GetScDrawView();
85 // #i76114# MapMode has to be set because BeginDrawLayers uses GetPaintRegion
86 MapMode aOldMode
= mpDev
->GetMapMode();
88 mpDev
->SetMapMode( MapMode( MapUnit::Map100thMM
, aMMOffset
, aOldMode
.GetScaleX(), aOldMode
.GetScaleY() ) );
90 // #i74769# work with SdrPaintWindow directly
91 // #i76114# pass bDisableIntersect = true, because the intersection of the table area
92 // with the Window's paint region can be empty
93 vcl::Region
aRectRegion(aRect
);
94 mpTargetPaintWindow
= pLocalDrawView
->BeginDrawLayers(mpDev
, aRectRegion
, true);
95 OSL_ENSURE(mpTargetPaintWindow
, "BeginDrawLayers: Got no SdrPaintWindow (!)");
98 mpDev
->SetMapMode( aOldMode
);
106 void ScOutputData::PostPrintDrawingLayer(const Point
& rMMOffset
) // #i74768#
108 // #i74768# just use offset as in PrintDrawingLayer() to also get the form controls
109 // painted with offset
110 MapMode aOldMode
= mpDev
->GetMapMode();
114 mpDev
->SetMapMode( MapMode( MapUnit::Map100thMM
, rMMOffset
, aOldMode
.GetScaleX(), aOldMode
.GetScaleY() ) );
117 if(pViewShell
|| pDrawView
)
119 SdrView
* pLocalDrawView
= pDrawView
? pDrawView
: pViewShell
->GetScDrawView();
123 // #i74769# work with SdrPaintWindow directly
124 pLocalDrawView
->EndDrawLayers(*mpTargetPaintWindow
, true);
125 mpTargetPaintWindow
= nullptr;
132 mpDev
->SetMapMode( aOldMode
);
137 void ScOutputData::PrintDrawingLayer(SdrLayerID nLayer
, const Point
& rMMOffset
)
139 bool bHideAllDrawingLayer(false);
141 if(pViewShell
|| pDrawView
)
143 SdrView
* pLocalDrawView
= pDrawView
? pDrawView
: pViewShell
->GetScDrawView();
147 bHideAllDrawingLayer
= pLocalDrawView
->getHideOle() && pLocalDrawView
->getHideChart()
148 && pLocalDrawView
->getHideDraw() && pLocalDrawView
->getHideFormControl();
152 if(bHideAllDrawingLayer
|| (!mpDoc
->GetDrawLayer()))
157 MapMode aOldMode
= mpDev
->GetMapMode();
161 mpDev
->SetMapMode( MapMode( MapUnit::Map100thMM
, rMMOffset
, aOldMode
.GetScaleX(), aOldMode
.GetScaleY() ) );
164 DrawSelectiveObjects( nLayer
);
168 mpDev
->SetMapMode( aOldMode
);
172 void ScOutputData::DrawSelectiveObjects(SdrLayerID nLayer
)
174 ScDrawLayer
* pModel
= mpDoc
->GetDrawLayer();
178 // #i46362# high contrast mode (and default text direction) must be handled
179 // by the application, so it's still needed when using DrawLayer().
181 SdrOutliner
& rOutl
= pModel
->GetDrawOutliner();
182 rOutl
.EnableAutoColor( mbUseStyleColor
);
183 rOutl
.SetDefaultHorizontalTextDirection(
184 mpDoc
->GetEditTextDirection( nTab
) );
185 Color aOldOutlinerBackgroundColor
= rOutl
.GetBackgroundColor();
186 const ScTabViewShell
* pTabViewShellBg
= mbUseStyleColor
? ScTabViewShell::GetActiveViewShell() : nullptr;
189 // Similar to writer's SwViewShellImp::PaintLayer set the default
190 // background of the Outliner for the AutoColor cases where there is no
191 // explicit background known. But like elsewhere in calc, take
192 // mbUseStyleColor of false as ScAutoFontColorMode::Print for print
193 // output, so don't set a default outliner background then.
194 const ScViewRenderingOptions
& rViewRenderingOptions
= pTabViewShellBg
->GetViewRenderingData();
195 rOutl
.SetBackgroundColor(rViewRenderingOptions
.GetDocColor());
198 // #i69767# The hyphenator must be set (used to be before drawing a text shape with hyphenation).
199 // LinguMgr::GetHyphenator (EditEngine) uses a wrapper now that creates the real hyphenator on demand,
200 // so it's not a performance problem to call UseHyphenator even when it's not needed.
202 pModel
->UseHyphenator();
204 DrawModeFlags nOldDrawMode
= mpDev
->GetDrawMode();
205 if ( mbUseStyleColor
&& Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
207 mpDev
->SetDrawMode( nOldDrawMode
| DrawModeFlags::SettingsLine
| DrawModeFlags::SettingsFill
|
208 DrawModeFlags::SettingsText
| DrawModeFlags::SettingsGradient
);
211 if(pViewShell
|| pDrawView
)
213 SdrView
* pLocalDrawView
= pDrawView
? pDrawView
: pViewShell
->GetScDrawView();
217 SdrPageView
* pPageView
= pLocalDrawView
->GetSdrPageView();
221 // tdf#160589 need to check for registered PaintWindow using the
222 // 'original' TargetDevice, mpDev might have been changed by a
223 // call to ::SetContentDevice. That again might patch in a
224 // pre-render device fetched from SdrPaintWindow::GetTargetOutputDevice
225 // and thus the test if target is a registered PageWindow would fail
226 assert(nullptr != mpOriginalTargetDevice
&& "mpOriginalTargetDevice *must* be set when constructing ScOutputData (!)");
227 if (nullptr != pPageView
->FindPageWindow(*mpOriginalTargetDevice
))
229 // Target OutputDevice is registered for this view
230 // (as it should be), we can just render
231 pPageView
->DrawLayer(sal::static_int_cast
<SdrLayerID
>(nLayer
), mpDev
);
233 else if (0 != pPageView
->PageWindowCount())
235 // We need to temporarily make the target OutputDevice being
236 // 'known/registered' in the paint mechanism so that
237 // SdrPageView::DrawLayer can find it.
238 // This situation can occur when someone interprets the
239 // OutputDevice parameter that gets handed over to DrawLayer
240 // (or other SdrPageView repaint methods) to be there to
241 // define a new render target.
242 // This is *not* the case: This parameter is used to
243 // *identify* an already registered target-OutputDevice.
244 // The default is even to call with a nullptr -> that triggers
245 // the repaint for *all* registered OutputDevices/Windows.
246 // Since this is a common and known misinterpretation it
247 // is good to offer workarounds in the code - there are some
249 // For now - use an already existing 'patch mechanism' and
250 // 'smuggle' the unknown/temporary OutputDevice as a
251 // temporary SdrPaintWindow to the SdrPageWindow, that is
252 // not very expensive.
253 // NOTE: Just using the 1st SdrPageWindow here will be OK
254 // in most cases, the splitting of a view is only used
255 // in calc nowadays and should have identical zoom.
256 // Still, trigger a warning...
257 OSL_ENSURE(1 == pPageView
->PageWindowCount(),
258 "ScOutputData::DrawSelectiveObjects: More than one SdrPageView, still using 1st one (!)");
259 SdrPageWindow
* patchedPageWindow(pPageView
->GetPageWindow(0));
260 assert(nullptr != patchedPageWindow
&& "SdrPageWindow *must* exist when 0 != PageWindowCount()");
261 SdrPaintWindow
temporaryPaintWindow(*pLocalDrawView
, *mpDev
);
262 SdrPaintWindow
* previousPaintWindow(patchedPageWindow
->patchPaintWindow(temporaryPaintWindow
));
263 pPageView
->DrawLayer(sal::static_int_cast
<SdrLayerID
>(nLayer
), mpDev
);
264 patchedPageWindow
->unpatchPaintWindow(previousPaintWindow
);
268 // There does not even exist a SdrPageWindow. Still call the
269 // paint to get the paint done, but be aware that this will create
270 // temporary SdrPaintWindow and SdrPageWindow and - due to the
271 // former - will not be able to use the decomposition buffering
272 // in the VC/VOC/OC mechanism. For that reason this might be
273 // somewhat 'expensive'.
274 // You will also get a warning about it (see OSL_FAIL in
275 // SdrPageView::DrawLayer)
276 pPageView
->DrawLayer(sal::static_int_cast
<SdrLayerID
>(nLayer
), mpDev
);
283 rOutl
.SetBackgroundColor(aOldOutlinerBackgroundColor
);
285 mpDev
->SetDrawMode(nOldDrawMode
);
288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */