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