From b3234d8f8b995a53de6474e4db1e811b8f3377d8 Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Thu, 6 Jun 2019 17:09:02 +0700 Subject: [PATCH 01/10] improve decodableFormat for image --- Source/model/scene/Image.swift | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/model/scene/Image.swift b/Source/model/scene/Image.swift index 8f9cbfe9..a04ff3d7 100644 --- a/Source/model/scene/Image.swift +++ b/Source/model/scene/Image.swift @@ -150,7 +150,7 @@ open class Image: Node { } // Base64 image - let decodableFormat = ["image/png", "image/jpg", "image/svg+xml"] + let decodableFormat = ["image/png", "image/jpg", "image/jpeg"] for format in decodableFormat { let prefix = "data:\(format);base64," if src.hasPrefix(prefix) { @@ -163,10 +163,6 @@ open class Image: Node { } } - #if os(iOS) - return MImage(named: src) - #elseif os(OSX) - return MImage(contentsOfFile: src) - #endif + return MImage(named: src) ?? MImage(contentsOfFile: src) } } From a0b0fe6edf087cd7703049384e28a57f0c768e9e Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Mon, 10 Jun 2019 20:28:40 +0700 Subject: [PATCH 02/10] #203 improve pattern filling --- Source/svg/SVGParser.swift | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 0310c786..a8b0ee05 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -370,6 +370,10 @@ open class SVGParser { let w = getDoubleValue(element, attribute: "width") ?? parentPattern?.bounds.w ?? 0 let h = getDoubleValue(element, attribute: "height") ?? parentPattern?.bounds.h ?? 0 let bounds = Rect(x: x, y: y, w: w, h: h) + + guard bounds.w > 0 && bounds.h > 0 else { + return .none + } var userSpace = parentPattern?.userSpace ?? false if let units = element.allAttributes["patternUnits"]?.text, units == "userSpaceOnUse" { @@ -398,8 +402,12 @@ open class SVGParser { } contentNode = Group(contents: shapes) } + + if let contentNode = contentNode { + return UserSpacePattern(content: contentNode, bounds: bounds, userSpace: userSpace, contentUserSpace: contentUserSpace) + } - return UserSpacePattern(content: contentNode!, bounds: bounds, userSpace: userSpace, contentUserSpace: contentUserSpace) + return .none } fileprivate func parseGroup(_ group: XMLIndexer, style: [String: String]) throws -> Group? { @@ -653,7 +661,11 @@ open class SVGParser { if let pattern = defPatterns[colorId] { return getPatternFill(pattern: pattern, locus: locus) } + if let fallbackColor = fillColor.split(separator: " ").last { + fillColor = String(fallbackColor) + } } + if fillColor == SVGKeys.currentColor, let currentColor = groupStyle[SVGKeys.color] { fillColor = currentColor } @@ -1392,7 +1404,7 @@ open class SVGParser { fileprivate func parseIdFromUrl(_ urlString: String) -> String? { if urlString.hasPrefix("url") { - return urlString.substringWithOffset(fromStart: 5, fromEnd: 1) + return urlString.slice(from: "(#", to: ")") } return .none } @@ -1881,6 +1893,14 @@ fileprivate extension String { let end = index(endIndex, offsetBy: -fromEnd) return String(self[start.. String? { + return (range(of: from)?.upperBound).flatMap { substringFrom in + (range(of: to, range: substringFrom.. Date: Mon, 10 Jun 2019 20:45:51 +0700 Subject: [PATCH 03/10] #203 add svg test for pservers-pattern-03-f-manual --- Macaw.xcodeproj/project.pbxproj | 8 + MacawTests/MacawSVGTests.swift | 121 ++++--- .../pservers-pattern-03-f-manual.reference | 342 ++++++++++++++++++ .../pservers-pattern-03-f-manual.svg | 91 +++++ 4 files changed, 503 insertions(+), 59 deletions(-) create mode 100644 MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.reference create mode 100644 MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.svg diff --git a/Macaw.xcodeproj/project.pbxproj b/Macaw.xcodeproj/project.pbxproj index 8eaf5d54..6321f54f 100644 --- a/Macaw.xcodeproj/project.pbxproj +++ b/Macaw.xcodeproj/project.pbxproj @@ -670,6 +670,8 @@ A74C8326229EB77B0085A832 /* masking-path-13-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C8325229EB77B0085A832 /* masking-path-13-f-manual.reference */; }; A74C832C229FB7690085A832 /* color-prop-04-t-manual-osx.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C832B229FB7690085A832 /* color-prop-04-t-manual-osx.svg */; }; A74C832E229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */; }; + A75A2F5922AE92B40056A89D /* pservers-pattern-03-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */; }; + A75A2F5B22AE96050056A89D /* pservers-pattern-03-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F5A22AE96050056A89D /* pservers-pattern-03-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 */; }; @@ -1248,6 +1250,8 @@ A74C8325229EB77B0085A832 /* masking-path-13-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-path-13-f-manual.reference"; sourceTree = ""; }; A74C832B229FB7690085A832 /* color-prop-04-t-manual-osx.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.svg"; sourceTree = ""; }; A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.reference"; sourceTree = ""; }; + A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-03-f-manual.svg"; sourceTree = ""; }; + A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-03-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 = ""; }; @@ -1979,6 +1983,8 @@ A74C82DB229E35D20085A832 /* pservers-grad-24-f-manual.svg */, 5B1AE1F020B6A669007EECCB /* pservers-grad-stops-01-f-manual.reference */, 5B1AE1EB20B6A669007EECCB /* pservers-grad-stops-01-f-manual.svg */, + A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */, + A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */, 5B1AE1A220B6A669007EECCB /* render-elems-01-t-manual.reference */, 5B1AE1E920B6A669007EECCB /* render-elems-01-t-manual.svg */, 5B1AE19020B6A669007EECCB /* render-elems-02-t-manual.reference */, @@ -2518,6 +2524,7 @@ 5B1AE26020B6A669007EECCB /* shapes-polygon-02-t-manual.reference in Resources */, 4295959022A0F7CE00869079 /* painting-control-02-f-manual.png in Resources */, 5B1AE2AA20B6A669007EECCB /* struct-frag-03-t-manual.svg in Resources */, + A75A2F5922AE92B40056A89D /* pservers-pattern-03-f-manual.svg in Resources */, 5B1AE24720B6A669007EECCB /* painting-stroke-01-t-manual.reference in Resources */, 5B1AE29B20B6A669007EECCB /* shapes-line-01-t-manual.reference in Resources */, 429595A722A0F7CE00869079 /* paths-data-08-t-manual.png in Resources */, @@ -2620,6 +2627,7 @@ 5B1AE27C20B6A669007EECCB /* shapes-rect-04-f-manual.svg in Resources */, 5B1AE2DB20B6A669007EECCB /* color-prop-01-b-manual.reference in Resources */, 4295959122A0F7CE00869079 /* coords-coord-02-t-manual.png in Resources */, + A75A2F5B22AE96050056A89D /* pservers-pattern-03-f-manual.reference in Resources */, 4295958022A0F7CE00869079 /* coords-trans-04-t-manual.png in Resources */, 42DB451422A52A4200091DC6 /* pservers-grad-22-b-manual.png in Resources */, 5B1AE2BF20B6A669007EECCB /* shapes-ellipse-02-t-manual.reference in Resources */, diff --git a/MacawTests/MacawSVGTests.swift b/MacawTests/MacawSVGTests.swift index fb22ef30..5eba94fb 100644 --- a/MacawTests/MacawSVGTests.swift +++ b/MacawTests/MacawSVGTests.swift @@ -136,6 +136,65 @@ class MacawSVGTests: XCTestCase { } } + func getImage(from svgName: String) -> MImage { + let bundle = Bundle(for: type(of: TestUtils())) + do { + let node = try SVGParser.parse(resource: svgName, fromBundle: bundle) + + var frame = node.bounds + if frame == nil, let group = node as? Group { + frame = Group(contents: group.contents).bounds + } + + let image = node.toNativeImage(size: frame?.size() ?? Size.init(w: 100, h: 100)) + return image + } catch { + XCTFail(error.localizedDescription) + } + + XCTFail() + return MImage() + } + + func saveImage(image: MImage, fileName: String) { + #if os(OSX) + guard let data = image.tiffRepresentation else { + return + } + #endif + + #if os(iOS) + guard let data = image.pngData() else { + return + } + #endif + + let _ = writeToFile(data: data, fileName: "\(fileName).png") + } + + fileprivate func setupTestFolderDirectory() { + guard let myDocuments = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { + return + } + + let testDirectoryPath = myDocuments.appendingPathComponent("\(testFolderName)") + + do { + if !multipleTestsWillRun { + try FileManager.default.removeItem(at: testDirectoryPath) + } + + var isDirectory: ObjCBool = ObjCBool(true) + if !FileManager.default.fileExists(atPath: testDirectoryPath.absoluteString, isDirectory: &isDirectory) { + try FileManager.default.createDirectory(at: testDirectoryPath, withIntermediateDirectories: true, attributes: .none) + } + } catch { + XCTFail(error.localizedDescription) + return + } + } + + func testViewBox() { validate("viewBox") } @@ -199,12 +258,11 @@ class MacawSVGTests: XCTestCase { if nodeContent != referenceContent { XCTFail("nodeContent is not equal to referenceContent") } - - let nativeImage = getImage(from: referenceFile) //To save new PNG image for test, uncomment this //saveImage(image: nativeImage, fileName: referenceFile) #if os(OSX) + let nativeImage = getImage(from: referenceFile) if shouldComparePNGImages { validateImage(nodeImage: nativeImage, referenceFile: referenceFile) } @@ -814,62 +872,7 @@ class MacawSVGTests: XCTestCase { validateJSON("masking-mask-02-f-manual") } - func getImage(from svgName: String) -> MImage { - let bundle = Bundle(for: type(of: TestUtils())) - do { - let node = try SVGParser.parse(resource: svgName, fromBundle: bundle) - - var frame = node.bounds - if frame == nil, let group = node as? Group { - frame = Group(contents: group.contents).bounds - } - - let image = node.toNativeImage(size: frame?.size() ?? Size.init(w: 100, h: 100)) - return image - } catch { - XCTFail(error.localizedDescription) - } - - XCTFail() - return MImage() + func testPserversPattern03() { + validateJSON("pservers-pattern-03-f-manual") } - - func saveImage(image: MImage, fileName: String) { - #if os(OSX) - guard let data = image.tiffRepresentation else { - return - } - #endif - - #if os(iOS) - guard let data = image.pngData() else { - return - } - #endif - - let _ = writeToFile(data: data, fileName: "\(fileName).png") - } - - fileprivate func setupTestFolderDirectory() { - guard let myDocuments = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { - return - } - - let testDirectoryPath = myDocuments.appendingPathComponent("\(testFolderName)") - - do { - if !multipleTestsWillRun { - try FileManager.default.removeItem(at: testDirectoryPath) - } - - var isDirectory: ObjCBool = ObjCBool(true) - if !FileManager.default.fileExists(atPath: testDirectoryPath.absoluteString, isDirectory: &isDirectory) { - try FileManager.default.createDirectory(at: testDirectoryPath, withIntermediateDirectories: true, attributes: .none) - } - } catch { - XCTFail(error.localizedDescription) - return - } - } - } diff --git a/MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.reference b/MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.reference new file mode 100644 index 00000000..ac3e85ca --- /dev/null +++ b/MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.reference @@ -0,0 +1,342 @@ +{ + "contents" : [ + { + "contents" : [ + { + "contents" : [ + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 0, + "y" : 0 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 100, + "y" : 0 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 200, + "y" : 0 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 300, + "y" : 0 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 0, + "y" : 100 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 100, + "y" : 100 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 200, + "y" : 100 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 100, + "type" : "Rect", + "w" : 100, + "x" : 300, + "y" : 100 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + } + ], + "node" : "Group", + "place" : "1, 0, 0, 1, 40, 60" + } + ], + "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.1 $" + } + ], + "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 + } + }, + { + "contents" : [ + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "h" : 20, + "type" : "Rect", + "w" : 478, + "x" : 1, + "y" : 1 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "align" : "mid", + "baseline" : "bottom", + "fill" : { + "type" : "Color", + "val" : 16777215 + }, + "font" : { + "name" : "SVGFreeSansASCII,sans-serif", + "size" : 20, + "weight" : "bold" + }, + "node" : "Text", + "place" : "1, 0, 0, 1, 240, 18", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 0.5 + }, + "text" : "DRAFT" + } + ], + "node" : "Group" + } + ], + "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/pservers-pattern-03-f-manual.svg b/MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.svg new file mode 100644 index 00000000..a363e5e0 --- /dev/null +++ b/MacawTests/w3cSVGTests/pservers-pattern-03-f-manual.svg @@ -0,0 +1,91 @@ + + + + + + + + + + +

