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 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 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 75 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 159 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 215 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 295 bool SvgNumber::isPositive() const 296 { 297 return basegfx::fTools::moreOrEqual(mfNumber, 0.0); 298 } 299 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 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 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 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 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 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 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 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 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 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 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 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 649 bool match_colorKeyword( 650 basegfx::BColor& rColor, 651 const rtl::OUString& rName, 652 bool bCaseIndependent) 653 { 654 typedef std::hash_map< rtl::OUString, Color, rtl::OUStringHash > ColorTokenMapper; 655 typedef std::pair< rtl::OUString, Color > ColorTokenValueType; 656 ColorTokenMapper aColorTokenMapperList; 657 658 if(aColorTokenMapperList.empty()) 659 { 660 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aliceblue"), Color(240, 248, 255))); 661 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("antiquewhite"), Color(250, 235, 215))); 662 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aqua"), Color( 0, 255, 255))); 663 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aquamarine"), Color(127, 255, 212))); 664 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("azure"), Color(240, 255, 255))); 665 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("beige"), Color(245, 245, 220))); 666 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("bisque"), Color(255, 228, 196))); 667 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("black"), Color( 0, 0, 0))); 668 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blanchedalmond"), Color(255, 235, 205))); 669 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blue"), Color( 0, 0, 255))); 670 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blueviolet"), Color(138, 43, 226))); 671 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("brown"), Color(165, 42, 42))); 672 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("burlywood"), Color(222, 184, 135))); 673 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cadetblue"), Color( 95, 158, 160))); 674 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chartreuse"), Color(127, 255, 0))); 675 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chocolate"), Color(210, 105, 30))); 676 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("coral"), Color(255, 127, 80))); 677 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornflowerblue"), Color(100, 149, 237))); 678 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornsilk"), Color(255, 248, 220))); 679 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("crimson"), Color(220, 20, 60))); 680 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cyan"), Color( 0, 255, 255))); 681 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkblue"), Color( 0, 0, 139))); 682 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkcyan"), Color( 0, 139, 139))); 683 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgoldenrod"), Color(184, 134, 11))); 684 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgray"), Color(169, 169, 169))); 685 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgreen"), Color( 0, 100, 0))); 686 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgrey"), Color(169, 169, 169))); 687 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkkhaki"), Color(189, 183, 107))); 688 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkmagenta"), Color(139, 0, 139))); 689 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkolivegreen"), Color( 85, 107, 47))); 690 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorange"), Color(255, 140, 0))); 691 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorchid"), Color(153, 50, 204))); 692 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkred"), Color(139, 0, 0))); 693 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darksalmon"), Color(233, 150, 122))); 694 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkseagreen"), Color(143, 188, 143))); 695 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslateblue"), Color( 72, 61, 139))); 696 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategray"), Color( 47, 79, 79))); 697 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategrey"), Color( 47, 79, 79))); 698 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkturquoise"), Color( 0, 206, 209))); 699 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkviolet"), Color(148, 0, 211))); 700 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deeppink"), Color(255, 20, 147))); 701 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deepskyblue"), Color( 0, 191, 255))); 702 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgray"), Color(105, 105, 105))); 703 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgrey"), Color(105, 105, 105))); 704 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dodgerblue"), Color( 30, 144, 255))); 705 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("firebrick"), Color(178, 34, 34))); 706 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("floralwhite"), Color(255, 250, 240))); 707 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("forestgreen"), Color( 34, 139, 34))); 708 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("fuchsia"), Color(255, 0, 255))); 709 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gainsboro"), Color(220, 220, 220))); 710 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ghostwhite"), Color(248, 248, 255))); 711 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gold"), Color(255, 215, 0))); 712 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("goldenrod"), Color(218, 165, 32))); 713 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gray"), Color(128, 128, 128))); 714 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("grey"), Color(128, 128, 128))); 715 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("green"), Color(0, 128, 0))); 716 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("greenyellow"), Color(173, 255, 47))); 717 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("honeydew"), Color(240, 255, 240))); 718 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("hotpink"), Color(255, 105, 180))); 719 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indianred"), Color(205, 92, 92))); 720 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indigo"), Color( 75, 0, 130))); 721 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ivory"), Color(255, 255, 240))); 722 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("khaki"), Color(240, 230, 140))); 723 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavender"), Color(230, 230, 250))); 724 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavenderblush"), Color(255, 240, 245))); 725 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lawngreen"), Color(124, 252, 0))); 726 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lemonchiffon"), Color(255, 250, 205))); 727 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightblue"), Color(173, 216, 230))); 728 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcoral"), Color(240, 128, 128))); 729 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcyan"), Color(224, 255, 255))); 730 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgoldenrodyellow"), Color(250, 250, 210))); 731 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgray"), Color(211, 211, 211))); 732 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgreen"), Color(144, 238, 144))); 733 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgrey"), Color(211, 211, 211))); 734 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightpink"), Color(255, 182, 193))); 735 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsalmon"), Color(255, 160, 122))); 736 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightseagreen"), Color( 32, 178, 170))); 737 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightskyblue"), Color(135, 206, 250))); 738 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategray"), Color(119, 136, 153))); 739 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategrey"), Color(119, 136, 153))); 740 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsteelblue"), Color(176, 196, 222))); 741 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightyellow"), Color(255, 255, 224))); 742 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lime"), Color( 0, 255, 0))); 743 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("limegreen"), Color( 50, 205, 50))); 744 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("linen"), Color(250, 240, 230))); 745 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("magenta"), Color(255, 0, 255))); 746 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("maroon"), Color(128, 0, 0))); 747 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumaquamarine"), Color(102, 205, 170))); 748 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumblue"), Color( 0, 0, 205))); 749 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumorchid"), Color(186, 85, 211))); 750 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumpurple"), Color(147, 112, 219))); 751 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumseagreen"), Color( 60, 179, 113))); 752 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumslateblue"), Color(123, 104, 238))); 753 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumspringgreen"), Color( 0, 250, 154))); 754 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumturquoise"), Color( 72, 209, 204))); 755 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumvioletred"), Color(199, 21, 133))); 756 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("midnightblue"), Color( 25, 25, 112))); 757 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mintcream"), Color(245, 255, 250))); 758 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mistyrose"), Color(255, 228, 225))); 759 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("moccasin"), Color(255, 228, 181))); 760 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navajowhite"), Color(255, 222, 173))); 761 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navy"), Color( 0, 0, 128))); 762 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("oldlace"), Color(253, 245, 230))); 763 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olive"), Color(128, 128, 0))); 764 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olivedrab"), Color(107, 142, 35))); 765 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orange"), Color(255, 165, 0))); 766 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orangered"), Color(255, 69, 0))); 767 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orchid"), Color(218, 112, 214))); 768 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegoldenrod"), Color(238, 232, 170))); 769 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegreen"), Color(152, 251, 152))); 770 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("paleturquoise"), Color(175, 238, 238))); 771 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palevioletred"), Color(219, 112, 147))); 772 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("papayawhip"), Color(255, 239, 213))); 773 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peachpuff"), Color(255, 218, 185))); 774 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peru"), Color(205, 133, 63))); 775 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("pink"), Color(255, 192, 203))); 776 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("plum"), Color(221, 160, 221))); 777 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("powderblue"), Color(176, 224, 230))); 778 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("purple"), Color(128, 0, 128))); 779 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("red"), Color(255, 0, 0))); 780 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("rosybrown"), Color(188, 143, 143))); 781 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("royalblue"), Color( 65, 105, 225))); 782 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("saddlebrown"), Color(139, 69, 19))); 783 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("salmon"), Color(250, 128, 114))); 784 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sandybrown"), Color(244, 164, 96))); 785 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seagreen"), Color( 46, 139, 87))); 786 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seashell"), Color(255, 245, 238))); 787 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sienna"), Color(160, 82, 45))); 788 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("silver"), Color(192, 192, 192))); 789 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("skyblue"), Color(135, 206, 235))); 790 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slateblue"), Color(106, 90, 205))); 791 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategray"), Color(112, 128, 144))); 792 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategrey"), Color(112, 128, 144))); 793 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("snow"), Color(255, 250, 250))); 794 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("springgreen"), Color( 0, 255, 127))); 795 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("steelblue"), Color( 70, 130, 180))); 796 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tan"), Color(210, 180, 140))); 797 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("teal"), Color( 0, 128, 128))); 798 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("thistle"), Color(216, 191, 216))); 799 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tomato"), Color(255, 99, 71))); 800 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("turquoise"), Color( 64, 224, 208))); 801 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("violet"), Color(238, 130, 238))); 802 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("wheat"), Color(245, 222, 179))); 803 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("white"), Color(255, 255, 255))); 804 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("whitesmoke"), Color(245, 245, 245))); 805 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellow"), Color(255, 255, 0))); 806 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellowgreen"), Color(154, 205, 50))); 807 } 808 809 ColorTokenMapper::const_iterator aResult(aColorTokenMapperList.find(rName)); 810 811 if(bCaseIndependent && aResult == aColorTokenMapperList.end()) 812 { 813 // also try case independent match (e.g. for Css styles) 814 aResult = aColorTokenMapperList.find(rName.toAsciiLowerCase()); 815 } 816 817 if(aResult == aColorTokenMapperList.end()) 818 { 819 return false; 820 } 821 else 822 { 823 rColor = aResult->second.getBColor(); 824 return true; 825 } 826 } 827 828 bool read_color( 829 const rtl::OUString& rCandidate, 830 basegfx::BColor& rColor, 831 bool bCaseIndependent) 832 { 833 const sal_Int32 nLen(rCandidate.getLength()); 834 835 if(nLen) 836 { 837 const sal_Unicode aChar(rCandidate[0]); 838 const double fFactor(1.0 / 255.0); 839 840 if(aChar == sal_Unicode('#')) 841 { 842 // hex definition 843 rtl::OUStringBuffer aNum; 844 sal_Int32 nPos(1); 845 846 copyHex(rCandidate, nPos, aNum, nLen); 847 const sal_Int32 nLength(aNum.getLength()); 848 849 if(3 == nLength) 850 { 851 const sal_Int32 nR(read_hex(aNum.charAt(0))); 852 const sal_Int32 nG(read_hex(aNum.charAt(1))); 853 const sal_Int32 nB(read_hex(aNum.charAt(2))); 854 855 rColor.setRed((nR | (nR << 4)) * fFactor); 856 rColor.setGreen((nG | (nG << 4)) * fFactor); 857 rColor.setBlue((nB | (nB << 4)) * fFactor); 858 859 return true; 860 } 861 else if(6 == nLength) 862 { 863 const sal_Int32 nR1(read_hex(aNum.charAt(0))); 864 const sal_Int32 nR2(read_hex(aNum.charAt(1))); 865 const sal_Int32 nG1(read_hex(aNum.charAt(2))); 866 const sal_Int32 nG2(read_hex(aNum.charAt(3))); 867 const sal_Int32 nB1(read_hex(aNum.charAt(4))); 868 const sal_Int32 nB2(read_hex(aNum.charAt(5))); 869 870 rColor.setRed((nR2 | (nR1 << 4)) * fFactor); 871 rColor.setGreen((nG2 | (nG1 << 4)) * fFactor); 872 rColor.setBlue((nB2 | (nB1 << 4)) * fFactor); 873 874 return true; 875 } 876 } 877 else 878 { 879 static rtl::OUString aStrRgb(rtl::OUString::createFromAscii("rgb")); 880 881 if(rCandidate.matchIgnoreAsciiCase(aStrRgb, 0)) 882 { 883 // rgb definition 884 sal_Int32 nPos(aStrRgb.getLength()); 885 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 886 double fR(0.0); 887 888 if(readNumber(rCandidate, nPos, fR, nLen)) 889 { 890 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 891 892 if(nPos < nLen) 893 { 894 const sal_Unicode aPercentChar(rCandidate[nPos]); 895 const bool bIsPercent(sal_Unicode('%') == aPercentChar); 896 double fG(0.0); 897 898 if(bIsPercent) 899 { 900 skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); 901 } 902 903 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 904 905 if(readNumber(rCandidate, nPos, fG, nLen)) 906 { 907 double fB(0.0); 908 909 if(bIsPercent) 910 { 911 skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); 912 } 913 914 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 915 916 if(readNumber(rCandidate, nPos, fB, nLen)) 917 { 918 const double fFac(bIsPercent ? 0.01 : fFactor); 919 920 rColor.setRed(fR * fFac); 921 rColor.setGreen(fG * fFac); 922 rColor.setBlue(fB * fFac); 923 924 if(bIsPercent) 925 { 926 skip_char(rCandidate, sal_Unicode('%'), nPos, nLen); 927 } 928 929 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 930 return true; 931 } 932 } 933 } 934 } 935 } 936 else 937 { 938 // color keyword 939 if(match_colorKeyword(rColor, rCandidate, bCaseIndependent)) 940 { 941 return true; 942 } 943 } 944 } 945 } 946 947 return false; 948 } 949 950 basegfx::B2DRange readViewBox(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider) 951 { 952 const sal_Int32 nLen(rCandidate.getLength()); 953 954 if(nLen) 955 { 956 sal_Int32 nPos(0); 957 SvgNumber aMinX; 958 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 959 960 if(readNumberAndUnit(rCandidate, nPos, aMinX, nLen)) 961 { 962 SvgNumber aMinY; 963 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 964 965 if(readNumberAndUnit(rCandidate, nPos, aMinY, nLen)) 966 { 967 SvgNumber aWidth; 968 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 969 970 if(readNumberAndUnit(rCandidate, nPos, aWidth, nLen)) 971 { 972 SvgNumber aHeight; 973 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 974 975 if(readNumberAndUnit(rCandidate, nPos, aHeight, nLen)) 976 { 977 double fX(aMinX.solve(rInfoProvider, xcoordinate)); 978 double fY(aMinY.solve(rInfoProvider, ycoordinate)); 979 double fW(aWidth.solve(rInfoProvider,xcoordinate)); 980 double fH(aHeight.solve(rInfoProvider,ycoordinate)); 981 return basegfx::B2DRange(fX,fY,fX+fW,fY+fH); 982 } 983 } 984 } 985 } 986 } 987 988 return basegfx::B2DRange(); 989 } 990 991 basegfx::B2DHomMatrix readTransform(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider) 992 { 993 basegfx::B2DHomMatrix aMatrix; 994 const sal_Int32 nLen(rCandidate.getLength()); 995 996 if(nLen) 997 { 998 sal_Int32 nPos(0); 999 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1000 1001 while(nPos < nLen) 1002 { 1003 const sal_Unicode aChar(rCandidate[nPos]); 1004 const sal_Int32 nInitPos(nPos); 1005 static rtl::OUString aStrMatrix(rtl::OUString::createFromAscii("matrix")); 1006 static rtl::OUString aStrTranslate(rtl::OUString::createFromAscii("translate")); 1007 static rtl::OUString aStrScale(rtl::OUString::createFromAscii("scale")); 1008 static rtl::OUString aStrRotate(rtl::OUString::createFromAscii("rotate")); 1009 static rtl::OUString aStrSkewX(rtl::OUString::createFromAscii("skewX")); 1010 static rtl::OUString aStrSkewY(rtl::OUString::createFromAscii("skewY")); 1011 1012 switch(aChar) 1013 { 1014 case sal_Unicode('m') : 1015 { 1016 if(rCandidate.match(aStrMatrix, nPos)) 1017 { 1018 // matrix element 1019 nPos += aStrMatrix.getLength(); 1020 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1021 SvgNumber aVal; 1022 basegfx::B2DHomMatrix aNew; 1023 1024 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1025 { 1026 aNew.set(0, 0, aVal.solve(rInfoProvider)); // Element A 1027 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1028 1029 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1030 { 1031 aNew.set(1, 0, aVal.solve(rInfoProvider)); // Element B 1032 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1033 1034 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1035 { 1036 aNew.set(0, 1, aVal.solve(rInfoProvider)); // Element C 1037 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1038 1039 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1040 { 1041 aNew.set(1, 1, aVal.solve(rInfoProvider)); // Element D 1042 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1043 1044 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1045 { 1046 aNew.set(0, 2, aVal.solve(rInfoProvider, xcoordinate)); // Element E 1047 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1048 1049 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen)) 1050 { 1051 aNew.set(1, 2, aVal.solve(rInfoProvider, ycoordinate)); // Element F 1052 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1053 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1054 1055 // caution: String is evaluated from left to right, but matrix multiplication 1056 // in SVG is right to left, so put the new transformation before the current 1057 // one by multiplicating from the right side 1058 aMatrix = aMatrix * aNew; 1059 } 1060 } 1061 } 1062 } 1063 } 1064 } 1065 } 1066 break; 1067 } 1068 case sal_Unicode('t') : 1069 { 1070 if(rCandidate.match(aStrTranslate, nPos)) 1071 { 1072 // translate element 1073 nPos += aStrTranslate.getLength(); 1074 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1075 SvgNumber aTransX; 1076 1077 if(readNumberAndUnit(rCandidate, nPos, aTransX, nLen)) 1078 { 1079 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1080 SvgNumber aTransY; 1081 readNumberAndUnit(rCandidate, nPos, aTransY, nLen); 1082 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1083 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1084 1085 aMatrix = aMatrix * basegfx::tools::createTranslateB2DHomMatrix( 1086 aTransX.solve(rInfoProvider, xcoordinate), 1087 aTransY.solve(rInfoProvider, ycoordinate)); 1088 } 1089 } 1090 break; 1091 } 1092 case sal_Unicode('s') : 1093 { 1094 if(rCandidate.match(aStrScale, nPos)) 1095 { 1096 // scale element 1097 nPos += aStrScale.getLength(); 1098 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1099 SvgNumber aScaleX; 1100 1101 if(readNumberAndUnit(rCandidate, nPos, aScaleX, nLen)) 1102 { 1103 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1104 SvgNumber aScaleY(aScaleX); 1105 readNumberAndUnit(rCandidate, nPos, aScaleY, nLen); 1106 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1107 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1108 1109 aMatrix = aMatrix * basegfx::tools::createScaleB2DHomMatrix( 1110 aScaleX.solve(rInfoProvider), 1111 aScaleY.solve(rInfoProvider)); 1112 } 1113 } 1114 else if(rCandidate.match(aStrSkewX, nPos)) 1115 { 1116 // skewx element 1117 nPos += aStrSkewX.getLength(); 1118 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1119 double fSkewX(0.0); 1120 1121 if(readAngle(rCandidate, nPos, fSkewX, nLen)) 1122 { 1123 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1124 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1125 1126 aMatrix = aMatrix * basegfx::tools::createShearXB2DHomMatrix(tan(fSkewX)); 1127 } 1128 } 1129 else if(rCandidate.match(aStrSkewY, nPos)) 1130 { 1131 // skewy element 1132 nPos += aStrSkewY.getLength(); 1133 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1134 double fSkewY(0.0); 1135 1136 if(readAngle(rCandidate, nPos, fSkewY, nLen)) 1137 { 1138 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1139 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1140 1141 aMatrix = aMatrix * basegfx::tools::createShearYB2DHomMatrix(tan(fSkewY)); 1142 } 1143 } 1144 break; 1145 } 1146 case sal_Unicode('r') : 1147 { 1148 if(rCandidate.match(aStrRotate, nPos)) 1149 { 1150 // rotate element 1151 nPos += aStrRotate.getLength(); 1152 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen); 1153 double fAngle(0.0); 1154 1155 if(readAngle(rCandidate, nPos, fAngle, nLen)) 1156 { 1157 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1158 SvgNumber aX; 1159 readNumberAndUnit(rCandidate, nPos, aX, nLen); 1160 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1161 SvgNumber aY; 1162 readNumberAndUnit(rCandidate, nPos, aY, nLen); 1163 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen); 1164 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1165 1166 const double fX(aX.isSet() ? aX.solve(rInfoProvider, xcoordinate) : 0.0); 1167 const double fY(aY.isSet() ? aY.solve(rInfoProvider, ycoordinate) : 0.0); 1168 1169 if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY)) 1170 { 1171 // rotate around point 1172 aMatrix = aMatrix * basegfx::tools::createRotateAroundPoint(fX, fY, fAngle); 1173 } 1174 else 1175 { 1176 // rotate 1177 aMatrix = aMatrix * basegfx::tools::createRotateB2DHomMatrix(fAngle); 1178 } 1179 } 1180 } 1181 break; 1182 } 1183 } 1184 1185 if(nInitPos == nPos) 1186 { 1187 OSL_ENSURE(false, "Could not interpret on current position (!)"); 1188 nPos++; 1189 } 1190 } 1191 } 1192 1193 return aMatrix; 1194 } 1195 1196 bool readSingleNumber(const rtl::OUString& rCandidate, SvgNumber& aNum) 1197 { 1198 const sal_Int32 nLen(rCandidate.getLength()); 1199 sal_Int32 nPos(0); 1200 1201 return readNumberAndUnit(rCandidate, nPos, aNum, nLen); 1202 } 1203 1204 bool readLocalUrl(const rtl::OUString& rCandidate, rtl::OUString& rURL) 1205 { 1206 static rtl::OUString aStrUrl(rtl::OUString::createFromAscii("url")); 1207 1208 if(rCandidate.match(aStrUrl, 0)) 1209 { 1210 const sal_Int32 nLen(rCandidate.getLength()); 1211 sal_Int32 nPos(aStrUrl.getLength()); 1212 1213 skip_char(rCandidate, sal_Unicode('('), sal_Unicode('#'), nPos, nLen); 1214 rtl::OUStringBuffer aTokenValue; 1215 copyToLimiter(rCandidate, sal_Unicode(')'), nPos, aTokenValue, nLen); 1216 rURL = aTokenValue.makeStringAndClear(); 1217 1218 return true; 1219 } 1220 1221 return false; 1222 } 1223 1224 bool readSvgPaint( 1225 const rtl::OUString& rCandidate, 1226 SvgPaint& rSvgPaint, 1227 rtl::OUString& rURL, 1228 bool bCaseIndependent) 1229 { 1230 const sal_Int32 nLen(rCandidate.getLength()); 1231 1232 if(nLen) 1233 { 1234 basegfx::BColor aColor; 1235 1236 if(read_color(rCandidate, aColor, bCaseIndependent)) 1237 { 1238 rSvgPaint = SvgPaint(aColor, true, true); 1239 return true; 1240 } 1241 else 1242 { 1243 static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none")); 1244 static rtl::OUString aStrCurrentColor(rtl::OUString::createFromAscii("currentColor")); 1245 1246 if(rCandidate.match(aStrNone, 0)) 1247 { 1248 rSvgPaint = SvgPaint(aColor, true, false, false); 1249 return true; 1250 } 1251 else if(readLocalUrl(rCandidate, rURL)) 1252 { 1253 /// Url is copied to rURL, but needs to be solved outside this helper 1254 return false; 1255 } 1256 else if(rCandidate.match(aStrCurrentColor, 0)) 1257 { 1258 rSvgPaint = SvgPaint(aColor, true, true, true); 1259 return true; 1260 } 1261 } 1262 } 1263 1264 return false; 1265 } 1266 1267 bool readSvgNumberVector(const rtl::OUString& rCandidate, SvgNumberVector& rSvgNumberVector) 1268 { 1269 const sal_Int32 nLen(rCandidate.getLength()); 1270 rSvgNumberVector.clear(); 1271 1272 if(nLen) 1273 { 1274 sal_Int32 nPos(0); 1275 SvgNumber aNum; 1276 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1277 1278 while(readNumberAndUnit(rCandidate, nPos, aNum, nLen)) 1279 { 1280 rSvgNumberVector.push_back(aNum); 1281 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1282 } 1283 1284 return !rSvgNumberVector.empty(); 1285 } 1286 1287 return false; 1288 } 1289 1290 SvgAspectRatio readSvgAspectRatio(const rtl::OUString& rCandidate) 1291 { 1292 const sal_Int32 nLen(rCandidate.getLength()); 1293 1294 if(nLen) 1295 { 1296 sal_Int32 nPos(0); 1297 SvgAlign aSvgAlign(Align_xMidYMid); 1298 bool bDefer(false); 1299 bool bMeetOrSlice(true); 1300 bool bChanged(false); 1301 1302 while(nPos < nLen) 1303 { 1304 const sal_Int32 nInitPos(nPos); 1305 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 1306 rtl::OUStringBuffer aTokenName; 1307 copyString(rCandidate, nPos, aTokenName, nLen); 1308 1309 if(aTokenName.getLength()) 1310 { 1311 switch(StrToSVGToken(aTokenName.makeStringAndClear(), false)) 1312 { 1313 case SVGTokenDefer: 1314 { 1315 bDefer = true; 1316 bChanged = true; 1317 break; 1318 } 1319 case SVGTokenNone: 1320 { 1321 aSvgAlign = Align_none; 1322 bChanged = true; 1323 break; 1324 } 1325 case SVGTokenXMinYMin: 1326 { 1327 aSvgAlign = Align_xMinYMin; 1328 bChanged = true; 1329 break; 1330 } 1331 case SVGTokenXMidYMin: 1332 { 1333 aSvgAlign = Align_xMidYMin; 1334 bChanged = true; 1335 break; 1336 } 1337 case SVGTokenXMaxYMin: 1338 { 1339 aSvgAlign = Align_xMaxYMin; 1340 bChanged = true; 1341 break; 1342 } 1343 case SVGTokenXMinYMid: 1344 { 1345 aSvgAlign = Align_xMinYMid; 1346 bChanged = true; 1347 break; 1348 } 1349 case SVGTokenXMidYMid: 1350 { 1351 aSvgAlign = Align_xMidYMid; 1352 bChanged = true; 1353 break; 1354 } 1355 case SVGTokenXMaxYMid: 1356 { 1357 aSvgAlign = Align_xMaxYMid; 1358 bChanged = true; 1359 break; 1360 } 1361 case SVGTokenXMinYMax: 1362 { 1363 aSvgAlign = Align_xMinYMax; 1364 bChanged = true; 1365 break; 1366 } 1367 case SVGTokenXMidYMax: 1368 { 1369 aSvgAlign = Align_xMidYMax; 1370 bChanged = true; 1371 break; 1372 } 1373 case SVGTokenXMaxYMax: 1374 { 1375 aSvgAlign = Align_xMaxYMax; 1376 bChanged = true; 1377 break; 1378 } 1379 case SVGTokenMeet: 1380 { 1381 bMeetOrSlice = true; 1382 bChanged = true; 1383 break; 1384 } 1385 case SVGTokenSlice: 1386 { 1387 bMeetOrSlice = false; 1388 bChanged = true; 1389 break; 1390 } 1391 default: 1392 { 1393 break; 1394 } 1395 } 1396 } 1397 1398 if(nInitPos == nPos) 1399 { 1400 OSL_ENSURE(false, "Could not interpret on current position (!)"); 1401 nPos++; 1402 } 1403 } 1404 1405 if(bChanged) 1406 { 1407 return SvgAspectRatio(aSvgAlign, bDefer, bMeetOrSlice); 1408 } 1409 } 1410 1411 return SvgAspectRatio(); 1412 } 1413 1414 bool readSvgStringVector(const rtl::OUString& rCandidate, SvgStringVector& rSvgStringVector) 1415 { 1416 rSvgStringVector.clear(); 1417 const sal_Int32 nLen(rCandidate.getLength()); 1418 1419 if(nLen) 1420 { 1421 sal_Int32 nPos(0); 1422 rtl::OUStringBuffer aTokenValue; 1423 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1424 1425 while(nPos < nLen) 1426 { 1427 copyToLimiter(rCandidate, sal_Unicode(','), nPos, aTokenValue, nLen); 1428 skip_char(rCandidate, sal_Unicode(','), sal_Unicode(' '), nPos, nLen); 1429 const rtl::OUString aString = aTokenValue.makeStringAndClear(); 1430 1431 if(aString.getLength()) 1432 { 1433 rSvgStringVector.push_back(aString); 1434 } 1435 } 1436 } 1437 1438 return !rSvgStringVector.empty(); 1439 } 1440 1441 void readImageLink(const rtl::OUString& rCandidate, rtl::OUString& rXLink, rtl::OUString& rUrl, rtl::OUString& rMimeType, rtl::OUString& rData) 1442 { 1443 rXLink = rUrl = rMimeType = rData = rtl::OUString(); 1444 1445 if(sal_Unicode('#') == rCandidate[0]) 1446 { 1447 // local link 1448 rXLink = rCandidate.copy(1); 1449 } 1450 else 1451 { 1452 static rtl::OUString aStrData(rtl::OUString::createFromAscii("data:")); 1453 1454 if(rCandidate.match(aStrData, 0)) 1455 { 1456 // embedded data 1457 sal_Int32 nPos(aStrData.getLength()); 1458 sal_Int32 nLen(rCandidate.getLength()); 1459 rtl::OUStringBuffer aBuffer; 1460 1461 // read mime type 1462 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 1463 copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aBuffer, nLen); 1464 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen); 1465 rMimeType = aBuffer.makeStringAndClear(); 1466 1467 if(rMimeType.getLength() && nPos < nLen) 1468 { 1469 static rtl::OUString aStrImage(rtl::OUString::createFromAscii("image")); 1470 1471 if(rMimeType.match(aStrImage, 0)) 1472 { 1473 // image data 1474 rtl::OUString aData(rCandidate.copy(nPos)); 1475 static rtl::OUString aStrBase64(rtl::OUString::createFromAscii("base64")); 1476 1477 if(aData.match(aStrBase64, 0)) 1478 { 1479 // base64 encoded 1480 nPos = aStrBase64.getLength(); 1481 nLen = aData.getLength(); 1482 1483 skip_char(aData, sal_Unicode(' '), sal_Unicode(','), nPos, nLen); 1484 1485 if(nPos < nLen) 1486 { 1487 rData = aData.copy(nPos); 1488 } 1489 } 1490 } 1491 } 1492 } 1493 else 1494 { 1495 // Url (path and filename) 1496 rUrl = rCandidate; 1497 } 1498 } 1499 } 1500 1501 rtl::OUString convert(const rtl::OUString& rCandidate, const sal_Unicode& rPattern, const sal_Unicode& rNew, bool bRemove) 1502 { 1503 const sal_Int32 nLen(rCandidate.getLength()); 1504 1505 if(nLen) 1506 { 1507 sal_Int32 nPos(0); 1508 rtl::OUStringBuffer aBuffer; 1509 bool bChanged(false); 1510 1511 while(nPos < nLen) 1512 { 1513 const sal_Unicode aChar(rCandidate[nPos]); 1514 1515 if(rPattern == aChar) 1516 { 1517 bChanged = true; 1518 1519 if(!bRemove) 1520 { 1521 aBuffer.append(rNew); 1522 } 1523 } 1524 else 1525 { 1526 aBuffer.append(aChar); 1527 } 1528 1529 nPos++; 1530 } 1531 1532 if(bChanged) 1533 { 1534 return aBuffer.makeStringAndClear(); 1535 } 1536 } 1537 1538 return rCandidate; 1539 } 1540 1541 rtl::OUString consolidateContiguosSpace(const rtl::OUString& rCandidate) 1542 { 1543 const sal_Int32 nLen(rCandidate.getLength()); 1544 1545 if(nLen) 1546 { 1547 sal_Int32 nPos(0); 1548 rtl::OUStringBuffer aBuffer; 1549 bool bInsideSpace(false); 1550 const sal_Unicode aSpace(' '); 1551 1552 while(nPos < nLen) 1553 { 1554 const sal_Unicode aChar(rCandidate[nPos]); 1555 1556 if(aSpace == aChar) 1557 { 1558 bInsideSpace = true; 1559 } 1560 else 1561 { 1562 if(bInsideSpace) 1563 { 1564 bInsideSpace = false; 1565 aBuffer.append(aSpace); 1566 } 1567 1568 aBuffer.append(aChar); 1569 } 1570 1571 nPos++; 1572 } 1573 1574 if(bInsideSpace) 1575 { 1576 aBuffer.append(aSpace); 1577 } 1578 1579 if(aBuffer.getLength() != nLen) 1580 { 1581 return aBuffer.makeStringAndClear(); 1582 } 1583 } 1584 1585 return rCandidate; 1586 } 1587 1588 rtl::OUString whiteSpaceHandlingDefault(const rtl::OUString& rCandidate) 1589 { 1590 const sal_Unicode aNewline('\n'); 1591 const sal_Unicode aTab('\t'); 1592 const sal_Unicode aSpace(' '); 1593 1594 // remove all newline characters 1595 rtl::OUString aRetval(convert(rCandidate, aNewline, aNewline, true)); 1596 1597 // convert tab to space 1598 aRetval = convert(aRetval, aTab, aSpace, false); 1599 1600 // strip of all leading and trailing spaces 1601 aRetval = aRetval.trim(); 1602 1603 // consolidate contiguos space 1604 aRetval = consolidateContiguosSpace(aRetval); 1605 1606 return aRetval; 1607 } 1608 1609 rtl::OUString whiteSpaceHandlingPreserve(const rtl::OUString& rCandidate) 1610 { 1611 const sal_Unicode aNewline('\n'); 1612 const sal_Unicode aTab('\t'); 1613 const sal_Unicode aSpace(' '); 1614 1615 // convert newline to space 1616 rtl::OUString aRetval(convert(rCandidate, aNewline, aSpace, false)); 1617 1618 // convert tab to space 1619 aRetval = convert(rCandidate, aTab, aSpace, false); 1620 1621 return rCandidate; 1622 } 1623 1624 ::std::vector< double > solveSvgNumberVector(const SvgNumberVector& rInput, const InfoProvider& rInfoProvider, NumberType aNumberType) 1625 { 1626 ::std::vector< double > aRetval; 1627 1628 if(!rInput.empty()) 1629 { 1630 const double nCount(rInput.size()); 1631 aRetval.reserve(nCount); 1632 1633 for(sal_uInt32 a(0); a < nCount; a++) 1634 { 1635 aRetval.push_back(rInput[a].solve(rInfoProvider, aNumberType)); 1636 } 1637 } 1638 1639 return aRetval; 1640 } 1641 1642 } // end of namespace svgreader 1643 } // end of namespace svgio 1644 1645 ////////////////////////////////////////////////////////////////////////////// 1646 // eof 1647