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 <sal/config.h>
23 #include <basegfx/numeric/ftools.hxx>
24 #include <o3tl/any.hxx>
27 #include "epptdef.hxx"
28 #include "escherex.hxx"
29 #include <tools/poly.hxx>
30 #include <tools/stream.hxx>
31 #include <tools/fontenum.hxx>
32 #include <sot/storage.hxx>
33 #include <vcl/graph.hxx>
34 #include <editeng/svxenum.hxx>
35 #include <svx/svdobj.hxx>
36 #include <svx/unoapi.hxx>
37 #include <com/sun/star/awt/FontFamily.hpp>
38 #include <com/sun/star/awt/FontPitch.hpp>
39 #include <com/sun/star/awt/Rectangle.hpp>
40 #include <com/sun/star/awt/FontDescriptor.hpp>
41 #include <com/sun/star/style/TabStop.hpp>
42 #include <com/sun/star/drawing/CircleKind.hpp>
43 #include <com/sun/star/drawing/FillStyle.hpp>
44 #include <com/sun/star/beans/XPropertyState.hpp>
45 #include <com/sun/star/drawing/XControlShape.hpp>
46 #include <com/sun/star/embed/Aspects.hpp>
47 #include <tools/urlobj.hxx>
48 #include <com/sun/star/text/XSimpleText.hpp>
49 #include <com/sun/star/task/XStatusIndicator.hpp>
50 #include <com/sun/star/table/XTable.hpp>
51 #include <com/sun/star/table/XMergeableCell.hpp>
52 #include <com/sun/star/table/BorderLine.hpp>
53 #include <com/sun/star/table/XColumnRowRange.hpp>
54 #include <com/sun/star/table/XCellRange.hpp>
55 #include <oox/ole/olehelper.hxx>
56 #include <i18nlangtag/languagetag.hxx>
58 using namespace ::com::sun::star
;
60 #define ANSI_CHARSET 0
61 #define SYMBOL_CHARSET 2
66 #define FF_MODERN 0x30
67 #define FF_SCRIPT 0x40
68 #define FF_DECORATIVE 0x50
70 #define DEFAULT_PITCH 0x00
71 #define FIXED_PITCH 0x01
73 PPTExBulletProvider::PPTExBulletProvider()
74 : pGraphicProv( new EscherGraphicProvider( EscherGraphicProviderFlags::UseInstances
) )
78 PPTExBulletProvider::~PPTExBulletProvider()
82 sal_uInt16
PPTExBulletProvider::GetId(Graphic
const & rGraphic
, Size
& rGraphicSize
)
84 sal_uInt16 nRetValue
= 0xffff;
86 if (!rGraphic
.IsNone())
88 Graphic aMappedGraphic
, aGraphic(rGraphic
);
89 std::unique_ptr
<GraphicObject
> xGraphicObject(new GraphicObject(aGraphic
));
90 Size
aPrefSize( aGraphic
.GetPrefSize() );
91 BitmapEx
aBmpEx( aGraphic
.GetBitmapEx() );
93 if ( rGraphicSize
.Width() && rGraphicSize
.Height() )
97 if (aPrefSize
.Width() == 0 || aPrefSize
.Height() == 0)
99 aBmpEx
.Scale(aPrefSize
);
100 aNewSize
= aPrefSize
;
105 double fQ1
= static_cast<double>(aPrefSize
.Width()) / static_cast<double>(aPrefSize
.Height());
106 double fQ2
= static_cast<double>(rGraphicSize
.Width()) / static_cast<double>(rGraphicSize
.Height());
112 else if ( fQ1
< fQ2
)
115 if ( ( fXScale
!= 1.0 ) || ( fYScale
!= 1.0 ) )
117 aBmpEx
.Scale( fXScale
, fYScale
);
118 aNewSize
= Size( static_cast<sal_Int32
>(static_cast<double>(rGraphicSize
.Width()) / fXScale
+ 0.5 ),
119 static_cast<sal_Int32
>(static_cast<double>(rGraphicSize
.Height()) / fYScale
+ 0.5 ) );
125 rGraphicSize
= aNewSize
;
127 aMappedGraphic
= Graphic( aBmpEx
);
128 xGraphicObject
.reset(new GraphicObject(aMappedGraphic
));
132 sal_uInt32 nId
= pGraphicProv
->GetBlibID(aBuExPictureStream
, *xGraphicObject
);
134 if ( nId
&& ( nId
< 0x10000 ) )
135 nRetValue
= static_cast<sal_uInt16
>(nId
) - 1;
140 sal_uInt32
PPTWriter::ImplVBAInfoContainer( SvStream
* pStrm
)
142 sal_uInt32 nSize
= 28;
145 pStrm
->WriteUInt32( 0x1f | ( EPP_VBAInfo
<< 16 ) )
146 .WriteUInt32( nSize
- 8 )
147 .WriteUInt32( 2 | ( EPP_VBAInfoAtom
<< 16 ) )
149 mpPptEscherEx
->InsertPersistOffset( EPP_Persist_VBAInfoAtom
, pStrm
->Tell() );
150 pStrm
->WriteUInt32( 0 )
157 sal_uInt32
PPTWriter::ImplSlideViewInfoContainer( sal_uInt32 nInstance
, SvStream
* pStrm
)
159 sal_uInt32 nSize
= 111;
162 sal_uInt8 bShowGuides
= 0;
163 sal_uInt8
const bSnapToGrid
= 1;
164 sal_uInt8
const bSnapToShape
= 0;
166 sal_Int32 nScaling
= 85;
167 sal_Int32 nMasterCoordinate
= 0xdda;
168 sal_Int32 nXOrigin
= -780;
169 sal_Int32 nYOrigin
= -84;
171 sal_Int32 nPosition1
= 0x870;
172 sal_Int32 nPosition2
= 0xb40;
178 nMasterCoordinate
= 0xf0c;
184 pStrm
->WriteUInt32( 0xf | ( EPP_SlideViewInfo
<< 16 ) | ( nInstance
<< 4 ) )
185 .WriteUInt32( nSize
- 8 )
186 .WriteUInt32( EPP_SlideViewInfoAtom
<< 16 ).WriteUInt32( 3 )
187 .WriteUChar( bShowGuides
).WriteUChar( bSnapToGrid
).WriteUChar( bSnapToShape
)
188 .WriteUInt32( EPP_ViewInfoAtom
<< 16 ).WriteUInt32( 52 )
189 .WriteInt32( nScaling
).WriteInt32( 100 ).WriteInt32( nScaling
).WriteInt32( 100 ) // scaling atom - Keeps the current scale
190 .WriteInt32( nScaling
).WriteInt32( 100 ).WriteInt32( nScaling
).WriteInt32( 100 ) // scaling atom - Keeps the previous scale
191 .WriteInt32( 0x17ac ).WriteInt32( nMasterCoordinate
)// Origin - Keeps the origin in master coordinates
192 .WriteInt32( nXOrigin
).WriteInt32( nYOrigin
) // Origin
193 .WriteUChar( 1 ) // Bool1 varScale - Set if zoom to fit is set
194 .WriteUChar( 0 ) // bool1 draftMode - Not used
195 .WriteUInt16( 0 ) // padword
196 .WriteUInt32( ( 7 << 4 ) | ( EPP_GuideAtom
<< 16 ) ).WriteUInt32( 8 )
197 .WriteUInt32( 0 ) // Type of the guide. If the guide is horizontal this value is zero. If it's vertical, it's one.
198 .WriteInt32( nPosition1
) // Position of the guide in master coordinates. X coordinate if it's vertical, and Y coordinate if it's horizontal.
199 .WriteUInt32( ( 7 << 4 ) | ( EPP_GuideAtom
<< 16 ) ).WriteUInt32( 8 )
200 .WriteInt32( 1 ) // Type of the guide. If the guide is horizontal this value is zero. If it's vertical, it's one.
201 .WriteInt32( nPosition2
); // Position of the guide in master coordinates. X coordinate if it's vertical, and Y coordinate if it's horizontal.
206 sal_uInt32
PPTWriter::ImplOutlineViewInfoContainer( SvStream
* pStrm
)
208 sal_uInt32 nSize
= 68;
211 pStrm
->WriteUInt32( 0xf | ( EPP_OutlineViewInfo
<< 16 ) ).WriteUInt32( nSize
- 8 )
212 .WriteUInt32( EPP_ViewInfoAtom
<< 16 ).WriteUInt32( 52 )
213 .WriteInt32( 170 ).WriteInt32( 200 ).WriteInt32( 170 ).WriteInt32( 200 ) // scaling atom - Keeps the current scale
214 .WriteInt32( 170 ).WriteInt32( 200 ).WriteInt32( 170 ).WriteInt32( 200 ) // scaling atom - Keeps the previous scale
215 .WriteInt32( 0x17ac ).WriteInt32( 0xdda ) // Origin - Keeps the origin in master coordinates
216 .WriteInt32( -780 ).WriteInt32( -84 ) // Origin
217 .WriteUChar( 1 ) // bool1 varScale - Set if zoom to fit is set
218 .WriteUChar( 0 ) // bool1 draftMode - Not used
219 .WriteUInt16( 0 ); // padword
224 sal_uInt32
PPTWriter::ImplProgBinaryTag( SvStream
* pStrm
)
226 sal_uInt32 nPictureStreamSize
, nOutlineStreamSize
, nSize
= 8;
228 nPictureStreamSize
= aBuExPictureStream
.Tell();
229 if ( nPictureStreamSize
)
230 nSize
+= nPictureStreamSize
+ 8;
232 nOutlineStreamSize
= aBuExOutlineStream
.Tell();
233 if ( nOutlineStreamSize
)
234 nSize
+= nOutlineStreamSize
+ 8;
238 pStrm
->WriteUInt32( EPP_BinaryTagData
<< 16 ).WriteUInt32( nSize
- 8 );
239 if ( nPictureStreamSize
)
241 pStrm
->WriteUInt32( 0xf | ( EPP_PST_ExtendedBuGraContainer
<< 16 ) ).WriteUInt32( nPictureStreamSize
);
242 pStrm
->WriteBytes(aBuExPictureStream
.GetData(), nPictureStreamSize
);
244 if ( nOutlineStreamSize
)
246 pStrm
->WriteUInt32( 0xf | ( EPP_PST_ExtendedPresRuleContainer
<< 16 ) ).WriteUInt32( nOutlineStreamSize
);
247 pStrm
->WriteBytes(aBuExOutlineStream
.GetData(), nOutlineStreamSize
);
253 sal_uInt32
PPTWriter::ImplProgBinaryTagContainer( SvStream
* pStrm
, SvMemoryStream
* pBinTagStrm
)
255 sal_uInt32 nSize
= 8 + 8 + 14;
258 pStrm
->WriteUInt32( 0xf | ( EPP_ProgBinaryTag
<< 16 ) ).WriteUInt32( 0 )
259 .WriteUInt32( EPP_CString
<< 16 ).WriteUInt32( 14 )
260 .WriteUInt32( 0x5f005f ).WriteUInt32( 0x50005f )
261 .WriteUInt32( 0x540050 ).WriteUInt16( 0x39 );
263 if ( pStrm
&& pBinTagStrm
)
265 sal_uInt32 nLen
= pBinTagStrm
->Tell();
267 pStrm
->WriteUInt32( EPP_BinaryTagData
<< 16 ).WriteUInt32( nLen
);
268 pStrm
->WriteBytes(pBinTagStrm
->GetData(), nLen
);
271 nSize
+= ImplProgBinaryTag( pStrm
);
275 pStrm
->SeekRel( - ( static_cast<sal_Int32
>(nSize
) - 4 ) );
276 pStrm
->WriteUInt32( nSize
- 8 );
277 pStrm
->SeekRel( nSize
- 8 );
282 sal_uInt32
PPTWriter::ImplProgTagContainer( SvStream
* pStrm
, SvMemoryStream
* pBinTagStrm
)
284 sal_uInt32 nSize
= 0;
285 if ( aBuExPictureStream
.Tell() || aBuExOutlineStream
.Tell() || pBinTagStrm
)
290 pStrm
->WriteUInt32( 0xf | ( EPP_ProgTags
<< 16 ) ).WriteUInt32( 0 );
292 nSize
+= ImplProgBinaryTagContainer( pStrm
, pBinTagStrm
);
295 pStrm
->SeekRel( - ( static_cast<sal_Int32
>(nSize
) - 4 ) );
296 pStrm
->WriteUInt32( nSize
- 8 );
297 pStrm
->SeekRel( nSize
- 8 );
303 sal_uInt32
PPTWriter::ImplDocumentListContainer( SvStream
* pStrm
)
305 sal_uInt32 nSize
= 8;
308 pStrm
->WriteUInt32( ( EPP_List
<< 16 ) | 0xf ).WriteUInt32( 0 );
311 nSize
+= ImplVBAInfoContainer( pStrm
);
312 nSize
+= ImplSlideViewInfoContainer( 0, pStrm
);
313 nSize
+= ImplOutlineViewInfoContainer( pStrm
);
314 nSize
+= ImplSlideViewInfoContainer( 1, pStrm
);
315 nSize
+= ImplProgTagContainer( pStrm
);
319 pStrm
->SeekRel( - ( static_cast<sal_Int32
>(nSize
) - 4 ) );
320 pStrm
->WriteUInt32( nSize
- 8 );
321 pStrm
->SeekRel( nSize
- 8 );
326 sal_uInt32
PPTWriter::ImplMasterSlideListContainer( SvStream
* pStrm
)
328 sal_uInt32 i
, nSize
= 28 * mnMasterPages
+ 8;
331 pStrm
->WriteUInt32( 0x1f | ( EPP_SlideListWithText
<< 16 ) ).WriteUInt32( nSize
- 8 );
333 for ( i
= 0; i
< mnMasterPages
; i
++ )
335 pStrm
->WriteUInt32( EPP_SlidePersistAtom
<< 16 ).WriteUInt32( 20 );
336 mpPptEscherEx
->InsertPersistOffset( EPP_MAINMASTER_PERSIST_KEY
| i
, pStrm
->Tell() );
337 pStrm
->WriteUInt32( 0 ) // psrReference - logical reference to the slide persist object ( EPP_MAINMASTER_PERSIST_KEY )
338 .WriteUInt32( 0 ) // flags - only bit 3 used, if set then slide contains shapes other than placeholders
339 .WriteInt32( 0 ) // numberTexts - number of placeholder texts stored with the persist object. Allows to display outline view without loading the slide persist objects
340 .WriteInt32( 0x80000000 | i
) // slideId - Unique slide identifier, used for OLE link monikers for example
341 .WriteUInt32( 0 ); // reserved, usually 0
347 sal_uInt32
PPTWriter::ImplInsertBookmarkURL( const OUString
& rBookmarkURL
, const sal_uInt32 nType
,
348 const OUString
& rStringVer0
, const OUString
& rStringVer1
, const OUString
& rStringVer2
, const OUString
& rStringVer3
)
350 sal_uInt32 nHyperId
= ++mnExEmbed
;
352 OUString
sBookmarkURL( rBookmarkURL
);
353 INetURLObject
aBaseURI( maBaseURI
);
354 INetURLObject
aBookmarkURI( rBookmarkURL
);
355 if( aBaseURI
.GetProtocol() == aBookmarkURI
.GetProtocol() )
357 OUString
aRelUrl( INetURLObject::GetRelURL( maBaseURI
, rBookmarkURL
) );
358 if ( !aRelUrl
.isEmpty() )
359 sBookmarkURL
= aRelUrl
;
361 maHyperlink
.emplace_back( sBookmarkURL
, nType
);
363 mpExEmbed
->WriteUInt16( 0xf )
364 .WriteUInt16( EPP_ExHyperlink
)
366 sal_uInt32 nHyperSize
, nHyperStart
= mpExEmbed
->Tell();
367 mpExEmbed
->WriteUInt16( 0 )
368 .WriteUInt16( EPP_ExHyperlinkAtom
)
370 .WriteUInt32( nHyperId
);
372 PPTWriter::WriteCString( *mpExEmbed
, rStringVer0
);
373 PPTWriter::WriteCString( *mpExEmbed
, rStringVer1
, 1 );
374 PPTWriter::WriteCString( *mpExEmbed
, rStringVer2
, 2 );
375 PPTWriter::WriteCString( *mpExEmbed
, rStringVer3
, 3 );
377 nHyperSize
= mpExEmbed
->Tell() - nHyperStart
;
378 mpExEmbed
->SeekRel( - ( static_cast<sal_Int32
>(nHyperSize
) + 4 ) );
379 mpExEmbed
->WriteUInt32( nHyperSize
);
380 mpExEmbed
->SeekRel( nHyperSize
);
384 bool PPTWriter::ImplCloseDocument()
386 sal_uInt32 nOfs
= mpPptEscherEx
->PtGetOffsetByID( EPP_Persist_Document
);
389 mpPptEscherEx
->PtReplaceOrInsert( EPP_Persist_CurrentPos
, mpStrm
->Tell() );
390 mpStrm
->Seek( nOfs
);
392 // creating the TxMasterStyleAtom
393 SvMemoryStream
aTxMasterStyleAtomStrm( 0x200, 0x200 );
395 EscherExAtom
aTxMasterStyleAtom( aTxMasterStyleAtomStrm
, EPP_TxMasterStyleAtom
, EPP_TEXTTYPE_Other
);
396 aTxMasterStyleAtomStrm
.WriteUInt16( 5 ); // paragraph count
398 for ( nLev
= 0; nLev
< 5; nLev
++ )
400 mpStyleSheet
->mpParaSheet
[ EPP_TEXTTYPE_Other
]->Write( aTxMasterStyleAtomStrm
, nLev
, false, mXPagePropSet
);
401 mpStyleSheet
->mpCharSheet
[ EPP_TEXTTYPE_Other
]->Write( aTxMasterStyleAtomStrm
, nLev
, false, mXPagePropSet
);
405 sal_uInt32 nExEmbedSize
= mpExEmbed
->TellEnd();
407 // nEnvironment : whole size of the environment container
408 sal_uInt32 nEnvironment
= maFontCollection
.GetCount() * 76 // 68 bytes per Fontenityatom and 8 Bytes per header
409 + 8 // 1 FontCollection container
410 + 20 // SrKinsoku container
411 + 18 // 1 TxSiStyleAtom
412 + aTxMasterStyleAtomStrm
.Tell() // 1 TxMasterStyleAtom;
413 + PPTExStyleSheet::SizeOfTxCFStyleAtom();
415 sal_uInt32 nBytesToInsert
= nEnvironment
+ 8;
418 nBytesToInsert
+= nExEmbedSize
+ 8 + 12;
420 nBytesToInsert
+= maSoundCollection
.GetSize();
421 nBytesToInsert
+= mpPptEscherEx
->DrawingGroupContainerSize();
422 nBytesToInsert
+= ImplMasterSlideListContainer(nullptr);
423 nBytesToInsert
+= ImplDocumentListContainer(nullptr);
425 // insert nBytes into stream and adjust depending container
426 mpPptEscherEx
->InsertAtCurrentPos( nBytesToInsert
);
428 // CREATE HYPERLINK CONTAINER
431 mpStrm
->WriteUInt16( 0xf )
432 .WriteUInt16( EPP_ExObjList
)
433 .WriteUInt32( nExEmbedSize
+ 12 )
435 .WriteUInt16( EPP_ExObjListAtom
)
437 .WriteUInt32( mnExEmbed
);
438 mpPptEscherEx
->InsertPersistOffset( EPP_Persist_ExObj
, mpStrm
->Tell() );
439 mpStrm
->WriteBytes(mpExEmbed
->GetData(), nExEmbedSize
);
442 // CREATE ENVIRONMENT
443 mpStrm
->WriteUInt16( 0xf ).WriteUInt16( EPP_Environment
).WriteUInt32( nEnvironment
);
445 // Open Container ( EPP_SrKinsoku )
446 mpStrm
->WriteUInt16( 0x2f ).WriteUInt16( EPP_SrKinsoku
).WriteUInt32( 12 );
447 mpPptEscherEx
->AddAtom( 4, EPP_SrKinsokuAtom
, 0, 3 );
448 mpStrm
->WriteInt32( 0 ); // SrKinsoku Level 0
450 // Open Container ( EPP_FontCollection )
451 mpStrm
->WriteUInt16( 0xf ).WriteUInt16( EPP_FontCollection
).WriteUInt32( maFontCollection
.GetCount() * 76 );
453 for ( sal_uInt32 i
= 0; i
< maFontCollection
.GetCount(); i
++ )
455 mpPptEscherEx
->AddAtom( 68, EPP_FontEnityAtom
, 0, i
);
456 const FontCollectionEntry
* pDesc
= maFontCollection
.GetById( i
);
457 sal_Int32 nFontLen
= pDesc
->Name
.getLength();
460 for ( sal_Int32 n
= 0; n
< 32; n
++ )
462 sal_Unicode nUniCode
= 0;
464 nUniCode
= pDesc
->Name
[n
];
465 mpStrm
->WriteUInt16( nUniCode
);
467 sal_uInt8 lfCharSet
= ANSI_CHARSET
;
468 sal_uInt8
const lfClipPrecision
= 0;
469 sal_uInt8
const lfQuality
= 6;
470 sal_uInt8 lfPitchAndFamily
= 0;
472 if ( pDesc
->CharSet
== RTL_TEXTENCODING_SYMBOL
)
473 lfCharSet
= SYMBOL_CHARSET
;
475 switch( pDesc
->Family
)
477 case css::awt::FontFamily::ROMAN
:
478 lfPitchAndFamily
|= FF_ROMAN
;
481 case css::awt::FontFamily::SWISS
:
482 lfPitchAndFamily
|= FF_SWISS
;
485 case css::awt::FontFamily::MODERN
:
486 lfPitchAndFamily
|= FF_MODERN
;
489 case css::awt::FontFamily::SCRIPT
:
490 lfPitchAndFamily
|= FF_SCRIPT
;
493 case css::awt::FontFamily::DECORATIVE
:
494 lfPitchAndFamily
|= FF_DECORATIVE
;
498 lfPitchAndFamily
|= FAMILY_DONTKNOW
;
501 switch( pDesc
->Pitch
)
503 case css::awt::FontPitch::FIXED
:
504 lfPitchAndFamily
|= FIXED_PITCH
;
508 lfPitchAndFamily
|= DEFAULT_PITCH
;
511 mpStrm
->WriteUChar( lfCharSet
)
512 .WriteUChar( lfClipPrecision
)
513 .WriteUChar( lfQuality
)
514 .WriteUChar( lfPitchAndFamily
);
516 mpStyleSheet
->WriteTxCFStyleAtom( *mpStrm
); // create style that is used for new standard objects
517 mpPptEscherEx
->AddAtom( 10, EPP_TxSIStyleAtom
);
518 mpStrm
->WriteUInt32( 7 ) // ?
519 .WriteInt16( 2 ) // ?
520 .WriteUChar( 9 ) // ?
521 .WriteUChar( 8 ) // ?
522 .WriteInt16( 0 ); // ?
524 mpStrm
->WriteBytes(aTxMasterStyleAtomStrm
.GetData(), aTxMasterStyleAtomStrm
.Tell());
525 maSoundCollection
.Write( *mpStrm
);
526 mpPptEscherEx
->WriteDrawingGroupContainer( *mpStrm
);
527 ImplMasterSlideListContainer( mpStrm
.get() );
528 ImplDocumentListContainer( mpStrm
.get() );
530 sal_uInt32 nOldPos
= mpPptEscherEx
->PtGetOffsetByID( EPP_Persist_CurrentPos
);
533 mpStrm
->Seek( nOldPos
);
540 bool PropValue::GetPropertyValue(
542 const css::uno::Reference
< css::beans::XPropertySet
> & rXPropSet
,
543 const OUString
& rString
,
544 bool bTestPropertyAvailability
)
546 bool bRetValue
= true;
547 if ( bTestPropertyAvailability
)
552 css::uno::Reference
< css::beans::XPropertySetInfo
> aXPropSetInfo( rXPropSet
->getPropertySetInfo() );
553 if ( aXPropSetInfo
.is() )
554 bRetValue
= aXPropSetInfo
->hasPropertyByName( rString
);
556 catch( css::uno::Exception
& )
565 rAny
= rXPropSet
->getPropertyValue( rString
);
566 if ( !rAny
.hasValue() )
569 catch( css::uno::Exception
& )
577 css::beans::PropertyState
PropValue::GetPropertyState(
578 const css::uno::Reference
< css::beans::XPropertySet
> & rXPropSet
,
579 const OUString
& rPropertyName
)
581 css::beans::PropertyState eRetValue
= css::beans::PropertyState_AMBIGUOUS_VALUE
;
584 css::uno::Reference
< css::beans::XPropertyState
> aXPropState( rXPropSet
, css::uno::UNO_QUERY
);
585 if ( aXPropState
.is() )
586 eRetValue
= aXPropState
->getPropertyState( rPropertyName
);
588 catch( css::uno::Exception
& )
595 bool PropValue::ImplGetPropertyValue( const OUString
& rString
)
597 return GetPropertyValue( mAny
, mXPropSet
, rString
);
600 bool PropValue::ImplGetPropertyValue( const css::uno::Reference
< css::beans::XPropertySet
> & aXPropSet
, const OUString
& rString
)
602 return GetPropertyValue( mAny
, aXPropSet
, rString
);
605 bool PropStateValue::ImplGetPropertyValue( const OUString
& rString
, bool bGetPropertyState
)
607 ePropState
= css::beans::PropertyState_AMBIGUOUS_VALUE
;
608 bool bRetValue
= true;
610 css::uno::Reference
< css::beans::XPropertySetInfo
>
611 aXPropSetInfo( mXPropSet
->getPropertySetInfo() );
612 if ( !aXPropSetInfo
.is() )
617 mAny
= mXPropSet
->getPropertyValue( rString
);
618 if ( !mAny
.hasValue() )
620 else if ( bGetPropertyState
)
621 ePropState
= mXPropState
->getPropertyState( rString
);
623 ePropState
= css::beans::PropertyState_DIRECT_VALUE
;
625 catch( css::uno::Exception
& )
632 void PPTWriter::ImplWriteParagraphs( SvStream
& rOut
, TextObj
& rTextObj
)
634 bool bFirstParagraph
= true;
635 sal_uInt32 nCharCount
;
636 sal_uInt32 nPropertyFlags
= 0;
637 sal_Int16 nLineSpacing
;
638 int nInstance
= rTextObj
.GetInstance();
640 for ( sal_uInt32 i
= 0; i
< rTextObj
.ParagraphCount(); ++i
, bFirstParagraph
= false )
642 ParagraphObj
* pPara
= rTextObj
.GetParagraph(i
);
643 const PortionObj
& rPortion
= pPara
->front();
644 nCharCount
= pPara
->CharacterCount();
646 if ( ( pPara
->meTextAdjust
== css::beans::PropertyState_DIRECT_VALUE
) ||
647 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_Adjust
, pPara
->mnTextAdjust
) ) )
648 nPropertyFlags
|= 0x00000800;
649 nLineSpacing
= pPara
->mnLineSpacing
;
651 const FontCollectionEntry
* pDesc
= maFontCollection
.GetById( rPortion
.mnFont
);
652 sal_Int16 nNormalSpacing
= 100;
653 if ( !mbFontIndependentLineSpacing
&& pDesc
)
656 fN
*= pDesc
->Scaling
;
657 nNormalSpacing
= static_cast<sal_Int16
>( fN
+ 0.5 );
659 if ( !mbFontIndependentLineSpacing
&& bFirstParagraph
&& ( nLineSpacing
> nNormalSpacing
) ) // sj: i28747, no replacement for fixed linespacing
661 nLineSpacing
= nNormalSpacing
;
662 nPropertyFlags
|= 0x00001000;
666 if ( nLineSpacing
> 0 )
668 if ( !mbFontIndependentLineSpacing
&& pDesc
)
669 nLineSpacing
= static_cast<sal_Int16
>( static_cast<double>(nLineSpacing
) * pDesc
->Scaling
+ 0.5 );
673 if ( !pPara
->mbFixedLineSpacing
&& rPortion
.mnCharHeight
> static_cast<sal_uInt16
>( static_cast<double>(-nLineSpacing
) * 0.001 * 72.0 / 2.54 ) ) // 1/100mm to point
674 nLineSpacing
= nNormalSpacing
;
676 nLineSpacing
= static_cast<sal_Int16
>( static_cast<double>(nLineSpacing
) / 4.40972 );
678 if ( ( pPara
->meLineSpacing
== css::beans::PropertyState_DIRECT_VALUE
) ||
679 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_LineFeed
, nLineSpacing
) ) )
680 nPropertyFlags
|= 0x00001000;
682 if ( ( pPara
->meLineSpacingTop
== css::beans::PropertyState_DIRECT_VALUE
) ||
683 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_UpperDist
, pPara
->mnLineSpacingTop
) ) )
684 nPropertyFlags
|= 0x00002000;
685 if ( ( pPara
->meLineSpacingBottom
== css::beans::PropertyState_DIRECT_VALUE
) ||
686 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_LowerDist
, pPara
->mnLineSpacingBottom
) ) )
687 nPropertyFlags
|= 0x00004000;
688 if ( ( pPara
->meForbiddenRules
== css::beans::PropertyState_DIRECT_VALUE
) ||
689 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_UpperDist
, pPara
->mbForbiddenRules
? 1 : 0 ) ) )
690 nPropertyFlags
|= 0x00020000;
691 if ( ( pPara
->meParagraphPunctation
== css::beans::PropertyState_DIRECT_VALUE
) ||
692 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_UpperDist
, pPara
->mbParagraphPunctation
? 1 : 0 ) ) )
693 nPropertyFlags
|= 0x00080000;
694 if ( ( pPara
->meBiDi
== css::beans::PropertyState_DIRECT_VALUE
) ||
695 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_BiDi
, pPara
->mnBiDi
) ) )
696 nPropertyFlags
|= 0x00200000;
698 sal_Int32 nBuRealSize
= pPara
->nBulletRealSize
;
699 sal_Int16 nBulletFlags
= pPara
->nBulletFlags
;
701 if ( pPara
->bExtendedParameters
)
702 nPropertyFlags
|= pPara
->nParaFlags
;
705 nPropertyFlags
|= 1; // turn off bullet explicit
709 // Write nTextOfs and nBullets
710 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_TextOfs
, pPara
->nTextOfs
) )
711 nPropertyFlags
|= 0x100;
712 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, ParaAttr_BulletOfs
, pPara
->nBulletOfs
))
713 nPropertyFlags
|= 0x400;
715 FontCollectionEntry
aFontDescEntry( pPara
->aFontDesc
.Name
, pPara
->aFontDesc
.Family
, pPara
->aFontDesc
.Pitch
, pPara
->aFontDesc
.CharSet
);
716 sal_uInt16 nFontId
= static_cast<sal_uInt16
>(maFontCollection
.GetId( aFontDescEntry
));
718 rOut
.WriteUInt32( nCharCount
)
719 .WriteUInt16( pPara
->nDepth
) // Level
720 .WriteUInt32( nPropertyFlags
); // Paragraph Attribut Set
722 if ( nPropertyFlags
& 0xf )
723 rOut
.WriteInt16( nBulletFlags
);
724 if ( nPropertyFlags
& 0x80 )
725 rOut
.WriteUInt16( pPara
->cBulletId
);
726 if ( nPropertyFlags
& 0x10 )
727 rOut
.WriteUInt16( nFontId
);
728 if ( nPropertyFlags
& 0x40 )
729 rOut
.WriteInt16( nBuRealSize
);
730 if ( nPropertyFlags
& 0x20 )
732 sal_uInt32 nBulletColor
= pPara
->nBulletColor
;
733 if ( nBulletColor
== sal_uInt32(COL_AUTO
) )
735 bool bIsDark
= false;
737 if ( PropValue::GetPropertyValue( aAny
, mXPagePropSet
, "IsBackgroundDark", true ) )
739 nBulletColor
= bIsDark
? 0xffffff : 0x000000;
741 nBulletColor
&= 0xffffff;
742 nBulletColor
|= 0xfe000000;
743 rOut
.WriteUInt32( nBulletColor
);
745 if ( nPropertyFlags
& 0x00000800 )
746 rOut
.WriteUInt16( pPara
->mnTextAdjust
);
747 if ( nPropertyFlags
& 0x00001000 )
748 rOut
.WriteUInt16( nLineSpacing
);
749 if ( nPropertyFlags
& 0x00002000 )
750 rOut
.WriteUInt16( pPara
->mnLineSpacingTop
);
751 if ( nPropertyFlags
& 0x00004000 )
752 rOut
.WriteUInt16( pPara
->mnLineSpacingBottom
);
753 if ( nPropertyFlags
& 0x100 )
754 rOut
.WriteUInt16( pPara
->nTextOfs
);
755 if ( nPropertyFlags
& 0x400 )
756 rOut
.WriteUInt16( pPara
->nBulletOfs
);
757 if ( nPropertyFlags
& 0x000e0000 )
759 sal_uInt16 nAsianSettings
= 0;
760 if ( pPara
->mbForbiddenRules
)
762 if ( pPara
->mbParagraphPunctation
)
764 rOut
.WriteUInt16( nAsianSettings
);
766 if ( nPropertyFlags
& 0x200000 )
767 rOut
.WriteUInt16( pPara
->mnBiDi
);
771 void PPTWriter::ImplWritePortions( SvStream
& rOut
, TextObj
& rTextObj
)
773 sal_uInt32 nPropertyFlags
;
774 int nInstance
= rTextObj
.GetInstance();
776 for ( sal_uInt32 i
= 0; i
< rTextObj
.ParagraphCount(); ++i
)
778 ParagraphObj
* pPara
= rTextObj
.GetParagraph(i
);
779 for ( std::vector
<std::unique_ptr
<PortionObj
> >::const_iterator it
= pPara
->begin(); it
!= pPara
->end(); ++it
)
781 const PortionObj
& rPortion
= **it
;
783 sal_uInt32 nCharAttr
= rPortion
.mnCharAttr
;
784 sal_uInt32 nCharColor
= rPortion
.mnCharColor
;
786 if ( nCharColor
== sal_uInt32(COL_AUTO
) ) // nCharColor depends to the background color
788 bool bIsDark
= false;
790 if ( PropValue::GetPropertyValue( aAny
, mXPagePropSet
, "IsBackgroundDark", true ) )
792 nCharColor
= bIsDark
? 0xffffff : 0x000000;
795 nCharColor
&= 0xffffff;
797 /* the portion is using the embossed or engraved attribute, which we want to map to the relief feature of PPT.
798 Because the relief feature of PPT is dependent to the background color, such a mapping can not always be used. */
799 if ( nCharAttr
& 0x200 )
801 sal_uInt32 nBackgroundColor
= 0xffffff;
803 if ( !nCharColor
) // special treatment for
804 nCharColor
= 0xffffff; // black fontcolor
807 css::drawing::FillStyle
aFS( css::drawing::FillStyle_NONE
);
808 if ( PropValue::GetPropertyValue( aAny
, mXPropSet
, "FillStyle" ) )
812 case css::drawing::FillStyle_GRADIENT
:
814 ::tools::Rectangle
aRect( Point(), Size( 28000, 21000 ) );
815 EscherPropertyContainer
aPropOpt( mpPptEscherEx
->GetGraphicProvider(), mpPicStrm
.get(), aRect
);
816 aPropOpt
.CreateGradientProperties( mXPropSet
);
817 aPropOpt
.GetOpt( ESCHER_Prop_fillColor
, nBackgroundColor
);
820 case css::drawing::FillStyle_SOLID
:
822 if ( PropValue::GetPropertyValue( aAny
, mXPropSet
, "FillColor" ) )
823 nBackgroundColor
= EscherEx::GetColor( *o3tl::doAccess
<sal_uInt32
>(aAny
) );
826 case css::drawing::FillStyle_NONE
:
828 css::uno::Any aBackAny
;
829 css::drawing::FillStyle
aBackFS( css::drawing::FillStyle_NONE
);
830 if ( PropValue::GetPropertyValue( aBackAny
, mXBackgroundPropSet
, "FillStyle" ) )
831 aBackAny
>>= aBackFS
;
834 case css::drawing::FillStyle_GRADIENT
:
836 ::tools::Rectangle
aRect( Point(), Size( 28000, 21000 ) );
837 EscherPropertyContainer
aPropOpt( mpPptEscherEx
->GetGraphicProvider(), mpPicStrm
.get(), aRect
);
838 aPropOpt
.CreateGradientProperties( mXBackgroundPropSet
);
839 aPropOpt
.GetOpt( ESCHER_Prop_fillColor
, nBackgroundColor
);
842 case css::drawing::FillStyle_SOLID
:
844 if ( PropValue::GetPropertyValue( aAny
, mXBackgroundPropSet
, "FillColor" ) )
845 nBackgroundColor
= EscherEx::GetColor( *o3tl::doAccess
<sal_uInt32
>(aAny
) );
857 sal_Int32 nB
= nBackgroundColor
& 0xff;
858 nB
+= static_cast<sal_uInt8
>( nBackgroundColor
>> 8 );
859 nB
+= static_cast<sal_uInt8
>( nBackgroundColor
>> 16 );
860 // if the background color is nearly black, relief can't been used, because the text would not be visible
861 if ( nB
< 0x60 || ( nBackgroundColor
!= nCharColor
) )
865 // now check if the text is part of a group, and if the previous object has the same color than the fontcolor
866 // ( and if fillcolor is not available the background color ), it is sometimes
867 // not possible to export the 'embossed' flag
868 if ( ( GetCurrentGroupLevel() > 0 ) && ( GetCurrentGroupIndex() >= 1 ) )
870 css::uno::Reference
< css::drawing::XShape
> aGroupedShape( GetCurrentGroupAccess()->getByIndex( GetCurrentGroupIndex() - 1 ), uno::UNO_QUERY
);
871 if( aGroupedShape
.is() )
873 css::uno::Reference
< css::beans::XPropertySet
> aPropSetOfNextShape
874 ( aGroupedShape
, css::uno::UNO_QUERY
);
875 if ( aPropSetOfNextShape
.is() )
877 if ( PropValue::GetPropertyValue( aAny
, aPropSetOfNextShape
,
878 "FillColor", true ) )
880 if ( nCharColor
== EscherEx::GetColor( *o3tl::doAccess
<sal_uInt32
>(aAny
) ) )
890 nCharColor
|= 0xfe000000;
891 if ( nInstance
== 4 ) // special handling for normal textobjects:
892 nPropertyFlags
|= nCharAttr
& 0x217; // not all attributes are inherited
895 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Bold
, nCharAttr
) )
897 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Italic
, nCharAttr
) )
899 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Underline
, nCharAttr
) )
901 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Shadow
, nCharAttr
) )
902 nPropertyFlags
|= 0x10;
903 if ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Embossed
, nCharAttr
) )
904 nPropertyFlags
|= 512;
906 if ( rTextObj
.HasExtendedBullets() )
908 nPropertyFlags
|= ( i
& 0x3f ) << 10 ;
909 nCharAttr
|= ( i
& 0x3f ) << 10;
911 if ( ( rPortion
.meFontName
== css::beans::PropertyState_DIRECT_VALUE
) ||
912 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Font
, rPortion
.mnFont
) ) )
913 nPropertyFlags
|= 0x00010000;
914 if ( ( rPortion
.meAsianOrComplexFont
== css::beans::PropertyState_DIRECT_VALUE
) ||
915 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_AsianOrComplexFont
, rPortion
.mnAsianOrComplexFont
) ) )
916 nPropertyFlags
|= 0x00200000;
917 if ( ( rPortion
.meCharHeight
== css::beans::PropertyState_DIRECT_VALUE
) ||
918 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_FontHeight
, rPortion
.mnCharHeight
) ) )
919 nPropertyFlags
|= 0x00020000;
920 if ( ( rPortion
.meCharColor
== css::beans::PropertyState_DIRECT_VALUE
) ||
921 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_FontColor
, nCharColor
& 0xffffff ) ) )
922 nPropertyFlags
|= 0x00040000;
923 if ( ( rPortion
.meCharEscapement
== css::beans::PropertyState_DIRECT_VALUE
) ||
924 ( mpStyleSheet
->IsHardAttribute( nInstance
, pPara
->nDepth
, CharAttr_Escapement
, rPortion
.mnCharEscapement
) ) )
925 nPropertyFlags
|= 0x00080000;
927 sal_uInt32 nCharCount
= rPortion
.Count();
929 rOut
.WriteUInt32( nCharCount
)
930 .WriteUInt32( nPropertyFlags
); //PropertyFlags
932 if ( nPropertyFlags
& 0xffff )
933 rOut
.WriteUInt16( nCharAttr
);
934 if ( nPropertyFlags
& 0x00010000 )
935 rOut
.WriteUInt16( rPortion
.mnFont
);
936 if ( nPropertyFlags
& 0x00200000 )
937 rOut
.WriteUInt16( rPortion
.mnAsianOrComplexFont
);
938 if ( nPropertyFlags
& 0x00020000 )
939 rOut
.WriteUInt16( rPortion
.mnCharHeight
);
940 if ( nPropertyFlags
& 0x00040000 )
941 rOut
.WriteUInt32( nCharColor
);
942 if ( nPropertyFlags
& 0x00080000 )
943 rOut
.WriteInt16( rPortion
.mnCharEscapement
);
949 * Loads and converts text from shape, value is stored in mnTextSize.
951 bool PPTWriter::ImplGetText()
954 mbFontIndependentLineSpacing
= false;
955 mXText
.set( mXShape
, css::uno::UNO_QUERY
);
959 mnTextSize
= mXText
->getString().getLength();
961 if ( GetPropertyValue( aAny
, mXPropSet
, "FontIndependentLineSpacing", true ) )
962 aAny
>>= mbFontIndependentLineSpacing
;
964 return ( mnTextSize
!= 0 );
967 void PPTWriter::ImplFlipBoundingBox( EscherPropertyContainer
& rPropOpt
)
970 mnAngle
= ( 36000 + mnAngle
) % 36000;
972 mnAngle
= ( 36000 - ( mnAngle
% 36000 ) );
974 double fCos
= cos( static_cast<double>(mnAngle
) * F_PI18000
);
975 double fSin
= sin( static_cast<double>(mnAngle
) * F_PI18000
);
977 double fWidthHalf
= maRect
.GetWidth() / 2.0;
978 double fHeightHalf
= maRect
.GetHeight() / 2.0;
980 double fXDiff
= fCos
* fWidthHalf
+ fSin
* (-fHeightHalf
);
981 double fYDiff
= - ( fSin
* fWidthHalf
- fCos
* ( -fHeightHalf
) );
983 maRect
.Move( static_cast<sal_Int32
>( -( fWidthHalf
- fXDiff
) ), static_cast<sal_Int32
>( - ( fHeightHalf
+ fYDiff
) ) );
986 mnAngle
&=~0xffff; // round nAngle to full grads
987 rPropOpt
.AddOpt( ESCHER_Prop_Rotation
, mnAngle
);
989 if ( ( mnAngle
>= ( 45 << 16 ) && mnAngle
< ( 135 << 16 ) ) ||
990 ( mnAngle
>= ( 225 << 16 ) && mnAngle
< ( 315 << 16 ) ) )
992 // Maddeningly, in those two areas of PPT is the BoundingBox already
993 // vertical. Therefore, we need to put down it BEFORE THE ROTATION.
994 css::awt::Point
aTopLeft( static_cast<sal_Int32
>( maRect
.Left() + fWidthHalf
- fHeightHalf
), static_cast<sal_Int32
>( maRect
.Top() + fHeightHalf
- fWidthHalf
) );
995 const long nRotatedWidth(maRect
.GetHeight());
996 const long nRotatedHeight(maRect
.GetWidth());
997 const Size
aNewSize(nRotatedWidth
, nRotatedHeight
);
998 maRect
= ::tools::Rectangle( Point( aTopLeft
.X
, aTopLeft
.Y
), aNewSize
);
1002 void PPTWriter::ImplAdjustFirstLineLineSpacing( TextObj
& rTextObj
, EscherPropertyContainer
& rPropOpt
)
1004 if ( mbFontIndependentLineSpacing
)
1007 if ( !rTextObj
.ParagraphCount() )
1010 ParagraphObj
* pPara
= rTextObj
.GetParagraph(0);
1011 if ( pPara
->empty() )
1014 const PortionObj
& rPortion
= pPara
->front();
1015 sal_Int16 nLineSpacing
= pPara
->mnLineSpacing
;
1016 const FontCollectionEntry
* pDesc
= maFontCollection
.GetById( rPortion
.mnFont
);
1018 nLineSpacing
= static_cast<sal_Int16
>( static_cast<double>(nLineSpacing
) * pDesc
->Scaling
+ 0.5 );
1020 if ( ( nLineSpacing
> 0 ) && ( nLineSpacing
< 100 ) )
1022 double fCharHeight
= rPortion
.mnCharHeight
;
1023 fCharHeight
*= 2540 / 72.0;
1024 fCharHeight
*= 100 - nLineSpacing
;
1027 sal_uInt32 nUpperDistance
= 0;
1028 rPropOpt
.GetOpt( ESCHER_Prop_dyTextTop
, nUpperDistance
);
1029 nUpperDistance
+= static_cast< sal_uInt32
>( fCharHeight
* 360.0 );
1030 rPropOpt
.AddOpt( ESCHER_Prop_dyTextTop
, nUpperDistance
);
1034 void PPTWriter::ImplWriteTextStyleAtom( SvStream
& rOut
, int nTextInstance
, sal_uInt32 nAtomInstance
,
1035 TextRuleEntry
* pTextRule
, SvStream
& rExtBuStr
, EscherPropertyContainer
* pPropOpt
)
1037 PPTExParaSheet
& rParaSheet
= mpStyleSheet
->GetParaSheet( nTextInstance
);
1039 rOut
.WriteUInt32( ( EPP_TextHeaderAtom
<< 16 ) | ( nAtomInstance
<< 4 ) ).WriteUInt32( 4 )
1040 .WriteInt32( nTextInstance
);
1042 if ( mbEmptyPresObj
)
1044 if ( mbEmptyPresObj
)
1047 ParagraphObj
* pPara
;
1048 TextObjBinary
aTextObj( mXText
, nTextInstance
, maFontCollection
, static_cast<PPTExBulletProvider
&>(*this) );
1050 // leaving out EPP_TextCharsAtom w/o text - still write out
1051 // attribute info though
1053 aTextObj
.Write( &rOut
);
1055 if ( pPropOpt
&& mType
!= "drawing.Table" )
1056 ImplAdjustFirstLineLineSpacing( aTextObj
, *pPropOpt
);
1058 sal_uInt32 nSize
, nPos
= rOut
.Tell();
1060 rOut
.WriteUInt32( EPP_StyleTextPropAtom
<< 16 ).WriteUInt32( 0 );
1061 ImplWriteParagraphs( rOut
, aTextObj
);
1062 ImplWritePortions( rOut
, aTextObj
);
1063 nSize
= rOut
.Tell() - nPos
;
1064 rOut
.SeekRel( - ( static_cast<sal_Int32
>(nSize
) - 4 ) );
1065 rOut
.WriteUInt32( nSize
- 8 );
1066 rOut
.SeekRel( nSize
- 8 );
1068 for ( sal_uInt32 i
= 0; i
< aTextObj
.ParagraphCount(); ++i
)
1070 pPara
= aTextObj
.GetParagraph(i
);
1071 for ( std::vector
<std::unique_ptr
<PortionObj
> >::const_iterator it
= pPara
->begin(); it
!= pPara
->end(); ++it
)
1073 const PortionObj
& rPortion
= **it
;
1074 if ( rPortion
.mpFieldEntry
)
1076 const FieldEntry
* pFieldEntry
= rPortion
.mpFieldEntry
.get();
1078 switch ( pFieldEntry
->nFieldType
>> 28 )
1083 rOut
.WriteUInt32( EPP_DateTimeMCAtom
<< 16 ).WriteUInt32( 8 )
1084 .WriteUInt32( pFieldEntry
->nFieldStartPos
) // TxtOffset to TxtField;
1085 .WriteUChar( pFieldEntry
->nFieldType
& 0xff ) // Type
1086 .WriteUChar( 0 ).WriteUInt16( 0 ); // PadBytes
1091 rOut
.WriteUInt32( EPP_SlideNumberMCAtom
<< 16 ).WriteUInt32( 4 )
1092 .WriteUInt32( pFieldEntry
->nFieldStartPos
);
1097 sal_uInt32 nPageIndex
= 0;
1099 OUString
aFile( pFieldEntry
->aFieldUrl
);
1100 OUString
aTarget( pFieldEntry
->aFieldUrl
);
1101 INetURLObject
aUrl( pFieldEntry
->aFieldUrl
);
1102 if ( INetProtocol::File
== aUrl
.GetProtocol() )
1103 aFile
= aUrl
.PathToFileName();
1104 else if ( INetProtocol::Smb
== aUrl
.GetProtocol() )
1106 // Convert smb notation to '\\' and skip the 'smb:' part
1107 aFile
= aUrl
.GetMainURL(INetURLObject::DecodeMechanism::NONE
).copy(4);
1108 aFile
= aFile
.replaceAll( "/", "\\" );
1111 else if ( pFieldEntry
->aFieldUrl
.startsWith("#") )
1113 OUString
aPage( INetURLObject::decode( pFieldEntry
->aFieldUrl
, INetURLObject::DecodeMechanism::WithCharset
) );
1114 aPage
= aPage
.copy( 1 );
1116 std::vector
<OUString
>::const_iterator pIter
= std::find(
1117 maSlideNameList
.begin(),maSlideNameList
.end(),aPage
);
1119 if ( pIter
!= maSlideNameList
.end() )
1121 nPageIndex
= pIter
- maSlideNameList
.begin();
1122 aPageUrl
= OUString::number(256 + nPageIndex
) +
1124 OUString::number(nPageIndex
+ 1) +
1126 OUString::number(nPageIndex
+ 1);
1129 sal_uInt32
nHyperId(0);
1130 if ( !aPageUrl
.isEmpty() )
1131 nHyperId
= ImplInsertBookmarkURL( aPageUrl
, 1 | ( nPageIndex
<< 8 ) | ( 1U << 31 ), pFieldEntry
->aRepresentation
, "", "", aPageUrl
);
1133 nHyperId
= ImplInsertBookmarkURL( pFieldEntry
->aFieldUrl
, 2 | ( nHyperId
<< 8 ), aFile
, aTarget
, "", "" );
1135 rOut
.WriteUInt32( ( EPP_InteractiveInfo
<< 16 ) | 0xf ).WriteUInt32( 24 )
1136 .WriteUInt32( EPP_InteractiveInfoAtom
<< 16 ).WriteUInt32( 16 )
1137 .WriteUInt32( 0 ) // soundref
1138 .WriteUInt32( nHyperId
) // hyperlink id
1139 .WriteUChar( 4 ) // hyperlink action
1140 .WriteUChar( 0 ) // ole verb
1141 .WriteUChar( 0 ) // jump
1142 .WriteUChar( 0 ) // flags
1143 .WriteUChar( 8 ) // hyperlink type ?
1144 .WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 )
1145 .WriteUInt32( EPP_TxInteractiveInfoAtom
<< 16 ).WriteUInt32( 8 )
1146 .WriteUInt32( pFieldEntry
->nFieldStartPos
)
1147 .WriteUInt32( pFieldEntry
->nFieldEndPos
);
1152 rOut
.WriteUInt32( EPP_GenericDateMCAtom
<< 16 ).WriteUInt32( 4 )
1153 .WriteUInt32( pFieldEntry
->nFieldStartPos
);
1158 rOut
.WriteUInt32( EPP_HeaderMCAtom
<< 16 ).WriteUInt32( 4 )
1159 .WriteUInt32( pFieldEntry
->nFieldStartPos
);
1164 rOut
.WriteUInt32( EPP_FooterMCAtom
<< 16 ).WriteUInt32( 4 )
1165 .WriteUInt32( pFieldEntry
->nFieldStartPos
);
1175 aTextObj
.WriteTextSpecInfo( &rOut
);
1177 // write Star Office Default TabSizes (if necessary)
1178 if ( aTextObj
.ParagraphCount() )
1180 pPara
= aTextObj
.GetParagraph(0);
1181 sal_uInt32 nParaFlags
= 0x1f;
1182 sal_Int16 nMask
, nNumberingRule
[ 10 ];
1183 sal_uInt32 nTextOfs
= pPara
->nTextOfs
;
1184 sal_uInt32 nTabs
= pPara
->maTabStop
.getLength();
1185 const css::style::TabStop
* pTabStop
= pPara
->maTabStop
.getConstArray();
1187 for ( sal_uInt32 i
= 0; i
< aTextObj
.ParagraphCount(); ++i
)
1189 pPara
= aTextObj
.GetParagraph(i
);
1190 if ( pPara
->bExtendedParameters
)
1192 nMask
= 1 << pPara
->nDepth
;
1193 if ( nParaFlags
& nMask
)
1195 nParaFlags
&=~ nMask
;
1196 if ( ( rParaSheet
.maParaLevel
[ pPara
->nDepth
].mnTextOfs
!= pPara
->nTextOfs
) ||
1197 ( rParaSheet
.maParaLevel
[ pPara
->nDepth
].mnBulletOfs
!= pPara
->nBulletOfs
) )
1199 nParaFlags
|= nMask
<< 16;
1200 nNumberingRule
[ pPara
->nDepth
<< 1 ] = pPara
->nTextOfs
;
1201 nNumberingRule
[ ( pPara
->nDepth
<< 1 ) + 1 ] = static_cast<sal_Int16
>(pPara
->nBulletOfs
);
1208 sal_Int32 nDefaultTabSizeSrc
= 2011; // I've no idea where this number came from, honestly
1209 const uno::Reference
< beans::XPropertySet
> xPropSet( mXModel
, uno::UNO_QUERY
);
1210 if ( xPropSet
.is() )
1212 if(ImplGetPropertyValue( xPropSet
, "TabStop" ))
1214 sal_Int32
nTabStop( 0 );
1215 if ( mAny
>>= nTabStop
)
1216 nDefaultTabSizeSrc
= nTabStop
;
1219 const sal_uInt32 nDefaultTabSize
= MapSize( awt::Size( nDefaultTabSizeSrc
, 1 ) ).Width
;
1220 sal_uInt32 nDefaultTabs
= std::abs( maRect
.GetWidth() ) / nDefaultTabSize
;
1222 nDefaultTabs
-= static_cast<sal_Int32
>( ( ( pTabStop
[ nTabs
- 1 ].Position
/ 4.40972 ) + nTextOfs
) / nDefaultTabSize
);
1223 if ( static_cast<sal_Int32
>(nDefaultTabs
) < 0 )
1226 sal_uInt32 nTabCount
= nTabs
+ nDefaultTabs
;
1227 sal_uInt32 i
, nTextRulerAtomFlags
= 0;
1230 nTextRulerAtomFlags
|= 4;
1232 nTextRulerAtomFlags
|= ( ( nParaFlags
<< 3 ) | ( nParaFlags
<< 8 ) );
1234 if ( nTextRulerAtomFlags
)
1236 SvStream
* pRuleOut
= &rOut
;
1239 pTextRule
->pOut
.reset( new SvMemoryStream( 0x100, 0x100 ) );
1240 pRuleOut
= pTextRule
->pOut
.get();
1243 sal_uInt32 nRulePos
= pRuleOut
->Tell();
1244 pRuleOut
->WriteUInt32( EPP_TextRulerAtom
<< 16 ).WriteUInt32( 0 );
1245 pRuleOut
->WriteUInt32( nTextRulerAtomFlags
);
1246 if ( nTextRulerAtomFlags
& 4 )
1248 pRuleOut
->WriteUInt16( nTabCount
);
1249 for ( const css::style::TabStop
& rTabStop
: std::as_const(pPara
->maTabStop
) )
1251 sal_uInt16 nPosition
= static_cast<sal_uInt16
>( ( rTabStop
.Position
/ 4.40972 ) + nTextOfs
);
1253 switch ( rTabStop
.Alignment
)
1255 case css::style::TabAlign_DECIMAL
: nType
= 3; break;
1256 case css::style::TabAlign_RIGHT
: nType
= 2; break;
1257 case css::style::TabAlign_CENTER
: nType
= 1; break;
1259 case css::style::TabAlign_LEFT
:
1262 pRuleOut
->WriteUInt16( nPosition
)
1263 .WriteUInt16( nType
);
1266 sal_uInt32 nWidth
= 1;
1268 nWidth
+= static_cast<sal_Int32
>( ( pTabStop
[ nTabs
- 1 ].Position
/ 4.40972 + nTextOfs
) / nDefaultTabSize
);
1269 nWidth
*= nDefaultTabSize
;
1270 for ( i
= 0; i
< nDefaultTabs
; i
++, nWidth
+= nDefaultTabSize
)
1271 pRuleOut
->WriteUInt32( nWidth
);
1273 for ( i
= 0; i
< 5; i
++ )
1275 if ( nTextRulerAtomFlags
& ( 8 << i
) )
1276 pRuleOut
->WriteInt16( nNumberingRule
[ i
<< 1 ] );
1277 if ( nTextRulerAtomFlags
& ( 256 << i
) )
1278 pRuleOut
->WriteInt16( nNumberingRule
[ ( i
<< 1 ) + 1 ] );
1280 sal_uInt32 nBufSize
= pRuleOut
->Tell() - nRulePos
;
1281 pRuleOut
->SeekRel( - ( static_cast<sal_Int32
>(nBufSize
) - 4 ) );
1282 pRuleOut
->WriteUInt32( nBufSize
- 8 );
1283 pRuleOut
->SeekRel( nBufSize
- 8 );
1286 if ( !aTextObj
.HasExtendedBullets() )
1289 if ( !aTextObj
.ParagraphCount() )
1292 sal_uInt32 nNumberingType
= 0, nPos2
= rExtBuStr
.Tell();
1294 rExtBuStr
.WriteUInt32( EPP_PST_ExtendedParagraphAtom
<< 16 ).WriteUInt32( 0 );
1296 for ( sal_uInt32 i
= 0; i
< aTextObj
.ParagraphCount(); ++i
)
1298 ParagraphObj
* pBulletPara
= aTextObj
.GetParagraph(i
);
1299 sal_uInt32 nBulletFlags
= 0;
1300 sal_uInt16 nBulletId
= pBulletPara
->nBulletId
;
1302 if ( pBulletPara
->bExtendedBulletsUsed
)
1304 nBulletFlags
= 0x800000;
1305 if ( pBulletPara
->nNumberingType
!= SVX_NUM_BITMAP
)
1306 nBulletFlags
= 0x3000000;
1308 rExtBuStr
.WriteUInt32( nBulletFlags
);
1310 if ( nBulletFlags
& 0x800000 )
1311 rExtBuStr
.WriteUInt16( nBulletId
);
1312 if ( nBulletFlags
& 0x1000000 )
1314 switch( pBulletPara
->nNumberingType
)
1316 case SVX_NUM_NUMBER_NONE
:
1317 case SVX_NUM_CHAR_SPECIAL
:
1320 case SVX_NUM_CHARS_UPPER_LETTER
:
1321 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1322 case SVX_NUM_CHARS_LOWER_LETTER
:
1323 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1324 case SVX_NUM_ROMAN_UPPER
:
1325 case SVX_NUM_ROMAN_LOWER
:
1326 case SVX_NUM_ARABIC
:
1327 case SVX_NUM_NUMBER_UPPER_ZH
:
1328 case SVX_NUM_CIRCLE_NUMBER
:
1329 case SVX_NUM_NUMBER_UPPER_ZH_TW
:
1330 case SVX_NUM_NUMBER_LOWER_ZH
:
1331 case SVX_NUM_FULL_WIDTH_ARABIC
:
1332 nNumberingType
= pBulletPara
->nMappedNumType
;
1335 case SVX_NUM_BITMAP
:
1340 rExtBuStr
.WriteUInt32( nNumberingType
);
1342 if ( nBulletFlags
& 0x2000000 )
1343 rExtBuStr
.WriteUInt16( pBulletPara
->nStartWith
);
1344 rExtBuStr
.WriteUInt32( 0 ).WriteUInt32( 0 );
1346 sal_uInt32 nBulletSize
= ( rExtBuStr
.Tell() - nPos2
) - 8;
1347 rExtBuStr
.SeekRel( - ( static_cast<sal_Int32
>(nBulletSize
) + 4 ) );
1348 rExtBuStr
.WriteUInt32( nBulletSize
);
1349 rExtBuStr
.SeekRel( nBulletSize
);
1352 void PPTWriter::ImplWriteClickAction( SvStream
& rSt
, css::presentation::ClickAction eCa
, bool bMediaClickAction
)
1354 sal_uInt32 nSoundRef
= 0; // a reference to a sound in the sound collection, or NULL.
1355 sal_uInt32 nHyperLinkID
= 0;// a persistent unique identifier to an external hyperlink object (only valid when action == HyperlinkAction).
1356 sal_uInt8 nAction
= 0; // Action See Action Table
1357 sal_uInt8
const nOleVerb
= 0; // OleVerb Only valid when action == OLEAction. OLE verb to use, 0 = first verb, 1 = second verb, etc.
1358 sal_uInt8 nJump
= 0; // Jump See Jump Table
1359 sal_uInt8
const nFlags
= 0; // Bit 1: Animated. If 1, then button is animated
1360 // Bit 2: Stop sound. If 1, then stop current sound when button is pressed.
1361 // Bit 3: CustomShowReturn. If 1, and this is a jump to custom show, then return to this slide after custom show.
1362 sal_uInt8 nHyperLinkType
= 0;// HyperlinkType a value from the LinkTo enum, such as LT_URL (only valid when action == HyperlinkAction).
1367 Action Table: Action Value
1377 Jump Table: Jump Value
1387 if ( bMediaClickAction
)
1391 case css::presentation::ClickAction_STOPPRESENTATION
:
1394 case css::presentation::ClickAction_LASTPAGE
:
1397 case css::presentation::ClickAction_FIRSTPAGE
:
1400 case css::presentation::ClickAction_PREVPAGE
:
1403 case css::presentation::ClickAction_NEXTPAGE
:
1409 case css::presentation::ClickAction_SOUND
:
1411 if ( ImplGetPropertyValue( "Bookmark" ) )
1412 nSoundRef
= maSoundCollection
.GetId( *o3tl::doAccess
<OUString
>(mAny
) );
1415 case css::presentation::ClickAction_PROGRAM
:
1417 if ( ImplGetPropertyValue( "Bookmark" ) )
1419 INetURLObject
aUrl( *o3tl::doAccess
<OUString
>(mAny
) );
1420 if ( INetProtocol::File
== aUrl
.GetProtocol() )
1422 aFile
= aUrl
.PathToFileName();
1429 case css::presentation::ClickAction_BOOKMARK
:
1431 if ( ImplGetPropertyValue( "Bookmark" ) )
1433 OUString
aBookmark( *o3tl::doAccess
<OUString
>(mAny
) );
1434 sal_uInt32 nIndex
= 0;
1435 for ( const auto& rSlideName
: maSlideNameList
)
1437 if ( rSlideName
== aBookmark
)
1439 // Bookmark is a link to a document page
1443 OUString aHyperString
= OUString::number(256 + nIndex
) +
1445 OUString::number(nIndex
+ 1) +
1447 OUString::number(nIndex
+ 1);
1448 nHyperLinkID
= ImplInsertBookmarkURL( aHyperString
, 1 | ( nIndex
<< 8 ) | ( 1U << 31 ), aBookmark
, "", "", aHyperString
);
1456 case css::presentation::ClickAction_DOCUMENT
:
1458 if ( ImplGetPropertyValue( "Bookmark" ) )
1460 OUString
aBookmark( *o3tl::doAccess
<OUString
>(mAny
) );
1461 if ( !aBookmark
.isEmpty() )
1466 OUString
aBookmarkFile( aBookmark
);
1467 INetURLObject
aUrl( aBookmark
);
1468 if ( INetProtocol::File
== aUrl
.GetProtocol() )
1469 aBookmarkFile
= aUrl
.PathToFileName();
1470 nHyperLinkID
= ImplInsertBookmarkURL( aBookmark
, sal_uInt32(2 | ( 1U << 31 )), aBookmarkFile
, aBookmark
, "", "" );
1476 case css::presentation::ClickAction_INVISIBLE
:
1477 case css::presentation::ClickAction_VERB
:
1478 case css::presentation::ClickAction_VANISH
:
1479 case css::presentation::ClickAction_MACRO
:
1484 sal_uInt32 nContainerSize
= 24;
1486 nContainerSize
+= ( aFile
.getLength() * 2 ) + 8;
1487 rSt
.WriteUInt32( ( EPP_InteractiveInfo
<< 16 ) | 0xf ).WriteUInt32( nContainerSize
)
1488 .WriteUInt32( EPP_InteractiveInfoAtom
<< 16 ).WriteUInt32( 16 )
1489 .WriteUInt32( nSoundRef
)
1490 .WriteUInt32( nHyperLinkID
)
1491 .WriteUChar( nAction
)
1492 .WriteUChar( nOleVerb
)
1493 .WriteUChar( nJump
)
1494 .WriteUChar( nFlags
)
1495 .WriteUInt32( nHyperLinkType
);
1497 if ( nAction
== 2 ) // run program Action
1499 sal_Int32 nLen
= aFile
.getLength();
1500 rSt
.WriteUInt32( ( EPP_CString
<< 16 ) | 0x20 ).WriteUInt32( nLen
* 2 );
1501 for ( sal_Int32 i
= 0; i
< nLen
; i
++ )
1502 rSt
.WriteUInt16( aFile
[i
] );
1505 rSt
.WriteUInt32( ( EPP_InteractiveInfo
<< 16 ) | 0x1f ).WriteUInt32( 24 ) // Mouse Over Action
1506 .WriteUInt32( EPP_InteractiveInfo
<< 16 ).WriteUInt32( 16 );
1507 for ( int i
= 0; i
< 4; i
++, rSt
.WriteUInt32( 0 ) ) ;
1510 bool PPTWriter::ImplGetEffect( const css::uno::Reference
< css::beans::XPropertySet
> & rPropSet
,
1511 css::presentation::AnimationEffect
& eEffect
,
1512 css::presentation::AnimationEffect
& eTextEffect
,
1516 if ( GetPropertyValue( aAny
, rPropSet
, "Effect" ) )
1519 eEffect
= css::presentation::AnimationEffect_NONE
;
1521 if ( GetPropertyValue( aAny
, rPropSet
, "TextEffect" ) )
1522 aAny
>>= eTextEffect
;
1524 eTextEffect
= css::presentation::AnimationEffect_NONE
;
1525 if ( GetPropertyValue( aAny
, rPropSet
, "SoundOn" ) )
1530 bool bHasEffect
= ( ( eEffect
!= css::presentation::AnimationEffect_NONE
)
1531 || ( eTextEffect
!= css::presentation::AnimationEffect_NONE
)
1536 bool PPTWriter::ImplCreatePresentationPlaceholder( const bool bMasterPage
,
1537 const sal_uInt32 nStyleInstance
, const sal_uInt8 nPlaceHolderId
)
1539 bool bRet
= ImplGetText();
1540 if ( bRet
&& bMasterPage
)
1542 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
1543 sal_uInt32 nPresShapeID
= mpPptEscherEx
->GenerateShapeId();
1544 mpPptEscherEx
->AddShape( ESCHER_ShpInst_Rectangle
,
1545 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
, nPresShapeID
);
1546 EscherPropertyContainer aPropOpt
;
1547 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x50001 );
1549 aPropOpt
.AddOpt( ESCHER_Prop_lTxid
, mnTxId
);
1550 aPropOpt
.AddOpt( ESCHER_Prop_AnchorText
, ESCHER_AnchorMiddle
);
1551 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x110001 );
1552 aPropOpt
.AddOpt( ESCHER_Prop_lineColor
, 0x8000001 );
1553 aPropOpt
.AddOpt( ESCHER_Prop_shadowColor
, 0x8000002 );
1554 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
1555 sal_uInt32 nLineFlags
= 0x90001;
1556 if ( aPropOpt
.GetOpt( ESCHER_Prop_fNoLineDrawDash
, nLineFlags
) )
1557 nLineFlags
|= 0x10001; // draw dashed line if no line
1558 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, nLineFlags
);
1560 SvMemoryStream
aExtBu( 0x200, 0x200 );
1561 SvMemoryStream
aClientTextBox( 0x200, 0x200 );
1562 ImplWriteTextStyleAtom( aClientTextBox
, nStyleInstance
, 0, nullptr, aExtBu
, &aPropOpt
);
1565 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
);
1566 aPropOpt
.CreateShapeProperties( mXShape
);
1567 aPropOpt
.Commit( *mpStrm
);
1568 mpPptEscherEx
->AddAtom( 8, ESCHER_ClientAnchor
);
1569 mpStrm
->WriteInt16( maRect
.Top() ).WriteInt16( maRect
.Left() ).WriteInt16( maRect
.Right() ).WriteInt16( maRect
.Bottom() ); // top, left, right, bottom ????
1570 mpPptEscherEx
->OpenContainer( ESCHER_ClientData
);
1571 mpPptEscherEx
->AddAtom( 8, EPP_OEPlaceholderAtom
);
1572 mpStrm
->WriteUInt32( 0 ) // PlacementID
1573 .WriteUChar( nPlaceHolderId
) // PlaceHolderID
1574 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
1575 .WriteUInt16( 0 ); // padword
1576 mpPptEscherEx
->CloseContainer(); // ESCHER_ClientData
1578 if ( aClientTextBox
.Tell() )
1580 mpStrm
->WriteUInt32( ( ESCHER_ClientTextbox
<< 16 ) | 0xf )
1581 .WriteUInt32( aClientTextBox
.Tell() );
1583 mpStrm
->WriteBytes(aClientTextBox
.GetData(), aClientTextBox
.Tell());
1585 mpPptEscherEx
->CloseContainer(); // ESCHER_SpContainer
1592 void PPTWriter::ImplCreateShape( sal_uInt32 nType
, ShapeFlag nFlags
, EscherSolverContainer
& rSolver
)
1594 sal_uInt32 nId
= mpPptEscherEx
->GenerateShapeId();
1595 mpPptEscherEx
->AddShape( nType
, nFlags
, nId
);
1596 rSolver
.AddShape( mXShape
, nId
);
1599 void PPTWriter::ImplCreateTextShape( EscherPropertyContainer
& rPropOpt
, EscherSolverContainer
& rSolver
, bool bFill
)
1601 mnTextStyle
= EPP_TEXTSTYLE_TEXT
;
1602 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
1603 ImplCreateShape( ESCHER_ShpInst_TextBox
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
, rSolver
);
1605 rPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
1606 if ( ImplGetText() )
1609 rPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
);
1613 void PPTWriter::ImplWritePage( const PHLayout
& rLayout
, EscherSolverContainer
& aSolverContainer
, PageType ePageType
, bool bMasterPage
, int nPageNumber
)
1615 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
1616 // sal_uInt32 nGroupLevel = 0;
1618 sal_uInt32 nGroups
, nShapes
, nShapeCount
, nPer
, nLastPer
, nIndices
, nOlePictureId
;
1619 css::awt::Point aTextRefPoint
;
1621 nShapes
= mXShapes
->getCount();
1622 ResetGroupTable( nShapes
);
1624 nIndices
= nLastPer
= nShapeCount
= 0;
1626 bool bIsTitlePossible
= true; // powerpoint is not able to handle more than one title
1628 sal_uInt32 nOutlinerCount
= 0; // the outline objects have to conform to the layout,
1629 sal_uInt32 nPrevTextStyle
= 0; // there are no more than two allowed
1633 bool bAdditionalText
= false;
1635 bool bSecOutl
= false;
1636 sal_uInt32 nPObjects
= 0;
1638 std::unique_ptr
<SvMemoryStream
> pClientTextBox
;
1639 std::unique_ptr
<SvMemoryStream
> pClientData
;
1641 while( GetNextGroupEntry() )
1645 nPer
= ( 5 * nShapeCount
) / nShapes
;
1646 if ( nPer
!= nLastPer
)
1649 sal_uInt32 nValue
= mnPagesWritten
* 5 + nPer
;
1650 if ( nValue
> mnStatMaxValue
)
1651 nValue
= mnStatMaxValue
;
1652 if ( mbStatusIndicator
&& ( nValue
> mnLatestStatValue
) )
1654 mXStatusIndicator
->setValue( nValue
);
1655 mnLatestStatValue
= nValue
;
1658 nGroups
= GetGroupsClosed();
1659 for ( sal_uInt32 i
= 0; i
< nGroups
; i
++, mpPptEscherEx
->LeaveGroup() ) ;
1661 if ( GetShapeByIndex( GetCurrentGroupIndex(), true ) )
1664 bool bMediaClickAction
= false;
1665 css::presentation::AnimationEffect eAe
;
1666 css::presentation::AnimationEffect eTe
;
1668 bool bEffect
= ImplGetEffect( mXPropSet
, eAe
, eTe
, bIsSound
);
1669 css::presentation::ClickAction eCa
= css::presentation::ClickAction_NONE
;
1670 if ( ImplGetPropertyValue( "OnClick" ) )
1673 bool bGroup
= mType
== "drawing.Group";
1674 bool bOpenBezier
= mType
== "drawing.OpenBezier";
1675 bool bClosedBezier
= mType
== "drawing.ClosedBezier";
1676 bool bPolyPolygon
= mType
== "drawing.PolyPolygon";
1677 bool bPolyLine
= mType
== "drawing.PolyLine";
1679 const css::awt::Size
aSize100thmm( mXShape
->getSize() );
1680 const css::awt::Point
aPoint100thmm( mXShape
->getPosition() );
1681 ::tools::Rectangle
aRect100thmm( Point( aPoint100thmm
.X
, aPoint100thmm
.Y
), Size( aSize100thmm
.Width
, aSize100thmm
.Height
) );
1682 EscherPropertyContainer
aPropOpt( mpPptEscherEx
->GetGraphicProvider(), mpPicStrm
.get(), aRect100thmm
);
1686 css::uno::Reference
< css::container::XIndexAccess
>
1687 aXIndexAccess( mXShape
, css::uno::UNO_QUERY
);
1688 if ( EnterGroup( aXIndexAccess
) )
1690 std::unique_ptr
<SvMemoryStream
> pTmp
;
1691 if ( eCa
!= css::presentation::ClickAction_NONE
)
1693 pTmp
.reset(new SvMemoryStream(0x200, 0x200));
1694 ImplWriteClickAction( *pTmp
, eCa
, bMediaClickAction
);
1696 sal_uInt32 nShapeId
= mpPptEscherEx
->EnterGroup(&maRect
, pTmp
.get());
1697 aSolverContainer
.AddShape( mXShape
, nShapeId
);
1702 bool bIsFontwork
= false;
1703 bool bIsHatching
= false;
1705 css::drawing::FillStyle eFS
;
1706 if ( GetPropertyValue( aAny
, mXPropSet
, "IsFontwork", true ) )
1707 aAny
>>= bIsFontwork
;
1708 if ( GetPropertyValue( aAny
, mXPropSet
, "FillStyle", true ) )
1711 bIsHatching
= eFS
== css::drawing::FillStyle_HATCH
;
1713 if ( bIsHatching
|| bIsFontwork
|| ( mType
== "drawing.Measure" ) || ( mType
== "drawing.Caption" ) )
1715 if ( ImplGetPropertyValue( "BoundRect" ) )
1717 auto aRect
= o3tl::doAccess
<css::awt::Rectangle
>(mAny
);
1718 maPosition
= MapPoint( css::awt::Point( aRect
->X
, aRect
->Y
) );
1719 maSize
= MapSize( css::awt::Size( aRect
->Width
, aRect
->Height
) );
1720 maRect
= ::tools::Rectangle( Point( maPosition
.X
, maPosition
.Y
), Size( maSize
.Width
, maSize
.Height
) );
1722 mType
= "drawing.dontknow";
1725 sal_uInt8 nPlaceHolderAtom
= EPP_PLACEHOLDER_NONE
;
1728 mnTextStyle
= EPP_TEXTSTYLE_NORMAL
;
1730 if ( mType
== "drawing.Custom" )
1732 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
1733 ShapeFlag nMirrorFlags
;
1734 OUString sCustomShapeType
;
1735 MSO_SPT eShapeType
= EscherPropertyContainer::GetCustomShapeType( mXShape
, nMirrorFlags
, sCustomShapeType
);
1736 if ( sCustomShapeType
== "col-502ad400" || sCustomShapeType
== "col-60da8460" )
1737 { // sj: creating metafile for customshapes that can't be saved to ms format properly
1738 ImplCreateShape( ESCHER_ShpInst_PictureFrame
,
1739 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
1741 if ( aPropOpt
.CreateGraphicProperties( mXPropSet
, "MetaFile", false ) )
1743 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
1744 SdrObject
* pObj
= GetSdrObjectFromXShape( mXShape
);
1747 ::tools::Rectangle aBound
= pObj
->GetCurrentBoundRect();
1748 maPosition
= MapPoint( css::awt::Point( aBound
.Left(), aBound
.Top() ) );
1749 maSize
= MapSize( css::awt::Size ( aBound
.GetWidth(), aBound
.GetHeight() ) );
1750 maRect
= ::tools::Rectangle( Point( maPosition
.X
, maPosition
.Y
), Size( maSize
.Width
, maSize
.Height
) );
1757 ImplCreateShape( eShapeType
,
1758 nMirrorFlags
| ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
1760 aPropOpt
.CreateCustomShapeProperties( eShapeType
, mXShape
);
1761 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
1762 if ( ImplGetText() )
1764 if ( !aPropOpt
.IsFontWork() )
1767 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
, true );
1772 else if ( mType
== "drawing.Rectangle" )
1774 sal_Int32 nRadius
= 0;
1775 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
1776 if ( ImplGetPropertyValue( "CornerRadius" ) )
1779 nRadius
= MapSize( css::awt::Size( nRadius
, 0 ) ).Width
;
1783 ImplCreateShape( ESCHER_ShpInst_RoundRectangle
,
1784 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
1786 sal_Int32 nLength
= maRect
.GetWidth();
1787 if ( nLength
> maRect
.GetHeight() )
1788 nLength
= maRect
.GetHeight();
1790 if ( nRadius
>= nLength
)
1791 nRadius
= 0x2a30; // 0x2a30 is PPTs maximum radius
1795 nRadius
= ( 0x2a30 * nRadius
) / nLength
;
1797 nRadius
= 0x2a30; // 0x2a30 is PPTs maximum radius
1799 aPropOpt
.AddOpt( ESCHER_Prop_adjustValue
, nRadius
);
1803 ImplCreateShape( ESCHER_ShpInst_Rectangle
,
1804 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
1807 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
1808 if ( ImplGetText() )
1811 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
, false, false );
1814 else if ( mType
== "drawing.Ellipse" )
1816 css::drawing::CircleKind
eCircleKind( css::drawing::CircleKind_FULL
);
1817 PolyStyle ePolyKind
= PolyStyle::Chord
;
1818 if ( ImplGetPropertyValue( "CircleKind" ) )
1820 mAny
>>= eCircleKind
;
1821 switch ( eCircleKind
)
1823 case css::drawing::CircleKind_SECTION
:
1825 ePolyKind
= PolyStyle::Pie
;
1828 case css::drawing::CircleKind_ARC
:
1830 ePolyKind
= PolyStyle::Arc
;
1834 case css::drawing::CircleKind_CUT
:
1836 ePolyKind
= PolyStyle::Chord
;
1841 eCircleKind
= css::drawing::CircleKind_FULL
;
1844 if ( eCircleKind
== css::drawing::CircleKind_FULL
)
1846 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
1847 ImplCreateShape( ESCHER_ShpInst_Ellipse
,
1848 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
1850 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
1851 if ( ImplGetText() )
1854 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
, false, false );
1859 sal_Int32 nStartAngle
, nEndAngle
;
1860 if ( !ImplGetPropertyValue( "CircleStartAngle" ) )
1862 nStartAngle
= *o3tl::doAccess
<sal_Int32
>(mAny
);
1863 if( !ImplGetPropertyValue( "CircleEndAngle" ) )
1865 nEndAngle
= *o3tl::doAccess
<sal_Int32
>(mAny
);
1866 css::awt::Point
aPoint( mXShape
->getPosition() );
1867 css::awt::Size
aSize( mXShape
->getSize() );
1868 css::awt::Point aStart
, aEnd
, aCenter
;
1869 ::tools::Rectangle
aRect( Point( aPoint
.X
, aPoint
.Y
), Size( aSize
.Width
, aSize
.Height
) );
1870 aStart
.X
= static_cast<sal_Int32
>( cos( nStartAngle
* F_PI18000
) * 100.0 );
1871 aStart
.Y
= - static_cast<sal_Int32
>( sin( nStartAngle
* F_PI18000
) * 100.0 );
1872 aEnd
.X
= static_cast<sal_Int32
>( cos( nEndAngle
* F_PI18000
) * 100.0 );
1873 aEnd
.Y
= - static_cast<sal_Int32
>( sin( nEndAngle
* F_PI18000
) * 100.0 ) ;
1874 aCenter
.X
= aPoint
.X
+ ( aSize
.Width
/ 2 );
1875 aCenter
.Y
= aPoint
.Y
+ ( aSize
.Height
/ 2 );
1876 aStart
.X
+= aCenter
.X
;
1877 aStart
.Y
+= aCenter
.Y
;
1878 aEnd
.X
+= aCenter
.X
;
1879 aEnd
.Y
+= aCenter
.Y
;
1880 tools::Polygon
aPolygon( aRect
, Point( aStart
.X
, aStart
.Y
), Point( aEnd
.X
, aEnd
.Y
), ePolyKind
);
1881 bool bNeedText
= true;
1884 aPolygon
.Rotate( aRect
.TopLeft(), static_cast<sal_uInt16
>( mnAngle
/ 10 ) );
1885 if ( ImplGetText() )
1887 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
1888 // mpPptEscherEx->EnterGroup( 0,0 );
1889 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
1891 bAdditionalText
= true;
1896 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
1897 ImplCreateShape( ESCHER_ShpInst_NotPrimitive
,
1898 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
1900 css::awt::Rectangle aNewRect
;
1901 switch ( ePolyKind
)
1903 case PolyStyle::Pie
:
1904 case PolyStyle::Chord
:
1906 if ( aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_POLYPOLYGON
, false, aNewRect
, &aPolygon
) )
1907 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
1911 case PolyStyle::Arc
:
1913 if ( aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_POLYLINE
, false, aNewRect
, &aPolygon
) )
1914 aPropOpt
.CreateLineProperties( mXPropSet
, false );
1918 maRect
= MapRectangle( aNewRect
);
1919 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
1920 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
1921 if ( bNeedText
&& ImplGetText() )
1924 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
, false, false );
1928 else if ( mType
== "drawing.Control" )
1930 css::uno::Reference
< css::drawing::XControlShape
> aXControlShape( mXShape
, css::uno::UNO_QUERY
);
1931 if ( !aXControlShape
.is() )
1933 css::uno::Reference
< css::awt::XControlModel
> aXControlModel( aXControlShape
->getControl() );
1934 if ( !aXControlModel
.is() )
1937 sal_Int64 nAspect
= css::embed::Aspects::MSOLE_CONTENT
;
1940 // try to get the aspect when available
1941 css::uno::Reference
< css::beans::XPropertySet
> xShapeProps( mXShape
, css::uno::UNO_QUERY_THROW
);
1942 xShapeProps
->getPropertyValue("Aspect") >>= nAspect
;
1944 catch( css::uno::Exception
& )
1947 mpExEmbed
->WriteUInt32( 0xf | ( EPP_ExControl
<< 16 ) )
1948 .WriteUInt32( 0 ); // Size of this container
1950 sal_uInt32 nSize
, nOldPos
= mpExEmbed
->Tell();
1952 sal_uInt32 nPageId
= nPageNumber
;
1953 if ( ePageType
== MASTER
)
1954 nPageId
|= 0x80000000;
1957 mpExEmbed
->WriteUInt32( EPP_ExControlAtom
<< 16 )
1959 .WriteUInt32( nPageId
);
1960 std::unique_ptr
<PPTExOleObjEntry
> pEntry( new PPTExOleObjEntry( OCX_CONTROL
, mpExEmbed
->Tell() ) );
1961 pEntry
->xControlModel
= aXControlModel
;
1962 pEntry
->xShape
= mXShape
;
1963 maExOleObj
.push_back( std::move(pEntry
) );
1967 mpExEmbed
->WriteUInt32( 1 | ( EPP_ExOleObjAtom
<< 16 ) )
1969 .WriteUInt32( nAspect
)
1971 .WriteUInt32( mnExEmbed
)
1973 .WriteUInt32( 4 ) // index to the persist table
1974 .WriteUInt32( 0x0012de00 );
1976 css::awt::Size aSize
;
1977 OUString aControlName
;
1978 tools::SvRef
<SotStorage
> xTemp( new SotStorage( new SvMemoryStream(), true ) );
1979 if ( oox::ole::MSConvertOCXControls::WriteOCXStream( mXModel
, xTemp
, aXControlModel
, aSize
, aControlName
) )
1981 OUString
aUserName( xTemp
->GetUserName() );
1982 OUString aOleIdentifier
;
1983 if ( !aUserName
.isEmpty() )
1985 tools::SvRef
<SotStorageStream
> xCompObj
= xTemp
->OpenSotStream(
1987 StreamMode::READ
| StreamMode::NOCREATE
| StreamMode::SHARE_DENYALL
);
1988 sal_uInt32
const nStreamLen
= xCompObj
->remainingSize();
1989 sal_Int16 nVersion
, nByteOrder
;
1990 sal_Int32 nWinVersion
, nVal
, nStringLen
;
1991 xCompObj
->ReadInt16( nVersion
)
1992 .ReadInt16( nByteOrder
)
1993 .ReadInt32( nWinVersion
)
1995 xCompObj
->SeekRel( 16 ); // skipping clsid
1996 xCompObj
->ReadInt32( nStringLen
);
1997 if ( ( xCompObj
->Tell() + nStringLen
) < nStreamLen
)
1999 xCompObj
->SeekRel( nStringLen
); // now skipping the UserName;
2000 xCompObj
->ReadInt32( nStringLen
);
2001 if ( ( xCompObj
->Tell() + nStringLen
) < nStreamLen
)
2003 xCompObj
->SeekRel( nStringLen
); // now skipping the clipboard formatname
2004 xCompObj
->ReadInt32( nStringLen
);
2005 if ( ( nStringLen
> 1 ) && ( ( xCompObj
->Tell() + nStringLen
) < nStreamLen
) )
2006 { // i think that the OleIdentifier will follow
2007 OString aTemp
= read_uInt8s_ToOString(*xCompObj
, nStringLen
- 1);
2008 aOleIdentifier
= OStringToOUString(aTemp
, RTL_TEXTENCODING_MS_1252
);
2014 PPTWriter::WriteCString( *mpExEmbed
, aControlName
, 1 );
2015 PPTWriter::WriteCString( *mpExEmbed
, aOleIdentifier
, 2 );
2016 PPTWriter::WriteCString( *mpExEmbed
, aUserName
, 3 );
2018 nSize
= mpExEmbed
->Tell() - nOldPos
;
2019 mpExEmbed
->Seek( nOldPos
- 4 );
2020 mpExEmbed
->WriteUInt32( nSize
);
2021 mpExEmbed
->Seek( STREAM_SEEK_TO_END
);
2022 nOlePictureId
= mnExEmbed
;
2024 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2025 ShapeFlag
const nSpFlags
= ShapeFlag::HaveShapeProperty
| ShapeFlag::HaveAnchor
| ShapeFlag::OLEShape
;
2026 ImplCreateShape( ESCHER_ShpInst_HostControl
, nSpFlags
, aSolverContainer
);
2027 if ( aPropOpt
.CreateGraphicProperties( mXPropSet
, "MetaFile", false ) )
2028 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2029 //export form control graphic
2030 else if ( aPropOpt
.CreateBlipPropertiesforOLEControl(mXPropSet
,mXShape
))
2031 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2032 aPropOpt
.AddOpt( ESCHER_Prop_pictureId
, mnExEmbed
);
2033 aPropOpt
.AddOpt( ESCHER_Prop_pictureActive
, 0x10000 );
2035 if ( !aControlName
.isEmpty() )
2037 aPropOpt
.AddOpt(ESCHER_Prop_wzName
, aControlName
);
2040 else if ( mType
== "drawing.Connector" )
2044 css::awt::Rectangle aNewRect
;
2045 if ( !aPropOpt
.CreateConnectorProperties( mXShape
, aSolverContainer
, aNewRect
, nSpType
, nSpFlags
) )
2048 maRect
= MapRectangle( aNewRect
);
2049 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2050 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
2052 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2053 ImplCreateShape( nSpType
, nSpFlags
, aSolverContainer
);
2055 // #119459# for connector shape, the start point and end point is fixed, and should not be rotated.
2058 else if ( mType
== "drawing.Measure" )
2062 else if ( mType
== "drawing.Line" )
2064 css::awt::Rectangle aNewRect
;
2065 aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_LINE
, false, aNewRect
);
2066 maRect
= MapRectangle( aNewRect
);
2067 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2068 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
2069 if ( ImplGetText() )
2071 aTextRefPoint
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2073 bAdditionalText
= true;
2074 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2075 // mpPptEscherEx->EnterGroup( &maRect,0 );
2077 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2078 ShapeFlag nFlags
= ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
;
2080 if ( maRect
.Top() > maRect
.Bottom() )
2081 nFlags
|= ShapeFlag::FlipV
;
2082 if ( maRect
.Left() > maRect
.Right() )
2083 nFlags
|= ShapeFlag::FlipH
;
2085 ImplCreateShape( ESCHER_ShpInst_Line
, nFlags
, aSolverContainer
);
2086 aPropOpt
.AddOpt( ESCHER_Prop_shapePath
, ESCHER_ShapeComplex
);
2087 aPropOpt
.CreateLineProperties( mXPropSet
, false );
2090 else if ( bPolyPolygon
)
2092 if ( ImplGetText() )
2094 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2095 // mpPptEscherEx->EnterGroup( 0,0 );
2096 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2097 bAdditionalText
= true;
2100 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2101 ImplCreateShape( ESCHER_ShpInst_NotPrimitive
,
2102 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2104 css::awt::Rectangle aNewRect
;
2105 aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_POLYPOLYGON
, false, aNewRect
);
2106 maRect
= MapRectangle( aNewRect
);
2107 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2108 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
2109 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
2112 else if ( bPolyLine
)
2114 if ( ImplGetText() )
2116 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2117 // mpPptEscherEx->EnterGroup( 0,0 );
2118 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2119 bAdditionalText
= true;
2122 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2123 ImplCreateShape( ESCHER_ShpInst_NotPrimitive
,
2124 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2126 css::awt::Rectangle aNewRect
;
2127 aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_POLYLINE
, false, aNewRect
);
2128 maRect
= MapRectangle( aNewRect
);
2129 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2130 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
2131 aPropOpt
.CreateLineProperties( mXPropSet
, false );
2134 else if ( bOpenBezier
)
2136 if ( ImplGetText() )
2138 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2139 // mpPptEscherEx->EnterGroup( 0,0 );
2140 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2141 bAdditionalText
= true;
2144 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2145 ImplCreateShape( ESCHER_ShpInst_NotPrimitive
,
2146 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2148 css::awt::Rectangle aNewRect
;
2149 aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_POLYLINE
, true, aNewRect
);
2150 maRect
= MapRectangle( aNewRect
);
2151 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2152 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
2153 aPropOpt
.CreateLineProperties( mXPropSet
, false );
2156 else if ( bClosedBezier
)
2158 if ( ImplGetText() )
2160 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2161 // mpPptEscherEx->EnterGroup( 0,0 );
2162 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2163 bAdditionalText
= true;
2166 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2167 ImplCreateShape( ESCHER_ShpInst_NotPrimitive
,
2168 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2170 css::awt::Rectangle aNewRect
;
2171 aPropOpt
.CreatePolygonProperties( mXPropSet
, ESCHER_CREATEPOLYGON_POLYPOLYGON
, true, aNewRect
);
2172 maRect
= MapRectangle( aNewRect
);
2173 maPosition
= css::awt::Point( maRect
.Left(), maRect
.Top() );
2174 maSize
= css::awt::Size( maRect
.GetWidth(), maRect
.GetHeight() );
2175 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
2178 else if ( ( mType
== "drawing.GraphicObject" ) || ( mType
== "presentation.GraphicObject" ) )
2180 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2182 // a GraphicObject can also be a ClickMe element
2183 if ( mbEmptyPresObj
&& ( ePageType
== NORMAL
) )
2185 nPlaceHolderAtom
= rLayout
.nUsedObjectPlaceHolder
;
2186 ImplCreateShape( ESCHER_ShpInst_Rectangle
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveMaster
, aSolverContainer
);
2188 aPropOpt
.AddOpt( ESCHER_Prop_lTxid
, mnTxId
);
2189 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x10001 );
2190 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x10001 );
2191 aPropOpt
.AddOpt( ESCHER_Prop_hspMaster
, mnShapeMasterBody
);
2195 mXText
.set( mXShape
, css::uno::UNO_QUERY
);
2198 mnTextSize
= mXText
->getString().getLength();
2200 if ( mnTextSize
) // graphic object or area fill
2202 /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
2203 have to create a simple Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
2205 ImplCreateShape( ESCHER_ShpInst_Rectangle
,
2206 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2208 if ( aPropOpt
.CreateGraphicProperties( mXPropSet
, "Graphic", true, true, false ) )
2210 aPropOpt
.AddOpt( ESCHER_Prop_WrapText
, ESCHER_WrapNone
);
2211 aPropOpt
.AddOpt( ESCHER_Prop_AnchorText
, ESCHER_AnchorMiddle
);
2212 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x140014 );
2213 aPropOpt
.AddOpt( ESCHER_Prop_fillBackColor
, 0x8000000 );
2214 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x80000 );
2215 if ( ImplGetText() )
2218 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
, false, false );
2224 ImplCreateShape( ESCHER_ShpInst_PictureFrame
,
2225 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2228 if ( aPropOpt
.CreateGraphicProperties( mXPropSet
, "Graphic", false, true ) )
2230 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2235 else if ( ( mType
== "drawing.Text" ) || ( mType
== "presentation.Notes" ) )
2237 if ( ( ePageType
== NOTICE
) && mbPresObj
)
2239 if ( ImplCreatePresentationPlaceholder( bMasterPage
, EPP_TEXTTYPE_Notes
, EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE
) )
2242 nPlaceHolderAtom
= EPP_PLACEHOLDER_NOTESBODY
;
2244 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2246 else if ( mType
== "presentation.TitleText" )
2250 if ( ( ePageType
== NOTICE
) && mbEmptyPresObj
)
2252 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2253 nPlaceHolderAtom
= EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE
;
2254 ImplCreateShape( ESCHER_ShpInst_Rectangle
, ShapeFlag::HaveAnchor
, aSolverContainer
);
2255 aPropOpt
.CreateLineProperties( mXPropSet
, false );
2256 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x10001 );
2258 else if ( rLayout
.bTitlePossible
&& bIsTitlePossible
)
2260 bIsTitlePossible
= false;
2263 TextObjBinary
aTextObj( mXText
, EPP_TEXTTYPE_Title
, maFontCollection
, static_cast<PPTExBulletProvider
&>(*this) );
2264 if ( ePageType
== MASTER
)
2268 OUString
aUString( mXText
->getString() );
2271 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2272 mnShapeMasterTitle
= mpPptEscherEx
->GenerateShapeId();
2273 mpPptEscherEx
->AddShape( ESCHER_ShpInst_Rectangle
,
2274 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2275 mnShapeMasterTitle
);
2276 EscherPropertyContainer aPropertyOptions
;
2277 aPropertyOptions
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x50001 );
2279 aPropertyOptions
.AddOpt( ESCHER_Prop_lTxid
, mnTxId
);
2280 aPropertyOptions
.AddOpt( ESCHER_Prop_AnchorText
, ESCHER_AnchorMiddle
);
2281 aPropertyOptions
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x110001 );
2282 aPropertyOptions
.AddOpt( ESCHER_Prop_lineColor
, 0x8000001 );
2283 aPropertyOptions
.AddOpt( ESCHER_Prop_shadowColor
, 0x8000002 );
2284 aPropertyOptions
.CreateFillProperties( mXPropSet
, true, mXShape
);
2285 sal_uInt32 nLineFlags
= 0x90001;
2286 if ( aPropertyOptions
.GetOpt( ESCHER_Prop_fNoLineDrawDash
, nLineFlags
) )
2287 nLineFlags
|= 0x10001; // draw dashed line if no line
2288 aPropertyOptions
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, nLineFlags
);
2290 aPropertyOptions
.CreateTextProperties( mXPropSet
, mnTxId
);
2291 ImplAdjustFirstLineLineSpacing( aTextObj
, aPropOpt
);
2292 aPropertyOptions
.Commit( *mpStrm
);
2293 mpPptEscherEx
->AddAtom( 8, ESCHER_ClientAnchor
);
2294 mpStrm
->WriteInt16( maRect
.Top() ).WriteInt16( maRect
.Left() ).WriteInt16( maRect
.Right() ).WriteInt16( maRect
.Bottom() ); // top, left, right, bottom ????
2295 mpPptEscherEx
->OpenContainer( ESCHER_ClientData
);
2296 mpPptEscherEx
->AddAtom( 8, EPP_OEPlaceholderAtom
);
2297 mpStrm
->WriteUInt32( 0 ) // PlacementID
2298 .WriteUChar( EPP_PLACEHOLDER_MASTERTITLE
) // PlaceHolderID
2299 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2300 .WriteUInt16( 0 ); // padword
2301 mpPptEscherEx
->CloseContainer(); // ESCHER_ClientData
2302 mpPptEscherEx
->OpenContainer( ESCHER_ClientTextbox
);
2303 mpPptEscherEx
->AddAtom( 4, EPP_TextHeaderAtom
);
2304 mpStrm
->WriteUInt32( EPP_TEXTTYPE_Title
);
2305 mpPptEscherEx
->AddAtom( mnTextSize
<< 1, EPP_TextCharsAtom
);
2306 const sal_Unicode
* pString
= aUString
.getStr();
2307 for ( sal_uInt32 i
= 0; i
< mnTextSize
; i
++ )
2309 nChar
= pString
[ i
]; // 0xa -> 0xb soft newline
2311 nChar
++; // 0xd -> 0xd hard newline
2312 mpStrm
->WriteUInt16( nChar
);
2314 mpPptEscherEx
->AddAtom( 6, EPP_BaseTextPropAtom
);
2315 mpStrm
->WriteUInt32( mnTextSize
+ 1 ).WriteUInt16( 0 );
2316 mpPptEscherEx
->AddAtom( 10, EPP_TextSpecInfoAtom
);
2317 mpStrm
->WriteUInt32( mnTextSize
+ 1 ).WriteUInt32( 1 ).WriteUInt16( 0 );
2318 mpPptEscherEx
->CloseContainer(); // ESCHER_ClientTextBox
2319 mpPptEscherEx
->CloseContainer(); // ESCHER_SpContainer
2325 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2326 mnTextStyle
= EPP_TEXTSTYLE_TITLE
;
2327 nPlaceHolderAtom
= rLayout
.nTypeOfTitle
;
2328 ImplCreateShape( ESCHER_ShpInst_Rectangle
,
2329 ShapeFlag::HaveAnchor
| ShapeFlag::HaveMaster
,
2331 aPropOpt
.AddOpt( ESCHER_Prop_hspMaster
, mnShapeMasterTitle
);
2332 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
2334 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
);
2335 ImplAdjustFirstLineLineSpacing( aTextObj
, aPropOpt
);
2336 if ( mbEmptyPresObj
)
2338 sal_uInt32 nNoLineDrawDash
= 0;
2339 aPropOpt
.GetOpt( ESCHER_Prop_fNoLineDrawDash
, nNoLineDrawDash
);
2340 nNoLineDrawDash
|= 0x10001;
2341 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, nNoLineDrawDash
);
2350 mType
= "drawing.Text";
2351 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2354 else if ( ( mType
== "presentation.Outliner" ) || ( mType
== "presentation.Subtitle" ) )
2359 if ( (rLayout
.bOutlinerPossible
&& ( nOutlinerCount
== 1 )) ||
2360 (( rLayout
.bSecOutlinerPossible
&& ( nOutlinerCount
== 2 ) ) && ( nPrevTextStyle
== EPP_TEXTSTYLE_BODY
))
2364 TextObjBinary
aTextObj( mXText
, EPP_TEXTTYPE_Body
, maFontCollection
, static_cast<PPTExBulletProvider
&>(*this) );
2365 if ( ePageType
== MASTER
)
2367 nPrevTextStyle
= EPP_TEXTSTYLE_TITLE
;
2370 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2371 mnShapeMasterBody
= mpPptEscherEx
->GenerateShapeId();
2372 mpPptEscherEx
->AddShape( ESCHER_ShpInst_Rectangle
,
2373 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2374 mnShapeMasterBody
);
2375 EscherPropertyContainer aPropOpt2
;
2376 aPropOpt2
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x50001 );
2378 aPropOpt2
.AddOpt( ESCHER_Prop_lTxid
, mnTxId
);
2379 aPropOpt2
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x110001 );
2380 aPropOpt2
.AddOpt( ESCHER_Prop_lineColor
, 0x8000001 );
2381 aPropOpt2
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x90001 );
2382 aPropOpt2
.AddOpt( ESCHER_Prop_shadowColor
, 0x8000002 );
2383 aPropOpt2
.CreateFillProperties( mXPropSet
, true, mXShape
);
2384 sal_uInt32 nLineFlags
= 0x90001;
2385 if ( aPropOpt2
.GetOpt( ESCHER_Prop_fNoLineDrawDash
, nLineFlags
) )
2386 nLineFlags
|= 0x10001; // draw dashed line if no line
2387 aPropOpt2
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, nLineFlags
);
2389 aPropOpt2
.CreateTextProperties( mXPropSet
, mnTxId
);
2390 ImplAdjustFirstLineLineSpacing( aTextObj
, aPropOpt2
);
2391 aPropOpt2
.Commit( *mpStrm
);
2392 mpPptEscherEx
->AddAtom( 8, ESCHER_ClientAnchor
);
2393 mpStrm
->WriteInt16( maRect
.Top() ).WriteInt16( maRect
.Left() ).WriteInt16( maRect
.Right() ).WriteInt16( maRect
.Bottom() ); // top, left, right, bottom ????
2394 mpPptEscherEx
->OpenContainer( ESCHER_ClientData
);
2395 mpPptEscherEx
->AddAtom( 8, EPP_OEPlaceholderAtom
);
2396 sal_uInt8 PlaceHolderID
= ( mType
== "presentation.Subtitle") ? EPP_PLACEHOLDER_MASTERSUBTITLE
:EPP_PLACEHOLDER_MASTERBODY
;
2397 mpStrm
->WriteUInt32( 1 ) // PlacementID
2398 .WriteUChar( PlaceHolderID
)/*(sal_uInt8)EPP_PLACEHOLDER_MASTERBODY */ // PlaceHolderID
2399 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2400 .WriteUInt16( 0 ); // padword
2401 mpPptEscherEx
->CloseContainer(); // ESCHER_ClientData
2402 mpPptEscherEx
->OpenContainer( ESCHER_ClientTextbox
); // printf
2403 mpPptEscherEx
->AddAtom( 4, EPP_TextHeaderAtom
);
2404 if ( mType
== "presentation.Subtitle")
2405 mpStrm
->WriteUInt32( EPP_TEXTTYPE_CenterBody
);
2407 mpStrm
->WriteUInt32( EPP_TEXTTYPE_Body
);
2408 mnTextSize
= aTextObj
.Count();
2409 aTextObj
.Write( mpStrm
.get() );
2410 mpPptEscherEx
->BeginAtom();
2411 for ( sal_uInt32 i
= 0; i
< aTextObj
.ParagraphCount() ; ++i
)
2413 ParagraphObj
* pPara
= aTextObj
.GetParagraph(i
);
2414 mpStrm
->WriteUInt32( pPara
->CharacterCount() )
2415 .WriteUInt16( pPara
->nDepth
);
2417 mpPptEscherEx
->EndAtom( EPP_BaseTextPropAtom
);
2418 mpPptEscherEx
->AddAtom( 10, EPP_TextSpecInfoAtom
);
2419 mpStrm
->WriteUInt32( mnTextSize
).WriteUInt32( 1 ).WriteUInt16( 0 );
2421 mpPptEscherEx
->CloseContainer(); // ESCHER_ClientTextBox
2422 mpPptEscherEx
->CloseContainer(); // ESCHER_SpContainer
2428 mnTextStyle
= EPP_TEXTSTYLE_BODY
;
2429 nPlaceHolderAtom
= rLayout
.nTypeOfOutliner
;
2430 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2431 ImplCreateShape( ESCHER_ShpInst_Rectangle
,
2432 ShapeFlag::HaveAnchor
| ShapeFlag::HaveMaster
,
2434 aPropOpt
.AddOpt( ESCHER_Prop_hspMaster
, mnShapeMasterBody
);
2435 aPropOpt
.CreateFillProperties( mXPropSet
, true, mXShape
);
2437 aPropOpt
.CreateTextProperties( mXPropSet
, mnTxId
);
2438 ImplAdjustFirstLineLineSpacing( aTextObj
, aPropOpt
);
2439 if ( mbEmptyPresObj
)
2441 sal_uInt32 nNoLineDrawDash
= 0;
2442 aPropOpt
.GetOpt( ESCHER_Prop_fNoLineDrawDash
, nNoLineDrawDash
);
2443 nNoLineDrawDash
|= 0x10001;
2444 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, nNoLineDrawDash
);
2453 if (ePageType
== MASTER
)
2455 SdrObject
* pObj
= GetSdrObjectFromXShape( mXShape
);
2456 if (pObj
&& pObj
->IsNotVisibleAsMaster())
2460 mType
= "drawing.Text";
2461 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2464 else if ( ( mType
== "drawing.Page" ) || ( mType
== "presentation.Page" ) )
2466 if ( ( ePageType
== NOTICE
) && mbPresObj
)
2468 if ( ImplCreatePresentationPlaceholder( bMasterPage
, EPP_TEXTTYPE_Notes
, EPP_PLACEHOLDER_MASTERNOTESSLIDEIMAGE
) )
2471 nPlaceHolderAtom
= EPP_PLACEHOLDER_NOTESSLIDEIMAGE
;
2473 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2475 else if ( mType
== "drawing.Frame" )
2479 else if ( ( mType
== "drawing.OLE2" ) || ( mType
== "presentation.OLE2" )
2480 || ( mType
== "presentation.Chart" ) || ( mType
== "presentation.Calc" )
2481 || ( mType
== "presentation.OrgChart" ) )
2483 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2484 if ( mbEmptyPresObj
&& ( ePageType
== NORMAL
) )
2486 nPlaceHolderAtom
= rLayout
.nUsedObjectPlaceHolder
;
2487 ImplCreateShape( ESCHER_ShpInst_Rectangle
,
2488 ShapeFlag::HaveAnchor
| ShapeFlag::HaveMaster
,
2491 aPropOpt
.AddOpt( ESCHER_Prop_lTxid
, mnTxId
);
2492 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x10001 );
2493 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x10001 );
2494 aPropOpt
.AddOpt( ESCHER_Prop_hspMaster
, mnShapeMasterBody
);
2498 mpExEmbed
->WriteUInt32( 0xf | ( EPP_ExEmbed
<< 16 ) )
2499 .WriteUInt32( 0 ); // Size of this container
2501 sal_uInt32 nSize
, nOldPos
= mpExEmbed
->Tell();
2503 mpExEmbed
->WriteUInt32( EPP_ExEmbedAtom
<< 16 )
2505 .WriteUInt32( 0 ) // follow colorscheme : 0->do not follow
2506 // 1->follow colorscheme
2507 // 2->follow text and background scheme
2508 .WriteUChar( 1 ) // (bool)set if embedded server can not be locked
2509 .WriteUChar( 0 ) // (bool)do not need to send dimension
2510 .WriteUChar( 0 ) // (bool)is object a world table
2511 .WriteUChar( 0 ); // pad byte
2513 std::unique_ptr
<PPTExOleObjEntry
> pE( new PPTExOleObjEntry( NORMAL_OLE_OBJECT
, mpExEmbed
->Tell() ) );
2514 pE
->xShape
= mXShape
;
2515 maExOleObj
.push_back( std::move(pE
) );
2519 sal_Int64 nAspect
= css::embed::Aspects::MSOLE_CONTENT
;
2522 // try to get the aspect when available
2523 css::uno::Reference
< css::beans::XPropertySet
> xShapeProps( mXShape
, css::uno::UNO_QUERY_THROW
);
2524 xShapeProps
->getPropertyValue("Aspect") >>= nAspect
;
2526 catch( css::uno::Exception
& )
2529 mpExEmbed
->WriteUInt32( 1 | ( EPP_ExOleObjAtom
<< 16 ) )
2531 .WriteUInt32( nAspect
) // Aspect
2533 .WriteUInt32( mnExEmbed
) // index to the persist table
2534 .WriteUInt32( 0 ) // subtype
2536 .WriteUInt32( 0x0012b600 );
2538 nSize
= mpExEmbed
->Tell() - nOldPos
;
2539 mpExEmbed
->Seek( nOldPos
- 4 );
2540 mpExEmbed
->WriteUInt32( nSize
);
2541 mpExEmbed
->Seek( STREAM_SEEK_TO_END
);
2542 nOlePictureId
= mnExEmbed
;
2544 ShapeFlag nSpFlags
= ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
;
2545 if ( nOlePictureId
)
2546 nSpFlags
|= ShapeFlag::OLEShape
;
2547 ImplCreateShape( ESCHER_ShpInst_PictureFrame
, nSpFlags
, aSolverContainer
);
2548 if ( aPropOpt
.CreateOLEGraphicProperties( mXShape
) )
2549 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2550 if ( nOlePictureId
)
2551 aPropOpt
.AddOpt( ESCHER_Prop_pictureId
, nOlePictureId
);
2554 else if ( mType
== "presentation.Header" )
2556 if ( ImplCreatePresentationPlaceholder( bMasterPage
, EPP_TEXTTYPE_Other
, EPP_PLACEHOLDER_MASTERHEADER
) )
2561 mType
= "drawing.Text";
2562 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2565 else if ( mType
== "presentation.Footer" )
2567 if ( ImplCreatePresentationPlaceholder( bMasterPage
, EPP_TEXTTYPE_Other
, EPP_PLACEHOLDER_MASTERFOOTER
) )
2572 mType
= "drawing.Text";
2573 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2576 else if ( mType
== "presentation.DateTime" )
2578 if ( ImplCreatePresentationPlaceholder( bMasterPage
, EPP_TEXTTYPE_Other
, EPP_PLACEHOLDER_MASTERDATE
) )
2583 mType
= "drawing.Text";
2584 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2587 else if ( mType
== "presentation.SlideNumber" )
2589 if ( ImplCreatePresentationPlaceholder( bMasterPage
, EPP_TEXTTYPE_Other
, EPP_PLACEHOLDER_MASTERSLIDENUMBER
) )
2594 mType
= "drawing.Text";
2595 ImplCreateTextShape( aPropOpt
, aSolverContainer
, true );
2598 else if ( (mType
.getLength() > 9) && (mType
[8] == '3') && (mType
[9] == 'D') ) // drawing.3D
2600 // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
2601 if ( !ImplGetPropertyValue( "Bitmap" ) )
2604 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2605 ImplCreateShape( ESCHER_ShpInst_PictureFrame
,
2606 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2609 if ( aPropOpt
.CreateGraphicProperties( mXPropSet
, "Bitmap", false ) )
2610 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2612 else if ( mType
== "drawing.Media" )
2615 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2616 ImplCreateShape( ESCHER_ShpInst_PictureFrame
,
2617 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2619 if ( aPropOpt
.CreateMediaGraphicProperties( mXShape
) )
2620 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2622 if ( PropValue::GetPropertyValue( aAny
, mXPropSet
, "MediaURL", true ) )
2625 if ( (aAny
>>= aMediaURL
) && !aMediaURL
.isEmpty() )
2627 // SJ: creating the Media RefObj
2628 sal_uInt32 nRefId
= ++mnExEmbed
;
2630 mpExEmbed
->WriteUInt16( 0xf )
2631 .WriteUInt16( EPP_ExMCIMovie
) // PPT_PST_ExAviMovie
2633 sal_uInt32 nSize
, nStart
= mpExEmbed
->Tell();
2634 mpExEmbed
->WriteUInt16( 0 )
2635 .WriteUInt16( EPP_ExObjRefAtom
)
2637 .WriteUInt32( nRefId
);
2638 mpExEmbed
->WriteUInt16( 0xf )
2639 .WriteUInt16( EPP_ExVideo
)
2642 mpExEmbed
->WriteUInt16( 0 )
2643 .WriteUInt16( EPP_ExMediaAtom
)
2645 .WriteUInt32( nRefId
)
2647 .WriteUInt16( 0x435 );
2649 sal_uInt16 i
, nStringLen
= static_cast<sal_uInt16
>(aMediaURL
.getLength());
2650 mpExEmbed
->WriteUInt32( EPP_CString
<< 16 ).WriteUInt32( nStringLen
* 2 );
2651 for ( i
= 0; i
< nStringLen
; i
++ )
2653 sal_Unicode nChar
= aMediaURL
[ i
];
2654 mpExEmbed
->WriteUInt16( nChar
);
2656 nSize
= mpExEmbed
->Tell() - nStart
;
2657 mpExEmbed
->SeekRel( - ( static_cast<sal_Int32
>(nSize
) + 4 ) );
2658 mpExEmbed
->WriteUInt32( nSize
); // size of PPT_PST_ExMCIMovie
2659 mpExEmbed
->SeekRel( 0x10 );
2661 mpExEmbed
->WriteUInt32( nSize
); // PPT_PST_ExMediaAtom
2662 mpExEmbed
->SeekRel( nSize
);
2665 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2666 pClientData
->WriteUInt16( 0 )
2667 .WriteUInt16( EPP_ExObjRefAtom
)
2669 .WriteUInt32( nRefId
);
2670 // write EPP_InteractiveInfo container for no_action
2671 pClientData
->WriteUInt32( ( EPP_InteractiveInfo
<< 16 ) | 0xf ).WriteUInt32( 24 );
2672 pClientData
->WriteUInt16( 0 )
2673 .WriteUInt16( EPP_InteractiveInfoAtom
)
2685 else if ( (mType
== "drawing.Table") || (mType
== "presentation.Table") )
2687 if ( eCa
!= css::presentation::ClickAction_NONE
)
2689 SvMemoryStream
aTmp(0x200, 0x200);
2690 ImplWriteClickAction( aTmp
, eCa
, bMediaClickAction
);
2692 ImplCreateTable( mXShape
, aSolverContainer
, aPropOpt
);
2695 else if ( mType
== "drawing.dontknow" )
2698 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2699 ImplCreateShape( ESCHER_ShpInst_PictureFrame
,
2700 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
,
2702 if ( aPropOpt
.CreateGraphicProperties( mXPropSet
, "MetaFile", false ) )
2703 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x800080 );
2710 bool bClientData
= ( bEffect
|| ( eCa
!= css::presentation::ClickAction_NONE
) ||
2711 nPlaceHolderAtom
|| nOlePictureId
);
2714 if ( nPlaceHolderAtom
)
2716 sal_Int32 nPlacementID
= -1;
2717 if ( ( mnTextStyle
== EPP_TEXTSTYLE_TITLE
) || ( mnTextStyle
== EPP_TEXTSTYLE_BODY
) )
2718 nPlacementID
= nIndices
++;
2721 switch ( nPlaceHolderAtom
)
2725 if ( nPlaceHolderAtom
< 19 )
2729 case EPP_PLACEHOLDER_NOTESBODY
:
2730 case EPP_PLACEHOLDER_MASTERDATE
:
2731 case EPP_PLACEHOLDER_NOTESSLIDEIMAGE
:
2732 case EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE
:
2733 nPlacementID
= nIndices
++;
2737 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2739 pClientData
->WriteUInt32( EPP_OEPlaceholderAtom
<< 16 ).WriteUInt32( 8 )
2740 .WriteInt32( nPlacementID
) // PlacementID
2741 .WriteUChar( nPlaceHolderAtom
) // PlaceHolderID
2742 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2743 .WriteUInt16( 0 ); // padword
2745 if ( nOlePictureId
)
2748 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2750 pClientData
->WriteUInt32( EPP_ExObjRefAtom
<< 16 ).WriteUInt32( 4 )
2751 .WriteUInt32( nOlePictureId
);
2754 if ( bEffect
&& !pClientData
)
2756 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2759 if ( eCa
!= css::presentation::ClickAction_NONE
)
2762 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2763 ImplWriteClickAction( *pClientData
, eCa
, bMediaClickAction
);
2766 if ( ( mnTextStyle
== EPP_TEXTSTYLE_TITLE
) || ( mnTextStyle
== EPP_TEXTSTYLE_BODY
) )
2768 if ( !pClientTextBox
)
2769 pClientTextBox
.reset(new SvMemoryStream( 0x200, 0x200 ));
2771 if ( !mbEmptyPresObj
)
2773 if ( ( ePageType
== NORMAL
) && !bMasterPage
)
2775 sal_uInt32 nTextType
= EPP_TEXTTYPE_Body
;
2776 if ( mnTextStyle
== EPP_TEXTSTYLE_BODY
)
2779 nTextType
= EPP_TEXTTYPE_HalfBody
;
2780 else if ( mType
== "presentation.Subtitle" )
2781 nTextType
= EPP_TEXTTYPE_CenterBody
;
2785 nTextType
= EPP_TEXTTYPE_Title
;
2787 TextRuleEntry aTextRule
;
2788 SvMemoryStream
aExtBu( 0x200, 0x200 );
2790 ImplWriteTextStyleAtom( *pClientTextBox
, nTextType
, nPObjects
, &aTextRule
, aExtBu
, nullptr );
2791 ImplWriteExtParaHeader( aExtBu
, nPObjects
++, nTextType
, nPageNumber
+ 0x100 );
2792 SvMemoryStream
* pOut
= aTextRule
.pOut
.get();
2795 pClientTextBox
->WriteBytes(pOut
->GetData(), pOut
->Tell());
2796 aTextRule
.pOut
.reset();
2798 if ( aExtBu
.Tell() )
2801 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2802 ImplProgTagContainer( pClientData
.get(), &aExtBu
);
2809 if ( !aPropOpt
.IsFontWork() )
2811 if ( mnTextSize
|| ( nPlaceHolderAtom
== EPP_PLACEHOLDER_MASTERDATE
) || ( nPlaceHolderAtom
== EPP_PLACEHOLDER_NOTESBODY
) )
2814 if ( ( nPlaceHolderAtom
== EPP_PLACEHOLDER_MASTERDATE
) || ( nPlaceHolderAtom
== EPP_PLACEHOLDER_NOTESBODY
) )
2817 nInstance2
= EPP_TEXTTYPE_Other
; // Text in a Shape
2819 if ( !pClientTextBox
)
2820 pClientTextBox
.reset(new SvMemoryStream( 0x200, 0x200 ));
2822 SvMemoryStream
aExtBu( 0x200, 0x200 );
2823 ImplWriteTextStyleAtom( *pClientTextBox
, nInstance2
, 0, nullptr, aExtBu
, &aPropOpt
);
2824 if ( aExtBu
.Tell() )
2827 pClientData
.reset(new SvMemoryStream( 0x200, 0x200 ));
2828 ImplProgTagContainer( pClientData
.get(), &aExtBu
);
2831 else if ( nPlaceHolderAtom
>= 19 )
2833 if ( !pClientTextBox
)
2834 pClientTextBox
.reset(new SvMemoryStream( 12 ));
2836 pClientTextBox
->WriteUInt32( EPP_TextHeaderAtom
<< 16 ).WriteUInt32( 4 )
2842 aPropOpt
.CreateShadowProperties( mXPropSet
);
2845 ImplFlipBoundingBox( aPropOpt
);
2846 aPropOpt
.CreateShapeProperties( mXShape
);
2847 aPropOpt
.Commit( *mpStrm
);
2848 if ( GetCurrentGroupLevel() > 0 )
2849 mpPptEscherEx
->AddChildAnchor( maRect
);
2851 mpPptEscherEx
->AddClientAnchor( maRect
);
2855 mpStrm
->WriteUInt32( ( ESCHER_ClientData
<< 16 ) | 0xf )
2856 .WriteUInt32( pClientData
->Tell() );
2858 mpStrm
->WriteBytes(pClientData
->GetData(), pClientData
->Tell());
2859 pClientData
.reset();
2861 if ( pClientTextBox
)
2863 mpStrm
->WriteUInt32( ( ESCHER_ClientTextbox
<< 16 ) | 0xf )
2864 .WriteUInt32( pClientTextBox
->Tell() );
2866 mpStrm
->WriteBytes(pClientTextBox
->GetData(), pClientTextBox
->Tell());
2867 pClientTextBox
.reset();
2869 mpPptEscherEx
->CloseContainer(); // ESCHER_SpContainer
2871 nPrevTextStyle
= mnTextStyle
;
2873 if ( bAdditionalText
)
2875 bAdditionalText
= false;
2878 EscherPropertyContainer aPropOpt
;
2879 mnAngle
= ( PropValue::GetPropertyValue( aAny
,
2880 mXPropSet
, "RotateAngle", true ) )
2881 ? *o3tl::doAccess
<sal_Int32
>(aAny
)
2884 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x90000 );
2885 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x100000 );
2886 if ( mType
== "drawing.Line" )
2888 double fDist
= hypot( maRect
.GetWidth(), maRect
.GetHeight() );
2889 maRect
= ::tools::Rectangle( Point( aTextRefPoint
.X
, aTextRefPoint
.Y
),
2890 Point( static_cast<sal_Int32
>( aTextRefPoint
.X
+ fDist
), aTextRefPoint
.Y
- 1 ) );
2891 ImplCreateTextShape( aPropOpt
, aSolverContainer
, false );
2892 aPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x60006 ); // Size Shape To Fit Text
2894 mnAngle
= ( 36000 + mnAngle
) % 36000;
2896 ImplFlipBoundingBox( aPropOpt
);
2900 ImplCreateTextShape( aPropOpt
, aSolverContainer
, false );
2902 mnAngle
= ( 36000 + mnAngle
) % 36000;
2904 mnAngle
= ( 36000 - ( mnAngle
% 36000 ) );
2908 mnAngle
&=~0xffff; // round nAngle to full grad
2909 aPropOpt
.AddOpt( ESCHER_Prop_Rotation
, mnAngle
);
2911 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2912 // mpPptEscherEx->SetGroupSnapRect( nGroupLevel, maRect );
2913 // mpPptEscherEx->SetGroupLogicRect( nGroupLevel, maRect );
2915 if ( !pClientTextBox
)
2916 pClientTextBox
.reset(new SvMemoryStream( 0x200, 0x200 ));
2918 SvMemoryStream
aExtBu( 0x200, 0x200 );
2919 ImplWriteTextStyleAtom( *pClientTextBox
, EPP_TEXTTYPE_Other
, 0, nullptr, aExtBu
, &aPropOpt
);
2921 aPropOpt
.CreateShapeProperties( mXShape
);
2922 aPropOpt
.Commit( *mpStrm
);
2923 if ( GetCurrentGroupLevel() > 0 )
2924 mpPptEscherEx
->AddChildAnchor( maRect
);
2926 mpPptEscherEx
->AddClientAnchor( maRect
);
2928 mpStrm
->WriteUInt32( ( ESCHER_ClientTextbox
<< 16 ) | 0xf )
2929 .WriteUInt32( pClientTextBox
->Tell() );
2931 mpStrm
->WriteBytes(pClientTextBox
->GetData(), pClientTextBox
->Tell());
2932 pClientTextBox
.reset();
2934 mpPptEscherEx
->CloseContainer(); // ESCHER_SpContainer
2936 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2937 // mpPptEscherEx->LeaveGroup();
2940 ClearGroupTable(); // storing groups if any are still open, which should not be the case
2941 nGroups
= GetGroupsClosed();
2942 for ( sal_uInt32 i
= 0; i
< nGroups
; i
++, mpPptEscherEx
->LeaveGroup() ) ;
2948 sal_Int32 mnPos
; // specifies the distance to the top/left position of the table
2949 table::BorderLine maCellBorder
;
2951 CellBorder() : mnPos ( 0 ) {};
2954 bool PPTWriter::ImplCreateCellBorder( const CellBorder
* pCellBorder
, sal_Int32 nX1
, sal_Int32 nY1
, sal_Int32 nX2
, sal_Int32 nY2
)
2956 sal_Int32 nLineWidth
= pCellBorder
->maCellBorder
.OuterLineWidth
+ pCellBorder
->maCellBorder
.InnerLineWidth
;
2961 mpPptEscherEx
->OpenContainer( ESCHER_SpContainer
);
2962 EscherPropertyContainer aPropOptSp
;
2964 sal_uInt32 nId
= mpPptEscherEx
->GenerateShapeId();
2965 mpPptEscherEx
->AddShape( ESCHER_ShpInst_Line
,
2966 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
| ShapeFlag::Child
,
2968 aPropOptSp
.AddOpt( ESCHER_Prop_shapePath
, ESCHER_ShapeComplex
);
2969 aPropOptSp
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0xa0008 );
2970 aPropOptSp
.AddOpt( ESCHER_Prop_fshadowObscured
, 0x20000 );
2972 sal_uInt32 nBorderColor
= pCellBorder
->maCellBorder
.Color
& 0xff00; // green
2973 nBorderColor
|= static_cast< sal_uInt8
>( pCellBorder
->maCellBorder
.Color
) << 16; // red
2974 nBorderColor
|= static_cast< sal_uInt8
>( pCellBorder
->maCellBorder
.Color
>> 16 ); // blue
2975 aPropOptSp
.AddOpt( ESCHER_Prop_lineColor
, nBorderColor
);
2977 aPropOptSp
.AddOpt( ESCHER_Prop_lineWidth
, nLineWidth
* 360 );
2978 aPropOptSp
.AddOpt( ESCHER_Prop_fc3DLightFace
, 0x80000 );
2979 aPropOptSp
.Commit( *mpStrm
);
2980 mpPptEscherEx
->AddAtom( 16, ESCHER_ChildAnchor
);
2981 mpStrm
->WriteInt32( nX1
)
2985 mpPptEscherEx
->CloseContainer();
2991 //get merged cell's width
2992 static sal_Int32
GetCellRight( sal_Int32 nColumn
,
2993 ::tools::Rectangle
const & rect
,
2994 std::vector
< std::pair
< sal_Int32
, sal_Int32
> >& aColumns
,
2995 uno::Reference
< table::XMergeableCell
> const & xCell
)
2997 sal_Int32 nRight
= aColumns
[ nColumn
].first
+ aColumns
[ nColumn
].second
;
2998 for ( sal_Int32 nColumnSpan
= 1; nColumnSpan
< xCell
->getColumnSpan(); nColumnSpan
++ )
3000 sal_uInt32 nC
= nColumnSpan
+ nColumn
;
3001 if ( nC
< aColumns
.size() )
3002 nRight
+= aColumns
[ nC
].second
;
3004 nRight
= rect
.Right();
3008 //get merged cell's height
3009 static sal_Int32
GetCellBottom( sal_Int32 nRow
,
3010 ::tools::Rectangle
const & rect
,
3011 std::vector
< std::pair
< sal_Int32
, sal_Int32
> >& aRows
,
3012 uno::Reference
< table::XMergeableCell
> const & xCell
)
3014 sal_Int32 nBottom
= aRows
[nRow
].first
+ aRows
[nRow
].second
;
3015 for ( sal_Int32 nRowSpan
= 1; nRowSpan
< xCell
->getRowSpan(); nRowSpan
++ )
3017 sal_uInt32 nR
= nRowSpan
+ nRow
;
3018 if ( nR
< aRows
.size() )
3019 nBottom
+= aRows
[ nR
].second
;
3021 nBottom
= rect
.Bottom();
3026 void PPTWriter::WriteCString( SvStream
& rSt
, const OUString
& rString
, sal_uInt32 nInstance
)
3028 sal_Int32 nLen
= rString
.getLength();
3031 rSt
.WriteUInt32( ( nInstance
<< 4 ) | ( EPP_CString
<< 16 ) )
3032 .WriteUInt32( nLen
<< 1 );
3033 for ( sal_Int32 i
= 0; i
< nLen
; i
++ )
3034 rSt
.WriteUInt16( rString
[i
] );
3038 class ContainerGuard
3041 PptEscherEx
* m_pPptEscherEx
;
3043 ContainerGuard(PptEscherEx
* pPptEscherEx
, sal_uInt16 nRecord
)
3044 : m_pPptEscherEx(pPptEscherEx
)
3046 m_pPptEscherEx
->OpenContainer(nRecord
);
3050 m_pPptEscherEx
->CloseContainer();
3054 void PPTWriter::ImplCreateTable( uno::Reference
< drawing::XShape
> const & rXShape
, EscherSolverContainer
& aSolverContainer
,
3055 EscherPropertyContainer
& aPropOpt
)
3059 uno::Reference
< table::XTable
> xTable
;
3060 if ( mXPropSet
->getPropertyValue( "Model" ) >>= xTable
)
3062 uno::Reference
< table::XColumnRowRange
> xColumnRowRange( xTable
, uno::UNO_QUERY_THROW
);
3063 uno::Reference
< container::XIndexAccess
> xColumns( xColumnRowRange
->getColumns(), uno::UNO_QUERY_THROW
);
3064 uno::Reference
< container::XIndexAccess
> xRows( xColumnRowRange
->getRows(), uno::UNO_QUERY_THROW
);
3065 sal_uInt16 nRowCount
= static_cast< sal_uInt16
>( xRows
->getCount() );
3066 sal_uInt16 nColumnCount
= static_cast< sal_uInt16
>( xColumns
->getCount() );
3068 std::vector
< std::pair
< sal_Int32
, sal_Int32
> > aColumns
;
3069 std::vector
< std::pair
< sal_Int32
, sal_Int32
> > aRows
;
3071 awt::Point
aPosition( MapPoint( rXShape
->getPosition() ) );
3072 sal_Int32 nPosition
= aPosition
.X
;
3073 for ( sal_Int32 x
= 0; x
< nColumnCount
; x
++ )
3075 uno::Reference
< beans::XPropertySet
> xPropSet( xColumns
->getByIndex( x
), uno::UNO_QUERY_THROW
);
3076 awt::Size
aS( 0, 0 );
3077 xPropSet
->getPropertyValue( "Width" ) >>= aS
.Width
;
3078 awt::Size
aM( MapSize( aS
) );
3079 aColumns
.emplace_back( nPosition
, aM
.Width
);
3080 nPosition
+= aM
.Width
;
3081 if ( x
== nColumnCount
- 1 && nPosition
!= maRect
.Right() )
3082 maRect
.SetRight( nPosition
);
3085 nPosition
= aPosition
.Y
;
3086 for ( sal_Int32 y
= 0; y
< nRowCount
; y
++ )
3088 uno::Reference
< beans::XPropertySet
> xPropSet( xRows
->getByIndex( y
), uno::UNO_QUERY_THROW
);
3089 awt::Size
aS( 0, 0 );
3090 xPropSet
->getPropertyValue( "Height" ) >>= aS
.Height
;
3091 awt::Size
aM( MapSize( aS
) );
3092 aRows
.emplace_back( nPosition
, aM
.Height
);
3093 nPosition
+= aM
.Height
;
3094 if ( y
== nRowCount
- 1 && nPosition
!= maRect
.Bottom())
3095 maRect
.SetBottom( nPosition
);
3097 std::unique_ptr
<ContainerGuard
> xSpgrContainer(new ContainerGuard(mpPptEscherEx
.get(), ESCHER_SpgrContainer
));
3098 std::unique_ptr
<ContainerGuard
> xSpContainer(new ContainerGuard(mpPptEscherEx
.get(), ESCHER_SpContainer
));
3099 mpPptEscherEx
->AddAtom( 16, ESCHER_Spgr
, 1 );
3100 mpStrm
->WriteInt32( maRect
.Left() ) // Bounding box for the grouped shapes to which they are attached
3101 .WriteInt32( maRect
.Top() )
3102 .WriteInt32( maRect
.Right() )
3103 .WriteInt32( maRect
.Bottom() );
3105 sal_uInt32 nShapeId
= mpPptEscherEx
->GenerateShapeId();
3106 mpPptEscherEx
->AddShape( ESCHER_ShpInst_Min
, ShapeFlag::HaveAnchor
| ShapeFlag::Group
, nShapeId
);
3107 // TODO: check flags, comment does not match code // Flags: Group | Patriarch
3108 aSolverContainer
.AddShape( rXShape
, nShapeId
);
3109 EscherPropertyContainer aPropOpt2
;
3111 SvMemoryStream aMemStrm
;
3112 aMemStrm
.WriteUInt16( nRowCount
)
3113 .WriteUInt16( nRowCount
)
3116 for( const auto& rRow
: aRows
)
3117 aMemStrm
.WriteInt32( rRow
.second
);
3119 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x1000100 );
3120 aPropOpt2
.AddOpt( ESCHER_Prop_tableProperties
, 1 );
3121 aPropOpt2
.AddOpt(ESCHER_Prop_tableRowProperties
, true, 0, aMemStrm
);
3122 aPropOpt
.CreateShapeProperties( rXShape
);
3123 aPropOpt
.Commit( *mpStrm
);
3124 aPropOpt2
.Commit( *mpStrm
, 3, ESCHER_UDefProp
);
3125 if ( GetCurrentGroupLevel() > 0 )
3126 mpPptEscherEx
->AddChildAnchor( maRect
);
3128 mpPptEscherEx
->AddClientAnchor( maRect
);
3129 xSpContainer
.reset(); //ESCHER_SpContainer
3131 uno::Reference
< table::XCellRange
> xCellRange( xTable
, uno::UNO_QUERY_THROW
);
3132 for( sal_Int32 nRow
= 0; nRow
< xRows
->getCount(); nRow
++ )
3134 for( sal_Int32 nColumn
= 0; nColumn
< xColumns
->getCount(); nColumn
++ )
3136 uno::Reference
< table::XMergeableCell
> xCell( xCellRange
->getCellByPosition( nColumn
, nRow
), uno::UNO_QUERY_THROW
);
3137 if ( !xCell
->isMerged() )
3139 sal_Int32 nLeft
= aColumns
[ nColumn
].first
;
3140 sal_Int32 nTop
= aRows
[ nRow
].first
;
3141 sal_Int32 nRight
= GetCellRight( nColumn
, maRect
,aColumns
,xCell
);
3142 sal_Int32 nBottom
= GetCellBottom( nRow
, maRect
,aRows
,xCell
);
3144 mbFontIndependentLineSpacing
= false;
3145 mXPropSet
.set( xCell
, uno::UNO_QUERY_THROW
);
3146 mXText
.set( xCell
, uno::UNO_QUERY_THROW
);
3147 mnTextSize
= mXText
->getString().getLength();
3150 if ( GetPropertyValue( aAny
, mXPropSet
, "FontIndependentLineSpacing", true ) )
3151 aAny
>>= mbFontIndependentLineSpacing
;
3153 EscherPropertyContainer aPropOptSp
;
3154 std::unique_ptr
<ContainerGuard
> xCellContainer(new ContainerGuard(mpPptEscherEx
.get(), ESCHER_SpContainer
));
3155 ImplCreateShape( ESCHER_ShpInst_Rectangle
,
3156 ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
| ShapeFlag::Child
,
3158 aPropOptSp
.CreateFillProperties( mXPropSet
, true );
3159 aPropOptSp
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x90000 );
3161 aPropOptSp
.CreateTextProperties( mXPropSet
, mnTxId
);
3162 aPropOptSp
.AddOpt( ESCHER_Prop_WrapText
, ESCHER_WrapSquare
);
3164 SvMemoryStream
aClientTextBox( 0x200, 0x200 );
3165 SvMemoryStream
aExtBu( 0x200, 0x200 );
3167 ImplWriteTextStyleAtom( aClientTextBox
, EPP_TEXTTYPE_Other
, 0, nullptr, aExtBu
, &aPropOptSp
);
3169 // need write client data for extend bullet
3170 if ( aExtBu
.Tell() )
3172 std::unique_ptr
<SvMemoryStream
> pClientData(new SvMemoryStream( 0x200, 0x200 ));
3173 ImplProgTagContainer( pClientData
.get(), &aExtBu
);
3174 mpStrm
->WriteUInt32( ( ESCHER_ClientData
<< 16 ) | 0xf )
3175 .WriteUInt32( pClientData
->Tell() );
3177 mpStrm
->WriteBytes(pClientData
->GetData(), pClientData
->Tell());
3180 aPropOptSp
.Commit( *mpStrm
);
3181 mpPptEscherEx
->AddAtom( 16, ESCHER_ChildAnchor
);
3182 mpStrm
->WriteInt32( nLeft
)
3184 .WriteInt32( nRight
)
3185 .WriteInt32( nBottom
);
3187 mpStrm
->WriteUInt32( ( ESCHER_ClientTextbox
<< 16 ) | 0xf )
3188 .WriteUInt32( aClientTextBox
.Tell() );
3190 mpStrm
->WriteBytes(aClientTextBox
.GetData(), aClientTextBox
.Tell());
3191 xCellContainer
.reset();
3196 // creating horz lines
3197 for( sal_Int32 nLine
= 0; nLine
< ( xRows
->getCount() + 1 ); nLine
++ )
3199 for( sal_Int32 nColumn
= 0; nColumn
< xColumns
->getCount(); nColumn
++ )
3201 CellBorder aCellBorder
;
3202 aCellBorder
.mnPos
= aColumns
[ nColumn
].first
;
3204 //write nLine*nColumn cell's top border
3205 if ( nLine
< xRows
->getCount() )
3207 uno::Reference
< table::XMergeableCell
> xCell( xCellRange
->getCellByPosition( nColumn
, nLine
), uno::UNO_QUERY_THROW
);
3208 if ( !xCell
->isMerged() )
3210 uno::Reference
< beans::XPropertySet
> xPropSet2( xCell
, uno::UNO_QUERY_THROW
);
3211 table::BorderLine aBorderLine
;
3212 if ( xPropSet2
->getPropertyValue( "TopBorder" ) >>= aBorderLine
)
3213 aCellBorder
.maCellBorder
= aBorderLine
;
3214 sal_Int32 nRight
= GetCellRight( nColumn
, maRect
,aColumns
,xCell
);
3215 bTop
= ImplCreateCellBorder( &aCellBorder
, aCellBorder
.mnPos
,
3216 aRows
[ nLine
].first
, nRight
, aRows
[ nLine
].first
);
3220 //if nLine*nColumn cell's top border is empty, check (nLine-1)*nColumn cell's bottom border
3221 //and write the last row's bottom border
3222 if (( nLine
&& !bTop
) || (nLine
== xRows
->getCount()))
3224 sal_Int32 nRow
= nLine
;
3227 { //find last no merged cell
3228 uno::Reference
< table::XMergeableCell
> xCell( xCellRange
->getCellByPosition( nColumn
, nRow
- 1 ), uno::UNO_QUERY_THROW
);
3229 if ( !xCell
->isMerged() )
3231 sal_Int32 nRight
= GetCellRight( nColumn
, maRect
,aColumns
,xCell
);
3232 sal_Int32 nBottom
= GetCellBottom( nRow
- 1, maRect
,aRows
,xCell
);
3233 if ( nBottom
== ( aRows
[ nLine
-1 ].first
+ aRows
[ nLine
-1 ].second
) )
3235 uno::Reference
< table::XMergeableCell
> xCellOwn( xCellRange
->getCellByPosition( nColumn
, nRow
- 1 ), uno::UNO_QUERY_THROW
);
3236 uno::Reference
< beans::XPropertySet
> xPropSet2( xCellOwn
, uno::UNO_QUERY_THROW
);
3237 table::BorderLine aBorderLine
;
3238 if ( xPropSet2
->getPropertyValue( "BottomBorder" ) >>= aBorderLine
)
3239 aCellBorder
.maCellBorder
= aBorderLine
;
3240 ImplCreateCellBorder( &aCellBorder
, aCellBorder
.mnPos
,
3241 nBottom
, nRight
, nBottom
);
3252 // creating vertical lines
3253 for( sal_Int32 nLine
= 0; nLine
< ( xColumns
->getCount() + 1 ); nLine
++ )
3255 for( sal_Int32 nRow
= 0; nRow
< xRows
->getCount(); nRow
++ )
3258 CellBorder aCellBorder
;
3259 aCellBorder
.mnPos
= aRows
[ nRow
].first
;
3261 if ( nLine
< xColumns
->getCount() )
3263 uno::Reference
< table::XMergeableCell
> xCell( xCellRange
->getCellByPosition( nLine
, nRow
), uno::UNO_QUERY_THROW
);
3264 if (!xCell
->isMerged() )
3266 uno::Reference
< beans::XPropertySet
> xCellSet( xCell
, uno::UNO_QUERY_THROW
);
3267 table::BorderLine aBorderLine
;
3268 if ( xCellSet
->getPropertyValue( "LeftBorder" ) >>= aBorderLine
)
3269 aCellBorder
.maCellBorder
= aBorderLine
;
3270 sal_Int32 nBottom
= GetCellBottom( nRow
, maRect
, aRows
,xCell
);
3271 bLeft
= ImplCreateCellBorder( &aCellBorder
, aColumns
[nLine
].first
, aCellBorder
.mnPos
,
3272 aColumns
[nLine
].first
, nBottom
);
3275 if ( ( nLine
&& !bLeft
)||(nLine
== xColumns
->getCount()))
3277 sal_Int32 nColumn
= nLine
;
3280 uno::Reference
< table::XMergeableCell
> xCell( xCellRange
->getCellByPosition( nColumn
- 1, nRow
), uno::UNO_QUERY_THROW
);
3281 if (!xCell
->isMerged() )
3283 sal_Int32 nRight
= GetCellRight( nColumn
-1, maRect
, aColumns
,xCell
);
3284 sal_Int32 nBottom
= GetCellBottom( nRow
, maRect
, aRows
, xCell
);
3285 if ( nRight
== (aColumns
[nLine
-1].first
+ aColumns
[nLine
-1].second
) )
3287 uno::Reference
< table::XMergeableCell
> xCellOwn( xCellRange
->getCellByPosition( nColumn
- 1, nRow
), uno::UNO_QUERY_THROW
);
3288 uno::Reference
< beans::XPropertySet
> xCellSet( xCellOwn
, uno::UNO_QUERY_THROW
);
3289 table::BorderLine aBorderLine
;
3290 if ( xCellSet
->getPropertyValue( "RightBorder" ) >>= aBorderLine
)
3291 aCellBorder
.maCellBorder
= aBorderLine
;
3292 ImplCreateCellBorder( &aCellBorder
, nRight
, aCellBorder
.mnPos
,
3304 xSpgrContainer
.reset(); //ESCHER_SpgrContainer
3307 catch( uno::Exception
& )
3312 void TextObjBinary::Write( SvStream
* pStrm
)
3314 sal_uInt32 nSize
, nPos
= pStrm
->Tell();
3315 pStrm
->WriteUInt32( EPP_TextCharsAtom
<< 16 ).WriteUInt32( 0 );
3316 for ( sal_uInt32 i
= 0; i
< ParagraphCount(); ++i
)
3317 GetParagraph(i
)->Write( pStrm
);
3318 nSize
= pStrm
->Tell() - nPos
;
3319 pStrm
->SeekRel( - ( static_cast<sal_Int32
>(nSize
) - 4 ) );
3320 pStrm
->WriteUInt32( nSize
- 8 );
3321 pStrm
->SeekRel( nSize
- 8 );
3324 void TextObjBinary::WriteTextSpecInfo( SvStream
* pStrm
)
3326 sal_uInt32
nCharactersLeft( Count() );
3327 if ( nCharactersLeft
< 1 )
3330 EscherExAtom
aAnimationInfoAtom( *pStrm
, EPP_TextSpecInfoAtom
, 0, 0 );
3331 for ( sal_uInt32 i
= 0; nCharactersLeft
&& i
< ParagraphCount(); ++i
)
3333 ParagraphObj
* pPtr
= GetParagraph(i
);
3334 for ( std::vector
<std::unique_ptr
<PortionObj
> >::const_iterator it
= pPtr
->begin(); nCharactersLeft
&& it
!= pPtr
->end(); ++it
)
3336 const PortionObj
& rPortion
= **it
;
3337 sal_Int32 nPortionSize
= rPortion
.mnTextSize
>= nCharactersLeft
? nCharactersLeft
: rPortion
.mnTextSize
;
3338 sal_Int32
const nFlags
= 7;
3339 nCharactersLeft
-= nPortionSize
;
3340 pStrm
->WriteUInt32( nPortionSize
)
3341 .WriteInt32( nFlags
)
3342 .WriteInt16( 1 ) // spellinfo -> needs rechecking
3343 .WriteInt16( static_cast<sal_uInt16
>(LanguageTag( rPortion
.meCharLocale
).makeFallback().getLanguageType()) )
3344 .WriteInt16( 0 ); // alt language
3347 if ( nCharactersLeft
)
3348 pStrm
->WriteUInt32( nCharactersLeft
).WriteInt32( 1 ).WriteInt16( 1 );
3351 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */