Compare commits

...

96 Commits

Author SHA1 Message Date
Curtis Hard d0878c9f1b Added convenience method in 2019-12-11 15:47:12 +00:00
Curtis Hard cd135ce271 Refactor and more performant string passing 2019-12-11 13:22:16 +00:00
Curtis Hard b369891e96 Added sequences to float parsing 2019-12-10 22:25:21 +00:00
Curtis Hard cde99fc501 Fixes memory leak 2019-12-06 12:03:44 +00:00
Curtis Hard efc5f139f6 Formatting 2019-12-06 08:26:03 +00:00
Curtis Hard f1c62ed828 Fixes a few things 2019-12-05 21:07:40 +00:00
Curtis Hard d66332ad07 Added is main thread check to transaction 2019-12-05 11:12:45 +00:00
Curtis Hard f2363769bf replaced calls with prefix 2019-12-04 12:58:08 +00:00
Curtis Hard ca1f0d9bf3 Performance increases and memory enhancements 2019-12-04 12:52:58 +00:00
Curtis Hard 8b7fc3171d More goodies 2019-12-04 08:59:55 +00:00
Curtis Hard 38df2094c9 Refactor and moving of groups 2019-12-04 08:59:46 +00:00
Curtis Hard 2355e86ed7 Fixes memory leak 2019-12-03 22:43:25 +00:00
Curtis Hard 192a9259fe Fixes performance here 2019-12-03 22:38:20 +00:00
Curtis Hard 2a9eb3cdc5 Added support for transparent 2019-12-03 14:26:11 +00:00
Curtis Hard 6ed4e3fb8e Export primitive shapes if they were that on import 2019-12-03 14:17:31 +00:00
Curtis Hard f6e1f1494e Initial stuff 2019-12-03 09:22:46 +00:00
Curtis Hard 775e5c15a0 Performance increases and modern syntax things 2019-12-02 22:30:52 +00:00
Curtis Hard abd19c78dd This updates formatting to meet the WebKit standard 2019-12-02 21:05:12 +00:00
Curtis Hard 29090f30f9 Fixes stuff 2019-11-28 21:56:56 +00:00
Curtis Hard e2a2fc615c Fixes warning about commas 2019-11-28 20:33:04 +00:00
Curtis Hard 5466e0f2ec More framework stuff 2019-11-28 13:26:37 +00:00
Curtis Hard c2f0c25913 Updated framework stuff 2019-11-28 13:21:08 +00:00
Curtis Hard cddc9554b4 Start of framework 2019-11-28 12:36:14 +00:00
Curtis Hard ffdbe1ec9c Fixes userSpaceOnUse for masks and clipPaths 2019-11-27 22:08:12 +00:00
Curtis Hard 63586f1181 Reformat 2019-11-18 22:57:55 +00:00
Curtis Hard dc94d9761b Fixes subcommands, this is fairly big bug… 2019-11-18 22:55:44 +00:00
Curtis Hard 8deef07f7f Merge branch 'feature/primitive-colors' of https://github.com/curthard89/IJSVG into feature/primitive-colors 2019-10-24 19:31:54 +01:00
Curtis Hard 2c962db6cc Refactoring of commands 2019-10-24 19:31:51 +01:00
Curtis Hard 9dda7915fa Fixes shorthand 2019-10-22 14:11:12 +01:00
Curtis Hard 1fbb56b443 Fixes shorthand not working correctly 2019-10-22 14:10:23 +01:00
Curtis Hard 4bbf2277bc Fixes exporter 2019-10-20 18:50:34 +01:00
Curtis Hard 7eeeea5167 Adds support for RRGGBBAA 2019-10-20 17:07:07 +01:00
Curtis Hard 8f84aa9070 Modern syntax 2019-08-15 13:16:20 +01:00
Curtis Hard 200fd6893d Fixes memory leak 2019-08-14 23:04:01 +01:00
Curtis Hard 01ad4eaeb2 Fixes clipping issue when drawing into a context 2019-07-21 22:17:58 +01:00
Curtis Hard 6b1c988d89 Added shorthand function for chcking export types 2019-07-17 22:31:13 +01:00
Curtis Hard c91ac95bc2 Swaps over normal attribute setting to a rendering style object instead 2019-07-14 15:35:40 +01:00
Curtis Hard cf14f27560 More color list features 2019-07-07 21:01:38 +01:00
Curtis Hard cef1de35d7 Inital colour sstuff 2019-07-07 20:26:39 +01:00
Curtis Hard c1a98ef5a6 Update all things! 2019-07-07 11:27:20 +01:00
Curtis Hard 690e1c8619 visibleColors now also returns if it has patternFills 2019-07-06 16:55:07 +01:00
Curtis Hard eda2b73eb2 More fixes for gradients 2019-07-06 15:52:41 +01:00
Curtis Hard f00ede11f0 More gradient fixes 2019-07-06 15:31:17 +01:00
Curtis Hard 169da55131 More fixes 2019-07-05 22:34:05 +01:00
Curtis Hard acfec29765 Fixes project for latest master 2019-07-05 15:18:14 +01:00
Curtis Hard a44cc7c098 Fixes objectBoundBox values 2019-07-05 15:16:56 +01:00
Curtis Hard 171e97451b Initial fixes for userSpaceOnUse 2019-07-05 13:27:18 +01:00
Curtis Hard 27e096350e Fixes issue with RGB being parsed incorrectly 2019-07-04 10:04:27 +01:00
Curtis Hard 04646fe4ec Fixes color bug with predefined colours 2019-07-03 21:06:58 +01:00
Curtis Hard a092b612a8 Added translateX and translateY to available transforms
- also fixes more gradient issues
2019-07-03 20:59:47 +01:00
Curtis Hard d176fe6396 This fixes userSpaceOnUse issues with gradients (i think and hope - fingers crossed) 2019-07-03 18:29:12 +01:00
Curtis Hard c94de1d241 Fixes URL parsing and scaling for gradients 2019-07-02 22:27:51 +01:00
Curtis Hard 1294372daa Moved [self class] over to modern syntax 2019-06-22 16:24:32 +01:00
Curtis Hard 60e5c6b68a Slight refactor 2019-06-16 14:00:47 +01:00
Curtis Hard 06c8191732 Added image by maintaining aspect ratio 2019-06-16 12:56:36 +01:00
Curtis Hard 2f0bead7a4 Sets initial stroke width to 1.0, should not be 0.f! 2019-06-10 15:10:52 +01:00
Curtis Hard ee46609165 Merge branch 'master' of https://github.com/IconJar/IJSVG 2019-06-07 10:04:50 +01:00
Curtis Hard 9e58ae6e19 Added string additions 2019-06-07 10:04:47 +01:00
Curtis Hard 199d1a5707 This fixes issue with strokes being set to 0 and not being interpreted correctly 2019-05-22 18:14:29 +01:00
Curtis Hard f72ae8b401 RGB values now support percentage values 2019-05-13 15:58:36 +01:00
Curtis Hard c126f511d6 Merge branch 'features/performance-increases' 2019-03-27 08:25:47 +00:00
Curtis Hard 399e9271b4 Pretty much working 2019-03-19 21:43:09 +00:00
Curtis Hard f9107094a4 Added IJSVGImageRep 2019-03-15 21:41:03 +00:00
Curtis Hard 7a64c122cf #oops 2019-03-15 09:45:18 +00:00
Curtis Hard 8ee96c4a5b Fixes gradient clipping and masking issues 2019-03-15 09:41:24 +00:00
Curtis Hard 7cace854bd Fixes duplicate colors 2019-03-14 21:37:17 +00:00
Curtis Hard 91cf59bd32 Gradient layer now works out if it can be opaque or not 2019-03-14 20:51:19 +00:00
Curtis Hard b5e15445a5 Added renderingQuality property to IJSVG 2019-03-14 20:11:49 +00:00
Curtis Hard e7577a3e76 Various performance increases
- mainly due to gradients having a party off-screen
2019-03-14 16:50:34 +00:00
Curtis Hard 25b38fa128 Various performance increases 2019-03-13 22:19:30 +00:00
Curtis Hard 8ef14224dd Fixes memory crash 2019-03-11 09:44:39 +00:00
Curtis Hard ebfc31cdb1 Ongoing performance increases 2019-03-10 21:24:45 +00:00
Curtis Hard ccfcfbf228 This fixes fillOpacity not inheriting correctly 2019-03-08 15:43:11 +00:00
Curtis Hard 4fe1d594b0 Some reason, this is not needed on 10.14
- removed for perf reasons, still does if needed, does the check for the OS
2019-03-06 21:38:57 +00:00
Curtis Hard 61d5bb99d5 Swappwd strtod over to strtod_l to use POSIX
- reuses memory instead of malloc every string, massive performance increase
2019-03-02 19:49:36 +00:00
Curtis Hard faccec3e01 Swappted atof with strtod - performs alot better 2019-03-02 14:17:28 +00:00
Curtis Hard 66e9c9000e This improves performance by using a prebuild switch of command classes instead of registering from the command class iteself 2019-03-01 21:45:19 +00:00
Curtis Hard 2006e68c2a Updated for 10.14 2018-12-02 21:52:49 +00:00
Curtis Hard 01aea1129d Added tint color 2018-10-09 15:58:59 +01:00
Curtis Hard 388982d37b Added IJSVGExporterOptionRemoveWidthHeightAttributes option to exporter 2018-08-24 21:55:51 +01:00
Curtis Hard 941130d1f2 Removed DOM discard 2018-06-03 21:27:43 +01:00
Curtis Hard b9e964dc50 Style over attribute order 2018-05-20 22:08:30 +01:00
Curtis Hard 8532819b6a Updated generator 2018-05-07 22:03:00 +01:00
Curtis Hard e576803bb7 Fixes opacity issue, defaults to 1.0 unless specified otherwise 2018-04-30 21:48:01 +01:00
Curtis Hard a6a802a36b Fixes crashes for use elements that cannot find their linked object 2018-04-14 18:41:41 +01:00
Curtis Hard b50963292c Fixes crash with restoring context 2018-03-27 19:16:20 +01:00
Curtis Hard c40c63c48d Fixes compiler error -_- 2018-03-04 13:44:38 +00:00
Curtis Hard 6d21b56416 Fixes nested SVG’s origins 2018-03-02 15:45:07 +00:00
Curtis Hard dbdd8a6971 Removed useless defintion 2018-03-02 15:32:52 +00:00
Curtis Hard b7ba91aa82 Moves frame positions over to transforms 2018-03-02 15:31:41 +00:00
Curtis Hard 98efacf93c Fixes Sub SVG rendering 2018-03-02 14:56:30 +00:00
Curtis Hard 1b3cf5a1a0 Updated Example 2018-03-02 14:12:57 +00:00
Curtis Hard 35f8663631 Gradient stroke SVG 2018-03-02 14:09:50 +00:00
Curtis Hard 6d4eb76803 Squashed commit of the following:
commit ffb55b0f31
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Mar 2 13:28:40 2018 +0000

    Fixes viewBox origin translate

commit a4c032afa2
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Feb 28 21:29:11 2018 +0000

    Added clip to viewport

commit abe8f4cba5
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Feb 28 21:00:20 2018 +0000

    Fixes drawInRect not obeying origin

commit a16842271b
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Feb 26 13:46:41 2018 +0000

    Resolves namespaces correctly + added common HTML list to be parsed as groups

commit 58126e06e4
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 25 21:58:49 2018 +0000

    Fixes!

commit 5af5e054ab
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Feb 23 22:37:53 2018 +0000

    Fixed defNode being removed

commit edd3aa1f33
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Feb 23 16:29:54 2018 +0000

    excluded various elements from diff

commit 3366bc4fa5
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Feb 23 14:05:03 2018 +0000

    Better optimaztion

commit 104002183b
Author: Curtis Hard <curtishard@me.com>
Date:   Thu Feb 22 22:17:50 2018 +0000

    Added rudimenatry inline styles -> stylesheet

commit 7010b7ea50
Author: Curtis Hard <curtishard@me.com>
Date:   Thu Feb 22 13:33:32 2018 +0000

    Correct order of cleanup

commit 5266a8c07a
Author: Curtis Hard <curtishard@me.com>
Date:   Thu Feb 22 08:22:17 2018 +0000

    corrent length of string

commit caf55e8bdf
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Feb 21 20:45:17 2018 +0000

    removes useless def if required

commit 8160d05eba
Author: Curtis Hard <curtishard@me.com>
Date:   Tue Feb 20 14:12:02 2018 +0000

    Refactor of a few methods

commit a6d6a06521
Author: Curtis Hard <curtishard@me.com>
Date:   Tue Feb 20 09:40:21 2018 +0000

    Added collpasing of gradients

commit 103a4d71f6
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Feb 19 19:07:30 2018 +0000

    Reduced floats even more

commit 98874b1d2c
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Feb 19 18:53:02 2018 +0000

    More compression goodness

commit e742db31e0
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Feb 19 14:02:15 2018 +0000

    Added intermediateParent

commit 198fd09f07
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Feb 19 11:51:37 2018 +0000

    Fixes! and performance increases

commit 3493194b1b
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Feb 19 08:20:02 2018 +0000

    Scale computation

commit 0016775eaf
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 18 22:33:26 2018 +0000

    More goodness

commit 304a04cc22
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 18 22:32:04 2018 +0000

    Vastly improved the exporter

commit e4fd0af582
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 18 15:20:28 2018 +0000

    This is insanely important!

commit 69a2a0c97e
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 4 22:02:19 2018 +0000

    Refactor

commit 5299bb0479
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 4 21:58:21 2018 +0000

    will continue to use CoreAnimation for the time being

commit 4f1943cad1
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 4 21:57:46 2018 +0000

    Fixes gradient strokes

commit f02d186293
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Feb 4 11:15:04 2018 +0000

    trying to get masks to work

commit 3291718cfb
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Feb 2 22:35:22 2018 +0000

    Beginning of quartz renderer

commit 6fbaaf5884
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Jan 29 22:32:08 2018 +0000

    Removed useless log

commit abc65797ea
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Jan 29 21:37:45 2018 +0000

    I think gradients work :D

commit af5a1c2718
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Jan 28 22:18:02 2018 +0000

    Possible fx and fy things…

commit fb9a5282b9
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Jan 28 19:22:40 2018 +0000

    Even more gradient fixes

commit d83933a103
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Jan 28 14:21:50 2018 +0000

    Various improvements

commit bd7a0d5021
Author: Curtis Hard <curtishard@me.com>
Date:   Sat Jan 27 22:26:33 2018 +0000

    Start to linear

commit a9a038568c
Author: Curtis Hard <curtishard@me.com>
Date:   Sat Jan 27 21:14:25 2018 +0000

    This kind of actually works...

commit 77fbb38b6f
Author: Curtis Hard <curtishard@me.com>
Date:   Sat Jan 27 20:31:36 2018 +0000

    I guess this could be a good start?

    Posssible start of fixes?

commit 12c3191569
Author: Curtis Hard <curtishard@me.com>
Date:   Sat Jan 27 15:32:15 2018 +0000

    Added method for findind absolute position

commit e3e9626ef7
Author: Curtis Hard <curtishard@me.com>
Date:   Sat Jan 27 14:25:03 2018 +0000

    Fixes crash due to parentNode on temp groups being released

commit 1160d89f16
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Jan 26 22:29:22 2018 +0000

    Fixes use statements with transforms

commit 1575cbfde8
Author: Curtis Hard <curtishard@me.com>
Date:   Fri Jan 26 18:16:03 2018 +0000

    Moved color tree over to modern syntax

commit 5c4c2eee91
Author: Curtis Hard <curtishard@me.com>
Date:   Thu Jan 25 18:23:53 2018 +0000

    Added HSL/HSLA support

commit 087b13e58f
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Jan 24 22:24:43 2018 +0000

    Various image loading issues resolved from base64 images

commit 1183e167aa
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Jan 24 21:21:41 2018 +0000

    Rect issue fix

commit 4dbfc59437
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Jan 24 21:19:24 2018 +0000

    Moved transforms over from being concatinated to seperate calls

