OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2002, 2003 The Karbon Developers | 2 * Copyright (C) 2002, 2003 The Karbon Developers |
3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> | 3 * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> |
4 * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org> | 4 * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org> |
5 * Copyright (C) 2007, 2009, 2013 Apple Inc. All rights reserved. | 5 * Copyright (C) 2007, 2009, 2013 Apple Inc. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
11 * | 11 * |
12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
16 * | 16 * |
17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
21 */ | 21 */ |
22 | 22 |
23 #include "config.h" | 23 #include "config.h" |
24 #include "core/svg/SVGParserUtilities.h" | 24 #include "core/svg/SVGParserUtilities.h" |
25 | 25 |
26 #include "core/dom/Document.h" | 26 #include "core/dom/Document.h" |
27 #include "core/svg/SVGPointList.h" | 27 #include "core/svg/SVGPointList.h" |
| 28 #include "core/svg/SVGTransformList.h" |
28 #include "platform/geometry/FloatRect.h" | 29 #include "platform/geometry/FloatRect.h" |
| 30 #include "platform/transforms/AffineTransform.h" |
29 #include "wtf/ASCIICType.h" | 31 #include "wtf/ASCIICType.h" |
30 #include <limits> | 32 #include <limits> |
31 | 33 |
32 namespace WebCore { | 34 namespace WebCore { |
33 | 35 |
34 template <typename FloatType> | 36 template <typename FloatType> |
35 static inline bool isValidRange(const FloatType& x) | 37 static inline bool isValidRange(const FloatType& x) |
36 { | 38 { |
37 static const FloatType max = std::numeric_limits<FloatType>::max(); | 39 static const FloatType max = std::numeric_limits<FloatType>::max(); |
38 return x >= -max && x <= max; | 40 return x >= -max && x <= max; |
(...skipping 513 matching lines...) Loading... |
552 return false; | 554 return false; |
553 point1 = FloatPoint(x1, y1); | 555 point1 = FloatPoint(x1, y1); |
554 point2 = FloatPoint(x2, y2); | 556 point2 = FloatPoint(x2, y2); |
555 point3 = FloatPoint(x3, y3); | 557 point3 = FloatPoint(x3, y3); |
556 return true; | 558 return true; |
557 } | 559 } |
558 | 560 |
559 template bool parseFloatPoint3(const LChar*& current, const LChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); | 561 template bool parseFloatPoint3(const LChar*& current, const LChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); |
560 template bool parseFloatPoint3(const UChar*& current, const UChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); | 562 template bool parseFloatPoint3(const UChar*& current, const UChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); |
561 | 563 |
562 } | 564 template<typename CharType> |
| 565 static int parseTransformParamList(const CharType*& ptr, const CharType* end, fl
oat* values, int required, int optional) |
| 566 { |
| 567 int optionalParams = 0, requiredParams = 0; |
| 568 |
| 569 if (!skipOptionalSVGSpaces(ptr, end) || *ptr != '(') |
| 570 return -1; |
| 571 |
| 572 ptr++; |
| 573 |
| 574 skipOptionalSVGSpaces(ptr, end); |
| 575 |
| 576 while (requiredParams < required) { |
| 577 if (ptr >= end || !parseNumber(ptr, end, values[requiredParams], false)) |
| 578 return -1; |
| 579 requiredParams++; |
| 580 if (requiredParams < required) |
| 581 skipOptionalSVGSpacesOrDelimiter(ptr, end); |
| 582 } |
| 583 if (!skipOptionalSVGSpaces(ptr, end)) |
| 584 return -1; |
| 585 |
| 586 bool delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end); |
| 587 |
| 588 if (ptr >= end) |
| 589 return -1; |
| 590 |
| 591 if (*ptr == ')') { // skip optionals |
| 592 ptr++; |
| 593 if (delimParsed) |
| 594 return -1; |
| 595 } else { |
| 596 while (optionalParams < optional) { |
| 597 if (ptr >= end || !parseNumber(ptr, end, values[requiredParams + opt
ionalParams], false)) |
| 598 return -1; |
| 599 optionalParams++; |
| 600 if (optionalParams < optional) |
| 601 skipOptionalSVGSpacesOrDelimiter(ptr, end); |
| 602 } |
| 603 |
| 604 if (!skipOptionalSVGSpaces(ptr, end)) |
| 605 return -1; |
| 606 |
| 607 delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end); |
| 608 |
| 609 if (ptr >= end || *ptr != ')' || delimParsed) |
| 610 return -1; |
| 611 ptr++; |
| 612 } |
| 613 |
| 614 return requiredParams + optionalParams; |
| 615 } |
| 616 |
| 617 // These should be kept in sync with enum SVGTransformType |
| 618 static const int requiredValuesForType[] = {0, 6, 1, 1, 1, 1, 1}; |
| 619 static const int optionalValuesForType[] = {0, 0, 1, 1, 2, 0, 0}; |
| 620 |
| 621 template<typename CharType> |
| 622 static bool parseTransformValueInternal(unsigned type, const CharType*& ptr, con
st CharType* end, SVGTransform& transform) |
| 623 { |
| 624 if (type == SVGTransform::SVG_TRANSFORM_UNKNOWN) |
| 625 return false; |
| 626 |
| 627 int valueCount = 0; |
| 628 float values[] = {0, 0, 0, 0, 0, 0}; |
| 629 if ((valueCount = parseTransformParamList(ptr, end, values, requiredValuesFo
rType[type], optionalValuesForType[type])) < 0) |
| 630 return false; |
| 631 |
| 632 switch (type) { |
| 633 case SVGTransform::SVG_TRANSFORM_SKEWX: |
| 634 transform.setSkewX(values[0]); |
| 635 break; |
| 636 case SVGTransform::SVG_TRANSFORM_SKEWY: |
| 637 transform.setSkewY(values[0]); |
| 638 break; |
| 639 case SVGTransform::SVG_TRANSFORM_SCALE: |
| 640 if (valueCount == 1) // Spec: if only one param given, assume uniform sc
aling |
| 641 transform.setScale(values[0], values[0]); |
| 642 else |
| 643 transform.setScale(values[0], values[1]); |
| 644 break; |
| 645 case SVGTransform::SVG_TRANSFORM_TRANSLATE: |
| 646 if (valueCount == 1) // Spec: if only one param given, assume 2nd param
to be 0 |
| 647 transform.setTranslate(values[0], 0); |
| 648 else |
| 649 transform.setTranslate(values[0], values[1]); |
| 650 break; |
| 651 case SVGTransform::SVG_TRANSFORM_ROTATE: |
| 652 if (valueCount == 1) |
| 653 transform.setRotate(values[0], 0, 0); |
| 654 else |
| 655 transform.setRotate(values[0], values[1], values[2]); |
| 656 break; |
| 657 case SVGTransform::SVG_TRANSFORM_MATRIX: |
| 658 transform.setMatrix(AffineTransform(values[0], values[1], values[2], val
ues[3], values[4], values[5])); |
| 659 break; |
| 660 } |
| 661 |
| 662 return true; |
| 663 } |
| 664 |
| 665 bool parseTransformValue(unsigned type, const LChar*& ptr, const LChar* end, SVG
Transform& transform) |
| 666 { |
| 667 return parseTransformValueInternal(type, ptr, end, transform); |
| 668 } |
| 669 |
| 670 bool parseTransformValue(unsigned type, const UChar*& ptr, const UChar* end, SVG
Transform& transform) |
| 671 { |
| 672 return parseTransformValueInternal(type, ptr, end, transform); |
| 673 } |
| 674 |
| 675 static const LChar skewXDesc[] = {'s', 'k', 'e', 'w', 'X'}; |
| 676 static const LChar skewYDesc[] = {'s', 'k', 'e', 'w', 'Y'}; |
| 677 static const LChar scaleDesc[] = {'s', 'c', 'a', 'l', 'e'}; |
| 678 static const LChar translateDesc[] = {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', '
e'}; |
| 679 static const LChar rotateDesc[] = {'r', 'o', 't', 'a', 't', 'e'}; |
| 680 static const LChar matrixDesc[] = {'m', 'a', 't', 'r', 'i', 'x'}; |
| 681 |
| 682 template<typename CharType> |
| 683 static inline bool parseAndSkipType(const CharType*& ptr, const CharType* end, u
nsigned short& type) |
| 684 { |
| 685 if (ptr >= end) |
| 686 return false; |
| 687 |
| 688 if (*ptr == 's') { |
| 689 if (skipString(ptr, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc))) |
| 690 type = SVGTransform::SVG_TRANSFORM_SKEWX; |
| 691 else if (skipString(ptr, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc))) |
| 692 type = SVGTransform::SVG_TRANSFORM_SKEWY; |
| 693 else if (skipString(ptr, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc))) |
| 694 type = SVGTransform::SVG_TRANSFORM_SCALE; |
| 695 else |
| 696 return false; |
| 697 } else if (skipString(ptr, end, translateDesc, WTF_ARRAY_LENGTH(translateDes
c))) |
| 698 type = SVGTransform::SVG_TRANSFORM_TRANSLATE; |
| 699 else if (skipString(ptr, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc))) |
| 700 type = SVGTransform::SVG_TRANSFORM_ROTATE; |
| 701 else if (skipString(ptr, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc))) |
| 702 type = SVGTransform::SVG_TRANSFORM_MATRIX; |
| 703 else |
| 704 return false; |
| 705 |
| 706 return true; |
| 707 } |
| 708 |
| 709 SVGTransform::SVGTransformType parseTransformType(const String& string) |
| 710 { |
| 711 if (string.isEmpty()) |
| 712 return SVGTransform::SVG_TRANSFORM_UNKNOWN; |
| 713 unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; |
| 714 if (string.is8Bit()) { |
| 715 const LChar* ptr = string.characters8(); |
| 716 const LChar* end = ptr + string.length(); |
| 717 parseAndSkipType(ptr, end, type); |
| 718 } else { |
| 719 const UChar* ptr = string.characters16(); |
| 720 const UChar* end = ptr + string.length(); |
| 721 parseAndSkipType(ptr, end, type); |
| 722 } |
| 723 return static_cast<SVGTransform::SVGTransformType>(type); |
| 724 } |
| 725 |
| 726 template<typename CharType> |
| 727 bool parseTransformAttributeInternal(SVGTransformList& list, const CharType*& pt
r, const CharType* end, TransformParsingMode mode) |
| 728 { |
| 729 if (mode == ClearList) |
| 730 list.clear(); |
| 731 |
| 732 bool delimParsed = false; |
| 733 while (ptr < end) { |
| 734 delimParsed = false; |
| 735 unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; |
| 736 skipOptionalSVGSpaces(ptr, end); |
| 737 |
| 738 if (!parseAndSkipType(ptr, end, type)) |
| 739 return false; |
| 740 |
| 741 SVGTransform transform; |
| 742 if (!parseTransformValue(type, ptr, end, transform)) |
| 743 return false; |
| 744 |
| 745 list.append(transform); |
| 746 skipOptionalSVGSpaces(ptr, end); |
| 747 if (ptr < end && *ptr == ',') { |
| 748 delimParsed = true; |
| 749 ++ptr; |
| 750 } |
| 751 skipOptionalSVGSpaces(ptr, end); |
| 752 } |
| 753 |
| 754 return !delimParsed; |
| 755 } |
| 756 |
| 757 bool parseTransformAttribute(SVGTransformList& list, const LChar*& ptr, const LC
har* end, TransformParsingMode mode) |
| 758 { |
| 759 return parseTransformAttributeInternal(list, ptr, end, mode); |
| 760 } |
| 761 |
| 762 bool parseTransformAttribute(SVGTransformList& list, const UChar*& ptr, const UC
har* end, TransformParsingMode mode) |
| 763 { |
| 764 return parseTransformAttributeInternal(list, ptr, end, mode); |
| 765 } |
| 766 |
| 767 } |
OLD | NEW |