xref: /trunk/main/filter/source/msfilter/escherex.cxx (revision b63233d8)
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/helper/vclunohelper.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 && (nEquationSourceCount <= 128) )
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                         const sal_Int32 nIndex(aIter->nPara[ i ] & 0x3ff);
2608 
2609                         // #124661# check index access, there are cases where this is out of bound leading
2610                         // to errors up to crashes when executed
2611                         if(nIndex < rEquationOrder.size())
2612                         {
2613                             aIter->nPara[ i ] = rEquationOrder[ nIndex ] | 0x400;
2614                         }
2615                         else
2616                         {
2617                             OSL_ENSURE(false, "Attempted out of bound access to rEquationOrder of CustomShape (!)");
2618                         }
2619 					}
2620 					nMask <<= 1;
2621 				}
2622 				aIter++;
2623 			}
2624 		}
2625 	}
2626 }
2627 
IsDefaultObject(SdrObjCustomShape * pCustoShape,const MSO_SPT eShapeType)2628 sal_Bool EscherPropertyContainer::IsDefaultObject( SdrObjCustomShape* pCustoShape , const MSO_SPT eShapeType )
2629 {
2630     sal_Bool bIsDefaultObject = sal_False;
2631 	switch(eShapeType)
2632 	{
2633 		//if the custom shape is not default shape of ppt, return sal_Fasle;
2634 		case mso_sptTearDrop:
2635 			return bIsDefaultObject;
2636 
2637 		default:
2638 			break;
2639 	}
2640 
2641     if ( pCustoShape )
2642     {
2643 	if (   pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_EQUATIONS )
2644 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_VIEWBOX )
2645 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_PATH )
2646 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_GLUEPOINTS )
2647 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_SEGMENTS )
2648 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHX )
2649 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHY )
2650 //					&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_HANDLES )
2651 	       && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_TEXTFRAMES ) )
2652 	    bIsDefaultObject = sal_True;
2653     }
2654 
2655     return bIsDefaultObject;
2656 }
2657 
LookForPolarHandles(const MSO_SPT eShapeType,sal_Int32 & nAdjustmentsWhichNeedsToBeConverted)2658 void EscherPropertyContainer::LookForPolarHandles( const MSO_SPT eShapeType, sal_Int32& nAdjustmentsWhichNeedsToBeConverted )
2659 {
2660     const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eShapeType );
2661     if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
2662     {
2663 	sal_Int32 k, nkCount = pDefCustomShape->nHandles;
2664 	const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
2665 	for ( k = 0; k < nkCount; k++, pData++ )
2666 	{
2667 	    if ( pData->nFlags & MSDFF_HANDLE_FLAGS_POLAR )
2668 	    {
2669 		if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
2670 		    nAdjustmentsWhichNeedsToBeConverted |= ( 1 << k );
2671 	    }
2672 	}
2673     }
2674 }
2675 
GetAdjustmentValue(const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue & rkProp,sal_Int32 nIndex,sal_Int32 nAdjustmentsWhichNeedsToBeConverted,sal_Int32 & nValue)2676 sal_Bool EscherPropertyContainer::GetAdjustmentValue( const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue & rkProp, sal_Int32 nIndex, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, sal_Int32& nValue )
2677 {
2678     if ( rkProp.State != beans::PropertyState_DIRECT_VALUE )
2679 	return sal_False;
2680 
2681     sal_Bool bUseFixedFloat = ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << nIndex ) ) != 0;
2682     if ( rkProp.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
2683     {
2684 	double fValue(0.0);
2685 	rkProp.Value >>= fValue;
2686 	if ( bUseFixedFloat )
2687 	    fValue *= 65536.0;
2688 	nValue = (sal_Int32)fValue;
2689     }
2690     else
2691     {
2692 	rkProp.Value >>= nValue;
2693 	if ( bUseFixedFloat )
2694 	    nValue <<= 16;
2695     }
2696 
2697     return sal_True;
2698 }
2699 
CreateCustomShapeProperties(const MSO_SPT eShapeType,const uno::Reference<drawing::XShape> & rXShape)2700 void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeType, const uno::Reference< drawing::XShape > & rXShape )
2701 {
2702 	uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
2703     if ( aXPropSet.is() )
2704     {
2705 		SdrObjCustomShape* pCustoShape = (SdrObjCustomShape*)GetSdrObjectFromXShape( rXShape );
2706 		if ( !pCustoShape ) return;
2707 		const rtl::OUString	sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) );
2708 		uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
2709 		uno::Sequence< beans::PropertyValue > aGeoPropSeq;
2710 		if ( aGeoPropSet >>= aGeoPropSeq )
2711 		{
2712 			const rtl::OUString	sViewBox			( RTL_CONSTASCII_USTRINGPARAM( "ViewBox" ) );
2713 			const rtl::OUString	sTextRotateAngle	( RTL_CONSTASCII_USTRINGPARAM( "TextRotateAngle" ) );
2714 			const rtl::OUString	sExtrusion			( RTL_CONSTASCII_USTRINGPARAM( "Extrusion" ) );
2715 			const rtl::OUString	sEquations			( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
2716 			const rtl::OUString	sPath				( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
2717 			const rtl::OUString	sTextPath			( RTL_CONSTASCII_USTRINGPARAM( "TextPath" ) );
2718 			const rtl::OUString	sHandles			( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
2719 			const rtl::OUString sAdjustmentValues	( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) );
2720 
2721             bool bHasAdjustmentValuesProp = false;
2722             uno::Any aAdjustmentValuesProp;
2723             bool bHasPathCoordinatesProp = false;
2724             uno::Any aPathCoordinatesProp;
2725 			sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0;
2726 			uno::Sequence< beans::PropertyValues > aHandlesPropSeq;
2727 			sal_Bool bPredefinedHandlesUsed = sal_True;
2728 			sal_Bool bIsDefaultObject = IsDefaultObject( pCustoShape , eShapeType);
2729 
2730 			// convert property "Equations" into std::vector< EnhancedCustomShapeEquationEquation >
2731 			std::vector< EnhancedCustomShapeEquation >	aEquations;
2732 			std::vector< sal_Int32 >					aEquationOrder;
2733 			ConvertEnhancedCustomShapeEquation( pCustoShape, aEquations, aEquationOrder );
2734 
2735 			sal_Int32 i, nCount = aGeoPropSeq.getLength();
2736 			for ( i = 0; i < nCount; i++ )
2737 			{
2738 				const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
2739 				if ( rProp.Name.equals( sViewBox ) )
2740 				{
2741 					if ( !bIsDefaultObject )
2742 					{
2743 						awt::Rectangle aViewBox;
2744 						if ( rProp.Value >>= aViewBox )
2745 						{
2746 							AddOpt( DFF_Prop_geoLeft,  aViewBox.X );
2747 							AddOpt( DFF_Prop_geoTop,   aViewBox.Y );
2748 							AddOpt( DFF_Prop_geoRight, aViewBox.X + aViewBox.Width );
2749 							AddOpt( DFF_Prop_geoBottom,aViewBox.Y + aViewBox.Height );
2750 						}
2751 					}
2752 				}
2753 				else if ( rProp.Name.equals( sTextRotateAngle ) )
2754 				{
2755 					double f = 0, fTextRotateAngle;
2756 					if ( rProp.Value >>= f )
2757 					{
2758 						fTextRotateAngle = fmod( f, 360.0 );
2759 						if ( fTextRotateAngle < 0 )
2760 							fTextRotateAngle = 360 + fTextRotateAngle;
2761 						if ( ( fTextRotateAngle < 271.0 ) && ( fTextRotateAngle > 269.0 ) )
2762 					        AddOpt( DFF_Prop_cdirFont, mso_cdir90 );
2763 						else if ( ( fTextRotateAngle < 181.0 ) && ( fTextRotateAngle > 179.0 ) )
2764 							AddOpt( DFF_Prop_cdirFont, mso_cdir180 );
2765 						else if ( ( fTextRotateAngle < 91.0 ) && ( fTextRotateAngle > 79.0 ) )
2766 							AddOpt( DFF_Prop_cdirFont, mso_cdir270 );
2767 					}
2768 				}
2769 				else if ( rProp.Name.equals( sExtrusion ) )
2770 				{
2771 					uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
2772 					if ( rProp.Value >>= aExtrusionPropSeq )
2773 					{
2774 						sal_uInt32 nLightFaceFlagsOrg, nLightFaceFlags;
2775 						sal_uInt32 nFillHarshFlagsOrg, nFillHarshFlags;
2776 						nLightFaceFlagsOrg = nLightFaceFlags = 0x000001;
2777 						nFillHarshFlagsOrg = nFillHarshFlags = 0x00001e;
2778 						if ( GetOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ) )
2779 							nLightFaceFlagsOrg = nLightFaceFlags;
2780 						if ( GetOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ) )
2781 							nFillHarshFlagsOrg = nFillHarshFlags;
2782 
2783 						sal_Int32 r, nrCount = aExtrusionPropSeq.getLength();
2784 						for ( r = 0; r < nrCount; r++ )
2785 						{
2786 							const beans::PropertyValue& rrProp = aExtrusionPropSeq[ r ];
2787 							const rtl::OUString	sExtrusionBrightness			( RTL_CONSTASCII_USTRINGPARAM( "Brightness" ) );
2788 							const rtl::OUString	sExtrusionDepth					( RTL_CONSTASCII_USTRINGPARAM( "Depth" ) );
2789 							const rtl::OUString	sExtrusionDiffusion				( RTL_CONSTASCII_USTRINGPARAM( "Diffusion" ) );
2790 							const rtl::OUString	sExtrusionNumberOfLineSegments	( RTL_CONSTASCII_USTRINGPARAM( "NumberOfLineSegments" ) );
2791 							const rtl::OUString	sExtrusionLightFace				( RTL_CONSTASCII_USTRINGPARAM( "LightFace" ) );
2792 							const rtl::OUString	sExtrusionFirstLightHarsh		( RTL_CONSTASCII_USTRINGPARAM( "FirstLightHarsh" ) );
2793 							const rtl::OUString	sExtrusionSecondLightHarsh		( RTL_CONSTASCII_USTRINGPARAM( "SecondLightHarsh" ) );
2794 							const rtl::OUString	sExtrusionFirstLightLevel		( RTL_CONSTASCII_USTRINGPARAM( "FirstLightLevel" ) );
2795 							const rtl::OUString	sExtrusionSecondLightLevel		( RTL_CONSTASCII_USTRINGPARAM( "SecondLightLevel" ) );
2796 							const rtl::OUString	sExtrusionFirstLightDirection	( RTL_CONSTASCII_USTRINGPARAM( "FirstLightDirection" ) );
2797 							const rtl::OUString	sExtrusionSecondLightDirection	( RTL_CONSTASCII_USTRINGPARAM( "SecondLightDirection" ) );
2798 							const rtl::OUString	sExtrusionMetal					( RTL_CONSTASCII_USTRINGPARAM( "Metal" ) );
2799 							const rtl::OUString	sExtrusionShadeMode				( RTL_CONSTASCII_USTRINGPARAM( "ShadeMode" ) );
2800 							const rtl::OUString	sExtrusionRotateAngle			( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) );
2801 							const rtl::OUString	sExtrusionRotationCenter		( RTL_CONSTASCII_USTRINGPARAM( "RotationCenter" ) );
2802 							const rtl::OUString	sExtrusionShininess				( RTL_CONSTASCII_USTRINGPARAM( "Shininess" ) );
2803 							const rtl::OUString	sExtrusionSkew					( RTL_CONSTASCII_USTRINGPARAM( "Skew" ) );
2804 							const rtl::OUString	sExtrusionSpecularity			( RTL_CONSTASCII_USTRINGPARAM( "Specularity" ) );
2805 							const rtl::OUString	sExtrusionProjectionMode		( RTL_CONSTASCII_USTRINGPARAM( "ProjectionMode" ) );
2806 							const rtl::OUString	sExtrusionViewPoint				( RTL_CONSTASCII_USTRINGPARAM( "ViewPoint" ) );
2807 							const rtl::OUString	sExtrusionOrigin				( RTL_CONSTASCII_USTRINGPARAM( "Origin" ) );
2808 							const rtl::OUString	sExtrusionColor					( RTL_CONSTASCII_USTRINGPARAM( "Color" ) );
2809 
2810 							if ( rrProp.Name.equals( sExtrusion ) )
2811 							{
2812 								sal_Bool bExtrusionOn = sal_Bool();
2813 								if ( rrProp.Value >>= bExtrusionOn )
2814 								{
2815 									nLightFaceFlags |= 0x80000;
2816 									if ( bExtrusionOn )
2817 										nLightFaceFlags |= 8;
2818 									else
2819 										nLightFaceFlags &=~8;
2820 								}
2821 							}
2822 							else if ( rrProp.Name.equals( sExtrusionBrightness ) )
2823 							{
2824 								double fExtrusionBrightness = 0;
2825 								if ( rrProp.Value >>= fExtrusionBrightness )
2826 									AddOpt( DFF_Prop_c3DAmbientIntensity, (sal_Int32)( fExtrusionBrightness * 655.36 ) );
2827 							}
2828 							else if ( rrProp.Name.equals( sExtrusionDepth ) )
2829 							{
2830 								double fDepth = 0;
2831 								double fFraction = 0;
2832 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
2833 								if ( ( rrProp.Value >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) )
2834 								{
2835 									double fForeDepth = fDepth * fFraction;
2836 									double fBackDepth = fDepth - fForeDepth;
2837 
2838 									fBackDepth *= 360.0;
2839 									AddOpt( DFF_Prop_c3DExtrudeBackward, (sal_Int32)fBackDepth );
2840 
2841 									if ( fForeDepth != 0.0 )
2842 									{
2843 										fForeDepth *= 360.0;
2844 										AddOpt( DFF_Prop_c3DExtrudeForward, (sal_Int32)fForeDepth );
2845 									}
2846 								}
2847 							}
2848 							else if ( rrProp.Name.equals( sExtrusionDiffusion ) )
2849 							{
2850 								double fExtrusionDiffusion = 0;
2851 								if ( rrProp.Value >>= fExtrusionDiffusion )
2852 									AddOpt( DFF_Prop_c3DDiffuseAmt, (sal_Int32)( fExtrusionDiffusion * 655.36 ) );
2853 							}
2854 							else if ( rrProp.Name.equals( sExtrusionNumberOfLineSegments ) )
2855 							{
2856 								sal_Int32 nExtrusionNumberOfLineSegments = 0;
2857 								if ( rrProp.Value >>= nExtrusionNumberOfLineSegments )
2858 									AddOpt( DFF_Prop_c3DTolerance, nExtrusionNumberOfLineSegments );
2859 							}
2860 							else if ( rrProp.Name.equals( sExtrusionLightFace ) )
2861 							{
2862 								sal_Bool bExtrusionLightFace = sal_Bool();
2863 								if ( rrProp.Value >>= bExtrusionLightFace )
2864 								{
2865 									nLightFaceFlags |= 0x10000;
2866 									if ( bExtrusionLightFace )
2867 										nLightFaceFlags |= 1;
2868 									else
2869 										nLightFaceFlags &=~1;
2870 								}
2871 							}
2872 							else if ( rrProp.Name.equals( sExtrusionFirstLightHarsh ) )
2873 							{
2874 								sal_Bool bExtrusionFirstLightHarsh = sal_Bool();
2875 								if ( rrProp.Value >>= bExtrusionFirstLightHarsh )
2876 								{
2877 									nFillHarshFlags |= 0x20000;
2878 									if ( bExtrusionFirstLightHarsh )
2879 										nFillHarshFlags |= 2;
2880 									else
2881 										nFillHarshFlags &=~2;
2882 								}
2883 							}
2884 							else if ( rrProp.Name.equals( sExtrusionSecondLightHarsh ) )
2885 							{
2886 								sal_Bool bExtrusionSecondLightHarsh = sal_Bool();
2887 								if ( rrProp.Value >>= bExtrusionSecondLightHarsh )
2888 								{
2889 									nFillHarshFlags |= 0x10000;
2890 									if ( bExtrusionSecondLightHarsh )
2891 										nFillHarshFlags |= 1;
2892 									else
2893 										nFillHarshFlags &=~1;
2894 								}
2895 							}
2896 							else if ( rrProp.Name.equals( sExtrusionFirstLightLevel ) )
2897 							{
2898 								double fExtrusionFirstLightLevel = 0;
2899 								if ( rrProp.Value >>= fExtrusionFirstLightLevel )
2900 									AddOpt( DFF_Prop_c3DKeyIntensity, (sal_Int32)( fExtrusionFirstLightLevel * 655.36 ) );
2901 							}
2902 							else if ( rrProp.Name.equals( sExtrusionSecondLightLevel ) )
2903 							{
2904 								double fExtrusionSecondLightLevel = 0;
2905 								if ( rrProp.Value >>= fExtrusionSecondLightLevel )
2906 									AddOpt( DFF_Prop_c3DFillIntensity, (sal_Int32)( fExtrusionSecondLightLevel * 655.36 ) );
2907 							}
2908 							else if ( rrProp.Name.equals( sExtrusionFirstLightDirection ) )
2909 							{
2910 								drawing::Direction3D aExtrusionFirstLightDirection;
2911 								if ( rrProp.Value >>= aExtrusionFirstLightDirection )
2912 								{
2913 									AddOpt( DFF_Prop_c3DKeyX, (sal_Int32)aExtrusionFirstLightDirection.DirectionX  );
2914 									AddOpt( DFF_Prop_c3DKeyY, (sal_Int32)aExtrusionFirstLightDirection.DirectionY  );
2915 									AddOpt( DFF_Prop_c3DKeyZ, (sal_Int32)aExtrusionFirstLightDirection.DirectionZ  );
2916 								}
2917 							}
2918 							else if ( rrProp.Name.equals( sExtrusionSecondLightDirection ) )
2919 							{
2920 								drawing::Direction3D aExtrusionSecondLightPosition;
2921 								if ( rrProp.Value >>= aExtrusionSecondLightPosition )
2922 								{
2923 									AddOpt( DFF_Prop_c3DFillX, (sal_Int32)aExtrusionSecondLightPosition.DirectionX  );
2924 									AddOpt( DFF_Prop_c3DFillY, (sal_Int32)aExtrusionSecondLightPosition.DirectionY  );
2925 									AddOpt( DFF_Prop_c3DFillZ, (sal_Int32)aExtrusionSecondLightPosition.DirectionZ  );
2926 								}
2927 							}
2928 							else if ( rrProp.Name.equals( sExtrusionMetal ) )
2929 							{
2930 								sal_Bool bExtrusionMetal = sal_Bool();
2931 								if ( rrProp.Value >>= bExtrusionMetal )
2932 								{
2933 									nLightFaceFlags |= 0x40000;
2934 									if ( bExtrusionMetal )
2935 										nLightFaceFlags |= 4;
2936 									else
2937 										nLightFaceFlags &=~4;
2938 								}
2939 							}
2940 							else if ( rrProp.Name.equals( sExtrusionShadeMode ) )
2941 							{
2942 								drawing::ShadeMode eExtrusionShadeMode;
2943 								if ( rrProp.Value >>= eExtrusionShadeMode )
2944 								{
2945 									sal_uInt32 nRenderMode;
2946 									switch( eExtrusionShadeMode )
2947 									{
2948 										default:
2949 										case drawing::ShadeMode_FLAT :
2950 										case drawing::ShadeMode_PHONG :
2951 										case drawing::ShadeMode_SMOOTH :
2952 											nRenderMode = mso_FullRender;
2953 										break;
2954 										case drawing::ShadeMode_DRAFT :
2955 										{
2956 											nRenderMode = mso_Wireframe;
2957 										}
2958 										break;
2959 									}
2960 									AddOpt( DFF_Prop_c3DRenderMode, nRenderMode );
2961 								}
2962 							}
2963 							else if ( rrProp.Name.equals( sExtrusionRotateAngle ) )
2964 							{
2965 								double fExtrusionAngleX = 0;
2966 								double fExtrusionAngleY = 0;
2967 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAnglePair;
2968 								if ( ( rrProp.Value >>= aRotateAnglePair ) && ( aRotateAnglePair.First.Value >>= fExtrusionAngleX ) && ( aRotateAnglePair.Second.Value >>= fExtrusionAngleY ) )
2969 								{
2970 									fExtrusionAngleX *= 65536;
2971 									fExtrusionAngleY *= 65536;
2972 									AddOpt( DFF_Prop_c3DXRotationAngle, (sal_Int32)fExtrusionAngleX );
2973 									AddOpt( DFF_Prop_c3DYRotationAngle, (sal_Int32)fExtrusionAngleY );
2974 								}
2975 							}
2976 							else if ( rrProp.Name.equals( sExtrusionRotationCenter ) )
2977 							{
2978 								drawing::Direction3D aExtrusionRotationCenter;
2979 								if ( rrProp.Value >>= aExtrusionRotationCenter )
2980 								{
2981 									AddOpt( DFF_Prop_c3DRotationCenterX, (sal_Int32)( aExtrusionRotationCenter.DirectionX * 360.0 ) );
2982 									AddOpt( DFF_Prop_c3DRotationCenterY, (sal_Int32)( aExtrusionRotationCenter.DirectionY * 360.0 ) );
2983 									AddOpt( DFF_Prop_c3DRotationCenterZ, (sal_Int32)( aExtrusionRotationCenter.DirectionZ * 360.0 ) );
2984 									nFillHarshFlags &=~8; // don't use AutoRotationCenter;
2985 								}
2986 							}
2987 							else if ( rrProp.Name.equals( sExtrusionShininess ) )
2988 							{
2989 								double fExtrusionShininess = 0;
2990 								if ( rrProp.Value >>= fExtrusionShininess )
2991 									AddOpt( DFF_Prop_c3DShininess, (sal_Int32)( fExtrusionShininess * 655.36 ) );
2992 							}
2993 							else if ( rrProp.Name.equals( sExtrusionSkew ) )
2994 							{
2995 								double fSkewAmount = 0;
2996 								double fSkewAngle = 0;
2997 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
2998 								if ( ( rrProp.Value >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= fSkewAmount ) && ( aSkewParaPair.Second.Value >>= fSkewAngle ) )
2999 								{
3000 									AddOpt( DFF_Prop_c3DSkewAmount, (sal_Int32)fSkewAmount );
3001 									AddOpt( DFF_Prop_c3DSkewAngle, (sal_Int32)( fSkewAngle * 65536 ) );
3002 								}
3003 							}
3004 							else if ( rrProp.Name.equals( sExtrusionSpecularity ) )
3005 							{
3006 								double fExtrusionSpecularity = 0;
3007 								if ( rrProp.Value >>= fExtrusionSpecularity )
3008 									AddOpt( DFF_Prop_c3DSpecularAmt, (sal_Int32)( fExtrusionSpecularity * 1333 ) );
3009 							}
3010 							else if ( rrProp.Name.equals( sExtrusionProjectionMode ) )
3011 							{
3012 								drawing::ProjectionMode eExtrusionProjectionMode;
3013 								if ( rrProp.Value >>= eExtrusionProjectionMode )
3014 								{
3015 									nFillHarshFlags |= 0x40000;
3016 									if ( eExtrusionProjectionMode == drawing::ProjectionMode_PARALLEL )
3017 										nFillHarshFlags |= 4;
3018 									else
3019 										nFillHarshFlags &=~4;
3020 								}
3021 							}
3022 							else if ( rrProp.Name.equals( sExtrusionViewPoint ) )
3023 							{
3024 								drawing::Position3D aExtrusionViewPoint;
3025 								if ( rrProp.Value >>= aExtrusionViewPoint )
3026 								{
3027 									aExtrusionViewPoint.PositionX *= 360.0;
3028 									aExtrusionViewPoint.PositionY *= 360.0;
3029 									aExtrusionViewPoint.PositionZ *= 360.0;
3030 									AddOpt( DFF_Prop_c3DXViewpoint, (sal_Int32)aExtrusionViewPoint.PositionX  );
3031 									AddOpt( DFF_Prop_c3DYViewpoint, (sal_Int32)aExtrusionViewPoint.PositionY  );
3032 									AddOpt( DFF_Prop_c3DZViewpoint, (sal_Int32)aExtrusionViewPoint.PositionZ  );
3033 								}
3034 							}
3035 							else if ( rrProp.Name.equals( sExtrusionOrigin ) )
3036 							{
3037 								double fExtrusionOriginX = 0;
3038 								double fExtrusionOriginY = 0;
3039 								com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginPair;
3040 								if ( ( rrProp.Value >>= aOriginPair ) && ( aOriginPair.First.Value >>= fExtrusionOriginX ) && ( aOriginPair.Second.Value >>= fExtrusionOriginY ) )
3041 								{
3042 									AddOpt( DFF_Prop_c3DOriginX, (sal_Int32)( fExtrusionOriginX * 65536 ) );
3043 									AddOpt( DFF_Prop_c3DOriginY, (sal_Int32)( fExtrusionOriginY * 65536 ) );
3044 								}
3045 							}
3046 							else if ( rrProp.Name.equals( sExtrusionColor ) )
3047 							{
3048 								sal_Bool bExtrusionColor = sal_Bool();
3049 								if ( rrProp.Value >>= bExtrusionColor )
3050 								{
3051 									nLightFaceFlags |= 0x20000;
3052 									if ( bExtrusionColor )
3053 									{
3054 										nLightFaceFlags |= 2;
3055 										uno::Any aFillColor2;
3056 										if ( EscherPropertyValueHelper::GetPropertyValue( aFillColor2, aXPropSet,
3057 											String( RTL_CONSTASCII_USTRINGPARAM( "FillColor2" ) ), sal_True ) )
3058 										{
3059 											sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aFillColor2.getValue()) );
3060 											AddOpt( DFF_Prop_c3DExtrusionColor, nFillColor );
3061 										}
3062 									}
3063 									else
3064 										nLightFaceFlags &=~2;
3065 								}
3066 							}
3067 						}
3068 						if ( nLightFaceFlags != nLightFaceFlagsOrg )
3069 							AddOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags );
3070 						if ( nFillHarshFlags != nFillHarshFlagsOrg )
3071 							AddOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags );
3072 					}
3073 				}
3074 				else if ( rProp.Name.equals( sEquations ) )
3075 				{
3076 					if ( !bIsDefaultObject )
3077 					{
3078 						sal_uInt16 nElements = (sal_uInt16)aEquations.size();
3079 						if ( nElements )
3080 						{
3081 							sal_uInt16 nElementSize = 8;
3082 							sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3083 							SvMemoryStream aOut( nStreamSize );
3084 							aOut << nElements
3085 								<< nElements
3086 								<< nElementSize;
3087 
3088 							std::vector< EnhancedCustomShapeEquation >::const_iterator aIter( aEquations.begin() );
3089 							std::vector< EnhancedCustomShapeEquation >::const_iterator aEnd ( aEquations.end() );
3090 							while( aIter != aEnd )
3091 							{
3092 								aOut << (sal_uInt16)aIter->nOperation
3093 									 << (sal_Int16)aIter->nPara[ 0 ]
3094 									 << (sal_Int16)aIter->nPara[ 1 ]
3095 									 << (sal_Int16)aIter->nPara[ 2 ];
3096 								aIter++;
3097 							}
3098 							sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3099 							memcpy( pBuf, aOut.GetData(), nStreamSize );
3100 							AddOpt( DFF_Prop_pFormulas, sal_True, nStreamSize - 6, pBuf, nStreamSize );
3101 						}
3102 						else
3103 						{
3104 							sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3105 							AddOpt( DFF_Prop_pFormulas, sal_True, 0, pBuf, 0 );
3106 						}
3107 					}
3108 				}
3109 				else if ( rProp.Name.equals( sPath ) )
3110 				{
3111 					uno::Sequence< beans::PropertyValue > aPathPropSeq;
3112 					if ( rProp.Value >>= aPathPropSeq )
3113 					{
3114 						sal_uInt32 nPathFlags, nPathFlagsOrg;
3115 						nPathFlagsOrg = nPathFlags = 0x39;
3116 						if ( GetOpt( DFF_Prop_fFillOK, nPathFlags ) )
3117 							nPathFlagsOrg = nPathFlags;
3118 
3119 						sal_Int32 r, nrCount = aPathPropSeq.getLength();
3120 						for ( r = 0; r < nrCount; r++ )
3121 						{
3122 							const beans::PropertyValue& rrProp = aPathPropSeq[ r ];
3123 							const rtl::OUString	sPathExtrusionAllowed				( RTL_CONSTASCII_USTRINGPARAM( "ExtrusionAllowed" ) );
3124 							const rtl::OUString	sPathConcentricGradientFillAllowed	( RTL_CONSTASCII_USTRINGPARAM( "ConcentricGradientFillAllowed" ) );
3125 							const rtl::OUString	sPathTextPathAllowed				( RTL_CONSTASCII_USTRINGPARAM( "TextPathAllowed" ) );
3126 							const rtl::OUString	sPathCoordinates					( RTL_CONSTASCII_USTRINGPARAM( "Coordinates" ) );
3127 							const rtl::OUString sPathGluePoints						( RTL_CONSTASCII_USTRINGPARAM( "GluePoints" ) );
3128 							const rtl::OUString sPathGluePointType					( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
3129 							const rtl::OUString	sPathSegments						( RTL_CONSTASCII_USTRINGPARAM( "Segments" ) );
3130 							const rtl::OUString	sPathStretchX						( RTL_CONSTASCII_USTRINGPARAM( "StretchX" ) );
3131 							const rtl::OUString	sPathStretchY						( RTL_CONSTASCII_USTRINGPARAM( "StretchY" ) );
3132 							const rtl::OUString	sPathTextFrames						( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) );
3133 
3134 							if ( rrProp.Name.equals( sPathExtrusionAllowed ) )
3135 							{
3136 								sal_Bool bExtrusionAllowed = sal_Bool();
3137 								if ( rrProp.Value >>= bExtrusionAllowed )
3138 								{
3139 									nPathFlags |= 0x100000;
3140 									if ( bExtrusionAllowed )
3141 										nPathFlags |= 16;
3142 									else
3143 										nPathFlags &=~16;
3144 								}
3145 							}
3146 							else if ( rrProp.Name.equals( sPathConcentricGradientFillAllowed ) )
3147 							{
3148 								sal_Bool bConcentricGradientFillAllowed = sal_Bool();
3149 								if ( rrProp.Value >>= bConcentricGradientFillAllowed )
3150 								{
3151 									nPathFlags |= 0x20000;
3152 									if ( bConcentricGradientFillAllowed )
3153 										nPathFlags |= 2;
3154 									else
3155 										nPathFlags &=~2;
3156 								}
3157 							}
3158 							else if ( rrProp.Name.equals( sPathTextPathAllowed ) )
3159 							{
3160 								sal_Bool bTextPathAllowed = sal_Bool();
3161 								if ( rrProp.Value >>= bTextPathAllowed )
3162 								{
3163 									nPathFlags |= 0x40000;
3164 									if ( bTextPathAllowed )
3165 										nPathFlags |= 4;
3166 									else
3167 										nPathFlags &=~4;
3168 								}
3169 							}
3170 							else if ( rrProp.Name.equals( sPathCoordinates ) )
3171 							{
3172 								if ( !bIsDefaultObject )
3173                                 {
3174 									aPathCoordinatesProp = rrProp.Value;
3175                                     bHasPathCoordinatesProp = true;
3176                                 }
3177 							}
3178 							else if ( rrProp.Name.equals( sPathGluePoints ) )
3179 							{
3180 								if ( !bIsDefaultObject )
3181 								{
3182 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
3183 									if ( rrProp.Value >>= aGluePoints )
3184 									{
3185 										// creating the vertices
3186 										sal_uInt16 nElements = (sal_uInt16)aGluePoints.getLength();
3187 										if ( nElements )
3188 										{
3189 											sal_uInt16 j, nElementSize = 8;
3190 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3191 											SvMemoryStream aOut( nStreamSize );
3192 											aOut << nElements
3193 												<< nElements
3194 												<< nElementSize;
3195 											for( j = 0; j < nElements; j++ )
3196 											{
3197 												sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].First, aEquationOrder );
3198 												sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].Second, aEquationOrder );
3199 												aOut << X
3200 													<< Y;
3201 											}
3202 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3203 											memcpy( pBuf, aOut.GetData(), nStreamSize );
3204 											AddOpt( DFF_Prop_connectorPoints, sal_True, nStreamSize - 6, pBuf, nStreamSize );	// -6
3205 										}
3206 										else
3207 										{
3208 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3209 											AddOpt( DFF_Prop_connectorPoints, sal_True, 0, pBuf, 0 );
3210 										}
3211 									}
3212 								}
3213 							}
3214 							else if ( rrProp.Name.equals( sPathGluePointType ) )
3215 							{
3216 								sal_Int16 nGluePointType = sal_Int16();
3217 								if ( rrProp.Value >>= nGluePointType )
3218 									AddOpt( DFF_Prop_connectorType, (sal_uInt16)nGluePointType );
3219 							}
3220 							else if ( rrProp.Name.equals( sPathSegments ) )
3221 							{
3222 								if ( !bIsDefaultObject )
3223 								{
3224 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments;
3225 									if ( rrProp.Value >>= aSegments )
3226 									{
3227 										// creating seginfo
3228 										if ( (sal_uInt16)aSegments.getLength() )
3229 										{
3230 											sal_uInt16 j, nElements = (sal_uInt16)aSegments.getLength();
3231 											sal_uInt16 nElementSize = 2;
3232 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3233 											SvMemoryStream aOut( nStreamSize );
3234 											aOut << nElements
3235 												<< nElements
3236 												<< nElementSize;
3237 											for ( j = 0; j < nElements; j++ )
3238 											{
3239 												sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count;
3240 												switch( aSegments[ j ].Command )
3241 												{
3242 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
3243 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break;
3244 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
3245 													{
3246 														nVal = 0x4000;
3247 													}
3248 													break;
3249 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
3250 													{
3251 														nVal |= 0x2000;
3252 													}
3253 													break;
3254 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
3255 													{
3256 														nVal = 0x6001;
3257 													}
3258 													break;
3259 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
3260 													{
3261 														nVal = 0x8000;
3262 													}
3263 													break;
3264 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
3265 													{
3266 														nVal = 0xaa00;
3267 													}
3268 													break;
3269 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
3270 													{
3271 														nVal = 0xab00;
3272 													}
3273 													break;
3274 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
3275 													{
3276 														nVal *= 3;
3277 														nVal |= 0xa100;
3278 													}
3279 													break;
3280 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
3281 													{
3282 														nVal *= 3;
3283 														nVal |= 0xa200;
3284 													}
3285 													break;
3286 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
3287 													{
3288 														nVal <<= 2;
3289 														nVal |= 0xa300;
3290 													}
3291 													break;
3292 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC :
3293 													{
3294 														nVal <<= 2;
3295 														nVal |= 0xa400;
3296 													}
3297 													break;
3298 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
3299 													{
3300 														nVal <<= 2;
3301 														nVal |= 0xa500;
3302 													}
3303 													break;
3304 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
3305 													{
3306 														nVal <<= 2;
3307 														nVal |= 0xa600;
3308 													}
3309 													break;
3310 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
3311 													{
3312 														nVal |= 0xa700;
3313 													}
3314 													break;
3315 													case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
3316 													{
3317 														nVal |= 0xa800;
3318 													}
3319 													break;
3320 												}
3321 												aOut << nVal;
3322 											}
3323 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3324 											memcpy( pBuf, aOut.GetData(), nStreamSize );
3325 											AddOpt( DFF_Prop_pSegmentInfo, sal_False, nStreamSize - 6, pBuf, nStreamSize );
3326 										}
3327 										else
3328 										{
3329 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3330 											AddOpt( DFF_Prop_pSegmentInfo, sal_True, 0, pBuf, 0 );
3331 										}
3332 									}
3333 								}
3334 							}
3335 							else if ( rrProp.Name.equals( sPathStretchX ) )
3336 							{
3337 								if ( !bIsDefaultObject )
3338 								{
3339 									sal_Int32 nStretchX = 0;
3340 									if ( rrProp.Value >>= nStretchX )
3341 										AddOpt( DFF_Prop_stretchPointX, nStretchX );
3342 								}
3343 							}
3344 							else if ( rrProp.Name.equals( sPathStretchY ) )
3345 							{
3346 								if ( !bIsDefaultObject )
3347 								{
3348 									sal_Int32 nStretchY = 0;
3349 									if ( rrProp.Value >>= nStretchY )
3350 										AddOpt( DFF_Prop_stretchPointY, nStretchY );
3351 								}
3352 							}
3353 							else if ( rrProp.Name.equals( sPathTextFrames ) )
3354 							{
3355 								if ( !bIsDefaultObject )
3356 								{
3357 									com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
3358 									if ( rrProp.Value >>= aPathTextFrames )
3359 									{
3360 										if ( (sal_uInt16)aPathTextFrames.getLength() )
3361 										{
3362 											sal_uInt16 j, nElements = (sal_uInt16)aPathTextFrames.getLength();
3363 											sal_uInt16 nElementSize = 16;
3364 											sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3365 											SvMemoryStream aOut( nStreamSize );
3366 											aOut << nElements
3367 												<< nElements
3368 												<< nElementSize;
3369 											for ( j = 0; j < nElements; j++ )
3370 											{
3371 												sal_Int32 nLeft = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.First, aEquationOrder );
3372 												sal_Int32 nTop  = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.Second, aEquationOrder );
3373 												sal_Int32 nRight = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.First, aEquationOrder );
3374 												sal_Int32 nBottom = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.Second, aEquationOrder );
3375 
3376 												aOut << nLeft
3377 													<< nTop
3378 													<< nRight
3379 													<< nBottom;
3380 											}
3381 											sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3382 											memcpy( pBuf, aOut.GetData(), nStreamSize );
3383 											AddOpt( DFF_Prop_textRectangles, sal_True, nStreamSize - 6, pBuf, nStreamSize );
3384 										}
3385 										else
3386 										{
3387 											sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3388 											AddOpt( DFF_Prop_textRectangles, sal_True, 0, pBuf, 0 );
3389 										}
3390 									}
3391 								}
3392 							}
3393 						}
3394 						if ( nPathFlags != nPathFlagsOrg )
3395 							AddOpt( DFF_Prop_fFillOK, nPathFlags );
3396 					}
3397 				}
3398 				else if ( rProp.Name.equals( sTextPath ) )
3399 				{
3400 					uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
3401 					if ( rProp.Value >>= aTextPathPropSeq )
3402 					{
3403 						sal_uInt32 nTextPathFlagsOrg, nTextPathFlags;
3404 						nTextPathFlagsOrg = nTextPathFlags = 0xffff1000;		// default
3405 						if ( GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ) )
3406 							nTextPathFlagsOrg = nTextPathFlags;
3407 
3408 						sal_Int32 r, nrCount = aTextPathPropSeq.getLength();
3409 						for ( r = 0; r < nrCount; r++ )
3410 						{
3411 							const beans::PropertyValue& rrProp = aTextPathPropSeq[ r ];
3412 							const rtl::OUString	sTextPathMode		( RTL_CONSTASCII_USTRINGPARAM( "TextPathMode" ) );
3413 							const rtl::OUString	sTextPathScaleX		( RTL_CONSTASCII_USTRINGPARAM( "ScaleX" ) );
3414 							const rtl::OUString sSameLetterHeights	( RTL_CONSTASCII_USTRINGPARAM( "SameLetterHeights" ) );
3415 
3416 							if ( rrProp.Name.equals( sTextPath ) )
3417 							{
3418 								sal_Bool bTextPathOn = sal_Bool();
3419 								if ( rrProp.Value >>= bTextPathOn )
3420 								{
3421 									nTextPathFlags |= 0x40000000;
3422 									if ( bTextPathOn )
3423 									{
3424 										nTextPathFlags |= 0x4000;
3425 
3426 										sal_uInt32 nPathFlags = 0x39;
3427 										GetOpt( DFF_Prop_fFillOK, nPathFlags );	// SJ: can be removed if we are supporting the TextPathAllowed property in XML
3428 										nPathFlags |= 0x40004;
3429 										AddOpt( DFF_Prop_fFillOK, nPathFlags );
3430 									}
3431 									else
3432 										nTextPathFlags &=~0x4000;
3433 								}
3434 							}
3435 							else if ( rrProp.Name.equals( sTextPathMode ) )
3436 							{
3437 								com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
3438 								if ( rrProp.Value >>= eTextPathMode )
3439 								{
3440 									nTextPathFlags |= 0x05000000;
3441 									nTextPathFlags &=~0x500;	// TextPathMode_NORMAL
3442 									if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH )
3443 										nTextPathFlags |= 0x100;
3444 									else if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE )
3445 										nTextPathFlags |= 0x500;
3446 								}
3447 							}
3448 							else if ( rrProp.Name.equals( sTextPathScaleX ) )
3449 							{
3450 								sal_Bool bTextPathScaleX = sal_Bool();
3451 								if ( rrProp.Value >>= bTextPathScaleX )
3452 								{
3453 									nTextPathFlags |= 0x00400000;
3454 									if ( bTextPathScaleX )
3455 										nTextPathFlags |= 0x40;
3456 									else
3457 										nTextPathFlags &=~0x40;
3458 								}
3459 							}
3460 							else if ( rrProp.Name.equals( sSameLetterHeights ) )
3461 							{
3462 								sal_Bool bSameLetterHeights = sal_Bool();
3463 								if ( rrProp.Value >>= bSameLetterHeights )
3464 								{
3465 									nTextPathFlags |= 0x00800000;
3466 									if ( bSameLetterHeights )
3467 										nTextPathFlags |= 0x80;
3468 									else
3469 										nTextPathFlags &=~0x80;
3470 								}
3471 							}
3472 						}
3473 						if ( nTextPathFlags & 0x4000 )		// Is FontWork ?
3474 						{
3475 							// FontWork Text
3476 							rtl::OUString aText;
3477 							uno::Reference< text::XSimpleText > xText( rXShape, uno::UNO_QUERY );
3478 							if ( xText.is() )
3479 								aText = xText->getString();
3480 							if ( !aText.getLength() )
3481 								aText = ::rtl::OUString::createFromAscii( "your text" );	// todo: moving into a resource
3482 							AddOpt( DFF_Prop_gtextUNICODE, aText );
3483 
3484 							// FontWork Font
3485 							rtl::OUString aFontName;
3486 							const rtl::OUString	sCharFontName			( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) );
3487 				    		uno::Any aAny = aXPropSet->getPropertyValue( sCharFontName );
3488 							aAny >>= aFontName;
3489 							if ( !aFontName.getLength() )
3490 								aFontName = ::rtl::OUString::createFromAscii( "Arial Black" );
3491 							AddOpt( DFF_Prop_gtextFont, aFontName );
3492 
3493 							sal_Int16 nCharScaleWidth = 100;
3494 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharScaleWidth" ) ), sal_True ) )
3495 							{
3496 								if ( aAny >>= nCharScaleWidth )
3497 								{
3498 									if ( nCharScaleWidth != 100 )
3499 									{
3500 										sal_Int32 nVal = nCharScaleWidth * 655;
3501 										AddOpt( DFF_Prop_gtextSpacing, nVal );
3502 									}
3503 								}
3504 							}
3505 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) ), sal_True ) )
3506 							{
3507 								float fCharHeight = 0.0;
3508 								if ( aAny >>= fCharHeight )
3509 								{
3510 									sal_Int32 nTextSize = static_cast< sal_Int32 > ( fCharHeight * 65536 );
3511 									AddOpt(ESCHER_Prop_gtextSize, nTextSize);
3512 								}
3513 							}
3514 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharKerning" ) ), sal_True ) )
3515 							{
3516 								sal_Int16 nCharKerning = sal_Int16();
3517 								if ( aAny >>= nCharKerning )
3518 							{
3519 									nTextPathFlags |= 0x10000000;
3520 									if ( nCharKerning )
3521 										nTextPathFlags |= 0x1000;
3522 									else
3523 										nTextPathFlags &=~0x1000;
3524 								}
3525 							}
3526 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharPosture" ) ), sal_True ) )
3527 							{
3528 								awt::FontSlant eFontSlant;
3529 								if ( aAny >>= eFontSlant )
3530 								{
3531 									nTextPathFlags |= 0x100010;
3532 									if ( eFontSlant != awt::FontSlant_NONE )
3533 										nTextPathFlags |= 0x10;
3534 									else
3535 										nTextPathFlags &=~0x10;
3536 								}
3537 							}
3538 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) ), sal_True ) )
3539 							{
3540 								float fFontWidth = 0;
3541 								if ( aAny >>= fFontWidth )
3542 								{
3543 									nTextPathFlags |= 0x200020;
3544 									if ( fFontWidth > awt::FontWeight::NORMAL )
3545 										nTextPathFlags |= 0x20;
3546 									else
3547 										nTextPathFlags &=~0x20;
3548 								}
3549 							}
3550 							//export gTextAlign attr
3551 							if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), sal_True ) )
3552 							{
3553 								MSO_GeoTextAlign  gTextAlign = mso_alignTextCenter;
3554 								// SdrFitToSizeType  eFTS( ((SdrTextFitToSizeTypeItem&)pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
3555 								drawing::TextHorizontalAdjust	eHA( drawing::TextHorizontalAdjust_LEFT );
3556 								aAny >>= eHA;
3557 								switch( eHA )
3558 								{
3559 								case drawing::TextHorizontalAdjust_LEFT :
3560 									gTextAlign = mso_alignTextLeft;
3561 									break;
3562 								case drawing::TextHorizontalAdjust_CENTER:
3563 									gTextAlign = mso_alignTextCenter;
3564 									break;
3565 								case drawing::TextHorizontalAdjust_RIGHT:
3566 									gTextAlign = mso_alignTextRight;
3567 									break;
3568 								case drawing::TextHorizontalAdjust_BLOCK:
3569 									{
3570 										SdrFitToSizeType  eFTS( ((SdrTextFitToSizeTypeItem&)pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
3571 										if ( eFTS == SDRTEXTFIT_ALLLINES)
3572 										{
3573 											gTextAlign = mso_alignTextStretch;
3574 										}
3575 										else
3576 										{
3577 											gTextAlign = mso_alignTextWordJust;
3578 										}
3579 										break;
3580 									}
3581 								default:
3582 									break;
3583 								}
3584 								AddOpt(DFF_Prop_gtextAlign,gTextAlign);
3585 							}
3586 						}
3587 						if((nTextPathFlags & 0x4000) != 0)  //Is Font work
3588 						{
3589 							OutlinerParaObject* pOutlinerParaObject = pCustoShape->GetOutlinerParaObject();
3590 							if ( pOutlinerParaObject && pOutlinerParaObject->IsVertical() )
3591 								nTextPathFlags |= 0x2000;
3592 						}
3593 						if ( nTextPathFlags != nTextPathFlagsOrg )
3594 							AddOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
3595 					}
3596 				}
3597 				else if ( rProp.Name.equals( sHandles ) )
3598 				{
3599 					if ( !bIsDefaultObject )
3600 					{
3601 						bPredefinedHandlesUsed = sal_False;
3602 						if ( rProp.Value >>= aHandlesPropSeq )
3603 						{
3604 							sal_uInt16 nElements = (sal_uInt16)aHandlesPropSeq.getLength();
3605 							if ( nElements )
3606 							{
3607 								const rtl::OUString	sHandle ( RTL_CONSTASCII_USTRINGPARAM( "Handle" ) );
3608 
3609 								sal_uInt16 k, j, nElementSize = 36;
3610 								sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3611 								SvMemoryStream aOut( nStreamSize );
3612 								aOut << nElements
3613 									<< nElements
3614 									<< nElementSize;
3615 
3616 								for ( k = 0; k < nElements; k++ )
3617 								{
3618 									sal_uInt32 nFlags = 0;
3619 									sal_Int32 nXPosition = 0;
3620 									sal_Int32 nYPosition = 0;
3621 									sal_Int32 nXMap = 0;
3622 									sal_Int32 nYMap = 0;
3623 									sal_Int32 nXRangeMin = 0x80000000;
3624 									sal_Int32 nXRangeMax = 0x7fffffff;
3625 									sal_Int32 nYRangeMin = 0x80000000;
3626 									sal_Int32 nYRangeMax = 0x7fffffff;
3627 
3628 									const uno::Sequence< beans::PropertyValue >& rPropSeq = aHandlesPropSeq[ k ];
3629 									for ( j = 0; j < rPropSeq.getLength(); j++ )
3630 									{
3631 										const beans::PropertyValue& rPropVal = rPropSeq[ j ];
3632 
3633 										const rtl::OUString	sPosition			( RTL_CONSTASCII_USTRINGPARAM( "Position" ) );
3634 										const rtl::OUString	sMirroredX			( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) );
3635 										const rtl::OUString	sMirroredY			( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) );
3636 										const rtl::OUString	sSwitched			( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) );
3637 										const rtl::OUString	sPolar				( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) );
3638 	//									const rtl::OUString	sMap				( RTL_CONSTASCII_USTRINGPARAM( "Map" ) );
3639 										const rtl::OUString	sRadiusRangeMinimum	( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) );
3640 										const rtl::OUString	sRadiusRangeMaximum	( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) );
3641 										const rtl::OUString	sRangeXMinimum		( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) );
3642 										const rtl::OUString	sRangeXMaximum		( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) );
3643 										const rtl::OUString	sRangeYMinimum		( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) );
3644 										const rtl::OUString	sRangeYMaximum		( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) );
3645 
3646 										if ( rPropVal.Name.equals( sPosition ) )
3647 										{
3648 											com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
3649 											if ( rPropVal.Value >>= aPosition )
3650 											{
3651 												GetValueForEnhancedCustomShapeHandleParameter( nXPosition, aPosition.First );
3652 												GetValueForEnhancedCustomShapeHandleParameter( nYPosition, aPosition.Second );
3653 											}
3654 										}
3655 										else if ( rPropVal.Name.equals( sMirroredX ) )
3656 										{
3657 											sal_Bool bMirroredX = sal_Bool();
3658 											if ( rPropVal.Value >>= bMirroredX )
3659 											{
3660 												if ( bMirroredX )
3661 													nFlags |= 1;
3662 											}
3663 										}
3664 										else if ( rPropVal.Name.equals( sMirroredY ) )
3665 										{
3666 											sal_Bool bMirroredY = sal_Bool();
3667 											if ( rPropVal.Value >>= bMirroredY )
3668 											{
3669 												if ( bMirroredY )
3670 													nFlags |= 2;
3671 											}
3672 										}
3673 										else if ( rPropVal.Name.equals( sSwitched ) )
3674 										{
3675 											sal_Bool bSwitched = sal_Bool();
3676 											if ( rPropVal.Value >>= bSwitched )
3677 											{
3678 												if ( bSwitched )
3679 													nFlags |= 4;
3680 											}
3681 										}
3682 										else if ( rPropVal.Name.equals( sPolar ) )
3683 										{
3684 											com::sun::star::drawing::EnhancedCustomShapeParameterPair aPolar;
3685 											if ( rPropVal.Value >>= aPolar )
3686 											{
3687 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aPolar.First ) )
3688 													nFlags |= 0x800;
3689 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aPolar.Second ) )
3690 													nFlags |= 0x1000;
3691 												nFlags |= 8;
3692 											}
3693 										}
3694 	/* seems not to be used.
3695 										else if ( rPropVal.Name.equals( sMap ) )
3696 										{
3697 											com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap;
3698 											if ( rPropVal.Value >>= aMap )
3699 											{
3700 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) )
3701 													nFlags |= 0x800;
3702 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) )
3703 													nFlags |= 0x1000;
3704 												nFlags |= 0x10;
3705 											}
3706 										}
3707 	*/
3708 										else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) )
3709 										{
3710 											nYRangeMin = (sal_Int32)0xff4c0000;	// the range of angles seems to be a not
3711 											nYRangeMax = (sal_Int32)0x00b40000;	// used feature, so we are defaulting this
3712 
3713 											com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
3714 											if ( rPropVal.Value >>= aRadiusRangeMinimum )
3715 											{
3716 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aRadiusRangeMinimum ) )
3717 													nFlags |= 0x80;
3718 												nFlags |= 0x2000;
3719 											}
3720 										}
3721 										else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) )
3722 										{
3723 											nYRangeMin = (sal_Int32)0xff4c0000;	// the range of angles seems to be a not
3724 											nYRangeMax = (sal_Int32)0x00b40000;	// used feature, so we are defaulting this
3725 
3726 											com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
3727 											if ( rPropVal.Value >>= aRadiusRangeMaximum )
3728 											{
3729 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aRadiusRangeMaximum ) )
3730 													nFlags |= 0x100;
3731 												nFlags |= 0x2000;
3732 											}
3733 										}
3734 										else if ( rPropVal.Name.equals( sRangeXMinimum ) )
3735 										{
3736 											com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
3737 											if ( rPropVal.Value >>= aXRangeMinimum )
3738 											{
3739 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aXRangeMinimum ) )
3740 													nFlags |= 0x80;
3741 												nFlags |= 0x20;
3742 											}
3743 										}
3744 										else if ( rPropVal.Name.equals( sRangeXMaximum ) )
3745 										{
3746 											com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
3747 											if ( rPropVal.Value >>= aXRangeMaximum )
3748 											{
3749 												if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aXRangeMaximum ) )
3750 													nFlags |= 0x100;
3751 												nFlags |= 0x20;
3752 											}
3753 										}
3754 										else if ( rPropVal.Name.equals( sRangeYMinimum ) )
3755 										{
3756 											com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
3757 											if ( rPropVal.Value >>= aYRangeMinimum )
3758 											{
3759 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMin, aYRangeMinimum ) )
3760 													nFlags |= 0x200;
3761 												nFlags |= 0x20;
3762 											}
3763 										}
3764 										else if ( rPropVal.Name.equals( sRangeYMaximum ) )
3765 										{
3766 											com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
3767 											if ( rPropVal.Value >>= aYRangeMaximum )
3768 											{
3769 												if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMax, aYRangeMaximum ) )
3770 													nFlags |= 0x400;
3771 												nFlags |= 0x20;
3772 											}
3773 										}
3774 									}
3775 									aOut << nFlags
3776 										<< nXPosition
3777 										<< nYPosition
3778 										<< nXMap
3779 										<< nYMap
3780 										<< nXRangeMin
3781 										<< nXRangeMax
3782 										<< nYRangeMin
3783 										<< nYRangeMax;
3784 
3785 									if ( nFlags & 8 )
3786 										nAdjustmentsWhichNeedsToBeConverted |= ( 1 << ( nYPosition - 0x100 ) );
3787 								}
3788 								sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3789 								memcpy( pBuf, aOut.GetData(), nStreamSize );
3790 								AddOpt( DFF_Prop_Handles, sal_True, nStreamSize - 6, pBuf, nStreamSize );
3791 							}
3792 							else
3793 							{
3794 								sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3795 								AddOpt( DFF_Prop_Handles, sal_True, 0, pBuf, 0 );
3796 							}
3797 						}
3798 					}
3799 				}
3800 				else if ( rProp.Name.equals( sAdjustmentValues ) )
3801 				{
3802 					// it is required, that the information which handle is polar has already be read,
3803 					// so we are able to change the polar value to a fixed float
3804 					aAdjustmentValuesProp = rProp.Value;
3805                     bHasAdjustmentValuesProp = true;
3806 				}
3807 			}
3808 			if ( bHasAdjustmentValuesProp )
3809 			{
3810 				uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
3811 				if ( aAdjustmentValuesProp >>= aAdjustmentSeq )
3812 				{
3813 					if ( bPredefinedHandlesUsed )
3814 					    LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
3815 
3816 					sal_Int32 k, nValue = 0, nAdjustmentValues = aAdjustmentSeq.getLength();
3817 					for ( k = 0; k < nAdjustmentValues; k++ )
3818 					    if( GetAdjustmentValue( aAdjustmentSeq[ k ], k, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
3819 							AddOpt( (sal_uInt16)( DFF_Prop_adjustValue + k ), (sal_uInt32)nValue );
3820 				}
3821 			}
3822 			if( bHasPathCoordinatesProp )
3823 			{
3824 				com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
3825 				if ( aPathCoordinatesProp >>= aCoordinates )
3826 				{
3827 					// creating the vertices
3828 					if ( (sal_uInt16)aCoordinates.getLength() )
3829 					{
3830 						sal_uInt16 j, nElements = (sal_uInt16)aCoordinates.getLength();
3831 						sal_uInt16 nElementSize = 8;
3832 						sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3833 						SvMemoryStream aOut( nStreamSize );
3834 						aOut << nElements
3835 							<< nElements
3836 							<< nElementSize;
3837 						for( j = 0; j < nElements; j++ )
3838 						{
3839 							sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].First, aEquationOrder, sal_True );
3840 							sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].Second, aEquationOrder, sal_True );
3841 							aOut << X
3842 								<< Y;
3843 						}
3844 						sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3845 						memcpy( pBuf, aOut.GetData(), nStreamSize );
3846 						AddOpt( DFF_Prop_pVertices, sal_True, nStreamSize - 6, pBuf, nStreamSize );	// -6
3847 					}
3848 					else
3849 					{
3850 						sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3851 						AddOpt( DFF_Prop_pVertices, sal_True, 0, pBuf, 0 );
3852 					}
3853 				}
3854 			}
3855 		}
3856 	}
3857 }
3858 
3859 // ---------------------------------------------------------------------------------------------
3860 
GetCustomShapeType(const uno::Reference<drawing::XShape> & rXShape,sal_uInt32 & nMirrorFlags,rtl::OUString & rShapeType)3861 MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags, rtl::OUString& rShapeType )
3862 {
3863 	MSO_SPT eShapeType = mso_sptNil;
3864 	nMirrorFlags = 0;
3865 	uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
3866     if ( aXPropSet.is() )
3867     {
3868 		try
3869 		{
3870 			const OUString	sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM ( "CustomShapeGeometry" ) );
3871 			uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
3872 			uno::Sequence< beans::PropertyValue > aGeoPropSeq;
3873 			if ( aGeoPropSet >>= aGeoPropSeq )
3874 			{
3875 				sal_Int32 i, nCount = aGeoPropSeq.getLength();
3876 				for ( i = 0; i < nCount; i++ )
3877 				{
3878 					const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
3879 					if ( rProp.Name.equalsAscii( "Type" ) )
3880 					{
3881 						if ( rProp.Value >>= rShapeType )
3882 							eShapeType = EnhancedCustomShapeTypeNames::Get( rShapeType );
3883 					}
3884 					else if ( rProp.Name.equalsAscii( "MirroredX" ) )
3885 					{
3886 						sal_Bool bMirroredX = sal_Bool();
3887 						if ( ( rProp.Value >>= bMirroredX ) && bMirroredX )
3888 							nMirrorFlags  |= SHAPEFLAG_FLIPH;
3889 					}
3890 					else if ( rProp.Name.equalsAscii( "MirroredY" ) )
3891 					{
3892 						sal_Bool bMirroredY = sal_Bool();
3893 						if ( ( rProp.Value >>= bMirroredY ) && bMirroredY )
3894 							nMirrorFlags  |= SHAPEFLAG_FLIPV;
3895 					}
3896 				}
3897 			}
3898 		}
3899 		catch( ::com::sun::star::uno::Exception& )
3900 		{
3901 		}
3902 	}
3903 	return eShapeType;
3904 }
3905 
GetCustomShapeType(const uno::Reference<drawing::XShape> & rXShape,sal_uInt32 & nMirrorFlags)3906 MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags )
3907 {
3908 	rtl::OUString aShapeType;
3909 	return GetCustomShapeType( rXShape, nMirrorFlags, aShapeType );
3910 }
3911 
3912 // ---------------------------------------------------------------------------------------------
3913 //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)3914 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)
3915 {
3916 	SdrObject* pShape = GetSdrObjectFromXShape( rXShape );
3917 	if ( pShape )
3918 	{
3919 		SdrModel* pMod = pShape->GetModel();
3920 		Graphic aGraphic(SdrExchangeView::GetObjGraphic( pMod, pShape));
3921 
3922         GraphicObject   aGraphicObject = aGraphic;
3923         ByteString  aUniqueId = aGraphicObject.GetUniqueID();
3924 		if ( aUniqueId.Len() )
3925 		{
3926 			if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect )
3927 			{
3928 				Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() );
3929 
3930 				sal_uInt32 nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, NULL );
3931 				if ( nBlibId )
3932 				{
3933 					AddOpt( ESCHER_Prop_pib, nBlibId, sal_True );
3934 					ImplCreateGraphicAttributes( rXPropSet, nBlibId, sal_False );
3935 					return sal_True;
3936 				}
3937 			}
3938 		}
3939 	}
3940 
3941 	return sal_False;
3942 
3943 }
3944 
EscherPersistTable()3945 EscherPersistTable::EscherPersistTable()
3946 {
3947 }
3948 
3949 // ---------------------------------------------------------------------------------------------
3950 
~EscherPersistTable()3951 EscherPersistTable::~EscherPersistTable()
3952 {
3953 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3954 		delete (EscherPersistEntry*)pPtr;
3955 }
3956 
3957 // ---------------------------------------------------------------------------------------------
3958 
PtIsID(sal_uInt32 nID)3959 sal_Bool EscherPersistTable::PtIsID( sal_uInt32 nID )
3960 {
3961 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3962 	{
3963 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3964 			return sal_True;
3965 	}
3966 	return sal_False;
3967 }
3968 
3969 // ---------------------------------------------------------------------------------------------
3970 
PtInsert(sal_uInt32 nID,sal_uInt32 nOfs)3971 void EscherPersistTable::PtInsert( sal_uInt32 nID, sal_uInt32 nOfs )
3972 {
3973 	maPersistTable.Insert( new EscherPersistEntry( nID, nOfs ) );
3974 }
3975 
3976 // ---------------------------------------------------------------------------------------------
3977 
PtDelete(sal_uInt32 nID)3978 sal_uInt32 EscherPersistTable::PtDelete( sal_uInt32 nID )
3979 {
3980 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3981 	{
3982 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3983 		{
3984 //			sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3985 			delete (EscherPersistEntry*) maPersistTable.Remove();
3986 		}
3987 	}
3988 	return 0;
3989 }
3990 
3991 // ---------------------------------------------------------------------------------------------
3992 
PtGetOffsetByID(sal_uInt32 nID)3993 sal_uInt32 EscherPersistTable::PtGetOffsetByID( sal_uInt32 nID )
3994 {
3995 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3996 	{
3997 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3998 			return ((EscherPersistEntry*)pPtr)->mnOffset;
3999 	}
4000 	return 0;
4001 };
4002 
4003 // ---------------------------------------------------------------------------------------------
4004 
PtReplace(sal_uInt32 nID,sal_uInt32 nOfs)4005 sal_uInt32 EscherPersistTable::PtReplace( sal_uInt32 nID, sal_uInt32 nOfs )
4006 {
4007 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
4008 	{
4009 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
4010 		{
4011 			sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
4012 			((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
4013 			return nRetValue;
4014 		}
4015 	}
4016 	return 0;
4017 }
4018 
4019 // ---------------------------------------------------------------------------------------------
4020 
PtReplaceOrInsert(sal_uInt32 nID,sal_uInt32 nOfs)4021 sal_uInt32 EscherPersistTable::PtReplaceOrInsert( sal_uInt32 nID, sal_uInt32 nOfs )
4022 {
4023 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
4024 	{
4025 		if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
4026 		{
4027 			sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
4028 			((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
4029 			return nRetValue;
4030 		}
4031 	}
4032 	PtInsert( nID, nOfs );
4033 	return 0;
4034 }
4035 
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)4036 sal_Bool EscherPropertyValueHelper::GetPropertyValue(
4037 	::com::sun::star::uno::Any& rAny,
4038 		const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
4039 			const String& rString,
4040 					sal_Bool bTestPropertyAvailability )
4041 {
4042     sal_Bool bRetValue = sal_True;
4043 	if ( bTestPropertyAvailability )
4044 	{
4045 		bRetValue = sal_False;
4046 		try
4047 		{
4048 			::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
4049 				aXPropSetInfo( rXPropSet->getPropertySetInfo() );
4050 			if ( aXPropSetInfo.is() )
4051 				bRetValue = aXPropSetInfo->hasPropertyByName( rString );
4052 		}
4053 		catch( ::com::sun::star::uno::Exception& )
4054 		{
4055 			bRetValue = sal_False;
4056 		}
4057 	}
4058 	if ( bRetValue )
4059 	{
4060 		try
4061 		{
4062 			rAny = rXPropSet->getPropertyValue( rString );
4063 			if ( !rAny.hasValue() )
4064 				bRetValue = sal_False;
4065 		}
4066 		catch( ::com::sun::star::uno::Exception& )
4067 		{
4068 			bRetValue = sal_False;
4069 		}
4070 	}
4071     return bRetValue;
4072 }
4073 
4074 // ---------------------------------------------------------------------------------------------
4075 
GetPropertyState(const::com::sun::star::uno::Reference<::com::sun::star::beans::XPropertySet> & rXPropSet,const String & rPropertyName)4076 ::com::sun::star::beans::PropertyState EscherPropertyValueHelper::GetPropertyState(
4077 	const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
4078 		const String& rPropertyName )
4079 {
4080 	::com::sun::star::beans::PropertyState eRetValue = ::com::sun::star::beans::PropertyState_AMBIGUOUS_VALUE;
4081 	try
4082 	{
4083 		::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState >	aXPropState
4084 				( rXPropSet, ::com::sun::star::uno::UNO_QUERY );
4085 		if ( aXPropState.is() )
4086             eRetValue = aXPropState->getPropertyState( rPropertyName );
4087 	}
4088 	catch( ::com::sun::star::uno::Exception& )
4089 	{
4090 		//...
4091 	}
4092 	return eRetValue;
4093 }
4094 
4095 // ---------------------------------------------------------------------------------------------
4096 // ---------------------------------------------------------------------------------------------
4097 // ---------------------------------------------------------------------------------------------
4098 
EscherBlibEntry(sal_uInt32 nPictureOffset,const GraphicObject & rObject,const ByteString & rId,const GraphicAttr * pGraphicAttr)4099 EscherBlibEntry::EscherBlibEntry( sal_uInt32 nPictureOffset, const GraphicObject& rObject, const ByteString& rId,
4100 										const GraphicAttr* pGraphicAttr ) :
4101 	mnPictureOffset ( nPictureOffset ),
4102 	mnRefCount		( 1 ),
4103 	mnSizeExtra		( 0 ),
4104 	maPrefSize		( rObject.GetPrefSize() ),
4105 	maPrefMapMode	( rObject.GetPrefMapMode() ),
4106 	mbIsEmpty		( sal_True )
4107 {
4108 	mbIsNativeGraphicPossible = ( pGraphicAttr == NULL );
4109 	meBlibType = UNKNOWN;
4110 	mnSize = 0;
4111 
4112 	sal_uInt32		nLen = rId.Len();
4113 	const sal_Char* pData = rId.GetBuffer();
4114 	GraphicType		eType( rObject.GetType() );
4115 	if ( nLen && pData && ( eType != GRAPHIC_NONE ) )
4116 	{
4117 		mnIdentifier[ 0 ] = rtl_crc32( 0,pData, nLen );
4118 		mnIdentifier[ 1 ] = 0;
4119 
4120 		if ( pGraphicAttr )
4121 		{
4122 			if ( pGraphicAttr->IsSpecialDrawMode()
4123 					|| pGraphicAttr->IsMirrored()
4124 						 || pGraphicAttr->IsCropped()
4125 							|| pGraphicAttr->IsRotated()
4126 								|| pGraphicAttr->IsTransparent()
4127 									|| pGraphicAttr->IsAdjusted() )
4128 			{
4129 				SvMemoryStream aSt( sizeof( GraphicAttr ) );
4130 				aSt << static_cast<sal_uInt16>(pGraphicAttr->GetDrawMode())
4131 					<< static_cast<sal_uInt32>(pGraphicAttr->GetMirrorFlags())
4132 					<< pGraphicAttr->GetLeftCrop()
4133 					<< pGraphicAttr->GetTopCrop()
4134 					<< pGraphicAttr->GetRightCrop()
4135 					<< pGraphicAttr->GetBottomCrop()
4136 					<< pGraphicAttr->GetRotation()
4137 					<< pGraphicAttr->GetLuminance()
4138 					<< pGraphicAttr->GetContrast()
4139 					<< pGraphicAttr->GetChannelR()
4140 					<< pGraphicAttr->GetChannelG()
4141 					<< pGraphicAttr->GetChannelB()
4142 					<< pGraphicAttr->GetGamma()
4143 					<< (sal_Bool)( pGraphicAttr->IsInvert() == sal_True )
4144 					<< pGraphicAttr->GetTransparency();
4145 				mnIdentifier[ 1 ] = rtl_crc32( 0, aSt.GetData(), aSt.Tell() );
4146 			}
4147 			else
4148 				mbIsNativeGraphicPossible = sal_True;
4149 		}
4150 		sal_uInt32 i, nTmp, n1, n2;
4151 		n1 = n2 = 0;
4152 		for ( i = 0; i < nLen; i++ )
4153 		{
4154 			nTmp = n2 >> 28;	// rotating 4 bit
4155 			n2 <<= 4;
4156 			n2 |= n1 >> 28;
4157 			n1 <<= 4;
4158 			n1 |= nTmp;
4159 			n1 ^= *pData++ - '0';
4160 		}
4161 		mnIdentifier[ 2 ] = n1;
4162 		mnIdentifier[ 3 ] = n2;
4163 		mbIsEmpty = sal_False;
4164 	}
4165 };
4166 
4167 // ---------------------------------------------------------------------------------------------
4168 
WriteBlibEntry(SvStream & rSt,sal_Bool bWritePictureOffset,sal_uInt32 nResize)4169 void EscherBlibEntry::WriteBlibEntry( SvStream& rSt, sal_Bool bWritePictureOffset, sal_uInt32 nResize )
4170 {
4171 	sal_uInt32	nPictureOffset = ( bWritePictureOffset ) ? mnPictureOffset : 0;
4172 
4173 	rSt << (sal_uInt32)( ( ESCHER_BSE << 16 ) | ( ( (sal_uInt16)meBlibType << 4 ) | 2 ) )
4174 		<< (sal_uInt32)( 36 + nResize )
4175 		<< (sal_uInt8)meBlibType;
4176 
4177 	switch ( meBlibType )
4178 	{
4179 		case EMF :
4180 		case WMF :	// EMF/WMF auf OS2 zu Pict Konvertieren
4181 			rSt << (sal_uInt8)PICT;
4182 		break;
4183 		default:
4184 			rSt << (sal_uInt8)meBlibType;
4185 	};
4186 
4187 	rSt.Write( &mnIdentifier[ 0 ], 16 );
4188 	rSt << (sal_uInt16)0
4189 		<< (sal_uInt32)( mnSize + mnSizeExtra )
4190 		<< mnRefCount
4191 		<< nPictureOffset
4192 		<< (sal_uInt32)0;
4193 }
4194 
4195 // ---------------------------------------------------------------------------------------------
4196 
~EscherBlibEntry()4197 EscherBlibEntry::~EscherBlibEntry()
4198 {
4199 };
4200 
4201 // ---------------------------------------------------------------------------------------------
4202 
operator ==(const EscherBlibEntry & rEscherBlibEntry) const4203 sal_Bool EscherBlibEntry::operator==( const EscherBlibEntry& rEscherBlibEntry ) const
4204 {
4205 	for ( int i = 0; i < 3; i++ )
4206 	{
4207 		if ( mnIdentifier[ i ] != rEscherBlibEntry.mnIdentifier[ i ] )
4208 			return sal_False;
4209 	}
4210 	return sal_True;
4211 }
4212 
4213 // ---------------------------------------------------------------------------------------------
4214 // ---------------------------------------------------------------------------------------------
4215 // ---------------------------------------------------------------------------------------------
4216 
EscherGraphicProvider(sal_uInt32 nFlags)4217 EscherGraphicProvider::EscherGraphicProvider( sal_uInt32 nFlags ) :
4218 	mnFlags			( nFlags ),
4219 	mpBlibEntrys	( NULL ),
4220 	mnBlibBufSize	( 0 ),
4221 	mnBlibEntrys	( 0 )
4222 {
4223 }
4224 
~EscherGraphicProvider()4225 EscherGraphicProvider::~EscherGraphicProvider()
4226 {
4227 	for ( sal_uInt32 i = 0; i < mnBlibEntrys; delete mpBlibEntrys[ i++ ] ) ;
4228 	delete[] mpBlibEntrys;
4229 }
4230 
SetNewBlipStreamOffset(sal_Int32 nOffset)4231 void EscherGraphicProvider::SetNewBlipStreamOffset( sal_Int32 nOffset )
4232 {
4233 	for( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
4234 	{
4235 		EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
4236 		pBlibEntry->mnPictureOffset += nOffset;
4237 	}
4238 }
4239 
ImplInsertBlib(EscherBlibEntry * p_EscherBlibEntry)4240 sal_uInt32 EscherGraphicProvider::ImplInsertBlib( EscherBlibEntry* p_EscherBlibEntry )
4241 {
4242 	if ( mnBlibBufSize == mnBlibEntrys )
4243 	{
4244 		mnBlibBufSize += 64;
4245 		EscherBlibEntry** pTemp = new EscherBlibEntry*[ mnBlibBufSize ];
4246 		for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
4247 		{
4248 			pTemp[ i ] = mpBlibEntrys[ i ];
4249 		}
4250 		delete[] mpBlibEntrys;
4251 		mpBlibEntrys = pTemp;
4252 	}
4253 	mpBlibEntrys[ mnBlibEntrys++ ] = p_EscherBlibEntry;
4254 	return mnBlibEntrys;
4255 }
4256 
GetBlibStoreContainerSize(SvStream * pMergePicStreamBSE) const4257 sal_uInt32 EscherGraphicProvider::GetBlibStoreContainerSize( SvStream* pMergePicStreamBSE ) const
4258 {
4259 	sal_uInt32 nSize = 44 * mnBlibEntrys + 8;
4260 	if ( pMergePicStreamBSE )
4261 	{
4262 		for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
4263 			nSize += mpBlibEntrys[ i ]->mnSize + mpBlibEntrys[ i ]->mnSizeExtra;
4264 	}
4265 	return nSize;
4266 }
4267 
WriteBlibStoreEntry(SvStream & rSt,sal_uInt32 nBlipId,sal_Bool bWritePictureOffSet,sal_uInt32 nResize)4268 sal_Bool EscherGraphicProvider::WriteBlibStoreEntry(SvStream& rSt,
4269     sal_uInt32 nBlipId, sal_Bool bWritePictureOffSet, sal_uInt32 nResize)
4270 {
4271     if (nBlipId > mnBlibEntrys || nBlipId == 0)
4272         return sal_False;
4273     mpBlibEntrys[nBlipId-1]->WriteBlibEntry(rSt, bWritePictureOffSet, nResize);
4274     return sal_True;
4275 }
4276 
WriteBlibStoreContainer(SvStream & rSt,SvStream * pMergePicStreamBSE)4277 void EscherGraphicProvider::WriteBlibStoreContainer( SvStream& rSt, SvStream* pMergePicStreamBSE )
4278 {
4279 	sal_uInt32	nSize = GetBlibStoreContainerSize( pMergePicStreamBSE );
4280 	if ( nSize )
4281 	{
4282 		rSt << (sal_uInt32)( ( ESCHER_BstoreContainer << 16 ) | 0x1f )
4283 			<< (sal_uInt32)( nSize - 8 );
4284 
4285 		if ( pMergePicStreamBSE )
4286 		{
4287 			sal_uInt32 i, nBlipSize, nOldPos = pMergePicStreamBSE->Tell();
4288 			const sal_uInt32 nBuf = 0x40000;	// 256KB buffer
4289 			sal_uInt8* pBuf = new sal_uInt8[ nBuf ];
4290 
4291 			for ( i = 0; i < mnBlibEntrys; i++ )
4292 			{
4293 				EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
4294 
4295 				ESCHER_BlibType nBlibType = pBlibEntry->meBlibType;
4296 				nBlipSize = pBlibEntry->mnSize + pBlibEntry->mnSizeExtra;
4297 				pBlibEntry->WriteBlibEntry( rSt, sal_False, nBlipSize );
4298 
4299 				// BLIP
4300 				pMergePicStreamBSE->Seek( pBlibEntry->mnPictureOffset );
4301 				sal_uInt16 n16;
4302 				// record version and instance
4303 				*pMergePicStreamBSE >> n16;
4304 				rSt << n16;
4305 				// record type
4306 				*pMergePicStreamBSE >> n16;
4307 				rSt << sal_uInt16( ESCHER_BlipFirst + nBlibType );
4308                 DBG_ASSERT( n16 == ESCHER_BlipFirst + nBlibType , "EscherGraphicProvider::WriteBlibStoreContainer: BLIP record types differ" );
4309 				sal_uInt32 n32;
4310 				// record size
4311 				*pMergePicStreamBSE >> n32;
4312 				nBlipSize -= 8;
4313 				rSt << nBlipSize;
4314                 DBG_ASSERT( nBlipSize == n32, "EscherGraphicProvider::WriteBlibStoreContainer: BLIP sizes differ" );
4315 				// record
4316 				while ( nBlipSize )
4317 				{
4318 					sal_uInt32 nBytes = ( nBlipSize > nBuf ? nBuf : nBlipSize );
4319 					pMergePicStreamBSE->Read( pBuf, nBytes );
4320 					rSt.Write( pBuf, nBytes );
4321 					nBlipSize -= nBytes;
4322 				}
4323 			}
4324 			delete[] pBuf;
4325 			pMergePicStreamBSE->Seek( nOldPos );
4326 		}
4327 		else
4328 		{
4329             for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
4330                 mpBlibEntrys[ i ]->WriteBlibEntry( rSt, sal_True );
4331 		}
4332 	}
4333 }
4334 
GetPrefSize(const sal_uInt32 nBlibId,Size & rPrefSize,MapMode & rPrefMapMode)4335 sal_Bool EscherGraphicProvider::GetPrefSize( const sal_uInt32 nBlibId, Size& rPrefSize, MapMode& rPrefMapMode )
4336 {
4337 	sal_Bool bInRange = nBlibId && ( ( nBlibId - 1 ) < mnBlibEntrys );
4338 	if ( bInRange )
4339 	{
4340 		EscherBlibEntry* pEntry = mpBlibEntrys[ nBlibId - 1 ];
4341 		rPrefSize = pEntry->maPrefSize;
4342 		rPrefMapMode = pEntry->maPrefMapMode;
4343 	}
4344 	return bInRange;
4345 }
4346 
GetBlibID(SvStream & rPicOutStrm,const ByteString & rId,const Rectangle &,const com::sun::star::awt::Rectangle * pVisArea,const GraphicAttr * pGraphicAttr)4347 sal_uInt32 EscherGraphicProvider::GetBlibID( SvStream& rPicOutStrm, const ByteString& rId,
4348 											const Rectangle& /* rBoundRect */, const com::sun::star::awt::Rectangle* pVisArea, const GraphicAttr* pGraphicAttr )
4349 {
4350 	sal_uInt32			nBlibId = 0;
4351 	GraphicObject		aGraphicObject( rId );
4352 
4353 	EscherBlibEntry* p_EscherBlibEntry = new EscherBlibEntry( rPicOutStrm.Tell(), aGraphicObject, rId, pGraphicAttr );
4354 	if ( !p_EscherBlibEntry->IsEmpty() )
4355 	{
4356 		for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
4357 		{
4358 			if ( *( mpBlibEntrys[ i ] )	== *p_EscherBlibEntry )
4359 			{
4360 				mpBlibEntrys[ i ]->mnRefCount++;
4361 				delete p_EscherBlibEntry;
4362 				return i + 1;
4363 			}
4364 		}
4365 
4366 		sal_Bool			bUseNativeGraphic( sal_False );
4367 
4368 		Graphic				aGraphic( aGraphicObject.GetTransformedGraphic( pGraphicAttr ) );
4369 		GfxLink				aGraphicLink;
4370 		SvMemoryStream		aStream;
4371 
4372 		const sal_uInt8*	pGraphicAry = NULL;
4373 
4374 		if ( p_EscherBlibEntry->mbIsNativeGraphicPossible && aGraphic.IsLink() )
4375 		{
4376 			aGraphicLink = aGraphic.GetLink();
4377 
4378 			p_EscherBlibEntry->mnSize = aGraphicLink.GetDataSize();
4379 			pGraphicAry = aGraphicLink.GetData();
4380 
4381 			if ( p_EscherBlibEntry->mnSize && pGraphicAry )
4382 			{
4383 				switch ( aGraphicLink.GetType() )
4384 				{
4385 					case GFX_LINK_TYPE_NATIVE_JPG : p_EscherBlibEntry->meBlibType = PEG; break;
4386 					case GFX_LINK_TYPE_NATIVE_PNG : p_EscherBlibEntry->meBlibType = PNG; break;
4387 
4388                     // #15508# added BMP type for better exports; need to check this
4389                     // checked - does not work that way, so keep out for now. It may
4390                     // work somehow with direct DIB data, but that would need to be checked
4391                     // carefully
4392                     // for more comments please check RtfAttributeOutput::FlyFrameGraphic
4393                     //
4394                     // case GFX_LINK_TYPE_NATIVE_BMP : p_EscherBlibEntry->meBlibType = DIB; break;
4395 
4396 					case GFX_LINK_TYPE_NATIVE_WMF :
4397 					{
4398 						if ( pGraphicAry && ( p_EscherBlibEntry->mnSize > 0x2c ) )
4399 						{
4400 							if ( ( pGraphicAry[ 0x28 ] == 0x20 ) && ( pGraphicAry[ 0x29 ] == 0x45 )		// check the magic
4401 								&& ( pGraphicAry[ 0x2a ] == 0x4d ) && ( pGraphicAry[ 0x2b ] == 0x46 ) )	// number ( emf detection )
4402 							{
4403 								p_EscherBlibEntry->meBlibType = EMF;
4404 							}
4405 							else
4406 							{
4407 								p_EscherBlibEntry->meBlibType = WMF;
4408 								if ( ( pGraphicAry[ 0 ] == 0xd7 ) && ( pGraphicAry[ 1 ] == 0xcd )
4409 									&& ( pGraphicAry[ 2 ] == 0xc6 ) && ( pGraphicAry[ 3 ] == 0x9a ) )
4410 								{	// we have to get rid of the metafileheader
4411 									pGraphicAry += 22;
4412 									p_EscherBlibEntry->mnSize -= 22;
4413 								}
4414 							}
4415 						}
4416 					}
4417 					break;
4418 					default: break;
4419 				}
4420 				if ( p_EscherBlibEntry->meBlibType != UNKNOWN )
4421 					bUseNativeGraphic = sal_True;
4422 			}
4423 		}
4424 		if ( !bUseNativeGraphic )
4425 		{
4426 			GraphicType eGraphicType = aGraphic.GetType();
4427 			if ( ( eGraphicType == GRAPHIC_BITMAP ) || ( eGraphicType == GRAPHIC_GDIMETAFILE ) )
4428 			{
4429 				sal_uInt32 nErrCode;
4430 				if ( !aGraphic.IsAnimated() )
4431 // !EMF				nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG  : CVT_WMF );
4432 					nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG  : CVT_EMF );
4433 				else
4434 				{	// to store a animation, a gif has to be included into the msOG chunk of a png	#I5583#
4435 					GraphicFilter*	pFilter = GraphicFilter::GetGraphicFilter();
4436 					SvMemoryStream  aGIFStream;
4437 					ByteString		aVersion( "MSOFFICE9.0" );
4438 					aGIFStream.Write( aVersion.GetBuffer(), aVersion.Len() );
4439 					nErrCode = pFilter->ExportGraphic( aGraphic, String(), aGIFStream,
4440 						pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "GIF" ) ) ), NULL );
4441 					com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aFilterData( 1 );
4442 					com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence( 1 );
4443 					sal_uInt32 nGIFSreamLen = aGIFStream.Tell();
4444 					com::sun::star::uno::Sequence< sal_Int8 > aGIFSeq( nGIFSreamLen );
4445 					sal_Int8* pSeq = aGIFSeq.getArray();
4446 					aGIFStream.Seek( STREAM_SEEK_TO_BEGIN );
4447 					aGIFStream.Read( pSeq, nGIFSreamLen );
4448 					com::sun::star::beans::PropertyValue aChunkProp, aFilterProp;
4449 					aChunkProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "msOG" ) );
4450 					aChunkProp.Value <<= aGIFSeq;
4451 					aAdditionalChunkSequence[ 0 ] = aChunkProp;
4452 					aFilterProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "AdditionalChunks" ) );
4453 					aFilterProp.Value <<= aAdditionalChunkSequence;
4454 					aFilterData[ 0 ] = aFilterProp;
4455 					nErrCode = pFilter->ExportGraphic( aGraphic, String(), aStream,
4456 						pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "PNG" ) ) ), &aFilterData );
4457 				}
4458 				if ( nErrCode == ERRCODE_NONE )
4459 				{
4460 // !EMF				p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : WMF;
4461 					p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : EMF;
4462 					aStream.Seek( STREAM_SEEK_TO_END );
4463 					p_EscherBlibEntry->mnSize = aStream.Tell();
4464 					pGraphicAry = (sal_uInt8*)aStream.GetData();
4465 
4466 					if ( p_EscherBlibEntry->meBlibType == WMF )		// the fileheader is not used
4467 					{
4468 						p_EscherBlibEntry->mnSize -= 22;
4469 						pGraphicAry += 22;
4470 					}
4471 				}
4472 			}
4473 		}
4474 
4475 		ESCHER_BlibType	eBlibType = p_EscherBlibEntry->meBlibType;
4476 		if ( p_EscherBlibEntry->mnSize && pGraphicAry && ( eBlibType != UNKNOWN ) )
4477 		{
4478 			sal_uInt32 nExtra, nAtomSize = 0;
4479 			sal_uInt32 nInstance, nUncompressedSize = p_EscherBlibEntry->mnSize;
4480 
4481 			if ( mnFlags & _E_GRAPH_PROV_USE_INSTANCES )
4482 			{
4483 				rPicOutStrm << (sal_uInt32)( 0x7f90000 | (sal_uInt16)( mnBlibEntrys << 4 ) )
4484 							<< (sal_uInt32)0;
4485 				nAtomSize = rPicOutStrm.Tell();
4486  				if ( eBlibType == PNG )
4487 					rPicOutStrm << (sal_uInt16)0x0606;
4488 				else if ( eBlibType == WMF )
4489 					rPicOutStrm << (sal_uInt16)0x0403;
4490 				else if ( eBlibType == EMF )
4491 					rPicOutStrm << (sal_uInt16)0x0402;
4492 				else if ( eBlibType == PEG )
4493 					rPicOutStrm << (sal_uInt16)0x0505;
4494 			}
4495 			if ( ( eBlibType == PEG ) || ( eBlibType == PNG ) ) // || ( eBlibType == DIB )) // #15508#
4496 			{
4497 				nExtra = 17;
4498 				p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
4499 
4500                 // #15508# type see SvxMSDffManager::GetBLIPDirect (checked, does not work this way)
4501                 // see RtfAttributeOutput::FlyFrameGraphic for more comments
4502                 // maybe it would work with direct DIB data, but that would need thorough testing
4503                 if( eBlibType == PNG )
4504                 {
4505                     nInstance = 0xf01e6e00;
4506                 }
4507                 else // if( eBlibType == PEG )
4508                 {
4509                     nInstance = 0xf01d46a0;
4510                 }
4511                 //else // eBlibType == DIB
4512                 //{
4513                 //    nInstance = 0xf01d7A80;
4514                 //}
4515 
4516                 // #15508#
4517                 //nInstance = ( eBlibType == PNG ) ? 0xf01e6e00 : 0xf01d46a0;
4518 
4519 				rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
4520 				rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
4521 				rPicOutStrm << (sal_uInt8)0xff;
4522 				rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
4523 			}
4524 			else
4525 			{
4526 				ZCodec aZCodec( 0x8000, 0x8000 );
4527 				aZCodec.BeginCompression();
4528 				SvMemoryStream aDestStrm;
4529 				aZCodec.Write( aDestStrm, pGraphicAry, p_EscherBlibEntry->mnSize );
4530 				aZCodec.EndCompression();
4531 				aDestStrm.Seek( STREAM_SEEK_TO_END );
4532 				p_EscherBlibEntry->mnSize = aDestStrm.Tell();
4533 				pGraphicAry = (sal_uInt8*)aDestStrm.GetData();
4534 				if ( p_EscherBlibEntry->mnSize && pGraphicAry )
4535 				{
4536 					nExtra = eBlibType == WMF ? 0x42 : 0x32;									// !EMF -> no change
4537 					p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
4538 					nInstance = ( eBlibType == WMF ) ? 0xf01b2170 : 0xf01a3d40;					// !EMF -> no change
4539 					rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
4540 					if ( eBlibType == WMF )														// !EMF -> no change
4541 						rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
4542 					rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
4543 
4544                     /*
4545                      ##913##
4546                      For Word the stored size of the graphic is critical the
4547                      metafile boundaries must match the actual graphics
4548                      boundaries, and the width and height must be in EMU's
4549 
4550                      If you don't do it this way then objects edited in the
4551                      msoffice app may show strange behaviour as the size jumps
4552                      around, and the original size and scaling factor in word
4553                      will be a very strange figure
4554                     */
4555                     sal_uInt32 nPrefWidth = p_EscherBlibEntry->maPrefSize.Width();
4556                     sal_uInt32 nPrefHeight = p_EscherBlibEntry->maPrefSize.Height();
4557 					sal_uInt32 nWidth, nHeight;
4558 					if ( pVisArea )
4559 					{
4560 						nWidth = pVisArea->Width * 360;
4561 						nHeight = pVisArea->Height * 360;
4562 					}
4563 					else
4564 					{
4565 						Size aPrefSize(lcl_SizeToEmu(p_EscherBlibEntry->maPrefSize, p_EscherBlibEntry->maPrefMapMode));
4566 						nWidth = aPrefSize.Width() * 360;
4567 	                    nHeight = aPrefSize.Height() * 360;
4568 					}
4569                     rPicOutStrm	<< nUncompressedSize // WMFSize without FileHeader
4570                     << (sal_Int32)0		// da die Originalgroesse des WMF's (ohne FileHeader)
4571                     << (sal_Int32)0		// nicht mehr feststellbar ist, schreiben wir 10cm / x
4572                     << nPrefWidth
4573                     << nPrefHeight
4574                     << nWidth
4575                     << nHeight
4576                     << p_EscherBlibEntry->mnSize
4577                     << (sal_uInt16)0xfe00;	// compression Flags
4578                     rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
4579 				}
4580 			}
4581 			if ( nAtomSize )
4582 			{
4583 				sal_uInt32	nPos = rPicOutStrm.Tell();
4584 				rPicOutStrm.Seek( nAtomSize - 4 );
4585 				rPicOutStrm << (sal_uInt32)( nPos - nAtomSize );
4586 				rPicOutStrm.Seek( nPos );
4587 			}
4588 			nBlibId = ImplInsertBlib( p_EscherBlibEntry ), p_EscherBlibEntry = NULL;
4589 		}
4590 	}
4591 	if ( p_EscherBlibEntry )
4592 		delete p_EscherBlibEntry;
4593 	return nBlibId;
4594 }
4595 
4596 // ---------------------------------------------------------------------------------------------
4597 // ---------------------------------------------------------------------------------------------
4598 // ---------------------------------------------------------------------------------------------
4599 
4600 struct EscherConnectorRule
4601 {
4602 	sal_uInt32	nRuleId;
4603 	sal_uInt32	nShapeA;		// SPID of shape A
4604 	sal_uInt32	nShapeB;		// SPID of shape B
4605 	sal_uInt32	nShapeC;		// SPID of connector shape
4606 	sal_uInt32	ncptiA;			// Connection site Index of shape A
4607 	sal_uInt32	ncptiB;			// Connection site Index of shape B
4608 };
4609 
4610 struct EscherShapeListEntry
4611 {
4612 	::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape	>	aXShape;
4613 	sal_uInt32			n_EscherId;
4614 
EscherShapeListEntryEscherShapeListEntry4615 						EscherShapeListEntry( const ::com::sun::star::uno::Reference
4616 							< ::com::sun::star::drawing::XShape > & rShape, sal_uInt32 nId ) :
4617 										aXShape		( rShape ),
4618 										n_EscherId	( nId ) {}
4619 };
4620 
GetClosestPoint(const Polygon & rPoly,const::com::sun::star::awt::Point & rPoint)4621 sal_uInt32 EscherConnectorListEntry::GetClosestPoint( const Polygon& rPoly, const ::com::sun::star::awt::Point& rPoint )
4622 {
4623 	sal_uInt16 nCount = rPoly.GetSize();
4624 	sal_uInt16 nClosest = nCount;
4625 	double fDist = (sal_uInt32)0xffffffff;
4626 	while( nCount-- )
4627 	{
4628 		double fDistance = hypot( rPoint.X - rPoly[ nCount ].X(), rPoint.Y - rPoly[ nCount ].Y() );
4629 		if ( fDistance < fDist )
4630 		{
4631 			nClosest =  nCount;
4632 			fDist = fDistance;
4633 		}
4634 	}
4635 	return nClosest;
4636 };
4637 
4638 // ---------------------------------------------------------------------------------------------
4639 // bei Rechtecken           bei Ellipsen    bei Polygonen
4640 //
4641 // nRule =  0 ->Top         0 ->Top         nRule = Index auf ein (Poly)Polygon Punkt
4642 //          1 ->Left        2 ->Left
4643 //          2 ->Bottom      4 ->Bottom
4644 //          3 ->Right       6 ->Right
4645 
GetConnectorRule(sal_Bool bFirst)4646 sal_uInt32 EscherConnectorListEntry::GetConnectorRule( sal_Bool bFirst )
4647 {
4648     sal_uInt32 nRule = 0;
4649 
4650 	::com::sun::star::uno::Any aAny;
4651     ::com::sun::star::awt::Point aRefPoint( ( bFirst ) ? maPointA : maPointB );
4652     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
4653 		aXShape( ( bFirst ) ? mXConnectToA : mXConnectToB );
4654 
4655 	String aString( (::rtl::OUString)aXShape->getShapeType() );
4656     ByteString aType( aString, RTL_TEXTENCODING_UTF8 );
4657     aType.Erase( 0, 13 );   // removing "com.sun.star."
4658     sal_uInt16 nPos = aType.Search( "Shape" );
4659     aType.Erase( nPos, 5 );
4660 
4661     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
4662 		aPropertySet( aXShape, ::com::sun::star::uno::UNO_QUERY );
4663 
4664     if ( aType == "drawing.PolyPolygon" || aType == "drawing.PolyLine" )
4665     {
4666         if ( aPropertySet.is() )
4667         {
4668 			if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4669 					aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ) ) )
4670 			{
4671                 ::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon =
4672 					(::com::sun::star::drawing::PointSequenceSequence*)aAny.getValue();
4673                 sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->getLength();
4674                 ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
4675 
4676                 if ( pOuterSequence )
4677                 {
4678                     sal_Int32 a, b, nIndex = 0;
4679                     sal_uInt32 nDistance = 0xffffffff;
4680                     for( a = 0; a < nOuterSequenceCount; a++ )
4681                     {
4682                         ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
4683                         if ( pInnerSequence )
4684                         {
4685                             ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
4686                             if ( pArray )
4687                             {
4688                                 for ( b = 0; b < pInnerSequence->getLength(); b++, nIndex++, pArray++ )
4689                                 {
4690                                     sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
4691                                     if ( nDist < nDistance )
4692                                     {
4693                                         nRule = nIndex;
4694                                         nDistance = nDist;
4695                                     }
4696                                 }
4697                             }
4698                         }
4699                     }
4700                 }
4701 			}
4702         }
4703     }
4704     else if ( ( aType == "drawing.OpenBezier" ) || ( aType == "drawing.OpenFreeHand" ) || ( aType == "drawing.PolyLinePath" )
4705         || ( aType == "drawing.ClosedBezier" ) || ( aType == "drawing.ClosedFreeHand" ) || ( aType == "drawing.PolyPolygonPath" ) )
4706     {
4707         ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
4708 			aPropertySet2( aXShape, ::com::sun::star::uno::UNO_QUERY );
4709         if ( aPropertySet2.is() )
4710         {
4711 			if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4712 					aPropertySet2, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ) ) )
4713 			{
4714 				::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon =
4715 					(::com::sun::star::drawing::PolyPolygonBezierCoords*)aAny.getValue();
4716                 sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->Coordinates.getLength();
4717 
4718                 // Zeiger auf innere sequences holen
4719                 ::com::sun::star::drawing::PointSequence* pOuterSequence =
4720 					pSourcePolyPolygon->Coordinates.getArray();
4721                 ::com::sun::star::drawing::FlagSequence*  pOuterFlags =
4722 					pSourcePolyPolygon->Flags.getArray();
4723 
4724                 if ( pOuterSequence && pOuterFlags )
4725                 {
4726                     sal_Int32 a, b, nIndex = 0;
4727                     sal_uInt32 nDistance = 0xffffffff;
4728 
4729                     for ( a = 0; a < nOuterSequenceCount; a++ )
4730                     {
4731                         ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
4732                         ::com::sun::star::drawing::FlagSequence*  pInnerFlags = pOuterFlags++;
4733                         if ( pInnerSequence && pInnerFlags )
4734                         {
4735                             ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
4736                             ::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
4737                             if ( pArray && pFlags )
4738                             {
4739                                 for ( b = 0; b < pInnerSequence->getLength(); b++, pArray++ )
4740                                 {
4741                                     PolyFlags ePolyFlags = *( (PolyFlags*)pFlags++ );
4742                                     if ( ePolyFlags == POLY_CONTROL )
4743                                         continue;
4744                                     sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
4745                                     if ( nDist < nDistance )
4746                                     {
4747                                         nRule = nIndex;
4748                                         nDistance = nDist;
4749                                     }
4750                                     nIndex++;
4751                                 }
4752                             }
4753                         }
4754                     }
4755                 }
4756             }
4757         }
4758     }
4759     else
4760     {
4761 		bool bRectangularConnection = true;
4762 
4763 		if ( aType == "drawing.Custom" )
4764 		{
4765 			SdrObject* pCustoShape( GetSdrObjectFromXShape( aXShape ) );
4766 			if ( pCustoShape && pCustoShape->ISA( SdrObjCustomShape ) )
4767 			{
4768 				SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)
4769 					pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
4770 
4771 				const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
4772 				const rtl::OUString	sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
4773 				const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
4774 
4775 				rtl::OUString sShapeType;
4776 				uno::Any* pType = rGeometryItem.GetPropertyValueByName( sType );
4777 				if ( pType )
4778 					*pType >>= sShapeType;
4779 				MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
4780 
4781 				uno::Any* pGluePointType = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePointType );
4782 
4783 				sal_Int16 nGluePointType = sal_Int16();
4784 				if ( !( pGluePointType &&
4785                         ( *pGluePointType >>= nGluePointType ) ) )
4786 					nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
4787 
4788 				if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::CUSTOM )
4789 				{
4790 					const SdrGluePointList* pList = pCustoShape->GetGluePointList();
4791 					if ( pList )
4792 					{
4793 						Polygon aPoly;
4794 						sal_uInt16 nNum, nAnz = pList->GetCount();
4795 						if ( nAnz )
4796 						{
4797 							for ( nNum = 0; nNum < nAnz; nNum++ )
4798 							{
4799 								const SdrGluePoint& rGP = (*pList)[ nNum ];
4800 								Point aPt( rGP.GetAbsolutePos( *pCustoShape ) );
4801 								aPoly.Insert( POLY_APPEND, aPt );
4802 							}
4803 							nRule = GetClosestPoint( aPoly, aRefPoint );
4804 							bRectangularConnection = false;
4805 						}
4806 					}
4807 				}
4808 				else if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::SEGMENTS )
4809 				{
4810 					SdrObject* pPoly = pCustoShape->DoConvertToPolyObj( sal_True, true );
4811 					if ( pPoly && pPoly->ISA( SdrPathObj ) )
4812 					{
4813 						sal_Int16 a, b, nIndex = 0;
4814 						sal_uInt32 nDistance = 0xffffffff;
4815 
4816 						// #i74631# use explicit constructor here. Also XPolyPolygon is not necessary,
4817 						// reducing to PolyPolygon
4818 						const PolyPolygon aPolyPoly(((SdrPathObj*)pPoly)->GetPathPoly());
4819 
4820 						for ( a = 0; a < aPolyPoly.Count(); a++ )
4821 						{
4822 							const Polygon& rPoly = aPolyPoly.GetObject( a );
4823 							for ( b = 0; b < rPoly.GetSize(); b++ )
4824 							{
4825 								if ( rPoly.GetFlags( b ) != POLY_NORMAL )
4826 									continue;
4827 								const Point& rPt = rPoly[ b ];
4828                                 sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - rPt.X(), aRefPoint.Y - rPt.Y() );
4829                                 if ( nDist < nDistance )
4830                                 {
4831                                     nRule = nIndex;
4832                                     nDistance = nDist;
4833                                 }
4834                                 nIndex++;
4835 							}
4836 						}
4837 						if ( nDistance != 0xffffffff )
4838 							bRectangularConnection = false;
4839 					}
4840 				}
4841 			}
4842 		}
4843 		if ( bRectangularConnection )
4844 		{
4845 			::com::sun::star::awt::Point aPoint( aXShape->getPosition() );
4846 			::com::sun::star::awt::Size	 aSize( aXShape->getSize() );
4847 
4848 			Rectangle	aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
4849 			Point		aCenter( aRect.Center() );
4850 			Polygon		aPoly( 4 );
4851 
4852 			aPoly[ 0 ] = Point( aCenter.X(), aRect.Top() );
4853 			aPoly[ 1 ] = Point( aRect.Left(), aCenter.Y() );
4854 			aPoly[ 2 ] = Point( aCenter.X(), aRect.Bottom() );
4855 			aPoly[ 3 ] = Point( aRect.Right(), aCenter.Y() );
4856 
4857 			sal_Int32 nAngle = ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4858 				aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True ) )
4859 					? *((sal_Int32*)aAny.getValue() )
4860 					: 0;
4861 			if ( nAngle )
4862 				aPoly.Rotate( aRect.TopLeft(), (sal_uInt16)( ( nAngle + 5 ) / 10 ) );
4863 			nRule = GetClosestPoint( aPoly, aRefPoint );
4864 
4865 			if ( aType == "drawing.Ellipse" )
4866 				nRule <<= 1;    // In PPT hat eine Ellipse 8 M?glichkeiten sich zu connecten
4867 		}
4868     }
4869     return nRule;
4870 }
4871 
~EscherSolverContainer()4872 EscherSolverContainer::~EscherSolverContainer()
4873 {
4874     void* pP;
4875 
4876     for( pP = maShapeList.First(); pP; pP = maShapeList.Next() )
4877         delete (EscherShapeListEntry*)pP;
4878     for( pP = maConnectorList.First(); pP; pP = maConnectorList.Next() )
4879         delete (EscherConnectorListEntry*)pP;
4880 }
4881 
AddShape(const::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & rXShape,sal_uInt32 nId)4882 void EscherSolverContainer::AddShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape, sal_uInt32 nId )
4883 {
4884     maShapeList.Insert( new EscherShapeListEntry( rXShape, nId ), LIST_APPEND );
4885 }
4886 
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)4887 void EscherSolverContainer::AddConnector( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConnector,
4888 										const ::com::sun::star::awt::Point& rPA,
4889 									::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConA,
4890 										const ::com::sun::star::awt::Point& rPB,
4891 									::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConB )
4892 {
4893     maConnectorList.Insert( new EscherConnectorListEntry( rConnector, rPA, rConA, rPB, rConB ), LIST_APPEND );
4894 }
4895 
GetShapeId(const::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & rXShape) const4896 sal_uInt32 EscherSolverContainer::GetShapeId( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) const
4897 {
4898     for ( EscherShapeListEntry* pPtr = (EscherShapeListEntry*)((List&)maShapeList).First();
4899 			pPtr; pPtr = (EscherShapeListEntry*)((List&)maShapeList).Next() )
4900     {
4901         if ( rXShape == pPtr->aXShape )
4902             return ( pPtr->n_EscherId );
4903     }
4904     return 0;
4905 }
4906 
WriteSolver(SvStream & rStrm)4907 void EscherSolverContainer::WriteSolver( SvStream& rStrm )
4908 {
4909     sal_uInt32 nCount = maConnectorList.Count();
4910     if ( nCount )
4911     {
4912 		sal_uInt32	nRecHdPos, nCurrentPos, nSize;
4913 		rStrm	<< (sal_uInt16)( ( nCount << 4 ) | 0xf )	// open an ESCHER_SolverContainer
4914 				<< (sal_uInt16)ESCHER_SolverContainer		//
4915 				<< (sal_uInt32)0;							//
4916 
4917 		nRecHdPos = rStrm.Tell() - 4;
4918 
4919         EscherConnectorRule aConnectorRule;
4920         aConnectorRule.nRuleId = 2;
4921         for ( EscherConnectorListEntry* pPtr = (EscherConnectorListEntry*)maConnectorList.First();
4922 				pPtr; pPtr = (EscherConnectorListEntry*)maConnectorList.Next() )
4923         {
4924             aConnectorRule.ncptiA = aConnectorRule.ncptiB = 0xffffffff;
4925             aConnectorRule.nShapeC = GetShapeId( pPtr->mXConnector );
4926             aConnectorRule.nShapeA = GetShapeId( pPtr->mXConnectToA );
4927             aConnectorRule.nShapeB = GetShapeId( pPtr->mXConnectToB );
4928 
4929             if ( aConnectorRule.nShapeC )
4930             {
4931                 if ( aConnectorRule.nShapeA )
4932                     aConnectorRule.ncptiA = pPtr->GetConnectorRule( sal_True );
4933                 if ( aConnectorRule.nShapeB )
4934                     aConnectorRule.ncptiB = pPtr->GetConnectorRule( sal_False );
4935             }
4936 			rStrm	<< (sal_uInt32)( ( ESCHER_ConnectorRule << 16 ) | 1 )	// atom hd
4937 					<< (sal_uInt32)24										//
4938 					<< aConnectorRule.nRuleId
4939                     << aConnectorRule.nShapeA
4940                     << aConnectorRule.nShapeB
4941                     << aConnectorRule.nShapeC
4942                     << aConnectorRule.ncptiA
4943                     << aConnectorRule.ncptiB;
4944 
4945             aConnectorRule.nRuleId += 2;
4946         }
4947 
4948 		nCurrentPos = rStrm.Tell();				// close the ESCHER_SolverContainer
4949 		nSize = ( nCurrentPos - nRecHdPos ) - 4;//
4950 		rStrm.Seek( nRecHdPos );				//
4951 		rStrm << nSize;							//
4952 		rStrm.Seek( nCurrentPos );				//
4953     }
4954 }
4955 
4956 // ---------------------------------------------------------------------------------------------
4957 
EscherExGlobal(sal_uInt32 nGraphicProvFlags)4958 EscherExGlobal::EscherExGlobal( sal_uInt32 nGraphicProvFlags ) :
4959     EscherGraphicProvider( nGraphicProvFlags ),
4960     mpPicStrm( 0 ),
4961     mbHasDggCont( false ),
4962     mbPicStrmQueried( false )
4963 {
4964 }
4965 
~EscherExGlobal()4966 EscherExGlobal::~EscherExGlobal()
4967 {
4968 }
4969 
GenerateDrawingId()4970 sal_uInt32 EscherExGlobal::GenerateDrawingId()
4971 {
4972     // new drawing starts a new cluster in the cluster table (cluster identifiers are one-based)
4973     sal_uInt32 nClusterId = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
4974     // drawing identifiers are one-based
4975     sal_uInt32 nDrawingId = static_cast< sal_uInt32 >( maDrawingInfos.size() + 1 );
4976     // prepare new entries in the tables
4977     maClusterTable.push_back( ClusterEntry( nDrawingId ) );
4978     maDrawingInfos.push_back( DrawingInfo( nClusterId ) );
4979     // return the new drawing identifier
4980     return nDrawingId;
4981 }
4982 
GenerateShapeId(sal_uInt32 nDrawingId,bool bIsInSpgr)4983 sal_uInt32 EscherExGlobal::GenerateShapeId( sal_uInt32 nDrawingId, bool bIsInSpgr )
4984 {
4985     // drawing identifier is one-based
4986     size_t nDrawingIdx = nDrawingId - 1;
4987     OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GenerateShapeId - invalid drawing ID" );
4988     if( nDrawingIdx >= maDrawingInfos.size() )
4989         return 0;
4990     DrawingInfo& rDrawingInfo = maDrawingInfos[ nDrawingIdx ];
4991 
4992     // cluster identifier in drawing info struct is one-based
4993     ClusterEntry* pClusterEntry = &maClusterTable[ rDrawingInfo.mnClusterId - 1 ];
4994 
4995     // check cluster overflow, create new cluster entry
4996     if( pClusterEntry->mnNextShapeId == DFF_DGG_CLUSTER_SIZE )
4997     {
4998         // start a new cluster in the cluster table
4999         maClusterTable.push_back( ClusterEntry( nDrawingId ) );
5000         pClusterEntry = &maClusterTable.back();
5001         // new size of maClusterTable is equal to one-based identifier of the new cluster
5002         rDrawingInfo.mnClusterId = static_cast< sal_uInt32 >( maClusterTable.size() );
5003     }
5004 
5005     // build shape identifier from cluster identifier and next free cluster shape identifier
5006     rDrawingInfo.mnLastShapeId = static_cast< sal_uInt32 >( rDrawingInfo.mnClusterId * DFF_DGG_CLUSTER_SIZE + pClusterEntry->mnNextShapeId );
5007     // update free shape identifier in cluster entry
5008     ++pClusterEntry->mnNextShapeId;
5009     /*  Old code has counted the shapes only, if we are in a SPGRCONTAINER. Is
5010         this really intended? Maybe it's always true... */
5011     if( bIsInSpgr )
5012         ++rDrawingInfo.mnShapeCount;
5013 
5014     // return the new shape identifier
5015     return rDrawingInfo.mnLastShapeId;
5016 }
5017 
GetDrawingShapeCount(sal_uInt32 nDrawingId) const5018 sal_uInt32 EscherExGlobal::GetDrawingShapeCount( sal_uInt32 nDrawingId ) const
5019 {
5020     size_t nDrawingIdx = nDrawingId - 1;
5021     OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetDrawingShapeCount - invalid drawing ID" );
5022     return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnShapeCount : 0;
5023 }
5024 
GetLastShapeId(sal_uInt32 nDrawingId) const5025 sal_uInt32 EscherExGlobal::GetLastShapeId( sal_uInt32 nDrawingId ) const
5026 {
5027     size_t nDrawingIdx = nDrawingId - 1;
5028     OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetLastShapeId - invalid drawing ID" );
5029     return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnLastShapeId : 0;
5030 }
5031 
GetDggAtomSize() const5032 sal_uInt32 EscherExGlobal::GetDggAtomSize() const
5033 {
5034     // 8 bytes header, 16 bytes fixed DGG data, 8 bytes for each cluster
5035     return static_cast< sal_uInt32 >( 24 + 8 * maClusterTable.size() );
5036 }
5037 
WriteDggAtom(SvStream & rStrm) const5038 void EscherExGlobal::WriteDggAtom( SvStream& rStrm ) const
5039 {
5040     sal_uInt32 nDggSize = GetDggAtomSize();
5041 
5042     // write the DGG record header (do not include the 8 bytes of the header in the data size)
5043     rStrm << static_cast< sal_uInt32 >( ESCHER_Dgg << 16 ) << static_cast< sal_uInt32 >( nDggSize - 8 );
5044 
5045     // claculate and write the fixed DGG data
5046     sal_uInt32 nShapeCount = 0;
5047     sal_uInt32 nLastShapeId = 0;
5048     for( DrawingInfoVector::const_iterator aIt = maDrawingInfos.begin(), aEnd = maDrawingInfos.end(); aIt != aEnd; ++aIt )
5049     {
5050         nShapeCount += aIt->mnShapeCount;
5051         nLastShapeId = ::std::max( nLastShapeId, aIt->mnLastShapeId );
5052     }
5053     // the non-existing cluster with index #0 is counted too
5054     sal_uInt32 nClusterCount = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
5055     sal_uInt32 nDrawingCount = static_cast< sal_uInt32 >( maDrawingInfos.size() );
5056     rStrm << nLastShapeId << nClusterCount << nShapeCount << nDrawingCount;
5057 
5058     // write the cluster table
5059     for( ClusterTable::const_iterator aIt = maClusterTable.begin(), aEnd = maClusterTable.end(); aIt != aEnd; ++aIt )
5060         rStrm << aIt->mnDrawingId << aIt->mnNextShapeId;
5061 }
5062 
QueryPictureStream()5063 SvStream* EscherExGlobal::QueryPictureStream()
5064 {
5065     if( !mbPicStrmQueried )
5066     {
5067         mpPicStrm = ImplQueryPictureStream();
5068         mbPicStrmQueried = true;
5069     }
5070     return mpPicStrm;
5071 }
5072 
ImplQueryPictureStream()5073 SvStream* EscherExGlobal::ImplQueryPictureStream()
5074 {
5075     return 0;
5076 }
5077 
5078 // ---------------------------------------------------------------------------------------------
5079 // ---------------------------------------------------------------------------------------------
5080 // ---------------------------------------------------------------------------------------------
5081 
EscherEx(const EscherExGlobalRef & rxGlobal,SvStream & rOutStrm)5082 EscherEx::EscherEx( const EscherExGlobalRef& rxGlobal, SvStream& rOutStrm ) :
5083     mxGlobal                ( rxGlobal ),
5084 	mpOutStrm				( &rOutStrm ),
5085 
5086 	mnGroupLevel			( 0 ),
5087 	mnHellLayerId			( USHRT_MAX ),
5088 
5089 	mbEscherSpgr			( sal_False ),
5090     mbEscherDg              ( sal_False )
5091 {
5092 	mnStrmStartOfs = mpOutStrm->Tell();
5093     mpImplEscherExSdr.reset( new ImplEscherExSdr( *this ) );
5094 }
5095 
~EscherEx()5096 EscherEx::~EscherEx()
5097 {
5098 }
5099 
5100 // ---------------------------------------------------------------------------------------------
5101 
Flush(SvStream * pPicStreamMergeBSE)5102 void EscherEx::Flush( SvStream* pPicStreamMergeBSE /* = NULL */ )
5103 {
5104     if ( mxGlobal->HasDggContainer() )
5105 	{
5106         // store the current stream position at ESCHER_Persist_CurrentPosition key
5107 		PtReplaceOrInsert( ESCHER_Persist_CurrentPosition, mpOutStrm->Tell() );
5108 		if ( DoSeek( ESCHER_Persist_Dgg ) )
5109 		{
5110             /*  The DGG record is still not written. ESCHER_Persist_Dgg seeks
5111                 to the place where the complete record has to be inserted. */
5112             InsertAtCurrentPos( mxGlobal->GetDggAtomSize(), false );
5113             mxGlobal->WriteDggAtom( *mpOutStrm );
5114 
5115             if ( mxGlobal->HasGraphics() )
5116             {
5117                 /*  Calculate the total size of the BSTORECONTAINER including
5118                     all BSE records containing the picture data contained in
5119                     the passed in pPicStreamMergeBSE. */
5120                 sal_uInt32 nBSCSize = mxGlobal->GetBlibStoreContainerSize( pPicStreamMergeBSE );
5121                 if ( nBSCSize > 0 )
5122                 {
5123                     InsertAtCurrentPos( nBSCSize, false );
5124                     mxGlobal->WriteBlibStoreContainer( *mpOutStrm, pPicStreamMergeBSE );
5125                 }
5126             }
5127 
5128             /*  Forget the stream position stored for the DGG which is invalid
5129                 after the call to InsertAtCurrentPos() anyway. */
5130             PtDelete( ESCHER_Persist_Dgg );
5131         }
5132         // seek to initial position (may be different due to inserted DGG and BLIPs)
5133 		mpOutStrm->Seek( PtGetOffsetByID( ESCHER_Persist_CurrentPosition ) );
5134 	}
5135 }
5136 
5137 // ---------------------------------------------------------------------------------------------
5138 
InsertAtCurrentPos(sal_uInt32 nBytes,bool bExpandEndOfAtom)5139 void EscherEx::InsertAtCurrentPos( sal_uInt32 nBytes, bool bExpandEndOfAtom )
5140 {
5141 	sal_uInt32	nSize, nType, nSource, nBufSize, nToCopy, nCurPos = mpOutStrm->Tell();
5142 	sal_uInt8*	pBuf;
5143 
5144 	// Persist table anpassen
5145 	for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
5146 	{
5147 		sal_uInt32 nOfs = ((EscherPersistEntry*)pPtr)->mnOffset;
5148 		if ( nOfs >= nCurPos )
5149 			((EscherPersistEntry*)pPtr)->mnOffset += nBytes;
5150 	}
5151 
5152 	// container und atom sizes anpassen
5153 	mpOutStrm->Seek( mnStrmStartOfs );
5154 	while ( mpOutStrm->Tell() < nCurPos )
5155 	{
5156 		*mpOutStrm >> nType >> nSize;
5157         sal_uInt32 nEndOfRecord = mpOutStrm->Tell() + nSize;
5158         bool bContainer = (nType & 0x0F) == 0x0F;
5159         /*  Expand the record, if the insertion position is inside, or if the
5160             position is at the end of a container (expands always), or at the
5161             end of an atom and bExpandEndOfAtom is set. */
5162         if ( (nCurPos < nEndOfRecord) || ((nCurPos == nEndOfRecord) && (bContainer || bExpandEndOfAtom)) )
5163 		{
5164 			mpOutStrm->SeekRel( -4 );
5165 			*mpOutStrm << (sal_uInt32)( nSize + nBytes );
5166             if ( !bContainer )
5167 				mpOutStrm->SeekRel( nSize );
5168 		}
5169 		else
5170 			mpOutStrm->SeekRel( nSize );
5171 	}
5172 	std::vector< sal_uInt32 >::iterator aIter( mOffsets.begin() );
5173 	std::vector< sal_uInt32 >::iterator aEnd( mOffsets.end() );
5174 	while( aIter != aEnd )
5175 	{
5176 		if ( *aIter > nCurPos )
5177 			*aIter += nBytes;
5178 		aIter++;
5179 	}
5180 	mpOutStrm->Seek( STREAM_SEEK_TO_END );
5181 	nSource = mpOutStrm->Tell();
5182 	nToCopy = nSource - nCurPos;						// Stream um nBytes vergroessern
5183 	pBuf = new sal_uInt8[ 0x40000 ];							// 256KB Buffer
5184 	while ( nToCopy )
5185 	{
5186 		nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
5187 		nToCopy -= nBufSize;
5188 		nSource -= nBufSize;
5189 		mpOutStrm->Seek( nSource );
5190 		mpOutStrm->Read( pBuf, nBufSize );
5191 		mpOutStrm->Seek( nSource + nBytes );
5192 		mpOutStrm->Write( pBuf, nBufSize );
5193 	}
5194 	delete[] pBuf;
5195 	mpOutStrm->Seek( nCurPos );
5196 }
5197 
5198 // ---------------------------------------------------------------------------------------------
5199 
SeekBehindRecHeader(sal_uInt16 nRecType)5200 sal_Bool EscherEx::SeekBehindRecHeader( sal_uInt16 nRecType )
5201 {
5202 	sal_uInt32	nOldPos, nStreamEnd, nType, nSize;
5203 
5204 	nOldPos = mpOutStrm->Tell();
5205 	nStreamEnd = mpOutStrm->Seek( STREAM_SEEK_TO_END );
5206 	mpOutStrm->Seek( nOldPos );
5207 	while ( mpOutStrm->Tell() < nStreamEnd )
5208 	{
5209 		*mpOutStrm >> nType >> nSize;
5210 		if ( ( nType >> 16 ) == nRecType )
5211 			return sal_True;
5212 		if ( ( nType & 0xf ) != 0xf )
5213 			mpOutStrm->SeekRel( nSize );
5214 	}
5215 	mpOutStrm->Seek( nOldPos );
5216 	return sal_False;
5217 }
5218 
5219 // ---------------------------------------------------------------------------------------------
5220 
InsertPersistOffset(sal_uInt32 nKey,sal_uInt32 nOffset)5221 void EscherEx::InsertPersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
5222 {
5223 	PtInsert( ESCHER_Persist_PrivateEntry | nKey, nOffset );
5224 }
5225 
ReplacePersistOffset(sal_uInt32 nKey,sal_uInt32 nOffset)5226 void EscherEx::ReplacePersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
5227 {
5228     PtReplace( ESCHER_Persist_PrivateEntry | nKey, nOffset );
5229 }
5230 
GetPersistOffset(sal_uInt32 nKey)5231 sal_uInt32 EscherEx::GetPersistOffset( sal_uInt32 nKey )
5232 {
5233     return PtGetOffsetByID( ESCHER_Persist_PrivateEntry | nKey );
5234 }
5235 
5236 // ---------------------------------------------------------------------------------------------
5237 
DoSeek(sal_uInt32 nKey)5238 sal_Bool EscherEx::DoSeek( sal_uInt32 nKey )
5239 {
5240 	sal_uInt32 nPos = PtGetOffsetByID( nKey );
5241 	if ( nPos )
5242 		mpOutStrm->Seek( nPos );
5243 	else
5244 	{
5245 		if (! PtIsID( nKey ) )
5246 			return sal_False;
5247 		mpOutStrm->Seek( 0 );
5248 	}
5249 	return sal_True;
5250 }
5251 
5252 // ---------------------------------------------------------------------------------------------
5253 
SeekToPersistOffset(sal_uInt32 nKey)5254 sal_Bool EscherEx::SeekToPersistOffset( sal_uInt32 nKey )
5255 {
5256 	return DoSeek( ESCHER_Persist_PrivateEntry | nKey );
5257 }
5258 
5259 // ---------------------------------------------------------------------------------------------
5260 
InsertAtPersistOffset(sal_uInt32 nKey,sal_uInt32 nValue)5261 sal_Bool EscherEx::InsertAtPersistOffset( sal_uInt32 nKey, sal_uInt32 nValue )
5262 {
5263 	sal_uInt32	nOldPos = mpOutStrm->Tell();
5264 	sal_Bool	bRetValue = SeekToPersistOffset( nKey );
5265 	if ( bRetValue )
5266 	{
5267 		*mpOutStrm << nValue;
5268 		mpOutStrm->Seek( nOldPos );
5269 	}
5270 	return bRetValue;
5271 }
5272 
5273 // ---------------------------------------------------------------------------------------------
5274 
OpenContainer(sal_uInt16 nEscherContainer,int nRecInstance)5275 void EscherEx::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
5276 {
5277 	*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | 0xf  ) << nEscherContainer << (sal_uInt32)0;
5278 	mOffsets.push_back( mpOutStrm->Tell() - 4 );
5279 	mRecTypes.push_back( nEscherContainer );
5280 	switch( nEscherContainer )
5281 	{
5282 		case ESCHER_DggContainer :
5283 		{
5284             mxGlobal->SetDggContainer();
5285 			mnCurrentDg	= 0;
5286             /*  Remember the current position as start position of the DGG
5287                 record and BSTORECONTAINER, but do not write them actually.
5288                 This will be done later in Flush() when the number of drawings,
5289                 the size and contents of the FIDCL cluster table, and the size
5290                 of the BLIP container are known. */
5291 			PtReplaceOrInsert( ESCHER_Persist_Dgg, mpOutStrm->Tell() );
5292 		}
5293 		break;
5294 
5295 		case ESCHER_DgContainer :
5296 		{
5297             if ( mxGlobal->HasDggContainer() )
5298 			{
5299 				if ( !mbEscherDg )
5300 				{
5301 					mbEscherDg = sal_True;
5302                     mnCurrentDg = mxGlobal->GenerateDrawingId();
5303 					AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
5304 					PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
5305 					*mpOutStrm << (sal_uInt32)0		// The number of shapes in this drawing
5306 							   << (sal_uInt32)0;	// The last MSOSPID given to an SP in this DG
5307 				}
5308 			}
5309 		}
5310 		break;
5311 
5312 		case ESCHER_SpgrContainer :
5313 		{
5314 			if ( mbEscherDg )
5315 			{
5316 				mbEscherSpgr = sal_True;
5317 			}
5318 		}
5319 		break;
5320 
5321 		case ESCHER_SpContainer :
5322 		{
5323 		}
5324 		break;
5325 
5326 		default:
5327 		break;
5328 	}
5329 }
5330 
5331 // ---------------------------------------------------------------------------------------------
5332 
CloseContainer()5333 void EscherEx::CloseContainer()
5334 {
5335 	sal_uInt32 nSize, nPos = mpOutStrm->Tell();
5336 	nSize = ( nPos - mOffsets.back() ) - 4;
5337 	mpOutStrm->Seek( mOffsets.back() );
5338 	*mpOutStrm << nSize;
5339 
5340 	switch( mRecTypes.back() )
5341 	{
5342 		case ESCHER_DgContainer :
5343 		{
5344 			if ( mbEscherDg )
5345 			{
5346 				mbEscherDg = sal_False;
5347 				if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
5348                     *mpOutStrm << mxGlobal->GetDrawingShapeCount( mnCurrentDg ) << mxGlobal->GetLastShapeId( mnCurrentDg );
5349 			}
5350 		}
5351 		break;
5352 
5353 		case ESCHER_SpgrContainer :
5354 		{
5355 			if ( mbEscherSpgr )
5356 			{
5357 				mbEscherSpgr = sal_False;
5358 
5359 			}
5360 		}
5361 		break;
5362 
5363 		default:
5364 		break;
5365 	}
5366 	mOffsets.pop_back();
5367 	mRecTypes.pop_back();
5368 	mpOutStrm->Seek( nPos );
5369 }
5370 
5371 // ---------------------------------------------------------------------------------------------
5372 
BeginAtom()5373 void EscherEx::BeginAtom()
5374 {
5375 	mnCountOfs = mpOutStrm->Tell();
5376 	*mpOutStrm << (sal_uInt32)0 << (sal_uInt32)0;		// record header wird spaeter geschrieben
5377 }
5378 
5379 // ---------------------------------------------------------------------------------------------
5380 
EndAtom(sal_uInt16 nRecType,int nRecVersion,int nRecInstance)5381 void EscherEx::EndAtom( sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
5382 {
5383 	sal_uInt32	nOldPos = mpOutStrm->Tell();
5384 	mpOutStrm->Seek( mnCountOfs );
5385 	sal_uInt32 nSize = nOldPos - mnCountOfs;
5386 	*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << (sal_uInt32)( nSize - 8 );
5387 	mpOutStrm->Seek( nOldPos );
5388 }
5389 
5390 // ---------------------------------------------------------------------------------------------
5391 
AddAtom(sal_uInt32 nAtomSize,sal_uInt16 nRecType,int nRecVersion,int nRecInstance)5392 void EscherEx::AddAtom( sal_uInt32 nAtomSize, sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
5393 {
5394 	*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << nAtomSize;
5395 }
5396 
5397 // ---------------------------------------------------------------------------------------------
5398 
AddChildAnchor(const Rectangle & rRect)5399 void EscherEx::AddChildAnchor( const Rectangle& rRect )
5400 {
5401     AddAtom( 16, ESCHER_ChildAnchor );
5402     *mpOutStrm  << (sal_Int32)rRect.Left()
5403                 << (sal_Int32)rRect.Top()
5404                 << (sal_Int32)rRect.Right()
5405                 << (sal_Int32)rRect.Bottom();
5406 }
5407 
5408 // ---------------------------------------------------------------------------------------------
5409 
AddClientAnchor(const Rectangle & rRect)5410 void EscherEx::AddClientAnchor( const Rectangle& rRect )
5411 {
5412 	AddAtom( 8, ESCHER_ClientAnchor );
5413     *mpOutStrm << (sal_Int16)rRect.Top()
5414                << (sal_Int16)rRect.Left()
5415                << (sal_Int16)( rRect.GetWidth()  + rRect.Left() )
5416                << (sal_Int16)( rRect.GetHeight() + rRect.Top() );
5417 }
5418 
5419 // ---------------------------------------------------------------------------------------------
5420 
EnterAdditionalTextGroup()5421 EscherExHostAppData* EscherEx::EnterAdditionalTextGroup()
5422 {
5423 	return NULL;
5424 }
5425 
5426 // ---------------------------------------------------------------------------------------------
5427 
EnterGroup(const String & rShapeName,const Rectangle * pBoundRect)5428 sal_uInt32 EscherEx::EnterGroup( const String& rShapeName, const Rectangle* pBoundRect )
5429 {
5430 	Rectangle aRect;
5431 	if( pBoundRect )
5432 		aRect = *pBoundRect;
5433 
5434 	OpenContainer( ESCHER_SpgrContainer );
5435 	OpenContainer( ESCHER_SpContainer );
5436 	AddAtom( 16, ESCHER_Spgr, 1 );
5437 	PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel,
5438 						mpOutStrm->Tell() );
5439 	*mpOutStrm	<< (sal_Int32)aRect.Left()	// Bounding box fuer die Gruppierten shapes an die sie attached werden
5440 				<< (sal_Int32)aRect.Top()
5441 				<< (sal_Int32)aRect.Right()
5442 				<< (sal_Int32)aRect.Bottom();
5443 
5444     sal_uInt32 nShapeId = GenerateShapeId();
5445 	if ( !mnGroupLevel )
5446         AddShape( ESCHER_ShpInst_Min, 5, nShapeId );                    // Flags: Group | Patriarch
5447 	else
5448 	{
5449         AddShape( ESCHER_ShpInst_Min, 0x201, nShapeId );                // Flags: Group | HaveAnchor
5450 		EscherPropertyContainer aPropOpt;
5451 		aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x00040004 );
5452         aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
5453         aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
5454 
5455         // #i51348# shape name
5456         if( rShapeName.Len() > 0 )
5457             aPropOpt.AddOpt( ESCHER_Prop_wzName, rShapeName );
5458 
5459 		Commit( aPropOpt, aRect );
5460 		if ( mnGroupLevel > 1 )
5461             AddChildAnchor( aRect );
5462 
5463 		EscherExHostAppData* pAppData = mpImplEscherExSdr->ImplGetHostData();
5464 		if( pAppData )
5465 		{
5466 			if ( mnGroupLevel <= 1 )
5467 				pAppData->WriteClientAnchor( *this, aRect );
5468 			pAppData->WriteClientData( *this );
5469 		}
5470 	}
5471 	CloseContainer();												// ESCHER_SpContainer
5472 	mnGroupLevel++;
5473     return nShapeId;
5474 }
5475 
EnterGroup(const Rectangle * pBoundRect)5476 sal_uInt32 EscherEx::EnterGroup( const Rectangle* pBoundRect )
5477 {
5478     return EnterGroup( String::EmptyString(), pBoundRect );
5479 }
5480 
5481 // ---------------------------------------------------------------------------------------------
5482 
SetGroupSnapRect(sal_uInt32 nGroupLevel,const Rectangle & rRect)5483 sal_Bool EscherEx::SetGroupSnapRect( sal_uInt32 nGroupLevel, const Rectangle& rRect )
5484 {
5485 	sal_Bool bRetValue = sal_False;
5486 	if ( nGroupLevel )
5487 	{
5488 		sal_uInt32 nCurrentPos = mpOutStrm->Tell();
5489 		if ( DoSeek( ESCHER_Persist_Grouping_Snap | ( nGroupLevel - 1 ) ) )
5490 		{
5491 			*mpOutStrm	<< (sal_Int32)rRect.Left()	// Bounding box fuer die Gruppierten shapes an die sie attached werden
5492 						<< (sal_Int32)rRect.Top()
5493 						<< (sal_Int32)rRect.Right()
5494 						<< (sal_Int32)rRect.Bottom();
5495 			mpOutStrm->Seek( nCurrentPos );
5496 		}
5497 	}
5498 	return bRetValue;
5499 }
5500 
5501 // ---------------------------------------------------------------------------------------------
5502 
SetGroupLogicRect(sal_uInt32 nGroupLevel,const Rectangle & rRect)5503 sal_Bool EscherEx::SetGroupLogicRect( sal_uInt32 nGroupLevel, const Rectangle& rRect )
5504 {
5505 	sal_Bool bRetValue = sal_False;
5506 	if ( nGroupLevel )
5507 	{
5508 		sal_uInt32 nCurrentPos = mpOutStrm->Tell();
5509 		if ( DoSeek( ESCHER_Persist_Grouping_Logic | ( nGroupLevel - 1 ) ) )
5510 		{
5511 			*mpOutStrm << (sal_Int16)rRect.Top() << (sal_Int16)rRect.Left() << (sal_Int16)rRect.Right() << (sal_Int16)rRect.Bottom();
5512 			mpOutStrm->Seek( nCurrentPos );
5513 		}
5514 	}
5515 	return bRetValue;
5516 }
5517 
5518 // ---------------------------------------------------------------------------------------------
5519 
LeaveGroup()5520 void EscherEx::LeaveGroup()
5521 {
5522 	--mnGroupLevel;
5523 	PtDelete( ESCHER_Persist_Grouping_Snap | mnGroupLevel );
5524 	PtDelete( ESCHER_Persist_Grouping_Logic | mnGroupLevel );
5525 	CloseContainer();
5526 }
5527 
5528 // ---------------------------------------------------------------------------------------------
5529 
AddShape(sal_uInt32 nShpInstance,sal_uInt32 nFlags,sal_uInt32 nShapeID)5530 void EscherEx::AddShape( sal_uInt32 nShpInstance, sal_uInt32 nFlags, sal_uInt32 nShapeID )
5531 {
5532 	AddAtom( 8, ESCHER_Sp, 2, nShpInstance );
5533 
5534 	if ( !nShapeID )
5535         nShapeID = GenerateShapeId();
5536 
5537 	if ( nFlags ^ 1 )							// is this a group shape ?
5538 	{											// if not
5539 		if ( mnGroupLevel > 1 )
5540 			nFlags |= 2;						// this not a topmost shape
5541 	}
5542 	*mpOutStrm << nShapeID << nFlags;
5543 }
5544 
5545 // ---------------------------------------------------------------------------------------------
5546 
Commit(EscherPropertyContainer & rProps,const Rectangle &)5547 void EscherEx::Commit( EscherPropertyContainer& rProps, const Rectangle& )
5548 {
5549 	rProps.Commit( GetStream() );
5550 }
5551 
5552 // ---------------------------------------------------------------------------------------------
5553 
GetColor(const sal_uInt32 nSOColor,sal_Bool bSwap)5554 sal_uInt32 EscherEx::GetColor( const sal_uInt32 nSOColor, sal_Bool bSwap )
5555 {
5556 	if ( bSwap )
5557 	{
5558 		sal_uInt32 nColor = nSOColor & 0xff00;		// GRUEN
5559 		nColor |= (sal_uInt8)( nSOColor ) << 16;		// ROT
5560 		nColor |= (sal_uInt8)( nSOColor >> 16 );		// BLAU
5561 		return nColor;
5562 	}
5563 	else
5564 		return nSOColor & 0xffffff;
5565 }
5566 
5567 // ---------------------------------------------------------------------------------------------
5568 
GetColor(const Color & rSOColor,sal_Bool bSwap)5569 sal_uInt32 EscherEx::GetColor( const Color& rSOColor, sal_Bool bSwap )
5570 {
5571 	sal_uInt32 nColor = ( rSOColor.GetRed() << 16 );
5572 	nColor |= ( rSOColor.GetGreen() << 8 );
5573 	nColor |= rSOColor.GetBlue();
5574 
5575 	if ( !bSwap )
5576 		nColor = GetColor( nColor, sal_True );
5577 
5578 	return nColor;
5579 }
5580 
5581 // ---------------------------------------------------------------------------------------------
5582 
5583