1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-09-11 05:05:23 +03:00

Merge branch 'master'

Conflicts:
	Macaw.xcodeproj/project.pbxproj
	MacawTests/MacawSVGTests.swift
	MacawTests/w3c-test-suite.md
This commit is contained in:
Daniil Manin 2019-05-31 19:24:57 +07:00
commit f72a31a925
23 changed files with 1444 additions and 39 deletions

View File

@ -1,4 +1,4 @@
language: objective-c
language: swift
osx_image: xcode10.2
branches:
@ -7,7 +7,8 @@ branches:
script:
- set -o pipefail && xcodebuild test -project Macaw.xcodeproj -scheme 'Macaw iOS' -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,OS=12.2,name=iPhone X' | xcpretty;
- set -o pipefail && xcodebuild build -project Macaw.xcodeproj -scheme 'MacawOSX' ONLY_ACTIVE_ARCH=NO | xcpretty;
- set -o pipefail && xcodebuild test -project Macaw.xcodeproj -scheme 'MacawOSX' ONLY_ACTIVE_ARCH=NO | xcpretty;
notifications:
slack: exyte:kdo9FNtTOFMuMqAyyvZPDAD7

View File

@ -21,6 +21,7 @@
30FF4971215CF4CE00FF653C /* MCAMediaTimingFunctionName_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FF4970215CF4CE00FF653C /* MCAMediaTimingFunctionName_macOS.swift */; };
421C66502225196900DD73F5 /* color-prop-04-t-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = 421C664F2225196900DD73F5 /* color-prop-04-t-manual.svg */; };
4269F43E2257265800D91393 /* color-prop-04-t-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = 4269F43D2257265700D91393 /* color-prop-04-t-manual.reference */; };
42D86F3C229E86300035DE11 /* README in Resources */ = {isa = PBXBuildFile; fileRef = 42D86F3B229E86300035DE11 /* README */; };
5713C4E21E51EC8F00BBA4D9 /* TouchEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4E11E51EC8F00BBA4D9 /* TouchEvent.swift */; };
5713C4F31E5AD46800BBA4D9 /* ControlStatesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F21E5AD46800BBA4D9 /* ControlStatesTests.swift */; };
5713C4F51E5AE2C300BBA4D9 /* CombineAnimationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5713C4F41E5AE2C300BBA4D9 /* CombineAnimationTests.swift */; };
@ -223,7 +224,6 @@
57F108741F502A3600DC365B /* Touchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F108731F502A3600DC365B /* Touchable.swift */; };
57F1087A1F53C92000DC365B /* MDisplayLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F108791F53C92000DC365B /* MDisplayLink.swift */; };
57F1087C1F53CA7E00DC365B /* MDisplayLink_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57F1087B1F53CA7E00DC365B /* MDisplayLink_iOS.swift */; };
57FCD2771D76EA4600CC0FB6 /* Macaw.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57FCD26C1D76EA4600CC0FB6 /* Macaw.framework */; };
57FCD27C1D76EA4600CC0FB6 /* MacawTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57FCD27B1D76EA4600CC0FB6 /* MacawTests.swift */; };
5815D59D2186E89A00BD08F9 /* CSSParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815D59C2186E89A00BD08F9 /* CSSParser.swift */; };
5815D59E2186E89A00BD08F9 /* CSSParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815D59C2186E89A00BD08F9 /* CSSParser.swift */; };
@ -546,6 +546,14 @@
A74C82F3229E369A0085A832 /* pservers-grad-09-b-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C82EC229E36990085A832 /* pservers-grad-09-b-manual.reference */; };
A74C82F4229E369A0085A832 /* pservers-grad-13-b-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C82ED229E36990085A832 /* pservers-grad-13-b-manual.reference */; };
A74C82F5229E369A0085A832 /* pservers-grad-22-b-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = A74C82EE229E369A0085A832 /* pservers-grad-22-b-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 */; };
@ -599,6 +607,7 @@
30FF4970215CF4CE00FF653C /* MCAMediaTimingFunctionName_macOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCAMediaTimingFunctionName_macOS.swift; sourceTree = "<group>"; };
421C664F2225196900DD73F5 /* color-prop-04-t-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual.svg"; sourceTree = "<group>"; };
4269F43D2257265700D91393 /* color-prop-04-t-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "color-prop-04-t-manual.reference"; sourceTree = "<group>"; };
42D86F3B229E86300035DE11 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
5713C4E11E51EC8F00BBA4D9 /* TouchEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchEvent.swift; sourceTree = "<group>"; };
5713C4F21E5AD46800BBA4D9 /* ControlStatesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlStatesTests.swift; sourceTree = "<group>"; };
5713C4F41E5AE2C300BBA4D9 /* CombineAnimationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineAnimationTests.swift; sourceTree = "<group>"; };
@ -999,6 +1008,14 @@
A74C82EC229E36990085A832 /* pservers-grad-09-b-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-grad-09-b-manual.reference"; sourceTree = "<group>"; };
A74C82ED229E36990085A832 /* pservers-grad-13-b-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-grad-13-b-manual.reference"; sourceTree = "<group>"; };
A74C82EE229E369A0085A832 /* pservers-grad-22-b-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "pservers-grad-22-b-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>"; };
@ -1027,7 +1044,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
57FCD2771D76EA4600CC0FB6 /* Macaw.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1419,12 +1435,13 @@
5713C4F11E5AD35900BBA4D9 /* Animation */,
57CAB1241D7832E000FD8E47 /* svg */,
5B1AE18320B6A669007EECCB /* w3cSVGTests */,
57CAB1221D782DFC00FD8E47 /* TestUtils.swift */,
57FCD27B1D76EA4600CC0FB6 /* MacawTests.swift */,
C4820B191F458D64008CE0FF /* MacawSVGTests.swift */,
5BAE2057208F24DE006BF277 /* SceneSerialization.swift */,
57FCD27D1D76EA4600CC0FB6 /* Info.plist */,
6A616BFB212964E8006A07FA /* SVGParserTest.swift */,
5BAE2057208F24DE006BF277 /* SceneSerialization.swift */,
57CAB1221D782DFC00FD8E47 /* TestUtils.swift */,
42D86F3B229E86300035DE11 /* README */,
57FCD27D1D76EA4600CC0FB6 /* Info.plist */,
);
path = MacawTests;
sourceTree = "<group>";
@ -1448,6 +1465,8 @@
5B1AE20320B6A669007EECCB /* color-prop-03-t-manual.svg */,
4269F43D2257265700D91393 /* color-prop-04-t-manual.reference */,
421C664F2225196900DD73F5 /* color-prop-04-t-manual.svg */,
A74C832D229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference */,
A74C832B229FB7690085A832 /* color-prop-04-t-manual-osx.svg */,
A74C81F22292B45D0085A832 /* color-prop-05-t-manual.reference */,
A74C81F02292B3940085A832 /* color-prop-05-t-manual.svg */,
5B1AE1D420B6A669007EECCB /* coords-coord-01-t-manual.reference */,
@ -1496,6 +1515,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 */,
@ -1876,6 +1901,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 */,
@ -1927,11 +1953,13 @@
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 */,
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 */,
58944BDA20AC8A9A00657640 /* logo_base64.txt in Resources */,
5B1AE2C520B6A669007EECCB /* coords-trans-02-t-manual.svg in Resources */,
@ -1946,6 +1974,7 @@
A74C82E1229E35D30085A832 /* pservers-grad-09-b-manual.svg 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 */,
@ -2027,6 +2056,7 @@
5B1AE29920B6A669007EECCB /* pservers-grad-stops-01-f-manual.svg in Resources */,
5B1AE27520B6A669007EECCB /* struct-frag-04-t-manual.reference in Resources */,
A74C82292297D5350085A832 /* coords-trans-12-f-manual.reference in Resources */,
A74C832E229FBA4C0085A832 /* color-prop-04-t-manual-osx.reference in Resources */,
5B1AE28720B6A669007EECCB /* render-elems-03-t-manual.svg in Resources */,
5B1AE2AD20B6A669007EECCB /* painting-stroke-05-t-manual.reference in Resources */,
5B1AE25920B6A669007EECCB /* coords-trans-01-b-manual.svg in Resources */,
@ -2084,6 +2114,7 @@
57CAB1311D7832E000FD8E47 /* line.svg in Resources */,
A74C82222297D4810085A832 /* coords-trans-10-f-manual.svg in Resources */,
57B7A4DF1EE70D17009D78D7 /* logo.png in Resources */,
A74C832C229FB7690085A832 /* color-prop-04-t-manual-osx.svg in Resources */,
5B1AE24F20B6A669007EECCB /* painting-stroke-02-t-manual.reference in Resources */,
5B1AE28420B6A669007EECCB /* shapes-polyline-01-t-manual.reference in Resources */,
5B1AE2C320B6A669007EECCB /* text-fonts-02-t-manual.reference in Resources */,
@ -2091,6 +2122,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 */,
@ -2111,6 +2143,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 */,
@ -2124,6 +2157,7 @@
A74C82E7229E35D30085A832 /* pservers-grad-12-b-manual.svg in Resources */,
5B1AE25F20B6A669007EECCB /* coords-transformattr-05-f-manual.svg in Resources */,
57CAB1341D7832E000FD8E47 /* rect.svg in Resources */,
42D86F3C229E86300035DE11 /* README in Resources */,
5B1AE2D920B6A669007EECCB /* render-elems-03-t-manual.reference in Resources */,
5B1AE28120B6A669007EECCB /* coords-transformattr-04-f-manual.svg in Resources */,
5B1AE2B020B6A669007EECCB /* paths-data-16-t-manual.svg in Resources */,

