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_xmloff.hxx" 26 #include "ximpcustomshape.hxx" 27 #include "ximpshap.hxx" 28 #include "xmlehelp.hxx" 29 #include <rtl/math.hxx> 30 #include <rtl/ustrbuf.hxx> 31 #include <rtl/ustring.hxx> 32 #include <com/sun/star/uno/Reference.h> 33 #include <com/sun/star/beans/XPropertySet.hpp> 34 #include <com/sun/star/xml/sax/XAttributeList.hpp> 35 #include <com/sun/star/container/XIndexContainer.hpp> 36 #include <xmloff/xmltoken.hxx> 37 #include "EnhancedCustomShapeToken.hxx" 38 #include <xmloff/xmlimp.hxx> 39 #include <xmloff/xmltkmap.hxx> 40 #include "xmloff/xmlnmspe.hxx" 41 #include <xmloff/nmspmap.hxx> 42 #include <xmloff/xmluconv.hxx> 43 #include "xexptran.hxx" 44 #include "xmloff/xmlerror.hxx" 45 #include <tools/debug.hxx> 46 #include <com/sun/star/drawing/Direction3D.hpp> 47 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> 48 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp> 49 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> 50 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> 51 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> 52 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> 53 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp> 54 #include <com/sun/star/drawing/ProjectionMode.hpp> 55 #include <com/sun/star/drawing/HomogenMatrix3.hpp> 56 #include <basegfx/vector/b2dvector.hxx> 57 #include <hash_map> 58 59 using namespace ::com::sun::star; 60 using namespace ::xmloff::token; 61 using namespace ::xmloff::EnhancedCustomShapeToken; 62 63 TYPEINIT1( XMLEnhancedCustomShapeContext, SvXMLImportContext ); 64 65 XMLEnhancedCustomShapeContext::XMLEnhancedCustomShapeContext( SvXMLImport& rImport, 66 ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape, 67 sal_uInt16 nPrefix, const rtl::OUString& rLocalName, 68 std::vector< com::sun::star::beans::PropertyValue >& rCustomShapeGeometry ) : 69 SvXMLImportContext( rImport, nPrefix, rLocalName ), 70 mrUnitConverter( rImport.GetMM100UnitConverter() ), 71 mrxShape( rxShape ), 72 mrCustomShapeGeometry( rCustomShapeGeometry ) 73 { 74 } 75 76 const SvXMLEnumMapEntry aXML_GluePointEnumMap[] = 77 { 78 { XML_NONE, 0 }, 79 { XML_SEGMENTS, 1 }, 80 { XML_NONE, 2 }, 81 { XML_RECTANGLE, 3 }, 82 { XML_TOKEN_INVALID, 0 } 83 }; 84 void GetBool( std::vector< com::sun::star::beans::PropertyValue >& rDest, 85 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 86 { 87 sal_Bool bAttrBool; 88 if ( SvXMLUnitConverter::convertBool( bAttrBool, rValue ) ) 89 { 90 beans::PropertyValue aProp; 91 aProp.Name = EASGet( eDestProp ); 92 aProp.Value <<= bAttrBool; 93 rDest.push_back( aProp ); 94 } 95 } 96 97 void GetInt32( std::vector< com::sun::star::beans::PropertyValue >& rDest, 98 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 99 { 100 sal_Int32 nAttrNumber; 101 if ( SvXMLUnitConverter::convertNumber( nAttrNumber, rValue ) ) 102 { 103 beans::PropertyValue aProp; 104 aProp.Name = EASGet( eDestProp ); 105 aProp.Value <<= nAttrNumber; 106 rDest.push_back( aProp ); 107 } 108 } 109 110 void GetDouble( std::vector< com::sun::star::beans::PropertyValue >& rDest, 111 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 112 { 113 double fAttrDouble; 114 if ( SvXMLUnitConverter::convertDouble( fAttrDouble, rValue ) ) 115 { 116 beans::PropertyValue aProp; 117 aProp.Name = EASGet( eDestProp ); 118 aProp.Value <<= fAttrDouble; 119 rDest.push_back( aProp ); 120 } 121 } 122 123 void GetDistance( std::vector< com::sun::star::beans::PropertyValue >& rDest, 124 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 125 { 126 double fAttrDouble; 127 MapUnit eSrcUnit( SvXMLExportHelper::GetUnitFromString( rValue, MAP_100TH_MM ) ); 128 if ( SvXMLUnitConverter::convertDouble( fAttrDouble, rValue, eSrcUnit, MAP_100TH_MM ) ) 129 { 130 beans::PropertyValue aProp; 131 aProp.Name = EASGet( eDestProp ); 132 aProp.Value <<= fAttrDouble; 133 rDest.push_back( aProp ); 134 } 135 } 136 137 void GetString( std::vector< com::sun::star::beans::PropertyValue >& rDest, 138 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 139 { 140 beans::PropertyValue aProp; 141 aProp.Name = EASGet( eDestProp ); 142 aProp.Value <<= rValue; 143 rDest.push_back( aProp ); 144 } 145 146 void GetEnum( std::vector< com::sun::star::beans::PropertyValue >& rDest, 147 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp, 148 const SvXMLEnumMapEntry& rMap ) 149 { 150 sal_uInt16 eKind; 151 if( SvXMLUnitConverter::convertEnum( eKind, rValue, &rMap ) ) 152 { 153 sal_Int16 nEnum = (sal_Int16)eKind; 154 beans::PropertyValue aProp; 155 aProp.Name = EASGet( eDestProp ); 156 aProp.Value <<= nEnum; 157 rDest.push_back( aProp ); 158 } 159 } 160 161 void GetDoublePercentage( std::vector< com::sun::star::beans::PropertyValue >& rDest, 162 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 163 { 164 MapUnit eSrcUnit = SvXMLExportHelper::GetUnitFromString( rValue, MAP_100TH_MM ); 165 if ( eSrcUnit == MAP_RELATIVE ) 166 { 167 rtl_math_ConversionStatus eStatus; 168 double fAttrDouble = ::rtl::math::stringToDouble( rValue, 169 (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); 170 if ( eStatus == rtl_math_ConversionStatus_Ok ) 171 { 172 beans::PropertyValue aProp; 173 aProp.Name = EASGet( eDestProp ); 174 aProp.Value <<= fAttrDouble; 175 rDest.push_back( aProp ); 176 } 177 } 178 } 179 180 void GetB3DVector( std::vector< com::sun::star::beans::PropertyValue >& rDest, 181 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 182 { 183 ::basegfx::B3DVector aB3DVector; 184 if ( SvXMLUnitConverter::convertB3DVector( aB3DVector, rValue ) ) 185 { 186 drawing::Direction3D aDirection3D( aB3DVector.getX(), aB3DVector.getY(), aB3DVector.getZ() ); 187 beans::PropertyValue aProp; 188 aProp.Name = EASGet( eDestProp ); 189 aProp.Value <<= aDirection3D; 190 rDest.push_back( aProp ); 191 } 192 } 193 194 sal_Bool GetEquationName( const rtl::OUString& rEquation, const sal_Int32 nStart, rtl::OUString& rEquationName ) 195 { 196 sal_Int32 nIndex = nStart; 197 while( nIndex < rEquation.getLength() ) 198 { 199 sal_Unicode nChar = rEquation[ nIndex ]; 200 if ( 201 ( ( nChar >= 'a' ) && ( nChar <= 'z' ) ) 202 || ( ( nChar >= 'A' ) && ( nChar <= 'Z' ) ) 203 || ( ( nChar >= '0' ) && ( nChar <= '9' ) ) 204 ) 205 { 206 nIndex++; 207 } 208 else 209 break; 210 } 211 sal_Bool bValid = ( nIndex - nStart ) != 0; 212 if ( bValid ) 213 rEquationName = rEquation.copy( nStart, nIndex - nStart ); 214 return bValid; 215 } 216 217 sal_Bool GetNextParameter( com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter, sal_Int32& nIndex, const rtl::OUString& rParaString ) 218 { 219 if ( nIndex >= rParaString.getLength() ) 220 return sal_False; 221 222 sal_Bool bValid = sal_True; 223 sal_Bool bNumberRequired = sal_True; 224 sal_Bool bMustBePositiveWholeNumbered = sal_False; 225 226 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL; 227 if ( rParaString[ nIndex ] == (sal_Unicode)'$' ) 228 { 229 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT; 230 bMustBePositiveWholeNumbered = sal_True; 231 nIndex++; 232 } 233 else if ( rParaString[ nIndex ] == (sal_Unicode)'?' ) 234 { 235 nIndex++; 236 bNumberRequired = sal_False; 237 rtl::OUString aEquationName; 238 bValid = GetEquationName( rParaString, nIndex, aEquationName ); 239 if ( bValid ) 240 { 241 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION; 242 rParameter.Value <<= aEquationName; 243 nIndex += aEquationName.getLength(); 244 } 245 } 246 else if ( rParaString[ nIndex ] > (sal_Unicode)'9' ) 247 { 248 bNumberRequired = sal_False; 249 if ( rParaString.matchIgnoreAsciiCaseAsciiL( "left", 4, nIndex ) ) 250 { 251 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT; 252 nIndex += 4; 253 } 254 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "top", 3, nIndex ) ) 255 { 256 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP; 257 nIndex += 3; 258 } 259 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "right", 5, nIndex ) ) 260 { 261 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT; 262 nIndex += 5; 263 } 264 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "bottom", 6, nIndex ) ) 265 { 266 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM; 267 nIndex += 6; 268 } 269 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "xstretch", 8, nIndex ) ) 270 { 271 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::XSTRETCH; 272 nIndex += 8; 273 } 274 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "ystretch", 8, nIndex ) ) 275 { 276 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::YSTRETCH; 277 nIndex += 8; 278 } 279 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "hasstroke", 9, nIndex ) ) 280 { 281 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::HASSTROKE; 282 nIndex += 9; 283 } 284 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "hasfill", 7, nIndex ) ) 285 { 286 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::HASFILL; 287 nIndex += 7; 288 } 289 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "width", 5, nIndex ) ) 290 { 291 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::WIDTH; 292 nIndex += 5; 293 } 294 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "height", 6, nIndex ) ) 295 { 296 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::HEIGHT; 297 nIndex += 6; 298 } 299 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "logwidth", 8, nIndex ) ) 300 { 301 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::LOGWIDTH; 302 nIndex += 8; 303 } 304 else if ( rParaString.matchIgnoreAsciiCaseAsciiL( "logheight", 9, nIndex ) ) 305 { 306 rParameter.Type = com::sun::star::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT; 307 nIndex += 9; 308 } 309 else 310 bValid = sal_False; 311 } 312 if ( bValid ) 313 { 314 if ( bNumberRequired ) 315 { 316 sal_Int32 nStartIndex = nIndex; 317 318 sal_Bool bM = sal_False; // set if the value is negative 319 sal_Bool bE = sal_False; // set if a double is including a "E" statement 320 sal_Bool bEM = sal_False; // set if a double is including a "E-"statement 321 sal_Bool bDot = sal_False; // set if there is a dot included 322 sal_Bool bEnd = sal_False; // set for each value that can not be part of a double/integer 323 324 while( ( nIndex < rParaString.getLength() ) && bValid ) 325 { 326 switch( rParaString[ nIndex ] ) 327 { 328 case '.' : 329 { 330 if ( bMustBePositiveWholeNumbered ) 331 bValid = sal_False; 332 else 333 { 334 if ( bDot ) 335 bValid = sal_False; 336 else 337 bDot = sal_True; 338 } 339 } 340 break; 341 case '-' : 342 { 343 if ( bMustBePositiveWholeNumbered ) 344 bValid = sal_False; 345 else 346 { 347 if ( nStartIndex == nIndex ) 348 bM = sal_True; 349 else if ( bE ) 350 bEM = sal_True; 351 else 352 bValid = sal_False; 353 } 354 } 355 break; 356 357 case 'e' : 358 case 'E' : 359 { 360 if ( bMustBePositiveWholeNumbered ) 361 bEnd = sal_True; 362 else 363 { 364 if ( !bE ) 365 bE = sal_True; 366 else 367 bEnd = sal_True; 368 } 369 } 370 break; 371 case '0' : 372 case '1' : 373 case '2' : 374 case '3' : 375 case '4' : 376 case '5' : 377 case '6' : 378 case '7' : 379 case '8' : 380 case '9' : 381 break; 382 default: 383 bEnd = sal_True; 384 } 385 if ( !bEnd ) 386 nIndex++; 387 else 388 break; 389 } 390 if ( nIndex == nStartIndex ) 391 bValid = sal_False; 392 if ( bValid ) 393 { 394 rtl::OUString aNumber( rParaString.copy( nStartIndex, nIndex - nStartIndex ) ); 395 if ( bE || bDot ) 396 { 397 double fAttrDouble; 398 if ( SvXMLUnitConverter::convertDouble( fAttrDouble, aNumber ) ) 399 rParameter.Value <<= fAttrDouble; 400 else 401 bValid = sal_False; 402 } 403 else 404 { 405 sal_Int32 nValue; 406 if ( SvXMLUnitConverter::convertNumber( nValue, aNumber ) ) 407 rParameter.Value <<= nValue; 408 else 409 bValid = sal_False; 410 } 411 } 412 } 413 } 414 if ( bValid ) 415 { 416 // skipping white spaces and commatas (#121507#) 417 const sal_Unicode aSpace(sal_Unicode(' ')); 418 const sal_Unicode aCommata(sal_Unicode(',')); 419 420 while(nIndex < rParaString.getLength()) 421 { 422 const sal_Unicode aCandidate(rParaString[nIndex]); 423 424 if(aSpace == aCandidate || aCommata == aCandidate) 425 { 426 nIndex++; 427 } 428 else 429 { 430 break; 431 } 432 } 433 } 434 return bValid; 435 } 436 437 void GetPosition3D( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:extrusion-viewpoint 438 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp, 439 SvXMLUnitConverter& rUnitConverter ) 440 { 441 drawing::Position3D aPosition3D; 442 if ( rUnitConverter.convertPosition3D( aPosition3D, rValue ) ) 443 { 444 beans::PropertyValue aProp; 445 aProp.Name = EASGet( eDestProp ); 446 aProp.Value <<= aPosition3D; 447 rDest.push_back( aProp ); 448 } 449 } 450 451 void GetDoubleSequence( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:glue-point-leaving-directions 452 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 453 { 454 std::vector< double > vDirection; 455 sal_Int32 nIndex = 0; 456 do 457 { 458 double fAttrDouble; 459 rtl::OUString aToken( rValue.getToken( 0, ',', nIndex ) ); 460 if ( !SvXMLUnitConverter::convertDouble( fAttrDouble, aToken ) ) 461 break; 462 else 463 vDirection.push_back( fAttrDouble ); 464 } 465 while ( nIndex >= 0 ); 466 467 if ( !vDirection.empty() ) 468 { 469 uno::Sequence< double > aDirectionsSeq( vDirection.size() ); 470 std::vector< double >::const_iterator aIter = vDirection.begin(); 471 std::vector< double >::const_iterator aEnd = vDirection.end(); 472 double* pValues = aDirectionsSeq.getArray(); 473 474 while ( aIter != aEnd ) 475 *pValues++ = *aIter++; 476 477 beans::PropertyValue aProp; 478 aProp.Name = EASGet( eDestProp ); 479 aProp.Value <<= aDirectionsSeq; 480 rDest.push_back( aProp ); 481 } 482 } 483 484 void GetEnhancedParameter( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:handle-position 485 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 486 { 487 sal_Int32 nIndex = 0; 488 com::sun::star::drawing::EnhancedCustomShapeParameter aParameter; 489 if ( GetNextParameter( aParameter, nIndex, rValue ) ) 490 { 491 beans::PropertyValue aProp; 492 aProp.Name = EASGet( eDestProp ); 493 aProp.Value <<= aParameter; 494 rDest.push_back( aProp ); 495 } 496 } 497 498 void GetEnhancedParameterPair( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:handle-position 499 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 500 { 501 sal_Int32 nIndex = 0; 502 com::sun::star::drawing::EnhancedCustomShapeParameterPair aParameterPair; 503 if ( GetNextParameter( aParameterPair.First, nIndex, rValue ) 504 && GetNextParameter( aParameterPair.Second, nIndex, rValue ) ) 505 { 506 beans::PropertyValue aProp; 507 aProp.Name = EASGet( eDestProp ); 508 aProp.Value <<= aParameterPair; 509 rDest.push_back( aProp ); 510 } 511 } 512 513 sal_Int32 GetEnhancedParameterPairSequence( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:glue-points 514 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 515 { 516 std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair > vParameter; 517 com::sun::star::drawing::EnhancedCustomShapeParameterPair aParameter; 518 519 sal_Int32 nIndex = 0; 520 while ( GetNextParameter( aParameter.First, nIndex, rValue ) 521 && GetNextParameter( aParameter.Second, nIndex, rValue ) ) 522 { 523 vParameter.push_back( aParameter ); 524 } 525 if ( !vParameter.empty() ) 526 { 527 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aParameterSeq( vParameter.size() ); 528 std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aIter = vParameter.begin(); 529 std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aEnd = vParameter.end(); 530 com::sun::star::drawing::EnhancedCustomShapeParameterPair* pValues = aParameterSeq.getArray(); 531 532 while ( aIter != aEnd ) 533 *pValues++ = *aIter++; 534 535 beans::PropertyValue aProp; 536 aProp.Name = EASGet( eDestProp ); 537 aProp.Value <<= aParameterSeq; 538 rDest.push_back( aProp ); 539 } 540 return vParameter.size(); 541 } 542 543 void GetEnhancedRectangleSequence( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:text-areas 544 const rtl::OUString& rValue, const EnhancedCustomShapeTokenEnum eDestProp ) 545 { 546 std::vector< com::sun::star::drawing::EnhancedCustomShapeTextFrame > vTextFrame; 547 com::sun::star::drawing::EnhancedCustomShapeTextFrame aParameter; 548 549 sal_Int32 nIndex = 0; 550 551 while ( GetNextParameter( aParameter.TopLeft.First, nIndex, rValue ) 552 && GetNextParameter( aParameter.TopLeft.Second, nIndex, rValue ) 553 && GetNextParameter( aParameter.BottomRight.First, nIndex, rValue ) 554 && GetNextParameter( aParameter.BottomRight.Second, nIndex, rValue ) ) 555 { 556 vTextFrame.push_back( aParameter ); 557 } 558 if ( !vTextFrame.empty() ) 559 { 560 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aTextFrameSeq( vTextFrame.size() ); 561 std::vector< com::sun::star::drawing::EnhancedCustomShapeTextFrame >::const_iterator aIter = vTextFrame.begin(); 562 std::vector< com::sun::star::drawing::EnhancedCustomShapeTextFrame >::const_iterator aEnd = vTextFrame.end(); 563 com::sun::star::drawing::EnhancedCustomShapeTextFrame* pValues = aTextFrameSeq.getArray(); 564 565 while ( aIter != aEnd ) 566 *pValues++ = *aIter++; 567 568 beans::PropertyValue aProp; 569 aProp.Name = EASGet( eDestProp ); 570 aProp.Value <<= aTextFrameSeq; 571 rDest.push_back( aProp ); 572 } 573 } 574 575 void GetEnhancedPath( std::vector< com::sun::star::beans::PropertyValue >& rDest, // e.g. draw:enhanced-path 576 const rtl::OUString& rValue ) 577 { 578 std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair > vCoordinates; 579 std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment > vSegments; 580 581 sal_Int32 nIndex = 0; 582 sal_Int32 nParameterCount = 0; 583 584 sal_Int32 nParametersNeeded = 1; 585 sal_Int16 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO; 586 587 sal_Bool bValid = sal_True; 588 589 while( bValid && ( nIndex < rValue.getLength() ) ) 590 { 591 switch( rValue[ nIndex ] ) 592 { 593 case 'M' : 594 { 595 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO; 596 nParametersNeeded = 1; 597 nIndex++; 598 } 599 break; 600 case 'L' : 601 { 602 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO; 603 nParametersNeeded = 1; 604 nIndex++; 605 } 606 break; 607 case 'C' : 608 { 609 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO; 610 nParametersNeeded = 3; 611 nIndex++; 612 } 613 break; 614 case 'Z' : 615 { 616 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; 617 nParametersNeeded = 0; 618 nIndex++; 619 } 620 break; 621 case 'N' : 622 { 623 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH; 624 nParametersNeeded = 0; 625 nIndex++; 626 } 627 break; 628 case 'F' : 629 { 630 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL; 631 nParametersNeeded = 0; 632 nIndex++; 633 } 634 break; 635 case 'S' : 636 { 637 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE; 638 nParametersNeeded = 0; 639 nIndex++; 640 } 641 break; 642 case 'T' : 643 { 644 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; 645 nParametersNeeded = 3; 646 nIndex++; 647 } 648 break; 649 case 'U' : 650 { 651 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; 652 nParametersNeeded = 3; 653 nIndex++; 654 } 655 break; 656 case 'A' : 657 { 658 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO; 659 nParametersNeeded = 4; 660 nIndex++; 661 } 662 break; 663 case 'B' : 664 { 665 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC; 666 nParametersNeeded = 4; 667 nIndex++; 668 } 669 break; 670 case 'W' : 671 { 672 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; 673 nParametersNeeded = 4; 674 nIndex++; 675 } 676 break; 677 case 'V' : 678 { 679 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; 680 nParametersNeeded = 4; 681 nIndex++; 682 } 683 break; 684 case 'X' : 685 { 686 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; 687 nParametersNeeded = 1; 688 nIndex++; 689 } 690 break; 691 case 'Y' : 692 { 693 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; 694 nParametersNeeded = 1; 695 nIndex++; 696 } 697 break; 698 case 'Q' : 699 { 700 nLatestSegmentCommand = com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO; 701 nParametersNeeded = 2; 702 nIndex++; 703 } 704 break; 705 case ' ' : 706 { 707 nIndex++; 708 } 709 break; 710 711 case '$' : 712 case '?' : 713 case '0' : 714 case '1' : 715 case '2' : 716 case '3' : 717 case '4' : 718 case '5' : 719 case '6' : 720 case '7' : 721 case '8' : 722 case '9' : 723 case '.' : 724 case '-' : 725 { 726 com::sun::star::drawing::EnhancedCustomShapeParameterPair aPair; 727 if ( GetNextParameter( aPair.First, nIndex, rValue ) && 728 GetNextParameter( aPair.Second, nIndex, rValue ) ) 729 { 730 vCoordinates.push_back( aPair ); 731 nParameterCount++; 732 } 733 else 734 bValid = sal_False; 735 } 736 break; 737 default: 738 nIndex++; 739 break; 740 } 741 if ( !nParameterCount && !nParametersNeeded ) 742 { 743 com::sun::star::drawing::EnhancedCustomShapeSegment aSegment; 744 aSegment.Command = nLatestSegmentCommand; 745 aSegment.Count = 0; 746 vSegments.push_back( aSegment ); 747 nParametersNeeded = 0x7fffffff; 748 } 749 else if ( nParameterCount >= nParametersNeeded ) 750 { 751 // check if the last command is identical, 752 // if so, we just need to increment the count 753 if ( !vSegments.empty() && ( vSegments[ vSegments.size() - 1 ].Command == nLatestSegmentCommand ) ) 754 vSegments[ vSegments.size() -1 ].Count++; 755 else 756 { 757 com::sun::star::drawing::EnhancedCustomShapeSegment aSegment; 758 aSegment.Command = nLatestSegmentCommand; 759 aSegment.Count = 1; 760 vSegments.push_back( aSegment ); 761 } 762 nParameterCount = 0; 763 } 764 } 765 // adding the Coordinates property 766 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > seqCoordinates( vCoordinates.size() ); 767 std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aCoordinatesIter = vCoordinates.begin(); 768 std::vector< com::sun::star::drawing::EnhancedCustomShapeParameterPair >::const_iterator aCoordinatesEnd = vCoordinates.end(); 769 com::sun::star::drawing::EnhancedCustomShapeParameterPair* pCoordinateValues = seqCoordinates.getArray(); 770 771 while ( aCoordinatesIter != aCoordinatesEnd ) 772 *pCoordinateValues++ = *aCoordinatesIter++; 773 774 beans::PropertyValue aProp; 775 aProp.Name = EASGet( EAS_Coordinates ); 776 aProp.Value <<= seqCoordinates; 777 rDest.push_back( aProp ); 778 779 780 // adding the Segments property 781 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments( vSegments.size() ); 782 std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >::const_iterator aSegmentsIter = vSegments.begin(); 783 std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >::const_iterator aSegmentsEnd = vSegments.end(); 784 com::sun::star::drawing::EnhancedCustomShapeSegment* pSegmentValues = seqSegments.getArray(); 785 786 while ( aSegmentsIter != aSegmentsEnd ) 787 *pSegmentValues++ = *aSegmentsIter++; 788 789 aProp.Name = EASGet( EAS_Segments ); 790 aProp.Value <<= seqSegments; 791 rDest.push_back( aProp ); 792 } 793 794 void GetAdjustmentValues( std::vector< com::sun::star::beans::PropertyValue >& rDest, // draw:adjustments 795 const rtl::OUString& rValue ) 796 { 797 std::vector< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > vAdjustmentValue; 798 com::sun::star::drawing::EnhancedCustomShapeParameter aParameter; 799 sal_Int32 nIndex = 0; 800 while ( GetNextParameter( aParameter, nIndex, rValue ) ) 801 { 802 com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue aAdj; 803 if ( aParameter.Type == com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL ) 804 { 805 aAdj.Value <<= aParameter.Value; 806 aAdj.State = beans::PropertyState_DIRECT_VALUE; 807 } 808 else 809 aAdj.State = beans::PropertyState_DEFAULT_VALUE; // this should not be, but better than setting nothing 810 811 vAdjustmentValue.push_back( aAdj ); 812 } 813 814 sal_Int32 nAdjustmentValues = vAdjustmentValue.size(); 815 if ( nAdjustmentValues ) 816 { 817 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentValues( nAdjustmentValues ); 818 std::vector< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue >::const_iterator aIter = vAdjustmentValue.begin(); 819 std::vector< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue >::const_iterator aEnd = vAdjustmentValue.end(); 820 com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue* pValues = aAdjustmentValues.getArray(); 821 822 while ( aIter != aEnd ) 823 *pValues++ = *aIter++; 824 825 beans::PropertyValue aProp; 826 aProp.Name = EASGet( EAS_AdjustmentValues ); 827 aProp.Value <<= aAdjustmentValues; 828 rDest.push_back( aProp ); 829 } 830 } 831 832 void XMLEnhancedCustomShapeContext::StartElement( const uno::Reference< xml::sax::XAttributeList >& xAttrList ) 833 { 834 sal_Int16 nLength = xAttrList->getLength(); 835 if ( nLength ) 836 { 837 sal_Int32 nAttrNumber; 838 for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ ) 839 { 840 rtl::OUString aLocalName; 841 const rtl::OUString& rValue = xAttrList->getValueByIndex( nAttr ); 842 /* sven fixme, this must be checked! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName ); 843 844 switch( EASGet( aLocalName ) ) 845 { 846 case EAS_type : 847 GetString( mrCustomShapeGeometry, rValue, EAS_Type ); 848 break; 849 case EAS_mirror_horizontal : 850 GetBool( mrCustomShapeGeometry, rValue, EAS_MirroredX ); 851 break; 852 case EAS_mirror_vertical : 853 GetBool( mrCustomShapeGeometry, rValue, EAS_MirroredY ); 854 break; 855 case EAS_viewBox : 856 { 857 SdXMLImExViewBox aViewBox( rValue, GetImport().GetMM100UnitConverter() ); 858 awt::Rectangle aRect( 859 basegfx::fround(aViewBox.GetX()), 860 basegfx::fround(aViewBox.GetY()), 861 basegfx::fround(aViewBox.GetWidth()), 862 basegfx::fround(aViewBox.GetHeight())); 863 864 if(0 == aRect.Width && 0 == aRect.Height) 865 { 866 // #124452# If in svg:viewBox no width and height is given the objects should normally 867 // not be visible at all, but in this case it is a bug in LO to write empty svg:viewBox 868 // entries for CustomShapes. To allow for a better ODF user experience, just correct this 869 // here by getting the real object scale from the already set transformation from the xShape. 870 // Hopefully LO will fix that bug (but this will still leave the files with the error), but 871 // even when not this will do no harm as long no one uses this state explicitely for some 872 // purpose (e.g. to really have CustomShapes without content, but unlikely). 873 // When they do fix this they will need this fix anyways to read their own misformed ODF files 874 // again, so I guess it will be taken, too... 875 uno::Reference< beans::XPropertySet > xProps(mrxShape, uno::UNO_QUERY_THROW); 876 uno::Any aObjectTransform = xProps->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation"))); 877 drawing::HomogenMatrix3 aTransformMatrix; 878 aObjectTransform >>= aTransformMatrix; 879 basegfx::B2DHomMatrix aMatrix; 880 881 aMatrix.set(0, 0, aTransformMatrix.Line1.Column1); 882 aMatrix.set(0, 1, aTransformMatrix.Line1.Column2); 883 aMatrix.set(0, 2, aTransformMatrix.Line1.Column3); 884 aMatrix.set(1, 0, aTransformMatrix.Line2.Column1); 885 aMatrix.set(1, 1, aTransformMatrix.Line2.Column2); 886 aMatrix.set(1, 2, aTransformMatrix.Line2.Column3); 887 aMatrix.set(2, 0, aTransformMatrix.Line3.Column1); 888 aMatrix.set(2, 1, aTransformMatrix.Line3.Column2); 889 aMatrix.set(2, 2, aTransformMatrix.Line3.Column3); 890 891 basegfx::B2DVector aScale, aTranslate; 892 double fRotate, fShearX; 893 894 aMatrix.decompose(aScale, aTranslate, fRotate, fShearX); 895 896 aRect.Width = basegfx::fround(fabs(aScale.getX())); 897 aRect.Height = basegfx::fround(fabs(aScale.getY())); 898 } 899 900 beans::PropertyValue aProp; 901 aProp.Name = EASGet( EAS_ViewBox ); 902 aProp.Value <<= aRect; 903 mrCustomShapeGeometry.push_back( aProp ); 904 } 905 break; 906 case EAS_text_rotate_angle : 907 GetDouble( mrCustomShapeGeometry, rValue, EAS_TextRotateAngle ); 908 break; 909 case EAS_extrusion_allowed : 910 GetBool( maPath, rValue, EAS_ExtrusionAllowed ); 911 break; 912 case EAS_text_path_allowed : 913 GetBool( maPath, rValue, EAS_TextPathAllowed ); 914 break; 915 case EAS_concentric_gradient_fill_allowed : 916 GetBool( maPath, rValue, EAS_ConcentricGradientFillAllowed ); 917 break; 918 case EAS_extrusion : 919 GetBool( maExtrusion, rValue, EAS_Extrusion ); 920 break; 921 case EAS_extrusion_brightness : 922 GetDoublePercentage( maExtrusion, rValue, EAS_Brightness ); 923 break; 924 case EAS_extrusion_depth : 925 { 926 sal_Int32 nIndex = 0; 927 com::sun::star::drawing::EnhancedCustomShapeParameterPair aParameterPair; 928 com::sun::star::drawing::EnhancedCustomShapeParameter& rDepth = aParameterPair.First; 929 com::sun::star::drawing::EnhancedCustomShapeParameter& rFraction = aParameterPair.Second; 930 if ( GetNextParameter( rDepth, nIndex, rValue ) ) 931 { 932 // try to catch the unit for the depth 933 MapUnit eSrcUnit( SvXMLExportHelper::GetUnitFromString( rValue, MAP_100TH_MM ) ); 934 935 rtl::OUStringBuffer aUnitStr; 936 double fFactor = SvXMLExportHelper::GetConversionFactor( aUnitStr, MAP_100TH_MM, eSrcUnit ); 937 if ( ( fFactor != 1.0 ) && ( fFactor != 0.0 ) ) 938 { 939 double fDepth; 940 if ( rDepth.Value >>= fDepth ) 941 { 942 fDepth /= fFactor; 943 rDepth.Value <<= fDepth; 944 } 945 } 946 if ( rValue.matchIgnoreAsciiCase( rtl::OUString( aUnitStr ), nIndex ) ) 947 nIndex += aUnitStr.getLength(); 948 949 // skipping white spaces 950 while( ( nIndex < rValue.getLength() ) && rValue[ nIndex ] == (sal_Unicode)' ' ) 951 nIndex++; 952 953 if ( GetNextParameter( rFraction, nIndex, rValue ) ) 954 { 955 beans::PropertyValue aProp; 956 aProp.Name = EASGet( EAS_Depth ); 957 aProp.Value <<= aParameterPair; 958 maExtrusion.push_back( aProp ); 959 } 960 } 961 } 962 break; 963 case EAS_extrusion_diffusion : 964 GetDoublePercentage( maExtrusion, rValue, EAS_Diffusion ); 965 break; 966 case EAS_extrusion_number_of_line_segments : 967 GetInt32( maExtrusion, rValue, EAS_NumberOfLineSegments ); 968 break; 969 case EAS_extrusion_light_face : 970 GetBool( maExtrusion, rValue, EAS_LightFace ); 971 break; 972 case EAS_extrusion_first_light_harsh : 973 GetBool( maExtrusion, rValue, EAS_FirstLightHarsh ); 974 break; 975 case EAS_extrusion_second_light_harsh : 976 GetBool( maExtrusion, rValue, EAS_SecondLightHarsh ); 977 break; 978 case EAS_extrusion_first_light_level : 979 GetDoublePercentage( maExtrusion, rValue, EAS_FirstLightLevel ); 980 break; 981 case EAS_extrusion_second_light_level : 982 GetDoublePercentage( maExtrusion, rValue, EAS_SecondLightLevel ); 983 break; 984 case EAS_extrusion_first_light_direction : 985 GetB3DVector( maExtrusion, rValue, EAS_FirstLightDirection ); 986 break; 987 case EAS_extrusion_second_light_direction : 988 GetB3DVector( maExtrusion, rValue, EAS_SecondLightDirection ); 989 break; 990 case EAS_extrusion_metal : 991 GetBool( maExtrusion, rValue, EAS_Metal ); 992 break; 993 case EAS_shade_mode : 994 { 995 drawing::ShadeMode eShadeMode( drawing::ShadeMode_FLAT ); 996 if( IsXMLToken( rValue, XML_PHONG ) ) 997 eShadeMode = drawing::ShadeMode_PHONG; 998 else if ( IsXMLToken( rValue, XML_GOURAUD ) ) 999 eShadeMode = drawing::ShadeMode_SMOOTH; 1000 else if ( IsXMLToken( rValue, XML_DRAFT ) ) 1001 eShadeMode = drawing::ShadeMode_DRAFT; 1002 1003 beans::PropertyValue aProp; 1004 aProp.Name = EASGet( EAS_ShadeMode ); 1005 aProp.Value <<= eShadeMode; 1006 maExtrusion.push_back( aProp ); 1007 } 1008 break; 1009 case EAS_extrusion_rotation_angle : 1010 GetEnhancedParameterPair( maExtrusion, rValue, EAS_RotateAngle ); 1011 break; 1012 case EAS_extrusion_rotation_center : 1013 GetB3DVector( maExtrusion, rValue, EAS_RotationCenter ); 1014 break; 1015 case EAS_extrusion_shininess : 1016 GetDoublePercentage( maExtrusion, rValue, EAS_Shininess ); 1017 break; 1018 case EAS_extrusion_skew : 1019 GetEnhancedParameterPair( maExtrusion, rValue, EAS_Skew ); 1020 break; 1021 case EAS_extrusion_specularity : 1022 GetDoublePercentage( maExtrusion, rValue, EAS_Specularity ); 1023 break; 1024 case EAS_projection : 1025 { 1026 drawing::ProjectionMode eProjectionMode( drawing::ProjectionMode_PERSPECTIVE ); 1027 if( IsXMLToken( rValue, XML_PARALLEL ) ) 1028 eProjectionMode = drawing::ProjectionMode_PARALLEL; 1029 1030 beans::PropertyValue aProp; 1031 aProp.Name = EASGet( EAS_ProjectionMode ); 1032 aProp.Value <<= eProjectionMode; 1033 maExtrusion.push_back( aProp ); 1034 } 1035 break; 1036 case EAS_extrusion_viewpoint : 1037 GetPosition3D( maExtrusion, rValue, EAS_ViewPoint, mrUnitConverter ); 1038 break; 1039 case EAS_extrusion_origin : 1040 GetEnhancedParameterPair( maExtrusion, rValue, EAS_Origin ); 1041 break; 1042 case EAS_extrusion_color : 1043 GetBool( maExtrusion, rValue, EAS_Color ); 1044 break; 1045 case EAS_enhanced_path : 1046 GetEnhancedPath( maPath, rValue ); 1047 break; 1048 case EAS_path_stretchpoint_x : 1049 { 1050 if ( SvXMLUnitConverter::convertNumber( nAttrNumber, rValue ) ) 1051 { 1052 beans::PropertyValue aProp; 1053 aProp.Name = EASGet( EAS_StretchX ); 1054 aProp.Value <<= nAttrNumber; 1055 maPath.push_back( aProp ); 1056 } 1057 } 1058 break; 1059 case EAS_path_stretchpoint_y : 1060 { 1061 if ( SvXMLUnitConverter::convertNumber( nAttrNumber, rValue ) ) 1062 { 1063 beans::PropertyValue aProp; 1064 aProp.Name = EASGet( EAS_StretchY ); 1065 aProp.Value <<= nAttrNumber; 1066 maPath.push_back( aProp ); 1067 } 1068 } 1069 break; 1070 case EAS_text_areas : 1071 GetEnhancedRectangleSequence( maPath, rValue, EAS_TextFrames ); 1072 break; 1073 case EAS_glue_points : 1074 { 1075 sal_Int32 i, nPairs = GetEnhancedParameterPairSequence( maPath, rValue, EAS_GluePoints ); 1076 GetImport().GetShapeImport()->moveGluePointMapping( mrxShape, nPairs ); 1077 for ( i = 0; i < nPairs; i++ ) 1078 GetImport().GetShapeImport()->addGluePointMapping( mrxShape, i + 4, i + 4 ); 1079 } 1080 break; 1081 case EAS_glue_point_type : 1082 GetEnum( maPath, rValue, EAS_GluePointType, *aXML_GluePointEnumMap ); 1083 break; 1084 case EAS_glue_point_leaving_directions : 1085 GetDoubleSequence( maPath, rValue, EAS_GluePointLeavingDirections ); 1086 break; 1087 case EAS_text_path : 1088 GetBool( maTextPath, rValue, EAS_TextPath ); 1089 break; 1090 case EAS_text_path_mode : 1091 { 1092 com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode( com::sun::star::drawing::EnhancedCustomShapeTextPathMode_NORMAL ); 1093 if( IsXMLToken( rValue, XML_PATH ) ) 1094 eTextPathMode = com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH; 1095 else if ( IsXMLToken( rValue, XML_SHAPE ) ) 1096 eTextPathMode = com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE; 1097 1098 beans::PropertyValue aProp; 1099 aProp.Name = EASGet( EAS_TextPathMode ); 1100 aProp.Value <<= eTextPathMode; 1101 maTextPath.push_back( aProp ); 1102 } 1103 break; 1104 case EAS_text_path_scale : 1105 { 1106 sal_Bool bScaleX = IsXMLToken( rValue, XML_SHAPE ); 1107 beans::PropertyValue aProp; 1108 aProp.Name = EASGet( EAS_ScaleX ); 1109 aProp.Value <<= bScaleX; 1110 maTextPath.push_back( aProp ); 1111 } 1112 break; 1113 case EAS_text_path_same_letter_heights : 1114 GetBool( maTextPath, rValue, EAS_SameLetterHeights ); 1115 break; 1116 case EAS_modifiers : 1117 GetAdjustmentValues( mrCustomShapeGeometry, rValue ); 1118 break; 1119 default: 1120 break; 1121 } 1122 } 1123 } 1124 } 1125 1126 void SdXMLCustomShapePropertyMerge( std::vector< com::sun::star::beans::PropertyValue >& rPropVec, 1127 const std::vector< beans::PropertyValues >& rElement, 1128 const rtl::OUString& rElementName ) 1129 { 1130 if ( !rElement.empty() ) 1131 { 1132 uno::Sequence< beans::PropertyValues > aPropSeq( rElement.size() ); 1133 std::vector< beans::PropertyValues >::const_iterator aIter = rElement.begin(); 1134 std::vector< beans::PropertyValues >::const_iterator aEnd = rElement.end(); 1135 beans::PropertyValues* pValues = aPropSeq.getArray(); 1136 1137 while ( aIter != aEnd ) 1138 *pValues++ = *aIter++; 1139 1140 beans::PropertyValue aProp; 1141 aProp.Name = rElementName; 1142 aProp.Value <<= aPropSeq; 1143 rPropVec.push_back( aProp ); 1144 } 1145 } 1146 1147 void SdXMLCustomShapePropertyMerge( std::vector< com::sun::star::beans::PropertyValue >& rPropVec, 1148 const std::vector< rtl::OUString >& rElement, 1149 const rtl::OUString& rElementName ) 1150 { 1151 if ( !rElement.empty() ) 1152 { 1153 uno::Sequence< rtl::OUString > aPropSeq( rElement.size() ); 1154 std::vector< rtl::OUString >::const_iterator aIter = rElement.begin(); 1155 std::vector< rtl::OUString >::const_iterator aEnd = rElement.end(); 1156 rtl::OUString* pValues = aPropSeq.getArray(); 1157 1158 while ( aIter != aEnd ) 1159 *pValues++ = *aIter++; 1160 1161 beans::PropertyValue aProp; 1162 aProp.Name = rElementName; 1163 aProp.Value <<= aPropSeq; 1164 rPropVec.push_back( aProp ); 1165 } 1166 } 1167 1168 void SdXMLCustomShapePropertyMerge( std::vector< com::sun::star::beans::PropertyValue >& rPropVec, 1169 const std::vector< com::sun::star::beans::PropertyValue >& rElement, 1170 const rtl::OUString& rElementName ) 1171 { 1172 if ( !rElement.empty() ) 1173 { 1174 uno::Sequence< beans::PropertyValue > aPropSeq( rElement.size() ); 1175 std::vector< beans::PropertyValue >::const_iterator aIter = rElement.begin(); 1176 std::vector< beans::PropertyValue >::const_iterator aEnd = rElement.end(); 1177 beans::PropertyValue* pValues = aPropSeq.getArray(); 1178 1179 while ( aIter != aEnd ) 1180 *pValues++ = *aIter++; 1181 1182 beans::PropertyValue aProp; 1183 aProp.Name = rElementName; 1184 aProp.Value <<= aPropSeq; 1185 rPropVec.push_back( aProp ); 1186 } 1187 } 1188 1189 typedef std::hash_map< rtl::OUString, sal_Int32, rtl::OUStringHash, OUStringEqFunc> EquationHashMap; 1190 1191 /* if rPara.Type is from type EnhancedCustomShapeParameterType::EQUATION, the name of the equation 1192 will be converted from rtl::OUString to index */ 1193 void CheckAndResolveEquationParameter( com::sun::star::drawing::EnhancedCustomShapeParameter& rPara, EquationHashMap* pH ) 1194 { 1195 if ( rPara.Type == com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION ) 1196 { 1197 rtl::OUString aEquationName; 1198 if ( rPara.Value >>= aEquationName ) 1199 { 1200 sal_Int32 nIndex = 0; 1201 EquationHashMap::iterator aHashIter( pH->find( aEquationName ) ); 1202 if ( aHashIter != pH->end() ) 1203 nIndex = (*aHashIter).second; 1204 rPara.Value <<= nIndex; 1205 } 1206 } 1207 } 1208 1209 void XMLEnhancedCustomShapeContext::EndElement() 1210 { 1211 // resolve properties that are indexing a Equation 1212 if ( !maEquations.empty() ) 1213 { 1214 // creating hash map containing the name and index of each equation 1215 EquationHashMap* pH = new EquationHashMap; 1216 std::vector< rtl::OUString >::iterator aEquationNameIter = maEquationNames.begin(); 1217 std::vector< rtl::OUString >::iterator aEquationNameEnd = maEquationNames.end(); 1218 while( aEquationNameIter != aEquationNameEnd ) 1219 { 1220 (*pH)[ *aEquationNameIter ] = (sal_Int32)( aEquationNameIter - maEquationNames.begin() ); 1221 aEquationNameIter++; 1222 } 1223 1224 // resolve equation 1225 std::vector< rtl::OUString >::iterator aEquationIter = maEquations.begin(); 1226 std::vector< rtl::OUString >::iterator aEquationEnd = maEquations.end(); 1227 while( aEquationIter != aEquationEnd ) 1228 { 1229 sal_Int32 nIndexOf = 0; 1230 do 1231 { 1232 nIndexOf = aEquationIter->indexOf( '?', nIndexOf ); 1233 if ( nIndexOf != -1 ) 1234 { 1235 rtl::OUString aEquationName; 1236 if ( GetEquationName( *aEquationIter, nIndexOf + 1, aEquationName ) ) 1237 { 1238 // copying first characters inclusive '?' 1239 rtl::OUString aNew( aEquationIter->copy( 0, nIndexOf + 1 ) ); 1240 sal_Int32 nIndex = 0; 1241 EquationHashMap::iterator aHashIter( pH->find( aEquationName ) ); 1242 if ( aHashIter != pH->end() ) 1243 nIndex = (*aHashIter).second; 1244 aNew += rtl::OUString::valueOf( nIndex ); 1245 aNew += aEquationIter->copy( nIndexOf + aEquationName.getLength() + 1 ); 1246 *aEquationIter = aNew; 1247 } 1248 nIndexOf++; 1249 } 1250 } 1251 while( nIndexOf != -1 ); 1252 aEquationIter++; 1253 } 1254 1255 // Path 1256 sal_Int32 i; 1257 std::vector< beans::PropertyValue >::iterator aPathIter = maPath.begin(); 1258 std::vector< beans::PropertyValue >::iterator aPathEnd = maPath.end(); 1259 while ( aPathIter != aPathEnd ) 1260 { 1261 switch( EASGet( aPathIter->Name ) ) 1262 { 1263 case EAS_Coordinates : 1264 case EAS_GluePoints : 1265 { 1266 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair >& rSeq = 1267 *((uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair >*) 1268 aPathIter->Value.getValue()); 1269 for ( i = 0; i < rSeq.getLength(); i++ ) 1270 { 1271 CheckAndResolveEquationParameter( rSeq[ i ].First, pH ); 1272 CheckAndResolveEquationParameter( rSeq[ i ].Second, pH ); 1273 } 1274 } 1275 break; 1276 case EAS_TextFrames : 1277 { 1278 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame >& rSeq = 1279 *((uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame >*) 1280 aPathIter->Value.getValue()); 1281 for ( i = 0; i < rSeq.getLength(); i++ ) 1282 { 1283 CheckAndResolveEquationParameter( rSeq[ i ].TopLeft.First, pH ); 1284 CheckAndResolveEquationParameter( rSeq[ i ].TopLeft.Second, pH ); 1285 CheckAndResolveEquationParameter( rSeq[ i ].BottomRight.First, pH ); 1286 CheckAndResolveEquationParameter( rSeq[ i ].BottomRight.Second, pH ); 1287 } 1288 } 1289 break; 1290 default: 1291 break; 1292 } 1293 aPathIter++; 1294 } 1295 std::vector< beans::PropertyValues >::iterator aHandleIter = maHandles.begin(); 1296 std::vector< beans::PropertyValues >::iterator aHandleEnd = maHandles.end(); 1297 while ( aHandleIter != aHandleEnd ) 1298 { 1299 beans::PropertyValue* pValues = aHandleIter->getArray(); 1300 for ( i = 0; i < aHandleIter->getLength(); i++ ) 1301 { 1302 switch( EASGet( pValues->Name ) ) 1303 { 1304 case EAS_RangeYMinimum : 1305 case EAS_RangeYMaximum : 1306 case EAS_RangeXMinimum : 1307 case EAS_RangeXMaximum : 1308 case EAS_RadiusRangeMinimum : 1309 case EAS_RadiusRangeMaximum : 1310 { 1311 CheckAndResolveEquationParameter( *((com::sun::star::drawing::EnhancedCustomShapeParameter*) 1312 pValues->Value.getValue()), pH ); 1313 } 1314 break; 1315 1316 case EAS_Position : 1317 case EAS_Polar : 1318 { 1319 CheckAndResolveEquationParameter( (*((com::sun::star::drawing::EnhancedCustomShapeParameterPair*) 1320 pValues->Value.getValue())).First, pH ); 1321 CheckAndResolveEquationParameter( (*((com::sun::star::drawing::EnhancedCustomShapeParameterPair*) 1322 pValues->Value.getValue())).Second, pH ); 1323 } 1324 break; 1325 default: 1326 break; 1327 } 1328 pValues++; 1329 } 1330 aHandleIter++; 1331 } 1332 delete pH; 1333 } 1334 1335 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maExtrusion, EASGet( EAS_Extrusion ) ); 1336 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maPath, EASGet( EAS_Path ) ); 1337 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maTextPath, EASGet( EAS_TextPath ) ); 1338 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maEquations, EASGet( EAS_Equations ) ); 1339 if ( !maHandles.empty() ) 1340 SdXMLCustomShapePropertyMerge( mrCustomShapeGeometry, maHandles, EASGet( EAS_Handles ) ); 1341 } 1342 1343 SvXMLImportContext* XMLEnhancedCustomShapeContext::CreateChildContext( sal_uInt16 nPrefix,const rtl::OUString& rLocalName, 1344 const uno::Reference< xml::sax::XAttributeList> & xAttrList ) 1345 { 1346 EnhancedCustomShapeTokenEnum aTokenEnum = EASGet( rLocalName ); 1347 if ( aTokenEnum == EAS_equation ) 1348 { 1349 sal_Int16 nLength = xAttrList->getLength(); 1350 if ( nLength ) 1351 { 1352 rtl::OUString aFormula; 1353 rtl::OUString aFormulaName; 1354 for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ ) 1355 { 1356 rtl::OUString aLocalName; 1357 const rtl::OUString& rValue = xAttrList->getValueByIndex( nAttr ); 1358 /* fixme sven, this needs to be chekced! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName ); 1359 1360 switch( EASGet( aLocalName ) ) 1361 { 1362 case EAS_formula : 1363 aFormula = rValue; 1364 break; 1365 case EAS_name : 1366 aFormulaName = rValue; 1367 break; 1368 default: 1369 break; 1370 } 1371 } 1372 if ( aFormulaName.getLength() || aFormula.getLength() ) 1373 { 1374 maEquations.push_back( aFormula ); 1375 maEquationNames.push_back( aFormulaName ); 1376 } 1377 } 1378 } 1379 else if ( aTokenEnum == EAS_handle ) 1380 { 1381 std::vector< com::sun::star::beans::PropertyValue > aHandle; 1382 const sal_Int16 nLength = xAttrList->getLength(); 1383 for( sal_Int16 nAttr = 0; nAttr < nLength; nAttr++ ) 1384 { 1385 rtl::OUString aLocalName; 1386 const rtl::OUString& rValue = xAttrList->getValueByIndex( nAttr ); 1387 /* fixme sven, this needs to be chekced! sal_uInt16 nPrefix = */ GetImport().GetNamespaceMap().GetKeyByAttrName( xAttrList->getNameByIndex( nAttr ), &aLocalName ); 1388 switch( EASGet( aLocalName ) ) 1389 { 1390 case EAS_handle_mirror_vertical : 1391 GetBool( aHandle, rValue, EAS_MirroredY ); 1392 break; 1393 case EAS_handle_mirror_horizontal : 1394 GetBool( aHandle, rValue, EAS_MirroredX ); 1395 break; 1396 case EAS_handle_switched : 1397 GetBool( aHandle, rValue, EAS_Switched ); 1398 break; 1399 case EAS_handle_position : 1400 GetEnhancedParameterPair( aHandle, rValue, EAS_Position ); 1401 break; 1402 case EAS_handle_range_x_minimum : 1403 GetEnhancedParameter( aHandle, rValue, EAS_RangeXMinimum ); 1404 break; 1405 case EAS_handle_range_x_maximum : 1406 GetEnhancedParameter( aHandle, rValue, EAS_RangeXMaximum ); 1407 break; 1408 case EAS_handle_range_y_minimum : 1409 GetEnhancedParameter( aHandle, rValue, EAS_RangeYMinimum ); 1410 break; 1411 case EAS_handle_range_y_maximum : 1412 GetEnhancedParameter( aHandle, rValue, EAS_RangeYMaximum ); 1413 break; 1414 case EAS_handle_polar : 1415 GetEnhancedParameterPair( aHandle, rValue, EAS_Polar ); 1416 break; 1417 case EAS_handle_radius_range_minimum : 1418 GetEnhancedParameter( aHandle, rValue, EAS_RadiusRangeMinimum ); 1419 break; 1420 case EAS_handle_radius_range_maximum : 1421 GetEnhancedParameter( aHandle, rValue, EAS_RadiusRangeMaximum ); 1422 break; 1423 default: 1424 break; 1425 } 1426 } 1427 beans::PropertyValues aPropSeq( aHandle.size() ); 1428 std::vector< beans::PropertyValue >::const_iterator aIter = aHandle.begin(); 1429 std::vector< beans::PropertyValue >::const_iterator aEnd = aHandle.end(); 1430 beans::PropertyValue* pValues = aPropSeq.getArray(); 1431 1432 while ( aIter != aEnd ) 1433 *pValues++ = *aIter++; 1434 1435 maHandles.push_back( aPropSeq ); 1436 } 1437 return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList ); 1438 } 1439