1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sdgrffilter.cxx,v $
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"
35 #pragma warning (disable:4190)
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"
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>
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
;
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
;
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
)
141 com::sun::star::drawing::GraphicFilterRequest aErr
;
142 if ( xRequest
->getRequest() >>= aErr
)
143 nFilterError
= (USHORT
)aErr
.ErrCode
;
145 m_xInter
->handle( xRequest
);
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
)
170 switch( nFilterError
)
172 case GRFILTER_OPENERROR
:
173 nId
= STR_IMPORT_GRFILTER_OPENERROR
;
175 case GRFILTER_IOERROR
:
176 nId
= STR_IMPORT_GRFILTER_IOERROR
;
178 case GRFILTER_FORMATERROR
:
179 nId
= STR_IMPORT_GRFILTER_FORMATERROR
;
181 case GRFILTER_VERSIONERROR
:
182 nId
= STR_IMPORT_GRFILTER_VERSIONERROR
;
184 case GRFILTER_TOOBIG
:
185 nId
= STR_IMPORT_GRFILTER_TOOBIG
;
192 case GRFILTER_FILTERERROR
:
193 nId
= STR_IMPORT_GRFILTER_FILTERERROR
;
197 if( ERRCODE_NONE
!= nStreamError
)
198 ErrorHandler::HandleError( nStreamError
);
199 else if( STR_IMPORT_GRFILTER_IOERROR
== nId
)
200 ErrorHandler::HandleError( ERRCODE_IO_GENERAL
);
203 ErrorBox
aErrorBox( NULL
, WB_OK
, String( SdResId( nId
) ) );
208 // -----------------------------------------------------------------------------
210 sal_Bool
SdGRFFilter::Import()
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;
225 HandleGraphicFilterError( nReturn
, pGraphicFilter
->GetLastError().nStreamError
);
228 if( mrDocument
.GetPageCount() == 0L )
229 mrDocument
.CreateFirstPages();
231 SdPage
* pPage
= mrDocument
.GetSdPage( 0, PK_STANDARD
);
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();
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
) ) );
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" ) ),
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
;
299 ePageKind
= pDrawViewShell
->GetPageKind();
300 if( PK_HANDOUT
== ePageKind
)
301 pPage
= mrDocument
.GetSdPage( 0, PK_HANDOUT
);
303 pPage
= pDrawViewShell
->GetActualPage();
306 pPage
= mrDocument
.GetSdPage( 0, PK_STANDARD
);
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
);
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
;
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()
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
);
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
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);
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" );
449 case ::com::sun::star::graphic::GraphicType::PIXEL
:
451 sal_Bool bAnimated
= sal_False
;
452 xGraphicSet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Animated" ) ) ) >>= bAnimated
;
456 aMimeType
= OUString::createFromAscii( "image/gif" );
461 // case ::com::sun::star::graphic::GraphicType::EMPTY:
463 aMimeType
= OUString::createFromAscii( "image/png" );
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
);
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
;
517 if( aDefaultFormatName
.getLength() == 0 )
518 aDefaultFormatName
= OUString( RTL_CONSTASCII_USTRINGPARAM( "PNG - Portable Network Graphic" ) );
520 xFltMgr
->setCurrentFilter( aDefaultFormatName
);
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
);
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
);
556 (rtl::OString("SdGRFFilter::SaveGraphic(), "
557 "exception caught: ") +
558 rtl::OUStringToOString(
559 comphelper::anyToString( cppu::getCaughtException() ),
560 RTL_TEXTENCODING_UTF8
)).getStr() );