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