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