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" | |
29 #include "platform/geometry/FloatRect.h" | 28 #include "platform/geometry/FloatRect.h" |
30 #include "platform/transforms/AffineTransform.h" | 29 #include "platform/transforms/AffineTransform.h" |
31 #include "wtf/ASCIICType.h" | 30 #include "wtf/ASCIICType.h" |
32 #include <limits> | 31 #include <limits> |
33 | 32 |
34 namespace WebCore { | 33 namespace WebCore { |
35 | 34 |
36 template <typename FloatType> | 35 template <typename FloatType> |
37 static inline bool isValidRange(const FloatType& x) | 36 static inline bool isValidRange(const FloatType& x) |
38 { | 37 { |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 return false; | 481 return false; |
483 point1 = FloatPoint(x1, y1); | 482 point1 = FloatPoint(x1, y1); |
484 point2 = FloatPoint(x2, y2); | 483 point2 = FloatPoint(x2, y2); |
485 point3 = FloatPoint(x3, y3); | 484 point3 = FloatPoint(x3, y3); |
486 return true; | 485 return true; |
487 } | 486 } |
488 | 487 |
489 template bool parseFloatPoint3(const LChar*& current, const LChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); | 488 template bool parseFloatPoint3(const LChar*& current, const LChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); |
490 template bool parseFloatPoint3(const UChar*& current, const UChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); | 489 template bool parseFloatPoint3(const UChar*& current, const UChar* end, FloatPoi
nt& point1, FloatPoint& point2, FloatPoint& point3); |
491 | 490 |
492 template<typename CharType> | |
493 static int parseTransformParamList(const CharType*& ptr, const CharType* end, fl
oat* values, int required, int optional) | |
494 { | |
495 int optionalParams = 0, requiredParams = 0; | |
496 | |
497 if (!skipOptionalSVGSpaces(ptr, end) || *ptr != '(') | |
498 return -1; | |
499 | |
500 ptr++; | |
501 | |
502 skipOptionalSVGSpaces(ptr, end); | |
503 | |
504 while (requiredParams < required) { | |
505 if (ptr >= end || !parseNumber(ptr, end, values[requiredParams], false)) | |
506 return -1; | |
507 requiredParams++; | |
508 if (requiredParams < required) | |
509 skipOptionalSVGSpacesOrDelimiter(ptr, end); | |
510 } | |
511 if (!skipOptionalSVGSpaces(ptr, end)) | |
512 return -1; | |
513 | |
514 bool delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end); | |
515 | |
516 if (ptr >= end) | |
517 return -1; | |
518 | |
519 if (*ptr == ')') { // skip optionals | |
520 ptr++; | |
521 if (delimParsed) | |
522 return -1; | |
523 } else { | |
524 while (optionalParams < optional) { | |
525 if (ptr >= end || !parseNumber(ptr, end, values[requiredParams + opt
ionalParams], false)) | |
526 return -1; | |
527 optionalParams++; | |
528 if (optionalParams < optional) | |
529 skipOptionalSVGSpacesOrDelimiter(ptr, end); | |
530 } | |
531 | |
532 if (!skipOptionalSVGSpaces(ptr, end)) | |
533 return -1; | |
534 | |
535 delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end); | |
536 | |
537 if (ptr >= end || *ptr != ')' || delimParsed) | |
538 return -1; | |
539 ptr++; | |
540 } | |
541 | |
542 return requiredParams + optionalParams; | |
543 } | |
544 | |
545 // These should be kept in sync with enum SVGTransformType | |
546 static const int requiredValuesForType[] = {0, 6, 1, 1, 1, 1, 1}; | |
547 static const int optionalValuesForType[] = {0, 0, 1, 1, 2, 0, 0}; | |
548 | |
549 template<typename CharType> | |
550 static bool parseTransformValueInternal(unsigned type, const CharType*& ptr, con
st CharType* end, SVGTransform& transform) | |
551 { | |
552 if (type == SVGTransform::SVG_TRANSFORM_UNKNOWN) | |
553 return false; | |
554 | |
555 int valueCount = 0; | |
556 float values[] = {0, 0, 0, 0, 0, 0}; | |
557 if ((valueCount = parseTransformParamList(ptr, end, values, requiredValuesFo
rType[type], optionalValuesForType[type])) < 0) | |
558 return false; | |
559 | |
560 switch (type) { | |
561 case SVGTransform::SVG_TRANSFORM_SKEWX: | |
562 transform.setSkewX(values[0]); | |
563 break; | |
564 case SVGTransform::SVG_TRANSFORM_SKEWY: | |
565 transform.setSkewY(values[0]); | |
566 break; | |
567 case SVGTransform::SVG_TRANSFORM_SCALE: | |
568 if (valueCount == 1) // Spec: if only one param given, assume uniform sc
aling | |
569 transform.setScale(values[0], values[0]); | |
570 else | |
571 transform.setScale(values[0], values[1]); | |
572 break; | |
573 case SVGTransform::SVG_TRANSFORM_TRANSLATE: | |
574 if (valueCount == 1) // Spec: if only one param given, assume 2nd param
to be 0 | |
575 transform.setTranslate(values[0], 0); | |
576 else | |
577 transform.setTranslate(values[0], values[1]); | |
578 break; | |
579 case SVGTransform::SVG_TRANSFORM_ROTATE: | |
580 if (valueCount == 1) | |
581 transform.setRotate(values[0], 0, 0); | |
582 else | |
583 transform.setRotate(values[0], values[1], values[2]); | |
584 break; | |
585 case SVGTransform::SVG_TRANSFORM_MATRIX: | |
586 transform.setMatrix(AffineTransform(values[0], values[1], values[2], val
ues[3], values[4], values[5])); | |
587 break; | |
588 } | |
589 | |
590 return true; | |
591 } | |
592 | |
593 bool parseTransformValue(unsigned type, const LChar*& ptr, const LChar* end, SVG
Transform& transform) | |
594 { | |
595 return parseTransformValueInternal(type, ptr, end, transform); | |
596 } | |
597 | |
598 bool parseTransformValue(unsigned type, const UChar*& ptr, const UChar* end, SVG
Transform& transform) | |
599 { | |
600 return parseTransformValueInternal(type, ptr, end, transform); | |
601 } | |
602 | |
603 static const LChar skewXDesc[] = {'s', 'k', 'e', 'w', 'X'}; | 491 static const LChar skewXDesc[] = {'s', 'k', 'e', 'w', 'X'}; |
604 static const LChar skewYDesc[] = {'s', 'k', 'e', 'w', 'Y'}; | 492 static const LChar skewYDesc[] = {'s', 'k', 'e', 'w', 'Y'}; |
605 static const LChar scaleDesc[] = {'s', 'c', 'a', 'l', 'e'}; | 493 static const LChar scaleDesc[] = {'s', 'c', 'a', 'l', 'e'}; |
606 static const LChar translateDesc[] = {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', '
e'}; | 494 static const LChar translateDesc[] = {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', '
e'}; |
607 static const LChar rotateDesc[] = {'r', 'o', 't', 'a', 't', 'e'}; | 495 static const LChar rotateDesc[] = {'r', 'o', 't', 'a', 't', 'e'}; |
608 static const LChar matrixDesc[] = {'m', 'a', 't', 'r', 'i', 'x'}; | 496 static const LChar matrixDesc[] = {'m', 'a', 't', 'r', 'i', 'x'}; |
609 | 497 |
610 template<typename CharType> | 498 template<typename CharType> |
611 static inline bool parseAndSkipType(const CharType*& ptr, const CharType* end, u
nsigned short& type) | 499 bool parseAndSkipTransformType(const CharType*& ptr, const CharType* end, SVGTra
nsformType& type) |
612 { | 500 { |
613 if (ptr >= end) | 501 if (ptr >= end) |
614 return false; | 502 return false; |
615 | 503 |
616 if (*ptr == 's') { | 504 if (*ptr == 's') { |
617 if (skipString(ptr, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc))) | 505 if (skipString(ptr, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc))) |
618 type = SVGTransform::SVG_TRANSFORM_SKEWX; | 506 type = SVG_TRANSFORM_SKEWX; |
619 else if (skipString(ptr, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc))) | 507 else if (skipString(ptr, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc))) |
620 type = SVGTransform::SVG_TRANSFORM_SKEWY; | 508 type = SVG_TRANSFORM_SKEWY; |
621 else if (skipString(ptr, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc))) | 509 else if (skipString(ptr, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc))) |
622 type = SVGTransform::SVG_TRANSFORM_SCALE; | 510 type = SVG_TRANSFORM_SCALE; |
623 else | 511 else |
624 return false; | 512 return false; |
625 } else if (skipString(ptr, end, translateDesc, WTF_ARRAY_LENGTH(translateDes
c))) | 513 } else if (skipString(ptr, end, translateDesc, WTF_ARRAY_LENGTH(translateDes
c))) |
626 type = SVGTransform::SVG_TRANSFORM_TRANSLATE; | 514 type = SVG_TRANSFORM_TRANSLATE; |
627 else if (skipString(ptr, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc))) | 515 else if (skipString(ptr, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc))) |
628 type = SVGTransform::SVG_TRANSFORM_ROTATE; | 516 type = SVG_TRANSFORM_ROTATE; |
629 else if (skipString(ptr, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc))) | 517 else if (skipString(ptr, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc))) |
630 type = SVGTransform::SVG_TRANSFORM_MATRIX; | 518 type = SVG_TRANSFORM_MATRIX; |
631 else | 519 else |
632 return false; | 520 return false; |
633 | 521 |
634 return true; | 522 return true; |
635 } | 523 } |
636 | 524 |
637 SVGTransform::SVGTransformType parseTransformType(const String& string) | 525 template bool parseAndSkipTransformType(const UChar*& current, const UChar* end,
SVGTransformType&); |
| 526 template bool parseAndSkipTransformType(const LChar*& current, const LChar* end,
SVGTransformType&); |
| 527 |
| 528 SVGTransformType parseTransformType(const String& string) |
638 { | 529 { |
639 if (string.isEmpty()) | 530 if (string.isEmpty()) |
640 return SVGTransform::SVG_TRANSFORM_UNKNOWN; | 531 return SVG_TRANSFORM_UNKNOWN; |
641 unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; | 532 SVGTransformType type = SVG_TRANSFORM_UNKNOWN; |
642 if (string.is8Bit()) { | 533 if (string.is8Bit()) { |
643 const LChar* ptr = string.characters8(); | 534 const LChar* ptr = string.characters8(); |
644 const LChar* end = ptr + string.length(); | 535 const LChar* end = ptr + string.length(); |
645 parseAndSkipType(ptr, end, type); | 536 parseAndSkipTransformType(ptr, end, type); |
646 } else { | 537 } else { |
647 const UChar* ptr = string.characters16(); | 538 const UChar* ptr = string.characters16(); |
648 const UChar* end = ptr + string.length(); | 539 const UChar* end = ptr + string.length(); |
649 parseAndSkipType(ptr, end, type); | 540 parseAndSkipTransformType(ptr, end, type); |
650 } | 541 } |
651 return static_cast<SVGTransform::SVGTransformType>(type); | 542 return type; |
652 } | |
653 | |
654 template<typename CharType> | |
655 bool parseTransformAttributeInternal(SVGTransformList& list, const CharType*& pt
r, const CharType* end, TransformParsingMode mode) | |
656 { | |
657 if (mode == ClearList) | |
658 list.clear(); | |
659 | |
660 bool delimParsed = false; | |
661 while (ptr < end) { | |
662 delimParsed = false; | |
663 unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; | |
664 skipOptionalSVGSpaces(ptr, end); | |
665 | |
666 if (!parseAndSkipType(ptr, end, type)) | |
667 return false; | |
668 | |
669 SVGTransform transform; | |
670 if (!parseTransformValue(type, ptr, end, transform)) | |
671 return false; | |
672 | |
673 list.append(transform); | |
674 skipOptionalSVGSpaces(ptr, end); | |
675 if (ptr < end && *ptr == ',') { | |
676 delimParsed = true; | |
677 ++ptr; | |
678 } | |
679 skipOptionalSVGSpaces(ptr, end); | |
680 } | |
681 | |
682 return !delimParsed; | |
683 } | |
684 | |
685 bool parseTransformAttribute(SVGTransformList& list, const LChar*& ptr, const LC
har* end, TransformParsingMode mode) | |
686 { | |
687 return parseTransformAttributeInternal(list, ptr, end, mode); | |
688 } | |
689 | |
690 bool parseTransformAttribute(SVGTransformList& list, const UChar*& ptr, const UC
har* end, TransformParsingMode mode) | |
691 { | |
692 return parseTransformAttributeInternal(list, ptr, end, mode); | |
693 } | 543 } |
694 | 544 |
695 } | 545 } |
OLD | NEW |