/src/libreoffice/sc/source/ui/view/output3.cxx
Line | Count | Source |
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 <sal/config.h> |
21 | | |
22 | | #include <o3tl/unit_conversion.hxx> |
23 | | #include <svx/svdoutl.hxx> |
24 | | #include <svx/svdpagv.hxx> |
25 | | #include <svx/svdview.hxx> |
26 | | #include <vcl/rendercontext/DrawModeFlags.hxx> |
27 | | #include <vcl/svapp.hxx> |
28 | | #include <vcl/settings.hxx> |
29 | | #include <osl/diagnose.h> |
30 | | |
31 | | #include <output.hxx> |
32 | | #include <drwlayer.hxx> |
33 | | #include <document.hxx> |
34 | | #include <tabvwsh.hxx> |
35 | | |
36 | | #include <svx/fmview.hxx> |
37 | | #include <svx/sdrpaintwindow.hxx> |
38 | | #include <svx/sdrpagewindow.hxx> |
39 | | |
40 | | // #i72502# |
41 | | Point ScOutputData::PrePrintDrawingLayer(tools::Long nLogStX, tools::Long nLogStY ) |
42 | 0 | { |
43 | 0 | tools::Rectangle aRect; |
44 | 0 | SCCOL nCol; |
45 | 0 | Point aOffset; |
46 | 0 | tools::Long nLayoutSign(mbLayoutRTL ? -1 : 1); |
47 | |
|
48 | 0 | for (nCol=0; nCol<mnX1; nCol++) |
49 | 0 | aOffset.AdjustX( -(mpDoc->GetColWidth( nCol, mnTab ) * nLayoutSign) ); |
50 | 0 | aOffset.AdjustY( -sal_Int32(mpDoc->GetRowHeight( 0, mnY1-1, mnTab )) ); |
51 | |
|
52 | 0 | tools::Long nDataWidth = 0; |
53 | 0 | for (nCol=mnX1; nCol<=mnX2; nCol++) |
54 | 0 | nDataWidth += mpDoc->GetColWidth( nCol, mnTab ); |
55 | |
|
56 | 0 | if ( mbLayoutRTL ) |
57 | 0 | aOffset.AdjustX(nDataWidth ); |
58 | |
|
59 | 0 | aRect.SetLeft( -aOffset.X() ); |
60 | 0 | aRect.SetRight( -aOffset.X() ); |
61 | 0 | aRect.SetTop( -aOffset.Y() ); |
62 | 0 | aRect.SetBottom( -aOffset.Y() ); |
63 | |
|
64 | 0 | Point aMMOffset( aOffset ); |
65 | 0 | aMMOffset.setX(o3tl::convert(aMMOffset.X(), o3tl::Length::twip, o3tl::Length::mm100)); |
66 | 0 | aMMOffset.setY(o3tl::convert(aMMOffset.Y(), o3tl::Length::twip, o3tl::Length::mm100)); |
67 | |
|
68 | 0 | if (!mbMetaFile) |
69 | 0 | aMMOffset += Point( nLogStX, nLogStY ); |
70 | |
|
71 | 0 | for (nCol=mnX1; nCol<=mnX2; nCol++) |
72 | 0 | aRect.AdjustRight(mpDoc->GetColWidth( nCol, mnTab ) ); |
73 | 0 | aRect.AdjustBottom(mpDoc->GetRowHeight( mnY1, mnY2, mnTab ) ); |
74 | |
|
75 | 0 | aRect.SetLeft(o3tl::convert(aRect.Left(), o3tl::Length::twip, o3tl::Length::mm100)); |
76 | 0 | aRect.SetTop(o3tl::convert(aRect.Top(), o3tl::Length::twip, o3tl::Length::mm100)); |
77 | 0 | aRect.SetRight(o3tl::convert(aRect.Right(), o3tl::Length::twip, o3tl::Length::mm100)); |
78 | 0 | aRect.SetBottom(o3tl::convert(aRect.Bottom(), o3tl::Length::twip, o3tl::Length::mm100)); |
79 | |
|
80 | 0 | if(mpViewShell || mpDrawView) |
81 | 0 | { |
82 | 0 | SdrView* pLocalDrawView = mpDrawView ? mpDrawView : mpViewShell->GetScDrawView(); |
83 | |
|
84 | 0 | if(pLocalDrawView) |
85 | 0 | { |
86 | | // #i76114# MapMode has to be set because BeginDrawLayers uses GetPaintRegion |
87 | 0 | MapMode aOldMode = mpDev->GetMapMode(); |
88 | 0 | if (!mbMetaFile) |
89 | 0 | mpDev->SetMapMode( MapMode( MapUnit::Map100thMM, aMMOffset, aOldMode.GetScaleX(), aOldMode.GetScaleY() ) ); |
90 | | |
91 | | // #i74769# work with SdrPaintWindow directly |
92 | | // #i76114# pass bDisableIntersect = true, because the intersection of the table area |
93 | | // with the Window's paint region can be empty |
94 | 0 | vcl::Region aRectRegion(aRect); |
95 | 0 | mpTargetPaintWindow = pLocalDrawView->BeginDrawLayers(mpDev, aRectRegion, true); |
96 | 0 | OSL_ENSURE(mpTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)"); |
97 | |
|
98 | 0 | if (!mbMetaFile) |
99 | 0 | mpDev->SetMapMode( aOldMode ); |
100 | 0 | } |
101 | 0 | } |
102 | |
|
103 | 0 | return aMMOffset; |
104 | 0 | } |
105 | | |
106 | | // #i72502# |
107 | | void ScOutputData::PostPrintDrawingLayer(const Point& rMMOffset) // #i74768# |
108 | 0 | { |
109 | | // #i74768# just use offset as in PrintDrawingLayer() to also get the form controls |
110 | | // painted with offset |
111 | 0 | MapMode aOldMode = mpDev->GetMapMode(); |
112 | |
|
113 | 0 | if (!mbMetaFile) |
114 | 0 | { |
115 | 0 | mpDev->SetMapMode( MapMode( MapUnit::Map100thMM, rMMOffset, aOldMode.GetScaleX(), aOldMode.GetScaleY() ) ); |
116 | 0 | } |
117 | |
|
118 | 0 | if(mpViewShell || mpDrawView) |
119 | 0 | { |
120 | 0 | SdrView* pLocalDrawView = mpDrawView ? mpDrawView : mpViewShell->GetScDrawView(); |
121 | |
|
122 | 0 | if(pLocalDrawView) |
123 | 0 | { |
124 | | // #i74769# work with SdrPaintWindow directly |
125 | 0 | pLocalDrawView->EndDrawLayers(*mpTargetPaintWindow, true); |
126 | 0 | mpTargetPaintWindow = nullptr; |
127 | 0 | } |
128 | 0 | } |
129 | | |
130 | | // #i74768# |
131 | 0 | if (!mbMetaFile) |
132 | 0 | { |
133 | 0 | mpDev->SetMapMode( aOldMode ); |
134 | 0 | } |
135 | 0 | } |
136 | | |
137 | | // #i72502# |
138 | | void ScOutputData::PrintDrawingLayer(SdrLayerID nLayer, const Point& rMMOffset) |
139 | 0 | { |
140 | 0 | bool bHideAllDrawingLayer(false); |
141 | |
|
142 | 0 | if(mpViewShell || mpDrawView) |
143 | 0 | { |
144 | 0 | SdrView* pLocalDrawView = mpDrawView ? mpDrawView : mpViewShell->GetScDrawView(); |
145 | |
|
146 | 0 | if(pLocalDrawView) |
147 | 0 | { |
148 | 0 | bHideAllDrawingLayer = pLocalDrawView->getHideOle() && pLocalDrawView->getHideChart() |
149 | 0 | && pLocalDrawView->getHideDraw() && pLocalDrawView->getHideFormControl(); |
150 | 0 | } |
151 | 0 | } |
152 | |
|
153 | 0 | if(bHideAllDrawingLayer || (!mpDoc->GetDrawLayer())) |
154 | 0 | { |
155 | 0 | return; |
156 | 0 | } |
157 | | |
158 | 0 | MapMode aOldMode = mpDev->GetMapMode(); |
159 | |
|
160 | 0 | if (!mbMetaFile) |
161 | 0 | { |
162 | 0 | mpDev->SetMapMode( MapMode( MapUnit::Map100thMM, rMMOffset, aOldMode.GetScaleX(), aOldMode.GetScaleY() ) ); |
163 | 0 | } |
164 | |
|
165 | 0 | DrawSelectiveObjects( nLayer ); |
166 | |
|
167 | 0 | if (!mbMetaFile) |
168 | 0 | { |
169 | 0 | mpDev->SetMapMode( aOldMode ); |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | void ScOutputData::DrawSelectiveObjects(SdrLayerID nLayer) |
174 | 0 | { |
175 | 0 | ScDrawLayer* pModel = mpDoc->GetDrawLayer(); |
176 | 0 | if (!pModel) |
177 | 0 | return; |
178 | | |
179 | | // #i46362# high contrast mode (and default text direction) must be handled |
180 | | // by the application, so it's still needed when using DrawLayer(). |
181 | | |
182 | 0 | SdrOutliner& rOutl = pModel->GetDrawOutliner(); |
183 | 0 | rOutl.EnableAutoColor( mbUseStyleColor ); |
184 | 0 | rOutl.SetDefaultHorizontalTextDirection( |
185 | 0 | mpDoc->GetEditTextDirection( mnTab ) ); |
186 | 0 | Color aOldOutlinerBackgroundColor = rOutl.GetBackgroundColor(); |
187 | 0 | const ScTabViewShell* pTabViewShellBg = mbUseStyleColor ? ScTabViewShell::GetActiveViewShell() : nullptr; |
188 | 0 | if (pTabViewShellBg) |
189 | 0 | { |
190 | | // Similar to writer's SwViewShellImp::PaintLayer set the default |
191 | | // background of the Outliner for the AutoColor cases where there is no |
192 | | // explicit background known. But like elsewhere in calc, take |
193 | | // mbUseStyleColor of false as ScAutoFontColorMode::Print for print |
194 | | // output, so don't set a default outliner background then. |
195 | 0 | const ScViewRenderingOptions& rViewRenderingOptions = pTabViewShellBg->GetViewRenderingData(); |
196 | 0 | rOutl.SetBackgroundColor(rViewRenderingOptions.GetDocColor()); |
197 | 0 | } |
198 | | |
199 | | // #i69767# The hyphenator must be set (used to be before drawing a text shape with hyphenation). |
200 | | // LinguMgr::GetHyphenator (EditEngine) uses a wrapper now that creates the real hyphenator on demand, |
201 | | // so it's not a performance problem to call UseHyphenator even when it's not needed. |
202 | |
|
203 | 0 | pModel->UseHyphenator(); |
204 | |
|
205 | 0 | DrawModeFlags nOldDrawMode = mpDev->GetDrawMode(); |
206 | 0 | if ( mbUseStyleColor && Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) |
207 | 0 | { |
208 | 0 | mpDev->SetDrawMode( nOldDrawMode | DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill | |
209 | 0 | DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient ); |
210 | 0 | } |
211 | |
|
212 | 0 | if(mpViewShell || mpDrawView) |
213 | 0 | { |
214 | 0 | SdrView* pLocalDrawView = mpDrawView ? mpDrawView : mpViewShell->GetScDrawView(); |
215 | |
|
216 | 0 | if(pLocalDrawView) |
217 | 0 | { |
218 | 0 | SdrPageView* pPageView = pLocalDrawView->GetSdrPageView(); |
219 | |
|
220 | 0 | if(pPageView) |
221 | 0 | { |
222 | | // tdf#160589 need to check for registered PaintWindow using the |
223 | | // 'original' TargetDevice, mpDev might have been changed by a |
224 | | // call to ::SetContentDevice. That again might patch in a |
225 | | // pre-render device fetched from SdrPaintWindow::GetTargetOutputDevice |
226 | | // and thus the test if target is a registered PageWindow would fail |
227 | 0 | assert(nullptr != mpOriginalTargetDevice && "mpOriginalTargetDevice *must* be set when constructing ScOutputData (!)"); |
228 | 0 | if (nullptr != pPageView->FindPageWindow(*mpOriginalTargetDevice)) |
229 | 0 | { |
230 | | // Target OutputDevice is registered for this view |
231 | | // (as it should be), we can just render |
232 | 0 | pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); |
233 | 0 | } |
234 | 0 | else if (0 != pPageView->PageWindowCount()) |
235 | 0 | { |
236 | | // We need to temporarily make the target OutputDevice being |
237 | | // 'known/registered' in the paint mechanism so that |
238 | | // SdrPageView::DrawLayer can find it. |
239 | | // This situation can occur when someone interprets the |
240 | | // OutputDevice parameter that gets handed over to DrawLayer |
241 | | // (or other SdrPageView repaint methods) to be there to |
242 | | // define a new render target. |
243 | | // This is *not* the case: This parameter is used to |
244 | | // *identify* an already registered target-OutputDevice. |
245 | | // The default is even to call with a nullptr -> that triggers |
246 | | // the repaint for *all* registered OutputDevices/Windows. |
247 | | // Since this is a common and known misinterpretation it |
248 | | // is good to offer workarounds in the code - there are some |
249 | | // already. |
250 | | // For now - use an already existing 'patch mechanism' and |
251 | | // 'smuggle' the unknown/temporary OutputDevice as a |
252 | | // temporary SdrPaintWindow to the SdrPageWindow, that is |
253 | | // not very expensive. |
254 | | // NOTE: Just using the 1st SdrPageWindow here will be OK |
255 | | // in most cases, the splitting of a view is only used |
256 | | // in calc nowadays and should have identical zoom. |
257 | | // Still, trigger a warning... |
258 | 0 | OSL_ENSURE(1 == pPageView->PageWindowCount(), |
259 | 0 | "ScOutputData::DrawSelectiveObjects: More than one SdrPageView, still using 1st one (!)"); |
260 | 0 | SdrPageWindow* patchedPageWindow(pPageView->GetPageWindow(0)); |
261 | 0 | assert(nullptr != patchedPageWindow && "SdrPageWindow *must* exist when 0 != PageWindowCount()"); |
262 | 0 | SdrPaintWindow temporaryPaintWindow(*pLocalDrawView, *mpDev); |
263 | 0 | SdrPaintWindow* previousPaintWindow(patchedPageWindow->patchPaintWindow(temporaryPaintWindow)); |
264 | 0 | pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); |
265 | 0 | patchedPageWindow->unpatchPaintWindow(previousPaintWindow); |
266 | 0 | } |
267 | 0 | else |
268 | 0 | { |
269 | | // There does not even exist a SdrPageWindow. Still call the |
270 | | // paint to get the paint done, but be aware that this will create |
271 | | // temporary SdrPaintWindow and SdrPageWindow and - due to the |
272 | | // former - will not be able to use the decomposition buffering |
273 | | // in the VC/VOC/OC mechanism. For that reason this might be |
274 | | // somewhat 'expensive'. |
275 | | // You will also get a warning about it (see OSL_FAIL in |
276 | | // SdrPageView::DrawLayer) |
277 | 0 | pPageView->DrawLayer(sal::static_int_cast<SdrLayerID>(nLayer), mpDev); |
278 | 0 | } |
279 | 0 | } |
280 | 0 | } |
281 | 0 | } |
282 | |
|
283 | 0 | if (pTabViewShellBg) |
284 | 0 | rOutl.SetBackgroundColor(aOldOutlinerBackgroundColor); |
285 | |
|
286 | 0 | mpDev->SetDrawMode(nOldDrawMode); |
287 | 0 | } |
288 | | |
289 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |