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