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_filter.hxx"
26 #include "eschesdo.hxx"
27 #include <filter/msfilter/escherex.hxx>
28 #include <svx/unoapi.hxx>
29 #include <svx/svdobj.hxx>
30 #include <svx/svdoashp.hxx>
31 #include <svx/svdoole2.hxx>
32 #include <svx/svdmodel.hxx>
33 #include <editeng/outlobj.hxx>
34 #include <vcl/gradient.hxx>
35 #include <vcl/graph.hxx>
36 #include <vcl/cvtgrf.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/wrkwin.hxx>
39 #include <tools/stream.hxx>
40 #include <tools/zcodec.hxx>
41 #include <svx/svdopath.hxx>
42 #include <stdlib.h>
43 #include <svtools/filter.hxx>
44 #include "svx/EnhancedCustomShapeTypeNames.hxx"
45 #include "svx/EnhancedCustomShapeGeometry.hxx"
46 #include <svx/EnhancedCustomShapeFunctionParser.hxx>
47 #include "svx/EnhancedCustomShape2d.hxx"
48 #include <com/sun/star/beans/PropertyValues.hpp>
49 #include <com/sun/star/beans/XPropertyState.hpp>
50 #include <com/sun/star/awt/GradientStyle.hpp>
51 #include <com/sun/star/awt/RasterOperation.hpp>
52 #include <com/sun/star/awt/Gradient.hpp>
53 #include <com/sun/star/drawing/LineStyle.hpp>
54 #include <com/sun/star/drawing/LineJoint.hpp>
55 #include <com/sun/star/drawing/LineCap.hpp>
56 #include <com/sun/star/drawing/FillStyle.hpp>
57 #include <com/sun/star/drawing/LineDash.hpp>
58 #include <com/sun/star/drawing/BezierPoint.hpp>
59 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
60 #include <com/sun/star/drawing/ConnectorType.hpp>
61 #include <com/sun/star/drawing/ConnectionType.hpp>
62 #include <com/sun/star/drawing/CircleKind.hpp>
63 #include <com/sun/star/drawing/PointSequence.hpp>
64 #include <com/sun/star/drawing/FlagSequence.hpp>
65 #include <com/sun/star/drawing/PolygonFlags.hpp>
66 #include <com/sun/star/text/WritingMode.hpp>
67 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
68 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
69 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
70 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
71 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
72 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
73 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
74 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
75 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
76 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
77 #include <com/sun/star/drawing/ProjectionMode.hpp>
78 #include <com/sun/star/text/XSimpleText.hpp>
79 #include <com/sun/star/drawing/ShadeMode.hpp>
80 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
81 #include <vcl/hatch.hxx>
82 #include <com/sun/star/awt/XGraphics.hpp>
83 #include <com/sun/star/awt/FontSlant.hpp>
84 #include <com/sun/star/awt/FontWeight.hpp>
85 #include <com/sun/star/drawing/ColorMode.hpp>
86 #include <com/sun/star/drawing/Position3D.hpp>
87 #include <com/sun/star/drawing/Direction3D.hpp>
88 #include <com/sun/star/text/GraphicCrop.hpp>
89 #include <unotools/ucbstreamhelper.hxx>
90 #include <unotools/localfilehelper.hxx>
91 #include <comphelper/extract.hxx>
92 #include <toolkit/unohlp.hxx>
93 #include <vcl/virdev.hxx>
94 #include <rtl/crc.h>
95 #include <vos/xception.hxx>
96 using namespace vos;
97 
98 using namespace ::rtl;
99 using namespace ::com::sun::star;
100 
101 
102 // ---------------------------------------------------------------------------------------------
103 
104 EscherExContainer::EscherExContainer( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance ) :
105 	rStrm	( rSt )
106 {
107 	rStrm << (sal_uInt32)( ( 0xf | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0;
108 	nContPos = rStrm.Tell();
109 }
110 EscherExContainer::~EscherExContainer()
111 {
112 	sal_uInt32 nPos = rStrm.Tell();
113 	sal_uInt32 nSize= nPos - nContPos;
114 	if ( nSize )
115 	{
116 		rStrm.Seek( nContPos - 4 );
117 		rStrm << nSize;
118 		rStrm.Seek( nPos );
119 	}
120 }
121 
122 EscherExAtom::EscherExAtom( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance, const sal_uInt8 nVersion ) :
123 	rStrm	( rSt )
124 {
125 	rStrm << (sal_uInt32)( ( nVersion | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0;
126 	nContPos = rStrm.Tell();
127 }
128 EscherExAtom::~EscherExAtom()
129 {
130 	sal_uInt32 nPos = rStrm.Tell();
131 	sal_uInt32 nSize= nPos - nContPos;
132 	if ( nSize )
133 	{
134 		rStrm.Seek( nContPos - 4 );
135 		rStrm << nSize;
136 		rStrm.Seek( nPos );
137 	}
138 }
139 
140 // ---------------------------------------------------------------------------------------------
141 
142 EscherExClientRecord_Base::~EscherExClientRecord_Base()
143 {
144 }
145 
146 EscherExClientAnchor_Base::~EscherExClientAnchor_Base()
147 {
148 }
149 
150 // ---------------------------------------------------------------------------------------------
151 
152 void EscherPropertyContainer::ImplInit()
153 {
154 	nSortCount = 0;
155 	nCountCount = 0;
156 	nCountSize = 0;
157 	nSortBufSize = 64;
158 	bHasComplexData	= sal_False;
159 	bSuppressRotation = sal_False;
160 	pSortStruct = new EscherPropSortStruct[ nSortBufSize ];
161 }
162 
163 EscherPropertyContainer::EscherPropertyContainer() :
164 	pGraphicProvider	( NULL ),
165 	pPicOutStrm			( NULL )
166 {
167 	ImplInit();
168 };
169 
170 EscherPropertyContainer::EscherPropertyContainer(
171 	EscherGraphicProvider& rGraphProv,
172 			SvStream* pPiOutStrm,
173 				Rectangle& rBoundRect ) :
174 
175 	pGraphicProvider	( &rGraphProv ),
176 	pPicOutStrm			( pPiOutStrm ),
177 	pShapeBoundRect		( &rBoundRect )
178 {
179 	ImplInit();
180 }
181 
182 EscherPropertyContainer::~EscherPropertyContainer()
183 {
184 	if ( bHasComplexData )
185 	{
186 		while ( nSortCount-- )
187 			delete[] pSortStruct[ nSortCount ].pBuf;
188 	}
189 	delete[] pSortStruct;
190 };
191 
192 void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_uInt32 nPropValue, sal_Bool bBlib )
193 {
194 	AddOpt( nPropID, bBlib, nPropValue, NULL, 0 );
195 }
196 
197 void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, const rtl::OUString& rString )
198 {
199 	sal_Int32 j, i, nLen = rString.getLength() * 2 + 2;
200 	sal_uInt8* pBuf = new sal_uInt8[ nLen ];
201 	for ( j = i = 0; i < rString.getLength(); i++ )
202 	{
203 		sal_uInt16 nChar = (sal_uInt16)rString[ i ];
204 		pBuf[ j++ ] = (sal_uInt8)nChar;
205 		pBuf[ j++ ] = (sal_uInt8)( nChar >> 8 );
206 	}
207 	pBuf[ j++ ] = 0;
208 	pBuf[ j++ ] = 0;
209 	AddOpt( nPropID, sal_True, nLen, pBuf, nLen );
210 }
211 
212 void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_Bool bBlib, sal_uInt32 nPropValue, sal_uInt8* pProp, sal_uInt32 nPropSize )
213 {
214 	if ( bBlib )				// bBlib is only valid when fComplex = 0
215 		nPropID |= 0x4000;
216 	if ( pProp )
217 		nPropID |= 0x8000;		// fComplex = sal_True;
218 
219 	sal_uInt32 i;
220 	for( i = 0; i < nSortCount; i++ )
221 	{
222 		if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropID &~0xc000 ) )	// pruefen, ob Property nur ersetzt wird
223 		{
224 			pSortStruct[ i ].nPropId = nPropID;
225 			if ( pSortStruct[ i ].pBuf )
226 			{
227 				nCountSize -= pSortStruct[ i ].nPropSize;
228 				delete[] pSortStruct[ i ].pBuf;
229 			}
230 			pSortStruct[ i ].pBuf = pProp;
231 			pSortStruct[ i ].nPropSize = nPropSize;
232 			pSortStruct[ i ].nPropValue = nPropValue;
233 			if ( pProp )
234 				nCountSize += nPropSize;
235 			return;
236 		}
237 	}
238 	nCountCount++;
239 	nCountSize += 6;
240 	if ( nSortCount == nSortBufSize )											// buffer vergroessern
241 	{
242 		nSortBufSize <<= 1;
243 		EscherPropSortStruct* pTemp = new EscherPropSortStruct[ nSortBufSize ];
244 		for( i = 0; i < nSortCount; i++ )
245 		{
246 			pTemp[ i ] = pSortStruct[ i ];
247 		}
248 		delete pSortStruct;
249 		pSortStruct = pTemp;
250 	}
251 	pSortStruct[ nSortCount ].nPropId = nPropID;								// property einfuegen
252 	pSortStruct[ nSortCount ].pBuf = pProp;
253 	pSortStruct[ nSortCount ].nPropSize = nPropSize;
254 	pSortStruct[ nSortCount++ ].nPropValue = nPropValue;
255 
256 	if ( pProp )
257 	{
258 		nCountSize += nPropSize;
259 		bHasComplexData = sal_True;
260 	}
261 }
262 
263 sal_Bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, sal_uInt32& rPropValue ) const
264 {
265     EscherPropSortStruct aPropStruct;
266 
267     if ( GetOpt( nPropId, aPropStruct ) )
268     {
269         rPropValue = aPropStruct.nPropValue;
270         return sal_True;
271     }
272     return sal_False;
273 }
274 
275 sal_Bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, EscherPropSortStruct& rPropValue ) const
276 {
277 	for( sal_uInt32 i = 0; i < nSortCount; i++ )
278 	{
279 		if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropId &~0xc000 ) )
280 		{
281 			rPropValue = pSortStruct[ i ];
282 			return sal_True;
283 		}
284 	}
285 	return sal_False;
286 }
287 
288 EscherProperties EscherPropertyContainer::GetOpts() const
289 {
290 	EscherProperties aVector;
291 
292 	for ( sal_uInt32 i = 0; i < nSortCount; ++i )
293 		aVector.push_back( pSortStruct[ i ] );
294 
295 	return aVector;
296 }
297 
298 extern "C" int __LOADONCALLAPI EscherPropSortFunc( const void* p1, const void* p2 )
299 {
300 	sal_Int16	nID1 = ((EscherPropSortStruct*)p1)->nPropId &~0xc000;
301 	sal_Int16	nID2 = ((EscherPropSortStruct*)p2)->nPropId &~0xc000;
302 
303 	if( nID1  < nID2 )
304 		return -1;
305 	else if( nID1 > nID2 )
306 		return 1;
307 	else
308 		return 0;
309 }
310 
311 void EscherPropertyContainer::Commit( SvStream& rSt, sal_uInt16 nVersion, sal_uInt16 nRecType )
312 {
313 	rSt << (sal_uInt16)( ( nCountCount << 4 ) | ( nVersion & 0xf ) ) << nRecType << nCountSize;
314 	if ( nSortCount )
315 	{
316 		qsort( pSortStruct, nSortCount, sizeof( EscherPropSortStruct ), EscherPropSortFunc );
317 		sal_uInt32 i;
318 
319 		for ( i = 0; i < nSortCount; i++ )
320 		{
321 			sal_uInt32 nPropValue = pSortStruct[ i ].nPropValue;
322 			sal_uInt16 nPropId = pSortStruct[ i ].nPropId;
323 
324 			if ( bSuppressRotation && ( nPropId == ESCHER_Prop_Rotation ) )
325 				nPropValue = 0;
326 
327 			rSt << nPropId
328 				<< nPropValue;
329 		}
330 		if ( bHasComplexData )
331 		{
332 			for ( i = 0; i < nSortCount; i++ )
333 			{
334 				if ( pSortStruct[ i ].pBuf )
335 					rSt.Write( pSortStruct[ i ].pBuf, pSortStruct[ i ].nPropSize );
336 			}
337 		}
338 	}
339 }
340 
341 sal_Bool EscherPropertyContainer::IsFontWork() const
342 {
343 	sal_uInt32 nTextPathFlags = 0;
344 	GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
345 	return ( nTextPathFlags & 0x4000 ) != 0;
346 }
347 
348 sal_uInt32 EscherPropertyContainer::ImplGetColor( const sal_uInt32 nSOColor, sal_Bool bSwap )
349 {
350 	if ( bSwap )
351 	{
352 		sal_uInt32 nColor = nSOColor & 0xff00;		// GRUEN
353 		nColor |= (sal_uInt8)( nSOColor ) << 16;	// ROT
354 		nColor |= (sal_uInt8)( nSOColor >> 16 );	// BLAU
355 		return nColor;
356 	}
357 	else
358 		return nSOColor & 0xffffff;
359 }
360 
361 sal_uInt32 EscherPropertyContainer::GetGradientColor(
362 	const ::com::sun::star::awt::Gradient* pGradient,
363 		sal_uInt32 nStartColor )
364 {
365 	sal_uInt32	nIntensity = 100;
366 	Color		aColor;
367 
368 	if ( pGradient )
369 	{
370 		if ( nStartColor & 1 )
371 		{
372 			nIntensity = pGradient->StartIntensity;
373 			aColor = pGradient->StartColor;
374 		}
375 		else
376 		{
377 			nIntensity = pGradient->EndIntensity;
378 			aColor = pGradient->EndColor;
379 		}
380 	}
381 	sal_uInt32	nRed = ( ( aColor.GetRed() * nIntensity ) / 100 );
382 	sal_uInt32	nGreen = ( ( aColor.GetGreen() * nIntensity ) / 100 ) << 8;
383 	sal_uInt32	nBlue = ( ( aColor.GetBlue() * nIntensity ) / 100 ) << 16;
384 	return nRed | nGreen | nBlue;
385 }
386 
387 void EscherPropertyContainer::CreateGradientProperties(
388     const ::com::sun::star::awt::Gradient & rGradient )
389 {
390     sal_uInt32  nFillType = ESCHER_FillShadeScale;
391     sal_uInt32  nAngle = 0;
392     sal_uInt32  nFillFocus = 0;
393     sal_uInt32  nFillLR = 0;
394     sal_uInt32  nFillTB = 0;
395     sal_uInt32  nFirstColor = 0;
396     bool        bWriteFillTo = false;
397 
398     switch ( rGradient.Style )
399     {
400         case ::com::sun::star::awt::GradientStyle_LINEAR :
401         case ::com::sun::star::awt::GradientStyle_AXIAL :
402         {
403             nFillType = ESCHER_FillShadeScale;
404             nAngle = (rGradient.Angle * 0x10000) / 10;
405             nFillFocus = (sal::static_int_cast<int>(rGradient.Style) ==
406                           sal::static_int_cast<int>(GradientStyle_LINEAR)) ? 0 : 50;
407         }
408         break;
409         case ::com::sun::star::awt::GradientStyle_RADIAL :
410         case ::com::sun::star::awt::GradientStyle_ELLIPTICAL :
411         case ::com::sun::star::awt::GradientStyle_SQUARE :
412         case ::com::sun::star::awt::GradientStyle_RECT :
413         {
414             nFillLR = (rGradient.XOffset * 0x10000) / 100;
415             nFillTB = (rGradient.YOffset * 0x10000) / 100;
416             if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) )
417                 nFillType = ESCHER_FillShadeShape;
418             else
419                 nFillType = ESCHER_FillShadeCenter;
420             nFirstColor = 1;
421             bWriteFillTo = true;
422         }
423         break;
424         case ::com::sun::star::awt::GradientStyle_MAKE_FIXED_SIZE : break;
425     }
426     AddOpt( ESCHER_Prop_fillType, nFillType );
427     AddOpt( ESCHER_Prop_fillAngle, nAngle );
428     AddOpt( ESCHER_Prop_fillColor, GetGradientColor( &rGradient, nFirstColor ) );
429     AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( &rGradient, nFirstColor ^ 1 ) );
430     AddOpt( ESCHER_Prop_fillFocus, nFillFocus );
431     if ( bWriteFillTo )
432     {
433         AddOpt( ESCHER_Prop_fillToLeft, nFillLR );
434         AddOpt( ESCHER_Prop_fillToTop, nFillTB );
435         AddOpt( ESCHER_Prop_fillToRight, nFillLR );
436         AddOpt( ESCHER_Prop_fillToBottom, nFillTB );
437     }
438 }
439 
440 void EscherPropertyContainer::CreateGradientProperties(
441     const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet )
442 {
443     ::com::sun::star::uno::Any aAny;
444     ::com::sun::star::awt::Gradient aGradient;
445     if ( EscherPropertyValueHelper::GetPropertyValue(
446             aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillGradient" ) ), sal_False ) )
447     {
448         aGradient = *static_cast< const ::com::sun::star::awt::Gradient* >( aAny.getValue() );
449     }
450     CreateGradientProperties( aGradient );
451 };
452 
453 void EscherPropertyContainer::CreateFillProperties(
454 	const uno::Reference< beans::XPropertySet > & rXPropSet,
455 		sal_Bool bEdge )
456 {
457 	::com::sun::star::uno::Any aAny;
458     AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
459     AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
460 
461     sal_uInt32 nFillBackColor = 0;
462 
463 	const rtl::OUString aPropName( String( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" ) ) );
464     if ( EscherPropertyValueHelper::GetPropertyValue(
465 			aAny, rXPropSet, aPropName, sal_False ) )
466     {
467 		::com::sun::star::drawing::FillStyle eFS;
468 		if ( ! ( aAny >>= eFS ) )
469 			eFS = ::com::sun::star::drawing::FillStyle_SOLID;
470         switch( eFS )
471         {
472             case ::com::sun::star::drawing::FillStyle_GRADIENT :
473             {
474 				CreateGradientProperties( rXPropSet );
475                 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
476             }
477             break;
478 
479             case ::com::sun::star::drawing::FillStyle_BITMAP :
480             {
481                 CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ), sal_True );
482                 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
483                 AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor  );
484             }
485             break;
486             case ::com::sun::star::drawing::FillStyle_HATCH :
487 			{
488 				CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ), sal_True );
489 			}
490 			break;
491             case ::com::sun::star::drawing::FillStyle_SOLID :
492             default:
493             {
494 				::com::sun::star::beans::PropertyState ePropState = EscherPropertyValueHelper::GetPropertyState(
495 					rXPropSet, aPropName );
496 				if ( ePropState == ::com::sun::star::beans::PropertyState_DIRECT_VALUE )
497 	                AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
498 
499 				if ( EscherPropertyValueHelper::GetPropertyValue(
500 						aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), sal_False ) )
501 				{
502                     sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) );
503                     nFillBackColor = nFillColor ^ 0xffffff;
504                     AddOpt( ESCHER_Prop_fillColor, nFillColor );
505 				}
506                 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
507                 AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
508                 break;
509             }
510             case ::com::sun::star::drawing::FillStyle_NONE :
511                 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
512             break;
513         }
514 		if ( eFS != ::com::sun::star::drawing::FillStyle_NONE )
515 		{
516 			sal_uInt16 nTransparency = ( EscherPropertyValueHelper::GetPropertyValue(
517 									aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparence" ) ), sal_True ) )
518 									? *((sal_Int16*)aAny.getValue() )
519 									: 0;
520 			if (  nTransparency )
521 				AddOpt( ESCHER_Prop_fillOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
522 		}
523     }
524     CreateLineProperties( rXPropSet, bEdge );
525 }
526 
527 void EscherPropertyContainer::CreateTextProperties(
528 	const uno::Reference< beans::XPropertySet > & rXPropSet, sal_uInt32 nTextId,
529 		const sal_Bool bIsCustomShape, const sal_Bool bIsTextFrame )
530 {
531     uno::Any aAny;
532 	text::WritingMode				eWM( text::WritingMode_LR_TB );
533     drawing::TextVerticalAdjust		eVA( drawing::TextVerticalAdjust_TOP );
534     drawing::TextHorizontalAdjust	eHA( drawing::TextHorizontalAdjust_LEFT );
535 
536     sal_Int32 nLeft             ( 0 );
537     sal_Int32 nTop              ( 0 );
538     sal_Int32 nRight            ( 0 );
539     sal_Int32 nBottom           ( 0 );
540 
541 	// used with normal shapes:
542 	sal_Bool bAutoGrowWidth     ( sal_False );
543     sal_Bool bAutoGrowHeight    ( sal_False );
544 	// used with ashapes:
545 	sal_Bool bWordWrap			( sal_False );
546 	sal_Bool bAutoGrowSize		( sal_False );
547 
548     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWritingMode" ) ), sal_True ) )
549         aAny >>= eWM;
550     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextVerticalAdjust" ) ), sal_True ) )
551         aAny >>= eVA;
552     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), sal_True ) )
553         aAny >>= eHA;
554 	if ( bIsCustomShape )
555 	{
556 		if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWordWrap" ) ), sal_False ) )
557 			aAny >>= bWordWrap;
558 		if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), sal_True ) )
559 			aAny >>= bAutoGrowSize;
560 	}
561 	else if ( bIsTextFrame )
562 	{
563 		if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowWidth" ) ), sal_True ) )
564 			aAny >>= bAutoGrowWidth;
565 
566 // i63936 not setting autogrowheight, because otherwise
567 // the minframeheight of the text will be ignored
568 //
569 //		if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), sal_True ) )
570 //			aAny >>= bAutoGrowHeight;
571 	}
572     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ) ) )
573         aAny >>= nLeft;
574     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ) ) )
575         aAny >>= nTop;
576     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ) ) )
577         aAny >>= nRight;
578     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ) ) )
579         aAny >>= nBottom;
580 
581 /*
582     if ( rObj.ImplGetPropertyValue(
583         ::rtl::OUString::createFromAscii("TextWritingMode") ) )
584     {
585         ::com::sun::star::text::WritingMode eMode;
586         rObj.GetUsrAny() >>= eMode;
587         switch (eMode)
588         {
589             case ::com::sun::star::text::WritingMode_TB_RL:
590                 //Well if it so happens that we are fliped 180 we can use
591                 //this instead.
592                 if (rObj.GetAngle() == 18000)
593                     eFlow = ESCHER_txflBtoT;
594                 else
595                     eFlow = ESCHER_txflTtoBA;
596                 break;
597             case ::com::sun::star::text::WritingMode_RL_TB:
598                 eDir = ESCHER_txdirRTL;
599                 break;
600         }
601     }
602 */
603 
604     ESCHER_AnchorText eAnchor = ESCHER_AnchorTop;
605     ESCHER_WrapMode eWrapMode = ESCHER_WrapSquare;
606     sal_uInt32 nTextAttr = 0x40004;     // rotate text with shape
607 
608     if ( eWM == text::WritingMode_TB_RL )
609     {   // verical writing
610         switch ( eHA )
611         {
612             case drawing::TextHorizontalAdjust_LEFT :
613                 eAnchor = ESCHER_AnchorBottom;
614             break;
615             case drawing::TextHorizontalAdjust_CENTER :
616                 eAnchor = ESCHER_AnchorMiddle;
617             break;
618             default :
619             case drawing::TextHorizontalAdjust_BLOCK :
620             case drawing::TextHorizontalAdjust_RIGHT :
621                 eAnchor = ESCHER_AnchorTop;
622             break;
623         }
624         if ( eVA == drawing::TextVerticalAdjust_CENTER )
625         {
626             switch ( eAnchor )
627             {
628                 case ESCHER_AnchorMiddle :
629                     eAnchor = ESCHER_AnchorMiddleCentered;
630                 break;
631                 case ESCHER_AnchorBottom :
632                     eAnchor = ESCHER_AnchorBottomCentered;
633                 break;
634                 default :
635                 case ESCHER_AnchorTop :
636                     eAnchor = ESCHER_AnchorTopCentered;
637                 break;
638             }
639         }
640 		if ( bIsCustomShape )
641 		{
642 			if ( bWordWrap )
643 				eWrapMode = ESCHER_WrapSquare;
644 			else
645 				eWrapMode = ESCHER_WrapNone;
646 			if ( bAutoGrowSize )
647 				nTextAttr |= 0x20002;
648 		}
649 		else
650 		{
651 			if ( bAutoGrowHeight )
652 				eWrapMode = ESCHER_WrapNone;
653 			if ( bAutoGrowWidth )
654 				nTextAttr |= 0x20002;
655 		}
656 
657 		AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflTtoBA ); // rotate text within shape by 90
658     }
659     else
660     {   // normal from left to right
661         switch ( eVA )
662         {
663             case drawing::TextVerticalAdjust_CENTER :
664                 eAnchor = ESCHER_AnchorMiddle;
665             break;
666 
667             case drawing::TextVerticalAdjust_BOTTOM :
668                 eAnchor = ESCHER_AnchorBottom;
669             break;
670 
671             default :
672             case drawing::TextVerticalAdjust_TOP :
673                 eAnchor = ESCHER_AnchorTop;
674             break;
675         }
676         if ( eHA == drawing::TextHorizontalAdjust_CENTER )
677         {
678             switch( eAnchor )
679             {
680                 case ESCHER_AnchorMiddle :
681                     eAnchor = ESCHER_AnchorMiddleCentered;
682                 break;
683                 case ESCHER_AnchorBottom :
684                     eAnchor = ESCHER_AnchorBottomCentered;
685                 break;
686                 case ESCHER_AnchorTop :
687                     eAnchor = ESCHER_AnchorTopCentered;
688                 break;
689 				default: break;
690             }
691         }
692 		if ( bIsCustomShape )
693 		{
694 			if ( bWordWrap )
695 				eWrapMode = ESCHER_WrapSquare;
696 			else
697 				eWrapMode = ESCHER_WrapNone;
698 			if ( bAutoGrowSize )
699 				nTextAttr |= 0x20002;
700 		}
701 		else
702 		{
703 			if ( bAutoGrowWidth )
704 				eWrapMode = ESCHER_WrapNone;
705 			if ( bAutoGrowHeight )
706 				nTextAttr |= 0x20002;
707 		}
708     }
709     AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
710     AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
711     AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
712     AddOpt( ESCHER_Prop_dyTextBottom, nBottom * 360 );
713 
714 	AddOpt( ESCHER_Prop_WrapText, eWrapMode );
715 	AddOpt( ESCHER_Prop_AnchorText, eAnchor );
716     AddOpt( ESCHER_Prop_FitTextToShape, nTextAttr );
717 
718 	if ( nTextId )
719 		AddOpt( ESCHER_Prop_lTxid, nTextId );
720 }
721 
722 sal_Bool EscherPropertyContainer::GetLineArrow( const sal_Bool bLineStart,
723 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
724 		ESCHER_LineEnd& reLineEnd, sal_Int32& rnArrowLength, sal_Int32& rnArrowWidth )
725 {
726 	static String sLineStart	( RTL_CONSTASCII_USTRINGPARAM( "LineStart" ) );
727 	static String sLineStartName( RTL_CONSTASCII_USTRINGPARAM( "LineStartName" ) );
728 	static String sLineEnd		( RTL_CONSTASCII_USTRINGPARAM( "LineEnd" ) );
729 	static String sLineEndName	( RTL_CONSTASCII_USTRINGPARAM( "LineEndName" ) );
730 
731 	const String sLine		( bLineStart ? sLineStart : sLineEnd );
732 	const String sLineName	( bLineStart ? sLineStartName : sLineEndName );
733 
734 	sal_Bool bIsArrow = sal_False;
735 
736 	::com::sun::star::uno::Any aAny;
737     if ( EscherPropertyValueHelper::GetPropertyValue(
738 			aAny, rXPropSet, sLine, sal_False ) )
739     {
740 		PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aAny ) );
741 		if ( aPolyPoly.Count() && aPolyPoly[ 0 ].GetSize() )
742 		{
743 			bIsArrow = sal_True;
744 
745 			reLineEnd     = ESCHER_LineArrowEnd;
746 			rnArrowLength = 1;
747 			rnArrowWidth  = 1;
748 
749 			if ( EscherPropertyValueHelper::GetPropertyValue(
750 				aAny, rXPropSet, sLineName, sal_False ) )
751 			{
752 				String			aArrowStartName = *(::rtl::OUString*)aAny.getValue();
753 				rtl::OUString	aApiName;
754 				sal_Int16		nWhich = bLineStart ? XATTR_LINESTART : XATTR_LINEEND;
755 
756 				SvxUnogetApiNameForItem( nWhich, aArrowStartName, aApiName );
757 				if ( aApiName.getLength() )
758 				{
759 
760 					/* todo:
761 					calculate the best option for ArrowLenght and ArrowWidth
762 					*/
763 					if ( aApiName.equalsAscii( "Arrow concave" ) )
764 						reLineEnd = ESCHER_LineArrowStealthEnd;
765 					else if ( aApiName.equalsAscii( "Square 45" ) )
766 						reLineEnd = ESCHER_LineArrowDiamondEnd;
767 					else if ( aApiName.equalsAscii( "Small Arrow" ) )
768 						reLineEnd = ESCHER_LineArrowEnd;
769 					else if ( aApiName.equalsAscii( "Dimension Lines" ) )
770 					{
771 						rnArrowLength = 0;
772 						rnArrowWidth  = 2;
773 						reLineEnd = ESCHER_LineArrowOvalEnd;
774 					}
775 					else if ( aApiName.equalsAscii( "Double Arrow" ) )
776 						reLineEnd = ESCHER_LineArrowEnd;
777 					else if ( aApiName.equalsAscii( "Rounded short Arrow" ) )
778 						reLineEnd = ESCHER_LineArrowEnd;
779 					else if ( aApiName.equalsAscii( "Symmetric Arrow" ) )
780 						reLineEnd = ESCHER_LineArrowEnd;
781 					else if ( aApiName.equalsAscii( "Line Arrow" ) )
782 						reLineEnd = ESCHER_LineArrowOpenEnd;
783 					else if ( aApiName.equalsAscii( "Rounded large Arrow" ) )
784 						reLineEnd = ESCHER_LineArrowEnd;
785 					else if ( aApiName.equalsAscii( "Circle" ) )
786 						reLineEnd = ESCHER_LineArrowOvalEnd;
787 					else if ( aApiName.equalsAscii( "Square" ) )
788 						reLineEnd = ESCHER_LineArrowDiamondEnd;
789 					else if ( aApiName.equalsAscii( "Arrow" ) )
790 						reLineEnd = ESCHER_LineArrowEnd;
791 				}
792 				else if ( aArrowStartName.GetTokenCount( ' ' ) == 2 )
793 				{
794 					sal_Bool b = sal_True;
795 					String aArrowName( aArrowStartName.GetToken( 0, ' ' ) );
796 					if (  aArrowName.EqualsAscii( "msArrowEnd" ) )
797 						reLineEnd = ESCHER_LineArrowEnd;
798 					else if (  aArrowName.EqualsAscii( "msArrowOpenEnd" ) )
799 						reLineEnd = ESCHER_LineArrowOpenEnd;
800 					else if ( aArrowName.EqualsAscii( "msArrowStealthEnd" ) )
801 						reLineEnd = ESCHER_LineArrowStealthEnd;
802 					else if ( aArrowName.EqualsAscii( "msArrowDiamondEnd" ) )
803 						reLineEnd = ESCHER_LineArrowDiamondEnd;
804 					else if ( aArrowName.EqualsAscii( "msArrowOvalEnd" ) )
805 						reLineEnd = ESCHER_LineArrowOvalEnd;
806 					else
807 						b = sal_False;
808 
809 					// now we have the arrow, and try to determine the arrow size;
810 					if ( b )
811 					{
812 						String aArrowSize( aArrowStartName.GetToken( 1, ' ' ) );
813 						sal_Int32 nArrowSize = aArrowSize.ToInt32();
814 						rnArrowWidth = ( nArrowSize - 1 ) / 3;
815 						rnArrowLength = nArrowSize - ( rnArrowWidth * 3 ) - 1;
816 					}
817 				}
818 			}
819 		}
820     }
821 	return bIsArrow;
822 }
823 
824 void EscherPropertyContainer::CreateLineProperties(
825 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
826 		sal_Bool bEdge )
827 {
828 	::com::sun::star::uno::Any aAny;
829     sal_uInt32 nLineFlags = 0x80008;
830 
831 	ESCHER_LineEnd eLineEnd;
832 	sal_Int32 nArrowLength;
833 	sal_Int32 nArrowWidth;
834 
835 	sal_Bool bSwapLineEnds = sal_False;
836 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CircleKind" ) ), sal_True ) )
837 	{
838 		::com::sun::star::drawing::CircleKind  eCircleKind;
839 		if ( aAny >>= eCircleKind )
840 		{
841             if ( eCircleKind == ::com::sun::star::drawing::CircleKind_ARC )
842 				bSwapLineEnds = sal_True;
843 		}
844 	}
845 	if ( GetLineArrow( bSwapLineEnds ? sal_False : sal_True, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
846 	{
847         AddOpt( ESCHER_Prop_lineStartArrowLength, nArrowLength );
848         AddOpt( ESCHER_Prop_lineStartArrowWidth, nArrowWidth );
849         AddOpt( ESCHER_Prop_lineStartArrowhead, eLineEnd );
850         nLineFlags |= 0x100010;
851 	}
852 	if ( GetLineArrow( bSwapLineEnds ? sal_True : sal_False, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
853 	{
854         AddOpt( ESCHER_Prop_lineEndArrowLength, nArrowLength );
855         AddOpt( ESCHER_Prop_lineEndArrowWidth, nArrowWidth );
856         AddOpt( ESCHER_Prop_lineEndArrowhead, eLineEnd );
857         nLineFlags |= 0x100010;
858 	}
859 
860     // support LineCaps
861     if(EscherPropertyValueHelper::GetPropertyValue(aAny, rXPropSet, String(RTL_CONSTASCII_USTRINGPARAM("LineCap")), sal_False))
862     {
863         ::com::sun::star::drawing::LineCap aLineCap(com::sun::star::drawing::LineCap_BUTT);
864 
865         if(aAny >>= aLineCap)
866         {
867             switch (aLineCap)
868             {
869                 default: /* com::sun::star::drawing::LineCap_BUTT */
870                 {
871                     AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapFlat);
872                     break;
873                 }
874                 case com::sun::star::drawing::LineCap_ROUND:
875                 {
876                     AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapRound);
877                     break;
878                 }
879                 case com::sun::star::drawing::LineCap_SQUARE:
880                 {
881                     AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapSquare);
882                     break;
883                 }
884             }
885         }
886     }
887 
888 	if ( EscherPropertyValueHelper::GetPropertyValue(
889 		aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineStyle"  ) ), sal_False ) )
890     {
891 		::com::sun::star::drawing::LineStyle eLS;
892 		if ( aAny >>= eLS )
893 		{
894 			switch ( eLS )
895 			{
896 				case ::com::sun::star::drawing::LineStyle_NONE :
897 					AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );           // 80000
898 				break;
899 
900 				case ::com::sun::star::drawing::LineStyle_DASH :
901 				{
902 					if ( EscherPropertyValueHelper::GetPropertyValue(
903 						aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineDash" ) ), sal_False ) )
904 					{
905 						ESCHER_LineDashing eDash = ESCHER_LineSolid;
906 						::com::sun::star::drawing::LineDash* pLineDash = (::com::sun::star::drawing::LineDash*)aAny.getValue();
907 						sal_Int32 nDistance = pLineDash->Distance << 1;
908 						switch ( pLineDash->Style )
909 						{
910 							case ::com::sun::star::drawing::DashStyle_ROUND :
911 							case ::com::sun::star::drawing::DashStyle_ROUNDRELATIVE :
912 								AddOpt( ESCHER_Prop_lineEndCapStyle, 0 ); // Style Round setzen
913 							break;
914 							default : break;
915 						}
916 						if ( ((!(pLineDash->Dots )) || (!(pLineDash->Dashes )) ) || ( pLineDash->DotLen == pLineDash->DashLen ) )
917 						{
918 							sal_Int32 nLen = pLineDash->DotLen;
919 							if ( pLineDash->Dashes )
920 								nLen = pLineDash->DashLen;
921 
922 							if ( nLen >= nDistance )
923 								eDash = ESCHER_LineLongDashGEL;
924 							else if ( pLineDash->Dots )
925 								eDash = ESCHER_LineDotSys;
926 							else
927 								eDash = ESCHER_LineDashGEL;
928 						}
929 						else                                                            // X Y
930 						{
931 							if ( pLineDash->Dots != pLineDash->Dashes )
932 							{
933 								if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
934 									eDash = ESCHER_LineLongDashDotDotGEL;
935 								else
936 									eDash = ESCHER_LineDashDotDotSys;
937 							}
938 							else                                                        // X Y Y
939 							{
940 								if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
941 									eDash = ESCHER_LineLongDashDotGEL;
942 								else
943 									eDash = ESCHER_LineDashDotGEL;
944 
945 							}
946 						}
947 						AddOpt( ESCHER_Prop_lineDashing, eDash );
948 					}
949 				}
950 				case ::com::sun::star::drawing::LineStyle_SOLID :
951 				default:
952 				{
953 					AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
954 				}
955 				break;
956 			}
957 		}
958 		if ( EscherPropertyValueHelper::GetPropertyValue(
959 			aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineColor"  ) ), sal_False ) )
960         {
961             sal_uInt32 nLineColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) );
962             AddOpt( ESCHER_Prop_lineColor, nLineColor );
963             AddOpt( ESCHER_Prop_lineBackColor, nLineColor ^ 0xffffff );
964         }
965     }
966 
967 	sal_uInt32 nLineSize = ( EscherPropertyValueHelper::GetPropertyValue(
968 		aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineWidth"  ) ), sal_False ) )
969 		? *((sal_uInt32*)aAny.getValue())
970 		: 0;
971     if ( nLineSize > 1 )
972         AddOpt( ESCHER_Prop_lineWidth, nLineSize * 360 );		// 100TH MM -> PT , 1PT = 12700 EMU
973 
974 	ESCHER_LineJoin eLineJoin = ESCHER_LineJoinMiter;
975 	if ( EscherPropertyValueHelper::GetPropertyValue(
976 		aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineJoint" ) ), sal_True ) )
977 	{
978 		::com::sun::star::drawing::LineJoint eLJ;
979 		if ( aAny >>= eLJ )
980 		{
981 			switch ( eLJ )
982 			{
983 				case com::sun::star::drawing::LineJoint_NONE :
984 				case com::sun::star::drawing::LineJoint_MIDDLE :
985 				case com::sun::star::drawing::LineJoint_BEVEL :
986 					eLineJoin = ESCHER_LineJoinBevel;
987 				break;
988 				default:
989 				case com::sun::star::drawing::LineJoint_MITER :
990 					eLineJoin = ESCHER_LineJoinMiter;
991 				break;
992 				case com::sun::star::drawing::LineJoint_ROUND :
993 					eLineJoin = ESCHER_LineJoinRound;
994 				break;
995 			}
996 		}
997 	}
998 	AddOpt( ESCHER_Prop_lineJoinStyle, eLineJoin );
999 
1000 	if ( EscherPropertyValueHelper::GetPropertyValue(
1001 		aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineTransparence" ) ), sal_True ) )
1002 	{
1003 		sal_Int16 nTransparency = 0;
1004 		if ( aAny >>= nTransparency )
1005 			AddOpt( ESCHER_Prop_lineOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
1006 	}
1007 
1008 
1009     if ( bEdge == sal_False )
1010     {
1011         AddOpt( ESCHER_Prop_fFillOK, 0x1001 );
1012         AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
1013     }
1014 }
1015 
1016 static Size lcl_SizeToEmu(Size aPrefSize, MapMode aPrefMapMode)
1017 {
1018     Size aRetSize;
1019     if (aPrefMapMode == MAP_PIXEL)
1020         aRetSize = Application::GetDefaultDevice()->PixelToLogic( aPrefSize, MAP_100TH_MM );
1021     else
1022         aRetSize = Application::GetDefaultDevice()->LogicToLogic( aPrefSize, aPrefMapMode, MAP_100TH_MM );
1023     return aRetSize;
1024 }
1025 
1026 void EscherPropertyContainer::ImplCreateGraphicAttributes( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
1027 															sal_uInt32 nBlibId, sal_Bool bCreateCroppingAttributes )
1028 {
1029 	::com::sun::star::uno::Any aAny;
1030 
1031 	sal_uInt32 nPicFlags = 0;
1032 	::com::sun::star::drawing::ColorMode eColorMode( ::com::sun::star::drawing::ColorMode_STANDARD );
1033 	sal_Int16 nLuminance = 0;
1034 	sal_Int32 nContrast = 0;
1035 	sal_Int16 nRed = 0;
1036 	sal_Int16 nGreen = 0;
1037 	sal_Int16 nBlue = 0;
1038 	double fGamma = 1.0;
1039 	sal_Int16 nTransparency = 0;
1040 
1041 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicColorMode" ) ) ) )
1042 		aAny >>= eColorMode;
1043 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustLuminance" ) ) ) )
1044 		aAny >>= nLuminance;
1045 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustContrast" ) ) ) )
1046 	{
1047 		sal_Int16 nC = sal_Int16();
1048 		aAny >>= nC;
1049 		nContrast = nC;
1050 	}
1051 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustRed" ) ) ) )
1052 		aAny >>= nRed;
1053 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustGreen" ) ) ) )
1054 		aAny >>= nGreen;
1055 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustBlue" ) ) ) )
1056 		aAny >>= nBlue;
1057 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Gamma" ) ) ) )
1058 		aAny >>= fGamma;
1059 	if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Transparency" ) ) ) )
1060 		aAny >>= nTransparency;
1061 
1062 	if ( eColorMode == ::com::sun::star::drawing::ColorMode_WATERMARK )
1063 	{
1064 		eColorMode = ::com::sun::star::drawing::ColorMode_STANDARD;
1065 		nLuminance += 70;
1066 		if ( nLuminance > 100 )
1067 			nLuminance = 100;
1068 		nContrast -= 70;
1069 		if ( nContrast < -100 )
1070 			nContrast = -100;
1071 	}
1072 	if ( eColorMode == ::com::sun::star::drawing::ColorMode_GREYS )
1073 		nPicFlags |= 0x40004;
1074 	else if ( eColorMode == ::com::sun::star::drawing::ColorMode_MONO )
1075 		nPicFlags |= 0x60006;
1076 
1077 	if ( nContrast )
1078 	{
1079 		nContrast += 100;
1080 		if ( nContrast == 100)
1081 			nContrast = 0x10000;
1082 		else if ( nContrast < 100 )
1083 		{
1084 			nContrast *= 0x10000;
1085 			nContrast /= 100;
1086 		}
1087 		else if ( nContrast < 200 )
1088 			nContrast = ( 100 * 0x10000 ) / ( 200 - nContrast );
1089 		else
1090 			nContrast = 0x7fffffff;
1091 		AddOpt( ESCHER_Prop_pictureContrast, nContrast );
1092 	}
1093 	if ( nLuminance )
1094 		AddOpt( ESCHER_Prop_pictureBrightness, nLuminance * 327 );
1095 	if ( nPicFlags )
1096 		AddOpt( ESCHER_Prop_pictureActive, nPicFlags );
1097 
1098 	if ( bCreateCroppingAttributes && pGraphicProvider )
1099 	{
1100 		Size	aPrefSize;
1101 		MapMode	aPrefMapMode;
1102 		if ( pGraphicProvider->GetPrefSize( nBlibId, aPrefSize, aPrefMapMode ) )
1103 		{
1104             Size aCropSize(lcl_SizeToEmu(aPrefSize, aPrefMapMode));
1105 			if ( aCropSize.Width() && aCropSize.Height() )
1106 			{
1107 				if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicCrop" ) ) ) )
1108 				{
1109 					::com::sun::star::text::GraphicCrop aGraphCrop;
1110 					if ( aAny >>= aGraphCrop )
1111 					{
1112 						if ( aGraphCrop.Left )
1113 						{
1114 							sal_uInt32 nLeft = ( aGraphCrop.Left * 65536 ) / aCropSize.Width();
1115 							AddOpt( ESCHER_Prop_cropFromLeft, nLeft );
1116 						}
1117 						if ( aGraphCrop.Top )
1118 						{
1119 							sal_uInt32 nTop = ( aGraphCrop.Top * 65536 ) / aCropSize.Height();
1120 							AddOpt( ESCHER_Prop_cropFromTop, nTop );
1121 						}
1122 						if ( aGraphCrop.Right )
1123 						{
1124 							sal_uInt32 nRight = ( aGraphCrop.Right * 65536 ) / aCropSize.Width();
1125 							AddOpt( ESCHER_Prop_cropFromRight, nRight );
1126 						}
1127 						if ( aGraphCrop.Bottom )
1128 						{
1129 							sal_uInt32 nBottom = ( aGraphCrop.Bottom * 65536 ) / aCropSize.Height();
1130 							AddOpt( ESCHER_Prop_cropFromBottom, nBottom );
1131 						}
1132 					}
1133 				}
1134 			}
1135 		}
1136 	}
1137 }
1138 
1139 sal_Bool EscherPropertyContainer::CreateShapeProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
1140 {
1141 	uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
1142 	if ( aXPropSet.is() )
1143 	{
1144 		sal_Bool bVal = false;
1145 		::com::sun::star::uno::Any aAny;
1146 		sal_uInt32 nShapeAttr = 0;
1147 		EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) ), sal_True );
1148 		if ( aAny >>= bVal )
1149 		{
1150 			if ( !bVal )
1151 				nShapeAttr |= 0x20002;	// set fHidden = true
1152 		}
1153 		EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) ), sal_True );
1154 		if ( aAny >>= bVal )
1155 		{
1156 			if ( !bVal )
1157 				nShapeAttr |= 0x10000;	// set fPrint = false;
1158 		}
1159 		if ( nShapeAttr )
1160 		    AddOpt( ESCHER_Prop_fPrint, nShapeAttr );
1161 	}
1162 	return sal_True;
1163 }
1164 
1165 sal_Bool EscherPropertyContainer::CreateOLEGraphicProperties(
1166 	const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
1167 {
1168 	sal_Bool	bRetValue = sal_False;
1169 
1170 	if ( rXShape.is() )
1171 	{
1172 		SdrObject* pSdrOLE2( GetSdrObjectFromXShape( rXShape ) );	// SJ: leaving unoapi, because currently there is
1173 		if ( pSdrOLE2 && pSdrOLE2->ISA( SdrOle2Obj ) )				// no access to the native graphic object
1174 		{
1175 			Graphic* pGraphic = ((SdrOle2Obj*)pSdrOLE2)->GetGraphic();
1176 			if ( pGraphic )
1177 			{
1178 				GraphicObject aGraphicObject( *pGraphic );
1179                 ByteString aUniqueId( aGraphicObject.GetUniqueID() );
1180 				if ( aUniqueId.Len() )
1181 				{
1182 					AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1183 					uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
1184 
1185 					if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect && aXPropSet.is() )
1186 					{
1187 						::com::sun::star::uno::Any aAny;
1188 						::com::sun::star::awt::Rectangle* pVisArea = NULL;
1189 						if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "VisibleArea" ) ) ) )
1190 						{
1191 							pVisArea = new ::com::sun::star::awt::Rectangle;
1192 							aAny >>= (*pVisArea);
1193 						}
1194 						Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() );
1195 						sal_uInt32 nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, pVisArea, NULL );
1196 						if ( nBlibId )
1197 						{
1198 							AddOpt( ESCHER_Prop_pib, nBlibId, sal_True );
1199 							ImplCreateGraphicAttributes( aXPropSet, nBlibId, sal_False );
1200 							bRetValue = sal_True;
1201 						}
1202 						delete pVisArea;
1203 					}
1204 				}
1205 			}
1206 		}
1207 	}
1208 	return bRetValue;
1209 }
1210 
1211 
1212 sal_Bool EscherPropertyContainer::ImplCreateEmbeddedBmp( const ByteString& rUniqueId )
1213 {
1214     if( rUniqueId.Len() > 0 )
1215     {
1216         EscherGraphicProvider aProvider;
1217         SvMemoryStream aMemStrm;
1218         Rectangle aRect;
1219         if ( aProvider.GetBlibID( aMemStrm, rUniqueId, aRect ) )
1220         {
1221             // grab BLIP from stream and insert directly as complex property
1222             // ownership of stream memory goes to complex property
1223             aMemStrm.ObjectOwnsMemory( sal_False );
1224             sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData();
1225             sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END );
1226             AddOpt( ESCHER_Prop_fillBlip, sal_True, nSize, pBuf, nSize );
1227             return sal_True;
1228         }
1229     }
1230     return sal_False;
1231 }
1232 
1233 sal_Bool EscherPropertyContainer::CreateEmbeddedBitmapProperties(
1234     const ::rtl::OUString& rBitmapUrl, ::com::sun::star::drawing::BitmapMode eBitmapMode )
1235 {
1236     sal_Bool bRetValue = sal_False;
1237     String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
1238     String aBmpUrl( rBitmapUrl );
1239     xub_StrLen nIndex = aBmpUrl.Search( aVndUrl, 0 );
1240     if( nIndex != STRING_NOTFOUND )
1241     {
1242         // note: += ist not defined for xub_StrLen -> conversion to int and back to xub_StrLen
1243         nIndex = nIndex + aVndUrl.Len();
1244         if( aBmpUrl.Len() > nIndex )
1245         {
1246             ByteString aUniqueId( aBmpUrl, nIndex, aBmpUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 );
1247             bRetValue = ImplCreateEmbeddedBmp( aUniqueId );
1248             if( bRetValue )
1249             {
1250                 // bitmap mode property
1251                 bool bRepeat = eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT;
1252                 AddOpt( ESCHER_Prop_fillType, bRepeat ? ESCHER_FillTexture : ESCHER_FillPicture );
1253             }
1254         }
1255     }
1256     return bRetValue;
1257 }
1258 
1259 
1260 namespace {
1261 
1262 GraphicObject lclDrawHatch( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground )
1263 {
1264     const MapMode aMap100( MAP_100TH_MM );
1265     VirtualDevice aVDev( *Application::GetDefaultDevice(), 0, 1 );
1266     aVDev.SetMapMode( aMap100 );
1267 
1268     const Size aOutSize = aVDev.PixelToLogic( Size( 28, 28 ) );
1269     aVDev.SetOutputSize( aOutSize );
1270 
1271     Rectangle aRectangle( Point( 0, 0 ), aOutSize );
1272     const PolyPolygon aPolyPoly( aRectangle );
1273 
1274     aVDev.SetLineColor();
1275     aVDev.SetFillColor( bFillBackground ? rBackColor : Color( COL_TRANSPARENT ) );
1276     aVDev.DrawRect( Rectangle( Point(), aOutSize ) );
1277 
1278     Hatch aVclHatch( (HatchStyle) rHatch.Style, Color( rHatch.Color ), rHatch.Distance, (sal_uInt16)rHatch.Angle );
1279     aVDev.DrawHatch( aPolyPoly, aVclHatch );
1280 
1281     return GraphicObject( Graphic( aVDev.GetBitmapEx( Point(), aOutSize ) ) );
1282 }
1283 
1284 } // namespace
1285 
1286 
1287 sal_Bool EscherPropertyContainer::CreateEmbeddedHatchProperties( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground )
1288 {
1289     GraphicObject aGraphicObject = lclDrawHatch( rHatch, rBackColor, bFillBackground );
1290     ByteString aUniqueId = aGraphicObject.GetUniqueID();
1291     sal_Bool bRetValue = ImplCreateEmbeddedBmp( aUniqueId );
1292     if ( bRetValue )
1293         AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
1294     return bRetValue;
1295 }
1296 
1297 
1298 sal_Bool EscherPropertyContainer::CreateGraphicProperties(
1299 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
1300 		const String& rSource, const sal_Bool bCreateFillBitmap, const sal_Bool bCreateCroppingAttributes,
1301 			const sal_Bool bFillBitmapModeAllowed )
1302 {
1303 	sal_Bool		bRetValue = sal_False;
1304 	sal_Bool		bCreateFillStyles = sal_False;
1305 
1306     sal_Bool        bMirrored = sal_False;
1307     sal_Bool        bRotate   = sal_True;
1308     sal_uInt16      nAngle    = 0;
1309     GraphicAttr*    pGraphicAttr = NULL;
1310     GraphicObject   aGraphicObject;
1311     String          aGraphicUrl;
1312     ByteString      aUniqueId;
1313     bool            bIsGraphicMtf(false);
1314 
1315     ::com::sun::star::drawing::BitmapMode   eBitmapMode( ::com::sun::star::drawing::BitmapMode_NO_REPEAT );
1316     ::com::sun::star::uno::Any aAny;
1317 
1318     if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, rSource ) )
1319     {
1320         if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ) )
1321         {
1322             ::com::sun::star::uno::Sequence<sal_uInt8> aSeq = *(::com::sun::star::uno::Sequence<sal_uInt8>*)aAny.getValue();
1323             const sal_uInt8*    pAry = aSeq.getArray();
1324             sal_uInt32          nAryLen = aSeq.getLength();
1325 
1326             // the metafile is already rotated
1327             bRotate = sal_False;
1328 
1329             if ( pAry && nAryLen )
1330             {
1331                 Graphic         aGraphic;
1332                 SvMemoryStream  aTemp( (void*)pAry, nAryLen, STREAM_READ );
1333                 sal_uInt32 nErrCode = GraphicConverter::Import( aTemp, aGraphic, CVT_WMF );
1334                 if ( nErrCode == ERRCODE_NONE )
1335                 {
1336                     aGraphicObject = aGraphic;
1337                     aUniqueId = aGraphicObject.GetUniqueID();
1338                     bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
1339                 }
1340             }
1341         }
1342         else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ) )
1343         {
1344             ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >xBitmap;
1345             if ( ::cppu::extractInterface( xBitmap, aAny ) )
1346             {
1347                 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > xBmp;
1348                 if ( aAny >>= xBmp )
1349                 {
1350                     BitmapEx    aBitmapEx( VCLUnoHelper::GetBitmap( xBmp ) );
1351                     Graphic     aGraphic( aBitmapEx );
1352                     aGraphicObject = aGraphic;
1353                     aUniqueId = aGraphicObject.GetUniqueID();
1354                     bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
1355                 }
1356             }
1357         }
1358         else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ) )
1359         {
1360             aGraphicUrl = *(::rtl::OUString*)aAny.getValue();
1361         }
1362         else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) )
1363         {
1364             aGraphicUrl = *(::rtl::OUString*)aAny.getValue();
1365 			bCreateFillStyles = sal_True;
1366         }
1367         else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ) )
1368         {
1369             ::com::sun::star::drawing::Hatch aHatch;
1370             if ( aAny >>= aHatch )
1371             {
1372                 Color aBackColor;
1373                 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1374                     String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), sal_False ) )
1375                 {
1376                     aBackColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()), sal_False );
1377                 }
1378                 bool bFillBackground = false;
1379                 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1380                         String( RTL_CONSTASCII_USTRINGPARAM( "FillBackground" ) ), sal_True ) )
1381                 {
1382                     aAny >>= bFillBackground;
1383                 }
1384                 aGraphicObject = lclDrawHatch( aHatch, aBackColor, bFillBackground );
1385                 aUniqueId = aGraphicObject.GetUniqueID();
1386                 eBitmapMode = ::com::sun::star::drawing::BitmapMode_REPEAT;
1387                 bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
1388             }
1389         }
1390 
1391         if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "IsMirrored" ) ), sal_True ) )
1392             aAny >>= bMirrored;
1393 
1394         if ( bCreateFillBitmap && bFillBitmapModeAllowed )
1395         {
1396             if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapMode" ) ), sal_True ) )
1397                 aAny >>= eBitmapMode;
1398         }
1399         else
1400         {
1401             nAngle = bRotate && EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1402                                                                              String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True )
1403                 ? (sal_uInt16)( ( *((sal_Int32*)aAny.getValue() ) ) + 5 ) / 10
1404                 : 0;
1405         }
1406 
1407         if ( aGraphicUrl.Len() )
1408         {
1409             String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
1410             xub_StrLen nIndex = aGraphicUrl.Search( aVndUrl, 0 );
1411             if ( nIndex != STRING_NOTFOUND )
1412             {
1413                 nIndex = nIndex + aVndUrl.Len();
1414                 if ( aGraphicUrl.Len() > nIndex  )
1415                     aUniqueId = ByteString( aGraphicUrl, nIndex, aGraphicUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 );
1416             }
1417             else
1418             {
1419                 // externally, linked graphic? convert to embedded
1420                 // one, if transformations are needed. this is because
1421                 // everything < msoxp cannot even handle rotated
1422                 // bitmaps.
1423                 // And check whether the graphic link target is
1424                 // actually supported by mso.
1425                 INetURLObject   aTmp( aGraphicUrl );
1426                 GraphicDescriptor aDescriptor(aTmp);
1427                 aDescriptor.Detect();
1428                 const sal_uInt16 nFormat = aDescriptor.GetFileFormat();
1429 
1430                 // can MSO handle it?
1431                 if ( bMirrored || nAngle ||
1432                      (nFormat != GFF_BMP &&
1433                       nFormat != GFF_GIF &&
1434                       nFormat != GFF_JPG &&
1435                       nFormat != GFF_PNG &&
1436                       nFormat != GFF_TIF &&
1437                       nFormat != GFF_PCT &&
1438                       nFormat != GFF_WMF &&
1439                       nFormat != GFF_EMF) )
1440                 {
1441                     SvStream* pIn = ::utl::UcbStreamHelper::CreateStream(
1442                         aTmp.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
1443                     if ( pIn )
1444                     {
1445                         Graphic aGraphic;
1446                         sal_uInt32 nErrCode = GraphicConverter::Import( *pIn, aGraphic );
1447 
1448                         if ( nErrCode == ERRCODE_NONE )
1449                         {
1450                             // no.
1451                             aGraphicObject = aGraphic;
1452                             aUniqueId = aGraphicObject.GetUniqueID();
1453                         }
1454                         // else: simply keep the graphic link
1455                         delete pIn;
1456                     }
1457                 }
1458 				if ( !aUniqueId.Len() )
1459 				{
1460 					if ( pGraphicProvider )
1461 					{
1462 						const rtl::OUString& rBaseURI( pGraphicProvider->GetBaseURI() );
1463 						INetURLObject aBaseURI( rBaseURI );
1464 						if( aBaseURI.GetProtocol() == aTmp.GetProtocol() )
1465 						{
1466 							rtl::OUString aRelUrl( INetURLObject::GetRelURL( rBaseURI, aGraphicUrl,
1467 								INetURLObject::WAS_ENCODED, INetURLObject::DECODE_TO_IURI, RTL_TEXTENCODING_UTF8, INetURLObject::FSYS_DETECT ) );
1468 							if ( aRelUrl.getLength() )
1469 								aGraphicUrl = aRelUrl;
1470 						}
1471 					}
1472 				}
1473             }
1474         }
1475 
1476         if ( aGraphicUrl.Len() || aUniqueId.Len() )
1477         {
1478             if ( bMirrored || nAngle )
1479             {
1480                 pGraphicAttr = new GraphicAttr;
1481                 if ( bMirrored )
1482                     pGraphicAttr->SetMirrorFlags( BMP_MIRROR_HORZ );
1483                 if ( bIsGraphicMtf )
1484                     AddOpt( ESCHER_Prop_Rotation, ( ( ((sal_Int32)nAngle << 16 ) / 10 ) + 0x8000 ) &~ 0xffff );
1485             }
1486 
1487             if ( eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT )
1488                 AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
1489             else
1490                 AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1491 
1492             if ( aUniqueId.Len() )
1493             {
1494                 // write out embedded graphic
1495                 if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect )
1496                 {
1497                     Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() );
1498 
1499                     sal_uInt32 nBlibId = 0;
1500                     nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, NULL, pGraphicAttr );
1501                     if ( nBlibId )
1502                     {
1503                         if ( bCreateFillBitmap )
1504                             AddOpt( ESCHER_Prop_fillBlip, nBlibId, sal_True );
1505                         else
1506                         {
1507                             AddOpt( ESCHER_Prop_pib, nBlibId, sal_True );
1508                             ImplCreateGraphicAttributes( rXPropSet, nBlibId, bCreateCroppingAttributes );
1509                         }
1510                         bRetValue = sal_True;
1511                     }
1512                 }
1513                 else
1514                 {
1515                     EscherGraphicProvider aProvider;
1516                     SvMemoryStream aMemStrm;
1517                     Rectangle aRect;
1518 
1519                     if ( aProvider.GetBlibID( aMemStrm, aUniqueId, aRect, NULL, pGraphicAttr ) )
1520                     {
1521                         // grab BLIP from stream and insert directly as complex property
1522                         // ownership of stream memory goes to complex property
1523                         aMemStrm.ObjectOwnsMemory( sal_False );
1524                         sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData();
1525                         sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END );
1526                         AddOpt( ESCHER_Prop_fillBlip, sal_True, nSize, pBuf, nSize );
1527                         bRetValue = sal_True;
1528                     }
1529                 }
1530             }
1531             // write out link to graphic
1532             else
1533             {
1534                 OSL_ASSERT(aGraphicUrl.Len());
1535 
1536                 AddOpt( ESCHER_Prop_pibName, aGraphicUrl );
1537                 sal_uInt32	nPibFlags=0;
1538                 GetOpt( ESCHER_Prop_pibFlags, nPibFlags );
1539                 AddOpt( ESCHER_Prop_pibFlags,
1540                         ESCHER_BlipFlagLinkToFile|ESCHER_BlipFlagFile|ESCHER_BlipFlagDoNotSave | nPibFlags );
1541             }
1542         }
1543     }
1544     delete pGraphicAttr;
1545 	if ( bCreateFillStyles )
1546 		CreateFillProperties( rXPropSet, sal_True );
1547 
1548 	return bRetValue;
1549 }
1550 
1551 PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
1552 {
1553     PolyPolygon aRetPolyPoly;
1554     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet;
1555     ::com::sun::star::uno::Any aAny( rXShape->queryInterface(
1556         ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) ));
1557 
1558     String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) );
1559     String sPolyPolygon		( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) );
1560     String sPolygon		    ( RTL_CONSTASCII_USTRINGPARAM( "Polygon" ) );
1561 
1562     if ( aAny >>= aXPropSet )
1563     {
1564         sal_Bool bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygonBezier, sal_True );
1565         if ( !bHasProperty )
1566             bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygon, sal_True );
1567         if ( !bHasProperty )
1568             bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolygon, sal_True );
1569         if ( bHasProperty )
1570             aRetPolyPoly = GetPolyPolygon( aAny );
1571     }
1572     return aRetPolyPoly;
1573 }
1574 
1575 PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Any& rAny )
1576 {
1577 	sal_Bool bNoError = sal_True;
1578 
1579 	Polygon aPolygon;
1580 	PolyPolygon aPolyPolygon;
1581 
1582 	if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PolyPolygonBezierCoords* ) 0 ) )
1583 	{
1584 		::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon
1585 			= (::com::sun::star::drawing::PolyPolygonBezierCoords*)rAny.getValue();
1586 		sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->Coordinates.getLength();
1587 
1588 		// Zeiger auf innere sequences holen
1589 		::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->Coordinates.getArray();
1590 		::com::sun::star::drawing::FlagSequence*  pOuterFlags = pSourcePolyPolygon->Flags.getArray();
1591 
1592 		bNoError = pOuterSequence && pOuterFlags;
1593 		if ( bNoError )
1594 		{
1595 			sal_uInt16  a, b, nInnerSequenceCount;
1596 			::com::sun::star::awt::Point* pArray;
1597 
1598 			// dies wird ein Polygon set
1599 			for ( a = 0; a < nOuterSequenceCount; a++ )
1600 			{
1601 				::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
1602 				::com::sun::star::drawing::FlagSequence*  pInnerFlags = pOuterFlags++;
1603 
1604 				bNoError = pInnerSequence && pInnerFlags;
1605 				if  ( bNoError )
1606 				{
1607 					// Zeiger auf Arrays holen
1608 					pArray = pInnerSequence->getArray();
1609 					::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
1610 
1611 					if ( pArray && pFlags )
1612 					{
1613 						nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
1614 						aPolygon = Polygon( nInnerSequenceCount );
1615 						for( b = 0; b < nInnerSequenceCount; b++)
1616 						{
1617 							PolyFlags   ePolyFlags( *( (PolyFlags*)pFlags++ ) );
1618 							::com::sun::star::awt::Point aPoint( (::com::sun::star::awt::Point)*(pArray++) );
1619 							aPolygon[ b ] = Point( aPoint.X, aPoint.Y );
1620 							aPolygon.SetFlags( b, ePolyFlags );
1621 
1622 							if ( ePolyFlags == POLY_CONTROL )
1623 								continue;
1624 						}
1625 						aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
1626 					}
1627 				}
1628 			}
1629 		}
1630 	}
1631 	else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequenceSequence* ) 0 ) )
1632 	{
1633 		::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon
1634 			= (::com::sun::star::drawing::PointSequenceSequence*)rAny.getValue();
1635 		sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->getLength();
1636 
1637 		// Zeiger auf innere sequences holen
1638 		::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
1639 		bNoError = pOuterSequence != NULL;
1640 		if ( bNoError )
1641 		{
1642 			sal_uInt16 a, b, nInnerSequenceCount;
1643 
1644 			// dies wird ein Polygon set
1645 			for( a = 0; a < nOuterSequenceCount; a++ )
1646 			{
1647 				::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
1648 				bNoError = pInnerSequence != NULL;
1649 				if ( bNoError )
1650 				{
1651 					// Zeiger auf Arrays holen
1652                     ::com::sun::star::awt::Point* pArray =
1653                           pInnerSequence->getArray();
1654 					if ( pArray != NULL )
1655 					{
1656 						nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
1657 						aPolygon = Polygon( nInnerSequenceCount );
1658 						for( b = 0; b < nInnerSequenceCount; b++)
1659 						{
1660 							aPolygon[ b ] = Point( pArray->X, pArray->Y );
1661 							pArray++;
1662 						}
1663 						aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
1664 					}
1665 				}
1666 			}
1667 		}
1668 	}
1669 	else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequence* ) 0 ) )
1670 	{
1671         ::com::sun::star::drawing::PointSequence* pInnerSequence =
1672 			(::com::sun::star::drawing::PointSequence*)rAny.getValue();
1673 
1674 		bNoError = pInnerSequence != NULL;
1675 		if ( bNoError )
1676 		{
1677 			sal_uInt16 a, nInnerSequenceCount;
1678 
1679 			// Zeiger auf Arrays holen
1680 			::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
1681 			if ( pArray != NULL )
1682 			{
1683 				nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
1684 				aPolygon = Polygon( nInnerSequenceCount );
1685 				for( a = 0; a < nInnerSequenceCount; a++)
1686 				{
1687 					aPolygon[ a ] = Point( pArray->X, pArray->Y );
1688 					pArray++;
1689 				}
1690 				aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
1691 			}
1692 		}
1693 	}
1694 	return aPolyPolygon;
1695 }
1696 
1697 sal_Bool EscherPropertyContainer::CreatePolygonProperties(
1698 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
1699 		sal_uInt32 nFlags,
1700 			sal_Bool bBezier,
1701 				::com::sun::star::awt::Rectangle& rGeoRect,
1702 					Polygon* pPolygon )
1703 {
1704 	static String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) );
1705 	static String sPolyPolygon		( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) );
1706 
1707 	sal_Bool	bRetValue = sal_True;
1708 	sal_Bool	bLine = ( nFlags & ESCHER_CREATEPOLYGON_LINE ) != 0;
1709 
1710     PolyPolygon aPolyPolygon;
1711 
1712     if ( pPolygon )
1713         aPolyPolygon.Insert( *pPolygon, POLYPOLY_APPEND );
1714     else
1715     {
1716 		::com::sun::star::uno::Any aAny;
1717 		bRetValue = EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1718 						( bBezier ) ? sPolyPolygonBezier : sPolyPolygon, sal_True );
1719 		if ( bRetValue )
1720 		{
1721 			aPolyPolygon = GetPolyPolygon( aAny );
1722 			bRetValue = aPolyPolygon.Count() != 0;
1723 		}
1724     }
1725 	if ( bRetValue )
1726 	{
1727 		if ( bLine )
1728 		{
1729 			if ( ( aPolyPolygon.Count() == 1 ) && ( aPolyPolygon[ 0 ].GetSize() == 2 ) )
1730 			{
1731 				const Polygon& rPoly = aPolyPolygon[ 0 ];
1732 				rGeoRect = ::com::sun::star::awt::Rectangle(
1733 					rPoly[ 0 ].X(),
1734 						rPoly[ 0 ].Y(),
1735 							rPoly[ 1 ].X() - rPoly[ 0 ].X(),
1736 								rPoly[ 1 ].Y() - rPoly[ 0 ].Y() );
1737 			}
1738 			else
1739 				bRetValue = sal_False;
1740 		}
1741 		else
1742 		{
1743 			Polygon aPolygon;
1744 
1745 			sal_uInt16 i, j, k, nPoints, nBezPoints, nPolyCount = aPolyPolygon.Count();
1746 			Rectangle aRect( aPolyPolygon.GetBoundRect() );
1747 			rGeoRect = ::com::sun::star::awt::Rectangle( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
1748 
1749 			for ( nBezPoints = nPoints = i = 0; i < nPolyCount; i++ )
1750 			{
1751 				k = aPolyPolygon[ i ].GetSize();
1752 				nPoints = nPoints + k;
1753 				for ( j = 0; j < k; j++ )
1754 				{
1755 					if ( aPolyPolygon[ i ].GetFlags( j ) != POLY_CONTROL )
1756 						nBezPoints++;
1757 				}
1758 			}
1759 			sal_uInt32 nVerticesBufSize = ( nPoints << 2 ) + 6;
1760 			sal_uInt8* pVerticesBuf = new sal_uInt8[ nVerticesBufSize ];
1761 
1762 
1763 			sal_uInt32 nSegmentBufSize = ( ( nBezPoints << 2 ) + 8 );
1764 			if ( nPolyCount > 1 )
1765 				nSegmentBufSize += ( nPolyCount << 1 );
1766 			sal_uInt8* pSegmentBuf = new sal_uInt8[ nSegmentBufSize ];
1767 
1768 			sal_uInt8* pPtr = pVerticesBuf;
1769 			*pPtr++ = (sal_uInt8)( nPoints );                    // Little endian
1770 			*pPtr++ = (sal_uInt8)( nPoints >> 8 );
1771 			*pPtr++ = (sal_uInt8)( nPoints );
1772 			*pPtr++ = (sal_uInt8)( nPoints >> 8 );
1773 			*pPtr++ = (sal_uInt8)0xf0;
1774 			*pPtr++ = (sal_uInt8)0xff;
1775 
1776 			for ( j = 0; j < nPolyCount; j++ )
1777 			{
1778 				aPolygon = aPolyPolygon[ j ];
1779 				nPoints = aPolygon.GetSize();
1780 				for ( i = 0; i < nPoints; i++ )             // Punkte aus Polygon in Buffer schreiben
1781 				{
1782 					Point aPoint = aPolygon[ i ];
1783 					aPoint.X() -= rGeoRect.X;
1784 					aPoint.Y() -= rGeoRect.Y;
1785 
1786 					*pPtr++ = (sal_uInt8)( aPoint.X() );
1787 					*pPtr++ = (sal_uInt8)( aPoint.X() >> 8 );
1788 					*pPtr++ = (sal_uInt8)( aPoint.Y() );
1789 					*pPtr++ = (sal_uInt8)( aPoint.Y() >> 8 );
1790 				}
1791 			}
1792 
1793 			pPtr = pSegmentBuf;
1794 			*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 );
1795 			*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 );
1796 			*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 );
1797 			*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 );
1798 			*pPtr++ = (sal_uInt8)2;
1799 			*pPtr++ = (sal_uInt8)0;
1800 
1801 			for ( j = 0; j < nPolyCount; j++ )
1802 			{
1803 				*pPtr++ = 0x0;          // Polygon start
1804 				*pPtr++ = 0x40;
1805 				aPolygon = aPolyPolygon[ j ];
1806 				nPoints = aPolygon.GetSize();
1807 				for ( i = 0; i < nPoints; i++ )         // Polyflags in Buffer schreiben
1808 				{
1809 					*pPtr++ = 0;
1810 					if ( bBezier )
1811 						*pPtr++ = 0xb3;
1812 					else
1813 						*pPtr++ = 0xac;
1814 					if ( ( i + 1 ) != nPoints )
1815 					{
1816 						*pPtr++ = 1;
1817 						if ( aPolygon.GetFlags( i + 1 ) == POLY_CONTROL )
1818 						{
1819 							*pPtr++ = 0x20;
1820 							i += 2;
1821 						}
1822 						else
1823 							*pPtr++ = 0;
1824 					}
1825 				}
1826 				if ( nPolyCount > 1 )
1827 				{
1828 					*pPtr++ = 1;                        // end of polygon
1829 					*pPtr++ = 0x60;
1830 				}
1831 			}
1832 			*pPtr++ = 0;
1833 			*pPtr++ = 0x80;
1834 
1835 			AddOpt( ESCHER_Prop_geoRight, rGeoRect.Width );
1836 			AddOpt( ESCHER_Prop_geoBottom, rGeoRect.Height );
1837 
1838 			AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
1839 			AddOpt( ESCHER_Prop_pVertices, sal_True, nVerticesBufSize - 6, (sal_uInt8*)pVerticesBuf, nVerticesBufSize );
1840 			AddOpt( ESCHER_Prop_pSegmentInfo, sal_True, nSegmentBufSize, (sal_uInt8*)pSegmentBuf, nSegmentBufSize );
1841 		}
1842 	}
1843 	return bRetValue;
1844 }
1845 
1846 sal_Bool EscherPropertyContainer::CreateConnectorProperties(
1847 	const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape,
1848 	EscherSolverContainer& rSolverContainer, ::com::sun::star::awt::Rectangle& rGeoRect,
1849 			sal_uInt16& rShapeType, sal_uInt16& rShapeFlags )
1850 {
1851 	static String sEdgeKind				( RTL_CONSTASCII_USTRINGPARAM( "EdgeKind" ) );
1852 	static String sEdgeStartPoint		( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartPoint" ) );
1853 	static String sEdgeEndPoint			( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndPoint" ) );
1854 	static String sEdgeStartConnection	( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartConnection" ) );
1855 	static String sEdgeEndConnection	( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndConnection" ) );
1856 
1857 	sal_Bool bRetValue = sal_False;
1858 	rShapeType = rShapeFlags = 0;
1859 
1860 	if ( rXShape.is() )
1861 	{
1862 		::com::sun::star::awt::Point aStartPoint, aEndPoint;
1863 		::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet;
1864 		::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aShapeA, aShapeB;
1865 		::com::sun::star::uno::Any aAny( rXShape->queryInterface( ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) ));
1866 		if ( aAny >>= aXPropSet )
1867 		{
1868 			if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeKind, sal_True ) )
1869 			{
1870 				::com::sun::star::drawing::ConnectorType eCt;
1871 				aAny >>= eCt;
1872 				if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartPoint ) )
1873 				{
1874 					aStartPoint = *(::com::sun::star::awt::Point*)aAny.getValue();
1875 					if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndPoint ) )
1876 					{
1877 						aEndPoint = *(::com::sun::star::awt::Point*)aAny.getValue();
1878 
1879 						rShapeFlags = SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT | SHAPEFLAG_CONNECTOR;
1880 						rGeoRect = ::com::sun::star::awt::Rectangle( aStartPoint.X, aStartPoint.Y,
1881 															( aEndPoint.X - aStartPoint.X ) + 1, ( aEndPoint.Y - aStartPoint.Y ) + 1 );
1882 						if ( rGeoRect.Height < 0 )			// justify
1883 						{
1884 							rShapeFlags |= SHAPEFLAG_FLIPV;
1885 							rGeoRect.Y = aEndPoint.Y;
1886 							rGeoRect.Height = -rGeoRect.Height;
1887 						}
1888 						if ( rGeoRect.Width < 0 )
1889 						{
1890 							rShapeFlags |= SHAPEFLAG_FLIPH;
1891 							rGeoRect.X = aEndPoint.X;
1892 							rGeoRect.Width = -rGeoRect.Width;
1893 						}
1894 						sal_uInt32 nAdjustValue1, nAdjustValue2, nAdjustValue3;
1895 						nAdjustValue1 = nAdjustValue2 = nAdjustValue3 = 0x2a30;
1896 
1897 						if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartConnection ) )
1898 							aAny >>= aShapeA;
1899 						if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndConnection ) )
1900 							aAny >>= aShapeB;
1901 /*
1902 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine1Delta" ) ) ) )
1903 						{
1904 						}
1905 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine2Delta" ) ) ) )
1906 						{
1907 						}
1908 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine3Delta" ) ) ) )
1909 						{
1910 						}
1911 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1HorzDist" ) ) ) )
1912 						{
1913 						}
1914 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1VertDist" ) ) ) )
1915 						{
1916 						}
1917 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2HorzDist" ) ) ) )
1918 						{
1919 						}
1920 						if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2VertDist" ) ) ) )
1921 						{
1922 						}
1923 */
1924 						rSolverContainer.AddConnector( rXShape, aStartPoint, aShapeA, aEndPoint, aShapeB );
1925 						switch ( eCt )
1926 						{
1927 							case ::com::sun::star::drawing::ConnectorType_CURVE :
1928 							{
1929 								rShapeType = ESCHER_ShpInst_CurvedConnector3;
1930 								AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleCurved );
1931 								AddOpt( ESCHER_Prop_adjustValue, nAdjustValue1 );
1932 								AddOpt( ESCHER_Prop_adjust2Value, -(sal_Int32)nAdjustValue2 );
1933 							}
1934 							break;
1935 
1936 							case ::com::sun::star::drawing::ConnectorType_STANDARD :// Connector 2->5
1937 							{
1938 								rShapeType = ESCHER_ShpInst_BentConnector3;
1939 								AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent );
1940 							}
1941 							break;
1942 
1943 							default:
1944 							case ::com::sun::star::drawing::ConnectorType_LINE :
1945 							case ::com::sun::star::drawing::ConnectorType_LINES :	// Connector 2->5
1946 							{
1947 								rShapeType = ESCHER_ShpInst_StraightConnector1;
1948 								AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleStraight );
1949 							}
1950 							break;
1951 						}
1952 						CreateLineProperties( aXPropSet, sal_False );
1953 						bRetValue = bSuppressRotation = sal_True;
1954 					}
1955 				}
1956 			}
1957 		}
1958 	}
1959 	return bRetValue;
1960 }
1961 
1962 sal_Bool EscherPropertyContainer::CreateShadowProperties(
1963 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet )
1964 {
1965 	::com::sun::star::uno::Any aAny;
1966 
1967 	sal_Bool	bHasShadow = sal_False;	// shadow is possible only if at least a fillcolor, linecolor or graphic is set
1968 	sal_uInt32	nLineFlags = 0;			// default : shape has no line
1969 	sal_uInt32	nFillFlags = 0x10;		//			 shape is filled
1970 
1971 	GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
1972 	GetOpt( ESCHER_Prop_fNoFillHitTest, nFillFlags );
1973 
1974 	sal_uInt32 nDummy;
1975 	sal_Bool bGraphic = GetOpt( DFF_Prop_pib, nDummy ) || GetOpt( DFF_Prop_pibName, nDummy ) || GetOpt( DFF_Prop_pibFlags, nDummy );
1976 
1977 	sal_uInt32 nShadowFlags = 0x20000;
1978 	if ( ( nLineFlags & 8 ) || ( nFillFlags & 0x10 ) || bGraphic )
1979 	{
1980 		if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1981 				String( RTL_CONSTASCII_USTRINGPARAM( "Shadow" ) ), sal_True ) )
1982 		{
1983 			if ( aAny >>= bHasShadow )
1984             {
1985 				if ( bHasShadow )
1986 				{
1987 					nShadowFlags |= 2;
1988 					if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1989 							String( RTL_CONSTASCII_USTRINGPARAM( "ShadowColor" ) ), sal_False ) )
1990 						AddOpt( ESCHER_Prop_shadowColor, ImplGetColor( *((sal_uInt32*)aAny.getValue()) ) );
1991 					if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1992 							String( RTL_CONSTASCII_USTRINGPARAM( "ShadowXDistance" ) ), sal_False ) )
1993 						AddOpt( ESCHER_Prop_shadowOffsetX, *((sal_Int32*)aAny.getValue()) * 360 );
1994 					if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1995 							String( RTL_CONSTASCII_USTRINGPARAM( "ShadowYDistance" ) ), sal_False ) )
1996 						AddOpt( ESCHER_Prop_shadowOffsetY, *((sal_Int32*)aAny.getValue()) * 360 );
1997 					if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1998 							String( RTL_CONSTASCII_USTRINGPARAM( "ShadowTransparence" ) ), sal_False ) )
1999 						AddOpt( ESCHER_Prop_shadowOpacity,  0x10000 - (((sal_uInt32)*((sal_uInt16*)aAny.getValue())) * 655 ) );
2000 				}
2001             }
2002         }
2003 	}
2004 	AddOpt( ESCHER_Prop_fshadowObscured, nShadowFlags );
2005 	return bHasShadow;
2006 }
2007 
2008 // ---------------------------------------------------------------------------------------------
2009 
2010 sal_Int32 GetValueForEnhancedCustomShapeParameter( const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter, const std::vector< sal_Int32 >& rEquationOrder )
2011 {
2012 	sal_Int32 nValue = 0;
2013 	if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
2014 	{
2015 		double fValue;
2016 		if ( rParameter.Value >>= fValue )
2017 			nValue = (sal_Int32)fValue;
2018 	}
2019 	else
2020 		rParameter.Value >>= nValue;
2021 
2022 	switch( rParameter.Type )
2023 	{
2024 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
2025 		{
2026 			OSL_ASSERT(nValue < rEquationOrder.size());
2027 			if ( nValue < rEquationOrder.size() )
2028 			{
2029 				nValue = (sal_uInt16)rEquationOrder[ nValue ];
2030 				nValue |= (sal_uInt32)0x80000000;
2031 			}
2032 		}
2033 		break;
2034 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL :
2035 		{
2036 
2037 		}
2038 		break;
2039 /* not sure if it is allowed to set following values
2040 (but they are not yet used)
2041 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
2042 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
2043 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
2044 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
2045 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
2046 */
2047 	}
2048 	return nValue;
2049 }
2050 
2051 sal_Bool GetValueForEnhancedCustomShapeHandleParameter( sal_Int32& nRetValue, const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter )
2052 {
2053 	sal_Bool bSpecial = sal_False;
2054 	nRetValue = 0;
2055 	if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
2056 	{
2057 		double fValue;
2058 		if ( rParameter.Value >>= fValue )
2059 			nRetValue = (sal_Int32)fValue;
2060 	}
2061 	else
2062 		rParameter.Value >>= nRetValue;
2063 
2064 	switch( rParameter.Type )
2065 	{
2066 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
2067 		{
2068 			nRetValue += 3;
2069 			bSpecial = sal_True;
2070 		}
2071 		break;
2072 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
2073 		{
2074 			nRetValue += 0x100;
2075 			bSpecial = sal_True;
2076 		}
2077 		break;
2078 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
2079 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
2080 		{
2081 			nRetValue = 0;
2082 			bSpecial = sal_True;
2083 		}
2084 		break;
2085 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
2086 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
2087 		{
2088 			nRetValue = 1;
2089 			bSpecial = sal_True;
2090 		}
2091 		break;
2092 		case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL :
2093 		{
2094 
2095 		}
2096 		break;
2097 	}
2098 	return bSpecial;
2099 }
2100 
2101 void ConvertEnhancedCustomShapeEquation( SdrObjCustomShape* pCustoShape,
2102 		std::vector< EnhancedCustomShapeEquation >& rEquations, std::vector< sal_Int32 >& rEquationOrder )
2103 {
2104 	if ( pCustoShape )
2105 	{
2106 		uno::Sequence< rtl::OUString > sEquationSource;
2107 		const rtl::OUString	sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
2108 		SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)
2109 			pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
2110 		const uno::Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
2111 		if ( pAny )
2112 			*pAny >>= sEquationSource;
2113 		sal_Int32 nEquationSourceCount = sEquationSource.getLength();
2114 		if ( nEquationSourceCount )
2115 		{
2116 			sal_Int32 i;
2117 			for ( i = 0; i < nEquationSourceCount; i++ )
2118 			{
2119 				EnhancedCustomShape2d aCustoShape2d( pCustoShape );
2120 				try
2121 				{
2122 					::boost::shared_ptr< EnhancedCustomShape::ExpressionNode > aExpressNode(
2123 						EnhancedCustomShape::FunctionParser::parseFunction( sEquationSource[ i ], aCustoShape2d ) );
2124 					com::sun::star::drawing::EnhancedCustomShapeParameter aPara( aExpressNode->fillNode( rEquations, NULL, 0 ) );
2125 					if ( aPara.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION )
2126 					{
2127 						EnhancedCustomShapeEquation	aEquation;
2128 						aEquation.nOperation = 0;
2129 						EnhancedCustomShape::FillEquationParameter( aPara, 0, aEquation );
2130 						rEquations.push_back( aEquation );
2131 					}
2132 				}
2133 				catch ( EnhancedCustomShape::ParseError& )
2134 				{
2135 					EnhancedCustomShapeEquation	aEquation;		// ups, we should not be here,
2136 					aEquation.nOperation = 0;					// creating a default equation with value 1
2137 					aEquation.nPara[ 0 ] = 1;					// hoping that this will not break anything
2138 					rEquations.push_back( aEquation );
2139 				}
2140 				catch ( ... )
2141 				{
2142 					EnhancedCustomShapeEquation	aEquation;		// #i112309# EnhancedCustomShape::Parse error
2143 					aEquation.nOperation = 0;					// not catched on linux platform
2144 					aEquation.nPara[ 0 ] = 1;
2145 					rEquations.push_back( aEquation );
2146 				}
2147 				rEquationOrder.push_back( rEquations.size() - 1 );
2148 			}
2149 			// now updating our old equation indices, they are marked with a bit in the hiword of nOperation
2150 			std::vector< EnhancedCustomShapeEquation >::iterator aIter( rEquations.begin() );
2151 			std::vector< EnhancedCustomShapeEquation >::iterator aEnd ( rEquations.end() );
2152 			while( aIter != aEnd )
2153 			{
2154 				sal_Int32 nMask = 0x20000000;
2155 				for( i = 0; i < 3; i++ )
2156 				{
2157 					if ( aIter->nOperation & nMask )
2158 					{
2159 						aIter->nOperation ^= nMask;
2160 						aIter->nPara[ i ] = rEquationOrder[ aIter->nPara[ i ] & 0x3ff ] | 0x400;
2161 					}
2162 					nMask <<= 1;
2163 				}
2164 				aIter++;
2165 			}
2166 		}
2167 	}
2168 }
2169 
2170 sal_Bool EscherPropertyContainer::IsDefaultObject( SdrObjCustomShape* pCustoShape )
2171 {
2172     sal_Bool bIsDefaultObject = sal_False;
2173     if ( pCustoShape )
2174     {
2175 	if (   pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_EQUATIONS )
2176 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_VIEWBOX )
2177 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_PATH )
2178 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_GLUEPOINTS )
2179 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_SEGMENTS )
2180 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHX )
2181 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHY )
2182 //					&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_HANDLES )
2183 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_TEXTFRAMES ) )
2184 	    bIsDefaultObject = sal_True;
2185     }
2186 
2187     return bIsDefaultObject;
2188 }
2189 
2190 void EscherPropertyContainer::LookForPolarHandles( const MSO_SPT eShapeType, sal_Int32& nAdjustmentsWhichNeedsToBeConverted )
2191 {
2192     const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eShapeType );
2193     if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
2194     {
2195 	sal_Int32 k, nkCount = pDefCustomShape->nHandles;
2196 	const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
2197 	for ( k = 0; k < nkCount; k++, pData++ )
2198 	{
2199 	    if ( pData->nFlags & MSDFF_HANDLE_FLAGS_POLAR )
2200 	    {
2201 		if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
2202 		    nAdjustmentsWhichNeedsToBeConverted |= ( 1 << k );
2203 	    }
2204 	}
2205     }
2206 }
2207 
2208 sal_Bool EscherPropertyContainer::GetAdjustmentValue( const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue & rkProp, sal_Int32 nIndex, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, sal_Int32& nValue )
2209 {
2210     if ( rkProp.State != beans::PropertyState_DIRECT_VALUE )
2211 	return sal_False;
2212 
2213     sal_Bool bUseFixedFloat = ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << nIndex ) ) != 0;
2214     if ( rkProp.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
2215     {
2216 	double fValue(0.0);
2217 	rkProp.Value >>= fValue;
2218 	if ( bUseFixedFloat )
2219 	    fValue *= 65536.0;
2220 	nValue = (sal_Int32)fValue;
2221     }
2222     else
2223     {
2224 	rkProp.Value >>= nValue;
2225 	if ( bUseFixedFloat )
2226 	    nValue <<= 16;
2227     }
2228 
2229     return sal_True;
2230 }
2231 
2232 void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeType, const uno::Reference< drawing::XShape > & rXShape )
2233 {
2234 	uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
2235     if ( aXPropSet.is() )
2236     {
2237 		SdrObjCustomShape* pCustoShape = (SdrObjCustomShape*)GetSdrObjectFromXShape( rXShape );
2238 		const rtl::OUString	sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) );
2239 		uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
2240 		uno::Sequence< beans::PropertyValue > aGeoPropSeq;
2241 		if ( aGeoPropSet >>= aGeoPropSeq )
2242 		{
2243 			const rtl::OUString	sViewBox			( RTL_CONSTASCII_USTRINGPARAM( "ViewBox" ) );
2244 			const rtl::OUString	sTextRotateAngle	( RTL_CONSTASCII_USTRINGPARAM( "TextRotateAngle" ) );
2245 			const rtl::OUString	sExtrusion			( RTL_CONSTASCII_USTRINGPARAM( "Extrusion" ) );
2246 			const rtl::OUString	sEquations			( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
2247 			const rtl::OUString	sPath				( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
2248 			const rtl::OUString	sTextPath			( RTL_CONSTASCII_USTRINGPARAM( "TextPath" ) );
2249 			const rtl::OUString	sHandles			( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
2250 			const rtl::OUString sAdjustmentValues	( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) );
2251 
2252 			const beans::PropertyValue* pAdjustmentValuesProp = NULL;
2253 			sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0;
2254 			uno::Sequence< beans::PropertyValues > aHandlesPropSeq;
2255 			sal_Bool bPredefinedHandlesUsed = sal_True;
2256 			sal_Bool bIsDefaultObject = IsDefaultObject( pCustoShape );
2257 
2258 			// convert property "Equations" into std::vector< EnhancedCustomShapeEquationEquation >
2259 			std::vector< EnhancedCustomShapeEquation >	aEquations;
2260 			std::vector< sal_Int32 >					aEquationOrder;
2261 			ConvertEnhancedCustomShapeEquation( pCustoShape, aEquations, aEquationOrder );
2262 
2263 			sal_Int32 i, nCount = aGeoPropSeq.getLength();
2264 			for ( i = 0; i < nCount; i++ )
2265 			{
2266 				const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
2267 				if ( rProp.Name.equals( sViewBox ) )
2268 				{
2269 					if ( !bIsDefaultObject )
2270 					{
2271 						awt::Rectangle aViewBox;
2272 						if ( rProp.Value >>= aViewBox )
2273 						{
2274 							AddOpt( DFF_Prop_geoLeft,  aViewBox.X );
2275 							AddOpt( DFF_Prop_geoTop,   aViewBox.Y );
2276 							AddOpt( DFF_Prop_geoRight, aViewBox.X + aViewBox.Width );
2277 							AddOpt( DFF_Prop_geoBottom,aViewBox.Y + aViewBox.Height );
2278 						}
2279 					}
2280 				}
2281 				else if ( rProp.Name.equals( sTextRotateAngle ) )
2282 				{
2283 					double f = 0, fTextRotateAngle;
2284 					if ( rProp.Value >>= f )
2285 					{
2286 						fTextRotateAngle = fmod( f, 360.0 );
2287 						if ( fTextRotateAngle < 0 )
2288 							fTextRotateAngle = 360 + fTextRotateAngle;
2289 						if ( ( fTextRotateAngle < 271.0 ) && ( fTextRotateAngle > 269.0 ) )
2290 					        AddOpt( DFF_Prop_cdirFont, mso_cdir90 );
2291 						else if ( ( fTextRotateAngle < 181.0 ) && ( fTextRotateAngle > 179.0 ) )
2292 							AddOpt( DFF_Prop_cdirFont, mso_cdir180 );
2293 						else if ( ( fTextRotateAngle < 91.0 ) && ( fTextRotateAngle > 79.0 ) )
2294 							AddOpt( DFF_Prop_cdirFont, mso_cdir270 );
2295 					}
2296 				}
2297 				else if ( rProp.Name.equals( sExtrusion ) )
2298 				{
2299 					uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
2300 					if ( rProp.Value >>= aExtrusionPropSeq )
2301 					{
2302 						sal_uInt32 nLightFaceFlagsOrg, nLightFaceFlags;
2303 						sal_uInt32 nFillHarshFlagsOrg, nFillHarshFlags;
2304 						nLightFaceFlagsOrg = nLightFaceFlags = 0x000001;
2305 						nFillHarshFlagsOrg = nFillHarshFlags = 0x00001e;
2306 						if ( GetOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ) )
2307 							nLightFaceFlagsOrg = nLightFaceFlags;
2308 						if ( GetOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ) )
2309 							nFillHarshFlagsOrg = nFillHarshFlags;
2310 
2311 						sal_Int32 r, nrCount = aExtrusionPropSeq.getLength();
2312 						for ( r = 0; r < nrCount; r++ )
2313 						{
2314 							const beans::PropertyValue& rrProp = aExtrusionPropSeq[ r ];
2315 							const rtl::OUString	sExtrusionBrightness			( RTL_CONSTASCII_USTRINGPARAM( "Brightness" ) );
2316 							const rtl::OUString	sExtrusionDepth					( RTL_CONSTASCII_USTRINGPARAM( "Depth" ) );
2317 							const rtl::OUString	sExtrusionDiffusion				( RTL_CONSTASCII_USTRINGPARAM( "Diffusion" ) );
2318 							const rtl::OUString	sExtrusionNumberOfLineSegments	( RTL_CONSTASCII_USTRINGPARAM( "NumberOfLineSegments" ) );
2319 							const rtl::OUString	sExtrusionLightFace				( RTL_CONSTASCII_USTRINGPARAM( "LightFace" ) );
2320 							const rtl::OUString	sExtrusionFirstLightHarsh		( RTL_CONSTASCII_USTRINGPARAM( "FirstLightHarsh" ) );
2321 							const rtl::OUString	sExtrusionSecondLightHarsh		( RTL_CONSTASCII_USTRINGPARAM( "SecondLightHarsh" ) );
2322 							const rtl::OUString	sExtrusionFirstLightLevel		( RTL_CONSTASCII_USTRINGPARAM( "FirstLightLevel" ) );
2323 							const rtl::OUString	sExtrusionSecondLightLevel		( RTL_CONSTASCII_USTRINGPARAM( "SecondLightLevel" ) );
2324 							const rtl::OUString	sExtrusionFirstLightDirection	( RTL_CONSTASCII_USTRINGPARAM( "FirstLightDirection" ) );
2325 							const rtl::OUString	sExtrusionSecondLightDirection	( RTL_CONSTASCII_USTRINGPARAM( "SecondLightDirection" ) );
2326 							const rtl::OUString	sExtrusionMetal					( RTL_CONSTASCII_USTRINGPARAM( "Metal" ) );
2327 							const rtl::OUString	sExtrusionShadeMode				( RTL_CONSTASCII_USTRINGPARAM( "ShadeMode" ) );
2328 							const rtl::OUString	sExtrusionRotateAngle			( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) );
2329 							const rtl::OUString	sExtrusionRotationCenter		( RTL_CONSTASCII_USTRINGPARAM( "RotationCenter" ) );
2330 							const rtl::OUString	sExtrusionShininess				( RTL_CONSTASCII_USTRINGPARAM( "Shininess" ) );
2331 							const rtl::OUString	sExtrusionSkew					( RTL_CONSTASCII_USTRINGPARAM( "Skew" ) );
2332 							const rtl::OUString	sExtrusionSpecularity			( RTL_CONSTASCII_USTRINGPARAM( "Specularity" ) );
2333 							const rtl::OUString	sExtrusionProjectionMode		( RTL_CONSTASCII_USTRINGPARAM( "ProjectionMode" ) );
2334 							const rtl::OUString	sExtrusionViewPoint				( RTL_CONSTASCII_USTRINGPARAM( "ViewPoint" ) );
2335 							const rtl::OUString	sExtrusionOrigin				( RTL_CONSTASCII_USTRINGPARAM( "Origin" ) );
2336 							const rtl::OUString	sExtrusionColor					( RTL_CONSTASCII_USTRINGPARAM( "Color" ) );
2337 
2338 							if ( rrProp.Name.equals( sExtrusion ) )
2339 							{
2340 								sal_Bool bExtrusionOn = sal_Bool();
2341 								if ( rrProp.Value >>= bExtrusionOn )
2342 								{
2343 									nLightFaceFlags |= 0x80000;
2344 									if ( bExtrusionOn )
2345 										nLightFaceFlags |= 8;
2346 									else
2347 										nLightFaceFlags &=~8;
2348 								}
2349 							}
2350 							else if ( rrProp.Name.equals( sExtrusionBrightness ) )
2351 							{
2352 								double fExtrusionBrightness = 0;
2353 								if ( rrProp.Value >>= fExtrusionBrightness )
2354 									AddOpt( DFF_Prop_c3DAmbientIntensity, (sal_Int32)( fExtrusionBrightness * 655.36 ) );
2355 							}
2356 							else if ( rrProp.Name.equals( sExtrusionDepth ) )
2357 							{
2358 								double fDepth = 0;
2359 								double fFraction = 0;
2360 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
2361 								if ( ( rrProp.Value >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) )
2362 								{
2363 									double fForeDepth = fDepth * fFraction;
2364 									double fBackDepth = fDepth - fForeDepth;
2365 
2366 									fBackDepth *= 360.0;
2367 									AddOpt( DFF_Prop_c3DExtrudeBackward, (sal_Int32)fBackDepth );
2368 
2369 									if ( fForeDepth != 0.0 )
2370 									{
2371 										fForeDepth *= 360.0;
2372 										AddOpt( DFF_Prop_c3DExtrudeForward, (sal_Int32)fForeDepth );
2373 									}
2374 								}
2375 							}
2376 							else if ( rrProp.Name.equals( sExtrusionDiffusion ) )
2377 							{
2378 								double fExtrusionDiffusion = 0;
2379 								if ( rrProp.Value >>= fExtrusionDiffusion )
2380 									AddOpt( DFF_Prop_c3DDiffuseAmt, (sal_Int32)( fExtrusionDiffusion * 655.36 ) );
2381 							}
2382 							else if ( rrProp.Name.equals( sExtrusionNumberOfLineSegments ) )
2383 							{
2384 								sal_Int32 nExtrusionNumberOfLineSegments = 0;
2385 								if ( rrProp.Value >>= nExtrusionNumberOfLineSegments )
2386 									AddOpt( DFF_Prop_c3DTolerance, nExtrusionNumberOfLineSegments );
2387 							}
2388 							else if ( rrProp.Name.equals( sExtrusionLightFace ) )
2389 							{
2390 								sal_Bool bExtrusionLightFace = sal_Bool();
2391 								if ( rrProp.Value >>= bExtrusionLightFace )
2392 								{
2393 									nLightFaceFlags |= 0x10000;
2394 									if ( bExtrusionLightFace )
2395 										nLightFaceFlags |= 1;
2396 									else
2397 										nLightFaceFlags &=~1;
2398 								}
2399 							}
2400 							else if ( rrProp.Name.equals( sExtrusionFirstLightHarsh ) )
2401 							{
2402 								sal_Bool bExtrusionFirstLightHarsh = sal_Bool();
2403 								if ( rrProp.Value >>= bExtrusionFirstLightHarsh )
2404 								{
2405 									nFillHarshFlags |= 0x20000;
2406 									if ( bExtrusionFirstLightHarsh )
2407 										nFillHarshFlags |= 2;
2408 									else
2409 										nFillHarshFlags &=~2;
2410 								}
2411 							}
2412 							else if ( rrProp.Name.equals( sExtrusionSecondLightHarsh ) )
2413 							{
2414 								sal_Bool bExtrusionSecondLightHarsh = sal_Bool();
2415 								if ( rrProp.Value >>= bExtrusionSecondLightHarsh )
2416 								{
2417 									nFillHarshFlags |= 0x10000;
2418 									if ( bExtrusionSecondLightHarsh )
2419 										nFillHarshFlags |= 1;
2420 									else
2421 										nFillHarshFlags &=~1;
2422 								}
2423 							}
2424 							else if ( rrProp.Name.equals( sExtrusionFirstLightLevel ) )
2425 							{
2426 								double fExtrusionFirstLightLevel = 0;
2427 								if ( rrProp.Value >>= fExtrusionFirstLightLevel )
2428 									AddOpt( DFF_Prop_c3DKeyIntensity, (sal_Int32)( fExtrusionFirstLightLevel * 655.36 ) );
2429 							}
2430 							else if ( rrProp.Name.equals( sExtrusionSecondLightLevel ) )
2431 							{
2432 								double fExtrusionSecondLightLevel = 0;
2433 								if ( rrProp.Value >>= fExtrusionSecondLightLevel )
2434 									AddOpt( DFF_Prop_c3DFillIntensity, (sal_Int32)( fExtrusionSecondLightLevel * 655.36 ) );
2435 							}
2436 							else if ( rrProp.Name.equals( sExtrusionFirstLightDirection ) )
2437 							{
2438 								drawing::Direction3D aExtrusionFirstLightDirection;
2439 								if ( rrProp.Value >>= aExtrusionFirstLightDirection )
2440 								{
2441 									AddOpt( DFF_Prop_c3DKeyX, (sal_Int32)aExtrusionFirstLightDirection.DirectionX  );
2442 									AddOpt( DFF_Prop_c3DKeyY, (sal_Int32)aExtrusionFirstLightDirection.DirectionY  );
2443 									AddOpt( DFF_Prop_c3DKeyZ, (sal_Int32)aExtrusionFirstLightDirection.DirectionZ  );
2444 								}
2445 							}
2446 							else if ( rrProp.Name.equals( sExtrusionSecondLightDirection ) )
2447 							{
2448 								drawing::Direction3D aExtrusionSecondLightPosition;
2449 								if ( rrProp.Value >>= aExtrusionSecondLightPosition )
2450 								{
2451 									AddOpt( DFF_Prop_c3DFillX, (sal_Int32)aExtrusionSecondLightPosition.DirectionX  );
2452 									AddOpt( DFF_Prop_c3DFillY, (sal_Int32)aExtrusionSecondLightPosition.DirectionY  );
2453 									AddOpt( DFF_Prop_c3DFillZ, (sal_Int32)aExtrusionSecondLightPosition.DirectionZ  );
2454 								}
2455 							}
2456 							else if ( rrProp.Name.equals( sExtrusionMetal ) )
2457 							{
2458 								sal_Bool bExtrusionMetal = sal_Bool();
2459 								if ( rrProp.Value >>= bExtrusionMetal )
2460 								{
2461 									nLightFaceFlags |= 0x40000;
2462 									if ( bExtrusionMetal )
2463 										nLightFaceFlags |= 4;
2464 									else
2465 										nLightFaceFlags &=~4;
2466 								}
2467 							}
2468 							else if ( rrProp.Name.equals( sExtrusionShadeMode ) )
2469 							{
2470 								drawing::ShadeMode eExtrusionShadeMode;
2471 								if ( rrProp.Value >>= eExtrusionShadeMode )
2472 								{
2473 									sal_uInt32 nRenderMode;
2474 									switch( eExtrusionShadeMode )
2475 									{
2476 										default:
2477 										case drawing::ShadeMode_FLAT :
2478 										case drawing::ShadeMode_PHONG :
2479 										case drawing::ShadeMode_SMOOTH :
2480 											nRenderMode = mso_FullRender;
2481 										break;
2482 										case drawing::ShadeMode_DRAFT :
2483 										{
2484 											nRenderMode = mso_Wireframe;
2485 										}
2486 										break;
2487 									}
2488 									AddOpt( DFF_Prop_c3DRenderMode, nRenderMode );
2489 								}
2490 							}
2491 							else if ( rrProp.Name.equals( sExtrusionRotateAngle ) )
2492 							{
2493 								double fExtrusionAngleX = 0;
2494 								double fExtrusionAngleY = 0;
2495 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAnglePair;
2496 								if ( ( rrProp.Value >>= aRotateAnglePair ) && ( aRotateAnglePair.First.Value >>= fExtrusionAngleX ) && ( aRotateAnglePair.Second.Value >>= fExtrusionAngleY ) )
2497 								{
2498 									fExtrusionAngleX *= 65536;
2499 									fExtrusionAngleY *= 65536;
2500 									AddOpt( DFF_Prop_c3DXRotationAngle, (sal_Int32)fExtrusionAngleX );
2501 									AddOpt( DFF_Prop_c3DYRotationAngle, (sal_Int32)fExtrusionAngleY );
2502 								}
2503 							}
2504 							else if ( rrProp.Name.equals( sExtrusionRotationCenter ) )
2505 							{
2506 								drawing::Direction3D aExtrusionRotationCenter;
2507 								if ( rrProp.Value >>= aExtrusionRotationCenter )
2508 								{
2509 									AddOpt( DFF_Prop_c3DRotationCenterX, (sal_Int32)( aExtrusionRotationCenter.DirectionX * 360.0 ) );
2510 									AddOpt( DFF_Prop_c3DRotationCenterY, (sal_Int32)( aExtrusionRotationCenter.DirectionY * 360.0 ) );
2511 									AddOpt( DFF_Prop_c3DRotationCenterZ, (sal_Int32)( aExtrusionRotationCenter.DirectionZ * 360.0 ) );
2512 									nFillHarshFlags &=~8; // don't use AutoRotationCenter;
2513 								}
2514 							}
2515 							else if ( rrProp.Name.equals( sExtrusionShininess ) )
2516 							{
2517 								double fExtrusionShininess = 0;
2518 								if ( rrProp.Value >>= fExtrusionShininess )
2519 									AddOpt( DFF_Prop_c3DShininess, (sal_Int32)( fExtrusionShininess * 655.36 ) );
2520 							}
2521 							else if ( rrProp.Name.equals( sExtrusionSkew ) )
2522 							{
2523 								double fSkewAmount = 0;
2524 								double fSkewAngle = 0;
2525 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
2526 								if ( ( rrProp.Value >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= fSkewAmount ) && ( aSkewParaPair.Second.Value >>= fSkewAngle ) )
2527 								{
2528 									AddOpt( DFF_Prop_c3DSkewAmount, (sal_Int32)fSkewAmount );
2529 									AddOpt( DFF_Prop_c3DSkewAngle, (sal_Int32)( fSkewAngle * 65536 ) );
2530 								}
2531 							}
2532 							else if ( rrProp.Name.equals( sExtrusionSpecularity ) )
2533 							{
2534 								double fExtrusionSpecularity = 0;
2535 								if ( rrProp.Value >>= fExtrusionSpecularity )
2536 									AddOpt( DFF_Prop_c3DSpecularAmt, (sal_Int32)( fExtrusionSpecularity * 1333 ) );
2537 							}
2538 							else if ( rrProp.Name.equals( sExtrusionProjectionMode ) )
2539 							{
2540 								drawing::ProjectionMode eExtrusionProjectionMode;
2541 								if ( rrProp.Value >>= eExtrusionProjectionMode )
2542 								{
2543 									nFillHarshFlags |= 0x40000;
2544 									if ( eExtrusionProjectionMode == drawing::ProjectionMode_PARALLEL )
2545 										nFillHarshFlags |= 4;
2546 									else
2547 										nFillHarshFlags &=~4;
2548 								}
2549 							}
2550 							else if ( rrProp.Name.equals( sExtrusionViewPoint ) )
2551 							{
2552 								drawing::Position3D aExtrusionViewPoint;
2553 								if ( rrProp.Value >>= aExtrusionViewPoint )
2554 								{
2555 									aExtrusionViewPoint.PositionX *= 360.0;
2556 									aExtrusionViewPoint.PositionY *= 360.0;
2557 									aExtrusionViewPoint.PositionZ *= 360.0;
2558 									AddOpt( DFF_Prop_c3DXViewpoint, (sal_Int32)aExtrusionViewPoint.PositionX  );
2559 									AddOpt( DFF_Prop_c3DYViewpoint, (sal_Int32)aExtrusionViewPoint.PositionY  );
2560 									AddOpt( DFF_Prop_c3DZViewpoint, (sal_Int32)aExtrusionViewPoint.PositionZ  );
2561 								}
2562 							}
2563 							else if ( rrProp.Name.equals( sExtrusionOrigin ) )
2564 							{
2565 								double fExtrusionOriginX = 0;
2566 								double fExtrusionOriginY = 0;
2567 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginPair;
2568 								if ( ( rrProp.Value >>= aOriginPair ) && ( aOriginPair.First.Value >>= fExtrusionOriginX ) && ( aOriginPair.Second.Value >>= fExtrusionOriginY ) )
2569 								{
2570 									AddOpt( DFF_Prop_c3DOriginX, (sal_Int32)( fExtrusionOriginX * 65536 ) );
2571 									AddOpt( DFF_Prop_c3DOriginY, (sal_Int32)( fExtrusionOriginY * 65536 ) );
2572 								}
2573 							}
2574 							else if ( rrProp.Name.equals( sExtrusionColor ) )
2575 							{
2576 								sal_Bool bExtrusionColor = sal_Bool();
2577 								if ( rrProp.Value >>= bExtrusionColor )
2578 								{
2579 									nLightFaceFlags |= 0x20000;
2580 									if ( bExtrusionColor )
2581 									{
2582 										nLightFaceFlags |= 2;
2583 										uno::Any aFillColor2;
2584 										if ( EscherPropertyValueHelper::GetPropertyValue( aFillColor2, aXPropSet,
2585 											String( RTL_CONSTASCII_USTRINGPARAM( "FillColor2" ) ), sal_True ) )
2586 										{
2587 											sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aFillColor2.getValue()) );
2588 											AddOpt( DFF_Prop_c3DExtrusionColor, nFillColor );
2589 										}
2590 									}
2591 									else
2592 										nLightFaceFlags &=~2;
2593 								}
2594 							}
2595 						}
2596 						if ( nLightFaceFlags != nLightFaceFlagsOrg )
2597 							AddOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags );
2598 						if ( nFillHarshFlags != nFillHarshFlagsOrg )
2599 							AddOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags );
2600 					}
2601 				}
2602 				else if ( rProp.Name.equals( sEquations ) )
2603 				{
2604 					if ( !bIsDefaultObject )
2605 					{
2606 						sal_uInt16 nElements = (sal_uInt16)aEquations.size();
2607 						if ( nElements )
2608 						{
2609 							sal_uInt16 nElementSize = 8;
2610 							sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2611 							SvMemoryStream aOut( nStreamSize );
2612 							aOut << nElements
2613 								<< nElements
2614 								<< nElementSize;
2615 
2616 							std::vector< EnhancedCustomShapeEquation >::const_iterator aIter( aEquations.begin() );
2617 							std::vector< EnhancedCustomShapeEquation >::const_iterator aEnd ( aEquations.end() );
2618 							while( aIter != aEnd )
2619 							{
2620 								aOut << (sal_uInt16)aIter->nOperation
2621 									 << (sal_Int16)aIter->nPara[ 0 ]
2622 									 << (sal_Int16)aIter->nPara[ 1 ]
2623 									 << (sal_Int16)aIter->nPara[ 2 ];
2624 								aIter++;
2625 							}
2626 							sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2627 							memcpy( pBuf, aOut.GetData(), nStreamSize );
2628 							AddOpt( DFF_Prop_pFormulas, sal_True, nStreamSize - 6, pBuf, nStreamSize );
2629 						}
2630 						else
2631 						{
2632 							sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2633 							AddOpt( DFF_Prop_pFormulas, sal_True, 0, pBuf, 0 );
2634 						}
2635 					}
2636 				}
2637 				else if ( rProp.Name.equals( sPath ) )
2638 				{
2639 					uno::Sequence< beans::PropertyValue > aPathPropSeq;
2640 					if ( rProp.Value >>= aPathPropSeq )
2641 					{
2642 						sal_uInt32 nPathFlags, nPathFlagsOrg;
2643 						nPathFlagsOrg = nPathFlags = 0x39;
2644 						if ( GetOpt( DFF_Prop_fFillOK, nPathFlags ) )
2645 							nPathFlagsOrg = nPathFlags;
2646 
2647 						sal_Int32 r, nrCount = aPathPropSeq.getLength();
2648 						for ( r = 0; r < nrCount; r++ )
2649 						{
2650 							const beans::PropertyValue& rrProp = aPathPropSeq[ r ];
2651 							const rtl::OUString	sPathExtrusionAllowed				( RTL_CONSTASCII_USTRINGPARAM( "ExtrusionAllowed" ) );
2652 							const rtl::OUString	sPathConcentricGradientFillAllowed	( RTL_CONSTASCII_USTRINGPARAM( "ConcentricGradientFillAllowed" ) );
2653 							const rtl::OUString	sPathTextPathAllowed				( RTL_CONSTASCII_USTRINGPARAM( "TextPathAllowed" ) );
2654 							const rtl::OUString	sPathCoordinates					( RTL_CONSTASCII_USTRINGPARAM( "Coordinates" ) );
2655 							const rtl::OUString sPathGluePoints						( RTL_CONSTASCII_USTRINGPARAM( "GluePoints" ) );
2656 							const rtl::OUString sPathGluePointType					( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
2657 							const rtl::OUString	sPathSegments						( RTL_CONSTASCII_USTRINGPARAM( "Segments" ) );
2658 							const rtl::OUString	sPathStretchX						( RTL_CONSTASCII_USTRINGPARAM( "StretchX" ) );
2659 							const rtl::OUString	sPathStretchY						( RTL_CONSTASCII_USTRINGPARAM( "StretchY" ) );
2660 							const rtl::OUString	sPathTextFrames						( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) );
2661 
2662 							if ( rrProp.Name.equals( sPathExtrusionAllowed ) )
2663 							{
2664 								sal_Bool bExtrusionAllowed = sal_Bool();
2665 								if ( rrProp.Value >>= bExtrusionAllowed )
2666 								{
2667 									nPathFlags |= 0x100000;
2668 									if ( bExtrusionAllowed )
2669 										nPathFlags |= 16;
2670 									else
2671 										nPathFlags &=~16;
2672 								}
2673 							}
2674 							else if ( rrProp.Name.equals( sPathConcentricGradientFillAllowed ) )
2675 							{
2676 								sal_Bool bConcentricGradientFillAllowed = sal_Bool();
2677 								if ( rrProp.Value >>= bConcentricGradientFillAllowed )
2678 								{
2679 									nPathFlags |= 0x20000;
2680 									if ( bConcentricGradientFillAllowed )
2681 										nPathFlags |= 2;
2682 									else
2683 										nPathFlags &=~2;
2684 								}
2685 							}
2686 							else if ( rrProp.Name.equals( sPathTextPathAllowed ) )
2687 							{
2688 								sal_Bool bTextPathAllowed = sal_Bool();
2689 								if ( rrProp.Value >>= bTextPathAllowed )
2690 								{
2691 									nPathFlags |= 0x40000;
2692 									if ( bTextPathAllowed )
2693 										nPathFlags |= 4;
2694 									else
2695 										nPathFlags &=~4;
2696 								}
2697 							}
2698 							else if ( rrProp.Name.equals( sPathCoordinates ) )
2699 							{
2700 								if ( !bIsDefaultObject )
2701 								{
2702 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
2703 									if ( rrProp.Value >>= aCoordinates )
2704 									{
2705 										// creating the vertices
2706 										if ( (sal_uInt16)aCoordinates.getLength() )
2707 										{
2708 											sal_uInt16 j, nElements = (sal_uInt16)aCoordinates.getLength();
2709 											sal_uInt16 nElementSize = 8;
2710 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2711 											SvMemoryStream aOut( nStreamSize );
2712 											aOut << nElements
2713 												<< nElements
2714 												<< nElementSize;
2715 											for( j = 0; j < nElements; j++ )
2716 											{
2717 												sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].First, aEquationOrder );
2718 												sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].Second, aEquationOrder );
2719 												aOut << X
2720 													<< Y;
2721 											}
2722 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2723 											memcpy( pBuf, aOut.GetData(), nStreamSize );
2724 											AddOpt( DFF_Prop_pVertices, sal_True, nStreamSize - 6, pBuf, nStreamSize );	// -6
2725 										}
2726 										else
2727 										{
2728 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2729 											AddOpt( DFF_Prop_pVertices, sal_True, 0, pBuf, 0 );
2730 										}
2731 									}
2732 								}
2733 							}
2734 							else if ( rrProp.Name.equals( sPathGluePoints ) )
2735 							{
2736 								if ( !bIsDefaultObject )
2737 								{
2738 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
2739 									if ( rrProp.Value >>= aGluePoints )
2740 									{
2741 										// creating the vertices
2742 										sal_uInt16 nElements = (sal_uInt16)aGluePoints.getLength();
2743 										if ( nElements )
2744 										{
2745 											sal_uInt16 j, nElementSize = 8;
2746 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2747 											SvMemoryStream aOut( nStreamSize );
2748 											aOut << nElements
2749 												<< nElements
2750 												<< nElementSize;
2751 											for( j = 0; j < nElements; j++ )
2752 											{
2753 												sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].First, aEquationOrder );
2754 												sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].Second, aEquationOrder );
2755 												aOut << X
2756 													<< Y;
2757 											}
2758 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2759 											memcpy( pBuf, aOut.GetData(), nStreamSize );
2760 											AddOpt( DFF_Prop_connectorPoints, sal_True, nStreamSize - 6, pBuf, nStreamSize );	// -6
2761 										}
2762 										else
2763 										{
2764 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2765 											AddOpt( DFF_Prop_connectorPoints, sal_True, 0, pBuf, 0 );
2766 										}
2767 									}
2768 								}
2769 							}
2770 							else if ( rrProp.Name.equals( sPathGluePointType ) )
2771 							{
2772 								sal_Int16 nGluePointType = sal_Int16();
2773 								if ( rrProp.Value >>= nGluePointType )
2774 									AddOpt( DFF_Prop_connectorType, (sal_uInt16)nGluePointType );
2775 							}
2776 							else if ( rrProp.Name.equals( sPathSegments ) )
2777 							{
2778 								if ( !bIsDefaultObject )
2779 								{
2780 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments;
2781 									if ( rrProp.Value >>= aSegments )
2782 									{
2783 										// creating seginfo
2784 										if ( (sal_uInt16)aSegments.getLength() )
2785 										{
2786 											sal_uInt16 j, nElements = (sal_uInt16)aSegments.getLength();
2787 											sal_uInt16 nElementSize = 2;
2788 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2789 											SvMemoryStream aOut( nStreamSize );
2790 											aOut << nElements
2791 												<< nElements
2792 												<< nElementSize;
2793 											for ( j = 0; j < nElements; j++ )
2794 											{
2795 												sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count;
2796 												switch( aSegments[ j ].Command )
2797 												{
2798 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
2799 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break;
2800 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
2801 													{
2802 														nVal = 0x4000;
2803 													}
2804 													break;
2805 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
2806 													{
2807 														nVal |= 0x2000;
2808 													}
2809 													break;
2810 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
2811 													{
2812 														nVal = 0x6001;
2813 													}
2814 													break;
2815 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
2816 													{
2817 														nVal = 0x8000;
2818 													}
2819 													break;
2820 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
2821 													{
2822 														nVal = 0xaa00;
2823 													}
2824 													break;
2825 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
2826 													{
2827 														nVal = 0xab00;
2828 													}
2829 													break;
2830 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
2831 													{
2832 														nVal *= 3;
2833 														nVal |= 0xa100;
2834 													}
2835 													break;
2836 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
2837 													{
2838 														nVal *= 3;
2839 														nVal |= 0xa200;
2840 													}
2841 													break;
2842 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
2843 													{
2844 														nVal <<= 2;
2845 														nVal |= 0xa300;
2846 													}
2847 													break;
2848 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC :
2849 													{
2850 														nVal <<= 2;
2851 														nVal |= 0xa400;
2852 													}
2853 													break;
2854 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
2855 													{
2856 														nVal <<= 2;
2857 														nVal |= 0xa500;
2858 													}
2859 													break;
2860 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
2861 													{
2862 														nVal <<= 2;
2863 														nVal |= 0xa600;
2864 													}
2865 													break;
2866 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
2867 													{
2868 														nVal |= 0xa700;
2869 													}
2870 													break;
2871 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
2872 													{
2873 														nVal |= 0xa800;
2874 													}
2875 													break;
2876 												}
2877 												aOut << nVal;
2878 											}
2879 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2880 											memcpy( pBuf, aOut.GetData(), nStreamSize );
2881 											AddOpt( DFF_Prop_pSegmentInfo, sal_False, nStreamSize - 6, pBuf, nStreamSize );
2882 										}
2883 										else
2884 										{
2885 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2886 											AddOpt( DFF_Prop_pSegmentInfo, sal_True, 0, pBuf, 0 );
2887 										}
2888 									}
2889 								}
2890 							}
2891 							else if ( rrProp.Name.equals( sPathStretchX ) )
2892 							{
2893 								if ( !bIsDefaultObject )
2894 								{
2895 									sal_Int32 nStretchX = 0;
2896 									if ( rrProp.Value >>= nStretchX )
2897 										AddOpt( DFF_Prop_stretchPointX, nStretchX );
2898 								}
2899 							}
2900 							else if ( rrProp.Name.equals( sPathStretchY ) )
2901 							{
2902 								if ( !bIsDefaultObject )
2903 								{
2904 									sal_Int32 nStretchY = 0;
2905 									if ( rrProp.Value >>= nStretchY )
2906 										AddOpt( DFF_Prop_stretchPointY, nStretchY );
2907 								}
2908 							}
2909 							else if ( rrProp.Name.equals( sPathTextFrames ) )
2910 							{
2911 								if ( !bIsDefaultObject )
2912 								{
2913 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
2914 									if ( rrProp.Value >>= aPathTextFrames )
2915 									{
2916 										if ( (sal_uInt16)aPathTextFrames.getLength() )
2917 										{
2918 											sal_uInt16 j, nElements = (sal_uInt16)aPathTextFrames.getLength();
2919 											sal_uInt16 nElementSize = 16;
2920 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2921 											SvMemoryStream aOut( nStreamSize );
2922 											aOut << nElements
2923 												<< nElements
2924 												<< nElementSize;
2925 											for ( j = 0; j < nElements; j++ )
2926 											{
2927 												sal_Int32 nLeft = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.First, aEquationOrder );
2928 												sal_Int32 nTop  = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.Second, aEquationOrder );
2929 												sal_Int32 nRight = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.First, aEquationOrder );
2930 												sal_Int32 nBottom = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.Second, aEquationOrder );
2931 
2932 												aOut << nLeft
2933 													<< nTop
2934 													<< nRight
2935 													<< nBottom;
2936 											}
2937 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2938 											memcpy( pBuf, aOut.GetData(), nStreamSize );
2939 											AddOpt( DFF_Prop_textRectangles, sal_True, nStreamSize - 6, pBuf, nStreamSize );
2940 										}
2941 										else
2942 										{
2943 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2944 											AddOpt( DFF_Prop_textRectangles, sal_True, 0, pBuf, 0 );
2945 										}
2946 									}
2947 								}
2948 							}
2949 						}
2950 						if ( nPathFlags != nPathFlagsOrg )
2951 							AddOpt( DFF_Prop_fFillOK, nPathFlags );
2952 					}
2953 				}
2954 				else if ( rProp.Name.equals( sTextPath ) )
2955 				{
2956 					uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
2957 					if ( rProp.Value >>= aTextPathPropSeq )
2958 					{
2959 						sal_uInt32 nTextPathFlagsOrg, nTextPathFlags;
2960 						nTextPathFlagsOrg = nTextPathFlags = 0xffff1000;		// default
2961 						if ( GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ) )
2962 							nTextPathFlagsOrg = nTextPathFlags;
2963 
2964 						sal_Int32 r, nrCount = aTextPathPropSeq.getLength();
2965 						for ( r = 0; r < nrCount; r++ )
2966 						{
2967 							const beans::PropertyValue& rrProp = aTextPathPropSeq[ r ];
2968 							const rtl::OUString	sTextPathMode		( RTL_CONSTASCII_USTRINGPARAM( "TextPathMode" ) );
2969 							const rtl::OUString	sTextPathScaleX		( RTL_CONSTASCII_USTRINGPARAM( "ScaleX" ) );
2970 							const rtl::OUString sSameLetterHeights	( RTL_CONSTASCII_USTRINGPARAM( "SameLetterHeights" ) );
2971 
2972 							if ( rrProp.Name.equals( sTextPath ) )
2973 							{
2974 								sal_Bool bTextPathOn = sal_Bool();
2975 								if ( rrProp.Value >>= bTextPathOn )
2976 								{
2977 									nTextPathFlags |= 0x40000000;
2978 									if ( bTextPathOn )
2979 									{
2980 										nTextPathFlags |= 0x4000;
2981 
2982 										sal_uInt32 nPathFlags = 0x39;
2983 										GetOpt( DFF_Prop_fFillOK, nPathFlags );	// SJ: can be removed if we are supporting the TextPathAllowed property in XML
2984 										nPathFlags |= 0x40004;
2985 										AddOpt( DFF_Prop_fFillOK, nPathFlags );
2986 									}
2987 									else
2988 										nTextPathFlags &=~0x4000;
2989 								}
2990 							}
2991 							else if ( rrProp.Name.equals( sTextPathMode ) )
2992 							{
2993 								com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
2994 								if ( rrProp.Value >>= eTextPathMode )
2995 								{
2996 									nTextPathFlags |= 0x05000000;
2997 									nTextPathFlags &=~0x500;	// TextPathMode_NORMAL
2998 									if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH )
2999 										nTextPathFlags |= 0x100;
3000 									else if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE )
3001 										nTextPathFlags |= 0x500;
3002 								}
3003 							}
3004 							else if ( rrProp.Name.equals( sTextPathScaleX ) )
3005 							{
3006 								sal_Bool bTextPathScaleX = sal_Bool();
3007 								if ( rrProp.Value >>= bTextPathScaleX )
3008 								{
3009 									nTextPathFlags |= 0x00400000;
3010 									if ( bTextPathScaleX )
3011 										nTextPathFlags |= 0x40;
3012 									else
3013 										nTextPathFlags &=~0x40;
3014 								}
3015 							}
3016 							else if ( rrProp.Name.equals( sSameLetterHeights ) )
3017 							{
3018 								sal_Bool bSameLetterHeights = sal_Bool();
3019 								if ( rrProp.Value >>= bSameLetterHeights )
3020 								{
3021 									nTextPathFlags |= 0x00800000;
3022 									if ( bSameLetterHeights )
3023 										nTextPathFlags |= 0x80;
3024 									else
3025 										nTextPathFlags &=~0x80;
3026 								}
3027 							}
3028 						}
3029 						if ( nTextPathFlags & 0x4000 )		// Is FontWork ?
3030 						{
3031 							// FontWork Text
3032 							rtl::OUString aText;
3033 							uno::Reference< text::XSimpleText > xText( rXShape, uno::UNO_QUERY );
3034 							if ( xText.is() )
3035 								aText = xText->getString();
3036 							if ( !aText.getLength() )
3037 								aText = ::rtl::OUString::createFromAscii( "your text" );	// todo: moving into a resource
3038 							AddOpt( DFF_Prop_gtextUNICODE, aText );
3039 
3040 							// FontWork Font
3041 							rtl::OUString aFontName;
3042 							const rtl::OUString	sCharFontName			( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) );
3043 				    		uno::Any aAny = aXPropSet->getPropertyValue( sCharFontName );
3044 							aAny >>= aFontName;
3045 							if ( !aFontName.getLength() )
3046 								aFontName = ::rtl::OUString::createFromAscii( "Arial Black" );
3047 							AddOpt( DFF_Prop_gtextFont, aFontName );
3048 
3049 							sal_Int16 nCharScaleWidth = 100;
3050 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharScaleWidth" ) ), sal_True ) )
3051 							{
3052 								if ( aAny >>= nCharScaleWidth )
3053 								{
3054 									if ( nCharScaleWidth != 100 )
3055 									{
3056 										sal_Int32 nVal = nCharScaleWidth * 655;
3057 										AddOpt( DFF_Prop_gtextSpacing, nVal );
3058 									}
3059 								}
3060 							}
3061 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) ), sal_True ) )
3062 							{
3063 								float fCharHeight = 0.0;
3064 								if ( aAny >>= fCharHeight )
3065 								{
3066 									sal_Int32 nTextSize = static_cast< sal_Int32 > ( fCharHeight * 65536 );
3067 									AddOpt(ESCHER_Prop_gtextSize, nTextSize);
3068 								}
3069 							}
3070 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharKerning" ) ), sal_True ) )
3071 							{
3072 								sal_Int16 nCharKerning = sal_Int16();
3073 								if ( aAny >>= nCharKerning )
3074 							{
3075 									nTextPathFlags |= 0x10000000;
3076 									if ( nCharKerning )
3077 										nTextPathFlags |= 0x1000;
3078 									else
3079 										nTextPathFlags &=~0x1000;
3080 								}
3081 							}
3082 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharPosture" ) ), sal_True ) )
3083 							{
3084 								awt::FontSlant eFontSlant;
3085 								if ( aAny >>= eFontSlant )
3086 								{
3087 									nTextPathFlags |= 0x100010;
3088 									if ( eFontSlant != awt::FontSlant_NONE )
3089 										nTextPathFlags |= 0x10;
3090 									else
3091 										nTextPathFlags &=~0x10;
3092 								}
3093 							}
3094 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) ), sal_True ) )
3095 							{
3096 								float fFontWidth = 0;
3097 								if ( aAny >>= fFontWidth )
3098 								{
3099 									nTextPathFlags |= 0x200020;
3100 									if ( fFontWidth > awt::FontWeight::NORMAL )
3101 										nTextPathFlags |= 0x20;
3102 									else
3103 										nTextPathFlags &=~0x20;
3104 								}
3105 							}
3106 							//export gTextAlign attr
3107 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), sal_True ) )
3108 							{
3109 								MSO_GeoTextAlign  gTextAlign = mso_alignTextCenter;
3110 								SdrFitToSizeType  eFTS( ((SdrTextFitToSizeTypeItem&)pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
3111 								drawing::TextHorizontalAdjust	eHA( drawing::TextHorizontalAdjust_LEFT );
3112 								aAny >>= eHA;
3113 								switch( eHA )
3114 								{
3115 								case drawing::TextHorizontalAdjust_LEFT :
3116 									gTextAlign = mso_alignTextLeft;
3117 									break;
3118 								case drawing::TextHorizontalAdjust_CENTER:
3119 									gTextAlign = mso_alignTextCenter;
3120 									break;
3121 								case drawing::TextHorizontalAdjust_RIGHT:
3122 									gTextAlign = mso_alignTextRight;
3123 									break;
3124 								case drawing::TextHorizontalAdjust_BLOCK:
3125 									{
3126 										SdrFitToSizeType  eFTS( ((SdrTextFitToSizeTypeItem&)pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
3127 										if ( eFTS == SDRTEXTFIT_ALLLINES)
3128 										{
3129 											gTextAlign = mso_alignTextStretch;
3130 										}
3131 										else
3132 										{
3133 											gTextAlign = mso_alignTextWordJust;
3134 										}
3135 										break;
3136 									}
3137 								default:
3138 									break;
3139 								}
3140 								AddOpt(DFF_Prop_gtextAlign,gTextAlign);
3141 							}
3142 						}
3143 						if((nTextPathFlags & 0x4000) != 0)  //Is Font work
3144 						{
3145 							OutlinerParaObject* pOutlinerParaObject = pCustoShape->GetOutlinerParaObject();
3146 							if ( pOutlinerParaObject && pOutlinerParaObject->IsVertical() )
3147 								nTextPathFlags |= 0x2000;
3148 						}
3149 						if ( nTextPathFlags != nTextPathFlagsOrg )
3150 							AddOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
3151 					}
3152 				}
3153 				else if ( rProp.Name.equals( sHandles ) )
3154 				{
3155 					if ( !bIsDefaultObject )
3156 					{
3157 						bPredefinedHandlesUsed = sal_False;
3158 						if ( rProp.Value >>= aHandlesPropSeq )
3159 						{
3160 							sal_uInt16 nElements = (sal_uInt16)aHandlesPropSeq.getLength();
3161 							if ( nElements )
3162 							{
3163 								const rtl::OUString	sHandle ( RTL_CONSTASCII_USTRINGPARAM( "Handle" ) );
3164 
3165 								sal_uInt16 k, j, nElementSize = 36;
3166 								sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3167 								SvMemoryStream aOut( nStreamSize );
3168 								aOut << nElements
3169 									<< nElements
3170 									<< nElementSize;
3171 
3172 								for ( k = 0; k < nElements; k++ )
3173 								{
3174 									sal_uInt32 nFlags = 0;
3175 									sal_Int32 nXPosition = 0;
3176 									sal_Int32 nYPosition = 0;
3177 									sal_Int32 nXMap = 0;
3178 									sal_Int32 nYMap = 0;
3179 									sal_Int32 nXRangeMin = 0x80000000;
3180 									sal_Int32 nXRangeMax = 0x7fffffff;
3181 									sal_Int32 nYRangeMin = 0x80000000;
3182 									sal_Int32 nYRangeMax = 0x7fffffff;
3183 
3184 									const uno::Sequence< beans::PropertyValue >& rPropSeq = aHandlesPropSeq[ k ];
3185 									for ( j = 0; j < rPropSeq.getLength(); j++ )
3186 									{
3187 										const beans::PropertyValue& rPropVal = rPropSeq[ j ];
3188 
3189 										const rtl::OUString	sPosition			( RTL_CONSTASCII_USTRINGPARAM( "Position" ) );
3190 										const rtl::OUString	sMirroredX			( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) );
3191 										const rtl::OUString	sMirroredY			( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) );
3192 										const rtl::OUString	sSwitched			( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) );
3193 										const rtl::OUString	sPolar				( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) );
3194 	//									const rtl::OUString	sMap				( RTL_CONSTASCII_USTRINGPARAM( "Map" ) );
3195 										const rtl::OUString	sRadiusRangeMinimum	( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) );
3196 										const rtl::OUString	sRadiusRangeMaximum	( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) );
3197 										const rtl::OUString	sRangeXMinimum		( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) );
3198 										const rtl::OUString	sRangeXMaximum		( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) );
3199 										const rtl::OUString	sRangeYMinimum		( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) );
3200 										const rtl::OUString	sRangeYMaximum		( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) );
3201 
3202 										if ( rPropVal.Name.equals( sPosition ) )
3203 										{
3204 											com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
3205 											if ( rPropVal.Value >>= aPosition )
3206 											{
3207 												GetValueForEnhancedCustomShapeHandleParameter( nXPosition, aPosition.First );
3208 												GetValueForEnhancedCustomShapeHandleParameter( nYPosition, aPosition.Second );
3209 											}
3210 										}
3211 										else if ( rPropVal.Name.equals( sMirroredX ) )
3212 										{
3213 											sal_Bool bMirroredX = sal_Bool();
3214 											if ( rPropVal.Value >>= bMirroredX )
3215 											{
3216 												if ( bMirroredX )
3217 													nFlags |= 1;
3218 											}
3219 										}
3220 										else if ( rPropVal.Name.equals( sMirroredY ) )
3221 										{
3222 											sal_Bool bMirroredY = sal_Bool();
3223 											if ( rPropVal.Value >>= bMirroredY )
3224 											{
3225 												if ( bMirroredY )
3226 													nFlags |= 2;
3227 											}
3228 										}
3229 										else if ( rPropVal.Name.equals( sSwitched ) )
3230 										{
3231 											sal_Bool bSwitched = sal_Bool();
3232 											if ( rPropVal.Value >>= bSwitched )
3233 											{
3234 												if ( bSwitched )
3235 													nFlags |= 4;
3236 											}
3237 										}
3238 										else if ( rPropVal.Name.equals( sPolar ) )
3239 										{
3240 											com::sun::star::drawing::EnhancedCustomShapeParameterPair aPolar;
3241 											if ( rPropVal.Value >>= aPolar )
3242 											{
3243 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aPolar.First ) )
3244 													nFlags |= 0x800;
3245 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aPolar.Second ) )
3246 													nFlags |= 0x1000;
3247 												nFlags |= 8;
3248 											}
3249 										}
3250 	/* seems not to be used.
3251 										else if ( rPropVal.Name.equals( sMap ) )
3252 										{
3253 											com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap;
3254 											if ( rPropVal.Value >>= aMap )
3255 											{
3256 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) )
3257 													nFlags |= 0x800;
3258 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) )
3259 													nFlags |= 0x1000;
3260 												nFlags |= 0x10;
3261 											}
3262 										}
3263 	*/
3264 										else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) )
3265 										{
3266 											nYRangeMin = (sal_Int32)0xff4c0000;	// the range of angles seems to be a not
3267 											nYRangeMax = (sal_Int32)0x00b40000;	// used feature, so we are defaulting this
3268 
3269 											com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
3270 											if ( rPropVal.Value >>= aRadiusRangeMinimum )
3271 											{
3272 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aRadiusRangeMinimum ) )
3273 													nFlags |= 0x80;
3274 												nFlags |= 0x2000;
3275 											}
3276 										}
3277 										else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) )
3278 										{
3279 											nYRangeMin = (sal_Int32)0xff4c0000;	// the range of angles seems to be a not
3280 											nYRangeMax = (sal_Int32)0x00b40000;	// used feature, so we are defaulting this
3281 
3282 											com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
3283 											if ( rPropVal.Value >>= aRadiusRangeMaximum )
3284 											{
3285 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aRadiusRangeMaximum ) )
3286 													nFlags |= 0x100;
3287 												nFlags |= 0x2000;
3288 											}
3289 										}
3290 										else if ( rPropVal.Name.equals( sRangeXMinimum ) )
3291 										{
3292 											com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
3293 											if ( rPropVal.Value >>= aXRangeMinimum )
3294 											{
3295 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aXRangeMinimum ) )
3296 													nFlags |= 0x80;
3297 												nFlags |= 0x20;
3298 											}
3299 										}
3300 										else if ( rPropVal.Name.equals( sRangeXMaximum ) )
3301 										{
3302 											com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
3303 											if ( rPropVal.Value >>= aXRangeMaximum )
3304 											{
3305 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aXRangeMaximum ) )
3306 													nFlags |= 0x100;
3307 												nFlags |= 0x20;
3308 											}
3309 										}
3310 										else if ( rPropVal.Name.equals( sRangeYMinimum ) )
3311 										{
3312 											com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
3313 											if ( rPropVal.Value >>= aYRangeMinimum )
3314 											{
3315 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMin, aYRangeMinimum ) )
3316 													nFlags |= 0x200;
3317 												nFlags |= 0x20;
3318 											}
3319 										}
3320 										else if ( rPropVal.Name.equals( sRangeYMaximum ) )
3321 										{
3322 											com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
3323 											if ( rPropVal.Value >>= aYRangeMaximum )
3324 											{
3325 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMax, aYRangeMaximum ) )
3326 													nFlags |= 0x400;
3327 												nFlags |= 0x20;
3328 											}
3329 										}
3330 									}
3331 									aOut << nFlags
3332 										<< nXPosition
3333 										<< nYPosition
3334 										<< nXMap
3335 										<< nYMap
3336 										<< nXRangeMin
3337 										<< nXRangeMax
3338 										<< nYRangeMin
3339 										<< nYRangeMax;
3340 
3341 									if ( nFlags & 8 )
3342 										nAdjustmentsWhichNeedsToBeConverted |= ( 1 << ( nYPosition - 0x100 ) );
3343 								}
3344 								sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3345 								memcpy( pBuf, aOut.GetData(), nStreamSize );
3346 								AddOpt( DFF_Prop_Handles, sal_True, nStreamSize - 6, pBuf, nStreamSize );
3347 							}
3348 							else
3349 							{
3350 								sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3351 								AddOpt( DFF_Prop_Handles, sal_True, 0, pBuf, 0 );
3352 							}
3353 						}
3354 					}
3355 				}
3356 				else if ( rProp.Name.equals( sAdjustmentValues ) )
3357 				{
3358 					// it is required, that the information which handle is polar has already be read,
3359 					// so we are able to change the polar value to a fixed float
3360 					pAdjustmentValuesProp = &rProp;
3361 				}
3362 			}
3363 			if ( pAdjustmentValuesProp )
3364 			{
3365 				uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
3366 				if ( pAdjustmentValuesProp->Value >>= aAdjustmentSeq )
3367 				{
3368 					if ( bPredefinedHandlesUsed )
3369 					    LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
3370 
3371 					sal_Int32 k, nValue = 0, nAdjustmentValues = aAdjustmentSeq.getLength();
3372 					for ( k = 0; k < nAdjustmentValues; k++ )
3373 					    if( GetAdjustmentValue( aAdjustmentSeq[ k ], k, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
3374 							AddOpt( (sal_uInt16)( DFF_Prop_adjustValue + k ), (sal_uInt32)nValue );
3375 				}
3376 			}
3377 		}
3378 	}
3379 }
3380 
3381 // ---------------------------------------------------------------------------------------------
3382 
3383 MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags, rtl::OUString& rShapeType )
3384 {
3385 	MSO_SPT eShapeType = mso_sptNil;
3386 	nMirrorFlags = 0;
3387 	uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
3388     if ( aXPropSet.is() )
3389     {
3390 		try
3391 		{
3392 			const OUString	sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM ( "CustomShapeGeometry" ) );
3393 			uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
3394 			uno::Sequence< beans::PropertyValue > aGeoPropSeq;
3395 			if ( aGeoPropSet >>= aGeoPropSeq )
3396 			{
3397 				sal_Int32 i, nCount = aGeoPropSeq.getLength();
3398 				for ( i = 0; i < nCount; i++ )
3399 				{
3400 					const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
3401 					if ( rProp.Name.equalsAscii( "Type" ) )
3402 					{
3403 						if ( rProp.Value >>= rShapeType )
3404 							eShapeType = EnhancedCustomShapeTypeNames::Get( rShapeType );
3405 					}
3406 					else if ( rProp.Name.equalsAscii( "MirroredX" ) )
3407 					{
3408 						sal_Bool bMirroredX = sal_Bool();
3409 						if ( ( rProp.Value >>= bMirroredX ) && bMirroredX )
3410 							nMirrorFlags  |= SHAPEFLAG_FLIPH;
3411 					}
3412 					else if ( rProp.Name.equalsAscii( "MirroredY" ) )
3413 					{
3414 						sal_Bool bMirroredY = sal_Bool();
3415 						if ( ( rProp.Value >>= bMirroredY ) && bMirroredY )
3416 							nMirrorFlags  |= SHAPEFLAG_FLIPV;
3417 					}
3418 				}
3419 			}
3420 		}
3421 		catch( ::com::sun::star::uno::Exception& )
3422 		{
3423 		}
3424 	}
3425 	return eShapeType;
3426 }
3427 
3428 MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags )
3429 {
3430 	rtl::OUString aShapeType;
3431 	return GetCustomShapeType( rXShape, nMirrorFlags, aShapeType );
3432 }
3433 
3434 // ---------------------------------------------------------------------------------------------
3435 
3436 EscherPersistTable::EscherPersistTable()
3437 {
3438 }
3439 
3440 // ---------------------------------------------------------------------------------------------
3441 
3442 EscherPersistTable::~EscherPersistTable()
3443 {
3444 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3445 		delete (EscherPersistEntry*)pPtr;
3446 }
3447 
3448 // ---------------------------------------------------------------------------------------------
3449 
3450 sal_Bool EscherPersistTable::PtIsID( sal_uInt32 nID )
3451 {
3452 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3453 	{
3454 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3455 			return sal_True;
3456 	}
3457 	return sal_False;
3458 }
3459 
3460 // ---------------------------------------------------------------------------------------------
3461 
3462 void EscherPersistTable::PtInsert( sal_uInt32 nID, sal_uInt32 nOfs )
3463 {
3464 	maPersistTable.Insert( new EscherPersistEntry( nID, nOfs ) );
3465 }
3466 
3467 // ---------------------------------------------------------------------------------------------
3468 
3469 sal_uInt32 EscherPersistTable::PtDelete( sal_uInt32 nID )
3470 {
3471 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3472 	{
3473 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3474 		{
3475 //			sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3476 			delete (EscherPersistEntry*) maPersistTable.Remove();
3477 		}
3478 	}
3479 	return 0;
3480 }
3481 
3482 // ---------------------------------------------------------------------------------------------
3483 
3484 sal_uInt32 EscherPersistTable::PtGetOffsetByID( sal_uInt32 nID )
3485 {
3486 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3487 	{
3488 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3489 			return ((EscherPersistEntry*)pPtr)->mnOffset;
3490 	}
3491 	return 0;
3492 };
3493 
3494 // ---------------------------------------------------------------------------------------------
3495 
3496 sal_uInt32 EscherPersistTable::PtReplace( sal_uInt32 nID, sal_uInt32 nOfs )
3497 {
3498 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3499 	{
3500 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3501 		{
3502 			sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3503 			((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
3504 			return nRetValue;
3505 		}
3506 	}
3507 	return 0;
3508 }
3509 
3510 // ---------------------------------------------------------------------------------------------
3511 
3512 sal_uInt32 EscherPersistTable::PtReplaceOrInsert( sal_uInt32 nID, sal_uInt32 nOfs )
3513 {
3514 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3515 	{
3516 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3517 		{
3518 			sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3519 			((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
3520 			return nRetValue;
3521 		}
3522 	}
3523 	PtInsert( nID, nOfs );
3524 	return 0;
3525 }
3526 
3527 sal_Bool EscherPropertyValueHelper::GetPropertyValue(
3528 	::com::sun::star::uno::Any& rAny,
3529 		const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
3530 			const String& rString,
3531 					sal_Bool bTestPropertyAvailability )
3532 {
3533     sal_Bool bRetValue = sal_True;
3534 	if ( bTestPropertyAvailability )
3535 	{
3536 		bRetValue = sal_False;
3537 		try
3538 		{
3539 			::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
3540 				aXPropSetInfo( rXPropSet->getPropertySetInfo() );
3541 			if ( aXPropSetInfo.is() )
3542 				bRetValue = aXPropSetInfo->hasPropertyByName( rString );
3543 		}
3544 		catch( ::com::sun::star::uno::Exception& )
3545 		{
3546 			bRetValue = sal_False;
3547 		}
3548 	}
3549 	if ( bRetValue )
3550 	{
3551 		try
3552 		{
3553 			rAny = rXPropSet->getPropertyValue( rString );
3554 			if ( !rAny.hasValue() )
3555 				bRetValue = sal_False;
3556 		}
3557 		catch( ::com::sun::star::uno::Exception& )
3558 		{
3559 			bRetValue = sal_False;
3560 		}
3561 	}
3562     return bRetValue;
3563 }
3564 
3565 // ---------------------------------------------------------------------------------------------
3566 
3567 ::com::sun::star::beans::PropertyState EscherPropertyValueHelper::GetPropertyState(
3568 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
3569 		const String& rPropertyName )
3570 {
3571 	::com::sun::star::beans::PropertyState eRetValue = ::com::sun::star::beans::PropertyState_AMBIGUOUS_VALUE;
3572 	try
3573 	{
3574 		::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState >	aXPropState
3575 				( rXPropSet, ::com::sun::star::uno::UNO_QUERY );
3576 		if ( aXPropState.is() )
3577             eRetValue = aXPropState->getPropertyState( rPropertyName );
3578 	}
3579 	catch( ::com::sun::star::uno::Exception& )
3580 	{
3581 		//...
3582 	}
3583 	return eRetValue;
3584 }
3585 
3586 // ---------------------------------------------------------------------------------------------
3587 // ---------------------------------------------------------------------------------------------
3588 // ---------------------------------------------------------------------------------------------
3589 
3590 EscherBlibEntry::EscherBlibEntry( sal_uInt32 nPictureOffset, const GraphicObject& rObject, const ByteString& rId,
3591 										const GraphicAttr* pGraphicAttr ) :
3592 	mnPictureOffset ( nPictureOffset ),
3593 	mnRefCount		( 1 ),
3594 	mnSizeExtra		( 0 ),
3595 	maPrefSize		( rObject.GetPrefSize() ),
3596 	maPrefMapMode	( rObject.GetPrefMapMode() ),
3597 	mbIsEmpty		( sal_True )
3598 {
3599 	mbIsNativeGraphicPossible = ( pGraphicAttr == NULL );
3600 	meBlibType = UNKNOWN;
3601 	mnSize = 0;
3602 
3603 	sal_uInt32		nLen = rId.Len();
3604 	const sal_Char* pData = rId.GetBuffer();
3605 	GraphicType		eType( rObject.GetType() );
3606 	if ( nLen && pData && ( eType != GRAPHIC_NONE ) )
3607 	{
3608 		mnIdentifier[ 0 ] = rtl_crc32( 0,pData, nLen );
3609 		mnIdentifier[ 1 ] = 0;
3610 
3611 		if ( pGraphicAttr )
3612 		{
3613 			if ( pGraphicAttr->IsSpecialDrawMode()
3614 					|| pGraphicAttr->IsMirrored()
3615 						 || pGraphicAttr->IsCropped()
3616 							|| pGraphicAttr->IsRotated()
3617 								|| pGraphicAttr->IsTransparent()
3618 									|| pGraphicAttr->IsAdjusted() )
3619 			{
3620 				SvMemoryStream aSt( sizeof( GraphicAttr ) );
3621 				aSt << static_cast<sal_uInt16>(pGraphicAttr->GetDrawMode())
3622 					<< static_cast<sal_uInt32>(pGraphicAttr->GetMirrorFlags())
3623 					<< pGraphicAttr->GetLeftCrop()
3624 					<< pGraphicAttr->GetTopCrop()
3625 					<< pGraphicAttr->GetRightCrop()
3626 					<< pGraphicAttr->GetBottomCrop()
3627 					<< pGraphicAttr->GetRotation()
3628 					<< pGraphicAttr->GetLuminance()
3629 					<< pGraphicAttr->GetContrast()
3630 					<< pGraphicAttr->GetChannelR()
3631 					<< pGraphicAttr->GetChannelG()
3632 					<< pGraphicAttr->GetChannelB()
3633 					<< pGraphicAttr->GetGamma()
3634 					<< (sal_Bool)( pGraphicAttr->IsInvert() == sal_True )
3635 					<< pGraphicAttr->GetTransparency();
3636 				mnIdentifier[ 1 ] = rtl_crc32( 0, aSt.GetData(), aSt.Tell() );
3637 			}
3638 			else
3639 				mbIsNativeGraphicPossible = sal_True;
3640 		}
3641 		sal_uInt32 i, nTmp, n1, n2;
3642 		n1 = n2 = 0;
3643 		for ( i = 0; i < nLen; i++ )
3644 		{
3645 			nTmp = n2 >> 28;	// rotating 4 bit
3646 			n2 <<= 4;
3647 			n2 |= n1 >> 28;
3648 			n1 <<= 4;
3649 			n1 |= nTmp;
3650 			n1 ^= *pData++ - '0';
3651 		}
3652 		mnIdentifier[ 2 ] = n1;
3653 		mnIdentifier[ 3 ] = n2;
3654 		mbIsEmpty = sal_False;
3655 	}
3656 };
3657 
3658 // ---------------------------------------------------------------------------------------------
3659 
3660 void EscherBlibEntry::WriteBlibEntry( SvStream& rSt, sal_Bool bWritePictureOffset, sal_uInt32 nResize )
3661 {
3662 	sal_uInt32	nPictureOffset = ( bWritePictureOffset ) ? mnPictureOffset : 0;
3663 
3664 	rSt << (sal_uInt32)( ( ESCHER_BSE << 16 ) | ( ( (sal_uInt16)meBlibType << 4 ) | 2 ) )
3665 		<< (sal_uInt32)( 36 + nResize )
3666 		<< (sal_uInt8)meBlibType;
3667 
3668 	switch ( meBlibType )
3669 	{
3670 		case EMF :
3671 		case WMF :	// EMF/WMF auf OS2 zu Pict Konvertieren
3672 			rSt << (sal_uInt8)PICT;
3673 		break;
3674 		default:
3675 			rSt << (sal_uInt8)meBlibType;
3676 	};
3677 
3678 	rSt.Write( &mnIdentifier[ 0 ], 16 );
3679 	rSt << (sal_uInt16)0
3680 		<< (sal_uInt32)( mnSize + mnSizeExtra )
3681 		<< mnRefCount
3682 		<< nPictureOffset
3683 		<< (sal_uInt32)0;
3684 }
3685 
3686 // ---------------------------------------------------------------------------------------------
3687 
3688 EscherBlibEntry::~EscherBlibEntry()
3689 {
3690 };
3691 
3692 // ---------------------------------------------------------------------------------------------
3693 
3694 sal_Bool EscherBlibEntry::operator==( const EscherBlibEntry& rEscherBlibEntry ) const
3695 {
3696 	for ( int i = 0; i < 3; i++ )
3697 	{
3698 		if ( mnIdentifier[ i ] != rEscherBlibEntry.mnIdentifier[ i ] )
3699 			return sal_False;
3700 	}
3701 	return sal_True;
3702 }
3703 
3704 // ---------------------------------------------------------------------------------------------
3705 // ---------------------------------------------------------------------------------------------
3706 // ---------------------------------------------------------------------------------------------
3707 
3708 EscherGraphicProvider::EscherGraphicProvider( sal_uInt32 nFlags ) :
3709 	mnFlags			( nFlags ),
3710 	mpBlibEntrys	( NULL ),
3711 	mnBlibBufSize	( 0 ),
3712 	mnBlibEntrys	( 0 )
3713 {
3714 }
3715 
3716 EscherGraphicProvider::~EscherGraphicProvider()
3717 {
3718 	for ( sal_uInt32 i = 0; i < mnBlibEntrys; delete mpBlibEntrys[ i++ ] ) ;
3719 	delete[] mpBlibEntrys;
3720 }
3721 
3722 void EscherGraphicProvider::SetNewBlipStreamOffset( sal_Int32 nOffset )
3723 {
3724 	for( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3725 	{
3726 		EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
3727 		pBlibEntry->mnPictureOffset += nOffset;
3728 	}
3729 }
3730 
3731 sal_uInt32 EscherGraphicProvider::ImplInsertBlib( EscherBlibEntry* p_EscherBlibEntry )
3732 {
3733 	if ( mnBlibBufSize == mnBlibEntrys )
3734 	{
3735 		mnBlibBufSize += 64;
3736 		EscherBlibEntry** pTemp = new EscherBlibEntry*[ mnBlibBufSize ];
3737 		for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3738 		{
3739 			pTemp[ i ] = mpBlibEntrys[ i ];
3740 		}
3741 		delete[] mpBlibEntrys;
3742 		mpBlibEntrys = pTemp;
3743 	}
3744 	mpBlibEntrys[ mnBlibEntrys++ ] = p_EscherBlibEntry;
3745 	return mnBlibEntrys;
3746 }
3747 
3748 sal_uInt32 EscherGraphicProvider::GetBlibStoreContainerSize( SvStream* pMergePicStreamBSE ) const
3749 {
3750 	sal_uInt32 nSize = 44 * mnBlibEntrys + 8;
3751 	if ( pMergePicStreamBSE )
3752 	{
3753 		for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3754 			nSize += mpBlibEntrys[ i ]->mnSize + mpBlibEntrys[ i ]->mnSizeExtra;
3755 	}
3756 	return nSize;
3757 }
3758 
3759 sal_Bool EscherGraphicProvider::WriteBlibStoreEntry(SvStream& rSt,
3760     sal_uInt32 nBlipId, sal_Bool bWritePictureOffSet, sal_uInt32 nResize)
3761 {
3762     if (nBlipId > mnBlibEntrys || nBlipId == 0)
3763         return sal_False;
3764     mpBlibEntrys[nBlipId-1]->WriteBlibEntry(rSt, bWritePictureOffSet, nResize);
3765     return sal_True;
3766 }
3767 
3768 void EscherGraphicProvider::WriteBlibStoreContainer( SvStream& rSt, SvStream* pMergePicStreamBSE )
3769 {
3770 	sal_uInt32	nSize = GetBlibStoreContainerSize( pMergePicStreamBSE );
3771 	if ( nSize )
3772 	{
3773 		rSt << (sal_uInt32)( ( ESCHER_BstoreContainer << 16 ) | 0x1f )
3774 			<< (sal_uInt32)( nSize - 8 );
3775 
3776 		if ( pMergePicStreamBSE )
3777 		{
3778 			sal_uInt32 i, nBlipSize, nOldPos = pMergePicStreamBSE->Tell();
3779 			const sal_uInt32 nBuf = 0x40000;	// 256KB buffer
3780 			sal_uInt8* pBuf = new sal_uInt8[ nBuf ];
3781 
3782 			for ( i = 0; i < mnBlibEntrys; i++ )
3783 			{
3784 				EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
3785 
3786 				ESCHER_BlibType nBlibType = pBlibEntry->meBlibType;
3787 				nBlipSize = pBlibEntry->mnSize + pBlibEntry->mnSizeExtra;
3788 				pBlibEntry->WriteBlibEntry( rSt, sal_False, nBlipSize );
3789 
3790 				// BLIP
3791 				pMergePicStreamBSE->Seek( pBlibEntry->mnPictureOffset );
3792 				sal_uInt16 n16;
3793 				// record version and instance
3794 				*pMergePicStreamBSE >> n16;
3795 				rSt << n16;
3796 				// record type
3797 				*pMergePicStreamBSE >> n16;
3798 				rSt << sal_uInt16( ESCHER_BlipFirst + nBlibType );
3799                 DBG_ASSERT( n16 == ESCHER_BlipFirst + nBlibType , "EscherGraphicProvider::WriteBlibStoreContainer: BLIP record types differ" );
3800 				sal_uInt32 n32;
3801 				// record size
3802 				*pMergePicStreamBSE >> n32;
3803 				nBlipSize -= 8;
3804 				rSt << nBlipSize;
3805                 DBG_ASSERT( nBlipSize == n32, "EscherGraphicProvider::WriteBlibStoreContainer: BLIP sizes differ" );
3806 				// record
3807 				while ( nBlipSize )
3808 				{
3809 					sal_uInt32 nBytes = ( nBlipSize > nBuf ? nBuf : nBlipSize );
3810 					pMergePicStreamBSE->Read( pBuf, nBytes );
3811 					rSt.Write( pBuf, nBytes );
3812 					nBlipSize -= nBytes;
3813 				}
3814 			}
3815 			delete[] pBuf;
3816 			pMergePicStreamBSE->Seek( nOldPos );
3817 		}
3818 		else
3819 		{
3820             for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3821                 mpBlibEntrys[ i ]->WriteBlibEntry( rSt, sal_True );
3822 		}
3823 	}
3824 }
3825 
3826 sal_Bool EscherGraphicProvider::GetPrefSize( const sal_uInt32 nBlibId, Size& rPrefSize, MapMode& rPrefMapMode )
3827 {
3828 	sal_Bool bInRange = nBlibId && ( ( nBlibId - 1 ) < mnBlibEntrys );
3829 	if ( bInRange )
3830 	{
3831 		EscherBlibEntry* pEntry = mpBlibEntrys[ nBlibId - 1 ];
3832 		rPrefSize = pEntry->maPrefSize;
3833 		rPrefMapMode = pEntry->maPrefMapMode;
3834 	}
3835 	return bInRange;
3836 }
3837 
3838 sal_uInt32 EscherGraphicProvider::GetBlibID( SvStream& rPicOutStrm, const ByteString& rId,
3839 											const Rectangle& /* rBoundRect */, const com::sun::star::awt::Rectangle* pVisArea, const GraphicAttr* pGraphicAttr )
3840 {
3841 	sal_uInt32			nBlibId = 0;
3842 	GraphicObject		aGraphicObject( rId );
3843 
3844 	EscherBlibEntry* p_EscherBlibEntry = new EscherBlibEntry( rPicOutStrm.Tell(), aGraphicObject, rId, pGraphicAttr );
3845 	if ( !p_EscherBlibEntry->IsEmpty() )
3846 	{
3847 		for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3848 		{
3849 			if ( *( mpBlibEntrys[ i ] )	== *p_EscherBlibEntry )
3850 			{
3851 				mpBlibEntrys[ i ]->mnRefCount++;
3852 				delete p_EscherBlibEntry;
3853 				return i + 1;
3854 			}
3855 		}
3856 
3857 		sal_Bool			bUseNativeGraphic( sal_False );
3858 
3859 		Graphic				aGraphic( aGraphicObject.GetTransformedGraphic( pGraphicAttr ) );
3860 		GfxLink				aGraphicLink;
3861 		SvMemoryStream		aStream;
3862 
3863 		const sal_uInt8*	pGraphicAry = NULL;
3864 
3865 		if ( p_EscherBlibEntry->mbIsNativeGraphicPossible && aGraphic.IsLink() )
3866 		{
3867 			aGraphicLink = aGraphic.GetLink();
3868 
3869 			p_EscherBlibEntry->mnSize = aGraphicLink.GetDataSize();
3870 			pGraphicAry = aGraphicLink.GetData();
3871 
3872 			if ( p_EscherBlibEntry->mnSize && pGraphicAry )
3873 			{
3874 				switch ( aGraphicLink.GetType() )
3875 				{
3876 					case GFX_LINK_TYPE_NATIVE_JPG : p_EscherBlibEntry->meBlibType = PEG; break;
3877 					case GFX_LINK_TYPE_NATIVE_PNG : p_EscherBlibEntry->meBlibType = PNG; break;
3878 					case GFX_LINK_TYPE_NATIVE_WMF :
3879 					{
3880 						if ( pGraphicAry && ( p_EscherBlibEntry->mnSize > 0x2c ) )
3881 						{
3882 							if ( ( pGraphicAry[ 0x28 ] == 0x20 ) && ( pGraphicAry[ 0x29 ] == 0x45 )		// check the magic
3883 								&& ( pGraphicAry[ 0x2a ] == 0x4d ) && ( pGraphicAry[ 0x2b ] == 0x46 ) )	// number ( emf detection )
3884 							{
3885 								p_EscherBlibEntry->meBlibType = EMF;
3886 							}
3887 							else
3888 							{
3889 								p_EscherBlibEntry->meBlibType = WMF;
3890 								if ( ( pGraphicAry[ 0 ] == 0xd7 ) && ( pGraphicAry[ 1 ] == 0xcd )
3891 									&& ( pGraphicAry[ 2 ] == 0xc6 ) && ( pGraphicAry[ 3 ] == 0x9a ) )
3892 								{	// we have to get rid of the metafileheader
3893 									pGraphicAry += 22;
3894 									p_EscherBlibEntry->mnSize -= 22;
3895 								}
3896 							}
3897 						}
3898 					}
3899 					break;
3900 					default: break;
3901 				}
3902 				if ( p_EscherBlibEntry->meBlibType != UNKNOWN )
3903 					bUseNativeGraphic = sal_True;
3904 			}
3905 		}
3906 		if ( !bUseNativeGraphic )
3907 		{
3908 			GraphicType eGraphicType = aGraphic.GetType();
3909 			if ( ( eGraphicType == GRAPHIC_BITMAP ) || ( eGraphicType == GRAPHIC_GDIMETAFILE ) )
3910 			{
3911 				sal_uInt32 nErrCode;
3912 				if ( !aGraphic.IsAnimated() )
3913 // !EMF				nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG  : CVT_WMF );
3914 					nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG  : CVT_EMF );
3915 				else
3916 				{	// to store a animation, a gif has to be included into the msOG chunk of a png	#I5583#
3917 					GraphicFilter*	pFilter = GraphicFilter::GetGraphicFilter();
3918 					SvMemoryStream  aGIFStream;
3919 					ByteString		aVersion( "MSOFFICE9.0" );
3920 					aGIFStream.Write( aVersion.GetBuffer(), aVersion.Len() );
3921 					nErrCode = pFilter->ExportGraphic( aGraphic, String(), aGIFStream,
3922 						pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "GIF" ) ) ), NULL );
3923 					com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aFilterData( 1 );
3924 					com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence( 1 );
3925 					sal_uInt32 nGIFSreamLen = aGIFStream.Tell();
3926 					com::sun::star::uno::Sequence< sal_Int8 > aGIFSeq( nGIFSreamLen );
3927 					sal_Int8* pSeq = aGIFSeq.getArray();
3928 					aGIFStream.Seek( STREAM_SEEK_TO_BEGIN );
3929 					aGIFStream.Read( pSeq, nGIFSreamLen );
3930 					com::sun::star::beans::PropertyValue aChunkProp, aFilterProp;
3931 					aChunkProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "msOG" ) );
3932 					aChunkProp.Value <<= aGIFSeq;
3933 					aAdditionalChunkSequence[ 0 ] = aChunkProp;
3934 					aFilterProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "AdditionalChunks" ) );
3935 					aFilterProp.Value <<= aAdditionalChunkSequence;
3936 					aFilterData[ 0 ] = aFilterProp;
3937 					nErrCode = pFilter->ExportGraphic( aGraphic, String(), aStream,
3938 						pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "PNG" ) ) ), &aFilterData );
3939 				}
3940 				if ( nErrCode == ERRCODE_NONE )
3941 				{
3942 // !EMF				p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : WMF;
3943 					p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : EMF;
3944 					aStream.Seek( STREAM_SEEK_TO_END );
3945 					p_EscherBlibEntry->mnSize = aStream.Tell();
3946 					pGraphicAry = (sal_uInt8*)aStream.GetData();
3947 
3948 					if ( p_EscherBlibEntry->meBlibType == WMF )		// the fileheader is not used
3949 					{
3950 						p_EscherBlibEntry->mnSize -= 22;
3951 						pGraphicAry += 22;
3952 					}
3953 				}
3954 			}
3955 		}
3956 
3957 		ESCHER_BlibType	eBlibType = p_EscherBlibEntry->meBlibType;
3958 		if ( p_EscherBlibEntry->mnSize && pGraphicAry && ( eBlibType != UNKNOWN ) )
3959 		{
3960 			sal_uInt32 nExtra, nAtomSize = 0;
3961 			sal_uInt32 nInstance, nUncompressedSize = p_EscherBlibEntry->mnSize;
3962 
3963 			if ( mnFlags & _E_GRAPH_PROV_USE_INSTANCES )
3964 			{
3965 				rPicOutStrm << (sal_uInt32)( 0x7f90000 | (sal_uInt16)( mnBlibEntrys << 4 ) )
3966 							<< (sal_uInt32)0;
3967 				nAtomSize = rPicOutStrm.Tell();
3968  				if ( eBlibType == PNG )
3969 					rPicOutStrm << (sal_uInt16)0x0606;
3970 				else if ( eBlibType == WMF )
3971 					rPicOutStrm << (sal_uInt16)0x0403;
3972 				else if ( eBlibType == EMF )
3973 					rPicOutStrm << (sal_uInt16)0x0402;
3974 				else if ( eBlibType == PEG )
3975 					rPicOutStrm << (sal_uInt16)0x0505;
3976 			}
3977 			if ( ( eBlibType == PEG ) || ( eBlibType == PNG ) )
3978 			{
3979 				nExtra = 17;
3980 				p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
3981 				nInstance = ( eBlibType == PNG ) ? 0xf01e6e00 : 0xf01d46a0;
3982 				rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
3983 				rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
3984 				rPicOutStrm << (sal_uInt8)0xff;
3985 				rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
3986 			}
3987 			else
3988 			{
3989 				ZCodec aZCodec( 0x8000, 0x8000 );
3990 				aZCodec.BeginCompression();
3991 				SvMemoryStream aDestStrm;
3992 				aZCodec.Write( aDestStrm, pGraphicAry, p_EscherBlibEntry->mnSize );
3993 				aZCodec.EndCompression();
3994 				aDestStrm.Seek( STREAM_SEEK_TO_END );
3995 				p_EscherBlibEntry->mnSize = aDestStrm.Tell();
3996 				pGraphicAry = (sal_uInt8*)aDestStrm.GetData();
3997 				if ( p_EscherBlibEntry->mnSize && pGraphicAry )
3998 				{
3999 					nExtra = eBlibType == WMF ? 0x42 : 0x32;									// !EMF -> no change
4000 					p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
4001 					nInstance = ( eBlibType == WMF ) ? 0xf01b2170 : 0xf01a3d40;					// !EMF -> no change
4002 					rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
4003 					if ( eBlibType == WMF )														// !EMF -> no change
4004 						rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
4005 					rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
4006 
4007                     /*
4008                      ##913##
4009                      For Word the stored size of the graphic is critical the
4010                      metafile boundaries must match the actual graphics
4011                      boundaries, and the width and height must be in EMU's
4012 
4013                      If you don't do it this way then objects edited in the
4014                      msoffice app may show strange behaviour as the size jumps
4015                      around, and the original size and scaling factor in word
4016                      will be a very strange figure
4017                     */
4018                     sal_uInt32 nPrefWidth = p_EscherBlibEntry->maPrefSize.Width();
4019                     sal_uInt32 nPrefHeight = p_EscherBlibEntry->maPrefSize.Height();
4020 					sal_uInt32 nWidth, nHeight;
4021 					if ( pVisArea )
4022 					{
4023 						nWidth = pVisArea->Width * 360;
4024 						nHeight = pVisArea->Height * 360;
4025 					}
4026 					else
4027 					{
4028 						Size aPrefSize(lcl_SizeToEmu(p_EscherBlibEntry->maPrefSize, p_EscherBlibEntry->maPrefMapMode));
4029 						nWidth = aPrefSize.Width() * 360;
4030 	                    nHeight = aPrefSize.Height() * 360;
4031 					}
4032                     rPicOutStrm	<< nUncompressedSize // WMFSize without FileHeader
4033                     << (sal_Int32)0		// da die Originalgroesse des WMF's (ohne FileHeader)
4034                     << (sal_Int32)0		// nicht mehr feststellbar ist, schreiben wir 10cm / x
4035                     << nPrefWidth
4036                     << nPrefHeight
4037                     << nWidth
4038                     << nHeight
4039                     << p_EscherBlibEntry->mnSize
4040                     << (sal_uInt16)0xfe00;	// compression Flags
4041                     rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
4042 				}
4043 			}
4044 			if ( nAtomSize )
4045 			{
4046 				sal_uInt32	nPos = rPicOutStrm.Tell();
4047 				rPicOutStrm.Seek( nAtomSize - 4 );
4048 				rPicOutStrm << (sal_uInt32)( nPos - nAtomSize );
4049 				rPicOutStrm.Seek( nPos );
4050 			}
4051 			nBlibId = ImplInsertBlib( p_EscherBlibEntry ), p_EscherBlibEntry = NULL;
4052 		}
4053 	}
4054 	if ( p_EscherBlibEntry )
4055 		delete p_EscherBlibEntry;
4056 	return nBlibId;
4057 }
4058 
4059 // ---------------------------------------------------------------------------------------------
4060 // ---------------------------------------------------------------------------------------------
4061 // ---------------------------------------------------------------------------------------------
4062 
4063 struct EscherConnectorRule
4064 {
4065 	sal_uInt32	nRuleId;
4066 	sal_uInt32	nShapeA;		// SPID of shape A
4067 	sal_uInt32	nShapeB;		// SPID of shape B
4068 	sal_uInt32	nShapeC;		// SPID of connector shape
4069 	sal_uInt32	ncptiA;			// Connection site Index of shape A
4070 	sal_uInt32	ncptiB;			// Connection site Index of shape B
4071 };
4072 
4073 struct EscherShapeListEntry
4074 {
4075 	::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape	>	aXShape;
4076 	sal_uInt32			n_EscherId;
4077 
4078 						EscherShapeListEntry( const ::com::sun::star::uno::Reference
4079 							< ::com::sun::star::drawing::XShape > & rShape, sal_uInt32 nId ) :
4080 										aXShape		( rShape ),
4081 										n_EscherId	( nId ) {}
4082 };
4083 
4084 sal_uInt32 EscherConnectorListEntry::GetClosestPoint( const Polygon& rPoly, const ::com::sun::star::awt::Point& rPoint )
4085 {
4086 	sal_uInt16 nCount = rPoly.GetSize();
4087 	sal_uInt16 nClosest = nCount;
4088 	double fDist = (sal_uInt32)0xffffffff;
4089 	while( nCount-- )
4090 	{
4091 		double fDistance = hypot( rPoint.X - rPoly[ nCount ].X(), rPoint.Y - rPoly[ nCount ].Y() );
4092 		if ( fDistance < fDist )
4093 		{
4094 			nClosest =  nCount;
4095 			fDist = fDistance;
4096 		}
4097 	}
4098 	return nClosest;
4099 };
4100 
4101 // ---------------------------------------------------------------------------------------------
4102 // bei Rechtecken           bei Ellipsen    bei Polygonen
4103 //
4104 // nRule =  0 ->Top         0 ->Top         nRule = Index auf ein (Poly)Polygon Punkt
4105 //          1 ->Left        2 ->Left
4106 //          2 ->Bottom      4 ->Bottom
4107 //          3 ->Right       6 ->Right
4108 
4109 sal_uInt32 EscherConnectorListEntry::GetConnectorRule( sal_Bool bFirst )
4110 {
4111     sal_uInt32 nRule = 0;
4112 
4113 	::com::sun::star::uno::Any aAny;
4114     ::com::sun::star::awt::Point aRefPoint( ( bFirst ) ? maPointA : maPointB );
4115     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
4116 		aXShape( ( bFirst ) ? mXConnectToA : mXConnectToB );
4117 
4118 	String aString( (::rtl::OUString)aXShape->getShapeType() );
4119     ByteString aType( aString, RTL_TEXTENCODING_UTF8 );
4120     aType.Erase( 0, 13 );   // removing "com.sun.star."
4121     sal_uInt16 nPos = aType.Search( "Shape" );
4122     aType.Erase( nPos, 5 );
4123 
4124     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
4125 		aPropertySet( aXShape, ::com::sun::star::uno::UNO_QUERY );
4126 
4127     if ( aType == "drawing.PolyPolygon" || aType == "drawing.PolyLine" )
4128     {
4129         if ( aPropertySet.is() )
4130         {
4131 			if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4132 					aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ) ) )
4133 			{
4134                 ::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon =
4135 					(::com::sun::star::drawing::PointSequenceSequence*)aAny.getValue();
4136                 sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->getLength();
4137                 ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
4138 
4139                 if ( pOuterSequence )
4140                 {
4141                     sal_Int32 a, b, nIndex = 0;
4142                     sal_uInt32 nDistance = 0xffffffff;
4143                     for( a = 0; a < nOuterSequenceCount; a++ )
4144                     {
4145                         ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
4146                         if ( pInnerSequence )
4147                         {
4148                             ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
4149                             if ( pArray )
4150                             {
4151                                 for ( b = 0; b < pInnerSequence->getLength(); b++, nIndex++, pArray++ )
4152                                 {
4153                                     sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
4154                                     if ( nDist < nDistance )
4155                                     {
4156                                         nRule = nIndex;
4157                                         nDistance = nDist;
4158                                     }
4159                                 }
4160                             }
4161                         }
4162                     }
4163                 }
4164 			}
4165         }
4166     }
4167     else if ( ( aType == "drawing.OpenBezier" ) || ( aType == "drawing.OpenFreeHand" ) || ( aType == "drawing.PolyLinePath" )
4168         || ( aType == "drawing.ClosedBezier" ) || ( aType == "drawing.ClosedFreeHand" ) || ( aType == "drawing.PolyPolygonPath" ) )
4169     {
4170         ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
4171 			aPropertySet2( aXShape, ::com::sun::star::uno::UNO_QUERY );
4172         if ( aPropertySet2.is() )
4173         {
4174 			if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4175 					aPropertySet2, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ) ) )
4176 			{
4177 				::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon =
4178 					(::com::sun::star::drawing::PolyPolygonBezierCoords*)aAny.getValue();
4179                 sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->Coordinates.getLength();
4180 
4181                 // Zeiger auf innere sequences holen
4182                 ::com::sun::star::drawing::PointSequence* pOuterSequence =
4183 					pSourcePolyPolygon->Coordinates.getArray();
4184                 ::com::sun::star::drawing::FlagSequence*  pOuterFlags =
4185 					pSourcePolyPolygon->Flags.getArray();
4186 
4187                 if ( pOuterSequence && pOuterFlags )
4188                 {
4189                     sal_Int32 a, b, nIndex = 0;
4190                     sal_uInt32 nDistance = 0xffffffff;
4191 
4192                     for ( a = 0; a < nOuterSequenceCount; a++ )
4193                     {
4194                         ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
4195                         ::com::sun::star::drawing::FlagSequence*  pInnerFlags = pOuterFlags++;
4196                         if ( pInnerSequence && pInnerFlags )
4197                         {
4198                             ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
4199                             ::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
4200                             if ( pArray && pFlags )
4201                             {
4202                                 for ( b = 0; b < pInnerSequence->getLength(); b++, pArray++ )
4203                                 {
4204                                     PolyFlags ePolyFlags = *( (PolyFlags*)pFlags++ );
4205                                     if ( ePolyFlags == POLY_CONTROL )
4206                                         continue;
4207                                     sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
4208                                     if ( nDist < nDistance )
4209                                     {
4210                                         nRule = nIndex;
4211                                         nDistance = nDist;
4212                                     }
4213                                     nIndex++;
4214                                 }
4215                             }
4216                         }
4217                     }
4218                 }
4219             }
4220         }
4221     }
4222     else
4223     {
4224 		bool bRectangularConnection = true;
4225 
4226 		if ( aType == "drawing.Custom" )
4227 		{
4228 			SdrObject* pCustoShape( GetSdrObjectFromXShape( aXShape ) );
4229 			if ( pCustoShape && pCustoShape->ISA( SdrObjCustomShape ) )
4230 			{
4231 				SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)
4232 					pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
4233 
4234 				const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
4235 				const rtl::OUString	sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
4236 				const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
4237 
4238 				rtl::OUString sShapeType;
4239 				uno::Any* pType = rGeometryItem.GetPropertyValueByName( sType );
4240 				if ( pType )
4241 					*pType >>= sShapeType;
4242 				MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
4243 
4244 				uno::Any* pGluePointType = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePointType );
4245 
4246 				sal_Int16 nGluePointType = sal_Int16();
4247 				if ( !( pGluePointType &&
4248                         ( *pGluePointType >>= nGluePointType ) ) )
4249 					nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
4250 
4251 				if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::CUSTOM )
4252 				{
4253 					const SdrGluePointList* pList = pCustoShape->GetGluePointList();
4254 					if ( pList )
4255 					{
4256 						Polygon aPoly;
4257 						sal_uInt16 nNum, nAnz = pList->GetCount();
4258 						if ( nAnz )
4259 						{
4260 							for ( nNum = 0; nNum < nAnz; nNum++ )
4261 							{
4262 								const SdrGluePoint& rGP = (*pList)[ nNum ];
4263 								Point aPt( rGP.GetAbsolutePos( *pCustoShape ) );
4264 								aPoly.Insert( POLY_APPEND, aPt );
4265 							}
4266 							nRule = GetClosestPoint( aPoly, aRefPoint );
4267 							bRectangularConnection = false;
4268 						}
4269 					}
4270 				}
4271 				else if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::SEGMENTS )
4272 				{
4273 					SdrObject* pPoly = pCustoShape->DoConvertToPolyObj( sal_True, true );
4274 					if ( pPoly && pPoly->ISA( SdrPathObj ) )
4275 					{
4276 						sal_Int16 a, b, nIndex = 0;
4277 						sal_uInt32 nDistance = 0xffffffff;
4278 
4279 						// #i74631# use explicit constructor here. Also XPolyPolygon is not necessary,
4280 						// reducing to PolyPolygon
4281 						const PolyPolygon aPolyPoly(((SdrPathObj*)pPoly)->GetPathPoly());
4282 
4283 						for ( a = 0; a < aPolyPoly.Count(); a++ )
4284 						{
4285 							const Polygon& rPoly = aPolyPoly.GetObject( a );
4286 							for ( b = 0; b < rPoly.GetSize(); b++ )
4287 							{
4288 								if ( rPoly.GetFlags( b ) != POLY_NORMAL )
4289 									continue;
4290 								const Point& rPt = rPoly[ b ];
4291                                 sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - rPt.X(), aRefPoint.Y - rPt.Y() );
4292                                 if ( nDist < nDistance )
4293                                 {
4294                                     nRule = nIndex;
4295                                     nDistance = nDist;
4296                                 }
4297                                 nIndex++;
4298 							}
4299 						}
4300 						if ( nDistance != 0xffffffff )
4301 							bRectangularConnection = false;
4302 					}
4303 				}
4304 			}
4305 		}
4306 		if ( bRectangularConnection )
4307 		{
4308 			::com::sun::star::awt::Point aPoint( aXShape->getPosition() );
4309 			::com::sun::star::awt::Size	 aSize( aXShape->getSize() );
4310 
4311 			Rectangle	aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
4312 			Point		aCenter( aRect.Center() );
4313 			Polygon		aPoly( 4 );
4314 
4315 			aPoly[ 0 ] = Point( aCenter.X(), aRect.Top() );
4316 			aPoly[ 1 ] = Point( aRect.Left(), aCenter.Y() );
4317 			aPoly[ 2 ] = Point( aCenter.X(), aRect.Bottom() );
4318 			aPoly[ 3 ] = Point( aRect.Right(), aCenter.Y() );
4319 
4320 			sal_Int32 nAngle = ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4321 				aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True ) )
4322 					? *((sal_Int32*)aAny.getValue() )
4323 					: 0;
4324 			if ( nAngle )
4325 				aPoly.Rotate( aRect.TopLeft(), (sal_uInt16)( ( nAngle + 5 ) / 10 ) );
4326 			nRule = GetClosestPoint( aPoly, aRefPoint );
4327 
4328 			if ( aType == "drawing.Ellipse" )
4329 				nRule <<= 1;    // In PPT hat eine Ellipse 8 M?glichkeiten sich zu connecten
4330 		}
4331     }
4332     return nRule;
4333 }
4334 
4335 EscherSolverContainer::~EscherSolverContainer()
4336 {
4337     void* pP;
4338 
4339     for( pP = maShapeList.First(); pP; pP = maShapeList.Next() )
4340         delete (EscherShapeListEntry*)pP;
4341     for( pP = maConnectorList.First(); pP; pP = maConnectorList.Next() )
4342         delete (EscherConnectorListEntry*)pP;
4343 }
4344 
4345 void EscherSolverContainer::AddShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape, sal_uInt32 nId )
4346 {
4347     maShapeList.Insert( new EscherShapeListEntry( rXShape, nId ), LIST_APPEND );
4348 }
4349 
4350 void EscherSolverContainer::AddConnector( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConnector,
4351 										const ::com::sun::star::awt::Point& rPA,
4352 									::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConA,
4353 										const ::com::sun::star::awt::Point& rPB,
4354 									::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConB )
4355 {
4356     maConnectorList.Insert( new EscherConnectorListEntry( rConnector, rPA, rConA, rPB, rConB ), LIST_APPEND );
4357 }
4358 
4359 sal_uInt32 EscherSolverContainer::GetShapeId( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) const
4360 {
4361     for ( EscherShapeListEntry* pPtr = (EscherShapeListEntry*)((List&)maShapeList).First();
4362 			pPtr; pPtr = (EscherShapeListEntry*)((List&)maShapeList).Next() )
4363     {
4364         if ( rXShape == pPtr->aXShape )
4365             return ( pPtr->n_EscherId );
4366     }
4367     return 0;
4368 }
4369 
4370 void EscherSolverContainer::WriteSolver( SvStream& rStrm )
4371 {
4372     sal_uInt32 nCount = maConnectorList.Count();
4373     if ( nCount )
4374     {
4375 		sal_uInt32	nRecHdPos, nCurrentPos, nSize;
4376 		rStrm	<< (sal_uInt16)( ( nCount << 4 ) | 0xf )	// open an ESCHER_SolverContainer
4377 				<< (sal_uInt16)ESCHER_SolverContainer		//
4378 				<< (sal_uInt32)0;							//
4379 
4380 		nRecHdPos = rStrm.Tell() - 4;
4381 
4382         EscherConnectorRule aConnectorRule;
4383         aConnectorRule.nRuleId = 2;
4384         for ( EscherConnectorListEntry* pPtr = (EscherConnectorListEntry*)maConnectorList.First();
4385 				pPtr; pPtr = (EscherConnectorListEntry*)maConnectorList.Next() )
4386         {
4387             aConnectorRule.ncptiA = aConnectorRule.ncptiB = 0xffffffff;
4388             aConnectorRule.nShapeC = GetShapeId( pPtr->mXConnector );
4389             aConnectorRule.nShapeA = GetShapeId( pPtr->mXConnectToA );
4390             aConnectorRule.nShapeB = GetShapeId( pPtr->mXConnectToB );
4391 
4392             if ( aConnectorRule.nShapeC )
4393             {
4394                 if ( aConnectorRule.nShapeA )
4395                     aConnectorRule.ncptiA = pPtr->GetConnectorRule( sal_True );
4396                 if ( aConnectorRule.nShapeB )
4397                     aConnectorRule.ncptiB = pPtr->GetConnectorRule( sal_False );
4398             }
4399 			rStrm	<< (sal_uInt32)( ( ESCHER_ConnectorRule << 16 ) | 1 )	// atom hd
4400 					<< (sal_uInt32)24										//
4401 					<< aConnectorRule.nRuleId
4402                     << aConnectorRule.nShapeA
4403                     << aConnectorRule.nShapeB
4404                     << aConnectorRule.nShapeC
4405                     << aConnectorRule.ncptiA
4406                     << aConnectorRule.ncptiB;
4407 
4408             aConnectorRule.nRuleId += 2;
4409         }
4410 
4411 		nCurrentPos = rStrm.Tell();				// close the ESCHER_SolverContainer
4412 		nSize = ( nCurrentPos - nRecHdPos ) - 4;//
4413 		rStrm.Seek( nRecHdPos );				//
4414 		rStrm << nSize;							//
4415 		rStrm.Seek( nCurrentPos );				//
4416     }
4417 }
4418 
4419 // ---------------------------------------------------------------------------------------------
4420 
4421 EscherExGlobal::EscherExGlobal( sal_uInt32 nGraphicProvFlags ) :
4422     EscherGraphicProvider( nGraphicProvFlags ),
4423     mpPicStrm( 0 ),
4424     mbHasDggCont( false ),
4425     mbPicStrmQueried( false )
4426 {
4427 }
4428 
4429 EscherExGlobal::~EscherExGlobal()
4430 {
4431 }
4432 
4433 sal_uInt32 EscherExGlobal::GenerateDrawingId()
4434 {
4435     // new drawing starts a new cluster in the cluster table (cluster identifiers are one-based)
4436     sal_uInt32 nClusterId = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
4437     // drawing identifiers are one-based
4438     sal_uInt32 nDrawingId = static_cast< sal_uInt32 >( maDrawingInfos.size() + 1 );
4439     // prepare new entries in the tables
4440     maClusterTable.push_back( ClusterEntry( nDrawingId ) );
4441     maDrawingInfos.push_back( DrawingInfo( nClusterId ) );
4442     // return the new drawing identifier
4443     return nDrawingId;
4444 }
4445 
4446 sal_uInt32 EscherExGlobal::GenerateShapeId( sal_uInt32 nDrawingId, bool bIsInSpgr )
4447 {
4448     // drawing identifier is one-based
4449     size_t nDrawingIdx = nDrawingId - 1;
4450     OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GenerateShapeId - invalid drawing ID" );
4451     if( nDrawingIdx >= maDrawingInfos.size() )
4452         return 0;
4453     DrawingInfo& rDrawingInfo = maDrawingInfos[ nDrawingIdx ];
4454 
4455     // cluster identifier in drawing info struct is one-based
4456     ClusterEntry* pClusterEntry = &maClusterTable[ rDrawingInfo.mnClusterId - 1 ];
4457 
4458     // check cluster overflow, create new cluster entry
4459     if( pClusterEntry->mnNextShapeId == DFF_DGG_CLUSTER_SIZE )
4460     {
4461         // start a new cluster in the cluster table
4462         maClusterTable.push_back( ClusterEntry( nDrawingId ) );
4463         pClusterEntry = &maClusterTable.back();
4464         // new size of maClusterTable is equal to one-based identifier of the new cluster
4465         rDrawingInfo.mnClusterId = static_cast< sal_uInt32 >( maClusterTable.size() );
4466     }
4467 
4468     // build shape identifier from cluster identifier and next free cluster shape identifier
4469     rDrawingInfo.mnLastShapeId = static_cast< sal_uInt32 >( rDrawingInfo.mnClusterId * DFF_DGG_CLUSTER_SIZE + pClusterEntry->mnNextShapeId );
4470     // update free shape identifier in cluster entry
4471     ++pClusterEntry->mnNextShapeId;
4472     /*  Old code has counted the shapes only, if we are in a SPGRCONTAINER. Is
4473         this really intended? Maybe it's always true... */
4474     if( bIsInSpgr )
4475         ++rDrawingInfo.mnShapeCount;
4476 
4477     // return the new shape identifier
4478     return rDrawingInfo.mnLastShapeId;
4479 }
4480 
4481 sal_uInt32 EscherExGlobal::GetDrawingShapeCount( sal_uInt32 nDrawingId ) const
4482 {
4483     size_t nDrawingIdx = nDrawingId - 1;
4484     OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetDrawingShapeCount - invalid drawing ID" );
4485     return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnShapeCount : 0;
4486 }
4487 
4488 sal_uInt32 EscherExGlobal::GetLastShapeId( sal_uInt32 nDrawingId ) const
4489 {
4490     size_t nDrawingIdx = nDrawingId - 1;
4491     OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetLastShapeId - invalid drawing ID" );
4492     return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnLastShapeId : 0;
4493 }
4494 
4495 sal_uInt32 EscherExGlobal::GetDggAtomSize() const
4496 {
4497     // 8 bytes header, 16 bytes fixed DGG data, 8 bytes for each cluster
4498     return static_cast< sal_uInt32 >( 24 + 8 * maClusterTable.size() );
4499 }
4500 
4501 void EscherExGlobal::WriteDggAtom( SvStream& rStrm ) const
4502 {
4503     sal_uInt32 nDggSize = GetDggAtomSize();
4504 
4505     // write the DGG record header (do not include the 8 bytes of the header in the data size)
4506     rStrm << static_cast< sal_uInt32 >( ESCHER_Dgg << 16 ) << static_cast< sal_uInt32 >( nDggSize - 8 );
4507 
4508     // claculate and write the fixed DGG data
4509     sal_uInt32 nShapeCount = 0;
4510     sal_uInt32 nLastShapeId = 0;
4511     for( DrawingInfoVector::const_iterator aIt = maDrawingInfos.begin(), aEnd = maDrawingInfos.end(); aIt != aEnd; ++aIt )
4512     {
4513         nShapeCount += aIt->mnShapeCount;
4514         nLastShapeId = ::std::max( nLastShapeId, aIt->mnLastShapeId );
4515     }
4516     // the non-existing cluster with index #0 is counted too
4517     sal_uInt32 nClusterCount = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
4518     sal_uInt32 nDrawingCount = static_cast< sal_uInt32 >( maDrawingInfos.size() );
4519     rStrm << nLastShapeId << nClusterCount << nShapeCount << nDrawingCount;
4520 
4521     // write the cluster table
4522     for( ClusterTable::const_iterator aIt = maClusterTable.begin(), aEnd = maClusterTable.end(); aIt != aEnd; ++aIt )
4523         rStrm << aIt->mnDrawingId << aIt->mnNextShapeId;
4524 }
4525 
4526 SvStream* EscherExGlobal::QueryPictureStream()
4527 {
4528     if( !mbPicStrmQueried )
4529     {
4530         mpPicStrm = ImplQueryPictureStream();
4531         mbPicStrmQueried = true;
4532     }
4533     return mpPicStrm;
4534 }
4535 
4536 SvStream* EscherExGlobal::ImplQueryPictureStream()
4537 {
4538     return 0;
4539 }
4540 
4541 // ---------------------------------------------------------------------------------------------
4542 // ---------------------------------------------------------------------------------------------
4543 // ---------------------------------------------------------------------------------------------
4544 
4545 EscherEx::EscherEx( const EscherExGlobalRef& rxGlobal, SvStream& rOutStrm ) :
4546     mxGlobal                ( rxGlobal ),
4547 	mpOutStrm				( &rOutStrm ),
4548 
4549 	mnGroupLevel			( 0 ),
4550 	mnHellLayerId			( USHRT_MAX ),
4551 
4552 	mbEscherSpgr			( sal_False ),
4553     mbEscherDg              ( sal_False )
4554 {
4555 	mnStrmStartOfs = mpOutStrm->Tell();
4556     mpImplEscherExSdr.reset( new ImplEscherExSdr( *this ) );
4557 }
4558 
4559 EscherEx::~EscherEx()
4560 {
4561 }
4562 
4563 // ---------------------------------------------------------------------------------------------
4564 
4565 void EscherEx::Flush( SvStream* pPicStreamMergeBSE /* = NULL */ )
4566 {
4567     if ( mxGlobal->HasDggContainer() )
4568 	{
4569         // store the current stream position at ESCHER_Persist_CurrentPosition key
4570 		PtReplaceOrInsert( ESCHER_Persist_CurrentPosition, mpOutStrm->Tell() );
4571 		if ( DoSeek( ESCHER_Persist_Dgg ) )
4572 		{
4573             /*  The DGG record is still not written. ESCHER_Persist_Dgg seeks
4574                 to the place where the complete record has to be inserted. */
4575             InsertAtCurrentPos( mxGlobal->GetDggAtomSize(), false );
4576             mxGlobal->WriteDggAtom( *mpOutStrm );
4577 
4578             if ( mxGlobal->HasGraphics() )
4579             {
4580                 /*  Calculate the total size of the BSTORECONTAINER including
4581                     all BSE records containing the picture data contained in
4582                     the passed in pPicStreamMergeBSE. */
4583                 sal_uInt32 nBSCSize = mxGlobal->GetBlibStoreContainerSize( pPicStreamMergeBSE );
4584                 if ( nBSCSize > 0 )
4585                 {
4586                     InsertAtCurrentPos( nBSCSize, false );
4587                     mxGlobal->WriteBlibStoreContainer( *mpOutStrm, pPicStreamMergeBSE );
4588                 }
4589             }
4590 
4591             /*  Forget the stream position stored for the DGG which is invalid
4592                 after the call to InsertAtCurrentPos() anyway. */
4593             PtDelete( ESCHER_Persist_Dgg );
4594         }
4595         // seek to initial position (may be different due to inserted DGG and BLIPs)
4596 		mpOutStrm->Seek( PtGetOffsetByID( ESCHER_Persist_CurrentPosition ) );
4597 	}
4598 }
4599 
4600 // ---------------------------------------------------------------------------------------------
4601 
4602 void EscherEx::InsertAtCurrentPos( sal_uInt32 nBytes, bool bExpandEndOfAtom )
4603 {
4604 	sal_uInt32	nSize, nType, nSource, nBufSize, nToCopy, nCurPos = mpOutStrm->Tell();
4605 	sal_uInt8*	pBuf;
4606 
4607 	// Persist table anpassen
4608 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
4609 	{
4610 		sal_uInt32 nOfs = ((EscherPersistEntry*)pPtr)->mnOffset;
4611 		if ( nOfs >= nCurPos )
4612 			((EscherPersistEntry*)pPtr)->mnOffset += nBytes;
4613 	}
4614 
4615 	// container und atom sizes anpassen
4616 	mpOutStrm->Seek( mnStrmStartOfs );
4617 	while ( mpOutStrm->Tell() < nCurPos )
4618 	{
4619 		*mpOutStrm >> nType >> nSize;
4620         sal_uInt32 nEndOfRecord = mpOutStrm->Tell() + nSize;
4621         bool bContainer = (nType & 0x0F) == 0x0F;
4622         /*  Expand the record, if the insertion position is inside, or if the
4623             position is at the end of a container (expands always), or at the
4624             end of an atom and bExpandEndOfAtom is set. */
4625         if ( (nCurPos < nEndOfRecord) || ((nCurPos == nEndOfRecord) && (bContainer || bExpandEndOfAtom)) )
4626 		{
4627 			mpOutStrm->SeekRel( -4 );
4628 			*mpOutStrm << (sal_uInt32)( nSize + nBytes );
4629             if ( !bContainer )
4630 				mpOutStrm->SeekRel( nSize );
4631 		}
4632 		else
4633 			mpOutStrm->SeekRel( nSize );
4634 	}
4635 	std::vector< sal_uInt32 >::iterator aIter( mOffsets.begin() );
4636 	std::vector< sal_uInt32 >::iterator aEnd( mOffsets.end() );
4637 	while( aIter != aEnd )
4638 	{
4639 		if ( *aIter > nCurPos )
4640 			*aIter += nBytes;
4641 		aIter++;
4642 	}
4643 	mpOutStrm->Seek( STREAM_SEEK_TO_END );
4644 	nSource = mpOutStrm->Tell();
4645 	nToCopy = nSource - nCurPos;						// Stream um nBytes vergroessern
4646 	pBuf = new sal_uInt8[ 0x40000 ];							// 256KB Buffer
4647 	while ( nToCopy )
4648 	{
4649 		nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
4650 		nToCopy -= nBufSize;
4651 		nSource -= nBufSize;
4652 		mpOutStrm->Seek( nSource );
4653 		mpOutStrm->Read( pBuf, nBufSize );
4654 		mpOutStrm->Seek( nSource + nBytes );
4655 		mpOutStrm->Write( pBuf, nBufSize );
4656 	}
4657 	delete[] pBuf;
4658 	mpOutStrm->Seek( nCurPos );
4659 }
4660 
4661 // ---------------------------------------------------------------------------------------------
4662 
4663 sal_Bool EscherEx::SeekBehindRecHeader( sal_uInt16 nRecType )
4664 {
4665 	sal_uInt32	nOldPos, nStreamEnd, nType, nSize;
4666 
4667 	nOldPos = mpOutStrm->Tell();
4668 	nStreamEnd = mpOutStrm->Seek( STREAM_SEEK_TO_END );
4669 	mpOutStrm->Seek( nOldPos );
4670 	while ( mpOutStrm->Tell() < nStreamEnd )
4671 	{
4672 		*mpOutStrm >> nType >> nSize;
4673 		if ( ( nType >> 16 ) == nRecType )
4674 			return sal_True;
4675 		if ( ( nType & 0xf ) != 0xf )
4676 			mpOutStrm->SeekRel( nSize );
4677 	}
4678 	mpOutStrm->Seek( nOldPos );
4679 	return sal_False;
4680 }
4681 
4682 // ---------------------------------------------------------------------------------------------
4683 
4684 void EscherEx::InsertPersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
4685 {
4686 	PtInsert( ESCHER_Persist_PrivateEntry | nKey, nOffset );
4687 }
4688 
4689 void EscherEx::ReplacePersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
4690 {
4691     PtReplace( ESCHER_Persist_PrivateEntry | nKey, nOffset );
4692 }
4693 
4694 sal_uInt32 EscherEx::GetPersistOffset( sal_uInt32 nKey )
4695 {
4696     return PtGetOffsetByID( ESCHER_Persist_PrivateEntry | nKey );
4697 }
4698 
4699 // ---------------------------------------------------------------------------------------------
4700 
4701 sal_Bool EscherEx::DoSeek( sal_uInt32 nKey )
4702 {
4703 	sal_uInt32 nPos = PtGetOffsetByID( nKey );
4704 	if ( nPos )
4705 		mpOutStrm->Seek( nPos );
4706 	else
4707 	{
4708 		if (! PtIsID( nKey ) )
4709 			return sal_False;
4710 		mpOutStrm->Seek( 0 );
4711 	}
4712 	return sal_True;
4713 }
4714 
4715 // ---------------------------------------------------------------------------------------------
4716 
4717 sal_Bool EscherEx::SeekToPersistOffset( sal_uInt32 nKey )
4718 {
4719 	return DoSeek( ESCHER_Persist_PrivateEntry | nKey );
4720 }
4721 
4722 // ---------------------------------------------------------------------------------------------
4723 
4724 sal_Bool EscherEx::InsertAtPersistOffset( sal_uInt32 nKey, sal_uInt32 nValue )
4725 {
4726 	sal_uInt32	nOldPos = mpOutStrm->Tell();
4727 	sal_Bool	bRetValue = SeekToPersistOffset( nKey );
4728 	if ( bRetValue )
4729 	{
4730 		*mpOutStrm << nValue;
4731 		mpOutStrm->Seek( nOldPos );
4732 	}
4733 	return bRetValue;
4734 }
4735 
4736 // ---------------------------------------------------------------------------------------------
4737 
4738 void EscherEx::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
4739 {
4740 	*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | 0xf  ) << nEscherContainer << (sal_uInt32)0;
4741 	mOffsets.push_back( mpOutStrm->Tell() - 4 );
4742 	mRecTypes.push_back( nEscherContainer );
4743 	switch( nEscherContainer )
4744 	{
4745 		case ESCHER_DggContainer :
4746 		{
4747             mxGlobal->SetDggContainer();
4748 			mnCurrentDg	= 0;
4749             /*  Remember the current position as start position of the DGG
4750                 record and BSTORECONTAINER, but do not write them actually.
4751                 This will be done later in Flush() when the number of drawings,
4752                 the size and contents of the FIDCL cluster table, and the size
4753                 of the BLIP container are known. */
4754 			PtReplaceOrInsert( ESCHER_Persist_Dgg, mpOutStrm->Tell() );
4755 		}
4756 		break;
4757 
4758 		case ESCHER_DgContainer :
4759 		{
4760             if ( mxGlobal->HasDggContainer() )
4761 			{
4762 				if ( !mbEscherDg )
4763 				{
4764 					mbEscherDg = sal_True;
4765                     mnCurrentDg = mxGlobal->GenerateDrawingId();
4766 					AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
4767 					PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
4768 					*mpOutStrm << (sal_uInt32)0		// The number of shapes in this drawing
4769 							   << (sal_uInt32)0;	// The last MSOSPID given to an SP in this DG
4770 				}
4771 			}
4772 		}
4773 		break;
4774 
4775 		case ESCHER_SpgrContainer :
4776 		{
4777 			if ( mbEscherDg )
4778 			{
4779 				mbEscherSpgr = sal_True;
4780 			}
4781 		}
4782 		break;
4783 
4784 		case ESCHER_SpContainer :
4785 		{
4786 		}
4787 		break;
4788 
4789 		default:
4790 		break;
4791 	}
4792 }
4793 
4794 // ---------------------------------------------------------------------------------------------
4795 
4796 void EscherEx::CloseContainer()
4797 {
4798 	sal_uInt32 nSize, nPos = mpOutStrm->Tell();
4799 	nSize = ( nPos - mOffsets.back() ) - 4;
4800 	mpOutStrm->Seek( mOffsets.back() );
4801 	*mpOutStrm << nSize;
4802 
4803 	switch( mRecTypes.back() )
4804 	{
4805 		case ESCHER_DgContainer :
4806 		{
4807 			if ( mbEscherDg )
4808 			{
4809 				mbEscherDg = sal_False;
4810 				if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
4811                     *mpOutStrm << mxGlobal->GetDrawingShapeCount( mnCurrentDg ) << mxGlobal->GetLastShapeId( mnCurrentDg );
4812 			}
4813 		}
4814 		break;
4815 
4816 		case ESCHER_SpgrContainer :
4817 		{
4818 			if ( mbEscherSpgr )
4819 			{
4820 				mbEscherSpgr = sal_False;
4821 
4822 			}
4823 		}
4824 		break;
4825 
4826 		default:
4827 		break;
4828 	}
4829 	mOffsets.pop_back();
4830 	mRecTypes.pop_back();
4831 	mpOutStrm->Seek( nPos );
4832 }
4833 
4834 // ---------------------------------------------------------------------------------------------
4835 
4836 void EscherEx::BeginAtom()
4837 {
4838 	mnCountOfs = mpOutStrm->Tell();
4839 	*mpOutStrm << (sal_uInt32)0 << (sal_uInt32)0;		// record header wird spaeter geschrieben
4840 }
4841 
4842 // ---------------------------------------------------------------------------------------------
4843 
4844 void EscherEx::EndAtom( sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
4845 {
4846 	sal_uInt32	nOldPos = mpOutStrm->Tell();
4847 	mpOutStrm->Seek( mnCountOfs );
4848 	sal_uInt32 nSize = nOldPos - mnCountOfs;
4849 	*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << (sal_uInt32)( nSize - 8 );
4850 	mpOutStrm->Seek( nOldPos );
4851 }
4852 
4853 // ---------------------------------------------------------------------------------------------
4854 
4855 void EscherEx::AddAtom( sal_uInt32 nAtomSize, sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
4856 {
4857 	*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << nAtomSize;
4858 }
4859 
4860 // ---------------------------------------------------------------------------------------------
4861 
4862 void EscherEx::AddChildAnchor( const Rectangle& rRect )
4863 {
4864     AddAtom( 16, ESCHER_ChildAnchor );
4865     *mpOutStrm  << (sal_Int32)rRect.Left()
4866                 << (sal_Int32)rRect.Top()
4867                 << (sal_Int32)rRect.Right()
4868                 << (sal_Int32)rRect.Bottom();
4869 }
4870 
4871 // ---------------------------------------------------------------------------------------------
4872 
4873 void EscherEx::AddClientAnchor( const Rectangle& rRect )
4874 {
4875 	AddAtom( 8, ESCHER_ClientAnchor );
4876     *mpOutStrm << (sal_Int16)rRect.Top()
4877                << (sal_Int16)rRect.Left()
4878                << (sal_Int16)( rRect.GetWidth()  + rRect.Left() )
4879                << (sal_Int16)( rRect.GetHeight() + rRect.Top() );
4880 }
4881 
4882 // ---------------------------------------------------------------------------------------------
4883 
4884 EscherExHostAppData* EscherEx::EnterAdditionalTextGroup()
4885 {
4886 	return NULL;
4887 }
4888 
4889 // ---------------------------------------------------------------------------------------------
4890 
4891 sal_uInt32 EscherEx::EnterGroup( const String& rShapeName, const Rectangle* pBoundRect )
4892 {
4893 	Rectangle aRect;
4894 	if( pBoundRect )
4895 		aRect = *pBoundRect;
4896 
4897 	OpenContainer( ESCHER_SpgrContainer );
4898 	OpenContainer( ESCHER_SpContainer );
4899 	AddAtom( 16, ESCHER_Spgr, 1 );
4900 	PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel,
4901 						mpOutStrm->Tell() );
4902 	*mpOutStrm	<< (sal_Int32)aRect.Left()	// Bounding box fuer die Gruppierten shapes an die sie attached werden
4903 				<< (sal_Int32)aRect.Top()
4904 				<< (sal_Int32)aRect.Right()
4905 				<< (sal_Int32)aRect.Bottom();
4906 
4907     sal_uInt32 nShapeId = GenerateShapeId();
4908 	if ( !mnGroupLevel )
4909         AddShape( ESCHER_ShpInst_Min, 5, nShapeId );                    // Flags: Group | Patriarch
4910 	else
4911 	{
4912         AddShape( ESCHER_ShpInst_Min, 0x201, nShapeId );                // Flags: Group | HaveAnchor
4913 		EscherPropertyContainer aPropOpt;
4914 		aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x00040004 );
4915         aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
4916         aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
4917 
4918         // #i51348# shape name
4919         if( rShapeName.Len() > 0 )
4920             aPropOpt.AddOpt( ESCHER_Prop_wzName, rShapeName );
4921 
4922 		Commit( aPropOpt, aRect );
4923 		if ( mnGroupLevel > 1 )
4924             AddChildAnchor( aRect );
4925 
4926 		EscherExHostAppData* pAppData = mpImplEscherExSdr->ImplGetHostData();
4927 		if( pAppData )
4928 		{
4929 			if ( mnGroupLevel <= 1 )
4930 				pAppData->WriteClientAnchor( *this, aRect );
4931 			pAppData->WriteClientData( *this );
4932 		}
4933 	}
4934 	CloseContainer();												// ESCHER_SpContainer
4935 	mnGroupLevel++;
4936     return nShapeId;
4937 }
4938 
4939 sal_uInt32 EscherEx::EnterGroup( const Rectangle* pBoundRect )
4940 {
4941     return EnterGroup( String::EmptyString(), pBoundRect );
4942 }
4943 
4944 // ---------------------------------------------------------------------------------------------
4945 
4946 sal_Bool EscherEx::SetGroupSnapRect( sal_uInt32 nGroupLevel, const Rectangle& rRect )
4947 {
4948 	sal_Bool bRetValue = sal_False;
4949 	if ( nGroupLevel )
4950 	{
4951 		sal_uInt32 nCurrentPos = mpOutStrm->Tell();
4952 		if ( DoSeek( ESCHER_Persist_Grouping_Snap | ( nGroupLevel - 1 ) ) )
4953 		{
4954 			*mpOutStrm	<< (sal_Int32)rRect.Left()	// Bounding box fuer die Gruppierten shapes an die sie attached werden
4955 						<< (sal_Int32)rRect.Top()
4956 						<< (sal_Int32)rRect.Right()
4957 						<< (sal_Int32)rRect.Bottom();
4958 			mpOutStrm->Seek( nCurrentPos );
4959 		}
4960 	}
4961 	return bRetValue;
4962 }
4963 
4964 // ---------------------------------------------------------------------------------------------
4965 
4966 sal_Bool EscherEx::SetGroupLogicRect( sal_uInt32 nGroupLevel, const Rectangle& rRect )
4967 {
4968 	sal_Bool bRetValue = sal_False;
4969 	if ( nGroupLevel )
4970 	{
4971 		sal_uInt32 nCurrentPos = mpOutStrm->Tell();
4972 		if ( DoSeek( ESCHER_Persist_Grouping_Logic | ( nGroupLevel - 1 ) ) )
4973 		{
4974 			*mpOutStrm << (sal_Int16)rRect.Top() << (sal_Int16)rRect.Left() << (sal_Int16)rRect.Right() << (sal_Int16)rRect.Bottom();
4975 			mpOutStrm->Seek( nCurrentPos );
4976 		}
4977 	}
4978 	return bRetValue;
4979 }
4980 
4981 // ---------------------------------------------------------------------------------------------
4982 
4983 void EscherEx::LeaveGroup()
4984 {
4985 	--mnGroupLevel;
4986 	PtDelete( ESCHER_Persist_Grouping_Snap | mnGroupLevel );
4987 	PtDelete( ESCHER_Persist_Grouping_Logic | mnGroupLevel );
4988 	CloseContainer();
4989 }
4990 
4991 // ---------------------------------------------------------------------------------------------
4992 
4993 void EscherEx::AddShape( sal_uInt32 nShpInstance, sal_uInt32 nFlags, sal_uInt32 nShapeID )
4994 {
4995 	AddAtom( 8, ESCHER_Sp, 2, nShpInstance );
4996 
4997 	if ( !nShapeID )
4998         nShapeID = GenerateShapeId();
4999 
5000 	if ( nFlags ^ 1 )							// is this a group shape ?
5001 	{											// if not
5002 		if ( mnGroupLevel > 1 )
5003 			nFlags |= 2;						// this not a topmost shape
5004 	}
5005 	*mpOutStrm << nShapeID << nFlags;
5006 }
5007 
5008 // ---------------------------------------------------------------------------------------------
5009 
5010 void EscherEx::Commit( EscherPropertyContainer& rProps, const Rectangle& )
5011 {
5012 	rProps.Commit( GetStream() );
5013 }
5014 
5015 // ---------------------------------------------------------------------------------------------
5016 
5017 sal_uInt32 EscherEx::GetColor( const sal_uInt32 nSOColor, sal_Bool bSwap )
5018 {
5019 	if ( bSwap )
5020 	{
5021 		sal_uInt32 nColor = nSOColor & 0xff00;		// GRUEN
5022 		nColor |= (sal_uInt8)( nSOColor ) << 16;		// ROT
5023 		nColor |= (sal_uInt8)( nSOColor >> 16 );		// BLAU
5024 		return nColor;
5025 	}
5026 	else
5027 		return nSOColor & 0xffffff;
5028 }
5029 
5030 // ---------------------------------------------------------------------------------------------
5031 
5032 sal_uInt32 EscherEx::GetColor( const Color& rSOColor, sal_Bool bSwap )
5033 {
5034 	sal_uInt32 nColor = ( rSOColor.GetRed() << 16 );
5035 	nColor |= ( rSOColor.GetGreen() << 8 );
5036 	nColor |= rSOColor.GetBlue();
5037 
5038 	if ( !bSwap )
5039 		nColor = GetColor( nColor, sal_True );
5040 
5041 	return nColor;
5042 }
5043 
5044 // ---------------------------------------------------------------------------------------------
5045 
5046