Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 717198457b | |||
| e2991ab8b0 | |||
| dda3e5ed8c | |||
| c3a0fb5b91 | |||
| 7ce4520a56 | |||
| 368d19ea81 | |||
| d26c2f489f | |||
| 75b0d55b63 | |||
| 310308cd8a | |||
| 278f405a41 | |||
| 7addd97d0c | |||
| d01ca0f3bb | |||
| 6d7ad17e2a | |||
| deb09eaf04 | |||
| 1e7b8b38a5 | |||
| 58e1a8c45d | |||
| a525e4351a | |||
| c87716b311 | |||
| 583a930bf7 | |||
| ec2473d450 | |||
| 3cc477955a | |||
| 1f0ff52dff | |||
| e96bfa54b0 | |||
| cd3b540274 | |||
| 1cfbaf14e4 | |||
| 5a389f88d3 | |||
| 9f43832ff3 | |||
| 65623ec552 | |||
| 5192520b7c | |||
| 5123ee7308 | |||
| c886a6a80d | |||
| 4cd2895703 | |||
| a98d84f209 | |||
| 8faab28823 | |||
| cca5524a11 | |||
| c14e2367a0 | |||
| db4b0e9a18 | |||
| 93d6a868a9 | |||
| 60fa627d99 | |||
| ccaa350190 | |||
| 727f8a2dea | |||
| 972812b3f6 | |||
| ad8f440c72 | |||
| 68393b296b | |||
| 1cfcb596d9 | |||
| 69077e49cf | |||
| 3bdf2151ca | |||
| f7e28a2962 | |||
| 2c07cfabdd | |||
| 3e356b3fdc | |||
| 49f759edc0 | |||
| 38e314eb99 | |||
| d0eb015cf1 | |||
| 080626a022 | |||
| 36c20bc55c | |||
| 4d89631e9a | |||
| 65f62007f3 | |||
| af5f16288d | |||
| 08e0f9288d | |||
| 7650f6205c | |||
| 263768af5b | |||
| 4b1be17f9a | |||
| 6b0d6b1452 | |||
| f80d4145bb | |||
| f68c83285b | |||
| 1f4bd989d8 | |||
| 5b5d0b738b | |||
| bd82c5d81b | |||
| 145bbb17f8 | |||
| d9f40551a4 | |||
| 4448f6aeaf | |||
| 6834abba19 | |||
| a86b4e80ba | |||
| 2e8d039599 | |||
| 4ba6bb776d | |||
| 9c80412e88 | |||
| 509f0e0b0a | |||
| ce30877a26 | |||
| 122271bf36 | |||
| 28b4c6b85c | |||
| 4b308d3a3e | |||
| d3ee05d8ac | |||
| 204b516e77 | |||
| a832a986fd | |||
| f875714609 | |||
| b8f166f4c1 | |||
| 7901c9eafe | |||
| 5de88cb1d7 | |||
| 6216b61c19 | |||
| e05f5a0884 |
@@ -7,10 +7,20 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
5919E65723F47FF60051873A /* IJSVGUnitRect.h in Headers */ = {isa = PBXBuildFile; fileRef = 5919E65523F47FF60051873A /* IJSVGUnitRect.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
5919E65823F47FF60051873A /* IJSVGUnitRect.m in Sources */ = {isa = PBXBuildFile; fileRef = 5919E65623F47FF60051873A /* IJSVGUnitRect.m */; };
|
||||||
|
5919E65B23F480330051873A /* IJSVGUnitPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 5919E65923F480330051873A /* IJSVGUnitPoint.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
5919E65C23F480330051873A /* IJSVGUnitPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 5919E65A23F480330051873A /* IJSVGUnitPoint.m */; };
|
||||||
|
591A3E4D25CC91F800AD45B7 /* IJSVGParsing.h in Headers */ = {isa = PBXBuildFile; fileRef = 591A3E4B25CC91F800AD45B7 /* IJSVGParsing.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
591A3E4E25CC91F800AD45B7 /* IJSVGParsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 591A3E4C25CC91F800AD45B7 /* IJSVGParsing.m */; };
|
||||||
|
594A10DA248D7C90001A3181 /* NSImage+IJSVGAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
594A10DB248D7C90001A3181 /* NSImage+IJSVGAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */; };
|
||||||
594CF55F238FF462009B251B /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF55E238FF462009B251B /* AppKit.framework */; };
|
594CF55F238FF462009B251B /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF55E238FF462009B251B /* AppKit.framework */; };
|
||||||
594CF561238FF46C009B251B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF560238FF46C009B251B /* Foundation.framework */; };
|
594CF561238FF46C009B251B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF560238FF46C009B251B /* Foundation.framework */; };
|
||||||
594CF563238FF473009B251B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF562238FF473009B251B /* QuartzCore.framework */; };
|
594CF563238FF473009B251B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF562238FF473009B251B /* QuartzCore.framework */; };
|
||||||
599EB4D3238FF570004CB6BC /* libobjc.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 599EB4D2238FF535004CB6BC /* libobjc.tbd */; };
|
599EB4D3238FF570004CB6BC /* libobjc.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 599EB4D2238FF535004CB6BC /* libobjc.tbd */; };
|
||||||
|
59A24EBC23F480EA0090C374 /* IJSVGUnitSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A24EBA23F480EA0090C374 /* IJSVGUnitSize.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
59A24EBD23F480EA0090C374 /* IJSVGUnitSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A24EBB23F480EA0090C374 /* IJSVGUnitSize.m */; };
|
||||||
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */; };
|
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */; };
|
||||||
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756523905F6B00F5AE63 /* IJSVGLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756523905F6B00F5AE63 /* IJSVGLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
@@ -22,7 +32,6 @@
|
|||||||
59EB75DC23905F7300F5AE63 /* IJSVGText.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756B23905F6B00F5AE63 /* IJSVGText.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75DC23905F7300F5AE63 /* IJSVGText.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756B23905F6B00F5AE63 /* IJSVGText.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75DD23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */; };
|
59EB75DD23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */; };
|
||||||
59EB75DE23905F7300F5AE63 /* IJSVGCommandVerticalLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75DE23905F7300F5AE63 /* IJSVGCommandVerticalLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75DF23905F7300F5AE63 /* IJSVGWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756E23905F6C00F5AE63 /* IJSVGWriter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
59EB75E023905F7300F5AE63 /* IJSVGStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75E023905F7300F5AE63 /* IJSVGStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75E123905F7300F5AE63 /* IJSVGCommandSmoothCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75E123905F7300F5AE63 /* IJSVGCommandSmoothCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757123905F6C00F5AE63 /* IJSVGColorList.m */; };
|
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757123905F6C00F5AE63 /* IJSVGColorList.m */; };
|
||||||
@@ -49,12 +58,10 @@
|
|||||||
59EB75F723905F7300F5AE63 /* IJSVGDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758623905F6C00F5AE63 /* IJSVGDef.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75F723905F7300F5AE63 /* IJSVGDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758623905F6C00F5AE63 /* IJSVGDef.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */; };
|
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */; };
|
||||||
59EB75F923905F7300F5AE63 /* IJSVGFontConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75F923905F7300F5AE63 /* IJSVGFontConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75FA23905F7300F5AE63 /* IJSVGWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758923905F6D00F5AE63 /* IJSVGWriter.m */; };
|
|
||||||
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758A23905F6D00F5AE63 /* IJSVGPath.m */; };
|
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758A23905F6D00F5AE63 /* IJSVGPath.m */; };
|
||||||
59EB75FC23905F7300F5AE63 /* IJSVGGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB75FC23905F7300F5AE63 /* IJSVGGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */; };
|
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */; };
|
||||||
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */; };
|
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */; };
|
||||||
59EB75FF23905F7300F5AE63 /* IJSVGBezierPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758E23905F6D00F5AE63 /* IJSVGBezierPathAdditions.m */; };
|
|
||||||
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */; };
|
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */; };
|
||||||
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */; };
|
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */; };
|
||||||
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */; };
|
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */; };
|
||||||
@@ -105,7 +112,6 @@
|
|||||||
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C023905F7100F5AE63 /* IJSVGText.m */; };
|
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C023905F7100F5AE63 /* IJSVGText.m */; };
|
||||||
59EB763223905F7300F5AE63 /* IJSVGView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C123905F7100F5AE63 /* IJSVGView.m */; };
|
59EB763223905F7300F5AE63 /* IJSVGView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C123905F7100F5AE63 /* IJSVGView.m */; };
|
||||||
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */; };
|
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */; };
|
||||||
59EB763423905F7300F5AE63 /* IJSVGBezierPathAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75C323905F7100F5AE63 /* IJSVGBezierPathAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */; };
|
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */; };
|
||||||
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */; };
|
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */; };
|
||||||
59EB763723905F7300F5AE63 /* IJSVGCommandClose.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */; };
|
59EB763723905F7300F5AE63 /* IJSVGCommandClose.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */; };
|
||||||
@@ -124,15 +130,27 @@
|
|||||||
59EB764423905F7300F5AE63 /* IJSVGRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D323905F7300F5AE63 /* IJSVGRendering.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB764423905F7300F5AE63 /* IJSVGRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D323905F7300F5AE63 /* IJSVGRendering.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D423905F7300F5AE63 /* IJSVGExporter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D423905F7300F5AE63 /* IJSVGExporter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D523905F7300F5AE63 /* IJSVGRendering.m */; };
|
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D523905F7300F5AE63 /* IJSVGRendering.m */; };
|
||||||
|
59F36508262F1ABB00BCE3FD /* IJSVGColorType.h in Headers */ = {isa = PBXBuildFile; fileRef = 59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
59F36509262F1ABB00BCE3FD /* IJSVGColorType.m in Sources */ = {isa = PBXBuildFile; fileRef = 59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
5919E65523F47FF60051873A /* IJSVGUnitRect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitRect.h; sourceTree = "<group>"; };
|
||||||
|
5919E65623F47FF60051873A /* IJSVGUnitRect.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitRect.m; sourceTree = "<group>"; };
|
||||||
|
5919E65923F480330051873A /* IJSVGUnitPoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitPoint.h; sourceTree = "<group>"; };
|
||||||
|
5919E65A23F480330051873A /* IJSVGUnitPoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitPoint.m; sourceTree = "<group>"; };
|
||||||
|
591A3E4B25CC91F800AD45B7 /* IJSVGParsing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGParsing.h; sourceTree = "<group>"; };
|
||||||
|
591A3E4C25CC91F800AD45B7 /* IJSVGParsing.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGParsing.m; sourceTree = "<group>"; };
|
||||||
|
594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSImage+IJSVGAdditions.h"; sourceTree = "<group>"; };
|
||||||
|
594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSImage+IJSVGAdditions.m"; sourceTree = "<group>"; };
|
||||||
594CF46F238FF38E009B251B /* IJSVG.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IJSVG.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
594CF46F238FF38E009B251B /* IJSVG.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IJSVG.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
594CF473238FF38E009B251B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
594CF473238FF38E009B251B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
594CF55E238FF462009B251B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
594CF55E238FF462009B251B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||||
594CF560238FF46C009B251B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
594CF560238FF46C009B251B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
594CF562238FF473009B251B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
594CF562238FF473009B251B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||||
599EB4D2238FF535004CB6BC /* libobjc.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libobjc.tbd; path = usr/lib/libobjc.tbd; sourceTree = SDKROOT; };
|
599EB4D2238FF535004CB6BC /* libobjc.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libobjc.tbd; path = usr/lib/libobjc.tbd; sourceTree = SDKROOT; };
|
||||||
|
59A24EBA23F480EA0090C374 /* IJSVGUnitSize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitSize.h; sourceTree = "<group>"; };
|
||||||
|
59A24EBB23F480EA0090C374 /* IJSVGUnitSize.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitSize.m; sourceTree = "<group>"; };
|
||||||
59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IJSVGCommandParser.h; path = IJSVG/Source/Parsing/IJSVGCommandParser.h; sourceTree = SOURCE_ROOT; };
|
59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IJSVGCommandParser.h; path = IJSVG/Source/Parsing/IJSVGCommandParser.h; sourceTree = SOURCE_ROOT; };
|
||||||
59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = IJSVGCommandParser.m; path = IJSVG/Source/Parsing/IJSVGCommandParser.m; sourceTree = SOURCE_ROOT; };
|
59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = IJSVGCommandParser.m; path = IJSVG/Source/Parsing/IJSVGCommandParser.m; sourceTree = SOURCE_ROOT; };
|
||||||
59EB756523905F6B00F5AE63 /* IJSVGLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLayer.h; sourceTree = "<group>"; };
|
59EB756523905F6B00F5AE63 /* IJSVGLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLayer.h; sourceTree = "<group>"; };
|
||||||
@@ -144,7 +162,6 @@
|
|||||||
59EB756B23905F6B00F5AE63 /* IJSVGText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGText.h; sourceTree = "<group>"; };
|
59EB756B23905F6B00F5AE63 /* IJSVGText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGText.h; sourceTree = "<group>"; };
|
||||||
59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandQuadraticCurve.m; sourceTree = "<group>"; };
|
59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandQuadraticCurve.m; sourceTree = "<group>"; };
|
||||||
59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandVerticalLine.h; sourceTree = "<group>"; };
|
59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandVerticalLine.h; sourceTree = "<group>"; };
|
||||||
59EB756E23905F6C00F5AE63 /* IJSVGWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGWriter.h; sourceTree = "<group>"; };
|
|
||||||
59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheet.h; sourceTree = "<group>"; };
|
59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheet.h; sourceTree = "<group>"; };
|
||||||
59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandSmoothCurve.h; sourceTree = "<group>"; };
|
59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandSmoothCurve.h; sourceTree = "<group>"; };
|
||||||
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGColorList.m; sourceTree = "<group>"; };
|
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGColorList.m; sourceTree = "<group>"; };
|
||||||
@@ -171,12 +188,10 @@
|
|||||||
59EB758623905F6C00F5AE63 /* IJSVGDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGDef.h; sourceTree = "<group>"; };
|
59EB758623905F6C00F5AE63 /* IJSVGDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGDef.h; sourceTree = "<group>"; };
|
||||||
59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandHorizontalLine.m; sourceTree = "<group>"; };
|
59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandHorizontalLine.m; sourceTree = "<group>"; };
|
||||||
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGFontConverter.h; sourceTree = "<group>"; };
|
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGFontConverter.h; sourceTree = "<group>"; };
|
||||||
59EB758923905F6D00F5AE63 /* IJSVGWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGWriter.m; sourceTree = "<group>"; };
|
|
||||||
59EB758A23905F6D00F5AE63 /* IJSVGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPath.m; sourceTree = "<group>"; };
|
59EB758A23905F6D00F5AE63 /* IJSVGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPath.m; sourceTree = "<group>"; };
|
||||||
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGroup.h; sourceTree = "<group>"; };
|
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGroup.h; sourceTree = "<group>"; };
|
||||||
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPatternLayer.m; sourceTree = "<group>"; };
|
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPatternLayer.m; sourceTree = "<group>"; };
|
||||||
59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRenderingStyle.m; sourceTree = "<group>"; };
|
59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRenderingStyle.m; sourceTree = "<group>"; };
|
||||||
59EB758E23905F6D00F5AE63 /* IJSVGBezierPathAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGBezierPathAdditions.m; sourceTree = "<group>"; };
|
|
||||||
59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientLayer.m; sourceTree = "<group>"; };
|
59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientLayer.m; sourceTree = "<group>"; };
|
||||||
59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLayerTree.m; sourceTree = "<group>"; };
|
59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLayerTree.m; sourceTree = "<group>"; };
|
||||||
59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandVerticalLine.m; sourceTree = "<group>"; };
|
59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandVerticalLine.m; sourceTree = "<group>"; };
|
||||||
@@ -227,7 +242,6 @@
|
|||||||
59EB75C023905F7100F5AE63 /* IJSVGText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGText.m; sourceTree = "<group>"; };
|
59EB75C023905F7100F5AE63 /* IJSVGText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGText.m; sourceTree = "<group>"; };
|
||||||
59EB75C123905F7100F5AE63 /* IJSVGView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGView.m; sourceTree = "<group>"; };
|
59EB75C123905F7100F5AE63 /* IJSVGView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGView.m; sourceTree = "<group>"; };
|
||||||
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLinearGradient.m; sourceTree = "<group>"; };
|
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLinearGradient.m; sourceTree = "<group>"; };
|
||||||
59EB75C323905F7100F5AE63 /* IJSVGBezierPathAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGBezierPathAdditions.h; sourceTree = "<group>"; };
|
|
||||||
59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetSelector.m; sourceTree = "<group>"; };
|
59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetSelector.m; sourceTree = "<group>"; };
|
||||||
59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImageLayer.m; sourceTree = "<group>"; };
|
59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImageLayer.m; sourceTree = "<group>"; };
|
||||||
59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandClose.m; sourceTree = "<group>"; };
|
59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandClose.m; sourceTree = "<group>"; };
|
||||||
@@ -246,6 +260,8 @@
|
|||||||
59EB75D323905F7300F5AE63 /* IJSVGRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRendering.h; sourceTree = "<group>"; };
|
59EB75D323905F7300F5AE63 /* IJSVGRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRendering.h; sourceTree = "<group>"; };
|
||||||
59EB75D423905F7300F5AE63 /* IJSVGExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGExporter.h; sourceTree = "<group>"; };
|
59EB75D423905F7300F5AE63 /* IJSVGExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGExporter.h; sourceTree = "<group>"; };
|
||||||
59EB75D523905F7300F5AE63 /* IJSVGRendering.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRendering.m; sourceTree = "<group>"; };
|
59EB75D523905F7300F5AE63 /* IJSVGRendering.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRendering.m; sourceTree = "<group>"; };
|
||||||
|
59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGColorType.h; sourceTree = "<group>"; };
|
||||||
|
59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGColorType.m; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -316,6 +332,8 @@
|
|||||||
59EB758523905F6C00F5AE63 /* IJSVGColor.m */,
|
59EB758523905F6C00F5AE63 /* IJSVGColor.m */,
|
||||||
59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */,
|
59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */,
|
||||||
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */,
|
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */,
|
||||||
|
59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */,
|
||||||
|
59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */,
|
||||||
);
|
);
|
||||||
path = Colors;
|
path = Colors;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -333,8 +351,6 @@
|
|||||||
59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */,
|
59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */,
|
||||||
59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */,
|
59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */,
|
||||||
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */,
|
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */,
|
||||||
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */,
|
|
||||||
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */,
|
|
||||||
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */,
|
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */,
|
||||||
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */,
|
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */,
|
||||||
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */,
|
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */,
|
||||||
@@ -363,6 +379,8 @@
|
|||||||
59EB756923905F6B00F5AE63 /* IJSVGDef.m */,
|
59EB756923905F6B00F5AE63 /* IJSVGDef.m */,
|
||||||
59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */,
|
59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */,
|
||||||
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */,
|
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */,
|
||||||
|
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */,
|
||||||
|
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */,
|
||||||
59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */,
|
59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */,
|
||||||
59EB75D223905F7300F5AE63 /* IJSVGGradient.m */,
|
59EB75D223905F7300F5AE63 /* IJSVGGradient.m */,
|
||||||
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */,
|
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */,
|
||||||
@@ -396,6 +414,14 @@
|
|||||||
59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */,
|
59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */,
|
||||||
59EB759423905F6D00F5AE63 /* IJSVGUtils.h */,
|
59EB759423905F6D00F5AE63 /* IJSVGUtils.h */,
|
||||||
59EB758023905F6C00F5AE63 /* IJSVGUtils.m */,
|
59EB758023905F6C00F5AE63 /* IJSVGUtils.m */,
|
||||||
|
5919E65523F47FF60051873A /* IJSVGUnitRect.h */,
|
||||||
|
5919E65623F47FF60051873A /* IJSVGUnitRect.m */,
|
||||||
|
5919E65923F480330051873A /* IJSVGUnitPoint.h */,
|
||||||
|
5919E65A23F480330051873A /* IJSVGUnitPoint.m */,
|
||||||
|
59A24EBA23F480EA0090C374 /* IJSVGUnitSize.h */,
|
||||||
|
59A24EBB23F480EA0090C374 /* IJSVGUnitSize.m */,
|
||||||
|
591A3E4B25CC91F800AD45B7 /* IJSVGParsing.h */,
|
||||||
|
591A3E4C25CC91F800AD45B7 /* IJSVGParsing.m */,
|
||||||
);
|
);
|
||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -427,10 +453,10 @@
|
|||||||
592ABBEB2397A11800F44380 /* Additions */ = {
|
592ABBEB2397A11800F44380 /* Additions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
59EB75C323905F7100F5AE63 /* IJSVGBezierPathAdditions.h */,
|
|
||||||
59EB758E23905F6D00F5AE63 /* IJSVGBezierPathAdditions.m */,
|
|
||||||
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */,
|
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */,
|
||||||
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */,
|
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */,
|
||||||
|
594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */,
|
||||||
|
594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */,
|
||||||
);
|
);
|
||||||
path = Additions;
|
path = Additions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -484,8 +510,6 @@
|
|||||||
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */,
|
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */,
|
||||||
59EB75CD23905F7200F5AE63 /* IJSVGView.h */,
|
59EB75CD23905F7200F5AE63 /* IJSVGView.h */,
|
||||||
59EB75C123905F7100F5AE63 /* IJSVGView.m */,
|
59EB75C123905F7100F5AE63 /* IJSVGView.m */,
|
||||||
59EB756E23905F6C00F5AE63 /* IJSVGWriter.h */,
|
|
||||||
59EB758923905F6D00F5AE63 /* IJSVGWriter.m */,
|
|
||||||
);
|
);
|
||||||
path = Core;
|
path = Core;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -517,7 +541,6 @@
|
|||||||
files = (
|
files = (
|
||||||
59EB762623905F7300F5AE63 /* IJSVGImage.h in Headers */,
|
59EB762623905F7300F5AE63 /* IJSVGImage.h in Headers */,
|
||||||
59EB760823905F7300F5AE63 /* IJSVGShapeLayer.h in Headers */,
|
59EB760823905F7300F5AE63 /* IJSVGShapeLayer.h in Headers */,
|
||||||
59EB75DF23905F7300F5AE63 /* IJSVGWriter.h in Headers */,
|
|
||||||
59EB760F23905F7300F5AE63 /* IJSVGCommandEllipticalArc.h in Headers */,
|
59EB760F23905F7300F5AE63 /* IJSVGCommandEllipticalArc.h in Headers */,
|
||||||
59EB75F523905F7300F5AE63 /* IJSVGError.h in Headers */,
|
59EB75F523905F7300F5AE63 /* IJSVGError.h in Headers */,
|
||||||
59EB763E23905F7300F5AE63 /* IJSVGView.h in Headers */,
|
59EB763E23905F7300F5AE63 /* IJSVGView.h in Headers */,
|
||||||
@@ -562,14 +585,19 @@
|
|||||||
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */,
|
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */,
|
||||||
59EB763023905F7300F5AE63 /* IJSVGPatternLayer.h in Headers */,
|
59EB763023905F7300F5AE63 /* IJSVGPatternLayer.h in Headers */,
|
||||||
59EB75F023905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.h in Headers */,
|
59EB75F023905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.h in Headers */,
|
||||||
59EB763423905F7300F5AE63 /* IJSVGBezierPathAdditions.h in Headers */,
|
|
||||||
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */,
|
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */,
|
||||||
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.h in Headers */,
|
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.h in Headers */,
|
||||||
59EB761D23905F7300F5AE63 /* IJSVGStyle.h in Headers */,
|
59EB761D23905F7300F5AE63 /* IJSVGStyle.h in Headers */,
|
||||||
|
5919E65723F47FF60051873A /* IJSVGUnitRect.h in Headers */,
|
||||||
|
5919E65B23F480330051873A /* IJSVGUnitPoint.h in Headers */,
|
||||||
|
591A3E4D25CC91F800AD45B7 /* IJSVGParsing.h in Headers */,
|
||||||
|
59A24EBC23F480EA0090C374 /* IJSVGUnitSize.h in Headers */,
|
||||||
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */,
|
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */,
|
||||||
|
59F36508262F1ABB00BCE3FD /* IJSVGColorType.h in Headers */,
|
||||||
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */,
|
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */,
|
||||||
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */,
|
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */,
|
||||||
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.h in Headers */,
|
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.h in Headers */,
|
||||||
|
594A10DA248D7C90001A3181 /* NSImage+IJSVGAdditions.h in Headers */,
|
||||||
59EB762D23905F7300F5AE63 /* IJSVGLayerTree.h in Headers */,
|
59EB762D23905F7300F5AE63 /* IJSVGLayerTree.h in Headers */,
|
||||||
59EB760B23905F7300F5AE63 /* IJSVGStyleSheetSelector.h in Headers */,
|
59EB760B23905F7300F5AE63 /* IJSVGStyleSheetSelector.h in Headers */,
|
||||||
);
|
);
|
||||||
@@ -602,7 +630,7 @@
|
|||||||
594CF466238FF38E009B251B /* Project object */ = {
|
594CF466238FF38E009B251B /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1100;
|
LastUpgradeCheck = 1220;
|
||||||
ORGANIZATIONNAME = "Curtis Hard";
|
ORGANIZATIONNAME = "Curtis Hard";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
594CF46E238FF38E009B251B = {
|
594CF46E238FF38E009B251B = {
|
||||||
@@ -644,16 +672,19 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */,
|
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */,
|
||||||
|
59A24EBD23F480EA0090C374 /* IJSVGUnitSize.m in Sources */,
|
||||||
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */,
|
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */,
|
||||||
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */,
|
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */,
|
||||||
59EB763923905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m in Sources */,
|
59EB763923905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m in Sources */,
|
||||||
59EB75D823905F7300F5AE63 /* IJSVGStyleSheetRule.m in Sources */,
|
59EB75D823905F7300F5AE63 /* IJSVGStyleSheetRule.m in Sources */,
|
||||||
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */,
|
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */,
|
||||||
|
59F36509262F1ABB00BCE3FD /* IJSVGColorType.m in Sources */,
|
||||||
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */,
|
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */,
|
||||||
59EB763A23905F7300F5AE63 /* IJSVGForeignObject.m in Sources */,
|
59EB763A23905F7300F5AE63 /* IJSVGForeignObject.m in Sources */,
|
||||||
59EB761123905F7300F5AE63 /* IJSVGCommand.m in Sources */,
|
59EB761123905F7300F5AE63 /* IJSVGCommand.m in Sources */,
|
||||||
59EB760923905F7300F5AE63 /* IJSVGCommandCurve.m in Sources */,
|
59EB760923905F7300F5AE63 /* IJSVGCommandCurve.m in Sources */,
|
||||||
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */,
|
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */,
|
||||||
|
594A10DB248D7C90001A3181 /* NSImage+IJSVGAdditions.m in Sources */,
|
||||||
59EB761923905F7300F5AE63 /* IJSVGCommandSmoothCurve.m in Sources */,
|
59EB761923905F7300F5AE63 /* IJSVGCommandSmoothCurve.m in Sources */,
|
||||||
59EB761323905F7300F5AE63 /* IJSVG.m in Sources */,
|
59EB761323905F7300F5AE63 /* IJSVG.m in Sources */,
|
||||||
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */,
|
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */,
|
||||||
@@ -663,22 +694,23 @@
|
|||||||
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */,
|
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */,
|
||||||
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */,
|
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */,
|
||||||
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */,
|
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */,
|
||||||
|
5919E65C23F480330051873A /* IJSVGUnitPoint.m in Sources */,
|
||||||
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */,
|
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */,
|
||||||
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */,
|
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */,
|
||||||
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */,
|
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */,
|
||||||
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */,
|
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */,
|
||||||
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */,
|
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */,
|
||||||
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */,
|
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */,
|
||||||
59EB75FF23905F7300F5AE63 /* IJSVGBezierPathAdditions.m in Sources */,
|
|
||||||
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */,
|
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */,
|
||||||
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */,
|
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */,
|
||||||
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */,
|
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */,
|
||||||
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */,
|
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */,
|
||||||
|
591A3E4E25CC91F800AD45B7 /* IJSVGParsing.m in Sources */,
|
||||||
|
5919E65823F47FF60051873A /* IJSVGUnitRect.m in Sources */,
|
||||||
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */,
|
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */,
|
||||||
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */,
|
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */,
|
||||||
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */,
|
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */,
|
||||||
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */,
|
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */,
|
||||||
59EB75FA23905F7300F5AE63 /* IJSVGWriter.m in Sources */,
|
|
||||||
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */,
|
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */,
|
||||||
59EB762E23905F7300F5AE63 /* IJSVGExporter.m in Sources */,
|
59EB762E23905F7300F5AE63 /* IJSVGExporter.m in Sources */,
|
||||||
59EB761623905F7300F5AE63 /* IJSVGParser.m in Sources */,
|
59EB761623905F7300F5AE63 /* IJSVGParser.m in Sources */,
|
||||||
@@ -731,6 +763,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -746,6 +779,7 @@
|
|||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREFIX_HEADER = "";
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"DEBUG=1",
|
"DEBUG=1",
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -792,6 +826,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -805,6 +840,7 @@
|
|||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_PREFIX_HEADER = "";
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1130"
|
LastUpgradeVersion = "1250"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
<key>594CF46E238FF38E009B251B</key>
|
<key>594CF46E238FF38E009B251B</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>primary</key>
|
<key>primary</key>
|
||||||
<true/>
|
<true />
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
@@ -19,6 +19,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2019 Curtis Hard. All rights reserved.</string>
|
<string>Copyright © 2020 Curtis Hard. All rights reserved.</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// IJSVGBezierPathAdditions.h
|
|
||||||
// IconJar
|
|
||||||
//
|
|
||||||
// Created by Curtis Hard on 30/08/2014.
|
|
||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <AppKit/AppKit.h>
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
@interface NSBezierPath (IJSVGAdditions)
|
|
||||||
|
|
||||||
- (void)addQuadCurveToPoint:(NSPoint)aPoint
|
|
||||||
controlPoint:(NSPoint)cp;
|
|
||||||
|
|
||||||
- (CGPathRef)newCGPathRef:(BOOL)autoClose;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
//
|
|
||||||
// IJSVGBezierPathAdditions.m
|
|
||||||
// IconJar
|
|
||||||
//
|
|
||||||
// Created by Curtis Hard on 30/08/2014.
|
|
||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "IJSVGBezierPathAdditions.h"
|
|
||||||
|
|
||||||
@implementation NSBezierPath (IJSVGAdditions)
|
|
||||||
|
|
||||||
- (void)addQuadCurveToPoint:(CGPoint)QP2
|
|
||||||
controlPoint:(CGPoint)QP1
|
|
||||||
{
|
|
||||||
CGPoint QP0 = [self currentPoint];
|
|
||||||
CGPoint CP3 = QP2;
|
|
||||||
CGPoint CP1 = CGPointMake(QP0.x + ((2.0 / 3.0) * (QP1.x - QP0.x)), QP0.y + ((2.0 / 3.0) * (QP1.y - QP0.y)));
|
|
||||||
CGPoint CP2 = CGPointMake(QP2.x + (2.0 / 3.0) * (QP1.x - QP2.x), QP2.y + (2.0 / 3.0) * (QP1.y - QP2.y));
|
|
||||||
|
|
||||||
[self curveToPoint:CP3
|
|
||||||
controlPoint1:CP1
|
|
||||||
controlPoint2:CP2];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGPathRef)newCGPathRef:(BOOL)autoClose
|
|
||||||
{
|
|
||||||
NSInteger i = 0;
|
|
||||||
NSInteger numElements = self.elementCount;
|
|
||||||
NSBezierPath* bezPath = self;
|
|
||||||
|
|
||||||
// nothing to return
|
|
||||||
if (numElements == 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGMutablePathRef aPath = CGPathCreateMutable();
|
|
||||||
|
|
||||||
NSPoint points[3];
|
|
||||||
BOOL didClosePath = YES;
|
|
||||||
|
|
||||||
for (i = 0; i < numElements; i++) {
|
|
||||||
switch ([bezPath elementAtIndex:i associatedPoints:points]) {
|
|
||||||
|
|
||||||
// move
|
|
||||||
case NSMoveToBezierPathElement: {
|
|
||||||
CGPathMoveToPoint(aPath, NULL, points[0].x, points[0].y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// line
|
|
||||||
case NSLineToBezierPathElement: {
|
|
||||||
CGPathAddLineToPoint(aPath, NULL, points[0].x, points[0].y);
|
|
||||||
didClosePath = NO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// curve
|
|
||||||
case NSCurveToBezierPathElement: {
|
|
||||||
CGPathAddCurveToPoint(aPath, NULL, points[0].x, points[0].y,
|
|
||||||
points[1].x, points[1].y,
|
|
||||||
points[2].x, points[2].y);
|
|
||||||
didClosePath = NO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// close
|
|
||||||
case NSClosePathBezierPathElement: {
|
|
||||||
CGPathCloseSubpath(aPath);
|
|
||||||
didClosePath = YES;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!didClosePath && autoClose) {
|
|
||||||
CGPathCloseSubpath(aPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create immutable and release
|
|
||||||
CGPathRef pathToReturn = CGPathCreateCopy(aPath);
|
|
||||||
CGPathRelease(aPath);
|
|
||||||
|
|
||||||
return pathToReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
- (BOOL)ijsvg_isNumeric;
|
- (BOOL)ijsvg_isNumeric;
|
||||||
- (BOOL)ijsvg_containsAlpha;
|
- (BOOL)ijsvg_containsAlpha;
|
||||||
- (NSArray*)ijsvg_componentsSplitByWhiteSpace;
|
- (NSArray*)ijsvg_componentsSplitByWhiteSpace;
|
||||||
|
- (BOOL)ijsvg_isHexString;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,51 +7,38 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGStringAdditions.h"
|
#import "IJSVGStringAdditions.h"
|
||||||
|
#import "IJSVGUtils.h"
|
||||||
|
|
||||||
@implementation NSString (IJSVGAdditions)
|
@implementation NSString (IJSVGAdditions)
|
||||||
|
|
||||||
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(const char*)aChar
|
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(const char*)aChar
|
||||||
{
|
{
|
||||||
NSMutableArray* comp = [[[NSMutableArray alloc] init] autorelease];
|
char* chars = (char*)self.UTF8String;
|
||||||
NSInteger length = self.length;
|
if(chars == NULL || strlen(chars) == 0) {
|
||||||
unichar* chars = (unichar*)calloc(sizeof(unichar), self.length);
|
return @[];
|
||||||
|
|
||||||
NSInteger ind = 0;
|
|
||||||
BOOL startedString = NO;
|
|
||||||
const char* buffer = self.UTF8String;
|
|
||||||
|
|
||||||
for (NSInteger i = 0; i < length; i++) {
|
|
||||||
unichar theChar = buffer[i];
|
|
||||||
|
|
||||||
// start the buffer
|
|
||||||
BOOL isEqualToChar = strchr(aChar, theChar) != NULL;
|
|
||||||
if (isEqualToChar == NO) {
|
|
||||||
startedString = YES;
|
|
||||||
chars[ind++] = theChar;
|
|
||||||
}
|
|
||||||
|
|
||||||
// has started and char is the search char, or its at end
|
|
||||||
if ((startedString == YES && isEqualToChar) || (i == (length - 1) && startedString == YES)) {
|
|
||||||
startedString = NO;
|
|
||||||
|
|
||||||
// append the comp
|
|
||||||
[comp addObject:[NSString stringWithCharacters:chars length:ind]];
|
|
||||||
|
|
||||||
// restart and realloc the memory
|
|
||||||
ind = 0;
|
|
||||||
chars = memset(chars, '\0', sizeof(unichar) * ind);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(chars);
|
NSMutableArray<NSString*>* strings = nil;
|
||||||
return comp;
|
strings = [[[NSMutableArray alloc] init] autorelease];
|
||||||
|
char* copy = strdup(chars);
|
||||||
|
char* spt = NULL;
|
||||||
|
char* ptr = strtok_r(copy, aChar, &spt);
|
||||||
|
while(ptr != NULL) {
|
||||||
|
NSString* possibleString = nil;
|
||||||
|
if((possibleString = [NSString stringWithUTF8String:ptr]) != nil) {
|
||||||
|
[strings addObject:possibleString];
|
||||||
|
}
|
||||||
|
ptr = strtok_r(NULL, aChar, &spt);
|
||||||
|
}
|
||||||
|
(void)free(copy), copy = NULL;
|
||||||
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)ijsvg_containsAlpha
|
- (BOOL)ijsvg_containsAlpha
|
||||||
{
|
{
|
||||||
const char* buffer = self.UTF8String;
|
const char* buffer = self.UTF8String;
|
||||||
unsigned long length = strlen(buffer);
|
char currentChar;
|
||||||
for (int i = 0; i < length; i++) {
|
while((currentChar = *buffer++) ) {
|
||||||
if (isalpha(buffer[i])) {
|
if (isalpha(currentChar)) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,9 +48,9 @@
|
|||||||
- (BOOL)ijsvg_isNumeric
|
- (BOOL)ijsvg_isNumeric
|
||||||
{
|
{
|
||||||
const char* buffer = self.UTF8String;
|
const char* buffer = self.UTF8String;
|
||||||
unsigned long length = strlen(buffer);
|
char currentChar;
|
||||||
for (int i = 0; i < length; i++) {
|
while((currentChar = *buffer++) ) {
|
||||||
if (!isnumber(buffer[i])) {
|
if (!isnumber(currentChar)) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,4 +62,10 @@
|
|||||||
return [self ijsvg_componentsSeparatedByChars:"\t\n\r "];
|
return [self ijsvg_componentsSeparatedByChars:"\t\n\r "];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)ijsvg_isHexString
|
||||||
|
{
|
||||||
|
const char* chars = self.UTF8String;
|
||||||
|
return IJSVGCharBufferIsHEX((char*)chars);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// NSImage+IJSVGAdditions.h
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 07/06/2020.
|
||||||
|
// Copyright © 2020 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
IJSVG* IJSVGGetFromNSImage(NSImage* image);
|
||||||
|
|
||||||
|
@interface NSImage (IJSVGAdditions)
|
||||||
|
|
||||||
|
+ (NSImage*)SVGImageNamed:(NSString*)imageName;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// NSImage+IJSVGAdditions.m
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 07/06/2020.
|
||||||
|
// Copyright © 2020 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IJSVGImageRep.h"
|
||||||
|
#import "NSImage+IJSVGAdditions.h"
|
||||||
|
|
||||||
|
IJSVG* IJSVGGetFromNSImage(NSImage* image)
|
||||||
|
{
|
||||||
|
for (NSImageRep* rep in image.representations) {
|
||||||
|
if ([rep isKindOfClass:IJSVGImageRep.class]) {
|
||||||
|
return ((IJSVGImageRep*)rep).SVG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation NSImage (IJSVGAdditions)
|
||||||
|
|
||||||
|
+ (NSImage*)SVGImageNamed:(NSString*)imageName
|
||||||
|
{
|
||||||
|
// find the image
|
||||||
|
NSBundle* bundle = NSBundle.mainBundle;
|
||||||
|
NSString* str = nil;
|
||||||
|
NSString* ext = imageName.pathExtension;
|
||||||
|
if (ext == nil || ext.length == 0) {
|
||||||
|
ext = @"svg";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((str = [bundle pathForResource:imageName.stringByDeletingPathExtension
|
||||||
|
ofType:ext])
|
||||||
|
!= nil) {
|
||||||
|
|
||||||
|
// work out if we can get the data
|
||||||
|
NSData* data = [[[NSData alloc] initWithContentsOfFile:str] autorelease];
|
||||||
|
if (data == nil) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab the image rep
|
||||||
|
IJSVGImageRep* rep = [[[IJSVGImageRep alloc] initWithData:data] autorelease];
|
||||||
|
NSImage* image = [[[NSImage alloc] init] autorelease];
|
||||||
|
[image addRepresentation:rep];
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -167,6 +167,8 @@ typedef NS_ENUM(NSInteger, IJSVGPredefinedColor) {
|
|||||||
IJSVGColorYellowgreen
|
IJSVGColorYellowgreen
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern NSString* const IJSVGColorCurrentColorName;
|
||||||
|
|
||||||
@interface IJSVGColor : NSObject
|
@interface IJSVGColor : NSObject
|
||||||
|
|
||||||
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness);
|
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness);
|
||||||
|
|||||||
@@ -8,11 +8,16 @@
|
|||||||
|
|
||||||
#import "IJSVGColor.h"
|
#import "IJSVGColor.h"
|
||||||
#import "IJSVGUtils.h"
|
#import "IJSVGUtils.h"
|
||||||
|
#import "IJSVGStringAdditions.h"
|
||||||
|
#import "IJSVGParsing.h"
|
||||||
|
|
||||||
|
NSString* const IJSVGColorCurrentColorName = @"currentColor";
|
||||||
|
|
||||||
@implementation IJSVGColor
|
@implementation IJSVGColor
|
||||||
|
|
||||||
static NSDictionary* _colorTree = nil;
|
static NSDictionary* _colorTree = nil;
|
||||||
|
|
||||||
|
|
||||||
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness)
|
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness)
|
||||||
{
|
{
|
||||||
hue *= (1.f / 360.f);
|
hue *= (1.f / 360.f);
|
||||||
@@ -241,37 +246,51 @@ CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightnes
|
|||||||
|
|
||||||
+ (NSColor*)colorFromString:(NSString*)string
|
+ (NSColor*)colorFromString:(NSString*)string
|
||||||
{
|
{
|
||||||
NSCharacterSet* set = NSCharacterSet.whitespaceAndNewlineCharacterSet;
|
// swap over to C for performance
|
||||||
string = [string stringByTrimmingCharactersInSet:set];
|
if(string == nil) {
|
||||||
|
|
||||||
if ([string length] < 3) {
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSColor* color = nil;
|
const char* oString = string.UTF8String;
|
||||||
string = [string lowercaseString];
|
if(strlen(oString) == 0) {
|
||||||
if ([self.class isHex:string] == NO) {
|
return nil;
|
||||||
color = [self.class colorFromPredefinedColorName:string];
|
|
||||||
if (color != nil) {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// is simply a clear color, dont fill
|
char* str = IJSVGTimmedCharBufferCreate(oString);
|
||||||
if ([string.lowercaseString isEqualToString:@"none"] ||
|
if (IJSVGCharBufferIsHEX(str) == YES) {
|
||||||
[string.lowercaseString isEqualToString:@"transparent"]) {
|
(void)free(str), str = NULL;
|
||||||
return [self computeColorSpace:NSColor.clearColor];
|
return [self.class colorFromHEXString:string];
|
||||||
}
|
}
|
||||||
|
|
||||||
// is it RGB?
|
// is it RGB?
|
||||||
if ([string hasPrefix:@"rgb"] == YES) {
|
if (IJSVGCharBufferHasPrefix(str, "rgb") == YES) {
|
||||||
NSRange range = [IJSVGUtils rangeOfParentheses:string];
|
NSUInteger count = 0;
|
||||||
NSString* rgbString = [string substringWithRange:range];
|
IJSVGParsingStringMethod** methods = NULL;
|
||||||
NSArray* parts = [rgbString ijsvg_componentsSeparatedByChars:","];
|
methods = IJSVGParsingMethodParseString(str, &count);
|
||||||
|
IJSVGParsingStringMethod* method = methods[0];
|
||||||
|
|
||||||
|
// memory clean for the string
|
||||||
|
(void)free(str), str = NULL;
|
||||||
|
|
||||||
|
// nothing to return, just mem clean and get out of here
|
||||||
|
if(count == 0 || methods == NULL) {
|
||||||
|
if(methods != NULL) {
|
||||||
|
IJSVGParsingStringMethodsRelease(methods, count);
|
||||||
|
methods = NULL;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the parameters
|
||||||
|
NSString* parameters = [NSString stringWithUTF8String:method->parameters];
|
||||||
|
NSArray* parts = [parameters ijsvg_componentsSeparatedByChars:","];
|
||||||
NSString* alpha = @"100%";
|
NSString* alpha = @"100%";
|
||||||
if (parts.count == 4) {
|
if (parts.count == 4) {
|
||||||
alpha = parts[3];
|
alpha = parts[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IJSVGParsingStringMethodsRelease(methods, count);
|
||||||
|
methods = NULL;
|
||||||
return [self colorFromRString:parts[0]
|
return [self colorFromRString:parts[0]
|
||||||
gString:parts[1]
|
gString:parts[1]
|
||||||
bString:parts[2]
|
bString:parts[2]
|
||||||
@@ -279,10 +298,10 @@ CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightnes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// is it HSL?
|
// is it HSL?
|
||||||
if ([string hasPrefix:@"hsl"]) {
|
if (IJSVGCharBufferHasPrefix(str, "hsl")) {
|
||||||
NSInteger count = 0;
|
NSInteger count = 0;
|
||||||
CGFloat* params = [IJSVGUtils commandParameters:string
|
CGFloat* params = [IJSVGUtils scanFloatsFromCString:str
|
||||||
count:&count];
|
size:&count];
|
||||||
CGFloat alpha = 1;
|
CGFloat alpha = 1;
|
||||||
if (count == 4) {
|
if (count == 4) {
|
||||||
alpha = params[3];
|
alpha = params[3];
|
||||||
@@ -290,21 +309,30 @@ CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightnes
|
|||||||
|
|
||||||
// convert HSL to HSB
|
// convert HSL to HSB
|
||||||
CGFloat* hsb = IJSVGColorCSSHSLToHSB(params[0], params[1], params[2]);
|
CGFloat* hsb = IJSVGColorCSSHSLToHSB(params[0], params[1], params[2]);
|
||||||
color = [NSColor colorWithDeviceHue:hsb[0]
|
NSColor* color = [NSColor colorWithDeviceHue:hsb[0]
|
||||||
saturation:hsb[1]
|
saturation:hsb[1]
|
||||||
brightness:hsb[2]
|
brightness:hsb[2]
|
||||||
alpha:alpha];
|
alpha:alpha];
|
||||||
|
|
||||||
color = [self computeColorSpace:color];
|
color = [self computeColorSpace:color];
|
||||||
|
|
||||||
// memory clean!
|
// memory clean!
|
||||||
free(hsb);
|
(void)free(str), str = NULL;
|
||||||
free(params);
|
(void)free(hsb), hsb = NULL;
|
||||||
|
(void)free(params), params = NULL;
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = [self.class colorFromHEXString:string];
|
// is simply a clear color, dont fill
|
||||||
return color;
|
if (strcmp(str, "none") == 0 ||
|
||||||
|
strcmp(str, "transparent") == 0) {
|
||||||
|
(void)free(str), str = NULL;
|
||||||
|
return [self computeColorSpace:NSColor.clearColor];
|
||||||
|
}
|
||||||
|
|
||||||
|
// could return nil
|
||||||
|
(void)free(str), str = NULL;
|
||||||
|
return [self.class colorFromPredefinedColorName:string];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSColor*)colorFromPredefinedColorName:(NSString*)name
|
+ (NSColor*)colorFromPredefinedColorName:(NSString*)name
|
||||||
@@ -707,14 +735,7 @@ CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightnes
|
|||||||
|
|
||||||
+ (BOOL)isHex:(NSString*)string
|
+ (BOOL)isHex:(NSString*)string
|
||||||
{
|
{
|
||||||
const char* validList = "0123456789ABCDEFabcdef#";
|
return string.ijsvg_isHexString;
|
||||||
for (NSInteger i = 0; i < string.length; i++) {
|
|
||||||
char c = [string characterAtIndex:i];
|
|
||||||
if (strchr(validList, c) == NULL) {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (unsigned long)lengthOfHEXInteger:(NSUInteger)hex
|
+ (unsigned long)lengthOfHEXInteger:(NSUInteger)hex
|
||||||
@@ -760,28 +781,38 @@ CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightnes
|
|||||||
containsAlphaComponent:(BOOL*)containsAlphaComponent
|
containsAlphaComponent:(BOOL*)containsAlphaComponent
|
||||||
{
|
{
|
||||||
// absolutely no string
|
// absolutely no string
|
||||||
if (string == nil || string.length == 0 || ![self.class isHex:string]) {
|
if(string == nil) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* str = (char*)string.UTF8String;
|
||||||
|
size_t length = strlen(str);
|
||||||
|
if (length == 0 || IJSVGCharBufferIsHEX(str) == NO) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([string hasPrefix:@"#"] == YES) {
|
// remove the hash from the front of the string
|
||||||
string = [string substringFromIndex:1];
|
if(str[0] == '#') {
|
||||||
|
length--;
|
||||||
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// whats the length?
|
unsigned long hex;
|
||||||
NSUInteger length = string.length;
|
// we need to work out if its shorthand
|
||||||
|
// if it is, the length needs to be length*2
|
||||||
if (length == 3 || length == 4) {
|
if (length == 3 || length == 4) {
|
||||||
// shorthand...
|
char* chars = NULL;
|
||||||
NSMutableString* str = [[[NSMutableString alloc] init] autorelease];
|
chars = (char*)calloc(sizeof(char),length*2+1);
|
||||||
for (NSInteger i = 0; i < length; i++) {
|
for(int i = 0; i < length; i++) {
|
||||||
NSString* sub = [string substringWithRange:NSMakeRange(i, 1)];
|
chars[i*2] = chars[i*2+1] = str[i];
|
||||||
[str appendFormat:@"%@%@", sub, sub];
|
|
||||||
}
|
}
|
||||||
string = str;
|
hex = strtoul(chars, NULL, 16);
|
||||||
|
(void)free(chars), chars = NULL;
|
||||||
|
} else {
|
||||||
|
hex = strtoul(str, NULL, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now convert rest to hex
|
// now convert rest to hex
|
||||||
unsigned long hex = [self HEXFromArbitraryHexString:string];
|
|
||||||
if (containsAlphaComponent != nil) {
|
if (containsAlphaComponent != nil) {
|
||||||
*containsAlphaComponent = [self HEXContainsAlphaComponent:hex];
|
*containsAlphaComponent = [self HEXContainsAlphaComponent:hex];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,19 @@
|
|||||||
// Copyright © 2019 Curtis Hard. All rights reserved.
|
// Copyright © 2019 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGColor.h"
|
#import <IJSVG/IJSVGColor.h>
|
||||||
|
#import <IJSVG/IJSVGColorType.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGColorList : NSObject <NSCopying> {
|
@interface IJSVGColorList : NSObject <NSCopying> {
|
||||||
|
|
||||||
@private
|
@private
|
||||||
NSMutableDictionary<NSColor*, NSColor*>* _replacementColorTree;
|
NSMutableDictionary<NSColor*, NSColor*>* _replacementColorTree;
|
||||||
NSMutableSet<NSColor*>* _colors;
|
NSMutableSet<IJSVGColorType*>* _colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, assign, readonly) NSUInteger count;
|
||||||
|
|
||||||
- (NSColor*)proposedColorForColor:(NSColor*)color;
|
- (NSColor*)proposedColorForColor:(NSColor*)color;
|
||||||
- (void)removeAllReplacementColors;
|
- (void)removeAllReplacementColors;
|
||||||
- (void)removeReplacementColor:(NSColor*)color;
|
- (void)removeReplacementColor:(NSColor*)color;
|
||||||
@@ -25,7 +28,8 @@
|
|||||||
clearExistingColors:(BOOL)clearExistingColors;
|
clearExistingColors:(BOOL)clearExistingColors;
|
||||||
|
|
||||||
- (void)addColorsFromList:(IJSVGColorList*)sheet;
|
- (void)addColorsFromList:(IJSVGColorList*)sheet;
|
||||||
- (NSSet<NSColor*>*)colors;
|
- (NSSet<IJSVGColorType*>*)colors;
|
||||||
- (void)addColor:(NSColor*)color;
|
- (void)addColor:(IJSVGColorType*)color;
|
||||||
|
- (NSDictionary<NSColor*, NSColor*>*)replacementColors;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -89,24 +89,48 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSSet<NSColor*>*)colors
|
- (NSSet<IJSVGColorType*>*)colors
|
||||||
{
|
{
|
||||||
return [NSSet setWithSet:_colors];
|
return [NSSet setWithSet:_colors];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addColorsFromList:(IJSVGColorList*)sheet
|
- (void)addColorsFromList:(IJSVGColorList*)sheet
|
||||||
{
|
{
|
||||||
[_colors addObjectsFromArray:sheet.colors.allObjects];
|
for(IJSVGColorType* color in sheet.colors) {
|
||||||
|
[self addColor:color];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addColor:(NSColor*)color
|
- (void)addColor:(IJSVGColorType*)color
|
||||||
{
|
{
|
||||||
[_colors addObject:[IJSVGColor computeColorSpace:color]];
|
// we just need to update its bit mask
|
||||||
|
if([_colors containsObject:color] == YES) {
|
||||||
|
void (^handler)(IJSVGColorType * _Nonnull obj, BOOL * _Nonnull stop) =
|
||||||
|
^(IJSVGColorType * _Nonnull obj, BOOL * _Nonnull stop) {
|
||||||
|
if([obj isEqual:color] == YES) {
|
||||||
|
obj.flags |= color.flags;
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
[_colors enumerateObjectsUsingBlock:handler];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[_colors addObject:color];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeColor:(NSColor*)color
|
- (NSDictionary<NSColor*,NSColor*>*)replacementColors
|
||||||
{
|
{
|
||||||
[_colors removeObject:[IJSVGColor computeColorSpace:color]];
|
return _replacementColorTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeColor:(IJSVGColorType*)color
|
||||||
|
{
|
||||||
|
[_colors removeObject:color];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)count
|
||||||
|
{
|
||||||
|
return _colors.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// IJSVGColorType.h
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 20/04/2021.
|
||||||
|
// Copyright © 2021 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(NSInteger, IJSVGColorTypeFlags) {
|
||||||
|
IJSVGColorTypeNone = 0,
|
||||||
|
IJSVGColorTypeFlagUnknown = 1 << 0,
|
||||||
|
IJSVGColorTypeFlagFill = 1 << 1,
|
||||||
|
IJSVGColorTypeFlagStroke = 1 << 2,
|
||||||
|
IJSVGColorTypeFlagStop = 1 << 3
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface IJSVGColorType : NSObject {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, retain) NSColor* color;
|
||||||
|
@property (nonatomic, assign) IJSVGColorTypeFlags flags;
|
||||||
|
|
||||||
|
+ (IJSVGColorType*)typeWithColor:(NSColor*)color
|
||||||
|
flags:(IJSVGColorTypeFlags)mask;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// IJSVGColorType.m
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 20/04/2021.
|
||||||
|
// Copyright © 2021 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IJSVGColorType.h"
|
||||||
|
|
||||||
|
@implementation IJSVGColorType
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
(void)[_color release], _color = nil;
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (IJSVGColorType*)typeWithColor:(NSColor*)color
|
||||||
|
flags:(IJSVGColorTypeFlags)mask
|
||||||
|
{
|
||||||
|
IJSVGColorType* type = [[[self alloc] init] autorelease];
|
||||||
|
type.color = color;
|
||||||
|
type.flags = mask;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)object
|
||||||
|
{
|
||||||
|
if([object isKindOfClass:IJSVGColorType.class] == NO) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return [self.color isEqual:((IJSVGColorType*)object).color];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)hash
|
||||||
|
{
|
||||||
|
return self.color.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGCommandParser.h"
|
#import <IJSVG/IJSVGCommandParser.h>
|
||||||
#import "IJSVGPath.h"
|
#import <IJSVG/IJSVGPath.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
static const NSInteger IJSVGCustomVariableParameterCount = NSNotFound;
|
static const NSInteger IJSVGCustomVariableParameterCount = NSNotFound;
|
||||||
@@ -18,16 +18,8 @@ typedef NS_ENUM(NSInteger, IJSVGCommandType) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@interface IJSVGCommand : NSObject {
|
@interface IJSVGCommand : NSObject {
|
||||||
NSString* commandString;
|
@private
|
||||||
char command;
|
|
||||||
CGFloat* parameters;
|
|
||||||
NSInteger parameterCount;
|
|
||||||
NSArray<IJSVGCommand*>* subCommands;
|
|
||||||
NSInteger requiredParameters;
|
|
||||||
IJSVGCommandType type;
|
|
||||||
IJSVGCommand* previousCommand;
|
|
||||||
NSInteger _currentIndex;
|
NSInteger _currentIndex;
|
||||||
BOOL isSubCommand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString* commandString;
|
@property (nonatomic, copy) NSString* commandString;
|
||||||
@@ -55,8 +47,8 @@ typedef NS_ENUM(NSInteger, IJSVGCommandType) {
|
|||||||
intoArray:(NSMutableArray<IJSVGCommand*>*)commands
|
intoArray:(NSMutableArray<IJSVGCommand*>*)commands
|
||||||
parentCommand:(IJSVGCommand*)parentCommand;
|
parentCommand:(IJSVGCommand*)parentCommand;
|
||||||
|
|
||||||
- (id)initWithCommandString:(NSString*)str
|
- (id)initWithCommandStringBuffer:(const char*)str
|
||||||
dataStream:(IJSVGPathDataStream*)dataStream;
|
dataStream:(IJSVGPathDataStream*)dataStream;
|
||||||
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
|
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
|
||||||
paramCount:(NSInteger)paramCount
|
paramCount:(NSInteger)paramCount
|
||||||
previousCommand:(IJSVGCommand*)command;
|
previousCommand:(IJSVGCommand*)command;
|
||||||
|
|||||||
@@ -22,15 +22,6 @@
|
|||||||
|
|
||||||
@implementation IJSVGCommand
|
@implementation IJSVGCommand
|
||||||
|
|
||||||
@synthesize commandString;
|
|
||||||
@synthesize command;
|
|
||||||
@synthesize parameterCount;
|
|
||||||
@synthesize parameters;
|
|
||||||
@synthesize subCommands;
|
|
||||||
@synthesize type;
|
|
||||||
@synthesize previousCommand;
|
|
||||||
@synthesize isSubCommand;
|
|
||||||
|
|
||||||
+ (BOOL)requiresCustomParameterParsing
|
+ (BOOL)requiresCustomParameterParsing
|
||||||
{
|
{
|
||||||
return NO;
|
return NO;
|
||||||
@@ -103,26 +94,26 @@
|
|||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([commandString release]), commandString = nil;
|
(void)([_commandString release]), _commandString = nil;
|
||||||
(void)([subCommands release]), subCommands = nil;
|
(void)([_subCommands release]), _subCommands = nil;
|
||||||
if (parameters) {
|
if (_parameters) {
|
||||||
(void)(free(parameters)), parameters = nil;
|
(void)(free(_parameters)), _parameters = nil;
|
||||||
}
|
}
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithCommandString:(NSString*)str
|
- (id)initWithCommandStringBuffer:(const char*)str
|
||||||
dataStream:(IJSVGPathDataStream*)dataStream
|
dataStream:(IJSVGPathDataStream*)dataStream
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil) {
|
if ((self = [super init]) != nil) {
|
||||||
// work out the basics
|
// work out the basics
|
||||||
_currentIndex = 0;
|
_currentIndex = 0;
|
||||||
command = [str characterAtIndex:0];
|
_command = str[0];
|
||||||
type = [IJSVGUtils typeForCommandChar:command];
|
_type = [IJSVGUtils typeForCommandChar:_command];
|
||||||
NSInteger sets = 0;
|
NSInteger sets = 0;
|
||||||
NSInteger paramCount = [self.class requiredParameterCount];
|
NSInteger paramCount = [self.class requiredParameterCount];
|
||||||
IJSVGPathDataSequence* sequence = [self.class pathDataSequence];
|
IJSVGPathDataSequence* sequence = [self.class pathDataSequence];
|
||||||
parameters = IJSVGParsePathDataStreamSequence(str.UTF8String, str.length,
|
_parameters = IJSVGParsePathDataStreamSequence(str, strlen(str),
|
||||||
dataStream, sequence, [self.class requiredParameterCount], &sets);
|
dataStream, sequence, [self.class requiredParameterCount], &sets);
|
||||||
|
|
||||||
if (sets <= 1) {
|
if (sets <= 1) {
|
||||||
@@ -130,7 +121,7 @@
|
|||||||
IJSVGCommand* command = [self subcommandWithParameters:subParams
|
IJSVGCommand* command = [self subcommandWithParameters:subParams
|
||||||
paramCount:paramCount
|
paramCount:paramCount
|
||||||
previousCommand:nil];
|
previousCommand:nil];
|
||||||
subCommands = @[ command ].retain;
|
_subCommands = @[ command ].retain;
|
||||||
} else {
|
} else {
|
||||||
NSMutableArray<IJSVGCommand*>* subCommandArray = nil;
|
NSMutableArray<IJSVGCommand*>* subCommandArray = nil;
|
||||||
subCommandArray = [[NSMutableArray alloc] initWithCapacity:sets].autorelease;
|
subCommandArray = [[NSMutableArray alloc] initWithCapacity:sets].autorelease;
|
||||||
@@ -154,7 +145,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store the retained value
|
// store the retained value
|
||||||
subCommands = subCommandArray.copy;
|
_subCommands = subCommandArray.copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -188,15 +179,15 @@
|
|||||||
|
|
||||||
- (CGFloat)readFloat
|
- (CGFloat)readFloat
|
||||||
{
|
{
|
||||||
CGFloat f = parameters[_currentIndex];
|
CGFloat f = _parameters[_currentIndex];
|
||||||
_currentIndex++;
|
_currentIndex++;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSPoint)readPoint
|
- (NSPoint)readPoint
|
||||||
{
|
{
|
||||||
CGFloat x = parameters[_currentIndex];
|
CGFloat x = _parameters[_currentIndex];
|
||||||
CGFloat y = parameters[_currentIndex + 1];
|
CGFloat y = _parameters[_currentIndex + 1];
|
||||||
_currentIndex += 2;
|
_currentIndex += 2;
|
||||||
return NSMakePoint(x, y);
|
return NSMakePoint(x, y);
|
||||||
}
|
}
|
||||||
@@ -211,4 +202,16 @@
|
|||||||
_currentIndex = 0;
|
_currentIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)description
|
||||||
|
{
|
||||||
|
NSMutableString* str = [[[NSMutableString alloc] init] autorelease];
|
||||||
|
[str appendFormat:@"%c ",_command];
|
||||||
|
NSMutableArray* args = [[[NSMutableArray alloc] initWithCapacity:_parameterCount] autorelease];
|
||||||
|
for(int i = 0; i < _parameterCount; i++) {
|
||||||
|
[args addObject:[NSString stringWithFormat:@"%f",_parameters[i]]];
|
||||||
|
}
|
||||||
|
[str appendString:[args componentsJoinedByString:@", "]];
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -23,14 +23,16 @@
|
|||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path curveToPoint:NSMakePoint(params[4], params[5])
|
CGPathAddCurveToPoint(path.path, NULL, params[0], params[1],
|
||||||
controlPoint1:NSMakePoint(params[0], params[1])
|
params[2], params[3],
|
||||||
controlPoint2:NSMakePoint(params[2], params[3])];
|
params[4], params[5]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[path.path relativeCurveToPoint:NSMakePoint(params[4], params[5])
|
CGPoint currentPoint = path.currentPoint;
|
||||||
controlPoint1:NSMakePoint(params[0], params[1])
|
CGPathAddCurveToPoint(path.path, NULL,
|
||||||
controlPoint2:NSMakePoint(params[2], params[3])];
|
currentPoint.x + params[0], currentPoint.y + params[1],
|
||||||
|
currentPoint.x + params[2], currentPoint.y + params[3],
|
||||||
|
currentPoint.x + params[4], currentPoint.y + params[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ static IJSVGPathDataSequence* _sequence;
|
|||||||
|
|
||||||
+ (IJSVGPathDataSequence*)pathDataSequence
|
+ (IJSVGPathDataSequence*)pathDataSequence
|
||||||
{
|
{
|
||||||
if(_sequence == NULL) {
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
_sequence = (IJSVGPathDataSequence*)malloc(sizeof(IJSVGPathDataSequence) * 7);
|
_sequence = (IJSVGPathDataSequence*)malloc(sizeof(IJSVGPathDataSequence) * 7);
|
||||||
_sequence[0] = kIJSVGPathDataSequenceTypeFloat;
|
_sequence[0] = kIJSVGPathDataSequenceTypeFloat;
|
||||||
_sequence[1] = kIJSVGPathDataSequenceTypeFloat;
|
_sequence[1] = kIJSVGPathDataSequenceTypeFloat;
|
||||||
@@ -29,10 +30,11 @@ static IJSVGPathDataSequence* _sequence;
|
|||||||
_sequence[4] = kIJSVGPathDataSequenceTypeFlag;
|
_sequence[4] = kIJSVGPathDataSequenceTypeFlag;
|
||||||
_sequence[5] = kIJSVGPathDataSequenceTypeFloat;
|
_sequence[5] = kIJSVGPathDataSequenceTypeFloat;
|
||||||
_sequence[6] = kIJSVGPathDataSequenceTypeFloat;
|
_sequence[6] = kIJSVGPathDataSequenceTypeFloat;
|
||||||
}
|
});
|
||||||
return _sequence;
|
return _sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modified from https://github.com/SVGKit/SVGKit/blob/880c94a5b77b6f22beb491a7a7e02ace220c32af/Source/Parsers/SVGKPointsAndPathsParser.m
|
||||||
+ (void)runWithParams:(CGFloat*)params
|
+ (void)runWithParams:(CGFloat*)params
|
||||||
paramCount:(NSInteger)count
|
paramCount:(NSInteger)count
|
||||||
command:(IJSVGCommand*)currentCommand
|
command:(IJSVGCommand*)currentCommand
|
||||||
@@ -42,83 +44,96 @@ static IJSVGPathDataSequence* _sequence;
|
|||||||
{
|
{
|
||||||
CGPoint radii = CGPointZero;
|
CGPoint radii = CGPointZero;
|
||||||
CGPoint arcEndPoint = CGPointZero;
|
CGPoint arcEndPoint = CGPointZero;
|
||||||
CGPoint arcStartPoint = path.currentPoint;
|
CGPoint pathCurrentPoint = path.currentPoint;
|
||||||
CGFloat xAxisRotation = 0;
|
CGFloat xAxisRotation = 0.f;
|
||||||
BOOL largeArcFlag = 0;
|
BOOL largeArcFlag = NO;
|
||||||
BOOL sweepFlag = 0;
|
BOOL sweepFlag = NO;
|
||||||
|
|
||||||
radii = [currentCommand readPoint];
|
radii = [currentCommand readPoint];
|
||||||
xAxisRotation = [currentCommand readFloat];
|
xAxisRotation = [currentCommand readFloat];
|
||||||
largeArcFlag = [currentCommand readBOOL];
|
largeArcFlag = [currentCommand readBOOL];
|
||||||
sweepFlag = [currentCommand readBOOL];
|
sweepFlag = [currentCommand readBOOL];
|
||||||
arcEndPoint = [currentCommand readPoint];
|
arcEndPoint = [currentCommand readPoint];
|
||||||
|
|
||||||
|
CGFloat rx = fabs(radii.x);
|
||||||
|
CGFloat ry = fabs(radii.y);
|
||||||
|
|
||||||
|
xAxisRotation *= M_PI / 180.f;
|
||||||
|
xAxisRotation = fmod(xAxisRotation, 2.f * M_PI);
|
||||||
|
|
||||||
if (type == kIJSVGCommandTypeRelative) {
|
if (type == kIJSVGCommandTypeRelative) {
|
||||||
arcEndPoint.x += path.currentPoint.x;
|
arcEndPoint.x += pathCurrentPoint.x;
|
||||||
arcEndPoint.y += path.currentPoint.y;
|
arcEndPoint.y += pathCurrentPoint.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
xAxisRotation *= M_PI / 180.f;
|
CGFloat x1 = pathCurrentPoint.x;
|
||||||
CGPoint currentPoint = CGPointMake(cos(xAxisRotation) * (arcStartPoint.x - arcEndPoint.x) / 2.0 + sin(xAxisRotation) * (arcStartPoint.y - arcEndPoint.y) / 2.0, -sin(xAxisRotation) * (arcStartPoint.x - arcEndPoint.x) / 2.0 + cos(xAxisRotation) * (arcStartPoint.y - arcEndPoint.y) / 2.0);
|
CGFloat y1 = pathCurrentPoint.y;
|
||||||
|
|
||||||
CGFloat radiiAdjustment = pow(currentPoint.x, 2) / pow(radii.x, 2) + pow(currentPoint.y, 2) / pow(radii.y, 2);
|
CGFloat x2 = arcEndPoint.x;
|
||||||
radii.x *= (radiiAdjustment > 1) ? sqrt(radiiAdjustment) : 1;
|
CGFloat y2 = arcEndPoint.y;
|
||||||
radii.y *= (radiiAdjustment > 1) ? sqrt(radiiAdjustment) : 1;
|
|
||||||
|
if (rx == 0.f || ry == 0.f) {
|
||||||
CGFloat sweep = (largeArcFlag == sweepFlag ? -1 : 1) * sqrt(((pow(radii.x, 2) * pow(radii.y, 2)) - (pow(radii.x, 2) * pow(currentPoint.y, 2)) - (pow(radii.y, 2) * pow(currentPoint.x, 2))) / (pow(radii.x, 2) * pow(currentPoint.y, 2) + pow(radii.y, 2) * pow(currentPoint.x, 2)));
|
CGPathAddLineToPoint(path.path, NULL, x2, y2);
|
||||||
sweep = (sweep != sweep) ? 0 : sweep;
|
|
||||||
CGPoint preCenterPoint = CGPointMake(sweep * radii.x * currentPoint.y / radii.y, sweep * -radii.y * currentPoint.x / radii.x);
|
|
||||||
|
|
||||||
CGPoint centerPoint = CGPointMake((arcStartPoint.x + arcEndPoint.x) / 2.0 + cos(xAxisRotation) * preCenterPoint.x - sin(xAxisRotation) * preCenterPoint.y, (arcStartPoint.y + arcEndPoint.y) / 2.0 + sin(xAxisRotation) * preCenterPoint.x + cos(xAxisRotation) * preCenterPoint.y);
|
|
||||||
|
|
||||||
CGFloat startAngle = angle(CGPointMake(1, 0), CGPointMake((currentPoint.x - preCenterPoint.x) / radii.x, (currentPoint.y - preCenterPoint.y) / radii.y));
|
|
||||||
|
|
||||||
CGPoint deltaU = CGPointMake((currentPoint.x - preCenterPoint.x) / radii.x,
|
|
||||||
(currentPoint.y - preCenterPoint.y) / radii.y);
|
|
||||||
CGPoint deltaV = CGPointMake((-currentPoint.x - preCenterPoint.x) / radii.x,
|
|
||||||
(-currentPoint.y - preCenterPoint.y) / radii.y);
|
|
||||||
CGFloat angleDelta = (deltaU.x * deltaV.y < deltaU.y * deltaV.x ? -1 : 1) * acos(ratio(deltaU, deltaV));
|
|
||||||
|
|
||||||
angleDelta = (ratio(deltaU, deltaV) <= -1) ? M_PI : (ratio(deltaU, deltaV) >= 1) ? 0 : angleDelta;
|
|
||||||
|
|
||||||
// check for actually numbers, if this is not valid
|
|
||||||
// kill it, blame WWDC 2017 SVG background for this...
|
|
||||||
if (isnan(startAngle) || isnan(angleDelta)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGFloat cosPhi = cos(xAxisRotation);
|
||||||
|
CGFloat sinPhi = sin(xAxisRotation);
|
||||||
|
|
||||||
|
CGFloat x1p = cosPhi * (x1 - x2) / 2.f + sinPhi * (y1 - y2) / 2.f;
|
||||||
|
CGFloat y1p = -sinPhi * (x1 - x2) / 2.f + cosPhi * (y1 - y2) / 2.f;
|
||||||
|
|
||||||
|
CGFloat rx_2 = rx * rx;
|
||||||
|
CGFloat ry_2 = ry * ry;
|
||||||
|
CGFloat xp_2 = x1p * x1p;
|
||||||
|
CGFloat yp_2 = y1p * y1p;
|
||||||
|
|
||||||
CGFloat radius = MAX(radii.x, radii.y);
|
CGFloat delta = xp_2 / rx_2 + yp_2 / ry_2;
|
||||||
CGPoint scale = (radii.x > radii.y) ? CGPointMake(1, radii.y / radii.x) : CGPointMake(radii.x / radii.y, 1);
|
|
||||||
|
if (delta > 1.f) {
|
||||||
|
rx *= sqrt(delta);
|
||||||
|
ry *= sqrt(delta);
|
||||||
|
rx_2 = rx * rx;
|
||||||
|
ry_2 = ry * ry;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat sign = (largeArcFlag == sweepFlag) ? -1.f : 1.f;
|
||||||
|
CGFloat numerator = MAX(0.f, rx_2 * ry_2 - rx_2 * yp_2 - ry_2 * xp_2);
|
||||||
|
CGFloat denom = rx_2 * yp_2 + ry_2 * xp_2;
|
||||||
|
CGFloat lhs = denom == 0.f ? 0.f : sign * sqrt(numerator / denom);
|
||||||
|
|
||||||
|
CGFloat cxp = lhs * (rx * y1p) / ry;
|
||||||
|
CGFloat cyp = lhs * -((ry * x1p) / rx);
|
||||||
|
|
||||||
|
CGFloat cx = cosPhi * cxp + -sinPhi * cyp + (x1 + x2) / 2.f;
|
||||||
|
CGFloat cy = cxp * sinPhi + cyp * cosPhi + (y1 + y2) / 2.f;
|
||||||
|
|
||||||
NSAffineTransform* trans = NSAffineTransform.transform;
|
CGAffineTransform transform = CGAffineTransformMakeScale(1.f / rx, 1.f / ry);
|
||||||
[trans translateXBy:-centerPoint.x yBy:-centerPoint.y];
|
transform = CGAffineTransformRotate(transform, -xAxisRotation);
|
||||||
[path.path transformUsingAffineTransform:trans];
|
transform = CGAffineTransformTranslate(transform, -cx, -cy);
|
||||||
|
|
||||||
|
CGPoint arcPt1 = CGPointApplyAffineTransform(CGPointMake(x1, y1), transform);
|
||||||
|
CGPoint arcPt2 = CGPointApplyAffineTransform(CGPointMake(x2, y2), transform);
|
||||||
|
|
||||||
|
CGFloat startAngle = atan2(arcPt1.y, arcPt1.x);
|
||||||
|
CGFloat endAngle = atan2(arcPt2.y, arcPt2.x);
|
||||||
|
|
||||||
|
CGFloat angleDelta = endAngle - startAngle;;
|
||||||
|
|
||||||
|
if (sweepFlag == YES) {
|
||||||
|
if (angleDelta < 0.f) {
|
||||||
|
angleDelta += 2.f * M_PI;
|
||||||
|
}
|
||||||
|
} else if (angleDelta > 0.f) {
|
||||||
|
angleDelta = angleDelta - 2.f * M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform = CGAffineTransformMakeTranslation(cx, cy);
|
||||||
|
transform = CGAffineTransformRotate(transform, xAxisRotation);
|
||||||
|
transform = CGAffineTransformScale(transform, rx, ry);
|
||||||
|
|
||||||
trans = NSAffineTransform.transform;
|
CGPathAddRelativeArc(path.path, &transform, 0.f, 0.f, 1.f,
|
||||||
[trans rotateByRadians:-xAxisRotation];
|
startAngle, angleDelta);
|
||||||
[path.path transformUsingAffineTransform:trans];
|
|
||||||
|
|
||||||
trans = NSAffineTransform.transform;
|
|
||||||
[trans scaleXBy:(1 / scale.x) yBy:(1 / scale.y)];
|
|
||||||
[path.path transformUsingAffineTransform:trans];
|
|
||||||
|
|
||||||
[path.path appendBezierPathWithArcWithCenter:NSZeroPoint
|
|
||||||
radius:radius
|
|
||||||
startAngle:radians_to_degrees(startAngle)
|
|
||||||
endAngle:radians_to_degrees(startAngle + angleDelta)
|
|
||||||
clockwise:!sweepFlag];
|
|
||||||
|
|
||||||
trans = NSAffineTransform.transform;
|
|
||||||
[trans scaleXBy:scale.x yBy:scale.y];
|
|
||||||
[path.path transformUsingAffineTransform:trans];
|
|
||||||
|
|
||||||
trans = NSAffineTransform.transform;
|
|
||||||
[trans rotateByRadians:xAxisRotation];
|
|
||||||
[path.path transformUsingAffineTransform:trans];
|
|
||||||
|
|
||||||
trans = NSAffineTransform.transform;
|
|
||||||
[trans translateXBy:centerPoint.x yBy:centerPoint.y];
|
|
||||||
[path.path transformUsingAffineTransform:trans];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -23,10 +23,12 @@
|
|||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path lineToPoint:NSMakePoint(params[0], path.currentPoint.y)];
|
CGPathAddLineToPoint(path.path, NULL, params[0], path.currentPoint.y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[path.path relativeLineToPoint:NSMakePoint(params[0], 0.f)];
|
CGPoint currentPoint = path.currentPoint;
|
||||||
|
CGPathAddLineToPoint(path.path, NULL, currentPoint.x + params[0],
|
||||||
|
path.currentPoint.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -23,12 +23,12 @@
|
|||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path lineToPoint:NSMakePoint(params[0], params[1])];
|
CGPathAddLineToPoint(path.path, NULL, params[0], params[1]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NSPoint point = NSMakePoint(path.currentPoint.x + params[0],
|
CGPoint currentPoint = path.currentPoint;
|
||||||
path.currentPoint.y + params[1]);
|
CGPathAddLineToPoint(path.path, NULL, currentPoint.x + params[0],
|
||||||
[path.path lineToPoint:point];
|
currentPoint.y + params[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -35,17 +35,20 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// actual move to command
|
// actual move to command - do a moveToPoint only
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
// if the type is absolute, or its possible the type is
|
||||||
[path.path moveToPoint:NSMakePoint(params[0], params[1])];
|
// relative but there is no previous command which means
|
||||||
|
// there is no current point. Asking for current point on an empty
|
||||||
|
// path will result in an exception being thrown
|
||||||
|
if (type == kIJSVGCommandTypeAbsolute || command == nil) {
|
||||||
|
CGPathMoveToPoint(path.path, NULL,
|
||||||
|
params[0], params[1]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@try {
|
CGPoint currentPoint = path.currentPoint;
|
||||||
[path.path relativeMoveToPoint:NSMakePoint(params[0], params[1])];
|
CGPathMoveToPoint(path.path, NULL,
|
||||||
}
|
currentPoint.x + params[0],
|
||||||
@catch (NSException* exception) {
|
currentPoint.y + params[1]);
|
||||||
[path.path moveToPoint:NSMakePoint(params[0], params[1])];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -24,12 +24,14 @@
|
|||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path addQuadCurveToPoint:NSMakePoint(params[2], params[3])
|
CGPathAddQuadCurveToPoint(path.path, NULL, params[0], params[1],
|
||||||
controlPoint:NSMakePoint(params[0], params[1])];
|
params[2], params[3]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[path.path addQuadCurveToPoint:NSMakePoint(path.currentPoint.x + params[2], path.currentPoint.y + params[3])
|
CGPoint currentPoint = path.currentPoint;
|
||||||
controlPoint:NSMakePoint(path.currentPoint.x + params[0], path.currentPoint.y + params[1])];
|
CGPathAddQuadCurveToPoint(path.path, NULL,
|
||||||
|
currentPoint.x + params[0], currentPoint.y + params[1],
|
||||||
|
currentPoint.x + params[2], currentPoint.y + params[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -24,41 +24,41 @@
|
|||||||
type:(IJSVGCommandType)type
|
type:(IJSVGCommandType)type
|
||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
NSPoint firstControl = NSMakePoint(path.currentPoint.x, path.currentPoint.y);
|
CGPoint currentPoint = path.currentPoint;
|
||||||
|
CGPoint firstControl = CGPointMake(currentPoint.x, currentPoint.y);
|
||||||
if (command != nil) {
|
if (command != nil) {
|
||||||
if (command.class == [IJSVGCommandCurve class] || command.class == self.class) {
|
if (command.class == [IJSVGCommandCurve class] || command.class == self.class) {
|
||||||
if (command.class == [IJSVGCommandCurve class]) {
|
if (command.class == [IJSVGCommandCurve class]) {
|
||||||
if (command.type == kIJSVGCommandTypeAbsolute) {
|
if (command.type == kIJSVGCommandTypeAbsolute) {
|
||||||
firstControl = NSMakePoint(-1 * command.parameters[2] + 2 * path.currentPoint.x,
|
firstControl = CGPointMake(-1 * command.parameters[2] + 2 * currentPoint.x,
|
||||||
-1 * command.parameters[3] + 2 * path.currentPoint.y);
|
-1 * command.parameters[3] + 2 * currentPoint.y);
|
||||||
} else {
|
} else {
|
||||||
NSPoint oldPoint = NSMakePoint(path.currentPoint.x - command.parameters[4],
|
NSPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[4],
|
||||||
path.currentPoint.y - command.parameters[5]);
|
currentPoint.y - command.parameters[5]);
|
||||||
firstControl = NSMakePoint(-1 * (command.parameters[2] + oldPoint.x) + 2 * path.currentPoint.x,
|
firstControl = CGPointMake(-1 * (command.parameters[2] + oldPoint.x) + 2 * currentPoint.x,
|
||||||
-1 * (command.parameters[3] + oldPoint.y) + 2 * path.currentPoint.y);
|
-1 * (command.parameters[3] + oldPoint.y) + 2 * currentPoint.y);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (command.type == kIJSVGCommandTypeAbsolute) {
|
if (command.type == kIJSVGCommandTypeAbsolute) {
|
||||||
firstControl = NSMakePoint(-1 * command.parameters[0] + 2 * path.currentPoint.x,
|
firstControl = CGPointMake(-1 * command.parameters[0] + 2 * currentPoint.x,
|
||||||
-1 * command.parameters[1] + 2 * path.currentPoint.y);
|
-1 * command.parameters[1] + 2 * currentPoint.y);
|
||||||
} else {
|
} else {
|
||||||
NSPoint oldPoint = NSMakePoint(path.currentPoint.x - command.parameters[2],
|
NSPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[2],
|
||||||
path.currentPoint.y - command.parameters[3]);
|
currentPoint.y - command.parameters[3]);
|
||||||
firstControl = NSMakePoint(-1 * (command.parameters[0] + oldPoint.x) + 2 * path.currentPoint.x,
|
firstControl = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * currentPoint.x,
|
||||||
-1 * (command.parameters[1] + oldPoint.y) + 2 * path.currentPoint.y);
|
-1 * (command.parameters[1] + oldPoint.y) + 2 * currentPoint.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path curveToPoint:NSMakePoint(params[2], params[3])
|
CGPathAddCurveToPoint(path.path, NULL, firstControl.x, firstControl.y,
|
||||||
controlPoint1:NSMakePoint(firstControl.x, firstControl.y)
|
params[0], params[1], params[2], params[3]);
|
||||||
controlPoint2:NSMakePoint(params[0], params[1])];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[path.path curveToPoint:NSMakePoint(path.currentPoint.x + params[2], path.currentPoint.y + params[3])
|
CGPathAddCurveToPoint(path.path, NULL, firstControl.x, firstControl.y,
|
||||||
controlPoint1:NSMakePoint(firstControl.x, firstControl.y)
|
currentPoint.x + params[0], currentPoint.y + params[1],
|
||||||
controlPoint2:NSMakePoint(path.currentPoint.x + params[0], path.currentPoint.y + params[1])];
|
currentPoint.x + params[2], currentPoint.y + params[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -24,33 +24,34 @@
|
|||||||
type:(IJSVGCommandType)type
|
type:(IJSVGCommandType)type
|
||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
NSPoint commandPoint = NSMakePoint(path.currentPoint.x, path.currentPoint.y);
|
CGPoint currentPoint = path.currentPoint;
|
||||||
|
CGPoint commandPoint = CGPointMake(currentPoint.x, currentPoint.y);
|
||||||
if (command != nil) {
|
if (command != nil) {
|
||||||
if (command.class == IJSVGCommandQuadraticCurve.class) {
|
if (command.class == IJSVGCommandQuadraticCurve.class) {
|
||||||
// quadratic curve
|
// quadratic curve
|
||||||
if (command.type == kIJSVGCommandTypeAbsolute) {
|
if (command.type == kIJSVGCommandTypeAbsolute) {
|
||||||
commandPoint = NSMakePoint(-1 * command.parameters[0] + 2 * path.currentPoint.x,
|
commandPoint = NSMakePoint(-1 * command.parameters[0] + 2 * currentPoint.x,
|
||||||
-1 * command.parameters[1] + 2 * path.currentPoint.y);
|
-1 * command.parameters[1] + 2 * currentPoint.y);
|
||||||
} else {
|
} else {
|
||||||
NSPoint oldPoint = CGPointMake(path.currentPoint.x - command.parameters[2],
|
CGPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[2],
|
||||||
path.currentPoint.y - command.parameters[3]);
|
currentPoint.y - command.parameters[3]);
|
||||||
commandPoint = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * (path.currentPoint.x),
|
commandPoint = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * (currentPoint.x),
|
||||||
-1 * (command.parameters[1] + oldPoint.y) + 2 * path.currentPoint.y);
|
-1 * (command.parameters[1] + oldPoint.y) + 2 * currentPoint.y);
|
||||||
}
|
}
|
||||||
} else if (command.class == self.class) {
|
} else if (command.class == self.class) {
|
||||||
// smooth quadratic curve
|
// smooth quadratic curve
|
||||||
commandPoint = CGPointMake(-1 * (path.lastControlPoint.x) + 2 * (path.currentPoint.x),
|
commandPoint = CGPointMake(-1 * (path.lastControlPoint.x) + 2 * (currentPoint.x),
|
||||||
-1 * (path.lastControlPoint.y) + 2 * path.currentPoint.y);
|
-1 * (path.lastControlPoint.y) + 2 * currentPoint.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path.lastControlPoint = commandPoint;
|
path.lastControlPoint = commandPoint;
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path addQuadCurveToPoint:NSMakePoint(params[0], params[1])
|
CGPathAddQuadCurveToPoint(path.path, NULL, commandPoint.x, commandPoint.y,
|
||||||
controlPoint:commandPoint];
|
params[0], params[1]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[path.path addQuadCurveToPoint:NSMakePoint(path.currentPoint.x + params[0], path.currentPoint.y + params[1])
|
CGPathAddQuadCurveToPoint(path.path, NULL, commandPoint.x, commandPoint.y,
|
||||||
controlPoint:commandPoint];
|
currentPoint.x + params[0], currentPoint.y + params[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -23,10 +23,11 @@
|
|||||||
path:(IJSVGPath*)path
|
path:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
if (type == kIJSVGCommandTypeAbsolute) {
|
if (type == kIJSVGCommandTypeAbsolute) {
|
||||||
[path.path lineToPoint:NSMakePoint(path.currentPoint.x, params[0])];
|
CGPathAddLineToPoint(path.path, NULL, path.currentPoint.x, params[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[path.path relativeLineToPoint:NSMakePoint(0.f, params[0])];
|
CGPoint currentPoint = path.currentPoint;
|
||||||
|
CGPathAddLineToPoint(path.path, NULL, currentPoint.x, currentPoint.y + params[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,21 +6,26 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGBezierPathAdditions.h"
|
#import <IJSVG/IJSVGColorList.h>
|
||||||
#import "IJSVGColorList.h"
|
#import <IJSVG/IJSVGExporter.h>
|
||||||
#import "IJSVGExporter.h"
|
#import <IJSVG/IJSVGGradientLayer.h>
|
||||||
#import "IJSVGGradientLayer.h"
|
#import <IJSVG/IJSVGGroupLayer.h>
|
||||||
#import "IJSVGGroupLayer.h"
|
#import <IJSVG/IJSVGImageLayer.h>
|
||||||
#import "IJSVGImageLayer.h"
|
#import <IJSVG/IJSVGLayerTree.h>
|
||||||
#import "IJSVGLayerTree.h"
|
#import <IJSVG/IJSVGParser.h>
|
||||||
#import "IJSVGParser.h"
|
#import <IJSVG/IJSVGRendering.h>
|
||||||
#import "IJSVGRendering.h"
|
#import <IJSVG/IJSVGRenderingStyle.h>
|
||||||
#import "IJSVGRenderingStyle.h"
|
#import <IJSVG/IJSVGTransaction.h>
|
||||||
#import "IJSVGTransaction.h"
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVG;
|
@class IJSVG;
|
||||||
|
|
||||||
|
typedef NS_OPTIONS(NSInteger, IJSVGMatchPropertiesMask) {
|
||||||
|
IJSVGMatchPropertyNone = 0,
|
||||||
|
IJSVGMatchPropertyContainsMaskedElement = 1 << 0,
|
||||||
|
IJSVGMatchPropertyContainsStrokedElement = 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
@protocol IJSVGDelegate <NSObject, IJSVGParserDelegate>
|
@protocol IJSVGDelegate <NSObject, IJSVGParserDelegate>
|
||||||
|
|
||||||
@optional
|
@optional
|
||||||
@@ -44,7 +49,6 @@
|
|||||||
id<IJSVGDelegate> _delegate;
|
id<IJSVGDelegate> _delegate;
|
||||||
IJSVGLayer* _layerTree;
|
IJSVGLayer* _layerTree;
|
||||||
CGRect _viewBox;
|
CGRect _viewBox;
|
||||||
CGSize _proposedViewSize;
|
|
||||||
CGFloat _backingScaleFactor;
|
CGFloat _backingScaleFactor;
|
||||||
CGFloat _lastProposedBackingScale;
|
CGFloat _lastProposedBackingScale;
|
||||||
IJSVGRenderQuality _lastProposedRenderQuality;
|
IJSVGRenderQuality _lastProposedRenderQuality;
|
||||||
@@ -68,7 +72,10 @@
|
|||||||
// fillColor, strokeColor, pattern and gradient fill
|
// fillColor, strokeColor, pattern and gradient fill
|
||||||
@property (nonatomic, assign) IJSVGRenderQuality renderQuality;
|
@property (nonatomic, assign) IJSVGRenderQuality renderQuality;
|
||||||
@property (nonatomic, assign) BOOL clipToViewport;
|
@property (nonatomic, assign) BOOL clipToViewport;
|
||||||
@property (nonatomic, retain) IJSVGRenderingStyle* style;
|
@property (nonatomic, retain) IJSVGRenderingStyle* renderingStyle;
|
||||||
|
@property (nonatomic, readonly) IJSVGUnitSize * intrinsicSize;
|
||||||
|
@property (nonatomic, copy) NSString* title;
|
||||||
|
@property (nonatomic, copy) NSString* desc;
|
||||||
|
|
||||||
- (void)prepForDrawingInView:(NSView*)view;
|
- (void)prepForDrawingInView:(NSView*)view;
|
||||||
- (BOOL)isFont;
|
- (BOOL)isFont;
|
||||||
@@ -80,6 +87,8 @@
|
|||||||
- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree;
|
- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree;
|
||||||
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive;
|
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive;
|
||||||
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options;
|
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options;
|
||||||
|
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
|
||||||
- (CGFloat)computeBackingScale:(CGFloat)scale;
|
- (CGFloat)computeBackingScale:(CGFloat)scale;
|
||||||
- (void)discardDOM;
|
- (void)discardDOM;
|
||||||
@@ -101,6 +110,10 @@
|
|||||||
- (id)initWithSVGString:(NSString*)string
|
- (id)initWithSVGString:(NSString*)string
|
||||||
error:(NSError**)error;
|
error:(NSError**)error;
|
||||||
|
|
||||||
|
- (id)initWithSVGData:(NSData*)data;
|
||||||
|
- (id)initWithSVGData:(NSData*)data
|
||||||
|
error:(NSError**)error;
|
||||||
|
|
||||||
- (id)initWithFile:(NSString*)file;
|
- (id)initWithFile:(NSString*)file;
|
||||||
- (id)initWithFile:(NSString*)file
|
- (id)initWithFile:(NSString*)file
|
||||||
error:(NSError**)error;
|
error:(NSError**)error;
|
||||||
@@ -117,11 +130,21 @@
|
|||||||
- (id)initWithFilePathURL:(NSURL*)aURL
|
- (id)initWithFilePathURL:(NSURL*)aURL
|
||||||
error:(NSError**)error
|
error:(NSError**)error
|
||||||
delegate:(id<IJSVGDelegate>)delegate;
|
delegate:(id<IJSVGDelegate>)delegate;
|
||||||
|
|
||||||
|
- (id)initWithDataAssetNamed:(NSDataAssetName)name
|
||||||
|
error:(NSError**)error;
|
||||||
|
- (id)initWithDataAssetNamed:(NSDataAssetName)name
|
||||||
|
bundle:(NSBundle*)bundle
|
||||||
|
error:(NSError**)error;
|
||||||
|
|
||||||
- (NSImage*)imageWithSize:(NSSize)aSize;
|
- (NSImage*)imageWithSize:(NSSize)aSize;
|
||||||
- (NSImage*)imageWithSize:(NSSize)aSize
|
- (NSImage*)imageWithSize:(NSSize)aSize
|
||||||
error:(NSError**)error;
|
error:(NSError**)error;
|
||||||
- (NSImage*)imageWithSize:(NSSize)aSize
|
- (NSImage*)imageWithSize:(NSSize)aSize
|
||||||
flipped:(BOOL)flipped;
|
flipped:(BOOL)flipped;
|
||||||
|
- (NSImage*)imageWithSize:(NSSize)aSize
|
||||||
|
flipped:(BOOL)flipped
|
||||||
|
error:(NSError**)error;
|
||||||
- (NSImage*)imageByMaintainingAspectRatioWithSize:(NSSize)aSize
|
- (NSImage*)imageByMaintainingAspectRatioWithSize:(NSSize)aSize
|
||||||
flipped:(BOOL)flipped
|
flipped:(BOOL)flipped
|
||||||
error:(NSError**)error;
|
error:(NSError**)error;
|
||||||
@@ -153,5 +176,9 @@
|
|||||||
- (void)setNeedsDisplay;
|
- (void)setNeedsDisplay;
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
- (IJSVGColorList*)computedColorList:(BOOL*)hasPatternFills;
|
- (IJSVGColorList*)colorList;
|
||||||
|
- (void)performBlock:(dispatch_block_t)block;
|
||||||
|
|
||||||
|
// matching
|
||||||
|
- (BOOL)matchesPropertiesWithMask:(IJSVGMatchPropertiesMask)mask;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,23 +12,28 @@
|
|||||||
|
|
||||||
@implementation IJSVG
|
@implementation IJSVG
|
||||||
|
|
||||||
@synthesize renderingBackingScaleHelper;
|
// these are explicitly implemented
|
||||||
@synthesize clipToViewport;
|
@synthesize title = _title;
|
||||||
@synthesize renderQuality;
|
@synthesize desc = _desc;
|
||||||
@synthesize style = _style;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
// this can all be called on the background thread to be released
|
// this can all be called on the background thread to be released
|
||||||
(void)([renderingBackingScaleHelper release]),
|
BOOL hasTransaction = IJSVGBeginTransaction();
|
||||||
renderingBackingScaleHelper = nil;
|
(void)([_renderingBackingScaleHelper release]), _renderingBackingScaleHelper = nil;
|
||||||
(void)([_replacementColors release]), _replacementColors = nil;
|
(void)([_replacementColors release]), _replacementColors = nil;
|
||||||
(void)([_style release]), _style = nil;
|
(void)([_renderingStyle release]), _renderingStyle = nil;
|
||||||
(void)([_group release]), _group = nil;
|
(void)([_group release]), _group = nil;
|
||||||
|
(void)([_intrinsicSize release]), _intrinsicSize = nil;
|
||||||
|
(void)([_title release]), _title = nil;
|
||||||
|
(void)([_desc release]), _desc = nil;
|
||||||
|
|
||||||
// kill any memory that has been around
|
// kill any memory that has been around
|
||||||
(void)([_layerTree release]), _layerTree = nil;
|
(void)([_layerTree release]), _layerTree = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
|
if (hasTransaction == YES) {
|
||||||
|
IJSVGEndTransaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)svgNamed:(NSString*)string
|
+ (id)svgNamed:(NSString*)string
|
||||||
@@ -64,12 +69,35 @@
|
|||||||
ext = @"svg";
|
ext = @"svg";
|
||||||
}
|
}
|
||||||
if ((str = [bundle pathForResource:[string stringByDeletingPathExtension]
|
if ((str = [bundle pathForResource:[string stringByDeletingPathExtension]
|
||||||
ofType:ext])
|
ofType:ext]) != nil) {
|
||||||
!= nil) {
|
|
||||||
return [[[self alloc] initWithFile:str
|
return [[[self alloc] initWithFile:str
|
||||||
error:error
|
error:error
|
||||||
delegate:delegate] autorelease];
|
delegate:delegate] autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the asset catalogues
|
||||||
|
return [[[self alloc] initWithDataAssetNamed:string
|
||||||
|
error:error] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithDataAssetNamed:(NSDataAssetName)name
|
||||||
|
error:(NSError**)error
|
||||||
|
{
|
||||||
|
return [self initWithDataAssetNamed:name
|
||||||
|
bundle:NSBundle.mainBundle
|
||||||
|
error:error];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithDataAssetNamed:(NSDataAssetName)name
|
||||||
|
bundle:(NSBundle*)bundle
|
||||||
|
error:(NSError**)error
|
||||||
|
{
|
||||||
|
NSDataAsset* dataAsset = [[[NSDataAsset alloc] initWithName:name
|
||||||
|
bundle:bundle] autorelease];
|
||||||
|
if(dataAsset != nil) {
|
||||||
|
return [[self initWithSVGData:dataAsset.data
|
||||||
|
error:error] autorelease];
|
||||||
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,10 +107,14 @@
|
|||||||
__block IJSVGImageLayer* imageLayer = nil;
|
__block IJSVGImageLayer* imageLayer = nil;
|
||||||
|
|
||||||
// create the layers we require
|
// create the layers we require
|
||||||
|
BOOL hasTransaction = IJSVGBeginTransaction();
|
||||||
layer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
layer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
||||||
imageLayer =
|
imageLayer =
|
||||||
[[[IJSVGImageLayer alloc] initWithImage:image] autorelease];
|
[[[IJSVGImageLayer alloc] initWithImage:image] autorelease];
|
||||||
[layer addSublayer:imageLayer];
|
[layer addSublayer:imageLayer];
|
||||||
|
if (hasTransaction == YES) {
|
||||||
|
IJSVGEndTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
// return the initialized SVG
|
// return the initialized SVG
|
||||||
return [self initWithSVGLayer:layer
|
return [self initWithSVGLayer:layer
|
||||||
@@ -115,7 +147,7 @@
|
|||||||
error:(NSError**)error
|
error:(NSError**)error
|
||||||
delegate:(id<IJSVGDelegate>)delegate
|
delegate:(id<IJSVGDelegate>)delegate
|
||||||
{
|
{
|
||||||
return [self initWithFilePathURL:[NSURL fileURLWithPath:file]
|
return [self initWithFilePathURL:[NSURL fileURLWithPath:file isDirectory:NO]
|
||||||
error:error
|
error:error
|
||||||
delegate:delegate];
|
delegate:delegate];
|
||||||
}
|
}
|
||||||
@@ -192,6 +224,21 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id)initWithSVGData:(NSData*)data
|
||||||
|
{
|
||||||
|
return [self initWithSVGData:data
|
||||||
|
error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithSVGData:(NSData*)data
|
||||||
|
error:(NSError**)error
|
||||||
|
{
|
||||||
|
NSString* svgString = [[NSString alloc] initWithData:data
|
||||||
|
encoding:NSUTF8StringEncoding];
|
||||||
|
return [self initWithSVGString:svgString.autorelease
|
||||||
|
error:error];
|
||||||
|
}
|
||||||
|
|
||||||
- (id)initWithSVGString:(NSString*)string
|
- (id)initWithSVGString:(NSString*)string
|
||||||
{
|
{
|
||||||
return [self initWithSVGString:string
|
return [self initWithSVGString:string
|
||||||
@@ -238,6 +285,15 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)performBlock:(dispatch_block_t)block
|
||||||
|
{
|
||||||
|
BOOL hasTransaction = IJSVGBeginTransaction();
|
||||||
|
block();
|
||||||
|
if (hasTransaction == YES) {
|
||||||
|
IJSVGEndTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)discardDOM
|
- (void)discardDOM
|
||||||
{
|
{
|
||||||
// if we discard, we can no longer create a tree, so lets create tree
|
// if we discard, we can no longer create a tree, so lets create tree
|
||||||
@@ -250,24 +306,43 @@
|
|||||||
|
|
||||||
- (void)_setupBasicInfoFromGroup
|
- (void)_setupBasicInfoFromGroup
|
||||||
{
|
{
|
||||||
// store the viewbox
|
|
||||||
_viewBox = _group.viewBox;
|
_viewBox = _group.viewBox;
|
||||||
_proposedViewSize = _group.proposedViewSize;
|
_intrinsicSize = _group.intrinsicSize.retain;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_setupBasicsFromAnyInitializer
|
- (void)_setupBasicsFromAnyInitializer
|
||||||
{
|
{
|
||||||
self.style = [[[IJSVGRenderingStyle alloc] init] autorelease];
|
self.renderingStyle = [[[IJSVGRenderingStyle alloc] init] autorelease];
|
||||||
self.clipToViewport = YES;
|
self.clipToViewport = YES;
|
||||||
self.renderQuality = kIJSVGRenderQualityFullResolution;
|
self.renderQuality = kIJSVGRenderQualityFullResolution;
|
||||||
|
|
||||||
// setup low level backing scale
|
// setup low level backing scale
|
||||||
_lastProposedBackingScale = 0.f;
|
_lastProposedBackingScale = 0.f;
|
||||||
self.renderingBackingScaleHelper = ^CGFloat {
|
self.renderingBackingScaleHelper = ^CGFloat {
|
||||||
return 1.f;
|
return NSScreen.mainScreen.backingScaleFactor;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setTitle:(NSString*)title
|
||||||
|
{
|
||||||
|
_group.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*)title
|
||||||
|
{
|
||||||
|
return _group.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setDesc:(NSString*)description
|
||||||
|
{
|
||||||
|
_group.desc = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*)desc
|
||||||
|
{
|
||||||
|
return _group.desc;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString*)identifier
|
- (NSString*)identifier
|
||||||
{
|
{
|
||||||
return _group.identifier;
|
return _group.identifier;
|
||||||
@@ -310,10 +385,19 @@
|
|||||||
|
|
||||||
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options
|
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options
|
||||||
{
|
{
|
||||||
IJSVGExporter* exporter =
|
IJSVGExporter* exporter = [[[IJSVGExporter alloc] initWithSVG:self
|
||||||
[[[IJSVGExporter alloc] initWithSVG:self
|
size:self.viewBox.size
|
||||||
size:self.viewBox.size
|
options:options] autorelease];
|
||||||
options:options] autorelease];
|
return [exporter SVGString];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
IJSVGExporter* exporter = [[[IJSVGExporter alloc] initWithSVG:self
|
||||||
|
size:self.viewBox.size
|
||||||
|
options:options
|
||||||
|
floatingPointOptions:floatingPointOptions] autorelease];
|
||||||
return [exporter SVGString];
|
return [exporter SVGString];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,11 +424,19 @@
|
|||||||
error:nil];
|
error:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSSize)computeSVGSizeWithRenderSize:(NSSize)size
|
||||||
|
{
|
||||||
|
IJSVGUnitSize* svgSize = _intrinsicSize;
|
||||||
|
return NSMakeSize([svgSize.width computeValue:size.width],
|
||||||
|
[svgSize.height computeValue:size.height]);
|
||||||
|
}
|
||||||
|
|
||||||
- (NSRect)computeOriginalDrawingFrameWithSize:(NSSize)aSize
|
- (NSRect)computeOriginalDrawingFrameWithSize:(NSSize)aSize
|
||||||
{
|
{
|
||||||
[self _beginDraw:(NSRect){ .origin = CGPointZero, .size = aSize }];
|
NSSize propSize = [self computeSVGSizeWithRenderSize:aSize];
|
||||||
return NSMakeRect(0.f, 0.f, _proposedViewSize.width * _clipScale,
|
[self _beginDraw:(NSRect) { .origin = CGPointZero, .size = aSize }];
|
||||||
_proposedViewSize.height * _clipScale);
|
return NSMakeRect(0.f, 0.f, propSize.width * _clipScale,
|
||||||
|
propSize.height * _clipScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGImageRef)newCGImageRefWithSize:(CGSize)size
|
- (CGImageRef)newCGImageRefWithSize:(CGSize)size
|
||||||
@@ -353,7 +445,7 @@
|
|||||||
{
|
{
|
||||||
// setup the drawing rect, this is used for both the intial drawing
|
// setup the drawing rect, this is used for both the intial drawing
|
||||||
// and the backing scale helper block
|
// and the backing scale helper block
|
||||||
NSRect rect = (CGRect){
|
NSRect rect = (CGRect) {
|
||||||
.origin = CGPointZero,
|
.origin = CGPointZero,
|
||||||
.size = (CGSize)size
|
.size = (CGSize)size
|
||||||
};
|
};
|
||||||
@@ -362,7 +454,7 @@
|
|||||||
[self _beginDraw:rect];
|
[self _beginDraw:rect];
|
||||||
|
|
||||||
// make sure we setup the scale based on the backing scale factor
|
// make sure we setup the scale based on the backing scale factor
|
||||||
CGFloat scale = [self backindScaleFactor:NULL];
|
CGFloat scale = [self backingScaleFactor:NULL];
|
||||||
|
|
||||||
// create the context and colorspace
|
// create the context and colorspace
|
||||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
@@ -422,7 +514,7 @@
|
|||||||
- (NSData*)PDFData:(NSError**)error
|
- (NSData*)PDFData:(NSError**)error
|
||||||
{
|
{
|
||||||
return [self
|
return [self
|
||||||
PDFDataWithRect:(NSRect){ .origin = NSZeroPoint, .size = _viewBox.size }
|
PDFDataWithRect:(NSRect) { .origin = NSZeroPoint, .size = _viewBox.size }
|
||||||
error:error];
|
error:error];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,20 +572,24 @@
|
|||||||
{
|
{
|
||||||
// turn on converts masks to PDF's
|
// turn on converts masks to PDF's
|
||||||
// as PDF context and layer masks dont work
|
// as PDF context and layer masks dont work
|
||||||
void (^block)(CALayer* layer, BOOL isMask) = ^void(CALayer* layer, BOOL isMask) {
|
void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) =
|
||||||
|
^void(CALayer* layer, BOOL isMask, BOOL* stop) {
|
||||||
((IJSVGLayer*)layer).convertMasksToPaths = YES;
|
((IJSVGLayer*)layer).convertMasksToPaths = YES;
|
||||||
};
|
};
|
||||||
[IJSVGLayer recursivelyWalkLayer:self.layer withBlock:block];
|
[IJSVGLayer recursivelyWalkLayer:self.layer
|
||||||
|
withBlock:block];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_endVectorDraw
|
- (void)_endVectorDraw
|
||||||
{
|
{
|
||||||
// turn of convert masks to paths as not
|
// turn of convert masks to paths as not
|
||||||
// needed for generic rendering
|
// needed for generic rendering
|
||||||
void (^block)(CALayer* layer, BOOL isMask) = ^void(CALayer* layer, BOOL isMask) {
|
void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) =
|
||||||
|
^void(CALayer* layer, BOOL isMask, BOOL* stop) {
|
||||||
((IJSVGLayer*)layer).convertMasksToPaths = NO;
|
((IJSVGLayer*)layer).convertMasksToPaths = NO;
|
||||||
};
|
};
|
||||||
[IJSVGLayer recursivelyWalkLayer:self.layer withBlock:block];
|
[IJSVGLayer recursivelyWalkLayer:self.layer
|
||||||
|
withBlock:block];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)prepForDrawingInView:(NSView*)view
|
- (void)prepForDrawingInView:(NSView*)view
|
||||||
@@ -540,8 +636,14 @@
|
|||||||
- (BOOL)drawInRect:(NSRect)rect
|
- (BOOL)drawInRect:(NSRect)rect
|
||||||
error:(NSError**)error
|
error:(NSError**)error
|
||||||
{
|
{
|
||||||
|
CGContextRef currentCGContext;
|
||||||
|
if (@available(macOS 10.10, *)) {
|
||||||
|
currentCGContext = NSGraphicsContext.currentContext.CGContext;
|
||||||
|
} else {
|
||||||
|
currentCGContext = NSGraphicsContext.currentContext.graphicsPort;
|
||||||
|
}
|
||||||
return [self _drawInRect:rect
|
return [self _drawInRect:rect
|
||||||
context:[[NSGraphicsContext currentContext] CGContext]
|
context:currentCGContext
|
||||||
error:error];
|
error:error];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,14 +659,22 @@
|
|||||||
// we also need to calculate the viewport so we can clip
|
// we also need to calculate the viewport so we can clip
|
||||||
// the drawing if needed
|
// the drawing if needed
|
||||||
NSRect viewPort = NSZeroRect;
|
NSRect viewPort = NSZeroRect;
|
||||||
viewPort.origin.x = round((rect.size.width / 2 - (_proposedViewSize.width / 2) * _clipScale) + rect.origin.x);
|
NSSize propSize = [self computeSVGSizeWithRenderSize:rect.size];
|
||||||
|
viewPort.origin.x = round((rect.size.width / 2 - (propSize.width / 2) * _clipScale) + rect.origin.x);
|
||||||
viewPort.origin.y = round(
|
viewPort.origin.y = round(
|
||||||
(rect.size.height / 2 - (_proposedViewSize.height / 2) * _clipScale) + rect.origin.y);
|
(rect.size.height / 2 - (propSize.height / 2) * _clipScale) + rect.origin.y);
|
||||||
viewPort.size.width = _proposedViewSize.width * _clipScale;
|
viewPort.size.width = propSize.width * _clipScale;
|
||||||
viewPort.size.height = _proposedViewSize.height * _clipScale;
|
viewPort.size.height = propSize.height * _clipScale;
|
||||||
|
|
||||||
// check the viewport
|
// check the viewport
|
||||||
if (NSEqualRects(_viewBox, NSZeroRect) || _viewBox.size.width <= 0 || _viewBox.size.height <= 0 || NSEqualRects(NSZeroRect, viewPort) || CGRectIsEmpty(viewPort) || CGRectIsNull(viewPort) || viewPort.size.width <= 0 || viewPort.size.height <= 0) {
|
if (NSEqualRects(_viewBox, NSZeroRect) ||
|
||||||
|
_viewBox.size.width <= 0 ||
|
||||||
|
_viewBox.size.height <= 0 ||
|
||||||
|
NSEqualRects(NSZeroRect, viewPort) ||
|
||||||
|
CGRectIsEmpty(viewPort) ||
|
||||||
|
CGRectIsNull(viewPort) ||
|
||||||
|
viewPort.size.width <= 0 ||
|
||||||
|
viewPort.size.height <= 0) {
|
||||||
*valid = NO;
|
*valid = NO;
|
||||||
return NSZeroRect;
|
return NSZeroRect;
|
||||||
}
|
}
|
||||||
@@ -615,9 +725,7 @@
|
|||||||
|
|
||||||
// do we need to update the backing scales on the
|
// do we need to update the backing scales on the
|
||||||
// layers?
|
// layers?
|
||||||
if (self.renderingBackingScaleHelper != nil) {
|
[self backingScaleFactor:nil];
|
||||||
[self backindScaleFactor:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
CGInterpolationQuality quality;
|
CGInterpolationQuality quality;
|
||||||
switch (self.renderQuality) {
|
switch (self.renderQuality) {
|
||||||
@@ -634,7 +742,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CGContextSetInterpolationQuality(ref, quality);
|
CGContextSetInterpolationQuality(ref, quality);
|
||||||
|
BOOL hasTransaction = IJSVGBeginTransaction();
|
||||||
[self.layer renderInContext:ref];
|
[self.layer renderInContext:ref];
|
||||||
|
if (hasTransaction == YES) {
|
||||||
|
IJSVGEndTransaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} @catch (NSException* exception) {
|
} @catch (NSException* exception) {
|
||||||
// just catch and give back a drawing error to the caller
|
// just catch and give back a drawing error to the caller
|
||||||
@@ -648,7 +760,7 @@
|
|||||||
return (error == nil);
|
return (error == nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)backindScaleFactor:(CGFloat* _Nullable)proposedBackingScale
|
- (CGFloat)backingScaleFactor:(CGFloat* _Nullable)proposedBackingScale
|
||||||
{
|
{
|
||||||
__block CGFloat scale = 1.f;
|
__block CGFloat scale = 1.f;
|
||||||
scale = (self.renderingBackingScaleHelper)();
|
scale = (self.renderingBackingScaleHelper)();
|
||||||
@@ -663,7 +775,7 @@
|
|||||||
|
|
||||||
// dont do anything, nothing has changed, no point of iterating over
|
// dont do anything, nothing has changed, no point of iterating over
|
||||||
// every layer for no reason!
|
// every layer for no reason!
|
||||||
if (scale == _lastProposedBackingScale && renderQuality == _lastProposedRenderQuality) {
|
if (scale == _lastProposedBackingScale && _renderQuality == _lastProposedRenderQuality) {
|
||||||
return _backingScaleFactor;
|
return _backingScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,7 +787,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// walk the tree
|
// walk the tree
|
||||||
void (^block)(CALayer* layer, BOOL isMask) = ^void(CALayer* layer, BOOL isMask) {
|
void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) =
|
||||||
|
^void(CALayer* layer, BOOL isMask, BOOL* stop) {
|
||||||
IJSVGLayer* propLayer = ((IJSVGLayer*)layer);
|
IJSVGLayer* propLayer = ((IJSVGLayer*)layer);
|
||||||
propLayer.renderQuality = quality;
|
propLayer.renderQuality = quality;
|
||||||
if (propLayer.requiresBackingScaleHelp == YES) {
|
if (propLayer.requiresBackingScaleHelp == YES) {
|
||||||
@@ -684,19 +797,27 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// gogogo
|
// gogogo
|
||||||
|
BOOL hasTransaction = IJSVGBeginTransaction();
|
||||||
[IJSVGLayer recursivelyWalkLayer:self.layer withBlock:block];
|
[IJSVGLayer recursivelyWalkLayer:self.layer withBlock:block];
|
||||||
|
if (hasTransaction == YES) {
|
||||||
|
IJSVGEndTransaction();
|
||||||
|
}
|
||||||
return _backingScaleFactor;
|
return _backingScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree
|
- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree
|
||||||
{
|
{
|
||||||
// clear memory
|
// clear memory
|
||||||
|
BOOL hasTransaction = IJSVGBeginTransaction();
|
||||||
if (_layerTree != nil) {
|
if (_layerTree != nil) {
|
||||||
(void)([_layerTree release]), _layerTree = nil;
|
(void)([_layerTree release]), _layerTree = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// force rebuild of the tree
|
// force rebuild of the tree
|
||||||
_layerTree = [[tree layerForNode:_group] retain];
|
_layerTree = [[tree layerForNode:_group] retain];
|
||||||
|
if (hasTransaction == YES) {
|
||||||
|
IJSVGEndTransaction();
|
||||||
|
}
|
||||||
return _layerTree;
|
return _layerTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,16 +831,16 @@
|
|||||||
// from this SVG object
|
// from this SVG object
|
||||||
IJSVGLayerTree* renderer = [[[IJSVGLayerTree alloc] init] autorelease];
|
IJSVGLayerTree* renderer = [[[IJSVGLayerTree alloc] init] autorelease];
|
||||||
renderer.viewBox = self.viewBox;
|
renderer.viewBox = self.viewBox;
|
||||||
renderer.style = self.style;
|
renderer.style = self.renderingStyle;
|
||||||
|
|
||||||
// return the rendered layer
|
// return the rendered layer
|
||||||
return [self layerWithTree:renderer];
|
return [self layerWithTree:renderer];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setStyle:(IJSVGRenderingStyle*)style
|
- (void)setRenderingStyle:(IJSVGRenderingStyle*)style
|
||||||
{
|
{
|
||||||
(void)([_style release]), _style = nil;
|
(void)([_renderingStyle release]), _renderingStyle = nil;
|
||||||
_style = style.retain;
|
_renderingStyle = style.retain;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)observeValueForKeyPath:(NSString*)keyPath
|
- (void)observeValueForKeyPath:(NSString*)keyPath
|
||||||
@@ -728,7 +849,7 @@
|
|||||||
context:(void*)context
|
context:(void*)context
|
||||||
{
|
{
|
||||||
// invalidate the tree if a style is set
|
// invalidate the tree if a style is set
|
||||||
if (object == _style) {
|
if (object == _renderingStyle) {
|
||||||
[self invalidateLayerTree];
|
[self invalidateLayerTree];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,53 +864,72 @@
|
|||||||
(void)([_layerTree release]), _layerTree = nil;
|
(void)([_layerTree release]), _layerTree = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGColorList*)computedColorList:(BOOL*)hasPatternFills
|
- (IJSVGColorList*)colorList
|
||||||
{
|
{
|
||||||
IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease];
|
IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease];
|
||||||
void (^block)(CALayer* layer, BOOL isMask) = ^void(CALayer* layer,
|
void (^block)(CALayer* layer, BOOL isMask, BOOL* stop) =
|
||||||
BOOL isMask) {
|
^void(CALayer* layer, BOOL isMask, BOOL* stop) {
|
||||||
if ([layer isKindOfClass:[IJSVGShapeLayer class]] && isMask == NO && layer.isHidden == NO) {
|
|
||||||
IJSVGShapeLayer* sLayer = (IJSVGShapeLayer*)layer;
|
// dont do anything
|
||||||
NSColor* color = nil;
|
if(([layer isKindOfClass:IJSVGShapeLayer.class] && isMask == NO &&
|
||||||
if (sLayer.fillColor != nil) {
|
layer.isHidden == NO) == false) {
|
||||||
color = [NSColor colorWithCGColor:sLayer.fillColor];
|
return;
|
||||||
if (color.alphaComponent != 0.f) {
|
}
|
||||||
[sheet addColor:color];
|
|
||||||
}
|
|
||||||
}
|
// compute
|
||||||
if (sLayer.strokeColor != nil) {
|
IJSVGShapeLayer* sLayer = (IJSVGShapeLayer*)layer;
|
||||||
color = [NSColor colorWithCGColor:sLayer.strokeColor];
|
NSColor* color = nil;
|
||||||
color = [IJSVGColor computeColorSpace:color];
|
|
||||||
if (color.alphaComponent != 0.f) {
|
|
||||||
[sheet addColor:color];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for any patterns
|
// fill color
|
||||||
if (sLayer.patternFillLayer != nil || sLayer.gradientFillLayer != nil || sLayer.gradientStrokeLayer != nil || sLayer.patternStrokeLayer != nil) {
|
if (sLayer.fillColor != nil) {
|
||||||
if (hasPatternFills != nil && *hasPatternFills != YES) {
|
color = [NSColor colorWithCGColor:sLayer.fillColor];
|
||||||
*hasPatternFills = YES;
|
color = [IJSVGColor computeColorSpace:color];
|
||||||
}
|
if (color.alphaComponent != 0.f) {
|
||||||
|
IJSVGColorType* type = nil;
|
||||||
|
type = [IJSVGColorType typeWithColor:color
|
||||||
|
flags:IJSVGColorTypeFlagFill];
|
||||||
|
[sheet addColor:type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add any colors from gradients
|
// stroke color
|
||||||
IJSVGGradientLayer* gradLayer = nil;
|
if (sLayer.strokeColor != nil) {
|
||||||
IJSVGGradientLayer* gradStrokeLayer = nil;
|
color = [NSColor colorWithCGColor:sLayer.strokeColor];
|
||||||
if ((gradLayer = sLayer.gradientFillLayer) != nil) {
|
color = [IJSVGColor computeColorSpace:color];
|
||||||
IJSVGColorList* gradSheet = gradLayer.gradient.computedColorList;
|
if (color.alphaComponent != 0.f) {
|
||||||
[sheet addColorsFromList:gradSheet];
|
IJSVGColorType* type = nil;
|
||||||
}
|
type = [IJSVGColorType typeWithColor:color
|
||||||
if ((gradStrokeLayer = sLayer.gradientStrokeLayer) != nil) {
|
flags:IJSVGColorTypeFlagStroke];
|
||||||
IJSVGColorList* gradSheet = gradStrokeLayer.gradient.computedColorList;
|
[sheet addColor:type];
|
||||||
[sheet addColorsFromList:gradSheet];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for any patterns or strokes
|
||||||
|
if (sLayer.patternFillLayer != nil || sLayer.gradientFillLayer != nil ||
|
||||||
|
sLayer.gradientStrokeLayer != nil || sLayer.patternStrokeLayer != nil) {
|
||||||
|
|
||||||
|
// add any colors from gradients
|
||||||
|
IJSVGGradientLayer* gradLayer = nil;
|
||||||
|
IJSVGGradientLayer* gradStrokeLayer = nil;
|
||||||
|
|
||||||
|
// gradient fill
|
||||||
|
if ((gradLayer = sLayer.gradientFillLayer) != nil) {
|
||||||
|
IJSVGColorList* gradSheet = gradLayer.gradient.colorList;
|
||||||
|
[sheet addColorsFromList:gradSheet];
|
||||||
|
}
|
||||||
|
|
||||||
|
// gradient stroke layers
|
||||||
|
if ((gradStrokeLayer = sLayer.gradientStrokeLayer) != nil) {
|
||||||
|
IJSVGColorList* gradSheet = gradStrokeLayer.gradient.colorList;
|
||||||
|
[sheet addColorsFromList:gradSheet];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// walk
|
// gogogo!
|
||||||
[IJSVGLayer recursivelyWalkLayer:self.layer withBlock:block];
|
[IJSVGLayer recursivelyWalkLayer:self.layer
|
||||||
|
withBlock:block];
|
||||||
// return the colours!
|
|
||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,12 +940,13 @@
|
|||||||
// to transform the paths into our viewbox
|
// to transform the paths into our viewbox
|
||||||
NSSize dest = rect.size;
|
NSSize dest = rect.size;
|
||||||
NSSize source = _viewBox.size;
|
NSSize source = _viewBox.size;
|
||||||
_clipScale = MIN(dest.width / _proposedViewSize.width,
|
NSSize propSize = [self computeSVGSizeWithRenderSize:rect.size];
|
||||||
dest.height / _proposedViewSize.height);
|
_clipScale = MIN(dest.width / propSize.width,
|
||||||
|
dest.height / propSize.height);
|
||||||
|
|
||||||
// work out the actual scale based on the clip scale
|
// work out the actual scale based on the clip scale
|
||||||
CGFloat w = _proposedViewSize.width * _clipScale;
|
CGFloat w = propSize.width * _clipScale;
|
||||||
CGFloat h = _proposedViewSize.height * _clipScale;
|
CGFloat h = propSize.height * _clipScale;
|
||||||
_scale = MIN(w / source.width, h / source.height);
|
_scale = MIN(w / source.width, h / source.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -858,4 +999,43 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark matching
|
||||||
|
|
||||||
|
- (BOOL)matchesPropertiesWithMask:(IJSVGMatchPropertiesMask)mask
|
||||||
|
{
|
||||||
|
__block IJSVGMatchPropertiesMask matchedMask = IJSVGMatchPropertyNone;
|
||||||
|
IJSVGNodeWalkHandler handler = ^(IJSVGNode* node, BOOL* allowChildNodes,
|
||||||
|
BOOL* stop) {
|
||||||
|
// dont compute nodes that are not designed
|
||||||
|
// to be rendered
|
||||||
|
if(node.shouldRender == NO) {
|
||||||
|
*allowChildNodes = NO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for stroke
|
||||||
|
IJSVGPath* path = (IJSVGPath*)node;
|
||||||
|
if((mask & IJSVGMatchPropertyContainsStrokedElement) != 0 &&
|
||||||
|
[node isKindOfClass:IJSVGPath.class] == YES &&
|
||||||
|
path.isStroked == YES) {
|
||||||
|
matchedMask |= IJSVGMatchPropertyContainsStrokedElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for mask
|
||||||
|
if((mask & IJSVGMatchPropertyContainsMaskedElement) != 0 &&
|
||||||
|
node.mask != nil) {
|
||||||
|
matchedMask |= IJSVGMatchPropertyContainsMaskedElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// simply check if masks equal, if they are, stop this loop
|
||||||
|
// and return the evaluation
|
||||||
|
if(matchedMask == mask) {
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
[IJSVGNode walkNodeTree:_group
|
||||||
|
handler:handler];
|
||||||
|
return matchedMask == mask;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright (c) 2015 Curtis Hard. All rights reserved.
|
// Copyright (c) 2015 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVG.h"
|
#import <IJSVG/IJSVG.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
typedef void (^IJSVGFontConverterEnumerateBlock)(NSString* unicode, IJSVG* svg);
|
typedef void (^IJSVGFontConverterEnumerateBlock)(NSString* unicode, IJSVG* svg);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
// Copyright (c) 2015 Curtis Hard. All rights reserved.
|
// Copyright (c) 2015 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGBezierPathAdditions.h"
|
|
||||||
#import "IJSVGFontConverter.h"
|
#import "IJSVGFontConverter.h"
|
||||||
#import "IJSVGShapeLayer.h"
|
#import "IJSVGShapeLayer.h"
|
||||||
|
|
||||||
@@ -104,16 +103,15 @@
|
|||||||
|
|
||||||
+ (IJSVG*)convertIJSVGPathToSVG:(IJSVGPath*)path
|
+ (IJSVG*)convertIJSVGPathToSVG:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
CGPathRef cgPath = [path.path newCGPathRef:NO];
|
CGPathRef flippedPath = [IJSVGUtils newFlippedCGPath:path.path];
|
||||||
CGPathRef flippedPath = [IJSVGUtils newFlippedCGPath:cgPath];
|
|
||||||
IJSVG* svg = [self convertPathToSVG:flippedPath];
|
IJSVG* svg = [self convertPathToSVG:flippedPath];
|
||||||
CGPathRelease(flippedPath);
|
CGPathRelease(flippedPath);
|
||||||
CGPathRelease(cgPath);
|
|
||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (IJSVG*)convertPathToSVG:(CGPathRef)path
|
+ (IJSVG*)convertPathToSVG:(CGPathRef)path
|
||||||
{
|
{
|
||||||
|
IJSVGBeginTransaction();
|
||||||
__block IJSVG* svg = nil;
|
__block IJSVG* svg = nil;
|
||||||
IJSVGGroupLayer* layer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
IJSVGGroupLayer* layer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
||||||
IJSVGShapeLayer* shape = [[[IJSVGShapeLayer alloc] init] autorelease];
|
IJSVGShapeLayer* shape = [[[IJSVGShapeLayer alloc] init] autorelease];
|
||||||
@@ -122,6 +120,7 @@
|
|||||||
CGRect box = CGPathGetPathBoundingBox(path);
|
CGRect box = CGPathGetPathBoundingBox(path);
|
||||||
svg = [[IJSVG alloc] initWithSVGLayer:layer
|
svg = [[IJSVG alloc] initWithSVGLayer:layer
|
||||||
viewBox:box];
|
viewBox:box];
|
||||||
|
IJSVGEndTransaction();
|
||||||
return [svg autorelease];
|
return [svg autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
IJSVG* _svg;
|
IJSVG* _svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithData:(NSData*)data;
|
||||||
|
|
||||||
@property (nonatomic, readonly) CGRect viewBox;
|
@property (nonatomic, readonly) CGRect viewBox;
|
||||||
|
@property (nonatomic, readonly) IJSVG* SVG;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
@implementation IJSVGImageRep
|
@implementation IJSVGImageRep
|
||||||
|
|
||||||
@synthesize viewBox = _viewBox;
|
|
||||||
|
|
||||||
+ (void)load
|
+ (void)load
|
||||||
{
|
{
|
||||||
[NSBitmapImageRep registerImageRepClass:self];
|
[NSBitmapImageRep registerImageRepClass:self];
|
||||||
@@ -25,12 +23,20 @@
|
|||||||
|
|
||||||
+ (NSArray<NSString*>*)imageTypes
|
+ (NSArray<NSString*>*)imageTypes
|
||||||
{
|
{
|
||||||
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
|
if (@available(macOS 10.10, *)) {
|
||||||
|
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
|
||||||
|
} else {
|
||||||
|
return @[ @"public.svg-image", @"svg" ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray<NSString*>*)imageUnfilteredTypes
|
+ (NSArray<NSString*>*)imageUnfilteredTypes
|
||||||
{
|
{
|
||||||
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
|
if (@available(macOS 10.10, *)) {
|
||||||
|
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
|
||||||
|
} else {
|
||||||
|
return @[ @"public.svg-image", @"svg" ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray<NSImageRep*>*)imageRepsWithData:(NSData*)data
|
+ (NSArray<NSImageRep*>*)imageRepsWithData:(NSData*)data
|
||||||
@@ -101,4 +107,9 @@
|
|||||||
return _svg.viewBox;
|
return _svg.viewBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IJSVG*)SVG
|
||||||
|
{
|
||||||
|
return _svg;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVG.h"
|
#import <IJSVG/IJSVG.h>
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
IB_DESIGNABLE
|
IB_DESIGNABLE
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
if (imageName != nil) {
|
if (imageName != nil) {
|
||||||
IJSVG* anSVG = [IJSVG svgNamed:imageName];
|
IJSVG* anSVG = [IJSVG svgNamed:imageName];
|
||||||
if (tintColor != nil) {
|
if (tintColor != nil) {
|
||||||
anSVG.style.fillColor = tintColor;
|
anSVG.renderingStyle.fillColor = tintColor;
|
||||||
}
|
}
|
||||||
self.SVG = anSVG;
|
self.SVG = anSVG;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// IJSVGWriter.h
|
|
||||||
// IJSVGExample
|
|
||||||
//
|
|
||||||
// Created by Curtis Hard on 21/05/2015.
|
|
||||||
// Copyright (c) 2015 Curtis Hard. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "IJSVGPath.h"
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
@interface IJSVGWriter : NSObject {
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSString*)SVGDocumentStringForSVGGlyph:(IJSVGPath*)node;
|
|
||||||
+ (NSString*)SVGDocumentStringForBezierPath:(NSBezierPath*)path;
|
|
||||||
+ (NSXMLDocument*)SVGDocumentForBezierPath:(NSBezierPath*)path;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
//
|
|
||||||
// IJSVGWriter.m
|
|
||||||
// IJSVGExample
|
|
||||||
//
|
|
||||||
// Created by Curtis Hard on 21/05/2015.
|
|
||||||
// Copyright (c) 2015 Curtis Hard. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "IJSVGWriter.h"
|
|
||||||
|
|
||||||
@implementation IJSVGWriter
|
|
||||||
|
|
||||||
+ (NSString*)SVGDocumentStringForSVGGlyph:(IJSVGPath*)node
|
|
||||||
{
|
|
||||||
NSBezierPath* path = [node path];
|
|
||||||
// we need to flip it
|
|
||||||
NSAffineTransform* trans = NSAffineTransform.transform;
|
|
||||||
[trans scaleXBy:1.f yBy:-1.f];
|
|
||||||
[trans translateXBy:0.f yBy:path.controlPointBounds.size.height];
|
|
||||||
path = [trans transformBezierPath:path];
|
|
||||||
return [self.class SVGDocumentStringForBezierPath:path];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSString*)SVGDocumentStringForBezierPath:(NSBezierPath*)path
|
|
||||||
{
|
|
||||||
return [self.class SVGDocumentForBezierPath:path].XMLString;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSXMLDocument*)SVGDocumentForBezierPath:(NSBezierPath*)path
|
|
||||||
{
|
|
||||||
NSXMLElement* root = [self.class rootElementForPath:path];
|
|
||||||
|
|
||||||
// create the path data
|
|
||||||
NSXMLElement* p = [[[NSXMLElement alloc] initWithName:@"path"] autorelease];
|
|
||||||
|
|
||||||
// add the drawing command
|
|
||||||
NSXMLNode* n = [[[NSXMLNode alloc] initWithKind:NSXMLAttributeKind] autorelease];
|
|
||||||
[n setName:@"d"];
|
|
||||||
[n setStringValue:[self.class SVGPathStringForBezierPath:path]];
|
|
||||||
[p addAttribute:n];
|
|
||||||
|
|
||||||
// add the drawing path to the root
|
|
||||||
[root addChild:p];
|
|
||||||
return [[[NSXMLDocument alloc] initWithRootElement:root] autorelease];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSXMLElement*)rootElementForPath:(NSBezierPath*)path
|
|
||||||
{
|
|
||||||
NSXMLElement* element = [[[NSXMLElement alloc] initWithName:@"svg"] autorelease];
|
|
||||||
NSRect bounds = path.controlPointBounds;
|
|
||||||
|
|
||||||
// width
|
|
||||||
NSXMLNode* att = [[[NSXMLNode alloc] initWithKind:NSXMLAttributeKind] autorelease];
|
|
||||||
[att setName:@"width"];
|
|
||||||
[att setStringValue:[NSString stringWithFormat:@"%f", bounds.size.width]];
|
|
||||||
[element addAttribute:att];
|
|
||||||
|
|
||||||
// height
|
|
||||||
att = [[[NSXMLNode alloc] initWithKind:NSXMLAttributeKind] autorelease];
|
|
||||||
[att setName:@"height"];
|
|
||||||
[att setStringValue:[NSString stringWithFormat:@"%f", bounds.size.height]];
|
|
||||||
[element addAttribute:att];
|
|
||||||
|
|
||||||
// viewbox
|
|
||||||
att = [[[NSXMLNode alloc] initWithKind:NSXMLAttributeKind] autorelease];
|
|
||||||
[att setName:@"viewBox"];
|
|
||||||
[att setStringValue:[NSString stringWithFormat:@"%f %f %f %f", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height]];
|
|
||||||
[element addAttribute:att];
|
|
||||||
|
|
||||||
// namespace
|
|
||||||
att = [[[NSXMLNode alloc] initWithKind:NSXMLAttributeKind] autorelease];
|
|
||||||
[att setName:@"xmlns"];
|
|
||||||
[att setStringValue:@"http://www.w3.org/2000/svg"];
|
|
||||||
[element addAttribute:att];
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSString*)SVGPathStringForBezierPath:(NSBezierPath*)path
|
|
||||||
{
|
|
||||||
NSMutableString* str = [[[NSMutableString alloc] init] autorelease];
|
|
||||||
for (NSInteger i = 0; i < path.elementCount; i++) {
|
|
||||||
NSBezierPathElement element = [path elementAtIndex:i];
|
|
||||||
switch (element) {
|
|
||||||
// move
|
|
||||||
case NSMoveToBezierPathElement: {
|
|
||||||
NSPoint points[1];
|
|
||||||
[path elementAtIndex:i associatedPoints:points];
|
|
||||||
[str appendFormat:@"M%f %f", points[0].x, points[0].y];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// line
|
|
||||||
case NSLineToBezierPathElement: {
|
|
||||||
NSPoint points[1];
|
|
||||||
[path elementAtIndex:i associatedPoints:points];
|
|
||||||
[str appendFormat:@"L%f %f", points[0].x, points[0].y];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// curve
|
|
||||||
case NSCurveToBezierPathElement: {
|
|
||||||
NSPoint points[3];
|
|
||||||
[path elementAtIndex:i associatedPoints:points];
|
|
||||||
[str appendFormat:@"C%f %f %f %f %f %f", points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// close
|
|
||||||
case NSClosePathBezierPathElement: {
|
|
||||||
[str appendFormat:@"Z"];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -7,8 +7,15 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <IJSVG/IJSVGUtils.h>
|
||||||
|
#import <IJSVG/IJSVGColorType.h>
|
||||||
|
|
||||||
@class IJSVG;
|
@class IJSVG;
|
||||||
|
@class IJSVGExporter;
|
||||||
|
@class IJSVGLayer;
|
||||||
|
@class IJSVGNode;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
typedef void (^IJSVGCGPathHandler)(const CGPathElement* pathElement);
|
typedef void (^IJSVGCGPathHandler)(const CGPathElement* pathElement);
|
||||||
typedef void (^IJSVGPathElementEnumerationBlock)(const CGPathElement* pathElement, CGPoint currentPoint);
|
typedef void (^IJSVGPathElementEnumerationBlock)(const CGPathElement* pathElement, CGPoint currentPoint);
|
||||||
@@ -33,12 +40,43 @@ typedef NS_OPTIONS(NSInteger, IJSVGExporterOptions) {
|
|||||||
IJSVGExporterOptionColorAllowRRGGBBAA = 1 << 14,
|
IJSVGExporterOptionColorAllowRRGGBBAA = 1 << 14,
|
||||||
IJSVGExporterOptionRemoveComments = 1 << 15,
|
IJSVGExporterOptionRemoveComments = 1 << 15,
|
||||||
IJSVGExporterOptionCenterWithinViewBox = 1 << 16,
|
IJSVGExporterOptionCenterWithinViewBox = 1 << 16,
|
||||||
IJSVGExporterOptionAll = IJSVGExporterOptionRemoveUselessDef | IJSVGExporterOptionRemoveUselessGroups | IJSVGExporterOptionCreateUseForPaths | IJSVGExporterOptionMoveAttributesToGroup | IJSVGExporterOptionSortAttributes | IJSVGExporterOptionCollapseGroups | IJSVGExporterOptionCleanupPaths | IJSVGExporterOptionRemoveHiddenElements | IJSVGExporterOptionScaleToSizeIfNecessary | IJSVGExporterOptionCompressOutput | IJSVGExporterOptionCollapseGradients | IJSVGExporterOptionRemoveWidthHeightAttributes | IJSVGExporterOptionColorAllowRRGGBBAA | IJSVGExporterOptionRemoveComments | IJSVGExporterOptionCenterWithinViewBox
|
IJSVGExporterOptionRemoveXMLDeclaration = 1 << 17,
|
||||||
|
IJSVGExporterOptionConvertArcs = 1 << 18,
|
||||||
|
IJSVGExporterOptionConvertShapesToPaths = 1 << 19,
|
||||||
|
IJSVGExporterOptionRoundTransforms = 1 << 20,
|
||||||
|
IJSVGExporterOptionRemoveDefaultValues = 1 << 21,
|
||||||
|
IJSVGExporterOptionAll = IJSVGExporterOptionRemoveUselessDef | IJSVGExporterOptionRemoveUselessGroups |
|
||||||
|
IJSVGExporterOptionCreateUseForPaths | IJSVGExporterOptionMoveAttributesToGroup |
|
||||||
|
IJSVGExporterOptionSortAttributes | IJSVGExporterOptionCollapseGroups |
|
||||||
|
IJSVGExporterOptionCleanupPaths | IJSVGExporterOptionRemoveHiddenElements |
|
||||||
|
IJSVGExporterOptionScaleToSizeIfNecessary | IJSVGExporterOptionCompressOutput |
|
||||||
|
IJSVGExporterOptionCollapseGradients | IJSVGExporterOptionRemoveWidthHeightAttributes |
|
||||||
|
IJSVGExporterOptionColorAllowRRGGBBAA | IJSVGExporterOptionRemoveComments |
|
||||||
|
IJSVGExporterOptionCenterWithinViewBox | IJSVGExporterOptionRemoveXMLDeclaration |
|
||||||
|
IJSVGExporterOptionConvertArcs | IJSVGExporterOptionConvertShapesToPaths |
|
||||||
|
IJSVGExporterOptionRoundTransforms | IJSVGExporterOptionRemoveDefaultValues
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOL IJSVGExporterHasOption(IJSVGExporterOptions options, NSInteger option);
|
BOOL IJSVGExporterHasOption(IJSVGExporterOptions options, NSInteger option);
|
||||||
void IJSVGEnumerateCGPathElements(CGPathRef path, IJSVGPathElementEnumerationBlock enumBlock);
|
void IJSVGEnumerateCGPathElements(CGPathRef path, IJSVGPathElementEnumerationBlock enumBlock);
|
||||||
const NSArray* IJSVGShortCharacterArray(void);
|
const NSArray<NSString*>* IJSVGShortCharacterArray(void);
|
||||||
|
const NSDictionary<NSString*, NSString*>* IJSVGDefaultAttributes(void);
|
||||||
|
|
||||||
|
|
||||||
|
@protocol IJSVGExporterDelegate <NSObject>
|
||||||
|
|
||||||
|
@optional
|
||||||
|
- (NSString* _Nullable)svgExporter:(IJSVGExporter*)exporter
|
||||||
|
identifierForElement:(NSXMLElement* _Nullable)element
|
||||||
|
type:(IJSVGNodeType)type
|
||||||
|
defaultID:(NSString* (^)(void))defaultID;
|
||||||
|
- (NSString* _Nullable)svgExporter:(IJSVGExporter*)exporter
|
||||||
|
stringForColor:(NSColor*)color
|
||||||
|
flags:(IJSVGColorTypeFlags)flag
|
||||||
|
options:(IJSVGColorStringOptions)options;
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface IJSVGExporter : NSObject {
|
@interface IJSVGExporter : NSObject {
|
||||||
|
|
||||||
@@ -50,15 +88,31 @@ const NSArray* IJSVGShortCharacterArray(void);
|
|||||||
NSXMLElement* _defElement;
|
NSXMLElement* _defElement;
|
||||||
NSInteger _idCount;
|
NSInteger _idCount;
|
||||||
NSInteger _shortIdCount;
|
NSInteger _shortIdCount;
|
||||||
|
BOOL _appliedXLink;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned int identifierForElement: 1;
|
||||||
|
unsigned int stringForColor: 1;
|
||||||
|
} _respondsTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString* title;
|
@property (nonatomic, assign) id<IJSVGExporterDelegate> delegate;
|
||||||
@property (nonatomic, copy) NSString* description;
|
@property (nonatomic, assign) IJSVGFloatingPointOptions floatingPointOptions;
|
||||||
|
@property (nonatomic, copy, nullable) NSString* title;
|
||||||
|
@property (nonatomic, copy, nullable) NSString* desc;
|
||||||
|
|
||||||
- (id)initWithSVG:(IJSVG*)svg
|
- (id)initWithSVG:(IJSVG*)svg
|
||||||
size:(CGSize)size
|
size:(CGSize)size
|
||||||
options:(IJSVGExporterOptions)options;
|
options:(IJSVGExporterOptions)options;
|
||||||
|
- (id)initWithSVG:(IJSVG*)svg
|
||||||
|
size:(CGSize)size
|
||||||
|
options:(IJSVGExporterOptions)options
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
|
||||||
- (NSString*)SVGString;
|
- (NSString*)SVGString;
|
||||||
- (NSData*)SVGData;
|
- (NSData*)SVGData;
|
||||||
|
- (IJSVG*)SVG:(NSError**)error;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -15,30 +15,53 @@ typedef struct {
|
|||||||
NSArray<NSString*>* params;
|
NSArray<NSString*>* params;
|
||||||
} IJSVGExporterPathInstructionCommand;
|
} IJSVGExporterPathInstructionCommand;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CGPoint center;
|
||||||
|
CGFloat radius;
|
||||||
|
} IJSVGExporterPathInstructionCircle;
|
||||||
|
|
||||||
@interface IJSVGExporterPathInstruction : NSObject {
|
@interface IJSVGExporterPathInstruction : NSObject {
|
||||||
|
|
||||||
@private
|
@private
|
||||||
NSInteger _dataCount;
|
NSInteger _dataCount;
|
||||||
char _instruction;
|
|
||||||
CGFloat* _data;
|
CGFloat* _data;
|
||||||
|
CGFloat* _base;
|
||||||
|
CGFloat* _coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, assign) char instruction;
|
||||||
|
|
||||||
|
void IJSVGExporterPathInstructionRoundData(CGFloat* data, NSInteger length, IJSVGFloatingPointOptions options);
|
||||||
|
CGFloat IJSVGExporterPathFloatToFixed(CGFloat number, int precision);
|
||||||
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command);
|
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command);
|
||||||
void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand* _Nullable command);
|
void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand* _Nullable command);
|
||||||
|
|
||||||
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path;
|
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
|
||||||
- (id)initWithInstruction:(char)instruction
|
- (id)initWithInstruction:(char)instruction
|
||||||
dataCount:(NSInteger)floatCount;
|
dataCount:(NSInteger)floatCount;
|
||||||
|
|
||||||
- (void)setInstruction:(char)newInstruction;
|
|
||||||
- (char)instruction;
|
|
||||||
- (CGFloat*)data;
|
- (CGFloat*)data;
|
||||||
- (NSInteger)dataLength;
|
- (NSInteger)dataLength;
|
||||||
|
|
||||||
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions;
|
+ (NSArray<IJSVGExporterPathInstruction*>*)convertInstructionsCurves:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions;
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets;
|
+ (void)convertInstructionsToMixedAbsoluteRelative:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
+ (void)convertInstructionsDataToRounded:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
static NSInteger const kIJSVGExporterPathInstructionFloatPrecision = 3;
|
||||||
|
static CGFloat const kIJSVGExporterPathInstructionErrorThreshold = 1e-2;
|
||||||
|
|
||||||
|
#define IJ_SVG_EXPORT_ROUND(value) IJSVGExporterPathFloatToFixed(value, kIJSVGExporterPathInstructionFloatPrecision)
|
||||||
|
|||||||
@@ -9,13 +9,22 @@
|
|||||||
#import "IJSVGExporter.h"
|
#import "IJSVGExporter.h"
|
||||||
#import "IJSVGExporterPathInstruction.h"
|
#import "IJSVGExporterPathInstruction.h"
|
||||||
#import "IJSVGUtils.h"
|
#import "IJSVGUtils.h"
|
||||||
|
#import <math.h>
|
||||||
|
|
||||||
@implementation IJSVGExporterPathInstruction
|
@implementation IJSVGExporterPathInstruction
|
||||||
|
|
||||||
|
@synthesize instruction = _instruction;
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
if (_data != NULL) {
|
if (_data != NULL) {
|
||||||
free(_data);
|
(void)free(_data), _data = NULL;
|
||||||
|
}
|
||||||
|
if (_base != NULL) {
|
||||||
|
(void)free(_base), _base = NULL;
|
||||||
|
}
|
||||||
|
if (_coords != NULL) {
|
||||||
|
(void)free(_coords), _coords = NULL;
|
||||||
}
|
}
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
@@ -28,8 +37,13 @@
|
|||||||
|
|
||||||
// only allocate if not zero
|
// only allocate if not zero
|
||||||
if (floatCount != 0) {
|
if (floatCount != 0) {
|
||||||
|
_dataCount = floatCount;
|
||||||
_data = (CGFloat*)calloc(sizeof(CGFloat), floatCount);
|
_data = (CGFloat*)calloc(sizeof(CGFloat), floatCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup base and coords
|
||||||
|
_base = (CGFloat*)malloc(sizeof(CGFloat) * 2);
|
||||||
|
_coords = (CGFloat*)malloc(sizeof(CGFloat) * 2);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -39,21 +53,21 @@
|
|||||||
return _dataCount;
|
return _dataCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setInstruction:(char)newInstruction
|
|
||||||
{
|
|
||||||
_instruction = newInstruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (char)instruction
|
|
||||||
{
|
|
||||||
return _instruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGFloat*)data
|
- (CGFloat*)data
|
||||||
{
|
{
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CGFloat*)base
|
||||||
|
{
|
||||||
|
return _base;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat*)coords
|
||||||
|
{
|
||||||
|
return _coords;
|
||||||
|
}
|
||||||
|
|
||||||
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command)
|
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command)
|
||||||
{
|
{
|
||||||
IJSVGExporterPathInstructionCommand* copy = NULL;
|
IJSVGExporterPathInstructionCommand* copy = NULL;
|
||||||
@@ -71,10 +85,10 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets
|
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
{
|
{
|
||||||
IJSVGExporterPathInstructionCommand* lastCommand = NULL;
|
IJSVGExporterPathInstructionCommand* lastCommand = NULL;
|
||||||
NSMutableString* string = [[[NSMutableString alloc] init] autorelease];
|
NSMutableString* string = [[[NSMutableString alloc] init] autorelease];
|
||||||
char* lastCommandChars = NULL;
|
|
||||||
for (NSValue* value in instructionSets) {
|
for (NSValue* value in instructionSets) {
|
||||||
// read back the bytes
|
// read back the bytes
|
||||||
IJSVGExporterPathInstructionCommand command;
|
IJSVGExporterPathInstructionCommand command;
|
||||||
@@ -89,31 +103,9 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
[string appendString:@" "];
|
[string appendString:@" "];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSInteger index = 0;
|
// compresses the floats
|
||||||
for (NSString* dataString in command.params) {
|
NSString* compressedFloats = IJSVGCompressFloatParameterArray(command.params);
|
||||||
const char* chars = dataString.UTF8String;
|
[string appendString:compressedFloats];
|
||||||
|
|
||||||
// work out if the command is signed and or decimal
|
|
||||||
BOOL isSigned = chars[0] == '-';
|
|
||||||
BOOL isDecimal = (isSigned == NO && chars[0] == '.') || (isSigned == YES && chars[1] == '.');
|
|
||||||
|
|
||||||
// we also need to know if the previous command was a decimal or not
|
|
||||||
BOOL lastWasDecimal = NO;
|
|
||||||
if (lastCommandChars != NULL) {
|
|
||||||
lastWasDecimal = strchr(lastCommandChars, '.') != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we only need a space if the current command is not signed
|
|
||||||
// a decimal and the previous command was decimal too
|
|
||||||
if (index++ == 0 || isSigned || (isDecimal == YES && lastWasDecimal == YES)) {
|
|
||||||
[string appendString:dataString];
|
|
||||||
} else {
|
|
||||||
[string appendFormat:@" %@", dataString];
|
|
||||||
}
|
|
||||||
|
|
||||||
// store last command chars
|
|
||||||
lastCommandChars = (char*)chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store last command
|
// store last command
|
||||||
IJSVGExporterPathInstructionCommandFree(lastCommand);
|
IJSVGExporterPathInstructionCommandFree(lastCommand);
|
||||||
@@ -125,6 +117,7 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
{
|
{
|
||||||
NSMutableArray* pathInstructions = [[[NSMutableArray alloc] init] autorelease];
|
NSMutableArray* pathInstructions = [[[NSMutableArray alloc] init] autorelease];
|
||||||
for (IJSVGExporterPathInstruction* instruction in instructions) {
|
for (IJSVGExporterPathInstruction* instruction in instructions) {
|
||||||
@@ -132,11 +125,12 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
const char lowerInstruction = tolower(instruction.instruction);
|
const char lowerInstruction = tolower(instruction.instruction);
|
||||||
NSArray<NSString*>* set = nil;
|
NSArray<NSString*>* set = nil;
|
||||||
switch (lowerInstruction) {
|
switch (lowerInstruction) {
|
||||||
|
case 't':
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'l': {
|
case 'l': {
|
||||||
set = @[
|
set = @[
|
||||||
IJSVGShortFloatString(data[0]),
|
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[1])
|
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions)
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -144,29 +138,43 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
case 'v':
|
case 'v':
|
||||||
case 'h': {
|
case 'h': {
|
||||||
set = @[
|
set = @[
|
||||||
IJSVGShortFloatString(data[0])
|
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions)
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'c': {
|
case 'c': {
|
||||||
set = @[
|
set = @[
|
||||||
IJSVGShortFloatString(data[0]),
|
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[1]),
|
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[2]),
|
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[3]),
|
IJSVGShortFloatStringWithOptions(data[3], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[4]),
|
IJSVGShortFloatStringWithOptions(data[4], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[5])
|
IJSVGShortFloatStringWithOptions(data[5], floatingPointOptions)
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 's':
|
||||||
case 'q': {
|
case 'q': {
|
||||||
set = @[
|
set = @[
|
||||||
IJSVGShortFloatString(data[0]),
|
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[1]),
|
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[2]),
|
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
|
||||||
IJSVGShortFloatString(data[3])
|
IJSVGShortFloatStringWithOptions(data[3], floatingPointOptions)
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'a': {
|
||||||
|
set = @[
|
||||||
|
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(data[3], floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(data[4], floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(data[5], floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(data[6], floatingPointOptions),
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -187,13 +195,201 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
objCType:@encode(IJSVGExporterPathInstructionCommand)];
|
objCType:@encode(IJSVGExporterPathInstructionCommand)];
|
||||||
[pathInstructions addObject:value];
|
[pathInstructions addObject:value];
|
||||||
}
|
}
|
||||||
return [self pathStringWithInstructionSet:pathInstructions];
|
return [self pathStringWithInstructionSet:pathInstructions
|
||||||
|
floatingPointOptions:floatingPointOptions];
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat IJSVGExporterPathFloatToFixed(CGFloat number, int precision)
|
||||||
|
{
|
||||||
|
return floorf(pow(10, precision) * number) / pow(10, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IJSVGExporterPathInstructionRoundData(CGFloat* data, NSInteger length,
|
||||||
|
IJSVGFloatingPointOptions options)
|
||||||
|
{
|
||||||
|
for (NSInteger i = length; i-- > 0;) {
|
||||||
|
CGFloat d = data[i];
|
||||||
|
CGFloat proposed = IJSVGExporterPathFloatToFixed(d, options.precision);
|
||||||
|
if (proposed != d) {
|
||||||
|
CGFloat rounded = +IJSVGExporterPathFloatToFixed(d, options.precision - 1);
|
||||||
|
data[i] = IJSVGExporterPathFloatToFixed(+fabs(rounded - d), options.precision + 1)
|
||||||
|
>= kIJSVGExporterPathInstructionErrorThreshold
|
||||||
|
? +IJSVGExporterPathFloatToFixed(d, options.precision)
|
||||||
|
: rounded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)convertInstructionsToRoundRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
CGFloat relSubPoint[2] = { 0.f, 0.f };
|
||||||
|
for (IJSVGExporterPathInstruction* instruction in instructions) {
|
||||||
|
char instructionChar = instruction.instruction;
|
||||||
|
NSInteger length = instruction.dataLength;
|
||||||
|
CGFloat* data = instruction.data;
|
||||||
|
if (strchr("mltqsc", instructionChar) != NULL) {
|
||||||
|
for (NSInteger i = length; i--;) {
|
||||||
|
data[i] += instruction.base[i % 2] - relSubPoint[i % 2];
|
||||||
|
}
|
||||||
|
} else if (instructionChar == 'h') {
|
||||||
|
data[0] += instruction.base[0] - relSubPoint[0];
|
||||||
|
} else if (instructionChar == 'v') {
|
||||||
|
data[0] += instruction.base[1] - relSubPoint[1];
|
||||||
|
} else if (instructionChar == 'a') {
|
||||||
|
data[5] += instruction.base[0] - relSubPoint[0];
|
||||||
|
data[5] += instruction.base[1] - relSubPoint[1];
|
||||||
|
}
|
||||||
|
IJSVGExporterPathInstructionRoundData(data, length, floatingPointOptions);
|
||||||
|
if (instructionChar == 'h') {
|
||||||
|
relSubPoint[0] += data[0];
|
||||||
|
} else if (instructionChar == 'v') {
|
||||||
|
relSubPoint[1] += data[0];
|
||||||
|
} else {
|
||||||
|
relSubPoint[0] += data[length - 2];
|
||||||
|
relSubPoint[1] += data[length - 1];
|
||||||
|
}
|
||||||
|
IJSVGExporterPathInstructionRoundData(relSubPoint, 2, floatingPointOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)convertInstructionsToMixedAbsoluteRelative:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
IJSVGExporterPathInstruction* prevInstruction = nil;
|
||||||
|
for (IJSVGExporterPathInstruction* instruction in instructions) {
|
||||||
|
if (prevInstruction == nil || instruction.dataLength == 0) {
|
||||||
|
prevInstruction = instruction;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char instructionChar = instruction.instruction;
|
||||||
|
CGFloat* data = instruction.data;
|
||||||
|
NSInteger length = instruction.dataLength;
|
||||||
|
CGFloat* adata = (CGFloat*)malloc(sizeof(CGFloat) * length);
|
||||||
|
memcpy(adata, data, sizeof(CGFloat) * length);
|
||||||
|
|
||||||
|
if (strchr("mltqsc", instructionChar) != NULL) {
|
||||||
|
for (NSInteger i = length; i--;) {
|
||||||
|
adata[i] += instruction.base[i % 2];
|
||||||
|
}
|
||||||
|
} else if (instructionChar == 'h') {
|
||||||
|
adata[0] += instruction.base[0];
|
||||||
|
} else if (instructionChar == 'v') {
|
||||||
|
adata[0] += instruction.base[1];
|
||||||
|
} else if (instructionChar == 'a') {
|
||||||
|
adata[5] += instruction.base[0];
|
||||||
|
adata[6] += instruction.base[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSVGExporterPathInstructionRoundData(adata, length, floatingPointOptions);
|
||||||
|
|
||||||
|
IJSVGExporterPathInstruction* ainstruction = nil;
|
||||||
|
ainstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:instructionChar
|
||||||
|
dataCount:length] autorelease];
|
||||||
|
memcpy(ainstruction.data, adata, sizeof(CGFloat) * length);
|
||||||
|
|
||||||
|
// run these through our default string runner
|
||||||
|
// to compare the outputs
|
||||||
|
NSString* orig = [self pathStringFromInstructions:@[ instruction ]
|
||||||
|
floatingPointOptions:floatingPointOptions];
|
||||||
|
NSString* comp = [self pathStringFromInstructions:@[ ainstruction ]
|
||||||
|
floatingPointOptions:floatingPointOptions];
|
||||||
|
|
||||||
|
if (comp.length < orig.length && !(instructionChar == prevInstruction.instruction && prevInstruction.instruction > 96 && comp.length == orig.length - 1 && data[0] < 0.f && fmod(prevInstruction.data[prevInstruction.dataLength - 1], 1) != 0.f)) {
|
||||||
|
instruction.instruction = toupper(instructionChar);
|
||||||
|
memcpy(data, adata, sizeof(CGFloat) * length);
|
||||||
|
}
|
||||||
|
(void)free(adata), adata = NULL;
|
||||||
|
prevInstruction = instruction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)convertInstructionsDataToRounded:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
for (IJSVGExporterPathInstruction* instruction in instructions) {
|
||||||
|
CGFloat* data = instruction.data;
|
||||||
|
IJSVGExporterPathInstructionRoundData(data, instruction.dataLength,
|
||||||
|
floatingPointOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<IJSVGExporterPathInstruction*>*)convertInstructionsCurves:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
NSMutableArray<IJSVGExporterPathInstruction*>* nInstructions = nil;
|
||||||
|
nInstructions = [[[NSMutableArray alloc] initWithCapacity:instructions.count] autorelease];
|
||||||
|
IJSVGExporterPathInstruction* lastInstruction = nil;
|
||||||
|
for (IJSVGExporterPathInstruction* instruction in instructions) {
|
||||||
|
lastInstruction = nInstructions.lastObject;
|
||||||
|
if (lastInstruction == nil) {
|
||||||
|
[nInstructions addObject:instruction];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (instruction.instruction == 'c') {
|
||||||
|
if (lastInstruction.instruction == 'c' && instruction.data[0] == -(lastInstruction.data[2] - lastInstruction.data[4]) && instruction.data[1] == -(lastInstruction.data[3] - lastInstruction.data[5])) {
|
||||||
|
IJSVGExporterPathInstruction* nInstruction = nil;
|
||||||
|
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'s'
|
||||||
|
dataCount:4] autorelease];
|
||||||
|
nInstruction.data[0] = instruction.data[2];
|
||||||
|
nInstruction.data[1] = instruction.data[3];
|
||||||
|
nInstruction.data[2] = instruction.data[4];
|
||||||
|
nInstruction.data[3] = instruction.data[5];
|
||||||
|
[nInstructions addObject:nInstruction];
|
||||||
|
continue;
|
||||||
|
} else if (lastInstruction.instruction == 's' && instruction.data[0] == -(lastInstruction.data[0] - lastInstruction.data[2]) && instruction.data[1] == -(lastInstruction.data[1] - lastInstruction.data[3])) {
|
||||||
|
IJSVGExporterPathInstruction* nInstruction = nil;
|
||||||
|
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'s'
|
||||||
|
dataCount:4] autorelease];
|
||||||
|
nInstruction.data[0] = instruction.data[2];
|
||||||
|
nInstruction.data[1] = instruction.data[3];
|
||||||
|
nInstruction.data[2] = instruction.data[4];
|
||||||
|
nInstruction.data[3] = instruction.data[5];
|
||||||
|
[nInstructions addObject:nInstruction];
|
||||||
|
continue;
|
||||||
|
} else if (lastInstruction.instruction != 'c' && lastInstruction.instruction != 's' && instruction.data[0] == 0.f && instruction.data[1] == 0.f) {
|
||||||
|
IJSVGExporterPathInstruction* nInstruction = nil;
|
||||||
|
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'s'
|
||||||
|
dataCount:4] autorelease];
|
||||||
|
nInstruction.data[0] = instruction.data[2];
|
||||||
|
nInstruction.data[1] = instruction.data[3];
|
||||||
|
nInstruction.data[2] = instruction.data[4];
|
||||||
|
nInstruction.data[3] = instruction.data[5];
|
||||||
|
[nInstructions addObject:nInstruction];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (instruction.instruction == 'q') {
|
||||||
|
if (lastInstruction.instruction == 'q' && instruction.data[0] == (lastInstruction.data[2] - lastInstruction.data[0]) && instruction.data[1] == (lastInstruction.data[3] - lastInstruction.data[1])) {
|
||||||
|
IJSVGExporterPathInstruction* nInstruction = nil;
|
||||||
|
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'t'
|
||||||
|
dataCount:2] autorelease];
|
||||||
|
nInstruction.data[0] = instruction.data[2];
|
||||||
|
nInstruction.data[1] = instruction.data[3];
|
||||||
|
[nInstructions addObject:nInstruction];
|
||||||
|
continue;
|
||||||
|
} else if (lastInstruction.instruction == 't' && instruction.data[2] == lastInstruction.data[0] && instruction.data[3] == lastInstruction.data[1]) {
|
||||||
|
IJSVGExporterPathInstruction* nInstruction = nil;
|
||||||
|
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'t'
|
||||||
|
dataCount:2] autorelease];
|
||||||
|
nInstruction.data[0] = instruction.data[2];
|
||||||
|
nInstruction.data[1] = instruction.data[3];
|
||||||
|
[nInstructions addObject:nInstruction];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[nInstructions addObject:instruction];
|
||||||
|
}
|
||||||
|
return nInstructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
{
|
{
|
||||||
CGFloat point[2] = { 0, 0 };
|
CGFloat point[2] = { 0, 0 };
|
||||||
CGFloat subpathPoint[2] = { 0, 0 };
|
CGFloat subpathPoint[2] = { 0, 0 };
|
||||||
|
IJSVGExporterPathInstruction* baseInstruction = nil;
|
||||||
|
IJSVGExporterPathInstruction* prevInstruction = nil;
|
||||||
|
|
||||||
NSInteger index = 0;
|
NSInteger index = 0;
|
||||||
for (IJSVGExporterPathInstruction* anInstruction in instructions) {
|
for (IJSVGExporterPathInstruction* anInstruction in instructions) {
|
||||||
@@ -212,6 +408,8 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
if (instruction == 'm') {
|
if (instruction == 'm') {
|
||||||
subpathPoint[0] = point[0];
|
subpathPoint[0] = point[0];
|
||||||
subpathPoint[1] = point[1];
|
subpathPoint[1] = point[1];
|
||||||
|
|
||||||
|
baseInstruction = anInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (instruction == 'h') {
|
} else if (instruction == 'h') {
|
||||||
@@ -232,8 +430,8 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
subpathPoint[0] = point[0] += data[0];
|
subpathPoint[0] = point[0] += data[0];
|
||||||
subpathPoint[1] = point[1] += data[1];
|
subpathPoint[1] = point[1] += data[1];
|
||||||
|
|
||||||
|
baseInstruction = anInstruction;
|
||||||
} else if (instruction == 'L' || instruction == 'T') {
|
} else if (instruction == 'L' || instruction == 'T') {
|
||||||
|
|
||||||
instruction = tolower(instruction);
|
instruction = tolower(instruction);
|
||||||
|
|
||||||
data[0] -= point[0];
|
data[0] -= point[0];
|
||||||
@@ -241,9 +439,7 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
|
|
||||||
point[0] += data[0];
|
point[0] += data[0];
|
||||||
point[1] += data[1];
|
point[1] += data[1];
|
||||||
|
|
||||||
} else if (instruction == 'C') {
|
} else if (instruction == 'C') {
|
||||||
|
|
||||||
instruction = 'c';
|
instruction = 'c';
|
||||||
|
|
||||||
data[0] -= point[0];
|
data[0] -= point[0];
|
||||||
@@ -255,9 +451,7 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
|
|
||||||
point[0] += data[4];
|
point[0] += data[4];
|
||||||
point[1] += data[5];
|
point[1] += data[5];
|
||||||
|
|
||||||
} else if (instruction == 'S' || instruction == 'Q') {
|
} else if (instruction == 'S' || instruction == 'Q') {
|
||||||
|
|
||||||
instruction = tolower(instruction);
|
instruction = tolower(instruction);
|
||||||
|
|
||||||
data[0] -= point[0];
|
data[0] -= point[0];
|
||||||
@@ -267,9 +461,7 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
|
|
||||||
point[0] += data[2];
|
point[0] += data[2];
|
||||||
point[1] += data[3];
|
point[1] += data[3];
|
||||||
|
|
||||||
} else if (instruction == 'A') {
|
} else if (instruction == 'A') {
|
||||||
|
|
||||||
instruction = 'a';
|
instruction = 'a';
|
||||||
|
|
||||||
data[5] -= point[0];
|
data[5] -= point[0];
|
||||||
@@ -277,38 +469,51 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
|
|
||||||
point[0] += data[5];
|
point[0] += data[5];
|
||||||
point[1] += data[6];
|
point[1] += data[6];
|
||||||
|
|
||||||
} else if (instruction == 'H') {
|
} else if (instruction == 'H') {
|
||||||
|
|
||||||
instruction = 'h';
|
instruction = 'h';
|
||||||
|
|
||||||
data[0] -= point[0];
|
data[0] -= point[0];
|
||||||
|
|
||||||
point[0] += data[0];
|
point[0] += data[0];
|
||||||
|
|
||||||
} else if (instruction == 'V') {
|
} else if (instruction == 'V') {
|
||||||
|
|
||||||
instruction = 'v';
|
instruction = 'v';
|
||||||
|
|
||||||
data[0] -= point[1];
|
data[0] -= point[1];
|
||||||
|
|
||||||
point[1] += data[0];
|
point[1] += data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the instruction
|
// reset the instruction
|
||||||
[anInstruction setInstruction:instruction];
|
anInstruction.instruction = instruction;
|
||||||
|
CGFloat* coords = anInstruction.coords;
|
||||||
|
coords[0] = point[0];
|
||||||
|
coords[1] = point[1];
|
||||||
|
|
||||||
} else if (instruction == 'Z' || instruction == 'z') {
|
} else if (instruction == 'Z' || instruction == 'z') {
|
||||||
|
if (baseInstruction != nil) {
|
||||||
|
CGFloat* coords = anInstruction.coords;
|
||||||
|
coords[0] = baseInstruction.coords[0];
|
||||||
|
coords[1] = baseInstruction.coords[1];
|
||||||
|
}
|
||||||
point[0] = subpathPoint[0];
|
point[0] = subpathPoint[0];
|
||||||
point[1] = subpathPoint[1];
|
point[1] = subpathPoint[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGFloat* base = anInstruction.base;
|
||||||
|
if (prevInstruction != nil) {
|
||||||
|
base[0] = prevInstruction.coords[0];
|
||||||
|
base[1] = prevInstruction.coords[1];
|
||||||
|
} else {
|
||||||
|
base[0] = 0.f;
|
||||||
|
base[1] = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
// increment index
|
// increment index
|
||||||
|
prevInstruction = anInstruction;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
|
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
{
|
{
|
||||||
|
|
||||||
// keep track of the current point
|
// keep track of the current point
|
||||||
@@ -378,6 +583,7 @@ void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand
|
|||||||
CGPoint controlPoint1 = pathElement->points[0];
|
CGPoint controlPoint1 = pathElement->points[0];
|
||||||
CGPoint controlPoint2 = pathElement->points[1];
|
CGPoint controlPoint2 = pathElement->points[1];
|
||||||
CGPoint point = pathElement->points[2];
|
CGPoint point = pathElement->points[2];
|
||||||
|
|
||||||
currentPoint = point;
|
currentPoint = point;
|
||||||
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'C'
|
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'C'
|
||||||
dataCount:6] autorelease];
|
dataCount:6] autorelease];
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGGradient.h"
|
#import <IJSVG/IJSVGGradient.h>
|
||||||
#import "IJSVGLayer.h"
|
#import <IJSVG/IJSVGLayer.h>
|
||||||
#import "IJSVGPath.h"
|
#import <IJSVG/IJSVGPath.h>
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
@interface IJSVGGradientLayer : IJSVGLayer {
|
@interface IJSVGGradientLayer : IJSVGLayer {
|
||||||
|
|||||||
@@ -10,14 +10,9 @@
|
|||||||
|
|
||||||
@implementation IJSVGGradientLayer
|
@implementation IJSVGGradientLayer
|
||||||
|
|
||||||
@synthesize viewBox;
|
|
||||||
@synthesize gradient;
|
|
||||||
@synthesize absoluteTransform;
|
|
||||||
@synthesize objectRect;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([gradient release]), gradient = nil;
|
(void)([_gradient release]), _gradient = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,17 +27,17 @@
|
|||||||
|
|
||||||
- (void)setGradient:(IJSVGGradient*)newGradient
|
- (void)setGradient:(IJSVGGradient*)newGradient
|
||||||
{
|
{
|
||||||
if (gradient != nil) {
|
if (_gradient != nil) {
|
||||||
(void)([gradient release]), gradient = nil;
|
(void)([_gradient release]), _gradient = nil;
|
||||||
}
|
}
|
||||||
gradient = [newGradient retain];
|
_gradient = [newGradient retain];
|
||||||
|
|
||||||
// lets check its alpha properties on the colors
|
// lets check its alpha properties on the colors
|
||||||
BOOL hasAlphaChannel = NO;
|
BOOL hasAlphaChannel = NO;
|
||||||
NSInteger stops = gradient.gradient.numberOfColorStops;
|
NSInteger stops = _gradient.gradient.numberOfColorStops;
|
||||||
for (NSInteger i = 0; i < stops; i++) {
|
for (NSInteger i = 0; i < stops; i++) {
|
||||||
NSColor* color = nil;
|
NSColor* color = nil;
|
||||||
[gradient.gradient getColor:&color
|
[_gradient.gradient getColor:&color
|
||||||
location:NULL
|
location:NULL
|
||||||
atIndex:i];
|
atIndex:i];
|
||||||
if (color.alphaComponent != 1.f) {
|
if (color.alphaComponent != 1.f) {
|
||||||
@@ -89,12 +84,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw the gradient
|
// draw the gradient
|
||||||
CGAffineTransform trans = CGAffineTransformMakeTranslation(-CGRectGetMinX(objectRect),
|
CGAffineTransform trans = CGAffineTransformMakeTranslation(-CGRectGetMinX(_objectRect),
|
||||||
-CGRectGetMinY(objectRect));
|
-CGRectGetMinY(_objectRect));
|
||||||
CGAffineTransform transform = CGAffineTransformConcat(absoluteTransform, trans);
|
CGAffineTransform transform = CGAffineTransformConcat(_absoluteTransform, trans);
|
||||||
CGContextSaveGState(ctx);
|
CGContextSaveGState(ctx);
|
||||||
[self.gradient drawInContextRef:ctx
|
[self.gradient drawInContextRef:ctx
|
||||||
objectRect:objectRect
|
objectRect:_objectRect
|
||||||
absoluteTransform:transform
|
absoluteTransform:transform
|
||||||
viewPort:self.viewBox];
|
viewPort:self.viewBox];
|
||||||
CGContextRestoreGState(ctx);
|
CGContextRestoreGState(ctx);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGLayer.h"
|
#import <IJSVG/IJSVGLayer.h>
|
||||||
#import "IJSVGShapeLayer.h"
|
#import <IJSVG/IJSVGShapeLayer.h>
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
@interface IJSVGGroupLayer : IJSVGLayer
|
@interface IJSVGGroupLayer : IJSVGLayer
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGLayer.h"
|
#import <IJSVG/IJSVGLayer.h>
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGRendering.h"
|
#import <IJSVG/IJSVGRendering.h>
|
||||||
#import "IJSVGTransaction.h"
|
#import <IJSVG/IJSVGTransaction.h>
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
@class IJSVGShapeLayer;
|
@class IJSVGShapeLayer;
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
+ (NSArray*)deepestSublayersOfLayer:(CALayer*)layer;
|
+ (NSArray*)deepestSublayersOfLayer:(CALayer*)layer;
|
||||||
+ (void)recursivelyWalkLayer:(CALayer*)layer
|
+ (void)recursivelyWalkLayer:(CALayer*)layer
|
||||||
withBlock:(void (^)(CALayer* layer, BOOL isMask))block;
|
withBlock:(void (^)(CALayer* layer, BOOL isMask, BOOL* stop))block;
|
||||||
|
|
||||||
- (void)applySublayerMaskToContext:(CGContextRef)context
|
- (void)applySublayerMaskToContext:(CGContextRef)context
|
||||||
forSublayer:(IJSVGLayer*)sublayer
|
forSublayer:(IJSVGLayer*)sublayer
|
||||||
|
|||||||
@@ -13,19 +13,8 @@
|
|||||||
|
|
||||||
@implementation IJSVGLayer
|
@implementation IJSVGLayer
|
||||||
|
|
||||||
@synthesize gradientFillLayer;
|
|
||||||
@synthesize patternFillLayer;
|
|
||||||
@synthesize gradientStrokeLayer;
|
|
||||||
@synthesize patternStrokeLayer;
|
|
||||||
@synthesize strokeLayer;
|
|
||||||
@synthesize requiresBackingScaleHelp;
|
|
||||||
@synthesize backingScaleFactor;
|
|
||||||
@synthesize blendingMode;
|
|
||||||
@synthesize convertMasksToPaths;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
self.contents = nil;
|
|
||||||
(void)([_maskingLayer release]), _maskingLayer = nil;
|
(void)([_maskingLayer release]), _maskingLayer = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
@@ -45,14 +34,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (void)recursivelyWalkLayer:(CALayer*)layer
|
+ (void)recursivelyWalkLayer:(CALayer*)layer
|
||||||
withBlock:(void (^)(CALayer* layer, BOOL isMask))block
|
withBlock:(void (^)(CALayer* layer, BOOL isMask, BOOL* stop))block
|
||||||
{
|
{
|
||||||
// call for layer and mask if there is one
|
// call for layer and mask if there is one
|
||||||
block(layer, NO);
|
BOOL stop = NO;
|
||||||
|
block(layer, NO, &stop);
|
||||||
|
if(stop == YES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// do the mask too!
|
// do the mask too!
|
||||||
if (layer.mask != nil) {
|
if (layer.mask != nil) {
|
||||||
block(layer.mask, YES);
|
block(layer.mask, YES, &stop);
|
||||||
|
if(stop == YES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sublayers!!
|
// sublayers!!
|
||||||
@@ -64,10 +60,10 @@
|
|||||||
|
|
||||||
- (void)setBackingScaleFactor:(CGFloat)newFactor
|
- (void)setBackingScaleFactor:(CGFloat)newFactor
|
||||||
{
|
{
|
||||||
if (self.backingScaleFactor == newFactor) {
|
if (_backingScaleFactor == newFactor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backingScaleFactor = newFactor;
|
_backingScaleFactor = newFactor;
|
||||||
self.contentsScale = newFactor;
|
self.contentsScale = newFactor;
|
||||||
self.rasterizationScale = newFactor;
|
self.rasterizationScale = newFactor;
|
||||||
[self setNeedsDisplay];
|
[self setNeedsDisplay];
|
||||||
@@ -75,7 +71,7 @@
|
|||||||
|
|
||||||
- (void)_customRenderInContext:(CGContextRef)ctx
|
- (void)_customRenderInContext:(CGContextRef)ctx
|
||||||
{
|
{
|
||||||
if (self.convertMasksToPaths == YES && _maskingLayer != nil) {
|
if (_convertMasksToPaths == YES && _maskingLayer != nil) {
|
||||||
CGContextSaveGState(ctx);
|
CGContextSaveGState(ctx);
|
||||||
[self applySublayerMaskToContext:ctx
|
[self applySublayerMaskToContext:ctx
|
||||||
forSublayer:(IJSVGLayer*)self
|
forSublayer:(IJSVGLayer*)self
|
||||||
@@ -89,10 +85,10 @@
|
|||||||
|
|
||||||
- (void)setConvertMasksToPaths:(BOOL)flag
|
- (void)setConvertMasksToPaths:(BOOL)flag
|
||||||
{
|
{
|
||||||
if (convertMasksToPaths == flag) {
|
if (_convertMasksToPaths == flag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
convertMasksToPaths = flag;
|
_convertMasksToPaths = flag;
|
||||||
if (flag == YES) {
|
if (flag == YES) {
|
||||||
if (_maskingLayer != nil) {
|
if (_maskingLayer != nil) {
|
||||||
(void)([_maskingLayer release]), _maskingLayer = nil;
|
(void)([_maskingLayer release]), _maskingLayer = nil;
|
||||||
@@ -152,9 +148,9 @@
|
|||||||
|
|
||||||
- (void)renderInContext:(CGContextRef)ctx
|
- (void)renderInContext:(CGContextRef)ctx
|
||||||
{
|
{
|
||||||
if (self.blendingMode != kCGBlendModeNormal) {
|
if (_blendingMode != kCGBlendModeNormal) {
|
||||||
CGContextSaveGState(ctx);
|
CGContextSaveGState(ctx);
|
||||||
CGContextSetBlendMode(ctx, self.blendingMode);
|
CGContextSetBlendMode(ctx, _blendingMode);
|
||||||
[self _customRenderInContext:ctx];
|
[self _customRenderInContext:ctx];
|
||||||
CGContextRestoreGState(ctx);
|
CGContextRestoreGState(ctx);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -10,13 +10,10 @@
|
|||||||
|
|
||||||
@implementation IJSVGPatternLayer
|
@implementation IJSVGPatternLayer
|
||||||
|
|
||||||
@synthesize pattern;
|
|
||||||
@synthesize patternNode;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([pattern release]), pattern = nil;
|
(void)([_pattern release]), _pattern = nil;
|
||||||
(void)([patternNode release]), patternNode = nil;
|
(void)([_patternNode release]), _patternNode = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,8 +47,8 @@ void IJSVGPatternDrawingCallBack(void* info, CGContextRef ctx)
|
|||||||
CGRect rect = self.bounds;
|
CGRect rect = self.bounds;
|
||||||
CGPatternRef ref = CGPatternCreate((void*)self, self.bounds,
|
CGPatternRef ref = CGPatternCreate((void*)self, self.bounds,
|
||||||
CGAffineTransformIdentity,
|
CGAffineTransformIdentity,
|
||||||
roundf(rect.size.width * self.patternNode.width.value),
|
roundf(rect.size.width * _patternNode.width.value),
|
||||||
roundf(rect.size.height * self.patternNode.height.value),
|
roundf(rect.size.height * _patternNode.height.value),
|
||||||
kCGPatternTilingConstantSpacing,
|
kCGPatternTilingConstantSpacing,
|
||||||
true, &callbacks);
|
true, &callbacks);
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGLayer.h"
|
#import <IJSVG/IJSVGLayer.h>
|
||||||
#import "IJSVGUtils.h"
|
#import <IJSVG/IJSVGUtils.h>
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
@interface IJSVGShapeLayer : CAShapeLayer {
|
@interface IJSVGShapeLayer : CAShapeLayer {
|
||||||
|
|||||||
@@ -11,22 +11,8 @@
|
|||||||
|
|
||||||
@implementation IJSVGShapeLayer
|
@implementation IJSVGShapeLayer
|
||||||
|
|
||||||
@synthesize gradientFillLayer;
|
|
||||||
@synthesize patternFillLayer;
|
|
||||||
@synthesize gradientStrokeLayer;
|
|
||||||
@synthesize patternStrokeLayer;
|
|
||||||
@synthesize strokeLayer;
|
|
||||||
@synthesize requiresBackingScaleHelp;
|
|
||||||
@synthesize backingScaleFactor;
|
|
||||||
@synthesize blendingMode;
|
|
||||||
@synthesize convertMasksToPaths;
|
|
||||||
@synthesize originalPathOrigin;
|
|
||||||
@synthesize renderQuality;
|
|
||||||
@synthesize primitiveType;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
self.contents = nil;
|
|
||||||
(void)([_maskingLayer release]), _maskingLayer = nil;
|
(void)([_maskingLayer release]), _maskingLayer = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
@@ -36,7 +22,7 @@
|
|||||||
if (self.backingScaleFactor == newFactor) {
|
if (self.backingScaleFactor == newFactor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backingScaleFactor = newFactor;
|
_backingScaleFactor = newFactor;
|
||||||
self.contentsScale = newFactor;
|
self.contentsScale = newFactor;
|
||||||
self.rasterizationScale = newFactor;
|
self.rasterizationScale = newFactor;
|
||||||
[self setNeedsDisplay];
|
[self setNeedsDisplay];
|
||||||
@@ -58,10 +44,10 @@
|
|||||||
|
|
||||||
- (void)setConvertMasksToPaths:(BOOL)flag
|
- (void)setConvertMasksToPaths:(BOOL)flag
|
||||||
{
|
{
|
||||||
if (convertMasksToPaths == flag) {
|
if (_convertMasksToPaths == flag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
convertMasksToPaths = flag;
|
_convertMasksToPaths = flag;
|
||||||
if (flag == YES) {
|
if (flag == YES) {
|
||||||
if (_maskingLayer != nil) {
|
if (_maskingLayer != nil) {
|
||||||
(void)([_maskingLayer release]), _maskingLayer = nil;
|
(void)([_maskingLayer release]), _maskingLayer = nil;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGNode.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGDef : NSObject {
|
@interface IJSVGDef : NSObject {
|
||||||
|
|||||||
@@ -7,14 +7,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "IJSVGNode.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
|
|
||||||
@interface IJSVGForeignObject : IJSVGNode {
|
@interface IJSVGForeignObject : IJSVGNode {
|
||||||
|
|
||||||
NSString * requiredExtension;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property ( nonatomic, copy ) NSString * requiredExtension;
|
@property (nonatomic, copy) NSString* requiredExtension;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,11 +10,9 @@
|
|||||||
|
|
||||||
@implementation IJSVGForeignObject
|
@implementation IJSVGForeignObject
|
||||||
|
|
||||||
@synthesize requiredExtension;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([requiredExtension release]), requiredExtension = nil;
|
(void)([_requiredExtension release]), _requiredExtension = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGColorList.h"
|
#import <IJSVG/IJSVGColorList.h>
|
||||||
#import "IJSVGDef.h"
|
#import <IJSVG/IJSVGDef.h>
|
||||||
#import "IJSVGTransform.h"
|
#import <IJSVG/IJSVGTransform.h>
|
||||||
|
#import <IJSVG/IJSVGGroup.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGGradient : IJSVGNode
|
@interface IJSVGGradient : IJSVGGroup
|
||||||
|
|
||||||
@property (nonatomic, retain) NSGradient* gradient;
|
@property (nonatomic, retain) NSGradient* gradient;
|
||||||
@property (nonatomic, assign) CGGradientRef CGGradient;
|
@property (nonatomic, assign) CGGradientRef CGGradient;
|
||||||
@@ -21,8 +22,9 @@
|
|||||||
@property (nonatomic, retain) IJSVGUnitLength* y2;
|
@property (nonatomic, retain) IJSVGUnitLength* y2;
|
||||||
@property (nonatomic, retain) IJSVGColorList* colorList;
|
@property (nonatomic, retain) IJSVGColorList* colorList;
|
||||||
|
|
||||||
+ (CGFloat*)computeColorStopsFromString:(NSXMLElement*)element
|
+ (CGFloat*)computeColorStops:(IJSVGGradient*)gradient
|
||||||
colors:(NSArray**)someColors;
|
colors:(NSArray**)someColors;
|
||||||
|
|
||||||
- (CGGradientRef)CGGradient;
|
- (CGGradientRef)CGGradient;
|
||||||
- (void)drawInContextRef:(CGContextRef)ctx
|
- (void)drawInContextRef:(CGContextRef)ctx
|
||||||
objectRect:(NSRect)objectRect
|
objectRect:(NSRect)objectRect
|
||||||
@@ -33,6 +35,7 @@
|
|||||||
end:(CGPoint)endPoint
|
end:(CGPoint)endPoint
|
||||||
context:(CGContextRef)ctx;
|
context:(CGContextRef)ctx;
|
||||||
|
|
||||||
|
- (IJSVGColorList*)colorList;
|
||||||
- (IJSVGColorList*)computedColorList;
|
- (IJSVGColorList*)computedColorList;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,23 +7,22 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGGradient.h"
|
#import "IJSVGGradient.h"
|
||||||
|
#import "IJSVGParser.h"
|
||||||
|
|
||||||
@implementation IJSVGGradient
|
@implementation IJSVGGradient
|
||||||
|
|
||||||
@synthesize gradient, CGGradient;
|
@synthesize colorList = _privateColorList;
|
||||||
@synthesize x1, x2, y1, y2;
|
|
||||||
@synthesize colorList = _colorList;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([x1 release]), x1 = nil;
|
(void)([_x1 release]), _x1 = nil;
|
||||||
(void)([x2 release]), x2 = nil;
|
(void)([_x2 release]), _x2 = nil;
|
||||||
(void)([y1 release]), y1 = nil;
|
(void)([_y1 release]), _y1 = nil;
|
||||||
(void)([y2 release]), y2 = nil;
|
(void)([_y2 release]), _y2 = nil;
|
||||||
(void)([gradient release]), gradient = nil;
|
(void)([_gradient release]), _gradient = nil;
|
||||||
(void)([_colorList release]), _colorList = nil;
|
(void)([_privateColorList release]), _privateColorList = nil;
|
||||||
if (CGGradient != nil) {
|
if (_CGGradient != nil) {
|
||||||
CGGradientRelease(CGGradient);
|
CGGradientRelease(_CGGradient);
|
||||||
}
|
}
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
@@ -37,84 +36,41 @@
|
|||||||
|
|
||||||
- (void)setColorList:(IJSVGColorList*)list
|
- (void)setColorList:(IJSVGColorList*)list
|
||||||
{
|
{
|
||||||
(void)([_colorList release]), _colorList = nil;
|
(void)([_privateColorList release]), _privateColorList = nil;
|
||||||
_colorList = list.retain;
|
_privateColorList = list.retain;
|
||||||
if (CGGradient != nil) {
|
if (_CGGradient != nil) {
|
||||||
CGGradientRelease(CGGradient);
|
CGGradientRelease(_CGGradient);
|
||||||
|
_CGGradient = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CGFloat*)computeColorStopsFromString:(NSXMLElement*)element
|
+ (CGFloat *)computeColorStops:(IJSVGGradient*)gradient
|
||||||
colors:(NSArray**)someColors
|
colors:(NSArray**)someColors
|
||||||
{
|
{
|
||||||
// find each stop element
|
NSArray<IJSVGNode*>* stops = gradient.childNodes;
|
||||||
NSArray* stops = [element children];
|
|
||||||
NSMutableArray* colors = [[[NSMutableArray alloc] initWithCapacity:stops.count] autorelease];
|
NSMutableArray* colors = [[[NSMutableArray alloc] initWithCapacity:stops.count] autorelease];
|
||||||
CGFloat* stopsParams = (CGFloat*)malloc(stops.count * sizeof(CGFloat));
|
CGFloat* stopsParams = (CGFloat*)malloc(stops.count * sizeof(CGFloat));
|
||||||
|
|
||||||
NSInteger i = 0;
|
NSInteger i = 0;
|
||||||
for (NSXMLElement* stop in stops) {
|
for(IJSVGNode* stopNode in stops) {
|
||||||
// find the offset
|
NSColor* color = stopNode.fillColor;
|
||||||
CGFloat offset = [stop attributeForName:@"offset"].stringValue.floatValue;
|
CGFloat opacity = stopNode.fillOpacity.value;
|
||||||
if (offset > 1.f) {
|
CGFloat offset = stopNode.offset.value;
|
||||||
offset /= 100.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
stopsParams[i++] = offset;
|
stopsParams[i++] = offset;
|
||||||
|
if(color == nil) {
|
||||||
// find the stop opacity
|
color = [IJSVGColor colorFromHEXInteger:0x000000];
|
||||||
CGFloat stopOpacity = 1.f;
|
if(opacity != 1.f) {
|
||||||
NSXMLNode* stopOpacityAttribute = [stop attributeForName:@"stop-opacity"];
|
color = [IJSVGColor changeAlphaOnColor:color
|
||||||
if (stopOpacityAttribute != nil) {
|
to:opacity];
|
||||||
stopOpacity = stopOpacityAttribute.stringValue.floatValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the stop color
|
|
||||||
NSString* scs = [stop attributeForName:@"stop-color"].stringValue;
|
|
||||||
NSColor* stopColor = [IJSVGColor colorFromString:scs];
|
|
||||||
if (stopColor != nil && stopOpacity != 1.f) {
|
|
||||||
stopColor = [IJSVGColor changeAlphaOnColor:stopColor
|
|
||||||
to:stopOpacity];
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute any style that there was...
|
|
||||||
NSXMLNode* styleAttribute = [stop attributeForName:@"style"];
|
|
||||||
if (styleAttribute != nil) {
|
|
||||||
|
|
||||||
IJSVGStyle* style = [IJSVGStyle parseStyleString:styleAttribute.stringValue];
|
|
||||||
NSColor* color = [IJSVGColor colorFromString:[style property:@"stop-color"]];
|
|
||||||
|
|
||||||
// we have a color!
|
|
||||||
if (color != nil) {
|
|
||||||
// is there a stop opacity?
|
|
||||||
NSString* numberString = nil;
|
|
||||||
if ((numberString = [style property:@"stop-opacity"]) != nil) {
|
|
||||||
color = [IJSVGColor changeAlphaOnColor:color
|
|
||||||
to:numberString.floatValue];
|
|
||||||
} else {
|
|
||||||
color = [IJSVGColor changeAlphaOnColor:color
|
|
||||||
to:stopOpacity];
|
|
||||||
}
|
|
||||||
stopColor = color;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[colors addObject:color];
|
||||||
// default is black
|
|
||||||
if (stopColor == nil) {
|
|
||||||
stopColor = [IJSVGColor colorFromString:@"black"];
|
|
||||||
if (stopOpacity != 1.f) {
|
|
||||||
stopColor = [IJSVGColor changeAlphaOnColor:stopColor
|
|
||||||
to:stopOpacity];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the stop color
|
|
||||||
[(NSMutableArray*)colors addObject:stopColor];
|
|
||||||
}
|
}
|
||||||
*someColors = colors;
|
*someColors = (NSArray*)colors;
|
||||||
return stopsParams;
|
return stopsParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGColorList*)computedColorList
|
- (IJSVGColorList*)colorList
|
||||||
{
|
{
|
||||||
IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease];
|
IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease];
|
||||||
NSInteger num = self.gradient.numberOfColorStops;
|
NSInteger num = self.gradient.numberOfColorStops;
|
||||||
@@ -123,16 +79,23 @@
|
|||||||
[self.gradient getColor:&color
|
[self.gradient getColor:&color
|
||||||
location:nil
|
location:nil
|
||||||
atIndex:i];
|
atIndex:i];
|
||||||
[sheet addColor:color];
|
IJSVGColorType* type = [IJSVGColorType typeWithColor:color
|
||||||
|
flags:IJSVGColorTypeFlagStop];
|
||||||
|
[sheet addColor:type];
|
||||||
}
|
}
|
||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IJSVGColorList*)computedColorList
|
||||||
|
{
|
||||||
|
return _privateColorList;
|
||||||
|
}
|
||||||
|
|
||||||
- (CGGradientRef)CGGradient
|
- (CGGradientRef)CGGradient
|
||||||
{
|
{
|
||||||
// store it in the cache
|
// store it in the cache
|
||||||
if (CGGradient != nil) {
|
if (_CGGradient != nil) {
|
||||||
return CGGradient;
|
return _CGGradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
// actually create the gradient
|
// actually create the gradient
|
||||||
@@ -145,8 +108,8 @@
|
|||||||
[self.gradient getColor:&color
|
[self.gradient getColor:&color
|
||||||
location:&locations[i]
|
location:&locations[i]
|
||||||
atIndex:i];
|
atIndex:i];
|
||||||
if (_colorList != nil) {
|
if (_privateColorList != nil) {
|
||||||
color = [_colorList proposedColorForColor:color];
|
color = [_privateColorList proposedColorForColor:color];
|
||||||
}
|
}
|
||||||
CFArrayAppendValue(colors, color.CGColor);
|
CFArrayAppendValue(colors, color.CGColor);
|
||||||
}
|
}
|
||||||
@@ -154,7 +117,7 @@
|
|||||||
colors, locations);
|
colors, locations);
|
||||||
CFRelease(colors);
|
CFRelease(colors);
|
||||||
free(locations);
|
free(locations);
|
||||||
return CGGradient = result;
|
return _CGGradient = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawInContextRef:(CGContextRef)ctx
|
- (void)drawInContextRef:(CGContextRef)ctx
|
||||||
|
|||||||
@@ -6,17 +6,18 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGNode.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
#import "IJSVGPath.h"
|
#import <IJSVG/IJSVGPath.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGGroup : IJSVGNode {
|
@interface IJSVGGroup : IJSVGNode {
|
||||||
|
|
||||||
NSMutableArray* children;
|
@private
|
||||||
|
NSMutableArray<IJSVGNode*>* _childNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addChild:(id)child;
|
- (void)addChild:(IJSVGNode*)child;
|
||||||
- (NSArray*)children;
|
- (NSArray<IJSVGNode*>*)childNodes;
|
||||||
- (void)purgeChildren;
|
- (void)purgeChildren;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,21 +12,24 @@
|
|||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([children release]), children = nil;
|
(void)([_childNodes release]), _childNodes = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil) {
|
if ((self = [super init]) != nil) {
|
||||||
children = [[NSMutableArray alloc] init];
|
_childNodes = [[NSMutableArray alloc] init];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)prepareFromCopy
|
- (void)prepareFromCopy
|
||||||
{
|
{
|
||||||
children = [[NSMutableArray alloc] init];
|
if(_childNodes != nil) {
|
||||||
|
(void)[_childNodes release], _childNodes = nil;
|
||||||
|
}
|
||||||
|
_childNodes = [[NSMutableArray alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)copyWithZone:(NSZone*)zone
|
- (id)copyWithZone:(NSZone*)zone
|
||||||
@@ -34,7 +37,7 @@
|
|||||||
IJSVGGroup* node = [super copyWithZone:zone];
|
IJSVGGroup* node = [super copyWithZone:zone];
|
||||||
[node prepareFromCopy];
|
[node prepareFromCopy];
|
||||||
|
|
||||||
for (IJSVGNode* childNode in self.children) {
|
for (IJSVGNode* childNode in _childNodes) {
|
||||||
childNode = [[childNode copy] autorelease];
|
childNode = [[childNode copy] autorelease];
|
||||||
childNode.parentNode = node;
|
childNode.parentNode = node;
|
||||||
[node addChild:childNode];
|
[node addChild:childNode];
|
||||||
@@ -44,23 +47,25 @@
|
|||||||
|
|
||||||
- (void)purgeChildren
|
- (void)purgeChildren
|
||||||
{
|
{
|
||||||
[children removeAllObjects];
|
[_childNodes removeAllObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addChild:(id)child
|
- (void)addChild:(IJSVGNode*)child
|
||||||
{
|
{
|
||||||
if (child != nil)
|
if (child != nil) {
|
||||||
[children addObject:child];
|
[_childNodes addObject:child];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*)children
|
- (NSArray<IJSVGNode*>*)childNodes
|
||||||
{
|
{
|
||||||
return children;
|
return _childNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)description
|
- (NSString*)description
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat:@"%@ - %@", [super description], self.children];
|
return [NSString stringWithFormat:@"%@ - %@",
|
||||||
|
[super description], self.childNodes];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGNode.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVGPath;
|
@class IJSVGPath;
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
- (CGImageRef)CGImage;
|
- (CGImageRef)CGImage;
|
||||||
- (void)drawInContextRef:(CGContextRef)context
|
- (void)drawInContextRef:(CGContextRef)context
|
||||||
path:(IJSVGPath*)path;
|
path:(IJSVGPath*)path;
|
||||||
- (void)loadFromBase64EncodedString:(NSString*)encodedString;
|
- (void)loadFromString:(NSString*)encodedString;
|
||||||
|
- (void)loadFromURL:(NSURL*)aURL;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)loadFromBase64EncodedString:(NSString*)encodedString
|
- (void)loadFromString:(NSString*)encodedString
|
||||||
{
|
{
|
||||||
if ([encodedString hasPrefix:@"data:"]) {
|
if ([encodedString hasPrefix:@"data:"]) {
|
||||||
encodedString = [encodedString stringByReplacingOccurrencesOfString:@"\\s+"
|
encodedString = [encodedString stringByReplacingOccurrencesOfString:@"\\s+"
|
||||||
@@ -28,8 +28,15 @@
|
|||||||
options:NSRegularExpressionSearch
|
options:NSRegularExpressionSearch
|
||||||
range:NSMakeRange(0, encodedString.length)];
|
range:NSMakeRange(0, encodedString.length)];
|
||||||
}
|
}
|
||||||
NSURL* URL = [NSURL URLWithString:encodedString];
|
NSURL* url = [NSURL URLWithString:encodedString];
|
||||||
NSData* data = [NSData dataWithContentsOfURL:URL];
|
if(url != nil) {
|
||||||
|
[self loadFromURL:url];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)loadFromURL:(NSURL*)aURL
|
||||||
|
{
|
||||||
|
NSData* data = [NSData dataWithContentsOfURL:aURL];
|
||||||
|
|
||||||
// no data, just ignore...invalid probably
|
// no data, just ignore...invalid probably
|
||||||
if (data == nil) {
|
if (data == nil) {
|
||||||
@@ -46,7 +53,8 @@
|
|||||||
if (imagePath == nil) {
|
if (imagePath == nil) {
|
||||||
// lazy load the path as it might not be needed
|
// lazy load the path as it might not be needed
|
||||||
imagePath = [[IJSVGPath alloc] init];
|
imagePath = [[IJSVGPath alloc] init];
|
||||||
[imagePath.path appendBezierPathWithRect:NSMakeRect(0.f, 0.f, self.width.value, self.height.value)];
|
CGRect rect = CGRectMake(0.f, 0.f, self.width.value, self.height.value);
|
||||||
|
CGPathAddRect(imagePath.path, NULL, rect);
|
||||||
[imagePath close];
|
[imagePath close];
|
||||||
}
|
}
|
||||||
return imagePath;
|
return imagePath;
|
||||||
@@ -92,7 +100,7 @@
|
|||||||
path = [self path];
|
path = [self path];
|
||||||
}
|
}
|
||||||
|
|
||||||
CGRect rect = path.path.bounds;
|
CGRect rect = path.pathBoundingBox;
|
||||||
CGRect bounds = CGRectMake(0.f, 0.f, rect.size.width, rect.size.height);
|
CGRect bounds = CGRectMake(0.f, 0.f, rect.size.width, rect.size.height);
|
||||||
|
|
||||||
// save the state of the context
|
// save the state of the context
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGGradient.h"
|
#import <IJSVG/IJSVGGradient.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGLinearGradient : IJSVGGradient
|
@interface IJSVGLinearGradient : IJSVGGradient
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#import "IJSVGLinearGradient.h"
|
#import "IJSVGLinearGradient.h"
|
||||||
#import "IJSVGUtils.h"
|
#import "IJSVGUtils.h"
|
||||||
|
#import "IJSVGParser.h"
|
||||||
|
|
||||||
@implementation IJSVGLinearGradient
|
@implementation IJSVGLinearGradient
|
||||||
|
|
||||||
@@ -15,10 +16,10 @@
|
|||||||
gradient:(IJSVGLinearGradient*)aGradient
|
gradient:(IJSVGLinearGradient*)aGradient
|
||||||
{
|
{
|
||||||
// just ask unit for the value
|
// just ask unit for the value
|
||||||
NSString* x1 = ([element attributeForName:@"x1"].stringValue ?: @"0");
|
NSString* x1 = ([element attributeForName:IJSVGAttributeX1].stringValue ?: @"0");
|
||||||
NSString* x2 = ([element attributeForName:@"x2"].stringValue ?: @"100%");
|
NSString* x2 = ([element attributeForName:IJSVGAttributeX2].stringValue ?: @"100%");
|
||||||
NSString* y1 = ([element attributeForName:@"y1"].stringValue ?: @"0");
|
NSString* y1 = ([element attributeForName:IJSVGAttributeY1].stringValue ?: @"0");
|
||||||
NSString* y2 = ([element attributeForName:@"y2"].stringValue ?: @"0");
|
NSString* y2 = ([element attributeForName:IJSVGAttributeY2].stringValue ?: @"0");
|
||||||
aGradient.x1 = [IJSVGGradientUnitLength unitWithString:x1 fromUnitType:aGradient.units];
|
aGradient.x1 = [IJSVGGradientUnitLength unitWithString:x1 fromUnitType:aGradient.units];
|
||||||
aGradient.x2 = [IJSVGGradientUnitLength unitWithString:x2 fromUnitType:aGradient.units];
|
aGradient.x2 = [IJSVGGradientUnitLength unitWithString:x2 fromUnitType:aGradient.units];
|
||||||
aGradient.y1 = [IJSVGGradientUnitLength unitWithString:y1 fromUnitType:aGradient.units];
|
aGradient.y1 = [IJSVGGradientUnitLength unitWithString:y1 fromUnitType:aGradient.units];
|
||||||
@@ -26,8 +27,8 @@
|
|||||||
|
|
||||||
// compute the color stops and colours
|
// compute the color stops and colours
|
||||||
NSArray* colors = nil;
|
NSArray* colors = nil;
|
||||||
CGFloat* stopsParams = [self.class computeColorStopsFromString:element
|
CGFloat* stopsParams = [self.class computeColorStops:aGradient
|
||||||
colors:&colors];
|
colors:&colors];
|
||||||
|
|
||||||
// create the gradient with the colours
|
// create the gradient with the colours
|
||||||
NSGradient* grad = [[NSGradient alloc] initWithColors:colors
|
NSGradient* grad = [[NSGradient alloc] initWithColors:colors
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGStyle.h"
|
#import <IJSVG/IJSVGStyle.h>
|
||||||
#import "IJSVGUnitLength.h"
|
#import <IJSVG/IJSVGUnitLength.h>
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class IJSVGNode;
|
||||||
@class IJSVG;
|
@class IJSVG;
|
||||||
@class IJSVGGroup;
|
@class IJSVGGroup;
|
||||||
@class IJSVGDef;
|
@class IJSVGDef;
|
||||||
@@ -19,6 +20,8 @@
|
|||||||
@class IJSVGPattern;
|
@class IJSVGPattern;
|
||||||
@class IJSVGTransform;
|
@class IJSVGTransform;
|
||||||
|
|
||||||
|
typedef void (^IJSVGNodeWalkHandler)(IJSVGNode* node, BOOL* allowChildNodes, BOOL* stop);
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, IJSVGNodeType) {
|
typedef NS_ENUM(NSInteger, IJSVGNodeType) {
|
||||||
IJSVGNodeTypeGroup,
|
IJSVGNodeTypeGroup,
|
||||||
IJSVGNodeTypePath,
|
IJSVGNodeTypePath,
|
||||||
@@ -43,6 +46,9 @@ typedef NS_ENUM(NSInteger, IJSVGNodeType) {
|
|||||||
IJSVGNodeTypeTextSpan,
|
IJSVGNodeTypeTextSpan,
|
||||||
IJSVGNodeTypeStyle,
|
IJSVGNodeTypeStyle,
|
||||||
IJSVGNodeTypeSwitch,
|
IJSVGNodeTypeSwitch,
|
||||||
|
IJSVGNodeTypeTitle,
|
||||||
|
IJSVGNodeTypeDesc,
|
||||||
|
IJSVGNodeTypeStop,
|
||||||
IJSVGNodeTypeNotFound,
|
IJSVGNodeTypeNotFound,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,10 +99,17 @@ typedef NS_ENUM(NSInteger, IJSVGBlendMode) {
|
|||||||
IJSVGBlendModeLuminosity = kCGBlendModeLuminosity
|
IJSVGBlendModeLuminosity = kCGBlendModeLuminosity
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, IJSVGOverflowVisibility) {
|
||||||
|
IJSVGOverflowVisibilityHidden,
|
||||||
|
IJSVGOverflowVisibilityVisible
|
||||||
|
};
|
||||||
|
|
||||||
static CGFloat IJSVGInheritedFloatValue = -99.9999991;
|
static CGFloat IJSVGInheritedFloatValue = -99.9999991;
|
||||||
|
|
||||||
@interface IJSVGNode : NSObject <NSCopying>
|
@interface IJSVGNode : NSObject <NSCopying>
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString* title;
|
||||||
|
@property (nonatomic, copy) NSString* desc;
|
||||||
@property (nonatomic, assign) IJSVGNodeType type;
|
@property (nonatomic, assign) IJSVGNodeType type;
|
||||||
@property (nonatomic, copy) NSString* name;
|
@property (nonatomic, copy) NSString* name;
|
||||||
@property (nonatomic, copy) NSString* className;
|
@property (nonatomic, copy) NSString* className;
|
||||||
@@ -112,6 +125,7 @@ static CGFloat IJSVGInheritedFloatValue = -99.9999991;
|
|||||||
@property (nonatomic, retain) IJSVGUnitLength* fillOpacity;
|
@property (nonatomic, retain) IJSVGUnitLength* fillOpacity;
|
||||||
@property (nonatomic, retain) IJSVGUnitLength* strokeOpacity;
|
@property (nonatomic, retain) IJSVGUnitLength* strokeOpacity;
|
||||||
@property (nonatomic, retain) IJSVGUnitLength* strokeWidth;
|
@property (nonatomic, retain) IJSVGUnitLength* strokeWidth;
|
||||||
|
@property (nonatomic, retain) IJSVGUnitLength* offset;
|
||||||
@property (nonatomic, retain) NSColor* fillColor;
|
@property (nonatomic, retain) NSColor* fillColor;
|
||||||
@property (nonatomic, retain) NSColor* strokeColor;
|
@property (nonatomic, retain) NSColor* strokeColor;
|
||||||
@property (nonatomic, copy) NSString* identifier;
|
@property (nonatomic, copy) NSString* identifier;
|
||||||
@@ -135,6 +149,10 @@ static CGFloat IJSVGInheritedFloatValue = -99.9999991;
|
|||||||
@property (nonatomic, assign) IJSVGUnitType contentUnits;
|
@property (nonatomic, assign) IJSVGUnitType contentUnits;
|
||||||
@property (nonatomic, assign) IJSVGUnitType units;
|
@property (nonatomic, assign) IJSVGUnitType units;
|
||||||
@property (nonatomic, assign) IJSVGBlendMode blendMode;
|
@property (nonatomic, assign) IJSVGBlendMode blendMode;
|
||||||
|
@property (nonatomic, assign) IJSVGOverflowVisibility overflowVisibility;
|
||||||
|
|
||||||
|
+ (void)walkNodeTree:(IJSVGNode*)node
|
||||||
|
handler:(IJSVGNodeWalkHandler)handler;
|
||||||
|
|
||||||
+ (IJSVGNodeType)typeForString:(NSString*)string
|
+ (IJSVGNodeType)typeForString:(NSString*)string
|
||||||
kind:(NSXMLNodeKind)kind;
|
kind:(NSXMLNodeKind)kind;
|
||||||
|
|||||||
@@ -9,136 +9,134 @@
|
|||||||
#import "IJSVGDef.h"
|
#import "IJSVGDef.h"
|
||||||
#import "IJSVGNode.h"
|
#import "IJSVGNode.h"
|
||||||
#import "IJSVGUtils.h"
|
#import "IJSVGUtils.h"
|
||||||
|
#import "IJSVGGroup.h"
|
||||||
|
|
||||||
@implementation IJSVGNode
|
@implementation IJSVGNode
|
||||||
|
|
||||||
@synthesize shouldRender;
|
|
||||||
@synthesize type;
|
|
||||||
@synthesize name;
|
|
||||||
@synthesize classNameList;
|
|
||||||
@synthesize className;
|
|
||||||
@synthesize unicode;
|
|
||||||
@synthesize x;
|
|
||||||
@synthesize y;
|
|
||||||
@synthesize width;
|
|
||||||
@synthesize height;
|
|
||||||
@synthesize fillColor;
|
|
||||||
@synthesize fillOpacity;
|
|
||||||
@synthesize strokeColor;
|
|
||||||
@synthesize strokeOpacity;
|
|
||||||
@synthesize strokeWidth;
|
|
||||||
@synthesize opacity;
|
|
||||||
@synthesize identifier;
|
|
||||||
@synthesize parentNode;
|
|
||||||
@synthesize intermediateParentNode;
|
|
||||||
@synthesize transforms;
|
|
||||||
@synthesize windingRule;
|
|
||||||
@synthesize def;
|
|
||||||
@synthesize fillGradient;
|
|
||||||
@synthesize fillPattern;
|
|
||||||
@synthesize strokeGradient;
|
|
||||||
@synthesize strokePattern;
|
|
||||||
@synthesize clipPath;
|
|
||||||
@synthesize lineCapStyle;
|
|
||||||
@synthesize lineJoinStyle;
|
|
||||||
@synthesize strokeDashArrayCount;
|
|
||||||
@synthesize strokeDashArray;
|
|
||||||
@synthesize strokeDashOffset;
|
|
||||||
@synthesize usesDefaultFillColor;
|
|
||||||
@synthesize svg;
|
|
||||||
@synthesize mask;
|
|
||||||
@synthesize units;
|
|
||||||
@synthesize contentUnits;
|
|
||||||
@synthesize blendMode;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
free(strokeDashArray);
|
(void)free(_strokeDashArray), _strokeDashArray = NULL;
|
||||||
(void)([x release]), x = nil;
|
(void)([_x release]), _x = nil;
|
||||||
(void)([y release]), y = nil;
|
(void)([_y release]), _y = nil;
|
||||||
(void)([width release]), width = nil;
|
(void)([_width release]), _width = nil;
|
||||||
(void)([height release]), height = nil;
|
(void)([_height release]), _height = nil;
|
||||||
(void)([opacity release]), opacity = nil;
|
(void)([_opacity release]), _opacity = nil;
|
||||||
(void)([fillOpacity release]), fillOpacity = nil;
|
(void)([_offset release]), _offset = nil;
|
||||||
(void)([strokeOpacity release]), strokeOpacity = nil;
|
(void)([_fillOpacity release]), _fillOpacity = nil;
|
||||||
(void)([strokeWidth release]), strokeWidth = nil;
|
(void)([_strokeOpacity release]), _strokeOpacity = nil;
|
||||||
(void)([strokeDashOffset release]), strokeDashOffset = nil;
|
(void)([_strokeWidth release]), _strokeWidth = nil;
|
||||||
(void)([unicode release]), unicode = nil;
|
(void)([_strokeDashOffset release]), _strokeDashOffset = nil;
|
||||||
(void)([fillGradient release]), fillGradient = nil;
|
(void)([_unicode release]), _unicode = nil;
|
||||||
(void)([strokeGradient release]), strokeGradient = nil;
|
(void)([_fillGradient release]), _fillGradient = nil;
|
||||||
(void)([strokePattern release]), strokePattern = nil;
|
(void)([_strokeGradient release]), _strokeGradient = nil;
|
||||||
(void)([transforms release]), transforms = nil;
|
(void)([_strokePattern release]), _strokePattern = nil;
|
||||||
(void)([fillColor release]), fillColor = nil;
|
(void)([_transforms release]), _transforms = nil;
|
||||||
(void)([strokeColor release]), strokeColor = nil;
|
(void)([_fillColor release]), _fillColor = nil;
|
||||||
(void)([identifier release]), identifier = nil;
|
(void)([_strokeColor release]), _strokeColor = nil;
|
||||||
(void)([def release]), def = nil;
|
(void)([_identifier release]), _identifier = nil;
|
||||||
(void)([name release]), name = nil;
|
(void)([_def release]), _def = nil;
|
||||||
(void)([className release]), className = nil;
|
(void)([_name release]), _name = nil;
|
||||||
(void)([classNameList release]), classNameList = nil;
|
(void)([_title release]), _title = nil;
|
||||||
(void)([fillPattern release]), fillPattern = nil;
|
(void)([_desc release]), _desc = nil;
|
||||||
(void)([clipPath release]), clipPath = nil;
|
(void)([_className release]), _className = nil;
|
||||||
(void)([svg release]), svg = nil;
|
(void)([_classNameList release]), _classNameList = nil;
|
||||||
(void)([mask release]), mask = nil;
|
(void)([_fillPattern release]), _fillPattern = nil;
|
||||||
|
(void)([_clipPath release]), _clipPath = nil;
|
||||||
|
(void)([_svg release]), _svg = nil;
|
||||||
|
(void)([_mask release]), _mask = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (IJSVGNodeType)typeForString:(NSString*)string
|
+ (IJSVGNodeType)typeForString:(NSString*)string
|
||||||
kind:(NSXMLNodeKind)kind
|
kind:(NSXMLNodeKind)kind
|
||||||
{
|
{
|
||||||
string = [string lowercaseString];
|
// possible fix for older os's that complain
|
||||||
if ([string isEqualToString:@"style"])
|
if(string == nil || kind == NSXMLCommentKind) {
|
||||||
|
return IJSVGNodeTypeNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name = string.lowercaseString.UTF8String;
|
||||||
|
if(name == NULL) {
|
||||||
|
return IJSVGNodeTypeNotFound;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "style") == 0) {
|
||||||
return IJSVGNodeTypeStyle;
|
return IJSVGNodeTypeStyle;
|
||||||
if ([string isEqualToString:@"switch"])
|
}
|
||||||
|
if (strcmp(name, "switch") == 0) {
|
||||||
return IJSVGNodeTypeSwitch;
|
return IJSVGNodeTypeSwitch;
|
||||||
if ([string isEqualToString:@"defs"])
|
}
|
||||||
|
if (strcmp(name, "defs") == 0) {
|
||||||
return IJSVGNodeTypeDef;
|
return IJSVGNodeTypeDef;
|
||||||
if ([string isEqualToString:@"g"])
|
}
|
||||||
|
if (strcmp(name, "g") == 0) {
|
||||||
return IJSVGNodeTypeGroup;
|
return IJSVGNodeTypeGroup;
|
||||||
if ([string isEqualToString:@"path"])
|
}
|
||||||
|
if (strcmp(name, "path") == 0) {
|
||||||
return IJSVGNodeTypePath;
|
return IJSVGNodeTypePath;
|
||||||
if ([string isEqualToString:@"polygon"])
|
}
|
||||||
|
if (strcmp(name, "polygon") == 0) {
|
||||||
return IJSVGNodeTypePolygon;
|
return IJSVGNodeTypePolygon;
|
||||||
if ([string isEqualToString:@"polyline"])
|
}
|
||||||
|
if (strcmp(name, "polyline") == 0) {
|
||||||
return IJSVGNodeTypePolyline;
|
return IJSVGNodeTypePolyline;
|
||||||
if ([string isEqualToString:@"rect"])
|
}
|
||||||
|
if (strcmp(name, "rect") == 0) {
|
||||||
return IJSVGNodeTypeRect;
|
return IJSVGNodeTypeRect;
|
||||||
if ([string isEqualToString:@"line"])
|
}
|
||||||
|
if (strcmp(name, "line") == 0) {
|
||||||
return IJSVGNodeTypeLine;
|
return IJSVGNodeTypeLine;
|
||||||
if ([string isEqualToString:@"circle"])
|
}
|
||||||
|
if (strcmp(name, "circle") == 0) {
|
||||||
return IJSVGNodeTypeCircle;
|
return IJSVGNodeTypeCircle;
|
||||||
if ([string isEqualToString:@"ellipse"])
|
}
|
||||||
|
if (strcmp(name, "ellipse") == 0) {
|
||||||
return IJSVGNodeTypeEllipse;
|
return IJSVGNodeTypeEllipse;
|
||||||
if ([string isEqualToString:@"use"])
|
}
|
||||||
|
if (strcmp(name, "use") == 0) {
|
||||||
return IJSVGNodeTypeUse;
|
return IJSVGNodeTypeUse;
|
||||||
if ([string isEqualToString:@"lineargradient"])
|
}
|
||||||
|
if (strcmp(name, "lineargradient") == 0) {
|
||||||
return IJSVGNodeTypeLinearGradient;
|
return IJSVGNodeTypeLinearGradient;
|
||||||
if ([string isEqualToString:@"radialgradient"])
|
}
|
||||||
|
if (strcmp(name, "radialgradient") == 0) {
|
||||||
return IJSVGNodeTypeRadialGradient;
|
return IJSVGNodeTypeRadialGradient;
|
||||||
if ([string isEqualToString:@"glyph"])
|
}
|
||||||
|
if(strcmp(name, "stop") == 0) {
|
||||||
|
return IJSVGNodeTypeStop;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "glyph") == 0) {
|
||||||
return IJSVGNodeTypeGlyph;
|
return IJSVGNodeTypeGlyph;
|
||||||
if ([string isEqualToString:@"font"])
|
}
|
||||||
|
if (strcmp(name, "font") == 0) {
|
||||||
return IJSVGNodeTypeFont;
|
return IJSVGNodeTypeFont;
|
||||||
if ([string isEqualToString:@"clippath"])
|
}
|
||||||
|
if (strcmp(name, "clippath") == 0) {
|
||||||
return IJSVGNodeTypeClipPath;
|
return IJSVGNodeTypeClipPath;
|
||||||
if ([string isEqualToString:@"mask"])
|
}
|
||||||
|
if (strcmp(name, "mask") == 0) {
|
||||||
return IJSVGNodeTypeMask;
|
return IJSVGNodeTypeMask;
|
||||||
if ([string isEqualToString:@"image"])
|
}
|
||||||
|
if (strcmp(name, "image") == 0) {
|
||||||
return IJSVGNodeTypeImage;
|
return IJSVGNodeTypeImage;
|
||||||
if ([string isEqualToString:@"pattern"])
|
}
|
||||||
|
if (strcmp(name, "pattern") == 0) {
|
||||||
return IJSVGNodeTypePattern;
|
return IJSVGNodeTypePattern;
|
||||||
if ([string isEqualToString:@"svg"])
|
}
|
||||||
|
if (strcmp(name, "svg") == 0) {
|
||||||
return IJSVGNodeTypeSVG;
|
return IJSVGNodeTypeSVG;
|
||||||
if ([string isEqualToString:@"text"])
|
}
|
||||||
|
if (strcmp(name, "text") == 0) {
|
||||||
return IJSVGNodeTypeText;
|
return IJSVGNodeTypeText;
|
||||||
if ([string isEqualToString:@"tspan"] || kind == NSXMLTextKind) {
|
}
|
||||||
|
if (strcmp(name, "tspan") == 0 || kind == NSXMLTextKind) {
|
||||||
return IJSVGNodeTypeTextSpan;
|
return IJSVGNodeTypeTextSpan;
|
||||||
}
|
}
|
||||||
|
if(strcmp(name, "title") == 0) {
|
||||||
// are we commong HTML? - if so just treat as a group
|
return IJSVGNodeTypeTitle;
|
||||||
if (IJSVGIsCommonHTMLElementName(string) == YES) {
|
}
|
||||||
return IJSVGNodeTypeGroup;
|
if(strcmp(name, "desc") == 0) {
|
||||||
|
return IJSVGNodeTypeDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return IJSVGNodeTypeNotFound;
|
return IJSVGNodeTypeNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +148,55 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)walkNodeTree:(IJSVGNode*)node
|
||||||
|
handler:(IJSVGNodeWalkHandler)handler
|
||||||
|
{
|
||||||
|
BOOL allowChildNodes = YES;
|
||||||
|
BOOL stop = NO;
|
||||||
|
[self _walkNodeTree:node
|
||||||
|
handler:handler
|
||||||
|
allowChildNodes:&allowChildNodes
|
||||||
|
stop:&stop];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)_walkNodeTree:(IJSVGNode*)node
|
||||||
|
handler:(IJSVGNodeWalkHandler)handler
|
||||||
|
allowChildNodes:(BOOL*)allowChildNodes
|
||||||
|
stop:(BOOL*)stop
|
||||||
|
{
|
||||||
|
// run the handler and instantly stop
|
||||||
|
// if stop is set
|
||||||
|
handler(node, allowChildNodes, stop);
|
||||||
|
if(*stop == YES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// child nodes only work for nodes
|
||||||
|
// that are type group
|
||||||
|
if(*allowChildNodes == NO ||
|
||||||
|
[node isKindOfClass:IJSVGGroup.class] == NO) {
|
||||||
|
*allowChildNodes = YES;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over the childnodes
|
||||||
|
IJSVGGroup* group = (IJSVGGroup*)node;
|
||||||
|
for(IJSVGNode* childNode in group.childNodes) {
|
||||||
|
[self _walkNodeTree:childNode
|
||||||
|
handler:handler
|
||||||
|
allowChildNodes:allowChildNodes
|
||||||
|
stop:stop];
|
||||||
|
if(*stop == YES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)applyPropertiesFromNode:(IJSVGNode*)node
|
- (void)applyPropertiesFromNode:(IJSVGNode*)node
|
||||||
{
|
{
|
||||||
|
self.title = node.title;
|
||||||
|
self.desc = node.desc;
|
||||||
|
|
||||||
self.name = node.name;
|
self.name = node.name;
|
||||||
self.type = node.type;
|
self.type = node.type;
|
||||||
self.unicode = node.unicode;
|
self.unicode = node.unicode;
|
||||||
@@ -192,6 +237,7 @@
|
|||||||
|
|
||||||
self.shouldRender = node.shouldRender;
|
self.shouldRender = node.shouldRender;
|
||||||
self.blendMode = node.blendMode;
|
self.blendMode = node.blendMode;
|
||||||
|
self.overflowVisibility = node.overflowVisibility;
|
||||||
|
|
||||||
// dash array needs physical memory copied
|
// dash array needs physical memory copied
|
||||||
CGFloat* nStrokeDashArray = (CGFloat*)malloc(node.strokeDashArrayCount * sizeof(CGFloat));
|
CGFloat* nStrokeDashArray = (CGFloat*)malloc(node.strokeDashArrayCount * sizeof(CGFloat));
|
||||||
@@ -230,9 +276,10 @@
|
|||||||
self.units = IJSVGUnitInherit;
|
self.units = IJSVGUnitInherit;
|
||||||
|
|
||||||
self.blendMode = IJSVGBlendModeNormal;
|
self.blendMode = IJSVGBlendModeNormal;
|
||||||
|
self.overflowVisibility = IJSVGOverflowVisibilityVisible;
|
||||||
|
|
||||||
if (flag) {
|
if (flag == YES) {
|
||||||
def = [[IJSVGDef alloc] init];
|
_def = [[IJSVGDef alloc] init];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -241,146 +288,146 @@
|
|||||||
- (IJSVGDef*)defForID:(NSString*)anID
|
- (IJSVGDef*)defForID:(NSString*)anID
|
||||||
{
|
{
|
||||||
IJSVGDef* aDef = nil;
|
IJSVGDef* aDef = nil;
|
||||||
if ((aDef = [def defForID:anID]) != nil) {
|
if ((aDef = [_def defForID:anID]) != nil) {
|
||||||
return aDef;
|
return aDef;
|
||||||
}
|
}
|
||||||
if (parentNode != nil) {
|
if (_parentNode != nil) {
|
||||||
return [parentNode defForID:anID];
|
return [_parentNode defForID:anID];
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addDef:(IJSVGNode*)aDef
|
- (void)addDef:(IJSVGNode*)aDef
|
||||||
{
|
{
|
||||||
[def addDef:aDef];
|
[_def addDef:aDef];
|
||||||
}
|
}
|
||||||
|
|
||||||
// winding rule can inherit..
|
// winding rule can inherit..
|
||||||
- (IJSVGWindingRule)windingRule
|
- (IJSVGWindingRule)windingRule
|
||||||
{
|
{
|
||||||
if (windingRule == IJSVGWindingRuleInherit && parentNode != nil) {
|
if (_windingRule == IJSVGWindingRuleInherit && _parentNode != nil) {
|
||||||
return parentNode.windingRule;
|
return _parentNode.windingRule;
|
||||||
}
|
}
|
||||||
return windingRule;
|
return _windingRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGLineCapStyle)lineCapStyle
|
- (IJSVGLineCapStyle)lineCapStyle
|
||||||
{
|
{
|
||||||
if (lineCapStyle == IJSVGLineCapStyleInherit) {
|
if (_lineCapStyle == IJSVGLineCapStyleInherit) {
|
||||||
if (parentNode != nil) {
|
if (_parentNode != nil) {
|
||||||
return parentNode.lineCapStyle;
|
return _parentNode.lineCapStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lineCapStyle;
|
return _lineCapStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGLineJoinStyle)lineJoinStyle
|
- (IJSVGLineJoinStyle)lineJoinStyle
|
||||||
{
|
{
|
||||||
if (lineJoinStyle == IJSVGLineJoinStyleInherit) {
|
if (_lineJoinStyle == IJSVGLineJoinStyleInherit) {
|
||||||
if (parentNode != nil) {
|
if (_parentNode != nil) {
|
||||||
return parentNode.lineJoinStyle;
|
return _parentNode.lineJoinStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lineJoinStyle;
|
return _lineJoinStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGUnitLength*)opacity
|
- (IJSVGUnitLength*)opacity
|
||||||
{
|
{
|
||||||
if (opacity.inherit && parentNode != nil) {
|
if (_opacity.inherit && _parentNode != nil) {
|
||||||
return parentNode.opacity;
|
return _parentNode.opacity;
|
||||||
}
|
}
|
||||||
return opacity;
|
return _opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGUnitLength*)fillOpacity
|
- (IJSVGUnitLength*)fillOpacity
|
||||||
{
|
{
|
||||||
if (fillOpacity.inherit && parentNode != nil) {
|
if (_fillOpacity.inherit && _parentNode != nil) {
|
||||||
return parentNode.fillOpacity;
|
return _parentNode.fillOpacity;
|
||||||
}
|
}
|
||||||
return fillOpacity;
|
return _fillOpacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGUnitLength*)strokeWidth
|
- (IJSVGUnitLength*)strokeWidth
|
||||||
{
|
{
|
||||||
if (strokeWidth.inherit && parentNode != nil) {
|
if (_strokeWidth.inherit && _parentNode != nil) {
|
||||||
return parentNode.strokeWidth;
|
return _parentNode.strokeWidth;
|
||||||
}
|
}
|
||||||
return strokeWidth;
|
return _strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (NSColor*)strokeColor
|
- (NSColor*)strokeColor
|
||||||
{
|
{
|
||||||
if (strokeColor != nil)
|
if (_strokeColor != nil)
|
||||||
return strokeColor;
|
return _strokeColor;
|
||||||
if (strokeColor == nil && parentNode != nil)
|
if (_strokeColor == nil && _parentNode != nil)
|
||||||
return parentNode.strokeColor;
|
return _parentNode.strokeColor;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGUnitLength*)strokeOpacity
|
- (IJSVGUnitLength*)strokeOpacity
|
||||||
{
|
{
|
||||||
if (strokeOpacity.inherit && parentNode != nil) {
|
if (_strokeOpacity.inherit && _parentNode != nil) {
|
||||||
return parentNode.strokeOpacity;
|
return _parentNode.strokeOpacity;
|
||||||
}
|
}
|
||||||
return strokeOpacity;
|
return _strokeOpacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// even though the spec explicity states fill color
|
// even though the spec explicity states fill color
|
||||||
// must be on the path, it can also be on the
|
// must be on the path, it can also be on the
|
||||||
- (NSColor*)fillColor
|
- (NSColor*)fillColor
|
||||||
{
|
{
|
||||||
if (fillColor == nil && parentNode != nil) {
|
if (_fillColor == nil && _parentNode != nil) {
|
||||||
return parentNode.fillColor;
|
return _parentNode.fillColor;
|
||||||
}
|
}
|
||||||
return fillColor;
|
return _fillColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGGradient*)fillGradient
|
- (IJSVGGradient*)fillGradient
|
||||||
{
|
{
|
||||||
if (fillGradient == nil && parentNode != nil) {
|
if (_fillGradient == nil && _parentNode != nil) {
|
||||||
return parentNode.fillGradient;
|
return _parentNode.fillGradient;
|
||||||
}
|
}
|
||||||
return fillGradient;
|
return _fillGradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGPattern*)fillPattern
|
- (IJSVGPattern*)fillPattern
|
||||||
{
|
{
|
||||||
if (fillPattern == nil && parentNode != nil) {
|
if (_fillPattern == nil && _parentNode != nil) {
|
||||||
return parentNode.fillPattern;
|
return _parentNode.fillPattern;
|
||||||
}
|
}
|
||||||
return fillPattern;
|
return _fillPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGGradient*)strokeGradient
|
- (IJSVGGradient*)strokeGradient
|
||||||
{
|
{
|
||||||
if (strokeGradient == nil && parentNode != nil) {
|
if (_strokeGradient == nil && _parentNode != nil) {
|
||||||
return parentNode.strokeGradient;
|
return _parentNode.strokeGradient;
|
||||||
}
|
}
|
||||||
return strokeGradient;
|
return _strokeGradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are all recursive, so go up the chain
|
// these are all recursive, so go up the chain
|
||||||
// if they dont exist on this specific node
|
// if they dont exist on this specific node
|
||||||
- (IJSVGPattern*)strokePattern
|
- (IJSVGPattern*)strokePattern
|
||||||
{
|
{
|
||||||
if (strokePattern == nil && parentNode != nil) {
|
if (_strokePattern == nil && _parentNode != nil) {
|
||||||
return parentNode.strokePattern;
|
return _parentNode.strokePattern;
|
||||||
}
|
}
|
||||||
return strokePattern;
|
return _strokePattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGBezierPathAdditions.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
#import "IJSVGNode.h"
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVGGroup;
|
@class IJSVGGroup;
|
||||||
@@ -23,15 +22,14 @@ typedef NS_ENUM(NSInteger, IJSVGPrimitivePathType) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@interface IJSVGPath : IJSVGNode {
|
@interface IJSVGPath : IJSVGNode {
|
||||||
|
|
||||||
NSBezierPath* path;
|
|
||||||
CGPoint lastControlPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, assign) IJSVGPrimitivePathType primitiveType;
|
@property (nonatomic, assign) IJSVGPrimitivePathType primitiveType;
|
||||||
@property (nonatomic, retain) NSBezierPath* path;
|
@property (nonatomic, assign) CGMutablePathRef path;
|
||||||
@property (nonatomic, assign) CGPoint lastControlPoint;
|
@property (nonatomic, assign) CGPoint lastControlPoint;
|
||||||
@property (nonatomic, readonly) CGPathRef CGPath;
|
@property (nonatomic, readonly) CGRect controlPointBoundingBox;
|
||||||
|
@property (nonatomic, readonly) CGRect pathBoundingBox;
|
||||||
|
@property (nonatomic, assign, readonly) BOOL isStroked;
|
||||||
|
|
||||||
- (void)close;
|
- (void)close;
|
||||||
- (NSPoint)currentPoint;
|
- (NSPoint)currentPoint;
|
||||||
|
|||||||
@@ -11,18 +11,11 @@
|
|||||||
|
|
||||||
@implementation IJSVGPath
|
@implementation IJSVGPath
|
||||||
|
|
||||||
@synthesize path = _path;
|
|
||||||
@synthesize lastControlPoint;
|
|
||||||
@synthesize CGPath = _CGPath;
|
|
||||||
@synthesize primitiveType = _primitiveType;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
if (_CGPath != nil) {
|
if(_path != NULL) {
|
||||||
CGPathRelease(_CGPath);
|
(void)CGPathRelease(_path), _path = NULL;
|
||||||
_CGPath = nil;
|
|
||||||
}
|
}
|
||||||
((void)[_path release]), _path = nil;
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +23,7 @@
|
|||||||
{
|
{
|
||||||
if ((self = [super init]) != nil) {
|
if ((self = [super init]) != nil) {
|
||||||
_primitiveType = kIJSVGPrimitivePathTypePath;
|
_primitiveType = kIJSVGPrimitivePathTypePath;
|
||||||
_path = NSBezierPath.bezierPath.retain;
|
_path = CGPathCreateMutable();
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -38,34 +31,45 @@
|
|||||||
- (id)copyWithZone:(NSZone*)zone
|
- (id)copyWithZone:(NSZone*)zone
|
||||||
{
|
{
|
||||||
IJSVGPath* node = [super copyWithZone:zone];
|
IJSVGPath* node = [super copyWithZone:zone];
|
||||||
node.path = [self.path.copy autorelease];
|
node.path = _path;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setPath:(CGMutablePathRef)path
|
||||||
|
{
|
||||||
|
// this will automatically copy any path into a mutable path
|
||||||
|
// regardless of if it was a mutable path to begin with
|
||||||
|
if(_path != NULL) {
|
||||||
|
(void)CGPathRelease(_path), _path = NULL;
|
||||||
|
}
|
||||||
|
_path = CGPathCreateMutableCopy(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)pathBoundingBox
|
||||||
|
{
|
||||||
|
return CGPathGetPathBoundingBox(_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGRect)controlPointBoundingBox
|
||||||
|
{
|
||||||
|
return CGPathGetBoundingBox(_path);
|
||||||
|
}
|
||||||
|
|
||||||
- (NSPoint)currentPoint
|
- (NSPoint)currentPoint
|
||||||
{
|
{
|
||||||
return _path.currentPoint;
|
return CGPathGetCurrentPoint(_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close
|
- (void)close
|
||||||
{
|
{
|
||||||
[_path closePath];
|
CGPathCloseSubpath(_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invlidateCGPath
|
- (BOOL)isStroked
|
||||||
{
|
{
|
||||||
if (_CGPath != nil) {
|
return (self.strokeColor != nil && self.strokeColor.alphaComponent != 0.f) ||
|
||||||
CGPathRelease(_CGPath);
|
self.strokePattern != nil ||
|
||||||
}
|
self.strokeGradient != nil;
|
||||||
_CGPath = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGPathRef)CGPath
|
|
||||||
{
|
|
||||||
if (_CGPath == nil) {
|
|
||||||
_CGPath = [_path newCGPathRef:NO];
|
|
||||||
}
|
|
||||||
return _CGPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGGroup.h"
|
#import <IJSVG/IJSVGGroup.h>
|
||||||
#import "IJSVGImage.h"
|
#import <IJSVG/IJSVGImage.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGPattern : IJSVGGroup {
|
@interface IJSVGPattern : IJSVGGroup {
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGGradient.h"
|
#import <IJSVG/IJSVGGradient.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGRadialGradient : IJSVGGradient
|
@interface IJSVGRadialGradient : IJSVGGradient
|
||||||
+25
-27
@@ -7,33 +7,28 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGRadialGradient.h"
|
#import "IJSVGRadialGradient.h"
|
||||||
|
#import "IJSVGParser.h"
|
||||||
|
|
||||||
@implementation IJSVGRadialGradient
|
@implementation IJSVGRadialGradient
|
||||||
|
|
||||||
@synthesize cx;
|
|
||||||
@synthesize cy;
|
|
||||||
@synthesize fx;
|
|
||||||
@synthesize fy;
|
|
||||||
@synthesize radius;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([cx release]), cx = nil;
|
(void)([_cx release]), _cx = nil;
|
||||||
(void)([cy release]), cy = nil;
|
(void)([_cy release]), _cy = nil;
|
||||||
(void)([fx release]), fx = nil;
|
(void)([_fx release]), _fx = nil;
|
||||||
(void)([fy release]), fy = nil;
|
(void)([_fy release]), _fy = nil;
|
||||||
(void)([radius release]), radius = nil;
|
(void)([_radius release]), _radius = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)copyWithZone:(NSZone*)zone
|
- (id)copyWithZone:(NSZone*)zone
|
||||||
{
|
{
|
||||||
IJSVGRadialGradient* grad = [super copyWithZone:zone];
|
IJSVGRadialGradient* grad = [super copyWithZone:zone];
|
||||||
grad.fx = self.fx;
|
grad.fx = _fx;
|
||||||
grad.fy = self.fy;
|
grad.fy = _fy;
|
||||||
grad.cx = self.cx;
|
grad.cx = _cx;
|
||||||
grad.cy = self.cy;
|
grad.cy = _cy;
|
||||||
grad.radius = self.radius;
|
grad.radius = _radius;
|
||||||
return grad;
|
return grad;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,9 +36,10 @@
|
|||||||
gradient:(IJSVGRadialGradient*)gradient
|
gradient:(IJSVGRadialGradient*)gradient
|
||||||
{
|
{
|
||||||
// cx defaults to 50% if not specified
|
// cx defaults to 50% if not specified
|
||||||
NSDictionary* kv = @{ @"cx" : @"cx",
|
NSDictionary* kv = @{
|
||||||
@"cy" : @"cy",
|
IJSVGAttributeCX : @"cx",
|
||||||
@"r" : @"radius" };
|
IJSVGAttributeCY : @"cy",
|
||||||
|
IJSVGAttributeR : @"radius" };
|
||||||
|
|
||||||
for (NSString* key in kv.allKeys) {
|
for (NSString* key in kv.allKeys) {
|
||||||
NSString* str = [element attributeForName:key].stringValue;
|
NSString* str = [element attributeForName:key].stringValue;
|
||||||
@@ -64,13 +60,13 @@
|
|||||||
gradient.fy = gradient.cy;
|
gradient.fy = gradient.cy;
|
||||||
|
|
||||||
// needs fixing
|
// needs fixing
|
||||||
NSString* fx = [element attributeForName:@"fx"].stringValue;
|
NSString* fx = [element attributeForName:IJSVGAttributeFX].stringValue;
|
||||||
if (fx != nil) {
|
if (fx != nil) {
|
||||||
gradient.fx = [IJSVGUnitLength unitWithString:fx
|
gradient.fx = [IJSVGUnitLength unitWithString:fx
|
||||||
fromUnitType:gradient.units];
|
fromUnitType:gradient.units];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* fy = [element attributeForName:@"fy"].stringValue;
|
NSString* fy = [element attributeForName:IJSVGAttributeFY].stringValue;
|
||||||
if (fx != nil) {
|
if (fx != nil) {
|
||||||
gradient.fy = [IJSVGUnitLength unitWithString:fy
|
gradient.fy = [IJSVGUnitLength unitWithString:fy
|
||||||
fromUnitType:gradient.units];
|
fromUnitType:gradient.units];
|
||||||
@@ -81,7 +77,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSArray* colors = nil;
|
NSArray* colors = nil;
|
||||||
CGFloat* colorStops = [self.class computeColorStopsFromString:element colors:&colors];
|
CGFloat* colorStops = [self.class computeColorStops:gradient
|
||||||
|
colors:&colors];
|
||||||
|
|
||||||
NSGradient* ret = [[[NSGradient alloc] initWithColors:colors
|
NSGradient* ret = [[[NSGradient alloc] initWithColors:colors
|
||||||
atLocations:colorStops
|
atLocations:colorStops
|
||||||
colorSpace:IJSVGColor.defaultColorSpace] autorelease];
|
colorSpace:IJSVGColor.defaultColorSpace] autorelease];
|
||||||
@@ -112,15 +110,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute size based on percentages
|
// compute size based on percentages
|
||||||
CGFloat x = [self.cx computeValue:CGRectGetWidth(boundingBox)];
|
CGFloat x = [_cx computeValue:CGRectGetWidth(boundingBox)];
|
||||||
CGFloat y = [self.cy computeValue:CGRectGetHeight(boundingBox)];
|
CGFloat y = [_cy computeValue:CGRectGetHeight(boundingBox)];
|
||||||
startPoint = CGPointMake(x, y);
|
startPoint = CGPointMake(x, y);
|
||||||
CGFloat val = MIN(CGRectGetWidth(boundingBox),
|
CGFloat val = MIN(CGRectGetWidth(boundingBox),
|
||||||
CGRectGetHeight(boundingBox));
|
CGRectGetHeight(boundingBox));
|
||||||
radius = [self.radius computeValue:val];
|
radius = [_radius computeValue:val];
|
||||||
|
|
||||||
CGFloat ex = [self.fx computeValue:CGRectGetWidth(boundingBox)];
|
CGFloat ex = [_fx computeValue:CGRectGetWidth(boundingBox)];
|
||||||
CGFloat ey = [self.fy computeValue:CGRectGetHeight(boundingBox)];
|
CGFloat ey = [_fy computeValue:CGRectGetHeight(boundingBox)];
|
||||||
|
|
||||||
gradientEndPoint = CGPointMake(ex, ey);
|
gradientEndPoint = CGPointMake(ex, ey);
|
||||||
gradientStartPoint = startPoint;
|
gradientStartPoint = startPoint;
|
||||||
@@ -6,11 +6,9 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGGroup.h"
|
#import <IJSVG/IJSVGGroup.h>
|
||||||
|
|
||||||
@interface IJSVGText : IJSVGGroup {
|
@interface IJSVGText : IJSVGGroup {
|
||||||
|
|
||||||
NSString* text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString* text;
|
@property (nonatomic, copy) NSString* text;
|
||||||
|
|||||||
@@ -10,18 +10,16 @@
|
|||||||
|
|
||||||
@implementation IJSVGText
|
@implementation IJSVGText
|
||||||
|
|
||||||
@synthesize text;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([text release]), text = nil;
|
(void)([_text release]), _text = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGText*)copyWithZone:(NSZone*)zone
|
- (IJSVGText*)copyWithZone:(NSZone*)zone
|
||||||
{
|
{
|
||||||
IJSVGText* node = [super copyWithZone:zone];
|
IJSVGText* node = [super copyWithZone:zone];
|
||||||
node.text = self.text;
|
node.text = _text;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,65 +6,74 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGColor.h"
|
#import <IJSVG/IJSVGColor.h>
|
||||||
#import "IJSVGCommand.h"
|
#import <IJSVG/IJSVGCommand.h>
|
||||||
#import "IJSVGDef.h"
|
#import <IJSVG/IJSVGDef.h>
|
||||||
#import "IJSVGError.h"
|
#import <IJSVG/IJSVGError.h>
|
||||||
#import "IJSVGForeignObject.h"
|
#import <IJSVG/IJSVGForeignObject.h>
|
||||||
#import "IJSVGGroup.h"
|
#import <IJSVG/IJSVGGroup.h>
|
||||||
#import "IJSVGImage.h"
|
#import <IJSVG/IJSVGImage.h>
|
||||||
#import "IJSVGLinearGradient.h"
|
#import <IJSVG/IJSVGLinearGradient.h>
|
||||||
#import "IJSVGPath.h"
|
#import <IJSVG/IJSVGPath.h>
|
||||||
#import "IJSVGPattern.h"
|
#import <IJSVG/IJSVGPattern.h>
|
||||||
#import "IJSVGRadialGradient.h"
|
#import <IJSVG/IJSVGRadialGradient.h>
|
||||||
#import "IJSVGStyleSheet.h"
|
#import <IJSVG/IJSVGStyleSheet.h>
|
||||||
#import "IJSVGText.h"
|
#import <IJSVG/IJSVGText.h>
|
||||||
#import "IJSVGTransform.h"
|
#import <IJSVG/IJSVGTransform.h>
|
||||||
#import "IJSVGUtils.h"
|
#import <IJSVG/IJSVGUnitRect.h>
|
||||||
|
#import <IJSVG/IJSVGUtils.h>
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
static NSString const* IJSVGAttributeViewBox = @"viewBox";
|
extern NSString* const IJSVGAttributeViewBox;
|
||||||
static NSString const* IJSVGAttributeID = @"id";
|
extern NSString* const IJSVGAttributeID;
|
||||||
static NSString const* IJSVGAttributeClass = @"class";
|
extern NSString* const IJSVGAttributeClass;
|
||||||
static NSString const* IJSVGAttributeX = @"x";
|
extern NSString* const IJSVGAttributeX;
|
||||||
static NSString const* IJSVGAttributeY = @"y";
|
extern NSString* const IJSVGAttributeY;
|
||||||
static NSString const* IJSVGAttributeWidth = @"width";
|
extern NSString* const IJSVGAttributeWidth;
|
||||||
static NSString const* IJSVGAttributeHeight = @"height";
|
extern NSString* const IJSVGAttributeHeight;
|
||||||
static NSString const* IJSVGAttributeOpacity = @"opacity";
|
extern NSString* const IJSVGAttributeOpacity;
|
||||||
static NSString const* IJSVGAttributeStrokeOpacity = @"stroke-opacity";
|
extern NSString* const IJSVGAttributeStrokeOpacity;
|
||||||
static NSString const* IJSVGAttributeStrokeWidth = @"stroke-width";
|
extern NSString* const IJSVGAttributeStrokeWidth;
|
||||||
static NSString const* IJSVGAttributeStrokeDashOffset = @"stroke-dashoffset";
|
extern NSString* const IJSVGAttributeStrokeDashOffset;
|
||||||
static NSString const* IJSVGAttributeFillOpacity = @"fill-opacity";
|
extern NSString* const IJSVGAttributeFillOpacity;
|
||||||
static NSString const* IJSVGAttributeClipPath = @"clip-path";
|
extern NSString* const IJSVGAttributeClipPath;
|
||||||
static NSString const* IJSVGAttributeMask = @"mask";
|
extern NSString* const IJSVGAttributeMask;
|
||||||
static NSString const* IJSVGAttributeGradientUnits = @"gradientUnits";
|
extern NSString* const IJSVGAttributeGradientUnits;
|
||||||
static NSString const* IJSVGAttributeMaskUnits = @"maskUnits";
|
extern NSString* const IJSVGAttributeMaskUnits;
|
||||||
static NSString const* IJSVGAttributeMaskContentUnits = @"maskContentUnits";
|
extern NSString* const IJSVGAttributeMaskContentUnits;
|
||||||
static NSString const* IJSVGAttributeTransform = @"transform";
|
extern NSString* const IJSVGAttributeTransform;
|
||||||
static NSString const* IJSVGAttributeGradientTransform = @"gradientTransform";
|
extern NSString* const IJSVGAttributeGradientTransform;
|
||||||
static NSString const* IJSVGAttributeUnicode = @"unicode";
|
extern NSString* const IJSVGAttributeUnicode;
|
||||||
static NSString const* IJSVGAttributeStrokeLineCap = @"stroke-linecap";
|
extern NSString* const IJSVGAttributeStrokeLineCap;
|
||||||
static NSString const* IJSVGAttributeLineJoin = @"stroke-linejoin";
|
extern NSString* const IJSVGAttributeLineJoin;
|
||||||
static NSString const* IJSVGAttributeStroke = @"stroke";
|
extern NSString* const IJSVGAttributeStroke;
|
||||||
static NSString const* IJSVGAttributeStrokeDashArray = @"stroke-dasharray";
|
extern NSString* const IJSVGAttributeStrokeDashArray;
|
||||||
static NSString const* IJSVGAttributeFill = @"fill";
|
extern NSString* const IJSVGAttributeFill;
|
||||||
static NSString const* IJSVGAttributeFillRule = @"fill-rule";
|
extern NSString* const IJSVGAttributeFillRule;
|
||||||
static NSString const* IJSVGAttributeBlendMode = @"mix-blend-mode";
|
extern NSString* const IJSVGAttributeBlendMode;
|
||||||
static NSString const* IJSVGAttributeDisplay = @"display";
|
extern NSString* const IJSVGAttributeDisplay;
|
||||||
static NSString const* IJSVGAttributeStyle = @"style";
|
extern NSString* const IJSVGAttributeStyle;
|
||||||
static NSString const* IJSVGAttributeD = @"d";
|
extern NSString* const IJSVGAttributeD;
|
||||||
static NSString const* IJSVGAttributeXLink = @"xlink:href";
|
extern NSString* const IJSVGAttributeXLink;
|
||||||
static NSString const* IJSVGAttributeX1 = @"x1";
|
extern NSString* const IJSVGAttributeX1;
|
||||||
static NSString const* IJSVGAttributeX2 = @"x2";
|
extern NSString* const IJSVGAttributeX2;
|
||||||
static NSString const* IJSVGAttributeY1 = @"y1";
|
extern NSString* const IJSVGAttributeY1;
|
||||||
static NSString const* IJSVGAttributeY2 = @"y2";
|
extern NSString* const IJSVGAttributeY2;
|
||||||
static NSString const* IJSVGAttributeRX = @"rx";
|
extern NSString* const IJSVGAttributeRX;
|
||||||
static NSString const* IJSVGAttributeRY = @"ry";
|
extern NSString* const IJSVGAttributeRY;
|
||||||
static NSString const* IJSVGAttributeCX = @"cx";
|
extern NSString* const IJSVGAttributeCX;
|
||||||
static NSString const* IJSVGAttributeCY = @"cy";
|
extern NSString* const IJSVGAttributeCY;
|
||||||
static NSString const* IJSVGAttributeR = @"r";
|
extern NSString* const IJSVGAttributeR;
|
||||||
static NSString const* IJSVGAttributePoints = @"points";
|
extern NSString* const IJSVGAttributeFX;
|
||||||
|
extern NSString* const IJSVGAttributeFY;
|
||||||
|
extern NSString* const IJSVGAttributePoints;
|
||||||
|
extern NSString* const IJSVGAttributeOffset;
|
||||||
|
extern NSString* const IJSVGAttributeStopColor;
|
||||||
|
extern NSString* const IJSVGAttributeStopOpacity;
|
||||||
|
extern NSString* const IJSVGAttributeHref;
|
||||||
|
extern NSString* const IJSVGAttributeOverflow;
|
||||||
|
|
||||||
|
|
||||||
@class IJSVGParser;
|
@class IJSVGParser;
|
||||||
|
|
||||||
@@ -84,17 +93,13 @@ static NSString const* IJSVGAttributePoints = @"points";
|
|||||||
|
|
||||||
@interface IJSVGParser : IJSVGGroup {
|
@interface IJSVGParser : IJSVGGroup {
|
||||||
|
|
||||||
NSRect viewBox;
|
|
||||||
NSSize proposedViewSize;
|
|
||||||
|
|
||||||
@private
|
@private
|
||||||
id<IJSVGParserDelegate> _delegate;
|
id<IJSVGParserDelegate> _delegate;
|
||||||
NSXMLDocument* _document;
|
NSXMLDocument* _document;
|
||||||
NSMutableArray* _glyphs;
|
NSMutableArray<IJSVGPath*>* _glyphs;
|
||||||
IJSVGStyleSheet* _styleSheet;
|
IJSVGStyleSheet* _styleSheet;
|
||||||
NSMutableArray* _parsedNodes;
|
NSMutableDictionary<NSString*, NSXMLElement*>* _defNodes;
|
||||||
NSMutableDictionary* _defNodes;
|
NSMutableDictionary<NSString*, NSXMLElement*>* _baseDefNodes;
|
||||||
NSMutableDictionary* _baseDefNodes;
|
|
||||||
NSMutableArray<IJSVG*>* _svgs;
|
NSMutableArray<IJSVG*>* _svgs;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -107,7 +112,7 @@ static NSString const* IJSVGAttributePoints = @"points";
|
|||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, readonly) NSRect viewBox;
|
@property (nonatomic, readonly) NSRect viewBox;
|
||||||
@property (nonatomic, readonly) NSSize proposedViewSize;
|
@property (nonatomic, readonly) IJSVGUnitSize* intrinsicSize;
|
||||||
|
|
||||||
+ (BOOL)isDataSVG:(NSData*)data;
|
+ (BOOL)isDataSVG:(NSData*)data;
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,85 @@
|
|||||||
#import "IJSVG.h"
|
#import "IJSVG.h"
|
||||||
#import "IJSVGParser.h"
|
#import "IJSVGParser.h"
|
||||||
|
|
||||||
|
NSString* const IJSVGAttributeViewBox = @"viewBox";
|
||||||
|
NSString* const IJSVGAttributeID = @"id";
|
||||||
|
NSString* const IJSVGAttributeClass = @"class";
|
||||||
|
NSString* const IJSVGAttributeX = @"x";
|
||||||
|
NSString* const IJSVGAttributeY = @"y";
|
||||||
|
NSString* const IJSVGAttributeWidth = @"width";
|
||||||
|
NSString* const IJSVGAttributeHeight = @"height";
|
||||||
|
NSString* const IJSVGAttributeOpacity = @"opacity";
|
||||||
|
NSString* const IJSVGAttributeStrokeOpacity = @"stroke-opacity";
|
||||||
|
NSString* const IJSVGAttributeStrokeWidth = @"stroke-width";
|
||||||
|
NSString* const IJSVGAttributeStrokeDashOffset = @"stroke-dashoffset";
|
||||||
|
NSString* const IJSVGAttributeFillOpacity = @"fill-opacity";
|
||||||
|
NSString* const IJSVGAttributeClipPath = @"clip-path";
|
||||||
|
NSString* const IJSVGAttributeMask = @"mask";
|
||||||
|
NSString* const IJSVGAttributeGradientUnits = @"gradientUnits";
|
||||||
|
NSString* const IJSVGAttributeMaskUnits = @"maskUnits";
|
||||||
|
NSString* const IJSVGAttributeMaskContentUnits = @"maskContentUnits";
|
||||||
|
NSString* const IJSVGAttributeTransform = @"transform";
|
||||||
|
NSString* const IJSVGAttributeGradientTransform = @"gradientTransform";
|
||||||
|
NSString* const IJSVGAttributeUnicode = @"unicode";
|
||||||
|
NSString* const IJSVGAttributeStrokeLineCap = @"stroke-linecap";
|
||||||
|
NSString* const IJSVGAttributeLineJoin = @"stroke-linejoin";
|
||||||
|
NSString* const IJSVGAttributeStroke = @"stroke";
|
||||||
|
NSString* const IJSVGAttributeStrokeDashArray = @"stroke-dasharray";
|
||||||
|
NSString* const IJSVGAttributeFill = @"fill";
|
||||||
|
NSString* const IJSVGAttributeFillRule = @"fill-rule";
|
||||||
|
NSString* const IJSVGAttributeBlendMode = @"mix-blend-mode";
|
||||||
|
NSString* const IJSVGAttributeDisplay = @"display";
|
||||||
|
NSString* const IJSVGAttributeStyle = @"style";
|
||||||
|
NSString* const IJSVGAttributeD = @"d";
|
||||||
|
NSString* const IJSVGAttributeXLink = @"xlink:href";
|
||||||
|
NSString* const IJSVGAttributeX1 = @"x1";
|
||||||
|
NSString* const IJSVGAttributeX2 = @"x2";
|
||||||
|
NSString* const IJSVGAttributeY1 = @"y1";
|
||||||
|
NSString* const IJSVGAttributeY2 = @"y2";
|
||||||
|
NSString* const IJSVGAttributeRX = @"rx";
|
||||||
|
NSString* const IJSVGAttributeRY = @"ry";
|
||||||
|
NSString* const IJSVGAttributeCX = @"cx";
|
||||||
|
NSString* const IJSVGAttributeCY = @"cy";
|
||||||
|
NSString* const IJSVGAttributeR = @"r";
|
||||||
|
NSString* const IJSVGAttributeFX = @"fx";
|
||||||
|
NSString* const IJSVGAttributeFY = @"fy";
|
||||||
|
NSString* const IJSVGAttributePoints = @"points";
|
||||||
|
NSString* const IJSVGAttributeOffset = @"offset";
|
||||||
|
NSString* const IJSVGAttributeStopColor = @"stop-color";
|
||||||
|
NSString* const IJSVGAttributeStopOpacity = @"stop-opacity";
|
||||||
|
NSString* const IJSVGAttributeHref = @"href";
|
||||||
|
NSString* const IJSVGAttributeOverflow = @"overflow";
|
||||||
|
|
||||||
@implementation IJSVGParser
|
@implementation IJSVGParser
|
||||||
|
|
||||||
@synthesize viewBox;
|
static NSDictionary* _IJSVGAttributeDictionaryFloats = nil;
|
||||||
@synthesize proposedViewSize;
|
static NSDictionary* _IJSVGAttributeDictionaryNodes = nil;
|
||||||
|
static NSDictionary* _IJSVGAttributeDictionaryUnits = nil;
|
||||||
|
static NSDictionary* _IJSVGAttributeDictionaryTransforms = nil;
|
||||||
|
|
||||||
|
+ (void)load
|
||||||
|
{
|
||||||
|
_IJSVGAttributeDictionaryFloats = [@{
|
||||||
|
IJSVGAttributeX : @"x",
|
||||||
|
IJSVGAttributeY : @"y",
|
||||||
|
IJSVGAttributeWidth : @"width",
|
||||||
|
IJSVGAttributeHeight : @"height",
|
||||||
|
IJSVGAttributeOpacity : @"opacity",
|
||||||
|
IJSVGAttributeStrokeOpacity : @"strokeOpacity",
|
||||||
|
IJSVGAttributeStrokeWidth : @"strokeWidth",
|
||||||
|
IJSVGAttributeStrokeDashOffset : @"strokeDashOffset",
|
||||||
|
IJSVGAttributeFillOpacity : @"fillOpacity" } retain];
|
||||||
|
_IJSVGAttributeDictionaryNodes = [@{
|
||||||
|
IJSVGAttributeClipPath : @"clipPath",
|
||||||
|
IJSVGAttributeMask : @"mask" } retain];
|
||||||
|
_IJSVGAttributeDictionaryUnits = [@{
|
||||||
|
IJSVGAttributeGradientUnits : @"units",
|
||||||
|
IJSVGAttributeMaskUnits : @"units",
|
||||||
|
IJSVGAttributeMaskContentUnits : @"contentUnits"} retain];
|
||||||
|
_IJSVGAttributeDictionaryTransforms = [@{
|
||||||
|
IJSVGAttributeTransform : @"transforms",
|
||||||
|
IJSVGAttributeGradientTransform : @"transforms" } retain];
|
||||||
|
}
|
||||||
|
|
||||||
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL
|
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL
|
||||||
{
|
{
|
||||||
@@ -42,10 +117,10 @@
|
|||||||
{
|
{
|
||||||
(void)([_glyphs release]), _glyphs = nil;
|
(void)([_glyphs release]), _glyphs = nil;
|
||||||
(void)([_styleSheet release]), _styleSheet = nil;
|
(void)([_styleSheet release]), _styleSheet = nil;
|
||||||
(void)([_parsedNodes release]), _parsedNodes = nil;
|
|
||||||
(void)([_defNodes release]), _defNodes = nil;
|
(void)([_defNodes release]), _defNodes = nil;
|
||||||
(void)([_baseDefNodes release]), _baseDefNodes = nil;
|
(void)([_baseDefNodes release]), _baseDefNodes = nil;
|
||||||
(void)([_svgs release]), _svgs = nil;
|
(void)([_svgs release]), _svgs = nil;
|
||||||
|
(void)([_intrinsicSize release]), _intrinsicSize = nil;
|
||||||
if (_commandDataStream != NULL) {
|
if (_commandDataStream != NULL) {
|
||||||
(void)IJSVGPathDataStreamRelease(_commandDataStream), _commandDataStream = nil;
|
(void)IJSVGPathDataStreamRelease(_commandDataStream), _commandDataStream = nil;
|
||||||
}
|
}
|
||||||
@@ -64,11 +139,7 @@
|
|||||||
_respondsTo.handleSubSVG = [_delegate respondsToSelector:@selector(svgParser:foundSubSVG:withSVGString:)];
|
_respondsTo.handleSubSVG = [_delegate respondsToSelector:@selector(svgParser:foundSubSVG:withSVGString:)];
|
||||||
|
|
||||||
_commandDataStream = IJSVGPathDataStreamCreateDefault();
|
_commandDataStream = IJSVGPathDataStreamCreateDefault();
|
||||||
_glyphs = [[NSMutableArray alloc] init];
|
|
||||||
_parsedNodes = [[NSMutableArray alloc] init];
|
|
||||||
_defNodes = [[NSMutableDictionary alloc] init];
|
_defNodes = [[NSMutableDictionary alloc] init];
|
||||||
_baseDefNodes = [[NSMutableDictionary alloc] init];
|
|
||||||
_svgs = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
// load the document / file, assume its UTF8
|
// load the document / file, assume its UTF8
|
||||||
|
|
||||||
@@ -181,7 +252,7 @@
|
|||||||
|
|
||||||
- (NSSize)size
|
- (NSSize)size
|
||||||
{
|
{
|
||||||
return viewBox.size;
|
return _viewBox.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_parse
|
- (void)_parse
|
||||||
@@ -195,35 +266,47 @@
|
|||||||
|
|
||||||
// find the sizebox!
|
// find the sizebox!
|
||||||
NSXMLNode* attribute = nil;
|
NSXMLNode* attribute = nil;
|
||||||
if ((attribute = [svgElement attributeForName:(NSString*)IJSVGAttributeViewBox]) != nil) {
|
if ((attribute = [svgElement attributeForName:IJSVGAttributeViewBox]) != nil) {
|
||||||
// we have a viewbox...
|
// we have a viewbox...
|
||||||
CGFloat* box = [IJSVGUtils parseViewBox:[attribute stringValue]];
|
CGFloat* box = [IJSVGUtils parseViewBox:attribute.stringValue];
|
||||||
viewBox = NSMakeRect(box[0], box[1], box[2], box[3]);
|
_viewBox = NSMakeRect(box[0], box[1], box[2], box[3]);
|
||||||
free(box);
|
(void)free(box);
|
||||||
} else {
|
} else {
|
||||||
// there is no view box so find the width and height
|
// there is no view box so find the width and height
|
||||||
CGFloat w = [svgElement attributeForName:(NSString*)IJSVGAttributeWidth].stringValue.floatValue;
|
NSString* wAtt = [svgElement attributeForName:IJSVGAttributeWidth].stringValue;
|
||||||
CGFloat h = [svgElement attributeForName:(NSString*)IJSVGAttributeHeight].stringValue.floatValue;
|
NSString* hAtt = [svgElement attributeForName:IJSVGAttributeHeight].stringValue;
|
||||||
|
IJSVGUnitLength* wLength = [IJSVGUnitLength unitWithString:wAtt];
|
||||||
|
IJSVGUnitLength* hLength = [IJSVGUnitLength unitWithString:hAtt];
|
||||||
|
|
||||||
|
// its possible wlength or hlength are nil
|
||||||
|
CGFloat w = wLength ? wLength.value : 0.f;
|
||||||
|
CGFloat h = hLength ? hLength.value : 0.f;
|
||||||
|
|
||||||
if (h == 0.f && w != 0.f) {
|
if (h == 0.f && w != 0.f) {
|
||||||
h = w;
|
h = w;
|
||||||
} else if (w == 0.f && h != 0.f) {
|
} else if (w == 0.f && h != 0.f) {
|
||||||
w = h;
|
w = h;
|
||||||
}
|
}
|
||||||
viewBox = NSMakeRect(0.f, 0.f, w, h);
|
_viewBox = NSMakeRect(0.f, 0.f, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the width and height....
|
// parse the width and height....
|
||||||
CGFloat w = [svgElement attributeForName:(NSString*)IJSVGAttributeWidth].stringValue.floatValue;
|
NSString* w = [svgElement attributeForName:IJSVGAttributeWidth].stringValue;
|
||||||
CGFloat h = [svgElement attributeForName:(NSString*)IJSVGAttributeHeight].stringValue.floatValue;
|
NSString* h = [svgElement attributeForName:IJSVGAttributeHeight].stringValue;
|
||||||
if (w == 0.f && h == 0.f) {
|
|
||||||
w = viewBox.size.width;
|
// by default just the the width and height from the viewbox unless
|
||||||
h = viewBox.size.height;
|
// specified otherwise
|
||||||
} else if (w == 0 && h != 0.f) {
|
IJSVGUnitLength* wl = [IJSVGUnitLength unitWithFloat:_viewBox.size.width];
|
||||||
w = viewBox.size.width;
|
IJSVGUnitLength* hl = [IJSVGUnitLength unitWithFloat:_viewBox.size.height];
|
||||||
} else if (h == 0 && w != 0.f) {
|
if (w != nil) {
|
||||||
h = viewBox.size.height;
|
wl = [IJSVGUnitLength unitWithString:w];
|
||||||
}
|
}
|
||||||
proposedViewSize = NSMakeSize(w, h);
|
if (h != nil) {
|
||||||
|
hl = [IJSVGUnitLength unitWithString:h];
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the width and height
|
||||||
|
_intrinsicSize = [IJSVGUnitSize sizeWithWidth:wl height:hl].retain;
|
||||||
|
|
||||||
// the root element is SVG, so iterate over its children
|
// the root element is SVG, so iterate over its children
|
||||||
// recursively
|
// recursively
|
||||||
@@ -232,16 +315,8 @@
|
|||||||
intoGroup:self
|
intoGroup:self
|
||||||
def:NO];
|
def:NO];
|
||||||
|
|
||||||
// now everything has been done we need to compute the style tree
|
|
||||||
for (NSDictionary* dict in _parsedNodes) {
|
|
||||||
[self _postParseElementForCommonAttributes:dict[@"element"]
|
|
||||||
node:dict[@"node"]
|
|
||||||
ignoreAttributes:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
// dont need the style sheet or the parsed nodes as this point
|
// dont need the style sheet or the parsed nodes as this point
|
||||||
(void)([_styleSheet release]), _styleSheet = nil;
|
(void)([_styleSheet release]), _styleSheet = nil;
|
||||||
(void)([_parsedNodes release]), _parsedNodes = nil;
|
|
||||||
(void)([_defNodes release]), _defNodes = nil;
|
(void)([_defNodes release]), _defNodes = nil;
|
||||||
(void)IJSVGPathDataStreamRelease(_commandDataStream), _commandDataStream = NULL;
|
(void)IJSVGPathDataStreamRelease(_commandDataStream), _commandDataStream = NULL;
|
||||||
}
|
}
|
||||||
@@ -317,22 +392,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// floats
|
// floats
|
||||||
atts(@{ (NSString*)IJSVGAttributeX : @"x",
|
atts(_IJSVGAttributeDictionaryFloats,
|
||||||
(NSString*)IJSVGAttributeY : @"y",
|
|
||||||
(NSString*)IJSVGAttributeWidth : @"width",
|
|
||||||
(NSString*)IJSVGAttributeHeight : @"height",
|
|
||||||
(NSString*)IJSVGAttributeOpacity : @"opacity",
|
|
||||||
(NSString*)IJSVGAttributeStrokeOpacity : @"strokeOpacity",
|
|
||||||
(NSString*)IJSVGAttributeStrokeWidth : @"strokeWidth",
|
|
||||||
(NSString*)IJSVGAttributeStrokeDashOffset : @"strokeDashOffset",
|
|
||||||
(NSString*)IJSVGAttributeFillOpacity : @"fillOpacity" },
|
|
||||||
^id(NSString* value) {
|
^id(NSString* value) {
|
||||||
return [IJSVGUnitLength unitWithString:value];
|
return [IJSVGUnitLength unitWithString:value];
|
||||||
});
|
});
|
||||||
|
|
||||||
// nodes
|
// nodes
|
||||||
atts(@{ (NSString*)IJSVGAttributeClipPath : @"clipPath",
|
atts(_IJSVGAttributeDictionaryNodes,
|
||||||
(NSString*)IJSVGAttributeMask : @"mask" },
|
|
||||||
^id(NSString* value) {
|
^id(NSString* value) {
|
||||||
NSString* url = [IJSVGUtils defURL:value];
|
NSString* url = [IJSVGUtils defURL:value];
|
||||||
if (url != nil) {
|
if (url != nil) {
|
||||||
@@ -342,16 +408,13 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// units
|
// units
|
||||||
atts(@{ (NSString*)IJSVGAttributeGradientUnits : @"units",
|
atts(_IJSVGAttributeDictionaryUnits,
|
||||||
(NSString*)IJSVGAttributeMaskUnits : @"units",
|
|
||||||
(NSString*)IJSVGAttributeMaskContentUnits : @"contentUnits" },
|
|
||||||
^id(NSString* value) {
|
^id(NSString* value) {
|
||||||
return @([IJSVGUtils unitTypeForString:value]);
|
return @([IJSVGUtils unitTypeForString:value]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// transforms
|
// transforms
|
||||||
atts(@{ (NSString*)IJSVGAttributeTransform : @"transforms",
|
atts(_IJSVGAttributeDictionaryTransforms,
|
||||||
(NSString*)IJSVGAttributeGradientTransform : @"transforms" },
|
|
||||||
^(NSString* value) {
|
^(NSString* value) {
|
||||||
NSMutableArray* tempTransforms = [[[NSMutableArray alloc] init] autorelease];
|
NSMutableArray* tempTransforms = [[[NSMutableArray alloc] init] autorelease];
|
||||||
[tempTransforms addObjectsFromArray:[IJSVGTransform transformsForString:value]];
|
[tempTransforms addObjectsFromArray:[IJSVGTransform transformsForString:value]];
|
||||||
@@ -418,7 +481,6 @@
|
|||||||
if (fillDefID != nil) {
|
if (fillDefID != nil) {
|
||||||
// find the object
|
// find the object
|
||||||
id obj = [self definedObjectForID:fillDefID];
|
id obj = [self definedObjectForID:fillDefID];
|
||||||
|
|
||||||
// what type is it?
|
// what type is it?
|
||||||
if ([obj isKindOfClass:[IJSVGGradient class]]) {
|
if ([obj isKindOfClass:[IJSVGGradient class]]) {
|
||||||
node.fillGradient = (IJSVGGradient*)obj;
|
node.fillGradient = (IJSVGGradient*)obj;
|
||||||
@@ -454,6 +516,52 @@
|
|||||||
node.shouldRender = NO;
|
node.shouldRender = NO;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// offset
|
||||||
|
attr(IJSVGAttributeOffset, ^(NSString* value) {
|
||||||
|
node.offset = [IJSVGUnitLength unitWithString:value];
|
||||||
|
});
|
||||||
|
|
||||||
|
// stop-opacity
|
||||||
|
attr(IJSVGAttributeStopOpacity, ^(NSString* value) {
|
||||||
|
node.fillOpacity = [IJSVGUnitLength unitWithString:value];
|
||||||
|
});
|
||||||
|
|
||||||
|
// stop-color
|
||||||
|
attr(IJSVGAttributeStopColor, ^(NSString* value) {
|
||||||
|
node.fillColor = [IJSVGColor colorFromString:value];
|
||||||
|
if(node.fillOpacity.value != 1.f) {
|
||||||
|
node.fillColor = [IJSVGColor changeAlphaOnColor:node.fillColor
|
||||||
|
to:node.fillOpacity.value];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// overflow
|
||||||
|
attr(IJSVGAttributeOverflow, ^(NSString* value) {
|
||||||
|
if([value.lowercaseString isEqualToString:@"hidden"]) {
|
||||||
|
node.overflowVisibility = IJSVGOverflowVisibilityHidden;
|
||||||
|
} else {
|
||||||
|
node.overflowVisibility = IJSVGOverflowVisibilityVisible;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// is there a title or desc?
|
||||||
|
for(NSXMLElement* childElement in element.children) {
|
||||||
|
IJSVGNodeType type = [IJSVGNode typeForString:childElement.localName
|
||||||
|
kind:childElement.kind];
|
||||||
|
switch(type) {
|
||||||
|
case IJSVGNodeTypeTitle: {
|
||||||
|
node.title = childElement.stringValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IJSVGNodeTypeDesc: {
|
||||||
|
node.desc = childElement.stringValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)definedObjectForID:(NSString*)anID
|
- (id)definedObjectForID:(NSString*)anID
|
||||||
@@ -483,25 +591,28 @@
|
|||||||
|
|
||||||
- (BOOL)isFont
|
- (BOOL)isFont
|
||||||
{
|
{
|
||||||
return [_glyphs count] != 0;
|
return _glyphs != nil && [_glyphs count] != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*)glyphs
|
- (NSArray*)glyphs
|
||||||
{
|
{
|
||||||
return _glyphs;
|
return _glyphs ?: @[];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addSubSVG:(IJSVG*)anSVG
|
- (void)addSubSVG:(IJSVG*)anSVG
|
||||||
{
|
{
|
||||||
|
if (_svgs == nil) {
|
||||||
|
_svgs = [[NSMutableArray alloc] init];
|
||||||
|
}
|
||||||
[_svgs addObject:anSVG];
|
[_svgs addObject:anSVG];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive
|
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive
|
||||||
{
|
{
|
||||||
if (recursive == NO) {
|
if (recursive == NO) {
|
||||||
return _svgs;
|
return _svgs ?: @[];
|
||||||
}
|
}
|
||||||
NSMutableArray* svgs = [[[NSMutableArray alloc] init] autorelease];
|
NSMutableArray<IJSVG*>* svgs = [[[NSMutableArray alloc] init] autorelease];
|
||||||
for (IJSVG* anSVG in svgs) {
|
for (IJSVG* anSVG in svgs) {
|
||||||
[svgs addObject:anSVG];
|
[svgs addObject:anSVG];
|
||||||
[svgs addObjectsFromArray:[anSVG subSVGs:recursive]];
|
[svgs addObjectsFromArray:[anSVG subSVGs:recursive]];
|
||||||
@@ -509,8 +620,11 @@
|
|||||||
return svgs;
|
return svgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addGlyph:(IJSVGNode*)glyph
|
- (void)addGlyph:(IJSVGPath*)glyph
|
||||||
{
|
{
|
||||||
|
if (_glyphs == nil) {
|
||||||
|
_glyphs = [[NSMutableArray alloc] init];
|
||||||
|
}
|
||||||
[_glyphs addObject:glyph];
|
[_glyphs addObject:glyph];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,9 +642,17 @@
|
|||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
// mask
|
// mask
|
||||||
case IJSVGNodeTypeMask: {
|
case IJSVGNodeTypeMask: {
|
||||||
|
node.overflowVisibility = IJSVGOverflowVisibilityHidden;
|
||||||
node.units = IJSVGUnitObjectBoundingBox;
|
node.units = IJSVGUnitObjectBoundingBox;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clippath
|
||||||
|
case IJSVGNodeTypeClipPath: {
|
||||||
|
node.units = IJSVGUnitObjectBoundingBox;
|
||||||
|
node.overflowVisibility = IJSVGOverflowVisibilityHidden;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// gradient
|
// gradient
|
||||||
case IJSVGNodeTypeRadialGradient:
|
case IJSVGNodeTypeRadialGradient:
|
||||||
@@ -581,7 +703,10 @@
|
|||||||
default: {
|
default: {
|
||||||
// just a default def, continue on, as we are a def element,
|
// just a default def, continue on, as we are a def element,
|
||||||
// store these seperately to the default ID string ones
|
// store these seperately to the default ID string ones
|
||||||
NSString* defID = [childDef attributeForName:@"id"].stringValue;
|
if (_baseDefNodes == nil) {
|
||||||
|
_baseDefNodes = [[NSMutableDictionary alloc] init];
|
||||||
|
}
|
||||||
|
NSString* defID = [childDef attributeForName:IJSVGAttributeID].stringValue;
|
||||||
if (defID != nil) {
|
if (defID != nil) {
|
||||||
_baseDefNodes[defID] = childDef;
|
_baseDefNodes[defID] = childDef;
|
||||||
}
|
}
|
||||||
@@ -635,8 +760,8 @@
|
|||||||
// if its a sub svg, we can remove the attributes for x and y
|
// if its a sub svg, we can remove the attributes for x and y
|
||||||
// this is required or it could go out of bounds before the exporter
|
// this is required or it could go out of bounds before the exporter
|
||||||
// hits the layers from the groups :)
|
// hits the layers from the groups :)
|
||||||
[element removeAttributeForName:@"x"];
|
[element removeAttributeForName:IJSVGAttributeX];
|
||||||
[element removeAttributeForName:@"y"];
|
[element removeAttributeForName:IJSVGAttributeY];
|
||||||
|
|
||||||
// work out the SVG
|
// work out the SVG
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
@@ -668,8 +793,8 @@
|
|||||||
case IJSVGNodeTypeGlyph: {
|
case IJSVGNodeTypeGlyph: {
|
||||||
|
|
||||||
// no path data
|
// no path data
|
||||||
if ([element attributeForName:(NSString*)IJSVGAttributeD] == nil ||
|
if ([element attributeForName:IJSVGAttributeD] == nil ||
|
||||||
[[element attributeForName:(NSString*)IJSVGAttributeD] stringValue].length == 0) {
|
[[element attributeForName:IJSVGAttributeD] stringValue].length == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,14 +810,14 @@
|
|||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
|
|
||||||
// pass the commands for it
|
// pass the commands for it
|
||||||
[self _parsePathCommandData:[[element attributeForName:(NSString*)IJSVGAttributeD] stringValue]
|
[self _parsePathCommandData:[[element attributeForName:IJSVGAttributeD] stringValue]
|
||||||
intoPath:path];
|
intoPath:path];
|
||||||
|
|
||||||
// check the size...
|
// check the size...
|
||||||
if (NSIsEmptyRect([path path].controlPointBounds)) {
|
if (CGRectIsEmpty(path.controlPointBoundingBox) == YES) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the glyph
|
// add the glyph
|
||||||
[self addGlyph:path];
|
[self addGlyph:path];
|
||||||
break;
|
break;
|
||||||
@@ -750,7 +875,7 @@
|
|||||||
[self _parseElementForCommonAttributes:element
|
[self _parseElementForCommonAttributes:element
|
||||||
node:path
|
node:path
|
||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
[self _parsePathCommandData:[[element attributeForName:(NSString*)IJSVGAttributeD] stringValue]
|
[self _parsePathCommandData:[[element attributeForName:IJSVGAttributeD] stringValue]
|
||||||
intoPath:path];
|
intoPath:path];
|
||||||
|
|
||||||
[parentGroup addDef:path];
|
[parentGroup addDef:path];
|
||||||
@@ -819,7 +944,7 @@
|
|||||||
[self _setupDefaultsForNode:path];
|
[self _setupDefaultsForNode:path];
|
||||||
[self _parseElementForCommonAttributes:element
|
[self _parseElementForCommonAttributes:element
|
||||||
node:path
|
node:path
|
||||||
ignoreAttributes:@[ @"x", @"y" ]];
|
ignoreAttributes:@[ IJSVGAttributeX, IJSVGAttributeY ]];
|
||||||
[parentGroup addDef:path];
|
[parentGroup addDef:path];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -891,7 +1016,7 @@
|
|||||||
// use
|
// use
|
||||||
case IJSVGNodeTypeUse: {
|
case IJSVGNodeTypeUse: {
|
||||||
|
|
||||||
NSString* xlink = [[element attributeForName:(NSString*)IJSVGAttributeXLink] stringValue];
|
NSString* xlink = [[self resolveXLinkAttributeForElement:element] stringValue];
|
||||||
NSString* xlinkID = [xlink substringFromIndex:1];
|
NSString* xlinkID = [xlink substringFromIndex:1];
|
||||||
IJSVGNode* node = [self definedObjectForID:xlinkID];
|
IJSVGNode* node = [self definedObjectForID:xlinkID];
|
||||||
|
|
||||||
@@ -902,7 +1027,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// due to this being a carbon clone, we need to clear the ID
|
// due to this being a carbon clone, we need to clear the ID
|
||||||
if ([element attributeForName:(NSString*)IJSVGAttributeID] == nil) {
|
if ([element attributeForName:IJSVGAttributeID] == nil) {
|
||||||
node.identifier = nil;
|
node.identifier = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -914,8 +1039,8 @@
|
|||||||
node.intermediateParentNode = subGroup;
|
node.intermediateParentNode = subGroup;
|
||||||
|
|
||||||
// is there a width and height?
|
// is there a width and height?
|
||||||
CGFloat x = [element attributeForName:(NSString*)IJSVGAttributeX].stringValue.floatValue;
|
CGFloat x = [element attributeForName:IJSVGAttributeX].stringValue.floatValue;
|
||||||
CGFloat y = [element attributeForName:(NSString*)IJSVGAttributeY].stringValue.floatValue;
|
CGFloat y = [element attributeForName:IJSVGAttributeY].stringValue.floatValue;
|
||||||
|
|
||||||
// we need to add a transform to the subgroup
|
// we need to add a transform to the subgroup
|
||||||
subGroup.transforms = @[ [IJSVGTransform transformByTranslatingX:x y:y] ];
|
subGroup.transforms = @[ [IJSVGTransform transformByTranslatingX:x y:y] ];
|
||||||
@@ -928,17 +1053,30 @@
|
|||||||
// says ignore x, y, width, height and xlink:href...
|
// says ignore x, y, width, height and xlink:href...
|
||||||
[self _parseElementForCommonAttributes:element
|
[self _parseElementForCommonAttributes:element
|
||||||
node:node
|
node:node
|
||||||
ignoreAttributes:@[ @"x", @"y", @"width",
|
ignoreAttributes:@[IJSVGAttributeX, IJSVGAttributeY,
|
||||||
@"height", @"xlink:href" ]];
|
IJSVGAttributeWidth, IJSVGAttributeHeight,
|
||||||
|
IJSVGAttributeXLink]];
|
||||||
|
|
||||||
[parentGroup addDef:node];
|
[parentGroup addDef:node];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stop color
|
||||||
|
case IJSVGNodeTypeStop: {
|
||||||
|
IJSVGNode* node = [[[IJSVGNode alloc] init] autorelease];
|
||||||
|
node.type = IJSVGNodeTypeStop;
|
||||||
|
[self _setupDefaultsForNode:node];
|
||||||
|
[self _parseElementForCommonAttributes:element
|
||||||
|
node:node
|
||||||
|
ignoreAttributes:nil];
|
||||||
|
[parentGroup addChild:node];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// linear gradient
|
// linear gradient
|
||||||
case IJSVGNodeTypeLinearGradient: {
|
case IJSVGNodeTypeLinearGradient: {
|
||||||
|
|
||||||
NSString* xlink = [[element attributeForName:(NSString*)IJSVGAttributeXLink] stringValue];
|
NSString* xlink = [[self resolveXLinkAttributeForElement:element] stringValue];
|
||||||
NSString* xlinkID = [xlink substringFromIndex:1];
|
NSString* xlinkID = [xlink substringFromIndex:1];
|
||||||
NSXMLElement* referenceElement;
|
NSXMLElement* referenceElement;
|
||||||
IJSVGNode* node = [self definedObjectForID:xlinkID
|
IJSVGNode* node = [self definedObjectForID:xlinkID
|
||||||
@@ -954,6 +1092,9 @@
|
|||||||
[self _parseElementForCommonAttributes:elementCopy
|
[self _parseElementForCommonAttributes:elementCopy
|
||||||
node:grad
|
node:grad
|
||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
|
[self _parseBlock:elementCopy
|
||||||
|
intoGroup:grad
|
||||||
|
def:NO];
|
||||||
grad.gradient = [IJSVGLinearGradient parseGradient:elementCopy
|
grad.gradient = [IJSVGLinearGradient parseGradient:elementCopy
|
||||||
gradient:grad];
|
gradient:grad];
|
||||||
[parentGroup addDef:grad];
|
[parentGroup addDef:grad];
|
||||||
@@ -966,6 +1107,9 @@
|
|||||||
[self _parseElementForCommonAttributes:element
|
[self _parseElementForCommonAttributes:element
|
||||||
node:gradient
|
node:gradient
|
||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
|
[self _parseBlock:element
|
||||||
|
intoGroup:gradient
|
||||||
|
def:NO];
|
||||||
gradient.gradient = [IJSVGLinearGradient parseGradient:element
|
gradient.gradient = [IJSVGLinearGradient parseGradient:element
|
||||||
gradient:gradient];
|
gradient:gradient];
|
||||||
[parentGroup addDef:gradient];
|
[parentGroup addDef:gradient];
|
||||||
@@ -975,7 +1119,7 @@
|
|||||||
// radial gradient
|
// radial gradient
|
||||||
case IJSVGNodeTypeRadialGradient: {
|
case IJSVGNodeTypeRadialGradient: {
|
||||||
|
|
||||||
NSString* xlink = [[element attributeForName:(NSString*)IJSVGAttributeXLink] stringValue];
|
NSString* xlink = [[self resolveXLinkAttributeForElement:element] stringValue];
|
||||||
NSString* xlinkID = [xlink substringFromIndex:1];
|
NSString* xlinkID = [xlink substringFromIndex:1];
|
||||||
NSXMLElement* referenceElement;
|
NSXMLElement* referenceElement;
|
||||||
IJSVGNode* node = [self definedObjectForID:xlinkID
|
IJSVGNode* node = [self definedObjectForID:xlinkID
|
||||||
@@ -991,6 +1135,9 @@
|
|||||||
[self _parseElementForCommonAttributes:elementCopy
|
[self _parseElementForCommonAttributes:elementCopy
|
||||||
node:grad
|
node:grad
|
||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
|
[self _parseBlock:elementCopy
|
||||||
|
intoGroup:grad
|
||||||
|
def:NO];
|
||||||
grad.gradient = [IJSVGRadialGradient parseGradient:elementCopy
|
grad.gradient = [IJSVGRadialGradient parseGradient:elementCopy
|
||||||
gradient:grad];
|
gradient:grad];
|
||||||
[parentGroup addDef:grad];
|
[parentGroup addDef:grad];
|
||||||
@@ -1003,6 +1150,9 @@
|
|||||||
[self _parseElementForCommonAttributes:element
|
[self _parseElementForCommonAttributes:element
|
||||||
node:gradient
|
node:gradient
|
||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
|
[self _parseBlock:element
|
||||||
|
intoGroup:gradient
|
||||||
|
def:NO];
|
||||||
gradient.gradient = [IJSVGRadialGradient parseGradient:element
|
gradient.gradient = [IJSVGRadialGradient parseGradient:element
|
||||||
gradient:gradient];
|
gradient:gradient];
|
||||||
[parentGroup addDef:gradient];
|
[parentGroup addDef:gradient];
|
||||||
@@ -1064,8 +1214,9 @@
|
|||||||
ignoreAttributes:nil];
|
ignoreAttributes:nil];
|
||||||
|
|
||||||
// from base64
|
// from base64
|
||||||
NSString* string = [element attributeForName:(NSString*)IJSVGAttributeXLink].stringValue;
|
NSXMLNode* attributeNode = [self resolveXLinkAttributeForElement:element] ?:
|
||||||
[image loadFromBase64EncodedString:string];
|
[element attributeForName:IJSVGAttributeHref];
|
||||||
|
[image loadFromString:attributeNode.stringValue];
|
||||||
|
|
||||||
// add to parent
|
// add to parent
|
||||||
[parentGroup addChild:image];
|
[parentGroup addChild:image];
|
||||||
@@ -1075,6 +1226,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSXMLNode*)resolveXLinkAttributeForElement:(NSXMLElement*)element
|
||||||
|
{
|
||||||
|
NSString* const namespaceURI = @"http://www.w3.org/1999/xlink";
|
||||||
|
NSXMLNode* attributeNode = [element attributeForLocalName:IJSVGAttributeHref
|
||||||
|
URI:namespaceURI];
|
||||||
|
if (attributeNode == nil) {
|
||||||
|
attributeNode = [element attributeForName:IJSVGAttributeXLink];
|
||||||
|
}
|
||||||
|
return attributeNode;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSXMLElement*)mergedElement:(NSXMLElement*)element
|
- (NSXMLElement*)mergedElement:(NSXMLElement*)element
|
||||||
withReferenceElement:(NSXMLElement*)reference
|
withReferenceElement:(NSXMLElement*)reference
|
||||||
{
|
{
|
||||||
@@ -1104,22 +1266,14 @@
|
|||||||
|
|
||||||
#pragma mark Parser stuff!
|
#pragma mark Parser stuff!
|
||||||
|
|
||||||
- (void)_parsePathCommandData:(NSString*)command
|
- (void)_parsePathCommandDataBuffer:(const char*)buffer
|
||||||
intoPath:(IJSVGPath*)path
|
intoPath:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
// invalid command
|
NSUInteger len = strlen(buffer);
|
||||||
if (command == nil || command.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate memory for the string buffer for reading
|
|
||||||
NSUInteger len = command.length;
|
|
||||||
NSUInteger lastIndex = len - 1;
|
NSUInteger lastIndex = len - 1;
|
||||||
const char* buffer = command.UTF8String;
|
|
||||||
|
|
||||||
// make sure we plus 1 for the null byte
|
|
||||||
char* charBuffer = (char*)malloc(sizeof(char) * (len + 1));
|
|
||||||
|
|
||||||
|
// make sure we plus 1 for the null byte
|
||||||
|
char* charBuffer = (char*)malloc(sizeof(char)*(len + 1));
|
||||||
NSInteger start = 0;
|
NSInteger start = 0;
|
||||||
IJSVGCommand* _currentCommand = nil;
|
IJSVGCommand* _currentCommand = nil;
|
||||||
for (NSInteger i = 0; i < len; i++) {
|
for (NSInteger i = 0; i < len; i++) {
|
||||||
@@ -1130,20 +1284,26 @@
|
|||||||
|
|
||||||
// copy memory from current buffer
|
// copy memory from current buffer
|
||||||
NSInteger index = ((i + 1) - start);
|
NSInteger index = ((i + 1) - start);
|
||||||
memcpy(&charBuffer[0], &buffer[start], sizeof(char) * index);
|
memcpy(&charBuffer[0], &buffer[start], sizeof(char)*index);
|
||||||
charBuffer[index] = '\0';
|
charBuffer[index] = '\0';
|
||||||
|
|
||||||
// create the command from the substring
|
// create the command from the substring
|
||||||
NSString* commandString = [NSString stringWithUTF8String:charBuffer];
|
unsigned long length = index + 1;
|
||||||
|
size_t mlength = sizeof(char)*length;
|
||||||
|
char* commandString = (char*)malloc(mlength);
|
||||||
|
memcpy(commandString, &charBuffer[0], mlength);
|
||||||
|
|
||||||
// reset start position
|
// reset start position
|
||||||
start = (i + 1);
|
start = (i + 1);
|
||||||
|
|
||||||
// previous command is actual subcommand
|
// previous command is actual subcommand
|
||||||
IJSVGCommand* previousCommand = _currentCommand.subCommands.lastObject;
|
IJSVGCommand* previousCommand = _currentCommand.subCommands.lastObject;
|
||||||
IJSVGCommand* cCommand = [self _parseCommandString:commandString
|
IJSVGCommand* cCommand = [self _parseCommandStringBuffer:commandString
|
||||||
previousCommand:previousCommand
|
previousCommand:previousCommand
|
||||||
intoPath:path];
|
intoPath:path];
|
||||||
|
|
||||||
|
// free the memory as at this point, we are done with it
|
||||||
|
(void)free(commandString), commandString = NULL;
|
||||||
|
|
||||||
// retain the current one
|
// retain the current one
|
||||||
if (cCommand != nil) {
|
if (cCommand != nil) {
|
||||||
@@ -1151,12 +1311,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(charBuffer);
|
(void)free(charBuffer), charBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IJSVGCommand*)_parseCommandString:(NSString*)string
|
- (void)_parsePathCommandData:(NSString*)command
|
||||||
previousCommand:(IJSVGCommand*)previousCommand
|
intoPath:(IJSVGPath*)path
|
||||||
intoPath:(IJSVGPath*)path
|
{
|
||||||
|
// invalid command
|
||||||
|
if (command == nil || command.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate memory for the string buffer for reading
|
||||||
|
const char* buffer = command.UTF8String;
|
||||||
|
[self _parsePathCommandDataBuffer:buffer
|
||||||
|
intoPath:path];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IJSVGCommand*)_parseCommandStringBuffer:(const char*)buffer
|
||||||
|
previousCommand:(IJSVGCommand*)previousCommand
|
||||||
|
intoPath:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
// work out the last command - the reason this is so long is because the command
|
// work out the last command - the reason this is so long is because the command
|
||||||
// could be a series of the same commands, so work it out by the number of parameters
|
// could be a series of the same commands, so work it out by the number of parameters
|
||||||
@@ -1168,9 +1342,10 @@
|
|||||||
|
|
||||||
// main commands
|
// main commands
|
||||||
// Class commandClass = [IJSVGCommand classFor]
|
// Class commandClass = [IJSVGCommand classFor]
|
||||||
Class commandClass = [IJSVGCommand commandClassForCommandChar:[string characterAtIndex:0]];
|
Class commandClass = [IJSVGCommand commandClassForCommandChar:buffer[0]];
|
||||||
IJSVGCommand* command = (IJSVGCommand*)[[[commandClass alloc] initWithCommandString:string
|
IJSVGCommand* command = nil;
|
||||||
dataStream:_commandDataStream] autorelease];
|
command = (IJSVGCommand*)[[[commandClass alloc] initWithCommandStringBuffer:buffer
|
||||||
|
dataStream:_commandDataStream] autorelease];
|
||||||
for (IJSVGCommand* subCommand in command.subCommands) {
|
for (IJSVGCommand* subCommand in command.subCommands) {
|
||||||
[command.class runWithParams:subCommand.parameters
|
[command.class runWithParams:subCommand.parameters
|
||||||
paramCount:subCommand.parameterCount
|
paramCount:subCommand.parameterCount
|
||||||
@@ -1189,41 +1364,44 @@
|
|||||||
// convert a line into a command,
|
// convert a line into a command,
|
||||||
// basically MX1 Y1LX2 Y2
|
// basically MX1 Y1LX2 Y2
|
||||||
path.primitiveType = kIJSVGPrimitivePathTypeLine;
|
path.primitiveType = kIJSVGPrimitivePathTypeLine;
|
||||||
CGFloat x1 = [element attributeForName:(NSString*)IJSVGAttributeX1].stringValue.floatValue;
|
CGFloat x1 = [element attributeForName:IJSVGAttributeX1].stringValue.floatValue;
|
||||||
CGFloat y1 = [element attributeForName:(NSString*)IJSVGAttributeY1].stringValue.floatValue;
|
CGFloat y1 = [element attributeForName:IJSVGAttributeY1].stringValue.floatValue;
|
||||||
CGFloat x2 = [element attributeForName:(NSString*)IJSVGAttributeX2].stringValue.floatValue;
|
CGFloat x2 = [element attributeForName:IJSVGAttributeX2].stringValue.floatValue;
|
||||||
CGFloat y2 = [element attributeForName:(NSString*)IJSVGAttributeY2].stringValue.floatValue;
|
CGFloat y2 = [element attributeForName:IJSVGAttributeY2].stringValue.floatValue;
|
||||||
|
|
||||||
// use sprintf as its quicker then stringWithFormat...
|
// use sprintf as its quicker then stringWithFormat...
|
||||||
char buffer[50];
|
char* buffer;
|
||||||
sprintf(buffer, "M%.2f %.2fL%.2f %.2f", x1, y1, x2, y2);
|
asprintf(&buffer, "M%.2f %.2fL%.2f %.2f", x1, y1, x2, y2);
|
||||||
NSString* command = [NSString stringWithCString:buffer
|
[self _parsePathCommandDataBuffer:buffer
|
||||||
encoding:NSUTF8StringEncoding];
|
intoPath:path];
|
||||||
[self _parsePathCommandData:command
|
(void)free(buffer);
|
||||||
intoPath:path];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_parseCircle:(NSXMLElement*)element
|
- (void)_parseCircle:(NSXMLElement*)element
|
||||||
intoPath:(IJSVGPath*)path
|
intoPath:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
path.primitiveType = kIJSVGPrimitivePathTypeCircle;
|
path.primitiveType = kIJSVGPrimitivePathTypeCircle;
|
||||||
CGFloat cX = [element attributeForName:(NSString*)IJSVGAttributeCX].stringValue.floatValue;
|
CGFloat cX = [element attributeForName:IJSVGAttributeCX].stringValue.floatValue;
|
||||||
CGFloat cY = [element attributeForName:(NSString*)IJSVGAttributeCY].stringValue.floatValue;
|
CGFloat cY = [element attributeForName:IJSVGAttributeCY].stringValue.floatValue;
|
||||||
CGFloat r = [element attributeForName:(NSString*)IJSVGAttributeR].stringValue.floatValue;
|
CGFloat r = [element attributeForName:IJSVGAttributeR].stringValue.floatValue;
|
||||||
NSRect rect = NSMakeRect(cX - r, cY - r, r * 2, r * 2);
|
CGRect rect = CGRectMake(cX - r, cY - r, r * 2, r * 2);
|
||||||
path.path = [NSBezierPath bezierPathWithOvalInRect:rect];
|
CGPathRef nPath = CGPathCreateWithEllipseInRect(rect, NULL);
|
||||||
|
path.path = (CGMutablePathRef)nPath;
|
||||||
|
CGPathRelease(nPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_parseEllipse:(NSXMLElement*)element
|
- (void)_parseEllipse:(NSXMLElement*)element
|
||||||
intoPath:(IJSVGPath*)path
|
intoPath:(IJSVGPath*)path
|
||||||
{
|
{
|
||||||
path.primitiveType = kIJSVGPrimitivePathTypeEllipse;
|
path.primitiveType = kIJSVGPrimitivePathTypeEllipse;
|
||||||
CGFloat cX = [element attributeForName:(NSString*)IJSVGAttributeCX].stringValue.floatValue;
|
CGFloat cX = [element attributeForName:IJSVGAttributeCX].stringValue.floatValue;
|
||||||
CGFloat cY = [element attributeForName:(NSString*)IJSVGAttributeCY].stringValue.floatValue;
|
CGFloat cY = [element attributeForName:IJSVGAttributeCY].stringValue.floatValue;
|
||||||
CGFloat rX = [element attributeForName:(NSString*)IJSVGAttributeRX].stringValue.floatValue;
|
CGFloat rX = [element attributeForName:IJSVGAttributeRX].stringValue.floatValue;
|
||||||
CGFloat rY = [element attributeForName:(NSString*)IJSVGAttributeRY].stringValue.floatValue;
|
CGFloat rY = [element attributeForName:IJSVGAttributeRY].stringValue.floatValue;
|
||||||
NSRect rect = NSMakeRect(cX - rX, cY - rY, rX * 2, rY * 2);
|
NSRect rect = NSMakeRect(cX - rX, cY - rY, rX * 2, rY * 2);
|
||||||
path.path = [NSBezierPath bezierPathWithOvalInRect:rect];
|
CGPathRef nPath = CGPathCreateWithEllipseInRect(rect, NULL);
|
||||||
|
path.path = (CGMutablePathRef)nPath;
|
||||||
|
CGPathRelease(nPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_parsePolyline:(NSXMLElement*)element
|
- (void)_parsePolyline:(NSXMLElement*)element
|
||||||
@@ -1248,7 +1426,7 @@
|
|||||||
intoPath:(IJSVGPath*)path
|
intoPath:(IJSVGPath*)path
|
||||||
closePath:(BOOL)closePath
|
closePath:(BOOL)closePath
|
||||||
{
|
{
|
||||||
NSString* points = [element attributeForName:(NSString*)IJSVGAttributePoints].stringValue;
|
NSString* points = [element attributeForName:IJSVGAttributePoints].stringValue;
|
||||||
NSInteger count = 0;
|
NSInteger count = 0;
|
||||||
CGFloat* params = [IJSVGUtils commandParameters:points
|
CGFloat* params = [IJSVGUtils commandParameters:points
|
||||||
count:&count];
|
count:&count];
|
||||||
@@ -1258,23 +1436,49 @@
|
|||||||
free(params);
|
free(params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct a command
|
const int defBufferSize = 10;
|
||||||
NSInteger capacity = count / 2;
|
char* buffer;
|
||||||
if (closePath == YES) {
|
asprintf(&buffer, "M%f %f L", params[0], params[1]);
|
||||||
capacity += 1;
|
|
||||||
|
// compute a default buffer - bSize is strlen + 1 for null byte
|
||||||
|
size_t bSize = strlen(buffer) + 1;
|
||||||
|
size_t strLength = bSize - 1;
|
||||||
|
|
||||||
|
// for every pair of coordinates
|
||||||
|
for(int i = 2; i < count; i+= 2) {
|
||||||
|
char* subbuf;
|
||||||
|
asprintf(&subbuf, "%f %f ", params[i], params[i + 1]);
|
||||||
|
size_t sSize = strlen(subbuf);
|
||||||
|
|
||||||
|
// if the new size of the string is large than the buffer
|
||||||
|
// increase the buffer up another def size - note, we always
|
||||||
|
// plus 2 incase the close path needs to be appended on the end
|
||||||
|
if((strLength + sSize + 2) > bSize) {
|
||||||
|
size_t nLength = MAX(sSize, defBufferSize) + 2;
|
||||||
|
buffer = realloc(buffer, sizeof(char)*(bSize+nLength));
|
||||||
|
bSize += nLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the string onto the buffer, increment the
|
||||||
|
// string length and free the subbuffer memory
|
||||||
|
strcat(buffer, subbuf);
|
||||||
|
strLength += sSize;
|
||||||
|
(void)free(subbuf), subbuf = NULL;
|
||||||
}
|
}
|
||||||
NSMutableString* str = [[[NSMutableString alloc] initWithCapacity:capacity] autorelease];
|
|
||||||
[str appendFormat:@"M%f,%f L", params[0], params[1]];
|
// append the close path if required
|
||||||
for (NSInteger i = 2; i < count; i += 2) {
|
if(closePath == YES) {
|
||||||
[str appendFormat:@"%f,%f ", params[i], params[i + 1]];
|
strcat(buffer, "z");
|
||||||
}
|
}
|
||||||
if (closePath) {
|
|
||||||
[str appendString:@"z"];
|
// actually perform the parse
|
||||||
}
|
[self _parsePathCommandDataBuffer:buffer
|
||||||
[self _parsePathCommandData:str
|
intoPath:path];
|
||||||
intoPath:path];
|
|
||||||
free(params);
|
// free the params
|
||||||
|
(void)free(buffer), buffer = NULL;
|
||||||
|
(void)free(params), params = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_parseRect:(NSXMLElement*)element
|
- (void)_parseRect:(NSXMLElement*)element
|
||||||
@@ -1282,27 +1486,28 @@
|
|||||||
{
|
{
|
||||||
path.primitiveType = kIJSVGPrimitivePathTypeRect;
|
path.primitiveType = kIJSVGPrimitivePathTypeRect;
|
||||||
// width and height
|
// width and height
|
||||||
CGFloat width = [IJSVGUtils floatValue:[element attributeForName:(NSString*)IJSVGAttributeWidth].stringValue
|
CGFloat width = [IJSVGUtils floatValue:[element attributeForName:IJSVGAttributeWidth].stringValue
|
||||||
fallBackForPercent:self.viewBox.size.width];
|
fallBackForPercent:self.viewBox.size.width];
|
||||||
|
|
||||||
CGFloat height = [IJSVGUtils floatValue:[element attributeForName:(NSString*)IJSVGAttributeHeight].stringValue
|
CGFloat height = [IJSVGUtils floatValue:[element attributeForName:IJSVGAttributeHeight].stringValue
|
||||||
fallBackForPercent:self.viewBox.size.height];
|
fallBackForPercent:self.viewBox.size.height];
|
||||||
|
|
||||||
// rect uses x and y as start of path, not move path object -_-
|
// rect uses x and y as start of path, not move path object -_-
|
||||||
CGFloat x = [IJSVGUtils floatValue:[element attributeForName:(NSString*)IJSVGAttributeX].stringValue
|
CGFloat x = [IJSVGUtils floatValue:[element attributeForName:IJSVGAttributeX].stringValue
|
||||||
fallBackForPercent:self.viewBox.size.width];
|
fallBackForPercent:self.viewBox.size.width];
|
||||||
CGFloat y = [IJSVGUtils floatValue:[element attributeForName:(NSString*)IJSVGAttributeY].stringValue
|
CGFloat y = [IJSVGUtils floatValue:[element attributeForName:IJSVGAttributeY].stringValue
|
||||||
fallBackForPercent:self.viewBox.size.height];
|
fallBackForPercent:self.viewBox.size.height];
|
||||||
|
|
||||||
// radius
|
// radius
|
||||||
CGFloat rX = [element attributeForName:(NSString*)IJSVGAttributeRX].stringValue.floatValue;
|
CGFloat rX = [element attributeForName:IJSVGAttributeRX].stringValue.floatValue;
|
||||||
CGFloat rY = [element attributeForName:(NSString*)IJSVGAttributeRY].stringValue.floatValue;
|
CGFloat rY = [element attributeForName:IJSVGAttributeRY].stringValue.floatValue;
|
||||||
if ([element attributeForName:(NSString*)IJSVGAttributeRY] == nil) {
|
if ([element attributeForName:IJSVGAttributeRY] == nil) {
|
||||||
rY = rX;
|
rY = rX;
|
||||||
}
|
}
|
||||||
path.path = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(x, y, width, height)
|
CGRect rect = CGRectMake(x, y, width, height);
|
||||||
xRadius:rX
|
CGPathRef nPath = CGPathCreateWithRoundedRect(rect, rX, rY, NULL);
|
||||||
yRadius:rY];
|
path.path = (CGMutablePathRef)nPath;
|
||||||
|
CGPathRelease(nPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGNode.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
#import "IJSVGRenderingStyle.h"
|
#import <IJSVG/IJSVGRenderingStyle.h>
|
||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
@class IJSVGLayer;
|
@class IJSVGLayer;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
@implementation IJSVGLayerTree
|
@implementation IJSVGLayerTree
|
||||||
|
|
||||||
@synthesize viewBox;
|
|
||||||
@synthesize style = _style;
|
@synthesize style = _style;
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
@@ -74,59 +73,40 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
// any x and y?
|
// any x and y?
|
||||||
CGFloat x = [node.x computeValue:layer.frame.size.width];
|
CGRect frame = layer.bounds;
|
||||||
CGFloat y = [node.y computeValue:layer.frame.size.height];
|
CGFloat x = [node.x computeValue:frame.size.width];
|
||||||
|
CGFloat y = [node.y computeValue:frame.size.height];
|
||||||
|
|
||||||
// do some magic transform
|
// no need to do anything if no transform, or x or y == 0
|
||||||
if (transforms.count == 0 && x == 0.f && y == 0.f) {
|
if (transforms.count == 0 && x == 0.f && y == 0.f) {
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// simply cascade all the transforms onto the identity
|
||||||
|
CGAffineTransform identity = CGAffineTransformIdentity;
|
||||||
if (x != 0.f || y != 0.f) {
|
if (x != 0.f || y != 0.f) {
|
||||||
// we must add translate to the stack
|
identity = CGAffineTransformTranslate(identity, x, y);
|
||||||
NSMutableArray* trans = nil;
|
|
||||||
if (transforms != nil) {
|
|
||||||
trans = [[transforms mutableCopy] autorelease];
|
|
||||||
} else {
|
|
||||||
trans = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
|
|
||||||
}
|
|
||||||
[trans addObject:[IJSVGTransform transformByTranslatingX:x y:y]];
|
|
||||||
transforms = trans;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add any transforms
|
// this used to be done with each transform being added to its own
|
||||||
IJSVGLayer* topLayer = nil;
|
// group layer, but we can simply use one and then apply
|
||||||
IJSVGLayer* parentLayer = nil;
|
// the transforms in reverse order, has same outcome with less memory
|
||||||
|
IJSVGGroupLayer* parentLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
||||||
for (IJSVGTransform* transform in transforms) {
|
for(IJSVGTransform* transform in transforms.reverseObjectEnumerator) {
|
||||||
// make sure we apply the transform to the parent
|
identity = CGAffineTransformConcat(identity, transform.CGAffineTransform);
|
||||||
// so they stack
|
|
||||||
IJSVGGroupLayer* childLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
|
||||||
childLayer.affineTransform = transform.CGAffineTransform;
|
|
||||||
|
|
||||||
// add it to the parent layer
|
|
||||||
if (parentLayer != nil) {
|
|
||||||
[parentLayer addSublayer:childLayer];
|
|
||||||
} else {
|
|
||||||
// make sure we keep track of the top most layer
|
|
||||||
topLayer = childLayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset parent layer to the new child
|
|
||||||
parentLayer = childLayer;
|
|
||||||
}
|
}
|
||||||
|
parentLayer.affineTransform = identity;
|
||||||
// swap the layer around
|
|
||||||
[parentLayer addSublayer:layer];
|
[parentLayer addSublayer:layer];
|
||||||
layer = topLayer;
|
return parentLayer;
|
||||||
return layer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyDefaultsToLayer:(IJSVGLayer*)layer
|
- (void)applyDefaultsToLayer:(IJSVGLayer*)layer
|
||||||
fromNode:(IJSVGNode*)node
|
fromNode:(IJSVGNode*)node
|
||||||
{
|
{
|
||||||
CGFloat opacity = node.opacity.value;
|
CGFloat opacity = node.opacity.value;
|
||||||
layer.opacity = opacity;
|
if(opacity != 1.f) {
|
||||||
|
layer.opacity = opacity;
|
||||||
|
}
|
||||||
|
|
||||||
// setup the blending mode
|
// setup the blending mode
|
||||||
if (node.blendMode != IJSVGBlendModeNormal) {
|
if (node.blendMode != IJSVGBlendModeNormal) {
|
||||||
@@ -164,14 +144,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
IJSVGGroupLayer* groupLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
IJSVGGroupLayer* groupLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
||||||
for (IJSVGNode* node in group.children) {
|
for (IJSVGNode* node in group.childNodes) {
|
||||||
[groupLayer addSublayer:[self layerForNode:node]];
|
[groupLayer addSublayer:[self layerForNode:node]];
|
||||||
}
|
}
|
||||||
groupLayer.frame = (CGRect){
|
groupLayer.frame = (CGRect) {
|
||||||
.origin = CGPointZero,
|
.origin = CGPointZero,
|
||||||
.size = (CGSize){
|
.size = (CGSize) {
|
||||||
.width = group.width.value,
|
.width = group.width.value,
|
||||||
.height = group.height.value }
|
.height = group.height.value
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// mask it - forgot groups can have masks too, doh! simple
|
// mask it - forgot groups can have masks too, doh! simple
|
||||||
@@ -204,7 +185,7 @@
|
|||||||
// setup path and layer
|
// setup path and layer
|
||||||
IJSVGShapeLayer* layer = [[[IJSVGShapeLayer alloc] init] autorelease];
|
IJSVGShapeLayer* layer = [[[IJSVGShapeLayer alloc] init] autorelease];
|
||||||
layer.primitiveType = path.primitiveType;
|
layer.primitiveType = path.primitiveType;
|
||||||
CGPathRef introPath = path.CGPath;
|
CGPathRef introPath = path.path;
|
||||||
|
|
||||||
*originalBoundingBox = CGRectIntegral(CGPathGetBoundingBox(introPath));
|
*originalBoundingBox = CGRectIntegral(CGPathGetBoundingBox(introPath));
|
||||||
layer.originalPathOrigin = (*originalBoundingBox).origin;
|
layer.originalPathOrigin = (*originalBoundingBox).origin;
|
||||||
@@ -299,9 +280,14 @@
|
|||||||
NSColor* fColor = path.fillColor;
|
NSColor* fColor = path.fillColor;
|
||||||
BOOL hasColor = (fColor.alphaComponent == 0.f || fColor == nil) == NO;
|
BOOL hasColor = (fColor.alphaComponent == 0.f || fColor == nil) == NO;
|
||||||
BOOL hasFill = path.fillPattern != nil || path.fillGradient != nil;
|
BOOL hasFill = path.fillPattern != nil || path.fillGradient != nil;
|
||||||
|
|
||||||
|
// is there an overriding style in the sheet?
|
||||||
if (_style.fillColor && (hasFill || hasColor || fColor == nil)) {
|
if (_style.fillColor && (hasFill || hasColor || fColor == nil)) {
|
||||||
fColor = _style.fillColor;
|
fColor = _style.fillColor;
|
||||||
} else if (fColor != nil && path.fillOpacity.value != 1.f) {
|
}
|
||||||
|
|
||||||
|
// if there is a color, change the opacity if required
|
||||||
|
if (fColor != nil && path.fillOpacity.value != 1.f) {
|
||||||
fColor = [IJSVGColor changeAlphaOnColor:fColor
|
fColor = [IJSVGColor changeAlphaOnColor:fColor
|
||||||
to:path.fillOpacity.value];
|
to:path.fillOpacity.value];
|
||||||
}
|
}
|
||||||
@@ -442,7 +428,7 @@
|
|||||||
// the gradient drawing layer
|
// the gradient drawing layer
|
||||||
gradient.colorList = _style.colorList;
|
gradient.colorList = _style.colorList;
|
||||||
IJSVGGradientLayer* gradLayer = [[[IJSVGGradientLayer alloc] init] autorelease];
|
IJSVGGradientLayer* gradLayer = [[[IJSVGGradientLayer alloc] init] autorelease];
|
||||||
gradLayer.viewBox = self.viewBox;
|
gradLayer.viewBox = _viewBox;
|
||||||
gradLayer.frame = layer.bounds;
|
gradLayer.frame = layer.bounds;
|
||||||
gradLayer.gradient = gradient;
|
gradLayer.gradient = gradient;
|
||||||
gradLayer.absoluteTransform = [self absoluteTransform:path];
|
gradLayer.absoluteTransform = [self absoluteTransform:path];
|
||||||
@@ -603,7 +589,9 @@
|
|||||||
|
|
||||||
// dashing
|
// dashing
|
||||||
strokeLayer.lineDashPhase = path.strokeDashOffset.value;
|
strokeLayer.lineDashPhase = path.strokeDashOffset.value;
|
||||||
strokeLayer.lineDashPattern = [self lineDashPattern:path];
|
if(path.strokeDashArrayCount != 0.f) {
|
||||||
|
strokeLayer.lineDashPattern = [self lineDashPattern:path];
|
||||||
|
}
|
||||||
|
|
||||||
return strokeLayer;
|
return strokeLayer;
|
||||||
}
|
}
|
||||||
@@ -616,15 +604,13 @@
|
|||||||
IJSVGGroupLayer* maskLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
IJSVGGroupLayer* maskLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
|
||||||
|
|
||||||
// add clip mask
|
// add clip mask
|
||||||
if (node.clipPath != nil) {
|
if (node.clipPath != nil && node.clipPath.overflowVisibility == IJSVGOverflowVisibilityHidden) {
|
||||||
IJSVGLayer* clip = [self layerForNode:node.clipPath];
|
IJSVGLayer* clip = [self layerForNode:node.clipPath];
|
||||||
|
|
||||||
// adjust the frame
|
// adjust the frame
|
||||||
if (node.clipPath.units == IJSVGUnitObjectBoundingBox) {
|
if (node.clipPath.units == IJSVGUnitObjectBoundingBox) {
|
||||||
[self adjustLayer:clip
|
[self adjustLayer:clip
|
||||||
toParentLayerFrame:layer];
|
toParentLayerFrame:layer];
|
||||||
} else {
|
|
||||||
clip.affineTransform = [self absoluteTransform:node];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the layer
|
// add the layer
|
||||||
@@ -632,27 +618,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add the actual mask
|
// add the actual mask
|
||||||
if (node.mask != nil) {
|
if (node.mask != nil && node.mask.overflowVisibility == IJSVGOverflowVisibilityHidden) {
|
||||||
IJSVGLayer* mask = [self layerForNode:node.mask];
|
IJSVGLayer* mask = [self layerForNode:node.mask];
|
||||||
|
|
||||||
// only move if bounding box
|
// only move if bounding box
|
||||||
if (node.mask.units == IJSVGUnitObjectBoundingBox) {
|
if (node.mask.units == IJSVGUnitObjectBoundingBox) {
|
||||||
[self adjustLayer:mask
|
[self adjustLayer:mask
|
||||||
toParentLayerFrame:layer];
|
toParentLayerFrame:layer];
|
||||||
} else {
|
|
||||||
mask.affineTransform = [self absoluteTransform:node];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the layer
|
// add the layer
|
||||||
[maskLayer addSublayer:mask];
|
[maskLayer addSublayer:mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursive colourize for each item
|
|
||||||
[self _recursiveColorLayersFromLayer:maskLayer
|
|
||||||
withColor:[IJSVGColor computeColorSpace:NSColor.whiteColor].CGColor];
|
|
||||||
|
|
||||||
// add the mask
|
// add the mask
|
||||||
layer.mask = maskLayer;
|
if(maskLayer.sublayers.count != 0) {
|
||||||
|
// recursive colourize for each item
|
||||||
|
NSColor* color = [IJSVGColor computeColorSpace:NSColor.whiteColor];
|
||||||
|
[self _recursiveColorLayersFromLayer:maskLayer
|
||||||
|
withColor:color.CGColor];
|
||||||
|
layer.mask = maskLayer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,54 +678,54 @@
|
|||||||
|
|
||||||
- (NSArray<NSNumber*>*)lineDashPattern:(IJSVGNode*)node
|
- (NSArray<NSNumber*>*)lineDashPattern:(IJSVGNode*)node
|
||||||
{
|
{
|
||||||
NSMutableArray* arr = [[[NSMutableArray alloc] init] autorelease];
|
NSMutableArray* arr = [[[NSMutableArray alloc] initWithCapacity:node.strokeDashArrayCount] autorelease];
|
||||||
for (NSInteger i = 0; i < node.strokeDashArrayCount; i++) {
|
for (NSInteger i = 0; i < node.strokeDashArrayCount; i++) {
|
||||||
[arr addObject:@((CGFloat)node.strokeDashArray[i])];
|
[arr addObject:@((CGFloat)node.strokeDashArray[i])];
|
||||||
}
|
}
|
||||||
return [[arr copy] autorelease];
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)lineJoin:(IJSVGLineJoinStyle)joinStyle
|
- (NSString*)lineJoin:(IJSVGLineJoinStyle)joinStyle
|
||||||
{
|
{
|
||||||
switch (joinStyle) {
|
switch (joinStyle) {
|
||||||
default:
|
default:
|
||||||
case IJSVGLineJoinStyleMiter: {
|
case IJSVGLineJoinStyleMiter: {
|
||||||
return kCALineJoinMiter;
|
return kCALineJoinMiter;
|
||||||
}
|
}
|
||||||
case IJSVGLineJoinStyleBevel: {
|
case IJSVGLineJoinStyleBevel: {
|
||||||
return kCALineJoinBevel;
|
return kCALineJoinBevel;
|
||||||
}
|
}
|
||||||
case IJSVGLineJoinStyleRound: {
|
case IJSVGLineJoinStyleRound: {
|
||||||
return kCALineJoinRound;
|
return kCALineJoinRound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)lineCap:(IJSVGLineCapStyle)capStyle
|
- (NSString*)lineCap:(IJSVGLineCapStyle)capStyle
|
||||||
{
|
{
|
||||||
switch (capStyle) {
|
switch (capStyle) {
|
||||||
default:
|
default:
|
||||||
case IJSVGLineCapStyleButt: {
|
case IJSVGLineCapStyleButt: {
|
||||||
return kCALineCapButt;
|
return kCALineCapButt;
|
||||||
}
|
}
|
||||||
case IJSVGLineCapStyleRound: {
|
case IJSVGLineCapStyleRound: {
|
||||||
return kCALineCapRound;
|
return kCALineCapRound;
|
||||||
}
|
}
|
||||||
case IJSVGLineCapStyleSquare: {
|
case IJSVGLineCapStyleSquare: {
|
||||||
return kCALineCapSquare;
|
return kCALineCapSquare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)fillRule:(IJSVGWindingRule)rule
|
- (NSString*)fillRule:(IJSVGWindingRule)rule
|
||||||
{
|
{
|
||||||
switch (rule) {
|
switch (rule) {
|
||||||
case IJSVGWindingRuleEvenOdd: {
|
case IJSVGWindingRuleEvenOdd: {
|
||||||
return kCAFillRuleEvenOdd;
|
return kCAFillRuleEvenOdd;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return kCAFillRuleNonZero;
|
return kCAFillRuleNonZero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2019 Curtis Hard. All rights reserved.
|
// Copyright © 2019 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGColorList.h"
|
#import <IJSVG/IJSVGColorList.h>
|
||||||
#import "IJSVGNode.h"
|
#import <IJSVG/IJSVGNode.h>
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
|||||||
@@ -10,13 +10,6 @@
|
|||||||
|
|
||||||
@implementation IJSVGRenderingStyle
|
@implementation IJSVGRenderingStyle
|
||||||
|
|
||||||
@synthesize colorList = _colorList;
|
|
||||||
@synthesize lineCapStyle = _lineCapStyle;
|
|
||||||
@synthesize lineJoinStyle = _lineJoinStyle;
|
|
||||||
@synthesize lineWidth = _lineWidth;
|
|
||||||
@synthesize fillColor = _fillColor;
|
|
||||||
@synthesize strokeColor = _strokeColor;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([_fillColor release]), _fillColor = nil;
|
(void)([_fillColor release]), _fillColor = nil;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGColor.h"
|
#import <IJSVG/IJSVGColor.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface IJSVGStyle : NSObject {
|
@interface IJSVGStyle : NSObject {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
|
|
||||||
+ (NSArray*)allowedColourKeys
|
+ (NSArray*)allowedColourKeys
|
||||||
{
|
{
|
||||||
return @[ @"fill", @"stroke-colour", @"stop-color", @"stroke" ];
|
return @[ @"fill", @"stroke-color", @"stop-color", @"stroke" ];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setProperties:(NSDictionary*)properties
|
- (void)setProperties:(NSDictionary*)properties
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGStyleSheetRule.h"
|
#import <IJSVG/IJSVGStyleSheetRule.h>
|
||||||
#import "IJSVGStyleSheetSelector.h"
|
#import <IJSVG/IJSVGStyleSheetSelector.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVGNode;
|
@class IJSVGNode;
|
||||||
|
|||||||
@@ -11,9 +11,6 @@
|
|||||||
#import "IJSVGStyleSheet.h"
|
#import "IJSVGStyleSheet.h"
|
||||||
|
|
||||||
@interface IJSVGStyleSheetSelectorListItem : NSObject {
|
@interface IJSVGStyleSheetSelectorListItem : NSObject {
|
||||||
|
|
||||||
IJSVGStyleSheetSelector* selector;
|
|
||||||
IJSVGStyleSheetRule* rule;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, retain) IJSVGStyleSheetRule* rule;
|
@property (nonatomic, retain) IJSVGStyleSheetRule* rule;
|
||||||
@@ -23,12 +20,11 @@
|
|||||||
|
|
||||||
@implementation IJSVGStyleSheetSelectorListItem
|
@implementation IJSVGStyleSheetSelectorListItem
|
||||||
|
|
||||||
@synthesize rule, selector;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([rule release]), rule = nil;
|
(void)([_rule release]), _rule = nil;
|
||||||
(void)([selector release]), selector = nil;
|
(void)([_selector release]), _selector = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,16 +6,13 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGStyle.h"
|
#import <IJSVG/IJSVGStyle.h>
|
||||||
#import "IJSVGStyleSheetSelector.h"
|
#import <IJSVG/IJSVGStyleSheetSelector.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVGNode;
|
@class IJSVGNode;
|
||||||
|
|
||||||
@interface IJSVGStyleSheetRule : NSObject {
|
@interface IJSVGStyleSheetRule : NSObject {
|
||||||
|
|
||||||
NSArray* selectors;
|
|
||||||
IJSVGStyle* style;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, retain) NSArray* selectors;
|
@property (nonatomic, retain) NSArray* selectors;
|
||||||
|
|||||||
@@ -10,12 +10,10 @@
|
|||||||
|
|
||||||
@implementation IJSVGStyleSheetRule
|
@implementation IJSVGStyleSheetRule
|
||||||
|
|
||||||
@synthesize selectors, style;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([selectors release]), selectors = nil;
|
(void)([_selectors release]), _selectors = nil;
|
||||||
(void)([style release]), style = nil;
|
(void)([_style release]), _style = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +22,7 @@
|
|||||||
{
|
{
|
||||||
// interate over each select and work out if
|
// interate over each select and work out if
|
||||||
// it allows us to be applied
|
// it allows us to be applied
|
||||||
for (IJSVGStyleSheetSelector* selector in selectors) {
|
for (IJSVGStyleSheetSelector* selector in _selectors) {
|
||||||
if ([selector matchesNode:node]) {
|
if ([selector matchesNode:node]) {
|
||||||
*matchedSelector = selector;
|
*matchedSelector = selector;
|
||||||
return YES;
|
return YES;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright © 2016 Curtis Hard. All rights reserved.
|
// Copyright © 2016 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGStyleSheetSelectorRaw.h"
|
#import <IJSVG/IJSVGStyleSheetSelectorRaw.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVGNode;
|
@class IJSVGNode;
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
@interface IJSVGStyleSheetSelector : NSObject {
|
@interface IJSVGStyleSheetSelector : NSObject {
|
||||||
|
|
||||||
NSString* selector;
|
NSString* selector;
|
||||||
NSUInteger specificity;
|
|
||||||
@private
|
@private
|
||||||
NSMutableArray* _rawSelectors;
|
NSMutableArray* _rawSelectors;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
#define SPECIFICITY_CLASS 10
|
#define SPECIFICITY_CLASS 10
|
||||||
#define SPECIFICITY_IDENTIFIER 100
|
#define SPECIFICITY_IDENTIFIER 100
|
||||||
|
|
||||||
@synthesize specificity;
|
|
||||||
|
|
||||||
BOOL IJSVGStyleSheetIsSiblingCombinator(IJSVGStyleSheetSelectorCombinator combinator)
|
BOOL IJSVGStyleSheetIsSiblingCombinator(IJSVGStyleSheetSelectorCombinator combinator)
|
||||||
{
|
{
|
||||||
return combinator == IJSVGStyleSheetSelectorCombinatorNextSibling ||
|
return combinator == IJSVGStyleSheetSelectorCombinatorNextSibling ||
|
||||||
@@ -43,11 +41,11 @@ IJSVGNode * IJSVGStyleSheetPreviousNode(IJSVGNode * node)
|
|||||||
IJSVGGroup * group = (IJSVGGroup *)node.parentNode;
|
IJSVGGroup * group = (IJSVGGroup *)node.parentNode;
|
||||||
if([group isKindOfClass:[IJSVGGroup class]] == NO)
|
if([group isKindOfClass:[IJSVGGroup class]] == NO)
|
||||||
return nil;
|
return nil;
|
||||||
NSInteger currentIndex = [group.children indexOfObject:node];
|
NSInteger currentIndex = [group.childNodes indexOfObject:node];
|
||||||
if(currentIndex == 0) {
|
if(currentIndex == 0) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return group.children[currentIndex-1];
|
return group.childNodes[currentIndex-1];
|
||||||
};
|
};
|
||||||
|
|
||||||
IJSVGNode * IJSVGStyleSheetNextNode(IJSVGNode * node)
|
IJSVGNode * IJSVGStyleSheetNextNode(IJSVGNode * node)
|
||||||
@@ -56,11 +54,11 @@ IJSVGNode * IJSVGStyleSheetNextNode(IJSVGNode * node)
|
|||||||
if([group isKindOfClass:[IJSVGGroup class]] == NO) {
|
if([group isKindOfClass:[IJSVGGroup class]] == NO) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
NSInteger currentIndex = [group.children indexOfObject:node];
|
NSInteger currentIndex = [group.childNodes indexOfObject:node];
|
||||||
if(currentIndex == group.children.count-1) {
|
if(currentIndex == group.childNodes.count-1) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return group.children[currentIndex+1];
|
return group.childNodes[currentIndex+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
IJSVGStyleSheetSelectorRaw * IJSVGStyleSheetPreviousSelector(IJSVGStyleSheetSelectorRaw * aSelector, NSArray * _rawSelectors)
|
IJSVGStyleSheetSelectorRaw * IJSVGStyleSheetPreviousSelector(IJSVGStyleSheetSelectorRaw * aSelector, NSArray * _rawSelectors)
|
||||||
@@ -149,7 +147,7 @@ BOOL IJSVGStyleSheetMatchSelector(IJSVGNode * node, IJSVGStyleSheetSelectorRaw *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// grab the children
|
// grab the children
|
||||||
NSArray * nodes = parentNode.children;
|
NSArray * nodes = parentNode.childNodes;
|
||||||
NSInteger index = [nodes indexOfObject:aNode];
|
NSInteger index = [nodes indexOfObject:aNode];
|
||||||
|
|
||||||
// doesnt contain the child
|
// doesnt contain the child
|
||||||
@@ -228,7 +226,7 @@ BOOL IJSVGStyleSheetMatchSelector(IJSVGNode * node, IJSVGStyleSheetSelectorRaw *
|
|||||||
// matches the next selector and... contains the node in question
|
// matches the next selector and... contains the node in question
|
||||||
IJSVGStyleSheetSelectorRaw * s = IJSVGStyleSheetNextSelector(aSelector,_rawSelectors);
|
IJSVGStyleSheetSelectorRaw * s = IJSVGStyleSheetNextSelector(aSelector,_rawSelectors);
|
||||||
if(IJSVGStyleSheetMatchSelector(parentNode, s) &&
|
if(IJSVGStyleSheetMatchSelector(parentNode, s) &&
|
||||||
[parentNode.children containsObject:aNode]) {
|
[parentNode.childNodes containsObject:aNode]) {
|
||||||
// set the new starting selector and node
|
// set the new starting selector and node
|
||||||
aSelector = s;
|
aSelector = s;
|
||||||
aNode = parentNode;
|
aNode = parentNode;
|
||||||
@@ -276,15 +274,16 @@ BOOL IJSVGStyleSheetMatchSelector(IJSVGNode * node, IJSVGStyleSheetSelectorRaw *
|
|||||||
|
|
||||||
// 1 for a tag
|
// 1 for a tag
|
||||||
if(rawSelector.tag != nil) {
|
if(rawSelector.tag != nil) {
|
||||||
self.specificity += SPECIFICITY_TAG;
|
_specificity += SPECIFICITY_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 100 for a id
|
// 100 for a id
|
||||||
if(rawSelector.identifier != nil)
|
if(rawSelector.identifier != nil) {
|
||||||
self.specificity += SPECIFICITY_IDENTIFIER;
|
_specificity += SPECIFICITY_IDENTIFIER;
|
||||||
|
}
|
||||||
|
|
||||||
// 10 for a class
|
// 10 for a class
|
||||||
self.specificity += (rawSelector.classes.count*SPECIFICITY_CLASS);
|
_specificity += (rawSelector.classes.count*SPECIFICITY_CLASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,9 @@ typedef NS_ENUM(NSUInteger, IJSVGStyleSheetSelectorCombinator) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@interface IJSVGStyleSheetSelectorRaw : NSObject {
|
@interface IJSVGStyleSheetSelectorRaw : NSObject {
|
||||||
|
|
||||||
NSString* tag;
|
@private
|
||||||
NSString* identifier;
|
|
||||||
|
|
||||||
NSMutableArray* classes;
|
NSMutableArray* classes;
|
||||||
|
|
||||||
IJSVGStyleSheetSelectorCombinator combinator;
|
|
||||||
NSString* combinatorString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString* tag;
|
@property (nonatomic, copy) NSString* tag;
|
||||||
|
|||||||
@@ -10,14 +10,14 @@
|
|||||||
|
|
||||||
@implementation IJSVGStyleSheetSelectorRaw
|
@implementation IJSVGStyleSheetSelectorRaw
|
||||||
|
|
||||||
@synthesize classes, identifier, tag, combinator, combinatorString;
|
@synthesize classes;
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
(void)([classes release]), classes = nil;
|
(void)([classes release]), classes = nil;
|
||||||
(void)([identifier release]), identifier = nil;
|
(void)([_identifier release]), _identifier = nil;
|
||||||
(void)([tag release]), tag = nil;
|
(void)([_tag release]), _tag = nil;
|
||||||
(void)([combinatorString release]), combinatorString = nil;
|
(void)([_combinatorString release]), _combinatorString = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
{
|
{
|
||||||
if ((self = [super init]) != nil) {
|
if ((self = [super init]) != nil) {
|
||||||
classes = [[NSMutableArray alloc] init];
|
classes = [[NSMutableArray alloc] init];
|
||||||
combinator = IJSVGStyleSheetSelectorCombinatorDescendant;
|
_combinator = IJSVGStyleSheetSelectorCombinatorDescendant;
|
||||||
combinatorString = @" ";
|
_combinatorString = @" ";
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,8 @@
|
|||||||
|
|
||||||
- (NSString*)description
|
- (NSString*)description
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat:@"Combinator: %@, Tag: %@, Classes: %@, Identifier: %@", combinatorString, tag, classes, identifier];
|
return [NSString stringWithFormat:@"Combinator: %@, Tag: %@, Classes: %@, Identifier: %@",
|
||||||
|
_combinatorString, _tag, classes, _identifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright © 2017 Curtis Hard. All rights reserved.
|
// Copyright © 2017 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGUnitLength.h"
|
#import <IJSVG/IJSVGUnitLength.h>
|
||||||
|
|
||||||
@interface IJSVGGradientUnitLength : IJSVGUnitLength
|
@interface IJSVGGradientUnitLength : IJSVGUnitLength
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGMath.h"
|
#import "IJSVGMath.h"
|
||||||
|
#import "IJSVGCommandParser.h"
|
||||||
|
|
||||||
@implementation IJSVGMath
|
@implementation IJSVGMath
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// IJSVGParsing.h
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 04/02/2021.
|
||||||
|
// Copyright © 2021 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
char* parameters;
|
||||||
|
} IJSVGParsingStringMethod;
|
||||||
|
|
||||||
|
IJSVGParsingStringMethod* IJSVGParsingStringMethodCreate(void);
|
||||||
|
void IJSVGParsingStringMethodRelease(IJSVGParsingStringMethod* stringMethod);
|
||||||
|
IJSVGParsingStringMethod** IJSVGParsingMethodParseString(const char* string,
|
||||||
|
NSUInteger* count);
|
||||||
|
void IJSVGParsingStringMethodsRelease(IJSVGParsingStringMethod** methods,
|
||||||
|
NSUInteger count);
|
||||||
|
|
||||||
|
@interface IJSVGParsing : NSObject
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// IJSVGParsing.m
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 04/02/2021.
|
||||||
|
// Copyright © 2021 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IJSVGParsing.h"
|
||||||
|
#import "IJSVGUtils.h"
|
||||||
|
|
||||||
|
IJSVGParsingStringMethod* IJSVGParsingStringMethodCreate(void)
|
||||||
|
{
|
||||||
|
IJSVGParsingStringMethod* method = (IJSVGParsingStringMethod*)malloc(sizeof(IJSVGParsingStringMethod));
|
||||||
|
method->name = NULL;
|
||||||
|
method->parameters = NULL;
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IJSVGParsingStringMethodRelease(IJSVGParsingStringMethod* stringMethod)
|
||||||
|
{
|
||||||
|
if(stringMethod->name != NULL) {
|
||||||
|
(void)free(stringMethod->name), stringMethod->name = NULL;
|
||||||
|
}
|
||||||
|
if(stringMethod->parameters != NULL) {
|
||||||
|
(void)free(stringMethod->parameters), stringMethod->parameters = NULL;
|
||||||
|
}
|
||||||
|
if(stringMethod != NULL) {
|
||||||
|
(void)free(stringMethod), stringMethod = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IJSVGParsingStringMethodsRelease(IJSVGParsingStringMethod** methods,
|
||||||
|
NSUInteger count)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < count; i++) {
|
||||||
|
IJSVGParsingStringMethodRelease(methods[i]);
|
||||||
|
}
|
||||||
|
(void)free(methods), methods = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IJSVGParsingStringMethod** IJSVGParsingMethodParseString(const char* string,
|
||||||
|
NSUInteger* count)
|
||||||
|
{
|
||||||
|
const char* charString = string;
|
||||||
|
unsigned long length = strlen(string);
|
||||||
|
char* buffer = (char*)calloc(sizeof(char), length);
|
||||||
|
char* originBuffer = buffer;
|
||||||
|
int bufferIndex = 0;
|
||||||
|
|
||||||
|
const size_t defBufferSize = 5;
|
||||||
|
size_t currentBufferSize = defBufferSize;
|
||||||
|
NSUInteger methodCount = 0;
|
||||||
|
|
||||||
|
IJSVGParsingStringMethod* method = NULL;
|
||||||
|
IJSVGParsingStringMethod** methods = NULL;
|
||||||
|
methods = (IJSVGParsingStringMethod**)malloc(sizeof(IJSVGParsingStringMethod*)*currentBufferSize);
|
||||||
|
|
||||||
|
// each command requires a name and parameters, store for later use
|
||||||
|
for(int i = 0; i < length; i++) {
|
||||||
|
char currentChar = *charString++;
|
||||||
|
|
||||||
|
// start of params - store the command name as its current in the buffer
|
||||||
|
if(currentChar == '(') {
|
||||||
|
// rest the pointer to beginning
|
||||||
|
buffer = originBuffer;
|
||||||
|
|
||||||
|
//write here
|
||||||
|
if(method == NULL) {
|
||||||
|
method = IJSVGParsingStringMethodCreate();
|
||||||
|
method->name = (char*)calloc(sizeof(char),bufferIndex+1);
|
||||||
|
memcpy(method->name, buffer, sizeof(char)*bufferIndex);
|
||||||
|
IJSVGTrimCharBuffer(method->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write null up until the limit we reached
|
||||||
|
memset(buffer, '\0', bufferIndex);
|
||||||
|
bufferIndex = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// end of params - store the params into the buffer
|
||||||
|
if(currentChar == ')') {
|
||||||
|
// rest the pointer to beginning
|
||||||
|
buffer = originBuffer;
|
||||||
|
|
||||||
|
// there has to be a method at this point, if not, something is wrong
|
||||||
|
// in the syntax
|
||||||
|
if(method != NULL) {
|
||||||
|
method->parameters = (char*)calloc(sizeof(char),bufferIndex+1);
|
||||||
|
memcpy(method->parameters, buffer, sizeof(char)*bufferIndex);
|
||||||
|
IJSVGTrimCharBuffer(method->parameters);
|
||||||
|
|
||||||
|
// now we can add
|
||||||
|
if(methodCount + 1 > currentBufferSize) {
|
||||||
|
currentBufferSize += defBufferSize;
|
||||||
|
*methods = *(IJSVGParsingStringMethod**)realloc(methods, sizeof(IJSVGParsingStringMethod*)*currentBufferSize);
|
||||||
|
}
|
||||||
|
methods[methodCount++] = method;
|
||||||
|
method = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write null up until the limit we reached
|
||||||
|
memset(buffer, '\0', bufferIndex);
|
||||||
|
bufferIndex = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment the buffer count
|
||||||
|
*buffer++ = currentChar;
|
||||||
|
bufferIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// left over
|
||||||
|
if(method != NULL) {
|
||||||
|
(void)IJSVGParsingStringMethodRelease(method), method = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = originBuffer;
|
||||||
|
*count = methodCount;
|
||||||
|
(void)free(buffer), buffer = NULL;
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation IJSVGParsing
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -10,5 +10,5 @@
|
|||||||
#import <QuartzCore/QuartzCore.h>
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
BOOL IJSVGIsMainThread(void);
|
BOOL IJSVGIsMainThread(void);
|
||||||
void IJSVGBeginTransactionLock(void);
|
BOOL IJSVGBeginTransaction(void);
|
||||||
void IJSVGEndTransactionLock(void);
|
void IJSVGEndTransaction(void);
|
||||||
|
|||||||
@@ -7,16 +7,25 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGTransaction.h"
|
#import "IJSVGTransaction.h"
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
BOOL IJSVGIsMainThread(void) { return NSThread.isMainThread; };
|
BOOL IJSVGIsMainThread(void) { return NSThread.isMainThread; };
|
||||||
|
|
||||||
void IJSVGBeginTransactionLock(void)
|
BOOL IJSVGBeginTransaction(void)
|
||||||
{
|
{
|
||||||
|
if(IJSVGIsMainThread() == YES) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
// use nsanimationcontext as this sets a private flag of 0x4
|
||||||
|
// of the catransaction for background composites
|
||||||
[CATransaction begin];
|
[CATransaction begin];
|
||||||
[CATransaction setDisableActions:YES];
|
[CATransaction setDisableActions:YES];
|
||||||
|
[CATransaction lock];
|
||||||
|
return YES;
|
||||||
};
|
};
|
||||||
|
|
||||||
void IJSVGEndTransactionLock(void)
|
void IJSVGEndTransaction(void)
|
||||||
{
|
{
|
||||||
|
[CATransaction unlock];
|
||||||
[CATransaction commit];
|
[CATransaction commit];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
// Copyright (c) 2014 Curtis Hard. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "IJSVGUtils.h"
|
#import <IJSVG/IJSVGUtils.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@class IJSVGTransform;
|
@class IJSVGTransform;
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
typedef CGFloat (^IJSVGTransformParameterModifier)(NSInteger index, CGFloat value);
|
typedef CGFloat (^IJSVGTransformParameterModifier)(NSInteger index, CGFloat value);
|
||||||
typedef void (^IJSVGTransformApplyBlock)(IJSVGTransform* transform);
|
typedef void (^IJSVGTransformApplyBlock)(IJSVGTransform* transform);
|
||||||
|
|
||||||
typedef NS_OPTIONS(NSInteger, IJSVGTransformCommand) {
|
typedef NS_ENUM(NSInteger, IJSVGTransformCommand) {
|
||||||
IJSVGTransformCommandMatrix,
|
IJSVGTransformCommandMatrix,
|
||||||
IJSVGTransformCommandTranslate,
|
IJSVGTransformCommandTranslate,
|
||||||
IJSVGTransformCommandTranslateX,
|
IJSVGTransformCommandTranslateX,
|
||||||
@@ -27,11 +27,6 @@ typedef NS_OPTIONS(NSInteger, IJSVGTransformCommand) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@interface IJSVGTransform : NSObject {
|
@interface IJSVGTransform : NSObject {
|
||||||
|
|
||||||
IJSVGTransformCommand command;
|
|
||||||
CGFloat* parameters;
|
|
||||||
NSInteger parameterCount;
|
|
||||||
NSInteger sort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, assign) IJSVGTransformCommand command;
|
@property (nonatomic, assign) IJSVGTransformCommand command;
|
||||||
@@ -43,10 +38,15 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
CGAffineTransform IJSVGConcatTransforms(NSArray<IJSVGTransform*>* transforms);
|
CGAffineTransform IJSVGConcatTransforms(NSArray<IJSVGTransform*>* transforms);
|
||||||
NSString* IJSVGTransformAttributeString(CGAffineTransform transform);
|
NSString* IJSVGTransformAttributeString(CGAffineTransform transform);
|
||||||
|
|
||||||
|
+ (NSArray<NSDictionary*>*)affineTransformToSVGTransformComponents:(CGAffineTransform)transform;
|
||||||
|
+ (NSString*)affineTransformToSVGTransformComponentString:(CGAffineTransform)transform
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
|
+ (NSString*)affineTransformToSVGTransformComponentString:(CGAffineTransform)transform;
|
||||||
+ (NSArray<IJSVGTransform*>*)transformsFromAffineTransform:(CGAffineTransform)affineTransform;
|
+ (NSArray<IJSVGTransform*>*)transformsFromAffineTransform:(CGAffineTransform)affineTransform;
|
||||||
+ (NSArray*)transformsForString:(NSString*)string;
|
+ (NSArray<IJSVGTransform*>*)transformsForString:(NSString*)string;
|
||||||
+ (NSBezierPath*)transformedPath:(IJSVGPath*)path;
|
|
||||||
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)affineTransform;
|
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)affineTransform;
|
||||||
|
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)transform
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
|
||||||
- (CGAffineTransform)CGAffineTransform;
|
- (CGAffineTransform)CGAffineTransform;
|
||||||
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier;
|
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier;
|
||||||
- (CGAffineTransform)stackIdentity:(CGAffineTransform)identity;
|
- (CGAffineTransform)stackIdentity:(CGAffineTransform)identity;
|
||||||
|
|||||||
@@ -8,28 +8,24 @@
|
|||||||
|
|
||||||
#import "IJSVGMath.h"
|
#import "IJSVGMath.h"
|
||||||
#import "IJSVGTransform.h"
|
#import "IJSVGTransform.h"
|
||||||
|
#import "IJSVGParsing.h"
|
||||||
|
|
||||||
@implementation IJSVGTransform
|
@implementation IJSVGTransform
|
||||||
|
|
||||||
@synthesize command;
|
|
||||||
@synthesize parameters;
|
|
||||||
@synthesize parameterCount;
|
|
||||||
@synthesize sort;
|
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
free(parameters);
|
(void)free(_parameters);
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)copyWithZone:(NSZone*)zone
|
- (id)copyWithZone:(NSZone*)zone
|
||||||
{
|
{
|
||||||
IJSVGTransform* trans = [[self.class alloc] init];
|
IJSVGTransform* trans = [[self.class alloc] init];
|
||||||
trans.command = self.command;
|
trans.command = _command;
|
||||||
trans.parameters = (CGFloat*)malloc(sizeof(CGFloat) * self.parameterCount);
|
trans.parameters = (CGFloat*)malloc(sizeof(CGFloat) * _parameterCount);
|
||||||
trans.sort = sort;
|
trans.sort = _sort;
|
||||||
trans.parameterCount = self.parameterCount;
|
trans.parameterCount = _parameterCount;
|
||||||
memcpy(trans.parameters, self.parameters, sizeof(CGFloat) * self.parameterCount);
|
memcpy(trans.parameters, _parameters, sizeof(CGFloat) * _parameterCount);
|
||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,19 +79,49 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
- (void)recalculateWithBounds:(CGRect)bounds
|
- (void)recalculateWithBounds:(CGRect)bounds
|
||||||
{
|
{
|
||||||
CGFloat max = bounds.size.width > bounds.size.height ? bounds.size.width : bounds.size.height;
|
CGFloat max = bounds.size.width > bounds.size.height ? bounds.size.width : bounds.size.height;
|
||||||
switch (self.command) {
|
switch (_command) {
|
||||||
case IJSVGTransformCommandRotate: {
|
case IJSVGTransformCommandRotate: {
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.parameters[1] = self.parameters[1] * max;
|
_parameters[1] = _parameters[1] * max;
|
||||||
self.parameters[2] = self.parameters[2] * max;
|
_parameters[2] = _parameters[2] * max;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (IJSVGTransformCommand)commandForCommandCString:(char*)str
|
||||||
|
{
|
||||||
|
IJSVGCharBufferToLower(str);
|
||||||
|
if (strcmp(str, "matrix") == 0) {
|
||||||
|
return IJSVGTransformCommandMatrix;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "translate") == 0) {
|
||||||
|
return IJSVGTransformCommandTranslate;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "translatex") == 0) {
|
||||||
|
return IJSVGTransformCommandTranslateX;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "translatey") == 0) {
|
||||||
|
return IJSVGTransformCommandTranslateY;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "scale") == 0) {
|
||||||
|
return IJSVGTransformCommandScale;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "skewx") == 0) {
|
||||||
|
return IJSVGTransformCommandSkewX;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "skewy") == 0) {
|
||||||
|
return IJSVGTransformCommandSkewY;
|
||||||
|
}
|
||||||
|
if (strcmp(str, "rotate") == 0) {
|
||||||
|
return IJSVGTransformCommandRotate;
|
||||||
|
}
|
||||||
|
return IJSVGTransformCommandNotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
+ (IJSVGTransformCommand)commandForCommandString:(NSString*)str
|
+ (IJSVGTransformCommand)commandForCommandString:(NSString*)str
|
||||||
{
|
{
|
||||||
str = str.lowercaseString;
|
str = str.lowercaseString;
|
||||||
@@ -137,188 +163,76 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSArray*)transformsForString:(NSString*)string
|
+ (NSArray<IJSVGTransform*>*)transformsForString:(NSString*)string
|
||||||
{
|
{
|
||||||
static NSRegularExpression* _reg = nil;
|
NSMutableArray<IJSVGTransform*>* transforms = nil;
|
||||||
static dispatch_once_t onceToken;
|
transforms = [[[NSMutableArray alloc] init] autorelease];
|
||||||
dispatch_once(&onceToken, ^{
|
|
||||||
_reg = [[NSRegularExpression alloc] initWithPattern:@"([a-zA-Z]+)\\(([^\\)]+)\\)"
|
const char* charString = string.UTF8String;
|
||||||
options:0
|
IJSVGParsingStringMethod** methods = NULL;
|
||||||
error:nil];
|
NSUInteger count = 0;
|
||||||
});
|
methods = IJSVGParsingMethodParseString(charString, &count);
|
||||||
NSMutableArray* transforms = [[[NSMutableArray alloc] init] autorelease];
|
for(int i = 0; i < count; i++) {
|
||||||
@autoreleasepool {
|
IJSVGParsingStringMethod* method = methods[i];
|
||||||
[_reg enumerateMatchesInString:string
|
IJSVGTransformCommand commandType;
|
||||||
options:0
|
commandType = [self.class commandForCommandCString:method->name];
|
||||||
range:NSMakeRange(0, string.length)
|
if(commandType == IJSVGTransformCommandNotImplemented) {
|
||||||
usingBlock:^(NSTextCheckingResult* result, NSMatchingFlags flags, BOOL* stop) {
|
(void)IJSVGParsingStringMethodRelease(method), method = NULL;
|
||||||
NSString* command = [string substringWithRange:[result rangeAtIndex:1]];
|
continue;
|
||||||
IJSVGTransformCommand commandType = [self.class commandForCommandString:command];
|
}
|
||||||
if (commandType == IJSVGTransformCommandNotImplemented) {
|
|
||||||
return;
|
// create a new transform object and parse the parameters
|
||||||
}
|
NSInteger count = 0;
|
||||||
|
IJSVGTransform* transform = [[[self.class alloc] init] autorelease];
|
||||||
|
transform.command = commandType;
|
||||||
|
transform.sort = [self.class sortForTransformCommand:commandType];
|
||||||
|
transform.parameters = [IJSVGUtils scanFloatsFromCString:method->parameters
|
||||||
|
size:&count];
|
||||||
|
transform.parameterCount = count;
|
||||||
|
|
||||||
// create the transform
|
// add to the list of transforms to return
|
||||||
NSString* params = [string substringWithRange:[result rangeAtIndex:2]];
|
[transforms addObject:transform];
|
||||||
IJSVGTransform* transform = [[[self.class alloc] init] autorelease];
|
(void)IJSVGParsingStringMethodRelease(method), method = NULL;
|
||||||
NSInteger count = 0;
|
|
||||||
transform.command = commandType;
|
|
||||||
transform.parameters = [IJSVGUtils commandParameters:params
|
|
||||||
count:&count];
|
|
||||||
transform.parameterCount = count;
|
|
||||||
transform.sort = [self.class sortForTransformCommand:commandType];
|
|
||||||
[transforms addObject:transform];
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
(void)free(methods), methods = NULL;
|
||||||
return transforms;
|
return transforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSBezierPath*)transformedPath:(IJSVGPath*)path
|
|
||||||
{
|
|
||||||
if (path.transforms.count == 0) {
|
|
||||||
return path.path;
|
|
||||||
}
|
|
||||||
NSBezierPath* cop = [[path.path copy] autorelease];
|
|
||||||
for (IJSVGTransform* transform in path.transforms) {
|
|
||||||
NSAffineTransform* at = NSAffineTransform.transform;
|
|
||||||
switch (transform.command) {
|
|
||||||
// matrix
|
|
||||||
case IJSVGTransformCommandMatrix: {
|
|
||||||
at.transformStruct = (NSAffineTransformStruct){
|
|
||||||
.m11 = transform.parameters[0],
|
|
||||||
.m12 = transform.parameters[1],
|
|
||||||
.m21 = transform.parameters[2],
|
|
||||||
.m22 = transform.parameters[3],
|
|
||||||
.tX = transform.parameters[4],
|
|
||||||
.tY = transform.parameters[5],
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skewX
|
|
||||||
case IJSVGTransformCommandSkewX: {
|
|
||||||
CGFloat degrees = transform.parameters[0];
|
|
||||||
CGFloat radians = degrees * M_PI / 180.f;
|
|
||||||
at.transformStruct = (NSAffineTransformStruct){
|
|
||||||
.m11 = 1.f,
|
|
||||||
.m12 = 0.f,
|
|
||||||
.m21 = tan(radians),
|
|
||||||
.m22 = 1.f,
|
|
||||||
.tX = 0.f,
|
|
||||||
.tY = 0.f
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skewX
|
|
||||||
case IJSVGTransformCommandSkewY: {
|
|
||||||
CGFloat degrees = transform.parameters[0];
|
|
||||||
CGFloat radians = degrees * M_PI / 180.f;
|
|
||||||
at.transformStruct = (NSAffineTransformStruct){
|
|
||||||
.m11 = 1.f,
|
|
||||||
.m12 = tan(radians),
|
|
||||||
.m21 = 0.f,
|
|
||||||
.m22 = 1.f,
|
|
||||||
.tX = 0.f,
|
|
||||||
.tY = 0.f
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate
|
|
||||||
case IJSVGTransformCommandTranslate: {
|
|
||||||
if (transform.parameterCount == 1)
|
|
||||||
[at translateXBy:transform.parameters[0]
|
|
||||||
yBy:0];
|
|
||||||
else
|
|
||||||
[at translateXBy:transform.parameters[0]
|
|
||||||
yBy:transform.parameters[1]];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// translateX
|
|
||||||
case IJSVGTransformCommandTranslateX: {
|
|
||||||
[at translateXBy:transform.parameters[0] yBy:0.f];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// translateY
|
|
||||||
case IJSVGTransformCommandTranslateY: {
|
|
||||||
[at translateXBy:0.f yBy:transform.parameters[0]];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// scale
|
|
||||||
case IJSVGTransformCommandScale: {
|
|
||||||
if (transform.parameterCount == 1)
|
|
||||||
[at scaleBy:transform.parameters[0]];
|
|
||||||
else
|
|
||||||
[at scaleXBy:transform.parameters[0]
|
|
||||||
yBy:transform.parameters[1]];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotate
|
|
||||||
case IJSVGTransformCommandRotate: {
|
|
||||||
if (transform.parameterCount == 1)
|
|
||||||
[at rotateByDegrees:transform.parameters[0]];
|
|
||||||
else {
|
|
||||||
CGFloat centerX = transform.parameters[1];
|
|
||||||
CGFloat centerY = transform.parameters[2];
|
|
||||||
CGFloat angle = transform.parameters[0] * (M_PI / 180.f);
|
|
||||||
[at translateXBy:centerX
|
|
||||||
yBy:centerY];
|
|
||||||
[at rotateByRadians:angle];
|
|
||||||
[at translateXBy:-1.f * centerX
|
|
||||||
yBy:-1.f * centerY];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do nothing
|
|
||||||
case IJSVGTransformCommandNotImplemented: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[cop transformUsingAffineTransform:at];
|
|
||||||
}
|
|
||||||
return cop;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGAffineTransform)CGAffineTransform
|
- (CGAffineTransform)CGAffineTransform
|
||||||
{
|
{
|
||||||
return [self CGAffineTransformWithModifier:nil];
|
return [self stackIdentity:CGAffineTransformIdentity];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGAffineTransform)stackIdentity:(CGAffineTransform)identity
|
- (CGAffineTransform)stackIdentity:(CGAffineTransform)identity
|
||||||
{
|
{
|
||||||
switch (self.command) {
|
switch (_command) {
|
||||||
|
|
||||||
// translate
|
// translate
|
||||||
case IJSVGTransformCommandTranslate: {
|
case IJSVGTransformCommandTranslate: {
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return CGAffineTransformTranslate(identity, self.parameters[0], 0.f);
|
return CGAffineTransformTranslate(identity, _parameters[0], 0.f);
|
||||||
}
|
}
|
||||||
return CGAffineTransformTranslate(identity, self.parameters[0], self.parameters[1]);
|
return CGAffineTransformTranslate(identity, _parameters[0], _parameters[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// translateX
|
// translateX
|
||||||
case IJSVGTransformCommandTranslateX: {
|
case IJSVGTransformCommandTranslateX: {
|
||||||
return CGAffineTransformTranslate(identity, self.parameters[0], 0.f);
|
return CGAffineTransformTranslate(identity, _parameters[0], 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// translateY
|
// translateY
|
||||||
case IJSVGTransformCommandTranslateY: {
|
case IJSVGTransformCommandTranslateY: {
|
||||||
return CGAffineTransformTranslate(identity, 0.f, self.parameters[0]);
|
return CGAffineTransformTranslate(identity, 0.f, _parameters[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotate
|
// rotate
|
||||||
case IJSVGTransformCommandRotate: {
|
case IJSVGTransformCommandRotate: {
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return CGAffineTransformRotate(identity, (self.parameters[0] / 180) * M_PI);
|
return CGAffineTransformRotate(identity, (_parameters[0] / 180) * M_PI);
|
||||||
}
|
}
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
CGFloat p2 = self.parameters[2];
|
CGFloat p2 = _parameters[2];
|
||||||
CGFloat angle = p0 * (M_PI / 180.f);
|
CGFloat angle = p0 * (M_PI / 180.f);
|
||||||
|
|
||||||
identity = CGAffineTransformTranslate(identity, p1, p2);
|
identity = CGAffineTransformTranslate(identity, p1, p2);
|
||||||
@@ -328,35 +242,35 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// scale
|
// scale
|
||||||
case IJSVGTransformCommandScale: {
|
case IJSVGTransformCommandScale: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return CGAffineTransformScale(identity, p0, p0);
|
return CGAffineTransformScale(identity, p0, p0);
|
||||||
}
|
}
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
return CGAffineTransformScale(identity, p0, p1);
|
return CGAffineTransformScale(identity, p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// matrix
|
// matrix
|
||||||
case IJSVGTransformCommandMatrix: {
|
case IJSVGTransformCommandMatrix: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
CGFloat p2 = self.parameters[2];
|
CGFloat p2 = _parameters[2];
|
||||||
CGFloat p3 = self.parameters[3];
|
CGFloat p3 = _parameters[3];
|
||||||
CGFloat p4 = self.parameters[4];
|
CGFloat p4 = _parameters[4];
|
||||||
CGFloat p5 = self.parameters[5];
|
CGFloat p5 = _parameters[5];
|
||||||
return CGAffineTransformMake(p0, p1, p2, p3, p4, p5);
|
return CGAffineTransformMake(p0, p1, p2, p3, p4, p5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skewX
|
// skewX
|
||||||
case IJSVGTransformCommandSkewX: {
|
case IJSVGTransformCommandSkewX: {
|
||||||
CGFloat degrees = self.parameters[0];
|
CGFloat degrees = _parameters[0];
|
||||||
CGFloat radians = degrees * M_PI / 180.f;
|
CGFloat radians = degrees * M_PI / 180.f;
|
||||||
return CGAffineTransformMake(1.f, 0.f, tan(radians), 1.f, 0.f, 0.f);
|
return CGAffineTransformMake(1.f, 0.f, tan(radians), 1.f, 0.f, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skewY
|
// skewY
|
||||||
case IJSVGTransformCommandSkewY: {
|
case IJSVGTransformCommandSkewY: {
|
||||||
CGFloat degrees = self.parameters[0];
|
CGFloat degrees = _parameters[0];
|
||||||
CGFloat radians = degrees * M_PI / 180.f;
|
CGFloat radians = degrees * M_PI / 180.f;
|
||||||
return CGAffineTransformMake(1.f, tan(radians), 0.f, 1.f, 0.f, 0.f);
|
return CGAffineTransformMake(1.f, tan(radians), 0.f, 1.f, 0.f, 0.f);
|
||||||
}
|
}
|
||||||
@@ -370,15 +284,15 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier
|
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier
|
||||||
{
|
{
|
||||||
switch (self.command) {
|
switch (_command) {
|
||||||
// matrix
|
// matrix
|
||||||
case IJSVGTransformCommandMatrix: {
|
case IJSVGTransformCommandMatrix: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
CGFloat p2 = self.parameters[2];
|
CGFloat p2 = _parameters[2];
|
||||||
CGFloat p3 = self.parameters[3];
|
CGFloat p3 = _parameters[3];
|
||||||
CGFloat p4 = self.parameters[4];
|
CGFloat p4 = _parameters[4];
|
||||||
CGFloat p5 = self.parameters[5];
|
CGFloat p5 = _parameters[5];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
p0 = modifier(0, p0);
|
p0 = modifier(0, p0);
|
||||||
p1 = modifier(1, p1);
|
p1 = modifier(1, p1);
|
||||||
@@ -392,11 +306,11 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// translate
|
// translate
|
||||||
case IJSVGTransformCommandTranslate: {
|
case IJSVGTransformCommandTranslate: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return CGAffineTransformMakeTranslation(p0, 0);
|
return CGAffineTransformMakeTranslation(p0, 0);
|
||||||
}
|
}
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
p0 = modifier(0, p0);
|
p0 = modifier(0, p0);
|
||||||
p1 = modifier(1, p1);
|
p1 = modifier(1, p1);
|
||||||
@@ -406,7 +320,7 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// translateX
|
// translateX
|
||||||
case IJSVGTransformCommandTranslateX: {
|
case IJSVGTransformCommandTranslateX: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
p0 = modifier(0, p0);
|
p0 = modifier(0, p0);
|
||||||
}
|
}
|
||||||
@@ -415,7 +329,7 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// translateY
|
// translateY
|
||||||
case IJSVGTransformCommandTranslateY: {
|
case IJSVGTransformCommandTranslateY: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
p0 = modifier(0, p0);
|
p0 = modifier(0, p0);
|
||||||
}
|
}
|
||||||
@@ -424,11 +338,11 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// scale
|
// scale
|
||||||
case IJSVGTransformCommandScale: {
|
case IJSVGTransformCommandScale: {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return CGAffineTransformMakeScale(p0, p0);
|
return CGAffineTransformMakeScale(p0, p0);
|
||||||
}
|
}
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
p0 = modifier(0, p0);
|
p0 = modifier(0, p0);
|
||||||
p1 = modifier(1, p1);
|
p1 = modifier(1, p1);
|
||||||
@@ -438,7 +352,7 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// skewX
|
// skewX
|
||||||
case IJSVGTransformCommandSkewX: {
|
case IJSVGTransformCommandSkewX: {
|
||||||
CGFloat degrees = self.parameters[0];
|
CGFloat degrees = _parameters[0];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
degrees = modifier(0, degrees);
|
degrees = modifier(0, degrees);
|
||||||
}
|
}
|
||||||
@@ -448,7 +362,7 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// skewY
|
// skewY
|
||||||
case IJSVGTransformCommandSkewY: {
|
case IJSVGTransformCommandSkewY: {
|
||||||
CGFloat degrees = self.parameters[0];
|
CGFloat degrees = _parameters[0];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
degrees = modifier(0, degrees);
|
degrees = modifier(0, degrees);
|
||||||
}
|
}
|
||||||
@@ -458,12 +372,12 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
|
|
||||||
// rotate
|
// rotate
|
||||||
case IJSVGTransformCommandRotate: {
|
case IJSVGTransformCommandRotate: {
|
||||||
if (self.parameterCount == 1) {
|
if (_parameterCount == 1) {
|
||||||
return CGAffineTransformMakeRotation((self.parameters[0] / 180) * M_PI);
|
return CGAffineTransformMakeRotation((_parameters[0] / 180) * M_PI);
|
||||||
} else {
|
} else {
|
||||||
CGFloat p0 = self.parameters[0];
|
CGFloat p0 = _parameters[0];
|
||||||
CGFloat p1 = self.parameters[1];
|
CGFloat p1 = _parameters[1];
|
||||||
CGFloat p2 = self.parameters[2];
|
CGFloat p2 = _parameters[2];
|
||||||
if (modifier != nil) {
|
if (modifier != nil) {
|
||||||
p0 = modifier(0, p0);
|
p0 = modifier(0, p0);
|
||||||
p1 = modifier(1, p1);
|
p1 = modifier(1, p1);
|
||||||
@@ -493,15 +407,199 @@ void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApp
|
|||||||
return [self transformsForString:matrix];
|
return [self transformsForString:matrix];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSString*)affineTransformToSVGTransformComponentString:(CGAffineTransform)transform
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
NSArray<NSDictionary*>* trans = [self affineTransformToSVGTransformComponents:transform];
|
||||||
|
trans = [self filterUselessAffineTransformComponents:trans];
|
||||||
|
NSMutableArray<NSString*>* strings = [[[NSMutableArray alloc] initWithCapacity:trans.count] autorelease];
|
||||||
|
for (NSDictionary* dict in trans) {
|
||||||
|
NSArray<NSNumber*>* data = dict[@"data"];
|
||||||
|
NSString* method = dict[@"name"];
|
||||||
|
NSMutableArray* dataStrings = [[[NSMutableArray alloc] initWithCapacity:data.count] autorelease];
|
||||||
|
for (NSNumber* number in data) {
|
||||||
|
[dataStrings addObject:IJSVGShortFloatStringWithOptions(number.floatValue,
|
||||||
|
floatingPointOptions)];
|
||||||
|
}
|
||||||
|
[strings addObject:[NSString stringWithFormat:@"%@(%@)", method,
|
||||||
|
IJSVGCompressFloatParameterArray(dataStrings)]];
|
||||||
|
}
|
||||||
|
NSString* componentsString = [strings componentsJoinedByString:@" "];
|
||||||
|
NSString* matrixString = [self affineTransformToSVGMatrixString:transform
|
||||||
|
floatingPointOptions:floatingPointOptions];
|
||||||
|
return componentsString.length < matrixString.length ? componentsString : matrixString;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString*)affineTransformToSVGTransformComponentString:(CGAffineTransform)transform
|
||||||
|
{
|
||||||
|
NSArray<NSDictionary*>* trans = [self affineTransformToSVGTransformComponents:transform];
|
||||||
|
trans = [self filterUselessAffineTransformComponents:trans];
|
||||||
|
NSMutableArray<NSString*>* strings = [[[NSMutableArray alloc] initWithCapacity:trans.count] autorelease];
|
||||||
|
for (NSDictionary* dict in trans) {
|
||||||
|
NSArray<NSNumber*>* data = dict[@"data"];
|
||||||
|
NSString* method = dict[@"name"];
|
||||||
|
NSMutableArray* dataStrings = [[[NSMutableArray alloc] initWithCapacity:data.count] autorelease];
|
||||||
|
for (NSNumber* number in data) {
|
||||||
|
[dataStrings addObject:IJSVGShortFloatString(number.floatValue)];
|
||||||
|
}
|
||||||
|
[strings addObject:[NSString stringWithFormat:@"%@(%@)", method,
|
||||||
|
IJSVGCompressFloatParameterArray(dataStrings)]];
|
||||||
|
}
|
||||||
|
NSString* componentsString = [strings componentsJoinedByString:@" "];
|
||||||
|
NSString* matrixString = [self affineTransformToSVGMatrixString:transform];
|
||||||
|
return componentsString.length < matrixString.length ? componentsString : matrixString;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)transform
|
||||||
|
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
|
||||||
|
{
|
||||||
|
NSArray<NSString*>* numbers = @[
|
||||||
|
IJSVGShortFloatStringWithOptions(transform.a, floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(transform.b, floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(transform.c, floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(transform.d, floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(transform.tx, floatingPointOptions),
|
||||||
|
IJSVGShortFloatStringWithOptions(transform.ty, floatingPointOptions)
|
||||||
|
];
|
||||||
|
return [NSString stringWithFormat:@"matrix(%@)", IJSVGCompressFloatParameterArray(numbers)];
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)transform
|
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)transform
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat:@"matrix(%@ %@ %@ %@ %@ %@)",
|
NSArray<NSString*>* numbers = @[
|
||||||
IJSVGShortFloatString(transform.a),
|
IJSVGShortFloatString(transform.a),
|
||||||
IJSVGShortFloatString(transform.b),
|
IJSVGShortFloatString(transform.b),
|
||||||
IJSVGShortFloatString(transform.c),
|
IJSVGShortFloatString(transform.c),
|
||||||
IJSVGShortFloatString(transform.d),
|
IJSVGShortFloatString(transform.d),
|
||||||
IJSVGShortFloatString(transform.tx),
|
IJSVGShortFloatString(transform.tx),
|
||||||
IJSVGShortFloatString(transform.ty)];
|
IJSVGShortFloatString(transform.ty)
|
||||||
|
];
|
||||||
|
return [NSString stringWithFormat:@"matrix(%@)",
|
||||||
|
IJSVGCompressFloatParameterArray(numbers)];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSDictionary*>*)filterUselessAffineTransformComponents:(NSArray<NSDictionary*>*)components
|
||||||
|
{
|
||||||
|
NSMutableArray* comps = [[[NSMutableArray alloc] initWithCapacity:components.count] autorelease];
|
||||||
|
NSArray<NSString*>* names = @[ @"translate", @"rotate", @"skewX", @"skewY" ];
|
||||||
|
for (NSDictionary* transform in components) {
|
||||||
|
NSString* name = transform[@"name"];
|
||||||
|
NSArray<NSNumber*>* data = transform[@"data"];
|
||||||
|
if ([names containsObject:name] && (data.count == 1 || [name isEqualToString:@"rotate"]) && data[0].floatValue == 0.f) {
|
||||||
|
continue;
|
||||||
|
} else if ([name isEqualToString:@"translate"] && data[0].floatValue == 0.f && data[1].floatValue == 0.f) {
|
||||||
|
continue;
|
||||||
|
} else if ([name isEqualToString:@"scale"] && data[0].floatValue == 1.f && (data.count < 2 || (data.count == 2 && data[1].floatValue == 1.f))) {
|
||||||
|
continue;
|
||||||
|
} else if ([name isEqualToString:@"matrix"] && data[0].floatValue == 1.f && data[3].floatValue == 1.f && !(data[1].floatValue != 0.f || data[2].floatValue != 0.f || data[4].floatValue != 0.f || data[5].floatValue != 0.f)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[comps addObject:transform];
|
||||||
|
}
|
||||||
|
return comps;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSDictionary*>*)affineTransformToSVGTransformComponents:(CGAffineTransform)transform
|
||||||
|
{
|
||||||
|
const NSUInteger precision = 5;
|
||||||
|
CGFloat data[6] = {
|
||||||
|
IJSVGMathToFixed(transform.a, precision),
|
||||||
|
IJSVGMathToFixed(transform.b, precision),
|
||||||
|
IJSVGMathToFixed(transform.c, precision),
|
||||||
|
IJSVGMathToFixed(transform.d, precision),
|
||||||
|
IJSVGMathToFixed(transform.tx, precision),
|
||||||
|
IJSVGMathToFixed(transform.ty, precision)
|
||||||
|
};
|
||||||
|
|
||||||
|
CGFloat sx = IJSVGMathToFixed(hypotf(data[0], data[1]), precision);
|
||||||
|
CGFloat sy = IJSVGMathToFixed(((data[0] * data[3] - data[1] * data[2]) / sx), precision);
|
||||||
|
CGFloat colSum = data[0] * data[2] + data[1] * data[3];
|
||||||
|
CGFloat rowSum = data[0] * data[1] + data[2] * data[3];
|
||||||
|
BOOL scaleBefore = rowSum != 0.f || sx == sy;
|
||||||
|
|
||||||
|
NSMutableArray* transforms = [[[NSMutableArray alloc] init] autorelease];
|
||||||
|
|
||||||
|
// tx, ty -> translate
|
||||||
|
if (data[4] != 0.f || data[5] != 0.f) {
|
||||||
|
[transforms addObject:@{
|
||||||
|
@"name" : @"translate",
|
||||||
|
@"data" : @[ @(data[4]), @(data[5]) ]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// [sx, 0, tan(a).sy, sy, 0, 0] -> skewX(a).scale(sx,sy)
|
||||||
|
if (data[1] == 0.f && data[2] != 0.f) {
|
||||||
|
[transforms addObject:@{
|
||||||
|
@"name" : @"skewX",
|
||||||
|
@"data" : @[ @(IJSVGMathToFixed(IJSVGMathAtan(data[2] / sy), precision)) ]
|
||||||
|
}];
|
||||||
|
|
||||||
|
// [sx, sy.tan(a), 0, sy, 0, 0] -> skewX(a).scale(sx, sy)
|
||||||
|
} else if (data[1] != 0.f && data[2] == 0.f) {
|
||||||
|
[transforms addObject:@{
|
||||||
|
@"name" : @"skewY",
|
||||||
|
@"data" : @[ @(IJSVGMathToFixed(IJSVGMathAtan(data[1] / data[0]), precision)) ]
|
||||||
|
}];
|
||||||
|
sx = data[0];
|
||||||
|
sy = data[3];
|
||||||
|
} else if (colSum == 0.f || (sx == 1.f && sy == 1.f) || !scaleBefore) {
|
||||||
|
if (!scaleBefore) {
|
||||||
|
sx = (data[0] < 0.f ? -1.f : 1.f) * hypotf(data[0], data[2]);
|
||||||
|
sy = (data[3] < 0.f ? -1.f : 1.f) * hypotf(data[1], data[3]);
|
||||||
|
if (sx != 1.f || sy != 1.f) {
|
||||||
|
[transforms addObject:@{
|
||||||
|
@"name" : @"scale",
|
||||||
|
@"data" : (sx == sy) ? @[ @(sx) ] : @[ @(sx), @(sy) ]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat angle = MIN(MAX(-1.f, data[0] / sx), 1.f);
|
||||||
|
NSMutableArray<NSNumber*>* rotate = [[[NSMutableArray alloc] initWithCapacity:3] autorelease];
|
||||||
|
[rotate addObject:@(IJSVGMathToFixed(IJSVGMathAcos(angle), precision) * ((scaleBefore ? 1.f : sy) * data[1] < 0.f ? -1.f : 1.f))];
|
||||||
|
|
||||||
|
if (rotate[0].floatValue != 0.f) {
|
||||||
|
[transforms addObject:@{
|
||||||
|
@"name" : @"rotate",
|
||||||
|
@"data" : rotate
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rowSum != 0.f && colSum != 0.f) {
|
||||||
|
[transforms addObject:@{
|
||||||
|
@"name" : @"skewX",
|
||||||
|
@"data" : @[ @(IJSVGMathToFixed(IJSVGMathAtan(colSum / (sx * sx)), precision)) ]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// rotate can consume translate
|
||||||
|
if (rotate[0].floatValue != 0.f && (data[4] != 0.f || data[5] != 0.f)) {
|
||||||
|
[transforms removeObjectAtIndex:0];
|
||||||
|
CGFloat cos = data[0] / sx;
|
||||||
|
CGFloat sin = data[1] / (scaleBefore ? sx : sy);
|
||||||
|
CGFloat x = data[4] * (scaleBefore ? 1.f : sy);
|
||||||
|
CGFloat y = data[5] * (scaleBefore ? 1.f : sx);
|
||||||
|
CGFloat denom = (powf(1.f - cos, 2.f) + powf(sin, 2.f)) * (scaleBefore ? 1.f : (sx * sy));
|
||||||
|
[rotate addObject:@(((1.f - cos) * x - sin * y) / denom)];
|
||||||
|
[rotate addObject:@(((1.f - cos) * y + sin * x) / denom)];
|
||||||
|
}
|
||||||
|
} else if (data[1] != 0.f || data[2] != 0.f) {
|
||||||
|
NSDictionary* trans = @{
|
||||||
|
@"name" : @"matrix",
|
||||||
|
@"data" : @[ @(data[0]), @(data[1]), @(data[2]), @(data[3]), @(data[4]), @(data[5]) ]
|
||||||
|
};
|
||||||
|
return @[ trans ];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaleBefore == YES && ((sx != 1.f || sy != 1.f) || transforms.count == 0)) {
|
||||||
|
NSDictionary* trans = @{
|
||||||
|
@"name" : @"scale",
|
||||||
|
@"data" : (sx == sy) ? @[ @(sx) ] : @[ @(sx), @(sy) ]
|
||||||
|
};
|
||||||
|
[transforms addObject:trans];
|
||||||
|
}
|
||||||
|
|
||||||
|
return transforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*)description
|
- (NSString*)description
|
||||||
|
|||||||
@@ -8,9 +8,20 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BOOL round;
|
||||||
|
int precision;
|
||||||
|
} IJSVGFloatingPointOptions;
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, IJSVGUnitLengthType) {
|
typedef NS_ENUM(NSInteger, IJSVGUnitLengthType) {
|
||||||
IJSVGUnitLengthTypeNumber,
|
IJSVGUnitLengthTypeNumber,
|
||||||
IJSVGUnitLengthTypePercentage
|
IJSVGUnitLengthTypePercentage,
|
||||||
|
IJSVGUnitLengthTypeCM,
|
||||||
|
IJSVGUnitLengthTypeMM,
|
||||||
|
IJSVGUnitLengthTypeIN,
|
||||||
|
IJSVGUnitLengthTypePT,
|
||||||
|
IJSVGUnitLengthTypePC,
|
||||||
|
IJSVGUnitLengthTypePX
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, IJSVGUnitType) {
|
typedef NS_ENUM(NSInteger, IJSVGUnitType) {
|
||||||
@@ -22,6 +33,7 @@ typedef NS_ENUM(NSInteger, IJSVGUnitType) {
|
|||||||
@interface IJSVGUnitLength : NSObject
|
@interface IJSVGUnitLength : NSObject
|
||||||
|
|
||||||
@property (nonatomic, assign) IJSVGUnitLengthType type;
|
@property (nonatomic, assign) IJSVGUnitLengthType type;
|
||||||
|
@property (nonatomic, assign) IJSVGUnitLengthType originalType;
|
||||||
@property (nonatomic, assign) CGFloat value;
|
@property (nonatomic, assign) CGFloat value;
|
||||||
@property (nonatomic, assign) BOOL inherit;
|
@property (nonatomic, assign) BOOL inherit;
|
||||||
|
|
||||||
@@ -38,5 +50,6 @@ typedef NS_ENUM(NSInteger, IJSVGUnitType) {
|
|||||||
- (CGFloat)valueAsPercentage;
|
- (CGFloat)valueAsPercentage;
|
||||||
- (CGFloat)computeValue:(CGFloat)anotherValue;
|
- (CGFloat)computeValue:(CGFloat)anotherValue;
|
||||||
- (NSString*)stringValue;
|
- (NSString*)stringValue;
|
||||||
|
- (NSString*)stringValueWithFloatingPointOptions:(IJSVGFloatingPointOptions)options;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
@implementation IJSVGUnitLength
|
@implementation IJSVGUnitLength
|
||||||
|
|
||||||
@synthesize value;
|
|
||||||
@synthesize type;
|
|
||||||
@synthesize inherit;
|
|
||||||
|
|
||||||
+ (IJSVGUnitLength*)unitWithFloat:(CGFloat)number
|
+ (IJSVGUnitLength*)unitWithFloat:(CGFloat)number
|
||||||
{
|
{
|
||||||
IJSVGUnitLength* unit = [[[self alloc] init] autorelease];
|
IJSVGUnitLength* unit = [[[self alloc] init] autorelease];
|
||||||
@@ -55,23 +51,143 @@
|
|||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (IJSVGUnitLengthType)typeForCString:(const char*)chars
|
||||||
|
{
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "%")) {
|
||||||
|
return IJSVGUnitLengthTypePercentage;
|
||||||
|
}
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "cm")) {
|
||||||
|
return IJSVGUnitLengthTypeCM;
|
||||||
|
}
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "mm")) {
|
||||||
|
return IJSVGUnitLengthTypeMM;
|
||||||
|
}
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "in")) {
|
||||||
|
return IJSVGUnitLengthTypeIN;
|
||||||
|
}
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "pt")) {
|
||||||
|
return IJSVGUnitLengthTypePT;
|
||||||
|
}
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "pc")) {
|
||||||
|
return IJSVGUnitLengthTypePC;
|
||||||
|
}
|
||||||
|
if(IJSVGCharBufferHasSuffix((char*)chars, "px")) {
|
||||||
|
return IJSVGUnitLengthTypePX;
|
||||||
|
}
|
||||||
|
return IJSVGUnitLengthTypeNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (IJSVGUnitLengthType)typeForString:(NSString*)string
|
||||||
|
{
|
||||||
|
if([string hasSuffix:@"%"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypePercentage;
|
||||||
|
}
|
||||||
|
if([string hasSuffix:@"cm"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypeCM;
|
||||||
|
}
|
||||||
|
if([string hasSuffix:@"mm"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypeMM;
|
||||||
|
}
|
||||||
|
if([string hasSuffix:@"in"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypeIN;
|
||||||
|
}
|
||||||
|
if([string hasSuffix:@"pt"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypePT;
|
||||||
|
}
|
||||||
|
if([string hasSuffix:@"pc"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypePC;
|
||||||
|
}
|
||||||
|
if([string hasSuffix:@"px"] == YES) {
|
||||||
|
return IJSVGUnitLengthTypePX;
|
||||||
|
}
|
||||||
|
return IJSVGUnitLengthTypeNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CGFloat)convertUnitValue:(CGFloat)unit
|
||||||
|
toBaseFromUnitLengthType:(IJSVGUnitLengthType)type
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case IJSVGUnitLengthTypeCM: {
|
||||||
|
return unit * (96.f / 2.54f);
|
||||||
|
}
|
||||||
|
case IJSVGUnitLengthTypeMM: {
|
||||||
|
return [self convertUnitValue:unit
|
||||||
|
toBaseFromUnitLengthType:IJSVGUnitLengthTypeCM] / 10.f;
|
||||||
|
}
|
||||||
|
case IJSVGUnitLengthTypePercentage: {
|
||||||
|
return unit / 100.f;
|
||||||
|
}
|
||||||
|
case IJSVGUnitLengthTypeIN: {
|
||||||
|
// 1in = 96px
|
||||||
|
return unit * 96.f;
|
||||||
|
}
|
||||||
|
case IJSVGUnitLengthTypePT: {
|
||||||
|
// 1pt = 1.333...px
|
||||||
|
return unit * 1.3333333f;
|
||||||
|
}
|
||||||
|
case IJSVGUnitLengthTypePC: {
|
||||||
|
// 1pc = 16px
|
||||||
|
return unit * 16.f;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
+ (IJSVGUnitLength*)unitWithString:(NSString*)string
|
+ (IJSVGUnitLength*)unitWithString:(NSString*)string
|
||||||
{
|
{
|
||||||
// just return noting for inherit, node will deal
|
// just return noting for inherit, node will deal
|
||||||
// with the rest...hopefully
|
// with the rest...hopefully
|
||||||
NSCharacterSet* cSet = NSCharacterSet.whitespaceCharacterSet;
|
if(string == nil) {
|
||||||
string = [string stringByTrimmingCharactersInSet:cSet];
|
|
||||||
|
|
||||||
if ([string isEqualToString:@"inherit"]) {
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* chars = IJSVGTimmedCharBufferCreate(string.UTF8String);
|
||||||
|
|
||||||
|
// is inherit or just nothing
|
||||||
|
size_t strl = strlen(chars);
|
||||||
|
if (strcmp(chars, "inherit") == 0 || strl == 0) {
|
||||||
|
(void)free(chars), chars = NULL;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab the float value from the string
|
||||||
|
NSInteger length;
|
||||||
|
CGFloat* floats = [IJSVGUtils scanFloatsFromCString:chars
|
||||||
|
floatCount:1
|
||||||
|
charCount:(NSUInteger)strl
|
||||||
|
size:&length];
|
||||||
|
// not sure how this ended up but nothing returned
|
||||||
|
// even though there should had been
|
||||||
|
if(length == 0) {
|
||||||
|
(void)free(floats), floats = NULL;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
IJSVGUnitLength* unit = [[[self alloc] init] autorelease];
|
IJSVGUnitLength* unit = [[[self alloc] init] autorelease];
|
||||||
unit.value = string.floatValue;
|
unit.value = floats[0];
|
||||||
unit.type = IJSVGUnitLengthTypeNumber;
|
unit.type = IJSVGUnitLengthTypeNumber;
|
||||||
if ([string hasSuffix:@"%"] == YES) {
|
|
||||||
unit.value /= 100.f;
|
|
||||||
unit.type = IJSVGUnitLengthTypePercentage;
|
IJSVGUnitLengthType type = [self typeForCString:chars];
|
||||||
|
unit.originalType = type;
|
||||||
|
|
||||||
|
// memory free
|
||||||
|
(void)(free(floats)), floats = NULL;
|
||||||
|
(void)free(chars), chars = NULL;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case IJSVGUnitLengthTypePercentage: {
|
||||||
|
unit.value = [self convertUnitValue:unit.value
|
||||||
|
toBaseFromUnitLengthType:type];
|
||||||
|
unit.type = IJSVGUnitLengthTypePercentage;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
unit.value = [self convertUnitValue:unit.value
|
||||||
|
toBaseFromUnitLengthType:type];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
@@ -79,7 +195,7 @@
|
|||||||
- (CGFloat)computeValue:(CGFloat)anotherValue
|
- (CGFloat)computeValue:(CGFloat)anotherValue
|
||||||
{
|
{
|
||||||
if (self.type == IJSVGUnitLengthTypePercentage) {
|
if (self.type == IJSVGUnitLengthTypePercentage) {
|
||||||
return ((anotherValue / 100.f) * (self.value * 100.f));
|
return ((anotherValue / 100.f) * (_value * 100.f));
|
||||||
}
|
}
|
||||||
return self.value;
|
return self.value;
|
||||||
}
|
}
|
||||||
@@ -92,15 +208,25 @@
|
|||||||
- (NSString*)stringValue
|
- (NSString*)stringValue
|
||||||
{
|
{
|
||||||
if (self.type == IJSVGUnitLengthTypePercentage) {
|
if (self.type == IJSVGUnitLengthTypePercentage) {
|
||||||
return [NSString stringWithFormat:@"%@%%", IJSVGShortFloatString(self.value * 100.f)];
|
return [NSString stringWithFormat:@"%@%%",
|
||||||
|
IJSVGShortFloatString(self.value * 100.f)];
|
||||||
}
|
}
|
||||||
return IJSVGShortFloatString(self.value);
|
return IJSVGShortFloatString(self.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString*)stringValueWithFloatingPointOptions:(IJSVGFloatingPointOptions)options
|
||||||
|
{
|
||||||
|
if (_type == IJSVGUnitLengthTypePercentage) {
|
||||||
|
return [NSString stringWithFormat:@"%@%%",
|
||||||
|
IJSVGShortFloatStringWithOptions(_value * 100.f, options)];
|
||||||
|
}
|
||||||
|
return IJSVGShortFloatStringWithOptions(_value, options);
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString*)description
|
- (NSString*)description
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat:@"%f%@",
|
return [NSString stringWithFormat:@"%f%@",
|
||||||
self.value, (self.type == IJSVGUnitLengthTypePercentage ? @"%" : @"")];
|
_value, (_value == IJSVGUnitLengthTypePercentage ? @"%" : @"")];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// IJSVGUnitPoint.h
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 12/02/2020.
|
||||||
|
// Copyright © 2020 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IJSVG/IJSVGUnitLength.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface IJSVGUnitPoint : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, retain) IJSVGUnitLength* x;
|
||||||
|
@property (nonatomic, retain) IJSVGUnitLength* y;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// IJSVGUnitPoint.m
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 12/02/2020.
|
||||||
|
// Copyright © 2020 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IJSVGUnitPoint.h"
|
||||||
|
|
||||||
|
@implementation IJSVGUnitPoint
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
(void)[_x release], _x = nil;
|
||||||
|
(void)[_y release], _y = nil;
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (IJSVGUnitPoint*)pointWithX:(IJSVGUnitLength*)x
|
||||||
|
y:(IJSVGUnitLength*)y
|
||||||
|
{
|
||||||
|
IJSVGUnitPoint* point = [[[self alloc] init] autorelease];
|
||||||
|
point.x = x;
|
||||||
|
point.y = y;
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// IJSVGUnitRect.h
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 12/02/2020.
|
||||||
|
// Copyright © 2020 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <IJSVG/IJSVGUnitPoint.h>
|
||||||
|
#import <IJSVG/IJSVGUnitSize.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface IJSVGUnitRect : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, retain) IJSVGUnitSize* size;
|
||||||
|
@property (nonatomic, retain) IJSVGUnitPoint* origin;
|
||||||
|
|
||||||
|
+ (IJSVGUnitRect*)rectWithOrigin:(IJSVGUnitPoint*)origin
|
||||||
|
size:(IJSVGUnitSize*)size;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// IJSVGUnitRect.m
|
||||||
|
// IJSVG
|
||||||
|
//
|
||||||
|
// Created by Curtis Hard on 12/02/2020.
|
||||||
|
// Copyright © 2020 Curtis Hard. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IJSVGUnitRect.h"
|
||||||
|
|
||||||
|
@implementation IJSVGUnitRect
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
(void)[_size release], _size = nil;
|
||||||
|
(void)[_origin release], _origin = nil;
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (IJSVGUnitRect*)rectWithOrigin:(IJSVGUnitPoint*)origin
|
||||||
|
size:(IJSVGUnitSize*)size
|
||||||
|
{
|
||||||
|
IJSVGUnitRect* rect = [[[self alloc] init] autorelease];
|
||||||
|
rect.origin = origin;
|
||||||
|
rect.size = size;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user