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