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