bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / filter / eppt / epptso.cxx
blobbcd4d1cf9711da133eb4f8c32c902c5ec6c928ef
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <sal/config.h>
23 #include <basegfx/numeric/ftools.hxx>
24 #include <o3tl/any.hxx>
25 #include "eppt.hxx"
26 #include "text.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
63 /* Font Families */
64 #define FF_ROMAN 0x10
65 #define FF_SWISS 0x20
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() )
95 Size aNewSize;
96 bool changed = false;
97 if (aPrefSize.Width() == 0 || aPrefSize.Height() == 0)
99 aBmpEx.Scale(aPrefSize);
100 aNewSize = aPrefSize;
101 changed = true;
103 else
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());
107 double fXScale = 1;
108 double fYScale = 1;
110 if ( fQ1 > fQ2 )
111 fYScale = fQ1 / fQ2;
112 else if ( fQ1 < fQ2 )
113 fXScale = fQ2 / fQ1;
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 ) );
120 changed = true;
123 if (changed)
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;
137 return nRetValue;
140 sal_uInt32 PPTWriter::ImplVBAInfoContainer( SvStream* pStrm )
142 sal_uInt32 nSize = 28;
143 if ( pStrm )
145 pStrm->WriteUInt32( 0x1f | ( EPP_VBAInfo << 16 ) )
146 .WriteUInt32( nSize - 8 )
147 .WriteUInt32( 2 | ( EPP_VBAInfoAtom << 16 ) )
148 .WriteUInt32( 12 );
149 mpPptEscherEx->InsertPersistOffset( EPP_Persist_VBAInfoAtom, pStrm->Tell() );
150 pStrm->WriteUInt32( 0 )
151 .WriteUInt32( 0 )
152 .WriteUInt32( 1 );
154 return nSize;
157 sal_uInt32 PPTWriter::ImplSlideViewInfoContainer( sal_uInt32 nInstance, SvStream* pStrm )
159 sal_uInt32 nSize = 111;
160 if ( pStrm )
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;
174 if ( nInstance )
176 bShowGuides = 1;
177 nScaling = 0x3b;
178 nMasterCoordinate = 0xf0c;
179 nXOrigin = -1752;
180 nYOrigin = -72;
181 nPosition1 = 0xb40;
182 nPosition2 = 0x870;
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.
203 return nSize;
206 sal_uInt32 PPTWriter::ImplOutlineViewInfoContainer( SvStream* pStrm )
208 sal_uInt32 nSize = 68;
209 if ( pStrm )
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
221 return nSize;
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;
236 if ( pStrm )
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);
250 return nSize;
253 sal_uInt32 PPTWriter::ImplProgBinaryTagContainer( SvStream* pStrm, SvMemoryStream* pBinTagStrm )
255 sal_uInt32 nSize = 8 + 8 + 14;
256 if ( pStrm )
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();
266 nSize += nLen + 8;
267 pStrm->WriteUInt32( EPP_BinaryTagData << 16 ).WriteUInt32( nLen );
268 pStrm->WriteBytes(pBinTagStrm->GetData(), nLen);
270 else
271 nSize += ImplProgBinaryTag( pStrm );
273 if ( pStrm )
275 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
276 pStrm->WriteUInt32( nSize - 8 );
277 pStrm->SeekRel( nSize - 8 );
279 return nSize;
282 sal_uInt32 PPTWriter::ImplProgTagContainer( SvStream* pStrm, SvMemoryStream* pBinTagStrm )
284 sal_uInt32 nSize = 0;
285 if ( aBuExPictureStream.Tell() || aBuExOutlineStream.Tell() || pBinTagStrm )
287 nSize = 8;
288 if ( pStrm )
290 pStrm->WriteUInt32( 0xf | ( EPP_ProgTags << 16 ) ).WriteUInt32( 0 );
292 nSize += ImplProgBinaryTagContainer( pStrm, pBinTagStrm );
293 if ( pStrm )
295 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
296 pStrm->WriteUInt32( nSize - 8 );
297 pStrm->SeekRel( nSize - 8 );
300 return nSize;
303 sal_uInt32 PPTWriter::ImplDocumentListContainer( SvStream* pStrm )
305 sal_uInt32 nSize = 8;
306 if ( pStrm )
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 );
317 if ( pStrm )
319 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
320 pStrm->WriteUInt32( nSize - 8 );
321 pStrm->SeekRel( nSize - 8 );
323 return nSize;
326 sal_uInt32 PPTWriter::ImplMasterSlideListContainer( SvStream* pStrm )
328 sal_uInt32 i, nSize = 28 * mnMasterPages + 8;
329 if ( pStrm )
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
344 return nSize;
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 )
365 .WriteUInt32( 0 );
366 sal_uInt32 nHyperSize, nHyperStart = mpExEmbed->Tell();
367 mpExEmbed->WriteUInt16( 0 )
368 .WriteUInt16( EPP_ExHyperlinkAtom )
369 .WriteUInt32( 4 )
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 );
381 return nHyperId;
384 bool PPTWriter::ImplCloseDocument()
386 sal_uInt32 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_Document );
387 if ( nOfs )
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
397 sal_uInt16 nLev;
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;
417 if ( nExEmbedSize )
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
429 if ( nExEmbedSize )
431 mpStrm->WriteUInt16( 0xf )
432 .WriteUInt16( EPP_ExObjList )
433 .WriteUInt32( nExEmbedSize + 12 )
434 .WriteUInt16( 0 )
435 .WriteUInt16( EPP_ExObjListAtom )
436 .WriteUInt32( 4 )
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();
458 if ( nFontLen > 31 )
459 nFontLen = 31;
460 for ( sal_Int32 n = 0; n < 32; n++ )
462 sal_Unicode nUniCode = 0;
463 if ( n < nFontLen )
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;
479 break;
481 case css::awt::FontFamily::SWISS :
482 lfPitchAndFamily |= FF_SWISS;
483 break;
485 case css::awt::FontFamily::MODERN :
486 lfPitchAndFamily |= FF_MODERN;
487 break;
489 case css::awt::FontFamily::SCRIPT:
490 lfPitchAndFamily |= FF_SCRIPT;
491 break;
493 case css::awt::FontFamily::DECORATIVE:
494 lfPitchAndFamily |= FF_DECORATIVE;
495 break;
497 default:
498 lfPitchAndFamily |= FAMILY_DONTKNOW;
499 break;
501 switch( pDesc->Pitch )
503 case css::awt::FontPitch::FIXED:
504 lfPitchAndFamily |= FIXED_PITCH;
505 break;
507 default:
508 lfPitchAndFamily |= DEFAULT_PITCH;
509 break;
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 );
531 if ( nOldPos )
533 mpStrm->Seek( nOldPos );
534 return true;
537 return false;
540 bool PropValue::GetPropertyValue(
541 css::uno::Any& rAny,
542 const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
543 const OUString& rString,
544 bool bTestPropertyAvailability )
546 bool bRetValue = true;
547 if ( bTestPropertyAvailability )
549 bRetValue = false;
552 css::uno::Reference< css::beans::XPropertySetInfo > aXPropSetInfo( rXPropSet->getPropertySetInfo() );
553 if ( aXPropSetInfo.is() )
554 bRetValue = aXPropSetInfo->hasPropertyByName( rString );
556 catch( css::uno::Exception& )
558 bRetValue = false;
561 if ( bRetValue )
565 rAny = rXPropSet->getPropertyValue( rString );
566 if ( !rAny.hasValue() )
567 bRetValue = false;
569 catch( css::uno::Exception& )
571 bRetValue = false;
574 return bRetValue;
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& )
592 return eRetValue;
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;
609 #ifdef UNX
610 css::uno::Reference< css::beans::XPropertySetInfo >
611 aXPropSetInfo( mXPropSet->getPropertySetInfo() );
612 if ( !aXPropSetInfo.is() )
613 return false;
614 #endif
617 mAny = mXPropSet->getPropertyValue( rString );
618 if ( !mAny.hasValue() )
619 bRetValue = false;
620 else if ( bGetPropertyState )
621 ePropState = mXPropState->getPropertyState( rString );
622 else
623 ePropState = css::beans::PropertyState_DIRECT_VALUE;
625 catch( css::uno::Exception& )
627 bRetValue = false;
629 return bRetValue;
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 )
655 double fN = 100.0;
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;
664 else
666 if ( nLineSpacing > 0 )
668 if ( !mbFontIndependentLineSpacing && pDesc )
669 nLineSpacing = static_cast<sal_Int16>( static_cast<double>(nLineSpacing) * pDesc->Scaling + 0.5 );
671 else
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;
675 else
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;
703 else
705 nPropertyFlags |= 1; // turn off bullet explicit
706 nBulletFlags = 0;
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;
736 css::uno::Any aAny;
737 if ( PropValue::GetPropertyValue( aAny, mXPagePropSet, "IsBackgroundDark", true ) )
738 aAny >>= bIsDark;
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 )
761 nAsianSettings |= 1;
762 if ( pPara->mbParagraphPunctation )
763 nAsianSettings |= 4;
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;
782 nPropertyFlags = 0;
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;
789 css::uno::Any aAny;
790 if ( PropValue::GetPropertyValue( aAny, mXPagePropSet, "IsBackgroundDark", true ) )
791 aAny >>= bIsDark;
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
806 css::uno::Any aAny;
807 css::drawing::FillStyle aFS( css::drawing::FillStyle_NONE );
808 if ( PropValue::GetPropertyValue( aAny, mXPropSet, "FillStyle" ) )
809 aAny >>= aFS;
810 switch( aFS )
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 );
819 break;
820 case css::drawing::FillStyle_SOLID :
822 if ( PropValue::GetPropertyValue( aAny, mXPropSet, "FillColor" ) )
823 nBackgroundColor = EscherEx::GetColor( *o3tl::doAccess<sal_uInt32>(aAny) );
825 break;
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;
832 switch( 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 );
841 break;
842 case css::drawing::FillStyle_SOLID :
844 if ( PropValue::GetPropertyValue( aAny, mXBackgroundPropSet, "FillColor" ) )
845 nBackgroundColor = EscherEx::GetColor( *o3tl::doAccess<sal_uInt32>(aAny) );
847 break;
848 default:
849 break;
852 break;
853 default:
854 break;
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 ) )
863 nCharAttr &=~ 0x200;
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) ) )
882 nCharAttr |= 0x200;
890 nCharColor |= 0xfe000000;
891 if ( nInstance == 4 ) // special handling for normal textobjects:
892 nPropertyFlags |= nCharAttr & 0x217; // not all attributes ar inherited
893 else
895 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Bold, nCharAttr ) )
896 nPropertyFlags |= 1;
897 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Italic, nCharAttr ) )
898 nPropertyFlags |= 2;
899 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Underline, nCharAttr ) )
900 nPropertyFlags |= 4;
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()
953 mnTextSize = 0;
954 mbFontIndependentLineSpacing = false;
955 mXText.set( mXShape, css::uno::UNO_QUERY );
957 if ( mXText.is() )
959 mnTextSize = mXText->getString().getLength();
960 css::uno::Any aAny;
961 if ( GetPropertyValue( aAny, mXPropSet, "FontIndependentLineSpacing", true ) )
962 aAny >>= mbFontIndependentLineSpacing;
964 return ( mnTextSize != 0 );
967 void PPTWriter::ImplFlipBoundingBox( EscherPropertyContainer& rPropOpt )
969 if ( mnAngle < 0 )
970 mnAngle = ( 36000 + mnAngle ) % 36000;
971 else
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 ) ) );
984 mnAngle *= 655;
985 mnAngle += 0x8000;
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 )
1005 return;
1007 if ( !rTextObj.ParagraphCount() )
1008 return;
1010 ParagraphObj* pPara = rTextObj.GetParagraph(0);
1011 if ( pPara->empty() )
1012 return;
1014 const PortionObj& rPortion = pPara->front();
1015 sal_Int16 nLineSpacing = pPara->mnLineSpacing;
1016 const FontCollectionEntry* pDesc = maFontCollection.GetById( rPortion.mnFont );
1017 if ( pDesc )
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;
1025 fCharHeight /= 100;
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 )
1043 mnTextSize = 0;
1044 if ( mbEmptyPresObj )
1045 return;
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
1052 if ( mnTextSize )
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 )
1080 case 1 :
1081 case 2 :
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
1088 break;
1089 case 3 :
1091 rOut.WriteUInt32( EPP_SlideNumberMCAtom << 16 ).WriteUInt32( 4 )
1092 .WriteUInt32( pFieldEntry->nFieldStartPos );
1094 break;
1095 case 4 :
1097 sal_uInt32 nPageIndex = 0;
1098 OUString aPageUrl;
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( "/", "\\" );
1109 aTarget = aFile;
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);
1123 aPageUrl += ",";
1124 aPageUrl += OUString::number(nPageIndex + 1);
1125 aPageUrl += ",Slide ";
1126 aPageUrl += 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 );
1132 else
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 );
1149 break;
1150 case 5 :
1152 rOut.WriteUInt32( EPP_GenericDateMCAtom << 16 ).WriteUInt32( 4 )
1153 .WriteUInt32( pFieldEntry->nFieldStartPos );
1155 break;
1156 case 6 :
1158 rOut.WriteUInt32( EPP_HeaderMCAtom << 16 ).WriteUInt32( 4 )
1159 .WriteUInt32( pFieldEntry->nFieldStartPos );
1161 break;
1162 case 7 :
1164 rOut.WriteUInt32( EPP_FooterMCAtom << 16 ).WriteUInt32( 4 )
1165 .WriteUInt32( pFieldEntry->nFieldStartPos );
1167 break;
1168 default:
1169 break;
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);
1206 nParaFlags >>= 16;
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;
1221 if ( nTabs )
1222 nDefaultTabs -= static_cast<sal_Int32>( ( ( pTabStop[ nTabs - 1 ].Position / 4.40972 ) + nTextOfs ) / nDefaultTabSize );
1223 if ( static_cast<sal_Int32>(nDefaultTabs) < 0 )
1224 nDefaultTabs = 0;
1226 sal_uInt32 nTabCount = nTabs + nDefaultTabs;
1227 sal_uInt32 i, nTextRulerAtomFlags = 0;
1229 if ( nTabCount )
1230 nTextRulerAtomFlags |= 4;
1231 if ( nParaFlags )
1232 nTextRulerAtomFlags |= ( ( nParaFlags << 3 ) | ( nParaFlags << 8 ) );
1234 if ( nTextRulerAtomFlags )
1236 SvStream* pRuleOut = &rOut;
1237 if ( pTextRule )
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 ( i = 0; i < nTabs; i++ )
1251 sal_uInt16 nPosition = static_cast<sal_uInt16>( ( pTabStop[ i ].Position / 4.40972 ) + nTextOfs );
1252 sal_uInt16 nType;
1253 switch ( pTabStop[ i ].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 :
1260 default: nType = 0;
1262 pRuleOut->WriteUInt16( nPosition )
1263 .WriteUInt16( nType );
1266 sal_uInt32 nWidth = 1;
1267 if ( nTabs )
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() )
1287 return;
1289 if ( !aTextObj.ParagraphCount() )
1290 return;
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 :
1318 nNumberingType = 0;
1319 break;
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;
1333 break;
1335 case SVX_NUM_BITMAP :
1336 nNumberingType = 0;
1337 break;
1338 default: break;
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).
1364 OUString aFile;
1367 Action Table: Action Value
1368 NoAction 0
1369 MacroAction 1
1370 RunProgramAction 2
1371 JumpAction 3
1372 HyperlinkAction 4
1373 OLEAction 5
1374 MediaAction 6
1375 CustomShowAction 7
1377 Jump Table: Jump Value
1378 NoJump 0
1379 NextSlide, 1
1380 PreviousSlide, 2
1381 FirstSlide, 3
1382 LastSlide, 4
1383 LastSlideViewed 5
1384 EndShow 6
1387 if ( bMediaClickAction )
1388 nAction = 6;
1389 else switch( eCa )
1391 case css::presentation::ClickAction_STOPPRESENTATION :
1392 nJump += 2;
1393 [[fallthrough]];
1394 case css::presentation::ClickAction_LASTPAGE :
1395 nJump++;
1396 [[fallthrough]];
1397 case css::presentation::ClickAction_FIRSTPAGE :
1398 nJump++;
1399 [[fallthrough]];
1400 case css::presentation::ClickAction_PREVPAGE :
1401 nJump++;
1402 [[fallthrough]];
1403 case css::presentation::ClickAction_NEXTPAGE :
1405 nJump++;
1406 nAction = 3;
1408 break;
1409 case css::presentation::ClickAction_SOUND :
1411 if ( ImplGetPropertyValue( "Bookmark" ) )
1412 nSoundRef = maSoundCollection.GetId( *o3tl::doAccess<OUString>(mAny) );
1414 break;
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();
1423 nAction = 2;
1427 break;
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
1440 nAction = 4;
1441 nHyperLinkType = 7;
1443 OUString aHyperString = OUString::number(256 + nIndex);
1444 aHyperString += ",";
1445 aHyperString += OUString::number(nIndex + 1);
1446 aHyperString += ",Slide ";
1447 aHyperString += OUString::number(nIndex + 1);
1448 nHyperLinkID = ImplInsertBookmarkURL( aHyperString, 1 | ( nIndex << 8 ) | ( 1U << 31 ), aBookmark, "", "", aHyperString );
1450 nIndex++;
1454 break;
1456 case css::presentation::ClickAction_DOCUMENT :
1458 if ( ImplGetPropertyValue( "Bookmark" ) )
1460 OUString aBookmark( *o3tl::doAccess<OUString>(mAny) );
1461 if ( !aBookmark.isEmpty() )
1463 nAction = 4;
1464 nHyperLinkType = 8;
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, "", "" );
1474 break;
1476 case css::presentation::ClickAction_INVISIBLE :
1477 case css::presentation::ClickAction_VERB :
1478 case css::presentation::ClickAction_VANISH :
1479 case css::presentation::ClickAction_MACRO :
1480 default :
1481 break;
1484 sal_uInt32 nContainerSize = 24;
1485 if ( nAction == 2 )
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,
1513 bool& bIsSound )
1515 css::uno::Any aAny;
1516 if ( GetPropertyValue( aAny, rPropSet, "Effect" ) )
1517 aAny >>= eEffect;
1518 else
1519 eEffect = css::presentation::AnimationEffect_NONE;
1521 if ( GetPropertyValue( aAny, rPropSet, "TextEffect" ) )
1522 aAny >>= eTextEffect;
1523 else
1524 eTextEffect = css::presentation::AnimationEffect_NONE;
1525 if ( GetPropertyValue( aAny, rPropSet, "SoundOn" ) )
1526 aAny >>= bIsSound;
1527 else
1528 bIsSound = false;
1530 bool bHasEffect = ( ( eEffect != css::presentation::AnimationEffect_NONE )
1531 || ( eTextEffect != css::presentation::AnimationEffect_NONE )
1532 || bIsSound );
1533 return bHasEffect;
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 );
1548 mnTxId += 0x60;
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 );
1564 mnTxId += 0x60;
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
1587 else
1588 bRet = false;
1589 return bRet;
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 );
1604 if ( bFill )
1605 rPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1606 if ( ImplGetText() )
1608 mnTxId += 0x60;
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
1631 nOlePictureId = 0;
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() )
1643 nShapeCount++;
1645 nPer = ( 5 * nShapeCount ) / nShapes;
1646 if ( nPer != nLastPer )
1648 nLastPer = nPer;
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 ) )
1663 bool bIsSound;
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" ) )
1671 mAny >>= eCa;
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 );
1684 if ( bGroup )
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 );
1700 else
1702 bool bIsFontwork = false;
1703 bool bIsHatching = false;
1704 css::uno::Any aAny;
1705 css::drawing::FillStyle eFS;
1706 if ( GetPropertyValue( aAny, mXPropSet, "IsFontwork", true ) )
1707 aAny >>= bIsFontwork;
1708 if ( GetPropertyValue( aAny, mXPropSet, "FillStyle", true ) )
1710 aAny >>= eFS;
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;
1727 mnTextSize = 0;
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,
1740 aSolverContainer );
1741 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "MetaFile", false ) )
1743 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
1744 SdrObject* pObj = GetSdrObjectFromXShape( mXShape );
1745 if ( pObj )
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 ) );
1751 mnAngle = 0;
1755 else
1757 ImplCreateShape( eShapeType,
1758 nMirrorFlags | ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1759 aSolverContainer );
1760 aPropOpt.CreateCustomShapeProperties( eShapeType, mXShape );
1761 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape);
1762 if ( ImplGetText() )
1764 if ( !aPropOpt.IsFontWork() )
1766 mnTxId += 0x60;
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" ) )
1778 mAny >>= nRadius;
1779 nRadius = MapSize( css::awt::Size( nRadius, 0 ) ).Width;
1781 if ( nRadius )
1783 ImplCreateShape( ESCHER_ShpInst_RoundRectangle,
1784 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1785 aSolverContainer );
1786 sal_Int32 nLength = maRect.GetWidth();
1787 if ( nLength > maRect.GetHeight() )
1788 nLength = maRect.GetHeight();
1789 nLength >>= 1;
1790 if ( nRadius >= nLength )
1791 nRadius = 0x2a30; // 0x2a30 is PPTs maximum radius
1792 else
1793 nRadius = ( 0x2a30 * nRadius ) / nLength;
1794 aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius );
1796 else
1798 ImplCreateShape( ESCHER_ShpInst_Rectangle,
1799 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1800 aSolverContainer );
1802 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1803 if ( ImplGetText() )
1805 mnTxId += 0x60;
1806 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
1809 else if ( mType == "drawing.Ellipse" )
1811 css::drawing::CircleKind eCircleKind( css::drawing::CircleKind_FULL );
1812 PolyStyle ePolyKind = PolyStyle::Chord;
1813 if ( ImplGetPropertyValue( "CircleKind" ) )
1815 mAny >>= eCircleKind;
1816 switch ( eCircleKind )
1818 case css::drawing::CircleKind_SECTION :
1820 ePolyKind = PolyStyle::Pie;
1822 break;
1823 case css::drawing::CircleKind_ARC :
1825 ePolyKind = PolyStyle::Arc;
1827 break;
1829 case css::drawing::CircleKind_CUT :
1831 ePolyKind = PolyStyle::Chord;
1833 break;
1835 default:
1836 eCircleKind = css::drawing::CircleKind_FULL;
1839 if ( eCircleKind == css::drawing::CircleKind_FULL )
1841 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1842 ImplCreateShape( ESCHER_ShpInst_Ellipse,
1843 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1844 aSolverContainer );
1845 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1846 if ( ImplGetText() )
1848 mnTxId += 0x60;
1849 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
1852 else
1854 sal_Int32 nStartAngle, nEndAngle;
1855 if ( !ImplGetPropertyValue( "CircleStartAngle" ) )
1856 continue;
1857 nStartAngle = *o3tl::doAccess<sal_Int32>(mAny);
1858 if( !ImplGetPropertyValue( "CircleEndAngle" ) )
1859 continue;
1860 nEndAngle = *o3tl::doAccess<sal_Int32>(mAny);
1861 css::awt::Point aPoint( mXShape->getPosition() );
1862 css::awt::Size aSize( mXShape->getSize() );
1863 css::awt::Point aStart, aEnd, aCenter;
1864 ::tools::Rectangle aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
1865 aStart.X = static_cast<sal_Int32>( cos( nStartAngle * F_PI18000 ) * 100.0 );
1866 aStart.Y = - static_cast<sal_Int32>( sin( nStartAngle * F_PI18000 ) * 100.0 );
1867 aEnd.X = static_cast<sal_Int32>( cos( nEndAngle * F_PI18000 ) * 100.0 );
1868 aEnd.Y = - static_cast<sal_Int32>( sin( nEndAngle * F_PI18000 ) * 100.0 ) ;
1869 aCenter.X = aPoint.X + ( aSize.Width / 2 );
1870 aCenter.Y = aPoint.Y + ( aSize.Height / 2 );
1871 aStart.X += aCenter.X;
1872 aStart.Y += aCenter.Y;
1873 aEnd.X += aCenter.X;
1874 aEnd.Y += aCenter.Y;
1875 tools::Polygon aPolygon( aRect, Point( aStart.X, aStart.Y ), Point( aEnd.X, aEnd.Y ), ePolyKind );
1876 bool bNeedText = true;
1877 if ( mnAngle )
1879 aPolygon.Rotate( aRect.TopLeft(), static_cast<sal_uInt16>( mnAngle / 10 ) );
1880 if ( ImplGetText() )
1882 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
1883 // mpPptEscherEx->EnterGroup( 0,0 );
1884 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
1885 bNeedText = false;
1886 bAdditionalText = true;
1887 mnTextSize = 0;
1889 mnAngle = 0;
1891 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1892 ImplCreateShape( ESCHER_ShpInst_NotPrimitive,
1893 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1894 aSolverContainer );
1895 css::awt::Rectangle aNewRect;
1896 switch ( ePolyKind )
1898 case PolyStyle::Pie :
1899 case PolyStyle::Chord :
1901 if ( aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect, &aPolygon ) )
1902 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1904 break;
1906 case PolyStyle::Arc :
1908 if ( aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect, &aPolygon ) )
1909 aPropOpt.CreateLineProperties( mXPropSet, false );
1911 break;
1913 maRect = MapRectangle( aNewRect );
1914 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
1915 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
1916 if ( bNeedText && ImplGetText() )
1918 mnTxId += 0x60;
1919 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
1923 else if ( mType == "drawing.Control" )
1925 css::uno::Reference< css::drawing::XControlShape > aXControlShape( mXShape, css::uno::UNO_QUERY );
1926 if ( !aXControlShape.is() )
1927 continue;
1928 css::uno::Reference< css::awt::XControlModel > aXControlModel( aXControlShape->getControl() );
1929 if ( !aXControlModel.is() )
1930 continue;
1932 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
1935 // try to get the aspect when available
1936 css::uno::Reference< css::beans::XPropertySet > xShapeProps( mXShape, css::uno::UNO_QUERY_THROW );
1937 xShapeProps->getPropertyValue("Aspect") >>= nAspect;
1939 catch( css::uno::Exception& )
1942 mpExEmbed->WriteUInt32( 0xf | ( EPP_ExControl << 16 ) )
1943 .WriteUInt32( 0 ); // Size of this container
1945 sal_uInt32 nSize, nOldPos = mpExEmbed->Tell();
1947 sal_uInt32 nPageId = nPageNumber;
1948 if ( ePageType == MASTER )
1949 nPageId |= 0x80000000;
1950 else
1951 nPageId += 0x100;
1952 mpExEmbed->WriteUInt32( EPP_ExControlAtom << 16 )
1953 .WriteUInt32( 4 )
1954 .WriteUInt32( nPageId );
1955 std::unique_ptr<PPTExOleObjEntry> pEntry( new PPTExOleObjEntry( OCX_CONTROL, mpExEmbed->Tell() ) );
1956 pEntry->xControlModel = aXControlModel;
1957 pEntry->xShape = mXShape;
1958 maExOleObj.push_back( std::move(pEntry) );
1960 mnExEmbed++;
1962 mpExEmbed->WriteUInt32( 1 | ( EPP_ExOleObjAtom << 16 ) )
1963 .WriteUInt32( 24 )
1964 .WriteUInt32( nAspect )
1965 .WriteUInt32( 2 )
1966 .WriteUInt32( mnExEmbed )
1967 .WriteUInt32( 0 )
1968 .WriteUInt32( 4 ) // index to the persist table
1969 .WriteUInt32( 0x0012de00 );
1971 css::awt::Size aSize;
1972 OUString aControlName;
1973 tools::SvRef<SotStorage> xTemp( new SotStorage( new SvMemoryStream(), true ) );
1974 if ( oox::ole::MSConvertOCXControls::WriteOCXStream( mXModel, xTemp, aXControlModel, aSize, aControlName ) )
1976 OUString aUserName( xTemp->GetUserName() );
1977 OUString aOleIdentifier;
1978 if ( !aUserName.isEmpty() )
1980 tools::SvRef<SotStorageStream> xCompObj = xTemp->OpenSotStream(
1981 "\1CompObj",
1982 StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL );
1983 sal_uInt32 const nStreamLen = xCompObj->remainingSize();
1984 sal_Int16 nVersion, nByteOrder;
1985 sal_Int32 nWinVersion, nVal, nStringLen;
1986 xCompObj->ReadInt16( nVersion )
1987 .ReadInt16( nByteOrder )
1988 .ReadInt32( nWinVersion )
1989 .ReadInt32( nVal );
1990 xCompObj->SeekRel( 16 ); // skipping clsid
1991 xCompObj->ReadInt32( nStringLen );
1992 if ( ( xCompObj->Tell() + nStringLen ) < nStreamLen )
1994 xCompObj->SeekRel( nStringLen ); // now skipping the UserName;
1995 xCompObj->ReadInt32( nStringLen );
1996 if ( ( xCompObj->Tell() + nStringLen ) < nStreamLen )
1998 xCompObj->SeekRel( nStringLen ); // now skipping the clipboard formatname
1999 xCompObj->ReadInt32( nStringLen );
2000 if ( ( nStringLen > 1 ) && ( ( xCompObj->Tell() + nStringLen ) < nStreamLen ) )
2001 { // i think that the OleIdentifier will follow
2002 OString aTemp = read_uInt8s_ToOString(*xCompObj, nStringLen - 1);
2003 aOleIdentifier = OStringToOUString(aTemp, RTL_TEXTENCODING_MS_1252);
2009 PPTWriter::WriteCString( *mpExEmbed, aControlName, 1 );
2010 PPTWriter::WriteCString( *mpExEmbed, aOleIdentifier, 2 );
2011 PPTWriter::WriteCString( *mpExEmbed, aUserName, 3 );
2013 nSize = mpExEmbed->Tell() - nOldPos;
2014 mpExEmbed->Seek( nOldPos - 4 );
2015 mpExEmbed->WriteUInt32( nSize );
2016 mpExEmbed->Seek( STREAM_SEEK_TO_END );
2017 nOlePictureId = mnExEmbed;
2019 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2020 ShapeFlag const nSpFlags = ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor | ShapeFlag::OLEShape;
2021 ImplCreateShape( ESCHER_ShpInst_HostControl, nSpFlags, aSolverContainer );
2022 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "MetaFile", false ) )
2023 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2024 //export form control graphic
2025 else if ( aPropOpt.CreateBlipPropertiesforOLEControl(mXPropSet,mXShape))
2026 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2027 aPropOpt.AddOpt( ESCHER_Prop_pictureId, mnExEmbed );
2028 aPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
2030 if ( !aControlName.isEmpty() )
2032 aPropOpt.AddOpt(ESCHER_Prop_wzName, aControlName);
2035 else if ( mType == "drawing.Connector" )
2037 sal_uInt16 nSpType;
2038 ShapeFlag nSpFlags;
2039 css::awt::Rectangle aNewRect;
2040 if ( !aPropOpt.CreateConnectorProperties( mXShape, aSolverContainer, aNewRect, nSpType, nSpFlags ) )
2041 continue;
2043 maRect = MapRectangle( aNewRect );
2044 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2045 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2047 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2048 ImplCreateShape( nSpType, nSpFlags, aSolverContainer );
2050 // #119459# for connector shape, the start point and end point is fixed, and should not be rotated.
2051 mnAngle = 0;
2053 else if ( mType == "drawing.Measure" )
2055 continue;
2057 else if ( mType == "drawing.Line" )
2059 css::awt::Rectangle aNewRect;
2060 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_LINE, false, aNewRect );
2061 maRect = MapRectangle( aNewRect );
2062 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2063 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2064 if ( ImplGetText() )
2066 aTextRefPoint = css::awt::Point( maRect.Left(), maRect.Top() );
2067 mnTextSize = 0;
2068 bAdditionalText = true;
2069 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2070 // mpPptEscherEx->EnterGroup( &maRect,0 );
2072 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2073 ShapeFlag nFlags = ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty;
2075 if ( maRect.Top() > maRect.Bottom() )
2076 nFlags |= ShapeFlag::FlipV;
2077 if ( maRect.Left() > maRect.Right() )
2078 nFlags |= ShapeFlag::FlipH;
2080 ImplCreateShape( ESCHER_ShpInst_Line, nFlags, aSolverContainer );
2081 aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
2082 aPropOpt.CreateLineProperties( mXPropSet, false );
2083 mnAngle = 0;
2085 else if ( bPolyPolygon )
2087 if ( ImplGetText() )
2089 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2090 // mpPptEscherEx->EnterGroup( 0,0 );
2091 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2092 bAdditionalText = true;
2093 mnTextSize = 0;
2095 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2096 ImplCreateShape( ESCHER_ShpInst_NotPrimitive,
2097 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2098 aSolverContainer );
2099 css::awt::Rectangle aNewRect;
2100 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect );
2101 maRect = MapRectangle( aNewRect );
2102 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2103 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2104 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2105 mnAngle = 0;
2107 else if ( bPolyLine )
2109 if ( ImplGetText() )
2111 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2112 // mpPptEscherEx->EnterGroup( 0,0 );
2113 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2114 bAdditionalText = true;
2115 mnTextSize = 0;
2117 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2118 ImplCreateShape( ESCHER_ShpInst_NotPrimitive,
2119 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2120 aSolverContainer );
2121 css::awt::Rectangle aNewRect;
2122 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect );
2123 maRect = MapRectangle( aNewRect );
2124 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2125 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2126 aPropOpt.CreateLineProperties( mXPropSet, false );
2127 mnAngle = 0;
2129 else if ( bOpenBezier )
2131 if ( ImplGetText() )
2133 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2134 // mpPptEscherEx->EnterGroup( 0,0 );
2135 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2136 bAdditionalText = true;
2137 mnTextSize = 0;
2139 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2140 ImplCreateShape( ESCHER_ShpInst_NotPrimitive,
2141 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2142 aSolverContainer );
2143 css::awt::Rectangle aNewRect;
2144 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, true, aNewRect );
2145 maRect = MapRectangle( aNewRect );
2146 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2147 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2148 aPropOpt.CreateLineProperties( mXPropSet, false );
2149 mnAngle = 0;
2151 else if ( bClosedBezier )
2153 if ( ImplGetText() )
2155 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2156 // mpPptEscherEx->EnterGroup( 0,0 );
2157 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2158 bAdditionalText = true;
2159 mnTextSize = 0;
2161 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2162 ImplCreateShape( ESCHER_ShpInst_NotPrimitive,
2163 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2164 aSolverContainer );
2165 css::awt::Rectangle aNewRect;
2166 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, true, aNewRect );
2167 maRect = MapRectangle( aNewRect );
2168 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2169 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2170 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2171 mnAngle = 0;
2173 else if ( ( mType == "drawing.GraphicObject" ) || ( mType == "presentation.GraphicObject" ) )
2175 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2177 // a GraphicObject can also be a ClickMe element
2178 if ( mbEmptyPresObj && ( ePageType == NORMAL ) )
2180 nPlaceHolderAtom = rLayout.nUsedObjectPlaceHolder;
2181 ImplCreateShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster, aSolverContainer );
2182 mnTxId += 0x60;
2183 aPropOpt.AddOpt( ESCHER_Prop_lTxid, mnTxId );
2184 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
2185 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
2186 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
2188 else
2190 mXText.set( mXShape, css::uno::UNO_QUERY );
2192 if ( mXText.is() )
2193 mnTextSize = mXText->getString().getLength();
2195 if ( mnTextSize ) // graphic object or area fill
2197 /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
2198 have to create a simple Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
2200 ImplCreateShape( ESCHER_ShpInst_Rectangle,
2201 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2202 aSolverContainer );
2203 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "Graphic", true, true, false ) )
2205 aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
2206 aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
2207 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
2208 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 );
2209 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
2210 if ( ImplGetText() )
2212 mnTxId += 0x60;
2213 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
2217 else
2219 ImplCreateShape( ESCHER_ShpInst_PictureFrame,
2220 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2221 aSolverContainer );
2223 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "Graphic", false, true ) )
2225 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2230 else if ( ( mType == "drawing.Text" ) || ( mType == "presentation.Notes" ) )
2232 if ( ( ePageType == NOTICE ) && mbPresObj )
2234 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Notes, EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE ) )
2235 continue;
2236 else
2237 nPlaceHolderAtom = EPP_PLACEHOLDER_NOTESBODY;
2239 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2241 else if ( mType == "presentation.TitleText" )
2243 if ( mbPresObj )
2245 if ( ( ePageType == NOTICE ) && mbEmptyPresObj )
2247 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2248 nPlaceHolderAtom = EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE;
2249 ImplCreateShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveAnchor, aSolverContainer );
2250 aPropOpt.CreateLineProperties( mXPropSet, false );
2251 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
2253 else if ( rLayout.bTitlePossible && bIsTitlePossible )
2255 bIsTitlePossible = false;
2257 ImplGetText();
2258 TextObjBinary aTextObj( mXText, EPP_TEXTTYPE_Title, maFontCollection, static_cast<PPTExBulletProvider&>(*this) );
2259 if ( ePageType == MASTER )
2261 if ( mnTextSize )
2263 OUString aUString( mXText->getString() );
2264 sal_uInt16 nChar;
2266 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2267 mnShapeMasterTitle = mpPptEscherEx->GenerateShapeId();
2268 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle,
2269 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2270 mnShapeMasterTitle );
2271 EscherPropertyContainer aPropertyOptions;
2272 aPropertyOptions.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x50001 );
2273 mnTxId += 0x60;
2274 aPropertyOptions.AddOpt( ESCHER_Prop_lTxid, mnTxId );
2275 aPropertyOptions.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
2276 aPropertyOptions.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110001 );
2277 aPropertyOptions.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
2278 aPropertyOptions.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
2279 aPropertyOptions.CreateFillProperties( mXPropSet, true, mXShape );
2280 sal_uInt32 nLineFlags = 0x90001;
2281 if ( aPropertyOptions.GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags ) )
2282 nLineFlags |= 0x10001; // draw dashed line if no line
2283 aPropertyOptions.AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
2284 mnTxId += 0x60;
2285 aPropertyOptions.CreateTextProperties( mXPropSet, mnTxId );
2286 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt );
2287 aPropertyOptions.Commit( *mpStrm );
2288 mpPptEscherEx->AddAtom( 8, ESCHER_ClientAnchor );
2289 mpStrm->WriteInt16( maRect.Top() ).WriteInt16( maRect.Left() ).WriteInt16( maRect.Right() ).WriteInt16( maRect.Bottom() ); // top, left, right, bottom ????
2290 mpPptEscherEx->OpenContainer( ESCHER_ClientData );
2291 mpPptEscherEx->AddAtom( 8, EPP_OEPlaceholderAtom );
2292 mpStrm->WriteUInt32( 0 ) // PlacementID
2293 .WriteUChar( EPP_PLACEHOLDER_MASTERTITLE ) // PlaceHolderID
2294 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2295 .WriteUInt16( 0 ); // padword
2296 mpPptEscherEx->CloseContainer(); // ESCHER_ClientData
2297 mpPptEscherEx->OpenContainer( ESCHER_ClientTextbox );
2298 mpPptEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
2299 mpStrm->WriteUInt32( EPP_TEXTTYPE_Title );
2300 mpPptEscherEx->AddAtom( mnTextSize << 1, EPP_TextCharsAtom );
2301 const sal_Unicode* pString = aUString.getStr();
2302 for ( sal_uInt32 i = 0; i < mnTextSize; i++ )
2304 nChar = pString[ i ]; // 0xa -> 0xb soft newline
2305 if ( nChar == 0xa )
2306 nChar++; // 0xd -> 0xd hard newline
2307 mpStrm->WriteUInt16( nChar );
2309 mpPptEscherEx->AddAtom( 6, EPP_BaseTextPropAtom );
2310 mpStrm->WriteUInt32( mnTextSize + 1 ).WriteUInt16( 0 );
2311 mpPptEscherEx->AddAtom( 10, EPP_TextSpecInfoAtom );
2312 mpStrm->WriteUInt32( mnTextSize + 1 ).WriteUInt32( 1 ).WriteUInt16( 0 );
2313 mpPptEscherEx->CloseContainer(); // ESCHER_ClientTextBox
2314 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2316 continue;
2318 else
2320 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2321 mnTextStyle = EPP_TEXTSTYLE_TITLE;
2322 nPlaceHolderAtom = rLayout.nTypeOfTitle;
2323 ImplCreateShape( ESCHER_ShpInst_Rectangle,
2324 ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster,
2325 aSolverContainer );
2326 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterTitle );
2327 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2328 mnTxId += 0x60;
2329 aPropOpt.CreateTextProperties( mXPropSet, mnTxId );
2330 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt );
2331 if ( mbEmptyPresObj )
2333 sal_uInt32 nNoLineDrawDash = 0;
2334 aPropOpt.GetOpt( ESCHER_Prop_fNoLineDrawDash, nNoLineDrawDash );
2335 nNoLineDrawDash |= 0x10001;
2336 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, nNoLineDrawDash );
2340 else
2341 mbPresObj = false;
2343 if ( !mbPresObj )
2345 mType = "drawing.Text";
2346 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2349 else if ( ( mType == "presentation.Outliner" ) || ( mType == "presentation.Subtitle" ) )
2351 if ( mbPresObj )
2353 nOutlinerCount++;
2354 if ( (rLayout.bOutlinerPossible && ( nOutlinerCount == 1 )) ||
2355 (( rLayout.bSecOutlinerPossible && ( nOutlinerCount == 2 ) ) && ( nPrevTextStyle == EPP_TEXTSTYLE_BODY ))
2358 ImplGetText();
2359 TextObjBinary aTextObj( mXText, EPP_TEXTTYPE_Body, maFontCollection, static_cast<PPTExBulletProvider&>(*this) );
2360 if ( ePageType == MASTER )
2362 nPrevTextStyle = EPP_TEXTSTYLE_TITLE;
2363 if ( mnTextSize )
2365 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2366 mnShapeMasterBody = mpPptEscherEx->GenerateShapeId();
2367 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle,
2368 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2369 mnShapeMasterBody );
2370 EscherPropertyContainer aPropOpt2;
2371 aPropOpt2.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x50001 );
2372 mnTxId += 0x60;
2373 aPropOpt2.AddOpt( ESCHER_Prop_lTxid, mnTxId );
2374 aPropOpt2.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110001 );
2375 aPropOpt2.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
2376 aPropOpt2.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90001 );
2377 aPropOpt2.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
2378 aPropOpt2.CreateFillProperties( mXPropSet, true, mXShape );
2379 sal_uInt32 nLineFlags = 0x90001;
2380 if ( aPropOpt2.GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags ) )
2381 nLineFlags |= 0x10001; // draw dashed line if no line
2382 aPropOpt2.AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
2383 mnTxId += 0x60;
2384 aPropOpt2.CreateTextProperties( mXPropSet, mnTxId );
2385 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt2 );
2386 aPropOpt2.Commit( *mpStrm );
2387 mpPptEscherEx->AddAtom( 8, ESCHER_ClientAnchor );
2388 mpStrm->WriteInt16( maRect.Top() ).WriteInt16( maRect.Left() ).WriteInt16( maRect.Right() ).WriteInt16( maRect.Bottom() ); // top, left, right, bottom ????
2389 mpPptEscherEx->OpenContainer( ESCHER_ClientData );
2390 mpPptEscherEx->AddAtom( 8, EPP_OEPlaceholderAtom );
2391 sal_uInt8 PlaceHolderID = ( mType == "presentation.Subtitle") ? EPP_PLACEHOLDER_MASTERSUBTITLE:EPP_PLACEHOLDER_MASTERBODY;
2392 mpStrm->WriteUInt32( 1 ) // PlacementID
2393 .WriteUChar( PlaceHolderID )/*(sal_uInt8)EPP_PLACEHOLDER_MASTERBODY */ // PlaceHolderID
2394 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2395 .WriteUInt16( 0 ); // padword
2396 mpPptEscherEx->CloseContainer(); // ESCHER_ClientData
2397 mpPptEscherEx->OpenContainer( ESCHER_ClientTextbox ); // printf
2398 mpPptEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
2399 if ( mType == "presentation.Subtitle")
2400 mpStrm->WriteUInt32( EPP_TEXTTYPE_CenterBody );
2401 else
2402 mpStrm->WriteUInt32( EPP_TEXTTYPE_Body );
2403 mnTextSize = aTextObj.Count();
2404 aTextObj.Write( mpStrm.get() );
2405 mpPptEscherEx->BeginAtom();
2406 for ( sal_uInt32 i = 0; i < aTextObj.ParagraphCount() ; ++i )
2408 ParagraphObj* pPara = aTextObj.GetParagraph(i);
2409 mpStrm->WriteUInt32( pPara->CharacterCount() )
2410 .WriteUInt16( pPara->nDepth );
2412 mpPptEscherEx->EndAtom( EPP_BaseTextPropAtom );
2413 mpPptEscherEx->AddAtom( 10, EPP_TextSpecInfoAtom );
2414 mpStrm->WriteUInt32( mnTextSize ).WriteUInt32( 1 ).WriteUInt16( 0 );
2416 mpPptEscherEx->CloseContainer(); // ESCHER_ClientTextBox
2417 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2419 continue;
2421 else
2423 mnTextStyle = EPP_TEXTSTYLE_BODY;
2424 nPlaceHolderAtom = rLayout.nTypeOfOutliner;
2425 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2426 ImplCreateShape( ESCHER_ShpInst_Rectangle,
2427 ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster,
2428 aSolverContainer );
2429 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
2430 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2431 mnTxId += 0x60;
2432 aPropOpt.CreateTextProperties( mXPropSet, mnTxId );
2433 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt );
2434 if ( mbEmptyPresObj )
2436 sal_uInt32 nNoLineDrawDash = 0;
2437 aPropOpt.GetOpt( ESCHER_Prop_fNoLineDrawDash, nNoLineDrawDash );
2438 nNoLineDrawDash |= 0x10001;
2439 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, nNoLineDrawDash );
2443 else
2444 mbPresObj = false;
2446 if ( !mbPresObj )
2448 if (ePageType == MASTER )
2450 SdrObject* pObj = GetSdrObjectFromXShape( mXShape );
2451 if (pObj && pObj->IsNotVisibleAsMaster())
2452 continue;
2455 mType = "drawing.Text";
2456 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2459 else if ( ( mType == "drawing.Page" ) || ( mType == "presentation.Page" ) )
2461 if ( ( ePageType == NOTICE ) && mbPresObj )
2463 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Notes, EPP_PLACEHOLDER_MASTERNOTESSLIDEIMAGE ) )
2464 continue;
2465 else
2466 nPlaceHolderAtom = EPP_PLACEHOLDER_NOTESSLIDEIMAGE;
2468 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2470 else if ( mType == "drawing.Frame" )
2472 continue;
2474 else if ( ( mType == "drawing.OLE2" ) || ( mType == "presentation.OLE2" )
2475 || ( mType == "presentation.Chart" ) || ( mType == "presentation.Calc" )
2476 || ( mType == "presentation.OrgChart" ) )
2478 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2479 if ( mbEmptyPresObj && ( ePageType == NORMAL ) )
2481 nPlaceHolderAtom = rLayout.nUsedObjectPlaceHolder;
2482 ImplCreateShape( ESCHER_ShpInst_Rectangle,
2483 ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster,
2484 aSolverContainer );
2485 mnTxId += 0x60;
2486 aPropOpt.AddOpt( ESCHER_Prop_lTxid, mnTxId );
2487 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
2488 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
2489 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
2491 else
2493 mpExEmbed->WriteUInt32( 0xf | ( EPP_ExEmbed << 16 ) )
2494 .WriteUInt32( 0 ); // Size of this container
2496 sal_uInt32 nSize, nOldPos = mpExEmbed->Tell();
2498 mpExEmbed->WriteUInt32( EPP_ExEmbedAtom << 16 )
2499 .WriteUInt32( 8 )
2500 .WriteUInt32( 0 ) // follow colorscheme : 0->do not follow
2501 // 1->follow colorscheme
2502 // 2->follow text and background scheme
2503 .WriteUChar( 1 ) // (bool)set if embedded server can not be locked
2504 .WriteUChar( 0 ) // (bool)do not need to send dimension
2505 .WriteUChar( 0 ) // (bool)is object a world table
2506 .WriteUChar( 0 ); // pad byte
2508 std::unique_ptr<PPTExOleObjEntry> pE( new PPTExOleObjEntry( NORMAL_OLE_OBJECT, mpExEmbed->Tell() ) );
2509 pE->xShape = mXShape;
2510 maExOleObj.push_back( std::move(pE) );
2512 mnExEmbed++;
2514 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
2517 // try to get the aspect when available
2518 css::uno::Reference< css::beans::XPropertySet > xShapeProps( mXShape, css::uno::UNO_QUERY_THROW );
2519 xShapeProps->getPropertyValue("Aspect") >>= nAspect;
2521 catch( css::uno::Exception& )
2524 mpExEmbed->WriteUInt32( 1 | ( EPP_ExOleObjAtom << 16 ) )
2525 .WriteUInt32( 24 )
2526 .WriteUInt32( nAspect ) // Aspect
2527 .WriteUInt32( 0 )
2528 .WriteUInt32( mnExEmbed ) // index to the persist table
2529 .WriteUInt32( 0 ) // subtype
2530 .WriteUInt32( 0 )
2531 .WriteUInt32( 0x0012b600 );
2533 nSize = mpExEmbed->Tell() - nOldPos;
2534 mpExEmbed->Seek( nOldPos - 4 );
2535 mpExEmbed->WriteUInt32( nSize );
2536 mpExEmbed->Seek( STREAM_SEEK_TO_END );
2537 nOlePictureId = mnExEmbed;
2539 ShapeFlag nSpFlags = ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty;
2540 if ( nOlePictureId )
2541 nSpFlags |= ShapeFlag::OLEShape;
2542 ImplCreateShape( ESCHER_ShpInst_PictureFrame, nSpFlags, aSolverContainer );
2543 if ( aPropOpt.CreateOLEGraphicProperties( mXShape ) )
2544 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2545 if ( nOlePictureId )
2546 aPropOpt.AddOpt( ESCHER_Prop_pictureId, nOlePictureId );
2549 else if ( mType == "presentation.Header" )
2551 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other, EPP_PLACEHOLDER_MASTERHEADER ) )
2552 continue;
2553 else
2555 mbPresObj = false;
2556 mType = "drawing.Text";
2557 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2560 else if ( mType == "presentation.Footer" )
2562 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other, EPP_PLACEHOLDER_MASTERFOOTER ) )
2563 continue;
2564 else
2566 mbPresObj = false;
2567 mType = "drawing.Text";
2568 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2571 else if ( mType == "presentation.DateTime" )
2573 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other, EPP_PLACEHOLDER_MASTERDATE ) )
2574 continue;
2575 else
2577 mbPresObj = false;
2578 mType = "drawing.Text";
2579 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2582 else if ( mType == "presentation.SlideNumber" )
2584 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other, EPP_PLACEHOLDER_MASTERSLIDENUMBER ) )
2585 continue;
2586 else
2588 mbPresObj = false;
2589 mType = "drawing.Text";
2590 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2593 else if ( (mType.getLength() > 9) && (mType[8] == '3') && (mType[9] == 'D') ) // drawing.3D
2595 // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
2596 if ( !ImplGetPropertyValue( "Bitmap" ) )
2597 continue;
2599 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2600 ImplCreateShape( ESCHER_ShpInst_PictureFrame,
2601 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2602 aSolverContainer );
2604 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "Bitmap", false ) )
2605 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2607 else if ( mType == "drawing.Media" )
2609 mnAngle = 0;
2610 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2611 ImplCreateShape( ESCHER_ShpInst_PictureFrame,
2612 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2613 aSolverContainer );
2614 if ( aPropOpt.CreateMediaGraphicProperties( mXShape ) )
2615 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2616 css::uno::Any aAny;
2617 if ( PropValue::GetPropertyValue( aAny, mXPropSet, "MediaURL", true ) )
2619 OUString aMediaURL;
2620 if ( (aAny >>= aMediaURL ) && !aMediaURL.isEmpty() )
2622 // SJ: creating the Media RefObj
2623 sal_uInt32 nRefId = ++mnExEmbed;
2625 mpExEmbed->WriteUInt16( 0xf )
2626 .WriteUInt16( EPP_ExMCIMovie ) // PPT_PST_ExAviMovie
2627 .WriteUInt32( 0 );
2628 sal_uInt32 nSize, nStart = mpExEmbed->Tell();
2629 mpExEmbed->WriteUInt16( 0 )
2630 .WriteUInt16( EPP_ExObjRefAtom )
2631 .WriteUInt32( 4 )
2632 .WriteUInt32( nRefId );
2633 mpExEmbed->WriteUInt16( 0xf )
2634 .WriteUInt16( EPP_ExVideo )
2635 .WriteUInt32( 0 );
2637 mpExEmbed->WriteUInt16( 0 )
2638 .WriteUInt16( EPP_ExMediaAtom )
2639 .WriteUInt32( 8 )
2640 .WriteUInt32( nRefId )
2641 .WriteUInt16( 0 )
2642 .WriteUInt16( 0x435 );
2644 sal_uInt16 i, nStringLen = static_cast<sal_uInt16>(aMediaURL.getLength());
2645 mpExEmbed->WriteUInt32( EPP_CString << 16 ).WriteUInt32( nStringLen * 2 );
2646 for ( i = 0; i < nStringLen; i++ )
2648 sal_Unicode nChar = aMediaURL[ i ];
2649 mpExEmbed->WriteUInt16( nChar );
2651 nSize = mpExEmbed->Tell() - nStart;
2652 mpExEmbed->SeekRel( - ( static_cast<sal_Int32>(nSize) + 4 ) );
2653 mpExEmbed->WriteUInt32( nSize ); // size of PPT_PST_ExMCIMovie
2654 mpExEmbed->SeekRel( 0x10 );
2655 nSize -= 20;
2656 mpExEmbed->WriteUInt32( nSize ); // PPT_PST_ExMediaAtom
2657 mpExEmbed->SeekRel( nSize );
2659 if ( !pClientData )
2660 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2661 pClientData->WriteUInt16( 0 )
2662 .WriteUInt16( EPP_ExObjRefAtom )
2663 .WriteUInt32( 4 )
2664 .WriteUInt32( nRefId );
2665 // write EPP_InteractiveInfo container for no_action
2666 pClientData->WriteUInt32( ( EPP_InteractiveInfo << 16 ) | 0xf ).WriteUInt32( 24 );
2667 pClientData->WriteUInt16( 0 )
2668 .WriteUInt16( EPP_InteractiveInfoAtom )
2669 .WriteUInt32( 16 )
2670 .WriteUInt32( 0 )
2671 .WriteUInt32( 0 )
2672 .WriteUChar( 6 )
2673 .WriteUChar( 0 )
2674 .WriteUChar( 0 )
2675 .WriteUChar( 0 )
2676 .WriteUInt32( 0 );
2680 else if ( (mType == "drawing.Table") || (mType == "presentation.Table") )
2682 if ( eCa != css::presentation::ClickAction_NONE )
2684 SvMemoryStream aTmp(0x200, 0x200);
2685 ImplWriteClickAction( aTmp, eCa, bMediaClickAction );
2687 ImplCreateTable( mXShape, aSolverContainer, aPropOpt );
2688 continue;
2690 else if ( mType == "drawing.dontknow" )
2692 mnAngle = 0;
2693 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2694 ImplCreateShape( ESCHER_ShpInst_PictureFrame,
2695 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2696 aSolverContainer );
2697 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "MetaFile", false ) )
2698 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
2700 else
2702 continue;
2705 bool bClientData = ( bEffect || ( eCa != css::presentation::ClickAction_NONE ) ||
2706 nPlaceHolderAtom || nOlePictureId );
2707 if ( bClientData )
2709 if ( nPlaceHolderAtom )
2711 sal_Int32 nPlacementID = -1;
2712 if ( ( mnTextStyle == EPP_TEXTSTYLE_TITLE ) || ( mnTextStyle == EPP_TEXTSTYLE_BODY ) )
2713 nPlacementID = nIndices++;
2714 else
2716 switch ( nPlaceHolderAtom )
2718 default :
2720 if ( nPlaceHolderAtom < 19 )
2721 break;
2722 [[fallthrough]];
2724 case EPP_PLACEHOLDER_NOTESBODY :
2725 case EPP_PLACEHOLDER_MASTERDATE :
2726 case EPP_PLACEHOLDER_NOTESSLIDEIMAGE :
2727 case EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE :
2728 nPlacementID = nIndices++;
2731 if ( !pClientData )
2732 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2734 pClientData->WriteUInt32( EPP_OEPlaceholderAtom << 16 ).WriteUInt32( 8 )
2735 .WriteInt32( nPlacementID ) // PlacementID
2736 .WriteUChar( nPlaceHolderAtom ) // PlaceHolderID
2737 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2738 .WriteUInt16( 0 ); // padword
2740 if ( nOlePictureId )
2742 if ( !pClientData )
2743 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2745 pClientData->WriteUInt32( EPP_ExObjRefAtom << 16 ).WriteUInt32( 4 )
2746 .WriteUInt32( nOlePictureId );
2747 nOlePictureId = 0;
2749 if ( bEffect && !pClientData )
2751 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2754 if ( eCa != css::presentation::ClickAction_NONE )
2756 if ( !pClientData )
2757 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2758 ImplWriteClickAction( *pClientData, eCa, bMediaClickAction );
2761 if ( ( mnTextStyle == EPP_TEXTSTYLE_TITLE ) || ( mnTextStyle == EPP_TEXTSTYLE_BODY ) )
2763 if ( !pClientTextBox )
2764 pClientTextBox.reset(new SvMemoryStream( 0x200, 0x200 ));
2766 if ( !mbEmptyPresObj )
2768 if ( ( ePageType == NORMAL ) && !bMasterPage )
2770 sal_uInt32 nTextType = EPP_TEXTTYPE_Body;
2771 if ( mnTextStyle == EPP_TEXTSTYLE_BODY )
2773 if ( bSecOutl )
2774 nTextType = EPP_TEXTTYPE_HalfBody;
2775 else if ( mType == "presentation.Subtitle" )
2776 nTextType = EPP_TEXTTYPE_CenterBody;
2777 bSecOutl = true;
2779 else
2780 nTextType = EPP_TEXTTYPE_Title;
2782 TextRuleEntry aTextRule;
2783 SvMemoryStream aExtBu( 0x200, 0x200 );
2784 ImplGetText();
2785 ImplWriteTextStyleAtom( *pClientTextBox, nTextType, nPObjects, &aTextRule, aExtBu, nullptr );
2786 ImplWriteExtParaHeader( aExtBu, nPObjects++, nTextType, nPageNumber + 0x100 );
2787 SvMemoryStream* pOut = aTextRule.pOut.get();
2788 if ( pOut )
2790 pClientTextBox->WriteBytes(pOut->GetData(), pOut->Tell());
2791 aTextRule.pOut.reset();
2793 if ( aExtBu.Tell() )
2795 if ( !pClientData )
2796 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2797 ImplProgTagContainer( pClientData.get(), &aExtBu );
2802 else
2804 if ( !aPropOpt.IsFontWork() )
2806 if ( mnTextSize || ( nPlaceHolderAtom == EPP_PLACEHOLDER_MASTERDATE ) || ( nPlaceHolderAtom == EPP_PLACEHOLDER_NOTESBODY ) )
2808 int nInstance2;
2809 if ( ( nPlaceHolderAtom == EPP_PLACEHOLDER_MASTERDATE ) || ( nPlaceHolderAtom == EPP_PLACEHOLDER_NOTESBODY ) )
2810 nInstance2 = 2;
2811 else
2812 nInstance2 = EPP_TEXTTYPE_Other; // Text in a Shape
2814 if ( !pClientTextBox )
2815 pClientTextBox.reset(new SvMemoryStream( 0x200, 0x200 ));
2817 SvMemoryStream aExtBu( 0x200, 0x200 );
2818 ImplWriteTextStyleAtom( *pClientTextBox, nInstance2, 0, nullptr, aExtBu, &aPropOpt );
2819 if ( aExtBu.Tell() )
2821 if ( !pClientData )
2822 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2823 ImplProgTagContainer( pClientData.get(), &aExtBu );
2826 else if ( nPlaceHolderAtom >= 19 )
2828 if ( !pClientTextBox )
2829 pClientTextBox.reset(new SvMemoryStream( 12 ));
2831 pClientTextBox->WriteUInt32( EPP_TextHeaderAtom << 16 ).WriteUInt32( 4 )
2832 .WriteUInt32( 7 );
2837 aPropOpt.CreateShadowProperties( mXPropSet );
2838 maRect.Justify();
2839 if ( mnAngle )
2840 ImplFlipBoundingBox( aPropOpt );
2841 aPropOpt.CreateShapeProperties( mXShape );
2842 aPropOpt.Commit( *mpStrm );
2843 if ( GetCurrentGroupLevel() > 0 )
2844 mpPptEscherEx->AddChildAnchor( maRect );
2845 else
2846 mpPptEscherEx->AddClientAnchor( maRect );
2848 if ( pClientData )
2850 mpStrm->WriteUInt32( ( ESCHER_ClientData << 16 ) | 0xf )
2851 .WriteUInt32( pClientData->Tell() );
2853 mpStrm->WriteBytes(pClientData->GetData(), pClientData->Tell());
2854 pClientData.reset();
2856 if ( pClientTextBox )
2858 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox << 16 ) | 0xf )
2859 .WriteUInt32( pClientTextBox->Tell() );
2861 mpStrm->WriteBytes(pClientTextBox->GetData(), pClientTextBox->Tell());
2862 pClientTextBox.reset();
2864 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2866 nPrevTextStyle = mnTextStyle;
2868 if ( bAdditionalText )
2870 bAdditionalText = false;
2872 css::uno::Any aAny;
2873 EscherPropertyContainer aPropOpt;
2874 mnAngle = ( PropValue::GetPropertyValue( aAny,
2875 mXPropSet, "RotateAngle", true ) )
2876 ? *o3tl::doAccess<sal_Int32>(aAny)
2877 : 0;
2879 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
2880 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
2881 if ( mType == "drawing.Line" )
2883 double fDist = hypot( maRect.GetWidth(), maRect.GetHeight() );
2884 maRect = ::tools::Rectangle( Point( aTextRefPoint.X, aTextRefPoint.Y ),
2885 Point( static_cast<sal_Int32>( aTextRefPoint.X + fDist ), aTextRefPoint.Y - 1 ) );
2886 ImplCreateTextShape( aPropOpt, aSolverContainer, false );
2887 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 ); // Size Shape To Fit Text
2888 if ( mnAngle < 0 )
2889 mnAngle = ( 36000 + mnAngle ) % 36000;
2890 if ( mnAngle )
2891 ImplFlipBoundingBox( aPropOpt );
2893 else
2895 ImplCreateTextShape( aPropOpt, aSolverContainer, false );
2896 if ( mnAngle < 0 )
2897 mnAngle = ( 36000 + mnAngle ) % 36000;
2898 else
2899 mnAngle = ( 36000 - ( mnAngle % 36000 ) );
2901 mnAngle *= 655;
2902 mnAngle += 0x8000;
2903 mnAngle &=~0xffff; // round nAngle to full grad
2904 aPropOpt.AddOpt( ESCHER_Prop_Rotation, mnAngle );
2906 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2907 // mpPptEscherEx->SetGroupSnapRect( nGroupLevel, maRect );
2908 // mpPptEscherEx->SetGroupLogicRect( nGroupLevel, maRect );
2910 if ( !pClientTextBox )
2911 pClientTextBox.reset(new SvMemoryStream( 0x200, 0x200 ));
2913 SvMemoryStream aExtBu( 0x200, 0x200 );
2914 ImplWriteTextStyleAtom( *pClientTextBox, EPP_TEXTTYPE_Other, 0, nullptr, aExtBu, &aPropOpt );
2916 aPropOpt.CreateShapeProperties( mXShape );
2917 aPropOpt.Commit( *mpStrm );
2918 if ( GetCurrentGroupLevel() > 0 )
2919 mpPptEscherEx->AddChildAnchor( maRect );
2920 else
2921 mpPptEscherEx->AddClientAnchor( maRect );
2923 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox << 16 ) | 0xf )
2924 .WriteUInt32( pClientTextBox->Tell() );
2926 mpStrm->WriteBytes(pClientTextBox->GetData(), pClientTextBox->Tell());
2927 pClientTextBox.reset();
2929 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2931 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2932 // mpPptEscherEx->LeaveGroup();
2935 ClearGroupTable(); // storing groups if any are still open, which should not be the case
2936 nGroups = GetGroupsClosed();
2937 for ( sal_uInt32 i = 0; i < nGroups; i++, mpPptEscherEx->LeaveGroup() ) ;
2938 mnPagesWritten++;
2941 struct CellBorder
2943 sal_Int32 mnPos; // specifies the distance to the top/left position of the table
2944 table::BorderLine maCellBorder;
2946 CellBorder() : mnPos ( 0 ) {};
2949 bool PPTWriter::ImplCreateCellBorder( const CellBorder* pCellBorder, sal_Int32 nX1, sal_Int32 nY1, sal_Int32 nX2, sal_Int32 nY2)
2951 sal_Int32 nLineWidth = pCellBorder->maCellBorder.OuterLineWidth + pCellBorder->maCellBorder.InnerLineWidth;
2952 if ( nLineWidth )
2954 nLineWidth *= 2;
2955 mnAngle = 0;
2956 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
2957 EscherPropertyContainer aPropOptSp;
2959 sal_uInt32 nId = mpPptEscherEx->GenerateShapeId();
2960 mpPptEscherEx->AddShape( ESCHER_ShpInst_Line,
2961 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty | ShapeFlag::Child,
2962 nId );
2963 aPropOptSp.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
2964 aPropOptSp.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0xa0008 );
2965 aPropOptSp.AddOpt( ESCHER_Prop_fshadowObscured, 0x20000 );
2967 sal_uInt32 nBorderColor = pCellBorder->maCellBorder.Color & 0xff00; // green
2968 nBorderColor |= static_cast< sal_uInt8 >( pCellBorder->maCellBorder.Color ) << 16; // red
2969 nBorderColor |= static_cast< sal_uInt8 >( pCellBorder->maCellBorder.Color >> 16 ); // blue
2970 aPropOptSp.AddOpt( ESCHER_Prop_lineColor, nBorderColor );
2972 aPropOptSp.AddOpt( ESCHER_Prop_lineWidth, nLineWidth * 360 );
2973 aPropOptSp.AddOpt( ESCHER_Prop_fc3DLightFace, 0x80000 );
2974 aPropOptSp.Commit( *mpStrm );
2975 mpPptEscherEx->AddAtom( 16, ESCHER_ChildAnchor );
2976 mpStrm ->WriteInt32( nX1 )
2977 .WriteInt32( nY1 )
2978 .WriteInt32( nX2 )
2979 .WriteInt32( nY2 );
2980 mpPptEscherEx->CloseContainer();
2981 return true;
2983 return false;
2986 //get merged cell's width
2987 static sal_Int32 GetCellRight( sal_Int32 nColumn,
2988 ::tools::Rectangle const & rect,
2989 std::vector< std::pair< sal_Int32, sal_Int32 > >& aColumns,
2990 uno::Reference< table::XMergeableCell > const & xCell )
2992 sal_Int32 nRight = aColumns[ nColumn ].first + aColumns[ nColumn ].second;
2993 for ( sal_Int32 nColumnSpan = 1; nColumnSpan < xCell->getColumnSpan(); nColumnSpan++ )
2995 sal_uInt32 nC = nColumnSpan + nColumn;
2996 if ( nC < aColumns.size() )
2997 nRight += aColumns[ nC ].second;
2998 else
2999 nRight = rect.Right();
3001 return nRight;
3003 //get merged cell's height
3004 static sal_Int32 GetCellBottom( sal_Int32 nRow,
3005 ::tools::Rectangle const & rect,
3006 std::vector< std::pair< sal_Int32, sal_Int32 > >& aRows,
3007 uno::Reference< table::XMergeableCell > const & xCell )
3009 sal_Int32 nBottom = aRows[nRow].first + aRows[nRow].second;
3010 for ( sal_Int32 nRowSpan = 1; nRowSpan < xCell->getRowSpan(); nRowSpan++ )
3012 sal_uInt32 nR = nRowSpan + nRow;
3013 if ( nR < aRows.size() )
3014 nBottom += aRows[ nR ].second;
3015 else
3016 nBottom = rect.Bottom();
3018 return nBottom;
3021 void PPTWriter::WriteCString( SvStream& rSt, const OUString& rString, sal_uInt32 nInstance )
3023 sal_Int32 nLen = rString.getLength();
3024 if ( nLen )
3026 rSt.WriteUInt32( ( nInstance << 4 ) | ( EPP_CString << 16 ) )
3027 .WriteUInt32( nLen << 1 );
3028 for ( sal_Int32 i = 0; i < nLen; i++ )
3029 rSt.WriteUInt16( rString[i] );
3033 class ContainerGuard
3035 private:
3036 PptEscherEx* m_pPptEscherEx;
3037 public:
3038 ContainerGuard(PptEscherEx* pPptEscherEx, sal_uInt16 nRecord)
3039 : m_pPptEscherEx(pPptEscherEx)
3041 m_pPptEscherEx->OpenContainer(nRecord);
3043 ~ContainerGuard()
3045 m_pPptEscherEx->CloseContainer();
3049 void PPTWriter::ImplCreateTable( uno::Reference< drawing::XShape > const & rXShape, EscherSolverContainer& aSolverContainer,
3050 EscherPropertyContainer& aPropOpt )
3054 uno::Reference< table::XTable > xTable;
3055 if ( mXPropSet->getPropertyValue( "Model" ) >>= xTable )
3057 uno::Reference< table::XColumnRowRange > xColumnRowRange( xTable, uno::UNO_QUERY_THROW );
3058 uno::Reference< container::XIndexAccess > xColumns( xColumnRowRange->getColumns(), uno::UNO_QUERY_THROW );
3059 uno::Reference< container::XIndexAccess > xRows( xColumnRowRange->getRows(), uno::UNO_QUERY_THROW );
3060 sal_uInt16 nRowCount = static_cast< sal_uInt16 >( xRows->getCount() );
3061 sal_uInt16 nColumnCount = static_cast< sal_uInt16 >( xColumns->getCount() );
3063 std::vector< std::pair< sal_Int32, sal_Int32 > > aColumns;
3064 std::vector< std::pair< sal_Int32, sal_Int32 > > aRows;
3066 awt::Point aPosition( MapPoint( rXShape->getPosition() ) );
3067 sal_Int32 nPosition = aPosition.X;
3068 for ( sal_Int32 x = 0; x < nColumnCount; x++ )
3070 uno::Reference< beans::XPropertySet > xPropSet( xColumns->getByIndex( x ), uno::UNO_QUERY_THROW );
3071 awt::Size aS( 0, 0 );
3072 xPropSet->getPropertyValue( "Width" ) >>= aS.Width;
3073 awt::Size aM( MapSize( aS ) );
3074 aColumns.emplace_back( nPosition, aM.Width );
3075 nPosition += aM.Width;
3076 if ( x == nColumnCount - 1 && nPosition != maRect.Right() )
3077 maRect.SetRight( nPosition );
3080 nPosition = aPosition.Y;
3081 for ( sal_Int32 y = 0; y < nRowCount; y++ )
3083 uno::Reference< beans::XPropertySet > xPropSet( xRows->getByIndex( y ), uno::UNO_QUERY_THROW );
3084 awt::Size aS( 0, 0 );
3085 xPropSet->getPropertyValue( "Height" ) >>= aS.Height;
3086 awt::Size aM( MapSize( aS ) );
3087 aRows.emplace_back( nPosition, aM.Height );
3088 nPosition += aM.Height;
3089 if ( y == nRowCount - 1 && nPosition != maRect.Bottom())
3090 maRect.SetBottom( nPosition );
3092 std::unique_ptr<ContainerGuard> xSpgrContainer(new ContainerGuard(mpPptEscherEx.get(), ESCHER_SpgrContainer));
3093 std::unique_ptr<ContainerGuard> xSpContainer(new ContainerGuard(mpPptEscherEx.get(), ESCHER_SpContainer));
3094 mpPptEscherEx->AddAtom( 16, ESCHER_Spgr, 1 );
3095 mpStrm ->WriteInt32( maRect.Left() ) // Bounding box for the grouped shapes to which they are attached
3096 .WriteInt32( maRect.Top() )
3097 .WriteInt32( maRect.Right() )
3098 .WriteInt32( maRect.Bottom() );
3100 sal_uInt32 nShapeId = mpPptEscherEx->GenerateShapeId();
3101 mpPptEscherEx->AddShape( ESCHER_ShpInst_Min, ShapeFlag::HaveAnchor | ShapeFlag::Group, nShapeId );
3102 // TODO: check flags, comment does not match code // Flags: Group | Patriarch
3103 aSolverContainer.AddShape( rXShape, nShapeId );
3104 EscherPropertyContainer aPropOpt2;
3106 SvMemoryStream aMemStrm;
3107 aMemStrm.WriteUInt16( nRowCount )
3108 .WriteUInt16( nRowCount )
3109 .WriteUInt16( 4 );
3111 for( const auto& rRow : aRows )
3112 aMemStrm.WriteInt32( rRow.second );
3114 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x1000100 );
3115 aPropOpt2.AddOpt( ESCHER_Prop_tableProperties, 1 );
3116 aPropOpt2.AddOpt(ESCHER_Prop_tableRowProperties, true, 0, aMemStrm);
3117 aPropOpt.CreateShapeProperties( rXShape );
3118 aPropOpt.Commit( *mpStrm );
3119 aPropOpt2.Commit( *mpStrm, 3, ESCHER_UDefProp );
3120 if ( GetCurrentGroupLevel() > 0 )
3121 mpPptEscherEx->AddChildAnchor( maRect );
3122 else
3123 mpPptEscherEx->AddClientAnchor( maRect );
3124 xSpContainer.reset(); //ESCHER_SpContainer
3126 uno::Reference< table::XCellRange > xCellRange( xTable, uno::UNO_QUERY_THROW );
3127 for( sal_Int32 nRow = 0; nRow < xRows->getCount(); nRow++ )
3129 for( sal_Int32 nColumn = 0; nColumn < xColumns->getCount(); nColumn++ )
3131 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nColumn, nRow ), uno::UNO_QUERY_THROW );
3132 if ( !xCell->isMerged() )
3134 sal_Int32 nLeft = aColumns[ nColumn ].first;
3135 sal_Int32 nTop = aRows[ nRow ].first;
3136 sal_Int32 nRight = GetCellRight( nColumn, maRect,aColumns,xCell );
3137 sal_Int32 nBottom = GetCellBottom( nRow, maRect,aRows,xCell );
3139 mbFontIndependentLineSpacing = false;
3140 mXPropSet.set( xCell, uno::UNO_QUERY_THROW );
3141 mXText.set( xCell, uno::UNO_QUERY_THROW );
3142 mnTextSize = mXText->getString().getLength();
3144 css::uno::Any aAny;
3145 if ( GetPropertyValue( aAny, mXPropSet, "FontIndependentLineSpacing", true ) )
3146 aAny >>= mbFontIndependentLineSpacing;
3148 EscherPropertyContainer aPropOptSp;
3149 std::unique_ptr<ContainerGuard> xCellContainer(new ContainerGuard(mpPptEscherEx.get(), ESCHER_SpContainer));
3150 ImplCreateShape( ESCHER_ShpInst_Rectangle,
3151 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty | ShapeFlag::Child,
3152 aSolverContainer );
3153 aPropOptSp.CreateFillProperties( mXPropSet, true );
3154 aPropOptSp.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
3155 mnTxId += 0x60;
3156 aPropOptSp.CreateTextProperties( mXPropSet, mnTxId );
3157 aPropOptSp.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapSquare );
3159 SvMemoryStream aClientTextBox( 0x200, 0x200 );
3160 SvMemoryStream aExtBu( 0x200, 0x200 );
3162 ImplWriteTextStyleAtom( aClientTextBox, EPP_TEXTTYPE_Other, 0, nullptr, aExtBu, &aPropOptSp );
3164 // need write client data for extend bullet
3165 if ( aExtBu.Tell() )
3167 std::unique_ptr<SvMemoryStream> pClientData(new SvMemoryStream( 0x200, 0x200 ));
3168 ImplProgTagContainer( pClientData.get(), &aExtBu );
3169 mpStrm->WriteUInt32( ( ESCHER_ClientData << 16 ) | 0xf )
3170 .WriteUInt32( pClientData->Tell() );
3172 mpStrm->WriteBytes(pClientData->GetData(), pClientData->Tell());
3175 aPropOptSp.Commit( *mpStrm );
3176 mpPptEscherEx->AddAtom( 16, ESCHER_ChildAnchor );
3177 mpStrm ->WriteInt32( nLeft )
3178 .WriteInt32( nTop )
3179 .WriteInt32( nRight )
3180 .WriteInt32( nBottom );
3182 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox << 16 ) | 0xf )
3183 .WriteUInt32( aClientTextBox.Tell() );
3185 mpStrm->WriteBytes(aClientTextBox.GetData(), aClientTextBox.Tell());
3186 xCellContainer.reset();
3191 // creating horz lines
3192 for( sal_Int32 nLine = 0; nLine < ( xRows->getCount() + 1 ); nLine++ )
3194 for( sal_Int32 nColumn = 0; nColumn < xColumns->getCount(); nColumn++ )
3196 CellBorder aCellBorder;
3197 aCellBorder.mnPos = aColumns[ nColumn ].first;
3198 bool bTop = false;
3199 //write nLine*nColumn cell's top border
3200 if ( nLine < xRows->getCount() )
3201 { // top border
3202 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nColumn, nLine ), uno::UNO_QUERY_THROW );
3203 if ( !xCell->isMerged() )
3205 uno::Reference< beans::XPropertySet > xPropSet2( xCell, uno::UNO_QUERY_THROW );
3206 table::BorderLine aBorderLine;
3207 if ( xPropSet2->getPropertyValue( "TopBorder" ) >>= aBorderLine )
3208 aCellBorder.maCellBorder = aBorderLine;
3209 sal_Int32 nRight = GetCellRight( nColumn, maRect,aColumns,xCell );
3210 bTop = ImplCreateCellBorder( &aCellBorder, aCellBorder.mnPos,
3211 aRows[ nLine ].first, nRight, aRows[ nLine ].first );
3215 //if nLine*nColumn cell's top border is empty, check (nLine-1)*nColumn cell's bottom border
3216 //and write the last row's bottom border
3217 if (( nLine && !bTop ) || (nLine == xRows->getCount()))
3218 { // bottom border
3219 sal_Int32 nRow = nLine;
3221 while( nRow )
3222 { //find last no merged cell
3223 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nColumn, nRow - 1 ), uno::UNO_QUERY_THROW );
3224 if ( !xCell->isMerged() )
3226 sal_Int32 nRight = GetCellRight( nColumn, maRect,aColumns,xCell );
3227 sal_Int32 nBottom = GetCellBottom( nRow - 1, maRect,aRows,xCell );
3228 if ( nBottom == ( aRows[ nLine-1 ].first + aRows[ nLine-1 ].second ) )
3230 uno::Reference< table::XMergeableCell > xCellOwn( xCellRange->getCellByPosition( nColumn, nRow - 1 ), uno::UNO_QUERY_THROW );
3231 uno::Reference< beans::XPropertySet > xPropSet2( xCellOwn, uno::UNO_QUERY_THROW );
3232 table::BorderLine aBorderLine;
3233 if ( xPropSet2->getPropertyValue( "BottomBorder" ) >>= aBorderLine )
3234 aCellBorder.maCellBorder = aBorderLine;
3235 ImplCreateCellBorder( &aCellBorder, aCellBorder.mnPos,
3236 nBottom, nRight, nBottom);
3238 nRow=0;
3240 else
3241 nRow--;
3247 // creating vertical lines
3248 for( sal_Int32 nLine = 0; nLine < ( xColumns->getCount() + 1 ); nLine++ )
3250 for( sal_Int32 nRow = 0; nRow < xRows->getCount(); nRow++ )
3253 CellBorder aCellBorder;
3254 aCellBorder.mnPos = aRows[ nRow].first;
3255 bool bLeft = false;
3256 if ( nLine < xColumns->getCount() )
3257 { // left border
3258 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nLine, nRow ), uno::UNO_QUERY_THROW );
3259 if (!xCell->isMerged() )
3261 uno::Reference< beans::XPropertySet > xCellSet( xCell, uno::UNO_QUERY_THROW );
3262 table::BorderLine aBorderLine;
3263 if ( xCellSet->getPropertyValue( "LeftBorder" ) >>= aBorderLine )
3264 aCellBorder.maCellBorder = aBorderLine;
3265 sal_Int32 nBottom = GetCellBottom( nRow, maRect, aRows,xCell );
3266 bLeft = ImplCreateCellBorder( &aCellBorder, aColumns[nLine].first, aCellBorder.mnPos,
3267 aColumns[nLine].first, nBottom );
3270 if ( ( nLine && !bLeft )||(nLine == xColumns->getCount()))
3271 { // right border
3272 sal_Int32 nColumn = nLine;
3273 while ( nColumn )
3275 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nColumn - 1, nRow ), uno::UNO_QUERY_THROW );
3276 if (!xCell->isMerged() )
3278 sal_Int32 nRight = GetCellRight( nColumn-1, maRect, aColumns,xCell );
3279 sal_Int32 nBottom = GetCellBottom( nRow, maRect, aRows, xCell );
3280 if ( nRight == (aColumns[nLine-1].first + aColumns[nLine-1].second) )
3282 uno::Reference< table::XMergeableCell > xCellOwn( xCellRange->getCellByPosition( nColumn - 1, nRow ), uno::UNO_QUERY_THROW );
3283 uno::Reference< beans::XPropertySet > xCellSet( xCellOwn, uno::UNO_QUERY_THROW );
3284 table::BorderLine aBorderLine;
3285 if ( xCellSet->getPropertyValue( "RightBorder" ) >>= aBorderLine )
3286 aCellBorder.maCellBorder = aBorderLine;
3287 ImplCreateCellBorder( &aCellBorder, nRight, aCellBorder.mnPos,
3288 nRight, nBottom );
3290 nColumn = 0;
3292 else
3293 nColumn --;
3299 xSpgrContainer.reset(); //ESCHER_SpgrContainer
3302 catch( uno::Exception& )
3307 void TextObjBinary::Write( SvStream* pStrm )
3309 sal_uInt32 nSize, nPos = pStrm->Tell();
3310 pStrm->WriteUInt32( EPP_TextCharsAtom << 16 ).WriteUInt32( 0 );
3311 for ( sal_uInt32 i = 0; i < ParagraphCount(); ++i )
3312 GetParagraph(i)->Write( pStrm );
3313 nSize = pStrm->Tell() - nPos;
3314 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
3315 pStrm->WriteUInt32( nSize - 8 );
3316 pStrm->SeekRel( nSize - 8 );
3319 void TextObjBinary::WriteTextSpecInfo( SvStream* pStrm )
3321 sal_uInt32 nCharactersLeft( Count() );
3322 if ( nCharactersLeft < 1 )
3323 return;
3325 EscherExAtom aAnimationInfoAtom( *pStrm, EPP_TextSpecInfoAtom, 0, 0 );
3326 for ( sal_uInt32 i = 0; nCharactersLeft && i < ParagraphCount(); ++i )
3328 ParagraphObj* pPtr = GetParagraph(i);
3329 for ( std::vector<std::unique_ptr<PortionObj> >::const_iterator it = pPtr->begin(); nCharactersLeft && it != pPtr->end(); ++it )
3331 const PortionObj& rPortion = **it;
3332 sal_Int32 nPortionSize = rPortion.mnTextSize >= nCharactersLeft ? nCharactersLeft : rPortion.mnTextSize;
3333 sal_Int32 const nFlags = 7;
3334 nCharactersLeft -= nPortionSize;
3335 pStrm ->WriteUInt32( nPortionSize )
3336 .WriteInt32( nFlags )
3337 .WriteInt16( 1 ) // spellinfo -> needs rechecking
3338 .WriteInt16( static_cast<sal_uInt16>(LanguageTag( rPortion.meCharLocale ).makeFallback().getLanguageType()) )
3339 .WriteInt16( 0 ); // alt language
3342 if ( nCharactersLeft )
3343 pStrm->WriteUInt32( nCharactersLeft ).WriteInt32( 1 ).WriteInt16( 1 );
3346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */