merge the formfield patch from ooo-build
[ooovba.git] / sd / source / filter / grf / sdgrffilter.cxx
blob8237fb96cb886ca5832ffca7dcff8ed153443f0d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sdgrffilter.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #ifdef _MSC_VER
35 #pragma warning (disable:4190)
36 #endif
37 #include <com/sun/star/graphic/XGraphicProvider.hpp>
38 #include <com/sun/star/graphic/GraphicType.hpp>
39 #include <com/sun/star/ucb/XSimpleFileAccess2.hpp>
41 #include <unotools/localfilehelper.hxx>
42 #include <tools/errinf.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <vcl/metaact.hxx>
45 #include <vcl/virdev.hxx>
46 #include <sfx2/docfile.hxx>
47 #include <sfx2/docfilt.hxx>
48 #include <sfx2/frame.hxx>
49 #include <svx/svdograf.hxx>
50 #include <svx/svdpagv.hxx>
52 #include "../../ui/inc/strings.hrc"
53 #include "../../ui/inc/DrawViewShell.hxx"
54 #include "../../ui/inc/DrawDocShell.hxx"
55 #include "../../ui/inc/ClientView.hxx"
56 #include "../../ui/inc/FrameView.hxx"
58 #include "comphelper/anytostring.hxx"
59 #include "cppuhelper/exc_hlp.hxx"
61 // --
62 #include <comphelper/processfactory.hxx>
63 #include <svtools/pathoptions.hxx>
64 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
65 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
66 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
67 #include <sfx2/filedlghelper.hxx>
68 #include <tools/urlobj.hxx>
69 #include <svtools/filter.hxx>
70 #include <svx/impgrf.hxx>
71 #include <svx/xoutbmp.hxx>
73 // --
75 #include "sdpage.hxx"
76 #include "drawdoc.hxx"
77 #include "sdresid.hxx"
78 #include "sdgrffilter.hxx"
79 #include "../../ui/inc/ViewShellBase.hxx"
80 #include <com/sun/star/uno/Sequence.h>
81 #include <com/sun/star/beans/PropertyValue.hpp>
82 #include <com/sun/star/beans/PropertyValues.hpp>
83 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
84 #include <com/sun/star/lang/XComponent.hpp>
85 #include <com/sun/star/document/XFilter.hpp>
86 #include <com/sun/star/document/XExporter.hpp>
87 #include <comphelper/processfactory.hxx>
88 #include <com/sun/star/view/XSelectionSupplier.hpp>
89 #include <com/sun/star/drawing/XDrawView.hpp>
90 #include "../../ui/inc/DrawController.hxx"
91 #include <cppuhelper/implbase2.hxx>
92 #include <com/sun/star/drawing/XShape.hpp>
93 #include <com/sun/star/task/XInteractionHandler.hpp>
94 #include <com/sun/star/task/XInteractionRequest.hpp>
95 #include <com/sun/star/drawing/GraphicFilterRequest.hpp>
97 using namespace ::com::sun::star;
98 using namespace ::com::sun::star::uno;
99 using namespace ::com::sun::star::lang;
100 using namespace ::com::sun::star::beans;
101 using namespace ::com::sun::star::graphic;
102 using namespace ::com::sun::star::io;
103 using namespace ::com::sun::star::ucb;
104 using namespace com::sun::star::ui::dialogs;
105 using rtl::OUString;
106 using namespace ::sfx2;
109 // -----------------------------------------------------------------------------
111 class SdGRFFilter_ImplInteractionHdl : public ::cppu::WeakImplHelper1< com::sun::star::task::XInteractionHandler >
113 com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > m_xInter;
114 USHORT nFilterError;
116 public:
118 SdGRFFilter_ImplInteractionHdl( com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > xInteraction ) :
119 m_xInter( xInteraction ),
120 nFilterError( GRFILTER_OK )
123 ~SdGRFFilter_ImplInteractionHdl();
125 USHORT GetErrorCode() const { return nFilterError; };
127 virtual void SAL_CALL handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& )
128 throw( com::sun::star::uno::RuntimeException );
131 SdGRFFilter_ImplInteractionHdl::~SdGRFFilter_ImplInteractionHdl()
135 void SdGRFFilter_ImplInteractionHdl::handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
136 throw( com::sun::star::uno::RuntimeException )
138 if( !m_xInter.is() )
139 return;
141 com::sun::star::drawing::GraphicFilterRequest aErr;
142 if ( xRequest->getRequest() >>= aErr )
143 nFilterError = (USHORT)aErr.ErrCode;
144 else
145 m_xInter->handle( xRequest );
149 // ---------------
150 // - SdPPTFilter -
151 // ---------------
153 SdGRFFilter::SdGRFFilter( SfxMedium& rMedium, ::sd::DrawDocShell& rDocShell ) :
154 SdFilter( rMedium, rDocShell, sal_True )
158 // -----------------------------------------------------------------------------
160 SdGRFFilter::~SdGRFFilter()
164 // -----------------------------------------------------------------------------
166 void SdGRFFilter::HandleGraphicFilterError( USHORT nFilterError, ULONG nStreamError )
168 USHORT nId;
170 switch( nFilterError )
172 case GRFILTER_OPENERROR:
173 nId = STR_IMPORT_GRFILTER_OPENERROR;
174 break;
175 case GRFILTER_IOERROR:
176 nId = STR_IMPORT_GRFILTER_IOERROR;
177 break;
178 case GRFILTER_FORMATERROR:
179 nId = STR_IMPORT_GRFILTER_FORMATERROR;
180 break;
181 case GRFILTER_VERSIONERROR:
182 nId = STR_IMPORT_GRFILTER_VERSIONERROR;
183 break;
184 case GRFILTER_TOOBIG:
185 nId = STR_IMPORT_GRFILTER_TOOBIG;
186 break;
187 case 0 :
188 nId = 0;
189 break;
191 default:
192 case GRFILTER_FILTERERROR:
193 nId = STR_IMPORT_GRFILTER_FILTERERROR;
194 break;
197 if( ERRCODE_NONE != nStreamError )
198 ErrorHandler::HandleError( nStreamError );
199 else if( STR_IMPORT_GRFILTER_IOERROR == nId )
200 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
201 else
203 ErrorBox aErrorBox( NULL, WB_OK, String( SdResId( nId ) ) );
204 aErrorBox.Execute();
208 // -----------------------------------------------------------------------------
210 sal_Bool SdGRFFilter::Import()
212 Graphic aGraphic;
213 const String aFileName( mrMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
214 GraphicFilter* pGraphicFilter = GetGrfFilter();
215 const USHORT nFilter = pGraphicFilter->GetImportFormatNumberForTypeName( mrMedium.GetFilter()->GetTypeName() );
216 sal_Bool bRet = sal_False;
218 // ggf. Filterdialog ausfuehren
219 if ( !pGraphicFilter->HasImportDialog( nFilter ) || pGraphicFilter->DoImportDialog( NULL, nFilter ) )
221 SvStream* pIStm = mrMedium.GetInStream();
222 USHORT nReturn = pIStm ? pGraphicFilter->ImportGraphic( aGraphic, aFileName, *pIStm, nFilter ) : 1;
224 if( nReturn )
225 HandleGraphicFilterError( nReturn, pGraphicFilter->GetLastError().nStreamError );
226 else
228 if( mrDocument.GetPageCount() == 0L )
229 mrDocument.CreateFirstPages();
231 SdPage* pPage = mrDocument.GetSdPage( 0, PK_STANDARD );
232 Point aPos;
233 Size aPagSize( pPage->GetSize() );
234 Size aGrfSize( OutputDevice::LogicToLogic( aGraphic.GetPrefSize(),
235 aGraphic.GetPrefMapMode(), MAP_100TH_MM ) );
237 aPagSize.Width() -= pPage->GetLftBorder() + pPage->GetRgtBorder();
238 aPagSize.Height() -= pPage->GetUppBorder() + pPage->GetLwrBorder();
240 // scale to fit page
241 if ( ( ( aGrfSize.Height() > aPagSize.Height() ) || ( aGrfSize.Width() > aPagSize.Width() ) ) &&
242 aGrfSize.Height() && aPagSize.Height() )
244 double fGrfWH = (double) aGrfSize.Width() / aGrfSize.Height();
245 double fWinWH = (double) aPagSize.Width() / aPagSize.Height();
247 // Grafik an Pagesize anpassen (skaliert)
248 if( fGrfWH < fWinWH )
250 aGrfSize.Width() = (long) ( aPagSize.Height() * fGrfWH );
251 aGrfSize.Height() = aPagSize.Height();
253 else if( fGrfWH > 0.F )
255 aGrfSize.Width() = aPagSize.Width();
256 aGrfSize.Height()= (long) ( aPagSize.Width() / fGrfWH );
260 // Ausgaberechteck fuer Grafik setzen
261 aPos.X() = ( ( aPagSize.Width() - aGrfSize.Width() ) >> 1 ) + pPage->GetLftBorder();
262 aPos.Y() = ( ( aPagSize.Height() - aGrfSize.Height() ) >> 1 ) + pPage->GetUppBorder();
264 pPage->InsertObject( new SdrGrafObj( aGraphic, Rectangle( aPos, aGrfSize ) ) );
265 bRet = sal_True;
268 return bRet;
271 // -----------------------------------------------------------------------------
273 sal_Bool SdGRFFilter::Export()
275 // SJ: todo: error handling, the GraphicExportFilter does not support proper errorhandling
277 sal_Bool bRet = sal_False;
279 uno::Reference< lang::XMultiServiceFactory >
280 xSMgr( ::comphelper::getProcessServiceFactory() );
281 uno::Reference< uno::XInterface > xComponent
282 ( xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.drawing.GraphicExportFilter" ) ),
283 uno::UNO_QUERY );
284 if ( xComponent.is() )
286 uno::Reference< document::XExporter > xExporter
287 ( xComponent, uno::UNO_QUERY );
288 uno::Reference< document::XFilter > xFilter
289 ( xComponent, uno::UNO_QUERY );
290 if ( xExporter.is() && xFilter.is() )
292 SdPage* pPage = NULL;
293 sd::DrawViewShell* pDrawViewShell = static_cast< ::sd::DrawViewShell* >
294 ( ( ( mrDocShell.GetViewShell() && mrDocShell.GetViewShell()->ISA(::sd::DrawViewShell ) ) ? mrDocShell.GetViewShell() : NULL ) );
296 PageKind ePageKind = PK_STANDARD;
297 if( pDrawViewShell )
299 ePageKind = pDrawViewShell->GetPageKind();
300 if( PK_HANDOUT == ePageKind )
301 pPage = mrDocument.GetSdPage( 0, PK_HANDOUT );
302 else
303 pPage = pDrawViewShell->GetActualPage();
305 else
306 pPage = mrDocument.GetSdPage( 0, PK_STANDARD );
308 if ( pPage )
310 // taking the 'correct' page number, seems that there might exist a better method to archive this
311 pPage = mrDocument.GetSdPage( pPage->GetPageNum() ? ( pPage->GetPageNum() - 1 ) >> 1 : 0, ePageKind );
312 if ( pPage )
314 uno::Reference< lang::XComponent > xSource( pPage->getUnoPage(), uno::UNO_QUERY );
315 SfxItemSet* pSet = mrMedium.GetItemSet();
316 GraphicFilter* pGraphicFilter = GetGrfFilter();
317 if ( pSet && pGraphicFilter && xSource.is() )
319 const String aTypeName( mrMedium.GetFilter()->GetTypeName() );
320 const USHORT nFilter = pGraphicFilter->GetExportFormatNumberForTypeName( aTypeName );
321 if ( nFilter != GRFILTER_FORMAT_NOTFOUND )
323 uno::Reference< task::XInteractionHandler > mXInteractionHandler;
325 beans::PropertyValues aArgs;
326 TransformItems( SID_SAVEASDOC, *pSet, aArgs );
328 rtl::OUString sInteractionHandler( RTL_CONSTASCII_USTRINGPARAM( "InteractionHandler" ) );
329 rtl::OUString sFilterName( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
330 rtl::OUString sShortName( pGraphicFilter->GetExportFormatShortName( nFilter ) );
332 sal_Bool bFilterNameFound = sal_False;
333 sal_Int32 i, nCount;
334 for ( i = 0, nCount = aArgs.getLength(); i < nCount; i++ )
336 rtl::OUString& rStr = aArgs[ i ].Name;
337 if ( rStr == sFilterName )
339 bFilterNameFound = sal_True;
340 aArgs[ i ].Name = sFilterName;
341 aArgs[ i ].Value <<= sShortName;
343 else if ( rStr == sInteractionHandler )
345 uno::Reference< task::XInteractionHandler > xHdl;
346 if ( aArgs[ i ].Value >>= xHdl )
348 mXInteractionHandler = new SdGRFFilter_ImplInteractionHdl( xHdl );
349 aArgs[ i ].Value <<= mXInteractionHandler;
353 if ( !bFilterNameFound )
355 aArgs.realloc( ++nCount );
356 aArgs[ i ].Name = sFilterName;
357 aArgs[ i ].Value <<= sShortName;
360 // take selection if needed
361 if( ( SFX_ITEM_SET == pSet->GetItemState( SID_SELECTION ) )
362 && static_cast< const SfxBoolItem& >( pSet->Get( SID_SELECTION ) ).GetValue()
363 && pDrawViewShell )
365 uno::Reference< view::XSelectionSupplier > xSelectionSupplier(
366 pDrawViewShell->GetViewShellBase().GetController(), uno::UNO_QUERY );
367 if ( xSelectionSupplier.is() )
369 uno::Any aSelection( xSelectionSupplier->getSelection() );
370 uno::Reference< lang::XComponent > xSelection;
371 if ( aSelection >>= xSelection )
372 xSource = xSelection;
375 xExporter->setSourceDocument( xSource );
376 bRet = xFilter->filter( aArgs );
377 if ( !bRet && mXInteractionHandler.is() )
378 SdGRFFilter::HandleGraphicFilterError(
379 static_cast< SdGRFFilter_ImplInteractionHdl* >( mXInteractionHandler.get() )->GetErrorCode(),
380 pGraphicFilter->GetLastError().nStreamError );
387 return bRet;
390 void SdGRFFilter::SaveGraphic( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape )
394 Reference< XMultiServiceFactory > xSM( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
396 Reference< XGraphicProvider > xProvider( xSM->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) ) ), UNO_QUERY_THROW );
397 Reference< XPropertySet > xShapeSet( xShape, UNO_QUERY_THROW );
399 // detect mime type of graphic
400 OUString aMimeType;
401 OUString sGraphicURL;
403 // first try to detect from graphic object
404 Reference< XPropertySet > xGraphicSet( xShapeSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ) ) ), UNO_QUERY_THROW );
405 xShapeSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) ) >>= sGraphicURL;
407 bool bIsLinked = (sGraphicURL.getLength() != 0) && (sGraphicURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.GraphicObject:") ) != 0);
409 if( !bIsLinked )
410 xGraphicSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "MimeType" ) ) ) >>= aMimeType;
412 if( bIsLinked || aMimeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "image/x-vclgraphic" ) ) || !aMimeType.getLength() )
414 // this failed, try to detect it from graphic stream and URL
415 OUString aURL( sGraphicURL );
417 if( aURL.getLength() == 0 )
418 xShapeSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStreamURL" ) ) ) >>= aURL;
421 Reference< XInputStream > xGraphStream( xShapeSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStream" ) ) ), UNO_QUERY );
422 PropertyValues aDesc(2);
423 aDesc[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
424 aDesc[0].Value <<= aURL;
425 aDesc[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) );
426 aDesc[1].Value <<= xGraphStream;
428 Reference< XPropertySet > xDescSet( xProvider->queryGraphicDescriptor( aDesc ), UNO_QUERY_THROW );
430 xDescSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "MimeType" ) ) ) >>= aMimeType;
434 if( aMimeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "image/x-vclgraphic" ) ) || !aMimeType.getLength() )
436 // this also failed, now set a mimetype that fits graphic best
438 // gif for animated pixel
439 // png for non animated pixel
440 // svm for vector format
441 sal_Int8 nGraphicType = 0;
442 xGraphicSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicType" ) ) ) >>= nGraphicType;
443 switch( nGraphicType )
445 case ::com::sun::star::graphic::GraphicType::VECTOR:
446 aMimeType = OUString::createFromAscii( "image/x-svm" );
447 break;
449 case ::com::sun::star::graphic::GraphicType::PIXEL:
451 sal_Bool bAnimated = sal_False;
452 xGraphicSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Animated" ) ) ) >>= bAnimated;
454 if( bAnimated )
456 aMimeType = OUString::createFromAscii( "image/gif" );
457 break;
460 // Fallthrough!
461 // case ::com::sun::star::graphic::GraphicType::EMPTY:
462 default:
463 aMimeType = OUString::createFromAscii( "image/png" );
464 break;
468 // init dialog
469 SvtPathOptions aPathOpt;
470 String sGrfPath( aPathOpt.GetGraphicPath() );
472 FileDialogHelper aDlgHelper( TemplateDescription::FILESAVE_AUTOEXTENSION, 0 );
473 Reference < XFilePicker > xFP = aDlgHelper.GetFilePicker();
475 String aTitle( SdResId( STR_TITLE_SAVE_AS_PICTURE ) );
476 aDlgHelper.SetTitle( aTitle );
478 INetURLObject aPath;
479 aPath.SetSmartURL( sGrfPath);
480 xFP->setDisplayDirectory( aPath.GetMainURL(INetURLObject::DECODE_TO_IURI) );
482 // populate filter dialog filter list and select default filter to match graphic mime type
484 GraphicFilter& rGF = *GetGrfFilter();
485 Reference<XFilterManager> xFltMgr(xFP, UNO_QUERY);
486 OUString aDefaultFormatName;
487 USHORT nCount = rGF.GetExportFormatCount();
489 std::map< OUString, OUString > aMimeTypeMap;
491 for ( USHORT i = 0; i < nCount; i++ )
493 const OUString aExportFormatName( rGF.GetExportFormatName( i ) );
494 const OUString aFilterMimeType( rGF.GetExportFormatMediaType( i ) );
495 xFltMgr->appendFilter( aExportFormatName, rGF.GetExportWildcard( i ) );
496 aMimeTypeMap[ aExportFormatName ] = aFilterMimeType;
497 if( aMimeType == aFilterMimeType )
498 aDefaultFormatName = aExportFormatName;
501 if( aDefaultFormatName.getLength() == 0 )
503 nCount = rGF.GetImportFormatCount();
504 for( USHORT i = 0; i < nCount; i++ )
506 const OUString aFilterMimeType( rGF.GetImportFormatMediaType( i ) );
507 if( aMimeType == aFilterMimeType )
509 aDefaultFormatName = rGF.GetImportFormatName( i );
510 xFltMgr->appendFilter( aDefaultFormatName, rGF.GetImportWildcard( i ) );
511 aMimeTypeMap[ aDefaultFormatName ] = aFilterMimeType;
512 break;
517 if( aDefaultFormatName.getLength() == 0 )
518 aDefaultFormatName = OUString( RTL_CONSTASCII_USTRINGPARAM( "PNG - Portable Network Graphic" ) );
520 xFltMgr->setCurrentFilter( aDefaultFormatName );
522 // execute dialog
524 if( aDlgHelper.Execute() == ERRCODE_NONE )
526 OUString sPath( xFP->getFiles().getConstArray()[0] );
527 aPath.SetSmartURL( sPath);
528 sGrfPath = aPath.GetPath();
530 OUString aExportMimeType( aMimeTypeMap[xFltMgr->getCurrentFilter()] );
532 Reference< XInputStream > xGraphStream;
533 if( aMimeType == aExportMimeType )
534 xShapeSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStream" ) ) ) >>= xGraphStream;
536 if( xGraphStream.is() )
538 Reference< XSimpleFileAccess2 > xFileAccess( xSM->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) ) ), UNO_QUERY_THROW );
539 xFileAccess->writeFile( sPath, xGraphStream );
541 else
543 PropertyValues aDesc(2);
544 aDesc[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
545 aDesc[0].Value <<= sPath;
546 aDesc[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "MimeType" ) );
547 aDesc[1].Value <<= aExportMimeType;
548 Reference< XGraphic > xGraphic( xShapeSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ) ) ), UNO_QUERY_THROW );
549 xProvider->storeGraphic( xGraphic, aDesc );
553 catch( Exception& )
555 DBG_ERROR(
556 (rtl::OString("SdGRFFilter::SaveGraphic(), "
557 "exception caught: ") +
558 rtl::OUStringToOString(
559 comphelper::anyToString( cppu::getCaughtException() ),
560 RTL_TEXTENCODING_UTF8 )).getStr() );