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