1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-10-26 13:01:25 +03:00

Merge pull request #590 from exyte/fix/393-Improve-mask-support

#393 Improve mask support
This commit is contained in:
Yuri Strot 2019-05-31 19:16:50 +07:00 committed by GitHub
commit f7c7b86bdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 581 additions and 24 deletions

View File

@ -534,6 +534,12 @@
A74C82412297DC220085A832 /* shapes-rect-02-t-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C82402297DC220085A832 /* shapes-rect-02-t-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 */; };
A74C8307229E9CCE0085A832 /* masking-filter-01-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C8305229E9CCD0085A832 /* masking-filter-01-f-manual.svg */; };
A74C8308229E9CCE0085A832 /* masking-mask-02-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C8306229E9CCE0085A832 /* masking-mask-02-f-manual.svg */; };
A74C830B229E9D700085A832 /* masking-filter-01-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C8309229E9D6F0085A832 /* masking-filter-01-f-manual.reference */; };
A74C830C229E9D700085A832 /* masking-mask-02-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C830A229E9D700085A832 /* masking-mask-02-f-manual.reference */; };
A74C8324229EB7150085A832 /* masking-path-13-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = A74C8323229EB7150085A832 /* masking-path-13-f-manual.svg */; };
A74C8326229EB77B0085A832 /* masking-path-13-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C8325229EB77B0085A832 /* masking-path-13-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 */; };
@ -976,6 +982,12 @@
A74C82402297DC220085A832 /* shapes-rect-02-t-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "shapes-rect-02-t-manual.reference"; sourceTree = "<group>"; };
A74C832B229FB7690085A832 /* color-prop-04-t-manual-osx.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.svg"; sourceTree = "<group>"; };
A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual-osx.reference"; sourceTree = "<group>"; };
A74C8305229E9CCD0085A832 /* masking-filter-01-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-filter-01-f-manual.svg"; sourceTree = "<group>"; };
A74C8306229E9CCE0085A832 /* masking-mask-02-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-mask-02-f-manual.svg"; sourceTree = "<group>"; };
A74C8309229E9D6F0085A832 /* masking-filter-01-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-filter-01-f-manual.reference"; sourceTree = "<group>"; };
A74C830A229E9D700085A832 /* masking-mask-02-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-mask-02-f-manual.reference"; sourceTree = "<group>"; };
A74C8323229EB7150085A832 /* masking-path-13-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-path-13-f-manual.svg"; sourceTree = "<group>"; };
A74C8325229EB77B0085A832 /* masking-path-13-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "masking-path-13-f-manual.reference"; sourceTree = "<group>"; };
A7E675551EC4213500BD9ECB /* NodeBoundsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NodeBoundsTests.swift; path = Bounds/NodeBoundsTests.swift; sourceTree = "<group>"; };
C410148D1F834D280022EE44 /* style.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = style.svg; sourceTree = "<group>"; };
C4153A8E1F8793DD001BA5EE /* small-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "small-logo.png"; sourceTree = "<group>"; };
@ -1475,6 +1487,12 @@
5B7E79DD20D2781A00C50BCF /* masking-intro-01-f-manual.svg */,
5B7E79CC20CBE69600C50BCF /* masking-path-02-b-manual.reference */,
5B7E79CD20CBE69700C50BCF /* masking-path-02-b-manual.svg */,
A74C8325229EB77B0085A832 /* masking-path-13-f-manual.reference */,
A74C8323229EB7150085A832 /* masking-path-13-f-manual.svg */,
A74C8309229E9D6F0085A832 /* masking-filter-01-f-manual.reference */,
A74C8305229E9CCD0085A832 /* masking-filter-01-f-manual.svg */,
A74C830A229E9D700085A832 /* masking-mask-02-f-manual.reference */,
A74C8306229E9CCE0085A832 /* masking-mask-02-f-manual.svg */,
5B1AE19E20B6A669007EECCB /* metadata-example-01-t-manual.reference */,
5B1AE22A20B6A669007EECCB /* metadata-example-01-t-manual.svg */,
5B1AE20C20B6A669007EECCB /* painting-control-01-f-manual.reference */,
@ -1841,6 +1859,7 @@
5B1AE2A420B6A669007EECCB /* paths-data-12-t-manual.reference in Resources */,
57CAB1361D7832E000FD8E47 /* triangle.svg in Resources */,
5B7E79CF20CBE69700C50BCF /* masking-path-02-b-manual.svg in Resources */,
A74C830C229E9D700085A832 /* masking-mask-02-f-manual.reference in Resources */,
5BFEF5D620BC1C1F008DAC11 /* paths-data-18-f-manual.svg in Resources */,
A74C81ED229284790085A832 /* struct-use-01-t-manual.svg in Resources */,
5B1AE23620B6A669007EECCB /* paths-data-07-t-manual.svg in Resources */,
@ -1890,10 +1909,12 @@
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 */,
A74C830B229E9D700085A832 /* masking-filter-01-f-manual.reference in Resources */,
5B1AE2AB20B6A669007EECCB /* painting-stroke-08-t-manual.reference in Resources */,
A74C82352297D8B40085A832 /* shapes-rect-07-f-manual.svg in Resources */,
5B1AE2A520B6A669007EECCB /* coords-trans-02-t-manual.reference in Resources */,
5B1AE23220B6A669007EECCB /* text-align-01-b-manual.svg in Resources */,
A74C8308229E9CCE0085A832 /* masking-mask-02-f-manual.svg in Resources */,
5B1AE2B220B6A669007EECCB /* types-basic-01-f-manual.svg in Resources */,
58944BDA20AC8A9A00657640 /* logo_base64.txt in Resources */,
5B1AE2C520B6A669007EECCB /* coords-trans-02-t-manual.svg in Resources */,
@ -1907,6 +1928,7 @@
A74C822C2297D5350085A832 /* coords-trans-10-f-manual.reference in Resources */,
5B1AE24520B6A669007EECCB /* struct-frag-01-t-manual.reference in Resources */,
5B1AE25B20B6A669007EECCB /* painting-stroke-01-t-manual.svg in Resources */,
A74C8324229EB7150085A832 /* masking-path-13-f-manual.svg in Resources */,
A74C823E2297DB2C0085A832 /* shapes-rect-03-t-manual.reference in Resources */,
5BAE2047208E163D006BF277 /* viewBox.reference in Resources */,
5B1AE2C120B6A669007EECCB /* painting-stroke-04-t-manual.svg in Resources */,
@ -2048,6 +2070,7 @@
5B1AE2D220B6A669007EECCB /* struct-group-01-t-manual.svg in Resources */,
5B1AE2B520B6A669007EECCB /* coords-trans-09-t-manual.reference in Resources */,
5B3713A320BE9D8A004BB6EE /* shapes-grammar-01-f-manual.reference in Resources */,
A74C8326229EB77B0085A832 /* masking-path-13-f-manual.reference in Resources */,
57CAB1321D7832E000FD8E47 /* polygon.svg in Resources */,
5BAE203A208E163D006BF277 /* rect.reference in Resources */,
5BAE2044208E163D006BF277 /* style.reference in Resources */,
@ -2066,6 +2089,7 @@
5B1AE27A20B6A669007EECCB /* coords-transformattr-01-f-manual.reference in Resources */,
5B1AE24C20B6A669007EECCB /* metadata-example-01-t-manual.reference in Resources */,
5B1AE29720B6A669007EECCB /* render-elems-01-t-manual.svg in Resources */,
A74C8307229E9CCE0085A832 /* masking-filter-01-f-manual.svg in Resources */,
5B1AE26220B6A669007EECCB /* coords-transformattr-02-f-manual.svg in Resources */,
5B1AE28F20B6A669007EECCB /* shapes-polyline-02-t-manual.svg in Resources */,
5B1AE24420B6A669007EECCB /* shapes-rect-05-f-manual.reference in Resources */,

