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