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