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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_svgio.hxx" 24 25 #include <svgio/svgreader/svgtools.hxx> 26 #include <osl/thread.h> 27 #include <tools/color.hxx> 28 #include <basegfx/matrix/b2dhommatrix.hxx> 29 #include <basegfx/matrix/b2dhommatrixtools.hxx> 30 #include <svgio/svgreader/svgtoken.hxx> 31 #include <hash_map> 32 33 ////////////////////////////////////////////////////////////////////////////// 34 35 namespace svgio 36 { 37 namespace svgreader 38 { 39 #ifdef DBG_UTIL myAssert(const rtl::OUString & rMessage)40 void myAssert(const rtl::OUString& rMessage) 41 { 42 rtl::OString aMessage2; 43 44 rMessage.convertToString(&aMessage2, osl_getThreadTextEncoding(), RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR|RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR); 45 OSL_ENSURE(false, aMessage2.getStr()); 46 } 47 #endif 48 49 // common non-token strings 50 const rtl::OUString commonStrings::aStrUserSpaceOnUse(rtl::OUString::createFromAscii("userSpaceOnUse")); 51 const rtl::OUString commonStrings::aStrObjectBoundingBox(rtl::OUString::createFromAscii("objectBoundingBox")); 52 const rtl::OUString commonStrings::aStrNonzero(rtl::OUString::createFromAscii("nonzero")); 53 const rtl::OUString commonStrings::aStrEvenOdd(rtl::OUString::createFromAscii("evenodd")); 54 createLinearMapping(const basegfx::B2DRange & rTarget,const basegfx::B2DRange & rSource)55 basegfx::B2DHomMatrix SvgAspectRatio::createLinearMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource) 56 { 57 basegfx::B2DHomMatrix aRetval; 58 const double fSWidth(rSource.getWidth()); 59 const double fSHeight(rSource.getHeight()); 60 const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth)); 61 const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight)); 62 63 // transform from source state to unit range 64 aRetval.translate(-rSource.getMinX(), -rSource.getMinY()); 65 aRetval.scale( 66 (bNoSWidth ? 1.0 : 1.0 / fSWidth) * rTarget.getWidth(), 67 (bNoSHeight ? 1.0 : 1.0 / fSHeight) * rTarget.getHeight()); 68 69 // transform from unit rage to target range 70 aRetval.translate(rTarget.getMinX(), rTarget.getMinY()); 71 72 return aRetval; 73 } 74 createMapping(const basegfx::B2DRange & rTarget,const basegfx::B2DRange & rSource) const75 basegfx::B2DHomMatrix SvgAspectRatio::createMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource) const 76 { 77 if(!isSet() || Align_none == getSvgAlign()) 78 { 79 // create linear mapping (default) 80 return createLinearMapping(rTarget, rSource); 81 } 82 83 basegfx::B2DHomMatrix aRetval; 84 85 const double fSWidth(rSource.getWidth()); 86 const double fSHeight(rSource.getHeight()); 87 const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth)); 88 const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight)); 89 const double fScaleX((bNoSWidth ? 1.0 : 1.0 / fSWidth) * rTarget.getWidth()); 90 const double fScaleY((bNoSHeight ? 1.0 : 1.0 / fSHeight) * rTarget.getHeight()); 91 const double fScale(isMeetOrSlice() ? std::min(fScaleX, fScaleY) : std::max(fScaleX, fScaleY)); 92 93 // remove source translation, apply scale 94 aRetval.translate(-rSource.getMinX(), -rSource.getMinY()); 95 aRetval.scale(fScale, fScale); 96 97 // evaluate horizontal alignment 98 const double fNewWidth(fSWidth * fScale); 99 double fTransX(0.0); 100 101 switch(getSvgAlign()) 102 { 103 case Align_xMidYMin: 104 case Align_xMidYMid: 105 case Align_xMidYMax: 106 { 107 // centerX 108 const double fFreeSpace(rTarget.getWidth() - fNewWidth); 109 fTransX = fFreeSpace * 0.5; 110 break; 111 } 112 case Align_xMaxYMin: 113 case Align_xMaxYMid: 114 case Align_xMaxYMax: 115 { 116 // Right align 117 const double fFreeSpace(rTarget.getWidth() - fNewWidth); 118 fTransX = fFreeSpace; 119 break; 120 } 121 default: break; 122 } 123 124 // evaluate vertical alignment 125 const double fNewHeight(fSHeight * fScale); 126 double fTransY(0.0); 127 128 switch(getSvgAlign()) 129 { 130 case Align_xMinYMid: 131 case Align_xMidYMid: 132 case Align_xMaxYMid: 133 { 134 // centerY 135 const double fFreeSpace(rTarget.getHeight() - fNewHeight); 136 fTransY = fFreeSpace * 0.5; 137 break; 138 } 139 case Align_xMinYMax: 140 case Align_xMidYMax: 141 case Align_xMaxYMax: 142 { 143 // Bottom align 144 const double fFreeSpace(rTarget.getHeight() - fNewHeight); 145 fTransY = fFreeSpace; 146 break; 147 } 148 default: break; 149 } 150 151 // add target translation 152 aRetval.translate( 153 rTarget.getMinX() + fTransX, 154 rTarget.getMinY() + fTransY); 155 156 return aRetval; 157 } 158 solveNonPercentage(const InfoProvider & rInfoProvider) const159 double SvgNumber::solveNonPercentage(const InfoProvider& rInfoProvider) const 160 { 161 if(isSet()) 162 { 163 switch(meUnit) 164 { 165 case Unit_em: 166 { 167 return mfNumber * rInfoProvider.getCurrentFontSize(); 168 break; 169 } 170 case Unit_ex: 171 { 172 return mfNumber * rInfoProvider.getCurrentXHeight() * 0.5; 173 break; 174 } 175 case Unit_px: 176 { 177 return mfNumber; 178 break; 179 } 180 case Unit_pt: 181 case Unit_pc: 182 case Unit_cm: 183 case Unit_mm: 184 case Unit_in: 185 { 186 double fRetval(mfNumber); 187 188 switch(meUnit) 189 { 190 case Unit_pt: fRetval *= F_SVG_PIXEL_PER_INCH / 72.0; break; 191 case Unit_pc: fRetval *= F_SVG_PIXEL_PER_INCH / 6.0; break; 192 case Unit_cm: fRetval *= F_SVG_PIXEL_PER_INCH / 2.54; break; 193 case Unit_mm: fRetval *= 0.1 * F_SVG_PIXEL_PER_INCH / 2.54; break; 194 case Unit_in: fRetval *= F_SVG_PIXEL_PER_INCH; break; 195 default: break; 196 } 197 198 return fRetval; 199 break; 200 } 201 default: 202 { 203 OSL_ENSURE(false, "Do not use with percentage! "); 204 return 0.0; 205 break; 206 } 207 } 208 } 209 210 /// not set 211 OSL_ENSURE(false, "SvgNumber not set (!)"); 212 return 0.0; 213 } 214 solve(const InfoProvider & rInfoProvider,NumberType aNumberType) const215 double SvgNumber::solve(const InfoProvider& rInfoProvider, NumberType aNumberType) const 216 { 217 if(isSet()) 218 { 219 switch(meUnit) 220 { 221 case Unit_px: 222 { 223 return mfNumber; 224 break; 225 } 226 case Unit_pt: 227 case Unit_pc: 228 case Unit_cm: 229 case Unit_mm: 230 case Unit_in: 231 case Unit_em: 232 case Unit_ex: 233 { 234 return solveNonPercentage( rInfoProvider); 235 break; 236 } 237 case Unit_percent: 238 { 239 double fRetval(mfNumber * 0.01); 240 basegfx::B2DRange aViewPort = rInfoProvider.getCurrentViewPort(); 241 242 if ( aViewPort.isEmpty() ) 243 { 244 #ifdef DBG_UTIL 245 myAssert(rtl::OUString::createFromAscii("Design error, this case should have been handled in the caller")); 246 #endif 247 // no viewPort, assume a normal page size (A4) 248 aViewPort = basegfx::B2DRange( 249 0.0, 250 0.0, 251 210.0 * F_SVG_PIXEL_PER_INCH / 2.54, 252 297.0 * F_SVG_PIXEL_PER_INCH / 2.54); 253 254 } 255 256 if ( !aViewPort.isEmpty() ) 257 { 258 if(xcoordinate == aNumberType) 259 { 260 // it's a x-coordinate, relative to current width (w) 261 fRetval *= aViewPort.getWidth(); 262 } 263 else if(ycoordinate == aNumberType) 264 { 265 // it's a y-coordinate, relative to current height (h) 266 fRetval *= aViewPort.getHeight(); 267 } 268 else // length 269 { 270 // it's a length, relative to sqrt(w*w + h*h)/sqrt(2) 271 const double fCurrentWidth(aViewPort.getWidth()); 272 const double fCurrentHeight(aViewPort.getHeight()); 273 const double fCurrentLength( 274 sqrt(fCurrentWidth * fCurrentWidth + fCurrentHeight * fCurrentHeight)/sqrt(2.0)); 275 276 fRetval *= fCurrentLength; 277 } 278 } 279 280 return fRetval; 281 break; 282 } 283 default: 284 { 285 break; 286 } 287 } 288 } 289 290 /// not set 291 OSL_ENSURE(false, "SvgNumber not set (!)"); 292 return 0.0; 293 } 294 isPositive() const295 bool SvgNumber::isPositive() const 296 { 297 return basegfx::fTools::moreOrEqual(mfNumber, 0.0); 298 } 299 skip_char(const rtl::OUString & rCandidate,const sal_Unicode & rChar,sal_Int32 & nPos,const sal_Int32 nLen)300 void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rChar, sal_Int32& nPos, const sal_Int32 nLen) 301 { 302 while(nPos < nLen && rChar == rCandidate[nPos]) 303 { 304 nPos++; 305 } 306 } 307 skip_char(const rtl::OUString & rCandidate,const sal_Unicode & rCharA,const sal_Unicode & rCharB,sal_Int32 & nPos,const sal_Int32 nLen)308 void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rCharA, const sal_Unicode& rCharB, sal_Int32& nPos, const sal_Int32 nLen) 309 { 310 while(nPos < nLen && (rCharA == rCandidate[nPos] || rCharB == rCandidate[nPos])) 311 { 312 nPos++; 313 } 314 } 315 copySign(const rtl::OUString & rCandidate,sal_Int32 & nPos,rtl::OUStringBuffer & rTarget,const sal_Int32 nLen)316 void copySign(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) 317 { 318 if(nPos < nLen) 319 { 320 const sal_Unicode aChar(rCandidate[nPos]); 321 322 if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar) 323 { 324 rTarget.append(aChar); 325 nPos++; 326 } 327 } 328 } 329 copyNumber(const rtl::OUString & rCandidate,sal_Int32 & nPos,rtl::OUStringBuffer & rTarget,const sal_Int32 nLen)330 void copyNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) 331 { 332 bool bOnNumber(true); 333 334 while(bOnNumber && nPos < nLen) 335 { 336 const sal_Unicode aChar(rCandidate[nPos]); 337 338 bOnNumber = (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) || sal_Unicode('.') == aChar; 339 340 if(bOnNumber) 341 { 342 rTarget.append(aChar); 343 nPos++; 344 } 345 } 346 } 347 copyHex(const rtl::OUString & rCandidate,sal_Int32 & nPos,rtl::OUStringBuffer & rTarget,const sal_Int32 nLen)348 void copyHex(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) 349 { 350 bool bOnHex(true); 351 352 while(bOnHex && nPos < nLen) 353 { 354 const sal_Unicode aChar(rCandidate[nPos]); 355 356 bOnHex = (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) 357 || (sal_Unicode('A') <= aChar && sal_Unicode('F') >= aChar) 358 || (sal_Unicode('a') <= aChar && sal_Unicode('f') >= aChar); 359 360 if(bOnHex) 361 { 362 rTarget.append(aChar); 363 nPos++; 364 } 365 } 366 } 367 copyString(const rtl::OUString & rCandidate,sal_Int32 & nPos,rtl::OUStringBuffer & rTarget,const sal_Int32 nLen)368 void copyString(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) 369 { 370 bool bOnChar(true); 371 372 while(bOnChar && nPos < nLen) 373 { 374 const sal_Unicode aChar(rCandidate[nPos]); 375 376 bOnChar = (sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar) 377 || (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar) 378 || sal_Unicode('-') == aChar; 379 380 if(bOnChar) 381 { 382 rTarget.append(aChar); 383 nPos++; 384 } 385 } 386 } 387 copyToLimiter(const rtl::OUString & rCandidate,const sal_Unicode & rLimiter,sal_Int32 & nPos,rtl::OUStringBuffer & rTarget,const sal_Int32 nLen)388 void copyToLimiter(const rtl::OUString& rCandidate, const sal_Unicode& rLimiter, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen) 389 { 390 while(nPos < nLen && rLimiter != rCandidate[nPos]) 391 { 392 rTarget.append(rCandidate[nPos]); 393 nPos++; 394 } 395 } 396 readNumber(const rtl::OUString & rCandidate,sal_Int32 & nPos,double & fNum,const sal_Int32 nLen)397 bool readNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fNum, const sal_Int32 nLen) 398 { 399 if(nPos < nLen) 400 { 401 rtl::OUStringBuffer aNum; 402 403 copySign(rCandidate, nPos, aNum, nLen); 404 copyNumber(rCandidate, nPos, aNum, nLen); 405 406 if(nPos < nLen) 407 { 408 const sal_Unicode aChar(rCandidate[nPos]); 409 410 if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar) 411 { 412 // try to read exponential number, but be careful. I had 413 // a case where dx="2em" was used, thus the 'e' was consumed 414 // by error. First try if there are numbers after the 'e', 415 // safe current state 416 nPos++; 417 const rtl::OUStringBuffer aNum2(aNum); 418 const sal_Int32 nPosAfterE(nPos); 419 420 aNum.append(aChar); 421 copySign(rCandidate, nPos, aNum, nLen); 422 copyNumber(rCandidate, nPos, aNum, nLen); 423 424 if(nPosAfterE == nPos) 425 { 426 // no number after 'e', go back. Do not 427 // return false, it's still a valid integer number 428 aNum = aNum2; 429 nPos--; 430 } 431 } 432 } 433 434 if(aNum.getLength()) 435 { 436 rtl_math_ConversionStatus eStatus; 437 438 fNum = rtl::math::stringToDouble( 439 aNum.makeStringAndClear(), (sal_Unicode)('.'), (sal_Unicode)(','), 440 &eStatus, 0); 441 442 return eStatus == rtl_math_ConversionStatus_Ok; 443 } 444 } 445 446 return false; 447 } 448 readUnit(const rtl::OUString & rCandidate,sal_Int32 & nPos,const sal_Int32 nLen)449 SvgUnit readUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, const sal_Int32 nLen) 450 { 451 SvgUnit aRetval(Unit_px); 452 453 if(nPos < nLen) 454 { 455 const sal_Unicode aCharA(rCandidate[nPos]); 456 457 if(nPos + 1 < nLen) 458 { 459 const sal_Unicode aCharB(rCandidate[nPos + 1]); 460 bool bTwoCharValid(false); 461 462 switch(aCharA) 463 { 464 case sal_Unicode('e') : 465 { 466 if(sal_Unicode('m') == aCharB) 467 { 468 // 'em' Relative to current font size 469 aRetval = Unit_em; 470 bTwoCharValid = true; 471 } 472 else if(sal_Unicode('x') == aCharB) 473 { 474 // 'ex' Relative to current font x-height 475 aRetval = Unit_ex; 476 bTwoCharValid = true; 477 } 478 break; 479 } 480 case sal_Unicode('p') : 481 { 482 if(sal_Unicode('x') == aCharB) 483 { 484 // 'px' UserUnit (default) 485 bTwoCharValid = true; 486 } 487 else if(sal_Unicode('t') == aCharB) 488 { 489 // 'pt' == 1.25 px 490 aRetval = Unit_pt; 491 bTwoCharValid = true; 492 } 493 else if(sal_Unicode('c') == aCharB) 494 { 495 // 'pc' == 15 px 496 aRetval = Unit_pc; 497 bTwoCharValid = true; 498 } 499 break; 500 } 501 case sal_Unicode('i') : 502 { 503 if(sal_Unicode('n') == aCharB) 504 { 505 // 'in' == 90 px 506 aRetval = Unit_in; 507 bTwoCharValid = true; 508 } 509 break; 510 } 511 case sal_Unicode('c') : 512 { 513 if(sal_Unicode('m') == aCharB) 514 { 515 // 'cm' == 35.43307 px 516 aRetval = Unit_cm; 517 bTwoCharValid = true; 518 } 519 break; 520 } 521 case sal_Unicode('m') : 522 { 523 if(sal_Unicode('m') == aCharB) 524 { 525 // 'mm' == 3.543307 px 526 aRetval = Unit_mm; 527 bTwoCharValid = true; 528 } 529 break; 530 } 531 } 532 533 if(bTwoCharValid) 534 { 535 nPos += 2; 536 } 537 } 538 else 539 { 540 if(sal_Unicode('%') == aCharA) 541 { 542 // percent used, relative to current 543 nPos++; 544 aRetval = Unit_percent; 545 } 546 } 547 } 548 549 return aRetval; 550 } 551 readNumberAndUnit(const rtl::OUString & rCandidate,sal_Int32 & nPos,SvgNumber & aNum,const sal_Int32 nLen)552 bool readNumberAndUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, SvgNumber& aNum, const sal_Int32 nLen) 553 { 554 double fNum(0.0); 555 556 if(readNumber(rCandidate, nPos, fNum, nLen)) 557 { 558 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 559 aNum = SvgNumber(fNum, readUnit(rCandidate, nPos, nLen)); 560 561 return true; 562 } 563 564 return false; 565 } 566 readAngle(const rtl::OUString & rCandidate,sal_Int32 & nPos,double & fAngle,const sal_Int32 nLen)567 bool readAngle(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fAngle, const sal_Int32 nLen) 568 { 569 if(readNumber(rCandidate, nPos, fAngle, nLen)) 570 { 571 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 572 573 enum DegreeType 574 { 575 deg, 576 grad, 577 rad 578 } aType(deg); // degrees is default 579 580 if(nPos < nLen) 581 { 582 const sal_Unicode aChar(rCandidate[nPos]); 583 static rtl::OUString aStrGrad(rtl::OUString::createFromAscii("grad")); 584 static rtl::OUString aStrRad(rtl::OUString::createFromAscii("rad")); 585 586 switch(aChar) 587 { 588 case sal_Unicode('g') : 589 case sal_Unicode('G') : 590 { 591 if(rCandidate.matchIgnoreAsciiCase(aStrGrad, nPos)) 592 { 593 // angle in grad 594 nPos += aStrGrad.getLength(); 595 } 596 break; 597 } 598 case sal_Unicode('r') : 599 case sal_Unicode('R') : 600 { 601 if(rCandidate.matchIgnoreAsciiCase(aStrRad, nPos)) 602 { 603 // angle in radians 604 nPos += aStrRad.getLength(); 605 } 606 break; 607 } 608 } 609 } 610 611 // convert to radians 612 if(deg == aType) 613 { 614 fAngle *= F_PI / 180.0; 615 } 616 else if(grad == aType) 617 { 618 // looks like 100 grad is 90 degrees 619 fAngle *= F_PI / 200.0; 620 } 621 622 return true; 623 } 624 625 return false; 626 } 627 read_hex(const sal_Unicode & rChar)628 sal_Int32 read_hex(const sal_Unicode& rChar) 629 { 630 if(rChar >= sal_Unicode('0') && rChar <=sal_Unicode('9')) 631 { 632 return sal_Int32(rChar - sal_Unicode('0')); 633 } 634 else if(rChar >= sal_Unicode('A') && rChar <=sal_Unicode('F')) 635 { 636 return 10 + sal_Int32(rChar - sal_Unicode('A')); 637 } 638 else if(rChar >= sal_Unicode('a') && rChar <=sal_Unicode('f')) 639 { 640 return 10 + sal_Int32(rChar - sal_Unicode('a')); 641 } 642 else 643 { 644 // error 645 return 0; 646 } 647 } 648 match_colorKeyword(basegfx::BColor & rColor,const rtl::OUString & rName)649 bool match_colorKeyword(basegfx::BColor& rColor, const rtl::OUString& rName) 650 { 651 typedef std::hash_map< rtl::OUString, Color, rtl::OUStringHash > ColorTokenMapper; 652 typedef std::pair< rtl::OUString, Color > ColorTokenValueType; 653 ColorTokenMapper aColorTokenMapperList; 654 655 if(aColorTokenMapperList.empty()) 656 { 657 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aliceblue"), Color(240, 248, 255))); 658 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("antiquewhite"), Color(250, 235, 215))); 659 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aqua"), Color( 0, 255, 255))); 660 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aquamarine"), Color(127, 255, 212))); 661 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("azure"), Color(240, 255, 255))); 662 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("beige"), Color(245, 245, 220))); 663 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("bisque"), Color(255, 228, 196))); 664 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("black"), Color( 0, 0, 0))); 665 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blanchedalmond"), Color(255, 235, 205))); 666 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blue"), Color( 0, 0, 255))); 667 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blueviolet"), Color(138, 43, 226))); 668 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("brown"), Color(165, 42, 42))); 669 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("burlywood"), Color(222, 184, 135))); 670 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cadetblue"), Color( 95, 158, 160))); 671 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chartreuse"), Color(127, 255, 0))); 672 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chocolate"), Color(210, 105, 30))); 673 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("coral"), Color(255, 127, 80))); 674 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornflowerblue"), Color(100, 149, 237))); 675 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornsilk"), Color(255, 248, 220))); 676 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("crimson"), Color(220, 20, 60))); 677 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cyan"), Color( 0, 255, 255))); 678 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkblue"), Color( 0, 0, 139))); 679 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkcyan"), Color( 0, 139, 139))); 680 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgoldenrod"), Color(184, 134, 11))); 681 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgray"), Color(169, 169, 169))); 682 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgreen"), Color( 0, 100, 0))); 683 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgrey"), Color(169, 169, 169))); 684 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkkhaki"), Color(189, 183, 107))); 685 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkmagenta"), Color(139, 0, 139))); 686 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkolivegreen"), Color( 85, 107, 47))); 687 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorange"), Color(255, 140, 0))); 688 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorchid"), Color(153, 50, 204))); 689 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkred"), Color(139, 0, 0))); 690 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darksalmon"), Color(233, 150, 122))); 691 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkseagreen"), Color(143, 188, 143))); 692 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslateblue"), Color( 72, 61, 139))); 693 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategray"), Color( 47, 79, 79))); 694 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategrey"), Color( 47, 79, 79))); 695 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkturquoise"), Color( 0, 206, 209))); 696 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkviolet"), Color(148, 0, 211))); 697 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deeppink"), Color(255, 20, 147))); 698 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deepskyblue"), Color( 0, 191, 255))); 699 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgray"), Color(105, 105, 105))); 700 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgrey"), Color(105, 105, 105))); 701 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dodgerblue"), Color( 30, 144, 255))); 702 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("firebrick"), Color(178, 34, 34))); 703 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("floralwhite"), Color(255, 250, 240))); 704 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("forestgreen"), Color( 34, 139, 34))); 705 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("fuchsia"), Color(255, 0, 255))); 706 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gainsboro"), Color(220, 220, 220))); 707 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ghostwhite"), Color(248, 248, 255))); 708 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gold"), Color(255, 215, 0))); 709 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("goldenrod"), Color(218, 165, 32))); 710 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gray"), Color(128, 128, 128))); 711 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("grey"), Color(128, 128, 128))); 712 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("green"), Color(0, 128, 0))); 713 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("greenyellow"), Color(173, 255, 47))); 714 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("honeydew"), Color(240, 255, 240))); 715 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("hotpink"), Color(255, 105, 180))); 716 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indianred"), Color(205, 92, 92))); 717 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indigo"), Color( 75, 0, 130))); 718 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ivory"), Color(255, 255, 240))); 719 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("khaki"), Color(240, 230, 140))); 720 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavender"), Color(230, 230, 250))); 721 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavenderblush"), Color(255, 240, 245))); 722 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lawngreen"), Color(124, 252, 0))); 723 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lemonchiffon"), Color(255, 250, 205))); 724 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightblue"), Color(173, 216, 230))); 725 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcoral"), Color(240, 128, 128))); 726 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcyan"), Color(224, 255, 255))); 727 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgoldenrodyellow"), Color(250, 250, 210))); 728 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgray"), Color(211, 211, 211))); 729 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgreen"), Color(144, 238, 144))); 730 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgrey"), Color(211, 211, 211))); 731 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightpink"), Color(255, 182, 193))); 732 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsalmon"), Color(255, 160, 122))); 733 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightseagreen"), Color( 32, 178, 170))); 734 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightskyblue"), Color(135, 206, 250))); 735 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategray"), Color(119, 136, 153))); 736 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategrey"), Color(119, 136, 153))); 737 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsteelblue"), Color(176, 196, 222))); 738 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightyellow"), Color(255, 255, 224))); 739 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lime"), Color( 0, 255, 0))); 740 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("limegreen"), Color( 50, 205, 50))); 741 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("linen"), Color(250, 240, 230))); 742 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("magenta"), Color(255, 0, 255))); 743 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("maroon"), Color(128, 0, 0))); 744 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumaquamarine"), Color(102, 205, 170))); 745 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumblue"), Color( 0, 0, 205))); 746 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumorchid"), Color(186, 85, 211))); 747 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumpurple"), Color(147, 112, 219))); 748 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumseagreen"), Color( 60, 179, 113))); 749 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumslateblue"), Color(123, 104, 238))); 750 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumspringgreen"), Color( 0, 250, 154))); 751 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumturquoise"), Color( 72, 209, 204))); 752 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumvioletred"), Color(199, 21, 133))); 753 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("midnightblue"), Color( 25, 25, 112))); 754 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mintcream"), Color(245, 255, 250))); 755 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mistyrose"), Color(255, 228, 225))); 756 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("moccasin"), Color(255, 228, 181))); 757 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navajowhite"), Color(255, 222, 173))); 758 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navy"), Color( 0, 0, 128))); 759 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("oldlace"), Color(253, 245, 230))); 760 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olive"), Color(128, 128, 0))); 761 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olivedrab"), Color(107, 142, 35))); 762 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orange"), Color(255, 165, 0))); 763 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orangered"), Color(255, 69, 0))); 764 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orchid"), Color(218, 112, 214))); 765 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegoldenrod"), Color(238, 232, 170))); 766 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegreen"), Color(152, 251, 152))); 767 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("paleturquoise"), Color(175, 238, 238))); 768 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palevioletred"), Color(219, 112, 147))); 769 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("papayawhip"), Color(255, 239, 213))); 770 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peachpuff"), Color(255, 218, 185))); 771 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peru"), Color(205, 133, 63))); 772 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("pink"), Color(255, 192, 203))); 773 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("plum"), Color(221, 160, 221))); 774 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("powderblue"), Color(176, 224, 230))); 775 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("purple"), Color(128, 0, 128))); 776 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("red"), Color(255, 0, 0))); 777 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("rosybrown"), Color(188, 143, 143))); 778 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("royalblue"), Color( 65, 105, 225))); 779 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("saddlebrown"), Color(139, 69, 19))); 780 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("salmon"), Color(250, 128, 114))); 781 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sandybrown"), Color(244, 164, 96))); 782 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seagreen"), Color( 46, 139, 87))); 783 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seashell"), Color(255, 245, 238))); 784 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sienna"), Color(160, 82, 45))); 785 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("silver"), Color(192, 192, 192))); 786 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("skyblue"), Color(135, 206, 235))); 787 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slateblue"), Color(106, 90, 205))); 788 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategray"), Color(112, 128, 144))); 789 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategrey"), Color(112, 128, 144))); 790 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("snow"), Color(255, 250, 250))); 791 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("springgreen"), Color( 0, 255, 127))); 792 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("steelblue"), Color( 70, 130, 180))); 793 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tan"), Color(210, 180, 140))); 794 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("teal"), Color( 0, 128, 128))); 795 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("thistle"), Color(216, 191, 216))); 796 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tomato"), Color(255, 99, 71))); 797 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("turquoise"), Color( 64, 224, 208))); 798 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("violet"), Color(238, 130, 238))); 799 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("wheat"), Color(245, 222, 179))); 800 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("white"), Color(255, 255, 255))); 801 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("whitesmoke"), Color(245, 245, 245))); 802 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellow"), Color(255, 255, 0))); 803 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellowgreen"), Color(154, 205, 50))); 804 } 805 806 const ColorTokenMapper::const_iterator aResult(aColorTokenMapperList.find(rName)); 807 808 if(aResult == aColorTokenMapperList.end()) 809 { 810 return false; 811 } 812 else 813 { 814 rColor = aResult->second.getBColor(); 815 return true; 816 } 817 } 818 read_color(const rtl::OUString & rCandidate,basegfx::BColor & rColor)819 bool read_color(const rtl::OUString& rCandidate, basegfx::BColor& rColor) 820 { 821 const sal_Int32 nLen(rCandidate.getLength()); 822 823 if(nLen) 824 { 825 const sal_Unicode aChar(rCandidate[0]); 826 const double fFactor(1.0 / 255.0); 827 828 if(aChar == sal_Unicode('#')) 829 { 830 // hex definition 831 rtl::OUStringBuffer aNum; 832 sal_Int32 nPos(1); 833 834 copyHex(rCandidate, nPos, aNum, nLen); 835 const sal_Int32 nLength(aNum.getLength()); 836 837 if(3 == nLength) 838 { 839 const sal_Int32 nR(read_hex(aNum.charAt(0))); 840 const sal_Int32 nG(read_hex(aNum.charAt(1))); 841 const sal_Int32 nB(read_hex(aNum.charAt(2))); 842 843 rColor.setRed((nR | (nR << 4)) * fFactor); 844 rColor.setGreen((nG | (nG << 4)) * fFactor); 845 rColor.setBlue((nB | (nB << 4)) * fFactor); 846 847 return true; 848 } 849 else if(6 == nLength) 850 { 851 const sal_Int32 nR1(read_hex(aNum.charAt(0))); 852 const sal_Int32 nR2(read_hex(aNum.charAt(1))); 853 const sal_Int32 nG1(read_hex(aNum.charAt(2))); 854 const sal_Int32 nG2(read_hex(aNum.charAt(3))); 855 const sal_Int32 nB1(read_hex(aNum.charAt(4))); 856 const sal_Int32 nB2(read_hex(aNum.charAt(5))); 857 858 rColor.setRed((nR2 | (nR1 << 4)) * fFactor); 859 rColor.setGreen((nG2 | (nG1 << 4)) * fFactor); 860 rColor.setBlue((nB2 | (nB1 << 4)) * fFactor); 861 862 return true; 863 } 864 } 865 else 866 { 867 static rtl::OUString aStrRgb(rtl::OUString::createFromAscii("rgb")); 868 869 if(rCandidate.matchIgnoreAsciiCase(aStrRgb, 0)) 870 { 871 // rgb definition 872 sal_Int32 nPos(aStrRgb.getLength()); 873 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 874 double fR(0.0); 875 876 if(readNumber(rCandidate, nPos, fR, nLen)) 877 { 878 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 879 880 if(nPos < nLen) 881 { 882 const sal_Unicode aPercentChar(rCandidate[nPos]); 883 const bool bIsPercent(sal_Unicode('%') == aPercentChar); 884 double fG(0.0); 885 886 if(bIsPercent) 887 { 888 skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); 889 } 890 891 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 892 893 if(readNumber(rCandidate, nPos, fG, nLen)) 894 { 895 double fB(0.0); 896 897 if(bIsPercent) 898 { 899 skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); 900 } 901 902 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 903 904 if(readNumber(rCandidate, nPos, fB, nLen)) 905 { 906 const double fFac(bIsPercent ? 0.01 : fFactor); 907 908 rColor.setRed(fR * fFac); 909 rColor.setGreen(fG * fFac); 910 rColor.setBlue(fB * fFac); 911 912 if(bIsPercent) 913 { 914 skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); 915 } 916 917 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 918 return true; 919 } 920 } 921 } 922 } 923 } 924 else 925 { 926 // color keyword 927 if(match_colorKeyword(rColor, rCandidate)) 928 { 929 return true; 930 } 931 } 932 } 933 } 934 935 return false; 936 } 937 readViewBox(const rtl::OUString & rCandidate,InfoProvider & rInfoProvider)938 basegfx::B2DRange readViewBox(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider) 939 { 940 const sal_Int32 nLen(rCandidate.getLength()); 941 942 if(nLen) 943 { 944 sal_Int32 nPos(0); 945 SvgNumber aMinX; 946 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 947 948 if(readNumberAndUnit(rCandidate, nPos, aMinX, nLen)) 949 { 950 SvgNumber aMinY; 951 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 952 953 if(readNumberAndUnit(rCandidate, nPos, aMinY, nLen)) 954 { 955 SvgNumber aWidth; 956 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 957 958 if(readNumberAndUnit(rCandidate, nPos, aWidth, nLen)) 959 { 960 SvgNumber aHeight; 961 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 962 963 if(readNumberAndUnit(rCandidate, nPos, aHeight, nLen)) 964 { 965 double fX(aMinX.solve(rInfoProvider, xcoordinate)); 966 double fY(aMinY.solve(rInfoProvider, ycoordinate)); 967 double fW(aWidth.solve(rInfoProvider,xcoordinate)); 968 double fH(aHeight.solve(rInfoProvider,ycoordinate)); 969 return basegfx::B2DRange(fX,fY,fX+fW,fY+fH); 970 } 971 } 972 } 973 } 974 } 975 976 return basegfx::B2DRange(); 977 } 978 readTransform(const rtl::OUString & rCandidate,InfoProvider & rInfoProvider)979 basegfx::B2DHomMatrix readTransform(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider) 980 { 981 basegfx::B2DHomMatrix aMatrix; 982 const sal_Int32 nLen(rCandidate.getLength()); 983 984 if(nLen) 985 { 986 sal_Int32 nPos(0); 987 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 988 989 while(nPos < nLen) 990 { 991 const sal_Unicode aChar(rCandidate[nPos]); 992 const sal_Int32 nInitPos(nPos); 993 static rtl::OUString aStrMatrix(rtl::OUString::createFromAscii("matrix")); 994 static rtl::OUString aStrTranslate(rtl::OUString::createFromAscii("translate")); 995 static rtl::OUString aStrScale(rtl::OUString::createFromAscii("scale")); 996 static rtl::OUString aStrRotate(rtl::OUString::createFromAscii("rotate")); 997 static rtl::OUString aStrSkewX(rtl::OUString::createFromAscii("skewX")); 998 static rtl::OUString aStrSkewY(rtl::OUString::createFromAscii("skewY")); 999 1000 switch(aChar) 1001 { 1002 case sal_Unicode('m') : 1003 { 1004 if(rCandidate.match(aStrMatrix, nPos)) 1005 { 1006 // matrix element 1007 nPos += aStrMatrix.getLength(); 1008 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1009 SvgNumber aVal; 1010 basegfx::B2DHomMatrix aNew; 1011 1012 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1013 { 1014 aNew.set(0, 0, aVal.solve(rInfoProvider)); // Element A 1015 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1016 1017 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1018 { 1019 aNew.set(1, 0, aVal.solve(rInfoProvider)); // Element B 1020 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1021 1022 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1023 { 1024 aNew.set(0, 1, aVal.solve(rInfoProvider)); // Element C 1025 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1026 1027 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1028 { 1029 aNew.set(1, 1, aVal.solve(rInfoProvider)); // Element D 1030 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1031 1032 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1033 { 1034 aNew.set(0, 2, aVal.solve(rInfoProvider, xcoordinate)); // Element E 1035 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1036 1037 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1038 { 1039 aNew.set(1, 2, aVal.solve(rInfoProvider, ycoordinate)); // Element F 1040 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1041 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1042 1043 // caution: String is evaluated from left to right, but matrix multiplication 1044 // in SVG is right to left, so put the new transformation before the current 1045 // one by multiplicating from the right side 1046 aMatrix = aMatrix * aNew; 1047 } 1048 } 1049 } 1050 } 1051 } 1052 } 1053 } 1054 break; 1055 } 1056 case sal_Unicode('t') : 1057 { 1058 if(rCandidate.match(aStrTranslate, nPos)) 1059 { 1060 // translate element 1061 nPos += aStrTranslate.getLength(); 1062 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1063 SvgNumber aTransX; 1064 1065 if(readNumberAndUnit(rCandidate, nPos, aTransX, nLen)) 1066 { 1067 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1068 SvgNumber aTransY; 1069 readNumberAndUnit(rCandidate, nPos, aTransY, nLen); 1070 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1071 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1072 1073 aMatrix = aMatrix * basegfx::tools::createTranslateB2DHomMatrix( 1074 aTransX.solve(rInfoProvider, xcoordinate), 1075 aTransY.solve(rInfoProvider, ycoordinate)); 1076 } 1077 } 1078 break; 1079 } 1080 case sal_Unicode('s') : 1081 { 1082 if(rCandidate.match(aStrScale, nPos)) 1083 { 1084 // scale element 1085 nPos += aStrScale.getLength(); 1086 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1087 SvgNumber aScaleX; 1088 1089 if(readNumberAndUnit(rCandidate, nPos, aScaleX, nLen)) 1090 { 1091 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1092 SvgNumber aScaleY(aScaleX); 1093 readNumberAndUnit(rCandidate, nPos, aScaleY, nLen); 1094 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1095 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1096 1097 aMatrix = aMatrix * basegfx::tools::createScaleB2DHomMatrix( 1098 aScaleX.solve(rInfoProvider), 1099 aScaleY.solve(rInfoProvider)); 1100 } 1101 } 1102 else if(rCandidate.match(aStrSkewX, nPos)) 1103 { 1104 // skewx element 1105 nPos += aStrSkewX.getLength(); 1106 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1107 double fSkewX(0.0); 1108 1109 if(readAngle(rCandidate, nPos, fSkewX, nLen)) 1110 { 1111 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1112 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1113 1114 aMatrix = aMatrix * basegfx::tools::createShearXB2DHomMatrix(tan(fSkewX)); 1115 } 1116 } 1117 else if(rCandidate.match(aStrSkewY, nPos)) 1118 { 1119 // skewy element 1120 nPos += aStrSkewY.getLength(); 1121 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1122 double fSkewY(0.0); 1123 1124 if(readAngle(rCandidate, nPos, fSkewY, nLen)) 1125 { 1126 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1127 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1128 1129 aMatrix = aMatrix * basegfx::tools::createShearYB2DHomMatrix(tan(fSkewY)); 1130 } 1131 } 1132 break; 1133 } 1134 case sal_Unicode('r') : 1135 { 1136 if(rCandidate.match(aStrRotate, nPos)) 1137 { 1138 // rotate element 1139 nPos += aStrRotate.getLength(); 1140 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1141 double fAngle(0.0); 1142 1143 if(readAngle(rCandidate, nPos, fAngle, nLen)) 1144 { 1145 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1146 SvgNumber aX; 1147 readNumberAndUnit(rCandidate, nPos, aX, nLen); 1148 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1149 SvgNumber aY; 1150 readNumberAndUnit(rCandidate, nPos, aY, nLen); 1151 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1152 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1153 1154 const double fX(aX.isSet() ? aX.solve(rInfoProvider, xcoordinate) : 0.0); 1155 const double fY(aY.isSet() ? aY.solve(rInfoProvider, ycoordinate) : 0.0); 1156 1157 if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) 1158 { 1159 // rotate around point 1160 aMatrix = aMatrix * basegfx::tools::createRotateAroundPoint(fX, fY, fAngle); 1161 } 1162 else 1163 { 1164 // rotate 1165 aMatrix = aMatrix * basegfx::tools::createRotateB2DHomMatrix(fAngle); 1166 } 1167 } 1168 } 1169 break; 1170 } 1171 } 1172 1173 if(nInitPos == nPos) 1174 { 1175 OSL_ENSURE(false, "Could not interpret on current position (!)"); 1176 nPos++; 1177 } 1178 } 1179 } 1180 1181 return aMatrix; 1182 } 1183 readSingleNumber(const rtl::OUString & rCandidate,SvgNumber & aNum)1184 bool readSingleNumber(const rtl::OUString& rCandidate, SvgNumber& aNum) 1185 { 1186 const sal_Int32 nLen(rCandidate.getLength()); 1187 sal_Int32 nPos(0); 1188 1189 return readNumberAndUnit(rCandidate, nPos, aNum, nLen); 1190 } 1191 readLocalUrl(const rtl::OUString & rCandidate,rtl::OUString & rURL)1192 bool readLocalUrl(const rtl::OUString& rCandidate, rtl::OUString& rURL) 1193 { 1194 static rtl::OUString aStrUrl(rtl::OUString::createFromAscii("url")); 1195 1196 if(rCandidate.match(aStrUrl, 0)) 1197 { 1198 const sal_Int32 nLen(rCandidate.getLength()); 1199 sal_Int32 nPos(aStrUrl.getLength()); 1200 1201 skip_char(rCandidate, sal_Unicode('('), sal_Unicode('#'), nPos, nLen); 1202 rtl::OUStringBuffer aTokenValue; 1203 copyToLimiter(rCandidate, sal_Unicode(')'), nPos, aTokenValue, nLen); 1204 rURL = aTokenValue.makeStringAndClear(); 1205 1206 return true; 1207 } 1208 1209 return false; 1210 } 1211 readSvgPaint(const rtl::OUString & rCandidate,SvgPaint & rSvgPaint,rtl::OUString & rURL)1212 bool readSvgPaint(const rtl::OUString& rCandidate, SvgPaint& rSvgPaint, rtl::OUString& rURL) 1213 { 1214 const sal_Int32 nLen(rCandidate.getLength()); 1215 1216 if(nLen) 1217 { 1218 basegfx::BColor aColor; 1219 1220 if(read_color(rCandidate, aColor)) 1221 { 1222 rSvgPaint = SvgPaint(aColor, true, true); 1223 return true; 1224 } 1225 else 1226 { 1227 static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none")); 1228 static rtl::OUString aStrCurrentColor(rtl::OUString::createFromAscii("currentColor")); 1229 1230 if(rCandidate.match(aStrNone, 0)) 1231 { 1232 rSvgPaint = SvgPaint(aColor, true, false, false); 1233 return true; 1234 } 1235 else if(readLocalUrl(rCandidate, rURL)) 1236 { 1237 /// Url is copied to rURL, but needs to be solved outside this helper 1238 return false; 1239 } 1240 else if(rCandidate.match(aStrCurrentColor, 0)) 1241 { 1242 rSvgPaint = SvgPaint(aColor, true, true, true); 1243 return true; 1244 } 1245 } 1246 } 1247 1248 return false; 1249 } 1250 readSvgNumberVector(const rtl::OUString & rCandidate,SvgNumberVector & rSvgNumberVector)1251 bool readSvgNumberVector(const rtl::OUString& rCandidate, SvgNumberVector& rSvgNumberVector) 1252 { 1253 const sal_Int32 nLen(rCandidate.getLength()); 1254 rSvgNumberVector.clear(); 1255 1256 if(nLen) 1257 { 1258 sal_Int32 nPos(0); 1259 SvgNumber aNum; 1260 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1261 1262 while(readNumberAndUnit(rCandidate, nPos, aNum, nLen)) 1263 { 1264 rSvgNumberVector.push_back(aNum); 1265 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1266 } 1267 1268 return !rSvgNumberVector.empty(); 1269 } 1270 1271 return false; 1272 } 1273 readSvgAspectRatio(const rtl::OUString & rCandidate)1274 SvgAspectRatio readSvgAspectRatio(const rtl::OUString& rCandidate) 1275 { 1276 const sal_Int32 nLen(rCandidate.getLength()); 1277 1278 if(nLen) 1279 { 1280 sal_Int32 nPos(0); 1281 SvgAlign aSvgAlign(Align_xMidYMid); 1282 bool bDefer(false); 1283 bool bMeetOrSlice(true); 1284 bool bChanged(false); 1285 1286 while(nPos < nLen) 1287 { 1288 const sal_Int32 nInitPos(nPos); 1289 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 1290 rtl::OUStringBuffer aTokenName; 1291 copyString(rCandidate, nPos, aTokenName, nLen); 1292 1293 if(aTokenName.getLength()) 1294 { 1295 switch(StrToSVGToken(aTokenName.makeStringAndClear())) 1296 { 1297 case SVGTokenDefer: 1298 { 1299 bDefer = true; 1300 bChanged = true; 1301 break; 1302 } 1303 case SVGTokenNone: 1304 { 1305 aSvgAlign = Align_none; 1306 bChanged = true; 1307 break; 1308 } 1309 case SVGTokenXMinYMin: 1310 { 1311 aSvgAlign = Align_xMinYMin; 1312 bChanged = true; 1313 break; 1314 } 1315 case SVGTokenXMidYMin: 1316 { 1317 aSvgAlign = Align_xMidYMin; 1318 bChanged = true; 1319 break; 1320 } 1321 case SVGTokenXMaxYMin: 1322 { 1323 aSvgAlign = Align_xMaxYMin; 1324 bChanged = true; 1325 break; 1326 } 1327 case SVGTokenXMinYMid: 1328 { 1329 aSvgAlign = Align_xMinYMid; 1330 bChanged = true; 1331 break; 1332 } 1333 case SVGTokenXMidYMid: 1334 { 1335 aSvgAlign = Align_xMidYMid; 1336 bChanged = true; 1337 break; 1338 } 1339 case SVGTokenXMaxYMid: 1340 { 1341 aSvgAlign = Align_xMaxYMid; 1342 bChanged = true; 1343 break; 1344 } 1345 case SVGTokenXMinYMax: 1346 { 1347 aSvgAlign = Align_xMinYMax; 1348 bChanged = true; 1349 break; 1350 } 1351 case SVGTokenXMidYMax: 1352 { 1353 aSvgAlign = Align_xMidYMax; 1354 bChanged = true; 1355 break; 1356 } 1357 case SVGTokenXMaxYMax: 1358 { 1359 aSvgAlign = Align_xMaxYMax; 1360 bChanged = true; 1361 break; 1362 } 1363 case SVGTokenMeet: 1364 { 1365 bMeetOrSlice = true; 1366 bChanged = true; 1367 break; 1368 } 1369 case SVGTokenSlice: 1370 { 1371 bMeetOrSlice = false; 1372 bChanged = true; 1373 break; 1374 } 1375 default: 1376 { 1377 break; 1378 } 1379 } 1380 } 1381 1382 if(nInitPos == nPos) 1383 { 1384 OSL_ENSURE(false, "Could not interpret on current position (!)"); 1385 nPos++; 1386 } 1387 } 1388 1389 if(bChanged) 1390 { 1391 return SvgAspectRatio(aSvgAlign, bDefer, bMeetOrSlice); 1392 } 1393 } 1394 1395 return SvgAspectRatio(); 1396 } 1397 readSvgStringVector(const rtl::OUString & rCandidate,SvgStringVector & rSvgStringVector)1398 bool readSvgStringVector(const rtl::OUString& rCandidate, SvgStringVector& rSvgStringVector) 1399 { 1400 rSvgStringVector.clear(); 1401 const sal_Int32 nLen(rCandidate.getLength()); 1402 1403 if(nLen) 1404 { 1405 sal_Int32 nPos(0); 1406 rtl::OUStringBuffer aTokenValue; 1407 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1408 1409 while(nPos < nLen) 1410 { 1411 copyToLimiter(rCandidate, sal_Unicode(','), nPos, aTokenValue, nLen); 1412 skip_char(rCandidate, sal_Unicode(','), sal_Unicode(' '), nPos, nLen); 1413 const rtl::OUString aString = aTokenValue.makeStringAndClear(); 1414 1415 if(aString.getLength()) 1416 { 1417 rSvgStringVector.push_back(aString); 1418 } 1419 } 1420 } 1421 1422 return !rSvgStringVector.empty(); 1423 } 1424 readImageLink(const rtl::OUString & rCandidate,rtl::OUString & rXLink,rtl::OUString & rUrl,rtl::OUString & rMimeType,rtl::OUString & rData)1425 void readImageLink(const rtl::OUString& rCandidate, rtl::OUString& rXLink, rtl::OUString& rUrl, rtl::OUString& rMimeType, rtl::OUString& rData) 1426 { 1427 rXLink = rUrl = rMimeType = rData = rtl::OUString(); 1428 1429 if(sal_Unicode('#') == rCandidate[0]) 1430 { 1431 // local link 1432 rXLink = rCandidate.copy(1); 1433 } 1434 else 1435 { 1436 static rtl::OUString aStrData(rtl::OUString::createFromAscii("data:")); 1437 1438 if(rCandidate.match(aStrData, 0)) 1439 { 1440 // embedded data 1441 sal_Int32 nPos(aStrData.getLength()); 1442 sal_Int32 nLen(rCandidate.getLength()); 1443 rtl::OUStringBuffer aBuffer; 1444 1445 // read mime type 1446 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 1447 copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aBuffer, nLen); 1448 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen); 1449 rMimeType = aBuffer.makeStringAndClear(); 1450 1451 if(rMimeType.getLength() && nPos < nLen) 1452 { 1453 static rtl::OUString aStrImage(rtl::OUString::createFromAscii("image")); 1454 1455 if(rMimeType.match(aStrImage, 0)) 1456 { 1457 // image data 1458 rtl::OUString aData(rCandidate.copy(nPos)); 1459 static rtl::OUString aStrBase64(rtl::OUString::createFromAscii("base64")); 1460 1461 if(aData.match(aStrBase64, 0)) 1462 { 1463 // base64 encoded 1464 nPos = aStrBase64.getLength(); 1465 nLen = aData.getLength(); 1466 1467 skip_char(aData, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1468 1469 if(nPos < nLen) 1470 { 1471 rData = aData.copy(nPos); 1472 } 1473 } 1474 } 1475 } 1476 } 1477 else 1478 { 1479 // Url (path and filename) 1480 rUrl = rCandidate; 1481 } 1482 } 1483 } 1484 convert(const rtl::OUString & rCandidate,const sal_Unicode & rPattern,const sal_Unicode & rNew,bool bRemove)1485 rtl::OUString convert(const rtl::OUString& rCandidate, const sal_Unicode& rPattern, const sal_Unicode& rNew, bool bRemove) 1486 { 1487 const sal_Int32 nLen(rCandidate.getLength()); 1488 1489 if(nLen) 1490 { 1491 sal_Int32 nPos(0); 1492 rtl::OUStringBuffer aBuffer; 1493 bool bChanged(false); 1494 1495 while(nPos < nLen) 1496 { 1497 const sal_Unicode aChar(rCandidate[nPos]); 1498 1499 if(rPattern == aChar) 1500 { 1501 bChanged = true; 1502 1503 if(!bRemove) 1504 { 1505 aBuffer.append(rNew); 1506 } 1507 } 1508 else 1509 { 1510 aBuffer.append(aChar); 1511 } 1512 1513 nPos++; 1514 } 1515 1516 if(bChanged) 1517 { 1518 return aBuffer.makeStringAndClear(); 1519 } 1520 } 1521 1522 return rCandidate; 1523 } 1524 consolidateContiguosSpace(const rtl::OUString & rCandidate)1525 rtl::OUString consolidateContiguosSpace(const rtl::OUString& rCandidate) 1526 { 1527 const sal_Int32 nLen(rCandidate.getLength()); 1528 1529 if(nLen) 1530 { 1531 sal_Int32 nPos(0); 1532 rtl::OUStringBuffer aBuffer; 1533 bool bInsideSpace(false); 1534 const sal_Unicode aSpace(' '); 1535 1536 while(nPos < nLen) 1537 { 1538 const sal_Unicode aChar(rCandidate[nPos]); 1539 1540 if(aSpace == aChar) 1541 { 1542 bInsideSpace = true; 1543 } 1544 else 1545 { 1546 if(bInsideSpace) 1547 { 1548 bInsideSpace = false; 1549 aBuffer.append(aSpace); 1550 } 1551 1552 aBuffer.append(aChar); 1553 } 1554 1555 nPos++; 1556 } 1557 1558 if(bInsideSpace) 1559 { 1560 aBuffer.append(aSpace); 1561 } 1562 1563 if(aBuffer.getLength() != nLen) 1564 { 1565 return aBuffer.makeStringAndClear(); 1566 } 1567 } 1568 1569 return rCandidate; 1570 } 1571 whiteSpaceHandlingDefault(const rtl::OUString & rCandidate)1572 rtl::OUString whiteSpaceHandlingDefault(const rtl::OUString& rCandidate) 1573 { 1574 const sal_Unicode aNewline('\n'); 1575 const sal_Unicode aTab('\t'); 1576 const sal_Unicode aSpace(' '); 1577 1578 // remove all newline characters 1579 rtl::OUString aRetval(convert(rCandidate, aNewline, aNewline, true)); 1580 1581 // convert tab to space 1582 aRetval = convert(aRetval, aTab, aSpace, false); 1583 1584 // strip of all leading and trailing spaces 1585 aRetval = aRetval.trim(); 1586 1587 // consolidate contiguos space 1588 aRetval = consolidateContiguosSpace(aRetval); 1589 1590 return aRetval; 1591 } 1592 whiteSpaceHandlingPreserve(const rtl::OUString & rCandidate)1593 rtl::OUString whiteSpaceHandlingPreserve(const rtl::OUString& rCandidate) 1594 { 1595 const sal_Unicode aNewline('\n'); 1596 const sal_Unicode aTab('\t'); 1597 const sal_Unicode aSpace(' '); 1598 1599 // convert newline to space 1600 rtl::OUString aRetval(convert(rCandidate, aNewline, aSpace, false)); 1601 1602 // convert tab to space 1603 aRetval = convert(rCandidate, aTab, aSpace, false); 1604 1605 return rCandidate; 1606 } 1607 solveSvgNumberVector(const SvgNumberVector & rInput,const InfoProvider & rInfoProvider,NumberType aNumberType)1608 ::std::vector< double > solveSvgNumberVector(const SvgNumberVector& rInput, const InfoProvider& rInfoProvider, NumberType aNumberType) 1609 { 1610 ::std::vector< double > aRetval; 1611 1612 if(!rInput.empty()) 1613 { 1614 const double nCount(rInput.size()); 1615 aRetval.reserve(nCount); 1616 1617 for(sal_uInt32 a(0); a < nCount; a++) 1618 { 1619 aRetval.push_back(rInput[a].solve(rInfoProvider, aNumberType)); 1620 } 1621 } 1622 1623 return aRetval; 1624 } 1625 1626 } // end of namespace svgreader 1627 } // end of namespace svgio 1628 1629 ////////////////////////////////////////////////////////////////////////////// 1630 // eof 1631