Bug Summary

File:home/maarten/src/libreoffice/core/sd/source/filter/eppt/epptso.cxx
Warning:line 1521, column 5
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name epptso.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/sd/inc -I /home/maarten/src/libreoffice/core/sd/source/ui/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sd/source/filter/eppt/epptso.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <memory>
21#include <sal/config.h>
22
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 <tools/UnitConversion.hxx>
33#include <sot/storage.hxx>
34#include <vcl/graph.hxx>
35#include <editeng/svxenum.hxx>
36#include <svx/svdobj.hxx>
37#include <svx/unoapi.hxx>
38#include <com/sun/star/awt/FontFamily.hpp>
39#include <com/sun/star/awt/FontPitch.hpp>
40#include <com/sun/star/awt/Rectangle.hpp>
41#include <com/sun/star/awt/FontDescriptor.hpp>
42#include <com/sun/star/frame/XModel.hpp>
43#include <com/sun/star/style/TabStop.hpp>
44#include <com/sun/star/drawing/CircleKind.hpp>
45#include <com/sun/star/drawing/FillStyle.hpp>
46#include <com/sun/star/beans/XPropertyState.hpp>
47#include <com/sun/star/drawing/XControlShape.hpp>
48#include <com/sun/star/embed/Aspects.hpp>
49#include <tools/urlobj.hxx>
50#include <com/sun/star/text/XSimpleText.hpp>
51#include <com/sun/star/task/XStatusIndicator.hpp>
52#include <com/sun/star/table/XTable.hpp>
53#include <com/sun/star/table/XMergeableCell.hpp>
54#include <com/sun/star/table/BorderLine.hpp>
55#include <com/sun/star/table/XColumnRowRange.hpp>
56#include <com/sun/star/table/XCellRange.hpp>
57#include <oox/ole/olehelper.hxx>
58#include <i18nlangtag/languagetag.hxx>
59
60using namespace ::com::sun::star;
61
62#define ANSI_CHARSET0 0
63#define SYMBOL_CHARSET2 2
64
65/* Font Families */
66#define FF_ROMAN0x10 0x10
67#define FF_SWISS0x20 0x20
68#define FF_MODERN0x30 0x30
69#define FF_SCRIPT0x40 0x40
70#define FF_DECORATIVE0x50 0x50
71
72#define DEFAULT_PITCH0x00 0x00
73#define FIXED_PITCH0x01 0x01
74
75PPTExBulletProvider::PPTExBulletProvider()
76 : pGraphicProv( new EscherGraphicProvider( EscherGraphicProviderFlags::UseInstances ) )
77{
78}
79
80PPTExBulletProvider::~PPTExBulletProvider()
81{
82}
83
84sal_uInt16 PPTExBulletProvider::GetId(Graphic const & rGraphic, Size& rGraphicSize )
85{
86 sal_uInt16 nRetValue = 0xffff;
87
88 if (!rGraphic.IsNone())
89 {
90 Graphic aMappedGraphic, aGraphic(rGraphic);
91 std::unique_ptr<GraphicObject> xGraphicObject(new GraphicObject(aGraphic));
92 Size aPrefSize( aGraphic.GetPrefSize() );
93 BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
94
95 if ( rGraphicSize.Width() && rGraphicSize.Height() )
96 {
97 if (aPrefSize.IsEmpty())
98 {
99 aBmpEx.Scale(aPrefSize);
100 }
101 else
102 {
103 double fQ1 = static_cast<double>(aPrefSize.Width()) / static_cast<double>(aPrefSize.Height());
104 double fQ2 = static_cast<double>(rGraphicSize.Width()) / static_cast<double>(rGraphicSize.Height());
105 double fXScale = 1;
106 double fYScale = 1;
107
108 if ( fQ1 > fQ2 )
109 fYScale = fQ1 / fQ2;
110 else if ( fQ1 < fQ2 )
111 fXScale = fQ2 / fQ1;
112
113 if ( ( fXScale != 1.0 ) || ( fYScale != 1.0 ) )
114 {
115 aBmpEx.Scale( fXScale, fYScale );
116 rGraphicSize = Size( static_cast<sal_Int32>(static_cast<double>(rGraphicSize.Width()) / fXScale + 0.5 ),
117 static_cast<sal_Int32>(static_cast<double>(rGraphicSize.Height()) / fYScale + 0.5 ) );
118
119 aMappedGraphic = Graphic( aBmpEx );
120 xGraphicObject.reset(new GraphicObject(aMappedGraphic));
121 }
122 }
123 }
124 sal_uInt32 nId = pGraphicProv->GetBlibID(aBuExPictureStream, *xGraphicObject);
125
126 if ( nId && ( nId < 0x10000 ) )
127 nRetValue = static_cast<sal_uInt16>(nId) - 1;
128 }
129 return nRetValue;
130}
131
132sal_uInt32 PPTWriter::ImplVBAInfoContainer( SvStream* pStrm )
133{
134 sal_uInt32 nSize = 28;
135 if ( pStrm )
136 {
137 pStrm->WriteUInt32( 0x1f | ( EPP_VBAInfo1023 << 16 ) )
138 .WriteUInt32( nSize - 8 )
139 .WriteUInt32( 2 | ( EPP_VBAInfoAtom1024 << 16 ) )
140 .WriteUInt32( 12 );
141 mpPptEscherEx->InsertPersistOffset( EPP_Persist_VBAInfoAtom0x84000000, pStrm->Tell() );
142 pStrm->WriteUInt32( 0 )
143 .WriteUInt32( 0 )
144 .WriteUInt32( 1 );
145 }
146 return nSize;
147}
148
149sal_uInt32 PPTWriter::ImplSlideViewInfoContainer( sal_uInt32 nInstance, SvStream* pStrm )
150{
151 sal_uInt32 nSize = 111;
152 if ( pStrm )
153 {
154 sal_uInt8 bShowGuides = 0;
155 sal_uInt8 const bSnapToGrid = 1;
156 sal_uInt8 const bSnapToShape = 0;
157
158 sal_Int32 nScaling = 85;
159 sal_Int32 nMasterCoordinate = 0xdda;
160 sal_Int32 nXOrigin = -780;
161 sal_Int32 nYOrigin = -84;
162
163 sal_Int32 nPosition1 = 0x870;
164 sal_Int32 nPosition2 = 0xb40;
165
166 if ( nInstance )
167 {
168 bShowGuides = 1;
169 nScaling = 0x3b;
170 nMasterCoordinate = 0xf0c;
171 nXOrigin = -1752;
172 nYOrigin = -72;
173 nPosition1 = 0xb40;
174 nPosition2 = 0x870;
175 }
176 pStrm->WriteUInt32( 0xf | ( EPP_SlideViewInfo1018 << 16 ) | ( nInstance << 4 ) )
177 .WriteUInt32( nSize - 8 )
178 .WriteUInt32( EPP_SlideViewInfoAtom1022 << 16 ).WriteUInt32( 3 )
179 .WriteUChar( bShowGuides ).WriteUChar( bSnapToGrid ).WriteUChar( bSnapToShape )
180 .WriteUInt32( EPP_ViewInfoAtom1021 << 16 ).WriteUInt32( 52 )
181 .WriteInt32( nScaling ).WriteInt32( 100 ).WriteInt32( nScaling ).WriteInt32( 100 ) // scaling atom - Keeps the current scale
182 .WriteInt32( nScaling ).WriteInt32( 100 ).WriteInt32( nScaling ).WriteInt32( 100 ) // scaling atom - Keeps the previous scale
183 .WriteInt32( 0x17ac ).WriteInt32( nMasterCoordinate )// Origin - Keeps the origin in master coordinates
184 .WriteInt32( nXOrigin ).WriteInt32( nYOrigin ) // Origin
185 .WriteUChar( 1 ) // Bool1 varScale - Set if zoom to fit is set
186 .WriteUChar( 0 ) // bool1 draftMode - Not used
187 .WriteUInt16( 0 ) // padword
188 .WriteUInt32( ( 7 << 4 ) | ( EPP_GuideAtom1019 << 16 ) ).WriteUInt32( 8 )
189 .WriteUInt32( 0 ) // Type of the guide. If the guide is horizontal this value is zero. If it's vertical, it's one.
190 .WriteInt32( nPosition1 ) // Position of the guide in master coordinates. X coordinate if it's vertical, and Y coordinate if it's horizontal.
191 .WriteUInt32( ( 7 << 4 ) | ( EPP_GuideAtom1019 << 16 ) ).WriteUInt32( 8 )
192 .WriteInt32( 1 ) // Type of the guide. If the guide is horizontal this value is zero. If it's vertical, it's one.
193 .WriteInt32( nPosition2 ); // Position of the guide in master coordinates. X coordinate if it's vertical, and Y coordinate if it's horizontal.
194 }
195 return nSize;
196}
197
198sal_uInt32 PPTWriter::ImplOutlineViewInfoContainer( SvStream* pStrm )
199{
200 sal_uInt32 nSize = 68;
201 if ( pStrm )
202 {
203 pStrm->WriteUInt32( 0xf | ( EPP_OutlineViewInfo1031 << 16 ) ).WriteUInt32( nSize - 8 )
204 .WriteUInt32( EPP_ViewInfoAtom1021 << 16 ).WriteUInt32( 52 )
205 .WriteInt32( 170 ).WriteInt32( 200 ).WriteInt32( 170 ).WriteInt32( 200 ) // scaling atom - Keeps the current scale
206 .WriteInt32( 170 ).WriteInt32( 200 ).WriteInt32( 170 ).WriteInt32( 200 ) // scaling atom - Keeps the previous scale
207 .WriteInt32( 0x17ac ).WriteInt32( 0xdda ) // Origin - Keeps the origin in master coordinates
208 .WriteInt32( -780 ).WriteInt32( -84 ) // Origin
209 .WriteUChar( 1 ) // bool1 varScale - Set if zoom to fit is set
210 .WriteUChar( 0 ) // bool1 draftMode - Not used
211 .WriteUInt16( 0 ); // padword
212 }
213 return nSize;
214}
215
216sal_uInt32 PPTWriter::ImplProgBinaryTag( SvStream* pStrm )
217{
218 sal_uInt32 nPictureStreamSize, nOutlineStreamSize, nSize = 8;
219
220 nPictureStreamSize = aBuExPictureStream.Tell();
221 if ( nPictureStreamSize )
222 nSize += nPictureStreamSize + 8;
223
224 nOutlineStreamSize = aBuExOutlineStream.Tell();
225 if ( nOutlineStreamSize )
226 nSize += nOutlineStreamSize + 8;
227
228 if ( pStrm )
229 {
230 pStrm->WriteUInt32( EPP_BinaryTagData5003 << 16 ).WriteUInt32( nSize - 8 );
231 if ( nPictureStreamSize )
232 {
233 pStrm->WriteUInt32( 0xf | ( EPP_PST_ExtendedBuGraContainer2040 << 16 ) ).WriteUInt32( nPictureStreamSize );
234 pStrm->WriteBytes(aBuExPictureStream.GetData(), nPictureStreamSize);
235 }
236 if ( nOutlineStreamSize )
237 {
238 pStrm->WriteUInt32( 0xf | ( EPP_PST_ExtendedPresRuleContainer4014 << 16 ) ).WriteUInt32( nOutlineStreamSize );
239 pStrm->WriteBytes(aBuExOutlineStream.GetData(), nOutlineStreamSize);
240 }
241 }
242 return nSize;
243}
244
245sal_uInt32 PPTWriter::ImplProgBinaryTagContainer( SvStream* pStrm, SvMemoryStream* pBinTagStrm )
246{
247 sal_uInt32 nSize = 8 + 8 + 14;
248 if ( pStrm )
249 {
250 pStrm->WriteUInt32( 0xf | ( EPP_ProgBinaryTag5002 << 16 ) ).WriteUInt32( 0 )
251 .WriteUInt32( EPP_CString4026 << 16 ).WriteUInt32( 14 )
252 .WriteUInt32( 0x5f005f ).WriteUInt32( 0x50005f )
253 .WriteUInt32( 0x540050 ).WriteUInt16( 0x39 );
254 }
255 if ( pStrm && pBinTagStrm )
256 {
257 sal_uInt32 nLen = pBinTagStrm->Tell();
258 nSize += nLen + 8;
259 pStrm->WriteUInt32( EPP_BinaryTagData5003 << 16 ).WriteUInt32( nLen );
260 pStrm->WriteBytes(pBinTagStrm->GetData(), nLen);
261 }
262 else
263 nSize += ImplProgBinaryTag( pStrm );
264
265 if ( pStrm )
266 {
267 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
268 pStrm->WriteUInt32( nSize - 8 );
269 pStrm->SeekRel( nSize - 8 );
270 }
271 return nSize;
272}
273
274sal_uInt32 PPTWriter::ImplProgTagContainer( SvStream* pStrm, SvMemoryStream* pBinTagStrm )
275{
276 sal_uInt32 nSize = 0;
277 if ( aBuExPictureStream.Tell() || aBuExOutlineStream.Tell() || pBinTagStrm )
278 {
279 nSize = 8;
280 if ( pStrm )
281 {
282 pStrm->WriteUInt32( 0xf | ( EPP_ProgTags5000 << 16 ) ).WriteUInt32( 0 );
283 }
284 nSize += ImplProgBinaryTagContainer( pStrm, pBinTagStrm );
285 if ( pStrm )
286 {
287 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
288 pStrm->WriteUInt32( nSize - 8 );
289 pStrm->SeekRel( nSize - 8 );
290 }
291 }
292 return nSize;
293}
294
295sal_uInt32 PPTWriter::ImplDocumentListContainer( SvStream* pStrm )
296{
297 sal_uInt32 nSize = 8;
298 if ( pStrm )
299 {
300 pStrm->WriteUInt32( ( EPP_List2000 << 16 ) | 0xf ).WriteUInt32( 0 );
301 }
302
303 nSize += ImplVBAInfoContainer( pStrm );
304 nSize += ImplSlideViewInfoContainer( 0, pStrm );
305 nSize += ImplOutlineViewInfoContainer( pStrm );
306 nSize += ImplSlideViewInfoContainer( 1, pStrm );
307 nSize += ImplProgTagContainer( pStrm );
308
309 if ( pStrm )
310 {
311 pStrm->SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
312 pStrm->WriteUInt32( nSize - 8 );
313 pStrm->SeekRel( nSize - 8 );
314 }
315 return nSize;
316}
317
318sal_uInt32 PPTWriter::ImplMasterSlideListContainer( SvStream* pStrm )
319{
320 sal_uInt32 i, nSize = 28 * mnMasterPages + 8;
321 if ( pStrm )
322 {
323 pStrm->WriteUInt32( 0x1f | ( EPP_SlideListWithText4080 << 16 ) ).WriteUInt32( nSize - 8 );
324
325 for ( i = 0; i < mnMasterPages; i++ )
326 {
327 pStrm->WriteUInt32( EPP_SlidePersistAtom1011 << 16 ).WriteUInt32( 20 );
328 mpPptEscherEx->InsertPersistOffset( EPP_MAINMASTER_PERSIST_KEY0x80010000 | i, pStrm->Tell() );
329 pStrm->WriteUInt32( 0 ) // psrReference - logical reference to the slide persist object ( EPP_MAINMASTER_PERSIST_KEY )
330 .WriteUInt32( 0 ) // flags - only bit 3 used, if set then slide contains shapes other than placeholders
331 .WriteInt32( 0 ) // numberTexts - number of placeholder texts stored with the persist object. Allows to display outline view without loading the slide persist objects
332 .WriteInt32( 0x80000000 | i ) // slideId - Unique slide identifier, used for OLE link monikers for example
333 .WriteUInt32( 0 ); // reserved, usually 0
334 }
335 }
336 return nSize;
337}
338
339sal_uInt32 PPTWriter::ImplInsertBookmarkURL( const OUString& rBookmarkURL, const sal_uInt32 nType,
340 const OUString& rStringVer0, const OUString& rStringVer1, const OUString& rStringVer2, const OUString& rStringVer3 )
341{
342 sal_uInt32 nHyperId = ++mnExEmbed;
343
344 OUString sBookmarkURL( rBookmarkURL );
345 INetURLObject aBaseURI( maBaseURI );
346 INetURLObject aBookmarkURI( rBookmarkURL );
347 if( aBaseURI.GetProtocol() == aBookmarkURI.GetProtocol() )
348 {
349 OUString aRelUrl( INetURLObject::GetRelURL( maBaseURI, rBookmarkURL ) );
350 if ( !aRelUrl.isEmpty() )
351 sBookmarkURL = aRelUrl;
352 }
353 maHyperlink.emplace_back( sBookmarkURL, nType );
354
355 mpExEmbed->WriteUInt16( 0xf )
356 .WriteUInt16( EPP_ExHyperlink4055 )
357 .WriteUInt32( 0 );
358 sal_uInt32 nHyperSize, nHyperStart = mpExEmbed->Tell();
359 mpExEmbed->WriteUInt16( 0 )
360 .WriteUInt16( EPP_ExHyperlinkAtom4051 )
361 .WriteUInt32( 4 )
362 .WriteUInt32( nHyperId );
363
364 PPTWriter::WriteCString( *mpExEmbed, rStringVer0 );
365 PPTWriter::WriteCString( *mpExEmbed, rStringVer1, 1 );
366 PPTWriter::WriteCString( *mpExEmbed, rStringVer2, 2 );
367 PPTWriter::WriteCString( *mpExEmbed, rStringVer3, 3 );
368
369 nHyperSize = mpExEmbed->Tell() - nHyperStart;
370 mpExEmbed->SeekRel( - ( static_cast<sal_Int32>(nHyperSize) + 4 ) );
371 mpExEmbed->WriteUInt32( nHyperSize );
372 mpExEmbed->SeekRel( nHyperSize );
373 return nHyperId;
374}
375
376bool PPTWriter::ImplCloseDocument()
377{
378 sal_uInt32 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_Document0x80080000 );
379 if ( nOfs )
380 {
381 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_CurrentPos0x81000000, mpStrm->Tell() );
382 mpStrm->Seek( nOfs );
383
384 // creating the TxMasterStyleAtom
385 SvMemoryStream aTxMasterStyleAtomStrm( 0x200, 0x200 );
386 {
387 EscherExAtom aTxMasterStyleAtom( aTxMasterStyleAtomStrm, EPP_TxMasterStyleAtom4003, EPP_TEXTTYPE_Other4 );
388 aTxMasterStyleAtomStrm.WriteUInt16( 5 ); // paragraph count
389 sal_uInt16 nLev;
390 for ( nLev = 0; nLev < 5; nLev++ )
391 {
392 mpStyleSheet->mpParaSheet[ EPP_TEXTTYPE_Other4 ]->Write( aTxMasterStyleAtomStrm, nLev, false, mXPagePropSet );
393 mpStyleSheet->mpCharSheet[ EPP_TEXTTYPE_Other4 ]->Write( aTxMasterStyleAtomStrm, nLev, false, mXPagePropSet );
394 }
395 }
396
397 sal_uInt32 nExEmbedSize = mpExEmbed->TellEnd();
398
399 // nEnvironment : whole size of the environment container
400 sal_uInt32 nEnvironment = maFontCollection.GetCount() * 76 // 68 bytes per Fontenityatom and 8 Bytes per header
401 + 8 // 1 FontCollection container
402 + 20 // SrKinsoku container
403 + 18 // 1 TxSiStyleAtom
404 + aTxMasterStyleAtomStrm.Tell() // 1 TxMasterStyleAtom;
405 + PPTExStyleSheet::SizeOfTxCFStyleAtom();
406
407 sal_uInt32 nBytesToInsert = nEnvironment + 8;
408
409 if ( nExEmbedSize )
410 nBytesToInsert += nExEmbedSize + 8 + 12;
411
412 nBytesToInsert += maSoundCollection.GetSize();
413 nBytesToInsert += mpPptEscherEx->DrawingGroupContainerSize();
414 nBytesToInsert += ImplMasterSlideListContainer(nullptr);
415 nBytesToInsert += ImplDocumentListContainer(nullptr);
416
417 // insert nBytes into stream and adjust depending container
418 mpPptEscherEx->InsertAtCurrentPos( nBytesToInsert );
419
420 // CREATE HYPERLINK CONTAINER
421 if ( nExEmbedSize )
422 {
423 mpStrm->WriteUInt16( 0xf )
424 .WriteUInt16( EPP_ExObjList1033 )
425 .WriteUInt32( nExEmbedSize + 12 )
426 .WriteUInt16( 0 )
427 .WriteUInt16( EPP_ExObjListAtom1034 )
428 .WriteUInt32( 4 )
429 .WriteUInt32( mnExEmbed );
430 mpPptEscherEx->InsertPersistOffset( EPP_Persist_ExObj0x88000000, mpStrm->Tell() );
431 mpStrm->WriteBytes(mpExEmbed->GetData(), nExEmbedSize);
432 }
433
434 // CREATE ENVIRONMENT
435 mpStrm->WriteUInt16( 0xf ).WriteUInt16( EPP_Environment1010 ).WriteUInt32( nEnvironment );
436
437 // Open Container ( EPP_SrKinsoku )
438 mpStrm->WriteUInt16( 0x2f ).WriteUInt16( EPP_SrKinsoku4040 ).WriteUInt32( 12 );
439 mpPptEscherEx->AddAtom( 4, EPP_SrKinsokuAtom4050, 0, 3 );
440 mpStrm->WriteInt32( 0 ); // SrKinsoku Level 0
441
442 // Open Container ( EPP_FontCollection )
443 mpStrm->WriteUInt16( 0xf ).WriteUInt16( EPP_FontCollection2005 ).WriteUInt32( maFontCollection.GetCount() * 76 );
444
445 for ( sal_uInt32 i = 0; i < maFontCollection.GetCount(); i++ )
446 {
447 mpPptEscherEx->AddAtom( 68, EPP_FontEnityAtom4023, 0, i );
448 const FontCollectionEntry* pDesc = maFontCollection.GetById( i );
449 sal_Int32 nFontLen = pDesc->Name.getLength();
450 if ( nFontLen > 31 )
451 nFontLen = 31;
452 for ( sal_Int32 n = 0; n < 32; n++ )
453 {
454 sal_Unicode nUniCode = 0;
455 if ( n < nFontLen )
456 nUniCode = pDesc->Name[n];
457 mpStrm->WriteUInt16( nUniCode );
458 }
459 sal_uInt8 lfCharSet = ANSI_CHARSET0;
460 sal_uInt8 const lfClipPrecision = 0;
461 sal_uInt8 const lfQuality = 6;
462 sal_uInt8 lfPitchAndFamily = 0;
463
464 if ( pDesc->CharSet == RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) )
465 lfCharSet = SYMBOL_CHARSET2;
466
467 switch( pDesc->Family )
468 {
469 case css::awt::FontFamily::ROMAN :
470 lfPitchAndFamily |= FF_ROMAN0x10;
471 break;
472
473 case css::awt::FontFamily::SWISS :
474 lfPitchAndFamily |= FF_SWISS0x20;
475 break;
476
477 case css::awt::FontFamily::MODERN :
478 lfPitchAndFamily |= FF_MODERN0x30;
479 break;
480
481 case css::awt::FontFamily::SCRIPT:
482 lfPitchAndFamily |= FF_SCRIPT0x40;
483 break;
484
485 case css::awt::FontFamily::DECORATIVE:
486 lfPitchAndFamily |= FF_DECORATIVE0x50;
487 break;
488
489 default:
490 lfPitchAndFamily |= FAMILY_DONTKNOW;
491 break;
492 }
493 switch( pDesc->Pitch )
494 {
495 case css::awt::FontPitch::FIXED:
496 lfPitchAndFamily |= FIXED_PITCH0x01;
497 break;
498
499 default:
500 lfPitchAndFamily |= DEFAULT_PITCH0x00;
501 break;
502 }
503 mpStrm->WriteUChar( lfCharSet )
504 .WriteUChar( lfClipPrecision )
505 .WriteUChar( lfQuality )
506 .WriteUChar( lfPitchAndFamily );
507 }
508 mpStyleSheet->WriteTxCFStyleAtom( *mpStrm ); // create style that is used for new standard objects
509 mpPptEscherEx->AddAtom( 10, EPP_TxSIStyleAtom4009 );
510 mpStrm->WriteUInt32( 7 ) // ?
511 .WriteInt16( 2 ) // ?
512 .WriteUChar( 9 ) // ?
513 .WriteUChar( 8 ) // ?
514 .WriteInt16( 0 ); // ?
515
516 mpStrm->WriteBytes(aTxMasterStyleAtomStrm.GetData(), aTxMasterStyleAtomStrm.Tell());
517 maSoundCollection.Write( *mpStrm );
518 mpPptEscherEx->WriteDrawingGroupContainer( *mpStrm );
519 ImplMasterSlideListContainer( mpStrm.get() );
520 ImplDocumentListContainer( mpStrm.get() );
521
522 sal_uInt32 nOldPos = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_CurrentPos0x81000000 );
523 if ( nOldPos )
524 {
525 mpStrm->Seek( nOldPos );
526 return true;
527 }
528 }
529 return false;
530}
531
532bool PropValue::GetPropertyValue(
533 css::uno::Any& rAny,
534 const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
535 const OUString& rString,
536 bool bTestPropertyAvailability )
537{
538 bool bRetValue = true;
539 if ( bTestPropertyAvailability )
540 {
541 bRetValue = false;
542 try
543 {
544 css::uno::Reference< css::beans::XPropertySetInfo > aXPropSetInfo( rXPropSet->getPropertySetInfo() );
545 if ( aXPropSetInfo.is() )
546 bRetValue = aXPropSetInfo->hasPropertyByName( rString );
547 }
548 catch( css::uno::Exception& )
549 {
550 bRetValue = false;
551 }
552 }
553 if ( bRetValue )
554 {
555 try
556 {
557 rAny = rXPropSet->getPropertyValue( rString );
558 if ( !rAny.hasValue() )
559 bRetValue = false;
560 }
561 catch( css::uno::Exception& )
562 {
563 bRetValue = false;
564 }
565 }
566 return bRetValue;
567}
568
569css::beans::PropertyState PropValue::GetPropertyState(
570 const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
571 const OUString& rPropertyName )
572{
573 css::beans::PropertyState eRetValue = css::beans::PropertyState_AMBIGUOUS_VALUE;
574 try
575 {
576 css::uno::Reference< css::beans::XPropertyState > aXPropState( rXPropSet, css::uno::UNO_QUERY );
577 if ( aXPropState.is() )
578 eRetValue = aXPropState->getPropertyState( rPropertyName );
579 }
580 catch( css::uno::Exception& )
581 {
582
583 }
584 return eRetValue;
585}
586
587bool PropValue::ImplGetPropertyValue( const OUString& rString )
588{
589 return GetPropertyValue( mAny, mXPropSet, rString );
590}
591
592bool PropValue::ImplGetPropertyValue( const css::uno::Reference< css::beans::XPropertySet > & aXPropSet, const OUString& rString )
593{
594 return GetPropertyValue( mAny, aXPropSet, rString );
595}
596
597bool PropStateValue::ImplGetPropertyValue( const OUString& rString, bool bGetPropertyState )
598{
599 ePropState = css::beans::PropertyState_AMBIGUOUS_VALUE;
600 bool bRetValue = true;
601#ifdef UNX1
602 css::uno::Reference< css::beans::XPropertySetInfo >
603 aXPropSetInfo( mXPropSet->getPropertySetInfo() );
604 if ( !aXPropSetInfo.is() )
605 return false;
606#endif
607 try
608 {
609 mAny = mXPropSet->getPropertyValue( rString );
610 if ( !mAny.hasValue() )
611 bRetValue = false;
612 else if ( bGetPropertyState )
613 ePropState = mXPropState->getPropertyState( rString );
614 else
615 ePropState = css::beans::PropertyState_DIRECT_VALUE;
616 }
617 catch( css::uno::Exception& )
618 {
619 bRetValue = false;
620 }
621 return bRetValue;
622}
623
624void PPTWriter::ImplWriteParagraphs( SvStream& rOut, TextObj& rTextObj )
625{
626 bool bFirstParagraph = true;
627 sal_uInt32 nCharCount;
628 sal_uInt32 nPropertyFlags = 0;
629 sal_Int16 nLineSpacing;
630 int nInstance = rTextObj.GetInstance();
631
632 for ( sal_uInt32 i = 0; i < rTextObj.ParagraphCount(); ++i, bFirstParagraph = false )
633 {
634 ParagraphObj* pPara = rTextObj.GetParagraph(i);
635 const PortionObj& rPortion = pPara->front();
636 nCharCount = pPara->CharacterCount();
637
638 if ( ( pPara->meTextAdjust == css::beans::PropertyState_DIRECT_VALUE ) ||
639 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_Adjust, pPara->mnTextAdjust ) ) )
640 nPropertyFlags |= 0x00000800;
641 nLineSpacing = pPara->mnLineSpacing;
642
643 const FontCollectionEntry* pDesc = maFontCollection.GetById( rPortion.mnFont );
644 sal_Int16 nNormalSpacing = 100;
645 if ( !mbFontIndependentLineSpacing && pDesc )
646 {
647 double fN = 100.0;
648 fN *= pDesc->Scaling;
649 nNormalSpacing = static_cast<sal_Int16>( fN + 0.5 );
650 }
651 if ( !mbFontIndependentLineSpacing && bFirstParagraph && ( nLineSpacing > nNormalSpacing ) ) // sj: i28747, no replacement for fixed linespacing
652 {
653 nLineSpacing = nNormalSpacing;
654 nPropertyFlags |= 0x00001000;
655 }
656 else
657 {
658 if ( nLineSpacing > 0 )
659 {
660 if ( !mbFontIndependentLineSpacing && pDesc )
661 nLineSpacing = static_cast<sal_Int16>( static_cast<double>(nLineSpacing) * pDesc->Scaling + 0.5 );
662 }
663 else
664 {
665 if ( !pPara->mbFixedLineSpacing && rPortion.mnCharHeight > static_cast<sal_uInt16>( static_cast<double>(-nLineSpacing) * 0.001 * 72.0 / 2.54 ) ) // 1/100mm to point
666 nLineSpacing = nNormalSpacing;
667 else
668 nLineSpacing = static_cast<sal_Int16>( convertTwipToMasterUnit(nLineSpacing) );
669 }
670 if ( ( pPara->meLineSpacing == css::beans::PropertyState_DIRECT_VALUE ) ||
671 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_LineFeed, nLineSpacing ) ) )
672 nPropertyFlags |= 0x00001000;
673 }
674 if ( ( pPara->meLineSpacingTop == css::beans::PropertyState_DIRECT_VALUE ) ||
675 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_UpperDist, pPara->mnLineSpacingTop ) ) )
676 nPropertyFlags |= 0x00002000;
677 if ( ( pPara->meLineSpacingBottom == css::beans::PropertyState_DIRECT_VALUE ) ||
678 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_LowerDist, pPara->mnLineSpacingBottom ) ) )
679 nPropertyFlags |= 0x00004000;
680 if ( ( pPara->meForbiddenRules == css::beans::PropertyState_DIRECT_VALUE ) ||
681 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_UpperDist, pPara->mbForbiddenRules ? 1 : 0 ) ) )
682 nPropertyFlags |= 0x00020000;
683 if ( ( pPara->meParagraphPunctation == css::beans::PropertyState_DIRECT_VALUE ) ||
684 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_UpperDist, pPara->mbParagraphPunctation ? 1 : 0 ) ) )
685 nPropertyFlags |= 0x00080000;
686 if ( ( pPara->meBiDi == css::beans::PropertyState_DIRECT_VALUE ) ||
687 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_BiDi, pPara->mnBiDi ) ) )
688 nPropertyFlags |= 0x00200000;
689
690 sal_Int32 nBuRealSize = pPara->nBulletRealSize;
691 sal_Int16 nBulletFlags = pPara->nBulletFlags;
692
693 if ( pPara->bExtendedParameters )
694 nPropertyFlags |= pPara->nParaFlags;
695 else
696 {
697 nPropertyFlags |= 1; // turn off bullet explicit
698 nBulletFlags = 0;
699 }
700
701 // Write nTextOfs and nBullets
702 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_TextOfs, pPara->nTextOfs ) )
703 nPropertyFlags |= 0x100;
704 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, ParaAttr_BulletOfs, pPara->nBulletOfs ))
705 nPropertyFlags |= 0x400;
706
707 FontCollectionEntry aFontDescEntry( pPara->aFontDesc.Name, pPara->aFontDesc.Family, pPara->aFontDesc.Pitch, pPara->aFontDesc.CharSet );
708 sal_uInt16 nFontId = static_cast<sal_uInt16>(maFontCollection.GetId( aFontDescEntry ));
709
710 rOut.WriteUInt32( nCharCount )
711 .WriteUInt16( pPara->nDepth ) // Level
712 .WriteUInt32( nPropertyFlags ); // Paragraph Attribut Set
713
714 if ( nPropertyFlags & 0xf )
715 rOut.WriteInt16( nBulletFlags );
716 if ( nPropertyFlags & 0x80 )
717 rOut.WriteUInt16( pPara->cBulletId );
718 if ( nPropertyFlags & 0x10 )
719 rOut.WriteUInt16( nFontId );
720 if ( nPropertyFlags & 0x40 )
721 rOut.WriteInt16( nBuRealSize );
722 if ( nPropertyFlags & 0x20 )
723 {
724 sal_uInt32 nBulletColor = pPara->nBulletColor;
725 if ( nBulletColor == sal_uInt32(COL_AUTO) )
726 {
727 bool bIsDark = false;
728 css::uno::Any aAny;
729 if ( PropValue::GetPropertyValue( aAny, mXPagePropSet, "IsBackgroundDark", true ) )
730 aAny >>= bIsDark;
731 nBulletColor = bIsDark ? 0xffffff : 0x000000;
732 }
733 nBulletColor &= 0xffffff;
734 nBulletColor |= 0xfe000000;
735 rOut.WriteUInt32( nBulletColor );
736 }
737 if ( nPropertyFlags & 0x00000800 )
738 rOut.WriteUInt16( pPara->mnTextAdjust );
739 if ( nPropertyFlags & 0x00001000 )
740 rOut.WriteUInt16( nLineSpacing );
741 if ( nPropertyFlags & 0x00002000 )
742 rOut.WriteUInt16( pPara->mnLineSpacingTop );
743 if ( nPropertyFlags & 0x00004000 )
744 rOut.WriteUInt16( pPara->mnLineSpacingBottom );
745 if ( nPropertyFlags & 0x100 )
746 rOut.WriteUInt16( pPara->nTextOfs );
747 if ( nPropertyFlags & 0x400 )
748 rOut.WriteUInt16( pPara->nBulletOfs );
749 if ( nPropertyFlags & 0x000e0000 )
750 {
751 sal_uInt16 nAsianSettings = 0;
752 if ( pPara->mbForbiddenRules )
753 nAsianSettings |= 1;
754 if ( pPara->mbParagraphPunctation )
755 nAsianSettings |= 4;
756 rOut.WriteUInt16( nAsianSettings );
757 }
758 if ( nPropertyFlags & 0x200000 )
759 rOut.WriteUInt16( pPara->mnBiDi );
760 }
761}
762
763void PPTWriter::ImplWritePortions( SvStream& rOut, TextObj& rTextObj )
764{
765 sal_uInt32 nPropertyFlags;
766 int nInstance = rTextObj.GetInstance();
767
768 for ( sal_uInt32 i = 0; i < rTextObj.ParagraphCount(); ++i )
769 {
770 ParagraphObj* pPara = rTextObj.GetParagraph(i);
771 for ( std::vector<std::unique_ptr<PortionObj> >::const_iterator it = pPara->begin(); it != pPara->end(); ++it )
772 {
773 const PortionObj& rPortion = **it;
774 nPropertyFlags = 0;
775 sal_uInt32 nCharAttr = rPortion.mnCharAttr;
776 sal_uInt32 nCharColor = rPortion.mnCharColor;
777
778 if ( nCharColor == sal_uInt32(COL_AUTO) ) // nCharColor depends to the background color
779 {
780 bool bIsDark = false;
781 css::uno::Any aAny;
782 if ( PropValue::GetPropertyValue( aAny, mXPagePropSet, "IsBackgroundDark", true ) )
783 aAny >>= bIsDark;
784 nCharColor = bIsDark ? 0xffffff : 0x000000;
785 }
786
787 nCharColor &= 0xffffff;
788
789 /* the portion is using the embossed or engraved attribute, which we want to map to the relief feature of PPT.
790 Because the relief feature of PPT is dependent to the background color, such a mapping can not always be used. */
791 if ( nCharAttr & 0x200 )
792 {
793 sal_uInt32 nBackgroundColor = 0xffffff;
794
795 if ( !nCharColor ) // special treatment for
796 nCharColor = 0xffffff; // black fontcolor
797
798 css::uno::Any aAny;
799 css::drawing::FillStyle aFS( css::drawing::FillStyle_NONE );
800 if ( PropValue::GetPropertyValue( aAny, mXPropSet, "FillStyle" ) )
801 aAny >>= aFS;
802 switch( aFS )
803 {
804 case css::drawing::FillStyle_GRADIENT :
805 {
806 ::tools::Rectangle aRect( Point(), Size( 28000, 21000 ) );
807 EscherPropertyContainer aPropOpt( mpPptEscherEx->GetGraphicProvider(), mpPicStrm.get(), aRect );
808 aPropOpt.CreateGradientProperties( mXPropSet );
809 aPropOpt.GetOpt( ESCHER_Prop_fillColor385, nBackgroundColor );
810 }
811 break;
812 case css::drawing::FillStyle_SOLID :
813 {
814 if ( PropValue::GetPropertyValue( aAny, mXPropSet, "FillColor" ) )
815 nBackgroundColor = EscherEx::GetColor( *o3tl::doAccess<sal_uInt32>(aAny) );
816 }
817 break;
818 case css::drawing::FillStyle_NONE :
819 {
820 css::uno::Any aBackAny;
821 css::drawing::FillStyle aBackFS( css::drawing::FillStyle_NONE );
822 if ( PropValue::GetPropertyValue( aBackAny, mXBackgroundPropSet, "FillStyle" ) )
823 aBackAny >>= aBackFS;
824 switch( aBackFS )
825 {
826 case css::drawing::FillStyle_GRADIENT :
827 {
828 ::tools::Rectangle aRect( Point(), Size( 28000, 21000 ) );
829 EscherPropertyContainer aPropOpt( mpPptEscherEx->GetGraphicProvider(), mpPicStrm.get(), aRect );
830 aPropOpt.CreateGradientProperties( mXBackgroundPropSet );
831 aPropOpt.GetOpt( ESCHER_Prop_fillColor385, nBackgroundColor );
832 }
833 break;
834 case css::drawing::FillStyle_SOLID :
835 {
836 if ( PropValue::GetPropertyValue( aAny, mXBackgroundPropSet, "FillColor" ) )
837 nBackgroundColor = EscherEx::GetColor( *o3tl::doAccess<sal_uInt32>(aAny) );
838 }
839 break;
840 default:
841 break;
842 }
843 }
844 break;
845 default:
846 break;
847 }
848
849 sal_Int32 nB = nBackgroundColor & 0xff;
850 nB += static_cast<sal_uInt8>( nBackgroundColor >> 8 );
851 nB += static_cast<sal_uInt8>( nBackgroundColor >> 16 );
852 // if the background color is nearly black, relief can't been used, because the text would not be visible
853 if ( nB < 0x60 || ( nBackgroundColor != nCharColor ) )
854 {
855 nCharAttr &=~ 0x200;
856
857 // now check if the text is part of a group, and if the previous object has the same color than the fontcolor
858 // ( and if fillcolor is not available the background color ), it is sometimes
859 // not possible to export the 'embossed' flag
860 if ( ( GetCurrentGroupLevel() > 0 ) && ( GetCurrentGroupIndex() >= 1 ) )
861 {
862 css::uno::Reference< css::drawing::XShape > aGroupedShape( GetCurrentGroupAccess()->getByIndex( GetCurrentGroupIndex() - 1 ), uno::UNO_QUERY );
863 if( aGroupedShape.is() )
864 {
865 css::uno::Reference< css::beans::XPropertySet > aPropSetOfNextShape
866 ( aGroupedShape, css::uno::UNO_QUERY );
867 if ( aPropSetOfNextShape.is() )
868 {
869 if ( PropValue::GetPropertyValue( aAny, aPropSetOfNextShape,
870 "FillColor", true ) )
871 {
872 if ( nCharColor == EscherEx::GetColor( *o3tl::doAccess<sal_uInt32>(aAny) ) )
873 {
874 nCharAttr |= 0x200;
875 }
876 }
877 }
878 }
879 }
880 }
881 }
882 nCharColor |= 0xfe000000;
883 if ( nInstance == 4 ) // special handling for normal textobjects:
884 nPropertyFlags |= nCharAttr & 0x217; // not all attributes are inherited
885 else
886 {
887 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Bold, nCharAttr ) )
888 nPropertyFlags |= 1;
889 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Italic, nCharAttr ) )
890 nPropertyFlags |= 2;
891 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Underline, nCharAttr ) )
892 nPropertyFlags |= 4;
893 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Shadow, nCharAttr ) )
894 nPropertyFlags |= 0x10;
895 if ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Embossed, nCharAttr ) )
896 nPropertyFlags |= 512;
897 }
898 if ( rTextObj.HasExtendedBullets() )
899 {
900 nPropertyFlags |= ( i & 0x3f ) << 10 ;
901 nCharAttr |= ( i & 0x3f ) << 10;
902 }
903 if ( ( rPortion.meFontName == css::beans::PropertyState_DIRECT_VALUE ) ||
904 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Font, rPortion.mnFont ) ) )
905 nPropertyFlags |= 0x00010000;
906 if ( ( rPortion.meAsianOrComplexFont == css::beans::PropertyState_DIRECT_VALUE ) ||
907 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_AsianOrComplexFont, rPortion.mnAsianOrComplexFont ) ) )
908 nPropertyFlags |= 0x00200000;
909 if ( ( rPortion.meCharHeight == css::beans::PropertyState_DIRECT_VALUE ) ||
910 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_FontHeight, rPortion.mnCharHeight ) ) )
911 nPropertyFlags |= 0x00020000;
912 if ( ( rPortion.meCharColor == css::beans::PropertyState_DIRECT_VALUE ) ||
913 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_FontColor, nCharColor & 0xffffff ) ) )
914 nPropertyFlags |= 0x00040000;
915 if ( ( rPortion.meCharEscapement == css::beans::PropertyState_DIRECT_VALUE ) ||
916 ( mpStyleSheet->IsHardAttribute( nInstance, pPara->nDepth, CharAttr_Escapement, rPortion.mnCharEscapement ) ) )
917 nPropertyFlags |= 0x00080000;
918
919 sal_uInt32 nCharCount = rPortion.Count();
920
921 rOut.WriteUInt32( nCharCount )
922 .WriteUInt32( nPropertyFlags ); //PropertyFlags
923
924 if ( nPropertyFlags & 0xffff )
925 rOut.WriteUInt16( nCharAttr );
926 if ( nPropertyFlags & 0x00010000 )
927 rOut.WriteUInt16( rPortion.mnFont );
928 if ( nPropertyFlags & 0x00200000 )
929 rOut.WriteUInt16( rPortion.mnAsianOrComplexFont );
930 if ( nPropertyFlags & 0x00020000 )
931 rOut.WriteUInt16( rPortion.mnCharHeight );
932 if ( nPropertyFlags & 0x00040000 )
933 rOut.WriteUInt32( nCharColor );
934 if ( nPropertyFlags & 0x00080000 )
935 rOut.WriteInt16( rPortion.mnCharEscapement );
936 }
937 }
938}
939
940/**
941 * Loads and converts text from shape, value is stored in mnTextSize.
942 */
943bool PPTWriter::ImplGetText()
944{
945 mnTextSize = 0;
946 mbFontIndependentLineSpacing = false;
947 mXText.set( mXShape, css::uno::UNO_QUERY );
948
949 if ( mXText.is() )
950 {
951 mnTextSize = mXText->getString().getLength();
952 css::uno::Any aAny;
953 if ( GetPropertyValue( aAny, mXPropSet, "FontIndependentLineSpacing", true ) )
954 aAny >>= mbFontIndependentLineSpacing;
955 }
956 return ( mnTextSize != 0 );
957}
958
959void PPTWriter::ImplFlipBoundingBox( EscherPropertyContainer& rPropOpt )
960{
961 if ( mnAngle < 0 )
962 mnAngle = ( 36000 + mnAngle ) % 36000;
963 else
964 mnAngle = ( 36000 - ( mnAngle % 36000 ) );
965
966 double fCos = cos( static_cast<double>(mnAngle) * F_PI18000(3.14159265358979323846/18000.0) );
967 double fSin = sin( static_cast<double>(mnAngle) * F_PI18000(3.14159265358979323846/18000.0) );
968
969 double fWidthHalf = maRect.GetWidth() / 2.0;
970 double fHeightHalf = maRect.GetHeight() / 2.0;
971
972 double fXDiff = fCos * fWidthHalf + fSin * (-fHeightHalf);
973 double fYDiff = - ( fSin * fWidthHalf - fCos * ( -fHeightHalf ) );
974
975 maRect.Move( static_cast<sal_Int32>( -( fWidthHalf - fXDiff ) ), static_cast<sal_Int32>( - ( fHeightHalf + fYDiff ) ) );
976 mnAngle *= 655;
977 mnAngle += 0x8000;
978 mnAngle &=~0xffff; // round nAngle to full grads
979 rPropOpt.AddOpt( ESCHER_Prop_Rotation4, mnAngle );
980
981 if ( ( mnAngle >= ( 45 << 16 ) && mnAngle < ( 135 << 16 ) ) ||
982 ( mnAngle >= ( 225 << 16 ) && mnAngle < ( 315 << 16 ) ) )
983 {
984 // Maddeningly, in those two areas of PPT is the BoundingBox already
985 // vertical. Therefore, we need to put down it BEFORE THE ROTATION.
986 css::awt::Point aTopLeft( static_cast<sal_Int32>( maRect.Left() + fWidthHalf - fHeightHalf ), static_cast<sal_Int32>( maRect.Top() + fHeightHalf - fWidthHalf ) );
987 const long nRotatedWidth(maRect.GetHeight());
988 const long nRotatedHeight(maRect.GetWidth());
989 const Size aNewSize(nRotatedWidth, nRotatedHeight);
990 maRect = ::tools::Rectangle( Point( aTopLeft.X, aTopLeft.Y ), aNewSize );
991 }
992}
993
994void PPTWriter::ImplAdjustFirstLineLineSpacing( TextObj& rTextObj, EscherPropertyContainer& rPropOpt )
995{
996 if ( mbFontIndependentLineSpacing )
997 return;
998
999 if ( !rTextObj.ParagraphCount() )
1000 return;
1001
1002 ParagraphObj* pPara = rTextObj.GetParagraph(0);
1003 if ( pPara->empty() )
1004 return;
1005
1006 const PortionObj& rPortion = pPara->front();
1007 sal_Int16 nLineSpacing = pPara->mnLineSpacing;
1008 const FontCollectionEntry* pDesc = maFontCollection.GetById( rPortion.mnFont );
1009 if ( pDesc )
1010 nLineSpacing = static_cast<sal_Int16>( static_cast<double>(nLineSpacing) * pDesc->Scaling + 0.5 );
1011
1012 if ( ( nLineSpacing > 0 ) && ( nLineSpacing < 100 ) )
1013 {
1014 double fCharHeight = rPortion.mnCharHeight;
1015 fCharHeight *= 2540 / 72.0;
1016 fCharHeight *= 100 - nLineSpacing;
1017 fCharHeight /= 100;
1018
1019 sal_uInt32 nUpperDistance = 0;
1020 rPropOpt.GetOpt( ESCHER_Prop_dyTextTop130, nUpperDistance );
1021 nUpperDistance += static_cast< sal_uInt32 >( fCharHeight * 360.0 );
1022 rPropOpt.AddOpt( ESCHER_Prop_dyTextTop130, nUpperDistance );
1023 }
1024}
1025
1026void PPTWriter::ImplWriteTextStyleAtom( SvStream& rOut, int nTextInstance, sal_uInt32 nAtomInstance,
1027 TextRuleEntry* pTextRule, SvStream& rExtBuStr, EscherPropertyContainer* pPropOpt )
1028{
1029 PPTExParaSheet& rParaSheet = mpStyleSheet->GetParaSheet( nTextInstance );
1030
1031 rOut.WriteUInt32( ( EPP_TextHeaderAtom3999 << 16 ) | ( nAtomInstance << 4 ) ).WriteUInt32( 4 )
1032 .WriteInt32( nTextInstance );
1033
1034 if ( mbEmptyPresObj )
1035 mnTextSize = 0;
1036 if ( mbEmptyPresObj )
1037 return;
1038
1039 ParagraphObj* pPara;
1040 TextObjBinary aTextObj( mXText, nTextInstance, maFontCollection, static_cast<PPTExBulletProvider&>(*this) );
1041
1042 // leaving out EPP_TextCharsAtom w/o text - still write out
1043 // attribute info though
1044 if ( mnTextSize )
1045 aTextObj.Write( &rOut );
1046
1047 if ( pPropOpt && mType != "drawing.Table" )
1048 ImplAdjustFirstLineLineSpacing( aTextObj, *pPropOpt );
1049
1050 sal_uInt32 nSize, nPos = rOut.Tell();
1051
1052 rOut.WriteUInt32( EPP_StyleTextPropAtom4001 << 16 ).WriteUInt32( 0 );
1053 ImplWriteParagraphs( rOut, aTextObj );
1054 ImplWritePortions( rOut, aTextObj );
1055 nSize = rOut.Tell() - nPos;
1056 rOut.SeekRel( - ( static_cast<sal_Int32>(nSize) - 4 ) );
1057 rOut.WriteUInt32( nSize - 8 );
1058 rOut.SeekRel( nSize - 8 );
1059
1060 for ( sal_uInt32 i = 0; i < aTextObj.ParagraphCount(); ++i )
1061 {
1062 pPara = aTextObj.GetParagraph(i);
1063 for ( std::vector<std::unique_ptr<PortionObj> >::const_iterator it = pPara->begin(); it != pPara->end(); ++it )
1064 {
1065 const PortionObj& rPortion = **it;
1066 if ( rPortion.mpFieldEntry )
1067 {
1068 const FieldEntry* pFieldEntry = rPortion.mpFieldEntry.get();
1069
1070 switch ( pFieldEntry->nFieldType >> 28 )
1071 {
1072 case 1 :
1073 case 2 :
1074 {
1075 rOut.WriteUInt32( EPP_DateTimeMCAtom4087 << 16 ).WriteUInt32( 8 )
1076 .WriteUInt32( pFieldEntry->nFieldStartPos ) // TxtOffset to TxtField;
1077 .WriteUChar( pFieldEntry->nFieldType & 0xff ) // Type
1078 .WriteUChar( 0 ).WriteUInt16( 0 ); // PadBytes
1079 }
1080 break;
1081 case 3 :
1082 {
1083 rOut.WriteUInt32( EPP_SlideNumberMCAtom4056 << 16 ).WriteUInt32( 4 )
1084 .WriteUInt32( pFieldEntry->nFieldStartPos );
1085 }
1086 break;
1087 case 4 :
1088 {
1089 sal_uInt32 nPageIndex = 0;
1090 OUString aPageUrl;
1091 OUString aFile( pFieldEntry->aFieldUrl );
1092 OUString aTarget( pFieldEntry->aFieldUrl );
1093 INetURLObject aUrl( pFieldEntry->aFieldUrl );
1094 if ( INetProtocol::File == aUrl.GetProtocol() )
1095 aFile = aUrl.PathToFileName();
1096 else if ( INetProtocol::Smb == aUrl.GetProtocol() )
1097 {
1098 // Convert smb notation to '\\' and skip the 'smb:' part
1099 aFile = aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE).copy(4);
1100 aFile = aFile.replaceAll( "/", "\\" );
1101 aTarget = aFile;
1102 }
1103 else if ( pFieldEntry->aFieldUrl.startsWith("#") )
1104 {
1105 OUString aPage( INetURLObject::decode( pFieldEntry->aFieldUrl, INetURLObject::DecodeMechanism::WithCharset ) );
1106 aPage = aPage.copy( 1 );
1107
1108 std::vector<OUString>::const_iterator pIter = std::find(
1109 maSlideNameList.begin(),maSlideNameList.end(),aPage);
1110
1111 if ( pIter != maSlideNameList.end() )
1112 {
1113 nPageIndex = pIter - maSlideNameList.begin();
1114 aPageUrl = OUString::number(256 + nPageIndex) +
1115 "," +
1116 OUString::number(nPageIndex + 1) +
1117 ",Slide " +
1118 OUString::number(nPageIndex + 1);
1119 }
1120 }
1121 sal_uInt32 nHyperId(0);
1122 if ( !aPageUrl.isEmpty() )
1123 nHyperId = ImplInsertBookmarkURL( aPageUrl, 1 | ( nPageIndex << 8 ) | ( 1U << 31 ), pFieldEntry->aRepresentation, "", "", aPageUrl );
1124 else
1125 nHyperId = ImplInsertBookmarkURL( pFieldEntry->aFieldUrl, 2 | ( nHyperId << 8 ), aFile, aTarget, "", "" );
1126
1127 rOut.WriteUInt32( ( EPP_InteractiveInfo4082 << 16 ) | 0xf ).WriteUInt32( 24 )
1128 .WriteUInt32( EPP_InteractiveInfoAtom4083 << 16 ).WriteUInt32( 16 )
1129 .WriteUInt32( 0 ) // soundref
1130 .WriteUInt32( nHyperId ) // hyperlink id
1131 .WriteUChar( 4 ) // hyperlink action
1132 .WriteUChar( 0 ) // ole verb
1133 .WriteUChar( 0 ) // jump
1134 .WriteUChar( 0 ) // flags
1135 .WriteUChar( 8 ) // hyperlink type ?
1136 .WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 )
1137 .WriteUInt32( EPP_TxInteractiveInfoAtom4063 << 16 ).WriteUInt32( 8 )
1138 .WriteUInt32( pFieldEntry->nFieldStartPos )
1139 .WriteUInt32( pFieldEntry->nFieldEndPos );
1140 }
1141 break;
1142 case 5 :
1143 {
1144 rOut.WriteUInt32( EPP_GenericDateMCAtom4088 << 16 ).WriteUInt32( 4 )
1145 .WriteUInt32( pFieldEntry->nFieldStartPos );
1146 }
1147 break;
1148 case 6 :
1149 {
1150 rOut.WriteUInt32( EPP_HeaderMCAtom4089 << 16 ).WriteUInt32( 4 )
1151 .WriteUInt32( pFieldEntry->nFieldStartPos );
1152 }
1153 break;
1154 case 7 :
1155 {
1156 rOut.WriteUInt32( EPP_FooterMCAtom4090 << 16 ).WriteUInt32( 4 )
1157 .WriteUInt32( pFieldEntry->nFieldStartPos );
1158 }
1159 break;
1160 default:
1161 break;
1162 }
1163 }
1164 }
1165 }
1166
1167 aTextObj.WriteTextSpecInfo( &rOut );
1168
1169 // write Star Office Default TabSizes (if necessary)
1170 if ( aTextObj.ParagraphCount() )
1171 {
1172 pPara = aTextObj.GetParagraph(0);
1173 sal_uInt32 nParaFlags = 0x1f;
1174 sal_Int16 nMask, nNumberingRule[ 10 ];
1175 const sal_uInt32 nTabs = pPara->maTabStop.getLength();
1176 const auto& rTabStops = pPara->maTabStop;
1177
1178 for ( sal_uInt32 i = 0; i < aTextObj.ParagraphCount(); ++i )
1179 {
1180 pPara = aTextObj.GetParagraph(i);
1181 if ( pPara->bExtendedParameters )
1182 {
1183 nMask = 1 << pPara->nDepth;
1184 if ( nParaFlags & nMask )
1185 {
1186 nParaFlags &=~ nMask;
1187 if ( ( rParaSheet.maParaLevel[ pPara->nDepth ].mnTextOfs != pPara->nTextOfs ) ||
1188 ( rParaSheet.maParaLevel[ pPara->nDepth ].mnBulletOfs != pPara->nBulletOfs ) )
1189 {
1190 nParaFlags |= nMask << 16;
1191 nNumberingRule[ pPara->nDepth << 1 ] = pPara->nTextOfs;
1192 nNumberingRule[ ( pPara->nDepth << 1 ) + 1 ] = static_cast<sal_Int16>(pPara->nBulletOfs);
1193 }
1194 }
1195 }
1196 }
1197 nParaFlags >>= 16;
1198
1199 sal_Int32 nDefaultTabSizeSrc = 2011; // I've no idea where this number came from, honestly
1200 const uno::Reference< beans::XPropertySet > xPropSet( mXModel, uno::UNO_QUERY );
1201 if ( xPropSet.is() )
1202 {
1203 if(ImplGetPropertyValue( xPropSet, "TabStop" ))
1204 {
1205 sal_Int32 nTabStop( 0 );
1206 if ( mAny >>= nTabStop )
1207 nDefaultTabSizeSrc = nTabStop;
1208 }
1209 }
1210 const sal_uInt32 nDefaultTabSize = MapSize( awt::Size( nDefaultTabSizeSrc, 1 ) ).Width;
1211 sal_uInt32 nDefaultTabs = std::abs( maRect.GetWidth() ) / nDefaultTabSize;
1212 if ( nTabs )
1213 nDefaultTabs -= static_cast<sal_Int32>( convertTwipToMasterUnit(rTabStops[ nTabs - 1 ].Position) / nDefaultTabSize );
1214 if ( static_cast<sal_Int32>(nDefaultTabs) < 0 )
1215 nDefaultTabs = 0;
1216
1217 sal_uInt32 nTabCount = nTabs + nDefaultTabs;
1218 sal_uInt32 i, nTextRulerAtomFlags = 0;
1219
1220 if ( nTabCount )
1221 nTextRulerAtomFlags |= 4;
1222 if ( nParaFlags )
1223 nTextRulerAtomFlags |= ( ( nParaFlags << 3 ) | ( nParaFlags << 8 ) );
1224
1225 if ( nTextRulerAtomFlags )
1226 {
1227 SvStream* pRuleOut = &rOut;
1228 if ( pTextRule )
1229 {
1230 pTextRule->pOut.reset( new SvMemoryStream( 0x100, 0x100 ) );
1231 pRuleOut = pTextRule->pOut.get();
1232 }
1233
1234 sal_uInt32 nRulePos = pRuleOut->Tell();
1235 pRuleOut->WriteUInt32( EPP_TextRulerAtom4006 << 16 ).WriteUInt32( 0 );
1236 pRuleOut->WriteUInt32( nTextRulerAtomFlags );
1237 if ( nTextRulerAtomFlags & 4 )
1238 {
1239 pRuleOut->WriteUInt16( nTabCount );
1240 for ( const css::style::TabStop& rTabStop : rTabStops )
1241 {
1242 sal_uInt16 nPosition = static_cast<sal_uInt16>( convertTwipToMasterUnit(rTabStop.Position) );
1243 sal_uInt16 nType;
1244 switch ( rTabStop.Alignment )
1245 {
1246 case css::style::TabAlign_DECIMAL : nType = 3; break;
1247 case css::style::TabAlign_RIGHT : nType = 2; break;
1248 case css::style::TabAlign_CENTER : nType = 1; break;
1249
1250 case css::style::TabAlign_LEFT :
1251 default: nType = 0;
1252 }
1253 pRuleOut->WriteUInt16( nPosition )
1254 .WriteUInt16( nType );
1255 }
1256
1257 sal_uInt32 nWidth = 1;
1258 if ( nTabs )
1259 nWidth += static_cast<sal_Int32>( convertTwipToMasterUnit(rTabStops[ nTabs - 1 ].Position) / nDefaultTabSize );
1260 nWidth *= nDefaultTabSize;
1261 for ( i = 0; i < nDefaultTabs; i++, nWidth += nDefaultTabSize )
1262 pRuleOut->WriteUInt32( nWidth );
1263 }
1264 for ( i = 0; i < 5; i++ )
1265 {
1266 if ( nTextRulerAtomFlags & ( 8 << i ) )
1267 pRuleOut->WriteInt16( nNumberingRule[ i << 1 ] );
1268 if ( nTextRulerAtomFlags & ( 256 << i ) )
1269 pRuleOut->WriteInt16( nNumberingRule[ ( i << 1 ) + 1 ] );
1270 }
1271 sal_uInt32 nBufSize = pRuleOut->Tell() - nRulePos;
1272 pRuleOut->SeekRel( - ( static_cast<sal_Int32>(nBufSize) - 4 ) );
1273 pRuleOut->WriteUInt32( nBufSize - 8 );
1274 pRuleOut->SeekRel( nBufSize - 8 );
1275 }
1276 }
1277 if ( !aTextObj.HasExtendedBullets() )
1278 return;
1279
1280 if ( !aTextObj.ParagraphCount() )
1281 return;
1282
1283 sal_uInt32 nNumberingType = 0, nPos2 = rExtBuStr.Tell();
1284
1285 rExtBuStr.WriteUInt32( EPP_PST_ExtendedParagraphAtom4012 << 16 ).WriteUInt32( 0 );
1286
1287 for ( sal_uInt32 i = 0; i < aTextObj.ParagraphCount(); ++i )
1288 {
1289 ParagraphObj* pBulletPara = aTextObj.GetParagraph(i);
1290 sal_uInt32 nBulletFlags = 0;
1291 sal_uInt16 nBulletId = pBulletPara->nBulletId;
1292
1293 if ( pBulletPara->bExtendedBulletsUsed )
1294 {
1295 nBulletFlags = 0x800000;
1296 if ( pBulletPara->nNumberingType != SVX_NUM_BITMAP )
1297 nBulletFlags = 0x3000000;
1298 }
1299 rExtBuStr.WriteUInt32( nBulletFlags );
1300
1301 if ( nBulletFlags & 0x800000 )
1302 rExtBuStr.WriteUInt16( nBulletId );
1303 if ( nBulletFlags & 0x1000000 )
1304 {
1305 switch( pBulletPara->nNumberingType )
1306 {
1307 case SVX_NUM_NUMBER_NONE :
1308 case SVX_NUM_CHAR_SPECIAL :
1309 nNumberingType = 0;
1310 break;
1311 case SVX_NUM_CHARS_UPPER_LETTER :
1312 case SVX_NUM_CHARS_UPPER_LETTER_N :
1313 case SVX_NUM_CHARS_LOWER_LETTER :
1314 case SVX_NUM_CHARS_LOWER_LETTER_N :
1315 case SVX_NUM_ROMAN_UPPER :
1316 case SVX_NUM_ROMAN_LOWER :
1317 case SVX_NUM_ARABIC :
1318 case SVX_NUM_NUMBER_UPPER_ZH:
1319 case SVX_NUM_CIRCLE_NUMBER:
1320 case SVX_NUM_NUMBER_UPPER_ZH_TW:
1321 case SVX_NUM_NUMBER_LOWER_ZH:
1322 case SVX_NUM_FULL_WIDTH_ARABIC:
1323 nNumberingType = pBulletPara->nMappedNumType;
1324 break;
1325
1326 case SVX_NUM_BITMAP :
1327 nNumberingType = 0;
1328 break;
1329 default: break;
1330 }
1331 rExtBuStr.WriteUInt32( nNumberingType );
1332 }
1333 if ( nBulletFlags & 0x2000000 )
1334 rExtBuStr.WriteUInt16( pBulletPara->nStartWith );
1335 rExtBuStr.WriteUInt32( 0 ).WriteUInt32( 0 );
1336 }
1337 sal_uInt32 nBulletSize = ( rExtBuStr.Tell() - nPos2 ) - 8;
1338 rExtBuStr.SeekRel( - ( static_cast<sal_Int32>(nBulletSize) + 4 ) );
1339 rExtBuStr.WriteUInt32( nBulletSize );
1340 rExtBuStr.SeekRel( nBulletSize );
1341}
1342
1343void PPTWriter::ImplWriteClickAction( SvStream& rSt, css::presentation::ClickAction eCa, bool bMediaClickAction )
1344{
1345 sal_uInt32 nSoundRef = 0; // a reference to a sound in the sound collection, or NULL.
1346 sal_uInt32 nHyperLinkID = 0;// a persistent unique identifier to an external hyperlink object (only valid when action == HyperlinkAction).
1347 sal_uInt8 nAction = 0; // Action See Action Table
1348 sal_uInt8 const nOleVerb = 0; // OleVerb Only valid when action == OLEAction. OLE verb to use, 0 = first verb, 1 = second verb, etc.
1349 sal_uInt8 nJump = 0; // Jump See Jump Table
1350 sal_uInt8 const nFlags = 0; // Bit 1: Animated. If 1, then button is animated
1351 // Bit 2: Stop sound. If 1, then stop current sound when button is pressed.
1352 // Bit 3: CustomShowReturn. If 1, and this is a jump to custom show, then return to this slide after custom show.
1353 sal_uInt8 nHyperLinkType = 0;// HyperlinkType a value from the LinkTo enum, such as LT_URL (only valid when action == HyperlinkAction).
1354
1355 OUString aFile;
1356
1357 /*
1358 Action Table: Action Value
1359 NoAction 0
1360 MacroAction 1
1361 RunProgramAction 2
1362 JumpAction 3
1363 HyperlinkAction 4
1364 OLEAction 5
1365 MediaAction 6
1366 CustomShowAction 7
1367
1368 Jump Table: Jump Value
1369 NoJump 0
1370 NextSlide, 1
1371 PreviousSlide, 2
1372 FirstSlide, 3
1373 LastSlide, 4
1374 LastSlideViewed 5
1375 EndShow 6
1376 */
1377
1378 if ( bMediaClickAction )
1379 nAction = 6;
1380 else switch( eCa )
1381 {
1382 case css::presentation::ClickAction_STOPPRESENTATION :
1383 nJump += 2;
1384 [[fallthrough]];
1385 case css::presentation::ClickAction_LASTPAGE :
1386 nJump++;
1387 [[fallthrough]];
1388 case css::presentation::ClickAction_FIRSTPAGE :
1389 nJump++;
1390 [[fallthrough]];
1391 case css::presentation::ClickAction_PREVPAGE :
1392 nJump++;
1393 [[fallthrough]];
1394 case css::presentation::ClickAction_NEXTPAGE :
1395 {
1396 nJump++;
1397 nAction = 3;
1398 }
1399 break;
1400 case css::presentation::ClickAction_SOUND :
1401 {
1402 if ( ImplGetPropertyValue( "Bookmark" ) )
1403 nSoundRef = maSoundCollection.GetId( *o3tl::doAccess<OUString>(mAny) );
1404 }
1405 break;
1406 case css::presentation::ClickAction_PROGRAM :
1407 {
1408 if ( ImplGetPropertyValue( "Bookmark" ) )
1409 {
1410 INetURLObject aUrl( *o3tl::doAccess<OUString>(mAny) );
1411 if ( INetProtocol::File == aUrl.GetProtocol() )
1412 {
1413 aFile = aUrl.PathToFileName();
1414 nAction = 2;
1415 }
1416 }
1417 }
1418 break;
1419
1420 case css::presentation::ClickAction_BOOKMARK :
1421 {
1422 if ( ImplGetPropertyValue( "Bookmark" ) )
1423 {
1424 OUString aBookmark( *o3tl::doAccess<OUString>(mAny) );
1425 sal_uInt32 nIndex = 0;
1426 for ( const auto& rSlideName : maSlideNameList )
1427 {
1428 if ( rSlideName == aBookmark )
1429 {
1430 // Bookmark is a link to a document page
1431 nAction = 4;
1432 nHyperLinkType = 7;
1433
1434 OUString aHyperString = OUString::number(256 + nIndex) +
1435 "," +
1436 OUString::number(nIndex + 1) +
1437 ",Slide " +
1438 OUString::number(nIndex + 1);
1439 nHyperLinkID = ImplInsertBookmarkURL( aHyperString, 1 | ( nIndex << 8 ) | ( 1U << 31 ), aBookmark, "", "", aHyperString );
1440 }
1441 nIndex++;
1442 }
1443 }
1444 }
1445 break;
1446
1447 case css::presentation::ClickAction_DOCUMENT :
1448 {
1449 if ( ImplGetPropertyValue( "Bookmark" ) )
1450 {
1451 OUString aBookmark( *o3tl::doAccess<OUString>(mAny) );
1452 if ( !aBookmark.isEmpty() )
1453 {
1454 nAction = 4;
1455 nHyperLinkType = 8;
1456
1457 OUString aBookmarkFile( aBookmark );
1458 INetURLObject aUrl( aBookmark );
1459 if ( INetProtocol::File == aUrl.GetProtocol() )
1460 aBookmarkFile = aUrl.PathToFileName();
1461 nHyperLinkID = ImplInsertBookmarkURL( aBookmark, sal_uInt32(2 | ( 1U << 31 )), aBookmarkFile, aBookmark, "", "" );
1462 }
1463 }
1464 }
1465 break;
1466
1467 case css::presentation::ClickAction_INVISIBLE :
1468 case css::presentation::ClickAction_VERB :
1469 case css::presentation::ClickAction_VANISH :
1470 case css::presentation::ClickAction_MACRO :
1471 default :
1472 break;
1473 }
1474
1475 sal_uInt32 nContainerSize = 24;
1476 if ( nAction == 2 )
1477 nContainerSize += ( aFile.getLength() * 2 ) + 8;
1478 rSt.WriteUInt32( ( EPP_InteractiveInfo4082 << 16 ) | 0xf ).WriteUInt32( nContainerSize )
1479 .WriteUInt32( EPP_InteractiveInfoAtom4083 << 16 ).WriteUInt32( 16 )
1480 .WriteUInt32( nSoundRef )
1481 .WriteUInt32( nHyperLinkID )
1482 .WriteUChar( nAction )
1483 .WriteUChar( nOleVerb )
1484 .WriteUChar( nJump )
1485 .WriteUChar( nFlags )
1486 .WriteUInt32( nHyperLinkType );
1487
1488 if ( nAction == 2 ) // run program Action
1489 {
1490 sal_Int32 nLen = aFile.getLength();
1491 rSt.WriteUInt32( ( EPP_CString4026 << 16 ) | 0x20 ).WriteUInt32( nLen * 2 );
1492 for ( sal_Int32 i = 0; i < nLen; i++ )
1493 rSt.WriteUInt16( aFile[i] );
1494 }
1495
1496 rSt.WriteUInt32( ( EPP_InteractiveInfo4082 << 16 ) | 0x1f ).WriteUInt32( 24 ) // Mouse Over Action
1497 .WriteUInt32( EPP_InteractiveInfo4082 << 16 ).WriteUInt32( 16 );
1498 for ( int i = 0; i < 4; i++, rSt.WriteUInt32( 0 ) ) ;
1499}
1500
1501bool PPTWriter::ImplGetEffect( const css::uno::Reference< css::beans::XPropertySet > & rPropSet,
1502 css::presentation::AnimationEffect& eEffect,
1503 css::presentation::AnimationEffect& eTextEffect,
1504 bool& bIsSound )
1505{
1506 css::uno::Any aAny;
1507 if ( GetPropertyValue( aAny, rPropSet, "Effect" ) )
9
Taking false branch
1508 aAny >>= eEffect;
1509 else
1510 eEffect = css::presentation::AnimationEffect_NONE;
1511
1512 if ( GetPropertyValue( aAny, rPropSet, "TextEffect" ) )
10
Taking false branch
1513 aAny >>= eTextEffect;
1514 else
1515 eTextEffect = css::presentation::AnimationEffect_NONE;
1516 if ( GetPropertyValue( aAny, rPropSet, "SoundOn" ) )
11
Taking true branch
1517 aAny >>= bIsSound;
1518 else
1519 bIsSound = false;
1520
1521 bool bHasEffect = ( ( eEffect
11.1
'eEffect' is equal to 'AnimationEffect_NONE'
!= css::presentation::AnimationEffect_NONE )
12
Assigned value is garbage or undefined
1522 || ( eTextEffect
11.2
'eTextEffect' is equal to 'AnimationEffect_NONE'
!= css::presentation::AnimationEffect_NONE )
1523 || bIsSound );
1524 return bHasEffect;
1525};
1526
1527bool PPTWriter::ImplCreatePresentationPlaceholder( const bool bMasterPage,
1528 const sal_uInt32 nStyleInstance, const sal_uInt8 nPlaceHolderId )
1529{
1530 bool bRet = ImplGetText();
1531 if ( bRet && bMasterPage )
1532 {
1533 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
1534 sal_uInt32 nPresShapeID = mpPptEscherEx->GenerateShapeId();
1535 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle1,
1536 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty, nPresShapeID );
1537 EscherPropertyContainer aPropOpt;
1538 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x50001 );
1539 mnTxId += 0x60;
1540 aPropOpt.AddOpt( ESCHER_Prop_lTxid128, mnTxId );
1541 aPropOpt.AddOpt( ESCHER_Prop_AnchorText135, ESCHER_AnchorMiddle );
1542 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x110001 );
1543 aPropOpt.AddOpt( ESCHER_Prop_lineColor448, 0x8000001 );
1544 aPropOpt.AddOpt( ESCHER_Prop_shadowColor513, 0x8000002 );
1545 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1546 sal_uInt32 nLineFlags = 0x90001;
1547 if ( aPropOpt.GetOpt( ESCHER_Prop_fNoLineDrawDash511, nLineFlags ) )
1548 nLineFlags |= 0x10001; // draw dashed line if no line
1549 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, nLineFlags );
1550
1551 SvMemoryStream aExtBu( 0x200, 0x200 );
1552 SvMemoryStream aClientTextBox( 0x200, 0x200 );
1553 ImplWriteTextStyleAtom( aClientTextBox, nStyleInstance, 0, nullptr, aExtBu, &aPropOpt );
1554
1555 mnTxId += 0x60;
1556 aPropOpt.CreateTextProperties( mXPropSet, mnTxId );
1557 aPropOpt.CreateShapeProperties( mXShape );
1558 aPropOpt.Commit( *mpStrm );
1559 mpPptEscherEx->AddAtom( 8, ESCHER_ClientAnchor0xF010u );
1560 mpStrm->WriteInt16( maRect.Top() ).WriteInt16( maRect.Left() ).WriteInt16( maRect.Right() ).WriteInt16( maRect.Bottom() ); // top, left, right, bottom ????
1561 mpPptEscherEx->OpenContainer( ESCHER_ClientData0xF011u );
1562 mpPptEscherEx->AddAtom( 8, EPP_OEPlaceholderAtom3011 );
1563 mpStrm->WriteUInt32( 0 ) // PlacementID
1564 .WriteUChar( nPlaceHolderId ) // PlaceHolderID
1565 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
1566 .WriteUInt16( 0 ); // padword
1567 mpPptEscherEx->CloseContainer(); // ESCHER_ClientData
1568
1569 if ( aClientTextBox.Tell() )
1570 {
1571 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox0xF00Du << 16 ) | 0xf )
1572 .WriteUInt32( aClientTextBox.Tell() );
1573
1574 mpStrm->WriteBytes(aClientTextBox.GetData(), aClientTextBox.Tell());
1575 }
1576 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1577 }
1578 else
1579 bRet = false;
1580 return bRet;
1581}
1582
1583void PPTWriter::ImplCreateShape( sal_uInt32 nType, ShapeFlag nFlags, EscherSolverContainer& rSolver )
1584{
1585 sal_uInt32 nId = mpPptEscherEx->GenerateShapeId();
1586 mpPptEscherEx->AddShape( nType, nFlags, nId );
1587 rSolver.AddShape( mXShape, nId );
1588}
1589
1590void PPTWriter::ImplCreateTextShape( EscherPropertyContainer& rPropOpt, EscherSolverContainer& rSolver, bool bFill )
1591{
1592 mnTextStyle = EPP_TEXTSTYLE_TEXT0x00001000;
1593 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
1594 ImplCreateShape( ESCHER_ShpInst_TextBox202, ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty, rSolver );
1595 if ( bFill )
1596 rPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1597 if ( ImplGetText() )
1598 {
1599 mnTxId += 0x60;
1600 rPropOpt.CreateTextProperties( mXPropSet, mnTxId );
1601 }
1602}
1603
1604void PPTWriter::ImplWritePage( const PHLayout& rLayout, EscherSolverContainer& aSolverContainer, PageType ePageType, bool bMasterPage, int nPageNumber )
1605{
1606 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
1607 // sal_uInt32 nGroupLevel = 0;
1608
1609 sal_uInt32 nGroups, nShapes, nShapeCount, nPer, nLastPer, nIndices, nOlePictureId;
1610 css::awt::Point aTextRefPoint;
1611
1612 nShapes = mXShapes->getCount();
1613 ResetGroupTable( nShapes );
1614
1615 nIndices = nLastPer = nShapeCount = 0;
1616
1617 bool bIsTitlePossible = true; // powerpoint is not able to handle more than one title
1618
1619 sal_uInt32 nOutlinerCount = 0; // the outline objects have to conform to the layout,
1620 sal_uInt32 nPrevTextStyle = 0; // there are no more than two allowed
1621
1622 nOlePictureId = 0;
1623
1624 bool bAdditionalText = false;
1625
1626 bool bSecOutl = false;
1627 sal_uInt32 nPObjects = 0;
1628
1629 std::unique_ptr<SvMemoryStream> pClientTextBox;
1630 std::unique_ptr<SvMemoryStream> pClientData;
1631
1632 while( GetNextGroupEntry() )
1
Loop condition is true. Entering loop body
1633 {
1634 nShapeCount++;
1635
1636 nPer = ( 5 * nShapeCount ) / nShapes;
1637 if ( nPer != nLastPer )
2
Assuming 'nPer' is equal to 'nLastPer'
3
Taking false branch
1638 {
1639 nLastPer = nPer;
1640 sal_uInt32 nValue = mnPagesWritten * 5 + nPer;
1641 if ( nValue > mnStatMaxValue )
1642 nValue = mnStatMaxValue;
1643 if ( mbStatusIndicator && ( nValue > mnLatestStatValue ) )
1644 {
1645 mXStatusIndicator->setValue( nValue );
1646 mnLatestStatValue = nValue;
1647 }
1648 }
1649 nGroups = GetGroupsClosed();
1650 for ( sal_uInt32 i = 0; i < nGroups; i++, mpPptEscherEx->LeaveGroup() ) ;
4
Assuming 'i' is >= 'nGroups'
5
Loop condition is false. Execution continues on line 1652
1651
1652 if ( GetShapeByIndex( GetCurrentGroupIndex(), true ) )
6
Assuming the condition is true
7
Taking true branch
1653 {
1654 bool bIsSound;
1655 bool bMediaClickAction = false;
1656 css::presentation::AnimationEffect eAe;
1657 css::presentation::AnimationEffect eTe;
1658
1659 bool bEffect = ImplGetEffect( mXPropSet, eAe, eTe, bIsSound );
8
Calling 'PPTWriter::ImplGetEffect'
1660 css::presentation::ClickAction eCa = css::presentation::ClickAction_NONE;
1661 if ( ImplGetPropertyValue( "OnClick" ) )
1662 mAny >>= eCa;
1663
1664 bool bGroup = mType == "drawing.Group";
1665 bool bOpenBezier = mType == "drawing.OpenBezier";
1666 bool bClosedBezier = mType == "drawing.ClosedBezier";
1667 bool bPolyPolygon = mType == "drawing.PolyPolygon";
1668 bool bPolyLine = mType == "drawing.PolyLine";
1669
1670 const css::awt::Size aSize100thmm( mXShape->getSize() );
1671 const css::awt::Point aPoint100thmm( mXShape->getPosition() );
1672 ::tools::Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
1673 EscherPropertyContainer aPropOpt( mpPptEscherEx->GetGraphicProvider(), mpPicStrm.get(), aRect100thmm );
1674
1675 if ( bGroup )
1676 {
1677 css::uno::Reference< css::container::XIndexAccess >
1678 aXIndexAccess( mXShape, css::uno::UNO_QUERY );
1679 if ( EnterGroup( aXIndexAccess ) )
1680 {
1681 std::unique_ptr<SvMemoryStream> pTmp;
1682 if ( eCa != css::presentation::ClickAction_NONE )
1683 {
1684 pTmp.reset(new SvMemoryStream(0x200, 0x200));
1685 ImplWriteClickAction( *pTmp, eCa, bMediaClickAction );
1686 }
1687 sal_uInt32 nShapeId = mpPptEscherEx->EnterGroup(&maRect, pTmp.get());
1688 aSolverContainer.AddShape( mXShape, nShapeId );
1689 }
1690 }
1691 else
1692 {
1693 bool bIsFontwork = false;
1694 bool bIsHatching = false;
1695 css::uno::Any aAny;
1696 if ( GetPropertyValue( aAny, mXPropSet, "IsFontwork", true ) )
1697 aAny >>= bIsFontwork;
1698 if ( GetPropertyValue( aAny, mXPropSet, "FillStyle", true ) )
1699 {
1700 css::drawing::FillStyle eFS;
1701 aAny >>= eFS;
1702 bIsHatching = eFS == css::drawing::FillStyle_HATCH;
1703 }
1704 if ( bIsHatching || bIsFontwork || ( mType == "drawing.Measure" ) || ( mType == "drawing.Caption" ) )
1705 {
1706 if ( ImplGetPropertyValue( "BoundRect" ) )
1707 {
1708 auto aRect = o3tl::doAccess<css::awt::Rectangle>(mAny);
1709 maPosition = MapPoint( css::awt::Point( aRect->X, aRect->Y ) );
1710 maSize = MapSize( css::awt::Size( aRect->Width, aRect->Height ) );
1711 maRect = ::tools::Rectangle( Point( maPosition.X, maPosition.Y ), Size( maSize.Width, maSize.Height ) );
1712 }
1713 mType = "drawing.dontknow";
1714 }
1715 }
1716 sal_uInt8 nPlaceHolderAtom = EPP_PLACEHOLDER_NONE0;
1717
1718 mnTextSize = 0;
1719 mnTextStyle = EPP_TEXTSTYLE_NORMAL0x00000001;
1720
1721 if ( mType == "drawing.Custom" )
1722 {
1723 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
1724 ShapeFlag nMirrorFlags;
1725 OUString sCustomShapeType;
1726 MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( mXShape, nMirrorFlags, sCustomShapeType );
1727 if ( sCustomShapeType == "col-502ad400" || sCustomShapeType == "col-60da8460" )
1728 { // sj: creating metafile for customshapes that can't be saved to ms format properly
1729 ImplCreateShape( ESCHER_ShpInst_PictureFrame75,
1730 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1731 aSolverContainer );
1732 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "MetaFile", false ) )
1733 {
1734 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
1735 SdrObject* pObj = GetSdrObjectFromXShape( mXShape );
1736 if ( pObj )
1737 {
1738 ::tools::Rectangle aBound = pObj->GetCurrentBoundRect();
1739 maPosition = MapPoint( css::awt::Point( aBound.Left(), aBound.Top() ) );
1740 maSize = MapSize( css::awt::Size ( aBound.GetWidth(), aBound.GetHeight() ) );
1741 maRect = ::tools::Rectangle( Point( maPosition.X, maPosition.Y ), Size( maSize.Width, maSize.Height ) );
1742 mnAngle = 0;
1743 }
1744 }
1745 }
1746 else
1747 {
1748 ImplCreateShape( eShapeType,
1749 nMirrorFlags | ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1750 aSolverContainer );
1751 aPropOpt.CreateCustomShapeProperties( eShapeType, mXShape );
1752 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape);
1753 if ( ImplGetText() )
1754 {
1755 if ( !aPropOpt.IsFontWork() )
1756 {
1757 mnTxId += 0x60;
1758 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, true );
1759 }
1760 }
1761 }
1762 }
1763 else if ( mType == "drawing.Rectangle" )
1764 {
1765 sal_Int32 nRadius = 0;
1766 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
1767 if ( ImplGetPropertyValue( "CornerRadius" ) )
1768 {
1769 mAny >>= nRadius;
1770 nRadius = MapSize( css::awt::Size( nRadius, 0 ) ).Width;
1771 }
1772 if ( nRadius )
1773 {
1774 ImplCreateShape( ESCHER_ShpInst_RoundRectangle2,
1775 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1776 aSolverContainer );
1777 sal_Int32 nLength = maRect.GetWidth();
1778 if ( nLength > maRect.GetHeight() )
1779 nLength = maRect.GetHeight();
1780 nLength >>= 1;
1781 if ( nRadius >= nLength )
1782 nRadius = 0x2a30; // 0x2a30 is PPTs maximum radius
1783 else
1784 {
1785 if (nLength != 0)
1786 nRadius = ( 0x2a30 * nRadius ) / nLength;
1787 else
1788 nRadius = 0x2a30; // 0x2a30 is PPTs maximum radius
1789 }
1790 aPropOpt.AddOpt( ESCHER_Prop_adjustValue327, nRadius );
1791 }
1792 else
1793 {
1794 ImplCreateShape( ESCHER_ShpInst_Rectangle1,
1795 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1796 aSolverContainer );
1797 }
1798 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1799 if ( ImplGetText() )
1800 {
1801 mnTxId += 0x60;
1802 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
1803 }
1804 }
1805 else if ( mType == "drawing.Ellipse" )
1806 {
1807 css::drawing::CircleKind eCircleKind( css::drawing::CircleKind_FULL );
1808 PolyStyle ePolyKind = PolyStyle::Chord;
1809 if ( ImplGetPropertyValue( "CircleKind" ) )
1810 {
1811 mAny >>= eCircleKind;
1812 switch ( eCircleKind )
1813 {
1814 case css::drawing::CircleKind_SECTION :
1815 {
1816 ePolyKind = PolyStyle::Pie;
1817 }
1818 break;
1819 case css::drawing::CircleKind_ARC :
1820 {
1821 ePolyKind = PolyStyle::Arc;
1822 }
1823 break;
1824
1825 case css::drawing::CircleKind_CUT :
1826 {
1827 ePolyKind = PolyStyle::Chord;
1828 }
1829 break;
1830
1831 default:
1832 eCircleKind = css::drawing::CircleKind_FULL;
1833 }
1834 }
1835 if ( eCircleKind == css::drawing::CircleKind_FULL )
1836 {
1837 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
1838 ImplCreateShape( ESCHER_ShpInst_Ellipse3,
1839 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1840 aSolverContainer );
1841 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1842 if ( ImplGetText() )
1843 {
1844 mnTxId += 0x60;
1845 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
1846 }
1847 }
1848 else
1849 {
1850 sal_Int32 nStartAngle, nEndAngle;
1851 if ( !ImplGetPropertyValue( "CircleStartAngle" ) )
1852 continue;
1853 nStartAngle = *o3tl::doAccess<sal_Int32>(mAny);
1854 if( !ImplGetPropertyValue( "CircleEndAngle" ) )
1855 continue;
1856 nEndAngle = *o3tl::doAccess<sal_Int32>(mAny);
1857 css::awt::Point aPoint( mXShape->getPosition() );
1858 css::awt::Size aSize( mXShape->getSize() );
1859 css::awt::Point aStart, aEnd, aCenter;
1860 ::tools::Rectangle aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
1861 aStart.X = static_cast<sal_Int32>( cos( nStartAngle * F_PI18000(3.14159265358979323846/18000.0) ) * 100.0 );
1862 aStart.Y = - static_cast<sal_Int32>( sin( nStartAngle * F_PI18000(3.14159265358979323846/18000.0) ) * 100.0 );
1863 aEnd.X = static_cast<sal_Int32>( cos( nEndAngle * F_PI18000(3.14159265358979323846/18000.0) ) * 100.0 );
1864 aEnd.Y = - static_cast<sal_Int32>( sin( nEndAngle * F_PI18000(3.14159265358979323846/18000.0) ) * 100.0 ) ;
1865 aCenter.X = aPoint.X + ( aSize.Width / 2 );
1866 aCenter.Y = aPoint.Y + ( aSize.Height / 2 );
1867 aStart.X += aCenter.X;
1868 aStart.Y += aCenter.Y;
1869 aEnd.X += aCenter.X;
1870 aEnd.Y += aCenter.Y;
1871 tools::Polygon aPolygon( aRect, Point( aStart.X, aStart.Y ), Point( aEnd.X, aEnd.Y ), ePolyKind );
1872 bool bNeedText = true;
1873 if ( mnAngle )
1874 {
1875 aPolygon.Rotate( aRect.TopLeft(), static_cast<sal_uInt16>( mnAngle / 10 ) );
1876 if ( ImplGetText() )
1877 {
1878 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
1879 // mpPptEscherEx->EnterGroup( 0,0 );
1880 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
1881 bNeedText = false;
1882 bAdditionalText = true;
1883 mnTextSize = 0;
1884 }
1885 mnAngle = 0;
1886 }
1887 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
1888 ImplCreateShape( ESCHER_ShpInst_NotPrimitive0,
1889 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
1890 aSolverContainer );
1891 css::awt::Rectangle aNewRect;
1892 switch ( ePolyKind )
1893 {
1894 case PolyStyle::Pie :
1895 case PolyStyle::Chord :
1896 {
1897 if ( aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON4, false, aNewRect, &aPolygon ) )
1898 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
1899 }
1900 break;
1901
1902 case PolyStyle::Arc :
1903 {
1904 if ( aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE2, false, aNewRect, &aPolygon ) )
1905 aPropOpt.CreateLineProperties( mXPropSet, false );
1906 }
1907 break;
1908 }
1909 maRect = MapRectangle( aNewRect );
1910 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
1911 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
1912 if ( bNeedText && ImplGetText() )
1913 {
1914 mnTxId += 0x60;
1915 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
1916 }
1917 }
1918 }
1919 else if ( mType == "drawing.Control" )
1920 {
1921 css::uno::Reference< css::drawing::XControlShape > aXControlShape( mXShape, css::uno::UNO_QUERY );
1922 if ( !aXControlShape.is() )
1923 continue;
1924 css::uno::Reference< css::awt::XControlModel > aXControlModel( aXControlShape->getControl() );
1925 if ( !aXControlModel.is() )
1926 continue;
1927
1928 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
1929 try
1930 {
1931 // try to get the aspect when available
1932 css::uno::Reference< css::beans::XPropertySet > xShapeProps( mXShape, css::uno::UNO_QUERY_THROW );
1933 xShapeProps->getPropertyValue("Aspect") >>= nAspect;
1934 }
1935 catch( css::uno::Exception& )
1936 {}
1937
1938 mpExEmbed->WriteUInt32( 0xf | ( EPP_ExControl4078 << 16 ) )
1939 .WriteUInt32( 0 ); // Size of this container
1940
1941 sal_uInt32 nSize, nOldPos = mpExEmbed->Tell();
1942
1943 sal_uInt32 nPageId = nPageNumber;
1944 if ( ePageType == MASTER )
1945 nPageId |= 0x80000000;
1946 else
1947 nPageId += 0x100;
1948 mpExEmbed->WriteUInt32( EPP_ExControlAtom4091 << 16 )
1949 .WriteUInt32( 4 )
1950 .WriteUInt32( nPageId );
1951 std::unique_ptr<PPTExOleObjEntry> pEntry( new PPTExOleObjEntry( OCX_CONTROL, mpExEmbed->Tell() ) );
1952 pEntry->xControlModel = aXControlModel;
1953 pEntry->xShape = mXShape;
1954 maExOleObj.push_back( std::move(pEntry) );
1955
1956 mnExEmbed++;
1957
1958 mpExEmbed->WriteUInt32( 1 | ( EPP_ExOleObjAtom4035 << 16 ) )
1959 .WriteUInt32( 24 )
1960 .WriteUInt32( nAspect )
1961 .WriteUInt32( 2 )
1962 .WriteUInt32( mnExEmbed )
1963 .WriteUInt32( 0 )
1964 .WriteUInt32( 4 ) // index to the persist table
1965 .WriteUInt32( 0x0012de00 );
1966
1967 css::awt::Size aSize;
1968 OUString aControlName;
1969 tools::SvRef<SotStorage> xTemp( new SotStorage( new SvMemoryStream(), true ) );
1970 if ( oox::ole::MSConvertOCXControls::WriteOCXStream( mXModel, xTemp, aXControlModel, aSize, aControlName ) )
1971 {
1972 OUString aUserName( xTemp->GetUserName() );
1973 OUString aOleIdentifier;
1974 if ( !aUserName.isEmpty() )
1975 {
1976 tools::SvRef<SotStorageStream> xCompObj = xTemp->OpenSotStream(
1977 "\1CompObj",
1978 StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL );
1979 sal_uInt32 const nStreamLen = xCompObj->remainingSize();
1980 sal_Int16 nVersion, nByteOrder;
1981 sal_Int32 nWinVersion, nVal, nStringLen;
1982 xCompObj->ReadInt16( nVersion )
1983 .ReadInt16( nByteOrder )
1984 .ReadInt32( nWinVersion )
1985 .ReadInt32( nVal );
1986 xCompObj->SeekRel( 16 ); // skipping clsid
1987 xCompObj->ReadInt32( nStringLen );
1988 if ( ( xCompObj->Tell() + nStringLen ) < nStreamLen )
1989 {
1990 xCompObj->SeekRel( nStringLen ); // now skipping the UserName;
1991 xCompObj->ReadInt32( nStringLen );
1992 if ( ( xCompObj->Tell() + nStringLen ) < nStreamLen )
1993 {
1994 xCompObj->SeekRel( nStringLen ); // now skipping the clipboard formatname
1995 xCompObj->ReadInt32( nStringLen );
1996 if ( ( nStringLen > 1 ) && ( ( xCompObj->Tell() + nStringLen ) < nStreamLen ) )
1997 { // i think that the OleIdentifier will follow
1998 OString aTemp = read_uInt8s_ToOString(*xCompObj, nStringLen - 1);
1999 aOleIdentifier = OStringToOUString(aTemp, RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1)));
2000 }
2001 }
2002 }
2003 }
2004
2005 PPTWriter::WriteCString( *mpExEmbed, aControlName, 1 );
2006 PPTWriter::WriteCString( *mpExEmbed, aOleIdentifier, 2 );
2007 PPTWriter::WriteCString( *mpExEmbed, aUserName, 3 );
2008 }
2009 nSize = mpExEmbed->Tell() - nOldPos;
2010 mpExEmbed->Seek( nOldPos - 4 );
2011 mpExEmbed->WriteUInt32( nSize );
2012 mpExEmbed->Seek( STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul) );
2013 nOlePictureId = mnExEmbed;
2014
2015 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2016 ShapeFlag const nSpFlags = ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor | ShapeFlag::OLEShape;
2017 ImplCreateShape( ESCHER_ShpInst_HostControl201, nSpFlags, aSolverContainer );
2018 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "MetaFile", false ) )
2019 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2020 //export form control graphic
2021 else if ( aPropOpt.CreateBlipPropertiesforOLEControl(mXPropSet,mXShape))
2022 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2023 aPropOpt.AddOpt( ESCHER_Prop_pictureId267, mnExEmbed );
2024 aPropOpt.AddOpt( ESCHER_Prop_pictureActive319, 0x10000 );
2025
2026 if ( !aControlName.isEmpty() )
2027 {
2028 aPropOpt.AddOpt(ESCHER_Prop_wzName896, aControlName);
2029 }
2030 }
2031 else if ( mType == "drawing.Connector" )
2032 {
2033 sal_uInt16 nSpType;
2034 ShapeFlag nSpFlags;
2035 css::awt::Rectangle aNewRect;
2036 if ( !aPropOpt.CreateConnectorProperties( mXShape, aSolverContainer, aNewRect, nSpType, nSpFlags ) )
2037 continue;
2038
2039 maRect = MapRectangle( aNewRect );
2040 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2041 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2042
2043 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2044 ImplCreateShape( nSpType, nSpFlags, aSolverContainer );
2045
2046 // #119459# for connector shape, the start point and end point is fixed, and should not be rotated.
2047 mnAngle = 0;
2048 }
2049 else if ( mType == "drawing.Measure" )
2050 {
2051 continue;
2052 }
2053 else if ( mType == "drawing.Line" )
2054 {
2055 css::awt::Rectangle aNewRect;
2056 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_LINE1, false, aNewRect );
2057 maRect = MapRectangle( aNewRect );
2058 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2059 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2060 if ( ImplGetText() )
2061 {
2062 aTextRefPoint = css::awt::Point( maRect.Left(), maRect.Top() );
2063 mnTextSize = 0;
2064 bAdditionalText = true;
2065 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2066 // mpPptEscherEx->EnterGroup( &maRect,0 );
2067 }
2068 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2069 ShapeFlag nFlags = ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty;
2070
2071 if ( maRect.Top() > maRect.Bottom() )
2072 nFlags |= ShapeFlag::FlipV;
2073 if ( maRect.Left() > maRect.Right() )
2074 nFlags |= ShapeFlag::FlipH;
2075
2076 ImplCreateShape( ESCHER_ShpInst_Line20, nFlags, aSolverContainer );
2077 aPropOpt.AddOpt( ESCHER_Prop_shapePath324, ESCHER_ShapeComplex );
2078 aPropOpt.CreateLineProperties( mXPropSet, false );
2079 mnAngle = 0;
2080 }
2081 else if ( bPolyPolygon )
2082 {
2083 if ( ImplGetText() )
2084 {
2085 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2086 // mpPptEscherEx->EnterGroup( 0,0 );
2087 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2088 bAdditionalText = true;
2089 mnTextSize = 0;
2090 }
2091 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2092 ImplCreateShape( ESCHER_ShpInst_NotPrimitive0,
2093 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2094 aSolverContainer );
2095 css::awt::Rectangle aNewRect;
2096 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON4, false, aNewRect );
2097 maRect = MapRectangle( aNewRect );
2098 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2099 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2100 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2101 mnAngle = 0;
2102 }
2103 else if ( bPolyLine )
2104 {
2105 if ( ImplGetText() )
2106 {
2107 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2108 // mpPptEscherEx->EnterGroup( 0,0 );
2109 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2110 bAdditionalText = true;
2111 mnTextSize = 0;
2112 }
2113 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2114 ImplCreateShape( ESCHER_ShpInst_NotPrimitive0,
2115 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2116 aSolverContainer );
2117 css::awt::Rectangle aNewRect;
2118 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE2, false, aNewRect );
2119 maRect = MapRectangle( aNewRect );
2120 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2121 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2122 aPropOpt.CreateLineProperties( mXPropSet, false );
2123 mnAngle = 0;
2124 }
2125 else if ( bOpenBezier )
2126 {
2127 if ( ImplGetText() )
2128 {
2129 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2130 // mpPptEscherEx->EnterGroup( 0,0 );
2131 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2132 bAdditionalText = true;
2133 mnTextSize = 0;
2134 }
2135 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2136 ImplCreateShape( ESCHER_ShpInst_NotPrimitive0,
2137 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2138 aSolverContainer );
2139 css::awt::Rectangle aNewRect;
2140 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE2, true, aNewRect );
2141 maRect = MapRectangle( aNewRect );
2142 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2143 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2144 aPropOpt.CreateLineProperties( mXPropSet, false );
2145 mnAngle = 0;
2146 }
2147 else if ( bClosedBezier )
2148 {
2149 if ( ImplGetText() )
2150 {
2151 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2152 // mpPptEscherEx->EnterGroup( 0,0 );
2153 // nGroupLevel = mpPptEscherEx->GetGroupLevel();
2154 bAdditionalText = true;
2155 mnTextSize = 0;
2156 }
2157 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2158 ImplCreateShape( ESCHER_ShpInst_NotPrimitive0,
2159 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2160 aSolverContainer );
2161 css::awt::Rectangle aNewRect;
2162 aPropOpt.CreatePolygonProperties( mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON4, true, aNewRect );
2163 maRect = MapRectangle( aNewRect );
2164 maPosition = css::awt::Point( maRect.Left(), maRect.Top() );
2165 maSize = css::awt::Size( maRect.GetWidth(), maRect.GetHeight() );
2166 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2167 mnAngle = 0;
2168 }
2169 else if ( ( mType == "drawing.GraphicObject" ) || ( mType == "presentation.GraphicObject" ) )
2170 {
2171 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2172
2173 // a GraphicObject can also be a ClickMe element
2174 if ( mbEmptyPresObj && ( ePageType == NORMAL ) )
2175 {
2176 nPlaceHolderAtom = rLayout.nUsedObjectPlaceHolder;
2177 ImplCreateShape( ESCHER_ShpInst_Rectangle1, ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster, aSolverContainer );
2178 mnTxId += 0x60;
2179 aPropOpt.AddOpt( ESCHER_Prop_lTxid128, mnTxId );
2180 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x10001 );
2181 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0x10001 );
2182 aPropOpt.AddOpt( ESCHER_Prop_hspMaster769, mnShapeMasterBody );
2183 }
2184 else
2185 {
2186 mXText.set( mXShape, css::uno::UNO_QUERY );
2187
2188 if ( mXText.is() )
2189 mnTextSize = mXText->getString().getLength();
2190
2191 if ( mnTextSize ) // graphic object or area fill
2192 {
2193 /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
2194 have to create a simple Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
2195 */
2196 ImplCreateShape( ESCHER_ShpInst_Rectangle1,
2197 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2198 aSolverContainer );
2199 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "Graphic", true, true, false ) )
2200 {
2201 aPropOpt.AddOpt( ESCHER_Prop_WrapText133, ESCHER_WrapNone );
2202 aPropOpt.AddOpt( ESCHER_Prop_AnchorText135, ESCHER_AnchorMiddle );
2203 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x140014 );
2204 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor387, 0x8000000 );
2205 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0x80000 );
2206 if ( ImplGetText() )
2207 {
2208 mnTxId += 0x60;
2209 aPropOpt.CreateTextProperties( mXPropSet, mnTxId, false, false );
2210 }
2211 }
2212 }
2213 else
2214 {
2215 ImplCreateShape( ESCHER_ShpInst_PictureFrame75,
2216 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2217 aSolverContainer );
2218
2219 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "Graphic", false, true ) )
2220 {
2221 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2222 }
2223 }
2224 }
2225 }
2226 else if ( ( mType == "drawing.Text" ) || ( mType == "presentation.Notes" ) )
2227 {
2228 if ( ( ePageType == NOTICE ) && mbPresObj )
2229 {
2230 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Notes2, EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE6 ) )
2231 continue;
2232 else
2233 nPlaceHolderAtom = EPP_PLACEHOLDER_NOTESBODY12;
2234 }
2235 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2236 }
2237 else if ( mType == "presentation.TitleText" )
2238 {
2239 if ( mbPresObj )
2240 {
2241 if ( ( ePageType == NOTICE ) && mbEmptyPresObj )
2242 {
2243 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2244 nPlaceHolderAtom = EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE6;
2245 ImplCreateShape( ESCHER_ShpInst_Rectangle1, ShapeFlag::HaveAnchor, aSolverContainer );
2246 aPropOpt.CreateLineProperties( mXPropSet, false );
2247 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x10001 );
2248 }
2249 else if ( rLayout.bTitlePossible && bIsTitlePossible )
2250 {
2251 bIsTitlePossible = false;
2252
2253 ImplGetText();
2254 TextObjBinary aTextObj( mXText, EPP_TEXTTYPE_Title0, maFontCollection, static_cast<PPTExBulletProvider&>(*this) );
2255 if ( ePageType == MASTER )
2256 {
2257 if ( mnTextSize )
2258 {
2259 OUString aUString( mXText->getString() );
2260 sal_uInt16 nChar;
2261
2262 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2263 mnShapeMasterTitle = mpPptEscherEx->GenerateShapeId();
2264 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle1,
2265 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2266 mnShapeMasterTitle );
2267 EscherPropertyContainer aPropertyOptions;
2268 aPropertyOptions.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x50001 );
2269 mnTxId += 0x60;
2270 aPropertyOptions.AddOpt( ESCHER_Prop_lTxid128, mnTxId );
2271 aPropertyOptions.AddOpt( ESCHER_Prop_AnchorText135, ESCHER_AnchorMiddle );
2272 aPropertyOptions.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x110001 );
2273 aPropertyOptions.AddOpt( ESCHER_Prop_lineColor448, 0x8000001 );
2274 aPropertyOptions.AddOpt( ESCHER_Prop_shadowColor513, 0x8000002 );
2275 aPropertyOptions.CreateFillProperties( mXPropSet, true, mXShape );
2276 sal_uInt32 nLineFlags = 0x90001;
2277 if ( aPropertyOptions.GetOpt( ESCHER_Prop_fNoLineDrawDash511, nLineFlags ) )
2278 nLineFlags |= 0x10001; // draw dashed line if no line
2279 aPropertyOptions.AddOpt( ESCHER_Prop_fNoLineDrawDash511, nLineFlags );
2280 mnTxId += 0x60;
2281 aPropertyOptions.CreateTextProperties( mXPropSet, mnTxId );
2282 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt );
2283 aPropertyOptions.Commit( *mpStrm );
2284 mpPptEscherEx->AddAtom( 8, ESCHER_ClientAnchor0xF010u );
2285 mpStrm->WriteInt16( maRect.Top() ).WriteInt16( maRect.Left() ).WriteInt16( maRect.Right() ).WriteInt16( maRect.Bottom() ); // top, left, right, bottom ????
2286 mpPptEscherEx->OpenContainer( ESCHER_ClientData0xF011u );
2287 mpPptEscherEx->AddAtom( 8, EPP_OEPlaceholderAtom3011 );
2288 mpStrm->WriteUInt32( 0 ) // PlacementID
2289 .WriteUChar( EPP_PLACEHOLDER_MASTERTITLE1 ) // PlaceHolderID
2290 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2291 .WriteUInt16( 0 ); // padword
2292 mpPptEscherEx->CloseContainer(); // ESCHER_ClientData
2293 mpPptEscherEx->OpenContainer( ESCHER_ClientTextbox0xF00Du );
2294 mpPptEscherEx->AddAtom( 4, EPP_TextHeaderAtom3999 );
2295 mpStrm->WriteUInt32( EPP_TEXTTYPE_Title0 );
2296 mpPptEscherEx->AddAtom( mnTextSize << 1, EPP_TextCharsAtom4000 );
2297 const sal_Unicode* pString = aUString.getStr();
2298 for ( sal_uInt32 i = 0; i < mnTextSize; i++ )
2299 {
2300 nChar = pString[ i ]; // 0xa -> 0xb soft newline
2301 if ( nChar == 0xa )
2302 nChar++; // 0xd -> 0xd hard newline
2303 mpStrm->WriteUInt16( nChar );
2304 }
2305 mpPptEscherEx->AddAtom( 6, EPP_BaseTextPropAtom4002 );
2306 mpStrm->WriteUInt32( mnTextSize + 1 ).WriteUInt16( 0 );
2307 mpPptEscherEx->AddAtom( 10, EPP_TextSpecInfoAtom4010 );
2308 mpStrm->WriteUInt32( mnTextSize + 1 ).WriteUInt32( 1 ).WriteUInt16( 0 );
2309 mpPptEscherEx->CloseContainer(); // ESCHER_ClientTextBox
2310 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2311 }
2312 continue;
2313 }
2314 else
2315 {
2316 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2317 mnTextStyle = EPP_TEXTSTYLE_TITLE0x00000010;
2318 nPlaceHolderAtom = rLayout.nTypeOfTitle;
2319 ImplCreateShape( ESCHER_ShpInst_Rectangle1,
2320 ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster,
2321 aSolverContainer );
2322 aPropOpt.AddOpt( ESCHER_Prop_hspMaster769, mnShapeMasterTitle );
2323 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2324 mnTxId += 0x60;
2325 aPropOpt.CreateTextProperties( mXPropSet, mnTxId );
2326 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt );
2327 if ( mbEmptyPresObj )
2328 {
2329 sal_uInt32 nNoLineDrawDash = 0;
2330 aPropOpt.GetOpt( ESCHER_Prop_fNoLineDrawDash511, nNoLineDrawDash );
2331 nNoLineDrawDash |= 0x10001;
2332 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, nNoLineDrawDash );
2333 }
2334 }
2335 }
2336 else
2337 mbPresObj = false;
2338 }
2339 if ( !mbPresObj )
2340 {
2341 mType = "drawing.Text";
2342 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2343 }
2344 }
2345 else if ( ( mType == "presentation.Outliner" ) || ( mType == "presentation.Subtitle" ) )
2346 {
2347 if ( mbPresObj )
2348 {
2349 nOutlinerCount++;
2350 if ( (rLayout.bOutlinerPossible && ( nOutlinerCount == 1 )) ||
2351 (( rLayout.bSecOutlinerPossible && ( nOutlinerCount == 2 ) ) && ( nPrevTextStyle == EPP_TEXTSTYLE_BODY0x00000100 ))
2352 )
2353 {
2354 ImplGetText();
2355 TextObjBinary aTextObj( mXText, EPP_TEXTTYPE_Body1, maFontCollection, static_cast<PPTExBulletProvider&>(*this) );
2356 if ( ePageType == MASTER )
2357 {
2358 nPrevTextStyle = EPP_TEXTSTYLE_TITLE0x00000010;
2359 if ( mnTextSize )
2360 {
2361 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2362 mnShapeMasterBody = mpPptEscherEx->GenerateShapeId();
2363 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle1,
2364 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2365 mnShapeMasterBody );
2366 EscherPropertyContainer aPropOpt2;
2367 aPropOpt2.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x50001 );
2368 mnTxId += 0x60;
2369 aPropOpt2.AddOpt( ESCHER_Prop_lTxid128, mnTxId );
2370 aPropOpt2.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x110001 );
2371 aPropOpt2.AddOpt( ESCHER_Prop_lineColor448, 0x8000001 );
2372 aPropOpt2.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0x90001 );
2373 aPropOpt2.AddOpt( ESCHER_Prop_shadowColor513, 0x8000002 );
2374 aPropOpt2.CreateFillProperties( mXPropSet, true, mXShape );
2375 sal_uInt32 nLineFlags = 0x90001;
2376 if ( aPropOpt2.GetOpt( ESCHER_Prop_fNoLineDrawDash511, nLineFlags ) )
2377 nLineFlags |= 0x10001; // draw dashed line if no line
2378 aPropOpt2.AddOpt( ESCHER_Prop_fNoLineDrawDash511, nLineFlags );
2379 mnTxId += 0x60;
2380 aPropOpt2.CreateTextProperties( mXPropSet, mnTxId );
2381 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt2 );
2382 aPropOpt2.Commit( *mpStrm );
2383 mpPptEscherEx->AddAtom( 8, ESCHER_ClientAnchor0xF010u );
2384 mpStrm->WriteInt16( maRect.Top() ).WriteInt16( maRect.Left() ).WriteInt16( maRect.Right() ).WriteInt16( maRect.Bottom() ); // top, left, right, bottom ????
2385 mpPptEscherEx->OpenContainer( ESCHER_ClientData0xF011u );
2386 mpPptEscherEx->AddAtom( 8, EPP_OEPlaceholderAtom3011 );
2387 sal_uInt8 PlaceHolderID = ( mType == "presentation.Subtitle") ? EPP_PLACEHOLDER_MASTERSUBTITLE4:EPP_PLACEHOLDER_MASTERBODY2;
2388 mpStrm->WriteUInt32( 1 ) // PlacementID
2389 .WriteUChar( PlaceHolderID )/*(sal_uInt8)EPP_PLACEHOLDER_MASTERBODY */ // PlaceHolderID
2390 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2391 .WriteUInt16( 0 ); // padword
2392 mpPptEscherEx->CloseContainer(); // ESCHER_ClientData
2393 mpPptEscherEx->OpenContainer( ESCHER_ClientTextbox0xF00Du ); // printf
2394 mpPptEscherEx->AddAtom( 4, EPP_TextHeaderAtom3999 );
2395 if ( mType == "presentation.Subtitle")
2396 mpStrm->WriteUInt32( EPP_TEXTTYPE_CenterBody5 );
2397 else
2398 mpStrm->WriteUInt32( EPP_TEXTTYPE_Body1 );
2399 mnTextSize = aTextObj.Count();
2400 aTextObj.Write( mpStrm.get() );
2401 mpPptEscherEx->BeginAtom();
2402 for ( sal_uInt32 i = 0; i < aTextObj.ParagraphCount() ; ++i )
2403 {
2404 ParagraphObj* pPara = aTextObj.GetParagraph(i);
2405 mpStrm->WriteUInt32( pPara->CharacterCount() )
2406 .WriteUInt16( pPara->nDepth );
2407 }
2408 mpPptEscherEx->EndAtom( EPP_BaseTextPropAtom4002 );
2409 mpPptEscherEx->AddAtom( 10, EPP_TextSpecInfoAtom4010 );
2410 mpStrm->WriteUInt32( mnTextSize ).WriteUInt32( 1 ).WriteUInt16( 0 );
2411
2412 mpPptEscherEx->CloseContainer(); // ESCHER_ClientTextBox
2413 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2414 }
2415 continue;
2416 }
2417 else
2418 {
2419 mnTextStyle = EPP_TEXTSTYLE_BODY0x00000100;
2420 nPlaceHolderAtom = rLayout.nTypeOfOutliner;
2421 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2422 ImplCreateShape( ESCHER_ShpInst_Rectangle1,
2423 ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster,
2424 aSolverContainer );
2425 aPropOpt.AddOpt( ESCHER_Prop_hspMaster769, mnShapeMasterBody );
2426 aPropOpt.CreateFillProperties( mXPropSet, true, mXShape );
2427 mnTxId += 0x60;
2428 aPropOpt.CreateTextProperties( mXPropSet, mnTxId );
2429 ImplAdjustFirstLineLineSpacing( aTextObj, aPropOpt );
2430 if ( mbEmptyPresObj )
2431 {
2432 sal_uInt32 nNoLineDrawDash = 0;
2433 aPropOpt.GetOpt( ESCHER_Prop_fNoLineDrawDash511, nNoLineDrawDash );
2434 nNoLineDrawDash |= 0x10001;
2435 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, nNoLineDrawDash );
2436 }
2437 }
2438 }
2439 else
2440 mbPresObj = false;
2441 }
2442 if ( !mbPresObj )
2443 {
2444 if (ePageType == MASTER )
2445 {
2446 SdrObject* pObj = GetSdrObjectFromXShape( mXShape );
2447 if (pObj && pObj->IsNotVisibleAsMaster())
2448 continue;
2449 }
2450
2451 mType = "drawing.Text";
2452 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2453 }
2454 }
2455 else if ( ( mType == "drawing.Page" ) || ( mType == "presentation.Page" ) )
2456 {
2457 if ( ( ePageType == NOTICE ) && mbPresObj )
2458 {
2459 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Notes2, EPP_PLACEHOLDER_MASTERNOTESSLIDEIMAGE5 ) )
2460 continue;
2461 else
2462 nPlaceHolderAtom = EPP_PLACEHOLDER_NOTESSLIDEIMAGE11;
2463 }
2464 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2465 }
2466 else if ( mType == "drawing.Frame" )
2467 {
2468 continue;
2469 }
2470 else if ( ( mType == "drawing.OLE2" ) || ( mType == "presentation.OLE2" )
2471 || ( mType == "presentation.Chart" ) || ( mType == "presentation.Calc" )
2472 || ( mType == "presentation.OrgChart" ) )
2473 {
2474 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2475 if ( mbEmptyPresObj && ( ePageType == NORMAL ) )
2476 {
2477 nPlaceHolderAtom = rLayout.nUsedObjectPlaceHolder;
2478 ImplCreateShape( ESCHER_ShpInst_Rectangle1,
2479 ShapeFlag::HaveAnchor | ShapeFlag::HaveMaster,
2480 aSolverContainer );
2481 mnTxId += 0x60;
2482 aPropOpt.AddOpt( ESCHER_Prop_lTxid128, mnTxId );
2483 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x10001 );
2484 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0x10001 );
2485 aPropOpt.AddOpt( ESCHER_Prop_hspMaster769, mnShapeMasterBody );
2486 }
2487 else
2488 {
2489 mpExEmbed->WriteUInt32( 0xf | ( EPP_ExEmbed4044 << 16 ) )
2490 .WriteUInt32( 0 ); // Size of this container
2491
2492 sal_uInt32 nSize, nOldPos = mpExEmbed->Tell();
2493
2494 mpExEmbed->WriteUInt32( EPP_ExEmbedAtom4045 << 16 )
2495 .WriteUInt32( 8 )
2496 .WriteUInt32( 0 ) // follow colorscheme : 0->do not follow
2497 // 1->follow colorscheme
2498 // 2->follow text and background scheme
2499 .WriteUChar( 1 ) // (bool)set if embedded server can not be locked
2500 .WriteUChar( 0 ) // (bool)do not need to send dimension
2501 .WriteUChar( 0 ) // (bool)is object a world table
2502 .WriteUChar( 0 ); // pad byte
2503
2504 std::unique_ptr<PPTExOleObjEntry> pE( new PPTExOleObjEntry( NORMAL_OLE_OBJECT, mpExEmbed->Tell() ) );
2505 pE->xShape = mXShape;
2506 maExOleObj.push_back( std::move(pE) );
2507
2508 mnExEmbed++;
2509
2510 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
2511 try
2512 {
2513 // try to get the aspect when available
2514 css::uno::Reference< css::beans::XPropertySet > xShapeProps( mXShape, css::uno::UNO_QUERY_THROW );
2515 xShapeProps->getPropertyValue("Aspect") >>= nAspect;
2516 }
2517 catch( css::uno::Exception& )
2518 {}
2519
2520 mpExEmbed->WriteUInt32( 1 | ( EPP_ExOleObjAtom4035 << 16 ) )
2521 .WriteUInt32( 24 )
2522 .WriteUInt32( nAspect ) // Aspect
2523 .WriteUInt32( 0 )
2524 .WriteUInt32( mnExEmbed ) // index to the persist table
2525 .WriteUInt32( 0 ) // subtype
2526 .WriteUInt32( 0 )
2527 .WriteUInt32( 0x0012b600 );
2528
2529 nSize = mpExEmbed->Tell() - nOldPos;
2530 mpExEmbed->Seek( nOldPos - 4 );
2531 mpExEmbed->WriteUInt32( nSize );
2532 mpExEmbed->Seek( STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul) );
2533 nOlePictureId = mnExEmbed;
2534
2535 ShapeFlag nSpFlags = ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty;
2536 if ( nOlePictureId )
2537 nSpFlags |= ShapeFlag::OLEShape;
2538 ImplCreateShape( ESCHER_ShpInst_PictureFrame75, nSpFlags, aSolverContainer );
2539 if ( aPropOpt.CreateOLEGraphicProperties( mXShape ) )
2540 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2541 if ( nOlePictureId )
2542 aPropOpt.AddOpt( ESCHER_Prop_pictureId267, nOlePictureId );
2543 }
2544 }
2545 else if ( mType == "presentation.Header" )
2546 {
2547 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other4, EPP_PLACEHOLDER_MASTERHEADER10 ) )
2548 continue;
2549 else
2550 {
2551 mbPresObj = false;
2552 mType = "drawing.Text";
2553 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2554 }
2555 }
2556 else if ( mType == "presentation.Footer" )
2557 {
2558 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other4, EPP_PLACEHOLDER_MASTERFOOTER9 ) )
2559 continue;
2560 else
2561 {
2562 mbPresObj = false;
2563 mType = "drawing.Text";
2564 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2565 }
2566 }
2567 else if ( mType == "presentation.DateTime" )
2568 {
2569 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other4, EPP_PLACEHOLDER_MASTERDATE7 ) )
2570 continue;
2571 else
2572 {
2573 mbPresObj = false;
2574 mType = "drawing.Text";
2575 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2576 }
2577 }
2578 else if ( mType == "presentation.SlideNumber" )
2579 {
2580 if ( ImplCreatePresentationPlaceholder( bMasterPage, EPP_TEXTTYPE_Other4, EPP_PLACEHOLDER_MASTERSLIDENUMBER8 ) )
2581 continue;
2582 else
2583 {
2584 mbPresObj = false;
2585 mType = "drawing.Text";
2586 ImplCreateTextShape( aPropOpt, aSolverContainer, true );
2587 }
2588 }
2589 else if ( (mType.getLength() > 9) && (mType[8] == '3') && (mType[9] == 'D') ) // drawing.3D
2590 {
2591 // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
2592 if ( !ImplGetPropertyValue( "Bitmap" ) )
2593 continue;
2594
2595 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2596 ImplCreateShape( ESCHER_ShpInst_PictureFrame75,
2597 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2598 aSolverContainer );
2599
2600 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "Bitmap", false ) )
2601 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2602 }
2603 else if ( mType == "drawing.Media" )
2604 {
2605 mnAngle = 0;
2606 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2607 ImplCreateShape( ESCHER_ShpInst_PictureFrame75,
2608 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2609 aSolverContainer );
2610 if ( aPropOpt.CreateMediaGraphicProperties( mXShape ) )
2611 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2612 css::uno::Any aAny;
2613 if ( PropValue::GetPropertyValue( aAny, mXPropSet, "MediaURL", true ) )
2614 {
2615 OUString aMediaURL;
2616 if ( (aAny >>= aMediaURL ) && !aMediaURL.isEmpty() )
2617 {
2618 // SJ: creating the Media RefObj
2619 sal_uInt32 nRefId = ++mnExEmbed;
2620
2621 mpExEmbed->WriteUInt16( 0xf )
2622 .WriteUInt16( EPP_ExMCIMovie4103 ) // PPT_PST_ExAviMovie
2623 .WriteUInt32( 0 );
2624 sal_uInt32 nSize, nStart = mpExEmbed->Tell();
2625 mpExEmbed->WriteUInt16( 0 )
2626 .WriteUInt16( EPP_ExObjRefAtom3009 )
2627 .WriteUInt32( 4 )
2628 .WriteUInt32( nRefId );
2629 mpExEmbed->WriteUInt16( 0xf )
2630 .WriteUInt16( EPP_ExVideo4101 )
2631 .WriteUInt32( 0 );
2632
2633 mpExEmbed->WriteUInt16( 0 )
2634 .WriteUInt16( EPP_ExMediaAtom4100 )
2635 .WriteUInt32( 8 )
2636 .WriteUInt32( nRefId )
2637 .WriteUInt16( 0 )
2638 .WriteUInt16( 0x435 );
2639
2640 sal_uInt16 i, nStringLen = static_cast<sal_uInt16>(aMediaURL.getLength());
2641 mpExEmbed->WriteUInt32( EPP_CString4026 << 16 ).WriteUInt32( nStringLen * 2 );
2642 for ( i = 0; i < nStringLen; i++ )
2643 {
2644 sal_Unicode nChar = aMediaURL[ i ];
2645 mpExEmbed->WriteUInt16( nChar );
2646 }
2647 nSize = mpExEmbed->Tell() - nStart;
2648 mpExEmbed->SeekRel( - ( static_cast<sal_Int32>(nSize) + 4 ) );
2649 mpExEmbed->WriteUInt32( nSize ); // size of PPT_PST_ExMCIMovie
2650 mpExEmbed->SeekRel( 0x10 );
2651 nSize -= 20;
2652 mpExEmbed->WriteUInt32( nSize ); // PPT_PST_ExMediaAtom
2653 mpExEmbed->SeekRel( nSize );
2654
2655 if ( !pClientData )
2656 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2657 pClientData->WriteUInt16( 0 )
2658 .WriteUInt16( EPP_ExObjRefAtom3009 )
2659 .WriteUInt32( 4 )
2660 .WriteUInt32( nRefId );
2661 // write EPP_InteractiveInfo container for no_action
2662 pClientData->WriteUInt32( ( EPP_InteractiveInfo4082 << 16 ) | 0xf ).WriteUInt32( 24 );
2663 pClientData->WriteUInt16( 0 )
2664 .WriteUInt16( EPP_InteractiveInfoAtom4083 )
2665 .WriteUInt32( 16 )
2666 .WriteUInt32( 0 )
2667 .WriteUInt32( 0 )
2668 .WriteUChar( 6 )
2669 .WriteUChar( 0 )
2670 .WriteUChar( 0 )
2671 .WriteUChar( 0 )
2672 .WriteUInt32( 0 );
2673 }
2674 }
2675 }
2676 else if ( (mType == "drawing.Table") || (mType == "presentation.Table") )
2677 {
2678 if ( eCa != css::presentation::ClickAction_NONE )
2679 {
2680 SvMemoryStream aTmp(0x200, 0x200);
2681 ImplWriteClickAction( aTmp, eCa, bMediaClickAction );
2682 }
2683 ImplCreateTable( mXShape, aSolverContainer, aPropOpt );
2684 continue;
2685 }
2686 else if ( mType == "drawing.dontknow" )
2687 {
2688 mnAngle = 0;
2689 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2690 ImplCreateShape( ESCHER_ShpInst_PictureFrame75,
2691 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty,
2692 aSolverContainer );
2693 if ( aPropOpt.CreateGraphicProperties( mXPropSet, "MetaFile", false ) )
2694 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x800080 );
2695 }
2696 else
2697 {
2698 continue;
2699 }
2700
2701 bool bClientData = ( bEffect || ( eCa != css::presentation::ClickAction_NONE ) ||
2702 nPlaceHolderAtom || nOlePictureId );
2703 if ( bClientData )
2704 {
2705 if ( nPlaceHolderAtom )
2706 {
2707 sal_Int32 nPlacementID = -1;
2708 if ( ( mnTextStyle == EPP_TEXTSTYLE_TITLE0x00000010 ) || ( mnTextStyle == EPP_TEXTSTYLE_BODY0x00000100 ) )
2709 nPlacementID = nIndices++;
2710 else
2711 {
2712 switch ( nPlaceHolderAtom )
2713 {
2714 default :
2715 {
2716 if ( nPlaceHolderAtom < 19 )
2717 break;
2718 [[fallthrough]];
2719 }
2720 case EPP_PLACEHOLDER_NOTESBODY12 :
2721 case EPP_PLACEHOLDER_MASTERDATE7 :
2722 case EPP_PLACEHOLDER_NOTESSLIDEIMAGE11 :
2723 case EPP_PLACEHOLDER_MASTERNOTESBODYIMAGE6 :
2724 nPlacementID = nIndices++;
2725 }
2726 }
2727 if ( !pClientData )
2728 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2729
2730 pClientData->WriteUInt32( EPP_OEPlaceholderAtom3011 << 16 ).WriteUInt32( 8 )
2731 .WriteInt32( nPlacementID ) // PlacementID
2732 .WriteUChar( nPlaceHolderAtom ) // PlaceHolderID
2733 .WriteUChar( 0 ) // Size of PlaceHolder ( 0 = FULL, 1 = HALF, 2 = QUARTER )
2734 .WriteUInt16( 0 ); // padword
2735 }
2736 if ( nOlePictureId )
2737 {
2738 if ( !pClientData )
2739 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2740
2741 pClientData->WriteUInt32( EPP_ExObjRefAtom3009 << 16 ).WriteUInt32( 4 )
2742 .WriteUInt32( nOlePictureId );
2743 nOlePictureId = 0;
2744 }
2745 if ( bEffect && !pClientData )
2746 {
2747 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2748 }
2749
2750 if ( eCa != css::presentation::ClickAction_NONE )
2751 {
2752 if ( !pClientData )
2753 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2754 ImplWriteClickAction( *pClientData, eCa, bMediaClickAction );
2755 }
2756 }
2757 if ( ( mnTextStyle == EPP_TEXTSTYLE_TITLE0x00000010 ) || ( mnTextStyle == EPP_TEXTSTYLE_BODY0x00000100 ) )
2758 {
2759 if ( !pClientTextBox )
2760 pClientTextBox.reset(new SvMemoryStream( 0x200, 0x200 ));
2761
2762 if ( !mbEmptyPresObj )
2763 {
2764 if ( ( ePageType == NORMAL ) && !bMasterPage )
2765 {
2766 sal_uInt32 nTextType = EPP_TEXTTYPE_Body1;
2767 if ( mnTextStyle == EPP_TEXTSTYLE_BODY0x00000100 )
2768 {
2769 if ( bSecOutl )
2770 nTextType = EPP_TEXTTYPE_HalfBody7;
2771 else if ( mType == "presentation.Subtitle" )
2772 nTextType = EPP_TEXTTYPE_CenterBody5;
2773 bSecOutl = true;
2774 }
2775 else
2776 nTextType = EPP_TEXTTYPE_Title0;
2777
2778 TextRuleEntry aTextRule;
2779 SvMemoryStream aExtBu( 0x200, 0x200 );
2780 ImplGetText();
2781 ImplWriteTextStyleAtom( *pClientTextBox, nTextType, nPObjects, &aTextRule, aExtBu, nullptr );
2782 ImplWriteExtParaHeader( aExtBu, nPObjects++, nTextType, nPageNumber + 0x100 );
2783 SvMemoryStream* pOut = aTextRule.pOut.get();
2784 if ( pOut )
2785 {
2786 pClientTextBox->WriteBytes(pOut->GetData(), pOut->Tell());
2787 aTextRule.pOut.reset();
2788 }
2789 if ( aExtBu.Tell() )
2790 {
2791 if ( !pClientData )
2792 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2793 ImplProgTagContainer( pClientData.get(), &aExtBu );
2794 }
2795 }
2796 }
2797 }
2798 else
2799 {
2800 if ( !aPropOpt.IsFontWork() )
2801 {
2802 if ( mnTextSize || ( nPlaceHolderAtom == EPP_PLACEHOLDER_MASTERDATE7 ) || ( nPlaceHolderAtom == EPP_PLACEHOLDER_NOTESBODY12 ) )
2803 {
2804 int nInstance2;
2805 if ( ( nPlaceHolderAtom == EPP_PLACEHOLDER_MASTERDATE7 ) || ( nPlaceHolderAtom == EPP_PLACEHOLDER_NOTESBODY12 ) )
2806 nInstance2 = 2;
2807 else
2808 nInstance2 = EPP_TEXTTYPE_Other4; // Text in a Shape
2809
2810 if ( !pClientTextBox )
2811 pClientTextBox.reset(new SvMemoryStream( 0x200, 0x200 ));
2812
2813 SvMemoryStream aExtBu( 0x200, 0x200 );
2814 ImplWriteTextStyleAtom( *pClientTextBox, nInstance2, 0, nullptr, aExtBu, &aPropOpt );
2815 if ( aExtBu.Tell() )
2816 {
2817 if ( !pClientData )
2818 pClientData.reset(new SvMemoryStream( 0x200, 0x200 ));
2819 ImplProgTagContainer( pClientData.get(), &aExtBu );
2820 }
2821 }
2822 else if ( nPlaceHolderAtom >= 19 )
2823 {
2824 if ( !pClientTextBox )
2825 pClientTextBox.reset(new SvMemoryStream( 12 ));
2826
2827 pClientTextBox->WriteUInt32( EPP_TextHeaderAtom3999 << 16 ).WriteUInt32( 4 )
2828 .WriteUInt32( 7 );
2829 }
2830 }
2831 }
2832
2833 aPropOpt.CreateShadowProperties( mXPropSet );
2834 maRect.Justify();
2835 if ( mnAngle )
2836 ImplFlipBoundingBox( aPropOpt );
2837 aPropOpt.CreateShapeProperties( mXShape );
2838 aPropOpt.Commit( *mpStrm );
2839 if ( GetCurrentGroupLevel() > 0 )
2840 mpPptEscherEx->AddChildAnchor( maRect );
2841 else
2842 mpPptEscherEx->AddClientAnchor( maRect );
2843
2844 if ( pClientData )
2845 {
2846 mpStrm->WriteUInt32( ( ESCHER_ClientData0xF011u << 16 ) | 0xf )
2847 .WriteUInt32( pClientData->Tell() );
2848
2849 mpStrm->WriteBytes(pClientData->GetData(), pClientData->Tell());
2850 pClientData.reset();
2851 }
2852 if ( pClientTextBox )
2853 {
2854 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox0xF00Du << 16 ) | 0xf )
2855 .WriteUInt32( pClientTextBox->Tell() );
2856
2857 mpStrm->WriteBytes(pClientTextBox->GetData(), pClientTextBox->Tell());
2858 pClientTextBox.reset();
2859 }
2860 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2861 }
2862 nPrevTextStyle = mnTextStyle;
2863
2864 if ( bAdditionalText )
2865 {
2866 bAdditionalText = false;
2867
2868 css::uno::Any aAny;
2869 EscherPropertyContainer aPropOpt;
2870 mnAngle = ( PropValue::GetPropertyValue( aAny,
2871 mXPropSet, "RotateAngle", true ) )
2872 ? *o3tl::doAccess<sal_Int32>(aAny)
2873 : 0;
2874
2875 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0x90000 );
2876 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest447, 0x100000 );
2877 if ( mType == "drawing.Line" )
2878 {
2879 double fDist = hypot( maRect.GetWidth(), maRect.GetHeight() );
2880 maRect = ::tools::Rectangle( Point( aTextRefPoint.X, aTextRefPoint.Y ),
2881 Point( static_cast<sal_Int32>( aTextRefPoint.X + fDist ), aTextRefPoint.Y - 1 ) );
2882 ImplCreateTextShape( aPropOpt, aSolverContainer, false );
2883 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape191, 0x60006 ); // Size Shape To Fit Text
2884 if ( mnAngle < 0 )
2885 mnAngle = ( 36000 + mnAngle ) % 36000;
2886 if ( mnAngle )
2887 ImplFlipBoundingBox( aPropOpt );
2888 }
2889 else
2890 {
2891 ImplCreateTextShape( aPropOpt, aSolverContainer, false );
2892 if ( mnAngle < 0 )
2893 mnAngle = ( 36000 + mnAngle ) % 36000;
2894 else
2895 mnAngle = ( 36000 - ( mnAngle % 36000 ) );
2896
2897 mnAngle *= 655;
2898 mnAngle += 0x8000;
2899 mnAngle &=~0xffff; // round nAngle to full grad
2900 aPropOpt.AddOpt( ESCHER_Prop_Rotation4, mnAngle );
2901
2902 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2903 // mpPptEscherEx->SetGroupSnapRect( nGroupLevel, maRect );
2904 // mpPptEscherEx->SetGroupLogicRect( nGroupLevel, maRect );
2905 }
2906 if ( !pClientTextBox )
2907 pClientTextBox.reset(new SvMemoryStream( 0x200, 0x200 ));
2908
2909 SvMemoryStream aExtBu( 0x200, 0x200 );
2910 ImplWriteTextStyleAtom( *pClientTextBox, EPP_TEXTTYPE_Other4, 0, nullptr, aExtBu, &aPropOpt );
2911
2912 aPropOpt.CreateShapeProperties( mXShape );
2913 aPropOpt.Commit( *mpStrm );
2914 if ( GetCurrentGroupLevel() > 0 )
2915 mpPptEscherEx->AddChildAnchor( maRect );
2916 else
2917 mpPptEscherEx->AddClientAnchor( maRect );
2918
2919 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox0xF00Du << 16 ) | 0xf )
2920 .WriteUInt32( pClientTextBox->Tell() );
2921
2922 mpStrm->WriteBytes(pClientTextBox->GetData(), pClientTextBox->Tell());
2923 pClientTextBox.reset();
2924
2925 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
2926
2927 // #i119551# PPT does not support groups of polygons and text (MS patch KB2289187)
2928 // mpPptEscherEx->LeaveGroup();
2929 }
2930 }
2931 ClearGroupTable(); // storing groups if any are still open, which should not be the case
2932 nGroups = GetGroupsClosed();
2933 for ( sal_uInt32 i = 0; i < nGroups; i++, mpPptEscherEx->LeaveGroup() ) ;
2934 mnPagesWritten++;
2935}
2936
2937struct CellBorder
2938{
2939 sal_Int32 mnPos; // specifies the distance to the top/left position of the table
2940 table::BorderLine maCellBorder;
2941
2942 CellBorder() : mnPos ( 0 ) {};
2943};
2944
2945bool PPTWriter::ImplCreateCellBorder( const CellBorder* pCellBorder, sal_Int32 nX1, sal_Int32 nY1, sal_Int32 nX2, sal_Int32 nY2)
2946{
2947 sal_Int32 nLineWidth = pCellBorder->maCellBorder.OuterLineWidth + pCellBorder->maCellBorder.InnerLineWidth;
2948 if ( nLineWidth )
2949 {
2950 nLineWidth *= 2;
2951 mnAngle = 0;
2952 mpPptEscherEx->OpenContainer( ESCHER_SpContainer0xF004u );
2953 EscherPropertyContainer aPropOptSp;
2954
2955 sal_uInt32 nId = mpPptEscherEx->GenerateShapeId();
2956 mpPptEscherEx->AddShape( ESCHER_ShpInst_Line20,
2957 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty | ShapeFlag::Child,
2958 nId );
2959 aPropOptSp.AddOpt( ESCHER_Prop_shapePath324, ESCHER_ShapeComplex );
2960 aPropOptSp.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0xa0008 );
2961 aPropOptSp.AddOpt( ESCHER_Prop_fshadowObscured575, 0x20000 );
2962
2963 sal_uInt32 nBorderColor = pCellBorder->maCellBorder.Color & 0xff00; // green
2964 nBorderColor |= static_cast< sal_uInt8 >( pCellBorder->maCellBorder.Color ) << 16; // red
2965 nBorderColor |= static_cast< sal_uInt8 >( pCellBorder->maCellBorder.Color >> 16 ); // blue
2966 aPropOptSp.AddOpt( ESCHER_Prop_lineColor448, nBorderColor );
2967
2968 aPropOptSp.AddOpt( ESCHER_Prop_lineWidth459, nLineWidth * 360 );
2969 aPropOptSp.AddOpt( ESCHER_Prop_fc3DLightFace703, 0x80000 );
2970 aPropOptSp.Commit( *mpStrm );
2971 mpPptEscherEx->AddAtom( 16, ESCHER_ChildAnchor0xF00Fu );
2972 mpStrm ->WriteInt32( nX1 )
2973 .WriteInt32( nY1 )
2974 .WriteInt32( nX2 )
2975 .WriteInt32( nY2 );
2976 mpPptEscherEx->CloseContainer();
2977 return true;
2978 }
2979 return false;
2980}
2981
2982//get merged cell's width
2983static sal_Int32 GetCellRight( sal_Int32 nColumn,
2984 ::tools::Rectangle const & rect,
2985 std::vector< std::pair< sal_Int32, sal_Int32 > >& aColumns,
2986 uno::Reference< table::XMergeableCell > const & xCell )
2987{
2988 sal_Int32 nRight = aColumns[ nColumn ].first + aColumns[ nColumn ].second;
2989 for ( sal_Int32 nColumnSpan = 1; nColumnSpan < xCell->getColumnSpan(); nColumnSpan++ )
2990 {
2991 sal_uInt32 nC = nColumnSpan + nColumn;
2992 if ( nC < aColumns.size() )
2993 nRight += aColumns[ nC ].second;
2994 else
2995 nRight = rect.Right();
2996 }
2997 return nRight;
2998}
2999//get merged cell's height
3000static sal_Int32 GetCellBottom( sal_Int32 nRow,
3001 ::tools::Rectangle const & rect,
3002 std::vector< std::pair< sal_Int32, sal_Int32 > >& aRows,
3003 uno::Reference< table::XMergeableCell > const & xCell )
3004{
3005 sal_Int32 nBottom = aRows[nRow].first + aRows[nRow].second;
3006 for ( sal_Int32 nRowSpan = 1; nRowSpan < xCell->getRowSpan(); nRowSpan++ )
3007 {
3008 sal_uInt32 nR = nRowSpan + nRow;
3009 if ( nR < aRows.size() )
3010 nBottom += aRows[ nR ].second;
3011 else
3012 nBottom = rect.Bottom();
3013 }
3014 return nBottom;
3015}
3016
3017void PPTWriter::WriteCString( SvStream& rSt, const OUString& rString, sal_uInt32 nInstance )
3018{
3019 sal_Int32 nLen = rString.getLength();
3020 if ( nLen )
3021 {
3022 rSt.WriteUInt32( ( nInstance << 4 ) | ( EPP_CString4026 << 16 ) )
3023 .WriteUInt32( nLen << 1 );
3024 for ( sal_Int32 i = 0; i < nLen; i++ )
3025 rSt.WriteUInt16( rString[i] );
3026 }
3027}
3028
3029namespace {
3030
3031class ContainerGuard
3032{
3033private:
3034 PptEscherEx* m_pPptEscherEx;
3035public:
3036 ContainerGuard(PptEscherEx* pPptEscherEx, sal_uInt16 nRecord)
3037 : m_pPptEscherEx(pPptEscherEx)
3038 {
3039 m_pPptEscherEx->OpenContainer(nRecord);
3040 }
3041 ~ContainerGuard()
3042 {
3043 m_pPptEscherEx->CloseContainer();
3044 }
3045};
3046
3047}
3048
3049void PPTWriter::ImplCreateTable( uno::Reference< drawing::XShape > const & rXShape, EscherSolverContainer& aSolverContainer,
3050 EscherPropertyContainer& aPropOpt )
3051{
3052 try
3053 {
3054 uno::Reference< table::XTable > xTable;
3055 if ( mXPropSet->getPropertyValue( "Model" ) >>= xTable )
3056 {
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() );
3062
3063 std::vector< std::pair< sal_Int32, sal_Int32 > > aColumns;
3064 std::vector< std::pair< sal_Int32, sal_Int32 > > aRows;
3065
3066 awt::Point aPosition( MapPoint( rXShape->getPosition() ) );
3067 sal_Int32 nPosition = aPosition.X;
3068 for ( sal_Int32 x = 0; x < nColumnCount; x++ )
3069 {
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 );
3078 }
3079
3080 nPosition = aPosition.Y;
3081 for ( sal_Int32 y = 0; y < nRowCount; y++ )
3082 {
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 );
3091 }
3092 std::unique_ptr<ContainerGuard> xSpgrContainer(new ContainerGuard(mpPptEscherEx.get(), ESCHER_SpgrContainer0xF003u));
3093 std::unique_ptr<ContainerGuard> xSpContainer(new ContainerGuard(mpPptEscherEx.get(), ESCHER_SpContainer0xF004u));
3094 mpPptEscherEx->AddAtom( 16, ESCHER_Spgr0xF009u, 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() );
3099
3100 sal_uInt32 nShapeId = mpPptEscherEx->GenerateShapeId();
3101 mpPptEscherEx->AddShape( ESCHER_ShpInst_Min0, 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;
3105
3106 SvMemoryStream aMemStrm;
3107 aMemStrm.WriteUInt16( nRowCount )
3108 .WriteUInt16( nRowCount )
3109 .WriteUInt16( 4 );
3110
3111 for( const auto& rRow : aRows )
3112 aMemStrm.WriteInt32( rRow.second );
3113
3114 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping127, 0x1000100 );
3115 aPropOpt2.AddOpt( ESCHER_Prop_tableProperties927, 1 );
3116 aPropOpt2.AddOpt(ESCHER_Prop_tableRowProperties928, true, 0, aMemStrm);
3117 aPropOpt.CreateShapeProperties( rXShape );
3118 aPropOpt.Commit( *mpStrm );
3119 aPropOpt2.Commit( *mpStrm, 3, ESCHER_UDefProp0xF122u );
3120 if ( GetCurrentGroupLevel() > 0 )
3121 mpPptEscherEx->AddChildAnchor( maRect );
3122 else
3123 mpPptEscherEx->AddClientAnchor( maRect );
3124 xSpContainer.reset(); //ESCHER_SpContainer
3125
3126 uno::Reference< table::XCellRange > xCellRange( xTable, uno::UNO_QUERY_THROW );
3127 for( sal_Int32 nRow = 0; nRow < xRows->getCount(); nRow++ )
3128 {
3129 for( sal_Int32 nColumn = 0; nColumn < xColumns->getCount(); nColumn++ )
3130 {
3131 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nColumn, nRow ), uno::UNO_QUERY_THROW );
3132 if ( !xCell->isMerged() )
3133 {
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 );
3138
3139 mbFontIndependentLineSpacing = false;
3140 mXPropSet.set( xCell, uno::UNO_QUERY_THROW );
3141 mXText.set( xCell, uno::UNO_QUERY_THROW );
3142 mnTextSize = mXText->getString().getLength();
3143
3144 css::uno::Any aAny;
3145 if ( GetPropertyValue( aAny, mXPropSet, "FontIndependentLineSpacing", true ) )
3146 aAny >>= mbFontIndependentLineSpacing;
3147
3148 EscherPropertyContainer aPropOptSp;
3149 std::unique_ptr<ContainerGuard> xCellContainer(new ContainerGuard(mpPptEscherEx.get(), ESCHER_SpContainer0xF004u));
3150 ImplCreateShape( ESCHER_ShpInst_Rectangle1,
3151 ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty | ShapeFlag::Child,
3152 aSolverContainer );
3153 aPropOptSp.CreateFillProperties( mXPropSet, true );
3154 aPropOptSp.AddOpt( ESCHER_Prop_fNoLineDrawDash511, 0x90000 );
3155 mnTxId += 0x60;
3156 aPropOptSp.CreateTextProperties( mXPropSet, mnTxId );
3157 aPropOptSp.AddOpt( ESCHER_Prop_WrapText133, ESCHER_WrapSquare );
3158
3159 SvMemoryStream aClientTextBox( 0x200, 0x200 );
3160 SvMemoryStream aExtBu( 0x200, 0x200 );
3161
3162 ImplWriteTextStyleAtom( aClientTextBox, EPP_TEXTTYPE_Other4, 0, nullptr, aExtBu, &aPropOptSp );
3163
3164 // need write client data for extend bullet
3165 if ( aExtBu.Tell() )
3166 {
3167 std::unique_ptr<SvMemoryStream> pClientData(new SvMemoryStream( 0x200, 0x200 ));
3168 ImplProgTagContainer( pClientData.get(), &aExtBu );
3169 mpStrm->WriteUInt32( ( ESCHER_ClientData0xF011u << 16 ) | 0xf )
3170 .WriteUInt32( pClientData->Tell() );
3171
3172 mpStrm->WriteBytes(pClientData->GetData(), pClientData->Tell());
3173 }
3174
3175 aPropOptSp.Commit( *mpStrm );
3176 mpPptEscherEx->AddAtom( 16, ESCHER_ChildAnchor0xF00Fu );
3177 mpStrm ->WriteInt32( nLeft )
3178 .WriteInt32( nTop )
3179 .WriteInt32( nRight )
3180 .WriteInt32( nBottom );
3181
3182 mpStrm->WriteUInt32( ( ESCHER_ClientTextbox0xF00Du << 16 ) | 0xf )
3183 .WriteUInt32( aClientTextBox.Tell() );
3184
3185 mpStrm->WriteBytes(aClientTextBox.GetData(), aClientTextBox.Tell());
3186 xCellContainer.reset();
3187 }
3188 }
3189 }
3190
3191 // creating horz lines
3192 for( sal_Int32 nLine = 0; nLine < ( xRows->getCount() + 1 ); nLine++ )
3193 {
3194 for( sal_Int32 nColumn = 0; nColumn < xColumns->getCount(); nColumn++ )
3195 {
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() )
3204 {
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 );
3212 }
3213 }
3214
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;
3220
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() )
3225 {
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 ) )
3229 {
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);
3237 }
3238 nRow=0;
3239 }
3240 else
3241 nRow--;
3242 }
3243 }
3244 }
3245 }
3246
3247 // creating vertical lines
3248 for( sal_Int32 nLine = 0; nLine < ( xColumns->getCount() + 1 ); nLine++ )
3249 {
3250 for( sal_Int32 nRow = 0; nRow < xRows->getCount(); nRow++ )
3251 {
3252
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() )
3260 {
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 );
3268 }
3269 }
3270 if ( ( nLine && !bLeft )||(nLine == xColumns->getCount()))
3271 { // right border
3272 sal_Int32 nColumn = nLine;
3273 while ( nColumn )
3274 {
3275 uno::Reference< table::XMergeableCell > xCell( xCellRange->getCellByPosition( nColumn - 1, nRow ), uno::UNO_QUERY_THROW );
3276 if (!xCell->isMerged() )
3277 {
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) )
3281 {
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 );
3289 }
3290 nColumn = 0;
3291 }
3292 else
3293 nColumn --;
3294 }
3295 }
3296 }
3297 }
3298
3299 xSpgrContainer.reset(); //ESCHER_SpgrContainer
3300 }
3301 }
3302 catch( uno::Exception& )
3303 {
3304 }
3305}
3306
3307void TextObjBinary::Write( SvStream* pStrm )
3308{
3309 sal_uInt32 nSize, nPos = pStrm->Tell();
3310 pStrm->WriteUInt32( EPP_TextCharsAtom4000 << 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 );
3317}
3318
3319void TextObjBinary::WriteTextSpecInfo( SvStream* pStrm )
3320{
3321 sal_uInt32 nCharactersLeft( Count() );
3322 if ( nCharactersLeft < 1 )
3323 return;
3324
3325 EscherExAtom aAnimationInfoAtom( *pStrm, EPP_TextSpecInfoAtom4010, 0, 0 );
3326 for ( sal_uInt32 i = 0; nCharactersLeft && i < ParagraphCount(); ++i )
3327 {
3328 ParagraphObj* pPtr = GetParagraph(i);
3329 for ( std::vector<std::unique_ptr<PortionObj> >::const_iterator it = pPtr->begin(); nCharactersLeft && it != pPtr->end(); ++it )
3330 {
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
3340 }
3341 }
3342 if ( nCharactersLeft )
3343 pStrm->WriteUInt32( nCharactersLeft ).WriteInt32( 1 ).WriteInt16( 1 );
3344}
3345
3346/* vim:set shiftwidth=4 softtabstop=4 expandtab: */