summaryrefslogtreecommitdiffstats
path: root/sw/source/core/doc/DocumentDeviceManager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc/DocumentDeviceManager.cxx')
-rw-r--r--sw/source/core/doc/DocumentDeviceManager.cxx370
1 files changed, 370 insertions, 0 deletions
diff --git a/sw/source/core/doc/DocumentDeviceManager.cxx b/sw/source/core/doc/DocumentDeviceManager.cxx
new file mode 100644
index 0000000000..b90474082c
--- /dev/null
+++ b/sw/source/core/doc/DocumentDeviceManager.cxx
@@ -0,0 +1,370 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <DocumentDeviceManager.hxx>
+
+#include <memory>
+#include <utility>
+
+#include <doc.hxx>
+#include <DocumentSettingManager.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentState.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <osl/diagnose.h>
+#include <sfx2/printer.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/jobset.hxx>
+#include <printdata.hxx>
+#include <vcl/mapmod.hxx>
+#include <svl/itemset.hxx>
+#include <cfgitems.hxx>
+#include <cmdid.h>
+#include <drawdoc.hxx>
+#include <wdocsh.hxx>
+#include <prtopt.hxx>
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+#include <viewopt.hxx>
+#include <swwait.hxx>
+#include <fntcache.hxx>
+
+class SwDocShell;
+class SwWait;
+
+namespace sw {
+
+DocumentDeviceManager::DocumentDeviceManager( SwDoc& i_rSwdoc ) : m_rDoc( i_rSwdoc ), mpPrt(nullptr), mpVirDev(nullptr) {}
+
+SfxPrinter* DocumentDeviceManager::getPrinter(/*[in]*/ bool bCreate ) const
+{
+ SfxPrinter* pRet = nullptr;
+ if ( !bCreate || mpPrt )
+ pRet = mpPrt;
+ else
+ pRet = &CreatePrinter_();
+
+ return pRet;
+}
+
+void DocumentDeviceManager::setPrinter(/*[in]*/ SfxPrinter *pP,/*[in]*/ bool bDeleteOld,/*[in]*/ bool bCallPrtDataChanged )
+{
+ assert ( !pP || !pP->isDisposed() );
+ if ( pP != mpPrt )
+ {
+ if ( bDeleteOld )
+ mpPrt.disposeAndClear();
+ mpPrt = pP;
+
+ // our printer should always use TWIP. Don't rely on this being set in SwViewShell::InitPrt, there
+ // are situations where this isn't called. #i108712#
+ if ( mpPrt )
+ {
+ MapMode aMapMode( mpPrt->GetMapMode() );
+ aMapMode.SetMapUnit( MapUnit::MapTwip );
+ mpPrt->SetMapMode( aMapMode );
+ }
+
+ if ( m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() && !m_rDoc.GetDocumentSettingManager().get( DocumentSettingId::USE_VIRTUAL_DEVICE ) )
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( mpPrt );
+ }
+
+ if ( bCallPrtDataChanged &&
+ // #i41075# Do not call PrtDataChanged() if we do not
+ // use the printer for formatting:
+ !m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE) )
+ PrtDataChanged();
+}
+
+VirtualDevice* DocumentDeviceManager::getVirtualDevice(/*[in]*/ bool bCreate ) const
+{
+ VirtualDevice* pRet = nullptr;
+ if ( !bCreate || mpVirDev )
+ pRet = mpVirDev;
+ else
+ pRet = &CreateVirtualDevice_();
+
+ assert ( !pRet || !pRet->isDisposed() );
+
+ return pRet;
+}
+
+void DocumentDeviceManager::setVirtualDevice(/*[in]*/ VirtualDevice* pVd )
+{
+ assert ( !pVd->isDisposed() );
+
+ if ( mpVirDev.get() != pVd )
+ {
+ mpVirDev.disposeAndClear();
+ mpVirDev = pVd;
+
+ if ( m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() && m_rDoc.GetDocumentSettingManager().get( DocumentSettingId::USE_VIRTUAL_DEVICE ) )
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( mpVirDev );
+ }
+}
+
+OutputDevice* DocumentDeviceManager::getReferenceDevice(/*[in]*/ bool bCreate ) const
+{
+ OutputDevice* pRet = nullptr;
+ if ( !m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE) )
+ {
+ pRet = getPrinter( bCreate );
+
+ if ( bCreate && !mpPrt->IsValid() )
+ {
+ pRet = getVirtualDevice( true );
+ }
+ }
+ else
+ {
+ pRet = getVirtualDevice( bCreate );
+ }
+
+ assert ( !pRet || !pRet->isDisposed() );
+
+ return pRet;
+}
+
+void DocumentDeviceManager::setReferenceDeviceType(/*[in]*/ bool bNewVirtual, /*[in]*/ bool bNewHiRes )
+{
+ if ( m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE) == bNewVirtual &&
+ m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE) == bNewHiRes )
+ return;
+
+ if ( bNewVirtual )
+ {
+ VirtualDevice* pMyVirDev = getVirtualDevice( true );
+ if ( !bNewHiRes )
+ pMyVirDev->SetReferenceDevice( VirtualDevice::RefDevMode::Dpi600 );
+ else
+ pMyVirDev->SetReferenceDevice( VirtualDevice::RefDevMode::MSO1 );
+
+ if( m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() )
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( pMyVirDev );
+ }
+ else
+ {
+ // #i41075#
+ // We have to take care that a printer exists before calling
+ // PrtDataChanged() in order to prevent that PrtDataChanged()
+ // triggers this funny situation:
+ // getReferenceDevice()->getPrinter()->CreatePrinter_()
+ // ->setPrinter()-> PrtDataChanged()
+ SfxPrinter* pPrinter = getPrinter( true );
+ if( m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() )
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( pPrinter );
+ }
+
+ m_rDoc.GetDocumentSettingManager().set(DocumentSettingId::USE_VIRTUAL_DEVICE, bNewVirtual );
+ m_rDoc.GetDocumentSettingManager().set(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE, bNewHiRes );
+ PrtDataChanged();
+ m_rDoc.getIDocumentState().SetModified();
+}
+
+const JobSetup* DocumentDeviceManager::getJobsetup() const
+{
+ return mpPrt ? &mpPrt->GetJobSetup() : nullptr;
+}
+
+void DocumentDeviceManager::setJobsetup(/*[in]*/ const JobSetup &rJobSetup )
+{
+ bool bCheckPageDescs = !mpPrt;
+ bool bDataChanged = false;
+
+ if ( mpPrt )
+ {
+ if ( mpPrt->GetName() == rJobSetup.GetPrinterName() )
+ {
+ if ( mpPrt->GetJobSetup() != rJobSetup )
+ {
+ mpPrt->SetJobSetup( rJobSetup );
+ bDataChanged = true;
+ }
+ }
+ else
+ mpPrt.disposeAndClear();
+ }
+
+ if( !mpPrt )
+ {
+ //The ItemSet is deleted by Sfx!
+ auto pSet = std::make_unique<SfxItemSetFixed<
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER>>(m_rDoc.GetAttrPool());
+ VclPtr<SfxPrinter> p = VclPtr<SfxPrinter>::Create( std::move(pSet), rJobSetup );
+ if ( bCheckPageDescs )
+ setPrinter( p, true, true );
+ else
+ {
+ mpPrt = p;
+ bDataChanged = true;
+ }
+ }
+ if ( bDataChanged && !m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::USE_VIRTUAL_DEVICE) )
+ PrtDataChanged();
+}
+
+const SwPrintData & DocumentDeviceManager::getPrintData() const
+{
+ if(!mpPrtData)
+ {
+ DocumentDeviceManager * pThis = const_cast< DocumentDeviceManager * >(this);
+ pThis->mpPrtData.reset(new SwPrintData);
+
+ // SwPrintData should be initialized from the configuration,
+ // the respective config item is implemented by SwPrintOptions which
+ // is also derived from SwPrintData
+ const SwDocShell *pDocSh = m_rDoc.GetDocShell();
+ OSL_ENSURE( pDocSh, "pDocSh is 0, can't determine if this is a WebDoc or not" );
+ bool bWeb = dynamic_cast< const SwWebDocShell * >(pDocSh) != nullptr;
+ SwPrintOptions aPrintOptions( bWeb );
+ *pThis->mpPrtData = aPrintOptions;
+ }
+ assert(mpPrtData && "this will always be set by now");
+ return *mpPrtData;
+}
+
+void DocumentDeviceManager::setPrintData(/*[in]*/ const SwPrintData& rPrtData )
+{
+ if(!mpPrtData)
+ mpPrtData.reset(new SwPrintData);
+ *mpPrtData = rPrtData;
+}
+
+DocumentDeviceManager::~DocumentDeviceManager()
+{
+ mpPrtData.reset();
+ mpVirDev.disposeAndClear();
+ mpPrt.disposeAndClear();
+}
+
+VirtualDevice& DocumentDeviceManager::CreateVirtualDevice_() const
+{
+#ifdef IOS
+ VclPtr<VirtualDevice> pNewVir = VclPtr<VirtualDevice>::Create(DeviceFormat::GRAYSCALE);
+#else
+ VclPtr<VirtualDevice> pNewVir = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
+#endif
+
+ pNewVir->SetReferenceDevice( VirtualDevice::RefDevMode::MSO1 );
+
+ // #i60945# External leading compatibility for unix systems.
+ if ( m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::UNIX_FORCE_ZERO_EXT_LEADING ) )
+ pNewVir->Compat_ZeroExtleadBug();
+
+ MapMode aMapMode( pNewVir->GetMapMode() );
+ aMapMode.SetMapUnit( MapUnit::MapTwip );
+ pNewVir->SetMapMode( aMapMode );
+
+ const_cast<DocumentDeviceManager*>(this)->setVirtualDevice( pNewVir );
+ return *mpVirDev;
+}
+
+SfxPrinter& DocumentDeviceManager::CreatePrinter_() const
+{
+ OSL_ENSURE( ! mpPrt, "Do not call CreatePrinter_(), call getPrinter() instead" );
+
+ // We create a default SfxPrinter.
+ // The ItemSet is deleted by Sfx!
+ auto pSet = std::make_unique<SfxItemSetFixed<
+ SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
+ SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
+ SID_HTML_MODE, SID_HTML_MODE,
+ FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER>>(m_rDoc.GetAttrPool());
+
+ VclPtr<SfxPrinter> pNewPrt = VclPtr<SfxPrinter>::Create( std::move(pSet) );
+
+ // assign PrintData to newly created printer
+ const SwPrintData& rPrtData = getPrintData();
+ SwAddPrinterItem aAddPrinterItem(rPrtData);
+ SfxItemSet aOptions(pNewPrt->GetOptions());
+ aOptions.Put(aAddPrinterItem);
+ pNewPrt->SetOptions(aOptions);
+
+ const_cast<DocumentDeviceManager*>(this)->setPrinter( pNewPrt, true, true );
+ return *mpPrt;
+}
+
+void DocumentDeviceManager::PrtDataChanged()
+{
+// If you change this, also modify InJobSetup in Sw3io if appropriate.
+
+ // #i41075#
+ OSL_ENSURE( m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::USE_VIRTUAL_DEVICE) ||
+ nullptr != getPrinter( false ), "PrtDataChanged will be called recursively!" );
+ SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
+ std::optional<SwWait> oWait;
+ bool bEndAction = false;
+
+ if( m_rDoc.GetDocShell() )
+ m_rDoc.GetDocShell()->UpdateFontList();
+
+ bool bDraw = true;
+ if ( pTmpRoot )
+ {
+ SwViewShell *pSh = m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell();
+ if( pSh &&
+ (!pSh->GetViewOptions()->getBrowseMode() ||
+ pSh->GetViewOptions()->IsPrtFormat()) )
+ {
+ if ( m_rDoc.GetDocShell() )
+ oWait.emplace( *m_rDoc.GetDocShell(), true );
+
+ pTmpRoot->StartAllAction();
+ bEndAction = true;
+
+ bDraw = false;
+ if( m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() )
+ {
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetAddExtLeading( m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::ADD_EXT_LEADING) );
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( getReferenceDevice( false ) );
+ }
+
+ pFntCache->Flush();
+
+ for(SwRootFrame* aLayout : m_rDoc.GetAllLayouts())
+ aLayout->InvalidateAllContent(SwInvalidateFlags::Size);
+
+ for(SwViewShell& rShell : pSh->GetRingContainer())
+ rShell.InitPrt(getPrinter(false));
+ }
+ }
+ if ( bDraw && m_rDoc.getIDocumentDrawModelAccess().GetDrawModel() )
+ {
+ const bool bTmpAddExtLeading = m_rDoc.GetDocumentSettingManager().get(DocumentSettingId::ADD_EXT_LEADING);
+ if ( bTmpAddExtLeading != m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->IsAddExtLeading() )
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetAddExtLeading( bTmpAddExtLeading );
+
+ OutputDevice* pOutDev = getReferenceDevice( false );
+ if ( pOutDev != m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->GetRefDevice() )
+ m_rDoc.getIDocumentDrawModelAccess().GetDrawModel()->SetRefDevice( pOutDev );
+ }
+
+ m_rDoc.PrtOLENotify( true );
+
+ if ( bEndAction )
+ pTmpRoot->EndAllAction();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */