1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include <comphelper/servicedecl.hxx>
24 #include <uno/environment.h>
25 #include <com/sun/star/drawing/XDrawPage.hpp>
26 #include <com/sun/star/drawing/XDrawView.hpp>
27 #include <com/sun/star/frame/Desktop.hpp>
28 #include <com/sun/star/frame/XController.hpp>
29 #include <com/sun/star/view/XSelectionSupplier.hpp>
30 #include <com/sun/star/drawing/XDrawSubController.hpp>
31 #include <com/sun/star/container/XNamed.hpp>
32 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
34 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
35 #include <com/sun/star/drawing/framework/XConfiguration.hpp>
36 #include <com/sun/star/drawing/framework/AnchorBindingMode.hpp>
37 #include <com/sun/star/drawing/framework/XResourceId.hpp>
38 #include <com/sun/star/drawing/framework/XResource.hpp>
39 #include <com/sun/star/drawing/framework/XView.hpp>
40 #include <com/sun/star/drawing/framework/ResourceId.hpp>
41 #include <comphelper/processfactory.hxx>
43 #include <osl/mutex.hxx>
45 #include "svgfilter.hxx"
46 #include "svgwriter.hxx"
48 using namespace ::com::sun::star
;
54 SVGFilter::SVGFilter( const Reference
< XComponentContext
>& rxCtx
) :
58 mpSVGFontExport( NULL
),
60 mpDefaultSdrPage( NULL
),
62 mbPresentation( sal_False
),
63 mbExportAll( sal_False
),
69 // -----------------------------------------------------------------------------
71 SVGFilter::~SVGFilter()
73 DBG_ASSERT( mpSVGDoc
== NULL
, "mpSVGDoc not destroyed" );
74 DBG_ASSERT( mpSVGExport
== NULL
, "mpSVGExport not destroyed" );
75 DBG_ASSERT( mpSVGFontExport
== NULL
, "mpSVGFontExport not destroyed" );
76 DBG_ASSERT( mpSVGWriter
== NULL
, "mpSVGWriter not destroyed" );
77 DBG_ASSERT( mpObjects
== NULL
, "mpObjects not destroyed" );
80 // -----------------------------------------------------------------------------
82 sal_Bool SAL_CALL
SVGFilter::filter( const Sequence
< PropertyValue
>& rDescriptor
)
83 throw (RuntimeException
)
85 SolarMutexGuard aGuard
;
86 Window
* pFocusWindow
= Application::GetFocusWindow();
90 pFocusWindow
->EnterWait();
93 bRet
= implImport( rDescriptor
);
94 #ifndef DISABLE_EXPORT
95 else if( mxSrcDoc
.is() )
97 if( !mbExportAll
&& !mSelectedPages
.hasElements() )
99 uno::Reference
< frame::XDesktop2
> xDesktop(frame::Desktop::create(mxContext
));
100 uno::Reference
< frame::XFrame
> xFrame(xDesktop
->getCurrentFrame(),
101 uno::UNO_QUERY_THROW
);
102 uno::Reference
<frame::XController
> xController(xFrame
->getController(),
103 uno::UNO_QUERY_THROW
);
104 uno::Reference
<drawing::XDrawView
> xDrawView(xController
,
105 uno::UNO_QUERY_THROW
);
106 uno::Reference
<drawing::framework::XControllerManager
> xManager(xController
,
107 uno::UNO_QUERY_THROW
);
108 uno::Reference
<drawing::framework::XConfigurationController
> xConfigController(xManager
->getConfigurationController());
110 // which view configuration are we in?
112 // * traverse Impress resources to find slide preview pane, grab selection from there
113 // * otherwise, fallback to current slide
115 uno::Sequence
<uno::Reference
<drawing::framework::XResourceId
> > aResIds(
116 xConfigController
->getCurrentConfiguration()->getResources(
117 uno::Reference
<drawing::framework::XResourceId
>(),
119 drawing::framework::AnchorBindingMode_INDIRECT
));
121 for( sal_Int32 i
=0; i
<aResIds
.getLength(); ++i
)
123 // can we somehow obtain the slidesorter from the Impress framework?
124 if( aResIds
[i
]->getResourceURL() == "private:resource/view/SlideSorter" )
126 // got it, grab current selection from there
127 uno::Reference
<drawing::framework::XResource
> xRes(
128 xConfigController
->getResource(aResIds
[i
]));
130 uno::Reference
< view::XSelectionSupplier
> xSelectionSupplier(
133 if( xSelectionSupplier
.is() )
135 uno::Any aSelection
= xSelectionSupplier
->getSelection();
136 if( aSelection
.hasValue() )
138 ObjectSequence aSelectedPageSequence
;
139 aSelection
>>= aSelectedPageSequence
;
140 mSelectedPages
.realloc( aSelectedPageSequence
.getLength() );
141 for( sal_Int32 j
=0; j
<mSelectedPages
.getLength(); ++j
)
143 uno::Reference
< drawing::XDrawPage
> xDrawPage( aSelectedPageSequence
[j
],
145 mSelectedPages
[j
] = xDrawPage
;
148 // and stop looping. it is likely not getting better
155 if( !mSelectedPages
.hasElements() )
157 // apparently failed to glean selection - fallback to current page
158 mSelectedPages
.realloc( 1 );
159 mSelectedPages
[0] = xDrawView
->getCurrentPage();
164 * Export all slides, or requested "PagePos"
166 if( !mSelectedPages
.hasElements() )
168 sal_Int32 nLength
= rDescriptor
.getLength();
169 const PropertyValue
* pValue
= rDescriptor
.getConstArray();
170 sal_Int32 nPageToExport
= -1;
172 for ( sal_Int32 i
= 0 ; i
< nLength
; ++i
)
174 if ( pValue
[ i
].Name
== "PagePos" )
176 pValue
[ i
].Value
>>= nPageToExport
;
180 uno::Reference
< drawing::XMasterPagesSupplier
> xMasterPagesSupplier( mxSrcDoc
, uno::UNO_QUERY
);
181 uno::Reference
< drawing::XDrawPagesSupplier
> xDrawPagesSupplier( mxSrcDoc
, uno::UNO_QUERY
);
183 if( xMasterPagesSupplier
.is() && xDrawPagesSupplier
.is() )
185 uno::Reference
< drawing::XDrawPages
> xMasterPages( xMasterPagesSupplier
->getMasterPages(), uno::UNO_QUERY
);
186 uno::Reference
< drawing::XDrawPages
> xDrawPages( xDrawPagesSupplier
->getDrawPages(), uno::UNO_QUERY
);
187 if( xMasterPages
.is() && xMasterPages
->getCount() &&
188 xDrawPages
.is() && xDrawPages
->getCount() )
190 sal_Int32 nDPCount
= xDrawPages
->getCount();
192 mSelectedPages
.realloc( nPageToExport
!= -1 ? 1 : nDPCount
);
194 for( i
= 0; i
< nDPCount
; ++i
)
196 if( nPageToExport
!= -1 && nPageToExport
== i
)
198 uno::Reference
< drawing::XDrawPage
> xDrawPage( xDrawPages
->getByIndex( i
), uno::UNO_QUERY
);
199 mSelectedPages
[0] = xDrawPage
;
203 uno::Reference
< drawing::XDrawPage
> xDrawPage( xDrawPages
->getByIndex( i
), uno::UNO_QUERY
);
204 mSelectedPages
[i
] = xDrawPage
;
212 * We get all master page that are targeted by at least one draw page.
213 * The master page are put in an unordered set.
215 ObjectSet aMasterPageTargetSet
;
216 for( sal_Int32 i
= 0; i
< mSelectedPages
.getLength(); ++i
)
218 uno::Reference
< drawing::XMasterPageTarget
> xMasterPageTarget( mSelectedPages
[i
], uno::UNO_QUERY
);
219 if( xMasterPageTarget
.is() )
221 aMasterPageTargetSet
.insert( xMasterPageTarget
->getMasterPage() );
224 // Later we move them to a uno::Sequence so we can get them by index
225 mMasterPageTargets
.realloc( aMasterPageTargetSet
.size() );
226 ObjectSet::const_iterator aElem
= aMasterPageTargetSet
.begin();
227 for( sal_Int32 i
= 0; aElem
!= aMasterPageTargetSet
.end(); ++aElem
, ++i
)
229 uno::Reference
< drawing::XDrawPage
> xMasterPage( *aElem
, uno::UNO_QUERY
);
230 mMasterPageTargets
[i
] = xMasterPage
;
233 bRet
= implExport( rDescriptor
);
240 pFocusWindow
->LeaveWait();
245 // -----------------------------------------------------------------------------
247 void SAL_CALL
SVGFilter::cancel( ) throw (RuntimeException
)
251 // -----------------------------------------------------------------------------
253 void SAL_CALL
SVGFilter::setSourceDocument( const Reference
< XComponent
>& xDoc
)
254 throw (IllegalArgumentException
, RuntimeException
)
259 // -----------------------------------------------------------------------------
261 void SAL_CALL
SVGFilter::setTargetDocument( const Reference
< XComponent
>& xDoc
)
262 throw (::com::sun::star::lang::IllegalArgumentException
, RuntimeException
)
267 // -----------------------------------------------------------------------------
269 OUString SAL_CALL
SVGFilter::detect( Sequence
< PropertyValue
>& io_rDescriptor
) throw (RuntimeException
)
271 uno::Reference
< io::XInputStream
> xInput
;
273 const beans::PropertyValue
* pAttribs
= io_rDescriptor
.getConstArray();
274 const sal_Int32 nAttribs
= io_rDescriptor
.getLength();
275 for( sal_Int32 i
= 0; i
< nAttribs
; i
++ )
277 if ( pAttribs
[i
].Name
== "InputStream" )
278 pAttribs
[i
].Value
>>= xInput
;
284 uno::Reference
< io::XSeekable
> xSeek( xInput
, uno::UNO_QUERY
);
288 // read the first 1024 bytes & check a few magic string
289 // constants (heuristically)
290 const sal_Int32 nLookAhead
= 1024;
291 uno::Sequence
< sal_Int8
> aBuf( nLookAhead
);
292 const sal_uInt64 nBytes
=xInput
->readBytes(aBuf
, nLookAhead
);
293 const sal_Int8
* const pBuf
=aBuf
.getConstArray();
295 sal_Int8 aMagic1
[] = {'<', 's', 'v', 'g'};
296 if( std::search(pBuf
, pBuf
+nBytes
,
297 aMagic1
, aMagic1
+sizeof(aMagic1
)/sizeof(*aMagic1
)) != pBuf
+nBytes
)
298 return OUString("svg_Scalable_Vector_Graphics");
300 sal_Int8 aMagic2
[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'};
301 if( std::search(pBuf
, pBuf
+nBytes
,
302 aMagic2
, aMagic2
+sizeof(aMagic2
)/sizeof(*aMagic2
)) != pBuf
+nBytes
)
303 return OUString("svg_Scalable_Vector_Graphics");
308 // -----------------------------------------------------------------------------
310 #define SVG_FILTER_IMPL_NAME "com.sun.star.comp.Draw.SVGFilter"
311 #define SVG_WRITER_IMPL_NAME "com.sun.star.comp.Draw.SVGWriter"
313 namespace sdecl
= comphelper::service_decl
;
314 sdecl::class_
<SVGFilter
> serviceFilterImpl
;
315 const sdecl::ServiceDecl
svgFilter(
317 SVG_FILTER_IMPL_NAME
,
318 "com.sun.star.document.ImportFilter;"
319 "com.sun.star.document.ExportFilter;"
320 "com.sun.star.document.ExtendedTypeDetection" );
322 sdecl::class_
<SVGWriter
> serviceWriterImpl
;
323 const sdecl::ServiceDecl
svgWriter(
325 SVG_WRITER_IMPL_NAME
,
326 "com.sun.star.svg.SVGWriter" );
328 // The C shared lib entry points
329 extern "C" SAL_DLLPUBLIC_EXPORT
void* SAL_CALL
svgfilter_component_getFactory(
330 sal_Char
const* pImplName
,
331 ::com::sun::star::lang::XMultiServiceFactory
* pServiceManager
,
332 ::com::sun::star::registry::XRegistryKey
* pRegistryKey
)
334 if ( rtl_str_compare (pImplName
, SVG_FILTER_IMPL_NAME
) == 0 )
336 return component_getFactoryHelper( pImplName
, pServiceManager
, pRegistryKey
, svgFilter
);
338 else if ( rtl_str_compare (pImplName
, SVG_WRITER_IMPL_NAME
) == 0 )
340 return component_getFactoryHelper( pImplName
, pServiceManager
, pRegistryKey
, svgWriter
);
345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */