1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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 ),
76 mpCurUserStrm ( NULL
),
79 mpPptEscherEx ( NULL
),
83 mpExEmbed ( new SvMemoryStream
),
89 void PPTWriter::exportPPTPre( const std::vector
< com::sun::star::beans::PropertyValue
>& rMediaData
)
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() )
110 mpStrm
= mrStg
->OpenSotStream( OUString( "PowerPoint Document" ) );
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
;
126 mpPptEscherEx
= new PptEscherEx( *mpStrm
, maBaseURI
);
129 void PPTWriter::exportPPTPost( )
131 if ( !ImplCloseDocument() )
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
;
149 if ( !ImplWriteAtomEnding() )
152 if ( !ImplCreateDocumentSummaryInformation() )
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
)
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)
176 << (sal_uInt16
)0; // padword
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" ) ) )
184 if ( GetPropertyValue( aAny
, mXPagePropSet
, OUString( "Change" ) ) )
186 switch ( *(sal_Int32
*)aAny
.getValue() )
188 case 1 : // automatic
190 case 2 : // semi-automatic
197 if ( GetPropertyValue( aAny
, mXPagePropSet
, OUString( "Effect" ) ) )
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" ) ) )
208 if ( aAny
>>= aSoundURL
)
210 nSoundRef
= maSoundCollection
.GetId( aSoundURL
);
216 if ( GetPropertyValue( aAny
, mXPagePropSet
, OUString( "LoopSound" ) ) )
219 sal_Bool bNeedsSSSlideInfoAtom
= ( bVisible
== sal_False
)
220 || ( mnDiaMode
== 2 )
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
;
236 nSpeed
= (sal_uInt8
)aAs
;
239 if ( GetPropertyValue( aAny
, mXPagePropSet
, OUString( "TransitionType" ) )
240 && ( aAny
>>= nTT
) )
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
)
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
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
);
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
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
)
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
);
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
)
404 bSimpleText
= sal_True
;
407 mpStyleSheet
->mpParaSheet
[ nInstance
]->Write( *mpStrm
, mpPptEscherEx
, nLev
, bFirst
, bSimpleText
, mXPagePropSet
);
408 mpStyleSheet
->mpCharSheet
[ nInstance
]->Write( *mpStrm
, mpPptEscherEx
, nLev
, bFirst
, bSimpleText
, mXPagePropSet
);
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()
445 delete mpPptEscherEx
;
446 delete mpCurUserStrm
;
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
)
457 if ( mbStatusIndicator
)
458 mXStatusIndicator
->end();
461 // ---------------------------------------------------------------------------------------------
463 sal_Bool
PPTWriter::ImplCreateCurrentUserStream()
465 mpCurUserStrm
= mrStg
->OpenSotStream( OUString( "Current User" ) );
466 if ( !mpCurUserStrm
)
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
);
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" ) ) )
531 *static_cast<const uno::Sequence
<sal_uInt8
>*>(mAny
.getValue());
533 sfx2::SaveOlePropertySet( xDocProps
, mrStg
,
534 &aThumbSeq
, &aGuidSeq
, &aHyperSeq
);
538 sfx2::SaveOlePropertySet( xDocProps
, mrStg
,
539 NULL
, &aGuidSeq
, &aHyperSeq
);
546 // ---------------------------------------------------------------------------------------------
548 void PPTWriter::ImplWriteExtParaHeader( SvMemoryStream
& rSt
, sal_uInt32 nRef
, sal_uInt32 nInstance
, sal_uInt32 nSlideId
)
552 aBuExOutlineStream
<< (sal_uInt32
)( ( EPP_PST_ExtendedParagraphHeaderAtom
<< 16 )
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() )
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
;
595 ::com::sun::star::uno::Any aAny
;
596 if ( PropValue::GetPropertyValue( aAny
, rXPagePropSet
, OUString( "IsHeaderVisible" ), sal_True
) )
598 if ( ( aAny
>>= bVal
) && bVal
)
601 if ( PropValue::GetPropertyValue( aAny
, rXPagePropSet
, OUString( "IsFooterVisible" ), sal_True
) )
603 if ( ( aAny
>>= bVal
) && bVal
)
606 if ( PropValue::GetPropertyValue( aAny
, rXPagePropSet
, OUString( "IsDateTimeVisible" ), sal_True
) )
608 if ( ( aAny
>>= bVal
) && bVal
)
611 if ( PropValue::GetPropertyValue( aAny
, rXPagePropSet
, OUString( "IsPageNumberVisible" ), sal_True
) )
613 if ( ( aAny
>>= bVal
) && bVal
)
616 if ( PropValue::GetPropertyValue( aAny
, rXPagePropSet
, OUString( "IsDateTimeFixed" ), sal_True
) )
618 if ( ( aAny
>>= bVal
) && !bVal
)
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
:
633 case SVXDATEFORMAT_D
:
636 case SVXDATEFORMAT_C
:
640 case SVXDATEFORMAT_A
:
643 switch( eTimeFormat
)
645 case SVXTIMEFORMAT_24_HM
:
648 case SVXTIMEFORMAT_12_HM
:
651 case SVXTIMEFORMAT_24_HMS
:
654 case SVXTIMEFORMAT_12_HMS
:
663 mpPptEscherEx
->OpenContainer( EPP_HeadersFooters
, 0 );
664 mpPptEscherEx
->AddAtom( 4, EPP_HeadersFootersAtom
);
666 ImplCreateHeaderFooterStrings( *mpStrm
, rXPagePropSet
);
667 mpPptEscherEx
->CloseContainer();
671 // ---------------------------------------------------------------------------------------------
673 sal_Bool
PPTWriter::ImplCreateDocument()
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
737 SetCurrentStyleSheet( GetMasterIndex( NORMAL
) );
739 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNamed
>
740 aXName( mXDrawPage
, ::com::sun::star::uno::UNO_QUERY
);
743 maSlideNameList
.push_back( aXName
->getName() );
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
757 << (sal_Int32
)i
+ 0x100
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() )
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;
810 nEndSlide
= (sal_uInt16
)mnPages
;
815 if ( ImplGetPropertyValue( OUString("IsAutomatic" ) ) )
817 sal_Bool bBool
= sal_False
;
823 if ( ImplGetPropertyValue( OUString( "IsEndless" ) ) ) // the correct name would be IsNotEndless: WTF?
825 sal_Bool bBool
= sal_False
;
830 if ( ImplGetPropertyValue( OUString( "IsFullScreen" ) ) )
832 sal_Bool bBool
= sal_False
;
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 ) ;
855 ::com::sun::star::uno::Reference
< ::com::sun::star::presentation::XCustomPresentationSupplier
>
856 aXCPSup( mXModel
, ::com::sun::star::uno::UNO_QUERY
);
859 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameContainer
>
860 aXCont( aXCPSup
->getCustomPresentations() );
863 ::com::sun::star::uno::Sequence
< OUString
> aNameSeq( aXCont
->getElementNames() );
864 const OUString
* pUString
= aNameSeq
.getArray();
865 sal_uInt32 nCount
= aNameSeq
.getLength();
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 )
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
;
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
);
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
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
)
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)
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
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
++ )
989 rStrm
<< (sal_uInt16
)0;
996 rStrm
<< (sal_uInt32
)0x1f
997 << (sal_uInt32
)( nUrlLen
+ 1 );
998 for ( i
= 0; i
< nUrlLen
; i
++ )
1003 rStrm
<< (sal_uInt16
)0;
1004 rStrm
<< (sal_uInt16
)0
1012 nCurrentOfs
= rStrm
.Tell();
1013 rStrm
.Seek( nParaOfs
);
1014 rStrm
<< (sal_uInt32
)( nCurrentOfs
- ( nParaOfs
+ 4 ) );
1015 rStrm
<< nParaCount
;
1016 rStrm
.Seek( nCurrentOfs
);
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
1062 // ---------------------------------------------------------------------------------------------
1064 static OUString
getInitials( const OUString
& rName
)
1068 const sal_Unicode
* pStr
= rName
.getStr();
1069 sal_Int32 nLength
= rName
.getLength();
1074 while( nLength
&& (*pStr
<= ' ') )
1082 sInitials
+= OUString( *pStr
);
1086 // skip letters until whitespace
1087 while( nLength
&& (*pStr
> ' ') )
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
++
1133 << aDateTime
.Day
// todo: day of week
1136 << aDateTime
.Minutes
1137 << aDateTime
.Seconds
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 ....
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" ) ) )
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
);
1224 case ::com::sun::star::drawing::FillStyle_BITMAP
:
1225 aPropOpt
.CreateGraphicProperties( rXPropSet
, OUString( "FillBitmapURL" ), sal_True
);
1228 case ::com::sun::star::drawing::FillStyle_HATCH
:
1229 aPropOpt
.CreateGraphicProperties( rXPropSet
, OUString( "FillHatch" ), sal_True
);
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
:
1242 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x120012 );
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()
1260 mpVBA
->Seek( STREAM_SEEK_TO_END
);
1261 sal_uInt32 nLen
= mpVBA
->Tell();
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() );
1295 SvStorageRef
xTempStorage( new SvStorage( new SvMemoryStream(), sal_True
) );
1296 aOleExport
.ExportOLEObject( xObj
, *xTempStorage
);
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 // "
1315 pStrm
= xCleanStorage
->CreateMemoryStream();
1323 if ( pPtr
->xControlModel
.is() )
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
);
1330 pStrm
= xDest
->CreateMemoryStream();
1336 mpPptEscherEx
->BeginAtom();
1337 pStrm
->Seek( STREAM_SEEK_TO_END
);
1338 sal_uInt32 npStrmSize
= pStrm
->Tell();
1339 *mpStrm
<< npStrmSize
; // uncompressed size
1342 ZCodec
aZCodec( 0x8000, 0x8000 );
1343 aZCodec
.BeginCompression();
1344 aZCodec
.Compress( *pStrm
, *mpStrm
);
1345 aZCodec
.EndCompression();
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
1366 *mpStrm
<< (sal_uInt32
)0;
1367 // write MasterPages persists
1368 for ( i
= 0; i
< mnMasterPages
; i
++ )
1370 nOfs
= mpPptEscherEx
->PtGetOffsetByID( EPP_Persist_MainMaster
| i
);
1374 mpPptEscherEx
->InsertAtPersistOffset( EPP_MAINMASTER_PERSIST_KEY
| i
, ++nPersistEntrys
);
1377 // write MainNotesMaster persist
1378 nOfs
= mpPptEscherEx
->PtGetOffsetByID( EPP_Persist_MainNotes
);
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
);
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
);
1401 mpPptEscherEx
->InsertAtPersistOffset( EPP_MAINNOTES_PERSIST_KEY
| i
, ++nPersistEntrys
);
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
);
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
);
1421 if ( mnVBAOleOfs
&& mpVBA
)
1423 nOfs
= mpPptEscherEx
->PtGetOffsetByID( EPP_Persist_VBAInfoAtom
);
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
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
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
);
1478 pPPTWriter
->exportPPT(rMediaData
);
1479 bStatus
= ( pPPTWriter
->IsValid() == sal_True
);
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();
1504 char* pTemp
= new char[ nLen
];
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
);
1521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */