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 <DocumentDeviceManager.hxx>
26 #include <DocumentSettingManager.hxx>
27 #include <IDocumentDrawModelAccess.hxx>
28 #include <IDocumentState.hxx>
29 #include <IDocumentLayoutAccess.hxx>
30 #include <osl/diagnose.h>
31 #include <sfx2/printer.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/outdev.hxx>
34 #include <vcl/jobset.hxx>
35 #include <printdata.hxx>
36 #include <vcl/mapmod.hxx>
37 #include <svl/itemset.hxx>
38 #include <cfgitems.hxx>
40 #include <drawdoc.hxx>
44 #include <rootfrm.hxx>
45 #include <viewopt.hxx>
47 #include <fntcache.hxx>
54 DocumentDeviceManager::DocumentDeviceManager( SwDoc
& i_rSwdoc
) : m_rDoc( i_rSwdoc
), mpPrt(nullptr), mpVirDev(nullptr) {}
56 SfxPrinter
* DocumentDeviceManager::getPrinter(/*[in]*/ bool bCreate
) const
58 SfxPrinter
* pRet
= nullptr;
59 if ( !bCreate
|| mpPrt
)
62 pRet
= &CreatePrinter_();
67 void DocumentDeviceManager::setPrinter(/*[in]*/ SfxPrinter
*pP
,/*[in]*/ bool bDeleteOld
,/*[in]*/ bool bCallPrtDataChanged
)
69 assert ( !pP
|| !pP
->isDisposed() );
73 mpPrt
.disposeAndClear();
76 // our printer should always use TWIP. Don't rely on this being set in SwViewShell::InitPrt, there
77 // are situations where this isn't called. #i108712#
80 MapMode
aMapMode( mpPrt
->GetMapMode() );
81 aMapMode
.SetMapUnit( MapUnit::MapTwip
);
82 mpPrt
->SetMapMode( aMapMode
);
85 if ( m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel() && !m_rDoc
.GetDocumentSettingManager().get( DocumentSettingId::USE_VIRTUAL_DEVICE
) )
86 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( mpPrt
);
89 if ( bCallPrtDataChanged
&&
90 // #i41075# Do not call PrtDataChanged() if we do not
91 // use the printer for formatting:
92 !m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE
) )
96 VirtualDevice
* DocumentDeviceManager::getVirtualDevice(/*[in]*/ bool bCreate
) const
98 VirtualDevice
* pRet
= nullptr;
99 if ( !bCreate
|| mpVirDev
)
102 pRet
= &CreateVirtualDevice_();
104 assert ( !pRet
|| !pRet
->isDisposed() );
109 void DocumentDeviceManager::setVirtualDevice(/*[in]*/ VirtualDevice
* pVd
)
111 assert ( !pVd
->isDisposed() );
113 if ( mpVirDev
.get() != pVd
)
115 mpVirDev
.disposeAndClear();
118 if ( m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel() && m_rDoc
.GetDocumentSettingManager().get( DocumentSettingId::USE_VIRTUAL_DEVICE
) )
119 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( mpVirDev
);
123 OutputDevice
* DocumentDeviceManager::getReferenceDevice(/*[in]*/ bool bCreate
) const
125 OutputDevice
* pRet
= nullptr;
126 if ( !m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE
) )
128 pRet
= getPrinter( bCreate
);
130 if ( bCreate
&& !mpPrt
->IsValid() )
132 pRet
= getVirtualDevice( true );
137 pRet
= getVirtualDevice( bCreate
);
140 assert ( !pRet
|| !pRet
->isDisposed() );
145 void DocumentDeviceManager::setReferenceDeviceType(/*[in]*/ bool bNewVirtual
, /*[in]*/ bool bNewHiRes
)
147 if ( m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE
) == bNewVirtual
&&
148 m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE
) == bNewHiRes
)
153 VirtualDevice
* pMyVirDev
= getVirtualDevice( true );
155 pMyVirDev
->SetReferenceDevice( VirtualDevice::RefDevMode::Dpi600
);
157 pMyVirDev
->SetReferenceDevice( VirtualDevice::RefDevMode::MSO1
);
159 if( m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel() )
160 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( pMyVirDev
);
165 // We have to take care that a printer exists before calling
166 // PrtDataChanged() in order to prevent that PrtDataChanged()
167 // triggers this funny situation:
168 // getReferenceDevice()->getPrinter()->CreatePrinter_()
169 // ->setPrinter()-> PrtDataChanged()
170 SfxPrinter
* pPrinter
= getPrinter( true );
171 if( m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel() )
172 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( pPrinter
);
175 m_rDoc
.GetDocumentSettingManager().set(DocumentSettingId::USE_VIRTUAL_DEVICE
, bNewVirtual
);
176 m_rDoc
.GetDocumentSettingManager().set(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE
, bNewHiRes
);
178 m_rDoc
.getIDocumentState().SetModified();
181 const JobSetup
* DocumentDeviceManager::getJobsetup() const
183 return mpPrt
? &mpPrt
->GetJobSetup() : nullptr;
186 void DocumentDeviceManager::setJobsetup(/*[in]*/ const JobSetup
&rJobSetup
)
188 bool bCheckPageDescs
= !mpPrt
;
189 bool bDataChanged
= false;
193 if ( mpPrt
->GetName() == rJobSetup
.GetPrinterName() )
195 if ( mpPrt
->GetJobSetup() != rJobSetup
)
197 mpPrt
->SetJobSetup( rJobSetup
);
202 mpPrt
.disposeAndClear();
207 //The ItemSet is deleted by Sfx!
208 auto pSet
= std::make_unique
<SfxItemSetFixed
<
209 SID_PRINTER_NOTFOUND_WARN
, SID_PRINTER_NOTFOUND_WARN
,
210 SID_PRINTER_CHANGESTODOC
, SID_PRINTER_CHANGESTODOC
,
211 SID_HTML_MODE
, SID_HTML_MODE
,
212 FN_PARAM_ADDPRINTER
, FN_PARAM_ADDPRINTER
>>(m_rDoc
.GetAttrPool());
213 VclPtr
<SfxPrinter
> p
= VclPtr
<SfxPrinter
>::Create( std::move(pSet
), rJobSetup
);
214 if ( bCheckPageDescs
)
215 setPrinter( p
, true, true );
222 if ( bDataChanged
&& !m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE
) )
226 const SwPrintData
& DocumentDeviceManager::getPrintData() const
230 DocumentDeviceManager
* pThis
= const_cast< DocumentDeviceManager
* >(this);
231 pThis
->mpPrtData
.reset(new SwPrintData
);
233 // SwPrintData should be initialized from the configuration,
234 // the respective config item is implemented by SwPrintOptions which
235 // is also derived from SwPrintData
236 const SwDocShell
*pDocSh
= m_rDoc
.GetDocShell();
237 OSL_ENSURE( pDocSh
, "pDocSh is 0, can't determine if this is a WebDoc or not" );
238 bool bWeb
= dynamic_cast< const SwWebDocShell
* >(pDocSh
) != nullptr;
239 SwPrintOptions
aPrintOptions( bWeb
);
240 *pThis
->mpPrtData
= aPrintOptions
;
242 assert(mpPrtData
&& "this will always be set by now");
246 void DocumentDeviceManager::setPrintData(/*[in]*/ const SwPrintData
& rPrtData
)
249 mpPrtData
.reset(new SwPrintData
);
250 *mpPrtData
= rPrtData
;
253 DocumentDeviceManager::~DocumentDeviceManager()
256 mpVirDev
.disposeAndClear();
257 mpPrt
.disposeAndClear();
260 VirtualDevice
& DocumentDeviceManager::CreateVirtualDevice_() const
263 VclPtr
<VirtualDevice
> pNewVir
= VclPtr
<VirtualDevice
>::Create(DeviceFormat::GRAYSCALE
);
265 VclPtr
<VirtualDevice
> pNewVir
= VclPtr
<VirtualDevice
>::Create(DeviceFormat::WITHOUT_ALPHA
);
268 pNewVir
->SetReferenceDevice( VirtualDevice::RefDevMode::MSO1
);
270 // #i60945# External leading compatibility for unix systems.
271 if ( m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::UNIX_FORCE_ZERO_EXT_LEADING
) )
272 pNewVir
->Compat_ZeroExtleadBug();
274 MapMode
aMapMode( pNewVir
->GetMapMode() );
275 aMapMode
.SetMapUnit( MapUnit::MapTwip
);
276 pNewVir
->SetMapMode( aMapMode
);
278 const_cast<DocumentDeviceManager
*>(this)->setVirtualDevice( pNewVir
);
282 SfxPrinter
& DocumentDeviceManager::CreatePrinter_() const
284 OSL_ENSURE( ! mpPrt
, "Do not call CreatePrinter_(), call getPrinter() instead" );
286 // We create a default SfxPrinter.
287 // The ItemSet is deleted by Sfx!
288 auto pSet
= std::make_unique
<SfxItemSetFixed
<
289 SID_PRINTER_NOTFOUND_WARN
, SID_PRINTER_NOTFOUND_WARN
,
290 SID_PRINTER_CHANGESTODOC
, SID_PRINTER_CHANGESTODOC
,
291 SID_HTML_MODE
, SID_HTML_MODE
,
292 FN_PARAM_ADDPRINTER
, FN_PARAM_ADDPRINTER
>>(m_rDoc
.GetAttrPool());
294 VclPtr
<SfxPrinter
> pNewPrt
= VclPtr
<SfxPrinter
>::Create( std::move(pSet
) );
296 // assign PrintData to newly created printer
297 const SwPrintData
& rPrtData
= getPrintData();
298 SwAddPrinterItem
aAddPrinterItem(rPrtData
);
299 SfxItemSet
aOptions(pNewPrt
->GetOptions());
300 aOptions
.Put(aAddPrinterItem
);
301 pNewPrt
->SetOptions(aOptions
);
303 const_cast<DocumentDeviceManager
*>(this)->setPrinter( pNewPrt
, true, true );
307 void DocumentDeviceManager::PrtDataChanged()
309 // If you change this, also modify InJobSetup in Sw3io if appropriate.
312 OSL_ENSURE( m_rDoc
.getIDocumentSettingAccess().get(DocumentSettingId::USE_VIRTUAL_DEVICE
) ||
313 nullptr != getPrinter( false ), "PrtDataChanged will be called recursively!" );
314 SwRootFrame
* pTmpRoot
= m_rDoc
.getIDocumentLayoutAccess().GetCurrentLayout();
315 std::optional
<SwWait
> oWait
;
316 bool bEndAction
= false;
318 if( m_rDoc
.GetDocShell() )
319 m_rDoc
.GetDocShell()->UpdateFontList();
324 SwViewShell
*pSh
= m_rDoc
.getIDocumentLayoutAccess().GetCurrentViewShell();
326 (!pSh
->GetViewOptions()->getBrowseMode() ||
327 pSh
->GetViewOptions()->IsPrtFormat()) )
329 if ( m_rDoc
.GetDocShell() )
330 oWait
.emplace( *m_rDoc
.GetDocShell(), true );
332 pTmpRoot
->StartAllAction();
336 if( m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel() )
338 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetAddExtLeading( m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::ADD_EXT_LEADING
) );
339 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( getReferenceDevice( false ) );
344 for(SwRootFrame
* aLayout
: m_rDoc
.GetAllLayouts())
345 aLayout
->InvalidateAllContent(SwInvalidateFlags::Size
);
347 for(SwViewShell
& rShell
: pSh
->GetRingContainer())
348 rShell
.InitPrt(getPrinter(false));
351 if ( bDraw
&& m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel() )
353 const bool bTmpAddExtLeading
= m_rDoc
.GetDocumentSettingManager().get(DocumentSettingId::ADD_EXT_LEADING
);
354 if ( bTmpAddExtLeading
!= m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->IsAddExtLeading() )
355 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetAddExtLeading( bTmpAddExtLeading
);
357 OutputDevice
* pOutDev
= getReferenceDevice( false );
358 if ( pOutDev
!= m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->GetRefDevice() )
359 m_rDoc
.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( pOutDev
);
362 m_rDoc
.PrtOLENotify( true );
365 pTmpRoot
->EndAllAction();
370 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */