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