From 3266afc07a2f0ccceb0e34f505dc4529b370e73c Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Thu, 23 May 2019 18:40:56 +0700 Subject: [PATCH 1/5] Fix #395: improvements for SVGParser for readData, flags for 'a' path segment type may not be separated properly --- Source/svg/SVGParser.swift | 47 ++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 904a7470..a831fb0a 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -1625,7 +1625,7 @@ private class PathDataReader { return [PathSegment(type: type)] } var result = [PathSegment]() - let data = readData() + let data = readData(type: type) var index = 0 var isFirstSegment = true while index < data.count { @@ -1651,11 +1651,11 @@ private class PathDataReader { return nil } - private func readData() -> [Double] { + private func readData(type: PathSegmentType) -> [Double] { var data = [Double]() while true { skipSpaces() - if let value = readNum() { + if let value = readNum(type: type, index: data.count) { data.append(value) } else { return data @@ -1670,21 +1670,38 @@ private class PathDataReader { } } - fileprivate func readNum() -> Double? { + fileprivate func readNum(type: PathSegmentType, index: Int) -> Double? { guard let ch = current else { - return nil + return .none } - if (ch >= "0" && ch <= "9") || ch == "." || ch == "-" { - var chars = [ch] - var hasDot = ch == "." - while let ch = readDigit(&hasDot) { - chars.append(ch) - } - var buf = "" - buf.unicodeScalars.append(contentsOf: chars) - return Double(buf) + + guard ch >= "0" && ch <= "9" || ch == "." || ch == "-" else { + return .none } - return nil + + var chars = [ch] + var hasDot = ch == "." + let isFlag = type == .a && (index == 3 || index == 4) + + while let ch = readDigit(&hasDot), !isFlag { + chars.append(ch) + } + + var buf = "" + buf.unicodeScalars.append(contentsOf: chars) + guard let value = Double(buf) else { + return .none + } + + guard isFlag else { + return value + } + + guard value == 0 || value == 1 else { + return .none + } + + return value } fileprivate func readDigit(_ hasDot: inout Bool) -> UnicodeScalar? { From 86cef55ef83a2fe0f5b70dba0256b19f31b5b88b Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Thu, 23 May 2019 18:50:46 +0700 Subject: [PATCH 2/5] Fix #395: add svg test for paths-data-20-f-manual --- Macaw.xcodeproj/project.pbxproj | 12 +- MacawTests/MacawSVGTests.swift | 4 + .../paths-data-20-f-manual.reference | 793 ++++++++++++++++++ .../w3cSVGTests/paths-data-20-f-manual.svg | 87 ++ 4 files changed, 894 insertions(+), 2 deletions(-) create mode 100644 MacawTests/w3cSVGTests/paths-data-20-f-manual.reference create mode 100644 MacawTests/w3cSVGTests/paths-data-20-f-manual.svg diff --git a/Macaw.xcodeproj/project.pbxproj b/Macaw.xcodeproj/project.pbxproj index 51617a0c..24128d66 100644 --- a/Macaw.xcodeproj/project.pbxproj +++ b/Macaw.xcodeproj/project.pbxproj @@ -512,6 +512,8 @@ A74C81ED229284790085A832 /* struct-use-01-t-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C81EB229284780085A832 /* struct-use-01-t-manual.svg */; }; A74C81F12292B3940085A832 /* color-prop-05-t-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C81F02292B3940085A832 /* color-prop-05-t-manual.svg */; }; A74C81F32292B45E0085A832 /* color-prop-05-t-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C81F22292B45D0085A832 /* color-prop-05-t-manual.reference */; }; + A74C82032296BE5F0085A832 /* paths-data-20-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C82022296BE5F0085A832 /* paths-data-20-f-manual.svg */; }; + A74C82052296BFC60085A832 /* paths-data-20-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C82042296BFC60085A832 /* paths-data-20-f-manual.reference */; }; A7E675561EC4213500BD9ECB /* NodeBoundsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */; }; C410148E1F834D290022EE44 /* style.svg in Resources */ = {isa = PBXBuildFile; fileRef = C410148D1F834D280022EE44 /* style.svg */; }; C4153A8F1F8793DE001BA5EE /* small-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = C4153A8E1F8793DD001BA5EE /* small-logo.png */; }; @@ -927,10 +929,12 @@ A718CD4B1F45C28F00966E06 /* MDisplayLink_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MDisplayLink_macOS.swift; path = Source/platform/macOS/MDisplayLink_macOS.swift; sourceTree = SOURCE_ROOT; }; A718CD4C1F45C28F00966E06 /* MView_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MView_macOS.swift; path = Source/platform/macOS/MView_macOS.swift; sourceTree = SOURCE_ROOT; }; A718CD511F45C2A400966E06 /* MBezierPath+Extension_macOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "MBezierPath+Extension_macOS.swift"; path = "Source/platform/macOS/MBezierPath+Extension_macOS.swift"; sourceTree = SOURCE_ROOT; }; - A74C81F02292B3940085A832 /* color-prop-05-t-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-05-t-manual.svg"; sourceTree = ""; }; - A74C81F22292B45D0085A832 /* color-prop-05-t-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-05-t-manual.reference"; sourceTree = ""; }; A74C81EA229284780085A832 /* struct-use-01-t-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "struct-use-01-t-manual.reference"; sourceTree = ""; }; A74C81EB229284780085A832 /* struct-use-01-t-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "struct-use-01-t-manual.svg"; sourceTree = ""; }; + A74C81F02292B3940085A832 /* color-prop-05-t-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-05-t-manual.svg"; sourceTree = ""; }; + A74C81F22292B45D0085A832 /* color-prop-05-t-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-05-t-manual.reference"; sourceTree = ""; }; + A74C82022296BE5F0085A832 /* paths-data-20-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "paths-data-20-f-manual.svg"; sourceTree = ""; }; + A74C82042296BFC60085A832 /* paths-data-20-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "paths-data-20-f-manual.reference"; sourceTree = ""; }; A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NodeBoundsTests.swift; path = Bounds/NodeBoundsTests.swift; sourceTree = ""; }; C410148D1F834D280022EE44 /* style.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = style.svg; sourceTree = ""; }; C4153A8E1F8793DD001BA5EE /* small-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "small-logo.png"; sourceTree = ""; }; @@ -1492,6 +1496,8 @@ 5BFEF5D420BC1C1E008DAC11 /* paths-data-18-f-manual.svg */, 5B1AE1D720B6A669007EECCB /* paths-data-19-f-manual.reference */, 5B1AE21A20B6A669007EECCB /* paths-data-19-f-manual.svg */, + A74C82022296BE5F0085A832 /* paths-data-20-f-manual.svg */, + A74C82042296BFC60085A832 /* paths-data-20-f-manual.reference */, 5B37139620BE95D7004BB6EE /* pservers-grad-01-b-manual.reference */, 5B37139220BE95D6004BB6EE /* pservers-grad-01-b-manual.svg */, 5B37139320BE95D6004BB6EE /* pservers-grad-02-b-manual.reference */, @@ -1815,6 +1821,7 @@ 5B1AE29C20B6A669007EECCB /* paths-data-01-t-manual.reference in Resources */, 5B1AE29320B6A669007EECCB /* coords-trans-09-t-manual.svg in Resources */, 5B1AE2DC20B6A669007EECCB /* struct-defs-01-t-manual.svg in Resources */, + A74C82052296BFC60085A832 /* paths-data-20-f-manual.reference in Resources */, 5B1AE29020B6A669007EECCB /* painting-stroke-08-t-manual.svg in Resources */, 5B1AE2A720B6A669007EECCB /* paths-data-09-t-manual.svg in Resources */, 5B1AE2AB20B6A669007EECCB /* painting-stroke-08-t-manual.reference in Resources */, @@ -1868,6 +1875,7 @@ 5B1AE2D120B6A669007EECCB /* paths-data-03-f-manual.reference in Resources */, 5B1AE28920B6A669007EECCB /* shapes-intro-01-t-manual.reference in Resources */, 5B1AE2C020B6A669007EECCB /* paths-data-14-t-manual.reference in Resources */, + A74C82032296BE5F0085A832 /* paths-data-20-f-manual.svg in Resources */, 5B1AE27420B6A669007EECCB /* color-prop-02-f-manual.svg in Resources */, 5B1AE25120B6A669007EECCB /* coords-trans-05-t-manual.reference in Resources */, 5B1AE29120B6A669007EECCB /* coords-transformattr-01-f-manual.svg in Resources */, diff --git a/MacawTests/MacawSVGTests.swift b/MacawTests/MacawSVGTests.swift index 97a25ac9..039cc47d 100644 --- a/MacawTests/MacawSVGTests.swift +++ b/MacawTests/MacawSVGTests.swift @@ -529,6 +529,10 @@ class MacawSVGTests: XCTestCase { validateJSON("paths-data-19-f-manual") } + func testPathsData20() { + validateJSON("paths-data-20-f-manual") + } + func testStructGroup01() { validateJSON("struct-group-01-t-manual") } diff --git a/MacawTests/w3cSVGTests/paths-data-20-f-manual.reference b/MacawTests/w3cSVGTests/paths-data-20-f-manual.reference new file mode 100644 index 00000000..c9be2934 --- /dev/null +++ b/MacawTests/w3cSVGTests/paths-data-20-f-manual.reference @@ -0,0 +1,793 @@ +{ + "contents" : [ + { + "contents" : [ + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 120, + 120 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 0, + -25, + 25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 120, + 120 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 0, + -25, + 25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 200, + 120 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 1, + 25, + 25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 200, + 120 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 1, + 25, + 25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 280, + 120 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 0, + -25, + 25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 280, + 120 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 360, + 120 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 1, + 25, + 25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 360, + 120 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 120, + 200 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 1, + -25, + -25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 120, + 200 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 1, + -25, + -25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 200, + 200 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 0, + 25, + -25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 200, + 200 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 280, + 200 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 1, + -25, + -25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 280, + 200 + ], + "type" : "M" + }, + { + "data" : [ + 25 + ], + "type" : "h" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "segments" : [ + { + "data" : [ + 360, + 200 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + 25, + 25, + 0, + 1, + 0, + 25, + -25 + ], + "type" : "a" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "segments" : [ + { + "data" : [ + 360, + 200 + ], + "type" : "M" + }, + { + "data" : [ + -25 + ], + "type" : "h" + }, + { + "data" : [ + + ], + "type" : "z" + } + ], + "type" : "Path" + }, + "node" : "Shape" + } + ], + "node" : "Group" + }, + { + "contents" : [ + { + "align" : "min", + "baseline" : "bottom", + "fill" : { + "type" : "Color", + "val" : 0 + }, + "font" : { + "name" : "SVGFreeSansASCII,sans-serif", + "size" : 32, + "weight" : "normal" + }, + "node" : "Text", + "place" : "1, 0, 0, 1, 10, 340", + "text" : "$Revision: 1.3 $" + } + ], + "node" : "Group" + }, + { + "form" : { + "h" : 358, + "type" : "Rect", + "w" : 478, + "x" : 1, + "y" : 1 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + } + ], + "layout" : { + "scalingMode" : "meet", + "svgSize" : { + "height" : "100.0%", + "width" : "100.0%" + }, + "viewBox" : { + "h" : 360, + "type" : "Rect", + "w" : 480, + "x" : 0, + "y" : 0 + }, + "xAligningMode" : "mid", + "yAligningMode" : "mid" + }, + "node" : "Canvas" +} \ No newline at end of file diff --git a/MacawTests/w3cSVGTests/paths-data-20-f-manual.svg b/MacawTests/w3cSVGTests/paths-data-20-f-manual.svg new file mode 100644 index 00000000..ed643bce --- /dev/null +++ b/MacawTests/w3cSVGTests/paths-data-20-f-manual.svg @@ -0,0 +1,87 @@ + + + + + + + + + + +

