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