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