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