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