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