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