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