xref: /AOO41X/main/sd/source/filter/eppt/escherex.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
27 
28 #ifndef _PptEscherEx_HXX
29 #include "escherex.hxx"
30 #endif
31 
32 // ---------------------------------------------------------------------------------------------
33 // ---------------------------------------------------------------------------------------------
34 // ---------------------------------------------------------------------------------------------
35 
PptEscherEx(SvStream & rOutStrm,const rtl::OUString & rBaseURI)36 PptEscherEx::PptEscherEx( SvStream& rOutStrm, const rtl::OUString& rBaseURI ) :
37     EscherEx( EscherExGlobalRef( new EscherExGlobal ), rOutStrm )
38 {
39     mxGlobal->SetBaseURI( rBaseURI );
40     mnCurrentDg = 0;
41 }
42 
43 // ---------------------------------------------------------------------------------------------
44 
DrawingGroupContainerSize()45 sal_uInt32 PptEscherEx::DrawingGroupContainerSize()
46 {
47     return ImplDggContainerSize() + 8;
48 }
49 
WriteDrawingGroupContainer(SvStream & rSt)50 void PptEscherEx::WriteDrawingGroupContainer( SvStream& rSt )
51 {
52     sal_uInt32 nSize = DrawingGroupContainerSize();
53     rSt << (sal_uInt32)( 0xf | ( 1035 << 16 ) )     // EPP_PPDrawingGroup
54         << (sal_uInt32)( nSize - 8 );
55 
56     ImplWriteDggContainer( rSt );
57 }
58 
59 // ---------------------------------------------------------------------------------------------
60 
ImplDggContainerSize()61 sal_uInt32 PptEscherEx::ImplDggContainerSize()
62 {
63     sal_uInt32 nSize;
64 
65     nSize  = mxGlobal->GetDggAtomSize();
66     nSize += mxGlobal->GetBlibStoreContainerSize();
67     nSize += ImplOptAtomSize();
68     nSize += ImplSplitMenuColorsAtomSize();
69 
70     return nSize + 8;
71 }
72 
ImplWriteDggContainer(SvStream & rSt)73 void PptEscherEx::ImplWriteDggContainer( SvStream& rSt )
74 {
75     sal_uInt32 nSize = ImplDggContainerSize();
76     if ( nSize )
77     {
78         rSt << (sal_uInt32)( 0xf | ( ESCHER_DggContainer << 16 ) )
79             << (sal_uInt32)( nSize - 8 );
80 
81         mxGlobal->SetDggContainer();
82         mxGlobal->WriteDggAtom( rSt );
83         mxGlobal->WriteBlibStoreContainer( rSt );
84         ImplWriteOptAtom( rSt );
85         ImplWriteSplitMenuColorsAtom( rSt );
86     }
87 }
88 
89 // ---------------------------------------------------------------------------------------------
90 
91 #define ESCHER_OPT_COUNT 6
92 
ImplOptAtomSize()93 sal_uInt32 PptEscherEx::ImplOptAtomSize()
94 {
95     sal_uInt32 nSize = 0;
96     if ( ESCHER_OPT_COUNT )
97         nSize = ( ESCHER_OPT_COUNT * 6 ) + 8;
98     return nSize;
99 }
100 
ImplWriteOptAtom(SvStream & rSt)101 void PptEscherEx::ImplWriteOptAtom( SvStream& rSt )
102 {
103     sal_uInt32 nSize = ImplOptAtomSize();
104     if ( nSize )
105     {
106         rSt << (sal_uInt32)( ( ESCHER_OPT << 16 ) | ( ESCHER_OPT_COUNT << 4 ) | 0x3 )
107             << (sal_uInt32)( nSize - 8 )
108             << (sal_uInt16)ESCHER_Prop_fillColor            << (sal_uInt32)0xffb800
109             << (sal_uInt16)ESCHER_Prop_fillBackColor        << (sal_uInt32)0
110             << (sal_uInt16)ESCHER_Prop_fNoFillHitTest       << (sal_uInt32)0x00100010
111             << (sal_uInt16)ESCHER_Prop_lineColor            << (sal_uInt32)0x8000001
112             << (sal_uInt16)ESCHER_Prop_fNoLineDrawDash      << (sal_uInt32)0x00080008
113             << (sal_uInt16)ESCHER_Prop_shadowColor          << (sal_uInt32)0x8000002;
114     }
115 }
116 
117 // ---------------------------------------------------------------------------------------------
118 
119 #define ESCHER_SPLIT_MENU_COLORS_COUNT  4
120 
ImplSplitMenuColorsAtomSize()121 sal_uInt32 PptEscherEx::ImplSplitMenuColorsAtomSize()
122 {
123     sal_uInt32 nSize = 0;
124     if ( ESCHER_SPLIT_MENU_COLORS_COUNT )
125         nSize = ( ESCHER_SPLIT_MENU_COLORS_COUNT << 2 ) + 8;
126     return nSize;
127 }
128 
ImplWriteSplitMenuColorsAtom(SvStream & rSt)129 void PptEscherEx::ImplWriteSplitMenuColorsAtom( SvStream& rSt )
130 {
131     sal_uInt32 nSize = ImplSplitMenuColorsAtomSize();
132     if ( nSize )
133     {
134         rSt << (sal_uInt32)( ( ESCHER_SplitMenuColors << 16 ) | ( ESCHER_SPLIT_MENU_COLORS_COUNT << 4 ) )
135             << (sal_uInt32)( nSize - 8 )
136             << (sal_uInt32)0x08000004
137             << (sal_uInt32)0x08000001
138             << (sal_uInt32)0x08000002
139             << (sal_uInt32)0x100000f7;
140     }
141 
142 }
143 
144 // ---------------------------------------------------------------------------------------------
145 
~PptEscherEx()146 PptEscherEx::~PptEscherEx()
147 {
148 }
149 
150 // ---------------------------------------------------------------------------------------------
151 
OpenContainer(sal_uInt16 n_EscherContainer,int nRecInstance)152 void PptEscherEx::OpenContainer( sal_uInt16 n_EscherContainer, int nRecInstance )
153 {
154     *mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | 0xf  ) << n_EscherContainer << (sal_uInt32)0;
155     mOffsets.push_back( mpOutStrm->Tell() - 4 );
156     mRecTypes.push_back( n_EscherContainer );
157 
158     switch( n_EscherContainer )
159     {
160         case ESCHER_DgContainer :
161         {
162             if ( !mbEscherDg )
163             {
164                 mbEscherDg = sal_True;
165                 mnCurrentDg = mxGlobal->GenerateDrawingId();
166                 AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
167                 PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
168                 *mpOutStrm << (sal_uInt32)0     // The number of shapes in this drawing
169                            << (sal_uInt32)0;    // The last MSOSPID given to an SP in this DG
170             }
171         }
172         break;
173 
174         case ESCHER_SpgrContainer :
175         {
176             if ( mbEscherDg )
177             {
178                 mbEscherSpgr = sal_True;
179             }
180         }
181         break;
182 
183         case ESCHER_SpContainer :
184         {
185         }
186         break;
187 
188         default:
189         break;
190     }
191 }
192 
193 // ---------------------------------------------------------------------------------------------
194 
CloseContainer()195 void PptEscherEx::CloseContainer()
196 {
197     /* SJ: #Issue 26747#
198        not creating group objects with a depth higher than 16, because then
199        PPT is having a big performance problem when starting a slide show
200     */
201     if ( ( mRecTypes.back() != ESCHER_SpgrContainer ) || ( mnGroupLevel < 12 ) )
202     {
203         sal_uInt32 nSize, nPos = mpOutStrm->Tell();
204         nSize = ( nPos - mOffsets.back() ) - 4;
205         mpOutStrm->Seek( mOffsets.back() );
206         *mpOutStrm << nSize;
207 
208         switch( mRecTypes.back() )
209         {
210             case ESCHER_DgContainer :
211             {
212                 if ( mbEscherDg )
213                 {
214                     mbEscherDg = sal_False;
215                     if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
216                         *mpOutStrm << mxGlobal->GetDrawingShapeCount( mnCurrentDg ) << mxGlobal->GetLastShapeId( mnCurrentDg );
217                 }
218             }
219             break;
220 
221             case ESCHER_SpgrContainer :
222             {
223                 if ( mbEscherSpgr )
224                 {
225                     mbEscherSpgr = sal_False;
226 
227                 }
228             }
229             break;
230 
231             default:
232             break;
233         }
234         mOffsets.pop_back();
235         mRecTypes.pop_back();
236         mpOutStrm->Seek( nPos );
237     }
238 }
239 
240 // ---------------------------------------------------------------------------------------------
241 
EnterGroup(Rectangle * pBoundRect,SvMemoryStream * pClientData)242 sal_uInt32 PptEscherEx::EnterGroup( Rectangle* pBoundRect, SvMemoryStream* pClientData )
243 {
244     sal_uInt32 nShapeId = 0;
245     /* SJ: #Issue 26747#
246        not creating group objects with a depth higher than 16, because then
247        PPT is having a big performance problem when starting a slide show
248     */
249     if ( mnGroupLevel < 12 )
250     {
251         Rectangle aRect;
252         if ( pBoundRect )
253             aRect = *pBoundRect;
254 
255         OpenContainer( ESCHER_SpgrContainer );
256         OpenContainer( ESCHER_SpContainer );
257         AddAtom( 16, ESCHER_Spgr, 1 );
258         PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel, mpOutStrm->Tell() );
259         *mpOutStrm  << (sal_Int32)aRect.Left()  // Bounding box fuer die Gruppierten shapes an die sie attached werden
260                     << (sal_Int32)aRect.Top()
261                     << (sal_Int32)aRect.Right()
262                     << (sal_Int32)aRect.Bottom();
263 
264         nShapeId = GenerateShapeId();
265         if ( !mnGroupLevel )
266             AddShape( ESCHER_ShpInst_Min, 5, nShapeId );                    // Flags: Group | Patriarch
267         else
268         {
269             AddShape( ESCHER_ShpInst_Min, 0x201, nShapeId );                // Flags: Group | HaveAnchor
270             if ( mnGroupLevel == 1 )
271             {
272                 AddAtom( 8, ESCHER_ClientAnchor );
273                 PtReplaceOrInsert( ESCHER_Persist_Grouping_Logic | mnGroupLevel, mpOutStrm->Tell() );
274                 *mpOutStrm << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left() << (sal_Int16)aRect.Right() << (sal_Int16)aRect.Bottom();
275             }
276             else
277             {
278                 AddAtom( 16, ESCHER_ChildAnchor );
279                 PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel, mpOutStrm->Tell() );
280                 *mpOutStrm  << (sal_Int32)aRect.Left()
281                             << (sal_Int32)aRect.Top()
282                             << (sal_Int32)aRect.Right()
283                             << (sal_Int32)aRect.Bottom();
284             }
285         }
286         if ( pClientData )
287         {
288             pClientData->Seek( STREAM_SEEK_TO_END );
289             sal_uInt32 nSize = pClientData->Tell();
290             if ( nSize )
291             {
292                 *mpOutStrm << (sal_uInt32)( ( ESCHER_ClientData << 16 ) | 0xf )
293                         << nSize;
294                 mpOutStrm->Write( pClientData->GetData(), nSize );
295             }
296         }
297         CloseContainer();                                               // ESCHER_SpContainer
298     }
299     mnGroupLevel++;
300     return nShapeId;
301 }
302 
303 // ---------------------------------------------------------------------------------------------
304