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