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