+ Tests parsing of the elliptical arc path syntax. +

+ + +

+ Run the test. No interaction required. +

+
+ +

+ The test has passed if the image looks as if there are eight green circles that have + two white rectangles overlapping them, like in the reference image. If any red is visible + the test has failed. +

+
+ + $RCSfile: paths-data-20-f.svg,v $ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Revision: 1.3 $ + + + + From 018bca18c0a318a8bc6c2fafb17da652a645cd4a Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Thu, 23 May 2019 18:53:20 +0700 Subject: [PATCH 3/5] Fix #395: update w3c-svg-test-suite --- MacawTests/w3c-test-suite.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MacawTests/w3c-test-suite.md b/MacawTests/w3c-test-suite.md index 4d15d351..111fc7ba 100644 --- a/MacawTests/w3c-test-suite.md +++ b/MacawTests/w3c-test-suite.md @@ -10,12 +10,12 @@ There are [521 SVG tests](https://github.com/web-platform-tests/wpt/tree/master/ * [switch/object](https://www.w3.org/TR/SVG11/backward.html) (7) The rest 306 tests can be split into following categories: -* 31.4% passed (96) +* 31.7% passed (97) * 14.1% filters (43) [#390](https://github.com/exyte/Macaw/issues/390) * 7.8% images (24) [wpt issue](https://github.com/web-platform-tests/wpt/issues/11178) * 2.6% markers (8) [#392](https://github.com/exyte/Macaw/issues/392) * 19.9% text (61) [#391](https://github.com/exyte/Macaw/issues/391) -* 24.5% blocked by issues (75) +* 24.2% blocked by issues (75) Status of each test: @@ -183,7 +183,7 @@ Status of each test: |[paths-data-17-f-manual](w3cSVGTests/paths-data-17-f-manual.svg) | ✅ | |[paths-data-18-f-manual](w3cSVGTests/paths-data-18-f-manual.svg) | ✅ | |[paths-data-19-f-manual](w3cSVGTests/paths-data-19-f-manual.svg) | ✅ | -|[paths-data-20-f-manual](w3cSVGTests/paths-data-20-f-manual.svg) | [#395](https://github.com/exyte/Macaw/issues/395) | +|[paths-data-20-f-manual](w3cSVGTests/paths-data-20-f-manual.svg) | ✅ | |[pservers-grad-01-b-manual](w3cSVGTests/pservers-grad-01-b-manual.svg) | ✅ | |[pservers-grad-02-b-manual](w3cSVGTests/pservers-grad-02-b-manual.svg) | ✅ | |[pservers-grad-03-b-manual](w3cSVGTests/pservers-grad-03-b-manual.svg) | ✅ | From 8affa6f988825f6051588861146b9331df350da7 Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Thu, 23 May 2019 19:18:25 +0700 Subject: [PATCH 4/5] Fix #395: add type == .A --- Source/svg/SVGParser.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index a831fb0a..2ddc0642 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -1681,7 +1681,7 @@ private class PathDataReader { var chars = [ch] var hasDot = ch == "." - let isFlag = type == .a && (index == 3 || index == 4) + let isFlag = (type == .a || type == .A) && (index == 3 || index == 4) while let ch = readDigit(&hasDot), !isFlag { chars.append(ch) @@ -1692,15 +1692,12 @@ private class PathDataReader { guard let value = Double(buf) else { return .none } - guard isFlag else { return value } - guard value == 0 || value == 1 else { return .none } - return value } From 0d5a5136da5574472720337131500f4691fc1996 Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Fri, 24 May 2019 16:07:34 +0700 Subject: [PATCH 5/5] Fix #395: improvements readSegments for A,a --- Source/svg/SVGParser.swift | 65 +++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 2ddc0642..26140633 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -1610,7 +1610,7 @@ private class PathDataReader { } public func read() -> [PathSegment] { - _ = readNext() + readNext() var segments = [PathSegment]() while let array = readSegments() { segments.append(contentsOf: array) @@ -1625,7 +1625,12 @@ private class PathDataReader { return [PathSegment(type: type)] } var result = [PathSegment]() - let data = readData(type: type) + let data: [Double] + if type == .a || type == .A { + data = readDataOfASegment() + } else { + data = readData() + } var index = 0 var isFirstSegment = true while index < data.count { @@ -1651,11 +1656,11 @@ private class PathDataReader { return nil } - private func readData(type: PathSegmentType) -> [Double] { + private func readData() -> [Double] { var data = [Double]() while true { skipSpaces() - if let value = readNum(type: type, index: data.count) { + if let value = readNum() { data.append(value) } else { return data @@ -1663,6 +1668,28 @@ private class PathDataReader { } } + private func readDataOfASegment() -> [Double] { + let argCount = getArgCount(segment: .A) + var data: [Double] = [] + var index = 0 + while true { + skipSpaces() + let value: Double? + let indexMod = index % argCount + if indexMod == 3 || indexMod == 4 { + value = readFlag() + } else { + value = readNum() + } + guard let doubleValue = value else { + return data + } + data.append(doubleValue) + index += 1 + } + return data + } + private func skipSpaces() { var ch = current while ch != nil && "\n\r\t ,".contains(String(ch!)) { @@ -1670,7 +1697,22 @@ private class PathDataReader { } } - fileprivate func readNum(type: PathSegmentType, index: Int) -> Double? { + private func readFlag() -> Double? { + guard let ch = current else { + return .none + } + readNext() + switch ch { + case "0": + return 0 + case "1": + return 1 + default: + return .none + } + } + + fileprivate func readNum() -> Double? { guard let ch = current else { return .none } @@ -1681,9 +1723,7 @@ private class PathDataReader { var chars = [ch] var hasDot = ch == "." - let isFlag = (type == .a || type == .A) && (index == 3 || index == 4) - - while let ch = readDigit(&hasDot), !isFlag { + while let ch = readDigit(&hasDot) { chars.append(ch) } @@ -1692,12 +1732,6 @@ private class PathDataReader { guard let value = Double(buf) else { return .none } - guard isFlag else { - return value - } - guard value == 0 || value == 1 else { - return .none - } return value } @@ -1728,6 +1762,7 @@ private class PathDataReader { return false } + @discardableResult private func readNext() -> UnicodeScalar? { previous = current current = iterator.next() @@ -1744,7 +1779,7 @@ private class PathDataReader { private func readSegmentType() -> PathSegmentType? { while true { if let type = getPathSegmentType() { - _ = readNext() + readNext() return type } if readNext() == nil {