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