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