fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sd / source / filter / eppt / eppt.cxx
blobdc0593837b2a576c765c24202211e284c96b9886
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <eppt.hxx>
21 #include "epptdef.hxx"
22 #include <tools/globname.hxx>
23 #include <tools/poly.hxx>
24 #include <vcl/graph.hxx>
25 #include <vcl/bmpacc.hxx>
26 #include <vcl/gradient.hxx>
27 #include <rtl/ustring.hxx>
28 #include <tools/stream.hxx>
29 #include <vcl/fltcall.hxx>
30 #include <sfx2/docfile.hxx>
31 #include <svx/unoapi.hxx>
32 #include <svx/svdobj.hxx>
33 #include <svx/svdoole2.hxx>
34 #include <svx/svdmodel.hxx>
35 #include <svx/svdpage.hxx>
36 #include <com/sun/star/view/PaperOrientation.hpp>
37 #include <com/sun/star/view/PaperFormat.hpp>
38 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
39 #include <com/sun/star/office/XAnnotation.hpp>
40 #include <com/sun/star/office/XAnnotationAccess.hpp>
41 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
42 #include <com/sun/star/geometry/RealPoint2D.hpp>
43 #include <com/sun/star/util/DateTime.hpp>
44 #include <tools/zcodec.hxx>
45 #include <editeng/svxenum.hxx>
46 #include <sot/storinfo.hxx>
47 #include <filter/msfilter/msoleexp.hxx>
48 #include <vcl/virdev.hxx>
49 #include <vcl/wmf.hxx>
50 #include <filter/msfilter/msdffimp.hxx>
51 #include <filter/msfilter/svxmsbas.hxx>
52 #include <editeng/flditem.hxx>
53 #include <sfx2/docinf.hxx>
54 #include <oox/export/utils.hxx>
55 #include <oox/ole/olehelper.hxx>
56 #include <rtl/math.hxx>
58 using namespace com::sun::star;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::presentation;
62 using ::com::sun::star::beans::XPropertySet;
64 //============================ PPTWriter ==================================
66 PPTWriter::PPTWriter( SvStorageRef& rSvStorage,
67 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & rXModel,
68 ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > & rXStatInd,
69 SvMemoryStream* pVBA, sal_uInt32 nCnvrtFlags ) :
70 PPTWriterBase ( rXModel, rXStatInd ),
71 mnCnvrtFlags ( nCnvrtFlags ),
72 mbStatus ( sal_False ),
73 mbUseNewAnimations ( sal_True ),
74 mnLatestStatValue ( 0 ),
75 mrStg ( rSvStorage ),
76 mpCurUserStrm ( NULL ),
77 mpStrm ( NULL ),
78 mpPicStrm ( NULL ),
79 mpPptEscherEx ( NULL ),
80 mnVBAOleOfs ( 0 ),
81 mpVBA ( pVBA ),
82 mnExEmbed ( 0 ),
83 mpExEmbed ( new SvMemoryStream ),
84 mnPagesWritten ( 0 ),
85 mnTxId ( 0x7a2f64 )
89 void PPTWriter::exportPPTPre( const std::vector< com::sun::star::beans::PropertyValue >& rMediaData )
91 if ( !mrStg.Is() )
92 return;
94 // master pages + slides and notes + notes master page
95 mnDrawings = mnMasterPages + ( mnPages << 1 ) + 1;
97 if ( mXStatusIndicator.is() )
99 mbStatusIndicator = sal_True;
100 mnStatMaxValue = ( mnPages + mnMasterPages ) * 5;
101 mXStatusIndicator->start( OUString( "PowerPoint Export" ), mnStatMaxValue + ( mnStatMaxValue >> 3 ) );
104 SvGlobalName aGName( 0x64818d10L, 0x4f9b, 0x11cf, 0x86, 0xea, 0x00, 0xaa, 0x00, 0xb9, 0x29, 0xe8 );
105 mrStg->SetClass( aGName, 0, OUString("MS PowerPoint 97") );
107 if ( !ImplCreateCurrentUserStream() )
108 return;
110 mpStrm = mrStg->OpenSotStream( OUString( "PowerPoint Document" ) );
111 if ( !mpStrm )
112 return;
114 if ( !mpPicStrm )
115 mpPicStrm = mrStg->OpenSotStream( OUString( "Pictures" ) );
117 for (std::vector< com::sun::star::beans::PropertyValue >::const_iterator aIter( rMediaData.begin() ), aEnd( rMediaData.end() );
118 aIter != aEnd ; ++aIter)
120 if ( (*aIter).Name == "BaseURI" )
122 (*aIter).Value >>= maBaseURI;
123 break;
126 mpPptEscherEx = new PptEscherEx( *mpStrm, maBaseURI );
129 void PPTWriter::exportPPTPost( )
131 if ( !ImplCloseDocument() )
132 return;
134 if ( mbStatusIndicator )
136 mXStatusIndicator->setText( OUString( "PowerPoint Export" ) );
137 sal_uInt32 nValue = mnStatMaxValue + ( mnStatMaxValue >> 3 );
138 if ( nValue > mnLatestStatValue )
140 mXStatusIndicator->setValue( nValue );
141 mnLatestStatValue = nValue;
145 ImplWriteOLE();
147 ImplWriteVBA();
149 if ( !ImplWriteAtomEnding() )
150 return;
152 if ( !ImplCreateDocumentSummaryInformation() )
153 return;
155 mbStatus = sal_True;
158 // ---------------------------------------------------------------------------------------------
160 void ImplExportComments( uno::Reference< drawing::XDrawPage > xPage, SvMemoryStream& rBinaryTagData10Atom );
162 void PPTWriter::ImplWriteSlide( sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 nMode,
163 sal_Bool bHasBackground, Reference< XPropertySet > aXBackgroundPropSet )
165 Any aAny;
167 const PHLayout& rLayout = GetLayout( mXPagePropSet );
168 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_Slide | nPageNum, mpStrm->Tell() );
169 mpPptEscherEx->OpenContainer( EPP_Slide );
170 mpPptEscherEx->AddAtom( 24, EPP_SlideAtom, 2 );
171 *mpStrm << rLayout.nLayout;
172 mpStrm->Write( rLayout.nPlaceHolder, 8 ); // placeholderIDs (8 parts)
173 *mpStrm << (sal_uInt32)(nMasterNum | 0x80000000)// master ID (equals 0x80000000 on a master page)
174 << (sal_uInt32)nPageNum + 0x100 // notes ID (equals null if no notes are present)
175 << nMode
176 << (sal_uInt16)0; // padword
178 mnDiaMode = 0;
179 sal_Bool bVisible = sal_True;
180 ::com::sun::star::presentation::FadeEffect eFe = ::com::sun::star::presentation::FadeEffect_NONE;
182 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "Visible" ) ) )
183 aAny >>= bVisible;
184 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "Change" ) ) )
186 switch ( *(sal_Int32*)aAny.getValue() )
188 case 1 : // automatic
189 mnDiaMode++;
190 case 2 : // semi-automatic
191 mnDiaMode++;
192 default :
193 case 0 : // manual
194 break;
197 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "Effect" ) ) )
198 aAny >>= eFe;
200 sal_uInt32 nSoundRef = 0;
201 sal_Bool bIsSound = sal_False;
202 sal_Bool bStopSound = sal_False;
203 sal_Bool bLoopSound = sal_False;
205 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "Sound" ) ) )
207 OUString aSoundURL;
208 if ( aAny >>= aSoundURL )
210 nSoundRef = maSoundCollection.GetId( aSoundURL );
211 bIsSound = sal_True;
213 else
214 aAny >>= bStopSound;
216 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "LoopSound" ) ) )
217 aAny >>= bLoopSound;
219 sal_Bool bNeedsSSSlideInfoAtom = ( bVisible == sal_False )
220 || ( mnDiaMode == 2 )
221 || ( bIsSound )
222 || ( bStopSound )
223 || ( eFe != ::com::sun::star::presentation::FadeEffect_NONE );
224 if ( bNeedsSSSlideInfoAtom )
226 sal_uInt8 nDirection = 0;
227 sal_uInt8 nTransitionType = 0;
228 sal_uInt16 nBuildFlags = 1; // advange by mouseclick
229 sal_Int32 nSlideTime = 0; // still has to !!!
230 sal_uInt8 nSpeed = 1;
232 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "Speed" ) ) )
234 ::com::sun::star::presentation::AnimationSpeed aAs;
235 aAny >>= aAs;
236 nSpeed = (sal_uInt8)aAs;
238 sal_Int16 nTT = 0;
239 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "TransitionType" ) )
240 && ( aAny >>= nTT ) )
242 sal_Int16 nTST = 0;
243 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "TransitionSubtype" ) )
244 && ( aAny >>= nTST ) )
245 nTransitionType = GetTransition( nTT, nTST, eFe, nDirection );
248 if ( !nTransitionType )
249 nTransitionType = GetTransition( eFe, nDirection );
250 if ( mnDiaMode == 2 ) // automatic ?
251 nBuildFlags |= 0x400;
252 if ( bVisible == sal_False )
253 nBuildFlags |= 4;
254 if ( bIsSound )
255 nBuildFlags |= 16;
256 if ( bLoopSound )
257 nBuildFlags |= 64;
258 if ( bStopSound )
259 nBuildFlags |= 256;
261 if ( GetPropertyValue( aAny, mXPagePropSet, OUString( "Duration" ) ) )// duration of this slide
262 nSlideTime = *(sal_Int32*)aAny.getValue() << 10; // in ticks
264 mpPptEscherEx->AddAtom( 16, EPP_SSSlideInfoAtom );
265 *mpStrm << nSlideTime // standtime in ticks
266 << nSoundRef
267 << nDirection
268 << nTransitionType
269 << nBuildFlags
270 << nSpeed
271 << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0;
274 ImplCreateHeaderFooters( mXPagePropSet );
276 EscherSolverContainer aSolverContainer;
277 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
278 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
279 mpPptEscherEx->EnterGroup(0,0);
280 ImplWritePage( rLayout, aSolverContainer, NORMAL, sal_False, nPageNum ); // the shapes of the pages are created in the PPT document
281 mpPptEscherEx->LeaveGroup();
283 if ( bHasBackground )
284 ImplWriteBackground( aXBackgroundPropSet );
285 else
287 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
288 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, 0xc00 ); // Flags: Connector | Background | HasSpt
289 EscherPropertyContainer aPropOpt;
290 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, PPTtoEMU( maDestPageSize.Width ) );
291 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, PPTtoEMU( maDestPageSize.Width ) );
292 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
293 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
294 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_wDontShow );
295 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 ); // if true, this is the background shape
296 aPropOpt.Commit( *mpStrm );
297 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
300 aSolverContainer.WriteSolver( *mpStrm );
302 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
303 mpPptEscherEx->CloseContainer(); // EPP_Drawing
304 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
305 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0x99cc00 << (sal_uInt32)0xcc3333 << (sal_uInt32)0xffcccc << (sal_uInt32)0xb2b2b2;
307 SvMemoryStream aBinaryTagData10Atom;
308 ImplExportComments( mXDrawPage, aBinaryTagData10Atom );
309 if ( mbUseNewAnimations )
311 SvMemoryStream amsofbtAnimGroup;
312 ppt::AnimationExporter aExporter( aSolverContainer, maSoundCollection );
313 aExporter.doexport( mXDrawPage, amsofbtAnimGroup );
314 sal_uInt32 nmsofbtAnimGroupSize = amsofbtAnimGroup.Tell();
315 if ( nmsofbtAnimGroupSize )
318 EscherExAtom aMagic2( aBinaryTagData10Atom, 0x2eeb );
319 aBinaryTagData10Atom << (sal_uInt32)0x01c45df9
320 << (sal_uInt32)0xe1471b30;
323 EscherExAtom aMagic( aBinaryTagData10Atom, 0x2b00 );
324 aBinaryTagData10Atom << (sal_uInt32)0;
326 aBinaryTagData10Atom.Write( amsofbtAnimGroup.GetData(), amsofbtAnimGroup.Tell() );
328 EscherExContainer aMagic2( aBinaryTagData10Atom, 0x2b02 );
332 if ( aBinaryTagData10Atom.Tell() )
334 EscherExContainer aProgTags ( *mpStrm, EPP_ProgTags );
335 EscherExContainer aProgBinaryTag( *mpStrm, EPP_ProgBinaryTag );
337 EscherExAtom aCString( *mpStrm, EPP_CString );
338 *mpStrm << (sal_uInt32)0x5f005f
339 << (sal_uInt32)0x50005f
340 << (sal_uInt32)0x540050
341 << (sal_uInt16)0x31
342 << (sal_uInt16)0x30;
345 EscherExAtom aBinaryTagData( *mpStrm, EPP_BinaryTagData );
346 mpStrm->Write( aBinaryTagData10Atom.GetData(), aBinaryTagData10Atom.Tell() );
349 mpPptEscherEx->CloseContainer(); // EPP_Slide
352 // ---------------------------------------------------------------------------------------------
354 void PPTWriter::ImplWriteSlideMaster( sal_uInt32 nPageNum, Reference< XPropertySet > aXBackgroundPropSet )
356 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_MainMaster | nPageNum, mpStrm->Tell() );
357 mpPptEscherEx->OpenContainer( EPP_MainMaster );
358 mpPptEscherEx->AddAtom( 24, EPP_SlideAtom, 2 );
359 *mpStrm << (sal_Int32)EPP_LAYOUT_TITLEANDBODYSLIDE // slide layout -> title and body slide
360 << (sal_uInt8)1 << (sal_uInt8)2 << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0 // placeholderID
361 << (sal_uInt32)0 // master ID (equals null at a master page)
362 << (sal_uInt32)0 // notes ID (equals null if no notes are present)
363 << (sal_uInt16)0 // Bit 1: Follow master objects, Bit 2: Follow master scheme, Bit 3: Follow master background
364 << (sal_uInt16)0; // padword
366 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
367 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0x99cc00 << (sal_uInt32)0xcc3333 << (sal_uInt32)0xffcccc << (sal_uInt32)0xb2b2b2;
368 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
369 *mpStrm << (sal_uInt32)0xff0000 << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x00ffff << (sal_uInt32)0x0099ff << (sal_uInt32)0xffff00 << (sal_uInt32)0x0000ff << (sal_uInt32)0x969696;
370 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
371 *mpStrm << (sal_uInt32)0xccffff << (sal_uInt32)0x000000 << (sal_uInt32)0x336666 << (sal_uInt32)0x008080 << (sal_uInt32)0x339933 << (sal_uInt32)0x000080 << (sal_uInt32)0xcc3300 << (sal_uInt32)0x66ccff;
372 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
373 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x333333 << (sal_uInt32)0x000000 << (sal_uInt32)0xdddddd << (sal_uInt32)0x808080 << (sal_uInt32)0x4d4d4d << (sal_uInt32)0xeaeaea;
374 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
375 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0x66ccff << (sal_uInt32)0xff0000 << (sal_uInt32)0xcc00cc << (sal_uInt32)0xc0c0c0;
376 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
377 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0xc0c0c0 << (sal_uInt32)0xff6600 << (sal_uInt32)0x0000ff << (sal_uInt32)0x009900;
378 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
379 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0xff9933 << (sal_uInt32)0xccff99 << (sal_uInt32)0xcc00cc << (sal_uInt32)0xb2b2b2;
381 for ( int nInstance = EPP_TEXTTYPE_Title; nInstance <= EPP_TEXTTYPE_QuarterBody; nInstance++ )
383 if ( nInstance == EPP_TEXTTYPE_notUsed )
384 continue;
386 // the auto color is dependent to the page background,so we have to set a page that is in the right context
387 if ( nInstance == EPP_TEXTTYPE_Notes )
388 GetPageByIndex( 0, NOTICE );
389 else
390 GetPageByIndex( 0, MASTER );
392 mpPptEscherEx->BeginAtom();
394 sal_Bool bFirst = sal_True;
395 sal_Bool bSimpleText = sal_False;
397 *mpStrm << (sal_uInt16)5; // paragraph count
399 for ( sal_uInt16 nLev = 0; nLev < 5; nLev++ )
401 if ( nInstance >= EPP_TEXTTYPE_CenterBody )
403 bFirst = sal_False;
404 bSimpleText = sal_True;
405 *mpStrm << nLev;
407 mpStyleSheet->mpParaSheet[ nInstance ]->Write( *mpStrm, mpPptEscherEx, nLev, bFirst, bSimpleText, mXPagePropSet );
408 mpStyleSheet->mpCharSheet[ nInstance ]->Write( *mpStrm, mpPptEscherEx, nLev, bFirst, bSimpleText, mXPagePropSet );
409 bFirst = sal_False;
411 mpPptEscherEx->EndAtom( EPP_TxMasterStyleAtom, 0, nInstance );
413 GetPageByIndex( nPageNum, MASTER );
415 EscherSolverContainer aSolverContainer;
417 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
418 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
420 mpPptEscherEx->EnterGroup(0,0);
421 ImplWritePage( GetLayout( 0 ), aSolverContainer, MASTER, sal_True ); // the shapes of the pages are created in the PPT document
422 mpPptEscherEx->LeaveGroup();
424 ImplWriteBackground( aXBackgroundPropSet );
426 aSolverContainer.WriteSolver( *mpStrm );
428 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
429 mpPptEscherEx->CloseContainer(); // EPP_Drawing
430 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
431 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0x99cc00 << (sal_uInt32)0xcc3333 << (sal_uInt32)0xffcccc << (sal_uInt32)0xb2b2b2;
433 if ( aBuExMasterStream.Tell() )
435 ImplProgTagContainer( mpStrm, &aBuExMasterStream );
437 mpPptEscherEx->CloseContainer(); // EPP_MainMaster
440 // ---------------------------------------------------------------------------------------------
442 PPTWriter::~PPTWriter()
444 delete mpExEmbed;
445 delete mpPptEscherEx;
446 delete mpCurUserStrm;
447 delete mpPicStrm;
448 delete mpStrm;
450 std::vector< PPTExStyleSheet* >::iterator aStyleSheetIter( maStyleSheetList.begin() );
451 while( aStyleSheetIter < maStyleSheetList.end() )
452 delete *aStyleSheetIter++;
454 for ( std::vector<PPTExOleObjEntry*>::const_iterator it = maExOleObj.begin(); it != maExOleObj.end(); ++it )
455 delete *it;
457 if ( mbStatusIndicator )
458 mXStatusIndicator->end();
461 // ---------------------------------------------------------------------------------------------
463 sal_Bool PPTWriter::ImplCreateCurrentUserStream()
465 mpCurUserStrm = mrStg->OpenSotStream( OUString( "Current User" ) );
466 if ( !mpCurUserStrm )
467 return sal_False;
468 char pUserName[] = "Current User";
469 sal_uInt32 nLenOfUserName = strlen( pUserName );
470 sal_uInt32 nSizeOfRecord = 0x14 + ( ( nLenOfUserName + 4 ) & ~ 3 );
472 *mpCurUserStrm << (sal_uInt16)0 << (sal_uInt16)EPP_CurrentUserAtom << nSizeOfRecord;
473 *mpCurUserStrm << (sal_uInt32)0x14 // Len
474 << (sal_uInt32)0xe391c05f; // Magic
476 sal_uInt32 nEditPos = mpCurUserStrm->Tell();
477 *mpCurUserStrm << (sal_uInt32)0x0 // OffsetToCurrentEdit;
478 << (sal_uInt16)nLenOfUserName //
479 << (sal_uInt16)0x3f4 // DocFileVersion
480 << (sal_uInt8)3 // MajorVersion
481 << (sal_uInt8)0 // MinorVersion
482 << (sal_uInt16)0; // Pad Word
483 pUserName[ nLenOfUserName ] = 8;
484 mpCurUserStrm->Write( pUserName, nLenOfUserName + 1 );
485 for ( sal_uInt32 i = 0x15 + nLenOfUserName; i < nSizeOfRecord; i++ )
487 *mpCurUserStrm << (sal_uInt8)0; // pad bytes
489 mpCurUserStrm->Seek( nEditPos );
490 return sal_True;
493 // ---------------------------------------------------------------------------------------------
495 sal_Bool PPTWriter::ImplCreateDocumentSummaryInformation()
497 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
498 mXModel, uno::UNO_QUERY_THROW);
499 uno::Reference<document::XDocumentProperties> xDocProps(
500 xDPS->getDocumentProperties());
502 if (xDocProps.is()) {
504 // no idea what this is...
505 static sal_uInt8 aGuid[ 0x52 ] =
507 0x4e, 0x00, 0x00, 0x00,
508 '{',0,'D',0,'B',0,'1',0,'A',0,'C',0,'9',0,'6',0,'4',0,'-',0,
509 'E',0,'3',0,'9',0,'C',0,'-',0,'1',0,'1',0,'D',0,'2',0,'-',0,
510 'A',0,'1',0,'E',0,'F',0,'-',0,'0',0,'0',0,'6',0,'0',0,'9',0,
511 '7',0,'D',0,'A',0,'5',0,'6',0,'8',0,'9',0,'}',0
513 uno::Sequence<sal_uInt8> aGuidSeq(aGuid, 0x52);
515 SvMemoryStream aHyperBlob;
516 ImplCreateHyperBlob( aHyperBlob );
518 uno::Sequence<sal_uInt8> aHyperSeq(aHyperBlob.Tell());
519 const sal_uInt8* pBlob(
520 static_cast<const sal_uInt8*>(aHyperBlob.GetData()));
521 for (sal_Int32 j = 0; j < aHyperSeq.getLength(); ++j) {
522 aHyperSeq[j] = pBlob[j];
525 if ( mnCnvrtFlags & 0x8000 )
527 uno::Sequence<sal_uInt8> aThumbSeq;
528 if ( GetPageByIndex( 0, NORMAL ) && ImplGetPropertyValue( mXPagePropSet, OUString( "PreviewBitmap" ) ) )
530 aThumbSeq =
531 *static_cast<const uno::Sequence<sal_uInt8>*>(mAny.getValue());
533 sfx2::SaveOlePropertySet( xDocProps, mrStg,
534 &aThumbSeq, &aGuidSeq, &aHyperSeq);
536 else
538 sfx2::SaveOlePropertySet( xDocProps, mrStg,
539 NULL, &aGuidSeq, &aHyperSeq );
543 return sal_True;
546 // ---------------------------------------------------------------------------------------------
548 void PPTWriter::ImplWriteExtParaHeader( SvMemoryStream& rSt, sal_uInt32 nRef, sal_uInt32 nInstance, sal_uInt32 nSlideId )
550 if ( rSt.Tell() )
552 aBuExOutlineStream << (sal_uInt32)( ( EPP_PST_ExtendedParagraphHeaderAtom << 16 )
553 | ( nRef << 4 ) )
554 << (sal_uInt32)8
555 << (sal_uInt32)nSlideId
556 << (sal_uInt32)nInstance;
557 aBuExOutlineStream.Write( rSt.GetData(), rSt.Tell() );
561 // ---------------------------------------------------------------------------------------------
563 void PPTWriter::ImplCreateHeaderFooterStrings( SvStream& rStrm, ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rXPagePropSet )
565 if ( rXPagePropSet.is() )
567 OUString aString;
568 ::com::sun::star::uno::Any aAny;
569 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "HeaderText" ), sal_True ) )
571 if ( aAny >>= aString )
572 PPTWriter::WriteCString( rStrm, aString, 1 );
574 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "FooterText" ), sal_True ) )
576 if ( aAny >>= aString )
577 PPTWriter::WriteCString( rStrm, aString, 2 );
579 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "DateTimeText" ), sal_True ) )
581 if ( aAny >>= aString )
582 PPTWriter::WriteCString( rStrm, aString, 0 );
587 // ---------------------------------------------------------------------------------------------
589 void PPTWriter::ImplCreateHeaderFooters( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rXPagePropSet )
591 if ( rXPagePropSet.is() )
593 sal_Bool bVal = sal_False;
594 sal_uInt32 nVal = 0;
595 ::com::sun::star::uno::Any aAny;
596 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "IsHeaderVisible" ), sal_True ) )
598 if ( ( aAny >>= bVal ) && bVal )
599 nVal |= 0x100000;
601 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "IsFooterVisible" ), sal_True ) )
603 if ( ( aAny >>= bVal ) && bVal )
604 nVal |= 0x200000;
606 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "IsDateTimeVisible" ), sal_True ) )
608 if ( ( aAny >>= bVal ) && bVal )
609 nVal |= 0x010000;
611 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "IsPageNumberVisible" ), sal_True ) )
613 if ( ( aAny >>= bVal ) && bVal )
614 nVal |= 0x080000;
616 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "IsDateTimeFixed" ), sal_True ) )
618 if ( ( aAny >>= bVal ) && !bVal )
619 nVal |= 0x20000;
620 else
621 nVal |= 0x40000;
623 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, OUString( "DateTimeFormat" ), sal_True ) )
625 sal_Int32 nFormat = *(sal_Int32*)aAny.getValue();
626 SvxDateFormat eDateFormat = (SvxDateFormat)( nFormat & 0xf );
627 SvxTimeFormat eTimeFormat = (SvxTimeFormat)( ( nFormat >> 4 ) & 0xf );
628 switch( eDateFormat )
630 case SVXDATEFORMAT_F :
631 nFormat = 1;
632 break;
633 case SVXDATEFORMAT_D :
634 nFormat = 2;
635 break;
636 case SVXDATEFORMAT_C :
637 nFormat = 4;
638 break;
639 default:
640 case SVXDATEFORMAT_A :
641 nFormat = 0;
643 switch( eTimeFormat )
645 case SVXTIMEFORMAT_24_HM :
646 nFormat = 9;
647 break;
648 case SVXTIMEFORMAT_12_HM :
649 nFormat = 11;
650 break;
651 case SVXTIMEFORMAT_24_HMS :
652 nFormat = 10;
653 break;
654 case SVXTIMEFORMAT_12_HMS :
655 nFormat = 12;
656 break;
657 default:
658 break;
660 nVal |= nFormat;
663 mpPptEscherEx->OpenContainer( EPP_HeadersFooters, 0 );
664 mpPptEscherEx->AddAtom( 4, EPP_HeadersFootersAtom );
665 *mpStrm << nVal;
666 ImplCreateHeaderFooterStrings( *mpStrm, rXPagePropSet );
667 mpPptEscherEx->CloseContainer();
671 // ---------------------------------------------------------------------------------------------
673 sal_Bool PPTWriter::ImplCreateDocument()
675 sal_uInt32 i;
676 sal_uInt16 nSlideType = EPP_SLIDESIZE_TYPECUSTOM;
678 sal_uInt32 nWidth = maDestPageSize.Width;
679 sal_uInt32 nHeight = maDestPageSize.Height;
681 if ( ( nWidth == 0x1680 ) && ( nHeight == 0x10e0 ) )
682 nSlideType = EPP_SLIDESIZE_TYPEONSCREEN;
683 else if ( ( nWidth == 0x1200 ) && ( nHeight == 0x240 ) )
684 nSlideType = EPP_SLIDESIZE_TYPEBANNER;
685 else if ( ( nWidth == 0x1950 ) && ( nHeight == 0x10e0 ) )
686 nSlideType = EPP_SLIDESIZE_TYPE35MM;
687 else if ( ( nWidth == 0x1860 ) && ( nHeight == 0x10e0 ) )
688 nSlideType = EPP_SLIDESIZE_TYPEA4PAPER;
690 mpPptEscherEx->OpenContainer( EPP_Document );
691 // CREATE DOCUMENT ATOM
692 mpPptEscherEx->AddAtom( 40, EPP_DocumentAtom, 1 );
693 *mpStrm << nWidth // Slide Size in Master coordinates X
694 << nHeight // " " " " " Y
695 << (sal_Int32)maNotesPageSize.Width // Notes Page Size X
696 << (sal_Int32)maNotesPageSize.Height // " " " Y
697 << (sal_Int32)1 << (sal_Int32)2; // the scale used when the Powerpoint document is embedded. the default is 1:2
698 mpPptEscherEx->InsertPersistOffset( EPP_MAINNOTESMASTER_PERSIST_KEY, mpStrm->Tell() );
699 *mpStrm << (sal_uInt32)0 // Reference to NotesMaster ( 0 if none );
700 << (sal_uInt32)0 // Reference to HandoutMaster ( 0 if none );
701 << (sal_Int16)1 // Number of the first slide;
702 << nSlideType // Size of the document slides ( default: EPP_SLIDESIZETYPEONSCREEN )
703 << (sal_uInt8)0 // bool1 indicates if document was saved with embedded true type fonts
704 << (sal_uInt8)0 // bool1 indicates if the placeholders on the title slide are omitted
705 << (sal_uInt8)0 // bool1 right to left ( flag for Bidi version )
706 << (sal_uInt8)1; // bool1 visibility of comments shapes
708 mpPptEscherEx->PtInsert( EPP_Persist_Document, mpStrm->Tell() );
710 mpPptEscherEx->OpenContainer( EPP_HeadersFooters, 3 ); //Master footer (default)
711 mpPptEscherEx->AddAtom( 4, EPP_HeadersFootersAtom );
712 *mpStrm << (sal_uInt32)0x25000d;
713 if ( GetPageByIndex( 0, MASTER ) )
714 ImplCreateHeaderFooterStrings( *mpStrm, mXPagePropSet );
715 mpPptEscherEx->CloseContainer();
716 mpPptEscherEx->OpenContainer( EPP_HeadersFooters, 4 ); //NotesMaster footer (default)
717 mpPptEscherEx->AddAtom( 4, EPP_HeadersFootersAtom );
718 *mpStrm << (sal_uInt32)0x3d000d;
719 if ( GetPageByIndex( 0, NOTICE ) )
720 ImplCreateHeaderFooterStrings( *mpStrm, mXPagePropSet );
721 mpPptEscherEx->CloseContainer();
723 mpPptEscherEx->OpenContainer( EPP_SlideListWithText ); // animation information for the slides
725 for ( i = 0; i < mnPages; i++ )
727 mpPptEscherEx->AddAtom( 20, EPP_SlidePersistAtom );
728 mpPptEscherEx->InsertPersistOffset( EPP_MAINSLIDE_PERSIST_KEY | i, mpStrm->Tell() );
729 *mpStrm << (sal_uInt32)0 // psrReference - logical reference to the slide persist object ( EPP_MAINSLIDE_PERSIST_KEY )
730 << (sal_uInt32)4 // flags - only bit 3 used, if set then slide contains shapes other than placeholders
731 << (sal_Int32)0 // numberTexts - number of placeholder texts stored with the persist object. Allows to display outline view without loading the slide persist objects
732 << (sal_Int32)i + 0x100 // slideId - Unique slide identifier, used for OLE link monikers for example
733 << (sal_uInt32)0; // reserved, usualy 0
735 if ( !GetPageByIndex( i, NORMAL ) ) // very exciting: once again through all pages
736 return sal_False;
737 SetCurrentStyleSheet( GetMasterIndex( NORMAL ) );
739 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNamed >
740 aXName( mXDrawPage, ::com::sun::star::uno::UNO_QUERY );
742 if ( aXName.is() )
743 maSlideNameList.push_back( aXName->getName() );
744 else
745 maSlideNameList.push_back( OUString() );
747 mpPptEscherEx->CloseContainer(); // EPP_SlideListWithText
749 mpPptEscherEx->OpenContainer( EPP_SlideListWithText, 2 ); // animation information for the notes
750 for( i = 0; i < mnPages; i++ )
752 mpPptEscherEx->AddAtom( 20, EPP_SlidePersistAtom );
753 mpPptEscherEx->InsertPersistOffset( EPP_MAINNOTES_PERSIST_KEY | i, mpStrm->Tell() );
754 *mpStrm << (sal_uInt32)0
755 << (sal_uInt32)4
756 << (sal_Int32)0
757 << (sal_Int32)i + 0x100
758 << (sal_uInt32)0;
760 mpPptEscherEx->CloseContainer(); // EPP_SlideListWithText
762 ::com::sun::star::uno::Reference< ::com::sun::star::presentation::XPresentationSupplier >
763 aXPresSupplier( mXModel, ::com::sun::star::uno::UNO_QUERY ); ;
764 if ( aXPresSupplier.is() )
766 ::com::sun::star::uno::Reference< ::com::sun::star::presentation::XPresentation >
767 aXPresentation( aXPresSupplier->getPresentation() );
768 if ( aXPresentation.is() )
770 mXPropSet = ::com::sun::star::uno::Reference<
771 ::com::sun::star::beans::XPropertySet >
772 ( aXPresentation, ::com::sun::star::uno::UNO_QUERY );
773 if ( mXPropSet.is() )
775 OUString aCustomShow;
776 sal_uInt32 nPenColor = 0x1000000;
777 sal_Int32 nRestartTime = 0x7fffffff;
778 sal_Int16 nStartSlide = 0;
779 sal_Int16 nEndSlide = 0;
780 sal_uInt32 nFlags = 0; // Bit 0: Auto advance
781 // Bit 1 Skip builds ( do not allow slide effects )
782 // Bit 2 Use slide range
783 // Bit 3 Use named show
784 // Bit 4 Browse mode on
785 // Bit 5 Kiosk mode on
786 // Bit 7 loop continously
787 // Bit ? show scrollbar
789 if ( ImplGetPropertyValue( OUString( "CustomShow" ) ) )
791 aCustomShow = ( *(OUString*)mAny.getValue() );
792 if ( !aCustomShow.isEmpty() )
794 nFlags |= 8;
797 if ( ( nFlags & 8 ) == 0 )
799 if ( ImplGetPropertyValue( OUString( "FirstPage" ) ) )
801 OUString aSlideName( *(OUString*)mAny.getValue() );
803 std::vector<OUString>::const_iterator pIter = std::find(
804 maSlideNameList.begin(),maSlideNameList.end(),aSlideName);
806 if (pIter != maSlideNameList.end())
808 nStartSlide = pIter - maSlideNameList.begin() + 1;
809 nFlags |= 4;
810 nEndSlide = (sal_uInt16)mnPages;
815 if ( ImplGetPropertyValue( OUString("IsAutomatic" ) ) )
817 sal_Bool bBool = sal_False;
818 mAny >>= bBool;
819 if ( !bBool )
820 nFlags |= 1;
823 if ( ImplGetPropertyValue( OUString( "IsEndless" ) ) ) // the correct name would be IsNotEndless: WTF?
825 sal_Bool bBool = sal_False;
826 mAny >>= bBool;
827 if ( bBool )
828 nFlags |= 0x80;
830 if ( ImplGetPropertyValue( OUString( "IsFullScreen" ) ) )
832 sal_Bool bBool = sal_False;
833 mAny >>= bBool;
834 if ( !bBool )
835 nFlags |= 0x11;
838 mpPptEscherEx->AddAtom( 80, EPP_SSDocInfoAtom, 1 );
839 *mpStrm << nPenColor << nRestartTime << nStartSlide << nEndSlide;
841 sal_uInt32 nCustomShowNameLen = aCustomShow.getLength();
842 if ( nCustomShowNameLen > 31 )
843 nCustomShowNameLen = 31;
844 if ( nCustomShowNameLen ) // named show identifier
846 const sal_Unicode* pCustomShow = aCustomShow.getStr();
847 for ( i = 0; i < nCustomShowNameLen; i++ )
849 *mpStrm << (sal_uInt16)( pCustomShow[ i ] );
852 for ( i = nCustomShowNameLen; i < 32; i++, *mpStrm << (sal_uInt16)0 ) ;
854 *mpStrm << nFlags;
855 ::com::sun::star::uno::Reference< ::com::sun::star::presentation::XCustomPresentationSupplier >
856 aXCPSup( mXModel, ::com::sun::star::uno::UNO_QUERY );
857 if ( aXCPSup.is() )
859 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >
860 aXCont( aXCPSup->getCustomPresentations() );
861 if ( aXCont.is() )
863 ::com::sun::star::uno::Sequence< OUString> aNameSeq( aXCont->getElementNames() );
864 const OUString* pUString = aNameSeq.getArray();
865 sal_uInt32 nCount = aNameSeq.getLength();
866 if ( nCount )
868 mpPptEscherEx->OpenContainer( EPP_NamedShows );
869 sal_uInt32 nCustomShowIndex = 0;
870 for( i = 0; i < nCount; i++ ) // number of custom shows
872 if ( !pUString[ i ].isEmpty() )
874 mpPptEscherEx->OpenContainer( EPP_NamedShow, nCustomShowIndex++ );
876 sal_uInt32 nNamedShowLen = pUString[ i ].getLength();
877 if ( nNamedShowLen > 31 )
878 nNamedShowLen = 31;
879 mpPptEscherEx->AddAtom( nNamedShowLen << 1, EPP_CString );
880 const sal_Unicode* pCustomShowName = pUString[ i ].getStr();
881 for ( sal_uInt32 k = 0; k < nNamedShowLen; *mpStrm << (sal_uInt16)( pCustomShowName[ k++ ] ) ) ;
882 mAny = aXCont->getByName( pUString[ i ] );
883 if ( mAny.getValue() )
886 ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > aXIC;
887 if ( mAny >>= aXIC )
889 mpPptEscherEx->BeginAtom();
891 sal_Int32 nSlideCount = aXIC->getCount();
892 for ( sal_Int32 j = 0; j < nSlideCount; j++ ) // number of slides
894 mAny = aXIC->getByIndex( j );
895 if ( mAny.getValue() )
897 ::com::sun::star::uno::Reference<
898 ::com::sun::star::drawing::XDrawPage > aXDrawPage;
899 if ( mAny >>= aXDrawPage )
901 ::com::sun::star::uno::Reference<
902 ::com::sun::star::container::XNamed >
903 aXName( aXDrawPage, ::com::sun::star::uno::UNO_QUERY );
904 if ( aXName.is() )
906 OUString aSlideName( aXName->getName() );
907 std::vector<OUString>::const_iterator pIter = std::find(
908 maSlideNameList.begin(),maSlideNameList.end(),aSlideName);
910 if (pIter != maSlideNameList.end())
912 sal_uInt32 nPageNumber = pIter - maSlideNameList.begin();
913 *mpStrm << (sal_uInt32)( nPageNumber + 0x100 ); // unique slide id
919 mpPptEscherEx->EndAtom( EPP_NamedShowSlides );
922 mpPptEscherEx->CloseContainer(); // EPP_NamedShow
925 mpPptEscherEx->CloseContainer(); // EPP_NamedShows
932 mpPptEscherEx->AddAtom( 0, EPP_EndDocument );
933 mpPptEscherEx->CloseContainer(); // EPP_Document
934 return sal_True;
937 // ---------------------------------------------------------------------------------------------
939 sal_Bool PPTWriter::ImplCreateHyperBlob( SvMemoryStream& rStrm )
941 sal_uInt32 nCurrentOfs, nParaOfs, nParaCount = 0;
943 nParaOfs = rStrm.Tell();
944 rStrm << (sal_uInt32)0; // property size
945 rStrm << (sal_uInt32)0; // property count
947 for ( std::vector<EPPTHyperlink>::const_iterator pIter = maHyperlink.begin(); pIter != maHyperlink.end(); ++pIter )
949 nParaCount += 6;
950 rStrm << (sal_uInt32)3 // Type VT_I4
951 << (sal_uInt32)7 // (VTI4 - Private1)
952 << (sal_uInt32)3 // Type VT_I4
953 << (sal_uInt32)6 // (VTI4 - Private2)
954 << (sal_uInt32)3 // Type VT_I4
955 << (sal_uInt32)0; // (VTI4 - Private3)
957 // INFO
958 // HIWORD: = 0 : do not change anything
959 // = 1 : replace the hyperlink with the target and subadress in the following two VTLPWSTR
960 // = 2 : delete the hyperlink
961 // LOWORD: = 0 : graphic shown as background (link)
962 // = 1 : graphic shown as shape (link)
963 // = 2 : graphic is used to fill a shape
964 // = 3 : graphic used to fill a shape outline (future use)
965 // = 4 : hyperlink attached to a shape
966 // = 5 : " " " " (Word) field
967 // = 6 : " " " " (Excel) range
968 // = 7 : " " " " (PPT) text range
969 // = 8 : " " " " (Project) task
971 sal_uInt32 nUrlLen = pIter->aURL.Len();
972 const sal_Unicode* pUrl = pIter->aURL.GetBuffer();
974 sal_uInt32 nInfo = 7;
976 rStrm << (sal_uInt32)3 // Type VT_I4
977 << nInfo; // Info
979 switch( pIter->nType & 0xff )
981 case 1 : // click action to slidenumber
983 rStrm << (sal_uInt32)0x1f << (sal_uInt32)1 << (sal_uInt32)0; // path
984 rStrm << (sal_uInt32)0x1f << (sal_uInt32)( nUrlLen + 1 );
985 for ( sal_uInt32 i = 0; i < nUrlLen; i++ )
987 rStrm << pUrl[ i ];
989 rStrm << (sal_uInt16)0;
991 break;
992 case 2 :
994 sal_uInt32 i;
996 rStrm << (sal_uInt32)0x1f
997 << (sal_uInt32)( nUrlLen + 1 );
998 for ( i = 0; i < nUrlLen; i++ )
1000 rStrm << pUrl[ i ];
1002 if ( ! ( i & 1 ) )
1003 rStrm << (sal_uInt16)0;
1004 rStrm << (sal_uInt16)0
1005 << (sal_uInt32)0x1f
1006 << (sal_uInt32)1
1007 << (sal_uInt32)0;
1009 break;
1012 nCurrentOfs = rStrm.Tell();
1013 rStrm.Seek( nParaOfs );
1014 rStrm << (sal_uInt32)( nCurrentOfs - ( nParaOfs + 4 ) );
1015 rStrm << nParaCount;
1016 rStrm.Seek( nCurrentOfs );
1017 return sal_True;
1020 // ---------------------------------------------------------------------------------------------
1022 sal_Bool PPTWriter::ImplCreateMainNotes()
1024 EscherSolverContainer aSolverContainer;
1026 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_MainNotes, mpStrm->Tell() );
1027 mpPptEscherEx->OpenContainer( EPP_Notes );
1028 mpPptEscherEx->AddAtom( 8, EPP_NotesAtom, 1 );
1029 *mpStrm << (sal_uInt32)0x80000001 // Number that identifies this slide
1030 << (sal_uInt32)0; // follow nothing
1031 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
1032 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
1033 mpPptEscherEx->EnterGroup(0,0);
1035 ImplWritePage( GetLayout( 20 ), aSolverContainer, NOTICE, sal_True );
1037 mpPptEscherEx->LeaveGroup();
1038 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1039 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, 0xc00 );
1040 EscherPropertyContainer aPropOpt;
1041 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0xffffff ); // stock valued fill color
1042 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1043 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, 0x68bdde );
1044 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, 0x8b9f8e );
1045 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
1046 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0 );
1047 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_wDontShow );
1048 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 ); // if true, this is the background shape
1049 aPropOpt.Commit( *mpStrm );
1050 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1052 aSolverContainer.WriteSolver( *mpStrm );
1054 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
1055 mpPptEscherEx->CloseContainer(); // EPP_Drawing
1056 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
1057 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0x99cc00 << (sal_uInt32)0xcc3333 << (sal_uInt32)0xffcccc << (sal_uInt32)0xb2b2b2;
1058 mpPptEscherEx->CloseContainer(); // EPP_Notes
1059 return sal_True;
1062 // ---------------------------------------------------------------------------------------------
1064 static OUString getInitials( const OUString& rName )
1066 OUString sInitials;
1068 const sal_Unicode * pStr = rName.getStr();
1069 sal_Int32 nLength = rName.getLength();
1071 while( nLength )
1073 // skip whitespace
1074 while( nLength && (*pStr <= ' ') )
1076 nLength--; pStr++;
1079 // take letter
1080 if( nLength )
1082 sInitials += OUString( *pStr );
1083 nLength--; pStr++;
1086 // skip letters until whitespace
1087 while( nLength && (*pStr > ' ') )
1089 nLength--; pStr++;
1093 return sInitials;
1096 void ImplExportComments( uno::Reference< drawing::XDrawPage > xPage, SvMemoryStream& rBinaryTagData10Atom )
1100 uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xPage, uno::UNO_QUERY_THROW );
1101 uno::Reference< office::XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() );
1103 sal_Int32 nIndex = 1;
1105 while( xAnnotationEnumeration->hasMoreElements() )
1107 EscherExContainer aComment10( rBinaryTagData10Atom, EPP_Comment10 );
1109 uno::Reference< office::XAnnotation > xAnnotation( xAnnotationEnumeration->nextElement() );
1111 geometry::RealPoint2D aRealPoint2D( xAnnotation->getPosition() );
1112 MapMode aMapDest( MAP_INCH, Point(), Fraction( 1, 576 ), Fraction( 1, 576 ) );
1113 Point aPoint( OutputDevice::LogicToLogic( Point( static_cast< sal_Int32 >( aRealPoint2D.X * 100.0 ),
1114 static_cast< sal_Int32 >( aRealPoint2D.Y * 100.0 ) ), MAP_100TH_MM, aMapDest ) );
1116 OUString sAuthor( xAnnotation->getAuthor() );
1117 uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
1118 OUString sText( xText->getString() );
1119 OUString sInitials( getInitials( sAuthor ) );
1120 util::DateTime aDateTime( xAnnotation->getDateTime() );
1121 if ( !sAuthor.isEmpty() )
1122 PPTWriter::WriteCString( rBinaryTagData10Atom, sAuthor, 0 );
1123 if ( !sText.isEmpty() )
1124 PPTWriter::WriteCString( rBinaryTagData10Atom, sText, 1 );
1125 if ( !sInitials.isEmpty() )
1126 PPTWriter::WriteCString( rBinaryTagData10Atom, sInitials, 2 );
1128 sal_Int16 nMilliSeconds = static_cast<sal_Int16>(::rtl::math::round(static_cast<double>(aDateTime.NanoSeconds) / 1000000000.0));
1129 EscherExAtom aCommentAtom10( rBinaryTagData10Atom, EPP_CommentAtom10 );
1130 rBinaryTagData10Atom << nIndex++
1131 << aDateTime.Year
1132 << aDateTime.Month
1133 << aDateTime.Day // todo: day of week
1134 << aDateTime.Day
1135 << aDateTime.Hours
1136 << aDateTime.Minutes
1137 << aDateTime.Seconds
1138 << nMilliSeconds
1139 << static_cast< sal_Int32 >( aPoint.X() )
1140 << static_cast< sal_Int32 >( aPoint.Y() );
1144 catch ( uno::Exception& )
1149 // ---------------------------------------------------------------------------------------------
1151 void PPTWriter::ImplWriteNotes( sal_uInt32 nPageNum )
1153 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_Notes | nPageNum, mpStrm->Tell() );
1154 mpPptEscherEx->OpenContainer( EPP_Notes );
1155 mpPptEscherEx->AddAtom( 8, EPP_NotesAtom, 1 );
1156 *mpStrm << (sal_uInt32)nPageNum + 0x100
1157 << (sal_uInt16)3 // follow master ....
1158 << (sal_uInt16)0;
1160 ImplCreateHeaderFooters( mXPagePropSet );
1162 EscherSolverContainer aSolverContainer;
1164 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
1165 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
1166 mpPptEscherEx->EnterGroup(0,0);
1168 ImplWritePage( GetLayout( 20 ), aSolverContainer, NOTICE, sal_False ); // the shapes of the pages are created in the PPT document
1170 mpPptEscherEx->LeaveGroup();
1171 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1172 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, 0xc00 ); // Flags: Connector | Background | HasSpt
1173 EscherPropertyContainer aPropOpt;
1174 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0xffffff ); // stock valued fill color
1175 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1176 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, 0x8b9f8e );
1177 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, 0x68bdde );
1178 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
1179 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1180 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_wDontShow );
1181 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
1182 aPropOpt.Commit( *mpStrm );
1183 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1185 aSolverContainer.WriteSolver( *mpStrm );
1187 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
1188 mpPptEscherEx->CloseContainer(); // EPP_Drawing
1189 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
1190 *mpStrm << (sal_uInt32)0xffffff << (sal_uInt32)0x000000 << (sal_uInt32)0x808080 << (sal_uInt32)0x000000 << (sal_uInt32)0x99cc00 << (sal_uInt32)0xcc3333 << (sal_uInt32)0xffcccc << (sal_uInt32)0xb2b2b2;
1191 mpPptEscherEx->CloseContainer(); // EPP_Notes
1194 void PPTWriter::ImplWriteBackground( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet )
1196 //************************ ******
1197 //** DEFAULT BACKGROUND SHAPE **
1198 //******************************
1200 sal_uInt32 nFillColor = 0xffffff;
1201 sal_uInt32 nFillBackColor = 0;
1203 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1204 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, 0xc00 ); // Flags: Connector | Background | HasSpt
1205 Point aEmptyPoint = Point();
1206 Rectangle aRect( aEmptyPoint, Size( 28000, 21000 ) );
1207 EscherPropertyContainer aPropOpt( mpPptEscherEx->GetGraphicProvider(), mpPicStrm, aRect );
1208 aPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
1209 ::com::sun::star::drawing::FillStyle aFS( ::com::sun::star::drawing::FillStyle_NONE );
1210 if ( ImplGetPropertyValue( rXPropSet, OUString( "FillStyle" ) ) )
1211 mAny >>= aFS;
1213 switch( aFS )
1215 case ::com::sun::star::drawing::FillStyle_GRADIENT :
1217 aPropOpt.CreateGradientProperties( rXPropSet );
1218 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x1f001e );
1219 aPropOpt.GetOpt( ESCHER_Prop_fillColor, nFillColor );
1220 aPropOpt.GetOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
1222 break;
1224 case ::com::sun::star::drawing::FillStyle_BITMAP :
1225 aPropOpt.CreateGraphicProperties( rXPropSet, OUString( "FillBitmapURL" ), sal_True );
1226 break;
1228 case ::com::sun::star::drawing::FillStyle_HATCH :
1229 aPropOpt.CreateGraphicProperties( rXPropSet, OUString( "FillHatch" ), sal_True );
1230 break;
1232 case ::com::sun::star::drawing::FillStyle_SOLID :
1234 if ( ImplGetPropertyValue( rXPropSet, OUString( "FillColor" ) ) )
1236 nFillColor = mpPptEscherEx->GetColor( *((sal_uInt32*)mAny.getValue()) );
1237 nFillBackColor = nFillColor ^ 0xffffff;
1239 } // PASSTHROUGH INTENDED
1240 case ::com::sun::star::drawing::FillStyle_NONE :
1241 default:
1242 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
1243 break;
1245 aPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
1246 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
1247 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, PPTtoEMU( maDestPageSize.Width ) );
1248 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, PPTtoEMU( maDestPageSize.Height ) );
1249 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1250 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_bwWhite );
1251 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
1252 aPropOpt.Commit( *mpStrm );
1253 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1256 void PPTWriter::ImplWriteVBA()
1258 if ( mpVBA )
1260 mpVBA->Seek( STREAM_SEEK_TO_END );
1261 sal_uInt32 nLen = mpVBA->Tell();
1262 if ( nLen > 8 )
1264 nLen -= 8;
1265 mnVBAOleOfs = mpStrm->Tell();
1266 mpPptEscherEx->BeginAtom();
1267 mpStrm->Write( (sal_Int8*)mpVBA->GetData() + 8, nLen );
1268 mpPptEscherEx->EndAtom( EPP_ExOleObjStg, 0, 1 );
1273 // ---------------------------------------------------------------------------------------------
1275 void PPTWriter::ImplWriteOLE( )
1278 SvxMSExportOLEObjects aOleExport( mnCnvrtFlags );
1280 for ( std::vector<PPTExOleObjEntry*>::const_iterator it = maExOleObj.begin(); it != maExOleObj.end(); ++it )
1282 PPTExOleObjEntry* pPtr = *it;
1283 SvMemoryStream* pStrm = NULL;
1284 pPtr->nOfsB = mpStrm->Tell();
1285 switch ( pPtr->eType )
1287 case NORMAL_OLE_OBJECT :
1289 SdrObject* pSdrObj = GetSdrObjectFromXShape( pPtr->xShape );
1290 if ( pSdrObj && pSdrObj->ISA( SdrOle2Obj ) )
1292 ::uno::Reference < embed::XEmbeddedObject > xObj( ( (SdrOle2Obj*) pSdrObj )->GetObjRef() );
1293 if( xObj.is() )
1295 SvStorageRef xTempStorage( new SvStorage( new SvMemoryStream(), sal_True ) );
1296 aOleExport.ExportOLEObject( xObj, *xTempStorage );
1298 //TODO/MBA: testing
1299 OUString aPersistStream( SVEXT_PERSIST_STREAM );
1300 SvMemoryStream aStream;
1301 SvStorageRef xCleanStorage( new SvStorage( sal_False, aStream ) );
1302 xTempStorage->CopyTo( xCleanStorage );
1303 // create a dummy content stream, the dummy content is necessary for ppt, but not for
1304 // doc files, so we can't share code.
1305 SotStorageStreamRef xStm = xCleanStorage->OpenSotStream( aPersistStream, STREAM_STD_READWRITE );
1306 *xStm << (sal_uInt32)0 // no ClipboardId
1307 << (sal_uInt32)4 // no target device
1308 << (sal_uInt32)1 // aspect ratio
1309 << (sal_Int32)-1 // L-Index
1310 << (sal_uInt32)0 // Advanced Flags
1311 << (sal_uInt32)0 // compression
1312 << (sal_uInt32)0 // Size
1313 << (sal_uInt32)0 // "
1314 << (sal_uInt32)0;
1315 pStrm = xCleanStorage->CreateMemoryStream();
1319 break;
1321 case OCX_CONTROL :
1323 if ( pPtr->xControlModel.is() )
1325 OUString aName;
1326 ::com::sun::star::awt::Size aSize;
1327 SvStorageRef xDest( new SvStorage( new SvMemoryStream(), sal_True ) );
1328 sal_Bool bOk = oox::ole::MSConvertOCXControls::WriteOCXStream( mXModel, xDest, pPtr->xControlModel, aSize, aName );
1329 if ( bOk )
1330 pStrm = xDest->CreateMemoryStream();
1334 if ( pStrm )
1336 mpPptEscherEx->BeginAtom();
1337 pStrm->Seek( STREAM_SEEK_TO_END );
1338 sal_uInt32 npStrmSize = pStrm->Tell();
1339 *mpStrm << npStrmSize; // uncompressed size
1341 pStrm->Seek( 0 );
1342 ZCodec aZCodec( 0x8000, 0x8000 );
1343 aZCodec.BeginCompression();
1344 aZCodec.Compress( *pStrm, *mpStrm );
1345 aZCodec.EndCompression();
1346 delete pStrm;
1347 mpPptEscherEx->EndAtom( EPP_ExOleObjStg, 0, 1 );
1352 // ---------------------------------------------------------------------------------------------
1353 // write PersistantTable and UserEditAtom
1355 sal_Bool PPTWriter::ImplWriteAtomEnding()
1358 #define EPP_LastViewTypeSlideView 1
1360 sal_uInt32 i, nPos, nOfs, nPersistOfs = mpStrm->Tell();
1361 sal_uInt32 nPersistEntrys = 0;
1362 *mpStrm << (sal_uInt32)0 << (sal_uInt32)0 << (sal_uInt32)0; // skip record header and first entry
1364 // write document persist
1365 nPersistEntrys++;
1366 *mpStrm << (sal_uInt32)0;
1367 // write MasterPages persists
1368 for ( i = 0; i < mnMasterPages; i++ )
1370 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_MainMaster | i );
1371 if ( nOfs )
1373 *mpStrm << nOfs;
1374 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINMASTER_PERSIST_KEY | i, ++nPersistEntrys );
1377 // write MainNotesMaster persist
1378 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_MainNotes );
1379 if ( nOfs )
1381 *mpStrm << nOfs;
1382 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINNOTESMASTER_PERSIST_KEY, ++nPersistEntrys );
1384 // write slide persists -> we have to write a valid value into EPP_SlidePersistAtome too
1385 for ( i = 0; i < mnPages; i++ )
1387 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_Slide | i );
1388 if ( nOfs )
1390 *mpStrm << nOfs;
1391 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINSLIDE_PERSIST_KEY | i, ++nPersistEntrys );
1394 // write Notes persists
1395 for ( i = 0; i < mnPages; i++ )
1397 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_Notes | i );
1398 if ( nOfs )
1400 *mpStrm << nOfs;
1401 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINNOTES_PERSIST_KEY | i, ++nPersistEntrys );
1404 // Ole persists
1405 for ( std::vector<PPTExOleObjEntry*>::const_iterator it = maExOleObj.begin(); it != maExOleObj.end(); ++it )
1407 PPTExOleObjEntry* pPtr = *it;
1408 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_ExObj );
1409 if ( nOfs )
1411 nPersistEntrys++;
1412 *mpStrm << pPtr->nOfsB;
1413 sal_uInt32 nOldPos, nPersOfs = nOfs + pPtr->nOfsA + 16 + 8; // 8 bytes atom header, +16 to the persist entry
1414 nOldPos = mpStrm->Tell();
1415 mpStrm->Seek( nPersOfs );
1416 *mpStrm << nPersistEntrys;
1417 mpStrm->Seek( nOldPos );
1420 // VB persist
1421 if ( mnVBAOleOfs && mpVBA )
1423 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_VBAInfoAtom );
1424 if ( nOfs )
1426 nPersistEntrys++;
1427 sal_uInt32 n1, n2;
1429 mpVBA->Seek( 0 );
1430 *mpVBA >> n1
1431 >> n2;
1433 *mpStrm << mnVBAOleOfs;
1434 sal_uInt32 nOldPos = mpStrm->Tell();
1435 mpStrm->Seek( nOfs ); // Fill the VBAInfoAtom with the correct index to the persisttable
1436 *mpStrm << nPersistEntrys
1437 << n1
1438 << sal_Int32(2);
1439 mpStrm->Seek( nOldPos );
1443 nPos = mpStrm->Tell();
1444 mpStrm->Seek( nPersistOfs );
1445 mpPptEscherEx->AddAtom( ( nPersistEntrys + 1 ) << 2, EPP_PersistPtrIncrementalBlock ); // insert Record Header
1446 *mpStrm << (sal_uInt32)( ( nPersistEntrys << 20 ) | 1 );
1447 mpStrm->Seek( nPos );
1449 *mpCurUserStrm << (sal_uInt32)nPos; // set offset to current edit
1450 mpPptEscherEx->AddAtom( 28, EPP_UserEditAtom );
1451 *mpStrm << (sal_Int32)0x100 // last slide ID
1452 << (sal_uInt32)0x03000dbc // minor and major app version that did the save
1453 << (sal_uInt32)0 // offset last save, 0 after a full save
1454 << nPersistOfs // File offset to persist pointers for this save operation
1455 << (sal_uInt32)1 // Persist reference to the document persist object
1456 << (sal_uInt32)nPersistEntrys // max persists written, Seed value for persist object id management
1457 << (sal_Int16)EPP_LastViewTypeSlideView // last view type
1458 << (sal_Int16)0x12; // padword
1460 return sal_True;
1463 // ---------------------
1464 // - exported function -
1465 // ---------------------
1467 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL ExportPPT( const std::vector< com::sun::star::beans::PropertyValue >& rMediaData, SvStorageRef& rSvStorage,
1468 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & rXModel,
1469 ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > & rXStatInd,
1470 SvMemoryStream* pVBA, sal_uInt32 nCnvrtFlags )
1472 PPTWriter* pPPTWriter;
1473 sal_Bool bStatus = sal_False;
1475 pPPTWriter = new PPTWriter( rSvStorage, rXModel, rXStatInd, pVBA, nCnvrtFlags );
1476 if ( pPPTWriter )
1478 pPPTWriter->exportPPT(rMediaData);
1479 bStatus = ( pPPTWriter->IsValid() == sal_True );
1480 delete pPPTWriter;
1483 return bStatus;
1486 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL SaveVBA( SfxObjectShell& rDocShell, SvMemoryStream*& pBas )
1488 SvStorageRef xDest( new SvStorage( new SvMemoryStream(), sal_True ) );
1489 SvxImportMSVBasic aMSVBas( rDocShell, *xDest );
1490 aMSVBas.SaveOrDelMSVBAStorage( sal_True, OUString( "_MS_VBA_Overhead" ) );
1492 SvStorageRef xOverhead = xDest->OpenSotStorage( OUString( "_MS_VBA_Overhead") );
1493 if ( xOverhead.Is() && ( xOverhead->GetError() == SVSTREAM_OK ) )
1495 SvStorageRef xOverhead2 = xOverhead->OpenSotStorage( OUString( "_MS_VBA_Overhead") );
1496 if ( xOverhead2.Is() && ( xOverhead2->GetError() == SVSTREAM_OK ) )
1498 SvStorageStreamRef xTemp = xOverhead2->OpenSotStream( OUString( "_MS_VBA_Overhead2") );
1499 if ( xTemp.Is() && ( xTemp->GetError() == SVSTREAM_OK ) )
1501 sal_uInt32 nLen = xTemp->GetSize();
1502 if ( nLen )
1504 char* pTemp = new char[ nLen ];
1505 if ( pTemp )
1507 xTemp->Seek( STREAM_SEEK_TO_BEGIN );
1508 xTemp->Read( pTemp, nLen );
1509 pBas = new SvMemoryStream( pTemp, nLen, STREAM_READ );
1510 pBas->ObjectOwnsMemory( sal_True );
1511 return sal_True;
1518 return sal_False;
1521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */