cid#1607171 Data race condition
[LibreOffice.git] / sd / source / filter / eppt / escherex.cxx
blobc1d449b735ad48f826cbd0da3605be665fc1801f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "escherex.hxx"
22 PptEscherEx::PptEscherEx( SvStream& rOutStrm, const OUString& rBaseURI ) :
23 EscherEx( std::make_shared<EscherExGlobal>( ), &rOutStrm )
25 mxGlobal->SetBaseURI( rBaseURI );
26 mnCurrentDg = 0;
29 sal_uInt32 PptEscherEx::DrawingGroupContainerSize()
31 return ImplDggContainerSize() + 8;
34 void PptEscherEx::WriteDrawingGroupContainer( SvStream& rSt )
36 sal_uInt32 nSize = DrawingGroupContainerSize();
37 rSt.WriteUInt32( 0xf | ( 1035 << 16 ) ) // EPP_PPDrawingGroup
38 .WriteUInt32( nSize - 8 );
40 ImplWriteDggContainer( rSt );
43 sal_uInt32 PptEscherEx::ImplDggContainerSize()
45 sal_uInt32 nSize;
47 nSize = mxGlobal->GetDggAtomSize();
48 nSize += mxGlobal->GetBlibStoreContainerSize();
49 nSize += ImplOptAtomSize();
50 nSize += ImplSplitMenuColorsAtomSize();
52 return nSize + 8;
55 void PptEscherEx::ImplWriteDggContainer( SvStream& rSt )
57 sal_uInt32 nSize = ImplDggContainerSize();
58 if ( nSize )
60 rSt.WriteUInt32( 0xf | ( ESCHER_DggContainer << 16 ) )
61 .WriteUInt32( nSize - 8 );
63 mxGlobal->SetDggContainer();
64 mxGlobal->WriteDggAtom( rSt );
65 mxGlobal->WriteBlibStoreContainer( rSt );
66 ImplWriteOptAtom( rSt );
67 ImplWriteSplitMenuColorsAtom( rSt );
71 #define ESCHER_OPT_COUNT 6
73 sal_uInt32 PptEscherEx::ImplOptAtomSize()
75 sal_uInt32 nSize = 0;
76 if ( ESCHER_OPT_COUNT != 0 )
77 nSize = ( ESCHER_OPT_COUNT * 6 ) + 8;
78 return nSize;
81 void PptEscherEx::ImplWriteOptAtom( SvStream& rSt )
83 sal_uInt32 nSize = ImplOptAtomSize();
84 if ( nSize )
86 rSt.WriteUInt32( ( ESCHER_OPT << 16 ) | ( ESCHER_OPT_COUNT << 4 ) | 0x3 )
87 .WriteUInt32( nSize - 8 )
88 .WriteUInt16( ESCHER_Prop_fillColor ) .WriteUInt32( 0xffb800 )
89 .WriteUInt16( ESCHER_Prop_fillBackColor ) .WriteUInt32( 0 )
90 .WriteUInt16( ESCHER_Prop_fNoFillHitTest ) .WriteUInt32( 0x00100010 )
91 .WriteUInt16( ESCHER_Prop_lineColor ) .WriteUInt32( 0x8000001 )
92 .WriteUInt16( ESCHER_Prop_fNoLineDrawDash ) .WriteUInt32( 0x00080008 )
93 .WriteUInt16( ESCHER_Prop_shadowColor ) .WriteUInt32( 0x8000002 );
97 #define ESCHER_SPLIT_MENU_COLORS_COUNT 4
99 sal_uInt32 PptEscherEx::ImplSplitMenuColorsAtomSize()
101 sal_uInt32 nSize = 0;
102 if ( ESCHER_SPLIT_MENU_COLORS_COUNT != 0 )
103 nSize = ( ESCHER_SPLIT_MENU_COLORS_COUNT << 2 ) + 8;
104 return nSize;
107 void PptEscherEx::ImplWriteSplitMenuColorsAtom( SvStream& rSt )
109 sal_uInt32 nSize = ImplSplitMenuColorsAtomSize();
110 if ( nSize )
112 rSt.WriteUInt32( ( ESCHER_SplitMenuColors << 16 ) | ( ESCHER_SPLIT_MENU_COLORS_COUNT << 4 ) )
113 .WriteUInt32( nSize - 8 )
114 .WriteUInt32( 0x08000004 )
115 .WriteUInt32( 0x08000001 )
116 .WriteUInt32( 0x08000002 )
117 .WriteUInt32( 0x100000f7 );
122 PptEscherEx::~PptEscherEx()
126 void PptEscherEx::OpenContainer( sal_uInt16 n_EscherContainer, int nRecInstance )
128 mpOutStrm->WriteUInt16( ( nRecInstance << 4 ) | 0xf ).WriteUInt16( n_EscherContainer ).WriteUInt32( 0 );
129 mOffsets.push_back( mpOutStrm->Tell() - 4 );
130 mRecTypes.push_back( n_EscherContainer );
132 switch( n_EscherContainer )
134 case ESCHER_DgContainer :
136 if ( !mbEscherDg )
138 mbEscherDg = true;
139 mnCurrentDg = mxGlobal->GenerateDrawingId();
140 AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
141 PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
142 mpOutStrm->WriteUInt32( 0 ) // The number of shapes in this drawing
143 .WriteUInt32( 0 ); // The last MSOSPID given to an SP in this DG
146 break;
148 case ESCHER_SpgrContainer :
150 if ( mbEscherDg )
152 mbEscherSpgr = true;
155 break;
157 default:
158 break;
162 void PptEscherEx::CloseContainer()
164 /* SJ: #Issue 26747#
165 not creating group objects with a depth higher than 16, because then
166 PPT is having a big performance problem when starting a slide show
168 if ( ( mRecTypes.back() == ESCHER_SpgrContainer ) && ( mnGroupLevel >= 12 ) )
169 return;
171 sal_uInt64 nPos = mpOutStrm->Tell();
172 sal_uInt32 nSize = ( nPos - mOffsets.back() ) - 4;
173 mpOutStrm->Seek( mOffsets.back() );
174 mpOutStrm->WriteUInt32( nSize );
176 switch( mRecTypes.back() )
178 case ESCHER_DgContainer :
180 if ( mbEscherDg )
182 mbEscherDg = false;
183 if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
184 mpOutStrm->WriteUInt32( mxGlobal->GetDrawingShapeCount( mnCurrentDg ) ).WriteUInt32( mxGlobal->GetLastShapeId( mnCurrentDg ) );
187 break;
189 case ESCHER_SpgrContainer :
191 if ( mbEscherSpgr )
193 mbEscherSpgr = false;
196 break;
198 default:
199 break;
201 mOffsets.pop_back();
202 mRecTypes.pop_back();
203 mpOutStrm->Seek( nPos );
206 sal_uInt32 PptEscherEx::EnterGroup( ::tools::Rectangle const * pBoundRect, SvMemoryStream* pClientData )
208 sal_uInt32 nShapeId = 0;
209 /* SJ: #Issue 26747#
210 not creating group objects with a depth higher than 16, because then
211 PPT is having a big performance problem when starting a slide show
213 if ( mnGroupLevel < 12 )
215 ::tools::Rectangle aRect;
216 if ( pBoundRect )
217 aRect = *pBoundRect;
219 OpenContainer( ESCHER_SpgrContainer );
220 OpenContainer( ESCHER_SpContainer );
221 AddAtom( 16, ESCHER_Spgr, 1 );
222 PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel, mpOutStrm->Tell() );
223 mpOutStrm ->WriteInt32( aRect.Left() ) // bounding box for the grouped shapes to which they are attached
224 .WriteInt32( aRect.Top() )
225 .WriteInt32( aRect.Right() )
226 .WriteInt32( aRect.Bottom() );
228 nShapeId = GenerateShapeId();
229 if ( !mnGroupLevel )
230 AddShape( ESCHER_ShpInst_Min, ShapeFlag::Group | ShapeFlag::Patriarch, nShapeId );
231 else
233 AddShape( ESCHER_ShpInst_Min, ShapeFlag::HaveAnchor | ShapeFlag::Group, nShapeId );
234 if ( mnGroupLevel == 1 )
236 AddAtom( 8, ESCHER_ClientAnchor );
237 PtReplaceOrInsert( ESCHER_Persist_Grouping_Logic | mnGroupLevel, mpOutStrm->Tell() );
238 mpOutStrm->WriteInt16( aRect.Top() ).WriteInt16( aRect.Left() ).WriteInt16( aRect.Right() ).WriteInt16( aRect.Bottom() );
240 else
242 AddAtom( 16, ESCHER_ChildAnchor );
243 PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel, mpOutStrm->Tell() );
244 mpOutStrm ->WriteInt32( aRect.Left() )
245 .WriteInt32( aRect.Top() )
246 .WriteInt32( aRect.Right() )
247 .WriteInt32( aRect.Bottom() );
250 if ( pClientData )
252 sal_uInt32 nSize = pClientData->TellEnd();
253 if ( nSize )
255 mpOutStrm->WriteUInt32( ( ESCHER_ClientData << 16 ) | 0xf )
256 .WriteUInt32( nSize );
257 mpOutStrm->WriteBytes(pClientData->GetData(), nSize);
260 CloseContainer(); // ESCHER_SpContainer
262 mnGroupLevel++;
263 return nShapeId;
266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */