xref: /trunk/main/filter/source/msfilter/escherex.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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             //transparency 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 flipped 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     {   // vertical 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 ArrowLength 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