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 <com/sun/star/drawing/GraphicExportFilter.hpp>
21
22 #include <vcl/errinf.hxx>
23 #include <vcl/weld.hxx>
24 #include <sfx2/sfxsids.hrc>
25 #include <sfx2/docfile.hxx>
26 #include <sfx2/docfilt.hxx>
27 #include <sfx2/sfxuno.hxx>
28 #include <svx/svdograf.hxx>
29
30 #include <strings.hrc>
31 #include <DrawViewShell.hxx>
32 #include <DrawDocShell.hxx>
33
34 #include <comphelper/processfactory.hxx>
35 #include <vcl/graphicfilter.hxx>
36 #include <vcl/svapp.hxx>
37
38 #include <sdpage.hxx>
39 #include <drawdoc.hxx>
40 #include <sdresid.hxx>
41 #include <sdgrffilter.hxx>
42 #include <ViewShellBase.hxx>
43 #include <com/sun/star/beans/PropertyValue.hpp>
44 #include <com/sun/star/beans/PropertyValues.hpp>
45 #include <com/sun/star/lang/XComponent.hpp>
46 #include <com/sun/star/view/XSelectionSupplier.hpp>
47 #include <cppuhelper/implbase.hxx>
48 #include <com/sun/star/task/XInteractionHandler.hpp>
49 #include <com/sun/star/task/XInteractionRequest.hpp>
50 #include <com/sun/star/drawing/GraphicFilterRequest.hpp>
51
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::beans;
56 using namespace ::com::sun::star::graphic;
57 using namespace ::com::sun::star::io;
58 using namespace ::com::sun::star::ucb;
59 using namespace com::sun::star::ui::dialogs;
60 using namespace ::sfx2;
61
62 class SdGRFFilter_ImplInteractionHdl : public ::cppu::WeakImplHelper< css::task::XInteractionHandler >
63 {
64 css::uno::Reference< css::task::XInteractionHandler > m_xInter;
65 ErrCode nFilterError;
66
67 public:
68
SdGRFFilter_ImplInteractionHdl(css::uno::Reference<css::task::XInteractionHandler> const & xInteraction)69 explicit SdGRFFilter_ImplInteractionHdl( css::uno::Reference< css::task::XInteractionHandler > const & xInteraction ) :
70 m_xInter( xInteraction ),
71 nFilterError( ERRCODE_NONE )
72 {}
73
GetErrorCode() const74 ErrCode const & GetErrorCode() const { return nFilterError; };
75
76 virtual void SAL_CALL handle( const css::uno::Reference< css::task::XInteractionRequest >& ) override;
77 };
78
handle(const css::uno::Reference<css::task::XInteractionRequest> & xRequest)79 void SdGRFFilter_ImplInteractionHdl::handle( const css::uno::Reference< css::task::XInteractionRequest >& xRequest )
80 {
81 if( !m_xInter.is() )
82 return;
83
84 css::drawing::GraphicFilterRequest aErr;
85 if ( xRequest->getRequest() >>= aErr )
86 nFilterError = ErrCode(aErr.ErrCode);
87 else
88 m_xInter->handle( xRequest );
89 }
90
91
SdGRFFilter(SfxMedium & rMedium,::sd::DrawDocShell & rDocShell)92 SdGRFFilter::SdGRFFilter( SfxMedium& rMedium, ::sd::DrawDocShell& rDocShell ) :
93 SdFilter( rMedium, rDocShell )
94 {
95 }
96
~SdGRFFilter()97 SdGRFFilter::~SdGRFFilter()
98 {
99 }
100
HandleGraphicFilterError(ErrCode nFilterError,ErrCode nStreamError)101 void SdGRFFilter::HandleGraphicFilterError( ErrCode nFilterError, ErrCode nStreamError )
102 {
103 if (ERRCODE_NONE != nStreamError)
104 {
105 ErrorHandler::HandleError(nStreamError);
106 return;
107 }
108
109 const char* pId;
110
111 if( nFilterError == ERRCODE_GRFILTER_OPENERROR )
112 pId = STR_IMPORT_GRFILTER_OPENERROR;
113 else if( nFilterError == ERRCODE_GRFILTER_IOERROR )
114 pId = STR_IMPORT_GRFILTER_IOERROR;
115 else if( nFilterError == ERRCODE_GRFILTER_FORMATERROR )
116 pId = STR_IMPORT_GRFILTER_FORMATERROR;
117 else if( nFilterError == ERRCODE_GRFILTER_VERSIONERROR )
118 pId = STR_IMPORT_GRFILTER_VERSIONERROR;
119 else if( nFilterError == ERRCODE_GRFILTER_TOOBIG )
120 pId = STR_IMPORT_GRFILTER_TOOBIG;
121 else if( nFilterError == ERRCODE_NONE )
122 pId = nullptr;
123 else
124 pId = STR_IMPORT_GRFILTER_FILTERERROR;
125
126 if (pId && strcmp(pId, STR_IMPORT_GRFILTER_IOERROR) == 0)
127 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
128 else
129 {
130 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
131 VclMessageType::Warning, VclButtonsType::Ok, pId ? SdResId(pId) : OUString()));
132 xErrorBox->run();
133 }
134 }
135
Import()136 bool SdGRFFilter::Import()
137 {
138 Graphic aGraphic;
139 const OUString aFileName( mrMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
140 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
141 const sal_uInt16 nFilter = rGraphicFilter.GetImportFormatNumberForTypeName( mrMedium.GetFilter()->GetTypeName() );
142 bool bRet = false;
143
144 SvStream* pIStm = mrMedium.GetInStream();
145 ErrCode nReturn = pIStm ? rGraphicFilter.ImportGraphic( aGraphic, aFileName, *pIStm, nFilter ) : ErrCode(1);
146
147 if( nReturn )
148 HandleGraphicFilterError( nReturn, rGraphicFilter.GetLastError().nStreamError );
149 else
150 {
151 if( mrDocument.GetPageCount() == 0 )
152 mrDocument.CreateFirstPages();
153
154 SdPage* pPage = mrDocument.GetSdPage( 0, PageKind::Standard );
155 Point aPos;
156 Size aPagSize( pPage->GetSize() );
157 Size aGrfSize( OutputDevice::LogicToLogic( aGraphic.GetPrefSize(),
158 aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)));
159
160 aPagSize.AdjustWidth( -(pPage->GetLeftBorder() + pPage->GetRightBorder()) );
161 aPagSize.AdjustHeight( -(pPage->GetUpperBorder() + pPage->GetLowerBorder()) );
162
163 // scale to fit page
164 if ( ( ( aGrfSize.Height() > aPagSize.Height() ) || ( aGrfSize.Width() > aPagSize.Width() ) ) &&
165 aGrfSize.Height() && aPagSize.Height() )
166 {
167 double fGrfWH = static_cast<double>(aGrfSize.Width()) / aGrfSize.Height();
168 double fWinWH = static_cast<double>(aPagSize.Width()) / aPagSize.Height();
169
170 // adjust graphic to page size (scales)
171 if( fGrfWH < fWinWH )
172 {
173 aGrfSize.setWidth( static_cast<long>( aPagSize.Height() * fGrfWH ) );
174 aGrfSize.setHeight( aPagSize.Height() );
175 }
176 else if( fGrfWH > 0.F )
177 {
178 aGrfSize.setWidth( aPagSize.Width() );
179 aGrfSize.setHeight( static_cast<long>( aPagSize.Width() / fGrfWH ) );
180 }
181 }
182
183 // set output rectangle for graphic
184 aPos.setX( ( ( aPagSize.Width() - aGrfSize.Width() ) >> 1 ) + pPage->GetLeftBorder() );
185 aPos.setY( ( ( aPagSize.Height() - aGrfSize.Height() ) >> 1 ) + pPage->GetUpperBorder() );
186
187 pPage->InsertObject(
188 new SdrGrafObj(
189 pPage->getSdrModelFromSdrPage(),
190 aGraphic,
191 ::tools::Rectangle(aPos, aGrfSize)));
192 bRet = true;
193 }
194
195 return bRet;
196 }
197
Export()198 bool SdGRFFilter::Export()
199 {
200 // SJ: todo: error handling, the GraphicExportFilter does not support proper errorhandling
201 bool bRet = false;
202
203 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
204 uno::Reference< drawing::XGraphicExportFilter > xExporter = drawing::GraphicExportFilter::create( xContext );
205
206 SdPage* pPage = nullptr;
207 sd::DrawViewShell* pDrawViewShell = dynamic_cast<::sd::DrawViewShell* >(mrDocShell.GetViewShell() );
208
209 PageKind ePageKind = PageKind::Standard;
210 if( pDrawViewShell )
211 {
212 ePageKind = pDrawViewShell->GetPageKind();
213 if( PageKind::Handout == ePageKind )
214 pPage = mrDocument.GetSdPage( 0, PageKind::Handout );
215 else
216 pPage = pDrawViewShell->GetActualPage();
217 }
218 else
219 pPage = mrDocument.GetSdPage( 0, PageKind::Standard );
220
221 if ( pPage )
222 {
223 // taking the 'correct' page number, seems that there might exist a better method to archive this
224 pPage = mrDocument.GetSdPage( pPage->GetPageNum() ? ( pPage->GetPageNum() - 1 ) >> 1 : 0, ePageKind );
225 if ( pPage )
226 {
227 uno::Reference< lang::XComponent > xSource( pPage->getUnoPage(), uno::UNO_QUERY );
228 SfxItemSet* pSet = mrMedium.GetItemSet();
229 if ( pSet && xSource.is() )
230 {
231 const OUString aTypeName( mrMedium.GetFilter()->GetTypeName() );
232 GraphicFilter &rGraphicFilter = GraphicFilter::GetGraphicFilter();
233 const sal_uInt16 nFilter = rGraphicFilter.GetExportFormatNumberForTypeName( aTypeName );
234 if ( nFilter != GRFILTER_FORMAT_NOTFOUND )
235 {
236 uno::Reference< task::XInteractionHandler > xInteractionHandler;
237
238 beans::PropertyValues aArgs;
239 TransformItems( SID_SAVEASDOC, *pSet, aArgs );
240
241 const OUString sFilterName( "FilterName" );
242 OUString sShortName( rGraphicFilter.GetExportFormatShortName( nFilter ) );
243
244 bool bFilterNameFound = false;
245 for ( auto& rArg : aArgs )
246 {
247 OUString& rStr = rArg.Name;
248 if ( rStr == sFilterName )
249 {
250 bFilterNameFound = true;
251 rArg.Value <<= sShortName;
252 }
253 else if ( rStr == "InteractionHandler" )
254 {
255 uno::Reference< task::XInteractionHandler > xHdl;
256 if ( rArg.Value >>= xHdl )
257 {
258 xInteractionHandler = new SdGRFFilter_ImplInteractionHdl( xHdl );
259 rArg.Value <<= xInteractionHandler;
260 }
261 }
262 }
263 if ( !bFilterNameFound )
264 {
265 sal_Int32 nCount = aArgs.getLength();
266 aArgs.realloc( nCount + 1 );
267 aArgs[ nCount ].Name = sFilterName;
268 aArgs[ nCount ].Value <<= sShortName;
269 }
270
271 // take selection if needed
272 if( ( SfxItemState::SET == pSet->GetItemState( SID_SELECTION ) )
273 && pSet->Get( SID_SELECTION ).GetValue()
274 && pDrawViewShell )
275 {
276 uno::Reference< view::XSelectionSupplier > xSelectionSupplier(
277 pDrawViewShell->GetViewShellBase().GetController(), uno::UNO_QUERY );
278 if ( xSelectionSupplier.is() )
279 {
280 uno::Any aSelection( xSelectionSupplier->getSelection() );
281 uno::Reference< lang::XComponent > xSelection;
282 if ( aSelection >>= xSelection )
283 xSource = xSelection;
284 }
285 }
286 xExporter->setSourceDocument( xSource );
287 bRet = xExporter->filter( aArgs );
288 if ( !bRet && xInteractionHandler.is() )
289 SdGRFFilter::HandleGraphicFilterError(
290 static_cast< SdGRFFilter_ImplInteractionHdl* >( xInteractionHandler.get() )->GetErrorCode(),
291 rGraphicFilter.GetLastError().nStreamError );
292 }
293 }
294 }
295 }
296 return bRet;
297 }
298
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
300