+ Test that empty patterns are not rendered, and that the fallback color is used instead. +

+ + +

+ Run the test. No interaction required. +

+
+ +

+ The test is passed if there are 8 green rectangles visible, and no red. +

+
+ + $RCSfile: pservers-pattern-03-f.svg,v $ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Revision: 1.1 $ + + + + + + DRAFT + + From 9c9ed8c4e4c776b124521af63e87c51b4899ec3f Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Tue, 11 Jun 2019 13:27:47 +0700 Subject: [PATCH 04/10] #203 add transform and viewBox for patterns --- Source/model/draw/Pattern.swift | 6 ++++- Source/render/ShapeRenderer.swift | 3 ++- Source/svg/SVGParser.swift | 42 +++++++++++++++++++++++-------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/Source/model/draw/Pattern.swift b/Source/model/draw/Pattern.swift index 20576331..c936e6dd 100644 --- a/Source/model/draw/Pattern.swift +++ b/Source/model/draw/Pattern.swift @@ -1,12 +1,16 @@ open class Pattern: Fill { + public let viewBox: Rect public let content: Node public let bounds: Rect public let userSpace: Bool + public let position: Transform - public init(content: Node, bounds: Rect, userSpace: Bool = false) { + public init(content: Node, bounds: Rect, viewBox: Rect, userSpace: Bool = false, position: Transform) { + self.viewBox = viewBox self.content = content self.bounds = bounds self.userSpace = userSpace + self.position = position } } diff --git a/Source/render/ShapeRenderer.swift b/Source/render/ShapeRenderer.swift index 22242651..6714a5c4 100644 --- a/Source/render/ShapeRenderer.swift +++ b/Source/render/ShapeRenderer.swift @@ -186,7 +186,8 @@ class ShapeRenderer: NodeRenderer { let boundsTranform = BoundsUtils.transformForLocusInRespectiveCoords(respectiveLocus: pattern.bounds, absoluteLocus: shape.form) patternBounds = pattern.bounds.applying(boundsTranform) } - let tileImage = renderer.renderToImage(bounds: patternBounds, inset: 0) + let tileImage = renderer.renderToImage(bounds: pattern.viewBox, inset: 0) + ctx?.concatenate(pattern.position.toCG()) ctx?.clip() ctx?.draw(tileImage.cgImage!, in: patternBounds.toCG(), byTiling: true) } diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index a8b0ee05..1dfb073a 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -365,12 +365,20 @@ open class SVGParser { parentPattern = defPatterns[id] } + var viewBox: Rect = .zero() + if let viewBoxString = element.allAttributes["viewBox"]?.text { + let nums = viewBoxString.components(separatedBy: .whitespaces).map { Double($0) } + if nums.count == 4, let x = nums[0], let y = nums[1], let w = nums[2], let h = nums[3] { + viewBox = Rect(x: x, y: y, w: w, h: h) + } + } + let x = getDoubleValue(element, attribute: "x") ?? parentPattern?.bounds.x ?? 0 let y = getDoubleValue(element, attribute: "y") ?? parentPattern?.bounds.y ?? 0 let w = getDoubleValue(element, attribute: "width") ?? parentPattern?.bounds.w ?? 0 let h = getDoubleValue(element, attribute: "height") ?? parentPattern?.bounds.h ?? 0 let bounds = Rect(x: x, y: y, w: w, h: h) - + guard bounds.w > 0 && bounds.h > 0 else { return .none } @@ -384,6 +392,8 @@ open class SVGParser { contentUserSpace = false } + let position = getPatternPosition(element) + var contentNode: Node? if pattern.children.isEmpty { if let parentPattern = parentPattern { @@ -402,11 +412,10 @@ open class SVGParser { } contentNode = Group(contents: shapes) } - + if let contentNode = contentNode { - return UserSpacePattern(content: contentNode, bounds: bounds, userSpace: userSpace, contentUserSpace: contentUserSpace) + return UserSpacePattern(content: contentNode, bounds: bounds, viewBox: viewBox, userSpace: userSpace, contentUserSpace: contentUserSpace, position: position) } - return .none } @@ -425,7 +434,14 @@ open class SVGParser { fileprivate func getPosition(_ element: SWXMLHash.XMLElement) -> Transform { guard let transformAttribute = element.allAttributes["transform"]?.text else { - return Transform.identity + return .identity + } + return parseTransformationAttribute(transformAttribute) + } + + fileprivate func getPatternPosition(_ element: SWXMLHash.XMLElement) -> Transform { + guard let transformAttribute = element.allAttributes["patternTransform"]?.text else { + return .identity } return parseTransformationAttribute(transformAttribute) } @@ -665,7 +681,7 @@ open class SVGParser { fillColor = String(fallbackColor) } } - + if fillColor == SVGKeys.currentColor, let currentColor = groupStyle[SVGKeys.color] { fillColor = currentColor } @@ -676,14 +692,14 @@ open class SVGParser { fileprivate func getPatternFill(pattern: UserSpacePattern, locus: Locus?) -> Pattern { if pattern.userSpace == false && pattern.contentUserSpace == true { let tranform = BoundsUtils.transformForLocusInRespectiveCoords(respectiveLocus: pattern.bounds, absoluteLocus: locus!) - return Pattern(content: pattern.content, bounds: pattern.bounds.applying(tranform), userSpace: true) + return Pattern(content: pattern.content, bounds: pattern.bounds.applying(tranform), viewBox: pattern.viewBox, userSpace: true, position: pattern.position) } if pattern.userSpace == true && pattern.contentUserSpace == false { if let patternNode = BoundsUtils.createNodeFromRespectiveCoords(respectiveNode: pattern.content, absoluteLocus: locus!) { - return Pattern(content: patternNode, bounds: pattern.bounds, userSpace: pattern.userSpace) + return Pattern(content: patternNode, bounds: pattern.bounds, viewBox: pattern.viewBox, userSpace: pattern.userSpace, position: pattern.position) } } - return Pattern(content: pattern.content, bounds: pattern.bounds, userSpace: true) + return Pattern(content: pattern.content, bounds: pattern.bounds, viewBox: pattern.viewBox, userSpace: true, position: pattern.position) } fileprivate func getStroke(_ styleParts: [String: String], groupStyle: [String: String] = [:]) -> Stroke? { @@ -1893,7 +1909,7 @@ fileprivate extension String { let end = index(endIndex, offsetBy: -fromEnd) return String(self[start.. String? { return (range(of: from)?.upperBound).flatMap { substringFrom in (range(of: to, range: substringFrom.. Date: Tue, 11 Jun 2019 13:30:46 +0700 Subject: [PATCH 05/10] #203 add svg test for pservers-pattern-02 --- Macaw.xcodeproj/project.pbxproj | 8 ++ MacawTests/MacawSVGTests.swift | 4 + .../pservers-pattern-02-f-manual.reference | 79 +++++++++++++++++++ .../pservers-pattern-02-f-manual.svg | 61 ++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.reference create mode 100644 MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.svg diff --git a/Macaw.xcodeproj/project.pbxproj b/Macaw.xcodeproj/project.pbxproj index 6321f54f..3a5ac01f 100644 --- a/Macaw.xcodeproj/project.pbxproj +++ b/Macaw.xcodeproj/project.pbxproj @@ -672,6 +672,8 @@ A74C832E229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */; }; A75A2F5922AE92B40056A89D /* pservers-pattern-03-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */; }; A75A2F5B22AE96050056A89D /* pservers-pattern-03-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */; }; + A75A2F6122AF818B0056A89D /* pservers-pattern-02-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F6022AF818B0056A89D /* pservers-pattern-02-f-manual.svg */; }; + A75A2F6322AF81D90056A89D /* pservers-pattern-02-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F6222AF81D80056A89D /* pservers-pattern-02-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 */; }; @@ -1252,6 +1254,8 @@ A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.reference"; sourceTree = ""; }; A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-03-f-manual.svg"; sourceTree = ""; }; A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-03-f-manual.reference"; sourceTree = ""; }; + A75A2F6022AF818B0056A89D /* pservers-pattern-02-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-02-f-manual.svg"; sourceTree = ""; }; + A75A2F6222AF81D80056A89D /* pservers-pattern-02-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-02-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 = ""; }; @@ -1983,6 +1987,8 @@ A74C82DB229E35D20085A832 /* pservers-grad-24-f-manual.svg */, 5B1AE1F020B6A669007EECCB /* pservers-grad-stops-01-f-manual.reference */, 5B1AE1EB20B6A669007EECCB /* pservers-grad-stops-01-f-manual.svg */, + A75A2F6222AF81D80056A89D /* pservers-pattern-02-f-manual.reference */, + A75A2F6022AF818B0056A89D /* pservers-pattern-02-f-manual.svg */, A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */, A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */, 5B1AE1A220B6A669007EECCB /* render-elems-01-t-manual.reference */, @@ -2550,6 +2556,7 @@ 5B1AE2B720B6A669007EECCB /* struct-frag-03-t-manual.reference in Resources */, 5B1AE25C20B6A669007EECCB /* shapes-intro-01-t-manual.svg in Resources */, 57CAB12E1D7832E000FD8E47 /* circle.svg in Resources */, + A75A2F6122AF818B0056A89D /* pservers-pattern-02-f-manual.svg in Resources */, 5B1AE2D820B6A669007EECCB /* metadata-example-01-t-manual.svg in Resources */, 4295957422A0F7CE00869079 /* paths-data-12-t-manual.png in Resources */, 5B1AE2C620B6A669007EECCB /* painting-fill-05-b-manual.reference in Resources */, @@ -2561,6 +2568,7 @@ 5B1AE2DE20B6A669007EECCB /* painting-control-03-f-manual.svg in Resources */, 5B1AE25520B6A669007EECCB /* paths-data-15-t-manual.reference in Resources */, 5B1AE24D20B6A669007EECCB /* paths-data-13-t-manual.svg in Resources */, + A75A2F6322AF81D90056A89D /* pservers-pattern-02-f-manual.reference in Resources */, A74C82202297D4810085A832 /* coords-trans-14-f-manual.svg in Resources */, 5B270B5D214BBC27001AD741 /* clearColor.reference in Resources */, 57CAB1311D7832E000FD8E47 /* line.svg in Resources */, diff --git a/MacawTests/MacawSVGTests.swift b/MacawTests/MacawSVGTests.swift index 5eba94fb..61143400 100644 --- a/MacawTests/MacawSVGTests.swift +++ b/MacawTests/MacawSVGTests.swift @@ -872,6 +872,10 @@ class MacawSVGTests: XCTestCase { validateJSON("masking-mask-02-f-manual") } + func testPserversPattern02() { + validateJSON("pservers-pattern-02-f-manual") + } + func testPserversPattern03() { validateJSON("pservers-pattern-03-f-manual") } diff --git a/MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.reference b/MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.reference new file mode 100644 index 00000000..f7742263 --- /dev/null +++ b/MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.reference @@ -0,0 +1,79 @@ +{ + "contents" : [ + { + "contents" : [ + { + "form" : { + "h" : 480, + "type" : "Rect", + "w" : 480, + "x" : 0, + "y" : 0 + }, + "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/pservers-pattern-02-f-manual.svg b/MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.svg new file mode 100644 index 00000000..d2e8655a --- /dev/null +++ b/MacawTests/w3cSVGTests/pservers-pattern-02-f-manual.svg @@ -0,0 +1,61 @@ + + + + + + + + + + +

