diff --git a/Macaw.xcodeproj/project.pbxproj b/Macaw.xcodeproj/project.pbxproj index e7585d7d..51617a0c 100644 --- a/Macaw.xcodeproj/project.pbxproj +++ b/Macaw.xcodeproj/project.pbxproj @@ -510,6 +510,8 @@ A718CD521F45C2A400966E06 /* MBezierPath+Extension_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD511F45C2A400966E06 /* MBezierPath+Extension_macOS.swift */; }; A74C81EC229284790085A832 /* struct-use-01-t-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C81EA229284780085A832 /* struct-use-01-t-manual.reference */; }; 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 */; }; 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 */; }; @@ -925,6 +927,8 @@ 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 = ""; }; A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NodeBoundsTests.swift; path = Bounds/NodeBoundsTests.swift; sourceTree = ""; }; @@ -1368,14 +1372,16 @@ 5B1AE18320B6A669007EECCB /* w3cSVGTests */ = { isa = PBXGroup; children = ( - 421C664F2225196900DD73F5 /* color-prop-04-t-manual.svg */, - 4269F43D2257265700D91393 /* color-prop-04-t-manual.reference */, 5B1AE22D20B6A669007EECCB /* color-prop-01-b-manual.reference */, 5B1AE18A20B6A669007EECCB /* color-prop-01-b-manual.svg */, 5B1AE22C20B6A669007EECCB /* color-prop-02-f-manual.reference */, 5B1AE1C620B6A669007EECCB /* color-prop-02-f-manual.svg */, 5B1AE1FA20B6A669007EECCB /* color-prop-03-t-manual.reference */, 5B1AE20320B6A669007EECCB /* color-prop-03-t-manual.svg */, + 4269F43D2257265700D91393 /* color-prop-04-t-manual.reference */, + 421C664F2225196900DD73F5 /* color-prop-04-t-manual.svg */, + A74C81F22292B45D0085A832 /* color-prop-05-t-manual.reference */, + A74C81F02292B3940085A832 /* color-prop-05-t-manual.svg */, 5B1AE1D420B6A669007EECCB /* coords-coord-01-t-manual.reference */, 5B1AE19A20B6A669007EECCB /* coords-coord-01-t-manual.svg */, 5B1AE1B920B6A669007EECCB /* coords-coord-02-t-manual.reference */, @@ -1817,6 +1823,7 @@ 5B1AE2B220B6A669007EECCB /* types-basic-01-f-manual.svg 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 */, 5B1AE26120B6A669007EECCB /* paths-data-13-t-manual.reference in Resources */, 5B1AE24820B6A669007EECCB /* coords-coord-01-t-manual.svg in Resources */, 5B1AE2B620B6A669007EECCB /* paths-data-04-t-manual.svg in Resources */, @@ -1879,6 +1886,7 @@ 5B1AE2D720B6A669007EECCB /* coords-trans-04-t-manual.svg in Resources */, 5B1AE2AC20B6A669007EECCB /* struct-use-12-f-manual.svg in Resources */, 5B1AE28220B6A669007EECCB /* coords-coord-01-t-manual.reference in Resources */, + A74C81F32292B45E0085A832 /* color-prop-05-t-manual.reference in Resources */, 5B1AE23420B6A669007EECCB /* painting-control-03-f-manual.reference in Resources */, 5B1AE26820B6A669007EECCB /* shapes-polyline-01-t-manual.svg in Resources */, 5B1AE29A20B6A669007EECCB /* struct-frag-02-t-manual.svg in Resources */, diff --git a/MacawTests/MacawSVGTests.swift b/MacawTests/MacawSVGTests.swift index 1837b299..97a25ac9 100644 --- a/MacawTests/MacawSVGTests.swift +++ b/MacawTests/MacawSVGTests.swift @@ -265,6 +265,10 @@ class MacawSVGTests: XCTestCase { validateJSON("color-prop-01-b-manual") } + func testColorProp05() { + validateJSON("color-prop-05-t-manual") + } + func testShapesEllipse01() { validateJSON("shapes-ellipse-01-t-manual") } diff --git a/MacawTests/w3c-test-suite.md b/MacawTests/w3c-test-suite.md index 132e66c9..4d15d351 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.0% passed (95) +* 31.4% passed (96) * 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.8% blocked by issues (76) +* 24.5% blocked by issues (75) Status of each test: @@ -26,7 +26,7 @@ Status of each test: |[color-prop-02-f-manual](w3cSVGTests/color-prop-02-f-manual.svg) | ✅ | |[color-prop-03-t-manual](w3cSVGTests/color-prop-03-t-manual.svg) | ✅ | |[color-prop-04-t-manual](w3cSVGTests/color-prop-04-t-manual.svg) | [#387](https://github.com/exyte/Macaw/issues/387) | -|[color-prop-05-t-manual](w3cSVGTests/color-prop-05-t-manual.svg) | [#388](https://github.com/exyte/Macaw/issues/388) | +|[color-prop-05-t-manual](w3cSVGTests/color-prop-05-t-manual.svg) | ✅ | |[conform-viewers-02-f-manual](w3cSVGTests/conform-viewers-02-f-manual.svg) | [wpt issue](https://github.com/web-platform-tests/wpt/issues/11178) | |[conform-viewers-03-f-manual](w3cSVGTests/conform-viewers-03-f-manual.svg) | [wpt issue](https://github.com/web-platform-tests/wpt/issues/11178) | |[coords-coord-01-t-manual](w3cSVGTests/coords-coord-01-t-manual.svg) | ✅ | @@ -275,7 +275,7 @@ Status of each test: |[struct-svg-03-f-manual](w3cSVGTests/struct-svg-03-f-manual.svg) | [#344](https://github.com/exyte/Macaw/issues/344) | |[struct-symbol-01-b-manual](w3cSVGTests/struct-symbol-01-b-manual.svg) | [#398](https://github.com/exyte/Macaw/issues/398) | |[struct-use-01-t-manual](w3cSVGTests/struct-use-01-t-manual.svg) | -✅ +✅ | |[struct-use-03-t-manual](w3cSVGTests/struct-use-03-t-manual.svg) | ✅ | |[struct-use-09-b-manual](w3cSVGTests/struct-use-09-b-manual.svg) | [#398](https://github.com/exyte/Macaw/issues/398) | |[struct-use-12-f-manual](w3cSVGTests/struct-use-12-f-manual.svg) | ✅ | diff --git a/MacawTests/w3cSVGTests/color-prop-05-t-manual.reference b/MacawTests/w3cSVGTests/color-prop-05-t-manual.reference new file mode 100644 index 00000000..f2df0f8b --- /dev/null +++ b/MacawTests/w3cSVGTests/color-prop-05-t-manual.reference @@ -0,0 +1,88 @@ +{ + "contents" : [ + { + "contents" : [ + { + "contents" : [ + { + "fill" : { + "type" : "Color", + "val" : 65280 + }, + "form" : { + "h" : 150, + "type" : "Rect", + "w" : 150, + "x" : 120, + "y" : 60 + }, + "node" : "Shape" + } + ], + "node" : "Group" + } + ], + "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.8 $" + } + ], + "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/color-prop-05-t-manual.svg b/MacawTests/w3cSVGTests/color-prop-05-t-manual.svg new file mode 100644 index 00000000..466dcda5 --- /dev/null +++ b/MacawTests/w3cSVGTests/color-prop-05-t-manual.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + +

+ Tests the color that is used for the currentColor value in the fill + attribute when more than one color is specified. +

+

+ This is illustrated using a single rectangle that is a child of a group + element. A fill is specified for the group element but not the + rectangle. Colour is specifed for the rectangle and the group element. +

+ + +

Run the test. No interaction required.

+
+ +

+ The test is passed if the user agent renders the rectangle with a green + fill. +

+
+ + $RCSfile: color-prop-05-t.svg,v $ + + + + + + + + + + + + + + $Revision: 1.8 $ + + + + + diff --git a/Source/svg/SVGParser.swift b/Source/svg/SVGParser.swift index 2b21bd02..904a7470 100644 --- a/Source/svg/SVGParser.swift +++ b/Source/svg/SVGParser.swift @@ -156,7 +156,7 @@ open class SVGParser { } if let id = element.allAttributes["id"]?.text { switch element.name { - case "linearGradient", "radialGradient", "fill": + case "linearGradient", "radialGradient", SVGKeys.fill: defFills[id] = try parseFill(node) case "pattern": defPatterns[id] = try parsePattern(node) @@ -316,7 +316,7 @@ open class SVGParser { case "use": return try parseUse(node, groupStyle: style, place: position) case "title", "desc", "mask", "clip", "filter", - "linearGradient", "radialGradient", "fill": + "linearGradient", "radialGradient", SVGKeys.fill: break default: print("SVG parsing error. Shape \(element.name) not supported") @@ -571,9 +571,14 @@ open class SVGParser { } } + let hasCurrentColor = styleAttributes[SVGKeys.fill] == SVGKeys.currentColor + self.availableStyleAttributes.forEach { availableAttribute in if let styleAttribute = element.allAttributes[availableAttribute]?.text, styleAttribute != "inherit" { - styleAttributes.updateValue(styleAttribute, forKey: availableAttribute) + + if !hasCurrentColor || availableAttribute != SVGKeys.color { + styleAttributes.updateValue(styleAttribute, forKey: availableAttribute) + } } } @@ -625,7 +630,7 @@ open class SVGParser { opacity = Double(fillOpacity.replacingOccurrences(of: " ", with: "")) ?? 1 } - guard var fillColor = styleParts["fill"] else { + guard var fillColor = styleParts[SVGKeys.fill] else { return Color.black.with(a: opacity) } if let colorId = parseIdFromUrl(fillColor) { @@ -636,7 +641,7 @@ open class SVGParser { return getPatternFill(pattern: pattern, locus: locus) } } - if fillColor == "currentColor", let currentColor = groupStyle["color"] { + if fillColor == SVGKeys.currentColor, let currentColor = groupStyle[SVGKeys.color] { fillColor = currentColor } @@ -660,7 +665,7 @@ open class SVGParser { guard var strokeColor = styleParts["stroke"] else { return .none } - if strokeColor == "currentColor", let currentColor = groupStyle["color"] { + if strokeColor == SVGKeys.currentColor, let currentColor = groupStyle[SVGKeys.color] { strokeColor = currentColor } var opacity: Double = 1 @@ -997,7 +1002,7 @@ open class SVGParser { let attributes = getStyleAttributes([:], element: element) return Text(text: text, font: getFont(attributes, fontName: fontName, fontWeight: fontWeight, fontSize: fontSize), - fill: (attributes["fill"] != nil) ? getFillColor(attributes)! : fill, stroke: stroke ?? getStroke(attributes), + fill: (attributes[SVGKeys.fill] != nil) ? getFillColor(attributes)! : fill, stroke: stroke ?? getStroke(attributes), align: anchorToAlign(textAnchor ?? getTextAnchor(attributes)), baseline: .alphabetic, place: pos, opacity: getOpacity(attributes), tag: getTag(element)) } @@ -1352,7 +1357,7 @@ open class SVGParser { } var color = Color.black.with(a: opacity) if var stopColor = getStyleAttributes([:], element: element)["stop-color"] { - if stopColor == "currentColor", let currentColor = groupStyle["color"] { + if stopColor == SVGKeys.currentColor, let currentColor = groupStyle[SVGKeys.color] { stopColor = currentColor } color = createColor(stopColor.replacingOccurrences(of: " ", with: ""), opacity: opacity)! @@ -1842,3 +1847,9 @@ fileprivate class UserSpacePattern { self.contentUserSpace = contentUserSpace } } + +fileprivate enum SVGKeys { + static let fill = "fill" + static let color = "color" + static let currentColor = "currentColor" +}