xref: /trunk/main/sd/source/filter/eppt/escherex.cxx (revision 79aad27f)
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