Update ooo320-m1
[ooovba.git] / svx / source / msfilter / escherex.cxx
blob2da3fed7edb792b3fd8db9fe01a31377e4d3b98c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: escherex.cxx,v $
10 * $Revision: 1.77.64.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include "impgrf.hxx"
34 #include "eschesdo.hxx"
35 #include <svx/escherex.hxx>
36 #include <unoapi.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdoashp.hxx>
39 #include <svx/svdoole2.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <vcl/gradient.hxx>
42 #include <vcl/graph.hxx>
43 #include <vcl/cvtgrf.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/wrkwin.hxx>
46 #include <tools/stream.hxx>
47 #include <tools/zcodec.hxx>
48 #include <svx/svdopath.hxx>
49 #include <stdlib.h>
50 #include <svtools/filter.hxx>
51 #include "../customshapes/EnhancedCustomShapeTypeNames.hxx"
52 #include "../customshapes/EnhancedCustomShapeGeometry.hxx"
53 #include <EnhancedCustomShapeFunctionParser.hxx>
54 #include "../customshapes/EnhancedCustomShape2d.hxx"
55 #include <com/sun/star/beans/PropertyValues.hpp>
56 #include <com/sun/star/beans/XPropertyState.hpp>
57 #include <com/sun/star/awt/GradientStyle.hpp>
58 #include <com/sun/star/awt/RasterOperation.hpp>
59 #include <com/sun/star/awt/Gradient.hpp>
60 #include <com/sun/star/drawing/LineStyle.hpp>
61 #include <com/sun/star/drawing/LineJoint.hpp>
62 #include <com/sun/star/drawing/FillStyle.hpp>
63 #include <com/sun/star/drawing/LineDash.hpp>
64 #include <com/sun/star/drawing/BezierPoint.hpp>
65 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
66 #include <com/sun/star/drawing/ConnectorType.hpp>
67 #include <com/sun/star/drawing/ConnectionType.hpp>
68 #include <com/sun/star/drawing/CircleKind.hpp>
69 #include <com/sun/star/drawing/PointSequence.hpp>
70 #include <com/sun/star/drawing/FlagSequence.hpp>
71 #include <com/sun/star/drawing/PolygonFlags.hpp>
72 #include <com/sun/star/text/WritingMode.hpp>
73 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
74 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
75 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
76 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
77 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
78 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
79 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
80 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
81 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
82 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
83 #include <com/sun/star/drawing/ProjectionMode.hpp>
84 #include <com/sun/star/text/XSimpleText.hpp>
85 #include <com/sun/star/drawing/ShadeMode.hpp>
86 #include <vcl/hatch.hxx>
87 #include <com/sun/star/awt/XGraphics.hpp>
88 #include <com/sun/star/awt/FontSlant.hpp>
89 #include <com/sun/star/awt/FontWeight.hpp>
90 #include <com/sun/star/drawing/ColorMode.hpp>
91 #include <com/sun/star/drawing/Position3D.hpp>
92 #include <com/sun/star/drawing/Direction3D.hpp>
93 #include <com/sun/star/text/GraphicCrop.hpp>
94 #include <unotools/ucbstreamhelper.hxx>
95 #include <unotools/localfilehelper.hxx>
96 #include <comphelper/extract.hxx>
97 #include <toolkit/unohlp.hxx>
98 #include <vcl/virdev.hxx>
99 #include <rtl/crc.h>
100 #include <vos/xception.hxx>
101 #ifndef _VOS_NO_NAMESPACE
102 using namespace vos;
103 #endif
105 using namespace ::rtl;
106 using namespace ::com::sun::star;
109 // ---------------------------------------------------------------------------------------------
111 EscherExContainer::EscherExContainer( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance ) :
112 rStrm ( rSt )
114 rStrm << (sal_uInt32)( ( 0xf | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0;
115 nContPos = rStrm.Tell();
117 EscherExContainer::~EscherExContainer()
119 sal_uInt32 nPos = rStrm.Tell();
120 sal_uInt32 nSize= nPos - nContPos;
121 if ( nSize )
123 rStrm.Seek( nContPos - 4 );
124 rStrm << nSize;
125 rStrm.Seek( nPos );
129 EscherExAtom::EscherExAtom( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance, const sal_uInt8 nVersion ) :
130 rStrm ( rSt )
132 rStrm << (sal_uInt32)( ( nVersion | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0;
133 nContPos = rStrm.Tell();
135 EscherExAtom::~EscherExAtom()
137 sal_uInt32 nPos = rStrm.Tell();
138 sal_uInt32 nSize= nPos - nContPos;
139 if ( nSize )
141 rStrm.Seek( nContPos - 4 );
142 rStrm << nSize;
143 rStrm.Seek( nPos );
147 // ---------------------------------------------------------------------------------------------
149 EscherExClientRecord_Base::~EscherExClientRecord_Base()
153 EscherExClientAnchor_Base::~EscherExClientAnchor_Base()
157 // ---------------------------------------------------------------------------------------------
159 void EscherPropertyContainer::ImplInit()
161 nSortCount = 0;
162 nCountCount = 0;
163 nCountSize = 0;
164 nSortBufSize = 64;
165 bHasComplexData = sal_False;
166 bSuppressRotation = sal_False;
167 pSortStruct = new EscherPropSortStruct[ nSortBufSize ];
170 EscherPropertyContainer::EscherPropertyContainer() :
171 pGraphicProvider ( NULL ),
172 pPicOutStrm ( NULL )
174 ImplInit();
177 EscherPropertyContainer::EscherPropertyContainer(
178 EscherGraphicProvider& rGraphProv,
179 SvStream* pPiOutStrm,
180 Rectangle& rBoundRect ) :
182 pGraphicProvider ( &rGraphProv ),
183 pPicOutStrm ( pPiOutStrm ),
184 pShapeBoundRect ( &rBoundRect )
186 ImplInit();
189 EscherPropertyContainer::~EscherPropertyContainer()
191 if ( bHasComplexData )
193 while ( nSortCount-- )
194 delete[] pSortStruct[ nSortCount ].pBuf;
196 delete[] pSortStruct;
199 void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_uInt32 nPropValue, sal_Bool bBlib )
201 AddOpt( nPropID, bBlib, nPropValue, NULL, 0 );
204 void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, const rtl::OUString& rString )
206 sal_Int32 j, i, nLen = rString.getLength() * 2 + 2;
207 sal_uInt8* pBuf = new sal_uInt8[ nLen ];
208 for ( j = i = 0; i < rString.getLength(); i++ )
210 sal_uInt16 nChar = (sal_uInt16)rString[ i ];
211 pBuf[ j++ ] = (sal_uInt8)nChar;
212 pBuf[ j++ ] = (sal_uInt8)( nChar >> 8 );
214 pBuf[ j++ ] = 0;
215 pBuf[ j++ ] = 0;
216 AddOpt( nPropID, sal_True, nLen, pBuf, nLen );
219 void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_Bool bBlib, sal_uInt32 nPropValue, sal_uInt8* pProp, sal_uInt32 nPropSize )
221 if ( bBlib ) // bBlib is only valid when fComplex = 0
222 nPropID |= 0x4000;
223 if ( pProp )
224 nPropID |= 0x8000; // fComplex = TRUE;
226 sal_uInt32 i;
227 for( i = 0; i < nSortCount; i++ )
229 if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropID &~0xc000 ) ) // pruefen, ob Property nur ersetzt wird
231 pSortStruct[ i ].nPropId = nPropID;
232 if ( pSortStruct[ i ].pBuf )
234 nCountSize -= pSortStruct[ i ].nPropSize;
235 delete[] pSortStruct[ i ].pBuf;
237 pSortStruct[ i ].pBuf = pProp;
238 pSortStruct[ i ].nPropSize = nPropSize;
239 pSortStruct[ i ].nPropValue = nPropValue;
240 if ( pProp )
241 nCountSize += nPropSize;
242 return;
245 nCountCount++;
246 nCountSize += 6;
247 if ( nSortCount == nSortBufSize ) // buffer vergroessern
249 nSortBufSize <<= 1;
250 EscherPropSortStruct* pTemp = new EscherPropSortStruct[ nSortBufSize ];
251 for( i = 0; i < nSortCount; i++ )
253 pTemp[ i ] = pSortStruct[ i ];
255 delete pSortStruct;
256 pSortStruct = pTemp;
258 pSortStruct[ nSortCount ].nPropId = nPropID; // property einfuegen
259 pSortStruct[ nSortCount ].pBuf = pProp;
260 pSortStruct[ nSortCount ].nPropSize = nPropSize;
261 pSortStruct[ nSortCount++ ].nPropValue = nPropValue;
263 if ( pProp )
265 nCountSize += nPropSize;
266 bHasComplexData = sal_True;
270 sal_Bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, sal_uInt32& rPropValue ) const
272 EscherPropSortStruct aPropStruct;
274 if ( GetOpt( nPropId, aPropStruct ) )
276 rPropValue = aPropStruct.nPropValue;
277 return sal_True;
279 return sal_False;
282 sal_Bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, EscherPropSortStruct& rPropValue ) const
284 for( sal_uInt32 i = 0; i < nSortCount; i++ )
286 if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropId &~0xc000 ) )
288 rPropValue = pSortStruct[ i ];
289 return sal_True;
292 return sal_False;
295 EscherProperties EscherPropertyContainer::GetOpts() const
297 EscherProperties aVector;
299 for ( sal_uInt32 i = 0; i < nSortCount; ++i )
300 aVector.push_back( pSortStruct[ i ] );
302 return aVector;
305 extern "C" int __LOADONCALLAPI EscherPropSortFunc( const void* p1, const void* p2 )
307 INT16 nID1 = ((EscherPropSortStruct*)p1)->nPropId &~0xc000;
308 INT16 nID2 = ((EscherPropSortStruct*)p2)->nPropId &~0xc000;
310 if( nID1 < nID2 )
311 return -1;
312 else if( nID1 > nID2 )
313 return 1;
314 else
315 return 0;
318 void EscherPropertyContainer::Commit( SvStream& rSt, sal_uInt16 nVersion, sal_uInt16 nRecType )
320 rSt << (sal_uInt16)( ( nCountCount << 4 ) | ( nVersion & 0xf ) ) << nRecType << nCountSize;
321 if ( nSortCount )
323 qsort( pSortStruct, nSortCount, sizeof( EscherPropSortStruct ), EscherPropSortFunc );
324 sal_uInt32 i;
326 for ( i = 0; i < nSortCount; i++ )
328 sal_uInt32 nPropValue = pSortStruct[ i ].nPropValue;
329 sal_uInt16 nPropId = pSortStruct[ i ].nPropId;
331 if ( bSuppressRotation && ( nPropId == ESCHER_Prop_Rotation ) )
332 nPropValue = 0;
334 rSt << nPropId
335 << nPropValue;
337 if ( bHasComplexData )
339 for ( i = 0; i < nSortCount; i++ )
341 if ( pSortStruct[ i ].pBuf )
342 rSt.Write( pSortStruct[ i ].pBuf, pSortStruct[ i ].nPropSize );
348 sal_Bool EscherPropertyContainer::IsFontWork() const
350 sal_uInt32 nTextPathFlags = 0;
351 GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
352 return ( nTextPathFlags & 0x4000 ) != 0;
355 sal_uInt32 EscherPropertyContainer::ImplGetColor( const sal_uInt32 nSOColor, sal_Bool bSwap )
357 if ( bSwap )
359 sal_uInt32 nColor = nSOColor & 0xff00; // GRUEN
360 nColor |= (sal_uInt8)( nSOColor ) << 16; // ROT
361 nColor |= (sal_uInt8)( nSOColor >> 16 ); // BLAU
362 return nColor;
364 else
365 return nSOColor & 0xffffff;
368 sal_uInt32 EscherPropertyContainer::GetGradientColor(
369 const ::com::sun::star::awt::Gradient* pGradient,
370 sal_uInt32 nStartColor )
372 sal_uInt32 nIntensity = 100;
373 Color aColor;
375 if ( pGradient )
377 if ( nStartColor & 1 )
379 nIntensity = pGradient->StartIntensity;
380 aColor = pGradient->StartColor;
382 else
384 nIntensity = pGradient->EndIntensity;
385 aColor = pGradient->EndColor;
388 sal_uInt32 nRed = ( ( aColor.GetRed() * nIntensity ) / 100 );
389 sal_uInt32 nGreen = ( ( aColor.GetGreen() * nIntensity ) / 100 ) << 8;
390 sal_uInt32 nBlue = ( ( aColor.GetBlue() * nIntensity ) / 100 ) << 16;
391 return nRed | nGreen | nBlue;
394 void EscherPropertyContainer::CreateGradientProperties(
395 const ::com::sun::star::awt::Gradient & rGradient )
397 sal_uInt32 nFillType = ESCHER_FillShadeScale;
398 sal_uInt32 nAngle = 0;
399 sal_uInt32 nFillFocus = 0;
400 sal_uInt32 nFillLR = 0;
401 sal_uInt32 nFillTB = 0;
402 sal_uInt32 nFirstColor = 0;
403 bool bWriteFillTo = false;
405 switch ( rGradient.Style )
407 case ::com::sun::star::awt::GradientStyle_LINEAR :
408 case ::com::sun::star::awt::GradientStyle_AXIAL :
410 nFillType = ESCHER_FillShadeScale;
411 nAngle = (rGradient.Angle * 0x10000) / 10;
412 nFillFocus = (sal::static_int_cast<int>(rGradient.Style) ==
413 sal::static_int_cast<int>(GradientStyle_LINEAR)) ? 0 : 50;
415 break;
416 case ::com::sun::star::awt::GradientStyle_RADIAL :
417 case ::com::sun::star::awt::GradientStyle_ELLIPTICAL :
418 case ::com::sun::star::awt::GradientStyle_SQUARE :
419 case ::com::sun::star::awt::GradientStyle_RECT :
421 nFillLR = (rGradient.XOffset * 0x10000) / 100;
422 nFillTB = (rGradient.YOffset * 0x10000) / 100;
423 if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) )
424 nFillType = ESCHER_FillShadeShape;
425 else
426 nFillType = ESCHER_FillShadeCenter;
427 nFirstColor = 1;
428 bWriteFillTo = true;
430 break;
431 case ::com::sun::star::awt::GradientStyle_MAKE_FIXED_SIZE : break;
433 AddOpt( ESCHER_Prop_fillType, nFillType );
434 AddOpt( ESCHER_Prop_fillAngle, nAngle );
435 AddOpt( ESCHER_Prop_fillColor, GetGradientColor( &rGradient, nFirstColor ) );
436 AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( &rGradient, nFirstColor ^ 1 ) );
437 AddOpt( ESCHER_Prop_fillFocus, nFillFocus );
438 if ( bWriteFillTo )
440 AddOpt( ESCHER_Prop_fillToLeft, nFillLR );
441 AddOpt( ESCHER_Prop_fillToTop, nFillTB );
442 AddOpt( ESCHER_Prop_fillToRight, nFillLR );
443 AddOpt( ESCHER_Prop_fillToBottom, nFillTB );
447 void EscherPropertyContainer::CreateGradientProperties(
448 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet )
450 ::com::sun::star::uno::Any aAny;
451 ::com::sun::star::awt::Gradient aGradient;
452 if ( EscherPropertyValueHelper::GetPropertyValue(
453 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillGradient" ) ), sal_False ) )
455 aGradient = *static_cast< const ::com::sun::star::awt::Gradient* >( aAny.getValue() );
457 CreateGradientProperties( aGradient );
460 void EscherPropertyContainer::CreateFillProperties(
461 const uno::Reference< beans::XPropertySet > & rXPropSet,
462 sal_Bool bEdge )
464 ::com::sun::star::uno::Any aAny;
465 AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
466 AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
468 sal_uInt32 nFillBackColor = 0;
470 const rtl::OUString aPropName( String( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" ) ) );
471 if ( EscherPropertyValueHelper::GetPropertyValue(
472 aAny, rXPropSet, aPropName, sal_False ) )
474 ::com::sun::star::drawing::FillStyle eFS;
475 if ( ! ( aAny >>= eFS ) )
476 eFS = ::com::sun::star::drawing::FillStyle_SOLID;
477 switch( eFS )
479 case ::com::sun::star::drawing::FillStyle_GRADIENT :
481 CreateGradientProperties( rXPropSet );
482 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
484 break;
486 case ::com::sun::star::drawing::FillStyle_BITMAP :
488 CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ), sal_True );
489 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
490 AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
492 break;
493 case ::com::sun::star::drawing::FillStyle_HATCH :
495 CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ), sal_True );
497 break;
498 case ::com::sun::star::drawing::FillStyle_SOLID :
499 default:
501 ::com::sun::star::beans::PropertyState ePropState = EscherPropertyValueHelper::GetPropertyState(
502 rXPropSet, aPropName );
503 if ( ePropState == ::com::sun::star::beans::PropertyState_DIRECT_VALUE )
504 AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
506 if ( EscherPropertyValueHelper::GetPropertyValue(
507 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), sal_False ) )
509 sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) );
510 nFillBackColor = nFillColor ^ 0xffffff;
511 AddOpt( ESCHER_Prop_fillColor, nFillColor );
513 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
514 AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
515 break;
517 case ::com::sun::star::drawing::FillStyle_NONE :
518 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
519 break;
521 if ( eFS != ::com::sun::star::drawing::FillStyle_NONE )
523 sal_uInt16 nTransparency = ( EscherPropertyValueHelper::GetPropertyValue(
524 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparence" ) ), sal_True ) )
525 ? *((sal_Int16*)aAny.getValue() )
526 : 0;
527 if ( nTransparency )
528 AddOpt( ESCHER_Prop_fillOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
531 CreateLineProperties( rXPropSet, bEdge );
534 void EscherPropertyContainer::CreateTextProperties(
535 const uno::Reference< beans::XPropertySet > & rXPropSet, sal_uInt32 nTextId,
536 const sal_Bool bIsCustomShape, const sal_Bool bIsTextFrame )
538 uno::Any aAny;
539 text::WritingMode eWM( text::WritingMode_LR_TB );
540 drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP );
541 drawing::TextHorizontalAdjust eHA( drawing::TextHorizontalAdjust_LEFT );
543 sal_Int32 nLeft ( 0 );
544 sal_Int32 nTop ( 0 );
545 sal_Int32 nRight ( 0 );
546 sal_Int32 nBottom ( 0 );
548 // used with normal shapes:
549 sal_Bool bAutoGrowWidth ( sal_False );
550 sal_Bool bAutoGrowHeight ( sal_False );
551 // used with ashapes:
552 sal_Bool bWordWrap ( sal_False );
553 sal_Bool bAutoGrowSize ( sal_False );
555 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWritingMode" ) ), sal_True ) )
556 aAny >>= eWM;
557 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextVerticalAdjust" ) ), sal_True ) )
558 aAny >>= eVA;
559 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), sal_True ) )
560 aAny >>= eHA;
561 if ( bIsCustomShape )
563 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWordWrap" ) ), sal_False ) )
564 aAny >>= bWordWrap;
565 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), sal_True ) )
566 aAny >>= bAutoGrowSize;
568 else if ( bIsTextFrame )
570 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowWidth" ) ), sal_True ) )
571 aAny >>= bAutoGrowWidth;
573 // i63936 not setting autogrowheight, because otherwise
574 // the minframeheight of the text will be ignored
576 // if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), sal_True ) )
577 // aAny >>= bAutoGrowHeight;
579 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ) ) )
580 aAny >>= nLeft;
581 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ) ) )
582 aAny >>= nTop;
583 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ) ) )
584 aAny >>= nRight;
585 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ) ) )
586 aAny >>= nBottom;
589 if ( rObj.ImplGetPropertyValue(
590 ::rtl::OUString::createFromAscii("TextWritingMode") ) )
592 ::com::sun::star::text::WritingMode eMode;
593 rObj.GetUsrAny() >>= eMode;
594 switch (eMode)
596 case ::com::sun::star::text::WritingMode_TB_RL:
597 //Well if it so happens that we are fliped 180 we can use
598 //this instead.
599 if (rObj.GetAngle() == 18000)
600 eFlow = ESCHER_txflBtoT;
601 else
602 eFlow = ESCHER_txflTtoBA;
603 break;
604 case ::com::sun::star::text::WritingMode_RL_TB:
605 eDir = ESCHER_txdirRTL;
606 break;
611 ESCHER_AnchorText eAnchor = ESCHER_AnchorTop;
612 ESCHER_WrapMode eWrapMode = ESCHER_WrapSquare;
613 sal_uInt32 nTextAttr = 0x40004; // rotate text with shape
615 if ( eWM == text::WritingMode_TB_RL )
616 { // verical writing
617 switch ( eHA )
619 case drawing::TextHorizontalAdjust_LEFT :
620 eAnchor = ESCHER_AnchorBottom;
621 break;
622 case drawing::TextHorizontalAdjust_CENTER :
623 eAnchor = ESCHER_AnchorMiddle;
624 break;
625 default :
626 case drawing::TextHorizontalAdjust_BLOCK :
627 case drawing::TextHorizontalAdjust_RIGHT :
628 eAnchor = ESCHER_AnchorTop;
629 break;
631 if ( eVA == drawing::TextVerticalAdjust_CENTER )
633 switch ( eAnchor )
635 case ESCHER_AnchorMiddle :
636 eAnchor = ESCHER_AnchorMiddleCentered;
637 break;
638 case ESCHER_AnchorBottom :
639 eAnchor = ESCHER_AnchorBottomCentered;
640 break;
641 default :
642 case ESCHER_AnchorTop :
643 eAnchor = ESCHER_AnchorTopCentered;
644 break;
647 if ( bIsCustomShape )
649 if ( bWordWrap )
650 eWrapMode = ESCHER_WrapSquare;
651 else
652 eWrapMode = ESCHER_WrapNone;
653 if ( bAutoGrowSize )
654 nTextAttr |= 0x20002;
656 else
658 if ( bAutoGrowHeight )
659 eWrapMode = ESCHER_WrapNone;
660 if ( bAutoGrowWidth )
661 nTextAttr |= 0x20002;
664 AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflTtoBA ); // rotate text within shape by 90
666 else
667 { // normal from left to right
668 switch ( eVA )
670 case drawing::TextVerticalAdjust_CENTER :
671 eAnchor = ESCHER_AnchorMiddle;
672 break;
674 case drawing::TextVerticalAdjust_BOTTOM :
675 eAnchor = ESCHER_AnchorBottom;
676 break;
678 default :
679 case drawing::TextVerticalAdjust_TOP :
680 eAnchor = ESCHER_AnchorTop;
681 break;
683 if ( eHA == drawing::TextHorizontalAdjust_CENTER )
685 switch( eAnchor )
687 case ESCHER_AnchorMiddle :
688 eAnchor = ESCHER_AnchorMiddleCentered;
689 break;
690 case ESCHER_AnchorBottom :
691 eAnchor = ESCHER_AnchorBottomCentered;
692 break;
693 case ESCHER_AnchorTop :
694 eAnchor = ESCHER_AnchorTopCentered;
695 break;
696 default: break;
699 if ( bIsCustomShape )
701 if ( bWordWrap )
702 eWrapMode = ESCHER_WrapSquare;
703 else
704 eWrapMode = ESCHER_WrapNone;
705 if ( bAutoGrowSize )
706 nTextAttr |= 0x20002;
708 else
710 if ( bAutoGrowWidth )
711 eWrapMode = ESCHER_WrapNone;
712 if ( bAutoGrowHeight )
713 nTextAttr |= 0x20002;
716 AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
717 AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
718 AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
719 AddOpt( ESCHER_Prop_dyTextBottom, nBottom * 360 );
721 AddOpt( ESCHER_Prop_WrapText, eWrapMode );
722 AddOpt( ESCHER_Prop_AnchorText, eAnchor );
723 AddOpt( ESCHER_Prop_FitTextToShape, nTextAttr );
725 if ( nTextId )
726 AddOpt( ESCHER_Prop_lTxid, nTextId );
728 // n#404221: In case of rotation we need to write the txtflTextFlow
729 // attribute too.
730 if (bIsTextFrame) {
731 sal_uInt16 nAngle = EscherPropertyValueHelper::GetPropertyValue(
732 aAny,
733 rXPropSet,
734 String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ),
735 sal_True )
736 ? (sal_uInt16)( ( *((sal_Int32*)aAny.getValue() ) ) + 5 ) / 10 : 0;
737 if (nAngle==900) {
738 AddOpt( ESCHER_Prop_txflTextFlow, 1 );
739 bSuppressRotation=true;
741 if (nAngle==1800) {
742 AddOpt( ESCHER_Prop_txflTextFlow, 2 );
743 bSuppressRotation=true;
745 if (nAngle==2700) {
746 AddOpt( ESCHER_Prop_txflTextFlow, 3 );
747 bSuppressRotation=true;
752 sal_Bool EscherPropertyContainer::GetLineArrow( const sal_Bool bLineStart,
753 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
754 ESCHER_LineEnd& reLineEnd, sal_Int32& rnArrowLength, sal_Int32& rnArrowWidth )
756 static String sLineStart ( RTL_CONSTASCII_USTRINGPARAM( "LineStart" ) );
757 static String sLineStartName( RTL_CONSTASCII_USTRINGPARAM( "LineStartName" ) );
758 static String sLineEnd ( RTL_CONSTASCII_USTRINGPARAM( "LineEnd" ) );
759 static String sLineEndName ( RTL_CONSTASCII_USTRINGPARAM( "LineEndName" ) );
761 const String sLine ( bLineStart ? sLineStart : sLineEnd );
762 const String sLineName ( bLineStart ? sLineStartName : sLineEndName );
764 sal_Bool bIsArrow = sal_False;
766 ::com::sun::star::uno::Any aAny;
767 if ( EscherPropertyValueHelper::GetPropertyValue(
768 aAny, rXPropSet, sLine, sal_False ) )
770 PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aAny ) );
771 if ( aPolyPoly.Count() && aPolyPoly[ 0 ].GetSize() )
773 bIsArrow = sal_True;
775 reLineEnd = ESCHER_LineArrowEnd;
776 rnArrowLength = 1;
777 rnArrowWidth = 1;
779 if ( EscherPropertyValueHelper::GetPropertyValue(
780 aAny, rXPropSet, sLineName, sal_False ) )
782 String aArrowStartName = *(::rtl::OUString*)aAny.getValue();
783 rtl::OUString aApiName;
784 sal_Int16 nWhich = bLineStart ? XATTR_LINESTART : XATTR_LINEEND;
786 SvxUnogetApiNameForItem( nWhich, aArrowStartName, aApiName );
787 if ( aApiName.getLength() )
790 /* todo:
791 calculate the best option for ArrowLenght and ArrowWidth
793 if ( aApiName.equalsAscii( "Arrow concave" ) )
794 reLineEnd = ESCHER_LineArrowStealthEnd;
795 else if ( aApiName.equalsAscii( "Square 45" ) )
796 reLineEnd = ESCHER_LineArrowDiamondEnd;
797 else if ( aApiName.equalsAscii( "Small Arrow" ) )
798 reLineEnd = ESCHER_LineArrowEnd;
799 else if ( aApiName.equalsAscii( "Dimension Lines" ) )
801 rnArrowLength = 0;
802 rnArrowWidth = 2;
803 reLineEnd = ESCHER_LineArrowOvalEnd;
805 else if ( aApiName.equalsAscii( "Double Arrow" ) )
806 reLineEnd = ESCHER_LineArrowEnd;
807 else if ( aApiName.equalsAscii( "Rounded short Arrow" ) )
808 reLineEnd = ESCHER_LineArrowEnd;
809 else if ( aApiName.equalsAscii( "Symmetric Arrow" ) )
810 reLineEnd = ESCHER_LineArrowEnd;
811 else if ( aApiName.equalsAscii( "Line Arrow" ) )
812 reLineEnd = ESCHER_LineArrowOpenEnd;
813 else if ( aApiName.equalsAscii( "Rounded large Arrow" ) )
814 reLineEnd = ESCHER_LineArrowEnd;
815 else if ( aApiName.equalsAscii( "Circle" ) )
816 reLineEnd = ESCHER_LineArrowOvalEnd;
817 else if ( aApiName.equalsAscii( "Square" ) )
818 reLineEnd = ESCHER_LineArrowDiamondEnd;
819 else if ( aApiName.equalsAscii( "Arrow" ) )
820 reLineEnd = ESCHER_LineArrowEnd;
822 else if ( aArrowStartName.GetTokenCount( ' ' ) == 2 )
824 sal_Bool b = sal_True;
825 String aArrowName( aArrowStartName.GetToken( 0, ' ' ) );
826 if ( aArrowName.EqualsAscii( "msArrowEnd" ) )
827 reLineEnd = ESCHER_LineArrowEnd;
828 else if ( aArrowName.EqualsAscii( "msArrowOpenEnd" ) )
829 reLineEnd = ESCHER_LineArrowOpenEnd;
830 else if ( aArrowName.EqualsAscii( "msArrowStealthEnd" ) )
831 reLineEnd = ESCHER_LineArrowStealthEnd;
832 else if ( aArrowName.EqualsAscii( "msArrowDiamondEnd" ) )
833 reLineEnd = ESCHER_LineArrowDiamondEnd;
834 else if ( aArrowName.EqualsAscii( "msArrowOvalEnd" ) )
835 reLineEnd = ESCHER_LineArrowOvalEnd;
836 else
837 b = sal_False;
839 // now we have the arrow, and try to determine the arrow size;
840 if ( b )
842 String aArrowSize( aArrowStartName.GetToken( 1, ' ' ) );
843 sal_Int32 nArrowSize = aArrowSize.ToInt32();
844 rnArrowWidth = ( nArrowSize - 1 ) / 3;
845 rnArrowLength = nArrowSize - ( rnArrowWidth * 3 ) - 1;
851 return bIsArrow;
854 void EscherPropertyContainer::CreateLineProperties(
855 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
856 sal_Bool bEdge )
858 ::com::sun::star::uno::Any aAny;
859 sal_uInt32 nLineFlags = 0x80008;
861 ESCHER_LineEnd eLineEnd;
862 sal_Int32 nArrowLength;
863 sal_Int32 nArrowWidth;
865 sal_Bool bSwapLineEnds = sal_False;
866 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CircleKind" ) ), sal_True ) )
868 ::com::sun::star::drawing::CircleKind eCircleKind;
869 if ( aAny >>= eCircleKind )
871 if ( eCircleKind == ::com::sun::star::drawing::CircleKind_ARC )
872 bSwapLineEnds = sal_True;
875 if ( GetLineArrow( bSwapLineEnds ? sal_False : sal_True, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
877 AddOpt( ESCHER_Prop_lineStartArrowLength, nArrowLength );
878 AddOpt( ESCHER_Prop_lineStartArrowWidth, nArrowWidth );
879 AddOpt( ESCHER_Prop_lineStartArrowhead, eLineEnd );
880 nLineFlags |= 0x100010;
882 if ( GetLineArrow( bSwapLineEnds ? sal_True : sal_False, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
884 AddOpt( ESCHER_Prop_lineEndArrowLength, nArrowLength );
885 AddOpt( ESCHER_Prop_lineEndArrowWidth, nArrowWidth );
886 AddOpt( ESCHER_Prop_lineEndArrowhead, eLineEnd );
887 nLineFlags |= 0x100010;
889 if ( EscherPropertyValueHelper::GetPropertyValue(
890 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineStyle" ) ), sal_False ) )
892 ::com::sun::star::drawing::LineStyle eLS;
893 if ( aAny >>= eLS )
895 switch ( eLS )
897 case ::com::sun::star::drawing::LineStyle_NONE :
898 AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // 80000
899 break;
901 case ::com::sun::star::drawing::LineStyle_DASH :
903 if ( EscherPropertyValueHelper::GetPropertyValue(
904 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineDash" ) ), sal_False ) )
906 ESCHER_LineDashing eDash = ESCHER_LineSolid;
907 ::com::sun::star::drawing::LineDash* pLineDash = (::com::sun::star::drawing::LineDash*)aAny.getValue();
908 sal_Int32 nDistance = pLineDash->Distance << 1;
909 switch ( pLineDash->Style )
911 case ::com::sun::star::drawing::DashStyle_ROUND :
912 case ::com::sun::star::drawing::DashStyle_ROUNDRELATIVE :
913 AddOpt( ESCHER_Prop_lineEndCapStyle, 0 ); // Style Round setzen
914 break;
915 default : break;
917 if ( ((!(pLineDash->Dots )) || (!(pLineDash->Dashes )) ) || ( pLineDash->DotLen == pLineDash->DashLen ) )
919 sal_Int32 nLen = pLineDash->DotLen;
920 if ( pLineDash->Dashes )
921 nLen = pLineDash->DashLen;
923 if ( nLen >= nDistance )
924 eDash = ESCHER_LineLongDashGEL;
925 else if ( pLineDash->Dots )
926 eDash = ESCHER_LineDotSys;
927 else
928 eDash = ESCHER_LineDashGEL;
930 else // X Y
932 if ( pLineDash->Dots != pLineDash->Dashes )
934 if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
935 eDash = ESCHER_LineLongDashDotDotGEL;
936 else
937 eDash = ESCHER_LineDashDotDotSys;
939 else // X Y Y
941 if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
942 eDash = ESCHER_LineLongDashDotGEL;
943 else
944 eDash = ESCHER_LineDashDotGEL;
948 AddOpt( ESCHER_Prop_lineDashing, eDash );
951 case ::com::sun::star::drawing::LineStyle_SOLID :
952 default:
954 AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
956 break;
959 if ( EscherPropertyValueHelper::GetPropertyValue(
960 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineColor" ) ), sal_False ) )
962 sal_uInt32 nLineColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) );
963 AddOpt( ESCHER_Prop_lineColor, nLineColor );
964 AddOpt( ESCHER_Prop_lineBackColor, nLineColor ^ 0xffffff );
968 sal_uInt32 nLineSize = ( EscherPropertyValueHelper::GetPropertyValue(
969 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineWidth" ) ), sal_False ) )
970 ? *((sal_uInt32*)aAny.getValue())
971 : 0;
972 if ( nLineSize > 1 )
973 AddOpt( ESCHER_Prop_lineWidth, nLineSize * 360 ); // 100TH MM -> PT , 1PT = 12700 EMU
975 ESCHER_LineJoin eLineJoin = ESCHER_LineJoinMiter;
976 if ( EscherPropertyValueHelper::GetPropertyValue(
977 aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineJoint" ) ), sal_True ) )
979 ::com::sun::star::drawing::LineJoint eLJ;
980 if ( aAny >>= eLJ )
982 switch ( eLJ )
984 case com::sun::star::drawing::LineJoint_NONE :
985 case com::sun::star::drawing::LineJoint_MIDDLE :
986 case com::sun::star::drawing::LineJoint_BEVEL :
987 eLineJoin = ESCHER_LineJoinBevel;
988 break;
989 default:
990 case com::sun::star::drawing::LineJoint_MITER :
991 eLineJoin = ESCHER_LineJoinMiter;
992 break;
993 case com::sun::star::drawing::LineJoint_ROUND :
994 eLineJoin = ESCHER_LineJoinRound;
995 break;
999 AddOpt( ESCHER_Prop_lineJoinStyle, eLineJoin );
1001 if ( bEdge == sal_False )
1003 AddOpt( ESCHER_Prop_fFillOK, 0x1001 );
1004 AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
1008 static Size lcl_SizeToEmu(Size aPrefSize, MapMode aPrefMapMode)
1010 Size aRetSize;
1011 if (aPrefMapMode == MAP_PIXEL)
1012 aRetSize = Application::GetDefaultDevice()->PixelToLogic( aPrefSize, MAP_100TH_MM );
1013 else
1014 aRetSize = Application::GetDefaultDevice()->LogicToLogic( aPrefSize, aPrefMapMode, MAP_100TH_MM );
1015 return aRetSize;
1018 void EscherPropertyContainer::ImplCreateGraphicAttributes( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
1019 sal_uInt32 nBlibId, sal_Bool bCreateCroppingAttributes )
1021 ::com::sun::star::uno::Any aAny;
1023 sal_uInt32 nPicFlags = 0;
1024 ::com::sun::star::drawing::ColorMode eColorMode( ::com::sun::star::drawing::ColorMode_STANDARD );
1025 sal_Int16 nLuminance = 0;
1026 sal_Int32 nContrast = 0;
1027 sal_Int16 nRed = 0;
1028 sal_Int16 nGreen = 0;
1029 sal_Int16 nBlue = 0;
1030 double fGamma = 1.0;
1031 sal_Int16 nTransparency = 0;
1033 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicColorMode" ) ) ) )
1034 aAny >>= eColorMode;
1035 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustLuminance" ) ) ) )
1036 aAny >>= nLuminance;
1037 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustContrast" ) ) ) )
1039 sal_Int16 nC = sal_Int16();
1040 aAny >>= nC;
1041 nContrast = nC;
1043 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustRed" ) ) ) )
1044 aAny >>= nRed;
1045 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustGreen" ) ) ) )
1046 aAny >>= nGreen;
1047 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustBlue" ) ) ) )
1048 aAny >>= nBlue;
1049 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Gamma" ) ) ) )
1050 aAny >>= fGamma;
1051 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Transparency" ) ) ) )
1052 aAny >>= nTransparency;
1054 if ( eColorMode == ::com::sun::star::drawing::ColorMode_WATERMARK )
1056 eColorMode = ::com::sun::star::drawing::ColorMode_STANDARD;
1057 nLuminance += 70;
1058 if ( nLuminance > 100 )
1059 nLuminance = 100;
1060 nContrast -= 70;
1061 if ( nContrast < -100 )
1062 nContrast = -100;
1064 if ( eColorMode == ::com::sun::star::drawing::ColorMode_GREYS )
1065 nPicFlags |= 0x40004;
1066 else if ( eColorMode == ::com::sun::star::drawing::ColorMode_MONO )
1067 nPicFlags |= 0x60006;
1069 if ( nContrast )
1071 nContrast += 100;
1072 if ( nContrast == 100)
1073 nContrast = 0x10000;
1074 else if ( nContrast < 100 )
1076 nContrast *= 0x10000;
1077 nContrast /= 100;
1079 else if ( nContrast < 200 )
1080 nContrast = ( 100 * 0x10000 ) / ( 200 - nContrast );
1081 else
1082 nContrast = 0x7fffffff;
1083 AddOpt( ESCHER_Prop_pictureContrast, nContrast );
1085 if ( nLuminance )
1086 AddOpt( ESCHER_Prop_pictureBrightness, nLuminance * 327 );
1087 if ( nPicFlags )
1088 AddOpt( ESCHER_Prop_pictureActive, nPicFlags );
1090 if ( bCreateCroppingAttributes && pGraphicProvider )
1092 Size aPrefSize;
1093 MapMode aPrefMapMode;
1094 if ( pGraphicProvider->GetPrefSize( nBlibId, aPrefSize, aPrefMapMode ) )
1096 Size aCropSize(lcl_SizeToEmu(aPrefSize, aPrefMapMode));
1097 if ( aCropSize.Width() && aCropSize.Height() )
1099 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicCrop" ) ) ) )
1101 ::com::sun::star::text::GraphicCrop aGraphCrop;
1102 if ( aAny >>= aGraphCrop )
1104 if ( aGraphCrop.Left )
1106 sal_uInt32 nLeft = ( aGraphCrop.Left * 65536 ) / aCropSize.Width();
1107 AddOpt( ESCHER_Prop_cropFromLeft, nLeft );
1109 if ( aGraphCrop.Top )
1111 sal_uInt32 nTop = ( aGraphCrop.Top * 65536 ) / aCropSize.Height();
1112 AddOpt( ESCHER_Prop_cropFromTop, nTop );
1114 if ( aGraphCrop.Right )
1116 sal_uInt32 nRight = ( aGraphCrop.Right * 65536 ) / aCropSize.Width();
1117 AddOpt( ESCHER_Prop_cropFromRight, nRight );
1119 if ( aGraphCrop.Bottom )
1121 sal_uInt32 nBottom = ( aGraphCrop.Bottom * 65536 ) / aCropSize.Height();
1122 AddOpt( ESCHER_Prop_cropFromBottom, nBottom );
1131 sal_Bool EscherPropertyContainer::CreateOLEGraphicProperties(
1132 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
1134 sal_Bool bRetValue = sal_False;
1136 if ( rXShape.is() )
1138 SdrObject* pSdrOLE2( GetSdrObjectFromXShape( rXShape ) ); // SJ: leaving unoapi, because currently there is
1139 if ( pSdrOLE2 && pSdrOLE2->ISA( SdrOle2Obj ) ) // no access to the native graphic object
1141 Graphic* pGraphic = ((SdrOle2Obj*)pSdrOLE2)->GetGraphic();
1142 if ( pGraphic )
1144 GraphicObject aGraphicObject( *pGraphic );
1145 ByteString aUniqueId( aGraphicObject.GetUniqueID() );
1146 if ( aUniqueId.Len() )
1148 AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1149 uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
1151 if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect && aXPropSet.is() )
1153 ::com::sun::star::uno::Any aAny;
1154 ::com::sun::star::awt::Rectangle* pVisArea = NULL;
1155 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "VisibleArea" ) ) ) )
1157 pVisArea = new ::com::sun::star::awt::Rectangle;
1158 aAny >>= (*pVisArea);
1160 Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() );
1161 sal_uInt32 nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, pVisArea, NULL );
1162 if ( nBlibId )
1164 AddOpt( ESCHER_Prop_pib, nBlibId, sal_True );
1165 ImplCreateGraphicAttributes( aXPropSet, nBlibId, sal_False );
1166 bRetValue = sal_True;
1168 delete pVisArea;
1174 return bRetValue;
1178 sal_Bool EscherPropertyContainer::ImplCreateEmbeddedBmp( const ByteString& rUniqueId )
1180 if( rUniqueId.Len() > 0 )
1182 EscherGraphicProvider aProvider;
1183 SvMemoryStream aMemStrm;
1184 Rectangle aRect;
1185 if ( aProvider.GetBlibID( aMemStrm, rUniqueId, aRect ) )
1187 // grab BLIP from stream and insert directly as complex property
1188 // ownership of stream memory goes to complex property
1189 aMemStrm.ObjectOwnsMemory( FALSE );
1190 sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData();
1191 sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END );
1192 AddOpt( ESCHER_Prop_fillBlip, sal_True, nSize, pBuf, nSize );
1193 return sal_True;
1196 return sal_False;
1199 sal_Bool EscherPropertyContainer::CreateEmbeddedBitmapProperties(
1200 const ::rtl::OUString& rBitmapUrl, ::com::sun::star::drawing::BitmapMode eBitmapMode )
1202 sal_Bool bRetValue = sal_False;
1203 String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
1204 String aBmpUrl( rBitmapUrl );
1205 xub_StrLen nIndex = aBmpUrl.Search( aVndUrl, 0 );
1206 if( nIndex != STRING_NOTFOUND )
1208 // note: += ist not defined for xub_StrLen -> conversion to int and back to xub_StrLen
1209 nIndex = nIndex + aVndUrl.Len();
1210 if( aBmpUrl.Len() > nIndex )
1212 ByteString aUniqueId( aBmpUrl, nIndex, aBmpUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 );
1213 bRetValue = ImplCreateEmbeddedBmp( aUniqueId );
1214 if( bRetValue )
1216 // bitmap mode property
1217 bool bRepeat = eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT;
1218 AddOpt( ESCHER_Prop_fillType, bRepeat ? ESCHER_FillTexture : ESCHER_FillPicture );
1222 return bRetValue;
1226 namespace {
1228 GraphicObject lclDrawHatch( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground )
1230 const MapMode aMap100( MAP_100TH_MM );
1231 VirtualDevice aVDev( *Application::GetDefaultDevice(), 0, 1 );
1232 aVDev.SetMapMode( aMap100 );
1234 const Size aOutSize = aVDev.PixelToLogic( Size( 28, 28 ) );
1235 aVDev.SetOutputSize( aOutSize );
1237 Rectangle aRectangle( Point( 0, 0 ), aOutSize );
1238 const PolyPolygon aPolyPoly( aRectangle );
1240 aVDev.SetLineColor();
1241 aVDev.SetFillColor( bFillBackground ? rBackColor : Color( COL_TRANSPARENT ) );
1242 aVDev.DrawRect( Rectangle( Point(), aOutSize ) );
1244 Hatch aVclHatch( (HatchStyle) rHatch.Style, Color( rHatch.Color ), rHatch.Distance, (sal_uInt16)rHatch.Angle );
1245 aVDev.DrawHatch( aPolyPoly, aVclHatch );
1247 return GraphicObject( Graphic( aVDev.GetBitmapEx( Point(), aOutSize ) ) );
1250 } // namespace
1253 sal_Bool EscherPropertyContainer::CreateEmbeddedHatchProperties( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground )
1255 GraphicObject aGraphicObject = lclDrawHatch( rHatch, rBackColor, bFillBackground );
1256 ByteString aUniqueId = aGraphicObject.GetUniqueID();
1257 sal_Bool bRetValue = ImplCreateEmbeddedBmp( aUniqueId );
1258 if ( bRetValue )
1259 AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
1260 return bRetValue;
1264 sal_Bool EscherPropertyContainer::CreateGraphicProperties(
1265 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
1266 const String& rSource, const sal_Bool bCreateFillBitmap, const sal_Bool bCreateCroppingAttributes,
1267 const sal_Bool bFillBitmapModeAllowed )
1269 sal_Bool bRetValue = sal_False;
1270 sal_Bool bCreateFillStyles = sal_False;
1272 sal_Bool bMirrored = sal_False;
1273 sal_Bool bRotate = sal_True;
1274 sal_uInt16 nAngle = 0;
1275 GraphicAttr* pGraphicAttr = NULL;
1276 GraphicObject aGraphicObject;
1277 String aGraphicUrl;
1278 ByteString aUniqueId;
1279 bool bIsGraphicMtf(false);
1281 ::com::sun::star::drawing::BitmapMode eBitmapMode( ::com::sun::star::drawing::BitmapMode_NO_REPEAT );
1282 ::com::sun::star::uno::Any aAny;
1284 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, rSource ) )
1286 if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ) )
1288 ::com::sun::star::uno::Sequence<sal_uInt8> aSeq = *(::com::sun::star::uno::Sequence<sal_uInt8>*)aAny.getValue();
1289 const sal_uInt8* pAry = aSeq.getArray();
1290 sal_uInt32 nAryLen = aSeq.getLength();
1292 // the metafile is already rotated
1293 bRotate = sal_False;
1295 if ( pAry && nAryLen )
1297 Graphic aGraphic;
1298 SvMemoryStream aTemp( (void*)pAry, nAryLen, STREAM_READ );
1299 sal_uInt32 nErrCode = GraphicConverter::Import( aTemp, aGraphic, CVT_WMF );
1300 if ( nErrCode == ERRCODE_NONE )
1302 aGraphicObject = aGraphic;
1303 aUniqueId = aGraphicObject.GetUniqueID();
1304 bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
1308 else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ) )
1310 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >xBitmap;
1311 if ( ::cppu::extractInterface( xBitmap, aAny ) )
1313 ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > xBmp;
1314 if ( aAny >>= xBmp )
1316 BitmapEx aBitmapEx( VCLUnoHelper::GetBitmap( xBmp ) );
1317 Graphic aGraphic( aBitmapEx );
1318 aGraphicObject = aGraphic;
1319 aUniqueId = aGraphicObject.GetUniqueID();
1320 bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
1324 else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ) )
1326 aGraphicUrl = *(::rtl::OUString*)aAny.getValue();
1328 else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) )
1330 aGraphicUrl = *(::rtl::OUString*)aAny.getValue();
1331 bCreateFillStyles = sal_True;
1333 else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ) )
1335 ::com::sun::star::drawing::Hatch aHatch;
1336 if ( aAny >>= aHatch )
1338 Color aBackColor;
1339 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1340 String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), sal_False ) )
1342 aBackColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()), sal_False );
1344 bool bFillBackground = false;
1345 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1346 String( RTL_CONSTASCII_USTRINGPARAM( "FillBackground" ) ), sal_True ) )
1348 aAny >>= bFillBackground;
1350 aGraphicObject = lclDrawHatch( aHatch, aBackColor, bFillBackground );
1351 aUniqueId = aGraphicObject.GetUniqueID();
1352 eBitmapMode = ::com::sun::star::drawing::BitmapMode_REPEAT;
1353 bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
1357 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "IsMirrored" ) ), sal_True ) )
1358 aAny >>= bMirrored;
1360 if ( bCreateFillBitmap && bFillBitmapModeAllowed )
1362 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapMode" ) ), sal_True ) )
1363 aAny >>= eBitmapMode;
1365 else
1367 nAngle = bRotate && EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1368 String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True )
1369 ? (sal_uInt16)( ( *((sal_Int32*)aAny.getValue() ) ) + 5 ) / 10
1370 : 0;
1373 if ( aGraphicUrl.Len() )
1375 String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
1376 xub_StrLen nIndex = aGraphicUrl.Search( aVndUrl, 0 );
1377 if ( nIndex != STRING_NOTFOUND )
1379 nIndex = nIndex + aVndUrl.Len();
1380 if ( aGraphicUrl.Len() > nIndex )
1381 aUniqueId = ByteString( aGraphicUrl, nIndex, aGraphicUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 );
1383 else
1385 // externally, linked graphic? convert to embedded
1386 // one, if transformations are needed. this is because
1387 // everything < msoxp cannot even handle rotated
1388 // bitmaps.
1389 // And check whether the graphic link target is
1390 // actually supported by mso.
1391 INetURLObject aTmp( aGraphicUrl );
1392 GraphicDescriptor aDescriptor(aTmp);
1393 aDescriptor.Detect();
1394 const USHORT nFormat = aDescriptor.GetFileFormat();
1396 // can MSO handle it?
1397 if ( bMirrored || nAngle ||
1398 (nFormat != GFF_BMP &&
1399 nFormat != GFF_GIF &&
1400 nFormat != GFF_JPG &&
1401 nFormat != GFF_PNG &&
1402 nFormat != GFF_TIF &&
1403 nFormat != GFF_PCT &&
1404 nFormat != GFF_WMF &&
1405 nFormat != GFF_EMF) )
1407 SvStream* pIn = ::utl::UcbStreamHelper::CreateStream(
1408 aTmp.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
1409 if ( pIn )
1411 Graphic aGraphic;
1412 sal_uInt32 nErrCode = GraphicConverter::Import( *pIn, aGraphic );
1414 if ( nErrCode == ERRCODE_NONE )
1416 // no.
1417 aGraphicObject = aGraphic;
1418 aUniqueId = aGraphicObject.GetUniqueID();
1420 // else: simply keep the graphic link
1421 delete pIn;
1427 if ( aGraphicUrl.Len() || aUniqueId.Len() )
1429 if ( bMirrored || nAngle )
1431 pGraphicAttr = new GraphicAttr;
1432 if ( bMirrored )
1433 pGraphicAttr->SetMirrorFlags( BMP_MIRROR_HORZ );
1434 if ( bIsGraphicMtf )
1435 AddOpt( ESCHER_Prop_Rotation, ( ( ((sal_Int32)nAngle << 16 ) / 10 ) + 0x8000 ) &~ 0xffff );
1436 else
1438 pGraphicAttr->SetRotation( nAngle );
1439 if ( nAngle && pShapeBoundRect ) // up to xp ppoint does not rotate bitmaps !
1441 Polygon aPoly( *pShapeBoundRect );
1442 aPoly.Rotate( pShapeBoundRect->TopLeft(), nAngle );
1443 *pShapeBoundRect = aPoly.GetBoundRect();
1444 bSuppressRotation = sal_True;
1449 if ( eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT )
1450 AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
1451 else
1452 AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1454 if ( aUniqueId.Len() )
1456 // write out embedded graphic
1457 if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect )
1459 Rectangle aRect( Point( 0, 0 ), pShapeBoundRect->GetSize() );
1461 sal_uInt32 nBlibId = 0;
1462 nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, aUniqueId, aRect, NULL, pGraphicAttr );
1463 if ( nBlibId )
1465 if ( bCreateFillBitmap )
1466 AddOpt( ESCHER_Prop_fillBlip, nBlibId, sal_True );
1467 else
1469 AddOpt( ESCHER_Prop_pib, nBlibId, sal_True );
1470 ImplCreateGraphicAttributes( rXPropSet, nBlibId, bCreateCroppingAttributes );
1472 bRetValue = sal_True;
1475 else
1477 EscherGraphicProvider aProvider;
1478 SvMemoryStream aMemStrm;
1479 Rectangle aRect;
1481 if ( aProvider.GetBlibID( aMemStrm, aUniqueId, aRect, NULL, pGraphicAttr ) )
1483 // grab BLIP from stream and insert directly as complex property
1484 // ownership of stream memory goes to complex property
1485 aMemStrm.ObjectOwnsMemory( FALSE );
1486 sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData();
1487 sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END );
1488 AddOpt( ESCHER_Prop_fillBlip, sal_True, nSize, pBuf, nSize );
1489 bRetValue = sal_True;
1493 // write out link to graphic
1494 else
1496 OSL_ASSERT(aGraphicUrl.Len());
1498 AddOpt( ESCHER_Prop_pibName, aGraphicUrl );
1499 sal_uInt32 nPibFlags=0;
1500 GetOpt( ESCHER_Prop_pibFlags, nPibFlags );
1501 AddOpt( ESCHER_Prop_pibFlags,
1502 ESCHER_BlipFlagLinkToFile|ESCHER_BlipFlagFile|ESCHER_BlipFlagDoNotSave | nPibFlags );
1506 delete pGraphicAttr;
1507 if ( bCreateFillStyles )
1508 CreateFillProperties( rXPropSet, sal_True );
1510 return bRetValue;
1513 PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
1515 PolyPolygon aRetPolyPoly;
1516 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet;
1517 ::com::sun::star::uno::Any aAny( rXShape->queryInterface(
1518 ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) ));
1520 String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) );
1521 String sPolyPolygon ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) );
1522 String sPolygon ( RTL_CONSTASCII_USTRINGPARAM( "Polygon" ) );
1524 if ( aAny >>= aXPropSet )
1526 sal_Bool bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygonBezier, sal_True );
1527 if ( !bHasProperty )
1528 bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygon, sal_True );
1529 if ( !bHasProperty )
1530 bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolygon, sal_True );
1531 if ( bHasProperty )
1532 aRetPolyPoly = GetPolyPolygon( aAny );
1534 return aRetPolyPoly;
1537 PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Any& rAny )
1539 sal_Bool bNoError = sal_True;
1541 Polygon aPolygon;
1542 PolyPolygon aPolyPolygon;
1544 if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PolyPolygonBezierCoords* ) 0 ) )
1546 ::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon
1547 = (::com::sun::star::drawing::PolyPolygonBezierCoords*)rAny.getValue();
1548 sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->Coordinates.getLength();
1550 // Zeiger auf innere sequences holen
1551 ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->Coordinates.getArray();
1552 ::com::sun::star::drawing::FlagSequence* pOuterFlags = pSourcePolyPolygon->Flags.getArray();
1554 bNoError = pOuterSequence && pOuterFlags;
1555 if ( bNoError )
1557 sal_uInt16 a, b, nInnerSequenceCount;
1558 ::com::sun::star::awt::Point* pArray;
1560 // dies wird ein Polygon set
1561 for ( a = 0; a < nOuterSequenceCount; a++ )
1563 ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
1564 ::com::sun::star::drawing::FlagSequence* pInnerFlags = pOuterFlags++;
1566 bNoError = pInnerSequence && pInnerFlags;
1567 if ( bNoError )
1569 // Zeiger auf Arrays holen
1570 pArray = pInnerSequence->getArray();
1571 ::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
1573 if ( pArray && pFlags )
1575 nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
1576 aPolygon = Polygon( nInnerSequenceCount );
1577 for( b = 0; b < nInnerSequenceCount; b++)
1579 PolyFlags ePolyFlags( *( (PolyFlags*)pFlags++ ) );
1580 ::com::sun::star::awt::Point aPoint( (::com::sun::star::awt::Point)*(pArray++) );
1581 aPolygon[ b ] = Point( aPoint.X, aPoint.Y );
1582 aPolygon.SetFlags( b, ePolyFlags );
1584 if ( ePolyFlags == POLY_CONTROL )
1585 continue;
1587 aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
1593 else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequenceSequence* ) 0 ) )
1595 ::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon
1596 = (::com::sun::star::drawing::PointSequenceSequence*)rAny.getValue();
1597 sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->getLength();
1599 // Zeiger auf innere sequences holen
1600 ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
1601 bNoError = pOuterSequence != NULL;
1602 if ( bNoError )
1604 sal_uInt16 a, b, nInnerSequenceCount;
1606 // dies wird ein Polygon set
1607 for( a = 0; a < nOuterSequenceCount; a++ )
1609 ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
1610 bNoError = pInnerSequence != NULL;
1611 if ( bNoError )
1613 // Zeiger auf Arrays holen
1614 ::com::sun::star::awt::Point* pArray =
1615 pInnerSequence->getArray();
1616 if ( pArray != NULL )
1618 nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
1619 aPolygon = Polygon( nInnerSequenceCount );
1620 for( b = 0; b < nInnerSequenceCount; b++)
1622 aPolygon[ b ] = Point( pArray->X, pArray->Y );
1623 pArray++;
1625 aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
1631 else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequence* ) 0 ) )
1633 ::com::sun::star::drawing::PointSequence* pInnerSequence =
1634 (::com::sun::star::drawing::PointSequence*)rAny.getValue();
1636 bNoError = pInnerSequence != NULL;
1637 if ( bNoError )
1639 sal_uInt16 a, nInnerSequenceCount;
1641 // Zeiger auf Arrays holen
1642 ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
1643 if ( pArray != NULL )
1645 nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
1646 aPolygon = Polygon( nInnerSequenceCount );
1647 for( a = 0; a < nInnerSequenceCount; a++)
1649 aPolygon[ a ] = Point( pArray->X, pArray->Y );
1650 pArray++;
1652 aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
1656 return aPolyPolygon;
1659 sal_Bool EscherPropertyContainer::CreatePolygonProperties(
1660 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
1661 sal_uInt32 nFlags,
1662 sal_Bool bBezier,
1663 ::com::sun::star::awt::Rectangle& rGeoRect,
1664 Polygon* pPolygon )
1666 static String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) );
1667 static String sPolyPolygon ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) );
1669 sal_Bool bRetValue = sal_True;
1670 sal_Bool bLine = ( nFlags & ESCHER_CREATEPOLYGON_LINE ) != 0;
1672 PolyPolygon aPolyPolygon;
1674 if ( pPolygon )
1675 aPolyPolygon.Insert( *pPolygon, POLYPOLY_APPEND );
1676 else
1678 ::com::sun::star::uno::Any aAny;
1679 bRetValue = EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1680 ( bBezier ) ? sPolyPolygonBezier : sPolyPolygon, sal_True );
1681 if ( bRetValue )
1683 aPolyPolygon = GetPolyPolygon( aAny );
1684 bRetValue = aPolyPolygon.Count() != 0;
1687 if ( bRetValue )
1689 if ( bLine )
1691 if ( ( aPolyPolygon.Count() == 1 ) && ( aPolyPolygon[ 0 ].GetSize() == 2 ) )
1693 const Polygon& rPoly = aPolyPolygon[ 0 ];
1694 rGeoRect = ::com::sun::star::awt::Rectangle(
1695 rPoly[ 0 ].X(),
1696 rPoly[ 0 ].Y(),
1697 rPoly[ 1 ].X() - rPoly[ 0 ].X(),
1698 rPoly[ 1 ].Y() - rPoly[ 0 ].Y() );
1700 else
1701 bRetValue = sal_False;
1703 else
1705 Polygon aPolygon;
1707 sal_uInt16 i, j, k, nPoints, nBezPoints, nPolyCount = aPolyPolygon.Count();
1708 Rectangle aRect( aPolyPolygon.GetBoundRect() );
1709 rGeoRect = ::com::sun::star::awt::Rectangle( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
1711 for ( nBezPoints = nPoints = i = 0; i < nPolyCount; i++ )
1713 k = aPolyPolygon[ i ].GetSize();
1714 nPoints = nPoints + k;
1715 for ( j = 0; j < k; j++ )
1717 if ( aPolyPolygon[ i ].GetFlags( j ) != POLY_CONTROL )
1718 nBezPoints++;
1721 sal_uInt32 nVerticesBufSize = ( nPoints << 2 ) + 6;
1722 sal_uInt8* pVerticesBuf = new sal_uInt8[ nVerticesBufSize ];
1725 sal_uInt32 nSegmentBufSize = ( ( nBezPoints << 2 ) + 8 );
1726 if ( nPolyCount > 1 )
1727 nSegmentBufSize += ( nPolyCount << 1 );
1728 sal_uInt8* pSegmentBuf = new sal_uInt8[ nSegmentBufSize ];
1730 sal_uInt8* pPtr = pVerticesBuf;
1731 *pPtr++ = (sal_uInt8)( nPoints ); // Little endian
1732 *pPtr++ = (sal_uInt8)( nPoints >> 8 );
1733 *pPtr++ = (sal_uInt8)( nPoints );
1734 *pPtr++ = (sal_uInt8)( nPoints >> 8 );
1735 *pPtr++ = (sal_uInt8)0xf0;
1736 *pPtr++ = (sal_uInt8)0xff;
1738 for ( j = 0; j < nPolyCount; j++ )
1740 aPolygon = aPolyPolygon[ j ];
1741 nPoints = aPolygon.GetSize();
1742 for ( i = 0; i < nPoints; i++ ) // Punkte aus Polygon in Buffer schreiben
1744 Point aPoint = aPolygon[ i ];
1745 aPoint.X() -= rGeoRect.X;
1746 aPoint.Y() -= rGeoRect.Y;
1748 *pPtr++ = (sal_uInt8)( aPoint.X() );
1749 *pPtr++ = (sal_uInt8)( aPoint.X() >> 8 );
1750 *pPtr++ = (sal_uInt8)( aPoint.Y() );
1751 *pPtr++ = (sal_uInt8)( aPoint.Y() >> 8 );
1755 pPtr = pSegmentBuf;
1756 *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 );
1757 *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 );
1758 *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 );
1759 *pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 );
1760 *pPtr++ = (sal_uInt8)2;
1761 *pPtr++ = (sal_uInt8)0;
1763 for ( j = 0; j < nPolyCount; j++ )
1765 *pPtr++ = 0x0; // Polygon start
1766 *pPtr++ = 0x40;
1767 aPolygon = aPolyPolygon[ j ];
1768 nPoints = aPolygon.GetSize();
1769 for ( i = 0; i < nPoints; i++ ) // Polyflags in Buffer schreiben
1771 *pPtr++ = 0;
1772 if ( bBezier )
1773 *pPtr++ = 0xb3;
1774 else
1775 *pPtr++ = 0xac;
1776 if ( ( i + 1 ) != nPoints )
1778 *pPtr++ = 1;
1779 if ( aPolygon.GetFlags( i + 1 ) == POLY_CONTROL )
1781 *pPtr++ = 0x20;
1782 i += 2;
1784 else
1785 *pPtr++ = 0;
1788 if ( nPolyCount > 1 )
1790 *pPtr++ = 1; // end of polygon
1791 *pPtr++ = 0x60;
1794 *pPtr++ = 0;
1795 *pPtr++ = 0x80;
1797 AddOpt( ESCHER_Prop_geoRight, rGeoRect.Width );
1798 AddOpt( ESCHER_Prop_geoBottom, rGeoRect.Height );
1800 AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
1801 AddOpt( ESCHER_Prop_pVertices, TRUE, nVerticesBufSize - 6, (sal_uInt8*)pVerticesBuf, nVerticesBufSize );
1802 AddOpt( ESCHER_Prop_pSegmentInfo, TRUE, nSegmentBufSize, (sal_uInt8*)pSegmentBuf, nSegmentBufSize );
1805 return bRetValue;
1808 sal_Bool EscherPropertyContainer::CreateConnectorProperties(
1809 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape,
1810 EscherSolverContainer& rSolverContainer, ::com::sun::star::awt::Rectangle& rGeoRect,
1811 sal_uInt16& rShapeType, sal_uInt16& rShapeFlags )
1813 static String sEdgeKind ( RTL_CONSTASCII_USTRINGPARAM( "EdgeKind" ) );
1814 static String sEdgeStartPoint ( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartPoint" ) );
1815 static String sEdgeEndPoint ( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndPoint" ) );
1816 static String sEdgeStartConnection ( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartConnection" ) );
1817 static String sEdgeEndConnection ( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndConnection" ) );
1819 sal_Bool bRetValue = sal_False;
1820 rShapeType = rShapeFlags = 0;
1822 if ( rXShape.is() )
1824 ::com::sun::star::awt::Point aStartPoint, aEndPoint;
1825 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet;
1826 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aShapeA, aShapeB;
1827 ::com::sun::star::uno::Any aAny( rXShape->queryInterface( ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) ));
1828 if ( aAny >>= aXPropSet )
1830 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeKind, sal_True ) )
1832 ::com::sun::star::drawing::ConnectorType eCt;
1833 aAny >>= eCt;
1834 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartPoint ) )
1836 aStartPoint = *(::com::sun::star::awt::Point*)aAny.getValue();
1837 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndPoint ) )
1839 aEndPoint = *(::com::sun::star::awt::Point*)aAny.getValue();
1841 rShapeFlags = SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT | SHAPEFLAG_CONNECTOR;
1842 rGeoRect = ::com::sun::star::awt::Rectangle( aStartPoint.X, aStartPoint.Y,
1843 ( aEndPoint.X - aStartPoint.X ) + 1, ( aEndPoint.Y - aStartPoint.Y ) + 1 );
1844 if ( rGeoRect.Height < 0 ) // justify
1846 rShapeFlags |= SHAPEFLAG_FLIPV;
1847 rGeoRect.Y = aEndPoint.Y;
1848 rGeoRect.Height = -rGeoRect.Height;
1850 if ( rGeoRect.Width < 0 )
1852 rShapeFlags |= SHAPEFLAG_FLIPH;
1853 rGeoRect.X = aEndPoint.X;
1854 rGeoRect.Width = -rGeoRect.Width;
1856 sal_uInt32 nAdjustValue1, nAdjustValue2, nAdjustValue3;
1857 nAdjustValue1 = nAdjustValue2 = nAdjustValue3 = 0x2a30;
1859 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartConnection ) )
1860 aAny >>= aShapeA;
1861 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndConnection ) )
1862 aAny >>= aShapeB;
1864 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine1Delta" ) ) ) )
1867 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine2Delta" ) ) ) )
1870 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine3Delta" ) ) ) )
1873 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1HorzDist" ) ) ) )
1876 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1VertDist" ) ) ) )
1879 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2HorzDist" ) ) ) )
1882 if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2VertDist" ) ) ) )
1886 rSolverContainer.AddConnector( rXShape, aStartPoint, aShapeA, aEndPoint, aShapeB );
1887 switch ( eCt )
1889 case ::com::sun::star::drawing::ConnectorType_CURVE :
1891 rShapeType = ESCHER_ShpInst_CurvedConnector3;
1892 AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleCurved );
1893 AddOpt( ESCHER_Prop_adjustValue, nAdjustValue1 );
1894 AddOpt( ESCHER_Prop_adjust2Value, -(sal_Int32)nAdjustValue2 );
1896 break;
1898 case ::com::sun::star::drawing::ConnectorType_STANDARD :// Connector 2->5
1900 rShapeType = ESCHER_ShpInst_BentConnector3;
1901 AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent );
1903 break;
1905 default:
1906 case ::com::sun::star::drawing::ConnectorType_LINE :
1907 case ::com::sun::star::drawing::ConnectorType_LINES : // Connector 2->5
1909 rShapeType = ESCHER_ShpInst_StraightConnector1;
1910 AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleStraight );
1912 break;
1914 CreateLineProperties( aXPropSet, sal_False );
1915 bRetValue = bSuppressRotation = sal_True;
1921 return bRetValue;
1924 sal_Bool EscherPropertyContainer::CreateShadowProperties(
1925 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet )
1927 ::com::sun::star::uno::Any aAny;
1929 sal_Bool bHasShadow = sal_False; // shadow is possible only if at least a fillcolor, linecolor or graphic is set
1930 sal_uInt32 nLineFlags = 0; // default : shape has no line
1931 sal_uInt32 nFillFlags = 0x10; // shape is filled
1933 GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
1934 GetOpt( ESCHER_Prop_fNoFillHitTest, nFillFlags );
1936 sal_uInt32 nDummy;
1937 sal_Bool bGraphic = GetOpt( DFF_Prop_pib, nDummy ) || GetOpt( DFF_Prop_pibName, nDummy ) || GetOpt( DFF_Prop_pibFlags, nDummy );
1939 sal_uInt32 nShadowFlags = 0x20000;
1940 if ( ( nLineFlags & 8 ) || ( nFillFlags & 0x10 ) || bGraphic )
1942 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1943 String( RTL_CONSTASCII_USTRINGPARAM( "Shadow" ) ), sal_True ) )
1945 if ( aAny >>= bHasShadow )
1947 if ( bHasShadow )
1949 nShadowFlags |= 2;
1950 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1951 String( RTL_CONSTASCII_USTRINGPARAM( "ShadowColor" ) ), sal_False ) )
1952 AddOpt( ESCHER_Prop_shadowColor, ImplGetColor( *((sal_uInt32*)aAny.getValue()) ) );
1953 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1954 String( RTL_CONSTASCII_USTRINGPARAM( "ShadowXDistance" ) ), sal_False ) )
1955 AddOpt( ESCHER_Prop_shadowOffsetX, *((sal_Int32*)aAny.getValue()) * 360 );
1956 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1957 String( RTL_CONSTASCII_USTRINGPARAM( "ShadowYDistance" ) ), sal_False ) )
1958 AddOpt( ESCHER_Prop_shadowOffsetY, *((sal_Int32*)aAny.getValue()) * 360 );
1959 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
1960 String( RTL_CONSTASCII_USTRINGPARAM( "ShadowTransparence" ) ), sal_False ) )
1961 AddOpt( ESCHER_Prop_shadowOpacity, 0x10000 - (((sal_uInt32)*((sal_uInt16*)aAny.getValue())) * 655 ) );
1966 AddOpt( ESCHER_Prop_fshadowObscured, nShadowFlags );
1967 return bHasShadow;
1970 // ---------------------------------------------------------------------------------------------
1972 sal_Int32 GetValueForEnhancedCustomShapeParameter( const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter, const std::vector< sal_Int32 >& rEquationOrder )
1974 sal_Int32 nValue = 0;
1975 if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
1977 double fValue;
1978 if ( rParameter.Value >>= fValue )
1979 nValue = (sal_Int32)fValue;
1981 else
1982 rParameter.Value >>= nValue;
1984 switch( rParameter.Type )
1986 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
1988 nValue = (sal_uInt16)rEquationOrder[ nValue ];
1989 nValue |= (sal_uInt32)0x80000000;
1991 break;
1992 case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL :
1996 break;
1997 /* not sure if it is allowed to set following values
1998 (but they are not yet used)
1999 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
2000 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
2001 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
2002 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
2003 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
2006 return nValue;
2009 sal_Bool GetValueForEnhancedCustomShapeHandleParameter( sal_Int32& nRetValue, const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter )
2011 sal_Bool bSpecial = sal_False;
2012 nRetValue = 0;
2013 if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
2015 double fValue;
2016 if ( rParameter.Value >>= fValue )
2017 nRetValue = (sal_Int32)fValue;
2019 else
2020 rParameter.Value >>= nRetValue;
2022 switch( rParameter.Type )
2024 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
2026 nRetValue += 3;
2027 bSpecial = sal_True;
2029 break;
2030 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
2032 nRetValue += 0x100;
2033 bSpecial = sal_True;
2035 break;
2036 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
2037 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
2039 nRetValue = 0;
2040 bSpecial = sal_True;
2042 break;
2043 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
2044 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
2046 nRetValue = 1;
2047 bSpecial = sal_True;
2049 break;
2050 case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL :
2054 break;
2056 return bSpecial;
2059 void ConvertEnhancedCustomShapeEquation( SdrObjCustomShape* pCustoShape,
2060 std::vector< EnhancedCustomShapeEquation >& rEquations, std::vector< sal_Int32 >& rEquationOrder )
2062 if ( pCustoShape )
2064 uno::Sequence< rtl::OUString > sEquationSource;
2065 const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
2066 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)
2067 pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
2068 const uno::Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
2069 if ( pAny )
2070 *pAny >>= sEquationSource;
2071 sal_Int32 nEquationSourceCount = sEquationSource.getLength();
2072 if ( nEquationSourceCount )
2074 sal_Int32 i;
2075 for ( i = 0; i < nEquationSourceCount; i++ )
2077 EnhancedCustomShape2d aCustoShape2d( pCustoShape );
2080 ::boost::shared_ptr< EnhancedCustomShape::ExpressionNode > aExpressNode(
2081 EnhancedCustomShape::FunctionParser::parseFunction( sEquationSource[ i ], aCustoShape2d ) );
2082 com::sun::star::drawing::EnhancedCustomShapeParameter aPara( aExpressNode->fillNode( rEquations, NULL, 0 ) );
2083 if ( aPara.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION )
2085 EnhancedCustomShapeEquation aEquation;
2086 aEquation.nOperation = 0;
2087 EnhancedCustomShape::FillEquationParameter( aPara, 0, aEquation );
2088 rEquations.push_back( aEquation );
2091 catch ( EnhancedCustomShape::ParseError& )
2093 EnhancedCustomShapeEquation aEquation; // ups, we should not be here,
2094 aEquation.nOperation = 0; // creating a default equation with value 1
2095 aEquation.nPara[ 0 ] = 1; // hoping that this will not break anything
2096 rEquations.push_back( aEquation );
2098 rEquationOrder.push_back( rEquations.size() - 1 );
2100 // now updating our old equation indices, they are marked with a bit in the hiword of nOperation
2101 std::vector< EnhancedCustomShapeEquation >::iterator aIter( rEquations.begin() );
2102 std::vector< EnhancedCustomShapeEquation >::iterator aEnd ( rEquations.end() );
2103 while( aIter != aEnd )
2105 sal_Int32 nMask = 0x20000000;
2106 for( i = 0; i < 3; i++ )
2108 if ( aIter->nOperation & nMask )
2110 aIter->nOperation ^= nMask;
2111 aIter->nPara[ i ] = rEquationOrder[ aIter->nPara[ i ] & 0x3ff ] | 0x400;
2113 nMask <<= 1;
2115 aIter++;
2121 sal_Bool EscherPropertyContainer::IsDefaultObject( SdrObjCustomShape* pCustoShape )
2123 sal_Bool bIsDefaultObject = sal_False;
2124 if ( pCustoShape )
2126 if ( pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_EQUATIONS )
2127 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_VIEWBOX )
2128 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_PATH )
2129 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_GLUEPOINTS )
2130 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_SEGMENTS )
2131 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHX )
2132 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHY )
2133 // && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_HANDLES )
2134 && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_TEXTFRAMES ) )
2135 bIsDefaultObject = sal_True;
2138 return bIsDefaultObject;
2141 void EscherPropertyContainer::LookForPolarHandles( const MSO_SPT eShapeType, sal_Int32& nAdjustmentsWhichNeedsToBeConverted )
2143 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eShapeType );
2144 if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
2146 sal_Int32 k, nkCount = pDefCustomShape->nHandles;
2147 const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
2148 for ( k = 0; k < nkCount; k++, pData++ )
2150 if ( pData->nFlags & MSDFF_HANDLE_FLAGS_POLAR )
2152 if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
2153 nAdjustmentsWhichNeedsToBeConverted |= ( 1 << k );
2159 sal_Bool EscherPropertyContainer::GetAdjustmentValue( const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue & rkProp, sal_Int32 nIndex, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, sal_Int32& nValue )
2161 if ( rkProp.State != beans::PropertyState_DIRECT_VALUE )
2162 return FALSE;
2164 sal_Bool bUseFixedFloat = ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << nIndex ) ) != 0;
2165 if ( rkProp.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
2167 double fValue;
2168 rkProp.Value >>= fValue;
2169 if ( bUseFixedFloat )
2170 fValue *= 65536.0;
2171 nValue = (sal_Int32)fValue;
2173 else
2175 rkProp.Value >>= nValue;
2176 if ( bUseFixedFloat )
2177 nValue <<= 16;
2180 return TRUE;
2183 void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeType, const uno::Reference< drawing::XShape > & rXShape )
2185 uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
2186 if ( aXPropSet.is() )
2188 SdrObjCustomShape* pCustoShape = (SdrObjCustomShape*)GetSdrObjectFromXShape( rXShape );
2189 const rtl::OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) );
2190 uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
2191 uno::Sequence< beans::PropertyValue > aGeoPropSeq;
2192 if ( aGeoPropSet >>= aGeoPropSeq )
2194 const rtl::OUString sViewBox ( RTL_CONSTASCII_USTRINGPARAM( "ViewBox" ) );
2195 const rtl::OUString sTextRotateAngle ( RTL_CONSTASCII_USTRINGPARAM( "TextRotateAngle" ) );
2196 const rtl::OUString sExtrusion ( RTL_CONSTASCII_USTRINGPARAM( "Extrusion" ) );
2197 const rtl::OUString sEquations ( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
2198 const rtl::OUString sPath ( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
2199 const rtl::OUString sTextPath ( RTL_CONSTASCII_USTRINGPARAM( "TextPath" ) );
2200 const rtl::OUString sHandles ( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
2201 const rtl::OUString sAdjustmentValues ( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) );
2203 const beans::PropertyValue* pAdjustmentValuesProp = NULL;
2204 sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0;
2205 uno::Sequence< beans::PropertyValues > aHandlesPropSeq;
2206 sal_Bool bPredefinedHandlesUsed = sal_True;
2207 sal_Bool bIsDefaultObject = IsDefaultObject( pCustoShape );
2209 // convert property "Equations" into std::vector< EnhancedCustomShapeEquationEquation >
2210 std::vector< EnhancedCustomShapeEquation > aEquations;
2211 std::vector< sal_Int32 > aEquationOrder;
2212 ConvertEnhancedCustomShapeEquation( pCustoShape, aEquations, aEquationOrder );
2214 sal_Int32 i, nCount = aGeoPropSeq.getLength();
2215 for ( i = 0; i < nCount; i++ )
2217 const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
2218 if ( rProp.Name.equals( sViewBox ) )
2220 if ( !bIsDefaultObject )
2222 awt::Rectangle aViewBox;
2223 if ( rProp.Value >>= aViewBox )
2225 AddOpt( DFF_Prop_geoLeft, aViewBox.X );
2226 AddOpt( DFF_Prop_geoTop, aViewBox.Y );
2227 AddOpt( DFF_Prop_geoRight, aViewBox.X + aViewBox.Width );
2228 AddOpt( DFF_Prop_geoBottom,aViewBox.Y + aViewBox.Height );
2232 else if ( rProp.Name.equals( sTextRotateAngle ) )
2234 double f = 0, fTextRotateAngle;
2235 if ( rProp.Value >>= f )
2237 fTextRotateAngle = fmod( f, 360.0 );
2238 if ( fTextRotateAngle < 0 )
2239 fTextRotateAngle = 360 + fTextRotateAngle;
2240 if ( ( fTextRotateAngle < 271.0 ) && ( fTextRotateAngle > 269.0 ) )
2241 AddOpt( DFF_Prop_cdirFont, mso_cdir90 );
2242 else if ( ( fTextRotateAngle < 181.0 ) && ( fTextRotateAngle > 179.0 ) )
2243 AddOpt( DFF_Prop_cdirFont, mso_cdir180 );
2244 else if ( ( fTextRotateAngle < 91.0 ) && ( fTextRotateAngle > 79.0 ) )
2245 AddOpt( DFF_Prop_cdirFont, mso_cdir270 );
2248 else if ( rProp.Name.equals( sExtrusion ) )
2250 uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
2251 if ( rProp.Value >>= aExtrusionPropSeq )
2253 sal_uInt32 nLightFaceFlagsOrg, nLightFaceFlags;
2254 sal_uInt32 nFillHarshFlagsOrg, nFillHarshFlags;
2255 nLightFaceFlagsOrg = nLightFaceFlags = 0x000001;
2256 nFillHarshFlagsOrg = nFillHarshFlags = 0x00001e;
2257 if ( GetOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ) )
2258 nLightFaceFlagsOrg = nLightFaceFlags;
2259 if ( GetOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ) )
2260 nFillHarshFlagsOrg = nFillHarshFlags;
2262 sal_Int32 r, nrCount = aExtrusionPropSeq.getLength();
2263 for ( r = 0; r < nrCount; r++ )
2265 const beans::PropertyValue& rrProp = aExtrusionPropSeq[ r ];
2266 const rtl::OUString sExtrusionBrightness ( RTL_CONSTASCII_USTRINGPARAM( "Brightness" ) );
2267 const rtl::OUString sExtrusionDepth ( RTL_CONSTASCII_USTRINGPARAM( "Depth" ) );
2268 const rtl::OUString sExtrusionDiffusion ( RTL_CONSTASCII_USTRINGPARAM( "Diffusion" ) );
2269 const rtl::OUString sExtrusionNumberOfLineSegments ( RTL_CONSTASCII_USTRINGPARAM( "NumberOfLineSegments" ) );
2270 const rtl::OUString sExtrusionLightFace ( RTL_CONSTASCII_USTRINGPARAM( "LightFace" ) );
2271 const rtl::OUString sExtrusionFirstLightHarsh ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightHarsh" ) );
2272 const rtl::OUString sExtrusionSecondLightHarsh ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightHarsh" ) );
2273 const rtl::OUString sExtrusionFirstLightLevel ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightLevel" ) );
2274 const rtl::OUString sExtrusionSecondLightLevel ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightLevel" ) );
2275 const rtl::OUString sExtrusionFirstLightDirection ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightDirection" ) );
2276 const rtl::OUString sExtrusionSecondLightDirection ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightDirection" ) );
2277 const rtl::OUString sExtrusionMetal ( RTL_CONSTASCII_USTRINGPARAM( "Metal" ) );
2278 const rtl::OUString sExtrusionShadeMode ( RTL_CONSTASCII_USTRINGPARAM( "ShadeMode" ) );
2279 const rtl::OUString sExtrusionRotateAngle ( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) );
2280 const rtl::OUString sExtrusionRotationCenter ( RTL_CONSTASCII_USTRINGPARAM( "RotationCenter" ) );
2281 const rtl::OUString sExtrusionShininess ( RTL_CONSTASCII_USTRINGPARAM( "Shininess" ) );
2282 const rtl::OUString sExtrusionSkew ( RTL_CONSTASCII_USTRINGPARAM( "Skew" ) );
2283 const rtl::OUString sExtrusionSpecularity ( RTL_CONSTASCII_USTRINGPARAM( "Specularity" ) );
2284 const rtl::OUString sExtrusionProjectionMode ( RTL_CONSTASCII_USTRINGPARAM( "ProjectionMode" ) );
2285 const rtl::OUString sExtrusionViewPoint ( RTL_CONSTASCII_USTRINGPARAM( "ViewPoint" ) );
2286 const rtl::OUString sExtrusionOrigin ( RTL_CONSTASCII_USTRINGPARAM( "Origin" ) );
2287 const rtl::OUString sExtrusionColor ( RTL_CONSTASCII_USTRINGPARAM( "Color" ) );
2289 if ( rrProp.Name.equals( sExtrusion ) )
2291 sal_Bool bExtrusionOn = sal_Bool();
2292 if ( rrProp.Value >>= bExtrusionOn )
2294 nLightFaceFlags |= 0x80000;
2295 if ( bExtrusionOn )
2296 nLightFaceFlags |= 8;
2297 else
2298 nLightFaceFlags &=~8;
2301 else if ( rrProp.Name.equals( sExtrusionBrightness ) )
2303 double fExtrusionBrightness = 0;
2304 if ( rrProp.Value >>= fExtrusionBrightness )
2305 AddOpt( DFF_Prop_c3DAmbientIntensity, (sal_Int32)( fExtrusionBrightness * 655.36 ) );
2307 else if ( rrProp.Name.equals( sExtrusionDepth ) )
2309 double fDepth = 0;
2310 double fFraction = 0;
2311 com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
2312 if ( ( rrProp.Value >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) )
2314 double fForeDepth = fDepth * fFraction;
2315 double fBackDepth = fDepth - fForeDepth;
2317 fBackDepth *= 360.0;
2318 AddOpt( DFF_Prop_c3DExtrudeBackward, (sal_Int32)fBackDepth );
2320 if ( fForeDepth != 0.0 )
2322 fForeDepth *= 360.0;
2323 AddOpt( DFF_Prop_c3DExtrudeForward, (sal_Int32)fForeDepth );
2327 else if ( rrProp.Name.equals( sExtrusionDiffusion ) )
2329 double fExtrusionDiffusion = 0;
2330 if ( rrProp.Value >>= fExtrusionDiffusion )
2331 AddOpt( DFF_Prop_c3DDiffuseAmt, (sal_Int32)( fExtrusionDiffusion * 655.36 ) );
2333 else if ( rrProp.Name.equals( sExtrusionNumberOfLineSegments ) )
2335 sal_Int32 nExtrusionNumberOfLineSegments = 0;
2336 if ( rrProp.Value >>= nExtrusionNumberOfLineSegments )
2337 AddOpt( DFF_Prop_c3DTolerance, nExtrusionNumberOfLineSegments );
2339 else if ( rrProp.Name.equals( sExtrusionLightFace ) )
2341 sal_Bool bExtrusionLightFace = sal_Bool();
2342 if ( rrProp.Value >>= bExtrusionLightFace )
2344 nLightFaceFlags |= 0x10000;
2345 if ( bExtrusionLightFace )
2346 nLightFaceFlags |= 1;
2347 else
2348 nLightFaceFlags &=~1;
2351 else if ( rrProp.Name.equals( sExtrusionFirstLightHarsh ) )
2353 sal_Bool bExtrusionFirstLightHarsh = sal_Bool();
2354 if ( rrProp.Value >>= bExtrusionFirstLightHarsh )
2356 nFillHarshFlags |= 0x20000;
2357 if ( bExtrusionFirstLightHarsh )
2358 nFillHarshFlags |= 2;
2359 else
2360 nFillHarshFlags &=~2;
2363 else if ( rrProp.Name.equals( sExtrusionSecondLightHarsh ) )
2365 sal_Bool bExtrusionSecondLightHarsh = sal_Bool();
2366 if ( rrProp.Value >>= bExtrusionSecondLightHarsh )
2368 nFillHarshFlags |= 0x10000;
2369 if ( bExtrusionSecondLightHarsh )
2370 nFillHarshFlags |= 1;
2371 else
2372 nFillHarshFlags &=~1;
2375 else if ( rrProp.Name.equals( sExtrusionFirstLightLevel ) )
2377 double fExtrusionFirstLightLevel = 0;
2378 if ( rrProp.Value >>= fExtrusionFirstLightLevel )
2379 AddOpt( DFF_Prop_c3DKeyIntensity, (sal_Int32)( fExtrusionFirstLightLevel * 655.36 ) );
2381 else if ( rrProp.Name.equals( sExtrusionSecondLightLevel ) )
2383 double fExtrusionSecondLightLevel = 0;
2384 if ( rrProp.Value >>= fExtrusionSecondLightLevel )
2385 AddOpt( DFF_Prop_c3DFillIntensity, (sal_Int32)( fExtrusionSecondLightLevel * 655.36 ) );
2387 else if ( rrProp.Name.equals( sExtrusionFirstLightDirection ) )
2389 drawing::Direction3D aExtrusionFirstLightDirection;
2390 if ( rrProp.Value >>= aExtrusionFirstLightDirection )
2392 AddOpt( DFF_Prop_c3DKeyX, (sal_Int32)aExtrusionFirstLightDirection.DirectionX );
2393 AddOpt( DFF_Prop_c3DKeyY, (sal_Int32)aExtrusionFirstLightDirection.DirectionY );
2394 AddOpt( DFF_Prop_c3DKeyZ, (sal_Int32)aExtrusionFirstLightDirection.DirectionZ );
2397 else if ( rrProp.Name.equals( sExtrusionSecondLightDirection ) )
2399 drawing::Direction3D aExtrusionSecondLightPosition;
2400 if ( rrProp.Value >>= aExtrusionSecondLightPosition )
2402 AddOpt( DFF_Prop_c3DFillX, (sal_Int32)aExtrusionSecondLightPosition.DirectionX );
2403 AddOpt( DFF_Prop_c3DFillY, (sal_Int32)aExtrusionSecondLightPosition.DirectionY );
2404 AddOpt( DFF_Prop_c3DFillZ, (sal_Int32)aExtrusionSecondLightPosition.DirectionZ );
2407 else if ( rrProp.Name.equals( sExtrusionMetal ) )
2409 sal_Bool bExtrusionMetal = sal_Bool();
2410 if ( rrProp.Value >>= bExtrusionMetal )
2412 nLightFaceFlags |= 0x40000;
2413 if ( bExtrusionMetal )
2414 nLightFaceFlags |= 4;
2415 else
2416 nLightFaceFlags &=~4;
2419 else if ( rrProp.Name.equals( sExtrusionShadeMode ) )
2421 drawing::ShadeMode eExtrusionShadeMode;
2422 if ( rrProp.Value >>= eExtrusionShadeMode )
2424 sal_uInt32 nRenderMode;
2425 switch( eExtrusionShadeMode )
2427 default:
2428 case drawing::ShadeMode_FLAT :
2429 case drawing::ShadeMode_PHONG :
2430 case drawing::ShadeMode_SMOOTH :
2431 nRenderMode = mso_FullRender;
2432 break;
2433 case drawing::ShadeMode_DRAFT :
2435 nRenderMode = mso_Wireframe;
2437 break;
2439 AddOpt( DFF_Prop_c3DRenderMode, nRenderMode );
2442 else if ( rrProp.Name.equals( sExtrusionRotateAngle ) )
2444 double fExtrusionAngleX = 0;
2445 double fExtrusionAngleY = 0;
2446 com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAnglePair;
2447 if ( ( rrProp.Value >>= aRotateAnglePair ) && ( aRotateAnglePair.First.Value >>= fExtrusionAngleX ) && ( aRotateAnglePair.Second.Value >>= fExtrusionAngleY ) )
2449 fExtrusionAngleX *= 65536;
2450 fExtrusionAngleY *= 65536;
2451 AddOpt( DFF_Prop_c3DXRotationAngle, (sal_Int32)fExtrusionAngleX );
2452 AddOpt( DFF_Prop_c3DYRotationAngle, (sal_Int32)fExtrusionAngleY );
2455 else if ( rrProp.Name.equals( sExtrusionRotationCenter ) )
2457 drawing::Direction3D aExtrusionRotationCenter;
2458 if ( rrProp.Value >>= aExtrusionRotationCenter )
2460 AddOpt( DFF_Prop_c3DRotationCenterX, (sal_Int32)( aExtrusionRotationCenter.DirectionX * 360.0 ) );
2461 AddOpt( DFF_Prop_c3DRotationCenterY, (sal_Int32)( aExtrusionRotationCenter.DirectionY * 360.0 ) );
2462 AddOpt( DFF_Prop_c3DRotationCenterZ, (sal_Int32)( aExtrusionRotationCenter.DirectionZ * 360.0 ) );
2463 nFillHarshFlags &=~8; // don't use AutoRotationCenter;
2466 else if ( rrProp.Name.equals( sExtrusionShininess ) )
2468 double fExtrusionShininess = 0;
2469 if ( rrProp.Value >>= fExtrusionShininess )
2470 AddOpt( DFF_Prop_c3DShininess, (sal_Int32)( fExtrusionShininess * 655.36 ) );
2472 else if ( rrProp.Name.equals( sExtrusionSkew ) )
2474 double fSkewAmount = 0;
2475 double fSkewAngle = 0;
2476 com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
2477 if ( ( rrProp.Value >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= fSkewAmount ) && ( aSkewParaPair.Second.Value >>= fSkewAngle ) )
2479 AddOpt( DFF_Prop_c3DSkewAmount, (sal_Int32)fSkewAmount );
2480 AddOpt( DFF_Prop_c3DSkewAngle, (sal_Int32)( fSkewAngle * 65536 ) );
2483 else if ( rrProp.Name.equals( sExtrusionSpecularity ) )
2485 double fExtrusionSpecularity = 0;
2486 if ( rrProp.Value >>= fExtrusionSpecularity )
2487 AddOpt( DFF_Prop_c3DSpecularAmt, (sal_Int32)( fExtrusionSpecularity * 1333 ) );
2489 else if ( rrProp.Name.equals( sExtrusionProjectionMode ) )
2491 drawing::ProjectionMode eExtrusionProjectionMode;
2492 if ( rrProp.Value >>= eExtrusionProjectionMode )
2494 nFillHarshFlags |= 0x40000;
2495 if ( eExtrusionProjectionMode == drawing::ProjectionMode_PARALLEL )
2496 nFillHarshFlags |= 4;
2497 else
2498 nFillHarshFlags &=~4;
2501 else if ( rrProp.Name.equals( sExtrusionViewPoint ) )
2503 drawing::Position3D aExtrusionViewPoint;
2504 if ( rrProp.Value >>= aExtrusionViewPoint )
2506 aExtrusionViewPoint.PositionX *= 360.0;
2507 aExtrusionViewPoint.PositionY *= 360.0;
2508 aExtrusionViewPoint.PositionZ *= 360.0;
2509 AddOpt( DFF_Prop_c3DXViewpoint, (sal_Int32)aExtrusionViewPoint.PositionX );
2510 AddOpt( DFF_Prop_c3DYViewpoint, (sal_Int32)aExtrusionViewPoint.PositionY );
2511 AddOpt( DFF_Prop_c3DZViewpoint, (sal_Int32)aExtrusionViewPoint.PositionZ );
2514 else if ( rrProp.Name.equals( sExtrusionOrigin ) )
2516 double fExtrusionOriginX = 0;
2517 double fExtrusionOriginY = 0;
2518 com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginPair;
2519 if ( ( rrProp.Value >>= aOriginPair ) && ( aOriginPair.First.Value >>= fExtrusionOriginX ) && ( aOriginPair.Second.Value >>= fExtrusionOriginY ) )
2521 AddOpt( DFF_Prop_c3DOriginX, (sal_Int32)( fExtrusionOriginX * 65536 ) );
2522 AddOpt( DFF_Prop_c3DOriginY, (sal_Int32)( fExtrusionOriginY * 65536 ) );
2525 else if ( rrProp.Name.equals( sExtrusionColor ) )
2527 sal_Bool bExtrusionColor = sal_Bool();
2528 if ( rrProp.Value >>= bExtrusionColor )
2530 nLightFaceFlags |= 0x20000;
2531 if ( bExtrusionColor )
2533 nLightFaceFlags |= 2;
2534 uno::Any aFillColor2;
2535 if ( EscherPropertyValueHelper::GetPropertyValue( aFillColor2, aXPropSet,
2536 String( RTL_CONSTASCII_USTRINGPARAM( "FillColor2" ) ), sal_True ) )
2538 sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aFillColor2.getValue()) );
2539 AddOpt( DFF_Prop_c3DExtrusionColor, nFillColor );
2542 else
2543 nLightFaceFlags &=~2;
2547 if ( nLightFaceFlags != nLightFaceFlagsOrg )
2548 AddOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags );
2549 if ( nFillHarshFlags != nFillHarshFlagsOrg )
2550 AddOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags );
2553 else if ( rProp.Name.equals( sEquations ) )
2555 if ( !bIsDefaultObject )
2557 sal_uInt16 nElements = (sal_uInt16)aEquations.size();
2558 if ( nElements )
2560 sal_uInt16 nElementSize = 8;
2561 sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2562 SvMemoryStream aOut( nStreamSize );
2563 aOut << nElements
2564 << nElements
2565 << nElementSize;
2567 std::vector< EnhancedCustomShapeEquation >::const_iterator aIter( aEquations.begin() );
2568 std::vector< EnhancedCustomShapeEquation >::const_iterator aEnd ( aEquations.end() );
2569 while( aIter != aEnd )
2571 aOut << (sal_uInt16)aIter->nOperation
2572 << (sal_Int16)aIter->nPara[ 0 ]
2573 << (sal_Int16)aIter->nPara[ 1 ]
2574 << (sal_Int16)aIter->nPara[ 2 ];
2575 aIter++;
2577 sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2578 memcpy( pBuf, aOut.GetData(), nStreamSize );
2579 AddOpt( DFF_Prop_pFormulas, sal_True, nStreamSize - 6, pBuf, nStreamSize );
2581 else
2583 sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2584 AddOpt( DFF_Prop_pFormulas, sal_True, 0, pBuf, 0 );
2588 else if ( rProp.Name.equals( sPath ) )
2590 uno::Sequence< beans::PropertyValue > aPathPropSeq;
2591 if ( rProp.Value >>= aPathPropSeq )
2593 sal_uInt32 nPathFlags, nPathFlagsOrg;
2594 nPathFlagsOrg = nPathFlags = 0x39;
2595 if ( GetOpt( DFF_Prop_fFillOK, nPathFlags ) )
2596 nPathFlagsOrg = nPathFlags;
2598 sal_Int32 r, nrCount = aPathPropSeq.getLength();
2599 for ( r = 0; r < nrCount; r++ )
2601 const beans::PropertyValue& rrProp = aPathPropSeq[ r ];
2602 const rtl::OUString sPathExtrusionAllowed ( RTL_CONSTASCII_USTRINGPARAM( "ExtrusionAllowed" ) );
2603 const rtl::OUString sPathConcentricGradientFillAllowed ( RTL_CONSTASCII_USTRINGPARAM( "ConcentricGradientFillAllowed" ) );
2604 const rtl::OUString sPathTextPathAllowed ( RTL_CONSTASCII_USTRINGPARAM( "TextPathAllowed" ) );
2605 const rtl::OUString sPathCoordinates ( RTL_CONSTASCII_USTRINGPARAM( "Coordinates" ) );
2606 const rtl::OUString sPathGluePoints ( RTL_CONSTASCII_USTRINGPARAM( "GluePoints" ) );
2607 const rtl::OUString sPathGluePointType ( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
2608 const rtl::OUString sPathSegments ( RTL_CONSTASCII_USTRINGPARAM( "Segments" ) );
2609 const rtl::OUString sPathStretchX ( RTL_CONSTASCII_USTRINGPARAM( "StretchX" ) );
2610 const rtl::OUString sPathStretchY ( RTL_CONSTASCII_USTRINGPARAM( "StretchY" ) );
2611 const rtl::OUString sPathTextFrames ( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) );
2613 if ( rrProp.Name.equals( sPathExtrusionAllowed ) )
2615 sal_Bool bExtrusionAllowed = sal_Bool();
2616 if ( rrProp.Value >>= bExtrusionAllowed )
2618 nPathFlags |= 0x100000;
2619 if ( bExtrusionAllowed )
2620 nPathFlags |= 16;
2621 else
2622 nPathFlags &=~16;
2625 else if ( rrProp.Name.equals( sPathConcentricGradientFillAllowed ) )
2627 sal_Bool bConcentricGradientFillAllowed = sal_Bool();
2628 if ( rrProp.Value >>= bConcentricGradientFillAllowed )
2630 nPathFlags |= 0x20000;
2631 if ( bConcentricGradientFillAllowed )
2632 nPathFlags |= 2;
2633 else
2634 nPathFlags &=~2;
2637 else if ( rrProp.Name.equals( sPathTextPathAllowed ) )
2639 sal_Bool bTextPathAllowed = sal_Bool();
2640 if ( rrProp.Value >>= bTextPathAllowed )
2642 nPathFlags |= 0x40000;
2643 if ( bTextPathAllowed )
2644 nPathFlags |= 4;
2645 else
2646 nPathFlags &=~4;
2649 else if ( rrProp.Name.equals( sPathCoordinates ) )
2651 if ( !bIsDefaultObject )
2653 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
2654 if ( rrProp.Value >>= aCoordinates )
2656 // creating the vertices
2657 if ( (sal_uInt16)aCoordinates.getLength() )
2659 sal_uInt16 j, nElements = (sal_uInt16)aCoordinates.getLength();
2660 sal_uInt16 nElementSize = 8;
2661 sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2662 SvMemoryStream aOut( nStreamSize );
2663 aOut << nElements
2664 << nElements
2665 << nElementSize;
2666 for( j = 0; j < nElements; j++ )
2668 sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].First, aEquationOrder );
2669 sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].Second, aEquationOrder );
2670 aOut << X
2671 << Y;
2673 sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2674 memcpy( pBuf, aOut.GetData(), nStreamSize );
2675 AddOpt( DFF_Prop_pVertices, sal_True, nStreamSize - 6, pBuf, nStreamSize ); // -6
2677 else
2679 sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2680 AddOpt( DFF_Prop_pVertices, sal_True, 0, pBuf, 0 );
2685 else if ( rrProp.Name.equals( sPathGluePoints ) )
2687 if ( !bIsDefaultObject )
2689 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
2690 if ( rrProp.Value >>= aGluePoints )
2692 // creating the vertices
2693 sal_uInt16 nElements = (sal_uInt16)aGluePoints.getLength();
2694 if ( nElements )
2696 sal_uInt16 j, nElementSize = 8;
2697 sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2698 SvMemoryStream aOut( nStreamSize );
2699 aOut << nElements
2700 << nElements
2701 << nElementSize;
2702 for( j = 0; j < nElements; j++ )
2704 sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].First, aEquationOrder );
2705 sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].Second, aEquationOrder );
2706 aOut << X
2707 << Y;
2709 sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2710 memcpy( pBuf, aOut.GetData(), nStreamSize );
2711 AddOpt( DFF_Prop_connectorPoints, sal_True, nStreamSize - 6, pBuf, nStreamSize ); // -6
2713 else
2715 sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2716 AddOpt( DFF_Prop_connectorPoints, sal_True, 0, pBuf, 0 );
2721 else if ( rrProp.Name.equals( sPathGluePointType ) )
2723 sal_Int16 nGluePointType = sal_Int16();
2724 if ( rrProp.Value >>= nGluePointType )
2725 AddOpt( DFF_Prop_connectorType, (sal_uInt16)nGluePointType );
2727 else if ( rrProp.Name.equals( sPathSegments ) )
2729 if ( !bIsDefaultObject )
2731 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments;
2732 if ( rrProp.Value >>= aSegments )
2734 // creating seginfo
2735 if ( (sal_uInt16)aSegments.getLength() )
2737 sal_uInt16 j, nElements = (sal_uInt16)aSegments.getLength();
2738 sal_uInt16 nElementSize = 2;
2739 sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2740 SvMemoryStream aOut( nStreamSize );
2741 aOut << nElements
2742 << nElements
2743 << nElementSize;
2744 for ( j = 0; j < nElements; j++ )
2746 sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count;
2747 switch( aSegments[ j ].Command )
2749 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
2750 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break;
2751 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
2753 nVal = 0x4000;
2755 break;
2756 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
2758 nVal |= 0x2000;
2760 break;
2761 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
2763 nVal = 0x6001;
2765 break;
2766 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
2768 nVal = 0x8000;
2770 break;
2771 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
2773 nVal = 0xaa00;
2775 break;
2776 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
2778 nVal = 0xab00;
2780 break;
2781 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
2783 nVal *= 3;
2784 nVal |= 0xa100;
2786 break;
2787 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
2789 nVal *= 3;
2790 nVal |= 0xa200;
2792 break;
2793 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
2795 nVal <<= 2;
2796 nVal |= 0xa300;
2798 break;
2799 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC :
2801 nVal <<= 2;
2802 nVal |= 0xa400;
2804 break;
2805 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
2807 nVal <<= 2;
2808 nVal |= 0xa500;
2810 break;
2811 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
2813 nVal <<= 2;
2814 nVal |= 0xa600;
2816 break;
2817 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
2819 nVal |= 0xa700;
2821 break;
2822 case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
2824 nVal |= 0xa800;
2826 break;
2828 aOut << nVal;
2830 sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2831 memcpy( pBuf, aOut.GetData(), nStreamSize );
2832 AddOpt( DFF_Prop_pSegmentInfo, sal_False, nStreamSize - 6, pBuf, nStreamSize );
2834 else
2836 sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2837 AddOpt( DFF_Prop_pSegmentInfo, sal_True, 0, pBuf, 0 );
2842 else if ( rrProp.Name.equals( sPathStretchX ) )
2844 if ( !bIsDefaultObject )
2846 sal_Int32 nStretchX = 0;
2847 if ( rrProp.Value >>= nStretchX )
2848 AddOpt( DFF_Prop_stretchPointX, nStretchX );
2851 else if ( rrProp.Name.equals( sPathStretchY ) )
2853 if ( !bIsDefaultObject )
2855 sal_Int32 nStretchY = 0;
2856 if ( rrProp.Value >>= nStretchY )
2857 AddOpt( DFF_Prop_stretchPointY, nStretchY );
2860 else if ( rrProp.Name.equals( sPathTextFrames ) )
2862 if ( !bIsDefaultObject )
2864 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
2865 if ( rrProp.Value >>= aPathTextFrames )
2867 if ( (sal_uInt16)aPathTextFrames.getLength() )
2869 sal_uInt16 j, nElements = (sal_uInt16)aPathTextFrames.getLength();
2870 sal_uInt16 nElementSize = 16;
2871 sal_uInt32 nStreamSize = nElementSize * nElements + 6;
2872 SvMemoryStream aOut( nStreamSize );
2873 aOut << nElements
2874 << nElements
2875 << nElementSize;
2876 for ( j = 0; j < nElements; j++ )
2878 sal_Int32 nLeft = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.First, aEquationOrder );
2879 sal_Int32 nTop = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.Second, aEquationOrder );
2880 sal_Int32 nRight = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.First, aEquationOrder );
2881 sal_Int32 nBottom = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.Second, aEquationOrder );
2883 aOut << nLeft
2884 << nTop
2885 << nRight
2886 << nBottom;
2888 sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
2889 memcpy( pBuf, aOut.GetData(), nStreamSize );
2890 AddOpt( DFF_Prop_textRectangles, sal_True, nStreamSize - 6, pBuf, nStreamSize );
2892 else
2894 sal_uInt8* pBuf = new sal_uInt8[ 1 ];
2895 AddOpt( DFF_Prop_textRectangles, sal_True, 0, pBuf, 0 );
2901 if ( nPathFlags != nPathFlagsOrg )
2902 AddOpt( DFF_Prop_fFillOK, nPathFlags );
2905 else if ( rProp.Name.equals( sTextPath ) )
2907 uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
2908 if ( rProp.Value >>= aTextPathPropSeq )
2910 sal_uInt32 nTextPathFlagsOrg, nTextPathFlags;
2911 nTextPathFlagsOrg = nTextPathFlags = 0xffff1000; // default
2912 if ( GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ) )
2913 nTextPathFlagsOrg = nTextPathFlags;
2915 sal_Int32 r, nrCount = aTextPathPropSeq.getLength();
2916 for ( r = 0; r < nrCount; r++ )
2918 const beans::PropertyValue& rrProp = aTextPathPropSeq[ r ];
2919 const rtl::OUString sTextPathMode ( RTL_CONSTASCII_USTRINGPARAM( "TextPathMode" ) );
2920 const rtl::OUString sTextPathScaleX ( RTL_CONSTASCII_USTRINGPARAM( "ScaleX" ) );
2921 const rtl::OUString sSameLetterHeights ( RTL_CONSTASCII_USTRINGPARAM( "SameLetterHeights" ) );
2923 if ( rrProp.Name.equals( sTextPath ) )
2925 sal_Bool bTextPathOn = sal_Bool();
2926 if ( rrProp.Value >>= bTextPathOn )
2928 nTextPathFlags |= 0x40000000;
2929 if ( bTextPathOn )
2931 nTextPathFlags |= 0x4000;
2933 sal_uInt32 nPathFlags = 0x39;
2934 GetOpt( DFF_Prop_fFillOK, nPathFlags ); // SJ: can be removed if we are supporting the TextPathAllowed property in XML
2935 nPathFlags |= 0x40004;
2936 AddOpt( DFF_Prop_fFillOK, nPathFlags );
2938 else
2939 nTextPathFlags &=~0x4000;
2942 else if ( rrProp.Name.equals( sTextPathMode ) )
2944 com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
2945 if ( rrProp.Value >>= eTextPathMode )
2947 nTextPathFlags |= 0x05000000;
2948 nTextPathFlags &=~0x500; // TextPathMode_NORMAL
2949 if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH )
2950 nTextPathFlags |= 0x100;
2951 else if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE )
2952 nTextPathFlags |= 0x500;
2955 else if ( rrProp.Name.equals( sTextPathScaleX ) )
2957 sal_Bool bTextPathScaleX = sal_Bool();
2958 if ( rrProp.Value >>= bTextPathScaleX )
2960 nTextPathFlags |= 0x00400000;
2961 if ( bTextPathScaleX )
2962 nTextPathFlags |= 0x40;
2963 else
2964 nTextPathFlags &=~0x40;
2967 else if ( rrProp.Name.equals( sSameLetterHeights ) )
2969 sal_Bool bSameLetterHeights = sal_Bool();
2970 if ( rrProp.Value >>= bSameLetterHeights )
2972 nTextPathFlags |= 0x00800000;
2973 if ( bSameLetterHeights )
2974 nTextPathFlags |= 0x80;
2975 else
2976 nTextPathFlags &=~0x80;
2980 if ( nTextPathFlags & 0x4000 ) // Is FontWork ?
2982 // FontWork Text
2983 rtl::OUString aText;
2984 uno::Reference< text::XSimpleText > xText( rXShape, uno::UNO_QUERY );
2985 if ( xText.is() )
2986 aText = xText->getString();
2987 if ( !aText.getLength() )
2988 aText = ::rtl::OUString::createFromAscii( "your text" ); // todo: moving into a resource
2989 AddOpt( DFF_Prop_gtextUNICODE, aText );
2991 // FontWork Font
2992 rtl::OUString aFontName;
2993 const rtl::OUString sCharFontName ( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) );
2994 uno::Any aAny = aXPropSet->getPropertyValue( sCharFontName );
2995 aAny >>= aFontName;
2996 if ( !aFontName.getLength() )
2997 aFontName = ::rtl::OUString::createFromAscii( "Arial Black" );
2998 AddOpt( DFF_Prop_gtextFont, aFontName );
3000 sal_Int16 nCharScaleWidth = 100;
3001 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharScaleWidth" ) ), sal_True ) )
3003 if ( aAny >>= nCharScaleWidth )
3005 if ( nCharScaleWidth != 100 )
3007 sal_Int32 nVal = nCharScaleWidth * 655;
3008 AddOpt( DFF_Prop_gtextSpacing, nVal );
3012 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharKerning" ) ), sal_True ) )
3014 sal_Int16 nCharKerning = sal_Int16();
3015 if ( aAny >>= nCharKerning )
3017 nTextPathFlags |= 0x10000000;
3018 if ( nCharKerning )
3019 nTextPathFlags |= 0x1000;
3020 else
3021 nTextPathFlags &=~0x1000;
3024 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharPosture" ) ), sal_True ) )
3026 awt::FontSlant eFontSlant;
3027 if ( aAny >>= eFontSlant )
3029 nTextPathFlags |= 0x100010;
3030 if ( eFontSlant != awt::FontSlant_NONE )
3031 nTextPathFlags |= 0x10;
3032 else
3033 nTextPathFlags &=~0x10;
3036 if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) ), sal_True ) )
3038 float fFontWidth = 0;
3039 if ( aAny >>= fFontWidth )
3041 nTextPathFlags |= 0x200020;
3042 if ( fFontWidth > awt::FontWeight::NORMAL )
3043 nTextPathFlags |= 0x20;
3044 else
3045 nTextPathFlags &=~0x20;
3049 if ( nTextPathFlags != nTextPathFlagsOrg )
3050 AddOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
3053 else if ( rProp.Name.equals( sHandles ) )
3055 if ( !bIsDefaultObject )
3057 bPredefinedHandlesUsed = sal_False;
3058 if ( rProp.Value >>= aHandlesPropSeq )
3060 sal_uInt16 nElements = (sal_uInt16)aHandlesPropSeq.getLength();
3061 if ( nElements )
3063 const rtl::OUString sHandle ( RTL_CONSTASCII_USTRINGPARAM( "Handle" ) );
3065 sal_uInt16 k, j, nElementSize = 36;
3066 sal_uInt32 nStreamSize = nElementSize * nElements + 6;
3067 SvMemoryStream aOut( nStreamSize );
3068 aOut << nElements
3069 << nElements
3070 << nElementSize;
3072 for ( k = 0; k < nElements; k++ )
3074 sal_uInt32 nFlags = 0;
3075 sal_Int32 nXPosition = 0;
3076 sal_Int32 nYPosition = 0;
3077 sal_Int32 nXMap = 0;
3078 sal_Int32 nYMap = 0;
3079 sal_Int32 nXRangeMin = 0x80000000;
3080 sal_Int32 nXRangeMax = 0x7fffffff;
3081 sal_Int32 nYRangeMin = 0x80000000;
3082 sal_Int32 nYRangeMax = 0x7fffffff;
3084 const uno::Sequence< beans::PropertyValue >& rPropSeq = aHandlesPropSeq[ k ];
3085 for ( j = 0; j < rPropSeq.getLength(); j++ )
3087 const beans::PropertyValue& rPropVal = rPropSeq[ j ];
3089 const rtl::OUString sPosition ( RTL_CONSTASCII_USTRINGPARAM( "Position" ) );
3090 const rtl::OUString sMirroredX ( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) );
3091 const rtl::OUString sMirroredY ( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) );
3092 const rtl::OUString sSwitched ( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) );
3093 const rtl::OUString sPolar ( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) );
3094 // const rtl::OUString sMap ( RTL_CONSTASCII_USTRINGPARAM( "Map" ) );
3095 const rtl::OUString sRadiusRangeMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) );
3096 const rtl::OUString sRadiusRangeMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) );
3097 const rtl::OUString sRangeXMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) );
3098 const rtl::OUString sRangeXMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) );
3099 const rtl::OUString sRangeYMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) );
3100 const rtl::OUString sRangeYMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) );
3102 if ( rPropVal.Name.equals( sPosition ) )
3104 com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
3105 if ( rPropVal.Value >>= aPosition )
3107 GetValueForEnhancedCustomShapeHandleParameter( nXPosition, aPosition.First );
3108 GetValueForEnhancedCustomShapeHandleParameter( nYPosition, aPosition.Second );
3111 else if ( rPropVal.Name.equals( sMirroredX ) )
3113 sal_Bool bMirroredX = sal_Bool();
3114 if ( rPropVal.Value >>= bMirroredX )
3116 if ( bMirroredX )
3117 nFlags |= 1;
3120 else if ( rPropVal.Name.equals( sMirroredY ) )
3122 sal_Bool bMirroredY = sal_Bool();
3123 if ( rPropVal.Value >>= bMirroredY )
3125 if ( bMirroredY )
3126 nFlags |= 2;
3129 else if ( rPropVal.Name.equals( sSwitched ) )
3131 sal_Bool bSwitched = sal_Bool();
3132 if ( rPropVal.Value >>= bSwitched )
3134 if ( bSwitched )
3135 nFlags |= 4;
3138 else if ( rPropVal.Name.equals( sPolar ) )
3140 com::sun::star::drawing::EnhancedCustomShapeParameterPair aPolar;
3141 if ( rPropVal.Value >>= aPolar )
3143 if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aPolar.First ) )
3144 nFlags |= 0x800;
3145 if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aPolar.Second ) )
3146 nFlags |= 0x1000;
3147 nFlags |= 8;
3150 /* seems not to be used.
3151 else if ( rPropVal.Name.equals( sMap ) )
3153 com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap;
3154 if ( rPropVal.Value >>= aMap )
3156 if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) )
3157 nFlags |= 0x800;
3158 if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) )
3159 nFlags |= 0x1000;
3160 nFlags |= 0x10;
3164 else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) )
3166 nYRangeMin = (sal_Int32)0xff4c0000; // the range of angles seems to be a not
3167 nYRangeMax = (sal_Int32)0x00b40000; // used feature, so we are defaulting this
3169 com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
3170 if ( rPropVal.Value >>= aRadiusRangeMinimum )
3172 if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aRadiusRangeMinimum ) )
3173 nFlags |= 0x80;
3174 nFlags |= 0x2000;
3177 else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) )
3179 nYRangeMin = (sal_Int32)0xff4c0000; // the range of angles seems to be a not
3180 nYRangeMax = (sal_Int32)0x00b40000; // used feature, so we are defaulting this
3182 com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
3183 if ( rPropVal.Value >>= aRadiusRangeMaximum )
3185 if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aRadiusRangeMaximum ) )
3186 nFlags |= 0x100;
3187 nFlags |= 0x2000;
3190 else if ( rPropVal.Name.equals( sRangeXMinimum ) )
3192 com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
3193 if ( rPropVal.Value >>= aXRangeMinimum )
3195 if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aXRangeMinimum ) )
3196 nFlags |= 0x80;
3197 nFlags |= 0x20;
3200 else if ( rPropVal.Name.equals( sRangeXMaximum ) )
3202 com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
3203 if ( rPropVal.Value >>= aXRangeMaximum )
3205 if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aXRangeMaximum ) )
3206 nFlags |= 0x100;
3207 nFlags |= 0x20;
3210 else if ( rPropVal.Name.equals( sRangeYMinimum ) )
3212 com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
3213 if ( rPropVal.Value >>= aYRangeMinimum )
3215 if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMin, aYRangeMinimum ) )
3216 nFlags |= 0x200;
3217 nFlags |= 0x20;
3220 else if ( rPropVal.Name.equals( sRangeYMaximum ) )
3222 com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
3223 if ( rPropVal.Value >>= aYRangeMaximum )
3225 if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMax, aYRangeMaximum ) )
3226 nFlags |= 0x400;
3227 nFlags |= 0x20;
3231 aOut << nFlags
3232 << nXPosition
3233 << nYPosition
3234 << nXMap
3235 << nYMap
3236 << nXRangeMin
3237 << nXRangeMax
3238 << nYRangeMin
3239 << nYRangeMax;
3241 if ( nFlags & 8 )
3242 nAdjustmentsWhichNeedsToBeConverted |= ( 1 << ( nYPosition - 0x100 ) );
3244 sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
3245 memcpy( pBuf, aOut.GetData(), nStreamSize );
3246 AddOpt( DFF_Prop_Handles, sal_True, nStreamSize - 6, pBuf, nStreamSize );
3248 else
3250 sal_uInt8* pBuf = new sal_uInt8[ 1 ];
3251 AddOpt( DFF_Prop_Handles, sal_True, 0, pBuf, 0 );
3256 else if ( rProp.Name.equals( sAdjustmentValues ) )
3258 // it is required, that the information which handle is polar has already be read,
3259 // so we are able to change the polar value to a fixed float
3260 pAdjustmentValuesProp = &rProp;
3263 if ( pAdjustmentValuesProp )
3265 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
3266 if ( pAdjustmentValuesProp->Value >>= aAdjustmentSeq )
3268 if ( bPredefinedHandlesUsed )
3269 LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
3271 sal_Int32 k, nValue = 0, nAdjustmentValues = aAdjustmentSeq.getLength();
3272 for ( k = 0; k < nAdjustmentValues; k++ )
3273 if( GetAdjustmentValue( aAdjustmentSeq[ k ], k, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
3274 AddOpt( (sal_uInt16)( DFF_Prop_adjustValue + k ), (sal_uInt32)nValue );
3281 // ---------------------------------------------------------------------------------------------
3283 MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags, rtl::OUString& rShapeType )
3285 MSO_SPT eShapeType = mso_sptNil;
3286 nMirrorFlags = 0;
3287 uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
3288 if ( aXPropSet.is() )
3292 const OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM ( "CustomShapeGeometry" ) );
3293 uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
3294 uno::Sequence< beans::PropertyValue > aGeoPropSeq;
3295 if ( aGeoPropSet >>= aGeoPropSeq )
3297 sal_Int32 i, nCount = aGeoPropSeq.getLength();
3298 for ( i = 0; i < nCount; i++ )
3300 const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
3301 if ( rProp.Name.equalsAscii( "Type" ) )
3303 if ( rProp.Value >>= rShapeType )
3304 eShapeType = EnhancedCustomShapeTypeNames::Get( rShapeType );
3306 else if ( rProp.Name.equalsAscii( "MirroredX" ) )
3308 sal_Bool bMirroredX = sal_Bool();
3309 if ( ( rProp.Value >>= bMirroredX ) && bMirroredX )
3310 nMirrorFlags |= SHAPEFLAG_FLIPH;
3312 else if ( rProp.Name.equalsAscii( "MirroredY" ) )
3314 sal_Bool bMirroredY = sal_Bool();
3315 if ( ( rProp.Value >>= bMirroredY ) && bMirroredY )
3316 nMirrorFlags |= SHAPEFLAG_FLIPV;
3321 catch( ::com::sun::star::uno::Exception& )
3325 return eShapeType;
3328 MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, sal_uInt32& nMirrorFlags )
3330 rtl::OUString aShapeType;
3331 return GetCustomShapeType( rXShape, nMirrorFlags, aShapeType );
3334 // ---------------------------------------------------------------------------------------------
3336 EscherPersistTable::EscherPersistTable()
3340 // ---------------------------------------------------------------------------------------------
3342 EscherPersistTable::~EscherPersistTable()
3344 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3345 delete (EscherPersistEntry*)pPtr;
3348 // ---------------------------------------------------------------------------------------------
3350 BOOL EscherPersistTable::PtIsID( UINT32 nID )
3352 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3354 if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3355 return TRUE;
3357 return FALSE;
3360 // ---------------------------------------------------------------------------------------------
3362 void EscherPersistTable::PtInsert( UINT32 nID, UINT32 nOfs )
3364 maPersistTable.Insert( new EscherPersistEntry( nID, nOfs ) );
3367 // ---------------------------------------------------------------------------------------------
3369 UINT32 EscherPersistTable::PtDelete( UINT32 nID )
3371 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3373 if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3375 // UINT32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3376 delete (EscherPersistEntry*) maPersistTable.Remove();
3379 return 0;
3382 // ---------------------------------------------------------------------------------------------
3384 UINT32 EscherPersistTable::PtGetOffsetByID( UINT32 nID )
3386 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3388 if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3389 return ((EscherPersistEntry*)pPtr)->mnOffset;
3391 return 0;
3394 // ---------------------------------------------------------------------------------------------
3396 UINT32 EscherPersistTable::PtReplace( UINT32 nID, UINT32 nOfs )
3398 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3400 if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3402 UINT32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3403 ((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
3404 return nRetValue;
3407 return 0;
3410 // ---------------------------------------------------------------------------------------------
3412 UINT32 EscherPersistTable::PtReplaceOrInsert( UINT32 nID, UINT32 nOfs )
3414 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
3416 if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
3418 UINT32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
3419 ((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
3420 return nRetValue;
3423 PtInsert( nID, nOfs );
3424 return 0;
3427 sal_Bool EscherPropertyValueHelper::GetPropertyValue(
3428 ::com::sun::star::uno::Any& rAny,
3429 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
3430 const String& rString,
3431 sal_Bool bTestPropertyAvailability )
3433 sal_Bool bRetValue = sal_True;
3434 if ( bTestPropertyAvailability )
3436 bRetValue = sal_False;
3439 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
3440 aXPropSetInfo( rXPropSet->getPropertySetInfo() );
3441 if ( aXPropSetInfo.is() )
3442 bRetValue = aXPropSetInfo->hasPropertyByName( rString );
3444 catch( ::com::sun::star::uno::Exception& )
3446 bRetValue = sal_False;
3449 if ( bRetValue )
3453 rAny = rXPropSet->getPropertyValue( rString );
3454 if ( !rAny.hasValue() )
3455 bRetValue = sal_False;
3457 catch( ::com::sun::star::uno::Exception& )
3459 bRetValue = sal_False;
3462 return bRetValue;
3465 // ---------------------------------------------------------------------------------------------
3467 ::com::sun::star::beans::PropertyState EscherPropertyValueHelper::GetPropertyState(
3468 const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
3469 const String& rPropertyName )
3471 ::com::sun::star::beans::PropertyState eRetValue = ::com::sun::star::beans::PropertyState_AMBIGUOUS_VALUE;
3474 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState > aXPropState
3475 ( rXPropSet, ::com::sun::star::uno::UNO_QUERY );
3476 if ( aXPropState.is() )
3477 eRetValue = aXPropState->getPropertyState( rPropertyName );
3479 catch( ::com::sun::star::uno::Exception& )
3481 //...
3483 return eRetValue;
3486 // ---------------------------------------------------------------------------------------------
3487 // ---------------------------------------------------------------------------------------------
3488 // ---------------------------------------------------------------------------------------------
3490 EscherBlibEntry::EscherBlibEntry( sal_uInt32 nPictureOffset, const GraphicObject& rObject, const ByteString& rId,
3491 const GraphicAttr* pGraphicAttr ) :
3492 mnPictureOffset ( nPictureOffset ),
3493 mnRefCount ( 1 ),
3494 mnSizeExtra ( 0 ),
3495 maPrefSize ( rObject.GetPrefSize() ),
3496 maPrefMapMode ( rObject.GetPrefMapMode() ),
3497 mbIsEmpty ( TRUE )
3499 mbIsNativeGraphicPossible = ( pGraphicAttr == NULL );
3500 meBlibType = UNKNOWN;
3501 mnSize = 0;
3503 sal_uInt32 nLen = rId.Len();
3504 const sal_Char* pData = rId.GetBuffer();
3505 GraphicType eType( rObject.GetType() );
3506 if ( nLen && pData && ( eType != GRAPHIC_NONE ) )
3508 mnIdentifier[ 0 ] = rtl_crc32( 0,pData, nLen );
3509 mnIdentifier[ 1 ] = 0;
3511 if ( pGraphicAttr )
3513 if ( pGraphicAttr->IsSpecialDrawMode()
3514 || pGraphicAttr->IsMirrored()
3515 || pGraphicAttr->IsCropped()
3516 || pGraphicAttr->IsRotated()
3517 || pGraphicAttr->IsTransparent()
3518 || pGraphicAttr->IsAdjusted() )
3520 SvMemoryStream aSt( sizeof( GraphicAttr ) );
3521 aSt << static_cast<sal_uInt16>(pGraphicAttr->GetDrawMode())
3522 << static_cast<sal_uInt32>(pGraphicAttr->GetMirrorFlags())
3523 << pGraphicAttr->GetLeftCrop()
3524 << pGraphicAttr->GetTopCrop()
3525 << pGraphicAttr->GetRightCrop()
3526 << pGraphicAttr->GetBottomCrop()
3527 << pGraphicAttr->GetRotation()
3528 << pGraphicAttr->GetLuminance()
3529 << pGraphicAttr->GetContrast()
3530 << pGraphicAttr->GetChannelR()
3531 << pGraphicAttr->GetChannelG()
3532 << pGraphicAttr->GetChannelB()
3533 << pGraphicAttr->GetGamma()
3534 << (BOOL)( pGraphicAttr->IsInvert() == TRUE )
3535 << pGraphicAttr->GetTransparency();
3536 mnIdentifier[ 1 ] = rtl_crc32( 0, aSt.GetData(), aSt.Tell() );
3538 else
3539 mbIsNativeGraphicPossible = TRUE;
3541 sal_uInt32 i, nTmp, n1, n2;
3542 n1 = n2 = 0;
3543 for ( i = 0; i < nLen; i++ )
3545 nTmp = n2 >> 28; // rotating 4 bit
3546 n2 <<= 4;
3547 n2 |= n1 >> 28;
3548 n1 <<= 4;
3549 n1 |= nTmp;
3550 n1 ^= *pData++ - '0';
3552 mnIdentifier[ 2 ] = n1;
3553 mnIdentifier[ 3 ] = n2;
3554 mbIsEmpty = FALSE;
3558 // ---------------------------------------------------------------------------------------------
3560 void EscherBlibEntry::WriteBlibEntry( SvStream& rSt, sal_Bool bWritePictureOffset, sal_uInt32 nResize )
3562 sal_uInt32 nPictureOffset = ( bWritePictureOffset ) ? mnPictureOffset : 0;
3564 rSt << (sal_uInt32)( ( ESCHER_BSE << 16 ) | ( ( (sal_uInt16)meBlibType << 4 ) | 2 ) )
3565 << (sal_uInt32)( 36 + nResize )
3566 << (sal_uInt8)meBlibType;
3568 switch ( meBlibType )
3570 case EMF :
3571 case WMF : // EMF/WMF auf OS2 zu Pict Konvertieren
3572 rSt << (sal_uInt8)PICT;
3573 break;
3574 default:
3575 rSt << (sal_uInt8)meBlibType;
3578 rSt.Write( &mnIdentifier[ 0 ], 16 );
3579 rSt << (sal_uInt16)0
3580 << (sal_uInt32)( mnSize + mnSizeExtra )
3581 << mnRefCount
3582 << nPictureOffset
3583 << (sal_uInt32)0;
3586 // ---------------------------------------------------------------------------------------------
3588 EscherBlibEntry::~EscherBlibEntry()
3592 // ---------------------------------------------------------------------------------------------
3594 BOOL EscherBlibEntry::operator==( const EscherBlibEntry& rEscherBlibEntry ) const
3596 for ( int i = 0; i < 3; i++ )
3598 if ( mnIdentifier[ i ] != rEscherBlibEntry.mnIdentifier[ i ] )
3599 return FALSE;
3601 return TRUE;
3604 // ---------------------------------------------------------------------------------------------
3605 // ---------------------------------------------------------------------------------------------
3606 // ---------------------------------------------------------------------------------------------
3608 EscherGraphicProvider::EscherGraphicProvider( sal_uInt32 nFlags ) :
3609 mnFlags ( nFlags ),
3610 mpBlibEntrys ( NULL ),
3611 mnBlibBufSize ( 0 ),
3612 mnBlibEntrys ( 0 )
3616 EscherGraphicProvider::~EscherGraphicProvider()
3618 for ( UINT32 i = 0; i < mnBlibEntrys; delete mpBlibEntrys[ i++ ] ) ;
3619 delete[] mpBlibEntrys;
3622 void EscherGraphicProvider::SetNewBlipStreamOffset( sal_Int32 nOffset )
3624 for( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3626 EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
3627 pBlibEntry->mnPictureOffset += nOffset;
3631 UINT32 EscherGraphicProvider::ImplInsertBlib( EscherBlibEntry* p_EscherBlibEntry )
3633 if ( mnBlibBufSize == mnBlibEntrys )
3635 mnBlibBufSize += 64;
3636 EscherBlibEntry** pTemp = new EscherBlibEntry*[ mnBlibBufSize ];
3637 for ( UINT32 i = 0; i < mnBlibEntrys; i++ )
3639 pTemp[ i ] = mpBlibEntrys[ i ];
3641 delete[] mpBlibEntrys;
3642 mpBlibEntrys = pTemp;
3644 mpBlibEntrys[ mnBlibEntrys++ ] = p_EscherBlibEntry;
3645 return mnBlibEntrys;
3648 sal_uInt32 EscherGraphicProvider::GetBlibStoreContainerSize( SvStream* pMergePicStreamBSE ) const
3650 sal_uInt32 nSize = 44 * mnBlibEntrys + 8;
3651 if ( pMergePicStreamBSE )
3653 for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3654 nSize += mpBlibEntrys[ i ]->mnSize + mpBlibEntrys[ i ]->mnSizeExtra;
3656 return nSize;
3659 sal_Bool EscherGraphicProvider::WriteBlibStoreEntry(SvStream& rSt,
3660 sal_uInt32 nBlipId, sal_Bool bWritePictureOffSet, sal_uInt32 nResize)
3662 if (nBlipId > mnBlibEntrys || nBlipId == 0)
3663 return sal_False;
3664 mpBlibEntrys[nBlipId-1]->WriteBlibEntry(rSt, bWritePictureOffSet, nResize);
3665 return sal_True;
3668 void EscherGraphicProvider::WriteBlibStoreContainer( SvStream& rSt, SvStream* pMergePicStreamBSE )
3670 sal_uInt32 nSize = GetBlibStoreContainerSize( pMergePicStreamBSE );
3671 if ( nSize )
3673 rSt << (sal_uInt32)( ( ESCHER_BstoreContainer << 16 ) | 0x1f )
3674 << (sal_uInt32)( nSize - 8 );
3676 if ( pMergePicStreamBSE )
3678 sal_uInt32 i, nBlipSize, nOldPos = pMergePicStreamBSE->Tell();
3679 const sal_uInt32 nBuf = 0x40000; // 256KB buffer
3680 sal_uInt8* pBuf = new sal_uInt8[ nBuf ];
3682 for ( i = 0; i < mnBlibEntrys; i++ )
3684 EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
3686 ESCHER_BlibType nBlibType = pBlibEntry->meBlibType;
3687 nBlipSize = pBlibEntry->mnSize + pBlibEntry->mnSizeExtra;
3688 pBlibEntry->WriteBlibEntry( rSt, sal_False, nBlipSize );
3690 // BLIP
3691 pMergePicStreamBSE->Seek( pBlibEntry->mnPictureOffset );
3692 UINT16 n16;
3693 // record version and instance
3694 *pMergePicStreamBSE >> n16;
3695 rSt << n16;
3696 // record type
3697 *pMergePicStreamBSE >> n16;
3698 rSt << UINT16( ESCHER_BlipFirst + nBlibType );
3699 DBG_ASSERT( n16 == ESCHER_BlipFirst + nBlibType , "EscherEx::Flush: BLIP record types differ" );
3700 UINT32 n32;
3701 // record size
3702 *pMergePicStreamBSE >> n32;
3703 nBlipSize -= 8;
3704 rSt << nBlipSize;
3705 DBG_ASSERT( nBlipSize == n32, "EscherEx::Flush: BLIP sizes differ" );
3706 // record
3707 while ( nBlipSize )
3709 UINT32 nBytes = ( nBlipSize > nBuf ? nBuf : nBlipSize );
3710 pMergePicStreamBSE->Read( pBuf, nBytes );
3711 rSt.Write( pBuf, nBytes );
3712 nBlipSize -= nBytes;
3715 delete[] pBuf;
3716 pMergePicStreamBSE->Seek( nOldPos );
3718 else
3720 for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
3721 mpBlibEntrys[ i ]->WriteBlibEntry( rSt, sal_True );
3726 sal_Bool EscherGraphicProvider::GetPrefSize( const sal_uInt32 nBlibId, Size& rPrefSize, MapMode& rPrefMapMode )
3728 sal_Bool bInRange = nBlibId && ( ( nBlibId - 1 ) < mnBlibEntrys );
3729 if ( bInRange )
3731 EscherBlibEntry* pEntry = mpBlibEntrys[ nBlibId - 1 ];
3732 rPrefSize = pEntry->maPrefSize;
3733 rPrefMapMode = pEntry->maPrefMapMode;
3735 return bInRange;
3738 sal_uInt32 EscherGraphicProvider::GetBlibID( SvStream& rPicOutStrm, const ByteString& rId,
3739 const Rectangle& /* rBoundRect */, const com::sun::star::awt::Rectangle* pVisArea, const GraphicAttr* pGraphicAttr )
3741 sal_uInt32 nBlibId = 0;
3742 GraphicObject aGraphicObject( rId );
3744 EscherBlibEntry* p_EscherBlibEntry = new EscherBlibEntry( rPicOutStrm.Tell(), aGraphicObject, rId, pGraphicAttr );
3745 if ( !p_EscherBlibEntry->IsEmpty() )
3747 for ( UINT32 i = 0; i < mnBlibEntrys; i++ )
3749 if ( *( mpBlibEntrys[ i ] ) == *p_EscherBlibEntry )
3751 mpBlibEntrys[ i ]->mnRefCount++;
3752 delete p_EscherBlibEntry;
3753 return i + 1;
3757 sal_Bool bUseNativeGraphic( FALSE );
3759 Graphic aGraphic( aGraphicObject.GetTransformedGraphic( pGraphicAttr ) );
3760 GfxLink aGraphicLink;
3761 SvMemoryStream aStream;
3763 const sal_uInt8* pGraphicAry = NULL;
3765 if ( p_EscherBlibEntry->mbIsNativeGraphicPossible && aGraphic.IsLink() )
3767 aGraphicLink = aGraphic.GetLink();
3769 p_EscherBlibEntry->mnSize = aGraphicLink.GetDataSize();
3770 pGraphicAry = aGraphicLink.GetData();
3772 if ( p_EscherBlibEntry->mnSize && pGraphicAry )
3774 switch ( aGraphicLink.GetType() )
3776 case GFX_LINK_TYPE_NATIVE_JPG : p_EscherBlibEntry->meBlibType = PEG; break;
3777 case GFX_LINK_TYPE_NATIVE_PNG : p_EscherBlibEntry->meBlibType = PNG; break;
3778 case GFX_LINK_TYPE_NATIVE_WMF :
3780 if ( pGraphicAry && ( p_EscherBlibEntry->mnSize > 0x2c ) )
3782 if ( ( pGraphicAry[ 0x28 ] == 0x20 ) && ( pGraphicAry[ 0x29 ] == 0x45 ) // check the magic
3783 && ( pGraphicAry[ 0x2a ] == 0x4d ) && ( pGraphicAry[ 0x2b ] == 0x46 ) ) // number ( emf detection )
3785 p_EscherBlibEntry->meBlibType = EMF;
3787 else
3789 p_EscherBlibEntry->meBlibType = WMF;
3790 if ( ( pGraphicAry[ 0 ] == 0xd7 ) && ( pGraphicAry[ 1 ] == 0xcd )
3791 && ( pGraphicAry[ 2 ] == 0xc6 ) && ( pGraphicAry[ 3 ] == 0x9a ) )
3792 { // we have to get rid of the metafileheader
3793 pGraphicAry += 22;
3794 p_EscherBlibEntry->mnSize -= 22;
3799 break;
3800 default: break;
3802 if ( p_EscherBlibEntry->meBlibType != UNKNOWN )
3803 bUseNativeGraphic = TRUE;
3806 if ( !bUseNativeGraphic )
3808 GraphicType eGraphicType = aGraphic.GetType();
3809 if ( ( eGraphicType == GRAPHIC_BITMAP ) || ( eGraphicType == GRAPHIC_GDIMETAFILE ) )
3811 sal_uInt32 nErrCode;
3812 if ( !aGraphic.IsAnimated() )
3813 // !EMF nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG : CVT_WMF );
3814 nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG : CVT_EMF );
3815 else
3816 { // to store a animation, a gif has to be included into the msOG chunk of a png #I5583#
3817 GraphicFilter* pFilter = GetGrfFilter();
3818 SvMemoryStream aGIFStream;
3819 ByteString aVersion( "MSOFFICE9.0" );
3820 aGIFStream.Write( aVersion.GetBuffer(), aVersion.Len() );
3821 nErrCode = pFilter->ExportGraphic( aGraphic, String(), aGIFStream,
3822 pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "GIF" ) ) ), NULL );
3823 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aFilterData( 1 );
3824 com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence( 1 );
3825 sal_uInt32 nGIFSreamLen = aGIFStream.Tell();
3826 com::sun::star::uno::Sequence< sal_Int8 > aGIFSeq( nGIFSreamLen );
3827 sal_Int8* pSeq = aGIFSeq.getArray();
3828 aGIFStream.Seek( STREAM_SEEK_TO_BEGIN );
3829 aGIFStream.Read( pSeq, nGIFSreamLen );
3830 com::sun::star::beans::PropertyValue aChunkProp, aFilterProp;
3831 aChunkProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "msOG" ) );
3832 aChunkProp.Value <<= aGIFSeq;
3833 aAdditionalChunkSequence[ 0 ] = aChunkProp;
3834 aFilterProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "AdditionalChunks" ) );
3835 aFilterProp.Value <<= aAdditionalChunkSequence;
3836 aFilterData[ 0 ] = aFilterProp;
3837 nErrCode = pFilter->ExportGraphic( aGraphic, String(), aStream,
3838 pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "PNG" ) ) ), &aFilterData );
3840 if ( nErrCode == ERRCODE_NONE )
3842 // !EMF p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : WMF;
3843 p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : EMF;
3844 aStream.Seek( STREAM_SEEK_TO_END );
3845 p_EscherBlibEntry->mnSize = aStream.Tell();
3846 pGraphicAry = (sal_uInt8*)aStream.GetData();
3848 if ( p_EscherBlibEntry->meBlibType == WMF ) // the fileheader is not used
3850 p_EscherBlibEntry->mnSize -= 22;
3851 pGraphicAry += 22;
3857 ESCHER_BlibType eBlibType = p_EscherBlibEntry->meBlibType;
3858 if ( p_EscherBlibEntry->mnSize && pGraphicAry && ( eBlibType != UNKNOWN ) )
3860 sal_uInt32 nExtra, nAtomSize = 0;
3861 sal_uInt32 nInstance, nUncompressedSize = p_EscherBlibEntry->mnSize;
3863 if ( mnFlags & _E_GRAPH_PROV_USE_INSTANCES )
3865 rPicOutStrm << (UINT32)( 0x7f90000 | (UINT16)( mnBlibEntrys << 4 ) )
3866 << (UINT32)0;
3867 nAtomSize = rPicOutStrm.Tell();
3868 if ( eBlibType == PNG )
3869 rPicOutStrm << (sal_uInt16)0x0606;
3870 else if ( eBlibType == WMF )
3871 rPicOutStrm << (sal_uInt16)0x0403;
3872 else if ( eBlibType == EMF )
3873 rPicOutStrm << (sal_uInt16)0x0402;
3874 else if ( eBlibType == PEG )
3875 rPicOutStrm << (sal_uInt16)0x0505;
3877 if ( ( eBlibType == PEG ) || ( eBlibType == PNG ) )
3879 nExtra = 17;
3880 p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
3881 nInstance = ( eBlibType == PNG ) ? 0xf01e6e00 : 0xf01d46a0;
3882 rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
3883 rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
3884 rPicOutStrm << (sal_uInt8)0xff;
3885 rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
3887 else
3889 ZCodec aZCodec( 0x8000, 0x8000 );
3890 aZCodec.BeginCompression();
3891 SvMemoryStream aDestStrm;
3892 aZCodec.Write( aDestStrm, pGraphicAry, p_EscherBlibEntry->mnSize );
3893 aZCodec.EndCompression();
3894 aDestStrm.Seek( STREAM_SEEK_TO_END );
3895 p_EscherBlibEntry->mnSize = aDestStrm.Tell();
3896 pGraphicAry = (sal_uInt8*)aDestStrm.GetData();
3897 if ( p_EscherBlibEntry->mnSize && pGraphicAry )
3899 nExtra = eBlibType == WMF ? 0x42 : 0x32; // !EMF -> no change
3900 p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
3901 nInstance = ( eBlibType == WMF ) ? 0xf01b2170 : 0xf01a3d40; // !EMF -> no change
3902 rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
3903 if ( eBlibType == WMF ) // !EMF -> no change
3904 rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
3905 rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
3908 ##913##
3909 For Word the stored size of the graphic is critical the
3910 metafile boundaries must match the actual graphics
3911 boundaries, and the width and height must be in EMU's
3913 If you don't do it this way then objects edited in the
3914 msoffice app may show strange behaviour as the size jumps
3915 around, and the original size and scaling factor in word
3916 will be a very strange figure
3918 UINT32 nPrefWidth = p_EscherBlibEntry->maPrefSize.Width();
3919 UINT32 nPrefHeight = p_EscherBlibEntry->maPrefSize.Height();
3920 UINT32 nWidth, nHeight;
3921 if ( pVisArea )
3923 nWidth = pVisArea->Width * 360;
3924 nHeight = pVisArea->Height * 360;
3926 else
3928 Size aPrefSize(lcl_SizeToEmu(p_EscherBlibEntry->maPrefSize, p_EscherBlibEntry->maPrefMapMode));
3929 nWidth = aPrefSize.Width() * 360;
3930 nHeight = aPrefSize.Height() * 360;
3932 rPicOutStrm << nUncompressedSize // WMFSize without FileHeader
3933 << (sal_Int32)0 // da die Originalgroesse des WMF's (ohne FileHeader)
3934 << (sal_Int32)0 // nicht mehr feststellbar ist, schreiben wir 10cm / x
3935 << nPrefWidth
3936 << nPrefHeight
3937 << nWidth
3938 << nHeight
3939 << p_EscherBlibEntry->mnSize
3940 << (sal_uInt16)0xfe00; // compression Flags
3941 rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
3944 if ( nAtomSize )
3946 sal_uInt32 nPos = rPicOutStrm.Tell();
3947 rPicOutStrm.Seek( nAtomSize - 4 );
3948 rPicOutStrm << (sal_uInt32)( nPos - nAtomSize );
3949 rPicOutStrm.Seek( nPos );
3951 nBlibId = ImplInsertBlib( p_EscherBlibEntry ), p_EscherBlibEntry = NULL;
3954 if ( p_EscherBlibEntry )
3955 delete p_EscherBlibEntry;
3956 return nBlibId;
3959 // ---------------------------------------------------------------------------------------------
3960 // ---------------------------------------------------------------------------------------------
3961 // ---------------------------------------------------------------------------------------------
3963 struct EscherConnectorRule
3965 sal_uInt32 nRuleId;
3966 sal_uInt32 nShapeA; // SPID of shape A
3967 sal_uInt32 nShapeB; // SPID of shape B
3968 sal_uInt32 nShapeC; // SPID of connector shape
3969 sal_uInt32 ncptiA; // Connection site Index of shape A
3970 sal_uInt32 ncptiB; // Connection site Index of shape B
3973 struct EscherShapeListEntry
3975 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aXShape;
3976 sal_uInt32 n_EscherId;
3978 EscherShapeListEntry( const ::com::sun::star::uno::Reference
3979 < ::com::sun::star::drawing::XShape > & rShape, sal_uInt32 nId ) :
3980 aXShape ( rShape ),
3981 n_EscherId ( nId ) {}
3984 sal_uInt32 EscherConnectorListEntry::GetClosestPoint( const Polygon& rPoly, const ::com::sun::star::awt::Point& rPoint )
3986 sal_uInt16 nCount = rPoly.GetSize();
3987 sal_uInt16 nClosest = nCount;
3988 double fDist = (sal_uInt32)0xffffffff;
3989 while( nCount-- )
3991 double fDistance = hypot( rPoint.X - rPoly[ nCount ].X(), rPoint.Y - rPoly[ nCount ].Y() );
3992 if ( fDistance < fDist )
3994 nClosest = nCount;
3995 fDist = fDistance;
3998 return nClosest;
4001 // ---------------------------------------------------------------------------------------------
4002 // bei Rechtecken bei Ellipsen bei Polygonen
4004 // nRule = 0 ->Top 0 ->Top nRule = Index auf ein (Poly)Polygon Punkt
4005 // 1 ->Left 2 ->Left
4006 // 2 ->Bottom 4 ->Bottom
4007 // 3 ->Right 6 ->Right
4009 sal_uInt32 EscherConnectorListEntry::GetConnectorRule( sal_Bool bFirst )
4011 sal_uInt32 nRule = 0;
4013 ::com::sun::star::uno::Any aAny;
4014 ::com::sun::star::awt::Point aRefPoint( ( bFirst ) ? maPointA : maPointB );
4015 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
4016 aXShape( ( bFirst ) ? mXConnectToA : mXConnectToB );
4018 String aString( (::rtl::OUString)aXShape->getShapeType() );
4019 ByteString aType( aString, RTL_TEXTENCODING_UTF8 );
4020 aType.Erase( 0, 13 ); // removing "com.sun.star."
4021 sal_uInt16 nPos = aType.Search( "Shape" );
4022 aType.Erase( nPos, 5 );
4024 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
4025 aPropertySet( aXShape, ::com::sun::star::uno::UNO_QUERY );
4027 if ( aType == "drawing.PolyPolygon" || aType == "drawing.PolyLine" )
4029 if ( aPropertySet.is() )
4031 if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4032 aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ) ) )
4034 ::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon =
4035 (::com::sun::star::drawing::PointSequenceSequence*)aAny.getValue();
4036 sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->getLength();
4037 ::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
4039 if ( pOuterSequence )
4041 sal_Int32 a, b, nIndex = 0;
4042 sal_uInt32 nDistance = 0xffffffff;
4043 for( a = 0; a < nOuterSequenceCount; a++ )
4045 ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
4046 if ( pInnerSequence )
4048 ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
4049 if ( pArray )
4051 for ( b = 0; b < pInnerSequence->getLength(); b++, nIndex++, pArray++ )
4053 sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
4054 if ( nDist < nDistance )
4056 nRule = nIndex;
4057 nDistance = nDist;
4067 else if ( ( aType == "drawing.OpenBezier" ) || ( aType == "drawing.OpenFreeHand" ) || ( aType == "drawing.PolyLinePath" )
4068 || ( aType == "drawing.ClosedBezier" ) || ( aType == "drawing.ClosedFreeHand" ) || ( aType == "drawing.PolyPolygonPath" ) )
4070 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
4071 aPropertySet2( aXShape, ::com::sun::star::uno::UNO_QUERY );
4072 if ( aPropertySet2.is() )
4074 if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4075 aPropertySet2, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ) ) )
4077 ::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon =
4078 (::com::sun::star::drawing::PolyPolygonBezierCoords*)aAny.getValue();
4079 sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->Coordinates.getLength();
4081 // Zeiger auf innere sequences holen
4082 ::com::sun::star::drawing::PointSequence* pOuterSequence =
4083 pSourcePolyPolygon->Coordinates.getArray();
4084 ::com::sun::star::drawing::FlagSequence* pOuterFlags =
4085 pSourcePolyPolygon->Flags.getArray();
4087 if ( pOuterSequence && pOuterFlags )
4089 sal_Int32 a, b, nIndex = 0;
4090 sal_uInt32 nDistance = 0xffffffff;
4092 for ( a = 0; a < nOuterSequenceCount; a++ )
4094 ::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
4095 ::com::sun::star::drawing::FlagSequence* pInnerFlags = pOuterFlags++;
4096 if ( pInnerSequence && pInnerFlags )
4098 ::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
4099 ::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
4100 if ( pArray && pFlags )
4102 for ( b = 0; b < pInnerSequence->getLength(); b++, pArray++ )
4104 PolyFlags ePolyFlags = *( (PolyFlags*)pFlags++ );
4105 if ( ePolyFlags == POLY_CONTROL )
4106 continue;
4107 sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
4108 if ( nDist < nDistance )
4110 nRule = nIndex;
4111 nDistance = nDist;
4113 nIndex++;
4122 else
4124 bool bRectangularConnection = true;
4126 if ( aType == "drawing.Custom" )
4128 SdrObject* pCustoShape( GetSdrObjectFromXShape( aXShape ) );
4129 if ( pCustoShape && pCustoShape->ISA( SdrObjCustomShape ) )
4131 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)
4132 pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
4134 const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
4135 const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
4136 const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
4138 rtl::OUString sShapeType;
4139 uno::Any* pType = rGeometryItem.GetPropertyValueByName( sType );
4140 if ( pType )
4141 *pType >>= sShapeType;
4142 MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
4144 uno::Any* pGluePointType = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePointType );
4146 sal_Int16 nGluePointType = sal_Int16();
4147 if ( !( pGluePointType &&
4148 ( *pGluePointType >>= nGluePointType ) ) )
4149 nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
4151 if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::CUSTOM )
4153 const SdrGluePointList* pList = pCustoShape->GetGluePointList();
4154 if ( pList )
4156 Polygon aPoly;
4157 USHORT nNum, nAnz = pList->GetCount();
4158 if ( nAnz )
4160 for ( nNum = 0; nNum < nAnz; nNum++ )
4162 const SdrGluePoint& rGP = (*pList)[ nNum ];
4163 Point aPt( rGP.GetAbsolutePos( *pCustoShape ) );
4164 aPoly.Insert( POLY_APPEND, aPt );
4166 nRule = GetClosestPoint( aPoly, aRefPoint );
4167 bRectangularConnection = false;
4171 else if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::SEGMENTS )
4173 SdrObject* pPoly = pCustoShape->DoConvertToPolyObj( TRUE );
4174 if ( pPoly && pPoly->ISA( SdrPathObj ) )
4176 sal_Int16 a, b, nIndex = 0;
4177 sal_uInt32 nDistance = 0xffffffff;
4179 // #i74631# use explicit constructor here. Also XPolyPolygon is not necessary,
4180 // reducing to PolyPolygon
4181 const PolyPolygon aPolyPoly(((SdrPathObj*)pPoly)->GetPathPoly());
4183 for ( a = 0; a < aPolyPoly.Count(); a++ )
4185 const Polygon& rPoly = aPolyPoly.GetObject( a );
4186 for ( b = 0; b < rPoly.GetSize(); b++ )
4188 if ( rPoly.GetFlags( b ) != POLY_NORMAL )
4189 continue;
4190 const Point& rPt = rPoly[ b ];
4191 sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - rPt.X(), aRefPoint.Y - rPt.Y() );
4192 if ( nDist < nDistance )
4194 nRule = nIndex;
4195 nDistance = nDist;
4197 nIndex++;
4200 if ( nDistance != 0xffffffff )
4201 bRectangularConnection = false;
4206 if ( bRectangularConnection )
4208 ::com::sun::star::awt::Point aPoint( aXShape->getPosition() );
4209 ::com::sun::star::awt::Size aSize( aXShape->getSize() );
4211 Rectangle aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
4212 Point aCenter( aRect.Center() );
4213 Polygon aPoly( 4 );
4215 aPoly[ 0 ] = Point( aCenter.X(), aRect.Top() );
4216 aPoly[ 1 ] = Point( aRect.Left(), aCenter.Y() );
4217 aPoly[ 2 ] = Point( aCenter.X(), aRect.Bottom() );
4218 aPoly[ 3 ] = Point( aRect.Right(), aCenter.Y() );
4220 sal_Int32 nAngle = ( EscherPropertyValueHelper::GetPropertyValue( aAny,
4221 aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), sal_True ) )
4222 ? *((sal_Int32*)aAny.getValue() )
4223 : 0;
4224 if ( nAngle )
4225 aPoly.Rotate( aRect.TopLeft(), (sal_uInt16)( ( nAngle + 5 ) / 10 ) );
4226 nRule = GetClosestPoint( aPoly, aRefPoint );
4228 if ( aType == "drawing.Ellipse" )
4229 nRule <<= 1; // In PPT hat eine Ellipse 8 Möglichkeiten sich zu connecten
4232 return nRule;
4235 EscherSolverContainer::~EscherSolverContainer()
4237 void* pP;
4239 for( pP = maShapeList.First(); pP; pP = maShapeList.Next() )
4240 delete (EscherShapeListEntry*)pP;
4241 for( pP = maConnectorList.First(); pP; pP = maConnectorList.Next() )
4242 delete (EscherConnectorListEntry*)pP;
4245 void EscherSolverContainer::AddShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape, sal_uInt32 nId )
4247 maShapeList.Insert( new EscherShapeListEntry( rXShape, nId ), LIST_APPEND );
4250 void EscherSolverContainer::AddConnector( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConnector,
4251 const ::com::sun::star::awt::Point& rPA,
4252 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConA,
4253 const ::com::sun::star::awt::Point& rPB,
4254 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConB )
4256 maConnectorList.Insert( new EscherConnectorListEntry( rConnector, rPA, rConA, rPB, rConB ), LIST_APPEND );
4259 sal_uInt32 EscherSolverContainer::GetShapeId( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) const
4261 for ( EscherShapeListEntry* pPtr = (EscherShapeListEntry*)((List&)maShapeList).First();
4262 pPtr; pPtr = (EscherShapeListEntry*)((List&)maShapeList).Next() )
4264 if ( rXShape == pPtr->aXShape )
4265 return ( pPtr->n_EscherId );
4267 return 0;
4270 void EscherSolverContainer::WriteSolver( SvStream& rStrm )
4272 sal_uInt32 nCount = maConnectorList.Count();
4273 if ( nCount )
4275 sal_uInt32 nRecHdPos, nCurrentPos, nSize;
4276 rStrm << (sal_uInt16)( ( nCount << 4 ) | 0xf ) // open an ESCHER_SolverContainer
4277 << (sal_uInt16)ESCHER_SolverContainer //
4278 << (sal_uInt32)0; //
4280 nRecHdPos = rStrm.Tell() - 4;
4282 EscherConnectorRule aConnectorRule;
4283 aConnectorRule.nRuleId = 2;
4284 for ( EscherConnectorListEntry* pPtr = (EscherConnectorListEntry*)maConnectorList.First();
4285 pPtr; pPtr = (EscherConnectorListEntry*)maConnectorList.Next() )
4287 aConnectorRule.ncptiA = aConnectorRule.ncptiB = 0xffffffff;
4288 aConnectorRule.nShapeC = GetShapeId( pPtr->mXConnector );
4289 aConnectorRule.nShapeA = GetShapeId( pPtr->mXConnectToA );
4290 aConnectorRule.nShapeB = GetShapeId( pPtr->mXConnectToB );
4292 if ( aConnectorRule.nShapeC )
4294 if ( aConnectorRule.nShapeA )
4295 aConnectorRule.ncptiA = pPtr->GetConnectorRule( sal_True );
4296 if ( aConnectorRule.nShapeB )
4297 aConnectorRule.ncptiB = pPtr->GetConnectorRule( sal_False );
4299 rStrm << (sal_uInt32)( ( ESCHER_ConnectorRule << 16 ) | 1 ) // atom hd
4300 << (sal_uInt32)24 //
4301 << aConnectorRule.nRuleId
4302 << aConnectorRule.nShapeA
4303 << aConnectorRule.nShapeB
4304 << aConnectorRule.nShapeC
4305 << aConnectorRule.ncptiA
4306 << aConnectorRule.ncptiB;
4308 aConnectorRule.nRuleId += 2;
4311 nCurrentPos = rStrm.Tell(); // close the ESCHER_SolverContainer
4312 nSize = ( nCurrentPos - nRecHdPos ) - 4;//
4313 rStrm.Seek( nRecHdPos ); //
4314 rStrm << nSize; //
4315 rStrm.Seek( nCurrentPos ); //
4319 // ---------------------------------------------------------------------------------------------
4320 // ---------------------------------------------------------------------------------------------
4321 // ---------------------------------------------------------------------------------------------
4323 EscherEx::EscherEx( SvStream& rOutStrm, UINT32 nDrawings ) :
4324 EscherGraphicProvider ( 0 ),
4325 mpOutStrm ( &rOutStrm ),
4326 mnDrawings ( nDrawings ),
4328 mnGroupLevel ( 0 ),
4329 mnHellLayerId ( USHRT_MAX ),
4331 mbEscherSpgr ( FALSE ),
4332 mbEscherDgg ( FALSE ), // TRUE, wenn jemals ein ESCHER_Dgg angelegt wurde, dieser wird dann im Dest. aktualisiert
4333 mbEscherDg ( FALSE ),
4334 mbOleEmf ( FALSE )
4336 mnStrmStartOfs = mpOutStrm->Tell();
4337 mpImplEscherExSdr = new ImplEscherExSdr( *this );
4340 // ---------------------------------------------------------------------------------------------
4342 void EscherEx::Flush( SvStream* pPicStreamMergeBSE /* = NULL */ )
4344 if ( mbEscherDgg ) // ESCHER_Dgg anpassen
4346 PtReplaceOrInsert( ESCHER_Persist_CurrentPosition, mpOutStrm->Tell() );
4347 if ( DoSeek( ESCHER_Persist_Dgg ) )
4349 *mpOutStrm << mnCurrentShapeID << (UINT32)( mnFIDCLs + 1 ) << mnTotalShapesDgg << mnDrawings;
4351 if ( HasGraphics() )
4353 if ( DoSeek( ESCHER_Persist_BlibStoreContainer ) ) // ESCHER_BlibStoreContainer schreiben
4355 sal_uInt32 nAddBytes = GetBlibStoreContainerSize( pPicStreamMergeBSE );
4356 if ( nAddBytes )
4358 InsertAtCurrentPos( nAddBytes, TRUE ); // platz schaffen fuer Blib Container samt seinen Blib Atomen
4359 WriteBlibStoreContainer( *mpOutStrm, pPicStreamMergeBSE );
4363 mpOutStrm->Seek( PtGetOffsetByID( ESCHER_Persist_CurrentPosition ) );
4367 // ---------------------------------------------------------------------------------------------
4369 EscherEx::~EscherEx()
4371 delete mpImplEscherExSdr;
4374 // ---------------------------------------------------------------------------------------------
4376 void EscherEx::InsertAtCurrentPos( UINT32 nBytes, BOOL bContainer )
4378 UINT32 nSize, nType, nSource, nBufSize, nToCopy, nCurPos = mpOutStrm->Tell();
4379 BYTE* pBuf;
4381 // Persist table anpassen
4382 for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
4384 UINT32 nOfs = ((EscherPersistEntry*)pPtr)->mnOffset;
4385 if ( nOfs >= nCurPos )
4386 ((EscherPersistEntry*)pPtr)->mnOffset += nBytes;
4389 // container und atom sizes anpassen
4390 mpOutStrm->Seek( mnStrmStartOfs );
4391 while ( mpOutStrm->Tell() < nCurPos )
4393 *mpOutStrm >> nType >> nSize;
4394 if ( ( mpOutStrm->Tell() + nSize ) >= ( ( bContainer ) ? nCurPos + 1 : nCurPos ) )
4396 mpOutStrm->SeekRel( -4 );
4397 *mpOutStrm << (UINT32)( nSize + nBytes );
4398 if ( ( nType & 0xf ) != 0xf )
4399 mpOutStrm->SeekRel( nSize );
4401 else
4402 mpOutStrm->SeekRel( nSize );
4404 std::vector< sal_uInt32 >::iterator aIter( mOffsets.begin() );
4405 std::vector< sal_uInt32 >::iterator aEnd( mOffsets.end() );
4406 while( aIter != aEnd )
4408 if ( *aIter > nCurPos )
4409 *aIter += nBytes;
4410 aIter++;
4412 mpOutStrm->Seek( STREAM_SEEK_TO_END );
4413 nSource = mpOutStrm->Tell();
4414 nToCopy = nSource - nCurPos; // Stream um nBytes vergroessern
4415 pBuf = new BYTE[ 0x40000 ]; // 256KB Buffer
4416 while ( nToCopy )
4418 nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
4419 nToCopy -= nBufSize;
4420 nSource -= nBufSize;
4421 mpOutStrm->Seek( nSource );
4422 mpOutStrm->Read( pBuf, nBufSize );
4423 mpOutStrm->Seek( nSource + nBytes );
4424 mpOutStrm->Write( pBuf, nBufSize );
4426 delete[] pBuf;
4427 mpOutStrm->Seek( nCurPos );
4430 // ---------------------------------------------------------------------------------------------
4432 BOOL EscherEx::SeekBehindRecHeader( UINT16 nRecType )
4434 UINT32 nOldPos, nStreamEnd, nType, nSize;
4436 nOldPos = mpOutStrm->Tell();
4437 nStreamEnd = mpOutStrm->Seek( STREAM_SEEK_TO_END );
4438 mpOutStrm->Seek( nOldPos );
4439 while ( mpOutStrm->Tell() < nStreamEnd )
4441 *mpOutStrm >> nType >> nSize;
4442 if ( ( nType >> 16 ) == nRecType )
4443 return TRUE;
4444 if ( ( nType & 0xf ) != 0xf )
4445 mpOutStrm->SeekRel( nSize );
4447 mpOutStrm->Seek( nOldPos );
4448 return FALSE;
4451 // ---------------------------------------------------------------------------------------------
4453 void EscherEx::InsertPersistOffset( UINT32 nKey, UINT32 nOffset )
4455 PtInsert( ESCHER_Persist_PrivateEntry | nKey, nOffset );
4458 // ---------------------------------------------------------------------------------------------
4460 BOOL EscherEx::DoSeek( UINT32 nKey )
4462 UINT32 nPos = PtGetOffsetByID( nKey );
4463 if ( nPos )
4464 mpOutStrm->Seek( nPos );
4465 else
4467 if (! PtIsID( nKey ) )
4468 return FALSE;
4469 mpOutStrm->Seek( 0 );
4471 return TRUE;
4474 // ---------------------------------------------------------------------------------------------
4476 BOOL EscherEx::SeekToPersistOffset( UINT32 nKey )
4478 return DoSeek( ESCHER_Persist_PrivateEntry | nKey );
4481 // ---------------------------------------------------------------------------------------------
4483 BOOL EscherEx::InsertAtPersistOffset( UINT32 nKey, UINT32 nValue )
4485 UINT32 nOldPos = mpOutStrm->Tell();
4486 BOOL bRetValue = SeekToPersistOffset( nKey );
4487 if ( bRetValue )
4489 *mpOutStrm << nValue;
4490 mpOutStrm->Seek( nOldPos );
4492 return bRetValue;
4495 // ---------------------------------------------------------------------------------------------
4497 void EscherEx::OpenContainer( UINT16 nEscherContainer, int nRecInstance )
4499 *mpOutStrm << (UINT16)( ( nRecInstance << 4 ) | 0xf ) << nEscherContainer << (UINT32)0;
4500 mOffsets.push_back( mpOutStrm->Tell() - 4 );
4501 mRecTypes.push_back( nEscherContainer );
4502 switch( nEscherContainer )
4504 case ESCHER_DggContainer :
4506 mbEscherDgg = TRUE;
4507 mnFIDCLs = mnDrawings;
4508 mnCurrentDg = 0;
4509 mnCurrentShapeID = 0;
4510 mnTotalShapesDgg = 0;
4511 mnCurrentShapeMaximumID = 0;
4512 AddAtom( 16 + ( mnDrawings << 3 ), ESCHER_Dgg ); // an FDGG and several FIDCLs
4513 PtReplaceOrInsert( ESCHER_Persist_Dgg, mpOutStrm->Tell() );
4514 *mpOutStrm << (UINT32)0 // the current maximum shape ID
4515 << (UINT32)0 // the number of ID clusters + 1
4516 << (UINT32)0 // the number of total shapes saved
4517 << (UINT32)0; // the total number of drawings saved
4518 PtReplaceOrInsert( ESCHER_Persist_Dgg_FIDCL, mpOutStrm->Tell() );
4519 for ( UINT32 i = 0; i < mnFIDCLs; i++ ) // Dummy FIDCLs einfuegen
4521 *mpOutStrm << (UINT32)0 << (UINT32)0; // Drawing Nummer, Anzahl der Shapes in diesem IDCL
4523 PtReplaceOrInsert( ESCHER_Persist_BlibStoreContainer, mpOutStrm->Tell() );
4525 break;
4527 case ESCHER_DgContainer :
4529 if ( mbEscherDgg )
4531 if ( !mbEscherDg )
4533 mbEscherDg = TRUE;
4534 mnCurrentDg++;
4535 mnTotalShapesDg = 0;
4536 mnTotalShapeIdUsedDg = 0;
4537 mnCurrentShapeID = ( mnCurrentShapeMaximumID &~0x3ff ) + 0x400; // eine neue Seite bekommt immer eine neue ShapeId die ein vielfaches von 1024 ist,
4538 // damit ist erste aktuelle Shape ID 0x400
4539 AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
4540 PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
4541 *mpOutStrm << (UINT32)0 // The number of shapes in this drawing
4542 << (UINT32)0; // The last MSOSPID given to an SP in this DG
4546 break;
4548 case ESCHER_SpgrContainer :
4550 if ( mbEscherDg )
4552 mbEscherSpgr = TRUE;
4555 break;
4557 case ESCHER_SpContainer :
4560 break;
4562 default:
4563 break;
4567 // ---------------------------------------------------------------------------------------------
4569 void EscherEx::CloseContainer()
4571 sal_uInt32 nSize, nPos = mpOutStrm->Tell();
4572 nSize = ( nPos - mOffsets.back() ) - 4;
4573 mpOutStrm->Seek( mOffsets.back() );
4574 *mpOutStrm << nSize;
4576 switch( mRecTypes.back() )
4578 case ESCHER_DgContainer :
4580 if ( mbEscherDg )
4582 mbEscherDg = FALSE;
4583 if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
4585 // shapeanzahl des drawings setzen
4586 mnTotalShapesDgg += mnTotalShapesDg;
4587 *mpOutStrm << mnTotalShapesDg << mnCurrentShapeMaximumID;
4588 if ( DoSeek( ESCHER_Persist_Dgg_FIDCL ) )
4590 if ( mnTotalShapesDg == 0 )
4592 mpOutStrm->SeekRel( 8 );
4594 else
4596 if ( mnTotalShapeIdUsedDg )
4598 // die benutzten Shape Ids des drawings in die fidcls setzen
4599 UINT32 i, nFIDCL = ( ( mnTotalShapeIdUsedDg - 1 ) / 0x400 );
4600 if ( nFIDCL )
4602 if ( nPos > mpOutStrm->Tell() )
4603 nPos += ( nFIDCL << 3 );
4605 mnFIDCLs += nFIDCL;
4606 InsertAtCurrentPos( nFIDCL << 3 ); // platz schaffen fuer weitere FIDCL's
4608 for ( i = 0; i <= nFIDCL; i++ )
4610 *mpOutStrm << mnCurrentDg;
4611 if ( i < nFIDCL )
4612 *mpOutStrm << (UINT32)0x400;
4613 else
4615 UINT32 nShapesLeft = mnTotalShapeIdUsedDg % 0x400;
4616 if ( !nShapesLeft )
4617 nShapesLeft = 0x400;
4618 *mpOutStrm << (UINT32)nShapesLeft;
4623 PtReplaceOrInsert( ESCHER_Persist_Dgg_FIDCL, mpOutStrm->Tell() ); // neuen FIDCL Offset fuer naechste Seite
4628 break;
4630 case ESCHER_SpgrContainer :
4632 if ( mbEscherSpgr )
4634 mbEscherSpgr = FALSE;
4638 break;
4640 default:
4641 break;
4643 mOffsets.pop_back();
4644 mRecTypes.pop_back();
4645 mpOutStrm->Seek( nPos );
4648 // ---------------------------------------------------------------------------------------------
4650 void EscherEx::BeginAtom()
4652 mnCountOfs = mpOutStrm->Tell();
4653 *mpOutStrm << (UINT32)0 << (UINT32)0; // record header wird spaeter geschrieben
4656 // ---------------------------------------------------------------------------------------------
4658 void EscherEx::EndAtom( UINT16 nRecType, int nRecVersion, int nRecInstance )
4660 UINT32 nOldPos = mpOutStrm->Tell();
4661 mpOutStrm->Seek( mnCountOfs );
4662 sal_uInt32 nSize = nOldPos - mnCountOfs;
4663 *mpOutStrm << (UINT16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << (UINT32)( nSize - 8 );
4664 mpOutStrm->Seek( nOldPos );
4667 // ---------------------------------------------------------------------------------------------
4669 void EscherEx::AddAtom( UINT32 nAtomSize, UINT16 nRecType, int nRecVersion, int nRecInstance )
4671 *mpOutStrm << (UINT16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << nAtomSize;
4674 // ---------------------------------------------------------------------------------------------
4676 void EscherEx::AddChildAnchor( const Rectangle& rRect )
4678 AddAtom( 16, ESCHER_ChildAnchor );
4679 GetStream() << (INT32)rRect.Left()
4680 << (INT32)rRect.Top()
4681 << (INT32)rRect.Right()
4682 << (INT32)rRect.Bottom();
4685 // ---------------------------------------------------------------------------------------------
4687 void EscherEx::AddClientAnchor( const Rectangle& rRect )
4689 AddAtom( 8, ESCHER_ClientAnchor );
4690 *mpOutStrm << (sal_Int16)rRect.Top()
4691 << (sal_Int16)rRect.Left()
4692 << (sal_Int16)( rRect.GetWidth() + rRect.Left() )
4693 << (sal_Int16)( rRect.GetHeight() + rRect.Top() );
4696 // ---------------------------------------------------------------------------------------------
4698 EscherExHostAppData* EscherEx::EnterAdditionalTextGroup()
4700 return NULL;
4703 // ---------------------------------------------------------------------------------------------
4705 UINT32 EscherEx::EnterGroup( const String& rShapeName, const Rectangle* pBoundRect )
4707 Rectangle aRect;
4708 if( pBoundRect )
4709 aRect = *pBoundRect;
4711 OpenContainer( ESCHER_SpgrContainer );
4712 OpenContainer( ESCHER_SpContainer );
4713 AddAtom( 16, ESCHER_Spgr, 1 );
4714 PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel,
4715 mpOutStrm->Tell() );
4716 *mpOutStrm << (INT32)aRect.Left() // Bounding box fuer die Gruppierten shapes an die sie attached werden
4717 << (INT32)aRect.Top()
4718 << (INT32)aRect.Right()
4719 << (INT32)aRect.Bottom();
4721 UINT32 nShapeId = GetShapeID();
4722 if ( !mnGroupLevel )
4723 AddShape( ESCHER_ShpInst_Min, 5, nShapeId ); // Flags: Group | Patriarch
4724 else
4726 AddShape( ESCHER_ShpInst_Min, 0x201, nShapeId ); // Flags: Group | HaveAnchor
4727 EscherPropertyContainer aPropOpt;
4728 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x00040004 );
4729 aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
4730 aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
4732 // #i51348# shape name
4733 if( rShapeName.Len() > 0 )
4734 aPropOpt.AddOpt( ESCHER_Prop_wzName, rShapeName );
4736 Commit( aPropOpt, aRect );
4737 if ( mnGroupLevel > 1 )
4738 AddChildAnchor( aRect );
4740 EscherExHostAppData* pAppData = mpImplEscherExSdr->ImplGetHostData();
4741 if( pAppData )
4743 if ( mnGroupLevel <= 1 )
4744 pAppData->WriteClientAnchor( *this, aRect );
4745 pAppData->WriteClientData( *this );
4748 CloseContainer(); // ESCHER_SpContainer
4749 mnGroupLevel++;
4750 return nShapeId;
4753 UINT32 EscherEx::EnterGroup( const Rectangle* pBoundRect )
4755 return EnterGroup( String::EmptyString(), pBoundRect );
4758 // ---------------------------------------------------------------------------------------------
4760 BOOL EscherEx::SetGroupSnapRect( UINT32 nGroupLevel, const Rectangle& rRect )
4762 BOOL bRetValue = FALSE;
4763 if ( nGroupLevel )
4765 UINT32 nCurrentPos = mpOutStrm->Tell();
4766 if ( DoSeek( ESCHER_Persist_Grouping_Snap | ( nGroupLevel - 1 ) ) )
4768 *mpOutStrm << (INT32)rRect.Left() // Bounding box fuer die Gruppierten shapes an die sie attached werden
4769 << (INT32)rRect.Top()
4770 << (INT32)rRect.Right()
4771 << (INT32)rRect.Bottom();
4772 mpOutStrm->Seek( nCurrentPos );
4775 return bRetValue;
4778 // ---------------------------------------------------------------------------------------------
4780 BOOL EscherEx::SetGroupLogicRect( UINT32 nGroupLevel, const Rectangle& rRect )
4782 BOOL bRetValue = FALSE;
4783 if ( nGroupLevel )
4785 UINT32 nCurrentPos = mpOutStrm->Tell();
4786 if ( DoSeek( ESCHER_Persist_Grouping_Logic | ( nGroupLevel - 1 ) ) )
4788 *mpOutStrm << (INT16)rRect.Top() << (INT16)rRect.Left() << (INT16)rRect.Right() << (INT16)rRect.Bottom();
4789 mpOutStrm->Seek( nCurrentPos );
4792 return bRetValue;
4795 // ---------------------------------------------------------------------------------------------
4797 void EscherEx::LeaveGroup()
4799 --mnGroupLevel;
4800 PtDelete( ESCHER_Persist_Grouping_Snap | mnGroupLevel );
4801 PtDelete( ESCHER_Persist_Grouping_Logic | mnGroupLevel );
4802 CloseContainer();
4805 // ---------------------------------------------------------------------------------------------
4807 void EscherEx::AddShape( UINT32 nShpInstance, UINT32 nFlags, UINT32 nShapeID )
4809 AddAtom( 8, ESCHER_Sp, 2, nShpInstance );
4811 if ( !nShapeID )
4812 nShapeID = GetShapeID();
4814 if ( nFlags ^ 1 ) // is this a group shape ?
4815 { // if not
4816 if ( mnGroupLevel > 1 )
4817 nFlags |= 2; // this not a topmost shape
4819 *mpOutStrm << nShapeID << nFlags;
4821 if ( mbEscherSpgr )
4822 mnTotalShapesDg++;
4825 // ---------------------------------------------------------------------------------------------
4827 UINT32 EscherEx::GetShapeID()
4829 mnCurrentShapeMaximumID = mnCurrentShapeID; // maximum setzen
4830 mnCurrentShapeID++; // mnCurrentShape ID auf nachste freie ID
4831 mnTotalShapeIdUsedDg++;
4832 return mnCurrentShapeMaximumID;
4835 // ---------------------------------------------------------------------------------------------
4837 void EscherEx::Commit( EscherPropertyContainer& rProps, const Rectangle& )
4839 rProps.Commit( GetStream() );
4842 // ---------------------------------------------------------------------------------------------
4844 UINT32 EscherEx::GetColor( const UINT32 nSOColor, BOOL bSwap )
4846 if ( bSwap )
4848 UINT32 nColor = nSOColor & 0xff00; // GRUEN
4849 nColor |= (BYTE)( nSOColor ) << 16; // ROT
4850 nColor |= (BYTE)( nSOColor >> 16 ); // BLAU
4851 return nColor;
4853 else
4854 return nSOColor & 0xffffff;
4857 // ---------------------------------------------------------------------------------------------
4859 UINT32 EscherEx::GetColor( const Color& rSOColor, BOOL bSwap )
4861 UINT32 nColor = ( rSOColor.GetRed() << 16 );
4862 nColor |= ( rSOColor.GetGreen() << 8 );
4863 nColor |= rSOColor.GetBlue();
4865 if ( !bSwap )
4866 nColor = GetColor( nColor, TRUE );
4868 return nColor;
4871 // ---------------------------------------------------------------------------------------------