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