View File

@ -28,7 +28,26 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "57FCD2751D76EA4600CC0FB6"
BuildableName = "MacawTests.xctest"
BlueprintName = "MacawTests"
ReferencedContainer = "container:Macaw.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "57614AFB1F83D15600875933"
BuildableName = "MacawOSX.framework"
BlueprintName = "MacawOSX"
ReferencedContainer = "container:Macaw.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>

View File

@ -7,7 +7,13 @@
//
import XCTest
#if os(OSX)
@testable import MacawOSX
#endif
#if os(iOS)
@testable import Macaw
#endif
class AnimationUtilsTests: XCTestCase {

View File

@ -7,7 +7,14 @@
//
import XCTest
#if os(OSX)
@testable import MacawOSX
#endif
#if os(iOS)
@testable import Macaw
#endif
class ControlStatesTests: XCTestCase {

View File

@ -1,5 +1,12 @@
import XCTest
#if os(OSX)
@testable import MacawOSX
#endif
#if os(iOS)
@testable import Macaw
#endif
class MacawSVGTests: XCTestCase {
@ -105,10 +112,13 @@ class MacawSVGTests: XCTestCase {
func testSVGImage() {
let bundle = Bundle(for: type(of: TestUtils()))
if let path = bundle.path(forResource: "small-logo", ofType: "png") {
if let mimage = MImage(contentsOfFile: path), let base64Content = MImagePNGRepresentation(mimage)?.base64EncodedString() {
let node = Image(image: mimage)
let imageReferenceContent = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" ><image xlink:href=\"data:image/png;base64,\(String(base64Content))\" width=\"59.0\" height=\"43.0\" /></svg>"
XCTAssertEqual(SVGSerializer.serialize(node: node), imageReferenceContent)
if let mImage = MImage(contentsOfFile: path), let base64Content = MImagePNGRepresentation(mImage)?.base64EncodedString() {
let imageSize = mImage.size
let imageReferenceContent = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" ><image xlink:href=\"data:image/png;base64,\(String(base64Content))\" width=\"\(imageSize.width)\" height=\"\(imageSize.height)\" /></svg>"
let node = Image(image: mImage)
let imageSerialization = SVGSerializer.serialize(node: node)
XCTAssertEqual(imageSerialization, imageReferenceContent)
}
}
}
@ -214,11 +224,24 @@ class MacawSVGTests: XCTestCase {
return Data()
}
do {
#if os(OSX)
if #available(OSX 10.13, *) {
return try JSONSerialization.data(withJSONObject: serializableNode.toDictionary(), options: [.prettyPrinted, .sortedKeys])
} else {
return try JSONSerialization.data(withJSONObject: serializableNode.toDictionary(), options: .prettyPrinted)
}
#endif
#if os(iOS)
if #available(iOS 11.0, *) {
return try JSONSerialization.data(withJSONObject: serializableNode.toDictionary(), options: [.prettyPrinted, .sortedKeys])
} else {
return try JSONSerialization.data(withJSONObject: serializableNode.toDictionary(), options: .prettyPrinted)
}
#endif
} catch {
XCTFail(error.localizedDescription)
return Data()
@ -546,7 +569,11 @@ class MacawSVGTests: XCTestCase {
}
func testColorProp04() {
#if os(iOS)
validateJSON("color-prop-04-t-manual")
#elseif os(OSX)
validateJSON("color-prop-04-t-manual-osx")
#endif
}
func testTypesBasic01() {
@ -656,14 +683,6 @@ class MacawSVGTests: XCTestCase {
func testShapesGrammar01() {
validateJSON("shapes-grammar-01-f-manual")
}
func testMaskingPath02() {
validateJSON("masking-path-02-b-manual")
}
func testMaskingIntro01() {
validateJSON("masking-intro-01-f-manual")
}
func testPserversGrad01() {
validateJSON("pservers-grad-01-b-manual")
@ -708,4 +727,24 @@ class MacawSVGTests: XCTestCase {
func testPserversGrad24() {
validateJSON("pservers-grad-24-f-manual")
}
func testMaskingIntro01() {
validateJSON("masking-intro-01-f-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

@ -1,5 +1,11 @@
import XCTest
#if os(OSX)
@testable import MacawOSX
#endif
#if os(iOS)
@testable import Macaw
#endif
class MacawTests: XCTestCase {

2
MacawTests/README Normal file
View File

@ -0,0 +1,2 @@
To run test on iOs add Macaw to MacawTests Target Membership.
To run test on Mac add MacawOSX to MacawTests Target Membership.

View File

@ -7,7 +7,13 @@
//
import XCTest
#if os(OSX)
@testable import MacawOSX
#endif
#if os(iOS)
@testable import Macaw
#endif
class SVGParserTest: XCTestCase {
func testParseFromOtherBundle() {

View File

@ -6,8 +6,15 @@
// Copyright © 2018 Exyte. All rights reserved.
//
#if os(OSX)
import Foundation
@testable import MacawOSX
#endif
#if os(iOS)
import UIKit
@testable import Macaw
#endif
protocol Initializable {
init()
@ -367,12 +374,23 @@ extension Path: Serializable {
}
}
#if os(iOS)
extension Polygon: Serializable {
func toDictionary() -> [String:Any] {
return ["type": "Polygon", "points": points]
}
}
#endif
#if os(OSX)
extension MacawOSX.Polygon: Serializable {
func toDictionary() -> [String:Any] {
return ["type": "Polygon", "points": points]
}
}
#endif
extension Polyline: Serializable {

View File

@ -1,5 +1,11 @@
import Foundation
import Macaw
#if os(OSX)
@testable import MacawOSX
#endif
#if os(iOS)
@testable import Macaw
#endif
class TestUtils {

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:
* 37.6% passed (115)
* 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)
* 16.7% blocked by issues (51)
* 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,642 @@
{
"contents" : [
{
"contents" : [
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 6513614
},
"form" : {
"h" : 300,
"type" : "Rect",
"w" : 460,
"x" : -230,
"y" : -170
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 11184810
},
"form" : {
"h" : 280,
"type" : "Rect",
"w" : 440,
"x" : -220,
"y" : -160
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 15527148
},
"form" : {
"h" : 221,
"type" : "Rect",
"w" : 317,
"x" : -152,
"y" : -108
},
"node" : "Shape"
},
{
"form" : {
"h" : 221,
"type" : "Rect",
"w" : 317,
"x" : -152,
"y" : -108
},
"node" : "Shape",
"stroke" : {
"cap" : "butt",
"dashes" : [
],
"fill" : {
"type" : "Color",
"val" : 11184810
},
"join" : "miter",
"width" : 3
}
},
{
"contents" : [
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 2368548
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 12,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -148, 0",
"text" : "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 2368548
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 12,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -148, 20",
"text" : "Vestibulum pulvinar. Duis laoreet, nunc vitae facilisis "
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 2368548
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 12,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -148, 40",
"text" : "tristique, pede sem iaculis mi, non consectetuer lorem "
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 2368548
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 12,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -148, 60",
"text" : "libero et est. Donec imperdiet purus sed odio. Duis "
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 2368548
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 12,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -148, 80",
"text" : "venenatis tortor eu lectus. Suspendisse sed metus at "
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 2368548
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 12,
"weight" : "normal"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -148, 100",
"text" : "metus viverra ultricies. Mauris porttitor, justo a vulputate"
}
],
"node" : "Group"
},
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 12632256
},
"form" : {
"h" : 190,
"type" : "Rect",
"w" : 118,
"x" : -150,
"y" : -107
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 16185078
},
"form" : {
"h" : 34,
"type" : "Rect",
"w" : 102,
"x" : -143,
"y" : 0
},
"node" : "Shape"
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 16777215
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 20,
"weight" : "bold"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -138, 24",
"text" : "Load"
},
{
"fill" : {
"type" : "Color",
"val" : 16185078
},
"form" : {
"h" : 34,
"type" : "Rect",
"w" : 102,
"x" : -143,
"y" : 40
},
"node" : "Shape"
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 16777215
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 20,
"weight" : "bold"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -138, 64",
"text" : "Save"
},
{
"form" : {
"segments" : [
{
"data" : [
-149,
83
],
"type" : "M"
},
{
"data" : [
114
],
"type" : "h"
},
{
"data" : [
-94
],
"type" : "v"
}
],
"type" : "Path"
},
"node" : "Shape",
"stroke" : {
"cap" : "butt",
"dashes" : [
],
"fill" : {
"type" : "Color",
"val" : 0
},
"join" : "miter",
"width" : 4
}
},
{
"form" : {
"segments" : [
{
"data" : [
-149,
83
],
"type" : "M"
},
{
"data" : [
-94
],
"type" : "v"
},
{
"data" : [
114
],
"type" : "h"
}
],
"type" : "Path"
},
"node" : "Shape",
"stroke" : {
"cap" : "butt",
"dashes" : [
],
"fill" : {
"type" : "Color",
"val" : 16777215
},
"join" : "miter",
"width" : 4
}
}
],
"node" : "Group",
"place" : "1, 0, 0, 1, 2, 0"
},
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 16777215
},
"form" : {
"h" : 46,
"type" : "Rect",
"w" : 310,
"x" : -148,
"y" : -62
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 0
},
"form" : {
"segments" : [
{
"data" : [
152,
-52
],
"type" : "M"
},
{
"data" : [
10,
-10
],
"type" : "l"
},
{
"data" : [
46
],
"type" : "v"
},
{
"data" : [
-311
],
"type" : "h"
},
{
"data" : [
10,
-10
],
"type" : "l"
},
{
"data" : [
],
"type" : "z"
}
],
"type" : "Path"
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 12632256
},
"form" : {
"h" : 37,
"type" : "Rect",
"w" : 302,
"x" : -144,
"y" : -58
},
"node" : "Shape"
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 0
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 20,
"weight" : "bold"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -141, -32",
"text" : "File"
},
{
"align" : "min",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 16777215
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 20,
"weight" : "bold"
},
"node" : "Text",
"place" : "1, 0, 0, 1, -90, -32",
"text" : "Edit"
}
],
"node" : "Group"
},
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 2368548
},
"form" : {
"h" : 42,
"type" : "Rect",
"w" : 311,
"x" : -149,
"y" : -106
},
"node" : "Shape",
"stroke" : {
"cap" : "butt",
"dashes" : [
],
"fill" : {
"type" : "Color",
"val" : 2569694413
},
"join" : "miter",
"width" : 4
}
},
{
"align" : "mid",
"baseline" : "bottom",
"fill" : {
"type" : "Color",
"val" : 0
},
"font" : {
"name" : "SVGFreeSansASCII,sans-serif",
"size" : 24,
"weight" : "bold"
},
"node" : "Text",
"place" : "1, 0, 0, 1, 5, -78",
"text" : "Lorem"
},
{
"contents" : [
{
"fill" : {
"type" : "Color",
"val" : 12632256
},
"form" : {
"rect" : {
"h" : 26,
"type" : "Rect",
"w" : 26,
"x" : 120,
"y" : -99
},
"rx" : 8,
"ry" : 8,
"type" : "RoundRect"
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 16777215
},
"form" : {
"rect" : {
"h" : 24,
"type" : "Rect",
"w" : 24,
"x" : 120,
"y" : -99
},
"rx" : 8,
"ry" : 8,
"type" : "RoundRect"
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 9276813
},
"form" : {
"rect" : {
"h" : 24,
"type" : "Rect",
"w" : 24,
"x" : 122,
"y" : -97
},
"rx" : 8,
"ry" : 8,
"type" : "RoundRect"
},
"node" : "Shape"
},
{
"fill" : {
"type" : "Color",
"val" : 12632256
},
"form" : {
"rect" : {
"h" : 22,
"type" : "Rect",
"w" : 22,
"x" : 122,
"y" : -97
},
"rx" : 8,
"ry" : 8,
"type" : "RoundRect"
},
"node" : "Shape"
}
],
"node" : "Group"
}
],
"node" : "Group"
}
],
"node" : "Group",
"place" : "1, 0, 0, 1, 240, 180"
}
],
"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,96 @@
<svg version="1.1" baseProfile="tiny" 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="[reviewer]" author="CL" status="accepted"
version="$Revision: 1.7 $" testname="$RCSfile: color-prop-04-t.svg,v $">
<d:testDescription xmlns="http://www.w3.org/1999/xhtml" href="http://www.w3.org/TR/SVG11/color.html#ColorProperty">
<p>
This tests the 'system' colors.
</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>
This test has no specific pass criteria, except that no error must be indicated.
</p>
<p>
The colors on your screen might not match the reference
image at all, but they should at minimum be legible and should
preferably resemble the colors used on menus and other user interface
elements on your computer, pda or phone.
</p>
</d:passCriteria>
</d:SVGTestCase>
<title id="test-title">$RCSfile: color-prop-04-t.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 id="Scene_1" transform="translate(240, 180)">
<rect x="-230" y="-170" width="460" height="300" fill="Background"/>
<rect x="-220" y="-160" width="440" height="280" fill="AppWorkspace"/>
<rect x="-152" y="-108" width="317" height="221" fill="Window"/>
<rect x="-152" y="-108" width="317" height="221" fill="none" stroke-width="3" stroke="WindowFrame"/>
<g id="contents" font-size="12" fill="WindowText">
<text x="-148" y="0">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. </text>
<text x="-148" y="20">Vestibulum pulvinar. Duis laoreet, nunc vitae facilisis </text>
<text x="-148" y="40">tristique, pede sem iaculis mi, non consectetuer lorem </text>
<text x="-148" y="60">libero et est. Donec imperdiet purus sed odio. Duis </text>
<text x="-148" y="80">venenatis tortor eu lectus. Suspendisse sed metus at </text>
<text x="-148" y="100">metus viverra ultricies. Mauris porttitor, justo a vulputate</text>
</g>
<g id="dropdown" transform="translate(2,0)">
<rect x="-150" y="-107" width="118" height="190" fill="ThreeDFace" id="drop-bg"/>
<rect x="-143" y="0" width="102" height="34" fill="Menu"/>
<text x="-138" y="24" font-size="20" font-weight="bold" fill="MenuText">Load</text>
<rect x="-143" y="40" width="102" height="34" fill="Menu"/>
<text x="-138" y="64" font-size="20" font-weight="bold" fill="MenuText">Save</text>
<path d="M-149 83 h114 v-94" stroke-width="4" stroke="ThreeDDarkShadow" fill="none"/>
<path d="M-149 83 v-94 h114" stroke-width="4" stroke="ThreeDLightShadow" fill="none"/>
</g>
<g id="menubar">
<rect x="-148" y="-62" width="310" height="46" fill="ThreeDLightShadow"/>
<path d="M152 -52 l 10 -10 v 46 h -311 l10-10 z" fill="ThreeDDarkShadow"/>
<rect x="-144" y="-58" width="302" height="37" fill="ThreeDFace"/>
<text x="-141" y="-32" font-size="20" font-weight="bold" fill="HighlightText">File</text>
<text x="-90" y="-32" font-size="20" font-weight="bold" fill="MenuText">Edit</text>
</g>
<g id="windowdecoration">
<rect x="-149" y="-106" width="311" height="42" fill="ActiveCaption" stroke-width="4" stroke="ActiveBorder" id="windowbar"/>
<text x="5" y="-78" text-anchor="middle" font-size="24" font-weight="bold" fill="CaptionText">Lorem</text>
<g id="button">
<rect x="120" y="-99" rx="8" width="26" height="26" fill="ButtonFace"/>
<rect x="120" y="-99" rx="8" width="24" height="24" fill="ButtonHighlight"/>
<rect x="122" y="-97" rx="8" width="24" height="24" fill="ButtonShadow"/>
<rect x="122" y="-97" rx="8" width="22" height="22" fill="ButtonFace"/>
</g>
</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: 5.7 KiB

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

@ -8,6 +8,8 @@
<img src="https://raw.githubusercontent.com/exyte/Macaw/master/logo.png" width="400">
Stay tuned on [twitter](https://twitter.com/MacawFramework) or [Instagram](https://www.instagram.com/macaw_framework/).
## What is Macaw?
Macaw is a powerful and easy-to-use vector graphics library written in Swift.

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 {