+ Test that the 'patternTransform' attribute has an effect on the 'pattern' element. +

+ + +

+ Run the test. No interaction required. +

+
+ +

+ The test is passed if the testframe is filled with a blue and white + diamond pattern. +

+
+ + $RCSfile: pservers-pattern-02-f.svg,v $ + + + + + + + + + + + + + + + + + + $Revision: 1.3 $ + + + + From bd7987c48344fe2d1b0494bb05fd6ded53840094 Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Tue, 11 Jun 2019 18:25:47 +0700 Subject: [PATCH 06/10] fix empty viewBox for drawing pattern --- Source/render/ShapeRenderer.swift | 8 +++++++- Source/svg/SVGParser.swift | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/render/ShapeRenderer.swift b/Source/render/ShapeRenderer.swift index 6714a5c4..87b1ef75 100644 --- a/Source/render/ShapeRenderer.swift +++ b/Source/render/ShapeRenderer.swift @@ -186,7 +186,13 @@ class ShapeRenderer: NodeRenderer { let boundsTranform = BoundsUtils.transformForLocusInRespectiveCoords(respectiveLocus: pattern.bounds, absoluteLocus: shape.form) patternBounds = pattern.bounds.applying(boundsTranform) } - let tileImage = renderer.renderToImage(bounds: pattern.viewBox, inset: 0) + + var viewBox = pattern.viewBox + if viewBox == .zero() { + viewBox = patternBounds + } + + let tileImage = renderer.renderToImage(bounds: viewBox, inset: 0) ctx?.concatenate(pattern.position.toCG()) ctx?.clip() ctx?.draw(tileImage.cgImage!, in: patternBounds.toCG(), byTiling: true) diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 1dfb073a..8bffa22a 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -365,7 +365,7 @@ open class SVGParser { parentPattern = defPatterns[id] } - var viewBox: Rect = .zero() + var viewBox: Rect = parentPattern?.viewBox ?? .zero() if let viewBoxString = element.allAttributes["viewBox"]?.text { let nums = viewBoxString.components(separatedBy: .whitespaces).map { Double($0) } if nums.count == 4, let x = nums[0], let y = nums[1], let w = nums[2], let h = nums[3] { From b7fee83b73d2c749dde8fa9cd3e65b1db4ffe57a Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Tue, 11 Jun 2019 18:27:59 +0700 Subject: [PATCH 07/10] #203 add svg test for pservers-pattern-09, add tests for macos --- Macaw.xcodeproj/project.pbxproj | 22 ++- MacawTests/MacawSVGTests.swift | 16 +- .../png/pservers-pattern-02-f-manual.png | Bin 0 -> 925030 bytes .../png/pservers-pattern-03-f-manual.png | Bin 0 -> 716166 bytes .../png/pservers-pattern-09-f-manual.png | Bin 0 -> 716166 bytes .../pservers-pattern-09-f-manual.reference | 166 ++++++++++++++++++ .../pservers-pattern-09-f-manual.svg | 70 ++++++++ 7 files changed, 267 insertions(+), 7 deletions(-) create mode 100644 MacawTests/png/pservers-pattern-02-f-manual.png create mode 100644 MacawTests/png/pservers-pattern-03-f-manual.png create mode 100644 MacawTests/png/pservers-pattern-09-f-manual.png create mode 100644 MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.reference create mode 100644 MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.svg diff --git a/Macaw.xcodeproj/project.pbxproj b/Macaw.xcodeproj/project.pbxproj index 3a5ac01f..8284b563 100644 --- a/Macaw.xcodeproj/project.pbxproj +++ b/Macaw.xcodeproj/project.pbxproj @@ -674,6 +674,11 @@ A75A2F5B22AE96050056A89D /* pservers-pattern-03-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */; }; A75A2F6122AF818B0056A89D /* pservers-pattern-02-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F6022AF818B0056A89D /* pservers-pattern-02-f-manual.svg */; }; A75A2F6322AF81D90056A89D /* pservers-pattern-02-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F6222AF81D80056A89D /* pservers-pattern-02-f-manual.reference */; }; + A75A2F7522AFBD0C0056A89D /* pservers-pattern-09-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F7422AFBD0C0056A89D /* pservers-pattern-09-f-manual.svg */; }; + A75A2F7722AFBD5C0056A89D /* pservers-pattern-09-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F7622AFBD5C0056A89D /* pservers-pattern-09-f-manual.reference */; }; + A75A2F8522AFC6570056A89D /* pservers-pattern-02-f-manual.png in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F8222AFC6560056A89D /* pservers-pattern-02-f-manual.png */; }; + A75A2F8622AFC6570056A89D /* pservers-pattern-03-f-manual.png in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F8322AFC6560056A89D /* pservers-pattern-03-f-manual.png */; }; + A75A2F8722AFC6570056A89D /* pservers-pattern-09-f-manual.png in Resources */ = {isa = PBXBuildFile; fileRef = A75A2F8422AFC6560056A89D /* pservers-pattern-09-f-manual.png */; }; 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 */; }; @@ -1256,6 +1261,11 @@ A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-03-f-manual.reference"; sourceTree = ""; }; A75A2F6022AF818B0056A89D /* pservers-pattern-02-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-02-f-manual.svg"; sourceTree = ""; }; A75A2F6222AF81D80056A89D /* pservers-pattern-02-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-02-f-manual.reference"; sourceTree = ""; }; + A75A2F7422AFBD0C0056A89D /* pservers-pattern-09-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-09-f-manual.svg"; sourceTree = ""; }; + A75A2F7622AFBD5C0056A89D /* pservers-pattern-09-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-pattern-09-f-manual.reference"; sourceTree = ""; }; + A75A2F8222AFC6560056A89D /* pservers-pattern-02-f-manual.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pservers-pattern-02-f-manual.png"; sourceTree = ""; }; + A75A2F8322AFC6560056A89D /* pservers-pattern-03-f-manual.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pservers-pattern-03-f-manual.png"; sourceTree = ""; }; + A75A2F8422AFC6560056A89D /* pservers-pattern-09-f-manual.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pservers-pattern-09-f-manual.png"; 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 = ""; }; @@ -1418,6 +1428,9 @@ 4295954322A0F7CE00869079 /* shapes-rect-06-f-manual.png */, 4295954422A0F7CE00869079 /* shapes-polyline-02-t-manual.png */, 4295954522A0F7CE00869079 /* shapes-polygon-01-t-manual.png */, + A75A2F8222AFC6560056A89D /* pservers-pattern-02-f-manual.png */, + A75A2F8322AFC6560056A89D /* pservers-pattern-03-f-manual.png */, + A75A2F8422AFC6560056A89D /* pservers-pattern-09-f-manual.png */, ); path = png; sourceTree = ""; @@ -1987,10 +2000,12 @@ A74C82DB229E35D20085A832 /* pservers-grad-24-f-manual.svg */, 5B1AE1F020B6A669007EECCB /* pservers-grad-stops-01-f-manual.reference */, 5B1AE1EB20B6A669007EECCB /* pservers-grad-stops-01-f-manual.svg */, + A75A2F7622AFBD5C0056A89D /* pservers-pattern-09-f-manual.reference */, + A75A2F7422AFBD0C0056A89D /* pservers-pattern-09-f-manual.svg */, A75A2F6222AF81D80056A89D /* pservers-pattern-02-f-manual.reference */, A75A2F6022AF818B0056A89D /* pservers-pattern-02-f-manual.svg */, - A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */, A75A2F5A22AE96050056A89D /* pservers-pattern-03-f-manual.reference */, + A75A2F5822AE92B40056A89D /* pservers-pattern-03-f-manual.svg */, 5B1AE1A220B6A669007EECCB /* render-elems-01-t-manual.reference */, 5B1AE1E920B6A669007EECCB /* render-elems-01-t-manual.svg */, 5B1AE19020B6A669007EECCB /* render-elems-02-t-manual.reference */, @@ -2293,6 +2308,7 @@ A74C822D2297D5350085A832 /* coords-trans-13-f-manual.reference in Resources */, 5B1AE26C20B6A669007EECCB /* painting-fill-05-b-manual.svg in Resources */, 429595AF22A0F7CE00869079 /* shapes-polyline-02-t-manual.png in Resources */, + A75A2F8622AFC6570056A89D /* pservers-pattern-03-f-manual.png in Resources */, 5B37139920BE95D7004BB6EE /* pservers-grad-02-b-manual.reference in Resources */, 4295955022A0F7CE00869079 /* painting-fill-02-t-manual.png in Resources */, 4295954622A0F7CE00869079 /* text-fonts-02-t-manual.png in Resources */, @@ -2348,6 +2364,7 @@ 42DAF9B022A6130D0095B936 /* color-prop-03-t-manual.svg in Resources */, 5B1AE2CD20B6A669007EECCB /* paths-data-10-t-manual.svg in Resources */, 42DAF9AE22A612EC0095B936 /* painting-control-01-f-manual.svg in Resources */, + A75A2F7522AFBD0C0056A89D /* pservers-pattern-09-f-manual.svg in Resources */, 5B1AE29C20B6A669007EECCB /* paths-data-01-t-manual.reference in Resources */, 4295955822A0F7CE00869079 /* shapes-ellipse-03-f-manual.png in Resources */, 4295959F22A0F7CE00869079 /* shapes-rect-07-f-manual.png in Resources */, @@ -2368,6 +2385,7 @@ A74C82E5229E35D30085A832 /* pservers-grad-13-b-manual.svg in Resources */, A74C8308229E9CCE0085A832 /* masking-mask-02-f-manual.svg in Resources */, 5B1AE2B220B6A669007EECCB /* types-basic-01-f-manual.svg in Resources */, + A75A2F7722AFBD5C0056A89D /* pservers-pattern-09-f-manual.reference in Resources */, 58944BDA20AC8A9A00657640 /* logo_base64.txt in Resources */, 5B1AE2C520B6A669007EECCB /* coords-trans-02-t-manual.svg in Resources */, A74C81F12292B3940085A832 /* color-prop-05-t-manual.svg in Resources */, @@ -2452,6 +2470,7 @@ 429595A622A0F7CE00869079 /* pservers-grad-stops-01-f-manual.png in Resources */, 5B1AE25120B6A669007EECCB /* coords-trans-05-t-manual.reference in Resources */, 5B1AE29120B6A669007EECCB /* coords-transformattr-01-f-manual.svg in Resources */, + A75A2F8522AFC6570056A89D /* pservers-pattern-02-f-manual.png in Resources */, 6A616BFA2129560A006A07FA /* MacawTests.bundle in Resources */, 4295957F22A0F7CE00869079 /* metadata-example-01-t-manual.png in Resources */, 5B1AE2D320B6A669007EECCB /* shapes-rect-04-f-manual.reference in Resources */, @@ -2472,6 +2491,7 @@ A74C81F32292B45E0085A832 /* color-prop-05-t-manual.reference in Resources */, 4295958922A0F7CE00869079 /* masking-path-02-b-manual.png in Resources */, 5B1AE23420B6A669007EECCB /* painting-control-03-f-manual.reference in Resources */, + A75A2F8722AFC6570056A89D /* pservers-pattern-09-f-manual.png in Resources */, 4295955F22A0F7CE00869079 /* coords-transformattr-05-f-manual.png in Resources */, A74C82342297D8B40085A832 /* shapes-rect-03-t-manual.svg in Resources */, 5B1AE26820B6A669007EECCB /* shapes-polyline-01-t-manual.svg in Resources */, diff --git a/MacawTests/MacawSVGTests.swift b/MacawTests/MacawSVGTests.swift index 61143400..86126aee 100644 --- a/MacawTests/MacawSVGTests.swift +++ b/MacawTests/MacawSVGTests.swift @@ -20,7 +20,7 @@ class MacawSVGTests: XCTestCase { private let testFolderName = "MacawTestOutputData" private let shouldComparePNGImages = true private let multipleTestsWillRun = false - private let shouldSaveFaildedTestImage = false + private let shouldSaveFaildedTestImage = true override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. @@ -146,7 +146,7 @@ class MacawSVGTests: XCTestCase { frame = Group(contents: group.contents).bounds } - let image = node.toNativeImage(size: frame?.size() ?? Size.init(w: 100, h: 100)) + let image = node.toNativeImage(size: frame?.size() ?? Size(w: 100, h: 100)) return image } catch { XCTFail(error.localizedDescription) @@ -253,16 +253,16 @@ class MacawSVGTests: XCTestCase { if let path = bundle.path(forResource: referenceFile, ofType: "reference") { let referenceContent = try String(contentsOfFile: path) - let nodeContent = String(data: getJSONData(node: node), encoding: String.Encoding.utf8) + let nodeContent = String(data: getJSONData(node: node), encoding: .utf8) if nodeContent != referenceContent { XCTFail("nodeContent is not equal to referenceContent") } - - //To save new PNG image for test, uncomment this - //saveImage(image: nativeImage, fileName: referenceFile) + #if os(OSX) let nativeImage = getImage(from: referenceFile) + //To save new PNG image for test, uncomment this + //saveImage(image: nativeImage, fileName: referenceFile) if shouldComparePNGImages { validateImage(nodeImage: nativeImage, referenceFile: referenceFile) } @@ -879,4 +879,8 @@ class MacawSVGTests: XCTestCase { func testPserversPattern03() { validateJSON("pservers-pattern-03-f-manual") } + + func testPserversPattern09() { + validateJSON("pservers-pattern-09-f-manual") + } } diff --git a/MacawTests/png/pservers-pattern-02-f-manual.png b/MacawTests/png/pservers-pattern-02-f-manual.png new file mode 100644 index 0000000000000000000000000000000000000000..04c5723ed641b810d4548dde6d7fa4fb0d571f55 GIT binary patch literal 925030 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/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 Vbls1AethVsF+aWg^NgQ={(p^N!2AFJ literal 0 HcmV?d00001 diff --git a/MacawTests/png/pservers-pattern-03-f-manual.png b/MacawTests/png/pservers-pattern-03-f-manual.png new file mode 100644 index 0000000000000000000000000000000000000000..5989cb79f7bd671d4a8f0836c8b6d682d0e26c17 GIT binary patch literal 716166 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 N)br5K86z?>{vR=;cOU=& literal 0 HcmV?d00001 diff --git a/MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.reference b/MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.reference new file mode 100644 index 00000000..be104dd1 --- /dev/null +++ b/MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.reference @@ -0,0 +1,166 @@ +{ + "contents" : [ + { + "contents" : [ + { + "form" : { + "h" : 200, + "type" : "Rect", + "w" : 200, + "x" : 1, + "y" : 1 + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 200, + "type" : "Rect", + "w" : 200, + "x" : 1, + "y" : 1 + }, + "node" : "Shape" + }, + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 200, + "type" : "Rect", + "w" : 200, + "x" : 201, + "y" : 1 + }, + "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.1 $" + } + ], + "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 + } + }, + { + "contents" : [ + { + "fill" : { + "type" : "Color", + "val" : 16711680 + }, + "form" : { + "h" : 20, + "type" : "Rect", + "w" : 478, + "x" : 1, + "y" : 1 + }, + "node" : "Shape", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 1 + } + }, + { + "align" : "mid", + "baseline" : "bottom", + "fill" : { + "type" : "Color", + "val" : 16777215 + }, + "font" : { + "name" : "SVGFreeSansASCII,sans-serif", + "size" : 20, + "weight" : "bold" + }, + "node" : "Text", + "place" : "1, 0, 0, 1, 240, 18", + "stroke" : { + "cap" : "butt", + "dashes" : [ + + ], + "fill" : { + "type" : "Color", + "val" : 0 + }, + "join" : "miter", + "width" : 0.5 + }, + "text" : "DRAFT" + } + ], + "node" : "Group" + } + ], + "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/pservers-pattern-09-f-manual.svg b/MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.svg new file mode 100644 index 00000000..f98cdc29 --- /dev/null +++ b/MacawTests/w3cSVGTests/pservers-pattern-09-f-manual.svg @@ -0,0 +1,70 @@ + + + + + + + + + + +

+ Test that an invalid xlink:href on a 'pattern' element has no effect on the pattern, and that the + pattern isn't rendered since the default 'width' and 'height' is 0. + A subtest that explicitly specifies 'width' and 'height' as 0 is added as a reference. + Both of these cases should result in the fallback color being used. +

+ + +

+ Run the test. No interaction required. +

+
+ +

+ The test is passed if there is a green rectangle visible on the page, and no red. +

+
+ + $RCSfile: pservers-pattern-09-f.svg,v $ + + + + + + + + + + + + + + + + + + + + + + + + + $Revision: 1.1 $ + + + + + + DRAFT + + From c7ff33a7d6edbc176c7c8d35c483a2b7bf74599f Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Tue, 11 Jun 2019 18:31:12 +0700 Subject: [PATCH 08/10] #203 update w3c svt test suite --- MacawTests/w3c-test-suite.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MacawTests/w3c-test-suite.md b/MacawTests/w3c-test-suite.md index 55f40ea9..81c78e56 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: -* 38.6% passed (118) +* 39.5% passed (121) * 14.1% filters (43) [#390](https://github.com/exyte/Macaw/issues/390) * 8.5% images (26) [wpt issue](https://github.com/web-platform-tests/wpt/issues/11178) * 2.6% markers (8) [#392](https://github.com/exyte/Macaw/issues/392) * 20.6% text (63) [#391](https://github.com/exyte/Macaw/issues/391) -* 15.7% blocked by issues (48) +* 14.7% blocked by issues (45) Status of each test: @@ -209,14 +209,14 @@ Status of each test: |[pservers-grad-24-f-manual](w3cSVGTests/pservers-grad-24-f-manual.svg) | ✅ | |[pservers-grad-stops-01-f-manual](w3cSVGTests/pservers-grad-stops-01-f-manual.svg) | ✅ | |[pservers-pattern-01-b-manual](w3cSVGTests/pservers-pattern-01-b-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | -|[pservers-pattern-02-f-manual](w3cSVGTests/pservers-pattern-02-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | -|[pservers-pattern-03-f-manual](w3cSVGTests/pservers-pattern-03-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | +|[pservers-pattern-02-f-manual](w3cSVGTests/pservers-pattern-02-f-manual.svg) | ✅ | +|[pservers-pattern-03-f-manual](w3cSVGTests/pservers-pattern-03-f-manual.svg) | ✅ | |[pservers-pattern-04-f-manual](w3cSVGTests/pservers-pattern-04-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | |[pservers-pattern-05-f-manual](w3cSVGTests/pservers-pattern-05-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | |[pservers-pattern-06-f-manual](w3cSVGTests/pservers-pattern-06-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | |[pservers-pattern-07-f-manual](w3cSVGTests/pservers-pattern-07-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | |[pservers-pattern-08-f-manual](w3cSVGTests/pservers-pattern-08-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | -|[pservers-pattern-09-f-manual](w3cSVGTests/pservers-pattern-09-f-manual.svg) | [#203](https://github.com/exyte/Macaw/issues/203) | +|[pservers-pattern-09-f-manual](w3cSVGTests/pservers-pattern-09-f-manual.svg) | ✅ | |[render-elems-01-t-manual](w3cSVGTests/render-elems-01-t-manual.svg) | ✅ | |[render-elems-02-t-manual](w3cSVGTests/render-elems-02-t-manual.svg) | ✅ | |[render-elems-03-t-manual](w3cSVGTests/render-elems-03-t-manual.svg) | ✅ | From 1234f0bac1aef185fcf7b20c1fa71374fda9099e Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Fri, 14 Jun 2019 17:04:39 +0700 Subject: [PATCH 09/10] #203 rename position to place of Pattern --- Source/model/draw/Pattern.swift | 6 +++--- Source/render/ShapeRenderer.swift | 2 +- Source/svg/SVGParser.swift | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Source/model/draw/Pattern.swift b/Source/model/draw/Pattern.swift index c936e6dd..32d250b7 100644 --- a/Source/model/draw/Pattern.swift +++ b/Source/model/draw/Pattern.swift @@ -4,13 +4,13 @@ open class Pattern: Fill { public let content: Node public let bounds: Rect public let userSpace: Bool - public let position: Transform + public let place: Transform - public init(content: Node, bounds: Rect, viewBox: Rect, userSpace: Bool = false, position: Transform) { + public init(content: Node, bounds: Rect, viewBox: Rect, userSpace: Bool = false, place: Transform) { self.viewBox = viewBox self.content = content self.bounds = bounds self.userSpace = userSpace - self.position = position + self.place = place } } diff --git a/Source/render/ShapeRenderer.swift b/Source/render/ShapeRenderer.swift index 87b1ef75..b997fbe0 100644 --- a/Source/render/ShapeRenderer.swift +++ b/Source/render/ShapeRenderer.swift @@ -193,7 +193,7 @@ class ShapeRenderer: NodeRenderer { } let tileImage = renderer.renderToImage(bounds: viewBox, inset: 0) - ctx?.concatenate(pattern.position.toCG()) + ctx?.concatenate(pattern.place.toCG()) ctx?.clip() ctx?.draw(tileImage.cgImage!, in: patternBounds.toCG(), byTiling: true) } diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 8bffa22a..88d05856 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -392,7 +392,7 @@ open class SVGParser { contentUserSpace = false } - let position = getPatternPosition(element) + let place = getPatternPlace(element) var contentNode: Node? if pattern.children.isEmpty { @@ -414,7 +414,7 @@ open class SVGParser { } if let contentNode = contentNode { - return UserSpacePattern(content: contentNode, bounds: bounds, viewBox: viewBox, userSpace: userSpace, contentUserSpace: contentUserSpace, position: position) + return UserSpacePattern(content: contentNode, bounds: bounds, viewBox: viewBox, userSpace: userSpace, contentUserSpace: contentUserSpace, place: place) } return .none } @@ -439,7 +439,7 @@ open class SVGParser { return parseTransformationAttribute(transformAttribute) } - fileprivate func getPatternPosition(_ element: SWXMLHash.XMLElement) -> Transform { + fileprivate func getPatternPlace(_ element: SWXMLHash.XMLElement) -> Transform { guard let transformAttribute = element.allAttributes["patternTransform"]?.text else { return .identity } @@ -692,14 +692,14 @@ open class SVGParser { fileprivate func getPatternFill(pattern: UserSpacePattern, locus: Locus?) -> Pattern { if pattern.userSpace == false && pattern.contentUserSpace == true { let tranform = BoundsUtils.transformForLocusInRespectiveCoords(respectiveLocus: pattern.bounds, absoluteLocus: locus!) - return Pattern(content: pattern.content, bounds: pattern.bounds.applying(tranform), viewBox: pattern.viewBox, userSpace: true, position: pattern.position) + return Pattern(content: pattern.content, bounds: pattern.bounds.applying(tranform), viewBox: pattern.viewBox, userSpace: true, place: pattern.place) } if pattern.userSpace == true && pattern.contentUserSpace == false { if let patternNode = BoundsUtils.createNodeFromRespectiveCoords(respectiveNode: pattern.content, absoluteLocus: locus!) { - return Pattern(content: patternNode, bounds: pattern.bounds, viewBox: pattern.viewBox, userSpace: pattern.userSpace, position: pattern.position) + return Pattern(content: patternNode, bounds: pattern.bounds, viewBox: pattern.viewBox, userSpace: pattern.userSpace, place: pattern.place) } } - return Pattern(content: pattern.content, bounds: pattern.bounds, viewBox: pattern.viewBox, userSpace: true, position: pattern.position) + return Pattern(content: pattern.content, bounds: pattern.bounds, viewBox: pattern.viewBox, userSpace: true, place: pattern.place) } fileprivate func getStroke(_ styleParts: [String: String], groupStyle: [String: String] = [:]) -> Stroke? { @@ -1945,15 +1945,15 @@ fileprivate class UserSpacePattern { let bounds: Rect let userSpace: Bool let contentUserSpace: Bool - let position: Transform + let place: Transform - init(content: Node, bounds: Rect, viewBox: Rect = Rect(x: 0, y: 0, w: 0, h: 0), userSpace: Bool = false, contentUserSpace: Bool = true, position: Transform = .identity) { + init(content: Node, bounds: Rect, viewBox: Rect = Rect(x: 0, y: 0, w: 0, h: 0), userSpace: Bool = false, contentUserSpace: Bool = true, place: Transform = .identity) { self.viewBox = viewBox self.content = content self.bounds = bounds self.userSpace = userSpace self.contentUserSpace = contentUserSpace - self.position = position + self.place = place } } From fb459b2960537f6464f81de0035d26cf20dfe02b Mon Sep 17 00:00:00 2001 From: Daniil Manin Date: Fri, 14 Jun 2019 17:10:56 +0700 Subject: [PATCH 10/10] #203 enable multipleTestsWillRun --- MacawTests/MacawSVGTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MacawTests/MacawSVGTests.swift b/MacawTests/MacawSVGTests.swift index 86126aee..ae26c796 100644 --- a/MacawTests/MacawSVGTests.swift +++ b/MacawTests/MacawSVGTests.swift @@ -19,7 +19,7 @@ class MacawSVGTests: XCTestCase { private let testFolderName = "MacawTestOutputData" private let shouldComparePNGImages = true - private let multipleTestsWillRun = false + private let multipleTestsWillRun = true private let shouldSaveFaildedTestImage = true override func setUp() {