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 "pdffilter.hxx"
21 #include "pdfexport.hxx"
22 #include <cppuhelper/supportsservice.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/window.hxx>
25 #include <svl/outstrm.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
27 #include <unotools/tempfile.hxx>
28 #include <vcl/FilterConfigItem.hxx>
29 #include <memory>
30 
31 #include <com/sun/star/io/XOutputStream.hpp>
32 
33 using namespace ::com::sun::star::io;
34 
PDFFilter(const Reference<XComponentContext> & rxContext)35 PDFFilter::PDFFilter( const Reference< XComponentContext > &rxContext ) :
36     mxContext( rxContext )
37 {
38 }
39 
40 
~PDFFilter()41 PDFFilter::~PDFFilter()
42 {
43 }
44 
45 
implExport(const Sequence<PropertyValue> & rDescriptor)46 bool PDFFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
47 {
48     Reference< XOutputStream >  xOStm;
49     Sequence< PropertyValue >   aFilterData;
50     sal_Int32                   nLength = rDescriptor.getLength();
51     const PropertyValue*        pValue = rDescriptor.getConstArray();
52     bool                        bIsRedactMode = false;
53     bool                    bRet = false;
54     Reference< task::XStatusIndicator > xStatusIndicator;
55     Reference< task::XInteractionHandler > xIH;
56 
57     for (sal_Int32 i = 0; i < nLength; ++i)
58     {
59         if ( pValue[ i ].Name == "OutputStream" )
60             pValue[ i ].Value >>= xOStm;
61         else if ( pValue[ i ].Name == "FilterData" )
62             pValue[ i ].Value >>= aFilterData;
63         else if ( pValue[ i ].Name == "StatusIndicator" )
64             pValue[ i ].Value >>= xStatusIndicator;
65         else if ( pValue[i].Name == "InteractionHandler" )
66             pValue[i].Value >>= xIH;
67     }
68 
69     for (sal_Int32 i = 0 ; i < nLength; ++i)
70     {
71         if ( pValue[i].Name == "IsRedactMode")
72             pValue[i].Value >>= bIsRedactMode;
73     }
74 
75     /* we don't get FilterData if we are exporting directly
76        to pdf, but we have to use the last user settings (especially for the CompressMode) */
77     if ( !aFilterData.hasElements() )
78     {
79         FilterConfigItem aCfgItem( u"Office.Common/Filter/PDF/Export/" );
80         aCfgItem.ReadBool(  "UseLosslessCompression", false );
81         aCfgItem.ReadInt32( "Quality", 90 );
82         aCfgItem.ReadBool(  "ReduceImageResolution", false );
83         aCfgItem.ReadInt32( "MaxImageResolution", 300 );
84         aCfgItem.ReadBool(  "UseTaggedPDF", false );
85         aCfgItem.ReadInt32( "SelectPdfVersion", 0 );
86         aCfgItem.ReadBool("PDFUACompliance", false);
87         aCfgItem.ReadBool(  "ExportNotes", false );
88         aCfgItem.ReadBool( "ExportPlaceholders", false );
89         aCfgItem.ReadBool(  "ExportNotesPages", false );
90         aCfgItem.ReadBool(  "ExportOnlyNotesPages", false );
91         aCfgItem.ReadBool(  "UseTransitionEffects", true );
92         aCfgItem.ReadBool(  "IsSkipEmptyPages", false );
93         aCfgItem.ReadBool(  "ExportFormFields", true );
94         aCfgItem.ReadInt32( "FormsType", 0 );
95         aCfgItem.ReadBool(  "HideViewerToolbar", false );
96         aCfgItem.ReadBool(  "HideViewerMenubar", false );
97         aCfgItem.ReadBool(  "HideViewerWindowControls", false );
98         aCfgItem.ReadBool(  "ResizeWindowToInitialPage", false );
99         aCfgItem.ReadBool(  "CenterWindow", false );
100         aCfgItem.ReadBool(  "OpenInFullScreenMode", false );
101         aCfgItem.ReadBool(  "DisplayPDFDocumentTitle", true );
102         aCfgItem.ReadInt32( "InitialView", 0 );
103         aCfgItem.ReadInt32( "Magnification", 0 );
104         aCfgItem.ReadInt32( "Zoom", 100 );
105         aCfgItem.ReadInt32( "PageLayout", 0 );
106         aCfgItem.ReadBool(  "FirstPageOnLeft", false );
107         aCfgItem.ReadInt32( "InitialPage", 1 );
108         aCfgItem.ReadBool(  "IsAddStream", false );
109 
110         // the encryption is not available when exporting directly, since the encryption is off by default and the selection
111         // (encrypt or not) is not persistent; it's available through macro though,
112         // provided the correct property values are set, see help
113 
114         // now, the relative link stuff
115         aCfgItem.ReadBool( "ExportLinksRelativeFsys", false );
116         aCfgItem.ReadInt32("PDFViewSelection", 0 );
117         aCfgItem.ReadBool( "ConvertOOoTargetToPDFTarget", false );
118         aCfgItem.ReadBool( "ExportBookmarksToPDFDestination", false );
119 
120         aCfgItem.ReadBool(  "ExportBookmarks", true );
121         aCfgItem.ReadBool(  "ExportHiddenSlides", false );
122         aCfgItem.ReadBool(  "SinglePageSheets", false );
123         aCfgItem.ReadInt32( "OpenBookmarkLevels", -1 );
124 
125         aCfgItem.ReadBool( "IsRedactMode", false);
126 
127         aFilterData = aCfgItem.GetFilterData();
128     }
129 
130 
131     if (bIsRedactMode)
132     {
133         bool bFound = false;
134 
135         for (PropertyValue& rProp : aFilterData)
136         {
137             if (rProp.Name == "IsRedactMode")
138             {
139                 rProp.Value <<= bIsRedactMode;
140                 bFound = true;
141                 break;
142             }
143         }
144 
145         if (!bFound)
146         {
147             sal_Int32 nNewSize = aFilterData.getLength() + 1;
148             aFilterData.realloc( nNewSize );
149             aFilterData[nNewSize - 1].Name = "IsRedactMode";
150             aFilterData[nNewSize - 1].Value <<= bIsRedactMode;
151         }
152     }
153 
154     if( mxSrcDoc.is() && xOStm.is() )
155     {
156         PDFExport       aExport( mxSrcDoc, xStatusIndicator, xIH, mxContext );
157         ::utl::TempFile aTempFile;
158 
159         aTempFile.EnableKillingFile();
160         bRet = aExport.Export( aTempFile.GetURL(), aFilterData );
161 
162         if( bRet )
163         {
164             std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ ));
165 
166             if( pIStm )
167             {
168                 SvOutputStream aOStm( xOStm );
169 
170                 aOStm.WriteStream( *pIStm );
171                 bRet = ( aOStm.Tell() && ( aOStm.GetError() == ERRCODE_NONE ) );
172             }
173         }
174     }
175 
176     return bRet;
177 }
178 
179 namespace {
180 
181 class FocusWindowWaitCursor
182 {
183 private:
184 
185     VclPtr<vcl::Window>         m_pFocusWindow;
186 
187 public:
FocusWindowWaitCursor()188     FocusWindowWaitCursor() :
189         m_pFocusWindow( Application::GetFocusWindow() )
190     {
191         if( m_pFocusWindow )
192         {
193             m_pFocusWindow->AddEventListener( LINK( this, FocusWindowWaitCursor, DestroyedLink ) );
194             m_pFocusWindow->EnterWait();
195         }
196     }
197 
~FocusWindowWaitCursor()198     ~FocusWindowWaitCursor()
199     {
200         if( m_pFocusWindow )
201         {
202             m_pFocusWindow->LeaveWait();
203             m_pFocusWindow->RemoveEventListener( LINK( this, FocusWindowWaitCursor, DestroyedLink ) );
204         }
205     }
206 
207     DECL_LINK( DestroyedLink, VclWindowEvent&, void );
208 };
209 
210 }
211 
IMPL_LINK(FocusWindowWaitCursor,DestroyedLink,VclWindowEvent &,rEvent,void)212 IMPL_LINK( FocusWindowWaitCursor, DestroyedLink, VclWindowEvent&, rEvent, void )
213 {
214     if( rEvent.GetId() == VclEventId::ObjectDying )
215         m_pFocusWindow = nullptr;
216 }
217 
218 
filter(const Sequence<PropertyValue> & rDescriptor)219 sal_Bool SAL_CALL PDFFilter::filter( const Sequence< PropertyValue >& rDescriptor )
220 {
221     FocusWindowWaitCursor aCur;
222 
223     const bool bRet = implExport( rDescriptor );
224 
225     return bRet;
226 }
227 
228 
cancel()229 void SAL_CALL PDFFilter::cancel( )
230 {
231 }
232 
233 
setSourceDocument(const Reference<XComponent> & xDoc)234 void SAL_CALL PDFFilter::setSourceDocument( const Reference< XComponent >& xDoc )
235 {
236     mxSrcDoc = xDoc;
237 }
238 
239 
initialize(const css::uno::Sequence<css::uno::Any> &)240 void SAL_CALL PDFFilter::initialize( const css::uno::Sequence< css::uno::Any >& )
241 {
242 }
243 
244 
getImplementationName()245 OUString SAL_CALL PDFFilter::getImplementationName()
246 {
247     return "com.sun.star.comp.PDF.PDFFilter";
248 }
249 
250 
supportsService(const OUString & rServiceName)251 sal_Bool SAL_CALL PDFFilter::supportsService( const OUString& rServiceName )
252 {
253     return cppu::supportsService( this, rServiceName );
254 }
255 
256 
getSupportedServiceNames()257 css::uno::Sequence< OUString > SAL_CALL PDFFilter::getSupportedServiceNames(  )
258 {
259     return { "com.sun.star.document.PDFFilter" };
260 }
261 
262 
263 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
filter_PDFFilter_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)264 filter_PDFFilter_get_implementation(
265     css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
266 {
267     return cppu::acquire(new PDFFilter(context));
268 }
269 
270 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
271