commit 409bd509fa
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Jan 24 20:30:38 2018 +0000

    Fixes color issue

commit 8ae1d1b4e0
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Jan 24 18:41:08 2018 +0000

    Removed check as its not needed here

commit 7243fbe5ff
Author: Curtis Hard <curtishard@me.com>
Date:   Wed Jan 24 18:35:43 2018 +0000

    Added excludeAttributes list to parseCommonAttributes

    added x and y to that list for rect

commit 51b9a5e85f
Author: Curtis Hard <curtishard@me.com>
Date:   Tue Jan 23 19:53:04 2018 +0000

    Added isSubcommand to IJSVGCommand

    - Fixes move command going awol when preceding move commands are not subcommands (woah)

commit 40098589de
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Jan 22 22:04:48 2018 +0000

    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 :-))

commit 7cb96b21f2
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Jan 22 22:01:56 2018 +0000

    Removed use of origin here as its computed in apply defaults

commit 1bff7c6970
Author: Curtis Hard <curtishard@me.com>
Date:   Mon Jan 22 21:48:07 2018 +0000

    Various fixes… still going…
2018-03-02 13:51:49 +00:00
Curtis Hard 36dae3ad1b Revert "Various fixes… still going…"
This reverts commit 8149293b7b.
2018-01-22 21:48:21 +00:00
Curtis Hard 8149293b7b Various fixes… still going… 2018-01-22 21:48:07 +00:00
177 changed files with 36630 additions and 8594 deletions
@@ -0,0 +1,893 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
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 */; };
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, ); }; };
59EB75DF23905F7300F5AE63 /* IJSVGWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756E23905F6C00F5AE63 /* IJSVGWriter.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E023905F7300F5AE63 /* IJSVGStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; };
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, ); }; };
59EB75FA23905F7300F5AE63 /* IJSVGWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758923905F6D00F5AE63 /* IJSVGWriter.m */; };
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758A23905F6D00F5AE63 /* IJSVGPath.m */; };
59EB75FC23905F7300F5AE63 /* IJSVGGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */; };
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */; };
59EB75FF23905F7300F5AE63 /* IJSVGBezierPathAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758E23905F6D00F5AE63 /* IJSVGBezierPathAdditions.m */; };
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */; };
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, ); }; };
59EB760423905F7300F5AE63 /* IJSVGCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759323905F6D00F5AE63 /* IJSVGCache.m */; };
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 */; };
59EB762F23905F7300F5AE63 /* IJSVGCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BE23905F7000F5AE63 /* IJSVGCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
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 */; };
59EB763423905F7300F5AE63 /* IJSVGBezierPathAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75C323905F7100F5AE63 /* IJSVGBezierPathAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */; };
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 */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
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; };
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; name = IJSVG.h; path = ../../../../source/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>"; };
59EB756E23905F6C00F5AE63 /* IJSVGWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IJSVGWriter.h; path = ../../../../source/IJSVGWriter.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; name = IJSVGFontConverter.m; path = ../../../../source/IJSVGFontConverter.m; sourceTree = "<group>"; };
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IJSVGImageRep.m; path = ../../../../source/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; name = IJSVGError.h; path = ../../../../source/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; name = IJSVGFontConverter.h; path = ../../../../source/IJSVGFontConverter.h; sourceTree = "<group>"; };
59EB758923905F6D00F5AE63 /* IJSVGWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IJSVGWriter.m; path = ../../../../source/IJSVGWriter.m; sourceTree = "<group>"; };
59EB758A23905F6D00F5AE63 /* IJSVGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPath.m; sourceTree = "<group>"; };
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGroup.h; sourceTree = "<group>"; };
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>"; };
59EB758E23905F6D00F5AE63 /* IJSVGBezierPathAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGBezierPathAdditions.m; sourceTree = "<group>"; };
59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientLayer.m; sourceTree = "<group>"; };
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>"; };
59EB759323905F6D00F5AE63 /* IJSVGCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IJSVGCache.m; path = ../../../../source/IJSVGCache.m; 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; name = IJSVG.m; path = ../../../../source/IJSVG.m; sourceTree = "<group>"; };
59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IJSVGImageRep.h; path = ../../../../source/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>"; };
59EB75BE23905F7000F5AE63 /* IJSVGCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IJSVGCache.h; path = ../../../../source/IJSVGCache.h; 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; name = IJSVGView.m; path = ../../../../source/IJSVGView.m; sourceTree = "<group>"; };
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLinearGradient.m; sourceTree = "<group>"; };
59EB75C323905F7100F5AE63 /* IJSVGBezierPathAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGBezierPathAdditions.h; sourceTree = "<group>"; };
59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetSelector.m; sourceTree = "<group>"; };
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; name = IJSVGView.h; path = ../../../../source/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>"; };
/* 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 */,
);
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 */,
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */,
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */,
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */,
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */,
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */,
59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */,
);
path = Layers;
sourceTree = "<group>";
};
592ABBE62397A00C00F44380 /* Parsing */ = {
isa = PBXGroup;
children = (
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 */,
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 */,
);
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 = (
59EB75C323905F7100F5AE63 /* IJSVGBezierPathAdditions.h */,
59EB758E23905F6D00F5AE63 /* IJSVGBezierPathAdditions.m */,
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */,
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.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>";
};
59EB756423905F3100F5AE63 /* Source */ = {
isa = PBXGroup;
children = (
592ABBEB2397A11800F44380 /* Additions */,
592ABBEA2397A10000F44380 /* Rendering */,
592ABBE92397A08500F44380 /* Exporter */,
592ABBE82397A06800F44380 /* Utils */,
592ABBE72397A02900F44380 /* Nodes */,
592ABBE62397A00C00F44380 /* Parsing */,
592ABBE523979FE100F44380 /* Layers */,
592ABBE423979FD200F44380 /* Colors */,
592ABBE323979FBB00F44380 /* Stylesheets */,
592ABBE223979F9B00F44380 /* Commands */,
59EB756A23905F6B00F5AE63 /* IJSVG.h */,
59EB75A223905F6E00F5AE63 /* IJSVG.m */,
59EB75BE23905F7000F5AE63 /* IJSVGCache.h */,
59EB759323905F6D00F5AE63 /* IJSVGCache.m */,
59EB758423905F6C00F5AE63 /* IJSVGError.h */,
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */,
59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */,
59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */,
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */,
59EB75CD23905F7200F5AE63 /* IJSVGView.h */,
59EB75C123905F7100F5AE63 /* IJSVGView.m */,
59EB756E23905F6C00F5AE63 /* IJSVGWriter.h */,
59EB758923905F6D00F5AE63 /* IJSVGWriter.m */,
);
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 */,
59EB75DF23905F7300F5AE63 /* IJSVGWriter.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 */,
59EB762F23905F7300F5AE63 /* IJSVGCache.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 */,
59EB763423905F7300F5AE63 /* IJSVGBezierPathAdditions.h in Headers */,
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */,
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.h in Headers */,
59EB761D23905F7300F5AE63 /* IJSVGStyle.h in Headers */,
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */,
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */,
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.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 = 1100;
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 */,
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 */,
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 */,
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 */,
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */,
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */,
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */,
59EB760423905F7300F5AE63 /* IJSVGCache.m in Sources */,
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */,
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */,
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */,
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */,
59EB75FF23905F7300F5AE63 /* IJSVGBezierPathAdditions.m in Sources */,
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */,
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */,
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */,
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */,
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */,
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */,
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */,
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */,
59EB75FA23905F7300F5AE63 /* IJSVGWriter.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_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_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_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_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;
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.1;
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;
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.1;
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 */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:IJSVG.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?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>
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
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>
@@ -0,0 +1,22 @@
<?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
@@ -0,0 +1,24 @@
<?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 © 2019 Curtis Hard. All rights reserved.</string>
</dict>
</plist>
@@ -6,6 +6,7 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@interface NSBezierPath (IJSVGAdditions)
@@ -15,9 +15,9 @@
{
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) );
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];
@@ -0,0 +1,18 @@
//
// 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:(char *)aChar;
- (BOOL)ijsvg_isNumeric;
- (BOOL)ijsvg_containsAlpha;
- (NSArray*)ijsvg_componentsSplitByWhiteSpace;
@end
@@ -0,0 +1,91 @@
//
// IJSVGStringAdditions.m
// IconJar
//
// Created by Curtis Hard on 07/06/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGStringAdditions.h"
@implementation NSString (IJSVGAdditions)
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(char*)aChar
{
NSMutableArray* comp = [[[NSMutableArray alloc] init] autorelease];
NSInteger length = self.length;
unichar* chars = (unichar*)calloc(sizeof(unichar), self.length);
NSInteger ind = 0;
BOOL startedString = NO;
// block for easy comparison
NSUInteger aLength = strlen(aChar);
BOOL (^charsContainsChar)(char anotherChar) = ^(char anotherChar) {
for (NSInteger i = 0; i < aLength; i++) {
if (aChar[i] == anotherChar) {
return YES;
}
}
return NO;
};
for (NSInteger i = 0; i < length; i++) {
// the char
unichar theChar = [self characterAtIndex:i];
// start the buffer
BOOL isEqualToChar = charsContainsChar(theChar);
if (isEqualToChar == NO) {
startedString = YES;
chars[ind++] = theChar;
}
// has started and char is the search char, or its at end
if ((startedString == YES && isEqualToChar) || (i == (length - 1) && startedString == YES)) {
startedString = NO;
// append the comp
[comp addObject:[NSString stringWithCharacters:chars length:ind]];
free(chars);
// restart and realloc the memory
ind = 0;
chars = (unichar*)calloc(sizeof(unichar), self.length);
}
}
free(chars);
return comp;
}
- (BOOL)ijsvg_containsAlpha
{
const char* buffer = self.UTF8String;
unsigned long length = strlen(buffer);
for (int i = 0; i < length; i++) {
if (isalpha(buffer[i])) {
return YES;
}
}
return NO;
}
- (BOOL)ijsvg_isNumeric
{
const char* buffer = self.UTF8String;
unsigned long length = strlen(buffer);
for (int i = 0; i < length; i++) {
if (!isnumber(buffer[i])) {
return NO;
}
}
return YES;
}
- (NSArray*)ijsvg_componentsSplitByWhiteSpace
{
return [self ijsvg_componentsSeparatedByChars:"\t\n\r "];
}
@end
@@ -6,9 +6,18 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
typedef NS_ENUM( NSInteger, IJSVGPredefinedColor ) {
typedef NS_OPTIONS(NSInteger, IJSVGColorStringOptions) {
IJSVGColorStringOptionNone = 1 << 0,
IJSVGColorStringOptionForceHEX = 1 << 1,
IJSVGColorStringOptionAllowShortHand = 1 << 2,
IJSVGColorStringOptionAllowRRGGBBAA = 1 << 3,
IJSVGColorStringOptionDefault = IJSVGColorStringOptionAllowShortHand
};
typedef NS_ENUM(NSInteger, IJSVGPredefinedColor) {
IJSVGColorAliceblue,
IJSVGColorAntiquewhite,
IJSVGColorAqua,
@@ -160,19 +169,29 @@ typedef NS_ENUM( NSInteger, IJSVGPredefinedColor ) {
@interface IJSVGColor : NSObject
+ (NSColor *)computeColorSpace:(NSColor *)color;
+ (NSColorSpace *)defaultColorSpace;
+ (BOOL)isColor:(NSString *)string;
+ (NSString *)colorStringFromColor:(NSColor *)color
forceHex:(BOOL)forceHex;
+ (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;
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;
@end
@@ -0,0 +1,791 @@
//
// 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" : @(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
{
NSCharacterSet* set = NSCharacterSet.whitespaceAndNewlineCharacterSet;
string = [string stringByTrimmingCharactersInSet:set];
if ([string length] < 3) {
return nil;
}
NSColor* color = nil;
string = [string lowercaseString];
if ([self.class isHex:string] == NO) {
color = [self.class colorFromPredefinedColorName:string];
if (color != nil) {
return color;
}
}
// is simply a clear color, dont fill
if ([string.lowercaseString isEqualToString:@"none"] ||
[string.lowercaseString isEqualToString:@"transparent"]) {
return [self computeColorSpace:NSColor.clearColor];
}
// is it RGB?
if ([string hasPrefix:@"rgb"] == YES) {
NSRange range = [IJSVGUtils rangeOfParentheses:string];
NSString* rgbString = [string substringWithRange:range];
NSArray* parts = [rgbString ijsvg_componentsSeparatedByChars:","];
NSString* alpha = @"100%";
if (parts.count == 4) {
alpha = parts[3];
}
return [self colorFromRString:parts[0]
gString:parts[1]
bString:parts[2]
aString:alpha];
}
// is it HSL?
if ([string hasPrefix:@"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];
color = [self computeColorSpace:color];
// memory clean!
free(hsb);
free(params);
return color;
}
color = [self.class colorFromHEXString:string];
return color;
}
+ (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,%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 [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
{
const char* validList = "0123456789ABCDEFabcdef#";
for (NSInteger i = 0; i < string.length; i++) {
char c = [string characterAtIndex:i];
if (strchr(validList, c) == NULL) {
return NO;
}
}
return YES;
}
+ (unsigned long)lengthOfHEXInteger:(NSUInteger)hex
{
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 || string.length == 0 || ![self.class isHex:string]) {
return nil;
}
if ([string hasPrefix:@"#"] == YES) {
string = [string substringFromIndex:1];
}
// whats the length?
NSUInteger length = string.length;
if (length == 3 || length == 4) {
// shorthand...
NSMutableString* str = [[[NSMutableString alloc] init] autorelease];
for (NSInteger i = 0; i < length; i++) {
NSString* sub = [string substringWithRange:NSMakeRange(i, 1)];
[str appendFormat:@"%@%@", sub, sub];
}
string = str;
}
// now convert rest to hex
unsigned long hex = [self HEXFromArbitraryHexString:string];
if (containsAlphaComponent != nil) {
*containsAlphaComponent = [self HEXContainsAlphaComponent:hex];
}
return [self colorFromHEXInteger:hex];
}
@end
@@ -0,0 +1,31 @@
//
// IJSVGColorList.h
// IconJar
//
// Created by Curtis Hard on 07/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGColor.h"
#import <Foundation/Foundation.h>
@interface IJSVGColorList : NSObject <NSCopying> {
@private
NSMutableDictionary<NSColor*, NSColor*>* _replacementColorTree;
NSMutableSet<NSColor*>* _colors;
}
- (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<NSColor*>*)colors;
- (void)addColor:(NSColor*)color;
@end
@@ -0,0 +1,112 @@
//
// 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<NSColor*>*)colors
{
return [NSSet setWithSet:_colors];
}
- (void)addColorsFromList:(IJSVGColorList*)sheet
{
[_colors addObjectsFromArray:sheet.colors.allObjects];
}
- (void)addColor:(NSColor*)color
{
[_colors addObject:[IJSVGColor computeColorSpace:color]];
}
- (void)removeColor:(NSColor*)color
{
[_colors removeObject:[IJSVGColor computeColorSpace:color]];
}
@end
@@ -0,0 +1,72 @@
//
// IJSVGCommand.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGPath.h"
#import <Foundation/Foundation.h>
static const NSInteger IJSVGCustomVariableParameterCount = NSNotFound;
typedef NS_ENUM(NSInteger, IJSVGCommandType) {
kIJSVGCommandTypeAbsolute,
kIJSVGCommandTypeRelative
};
typedef NS_ENUM(NSUInteger, IJSVGPathDataSequence) {
kIJSVGPathDataSequenceTypeFloat,
kIJSVGPathDataSequenceTypeFlag
};
@interface IJSVGCommand : NSObject {
NSString* commandString;
NSString* command;
CGFloat* parameters;
NSInteger parameterCount;
NSArray<IJSVGCommand*>* subCommands;
NSInteger requiredParameters;
IJSVGCommandType type;
IJSVGCommand* previousCommand;
NSInteger _currentIndex;
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) 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)initWithCommandString:(NSString*)commandString;
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
previousCommand:(IJSVGCommand*)command;
- (CGFloat)readFloat;
- (NSPoint)readPoint;
- (BOOL)readBOOL;
- (void)resetRead;
@end
@@ -0,0 +1,212 @@
//
// 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
@synthesize commandString;
@synthesize command;
@synthesize parameterCount;
@synthesize parameters;
@synthesize subCommands;
@synthesize requiredParameters;
@synthesize type;
@synthesize previousCommand;
@synthesize isSubCommand;
+ (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)([command release]), command = nil;
(void)([subCommands release]), subCommands = nil;
if (parameters) {
(void)(free(parameters)), parameters = nil;
}
[super dealloc];
}
- (id)initWithCommandString:(NSString*)str
{
if ((self = [super init]) != nil) {
// work out the basics
_currentIndex = 0;
command = [[str substringToIndex:1] copy];
type = [IJSVGUtils typeForCommandString:self.command];
requiredParameters = [self.class requiredParameterCount];
NSInteger sets = 0;
IJSVGPathDataSequence* sequence = [self.class pathDataSequence];
parameters = IJSVGParsePathDataSequence(str, sequence, requiredParameters, &sets);
if (sets <= 1) {
CGFloat* subParams = [self parametersFromIndexOffset:0];
IJSVGCommand* command = [self subcommandWithParameters:subParams
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
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.requiredParameters;
if (req != 0) {
subParams = (CGFloat*)malloc(req * sizeof(CGFloat));
memcpy(subParams, &self.parameters[index * req], sizeof(CGFloat) * req);
}
return subParams;
}
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
previousCommand:(IJSVGCommand*)aPreviousCommand
{
// 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 = 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;
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandClose : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandClose : IJSVGCommand
@end
@@ -10,23 +10,17 @@
@implementation IJSVGCommandClose
+ (void)load
{
[IJSVGCommand registerClass:[self class]
forCommand:@"z"];
}
+ (NSInteger)requiredParameterCount
{
return 0;
}
+ (void)runWithParams:(CGFloat *)params
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand *)currentCommand
previousCommand:(IJSVGCommand *)command
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath *)path
path:(IJSVGPath*)path
{
[path close];
}
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandCurve : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandCurve : IJSVGCommand
@end
@@ -0,0 +1,36 @@
//
// 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) {
[[path currentSubpath] curveToPoint:NSMakePoint(params[4], params[5])
controlPoint1:NSMakePoint(params[0], params[1])
controlPoint2:NSMakePoint(params[2], params[3])];
return;
}
[[path currentSubpath] relativeCurveToPoint:NSMakePoint(params[4], params[5])
controlPoint1:NSMakePoint(params[0], params[1])
controlPoint2:NSMakePoint(params[2], params[3])];
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandArc : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandEllipticalArc : IJSVGCommand
@end
@@ -6,104 +6,119 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandArc.h"
#import "IJSVGCommandEllipticalArc.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandArc
@implementation IJSVGCommandEllipticalArc
+ (void)load
{
[IJSVGCommand registerClass:[self class]
forCommand:@"a"];
}
static IJSVGPathDataSequence* _sequence;
+ (NSInteger)requiredParameterCount
{
return 7;
}
+ (void)runWithParams:(CGFloat *)params
paramCount:(NSInteger)count
command:(IJSVGCommand *)currentCommand
previousCommand:(IJSVGCommand *)command
type:(IJSVGCommandType)type
path:(IJSVGPath *)path
+ (IJSVGPathDataSequence*)pathDataSequence
{
if(_sequence == NULL) {
_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;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
// command was taken from: https://github.com/jmenter/JAMSVGImage/blob/89b375c0c3203355a0c693e3b805458415bf4e29/Classes/JAMSVGImage/Path%20and%20Parser/JAMStyledBezierPathFactory.m
// and modified to purpose inside this to be converted into degrees and not radians
CGPoint radii = CGPointZero;
CGPoint arcEndPoint = CGPointZero;
CGPoint arcStartPoint = path.currentPoint;
CGFloat xAxisRotation = 0;
BOOL largeArcFlag = 0;
BOOL sweepFlag = 0;
radii = [currentCommand readPoint];
xAxisRotation = [currentCommand readFloat];
largeArcFlag = [currentCommand readBOOL];
sweepFlag = [currentCommand readBOOL];
arcEndPoint = [currentCommand readPoint];
if ( type == IJSVGCommandTypeRelative ) {
if (type == kIJSVGCommandTypeRelative) {
arcEndPoint.x += path.currentPoint.x;
arcEndPoint.y += path.currentPoint.y;
}
xAxisRotation *= M_PI / 180.f;
CGPoint currentPoint = CGPointMake(cos(xAxisRotation) * (arcStartPoint.x - arcEndPoint.x) / 2.0 + sin(xAxisRotation) * (arcStartPoint.y - arcEndPoint.y) / 2.0, -sin(xAxisRotation) * (arcStartPoint.x - arcEndPoint.x) / 2.0 + cos(xAxisRotation) * (arcStartPoint.y - arcEndPoint.y) / 2.0);
CGFloat radiiAdjustment = pow(currentPoint.x, 2) / pow(radii.x, 2) + pow(currentPoint.y, 2) / pow(radii.y, 2);
radii.x *= (radiiAdjustment > 1) ? sqrt(radiiAdjustment) : 1;
radii.y *= (radiiAdjustment > 1) ? sqrt(radiiAdjustment) : 1;
CGFloat sweep = (largeArcFlag == sweepFlag ? -1 : 1) * sqrt(((pow(radii.x, 2) * pow(radii.y, 2)) - (pow(radii.x, 2) * pow(currentPoint.y, 2)) - (pow(radii.y, 2) * pow(currentPoint.x, 2))) / (pow(radii.x, 2) * pow(currentPoint.y, 2) + pow(radii.y, 2) * pow(currentPoint.x, 2)));
sweep = (sweep != sweep) ? 0 : sweep;
CGPoint preCenterPoint = CGPointMake(sweep * radii.x * currentPoint.y / radii.y, sweep * -radii.y * currentPoint.x / radii.x);
CGPoint centerPoint = CGPointMake((arcStartPoint.x + arcEndPoint.x) / 2.0 + cos(xAxisRotation) * preCenterPoint.x - sin(xAxisRotation) * preCenterPoint.y, (arcStartPoint.y + arcEndPoint.y) / 2.0 + sin(xAxisRotation) * preCenterPoint.x + cos(xAxisRotation) * preCenterPoint.y);
CGFloat startAngle = angle(CGPointMake(1, 0), CGPointMake((currentPoint.x-preCenterPoint.x)/radii.x,
(currentPoint.y-preCenterPoint.y)/radii.y));
CGFloat startAngle = angle(CGPointMake(1, 0), CGPointMake((currentPoint.x - preCenterPoint.x) / radii.x, (currentPoint.y - preCenterPoint.y) / radii.y));
CGPoint deltaU = CGPointMake((currentPoint.x - preCenterPoint.x) / radii.x,
(currentPoint.y - preCenterPoint.y) / radii.y);
(currentPoint.y - preCenterPoint.y) / radii.y);
CGPoint deltaV = CGPointMake((-currentPoint.x - preCenterPoint.x) / radii.x,
(-currentPoint.y - preCenterPoint.y) / radii.y);
(-currentPoint.y - preCenterPoint.y) / radii.y);
CGFloat angleDelta = (deltaU.x * deltaV.y < deltaU.y * deltaV.x ? -1 : 1) * acos(ratio(deltaU, deltaV));
angleDelta = (ratio(deltaU, deltaV) <= -1) ? M_PI : (ratio(deltaU, deltaV) >= 1) ? 0 : angleDelta;
// check for actually numbers, if this is not valid
// kill it, blame WWDC 2017 SVG background for this...
if(isnan(startAngle) || isnan(angleDelta)) {
if (isnan(startAngle) || isnan(angleDelta)) {
return;
}
CGFloat radius = MAX(radii.x, radii.y);
CGPoint scale = (radii.x > radii.y) ? CGPointMake(1, radii.y / radii.x) : CGPointMake(radii.x / radii.y, 1);
NSAffineTransform * trans = [NSAffineTransform transform];
NSAffineTransform* trans = NSAffineTransform.transform;
[trans translateXBy:-centerPoint.x yBy:-centerPoint.y];
[trans rotateByRadians:-xAxisRotation];
[trans scaleXBy:(1/scale.x) yBy:(1/scale.y)];
[path.currentSubpath transformUsingAffineTransform:trans];
trans = NSAffineTransform.transform;
[trans rotateByRadians:-xAxisRotation];
[path.currentSubpath transformUsingAffineTransform:trans];
trans = NSAffineTransform.transform;
[trans scaleXBy:(1 / scale.x) yBy:(1 / scale.y)];
[path.currentSubpath transformUsingAffineTransform:trans];
[path.currentSubpath appendBezierPathWithArcWithCenter:NSZeroPoint
radius:radius
startAngle:radians_to_degrees(startAngle)
endAngle:radians_to_degrees(startAngle + angleDelta)
clockwise:!sweepFlag];
trans = [NSAffineTransform transform];
[trans translateXBy:centerPoint.x yBy:centerPoint.y];
[trans rotateByRadians:xAxisRotation];
trans = NSAffineTransform.transform;
[trans scaleXBy:scale.x yBy:scale.y];
[path.currentSubpath transformUsingAffineTransform:trans];
trans = NSAffineTransform.transform;
[trans rotateByRadians:xAxisRotation];
[path.currentSubpath transformUsingAffineTransform:trans];
trans = NSAffineTransform.transform;
[trans translateXBy:centerPoint.x yBy:centerPoint.y];
[path.currentSubpath transformUsingAffineTransform:trans];
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandHorizontalLine : NSObject <IJSVGCommandProtocol>
@interface IJSVGCommandHorizontalLine : IJSVGCommand
@end
@@ -0,0 +1,32 @@
//
// 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) {
[[path currentSubpath] lineToPoint:NSMakePoint(params[0], [path currentSubpath].currentPoint.y)];
return;
}
[[path currentSubpath] relativeLineToPoint:NSMakePoint(params[0], 0.f)];
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandLineTo : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandLineTo : IJSVGCommand
@end
@@ -0,0 +1,34 @@
//
// 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) {
[[path currentSubpath] lineToPoint:NSMakePoint(params[0], params[1])];
return;
}
NSPoint point = NSMakePoint([path currentSubpath].currentPoint.x + params[0],
[path currentSubpath].currentPoint.y + params[1]);
[[path currentSubpath] lineToPoint:point];
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandMove : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandMove : IJSVGCommand
@end
@@ -6,34 +6,26 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandMove.h"
#import "IJSVGCommandLineTo.h"
#import "IJSVGCommandMove.h"
@implementation IJSVGCommandMove
+ (void)load
{
[IJSVGCommand registerClass:[self class]
forCommand:@"m"];
}
+ (NSInteger)requiredParameterCount
{
return 2;
}
+ (void)runWithParams:(CGFloat *)params
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand *)currentCommand
previousCommand:(IJSVGCommand *)command
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath *)path
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.commandClass == [self class])
{
if (command.class == self.class && currentCommand.isSubCommand == YES) {
[IJSVGCommandLineTo runWithParams:params
paramCount:count
command:currentCommand
@@ -42,18 +34,17 @@
path:path];
return;
}
// actual move to command
if( type == IJSVGCommandTypeAbsolute )
{
[[path currentSubpath] moveToPoint:NSMakePoint( params[0], params[1])];
if (type == kIJSVGCommandTypeAbsolute) {
[[path currentSubpath] moveToPoint:NSMakePoint(params[0], params[1])];
return;
}
@try {
[[path currentSubpath] relativeMoveToPoint:NSMakePoint( params[0], params[1])];
[[path currentSubpath] relativeMoveToPoint:NSMakePoint(params[0], params[1])];
}
@catch (NSException *exception) {
[[path currentSubpath] moveToPoint:NSMakePoint( params[0], params[1])];
@catch (NSException* exception) {
[[path currentSubpath] moveToPoint:NSMakePoint(params[0], params[1])];
}
}
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandQuadraticCurve : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandQuadraticCurve : IJSVGCommand
@end
@@ -11,28 +11,21 @@
@implementation IJSVGCommandQuadraticCurve
+ (void)load
{
[IJSVGCommand registerClass:[self class]
forCommand:@"q"];
}
+ (NSInteger)requiredParameterCount
{
return 4;
}
+ (void)runWithParams:(CGFloat *)params
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand *)currentCommand
previousCommand:(IJSVGCommand *)command
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath *)path
path:(IJSVGPath*)path
{
if( type == IJSVGCommandTypeAbsolute )
{
[[path currentSubpath] addQuadCurveToPoint:NSMakePoint( params[2], params[3])
controlPoint:NSMakePoint( params[0], params[1])];
if (type == kIJSVGCommandTypeAbsolute) {
[[path currentSubpath] addQuadCurveToPoint:NSMakePoint(params[2], params[3])
controlPoint:NSMakePoint(params[0], params[1])];
return;
}
[[path currentSubpath] addQuadCurveToPoint:NSMakePoint([path currentSubpath].currentPoint.x + params[2], [path currentSubpath].currentPoint.y + params[3])
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandSmoothCurve : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandSmoothCurve : IJSVGCommand
@end
@@ -0,0 +1,64 @@
//
// 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
{
NSPoint firstControl = NSMakePoint([path currentSubpath].currentPoint.x, [path currentSubpath].currentPoint.y);
if (command != nil) {
if (command.class == [IJSVGCommandCurve class] || command.class == self.class) {
if (command.class == [IJSVGCommandCurve class]) {
if (command.type == kIJSVGCommandTypeAbsolute) {
firstControl = NSMakePoint(-1 * command.parameters[2] + 2 * [path currentSubpath].currentPoint.x,
-1 * command.parameters[3] + 2 * [path currentSubpath].currentPoint.y);
} else {
NSPoint oldPoint = NSMakePoint([path currentSubpath].currentPoint.x - command.parameters[4],
[path currentSubpath].currentPoint.y - command.parameters[5]);
firstControl = NSMakePoint(-1 * (command.parameters[2] + oldPoint.x) + 2 * [path currentSubpath].currentPoint.x,
-1 * (command.parameters[3] + oldPoint.y) + 2 * [path currentSubpath].currentPoint.y);
}
} else {
if (command.type == kIJSVGCommandTypeAbsolute) {
firstControl = NSMakePoint(-1 * command.parameters[0] + 2 * [path currentSubpath].currentPoint.x,
-1 * command.parameters[1] + 2 * [path currentSubpath].currentPoint.y);
} else {
NSPoint oldPoint = NSMakePoint([path currentSubpath].currentPoint.x - command.parameters[2],
[path currentSubpath].currentPoint.y - command.parameters[3]);
firstControl = NSMakePoint(-1 * (command.parameters[0] + oldPoint.x) + 2 * [path currentSubpath].currentPoint.x,
-1 * (command.parameters[1] + oldPoint.y) + 2 * [path currentSubpath].currentPoint.y);
}
}
}
}
if (type == kIJSVGCommandTypeAbsolute) {
[[path currentSubpath] curveToPoint:NSMakePoint(params[2], params[3])
controlPoint1:NSMakePoint(firstControl.x, firstControl.y)
controlPoint2:NSMakePoint(params[0], params[1])];
return;
}
[[path currentSubpath] curveToPoint:NSMakePoint([path currentSubpath].currentPoint.x + params[2], [path currentSubpath].currentPoint.y + params[3])
controlPoint1:NSMakePoint(firstControl.x, firstControl.y)
controlPoint2:NSMakePoint([path currentSubpath].currentPoint.x + params[0], [path currentSubpath].currentPoint.y + params[1])];
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandCommandSmoothQuadraticCurve : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandSmoothQuadraticCurve : IJSVGCommand
@end
@@ -0,0 +1,56 @@
//
// 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
{
NSPoint commandPoint = NSMakePoint([path currentSubpath].currentPoint.x, [path currentSubpath].currentPoint.y);
if (command != nil) {
if (command.class == IJSVGCommandQuadraticCurve.class) {
// quadratic curve
if (command.type == kIJSVGCommandTypeAbsolute) {
commandPoint = NSMakePoint(-1 * command.parameters[0] + 2 * [path currentSubpath].currentPoint.x,
-1 * command.parameters[1] + 2 * [path currentSubpath].currentPoint.y);
} else {
NSPoint oldPoint = CGPointMake([path currentSubpath].currentPoint.x - command.parameters[2],
[path currentSubpath].currentPoint.y - command.parameters[3]);
commandPoint = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * ([path currentSubpath].currentPoint.x),
-1 * (command.parameters[1] + oldPoint.y) + 2 * [path currentSubpath].currentPoint.y);
}
} else if (command.class == self.class) {
// smooth quadratic curve
commandPoint = CGPointMake(-1 * (path.lastControlPoint.x) + 2 * ([path currentSubpath].currentPoint.x),
-1 * (path.lastControlPoint.y) + 2 * [path currentSubpath].currentPoint.y);
}
}
path.lastControlPoint = commandPoint;
if (type == kIJSVGCommandTypeAbsolute) {
[[path currentSubpath] addQuadCurveToPoint:NSMakePoint(params[0], params[1])
controlPoint:commandPoint];
return;
}
[[path currentSubpath] addQuadCurveToPoint:NSMakePoint([path currentSubpath].currentPoint.x + params[0], [path currentSubpath].currentPoint.y + params[1])
controlPoint:commandPoint];
}
@end
@@ -6,9 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGCommand.h"
#import <Foundation/Foundation.h>
@interface IJSVGCommandVerticalLine : IJSVGCommand <IJSVGCommandProtocol>
@interface IJSVGCommandVerticalLine : IJSVGCommand
@end
@@ -0,0 +1,32 @@
//
// 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) {
[[path currentSubpath] lineToPoint:NSMakePoint([path currentSubpath].currentPoint.x, params[0])];
return;
}
[[path currentSubpath] relativeLineToPoint:NSMakePoint(0.f, params[0])];
}
@end
@@ -0,0 +1,63 @@
//
// IJSVGExporter.h
// IJSVGExample
//
// Created by Curtis Hard on 06/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
@class IJSVG;
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,
IJSVGExporterOptionAll = IJSVGExporterOptionRemoveUselessDef | IJSVGExporterOptionRemoveUselessGroups | IJSVGExporterOptionCreateUseForPaths | IJSVGExporterOptionMoveAttributesToGroup | IJSVGExporterOptionSortAttributes | IJSVGExporterOptionCollapseGroups | IJSVGExporterOptionCleanupPaths | IJSVGExporterOptionRemoveHiddenElements | IJSVGExporterOptionScaleToSizeIfNecessary | IJSVGExporterOptionCompressOutput | IJSVGExporterOptionCollapseGradients | IJSVGExporterOptionRemoveWidthHeightAttributes | IJSVGExporterOptionColorAllowRRGGBBAA | IJSVGExporterOptionRemoveComments
};
BOOL IJSVGExporterHasOption(IJSVGExporterOptions options, NSInteger option);
void IJSVGEnumerateCGPathElements(CGPathRef path, IJSVGPathElementEnumerationBlock enumBlock);
@interface IJSVGExporter : NSObject {
@private
IJSVG* _svg;
CGSize _size;
IJSVGExporterOptions _options;
NSXMLDocument* _dom;
NSXMLElement* _defElement;
NSXMLElement* _scaledRootNode;
NSInteger _idCount;
NSInteger _shortIdCount;
}
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* description;
- (id)initWithSVG:(IJSVG*)svg
size:(CGSize)size
options:(IJSVGExporterOptions)options;
- (NSString*)SVGString;
- (NSData*)SVGData;
@end
File diff suppressed because it is too large Load Diff
@@ -9,24 +9,24 @@
#import <Foundation/Foundation.h>
@interface IJSVGExporterPathInstruction : NSObject {
@private
NSInteger _dataCount;
char _instruction;
CGFloat * _data;
CGFloat* _data;
}
+ (NSArray<IJSVGExporterPathInstruction *> *)instructionsFromPath:(CGPathRef)path;
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path;
- (id)initWithInstruction:(char)instruction
dataCount:(NSInteger)floatCount;
- (void)setInstruction:(char)newInstruction;
- (char)instruction;
- (CGFloat *)data;
- (CGFloat*)data;
- (NSInteger)dataLength;
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction *> *)instructions;
+ (NSString *)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction *> *)instructions;
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions;
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions;
@end
@@ -0,0 +1,369 @@
//
// IJSVGExporterPathInstruction.m
// IconJar
//
// Created by Curtis Hard on 08/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGExporter.h"
#import "IJSVGExporterPathInstruction.h"
@implementation IJSVGExporterPathInstruction
- (void)dealloc
{
if (_data != NULL) {
free(_data);
}
[super dealloc];
}
- (id)initWithInstruction:(char)instruction
dataCount:(NSInteger)floatCount
{
if ((self = [super init]) != nil) {
_instruction = instruction;
// only allocate if not zero
if (floatCount != 0) {
_data = (CGFloat*)calloc(sizeof(CGFloat), floatCount);
}
}
return self;
}
- (NSInteger)dataLength
{
return _dataCount;
}
- (void)setInstruction:(char)newInstruction
{
_instruction = newInstruction;
}
- (char)instruction
{
return _instruction;
}
- (CGFloat*)data
{
return _data;
}
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
{
NSMutableArray* pathData = [[[NSMutableArray alloc] init] autorelease];
for (IJSVGExporterPathInstruction* instruction in instructions) {
CGFloat* data = instruction.data;
NSString* str = nil;
switch (instruction.instruction) {
// move
case 'M':
case 'm': {
char* buffer;
asprintf(&buffer, "%c%g,%g", instruction.instruction, data[0], data[1]);
str = [NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding];
free(buffer);
[pathData addObject:str];
break;
}
// vertical and horizonal line
case 'V':
case 'v':
case 'H':
case 'h': {
char* buffer;
asprintf(&buffer, "%c%g", instruction.instruction, data[0]);
str = [NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding];
free(buffer);
[pathData addObject:str];
break;
}
// line
case 'L':
case 'l': {
char* buffer;
asprintf(&buffer, "%c%g,%g", instruction.instruction, data[0], data[1]);
str = [NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding];
free(buffer);
[pathData addObject:str];
break;
}
// curve
case 'C':
case 'c': {
char* buffer;
asprintf(&buffer, "%c%g,%g %g,%g %g,%g", instruction.instruction,
data[0], data[1], data[2], data[3], data[4], data[5]);
str = [NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding];
free(buffer);
[pathData addObject:str];
break;
}
// quadratic curve
case 'Q':
case 'q': {
char* buffer;
asprintf(&buffer, "%c%g,%g %g,%g", instruction.instruction,
data[0], data[1], data[2], data[3]);
str = [NSString stringWithCString:buffer
encoding:NSUTF8StringEncoding];
free(buffer);
[pathData addObject:str];
break;
}
// close path
case 'Z':
case 'z': {
str = [NSString stringWithFormat:@"%c", instruction.instruction];
[pathData addObject:str];
}
}
}
return [pathData componentsJoinedByString:@""];
}
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
{
CGFloat point[2] = { 0, 0 };
CGFloat subpathPoint[2] = { 0, 0 };
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];
}
} 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];
} 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 setInstruction:instruction];
} else if (instruction == 'Z' || instruction == 'z') {
point[0] = subpathPoint[0];
point[1] = subpathPoint[1];
}
// increment index
index++;
}
}
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
{
// 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
@@ -6,15 +6,18 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "IJSVGGradient.h"
#import "IJSVGPath.h"
#import "IJSVGLayer.h"
#import "IJSVGPath.h"
#import <QuartzCore/QuartzCore.h>
@interface IJSVGGradientLayer : IJSVGLayer {
}
@property (nonatomic, retain) IJSVGGradient * gradient;
@property (nonatomic, assign) CGRect viewBox;
@property (nonatomic, retain) IJSVGGradient* gradient;
@property (nonatomic, assign) CGAffineTransform absoluteTransform;
@property (nonatomic, assign) CGRect objectRect;
@end
@@ -0,0 +1,103 @@
//
// IJSVGGradientLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGGradientLayer.h"
@implementation IJSVGGradientLayer
@synthesize viewBox;
@synthesize gradient;
@synthesize absoluteTransform;
@synthesize objectRect;
- (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
@@ -6,9 +6,9 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "IJSVGLayer.h"
#import "IJSVGShapeLayer.h"
#import <QuartzCore/QuartzCore.h>
@interface IJSVGGroupLayer : IJSVGLayer
@@ -6,14 +6,14 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "IJSVGLayer.h"
#import <AppKit/AppKit.h>
#import <QuartzCore/QuartzCore.h>
@interface IJSVGImageLayer : IJSVGLayer {
}
- (id)initWithImage:(NSImage *)image;
- (id)initWithImage:(NSImage*)image;
- (id)initWithCGImage:(CGImageRef)imageRef;
@end
@@ -10,7 +10,7 @@
@implementation IJSVGImageLayer
- (id)initWithImage:(NSImage *)image
- (id)initWithImage:(NSImage*)image
{
NSRect rect = (NSRect){
.origin = NSZeroPoint,
@@ -24,21 +24,32 @@
- (id)initWithCGImage:(CGImageRef)imageRef
{
if((self = [super init]) != nil) {
if ((self = [super init]) != nil) {
// set the contents
self.contents = (id)imageRef;
// make sure we say we need help
self.requiresBackingScaleHelp = YES;
self.shouldRasterize = YES;
// set the frame, simple stuff
self.frame = (CGRect){
.origin = CGPointZero,
.size = CGSizeMake( CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef))
.size = CGSizeMake(CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef))
};
}
return self;
}
- (void)setNeedsDisplay
{
// swap the content around on call
// because set needs display discards previous
// content - yolo!
id oldContent = self.contents;
[super setNeedsDisplay];
self.contents = oldContent;
}
@end
@@ -6,8 +6,9 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "IJSVGRendering.h"
#import "IJSVGTransaction.h"
#import <QuartzCore/QuartzCore.h>
@class IJSVGShapeLayer;
@class IJSVGGradientLayer;
@@ -16,28 +17,29 @@
@class IJSVGGroupLayer;
@interface IJSVGLayer : CALayer {
@private
IJSVGLayer * _maskingLayer;
IJSVGLayer* _maskingLayer;
}
@property (nonatomic, assign) IJSVGGradientLayer * gradientFillLayer;
@property (nonatomic, assign) IJSVGPatternLayer * patternFillLayer;
@property (nonatomic, assign) IJSVGStrokeLayer * strokeLayer;
@property (nonatomic, assign) IJSVGGradientLayer * gradientStrokeLayer;
@property (nonatomic, assign) IJSVGPatternLayer * patternStrokeLayer;
@property (nonatomic, assign) IJSVGGradientLayer* gradientFillLayer;
@property (nonatomic, assign) IJSVGPatternLayer* patternFillLayer;
@property (nonatomic, assign) IJSVGStrokeLayer* strokeLayer;
@property (nonatomic, assign) IJSVGGradientLayer* gradientStrokeLayer;
@property (nonatomic, assign) IJSVGPatternLayer* patternStrokeLayer;
@property (nonatomic, assign) BOOL requiresBackingScaleHelp;
@property (nonatomic, assign) CGFloat backingScaleFactor;
@property (nonatomic, assign) IJSVGRenderQuality renderQuality;
@property (nonatomic, assign) CGBlendMode blendingMode;
@property (nonatomic, assign) CGPoint absoluteOrigin;
@property (nonatomic, assign) BOOL convertMasksToPaths;
+ (NSArray *)deepestSublayersOfLayer:(CALayer *)layer;
+ (void)recursivelyWalkLayer:(CALayer *)layer
withBlock:(void (^)(CALayer * layer, BOOL isMask))block;
+ (NSArray*)deepestSublayersOfLayer:(CALayer*)layer;
+ (void)recursivelyWalkLayer:(CALayer*)layer
withBlock:(void (^)(CALayer* layer, BOOL isMask))block;
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer *)sublayer
forSublayer:(IJSVGLayer*)sublayer
withOffset:(CGPoint)offset;
@end
@@ -0,0 +1,169 @@
//
// 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
@synthesize gradientFillLayer;
@synthesize patternFillLayer;
@synthesize gradientStrokeLayer;
@synthesize patternStrokeLayer;
@synthesize strokeLayer;
@synthesize requiresBackingScaleHelp;
@synthesize backingScaleFactor;
@synthesize blendingMode;
@synthesize convertMasksToPaths;
- (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))block
{
// call for layer and mask if there is one
block(layer, NO);
// do the mask too!
if (layer.mask != nil) {
block(layer.mask, YES);
}
// sublayers!!
for (CALayer* aLayer in layer.sublayers) {
[self recursivelyWalkLayer:aLayer
withBlock:block];
}
}
- (void)setBackingScaleFactor:(CGFloat)newFactor
{
if (self.backingScaleFactor == newFactor) {
return;
}
backingScaleFactor = newFactor;
self.contentsScale = newFactor;
self.rasterizationScale = newFactor;
[self setNeedsDisplay];
}
- (void)_customRenderInContext:(CGContextRef)ctx
{
if (self.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 (self.blendingMode != kCGBlendModeNormal) {
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx, self.blendingMode);
[self _customRenderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[self _customRenderInContext:ctx];
}
- (id<CAAction>)actionForKey:(NSString*)event
{
return nil;
}
@end
@@ -6,13 +6,13 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "IJSVGLayer.h"
#import "IJSVGPattern.h"
#import <QuartzCore/QuartzCore.h>
@interface IJSVGPatternLayer : IJSVGLayer
@property (nonatomic, retain) IJSVGLayer * pattern;
@property (nonatomic, retain) IJSVGPattern * patternNode;
@property (nonatomic, retain) IJSVGLayer* pattern;
@property (nonatomic, retain) IJSVGPattern* patternNode;
@end
@@ -15,49 +15,51 @@
- (void)dealloc
{
[pattern release], pattern = nil;
[patternNode release], patternNode = nil;
(void)([pattern release]), pattern = nil;
(void)([patternNode release]), patternNode = nil;
[super dealloc];
}
- (id)init
{
if((self = [super init]) != nil) {
if ((self = [super init]) != nil) {
self.requiresBackingScaleHelp = YES;
self.shouldRasterize = YES;
}
return self;
}
void IJSVGPatternDrawingCallBack(void * info, CGContextRef ctx) {
void IJSVGPatternDrawingCallBack(void* info, CGContextRef ctx)
{
// reassign the layer
IJSVGPatternLayer * layer = (IJSVGPatternLayer *)info;
IJSVGPatternLayer* layer = (IJSVGPatternLayer*)info;
[layer.pattern renderInContext:ctx];
};
- (void)drawInContext:(CGContextRef)ctx
{
// holder for callback
static const CGPatternCallbacks callbacks = {0, &IJSVGPatternDrawingCallBack, NULL};
static const CGPatternCallbacks callbacks = { 0, &IJSVGPatternDrawingCallBack, NULL };
// create base pattern space
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace(ctx, patternSpace);
CGColorSpaceRelease(patternSpace);
// create the pattern
CGRect rect = self.bounds;
CGPatternRef ref = CGPatternCreate( (void *)self, self.bounds,
CGAffineTransformIdentity,
roundf(rect.size.width*self.patternNode.width.value),
roundf(rect.size.height*self.patternNode.height.value),
kCGPatternTilingConstantSpacing,
true, &callbacks);
CGPatternRef ref = CGPatternCreate((void*)self, self.bounds,
CGAffineTransformIdentity,
roundf(rect.size.width * self.patternNode.width.value),
roundf(rect.size.height * self.patternNode.height.value),
kCGPatternTilingConstantSpacing,
true, &callbacks);
// set the pattern then release it
CGFloat alpha = 1.f;
CGContextSetFillPattern(ctx, ref, &alpha);
CGPatternRelease(ref);
// fill it
CGContextFillRect(ctx, rect);
}
@@ -0,0 +1,23 @@
//
// IJSVGRadialGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "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
@@ -0,0 +1,159 @@
//
// IJSVGRadialGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGRadialGradient.h"
@implementation IJSVGRadialGradient
@synthesize cx;
@synthesize cy;
@synthesize fx;
@synthesize fy;
@synthesize radius;
- (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 = self.fx;
grad.fy = self.fy;
grad.cx = self.cx;
grad.cy = self.cy;
grad.radius = self.radius;
return grad;
}
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGRadialGradient*)gradient
{
// cx defaults to 50% if not specified
NSDictionary* kv = @{ @"cx" : @"cx",
@"cy" : @"cy",
@"r" : @"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:@"fx"].stringValue;
if (fx != nil) {
gradient.fx = [IJSVGUnitLength unitWithString:fx
fromUnitType:gradient.units];
}
NSString* fy = [element attributeForName:@"fy"].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 computeColorStopsFromString:element 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 = [self.cx computeValue:CGRectGetWidth(boundingBox)];
CGFloat y = [self.cy computeValue:CGRectGetHeight(boundingBox)];
startPoint = CGPointMake(x, y);
CGFloat val = MIN(CGRectGetWidth(boundingBox),
CGRectGetHeight(boundingBox));
radius = [self.radius computeValue:val];
CGFloat ex = [self.fx computeValue:CGRectGetWidth(boundingBox)];
CGFloat ey = [self.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
@@ -6,29 +6,32 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "IJSVGLayer.h"
#import "IJSVGUtils.h"
#import <QuartzCore/QuartzCore.h>
@interface IJSVGShapeLayer : CAShapeLayer {
@private
IJSVGLayer * _maskingLayer;
IJSVGLayer* _maskingLayer;
}
@property (nonatomic, assign) IJSVGGradientLayer * gradientFillLayer;
@property (nonatomic, assign) IJSVGPatternLayer * patternFillLayer;
@property (nonatomic, assign) IJSVGStrokeLayer * strokeLayer;
@property (nonatomic, assign) IJSVGGradientLayer * gradientStrokeLayer;
@property (nonatomic, assign) IJSVGPatternLayer * patternStrokeLayer;
@property (nonatomic, assign) IJSVGGradientLayer* gradientFillLayer;
@property (nonatomic, assign) IJSVGPatternLayer* patternFillLayer;
@property (nonatomic, assign) IJSVGStrokeLayer* strokeLayer;
@property (nonatomic, assign) IJSVGGradientLayer* gradientStrokeLayer;
@property (nonatomic, assign) IJSVGPatternLayer* patternStrokeLayer;
@property (nonatomic, assign) BOOL requiresBackingScaleHelp;
@property (nonatomic, assign) CGFloat backingScaleFactor;
@property (nonatomic, assign) IJSVGRenderQuality renderQuality;
@property (nonatomic, assign) CGBlendMode blendingMode;
@property (nonatomic, assign) CGPoint absoluteOrigin;
@property (nonatomic, assign) CGPoint originalPathOrigin;
@property (nonatomic, assign) BOOL convertMasksToPaths;
@property (nonatomic, assign) IJSVGPrimitivePathType primitiveType;
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer *)sublayer
forSublayer:(IJSVGLayer*)sublayer
withOffset:(CGPoint)offset;
@end
@@ -6,8 +6,8 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGShapeLayer.h"
#import "IJSVGGroupLayer.h"
#import "IJSVGShapeLayer.h"
@implementation IJSVGShapeLayer
@@ -20,31 +20,19 @@
@synthesize backingScaleFactor;
@synthesize blendingMode;
@synthesize convertMasksToPaths;
@synthesize originalPathOrigin;
@synthesize renderQuality;
@synthesize primitiveType;
- (void)dealloc
{
IJSVGBeginTransactionLock();
[_maskingLayer release], _maskingLayer = nil;
(void)([_maskingLayer release]), _maskingLayer = nil;
[super dealloc];
IJSVGEndTransactionLock();
}
- (void)addSublayer:(CALayer *)layer {
if([layer isKindOfClass:[IJSVGLayer class]] == NO &&
[layer isKindOfClass:[IJSVGShapeLayer class]] == NO) {
NSString * r = [NSString stringWithFormat:@"The layer must be an instance of IJSVGLayer, %@ given.",
[layer class]];
NSException * exception = [NSException exceptionWithName:@"IJSVGInvalidSublayerException"
reason:r
userInfo:nil];
@throw exception;
}
[super addSublayer:layer];
}
- (void)setBackingScaleFactor:(CGFloat)newFactor
{
if(self.backingScaleFactor == newFactor) {
if (self.backingScaleFactor == newFactor) {
return;
}
backingScaleFactor = newFactor;
@@ -55,10 +43,10 @@
- (void)_customRenderInContext:(CGContextRef)ctx
{
if(self.convertMasksToPaths == YES && _maskingLayer != nil) {
if (self.convertMasksToPaths == YES && _maskingLayer != nil) {
CGContextSaveGState(ctx);
[self applySublayerMaskToContext:ctx
forSublayer:(IJSVGLayer *)self
forSublayer:(IJSVGLayer*)self
withOffset:CGPointZero];
[super renderInContext:ctx];
CGContextRestoreGState(ctx);
@@ -69,49 +57,49 @@
- (void)setConvertMasksToPaths:(BOOL)flag
{
if(convertMasksToPaths == flag) {
if (convertMasksToPaths == flag) {
return;
}
convertMasksToPaths = flag;
if(flag == YES) {
if(_maskingLayer != nil) {
[_maskingLayer release], _maskingLayer = nil;
if (flag == YES) {
if (_maskingLayer != nil) {
(void)([_maskingLayer release]), _maskingLayer = nil;
}
_maskingLayer = [(IJSVGLayer *)self.mask retain];
_maskingLayer = [(IJSVGLayer*)self.mask retain];
self.mask = nil;
} else {
self.mask = _maskingLayer;
[_maskingLayer release], _maskingLayer = nil;
(void)([_maskingLayer release]), _maskingLayer = nil;
}
}
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer *)sublayer
forSublayer:(IJSVGLayer*)sublayer
withOffset:(CGPoint)offset
{
// apply any transforms needed
CGPoint layerOffset = offset;
CGAffineTransform sublayerTransform = CATransform3DGetAffineTransform(sublayer.transform);
CGContextConcatCTM( context, CGAffineTransformInvert(sublayerTransform) );
CGContextConcatCTM(context, CGAffineTransformInvert(sublayerTransform));
// walk up the superlayer chain
CALayer * superlayer = self.superlayer;
CALayer* superlayer = self.superlayer;
if (IJSVGIsSVGLayer(superlayer) == YES) {
[(IJSVGLayer *)superlayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer *)self
withOffset:layerOffset];
[(IJSVGLayer*)superlayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer*)self
withOffset:layerOffset];
}
// grab the masking layer
IJSVGShapeLayer * maskingLayer = [self maskingLayer];
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) {
if ([maskingLayer isKindOfClass:[IJSVGGroupLayer class]]) {
NSArray* subs = [IJSVGLayer deepestSublayersOfLayer:maskingLayer];
for (IJSVGLayer* subLayer in subs) {
[subLayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer *)self
forSublayer:(IJSVGLayer*)self
withOffset:layerOffset];
}
} else if ([maskingLayer isKindOfClass:[IJSVGShapeLayer class]]) {
@@ -125,14 +113,14 @@
CGContextConcatCTM(context, sublayerTransform);
}
- (IJSVGShapeLayer *)maskingLayer
- (IJSVGShapeLayer*)maskingLayer
{
return (IJSVGShapeLayer *)_maskingLayer ?: nil;
return (IJSVGShapeLayer*)_maskingLayer ?: nil;
}
- (void)renderInContext:(CGContextRef)ctx
{
if(self.blendingMode != kCGBlendModeNormal) {
if (self.blendingMode != kCGBlendModeNormal) {
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx, self.blendingMode);
[self _customRenderInContext:ctx];
@@ -145,8 +133,8 @@
- (CGPoint)absoluteOrigin
{
CGPoint point = CGPointZero;
CALayer * pLayer = self;
while(pLayer != nil) {
CALayer* pLayer = self;
while (pLayer != nil) {
point.x += pLayer.frame.origin.x;
point.y += pLayer.frame.origin.y;
pLayer = pLayer.superlayer;
@@ -154,4 +142,9 @@
return point;
}
- (id<CAAction>)actionForKey:(NSString*)event
{
return nil;
}
@end
@@ -6,16 +6,15 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGNode.h"
#import <Foundation/Foundation.h>
@interface IJSVGDef : IJSVGNode {
@private
NSMutableDictionary * _dict;
NSMutableDictionary* _dict;
}
- (void)addDef:(IJSVGNode *)aDef;
- (void)addDef:(IJSVGNode*)aDef;
@end
@@ -12,28 +12,28 @@
- (void)dealloc
{
[_dict release], _dict = nil;
(void)([_dict release]), _dict = nil;
[super dealloc];
}
- (id)init
{
if( ( self = [super initWithDef:NO] ) != nil ) {
if ((self = [super initWithDef:NO]) != nil) {
_dict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)addDef:(IJSVGNode *)aDef
- (void)addDef:(IJSVGNode*)aDef
{
if( aDef.identifier == nil ) {
if (aDef.identifier == nil) {
return;
}
[_dict setObject:aDef
forKey:aDef.identifier];
}
- (IJSVGDef *)defForID:(NSString *)anID
- (IJSVGDef*)defForID:(NSString*)anID
{
return [_dict objectForKey:anID];
}
@@ -10,7 +10,7 @@
#import "IJSVGNode.h"
@interface IJSVGForeignObject : IJSVGNode {
NSString * requiredExtension;
}
@@ -14,7 +14,7 @@
- (void)dealloc
{
[requiredExtension release], requiredExtension = nil;
(void)([requiredExtension release]), requiredExtension = nil;
[super dealloc];
}
@@ -0,0 +1,38 @@
//
// IJSVGGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGColorList.h"
#import "IJSVGDef.h"
#import "IJSVGTransform.h"
#import <Foundation/Foundation.h>
@interface IJSVGGradient : IJSVGNode
@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*)computeColorStopsFromString:(NSXMLElement*)element
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*)computedColorList;
@end
@@ -0,0 +1,179 @@
//
// IJSVGGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGradient.h"
@implementation IJSVGGradient
@synthesize gradient, CGGradient;
@synthesize x1, x2, y1, y2;
@synthesize colorList = _colorList;
- (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)([_colorList release]), _colorList = 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)([_colorList release]), _colorList = nil;
_colorList = list.retain;
if (CGGradient != nil) {
CGGradientRelease(CGGradient);
}
}
+ (CGFloat*)computeColorStopsFromString:(NSXMLElement*)element
colors:(NSArray**)someColors
{
// find each stop element
NSArray* stops = [element children];
NSMutableArray* colors = [[[NSMutableArray alloc] initWithCapacity:stops.count] autorelease];
CGFloat* stopsParams = (CGFloat*)malloc(stops.count * sizeof(CGFloat));
NSInteger i = 0;
for (NSXMLElement* stop in stops) {
// find the offset
CGFloat offset = [stop attributeForName:@"offset"].stringValue.floatValue;
if (offset > 1.f) {
offset /= 100.f;
}
stopsParams[i++] = offset;
// find the stop opacity
CGFloat stopOpacity = 1.f;
NSXMLNode* stopOpacityAttribute = [stop attributeForName:@"stop-opacity"];
if (stopOpacityAttribute != nil) {
stopOpacity = stopOpacityAttribute.stringValue.floatValue;
}
// find the stop color
NSString* scs = [stop attributeForName:@"stop-color"].stringValue;
NSColor* stopColor = [IJSVGColor colorFromString:scs];
if (stopColor != nil && stopOpacity != 1.f) {
stopColor = [IJSVGColor changeAlphaOnColor:stopColor
to:stopOpacity];
}
// compute any style that there was...
NSXMLNode* styleAttribute = [stop attributeForName:@"style"];
if (styleAttribute != nil) {
IJSVGStyle* style = [IJSVGStyle parseStyleString:styleAttribute.stringValue];
NSColor* color = [IJSVGColor colorFromString:[style property:@"stop-color"]];
// we have a color!
if (color != nil) {
// is there a stop opacity?
NSString* numberString = nil;
if ((numberString = [style property:@"stop-opacity"]) != nil) {
color = [IJSVGColor changeAlphaOnColor:color
to:numberString.floatValue];
} else {
color = [IJSVGColor changeAlphaOnColor:color
to:stopOpacity];
}
stopColor = color;
}
}
// default is black
if (stopColor == nil) {
stopColor = [IJSVGColor colorFromString:@"black"];
if (stopOpacity != 1.f) {
stopColor = [IJSVGColor changeAlphaOnColor:stopColor
to:stopOpacity];
}
}
// add the stop color
[(NSMutableArray*)colors addObject:stopColor];
}
*someColors = colors;
return stopsParams;
}
- (IJSVGColorList*)computedColorList
{
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];
[sheet addColor:color];
}
return sheet;
}
- (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 (_colorList != nil) {
color = [_colorList 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
@@ -6,18 +6,17 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGNode.h"
#import "IJSVGPath.h"
#import <Foundation/Foundation.h>
@interface IJSVGGroup : IJSVGNode {
NSMutableArray * children;
NSMutableArray* children;
}
- (void)addChild:(id)child;
- (NSArray *)children;
- (NSArray*)children;
- (void)purgeChildren;
@end
@@ -12,14 +12,13 @@
- (void)dealloc
{
[children release], children = nil;
(void)([children release]), children = nil;
[super dealloc];
}
- (id)init
{
if( ( self = [super init] ) != nil )
{
if ((self = [super init]) != nil) {
children = [[NSMutableArray alloc] init];
}
return self;
@@ -30,13 +29,12 @@
children = [[NSMutableArray alloc] init];
}
- (id)copyWithZone:(NSZone *)zone
- (id)copyWithZone:(NSZone*)zone
{
IJSVGGroup * node = [super copyWithZone:zone];
IJSVGGroup* node = [super copyWithZone:zone];
[node prepareFromCopy];
for( IJSVGNode * childNode in self.children )
{
for (IJSVGNode* childNode in self.children) {
childNode = [[childNode copy] autorelease];
childNode.parentNode = node;
[node addChild:childNode];
@@ -51,18 +49,18 @@
- (void)addChild:(id)child
{
if( child != nil )
if (child != nil)
[children addObject:child];
}
- (NSArray *)children
- (NSArray*)children
{
return children;
}
- (NSString *)description
- (NSString*)description
{
return [NSString stringWithFormat:@"%@ - %@",[super description],self.children];
return [NSString stringWithFormat:@"%@ - %@", [super description], self.children];
}
@end
@@ -6,22 +6,21 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGNode.h"
#import <Foundation/Foundation.h>
@class IJSVGPath;
@interface IJSVGImage : IJSVGNode {
NSImage * image;
NSImage* image;
CGImageRef CGImage;
IJSVGPath * imagePath;
IJSVGPath* imagePath;
}
- (CGImageRef)CGImage;
- (void)drawInContextRef:(CGContextRef)context
path:(IJSVGPath *)path;
- (void)loadFromBase64EncodedString:(NSString *)encodedString;
path:(IJSVGPath*)path;
- (void)loadFromBase64EncodedString:(NSString*)encodedString;
@end
@@ -14,30 +14,36 @@
- (void)dealloc
{
CGImageRelease(CGImage), CGImage = nil;
[imagePath release], imagePath = nil;
[image release], image = nil;
(void)(CGImageRelease(CGImage)), CGImage = nil;
(void)([imagePath release]), imagePath = nil;
(void)([image release]), image = nil;
[super dealloc];
}
- (void)loadFromBase64EncodedString:(NSString *)encodedString
- (void)loadFromBase64EncodedString:(NSString*)encodedString
{
NSURL * URL = [NSURL URLWithString:encodedString];
NSData * data = [NSData dataWithContentsOfURL:URL];
// no data, jsut ignore...invalid probably
if(data == nil) {
if ([encodedString hasPrefix:@"data:"]) {
encodedString = [encodedString stringByReplacingOccurrencesOfString:@"\\s+"
withString:@""
options:NSRegularExpressionSearch
range:NSMakeRange(0, encodedString.length)];
}
NSURL* URL = [NSURL URLWithString:encodedString];
NSData* data = [NSData dataWithContentsOfURL:URL];
// no data, just ignore...invalid probably
if (data == nil) {
return;
}
// set the image against the container
NSImage * anImage = [[[NSImage alloc] initWithData:data] autorelease];
NSImage* anImage = [[[NSImage alloc] initWithData:data] autorelease];
[self setImage:anImage];
}
- (IJSVGPath *)path
- (IJSVGPath*)path
{
if(imagePath == nil) {
if (imagePath == nil) {
// lazy load the path as it might not be needed
imagePath = [[IJSVGPath alloc] init];
[imagePath.path appendBezierPathWithRect:NSMakeRect(0.f, 0.f, self.width.value, self.height.value)];
@@ -46,23 +52,23 @@
return imagePath;
}
- (void)setImage:(NSImage *)anImage
- (void)setImage:(NSImage*)anImage
{
if(image != nil) {
[image release], image = nil;
if (image != nil) {
(void)([image release]), image = nil;
}
image = [anImage retain];
if(CGImage != nil) {
if (CGImage != nil) {
CGImageRelease(CGImage);
CGImage = nil;
}
NSRect rect = NSMakeRect( 0.f, 0.f, self.width.value, self.height.value);
NSRect rect = NSMakeRect(0.f, 0.f, self.width.value, self.height.value);
CGImage = [image CGImageForProposedRect:&rect
context:nil
hints:nil];
// be sure to retain (some reason this is required in Xcode 8 beta 5?)
CGImageRetain(CGImage);
}
@@ -73,29 +79,29 @@
}
- (void)drawInContextRef:(CGContextRef)context
path:(IJSVGPath *)path
path:(IJSVGPath*)path
{
// run the transforms
// draw the image
if(self.width.value == 0.f || self.height.value == 0.f) {
if (self.width.value == 0.f || self.height.value == 0.f) {
return;
}
// make sure path is set
if(path == nil) {
if (path == nil) {
path = [self path];
}
CGRect rect = path.path.bounds;
CGRect bounds = CGRectMake( 0.f, 0.f, rect.size.width, rect.size.height);
CGRect bounds = CGRectMake(0.f, 0.f, rect.size.width, rect.size.height);
// save the state of the context
CGContextSaveGState(context);
{
// flip the coordinates
CGContextTranslateCTM(context, rect.origin.x, (rect.origin.y)+rect.size.height);
CGContextTranslateCTM(context, rect.origin.x, (rect.origin.y) + rect.size.height);
CGContextScaleCTM(context, 1.f, -1.f);
CGContextDrawImage( context, bounds, CGImage);
CGContextDrawImage(context, bounds, CGImage);
}
CGContextRestoreGState(context);
}
@@ -6,14 +6,12 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGGradient.h"
#import <Foundation/Foundation.h>
@interface IJSVGLinearGradient : IJSVGGradient
+ (NSGradient *)parseGradient:(NSXMLElement *)element
gradient:(IJSVGLinearGradient *)aGradient
startPoint:(CGPoint *)startPoint
endPoint:(CGPoint *)endPoint;
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGLinearGradient*)aGradient;
@end
@@ -0,0 +1,84 @@
//
// 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"
@implementation IJSVGLinearGradient
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGLinearGradient*)aGradient
{
// just ask unit for the value
NSString* x1 = ([element attributeForName:@"x1"].stringValue ?: @"0");
NSString* x2 = ([element attributeForName:@"x2"].stringValue ?: @"100%");
NSString* y1 = ([element attributeForName:@"y1"].stringValue ?: @"0");
NSString* y2 = ([element attributeForName:@"y2"].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 computeColorStopsFromString:element
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
@@ -0,0 +1,147 @@
//
// IJSVGNode.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGStyle.h"
#import "IJSVGUnitLength.h"
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@class IJSVG;
@class IJSVGGroup;
@class IJSVGDef;
@class IJSVGGradient;
@class IJSVGGroup;
@class IJSVGPattern;
@class IJSVGTransform;
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,
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
};
static CGFloat IJSVGInheritedFloatValue = -99.9999991;
@interface IJSVGNode : NSObject <NSCopying>
@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) 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;
+ (IJSVGNodeType)typeForString:(NSString*)string
kind:(NSXMLNodeKind)kind;
- (void)applyPropertiesFromNode:(IJSVGNode*)node;
- (id)initWithDef:(BOOL)flag;
- (void)addDef:(IJSVGNode*)aDef;
- (IJSVGDef*)defForID:(NSString*)anID;
@end
@@ -6,8 +6,9 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGNode.h"
#import "IJSVGDef.h"
#import "IJSVGNode.h"
#import "IJSVGUtils.h"
@implementation IJSVGNode
@@ -29,6 +30,7 @@
@synthesize opacity;
@synthesize identifier;
@synthesize parentNode;
@synthesize intermediateParentNode;
@synthesize transforms;
@synthesize windingRule;
@synthesize def;
@@ -52,195 +54,203 @@
- (void)dealloc
{
free(strokeDashArray);
[x release], x = nil;
[y release], y = nil;
[width release], width = nil;
[height release], height = nil;
[opacity release], opacity = nil;
[fillOpacity release], fillOpacity = nil;
[strokeOpacity release], strokeOpacity = nil;
[strokeWidth release], strokeWidth = nil;
[strokeDashOffset release], strokeDashOffset = nil;
[unicode release], unicode = nil;
[fillGradient release], fillGradient = nil;
[strokeGradient release], strokeGradient = nil;
[strokePattern release], strokePattern = nil;
[transforms release], transforms = nil;
[fillColor release], fillColor = nil;
[strokeColor release], strokeColor = nil;
[identifier release], identifier = nil;
[def release], def = nil;
[name release], name = nil;
[className release], className = nil;
[classNameList release], classNameList = nil;
[fillPattern release], fillPattern = nil;
[clipPath release], clipPath = nil;
[svg release], svg = nil;
[mask release], mask = nil;
(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)([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)([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
+ (IJSVGNodeType)typeForString:(NSString*)string
kind:(NSXMLNodeKind)kind
{
string = [string lowercaseString];
if([string isEqualToString:@"style"])
if ([string isEqualToString:@"style"])
return IJSVGNodeTypeStyle;
if([string isEqualToString:@"switch"])
if ([string isEqualToString:@"switch"])
return IJSVGNodeTypeSwitch;
if( [string isEqualToString:@"defs"] )
if ([string isEqualToString:@"defs"])
return IJSVGNodeTypeDef;
if( [string isEqualToString:@"g"] )
if ([string isEqualToString:@"g"])
return IJSVGNodeTypeGroup;
if( [string isEqualToString:@"path"] )
if ([string isEqualToString:@"path"])
return IJSVGNodeTypePath;
if( [string isEqualToString:@"polygon"] )
if ([string isEqualToString:@"polygon"])
return IJSVGNodeTypePolygon;
if( [string isEqualToString:@"polyline"] )
if ([string isEqualToString:@"polyline"])
return IJSVGNodeTypePolyline;
if( [string isEqualToString:@"rect"] )
if ([string isEqualToString:@"rect"])
return IJSVGNodeTypeRect;
if( [string isEqualToString:@"line"] )
if ([string isEqualToString:@"line"])
return IJSVGNodeTypeLine;
if( [string isEqualToString:@"circle"] )
if ([string isEqualToString:@"circle"])
return IJSVGNodeTypeCircle;
if( [string isEqualToString:@"ellipse"] )
if ([string isEqualToString:@"ellipse"])
return IJSVGNodeTypeEllipse;
if( [string isEqualToString:@"use"] )
if ([string isEqualToString:@"use"])
return IJSVGNodeTypeUse;
if( [string isEqualToString:@"lineargradient"] )
if ([string isEqualToString:@"lineargradient"])
return IJSVGNodeTypeLinearGradient;
if( [string isEqualToString:@"radialgradient"] )
if ([string isEqualToString:@"radialgradient"])
return IJSVGNodeTypeRadialGradient;
if( [string isEqualToString:@"glyph"] )
if ([string isEqualToString:@"glyph"])
return IJSVGNodeTypeGlyph;
if( [string isEqualToString:@"font"] )
if ([string isEqualToString:@"font"])
return IJSVGNodeTypeFont;
if( [string isEqualToString:@"clippath"] )
if ([string isEqualToString:@"clippath"])
return IJSVGNodeTypeClipPath;
if( [string isEqualToString:@"mask"] )
if ([string isEqualToString:@"mask"])
return IJSVGNodeTypeMask;
if( [string isEqualToString:@"image"] )
if ([string isEqualToString:@"image"])
return IJSVGNodeTypeImage;
if([string isEqualToString:@"pattern"])
if ([string isEqualToString:@"pattern"])
return IJSVGNodeTypePattern;
if([string isEqualToString:@"svg"])
if ([string isEqualToString:@"svg"])
return IJSVGNodeTypeSVG;
if([string isEqualToString:@"text"])
if ([string isEqualToString:@"text"])
return IJSVGNodeTypeText;
if([string isEqualToString:@"tspan"] || kind == NSXMLTextKind) {
if ([string isEqualToString:@"tspan"] || kind == NSXMLTextKind) {
return IJSVGNodeTypeTextSpan;
}
// are we commong HTML? - if so just treat as a group
if (IJSVGIsCommonHTMLElementName(string) == YES) {
return IJSVGNodeTypeGroup;
}
return IJSVGNodeTypeNotFound;
}
- (id)init
{
if( ( self = [self initWithDef:YES] ) != nil )
{
if ((self = [self initWithDef:YES]) != nil) {
self.opacity = [IJSVGUnitLength unitWithFloat:1];
}
return self;
}
- (void)applyPropertiesFromNode:(IJSVGNode *)node
- (void)applyPropertiesFromNode:(IJSVGNode*)node
{
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;
// dash array needs physical memory copied
CGFloat * nStrokeDashArray = (CGFloat *)malloc(node.strokeDashArrayCount*sizeof(CGFloat));
memcpy( self.strokeDashArray, nStrokeDashArray, node.strokeDashArrayCount*sizeof(CGFloat));
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
- (id)copyWithZone:(NSZone*)zone
{
IJSVGNode * node = [[self class] allocWithZone:zone];
IJSVGNode* node = [self.class allocWithZone:zone];
[node applyPropertiesFromNode:self];
return node;
}
- (id)initWithDef:(BOOL)flag
{
if( ( self = [super init] ) != nil )
{
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:0.f];
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;
if( flag ) {
if (flag) {
def = [[IJSVGDef alloc] init];
}
}
return self;
}
- (IJSVGDef *)defForID:(NSString *)anID
- (IJSVGDef*)defForID:(NSString*)anID
{
IJSVGDef * aDef = nil;
if( (aDef = [def defForID:anID]) != nil )
IJSVGDef* aDef = nil;
if ((aDef = [def defForID:anID]) != nil) {
return aDef;
if( parentNode != nil )
}
if (parentNode != nil) {
return [parentNode defForID:anID];
}
return nil;
}
- (void)addDef:(IJSVGNode *)aDef
- (void)addDef:(IJSVGNode*)aDef
{
[def addDef:aDef];
}
@@ -248,7 +258,7 @@
// winding rule can inherit..
- (IJSVGWindingRule)windingRule
{
if( windingRule == IJSVGWindingRuleInherit && parentNode != nil ) {
if (windingRule == IJSVGWindingRuleInherit && parentNode != nil) {
return parentNode.windingRule;
}
return windingRule;
@@ -256,29 +266,29 @@
- (IJSVGLineCapStyle)lineCapStyle
{
if( lineCapStyle == IJSVGLineCapStyleInherit )
{
if( parentNode != nil )
if (lineCapStyle == IJSVGLineCapStyleInherit) {
if (parentNode != nil) {
return parentNode.lineCapStyle;
}
}
return lineCapStyle;
}
- (IJSVGLineJoinStyle)lineJoinStyle
{
if( lineJoinStyle == IJSVGLineJoinStyleInherit )
{
if( parentNode != nil )
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
- (IJSVGUnitLength*)opacity
{
if(opacity.inherit && parentNode != nil) {
if (opacity.inherit && parentNode != nil) {
return parentNode.opacity;
}
return opacity;
@@ -286,9 +296,9 @@
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength *)fillOpacity
- (IJSVGUnitLength*)fillOpacity
{
if(fillOpacity.inherit && parentNode != nil) {
if (fillOpacity.inherit && parentNode != nil) {
return parentNode.fillOpacity;
}
return fillOpacity;
@@ -296,9 +306,9 @@
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength *)strokeWidth
- (IJSVGUnitLength*)strokeWidth
{
if(strokeWidth.inherit && parentNode != nil) {
if (strokeWidth.inherit && parentNode != nil) {
return parentNode.strokeWidth;
}
return strokeWidth;
@@ -306,18 +316,18 @@
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (NSColor *)strokeColor
- (NSColor*)strokeColor
{
if( strokeColor != nil )
if (strokeColor != nil)
return strokeColor;
if( strokeColor == nil && parentNode != nil )
if (strokeColor == nil && parentNode != nil)
return parentNode.strokeColor;
return nil;
}
- (IJSVGUnitLength *)strokeOpacity
- (IJSVGUnitLength*)strokeOpacity
{
if(strokeOpacity.inherit && parentNode != nil) {
if (strokeOpacity.inherit && parentNode != nil) {
return parentNode.strokeOpacity;
}
return strokeOpacity;
@@ -325,18 +335,19 @@
// even though the spec explicity states fill color
// must be on the path, it can also be on the
- (NSColor *)fillColor
- (NSColor*)fillColor
{
if( fillColor == nil && parentNode != nil )
if (fillColor == nil && parentNode != nil) {
return parentNode.fillColor;
}
return fillColor;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGGradient *)fillGradient
- (IJSVGGradient*)fillGradient
{
if(fillGradient == nil && parentNode != nil) {
if (fillGradient == nil && parentNode != nil) {
return parentNode.fillGradient;
}
return fillGradient;
@@ -344,9 +355,9 @@
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGPattern *)fillPattern
- (IJSVGPattern*)fillPattern
{
if(fillPattern == nil && parentNode != nil) {
if (fillPattern == nil && parentNode != nil) {
return parentNode.fillPattern;
}
return fillPattern;
@@ -354,9 +365,9 @@
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGGradient *)strokeGradient
- (IJSVGGradient*)strokeGradient
{
if(strokeGradient == nil && parentNode != nil) {
if (strokeGradient == nil && parentNode != nil) {
return parentNode.strokeGradient;
}
return strokeGradient;
@@ -364,9 +375,9 @@
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGPattern *)strokePattern
- (IJSVGPattern*)strokePattern
{
if(strokePattern == nil && parentNode != nil) {
if (strokePattern == nil && parentNode != nil) {
return parentNode.strokePattern;
}
return strokePattern;
@@ -0,0 +1,44 @@
//
// IJSVGPath.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGBezierPathAdditions.h"
#import "IJSVGNode.h"
#import <Foundation/Foundation.h>
@class IJSVGGroup;
typedef NS_ENUM(NSInteger, IJSVGPrimitivePathType) {
IJSVGPrimitivePathTypePath,
IJSVGPrimitivePathTypeRect,
IJSVGPrimitivePathTypePolygon,
IJSVGPrimitivePathTypePolyLine,
IJSVGPrimitivePathTypeCircle,
IJSVGPrimitivePathTypeEllipse,
IJSVGPrimitivePathTypeLine
};
@interface IJSVGPath : IJSVGNode {
NSBezierPath* path;
NSBezierPath* subpath;
CGPoint lastControlPoint;
}
@property (nonatomic, assign) IJSVGPrimitivePathType primitiveType;
@property (nonatomic, readonly) NSBezierPath* path;
@property (nonatomic, readonly) NSBezierPath* subpath;
@property (nonatomic, assign) CGPoint lastControlPoint;
@property (nonatomic, readonly) CGPathRef CGPath;
- (NSBezierPath*)currentSubpath;
- (void)close;
- (NSPoint)currentPoint;
- (void)overwritePath:(NSBezierPath*)aPath;
- (CGPathRef)newPathRefByAutoClosingPath:(BOOL)autoClose;
@end
@@ -0,0 +1,140 @@
//
// 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
@synthesize path;
@synthesize subpath;
@synthesize lastControlPoint;
@synthesize CGPath = _CGPath;
@synthesize primitiveType = _primitiveType;
- (void)dealloc
{
if(_CGPath != nil) {
CGPathRelease(_CGPath);
_CGPath = nil;
}
if (subpath != nil) {
(void)([subpath release]), subpath = nil;
}
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_primitiveType = IJSVGPrimitivePathTypePath;
subpath = NSBezierPath.bezierPath.retain;
path = subpath; // for legacy use
}
return self;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGPath* node = [super copyWithZone:zone];
[node overwritePath:self.path];
return node;
}
- (NSPoint)currentPoint
{
return [subpath currentPoint];
}
- (NSBezierPath*)currentSubpath
{
return subpath;
}
- (void)close
{
[subpath closePath];
}
- (CGPathRef)CGPath
{
if(_CGPath == nil) {
_CGPath = [self newPathRefByAutoClosingPath:NO];
}
return _CGPath;
}
- (void)overwritePath:(NSBezierPath*)aPath
{
(void)([subpath release]), subpath = nil;
subpath = [aPath retain];
path = subpath;
}
- (CGPathRef)newPathRefByAutoClosingPath:(BOOL)autoClose
{
NSInteger i = 0;
NSInteger numElements = self.path.elementCount;
NSBezierPath* bezPath = self.path;
// nothing to return
if (numElements == 0) {
return NULL;
}
CGMutablePathRef aPath = CGPathCreateMutable();
NSPoint points[3];
BOOL didClosePath = YES;
for (i = 0; i < numElements; i++) {
switch ([bezPath elementAtIndex:i associatedPoints:points]) {
// move
case NSMoveToBezierPathElement: {
CGPathMoveToPoint(aPath, NULL, points[0].x, points[0].y);
break;
}
// line
case NSLineToBezierPathElement: {
CGPathAddLineToPoint(aPath, NULL, points[0].x, points[0].y);
didClosePath = NO;
break;
}
// curve
case NSCurveToBezierPathElement: {
CGPathAddCurveToPoint(aPath, NULL, points[0].x, points[0].y,
points[1].x, points[1].y,
points[2].x, points[2].y);
didClosePath = NO;
break;
}
// close
case NSClosePathBezierPathElement: {
CGPathCloseSubpath(aPath);
didClosePath = YES;
break;
}
}
}
if (!didClosePath && autoClose) {
CGPathCloseSubpath(aPath);
}
// create immutable and release
CGPathRef pathToReturn = CGPathCreateCopy(aPath);
CGPathRelease(aPath);
return pathToReturn;
}
@end
@@ -6,12 +6,11 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGGroup.h"
#import "IJSVGImage.h"
#import <Foundation/Foundation.h>
@interface IJSVGPattern : IJSVGGroup {
}
@end
@@ -9,11 +9,10 @@
#import "IJSVGGroup.h"
@interface IJSVGText : IJSVGGroup {
NSString * text;
NSString* text;
}
@property (nonatomic, copy) NSString * text;
@property (nonatomic, copy) NSString* text;
@end
@@ -14,13 +14,13 @@
- (void)dealloc
{
[text release], text = nil;
(void)([text release]), text = nil;
[super dealloc];
}
- (IJSVGText *)copyWithZone:(NSZone *)zone
- (IJSVGText*)copyWithZone:(NSZone*)zone
{
IJSVGText * node = [super copyWithZone:zone];
IJSVGText* node = [super copyWithZone:zone];
node.text = self.text;
return node;
}
@@ -0,0 +1,131 @@
//
// IJSVGParser.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGColor.h"
#import "IJSVGCommand.h"
#import "IJSVGDef.h"
#import "IJSVGError.h"
#import "IJSVGForeignObject.h"
#import "IJSVGGroup.h"
#import "IJSVGImage.h"
#import "IJSVGLinearGradient.h"
#import "IJSVGPath.h"
#import "IJSVGPattern.h"
#import "IJSVGRadialGradient.h"
#import "IJSVGStyleSheet.h"
#import "IJSVGText.h"
#import "IJSVGTransform.h"
#import "IJSVGUtils.h"
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
static NSString const* IJSVGAttributeViewBox = @"viewBox";
static NSString const* IJSVGAttributeID = @"id";
static NSString const* IJSVGAttributeClass = @"class";
static NSString const* IJSVGAttributeX = @"x";
static NSString const* IJSVGAttributeY = @"y";
static NSString const* IJSVGAttributeWidth = @"width";
static NSString const* IJSVGAttributeHeight = @"height";
static NSString const* IJSVGAttributeOpacity = @"opacity";
static NSString const* IJSVGAttributeStrokeOpacity = @"stroke-opacity";
static NSString const* IJSVGAttributeStrokeWidth = @"stroke-width";
static NSString const* IJSVGAttributeStrokeDashOffset = @"stroke-dashoffset";
static NSString const* IJSVGAttributeFillOpacity = @"fill-opacity";
static NSString const* IJSVGAttributeClipPath = @"clip-path";
static NSString const* IJSVGAttributeMask = @"mask";
static NSString const* IJSVGAttributeGradientUnits = @"gradientUnits";
static NSString const* IJSVGAttributeMaskUnits = @"maskUnits";
static NSString const* IJSVGAttributeMaskContentUnits = @"maskContentUnits";
static NSString const* IJSVGAttributeTransform = @"transform";
static NSString const* IJSVGAttributeGradientTransform = @"gradientTransform";
static NSString const* IJSVGAttributeUnicode = @"unicode";
static NSString const* IJSVGAttributeStrokeLineCap = @"stroke-linecap";
static NSString const* IJSVGAttributeLineJoin = @"stroke-linejoin";
static NSString const* IJSVGAttributeStroke = @"stroke";
static NSString const* IJSVGAttributeStrokeDashArray = @"stroke-dasharray";
static NSString const* IJSVGAttributeFill = @"fill";
static NSString const* IJSVGAttributeFillRule = @"fill-rule";
static NSString const* IJSVGAttributeBlendMode = @"mix-blend-mode";
static NSString const* IJSVGAttributeDisplay = @"display";
static NSString const* IJSVGAttributeStyle = @"style";
static NSString const* IJSVGAttributeD = @"d";
static NSString const* IJSVGAttributeXLink = @"xlink:href";
static NSString const* IJSVGAttributeX1 = @"x1";
static NSString const* IJSVGAttributeX2 = @"x2";
static NSString const* IJSVGAttributeY1 = @"y1";
static NSString const* IJSVGAttributeY2 = @"y2";
static NSString const* IJSVGAttributeRX = @"rx";
static NSString const* IJSVGAttributeRY = @"ry";
static NSString const* IJSVGAttributeCX = @"cx";
static NSString const* IJSVGAttributeCY = @"cy";
static NSString const* IJSVGAttributeR = @"r";
static NSString const* IJSVGAttributePoints = @"points";
@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 {
NSRect viewBox;
NSSize proposedViewSize;
@private
id<IJSVGParserDelegate> _delegate;
NSXMLDocument* _document;
NSMutableArray* _glyphs;
IJSVGStyleSheet* _styleSheet;
NSMutableArray* _parsedNodes;
NSMutableDictionary* _defNodes;
NSMutableDictionary* _baseDefNodes;
NSMutableArray<IJSVG*>* _svgs;
NSMutableArray* _definedGroups;
struct {
unsigned int shouldHandleForeignObject : 1;
unsigned int handleForeignObject : 1;
unsigned int handleSubSVG : 1;
} _respondsTo;
}
@property (nonatomic, readonly) NSRect viewBox;
@property (nonatomic, readonly) NSSize proposedViewSize;
+ (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
@@ -0,0 +1,23 @@
//
// IJSVGLayerTree.h
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGNode.h"
#import "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
@@ -0,0 +1,761 @@
//
// 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 viewBox;
@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?
CGFloat x = [node.x computeValue:layer.frame.size.width];
CGFloat y = [node.y computeValue:layer.frame.size.height];
// do some magic transform
if (transforms.count == 0 && x == 0.f && y == 0.f) {
return layer;
}
if (x != 0.f || y != 0.f) {
// we must add translate to the stack
NSMutableArray* trans = nil;
if (transforms != nil) {
trans = [[transforms mutableCopy] autorelease];
} else {
trans = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
}
[trans addObject:[IJSVGTransform transformByTranslatingX:x y:y]];
transforms = trans;
}
// add any transforms
IJSVGLayer* topLayer = nil;
IJSVGLayer* parentLayer = nil;
for (IJSVGTransform* transform in transforms) {
// make sure we apply the transform to the parent
// so they stack
IJSVGGroupLayer* childLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
childLayer.affineTransform = transform.CGAffineTransform;
// add it to the parent layer
if (parentLayer != nil) {
[parentLayer addSublayer:childLayer];
} else {
// make sure we keep track of the top most layer
topLayer = childLayer;
}
// reset parent layer to the new child
parentLayer = childLayer;
}
// swap the layer around
[parentLayer addSublayer:layer];
layer = topLayer;
return layer;
}
- (void)applyDefaultsToLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
CGFloat opacity = node.opacity.value;
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.children) {
[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.CGPath;
*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;
if (_style.fillColor && (hasFill || hasColor || fColor == nil)) {
fColor = _style.fillColor;
} else 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 = self.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;
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) {
IJSVGLayer* clip = [self layerForNode:node.clipPath];
// adjust the frame
if (node.clipPath.units == IJSVGUnitObjectBoundingBox) {
[self adjustLayer:clip
toParentLayerFrame:layer];
} else {
clip.affineTransform = [self absoluteTransform:node];
}
// add the layer
[maskLayer addSublayer:clip];
}
// add the actual mask
if (node.mask != nil) {
IJSVGLayer* mask = [self layerForNode:node.mask];
// only move if bounding box
if (node.mask.units == IJSVGUnitObjectBoundingBox) {
[self adjustLayer:mask
toParentLayerFrame:layer];
} else {
mask.affineTransform = [self absoluteTransform:node];
}
// add the layer
[maskLayer addSublayer:mask];
}
// recursive colourize for each item
[self _recursiveColorLayersFromLayer:maskLayer
withColor:[IJSVGColor computeColorSpace:NSColor.whiteColor].CGColor];
// add the mask
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] init] autorelease];
for (NSInteger i = 0; i < node.strokeDashArrayCount; i++) {
[arr addObject:@((CGFloat)node.strokeDashArray[i])];
}
return [[arr copy] autorelease];
}
- (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;
}
}
}
+ (void)log:(IJSVGLayer*)layer
depth:(NSInteger)depth
{
NSLog(@"%@%@: %@, Transforms: %@", [@"" stringByPaddingToLength:depth
withString:@"\t"
startingAtIndex:0],
layer,
NSStringFromRect(layer.frame),
[IJSVGTransform affineTransformToSVGTransformAttributeString:layer.affineTransform]);
for (IJSVGLayer* sublayer in layer.sublayers) {
[self log:(IJSVGLayer*)sublayer
depth:depth++];
}
}
@end
@@ -0,0 +1,21 @@
//
// 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
@@ -0,0 +1,13 @@
//
// IJSVGRendering.m
// IJSVGExample
//
// Created by Curtis Hard on 14/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGRendering.h"
@implementation IJSVGRendering
@end
@@ -0,0 +1,26 @@
//
// IJSVGStyleList.h
// IconJar
//
// Created by Curtis Hard on 09/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGColorList.h"
#import "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
@@ -0,0 +1,50 @@
//
// IJSVGStyleList.m
// IconJar
//
// Created by Curtis Hard on 09/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGRenderingStyle.h"
@implementation IJSVGRenderingStyle
@synthesize colorList = _colorList;
@synthesize lineCapStyle = _lineCapStyle;
@synthesize lineJoinStyle = _lineJoinStyle;
@synthesize lineWidth = _lineWidth;
@synthesize fillColor = _fillColor;
@synthesize strokeColor = _strokeColor;
- (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
@@ -6,22 +6,21 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGColor.h"
#import <Foundation/Foundation.h>
@interface IJSVGStyle : NSObject {
@private
NSMutableDictionary * _dict;
NSMutableDictionary* _dict;
}
+ (IJSVGStyle *)parseStyleString:(NSString *)string;
+ (IJSVGStyle*)parseStyleString:(NSString*)string;
- (void)setPropertyValue:(id)value
forProperty:(NSString *)key;
- (id)property:(NSString *)key;
forProperty:(NSString*)key;
- (id)property:(NSString*)key;
- (IJSVGStyle *)mergedStyle:(IJSVGStyle *)style;
- (IJSVGStyle*)mergedStyle:(IJSVGStyle*)style;
@end
@@ -13,70 +13,70 @@
- (void)dealloc
{
[_dict release], _dict = nil;
(void)([_dict release]), _dict = nil;
[super dealloc];
}
- (id)init
{
if( ( self = [super init] ) != nil ) {
if ((self = [super init]) != nil) {
_dict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)setPropertyValue:(id)value
forProperty:(NSString *)key
forProperty:(NSString*)key
{
[_dict setObject:value
forKey:key];
}
- (NSDictionary *)properties
- (NSDictionary*)properties
{
return _dict;
}
- (id)property:(NSString *)key
- (id)property:(NSString*)key
{
return [_dict objectForKey:key];
}
+ (IJSVGStyle *)parseStyleString:(NSString *)string
+ (IJSVGStyle*)parseStyleString:(NSString*)string
{
IJSVGStyle * style = [[[[self class] alloc] init] autorelease];
IJSVGStyle* style = [[[self.class alloc] init] autorelease];
NSInteger length = string.length;
NSInteger index = 0;
NSString * key = nil;
NSString * value = nil;
NSString* key = nil;
NSString* value = nil;
// iterate over the string - its actually really simple what we need
// to do
for(NSInteger i = 0; i < length; i++) {
for (NSInteger i = 0; i < length; i++) {
unichar c = [string characterAtIndex:i];
// find the key
if(c == ':') {
key = [string substringWithRange:NSMakeRange(index, (i-index))];
index = i+1;
if (c == ':') {
key = [string substringWithRange:NSMakeRange(index, (i - index))];
index = i + 1;
}
// find the value
else if(c == ';' || i == (length-1)) {
else if (c == ';' || i == (length - 1)) {
NSInteger chomp;
if(i == (length-1) && c != ';') {
chomp = (i-(index-1));
if (i == (length - 1) && c != ';') {
chomp = (i - (index - 1));
} else {
chomp = (i-index);
chomp = (i - index);
}
value = [string substringWithRange:NSMakeRange(index, chomp)];
index = i+1;
index = i + 1;
}
// set the propery if it actually exists
if(key != nil && value != nil) {
[style setPropertyValue:[[self class] trimString:value]
forProperty:[[self class] trimString:key]];
if (key != nil && value != nil) {
[style setPropertyValue:[self.class trimString:value]
forProperty:[self.class trimString:key]];
key = nil;
value = nil;
}
@@ -84,46 +84,41 @@
return style;
}
+ (NSString *)trimString:(NSString *)string
+ (NSString*)trimString:(NSString*)string
{
return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
+ (NSArray *)allowedColourKeys
+ (NSArray*)allowedColourKeys
{
return @[@"fill",@"stroke-colour",@"stop-color",@"stroke"];
return @[ @"fill", @"stroke-colour", @"stop-color", @"stroke" ];
}
+ (BOOL)isNumeric:(NSString *)string
{
return [[NSScanner scannerWithString:string] scanFloat:NULL];
}
- (void)setProperties:(NSDictionary *)properties
- (void)setProperties:(NSDictionary*)properties
replaceAll:(BOOL)flag
{
if(flag) {
if (flag) {
[_dict removeAllObjects];
}
[_dict addEntriesFromDictionary:properties];
}
- (NSString *)description
- (NSString*)description
{
return [_dict description];
}
- (IJSVGStyle *)mergedStyle:(IJSVGStyle *)style
- (IJSVGStyle*)mergedStyle:(IJSVGStyle*)style
{
// create the new style
IJSVGStyle * newStyle = [[[IJSVGStyle alloc] init] autorelease];
IJSVGStyle* newStyle = [[[IJSVGStyle alloc] init] autorelease];
// grab the current style
NSMutableDictionary * dict = [[[self properties] mutableCopy] autorelease];
NSMutableDictionary* dict = [[[self properties] mutableCopy] autorelease];
// overwride the style with the new styles
[dict addEntriesFromDictionary:[style properties]];
// add the styles to the style
[newStyle setProperties:dict
replaceAll:YES];
@@ -6,20 +6,20 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGStyleSheetSelector.h"
#import "IJSVGStyleSheetRule.h"
#import "IJSVGStyleSheetSelector.h"
#import <Foundation/Foundation.h>
@class IJSVGNode;
@interface IJSVGStyleSheet : NSObject {
@private
NSMutableDictionary * _selectors;
NSMutableArray * _rules;
NSMutableDictionary* _selectors;
NSMutableArray* _rules;
}
- (void)parseStyleBlock:(NSString *)string;
- (IJSVGStyle *)styleForNode:(IJSVGNode *)node;
- (void)parseStyleBlock:(NSString*)string;
- (IJSVGStyle*)styleForNode:(IJSVGNode*)node;
@end
@@ -6,19 +6,18 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGStyleSheet.h"
#import "IJSVGStyle.h"
#import "IJSVGNode.h"
#import "IJSVGStyle.h"
#import "IJSVGStyleSheet.h"
@interface IJSVGStyleSheetSelectorListItem : NSObject {
IJSVGStyleSheetSelector * selector;
IJSVGStyleSheetRule * rule;
IJSVGStyleSheetSelector* selector;
IJSVGStyleSheetRule* rule;
}
@property (nonatomic, retain) IJSVGStyleSheetRule * rule;
@property (nonatomic, retain) IJSVGStyleSheetSelector * selector;
@property (nonatomic, retain) IJSVGStyleSheetRule* rule;
@property (nonatomic, retain) IJSVGStyleSheetSelector* selector;
@end
@@ -28,8 +27,8 @@
- (void)dealloc
{
[rule release], rule = nil;
[selector release], selector = nil;
(void)([rule release]), rule = nil;
(void)([selector release]), selector = nil;
[super dealloc];
}
@@ -39,76 +38,73 @@
- (void)dealloc
{
[_selectors release], _selectors = nil;
[_rules release], _rules = nil;
(void)([_selectors release]), _selectors = nil;
(void)([_rules release]), _rules = nil;
[super dealloc];
}
- (id)init
{
if((self = [super init]) != nil)
{
if ((self = [super init]) != nil) {
_selectors = [[NSMutableDictionary alloc] init];
_rules = [[NSMutableArray alloc] init];
}
return self;
}
- (NSArray *)selectorsWithSelectorString:(NSString *)string
- (NSArray*)selectorsWithSelectorString:(NSString*)string
{
NSMutableArray * array = [[[NSMutableArray alloc] init] autorelease];
NSMutableArray* array = [[[NSMutableArray alloc] init] autorelease];
// split the string by the comma, as it could be multiple
NSArray * comp = [string componentsSeparatedByString:@","];
NSCharacterSet * whiteSpaceCharSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSArray* comp = [string componentsSeparatedByString:@","];
NSCharacterSet* whiteSpaceCharSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
// create a selector or reuse one already being used
for( NSString * selectorName in comp )
{
for (NSString* selectorName in comp) {
selectorName = [selectorName stringByTrimmingCharactersInSet:whiteSpaceCharSet];
IJSVGStyleSheetSelector * selector = nil;
IJSVGStyleSheetSelector* selector = nil;
// create a new selector if not found
if((selector = [_selectors objectForKey:selectorName]) == nil) {
if ((selector = [_selectors objectForKey:selectorName]) == nil) {
selector = [[[IJSVGStyleSheetSelector alloc] initWithSelectorString:selectorName] autorelease];
if(selector != nil) {
if (selector != nil) {
[_selectors setObject:selector
forKey:selectorName];
}
}
// add it to our list
if(selector != nil) {
if (selector != nil) {
[array addObject:selector];
}
}
return array;
}
- (void)parseStyleBlock:(NSString *)string
- (void)parseStyleBlock:(NSString*)string
{
NSUInteger depth = 0, marker = 0;
NSUInteger length = [string length];
NSCharacterSet * whitespaceCharSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSString * selector = nil;
for( NSUInteger i = 0; i < length; i++ )
{
NSCharacterSet* whitespaceCharSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSString* selector = nil;
for (NSUInteger i = 0; i < length; i++) {
unichar c = [string characterAtIndex:i];
if( c == '/' ) {
if (c == '/') {
i++;
if( i<length ) {
if (i < length) {
c = [string characterAtIndex:i];
if( c == '*' ) {
if (c == '*') {
// skip comment until closing /
for( ; i < length; i++ ) {
if([string characterAtIndex:i] == '/') {
for (; i < length; i++) {
if ([string characterAtIndex:i] == '/') {
break;
}
}
if( i < length ) {
marker = i+1;
if (i < length) {
marker = i + 1;
continue;
} else {
// end of string
@@ -119,79 +115,77 @@
}
}
}
// opening brace, could be nested or start of a new string
if( c == '{' ) {
if (c == '{') {
// start a new rule
if(depth == 0) {
if (depth == 0) {
// grab selector and trim it
selector = [string substringWithRange:NSMakeRange(marker, i-marker)];
selector = [string substringWithRange:NSMakeRange(marker, i - marker)];
selector = [selector stringByTrimmingCharactersInSet:whitespaceCharSet];
marker = i+1;
marker = i + 1;
}
depth += 1;
}
// ending brace
else if( c == '}' ) {
else if (c == '}') {
// if we finished rule
if(depth == 1) {
NSString * rule = [string substringWithRange:NSMakeRange(marker, i-marker)];
if (depth == 1) {
NSString* rule = [string substringWithRange:NSMakeRange(marker, i - marker)];
rule = [rule stringByTrimmingCharactersInSet:whitespaceCharSet];
// append the rule to the style sheet
[self addStyleRule:rule
withSelectors:[self selectorsWithSelectorString:selector]];
marker = i+1;
marker = i + 1;
}
depth = MAX(depth-1, 0);
depth = MAX(depth - 1, 0);
}
}
}
- (void)addStyleRule:(NSString *)rule
withSelectors:(NSArray *)selectors
- (void)addStyleRule:(NSString*)rule
withSelectors:(NSArray*)selectors
{
// append the rule onto the list within
// this style sheet
IJSVGStyleSheetRule * aRule = [[[IJSVGStyleSheetRule alloc] init] autorelease];
IJSVGStyleSheetRule* aRule = [[[IJSVGStyleSheetRule alloc] init] autorelease];
aRule.style = [IJSVGStyle parseStyleString:rule];
aRule.selectors = selectors;
[_rules addObject:aRule];
}
- (IJSVGStyle *)styleForNode:(IJSVGNode *)node
- (IJSVGStyle*)styleForNode:(IJSVGNode*)node
{
IJSVGStyle * style = [[[IJSVGStyle alloc] init] autorelease];
NSMutableArray * matchedRules = [[[NSMutableArray alloc] init] autorelease];
for(IJSVGStyleSheetRule * rule in _rules)
{
IJSVGStyleSheetSelector * matchedSelector = nil;
if([rule matchesNode:node selector:&matchedSelector]) {
IJSVGStyle* style = [[[IJSVGStyle alloc] init] autorelease];
NSMutableArray* matchedRules = [[[NSMutableArray alloc] init] autorelease];
for (IJSVGStyleSheetRule* rule in _rules) {
IJSVGStyleSheetSelector* matchedSelector = nil;
if ([rule matchesNode:node selector:&matchedSelector]) {
// make a wrapper for the selector with the rule
IJSVGStyleSheetSelectorListItem * listItem = nil;
IJSVGStyleSheetSelectorListItem* listItem = nil;
listItem = [[[IJSVGStyleSheetSelectorListItem alloc] init] autorelease];
listItem.rule = rule;
listItem.selector = matchedSelector;
// add it to the array of matches
[matchedRules addObject:listItem];
}
}
// now we have all the wrappers, we need to sort them
// by specificity
NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:@"selector.specificity"
ascending:YES];
[matchedRules sortUsingDescriptors:@[sort]];
NSSortDescriptor* sort = [NSSortDescriptor sortDescriptorWithKey:@"selector.specificity"
ascending:YES];
[matchedRules sortUsingDescriptors:@[ sort ]];
// combine the rule
for(IJSVGStyleSheetSelectorListItem * listItem in matchedRules) {
for (IJSVGStyleSheetSelectorListItem* listItem in matchedRules) {
style = [style mergedStyle:listItem.rule.style];
}
return style;
}
@@ -6,23 +6,22 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGStyleSheetSelector.h"
#import "IJSVGStyle.h"
#import "IJSVGStyleSheetSelector.h"
#import <Foundation/Foundation.h>
@class IJSVGNode;
@interface IJSVGStyleSheetRule : NSObject {
NSArray * selectors;
IJSVGStyle * style;
NSArray* selectors;
IJSVGStyle* style;
}
@property (nonatomic, retain) NSArray * selectors;
@property (nonatomic, retain) IJSVGStyle * style;
@property (nonatomic, retain) NSArray* selectors;
@property (nonatomic, retain) IJSVGStyle* style;
- (BOOL)matchesNode:(IJSVGNode *)node
selector:(IJSVGStyleSheetSelector **)matchedSelector;
- (BOOL)matchesNode:(IJSVGNode*)node
selector:(IJSVGStyleSheetSelector**)matchedSelector;
@end
@@ -14,18 +14,18 @@
- (void)dealloc
{
[selectors release], selectors = nil;
[style release], style = nil;
(void)([selectors release]), selectors = nil;
(void)([style release]), style = nil;
[super dealloc];
}
- (BOOL)matchesNode:(IJSVGNode *)node
selector:(IJSVGStyleSheetSelector **)matchedSelector
- (BOOL)matchesNode:(IJSVGNode*)node
selector:(IJSVGStyleSheetSelector**)matchedSelector
{
// interate over each select and work out if
// it allows us to be applied
for(IJSVGStyleSheetSelector * selector in selectors) {
if([selector matchesNode:node]) {
for (IJSVGStyleSheetSelector* selector in selectors) {
if ([selector matchesNode:node]) {
*matchedSelector = selector;
return YES;
}
@@ -6,23 +6,22 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "IJSVGStyleSheetSelectorRaw.h"
#import <Foundation/Foundation.h>
@class IJSVGNode;
@interface IJSVGStyleSheetSelector : NSObject {
NSString * selector;
NSString* selector;
NSUInteger specificity;
@private
NSMutableArray * _rawSelectors;
NSMutableArray* _rawSelectors;
}
@property (nonatomic, assign) NSUInteger specificity;
- (id)initWithSelectorString:(NSString *)string;
- (BOOL)matchesNode:(IJSVGNode *)node;
- (id)initWithSelectorString:(NSString*)string;
- (BOOL)matchesNode:(IJSVGNode*)node;
@end
@@ -246,8 +246,8 @@ BOOL IJSVGStyleSheetMatchSelector(IJSVGNode * node, IJSVGStyleSheetSelectorRaw *
- (void)dealloc
{
[_rawSelectors release], _rawSelectors = nil;
[selector release], selector = nil;
(void)([_rawSelectors release]), _rawSelectors = nil;
(void)([selector release]), selector = nil;
[super dealloc];
}
@@ -260,7 +260,7 @@ BOOL IJSVGStyleSheetMatchSelector(IJSVGNode * node, IJSVGStyleSheetSelectorRaw *
// failed to compile
if([self _compile] == NO) {
[self release], self = nil;
(void)([self release]), self = nil;
return nil;
}
[self _calculate];
@@ -19,21 +19,20 @@ typedef NS_ENUM(NSUInteger, IJSVGStyleSheetSelectorCombinator) {
@interface IJSVGStyleSheetSelectorRaw : NSObject {
NSString * tag;
NSString * identifier;
NSMutableArray * classes;
NSString* tag;
NSString* identifier;
NSMutableArray* classes;
IJSVGStyleSheetSelectorCombinator combinator;
NSString * combinatorString;
NSString* combinatorString;
}
@property (nonatomic, copy) NSString * tag;
@property (nonatomic, copy) NSString * identifier;
@property (nonatomic, copy) NSString * combinatorString;
@property (nonatomic, retain) NSArray * classes;
@property (nonatomic, copy) NSString* tag;
@property (nonatomic, copy) NSString* identifier;
@property (nonatomic, copy) NSString* combinatorString;
@property (nonatomic, retain) NSArray* classes;
@property (nonatomic, assign) IJSVGStyleSheetSelectorCombinator combinator;
- (void)addClassName:(NSString *)className;
- (void)addClassName:(NSString*)className;
@end
@@ -14,17 +14,16 @@
- (void)dealloc
{
[classes release], classes = nil;
[identifier release], identifier = nil;
[tag release], tag = nil;
[combinatorString release], combinatorString = nil;
(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 )
{
if ((self = [super init]) != nil) {
classes = [[NSMutableArray alloc] init];
combinator = IJSVGStyleSheetSelectorCombinatorDescendant;
combinatorString = @" ";
@@ -32,12 +31,12 @@
return self;
}
- (void)addClassName:(NSString *)className
- (void)addClassName:(NSString*)className
{
[classes addObject:className];
}
- (NSString *)description
- (NSString*)description
{
return [NSString stringWithFormat:@"Combinator: %@, Tag: %@, Classes: %@, Identifier: %@", combinatorString, tag, classes, identifier];
}
@@ -10,10 +10,10 @@
@implementation IJSVGGradientUnitLength
- (NSString *)stringValue
- (NSString*)stringValue
{
if(self.type == IJSVGUnitLengthTypePercentage) {
return [NSString stringWithFormat:@"%g",self.value];
if (self.type == IJSVGUnitLengthTypePercentage) {
return [NSString stringWithFormat:@"%g", self.value];
}
return [super stringValue];
}
@@ -10,31 +10,38 @@
@implementation IJSVGMath
CGFloat IJSVGMathRad(CGFloat val) {
CGFloat IJSVGMathRad(CGFloat val)
{
return val * M_PI / 180;
};
CGFloat IJSVGMathDeg(CGFloat val) {
CGFloat IJSVGMathDeg(CGFloat val)
{
return val * 180.f / M_PI;
};
CGFloat IJSVGMathAcos(CGFloat val) {
CGFloat IJSVGMathAcos(CGFloat val)
{
return IJSVGMathDeg(acosf(val));
};
CGFloat IJSVGMathSin(CGFloat val) {
CGFloat IJSVGMathSin(CGFloat val)
{
return sinf(IJSVGMathRad(val));
};
CGFloat IJSVGMathAsin(CGFloat val) {
CGFloat IJSVGMathAsin(CGFloat val)
{
return IJSVGMathDeg(asinf(val));
};
CGFloat IJSVGMathTan(CGFloat val) {
CGFloat IJSVGMathTan(CGFloat val)
{
return tanf(IJSVGMathRad(val));
};
CGFloat IJSVGMathAtan(CGFloat val) {
CGFloat IJSVGMathAtan(CGFloat val)
{
return IJSVGMathDeg(atanf(val));
};
@@ -7,7 +7,8 @@
//
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
void IJSVGBeginTransactionLock();
void IJSVGEndTransactionLock();
void IJSVGObtainTransactionLock(dispatch_block_t block, BOOL renderOnMainThread);
BOOL IJSVGIsMainThread(void);
void IJSVGBeginTransactionLock(void);
void IJSVGEndTransactionLock(void);

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