Compare commits

..

50 Commits

Author SHA1 Message Date
Curtis Hard ffb55b0f31 Fixes viewBox origin translate 2018-03-02 13:28:40 +00:00
Curtis Hard a4c032afa2 Added clip to viewport 2018-02-28 21:29:11 +00:00
Curtis Hard abe8f4cba5 Fixes drawInRect not obeying origin 2018-02-28 21:00:20 +00:00
Curtis Hard a16842271b Resolves namespaces correctly + added common HTML list to be parsed as groups 2018-02-26 13:46:41 +00:00
Curtis Hard 58126e06e4 Fixes! 2018-02-25 21:58:49 +00:00
Curtis Hard 5af5e054ab Fixed defNode being removed 2018-02-23 22:37:53 +00:00
Curtis Hard edd3aa1f33 excluded various elements from diff 2018-02-23 16:29:54 +00:00
Curtis Hard 3366bc4fa5 Better optimaztion 2018-02-23 14:05:03 +00:00
Curtis Hard 104002183b Added rudimenatry inline styles -> stylesheet 2018-02-22 22:17:50 +00:00
Curtis Hard 7010b7ea50 Correct order of cleanup 2018-02-22 13:33:32 +00:00
Curtis Hard 5266a8c07a corrent length of string 2018-02-22 08:22:17 +00:00
Curtis Hard caf55e8bdf removes useless def if required 2018-02-21 20:45:17 +00:00
Curtis Hard 8160d05eba Refactor of a few methods 2018-02-20 14:12:02 +00:00
Curtis Hard a6d6a06521 Added collpasing of gradients 2018-02-20 09:40:21 +00:00
Curtis Hard 103a4d71f6 Reduced floats even more 2018-02-19 19:07:30 +00:00
Curtis Hard 98874b1d2c More compression goodness 2018-02-19 18:53:02 +00:00
Curtis Hard e742db31e0 Added intermediateParent 2018-02-19 14:02:15 +00:00
Curtis Hard 198fd09f07 Fixes! and performance increases 2018-02-19 11:51:37 +00:00
Curtis Hard 3493194b1b Scale computation 2018-02-19 08:20:02 +00:00
Curtis Hard 0016775eaf More goodness 2018-02-18 22:33:26 +00:00
Curtis Hard 304a04cc22 Vastly improved the exporter 2018-02-18 22:32:04 +00:00
Curtis Hard e4fd0af582 This is insanely important! 2018-02-18 15:20:28 +00:00
Curtis Hard 69a2a0c97e Refactor 2018-02-04 22:02:19 +00:00
Curtis Hard 5299bb0479 will continue to use CoreAnimation for the time being 2018-02-04 21:58:21 +00:00
Curtis Hard 4f1943cad1 Fixes gradient strokes 2018-02-04 21:57:46 +00:00
Curtis Hard f02d186293 trying to get masks to work 2018-02-04 11:15:04 +00:00
Curtis Hard 3291718cfb Beginning of quartz renderer 2018-02-02 22:35:22 +00:00
Curtis Hard 6fbaaf5884 Removed useless log 2018-01-29 22:32:08 +00:00
Curtis Hard abc65797ea I think gradients work :D 2018-01-29 21:37:45 +00:00
Curtis Hard af5a1c2718 Possible fx and fy things… 2018-01-28 22:18:02 +00:00
Curtis Hard fb9a5282b9 Even more gradient fixes 2018-01-28 19:22:40 +00:00
Curtis Hard d83933a103 Various improvements 2018-01-28 14:21:50 +00:00
Curtis Hard bd7a0d5021 Start to linear 2018-01-27 22:26:33 +00:00
Curtis Hard a9a038568c This kind of actually works... 2018-01-27 21:14:25 +00:00
Curtis Hard 77fbb38b6f I guess this could be a good start?
Posssible start of fixes?
2018-01-27 20:32:13 +00:00
Curtis Hard 12c3191569 Added method for findind absolute position 2018-01-27 15:32:15 +00:00
Curtis Hard e3e9626ef7 Fixes crash due to parentNode on temp groups being released 2018-01-27 14:25:03 +00:00
Curtis Hard 1160d89f16 Fixes use statements with transforms 2018-01-26 22:29:22 +00:00
Curtis Hard 1575cbfde8 Moved color tree over to modern syntax 2018-01-26 18:16:03 +00:00
Curtis Hard 5c4c2eee91 Added HSL/HSLA support 2018-01-25 18:23:53 +00:00
Curtis Hard 087b13e58f Various image loading issues resolved from base64 images 2018-01-24 22:24:43 +00:00
Curtis Hard 1183e167aa Rect issue fix 2018-01-24 21:21:41 +00:00
Curtis Hard 4dbfc59437 Moved transforms over from being concatinated to seperate calls 2018-01-24 21:19:24 +00:00
Curtis Hard 409bd509fa Fixes color issue 2018-01-24 20:30:38 +00:00
Curtis Hard 8ae1d1b4e0 Removed check as its not needed here 2018-01-24 18:41:08 +00:00
Curtis Hard 7243fbe5ff Added excludeAttributes list to parseCommonAttributes
added x and y to that list for rect
2018-01-24 18:35:43 +00:00
Curtis Hard 51b9a5e85f Added isSubcommand to IJSVGCommand
- Fixes move command going awol when preceding move commands are not subcommands (woah)
2018-01-23 19:53:04 +00:00
Curtis Hard 40098589de removed reverseObjectEnumerator
IJSVGTransform already deals with this at parse stage (was a test from earlier), spec states transforms are applied in reverse order (which parser already dealth with :-))
2018-01-22 22:04:48 +00:00
Curtis Hard 7cb96b21f2 Removed use of origin here as its computed in apply defaults 2018-01-22 22:01:56 +00:00
Curtis Hard 1bff7c6970 Various fixes… still going… 2018-01-22 21:48:59 +00:00
194 changed files with 10758 additions and 17373 deletions
@@ -1,939 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* 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 */; };
594CF561238FF46C009B251B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF560238FF46C009B251B /* Foundation.framework */; };
594CF563238FF473009B251B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF562238FF473009B251B /* QuartzCore.framework */; };
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, ); }; };
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, ); }; };
59EB75D723905F7300F5AE63 /* IJSVGGradientLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756623905F6B00F5AE63 /* IJSVGGradientLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75D823905F7300F5AE63 /* IJSVGStyleSheetRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756723905F6B00F5AE63 /* IJSVGStyleSheetRule.m */; };
59EB75D923905F7300F5AE63 /* IJSVGCommandLineTo.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756823905F6B00F5AE63 /* IJSVGCommandLineTo.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75DA23905F7300F5AE63 /* IJSVGDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756923905F6B00F5AE63 /* IJSVGDef.m */; };
59EB75DB23905F7300F5AE63 /* IJSVG.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756A23905F6B00F5AE63 /* IJSVG.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 */; };
59EB75DE23905F7300F5AE63 /* IJSVGCommandVerticalLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.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, ); }; };
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757123905F6C00F5AE63 /* IJSVGColorList.m */; };
59EB75E323905F7300F5AE63 /* IJSVGRadialGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757323905F6C00F5AE63 /* IJSVGGradientUnitLength.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E523905F7300F5AE63 /* IJSVGStrokeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */; };
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757523905F6C00F5AE63 /* IJSVGStyle.m */; };
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757623905F6C00F5AE63 /* IJSVGImage.m */; };
59EB75E823905F7300F5AE63 /* IJSVGUnitLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757723905F6C00F5AE63 /* IJSVGUnitLength.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */; };
59EB75EA23905F7300F5AE63 /* IJSVGTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757923905F6C00F5AE63 /* IJSVGTransaction.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */; };
59EB75EC23905F7300F5AE63 /* IJSVGLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */; };
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */; };
59EB75EE23905F7300F5AE63 /* IJSVGImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */; };
59EB75EF23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757E23905F6C00F5AE63 /* IJSVGCommandQuadraticCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F023905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757F23905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F123905F7300F5AE63 /* IJSVGUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758023905F6C00F5AE63 /* IJSVGUtils.m */; };
59EB75F223905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758123905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.m */; };
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758223905F6C00F5AE63 /* IJSVGGroupLayer.m */; };
59EB75F423905F7300F5AE63 /* IJSVGColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758323905F6C00F5AE63 /* IJSVGColor.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F523905F7300F5AE63 /* IJSVGError.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758423905F6C00F5AE63 /* IJSVGError.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758523905F6C00F5AE63 /* IJSVGColor.m */; };
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 */; };
59EB75F923905F7300F5AE63 /* IJSVGFontConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */; settings = {ATTRIBUTES = (Public, ); }; };
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, ); }; };
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */; };
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */; };
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */; };
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */; };
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */; };
59EB760323905F7300F5AE63 /* IJSVGNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759223905F6D00F5AE63 /* IJSVGNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760523905F7300F5AE63 /* IJSVGUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759423905F6D00F5AE63 /* IJSVGUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760623905F7300F5AE63 /* IJSVGCommandHorizontalLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759523905F6D00F5AE63 /* IJSVGCommandHorizontalLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759623905F6D00F5AE63 /* IJSVGNode.m */; };
59EB760823905F7300F5AE63 /* IJSVGShapeLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760923905F7300F5AE63 /* IJSVGCommandCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759823905F6E00F5AE63 /* IJSVGCommandCurve.m */; };
59EB760A23905F7300F5AE63 /* IJSVGCommandMove.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759923905F6E00F5AE63 /* IJSVGCommandMove.m */; };
59EB760B23905F7300F5AE63 /* IJSVGStyleSheetSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759A23905F6E00F5AE63 /* IJSVGStyleSheetSelector.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760C23905F7300F5AE63 /* IJSVGStyleSheetRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759B23905F6E00F5AE63 /* IJSVGStyleSheetRule.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760D23905F7300F5AE63 /* IJSVGCommandCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759C23905F6E00F5AE63 /* IJSVGCommandCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760E23905F7300F5AE63 /* IJSVGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759D23905F6E00F5AE63 /* IJSVGPath.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760F23905F7300F5AE63 /* IJSVGCommandEllipticalArc.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759E23905F6E00F5AE63 /* IJSVGCommandEllipticalArc.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761023905F7300F5AE63 /* IJSVGLinearGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761123905F7300F5AE63 /* IJSVGCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A023905F6E00F5AE63 /* IJSVGCommand.m */; };
59EB761223905F7300F5AE63 /* IJSVGRenderingStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A123905F6E00F5AE63 /* IJSVGRenderingStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761323905F7300F5AE63 /* IJSVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A223905F6E00F5AE63 /* IJSVG.m */; };
59EB761423905F7300F5AE63 /* IJSVGImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761523905F7300F5AE63 /* IJSVGStrokeLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761623905F7300F5AE63 /* IJSVGParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A523905F6E00F5AE63 /* IJSVGParser.m */; };
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */; };
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A723905F6F00F5AE63 /* IJSVGParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761923905F7300F5AE63 /* IJSVGCommandSmoothCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A823905F6F00F5AE63 /* IJSVGCommandSmoothCurve.m */; };
59EB761A23905F7300F5AE63 /* IJSVGColorList.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761B23905F7300F5AE63 /* IJSVGPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75AA23905F6F00F5AE63 /* IJSVGPattern.m */; };
59EB761C23905F7300F5AE63 /* IJSVGGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761D23905F7300F5AE63 /* IJSVGStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AC23905F6F00F5AE63 /* IJSVGStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AD23905F6F00F5AE63 /* IJSVGGroupLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761F23905F7300F5AE63 /* IJSVGCommandLineTo.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75AE23905F6F00F5AE63 /* IJSVGCommandLineTo.m */; };
59EB762023905F7300F5AE63 /* IJSVGCommandMove.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AF23905F6F00F5AE63 /* IJSVGCommandMove.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762123905F7300F5AE63 /* IJSVGTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B023905F6F00F5AE63 /* IJSVGTransform.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762223905F7300F5AE63 /* IJSVGMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B123905F6F00F5AE63 /* IJSVGMath.m */; };
59EB762323905F7300F5AE63 /* IJSVGExporterPathInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B223905F6F00F5AE63 /* IJSVGExporterPathInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762423905F7300F5AE63 /* IJSVGTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B323905F6F00F5AE63 /* IJSVGTransaction.m */; };
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B423905F6F00F5AE63 /* IJSVGTransform.m */; };
59EB762623905F7300F5AE63 /* IJSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B523905F7000F5AE63 /* IJSVGImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762723905F7300F5AE63 /* IJSVGMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B623905F7000F5AE63 /* IJSVGMath.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B723905F7000F5AE63 /* IJSVGCommandClose.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762923905F7300F5AE63 /* IJSVGStringAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762A23905F7300F5AE63 /* IJSVGGradientUnitLength.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B923905F7000F5AE63 /* IJSVGGradientUnitLength.m */; };
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */; };
59EB762C23905F7300F5AE63 /* IJSVGPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BB23905F7000F5AE63 /* IJSVGPattern.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762D23905F7300F5AE63 /* IJSVGLayerTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BC23905F7000F5AE63 /* IJSVGLayerTree.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762E23905F7300F5AE63 /* IJSVGExporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75BD23905F7000F5AE63 /* IJSVGExporter.m */; };
59EB763023905F7300F5AE63 /* IJSVGPatternLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C023905F7100F5AE63 /* IJSVGText.m */; };
59EB763223905F7300F5AE63 /* IJSVGView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C123905F7100F5AE63 /* IJSVGView.m */; };
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */; };
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */; };
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */; };
59EB763723905F7300F5AE63 /* IJSVGCommandClose.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */; };
59EB763823905F7300F5AE63 /* IJSVGCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75C723905F7100F5AE63 /* IJSVGCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763923905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C823905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m */; };
59EB763A23905F7300F5AE63 /* IJSVGForeignObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C923905F7200F5AE63 /* IJSVGForeignObject.m */; };
59EB763B23905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75CA23905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75CB23905F7200F5AE63 /* IJSVGCommandEllipticalArc.m */; };
59EB763D23905F7300F5AE63 /* IJSVGGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75CC23905F7200F5AE63 /* IJSVGGroup.m */; };
59EB763E23905F7300F5AE63 /* IJSVGView.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75CD23905F7200F5AE63 /* IJSVGView.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763F23905F7300F5AE63 /* IJSVGForeignObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75CE23905F7200F5AE63 /* IJSVGForeignObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB764023905F7300F5AE63 /* IJSVGExporterPathInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75CF23905F7200F5AE63 /* IJSVGExporterPathInstruction.m */; };
59EB764123905F7300F5AE63 /* IJSVGImageLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D023905F7200F5AE63 /* IJSVGImageLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB764223905F7300F5AE63 /* IJSVGStyleSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D123905F7300F5AE63 /* IJSVGStyleSheet.m */; };
59EB764323905F7300F5AE63 /* IJSVGGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D223905F7300F5AE63 /* IJSVGGradient.m */; };
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, ); }; };
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 */
/* 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; };
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; };
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; };
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; };
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>"; };
59EB756623905F6B00F5AE63 /* IJSVGGradientLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradientLayer.h; sourceTree = "<group>"; };
59EB756723905F6B00F5AE63 /* IJSVGStyleSheetRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetRule.m; sourceTree = "<group>"; };
59EB756823905F6B00F5AE63 /* IJSVGCommandLineTo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandLineTo.h; sourceTree = "<group>"; };
59EB756923905F6B00F5AE63 /* IJSVGDef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGDef.m; sourceTree = "<group>"; };
59EB756A23905F6B00F5AE63 /* IJSVG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVG.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>"; };
59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandVerticalLine.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>"; };
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGColorList.m; sourceTree = "<group>"; };
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRadialGradient.h; sourceTree = "<group>"; };
59EB757323905F6C00F5AE63 /* IJSVGGradientUnitLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradientUnitLength.h; sourceTree = "<group>"; };
59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStrokeLayer.m; sourceTree = "<group>"; };
59EB757523905F6C00F5AE63 /* IJSVGStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyle.m; sourceTree = "<group>"; };
59EB757623905F6C00F5AE63 /* IJSVGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImage.m; sourceTree = "<group>"; };
59EB757723905F6C00F5AE63 /* IJSVGUnitLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitLength.h; sourceTree = "<group>"; };
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStringAdditions.m; sourceTree = "<group>"; };
59EB757923905F6C00F5AE63 /* IJSVGTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGTransaction.h; sourceTree = "<group>"; };
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGShapeLayer.m; sourceTree = "<group>"; };
59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLayer.m; sourceTree = "<group>"; };
59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGFontConverter.m; sourceTree = "<group>"; };
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImageRep.m; sourceTree = "<group>"; };
59EB757E23905F6C00F5AE63 /* IJSVGCommandQuadraticCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandQuadraticCurve.h; sourceTree = "<group>"; };
59EB757F23905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheetSelectorRaw.h; sourceTree = "<group>"; };
59EB758023905F6C00F5AE63 /* IJSVGUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGUtils.m; sourceTree = "<group>"; };
59EB758123905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetSelectorRaw.m; sourceTree = "<group>"; };
59EB758223905F6C00F5AE63 /* IJSVGGroupLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGroupLayer.m; sourceTree = "<group>"; };
59EB758323905F6C00F5AE63 /* IJSVGColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGColor.h; sourceTree = "<group>"; };
59EB758423905F6C00F5AE63 /* IJSVGError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGError.h; sourceTree = "<group>"; };
59EB758523905F6C00F5AE63 /* IJSVGColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGColor.m; 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>"; };
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGFontConverter.h; 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>"; };
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>"; };
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>"; };
59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandVerticalLine.m; sourceTree = "<group>"; };
59EB759223905F6D00F5AE63 /* IJSVGNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGNode.h; sourceTree = "<group>"; };
59EB759423905F6D00F5AE63 /* IJSVGUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGUtils.h; sourceTree = "<group>"; };
59EB759523905F6D00F5AE63 /* IJSVGCommandHorizontalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandHorizontalLine.h; sourceTree = "<group>"; };
59EB759623905F6D00F5AE63 /* IJSVGNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGNode.m; sourceTree = "<group>"; };
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGShapeLayer.h; sourceTree = "<group>"; };
59EB759823905F6E00F5AE63 /* IJSVGCommandCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandCurve.m; sourceTree = "<group>"; };
59EB759923905F6E00F5AE63 /* IJSVGCommandMove.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandMove.m; sourceTree = "<group>"; };
59EB759A23905F6E00F5AE63 /* IJSVGStyleSheetSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheetSelector.h; sourceTree = "<group>"; };
59EB759B23905F6E00F5AE63 /* IJSVGStyleSheetRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheetRule.h; sourceTree = "<group>"; };
59EB759C23905F6E00F5AE63 /* IJSVGCommandCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandCurve.h; sourceTree = "<group>"; };
59EB759D23905F6E00F5AE63 /* IJSVGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGPath.h; sourceTree = "<group>"; };
59EB759E23905F6E00F5AE63 /* IJSVGCommandEllipticalArc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandEllipticalArc.h; sourceTree = "<group>"; };
59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLinearGradient.h; sourceTree = "<group>"; };
59EB75A023905F6E00F5AE63 /* IJSVGCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommand.m; sourceTree = "<group>"; };
59EB75A123905F6E00F5AE63 /* IJSVGRenderingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRenderingStyle.h; sourceTree = "<group>"; };
59EB75A223905F6E00F5AE63 /* IJSVG.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVG.m; sourceTree = "<group>"; };
59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImageRep.h; sourceTree = "<group>"; };
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStrokeLayer.h; sourceTree = "<group>"; };
59EB75A523905F6E00F5AE63 /* IJSVGParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGParser.m; sourceTree = "<group>"; };
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRadialGradient.m; sourceTree = "<group>"; };
59EB75A723905F6F00F5AE63 /* IJSVGParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGParser.h; sourceTree = "<group>"; };
59EB75A823905F6F00F5AE63 /* IJSVGCommandSmoothCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandSmoothCurve.m; sourceTree = "<group>"; };
59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGColorList.h; sourceTree = "<group>"; };
59EB75AA23905F6F00F5AE63 /* IJSVGPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPattern.m; sourceTree = "<group>"; };
59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradient.h; sourceTree = "<group>"; };
59EB75AC23905F6F00F5AE63 /* IJSVGStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyle.h; sourceTree = "<group>"; };
59EB75AD23905F6F00F5AE63 /* IJSVGGroupLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGroupLayer.h; sourceTree = "<group>"; };
59EB75AE23905F6F00F5AE63 /* IJSVGCommandLineTo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandLineTo.m; sourceTree = "<group>"; };
59EB75AF23905F6F00F5AE63 /* IJSVGCommandMove.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandMove.h; sourceTree = "<group>"; };
59EB75B023905F6F00F5AE63 /* IJSVGTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGTransform.h; sourceTree = "<group>"; };
59EB75B123905F6F00F5AE63 /* IJSVGMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGMath.m; sourceTree = "<group>"; };
59EB75B223905F6F00F5AE63 /* IJSVGExporterPathInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGExporterPathInstruction.h; sourceTree = "<group>"; };
59EB75B323905F6F00F5AE63 /* IJSVGTransaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGTransaction.m; sourceTree = "<group>"; };
59EB75B423905F6F00F5AE63 /* IJSVGTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGTransform.m; sourceTree = "<group>"; };
59EB75B523905F7000F5AE63 /* IJSVGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImage.h; sourceTree = "<group>"; };
59EB75B623905F7000F5AE63 /* IJSVGMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGMath.h; sourceTree = "<group>"; };
59EB75B723905F7000F5AE63 /* IJSVGCommandClose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandClose.h; sourceTree = "<group>"; };
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStringAdditions.h; sourceTree = "<group>"; };
59EB75B923905F7000F5AE63 /* IJSVGGradientUnitLength.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientUnitLength.m; sourceTree = "<group>"; };
59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitLength.m; sourceTree = "<group>"; };
59EB75BB23905F7000F5AE63 /* IJSVGPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGPattern.h; sourceTree = "<group>"; };
59EB75BC23905F7000F5AE63 /* IJSVGLayerTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLayerTree.h; sourceTree = "<group>"; };
59EB75BD23905F7000F5AE63 /* IJSVGExporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGExporter.m; sourceTree = "<group>"; };
59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGPatternLayer.h; 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>"; };
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLinearGradient.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>"; };
59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandClose.m; sourceTree = "<group>"; };
59EB75C723905F7100F5AE63 /* IJSVGCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommand.h; sourceTree = "<group>"; };
59EB75C823905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandSmoothQuadraticCurve.m; sourceTree = "<group>"; };
59EB75C923905F7200F5AE63 /* IJSVGForeignObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGForeignObject.m; sourceTree = "<group>"; };
59EB75CA23905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandSmoothQuadraticCurve.h; sourceTree = "<group>"; };
59EB75CB23905F7200F5AE63 /* IJSVGCommandEllipticalArc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandEllipticalArc.m; sourceTree = "<group>"; };
59EB75CC23905F7200F5AE63 /* IJSVGGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGroup.m; sourceTree = "<group>"; };
59EB75CD23905F7200F5AE63 /* IJSVGView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGView.h; sourceTree = "<group>"; };
59EB75CE23905F7200F5AE63 /* IJSVGForeignObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGForeignObject.h; sourceTree = "<group>"; };
59EB75CF23905F7200F5AE63 /* IJSVGExporterPathInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGExporterPathInstruction.m; sourceTree = "<group>"; };
59EB75D023905F7200F5AE63 /* IJSVGImageLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImageLayer.h; sourceTree = "<group>"; };
59EB75D123905F7300F5AE63 /* IJSVGStyleSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheet.m; sourceTree = "<group>"; };
59EB75D223905F7300F5AE63 /* IJSVGGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradient.m; 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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
594CF46C238FF38E009B251B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
599EB4D3238FF570004CB6BC /* libobjc.tbd in Frameworks */,
594CF55F238FF462009B251B /* AppKit.framework in Frameworks */,
594CF561238FF46C009B251B /* Foundation.framework in Frameworks */,
594CF563238FF473009B251B /* QuartzCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
592ABBE223979F9B00F44380 /* Commands */ = {
isa = PBXGroup;
children = (
59EB75C723905F7100F5AE63 /* IJSVGCommand.h */,
59EB75A023905F6E00F5AE63 /* IJSVGCommand.m */,
59EB75B723905F7000F5AE63 /* IJSVGCommandClose.h */,
59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */,
59EB759C23905F6E00F5AE63 /* IJSVGCommandCurve.h */,
59EB759823905F6E00F5AE63 /* IJSVGCommandCurve.m */,
59EB759E23905F6E00F5AE63 /* IJSVGCommandEllipticalArc.h */,
59EB75CB23905F7200F5AE63 /* IJSVGCommandEllipticalArc.m */,
59EB759523905F6D00F5AE63 /* IJSVGCommandHorizontalLine.h */,
59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */,
59EB756823905F6B00F5AE63 /* IJSVGCommandLineTo.h */,
59EB75AE23905F6F00F5AE63 /* IJSVGCommandLineTo.m */,
59EB75AF23905F6F00F5AE63 /* IJSVGCommandMove.h */,
59EB759923905F6E00F5AE63 /* IJSVGCommandMove.m */,
59EB757E23905F6C00F5AE63 /* IJSVGCommandQuadraticCurve.h */,
59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */,
59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */,
59EB75A823905F6F00F5AE63 /* IJSVGCommandSmoothCurve.m */,
59EB75CA23905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h */,
59EB75C823905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m */,
59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */,
59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */,
);
path = Commands;
sourceTree = "<group>";
};
592ABBE323979FBB00F44380 /* Stylesheets */ = {
isa = PBXGroup;
children = (
59EB75AC23905F6F00F5AE63 /* IJSVGStyle.h */,
59EB757523905F6C00F5AE63 /* IJSVGStyle.m */,
59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */,
59EB75D123905F7300F5AE63 /* IJSVGStyleSheet.m */,
59EB759B23905F6E00F5AE63 /* IJSVGStyleSheetRule.h */,
59EB756723905F6B00F5AE63 /* IJSVGStyleSheetRule.m */,
59EB759A23905F6E00F5AE63 /* IJSVGStyleSheetSelector.h */,
59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */,
59EB757F23905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.h */,
59EB758123905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.m */,
);
path = Stylesheets;
sourceTree = "<group>";
};
592ABBE423979FD200F44380 /* Colors */ = {
isa = PBXGroup;
children = (
59EB758323905F6C00F5AE63 /* IJSVGColor.h */,
59EB758523905F6C00F5AE63 /* IJSVGColor.m */,
59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */,
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */,
59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */,
59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */,
);
path = Colors;
sourceTree = "<group>";
};
592ABBE523979FE100F44380 /* Layers */ = {
isa = PBXGroup;
children = (
59EB756623905F6B00F5AE63 /* IJSVGGradientLayer.h */,
59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */,
59EB75AD23905F6F00F5AE63 /* IJSVGGroupLayer.h */,
59EB758223905F6C00F5AE63 /* IJSVGGroupLayer.m */,
59EB75D023905F7200F5AE63 /* IJSVGImageLayer.h */,
59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */,
59EB756523905F6B00F5AE63 /* IJSVGLayer.h */,
59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */,
59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */,
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */,
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */,
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */,
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */,
59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */,
);
path = Layers;
sourceTree = "<group>";
};
592ABBE62397A00C00F44380 /* Parsing */ = {
isa = PBXGroup;
children = (
59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */,
59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */,
59EB75A723905F6F00F5AE63 /* IJSVGParser.h */,
59EB75A523905F6E00F5AE63 /* IJSVGParser.m */,
);
path = Parsing;
sourceTree = "<group>";
};
592ABBE72397A02900F44380 /* Nodes */ = {
isa = PBXGroup;
children = (
59EB75CE23905F7200F5AE63 /* IJSVGForeignObject.h */,
59EB75C923905F7200F5AE63 /* IJSVGForeignObject.m */,
59EB758623905F6C00F5AE63 /* IJSVGDef.h */,
59EB756923905F6B00F5AE63 /* IJSVGDef.m */,
59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */,
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */,
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */,
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */,
59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */,
59EB75D223905F7300F5AE63 /* IJSVGGradient.m */,
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */,
59EB75CC23905F7200F5AE63 /* IJSVGGroup.m */,
59EB75B523905F7000F5AE63 /* IJSVGImage.h */,
59EB757623905F6C00F5AE63 /* IJSVGImage.m */,
59EB759223905F6D00F5AE63 /* IJSVGNode.h */,
59EB759623905F6D00F5AE63 /* IJSVGNode.m */,
59EB759D23905F6E00F5AE63 /* IJSVGPath.h */,
59EB758A23905F6D00F5AE63 /* IJSVGPath.m */,
59EB75BB23905F7000F5AE63 /* IJSVGPattern.h */,
59EB75AA23905F6F00F5AE63 /* IJSVGPattern.m */,
59EB756B23905F6B00F5AE63 /* IJSVGText.h */,
59EB75C023905F7100F5AE63 /* IJSVGText.m */,
);
path = Nodes;
sourceTree = "<group>";
};
592ABBE82397A06800F44380 /* Utils */ = {
isa = PBXGroup;
children = (
59EB757323905F6C00F5AE63 /* IJSVGGradientUnitLength.h */,
59EB75B923905F7000F5AE63 /* IJSVGGradientUnitLength.m */,
59EB75B623905F7000F5AE63 /* IJSVGMath.h */,
59EB75B123905F6F00F5AE63 /* IJSVGMath.m */,
59EB757923905F6C00F5AE63 /* IJSVGTransaction.h */,
59EB75B323905F6F00F5AE63 /* IJSVGTransaction.m */,
59EB75B023905F6F00F5AE63 /* IJSVGTransform.h */,
59EB75B423905F6F00F5AE63 /* IJSVGTransform.m */,
59EB757723905F6C00F5AE63 /* IJSVGUnitLength.h */,
59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */,
59EB759423905F6D00F5AE63 /* IJSVGUtils.h */,
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;
sourceTree = "<group>";
};
592ABBE92397A08500F44380 /* Exporter */ = {
isa = PBXGroup;
children = (
59EB75D423905F7300F5AE63 /* IJSVGExporter.h */,
59EB75BD23905F7000F5AE63 /* IJSVGExporter.m */,
59EB75B223905F6F00F5AE63 /* IJSVGExporterPathInstruction.h */,
59EB75CF23905F7200F5AE63 /* IJSVGExporterPathInstruction.m */,
);
path = Exporter;
sourceTree = "<group>";
};
592ABBEA2397A10000F44380 /* Rendering */ = {
isa = PBXGroup;
children = (
59EB75BC23905F7000F5AE63 /* IJSVGLayerTree.h */,
59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */,
59EB75D323905F7300F5AE63 /* IJSVGRendering.h */,
59EB75D523905F7300F5AE63 /* IJSVGRendering.m */,
59EB75A123905F6E00F5AE63 /* IJSVGRenderingStyle.h */,
59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */,
);
path = Rendering;
sourceTree = "<group>";
};
592ABBEB2397A11800F44380 /* Additions */ = {
isa = PBXGroup;
children = (
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */,
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */,
594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */,
594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */,
);
path = Additions;
sourceTree = "<group>";
};
594CF465238FF38E009B251B = {
isa = PBXGroup;
children = (
594CF471238FF38E009B251B /* IJSVG */,
594CF470238FF38E009B251B /* Products */,
594CF55D238FF461009B251B /* Frameworks */,
);
sourceTree = "<group>";
};
594CF470238FF38E009B251B /* Products */ = {
isa = PBXGroup;
children = (
594CF46F238FF38E009B251B /* IJSVG.framework */,
);
name = Products;
sourceTree = "<group>";
};
594CF471238FF38E009B251B /* IJSVG */ = {
isa = PBXGroup;
children = (
59EB756423905F3100F5AE63 /* Source */,
594CF473238FF38E009B251B /* Info.plist */,
);
path = IJSVG;
sourceTree = "<group>";
};
594CF55D238FF461009B251B /* Frameworks */ = {
isa = PBXGroup;
children = (
599EB4D2238FF535004CB6BC /* libobjc.tbd */,
594CF562238FF473009B251B /* QuartzCore.framework */,
594CF560238FF46C009B251B /* Foundation.framework */,
594CF55E238FF462009B251B /* AppKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
59DD1FD123A22CFD00E28C56 /* Core */ = {
isa = PBXGroup;
children = (
59EB756A23905F6B00F5AE63 /* IJSVG.h */,
59EB75A223905F6E00F5AE63 /* IJSVG.m */,
59EB758423905F6C00F5AE63 /* IJSVGError.h */,
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */,
59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */,
59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */,
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */,
59EB75CD23905F7200F5AE63 /* IJSVGView.h */,
59EB75C123905F7100F5AE63 /* IJSVGView.m */,
);
path = Core;
sourceTree = "<group>";
};
59EB756423905F3100F5AE63 /* Source */ = {
isa = PBXGroup;
children = (
59DD1FD123A22CFD00E28C56 /* Core */,
592ABBEB2397A11800F44380 /* Additions */,
592ABBEA2397A10000F44380 /* Rendering */,
592ABBE92397A08500F44380 /* Exporter */,
592ABBE82397A06800F44380 /* Utils */,
592ABBE72397A02900F44380 /* Nodes */,
592ABBE62397A00C00F44380 /* Parsing */,
592ABBE523979FE100F44380 /* Layers */,
592ABBE423979FD200F44380 /* Colors */,
592ABBE323979FBB00F44380 /* Stylesheets */,
592ABBE223979F9B00F44380 /* Commands */,
);
path = Source;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
594CF46A238FF38E009B251B /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
59EB762623905F7300F5AE63 /* IJSVGImage.h in Headers */,
59EB760823905F7300F5AE63 /* IJSVGShapeLayer.h in Headers */,
59EB760F23905F7300F5AE63 /* IJSVGCommandEllipticalArc.h in Headers */,
59EB75F523905F7300F5AE63 /* IJSVGError.h in Headers */,
59EB763E23905F7300F5AE63 /* IJSVGView.h in Headers */,
59EB75DB23905F7300F5AE63 /* IJSVG.h in Headers */,
59EB764423905F7300F5AE63 /* IJSVGRendering.h in Headers */,
59EB75DC23905F7300F5AE63 /* IJSVGText.h in Headers */,
59EB761C23905F7300F5AE63 /* IJSVGGradient.h in Headers */,
59EB75F923905F7300F5AE63 /* IJSVGFontConverter.h in Headers */,
59EB75EF23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.h in Headers */,
59EB75FC23905F7300F5AE63 /* IJSVGGroup.h in Headers */,
59EB760323905F7300F5AE63 /* IJSVGNode.h in Headers */,
59EB762023905F7300F5AE63 /* IJSVGCommandMove.h in Headers */,
59EB762C23905F7300F5AE63 /* IJSVGPattern.h in Headers */,
59EB762923905F7300F5AE63 /* IJSVGStringAdditions.h in Headers */,
59EB761A23905F7300F5AE63 /* IJSVGColorList.h in Headers */,
59EB762123905F7300F5AE63 /* IJSVGTransform.h in Headers */,
59EB763F23905F7300F5AE63 /* IJSVGForeignObject.h in Headers */,
59EB75F423905F7300F5AE63 /* IJSVGColor.h in Headers */,
59EB760D23905F7300F5AE63 /* IJSVGCommandCurve.h in Headers */,
59EB763823905F7300F5AE63 /* IJSVGCommand.h in Headers */,
59EB760C23905F7300F5AE63 /* IJSVGStyleSheetRule.h in Headers */,
59EB75E323905F7300F5AE63 /* IJSVGRadialGradient.h in Headers */,
59EB760523905F7300F5AE63 /* IJSVGUtils.h in Headers */,
59EB763B23905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h in Headers */,
59EB75E823905F7300F5AE63 /* IJSVGUnitLength.h in Headers */,
59EB762723905F7300F5AE63 /* IJSVGMath.h in Headers */,
59EB761523905F7300F5AE63 /* IJSVGStrokeLayer.h in Headers */,
59EB75DE23905F7300F5AE63 /* IJSVGCommandVerticalLine.h in Headers */,
59EB764123905F7300F5AE63 /* IJSVGImageLayer.h in Headers */,
59EB75E023905F7300F5AE63 /* IJSVGStyleSheet.h in Headers */,
59EB761423905F7300F5AE63 /* IJSVGImageRep.h in Headers */,
59EB761223905F7300F5AE63 /* IJSVGRenderingStyle.h in Headers */,
59EB760E23905F7300F5AE63 /* IJSVGPath.h in Headers */,
59EB75EA23905F7300F5AE63 /* IJSVGTransaction.h in Headers */,
59EB75D723905F7300F5AE63 /* IJSVGGradientLayer.h in Headers */,
59EB75F723905F7300F5AE63 /* IJSVGDef.h in Headers */,
59EB760623905F7300F5AE63 /* IJSVGCommandHorizontalLine.h in Headers */,
59EB762323905F7300F5AE63 /* IJSVGExporterPathInstruction.h in Headers */,
59EB761023905F7300F5AE63 /* IJSVGLinearGradient.h in Headers */,
59EB75E123905F7300F5AE63 /* IJSVGCommandSmoothCurve.h in Headers */,
59EB75D923905F7300F5AE63 /* IJSVGCommandLineTo.h in Headers */,
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */,
59EB763023905F7300F5AE63 /* IJSVGPatternLayer.h in Headers */,
59EB75F023905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.h in Headers */,
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */,
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.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 */,
59F36508262F1ABB00BCE3FD /* IJSVGColorType.h in Headers */,
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */,
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */,
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.h in Headers */,
594A10DA248D7C90001A3181 /* NSImage+IJSVGAdditions.h in Headers */,
59EB762D23905F7300F5AE63 /* IJSVGLayerTree.h in Headers */,
59EB760B23905F7300F5AE63 /* IJSVGStyleSheetSelector.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
594CF46E238FF38E009B251B /* IJSVG */ = {
isa = PBXNativeTarget;
buildConfigurationList = 594CF477238FF38E009B251B /* Build configuration list for PBXNativeTarget "IJSVG" */;
buildPhases = (
594CF46A238FF38E009B251B /* Headers */,
594CF46B238FF38E009B251B /* Sources */,
594CF46C238FF38E009B251B /* Frameworks */,
594CF46D238FF38E009B251B /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = IJSVG;
productName = IJSVG;
productReference = 594CF46F238FF38E009B251B /* IJSVG.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
594CF466238FF38E009B251B /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1220;
ORGANIZATIONNAME = "Curtis Hard";
TargetAttributes = {
594CF46E238FF38E009B251B = {
CreatedOnToolsVersion = 11.0;
};
};
};
buildConfigurationList = 594CF469238FF38E009B251B /* Build configuration list for PBXProject "IJSVG" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 594CF465238FF38E009B251B;
productRefGroup = 594CF470238FF38E009B251B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
594CF46E238FF38E009B251B /* IJSVG */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
594CF46D238FF38E009B251B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
594CF46B238FF38E009B251B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */,
59A24EBD23F480EA0090C374 /* IJSVGUnitSize.m in Sources */,
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */,
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */,
59EB763923905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m in Sources */,
59EB75D823905F7300F5AE63 /* IJSVGStyleSheetRule.m in Sources */,
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */,
59F36509262F1ABB00BCE3FD /* IJSVGColorType.m in Sources */,
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */,
59EB763A23905F7300F5AE63 /* IJSVGForeignObject.m in Sources */,
59EB761123905F7300F5AE63 /* IJSVGCommand.m in Sources */,
59EB760923905F7300F5AE63 /* IJSVGCommandCurve.m in Sources */,
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */,
594A10DB248D7C90001A3181 /* NSImage+IJSVGAdditions.m in Sources */,
59EB761923905F7300F5AE63 /* IJSVGCommandSmoothCurve.m in Sources */,
59EB761323905F7300F5AE63 /* IJSVG.m in Sources */,
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */,
59EB75EC23905F7300F5AE63 /* IJSVGLayer.m in Sources */,
59EB75E523905F7300F5AE63 /* IJSVGStrokeLayer.m in Sources */,
59EB763223905F7300F5AE63 /* IJSVGView.m in Sources */,
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */,
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */,
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */,
5919E65C23F480330051873A /* IJSVGUnitPoint.m in Sources */,
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */,
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */,
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */,
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */,
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */,
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */,
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */,
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */,
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */,
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */,
591A3E4E25CC91F800AD45B7 /* IJSVGParsing.m in Sources */,
5919E65823F47FF60051873A /* IJSVGUnitRect.m in Sources */,
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */,
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */,
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */,
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */,
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */,
59EB762E23905F7300F5AE63 /* IJSVGExporter.m in Sources */,
59EB761623905F7300F5AE63 /* IJSVGParser.m in Sources */,
59EB75DD23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.m in Sources */,
59EB762423905F7300F5AE63 /* IJSVGTransaction.m in Sources */,
59EB75DA23905F7300F5AE63 /* IJSVGDef.m in Sources */,
59EB763723905F7300F5AE63 /* IJSVGCommandClose.m in Sources */,
59EB764323905F7300F5AE63 /* IJSVGGradient.m in Sources */,
59EB762A23905F7300F5AE63 /* IJSVGGradientUnitLength.m in Sources */,
59EB764223905F7300F5AE63 /* IJSVGStyleSheet.m in Sources */,
59EB764023905F7300F5AE63 /* IJSVGExporterPathInstruction.m in Sources */,
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */,
59EB75F223905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.m in Sources */,
59EB75EE23905F7300F5AE63 /* IJSVGImageRep.m in Sources */,
59EB762223905F7300F5AE63 /* IJSVGMath.m in Sources */,
59EB763D23905F7300F5AE63 /* IJSVGGroup.m in Sources */,
59EB761F23905F7300F5AE63 /* IJSVGCommandLineTo.m in Sources */,
59EB75F123905F7300F5AE63 /* IJSVGUtils.m in Sources */,
59EB760A23905F7300F5AE63 /* IJSVGCommandMove.m in Sources */,
59EB761B23905F7300F5AE63 /* IJSVGPattern.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
594CF475238FF38E009B251B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREFIX_HEADER = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
594CF476238FF38E009B251B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
594CF478238FF38E009B251B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_COMMA = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = 9KTR4W9XX6;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = IJSVG/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.iconjar.ijsvg;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
};
name = Debug;
};
594CF479238FF38E009B251B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_COMMA = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = 9KTR4W9XX6;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = IJSVG/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.iconjar.ijsvg;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
594CF469238FF38E009B251B /* Build configuration list for PBXProject "IJSVG" */ = {
isa = XCConfigurationList;
buildConfigurations = (
594CF475238FF38E009B251B /* Debug */,
594CF476238FF38E009B251B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
594CF477238FF38E009B251B /* Build configuration list for PBXNativeTarget "IJSVG" */ = {
isa = XCConfigurationList;
buildConfigurations = (
594CF478238FF38E009B251B /* Debug */,
594CF479238FF38E009B251B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 594CF466238FF38E009B251B /* Project object */;
}
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:IJSVG.xcodeproj">
</FileRef>
</Workspace>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "594CF46E238FF38E009B251B"
BuildableName = "IJSVG.framework"
BlueprintName = "IJSVG"
ReferencedContainer = "container:IJSVG.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "594CF46E238FF38E009B251B"
BuildableName = "IJSVG.framework"
BlueprintName = "IJSVG"
ReferencedContainer = "container:IJSVG.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>IJSVG.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>594CF46E238FF38E009B251B</key>
<dict>
<key>primary</key>
<true />
</dict>
</dict>
</dict>
</plist>
-24
View File
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 Curtis Hard. All rights reserved.</string>
</dict>
</plist>
@@ -1,19 +0,0 @@
//
// IJSVGStringAdditions.h
// IconJar
//
// Created by Curtis Hard on 07/06/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (IJSVGAdditions)
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(const char*)aChar;
- (BOOL)ijsvg_isNumeric;
- (BOOL)ijsvg_containsAlpha;
- (NSArray*)ijsvg_componentsSplitByWhiteSpace;
- (BOOL)ijsvg_isHexString;
@end
@@ -1,71 +0,0 @@
//
// IJSVGStringAdditions.m
// IconJar
//
// Created by Curtis Hard on 07/06/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGStringAdditions.h"
#import "IJSVGUtils.h"
@implementation NSString (IJSVGAdditions)
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(const char*)aChar
{
char* chars = (char*)self.UTF8String;
if(chars == NULL || strlen(chars) == 0) {
return @[];
}
NSMutableArray<NSString*>* strings = nil;
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
{
const char* buffer = self.UTF8String;
char currentChar;
while((currentChar = *buffer++) ) {
if (isalpha(currentChar)) {
return YES;
}
}
return NO;
}
- (BOOL)ijsvg_isNumeric
{
const char* buffer = self.UTF8String;
char currentChar;
while((currentChar = *buffer++) ) {
if (!isnumber(currentChar)) {
return NO;
}
}
return YES;
}
- (NSArray*)ijsvg_componentsSplitByWhiteSpace
{
return [self ijsvg_componentsSeparatedByChars:"\t\n\r "];
}
- (BOOL)ijsvg_isHexString
{
const char* chars = self.UTF8String;
return IJSVGCharBufferIsHEX((char*)chars);
}
@end
@@ -1,18 +0,0 @@
//
// 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
@@ -1,53 +0,0 @@
//
// 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
@@ -1,822 +0,0 @@
//
// IJSVGColor.m
// IconJar
//
// Created by Curtis Hard on 31/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGColor.h"
#import "IJSVGUtils.h"
#import "IJSVGStringAdditions.h"
#import "IJSVGParsing.h"
NSString* const IJSVGColorCurrentColorName = @"currentColor";
@implementation IJSVGColor
static NSDictionary* _colorTree = nil;
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness)
{
hue *= (1.f / 360.f);
hue = (hue - floorf(hue));
saturation *= 0.01;
lightness *= 0.01;
lightness *= 2.f;
CGFloat s = saturation * ((lightness < 1.f) ? lightness : (2.f - lightness));
CGFloat brightness = (lightness + s) * .5f;
if (s != 0.f) {
s = (2.f * s) / (lightness + s);
}
CGFloat* floats = (CGFloat*)malloc(3 * sizeof(CGFloat));
floats[0] = hue;
floats[1] = s;
floats[2] = brightness;
return floats;
};
+ (void)load
{
[self.class _generateTree];
}
+ (NSColorSpace*)defaultColorSpace
{
return NSColorSpace.deviceRGBColorSpace;
}
+ (NSColor*)computeColorSpace:(NSColor*)color
{
NSColorSpace* space = [self defaultColorSpace];
if (color.colorSpace != space) {
color = [color colorUsingColorSpace:space];
}
return color;
}
+ (void)_generateTree
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_colorTree = [@{
@"aliceblue" : @(0xf0f8ff),
@"antiquewhite" : @(0xfaebd7),
@"aqua" : @(0x00ffff),
@"aquamarine" : @(0x7fffd4),
@"azure" : @(0xf0ffff),
@"beige" : @(0xf5f5dc),
@"bisque" : @(0xffe4c4),
@"black" : @(0x000000),
@"blanchedalmond" : @(0xffebcd),
@"blue" : @(0x0000ff),
@"blueviolet" : @(0x8a2be2),
@"brown" : @(0xa52a2a),
@"burlywood" : @(0xdeb887),
@"cadetblue" : @(0x5f9ea0),
@"chartreuse" : @(0x7fff00),
@"chocolate" : @(0xd2691e),
@"coral" : @(0xff7f50),
@"cornflowerblue" : @(0x6495ed),
@"cornsilk" : @(0xfff8dc),
@"crimson" : @(0xdc143c),
@"currentcolor" : @(0x000000),
@"cyan" : @(0x00ffff),
@"darkblue" : @(0x00008b),
@"darkcyan" : @(0x008b8b),
@"darkgoldenrod" : @(0xb8860b),
@"darkgray" : @(0xa9a9a9),
@"darkgreen" : @(0x006400),
@"darkgrey" : @(0xa9a9a9),
@"darkkhaki" : @(0xbdb76b),
@"darkmagenta" : @(0x8b008b),
@"darkolivegreen" : @(0x556b2f),
@"darkorange" : @(0xff8c00),
@"darkorchid" : @(0x9932cc),
@"darkred" : @(0x8b0000),
@"darksalmon" : @(0xe9967a),
@"darkseagreen" : @(0x8fbc8f),
@"darkslateblue" : @(0x483d8b),
@"darkslategray" : @(0x2f4f4f),
@"darkturquoise" : @(0x00ced1),
@"darkviolet" : @(0x9400d3),
@"deeppink" : @(0xff1493),
@"deepskyblue" : @(0x00bfff),
@"dimgray" : @(0x696969),
@"dimgrey" : @(0x696969),
@"dodgerblue" : @(0x1e90ff),
@"firebrick" : @(0xb22222),
@"floralwhite" : @(0xfffaf0),
@"forestgreen" : @(0x228b22),
@"fuchsia" : @(0xff00ff),
@"gainsboro" : @(0xdcdcdc),
@"ghostwhite" : @(0xf8f8ff),
@"gold" : @(0xffd700),
@"goldenrod" : @(0xdaa520),
@"gray" : @(0x808080),
@"green" : @(0x008000),
@"greenyellow" : @(0xadff2f),
@"grey" : @(0x808080),
@"honeydew" : @(0xf0fff0),
@"hotpink" : @(0xff69b4),
@"indianred" : @(0xcd5c5c),
@"indigo" : @(0x4b0082),
@"ivory" : @(0xfffff0),
@"khaki" : @(0xf0e68c),
@"lavender" : @(0xe6e6fa),
@"lavenderblush" : @(0xfff0f5),
@"lawngreen" : @(0x7cfc00),
@"lemonchiffon" : @(0xfffacd),
@"lightblue" : @(0xadd8e6),
@"lightcoral" : @(0xf08080),
@"lightcyan" : @(0xe0ffff),
@"lightgoldenrodyellow" : @(0xfafad2),
@"lightgray" : @(0xd3d3d3),
@"lightgreen" : @(0x90ee90),
@"lightgrey" : @(0xd3d3d3),
@"lightpink" : @(0xffb6c1),
@"lightsalmon" : @(0xffa07a),
@"lightseagreen" : @(0x20b2aa),
@"lightskyblue" : @(0x87cefa),
@"lightslategray" : @(0x778899),
@"lightsteelblue" : @(0xb0c4de),
@"lightyellow" : @(0xffffe0),
@"lime" : @(0x00ff00),
@"limegreen" : @(0x32cd32),
@"linen" : @(0xfaf0e6),
@"magenta" : @(0xff00ff),
@"maroon" : @(0x800000),
@"mediumaquamarine" : @(0x66cdaa),
@"mediumblue" : @(0x0000cd),
@"mediumorchid" : @(0xba55d3),
@"mediumpurple" : @(0x9370db),
@"mediumseagreen" : @(0x3cb371),
@"mediumslateblue" : @(0x7b68ee),
@"mediumspringgreen" : @(0x00fa9a),
@"mediumturquoise" : @(0x48d1cc),
@"mediumvioletred" : @(0xc71585),
@"midnightblue" : @(0x191970),
@"mintcream" : @(0xf5fffa),
@"mistyrose" : @(0xffe4e1),
@"moccasin" : @(0xffe4b5),
@"navajowhite" : @(0xffdead),
@"navy" : @(0x000080),
@"oldlace" : @(0xfdf5e6),
@"olive" : @(0x808000),
@"olivedrab" : @(0x6b8e23),
@"orange" : @(0xffa500),
@"orangered" : @(0xff4500),
@"orchid" : @(0xda70d6),
@"palegoldenrod" : @(0xeee8aa),
@"palegreen" : @(0x98fb98),
@"paleturquoise" : @(0xafeeee),
@"palevioletred" : @(0xdb7093),
@"papayawhip" : @(0xffefd5),
@"peachpuff" : @(0xffdab9),
@"peru" : @(0xcd853f),
@"pink" : @(0xffc0cb),
@"plum" : @(0xdda0dd),
@"powderblue" : @(0xb0e0e6),
@"purple" : @(0x800080),
@"red" : @(0xff0000),
@"rosybrown" : @(0xbc8f8f),
@"royalblue" : @(0x4169e1),
@"saddlebrown" : @(0x8b4513),
@"salmon" : @(0xfa8072),
@"sandybrown" : @(0xf4a460),
@"seagreen" : @(0x2e8b57),
@"seashell" : @(0xfff5ee),
@"sienna" : @(0xa0522d),
@"silver" : @(0xc0c0c0),
@"skyblue" : @(0x87ceeb),
@"slateblue" : @(0x6a5acd),
@"slategrey" : @(0x708090),
@"snow" : @(0xfffafa),
@"springgreen" : @(0x00ff7f),
@"steelblue" : @(0x4682b4),
@"tan" : @(0xd2b48c),
@"teal" : @(0x008080),
@"thistle" : @(0xd8bfd8),
@"tomato" : @(0xff6347),
@"turquoise" : @(0x40e0d0),
@"violet" : @(0xee82ee),
@"wheat" : @(0xf5deb3),
@"white" : @(0xffffff),
@"whitesmoke" : @(0xf5f5f5),
@"yellow" : @(0xffff00),
@"yellowgreen" : @(0x9acd32)
} retain];
});
}
+ (NSColor*)computeColor:(id)colour
{
if ([colour isKindOfClass:[NSColor class]])
return colour;
return nil;
}
+ (NSColor*)colorFromRString:(NSString*)rString
gString:(NSString*)gString
bString:(NSString*)bString
aString:(NSString*)aString
{
return [self colorFromRUnit:[IJSVGUnitLength unitWithString:rString]
gUnit:[IJSVGUnitLength unitWithString:gString]
bUnit:[IJSVGUnitLength unitWithString:bString]
aUnit:[IJSVGUnitLength unitWithString:aString]];
}
+ (NSColor*)colorFromRUnit:(IJSVGUnitLength*)rUnit
gUnit:(IJSVGUnitLength*)gUnit
bUnit:(IJSVGUnitLength*)bUnit
aUnit:(IJSVGUnitLength*)aUnit
{
CGFloat r = rUnit.type == IJSVGUnitLengthTypePercentage ? [rUnit computeValue:255.f] : [rUnit computeValue:1.f];
CGFloat g = gUnit.type == IJSVGUnitLengthTypePercentage ? [gUnit computeValue:255.f] : [gUnit computeValue:1.f];
CGFloat b = bUnit.type == IJSVGUnitLengthTypePercentage ? [bUnit computeValue:255.f] : [bUnit computeValue:1.f];
CGFloat a = [aUnit computeValue:100.f];
return [self computeColorSpace:[NSColor colorWithDeviceRed:(r / 255.f)
green:(g / 255.f)
blue:(b / 255.f)
alpha:a]];
}
+ (NSColor*)colorFromString:(NSString*)string
{
// swap over to C for performance
if(string == nil) {
return nil;
}
const char* oString = string.UTF8String;
if(strlen(oString) == 0) {
return nil;
}
char* str = IJSVGTimmedCharBufferCreate(oString);
if (IJSVGCharBufferIsHEX(str) == YES) {
(void)free(str), str = NULL;
return [self.class colorFromHEXString:string];
}
// is it RGB?
if (IJSVGCharBufferHasPrefix(str, "rgb") == YES) {
NSUInteger count = 0;
IJSVGParsingStringMethod** methods = NULL;
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%";
if (parts.count == 4) {
alpha = parts[3];
}
IJSVGParsingStringMethodsRelease(methods, count);
methods = NULL;
return [self colorFromRString:parts[0]
gString:parts[1]
bString:parts[2]
aString:alpha];
}
// is it HSL?
if (IJSVGCharBufferHasPrefix(str, "hsl")) {
NSInteger count = 0;
CGFloat* params = [IJSVGUtils scanFloatsFromCString:str
size:&count];
CGFloat alpha = 1;
if (count == 4) {
alpha = params[3];
}
// convert HSL to HSB
CGFloat* hsb = IJSVGColorCSSHSLToHSB(params[0], params[1], params[2]);
NSColor* color = [NSColor colorWithDeviceHue:hsb[0]
saturation:hsb[1]
brightness:hsb[2]
alpha:alpha];
color = [self computeColorSpace:color];
// memory clean!
(void)free(str), str = NULL;
(void)free(hsb), hsb = NULL;
(void)free(params), params = NULL;
return color;
}
// is simply a clear color, dont fill
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
{
NSNumber* hex = nil;
name = [name.lowercaseString stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
if ((hex = _colorTree[name]) == nil) {
return nil;
}
return [self.class colorFromHEXInteger:hex.integerValue];
}
+ (NSString*)colorStringFromColor:(NSColor*)color
{
IJSVGColorStringOptions options = IJSVGColorStringOptionDefault;
return [self colorStringFromColor:color
options:options];
}
+ (NSString*)colorStringFromColor:(NSColor*)color
options:(IJSVGColorStringOptions)options
{
// convert to RGB
color = [self computeColorSpace:color];
int red = color.redComponent * 0xFF;
int green = color.greenComponent * 0xFF;
int blue = color.blueComponent * 0xFF;
int alpha = (int)(color.alphaComponent * 100);
BOOL forceHex = (options & IJSVGColorStringOptionForceHEX) != 0;
BOOL allowShortHand = (options & IJSVGColorStringOptionAllowShortHand) != 0;
BOOL allowRRGGBBAA = (options & IJSVGColorStringOptionAllowRRGGBBAA) != 0;
// jsut return none
if (alpha == 0 && forceHex == NO) {
return @"none";
}
// always return hex unless criteria is met
if (forceHex == YES || allowRRGGBBAA == YES || alpha == 100 || (red == 0 && green == 0 && blue == 0 && alpha == 0) || (red == 255 && green == 255 && blue == 255 && alpha == 100)) {
// we need to make sure the last 2 chars
// are the same or we cant enable shorthand
if (allowRRGGBBAA == YES) {
NSString* alphaHexString = [NSString stringWithFormat:@"%02X",
(int)(color.alphaComponent * 0xFF)];
if ([alphaHexString characterAtIndex:0] !=
[alphaHexString characterAtIndex:1]) {
allowShortHand = NO;
}
}
if (allowShortHand == YES) {
NSString* r = [NSString stringWithFormat:@"%02X", red];
NSString* g = [NSString stringWithFormat:@"%02X", green];
NSString* b = [NSString stringWithFormat:@"%02X", blue];
if ([r characterAtIndex:0] == [r characterAtIndex:1] &&
[g characterAtIndex:0] == [g characterAtIndex:1] &&
[b characterAtIndex:0] == [b characterAtIndex:1]) {
// allow shorthand alpha
if (allowRRGGBBAA == YES && alpha != 100) {
NSString* a = [NSString stringWithFormat:@"%02X",
(int)(color.alphaComponent * 0xFF)];
return [NSString stringWithFormat:@"#%c%c%c%c",
[r characterAtIndex:0], [g characterAtIndex:0],
[b characterAtIndex:0], [a characterAtIndex:0]];
}
return [NSString stringWithFormat:@"#%c%c%c", [r characterAtIndex:0],
[g characterAtIndex:0], [b characterAtIndex:0]];
}
}
if (allowRRGGBBAA == YES && alpha != 100) {
return [NSString stringWithFormat:@"#%02X%02X%02X%02X", red, green,
blue, (int)(color.alphaComponent * 0xFF)];
}
return [NSString stringWithFormat:@"#%02X%02X%02X", red, green, blue];
}
// note the %g, CSS alpha is 0 to 1, not 0 - 100, my bad!
return [NSString stringWithFormat:@"rgba(%d,%d,%d,%@)", red, green, blue,
IJSVGShortFloatString((float)alpha / 100.f)];
}
+ (NSString*)colorNameFromPredefinedColor:(IJSVGPredefinedColor)color
{
switch (color) {
case IJSVGColorAliceblue:
return @"aliceblue";
case IJSVGColorAntiquewhite:
return @"antiquewhite";
case IJSVGColorAqua:
return @"aqua";
case IJSVGColorAquamarine:
return @"aquamarine";
case IJSVGColorAzure:
return @"azure";
case IJSVGColorBeige:
return @"beige";
case IJSVGColorBisque:
return @"bisque";
case IJSVGColorBlack:
return @"black";
case IJSVGColorBlanchedalmond:
return @"blanchedalmond";
case IJSVGColorBlue:
return @"blue";
case IJSVGColorBlueviolet:
return @"blueviolet";
case IJSVGColorBrown:
return @"brown";
case IJSVGColorBurlywood:
return @"burlywood";
case IJSVGColorCadetblue:
return @"cadetblue";
case IJSVGColorChartreuse:
return @"chartreuse";
case IJSVGColorChocolate:
return @"chocolate";
case IJSVGColorCoral:
return @"coral";
case IJSVGColorCornflowerblue:
return @"cornflowerblue";
case IJSVGColorCornsilk:
return @"cornsilk";
case IJSVGColorCrimson:
return @"crimson";
case IJSVGColorCyan:
return @"cyan";
case IJSVGColorDarkblue:
return @"darkblue";
case IJSVGColorDarkcyan:
return @"darkcyan";
case IJSVGColorDarkgoldenrod:
return @"darkgoldenrod";
case IJSVGColorDarkgray:
return @"darkgray";
case IJSVGColorDarkgreen:
return @"darkgreen";
case IJSVGColorDarkgrey:
return @"darkgrey";
case IJSVGColorDarkkhaki:
return @"darkkhaki";
case IJSVGColorDarkmagenta:
return @"darkmagenta";
case IJSVGColorDarkolivegreen:
return @"darkolivegreen";
case IJSVGColorDarkorange:
return @"darkorange";
case IJSVGColorDarkorchid:
return @"darkorchid";
case IJSVGColorDarkred:
return @"darkred";
case IJSVGColorDarksalmon:
return @"darksalmon";
case IJSVGColorDarkseagreen:
return @"darkseagreen";
case IJSVGColorDarkslateblue:
return @"darkslateblue";
case IJSVGColorDarkslategray:
return @"darkslategray";
case IJSVGColorDarkslategrey:
return @"darkslategrey";
case IJSVGColorDarkturquoise:
return @"darkturquoise";
case IJSVGColorDarkviolet:
return @"darkviolet";
case IJSVGColorDeeppink:
return @"deeppink";
case IJSVGColorDeepskyblue:
return @"deepskyblue";
case IJSVGColorDimgray:
return @"dimgray";
case IJSVGColorDimgrey:
return @"dimgrey";
case IJSVGColorDodgerblue:
return @"dodgerblue";
case IJSVGColorFirebrick:
return @"firebrick";
case IJSVGColorFloralwhite:
return @"floralwhite";
case IJSVGColorForestgreen:
return @"forestgreen";
case IJSVGColorFuchsia:
return @"fuchsia";
case IJSVGColorGainsboro:
return @"gainsboro";
case IJSVGColorGhostwhite:
return @"ghostwhite";
case IJSVGColorGold:
return @"gold";
case IJSVGColorGoldenrod:
return @"goldenrod";
case IJSVGColorGray:
return @"gray";
case IJSVGColorGreen:
return @"green";
case IJSVGColorGreenyellow:
return @"greenyellow";
case IJSVGColorGrey:
return @"grey";
case IJSVGColorHoneydew:
return @"honeydew";
case IJSVGColorHotpink:
return @"hotpink";
case IJSVGColorIndianred:
return @"indianred";
case IJSVGColorIndigo:
return @"indigo";
case IJSVGColorIvory:
return @"ivory";
case IJSVGColorKhaki:
return @"khaki";
case IJSVGColorLavender:
return @"lavender";
case IJSVGColorLavenderblush:
return @"lavenderblush";
case IJSVGColorLawngreen:
return @"lawngreen";
case IJSVGColorLemonchiffon:
return @"lemonchiffon";
case IJSVGColorLightblue:
return @"lightblue";
case IJSVGColorLightcoral:
return @"lightcoral";
case IJSVGColorLightcyan:
return @"lightcyan";
case IJSVGColorLightgoldenrodyellow:
return @"lightgoldenrodyellow";
case IJSVGColorLightgray:
return @"lightgray";
case IJSVGColorLightgreen:
return @"lightgreen";
case IJSVGColorLightgrey:
return @"lightgrey";
case IJSVGColorLightpink:
return @"lightpink";
case IJSVGColorLightsalmon:
return @"lightsalmon";
case IJSVGColorLightseagreen:
return @"lightseagreen";
case IJSVGColorLightskyblue:
return @"lightskyblue";
case IJSVGColorLightslategray:
return @"lightslategray";
case IJSVGColorLightslategrey:
return @"lightslategrey";
case IJSVGColorLightsteelblue:
return @"lightsteelblue";
case IJSVGColorLightyellow:
return @"lightyellow";
case IJSVGColorLime:
return @"lime";
case IJSVGColorLimegreen:
return @"limegreen";
case IJSVGColorLinen:
return @"linen";
case IJSVGColorMagenta:
return @"magenta";
case IJSVGColorMaroon:
return @"maroon";
case IJSVGColorMediumaquamarine:
return @"mediumaquamarine";
case IJSVGColorMediumblue:
return @"mediumblue";
case IJSVGColorMediumorchid:
return @"mediumorchid";
case IJSVGColorMediumpurple:
return @"mediumpurple";
case IJSVGColorMediumseagreen:
return @"mediumseagreen";
case IJSVGColorMediumslateblue:
return @"mediumslateblue";
case IJSVGColorMediumspringgreen:
return @"mediumspringgreen";
case IJSVGColorMediumturquoise:
return @"mediumturquoise";
case IJSVGColorMediumvioletred:
return @"mediumvioletred";
case IJSVGColorMidnightblue:
return @"midnightblue";
case IJSVGColorMintcream:
return @"mintcream";
case IJSVGColorMistyrose:
return @"mistyrose";
case IJSVGColorMoccasin:
return @"moccasin";
case IJSVGColorNavajowhite:
return @"navajowhite";
case IJSVGColorNavy:
return @"navy";
case IJSVGColorOldlace:
return @"oldlace";
case IJSVGColorOlive:
return @"olive";
case IJSVGColorOlivedrab:
return @"olivedrab";
case IJSVGColorOrange:
return @"orange";
case IJSVGColorOrangered:
return @"orangered";
case IJSVGColorOrchid:
return @"orchid";
case IJSVGColorPalegoldenrod:
return @"palegoldenrod";
case IJSVGColorPalegreen:
return @"palegreen";
case IJSVGColorPaleturquoise:
return @"paleturquoise";
case IJSVGColorPalevioletred:
return @"palevioletred";
case IJSVGColorPapayawhip:
return @"papayawhip";
case IJSVGColorPeachpuff:
return @"peachpuff";
case IJSVGColorPeru:
return @"peru";
case IJSVGColorPink:
return @"pink";
case IJSVGColorPlum:
return @"plum";
case IJSVGColorPowderblue:
return @"powderblue";
case IJSVGColorPurple:
return @"purple";
case IJSVGColorRed:
return @"red";
case IJSVGColorRosybrown:
return @"rosybrown";
case IJSVGColorRoyalblue:
return @"royalblue";
case IJSVGColorSaddlebrown:
return @"saddlebrown";
case IJSVGColorSalmon:
return @"salmon";
case IJSVGColorSandybrown:
return @"sandybrown";
case IJSVGColorSeagreen:
return @"seagreen";
case IJSVGColorSeashell:
return @"seashell";
case IJSVGColorSienna:
return @"sienna";
case IJSVGColorSilver:
return @"silver";
case IJSVGColorSkyblue:
return @"skyblue";
case IJSVGColorSlateblue:
return @"slateblue";
case IJSVGColorSlategray:
return @"slategray";
case IJSVGColorSlategrey:
return @"slategrey";
case IJSVGColorSnow:
return @"snow";
case IJSVGColorSpringgreen:
return @"springgreen";
case IJSVGColorSteelblue:
return @"steelblue";
case IJSVGColorTan:
return @"tan";
case IJSVGColorTeal:
return @"teal";
case IJSVGColorThistle:
return @"thistle";
case IJSVGColorTomato:
return @"tomato";
case IJSVGColorTurquoise:
return @"turquoise";
case IJSVGColorViolet:
return @"violet";
case IJSVGColorWheat:
return @"wheat";
case IJSVGColorWhite:
return @"white";
case IJSVGColorWhitesmoke:
return @"whitesmoke";
case IJSVGColorYellow:
return @"yellow";
case IJSVGColorYellowgreen:
return @"yellowgreen";
}
return nil;
}
+ (NSColor*)changeAlphaOnColor:(NSColor*)color
to:(CGFloat)alphaValue
{
color = [self computeColorSpace:color];
return [self computeColorSpace:[NSColor colorWithDeviceRed:color.redComponent
green:color.greenComponent
blue:color.blueComponent
alpha:alphaValue]];
}
+ (BOOL)isColor:(NSString*)string
{
return [string hasPrefix:@"#"] || [string hasPrefix:@"rgb"];
}
+ (BOOL)isHex:(NSString*)string
{
return string.ijsvg_isHexString;
}
+ (unsigned long)lengthOfHEXInteger:(NSUInteger)hex
{
char* buffer;
asprintf(&buffer, "%lX", (long)hex);
unsigned long length = strlen(buffer);
free(buffer);
return length;
}
+ (BOOL)HEXContainsAlphaComponent:(NSUInteger)hex
{
return [self lengthOfHEXInteger:hex] == 8;
}
+ (NSColor*)colorFromHEXInteger:(NSInteger)hex
{
CGFloat alpha = 1.f;
if ([self HEXContainsAlphaComponent:hex] == YES) {
alpha = (hex & 0xFF) / 255.f;
hex = hex >> 8;
}
return [self computeColorSpace:[NSColor colorWithDeviceRed:((hex >> 16) & 0xFF) / 255.f
green:((hex >> 8) & 0xFF) / 255.f
blue:(hex & 0xFF) / 255.f
alpha:alpha]];
}
+ (unsigned long)HEXFromArbitraryHexString:(NSString*)aString
{
const char* hexString = [aString cStringUsingEncoding:NSUTF8StringEncoding];
return strtoul(hexString, NULL, 16);
}
+ (NSColor*)colorFromHEXString:(NSString*)string
{
return [self colorFromHEXString:string
containsAlphaComponent:nil];
}
+ (NSColor*)colorFromHEXString:(NSString*)string
containsAlphaComponent:(BOOL*)containsAlphaComponent
{
// absolutely no string
if(string == nil) {
return nil;
}
char* str = (char*)string.UTF8String;
size_t length = strlen(str);
if (length == 0 || IJSVGCharBufferIsHEX(str) == NO) {
return nil;
}
// remove the hash from the front of the string
if(str[0] == '#') {
length--;
str++;
}
unsigned long hex;
// we need to work out if its shorthand
// if it is, the length needs to be length*2
if (length == 3 || length == 4) {
char* chars = NULL;
chars = (char*)calloc(sizeof(char),length*2+1);
for(int i = 0; i < length; i++) {
chars[i*2] = chars[i*2+1] = str[i];
}
hex = strtoul(chars, NULL, 16);
(void)free(chars), chars = NULL;
} else {
hex = strtoul(str, NULL, 16);
}
// now convert rest to hex
if (containsAlphaComponent != nil) {
*containsAlphaComponent = [self HEXContainsAlphaComponent:hex];
}
return [self colorFromHEXInteger:hex];
}
@end
@@ -1,35 +0,0 @@
//
// IJSVGColorList.h
// IconJar
//
// Created by Curtis Hard on 07/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColor.h>
#import <IJSVG/IJSVGColorType.h>
#import <Foundation/Foundation.h>
@interface IJSVGColorList : NSObject <NSCopying> {
@private
NSMutableDictionary<NSColor*, NSColor*>* _replacementColorTree;
NSMutableSet<IJSVGColorType*>* _colors;
}
@property (nonatomic, assign, readonly) NSUInteger count;
- (NSColor*)proposedColorForColor:(NSColor*)color;
- (void)removeAllReplacementColors;
- (void)removeReplacementColor:(NSColor*)color;
- (void)setReplacementColor:(NSColor*)newColor
forColor:(NSColor*)color;
- (void)setReplacementColors:(NSDictionary<NSColor*, NSColor*>*)colors
clearExistingColors:(BOOL)clearExistingColors;
- (void)addColorsFromList:(IJSVGColorList*)sheet;
- (NSSet<IJSVGColorType*>*)colors;
- (void)addColor:(IJSVGColorType*)color;
- (NSDictionary<NSColor*, NSColor*>*)replacementColors;
@end
@@ -1,136 +0,0 @@
//
// IJSVGColorList.m
// IconJar
//
// Created by Curtis Hard on 07/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGColorList.h"
@implementation IJSVGColorList
- (void)dealloc
{
(void)([_replacementColorTree release]), _replacementColorTree = nil;
(void)([_colors release]), _colors = nil;
[super dealloc];
}
- (instancetype)init
{
if ((self = [super init]) != nil) {
_replacementColorTree = [[NSMutableDictionary alloc] init];
_colors = [[NSMutableSet alloc] init];
}
return self;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGColorList* sheet = [[self.class alloc] init];
[sheet setReplacementColors:[_replacementColorTree.copy autorelease]
clearExistingColors:YES];
return sheet;
}
- (NSColor*)proposedColorForColor:(NSColor*)color
{
// nothing found, just return color
if (_replacementColorTree == nil || _replacementColorTree.count == 0) {
return color;
}
// check the mappings
NSColor* found = nil;
color = [IJSVGColor computeColorSpace:color];
if ((found = _replacementColorTree[color]) != nil) {
return found;
}
return color;
}
- (void)_invalidateColorTree
{
(void)([_replacementColorTree release]), _replacementColorTree = nil;
_replacementColorTree = [[NSMutableDictionary alloc] init];
}
- (void)removeAllReplacementColors
{
[self _invalidateColorTree];
}
- (void)removeReplacementColor:(NSColor*)color
{
if (_replacementColorTree == nil) {
return;
}
[_replacementColorTree removeObjectForKey:[IJSVGColor computeColorSpace:color]];
}
- (void)setReplacementColor:(NSColor*)newColor
forColor:(NSColor*)color
{
color = [IJSVGColor computeColorSpace:color];
newColor = [IJSVGColor computeColorSpace:newColor];
_replacementColorTree[color] = newColor;
}
- (void)setReplacementColors:(NSDictionary<NSColor*, NSColor*>*)colors
clearExistingColors:(BOOL)clearExistingColors
{
if (clearExistingColors == YES) {
[self _invalidateColorTree];
}
for (NSColor* oldColor in colors) {
[self setReplacementColor:colors[oldColor]
forColor:oldColor];
}
}
- (NSSet<IJSVGColorType*>*)colors
{
return [NSSet setWithSet:_colors];
}
- (void)addColorsFromList:(IJSVGColorList*)sheet
{
for(IJSVGColorType* color in sheet.colors) {
[self addColor:color];
}
}
- (void)addColor:(IJSVGColorType*)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];
}
- (NSDictionary<NSColor*,NSColor*>*)replacementColors
{
return _replacementColorTree;
}
- (void)removeColor:(IJSVGColorType*)color
{
[_colors removeObject:color];
}
- (NSUInteger)count
{
return _colors.count;
}
@end
@@ -1,30 +0,0 @@
//
// 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
@@ -1,41 +0,0 @@
//
// 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
@@ -1,61 +0,0 @@
//
// IJSVGCommand.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGCommandParser.h>
#import <IJSVG/IJSVGPath.h>
#import <Foundation/Foundation.h>
static const NSInteger IJSVGCustomVariableParameterCount = NSNotFound;
typedef NS_ENUM(NSInteger, IJSVGCommandType) {
kIJSVGCommandTypeAbsolute,
kIJSVGCommandTypeRelative
};
@interface IJSVGCommand : NSObject {
@private
NSInteger _currentIndex;
}
@property (nonatomic, copy) NSString* commandString;
@property (nonatomic, assign) char command;
@property (nonatomic, assign) CGFloat* parameters;
@property (nonatomic, assign) NSInteger parameterCount;
@property (nonatomic, assign) IJSVGCommandType type;
@property (nonatomic, retain) NSArray<IJSVGCommand*>* subCommands;
@property (nonatomic, assign) IJSVGCommand* previousCommand;
@property (nonatomic, assign) BOOL isSubCommand;
+ (Class)commandClassForCommandChar:(char)aChar;
+ (NSInteger)requiredParameterCount;
+ (NSPoint)readCoordinatePair:(CGFloat*)pairs
index:(NSInteger)index;
+ (IJSVGPathDataSequence*)pathDataSequence;
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path;
+ (void)parseParams:(CGFloat*)params
paramCount:(NSInteger)paramCount
intoArray:(NSMutableArray<IJSVGCommand*>*)commands
parentCommand:(IJSVGCommand*)parentCommand;
- (id)initWithCommandStringBuffer:(const char*)str
dataStream:(IJSVGPathDataStream*)dataStream;
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
paramCount:(NSInteger)paramCount
previousCommand:(IJSVGCommand*)command;
- (CGFloat)readFloat;
- (NSPoint)readPoint;
- (BOOL)readBOOL;
- (void)resetRead;
@end
@@ -1,217 +0,0 @@
//
// IJSVGCommand.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommand.h"
#import "IJSVGUtils.h"
#import "IJSVGCommandClose.h"
#import "IJSVGCommandCurve.h"
#import "IJSVGCommandEllipticalArc.h"
#import "IJSVGCommandHorizontalLine.h"
#import "IJSVGCommandLineTo.h"
#import "IJSVGCommandMove.h"
#import "IJSVGCommandQuadraticCurve.h"
#import "IJSVGCommandSmoothCurve.h"
#import "IJSVGCommandSmoothQuadraticCurve.h"
#import "IJSVGCommandVerticalLine.h"
@implementation IJSVGCommand
+ (BOOL)requiresCustomParameterParsing
{
return NO;
}
+ (NSInteger)requiredParameterCount
{
return 1;
}
+ (IJSVGPathDataSequence*)pathDataSequence
{
return NULL;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
}
+ (void)parseParams:(CGFloat*)params
paramCount:(NSInteger)paramCount
intoArray:(NSMutableArray<IJSVGCommand*>*)commands
parentCommand:(IJSVGCommand*)parentCommand
{
}
+ (NSPoint)readCoordinatePair:(CGFloat*)pairs
index:(NSInteger)index
{
return NSMakePoint(pairs[index * 2], pairs[index * 2 + 1]);
}
+ (void)load
{
// register here...
}
+ (Class)commandClassForCommandChar:(char)aChar
{
aChar = tolower(aChar);
switch (aChar) {
case 'a':
return IJSVGCommandEllipticalArc.class;
case 'c':
return IJSVGCommandCurve.class;
case 'h':
return IJSVGCommandHorizontalLine.class;
case 'l':
return IJSVGCommandLineTo.class;
case 'm':
return IJSVGCommandMove.class;
case 'q':
return IJSVGCommandQuadraticCurve.class;
case 's':
return IJSVGCommandSmoothCurve.class;
case 't':
return IJSVGCommandSmoothQuadraticCurve.class;
case 'v':
return IJSVGCommandVerticalLine.class;
case 'z':
return IJSVGCommandClose.class;
}
return nil;
}
- (void)dealloc
{
(void)([_commandString release]), _commandString = nil;
(void)([_subCommands release]), _subCommands = nil;
if (_parameters) {
(void)(free(_parameters)), _parameters = nil;
}
[super dealloc];
}
- (id)initWithCommandStringBuffer:(const char*)str
dataStream:(IJSVGPathDataStream*)dataStream
{
if ((self = [super init]) != nil) {
// work out the basics
_currentIndex = 0;
_command = str[0];
_type = [IJSVGUtils typeForCommandChar:_command];
NSInteger sets = 0;
NSInteger paramCount = [self.class requiredParameterCount];
IJSVGPathDataSequence* sequence = [self.class pathDataSequence];
_parameters = IJSVGParsePathDataStreamSequence(str, strlen(str),
dataStream, sequence, [self.class requiredParameterCount], &sets);
if (sets <= 1) {
CGFloat* subParams = [self parametersFromIndexOffset:0];
IJSVGCommand* command = [self subcommandWithParameters:subParams
paramCount:paramCount
previousCommand:nil];
_subCommands = @[ command ].retain;
} else {
NSMutableArray<IJSVGCommand*>* subCommandArray = nil;
subCommandArray = [[NSMutableArray alloc] initWithCapacity:sets].autorelease;
// interate over the sets
IJSVGCommand* lastCommand = nil;
for (NSInteger i = 0; i < sets; i++) {
// memory for this will be handled by the created subcommand
CGFloat* subParams = [self parametersFromIndexOffset:i];
// generate the subcommand
IJSVGCommand* command = [self subcommandWithParameters:subParams
paramCount:paramCount
previousCommand:lastCommand];
// make sure we assign the last command or hell breaks
// lose and the firey demons will run wild, namely, commands will break
// if they are multiples of a set
lastCommand = command;
[subCommandArray addObject:command];
}
// store the retained value
_subCommands = subCommandArray.copy;
}
}
return self;
}
- (CGFloat*)parametersFromIndexOffset:(NSInteger)index
{
CGFloat* subParams = 0;
NSInteger req = [self.class requiredParameterCount];
if (req != 0) {
subParams = (CGFloat*)malloc(req * sizeof(CGFloat));
memcpy(subParams, &self.parameters[index * req], sizeof(CGFloat) * req);
}
return subParams;
}
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
paramCount:(NSInteger)paramCount
previousCommand:(IJSVGCommand*)aPreviousCommand
{
// create a subcommand per set
IJSVGCommand* c = [[[self.class alloc] init] autorelease];
c.parameterCount = paramCount;
c.parameters = subParams;
c.type = self.type;
c.command = self.command;
c.previousCommand = aPreviousCommand;
c.isSubCommand = aPreviousCommand != nil;
return c;
}
- (CGFloat)readFloat
{
CGFloat f = _parameters[_currentIndex];
_currentIndex++;
return f;
}
- (NSPoint)readPoint
{
CGFloat x = _parameters[_currentIndex];
CGFloat y = _parameters[_currentIndex + 1];
_currentIndex += 2;
return NSMakePoint(x, y);
}
- (BOOL)readBOOL
{
return [self readFloat] == 1;
}
- (void)resetRead
{
_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
@@ -1,38 +0,0 @@
//
// IJSVGCommandCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandCurve.h"
@implementation IJSVGCommandCurve
+ (NSInteger)requiredParameterCount
{
return 6;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddCurveToPoint(path.path, NULL, params[0], params[1],
params[2], params[3],
params[4], params[5]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddCurveToPoint(path.path, NULL,
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
@@ -1,139 +0,0 @@
//
// IJSVGCommandArc.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandEllipticalArc.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandEllipticalArc
static IJSVGPathDataSequence* _sequence;
+ (NSInteger)requiredParameterCount
{
return 7;
}
+ (IJSVGPathDataSequence*)pathDataSequence
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sequence = (IJSVGPathDataSequence*)malloc(sizeof(IJSVGPathDataSequence) * 7);
_sequence[0] = kIJSVGPathDataSequenceTypeFloat;
_sequence[1] = kIJSVGPathDataSequenceTypeFloat;
_sequence[2] = kIJSVGPathDataSequenceTypeFloat;
_sequence[3] = kIJSVGPathDataSequenceTypeFlag;
_sequence[4] = kIJSVGPathDataSequenceTypeFlag;
_sequence[5] = kIJSVGPathDataSequenceTypeFloat;
_sequence[6] = kIJSVGPathDataSequenceTypeFloat;
});
return _sequence;
}
// modified from https://github.com/SVGKit/SVGKit/blob/880c94a5b77b6f22beb491a7a7e02ace220c32af/Source/Parsers/SVGKPointsAndPathsParser.m
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
CGPoint radii = CGPointZero;
CGPoint arcEndPoint = CGPointZero;
CGPoint pathCurrentPoint = path.currentPoint;
CGFloat xAxisRotation = 0.f;
BOOL largeArcFlag = NO;
BOOL sweepFlag = NO;
radii = [currentCommand readPoint];
xAxisRotation = [currentCommand readFloat];
largeArcFlag = [currentCommand readBOOL];
sweepFlag = [currentCommand readBOOL];
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) {
arcEndPoint.x += pathCurrentPoint.x;
arcEndPoint.y += pathCurrentPoint.y;
}
CGFloat x1 = pathCurrentPoint.x;
CGFloat y1 = pathCurrentPoint.y;
CGFloat x2 = arcEndPoint.x;
CGFloat y2 = arcEndPoint.y;
if (rx == 0.f || ry == 0.f) {
CGPathAddLineToPoint(path.path, NULL, x2, y2);
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 delta = xp_2 / rx_2 + yp_2 / ry_2;
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;
CGAffineTransform transform = CGAffineTransformMakeScale(1.f / rx, 1.f / ry);
transform = CGAffineTransformRotate(transform, -xAxisRotation);
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);
CGPathAddRelativeArc(path.path, &transform, 0.f, 0.f, 1.f,
startAngle, angleDelta);
}
@end
@@ -1,34 +0,0 @@
//
// IJSVGCommandHorizontalLine.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandHorizontalLine.h"
@implementation IJSVGCommandHorizontalLine
+ (NSInteger)requiredParameterCount
{
return 1;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddLineToPoint(path.path, NULL, params[0], path.currentPoint.y);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddLineToPoint(path.path, NULL, currentPoint.x + params[0],
path.currentPoint.y);
}
@end
@@ -1,34 +0,0 @@
//
// IJSVGCommandLineTo.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandLineTo.h"
@implementation IJSVGCommandLineTo
+ (NSInteger)requiredParameterCount
{
return 2;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddLineToPoint(path.path, NULL, params[0], params[1]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddLineToPoint(path.path, NULL, currentPoint.x + params[0],
currentPoint.y + params[1]);
}
@end
@@ -1,54 +0,0 @@
//
// IJSVGCommandMove.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandLineTo.h"
#import "IJSVGCommandMove.h"
@implementation IJSVGCommandMove
+ (NSInteger)requiredParameterCount
{
return 2;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
// move to's allow more then one move to, but if there are more then one,
// we need to run the line to instead...who knew!
if (command.class == self.class && currentCommand.isSubCommand == YES) {
[IJSVGCommandLineTo runWithParams:params
paramCount:count
command:currentCommand
previousCommand:command
type:type
path:path];
return;
}
// actual move to command - do a moveToPoint only
// if the type is absolute, or its possible the type is
// 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;
}
CGPoint currentPoint = path.currentPoint;
CGPathMoveToPoint(path.path, NULL,
currentPoint.x + params[0],
currentPoint.y + params[1]);
}
@end
@@ -1,37 +0,0 @@
//
// IJSVGCommandQuadraticCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandQuadraticCurve.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandQuadraticCurve
+ (NSInteger)requiredParameterCount
{
return 4;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddQuadCurveToPoint(path.path, NULL, params[0], params[1],
params[2], params[3]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddQuadCurveToPoint(path.path, NULL,
currentPoint.x + params[0], currentPoint.y + params[1],
currentPoint.x + params[2], currentPoint.y + params[3]);
}
@end
@@ -1,64 +0,0 @@
//
// IJSVGCommandSmoothCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandCurve.h"
#import "IJSVGCommandSmoothCurve.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandSmoothCurve
+ (NSInteger)requiredParameterCount
{
return 4;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
CGPoint currentPoint = path.currentPoint;
CGPoint firstControl = CGPointMake(currentPoint.x, currentPoint.y);
if (command != nil) {
if (command.class == [IJSVGCommandCurve class] || command.class == self.class) {
if (command.class == [IJSVGCommandCurve class]) {
if (command.type == kIJSVGCommandTypeAbsolute) {
firstControl = CGPointMake(-1 * command.parameters[2] + 2 * currentPoint.x,
-1 * command.parameters[3] + 2 * currentPoint.y);
} else {
NSPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[4],
currentPoint.y - command.parameters[5]);
firstControl = CGPointMake(-1 * (command.parameters[2] + oldPoint.x) + 2 * currentPoint.x,
-1 * (command.parameters[3] + oldPoint.y) + 2 * currentPoint.y);
}
} else {
if (command.type == kIJSVGCommandTypeAbsolute) {
firstControl = CGPointMake(-1 * command.parameters[0] + 2 * currentPoint.x,
-1 * command.parameters[1] + 2 * currentPoint.y);
} else {
NSPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[2],
currentPoint.y - command.parameters[3]);
firstControl = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * currentPoint.x,
-1 * (command.parameters[1] + oldPoint.y) + 2 * currentPoint.y);
}
}
}
}
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddCurveToPoint(path.path, NULL, firstControl.x, firstControl.y,
params[0], params[1], params[2], params[3]);
return;
}
CGPathAddCurveToPoint(path.path, NULL, firstControl.x, firstControl.y,
currentPoint.x + params[0], currentPoint.y + params[1],
currentPoint.x + params[2], currentPoint.y + params[3]);
}
@end
@@ -1,57 +0,0 @@
//
// IJSVGCommandCommandQuadraticCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandQuadraticCurve.h"
#import "IJSVGCommandSmoothQuadraticCurve.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandSmoothQuadraticCurve
+ (NSInteger)requiredParameterCount
{
return 2;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
CGPoint currentPoint = path.currentPoint;
CGPoint commandPoint = CGPointMake(currentPoint.x, currentPoint.y);
if (command != nil) {
if (command.class == IJSVGCommandQuadraticCurve.class) {
// quadratic curve
if (command.type == kIJSVGCommandTypeAbsolute) {
commandPoint = NSMakePoint(-1 * command.parameters[0] + 2 * currentPoint.x,
-1 * command.parameters[1] + 2 * currentPoint.y);
} else {
CGPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[2],
currentPoint.y - command.parameters[3]);
commandPoint = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * (currentPoint.x),
-1 * (command.parameters[1] + oldPoint.y) + 2 * currentPoint.y);
}
} else if (command.class == self.class) {
// smooth quadratic curve
commandPoint = CGPointMake(-1 * (path.lastControlPoint.x) + 2 * (currentPoint.x),
-1 * (path.lastControlPoint.y) + 2 * currentPoint.y);
}
}
path.lastControlPoint = commandPoint;
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddQuadCurveToPoint(path.path, NULL, commandPoint.x, commandPoint.y,
params[0], params[1]);
return;
}
CGPathAddQuadCurveToPoint(path.path, NULL, commandPoint.x, commandPoint.y,
currentPoint.x + params[0], currentPoint.y + params[1]);
}
@end
@@ -1,33 +0,0 @@
//
// IJSVGCommandVerticalLine.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandVerticalLine.h"
@implementation IJSVGCommandVerticalLine
+ (NSInteger)requiredParameterCount
{
return 1;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddLineToPoint(path.path, NULL, path.currentPoint.x, params[0]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddLineToPoint(path.path, NULL, currentPoint.x, currentPoint.y + params[0]);
}
@end
-184
View File
@@ -1,184 +0,0 @@
//
// IJSVGImage.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColorList.h>
#import <IJSVG/IJSVGExporter.h>
#import <IJSVG/IJSVGGradientLayer.h>
#import <IJSVG/IJSVGGroupLayer.h>
#import <IJSVG/IJSVGImageLayer.h>
#import <IJSVG/IJSVGLayerTree.h>
#import <IJSVG/IJSVGParser.h>
#import <IJSVG/IJSVGRendering.h>
#import <IJSVG/IJSVGRenderingStyle.h>
#import <IJSVG/IJSVGTransaction.h>
#import <Foundation/Foundation.h>
@class IJSVG;
typedef NS_OPTIONS(NSInteger, IJSVGMatchPropertiesMask) {
IJSVGMatchPropertyNone = 0,
IJSVGMatchPropertyContainsMaskedElement = 1 << 0,
IJSVGMatchPropertyContainsStrokedElement = 1 << 1
};
@protocol IJSVGDelegate <NSObject, IJSVGParserDelegate>
@optional
- (BOOL)svg:(IJSVG*)svg
shouldHandleForeignObject:(IJSVGForeignObject*)foreignObject;
- (void)svg:(IJSVG*)svg
handleForeignObject:(IJSVGForeignObject*)foreignObject
document:(NSXMLDocument*)document;
- (void)svg:(IJSVG*)svg
foundSubSVG:(IJSVG*)subSVG
withSVGString:(NSString*)subSVGString;
@end
@interface IJSVG : NSObject <NSPasteboardWriting, IJSVGParserDelegate> {
@private
IJSVGParser* _group;
CGFloat _scale;
CGFloat _clipScale;
id<IJSVGDelegate> _delegate;
IJSVGLayer* _layerTree;
CGRect _viewBox;
CGFloat _backingScaleFactor;
CGFloat _lastProposedBackingScale;
IJSVGRenderQuality _lastProposedRenderQuality;
CGFloat _backingScale;
NSMutableDictionary* _replacementColors;
struct {
unsigned int shouldHandleForeignObject : 1;
unsigned int handleForeignObject : 1;
unsigned int shouldHandleSubSVG : 1;
} _respondsTo;
}
// set this to be called when the layer is about to draw, it will call this
// and ask for the scale of the backing store where its going to be drawn
// and apply the scale to each layer that has custom drawing against it, mainly
// pattern and gradient layers
@property (nonatomic, copy) IJSVGRenderingBackingScaleFactorHelper renderingBackingScaleHelper;
// global overwriting rules for when rendering an SVG, this will overide any
// fillColor, strokeColor, pattern and gradient fill
@property (nonatomic, assign) IJSVGRenderQuality renderQuality;
@property (nonatomic, assign) BOOL clipToViewport;
@property (nonatomic, retain) IJSVGRenderingStyle* renderingStyle;
@property (nonatomic, readonly) IJSVGUnitSize * intrinsicSize;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;
- (void)prepForDrawingInView:(NSView*)view;
- (BOOL)isFont;
- (IJSVGGroup*)rootNode;
- (NSRect)viewBox;
- (NSArray<IJSVGPath*>*)glyphs;
- (NSString*)identifier;
- (IJSVGLayer*)layer;
- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree;
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive;
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options;
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (CGFloat)computeBackingScale:(CGFloat)scale;
- (void)discardDOM;
+ (id)svgNamed:(NSString*)string;
+ (id)svgNamed:(NSString*)string
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithImage:(NSImage*)image;
- (id)initWithSVGLayer:(IJSVGGroupLayer*)group
viewBox:(NSRect)viewBox;
- (id)initWithSVGString:(NSString*)string
error:(NSError**)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithSVGString:(NSString*)string;
- (id)initWithSVGString:(NSString*)string
error:(NSError**)error;
- (id)initWithSVGData:(NSData*)data;
- (id)initWithSVGData:(NSData*)data
error:(NSError**)error;
- (id)initWithFile:(NSString*)file;
- (id)initWithFile:(NSString*)file
error:(NSError**)error;
- (id)initWithFile:(NSString*)file
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFile:(NSString*)file
error:(NSError**)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFilePathURL:(NSURL*)aURL;
- (id)initWithFilePathURL:(NSURL*)aURL
error:(NSError**)error;
- (id)initWithFilePathURL:(NSURL*)aURL
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFilePathURL:(NSURL*)aURL
error:(NSError**)error
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
error:(NSError**)error;
- (NSImage*)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped;
- (NSImage*)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped
error:(NSError**)error;
- (NSImage*)imageByMaintainingAspectRatioWithSize:(NSSize)aSize
flipped:(BOOL)flipped
error:(NSError**)error;
- (CGImageRef)newCGImageRefWithSize:(CGSize)size
flipped:(BOOL)flipped
error:(NSError**)error;
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)size;
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)aSize
error:(NSError**)error;
- (BOOL)drawInRect:(NSRect)rect;
- (BOOL)drawInRect:(NSRect)rect
error:(NSError**)error;
- (void)drawInRect:(NSRect)rect
context:(CGContextRef)context;
- (NSData*)PDFData;
- (NSData*)PDFData:(NSError**)error;
- (NSData*)PDFDataWithRect:(NSRect)rect;
- (NSData*)PDFDataWithRect:(NSRect)rect
error:(NSError**)error;
- (void)beginVectorDraw;
- (void)endVectorDraw;
- (NSRect)computeOriginalDrawingFrameWithSize:(NSSize)aSize;
- (void)setNeedsDisplay;
// colors
- (IJSVGColorList*)colorList;
- (void)performBlock:(dispatch_block_t)block;
// matching
- (BOOL)matchesPropertiesWithMask:(IJSVGMatchPropertiesMask)mask;
@end
File diff suppressed because it is too large Load Diff
@@ -1,29 +0,0 @@
//
// IJSVGFontConverter.h
// IJSVGExample
//
// Created by Curtis Hard on 21/05/2015.
// Copyright (c) 2015 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVG.h>
#import <Foundation/Foundation.h>
typedef void (^IJSVGFontConverterEnumerateBlock)(NSString* unicode, IJSVG* svg);
@interface IJSVGFontConverter : NSObject {
@private
NSURL* _url;
NSFont* _font;
NSMutableDictionary<NSString*, id>* _transformedPaths;
}
- (id)initWithFontAtFileURL:(NSURL*)url;
- (NSFont*)font;
- (void)enumerateUsingBlock:(IJSVGFontConverterEnumerateBlock)block;
+ (IJSVG*)convertIJSVGPathToSVG:(IJSVGPath*)path;
+ (IJSVG*)convertPathToSVG:(CGPathRef)path;
@end
@@ -1,25 +0,0 @@
//
// IJSVGImageRep.h
// IJSVGExample
//
// Created by Curtis Hard on 15/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGParser.h"
#import <Cocoa/Cocoa.h>
@class IJSVG;
@interface IJSVGImageRep : NSImageRep {
@private
IJSVG* _svg;
}
- (instancetype)initWithData:(NSData*)data;
@property (nonatomic, readonly) CGRect viewBox;
@property (nonatomic, readonly) IJSVG* SVG;
@end
@@ -1,115 +0,0 @@
//
// IJSVGImageRep.m
// IJSVGExample
//
// Created by Curtis Hard on 15/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGImageRep.h"
@implementation IJSVGImageRep
+ (void)load
{
[NSBitmapImageRep registerImageRepClass:self];
}
+ (BOOL)canInitWithData:(NSData*)data
{
return [IJSVGParser isDataSVG:data];
}
+ (NSArray<NSString*>*)imageTypes
{
if (@available(macOS 10.10, *)) {
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
} else {
return @[ @"public.svg-image", @"svg" ];
}
}
+ (NSArray<NSString*>*)imageUnfilteredTypes
{
if (@available(macOS 10.10, *)) {
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
} else {
return @[ @"public.svg-image", @"svg" ];
}
}
+ (NSArray<NSImageRep*>*)imageRepsWithData:(NSData*)data
{
IJSVGImageRep* instance = [self imageRepWithData:data];
if (instance == nil) {
return @[];
}
return @[ instance ];
}
+ (instancetype)imageRepWithData:(NSData*)data
{
return [[[self alloc] initWithData:data] autorelease];
}
- (void)dealloc
{
(void)([_svg release]), _svg = nil;
[super dealloc];
}
- (instancetype)initWithData:(NSData*)data
{
if ((self = [super init]) != nil) {
// grab the string from the data
// its more then likely UTF-8...
NSString* string = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
_svg = [[IJSVG alloc] initWithSVGString:string];
// no valid SVG, just return nil;
if (_svg == nil) {
[self release];
return nil;
}
// set default properties
self.pixelsWide = _svg.viewBox.size.width;
self.pixelsHigh = _svg.viewBox.size.height;
self.size = _svg.viewBox.size;
}
return self;
}
- (BOOL)draw
{
[_svg drawInRect:self.viewBox];
return YES;
}
- (BOOL)drawAtPoint:(NSPoint)point
{
[_svg drawAtPoint:point
size:_svg.viewBox.size];
return YES;
}
- (BOOL)drawInRect:(NSRect)rect
{
[_svg drawInRect:rect];
return YES;
}
- (CGRect)viewBox
{
return _svg.viewBox;
}
- (IJSVG*)SVG
{
return _svg;
}
@end
@@ -1,25 +0,0 @@
//
// IJSVGView.h
// IconJar
//
// Created by Curtis Hard on 04/04/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVG.h>
#import <Cocoa/Cocoa.h>
IB_DESIGNABLE
@interface IJSVGView : NSView {
IBInspectable NSString* imageName;
IBInspectable NSColor* tintColor;
IJSVG* SVG;
}
@property (nonatomic, retain) IJSVG* SVG;
+ (IJSVGView*)viewWithSVGNamed:(NSString*)name;
- (id)initWithSVG:(IJSVG*)anSvg;
@end
@@ -1,118 +0,0 @@
//
// IJSVGExporter.h
// IJSVGExample
//
// Created by Curtis Hard on 06/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <IJSVG/IJSVGUtils.h>
#import <IJSVG/IJSVGColorType.h>
@class IJSVG;
@class IJSVGExporter;
@class IJSVGLayer;
@class IJSVGNode;
NS_ASSUME_NONNULL_BEGIN
typedef void (^IJSVGCGPathHandler)(const CGPathElement* pathElement);
typedef void (^IJSVGPathElementEnumerationBlock)(const CGPathElement* pathElement, CGPoint currentPoint);
void IJSVGExporterPathCaller(void* info, const CGPathElement* pathElement);
typedef NS_OPTIONS(NSInteger, IJSVGExporterOptions) {
IJSVGExporterOptionNone = 1 << 0,
IJSVGExporterOptionRemoveUselessGroups = 1 << 1,
IJSVGExporterOptionRemoveUselessDef = 1 << 2,
IJSVGExporterOptionMoveAttributesToGroup = 1 << 3,
IJSVGExporterOptionCreateUseForPaths = 1 << 4,
IJSVGExporterOptionSortAttributes = 1 << 5,
IJSVGExporterOptionCollapseGroups = 1 << 6,
IJSVGExporterOptionCleanupPaths = 1 << 7,
IJSVGExporterOptionRemoveHiddenElements = 1 << 8,
IJSVGExporterOptionScaleToSizeIfNecessary = 1 << 9,
IJSVGExporterOptionCompressOutput = 1 << 10,
IJSVGExporterOptionCollapseGradients = 1 << 11,
IJSVGExporterOptionCreateClasses = 1 << 12,
IJSVGExporterOptionRemoveWidthHeightAttributes = 1 << 13,
IJSVGExporterOptionColorAllowRRGGBBAA = 1 << 14,
IJSVGExporterOptionRemoveComments = 1 << 15,
IJSVGExporterOptionCenterWithinViewBox = 1 << 16,
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);
void IJSVGEnumerateCGPathElements(CGPathRef path, IJSVGPathElementEnumerationBlock enumBlock);
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 {
@private
IJSVG* _svg;
CGSize _size;
IJSVGExporterOptions _options;
NSXMLDocument* _dom;
NSXMLElement* _defElement;
NSInteger _idCount;
NSInteger _shortIdCount;
BOOL _appliedXLink;
struct {
unsigned int identifierForElement: 1;
unsigned int stringForColor: 1;
} _respondsTo;
}
@property (nonatomic, assign) id<IJSVGExporterDelegate> delegate;
@property (nonatomic, assign) IJSVGFloatingPointOptions floatingPointOptions;
@property (nonatomic, copy, nullable) NSString* title;
@property (nonatomic, copy, nullable) NSString* desc;
- (id)initWithSVG:(IJSVG*)svg
size:(CGSize)size
options:(IJSVGExporterOptions)options;
- (id)initWithSVG:(IJSVG*)svg
size:(CGSize)size
options:(IJSVGExporterOptions)options
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (NSString*)SVGString;
- (NSData*)SVGData;
- (IJSVG*)SVG:(NSError**)error;
@end
NS_ASSUME_NONNULL_END
File diff suppressed because it is too large Load Diff
@@ -1,67 +0,0 @@
//
// IJSVGExporterPathInstruction.h
// IconJar
//
// Created by Curtis Hard on 08/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef struct {
char instruction;
NSArray<NSString*>* params;
} IJSVGExporterPathInstructionCommand;
typedef struct {
CGPoint center;
CGFloat radius;
} IJSVGExporterPathInstructionCircle;
@interface IJSVGExporterPathInstruction : NSObject {
@private
NSInteger _dataCount;
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);
void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand* _Nullable command);
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (id)initWithInstruction:(char)instruction
dataCount:(NSInteger)floatCount;
- (CGFloat*)data;
- (NSInteger)dataLength;
+ (NSArray<IJSVGExporterPathInstruction*>*)convertInstructionsCurves:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
+ (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
NS_ASSUME_NONNULL_END
static NSInteger const kIJSVGExporterPathInstructionFloatPrecision = 3;
static CGFloat const kIJSVGExporterPathInstructionErrorThreshold = 1e-2;
#define IJ_SVG_EXPORT_ROUND(value) IJSVGExporterPathFloatToFixed(value, kIJSVGExporterPathInstructionFloatPrecision)
@@ -1,629 +0,0 @@
//
// IJSVGExporterPathInstruction.m
// IconJar
//
// Created by Curtis Hard on 08/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGExporter.h"
#import "IJSVGExporterPathInstruction.h"
#import "IJSVGUtils.h"
#import <math.h>
@implementation IJSVGExporterPathInstruction
@synthesize instruction = _instruction;
- (void)dealloc
{
if (_data != NULL) {
(void)free(_data), _data = NULL;
}
if (_base != NULL) {
(void)free(_base), _base = NULL;
}
if (_coords != NULL) {
(void)free(_coords), _coords = NULL;
}
[super dealloc];
}
- (id)initWithInstruction:(char)instruction
dataCount:(NSInteger)floatCount
{
if ((self = [super init]) != nil) {
_instruction = instruction;
// only allocate if not zero
if (floatCount != 0) {
_dataCount = 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;
}
- (NSInteger)dataLength
{
return _dataCount;
}
- (CGFloat*)data
{
return _data;
}
- (CGFloat*)base
{
return _base;
}
- (CGFloat*)coords
{
return _coords;
}
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command)
{
IJSVGExporterPathInstructionCommand* copy = NULL;
copy = (IJSVGExporterPathInstructionCommand*)malloc(sizeof(IJSVGExporterPathInstructionCommand));
copy->instruction = command.instruction;
copy->params = command.params;
return copy;
}
void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand* _Nullable command)
{
if (command != NULL) {
free(command);
}
}
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
IJSVGExporterPathInstructionCommand* lastCommand = NULL;
NSMutableString* string = [[[NSMutableString alloc] init] autorelease];
for (NSValue* value in instructionSets) {
// read back the bytes
IJSVGExporterPathInstructionCommand command;
[value getValue:&command];
// add on the instruction character only if there is no current command
// or the last command is not the same as the current command
// if they both are the same, we still need to seperate them via a space
if (lastCommand == nil || (lastCommand != nil && lastCommand->instruction != command.instruction)) {
[string appendFormat:@"%c", command.instruction];
} else {
[string appendString:@" "];
}
// compresses the floats
NSString* compressedFloats = IJSVGCompressFloatParameterArray(command.params);
[string appendString:compressedFloats];
// store last command
IJSVGExporterPathInstructionCommandFree(lastCommand);
lastCommand = IJSVGExporterPathInstructionCommandCopy(command);
}
IJSVGExporterPathInstructionCommandFree(lastCommand);
return string;
}
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
NSMutableArray* pathInstructions = [[[NSMutableArray alloc] init] autorelease];
for (IJSVGExporterPathInstruction* instruction in instructions) {
CGFloat* data = instruction.data;
const char lowerInstruction = tolower(instruction.instruction);
NSArray<NSString*>* set = nil;
switch (lowerInstruction) {
case 't':
case 'm':
case 'l': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions)
];
break;
}
case 'v':
case 'h': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions)
];
break;
}
case 'c': {
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)
];
break;
}
case 's':
case 'q': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
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;
}
// close path
case 'z': {
set = @[];
}
}
// wrap into the command and give to the array
IJSVGExporterPathInstructionCommand wrapper;
wrapper.instruction = instruction.instruction;
wrapper.params = set ?: @[];
// encode and store
NSValue* value = [NSValue valueWithBytes:&wrapper
objCType:@encode(IJSVGExporterPathInstructionCommand)];
[pathInstructions addObject:value];
}
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
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
CGFloat point[2] = { 0, 0 };
CGFloat subpathPoint[2] = { 0, 0 };
IJSVGExporterPathInstruction* baseInstruction = nil;
IJSVGExporterPathInstruction* prevInstruction = nil;
NSInteger index = 0;
for (IJSVGExporterPathInstruction* anInstruction in instructions) {
char instruction = anInstruction.instruction;
CGFloat* data = anInstruction.data;
NSInteger length = anInstruction.dataLength;
if (data != NULL) {
// already relative
if (instruction == 'm' || instruction == 'c' || instruction == 's' || instruction == 'l' || instruction == 'q' || instruction == 't' || instruction == 'a') {
point[0] += data[length - 2];
point[1] += data[length - 1];
if (instruction == 'm') {
subpathPoint[0] = point[0];
subpathPoint[1] = point[1];
baseInstruction = anInstruction;
}
} else if (instruction == 'h') {
point[0] += data[0];
} else if (instruction == 'v') {
point[1] += data[0];
}
// convert absolute to relative
if (instruction == 'M') {
if (index > 0) {
instruction = 'm';
}
data[0] -= point[0];
data[1] -= point[1];
subpathPoint[0] = point[0] += data[0];
subpathPoint[1] = point[1] += data[1];
baseInstruction = anInstruction;
} else if (instruction == 'L' || instruction == 'T') {
instruction = tolower(instruction);
data[0] -= point[0];
data[1] -= point[1];
point[0] += data[0];
point[1] += data[1];
} else if (instruction == 'C') {
instruction = 'c';
data[0] -= point[0];
data[1] -= point[1];
data[2] -= point[0];
data[3] -= point[1];
data[4] -= point[0];
data[5] -= point[1];
point[0] += data[4];
point[1] += data[5];
} else if (instruction == 'S' || instruction == 'Q') {
instruction = tolower(instruction);
data[0] -= point[0];
data[1] -= point[1];
data[2] -= point[0];
data[3] -= point[1];
point[0] += data[2];
point[1] += data[3];
} else if (instruction == 'A') {
instruction = 'a';
data[5] -= point[0];
data[6] -= point[1];
point[0] += data[5];
point[1] += data[6];
} else if (instruction == 'H') {
instruction = 'h';
data[0] -= point[0];
point[0] += data[0];
} else if (instruction == 'V') {
instruction = 'v';
data[0] -= point[1];
point[1] += data[0];
}
// reset the instruction
anInstruction.instruction = instruction;
CGFloat* coords = anInstruction.coords;
coords[0] = point[0];
coords[1] = point[1];
} 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[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
prevInstruction = anInstruction;
index++;
}
}
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
// keep track of the current point
__block CGPoint currentPoint = CGPointZero;
NSMutableArray* instructions = [[[NSMutableArray alloc] init] autorelease];
// create the path callback
IJSVGCGPathHandler callback = ^(const CGPathElement* pathElement) {
IJSVGExporterPathInstruction* instruction = nil;
// work out what to do
switch (pathElement->type) {
case kCGPathElementMoveToPoint: {
// move to command
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'M'
dataCount:2] autorelease];
CGPoint point = pathElement->points[0];
instruction.data[0] = point.x;
instruction.data[1] = point.y;
currentPoint = point;
[instructions addObject:instruction];
break;
}
case kCGPathElementAddLineToPoint: {
// line to command
CGPoint point = pathElement->points[0];
if (point.x == currentPoint.x) {
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'V'
dataCount:1] autorelease];
instruction.data[0] = point.y;
} else if (point.y == currentPoint.y) {
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'H'
dataCount:1] autorelease];
instruction.data[0] = point.x;
} else {
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'L'
dataCount:2] autorelease];
instruction.data[0] = point.x;
instruction.data[1] = point.y;
}
currentPoint = point;
[instructions addObject:instruction];
break;
}
case kCGPathElementAddQuadCurveToPoint: {
// quad curve to command
CGPoint controlPoint = pathElement->points[0];
CGPoint point = pathElement->points[1];
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'Q'
dataCount:4] autorelease];
instruction.data[0] = controlPoint.x;
instruction.data[1] = controlPoint.y;
instruction.data[2] = point.x;
instruction.data[3] = point.y;
currentPoint = point;
[instructions addObject:instruction];
break;
}
case kCGPathElementAddCurveToPoint: {
// curve to command
CGPoint controlPoint1 = pathElement->points[0];
CGPoint controlPoint2 = pathElement->points[1];
CGPoint point = pathElement->points[2];
currentPoint = point;
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'C'
dataCount:6] autorelease];
instruction.data[0] = controlPoint1.x;
instruction.data[1] = controlPoint1.y;
instruction.data[2] = controlPoint2.x;
instruction.data[3] = controlPoint2.y;
instruction.data[4] = point.x;
instruction.data[5] = point.y;
[instructions addObject:instruction];
break;
}
case kCGPathElementCloseSubpath: {
// close command
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'Z'
dataCount:0] autorelease];
[instructions addObject:instruction];
break;
}
}
};
// apply the
CGPathApply(path, (__bridge void*)callback, IJSVGExporterPathCaller);
// remove last instruction if it was Z -> M
IJSVGExporterPathInstruction* lastInstruction = instructions.lastObject;
if (lastInstruction.instruction == 'M' || lastInstruction.instruction == 'm') {
if (instructions.count >= 2) {
NSInteger index = [instructions indexOfObject:lastInstruction] - 1;
IJSVGExporterPathInstruction* prevInstruction = instructions[index];
if (prevInstruction.instruction == 'z' || prevInstruction.instruction == 'Z') {
[instructions removeLastObject];
}
}
}
return instructions;
}
@end
@@ -1,98 +0,0 @@
//
// IJSVGGradientLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGGradientLayer.h"
@implementation IJSVGGradientLayer
- (void)dealloc
{
(void)([_gradient release]), _gradient = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
self.requiresBackingScaleHelp = YES;
self.shouldRasterize = YES;
}
return self;
}
- (void)setGradient:(IJSVGGradient*)newGradient
{
if (_gradient != nil) {
(void)([_gradient release]), _gradient = nil;
}
_gradient = [newGradient retain];
// lets check its alpha properties on the colors
BOOL hasAlphaChannel = NO;
NSInteger stops = _gradient.gradient.numberOfColorStops;
for (NSInteger i = 0; i < stops; i++) {
NSColor* color = nil;
[_gradient.gradient getColor:&color
location:NULL
atIndex:i];
if (color.alphaComponent != 1.f) {
hasAlphaChannel = YES;
break;
}
}
self.opaque = hasAlphaChannel == NO;
}
- (void)setOpacity:(float)opacity
{
if (opacity != 1.f) {
self.opaque = NO;
}
[super setOpacity:opacity];
}
- (void)setBackingScaleFactor:(CGFloat)backingScaleFactor
{
switch (self.renderQuality) {
case kIJSVGRenderQualityOptimized: {
backingScaleFactor = (backingScaleFactor * .35f);
break;
}
case kIJSVGRenderQualityLow: {
backingScaleFactor = (backingScaleFactor * .05f);
break;
}
default: {
break;
}
}
[super setBackingScaleFactor:backingScaleFactor];
}
- (void)drawInContext:(CGContextRef)ctx
{
[super drawInContext:ctx];
// nothing to do :(
if (self.gradient == nil) {
return;
}
// draw the gradient
CGAffineTransform trans = CGAffineTransformMakeTranslation(-CGRectGetMinX(_objectRect),
-CGRectGetMinY(_objectRect));
CGAffineTransform transform = CGAffineTransformConcat(_absoluteTransform, trans);
CGContextSaveGState(ctx);
[self.gradient drawInContextRef:ctx
objectRect:_objectRect
absoluteTransform:transform
viewPort:self.viewBox];
CGContextRestoreGState(ctx);
}
@end
@@ -1,166 +0,0 @@
//
// IJSVGLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 07/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGGroupLayer.h"
#import "IJSVGLayer.h"
#import "IJSVGShapeLayer.h"
@implementation IJSVGLayer
- (void)dealloc
{
(void)([_maskingLayer release]), _maskingLayer = nil;
[super dealloc];
}
+ (NSArray*)deepestSublayersOfLayer:(CALayer*)layer
{
NSMutableArray* arr = [[[NSMutableArray alloc] init] autorelease];
for (CALayer* subLayer in layer.sublayers) {
if (subLayer.sublayers.count != 0) {
NSArray* moreLayers = [self deepestSublayersOfLayer:(IJSVGLayer*)subLayer];
[arr addObjectsFromArray:moreLayers];
} else {
[arr addObject:subLayer];
}
}
return arr;
}
+ (void)recursivelyWalkLayer:(CALayer*)layer
withBlock:(void (^)(CALayer* layer, BOOL isMask, BOOL* stop))block
{
// call for layer and mask if there is one
BOOL stop = NO;
block(layer, NO, &stop);
if(stop == YES) {
return;
}
// do the mask too!
if (layer.mask != nil) {
block(layer.mask, YES, &stop);
if(stop == YES) {
return;
}
}
// sublayers!!
for (CALayer* aLayer in layer.sublayers) {
[self recursivelyWalkLayer:aLayer
withBlock:block];
}
}
- (void)setBackingScaleFactor:(CGFloat)newFactor
{
if (_backingScaleFactor == newFactor) {
return;
}
_backingScaleFactor = newFactor;
self.contentsScale = newFactor;
self.rasterizationScale = newFactor;
[self setNeedsDisplay];
}
- (void)_customRenderInContext:(CGContextRef)ctx
{
if (_convertMasksToPaths == YES && _maskingLayer != nil) {
CGContextSaveGState(ctx);
[self applySublayerMaskToContext:ctx
forSublayer:(IJSVGLayer*)self
withOffset:CGPointZero];
[super renderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[super renderInContext:ctx];
}
- (void)setConvertMasksToPaths:(BOOL)flag
{
if (_convertMasksToPaths == flag) {
return;
}
_convertMasksToPaths = flag;
if (flag == YES) {
if (_maskingLayer != nil) {
(void)([_maskingLayer release]), _maskingLayer = nil;
}
_maskingLayer = [(IJSVGLayer*)self.mask retain];
self.mask = nil;
} else {
self.mask = _maskingLayer;
(void)([_maskingLayer release]), _maskingLayer = nil;
}
}
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer*)sublayer
withOffset:(CGPoint)offset
{
// apply any transforms needed
CGPoint layerOffset = offset;
CGAffineTransform sublayerTransform = CATransform3DGetAffineTransform(sublayer.transform);
CGContextConcatCTM(context, CGAffineTransformInvert(sublayerTransform));
// walk up the superlayer chain
CALayer* superlayer = self.superlayer;
if (IJSVGIsSVGLayer(superlayer) == YES) {
[(IJSVGLayer*)superlayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer*)self
withOffset:layerOffset];
}
// grab the masking layer
IJSVGShapeLayer* maskingLayer = [self maskingLayer];
// if its a group we need to get the lowest level children
// and walk up the chain again
if ([maskingLayer isKindOfClass:[IJSVGGroupLayer class]]) {
NSArray* subs = [IJSVGLayer deepestSublayersOfLayer:maskingLayer];
for (IJSVGLayer* subLayer in subs) {
[subLayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer*)self
withOffset:layerOffset];
}
} else if ([maskingLayer isKindOfClass:[IJSVGShapeLayer class]]) {
// is a shape, go for it!
CGPathRef maskPath = maskingLayer.path;
CGContextTranslateCTM(context, -layerOffset.x, -layerOffset.y);
CGContextAddPath(context, maskPath);
CGContextClip(context);
CGContextTranslateCTM(context, layerOffset.x, layerOffset.y);
}
CGContextConcatCTM(context, sublayerTransform);
}
- (IJSVGShapeLayer*)maskingLayer
{
return (IJSVGShapeLayer*)_maskingLayer ?: nil;
}
- (void)renderInContext:(CGContextRef)ctx
{
if (_blendingMode != kCGBlendModeNormal) {
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx, _blendingMode);
[self _customRenderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[self _customRenderInContext:ctx];
}
- (id<CAAction>)actionForKey:(NSString*)event
{
return nil;
}
@end
@@ -1,41 +0,0 @@
//
// IJSVGGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColorList.h>
#import <IJSVG/IJSVGDef.h>
#import <IJSVG/IJSVGTransform.h>
#import <IJSVG/IJSVGGroup.h>
#import <Foundation/Foundation.h>
@interface IJSVGGradient : IJSVGGroup
@property (nonatomic, retain) NSGradient* gradient;
@property (nonatomic, assign) CGGradientRef CGGradient;
@property (nonatomic, retain) IJSVGUnitLength* x1;
@property (nonatomic, retain) IJSVGUnitLength* x2;
@property (nonatomic, retain) IJSVGUnitLength* y1;
@property (nonatomic, retain) IJSVGUnitLength* y2;
@property (nonatomic, retain) IJSVGColorList* colorList;
+ (CGFloat*)computeColorStops:(IJSVGGradient*)gradient
colors:(NSArray**)someColors;
- (CGGradientRef)CGGradient;
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox;
- (void)_debugStart:(CGPoint)startPoint
end:(CGPoint)endPoint
context:(CGContextRef)ctx;
- (IJSVGColorList*)colorList;
- (IJSVGColorList*)computedColorList;
@end
@@ -1,142 +0,0 @@
//
// IJSVGGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGradient.h"
#import "IJSVGParser.h"
@implementation IJSVGGradient
@synthesize colorList = _privateColorList;
- (void)dealloc
{
(void)([_x1 release]), _x1 = nil;
(void)([_x2 release]), _x2 = nil;
(void)([_y1 release]), _y1 = nil;
(void)([_y2 release]), _y2 = nil;
(void)([_gradient release]), _gradient = nil;
(void)([_privateColorList release]), _privateColorList = nil;
if (_CGGradient != nil) {
CGGradientRelease(_CGGradient);
}
[super dealloc];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGGradient* clone = [super copyWithZone:zone];
clone.gradient = [[self.gradient copy] autorelease];
return clone;
}
- (void)setColorList:(IJSVGColorList*)list
{
(void)([_privateColorList release]), _privateColorList = nil;
_privateColorList = list.retain;
if (_CGGradient != nil) {
CGGradientRelease(_CGGradient);
_CGGradient = nil;
}
}
+ (CGFloat *)computeColorStops:(IJSVGGradient*)gradient
colors:(NSArray**)someColors
{
NSArray<IJSVGNode*>* stops = gradient.childNodes;
NSMutableArray* colors = [[[NSMutableArray alloc] initWithCapacity:stops.count] autorelease];
CGFloat* stopsParams = (CGFloat*)malloc(stops.count * sizeof(CGFloat));
NSInteger i = 0;
for(IJSVGNode* stopNode in stops) {
NSColor* color = stopNode.fillColor;
CGFloat opacity = stopNode.fillOpacity.value;
CGFloat offset = stopNode.offset.value;
stopsParams[i++] = offset;
if(color == nil) {
color = [IJSVGColor colorFromHEXInteger:0x000000];
if(opacity != 1.f) {
color = [IJSVGColor changeAlphaOnColor:color
to:opacity];
}
}
[colors addObject:color];
}
*someColors = (NSArray*)colors;
return stopsParams;
}
- (IJSVGColorList*)colorList
{
IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease];
NSInteger num = self.gradient.numberOfColorStops;
for (NSInteger i = 0; i < num; i++) {
NSColor* color;
[self.gradient getColor:&color
location:nil
atIndex:i];
IJSVGColorType* type = [IJSVGColorType typeWithColor:color
flags:IJSVGColorTypeFlagStop];
[sheet addColor:type];
}
return sheet;
}
- (IJSVGColorList*)computedColorList
{
return _privateColorList;
}
- (CGGradientRef)CGGradient
{
// store it in the cache
if (_CGGradient != nil) {
return _CGGradient;
}
// actually create the gradient
NSInteger num = self.gradient.numberOfColorStops;
CGFloat* locations = malloc(sizeof(CGFloat) * num);
CFMutableArrayRef colors = CFArrayCreateMutable(kCFAllocatorDefault, (CFIndex)num,
&kCFTypeArrayCallBacks);
for (NSInteger i = 0; i < num; i++) {
NSColor* color;
[self.gradient getColor:&color
location:&locations[i]
atIndex:i];
if (_privateColorList != nil) {
color = [_privateColorList proposedColorForColor:color];
}
CFArrayAppendValue(colors, color.CGColor);
}
CGGradientRef result = CGGradientCreateWithColors(self.gradient.colorSpace.CGColorSpace,
colors, locations);
CFRelease(colors);
free(locations);
return _CGGradient = result;
}
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox
{
}
- (void)_debugStart:(CGPoint)startPoint
end:(CGPoint)endPoint
context:(CGContextRef)ctx
{
CGContextSaveGState(ctx);
CGContextSetStrokeColorWithColor(ctx, NSColor.blackColor.CGColor);
CGContextSetLineWidth(ctx, 1.f);
CGContextMoveToPoint(ctx, startPoint.x, startPoint.y);
CGContextAddLineToPoint(ctx, endPoint.x, endPoint.y);
CGContextStrokePath(ctx);
}
@end
@@ -1,71 +0,0 @@
//
// IJSVGGroup.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGroup.h"
@implementation IJSVGGroup
- (void)dealloc
{
(void)([_childNodes release]), _childNodes = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_childNodes = [[NSMutableArray alloc] init];
}
return self;
}
- (void)prepareFromCopy
{
if(_childNodes != nil) {
(void)[_childNodes release], _childNodes = nil;
}
_childNodes = [[NSMutableArray alloc] init];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGGroup* node = [super copyWithZone:zone];
[node prepareFromCopy];
for (IJSVGNode* childNode in _childNodes) {
childNode = [[childNode copy] autorelease];
childNode.parentNode = node;
[node addChild:childNode];
}
return node;
}
- (void)purgeChildren
{
[_childNodes removeAllObjects];
}
- (void)addChild:(IJSVGNode*)child
{
if (child != nil) {
[_childNodes addObject:child];
}
}
- (NSArray<IJSVGNode*>*)childNodes
{
return _childNodes;
}
- (NSString*)description
{
return [NSString stringWithFormat:@"%@ - %@",
[super description], self.childNodes];
}
@end
@@ -1,85 +0,0 @@
//
// IJSVGGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGLinearGradient.h"
#import "IJSVGUtils.h"
#import "IJSVGParser.h"
@implementation IJSVGLinearGradient
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGLinearGradient*)aGradient
{
// just ask unit for the value
NSString* x1 = ([element attributeForName:IJSVGAttributeX1].stringValue ?: @"0");
NSString* x2 = ([element attributeForName:IJSVGAttributeX2].stringValue ?: @"100%");
NSString* y1 = ([element attributeForName:IJSVGAttributeY1].stringValue ?: @"0");
NSString* y2 = ([element attributeForName:IJSVGAttributeY2].stringValue ?: @"0");
aGradient.x1 = [IJSVGGradientUnitLength unitWithString:x1 fromUnitType:aGradient.units];
aGradient.x2 = [IJSVGGradientUnitLength unitWithString:x2 fromUnitType:aGradient.units];
aGradient.y1 = [IJSVGGradientUnitLength unitWithString:y1 fromUnitType:aGradient.units];
aGradient.y2 = [IJSVGGradientUnitLength unitWithString:y2 fromUnitType:aGradient.units];
// compute the color stops and colours
NSArray* colors = nil;
CGFloat* stopsParams = [self.class computeColorStops:aGradient
colors:&colors];
// create the gradient with the colours
NSGradient* grad = [[NSGradient alloc] initWithColors:colors
atLocations:stopsParams
colorSpace:IJSVGColor.defaultColorSpace];
free(stopsParams);
return [grad autorelease];
}
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox
{
BOOL inUserSpace = self.units == IJSVGUnitUserSpaceOnUse;
CGPoint gradientStartPoint = CGPointZero;
CGPoint gradientEndPoint = CGPointZero;
CGAffineTransform selfTransform = IJSVGConcatTransforms(self.transforms);
CGRect boundingBox = inUserSpace ? viewBox : objectRect;
// make sure we apply the absolute position to
// transform us back into the correct space
if (inUserSpace == YES) {
CGContextConcatCTM(ctx, absoluteTransform);
}
CGFloat width = CGRectGetWidth(boundingBox);
CGFloat height = CGRectGetHeight(boundingBox);
gradientStartPoint = CGPointMake([self.x1 computeValue:width],
[self.y1 computeValue:height]);
gradientEndPoint = CGPointMake([self.x2 computeValue:width],
[self.y2 computeValue:height]);
// transform the context
CGContextConcatCTM(ctx, selfTransform);
// draw the gradient
CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawLinearGradient(ctx, self.CGGradient, gradientStartPoint,
gradientEndPoint, options);
#ifdef IJSVG_DEBUG
[self _debugStart:gradientStartPoint
end:gradientEndPoint
context:ctx];
#endif
}
@end
@@ -1,165 +0,0 @@
//
// IJSVGNode.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGStyle.h>
#import <IJSVG/IJSVGUnitLength.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@class IJSVGNode;
@class IJSVG;
@class IJSVGGroup;
@class IJSVGDef;
@class IJSVGGradient;
@class IJSVGGroup;
@class IJSVGPattern;
@class IJSVGTransform;
typedef void (^IJSVGNodeWalkHandler)(IJSVGNode* node, BOOL* allowChildNodes, BOOL* stop);
typedef NS_ENUM(NSInteger, IJSVGNodeType) {
IJSVGNodeTypeGroup,
IJSVGNodeTypePath,
IJSVGNodeTypeDef,
IJSVGNodeTypePolygon,
IJSVGNodeTypePolyline,
IJSVGNodeTypeRect,
IJSVGNodeTypeLine,
IJSVGNodeTypeCircle,
IJSVGNodeTypeEllipse,
IJSVGNodeTypeUse,
IJSVGNodeTypeLinearGradient,
IJSVGNodeTypeRadialGradient,
IJSVGNodeTypeClipPath,
IJSVGNodeTypeFont,
IJSVGNodeTypeGlyph,
IJSVGNodeTypeMask,
IJSVGNodeTypeImage,
IJSVGNodeTypePattern,
IJSVGNodeTypeSVG,
IJSVGNodeTypeText,
IJSVGNodeTypeTextSpan,
IJSVGNodeTypeStyle,
IJSVGNodeTypeSwitch,
IJSVGNodeTypeTitle,
IJSVGNodeTypeDesc,
IJSVGNodeTypeStop,
IJSVGNodeTypeNotFound,
};
typedef NS_ENUM(NSInteger, IJSVGWindingRule) {
IJSVGWindingRuleNonZero,
IJSVGWindingRuleEvenOdd,
IJSVGWindingRuleInherit
};
typedef NS_ENUM(NSInteger, IJSVGLineCapStyle) {
IJSVGLineCapStyleNone,
IJSVGLineCapStyleButt,
IJSVGLineCapStyleRound,
IJSVGLineCapStyleSquare,
IJSVGLineCapStyleInherit
};
typedef NS_ENUM(NSInteger, IJSVGLineJoinStyle) {
IJSVGLineJoinStyleNone,
IJSVGLineJoinStyleMiter,
IJSVGLineJoinStyleRound,
IJSVGLineJoinStyleBevel,
IJSVGLineJoinStyleInherit
};
typedef NS_OPTIONS(NSInteger, IJSVGFontTraits) {
IJSVGFontTraitNone = 1 << 0,
IJSVGFontTraitBold = 1 << 1,
IJSVGFontTraitItalic = 1 << 2
};
typedef NS_ENUM(NSInteger, IJSVGBlendMode) {
IJSVGBlendModeNormal = kCGBlendModeNormal,
IJSVGBlendModeMultiply = kCGBlendModeMultiply,
IJSVGBlendModeScreen = kCGBlendModeScreen,
IJSVGBlendModeOverlay = kCGBlendModeOverlay,
IJSVGBlendModeDarken = kCGBlendModeDarken,
IJSVGBlendModeLighten = kCGBlendModeLighten,
IJSVGBlendModeColorDodge = kCGBlendModeColorDodge,
IJSVGBlendModeColorBurn = kCGBlendModeColorBurn,
IJSVGBlendModeHardLight = kCGBlendModeHardLight,
IJSVGBlendModeSoftLight = kCGBlendModeSoftLight,
IJSVGBlendModeDifference = kCGBlendModeDifference,
IJSVGBlendModeExclusion = kCGBlendModeExclusion,
IJSVGBlendModeHue = kCGBlendModeHue,
IJSVGBlendModeSaturation = kCGBlendModeSaturation,
IJSVGBlendModeColor = kCGBlendModeColor,
IJSVGBlendModeLuminosity = kCGBlendModeLuminosity
};
typedef NS_ENUM(NSInteger, IJSVGOverflowVisibility) {
IJSVGOverflowVisibilityHidden,
IJSVGOverflowVisibilityVisible
};
static CGFloat IJSVGInheritedFloatValue = -99.9999991;
@interface IJSVGNode : NSObject <NSCopying>
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;
@property (nonatomic, assign) IJSVGNodeType type;
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* className;
@property (nonatomic, retain) NSArray* classNameList;
@property (nonatomic, copy) NSString* unicode;
@property (nonatomic, assign) BOOL shouldRender;
@property (nonatomic, assign) BOOL usesDefaultFillColor;
@property (nonatomic, retain) IJSVGUnitLength* x;
@property (nonatomic, retain) IJSVGUnitLength* y;
@property (nonatomic, retain) IJSVGUnitLength* width;
@property (nonatomic, retain) IJSVGUnitLength* height;
@property (nonatomic, retain) IJSVGUnitLength* opacity;
@property (nonatomic, retain) IJSVGUnitLength* fillOpacity;
@property (nonatomic, retain) IJSVGUnitLength* strokeOpacity;
@property (nonatomic, retain) IJSVGUnitLength* strokeWidth;
@property (nonatomic, retain) IJSVGUnitLength* offset;
@property (nonatomic, retain) NSColor* fillColor;
@property (nonatomic, retain) NSColor* strokeColor;
@property (nonatomic, copy) NSString* identifier;
@property (nonatomic, assign) IJSVGNode* parentNode;
@property (nonatomic, assign) IJSVGNode* intermediateParentNode;
@property (nonatomic, retain) IJSVGGroup* clipPath;
@property (nonatomic, retain) IJSVGGroup* mask;
@property (nonatomic, assign) IJSVGWindingRule windingRule;
@property (nonatomic, assign) IJSVGLineCapStyle lineCapStyle;
@property (nonatomic, assign) IJSVGLineJoinStyle lineJoinStyle;
@property (nonatomic, retain) NSArray<IJSVGTransform*>* transforms;
@property (nonatomic, retain) IJSVGDef* def;
@property (nonatomic, retain) IJSVGGradient* fillGradient;
@property (nonatomic, retain) IJSVGPattern* fillPattern;
@property (nonatomic, retain) IJSVGGradient* strokeGradient;
@property (nonatomic, retain) IJSVGPattern* strokePattern;
@property (nonatomic, assign) CGFloat* strokeDashArray;
@property (nonatomic, assign) NSInteger strokeDashArrayCount;
@property (nonatomic, retain) IJSVGUnitLength* strokeDashOffset;
@property (nonatomic, retain) IJSVG* svg;
@property (nonatomic, assign) IJSVGUnitType contentUnits;
@property (nonatomic, assign) IJSVGUnitType units;
@property (nonatomic, assign) IJSVGBlendMode blendMode;
@property (nonatomic, assign) IJSVGOverflowVisibility overflowVisibility;
+ (void)walkNodeTree:(IJSVGNode*)node
handler:(IJSVGNodeWalkHandler)handler;
+ (IJSVGNodeType)typeForString:(NSString*)string
kind:(NSXMLNodeKind)kind;
- (void)applyPropertiesFromNode:(IJSVGNode*)node;
- (id)initWithDef:(BOOL)flag;
- (void)addDef:(IJSVGNode*)aDef;
- (IJSVGDef*)defForID:(NSString*)anID;
@end
@@ -1,433 +0,0 @@
//
// IJSVGNode.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGDef.h"
#import "IJSVGNode.h"
#import "IJSVGUtils.h"
#import "IJSVGGroup.h"
@implementation IJSVGNode
- (void)dealloc
{
(void)free(_strokeDashArray), _strokeDashArray = NULL;
(void)([_x release]), _x = nil;
(void)([_y release]), _y = nil;
(void)([_width release]), _width = nil;
(void)([_height release]), _height = nil;
(void)([_opacity release]), _opacity = nil;
(void)([_offset release]), _offset = nil;
(void)([_fillOpacity release]), _fillOpacity = nil;
(void)([_strokeOpacity release]), _strokeOpacity = nil;
(void)([_strokeWidth release]), _strokeWidth = nil;
(void)([_strokeDashOffset release]), _strokeDashOffset = nil;
(void)([_unicode release]), _unicode = nil;
(void)([_fillGradient release]), _fillGradient = nil;
(void)([_strokeGradient release]), _strokeGradient = nil;
(void)([_strokePattern release]), _strokePattern = nil;
(void)([_transforms release]), _transforms = nil;
(void)([_fillColor release]), _fillColor = nil;
(void)([_strokeColor release]), _strokeColor = nil;
(void)([_identifier release]), _identifier = nil;
(void)([_def release]), _def = nil;
(void)([_name release]), _name = nil;
(void)([_title release]), _title = nil;
(void)([_desc release]), _desc = nil;
(void)([_className release]), _className = nil;
(void)([_classNameList release]), _classNameList = nil;
(void)([_fillPattern release]), _fillPattern = nil;
(void)([_clipPath release]), _clipPath = nil;
(void)([_svg release]), _svg = nil;
(void)([_mask release]), _mask = nil;
[super dealloc];
}
+ (IJSVGNodeType)typeForString:(NSString*)string
kind:(NSXMLNodeKind)kind
{
// possible fix for older os's that complain
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;
}
if (strcmp(name, "switch") == 0) {
return IJSVGNodeTypeSwitch;
}
if (strcmp(name, "defs") == 0) {
return IJSVGNodeTypeDef;
}
if (strcmp(name, "g") == 0) {
return IJSVGNodeTypeGroup;
}
if (strcmp(name, "path") == 0) {
return IJSVGNodeTypePath;
}
if (strcmp(name, "polygon") == 0) {
return IJSVGNodeTypePolygon;
}
if (strcmp(name, "polyline") == 0) {
return IJSVGNodeTypePolyline;
}
if (strcmp(name, "rect") == 0) {
return IJSVGNodeTypeRect;
}
if (strcmp(name, "line") == 0) {
return IJSVGNodeTypeLine;
}
if (strcmp(name, "circle") == 0) {
return IJSVGNodeTypeCircle;
}
if (strcmp(name, "ellipse") == 0) {
return IJSVGNodeTypeEllipse;
}
if (strcmp(name, "use") == 0) {
return IJSVGNodeTypeUse;
}
if (strcmp(name, "lineargradient") == 0) {
return IJSVGNodeTypeLinearGradient;
}
if (strcmp(name, "radialgradient") == 0) {
return IJSVGNodeTypeRadialGradient;
}
if(strcmp(name, "stop") == 0) {
return IJSVGNodeTypeStop;
}
if (strcmp(name, "glyph") == 0) {
return IJSVGNodeTypeGlyph;
}
if (strcmp(name, "font") == 0) {
return IJSVGNodeTypeFont;
}
if (strcmp(name, "clippath") == 0) {
return IJSVGNodeTypeClipPath;
}
if (strcmp(name, "mask") == 0) {
return IJSVGNodeTypeMask;
}
if (strcmp(name, "image") == 0) {
return IJSVGNodeTypeImage;
}
if (strcmp(name, "pattern") == 0) {
return IJSVGNodeTypePattern;
}
if (strcmp(name, "svg") == 0) {
return IJSVGNodeTypeSVG;
}
if (strcmp(name, "text") == 0) {
return IJSVGNodeTypeText;
}
if (strcmp(name, "tspan") == 0 || kind == NSXMLTextKind) {
return IJSVGNodeTypeTextSpan;
}
if(strcmp(name, "title") == 0) {
return IJSVGNodeTypeTitle;
}
if(strcmp(name, "desc") == 0) {
return IJSVGNodeTypeDesc;
}
return IJSVGNodeTypeNotFound;
}
- (id)init
{
if ((self = [self initWithDef:YES]) != nil) {
self.opacity = [IJSVGUnitLength unitWithFloat:1];
}
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
{
self.title = node.title;
self.desc = node.desc;
self.name = node.name;
self.type = node.type;
self.unicode = node.unicode;
self.className = node.className;
self.classNameList = node.classNameList;
self.x = node.x;
self.y = node.y;
self.width = node.width;
self.height = node.height;
self.fillGradient = node.fillGradient;
self.fillPattern = node.fillPattern;
self.strokeGradient = node.strokeGradient;
self.strokePattern = node.strokePattern;
self.fillColor = node.fillColor;
self.strokeColor = node.strokeColor;
self.clipPath = node.clipPath;
self.units = node.units;
self.contentUnits = node.contentUnits;
self.opacity = node.opacity;
self.strokeWidth = node.strokeWidth;
self.fillOpacity = node.fillOpacity;
self.strokeOpacity = node.strokeOpacity;
self.identifier = node.identifier;
self.usesDefaultFillColor = node.usesDefaultFillColor;
self.transforms = node.transforms;
self.def = node.def;
self.windingRule = node.windingRule;
self.lineCapStyle = node.lineCapStyle;
self.lineJoinStyle = node.lineJoinStyle;
self.parentNode = node.parentNode;
self.shouldRender = node.shouldRender;
self.blendMode = node.blendMode;
self.overflowVisibility = node.overflowVisibility;
// dash array needs physical memory copied
CGFloat* nStrokeDashArray = (CGFloat*)malloc(node.strokeDashArrayCount * sizeof(CGFloat));
memcpy(self.strokeDashArray, nStrokeDashArray, node.strokeDashArrayCount * sizeof(CGFloat));
self.strokeDashArray = nStrokeDashArray;
self.strokeDashArrayCount = node.strokeDashArrayCount;
self.strokeDashOffset = node.strokeDashOffset;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGNode* node = [self.class allocWithZone:zone];
[node applyPropertiesFromNode:self];
return node;
}
- (id)initWithDef:(BOOL)flag
{
if ((self = [super init]) != nil) {
self.opacity = [IJSVGUnitLength unitWithFloat:0.f];
self.fillOpacity = [IJSVGUnitLength unitWithFloat:1.f];
self.fillOpacity.inherit = YES;
self.strokeDashOffset = [IJSVGUnitLength unitWithFloat:0.f];
self.shouldRender = YES;
self.strokeOpacity = [IJSVGUnitLength unitWithFloat:1.f];
self.strokeOpacity.inherit = YES;
self.strokeWidth = [IJSVGUnitLength unitWithFloat:1.f];
self.strokeWidth.inherit = YES;
self.windingRule = IJSVGWindingRuleInherit;
self.lineCapStyle = IJSVGLineCapStyleInherit;
self.lineJoinStyle = IJSVGLineJoinStyleInherit;
self.units = IJSVGUnitInherit;
self.blendMode = IJSVGBlendModeNormal;
self.overflowVisibility = IJSVGOverflowVisibilityVisible;
if (flag == YES) {
_def = [[IJSVGDef alloc] init];
}
}
return self;
}
- (IJSVGDef*)defForID:(NSString*)anID
{
IJSVGDef* aDef = nil;
if ((aDef = [_def defForID:anID]) != nil) {
return aDef;
}
if (_parentNode != nil) {
return [_parentNode defForID:anID];
}
return nil;
}
- (void)addDef:(IJSVGNode*)aDef
{
[_def addDef:aDef];
}
// winding rule can inherit..
- (IJSVGWindingRule)windingRule
{
if (_windingRule == IJSVGWindingRuleInherit && _parentNode != nil) {
return _parentNode.windingRule;
}
return _windingRule;
}
- (IJSVGLineCapStyle)lineCapStyle
{
if (_lineCapStyle == IJSVGLineCapStyleInherit) {
if (_parentNode != nil) {
return _parentNode.lineCapStyle;
}
}
return _lineCapStyle;
}
- (IJSVGLineJoinStyle)lineJoinStyle
{
if (_lineJoinStyle == IJSVGLineJoinStyleInherit) {
if (_parentNode != nil) {
return _parentNode.lineJoinStyle;
}
}
return _lineJoinStyle;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength*)opacity
{
if (_opacity.inherit && _parentNode != nil) {
return _parentNode.opacity;
}
return _opacity;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength*)fillOpacity
{
if (_fillOpacity.inherit && _parentNode != nil) {
return _parentNode.fillOpacity;
}
return _fillOpacity;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength*)strokeWidth
{
if (_strokeWidth.inherit && _parentNode != nil) {
return _parentNode.strokeWidth;
}
return _strokeWidth;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (NSColor*)strokeColor
{
if (_strokeColor != nil)
return _strokeColor;
if (_strokeColor == nil && _parentNode != nil)
return _parentNode.strokeColor;
return nil;
}
- (IJSVGUnitLength*)strokeOpacity
{
if (_strokeOpacity.inherit && _parentNode != nil) {
return _parentNode.strokeOpacity;
}
return _strokeOpacity;
}
// even though the spec explicity states fill color
// must be on the path, it can also be on the
- (NSColor*)fillColor
{
if (_fillColor == nil && _parentNode != nil) {
return _parentNode.fillColor;
}
return _fillColor;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGGradient*)fillGradient
{
if (_fillGradient == nil && _parentNode != nil) {
return _parentNode.fillGradient;
}
return _fillGradient;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGPattern*)fillPattern
{
if (_fillPattern == nil && _parentNode != nil) {
return _parentNode.fillPattern;
}
return _fillPattern;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGGradient*)strokeGradient
{
if (_strokeGradient == nil && _parentNode != nil) {
return _parentNode.strokeGradient;
}
return _strokeGradient;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGPattern*)strokePattern
{
if (_strokePattern == nil && _parentNode != nil) {
return _parentNode.strokePattern;
}
return _strokePattern;
}
@end
@@ -1,37 +0,0 @@
//
// IJSVGPath.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <Foundation/Foundation.h>
@class IJSVGGroup;
typedef NS_ENUM(NSInteger, IJSVGPrimitivePathType) {
kIJSVGPrimitivePathTypePath,
kIJSVGPrimitivePathTypeRect,
kIJSVGPrimitivePathTypePolygon,
kIJSVGPrimitivePathTypePolyLine,
kIJSVGPrimitivePathTypeCircle,
kIJSVGPrimitivePathTypeEllipse,
kIJSVGPrimitivePathTypeLine
};
@interface IJSVGPath : IJSVGNode {
}
@property (nonatomic, assign) IJSVGPrimitivePathType primitiveType;
@property (nonatomic, assign) CGMutablePathRef path;
@property (nonatomic, assign) CGPoint lastControlPoint;
@property (nonatomic, readonly) CGRect controlPointBoundingBox;
@property (nonatomic, readonly) CGRect pathBoundingBox;
@property (nonatomic, assign, readonly) BOOL isStroked;
- (void)close;
- (NSPoint)currentPoint;
@end
@@ -1,75 +0,0 @@
//
// IJSVGPath.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGroup.h"
#import "IJSVGPath.h"
@implementation IJSVGPath
- (void)dealloc
{
if(_path != NULL) {
(void)CGPathRelease(_path), _path = NULL;
}
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_primitiveType = kIJSVGPrimitivePathTypePath;
_path = CGPathCreateMutable();
}
return self;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGPath* node = [super copyWithZone:zone];
node.path = _path;
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
{
return CGPathGetCurrentPoint(_path);
}
- (void)close
{
CGPathCloseSubpath(_path);
}
- (BOOL)isStroked
{
return (self.strokeColor != nil && self.strokeColor.alphaComponent != 0.f) ||
self.strokePattern != nil ||
self.strokeGradient != nil;
}
@end
@@ -1,23 +0,0 @@
//
// IJSVGRadialGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGGradient.h>
#import <Foundation/Foundation.h>
@interface IJSVGRadialGradient : IJSVGGradient
@property (nonatomic, retain) IJSVGUnitLength* cx;
@property (nonatomic, retain) IJSVGUnitLength* cy;
@property (nonatomic, retain) IJSVGUnitLength* fx;
@property (nonatomic, retain) IJSVGUnitLength* fy;
@property (nonatomic, retain) IJSVGUnitLength* radius;
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGRadialGradient*)gradient;
@end
@@ -1,157 +0,0 @@
//
// IJSVGRadialGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGRadialGradient.h"
#import "IJSVGParser.h"
@implementation IJSVGRadialGradient
- (void)dealloc
{
(void)([_cx release]), _cx = nil;
(void)([_cy release]), _cy = nil;
(void)([_fx release]), _fx = nil;
(void)([_fy release]), _fy = nil;
(void)([_radius release]), _radius = nil;
[super dealloc];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGRadialGradient* grad = [super copyWithZone:zone];
grad.fx = _fx;
grad.fy = _fy;
grad.cx = _cx;
grad.cy = _cy;
grad.radius = _radius;
return grad;
}
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGRadialGradient*)gradient
{
// cx defaults to 50% if not specified
NSDictionary* kv = @{
IJSVGAttributeCX : @"cx",
IJSVGAttributeCY : @"cy",
IJSVGAttributeR : @"radius" };
for (NSString* key in kv.allKeys) {
NSString* str = [element attributeForName:key].stringValue;
IJSVGUnitLength* unit = nil;
if (str != nil) {
unit = [IJSVGUnitLength unitWithString:str
fromUnitType:gradient.units];
} else {
// spec says to say 50% for missing property default
unit = [IJSVGUnitLength unitWithPercentageFloat:.5f];
}
[gradient setValue:unit
forKey:kv[key]];
}
// fx and fy are the same unless specified otherwise
gradient.fx = gradient.cx;
gradient.fy = gradient.cy;
// needs fixing
NSString* fx = [element attributeForName:IJSVGAttributeFX].stringValue;
if (fx != nil) {
gradient.fx = [IJSVGUnitLength unitWithString:fx
fromUnitType:gradient.units];
}
NSString* fy = [element attributeForName:IJSVGAttributeFY].stringValue;
if (fx != nil) {
gradient.fy = [IJSVGUnitLength unitWithString:fy
fromUnitType:gradient.units];
}
if (gradient.gradient != nil) {
return nil;
}
NSArray* colors = nil;
CGFloat* colorStops = [self.class computeColorStops:gradient
colors:&colors];
NSGradient* ret = [[[NSGradient alloc] initWithColors:colors
atLocations:colorStops
colorSpace:IJSVGColor.defaultColorSpace] autorelease];
free(colorStops);
return ret;
}
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox
{
BOOL inUserSpace = self.units == IJSVGUnitUserSpaceOnUse;
CGFloat radius = 0.f;
CGPoint startPoint = CGPointZero;
CGPoint gradientStartPoint = CGPointZero;
CGPoint gradientEndPoint = CGPointZero;
// transforms
CGAffineTransform selfTransform = IJSVGConcatTransforms(self.transforms);
CGRect boundingBox = inUserSpace ? viewBox : objectRect;
// make sure we apply the absolute position to
// transform us back into the correct space
if (inUserSpace == YES) {
CGContextConcatCTM(ctx, absoluteTransform);
}
// compute size based on percentages
CGFloat x = [_cx computeValue:CGRectGetWidth(boundingBox)];
CGFloat y = [_cy computeValue:CGRectGetHeight(boundingBox)];
startPoint = CGPointMake(x, y);
CGFloat val = MIN(CGRectGetWidth(boundingBox),
CGRectGetHeight(boundingBox));
radius = [_radius computeValue:val];
CGFloat ex = [_fx computeValue:CGRectGetWidth(boundingBox)];
CGFloat ey = [_fy computeValue:CGRectGetHeight(boundingBox)];
gradientEndPoint = CGPointMake(ex, ey);
gradientStartPoint = startPoint;
// transform if width or height is not equal - this can only
// be done if we are using objectBoundingBox
if (inUserSpace == NO && CGRectGetWidth(boundingBox) != CGRectGetHeight(boundingBox)) {
CGAffineTransform tr = CGAffineTransformMakeTranslation(gradientStartPoint.x,
gradientStartPoint.y);
if (CGRectGetWidth(boundingBox) > CGRectGetHeight(boundingBox)) {
tr = CGAffineTransformScale(tr, CGRectGetWidth(boundingBox) / CGRectGetHeight(boundingBox), 1);
} else {
tr = CGAffineTransformScale(tr, 1.f, CGRectGetHeight(boundingBox) / CGRectGetWidth(boundingBox));
}
tr = CGAffineTransformTranslate(tr, -gradientStartPoint.x, -gradientStartPoint.y);
selfTransform = CGAffineTransformConcat(tr, selfTransform);
}
// transform the context
CGContextConcatCTM(ctx, selfTransform);
// draw the gradient
CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawRadialGradient(ctx, self.CGGradient,
gradientEndPoint, 0,
gradientStartPoint,
radius, options);
#ifdef IJSVG_DEBUG_GRADIENTS
[self _debugStart:gradientStartPoint
end:gradientEndPoint
context:ctx];
#endif
}
@end
@@ -1,42 +0,0 @@
//
// IJSVGCommandParser.h
// IJSVG
//
// Created by Curtis Hard on 23/12/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#include <xlocale.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, IJSVGPathDataSequence) {
kIJSVGPathDataSequenceTypeFloat,
kIJSVGPathDataSequenceTypeFlag
};
static NSUInteger const IJSVG_STREAM_FLOAT_BLOCK_SIZE = 50;
static NSUInteger const IJSVG_STREAM_CHAR_BLOCK_SIZE = 20;
typedef struct {
CGFloat* floatBuffer;
NSInteger floatCount;
char* charBuffer;
NSInteger charCount;
} IJSVGPathDataStream;
@interface IJSVGCommandParser : NSObject
IJSVGPathDataStream* IJSVGPathDataStreamCreateDefault(void);
IJSVGPathDataStream* IJSVGPathDataStreamCreate(NSUInteger floatCount, NSUInteger charCount);
void IJSVGPathDataStreamRelease(IJSVGPathDataStream* buffer);
IJSVGPathDataSequence* IJSVGPathDataSequenceCreateWithType(IJSVGPathDataSequence type, NSInteger length);
CGFloat* _Nullable IJSVGParsePathDataStreamSequence(const char* commandChars, NSInteger commandCharLength,
IJSVGPathDataStream* dataStream, IJSVGPathDataSequence* _Nullable sequence,
NSInteger commandLength, NSInteger* _Nullable commandsFound);
@end
NS_ASSUME_NONNULL_END
@@ -1,249 +0,0 @@
//
// IJSVGCommandParser.m
// IJSVG
//
// Created by Curtis Hard on 23/12/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandParser.h"
@implementation IJSVGCommandParser
#define VALID_DIGIT(c) ((c ^ '0') <= 9)
IJSVGPathDataSequence* IJSVGPathDataSequenceCreateWithType(IJSVGPathDataSequence type, NSInteger length)
{
size_t size = sizeof(IJSVGPathDataSequence) * length;
IJSVGPathDataSequence* sequence = (IJSVGPathDataSequence*)malloc(size);
memset(sequence, (int)type, size);
return sequence;
};
// Datastreams work by setting up one stream of bits/memory per SVG
// so that each SVG has a reusable memory block to read and parse paths into.
// As its all linear and one SVG per thread, this saves alot of memory allocation
// calls as we simple can just reuse the buffer that already exists - this also
// allows us to specify the default allocation size, so when parsing viewBox we
// can simply allocate (4*sizeof(CGFloat)) instead of the default 50 slots
IJSVGPathDataStream* IJSVGPathDataStreamCreateDefault(void)
{
return IJSVGPathDataStreamCreate(IJSVG_STREAM_FLOAT_BLOCK_SIZE,
IJSVG_STREAM_CHAR_BLOCK_SIZE);
}
IJSVGPathDataStream* IJSVGPathDataStreamCreate(NSUInteger floatCount, NSUInteger charCount)
{
floatCount = floatCount ?: IJSVG_STREAM_FLOAT_BLOCK_SIZE;
charCount = charCount ?: IJSVG_STREAM_CHAR_BLOCK_SIZE;
IJSVGPathDataStream* buffer = (IJSVGPathDataStream*)malloc(sizeof(IJSVGPathDataStream));
buffer->floatBuffer = (CGFloat*)malloc(sizeof(CGFloat) * floatCount);
buffer->floatCount = floatCount;
buffer->charBuffer = (char*)calloc(sizeof(char), charCount);
buffer->charCount = charCount;
return buffer;
}
void IJSVGPathDataStreamRelease(IJSVGPathDataStream* buffer)
{
free(buffer->charBuffer);
free(buffer->floatBuffer);
free(buffer);
};
CGFloat* _Nullable IJSVGParsePathDataStreamSequence(const char* commandChars, NSInteger commandCharLength,
IJSVGPathDataStream* dataStream, IJSVGPathDataSequence* _Nullable sequence,
NSInteger commandLength, NSInteger* _Nullable commandsFound)
{
// if no command length, its completely pointless function,
// so just return null and set commandsFound to 0, if we dont
// we get a arithmetic error later on due to zero
if (commandLength == 0) {
*commandsFound = 0;
return NULL;
}
// default memory size for the float
NSInteger i = 0;
NSInteger counter = 0;
const char* cString = commandChars;
const char* validChars = "+-.";
// this is much faster then doing strlen as it doesnt need
// to compute the length
NSInteger sLength = commandCharLength;
NSInteger sLengthMinusOne = sLength - 1;
bool isDecimal = false;
int bufferCount = 0;
while (i < sLength) {
char currentChar = *cString++;
// work out next char
char nextChar = (char)0;
if (i < sLengthMinusOne) {
nextChar = *cString++;
cString--;
}
// check for validator
bool isE = (currentChar | ('E' ^ 'e')) == 'e';
bool isValid = VALID_DIGIT(currentChar) || isE || strchr(validChars, currentChar) != NULL;
// in order to work out the split, its either because the next char is
// a hyphen or a plus, or next char is a decimal and the current number is a decimal
bool nIsSign = nextChar == '-' || nextChar == '+';
bool wantsEnd = nIsSign || (nextChar == '.' && isDecimal);
// work our what the sequence is...
IJSVGPathDataSequence seq = kIJSVGPathDataSequenceTypeFloat;
if (sequence != NULL) {
seq = sequence[counter % commandLength];
}
// is a flag, consists of one value
// if its invalid, make sure we free the memory
// and return null - or hell breaks lose
if (isValid == YES && seq == kIJSVGPathDataSequenceTypeFlag) {
if (bufferCount != 0 || (currentChar != '0' && currentChar != '1')) {
return NULL;
}
wantsEnd = YES;
}
// could be a float like 5.334e-5 so dont break on the hypen
if (wantsEnd && isE && nIsSign) {
wantsEnd = false;
}
// make sure its a valid string
if (isValid == YES) {
// alloc the buffer if needed
if ((bufferCount + 1) == dataStream->charCount) {
// realloc the buffer, incase the string is overflowing the
// allocated memory
dataStream->charCount += IJSVG_STREAM_CHAR_BLOCK_SIZE;
dataStream->charBuffer = (char*)realloc(dataStream->charBuffer,
sizeof(char) * dataStream->charCount);
}
// set the actual char against it
if (currentChar == '.') {
isDecimal = true;
}
dataStream->charBuffer[bufferCount++] = currentChar;
} else {
// if its an invalid char, just stop it
wantsEnd = true;
}
// is at end of string, or wants to be stopped
// buffer has to actually exist or its completly
// useless and will cause a crash
if (bufferCount != 0 && (wantsEnd || i == sLengthMinusOne)) {
// make sure there is enough room in the float pool
if ((counter + 1) == dataStream->floatCount) {
dataStream->floatCount += IJSVG_STREAM_FLOAT_BLOCK_SIZE;
dataStream->floatBuffer = (CGFloat*)realloc(dataStream->floatBuffer,
sizeof(CGFloat) * dataStream->floatCount);
}
// add the float - for performance reasons, we can simply set the
// null value of the end of the string instead of nulling out
// with memset \0 - huzzah!
dataStream->charBuffer[bufferCount] = '\0';
dataStream->floatBuffer[counter++] = IJSVGParseFloat(dataStream->charBuffer);
// reset
isDecimal = false;
bufferCount = 0;
}
i++;
}
// set commands found - only if there is one
if (commandsFound != NULL) {
*commandsFound = (NSInteger)round(counter / commandLength);
}
// allocate the new buffer from memory
CGFloat* floats = (CGFloat*)malloc(sizeof(CGFloat) * counter);
memcpy(floats, dataStream->floatBuffer, counter * sizeof(CGFloat));
// return the floats just set into the memory
return floats;
}
// this method is finely tuned to just handle the buffer
// that IJSVGParsePathDataSequence produces for each float
// it does not look or skip white space as the previous method
// handles this for us
// inspired and modified from http://www.leapsecond.com/tools/fast_atof.c
CGFloat IJSVGParseFloat(char* buffer)
{
int fraction;
double sign, value, scale;
// work out a sign, if any, might not be, who knows
sign = 1.f;
if (*buffer == '-') {
sign = -1.f;
buffer += 1;
} else if (*buffer == '+') {
buffer += 1;
}
// get numbers before decimal point or exponent
for (value = 0.f; VALID_DIGIT(*buffer); buffer += 1) {
value = value * 10.f + (*buffer - '0');
}
// get digits after decimal point
if (*buffer == '.') {
double pow10 = 10.f;
buffer += 1;
while (VALID_DIGIT(*buffer)) {
value += (*buffer - '0') / pow10;
pow10 *= 10.f;
buffer += 1;
}
}
// handle exponent
fraction = 0;
scale = 1.f;
if ((*buffer | ('E' ^ 'e')) == 'e') {
unsigned int exponent;
buffer += 1;
if (*buffer == '-') {
fraction = 1;
buffer += 1;
} else if (*buffer == '+') {
buffer += 1;
}
for (exponent = 0; VALID_DIGIT(*buffer); buffer += 1) {
exponent = exponent * 10 + (*buffer - '0');
}
if (exponent > 308) {
exponent = 308;
}
while (exponent >= 50) {
scale *= 1E50;
exponent -= 50;
}
while (exponent >= 8) {
scale *= 1E8;
exponent -= 8;
}
while (exponent > 0) {
scale *= 10.f;
exponent -= 1;
}
}
// make sure we cast this to a CGFloat before return
return (CGFloat)(sign * (fraction ? (value / scale) : (value * scale)));
}
@end
@@ -1,137 +0,0 @@
//
// IJSVGParser.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColor.h>
#import <IJSVG/IJSVGCommand.h>
#import <IJSVG/IJSVGDef.h>
#import <IJSVG/IJSVGError.h>
#import <IJSVG/IJSVGForeignObject.h>
#import <IJSVG/IJSVGGroup.h>
#import <IJSVG/IJSVGImage.h>
#import <IJSVG/IJSVGLinearGradient.h>
#import <IJSVG/IJSVGPath.h>
#import <IJSVG/IJSVGPattern.h>
#import <IJSVG/IJSVGRadialGradient.h>
#import <IJSVG/IJSVGStyleSheet.h>
#import <IJSVG/IJSVGText.h>
#import <IJSVG/IJSVGTransform.h>
#import <IJSVG/IJSVGUnitRect.h>
#import <IJSVG/IJSVGUtils.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
extern NSString* const IJSVGAttributeViewBox;
extern NSString* const IJSVGAttributeID;
extern NSString* const IJSVGAttributeClass;
extern NSString* const IJSVGAttributeX;
extern NSString* const IJSVGAttributeY;
extern NSString* const IJSVGAttributeWidth;
extern NSString* const IJSVGAttributeHeight;
extern NSString* const IJSVGAttributeOpacity;
extern NSString* const IJSVGAttributeStrokeOpacity;
extern NSString* const IJSVGAttributeStrokeWidth;
extern NSString* const IJSVGAttributeStrokeDashOffset;
extern NSString* const IJSVGAttributeFillOpacity;
extern NSString* const IJSVGAttributeClipPath;
extern NSString* const IJSVGAttributeMask;
extern NSString* const IJSVGAttributeGradientUnits;
extern NSString* const IJSVGAttributeMaskUnits;
extern NSString* const IJSVGAttributeMaskContentUnits;
extern NSString* const IJSVGAttributeTransform;
extern NSString* const IJSVGAttributeGradientTransform;
extern NSString* const IJSVGAttributeUnicode;
extern NSString* const IJSVGAttributeStrokeLineCap;
extern NSString* const IJSVGAttributeLineJoin;
extern NSString* const IJSVGAttributeStroke;
extern NSString* const IJSVGAttributeStrokeDashArray;
extern NSString* const IJSVGAttributeFill;
extern NSString* const IJSVGAttributeFillRule;
extern NSString* const IJSVGAttributeBlendMode;
extern NSString* const IJSVGAttributeDisplay;
extern NSString* const IJSVGAttributeStyle;
extern NSString* const IJSVGAttributeD;
extern NSString* const IJSVGAttributeXLink;
extern NSString* const IJSVGAttributeX1;
extern NSString* const IJSVGAttributeX2;
extern NSString* const IJSVGAttributeY1;
extern NSString* const IJSVGAttributeY2;
extern NSString* const IJSVGAttributeRX;
extern NSString* const IJSVGAttributeRY;
extern NSString* const IJSVGAttributeCX;
extern NSString* const IJSVGAttributeCY;
extern NSString* const IJSVGAttributeR;
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;
@protocol IJSVGParserDelegate <NSObject>
@optional
- (BOOL)svgParser:(IJSVGParser*)svg
shouldHandleForeignObject:(IJSVGForeignObject*)foreignObject;
- (void)svgParser:(IJSVGParser*)svg
handleForeignObject:(IJSVGForeignObject*)foreignObject
document:(NSXMLDocument*)document;
- (void)svgParser:(IJSVGParser*)svg
foundSubSVG:(IJSVG*)subSVG
withSVGString:(NSString*)string;
@end
@interface IJSVGParser : IJSVGGroup {
@private
id<IJSVGParserDelegate> _delegate;
NSXMLDocument* _document;
NSMutableArray<IJSVGPath*>* _glyphs;
IJSVGStyleSheet* _styleSheet;
NSMutableDictionary<NSString*, NSXMLElement*>* _defNodes;
NSMutableDictionary<NSString*, NSXMLElement*>* _baseDefNodes;
NSMutableArray<IJSVG*>* _svgs;
struct {
unsigned int shouldHandleForeignObject : 1;
unsigned int handleForeignObject : 1;
unsigned int handleSubSVG : 1;
} _respondsTo;
IJSVGPathDataStream* _commandDataStream;
}
@property (nonatomic, readonly) NSRect viewBox;
@property (nonatomic, readonly) IJSVGUnitSize* intrinsicSize;
+ (BOOL)isDataSVG:(NSData*)data;
- (id)initWithSVGString:(NSString*)string
error:(NSError**)error
delegate:(id<IJSVGParserDelegate>)delegate;
- (id)initWithFileURL:(NSURL*)aURL
error:(NSError**)error
delegate:(id<IJSVGParserDelegate>)delegate;
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL;
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL
delegate:(id<IJSVGParserDelegate>)delegate;
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL
error:(NSError**)error
delegate:(id<IJSVGParserDelegate>)delegate;
- (NSSize)size;
- (BOOL)isFont;
- (NSArray*)glyphs;
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive;
@end
File diff suppressed because it is too large Load Diff
@@ -1,23 +0,0 @@
//
// IJSVGLayerTree.h
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <IJSVG/IJSVGRenderingStyle.h>
#import <QuartzCore/QuartzCore.h>
@class IJSVGLayer;
@interface IJSVGLayerTree : NSObject {
}
@property (nonatomic, assign) CGRect viewBox;
@property (nonatomic, retain) IJSVGRenderingStyle* style;
- (IJSVGLayer*)layerForNode:(IJSVGNode*)node;
@end
@@ -1,732 +0,0 @@
//
// IJSVGLayerTree.m
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGGradient.h"
#import "IJSVGGradientLayer.h"
#import "IJSVGGroup.h"
#import "IJSVGGroupLayer.h"
#import "IJSVGImage.h"
#import "IJSVGImageLayer.h"
#import "IJSVGLayer.h"
#import "IJSVGLayerTree.h"
#import "IJSVGPath.h"
#import "IJSVGPattern.h"
#import "IJSVGPatternLayer.h"
#import "IJSVGShapeLayer.h"
#import "IJSVGStrokeLayer.h"
#import "IJSVGText.h"
#import "IJSVGTransform.h"
#import "IJSVGUtils.h"
@implementation IJSVGLayerTree
@synthesize style = _style;
- (void)dealloc
{
(void)([_style release]), _style = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
}
return self;
}
- (IJSVGLayer*)layerForNode:(IJSVGNode*)node
{
IJSVGLayer* layer = nil;
// is there a sub SVG?
if ([node isKindOfClass:[IJSVGPath class]]) {
// path
layer = [self layerForPath:(IJSVGPath*)node];
} else if ([node isKindOfClass:[IJSVGGroup class]]) {
// group
layer = [self layerForGroup:(IJSVGGroup*)node];
} else if ([node isKindOfClass:[IJSVGImage class]]) {
// image
layer = [self layerForImage:(IJSVGImage*)node];
}
[self applyDefaultsToLayer:layer fromNode:node];
// create the new layer
layer = [self applyTransforms:node.transforms
toLayer:layer
fromNode:node];
return layer;
}
- (IJSVGLayer*)applyTransforms:(NSArray<IJSVGTransform*>*)transforms
toLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
// any x and y?
CGRect frame = layer.bounds;
CGFloat x = [node.x computeValue:frame.size.width];
CGFloat y = [node.y computeValue:frame.size.height];
// no need to do anything if no transform, or x or y == 0
if (transforms.count == 0 && x == 0.f && y == 0.f) {
return layer;
}
// simply cascade all the transforms onto the identity
CGAffineTransform identity = CGAffineTransformIdentity;
if (x != 0.f || y != 0.f) {
identity = CGAffineTransformTranslate(identity, x, y);
}
// this used to be done with each transform being added to its own
// group layer, but we can simply use one and then apply
// the transforms in reverse order, has same outcome with less memory
IJSVGGroupLayer* parentLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
for(IJSVGTransform* transform in transforms.reverseObjectEnumerator) {
identity = CGAffineTransformConcat(identity, transform.CGAffineTransform);
}
parentLayer.affineTransform = identity;
[parentLayer addSublayer:layer];
return parentLayer;
}
- (void)applyDefaultsToLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
CGFloat opacity = node.opacity.value;
if(opacity != 1.f) {
layer.opacity = opacity;
}
// setup the blending mode
if (node.blendMode != IJSVGBlendModeNormal) {
layer.blendingMode = (CGBlendMode)node.blendMode;
}
// display?
if (node.shouldRender == NO) {
layer.hidden = YES;
}
}
- (IJSVGLayer*)layerForImage:(IJSVGImage*)image
{
IJSVGImageLayer* layer = [[[IJSVGImageLayer alloc] initWithCGImage:image.CGImage] autorelease];
layer.affineTransform = CGAffineTransformConcat(layer.affineTransform,
CGAffineTransformMakeScale(1.f, -1.f));
// make sure we set the width and height correctly,
// as this may not be exactly the same as the size of the
// given image
CGRect frame = layer.frame;
frame.size.width = image.width.value;
frame.size.height = image.height.value;
layer.frame = frame;
return layer;
}
- (IJSVGLayer*)layerForGroup:(IJSVGGroup*)group
{
// grab the sub layer tree from the SVG
if (group.svg != nil) {
return [self layerForGroup:group.svg.rootNode];
}
IJSVGGroupLayer* groupLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
for (IJSVGNode* node in group.childNodes) {
[groupLayer addSublayer:[self layerForNode:node]];
}
groupLayer.frame = (CGRect) {
.origin = CGPointZero,
.size = (CGSize) {
.width = group.width.value,
.height = group.height.value
}
};
// mask it - forgot groups can have masks too, doh! simple
// enough to apply though, recursion ftw!
[self maskLayer:groupLayer
fromNode:group];
return groupLayer;
}
- (CGRect)correctedBounds:(CGRect)bounds
{
if (bounds.origin.x >= INFINITY) {
bounds.origin.x = 0.f;
}
if (bounds.origin.y >= INFINITY) {
bounds.origin.y = 0.f;
}
if (bounds.size.width >= INFINITY) {
bounds.size.width = 0.f;
}
if (bounds.size.height >= INFINITY) {
bounds.size.height = 0.f;
}
return bounds;
}
- (IJSVGShapeLayer*)basicLayerForPath:(IJSVGPath*)path
originalBoundingBox:(CGRect*)originalBoundingBox
{
// setup path and layer
IJSVGShapeLayer* layer = [[[IJSVGShapeLayer alloc] init] autorelease];
layer.primitiveType = path.primitiveType;
CGPathRef introPath = path.path;
*originalBoundingBox = CGRectIntegral(CGPathGetBoundingBox(introPath));
layer.originalPathOrigin = (*originalBoundingBox).origin;
CGRect bounds = [self correctedBounds:*originalBoundingBox];
// zero back the path
CGAffineTransform trans = CGAffineTransformMakeTranslation(-bounds.origin.x,
-bounds.origin.y);
CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(introPath, &trans);
layer.path = transformedPath;
// clean up path memory
CGPathRelease(transformedPath);
// set the bounds
layer.frame = CGRectIntegral(bounds);
// basic fill color and rule
layer.fillColor = nil;
layer.fillRule = [self fillRule:path.windingRule];
return layer;
}
- (IJSVGShapeLayer*)layerMaskFromLayer:(CAShapeLayer*)layer
fromNode:(IJSVGNode*)node
{
IJSVGShapeLayer* mask = [[[IJSVGShapeLayer alloc] init] autorelease];
mask.fillColor = [NSColor blackColor].CGColor;
mask.path = layer.path;
return mask;
}
- (CGAffineTransform)absoluteTransform:(IJSVGNode*)node
{
CGAffineTransform parentAbsoluteTransform = CGAffineTransformIdentity;
IJSVGNode* intermediateNode = node.intermediateParentNode;
IJSVGNode* parentSVGNode = node;
while ((parentSVGNode = parentSVGNode.parentNode) != nil) {
if (node == intermediateNode) {
continue;
}
parentAbsoluteTransform = [self absoluteTransform:parentSVGNode];
}
return CGAffineTransformConcat(IJSVGConcatTransforms(node.transforms),
parentAbsoluteTransform);
}
- (IJSVGLayer*)layerForPath:(IJSVGPath*)path
{
// grab the basic shape layer
CGRect originalShapeBounds;
IJSVGShapeLayer* layer = [self basicLayerForPath:path
originalBoundingBox:&originalShapeBounds];
BOOL hasStroke = (path.strokeColor != nil || path.strokePattern != nil || path.strokeGradient != nil);
// any gradient?
if (_style.fillColor == nil && path.fillGradient != nil) {
// create the gradient
IJSVGGradientLayer* gradLayer = [self gradientLayerForLayer:layer
gradient:path.fillGradient
fromNode:path
objectRect:originalShapeBounds
shouldMask:YES];
// add the gradient and set it against the layer
[layer addSublayer:gradLayer];
layer.gradientFillLayer = gradLayer;
} else if (_style.fillColor == nil && path.fillPattern != nil) {
// create the pattern, this is actually not as easy as it may seem
IJSVGPatternLayer* patternLayer = [self patternLayerForLayer:layer
pattern:path.fillPattern
fromNode:path];
// add it
[layer addSublayer:patternLayer];
// apply offsets
[self applyOffsetsToLayer:patternLayer
fromNode:path.fillPattern];
layer.patternFillLayer = patternLayer;
} else {
// only use the global if its set and the current colors
// alpha channel is not 0.f, otherwise its a blank clear color,
// aka, not filled in
NSColor* fColor = path.fillColor;
BOOL hasColor = (fColor.alphaComponent == 0.f || fColor == nil) == NO;
BOOL hasFill = path.fillPattern != nil || path.fillGradient != nil;
// is there an overriding style in the sheet?
if (_style.fillColor && (hasFill || hasColor || fColor == nil)) {
fColor = _style.fillColor;
}
// if there is a color, change the opacity if required
if (fColor != nil && path.fillOpacity.value != 1.f) {
fColor = [IJSVGColor changeAlphaOnColor:fColor
to:path.fillOpacity.value];
}
// anything changed by user?
fColor = [_style.colorList proposedColorForColor:fColor];
// just set the color
if (fColor != nil) {
layer.fillColor = fColor.CGColor;
} else {
// use default color
NSColor* defColor = [IJSVGColor computeColorSpace:NSColor.blackColor];
if (path.fillOpacity.value != 1.f) {
defColor = [IJSVGColor changeAlphaOnColor:defColor
to:path.fillOpacity.value];
}
// work out if anything was changed by user
NSColor* proposedColor = [_style.colorList proposedColorForColor:defColor];
layer.fillColor = proposedColor.CGColor;
}
}
// stroke it
if (hasStroke == YES) {
// load the stroke layer
IJSVGStrokeLayer* strokeLayer = [self strokeLayer:layer
fromNode:path];
// reset the node
BOOL moveStrokeLayer = NO;
if (_style.strokeColor == nil && path.strokeGradient != nil) {
// force reset of the mask colour as we need to use the stroke layer
// as the mask for the stroke gradient
strokeLayer.strokeColor = [IJSVGColor computeColorSpace:NSColor.blackColor].CGColor;
// create the gradient
IJSVGGradientLayer* gradLayer = [self gradientStrokeLayerForLayer:layer
gradient:path.strokeGradient
fromNode:path
objectRect:originalShapeBounds];
moveStrokeLayer = YES;
gradLayer.mask = strokeLayer;
gradLayer.opacity = strokeLayer.opacity;
// add it
[layer addSublayer:gradLayer];
layer.strokeLayer = strokeLayer;
layer.gradientStrokeLayer = gradLayer;
} else if (_style.strokeColor == nil && path.strokePattern != nil) {
// force reset of the mask
strokeLayer.strokeColor = [IJSVGColor computeColorSpace:NSColor.blackColor].CGColor;
// create the pattern
IJSVGPatternLayer* patternLayer = [self patternStrokeLayerForLayer:layer
pattern:path.strokePattern
fromNode:path];
// set the mask for it
moveStrokeLayer = YES;
patternLayer.mask = strokeLayer;
patternLayer.opacity = strokeLayer.opacity;
// add it
[layer addSublayer:patternLayer];
layer.strokeLayer = strokeLayer;
layer.patternStrokeLayer = (IJSVGPatternLayer*)patternLayer;
} else {
// just add the coloured layer
[layer addSublayer:strokeLayer];
layer.strokeLayer = strokeLayer;
}
// if we required to move the stroke layer
// then move it in based on half of what the stroke
// width is, as strokes are draw on the center
if (moveStrokeLayer) {
CGFloat layerStrokeWidth = strokeLayer.lineWidth;
CGRect rect = strokeLayer.frame;
rect.origin.x += (layerStrokeWidth * .5f);
rect.origin.y += (layerStrokeWidth * .5f);
strokeLayer.frame = rect;
}
}
// apply masking
[self maskLayer:(IJSVGLayer*)layer
fromNode:path];
return (IJSVGLayer*)layer;
}
- (CGRect)correctBounds:(CGRect)bounds
forStrokedPath:(IJSVGNode*)path
{
// minus half the stroke width from x and y
// plus the stroke width to width and height
CGFloat val = path.strokeWidth.value;
bounds.origin.x -= (val * .5f);
bounds.origin.y -= (val * .5f);
bounds.size.width += val;
bounds.size.height += val;
return bounds;
}
- (IJSVGGradientLayer*)gradientStrokeLayerForLayer:(IJSVGShapeLayer*)layer
gradient:(IJSVGGradient*)gradient
fromNode:(IJSVGNode*)path
objectRect:(CGRect)objectRect
{
// the gradient drawing layer
IJSVGGradientLayer* gradLayer = [self gradientLayerForLayer:layer
gradient:gradient
fromNode:path
objectRect:objectRect
shouldMask:NO];
// set the bounds
CGRect bounds = CGPathGetBoundingBox(layer.path);
bounds = [self correctBounds:bounds forStrokedPath:path];
gradLayer.frame = bounds;
return gradLayer;
}
- (IJSVGGradientLayer*)gradientLayerForLayer:(IJSVGShapeLayer*)layer
gradient:(IJSVGGradient*)gradient
fromNode:(IJSVGNode*)path
objectRect:(CGRect)objectRect
shouldMask:(BOOL)shouldMask
{
// the gradient drawing layer
gradient.colorList = _style.colorList;
IJSVGGradientLayer* gradLayer = [[[IJSVGGradientLayer alloc] init] autorelease];
gradLayer.viewBox = _viewBox;
gradLayer.frame = layer.bounds;
gradLayer.gradient = gradient;
gradLayer.absoluteTransform = [self absoluteTransform:path];
gradLayer.objectRect = CGRectApplyAffineTransform(objectRect,
gradLayer.absoluteTransform);
if (shouldMask == YES) {
// add the mask
IJSVGShapeLayer* mask = [self layerMaskFromLayer:layer
fromNode:path];
gradLayer.mask = mask;
}
// is there a fill opacity?
if (path.fillOpacity.value != 0.f) {
gradLayer.opacity = path.fillOpacity.value;
}
gradLayer.masksToBounds = YES;
return gradLayer;
}
- (IJSVGPatternLayer*)patternStrokeLayerForLayer:(IJSVGShapeLayer*)layer
pattern:(IJSVGPattern*)pattern
fromNode:(IJSVGNode*)path
{
// create the pattern, this is actually not as easy as it may seem
IJSVGPatternLayer* patternLayer = [[[IJSVGPatternLayer alloc] init] autorelease];
patternLayer.patternNode = pattern;
patternLayer.pattern = [self layerForNode:pattern];
// is there a fill opacity?
if (path.fillOpacity.value != 0.f) {
patternLayer.opacity = path.fillOpacity.value;
}
// set the bounds
CGRect bounds = CGPathGetBoundingBox(layer.path);
bounds = [self correctBounds:bounds forStrokedPath:path];
patternLayer.frame = bounds;
patternLayer.masksToBounds = YES;
// display
[patternLayer setNeedsDisplay];
return patternLayer;
}
- (IJSVGPatternLayer*)patternLayerForLayer:(IJSVGShapeLayer*)layer
pattern:(IJSVGPattern*)pattern
fromNode:(IJSVGNode*)path
{
// create the pattern, this is actually not as easy as it may seem
IJSVGPatternLayer* patternLayer = [[[IJSVGPatternLayer alloc] init] autorelease];
patternLayer.patternNode = pattern;
patternLayer.pattern = [self layerForNode:pattern];
patternLayer.frame = CGPathGetBoundingBox(layer.path);
// is there a fill opacity?
if (path.fillOpacity.value != 0.f) {
patternLayer.opacity = path.fillOpacity.value;
}
// add the mask
patternLayer.mask = [self layerMaskFromLayer:layer
fromNode:path];
// display
[patternLayer setNeedsDisplay];
patternLayer.masksToBounds = YES;
return patternLayer;
}
- (void)applyOffsetsToLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
// make sure it has a superlayer
if (layer.superlayer == nil) {
return;
}
// grab the x and y
IJSVGUnitLength* x = nil;
IJSVGUnitLength* y = nil;
// sort out the rect
CGRect rect = layer.superlayer.frame;
CGRect frame = layer.frame;
// x
if ((x = node.x) != nil) {
frame.origin.x = [x computeValue:rect.size.width];
}
// y
if ((y = node.y) != nil) {
frame.origin.y = [y computeValue:rect.size.height];
}
// update the frame
if (CGRectEqualToRect(frame, layer.frame) == NO) {
layer.frame = frame;
}
}
- (IJSVGStrokeLayer*)strokeLayer:(IJSVGShapeLayer*)layer
fromNode:(IJSVGPath*)path
{
// same as fill, dont use global if the alpha is 0.f, but do use it
// if there is a pattern or gradient
NSColor* sColor = path.strokeColor;
if (_style.strokeColor != nil && ((sColor != nil && sColor.alphaComponent != 0.f) || path.strokePattern != nil || path.strokeGradient != nil)) {
sColor = _style.strokeColor;
}
sColor = [_style.colorList proposedColorForColor:sColor];
// stroke layer
IJSVGStrokeLayer* strokeLayer = [[[IJSVGStrokeLayer alloc] init] autorelease];
strokeLayer.path = layer.path;
strokeLayer.fillColor = nil;
strokeLayer.strokeColor = sColor.CGColor;
CGFloat lineWidth = 1.f;
if (_style.lineWidth != IJSVGInheritedFloatValue) {
lineWidth = _style.lineWidth;
} else {
lineWidth = path.strokeWidth.value;
}
// work out line styles
IJSVGLineCapStyle lCapStyle;
IJSVGLineJoinStyle lJoinStyle;
// forced cap style
if (_style.lineCapStyle != IJSVGLineCapStyleNone) {
lCapStyle = _style.lineCapStyle;
} else {
lCapStyle = path.lineCapStyle;
}
// forced join style
if (_style.lineJoinStyle != IJSVGLineJoinStyleNone) {
lJoinStyle = _style.lineJoinStyle;
} else {
lJoinStyle = path.lineJoinStyle;
}
// line styles
strokeLayer.lineWidth = lineWidth;
strokeLayer.lineCap = [self lineCap:lCapStyle];
strokeLayer.lineJoin = [self lineJoin:lJoinStyle];
CGFloat strokeOpacity = 1.f;
if (path.strokeOpacity.value != 0.f) {
strokeOpacity = path.strokeOpacity.value;
}
strokeLayer.opacity = strokeOpacity;
// dashing
strokeLayer.lineDashPhase = path.strokeDashOffset.value;
if(path.strokeDashArrayCount != 0.f) {
strokeLayer.lineDashPattern = [self lineDashPattern:path];
}
return strokeLayer;
}
- (void)maskLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
// any clippath?
if (node.clipPath != nil || node.mask != nil) {
IJSVGGroupLayer* maskLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
// add clip mask
if (node.clipPath != nil && node.clipPath.overflowVisibility == IJSVGOverflowVisibilityHidden) {
IJSVGLayer* clip = [self layerForNode:node.clipPath];
// adjust the frame
if (node.clipPath.units == IJSVGUnitObjectBoundingBox) {
[self adjustLayer:clip
toParentLayerFrame:layer];
}
// add the layer
[maskLayer addSublayer:clip];
}
// add the actual mask
if (node.mask != nil && node.mask.overflowVisibility == IJSVGOverflowVisibilityHidden) {
IJSVGLayer* mask = [self layerForNode:node.mask];
// only move if bounding box
if (node.mask.units == IJSVGUnitObjectBoundingBox) {
[self adjustLayer:mask
toParentLayerFrame:layer];
}
// add the layer
[maskLayer addSublayer:mask];
}
// add the mask
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;
}
}
}
- (void)_recursiveColorLayersFromLayer:(IJSVGLayer*)layer
withColor:(CGColorRef)color
{
if ([layer isKindOfClass:[IJSVGShapeLayer class]]) {
// has a proper fill method
for (IJSVGLayer* c in layer.sublayers) {
if ([c isKindOfClass:[IJSVGGradientLayer class]] ||
[c isKindOfClass:[IJSVGPatternLayer class]]) {
return;
}
}
// set the fill
IJSVGShapeLayer* l = (IJSVGShapeLayer*)layer;
l.fillColor = color;
} else if ([layer isKindOfClass:[IJSVGGroupLayer class]]) {
// go through its children, assume its a group
for (IJSVGLayer* child in layer.sublayers) {
[self _recursiveColorLayersFromLayer:child
withColor:color];
}
}
}
- (void)adjustLayer:(IJSVGLayer*)childLayer
toParentLayerFrame:(IJSVGLayer*)parent
{
childLayer.frame = (CGRect){
.size = childLayer.frame.size,
.origin = CGPointMake((childLayer.frame.origin.x - parent.frame.origin.x),
(childLayer.frame.origin.y - parent.frame.origin.y))
};
}
- (NSArray<NSNumber*>*)lineDashPattern:(IJSVGNode*)node
{
NSMutableArray* arr = [[[NSMutableArray alloc] initWithCapacity:node.strokeDashArrayCount] autorelease];
for (NSInteger i = 0; i < node.strokeDashArrayCount; i++) {
[arr addObject:@((CGFloat)node.strokeDashArray[i])];
}
return arr;
}
- (NSString*)lineJoin:(IJSVGLineJoinStyle)joinStyle
{
switch (joinStyle) {
default:
case IJSVGLineJoinStyleMiter: {
return kCALineJoinMiter;
}
case IJSVGLineJoinStyleBevel: {
return kCALineJoinBevel;
}
case IJSVGLineJoinStyleRound: {
return kCALineJoinRound;
}
}
}
- (NSString*)lineCap:(IJSVGLineCapStyle)capStyle
{
switch (capStyle) {
default:
case IJSVGLineCapStyleButt: {
return kCALineCapButt;
}
case IJSVGLineCapStyleRound: {
return kCALineCapRound;
}
case IJSVGLineCapStyleSquare: {
return kCALineCapSquare;
}
}
}
- (NSString*)fillRule:(IJSVGWindingRule)rule
{
switch (rule) {
case IJSVGWindingRuleEvenOdd: {
return kCAFillRuleEvenOdd;
}
default: {
return kCAFillRuleNonZero;
}
}
}
@end
@@ -1,21 +0,0 @@
//
// IJSVGRendering.h
// IJSVGExample
//
// Created by Curtis Hard on 14/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef CGFloat (^IJSVGRenderingBackingScaleFactorHelper)(void);
typedef NS_ENUM(NSInteger, IJSVGRenderQuality) {
kIJSVGRenderQualityFullResolution, // slowest to render
kIJSVGRenderQualityOptimized, // best of both worlds
kIJSVGRenderQualityLow // fast rendering
};
@interface IJSVGRendering : NSObject
@end
@@ -1,13 +0,0 @@
//
// IJSVGRendering.m
// IJSVGExample
//
// Created by Curtis Hard on 14/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGRendering.h"
@implementation IJSVGRendering
@end
@@ -1,26 +0,0 @@
//
// IJSVGStyleList.h
// IconJar
//
// Created by Curtis Hard on 09/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColorList.h>
#import <IJSVG/IJSVGNode.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface IJSVGRenderingStyle : NSObject
@property (nonatomic, assign) IJSVGLineCapStyle lineCapStyle;
@property (nonatomic, assign) IJSVGLineJoinStyle lineJoinStyle;
@property (nonatomic, assign) CGFloat lineWidth;
@property (nonatomic, retain) IJSVGColorList* colorList;
@property (nonatomic, retain) NSColor* fillColor;
@property (nonatomic, retain) NSColor* strokeColor;
+ (NSArray<NSString*>*)observableProperties;
@end
@@ -1,43 +0,0 @@
//
// IJSVGStyleList.m
// IconJar
//
// Created by Curtis Hard on 09/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGRenderingStyle.h"
@implementation IJSVGRenderingStyle
- (void)dealloc
{
(void)([_fillColor release]), _fillColor = nil;
(void)([_strokeColor release]), _strokeColor = nil;
(void)([_colorList release]), _colorList = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_lineCapStyle = IJSVGLineCapStyleNone;
_lineJoinStyle = IJSVGLineJoinStyleNone;
_lineWidth = IJSVGInheritedFloatValue;
_colorList = [[IJSVGColorList alloc] init];
}
return self;
}
+ (NSArray<NSString*>*)observableProperties
{
static NSArray* array = nil;
if (array == nil) {
array = @[ @"lineCapStyle", @"lineJoinStyle", @"lineWidth",
@"colorList", @"fillColor", @"strokeColor" ]
.retain;
}
return array;
}
@end
@@ -1,24 +0,0 @@
//
// IJSVGStyleSheetRule.h
// IJSVGExample
//
// Created by Curtis Hard on 16/01/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGStyle.h>
#import <IJSVG/IJSVGStyleSheetSelector.h>
#import <Foundation/Foundation.h>
@class IJSVGNode;
@interface IJSVGStyleSheetRule : NSObject {
}
@property (nonatomic, retain) NSArray* selectors;
@property (nonatomic, retain) IJSVGStyle* style;
- (BOOL)matchesNode:(IJSVGNode*)node
selector:(IJSVGStyleSheetSelector**)matchedSelector;
@end
@@ -1,45 +0,0 @@
//
// IJSVGStyleSheetSelectorRaw.m
// IJSVGExample
//
// Created by Curtis Hard on 16/01/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGStyleSheetSelectorRaw.h"
@implementation IJSVGStyleSheetSelectorRaw
@synthesize classes;
- (void)dealloc
{
(void)([classes release]), classes = nil;
(void)([_identifier release]), _identifier = nil;
(void)([_tag release]), _tag = nil;
(void)([_combinatorString release]), _combinatorString = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
classes = [[NSMutableArray alloc] init];
_combinator = IJSVGStyleSheetSelectorCombinatorDescendant;
_combinatorString = @" ";
}
return self;
}
- (void)addClassName:(NSString*)className
{
[classes addObject:className];
}
- (NSString*)description
{
return [NSString stringWithFormat:@"Combinator: %@, Tag: %@, Classes: %@, Identifier: %@",
_combinatorString, _tag, classes, _identifier];
}
@end
@@ -1,25 +0,0 @@
//
// 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
@@ -1,127 +0,0 @@
//
// 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
@@ -1,31 +0,0 @@
//
// IJSVGTransaction.m
// IconJar
//
// Created by Curtis Hard on 11/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGTransaction.h"
#import <AppKit/AppKit.h>
BOOL IJSVGIsMainThread(void) { return NSThread.isMainThread; };
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 setDisableActions:YES];
[CATransaction lock];
return YES;
};
void IJSVGEndTransaction(void)
{
[CATransaction unlock];
[CATransaction commit];
};
@@ -1,59 +0,0 @@
//
// IJSVGTransform.h
// IconJar
//
// Created by Curtis Hard on 01/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGUtils.h>
#import <Foundation/Foundation.h>
@class IJSVGTransform;
typedef CGFloat (^IJSVGTransformParameterModifier)(NSInteger index, CGFloat value);
typedef void (^IJSVGTransformApplyBlock)(IJSVGTransform* transform);
typedef NS_ENUM(NSInteger, IJSVGTransformCommand) {
IJSVGTransformCommandMatrix,
IJSVGTransformCommandTranslate,
IJSVGTransformCommandTranslateX,
IJSVGTransformCommandTranslateY,
IJSVGTransformCommandScale,
IJSVGTransformCommandRotate,
IJSVGTransformCommandSkewX,
IJSVGTransformCommandSkewY,
IJSVGTransformCommandNotImplemented
};
@interface IJSVGTransform : NSObject {
}
@property (nonatomic, assign) IJSVGTransformCommand command;
@property (nonatomic, assign) CGFloat* parameters;
@property (nonatomic, assign) NSInteger parameterCount;
@property (nonatomic, assign) NSInteger sort;
void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApplyBlock block);
CGAffineTransform IJSVGConcatTransforms(NSArray<IJSVGTransform*>* transforms);
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*>*)transformsForString:(NSString*)string;
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)affineTransform;
+ (NSString*)affineTransformToSVGMatrixString:(CGAffineTransform)transform
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (CGAffineTransform)CGAffineTransform;
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier;
- (CGAffineTransform)stackIdentity:(CGAffineTransform)identity;
- (void)recalculateWithBounds:(CGRect)bounds;
+ (IJSVGTransform*)transformByTranslatingX:(CGFloat)x
y:(CGFloat)y;
+ (IJSVGTransform*)transformByScaleX:(CGFloat)x
y:(CGFloat)y;
@end
@@ -1,611 +0,0 @@
//
// IJSVGTransform.m
// IconJar
//
// Created by Curtis Hard on 01/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGMath.h"
#import "IJSVGTransform.h"
#import "IJSVGParsing.h"
@implementation IJSVGTransform
- (void)dealloc
{
(void)free(_parameters);
[super dealloc];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGTransform* trans = [[self.class alloc] init];
trans.command = _command;
trans.parameters = (CGFloat*)malloc(sizeof(CGFloat) * _parameterCount);
trans.sort = _sort;
trans.parameterCount = _parameterCount;
memcpy(trans.parameters, _parameters, sizeof(CGFloat) * _parameterCount);
return trans;
}
CGAffineTransform IJSVGConcatTransforms(NSArray<IJSVGTransform*>* transforms)
{
__block CGAffineTransform trans = CGAffineTransformIdentity;
IJSVGApplyTransform(transforms, ^(IJSVGTransform* transform) {
trans = CGAffineTransformConcat(trans, transform.CGAffineTransform);
});
return trans;
}
NSString* IJSVGTransformAttributeString(CGAffineTransform transform)
{
return [IJSVGTransform affineTransformToSVGMatrixString:transform];
}
void IJSVGApplyTransform(NSArray<IJSVGTransform*>* transforms, IJSVGTransformApplyBlock block)
{
for (IJSVGTransform* transform in transforms) {
block(transform);
}
};
+ (IJSVGTransform*)transformByTranslatingX:(CGFloat)x
y:(CGFloat)y
{
IJSVGTransform* transform = [[[self alloc] init] autorelease];
transform.command = IJSVGTransformCommandTranslate;
transform.parameterCount = 2;
CGFloat* params = (CGFloat*)malloc(sizeof(CGFloat) * 2);
params[0] = x;
params[1] = y;
transform.parameters = params;
return transform;
}
+ (IJSVGTransform*)transformByScaleX:(CGFloat)x
y:(CGFloat)y
{
IJSVGTransform* transform = [[[self alloc] init] autorelease];
transform.command = IJSVGTransformCommandScale;
transform.parameterCount = 2;
CGFloat* params = (CGFloat*)malloc(sizeof(CGFloat) * 2);
params[0] = x;
params[1] = y;
transform.parameters = params;
return transform;
}
- (void)recalculateWithBounds:(CGRect)bounds
{
CGFloat max = bounds.size.width > bounds.size.height ? bounds.size.width : bounds.size.height;
switch (_command) {
case IJSVGTransformCommandRotate: {
if (_parameterCount == 1) {
return;
}
_parameters[1] = _parameters[1] * max;
_parameters[2] = _parameters[2] * max;
}
default:
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
{
str = str.lowercaseString;
if ([str isEqualToString:@"matrix"])
return IJSVGTransformCommandMatrix;
if ([str isEqualToString:@"translate"])
return IJSVGTransformCommandTranslate;
if ([str isEqualToString:@"translatex"])
return IJSVGTransformCommandTranslateX;
if ([str isEqualToString:@"translatey"])
return IJSVGTransformCommandTranslateY;
if ([str isEqualToString:@"scale"])
return IJSVGTransformCommandScale;
if ([str isEqualToString:@"skewx"])
return IJSVGTransformCommandSkewX;
if ([str isEqualToString:@"skewy"])
return IJSVGTransformCommandSkewY;
if ([str isEqualToString:@"rotate"])
return IJSVGTransformCommandRotate;
return IJSVGTransformCommandNotImplemented;
}
+ (NSInteger)sortForTransformCommand:(IJSVGTransformCommand)command
{
switch (command) {
case IJSVGTransformCommandScale:
return 0;
case IJSVGTransformCommandRotate:
return 1;
case IJSVGTransformCommandMatrix:
return 2;
case IJSVGTransformCommandTranslateX:
case IJSVGTransformCommandTranslateY:
case IJSVGTransformCommandTranslate:
return -1;
default:
return 10;
}
return 10;
}
+ (NSArray<IJSVGTransform*>*)transformsForString:(NSString*)string
{
NSMutableArray<IJSVGTransform*>* transforms = nil;
transforms = [[[NSMutableArray alloc] init] autorelease];
const char* charString = string.UTF8String;
IJSVGParsingStringMethod** methods = NULL;
NSUInteger count = 0;
methods = IJSVGParsingMethodParseString(charString, &count);
for(int i = 0; i < count; i++) {
IJSVGParsingStringMethod* method = methods[i];
IJSVGTransformCommand commandType;
commandType = [self.class commandForCommandCString:method->name];
if(commandType == IJSVGTransformCommandNotImplemented) {
(void)IJSVGParsingStringMethodRelease(method), method = NULL;
continue;
}
// 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;
// add to the list of transforms to return
[transforms addObject:transform];
(void)IJSVGParsingStringMethodRelease(method), method = NULL;
}
(void)free(methods), methods = NULL;
return transforms;
}
- (CGAffineTransform)CGAffineTransform
{
return [self stackIdentity:CGAffineTransformIdentity];
}
- (CGAffineTransform)stackIdentity:(CGAffineTransform)identity
{
switch (_command) {
// translate
case IJSVGTransformCommandTranslate: {
if (_parameterCount == 1) {
return CGAffineTransformTranslate(identity, _parameters[0], 0.f);
}
return CGAffineTransformTranslate(identity, _parameters[0], _parameters[1]);
}
// translateX
case IJSVGTransformCommandTranslateX: {
return CGAffineTransformTranslate(identity, _parameters[0], 0.f);
}
// translateY
case IJSVGTransformCommandTranslateY: {
return CGAffineTransformTranslate(identity, 0.f, _parameters[0]);
}
// rotate
case IJSVGTransformCommandRotate: {
if (_parameterCount == 1) {
return CGAffineTransformRotate(identity, (_parameters[0] / 180) * M_PI);
}
CGFloat p0 = _parameters[0];
CGFloat p1 = _parameters[1];
CGFloat p2 = _parameters[2];
CGFloat angle = p0 * (M_PI / 180.f);
identity = CGAffineTransformTranslate(identity, p1, p2);
identity = CGAffineTransformRotate(identity, angle);
return CGAffineTransformTranslate(identity, -1.f * p1, -1.f * p2);
}
// scale
case IJSVGTransformCommandScale: {
CGFloat p0 = _parameters[0];
if (_parameterCount == 1) {
return CGAffineTransformScale(identity, p0, p0);
}
CGFloat p1 = _parameters[1];
return CGAffineTransformScale(identity, p0, p1);
}
// matrix
case IJSVGTransformCommandMatrix: {
CGFloat p0 = _parameters[0];
CGFloat p1 = _parameters[1];
CGFloat p2 = _parameters[2];
CGFloat p3 = _parameters[3];
CGFloat p4 = _parameters[4];
CGFloat p5 = _parameters[5];
return CGAffineTransformMake(p0, p1, p2, p3, p4, p5);
}
// skewX
case IJSVGTransformCommandSkewX: {
CGFloat degrees = _parameters[0];
CGFloat radians = degrees * M_PI / 180.f;
return CGAffineTransformMake(1.f, 0.f, tan(radians), 1.f, 0.f, 0.f);
}
// skewY
case IJSVGTransformCommandSkewY: {
CGFloat degrees = _parameters[0];
CGFloat radians = degrees * M_PI / 180.f;
return CGAffineTransformMake(1.f, tan(radians), 0.f, 1.f, 0.f, 0.f);
}
case IJSVGTransformCommandNotImplemented: {
return CGAffineTransformIdentity;
}
}
return CGAffineTransformIdentity;
}
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier
{
switch (_command) {
// matrix
case IJSVGTransformCommandMatrix: {
CGFloat p0 = _parameters[0];
CGFloat p1 = _parameters[1];
CGFloat p2 = _parameters[2];
CGFloat p3 = _parameters[3];
CGFloat p4 = _parameters[4];
CGFloat p5 = _parameters[5];
if (modifier != nil) {
p0 = modifier(0, p0);
p1 = modifier(1, p1);
p2 = modifier(2, p2);
p3 = modifier(3, p3);
p4 = modifier(4, p4);
p5 = modifier(5, p5);
}
return CGAffineTransformMake(p0, p1, p2, p3, p4, p5);
}
// translate
case IJSVGTransformCommandTranslate: {
CGFloat p0 = _parameters[0];
if (_parameterCount == 1) {
return CGAffineTransformMakeTranslation(p0, 0);
}
CGFloat p1 = _parameters[1];
if (modifier != nil) {
p0 = modifier(0, p0);
p1 = modifier(1, p1);
}
return CGAffineTransformMakeTranslation(p0, p1);
}
// translateX
case IJSVGTransformCommandTranslateX: {
CGFloat p0 = _parameters[0];
if (modifier != nil) {
p0 = modifier(0, p0);
}
return CGAffineTransformMakeTranslation(p0, 0.f);
}
// translateY
case IJSVGTransformCommandTranslateY: {
CGFloat p0 = _parameters[0];
if (modifier != nil) {
p0 = modifier(0, p0);
}
return CGAffineTransformMakeTranslation(0.f, p0);
}
// scale
case IJSVGTransformCommandScale: {
CGFloat p0 = _parameters[0];
if (_parameterCount == 1) {
return CGAffineTransformMakeScale(p0, p0);
}
CGFloat p1 = _parameters[1];
if (modifier != nil) {
p0 = modifier(0, p0);
p1 = modifier(1, p1);
}
return CGAffineTransformMakeScale(p0, p1);
}
// skewX
case IJSVGTransformCommandSkewX: {
CGFloat degrees = _parameters[0];
if (modifier != nil) {
degrees = modifier(0, degrees);
}
CGFloat radians = degrees * M_PI / 180.f;
return CGAffineTransformMake(1.f, 0.f, tan(radians), 1.f, 0.f, 0.f);
}
// skewY
case IJSVGTransformCommandSkewY: {
CGFloat degrees = _parameters[0];
if (modifier != nil) {
degrees = modifier(0, degrees);
}
CGFloat radians = degrees * M_PI / 180.f;
return CGAffineTransformMake(1.f, tan(radians), 0.f, 1.f, 0.f, 0.f);
}
// rotate
case IJSVGTransformCommandRotate: {
if (_parameterCount == 1) {
return CGAffineTransformMakeRotation((_parameters[0] / 180) * M_PI);
} else {
CGFloat p0 = _parameters[0];
CGFloat p1 = _parameters[1];
CGFloat p2 = _parameters[2];
if (modifier != nil) {
p0 = modifier(0, p0);
p1 = modifier(1, p1);
p2 = modifier(2, p2);
}
CGFloat angle = p0 * (M_PI / 180.f);
CGAffineTransform def = CGAffineTransformIdentity;
def = CGAffineTransformTranslate(def, p1, p2);
def = CGAffineTransformRotate(def, angle);
def = CGAffineTransformTranslate(def, -1.f * p1, -1.f * p2);
return def;
}
break;
}
// do nothing
case IJSVGTransformCommandNotImplemented: {
return CGAffineTransformIdentity;
}
}
return CGAffineTransformIdentity;
}
+ (NSArray<IJSVGTransform*>*)transformsFromAffineTransform:(CGAffineTransform)affineTransform
{
NSString* matrix = [self affineTransformToSVGMatrixString:affineTransform];
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
{
NSArray<NSString*>* numbers = @[
IJSVGShortFloatString(transform.a),
IJSVGShortFloatString(transform.b),
IJSVGShortFloatString(transform.c),
IJSVGShortFloatString(transform.d),
IJSVGShortFloatString(transform.tx),
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
{
return [NSString stringWithFormat:@"%@ %@", [super description],
[self.class affineTransformToSVGMatrixString:self.CGAffineTransform]];
}
@end
@@ -1,55 +0,0 @@
//
// IJSVGUnitLength.h
// IJSVGExample
//
// Created by Curtis Hard on 13/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef struct {
BOOL round;
int precision;
} IJSVGFloatingPointOptions;
typedef NS_ENUM(NSInteger, IJSVGUnitLengthType) {
IJSVGUnitLengthTypeNumber,
IJSVGUnitLengthTypePercentage,
IJSVGUnitLengthTypeCM,
IJSVGUnitLengthTypeMM,
IJSVGUnitLengthTypeIN,
IJSVGUnitLengthTypePT,
IJSVGUnitLengthTypePC,
IJSVGUnitLengthTypePX
};
typedef NS_ENUM(NSInteger, IJSVGUnitType) {
IJSVGUnitUserSpaceOnUse,
IJSVGUnitObjectBoundingBox,
IJSVGUnitInherit
};
@interface IJSVGUnitLength : NSObject
@property (nonatomic, assign) IJSVGUnitLengthType type;
@property (nonatomic, assign) IJSVGUnitLengthType originalType;
@property (nonatomic, assign) CGFloat value;
@property (nonatomic, assign) BOOL inherit;
+ (IJSVGUnitLength*)unitWithFloat:(CGFloat)number;
+ (IJSVGUnitLength*)unitWithFloat:(CGFloat)number
type:(IJSVGUnitLengthType)type;
+ (IJSVGUnitLength*)unitWithPercentageFloat:(CGFloat)number;
+ (IJSVGUnitLength*)unitWithString:(NSString*)string;
+ (IJSVGUnitLength*)unitWithPercentageString:(NSString*)string;
+ (IJSVGUnitLength*)unitWithString:(NSString*)string
fromUnitType:(IJSVGUnitType)units;
- (CGFloat)valueAsPercentage;
- (CGFloat)computeValue:(CGFloat)anotherValue;
- (NSString*)stringValue;
- (NSString*)stringValueWithFloatingPointOptions:(IJSVGFloatingPointOptions)options;
@end
@@ -1,232 +0,0 @@
//
// IJSVGUnitLength.m
// IJSVGExample
//
// Created by Curtis Hard on 13/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGNode.h"
#import "IJSVGUnitLength.h"
#import "IJSVGUtils.h"
@implementation IJSVGUnitLength
+ (IJSVGUnitLength*)unitWithFloat:(CGFloat)number
{
IJSVGUnitLength* unit = [[[self alloc] init] autorelease];
unit.value = number;
unit.type = IJSVGUnitLengthTypeNumber;
return unit;
}
+ (IJSVGUnitLength*)unitWithString:(NSString*)string
fromUnitType:(IJSVGUnitType)units
{
if (units == IJSVGUnitObjectBoundingBox) {
return [self unitWithPercentageString:string];
}
return [self unitWithString:string];
}
+ (IJSVGUnitLength*)unitWithFloat:(CGFloat)number
type:(IJSVGUnitLengthType)type
{
IJSVGUnitLength* unit = [[[self alloc] init] autorelease];
unit.value = number;
unit.type = type;
return unit;
}
+ (IJSVGUnitLength*)unitWithPercentageFloat:(CGFloat)number
{
return [self unitWithFloat:number
type:IJSVGUnitLengthTypePercentage];
}
+ (IJSVGUnitLength*)unitWithPercentageString:(NSString*)string
{
IJSVGUnitLength* unit = [self unitWithString:string];
unit.type = IJSVGUnitLengthTypePercentage;
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
{
// just return noting for inherit, node will deal
// with the rest...hopefully
if(string == 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];
unit.value = floats[0];
unit.type = IJSVGUnitLengthTypeNumber;
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;
}
- (CGFloat)computeValue:(CGFloat)anotherValue
{
if (self.type == IJSVGUnitLengthTypePercentage) {
return ((anotherValue / 100.f) * (_value * 100.f));
}
return self.value;
}
- (CGFloat)valueAsPercentage
{
return self.value / 100;
}
- (NSString*)stringValue
{
if (self.type == IJSVGUnitLengthTypePercentage) {
return [NSString stringWithFormat:@"%@%%",
IJSVGShortFloatString(self.value * 100.f)];
}
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
{
return [NSString stringWithFormat:@"%f%@",
_value, (_value == IJSVGUnitLengthTypePercentage ? @"%" : @"")];
}
@end
@@ -1,17 +0,0 @@
//
// 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
@@ -1,29 +0,0 @@
//
// 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
@@ -1,21 +0,0 @@
//
// 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
@@ -1,29 +0,0 @@
//
// 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
@@ -1,20 +0,0 @@
//
// IJSVGUnitSize.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 IJSVGUnitSize : NSObject
@property (nonatomic, retain) IJSVGUnitLength* width;
@property (nonatomic, retain) IJSVGUnitLength* height;
+ (IJSVGUnitSize*)sizeWithWidth:(IJSVGUnitLength*)width
height:(IJSVGUnitLength*)height;
@end
@@ -1,29 +0,0 @@
//
// IJSVGUnitSize.m
// IJSVG
//
// Created by Curtis Hard on 12/02/2020.
// Copyright © 2020 Curtis Hard. All rights reserved.
//
#import "IJSVGUnitSize.h"
@implementation IJSVGUnitSize
- (void)dealloc
{
(void)[_width release], _width = nil;
(void)[_height release], _height = nil;
[super dealloc];
}
+ (IJSVGUnitSize*)sizeWithWidth:(IJSVGUnitLength*)width
height:(IJSVGUnitLength*)height
{
IJSVGUnitSize* size = [[[self alloc] init] autorelease];
size.width = width;
size.height = height;
return size;
}
@end
@@ -1,80 +0,0 @@
//
// IJSVGUtils.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGCommand.h>
#import <IJSVG/IJSVGGradientUnitLength.h>
#import <IJSVG/IJSVGStringAdditions.h>
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface IJSVGUtils : NSObject
CGFloat magnitude(CGPoint point);
CGFloat ratio(CGPoint a, CGPoint b);
CGFloat angle(CGPoint a, CGPoint b);
CGFloat radians_to_degrees(CGFloat radians);
CGFloat degrees_to_radians(CGFloat degrees);
BOOL IJSVGCharBufferIsHEX(char* buffer);
BOOL IJSVGCharBufferHasPrefix(char* pre, char* str);
BOOL IJSVGCharBufferHasSuffix(char* s1, char* s2);
char* IJSVGTimmedCharBufferCreate(const char* buffer);
void IJSVGTrimCharBuffer(char* buffer);
void IJSVGCharBufferToLower(char* buffer);
size_t IJSVGCharBufferHash(char* buffer);
IJSVGFloatingPointOptions IJSVGFloatingPointOptionsDefault(void);
IJSVGFloatingPointOptions IJSVGFloatingPointOptionsMake(BOOL round, int precision);
NSString* IJSVGCompressFloatParameterArray(NSArray<NSString*>* stringToCompress);
NSString* IJSVGShortFloatStringWithOptions(CGFloat f, IJSVGFloatingPointOptions options);
NSString* IJSVGShortenFloatString(NSString* string);
NSString* IJSVGPointToCommandString(CGPoint point);
NSString* IJSVGShortFloatString(CGFloat f);
NSString* IJSVGShortFloatStringWithPrecision(CGFloat f, NSInteger precision);
BOOL IJSVGIsLegalCommandCharacter(unichar aChar);
BOOL IJSVGIsSVGLayer(CALayer* layer);
+ (IJSVGCommandType)typeForCommandChar:(char)commandChar;
+ (CGFloat*)commandParameters:(NSString*)command
count:(NSInteger*)count;
+ (CGFloat*)parseViewBox:(NSString*)string;
+ (IJSVGWindingRule)windingRuleForString:(NSString*)string;
+ (IJSVGLineJoinStyle)lineJoinStyleForString:(NSString*)string;
+ (IJSVGLineCapStyle)lineCapStyleForString:(NSString*)string;
+ (IJSVGLineJoinStyle)lineJoinStyleForCGLineJoin:(CGLineJoin)lineJoin;
+ (IJSVGLineCapStyle)lineCapStyleForCGLineCap:(CGLineCap)lineCap;
+ (IJSVGUnitType)unitTypeForString:(NSString*)string;
+ (IJSVGBlendMode)blendModeForString:(NSString*)string;
+ (NSString* _Nullable)mixBlendingModeForBlendMode:(IJSVGBlendMode)blendMode;
+ (NSRange)rangeOfParentheses:(NSString*)string;
+ (void)logParameters:(CGFloat*)param
count:(NSInteger)count;
+ (CGFloat)floatValue:(NSString*)string;
+ (CGFloat)angleBetweenPointA:(NSPoint)point
pointb:(NSPoint)point;
+ (NSString* _Nullable)defURL:(NSString*)string;
+ (CGFloat)floatValue:(NSString*)string
fallBackForPercent:(CGFloat)viewBox;
+ (CGFloat*)scanFloatsFromString:(NSString*)string
size:(NSInteger*)length;
+ (CGFloat*)scanFloatsFromCString:(const char*)buffer
size:(NSInteger*)length;
+ (CGFloat*)scanFloatsFromCString:(const char*)buffer
floatCount:(NSUInteger)floatCount
charCount:(NSUInteger)charCount
size:(NSInteger*)length;
+ (IJSVGFontTraits)fontStyleStringForString:(NSString*)string;
+ (IJSVGFontTraits)fontWeightTraitForString:(NSString*)string
weight:(CGFloat*)weight;
+ (CGPathRef)newFlippedCGPath:(CGPathRef)path;
@end
NS_ASSUME_NONNULL_END
@@ -1,559 +0,0 @@
//
// IJSVGUtils.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGLayer.h"
#import "IJSVGShapeLayer.h"
#import "IJSVGUtils.h"
#import "IJSVGExporterPathInstruction.h"
#import "IJSVGParsing.h"
@implementation IJSVGUtils
BOOL IJSVGCharBufferIsHEX(char* buffer) {
char c;
while((c = *buffer++)) {
BOOL flag = ((c == '#') ||
(c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F'));
if(flag == NO) {
return NO;
}
}
return YES;
}
BOOL IJSVGCharBufferHasPrefix(char *str, char *pre)
{
return strncmp(pre, str, strlen(pre)) == 0;
}
BOOL IJSVGCharBufferHasSuffix(char* s1, char* s2)
{
size_t slen = strlen(s1);
size_t tlen = strlen(s2);
if (tlen > slen) {
return NO;
}
return strcmp(s1 + slen - tlen, s2) == 0;
}
char* IJSVGTimmedCharBufferCreate(const char* buffer)
{
unsigned long start = 0;
unsigned long length = strlen(buffer);
while(length-1 > 0 && isspace(buffer[length-1])) {
length--;
}
while(isspace(buffer[start])) {
start++;
}
char* chars = (char*)malloc(sizeof(char)*((length-start)+1) ?: sizeof(char));
memcpy(chars, &buffer[start], length-start);
chars[length] = '\0';
return chars;
}
void IJSVGTrimCharBuffer(char* buffer) {
char* ptr = buffer;
unsigned long length = strlen(ptr);
while(length-1 > 0 && isspace(ptr[length-1])) {
ptr[--length] = '\0';
}
while(*ptr && isspace(*ptr)) {
++ptr;
--length;
}
memmove(buffer, ptr, length+1);
}
void IJSVGCharBufferToLower(char* buffer)
{
for(char *p = buffer; *p; p++) {
*p = tolower(*p);
}
}
size_t IJSVGCharBufferHash(char* buffer)
{
unsigned long hash = 5381;
int c;
while ((c = *buffer++)) {
hash = ((hash << 5) + hash) + c;
}
return hash;
}
NSString* IJSVGShortenFloatString(NSString* string)
{
const char* chars = string.UTF8String;
if (chars[0] == '-' && chars[1] == '0' && strstr(chars, ".") != NULL) {
return [NSString stringWithFormat:@"-%@", [string substringFromIndex:2]];
} else if (chars[0] == '0' && chars[1] == '.') {
return [string substringFromIndex:1];
}
return string;
}
IJSVGFloatingPointOptions IJSVGFloatingPointOptionsDefault(void)
{
return IJSVGFloatingPointOptionsMake(NO, kIJSVGExporterPathInstructionFloatPrecision);
}
IJSVGFloatingPointOptions IJSVGFloatingPointOptionsMake(BOOL round, int precision)
{
return (IJSVGFloatingPointOptions) {
.round = round,
.precision = precision
};
}
NSString* IJSVGShortFloatStringWithOptions(CGFloat f, IJSVGFloatingPointOptions options)
{
if (options.round == YES) {
f = IJSVGExporterPathFloatToFixed(f, options.precision);
}
return IJSVGShortFloatString(f);
};
NSString* IJSVGShortFloatString(CGFloat f)
{
return IJSVGShortenFloatString([NSString stringWithFormat:@"%g", f]);
};
NSString* IJSVGCompressFloatParameterArray(NSArray<NSString*>* strings)
{
char* lastCommandChars = NULL;
NSInteger index = 0;
NSMutableString* string = [[[NSMutableString alloc] init] autorelease];
for (NSString* dataString in strings) {
const char* chars = dataString.UTF8String;
// 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;
}
return string;
};
NSString* IJSVGShortFloatStringWithPrecision(CGFloat f, NSInteger precision)
{
NSString* format = [NSString stringWithFormat:@"%@.%ld%@", @"%", precision, @"f"];
NSString* ret = [NSString stringWithFormat:format, f];
if (ret.floatValue == (float)ret.integerValue) {
ret = [NSString stringWithFormat:@"%ld", ret.integerValue];
}
return IJSVGShortenFloatString(ret);
};
NSString* IJSVGPointToCommandString(CGPoint point)
{
return [NSString stringWithFormat:@"%@ %@",
IJSVGShortFloatString(point.x),
IJSVGShortFloatString(point.y)];
};
BOOL IJSVGIsLegalCommandCharacter(unichar aChar)
{
if ((aChar | ('M' ^ 'm')) == 'm' ||
(aChar | ('Z' ^ 'z')) == 'z' ||
(aChar | ('C' ^ 'c')) == 'c' ||
(aChar | ('L' ^ 'l')) == 'l' ||
(aChar | ('S' ^ 's')) == 's' ||
(aChar | ('Q' ^ 'q')) == 'q' ||
(aChar | ('H' ^ 'h')) == 'h' ||
(aChar | ('V' ^ 'v')) == 'v' ||
(aChar | ('T' ^ 't')) == 't' ||
(aChar | ('A' ^ 'a')) == 'a') {
return YES;
}
return NO;
}
BOOL IJSVGIsSVGLayer(CALayer* layer)
{
return [layer isKindOfClass:IJSVGLayer.class] ||
[layer isKindOfClass:IJSVGShapeLayer.class];
}
CGFloat angle(CGPoint a, CGPoint b)
{
return [IJSVGUtils angleBetweenPointA:a
pointb:b];
}
CGFloat ratio(CGPoint a, CGPoint b)
{
return (a.x * b.x + a.y * b.y) / (magnitude(a) * magnitude(b));
}
CGFloat magnitude(CGPoint point)
{
return sqrtf(powf(point.x, 2) + powf(point.y, 2));
}
CGFloat radians_to_degrees(CGFloat radians)
{
return ((radians) * (180.0 / M_PI));
}
CGFloat degrees_to_radians(CGFloat degrees)
{
return ((degrees) / 180.0 * M_PI);
}
+ (IJSVGCommandType)typeForCommandChar:(char)commandChar
{
return isupper(commandChar) ? kIJSVGCommandTypeAbsolute : kIJSVGCommandTypeRelative;
}
+ (NSRange)rangeOfParentheses:(NSString*)string
{
NSRange range = NSMakeRange(NSNotFound, 0);
const char* characters = string.UTF8String;
unsigned long length = strlen(characters);
for (NSInteger i = 0; i < length; i++) {
char c = *characters++;
if (c == '(') {
range.location = i + 1;
} else if (c == ')') {
range.length = i - range.location;
}
}
return range;
}
+ (NSString* _Nullable)defURL:(NSString*)string
{
const char* str = string.UTF8String;
NSUInteger count = 0;
IJSVGParsingStringMethod** methods;
methods = IJSVGParsingMethodParseString(str, &count);
if(count == 0) {
IJSVGParsingStringMethodsRelease(methods, count);
return nil;
}
// what type of method is it?
IJSVGParsingStringMethod* method = methods[0];
IJSVGCharBufferToLower(method->name);
if(strcmp(method->name, "url") != 0) {
(void)IJSVGParsingStringMethodsRelease(methods, count), methods = NULL;
return nil;
}
// remove the #
char* parameters = method->parameters;
if(parameters[0] == '#') {
parameters++;
}
// make the nsstring
NSString* foundID = [NSString stringWithUTF8String:parameters];
// release the stuff
(void)IJSVGParsingStringMethodsRelease(methods, count), methods = NULL;
return foundID;
}
+ (IJSVGFontTraits)fontWeightTraitForString:(NSString*)string
weight:(CGFloat*)weight
{
*weight = string.floatValue;
if ([string isEqualToString:@"bold"])
return IJSVGFontTraitBold;
return IJSVGFontTraitNone;
}
+ (IJSVGFontTraits)fontStyleStringForString:(NSString*)string
{
if ([string isEqualToString:@"italic"])
return IJSVGFontTraitItalic;
return IJSVGFontTraitNone;
}
+ (IJSVGWindingRule)windingRuleForString:(NSString*)string
{
if ([string isEqualToString:@"evenodd"])
return IJSVGWindingRuleEvenOdd;
if ([string isEqualToString:@"inherit"])
return IJSVGWindingRuleInherit;
return IJSVGWindingRuleNonZero;
}
+ (IJSVGLineJoinStyle)lineJoinStyleForString:(NSString*)string
{
if ([string isEqualToString:@"mitre"])
return IJSVGLineJoinStyleMiter;
if ([string isEqualToString:@"round"])
return IJSVGLineJoinStyleRound;
if ([string isEqualToString:@"bevel"])
return IJSVGLineJoinStyleBevel;
if ([string isEqualToString:@"inherit"])
return IJSVGLineJoinStyleInherit;
return IJSVGLineJoinStyleMiter;
}
+ (IJSVGLineCapStyle)lineCapStyleForString:(NSString*)string
{
if ([string isEqualToString:@"butt"])
return IJSVGLineCapStyleButt;
if ([string isEqualToString:@"square"])
return IJSVGLineCapStyleSquare;
if ([string isEqualToString:@"round"])
return IJSVGLineCapStyleRound;
if ([string isEqualToString:@"inherit"])
return IJSVGLineCapStyleInherit;
return IJSVGLineCapStyleButt;
}
+ (IJSVGLineCapStyle)lineCapStyleForCGLineCap:(CGLineCap)lineCap
{
switch(lineCap) {
case kCGLineCapButt: {
return IJSVGLineCapStyleButt;
}
case kCGLineCapRound: {
return IJSVGLineCapStyleRound;
}
case kCGLineCapSquare: {
return IJSVGLineCapStyleSquare;
}
default: {
return IJSVGLineCapStyleInherit;
}
}
}
+ (IJSVGLineJoinStyle)lineJoinStyleForCGLineJoin:(CGLineJoin)lineJoin
{
switch(lineJoin) {
case kCGLineJoinRound: {
return IJSVGLineJoinStyleRound;
}
case kCGLineJoinMiter: {
return IJSVGLineJoinStyleMiter;
}
case kCGLineJoinBevel: {
return IJSVGLineJoinStyleBevel;
}
default: {
return IJSVGLineJoinStyleInherit;
}
}
}
+ (IJSVGUnitType)unitTypeForString:(NSString*)string
{
if ([string isEqualToString:@"userSpaceOnUse"]) {
return IJSVGUnitUserSpaceOnUse;
}
return IJSVGUnitObjectBoundingBox;
}
+ (IJSVGBlendMode)blendModeForString:(NSString*)string
{
string = string.lowercaseString;
if ([string isEqualToString:@"normal"])
return IJSVGBlendModeNormal;
if ([string isEqualToString:@"multiply"])
return IJSVGBlendModeMultiply;
if ([string isEqualToString:@"screen"])
return IJSVGBlendModeScreen;
if ([string isEqualToString:@"overlay"])
return IJSVGBlendModeOverlay;
if ([string isEqualToString:@"darken"])
return IJSVGBlendModeDarken;
if ([string isEqualToString:@"lighten"])
return IJSVGBlendModeLighten;
if ([string isEqualToString:@"color-dodge"])
return IJSVGBlendModeColorDodge;
if ([string isEqualToString:@"color-burn"])
return IJSVGBlendModeColorBurn;
if ([string isEqualToString:@"hard-light"])
return IJSVGBlendModeHardLight;
if ([string isEqualToString:@"soft-light"])
return IJSVGBlendModeSoftLight;
if ([string isEqualToString:@"difference"])
return IJSVGBlendModeDifference;
if ([string isEqualToString:@"exclusion"])
return IJSVGBlendModeExclusion;
if ([string isEqualToString:@"hue"])
return IJSVGBlendModeHue;
if ([string isEqualToString:@"saturation"])
return IJSVGBlendModeSaturation;
if ([string isEqualToString:@"color"])
return IJSVGBlendModeColor;
if ([string isEqualToString:@"luminosity"])
return IJSVGBlendModeLuminosity;
return IJSVGBlendModeNormal;
}
+ (NSString* _Nullable)mixBlendingModeForBlendMode:(IJSVGBlendMode)blendMode
{
switch (blendMode) {
case IJSVGBlendModeMultiply: {
return @"multiple";
}
case IJSVGBlendModeScreen: {
return @"screen";
}
case IJSVGBlendModeOverlay: {
return @"overlay";
}
case IJSVGBlendModeDarken: {
return @"darken";
}
case IJSVGBlendModeLighten: {
return @"lighten";
}
case IJSVGBlendModeColorDodge: {
return @"color-dodge";
}
case IJSVGBlendModeColorBurn: {
return @"color-burn";
}
case IJSVGBlendModeHardLight: {
return @"hard-light";
}
case IJSVGBlendModeSoftLight: {
return @"soft-light";
}
case IJSVGBlendModeDifference: {
return @"difference";
}
case IJSVGBlendModeExclusion: {
return @"exclusion";
}
case IJSVGBlendModeHue: {
return @"hue";
}
case IJSVGBlendModeSaturation: {
return @"saturation";
}
case IJSVGBlendModeColor: {
return @"color";
}
case IJSVGBlendModeLuminosity: {
return @"luminosity";
}
case IJSVGBlendModeNormal:
default: {
return nil;
}
}
}
+ (CGFloat*)commandParameters:(NSString*)command
count:(NSInteger*)count
{
return [self.class scanFloatsFromString:command
size:count];
}
+ (CGFloat*)scanFloatsFromString:(NSString*)string
size:(NSInteger*)length
{
return [self.class scanFloatsFromCString:string.UTF8String
size:length];
}
+ (CGFloat*)scanFloatsFromCString:(const char*)buffer
size:(NSInteger*)length
{
IJSVGPathDataStream* stream = IJSVGPathDataStreamCreateDefault();
CGFloat* floats = IJSVGParsePathDataStreamSequence(buffer, strlen(buffer),
stream, NULL, 1, length);
IJSVGPathDataStreamRelease(stream);
return floats;
}
+ (CGFloat*)scanFloatsFromCString:(const char*)buffer
floatCount:(NSUInteger)floatCount
charCount:(NSUInteger)charCount
size:(NSInteger*)length
{
IJSVGPathDataStream* stream = IJSVGPathDataStreamCreate(floatCount, charCount);
CGFloat* floats = IJSVGParsePathDataStreamSequence(buffer, strlen(buffer),
stream, NULL, 1, length);
IJSVGPathDataStreamRelease(stream);
return floats;
}
+ (CGFloat*)parseViewBox:(NSString*)string
{
IJSVGPathDataStream* stream = IJSVGPathDataStreamCreate(4,
IJSVG_STREAM_CHAR_BLOCK_SIZE);
const char* str = string.UTF8String;
CGFloat* floats = IJSVGParsePathDataStreamSequence(str, strlen(str),
stream, NULL, 1, NULL);
IJSVGPathDataStreamRelease(stream);
return floats;
}
+ (CGFloat)floatValue:(NSString*)string
fallBackForPercent:(CGFloat)fallBack
{
CGFloat val = [string floatValue];
if ([string rangeOfString:@"%"].location != NSNotFound) {
val = (fallBack * val) / 100;
}
return val;
}
+ (void)logParameters:(CGFloat*)param
count:(NSInteger)count
{
NSMutableString* str = [[[NSMutableString alloc] init] autorelease];
for (NSInteger i = 0; i < count; i++) {
[str appendFormat:@"%f ", param[i]];
}
NSLog(@"%@", str);
}
+ (CGFloat)floatValue:(NSString*)string
{
if ([string isEqualToString:@"inherit"]) {
return IJSVGInheritedFloatValue;
}
return [string floatValue];
}
+ (CGFloat)angleBetweenPointA:(NSPoint)point1
pointb:(NSPoint)point2
{
return (point1.x * point2.y < point1.y * point2.x ? -1 : 1) * acosf(ratio(point1, point2));
}
+ (CGPathRef)newFlippedCGPath:(CGPathRef)path
{
CGRect boundingBox = CGPathGetPathBoundingBox(path);
CGAffineTransform scale = CGAffineTransformMakeScale(1.f, -1.f);
CGAffineTransform translate = CGAffineTransformTranslate(scale, 0.f, boundingBox.size.height);
CGPathRef transformPath = CGPathCreateCopyByTransformingPath(path, &translate);
return transformPath;
}
@end
@@ -8,8 +8,6 @@
/* Begin PBXBuildFile section */
343A19181FB2212C000652A2 /* IJSVGGradientUnitLength.m in Sources */ = {isa = PBXBuildFile; fileRef = 343A19171FB2212C000652A2 /* IJSVGGradientUnitLength.m */; };
59069A2922D0ED85004DDEA5 /* compuserver_msn_Ford_Focus.svg in Resources */ = {isa = PBXBuildFile; fileRef = 59069A2822D0ED85004DDEA5 /* compuserver_msn_Ford_Focus.svg */; };
59069A2B22D0EE0E004DDEA5 /* test (1).svg in Resources */ = {isa = PBXBuildFile; fileRef = 59069A2A22D0EE0E004DDEA5 /* test (1).svg */; };
590C87EB201F9888004A1554 /* json.svg in Resources */ = {isa = PBXBuildFile; fileRef = 590C87EA201F9888004A1554 /* json.svg */; };
590C87ED201FA08C004A1554 /* intertwingly.svg in Resources */ = {isa = PBXBuildFile; fileRef = 590C87EC201FA08C004A1554 /* intertwingly.svg */; };
590C87EF201FA093004A1554 /* NewTux.svg in Resources */ = {isa = PBXBuildFile; fileRef = 590C87EE201FA092004A1554 /* NewTux.svg */; };
@@ -37,7 +35,6 @@
595665DE19B6309C00D805FF /* test.svg in Resources */ = {isa = PBXBuildFile; fileRef = 595665DD19B6309C00D805FF /* test.svg */; };
595665E119B630B600D805FF /* SVGView.m in Sources */ = {isa = PBXBuildFile; fileRef = 595665E019B630B600D805FF /* SVGView.m */; };
597046A21E24352700A60138 /* IJSVGStrokeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 597046A11E24352700A60138 /* IJSVGStrokeLayer.m */; };
597AC83322CFD0FC007C0E42 /* home.svg in Resources */ = {isa = PBXBuildFile; fileRef = 597AC83222CFD0FC007C0E42 /* home.svg */; };
5986308719BA104800CF15EA /* linecap.svg in Resources */ = {isa = PBXBuildFile; fileRef = 5986308619BA104800CF15EA /* linecap.svg */; };
5986308A19BA106D00CF15EA /* SVGExampleView5.m in Sources */ = {isa = PBXBuildFile; fileRef = 5986308919BA106D00CF15EA /* SVGExampleView5.m */; };
5986308C19BA180E00CF15EA /* dashed.svg in Resources */ = {isa = PBXBuildFile; fileRef = 5986308B19BA180E00CF15EA /* dashed.svg */; };
@@ -54,6 +51,7 @@
59A3DA6D1E283022003E59A9 /* IJSVGTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A3DA6C1E283022003E59A9 /* IJSVGTransaction.m */; };
59B93C6D19B7D1840063E823 /* paperplane.svg in Resources */ = {isa = PBXBuildFile; fileRef = 59B93C6C19B7D1840063E823 /* paperplane.svg */; };
59B93C6F19B7D32C0063E823 /* products.svg in Resources */ = {isa = PBXBuildFile; fileRef = 59B93C6E19B7D32C0063E823 /* products.svg */; };
59D1E39E2022577500C54672 /* IJSVGQuartzRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59D1E39D2022577500C54672 /* IJSVGQuartzRenderer.m */; };
59D1E3A0202279CA00C54672 /* Group.svg in Resources */ = {isa = PBXBuildFile; fileRef = 59D1E39F202279CA00C54672 /* Group.svg */; };
59E0F5ED1E29964700F757F7 /* IJSVGUnitLength.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E0F5EC1E29964700F757F7 /* IJSVGUnitLength.m */; };
59E2645119BA240D008A6FDB /* IJSVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E2641C19BA240D008A6FDB /* IJSVG.m */; };
@@ -89,10 +87,6 @@
59E8ABF31E2167D90032A80C /* IJSVGImageLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E8ABF21E2167D90032A80C /* IJSVGImageLayer.m */; };
59E8ABF61E2176340032A80C /* IJSVGGroupLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E8ABF51E2176340032A80C /* IJSVGGroupLayer.m */; };
59E8ABF91E219C860032A80C /* IJSVGMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E8ABF81E219C860032A80C /* IJSVGMath.m */; };
59EA311622CF395400DAB3B7 /* IJSVGStringAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EA310F22CF395400DAB3B7 /* IJSVGStringAdditions.m */; };
59EA311722CF395400DAB3B7 /* IJSVGRendering.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EA311022CF395400DAB3B7 /* IJSVGRendering.m */; };
59EA311822CF395400DAB3B7 /* IJSVGImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EA311322CF395400DAB3B7 /* IJSVGImageRep.m */; };
59EA311922CF395400DAB3B7 /* IJSVGView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EA311422CF395400DAB3B7 /* IJSVGView.m */; };
59F799E219B880CE00096CB7 /* htc_one.svg in Resources */ = {isa = PBXBuildFile; fileRef = 59F799E119B880CE00096CB7 /* htc_one.svg */; };
/* End PBXBuildFile section */
@@ -109,8 +103,6 @@
/* Begin PBXFileReference section */
343A19161FB2212C000652A2 /* IJSVGGradientUnitLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradientUnitLength.h; sourceTree = "<group>"; };
343A19171FB2212C000652A2 /* IJSVGGradientUnitLength.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientUnitLength.m; sourceTree = "<group>"; };
59069A2822D0ED85004DDEA5 /* compuserver_msn_Ford_Focus.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = compuserver_msn_Ford_Focus.svg; sourceTree = "<group>"; };
59069A2A22D0EE0E004DDEA5 /* test (1).svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "test (1).svg"; sourceTree = "<group>"; };
590C87EA201F9888004A1554 /* json.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = json.svg; sourceTree = "<group>"; };
590C87EC201FA08C004A1554 /* intertwingly.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = intertwingly.svg; sourceTree = "<group>"; };
590C87EE201FA092004A1554 /* NewTux.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = NewTux.svg; sourceTree = "<group>"; };
@@ -157,7 +149,6 @@
595665E019B630B600D805FF /* SVGView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVGView.m; sourceTree = "<group>"; };
597046A01E24352700A60138 /* IJSVGStrokeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStrokeLayer.h; sourceTree = "<group>"; };
597046A11E24352700A60138 /* IJSVGStrokeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStrokeLayer.m; sourceTree = "<group>"; };
597AC83222CFD0FC007C0E42 /* home.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = home.svg; sourceTree = "<group>"; };
5986308619BA104800CF15EA /* linecap.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = linecap.svg; sourceTree = "<group>"; };
5986308819BA106D00CF15EA /* SVGExampleView5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGExampleView5.h; sourceTree = "<group>"; };
5986308919BA106D00CF15EA /* SVGExampleView5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVGExampleView5.m; sourceTree = "<group>"; };
@@ -184,6 +175,8 @@
59A3DA6C1E283022003E59A9 /* IJSVGTransaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGTransaction.m; sourceTree = "<group>"; };
59B93C6C19B7D1840063E823 /* paperplane.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = paperplane.svg; sourceTree = "<group>"; };
59B93C6E19B7D32C0063E823 /* products.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = products.svg; sourceTree = "<group>"; };
59D1E39C2022577500C54672 /* IJSVGQuartzRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGQuartzRenderer.h; sourceTree = "<group>"; };
59D1E39D2022577500C54672 /* IJSVGQuartzRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGQuartzRenderer.m; sourceTree = "<group>"; };
59D1E39F202279CA00C54672 /* Group.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Group.svg; sourceTree = "<group>"; };
59E0F5EB1E29964700F757F7 /* IJSVGUnitLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitLength.h; sourceTree = "<group>"; };
59E0F5EC1E29964700F757F7 /* IJSVGUnitLength.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitLength.m; sourceTree = "<group>"; };
@@ -253,14 +246,6 @@
59E8ABF51E2176340032A80C /* IJSVGGroupLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGroupLayer.m; sourceTree = "<group>"; };
59E8ABF71E219C860032A80C /* IJSVGMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGMath.h; sourceTree = "<group>"; };
59E8ABF81E219C860032A80C /* IJSVGMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGMath.m; sourceTree = "<group>"; };
59EA310E22CF395300DAB3B7 /* IJSVGImageRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImageRep.h; sourceTree = "<group>"; };
59EA310F22CF395400DAB3B7 /* IJSVGStringAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStringAdditions.m; sourceTree = "<group>"; };
59EA311022CF395400DAB3B7 /* IJSVGRendering.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRendering.m; sourceTree = "<group>"; };
59EA311122CF395400DAB3B7 /* IJSVGRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRendering.h; sourceTree = "<group>"; };
59EA311222CF395400DAB3B7 /* IJSVGView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGView.h; sourceTree = "<group>"; };
59EA311322CF395400DAB3B7 /* IJSVGImageRep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImageRep.m; sourceTree = "<group>"; };
59EA311422CF395400DAB3B7 /* IJSVGView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGView.m; sourceTree = "<group>"; };
59EA311522CF395400DAB3B7 /* IJSVGStringAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStringAdditions.h; sourceTree = "<group>"; };
59F799E119B880CE00096CB7 /* htc_one.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = htc_one.svg; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -330,9 +315,6 @@
5956657A19B62F4600D805FF /* Supporting Files */ = {
isa = PBXGroup;
children = (
59069A2A22D0EE0E004DDEA5 /* test (1).svg */,
59069A2822D0ED85004DDEA5 /* compuserver_msn_Ford_Focus.svg */,
597AC83222CFD0FC007C0E42 /* home.svg */,
59D1E39F202279CA00C54672 /* Group.svg */,
590C87F5201FD0D4004A1554 /* car.svg */,
590C87F3201FC9E3004A1554 /* radialgradient2.svg */,
@@ -386,14 +368,6 @@
59E2641A19BA240D008A6FDB /* source */ = {
isa = PBXGroup;
children = (
59EA310E22CF395300DAB3B7 /* IJSVGImageRep.h */,
59EA311322CF395400DAB3B7 /* IJSVGImageRep.m */,
59EA311122CF395400DAB3B7 /* IJSVGRendering.h */,
59EA311022CF395400DAB3B7 /* IJSVGRendering.m */,
59EA311522CF395400DAB3B7 /* IJSVGStringAdditions.h */,
59EA310F22CF395400DAB3B7 /* IJSVGStringAdditions.m */,
59EA311222CF395400DAB3B7 /* IJSVGView.h */,
59EA311422CF395400DAB3B7 /* IJSVGView.m */,
59A3DA6B1E283022003E59A9 /* IJSVGTransaction.h */,
59A3DA6C1E283022003E59A9 /* IJSVGTransaction.m */,
598759F41E242C850024CC3F /* IJSVGExporterPathInstruction.h */,
@@ -495,6 +469,8 @@
597046A11E24352700A60138 /* IJSVGStrokeLayer.m */,
59E0F5EB1E29964700F757F7 /* IJSVGUnitLength.h */,
59E0F5EC1E29964700F757F7 /* IJSVGUnitLength.m */,
59D1E39C2022577500C54672 /* IJSVGQuartzRenderer.h */,
59D1E39D2022577500C54672 /* IJSVGQuartzRenderer.m */,
);
name = source;
path = ../../source;
@@ -561,7 +537,6 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
@@ -585,17 +560,14 @@
5956658219B62F4600D805FF /* Images.xcassets in Resources */,
590C87ED201FA08C004A1554 /* intertwingly.svg in Resources */,
590C87F1201FBF27004A1554 /* AJ_Digital_Camera.svg in Resources */,
59069A2B22D0EE0E004DDEA5 /* test (1).svg in Resources */,
590C87EF201FA093004A1554 /* NewTux.svg in Resources */,
59265CE81C4F840400F333F0 /* css.svg in Resources */,
595665DE19B6309C00D805FF /* test.svg in Resources */,
597AC83322CFD0FC007C0E42 /* home.svg in Resources */,
590C87EB201F9888004A1554 /* json.svg in Resources */,
59D1E3A0202279CA00C54672 /* Group.svg in Resources */,
59F799E219B880CE00096CB7 /* htc_one.svg in Resources */,
59B93C6F19B7D32C0063E823 /* products.svg in Resources */,
5991A2A9201E30E600913E3B /* gradients.svg in Resources */,
59069A2922D0ED85004DDEA5 /* compuserver_msn_Ford_Focus.svg in Resources */,
5986308719BA104800CF15EA /* linecap.svg in Resources */,
5956658519B62F4600D805FF /* MainMenu.xib in Resources */,
590C87F4201FC9E4004A1554 /* radialgradient2.svg in Resources */,
@@ -624,7 +596,7 @@
59E2646919BA240D008A6FDB /* IJSVGStyle.m in Sources */,
59E2646419BA240D008A6FDB /* IJSVGLinearGradient.m in Sources */,
595665DC19B6302600D805FF /* README.md in Sources */,
59EA311922CF395400DAB3B7 /* IJSVGView.m in Sources */,
59D1E39E2022577500C54672 /* IJSVGQuartzRenderer.m in Sources */,
5941DAFD1CF9BC9B00B3A911 /* IJSVGImage.m in Sources */,
599465DE1C4AA87200A2EEF3 /* IJSVGStyleSheetSelector.m in Sources */,
5948DED61BB2BFE5004156FF /* IJSVGWriter.m in Sources */,
@@ -653,7 +625,6 @@
5956658019B62F4600D805FF /* AppDelegate.m in Sources */,
59E2646519BA240D008A6FDB /* IJSVGNode.m in Sources */,
591A13E11E19838F001D1629 /* IJSVGText.m in Sources */,
59EA311822CF395400DAB3B7 /* IJSVGImageRep.m in Sources */,
59A11E6C19B89CEA00E44498 /* SVGExampleView1.m in Sources */,
59A3DA6D1E283022003E59A9 /* IJSVGTransaction.m in Sources */,
59E2646A19BA240D008A6FDB /* IJSVGTransform.m in Sources */,
@@ -665,7 +636,6 @@
598759F61E242C850024CC3F /* IJSVGExporterPathInstruction.m in Sources */,
59E2645E19BA240D008A6FDB /* IJSVGCommandSmoothCurve.m in Sources */,
59E2645819BA240D008A6FDB /* IJSVGCommandCommandSmoothQuadraticCurve.m in Sources */,
59EA311622CF395400DAB3B7 /* IJSVGStringAdditions.m in Sources */,
59E2645D19BA240D008A6FDB /* IJSVGCommandQuadraticCurve.m in Sources */,
59E2646719BA240D008A6FDB /* IJSVGPath.m in Sources */,
59E8ABED1E211EBE0032A80C /* IJSVGLayer.m in Sources */,
@@ -674,7 +644,6 @@
59A11E7219B89D6600E44498 /* SVGExampleView3.m in Sources */,
59E0F5ED1E29964700F757F7 /* IJSVGUnitLength.m in Sources */,
5956657D19B62F4600D805FF /* main.m in Sources */,
59EA311722CF395400DAB3B7 /* IJSVGRendering.m in Sources */,
59A11E6F19B89D2000E44498 /* SVGExampleView2.m in Sources */,
5948DED51BB2BFE5004156FF /* IJSVGFontConverter.m in Sources */,
59E2646319BA240D008A6FDB /* IJSVGGroup.m in Sources */,
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "21141E92-29FD-4CF6-AB04-0D4E4FD9A4AC"
type = "1"
version = "2.0">
</Bucket>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14835.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14835.7"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -667,21 +667,42 @@
</menu>
</menuItem>
</items>
<point key="canvasLocation" x="139" y="154"/>
</menu>
<window title="IJSVGExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" appearanceType="aqua" animationBehavior="default" id="QvC-M9-y7g">
<window title="IJSVGExample" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="335" y="390" width="600" height="479"/>
<rect key="screenRect" x="0.0" y="0.0" width="3008" height="1669"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" misplaced="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="600" height="479"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hhC-1S-CCX" customClass="SVGView">
<rect key="frame" x="0.0" y="0.0" width="600" height="479"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<customView misplaced="YES" id="hhC-1S-CCX" customClass="SVGView">
<rect key="frame" x="0.0" y="0.0" width="600" height="385"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
</customView>
<button verticalHuggingPriority="750" misplaced="YES" id="gpW-KV-dZb">
<rect key="frame" x="14" y="431" width="205" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Render with CoreAnimation" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="b5N-FF-ykt">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switchToCoreAnimation:" target="hhC-1S-CCX" id="318-qP-1z4"/>
</connections>
</button>
<button verticalHuggingPriority="750" misplaced="YES" id="68n-xB-I0F">
<rect key="frame" x="14" y="398" width="205" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Render with CoreGraphics" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Tcq-b5-8Y0">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="switchToCoreGraphics:" target="hhC-1S-CCX" id="gzP-YM-P2p"/>
</connections>
</button>
</subviews>
</view>
<point key="canvasLocation" x="98" y="496.5"/>
-19
View File
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="447px" height="336px" viewBox="0 0 447 336" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Rectangle</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
<stop stop-color="#1E54F6" offset="0%"></stop>
<stop stop-color="#EE2323" offset="100%"></stop>
</linearGradient>
<rect id="path-2" x="0" y="0" width="447" height="336"></rect>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Rectangle">
<use fill="#D8D8D8" fill-rule="evenodd" xlink:href="#path-2"></use>
<rect stroke="url(#linearGradient-1)" stroke-width="10" x="5" y="5" width="437" height="326"></rect>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 992 B

+3 -1
View File
@@ -11,9 +11,11 @@
@interface SVGView : NSView {
@private
IJSVG * svg;
}
- (IBAction)switchToCoreGraphics:(id)sender;
- (IBAction)switchToCoreAnimation:(id)sender;
@end
+14 -3
View File
@@ -22,17 +22,28 @@
if( ( self = [super initWithFrame:frameRect] ) != nil )
{
svg = [self svg];
svg.renderQuality = IJSVGRenderQualityFullResolution;
svg.renderingBackingScaleHelper = ^{
return self.window.backingScaleFactor;
return [svg computeBackingScale:self.window.backingScaleFactor];
};
}
return self;
}
- (void)switchToCoreGraphics:(id)sender
{
svg.renderingEngine = IJSVGRenderingEngineQuartz;
[self setNeedsDisplay:YES];
}
- (void)switchToCoreAnimation:(id)sender
{
svg.renderingEngine = IJSVGRenderingEngineLayered;
[self setNeedsDisplay:YES];
}
- (IJSVG *)svg
{
return [IJSVG svgNamed:@"test (1)"];
return [IJSVG svgNamed:@"clipped"];
}
- (void)drawRect:(NSRect)dirtyRect
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 318 KiB

-32
View File
@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="508" height="508" version="1.1" viewBox="0 0 508 508" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!--Generated by IJSVG (https://github.com/iconjar/IJSVG)-->
<defs>
<linearGradient id="a" x1="0.145454" x2="0.599999" y1="0.257812" y2="0.570312" gradientTransform="matrix(1,0,0,1,-7.61378e-09,-1.86769e-08)">
<stop offset="0%" stop-color="#FBDDB2" stop-opacity="0.99"></stop>
<stop offset="100%" stop-color="#EFA81A" stop-opacity="0.95"></stop>
</linearGradient>
<linearGradient id="b" x1="-0.0270271" x2="0.783784" y1="0.46875" y2="0.476562" gradientTransform="matrix(1,0,0,1,3.52391e-08,-2.90476e-08)">
<stop offset="0%" stop-color="#787878" stop-opacity="0.99"></stop>
<stop offset="100%" stop-color="#FFF" stop-opacity="0.99"></stop>
</linearGradient>
<linearGradient id="c" x1="0.235289" x2="0.672269" y1="0.265619" y2="0.59375" gradientTransform="matrix(1,0,0,1,1.18803e-07,-1.01189e-08)" xlink:href="#b"></linearGradient>
<linearGradient id="d" x1="0.981639" x2="0.146789" y1="0.0312495" y2="0.601562" gradientTransform="matrix(1,0,0,1,-5.18186e-08,1.7497e-08)" xlink:href="#b"></linearGradient>
<linearGradient id="e" x1="1.20507" x2="0.102482" y1="0.523438" y2="0.515617" gradientTransform="matrix(1,0,0,1,8.20491e-05,8.70101e-06)" xlink:href="#b"></linearGradient>
<radialGradient id="f" fx="-0.0123102%" fy="-0.0135221%" cx="-0.000123102" cy="-0.000135221" r="0.981982" gradientTransform="matrix(0.897766,0,0,1.11388,0.194914,0.125151)" xlink:href="#a"></radialGradient>
<linearGradient id="g" x1="0.242009" x2="0.497717" y1="0.382812" y2="0.507812" gradientTransform="matrix(1,0,0,1,5.50934e-10,1.51001e-09)">
<stop offset="0%" stop-color="#CA536D" stop-opacity="0.99"></stop>
<stop offset="100%" stop-color="#A81837" stop-opacity="0.95"></stop>
</linearGradient>
</defs>
<g transform="scale(1.00011)">
<path fill="url(#a)" fill-rule="evenodd" stroke="#580400" stroke-width="11.905" d="M126.604,52.0403h51.3235v120.598h-51.3235Z"></path>
<path fill="none" fill-rule="evenodd" stroke="#154850" stroke-linejoin="round" stroke-width="11.905" d="M111.364,481.507c270.797,-1.602 272.4,0 272.4,0l-1.603,-227.534l-134.597,-132.995l-134.598,136.2c-1.603,1.602 1.42109e-14,222.727 -1.602,224.329Z" transform="matrix(1.07519,0,0,1.07519,-12.0839,-29.7941)"></path>
<path fill="url(#b)" fill-rule="evenodd" d="M117.773,475.097c59.287,0 59.287,-1.602 59.287,-1.602c0,0 0,-171.451 0,-171.451c0,0 -57.685,-43.264 -57.685,-43.264c-3.205,1.602 -1.602,217.92 -1.602,216.317Z" transform="matrix(1.07519,0,0,1.07519,-12.0839,-29.7941)"></path>
<path fill="url(#c)" fill-rule="evenodd" d="M117.773,258.78l124.983,-126.586l28.844,84.924l-94.54,84.926l-59.287,-43.264Z" transform="matrix(1.07519,0,0,1.07519,-12.0839,-29.7941)"></path>
<path fill="url(#d)" fill-rule="evenodd" d="M229.938,205.902l22.433,-75.31l123.381,124.983l-59.288,51.275l-86.526,-100.948Z" transform="matrix(1.07519,0,0,1.07519,-12.0839,-29.7941)"></path>
<path fill="url(#e)" fill-rule="evenodd" d="M314.862,475.098l-1.602,-173.054l64.094,-48.071l1.603,221.125h-64.095Z" transform="matrix(1.07519,0,0,1.07519,-12.0839,-29.7941)"></path>
<path fill="url(#f)" fill-rule="evenodd" stroke="#580400" stroke-linejoin="round" stroke-width="11.9213" d="M177.06,486.314l-1.602,-153.826c0,-36.854 20.029,-62.491 62.491,-62.491c44.065,0 65.697,30.444 65.697,62.491v153.826c0,0 -126.586,-1.602 -126.586,0Z" transform="matrix(1.07519,0,0,1.07519,-5.19257,-47.0224)"></path>
<path fill="url(#g)" fill-rule="evenodd" stroke="#580400" stroke-width="11.905" d="M63.293,303.646c150.621,-144.212 150.621,-144.212 150.621,-144.212c0,0 68.901,-1.602 70.503,-1.602c1.603,0 139.405,137.802 139.405,137.802c0,0 32.048,-33.649 32.048,-33.649c0,0 -206.704,-206.704 -206.704,-206.704c0,-1.42109e-14 -216.318,214.716 -216.318,214.716c7.10543e-15,0 30.4448,33.649 30.4448,33.649Z" transform="matrix(1.07519,0,0,1.07519,-12.0839,-29.7941)"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="800" height="800" version="1.1" viewBox="0 0 800 800" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!--Generated by IJSVG (https://github.com/iconjar/IJSVG)-->
<defs>
<linearGradient id="b" x1="0" x2="1" gradientUnits="userSpaceOnUse" y1="0" y2="0" gradientTransform="matrix(0,1,1,0,0,200)">
<stop offset="0%" stop-color="#D83352"></stop>
<stop offset="50%" stop-color="#F6DC7B"></stop>
<stop offset="100%" stop-color="#F6DC7B"></stop>
</linearGradient>
</defs>
<rect x="100" y="100" width="600" height="600" fill="url(#b)"></rect>
</svg>

Before

Width:  |  Height:  |  Size: 691 B

+19 -5
View File
@@ -1,6 +1,20 @@
<svg viewBox="-5 -5 10 10" xmlns="http://www.w3.org/2000/svg">
<rect x="-3" y="-3" width="6" height="6" />
<?xml version="1.0"?>
<svg width="120" height="120"
viewPort="0 0 120 120" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<rect x="-3" y="-3" width="6" height="6" fill="red"
transform="skewY(30)" />
</svg>
<line stroke-linecap="butt"
x1="30" y1="30" x2="30" y2="90"
stroke="black" stroke-width="20"/>
<line stroke-linecap="round"
x1="60" y1="30" x2="60" y2="90"
stroke="black" stroke-width="20"/>
<line stroke-linecap="square"
x1="90" y1="30" x2="90" y2="90"
stroke="black" stroke-width="20"/>
<path d="M30,30 L30,90 M60,30 L60,90 M90,30 L90,90"
stroke="white" />
</svg>

Before

Width:  |  Height:  |  Size: 203 B

After

Width:  |  Height:  |  Size: 593 B

-30
View File
@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="269" height="269" version="1.1" viewBox="0 0 269 269" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!--Generated by IJSVG (https://github.com/iconjar/IJSVG)-->
<defs>
<mask id="a" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox">
<use fill="#FFF" xlink:href="#d"></use>
</mask>
<linearGradient id="b" x1="0" x2="1" gradientUnits="userSpaceOnUse" y1="0" y2="0" gradientTransform="matrix(0,-197.994,-197.994,0,101.4,199.62)">
<stop offset="0%" stop-color="#D83352"></stop>
<stop offset="41.2669%" stop-color="#F6DC7B"></stop>
<stop offset="100%" stop-color="#F6DC7B"></stop>
</linearGradient>
<mask id="c" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox">
<path fill="#FFF" d="M0,202h202v-202h-202Z"></path>
</mask>
<path id="d" d="M2.404,100.624c0,-54.674 44.321,-98.998 98.995,-98.998v-4.88498e-15c54.675,0 98.997,44.324 98.997,98.998v0c0,54.674 -44.322,98.996 -98.997,98.996v0c-54.674,0 -98.995,-44.322 -98.995,-98.996"></path>
</defs>
<g transform="scale(0.998762)">
<g transform="matrix(1.33333,0,0,-1.33333,0,269.333)">
<use mask="url(#a)" fill="url(#b)" stroke="none" xlink:href="#d"></use>
<g mask="url(#c)">
<path fill="#231F20" stroke="none" d="M0,0c0,-6.725 -5.451,-12.175 -12.177,-12.175c-6.725,0 -12.176,5.45 -12.176,12.175c0,6.725 5.451,12.178 12.176,12.178c6.726,0 12.177,-5.453 12.177,-12.178" transform="matrix(1,0,0,1,75.0225,94.2754)"></path>
<path fill="none" stroke="#231F20" stroke-linecap="round" stroke-width="9" d="M0,0c14.428,-16.873 42.352,-15.393 42.352,-15.393" transform="matrix(1,0,0,1,41.2588,117.041)"></path>
<path fill="#231F20" stroke="none" d="M0,0c0,-6.725 -5.453,-12.176 -12.178,-12.176c-6.724,0 -12.176,5.451 -12.176,12.176c0,6.725 5.452,12.178 12.176,12.178c6.725,0 12.178,-5.453 12.178,-12.178" transform="matrix(1,0,0,1,146.952,94.3281)"></path>
<path fill="none" stroke="#231F20" stroke-linecap="round" stroke-width="9" d="M0,0c-14.428,-16.873 -42.352,-15.393 -42.352,-15.393" transform="matrix(1,0,0,1,161.54,117.094)"></path>
<path fill="none" stroke="#231F20" stroke-linecap="round" stroke-width="10" d="M0,0c29.782,24.805 58.656,-1.05 58.656,-1.05" transform="matrix(1,0,0,1,72.0713,41.6172)"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

+175
View File
@@ -0,0 +1,175 @@
//
// IJSVGImage.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGParser.h"
#import "IJSVGBezierPathAdditions.h"
#import "IJSVGLayerTree.h"
#import "IJSVGGroupLayer.h"
#import "IJSVGImageLayer.h"
#import "IJSVGExporter.h"
#import "IJSVGQuartzRenderer.h"
@class IJSVG;
void IJSVGBeginTransactionLock();
void IJSVGEndTransactionLock();
void IJSVGObtainTransactionLock(dispatch_block_t block, BOOL renderOnMainThread);
@protocol IJSVGDelegate <NSObject,IJSVGParserDelegate>
@optional
- (BOOL)svg:(IJSVG *)svg
shouldHandleForeignObject:(IJSVGForeignObject *)foreignObject;
- (void)svg:(IJSVG *)svg
handleForeignObject:(IJSVGForeignObject *)foreignObject
document:(NSXMLDocument *)document;
- (void)svg:(IJSVG *)svg
foundSubSVG:(IJSVG *)subSVG
withSVGString:(NSString *)subSVGString;
@end
typedef CGFloat (^IJSVGRenderingBackingScaleFactorHelper)();
typedef NS_ENUM(NSInteger, IJSVGRenderingEngine) {
IJSVGRenderingEngineCoreGraphics,
IJSVGRenderingEngineCoreAnimation
};
@interface IJSVG : NSObject <NSPasteboardWriting, IJSVGParserDelegate> {
@private
IJSVGParser * _group;
CGFloat _scale;
CGFloat _clipScale;
id<IJSVGDelegate> _delegate;
IJSVGLayer * _layerTree;
CGRect _viewBox;
CGSize _proposedViewSize;
CGFloat _lastProposedBackingScale;
CGFloat _backingScale;
NSMutableDictionary * _replacementColors;
IJSVGQuartzRenderer * _quartzRenderer;
struct {
unsigned int shouldHandleForeignObject: 1;
unsigned int handleForeignObject: 1;
unsigned int shouldHandleSubSVG: 1;
} _respondsTo;
}
// set this to be called when the layer is about to draw, it will call this
// and ask for the scale of the backing store where its going to be drawn
// and apply the scale to each layer that has custom drawing against it, mainly
// pattern and gradient layers
@property (nonatomic, copy) IJSVGRenderingBackingScaleFactorHelper renderingBackingScaleHelper;
// global overwriting rules for when rendering an SVG, this will overide any
// fillColor, strokeColor, pattern and gradient fill
@property (nonatomic, retain) NSColor * fillColor;
@property (nonatomic, retain) NSColor * strokeColor;
@property (nonatomic, assign) CGFloat strokeWidth;
@property (nonatomic, assign) IJSVGLineCapStyle lineCapStyle;
@property (nonatomic, assign) IJSVGLineJoinStyle lineJoinStyle;
@property (nonatomic, assign) IJSVGRenderingEngine renderingEngine;
@property (nonatomic, assign) BOOL clipToViewport;
- (void)prepForDrawingInView:(NSView *)view;
- (BOOL)isFont;
- (NSRect)viewBox;
- (NSArray<IJSVGPath *> *)glyphs;
- (NSString *)identifier;
- (IJSVGLayer *)layer;
- (IJSVGLayer *)layerWithTree:(IJSVGLayerTree *)tree;
- (NSArray<IJSVG *> *)subSVGs:(BOOL)recursive;
- (NSString *)SVGStringWithOptions:(IJSVGExporterOptions)options;
- (CGFloat)computeBackingScale:(CGFloat)scale;
- (void)discardDOM;
+ (id)svgNamed:(NSString *)string;
+ (id)svgNamed:(NSString *)string
delegate:(id<IJSVGDelegate>)delegate;
+ (id)svgNamed:(NSString *)string
useCache:(BOOL)useCache
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithImage:(NSImage *)image;
- (id)initWithSVGLayer:(IJSVGGroupLayer *)group
viewBox:(NSRect)viewBox;
- (id)initWithSVGString:(NSString *)string
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithSVGString:(NSString *)string;
- (id)initWithSVGString:(NSString *)string
error:(NSError **)error;
- (id)initWithFile:(NSString *)file
useCache:(BOOL)useCache;
- (id)initWithFile:(NSString *)file;
- (id)initWithFile:(NSString *)file
error:(NSError **)error;
- (id)initWithFile:(NSString *)file
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFile:(NSString *)file
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFile:(NSString *)file
useCache:(BOOL)useCache
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFilePathURL:(NSURL *)aURL;
- (id)initWithFilePathURL:(NSURL *)aURL
useCache:(BOOL)useCache;
- (id)initWithFilePathURL:(NSURL *)aURL
error:(NSError **)error;
- (id)initWithFilePathURL:(NSURL *)aURL
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFilePathURL:(NSURL *)aURL
useCache:(BOOL)useCache
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate;
- (NSImage *)imageWithSize:(NSSize)aSize;
- (NSImage *)imageWithSize:(NSSize)aSize
error:(NSError **)error;
- (NSImage *)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped;
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)size;
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)aSize
error:(NSError **)error;
- (BOOL)drawInRect:(NSRect)rect;
- (BOOL)drawInRect:(NSRect)rect
error:(NSError **)error;
- (void)drawInRect:(NSRect)rect
context:(CGContextRef)context;
- (NSData *)PDFData;
- (NSData *)PDFData:(NSError **)error;
- (NSData *)PDFDataWithRect:(NSRect)rect;
- (NSData *)PDFDataWithRect:(NSRect)rect
error:(NSError **)error;
- (void)beginVectorDraw;
- (void)endVectorDraw;
// colors
- (NSArray<NSColor *> *)visibleColors;
- (void)setReplacementColors:(NSDictionary<NSColor *, NSColor *> *)colors;
- (void)removeReplacementColor:(NSColor *)color;
- (void)replaceColor:(NSColor *)color
withColor:(NSColor *)newColor;
- (void)removeAllReplacementColors;
@end
+931
View File
@@ -0,0 +1,931 @@
//
// IJSVGImage.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGCache.h"
#import "IJSVGTransaction.h"
#import "IJSVGExporter.h"
@implementation IJSVG
@synthesize fillColor;
@synthesize strokeColor;
@synthesize strokeWidth;
@synthesize lineCapStyle;
@synthesize lineJoinStyle;
@synthesize renderingBackingScaleHelper;
@synthesize renderingEngine;
@synthesize clipToViewport;
- (void)dealloc
{
[renderingBackingScaleHelper release], renderingBackingScaleHelper = nil;
[fillColor release], fillColor = nil;
[strokeColor release], strokeColor = nil;
[_group release], _group = nil;
[_layerTree release], _layerTree = nil;
[_replacementColors release], _replacementColors = nil;
[_quartzRenderer release], _quartzRenderer = nil;
[super dealloc];
}
+ (id)svgNamed:(NSString *)string
error:(NSError **)error
{
return [[self class] svgNamed:string
error:error
delegate:nil];
}
+ (id)svgNamed:(NSString *)string
{
return [[self class] svgNamed:string
error:nil];
}
+ (id)svgNamed:(NSString *)string
useCache:(BOOL)useCache
delegate:(id<IJSVGDelegate>)delegate
{
return [[self class] svgNamed:string
useCache:useCache
error:nil
delegate:delegate];
}
+ (id)svgNamed:(NSString *)string
delegate:(id<IJSVGDelegate>)delegate
{
return [[self class] svgNamed:string
error:nil
delegate:delegate];
}
+ (id)svgNamed:(NSString *)string
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate
{
return [self svgNamed:string
useCache:YES
error:error
delegate:delegate];
}
+ (id)svgNamed:(NSString *)string
useCache:(BOOL)useCache
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate
{
NSBundle * bundle = [NSBundle mainBundle];
NSString * str = nil;
NSString * ext = [string pathExtension];
if( ext == nil || ext.length == 0 ) {
ext = @"svg";
}
if( ( str = [bundle pathForResource:[string stringByDeletingPathExtension] ofType:ext] ) != nil ) {
return [[[self alloc] initWithFile:str
useCache:useCache
error:error
delegate:delegate] autorelease];
}
return nil;
}
- (id)initWithImage:(NSImage *)image
{
__block IJSVGGroupLayer * layer = nil;
__block IJSVGImageLayer * imageLayer = nil;
// make sure we obtain a lock, with whatever we do with layers!
IJSVGObtainTransactionLock(^{
// create the layers we require
layer = [[[IJSVGGroupLayer alloc] init] autorelease];
imageLayer = [[[IJSVGImageLayer alloc] initWithImage:image] autorelease];
[layer addSublayer:imageLayer];
}, NO);
// return the initialized SVG
return [self initWithSVGLayer:layer
viewBox:imageLayer.frame];
}
- (id)initWithSVGLayer:(IJSVGGroupLayer *)group
viewBox:(NSRect)viewBox
{
// this completely bypasses passing of files
if((self = [super init]) != nil) {
// keep the layer tree
_layerTree = [group retain];
_viewBox = viewBox;
// any setups
[self _setupBasicsFromAnyInitializer];
}
return self;
}
- (id)initWithFile:(NSString *)file
{
return [self initWithFile:file
delegate:nil];
}
- (id)initWithFile:(NSString *)file
useCache:(BOOL)useCache
{
return [self initWithFile:file
useCache:useCache
error:nil
delegate:nil];
}
- (id)initWithFile:(NSString *)file
useCache:(BOOL)useCache
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate
{
return [self initWithFilePathURL:[NSURL fileURLWithPath:file]
useCache:useCache
error:error
delegate:delegate];
}
- (id)initWithFile:(NSString *)file
error:(NSError **)error
{
return [self initWithFile:file
error:error
delegate:nil];
}
- (id)initWithFile:(NSString *)file
delegate:(id<IJSVGDelegate>)delegate
{
return [self initWithFile:file
error:nil
delegate:delegate];
}
- (id)initWithFile:(NSString *)file
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate
{
return [self initWithFilePathURL:[NSURL fileURLWithPath:file]
useCache:YES
error:error
delegate:delegate];
}
- (id)initWithFilePathURL:(NSURL *)aURL
{
return [self initWithFilePathURL:aURL
useCache:YES
error:nil
delegate:nil];
}
- (id)initWithFilePathURL:(NSURL *)aURL
error:(NSError **)error
{
return [self initWithFilePathURL:aURL
useCache:YES
error:error
delegate:nil];
}
- (id)initWithFilePathURL:(NSURL *)aURL
useCache:(BOOL)useCache
{
return [self initWithFilePathURL:aURL
useCache:useCache
error:nil
delegate:nil];
}
- (id)initWithFilePathURL:(NSURL *)aURL
delegate:(id<IJSVGDelegate>)delegate
{
return [self initWithFilePathURL:aURL
useCache:YES
error:nil
delegate:delegate];
}
- (id)initWithFilePathURL:(NSURL *)aURL
useCache:(BOOL)useCache
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate
{
#ifndef __clang_analyzer__
// check the cache first
if( useCache && [IJSVGCache enabled] ) {
IJSVG * svg = nil;
if( ( svg = [IJSVGCache cachedSVGForFileURL:aURL] ) != nil ) {
// have to release, as this was called from an alloc..!
[self release];
return [svg retain];
}
}
// create the object
if( ( self = [super init] ) != nil ) {
NSError * anError = nil;
_delegate = delegate;
// this is a really quick check against the delegate
// for methods that exist
[self _checkDelegate];
// create the group
_group = [[IJSVGParser groupForFileURL:aURL
error:&anError
delegate:self] retain];
[self _setupBasicInfoFromGroup];
[self _setupBasicsFromAnyInitializer];
// something went wrong...
if( _group == nil ) {
if( error != NULL ) {
*error = anError;
}
[self release], self = nil;
return nil;
}
// cache the file
if( useCache && [IJSVGCache enabled] ) {
[IJSVGCache cacheSVG:self
fileURL:aURL];
}
}
#endif
return self;
}
- (id)initWithSVGString:(NSString *)string
{
return [self initWithSVGString:string
error:nil
delegate:nil];
}
- (id)initWithSVGString:(NSString *)string
error:(NSError **)error
{
return [self initWithSVGString:string
error:error
delegate:nil];
}
- (id)initWithSVGString:(NSString *)string
error:(NSError **)error
delegate:(id<IJSVGDelegate>)delegate
{
if((self = [super init]) != nil) {
// this is basically the same as init with URL just
// bypasses the loading of a file
NSError * anError = nil;
_delegate = delegate;
[self _checkDelegate];
// setup the parser
_group = [[IJSVGParser alloc] initWithSVGString:string
error:&anError
delegate:self];
[self _setupBasicInfoFromGroup];
[self _setupBasicsFromAnyInitializer];
// something went wrong :(
if(_group == nil) {
if(error != NULL) {
*error = anError;
}
[self release], self = nil;
return nil;
}
}
return self;
}
- (void)discardDOM
{
// if we discard, we can no longer create a tree, so lets create tree
// upfront before we kill anything
[self layer];
// now clear memory
[_group release], _group = nil;
}
- (void)_setupBasicInfoFromGroup
{
// store the viewbox
_viewBox = _group.viewBox;
_proposedViewSize = _group.proposedViewSize;
}
- (void)_setupBasicsFromAnyInitializer
{
renderingEngine = IJSVGRenderingEngineCoreAnimation;
self.clipToViewport = YES;
// setup low level backing scale
_lastProposedBackingScale = 0.f;
self.renderingBackingScaleHelper = ^CGFloat{
return 1.f;
};
}
- (NSString *)identifier
{
return _group.identifier;
}
- (void)_checkDelegate
{
_respondsTo.shouldHandleForeignObject = [_delegate respondsToSelector:@selector(svg:shouldHandleForeignObject:)];
_respondsTo.handleForeignObject = [_delegate respondsToSelector:@selector(svg:handleForeignObject:document:)];
_respondsTo.shouldHandleSubSVG = [_delegate respondsToSelector:@selector(svg:foundSubSVG:withSVGString:)];
}
- (NSRect)viewBox
{
return _viewBox;
}
- (BOOL)isFont
{
return [_group isFont];
}
- (NSArray<IJSVGPath *> *)glyphs
{
return [_group glyphs];
}
- (NSArray<IJSVG *> *)subSVGs:(BOOL)recursive
{
return [_group subSVGs:recursive];
}
- (NSString *)SVGStringWithOptions:(IJSVGExporterOptions)options
{
IJSVGExporter * exporter = [[[IJSVGExporter alloc] initWithSVG:self
size:self.viewBox.size
options:options] autorelease];
return [exporter SVGString];
}
- (NSImage *)imageWithSize:(NSSize)aSize
{
return [self imageWithSize:aSize
flipped:NO
error:nil];
}
- (NSImage *)imageWithSize:(NSSize)aSize
error:(NSError **)error;
{
return [self imageWithSize:aSize
flipped:NO
error:error];
}
- (NSImage *)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped
{
return [self imageWithSize:aSize
flipped:flipped
error:nil];
}
- (NSImage *)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped
error:(NSError **)error
{
NSImage * im = [[[NSImage alloc] initWithSize:aSize] autorelease];
[im lockFocus];
CGContextRef ref = [[NSGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(ref);
if(flipped) {
CGContextTranslateCTM(ref, 0.f, aSize.height);
CGContextScaleCTM(ref, 1.f, -1.f);
}
[self drawAtPoint:NSMakePoint( 0.f, 0.f )
size:aSize
error:error];
CGContextRestoreGState(ref);
[im unlockFocus];
return im;
}
- (NSData *)PDFData
{
return [self PDFData:nil];
}
- (NSData *)PDFData:(NSError **)error
{
return [self PDFDataWithRect:(NSRect){
.origin=NSZeroPoint,
.size=_viewBox.size
} error:error];
}
- (NSData *)PDFDataWithRect:(NSRect)rect
{
return [self PDFDataWithRect:rect
error:nil];
}
- (NSData *)PDFDataWithRect:(NSRect)rect
error:(NSError **)error
{
// create the data for the PDF
NSMutableData * data = [[[NSMutableData alloc] init] autorelease];
// assign the data to the consumer
CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)data);
const CGRect box = CGRectMake( rect.origin.x, rect.origin.y,
rect.size.width, rect.size.height );
// create the context
CGContextRef context = CGPDFContextCreate( dataConsumer, &box, NULL );
CGContextBeginPage( context, &box );
// the context is currently upside down, doh! flip it...
CGContextScaleCTM( context, 1, -1 );
CGContextTranslateCTM( context, 0, -box.size.height);
// make sure we set the masks to path bits n bobs
[self _beginVectorDraw]; {
// draw the icon
[self _drawInRect:(NSRect)box
context:context
error:error];
} [self _endVectorDraw];
CGContextEndPage(context);
//clean up
CGPDFContextClose(context);
CGContextRelease(context);
CGDataConsumerRelease(dataConsumer);
return data;
}
- (void)endVectorDraw
{
[self _endVectorDraw];
}
- (void)beginVectorDraw
{
[self _beginVectorDraw];
}
- (void)_beginVectorDraw
{
// turn on converts masks to PDF's
// as PDF context and layer masks dont work
void (^block)(CALayer * layer, BOOL isMask) = ^void (CALayer * layer, BOOL isMask) {
((IJSVGLayer *)layer).convertMasksToPaths = YES;
};
[IJSVGLayer recursivelyWalkLayer:self.layer
withBlock:block];
}
- (void)_endVectorDraw
{
// turn of convert masks to paths as not
// needed for generic rendering
void (^block)(CALayer * layer, BOOL isMask) = ^void (CALayer * layer, BOOL isMask) {
((IJSVGLayer *)layer).convertMasksToPaths = NO;
};
[IJSVGLayer recursivelyWalkLayer:self.layer
withBlock:block];
}
- (void)prepForDrawingInView:(NSView *)view
{
// kill the render
if(view == nil) {
self.renderingBackingScaleHelper = nil;
return;
}
// construct the layer before drawing
[self layer];
// set the scale
__block NSView * weakView = view;
self.renderingBackingScaleHelper = ^CGFloat{
return weakView.window.screen.backingScaleFactor;
};
}
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)aSize
{
return [self drawAtPoint:point
size:aSize
error:nil];
}
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)aSize
error:(NSError **)error
{
return [self drawInRect:NSMakeRect( point.x, point.y, aSize.width, aSize.height )
error:error];
}
- (BOOL)drawInRect:(NSRect)rect
{
return [self drawInRect:rect
error:nil];
}
- (BOOL)drawInRect:(NSRect)rect
error:(NSError **)error
{
return [self _drawInRect:rect
context:[[NSGraphicsContext currentContext] graphicsPort]
error:error];
}
- (CGFloat)computeBackingScale:(CGFloat)actualScale
{
_backingScale = actualScale;
return (CGFloat)(_scale + actualScale);
}
- (NSRect)computeRectDrawingInRect:(NSRect)rect
isValid:(BOOL *)valid
{
// we also need to calculate the viewport so we can clip
// the drawing if needed
NSRect viewPort = NSZeroRect;
viewPort.origin.x = round((rect.size.width/2-(_proposedViewSize.width/2)*_clipScale) + rect.origin.x);
viewPort.origin.y = round((rect.size.height/2-(_proposedViewSize.height/2)*_clipScale) + rect.origin.y);
viewPort.size.width = _proposedViewSize.width*_clipScale;
viewPort.size.height = _proposedViewSize.height*_clipScale;
// 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 )
{
*valid = NO;
return NSZeroRect;
}
*valid = YES;
return viewPort;
}
- (void)drawInRect:(NSRect)rect
context:(CGContextRef)context
{
[self _drawInRect:rect
context:context
error:nil];
}
- (BOOL)_drawInRect:(NSRect)rect
context:(CGContextRef)ref
error:(NSError **)error
{
// prep for draw...
@synchronized (self) {
CGContextSaveGState(ref);
@try {
[self _beginDraw:rect];
// we also need to calculate the viewport so we can clip
// the drawing if needed
BOOL canDraw = NO;
NSRect viewPort = [self computeRectDrawingInRect:rect isValid:&canDraw];
// check the viewport
if( !canDraw ) {
if( error != NULL ) {
*error = [[[NSError alloc] initWithDomain:IJSVGErrorDomain
code:IJSVGErrorDrawing
userInfo:nil] autorelease];
}
CGContextRestoreGState(ref);
return NO;
}
// clip to mask
if(self.clipToViewport == YES) {
CGContextClipToRect( ref, viewPort);
}
// add the origin back onto the viewport
viewPort.origin.x -= round((_viewBox.origin.x)*_scale);
viewPort.origin.y -= round((_viewBox.origin.y)*_scale);
viewPort = CGRectIntegral(viewPort);
// transforms
CGContextTranslateCTM( ref, viewPort.origin.x, viewPort.origin.y);
CGContextScaleCTM( ref, _scale, _scale );
// render the layer, its really important we lock
// the transaction when drawing
IJSVGBeginTransactionLock();
// do we need to update the backing scales on the
// layers?
if(self.renderingBackingScaleHelper != nil) {
[self _askHelperForBackingScale];
}
// render the layers
switch(self.renderingEngine) {
// CoreGraphics / Quartz
case IJSVGRenderingEngineCoreGraphics: {
if(_quartzRenderer == nil) {
// init the renderer if its not already defined
_quartzRenderer = [[IJSVGQuartzRenderer alloc] init];
}
_quartzRenderer.scale = _scale;
_quartzRenderer.backingScale = _backingScale;
_quartzRenderer.viewPort = viewPort;
// render it
[_quartzRenderer renderLayer:self.layer
inContext:ref];
break;
}
// CALayer tree
case IJSVGRenderingEngineCoreAnimation: {
[self.layer renderInContext:ref];
}
}
IJSVGEndTransactionLock();
}
@catch (NSException *exception) {
// just catch and give back a drawing error to the caller
if( error != NULL )
*error = [[[NSError alloc] initWithDomain:IJSVGErrorDomain
code:IJSVGErrorDrawing
userInfo:nil] autorelease];
}
@finally {
CGContextRestoreGState(ref);
}
}
return (error == nil);
}
- (void)_askHelperForBackingScale
{
CGFloat scale = (self.renderingBackingScaleHelper)();
if(scale < 1.f) {
scale = 1.f;
}
// dont do anything, nothing has changed, no point of iterating over
// every layer for no reason!
if(scale == _lastProposedBackingScale) {
return;
}
_lastProposedBackingScale = scale;
// walk the tree
void (^block)(CALayer * layer, BOOL isMask) = ^void (CALayer * layer, BOOL isMask) {
IJSVGLayer * propLayer = ((IJSVGLayer *)layer);
if(propLayer.requiresBackingScaleHelp == YES) {
propLayer.backingScaleFactor = scale;
}
};
// gogogo
[IJSVGLayer recursivelyWalkLayer:self.layer
withBlock:block];
}
- (void)setFillColor:(NSColor *)aColor
{
if(fillColor != nil) {
[fillColor release], fillColor = nil;
}
fillColor = [aColor retain];
[_layerTree release], _layerTree = nil;
}
- (void)setStrokeColor:(NSColor *)aColor
{
if(strokeColor != nil) {
[strokeColor release], strokeColor = nil;
}
strokeColor = [aColor retain];
[_layerTree release], _layerTree = nil;
}
- (void)setStrokeWidth:(CGFloat)aWidth
{
strokeWidth = aWidth;
[_layerTree release], _layerTree = nil;
}
- (void)setLineCapStyle:(IJSVGLineCapStyle)aLineCapStyle
{
lineCapStyle = aLineCapStyle;
[_layerTree release], _layerTree = nil;
}
- (void)setLineJoinStyle:(IJSVGLineJoinStyle)aLineJoinStyle
{
lineJoinStyle = aLineJoinStyle;
[_layerTree release], _layerTree = nil;
}
- (IJSVGLayer *)layerWithTree:(IJSVGLayerTree *)tree
{
// clear memory
if(_layerTree != nil) {
[_layerTree release], _layerTree = nil;
}
// force rebuild of the tree
IJSVGBeginTransactionLock();
_layerTree = [[tree layerForNode:_group] retain];
IJSVGEndTransactionLock();
return _layerTree;
}
- (IJSVGLayer *)layer
{
if(_layerTree != nil) {
return _layerTree;
}
// create the renderer and assign default values
// from this SVG object
IJSVGLayerTree * renderer = [[[IJSVGLayerTree alloc] init] autorelease];
renderer.viewBox = self.viewBox;
renderer.fillColor = self.fillColor;
renderer.strokeColor = self.strokeColor;
renderer.strokeWidth = self.strokeWidth;
renderer.lineCapStyle = self.lineCapStyle;
renderer.lineJoinStyle = self.lineJoinStyle;
renderer.replacementColors = _replacementColors;
// return the rendered layer
return [self layerWithTree:renderer];
}
- (NSArray<NSColor *> *)visibleColors
{
// set for the colors
NSMutableSet * colors = [[[NSMutableSet alloc] init] autorelease];
// block to find colors in stroke and fill
void (^block)(CALayer * layer, BOOL isMask) = ^void (CALayer * layer, BOOL isMask) {
if([layer isKindOfClass:[IJSVGShapeLayer class]] && isMask == NO) {
IJSVGShapeLayer * sLayer = (IJSVGShapeLayer *)layer;
NSColor * color = nil;
if(sLayer.fillColor != nil) {
color = [NSColor colorWithCGColor:sLayer.fillColor];
if(color.alphaComponent != 0.f) {
[colors addObject:color];
}
}
if(sLayer.strokeColor != nil) {
color = [NSColor colorWithCGColor:sLayer.strokeColor];
if(color.alphaComponent != 0.f) {
[colors addObject:color];
}
}
}
};
// walk
[IJSVGLayer recursivelyWalkLayer:self.layer
withBlock:block];
// return the colours!
return colors.allObjects;
}
- (void)removeAllReplacementColors
{
[_replacementColors release], _replacementColors = nil;
}
- (void)removeReplacementColor:(NSColor *)color
{
if(_replacementColors == nil) {
return;
}
[_replacementColors removeObjectForKey:[IJSVGColor computeColorSpace:color]];
}
- (void)replaceColor:(NSColor *)color
withColor:(NSColor *)newColor
{
if(_replacementColors == nil) {
_replacementColors = [[NSMutableDictionary alloc] init];
}
color = [IJSVGColor computeColorSpace:color];
newColor = [IJSVGColor computeColorSpace:newColor];
_replacementColors[color] = newColor;
[_layerTree release], _layerTree = nil;
}
- (void)setReplacementColors:(NSDictionary<NSColor *, NSColor *> *)colors
{
if(_replacementColors != nil) {
[_replacementColors release], _replacementColors = nil;
}
for(NSColor * oldColor in colors) {
[self replaceColor:oldColor
withColor:colors[oldColor]];
}
}
- (void)_beginDraw:(NSRect)rect
{
// in order to correctly fit the the SVG into the
// rect, we need to work out the ratio scale in order
// to transform the paths into our viewbox
NSSize dest = rect.size;
NSSize source = _viewBox.size;
_clipScale = MIN(dest.width/_proposedViewSize.width,
dest.height/_proposedViewSize.height);
// work out the actual scale based on the clip scale
CGFloat w = _proposedViewSize.width*_clipScale;
CGFloat h = _proposedViewSize.height*_clipScale;
_scale = MIN(w/source.width,h/source.height);
}
#pragma mark NSPasteboard
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard
{
return @[NSPasteboardTypePDF];
}
- (id)pasteboardPropertyListForType:(NSString *)type
{
if( [type isEqualToString:NSPasteboardTypePDF] ) {
return [self PDFData];
}
return nil;
}
#pragma mark IJSVGParserDelegate
- (void)svgParser:(IJSVGParser *)svg
foundSubSVG:(IJSVG *)subSVG
withSVGString:(NSString *)string
{
if(_delegate != nil && _respondsTo.shouldHandleSubSVG == 1) {
[_delegate svg:self
foundSubSVG:subSVG
withSVGString:string];
}
}
- (BOOL)svgParser:(IJSVGParser *)parser
shouldHandleForeignObject:(IJSVGForeignObject *)foreignObject
{
if( _delegate != nil && _respondsTo.shouldHandleForeignObject == 1 ) {
return [_delegate svg:self shouldHandleForeignObject:foreignObject];
}
return NO;
}
- (void)svgParser:(IJSVGParser *)parser
handleForeignObject:(IJSVGForeignObject *)foreignObject
document:(NSXMLDocument *)document
{
if( _delegate != nil && _respondsTo.handleForeignObject == 1 ) {
[_delegate svg:self
handleForeignObject:foreignObject
document:document];
}
}
@end
+16
View File
@@ -0,0 +1,16 @@
//
// IJSVGBezierPathAdditions.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSBezierPath (IJSVGAdditions)
- (void)addQuadCurveToPoint:(NSPoint)aPoint
controlPoint:(NSPoint)cp;
@end
+26
View File
@@ -0,0 +1,26 @@
//
// 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];
}
@end
+25
View File
@@ -0,0 +1,25 @@
//
// IJSVGCache.h
// IconJar
//
// Created by Curtis Hard on 02/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <sys/stat.h>
#import "IJSVG.h"
@interface IJSVGCache : NSObject {
}
+ (IJSVG *)cachedSVGForFileURL:(NSURL *)aURL;
+ (void)cacheSVG:(IJSVG *)svg fileURL:(NSURL *)aURL;
+ (void)flushCache;
+ (BOOL)enabled;
+ (void)setEnabled:(BOOL)flag;
+ (void)purgeCachedSVGForFileURL:(NSURL *)aURL;
+ (void)setEvictItemsAfter:(NSInteger)count;
@end
+77
View File
@@ -0,0 +1,77 @@
//
// IJSVGCache.m
// IconJar
//
// Created by Curtis Hard on 02/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCache.h"
#import <malloc/malloc.h>
@implementation IJSVGCache
static NSInteger _maxCacheItems = 20;
static NSCache * _cache = nil;
static BOOL _enabled = YES;
+ (void)load
{
[self setEnabled:_enabled];
}
+ (void)setEvictItemsAfter:(NSInteger)count
{
_maxCacheItems = count;
[_cache setTotalCostLimit:_maxCacheItems];
}
+ (IJSVG *)cachedSVGForFileURL:(NSURL *)aURL
{
if( ![[self class] enabled] || _cache == nil )
return nil;
IJSVG * svg = nil;
if( ( svg = [_cache objectForKey:aURL] ) == nil )
return nil;
return svg;
}
+ (void)purgeCachedSVGForFileURL:(NSURL *)aURL
{
[_cache removeObjectForKey:aURL];
}
+ (void)cacheSVG:(IJSVG *)svg
fileURL:(NSURL *)aURL
{
[_cache setObject:svg
forKey:aURL
cost:1];
}
+ (void)setEnabled:(BOOL)flag
{
_enabled = flag;
if( !flag ) {
[[self class] flushCache];
return;
}
// create a new cache if allowed
if( _cache == nil ) {
_cache = [[NSCache alloc] init];
[_cache setTotalCostLimit:_maxCacheItems];
}
}
+ (BOOL)enabled
{
return _enabled;
}
+ (void)flushCache
{
[_cache removeAllObjects];
}
@end
@@ -6,18 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
typedef NS_OPTIONS(NSInteger, IJSVGColorStringOptions) {
IJSVGColorStringOptionNone = 1 << 0,
IJSVGColorStringOptionForceHEX = 1 << 1,
IJSVGColorStringOptionAllowShortHand = 1 << 2,
IJSVGColorStringOptionAllowRRGGBBAA = 1 << 3,
IJSVGColorStringOptionDefault = IJSVGColorStringOptionAllowShortHand
};
typedef NS_ENUM(NSInteger, IJSVGPredefinedColor) {
typedef NS_ENUM( NSInteger, IJSVGPredefinedColor ) {
IJSVGColorAliceblue,
IJSVGColorAntiquewhite,
IJSVGColorAqua,
@@ -167,33 +158,24 @@ typedef NS_ENUM(NSInteger, IJSVGPredefinedColor) {
IJSVGColorYellowgreen
};
extern NSString* const IJSVGColorCurrentColorName;
@interface IJSVGColor : NSObject
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness);
CGFloat * IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness);
+ (NSColor*)computeColorSpace:(NSColor*)color;
+ (NSColorSpace*)defaultColorSpace;
+ (BOOL)isColor:(NSString*)string;
+ (NSString*)colorStringFromColor:(NSColor*)color
options:(IJSVGColorStringOptions)options;
+ (NSString*)colorStringFromColor:(NSColor*)color;
+ (NSColor*)colorFromHEXInteger:(NSInteger)hex;
+ (NSColor*)computeColor:(id)colour;
+ (NSColor*)colorFromString:(NSString*)string;
+ (NSColor*)colorFromHEXString:(NSString*)string;
+ (NSColor*)colorFromHEXString:(NSString*)string
containsAlphaComponent:(BOOL*)containsAlphaComponent;
+ (BOOL)HEXContainsAlphaComponent:(NSUInteger)hex;
+ (unsigned long)lengthOfHEXInteger:(NSUInteger)hex;
+ (NSColor*)colorFromRString:(NSString*)rString
gString:(NSString*)gString
bString:(NSString*)bString
aString:(NSString*)aString;
+ (NSColor*)colorFromPredefinedColorName:(NSString*)name;
+ (NSString*)colorNameFromPredefinedColor:(IJSVGPredefinedColor)color;
+ (NSColor*)changeAlphaOnColor:(NSColor*)color
to:(CGFloat)alphaValue;
+ (NSColor *)computeColorSpace:(NSColor *)color;
+ (NSColorSpace *)defaultColorSpace;
+ (BOOL)isColor:(NSString *)string;
+ (NSString *)colorStringFromColor:(NSColor *)color
forceHex:(BOOL)forceHex
allowShorthand:(BOOL)allowShorthand;
+ (NSString *)colorStringFromColor:(NSColor *)color;
+ (NSColor *)computeColor:(id)colour;
+ (NSColor *)colorFromString:(NSString *)string;
+ (NSColor *)colorFromHEXString:(NSString *)string
alpha:(CGFloat)alpha;
+ (NSColor *)colorFromPredefinedColorName:(NSString *)name;
+ (NSString *)colorNameFromPredefinedColor:(IJSVGPredefinedColor)color;
+ (NSColor *)changeAlphaOnColor:(NSColor *)color
to:(CGFloat)alphaValue;
@end
+700
View File
@@ -0,0 +1,700 @@
//
// IJSVGColor.m
// IconJar
//
// Created by Curtis Hard on 31/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGColor.h"
#import "IJSVGUtils.h"
@implementation IJSVGColor
static NSDictionary * _colorTree = nil;
CGFloat * IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness)
{
hue *= (1.f/360.f);
hue = (hue - floorf(hue));
saturation *= 0.01;
lightness *= 0.01;
lightness *= 2.f;
CGFloat s = saturation * ((lightness < 1.f) ? lightness : (2.f - lightness));
CGFloat brightness = (lightness + s) * .5f;
if(s != 0.f) {
s = (2.f * s) / (lightness + s);
}
CGFloat * floats = (CGFloat *)malloc(3*sizeof(CGFloat));
floats[0] = hue;
floats[1] = s;
floats[2] = brightness;
return floats;
};
+ (void)load
{
[[self class] _generateTree];
}
+ (NSColorSpace *)defaultColorSpace
{
return [NSColorSpace deviceRGBColorSpace];
}
+ (NSColor *)computeColorSpace:(NSColor *)color
{
NSColorSpace * space = [self defaultColorSpace];
if(color.colorSpace != space) {
color = [color colorUsingColorSpace:space];
}
return color;
}
+ (void)_generateTree
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_colorTree = [@{
@"aliceblue":@"f0f8ff",
@"antiquewhite":@"faebd7",
@"aqua":@"00ffff",
@"aquamarine":@"7fffd4",
@"azure":@"f0ffff",
@"beige":@"f5f5dc",
@"bisque":@"ffe4c4",
@"black":@"000000",
@"blanchedalmond":@"ffebcd",
@"blue":@"0000ff",
@"blueviolet":@"8a2be2",
@"brown":@"a52a2a",
@"burlywood":@"deb887",
@"cadetblue":@"5f9ea0",
@"chartreuse":@"7fff00",
@"chocolate":@"d2691e",
@"coral":@"ff7f50",
@"cornflowerblue":@"6495ed",
@"cornsilk":@"fff8dc",
@"crimson":@"dc143c",
@"currentcolor":@"000000",
@"cyan":@"00ffff",
@"darkblue":@"00008b",
@"darkcyan":@"008b8b",
@"darkgoldenrod":@"b8860b",
@"darkgray":@"a9a9a9",
@"darkgreen":@"006400",
@"darkgrey":@"a9a9a9",
@"darkkhaki":@"bdb76b",
@"darkmagenta":@"8b008b",
@"darkolivegreen":@"556b2f",
@"darkorange":@"ff8c00",
@"darkorchid":@"9932cc",
@"darkred":@"8b0000",
@"darksalmon":@"e9967a",
@"darkseagreen":@"8fbc8f",
@"darkslateblue":@"483d8b",
@"darkslategray":@"2f4f4f",
@"darkslategrey":@"2f4f4f",
@"darkturquoise":@"00ced1",
@"darkviolet":@"9400d3",
@"deeppink":@"ff1493",
@"deepskyblue":@"00bfff",
@"dimgray":@"696969",
@"dimgrey":@"696969",
@"dodgerblue":@"1e90ff",
@"firebrick":@"b22222",
@"floralwhite":@"fffaf0",
@"forestgreen":@"228b22",
@"fuchsia":@"ff00ff",
@"gainsboro":@"dcdcdc",
@"ghostwhite":@"f8f8ff",
@"gold":@"ffd700",
@"goldenrod":@"daa520",
@"gray":@"808080",
@"green":@"008000",
@"greenyellow":@"adff2f",
@"grey":@"808080",
@"honeydew":@"f0fff0",
@"hotpink":@"ff69b4",
@"indianred":@"cd5c5c",
@"indigo":@"4b0082",
@"ivory":@"fffff0",
@"khaki":@"f0e68c",
@"lavender":@"e6e6fa",
@"lavenderblush":@"fff0f5",
@"lawngreen":@"7cfc00",
@"lemonchiffon":@"fffacd",
@"lightblue":@"add8e6",
@"lightcoral":@"f08080",
@"lightcyan":@"e0ffff",
@"lightgoldenrodyellow":@"fafad2",
@"lightgray":@"d3d3d3",
@"lightgreen":@"90ee90",
@"lightgrey":@"d3d3d3",
@"lightpink":@"ffb6c1",
@"lightsalmon":@"ffa07a",
@"lightseagreen":@"20b2aa",
@"lightskyblue":@"87cefa",
@"lightslategray":@"778899",
@"lightslategrey":@"778899",
@"lightsteelblue":@"b0c4de",
@"lightyellow":@"ffffe0",
@"lime":@"00ff00",
@"limegreen":@"32cd32",
@"linen":@"faf0e6",
@"magenta":@"ff00ff",
@"maroon":@"800000",
@"mediumaquamarine":@"66cdaa",
@"mediumblue":@"0000cd",
@"mediumorchid":@"ba55d3",
@"mediumpurple":@"9370db",
@"mediumseagreen":@"3cb371",
@"mediumslateblue":@"7b68ee",
@"mediumspringgreen":@"00fa9a",
@"mediumturquoise":@"48d1cc",
@"mediumvioletred":@"c71585",
@"midnightblue":@"191970",
@"mintcream":@"f5fffa",
@"mistyrose":@"ffe4e1",
@"moccasin":@"ffe4b5",
@"navajowhite":@"ffdead",
@"navy":@"000080",
@"oldlace":@"fdf5e6",
@"olive":@"808000",
@"olivedrab":@"6b8e23",
@"orange":@"ffa500",
@"orangered":@"ff4500",
@"orchid":@"da70d6",
@"palegoldenrod":@"eee8aa",
@"palegreen":@"98fb98",
@"paleturquoise":@"afeeee",
@"palevioletred":@"db7093",
@"papayawhip":@"ffefd5",
@"peachpuff":@"ffdab9",
@"peru":@"cd853f",
@"pink":@"ffc0cb",
@"plum":@"dda0dd",
@"powderblue":@"b0e0e6",
@"purple":@"800080",
@"red":@"ff0000",
@"rosybrown":@"bc8f8f",
@"royalblue":@"4169e1",
@"saddlebrown":@"8b4513",
@"salmon":@"fa8072",
@"sandybrown":@"f4a460",
@"seagreen":@"2e8b57",
@"seashell":@"fff5ee",
@"sienna":@"a0522d",
@"silver":@"c0c0c0",
@"skyblue":@"87ceeb",
@"slateblue":@"6a5acd",
@"slategray":@"708090",
@"slategrey":@"708090",
@"snow":@"fffafa",
@"springgreen":@"00ff7f",
@"steelblue":@"4682b4",
@"tan":@"d2b48c",
@"teal":@"008080",
@"thistle":@"d8bfd8",
@"tomato":@"ff6347",
@"turquoise":@"40e0d0",
@"violet":@"ee82ee",
@"wheat":@"f5deb3",
@"white":@"ffffff",
@"whitesmoke":@"f5f5f5",
@"yellow":@"ffff00",
@"yellowgreen":@"9acd32"
} retain];
});
}
+ (NSColor *)computeColor:(id)colour
{
if( [colour isKindOfClass:[NSColor class]] )
return colour;
return nil;
}
+ (NSColor *)colorFromString:(NSString *)string
{
NSCharacterSet * set = NSCharacterSet.whitespaceAndNewlineCharacterSet;
string = [string stringByTrimmingCharactersInSet:set];
if( [string length] < 3 ) {
return nil;
}
string = [string lowercaseString];
NSColor * color = [[self class] colorFromPredefinedColorName:string];
if( color != nil ) {
return color;
}
if( [[string lowercaseString] isEqualToString:@"none"] ) {
return [NSColor clearColor];
}
// is it RGB?
if( [[string substringToIndex:3] isEqualToString:@"rgb"] ) {
NSInteger count = 0;
CGFloat * params = [IJSVGUtils commandParameters:string
count:&count];
CGFloat alpha = 1;
if( count == 4 ) {
alpha = params[3];
}
color = [NSColor colorWithDeviceRed:params[0]/255.f
green:params[1]/255.f
blue:params[2]/255.f
alpha:alpha];
free(params);
return color;
}
// is it HSL?
if([[string substringToIndex:3] isEqualToString:@"hsl"]) {
NSInteger count = 0;
CGFloat * params = [IJSVGUtils commandParameters:string
count:&count];
CGFloat alpha = 1;
if(count == 4) {
alpha = params[3];
}
// convert HSL to HSB
CGFloat * hsb = IJSVGColorCSSHSLToHSB(params[0], params[1], params[2]);
color = [NSColor colorWithDeviceHue:hsb[0]
saturation:hsb[1]
brightness:hsb[2]
alpha:alpha];
// memory clean!
free(hsb);
free(params);
return color;
}
color = [[self class] colorFromHEXString:string
alpha:1.f];
return color;
}
+ (NSColor *)colorFromPredefinedColorName:(NSString *)name
{
NSString * hex = nil;
name = [name.lowercaseString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if( ( hex = [_colorTree objectForKey:name] ) == nil )
return nil;
return [[self class] colorFromHEXString:hex
alpha:1.f];
}
+ (NSString *)colorStringFromColor:(NSColor *)color
{
return [self colorStringFromColor:color
forceHex:NO
allowShorthand:YES];
}
+ (NSString *)colorStringFromColor:(NSColor *)color
forceHex:(BOOL)forceHex
allowShorthand:(BOOL)allowShorthand
{
// convert to RGB
color = [self computeColorSpace:color];
int red = color.redComponent * 0xFF;
int green = color.greenComponent * 0xFF;
int blue = color.blueComponent * 0xFF;
int alpha = (int)(color.alphaComponent*100);
// jsut return none
if(alpha == 0 && forceHex == NO) {
return @"none";
}
// always return hex unless criteria is met
if(forceHex || alpha == 100 ||
(red == 0 && green == 0 && blue == 0 && alpha == 0) ||
(red == 255 && green == 255 && blue == 255 && alpha == 100)) {
if(allowShorthand == YES) {
NSString * r = [NSString stringWithFormat:@"%02X",red];
NSString * g = [NSString stringWithFormat:@"%02X",green];
NSString * b = [NSString stringWithFormat:@"%02X",blue];
if([r characterAtIndex:0] == [r characterAtIndex:1] &&
[g characterAtIndex:0] == [g characterAtIndex:1] &&
[b characterAtIndex:0] == [b characterAtIndex:1]) {
return [NSString stringWithFormat:@"#%c%c%c",[r characterAtIndex:0],
[g characterAtIndex:0],[b characterAtIndex:0]];
}
}
return [NSString stringWithFormat:@"#%02X%02X%02X",red,green,blue];
}
// note the %g, CSS alpha is 0 to 1, not 0 - 100, my bad!
return [NSString stringWithFormat:@"rgba(%d,%d,%d,%g)",red, green, blue,
((float)alpha/100.f)];
}
+ (NSString *)colorNameFromPredefinedColor:(IJSVGPredefinedColor)color
{
switch(color)
{
case IJSVGColorAliceblue:
return @"aliceblue";
case IJSVGColorAntiquewhite:
return @"antiquewhite";
case IJSVGColorAqua:
return @"aqua";
case IJSVGColorAquamarine:
return @"aquamarine";
case IJSVGColorAzure:
return @"azure";
case IJSVGColorBeige:
return @"beige";
case IJSVGColorBisque:
return @"bisque";
case IJSVGColorBlack:
return @"black";
case IJSVGColorBlanchedalmond:
return @"blanchedalmond";
case IJSVGColorBlue:
return @"blue";
case IJSVGColorBlueviolet:
return @"blueviolet";
case IJSVGColorBrown:
return @"brown";
case IJSVGColorBurlywood:
return @"burlywood";
case IJSVGColorCadetblue:
return @"cadetblue";
case IJSVGColorChartreuse:
return @"chartreuse";
case IJSVGColorChocolate:
return @"chocolate";
case IJSVGColorCoral:
return @"coral";
case IJSVGColorCornflowerblue:
return @"cornflowerblue";
case IJSVGColorCornsilk:
return @"cornsilk";
case IJSVGColorCrimson:
return @"crimson";
case IJSVGColorCyan:
return @"cyan";
case IJSVGColorDarkblue:
return @"darkblue";
case IJSVGColorDarkcyan:
return @"darkcyan";
case IJSVGColorDarkgoldenrod:
return @"darkgoldenrod";
case IJSVGColorDarkgray:
return @"darkgray";
case IJSVGColorDarkgreen:
return @"darkgreen";
case IJSVGColorDarkgrey:
return @"darkgrey";
case IJSVGColorDarkkhaki:
return @"darkkhaki";
case IJSVGColorDarkmagenta:
return @"darkmagenta";
case IJSVGColorDarkolivegreen:
return @"darkolivegreen";
case IJSVGColorDarkorange:
return @"darkorange";
case IJSVGColorDarkorchid:
return @"darkorchid";
case IJSVGColorDarkred:
return @"darkred";
case IJSVGColorDarksalmon:
return @"darksalmon";
case IJSVGColorDarkseagreen:
return @"darkseagreen";
case IJSVGColorDarkslateblue:
return @"darkslateblue";
case IJSVGColorDarkslategray:
return @"darkslategray";
case IJSVGColorDarkslategrey:
return @"darkslategrey";
case IJSVGColorDarkturquoise:
return @"darkturquoise";
case IJSVGColorDarkviolet:
return @"darkviolet";
case IJSVGColorDeeppink:
return @"deeppink";
case IJSVGColorDeepskyblue:
return @"deepskyblue";
case IJSVGColorDimgray:
return @"dimgray";
case IJSVGColorDimgrey:
return @"dimgrey";
case IJSVGColorDodgerblue:
return @"dodgerblue";
case IJSVGColorFirebrick:
return @"firebrick";
case IJSVGColorFloralwhite:
return @"floralwhite";
case IJSVGColorForestgreen:
return @"forestgreen";
case IJSVGColorFuchsia:
return @"fuchsia";
case IJSVGColorGainsboro:
return @"gainsboro";
case IJSVGColorGhostwhite:
return @"ghostwhite";
case IJSVGColorGold:
return @"gold";
case IJSVGColorGoldenrod:
return @"goldenrod";
case IJSVGColorGray:
return @"gray";
case IJSVGColorGreen:
return @"green";
case IJSVGColorGreenyellow:
return @"greenyellow";
case IJSVGColorGrey:
return @"grey";
case IJSVGColorHoneydew:
return @"honeydew";
case IJSVGColorHotpink:
return @"hotpink";
case IJSVGColorIndianred:
return @"indianred";
case IJSVGColorIndigo:
return @"indigo";
case IJSVGColorIvory:
return @"ivory";
case IJSVGColorKhaki:
return @"khaki";
case IJSVGColorLavender:
return @"lavender";
case IJSVGColorLavenderblush:
return @"lavenderblush";
case IJSVGColorLawngreen:
return @"lawngreen";
case IJSVGColorLemonchiffon:
return @"lemonchiffon";
case IJSVGColorLightblue:
return @"lightblue";
case IJSVGColorLightcoral:
return @"lightcoral";
case IJSVGColorLightcyan:
return @"lightcyan";
case IJSVGColorLightgoldenrodyellow:
return @"lightgoldenrodyellow";
case IJSVGColorLightgray:
return @"lightgray";
case IJSVGColorLightgreen:
return @"lightgreen";
case IJSVGColorLightgrey:
return @"lightgrey";
case IJSVGColorLightpink:
return @"lightpink";
case IJSVGColorLightsalmon:
return @"lightsalmon";
case IJSVGColorLightseagreen:
return @"lightseagreen";
case IJSVGColorLightskyblue:
return @"lightskyblue";
case IJSVGColorLightslategray:
return @"lightslategray";
case IJSVGColorLightslategrey:
return @"lightslategrey";
case IJSVGColorLightsteelblue:
return @"lightsteelblue";
case IJSVGColorLightyellow:
return @"lightyellow";
case IJSVGColorLime:
return @"lime";
case IJSVGColorLimegreen:
return @"limegreen";
case IJSVGColorLinen:
return @"linen";
case IJSVGColorMagenta:
return @"magenta";
case IJSVGColorMaroon:
return @"maroon";
case IJSVGColorMediumaquamarine:
return @"mediumaquamarine";
case IJSVGColorMediumblue:
return @"mediumblue";
case IJSVGColorMediumorchid:
return @"mediumorchid";
case IJSVGColorMediumpurple:
return @"mediumpurple";
case IJSVGColorMediumseagreen:
return @"mediumseagreen";
case IJSVGColorMediumslateblue:
return @"mediumslateblue";
case IJSVGColorMediumspringgreen:
return @"mediumspringgreen";
case IJSVGColorMediumturquoise:
return @"mediumturquoise";
case IJSVGColorMediumvioletred:
return @"mediumvioletred";
case IJSVGColorMidnightblue:
return @"midnightblue";
case IJSVGColorMintcream:
return @"mintcream";
case IJSVGColorMistyrose:
return @"mistyrose";
case IJSVGColorMoccasin:
return @"moccasin";
case IJSVGColorNavajowhite:
return @"navajowhite";
case IJSVGColorNavy:
return @"navy";
case IJSVGColorOldlace:
return @"oldlace";
case IJSVGColorOlive:
return @"olive";
case IJSVGColorOlivedrab:
return @"olivedrab";
case IJSVGColorOrange:
return @"orange";
case IJSVGColorOrangered:
return @"orangered";
case IJSVGColorOrchid:
return @"orchid";
case IJSVGColorPalegoldenrod:
return @"palegoldenrod";
case IJSVGColorPalegreen:
return @"palegreen";
case IJSVGColorPaleturquoise:
return @"paleturquoise";
case IJSVGColorPalevioletred:
return @"palevioletred";
case IJSVGColorPapayawhip:
return @"papayawhip";
case IJSVGColorPeachpuff:
return @"peachpuff";
case IJSVGColorPeru:
return @"peru";
case IJSVGColorPink:
return @"pink";
case IJSVGColorPlum:
return @"plum";
case IJSVGColorPowderblue:
return @"powderblue";
case IJSVGColorPurple:
return @"purple";
case IJSVGColorRed:
return @"red";
case IJSVGColorRosybrown:
return @"rosybrown";
case IJSVGColorRoyalblue:
return @"royalblue";
case IJSVGColorSaddlebrown:
return @"saddlebrown";
case IJSVGColorSalmon:
return @"salmon";
case IJSVGColorSandybrown:
return @"sandybrown";
case IJSVGColorSeagreen:
return @"seagreen";
case IJSVGColorSeashell:
return @"seashell";
case IJSVGColorSienna:
return @"sienna";
case IJSVGColorSilver:
return @"silver";
case IJSVGColorSkyblue:
return @"skyblue";
case IJSVGColorSlateblue:
return @"slateblue";
case IJSVGColorSlategray:
return @"slategray";
case IJSVGColorSlategrey:
return @"slategrey";
case IJSVGColorSnow:
return @"snow";
case IJSVGColorSpringgreen:
return @"springgreen";
case IJSVGColorSteelblue:
return @"steelblue";
case IJSVGColorTan:
return @"tan";
case IJSVGColorTeal:
return @"teal";
case IJSVGColorThistle:
return @"thistle";
case IJSVGColorTomato:
return @"tomato";
case IJSVGColorTurquoise:
return @"turquoise";
case IJSVGColorViolet:
return @"violet";
case IJSVGColorWheat:
return @"wheat";
case IJSVGColorWhite:
return @"white";
case IJSVGColorWhitesmoke:
return @"whitesmoke";
case IJSVGColorYellow:
return @"yellow";
case IJSVGColorYellowgreen:
return @"yellowgreen";
}
return nil;
}
+ (NSColor *)changeAlphaOnColor:(NSColor *)color
to:(CGFloat)alphaValue
{
color = [self computeColorSpace:color];
return [NSColor colorWithDeviceRed:[color redComponent]
green:[color greenComponent]
blue:[color blueComponent]
alpha:alphaValue];
}
+ (BOOL)isColor:(NSString *)string
{
return [[string substringToIndex:1] isEqualToString:@"#"] || [[string substringToIndex:3] isEqualToString:@"rgb"];
}
+ (BOOL)isHex:(NSString *)string
{
NSCharacterSet *chars = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef#"] invertedSet];
return [string rangeOfCharacterFromSet:chars].location == NSNotFound;
}
+ (NSColor *)colorFromHEXString:(NSString *)string
alpha:(CGFloat)alpha
{
// absolutely no string
if( string == nil || string.length == 0 || ![[self class] isHex:string] )
return nil;
if( [[string substringToIndex:1] isEqualToString:@"#"] )
string = [string substringFromIndex:1];
// whats the length?
if(string.length == 3) {
// shorthand...
NSMutableString * str = [[[NSMutableString alloc] init] autorelease];
for( NSInteger i = 0; i < string.length; i++ )
{
NSString * sub = [string substringWithRange:NSMakeRange( i, 1)];
[str appendFormat:@"%@%@",sub,sub];
}
string = str;
}
NSScanner * scanner = [NSScanner scannerWithString:string];
unsigned int hex;
if( [scanner scanHexInt:&hex] )
{
NSInteger r = (hex>>16) & 0xFF;
NSInteger g = (hex>>8) & 0xFF;
NSInteger b = (hex) & 0xFF;
return [NSColor colorWithDeviceRed:r/255.f
green:g/255.f
blue:b/255.f
alpha:alpha];
}
return nil;
}
@end
+73
View File
@@ -0,0 +1,73 @@
//
// IJSVGCommand.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGPath.h"
typedef NS_ENUM( NSInteger, IJSVGCommandType ) {
IJSVGCommandTypeAbsolute,
IJSVGCommandTypeRelative
};
@class IJSVGCommand;
@protocol IJSVGCommandProtocol <NSObject>
@required
+ (void)runWithParams:(CGFloat *)params
paramCount:(NSInteger)count
command:(IJSVGCommand *)currentCommand
previousCommand:(IJSVGCommand *)command
type:(IJSVGCommandType)type
path:(IJSVGPath *)path;
+ (NSInteger)requiredParameterCount;
@end
@interface IJSVGCommand : NSObject {
NSString * commandString;
NSString * command;
CGFloat * parameters;
NSInteger parameterCount;
NSMutableArray * subCommands;
NSInteger requiredParameters;
IJSVGCommandType type;
IJSVGCommand * previousCommand;
NSInteger _currentIndex;
Class<IJSVGCommandProtocol> commandClass;
BOOL isSubCommand;
}
@property ( nonatomic, copy ) NSString * commandString;
@property ( nonatomic, copy ) NSString * command;
@property ( nonatomic, assign ) CGFloat * parameters;
@property ( nonatomic, assign ) NSInteger parameterCount;
@property ( nonatomic, assign ) NSInteger requiredParameters;
@property ( nonatomic, assign ) IJSVGCommandType type;
@property ( nonatomic, retain ) NSMutableArray * subCommands;
@property ( nonatomic, assign ) Class<IJSVGCommandProtocol> commandClass;
@property ( nonatomic, assign ) IJSVGCommand * previousCommand;
@property ( nonatomic, assign ) BOOL isSubCommand;
- (id)initWithCommandString:(NSString *)commandString;
+ (NSPoint)readCoordinatePair:(CGFloat *)pairs
index:(NSInteger)index;
+ (void)registerClass:(Class)aClass
forCommand:(NSString *)command;
+ (NSDictionary *)registeredCommandClasses;
+ (Class<IJSVGCommandProtocol>)commandClassForCommandLetter:(NSString *)str;
- (CGFloat)readFloat;
- (NSPoint)readPoint;
- (BOOL)readBOOL;
- (void)resetRead;
@end
+146
View File
@@ -0,0 +1,146 @@
//
// IJSVGCommand.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommand.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommand
@synthesize commandString;
@synthesize command;
@synthesize parameterCount;
@synthesize parameters;
@synthesize subCommands;
@synthesize commandClass;
@synthesize requiredParameters;
@synthesize type;
@synthesize previousCommand;
@synthesize isSubCommand;
static NSMutableDictionary * _classes = nil;
- (void)dealloc
{
[commandString release], commandString = nil;
[command release], command = nil;
[subCommands release], subCommands = nil;
free( parameters );
[super dealloc];
}
- (id)initWithCommandString:(NSString *)str
{
if( ( self = [super init] ) != nil )
{
// work out the basics
_currentIndex = 0;
subCommands = [[NSMutableArray alloc] init];
command = [[str substringToIndex:1] copy];
type = [IJSVGUtils typeForCommandString:self.command];
commandClass = [[self class] commandClassForCommandLetter:self.command];
parameters = [IJSVGUtils commandParameters:str count:&parameterCount];
requiredParameters = [self.commandClass requiredParameterCount];
// now work out the sets of parameters we have
// each command could have a series of subcommands
// if there is a multiple of commands in a command
// then we need to work those out...
NSInteger sets = 1;
if( self.requiredParameters != 0 ) {
sets = self.parameterCount/self.requiredParameters;
}
// interate over the sets
for( NSInteger i = 0; i < sets; i++ ) {
// memory for this will be handled by the created subcommand
CGFloat * subParams = 0;
if( self.requiredParameters != 0 ) {
subParams = (CGFloat*)malloc(self.requiredParameters*sizeof(CGFloat));
for( NSInteger p = 0; p < self.requiredParameters; p++ ) {
subParams[p] = self.parameters[i*self.requiredParameters+p];
}
}
// create a subcommand per set
IJSVGCommand * c = [[[[self class] alloc] init] autorelease];
c.parameterCount = self.requiredParameters;
c.parameters = subParams;
c.type = self.type;
c.command = self.command;
c.previousCommand = self.subCommands.lastObject;
c.commandClass = self.commandClass;
c.isSubCommand = i == 0 ? NO : YES;
// add it to our tree
[self.subCommands addObject:c];
}
}
return self;
}
+ (NSPoint)readCoordinatePair:(CGFloat *)pairs
index:(NSInteger)index
{
return NSMakePoint( pairs[index*2], pairs[index*2+1]);
}
+ (void)registerClass:(Class)aClass
forCommand:(NSString *)command
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_classes = [[NSMutableDictionary alloc] init];
});
[_classes setObject:NSStringFromClass(aClass)
forKey:command];
}
+ (NSDictionary *)registeredCommandClasses
{
return _classes;
}
+ (void)load
{
// register here...
}
+ (Class<IJSVGCommandProtocol>)commandClassForCommandLetter:(NSString *)str
{
NSString * command = nil;
if( ( command = [_classes objectForKey:[str lowercaseString]] ) == nil )
return nil;
return NSClassFromString(command);
}
- (CGFloat)readFloat
{
CGFloat f = parameters[_currentIndex];
_currentIndex++;
return f;
}
- (NSPoint)readPoint
{
CGFloat x = parameters[_currentIndex];
CGFloat y = parameters[_currentIndex+1];
_currentIndex+=2;
return NSMakePoint( x, y );
}
- (BOOL)readBOOL
{
return [self readFloat] == 1;
}
- (void)resetRead
{
_currentIndex = 0;
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
@interface IJSVGCommandEllipticalArc : IJSVGCommand
@interface IJSVGCommandArc : IJSVGCommand <IJSVGCommandProtocol>
@end

Some files were not shown because too many files have changed in this diff Show More