xref: /trunk/main/filter/source/svg/svgexport.cxx (revision 56b8eddc)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #define ITEMID_FIELD 0
28 
29 #include "svgwriter.hxx"
30 #include "svgfontexport.hxx"
31 #include "svgfilter.hxx"
32 #include "impsvgdialog.hxx"
33 
34 #include <com/sun/star/graphic/XPrimitiveFactory2D.hpp>
35 
36 #include <svx/unopage.hxx>
37 #include <svx/unoshape.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/svdoutl.hxx>
40 #include <editeng/outliner.hxx>
41 #include <editeng/flditem.hxx>
42 #include <editeng/numitem.hxx>
43 
44 using namespace ::com::sun::star::graphic;
45 using namespace ::com::sun::star::geometry;
46 using ::rtl::OUString;
47 
48 // -------------
49 // - SVGExport -
50 // -------------
51 
SVGExport(const::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> xServiceFactory,const Reference<XDocumentHandler> & rxHandler,const Sequence<PropertyValue> & rFilterData)52 SVGExport::SVGExport(
53 	const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
54 	const Reference< XDocumentHandler >& rxHandler,
55     const Sequence< PropertyValue >& rFilterData )
56 : SvXMLExport( xServiceFactory, MAP_100TH_MM )
57 , mbTinyProfile			( sal_True )
58 , mbTSpans				( sal_True )
59 , mbEmbedFonts			( sal_False )
60 , mbNativeTextDecoration( sal_True )
61 , mbOpacity				( sal_True )
62 , mbGradient			( sal_True )
63 {
64 	for ( sal_Int32 i = 0, nCount = rFilterData.getLength(); i < nCount; i++ )
65 	{
66 		if ( rFilterData[ i ].Name == B2UCONST( SVG_PROP_TINYPROFILE ) )
67 			rFilterData[ i ].Value >>= mbTinyProfile;
68 		else if ( rFilterData[ i ].Name == B2UCONST( "TSpans" ) )
69 			rFilterData[ i ].Value >>= mbTSpans;
70 		else if ( rFilterData[ i ].Name == B2UCONST( SVG_PROP_EMBEDFONTS ) )
71 			rFilterData[ i ].Value >>= mbEmbedFonts;
72 		else if ( rFilterData[ i ].Name == B2UCONST( SVG_PROP_NATIVEDECORATION ) )
73 			rFilterData[ i ].Value >>= mbNativeTextDecoration;
74 		else if ( rFilterData[ i ].Name == B2UCONST( "GlyphPlacement" ) )
75 			rFilterData[ i ].Value >>= maGlyphPlacement;
76 		else if ( rFilterData[ i ].Name == B2UCONST( SVG_PROP_OPACITY ) )
77 			rFilterData[ i ].Value >>= mbOpacity;
78 		else if ( rFilterData[ i ].Name == B2UCONST( SVG_PROP_GRADIENT ) )
79 			rFilterData[ i ].Value >>= mbGradient;
80 	}
81 	if ( mbTinyProfile )
82 		mbNativeTextDecoration = sal_False;
83 	else
84 	{
85 		mbTSpans = sal_False;
86 		mbOpacity = sal_True;
87 		mbGradient = sal_True;
88 	}
89 	SetDocHandler( rxHandler );
90 	GetDocHandler()->startDocument();
91 }
92 
93 // -----------------------------------------------------------------------------
94 
~SVGExport()95 SVGExport::~SVGExport()
96 {
97 	GetDocHandler()->endDocument();
98 }
99 
100 // -----------------------------------------------------------------------------
101 
pushClip(const::basegfx::B2DPolyPolygon & rPolyPoly)102 void SVGExport::pushClip( const ::basegfx::B2DPolyPolygon& rPolyPoly )
103 {
104     maClipList.push_front( ::basegfx::tools::correctOrientations( rPolyPoly ) );
105 }
106 
107 // -----------------------------------------------------------------------------
108 
popClip()109 void SVGExport::popClip()
110 {
111     if( !maClipList.empty() )
112         maClipList.pop_front();
113 }
114 
115 // -----------------------------------------------------------------------------
116 
hasClip() const117 sal_Bool SVGExport::hasClip() const
118 {
119     return( !maClipList.empty() );
120 }
121 
122 // -----------------------------------------------------------------------------
123 
getCurClip() const124 const ::basegfx::B2DPolyPolygon* SVGExport::getCurClip() const
125 {
126     return( maClipList.empty() ? NULL : &( *maClipList.begin() ) );
127 }
128 
129 // ------------------------
130 // - ObjectRepresentation -
131 // ------------------------
132 
ObjectRepresentation()133 ObjectRepresentation::ObjectRepresentation() :
134 	mpMtf( NULL )
135 {
136 }
137 
138 // -----------------------------------------------------------------------------
139 
ObjectRepresentation(const Reference<XInterface> & rxObject,const GDIMetaFile & rMtf)140 ObjectRepresentation::ObjectRepresentation( const Reference< XInterface >& rxObject,
141 											const GDIMetaFile& rMtf ) :
142 	mxObject( rxObject ),
143 	mpMtf( new GDIMetaFile( rMtf ) )
144 {
145 }
146 
147 // -----------------------------------------------------------------------------
148 
ObjectRepresentation(const ObjectRepresentation & rPresentation)149 ObjectRepresentation::ObjectRepresentation( const ObjectRepresentation& rPresentation ) :
150 	mxObject( rPresentation.mxObject ),
151 	mpMtf( rPresentation.mpMtf ? new GDIMetaFile( *rPresentation.mpMtf ) : NULL )
152 {
153 }
154 
155 // -----------------------------------------------------------------------------
156 
~ObjectRepresentation()157 ObjectRepresentation::~ObjectRepresentation()
158 {
159 	delete mpMtf;
160 }
161 
162 // -----------------------------------------------------------------------------
163 
operator =(const ObjectRepresentation & rPresentation)164 ObjectRepresentation& ObjectRepresentation::operator=( const ObjectRepresentation& rPresentation )
165 {
166 	mxObject = rPresentation.mxObject;
167 	delete mpMtf, ( mpMtf = rPresentation.mpMtf ? new GDIMetaFile( *rPresentation.mpMtf ) : NULL );
168 
169 	return *this;
170 }
171 
172 // -----------------------------------------------------------------------------
173 
operator ==(const ObjectRepresentation & rPresentation) const174 sal_Bool ObjectRepresentation::operator==( const ObjectRepresentation& rPresentation ) const
175 {
176 	return( ( mxObject == rPresentation.mxObject ) &&
177 			( *mpMtf == *rPresentation.mpMtf ) );
178 }
179 
180 // -------------
181 // - SVGFilter -
182 // -------------
183 
implExport(const Sequence<PropertyValue> & rDescriptor)184 sal_Bool SVGFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
185 	throw (RuntimeException)
186 {
187     Reference< XMultiServiceFactory >	xServiceFactory( ::comphelper::getProcessServiceFactory() ) ;
188     Reference< XOutputStream >          xOStm;
189     SvStream*                           pOStm = NULL;
190 	sal_Int32							nLength = rDescriptor.getLength();
191     sal_Int32                           nPageToExport = SVG_EXPORT_ALLPAGES;
192 	const PropertyValue*				pValue = rDescriptor.getConstArray();
193 	sal_Bool							bRet = sal_False;
194 
195     mnMasterSlideId = mnSlideId = mnDrawingGroupId = mnDrawingId = 0;
196     maFilterData.realloc( 0 );
197 
198 	for ( sal_Int32 i = 0 ; i < nLength; ++i)
199     {
200 		if( pValue[ i ].Name.equalsAscii( "OutputStream" ) )
201 			pValue[ i ].Value >>= xOStm;
202         else if( pValue[ i ].Name.equalsAscii( "FileName" ) )
203         {
204             ::rtl::OUString aFileName;
205 
206             pValue[ i ].Value >>= aFileName;
207             pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, STREAM_WRITE | STREAM_TRUNC );
208 
209             if( pOStm )
210                 xOStm = Reference< XOutputStream >( new ::utl::OOutputStreamWrapper ( *pOStm ) );
211         }
212         else if( pValue[ i ].Name.equalsAscii( "PagePos" ) )
213         {
214             pValue[ i ].Value >>= nPageToExport;
215         }
216         else if( pValue[ i ].Name.equalsAscii( "FilterData" ) )
217         {
218             pValue[ i ].Value >>= maFilterData;
219         }
220         else if( pValue[ i ].Name.equalsAscii( "ShapeSelection" ) )
221         {
222             // #124608# read selection if given
223             pValue[ i ].Value >>= maShapeSelection;
224         }
225     }
226 
227     // if no filter data is given use stored/prepared ones
228     if( !maFilterData.getLength() )
229     {
230 #ifdef _SVG_USE_CONFIG
231         FilterConfigItem aCfgItem( String( RTL_CONSTASCII_USTRINGPARAM( SVG_EXPORTFILTER_CONFIGPATH ) ) );
232 
233         aCfgItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_TINYPROFILE ) ), sal_True );
234         aCfgItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_EMBEDFONTS ) ), sal_True );
235         aCfgItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_NATIVEDECORATION ) ), sal_False );
236         aCfgItem.ReadString( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_NATIVEDECORATION ) ), B2UCONST( "xlist" ) );
237         aCfgItem.ReadString( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_OPACITY ) ), sal_True );
238         aCfgItem.ReadString( String( RTL_CONSTASCII_USTRINGPARAM( SVG_PROP_GRADIENT ) ), sal_True );
239 
240         maFilterData = aCfgItem.GetFilterData();
241 #else
242         maFilterData.realloc( 6 );
243 
244         maFilterData[ 0 ].Name = B2UCONST( SVG_PROP_TINYPROFILE );
245         maFilterData[ 0 ].Value <<= (sal_Bool) sal_True;
246 
247         // font embedding
248         const char* pSVGDisableFontEmbedding = getenv( "SVG_DISABLE_FONT_EMBEDDING" );
249 
250         maFilterData[ 1 ].Name = B2UCONST( SVG_PROP_EMBEDFONTS );
251         maFilterData[ 1 ].Value <<= (sal_Bool) ( pSVGDisableFontEmbedding ? sal_False : sal_True );
252 
253         // Native decoration
254         maFilterData[ 2 ].Name = B2UCONST( SVG_PROP_NATIVEDECORATION );
255         maFilterData[ 2 ].Value <<= (sal_Bool) sal_False;
256 
257         // glyph placement
258         const char* pSVGGlyphPlacement = getenv( "SVG_GLYPH_PLACEMENT" );
259 
260         maFilterData[ 3 ].Name = B2UCONST( SVG_PROP_GLYPHPLACEMENT );
261 
262         if( pSVGGlyphPlacement )
263             maFilterData[ 3 ].Value <<= ::rtl::OUString::createFromAscii( pSVGGlyphPlacement );
264         else
265             maFilterData[ 3 ].Value <<= B2UCONST( "xlist" );
266 
267         // Tiny Opacity
268         maFilterData[ 4 ].Name = B2UCONST( SVG_PROP_OPACITY );
269         maFilterData[ 4 ].Value <<= (sal_Bool) sal_True;
270 
271         // Tiny Gradient
272         maFilterData[ 5 ].Name = B2UCONST( SVG_PROP_GRADIENT );
273         maFilterData[ 5 ].Value <<= (sal_Bool) sal_False;
274 #endif
275     }
276 
277     if( xOStm.is() && xServiceFactory.is() )
278     {
279 		Reference< XMasterPagesSupplier >	xMasterPagesSupplier( mxSrcDoc, UNO_QUERY );
280 		Reference< XDrawPagesSupplier >		xDrawPagesSupplier( mxSrcDoc, UNO_QUERY );
281 
282 		if( xMasterPagesSupplier.is() && xDrawPagesSupplier.is() )
283 		{
284 			Reference< XDrawPages >   xMasterPages( xMasterPagesSupplier->getMasterPages(), UNO_QUERY );
285 			Reference< XDrawPages >   xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY );
286 
287 			if( xMasterPages.is() && xMasterPages->getCount() && xDrawPages.is() && xDrawPages->getCount() )
288 			{
289                 Reference< XDocumentHandler > xDocHandler( implCreateExportDocumentHandler( xOStm ) );
290 
291                 if( xDocHandler.is() )
292                 {
293 					mbPresentation = Reference< XPresentationSupplier >( mxSrcDoc, UNO_QUERY ).is();
294 					mpObjects = new ObjectMap;
295 
296 					// #110680#
297 					// mpSVGExport = new SVGExport( xDocHandler );
298                     mpSVGExport = new SVGExport( xServiceFactory, xDocHandler, maFilterData );
299 
300                     if( nPageToExport < 0 || nPageToExport >= xDrawPages->getCount() )
301                         nPageToExport = SVG_EXPORT_ALLPAGES;
302 
303 					try
304 					{
305     					const sal_Int32 nDefaultPage = ( ( SVG_EXPORT_ALLPAGES == nPageToExport ) ? 0 : nPageToExport );
306 
307 						xDrawPages->getByIndex( nDefaultPage ) >>= mxDefaultPage;
308 
309 						if( mxDefaultPage.is() )
310 						{
311 							SvxDrawPage* pSvxDrawPage = SvxDrawPage::getImplementation( mxDefaultPage );
312 
313 							if( pSvxDrawPage )
314 							{
315 								mpDefaultSdrPage = pSvxDrawPage->GetSdrPage();
316 								mpSdrModel = mpDefaultSdrPage->GetModel();
317 
318 								if( mpSdrModel )
319 								{
320 									SdrOutliner& rOutl = mpSdrModel->GetDrawOutliner(NULL);
321 
322 									maOldFieldHdl = rOutl.GetCalcFieldValueHdl();
323 									rOutl.SetCalcFieldValueHdl( LINK( this, SVGFilter, CalcFieldHdl) );
324 								}
325 							}
326 
327 							if( implCreateObjects( xMasterPages, xDrawPages, nPageToExport ) )
328 							{
329 								ObjectMap::const_iterator				aIter( mpObjects->begin() );
330 								::std::vector< ObjectRepresentation >	aObjects( mpObjects->size() );
331 								sal_uInt32								nPos = 0;
332 
333 								while( aIter != mpObjects->end() )
334 								{
335 									aObjects[ nPos++ ] = (*aIter).second;
336 									++aIter;
337 								}
338 
339 								mpSVGFontExport = new SVGFontExport( *mpSVGExport, aObjects );
340 								mpSVGWriter = new SVGActionWriter( *mpSVGExport, *mpSVGFontExport );
341 
342 								bRet = implExportDocument( xMasterPages, xDrawPages, nPageToExport );
343 							}
344 						}
345 					}
346 					catch( ... )
347 					{
348 						delete mpSVGDoc, mpSVGDoc = NULL;
349 						DBG_ERROR( "Exception caught" );
350 					}
351 
352 					if( mpSdrModel )
353 						mpSdrModel->GetDrawOutliner( NULL ).SetCalcFieldValueHdl( maOldFieldHdl );
354 
355 					delete mpSVGWriter, mpSVGWriter = NULL;
356                     delete mpSVGExport, mpSVGExport = NULL;
357 					delete mpSVGFontExport, mpSVGFontExport = NULL;
358 					delete mpObjects, mpObjects = NULL;
359                     mbPresentation = sal_False;
360                 }
361 			}
362 		}
363 	}
364 
365     delete pOStm;
366 
367 	return bRet;
368 }
369 
370 // -----------------------------------------------------------------------------
371 
implCreateExportDocumentHandler(const Reference<XOutputStream> & rxOStm)372 Reference< XDocumentHandler > SVGFilter::implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm )
373 {
374 	Reference< XMultiServiceFactory >   xMgr( ::comphelper::getProcessServiceFactory() );
375     Reference< XDocumentHandler >       xSaxWriter;
376 
377 	if( xMgr.is() && rxOStm.is() )
378 	{
379 		xSaxWriter = Reference< XDocumentHandler >( xMgr->createInstance( B2UCONST( "com.sun.star.xml.sax.Writer" ) ), UNO_QUERY );
380 
381 		if( xSaxWriter.is() )
382 		{
383 			Reference< XActiveDataSource > xActiveDataSource( xSaxWriter, UNO_QUERY );
384 
385 			if( xActiveDataSource.is() )
386 				xActiveDataSource->setOutputStream( rxOStm );
387             else
388                 xSaxWriter = NULL;
389 		}
390 	}
391 
392     return xSaxWriter;
393 }
394 
395 // -----------------------------------------------------------------------------
396 
implExportDocument(const Reference<XDrawPages> & rxMasterPages,const Reference<XDrawPages> & rxDrawPages,sal_Int32 nPageToExport)397 sal_Bool SVGFilter::implExportDocument( const Reference< XDrawPages >& rxMasterPages,
398 										const Reference< XDrawPages >& rxDrawPages,
399                                         sal_Int32 nPageToExport )
400 {
401 	DBG_ASSERT( rxMasterPages.is() && rxDrawPages.is(),
402 				"SVGFilter::implExportDocument: invalid parameter" );
403 
404 	OUString		aAttr;
405 	sal_Int32		nDocX = 0, nDocY = 0; // #124608#
406 	sal_Int32		nDocWidth = 0, nDocHeight = 0;
407 	sal_Int32		nVisible = -1, nVisibleMaster = -1;
408 	sal_Bool 		bRet = sal_False;
409 	const sal_Bool	bSinglePage = ( rxDrawPages->getCount() == 1 ) || ( SVG_EXPORT_ALLPAGES != nPageToExport );
410     const sal_Int32 nFirstPage = ( ( SVG_EXPORT_ALLPAGES == nPageToExport ) ? 0 : nPageToExport );
411 	sal_Int32       nCurPage = nFirstPage, nLastPage = ( bSinglePage ? nFirstPage : ( rxDrawPages->getCount() - 1 ) );
412 
413 	const Reference< XPropertySet >             xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY );
414     const Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
415 
416     // #124608#
417     mbExportSelection = maShapeSelection.is() && maShapeSelection->getCount();
418 
419     if(xDefaultPagePropertySet.is())
420     {
421         xDefaultPagePropertySet->getPropertyValue(B2UCONST("Width")) >>= nDocWidth;
422         xDefaultPagePropertySet->getPropertyValue(B2UCONST("Height")) >>= nDocHeight;
423     }
424 
425     if(mbExportSelection)
426     {
427         // #124608# create BoundRange and set nDocX, nDocY, nDocWidth and nDocHeight
428         basegfx::B2DRange aShapeRange;
429 
430         Reference< XPrimitiveFactory2D > xPrimitiveFactory(
431             mxMSF->createInstance(
432                 String(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.graphic.PrimitiveFactory2D"))),
433                 UNO_QUERY);
434 
435         // use XPrimitiveFactory2D and go the way over getting the primitives; this
436         // will give better precision (doubles) and be based on the true object
437         // geometry. If needed aViewInformation may be expanded to carry a view
438         // resolution for which to prepare the geometry.
439         if(xPrimitiveFactory.is())
440         {
441             Reference< XShape > xShapeCandidate;
442             const Sequence< PropertyValue > aViewInformation;
443             const Sequence< PropertyValue > aParams;
444 
445             for(sal_Int32 a(0); a < maShapeSelection->getCount(); a++)
446             {
447                 if((maShapeSelection->getByIndex(a) >>= xShapeCandidate) && xShapeCandidate.is())
448                 {
449                     const Sequence< Reference< XPrimitive2D > > aPrimitiveSequence(
450                         xPrimitiveFactory->createPrimitivesFromXShape( xShapeCandidate, aParams ));
451                     const sal_Int32 nCount(aPrimitiveSequence.getLength());
452 
453                     for(sal_Int32 nIndex = 0; nIndex < nCount; nIndex++)
454                     {
455                         const RealRectangle2D aRect(aPrimitiveSequence[nIndex]->getRange(aViewInformation));
456 
457                         aShapeRange.expand(basegfx::B2DTuple(aRect.X1, aRect.Y1));
458                         aShapeRange.expand(basegfx::B2DTuple(aRect.X2, aRect.Y2));
459                     }
460                 }
461             }
462         }
463 
464         if(!aShapeRange.isEmpty())
465         {
466             nDocX = basegfx::fround(aShapeRange.getMinX());
467             nDocY = basegfx::fround(aShapeRange.getMinY());
468             nDocWidth  = basegfx::fround(aShapeRange.getWidth());
469             nDocHeight = basegfx::fround(aShapeRange.getHeight());
470         }
471     }
472 
473     if( xExtDocHandler.is() && !mpSVGExport->IsUseTinyProfile() )
474     {
475         xExtDocHandler->unknown( SVG_DTD_STRING );
476     }
477 
478     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "version", B2UCONST( "1.2" ) );
479 
480     if( mpSVGExport->IsUseTinyProfile() )
481          mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "baseProfile", B2UCONST( "tiny" ) );
482 
483 #ifdef _SVG_WRITE_EXTENTS
484 	aAttr = OUString::valueOf( nDocWidth * 0.01 );
485 	aAttr += B2UCONST( "mm" );
486 	mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
487 
488 	aAttr = OUString::valueOf( nDocHeight * 0.01 );
489 	aAttr += B2UCONST( "mm" );
490 	mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
491 #endif
492 
493     // #124608# set viewBox explicitly to the exported content
494     if(mbExportSelection)
495     {
496         aAttr = OUString::valueOf( nDocX );
497         aAttr += B2UCONST( " " );
498         aAttr += OUString::valueOf( nDocY );
499         aAttr += B2UCONST( " " );
500     }
501     else
502     {
503         aAttr = B2UCONST( "0 0 " );
504     }
505 
506     aAttr += OUString::valueOf( nDocWidth );
507     aAttr += B2UCONST( " " );
508     aAttr += OUString::valueOf( nDocHeight );
509 	mpSVGExport->SetViewBox( Rectangle( Point(nDocX, nDocY), Size( nDocWidth, nDocHeight ) ) );
510     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
511 	mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", B2UCONST( "xMidYMid" ) );
512 	mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", B2UCONST( "evenodd" ) );
513 
514     // standard line width is based on 1 pixel on a 90 DPI device (0.28222mmm)
515     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::valueOf( 28.222 ) );
516     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", B2UCONST( "round" ) );
517 
518 	if( !bSinglePage )
519 	{
520 		mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:ooo", B2UCONST( "http://xml.openoffice.org/svg/export" ) );
521 		mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "onclick", B2UCONST( "onClick(evt)" ) );
522 		mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "onkeypress", B2UCONST( "onKeyPress(evt)" ) );
523 	}
524 
525 	mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns", B2UCONST( "http://www.w3.org/2000/svg" ) );
526 	mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:xlink", B2UCONST( "http://www.w3.org/1999/xlink" ) );
527 
528     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xml:space", B2UCONST( "preserve" ) );
529 
530 	mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", sal_True, sal_True );
531 
532 	while( ( nCurPage <= nLastPage ) && ( -1 == nVisible ) )
533 	{
534 		Reference< XDrawPage > xDrawPage;
535 
536 		rxDrawPages->getByIndex( nCurPage ) >>= xDrawPage;
537 
538 		if( xDrawPage.is() )
539 		{
540 			Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
541 
542 			if( xPropSet.is() )
543 			{
544 				sal_Bool bVisible = sal_False;
545 
546 				if( !mbPresentation || bSinglePage ||
547 					( ( xPropSet->getPropertyValue( B2UCONST( "Visible" ) ) >>= bVisible ) && bVisible ) )
548 				{
549 					Reference< XMasterPageTarget > xMasterTarget( xDrawPage, UNO_QUERY );
550 
551 					if( xMasterTarget.is() )
552 					{
553 						Reference< XDrawPage > xMasterPage( xMasterTarget->getMasterPage() );
554 
555 						nVisible = nCurPage;
556 
557 						for( sal_Int32 nMaster = 0, nMasterCount = rxMasterPages->getCount();
558 							 ( nMaster < nMasterCount ) && ( -1 == nVisibleMaster );
559 							 ++nMaster )
560 						{
561 							Reference< XDrawPage > xMasterTestPage;
562 
563 							rxMasterPages->getByIndex( nMaster ) >>= xMasterTestPage;
564 
565 							if( xMasterTestPage == xMasterPage )
566 								nVisibleMaster = nMaster;
567 						}
568 					}
569 				}
570 			}
571 		}
572 
573 		++nCurPage;
574 	}
575 
576     if( mpSVGExport->IsEmbedFonts() )
577     {
578         mpSVGFontExport->EmbedFonts();
579     }
580 
581 	if( -1 != nVisible )
582 	{
583         if(bSinglePage)
584         {
585             if(mbExportSelection)
586             {
587                 // #124608# export a given object selection, so no MasterPage export at all
588             }
589             else
590             {
591                 implExportPages(rxMasterPages,nVisibleMaster,nVisibleMaster,nVisibleMaster,sal_True);
592             }
593         }
594         else
595         {
596 			implGenerateMetaData( rxMasterPages, rxDrawPages );
597 			implGenerateScript( rxMasterPages, rxDrawPages );
598 			implExportPages( rxMasterPages, 0, rxMasterPages->getCount() - 1, nVisibleMaster, sal_True );
599 		}
600 
601 		implExportPages( rxDrawPages, nFirstPage, nLastPage, nVisible, sal_False );
602 
603 		delete mpSVGDoc, mpSVGDoc = NULL;
604 		bRet = sal_True;
605 	}
606 
607     return bRet;
608 }
609 
610 // -----------------------------------------------------------------------------
611 
implGenerateMetaData(const Reference<XDrawPages> &,const Reference<XDrawPages> & rxDrawPages)612 sal_Bool SVGFilter::implGenerateMetaData( const Reference< XDrawPages >& /* rxMasterPages */,
613 										  const Reference< XDrawPages >& rxDrawPages )
614 {
615 	sal_Bool bRet = sal_False;
616 
617 	if( rxDrawPages->getCount() )
618 	{
619 		mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", B2UCONST( "meta_slides" ) );
620 		mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "numberOfSlides", OUString::valueOf( rxDrawPages->getCount() ) );
621 
622 		{
623 			SvXMLElementExport	aExp( *mpSVGExport, XML_NAMESPACE_NONE, "ooo:slidesInfo", sal_True, sal_True );
624 			const OUString		aId( B2UCONST( "meta_slide" ) );
625 
626 			for( sal_Int32 i = 0, nCount = rxDrawPages->getCount(); i < nCount; ++i )
627 			{
628 				OUString						aSlideId( aId );
629 				Reference< XDrawPage >			xDrawPage( rxDrawPages->getByIndex( i ), UNO_QUERY );
630 				Reference< XMasterPageTarget >	xMasterPageTarget( xDrawPage, UNO_QUERY );
631 				Reference< XDrawPage >			xMasterPage( xMasterPageTarget->getMasterPage(), UNO_QUERY );
632                 sal_Bool                        bMasterVisible = sal_True;
633                 OUString                        aMasterVisibility;
634 
635 				aSlideId += OUString::valueOf( i );
636 
637                 if( mbPresentation )
638                 {
639                     Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
640 
641                     if( xPropSet.is() )
642                         xPropSet->getPropertyValue( B2UCONST( "Background" ) )  >>= bMasterVisible;
643                 }
644 
645                 if( bMasterVisible )
646                     aMasterVisibility = B2UCONST( "visible" );
647                 else
648                     aMasterVisibility = B2UCONST( "hidden" );
649 
650                 mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aSlideId );
651 				mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "slide", implGetValidIDFromInterface( xDrawPage ) );
652 				mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "master", implGetValidIDFromInterface( xMasterPage ) );
653 				mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "master-visibility", aMasterVisibility );
654 
655 				{
656 					SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "ooo:slideInfo", sal_True, sal_True );
657 				}
658 			}
659 		}
660 
661 
662 		bRet =sal_True;
663 	}
664 
665 	return bRet;
666 }
667 
668 // -----------------------------------------------------------------------------
669 
implGenerateScript(const Reference<XDrawPages> &,const Reference<XDrawPages> &)670 sal_Bool SVGFilter::implGenerateScript( const Reference< XDrawPages >& /* rxMasterPages */,
671                                         const Reference< XDrawPages >& /* rxDrawPages */ )
672 {
673     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "type", B2UCONST( "text/ecmascript" ) );
674 
675     {
676         SvXMLElementExport	                    aExp( *mpSVGExport, XML_NAMESPACE_NONE, "script", sal_True, sal_True );
677         Reference< XExtendedDocumentHandler >	xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
678 
679         if( xExtDocHandler.is() )
680         {
681             xExtDocHandler->unknown( OUString::createFromAscii( aSVGScript1 ) );
682             xExtDocHandler->unknown( OUString::createFromAscii( aSVGScript2 ) );
683         }
684     }
685 
686     return sal_True;
687 }
688 
689 // -----------------------------------------------------------------------------
690 
implExportPages(const Reference<XDrawPages> & rxPages,sal_Int32 nFirstPage,sal_Int32 nLastPage,sal_Int32 nVisiblePage,sal_Bool bMaster)691 sal_Bool SVGFilter::implExportPages( const Reference< XDrawPages >& rxPages,
692                                      sal_Int32 nFirstPage, sal_Int32 nLastPage,
693 									 sal_Int32 nVisiblePage, sal_Bool bMaster )
694 {
695     DBG_ASSERT( nFirstPage <= nLastPage,
696                 "SVGFilter::implExportPages: nFirstPage > nLastPage" );
697 
698 	sal_Bool bRet = sal_False;
699 
700 	for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
701 	{
702 		Reference< XDrawPage > xDrawPage;
703 
704 		rxPages->getByIndex( i ) >>= xDrawPage;
705 
706 		if( xDrawPage.is() )
707 		{
708             Reference< XShapes > xShapes;
709 
710             if(mbExportSelection)
711             {
712                 // #124608# export a given object selection
713                 xShapes = maShapeSelection;
714             }
715             else
716             {
717                 xShapes = Reference< XShapes >( xDrawPage, UNO_QUERY );
718             }
719 
720 			if( xShapes.is() )
721 			{
722                 OUString aVisibility, aId, aSlideName( implGetValidIDFromInterface( xShapes, sal_True ) );
723 
724 	            // add visibility attribute
725                 if( i == nVisiblePage )
726 					aVisibility = B2UCONST( "visible" );
727 				else
728 					aVisibility = B2UCONST( "hidden" );
729 
730 	            mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", aVisibility );
731 
732                 // add id attribute
733                 if( bMaster )
734                     aId = ( B2UCONST( "MasterSlide_" ) ) += ::rtl::OUString::valueOf( ++mnMasterSlideId );
735                 else
736                     aId = ( B2UCONST( "Slide_" ) ) += ::rtl::OUString::valueOf( ++mnSlideId );
737 
738                 if( aSlideName.getLength() )
739                     ( aId += B2UCONST( "_" ) ) += aSlideName;
740 
741                 mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId );
742 
743 				{
744 					SvXMLElementExport	aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
745 					const Point			aNullPt;
746 
747                     if( mpObjects->find( xDrawPage ) != mpObjects->end() )
748 					{
749 						Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
750 
751 						if( xExtDocHandler.is() )
752 						{
753 							SvXMLElementExport	aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True );
754 							OUString			aDesc;
755 
756 							if( bMaster )
757                                 aDesc = B2UCONST( "Master slide" );
758 							else
759 								aDesc = B2UCONST( "Slide" );
760 
761 							xExtDocHandler->unknown( aDesc );
762 						}
763 					}
764 
765 					if( bMaster )
766 					{
767 						const GDIMetaFile& rMtf = (*mpObjects)[ xDrawPage ].GetRepresentation();
768 						mpSVGWriter->WriteMetaFile( aNullPt, rMtf.GetPrefSize(), rMtf, SVGWRITER_WRITE_FILL );
769 					}
770 
771 					bRet = implExportShapes( xShapes ) || bRet;
772 				}
773 			}
774 		}
775 	}
776 
777     return bRet;
778 }
779 
780 // -----------------------------------------------------------------------------
781 
implExportShapes(const Reference<XShapes> & rxShapes)782 sal_Bool SVGFilter::implExportShapes( const Reference< XShapes >& rxShapes )
783 {
784     Reference< XShape > xShape;
785 	sal_Bool			bRet = sal_False;
786 
787     for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
788     {
789         if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
790 			bRet = implExportShape( xShape ) || bRet;
791 
792         xShape = NULL;
793     }
794 
795 	return bRet;
796 }
797 
798 // -----------------------------------------------------------------------------
799 
implExportShape(const Reference<XShape> & rxShape)800 sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
801 {
802     Reference< XPropertySet >   xShapePropSet( rxShape, UNO_QUERY );
803     sal_Bool                    bRet = sal_False;
804 
805     if( xShapePropSet.is() )
806     {
807         const ::rtl::OUString   aShapeType( rxShape->getShapeType() );
808         sal_Bool                    bHideObj = sal_False;
809 
810         if( mbPresentation )
811         {
812             xShapePropSet->getPropertyValue( B2UCONST( "IsEmptyPresentationObject" ) )  >>= bHideObj;
813 
814             if( !bHideObj )
815             {
816 				const Reference< XPropertySet > xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY );
817 				Reference< XPropertySetInfo > 	xPagePropSetInfo( xDefaultPagePropertySet->getPropertySetInfo() );
818 
819                 if( xPagePropSetInfo.is() )
820                 {
821                     const ::rtl::OUString aHeaderString( B2UCONST( "IsHeaderVisible" ) );
822                     const ::rtl::OUString aFooterString( B2UCONST( "IsFooterVisible" ) );
823                     const ::rtl::OUString aDateTimeString( B2UCONST( "IsDateTimeVisible" ) );
824                     const ::rtl::OUString aPageNumberString( B2UCONST( "IsPageNumberVisible" ) );
825 
826                     Any     aProperty;
827                     sal_Bool    bValue = sal_False;
828 
829                     if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.HeaderShape" ) ) != -1 ) &&
830                         xPagePropSetInfo->hasPropertyByName( aHeaderString ) &&
831                         ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aHeaderString ) ) >>= bValue ) &&
832                         !bValue )
833                     {
834                         bHideObj = sal_True;
835                     }
836                     else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.FooterShape" ) ) != -1 ) &&
837                                 xPagePropSetInfo->hasPropertyByName( aFooterString ) &&
838                                 ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aFooterString ) ) >>= bValue ) &&
839                             !bValue )
840                     {
841                         bHideObj = sal_True;
842                     }
843                     else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.DateTimeShape" ) ) != -1 ) &&
844                                 xPagePropSetInfo->hasPropertyByName( aDateTimeString ) &&
845                                 ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aDateTimeString ) ) >>= bValue ) &&
846                             !bValue )
847                     {
848                         bHideObj = sal_True;
849                     }
850                     else if( ( aShapeType.lastIndexOf( B2UCONST( "presentation.SlideNumberShape" ) ) != -1 ) &&
851                                 xPagePropSetInfo->hasPropertyByName( aPageNumberString ) &&
852                                 ( ( aProperty = xDefaultPagePropertySet->getPropertyValue( aPageNumberString ) ) >>= bValue ) &&
853                             !bValue )
854                     {
855                         bHideObj = sal_True;
856                     }
857                 }
858             }
859         }
860 
861         if( !bHideObj )
862         {
863 		    if( aShapeType.lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 )
864 		    {
865 			    Reference< XShapes > xShapes( rxShape, UNO_QUERY );
866 
867 			    if( xShapes.is() )
868 			    {
869                     OUString    aId( B2UCONST( "DrawingGroup_" ) );
870                     OUString    aObjName( implGetValidIDFromInterface( rxShape, sal_True ) ), aObjDesc;
871 
872                     aId += ::rtl::OUString::valueOf( ++mnDrawingGroupId );
873 
874                     if( aObjName.getLength() )
875                         ( aId += B2UCONST( "_" ) ) += aObjName;
876 
877                     mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId );
878 
879                     {
880 						SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
881         			    bRet = implExportShapes( xShapes );
882                     }
883                 }
884 		    }
885 
886 		    if( !bRet && mpObjects->find( rxShape ) !=  mpObjects->end() )
887 		    {
888  			    Reference< XText >                  xText( rxShape, UNO_QUERY );
889 				::com::sun::star::awt::Rectangle    aBoundRect;
890 				const GDIMetaFile&					rMtf = (*mpObjects)[ rxShape ].GetRepresentation();
891 
892                 xShapePropSet->getPropertyValue( B2UCONST( "BoundRect" ) ) >>= aBoundRect;
893 
894                 const Point aTopLeft( aBoundRect.X, aBoundRect.Y );
895                 const Size  aSize( aBoundRect.Width, aBoundRect.Height );
896 
897                 if( rMtf.GetActionCount() )
898                 {
899                     OUString aId( B2UCONST( "Drawing_" ) );
900                     OUString aObjName( implGetValidIDFromInterface( rxShape, sal_True ) ), aObjDesc;
901 
902                     aId += ::rtl::OUString::valueOf( ++mnDrawingId );
903 
904                     if( aObjName.getLength() )
905                         ( aId += B2UCONST( "_" ) ) += aObjName;
906 
907                     {
908                         if( ( aShapeType.lastIndexOf( B2UCONST( "drawing.OLE2Shape" ) ) != -1 ) ||
909                             ( aShapeType.lastIndexOf( B2UCONST( "drawing.GraphicObjectShape" ) ) != -1 ) )
910                         {
911                             mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId );
912 
913                             {
914                                 SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
915                                 mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT );
916                             }
917                         }
918                         else
919                         {
920                             if( implHasText( rMtf ) )
921                             {
922                                 mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aId );
923 
924                                 {
925                                     SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
926                                     mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL );
927                                     mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_TEXT );
928                                 }
929                             }
930                             else
931                             {
932                                 SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
933                                 mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf, SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT, &aId );
934                             }
935                         }
936                     }
937                 }
938 
939 				bRet = sal_True;
940 		    }
941         }
942     }
943 
944     return bRet;
945 }
946 
947 // -----------------------------------------------------------------------------
948 
implCreateObjects(const Reference<XDrawPages> & rxMasterPages,const Reference<XDrawPages> & rxDrawPages,sal_Int32 nPageToExport)949 sal_Bool SVGFilter::implCreateObjects( const Reference< XDrawPages >& rxMasterPages,
950 								       const Reference< XDrawPages >& rxDrawPages,
951                                        sal_Int32 nPageToExport )
952 {
953     if( SVG_EXPORT_ALLPAGES == nPageToExport )
954     {
955         // export the whole document
956 	    sal_Int32 i, nCount;
957 
958         for( i = 0, nCount = rxMasterPages->getCount(); i < nCount; ++i )
959     	{
960     		Reference< XDrawPage > xMasterPage;
961 
962     		rxMasterPages->getByIndex( i ) >>= xMasterPage;
963 
964     		if( xMasterPage.is() )
965     		{
966     			Reference< XShapes > xShapes( xMasterPage, UNO_QUERY );
967 
968     			implCreateObjectsFromBackground( xMasterPage );
969 
970     			if( xShapes.is() )
971     				implCreateObjectsFromShapes( xShapes );
972     		}
973     	}
974 
975     	for( i = 0, nCount = rxDrawPages->getCount(); i < nCount; ++i )
976     	{
977     		Reference< XDrawPage > xDrawPage;
978 
979     		rxDrawPages->getByIndex( i ) >>= xDrawPage;
980 
981     		if( xDrawPage.is() )
982     		{
983     			Reference< XShapes > xShapes( xDrawPage, UNO_QUERY );
984 
985     			if( xShapes.is() )
986     				implCreateObjectsFromShapes( xShapes );
987     		}
988     	}
989     }
990     else
991     {
992         DBG_ASSERT( nPageToExport >= 0 && nPageToExport < rxDrawPages->getCount(),
993                     "SVGFilter::implCreateObjects: invalid page number to export" );
994 
995         if(mbExportSelection)
996         {
997             // #124608# export a given object selection
998             implCreateObjectsFromShapes(maShapeSelection);
999         }
1000         else
1001         {
1002             // export a given xDrawPage
1003             Reference< XDrawPage > xDrawPage;
1004 
1005             rxDrawPages->getByIndex(nPageToExport) >>= xDrawPage;
1006 
1007             if(xDrawPage.is())
1008             {
1009                 Reference< XMasterPageTarget > xMasterTarget(xDrawPage,UNO_QUERY);
1010 
1011                 if(xMasterTarget.is())
1012                 {
1013                     Reference< XDrawPage > xMasterPage(xMasterTarget->getMasterPage());
1014 
1015                     if(xMasterPage.is())
1016                     {
1017                         Reference< XShapes > xShapes(xMasterPage,UNO_QUERY);
1018 
1019                         implCreateObjectsFromBackground(xMasterPage);
1020 
1021                         if(xShapes.is())
1022                             implCreateObjectsFromShapes(xShapes);
1023                     }
1024                 }
1025 
1026                 Reference< XShapes > xShapes(xDrawPage,UNO_QUERY);
1027 
1028                 if(xShapes.is())
1029                     implCreateObjectsFromShapes(xShapes);
1030             }
1031         }
1032     }
1033 
1034 	return sal_True;
1035 }
1036 
1037 // -----------------------------------------------------------------------------
1038 
implCreateObjectsFromShapes(const Reference<XShapes> & rxShapes)1039 sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XShapes >& rxShapes )
1040 {
1041     Reference< XShape > xShape;
1042 	sal_Bool			bRet = sal_False;
1043 
1044     for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
1045     {
1046         if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
1047 			bRet = implCreateObjectsFromShape( xShape ) || bRet;
1048 
1049         xShape = NULL;
1050     }
1051 
1052 	return bRet;
1053 }
1054 
1055 // -----------------------------------------------------------------------------
1056 
implCreateObjectsFromShape(const Reference<XShape> & rxShape)1057 sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XShape >& rxShape )
1058 {
1059     sal_Bool bRet = sal_False;
1060 
1061 	if( rxShape->getShapeType().lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 )
1062 	{
1063 		Reference< XShapes > xShapes( rxShape, UNO_QUERY );
1064 
1065 		if( xShapes.is() )
1066 			bRet = implCreateObjectsFromShapes( xShapes );
1067 	}
1068 	else
1069 	{
1070 		SdrObject*  pObj = GetSdrObjectFromXShape( rxShape );
1071 
1072 		if( pObj )
1073 		{
1074 			Graphic aGraphic( SdrExchangeView::GetObjGraphic( pObj->GetModel(), pObj ) );
1075 
1076 			if( aGraphic.GetType() != GRAPHIC_NONE )
1077 			{
1078 				if( aGraphic.GetType() == GRAPHIC_BITMAP )
1079 				{
1080 					GDIMetaFile	aMtf;
1081 					const Point	aNullPt;
1082 					const Size	aSize( pObj->GetCurrentBoundRect().GetSize() );
1083 
1084 					aMtf.AddAction( new MetaBmpExScaleAction( aNullPt, aSize, aGraphic.GetBitmapEx() ) );
1085 					aMtf.SetPrefSize( aSize );
1086 					aMtf.SetPrefMapMode( MAP_100TH_MM );
1087 
1088 					(*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
1089 				}
1090 				else
1091 					(*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
1092 
1093 				bRet = sal_True;
1094 			}
1095 		}
1096 	}
1097 
1098     return bRet;
1099 }
1100 
1101 // -----------------------------------------------------------------------------
1102 
implCreateObjectsFromBackground(const Reference<XDrawPage> & rxMasterPage)1103 sal_Bool SVGFilter::implCreateObjectsFromBackground( const Reference< XDrawPage >& rxMasterPage )
1104 {
1105 	Reference< XExporter >	xExporter( mxMSF->createInstance( B2UCONST( "com.sun.star.drawing.GraphicExportFilter" ) ), UNO_QUERY );
1106 	sal_Bool				bRet = sal_False;
1107 
1108 	if( xExporter.is() )
1109 	{
1110 		GDIMetaFile				aMtf;
1111 		Reference< XFilter >	xFilter( xExporter, UNO_QUERY );
1112 
1113 		utl::TempFile aFile;
1114 		aFile.EnableKillingFile();
1115 
1116 		Sequence< PropertyValue > aDescriptor( 3 );
1117 		aDescriptor[0].Name = B2UCONST( "FilterName" );
1118 		aDescriptor[0].Value <<= B2UCONST( "SVM" );
1119 		aDescriptor[1].Name = B2UCONST( "URL" );
1120 		aDescriptor[1].Value <<= OUString( aFile.GetURL() );
1121 		aDescriptor[2].Name = B2UCONST( "ExportOnlyBackground" );
1122 		aDescriptor[2].Value <<= (sal_Bool) sal_True;
1123 
1124 		xExporter->setSourceDocument( Reference< XComponent >( rxMasterPage, UNO_QUERY ) );
1125 		xFilter->filter( aDescriptor );
1126 		aMtf.Read( *aFile.GetStream( STREAM_READ ) );
1127 
1128 		(*mpObjects)[ rxMasterPage ] = ObjectRepresentation( rxMasterPage, aMtf );
1129 
1130 		bRet = sal_True;
1131 	}
1132 
1133 	return bRet;
1134 }
1135 
1136 // -----------------------------------------------------------------------------
1137 
implGetDescriptionFromShape(const Reference<XShape> & rxShape)1138 OUString SVGFilter::implGetDescriptionFromShape( const Reference< XShape >& rxShape )
1139 {
1140 	OUString			aRet;
1141     const OUString      aShapeType( rxShape->getShapeType() );
1142 
1143 	if( aShapeType.lastIndexOf( B2UCONST( "drawing.GroupShape" ) ) != -1 )
1144 		aRet = B2UCONST( "Group" );
1145 	else if( aShapeType.lastIndexOf( B2UCONST( "drawing.GraphicObjectShape" ) ) != -1 )
1146 		aRet = B2UCONST( "Graphic" );
1147 	else if( aShapeType.lastIndexOf( B2UCONST( "drawing.OLE2Shape" ) ) != -1 )
1148 		aRet = B2UCONST( "OLE2" );
1149     else if( aShapeType.lastIndexOf( B2UCONST( "presentation.HeaderShape" ) ) != -1 )
1150 		aRet = B2UCONST( "Header" );
1151     else if( aShapeType.lastIndexOf( B2UCONST( "presentation.FooterShape" ) ) != -1 )
1152 		aRet = B2UCONST( "Footer" );
1153     else if( aShapeType.lastIndexOf( B2UCONST( "presentation.DateTimeShape" ) ) != -1 )
1154 		aRet = B2UCONST( "Date/Time" );
1155     else if( aShapeType.lastIndexOf( B2UCONST( "presentation.SlideNumberShape" ) ) != -1 )
1156 		aRet = B2UCONST( "Slide Number" );
1157 	else
1158 		aRet = B2UCONST( "Drawing" );
1159 
1160 	return aRet;
1161 }
1162 
1163 // -----------------------------------------------------------------------------
1164 
implGetValidIDFromInterface(const Reference<XInterface> & rxIf,sal_Bool bUnique)1165 OUString SVGFilter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf, sal_Bool bUnique )
1166 {
1167 	Reference< XNamed > xNamed( rxIf, UNO_QUERY );
1168 	OUString			aRet;
1169 
1170 	if( xNamed.is() )
1171     {
1172         aRet = xNamed->getName().replace( ' ', '_' ).
1173                replace( ':', '_' ).
1174                replace( ',', '_' ).
1175                replace( ';', '_' ).
1176                replace( '&', '_' ).
1177                replace( '!', '_' ).
1178                replace( '|', '_' );
1179     }
1180 
1181     if( ( aRet.getLength() > 0 ) && bUnique )
1182     {
1183         while( ::std::find( maUniqueIdVector.begin(), maUniqueIdVector.end(), aRet ) != maUniqueIdVector.end() )
1184         {
1185             aRet += B2UCONST( "_" );
1186         }
1187 
1188         maUniqueIdVector.push_back( aRet );
1189     }
1190 
1191 	return aRet;
1192 }
1193 
1194 // -----------------------------------------------------------------------------
1195 
implHasText(const GDIMetaFile & rMtf) const1196 sal_Bool SVGFilter::implHasText( const GDIMetaFile& rMtf ) const
1197 {
1198     sal_Bool bRet = sal_False;
1199 
1200     for( sal_uInt32 nCurAction = 0, nCount = rMtf.GetActionCount(); ( nCurAction < nCount ) && !bRet; ++nCurAction )
1201     {
1202         switch( rMtf.GetAction( nCurAction )->GetType() )
1203         {
1204             case( META_TEXT_ACTION ):
1205             case( META_TEXTRECT_ACTION ):
1206             case( META_TEXTARRAY_ACTION ):
1207             case( META_STRETCHTEXT_ACTION ):
1208             {
1209                 bRet = sal_True;
1210             }
1211             break;
1212 
1213             default:
1214             break;
1215         }
1216     }
1217 
1218     return bRet;
1219 }
1220 
1221 // -----------------------------------------------------------------------------
1222 
IMPL_LINK(SVGFilter,CalcFieldHdl,EditFieldInfo *,pInfo)1223 IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo )
1224 {
1225 	OUString   aRepresentation;
1226     sal_Bool       bFieldProcessed = sal_False;
1227 
1228 	if( pInfo )
1229 	{
1230 		const ::rtl::OUString aHeaderText( B2UCONST( "HeaderText" ) );
1231 		const ::rtl::OUString aFooterText( B2UCONST( "FooterText" ) );
1232 		const ::rtl::OUString aDateTimeText( B2UCONST( "DateTimeText" ) );
1233 		const ::rtl::OUString aPageNumberText( B2UCONST( "Number" ) );
1234 
1235 		const Reference< XPropertySet >	xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY );
1236 		Reference< XPropertySetInfo > 	xDefaultPagePropSetInfo( xDefaultPagePropertySet->getPropertySetInfo() );
1237 
1238 		if( xDefaultPagePropSetInfo.is() )
1239 		{
1240 			const SvxFieldData* pField = pInfo->GetField().GetField();
1241 			Any     			aProperty;
1242 
1243 			if( pField->ISA( SvxHeaderField ) &&
1244 				xDefaultPagePropSetInfo->hasPropertyByName( aHeaderText ) )
1245 			{
1246 				xDefaultPagePropertySet->getPropertyValue( aHeaderText ) >>= aRepresentation;
1247                 bFieldProcessed = sal_True;
1248 			}
1249 			else if( pField->ISA( SvxFooterField ) &&
1250 					 xDefaultPagePropSetInfo->hasPropertyByName( aFooterText ) )
1251 			{
1252 				xDefaultPagePropertySet->getPropertyValue( aFooterText ) >>= aRepresentation;
1253                 bFieldProcessed = sal_True;
1254 			}
1255 			else if( pField->ISA( SvxDateTimeField ) &&
1256 					 xDefaultPagePropSetInfo->hasPropertyByName( aDateTimeText ) )
1257 			{
1258 				xDefaultPagePropertySet->getPropertyValue( aDateTimeText ) >>= aRepresentation;
1259                 bFieldProcessed = sal_True;
1260 			}
1261 			else if( pField->ISA( SvxPageField ) &&
1262 					 xDefaultPagePropSetInfo->hasPropertyByName( aPageNumberText ) )
1263 			{
1264 	            String     aPageNumValue;
1265 				sal_Int16  nPageNumber = 0;
1266 
1267                 xDefaultPagePropertySet->getPropertyValue( aPageNumberText ) >>= nPageNumber;
1268 
1269                 if( mpSdrModel )
1270                 {
1271                     sal_Bool bUpper = sal_False;
1272 
1273                 	switch( mpSdrModel->GetPageNumType() )
1274                     {
1275                         case SVX_CHARS_UPPER_LETTER:
1276                             aPageNumValue += (sal_Unicode)(char)( ( nPageNumber - 1 ) % 26 + 'A' );
1277                             break;
1278                         case SVX_CHARS_LOWER_LETTER:
1279                             aPageNumValue += (sal_Unicode)(char)( ( nPageNumber- 1 ) % 26 + 'a' );
1280                             break;
1281                         case SVX_ROMAN_UPPER:
1282                             bUpper = sal_True;
1283                         case SVX_ROMAN_LOWER:
1284                             aPageNumValue += SvxNumberFormat::CreateRomanString( nPageNumber, bUpper );
1285                             break;
1286                         case SVX_NUMBER_NONE:
1287                             aPageNumValue.Erase();
1288                             aPageNumValue += sal_Unicode(' ');
1289                             break;
1290 						default : break;
1291                     }
1292                	}
1293 
1294                 if( !aPageNumValue.Len() )
1295                     aPageNumValue += String::CreateFromInt32( nPageNumber );
1296 
1297                 aRepresentation = aPageNumValue;
1298                 bFieldProcessed = sal_True;
1299 			}
1300 		}
1301 
1302 		pInfo->SetRepresentation( aRepresentation );
1303 	}
1304 
1305 	return( bFieldProcessed ? 0 : maOldFieldHdl.Call( pInfo ) );
1306 }
1307 
1308 // -----------------------------------------------------------------------------
1309 
writeMtf(const GDIMetaFile & rMtf)1310 void SVGExport::writeMtf( const GDIMetaFile& rMtf )
1311 {
1312 	const Size									aSize( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_MM ) );
1313 	rtl::OUString							aAttr;
1314 	REF( NMSP_SAX::XExtendedDocumentHandler )	xExtDocHandler( GetDocHandler(), NMSP_UNO::UNO_QUERY );
1315 
1316 	if( xExtDocHandler.is() )
1317 		xExtDocHandler->unknown( SVG_DTD_STRING );
1318 
1319 	aAttr = rtl::OUString::valueOf( aSize.Width() );
1320 	aAttr += B2UCONST( "mm" );
1321 	AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
1322 
1323 	aAttr = rtl::OUString::valueOf( aSize.Height() );
1324 	aAttr += B2UCONST( "mm" );
1325 	AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
1326 
1327 	aAttr = B2UCONST( "0 0 " );
1328 	aAttr += rtl::OUString::valueOf( aSize.Width() * 100L );
1329 	aAttr += B2UCONST( " " );
1330 	aAttr += rtl::OUString::valueOf( aSize.Height() * 100L );
1331 	AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
1332 	SetViewBox( Rectangle( Point(), Size( aSize.Width() * 100, aSize.Height() * 100 ) ) );
1333 
1334 	// standard line width is based on 1 pixel on a 90 DPI device (0.28222mmm)
1335 	AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::valueOf( 28.222 ) );
1336 	AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", B2UCONST( "round" ) );
1337 
1338 	AddAttribute( XML_NAMESPACE_NONE, "xml:space", B2UCONST( "preserve" ) );
1339 	{
1340 		SvXMLElementExport	aSVG( *this, XML_NAMESPACE_NONE, "svg", sal_True, sal_True );
1341 
1342 		std::vector< ObjectRepresentation > aObjects;
1343 
1344 		aObjects.push_back( ObjectRepresentation( Reference< XInterface >(), rMtf ) );
1345 		SVGFontExport aSVGFontExport( *this, aObjects );
1346 
1347 		Point aPoint100thmm( OutputDevice::LogicToLogic( rMtf.GetPrefMapMode().GetOrigin(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
1348 		Size  aSize100thmm( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
1349 
1350 		SVGActionWriter		aWriter( *this, aSVGFontExport );
1351 		aWriter.WriteMetaFile( aPoint100thmm, aSize100thmm, rMtf,
1352 			SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT, NULL );
1353 	}
1354 }
1355