Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "svgwriter.hxx"
21 : #include "svgfontexport.hxx"
22 : #include "svgfilter.hxx"
23 : #include "svgscript.hxx"
24 : #include "impsvgdialog.hxx"
25 :
26 : #include <com/sun/star/drawing/GraphicExportFilter.hpp>
27 : #include <com/sun/star/text/textfield/Type.hpp>
28 : #include <com/sun/star/util/MeasureUnit.hpp>
29 : #include <com/sun/star/xml/sax/Writer.hpp>
30 :
31 : #include <rtl/bootstrap.hxx>
32 : #include <svtools/miscopt.hxx>
33 : #include <svx/unopage.hxx>
34 : #include <svx/unoshape.hxx>
35 : #include <svx/svdpage.hxx>
36 : #include <svx/svdoutl.hxx>
37 : #include <editeng/outliner.hxx>
38 : #include <editeng/flditem.hxx>
39 : #include <editeng/numitem.hxx>
40 : #include <comphelper/processfactory.hxx>
41 : #include <comphelper/sequenceashashmap.hxx>
42 : #include <i18nlangtag/lang.h>
43 : #include <svl/zforlist.hxx>
44 : #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
45 : #include <xmloff/animationexport.hxx>
46 :
47 : #include <boost/preprocessor/repetition/repeat.hpp>
48 :
49 : using namespace ::com::sun::star;
50 :
51 : // -------------------------------
52 : // - ooo elements and attributes -
53 : // -------------------------------
54 :
55 : #define NSPREFIX "ooo:"
56 :
57 : // ooo xml elements
58 : static const char aOOOElemMetaSlides[] = NSPREFIX "meta_slides";
59 : static const char aOOOElemMetaSlide[] = NSPREFIX "meta_slide";
60 : static const char aOOOElemTextField[] = NSPREFIX "text_field";
61 :
62 : // ooo xml attributes for meta_slides
63 : static const char aOOOAttrNumberOfSlides[] = NSPREFIX "number-of-slides";
64 : static const char aOOOAttrStartSlideNumber[] = NSPREFIX "start-slide-number";
65 : static const char aOOOAttrNumberingType[] = NSPREFIX "page-numbering-type";
66 :
67 : // ooo xml attributes for meta_slide
68 : static const char aOOOAttrSlide[] = NSPREFIX "slide";
69 : static const char aOOOAttrMaster[] = NSPREFIX "master";
70 : static const char aOOOAttrBackgroundVisibility[] = NSPREFIX "background-visibility";
71 : static const char aOOOAttrMasterObjectsVisibility[] = NSPREFIX "master-objects-visibility";
72 : static const char aOOOAttrPageNumberVisibility[] = NSPREFIX "page-number-visibility";
73 : static const char aOOOAttrDateTimeVisibility[] = NSPREFIX "date-time-visibility";
74 : static const char aOOOAttrFooterVisibility[] = NSPREFIX "footer-visibility";
75 0 : static const OUString aOOOAttrDateTimeField = NSPREFIX "date-time-field";
76 : static const char aOOOAttrFooterField[] = NSPREFIX "footer-field";
77 : static const char aOOOAttrHeaderField[] = NSPREFIX "header-field";
78 : static const char aOOOAttrHasTransition[] = NSPREFIX "has-transition";
79 : static const char aOOOAttrIdList[] = NSPREFIX "id-list";
80 :
81 : // ooo xml attributes for pages and shapes
82 : static const char aOOOAttrName[] = NSPREFIX "name";
83 :
84 : // ooo xml attributes for date_time_field
85 : static const char aOOOAttrDateTimeFormat[] = NSPREFIX "date-time-format";
86 :
87 : // ooo xml attributes for Placeholder Shapes
88 : static const char aOOOAttrTextAdjust[] = NSPREFIX "text-adjust";
89 :
90 :
91 :
92 : /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
93 : * - Text Field Class Hierarchy - *
94 : * *
95 : * This is a set of classes for exporting text field meta info. *
96 : * *
97 : * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
98 :
99 : #define TEXT_FIELD_GET_CLASS_NAME_METHOD( class_name ) \
100 : virtual OUString getClassName() const \
101 : { \
102 : static const char className[] = #class_name; \
103 : return OUString( className ); \
104 : }
105 :
106 :
107 0 : class TextField
108 : {
109 : protected:
110 : SVGFilter::ObjectSet mMasterPageSet;
111 : public:
112 :
113 0 : TEXT_FIELD_GET_CLASS_NAME_METHOD( TextField )
114 : virtual sal_Bool equalTo( const TextField & aTextField ) const = 0;
115 : virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const = 0;
116 0 : virtual void elementExport( SVGExport* pSVGExport ) const
117 : {
118 0 : pSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", getClassName() );
119 0 : }
120 0 : void insertMasterPage( Reference< XDrawPage> xMasterPage )
121 : {
122 0 : mMasterPageSet.insert( xMasterPage );
123 0 : }
124 0 : virtual ~TextField() {}
125 : protected:
126 0 : void implGrowCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets, OUString sText, OUString sTextFieldId ) const
127 : {
128 0 : const sal_Unicode * ustr = sText.getStr();
129 0 : sal_Int32 nLength = sText.getLength();
130 0 : SVGFilter::ObjectSet::const_iterator aMasterPageIt = mMasterPageSet.begin();
131 0 : for( ; aMasterPageIt != mMasterPageSet.end(); ++aMasterPageIt )
132 : {
133 0 : const Reference< XInterface > & xMasterPage = *aMasterPageIt;
134 0 : for( sal_Int32 i = 0; i < nLength; ++i )
135 : {
136 0 : aTextFieldCharSets[ xMasterPage ][ sTextFieldId ].insert( ustr[i] );
137 : }
138 : }
139 0 : }
140 : };
141 :
142 0 : class FixedTextField : public TextField
143 : {
144 : public:
145 : OUString text;
146 :
147 0 : TEXT_FIELD_GET_CLASS_NAME_METHOD( FixedTextField )
148 0 : virtual sal_Bool equalTo( const TextField & aTextField ) const
149 : {
150 0 : if( const FixedTextField* aFixedTextField = dynamic_cast< const FixedTextField* >( &aTextField ) )
151 : {
152 0 : return ( text == aFixedTextField->text );
153 : }
154 0 : return false;
155 : }
156 0 : virtual void elementExport( SVGExport* pSVGExport ) const
157 : {
158 0 : TextField::elementExport( pSVGExport );
159 0 : SvXMLElementExport aExp( *pSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
160 0 : pSVGExport->GetDocHandler()->characters( text );
161 0 : }
162 0 : virtual ~FixedTextField() {}
163 : };
164 :
165 0 : class FixedDateTimeField : public FixedTextField
166 : {
167 : public:
168 0 : FixedDateTimeField() {}
169 0 : TEXT_FIELD_GET_CLASS_NAME_METHOD( FixedDateTimeField )
170 0 : virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const
171 : {
172 0 : implGrowCharSet( aTextFieldCharSets, text, aOOOAttrDateTimeField );
173 0 : }
174 0 : virtual ~FixedDateTimeField() {}
175 : };
176 :
177 0 : class FooterField : public FixedTextField
178 : {
179 : public:
180 0 : FooterField() {}
181 0 : TEXT_FIELD_GET_CLASS_NAME_METHOD( FooterField )
182 0 : virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const
183 : {
184 0 : static const OUString sFieldId = aOOOAttrFooterField;
185 0 : implGrowCharSet( aTextFieldCharSets, text, sFieldId );
186 0 : }
187 0 : virtual ~FooterField() {}
188 : };
189 :
190 : class HeaderField : public FixedTextField
191 : {
192 : public:
193 : HeaderField() {}
194 : TEXT_FIELD_GET_CLASS_NAME_METHOD( HeaderField )
195 : virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const
196 : {
197 : static const OUString sFieldId = aOOOAttrHeaderField;
198 : implGrowCharSet( aTextFieldCharSets, text, sFieldId );
199 : }
200 : virtual ~HeaderField() {}
201 : };
202 :
203 0 : class VariableTextField : public TextField
204 : {
205 : public:
206 0 : TEXT_FIELD_GET_CLASS_NAME_METHOD( VariableTextField )
207 0 : virtual ~VariableTextField() {}
208 : };
209 :
210 0 : class VariableDateTimeField : public VariableTextField
211 : {
212 : public:
213 : sal_Int32 format;
214 :
215 0 : VariableDateTimeField() {}
216 0 : TEXT_FIELD_GET_CLASS_NAME_METHOD( VariableDateTimeField )
217 0 : virtual sal_Bool equalTo( const TextField & aTextField ) const
218 : {
219 0 : if( const VariableDateTimeField* aField = dynamic_cast< const VariableDateTimeField* >( &aTextField ) )
220 : {
221 0 : return ( format == aField->format );
222 : }
223 0 : return false;
224 : }
225 0 : virtual void elementExport( SVGExport* pSVGExport ) const
226 : {
227 0 : VariableTextField::elementExport( pSVGExport );
228 0 : OUString sDateFormat, sTimeFormat;
229 0 : SvxDateFormat eDateFormat = (SvxDateFormat)( format & 0x0f );
230 0 : if( eDateFormat )
231 : {
232 0 : switch( eDateFormat )
233 : {
234 : case SVXDATEFORMAT_STDSMALL: ;
235 : case SVXDATEFORMAT_A: // 13.02.96
236 0 : sDateFormat = "";
237 0 : break;
238 : case SVXDATEFORMAT_C: // 13.Feb 1996
239 0 : sDateFormat = "";
240 0 : break;
241 : case SVXDATEFORMAT_D: // 13.February 1996
242 0 : sDateFormat = "";
243 0 : break;
244 : case SVXDATEFORMAT_E: // Tue, 13.February 1996
245 0 : sDateFormat = "";
246 0 : break;
247 : case SVXDATEFORMAT_STDBIG: ;
248 : case SVXDATEFORMAT_F: // Tuesday, 13.February 1996
249 0 : sDateFormat = "";
250 0 : break;
251 : // default case
252 : case SVXDATEFORMAT_B: ; // 13.02.1996
253 : default:
254 0 : sDateFormat = "";
255 0 : break;
256 : }
257 : }
258 :
259 0 : SvxTimeFormat eTimeFormat = (SvxTimeFormat)( ( format >> 4 ) & 0x0f );
260 0 : if( eTimeFormat )
261 : {
262 0 : switch( eTimeFormat )
263 : {
264 : case SVXTIMEFORMAT_24_HMS: // 13:49:38
265 0 : sTimeFormat = "";
266 0 : break;
267 : case SVXTIMEFORMAT_AM_HM: ; // 01:49 PM
268 : case SVXTIMEFORMAT_12_HM:
269 0 : sTimeFormat = "";
270 0 : break;
271 : case SVXTIMEFORMAT_AM_HMS: ; // 01:49:38 PM
272 : case SVXTIMEFORMAT_12_HMS:
273 0 : sTimeFormat = "";
274 0 : break;
275 : // default case
276 : case SVXTIMEFORMAT_24_HM: ; // 13:49
277 : default:
278 0 : sTimeFormat = "";
279 0 : break;
280 : }
281 : }
282 :
283 0 : OUString sDateTimeFormat = sDateFormat + " " + sTimeFormat;
284 :
285 0 : pSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeFormat, sDateTimeFormat );
286 0 : SvXMLElementExport aExp( *pSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
287 0 : }
288 0 : virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const
289 : {
290 : // we use the unicode char set in an improper way: we put in the date/time fortat
291 : // in order to pass it to the CalcFieldValue method
292 0 : static const OUString sFieldId = aOOOAttrDateTimeField + "-variable";
293 0 : SVGFilter::ObjectSet::const_iterator aMasterPageIt = mMasterPageSet.begin();
294 0 : for( ; aMasterPageIt != mMasterPageSet.end(); ++aMasterPageIt )
295 : {
296 0 : aTextFieldCharSets[ *aMasterPageIt ][ sFieldId ].insert( (sal_Unicode)( format ) );
297 : }
298 0 : }
299 0 : virtual ~VariableDateTimeField() {}
300 : };
301 :
302 0 : sal_Bool operator==( const TextField & aLhsTextField, const TextField & aRhsTextField )
303 : {
304 0 : return aLhsTextField.equalTo( aRhsTextField );
305 : }
306 :
307 :
308 :
309 : // -------------
310 : // - SVGExport -
311 : // -------------
312 :
313 0 : SVGExport::SVGExport(
314 : const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext,
315 : const Reference< XDocumentHandler >& rxHandler,
316 : const Sequence< PropertyValue >& rFilterData )
317 : : SvXMLExport( util::MeasureUnit::MM_100TH,
318 : xContext,
319 : xmloff::token::XML_TOKEN_INVALID,
320 0 : EXPORT_META|EXPORT_PRETTY )
321 : {
322 0 : SetDocHandler( rxHandler );
323 0 : GetDocHandler()->startDocument();
324 :
325 : // initializing filter settings from filter data
326 0 : comphelper::SequenceAsHashMap aFilterDataHashMap = rFilterData;
327 :
328 : // TinyProfile
329 0 : mbIsUseTinyProfile = aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_TINYPROFILE, sal_True);
330 :
331 : // Font Embedding
332 0 : comphelper::SequenceAsHashMap::const_iterator iter = aFilterDataHashMap.find(SVG_PROP_EMBEDFONTS);
333 0 : if(iter==aFilterDataHashMap.end())
334 : {
335 0 : const char* pSVGDisableFontEmbedding = getenv( "SVG_DISABLE_FONT_EMBEDDING" );
336 0 : OUString aEmbedFontEnv("${SVG_DISABLE_FONT_EMBEDDING}");
337 0 : rtl::Bootstrap::expandMacros(aEmbedFontEnv);
338 : mbIsEmbedFonts=pSVGDisableFontEmbedding ? sal_False : (
339 0 : aEmbedFontEnv.getLength() ? sal_False : sal_True);
340 : }
341 : else
342 : {
343 0 : if(!(iter->second >>= mbIsEmbedFonts))
344 0 : mbIsEmbedFonts = sal_False;
345 : }
346 :
347 : // Native Decoration
348 0 : mbIsUseNativeTextDecoration = mbIsUseTinyProfile ? sal_False : aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_NATIVEDECORATION, sal_False);
349 :
350 : // Tiny Opacity
351 0 : mbIsUseOpacity = mbIsUseTinyProfile ? sal_False : aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_OPACITY, sal_True);
352 :
353 : // Positioned Characters (Seems to be experimental, as it was always initialized with false)
354 0 : mbIsUsePositionedCharacters = aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_POSITIONED_CHARACTERS, sal_False);
355 :
356 0 : }
357 :
358 : // -----------------------------------------------------------------------------
359 :
360 0 : SVGExport::~SVGExport()
361 : {
362 0 : GetDocHandler()->endDocument();
363 0 : }
364 :
365 :
366 : // ------------------------
367 : // - ObjectRepresentation -
368 : // ------------------------
369 :
370 0 : ObjectRepresentation::ObjectRepresentation() :
371 0 : mpMtf( NULL )
372 : {
373 0 : }
374 :
375 : // -----------------------------------------------------------------------------
376 :
377 0 : ObjectRepresentation::ObjectRepresentation( const Reference< XInterface >& rxObject,
378 : const GDIMetaFile& rMtf ) :
379 : mxObject( rxObject ),
380 0 : mpMtf( new GDIMetaFile( rMtf ) )
381 : {
382 0 : }
383 :
384 : // -----------------------------------------------------------------------------
385 :
386 0 : ObjectRepresentation::ObjectRepresentation( const ObjectRepresentation& rPresentation ) :
387 : mxObject( rPresentation.mxObject ),
388 0 : mpMtf( rPresentation.mpMtf ? new GDIMetaFile( *rPresentation.mpMtf ) : NULL )
389 : {
390 0 : }
391 :
392 : // -----------------------------------------------------------------------------
393 :
394 0 : ObjectRepresentation::~ObjectRepresentation()
395 : {
396 0 : delete mpMtf;
397 0 : }
398 :
399 : // -----------------------------------------------------------------------------
400 :
401 0 : ObjectRepresentation& ObjectRepresentation::operator=( const ObjectRepresentation& rPresentation )
402 : {
403 : // Check for self-assignment
404 0 : if (this == &rPresentation)
405 0 : return *this;
406 0 : mxObject = rPresentation.mxObject;
407 0 : delete mpMtf, ( mpMtf = rPresentation.mpMtf ? new GDIMetaFile( *rPresentation.mpMtf ) : NULL );
408 :
409 0 : return *this;
410 : }
411 :
412 : // -----------------------------------------------------------------------------
413 :
414 0 : sal_Bool ObjectRepresentation::operator==( const ObjectRepresentation& rPresentation ) const
415 : {
416 0 : return( ( mxObject == rPresentation.mxObject ) &&
417 0 : ( *mpMtf == *rPresentation.mpMtf ) );
418 : }
419 :
420 : // -----------------------------------------------------------------------------
421 :
422 0 : sal_uLong GetBitmapChecksum( const MetaAction* pAction )
423 : {
424 0 : sal_uLong nChecksum = 0;
425 0 : const sal_uInt16 nType = pAction->GetType();
426 :
427 0 : switch( nType )
428 : {
429 : case( META_BMPSCALE_ACTION ):
430 : {
431 0 : const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
432 0 : if( pA )
433 0 : nChecksum = pA->GetBitmap().GetChecksum();
434 : else
435 : OSL_FAIL( "GetBitmapChecksum: MetaBmpScaleAction pointer is null." );
436 : }
437 0 : break;
438 : case( META_BMPEXSCALE_ACTION ):
439 : {
440 0 : const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
441 0 : if( pA )
442 0 : nChecksum = pA->GetBitmapEx().GetChecksum();
443 : else
444 : OSL_FAIL( "GetBitmapChecksum: MetaBmpExScaleAction pointer is null." );
445 : }
446 0 : break;
447 : }
448 0 : return nChecksum;
449 : }
450 : // -----------------------------------------------------------------------------
451 :
452 0 : void MetaBitmapActionGetPoint( const MetaAction* pAction, Point& rPt )
453 : {
454 0 : const sal_uInt16 nType = pAction->GetType();
455 0 : switch( nType )
456 : {
457 : case( META_BMPSCALE_ACTION ):
458 : {
459 0 : const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
460 0 : if( pA )
461 0 : rPt = pA->GetPoint();
462 : else
463 : OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpScaleAction pointer is null." );
464 : }
465 0 : break;
466 : case( META_BMPEXSCALE_ACTION ):
467 : {
468 0 : const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
469 0 : if( pA )
470 0 : rPt = pA->GetPoint();
471 : else
472 : OSL_FAIL( "MetaBitmapActionGetPoint: MetaBmpExScaleAction pointer is null." );
473 : }
474 0 : break;
475 : }
476 :
477 0 : }
478 :
479 : // -----------------------------------------------------------------------------
480 :
481 0 : size_t HashBitmap::operator()( const ObjectRepresentation& rObjRep ) const
482 : {
483 0 : const GDIMetaFile& aMtf = rObjRep.GetRepresentation();
484 0 : if( aMtf.GetActionSize() == 1 )
485 : {
486 0 : return static_cast< size_t >( GetBitmapChecksum( aMtf.GetAction( 0 ) ) );
487 : }
488 : else
489 : {
490 : OSL_FAIL( "HashBitmap: metafile should have a single action." );
491 0 : return 0;
492 : }
493 : }
494 :
495 : // -----------------------------------------------------------------------------
496 :
497 0 : bool EqualityBitmap::operator()( const ObjectRepresentation& rObjRep1,
498 : const ObjectRepresentation& rObjRep2 ) const
499 : {
500 0 : const GDIMetaFile& aMtf1 = rObjRep1.GetRepresentation();
501 0 : const GDIMetaFile& aMtf2 = rObjRep2.GetRepresentation();
502 0 : if( aMtf1.GetActionSize() == 1 && aMtf2.GetActionSize() == 1 )
503 : {
504 0 : sal_uLong nChecksum1 = GetBitmapChecksum( aMtf1.GetAction( 0 ) );
505 0 : sal_uLong nChecksum2 = GetBitmapChecksum( aMtf2.GetAction( 0 ) );
506 0 : return ( nChecksum1 == nChecksum2 );
507 : }
508 : else
509 : {
510 : OSL_FAIL( "EqualityBitmap: metafile should have a single action." );
511 0 : return false;
512 : }
513 : }
514 :
515 :
516 : // -------------
517 : // - SVGFilter -
518 : // -------------
519 :
520 0 : sal_Bool SVGFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
521 : throw (RuntimeException)
522 : {
523 0 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ) ;
524 0 : Reference< XOutputStream > xOStm;
525 0 : SvStream* pOStm = NULL;
526 0 : sal_Int32 nLength = rDescriptor.getLength();
527 0 : const PropertyValue* pValue = rDescriptor.getConstArray();
528 0 : sal_Bool bRet = sal_False;
529 :
530 0 : maFilterData.realloc( 0 );
531 :
532 0 : for ( sal_Int32 i = 0 ; i < nLength; ++i)
533 : {
534 0 : if ( pValue[ i ].Name == "OutputStream" )
535 0 : pValue[ i ].Value >>= xOStm;
536 0 : else if ( pValue[ i ].Name == "FileName" )
537 : {
538 0 : OUString aFileName;
539 :
540 0 : pValue[ i ].Value >>= aFileName;
541 0 : pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, STREAM_WRITE | STREAM_TRUNC );
542 :
543 0 : if( pOStm )
544 0 : xOStm = Reference< XOutputStream >( new ::utl::OOutputStreamWrapper ( *pOStm ) );
545 : }
546 0 : else if ( pValue[ i ].Name == "FilterData" )
547 : {
548 0 : pValue[ i ].Value >>= maFilterData;
549 : }
550 : }
551 :
552 0 : if( xOStm.is() )
553 : {
554 0 : if( mSelectedPages.hasElements() && mMasterPageTargets.hasElements() )
555 : {
556 0 : Reference< XDocumentHandler > xDocHandler( implCreateExportDocumentHandler( xOStm ), UNO_QUERY );
557 :
558 0 : if( xDocHandler.is() )
559 : {
560 0 : mbPresentation = Reference< XPresentationSupplier >( mxSrcDoc, UNO_QUERY ).is();
561 0 : mpObjects = new ObjectMap;
562 :
563 : // #110680#
564 : // mpSVGExport = new SVGExport( xDocHandler );
565 0 : mpSVGExport = new SVGExport( xContext, xDocHandler, maFilterData );
566 :
567 0 : if( mpSVGExport != NULL )
568 : {
569 : // xSVGExport is set up only to manage the life-time of the object pointed by mpSVGExport,
570 : // and in order to prevent that it is destroyed when passed to AnimationExporter.
571 0 : Reference< XInterface > xSVGExport = static_cast< ::com::sun::star::document::XFilter* >( mpSVGExport );
572 :
573 : // create an id for each draw page
574 0 : for( sal_Int32 i = 0; i < mSelectedPages.getLength(); ++i )
575 0 : implRegisterInterface( mSelectedPages[i] );
576 :
577 : // create an id for each master page
578 0 : for( sal_Int32 i = 0; i < mMasterPageTargets.getLength(); ++i )
579 0 : implRegisterInterface( mMasterPageTargets[i] );
580 :
581 : try
582 : {
583 0 : mxDefaultPage = mSelectedPages[0];
584 :
585 0 : if( mxDefaultPage.is() )
586 : {
587 0 : SvxDrawPage* pSvxDrawPage = SvxDrawPage::getImplementation( mxDefaultPage );
588 :
589 0 : if( pSvxDrawPage )
590 : {
591 0 : mpDefaultSdrPage = pSvxDrawPage->GetSdrPage();
592 0 : mpSdrModel = mpDefaultSdrPage->GetModel();
593 :
594 0 : if( mpSdrModel )
595 : {
596 0 : SdrOutliner& rOutl = mpSdrModel->GetDrawOutliner(NULL);
597 :
598 0 : maOldFieldHdl = rOutl.GetCalcFieldValueHdl();
599 0 : rOutl.SetCalcFieldValueHdl( LINK( this, SVGFilter, CalcFieldHdl) );
600 : }
601 : }
602 0 : bRet = implExportDocument();
603 : }
604 : }
605 0 : catch( ... )
606 : {
607 0 : delete mpSVGDoc, mpSVGDoc = NULL;
608 : OSL_FAIL( "Exception caught" );
609 : }
610 :
611 0 : if( mpSdrModel )
612 0 : mpSdrModel->GetDrawOutliner( NULL ).SetCalcFieldValueHdl( maOldFieldHdl );
613 :
614 0 : delete mpSVGWriter, mpSVGWriter = NULL;
615 0 : mpSVGExport = NULL; // pointed object is released by xSVGExport dtor at the end of this scope
616 0 : delete mpSVGFontExport, mpSVGFontExport = NULL;
617 0 : delete mpObjects, mpObjects = NULL;
618 0 : mbPresentation = sal_False;
619 : }
620 0 : }
621 : }
622 : }
623 :
624 0 : delete pOStm;
625 :
626 0 : return bRet;
627 : }
628 :
629 : // -----------------------------------------------------------------------------
630 :
631 0 : Reference< XWriter > SVGFilter::implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm )
632 : {
633 0 : Reference< XWriter > xSaxWriter;
634 :
635 0 : if( rxOStm.is() )
636 : {
637 0 : xSaxWriter = Writer::create( ::comphelper::getProcessComponentContext() );
638 0 : xSaxWriter->setOutputStream( rxOStm );
639 : }
640 :
641 0 : return xSaxWriter;
642 : }
643 :
644 : // -----------------------------------------------------------------------------
645 :
646 0 : sal_Bool SVGFilter::implLookForFirstVisiblePage()
647 : {
648 0 : sal_Int32 nCurPage = 0, nLastPage = mSelectedPages.getLength() - 1;
649 :
650 0 : while( ( nCurPage <= nLastPage ) && ( -1 == mnVisiblePage ) )
651 : {
652 0 : const Reference< XDrawPage > & xDrawPage = mSelectedPages[nCurPage];
653 :
654 0 : if( xDrawPage.is() )
655 : {
656 0 : Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
657 :
658 0 : if( xPropSet.is() )
659 : {
660 0 : sal_Bool bVisible = sal_False;
661 :
662 0 : if( !mbPresentation || mbSinglePage ||
663 0 : ( ( xPropSet->getPropertyValue( "Visible" ) >>= bVisible ) && bVisible ) )
664 : {
665 0 : mnVisiblePage = nCurPage;
666 : }
667 0 : }
668 : }
669 0 : ++nCurPage;
670 : }
671 :
672 0 : return ( mnVisiblePage != -1 );
673 : }
674 :
675 : // -----------------------------------------------------------------------------
676 0 : sal_Bool SVGFilter::implExportDocument()
677 : {
678 0 : OUString aAttr;
679 0 : sal_Int32 nDocWidth = 0, nDocHeight = 0;
680 0 : sal_Bool bRet = sal_False;
681 0 : sal_Int32 nLastPage = mSelectedPages.getLength() - 1;
682 :
683 0 : SvtMiscOptions aMiscOptions;
684 0 : const bool bExperimentalMode = aMiscOptions.IsExperimentalMode();
685 :
686 0 : mbSinglePage = (nLastPage == 0) || !bExperimentalMode;
687 0 : mnVisiblePage = -1;
688 :
689 0 : const Reference< XPropertySet > xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY );
690 0 : const Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
691 :
692 0 : if( xDefaultPagePropertySet.is() )
693 : {
694 0 : xDefaultPagePropertySet->getPropertyValue( "Width" ) >>= nDocWidth;
695 0 : xDefaultPagePropertySet->getPropertyValue( "Height" ) >>= nDocHeight;
696 : }
697 :
698 0 : if( xExtDocHandler.is() && !mpSVGExport->IsUseTinyProfile() )
699 : {
700 0 : xExtDocHandler->unknown( SVG_DTD_STRING );
701 : }
702 :
703 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "version", "1.2" );
704 :
705 0 : if( mpSVGExport->IsUseTinyProfile() )
706 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "baseProfile", "tiny" );
707 :
708 : // enabling _SVG_WRITE_EXTENTS means that the slide size is not adapted
709 : // to the size of the browser window, moreover the slide is top left aligned
710 : // instead of centered.
711 : #define _SVG_WRITE_EXTENTS
712 : #ifdef _SVG_WRITE_EXTENTS
713 0 : if( mbSinglePage )
714 : {
715 0 : aAttr = OUString::valueOf( nDocWidth * 0.01 ) + "mm";
716 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
717 :
718 0 : aAttr = OUString::valueOf( nDocHeight * 0.01 ) + "mm";
719 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
720 : }
721 : #endif
722 :
723 :
724 0 : aAttr = "0 0 " + OUString::valueOf( nDocWidth ) + " " + OUString::valueOf( nDocHeight );
725 :
726 0 : msClipPathId = "presentation_clip_path";
727 0 : OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
728 :
729 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
730 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", "xMidYMid" );
731 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", "evenodd" );
732 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
733 :
734 : // standard line width is based on 1 pixel on a 90 DPI device (0.28222mmm)
735 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::valueOf( 28.222 ) );
736 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", "round" );
737 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns", "http://www.w3.org/2000/svg" );
738 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:ooo", "http://xml.openoffice.org/svg/export" );
739 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:xlink", "http://www.w3.org/1999/xlink" );
740 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xml:space", "preserve" );
741 :
742 0 : mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", sal_True, sal_True );
743 :
744 : // Create a ClipPath element that will be used for cutting bitmaps and other elements that could exceed the page margins.
745 : {
746 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "ClipPathGroup" );
747 0 : SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
748 : {
749 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", msClipPathId );
750 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clipPathUnits", "userSpaceOnUse" );
751 0 : SvXMLElementExport aClipPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "clipPath", sal_True, sal_True );
752 : {
753 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::valueOf( sal_Int32(0) ) );
754 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::valueOf( sal_Int32(0) ) );
755 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::valueOf( nDocWidth ) );
756 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::valueOf( nDocHeight ) );
757 0 : SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", sal_True, sal_True );
758 0 : }
759 0 : }
760 : }
761 :
762 0 : if( implLookForFirstVisiblePage() ) // OK! We found at least one visible page.
763 : {
764 0 : if( !mbSinglePage )
765 : {
766 0 : implGenerateMetaData();
767 0 : if( bExperimentalMode )
768 0 : implExportAnimations();
769 : }
770 : else
771 : {
772 0 : implGetPagePropSet( mSelectedPages[0] );
773 : }
774 :
775 : // Create the (Shape, GDIMetaFile) map
776 0 : if( implCreateObjects() )
777 : {
778 0 : ObjectMap::const_iterator aIter( mpObjects->begin() );
779 0 : ::std::vector< ObjectRepresentation > aObjects( mpObjects->size() );
780 0 : sal_uInt32 nPos = 0;
781 :
782 0 : while( aIter != mpObjects->end() )
783 : {
784 0 : aObjects[ nPos++ ] = (*aIter).second;
785 0 : ++aIter;
786 : }
787 :
788 0 : mpSVGFontExport = new SVGFontExport( *mpSVGExport, aObjects );
789 0 : mpSVGWriter = new SVGActionWriter( *mpSVGExport, *mpSVGFontExport );
790 :
791 0 : if( mpSVGExport->IsEmbedFonts() )
792 : {
793 0 : mpSVGFontExport->EmbedFonts();
794 : }
795 0 : if( !mpSVGExport->IsUsePositionedCharacters() )
796 : {
797 0 : implExportTextShapeIndex();
798 0 : implEmbedBulletGlyphs();
799 0 : implExportTextEmbeddedBitmaps();
800 : }
801 0 : implExportMasterPages( mMasterPageTargets, 0, mMasterPageTargets.getLength() - 1 );
802 0 : implExportDrawPages( mSelectedPages, 0, nLastPage );
803 :
804 0 : if( !mbSinglePage )
805 : {
806 0 : implGenerateScript();
807 : }
808 :
809 0 : delete mpSVGDoc, mpSVGDoc = NULL;
810 0 : bRet = sal_True;
811 : }
812 : }
813 :
814 0 : return bRet;
815 : }
816 :
817 :
818 : //------------------------------------------------------------------------------
819 : // Append aField to aFieldSet if it is not already present in the set
820 : // and create the field id sFieldId
821 : //
822 :
823 : template< typename TextFieldType >
824 0 : OUString implGenerateFieldId( std::vector< TextField* > & aFieldSet,
825 : const TextFieldType & aField,
826 : const OUString & sOOOElemField,
827 : Reference< XDrawPage > xMasterPage )
828 : {
829 0 : sal_Bool bFound = sal_False;
830 : sal_Int32 i;
831 0 : sal_Int32 nSize = aFieldSet.size();
832 0 : for( i = 0; i < nSize; ++i )
833 : {
834 0 : if( *(aFieldSet[i]) == aField )
835 : {
836 0 : bFound = sal_True;
837 0 : break;
838 : }
839 : }
840 0 : OUString sFieldId( sOOOElemField );
841 0 : sFieldId += OUString::valueOf( sal_Unicode('_') );
842 0 : if( !bFound )
843 : {
844 0 : aFieldSet.push_back( new TextFieldType( aField ) );
845 : }
846 0 : aFieldSet[i]->insertMasterPage( xMasterPage );
847 0 : sFieldId += OUString::valueOf( i );
848 0 : return sFieldId;
849 : }
850 :
851 : //------------------------------------------------------------------------------
852 :
853 0 : sal_Bool SVGFilter::implGenerateMetaData()
854 : {
855 0 : sal_Bool bRet = sal_False;
856 0 : sal_Int32 nCount = mSelectedPages.getLength();
857 0 : if( nCount != 0 )
858 : {
859 : // we wrap all meta presentation info into a svg:defs element
860 0 : SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
861 :
862 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aOOOElemMetaSlides );
863 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrNumberOfSlides, OUString::valueOf( nCount ) );
864 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrStartSlideNumber, OUString::valueOf( mnVisiblePage ) );
865 :
866 : /*
867 : * Add a (global) Page Numbering Type attribute for the document
868 : */
869 : // NOTE:
870 : // at present pSdrModel->GetPageNumType() returns always SVX_ARABIC
871 : // so the following code fragment is pretty unuseful
872 0 : sal_Int32 nPageNumberingType = SVX_ARABIC;
873 0 : SvxDrawPage* pSvxDrawPage = SvxDrawPage::getImplementation( mSelectedPages[0] );
874 0 : if( pSvxDrawPage )
875 : {
876 0 : SdrPage* pSdrPage = pSvxDrawPage->GetSdrPage();
877 0 : SdrModel* pSdrModel = pSdrPage->GetModel();
878 0 : nPageNumberingType = pSdrModel->GetPageNumType();
879 :
880 : // That is used by CalcFieldHdl method.
881 0 : mVisiblePagePropSet.nPageNumberingType = nPageNumberingType;
882 : }
883 0 : if( nPageNumberingType != SVX_NUMBER_NONE )
884 : {
885 0 : OUString sNumberingType;
886 0 : switch( nPageNumberingType )
887 : {
888 : case SVX_CHARS_UPPER_LETTER:
889 0 : sNumberingType = "alpha-upper";
890 0 : break;
891 : case SVX_CHARS_LOWER_LETTER:
892 0 : sNumberingType = "alpha-lower";
893 0 : break;
894 : case SVX_ROMAN_UPPER:
895 0 : sNumberingType = "roman-upper";
896 0 : break;
897 : case SVX_ROMAN_LOWER:
898 0 : sNumberingType = "roman-lower";
899 0 : break;
900 : // arabic numbering type is the default, so we do not append any attribute for it
901 : case SVX_ARABIC: ;
902 : // in case the numbering type is not handled we fall back on arabic numbering
903 : default: ;
904 0 : break;
905 : }
906 0 : if( !sNumberingType.isEmpty() )
907 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrNumberingType, sNumberingType );
908 : }
909 :
910 :
911 : {
912 0 : SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
913 0 : const OUString aId( aOOOElemMetaSlide );
914 0 : const OUString aElemTextFieldId( aOOOElemTextField );
915 0 : std::vector< TextField* > aFieldSet;
916 :
917 0 : for( sal_Int32 i = 0; i < nCount; ++i )
918 : {
919 0 : const Reference< XDrawPage > & xDrawPage = mSelectedPages[i];
920 0 : Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
921 0 : Reference< XDrawPage > xMasterPage( xMasterPageTarget->getMasterPage(), UNO_QUERY );
922 0 : OUString aSlideId( aId );
923 0 : aSlideId += OUString::valueOf( sal_Unicode('_') );
924 0 : aSlideId += OUString::valueOf( i );
925 :
926 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aSlideId );
927 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, implGetValidIDFromInterface( xDrawPage ) );
928 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMaster, implGetValidIDFromInterface( xMasterPage ) );
929 :
930 :
931 0 : if( mbPresentation )
932 : {
933 0 : Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
934 :
935 0 : if( xPropSet.is() )
936 : {
937 0 : sal_Bool bBackgroundVisibility = sal_True; // default: visible
938 0 : sal_Bool bBackgroundObjectsVisibility = sal_True; // default: visible
939 0 : sal_Bool bPageNumberVisibility = sal_False; // default: hidden
940 0 : sal_Bool bDateTimeVisibility = sal_True; // default: visible
941 0 : sal_Bool bFooterVisibility = sal_True; // default: visible
942 0 : sal_Bool bDateTimeFixed = sal_True; // default: fixed
943 :
944 0 : FixedDateTimeField aFixedDateTimeField;
945 0 : VariableDateTimeField aVariableDateTimeField;
946 0 : FooterField aFooterField;
947 :
948 0 : xPropSet->getPropertyValue( "IsBackgroundVisible" ) >>= bBackgroundVisibility;
949 : // in case the attribute is set to its default value it is not appended to the meta-slide element
950 0 : if( !bBackgroundVisibility ) // visibility default value: 'visible'
951 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" );
952 :
953 : // Page Number, Date/Time, Footer and Header Fields are regarded as background objects.
954 : // So bBackgroundObjectsVisibility overrides visibility of master page text fields.
955 0 : xPropSet->getPropertyValue( "IsBackgroundObjectsVisible" ) >>= bBackgroundObjectsVisibility;
956 0 : if( bBackgroundObjectsVisibility ) // visibility default value: 'visible'
957 : {
958 : /*
959 : * Page Number Field
960 : */
961 0 : xPropSet->getPropertyValue( "IsPageNumberVisible" ) >>= bPageNumberVisibility;
962 0 : bPageNumberVisibility = bPageNumberVisibility && ( nPageNumberingType != SVX_NUMBER_NONE );
963 0 : if( bPageNumberVisibility ) // visibility default value: 'hidden'
964 : {
965 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrPageNumberVisibility, "visible" );
966 : }
967 : /*
968 : * Date/Time Field
969 : */
970 0 : xPropSet->getPropertyValue( "IsDateTimeVisible" ) >>= bDateTimeVisibility;
971 0 : if( bDateTimeVisibility ) // visibility default value: 'visible'
972 : {
973 0 : xPropSet->getPropertyValue( "IsDateTimeFixed" ) >>= bDateTimeFixed;
974 0 : if( bDateTimeFixed ) // we are interested only in the field text not in the date/time format
975 : {
976 0 : xPropSet->getPropertyValue( "DateTimeText" ) >>= aFixedDateTimeField.text;
977 0 : if( !aFixedDateTimeField.text.isEmpty() )
978 : {
979 0 : OUString sFieldId = implGenerateFieldId( aFieldSet, aFixedDateTimeField, aElemTextFieldId, xMasterPage );
980 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
981 : }
982 : }
983 : else // the inverse applies: we are interested only in the date/time format not in the field text
984 : {
985 0 : xPropSet->getPropertyValue( "DateTimeFormat" ) >>= aVariableDateTimeField.format;
986 0 : OUString sFieldId = implGenerateFieldId( aFieldSet, aVariableDateTimeField, aElemTextFieldId, xMasterPage );
987 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
988 : }
989 : }
990 : else
991 : {
992 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeVisibility, "hidden" );
993 : }
994 : /*
995 : * Footer Field
996 : */
997 0 : xPropSet->getPropertyValue( "IsFooterVisible" ) >>= bFooterVisibility;
998 0 : if( bFooterVisibility ) // visibility default value: 'visible'
999 : {
1000 0 : xPropSet->getPropertyValue( "FooterText" ) >>= aFooterField.text;
1001 0 : if( !aFooterField.text.isEmpty() )
1002 : {
1003 0 : OUString sFieldId = implGenerateFieldId( aFieldSet, aFooterField, aElemTextFieldId, xMasterPage );
1004 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrFooterField, sFieldId );
1005 : }
1006 : }
1007 : else
1008 : {
1009 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrFooterVisibility, "hidden" );
1010 : }
1011 : }
1012 : else
1013 : {
1014 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMasterObjectsVisibility, "hidden" );
1015 : }
1016 :
1017 : // We look for a slide transition.
1018 : // Transition properties are exported together with animations.
1019 0 : sal_Int16 nTransitionType(0);
1020 0 : if( xPropSet->getPropertySetInfo()->hasPropertyByName( "TransitionType" ) &&
1021 0 : (xPropSet->getPropertyValue( "TransitionType" ) >>= nTransitionType) )
1022 : {
1023 0 : sal_Int16 nTransitionSubType(0);
1024 0 : if( xPropSet->getPropertyValue( "TransitionSubtype" ) >>= nTransitionSubType )
1025 : {
1026 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrHasTransition, "true" );
1027 : }
1028 0 : }
1029 :
1030 0 : }
1031 : }
1032 :
1033 : {
1034 0 : SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1035 : } // when the aExp2 destructor is called the </g> tag is appended to the output file
1036 0 : }
1037 :
1038 : // export text field elements
1039 0 : if( mbPresentation )
1040 : {
1041 0 : for( sal_Int32 i = 0, nSize = aFieldSet.size(); i < nSize; ++i )
1042 : {
1043 0 : OUString sElemId = OUString(aOOOElemTextField) + "_" + OUString::number( i );
1044 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sElemId );
1045 0 : aFieldSet[i]->elementExport( mpSVGExport );
1046 0 : }
1047 0 : if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
1048 : {
1049 0 : for( sal_Int32 i = 0, nSize = aFieldSet.size(); i < nSize; ++i )
1050 : {
1051 0 : aFieldSet[i]->growCharSet( mTextFieldCharSets );
1052 : }
1053 : }
1054 : }
1055 : // text fields are used only for generating meta info so we don't need them anymore
1056 0 : for( sal_uInt32 i = 0; i < aFieldSet.size(); ++i )
1057 : {
1058 0 : if( aFieldSet[i] != NULL )
1059 : {
1060 0 : delete aFieldSet[i];
1061 : }
1062 0 : }
1063 : }
1064 0 : bRet = sal_True;
1065 : }
1066 :
1067 0 : return bRet;
1068 : }
1069 :
1070 : // -----------------------------------------------------------------------------
1071 :
1072 0 : sal_Bool SVGFilter::implExportAnimations()
1073 : {
1074 0 : sal_Bool bRet = sal_False;
1075 :
1076 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "presentation-animations" );
1077 0 : SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
1078 :
1079 0 : for( sal_Int32 i = 0; i < mSelectedPages.getLength(); ++i )
1080 : {
1081 0 : Reference< XPropertySet > xProps( mSelectedPages[i], UNO_QUERY );
1082 :
1083 0 : if( xProps.is() && xProps->getPropertySetInfo()->hasPropertyByName( "TransitionType" ) )
1084 : {
1085 0 : sal_Int16 nTransition = 0;
1086 0 : xProps->getPropertyValue( "TransitionType" ) >>= nTransition;
1087 : // we have a slide transition ?
1088 0 : sal_Bool bHasEffects = ( nTransition != 0 );
1089 :
1090 0 : Reference< XAnimationNodeSupplier > xAnimNodeSupplier( mSelectedPages[i], UNO_QUERY );
1091 0 : if( xAnimNodeSupplier.is() )
1092 : {
1093 0 : Reference< XAnimationNode > xRootNode = xAnimNodeSupplier->getAnimationNode();
1094 0 : if( xRootNode.is() )
1095 : {
1096 0 : if( !bHasEffects )
1097 : {
1098 : // first check if there are no animations
1099 0 : Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
1100 0 : Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1101 0 : if( xEnumeration->hasMoreElements() )
1102 : {
1103 : // first child node may be an empty main sequence, check this
1104 0 : Reference< XAnimationNode > xMainNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
1105 0 : Reference< XEnumerationAccess > xMainEnumerationAccess( xMainNode, UNO_QUERY_THROW );
1106 0 : Reference< XEnumeration > xMainEnumeration( xMainEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
1107 :
1108 : // only export if the main sequence is not empty or if there are additional
1109 : // trigger sequences
1110 0 : bHasEffects = xMainEnumeration->hasMoreElements() || xEnumeration->hasMoreElements();
1111 0 : }
1112 : }
1113 0 : if( bHasEffects )
1114 : {
1115 0 : OUString sId = implGetValidIDFromInterface( mSelectedPages[i] );
1116 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, sId );
1117 0 : sId += "-animations";
1118 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1119 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Animations" );
1120 0 : SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
1121 :
1122 0 : UniReference< xmloff::AnimationsExporter > xAnimationsExporter;
1123 0 : xAnimationsExporter = new xmloff::AnimationsExporter( *mpSVGExport, xProps );
1124 0 : xAnimationsExporter->prepare( xRootNode );
1125 0 : xAnimationsExporter->exportAnimations( xRootNode );
1126 : }
1127 0 : }
1128 0 : }
1129 : }
1130 0 : }
1131 :
1132 0 : bRet = sal_True;
1133 0 : return bRet;
1134 : }
1135 :
1136 : // -----------------------------------------------------------------------------
1137 :
1138 0 : void SVGFilter::implExportTextShapeIndex()
1139 : {
1140 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "TextShapeIndex" );
1141 0 : SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
1142 :
1143 0 : sal_Int32 nCount = mSelectedPages.getLength();
1144 0 : for( sal_Int32 i = 0; i < nCount; ++i )
1145 : {
1146 0 : const Reference< XDrawPage > & xDrawPage = mSelectedPages[i];
1147 0 : if( mTextShapeIdListMap.find( xDrawPage ) != mTextShapeIdListMap.end() )
1148 : {
1149 0 : OUString sTextShapeIdList = mTextShapeIdListMap[xDrawPage].trim();
1150 :
1151 0 : const OUString& rPageId = implGetValidIDFromInterface( xDrawPage );
1152 0 : if( !rPageId.isEmpty() && !sTextShapeIdList.isEmpty() )
1153 : {
1154 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, rPageId );
1155 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrIdList, sTextShapeIdList );
1156 0 : SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1157 0 : }
1158 : }
1159 0 : }
1160 0 : }
1161 :
1162 : // -----------------------------------------------------------------------------
1163 :
1164 0 : void SVGFilter::implEmbedBulletGlyphs()
1165 : {
1166 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "EmbeddedBulletChars" );
1167 0 : SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
1168 :
1169 0 : OUString sPathData = "M 580,1141 L 1163,571 580,0 -4,571 580,1141 Z";
1170 0 : implEmbedBulletGlyph( 57356, sPathData );
1171 0 : sPathData = "M 8,1128 L 1137,1128 1137,0 8,0 8,1128 Z";
1172 0 : implEmbedBulletGlyph( 57354, sPathData );
1173 0 : sPathData = "M 174,0 L 602,739 174,1481 1456,739 174,0 Z M 1358,739 L 309,1346 659,739 1358,739 Z";
1174 0 : implEmbedBulletGlyph( 10146, sPathData );
1175 0 : sPathData = "M 2015,739 L 1276,0 717,0 1260,543 174,543 174,936 1260,936 717,1481 1274,1481 2015,739 Z";
1176 0 : implEmbedBulletGlyph( 10132, sPathData );
1177 0 : sPathData = "M 0,-2 C -7,14 -16,27 -25,37 L 356,567 C 262,823 215,952 215,954 215,979 228,992 255,992 264,992 276,990 289,987 310,991 331,999 354,1012 L 381,999 492,748 772,1049 836,1024 860,1049 C 881,1039 901,1025 922,1006 886,937 835,863 770,784 769,783 710,716 594,584 L 774,223 C 774,196 753,168 711,139 L 727,119 C 717,90 699,76 672,76 641,76 570,178 457,381 L 164,-76 C 142,-110 111,-127 72,-127 30,-127 9,-110 8,-76 1,-67 -2,-52 -2,-32 -2,-23 -1,-13 0,-2 Z";
1178 0 : implEmbedBulletGlyph( 10007, sPathData );
1179 0 : sPathData = "M 285,-33 C 182,-33 111,30 74,156 52,228 41,333 41,471 41,549 55,616 82,672 116,743 169,778 240,778 293,778 328,747 346,684 L 369,508 C 377,444 397,411 428,410 L 1163,1116 C 1174,1127 1196,1133 1229,1133 1271,1133 1292,1118 1292,1087 L 1292,965 C 1292,929 1282,901 1262,881 L 442,47 C 390,-6 338,-33 285,-33 Z";
1180 0 : implEmbedBulletGlyph( 10004, sPathData );
1181 0 : sPathData = "M 813,0 C 632,0 489,54 383,161 276,268 223,411 223,592 223,773 276,916 383,1023 489,1130 632,1184 813,1184 992,1184 1136,1130 1245,1023 1353,916 1407,772 1407,592 1407,412 1353,268 1245,161 1136,54 992,0 813,0 Z";
1182 0 : implEmbedBulletGlyph( 9679, sPathData );
1183 0 : sPathData = "M 346,457 C 273,457 209,483 155,535 101,586 74,649 74,723 74,796 101,859 155,911 209,963 273,989 346,989 419,989 480,963 531,910 582,859 608,796 608,723 608,648 583,586 532,535 482,483 420,457 346,457 Z";
1184 0 : implEmbedBulletGlyph( 8226, sPathData );
1185 0 : sPathData = "M -4,459 L 1135,459 1135,606 -4,606 -4,459 Z";
1186 0 : implEmbedBulletGlyph( 8211, sPathData );
1187 0 : }
1188 :
1189 : // -----------------------------------------------------------------------------
1190 :
1191 0 : void SVGFilter::implEmbedBulletGlyph( sal_Unicode cBullet, const OUString & sPathData )
1192 : {
1193 0 : OUString sId = "bullet-char-template(" + OUString::number( (sal_Int32)cBullet ) + ")";
1194 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1195 :
1196 0 : double fFactor = 1.0 / 2048;
1197 0 : OUString sFactor = OUString::valueOf( fFactor );
1198 0 : OUString sTransform = "scale(" + sFactor + ",-" + sFactor + ")";
1199 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "transform", sTransform );
1200 :
1201 0 : SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1202 :
1203 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "d", sPathData );
1204 0 : SvXMLElementExport aPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "path", sal_True, sal_True );
1205 :
1206 0 : }
1207 :
1208 : // -----------------------------------------------------------------------------
1209 :
1210 : /** SVGFilter::implExportTextEmbeddedBitmaps
1211 : * We export bitmaps embedded into text shapes, such as those used by list
1212 : * items with image style, only once in a specic <defs> element.
1213 : */
1214 0 : sal_Bool SVGFilter::implExportTextEmbeddedBitmaps()
1215 : {
1216 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "TextEmbeddedBitmaps" );
1217 0 : SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
1218 :
1219 0 : OUString sId;
1220 :
1221 0 : MetaBitmapActionSet::const_iterator it = mEmbeddedBitmapActionSet.begin();
1222 0 : MetaBitmapActionSet::const_iterator end = mEmbeddedBitmapActionSet.end();
1223 0 : for( ; it != end; ++it)
1224 : {
1225 0 : const GDIMetaFile& aMtf = it->GetRepresentation();
1226 :
1227 0 : if( aMtf.GetActionSize() == 1 )
1228 : {
1229 0 : MetaAction* pAction = aMtf.GetAction( 0 );
1230 0 : if( pAction )
1231 : {
1232 0 : sal_uLong nId = GetBitmapChecksum( pAction );
1233 0 : sId = "bitmap(" + OUString::valueOf( (sal_Int64)nId ) + ")";
1234 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1235 :
1236 0 : const Reference< XShape >& rxShape = (const Reference< XShape >&)( it->GetObject() );
1237 0 : Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
1238 0 : ::com::sun::star::awt::Rectangle aBoundRect;
1239 0 : if( xShapePropSet.is() && ( xShapePropSet->getPropertyValue( "BoundRect" ) >>= aBoundRect ) )
1240 : {
1241 : // Origin of the coordinate device must be (0,0).
1242 0 : const Point aTopLeft;
1243 0 : const Size aSize( aBoundRect.Width, aBoundRect.Height );
1244 :
1245 0 : Point aPt;
1246 0 : MetaBitmapActionGetPoint( pAction, aPt );
1247 : // The image must be exported with x, y attribute set to 0,
1248 : // on the contrary when referenced by a <use> element,
1249 : // specifying the wanted position, they will result
1250 : // misplaced.
1251 0 : pAction->Move( -aPt.X(), -aPt.Y() );
1252 0 : mpSVGWriter->WriteMetaFile( aTopLeft, aSize, aMtf, 0xffffffff, NULL );
1253 : // We reset to the original values so that when the <use>
1254 : // element is created the x, y attributes are correct.
1255 0 : pAction->Move( aPt.X(), aPt.Y() );
1256 : }
1257 : else
1258 : {
1259 : OSL_FAIL( "implExportTextEmbeddedBitmaps: no shape bounding box." );
1260 0 : return sal_False;
1261 0 : }
1262 : }
1263 : else
1264 : {
1265 : OSL_FAIL( "implExportTextEmbeddedBitmaps: metafile should have MetaBmpExScaleAction only." );
1266 0 : return sal_False;
1267 : }
1268 : }
1269 : else
1270 : {
1271 : OSL_FAIL( "implExportTextEmbeddedBitmaps: metafile should have a single action." );
1272 0 : return sal_False;
1273 : }
1274 :
1275 : }
1276 0 : return sal_True;
1277 : }
1278 :
1279 : // -----------------------------------------------------------------------------
1280 :
1281 : #define SVGFILTER_EXPORT_SVGSCRIPT( z, n, aFragment ) \
1282 : xExtDocHandler->unknown( OUString::createFromAscii( aFragment ## n ) );
1283 :
1284 0 : sal_Bool SVGFilter::implGenerateScript()
1285 : {
1286 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "type", "text/ecmascript" );
1287 :
1288 : {
1289 0 : SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "script", sal_True, sal_True );
1290 0 : Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
1291 :
1292 0 : if( xExtDocHandler.is() )
1293 : {
1294 0 : BOOST_PP_REPEAT( N_SVGSCRIPT_FRAGMENTS, SVGFILTER_EXPORT_SVGSCRIPT, aSVGScript )
1295 0 : }
1296 : }
1297 :
1298 0 : return sal_True;
1299 : }
1300 :
1301 : // -----------------------------------------------------------------------------
1302 :
1303 0 : Any SVGFilter::implSafeGetPagePropSet( const OUString & sPropertyName,
1304 : const Reference< XPropertySet > & rxPropSet,
1305 : const Reference< XPropertySetInfo > & rxPropSetInfo )
1306 : {
1307 0 : Any result;
1308 0 : if( rxPropSetInfo->hasPropertyByName( sPropertyName ) )
1309 : {
1310 0 : result = rxPropSet->getPropertyValue( sPropertyName );
1311 : }
1312 0 : return result;
1313 : }
1314 :
1315 : // -----------------------------------------------------------------------------
1316 :
1317 : /* SVGFilter::implGetPagePropSet
1318 : *
1319 : * We collect info on master page elements visibility,
1320 : * and placeholder text shape content.
1321 : * This method is used when exporting a single page
1322 : * as implGenerateMetaData is not invoked.
1323 : */
1324 0 : sal_Bool SVGFilter::implGetPagePropSet( const Reference< XDrawPage > & rxPage )
1325 : {
1326 0 : sal_Bool bRet = sal_False;
1327 :
1328 0 : mVisiblePagePropSet.bIsBackgroundVisible = true;
1329 0 : mVisiblePagePropSet.bAreBackgroundObjectsVisible = true;
1330 0 : mVisiblePagePropSet.bIsPageNumberFieldVisible = false;;
1331 0 : mVisiblePagePropSet.bIsHeaderFieldVisible = false;
1332 0 : mVisiblePagePropSet.bIsFooterFieldVisible = true;
1333 0 : mVisiblePagePropSet.bIsDateTimeFieldVisible = true;
1334 0 : mVisiblePagePropSet.bIsDateTimeFieldFixed = true;
1335 0 : mVisiblePagePropSet.nDateTimeFormat = SVXDATEFORMAT_B;
1336 0 : mVisiblePagePropSet.nPageNumberingType = SVX_ARABIC;
1337 :
1338 : /* We collect info on master page elements visibility,
1339 : * and placeholder text shape content.
1340 : */
1341 0 : Any result;
1342 0 : Reference< XPropertySet > xPropSet( rxPage, UNO_QUERY );
1343 0 : if( xPropSet.is() )
1344 : {
1345 0 : Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
1346 0 : if( xPropSetInfo.is() )
1347 : {
1348 0 : implSafeGetPagePropSet( "IsBackgroundVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsBackgroundVisible;
1349 0 : implSafeGetPagePropSet( "IsBackgroundObjectsVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bAreBackgroundObjectsVisible;
1350 0 : implSafeGetPagePropSet( "IsPageNumberVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsPageNumberFieldVisible;
1351 0 : implSafeGetPagePropSet( "IsHeaderVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsHeaderFieldVisible;
1352 0 : implSafeGetPagePropSet( "IsFooterVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsFooterFieldVisible;
1353 0 : implSafeGetPagePropSet( "IsDateTimeVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsDateTimeFieldVisible;
1354 :
1355 0 : implSafeGetPagePropSet( "IsDateTimeFixed", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsDateTimeFieldFixed;
1356 0 : implSafeGetPagePropSet( "DateTimeFormat", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.nDateTimeFormat;
1357 0 : implSafeGetPagePropSet( "Number", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.nPageNumber;
1358 0 : implSafeGetPagePropSet( "DateTimeText", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.sDateTimeText;
1359 0 : implSafeGetPagePropSet( "FooterText", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.sFooterText;
1360 0 : implSafeGetPagePropSet( "HeaderText", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.sHeaderText;
1361 :
1362 0 : if( mVisiblePagePropSet.bIsPageNumberFieldVisible )
1363 : {
1364 0 : SvxDrawPage* pSvxDrawPage = SvxDrawPage::getImplementation( rxPage );
1365 0 : if( pSvxDrawPage )
1366 : {
1367 0 : SdrPage* pSdrPage = pSvxDrawPage->GetSdrPage();
1368 0 : SdrModel* pSdrModel = pSdrPage->GetModel();
1369 0 : mVisiblePagePropSet.nPageNumberingType = pSdrModel->GetPageNumType();
1370 : }
1371 : }
1372 :
1373 0 : bRet = sal_True;
1374 0 : }
1375 : }
1376 :
1377 0 : return bRet;
1378 : }
1379 :
1380 :
1381 : // -----------------------------------------------------------------------------
1382 :
1383 0 : sal_Bool SVGFilter::implExportMasterPages( const SVGFilter::XDrawPageSequence & rxPages,
1384 : sal_Int32 nFirstPage, sal_Int32 nLastPage )
1385 : {
1386 : DBG_ASSERT( nFirstPage <= nLastPage,
1387 : "SVGFilter::implExportPages: nFirstPage > nLastPage" );
1388 :
1389 : // When the exported slides are more than one we wrap master page elements
1390 : // with a svg <defs> element.
1391 0 : OUString aContainerTag = (mbSinglePage) ? OUString( "g" ) : OUString( "defs" );
1392 0 : SvXMLElementExport aContainerElement( *mpSVGExport, XML_NAMESPACE_NONE, aContainerTag, sal_True, sal_True );
1393 :
1394 0 : sal_Bool bRet = sal_False;
1395 0 : for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
1396 : {
1397 0 : if( rxPages[i].is() )
1398 : {
1399 0 : Reference< XShapes > xShapes( rxPages[i], UNO_QUERY );
1400 :
1401 0 : if( xShapes.is() )
1402 : {
1403 : // add id attribute
1404 0 : const OUString & sPageId = implGetValidIDFromInterface( rxPages[i] );
1405 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPageId );
1406 :
1407 0 : bRet = implExportPage( sPageId, rxPages[i], xShapes, sal_True /* is a master page */ ) || bRet;
1408 0 : }
1409 : }
1410 : }
1411 0 : return bRet;
1412 : }
1413 :
1414 : // -----------------------------------------------------------------------------
1415 :
1416 0 : sal_Bool SVGFilter::implExportDrawPages( const SVGFilter::XDrawPageSequence & rxPages,
1417 : sal_Int32 nFirstPage, sal_Int32 nLastPage )
1418 : {
1419 : DBG_ASSERT( nFirstPage <= nLastPage,
1420 : "SVGFilter::implExportPages: nFirstPage > nLastPage" );
1421 :
1422 : // We wrap all slide in a group element with class name "SlideGroup".
1423 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "SlideGroup" );
1424 0 : SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1425 :
1426 0 : sal_Bool bRet = sal_False;
1427 0 : for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
1428 : {
1429 0 : Reference< XShapes > xShapes( rxPages[i], UNO_QUERY );
1430 :
1431 0 : if( xShapes.is() )
1432 : {
1433 : // Insert the <g> open tag related to the svg element for
1434 : // handling a slide visibility.
1435 : // In case the exported slides are more than one the initial
1436 : // visibility of each slide is set to 'hidden'.
1437 0 : if( !mbSinglePage )
1438 : {
1439 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
1440 : }
1441 0 : SvXMLElementExport aGElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1442 :
1443 : {
1444 : // add id attribute
1445 0 : const OUString & sPageId = implGetValidIDFromInterface( rxPages[i] );
1446 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPageId );
1447 :
1448 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Slide" );
1449 :
1450 : // Adding a clip path to each exported slide , so in case
1451 : // bitmaps or other elements exceed the slide margins, they are
1452 : // trimmed, even when they are shown inside a thumbnail view.
1453 0 : OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
1454 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
1455 :
1456 0 : SvXMLElementExport aSlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1457 :
1458 0 : bRet = implExportPage( sPageId, rxPages[i], xShapes, sal_False /* is not a master page */ ) || bRet;
1459 0 : }
1460 : } // append the </g> closing tag related to the svg element handling the slide visibility
1461 0 : }
1462 :
1463 0 : return bRet;
1464 : }
1465 :
1466 : // -----------------------------------------------------------------------------
1467 0 : sal_Bool SVGFilter::implExportPage( const OUString & sPageId,
1468 : const Reference< XDrawPage > & rxPage,
1469 : const Reference< XShapes > & xShapes,
1470 : sal_Bool bMaster )
1471 : {
1472 0 : sal_Bool bRet = sal_False;
1473 :
1474 : {
1475 0 : OUString sPageName = implGetInterfaceName( rxPage );
1476 0 : if( !(sPageName.isEmpty() || mbSinglePage ))
1477 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrName, sPageName );
1478 :
1479 : {
1480 0 : Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
1481 :
1482 0 : if( xExtDocHandler.is() )
1483 : {
1484 0 : OUString aDesc;
1485 :
1486 0 : if( bMaster )
1487 0 : aDesc = "Master_Slide";
1488 : else
1489 0 : aDesc = "Page";
1490 :
1491 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", aDesc );
1492 0 : }
1493 : }
1494 :
1495 : // insert the <g> open tag related to the DrawPage/MasterPage
1496 0 : SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1497 :
1498 : // In case the page has a background object we append it .
1499 0 : if( (mpObjects->find( rxPage ) != mpObjects->end()) )
1500 : {
1501 0 : const GDIMetaFile& rMtf = (*mpObjects)[ rxPage ].GetRepresentation();
1502 0 : if( rMtf.GetActionSize() )
1503 : {
1504 : // background id = "bg-" + page id
1505 0 : OUString sBackgroundId = "bg-";
1506 0 : sBackgroundId += sPageId;
1507 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBackgroundId );
1508 :
1509 : // At present (LibreOffice 3.4.0) the 'IsBackgroundVisible' property is not handled
1510 : // by Impress; anyway we handle this property as referring only to the visibility
1511 : // of the master page background. So if a slide has its own background object,
1512 : // the visibility of such a background object is always inherited from the visibility
1513 : // of the parent slide regardless of the value of the 'IsBackgroundVisible' property.
1514 : // This means that we need to set up the visibility attribute only for the background
1515 : // element of a master page.
1516 0 : if( mbSinglePage && bMaster )
1517 : {
1518 0 : if( !mVisiblePagePropSet.bIsBackgroundVisible )
1519 : {
1520 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
1521 : }
1522 : }
1523 :
1524 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Background" );
1525 :
1526 : // insert the <g> open tag related to the Background
1527 0 : SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1528 :
1529 : // append all elements that make up the Background
1530 0 : const Point aNullPt;
1531 0 : mpSVGWriter->WriteMetaFile( aNullPt, rMtf.GetPrefSize(), rMtf, SVGWRITER_WRITE_FILL );
1532 : } // insert the </g> closing tag related to the Background
1533 : }
1534 :
1535 : // In case we are dealing with a master page we need to to group all its shapes
1536 : // into a group element, this group will make up the so named "background objects"
1537 0 : if( bMaster )
1538 : {
1539 : // background objects id = "bo-" + page id
1540 0 : OUString sBackgroundObjectsId = "bo-";
1541 0 : sBackgroundObjectsId += sPageId;
1542 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBackgroundObjectsId );
1543 0 : if( mbSinglePage )
1544 : {
1545 0 : if( !mVisiblePagePropSet.bAreBackgroundObjectsVisible )
1546 : {
1547 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
1548 : }
1549 : }
1550 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundObjects" );
1551 :
1552 : // insert the <g> open tag related to the Background Objects
1553 0 : SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1554 :
1555 : // append all shapes that make up the Master Slide
1556 0 : bRet = implExportShapes( xShapes ) || bRet;
1557 : } // append the </g> closing tag related to the Background Objects
1558 : else
1559 : {
1560 : // append all shapes that make up the Slide
1561 0 : bRet = implExportShapes( xShapes ) || bRet;
1562 0 : }
1563 : } // append the </g> closing tag related to the Slide/Master_Slide
1564 :
1565 0 : return bRet;
1566 : }
1567 :
1568 :
1569 : // -----------------------------------------------------------------------------
1570 :
1571 0 : sal_Bool SVGFilter::implExportShapes( const Reference< XShapes >& rxShapes )
1572 : {
1573 0 : Reference< XShape > xShape;
1574 0 : sal_Bool bRet = sal_False;
1575 :
1576 0 : for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
1577 : {
1578 0 : if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
1579 0 : bRet = implExportShape( xShape ) || bRet;
1580 :
1581 0 : xShape = NULL;
1582 : }
1583 :
1584 0 : return bRet;
1585 : }
1586 :
1587 : // -----------------------------------------------------------------------------
1588 :
1589 0 : sal_Bool SVGFilter::implExportShape( const Reference< XShape >& rxShape )
1590 : {
1591 0 : Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
1592 0 : sal_Bool bRet = sal_False;
1593 :
1594 0 : if( xShapePropSet.is() )
1595 : {
1596 0 : const OUString aShapeType( rxShape->getShapeType() );
1597 0 : sal_Bool bHideObj = sal_False;
1598 :
1599 0 : if( mbPresentation )
1600 : {
1601 0 : xShapePropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bHideObj;
1602 : }
1603 :
1604 0 : if( !bHideObj )
1605 : {
1606 0 : if( aShapeType.lastIndexOf( "drawing.GroupShape" ) != -1 )
1607 : {
1608 0 : Reference< XShapes > xShapes( rxShape, UNO_QUERY );
1609 :
1610 0 : if( xShapes.is() )
1611 : {
1612 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Group" );
1613 0 : SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1614 :
1615 0 : bRet = implExportShapes( xShapes );
1616 0 : }
1617 : }
1618 :
1619 0 : if( !bRet && mpObjects->find( rxShape ) != mpObjects->end() )
1620 : {
1621 0 : const OUString* pElementId = NULL;
1622 :
1623 0 : ::com::sun::star::awt::Rectangle aBoundRect;
1624 0 : const GDIMetaFile& rMtf = (*mpObjects)[ rxShape ].GetRepresentation();
1625 :
1626 0 : xShapePropSet->getPropertyValue( "BoundRect" ) >>= aBoundRect;
1627 :
1628 0 : const Point aTopLeft( aBoundRect.X, aBoundRect.Y );
1629 0 : const Size aSize( aBoundRect.Width, aBoundRect.Height );
1630 :
1631 0 : if( rMtf.GetActionSize() )
1632 : { // for text field shapes we set up text-adjust attributes
1633 : // and set visibility to hidden
1634 0 : OUString aShapeClass = implGetClassFromShape( rxShape );
1635 0 : if( mbPresentation )
1636 : {
1637 0 : sal_Bool bIsPageNumber = ( aShapeClass == "Slide_Number" );
1638 0 : sal_Bool bIsFooter = ( aShapeClass == "Footer" );
1639 0 : sal_Bool bIsDateTime = ( aShapeClass == "Date/Time" );
1640 0 : if( bIsPageNumber || bIsDateTime || bIsFooter )
1641 : {
1642 0 : if( !mbSinglePage )
1643 : {
1644 : // to notify to the SVGActionWriter::ImplWriteActions method
1645 : // that we are dealing with a placeholder shape
1646 0 : pElementId = &sPlaceholderTag;
1647 :
1648 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
1649 :
1650 0 : sal_uInt16 nTextAdjust = ParagraphAdjust_LEFT;
1651 0 : OUString sTextAdjust;
1652 0 : xShapePropSet->getPropertyValue( "ParaAdjust" ) >>= nTextAdjust;
1653 :
1654 0 : switch( nTextAdjust )
1655 : {
1656 : case ParagraphAdjust_LEFT:
1657 0 : sTextAdjust = "left";
1658 0 : break;
1659 : case ParagraphAdjust_CENTER:
1660 0 : sTextAdjust = "center";
1661 0 : break;
1662 : case ParagraphAdjust_RIGHT:
1663 0 : sTextAdjust = "right";
1664 0 : break;
1665 : default:
1666 0 : break;
1667 : }
1668 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrTextAdjust, sTextAdjust );
1669 : }
1670 : else // single page case
1671 : {
1672 0 : if( !mVisiblePagePropSet.bAreBackgroundObjectsVisible || (
1673 0 : ( bIsPageNumber && !mVisiblePagePropSet.bIsPageNumberFieldVisible ) ||
1674 0 : ( bIsDateTime && !mVisiblePagePropSet.bIsDateTimeFieldVisible ) ||
1675 0 : ( bIsFooter && !mVisiblePagePropSet.bIsFooterFieldVisible ) ) )
1676 : {
1677 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
1678 : }
1679 : }
1680 : }
1681 : }
1682 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", aShapeClass );
1683 0 : SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1684 :
1685 0 : Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
1686 :
1687 0 : OUString aTitle;
1688 0 : xShapePropSet->getPropertyValue( "Title" ) >>= aTitle;
1689 0 : if( !aTitle.isEmpty() )
1690 : {
1691 0 : SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "title", sal_True, sal_True );
1692 0 : xExtDocHandler->characters( aTitle );
1693 : }
1694 :
1695 0 : OUString aDescription;
1696 0 : xShapePropSet->getPropertyValue( "Description" ) >>= aDescription;
1697 0 : if( !aDescription.isEmpty() )
1698 : {
1699 0 : SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", sal_True, sal_True );
1700 0 : xExtDocHandler->characters( aDescription );
1701 : }
1702 :
1703 :
1704 0 : const OUString& rShapeId = implGetValidIDFromInterface( rxShape );
1705 0 : if( !rShapeId.isEmpty() )
1706 : {
1707 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", rShapeId );
1708 : }
1709 :
1710 0 : const GDIMetaFile* pEmbeddedBitmapsMtf = NULL;
1711 0 : if( mEmbeddedBitmapActionMap.find( rxShape ) != mEmbeddedBitmapActionMap.end() )
1712 : {
1713 0 : pEmbeddedBitmapsMtf = &( mEmbeddedBitmapActionMap[ rxShape ].GetRepresentation() );
1714 : }
1715 :
1716 : {
1717 0 : OUString aBookmark;
1718 0 : Reference<XPropertySetInfo> xShapePropSetInfo = xShapePropSet->getPropertySetInfo();
1719 0 : if(xShapePropSetInfo->hasPropertyByName("Bookmark"))
1720 : {
1721 0 : xShapePropSet->getPropertyValue( "Bookmark" ) >>= aBookmark;
1722 : }
1723 :
1724 0 : SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", sal_True, sal_True );
1725 0 : if( !aBookmark.isEmpty() )
1726 : {
1727 0 : mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xlink:href", aBookmark);
1728 0 : SvXMLElementExport alinkA( *mpSVGExport, XML_NAMESPACE_NONE, "a", sal_True, sal_True );
1729 : mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
1730 : 0xffffffff,
1731 : pElementId,
1732 : &rxShape,
1733 0 : pEmbeddedBitmapsMtf );
1734 : }
1735 : else
1736 : {
1737 : mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
1738 : 0xffffffff,
1739 : pElementId,
1740 : &rxShape,
1741 0 : pEmbeddedBitmapsMtf );
1742 0 : }
1743 0 : }
1744 : }
1745 :
1746 0 : bRet = sal_True;
1747 : }
1748 0 : }
1749 : }
1750 :
1751 0 : return bRet;
1752 : }
1753 :
1754 : // -----------------------------------------------------------------------------
1755 :
1756 0 : sal_Bool SVGFilter::implCreateObjects()
1757 : {
1758 : sal_Int32 i, nCount;
1759 :
1760 0 : for( i = 0, nCount = mMasterPageTargets.getLength(); i < nCount; ++i )
1761 : {
1762 0 : const Reference< XDrawPage > & xMasterPage = mMasterPageTargets[i];
1763 :
1764 0 : if( xMasterPage.is() )
1765 : {
1766 0 : mCreateOjectsCurrentMasterPage = xMasterPage;
1767 0 : implCreateObjectsFromBackground( xMasterPage );
1768 :
1769 0 : if( xMasterPage.is() )
1770 0 : implCreateObjectsFromShapes( xMasterPage, xMasterPage );
1771 : }
1772 : }
1773 :
1774 0 : for( i = 0, nCount = mSelectedPages.getLength(); i < nCount; ++i )
1775 : {
1776 0 : const Reference< XDrawPage > & xDrawPage = mSelectedPages[i];
1777 :
1778 0 : if( xDrawPage.is() )
1779 : {
1780 : #ifdef ENABLE_EXPORT_CUSTOM_SLIDE_BACKGROUND
1781 : // TODO complete the implementation for exporting custom background for each slide
1782 : // implementation status:
1783 : // - hatch stroke color is set to 'none' so the hatch is not visible, why ?
1784 : // - gradient look is not really awesome, too few colors are used;
1785 : // - stretched bitmap, gradient and hatch are not exported only once
1786 : // and then referenced in case more than one slide uses them.
1787 : // - tiled bitmap: an image element is exported for each tile,
1788 : // this is really too expensive!
1789 : Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
1790 : Reference< XPropertySet > xBackground;
1791 : xPropSet->getPropertyValue( "Background" ) >>= xBackground;
1792 : if( xBackground.is() )
1793 : {
1794 : drawing::FillStyle aFillStyle;
1795 : sal_Bool assigned = ( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle );
1796 : if( assigned && aFillStyle != drawing::FillStyle_NONE )
1797 : {
1798 : implCreateObjectsFromBackground( xDrawPage );
1799 : }
1800 : }
1801 : #endif
1802 :
1803 0 : if( xDrawPage.is() )
1804 0 : implCreateObjectsFromShapes( xDrawPage, xDrawPage );
1805 : }
1806 : }
1807 0 : return sal_True;
1808 : }
1809 :
1810 : // -----------------------------------------------------------------------------
1811 :
1812 0 : sal_Bool SVGFilter::implCreateObjectsFromShapes( const Reference< XDrawPage > & rxPage, const Reference< XShapes >& rxShapes )
1813 : {
1814 0 : Reference< XShape > xShape;
1815 0 : sal_Bool bRet = sal_False;
1816 :
1817 0 : for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
1818 : {
1819 0 : if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
1820 0 : bRet = implCreateObjectsFromShape( rxPage, xShape ) || bRet;
1821 :
1822 0 : xShape = NULL;
1823 : }
1824 :
1825 0 : return bRet;
1826 : }
1827 :
1828 : // -----------------------------------------------------------------------------
1829 :
1830 0 : sal_Bool SVGFilter::implCreateObjectsFromShape( const Reference< XDrawPage > & rxPage, const Reference< XShape >& rxShape )
1831 : {
1832 0 : sal_Bool bRet = sal_False;
1833 0 : if( rxShape->getShapeType().lastIndexOf( "drawing.GroupShape" ) != -1 )
1834 : {
1835 0 : Reference< XShapes > xShapes( rxShape, UNO_QUERY );
1836 :
1837 0 : if( xShapes.is() )
1838 0 : bRet = implCreateObjectsFromShapes( rxPage, xShapes );
1839 : }
1840 : else
1841 : {
1842 0 : SdrObject* pObj = GetSdrObjectFromXShape( rxShape );
1843 :
1844 0 : if( pObj )
1845 : {
1846 0 : Graphic aGraphic( SdrExchangeView::GetObjGraphic( pObj->GetModel(), pObj ) );
1847 :
1848 0 : if( aGraphic.GetType() != GRAPHIC_NONE )
1849 : {
1850 0 : if( aGraphic.GetType() == GRAPHIC_BITMAP )
1851 : {
1852 0 : GDIMetaFile aMtf;
1853 0 : const Point aNullPt;
1854 0 : const Size aSize( pObj->GetCurrentBoundRect().GetSize() );
1855 :
1856 0 : aMtf.AddAction( new MetaBmpExScaleAction( aNullPt, aSize, aGraphic.GetBitmapEx() ) );
1857 0 : aMtf.SetPrefSize( aSize );
1858 0 : aMtf.SetPrefMapMode( MAP_100TH_MM );
1859 :
1860 0 : (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
1861 : }
1862 : else
1863 : {
1864 0 : if( aGraphic.GetGDIMetaFile().GetActionSize() )
1865 : {
1866 0 : Reference< XText > xText( rxShape, UNO_QUERY );
1867 0 : sal_Bool bIsTextShape = xText.is();
1868 :
1869 0 : if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
1870 : {
1871 0 : Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
1872 :
1873 0 : if( xShapePropSet.is() )
1874 : {
1875 0 : sal_Bool bHideObj = sal_False;
1876 :
1877 0 : if( mbPresentation )
1878 : {
1879 0 : xShapePropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bHideObj;
1880 : }
1881 :
1882 0 : if( !bHideObj )
1883 : {
1884 : // We create a map of text shape ids.
1885 0 : implRegisterInterface( rxShape );
1886 0 : const OUString& rShapeId = implGetValidIDFromInterface( rxShape );
1887 0 : if( !rShapeId.isEmpty() )
1888 : {
1889 0 : mTextShapeIdListMap[rxPage] += rShapeId;
1890 0 : mTextShapeIdListMap[rxPage] += " ";
1891 : }
1892 :
1893 : // We create a set of bitmaps embedded into text shape.
1894 0 : GDIMetaFile aMtf;
1895 0 : const Size aSize( pObj->GetCurrentBoundRect().GetSize() );
1896 : MetaAction* pAction;
1897 0 : sal_Bool bIsTextShapeStarted = sal_False;
1898 0 : const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
1899 0 : sal_uLong nCount = rMtf.GetActionSize();
1900 0 : for( sal_uLong nCurAction = 0; nCurAction < nCount; ++nCurAction )
1901 : {
1902 0 : pAction = rMtf.GetAction( nCurAction );
1903 0 : const sal_uInt16 nType = pAction->GetType();
1904 :
1905 0 : if( nType == META_COMMENT_ACTION )
1906 : {
1907 0 : const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
1908 0 : if( ( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XTEXT_PAINTSHAPE_BEGIN")) ) )
1909 : {
1910 0 : bIsTextShapeStarted = sal_True;
1911 : }
1912 0 : else if( ( pA->GetComment().equalsIgnoreAsciiCaseL( RTL_CONSTASCII_STRINGPARAM( "XTEXT_PAINTSHAPE_END" ) ) ) )
1913 : {
1914 0 : bIsTextShapeStarted = sal_False;
1915 : }
1916 : }
1917 0 : if( bIsTextShapeStarted && ( nType == META_BMPSCALE_ACTION || nType == META_BMPEXSCALE_ACTION ) )
1918 : {
1919 0 : GDIMetaFile aEmbeddedBitmapMtf;
1920 0 : pAction->Duplicate();
1921 0 : aEmbeddedBitmapMtf.AddAction( pAction );
1922 0 : aEmbeddedBitmapMtf.SetPrefSize( aSize );
1923 0 : aEmbeddedBitmapMtf.SetPrefMapMode( MAP_100TH_MM );
1924 0 : mEmbeddedBitmapActionSet.insert( ObjectRepresentation( rxShape, aEmbeddedBitmapMtf ) );
1925 0 : pAction->Duplicate();
1926 0 : aMtf.AddAction( pAction );
1927 : }
1928 : }
1929 0 : aMtf.SetPrefSize( aSize );
1930 0 : aMtf.SetPrefMapMode( MAP_100TH_MM );
1931 0 : mEmbeddedBitmapActionMap[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
1932 : }
1933 0 : }
1934 0 : }
1935 : }
1936 0 : (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
1937 : }
1938 0 : bRet = sal_True;
1939 0 : }
1940 : }
1941 : }
1942 :
1943 0 : return bRet;
1944 : }
1945 :
1946 : // -----------------------------------------------------------------------------
1947 :
1948 0 : sal_Bool SVGFilter::implCreateObjectsFromBackground( const Reference< XDrawPage >& rxDrawPage )
1949 : {
1950 0 : Reference< XGraphicExportFilter > xExporter = drawing::GraphicExportFilter::create( mxContext );
1951 0 : sal_Bool bRet = sal_False;
1952 :
1953 0 : GDIMetaFile aMtf;
1954 :
1955 0 : utl::TempFile aFile;
1956 0 : aFile.EnableKillingFile();
1957 :
1958 0 : Sequence< PropertyValue > aDescriptor( 3 );
1959 0 : aDescriptor[0].Name = "FilterName";
1960 0 : aDescriptor[0].Value <<= OUString( "SVM" );
1961 0 : aDescriptor[1].Name = "URL";
1962 0 : aDescriptor[1].Value <<= OUString( aFile.GetURL() );
1963 0 : aDescriptor[2].Name = "ExportOnlyBackground";
1964 0 : aDescriptor[2].Value <<= (sal_Bool) sal_True;
1965 :
1966 0 : xExporter->setSourceDocument( Reference< XComponent >( rxDrawPage, UNO_QUERY ) );
1967 0 : xExporter->filter( aDescriptor );
1968 0 : aMtf.Read( *aFile.GetStream( STREAM_READ ) );
1969 :
1970 0 : (*mpObjects)[ rxDrawPage ] = ObjectRepresentation( rxDrawPage, aMtf );
1971 :
1972 0 : bRet = sal_True;
1973 :
1974 0 : return bRet;
1975 : }
1976 :
1977 : // -----------------------------------------------------------------------------
1978 :
1979 0 : OUString SVGFilter::implGetClassFromShape( const Reference< XShape >& rxShape )
1980 : {
1981 0 : OUString aRet;
1982 0 : const OUString aShapeType( rxShape->getShapeType() );
1983 :
1984 0 : if( aShapeType.lastIndexOf( "drawing.GroupShape" ) != -1 )
1985 0 : aRet = "Group";
1986 0 : else if( aShapeType.lastIndexOf( "drawing.GraphicObjectShape" ) != -1 )
1987 0 : aRet = "Graphic";
1988 0 : else if( aShapeType.lastIndexOf( "drawing.OLE2Shape" ) != -1 )
1989 0 : aRet = "OLE2";
1990 0 : else if( aShapeType.lastIndexOf( "presentation.HeaderShape" ) != -1 )
1991 0 : aRet = "Header";
1992 0 : else if( aShapeType.lastIndexOf( "presentation.FooterShape" ) != -1 )
1993 0 : aRet = "Footer";
1994 0 : else if( aShapeType.lastIndexOf( "presentation.DateTimeShape" ) != -1 )
1995 0 : aRet = "Date/Time";
1996 0 : else if( aShapeType.lastIndexOf( "presentation.SlideNumberShape" ) != -1 )
1997 0 : aRet = "Slide_Number";
1998 : else
1999 0 : aRet = aShapeType;
2000 :
2001 0 : return aRet;
2002 : }
2003 :
2004 : // -----------------------------------------------------------------------------
2005 :
2006 0 : void SVGFilter::implRegisterInterface( const Reference< XInterface >& rxIf )
2007 : {
2008 0 : if( rxIf.is() )
2009 0 : (mpSVGExport->getInterfaceToIdentifierMapper()).registerReference( rxIf );
2010 0 : }
2011 :
2012 : // -----------------------------------------------------------------------------
2013 :
2014 0 : const OUString & SVGFilter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf )
2015 : {
2016 0 : return (mpSVGExport->getInterfaceToIdentifierMapper()).getIdentifier( rxIf );
2017 : }
2018 :
2019 : // -----------------------------------------------------------------------------
2020 :
2021 0 : OUString SVGFilter::implGetInterfaceName( const Reference< XInterface >& rxIf )
2022 : {
2023 0 : Reference< XNamed > xNamed( rxIf, UNO_QUERY );
2024 0 : OUString aRet;
2025 0 : if( xNamed.is() )
2026 : {
2027 0 : aRet = xNamed->getName().replace( ' ', '_' );
2028 : }
2029 0 : return aRet;
2030 : }
2031 :
2032 : // -----------------------------------------------------------------------------
2033 :
2034 0 : IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo )
2035 : {
2036 0 : sal_Bool bFieldProcessed = sal_False;
2037 0 : if( pInfo && mbPresentation )
2038 : {
2039 0 : bFieldProcessed = true;
2040 0 : OUString aRepresentation;
2041 0 : if( !mbSinglePage )
2042 : {
2043 0 : if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
2044 : {
2045 : // to notify to the SVGActionWriter::ImplWriteText method
2046 : // that we are dealing with a placeholder shape
2047 0 : aRepresentation = sPlaceholderTag;
2048 :
2049 0 : if( !mCreateOjectsCurrentMasterPage.is() )
2050 : {
2051 : OSL_FAIL( "error: !mCreateOjectsCurrentMasterPage.is()" );
2052 0 : return 0;
2053 : }
2054 0 : sal_Bool bHasCharSetMap = !( mTextFieldCharSets.find( mCreateOjectsCurrentMasterPage ) == mTextFieldCharSets.end() );
2055 :
2056 0 : static const OUString aHeaderId( aOOOAttrHeaderField );
2057 0 : static const OUString aFooterId( aOOOAttrFooterField );
2058 0 : static const OUString aDateTimeId( aOOOAttrDateTimeField );
2059 0 : static const OUString aVariableDateTimeId( aOOOAttrDateTimeField + "-variable" );
2060 :
2061 0 : const UCharSet * pCharSet = NULL;
2062 0 : UCharSetMap * pCharSetMap = NULL;
2063 0 : if( bHasCharSetMap )
2064 : {
2065 0 : pCharSetMap = &( mTextFieldCharSets[ mCreateOjectsCurrentMasterPage ] );
2066 : }
2067 0 : const SvxFieldData* pField = pInfo->GetField().GetField();
2068 0 : if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_HEADER ) && ( pCharSetMap->find( aHeaderId ) != pCharSetMap->end() ) )
2069 : {
2070 0 : pCharSet = &( (*pCharSetMap)[ aHeaderId ] );
2071 : }
2072 0 : else if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_FOOTER ) && ( pCharSetMap->find( aFooterId ) != pCharSetMap->end() ) )
2073 : {
2074 0 : pCharSet = &( (*pCharSetMap)[ aFooterId ] );
2075 : }
2076 0 : else if( pField->GetClassId() == text::textfield::Type::PRESENTATION_DATE_TIME )
2077 : {
2078 0 : if( bHasCharSetMap && ( pCharSetMap->find( aDateTimeId ) != pCharSetMap->end() ) )
2079 : {
2080 0 : pCharSet = &( (*pCharSetMap)[ aDateTimeId ] );
2081 : }
2082 0 : if( bHasCharSetMap && ( pCharSetMap->find( aVariableDateTimeId ) != pCharSetMap->end() ) && !(*pCharSetMap)[ aVariableDateTimeId ].empty() )
2083 : {
2084 0 : SvxDateFormat eDateFormat = SVXDATEFORMAT_B, eCurDateFormat;
2085 0 : const UCharSet & aCharSet = (*pCharSetMap)[ aVariableDateTimeId ];
2086 0 : UCharSet::const_iterator aChar = aCharSet.begin();
2087 : // we look for the most verbose date format
2088 0 : for( ; aChar != aCharSet.end(); ++aChar )
2089 : {
2090 0 : eCurDateFormat = (SvxDateFormat)( (int)( *aChar ) & 0x0f );
2091 0 : switch( eDateFormat )
2092 : {
2093 : case SVXDATEFORMAT_STDSMALL: ;
2094 : case SVXDATEFORMAT_A: ; // 13.02.96
2095 : case SVXDATEFORMAT_B: // 13.02.1996
2096 0 : switch( eCurDateFormat )
2097 : {
2098 : case SVXDATEFORMAT_C: ; // 13.Feb 1996
2099 : case SVXDATEFORMAT_D: // 13.February 1996
2100 : case SVXDATEFORMAT_E: ; // Tue, 13.February 1996
2101 : case SVXDATEFORMAT_STDBIG: ;
2102 : case SVXDATEFORMAT_F: // Tuesday, 13.February 1996
2103 0 : eDateFormat = eCurDateFormat;
2104 0 : break;
2105 : default:
2106 0 : break;
2107 : }
2108 : case SVXDATEFORMAT_C: ; // 13.Feb 1996
2109 : case SVXDATEFORMAT_D: // 13.February 1996
2110 0 : switch( eCurDateFormat )
2111 : {
2112 : case SVXDATEFORMAT_E: ; // Tue, 13.February 1996
2113 : case SVXDATEFORMAT_STDBIG: ;
2114 : case SVXDATEFORMAT_F: // Tuesday, 13.February 1996
2115 0 : eDateFormat = eCurDateFormat;
2116 0 : break;
2117 : default:
2118 0 : break;
2119 : }
2120 0 : break;
2121 : default:
2122 0 : break;
2123 : }
2124 : }
2125 : // Independently of the date format, we always put all these characters by default.
2126 : // They should be enough to cover every time format.
2127 0 : aRepresentation += "0123456789.:/-APM";
2128 :
2129 0 : if( eDateFormat )
2130 : {
2131 0 : String sDate;
2132 0 : LanguageType eLang = pInfo->GetOutliner()->GetLanguage( pInfo->GetPara(), pInfo->GetPos() );
2133 0 : SvNumberFormatter * pNumberFormatter = new SvNumberFormatter( ::comphelper::getProcessComponentContext(), LANGUAGE_SYSTEM );
2134 : // We always collect the characters obtained by using the SVXDATEFORMAT_B (as: 13.02.1996)
2135 : // so we are sure to include any unusual day|month|year separator.
2136 0 : Date aDate( 1, 1, 1996 );
2137 0 : sDate += SvxDateField::GetFormatted( aDate, SVXDATEFORMAT_B, *pNumberFormatter, eLang );
2138 0 : switch( eDateFormat )
2139 : {
2140 : case SVXDATEFORMAT_E: ; // Tue, 13.February 1996
2141 : case SVXDATEFORMAT_STDBIG: ;
2142 : case SVXDATEFORMAT_F: // Tuesday, 13.February 1996
2143 0 : for( sal_uInt16 i = 1; i <= 7; ++i ) // we get all days in a week
2144 : {
2145 0 : aDate.SetDay( i );
2146 0 : sDate += SvxDateField::GetFormatted( aDate, eDateFormat, *pNumberFormatter, eLang );
2147 : }
2148 : // No break here! We need months too!
2149 : case SVXDATEFORMAT_C: ; // 13.Feb 1996
2150 : case SVXDATEFORMAT_D: // 13.February 1996
2151 0 : for( sal_uInt16 i = 1; i <= 12; ++i ) // we get all months in a year
2152 : {
2153 0 : aDate.SetMonth( i );
2154 0 : sDate += SvxDateField::GetFormatted( aDate, eDateFormat, *pNumberFormatter, eLang );
2155 : }
2156 0 : break;
2157 : case SVXDATEFORMAT_STDSMALL: ;
2158 : case SVXDATEFORMAT_A: ; // 13.02.96
2159 : case SVXDATEFORMAT_B: ; // 13.02.1996
2160 : default:
2161 : // nothing to do here, we always collect the characters needed for these cases.
2162 0 : break;
2163 : }
2164 0 : aRepresentation += sDate;
2165 : }
2166 : }
2167 : }
2168 0 : else if( pField->GetClassId() == text::textfield::Type::PAGE )
2169 : {
2170 0 : switch( mVisiblePagePropSet.nPageNumberingType )
2171 : {
2172 : case SVX_CHARS_UPPER_LETTER:
2173 0 : aRepresentation += "QWERTYUIOPASDFGHJKLZXCVBNM";
2174 0 : break;
2175 : case SVX_CHARS_LOWER_LETTER:
2176 0 : aRepresentation += "qwertyuiopasdfghjklzxcvbnm";
2177 0 : break;
2178 : case SVX_ROMAN_UPPER:
2179 0 : aRepresentation += "IVXLCDM";
2180 0 : break;
2181 : case SVX_ROMAN_LOWER:
2182 0 : aRepresentation += "ivxlcdm";
2183 0 : break;
2184 : // arabic numbering type is the default
2185 : case SVX_ARABIC: ;
2186 : // in case the numbering type is not handled we fall back on arabic numbering
2187 : default:
2188 0 : aRepresentation += "0123456789";
2189 0 : break;
2190 : }
2191 : }
2192 : else
2193 : {
2194 0 : bFieldProcessed = sal_False;
2195 : }
2196 0 : if( bFieldProcessed )
2197 : {
2198 0 : if( pCharSet != NULL )
2199 : {
2200 0 : UCharSet::const_iterator aChar = pCharSet->begin();
2201 0 : for( ; aChar != pCharSet->end(); ++aChar )
2202 : {
2203 0 : aRepresentation += OUString::valueOf( *aChar );
2204 : }
2205 : }
2206 0 : pInfo->SetRepresentation( aRepresentation );
2207 : }
2208 : }
2209 : else
2210 : {
2211 0 : bFieldProcessed = sal_False;
2212 : }
2213 : }
2214 : else // single page case
2215 : {
2216 0 : if( mVisiblePagePropSet.bAreBackgroundObjectsVisible )
2217 : {
2218 0 : const SvxFieldData* pField = pInfo->GetField().GetField();
2219 0 : if( ( pField->GetClassId() == text::textfield::Type::PRESENTATION_HEADER ) && mVisiblePagePropSet.bIsHeaderFieldVisible )
2220 : {
2221 0 : aRepresentation += mVisiblePagePropSet.sHeaderText;
2222 : }
2223 0 : else if( ( pField->GetClassId() == text::textfield::Type::PRESENTATION_FOOTER ) && mVisiblePagePropSet.bIsFooterFieldVisible )
2224 : {
2225 0 : aRepresentation += mVisiblePagePropSet.sFooterText;
2226 : }
2227 0 : else if( ( pField->GetClassId() == text::textfield::Type::PRESENTATION_DATE_TIME ) && mVisiblePagePropSet.bIsDateTimeFieldVisible )
2228 : {
2229 : // TODO: implement the variable case
2230 0 : aRepresentation += mVisiblePagePropSet.sDateTimeText;
2231 : }
2232 0 : else if( ( pField->GetClassId() == text::textfield::Type::PAGE ) && mVisiblePagePropSet.bIsPageNumberFieldVisible )
2233 : {
2234 0 : sal_Int16 nPageNumber = mVisiblePagePropSet.nPageNumber;
2235 0 : switch( mVisiblePagePropSet.nPageNumberingType )
2236 : {
2237 : case SVX_CHARS_UPPER_LETTER:
2238 0 : aRepresentation += OUString::valueOf( (sal_Unicode)(char)( ( nPageNumber - 1 ) % 26 + 'A' ) );
2239 0 : break;
2240 : case SVX_CHARS_LOWER_LETTER:
2241 0 : aRepresentation += OUString::valueOf( (sal_Unicode)(char)( ( nPageNumber - 1 ) % 26 + 'a' ) );
2242 0 : break;
2243 : case SVX_ROMAN_UPPER:
2244 0 : aRepresentation += SvxNumberFormat::CreateRomanString( nPageNumber, true /* upper */ );
2245 0 : break;
2246 : case SVX_ROMAN_LOWER:
2247 0 : aRepresentation += SvxNumberFormat::CreateRomanString( nPageNumber, false /* lower */ );
2248 0 : break;
2249 : // arabic numbering type is the default
2250 : case SVX_ARABIC: ;
2251 : // in case the numbering type is not handled we fall back on arabic numbering
2252 : default:
2253 0 : aRepresentation += OUString::valueOf( sal_Int32(nPageNumber) );
2254 0 : break;
2255 : }
2256 : }
2257 : else
2258 : {
2259 0 : bFieldProcessed = sal_False;
2260 : }
2261 0 : if( bFieldProcessed )
2262 : {
2263 0 : pInfo->SetRepresentation( aRepresentation );
2264 : }
2265 : }
2266 :
2267 0 : }
2268 : }
2269 0 : return ( bFieldProcessed ? 0 : maOldFieldHdl.Call( pInfo ) );
2270 : }
2271 :
2272 : // -----------------------------------------------------------------------------
2273 :
2274 0 : void SVGExport::writeMtf( const GDIMetaFile& rMtf )
2275 : {
2276 0 : const Size aSize( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_MM ) );
2277 0 : rtl::OUString aAttr;
2278 0 : Reference< XExtendedDocumentHandler> xExtDocHandler( GetDocHandler(), UNO_QUERY );
2279 :
2280 0 : if( xExtDocHandler.is() )
2281 0 : xExtDocHandler->unknown( SVG_DTD_STRING );
2282 :
2283 0 : aAttr = rtl::OUString::valueOf( aSize.Width() );
2284 0 : aAttr += "mm";
2285 0 : AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
2286 :
2287 0 : aAttr = rtl::OUString::valueOf( aSize.Height() );
2288 0 : aAttr += "mm";
2289 0 : AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
2290 :
2291 0 : aAttr = "0 0 ";
2292 0 : aAttr += rtl::OUString::valueOf( aSize.Width() * 100L );
2293 0 : aAttr += " ";
2294 0 : aAttr += rtl::OUString::valueOf( aSize.Height() * 100L );
2295 0 : AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
2296 :
2297 : {
2298 0 : SvXMLElementExport aSVG( *this, XML_NAMESPACE_NONE, "svg", sal_True, sal_True );
2299 :
2300 0 : std::vector< ObjectRepresentation > aObjects;
2301 :
2302 0 : aObjects.push_back( ObjectRepresentation( Reference< XInterface >(), rMtf ) );
2303 0 : SVGFontExport aSVGFontExport( *this, aObjects );
2304 :
2305 0 : Point aPoint100thmm( OutputDevice::LogicToLogic( rMtf.GetPrefMapMode().GetOrigin(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
2306 0 : Size aSize100thmm( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
2307 :
2308 0 : SVGActionWriter aWriter( *this, aSVGFontExport );
2309 : aWriter.WriteMetaFile( aPoint100thmm, aSize100thmm, rMtf,
2310 0 : SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT, NULL );
2311 0 : }
2312 0 : }
2313 :
2314 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|