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