Changeset 263617 in webkit
- Timestamp:
- Jun 27, 2020 8:29:30 AM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 added
- 30 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r263601 r263617 1 2020-06-27 Sam Weinig <weinig@apple.com> 2 3 Convert SVG related parsers over to using StringParsingBuffer 4 https://bugs.webkit.org/show_bug.cgi?id=213635 5 6 Reviewed by Darin Adler. 7 8 - Adopt StringParsingBuffer across SVG code. 9 - Remove UTF-16 upconversions in SVGAnimationElement, SVGFitToViewBox, SVGLengthList, 10 SVGLengthValue, SVGNumberList, SVGParserUtilities, SVGPointList, SVGPreserveAspectRatioValue, 11 SVGStringList, SVGTransformList, SVGTransformable and SVGViewSpec. 12 13 * Headers.cmake: 14 * WebCore.xcodeproj/project.pbxproj: 15 Export ParsingUtilities.h, which is now included by SVGParserUtilities.h 16 17 * Sources.txt: 18 Add implementation files for SVGLengthList, SVGNumberList, SVGPointList, SVGStringList 19 and SVGTransformList to hold large functions are unlikely to benefit from inlining. 20 21 * html/parser/ParsingUtilities.h: 22 (WebCore::skipCharactersExactly): 23 Add new skipCharactersExactly, which takes a c-array (NOT null-terminated) of characters 24 to compare against. 25 26 * svg/SVGAngleValue.cpp: 27 (WebCore::parseAngleType): 28 (WebCore::SVGAngleValue::setValueAsString): 29 Adopt StringParsingBuffer. 30 31 * svg/SVGAnimateTransformElement.cpp: 32 (WebCore::SVGAnimateTransformElement::parseAttribute): 33 Adapt to new shared parseTransformType, which now returns an Optional and default to 34 SVG_TRANSFORM_UNKNOWN on parse failure as the old parseTransformType did. 35 36 * svg/SVGAnimationElement.cpp: 37 (WebCore::parseKeySplines): 38 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 39 StringView::upconvertedCharacters() 40 41 * svg/SVGFitToViewBox.cpp: 42 (WebCore::SVGFitToViewBox::parseViewBox): 43 (WebCore::SVGFitToViewBox::parseViewBoxGeneric): 44 * svg/SVGFitToViewBox.h: 45 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 46 StringView::upconvertedCharacters() 47 48 * svg/SVGLengthList.cpp: Added. 49 (WebCore::SVGLengthList::parse): 50 (WebCore::SVGLengthList::valueAsString const): 51 * svg/SVGLengthList.h: 52 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 53 StringView::upconvertedCharacters(). Move parse and valueAsString out of line. 54 55 * svg/SVGLengthValue.cpp: 56 (WebCore::parseLengthType): 57 (WebCore::SVGLengthValue::construct): 58 (WebCore::SVGLengthValue::setValueAsString): 59 * svg/SVGLengthValue.h: 60 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 61 StringView::upconvertedCharacters() 62 63 * svg/SVGNumberList.cpp: Added. 64 (WebCore::SVGNumberList::parse): 65 (WebCore::SVGNumberList::valueAsString const): 66 * svg/SVGNumberList.h: 67 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 68 StringView::upconvertedCharacters(). Move parse and valueAsString out of line. 69 70 * svg/SVGParserUtilities.cpp: 71 (WebCore::genericParseNumber): 72 (WebCore::parseNumber): 73 (WebCore::genericParseArcFlag): 74 (WebCore::parseArcFlag): 75 (WebCore::parseNumberOptionalNumber): 76 (WebCore::parsePoint): 77 (WebCore::parseRect): 78 (WebCore::parseGlyphName): 79 (WebCore::parseUnicodeRange): 80 (WebCore::parseKerningUnicodeString): 81 (WebCore::genericParseFloatPoint): 82 (WebCore::parseFloatPoint): 83 * svg/SVGParserUtilities.h: 84 (WebCore::isSVGSpaceOrComma): 85 (WebCore::skipOptionalSVGSpaces): 86 (WebCore::skipOptionalSVGSpacesOrDelimiter): 87 (WebCore::skipString): Deleted. 88 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 89 StringView::upconvertedCharacters(). Move parse and valueAsString out of line. 90 91 * svg/SVGPathSource.h: 92 Add missing include, which is now needed do to removing unncessary includes in other files. 93 94 * svg/SVGPathStringSource.cpp: 95 (WebCore::SVGPathStringSource::SVGPathStringSource): 96 (WebCore::SVGPathStringSource::hasMoreData const): 97 (WebCore::SVGPathStringSource::moveToNextToken): 98 (WebCore::nextCommandHelper): 99 (WebCore::SVGPathStringSource::nextCommand): 100 (WebCore::SVGPathStringSource::parse): 101 (WebCore::SVGPathStringSource::parseSVGSegmentType): 102 (WebCore::SVGPathStringSource::parseMoveToSegment): 103 (WebCore::SVGPathStringSource::parseLineToSegment): 104 (WebCore::SVGPathStringSource::parseLineToHorizontalSegment): 105 (WebCore::SVGPathStringSource::parseLineToVerticalSegment): 106 (WebCore::SVGPathStringSource::parseCurveToCubicSegment): 107 (WebCore::SVGPathStringSource::parseCurveToCubicSmoothSegment): 108 (WebCore::SVGPathStringSource::parseCurveToQuadraticSegment): 109 (WebCore::SVGPathStringSource::parseCurveToQuadraticSmoothSegment): 110 (WebCore::SVGPathStringSource::parseArcToSegment): 111 (WebCore::parseSVGSegmentTypeHelper): Deleted. 112 * svg/SVGPathStringSource.h: 113 Adopt StringParsingBuffer. Replace existing set of unions with a single 114 union of StringParsingBuffers. 115 116 * svg/SVGPointList.cpp: Added. 117 (WebCore::SVGPointList::parse): 118 (WebCore::SVGPointList::valueAsString const): 119 * svg/SVGPointList.h: 120 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 121 StringView::upconvertedCharacters(). Move parse and valueAsString out of line. 122 123 * svg/SVGPreserveAspectRatioValue.cpp: 124 (WebCore::SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue): 125 (WebCore::SVGPreserveAspectRatioValue::parse): 126 (WebCore::SVGPreserveAspectRatioValue::parseInternal): 127 (WebCore::SVGPreserveAspectRatioValue::valueAsString const): 128 * svg/SVGPreserveAspectRatioValue.h: 129 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 130 StringView::upconvertedCharacters(). 131 132 * svg/SVGStringList.cpp: Added. 133 (WebCore::SVGStringList::parse): 134 (WebCore::SVGStringList::valueAsString const): 135 * svg/SVGStringList.h: 136 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 137 StringView::upconvertedCharacters(). Move parse and valueAsString out of line. 138 139 * svg/SVGTransformList.cpp: Added. 140 (WebCore::SVGTransformList::consolidate): 141 (WebCore::SVGTransformList::concatenate const): 142 (WebCore::SVGTransformList::parseGeneric): 143 (WebCore::SVGTransformList::parse): 144 (WebCore::SVGTransformList::valueAsString const): 145 * svg/SVGTransformList.h: 146 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 147 StringView::upconvertedCharacters(). Move parse, valueAsString, consolidate and 148 concatenate out of line. 149 150 * svg/SVGTransformable.cpp: 151 (WebCore::parseTransformParamList): 152 (WebCore::parseTransformValueGeneric): 153 (WebCore::SVGTransformable::parseTransformValue): 154 (WebCore::parseTransformTypeGeneric): 155 (WebCore::SVGTransformable::parseTransformType): 156 (WebCore::SVGTransformable::parseAndSkipType): Deleted. 157 * svg/SVGTransformable.h: 158 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 159 StringView::upconvertedCharacters(). Unify parseTransformType implementations to all 160 use a single implementation and return an Optional<SVGTransformType>. 161 162 * svg/SVGViewSpec.cpp: 163 (WebCore::SVGViewSpec::parseViewSpec): 164 * svg/SVGViewSpec.h: 165 Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to 166 StringView::upconvertedCharacters(). 167 168 * svg/SVGZoomAndPan.cpp: 169 (WebCore::parseZoomAndPanGeneric): 170 (WebCore::SVGZoomAndPan::parseZoomAndPan): 171 * svg/SVGZoomAndPan.h: 172 Adopt StringParsingBuffer. 173 1 174 2020-06-26 Jer Noble <jer.noble@apple.com> 2 175 -
trunk/Source/WebCore/Headers.cmake
r263498 r263617 666 666 html/forms/FileIconLoader.h 667 667 668 html/parser/ParsingUtilities.h 668 669 html/parser/HTMLParserIdioms.h 669 670 -
trunk/Source/WebCore/Sources.txt
r263453 r263617 2541 2541 svg/SVGImageLoader.cpp 2542 2542 svg/SVGLengthContext.cpp 2543 svg/SVGLengthList.cpp 2543 2544 svg/SVGLengthValue.cpp 2544 2545 svg/SVGLineElement.cpp … … 2550 2551 svg/SVGMetadataElement.cpp 2551 2552 svg/SVGMissingGlyphElement.cpp 2553 svg/SVGNumberList.cpp 2552 2554 svg/SVGParserUtilities.cpp 2553 2555 svg/SVGPathBlender.cpp … … 2564 2566 svg/SVGPathUtilities.cpp 2565 2567 svg/SVGPatternElement.cpp 2568 svg/SVGPointList.cpp 2566 2569 svg/SVGPolyElement.cpp 2567 2570 svg/SVGPolygonElement.cpp … … 2574 2577 svg/SVGSetElement.cpp 2575 2578 svg/SVGStopElement.cpp 2579 svg/SVGStringList.cpp 2576 2580 svg/SVGStyleElement.cpp 2577 2581 svg/SVGSwitchElement.cpp … … 2587 2591 svg/SVGToOTFFontConversion.cpp 2588 2592 svg/SVGTransformDistance.cpp 2593 svg/SVGTransformList.cpp 2589 2594 svg/SVGTransformable.cpp 2590 2595 svg/SVGURIReference.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r263498 r263617 1591 1591 5351D4B11DF916B4008010CD /* FileHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 5351D4AF1DF916AC008010CD /* FileHandle.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1592 1592 536D5A20193E18E900CE4CAB /* HTMLSrcsetParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 536D5A1F193E18E900CE4CAB /* HTMLSrcsetParser.h */; }; 1593 536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 536D5A22193E8E0C00CE4CAB /* ParsingUtilities.h */; };1593 536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 536D5A22193E8E0C00CE4CAB /* ParsingUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1594 1594 538EC8021F96AF81004D22A8 /* UnifiedSource1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 538EC7FA1F96AA70004D22A8 /* UnifiedSource1.cpp */; }; 1595 1595 538EC8031F96AF81004D22A8 /* UnifiedSource1-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 538EC7F31F96AA5B004D22A8 /* UnifiedSource1-mm.mm */; }; … … 10197 10197 7CD494CA1A86EB1D000A87EC /* RenderAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderAttachment.cpp; sourceTree = "<group>"; }; 10198 10198 7CD494CB1A86EB1D000A87EC /* RenderAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderAttachment.h; sourceTree = "<group>"; }; 10199 7CD70C3D24A28A3A00E61040 /* SVGLengthList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGLengthList.cpp; sourceTree = "<group>"; }; 10200 7CD70C4024A28AC900E61040 /* SVGNumberList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGNumberList.cpp; sourceTree = "<group>"; }; 10201 7CD70C4224A28B7000E61040 /* SVGPointList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPointList.cpp; sourceTree = "<group>"; }; 10202 7CD70C4324A28BEC00E61040 /* SVGStringList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGStringList.cpp; sourceTree = "<group>"; }; 10203 7CD70C4624A28CD700E61040 /* SVGTransformList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGTransformList.cpp; sourceTree = "<group>"; }; 10199 10204 7CDE73961F9BD59500390312 /* Settings.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Settings.yaml; sourceTree = "<group>"; }; 10200 10205 7CDE8EBC1F193BC500168FE7 /* CSSStyleDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSStyleDeclaration.cpp; sourceTree = "<group>"; }; … … 25146 25151 7134496B146941B300720312 /* SVGLengthContext.cpp */, 25147 25152 7134496C146941B300720312 /* SVGLengthContext.h */, 25153 7CD70C3D24A28A3A00E61040 /* SVGLengthList.cpp */, 25148 25154 B22278A00D00BF200071B782 /* SVGLengthList.h */, 25149 25155 B22278A10D00BF200071B782 /* SVGLengthList.idl */, … … 25178 25184 7CE58D4F1DD69A1E00128552 /* SVGNumber.h */, 25179 25185 B22278B90D00BF200071B782 /* SVGNumber.idl */, 25186 7CD70C4024A28AC900E61040 /* SVGNumberList.cpp */, 25180 25187 B22278BB0D00BF200071B782 /* SVGNumberList.h */, 25181 25188 B22278BC0D00BF200071B782 /* SVGNumberList.idl */, … … 25241 25248 7CE58D491DD64A5B00128552 /* SVGPoint.h */, 25242 25249 B22278F40D00BF210071B782 /* SVGPoint.idl */, 25250 7CD70C4224A28B7000E61040 /* SVGPointList.cpp */, 25243 25251 B22278F60D00BF210071B782 /* SVGPointList.h */, 25244 25252 B22278F70D00BF210071B782 /* SVGPointList.idl */, … … 25274 25282 B22279130D00BF210071B782 /* SVGStopElement.h */, 25275 25283 B22279140D00BF210071B782 /* SVGStopElement.idl */, 25284 7CD70C4324A28BEC00E61040 /* SVGStringList.cpp */, 25276 25285 B22279160D00BF210071B782 /* SVGStringList.h */, 25277 25286 B22279170D00BF210071B782 /* SVGStringList.idl */, … … 25315 25324 B22279460D00BF210071B782 /* SVGTransformDistance.cpp */, 25316 25325 B22279470D00BF210071B782 /* SVGTransformDistance.h */, 25326 7CD70C4624A28CD700E61040 /* SVGTransformList.cpp */, 25317 25327 B22279490D00BF210071B782 /* SVGTransformList.h */, 25318 25328 B222794A0D00BF210071B782 /* SVGTransformList.idl */, -
trunk/Source/WebCore/html/parser/ParsingUtilities.h
r263581 r263617 143 143 } 144 144 145 template<typename CharacterType, unsigned characterCount> constexpr bool skipCharactersExactly(const CharacterType*& ptr, const CharacterType* end, const CharacterType(&str)[characterCount]) 146 { 147 if (end - ptr < characterCount) 148 return false; 149 if (memcmp(str, ptr, sizeof(CharacterType) * characterCount)) 150 return false; 151 ptr += characterCount; 152 return true; 153 } 154 155 template<typename CharacterType, unsigned characterCount> constexpr bool skipCharactersExactly(StringParsingBuffer<CharacterType>& buffer, const CharacterType(&str)[characterCount]) 156 { 157 if (buffer.lengthRemaining() < characterCount) 158 return false; 159 if (memcmp(str, buffer.position(), sizeof(CharacterType) * characterCount)) 160 return false; 161 buffer += characterCount; 162 return true; 163 } 164 145 165 } // namespace WebCore -
trunk/Source/WebCore/svg/SVGAngleValue.cpp
r263334 r263617 26 26 #include <wtf/MathExtras.h> 27 27 #include <wtf/text/StringConcatenateNumbers.h> 28 #include <wtf/text/StringParsingBuffer.h> 28 29 29 30 namespace WebCore { … … 81 82 } 82 83 83 template<typename CharacterType> static inline SVGAngleValue::Type parseAngleType( const CharacterType* ptr, const CharacterType* end)84 { 85 switch ( end - ptr) {84 template<typename CharacterType> static inline SVGAngleValue::Type parseAngleType(StringParsingBuffer<CharacterType> buffer) 85 { 86 switch (buffer.lengthRemaining()) { 86 87 case 0: 87 88 return SVGAngleValue::SVG_ANGLETYPE_UNSPECIFIED; 88 89 case 3: 89 if ( ptr[0] == 'd' && ptr[1] == 'e' && ptr[2] == 'g')90 if (buffer[0] == 'd' && buffer[1] == 'e' && buffer[2] == 'g') 90 91 return SVGAngleValue::SVG_ANGLETYPE_DEG; 91 if ( ptr[0] == 'r' && ptr[1] == 'a' && ptr[2] == 'd')92 if (buffer[0] == 'r' && buffer[1] == 'a' && buffer[2] == 'd') 92 93 return SVGAngleValue::SVG_ANGLETYPE_RAD; 93 94 break; 94 95 case 4: 95 if ( ptr[0] == 'g' && ptr[1] == 'r' && ptr[2] == 'a' && ptr[3] == 'd')96 if (buffer[0] == 'g' && buffer[1] == 'r' && buffer[2] == 'a' && buffer[3] == 'd') 96 97 return SVGAngleValue::SVG_ANGLETYPE_GRAD; 97 98 break; … … 107 108 } 108 109 109 auto helper = [&](auto* ptr, auto* end) -> ExceptionOr<void> {110 auto valueInSpecifiedUnits = parseNumber( ptr, end, SuffixSkippingPolicy::DontSkip);110 return readCharactersForParsing(value, [&](auto buffer) -> ExceptionOr<void> { 111 auto valueInSpecifiedUnits = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 111 112 if (!valueInSpecifiedUnits) 112 113 return Exception { SyntaxError }; 113 114 114 auto unitType = parseAngleType( ptr, end);115 auto unitType = parseAngleType(buffer); 115 116 if (unitType == SVGAngleValue::SVG_ANGLETYPE_UNKNOWN) 116 117 return Exception { SyntaxError }; … … 119 120 m_valueInSpecifiedUnits = *valueInSpecifiedUnits; 120 121 return { }; 121 }; 122 123 if (value.is8Bit()) { 124 auto* ptr = value.characters8(); 125 return helper(ptr, ptr + value.length()); 126 } 127 128 auto* ptr = value.characters16(); 129 return helper(ptr, ptr + value.length()); 122 }); 130 123 } 131 124 -
trunk/Source/WebCore/svg/SVGAnimateTransformElement.cpp
r246490 r263617 58 58 { 59 59 if (name == SVGNames::typeAttr) { 60 m_type = SVGTransformable::parseTransformType(value) ;60 m_type = SVGTransformable::parseTransformType(value).valueOr(SVGTransformValue::SVG_TRANSFORM_UNKNOWN); 61 61 if (m_type == SVGTransformValue::SVG_TRANSFORM_MATRIX) 62 62 m_type = SVGTransformValue::SVG_TRANSFORM_UNKNOWN; -
trunk/Source/WebCore/svg/SVGAnimationElement.cpp
r263334 r263617 42 42 #include <wtf/MathExtras.h> 43 43 #include <wtf/NeverDestroyed.h> 44 #include <wtf/text/StringParsingBuffer.h> 44 45 #include <wtf/text/StringView.h> 45 46 … … 78 79 } 79 80 80 static Optional<Vector<UnitBezier>> parseKeySplines( const StringView& parse)81 { 82 if ( parse.isEmpty())81 static Optional<Vector<UnitBezier>> parseKeySplines(StringView string) 82 { 83 if (string.isEmpty()) 83 84 return WTF::nullopt; 84 85 85 auto upconvertedCharacters = parse.upconvertedCharacters(); 86 const UChar* cur = upconvertedCharacters; 87 const UChar* end = cur + parse.length(); 88 89 skipOptionalSVGSpaces(cur, end); 90 91 Vector<UnitBezier> result; 92 93 bool delimParsed = false; 94 while (cur < end) { 95 delimParsed = false; 96 auto posA = parseNumber(cur, end); 97 if (!posA) 86 return readCharactersForParsing(string, [&](auto buffer) -> Optional<Vector<UnitBezier>> { 87 skipOptionalSVGSpaces(buffer); 88 89 Vector<UnitBezier> result; 90 91 bool delimParsed = false; 92 while (buffer.hasCharactersRemaining()) { 93 delimParsed = false; 94 auto posA = parseNumber(buffer); 95 if (!posA) 96 return WTF::nullopt; 97 98 auto posB = parseNumber(buffer); 99 if (!posB) 100 return WTF::nullopt; 101 102 auto posC = parseNumber(buffer); 103 if (!posC) 104 return WTF::nullopt; 105 106 auto posD = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 107 if (!posD) 108 return WTF::nullopt; 109 110 skipOptionalSVGSpaces(buffer); 111 112 if (skipExactly(buffer, ';')) 113 delimParsed = true; 114 115 skipOptionalSVGSpaces(buffer); 116 117 result.append(UnitBezier { *posA, *posB, *posC, *posD }); 118 } 119 120 if (!(buffer.atEnd() && !delimParsed)) 98 121 return WTF::nullopt; 99 122 100 auto posB = parseNumber(cur, end); 101 if (!posB) 102 return WTF::nullopt; 103 104 auto posC = parseNumber(cur, end); 105 if (!posC) 106 return WTF::nullopt; 107 108 auto posD = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip); 109 if (!posD) 110 return WTF::nullopt; 111 112 skipOptionalSVGSpaces(cur, end); 113 114 if (cur < end && *cur == ';') { 115 delimParsed = true; 116 cur++; 117 } 118 119 skipOptionalSVGSpaces(cur, end); 120 121 result.append(UnitBezier { *posA, *posB, *posC, *posD }); 122 } 123 124 if (!(cur == end && !delimParsed)) 125 return WTF::nullopt; 126 127 return result; 123 return result; 124 }); 128 125 } 129 126 -
trunk/Source/WebCore/svg/SVGFitToViewBox.cpp
r263334 r263617 31 31 #include "SVGParserUtilities.h" 32 32 #include "SVGPreserveAspectRatioValue.h" 33 #include <wtf/text/StringParsingBuffer.h> 33 34 #include <wtf/text/StringView.h> 34 35 … … 85 86 } 86 87 87 Optional<FloatRect> SVGFitToViewBox::parseViewBox( const StringView&value)88 Optional<FloatRect> SVGFitToViewBox::parseViewBox(StringView value) 88 89 { 89 auto upconvertedCharacters = value.upconvertedCharacters();90 const UChar* characters = upconvertedCharacters;91 return parseViewBox(characters, characters + value.length());90 return readCharactersForParsing(value, [&](auto buffer) { 91 return parseViewBoxGeneric(buffer); 92 }); 92 93 } 93 94 94 Optional<FloatRect> SVGFitToViewBox::parseViewBox( const UChar*& c, const UChar* end, bool validate)95 Optional<FloatRect> SVGFitToViewBox::parseViewBox(StringParsingBuffer<LChar>& buffer, bool validate) 95 96 { 96 StringView str(c, end - c); 97 return parseViewBoxGeneric(buffer, validate); 98 } 97 99 98 skipOptionalSVGSpaces(c, end); 100 Optional<FloatRect> SVGFitToViewBox::parseViewBox(StringParsingBuffer<UChar>& buffer, bool validate) 101 { 102 return parseViewBoxGeneric(buffer, validate); 103 } 99 104 100 auto x = parseNumber(c, end); 101 auto y = parseNumber(c, end); 102 auto width = parseNumber(c, end); 103 auto height = parseNumber(c, end, SuffixSkippingPolicy::DontSkip); 105 template<typename CharacterType> Optional<FloatRect> SVGFitToViewBox::parseViewBoxGeneric(StringParsingBuffer<CharacterType>& buffer, bool validate) 106 { 107 StringView stringToParse = buffer.stringViewOfCharactersRemaining(); 108 109 skipOptionalSVGSpaces(buffer); 110 111 auto x = parseNumber(buffer); 112 auto y = parseNumber(buffer); 113 auto width = parseNumber(buffer); 114 auto height = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 104 115 105 116 if (validate) { … … 107 118 108 119 if (!x || !y || !width || !height) { 109 document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", str , "\""));120 document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", stringToParse, "\"")); 110 121 return WTF::nullopt; 111 122 } … … 124 135 125 136 // Nothing should come after the last, fourth number. 126 skipOptionalSVGSpaces( c, end);127 if ( c < end) {128 document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", str , "\""));137 skipOptionalSVGSpaces(buffer); 138 if (buffer.hasCharactersRemaining()) { 139 document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", stringToParse, "\"")); 129 140 return WTF::nullopt; 130 141 } -
trunk/Source/WebCore/svg/SVGFitToViewBox.h
r263334 r263617 66 66 void reset(); 67 67 bool parseAttribute(const QualifiedName&, const AtomString&); 68 Optional<FloatRect> parseViewBox(const StringView& value); 69 Optional<FloatRect> parseViewBox(const UChar*& start, const UChar* end, bool validate = true); 68 Optional<FloatRect> parseViewBox(StringView); 69 Optional<FloatRect> parseViewBox(StringParsingBuffer<LChar>&, bool validate = true); 70 Optional<FloatRect> parseViewBox(StringParsingBuffer<UChar>&, bool validate = true); 70 71 71 72 private: 73 template<typename CharacterType> Optional<FloatRect> parseViewBoxGeneric(StringParsingBuffer<CharacterType>&, bool validate = true); 74 72 75 Ref<SVGAnimatedRect> m_viewBox; 73 76 Ref<SVGAnimatedPreserveAspectRatio> m_preserveAspectRatio; -
trunk/Source/WebCore/svg/SVGLengthList.h
r254514 r263617 28 28 #include "SVGLength.h" 29 29 #include "SVGValuePropertyList.h" 30 #include <wtf/text/StringBuilder.h>31 30 32 31 namespace WebCore { 33 32 34 class SVGLengthList : public SVGValuePropertyList<SVGLength> {33 class SVGLengthList final : public SVGValuePropertyList<SVGLength> { 35 34 using Base = SVGValuePropertyList<SVGLength>; 36 35 using Base::Base; … … 54 53 SVGLengthMode lengthMode() const { return m_lengthMode; } 55 54 56 bool parse(const String& value) 57 { 58 clearItems(); 55 bool parse(StringView); 59 56 60 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 61 const UChar* ptr = upconvertedCharacters; 62 const UChar* end = ptr + value.length(); 63 while (ptr < end) { 64 const UChar* start = ptr; 65 while (ptr < end && *ptr != ',' && !isSVGSpace(*ptr)) 66 ptr++; 67 if (ptr == start) 68 break; 69 70 String valueString(start, ptr - start); 71 SVGLengthValue value(m_lengthMode); 72 if (value.setValueAsString(valueString).hasException()) 73 break; 74 75 append(SVGLength::create(value)); 76 skipOptionalSVGSpacesOrDelimiter(ptr, end); 77 } 78 79 return ptr == end; 80 } 81 82 String valueAsString() const override 83 { 84 StringBuilder builder; 85 86 for (const auto& length : m_items) { 87 if (builder.length()) 88 builder.append(' '); 89 90 builder.append(length->value().valueAsString()); 91 } 92 93 return builder.toString(); 94 } 57 String valueAsString() const override; 95 58 96 59 private: -
trunk/Source/WebCore/svg/SVGLengthValue.cpp
r263334 r263617 28 28 #include "SVGParserUtilities.h" 29 29 #include <wtf/text/StringConcatenateNumbers.h> 30 #include <wtf/text/StringParsingBuffer.h> 30 31 #include <wtf/text/TextStream.h> 31 32 … … 62 63 } 63 64 64 static inline SVGLengthType parseLengthType(const UChar* ptr, const UChar* end)65 { 66 if ( ptr == end)65 template<typename CharacterType> static inline SVGLengthType parseLengthType(StringParsingBuffer<CharacterType>& buffer) 66 { 67 if (buffer.atEnd()) 67 68 return SVGLengthType::Number; 68 69 69 const UChar firstChar = *ptr;70 71 if ( ++ptr == end)70 auto firstChar = *buffer++; 71 72 if (buffer.atEnd()) 72 73 return firstChar == '%' ? SVGLengthType::Percentage : SVGLengthType::Unknown; 73 74 74 const UChar secondChar = *ptr;75 76 if ( ++ptr != end)75 auto secondChar = *buffer++; 76 77 if (!buffer.atEnd()) 77 78 return SVGLengthType::Unknown; 78 79 … … 181 182 } 182 183 183 SVGLengthValue SVGLengthValue::construct(SVGLengthMode lengthMode, const String& valueAsString, SVGParsingError& parseError, SVGLengthNegativeValuesMode negativeValuesMode) 184 Optional<SVGLengthValue> SVGLengthValue::construct(SVGLengthMode lengthMode, StringView valueAsString) 185 { 186 SVGLengthValue length { lengthMode }; 187 if (length.setValueAsString(valueAsString).hasException()) 188 return WTF::nullopt; 189 return length; 190 } 191 192 SVGLengthValue SVGLengthValue::construct(SVGLengthMode lengthMode, StringView valueAsString, SVGParsingError& parseError, SVGLengthNegativeValuesMode negativeValuesMode) 184 193 { 185 194 SVGLengthValue length(lengthMode); … … 240 249 } 241 250 242 ExceptionOr<void> SVGLengthValue::setValueAsString( const String&valueAsString, SVGLengthMode lengthMode)251 ExceptionOr<void> SVGLengthValue::setValueAsString(StringView valueAsString, SVGLengthMode lengthMode) 243 252 { 244 253 m_valueInSpecifiedUnits = 0; … … 287 296 } 288 297 289 ExceptionOr<void> SVGLengthValue::setValueAsString( const String&string)298 ExceptionOr<void> SVGLengthValue::setValueAsString(StringView string) 290 299 { 291 300 if (string.isEmpty()) 292 301 return { }; 293 302 294 auto upconvertedCharacters = StringView(string).upconvertedCharacters(); 295 const UChar* ptr = upconvertedCharacters; 296 const UChar* end = ptr + string.length(); 297 298 auto convertedNumber = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip); 299 if (!convertedNumber) 300 return Exception { SyntaxError }; 301 302 auto lengthType = parseLengthType(ptr, end); 303 if (lengthType == SVGLengthType::Unknown) 304 return Exception { SyntaxError }; 305 306 m_lengthType = lengthType; 307 m_valueInSpecifiedUnits = *convertedNumber; 308 return { }; 303 return readCharactersForParsing(string, [&](auto buffer) -> ExceptionOr<void> { 304 auto convertedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 305 if (!convertedNumber) 306 return Exception { SyntaxError }; 307 308 auto lengthType = parseLengthType(buffer); 309 if (lengthType == SVGLengthType::Unknown) 310 return Exception { SyntaxError }; 311 312 m_lengthType = lengthType; 313 m_valueInSpecifiedUnits = *convertedNumber; 314 return { }; 315 }); 309 316 } 310 317 -
trunk/Source/WebCore/svg/SVGLengthValue.h
r249822 r263617 59 59 WTF_MAKE_FAST_ALLOCATED; 60 60 public: 61 SVGLengthValue(SVGLengthMode = SVGLengthMode::Other, const String& valueAsString = String());61 SVGLengthValue(SVGLengthMode = SVGLengthMode::Other, const String& valueAsString = { }); 62 62 SVGLengthValue(float valueInSpecifiedUnits, SVGLengthType, SVGLengthMode = SVGLengthMode::Other); 63 63 SVGLengthValue(const SVGLengthContext&, float, SVGLengthType = SVGLengthType::Number, SVGLengthMode = SVGLengthMode::Other); 64 64 65 static SVGLengthValue construct(SVGLengthMode, const String&, SVGParsingError&, SVGLengthNegativeValuesMode = SVGLengthNegativeValuesMode::Allow); 65 static Optional<SVGLengthValue> construct(SVGLengthMode, StringView); 66 static SVGLengthValue construct(SVGLengthMode, StringView, SVGParsingError&, SVGLengthNegativeValuesMode = SVGLengthNegativeValuesMode::Allow); 66 67 static SVGLengthValue blend(const SVGLengthValue& from, const SVGLengthValue& to, float progress); 67 68 68 69 static SVGLengthValue fromCSSPrimitiveValue(const CSSPrimitiveValue&); 69 70 static Ref<CSSPrimitiveValue> toCSSPrimitiveValue(const SVGLengthValue&); … … 86 87 ExceptionOr<void> setValue(const SVGLengthContext&, float, SVGLengthType, SVGLengthMode); 87 88 88 ExceptionOr<void> setValueAsString( const String&);89 ExceptionOr<void> setValueAsString( const String&, SVGLengthMode);89 ExceptionOr<void> setValueAsString(StringView); 90 ExceptionOr<void> setValueAsString(StringView, SVGLengthMode); 90 91 91 92 ExceptionOr<void> convertToSpecifiedUnits(const SVGLengthContext&, SVGLengthType); -
trunk/Source/WebCore/svg/SVGNumberList.cpp
r263616 r263617 1 1 /* 2 * Copyright (C) 20 16-2019Apple Inc. All rights reserved.2 * Copyright (C) 2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #pragma once 26 #include "config.h" 27 #include "SVGNumberList.h" 27 28 28 #include "SVGNumber.h"29 #include "SVGValuePropertyList.h"29 #include <wtf/text/StringBuilder.h> 30 #include <wtf/text/StringParsingBuffer.h> 30 31 31 32 namespace WebCore { 32 33 33 class SVGNumberList : public SVGValuePropertyList<SVGNumber> { 34 using Base = SVGValuePropertyList<SVGNumber>; 35 using Base::Base;34 bool SVGNumberList::parse(StringView value) 35 { 36 clearItems(); 36 37 37 public: 38 static Ref<SVGNumberList> create() 39 { 40 return adoptRef(*new SVGNumberList()); 41 } 42 43 static Ref<SVGNumberList> create(SVGPropertyOwner* owner, SVGPropertyAccess access) 44 { 45 return adoptRef(*new SVGNumberList(owner, access)); 46 } 47 48 static Ref<SVGNumberList> create(const SVGNumberList& other, SVGPropertyAccess access) 49 { 50 return adoptRef(*new SVGNumberList(other, access)); 51 } 52 53 bool parse(const String& value) 54 { 55 clearItems(); 56 57 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 58 const UChar* ptr = upconvertedCharacters; 59 const UChar* end = ptr + value.length(); 60 38 return readCharactersForParsing(value, [&](auto buffer) { 61 39 // The spec (section 4.1) strangely doesn't allow leading whitespace. 62 40 // We might choose to violate that intentionally. 63 while ( ptr < end) {64 auto number = parseNumber( ptr, end);41 while (buffer.hasCharactersRemaining()) { 42 auto number = parseNumber(buffer); 65 43 if (!number) 66 44 break; … … 68 46 } 69 47 70 return ptr == end; 48 // FIXME: Should this clearItems() on failure like SVGTransformList does? 49 50 return buffer.atEnd(); 51 }); 52 } 53 54 String SVGNumberList::valueAsString() const 55 { 56 StringBuilder builder; 57 58 for (const auto& number : m_items) { 59 if (builder.length()) 60 builder.append(' '); 61 62 builder.append(number->value()); 71 63 } 72 64 73 String valueAsString() const override 74 { 75 StringBuilder builder; 65 return builder.toString(); 66 } 76 67 77 for (const auto& number : m_items) { 78 if (builder.length()) 79 builder.append(' '); 68 } 80 69 81 builder.append(number->value());82 }83 84 return builder.toString();85 }86 };87 88 } // namespace WebCore -
trunk/Source/WebCore/svg/SVGNumberList.h
r263334 r263617 31 31 namespace WebCore { 32 32 33 class SVGNumberList : public SVGValuePropertyList<SVGNumber> {33 class SVGNumberList final : public SVGValuePropertyList<SVGNumber> { 34 34 using Base = SVGValuePropertyList<SVGNumber>; 35 35 using Base::Base; … … 51 51 } 52 52 53 bool parse(const String& value) 54 { 55 clearItems(); 56 57 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 58 const UChar* ptr = upconvertedCharacters; 59 const UChar* end = ptr + value.length(); 60 61 // The spec (section 4.1) strangely doesn't allow leading whitespace. 62 // We might choose to violate that intentionally. 63 while (ptr < end) { 64 auto number = parseNumber(ptr, end); 65 if (!number) 66 break; 67 append(SVGNumber::create(*number)); 68 } 69 70 return ptr == end; 71 } 72 73 String valueAsString() const override 74 { 75 StringBuilder builder; 76 77 for (const auto& number : m_items) { 78 if (builder.length()) 79 builder.append(' '); 80 81 builder.append(number->value()); 82 } 83 84 return builder.toString(); 85 } 53 bool parse(StringView); 54 String valueAsString() const override; 86 55 }; 87 56 -
trunk/Source/WebCore/svg/SVGParserUtilities.cpp
r263334 r263617 28 28 #include <limits> 29 29 #include <wtf/ASCIICType.h> 30 #include <wtf/text/StringParsingBuffer.h> 30 31 #include <wtf/text/StringView.h> 31 32 … … 42 43 // complexity. 43 44 // FIXME: Can this be shared/replaced with number parsing in WTF? 44 template <typename CharacterType, typename FloatType = float> static Optional<FloatType> genericParseNumber( const CharacterType*& ptr, const CharacterType* end, SuffixSkippingPolicy skip = SuffixSkippingPolicy::Skip)45 template <typename CharacterType, typename FloatType = float> static Optional<FloatType> genericParseNumber(StringParsingBuffer<CharacterType>& buffer, SuffixSkippingPolicy skip = SuffixSkippingPolicy::Skip) 45 46 { 46 47 FloatType number = 0; … … 51 52 int sign = 1; 52 53 int expsign = 1; 53 const CharacterType* start = ptr;54 auto start = buffer.position(); 54 55 55 56 // read the sign 56 if ( ptr < end && *ptr == '+')57 ptr++;58 else if ( ptr < end && *ptr == '-') {59 ptr++;57 if (buffer.hasCharactersRemaining() && *buffer == '+') 58 ++buffer; 59 else if (buffer.hasCharactersRemaining() && *buffer == '-') { 60 ++buffer; 60 61 sign = -1; 61 62 } 62 63 63 if ( ptr == end || (!isASCIIDigit(*ptr) && *ptr != '.'))64 if (buffer.atEnd() || (!isASCIIDigit(*buffer) && *buffer != '.')) 64 65 return WTF::nullopt; 65 66 66 67 // read the integer part, build right-to-left 67 const CharacterType* ptrStartIntPart = ptr; 68 while (ptr < end && isASCIIDigit(*ptr)) 69 ++ptr; // Advance to first non-digit. 70 71 if (ptr != ptrStartIntPart) { 72 const CharacterType* ptrScanIntPart = ptr - 1; 68 auto ptrStartIntPart = buffer.position(); 69 70 // Advance to first non-digit. 71 skipWhile<CharacterType, isASCIIDigit>(buffer); 72 73 if (buffer.position() != ptrStartIntPart) { 74 auto ptrScanIntPart = buffer.position() - 1; 73 75 FloatType multiplier = 1; 74 76 while (ptrScanIntPart >= ptrStartIntPart) { … … 81 83 } 82 84 83 if (ptr < end && *ptr == '.') { // read the decimals 84 ptr++; 85 // read the decimals 86 if (buffer.hasCharactersRemaining() && *buffer == '.') { 87 ++buffer; 85 88 86 89 // There must be a least one digit following the . 87 if ( ptr >= end || !isASCIIDigit(*ptr))88 return WTF::nullopt; 89 90 while ( ptr < end && isASCIIDigit(*ptr))91 decimal += (*( ptr++) - '0') * (frac *= static_cast<FloatType>(0.1));90 if (buffer.atEnd() || !isASCIIDigit(*buffer)) 91 return WTF::nullopt; 92 93 while (buffer.hasCharactersRemaining() && isASCIIDigit(*buffer)) 94 decimal += (*(buffer++) - '0') * (frac *= static_cast<FloatType>(0.1)); 92 95 } 93 96 94 97 // read the exponent part 95 if ( ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E')96 && ( ptr[1] != 'x' && ptr[1] != 'm')) {97 ptr++;98 if (buffer.position() != start && buffer.position() + 1 < buffer.end() && (*buffer == 'e' || *buffer == 'E') 99 && (buffer[1] != 'x' && buffer[1] != 'm')) { 100 ++buffer; 98 101 99 102 // read the sign of the exponent 100 if (* ptr == '+')101 ptr++;102 else if (* ptr == '-') {103 ptr++;103 if (*buffer == '+') 104 ++buffer; 105 else if (*buffer == '-') { 106 ++buffer; 104 107 expsign = -1; 105 108 } 106 109 107 110 // There must be an exponent 108 if ( ptr >= end || !isASCIIDigit(*ptr))109 return WTF::nullopt; 110 111 while ( ptr < end && isASCIIDigit(*ptr)) {111 if (buffer.atEnd() || !isASCIIDigit(*buffer)) 112 return WTF::nullopt; 113 114 while (buffer.hasCharactersRemaining() && isASCIIDigit(*buffer)) { 112 115 exponent *= static_cast<FloatType>(10); 113 exponent += *ptr - '0'; 114 ptr++; 116 exponent += *buffer++ - '0'; 115 117 } 116 118 // Make sure exponent is valid. … … 129 131 return WTF::nullopt; 130 132 131 if (start == ptr)133 if (start == buffer.position()) 132 134 return WTF::nullopt; 133 135 134 136 if (skip == SuffixSkippingPolicy::Skip) 135 skipOptionalSVGSpacesOrDelimiter( ptr, end);137 skipOptionalSVGSpacesOrDelimiter(buffer); 136 138 137 139 return number; 138 140 } 139 141 140 Optional<float> parseNumber( const LChar*& ptr, const LChar* end, SuffixSkippingPolicy skip)141 { 142 return genericParseNumber( ptr, end, skip);143 } 144 145 Optional<float> parseNumber( const UChar*& ptr, const UChar* end, SuffixSkippingPolicy skip)146 { 147 return genericParseNumber( ptr, end, skip);142 Optional<float> parseNumber(StringParsingBuffer<LChar>& buffer, SuffixSkippingPolicy skip) 143 { 144 return genericParseNumber(buffer, skip); 145 } 146 147 Optional<float> parseNumber(StringParsingBuffer<UChar>& buffer, SuffixSkippingPolicy skip) 148 { 149 return genericParseNumber(buffer, skip); 148 150 } 149 151 150 152 Optional<float> parseNumber(const StringView& string, SuffixSkippingPolicy skip) 151 153 { 152 auto upconvertedCharacters = string.upconvertedCharacters(); 153 const UChar* ptr = upconvertedCharacters; 154 const UChar* end = ptr + string.length(); 155 auto result = genericParseNumber(ptr, end, skip); 156 if (ptr != end) 157 return WTF::nullopt; 158 return result; 154 return readCharactersForParsing(string, [skip](auto buffer) -> Optional<float> { 155 auto result = genericParseNumber(buffer, skip); 156 if (!buffer.atEnd()) 157 return WTF::nullopt; 158 return result; 159 }); 159 160 } 160 161 161 162 // only used to parse largeArcFlag and sweepFlag which must be a "0" or "1" 162 163 // and might not have any whitespace/comma after it 163 template <typename CharacterType> Optional<bool> genericParseArcFlag(const CharacterType*& ptr, const CharacterType* end) 164 { 165 if (ptr >= end) 166 return WTF::nullopt; 167 168 const CharacterType flagChar = *ptr++; 164 template <typename CharacterType> Optional<bool> genericParseArcFlag(StringParsingBuffer<CharacterType>& buffer) 165 { 166 if (buffer.atEnd()) 167 return WTF::nullopt; 168 169 const CharacterType flagChar = *buffer; 170 ++buffer; 169 171 170 172 bool flag; … … 176 178 return WTF::nullopt; 177 179 178 skipOptionalSVGSpacesOrDelimiter( ptr, end);180 skipOptionalSVGSpacesOrDelimiter(buffer); 179 181 180 182 return flag; 181 183 } 182 184 183 Optional<bool> parseArcFlag( const LChar*& ptr, const LChar* end)184 { 185 return genericParseArcFlag( ptr, end);186 } 187 188 Optional<bool> parseArcFlag( const UChar*& ptr, const UChar* end)189 { 190 return genericParseArcFlag( ptr, end);185 Optional<bool> parseArcFlag(StringParsingBuffer<LChar>& buffer) 186 { 187 return genericParseArcFlag(buffer); 188 } 189 190 Optional<bool> parseArcFlag(StringParsingBuffer<UChar>& buffer) 191 { 192 return genericParseArcFlag(buffer); 191 193 } 192 194 … … 196 198 return WTF::nullopt; 197 199 198 auto upconvertedCharacters = string.upconvertedCharacters(); 199 const UChar* cur = upconvertedCharacters; 200 const UChar* end = cur + string.length(); 201 202 auto x = parseNumber(cur, end); 203 if (!x) 204 return WTF::nullopt; 205 206 if (cur == end) 207 return std::make_pair(*x, *x); 208 209 auto y = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip); 210 if (!y) 211 return WTF::nullopt; 212 213 if (cur != end) 214 return WTF::nullopt; 215 216 return std::make_pair(*x, *y); 200 return readCharactersForParsing(string, [](auto buffer) -> Optional<std::pair<float, float>> { 201 auto x = parseNumber(buffer); 202 if (!x) 203 return WTF::nullopt; 204 205 if (buffer.atEnd()) 206 return std::make_pair(*x, *x); 207 208 auto y = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 209 if (!y) 210 return WTF::nullopt; 211 212 if (!buffer.atEnd()) 213 return WTF::nullopt; 214 215 return std::make_pair(*x, *y); 216 }); 217 217 } 218 218 … … 222 222 return WTF::nullopt; 223 223 224 auto upconvertedCharacters = string.upconvertedCharacters(); 225 const UChar* cur = upconvertedCharacters; 226 const UChar* end = cur + string.length(); 227 228 if (!skipOptionalSVGSpaces(cur, end)) 229 return WTF::nullopt; 230 231 auto point = parseFloatPoint(cur, end); 232 if (!point) 233 return WTF::nullopt; 234 235 // Disallow anything except spaces at the end. 236 skipOptionalSVGSpaces(cur, end); 237 238 return point; 224 return readCharactersForParsing(string, [](auto buffer) -> Optional<FloatPoint> { 225 if (!skipOptionalSVGSpaces(buffer)) 226 return WTF::nullopt; 227 228 auto point = parseFloatPoint(buffer); 229 if (!point) 230 return WTF::nullopt; 231 232 // Disallow anything except spaces at the end. 233 skipOptionalSVGSpaces(buffer); 234 235 return point; 236 }); 239 237 } 240 238 241 239 Optional<FloatRect> parseRect(const StringView& string) 242 240 { 243 auto upconvertedCharacters = string.upconvertedCharacters(); 244 const UChar* ptr = upconvertedCharacters; 245 const UChar* end = ptr + string.length(); 246 247 skipOptionalSVGSpaces(ptr, end); 248 249 auto x = parseNumber(ptr, end); 250 if (!x) 251 return WTF::nullopt; 252 auto y = parseNumber(ptr, end); 253 if (!y) 254 return WTF::nullopt; 255 auto width = parseNumber(ptr, end); 256 if (!width) 257 return WTF::nullopt; 258 auto height = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip); 259 if (!height) 260 return WTF::nullopt; 261 262 return FloatRect { *x, *y, *width, *height }; 241 return readCharactersForParsing(string, [](auto buffer) -> Optional<FloatRect> { 242 skipOptionalSVGSpaces(buffer); 243 244 auto x = parseNumber(buffer); 245 if (!x) 246 return WTF::nullopt; 247 auto y = parseNumber(buffer); 248 if (!y) 249 return WTF::nullopt; 250 auto width = parseNumber(buffer); 251 if (!width) 252 return WTF::nullopt; 253 auto height = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 254 if (!height) 255 return WTF::nullopt; 256 257 return FloatRect { *x, *y, *width, *height }; 258 }); 263 259 } 264 260 … … 267 263 // FIXME: Parsing error detection is missing. 268 264 269 auto upconvertedCharacters = string.upconvertedCharacters(); 270 const UChar* ptr = upconvertedCharacters; 271 const UChar* end = ptr + string.length(); 272 skipOptionalSVGSpaces(ptr, end); 273 274 HashSet<String> values; 275 276 while (ptr < end) { 277 // Leading and trailing white space, and white space before and after separators, will be ignored. 278 const UChar* inputStart = ptr; 279 while (ptr < end && *ptr != ',') 280 ++ptr; 281 282 if (ptr == inputStart) 283 break; 284 285 // walk backwards from the ; to ignore any whitespace 286 const UChar* inputEnd = ptr - 1; 287 while (inputStart < inputEnd && isSVGSpace(*inputEnd)) 288 --inputEnd; 289 290 values.add(String(inputStart, inputEnd - inputStart + 1)); 291 skipOptionalSVGSpacesOrDelimiter(ptr, end, ','); 292 } 293 294 return values; 295 } 296 297 static Optional<UnicodeRange> parseUnicodeRange(const UChar* characters, unsigned length) 298 { 299 if (length < 2 || characters[0] != 'U' || characters[1] != '+') 300 return WTF::nullopt; 301 265 return readCharactersForParsing(string, [](auto buffer) -> HashSet<String> { 266 skipOptionalSVGSpaces(buffer); 267 268 HashSet<String> values; 269 270 while (buffer.hasCharactersRemaining()) { 271 // Leading and trailing white space, and white space before and after separators, will be ignored. 272 auto inputStart = buffer.position(); 273 274 skipUntil(buffer, ','); 275 276 if (buffer.position() == inputStart) 277 break; 278 279 // walk backwards from the ; to ignore any whitespace 280 auto inputEnd = buffer.position() - 1; 281 while (inputStart < inputEnd && isSVGSpace(*inputEnd)) 282 --inputEnd; 283 284 values.add(String(inputStart, inputEnd - inputStart + 1)); 285 skipOptionalSVGSpacesOrDelimiter(buffer, ','); 286 } 287 return values; 288 }); 289 290 } 291 292 template<typename CharacterType> static Optional<UnicodeRange> parseUnicodeRange(StringParsingBuffer<CharacterType> buffer) 293 { 294 unsigned length = buffer.lengthRemaining(); 295 if (length < 2 || buffer[0] != 'U' || buffer[1] != '+') 296 return WTF::nullopt; 297 298 buffer += 2; 299 302 300 // Parse the starting hex number (or its prefix). 303 301 unsigned startRange = 0; 304 302 unsigned startLength = 0; 305 303 306 const UChar* ptr = characters + 2; 307 const UChar* end = characters + length; 308 while (ptr < end) { 309 if (!isASCIIHexDigit(*ptr)) 304 while (buffer.hasCharactersRemaining()) { 305 if (!isASCIIHexDigit(*buffer)) 310 306 break; 311 307 ++startLength; 312 308 if (startLength > 6) 313 309 return WTF::nullopt; 314 startRange = (startRange << 4) | toASCIIHexValue(* ptr);315 ++ ptr;310 startRange = (startRange << 4) | toASCIIHexValue(*buffer); 311 ++buffer; 316 312 } 317 313 318 314 // Handle the case of ranges separated by "-" sign. 319 if (2 + startLength < length && * ptr == '-') {315 if (2 + startLength < length && *buffer == '-') { 320 316 if (!startLength) 321 317 return WTF::nullopt; … … 324 320 unsigned endRange = 0; 325 321 unsigned endLength = 0; 326 ++ ptr;327 while ( ptr < end) {328 if (!isASCIIHexDigit(* ptr))322 ++buffer; 323 while (buffer.hasCharactersRemaining()) { 324 if (!isASCIIHexDigit(*buffer)) 329 325 break; 330 326 ++endLength; 331 327 if (endLength > 6) 332 328 return WTF::nullopt; 333 endRange = (endRange << 4) | toASCIIHexValue(* ptr);334 ++ ptr;329 endRange = (endRange << 4) | toASCIIHexValue(*buffer); 330 ++buffer; 335 331 } 336 332 … … 346 342 // Handle the case of a number with some optional trailing question marks. 347 343 unsigned endRange = startRange; 348 while ( ptr < end) {349 if (* ptr != '?')344 while (buffer.hasCharactersRemaining()) { 345 if (*buffer != '?') 350 346 break; 351 347 ++startLength; … … 354 350 startRange <<= 4; 355 351 endRange = (endRange << 4) | 0xF; 356 ++ ptr;352 ++buffer; 357 353 } 358 354 … … 370 366 // FIXME: Parsing error detection is missing. 371 367 372 auto upconvertedCharacters = string.upconvertedCharacters(); 373 const UChar* ptr = upconvertedCharacters; 374 const UChar* end = ptr + string.length(); 375 376 UnicodeRanges rangeList; 377 HashSet<String> stringList; 378 379 while (ptr < end) { 380 const UChar* inputStart = ptr; 381 while (ptr < end && *ptr != ',') 382 ++ptr; 383 384 if (ptr == inputStart) 385 break; 386 387 // Try to parse unicode range first 388 if (auto range = parseUnicodeRange(inputStart, ptr - inputStart)) 389 rangeList.append(WTFMove(*range)); 390 else 391 stringList.add(String(inputStart, ptr - inputStart)); 392 ++ptr; 393 } 394 395 return std::make_pair(rangeList, stringList); 396 } 397 398 template <typename CharacterType> static Optional<FloatPoint> genericParseFloatPoint(const CharacterType*& current, const CharacterType* end) 399 { 400 auto x = parseNumber(current, end); 368 return readCharactersForParsing(string, [](auto buffer) -> std::pair<UnicodeRanges, HashSet<String>> { 369 UnicodeRanges rangeList; 370 HashSet<String> stringList; 371 372 while (1) { 373 auto inputStart = buffer.position(); 374 375 skipUntil(buffer, ','); 376 377 if (buffer.position() == inputStart) 378 break; 379 380 // Try to parse unicode range first 381 if (auto range = parseUnicodeRange(StringParsingBuffer { inputStart, buffer.position() })) 382 rangeList.append(WTFMove(*range)); 383 else 384 stringList.add(String(inputStart, buffer.position() - inputStart)); 385 386 if (buffer.atEnd()) 387 break; 388 389 ++buffer; 390 } 391 392 return std::make_pair(WTFMove(rangeList), WTFMove(stringList)); 393 }); 394 } 395 396 template <typename CharacterType> static Optional<FloatPoint> genericParseFloatPoint(StringParsingBuffer<CharacterType>& buffer) 397 { 398 auto x = parseNumber(buffer); 401 399 if (!x) 402 400 return WTF::nullopt; 403 401 404 auto y = parseNumber( current, end);402 auto y = parseNumber(buffer); 405 403 if (!y) 406 404 return WTF::nullopt; … … 409 407 } 410 408 411 Optional<FloatPoint> parseFloatPoint( const LChar*& current, const LChar* end)412 { 413 return genericParseFloatPoint( current, end);414 } 415 416 Optional<FloatPoint> parseFloatPoint( const UChar*& current, const UChar* end)417 { 418 return genericParseFloatPoint( current, end);419 } 420 421 } 409 Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<LChar>& buffer) 410 { 411 return genericParseFloatPoint(buffer); 412 } 413 414 Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<UChar>& buffer) 415 { 416 return genericParseFloatPoint(buffer); 417 } 418 419 } -
trunk/Source/WebCore/svg/SVGParserUtilities.h
r263334 r263617 22 22 #pragma once 23 23 24 #include "ParsingUtilities.h" 24 25 #include <wtf/HashSet.h> 25 26 #include <wtf/Vector.h> 26 #include <wtf/text/WTFString.h>27 27 28 28 typedef std::pair<UChar32, UChar32> UnicodeRange; … … 39 39 }; 40 40 41 Optional<float> parseNumber( const LChar*& current, const LChar* end, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);42 Optional<float> parseNumber( const UChar*& current, const UChar* end, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);41 Optional<float> parseNumber(StringParsingBuffer<LChar>&, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip); 42 Optional<float> parseNumber(StringParsingBuffer<UChar>&, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip); 43 43 Optional<float> parseNumber(const StringView&, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip); 44 44 45 45 Optional<std::pair<float, float>> parseNumberOptionalNumber(const StringView&); 46 46 47 Optional<bool> parseArcFlag( const LChar*& current, const LChar* end);48 Optional<bool> parseArcFlag( const UChar*& current, const UChar* end);47 Optional<bool> parseArcFlag(StringParsingBuffer<LChar>&); 48 Optional<bool> parseArcFlag(StringParsingBuffer<UChar>&); 49 49 50 50 Optional<FloatPoint> parsePoint(const StringView&); 51 51 Optional<FloatRect> parseRect(const StringView&); 52 52 53 Optional<FloatPoint> parseFloatPoint( const LChar*& current, const LChar* end);54 Optional<FloatPoint> parseFloatPoint( const UChar*& current, const UChar* end);53 Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<LChar>&); 54 Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<UChar>&); 55 55 56 56 Optional<std::pair<UnicodeRanges, HashSet<String>>> parseKerningUnicodeString(const StringView&); … … 65 65 } 66 66 67 template<typename CharacterType> constexpr bool isSVGSpaceOrComma(CharacterType c) 68 { 69 return isSVGSpace(c) || c == ','; 70 } 71 67 72 template<typename CharacterType> constexpr bool skipOptionalSVGSpaces(const CharacterType*& ptr, const CharacterType* end) 68 73 { 69 while (ptr < end && isSVGSpace(*ptr)) 70 ptr++; 74 skipWhile<CharacterType, isSVGSpace>(ptr, end); 71 75 return ptr < end; 76 } 77 78 template<typename CharacterType> constexpr bool skipOptionalSVGSpaces(StringParsingBuffer<CharacterType>& characters) 79 { 80 skipWhile<CharacterType, isSVGSpace>(characters); 81 return characters.hasCharactersRemaining(); 72 82 } 73 83 … … 85 95 } 86 96 87 constexpr bool skipString(const UChar*& ptr, const UChar* end, const UChar* name, int length)97 template<typename CharacterType> constexpr bool skipOptionalSVGSpacesOrDelimiter(StringParsingBuffer<CharacterType>& characters, char delimiter = ',') 88 98 { 89 if ( end - ptr < length)99 if (characters.hasCharactersRemaining() && !isSVGSpace(*characters) && *characters != delimiter) 90 100 return false; 91 if (memcmp(name, ptr, sizeof(UChar) * length)) 92 return false; 93 ptr += length; 94 return true; 95 } 96 97 template<unsigned characterCount> 98 inline bool skipString(const UChar*& ptr, const UChar* end, const char (&str)[characterCount]) 99 { 100 int length = characterCount - 1; 101 if (end - ptr < length) 102 return false; 103 for (int i = 0; i < length; ++i) { 104 if (ptr[i] != str[i]) 105 return false; 101 if (skipOptionalSVGSpaces(characters)) { 102 if (characters.hasCharactersRemaining() && *characters == delimiter) { 103 characters++; 104 skipOptionalSVGSpaces(characters); 105 } 106 106 } 107 ptr += length; 108 return true; 107 return characters.hasCharactersRemaining(); 109 108 } 110 109 -
trunk/Source/WebCore/svg/SVGPathSource.h
r263334 r263617 20 20 #pragma once 21 21 22 #include "FloatPoint.h" 22 23 #include "SVGPathSeg.h" 23 24 24 25 namespace WebCore { 25 26 26 class FloatPoint;27 27 28 28 class SVGPathSource { -
trunk/Source/WebCore/svg/SVGPathStringSource.cpp
r263334 r263617 22 22 #include "SVGPathStringSource.h" 23 23 24 #include "FloatPoint.h"25 24 #include "SVGParserUtilities.h" 26 25 … … 33 32 ASSERT(!string.isEmpty()); 34 33 35 if (m_is8BitSource) { 36 m_current.m_character8 = string.characters8(); 37 m_end.m_character8 = m_current.m_character8 + string.length(); 38 } else { 39 m_current.m_character16 = string.characters16(); 40 m_end.m_character16 = m_current.m_character16 + string.length(); 41 } 34 if (m_is8BitSource) 35 m_buffer8 = { string.characters8(), string.length() }; 36 else 37 m_buffer16 = { string.characters16(), string.length() }; 42 38 } 43 39 … … 45 41 { 46 42 if (m_is8BitSource) 47 return m_ current.m_character8 < m_end.m_character8;48 return m_ current.m_character16 < m_end.m_character16;43 return m_buffer8.hasCharactersRemaining(); 44 return m_buffer16.hasCharactersRemaining(); 49 45 } 50 46 … … 52 48 { 53 49 if (m_is8BitSource) 54 return skipOptionalSVGSpaces(m_ current.m_character8, m_end.m_character8);55 return skipOptionalSVGSpaces(m_ current.m_character16, m_end.m_character16);56 } 57 58 template <typename CharacterType> static Optional<SVGPathSegType> nextCommandHelper( const CharacterType*& current, SVGPathSegType previousCommand)50 return skipOptionalSVGSpaces(m_buffer8); 51 return skipOptionalSVGSpaces(m_buffer16); 52 } 53 54 template <typename CharacterType> static Optional<SVGPathSegType> nextCommandHelper(StringParsingBuffer<CharacterType>& buffer, SVGPathSegType previousCommand) 59 55 { 60 56 // Check for remaining coordinates in the current command. 61 if ((* current == '+' || *current == '-' || *current == '.' || isASCIIDigit(*current))57 if ((*buffer == '+' || *buffer == '-' || *buffer == '.' || isASCIIDigit(*buffer)) 62 58 && previousCommand != PathSegClosePath) { 63 59 if (previousCommand == PathSegMoveToAbs) … … 74 70 { 75 71 if (m_is8BitSource) { 76 if (auto nextCommand = nextCommandHelper(m_ current.m_character8, previousCommand))72 if (auto nextCommand = nextCommandHelper(m_buffer8, previousCommand)) 77 73 return *nextCommand; 78 74 } else { 79 if (auto nextCommand = nextCommandHelper(m_ current.m_character16, previousCommand))75 if (auto nextCommand = nextCommandHelper(m_buffer16, previousCommand)) 80 76 return *nextCommand; 81 77 } … … 84 80 } 85 81 86 template <typename CharacterType> static SVGPathSegType parseSVGSegmentTypeHelper(const CharacterType*& current) 87 { 88 switch (*(current++)) { 89 case 'Z': 90 case 'z': 91 return PathSegClosePath; 92 case 'M': 93 return PathSegMoveToAbs; 94 case 'm': 95 return PathSegMoveToRel; 96 case 'L': 97 return PathSegLineToAbs; 98 case 'l': 99 return PathSegLineToRel; 100 case 'C': 101 return PathSegCurveToCubicAbs; 102 case 'c': 103 return PathSegCurveToCubicRel; 104 case 'Q': 105 return PathSegCurveToQuadraticAbs; 106 case 'q': 107 return PathSegCurveToQuadraticRel; 108 case 'A': 109 return PathSegArcAbs; 110 case 'a': 111 return PathSegArcRel; 112 case 'H': 113 return PathSegLineToHorizontalAbs; 114 case 'h': 115 return PathSegLineToHorizontalRel; 116 case 'V': 117 return PathSegLineToVerticalAbs; 118 case 'v': 119 return PathSegLineToVerticalRel; 120 case 'S': 121 return PathSegCurveToCubicSmoothAbs; 122 case 's': 123 return PathSegCurveToCubicSmoothRel; 124 case 'T': 125 return PathSegCurveToQuadraticSmoothAbs; 126 case 't': 127 return PathSegCurveToQuadraticSmoothRel; 128 default: 129 return PathSegUnknown; 130 } 82 template<typename F> decltype(auto) SVGPathStringSource::parse(F&& functor) 83 { 84 if (m_is8BitSource) 85 return functor(m_buffer8); 86 return functor(m_buffer16); 131 87 } 132 88 133 89 Optional<SVGPathSegType> SVGPathStringSource::parseSVGSegmentType() 134 90 { 135 if (m_is8BitSource) 136 return parseSVGSegmentTypeHelper(m_current.m_character8); 137 return parseSVGSegmentTypeHelper(m_current.m_character16); 91 return parse([](auto& buffer) -> SVGPathSegType { 92 auto character = *buffer; 93 buffer++; 94 switch (character) { 95 case 'Z': 96 case 'z': 97 return PathSegClosePath; 98 case 'M': 99 return PathSegMoveToAbs; 100 case 'm': 101 return PathSegMoveToRel; 102 case 'L': 103 return PathSegLineToAbs; 104 case 'l': 105 return PathSegLineToRel; 106 case 'C': 107 return PathSegCurveToCubicAbs; 108 case 'c': 109 return PathSegCurveToCubicRel; 110 case 'Q': 111 return PathSegCurveToQuadraticAbs; 112 case 'q': 113 return PathSegCurveToQuadraticRel; 114 case 'A': 115 return PathSegArcAbs; 116 case 'a': 117 return PathSegArcRel; 118 case 'H': 119 return PathSegLineToHorizontalAbs; 120 case 'h': 121 return PathSegLineToHorizontalRel; 122 case 'V': 123 return PathSegLineToVerticalAbs; 124 case 'v': 125 return PathSegLineToVerticalRel; 126 case 'S': 127 return PathSegCurveToCubicSmoothAbs; 128 case 's': 129 return PathSegCurveToCubicSmoothRel; 130 case 'T': 131 return PathSegCurveToQuadraticSmoothAbs; 132 case 't': 133 return PathSegCurveToQuadraticSmoothRel; 134 default: 135 return PathSegUnknown; 136 } 137 }); 138 138 } 139 139 140 140 Optional<SVGPathSource::MoveToSegment> SVGPathStringSource::parseMoveToSegment() 141 141 { 142 auto helper = [](const auto*& current, const auto* end) -> Optional<MoveToSegment> {143 auto targetPoint = parseFloatPoint( current, end);142 return parse([](auto& buffer) -> Optional<MoveToSegment> { 143 auto targetPoint = parseFloatPoint(buffer); 144 144 if (!targetPoint) 145 145 return WTF::nullopt; … … 148 148 segment.targetPoint = WTFMove(*targetPoint); 149 149 return segment; 150 }; 151 152 if (m_is8BitSource) 153 return helper(m_current.m_character8, m_end.m_character8); 154 return helper(m_current.m_character16, m_end.m_character16); 150 }); 155 151 } 156 152 157 153 Optional<SVGPathSource::LineToSegment> SVGPathStringSource::parseLineToSegment() 158 154 { 159 auto helper = [](const auto*& current, const auto* end) -> Optional<LineToSegment> {160 auto targetPoint = parseFloatPoint( current, end);155 return parse([](auto& buffer) -> Optional<LineToSegment> { 156 auto targetPoint = parseFloatPoint(buffer); 161 157 if (!targetPoint) 162 158 return WTF::nullopt; … … 165 161 segment.targetPoint = WTFMove(*targetPoint); 166 162 return segment; 167 }; 168 169 if (m_is8BitSource) 170 return helper(m_current.m_character8, m_end.m_character8); 171 return helper(m_current.m_character16, m_end.m_character16); 163 }); 172 164 } 173 165 174 166 Optional<SVGPathSource::LineToHorizontalSegment> SVGPathStringSource::parseLineToHorizontalSegment() 175 167 { 176 auto helper = [](const auto*& current, const auto* end) -> Optional<LineToHorizontalSegment> {177 auto x = parseNumber( current, end);168 return parse([](auto& buffer) -> Optional<LineToHorizontalSegment> { 169 auto x = parseNumber(buffer); 178 170 if (!x) 179 171 return WTF::nullopt; … … 182 174 segment.x = *x; 183 175 return segment; 184 }; 185 186 if (m_is8BitSource) 187 return helper(m_current.m_character8, m_end.m_character8); 188 return helper(m_current.m_character16, m_end.m_character16); 176 }); 189 177 } 190 178 191 179 Optional<SVGPathSource::LineToVerticalSegment> SVGPathStringSource::parseLineToVerticalSegment() 192 180 { 193 auto helper = [](const auto*& current, const auto* end) -> Optional<LineToVerticalSegment> {194 auto y = parseNumber( current, end);181 return parse([](auto& buffer) -> Optional<LineToVerticalSegment> { 182 auto y = parseNumber(buffer); 195 183 if (!y) 196 184 return WTF::nullopt; … … 199 187 segment.y = *y; 200 188 return segment; 201 }; 202 203 if (m_is8BitSource) 204 return helper(m_current.m_character8, m_end.m_character8); 205 return helper(m_current.m_character16, m_end.m_character16); 189 }); 206 190 } 207 191 208 192 Optional<SVGPathSource::CurveToCubicSegment> SVGPathStringSource::parseCurveToCubicSegment() 209 193 { 210 auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToCubicSegment> {211 auto point1 = parseFloatPoint( current, end);194 return parse([](auto& buffer) -> Optional<CurveToCubicSegment> { 195 auto point1 = parseFloatPoint(buffer); 212 196 if (!point1) 213 197 return WTF::nullopt; 214 198 215 auto point2 = parseFloatPoint( current, end);199 auto point2 = parseFloatPoint(buffer); 216 200 if (!point2) 217 201 return WTF::nullopt; 218 202 219 auto targetPoint = parseFloatPoint( current, end);203 auto targetPoint = parseFloatPoint(buffer); 220 204 if (!targetPoint) 221 205 return WTF::nullopt; … … 226 210 segment.targetPoint = *targetPoint; 227 211 return segment; 228 }; 229 230 if (m_is8BitSource) 231 return helper(m_current.m_character8, m_end.m_character8); 232 return helper(m_current.m_character16, m_end.m_character16); 212 }); 233 213 } 234 214 235 215 Optional<SVGPathSource::CurveToCubicSmoothSegment> SVGPathStringSource::parseCurveToCubicSmoothSegment() 236 216 { 237 auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToCubicSmoothSegment> {238 auto point2 = parseFloatPoint( current, end);217 return parse([](auto& buffer) -> Optional<CurveToCubicSmoothSegment> { 218 auto point2 = parseFloatPoint(buffer); 239 219 if (!point2) 240 220 return WTF::nullopt; 241 221 242 auto targetPoint = parseFloatPoint( current, end);222 auto targetPoint = parseFloatPoint(buffer); 243 223 if (!targetPoint) 244 224 return WTF::nullopt; … … 248 228 segment.targetPoint = *targetPoint; 249 229 return segment; 250 }; 251 252 if (m_is8BitSource) 253 return helper(m_current.m_character8, m_end.m_character8); 254 return helper(m_current.m_character16, m_end.m_character16); 230 }); 255 231 } 256 232 257 233 Optional<SVGPathSource::CurveToQuadraticSegment> SVGPathStringSource::parseCurveToQuadraticSegment() 258 234 { 259 auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToQuadraticSegment> {260 auto point1 = parseFloatPoint( current, end);235 return parse([](auto& buffer) -> Optional<CurveToQuadraticSegment> { 236 auto point1 = parseFloatPoint(buffer); 261 237 if (!point1) 262 238 return WTF::nullopt; 263 239 264 auto targetPoint = parseFloatPoint( current, end);240 auto targetPoint = parseFloatPoint(buffer); 265 241 if (!targetPoint) 266 242 return WTF::nullopt; … … 270 246 segment.targetPoint = *targetPoint; 271 247 return segment; 272 }; 273 274 if (m_is8BitSource) 275 return helper(m_current.m_character8, m_end.m_character8); 276 return helper(m_current.m_character16, m_end.m_character16); 248 }); 277 249 } 278 250 279 251 Optional<SVGPathSource::CurveToQuadraticSmoothSegment> SVGPathStringSource::parseCurveToQuadraticSmoothSegment() 280 252 { 281 auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToQuadraticSmoothSegment> {282 auto targetPoint = parseFloatPoint( current, end);253 return parse([](auto& buffer) -> Optional<CurveToQuadraticSmoothSegment> { 254 auto targetPoint = parseFloatPoint(buffer); 283 255 if (!targetPoint) 284 256 return WTF::nullopt; … … 287 259 segment.targetPoint = *targetPoint; 288 260 return segment; 289 }; 290 291 if (m_is8BitSource) 292 return helper(m_current.m_character8, m_end.m_character8); 293 return helper(m_current.m_character16, m_end.m_character16); 261 }); 294 262 } 295 263 296 264 Optional<SVGPathSource::ArcToSegment> SVGPathStringSource::parseArcToSegment() 297 265 { 298 auto helper = [](const auto*& current, const auto* end) -> Optional<ArcToSegment> {299 auto rx = parseNumber( current, end);266 return parse([](auto& buffer) -> Optional<ArcToSegment> { 267 auto rx = parseNumber(buffer); 300 268 if (!rx) 301 269 return WTF::nullopt; 302 auto ry = parseNumber( current, end);270 auto ry = parseNumber(buffer); 303 271 if (!ry) 304 272 return WTF::nullopt; 305 auto angle = parseNumber( current, end);273 auto angle = parseNumber(buffer); 306 274 if (!angle) 307 275 return WTF::nullopt; 308 auto largeArc = parseArcFlag( current, end);276 auto largeArc = parseArcFlag(buffer); 309 277 if (!largeArc) 310 278 return WTF::nullopt; 311 auto sweep = parseArcFlag( current, end);279 auto sweep = parseArcFlag(buffer); 312 280 if (!sweep) 313 281 return WTF::nullopt; 314 auto targetPoint = parseFloatPoint( current, end);282 auto targetPoint = parseFloatPoint(buffer); 315 283 if (!targetPoint) 316 284 return WTF::nullopt; … … 324 292 segment.targetPoint = *targetPoint; 325 293 return segment; 326 }; 327 328 if (m_is8BitSource) 329 return helper(m_current.m_character8, m_end.m_character8); 330 return helper(m_current.m_character16, m_end.m_character16); 294 }); 331 295 } 332 296 -
trunk/Source/WebCore/svg/SVGPathStringSource.h
r263334 r263617 22 22 23 23 #include "SVGPathSource.h" 24 #include <wtf/text/StringParsingBuffer.h> 24 25 #include <wtf/text/WTFString.h> 25 26 … … 46 47 Optional<ArcToSegment> parseArcToSegment() final; 47 48 49 template<typename Function> decltype(auto) parse(Function&&); 50 48 51 String m_string; 49 52 bool m_is8BitSource; 50 53 51 54 union { 52 const LChar* m_character8; 53 const UChar* m_character16; 54 } m_current; 55 union { 56 const LChar* m_character8; 57 const UChar* m_character16; 58 } m_end; 55 StringParsingBuffer<LChar> m_buffer8; 56 StringParsingBuffer<UChar> m_buffer16; 57 }; 59 58 }; 60 59 -
trunk/Source/WebCore/svg/SVGPointList.cpp
r263616 r263617 1 1 /* 2 * Copyright (C) 20 16-2019Apple Inc. All rights reserved.2 * Copyright (C) 2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #pragma once 26 #include "config.h" 27 #include "SVGPointList.h" 27 28 28 #include "SVGPoint.h"29 #include "SVGValuePropertyList.h"29 #include <wtf/text/StringBuilder.h> 30 #include <wtf/text/StringParsingBuffer.h> 30 31 31 32 namespace WebCore { 32 33 33 class SVGPointList : public SVGValuePropertyList<SVGPoint> { 34 using Base = SVGValuePropertyList<SVGPoint>; 35 using Base::Base;34 bool SVGPointList::parse(StringView value) 35 { 36 clearItems(); 36 37 37 public: 38 static Ref<SVGPointList> create() 39 { 40 return adoptRef(*new SVGPointList()); 41 } 42 43 static Ref<SVGPointList> create(SVGPropertyOwner* owner, SVGPropertyAccess access) 44 { 45 return adoptRef(*new SVGPointList(owner, access)); 46 } 47 48 static Ref<SVGPointList> create(const SVGPointList& other, SVGPropertyAccess access) 49 { 50 return adoptRef(*new SVGPointList(other, access)); 51 } 52 53 bool parse(const String& value) 54 { 55 clearItems(); 56 57 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 58 const UChar* cur = upconvertedCharacters; 59 const UChar* end = cur + value.length(); 60 61 skipOptionalSVGSpaces(cur, end); 38 return readCharactersForParsing(value, [&](auto buffer) { 39 skipOptionalSVGSpaces(buffer); 62 40 63 41 bool delimParsed = false; 64 while ( cur < end) {42 while (buffer.hasCharactersRemaining()) { 65 43 delimParsed = false; 66 44 67 auto xPos = parseNumber( cur, end);45 auto xPos = parseNumber(buffer); 68 46 if (!xPos) 69 47 return false; 70 48 71 auto yPos = parseNumber( cur, end, SuffixSkippingPolicy::DontSkip);49 auto yPos = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 72 50 if (!yPos) 73 51 return false; 74 52 75 skipOptionalSVGSpaces( cur, end);53 skipOptionalSVGSpaces(buffer); 76 54 77 if ( cur < end && *cur == ',') {55 if (skipExactly(buffer, ',')) 78 56 delimParsed = true; 79 cur++; 80 } 81 skipOptionalSVGSpaces(cur, end); 57 58 skipOptionalSVGSpaces(buffer); 82 59 83 60 append(SVGPoint::create({ *xPos, *yPos })); 84 61 } 85 62 63 // FIXME: Should this clearItems() on failure like SVGTransformList does? 64 86 65 return !delimParsed; 66 }); 67 } 68 69 String SVGPointList::valueAsString() const 70 { 71 StringBuilder builder; 72 73 for (const auto& point : m_items) { 74 if (builder.length()) 75 builder.append(' '); 76 77 builder.append(point->x(), ' ', point->y()); 87 78 } 88 79 89 String valueAsString() const override 90 { 91 StringBuilder builder; 92 93 for (const auto& point : m_items) { 94 if (builder.length()) 95 builder.append(' '); 96 97 builder.append(point->x(), ' ', point->y()); 98 } 99 100 return builder.toString(); 101 } 102 }; 80 return builder.toString(); 81 } 103 82 104 83 } -
trunk/Source/WebCore/svg/SVGPointList.h
r263334 r263617 31 31 namespace WebCore { 32 32 33 class SVGPointList : public SVGValuePropertyList<SVGPoint> {33 class SVGPointList final : public SVGValuePropertyList<SVGPoint> { 34 34 using Base = SVGValuePropertyList<SVGPoint>; 35 35 using Base::Base; … … 51 51 } 52 52 53 bool parse(const String& value) 54 { 55 clearItems(); 56 57 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 58 const UChar* cur = upconvertedCharacters; 59 const UChar* end = cur + value.length(); 60 61 skipOptionalSVGSpaces(cur, end); 62 63 bool delimParsed = false; 64 while (cur < end) { 65 delimParsed = false; 66 67 auto xPos = parseNumber(cur, end); 68 if (!xPos) 69 return false; 70 71 auto yPos = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip); 72 if (!yPos) 73 return false; 74 75 skipOptionalSVGSpaces(cur, end); 76 77 if (cur < end && *cur == ',') { 78 delimParsed = true; 79 cur++; 80 } 81 skipOptionalSVGSpaces(cur, end); 82 83 append(SVGPoint::create({ *xPos, *yPos })); 84 } 85 86 return !delimParsed; 87 } 88 89 String valueAsString() const override 90 { 91 StringBuilder builder; 92 93 for (const auto& point : m_items) { 94 if (builder.length()) 95 builder.append(' '); 96 97 builder.append(point->x(), ' ', point->y()); 98 } 99 100 return builder.toString(); 101 } 53 bool parse(StringView); 54 String valueAsString() const override; 102 55 }; 103 56 -
trunk/Source/WebCore/svg/SVGPreserveAspectRatioValue.cpp
r254703 r263617 27 27 #include "SVGParserUtilities.h" 28 28 #include <wtf/text/StringConcatenateNumbers.h> 29 #include <wtf/text/StringParsingBuffer.h> 29 30 #include <wtf/text/StringView.h> 30 31 … … 37 38 } 38 39 39 SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue( const String&value)40 SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue(StringView value) 40 41 { 41 42 parse(value); … … 60 61 } 61 62 62 void SVGPreserveAspectRatioValue::parse(const String& value) 63 { 64 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 65 const UChar* begin = upconvertedCharacters; 66 parseInternal(begin, begin + value.length(), true); 67 } 68 69 bool SVGPreserveAspectRatioValue::parse(const UChar*& currParam, const UChar* end, bool validate) 70 { 71 return parseInternal(currParam, end, validate); 72 } 73 74 bool SVGPreserveAspectRatioValue::parseInternal(const UChar*& currParam, const UChar* end, bool validate) 63 bool SVGPreserveAspectRatioValue::parse(StringView value) 64 { 65 return readCharactersForParsing(value, [&](auto buffer) { 66 return parseInternal(buffer, true); 67 }); 68 } 69 70 bool SVGPreserveAspectRatioValue::parse(StringParsingBuffer<LChar>& buffer, bool validate) 71 { 72 return parseInternal(buffer, validate); 73 } 74 75 bool SVGPreserveAspectRatioValue::parse(StringParsingBuffer<UChar>& buffer, bool validate) 76 { 77 return parseInternal(buffer, validate); 78 } 79 80 template<typename CharacterType> static constexpr CharacterType deferDesc[] = {'d', 'e', 'f', 'e', 'r'}; 81 template<typename CharacterType> static constexpr CharacterType noneDesc[] = {'n', 'o', 'n', 'e'}; 82 template<typename CharacterType> static constexpr CharacterType meetDesc[] = {'m', 'e', 'e', 't'}; 83 template<typename CharacterType> static constexpr CharacterType sliceDesc[] = {'s', 'l', 'i', 'c', 'e'}; 84 85 template<typename CharacterType> bool SVGPreserveAspectRatioValue::parseInternal(StringParsingBuffer<CharacterType>& buffer, bool validate) 75 86 { 76 87 SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_XMIDYMID; … … 80 91 m_meetOrSlice = meetOrSlice; 81 92 82 if (!skipOptionalSVGSpaces( currParam, end))93 if (!skipOptionalSVGSpaces(buffer)) 83 94 return false; 84 95 85 if (* currParam== 'd') {86 if (!skip String(currParam, end, "defer")) {96 if (*buffer == 'd') { 97 if (!skipCharactersExactly(buffer, deferDesc<CharacterType>)) { 87 98 LOG_ERROR("Skipped to parse except for *defer* value."); 88 99 return false; … … 90 101 91 102 // FIXME: We just ignore the "defer" here. 92 if ( currParam == end)103 if (buffer.atEnd()) 93 104 return true; 94 105 95 if (!skipOptionalSVGSpaces( currParam, end))96 return false; 97 } 98 99 if (* currParam== 'n') {100 if (!skip String(currParam, end, "none")) {106 if (!skipOptionalSVGSpaces(buffer)) 107 return false; 108 } 109 110 if (*buffer == 'n') { 111 if (!skipCharactersExactly(buffer, noneDesc<CharacterType>)) { 101 112 LOG_ERROR("Skipped to parse except for *none* value."); 102 113 return false; 103 114 } 104 115 align = SVG_PRESERVEASPECTRATIO_NONE; 105 skipOptionalSVGSpaces( currParam, end);106 } else if (* currParam== 'x') {107 if ( (end - currParam) < 8)108 return false; 109 if ( currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M')110 return false; 111 if ( currParam[2] == 'i') {112 if ( currParam[3] == 'n') {113 if ( currParam[6] == 'i') {114 if ( currParam[7] == 'n')116 skipOptionalSVGSpaces(buffer); 117 } else if (*buffer == 'x') { 118 if (buffer.lengthRemaining() < 8) 119 return false; 120 if (buffer[1] != 'M' || buffer[4] != 'Y' || buffer[5] != 'M') 121 return false; 122 if (buffer[2] == 'i') { 123 if (buffer[3] == 'n') { 124 if (buffer[6] == 'i') { 125 if (buffer[7] == 'n') 115 126 align = SVG_PRESERVEASPECTRATIO_XMINYMIN; 116 else if ( currParam[7] == 'd')127 else if (buffer[7] == 'd') 117 128 align = SVG_PRESERVEASPECTRATIO_XMINYMID; 118 129 else 119 130 return false; 120 } else if ( currParam[6] == 'a' && currParam[7] == 'x')131 } else if (buffer[6] == 'a' && buffer[7] == 'x') 121 132 align = SVG_PRESERVEASPECTRATIO_XMINYMAX; 122 133 else 123 134 return false; 124 } else if (currParam[3] == 'd') {125 if ( currParam[6] == 'i') {126 if ( currParam[7] == 'n')135 } else if (buffer[3] == 'd') { 136 if (buffer[6] == 'i') { 137 if (buffer[7] == 'n') 127 138 align = SVG_PRESERVEASPECTRATIO_XMIDYMIN; 128 else if ( currParam[7] == 'd')139 else if (buffer[7] == 'd') 129 140 align = SVG_PRESERVEASPECTRATIO_XMIDYMID; 130 141 else 131 142 return false; 132 } else if ( currParam[6] == 'a' && currParam[7] == 'x')143 } else if (buffer[6] == 'a' && buffer[7] == 'x') 133 144 align = SVG_PRESERVEASPECTRATIO_XMIDYMAX; 134 145 else … … 136 147 } else 137 148 return false; 138 } else if ( currParam[2] == 'a' && currParam[3] == 'x') {139 if ( currParam[6] == 'i') {140 if ( currParam[7] == 'n')149 } else if (buffer[2] == 'a' && buffer[3] == 'x') { 150 if (buffer[6] == 'i') { 151 if (buffer[7] == 'n') 141 152 align = SVG_PRESERVEASPECTRATIO_XMAXYMIN; 142 else if ( currParam[7] == 'd')153 else if (buffer[7] == 'd') 143 154 align = SVG_PRESERVEASPECTRATIO_XMAXYMID; 144 155 else 145 156 return false; 146 } else if ( currParam[6] == 'a' && currParam[7] == 'x')157 } else if (buffer[6] == 'a' && buffer[7] == 'x') 147 158 align = SVG_PRESERVEASPECTRATIO_XMAXYMAX; 148 159 else … … 150 161 } else 151 162 return false; 152 currParam+= 8;153 skipOptionalSVGSpaces( currParam, end);163 buffer += 8; 164 skipOptionalSVGSpaces(buffer); 154 165 } else 155 166 return false; 156 167 157 if ( currParam < end) {158 if (* currParam== 'm') {159 if (!skip String(currParam, end, "meet")) {168 if (buffer.hasCharactersRemaining()) { 169 if (*buffer == 'm') { 170 if (!skipCharactersExactly(buffer, meetDesc<CharacterType>)) { 160 171 LOG_ERROR("Skipped to parse except for *meet* or *slice* value."); 161 172 return false; 162 173 } 163 skipOptionalSVGSpaces( currParam, end);164 } else if (* currParam== 's') {165 if (!skip String(currParam, end, "slice")) {174 skipOptionalSVGSpaces(buffer); 175 } else if (*buffer == 's') { 176 if (!skipCharactersExactly(buffer, sliceDesc<CharacterType>)) { 166 177 LOG_ERROR("Skipped to parse except for *meet* or *slice* value."); 167 178 return false; 168 179 } 169 skipOptionalSVGSpaces( currParam, end);180 skipOptionalSVGSpaces(buffer); 170 181 if (align != SVG_PRESERVEASPECTRATIO_NONE) 171 182 meetOrSlice = SVG_MEETORSLICE_SLICE; … … 173 184 } 174 185 175 if ( end != currParam&& validate)186 if (!buffer.atEnd() && validate) 176 187 return false; 177 188 … … 329 340 String SVGPreserveAspectRatioValue::valueAsString() const 330 341 { 331 String alignType; 332 333 switch (m_align) { 334 case SVG_PRESERVEASPECTRATIO_NONE: 335 alignType = "none"; 336 break; 337 case SVG_PRESERVEASPECTRATIO_XMINYMIN: 338 alignType = "xMinYMin"; 339 break; 340 case SVG_PRESERVEASPECTRATIO_XMIDYMIN: 341 alignType = "xMidYMin"; 342 break; 343 case SVG_PRESERVEASPECTRATIO_XMAXYMIN: 344 alignType = "xMaxYMin"; 345 break; 346 case SVG_PRESERVEASPECTRATIO_XMINYMID: 347 alignType = "xMinYMid"; 348 break; 349 case SVG_PRESERVEASPECTRATIO_XMIDYMID: 350 alignType = "xMidYMid"; 351 break; 352 case SVG_PRESERVEASPECTRATIO_XMAXYMID: 353 alignType = "xMaxYMid"; 354 break; 355 case SVG_PRESERVEASPECTRATIO_XMINYMAX: 356 alignType = "xMinYMax"; 357 break; 358 case SVG_PRESERVEASPECTRATIO_XMIDYMAX: 359 alignType = "xMidYMax"; 360 break; 361 case SVG_PRESERVEASPECTRATIO_XMAXYMAX: 362 alignType = "xMaxYMax"; 363 break; 364 case SVG_PRESERVEASPECTRATIO_UNKNOWN: 365 alignType = "unknown"; 366 break; 342 auto alignType = [&]() { 343 switch (m_align) { 344 case SVG_PRESERVEASPECTRATIO_NONE: 345 return "none"_s; 346 case SVG_PRESERVEASPECTRATIO_XMINYMIN: 347 return "xMinYMin"_s; 348 case SVG_PRESERVEASPECTRATIO_XMIDYMIN: 349 return "xMidYMin"_s; 350 case SVG_PRESERVEASPECTRATIO_XMAXYMIN: 351 return "xMaxYMin"_s; 352 case SVG_PRESERVEASPECTRATIO_XMINYMID: 353 return "xMinYMid"_s; 354 case SVG_PRESERVEASPECTRATIO_XMIDYMID: 355 return "xMidYMid"_s; 356 case SVG_PRESERVEASPECTRATIO_XMAXYMID: 357 return "xMaxYMid"_s; 358 case SVG_PRESERVEASPECTRATIO_XMINYMAX: 359 return "xMinYMax"_s; 360 case SVG_PRESERVEASPECTRATIO_XMIDYMAX: 361 return "xMidYMax"_s; 362 case SVG_PRESERVEASPECTRATIO_XMAXYMAX: 363 return "xMaxYMax"_s; 364 case SVG_PRESERVEASPECTRATIO_UNKNOWN: 365 return "unknown"_s; 366 }; 367 368 ASSERT_NOT_REACHED(); 369 return "unknown"_s; 367 370 }; 368 371 … … 370 373 default: 371 374 case SVG_MEETORSLICE_UNKNOWN: 372 return alignType ;375 return alignType(); 373 376 case SVG_MEETORSLICE_MEET: 374 return alignType + " meet";377 return makeString(alignType(), " meet"); 375 378 case SVG_MEETORSLICE_SLICE: 376 return alignType + " slice";377 } 378 } 379 380 } 379 return makeString(alignType(), " slice"); 380 } 381 } 382 383 } -
trunk/Source/WebCore/svg/SVGPreserveAspectRatioValue.h
r239427 r263617 53 53 54 54 SVGPreserveAspectRatioValue(); 55 SVGPreserveAspectRatioValue( const String&);55 SVGPreserveAspectRatioValue(StringView); 56 56 57 57 ExceptionOr<void> setAlign(unsigned short); … … 65 65 AffineTransform getCTM(float logicalX, float logicalY, float logicalWidth, float logicalHeight, float physicalWidth, float physicalHeight) const; 66 66 67 void parse(const String&); 68 bool parse(const UChar*& currParam, const UChar* end, bool validate); 67 bool parse(StringView); 68 bool parse(StringParsingBuffer<LChar>&, bool validate); 69 bool parse(StringParsingBuffer<UChar>&, bool validate); 69 70 70 71 String valueAsString() const; … … 74 75 SVGMeetOrSliceType m_meetOrSlice; 75 76 76 bool parseInternal(const UChar*& currParam, const UChar* end, bool validate);77 template<typename CharacterType> bool parseInternal(StringParsingBuffer<CharacterType>&, bool validate); 77 78 }; 78 79 -
trunk/Source/WebCore/svg/SVGStringList.h
r250201 r263617 52 52 } 53 53 54 bool parse(const String& data, UChar delimiter) 55 { 56 clearItems(); 57 58 auto upconvertedCharacters = StringView(data).upconvertedCharacters(); 59 const UChar* ptr = upconvertedCharacters; 60 const UChar* end = ptr + data.length(); 61 while (ptr < end) { 62 const UChar* start = ptr; 63 while (ptr < end && *ptr != delimiter && !isSVGSpace(*ptr)) 64 ptr++; 65 if (ptr == start) 66 break; 67 m_items.append(String(start, ptr - start)); 68 skipOptionalSVGSpacesOrDelimiter(ptr, end, delimiter); 69 } 70 71 return ptr == end; 72 } 73 74 String valueAsString() const override 75 { 76 StringBuilder builder; 77 78 for (const auto& string : m_items) { 79 if (builder.length()) 80 builder.append(' '); 81 82 builder.append(string); 83 } 84 85 return builder.toString(); 86 } 54 bool parse(StringView, UChar delimiter); 55 String valueAsString() const override; 87 56 }; 88 57 -
trunk/Source/WebCore/svg/SVGTransformList.h
r263334 r263617 57 57 } 58 58 59 ExceptionOr<RefPtr<SVGTransform>> consolidate() 60 { 61 auto result = canAlterList(); 62 if (result.hasException()) 63 return result.releaseException(); 64 ASSERT(result.releaseReturnValue()); 59 ExceptionOr<RefPtr<SVGTransform>> consolidate(); 60 AffineTransform concatenate() const; 65 61 66 // Spec: If the list was empty, then a value of null is returned. 67 if (m_items.isEmpty()) 68 return nullptr; 69 70 if (m_items.size() == 1) 71 return makeRefPtr(at(0).get()); 72 73 auto newItem = SVGTransform::create(concatenate()); 74 clearItems(); 75 76 auto item = append(WTFMove(newItem)); 77 commitChange(); 78 return makeRefPtr(item.get()); 79 } 80 81 void parse(const String& value) 82 { 83 clearItems(); 84 85 auto upconvertedCharacters = StringView(value).upconvertedCharacters(); 86 const UChar* start = upconvertedCharacters; 87 if (!parse(start, start + value.length())) 88 clearItems(); 89 } 90 91 AffineTransform concatenate() const 92 { 93 AffineTransform result; 94 for (const auto& transform : m_items) 95 result *= transform->matrix()->value(); 96 return result; 97 } 98 99 String valueAsString() const override 100 { 101 StringBuilder builder; 102 for (const auto& transfrom : m_items) { 103 if (builder.length()) 104 builder.append(' '); 105 106 builder.append(transfrom->value().valueAsString()); 107 } 108 return builder.toString(); 109 } 62 void parse(StringView); 63 String valueAsString() const override; 110 64 111 65 private: 112 bool parse(const UChar*& start, const UChar* end) 113 { 114 bool delimParsed = false; 115 while (start < end) { 116 delimParsed = false; 117 skipOptionalSVGSpaces(start, end); 118 119 auto type = SVGTransformable::parseAndSkipType(start, end); 120 if (!type) 121 return false; 122 123 auto parsedTransformValue = SVGTransformable::parseTransformValue(*type, start, end); 124 if (!parsedTransformValue) 125 return false; 126 127 append(SVGTransform::create(*parsedTransformValue)); 128 129 skipOptionalSVGSpaces(start, end); 130 if (start < end && *start == ',') { 131 delimParsed = true; 132 ++start; 133 } 134 135 skipOptionalSVGSpaces(start, end); 136 } 137 return !delimParsed; 138 } 66 template<typename CharacterType> bool parseGeneric(StringParsingBuffer<CharacterType>&); 67 bool parse(StringParsingBuffer<LChar>&); 68 bool parse(StringParsingBuffer<UChar>&); 139 69 }; 140 70 -
trunk/Source/WebCore/svg/SVGTransformable.cpp
r263334 r263617 28 28 #include "SVGNames.h" 29 29 #include "SVGParserUtilities.h" 30 #include <wtf/text/StringParsingBuffer.h> 30 31 #include <wtf/text/StringView.h> 31 32 32 33 namespace WebCore { 33 34 34 static int parseTransformParamList(const UChar*& ptr, const UChar* end, float* values, int required, int optional) 35 SVGTransformable::~SVGTransformable() = default; 36 37 template<typename CharacterType> static int parseTransformParamList(StringParsingBuffer<CharacterType>& buffer, float* values, int required, int optional) 35 38 { 36 39 int optionalParams = 0, requiredParams = 0; 37 40 38 if (!skipOptionalSVGSpaces( ptr, end) || *ptr != '(')41 if (!skipOptionalSVGSpaces(buffer) || *buffer != '(') 39 42 return -1; 40 43 41 ptr++;44 ++buffer; 42 45 43 skipOptionalSVGSpaces( ptr, end);46 skipOptionalSVGSpaces(buffer); 44 47 45 48 while (requiredParams < required) { 46 if ( ptr >= end)47 return -1; 48 auto parsedNumber = parseNumber( ptr, end, SuffixSkippingPolicy::DontSkip);49 if (buffer.atEnd()) 50 return -1; 51 auto parsedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 49 52 if (!parsedNumber) 50 53 return -1; … … 52 55 requiredParams++; 53 56 if (requiredParams < required) 54 skipOptionalSVGSpacesOrDelimiter( ptr, end);55 } 56 if (!skipOptionalSVGSpaces( ptr, end))57 skipOptionalSVGSpacesOrDelimiter(buffer); 58 } 59 if (!skipOptionalSVGSpaces(buffer)) 57 60 return -1; 58 61 59 bool delimParsed = skipOptionalSVGSpacesOrDelimiter( ptr, end);60 61 if ( ptr >= end)62 bool delimParsed = skipOptionalSVGSpacesOrDelimiter(buffer); 63 64 if (buffer.atEnd()) 62 65 return -1; 63 66 64 if (*ptr == ')') { // skip optionals 65 ptr++; 67 if (*buffer == ')') { 68 // skip optionals 69 ++buffer; 66 70 if (delimParsed) 67 71 return -1; 68 72 } else { 69 73 while (optionalParams < optional) { 70 if ( ptr >= end)74 if (buffer.atEnd()) 71 75 return -1; 72 auto parsedNumber = parseNumber( ptr, end, SuffixSkippingPolicy::DontSkip);76 auto parsedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); 73 77 if (!parsedNumber) 74 78 return -1; … … 76 80 optionalParams++; 77 81 if (optionalParams < optional) 78 skipOptionalSVGSpacesOrDelimiter( ptr, end);82 skipOptionalSVGSpacesOrDelimiter(buffer); 79 83 } 80 84 81 if (!skipOptionalSVGSpaces( ptr, end))85 if (!skipOptionalSVGSpaces(buffer)) 82 86 return -1; 83 87 84 delimParsed = skipOptionalSVGSpacesOrDelimiter( ptr, end);88 delimParsed = skipOptionalSVGSpacesOrDelimiter(buffer); 85 89 86 if ( ptr >= end || *ptr != ')' || delimParsed)87 return -1; 88 ptr++;90 if (buffer.atEnd() || *buffer != ')' || delimParsed) 91 return -1; 92 ++buffer; 89 93 } 90 94 … … 93 97 94 98 // These should be kept in sync with enum SVGTransformType 95 static const int requiredValuesForType[] = {0, 6, 1, 1, 1, 1, 1}; 96 static const int optionalValuesForType[] = {0, 0, 1, 1, 2, 0, 0}; 97 98 // This destructor is needed in order to link correctly with Intel ICC. 99 SVGTransformable::~SVGTransformable() = default; 100 101 Optional<SVGTransformValue> SVGTransformable::parseTransformValue(SVGTransformValue::SVGTransformType type, const UChar*& ptr, const UChar* end) 99 static constexpr int requiredValuesForType[] = { 0, 6, 1, 1, 1, 1, 1 }; 100 static constexpr int optionalValuesForType[] = { 0, 0, 1, 1, 2, 0, 0 }; 101 102 template<typename CharacterType> static Optional<SVGTransformValue> parseTransformValueGeneric(SVGTransformValue::SVGTransformType type, StringParsingBuffer<CharacterType>& buffer) 102 103 { 103 104 if (type == SVGTransformValue::SVG_TRANSFORM_UNKNOWN) … … 106 107 int valueCount = 0; 107 108 float values[] = {0, 0, 0, 0, 0, 0}; 108 if ((valueCount = parseTransformParamList( ptr, end, values, requiredValuesForType[type], optionalValuesForType[type])) < 0)109 if ((valueCount = parseTransformParamList(buffer, values, requiredValuesForType[type], optionalValuesForType[type])) < 0) 109 110 return WTF::nullopt; 110 111 … … 146 147 } 147 148 148 static const UChar skewXDesc[] = {'s', 'k', 'e', 'w', 'X'}; 149 static const UChar skewYDesc[] = {'s', 'k', 'e', 'w', 'Y'}; 150 static const UChar scaleDesc[] = {'s', 'c', 'a', 'l', 'e'}; 151 static const UChar translateDesc[] = {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', 'e'}; 152 static const UChar rotateDesc[] = {'r', 'o', 't', 'a', 't', 'e'}; 153 static const UChar matrixDesc[] = {'m', 'a', 't', 'r', 'i', 'x'}; 154 155 Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseAndSkipType(const UChar*& currTransform, const UChar* end) 156 { 157 if (currTransform >= end) 158 return WTF::nullopt; 159 160 if (*currTransform == 's') { 161 if (skipString(currTransform, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc))) 149 Optional<SVGTransformValue> SVGTransformable::parseTransformValue(SVGTransformValue::SVGTransformType type, StringParsingBuffer<LChar>& buffer) 150 { 151 return parseTransformValueGeneric(type, buffer); 152 } 153 154 Optional<SVGTransformValue> SVGTransformable::parseTransformValue(SVGTransformValue::SVGTransformType type, StringParsingBuffer<UChar>& buffer) 155 { 156 return parseTransformValueGeneric(type, buffer); 157 } 158 159 template<typename CharacterType> static constexpr CharacterType skewXDesc[] = {'s', 'k', 'e', 'w', 'X'}; 160 template<typename CharacterType> static constexpr CharacterType skewYDesc[] = {'s', 'k', 'e', 'w', 'Y'}; 161 template<typename CharacterType> static constexpr CharacterType scaleDesc[] = {'s', 'c', 'a', 'l', 'e'}; 162 template<typename CharacterType> static constexpr CharacterType translateDesc[] = {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', 'e'}; 163 template<typename CharacterType> static constexpr CharacterType rotateDesc[] = {'r', 'o', 't', 'a', 't', 'e'}; 164 template<typename CharacterType> static constexpr CharacterType matrixDesc[] = {'m', 'a', 't', 'r', 'i', 'x'}; 165 166 template<typename CharacterType> static Optional<SVGTransformValue::SVGTransformType> parseTransformTypeGeneric(StringParsingBuffer<CharacterType>& buffer) 167 { 168 if (buffer.atEnd()) 169 return WTF::nullopt; 170 171 if (*buffer == 's') { 172 if (skipCharactersExactly(buffer, skewXDesc<CharacterType>)) 162 173 return SVGTransformValue::SVG_TRANSFORM_SKEWX; 163 else if (skipString(currTransform, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc)))174 if (skipCharactersExactly(buffer, skewYDesc<CharacterType>)) 164 175 return SVGTransformValue::SVG_TRANSFORM_SKEWY; 165 else if (skipString(currTransform, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc)))176 if (skipCharactersExactly(buffer, scaleDesc<CharacterType>)) 166 177 return SVGTransformValue::SVG_TRANSFORM_SCALE; 167 else 168 return WTF::nullopt; 169 } else if (skipString(currTransform, end, translateDesc, WTF_ARRAY_LENGTH(translateDesc))) 178 return WTF::nullopt; 179 } 180 181 if (skipCharactersExactly(buffer, translateDesc<CharacterType>)) 170 182 return SVGTransformValue::SVG_TRANSFORM_TRANSLATE; 171 else if (skipString(currTransform, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc)))183 if (skipCharactersExactly(buffer, rotateDesc<CharacterType>)) 172 184 return SVGTransformValue::SVG_TRANSFORM_ROTATE; 173 else if (skipString(currTransform, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc)))185 if (skipCharactersExactly(buffer, matrixDesc<CharacterType>)) 174 186 return SVGTransformValue::SVG_TRANSFORM_MATRIX; 175 187 … … 177 189 } 178 190 179 SVGTransformValue::SVGTransformType SVGTransformable::parseTransformType(const String& typeString) 180 { 181 auto upconvertedCharacters = StringView(typeString).upconvertedCharacters(); 182 const UChar* characters = upconvertedCharacters; 183 return parseAndSkipType(characters, characters + typeString.length()).valueOr(SVGTransformValue::SVG_TRANSFORM_UNKNOWN); 184 } 185 186 } 191 Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseTransformType(StringView string) 192 { 193 return readCharactersForParsing(string, [](auto buffer) { 194 return parseTransformType(buffer); 195 }); 196 } 197 198 Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseTransformType(StringParsingBuffer<LChar>& buffer) 199 { 200 return parseTransformTypeGeneric(buffer); 201 } 202 203 Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseTransformType(StringParsingBuffer<UChar>& buffer) 204 { 205 return parseTransformTypeGeneric(buffer); 206 } 207 208 } -
trunk/Source/WebCore/svg/SVGTransformable.h
r263334 r263617 23 23 #include "SVGLocatable.h" 24 24 #include "SVGTransformValue.h" 25 #include <wtf/text/WTFString.h>26 25 27 26 namespace WebCore { … … 33 32 virtual ~SVGTransformable(); 34 33 35 static Optional<SVGTransformValue> parseTransformValue(SVGTransformValue::SVGTransformType, const UChar*& ptr, const UChar* end); 36 static SVGTransformValue::SVGTransformType parseTransformType(const String&); 37 static Optional<SVGTransformValue::SVGTransformType> parseAndSkipType(const UChar*& currTransform, const UChar* end); 34 static Optional<SVGTransformValue> parseTransformValue(SVGTransformValue::SVGTransformType, StringParsingBuffer<LChar>&); 35 static Optional<SVGTransformValue> parseTransformValue(SVGTransformValue::SVGTransformType, StringParsingBuffer<UChar>&); 36 37 static Optional<SVGTransformValue::SVGTransformType> parseTransformType(StringView); 38 static Optional<SVGTransformValue::SVGTransformType> parseTransformType(StringParsingBuffer<LChar>&); 39 static Optional<SVGTransformValue::SVGTransformType> parseTransformType(StringParsingBuffer<UChar>&); 38 40 39 41 AffineTransform localCoordinateSpaceTransform(SVGLocatable::CTMScope) const override { return animatedLocalTransform(); } -
trunk/Source/WebCore/svg/SVGViewSpec.cpp
r263334 r263617 29 29 #include "SVGTransformList.h" 30 30 #include "SVGTransformable.h" 31 #include <wtf/text/StringParsingBuffer.h> 31 32 32 33 namespace WebCore { … … 61 62 } 62 63 63 static const UCharsvgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'};64 static const UCharviewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'};65 static const UCharpreserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'};66 static const UChartransformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'};67 static const UCharzoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'};68 static const UCharviewTargetSpec[] = {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'};64 template<typename CharacterType> static constexpr CharacterType svgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'}; 65 template<typename CharacterType> static constexpr CharacterType viewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'}; 66 template<typename CharacterType> static constexpr CharacterType preserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'}; 67 template<typename CharacterType> static constexpr CharacterType transformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'}; 68 template<typename CharacterType> static constexpr CharacterType zoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'}; 69 template<typename CharacterType> static constexpr CharacterType viewTargetSpec[] = {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'}; 69 70 70 bool SVGViewSpec::parseViewSpec(const String & viewSpec)71 bool SVGViewSpec::parseViewSpec(const StringView& string) 71 72 { 72 auto upconvertedCharacters = StringView(viewSpec).upconvertedCharacters(); 73 const UChar* currViewSpec = upconvertedCharacters; 74 const UChar* end = currViewSpec + viewSpec.length(); 73 return readCharactersForParsing(string, [&](auto buffer) -> bool { 74 using CharacterType = typename decltype(buffer)::CharacterType; 75 75 76 if (currViewSpec >= end|| !m_contextElement)77 return false;76 if (buffer.atEnd() || !m_contextElement) 77 return false; 78 78 79 if (!skipString(currViewSpec, end, svgViewSpec, WTF_ARRAY_LENGTH(svgViewSpec)))80 return false;79 if (!skipCharactersExactly(buffer, svgViewSpec<CharacterType>)) 80 return false; 81 81 82 if (currViewSpec >= end || *currViewSpec != '(') 83 return false; 84 currViewSpec++; 82 if (!skipExactly(buffer, '(')) 83 return false; 85 84 86 while (currViewSpec < end && *currViewSpec != ')') { 87 if (*currViewSpec == 'v') { 88 if (skipString(currViewSpec, end, viewBoxSpec, WTF_ARRAY_LENGTH(viewBoxSpec))) { 89 if (currViewSpec >= end || *currViewSpec != '(') 85 while (buffer.hasCharactersRemaining() && *buffer != ')') { 86 if (*buffer == 'v') { 87 if (skipCharactersExactly(buffer, viewBoxSpec<CharacterType>)) { 88 if (!skipExactly(buffer, '(')) 89 return false; 90 auto viewBox = SVGFitToViewBox::parseViewBox(buffer, false); 91 if (!viewBox) 92 return false; 93 setViewBox(WTFMove(*viewBox)); 94 if (!skipExactly(buffer, ')')) 95 return false; 96 } else if (skipCharactersExactly(buffer, viewTargetSpec<CharacterType>)) { 97 if (!skipExactly(buffer, '(')) 98 return false; 99 auto viewTargetStart = buffer.position(); 100 skipUntil(buffer, ')'); 101 if (buffer.atEnd()) 102 return false; 103 m_viewTargetString = String(viewTargetStart, buffer.position() - viewTargetStart); 104 ++buffer; 105 } else 90 106 return false; 91 currViewSpec++; 92 auto viewBox = SVGFitToViewBox::parseViewBox(currViewSpec, end, false); 93 if (!viewBox) 107 } else if (*buffer == 'z') { 108 if (!skipCharactersExactly(buffer, zoomAndPanSpec<CharacterType>)) 94 109 return false; 95 setViewBox(WTFMove(*viewBox)); 96 if (currViewSpec >= end || *currViewSpec != ')') 110 if (!skipExactly(buffer, '(')) 97 111 return false; 98 currViewSpec++; 99 } else if (skipString(currViewSpec, end, viewTargetSpec, WTF_ARRAY_LENGTH(viewTargetSpec))) { 100 if (currViewSpec >= end || *currViewSpec != '(') 112 auto zoomAndPan = SVGZoomAndPan::parseZoomAndPan(buffer); 113 if (!zoomAndPan) 101 114 return false; 102 const UChar* viewTargetStart = ++currViewSpec; 103 while (currViewSpec < end && *currViewSpec != ')') 104 currViewSpec++; 105 if (currViewSpec >= end) 115 setZoomAndPan(*zoomAndPan); 116 if (!skipExactly(buffer, ')')) 106 117 return false; 107 m_viewTargetString = String(viewTargetStart, currViewSpec - viewTargetStart); 108 currViewSpec++; 118 } else if (*buffer == 'p') { 119 if (!skipCharactersExactly(buffer, preserveAspectRatioSpec<CharacterType>)) 120 return false; 121 if (!skipExactly(buffer, '(')) 122 return false; 123 SVGPreserveAspectRatioValue preserveAspectRatio; 124 if (!preserveAspectRatio.parse(buffer, false)) 125 return false; 126 setPreserveAspectRatio(preserveAspectRatio); 127 if (!skipExactly(buffer, ')')) 128 return false; 129 } else if (*buffer == 't') { 130 if (!skipCharactersExactly(buffer, transformSpec<CharacterType>)) 131 return false; 132 if (!skipExactly(buffer, '(')) 133 return false; 134 m_transform->parse(buffer); 135 if (!skipExactly(buffer, ')')) 136 return false; 109 137 } else 110 138 return false; 111 } else if (*currViewSpec == 'z') { 112 if (!skipString(currViewSpec, end, zoomAndPanSpec, WTF_ARRAY_LENGTH(zoomAndPanSpec))) 113 return false; 114 if (currViewSpec >= end || *currViewSpec != '(') 115 return false; 116 currViewSpec++; 117 if (!SVGZoomAndPan::parseZoomAndPan(currViewSpec, end)) 118 return false; 119 if (currViewSpec >= end || *currViewSpec != ')') 120 return false; 121 currViewSpec++; 122 } else if (*currViewSpec == 'p') { 123 if (!skipString(currViewSpec, end, preserveAspectRatioSpec, WTF_ARRAY_LENGTH(preserveAspectRatioSpec))) 124 return false; 125 if (currViewSpec >= end || *currViewSpec != '(') 126 return false; 127 currViewSpec++; 128 SVGPreserveAspectRatioValue preserveAspectRatio; 129 if (!preserveAspectRatio.parse(currViewSpec, end, false)) 130 return false; 131 setPreserveAspectRatio(preserveAspectRatio); 132 if (currViewSpec >= end || *currViewSpec != ')') 133 return false; 134 currViewSpec++; 135 } else if (*currViewSpec == 't') { 136 if (!skipString(currViewSpec, end, transformSpec, WTF_ARRAY_LENGTH(transformSpec))) 137 return false; 138 if (currViewSpec >= end || *currViewSpec != '(') 139 return false; 140 currViewSpec++; 141 m_transform->parse(currViewSpec, end); 142 if (currViewSpec >= end || *currViewSpec != ')') 143 return false; 144 currViewSpec++; 145 } else 139 140 skipExactly(buffer, ';'); 141 } 142 143 if (buffer.atEnd() || *buffer != ')') 146 144 return false; 147 145 148 if (currViewSpec < end && *currViewSpec == ';') 149 currViewSpec++; 150 } 151 152 if (currViewSpec >= end || *currViewSpec != ')') 153 return false; 154 155 return true; 146 return true; 147 }); 156 148 } 157 149 -
trunk/Source/WebCore/svg/SVGViewSpec.h
r244115 r263617 37 37 } 38 38 39 bool parseViewSpec(const String &);39 bool parseViewSpec(const StringView&); 40 40 void reset(); 41 41 void resetContextElement() { m_contextElement = nullptr; } -
trunk/Source/WebCore/svg/SVGZoomAndPan.cpp
r254703 r263617 23 23 #include "SVGZoomAndPan.h" 24 24 25 #include <wtf/text/StringConcatenateNumbers.h>26 27 25 namespace WebCore { 28 26 29 bool SVGZoomAndPan::parseZoomAndPan(const UChar*& start, const UChar* end) 27 template<typename CharacterType> static constexpr CharacterType disable[] = { 'd', 'i', 's', 'a', 'b', 'l', 'e' }; 28 template<typename CharacterType> static constexpr CharacterType magnify[] = { 'm', 'a', 'g', 'n', 'i', 'f', 'y' }; 29 30 template<typename CharacterType> static Optional<SVGZoomAndPanType> parseZoomAndPanGeneric(StringParsingBuffer<CharacterType>& buffer) 30 31 { 31 static const UChar disable[] = { 'd', 'i', 's', 'a', 'b', 'l', 'e' }; 32 if (skipString(start, end, disable, WTF_ARRAY_LENGTH(disable))) { 33 m_zoomAndPan = SVGZoomAndPanDisable; 34 return true; 35 } 32 if (skipCharactersExactly(buffer, disable<CharacterType>)) 33 return SVGZoomAndPanDisable; 36 34 37 static const UChar magnify[] = { 'm', 'a', 'g', 'n', 'i', 'f', 'y' }; 38 if (skipString(start, end, magnify, WTF_ARRAY_LENGTH(magnify))) { 39 m_zoomAndPan = SVGZoomAndPanMagnify; 40 return true; 41 } 35 if (skipCharactersExactly(buffer, magnify<CharacterType>)) 36 return SVGZoomAndPanMagnify; 42 37 43 return false; 38 return WTF::nullopt; 39 } 40 41 Optional<SVGZoomAndPanType> SVGZoomAndPan::parseZoomAndPan(StringParsingBuffer<LChar>& buffer) 42 { 43 return parseZoomAndPanGeneric(buffer); 44 } 45 46 Optional<SVGZoomAndPanType> SVGZoomAndPan::parseZoomAndPan(StringParsingBuffer<UChar>& buffer) 47 { 48 return parseZoomAndPanGeneric(buffer); 44 49 } 45 50 -
trunk/Source/WebCore/svg/SVGZoomAndPan.h
r246490 r263617 49 49 SVGZoomAndPan() = default; 50 50 51 bool parseZoomAndPan(const UChar*&, const UChar*); 51 static Optional<SVGZoomAndPanType> parseZoomAndPan(StringParsingBuffer<LChar>&); 52 static Optional<SVGZoomAndPanType> parseZoomAndPan(StringParsingBuffer<UChar>&); 52 53 53 54 private:
Note: See TracChangeset
for help on using the changeset viewer.