View File

@ -696,15 +696,27 @@ class MacawSVGTests: XCTestCase {
validateJSON("shapes-grammar-01-f-manual")
}
func testMaskingPath02() {
validateJSON("masking-path-02-b-manual")
func testPserversGrad03() {
validateJSON("pservers-grad-03-b-manual")
}
func testMaskingIntro01() {
validateJSON("masking-intro-01-f-manual")
}
func testPserversGrad03() {
validateJSON("pservers-grad-03-b-manual")
func testMaskingFilter01() {
validateJSON("masking-filter-01-f-manual")
}
func testMaskingPath02() {
validateJSON("masking-path-02-b-manual")
}
func testMaskingPath13() {
validateJSON("masking-path-13-f-manual")
}
func testMaskingMask02() {
validateJSON("masking-mask-02-f-manual")
}
}

View File

@ -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:
* 35.3% passed (108)
* 38.6% passed (118)
* 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)
* 19.0% blocked by issues (58)
* 15.7% blocked by issues (48)
Status of each test:
@ -118,9 +118,9 @@ Status of each test:
|[fonts-kern-01-t-manual](w3cSVGTests/fonts-kern-01-t-manual.svg) | [#391](https://github.com/exyte/Macaw/issues/391) |
|[fonts-overview-201-t-manual](w3cSVGTests/fonts-overview-201-t-manual.svg) | [#391](https://github.com/exyte/Macaw/issues/391) |
|[imp-path-01-f-manual](w3cSVGTests/imp-path-01-f-manual.svg) | [#392](https://github.com/exyte/Macaw/issues/392) |
|[masking-filter-01-f-manual](w3cSVGTests/masking-filter-01-f-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-intro-01-f-manual](w3cSVGTests/masking-intro-01-f-manual.svg) | ✅ |
|[masking-mask-02-f-manual](w3cSVGTests/masking-mask-02-f-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-filter-01-f-manual](w3cSVGTests/masking-filter-01-f-manual.svg) | ✅ |
|[masking-intro-01-f-manual](w3cSVGTests/masking-intro-01-f-manual.svg) | ✅ |
|[masking-mask-02-f-manual](w3cSVGTests/masking-mask-02-f-manual.svg) | |
|[masking-opacity-01-b-manual](w3cSVGTests/masking-opacity-01-b-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-path-01-b-manual](w3cSVGTests/masking-path-01-b-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-path-02-b-manual](w3cSVGTests/masking-path-02-b-manual.svg) | ✅ |
@ -132,7 +132,7 @@ Status of each test:
|[masking-path-08-b-manual](w3cSVGTests/masking-path-08-b-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-path-10-b-manual](w3cSVGTests/masking-path-10-b-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-path-11-b-manual](w3cSVGTests/masking-path-11-b-manual.svg) | [wpt issue](https://github.com/web-platform-tests/wpt/issues/11178) |
|[masking-path-13-f-manual](w3cSVGTests/masking-path-13-f-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[masking-path-13-f-manual](w3cSVGTests/masking-path-13-f-manual.svg) | |
|[masking-path-14-f-manual](w3cSVGTests/masking-path-14-f-manual.svg) | [#393](https://github.com/exyte/Macaw/issues/393) |
|[metadata-example-01-t-manual](w3cSVGTests/metadata-example-01-t-manual.svg) | ✅ |
|[painting-control-01-f-manual](w3cSVGTests/painting-control-01-f-manual.svg) | ✅ |

View File

@ -0,0 +1,152 @@
{
"contents" : [
{
"contents" : [
{
"contents" : [
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 0
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 18,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, 10, 35",
"text" : "Testing 'filter' applied to 'mask'"
},
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 32768
},
"form" : {
"h" : 100,
"type" : "Rect",
"w" : 100,
"x" : 0,
"y" : 0
},
"mask" : {
"fill" : {
"type" : "Color",
"val" : 16777215
},
"form" : {
"h" : 100,
"type" : "Rect",
"w" : 100,
"x" : 0,
"y" : 0
},
"node" : "Shape"
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 16711680
},
"form" : {
"h" : 99,
"type" : "Rect",
"w" : 99,
"x" : 101,
"y" : 101
},
"mask" : {
"fill" : {
"type" : "Color",
"val" : 16777215
},
"form" : {
"h" : 100,
"type" : "Rect",
"w" : 100,
"x" : 0,
"y" : 0
},
"node" : "Shape"
},
"node" : "Shape"
}
],
"node" : "Group",
"place" : "1, 0, 0, 1, 10, 50"
}
],
"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.7 $"
}
],
"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"
}

View File

@ -0,0 +1,81 @@
<svg version="1.1" baseProfile="full" id="svg-root"
width="100%" height="100%" viewBox="0 0 480 360"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!--======================================================================-->
<!--= SVG 1.1 2nd Edition Test Case =-->
<!--======================================================================-->
<!--= Copyright 2009 World Wide Web Consortium, (Massachusetts =-->
<!--= Institute of Technology, European Research Consortium for =-->
<!--= Informatics and Mathematics (ERCIM), Keio University). =-->
<!--= All Rights Reserved. =-->
<!--= See http://www.w3.org/Consortium/Legal/. =-->
<!--======================================================================-->
<d:SVGTestCase xmlns:d="http://www.w3.org/2000/02/svg/testsuite/description/"
template-version="1.4" reviewer="AG" author="CM" status="accepted"
version="$Revision: 1.7 $" testname="$RCSfile: masking-filter-01-f.svg,v $">
<d:testDescription xmlns="http://www.w3.org/1999/xhtml" href="http://www.w3.org/TR/SVG11/masking.html#Introduction">
<p>
This tests that the 'filter' property does not apply to 'mask'.
</p>
<p>
The mask 'm' covers a rectangular area (200 x 200) except for a window
(100 x 100) in the top left hand corner. Initially the mask window is
set on top of the green square. Hence, the green square is shown and
the red square is covered. If filters are supported the window within
the mask will be shifted by an offset of 100,100 placing it on top of
the red square.
</p>
</d:testDescription>
<d:operatorScript xmlns="http://www.w3.org/1999/xhtml">
<p>
Run the test. No interaction required.
</p>
</d:operatorScript>
<d:passCriteria xmlns="http://www.w3.org/1999/xhtml">
<p>
The test passes if a green square is shown. If any
red shows, the test has failed.
</p>
</d:passCriteria>
</d:SVGTestCase>
<title id="test-title">$RCSfile: masking-filter-01-f.svg,v $</title>
<defs>
<font-face font-family="SVGFreeSansASCII" unicode-range="U+0-7F">
<font-face-src>
<font-face-uri xlink:href="../resources/SVGFreeSans.svg#ascii"/>
</font-face-src>
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<g shape-rendering="geometricPrecision">
<text font-size="18" x="10" y="35">Testing 'filter' applied to 'mask'</text>
<defs>
<filter id="f" x="0" y="0" width="200" height="200"
filterUnits="userSpaceOnUse" filterPrimitiveUnits="userSpaceOnUse">
<feOffset dx="100" dy="100"/>
</filter>
<mask id="m" x="0" y="0" width="200" height="200"
maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse"
filter="url(#f)">
<rect width="100" height="100" fill="white"/>
</mask>
</defs>
<g mask="url(#m)" transform="translate(10,50)">
<rect width="100" height="100" fill="green"/>
<rect x="101" y="101" width="99" height="99" fill="red"/>
</g>
</g>
</g>
<g font-family="SVGFreeSansASCII,sans-serif" font-size="32">
<text id="revision" x="10" y="340" stroke="none" fill="black">$Revision: 1.7 $</text>
</g>
<rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
<!-- comment out this watermark once the test is approved -->
<!--<g id="draft-watermark">
<rect x="1" y="1" width="478" height="20" fill="red" stroke="black" stroke-width="1"/>
<text font-family="SVGFreeSansASCII,sans-serif" font-weight="bold" font-size="20" x="240"
text-anchor="middle" y="18" stroke-width="0.5" stroke="black" fill="white">DRAFT</text>
</g>-->
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,83 @@
{
"contents" : [
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 32768
},
"form" : {
"h" : 150,
"type" : "Rect",
"w" : 250,
"x" : 100,
"y" : 100
},
"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"
}

View File

@ -0,0 +1,50 @@
<svg id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!--======================================================================-->
<!--= Copyright 2008 World Wide Web Consortium, (Massachusetts =-->
<!--= Institute of Technology, European Research Consortium for =-->
<!--= Informatics and Mathematics (ERCIM), Keio University). =-->
<!--= All Rights Reserved. =-->
<!--= See http://www.w3.org/Consortium/Legal/. =-->
<!--======================================================================-->
<d:SVGTestCase xmlns:d="http://www.w3.org/2000/02/svg/testsuite/description/" template-version="1.4" reviewer="CL" author="Microsoft" status="accepted" version="$Revision: 1.3 $" testname="$RCSfile: masking-mask-02-f.svg,v $">
<d:testDescription xmlns="http://www.w3.org/1999/xhtml" href="http://dev.w3.org/SVG/profiles/1.1F2/publish/masking.html#Masking">
<p>
If the 'mask' property references a 'mask' element containing no children, the element referencing it is not rendered.
</p>
</d:testDescription>
<d:operatorScript xmlns="http://www.w3.org/1999/xhtml">
<p>Run the test. No interaction required.</p>
</d:operatorScript>
<d:passCriteria xmlns="http://www.w3.org/1999/xhtml">
<p>
Test passes if there is a single green rectangle, with no red visible on the page.
</p>
</d:passCriteria>
</d:SVGTestCase>
<title id="test-title">$RCSfile: masking-mask-02-f.svg,v $</title>
<defs>
<font-face
font-family="SVGFreeSansASCII"
unicode-range="U+0-7F">
<font-face-src>
<font-face-uri xlink:href="../resources/SVGFreeSans.svg#ascii"/>
</font-face-src>
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<mask id="testMask" />
<rect x="100" y="100" width="250" height="150" fill="green" />
<rect x="100" y="100" width="250" height="150" fill="red" mask="url(#testMask)" />
</g>
<g font-family="SVGFreeSansASCII,sans-serif" font-size="32">
<text id="revision" x="10" y="340" stroke="none"
fill="black">$Revision: 1.3 $</text>
</g>
<rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000"/>
<!-- comment out this watermark once the test is approved
<g id="draft-watermark">
<rect x="1" y="1" width="478" height="20" fill="red" stroke="black" stroke-width="1"/>
<text font-family="SVGFreeSansASCII,sans-serif" font-weight="bold" font-size="20" x="240"
text-anchor="middle" y="18" stroke-width="0.5" stroke="black" fill="white">DRAFT</text>
</g>-->
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,83 @@
{
"contents" : [
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 32768
},
"form" : {
"h" : 100,
"type" : "Rect",
"w" : 200,
"x" : 100,
"y" : 100
},
"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.2 $"
}
],
"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"
}

View File

@ -0,0 +1,52 @@
<svg id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!--======================================================================-->
<!--= SVG 1.1 2nd Edition Test Case =-->
<!--======================================================================-->
<!--= Copyright 2008 World Wide Web Consortium, (Massachusetts =-->
<!--= Institute of Technology, European Research Consortium for =-->
<!--= Informatics and Mathematics (ERCIM), Keio University). =-->
<!--= All Rights Reserved. =-->
<!--= See http://www.w3.org/Consortium/Legal/. =-->
<!--======================================================================-->
<d:SVGTestCase xmlns:d="http://www.w3.org/2000/02/svg/testsuite/description/" template-version="1.4" reviewer="CL" author="Microsoft" status="accepted" version="$Revision: 1.2 $" testname="$RCSfile: masking-path-13-f.svg,v $">
<d:testDescription xmlns="http://www.w3.org/1999/xhtml" href="http://dev.w3.org/SVG/profiles/1.1F2/publish/masking.html#clipPath-geometry">
<p>
Test that the children of the 'clipPath' element are not rendered directly.
</p>
</d:testDescription>
<d:passCriteria xmlns="http://www.w3.org/1999/xhtml">
<p>
Test passes if there is a green rectangle, and no red visible on the page.
</p>
</d:passCriteria>
</d:SVGTestCase>
<title id="test-title">$RCSfile: masking-path-13-f.svg,v $</title>
<defs>
<font-face
font-family="SVGFreeSansASCII"
unicode-range="U+0-7F">
<font-face-src>
<font-face-uri xlink:href="../resources/SVGFreeSans.svg#ascii"/>
</font-face-src>
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<rect x="100" y="100" width="200" height="100" fill="green" />
<clipPath id="testClip">
<rect x="100" y="100" width="200" height="100" fill="red" />
</clipPath>
</g>
<g font-family="SVGFreeSansASCII,sans-serif" font-size="32">
<text id="revision" x="10" y="340" stroke="none"
fill="black">$Revision: 1.2 $</text>
</g>
<rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000"/>
<!-- comment out this watermark once the test is approved -->
<!--
<g id="draft-watermark">
<rect x="1" y="1" width="478" height="20" fill="red" stroke="black" stroke-width="1"/>
<text font-family="SVGFreeSansASCII,sans-serif" font-weight="bold" font-size="20" x="240"
text-anchor="middle" y="18" stroke-width="0.5" stroke="black" fill="white">DRAFT</text>
</g>
-->
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -150,7 +150,7 @@ open class Image: Node {
}
// Base64 image
let decodableFormat = ["image/png", "image/jpg"]
let decodableFormat = ["image/png", "image/jpg", "image/svg+xml"]
for format in decodableFormat {
let prefix = "data:\(format);base64,"
if src.hasPrefix(prefix) {

View File

@ -266,47 +266,60 @@ open class SVGParser {
guard let element = node.element else {
return .none
}
let hasMask = style["mask"] != .none
let position = getPosition(element)
switch element.name {
case "path":
if var path = parsePath(node) {
let mask = try getMask(style, locus: path)
if let rule = getFillRule(style) {
path = Path(segments: path.segments, fillRule: rule)
}
let mask = try getMask(style, locus: path)
return Shape(form: path, fill: getFillColor(style, groupStyle: style, locus: path), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: path), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: path, fill: getFillColor(style, groupStyle: style, locus: path), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: path), mask: mask, tag: getTag(element))
}
}
case "line":
if let line = parseLine(node) {
let mask = try getMask(style, locus: line)
return Shape(form: line, fill: getFillColor(style, groupStyle: style, locus: line), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: line), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: line, fill: getFillColor(style, groupStyle: style, locus: line), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: line), mask: mask, tag: getTag(element))
}
}
case "rect":
if let rect = parseRect(node) {
let mask = try getMask(style, locus: rect)
return Shape(form: rect, fill: getFillColor(style, groupStyle: style, locus: rect), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: rect), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: rect, fill: getFillColor(style, groupStyle: style, locus: rect), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: rect), mask: mask, tag: getTag(element))
}
}
case "circle":
if let circle = parseCircle(node) {
let mask = try getMask(style, locus: circle)
return Shape(form: circle, fill: getFillColor(style, groupStyle: style, locus: circle), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: circle), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: circle, fill: getFillColor(style, groupStyle: style, locus: circle), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: circle), mask: mask, tag: getTag(element))
}
}
case "ellipse":
if let ellipse = parseEllipse(node) {
let mask = try getMask(style, locus: ellipse)
return Shape(form: ellipse, fill: getFillColor(style, groupStyle: style, locus: ellipse), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: ellipse), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: ellipse, fill: getFillColor(style, groupStyle: style, locus: ellipse), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: ellipse), mask: mask, tag: getTag(element))
}
}
case "polygon":
if let polygon = parsePolygon(node) {
let mask = try getMask(style, locus: polygon)
return Shape(form: polygon, fill: getFillColor(style, groupStyle: style, locus: polygon), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: polygon), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: polygon, fill: getFillColor(style, groupStyle: style, locus: polygon), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: polygon), mask: mask, tag: getTag(element))
}
}
case "polyline":
if let polyline = parsePolyline(node) {
let mask = try getMask(style, locus: polyline)
return Shape(form: polyline, fill: getFillColor(style, groupStyle: style, locus: polyline), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: polyline), mask: mask, tag: getTag(element))
if !hasMask || hasMask && mask != .none {
return Shape(form: polyline, fill: getFillColor(style, groupStyle: style, locus: polyline), stroke: getStroke(style, groupStyle: style), place: position, opacity: getOpacity(style), clip: getClipPath(style, locus: polyline), mask: mask, tag: getTag(element))
}
}
case "image":
return parseImage(node, opacity: getOpacity(style), pos: position, clip: getClipPath(style, locus: nil))
@ -1103,7 +1116,11 @@ open class SVGParser {
}
}
}
return UserSpaceLocus(locus: path!, userSpace: userSpace)
if let path = path {
return UserSpaceLocus(locus: path, userSpace: userSpace)
}
return .none
}
fileprivate func parseMask(_ mask: XMLIndexer) throws -> UserSpaceNode? {
@ -1510,7 +1527,10 @@ open class SVGParser {
}
fileprivate func getMask(_ attributes: [String: String], locus: Locus?) throws -> Node? {
guard let maskName = attributes["mask"], let id = parseIdFromUrl(maskName), let userSpaceNode = defMasks[id], let locus = locus else {
guard let maskName = attributes["mask"], let locus = locus else {
return .none
}
guard let id = parseIdFromUrl(maskName), let userSpaceNode = defMasks[id] else {
return .none
}
if !userSpaceNode.userSpace {