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