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