Compare commits

...

277 Commits

Author SHA1 Message Date
Curtis Hard 1e7b8b38a5 Fixes the double quotes being used instead of angled brackets 2021-04-26 13:45:32 +01:00
Curtis Hard 58e1a8c45d fixes tempalte void things 2021-04-26 10:35:08 +01:00
Curtis Hard a525e4351a Fixes computeColorList for gradient export 2021-04-24 13:41:05 +01:00
Curtis Hard c87716b311 Code style 2021-04-21 20:18:07 +01:00
Curtis Hard 583a930bf7 Fixes multithread issue with strtok 2021-04-21 15:24:51 +01:00
Curtis Hard ec2473d450 Adds transaction to fix memory issue 2021-04-21 13:39:31 +01:00
Curtis Hard 3cc477955a Fixes enums and options 2021-04-20 20:36:37 +01:00
Curtis Hard 1f0ff52dff Adds color types 2021-04-20 16:31:52 +01:00
Curtis Hard e96bfa54b0 Make sure to check it has alpha 2021-04-20 12:15:23 +01:00
Curtis Hard cd3b540274 Initial commit 2021-04-20 09:31:10 +01:00
Curtis Hard 1cfbaf14e4 added utils for converting CGLineCap and Joi nto IJSVG counterparts 2021-04-11 17:13:45 +01:00
Curtis Hard 5a389f88d3 Added initWithDataAssetNamed:bundle:error:
Added support for loading SVG’s from the data asset catalogue
2021-04-07 21:42:00 +01:00
Curtis Hard 9f43832ff3 Fixes elliptical arc 2021-02-17 21:32:13 +00:00
Curtis Hard 65623ec552 Fixes colour forced from a style 2021-02-16 21:11:26 +00:00
Curtis Hard 5192520b7c Fixes memory crash 2021-02-16 09:37:22 +00:00
Curtis Hard 5123ee7308 Fixes crash 2021-02-11 21:39:31 +00:00
Curtis Hard c886a6a80d trolled by CGPath not being identical to bezierpath 2021-02-10 22:21:13 +00:00
Curtis Hard 4cd2895703 Seems to improve performance 2021-02-10 19:27:08 +00:00
Curtis Hard a98d84f209 Removed bezier path additions as its now useless
- more perfromance increases
2021-02-08 20:56:08 +00:00
Curtis Hard 8faab28823 Performance increases 2021-02-08 17:23:43 +00:00
Curtis Hard cca5524a11 Converts all bezier path storage over to CGPath
There was no need to use NSBezierPath, we only used to to convert to CGPath eventually, so swapped it all overm much faster
2021-02-06 18:33:23 +00:00
Curtis Hard c14e2367a0 Formatting 2021-02-06 13:21:46 +00:00
Curtis Hard db4b0e9a18 Fixes crash if string is nil 2021-02-06 12:25:16 +00:00
Curtis Hard 93d6a868a9 reformat and use of strtok - did not realise it was already built into C 2021-02-05 21:28:48 +00:00
Curtis Hard 60fa627d99 Perf 2021-02-05 15:51:15 +00:00
Curtis Hard ccaa350190 Fixes issue with mem crash when no width or height is specified as a fallback 2021-02-03 22:03:38 +00:00
Curtis Hard 727f8a2dea Modern Object-C refactor
This refactors most of the old style synthesized properties and lets the compiler do it for us.

This also changes how unit lengths works (now does correct parsing and using cstrings instead of nsstring where applicable)
2021-01-30 18:40:29 +00:00
Curtis Hard 972812b3f6 Fixes arc commands 2021-01-26 08:56:04 +00:00
Curtis Hard ad8f440c72 Merge branch 'feature/cm-mm-units' 2021-01-25 19:32:47 +00:00
Curtis Hard 68393b296b Faster low level parsing for paths 2021-01-25 19:29:53 +00:00
Curtis Hard 1cfcb596d9 Much faster command parsing
tl;dr, stops converting between char*/unichar* and NSString*, the low level code for passing commands wants char* so no point of converting it to a higher level NSString* just to convert it back again, waste of time.
2021-01-24 22:18:07 +00:00
Curtis Hard 69077e49cf Faster parsing for very large SVGs 2021-01-24 19:16:10 +00:00
Curtis Hard 3bdf2151ca Rewrote how we parse transforms (its much faster)
Also much faster arc transform processsing
2021-01-23 18:58:39 +00:00
Curtis Hard f7e28a2962 Added originalType for future reference 2021-01-20 21:39:10 +00:00
Curtis Hard 2c07cfabdd Added more units and neatened up methods 2021-01-20 21:19:28 +00:00
Curtis Hard 3e356b3fdc Possible fix for CM and MM units 2021-01-20 21:00:15 +00:00
Curtis Hard 49f759edc0 Added extra header in 2021-01-10 16:55:28 +00:00
Curtis Hard 38e314eb99 Cant use description as its already a thing on NSObject. #oops 2020-11-22 18:50:09 +00:00
Curtis Hard d0eb015cf1 Added title and desc parsing into the IJSVGNode 2020-11-22 18:14:04 +00:00
Curtis Hard 080626a022 Removed warning 2020-11-14 16:44:13 +00:00
Curtis Hard 36c20bc55c Updated clang warning 2020-11-13 20:01:37 +00:00
Curtis Hard 4d89631e9a Brace in the wrong place! #oops 2020-09-21 20:16:53 +01:00
Curtis Hard 65f62007f3 Fixes exception being thrown and lower cased move command 2020-09-21 19:55:31 +01:00
Curtis Hard af5f16288d Updated opyright 2020-09-21 09:58:38 +01:00
Curtis Hard 08e0f9288d Adds support to remove default attributes from exported files 2020-09-16 18:40:05 +01:00
Curtis Hard 7650f6205c More improvements to exporting data 2020-09-13 20:36:29 +01:00
Curtis Hard 263768af5b Initial compression changes 2020-09-12 22:59:54 +01:00
Curtis Hard 4b1be17f9a Reduces exported data by a fair amount on larger SVGs by using NSXMLNodeCompactEmptyElement to self close tags
- also added option to get back an IJSVG object from the current export string
2020-09-08 18:57:20 +01:00
Curtis Hard 6b0d6b1452 This adds in floating point export options
- aswell as an option to round matrix values
2020-09-03 19:37:37 +01:00
Curtis Hard f80d4145bb Default rounds numbers, but not for transforms 2020-08-14 20:48:33 +01:00
Curtis Hard f68c83285b Fixes issuew here stroke-opacity was not exported 2020-08-14 20:13:53 +01:00
Curtis Hard 1f4bd989d8 Fixes RX and RY on rect 2020-08-13 12:10:49 +01:00
Curtis Hard 5b5d0b738b Added instruction passing for c -> s + t 2020-08-04 20:58:05 +01:00
Curtis Hard bd82c5d81b Only add the xlink namespace attribute on if required 2020-07-31 18:27:16 +01:00
Curtis Hard 145bbb17f8 Adds xml declaration removal to options 2020-07-29 20:13:01 +01:00
Curtis Hard d9f40551a4 Added ijsvg_isHexString for faster hex comparison 2020-07-27 12:06:03 +01:00
Curtis Hard 4448f6aeaf Small perf increase 2020-07-12 14:36:12 +01:00
Curtis Hard 6834abba19 Typo fix 2020-07-11 11:56:42 +01:00
Curtis Hard a86b4e80ba Refacator name 2020-07-09 16:32:20 +01:00
Curtis Hard 2e8d039599 Memory reductions 2020-06-27 19:00:38 +01:00
Curtis Hard 4ba6bb776d Xcode stuff 2020-06-27 12:28:35 +01:00
Curtis Hard 9c80412e88 Various image additions 2020-06-15 09:25:53 +01:00
Curtis Hard 509f0e0b0a Only allow removal of 0 if the float contains a floating point 2020-06-05 13:34:44 +01:00
Curtis Hard ce30877a26 Xcode stuff 2020-05-25 19:58:48 +01:00
Curtis Hard 122271bf36 Fixes for layer tree masking 2020-04-18 17:16:29 +01:00
Curtis Hard 28b4c6b85c Fixes issue with intrinsicSize size and dom being discarded 2020-03-01 18:19:38 +00:00
Curtis Hard 4b308d3a3e Wrong unit used 2020-02-27 08:33:16 +00:00
Curtis Hard d3ee05d8ac #oops 2020-02-25 08:29:59 +00:00
Curtis Hard 204b516e77 Fixes width and height not working correctly 2020-02-12 22:32:52 +00:00
Curtis Hard a832a986fd Swaps back to CATransaction 2020-01-16 20:37:48 +00:00
Curtis Hard f875714609 FOrmatting 2020-01-14 21:12:38 +00:00
Curtis Hard b8f166f4c1 Uses NSAnimationContext over CATransaction for safety 2020-01-14 21:12:33 +00:00
Curtis Hard 7901c9eafe Possible fixes for main thread 2020-01-14 20:41:59 +00:00
Curtis Hard 5de88cb1d7 #oopsie 2020-01-14 16:38:08 +00:00
Curtis Hard 6216b61c19 Fixes compat for 10.13 with CGPath block applying 2020-01-14 16:34:52 +00:00
Curtis Hard e05f5a0884 Fixes compatibility issues for 10.9 2020-01-14 15:51:15 +00:00
Curtis Hard 849807d3c5 Updated build number 2020-01-05 17:11:41 +00:00
Curtis Hard eeb03bd89c Fixes exporter being wrong if the viewbox is not zero 2020-01-02 14:16:17 +00:00
Curtis Hard fdc0859e3f Faster parsing still 2020-01-01 22:06:29 +00:00
Curtis Hard e2a7f51507 Fixes 2020-01-01 17:48:15 +00:00
Curtis Hard ab69ed94dc Formatting 2019-12-29 20:50:44 +00:00
Curtis Hard c5be83f57f Code cleanup 2019-12-28 15:48:43 +00:00
Curtis Hard ed00aca06e Refactor 2019-12-27 16:48:12 +00:00
Curtis Hard f51fda5f1e Removed cache
- also fixes center if no scale was applied
2019-12-27 15:01:20 +00:00
Curtis Hard dd655053ca Finally fixes memory leak
- due to this being fixed, we can also get rid of the transaction lock
2019-12-26 20:10:47 +00:00
Curtis Hard 8c89627f74 Just use matrix, attributes are a pain in the butt 2019-12-26 16:08:14 +00:00
Curtis Hard eb1d27decd Much better path compression and float rewriting for exporting 2019-12-26 13:49:41 +00:00
Curtis Hard e6141d7a0f Fixes a long time ago bug with transforms with matrix converting to attribute strings 2019-12-25 21:05:56 +00:00
Curtis Hard 3b7ad40794 Vey strange... 2019-12-25 18:40:50 +00:00
Curtis Hard 674d17863f Fixes memory overflow issues
- also added centering for exported SVG’s as an option
2019-12-25 18:19:28 +00:00
Curtis Hard a59072fa1d Refactor 2019-12-25 13:53:42 +00:00
Curtis Hard 910b90cd4e More perf stuff 2019-12-25 13:45:13 +00:00
Curtis Hard bb3b9c5378 More improvements 2019-12-25 11:58:10 +00:00
Curtis Hard 6d10b172e7 Increases again 2019-12-24 14:47:47 +00:00
Curtis Hard c6e59a9280 More perf increases 2019-12-24 09:27:06 +00:00
Curtis Hard df5b3219ca Refactor of naming 2019-12-23 21:59:19 +00:00
Curtis Hard 2c1ae8d0f3 Credit where its due 2019-12-23 21:40:02 +00:00
Curtis Hard 7ba939aabf This is insanely fast 2019-12-23 20:48:12 +00:00
Curtis Hard 24e097fedf Faster again! 2019-12-23 20:30:05 +00:00
Curtis Hard 025ac84958 Refactor of command parsing 2019-12-23 19:37:56 +00:00
Curtis Hard ac9ccdda25 Refactor 2019-12-23 16:17:47 +00:00
Curtis Hard 14641ddd60 More goodies 2019-12-23 15:40:41 +00:00
Curtis Hard 5f32d03744 Intiial commit 2019-12-23 14:24:49 +00:00
Curtis Hard af086622b1 Faster implementation of transaction 2019-12-22 22:19:20 +00:00
Curtis Hard 79187326bc Added CGImageRef method 2019-12-21 13:23:52 +00:00
Curtis Hard ee570eb77f Fixes scale being incorrect 2019-12-20 08:36:12 +00:00
Curtis Hard d8e1ce8d70 This is much more performant then using nsimage lockFocus 2019-12-19 22:32:55 +00:00
Curtis Hard a900e2dc50 Resorted this list as its actually faster, basically stick the commonly used commands first 2019-12-17 21:48:52 +00:00
Curtis Hard 21f97babec Refactor of contsant names 2019-12-12 11:02:49 +00:00
Curtis Hard 0273a491de Refactor of path - uses less memory and makes more sense 2019-12-12 10:51:20 +00:00
Curtis Hard 488a0c3654 Update all things! 2019-12-12 08:09:08 +00:00
Curtis Hard 7f7321e6a7 Merge branch 'feature/primitiveExportTypes' 2019-12-12 08:07:05 +00:00
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
Curtis Hard 1993c55cb8 Fixed bounds issue + colors with new line not parsing correctly 2018-01-21 21:25:36 +00:00
Curtis Hard 1f13134ccd Refactored various font things
- added CGPath methods to IJSVGUtils
2018-01-20 12:48:54 +00:00
Curtis Hard 435489f65f Removed multipass 2018-01-19 22:07:29 +00:00
Curtis Hard 4bcbcc374b Check full detail …
- adds convenience method for grabbing an SVG string from an IJSVG object
- Completely swapped IJSVGFontConverter over to use IJSVG and the IJSVGExporter
- Fixed memory leak of Defs element when exporting
2018-01-19 21:55:47 +00:00
Curtis Hard cb544d7a6b Added begin and end vector draw so they are not private 2018-01-16 22:18:25 +00:00
Curtis Hard a4cd0bcc4e Fixes issue with comments being parsed incorrectly in defs 2018-01-16 21:15:24 +00:00
Curtis Hard 02b03d8862 Fixes issue with defined elements causing infinate loop when exported from latest Sketch version 2017-12-06 20:45:24 +00:00
Curtis Hard 94ae7c2757 Added easy method for replacing whole dictionary 2017-11-14 13:29:06 +00:00
Curtis Hard 27371a9d78 Fixes issue with default fill color not being able to be user defined/replaced 2017-11-13 22:00:33 +00:00
Curtis Hard 3c1422a65f Initial color replacement start 2017-11-11 22:50:14 +00:00
Curtis Hard 8ed817aa43 Merge pull request #9 from Deadpikle/master
Fix missing files and macOS SDK setting
2017-11-07 17:55:29 +00:00
Deadpikle ca754ff61c Fix missing files and macOS SDK setting 2017-11-07 12:14:22 -05:00
Curtis Hard 53da0fca4b Refactor of shape layer and default layer 2017-09-13 11:31:58 +01:00
Curtis Hard 1259ce1e63 method name changes 2017-09-12 23:30:58 +01:00
Curtis Hard 70cd111b1c Neatness change 2017-09-12 23:11:31 +01:00
Curtis Hard 15b0805bf9 PDF!!!!!!!!
- This is nuts, so we work out way through the layers working out which are masks, working out the actual path that the mask shape would eventually have amd clip the context when it draws, hell yehs…
2017-09-12 23:00:44 +01:00
Curtis Hard e11e28c54f Here we go.. 2017-09-12 16:23:37 +01:00
Curtis Hard f320bd4684 Added compression options to export SVG 2017-09-11 21:05:51 +01:00
Curtis Hard 2faeda560f More performance 2017-09-10 18:00:06 +01:00
Curtis Hard c56a5ecca1 Faster export 2017-09-07 13:17:48 +01:00
Curtis Hard e85f67358e Initial changes for icon size to export 2017-09-05 16:03:38 +01:00
Curtis Hard 0fb27d4e94 Fixed issue where a color was not specified but a fill opacity was if no overiding color was set. 2017-09-03 20:01:30 +01:00
Curtis Hard 9bce41afff Various memory fixes 2017-07-28 21:55:49 +01:00
Curtis Hard 09b0cc6d96 Added ability to customise strokeWidth, lineCapStyle and lineJoinStyle on the root SVG object
- These will override any given styles/attributes on any element in the SVG
2017-07-04 21:25:41 +01:00
Curtis Hard 58fbb01ff2 Moved command char checker over to C call, believe it or not, this is alot faster then using a characterSet 2017-06-05 21:36:01 +01:00
Curtis Hard 5a5b144ab1 Fixes infinate loop with invalid selector characters 2017-06-05 19:31:22 +01:00
Curtis Hard 359cff7569 Squashed commit of the following:
commit d6b14b9aadc8295512f9a5513d9a3f4169d5965d
Author: Curtis Hard <curtishard@me.com>
Date:   Sun Apr 9 22:37:15 2017 +0100

    Changes to valid chars for a selector
2017-04-16 20:40:32 +01:00
Curtis Hard 57bfe633e7 Fixes issue with capitals in CSS selectors 2017-04-07 14:17:24 +01:00
Curtis Hard c757fb4b33 Merge remote-tracking branch 'origin/fixes/stroke-gradients' 2017-04-05 09:09:26 +01:00
Curtis Hard 4d1141a889 Added methods for dealing with drawing in views 2017-04-04 14:50:07 +01:00
Curtis Hard 481359ec58 Added IJSVGView - easy way to set SVG image from bundle in IB 2017-04-04 10:08:01 +01:00
Curtis Hard fb14d7be65 Added viewPort to the layer tree 2017-03-30 09:55:22 +01:00
Curtis Hard 0e4a5528f7 Added gradient unit length 2017-03-29 16:17:58 +01:00
Curtis Hard 36216a51ed Fixed dashes offset being wrong attribute key 2017-03-28 12:30:49 +01:00
Curtis Hard 9e1ffd5d46 Fixes parsing issues for DEF’s
- Some defs were not being picked up due to people sticking them at the bottom of the file, IJSVG works top down, so they were ignored, now every group or parent element will be checked for defs, parsed and then will worry about being parsed afterwards :)
2017-03-17 14:46:18 +00:00
Curtis Hard 05d0b6e173 Fixes strokes not being exported of no stroke color is set 2017-03-13 22:23:35 +00:00
Curtis Hard 9cecea923c Comments... 2017-03-13 22:02:42 +00:00
Curtis Hard 8ff1fc860e Various fixes to gradient and pattern strokes 2017-03-13 21:59:50 +00:00
Curtis Hard edef84274d Merge branch 'feature/currentcolorsupport' 2017-03-06 12:50:04 +00:00
Curtis Hard 484675f666 removed miterLimit, added currentColor to being 000 2017-03-01 14:22:50 +00:00
Curtis Hard 2f574e3cbb Fix for end char being wrong when parsing a style 2017-02-22 23:05:52 +00:00
Curtis Hard b64b0f3735 Set theme jekyll-theme-cayman 2017-02-21 13:20:09 +00:00
Curtis Hard c0cdb41ddc Set theme jekyll-theme-minimal 2017-02-21 13:18:43 +00:00
Curtis Hard 258a617564 Added X and Y to pattern node 2017-02-20 11:00:40 +00:00
Curtis Hard bf40002fe0 Adds size option to the exporter 2017-02-19 21:35:42 +00:00
Curtis Hard 2ef0bd88ef Fixes NAN issue on Arc command 2017-02-16 15:41:31 +00:00
Curtis Hard 0aca44ef76 Added offsets to pattern and gradients 2017-02-16 15:26:02 +00:00
Curtis Hard a3e512d7b8 Added fill opacity to pattern layers 2017-02-15 13:44:15 +00:00
Curtis Hard 0ffd20e87c Fixes and better gradient support 2017-02-09 21:18:30 +00:00
Curtis Hard 0f0943816c Provided a color stop if none were provided 2017-02-09 14:37:33 +00:00
Curtis Hard ddb5b2f746 Remove comment 2017-02-08 21:23:01 +00:00
Curtis Hard 80bc3ed1d8 Fixes various drawing and export issues
- Fixes transform being incorrect on export
- Fixes incorrect collapasing of groups with transforms
- Fixes incorrect alpha value in RGBA being used when exporting
- Fixes masking issue on groups (basically never applied them)
- Fixed incorrect parsing of “none” on dash count
2017-02-08 21:22:54 +00:00
Curtis Hard 1a7a7b4d7b Told image layer to need help with rasterizing 2017-02-07 10:04:42 +00:00
Curtis Hard 0876a1e976 Fixes switches that needed parsing
- Basically just parses the things we actually support, nothing more, nothing less
2017-02-07 09:52:05 +00:00
Curtis Hard 6747160504 Fixes issue with Stylesheets that are embedded inside defs not being parsed 2017-02-06 14:01:02 +00:00
Curtis Hard d2059e4d2f Removed switch elements as they are pretty useless in context of what this is used for:
- Also moved styls element and defs element into the default parsing process, which actually speeds up parsing a fair bit (when dealing with loading of 100’s of SVG’s at once)
2017-02-04 23:04:56 +00:00
Curtis Hard 71c47a313e Fixes various export issues
- Fixed issue with exporting SVG where elements that should be hidden were not being given the display:none style.
- Added option for completely removing any elements that are technically hidden (as long as they are not in the defs)
2017-01-27 23:49:08 +00:00
Curtis Hard 70f9c29fe5 This fixes hidden layers from showing
- Basically not obbeying the hidden node properly
- Also fixes CSS parser from beach balling when parsing @ selectors
- Also dramatically improves parsing of key value pairs in CSS, by dramatically, i mean took a file down from 300ms parse to 5ms… woah.
2017-01-27 19:10:01 +00:00
Curtis Hard 5f8f3d8be5 Initial blending mode support 2017-01-24 15:38:17 +00:00
Curtis Hard e26ebe300f Merge branch 'feature/pattern_gradient_strokes' 2017-01-19 15:44:13 +00:00
Curtis Hard c0c46ad2b7 Fixes overriding stroke colour not being applied to gradient or pattern strokes 2017-01-19 15:43:26 +00:00
Curtis Hard abade39e2a Fixes a huge bug with duplication on use elements being parsed and reparsed over and over 2017-01-18 16:32:57 +00:00
Curtis Hard 2f7a6aa213 Fix for gradient units not being applied 2017-01-18 15:31:08 +00:00
Curtis Hard 2598046369 Fixes string issue with linear gradients 2017-01-18 15:20:11 +00:00
Curtis Hard 5424e32a63 Various refactors for stroke pattern and gradient pattern 2017-01-18 14:59:48 +00:00
Curtis Hard a8a7f8d356 Unit computation fixes 2017-01-17 10:46:46 +00:00
Curtis Hard a3bde2f710 Fixed value working out issue 2017-01-17 09:22:19 +00:00
Curtis Hard 0cc22cad44 Update README.md 2017-01-15 21:02:35 +00:00
Curtis Hard 448d46e8ec Update README.md 2017-01-15 12:28:14 +00:00
213 changed files with 40393 additions and 17566 deletions
@@ -0,0 +1,939 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
5919E65723F47FF60051873A /* IJSVGUnitRect.h in Headers */ = {isa = PBXBuildFile; fileRef = 5919E65523F47FF60051873A /* IJSVGUnitRect.h */; settings = {ATTRIBUTES = (Public, ); }; };
5919E65823F47FF60051873A /* IJSVGUnitRect.m in Sources */ = {isa = PBXBuildFile; fileRef = 5919E65623F47FF60051873A /* IJSVGUnitRect.m */; };
5919E65B23F480330051873A /* IJSVGUnitPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 5919E65923F480330051873A /* IJSVGUnitPoint.h */; settings = {ATTRIBUTES = (Public, ); }; };
5919E65C23F480330051873A /* IJSVGUnitPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 5919E65A23F480330051873A /* IJSVGUnitPoint.m */; };
591A3E4D25CC91F800AD45B7 /* IJSVGParsing.h in Headers */ = {isa = PBXBuildFile; fileRef = 591A3E4B25CC91F800AD45B7 /* IJSVGParsing.h */; settings = {ATTRIBUTES = (Public, ); }; };
591A3E4E25CC91F800AD45B7 /* IJSVGParsing.m in Sources */ = {isa = PBXBuildFile; fileRef = 591A3E4C25CC91F800AD45B7 /* IJSVGParsing.m */; };
594A10DA248D7C90001A3181 /* NSImage+IJSVGAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
594A10DB248D7C90001A3181 /* NSImage+IJSVGAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */; };
594CF55F238FF462009B251B /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF55E238FF462009B251B /* AppKit.framework */; };
594CF561238FF46C009B251B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF560238FF46C009B251B /* Foundation.framework */; };
594CF563238FF473009B251B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594CF562238FF473009B251B /* QuartzCore.framework */; };
599EB4D3238FF570004CB6BC /* libobjc.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 599EB4D2238FF535004CB6BC /* libobjc.tbd */; };
59A24EBC23F480EA0090C374 /* IJSVGUnitSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A24EBA23F480EA0090C374 /* IJSVGUnitSize.h */; settings = {ATTRIBUTES = (Public, ); }; };
59A24EBD23F480EA0090C374 /* IJSVGUnitSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A24EBB23F480EA0090C374 /* IJSVGUnitSize.m */; };
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */; };
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756523905F6B00F5AE63 /* IJSVGLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75D723905F7300F5AE63 /* IJSVGGradientLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756623905F6B00F5AE63 /* IJSVGGradientLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75D823905F7300F5AE63 /* IJSVGStyleSheetRule.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756723905F6B00F5AE63 /* IJSVGStyleSheetRule.m */; };
59EB75D923905F7300F5AE63 /* IJSVGCommandLineTo.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756823905F6B00F5AE63 /* IJSVGCommandLineTo.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75DA23905F7300F5AE63 /* IJSVGDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756923905F6B00F5AE63 /* IJSVGDef.m */; };
59EB75DB23905F7300F5AE63 /* IJSVG.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756A23905F6B00F5AE63 /* IJSVG.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75DC23905F7300F5AE63 /* IJSVGText.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756B23905F6B00F5AE63 /* IJSVGText.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75DD23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */; };
59EB75DE23905F7300F5AE63 /* IJSVGCommandVerticalLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E023905F7300F5AE63 /* IJSVGStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E123905F7300F5AE63 /* IJSVGCommandSmoothCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757123905F6C00F5AE63 /* IJSVGColorList.m */; };
59EB75E323905F7300F5AE63 /* IJSVGRadialGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757323905F6C00F5AE63 /* IJSVGGradientUnitLength.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E523905F7300F5AE63 /* IJSVGStrokeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */; };
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757523905F6C00F5AE63 /* IJSVGStyle.m */; };
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757623905F6C00F5AE63 /* IJSVGImage.m */; };
59EB75E823905F7300F5AE63 /* IJSVGUnitLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757723905F6C00F5AE63 /* IJSVGUnitLength.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */; };
59EB75EA23905F7300F5AE63 /* IJSVGTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757923905F6C00F5AE63 /* IJSVGTransaction.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */; };
59EB75EC23905F7300F5AE63 /* IJSVGLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */; };
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */; };
59EB75EE23905F7300F5AE63 /* IJSVGImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */; };
59EB75EF23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757E23905F6C00F5AE63 /* IJSVGCommandQuadraticCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F023905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB757F23905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F123905F7300F5AE63 /* IJSVGUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758023905F6C00F5AE63 /* IJSVGUtils.m */; };
59EB75F223905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758123905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.m */; };
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758223905F6C00F5AE63 /* IJSVGGroupLayer.m */; };
59EB75F423905F7300F5AE63 /* IJSVGColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758323905F6C00F5AE63 /* IJSVGColor.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F523905F7300F5AE63 /* IJSVGError.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758423905F6C00F5AE63 /* IJSVGError.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758523905F6C00F5AE63 /* IJSVGColor.m */; };
59EB75F723905F7300F5AE63 /* IJSVGDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758623905F6C00F5AE63 /* IJSVGDef.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */; };
59EB75F923905F7300F5AE63 /* IJSVGFontConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758A23905F6D00F5AE63 /* IJSVGPath.m */; };
59EB75FC23905F7300F5AE63 /* IJSVGGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */; };
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */; };
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */; };
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */; };
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */; };
59EB760323905F7300F5AE63 /* IJSVGNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759223905F6D00F5AE63 /* IJSVGNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760523905F7300F5AE63 /* IJSVGUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759423905F6D00F5AE63 /* IJSVGUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760623905F7300F5AE63 /* IJSVGCommandHorizontalLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759523905F6D00F5AE63 /* IJSVGCommandHorizontalLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759623905F6D00F5AE63 /* IJSVGNode.m */; };
59EB760823905F7300F5AE63 /* IJSVGShapeLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760923905F7300F5AE63 /* IJSVGCommandCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759823905F6E00F5AE63 /* IJSVGCommandCurve.m */; };
59EB760A23905F7300F5AE63 /* IJSVGCommandMove.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB759923905F6E00F5AE63 /* IJSVGCommandMove.m */; };
59EB760B23905F7300F5AE63 /* IJSVGStyleSheetSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759A23905F6E00F5AE63 /* IJSVGStyleSheetSelector.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760C23905F7300F5AE63 /* IJSVGStyleSheetRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759B23905F6E00F5AE63 /* IJSVGStyleSheetRule.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760D23905F7300F5AE63 /* IJSVGCommandCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759C23905F6E00F5AE63 /* IJSVGCommandCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760E23905F7300F5AE63 /* IJSVGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759D23905F6E00F5AE63 /* IJSVGPath.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB760F23905F7300F5AE63 /* IJSVGCommandEllipticalArc.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759E23905F6E00F5AE63 /* IJSVGCommandEllipticalArc.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761023905F7300F5AE63 /* IJSVGLinearGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761123905F7300F5AE63 /* IJSVGCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A023905F6E00F5AE63 /* IJSVGCommand.m */; };
59EB761223905F7300F5AE63 /* IJSVGRenderingStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A123905F6E00F5AE63 /* IJSVGRenderingStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761323905F7300F5AE63 /* IJSVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A223905F6E00F5AE63 /* IJSVG.m */; };
59EB761423905F7300F5AE63 /* IJSVGImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761523905F7300F5AE63 /* IJSVGStrokeLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761623905F7300F5AE63 /* IJSVGParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A523905F6E00F5AE63 /* IJSVGParser.m */; };
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */; };
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A723905F6F00F5AE63 /* IJSVGParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761923905F7300F5AE63 /* IJSVGCommandSmoothCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75A823905F6F00F5AE63 /* IJSVGCommandSmoothCurve.m */; };
59EB761A23905F7300F5AE63 /* IJSVGColorList.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761B23905F7300F5AE63 /* IJSVGPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75AA23905F6F00F5AE63 /* IJSVGPattern.m */; };
59EB761C23905F7300F5AE63 /* IJSVGGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761D23905F7300F5AE63 /* IJSVGStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AC23905F6F00F5AE63 /* IJSVGStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AD23905F6F00F5AE63 /* IJSVGGroupLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB761F23905F7300F5AE63 /* IJSVGCommandLineTo.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75AE23905F6F00F5AE63 /* IJSVGCommandLineTo.m */; };
59EB762023905F7300F5AE63 /* IJSVGCommandMove.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75AF23905F6F00F5AE63 /* IJSVGCommandMove.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762123905F7300F5AE63 /* IJSVGTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B023905F6F00F5AE63 /* IJSVGTransform.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762223905F7300F5AE63 /* IJSVGMath.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B123905F6F00F5AE63 /* IJSVGMath.m */; };
59EB762323905F7300F5AE63 /* IJSVGExporterPathInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B223905F6F00F5AE63 /* IJSVGExporterPathInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762423905F7300F5AE63 /* IJSVGTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B323905F6F00F5AE63 /* IJSVGTransaction.m */; };
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B423905F6F00F5AE63 /* IJSVGTransform.m */; };
59EB762623905F7300F5AE63 /* IJSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B523905F7000F5AE63 /* IJSVGImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762723905F7300F5AE63 /* IJSVGMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B623905F7000F5AE63 /* IJSVGMath.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B723905F7000F5AE63 /* IJSVGCommandClose.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762923905F7300F5AE63 /* IJSVGStringAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762A23905F7300F5AE63 /* IJSVGGradientUnitLength.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75B923905F7000F5AE63 /* IJSVGGradientUnitLength.m */; };
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */; };
59EB762C23905F7300F5AE63 /* IJSVGPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BB23905F7000F5AE63 /* IJSVGPattern.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762D23905F7300F5AE63 /* IJSVGLayerTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BC23905F7000F5AE63 /* IJSVGLayerTree.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB762E23905F7300F5AE63 /* IJSVGExporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75BD23905F7000F5AE63 /* IJSVGExporter.m */; };
59EB763023905F7300F5AE63 /* IJSVGPatternLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C023905F7100F5AE63 /* IJSVGText.m */; };
59EB763223905F7300F5AE63 /* IJSVGView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C123905F7100F5AE63 /* IJSVGView.m */; };
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */; };
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */; };
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */; };
59EB763723905F7300F5AE63 /* IJSVGCommandClose.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */; };
59EB763823905F7300F5AE63 /* IJSVGCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75C723905F7100F5AE63 /* IJSVGCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763923905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C823905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m */; };
59EB763A23905F7300F5AE63 /* IJSVGForeignObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75C923905F7200F5AE63 /* IJSVGForeignObject.m */; };
59EB763B23905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75CA23905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75CB23905F7200F5AE63 /* IJSVGCommandEllipticalArc.m */; };
59EB763D23905F7300F5AE63 /* IJSVGGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75CC23905F7200F5AE63 /* IJSVGGroup.m */; };
59EB763E23905F7300F5AE63 /* IJSVGView.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75CD23905F7200F5AE63 /* IJSVGView.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB763F23905F7300F5AE63 /* IJSVGForeignObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75CE23905F7200F5AE63 /* IJSVGForeignObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB764023905F7300F5AE63 /* IJSVGExporterPathInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75CF23905F7200F5AE63 /* IJSVGExporterPathInstruction.m */; };
59EB764123905F7300F5AE63 /* IJSVGImageLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D023905F7200F5AE63 /* IJSVGImageLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB764223905F7300F5AE63 /* IJSVGStyleSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D123905F7300F5AE63 /* IJSVGStyleSheet.m */; };
59EB764323905F7300F5AE63 /* IJSVGGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D223905F7300F5AE63 /* IJSVGGradient.m */; };
59EB764423905F7300F5AE63 /* IJSVGRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D323905F7300F5AE63 /* IJSVGRendering.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 59EB75D423905F7300F5AE63 /* IJSVGExporter.h */; settings = {ATTRIBUTES = (Public, ); }; };
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */ = {isa = PBXBuildFile; fileRef = 59EB75D523905F7300F5AE63 /* IJSVGRendering.m */; };
59F36508262F1ABB00BCE3FD /* IJSVGColorType.h in Headers */ = {isa = PBXBuildFile; fileRef = 59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */; settings = {ATTRIBUTES = (Public, ); }; };
59F36509262F1ABB00BCE3FD /* IJSVGColorType.m in Sources */ = {isa = PBXBuildFile; fileRef = 59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
5919E65523F47FF60051873A /* IJSVGUnitRect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitRect.h; sourceTree = "<group>"; };
5919E65623F47FF60051873A /* IJSVGUnitRect.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitRect.m; sourceTree = "<group>"; };
5919E65923F480330051873A /* IJSVGUnitPoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitPoint.h; sourceTree = "<group>"; };
5919E65A23F480330051873A /* IJSVGUnitPoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitPoint.m; sourceTree = "<group>"; };
591A3E4B25CC91F800AD45B7 /* IJSVGParsing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGParsing.h; sourceTree = "<group>"; };
591A3E4C25CC91F800AD45B7 /* IJSVGParsing.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGParsing.m; sourceTree = "<group>"; };
594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSImage+IJSVGAdditions.h"; sourceTree = "<group>"; };
594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSImage+IJSVGAdditions.m"; sourceTree = "<group>"; };
594CF46F238FF38E009B251B /* IJSVG.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IJSVG.framework; sourceTree = BUILT_PRODUCTS_DIR; };
594CF473238FF38E009B251B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
594CF55E238FF462009B251B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
594CF560238FF46C009B251B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
594CF562238FF473009B251B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
599EB4D2238FF535004CB6BC /* libobjc.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libobjc.tbd; path = usr/lib/libobjc.tbd; sourceTree = SDKROOT; };
59A24EBA23F480EA0090C374 /* IJSVGUnitSize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitSize.h; sourceTree = "<group>"; };
59A24EBB23F480EA0090C374 /* IJSVGUnitSize.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitSize.m; sourceTree = "<group>"; };
59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IJSVGCommandParser.h; path = IJSVG/Source/Parsing/IJSVGCommandParser.h; sourceTree = SOURCE_ROOT; };
59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = IJSVGCommandParser.m; path = IJSVG/Source/Parsing/IJSVGCommandParser.m; sourceTree = SOURCE_ROOT; };
59EB756523905F6B00F5AE63 /* IJSVGLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLayer.h; sourceTree = "<group>"; };
59EB756623905F6B00F5AE63 /* IJSVGGradientLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradientLayer.h; sourceTree = "<group>"; };
59EB756723905F6B00F5AE63 /* IJSVGStyleSheetRule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetRule.m; sourceTree = "<group>"; };
59EB756823905F6B00F5AE63 /* IJSVGCommandLineTo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandLineTo.h; sourceTree = "<group>"; };
59EB756923905F6B00F5AE63 /* IJSVGDef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGDef.m; sourceTree = "<group>"; };
59EB756A23905F6B00F5AE63 /* IJSVG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVG.h; sourceTree = "<group>"; };
59EB756B23905F6B00F5AE63 /* IJSVGText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGText.h; sourceTree = "<group>"; };
59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandQuadraticCurve.m; sourceTree = "<group>"; };
59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandVerticalLine.h; sourceTree = "<group>"; };
59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheet.h; sourceTree = "<group>"; };
59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandSmoothCurve.h; sourceTree = "<group>"; };
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGColorList.m; sourceTree = "<group>"; };
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRadialGradient.h; sourceTree = "<group>"; };
59EB757323905F6C00F5AE63 /* IJSVGGradientUnitLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradientUnitLength.h; sourceTree = "<group>"; };
59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStrokeLayer.m; sourceTree = "<group>"; };
59EB757523905F6C00F5AE63 /* IJSVGStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyle.m; sourceTree = "<group>"; };
59EB757623905F6C00F5AE63 /* IJSVGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImage.m; sourceTree = "<group>"; };
59EB757723905F6C00F5AE63 /* IJSVGUnitLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGUnitLength.h; sourceTree = "<group>"; };
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStringAdditions.m; sourceTree = "<group>"; };
59EB757923905F6C00F5AE63 /* IJSVGTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGTransaction.h; sourceTree = "<group>"; };
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGShapeLayer.m; sourceTree = "<group>"; };
59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLayer.m; sourceTree = "<group>"; };
59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGFontConverter.m; sourceTree = "<group>"; };
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImageRep.m; sourceTree = "<group>"; };
59EB757E23905F6C00F5AE63 /* IJSVGCommandQuadraticCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandQuadraticCurve.h; sourceTree = "<group>"; };
59EB757F23905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheetSelectorRaw.h; sourceTree = "<group>"; };
59EB758023905F6C00F5AE63 /* IJSVGUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGUtils.m; sourceTree = "<group>"; };
59EB758123905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetSelectorRaw.m; sourceTree = "<group>"; };
59EB758223905F6C00F5AE63 /* IJSVGGroupLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGroupLayer.m; sourceTree = "<group>"; };
59EB758323905F6C00F5AE63 /* IJSVGColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGColor.h; sourceTree = "<group>"; };
59EB758423905F6C00F5AE63 /* IJSVGError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGError.h; sourceTree = "<group>"; };
59EB758523905F6C00F5AE63 /* IJSVGColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGColor.m; sourceTree = "<group>"; };
59EB758623905F6C00F5AE63 /* IJSVGDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGDef.h; sourceTree = "<group>"; };
59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandHorizontalLine.m; sourceTree = "<group>"; };
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGFontConverter.h; sourceTree = "<group>"; };
59EB758A23905F6D00F5AE63 /* IJSVGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPath.m; sourceTree = "<group>"; };
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGroup.h; sourceTree = "<group>"; };
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPatternLayer.m; sourceTree = "<group>"; };
59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRenderingStyle.m; sourceTree = "<group>"; };
59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientLayer.m; sourceTree = "<group>"; };
59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLayerTree.m; sourceTree = "<group>"; };
59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandVerticalLine.m; sourceTree = "<group>"; };
59EB759223905F6D00F5AE63 /* IJSVGNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGNode.h; sourceTree = "<group>"; };
59EB759423905F6D00F5AE63 /* IJSVGUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGUtils.h; sourceTree = "<group>"; };
59EB759523905F6D00F5AE63 /* IJSVGCommandHorizontalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandHorizontalLine.h; sourceTree = "<group>"; };
59EB759623905F6D00F5AE63 /* IJSVGNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGNode.m; sourceTree = "<group>"; };
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGShapeLayer.h; sourceTree = "<group>"; };
59EB759823905F6E00F5AE63 /* IJSVGCommandCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandCurve.m; sourceTree = "<group>"; };
59EB759923905F6E00F5AE63 /* IJSVGCommandMove.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandMove.m; sourceTree = "<group>"; };
59EB759A23905F6E00F5AE63 /* IJSVGStyleSheetSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheetSelector.h; sourceTree = "<group>"; };
59EB759B23905F6E00F5AE63 /* IJSVGStyleSheetRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyleSheetRule.h; sourceTree = "<group>"; };
59EB759C23905F6E00F5AE63 /* IJSVGCommandCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandCurve.h; sourceTree = "<group>"; };
59EB759D23905F6E00F5AE63 /* IJSVGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGPath.h; sourceTree = "<group>"; };
59EB759E23905F6E00F5AE63 /* IJSVGCommandEllipticalArc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandEllipticalArc.h; sourceTree = "<group>"; };
59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLinearGradient.h; sourceTree = "<group>"; };
59EB75A023905F6E00F5AE63 /* IJSVGCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommand.m; sourceTree = "<group>"; };
59EB75A123905F6E00F5AE63 /* IJSVGRenderingStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRenderingStyle.h; sourceTree = "<group>"; };
59EB75A223905F6E00F5AE63 /* IJSVG.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVG.m; sourceTree = "<group>"; };
59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImageRep.h; sourceTree = "<group>"; };
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStrokeLayer.h; sourceTree = "<group>"; };
59EB75A523905F6E00F5AE63 /* IJSVGParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGParser.m; sourceTree = "<group>"; };
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRadialGradient.m; sourceTree = "<group>"; };
59EB75A723905F6F00F5AE63 /* IJSVGParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGParser.h; sourceTree = "<group>"; };
59EB75A823905F6F00F5AE63 /* IJSVGCommandSmoothCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandSmoothCurve.m; sourceTree = "<group>"; };
59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGColorList.h; sourceTree = "<group>"; };
59EB75AA23905F6F00F5AE63 /* IJSVGPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGPattern.m; sourceTree = "<group>"; };
59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGradient.h; sourceTree = "<group>"; };
59EB75AC23905F6F00F5AE63 /* IJSVGStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStyle.h; sourceTree = "<group>"; };
59EB75AD23905F6F00F5AE63 /* IJSVGGroupLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGGroupLayer.h; sourceTree = "<group>"; };
59EB75AE23905F6F00F5AE63 /* IJSVGCommandLineTo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandLineTo.m; sourceTree = "<group>"; };
59EB75AF23905F6F00F5AE63 /* IJSVGCommandMove.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandMove.h; sourceTree = "<group>"; };
59EB75B023905F6F00F5AE63 /* IJSVGTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGTransform.h; sourceTree = "<group>"; };
59EB75B123905F6F00F5AE63 /* IJSVGMath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGMath.m; sourceTree = "<group>"; };
59EB75B223905F6F00F5AE63 /* IJSVGExporterPathInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGExporterPathInstruction.h; sourceTree = "<group>"; };
59EB75B323905F6F00F5AE63 /* IJSVGTransaction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGTransaction.m; sourceTree = "<group>"; };
59EB75B423905F6F00F5AE63 /* IJSVGTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGTransform.m; sourceTree = "<group>"; };
59EB75B523905F7000F5AE63 /* IJSVGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImage.h; sourceTree = "<group>"; };
59EB75B623905F7000F5AE63 /* IJSVGMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGMath.h; sourceTree = "<group>"; };
59EB75B723905F7000F5AE63 /* IJSVGCommandClose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandClose.h; sourceTree = "<group>"; };
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGStringAdditions.h; sourceTree = "<group>"; };
59EB75B923905F7000F5AE63 /* IJSVGGradientUnitLength.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradientUnitLength.m; sourceTree = "<group>"; };
59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGUnitLength.m; sourceTree = "<group>"; };
59EB75BB23905F7000F5AE63 /* IJSVGPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGPattern.h; sourceTree = "<group>"; };
59EB75BC23905F7000F5AE63 /* IJSVGLayerTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGLayerTree.h; sourceTree = "<group>"; };
59EB75BD23905F7000F5AE63 /* IJSVGExporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGExporter.m; sourceTree = "<group>"; };
59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGPatternLayer.h; sourceTree = "<group>"; };
59EB75C023905F7100F5AE63 /* IJSVGText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGText.m; sourceTree = "<group>"; };
59EB75C123905F7100F5AE63 /* IJSVGView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGView.m; sourceTree = "<group>"; };
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGLinearGradient.m; sourceTree = "<group>"; };
59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheetSelector.m; sourceTree = "<group>"; };
59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGImageLayer.m; sourceTree = "<group>"; };
59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandClose.m; sourceTree = "<group>"; };
59EB75C723905F7100F5AE63 /* IJSVGCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommand.h; sourceTree = "<group>"; };
59EB75C823905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandSmoothQuadraticCurve.m; sourceTree = "<group>"; };
59EB75C923905F7200F5AE63 /* IJSVGForeignObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGForeignObject.m; sourceTree = "<group>"; };
59EB75CA23905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGCommandSmoothQuadraticCurve.h; sourceTree = "<group>"; };
59EB75CB23905F7200F5AE63 /* IJSVGCommandEllipticalArc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGCommandEllipticalArc.m; sourceTree = "<group>"; };
59EB75CC23905F7200F5AE63 /* IJSVGGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGroup.m; sourceTree = "<group>"; };
59EB75CD23905F7200F5AE63 /* IJSVGView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGView.h; sourceTree = "<group>"; };
59EB75CE23905F7200F5AE63 /* IJSVGForeignObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGForeignObject.h; sourceTree = "<group>"; };
59EB75CF23905F7200F5AE63 /* IJSVGExporterPathInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGExporterPathInstruction.m; sourceTree = "<group>"; };
59EB75D023905F7200F5AE63 /* IJSVGImageLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGImageLayer.h; sourceTree = "<group>"; };
59EB75D123905F7300F5AE63 /* IJSVGStyleSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGStyleSheet.m; sourceTree = "<group>"; };
59EB75D223905F7300F5AE63 /* IJSVGGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGGradient.m; sourceTree = "<group>"; };
59EB75D323905F7300F5AE63 /* IJSVGRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGRendering.h; sourceTree = "<group>"; };
59EB75D423905F7300F5AE63 /* IJSVGExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJSVGExporter.h; sourceTree = "<group>"; };
59EB75D523905F7300F5AE63 /* IJSVGRendering.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJSVGRendering.m; sourceTree = "<group>"; };
59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IJSVGColorType.h; sourceTree = "<group>"; };
59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJSVGColorType.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
594CF46C238FF38E009B251B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
599EB4D3238FF570004CB6BC /* libobjc.tbd in Frameworks */,
594CF55F238FF462009B251B /* AppKit.framework in Frameworks */,
594CF561238FF46C009B251B /* Foundation.framework in Frameworks */,
594CF563238FF473009B251B /* QuartzCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
592ABBE223979F9B00F44380 /* Commands */ = {
isa = PBXGroup;
children = (
59EB75C723905F7100F5AE63 /* IJSVGCommand.h */,
59EB75A023905F6E00F5AE63 /* IJSVGCommand.m */,
59EB75B723905F7000F5AE63 /* IJSVGCommandClose.h */,
59EB75C623905F7100F5AE63 /* IJSVGCommandClose.m */,
59EB759C23905F6E00F5AE63 /* IJSVGCommandCurve.h */,
59EB759823905F6E00F5AE63 /* IJSVGCommandCurve.m */,
59EB759E23905F6E00F5AE63 /* IJSVGCommandEllipticalArc.h */,
59EB75CB23905F7200F5AE63 /* IJSVGCommandEllipticalArc.m */,
59EB759523905F6D00F5AE63 /* IJSVGCommandHorizontalLine.h */,
59EB758723905F6C00F5AE63 /* IJSVGCommandHorizontalLine.m */,
59EB756823905F6B00F5AE63 /* IJSVGCommandLineTo.h */,
59EB75AE23905F6F00F5AE63 /* IJSVGCommandLineTo.m */,
59EB75AF23905F6F00F5AE63 /* IJSVGCommandMove.h */,
59EB759923905F6E00F5AE63 /* IJSVGCommandMove.m */,
59EB757E23905F6C00F5AE63 /* IJSVGCommandQuadraticCurve.h */,
59EB756C23905F6B00F5AE63 /* IJSVGCommandQuadraticCurve.m */,
59EB757023905F6C00F5AE63 /* IJSVGCommandSmoothCurve.h */,
59EB75A823905F6F00F5AE63 /* IJSVGCommandSmoothCurve.m */,
59EB75CA23905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h */,
59EB75C823905F7200F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m */,
59EB756D23905F6C00F5AE63 /* IJSVGCommandVerticalLine.h */,
59EB759123905F6D00F5AE63 /* IJSVGCommandVerticalLine.m */,
);
path = Commands;
sourceTree = "<group>";
};
592ABBE323979FBB00F44380 /* Stylesheets */ = {
isa = PBXGroup;
children = (
59EB75AC23905F6F00F5AE63 /* IJSVGStyle.h */,
59EB757523905F6C00F5AE63 /* IJSVGStyle.m */,
59EB756F23905F6C00F5AE63 /* IJSVGStyleSheet.h */,
59EB75D123905F7300F5AE63 /* IJSVGStyleSheet.m */,
59EB759B23905F6E00F5AE63 /* IJSVGStyleSheetRule.h */,
59EB756723905F6B00F5AE63 /* IJSVGStyleSheetRule.m */,
59EB759A23905F6E00F5AE63 /* IJSVGStyleSheetSelector.h */,
59EB75C423905F7100F5AE63 /* IJSVGStyleSheetSelector.m */,
59EB757F23905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.h */,
59EB758123905F6C00F5AE63 /* IJSVGStyleSheetSelectorRaw.m */,
);
path = Stylesheets;
sourceTree = "<group>";
};
592ABBE423979FD200F44380 /* Colors */ = {
isa = PBXGroup;
children = (
59EB758323905F6C00F5AE63 /* IJSVGColor.h */,
59EB758523905F6C00F5AE63 /* IJSVGColor.m */,
59EB75A923905F6F00F5AE63 /* IJSVGColorList.h */,
59EB757123905F6C00F5AE63 /* IJSVGColorList.m */,
59F36506262F1ABB00BCE3FD /* IJSVGColorType.h */,
59F36507262F1ABB00BCE3FD /* IJSVGColorType.m */,
);
path = Colors;
sourceTree = "<group>";
};
592ABBE523979FE100F44380 /* Layers */ = {
isa = PBXGroup;
children = (
59EB756623905F6B00F5AE63 /* IJSVGGradientLayer.h */,
59EB758F23905F6D00F5AE63 /* IJSVGGradientLayer.m */,
59EB75AD23905F6F00F5AE63 /* IJSVGGroupLayer.h */,
59EB758223905F6C00F5AE63 /* IJSVGGroupLayer.m */,
59EB75D023905F7200F5AE63 /* IJSVGImageLayer.h */,
59EB75C523905F7100F5AE63 /* IJSVGImageLayer.m */,
59EB756523905F6B00F5AE63 /* IJSVGLayer.h */,
59EB757B23905F6C00F5AE63 /* IJSVGLayer.m */,
59EB75BF23905F7000F5AE63 /* IJSVGPatternLayer.h */,
59EB758C23905F6D00F5AE63 /* IJSVGPatternLayer.m */,
59EB759723905F6D00F5AE63 /* IJSVGShapeLayer.h */,
59EB757A23905F6C00F5AE63 /* IJSVGShapeLayer.m */,
59EB75A423905F6E00F5AE63 /* IJSVGStrokeLayer.h */,
59EB757423905F6C00F5AE63 /* IJSVGStrokeLayer.m */,
);
path = Layers;
sourceTree = "<group>";
};
592ABBE62397A00C00F44380 /* Parsing */ = {
isa = PBXGroup;
children = (
59E7CFAD23B148600077D599 /* IJSVGCommandParser.h */,
59E7CFAE23B148600077D599 /* IJSVGCommandParser.m */,
59EB75A723905F6F00F5AE63 /* IJSVGParser.h */,
59EB75A523905F6E00F5AE63 /* IJSVGParser.m */,
);
path = Parsing;
sourceTree = "<group>";
};
592ABBE72397A02900F44380 /* Nodes */ = {
isa = PBXGroup;
children = (
59EB75CE23905F7200F5AE63 /* IJSVGForeignObject.h */,
59EB75C923905F7200F5AE63 /* IJSVGForeignObject.m */,
59EB758623905F6C00F5AE63 /* IJSVGDef.h */,
59EB756923905F6B00F5AE63 /* IJSVGDef.m */,
59EB759F23905F6E00F5AE63 /* IJSVGLinearGradient.h */,
59EB75C223905F7100F5AE63 /* IJSVGLinearGradient.m */,
59EB757223905F6C00F5AE63 /* IJSVGRadialGradient.h */,
59EB75A623905F6F00F5AE63 /* IJSVGRadialGradient.m */,
59EB75AB23905F6F00F5AE63 /* IJSVGGradient.h */,
59EB75D223905F7300F5AE63 /* IJSVGGradient.m */,
59EB758B23905F6D00F5AE63 /* IJSVGGroup.h */,
59EB75CC23905F7200F5AE63 /* IJSVGGroup.m */,
59EB75B523905F7000F5AE63 /* IJSVGImage.h */,
59EB757623905F6C00F5AE63 /* IJSVGImage.m */,
59EB759223905F6D00F5AE63 /* IJSVGNode.h */,
59EB759623905F6D00F5AE63 /* IJSVGNode.m */,
59EB759D23905F6E00F5AE63 /* IJSVGPath.h */,
59EB758A23905F6D00F5AE63 /* IJSVGPath.m */,
59EB75BB23905F7000F5AE63 /* IJSVGPattern.h */,
59EB75AA23905F6F00F5AE63 /* IJSVGPattern.m */,
59EB756B23905F6B00F5AE63 /* IJSVGText.h */,
59EB75C023905F7100F5AE63 /* IJSVGText.m */,
);
path = Nodes;
sourceTree = "<group>";
};
592ABBE82397A06800F44380 /* Utils */ = {
isa = PBXGroup;
children = (
59EB757323905F6C00F5AE63 /* IJSVGGradientUnitLength.h */,
59EB75B923905F7000F5AE63 /* IJSVGGradientUnitLength.m */,
59EB75B623905F7000F5AE63 /* IJSVGMath.h */,
59EB75B123905F6F00F5AE63 /* IJSVGMath.m */,
59EB757923905F6C00F5AE63 /* IJSVGTransaction.h */,
59EB75B323905F6F00F5AE63 /* IJSVGTransaction.m */,
59EB75B023905F6F00F5AE63 /* IJSVGTransform.h */,
59EB75B423905F6F00F5AE63 /* IJSVGTransform.m */,
59EB757723905F6C00F5AE63 /* IJSVGUnitLength.h */,
59EB75BA23905F7000F5AE63 /* IJSVGUnitLength.m */,
59EB759423905F6D00F5AE63 /* IJSVGUtils.h */,
59EB758023905F6C00F5AE63 /* IJSVGUtils.m */,
5919E65523F47FF60051873A /* IJSVGUnitRect.h */,
5919E65623F47FF60051873A /* IJSVGUnitRect.m */,
5919E65923F480330051873A /* IJSVGUnitPoint.h */,
5919E65A23F480330051873A /* IJSVGUnitPoint.m */,
59A24EBA23F480EA0090C374 /* IJSVGUnitSize.h */,
59A24EBB23F480EA0090C374 /* IJSVGUnitSize.m */,
591A3E4B25CC91F800AD45B7 /* IJSVGParsing.h */,
591A3E4C25CC91F800AD45B7 /* IJSVGParsing.m */,
);
path = Utils;
sourceTree = "<group>";
};
592ABBE92397A08500F44380 /* Exporter */ = {
isa = PBXGroup;
children = (
59EB75D423905F7300F5AE63 /* IJSVGExporter.h */,
59EB75BD23905F7000F5AE63 /* IJSVGExporter.m */,
59EB75B223905F6F00F5AE63 /* IJSVGExporterPathInstruction.h */,
59EB75CF23905F7200F5AE63 /* IJSVGExporterPathInstruction.m */,
);
path = Exporter;
sourceTree = "<group>";
};
592ABBEA2397A10000F44380 /* Rendering */ = {
isa = PBXGroup;
children = (
59EB75BC23905F7000F5AE63 /* IJSVGLayerTree.h */,
59EB759023905F6D00F5AE63 /* IJSVGLayerTree.m */,
59EB75D323905F7300F5AE63 /* IJSVGRendering.h */,
59EB75D523905F7300F5AE63 /* IJSVGRendering.m */,
59EB75A123905F6E00F5AE63 /* IJSVGRenderingStyle.h */,
59EB758D23905F6D00F5AE63 /* IJSVGRenderingStyle.m */,
);
path = Rendering;
sourceTree = "<group>";
};
592ABBEB2397A11800F44380 /* Additions */ = {
isa = PBXGroup;
children = (
59EB75B823905F7000F5AE63 /* IJSVGStringAdditions.h */,
59EB757823905F6C00F5AE63 /* IJSVGStringAdditions.m */,
594A10D8248D7C90001A3181 /* NSImage+IJSVGAdditions.h */,
594A10D9248D7C90001A3181 /* NSImage+IJSVGAdditions.m */,
);
path = Additions;
sourceTree = "<group>";
};
594CF465238FF38E009B251B = {
isa = PBXGroup;
children = (
594CF471238FF38E009B251B /* IJSVG */,
594CF470238FF38E009B251B /* Products */,
594CF55D238FF461009B251B /* Frameworks */,
);
sourceTree = "<group>";
};
594CF470238FF38E009B251B /* Products */ = {
isa = PBXGroup;
children = (
594CF46F238FF38E009B251B /* IJSVG.framework */,
);
name = Products;
sourceTree = "<group>";
};
594CF471238FF38E009B251B /* IJSVG */ = {
isa = PBXGroup;
children = (
59EB756423905F3100F5AE63 /* Source */,
594CF473238FF38E009B251B /* Info.plist */,
);
path = IJSVG;
sourceTree = "<group>";
};
594CF55D238FF461009B251B /* Frameworks */ = {
isa = PBXGroup;
children = (
599EB4D2238FF535004CB6BC /* libobjc.tbd */,
594CF562238FF473009B251B /* QuartzCore.framework */,
594CF560238FF46C009B251B /* Foundation.framework */,
594CF55E238FF462009B251B /* AppKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
59DD1FD123A22CFD00E28C56 /* Core */ = {
isa = PBXGroup;
children = (
59EB756A23905F6B00F5AE63 /* IJSVG.h */,
59EB75A223905F6E00F5AE63 /* IJSVG.m */,
59EB758423905F6C00F5AE63 /* IJSVGError.h */,
59EB758823905F6D00F5AE63 /* IJSVGFontConverter.h */,
59EB757C23905F6C00F5AE63 /* IJSVGFontConverter.m */,
59EB75A323905F6E00F5AE63 /* IJSVGImageRep.h */,
59EB757D23905F6C00F5AE63 /* IJSVGImageRep.m */,
59EB75CD23905F7200F5AE63 /* IJSVGView.h */,
59EB75C123905F7100F5AE63 /* IJSVGView.m */,
);
path = Core;
sourceTree = "<group>";
};
59EB756423905F3100F5AE63 /* Source */ = {
isa = PBXGroup;
children = (
59DD1FD123A22CFD00E28C56 /* Core */,
592ABBEB2397A11800F44380 /* Additions */,
592ABBEA2397A10000F44380 /* Rendering */,
592ABBE92397A08500F44380 /* Exporter */,
592ABBE82397A06800F44380 /* Utils */,
592ABBE72397A02900F44380 /* Nodes */,
592ABBE62397A00C00F44380 /* Parsing */,
592ABBE523979FE100F44380 /* Layers */,
592ABBE423979FD200F44380 /* Colors */,
592ABBE323979FBB00F44380 /* Stylesheets */,
592ABBE223979F9B00F44380 /* Commands */,
);
path = Source;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
594CF46A238FF38E009B251B /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
59EB762623905F7300F5AE63 /* IJSVGImage.h in Headers */,
59EB760823905F7300F5AE63 /* IJSVGShapeLayer.h in Headers */,
59EB760F23905F7300F5AE63 /* IJSVGCommandEllipticalArc.h in Headers */,
59EB75F523905F7300F5AE63 /* IJSVGError.h in Headers */,
59EB763E23905F7300F5AE63 /* IJSVGView.h in Headers */,
59EB75DB23905F7300F5AE63 /* IJSVG.h in Headers */,
59EB764423905F7300F5AE63 /* IJSVGRendering.h in Headers */,
59EB75DC23905F7300F5AE63 /* IJSVGText.h in Headers */,
59EB761C23905F7300F5AE63 /* IJSVGGradient.h in Headers */,
59EB75F923905F7300F5AE63 /* IJSVGFontConverter.h in Headers */,
59EB75EF23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.h in Headers */,
59EB75FC23905F7300F5AE63 /* IJSVGGroup.h in Headers */,
59EB760323905F7300F5AE63 /* IJSVGNode.h in Headers */,
59EB762023905F7300F5AE63 /* IJSVGCommandMove.h in Headers */,
59EB762C23905F7300F5AE63 /* IJSVGPattern.h in Headers */,
59EB762923905F7300F5AE63 /* IJSVGStringAdditions.h in Headers */,
59EB761A23905F7300F5AE63 /* IJSVGColorList.h in Headers */,
59EB762123905F7300F5AE63 /* IJSVGTransform.h in Headers */,
59EB763F23905F7300F5AE63 /* IJSVGForeignObject.h in Headers */,
59EB75F423905F7300F5AE63 /* IJSVGColor.h in Headers */,
59EB760D23905F7300F5AE63 /* IJSVGCommandCurve.h in Headers */,
59EB763823905F7300F5AE63 /* IJSVGCommand.h in Headers */,
59EB760C23905F7300F5AE63 /* IJSVGStyleSheetRule.h in Headers */,
59EB75E323905F7300F5AE63 /* IJSVGRadialGradient.h in Headers */,
59EB760523905F7300F5AE63 /* IJSVGUtils.h in Headers */,
59EB763B23905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.h in Headers */,
59EB75E823905F7300F5AE63 /* IJSVGUnitLength.h in Headers */,
59EB762723905F7300F5AE63 /* IJSVGMath.h in Headers */,
59EB761523905F7300F5AE63 /* IJSVGStrokeLayer.h in Headers */,
59EB75DE23905F7300F5AE63 /* IJSVGCommandVerticalLine.h in Headers */,
59EB764123905F7300F5AE63 /* IJSVGImageLayer.h in Headers */,
59EB75E023905F7300F5AE63 /* IJSVGStyleSheet.h in Headers */,
59EB761423905F7300F5AE63 /* IJSVGImageRep.h in Headers */,
59EB761223905F7300F5AE63 /* IJSVGRenderingStyle.h in Headers */,
59EB760E23905F7300F5AE63 /* IJSVGPath.h in Headers */,
59EB75EA23905F7300F5AE63 /* IJSVGTransaction.h in Headers */,
59EB75D723905F7300F5AE63 /* IJSVGGradientLayer.h in Headers */,
59EB75F723905F7300F5AE63 /* IJSVGDef.h in Headers */,
59EB760623905F7300F5AE63 /* IJSVGCommandHorizontalLine.h in Headers */,
59EB762323905F7300F5AE63 /* IJSVGExporterPathInstruction.h in Headers */,
59EB761023905F7300F5AE63 /* IJSVGLinearGradient.h in Headers */,
59EB75E123905F7300F5AE63 /* IJSVGCommandSmoothCurve.h in Headers */,
59EB75D923905F7300F5AE63 /* IJSVGCommandLineTo.h in Headers */,
59EB75D623905F7300F5AE63 /* IJSVGLayer.h in Headers */,
59EB763023905F7300F5AE63 /* IJSVGPatternLayer.h in Headers */,
59EB75F023905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.h in Headers */,
59EB761823905F7300F5AE63 /* IJSVGParser.h in Headers */,
59EB761E23905F7300F5AE63 /* IJSVGGroupLayer.h in Headers */,
59EB761D23905F7300F5AE63 /* IJSVGStyle.h in Headers */,
5919E65723F47FF60051873A /* IJSVGUnitRect.h in Headers */,
5919E65B23F480330051873A /* IJSVGUnitPoint.h in Headers */,
591A3E4D25CC91F800AD45B7 /* IJSVGParsing.h in Headers */,
59A24EBC23F480EA0090C374 /* IJSVGUnitSize.h in Headers */,
59EB764523905F7300F5AE63 /* IJSVGExporter.h in Headers */,
59F36508262F1ABB00BCE3FD /* IJSVGColorType.h in Headers */,
59E7CFAF23B148600077D599 /* IJSVGCommandParser.h in Headers */,
59EB762823905F7300F5AE63 /* IJSVGCommandClose.h in Headers */,
59EB75E423905F7300F5AE63 /* IJSVGGradientUnitLength.h in Headers */,
594A10DA248D7C90001A3181 /* NSImage+IJSVGAdditions.h in Headers */,
59EB762D23905F7300F5AE63 /* IJSVGLayerTree.h in Headers */,
59EB760B23905F7300F5AE63 /* IJSVGStyleSheetSelector.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
594CF46E238FF38E009B251B /* IJSVG */ = {
isa = PBXNativeTarget;
buildConfigurationList = 594CF477238FF38E009B251B /* Build configuration list for PBXNativeTarget "IJSVG" */;
buildPhases = (
594CF46A238FF38E009B251B /* Headers */,
594CF46B238FF38E009B251B /* Sources */,
594CF46C238FF38E009B251B /* Frameworks */,
594CF46D238FF38E009B251B /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = IJSVG;
productName = IJSVG;
productReference = 594CF46F238FF38E009B251B /* IJSVG.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
594CF466238FF38E009B251B /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1220;
ORGANIZATIONNAME = "Curtis Hard";
TargetAttributes = {
594CF46E238FF38E009B251B = {
CreatedOnToolsVersion = 11.0;
};
};
};
buildConfigurationList = 594CF469238FF38E009B251B /* Build configuration list for PBXProject "IJSVG" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 594CF465238FF38E009B251B;
productRefGroup = 594CF470238FF38E009B251B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
594CF46E238FF38E009B251B /* IJSVG */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
594CF46D238FF38E009B251B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
594CF46B238FF38E009B251B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
59EB763123905F7300F5AE63 /* IJSVGText.m in Sources */,
59A24EBD23F480EA0090C374 /* IJSVGUnitSize.m in Sources */,
59EB760223905F7300F5AE63 /* IJSVGCommandVerticalLine.m in Sources */,
59EB75FD23905F7300F5AE63 /* IJSVGPatternLayer.m in Sources */,
59EB763923905F7300F5AE63 /* IJSVGCommandSmoothQuadraticCurve.m in Sources */,
59EB75D823905F7300F5AE63 /* IJSVGStyleSheetRule.m in Sources */,
59EB75FB23905F7300F5AE63 /* IJSVGPath.m in Sources */,
59F36509262F1ABB00BCE3FD /* IJSVGColorType.m in Sources */,
59EB760123905F7300F5AE63 /* IJSVGLayerTree.m in Sources */,
59EB763A23905F7300F5AE63 /* IJSVGForeignObject.m in Sources */,
59EB761123905F7300F5AE63 /* IJSVGCommand.m in Sources */,
59EB760923905F7300F5AE63 /* IJSVGCommandCurve.m in Sources */,
59EB763323905F7300F5AE63 /* IJSVGLinearGradient.m in Sources */,
594A10DB248D7C90001A3181 /* NSImage+IJSVGAdditions.m in Sources */,
59EB761923905F7300F5AE63 /* IJSVGCommandSmoothCurve.m in Sources */,
59EB761323905F7300F5AE63 /* IJSVG.m in Sources */,
59EB763623905F7300F5AE63 /* IJSVGImageLayer.m in Sources */,
59EB75EC23905F7300F5AE63 /* IJSVGLayer.m in Sources */,
59EB75E523905F7300F5AE63 /* IJSVGStrokeLayer.m in Sources */,
59EB763223905F7300F5AE63 /* IJSVGView.m in Sources */,
59EB763523905F7300F5AE63 /* IJSVGStyleSheetSelector.m in Sources */,
59E7CFB023B148600077D599 /* IJSVGCommandParser.m in Sources */,
59EB760723905F7300F5AE63 /* IJSVGNode.m in Sources */,
5919E65C23F480330051873A /* IJSVGUnitPoint.m in Sources */,
59EB75E923905F7300F5AE63 /* IJSVGStringAdditions.m in Sources */,
59EB761723905F7300F5AE63 /* IJSVGRadialGradient.m in Sources */,
59EB75E223905F7300F5AE63 /* IJSVGColorList.m in Sources */,
59EB75ED23905F7300F5AE63 /* IJSVGFontConverter.m in Sources */,
59EB763C23905F7300F5AE63 /* IJSVGCommandEllipticalArc.m in Sources */,
59EB75E723905F7300F5AE63 /* IJSVGImage.m in Sources */,
59EB75E623905F7300F5AE63 /* IJSVGStyle.m in Sources */,
59EB75EB23905F7300F5AE63 /* IJSVGShapeLayer.m in Sources */,
59EB75F623905F7300F5AE63 /* IJSVGColor.m in Sources */,
59EB75F323905F7300F5AE63 /* IJSVGGroupLayer.m in Sources */,
591A3E4E25CC91F800AD45B7 /* IJSVGParsing.m in Sources */,
5919E65823F47FF60051873A /* IJSVGUnitRect.m in Sources */,
59EB762523905F7300F5AE63 /* IJSVGTransform.m in Sources */,
59EB760023905F7300F5AE63 /* IJSVGGradientLayer.m in Sources */,
59EB762B23905F7300F5AE63 /* IJSVGUnitLength.m in Sources */,
59EB75F823905F7300F5AE63 /* IJSVGCommandHorizontalLine.m in Sources */,
59EB764623905F7300F5AE63 /* IJSVGRendering.m in Sources */,
59EB762E23905F7300F5AE63 /* IJSVGExporter.m in Sources */,
59EB761623905F7300F5AE63 /* IJSVGParser.m in Sources */,
59EB75DD23905F7300F5AE63 /* IJSVGCommandQuadraticCurve.m in Sources */,
59EB762423905F7300F5AE63 /* IJSVGTransaction.m in Sources */,
59EB75DA23905F7300F5AE63 /* IJSVGDef.m in Sources */,
59EB763723905F7300F5AE63 /* IJSVGCommandClose.m in Sources */,
59EB764323905F7300F5AE63 /* IJSVGGradient.m in Sources */,
59EB762A23905F7300F5AE63 /* IJSVGGradientUnitLength.m in Sources */,
59EB764223905F7300F5AE63 /* IJSVGStyleSheet.m in Sources */,
59EB764023905F7300F5AE63 /* IJSVGExporterPathInstruction.m in Sources */,
59EB75FE23905F7300F5AE63 /* IJSVGRenderingStyle.m in Sources */,
59EB75F223905F7300F5AE63 /* IJSVGStyleSheetSelectorRaw.m in Sources */,
59EB75EE23905F7300F5AE63 /* IJSVGImageRep.m in Sources */,
59EB762223905F7300F5AE63 /* IJSVGMath.m in Sources */,
59EB763D23905F7300F5AE63 /* IJSVGGroup.m in Sources */,
59EB761F23905F7300F5AE63 /* IJSVGCommandLineTo.m in Sources */,
59EB75F123905F7300F5AE63 /* IJSVGUtils.m in Sources */,
59EB760A23905F7300F5AE63 /* IJSVGCommandMove.m in Sources */,
59EB761B23905F7300F5AE63 /* IJSVGPattern.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
594CF475238FF38E009B251B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREFIX_HEADER = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
594CF476238FF38E009B251B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREFIX_HEADER = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
594CF478238FF38E009B251B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_COMMA = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = 9KTR4W9XX6;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = IJSVG/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.iconjar.ijsvg;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
};
name = Debug;
};
594CF479238FF38E009B251B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_COMMA = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = 9KTR4W9XX6;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = IJSVG/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.iconjar.ijsvg;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
594CF469238FF38E009B251B /* Build configuration list for PBXProject "IJSVG" */ = {
isa = XCConfigurationList;
buildConfigurations = (
594CF475238FF38E009B251B /* Debug */,
594CF476238FF38E009B251B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
594CF477238FF38E009B251B /* Build configuration list for PBXNativeTarget "IJSVG" */ = {
isa = XCConfigurationList;
buildConfigurations = (
594CF478238FF38E009B251B /* Debug */,
594CF479238FF38E009B251B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 594CF466238FF38E009B251B /* Project object */;
}
@@ -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 = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "594CF46E238FF38E009B251B"
BuildableName = "IJSVG.framework"
BlueprintName = "IJSVG"
ReferencedContainer = "container:IJSVG.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "594CF46E238FF38E009B251B"
BuildableName = "IJSVG.framework"
BlueprintName = "IJSVG"
ReferencedContainer = "container:IJSVG.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -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 © 2020 Curtis Hard. All rights reserved.</string>
</dict>
</plist>
@@ -0,0 +1,19 @@
//
// IJSVGStringAdditions.h
// IconJar
//
// Created by Curtis Hard on 07/06/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (IJSVGAdditions)
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(const char*)aChar;
- (BOOL)ijsvg_isNumeric;
- (BOOL)ijsvg_containsAlpha;
- (NSArray*)ijsvg_componentsSplitByWhiteSpace;
- (BOOL)ijsvg_isHexString;
@end
@@ -0,0 +1,71 @@
//
// IJSVGStringAdditions.m
// IconJar
//
// Created by Curtis Hard on 07/06/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGStringAdditions.h"
#import "IJSVGUtils.h"
@implementation NSString (IJSVGAdditions)
- (NSArray<NSString*>*)ijsvg_componentsSeparatedByChars:(const char*)aChar
{
char* chars = (char*)self.UTF8String;
if(chars == NULL || strlen(chars) == 0) {
return @[];
}
NSMutableArray<NSString*>* strings = nil;
strings = [[[NSMutableArray alloc] init] autorelease];
char* copy = strdup(chars);
char* spt = NULL;
char* ptr = strtok_r(copy, aChar, &spt);
while(ptr != NULL) {
NSString* possibleString = nil;
if((possibleString = [NSString stringWithUTF8String:ptr]) != nil) {
[strings addObject:possibleString];
}
ptr = strtok_r(NULL, aChar, &spt);
}
(void)free(copy), copy = NULL;
return strings;
}
- (BOOL)ijsvg_containsAlpha
{
const char* buffer = self.UTF8String;
char currentChar;
while((currentChar = *buffer++) ) {
if (isalpha(currentChar)) {
return YES;
}
}
return NO;
}
- (BOOL)ijsvg_isNumeric
{
const char* buffer = self.UTF8String;
char currentChar;
while((currentChar = *buffer++) ) {
if (!isnumber(currentChar)) {
return NO;
}
}
return YES;
}
- (NSArray*)ijsvg_componentsSplitByWhiteSpace
{
return [self ijsvg_componentsSeparatedByChars:"\t\n\r "];
}
- (BOOL)ijsvg_isHexString
{
const char* chars = self.UTF8String;
return IJSVGCharBufferIsHEX((char*)chars);
}
@end
@@ -0,0 +1,18 @@
//
// NSImage+IJSVGAdditions.h
// IJSVG
//
// Created by Curtis Hard on 07/06/2020.
// Copyright © 2020 Curtis Hard. All rights reserved.
//
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>
IJSVG* IJSVGGetFromNSImage(NSImage* image);
@interface NSImage (IJSVGAdditions)
+ (NSImage*)SVGImageNamed:(NSString*)imageName;
@end
@@ -0,0 +1,53 @@
//
// NSImage+IJSVGAdditions.m
// IJSVG
//
// Created by Curtis Hard on 07/06/2020.
// Copyright © 2020 Curtis Hard. All rights reserved.
//
#import "IJSVGImageRep.h"
#import "NSImage+IJSVGAdditions.h"
IJSVG* IJSVGGetFromNSImage(NSImage* image)
{
for (NSImageRep* rep in image.representations) {
if ([rep isKindOfClass:IJSVGImageRep.class]) {
return ((IJSVGImageRep*)rep).SVG;
}
}
return nil;
}
@implementation NSImage (IJSVGAdditions)
+ (NSImage*)SVGImageNamed:(NSString*)imageName
{
// find the image
NSBundle* bundle = NSBundle.mainBundle;
NSString* str = nil;
NSString* ext = imageName.pathExtension;
if (ext == nil || ext.length == 0) {
ext = @"svg";
}
if ((str = [bundle pathForResource:imageName.stringByDeletingPathExtension
ofType:ext])
!= nil) {
// work out if we can get the data
NSData* data = [[[NSData alloc] initWithContentsOfFile:str] autorelease];
if (data == nil) {
return nil;
}
// grab the image rep
IJSVGImageRep* rep = [[[IJSVGImageRep alloc] initWithData:data] autorelease];
NSImage* image = [[[NSImage alloc] init] autorelease];
[image addRepresentation:rep];
return image;
}
return nil;
}
@end
@@ -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,17 +169,29 @@ typedef NS_ENUM( NSInteger, IJSVGPredefinedColor ) {
@interface IJSVGColor : NSObject
+ (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,812 @@
//
// IJSVGColor.m
// IconJar
//
// Created by Curtis Hard on 31/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGColor.h"
#import "IJSVGUtils.h"
#import "IJSVGStringAdditions.h"
#import "IJSVGParsing.h"
@implementation IJSVGColor
static NSDictionary* _colorTree = nil;
CGFloat* IJSVGColorCSSHSLToHSB(CGFloat hue, CGFloat saturation, CGFloat lightness)
{
hue *= (1.f / 360.f);
hue = (hue - floorf(hue));
saturation *= 0.01;
lightness *= 0.01;
lightness *= 2.f;
CGFloat s = saturation * ((lightness < 1.f) ? lightness : (2.f - lightness));
CGFloat brightness = (lightness + s) * .5f;
if (s != 0.f) {
s = (2.f * s) / (lightness + s);
}
CGFloat* floats = (CGFloat*)malloc(3 * sizeof(CGFloat));
floats[0] = hue;
floats[1] = s;
floats[2] = brightness;
return floats;
};
+ (void)load
{
[self.class _generateTree];
}
+ (NSColorSpace*)defaultColorSpace
{
return NSColorSpace.deviceRGBColorSpace;
}
+ (NSColor*)computeColorSpace:(NSColor*)color
{
NSColorSpace* space = [self defaultColorSpace];
if (color.colorSpace != space) {
color = [color colorUsingColorSpace:space];
}
return color;
}
+ (void)_generateTree
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_colorTree = [@{
@"aliceblue" : @(0xf0f8ff),
@"antiquewhite" : @(0xfaebd7),
@"aqua" : @(0x00ffff),
@"aquamarine" : @(0x7fffd4),
@"azure" : @(0xf0ffff),
@"beige" : @(0xf5f5dc),
@"bisque" : @(0xffe4c4),
@"black" : @(0x000000),
@"blanchedalmond" : @(0xffebcd),
@"blue" : @(0x0000ff),
@"blueviolet" : @(0x8a2be2),
@"brown" : @(0xa52a2a),
@"burlywood" : @(0xdeb887),
@"cadetblue" : @(0x5f9ea0),
@"chartreuse" : @(0x7fff00),
@"chocolate" : @(0xd2691e),
@"coral" : @(0xff7f50),
@"cornflowerblue" : @(0x6495ed),
@"cornsilk" : @(0xfff8dc),
@"crimson" : @(0xdc143c),
@"currentcolor" : @(0x000000),
@"cyan" : @(0x00ffff),
@"darkblue" : @(0x00008b),
@"darkcyan" : @(0x008b8b),
@"darkgoldenrod" : @(0xb8860b),
@"darkgray" : @(0xa9a9a9),
@"darkgreen" : @(0x006400),
@"darkgrey" : @(0xa9a9a9),
@"darkkhaki" : @(0xbdb76b),
@"darkmagenta" : @(0x8b008b),
@"darkolivegreen" : @(0x556b2f),
@"darkorange" : @(0xff8c00),
@"darkorchid" : @(0x9932cc),
@"darkred" : @(0x8b0000),
@"darksalmon" : @(0xe9967a),
@"darkseagreen" : @(0x8fbc8f),
@"darkslateblue" : @(0x483d8b),
@"darkslategray" : @(0x2f4f4f),
@"darkturquoise" : @(0x00ced1),
@"darkviolet" : @(0x9400d3),
@"deeppink" : @(0xff1493),
@"deepskyblue" : @(0x00bfff),
@"dimgray" : @(0x696969),
@"dimgrey" : @(0x696969),
@"dodgerblue" : @(0x1e90ff),
@"firebrick" : @(0xb22222),
@"floralwhite" : @(0xfffaf0),
@"forestgreen" : @(0x228b22),
@"fuchsia" : @(0xff00ff),
@"gainsboro" : @(0xdcdcdc),
@"ghostwhite" : @(0xf8f8ff),
@"gold" : @(0xffd700),
@"goldenrod" : @(0xdaa520),
@"gray" : @(0x808080),
@"green" : @(0x008000),
@"greenyellow" : @(0xadff2f),
@"grey" : @(0x808080),
@"honeydew" : @(0xf0fff0),
@"hotpink" : @(0xff69b4),
@"indianred" : @(0xcd5c5c),
@"indigo" : @(0x4b0082),
@"ivory" : @(0xfffff0),
@"khaki" : @(0xf0e68c),
@"lavender" : @(0xe6e6fa),
@"lavenderblush" : @(0xfff0f5),
@"lawngreen" : @(0x7cfc00),
@"lemonchiffon" : @(0xfffacd),
@"lightblue" : @(0xadd8e6),
@"lightcoral" : @(0xf08080),
@"lightcyan" : @(0xe0ffff),
@"lightgoldenrodyellow" : @(0xfafad2),
@"lightgray" : @(0xd3d3d3),
@"lightgreen" : @(0x90ee90),
@"lightgrey" : @(0xd3d3d3),
@"lightpink" : @(0xffb6c1),
@"lightsalmon" : @(0xffa07a),
@"lightseagreen" : @(0x20b2aa),
@"lightskyblue" : @(0x87cefa),
@"lightslategray" : @(0x778899),
@"lightsteelblue" : @(0xb0c4de),
@"lightyellow" : @(0xffffe0),
@"lime" : @(0x00ff00),
@"limegreen" : @(0x32cd32),
@"linen" : @(0xfaf0e6),
@"magenta" : @(0xff00ff),
@"maroon" : @(0x800000),
@"mediumaquamarine" : @(0x66cdaa),
@"mediumblue" : @(0x0000cd),
@"mediumorchid" : @(0xba55d3),
@"mediumpurple" : @(0x9370db),
@"mediumseagreen" : @(0x3cb371),
@"mediumslateblue" : @(0x7b68ee),
@"mediumspringgreen" : @(0x00fa9a),
@"mediumturquoise" : @(0x48d1cc),
@"mediumvioletred" : @(0xc71585),
@"midnightblue" : @(0x191970),
@"mintcream" : @(0xf5fffa),
@"mistyrose" : @(0xffe4e1),
@"moccasin" : @(0xffe4b5),
@"navajowhite" : @(0xffdead),
@"navy" : @(0x000080),
@"oldlace" : @(0xfdf5e6),
@"olive" : @(0x808000),
@"olivedrab" : @(0x6b8e23),
@"orange" : @(0xffa500),
@"orangered" : @(0xff4500),
@"orchid" : @(0xda70d6),
@"palegoldenrod" : @(0xeee8aa),
@"palegreen" : @(0x98fb98),
@"paleturquoise" : @(0xafeeee),
@"palevioletred" : @(0xdb7093),
@"papayawhip" : @(0xffefd5),
@"peachpuff" : @(0xffdab9),
@"peru" : @(0xcd853f),
@"pink" : @(0xffc0cb),
@"plum" : @(0xdda0dd),
@"powderblue" : @(0xb0e0e6),
@"purple" : @(0x800080),
@"red" : @(0xff0000),
@"rosybrown" : @(0xbc8f8f),
@"royalblue" : @(0x4169e1),
@"saddlebrown" : @(0x8b4513),
@"salmon" : @(0xfa8072),
@"sandybrown" : @(0xf4a460),
@"seagreen" : @(0x2e8b57),
@"seashell" : @(0xfff5ee),
@"sienna" : @(0xa0522d),
@"silver" : @(0xc0c0c0),
@"skyblue" : @(0x87ceeb),
@"slateblue" : @(0x6a5acd),
@"slategrey" : @(0x708090),
@"snow" : @(0xfffafa),
@"springgreen" : @(0x00ff7f),
@"steelblue" : @(0x4682b4),
@"tan" : @(0xd2b48c),
@"teal" : @(0x008080),
@"thistle" : @(0xd8bfd8),
@"tomato" : @(0xff6347),
@"turquoise" : @(0x40e0d0),
@"violet" : @(0xee82ee),
@"wheat" : @(0xf5deb3),
@"white" : @(0xffffff),
@"whitesmoke" : @(0xf5f5f5),
@"yellow" : @(0xffff00),
@"yellowgreen" : @(0x9acd32)
} retain];
});
}
+ (NSColor*)computeColor:(id)colour
{
if ([colour isKindOfClass:[NSColor class]])
return colour;
return nil;
}
+ (NSColor*)colorFromRString:(NSString*)rString
gString:(NSString*)gString
bString:(NSString*)bString
aString:(NSString*)aString
{
return [self colorFromRUnit:[IJSVGUnitLength unitWithString:rString]
gUnit:[IJSVGUnitLength unitWithString:gString]
bUnit:[IJSVGUnitLength unitWithString:bString]
aUnit:[IJSVGUnitLength unitWithString:aString]];
}
+ (NSColor*)colorFromRUnit:(IJSVGUnitLength*)rUnit
gUnit:(IJSVGUnitLength*)gUnit
bUnit:(IJSVGUnitLength*)bUnit
aUnit:(IJSVGUnitLength*)aUnit
{
CGFloat r = rUnit.type == IJSVGUnitLengthTypePercentage ? [rUnit computeValue:255.f] : [rUnit computeValue:1.f];
CGFloat g = gUnit.type == IJSVGUnitLengthTypePercentage ? [gUnit computeValue:255.f] : [gUnit computeValue:1.f];
CGFloat b = bUnit.type == IJSVGUnitLengthTypePercentage ? [bUnit computeValue:255.f] : [bUnit computeValue:1.f];
CGFloat a = [aUnit computeValue:100.f];
return [self computeColorSpace:[NSColor colorWithDeviceRed:(r / 255.f)
green:(g / 255.f)
blue:(b / 255.f)
alpha:a]];
}
+ (NSColor*)colorFromString:(NSString*)string
{
// swap over to C for performance
if(string == nil) {
return nil;
}
char* str = (char*)string.UTF8String;
if(strlen(str) == 0) {
return nil;
}
IJSVGTrimCharBuffer(str);
if (IJSVGCharBufferIsHEX(str) == YES) {
return [self.class colorFromHEXString:string];
}
// is it RGB?
if (IJSVGCharBufferHasPrefix(str, "rgb") == YES) {
NSUInteger count = 0;
IJSVGParsingStringMethod** methods = NULL;
methods = IJSVGParsingMethodParseString(str, &count);
IJSVGParsingStringMethod* method = methods[0];
// nothing to return, just mem clean and get out of here
if(count == 0 || methods == NULL) {
if(methods != NULL) {
IJSVGParsingStringMethodsRelease(methods, count);
methods = NULL;
}
return nil;
}
// parse the parameters
NSString* parameters = [NSString stringWithUTF8String:method->parameters];
NSArray* parts = [parameters ijsvg_componentsSeparatedByChars:","];
NSString* alpha = @"100%";
if (parts.count == 4) {
alpha = parts[3];
}
IJSVGParsingStringMethodsRelease(methods, count);
methods = NULL;
return [self colorFromRString:parts[0]
gString:parts[1]
bString:parts[2]
aString:alpha];
}
// is it HSL?
if (IJSVGCharBufferHasPrefix(str, "hsl")) {
NSInteger count = 0;
CGFloat* params = [IJSVGUtils scanFloatsFromCString:str
size:&count];
CGFloat alpha = 1;
if (count == 4) {
alpha = params[3];
}
// convert HSL to HSB
CGFloat* hsb = IJSVGColorCSSHSLToHSB(params[0], params[1], params[2]);
NSColor* color = [NSColor colorWithDeviceHue:hsb[0]
saturation:hsb[1]
brightness:hsb[2]
alpha:alpha];
color = [self computeColorSpace:color];
// memory clean!
(void)free(hsb), hsb = NULL;
(void)free(params), params = NULL;
return color;
}
// is simply a clear color, dont fill
if (strcmp(str, "none") == 0 ||
strcmp(str, "transparent") == 0) {
return [self computeColorSpace:NSColor.clearColor];
}
// could return nil
return [self.class colorFromPredefinedColorName:string];
}
+ (NSColor*)colorFromPredefinedColorName:(NSString*)name
{
NSNumber* hex = nil;
name = [name.lowercaseString stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
if ((hex = _colorTree[name]) == nil) {
return nil;
}
return [self.class colorFromHEXInteger:hex.integerValue];
}
+ (NSString*)colorStringFromColor:(NSColor*)color
{
IJSVGColorStringOptions options = IJSVGColorStringOptionDefault;
return [self colorStringFromColor:color
options:options];
}
+ (NSString*)colorStringFromColor:(NSColor*)color
options:(IJSVGColorStringOptions)options
{
// convert to RGB
color = [self computeColorSpace:color];
int red = color.redComponent * 0xFF;
int green = color.greenComponent * 0xFF;
int blue = color.blueComponent * 0xFF;
int alpha = (int)(color.alphaComponent * 100);
BOOL forceHex = (options & IJSVGColorStringOptionForceHEX) != 0;
BOOL allowShortHand = (options & IJSVGColorStringOptionAllowShortHand) != 0;
BOOL allowRRGGBBAA = (options & IJSVGColorStringOptionAllowRRGGBBAA) != 0;
// jsut return none
if (alpha == 0 && forceHex == NO) {
return @"none";
}
// always return hex unless criteria is met
if (forceHex == YES || allowRRGGBBAA == YES || alpha == 100 || (red == 0 && green == 0 && blue == 0 && alpha == 0) || (red == 255 && green == 255 && blue == 255 && alpha == 100)) {
// we need to make sure the last 2 chars
// are the same or we cant enable shorthand
if (allowRRGGBBAA == YES) {
NSString* alphaHexString = [NSString stringWithFormat:@"%02X",
(int)(color.alphaComponent * 0xFF)];
if ([alphaHexString characterAtIndex:0] !=
[alphaHexString characterAtIndex:1]) {
allowShortHand = NO;
}
}
if (allowShortHand == YES) {
NSString* r = [NSString stringWithFormat:@"%02X", red];
NSString* g = [NSString stringWithFormat:@"%02X", green];
NSString* b = [NSString stringWithFormat:@"%02X", blue];
if ([r characterAtIndex:0] == [r characterAtIndex:1] &&
[g characterAtIndex:0] == [g characterAtIndex:1] &&
[b characterAtIndex:0] == [b characterAtIndex:1]) {
// allow shorthand alpha
if (allowRRGGBBAA == YES && alpha != 100) {
NSString* a = [NSString stringWithFormat:@"%02X",
(int)(color.alphaComponent * 0xFF)];
return [NSString stringWithFormat:@"#%c%c%c%c",
[r characterAtIndex:0], [g characterAtIndex:0],
[b characterAtIndex:0], [a characterAtIndex:0]];
}
return [NSString stringWithFormat:@"#%c%c%c", [r characterAtIndex:0],
[g characterAtIndex:0], [b characterAtIndex:0]];
}
}
if (allowRRGGBBAA == YES && alpha != 100) {
return [NSString stringWithFormat:@"#%02X%02X%02X%02X", red, green,
blue, (int)(color.alphaComponent * 0xFF)];
}
return [NSString stringWithFormat:@"#%02X%02X%02X", red, green, blue];
}
// note the %g, CSS alpha is 0 to 1, not 0 - 100, my bad!
return [NSString stringWithFormat:@"rgba(%d,%d,%d,%@)", red, green, blue,
IJSVGShortFloatString((float)alpha / 100.f)];
}
+ (NSString*)colorNameFromPredefinedColor:(IJSVGPredefinedColor)color
{
switch (color) {
case IJSVGColorAliceblue:
return @"aliceblue";
case IJSVGColorAntiquewhite:
return @"antiquewhite";
case IJSVGColorAqua:
return @"aqua";
case IJSVGColorAquamarine:
return @"aquamarine";
case IJSVGColorAzure:
return @"azure";
case IJSVGColorBeige:
return @"beige";
case IJSVGColorBisque:
return @"bisque";
case IJSVGColorBlack:
return @"black";
case IJSVGColorBlanchedalmond:
return @"blanchedalmond";
case IJSVGColorBlue:
return @"blue";
case IJSVGColorBlueviolet:
return @"blueviolet";
case IJSVGColorBrown:
return @"brown";
case IJSVGColorBurlywood:
return @"burlywood";
case IJSVGColorCadetblue:
return @"cadetblue";
case IJSVGColorChartreuse:
return @"chartreuse";
case IJSVGColorChocolate:
return @"chocolate";
case IJSVGColorCoral:
return @"coral";
case IJSVGColorCornflowerblue:
return @"cornflowerblue";
case IJSVGColorCornsilk:
return @"cornsilk";
case IJSVGColorCrimson:
return @"crimson";
case IJSVGColorCyan:
return @"cyan";
case IJSVGColorDarkblue:
return @"darkblue";
case IJSVGColorDarkcyan:
return @"darkcyan";
case IJSVGColorDarkgoldenrod:
return @"darkgoldenrod";
case IJSVGColorDarkgray:
return @"darkgray";
case IJSVGColorDarkgreen:
return @"darkgreen";
case IJSVGColorDarkgrey:
return @"darkgrey";
case IJSVGColorDarkkhaki:
return @"darkkhaki";
case IJSVGColorDarkmagenta:
return @"darkmagenta";
case IJSVGColorDarkolivegreen:
return @"darkolivegreen";
case IJSVGColorDarkorange:
return @"darkorange";
case IJSVGColorDarkorchid:
return @"darkorchid";
case IJSVGColorDarkred:
return @"darkred";
case IJSVGColorDarksalmon:
return @"darksalmon";
case IJSVGColorDarkseagreen:
return @"darkseagreen";
case IJSVGColorDarkslateblue:
return @"darkslateblue";
case IJSVGColorDarkslategray:
return @"darkslategray";
case IJSVGColorDarkslategrey:
return @"darkslategrey";
case IJSVGColorDarkturquoise:
return @"darkturquoise";
case IJSVGColorDarkviolet:
return @"darkviolet";
case IJSVGColorDeeppink:
return @"deeppink";
case IJSVGColorDeepskyblue:
return @"deepskyblue";
case IJSVGColorDimgray:
return @"dimgray";
case IJSVGColorDimgrey:
return @"dimgrey";
case IJSVGColorDodgerblue:
return @"dodgerblue";
case IJSVGColorFirebrick:
return @"firebrick";
case IJSVGColorFloralwhite:
return @"floralwhite";
case IJSVGColorForestgreen:
return @"forestgreen";
case IJSVGColorFuchsia:
return @"fuchsia";
case IJSVGColorGainsboro:
return @"gainsboro";
case IJSVGColorGhostwhite:
return @"ghostwhite";
case IJSVGColorGold:
return @"gold";
case IJSVGColorGoldenrod:
return @"goldenrod";
case IJSVGColorGray:
return @"gray";
case IJSVGColorGreen:
return @"green";
case IJSVGColorGreenyellow:
return @"greenyellow";
case IJSVGColorGrey:
return @"grey";
case IJSVGColorHoneydew:
return @"honeydew";
case IJSVGColorHotpink:
return @"hotpink";
case IJSVGColorIndianred:
return @"indianred";
case IJSVGColorIndigo:
return @"indigo";
case IJSVGColorIvory:
return @"ivory";
case IJSVGColorKhaki:
return @"khaki";
case IJSVGColorLavender:
return @"lavender";
case IJSVGColorLavenderblush:
return @"lavenderblush";
case IJSVGColorLawngreen:
return @"lawngreen";
case IJSVGColorLemonchiffon:
return @"lemonchiffon";
case IJSVGColorLightblue:
return @"lightblue";
case IJSVGColorLightcoral:
return @"lightcoral";
case IJSVGColorLightcyan:
return @"lightcyan";
case IJSVGColorLightgoldenrodyellow:
return @"lightgoldenrodyellow";
case IJSVGColorLightgray:
return @"lightgray";
case IJSVGColorLightgreen:
return @"lightgreen";
case IJSVGColorLightgrey:
return @"lightgrey";
case IJSVGColorLightpink:
return @"lightpink";
case IJSVGColorLightsalmon:
return @"lightsalmon";
case IJSVGColorLightseagreen:
return @"lightseagreen";
case IJSVGColorLightskyblue:
return @"lightskyblue";
case IJSVGColorLightslategray:
return @"lightslategray";
case IJSVGColorLightslategrey:
return @"lightslategrey";
case IJSVGColorLightsteelblue:
return @"lightsteelblue";
case IJSVGColorLightyellow:
return @"lightyellow";
case IJSVGColorLime:
return @"lime";
case IJSVGColorLimegreen:
return @"limegreen";
case IJSVGColorLinen:
return @"linen";
case IJSVGColorMagenta:
return @"magenta";
case IJSVGColorMaroon:
return @"maroon";
case IJSVGColorMediumaquamarine:
return @"mediumaquamarine";
case IJSVGColorMediumblue:
return @"mediumblue";
case IJSVGColorMediumorchid:
return @"mediumorchid";
case IJSVGColorMediumpurple:
return @"mediumpurple";
case IJSVGColorMediumseagreen:
return @"mediumseagreen";
case IJSVGColorMediumslateblue:
return @"mediumslateblue";
case IJSVGColorMediumspringgreen:
return @"mediumspringgreen";
case IJSVGColorMediumturquoise:
return @"mediumturquoise";
case IJSVGColorMediumvioletred:
return @"mediumvioletred";
case IJSVGColorMidnightblue:
return @"midnightblue";
case IJSVGColorMintcream:
return @"mintcream";
case IJSVGColorMistyrose:
return @"mistyrose";
case IJSVGColorMoccasin:
return @"moccasin";
case IJSVGColorNavajowhite:
return @"navajowhite";
case IJSVGColorNavy:
return @"navy";
case IJSVGColorOldlace:
return @"oldlace";
case IJSVGColorOlive:
return @"olive";
case IJSVGColorOlivedrab:
return @"olivedrab";
case IJSVGColorOrange:
return @"orange";
case IJSVGColorOrangered:
return @"orangered";
case IJSVGColorOrchid:
return @"orchid";
case IJSVGColorPalegoldenrod:
return @"palegoldenrod";
case IJSVGColorPalegreen:
return @"palegreen";
case IJSVGColorPaleturquoise:
return @"paleturquoise";
case IJSVGColorPalevioletred:
return @"palevioletred";
case IJSVGColorPapayawhip:
return @"papayawhip";
case IJSVGColorPeachpuff:
return @"peachpuff";
case IJSVGColorPeru:
return @"peru";
case IJSVGColorPink:
return @"pink";
case IJSVGColorPlum:
return @"plum";
case IJSVGColorPowderblue:
return @"powderblue";
case IJSVGColorPurple:
return @"purple";
case IJSVGColorRed:
return @"red";
case IJSVGColorRosybrown:
return @"rosybrown";
case IJSVGColorRoyalblue:
return @"royalblue";
case IJSVGColorSaddlebrown:
return @"saddlebrown";
case IJSVGColorSalmon:
return @"salmon";
case IJSVGColorSandybrown:
return @"sandybrown";
case IJSVGColorSeagreen:
return @"seagreen";
case IJSVGColorSeashell:
return @"seashell";
case IJSVGColorSienna:
return @"sienna";
case IJSVGColorSilver:
return @"silver";
case IJSVGColorSkyblue:
return @"skyblue";
case IJSVGColorSlateblue:
return @"slateblue";
case IJSVGColorSlategray:
return @"slategray";
case IJSVGColorSlategrey:
return @"slategrey";
case IJSVGColorSnow:
return @"snow";
case IJSVGColorSpringgreen:
return @"springgreen";
case IJSVGColorSteelblue:
return @"steelblue";
case IJSVGColorTan:
return @"tan";
case IJSVGColorTeal:
return @"teal";
case IJSVGColorThistle:
return @"thistle";
case IJSVGColorTomato:
return @"tomato";
case IJSVGColorTurquoise:
return @"turquoise";
case IJSVGColorViolet:
return @"violet";
case IJSVGColorWheat:
return @"wheat";
case IJSVGColorWhite:
return @"white";
case IJSVGColorWhitesmoke:
return @"whitesmoke";
case IJSVGColorYellow:
return @"yellow";
case IJSVGColorYellowgreen:
return @"yellowgreen";
}
return nil;
}
+ (NSColor*)changeAlphaOnColor:(NSColor*)color
to:(CGFloat)alphaValue
{
color = [self computeColorSpace:color];
return [self computeColorSpace:[NSColor colorWithDeviceRed:color.redComponent
green:color.greenComponent
blue:color.blueComponent
alpha:alphaValue]];
}
+ (BOOL)isColor:(NSString*)string
{
return [string hasPrefix:@"#"] || [string hasPrefix:@"rgb"];
}
+ (BOOL)isHex:(NSString*)string
{
return string.ijsvg_isHexString;
}
+ (unsigned long)lengthOfHEXInteger:(NSUInteger)hex
{
char* buffer;
asprintf(&buffer, "%lX", (long)hex);
unsigned long length = strlen(buffer);
free(buffer);
return length;
}
+ (BOOL)HEXContainsAlphaComponent:(NSUInteger)hex
{
return [self lengthOfHEXInteger:hex] == 8;
}
+ (NSColor*)colorFromHEXInteger:(NSInteger)hex
{
CGFloat alpha = 1.f;
if ([self HEXContainsAlphaComponent:hex] == YES) {
alpha = (hex & 0xFF) / 255.f;
hex = hex >> 8;
}
return [self computeColorSpace:[NSColor colorWithDeviceRed:((hex >> 16) & 0xFF) / 255.f
green:((hex >> 8) & 0xFF) / 255.f
blue:(hex & 0xFF) / 255.f
alpha:alpha]];
}
+ (unsigned long)HEXFromArbitraryHexString:(NSString*)aString
{
const char* hexString = [aString cStringUsingEncoding:NSUTF8StringEncoding];
return strtoul(hexString, NULL, 16);
}
+ (NSColor*)colorFromHEXString:(NSString*)string
{
return [self colorFromHEXString:string
containsAlphaComponent:nil];
}
+ (NSColor*)colorFromHEXString:(NSString*)string
containsAlphaComponent:(BOOL*)containsAlphaComponent
{
// absolutely no string
if(string == nil) {
return nil;
}
char* str = (char*)string.UTF8String;
size_t length = strlen(str);
if (length == 0 || IJSVGCharBufferIsHEX(str) == NO) {
return nil;
}
// remove the hash from the front of the string
if(str[0] == '#') {
length--;
str++;
}
unsigned long hex;
// we need to work out if its shorthand
// if it is, the length needs to be length*2
if (length == 3 || length == 4) {
char* chars = NULL;
chars = (char*)calloc(sizeof(char),length*2+1);
for(int i = 0; i < length; i++) {
chars[i*2] = chars[i*2+1] = str[i];
}
hex = strtoul(chars, NULL, 16);
(void)free(chars), chars = NULL;
} else {
hex = strtoul(str, NULL, 16);
}
// now convert rest to hex
if (containsAlphaComponent != nil) {
*containsAlphaComponent = [self HEXContainsAlphaComponent:hex];
}
return [self colorFromHEXInteger:hex];
}
@end
@@ -0,0 +1,35 @@
//
// IJSVGColorList.h
// IconJar
//
// Created by Curtis Hard on 07/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColor.h>
#import <IJSVG/IJSVGColorType.h>
#import <Foundation/Foundation.h>
@interface IJSVGColorList : NSObject <NSCopying> {
@private
NSMutableDictionary<NSColor*, NSColor*>* _replacementColorTree;
NSMutableSet<IJSVGColorType*>* _colors;
}
@property (nonatomic, assign, readonly) NSUInteger count;
- (NSColor*)proposedColorForColor:(NSColor*)color;
- (void)removeAllReplacementColors;
- (void)removeReplacementColor:(NSColor*)color;
- (void)setReplacementColor:(NSColor*)newColor
forColor:(NSColor*)color;
- (void)setReplacementColors:(NSDictionary<NSColor*, NSColor*>*)colors
clearExistingColors:(BOOL)clearExistingColors;
- (void)addColorsFromList:(IJSVGColorList*)sheet;
- (NSSet<IJSVGColorType*>*)colors;
- (void)addColor:(IJSVGColorType*)color;
- (NSDictionary<NSColor*, NSColor*>*)replacementColors;
@end
@@ -0,0 +1,136 @@
//
// IJSVGColorList.m
// IconJar
//
// Created by Curtis Hard on 07/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGColorList.h"
@implementation IJSVGColorList
- (void)dealloc
{
(void)([_replacementColorTree release]), _replacementColorTree = nil;
(void)([_colors release]), _colors = nil;
[super dealloc];
}
- (instancetype)init
{
if ((self = [super init]) != nil) {
_replacementColorTree = [[NSMutableDictionary alloc] init];
_colors = [[NSMutableSet alloc] init];
}
return self;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGColorList* sheet = [[self.class alloc] init];
[sheet setReplacementColors:[_replacementColorTree.copy autorelease]
clearExistingColors:YES];
return sheet;
}
- (NSColor*)proposedColorForColor:(NSColor*)color
{
// nothing found, just return color
if (_replacementColorTree == nil || _replacementColorTree.count == 0) {
return color;
}
// check the mappings
NSColor* found = nil;
color = [IJSVGColor computeColorSpace:color];
if ((found = _replacementColorTree[color]) != nil) {
return found;
}
return color;
}
- (void)_invalidateColorTree
{
(void)([_replacementColorTree release]), _replacementColorTree = nil;
_replacementColorTree = [[NSMutableDictionary alloc] init];
}
- (void)removeAllReplacementColors
{
[self _invalidateColorTree];
}
- (void)removeReplacementColor:(NSColor*)color
{
if (_replacementColorTree == nil) {
return;
}
[_replacementColorTree removeObjectForKey:[IJSVGColor computeColorSpace:color]];
}
- (void)setReplacementColor:(NSColor*)newColor
forColor:(NSColor*)color
{
color = [IJSVGColor computeColorSpace:color];
newColor = [IJSVGColor computeColorSpace:newColor];
_replacementColorTree[color] = newColor;
}
- (void)setReplacementColors:(NSDictionary<NSColor*, NSColor*>*)colors
clearExistingColors:(BOOL)clearExistingColors
{
if (clearExistingColors == YES) {
[self _invalidateColorTree];
}
for (NSColor* oldColor in colors) {
[self setReplacementColor:colors[oldColor]
forColor:oldColor];
}
}
- (NSSet<IJSVGColorType*>*)colors
{
return [NSSet setWithSet:_colors];
}
- (void)addColorsFromList:(IJSVGColorList*)sheet
{
for(IJSVGColorType* color in sheet.colors) {
[self addColor:color];
}
}
- (void)addColor:(IJSVGColorType*)color
{
// we just need to update its bit mask
if([_colors containsObject:color] == YES) {
void (^handler)(IJSVGColorType * _Nonnull obj, BOOL * _Nonnull stop) =
^(IJSVGColorType * _Nonnull obj, BOOL * _Nonnull stop) {
if([obj isEqual:color] == YES) {
obj.flags |= color.flags;
*stop = YES;
}
};
[_colors enumerateObjectsUsingBlock:handler];
return;
}
[_colors addObject:color];
}
- (NSDictionary<NSColor*,NSColor*>*)replacementColors
{
return _replacementColorTree;
}
- (void)removeColor:(IJSVGColorType*)color
{
[_colors removeObject:color];
}
- (NSUInteger)count
{
return _colors.count;
}
@end
@@ -0,0 +1,30 @@
//
// IJSVGColorType.h
// IJSVG
//
// Created by Curtis Hard on 20/04/2021.
// Copyright © 2021 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
typedef NS_OPTIONS(NSInteger, IJSVGColorTypeFlags) {
IJSVGColorTypeNone = 0,
IJSVGColorTypeFlagUnknown = 1 << 0,
IJSVGColorTypeFlagFill = 1 << 1,
IJSVGColorTypeFlagStroke = 1 << 2,
IJSVGColorTypeFlagStop = 1 << 3
};
@interface IJSVGColorType : NSObject {
}
@property (nonatomic, retain) NSColor* color;
@property (nonatomic, assign) IJSVGColorTypeFlags flags;
+ (IJSVGColorType*)typeWithColor:(NSColor*)color
flags:(IJSVGColorTypeFlags)mask;
@end
@@ -0,0 +1,41 @@
//
// IJSVGColorType.m
// IJSVG
//
// Created by Curtis Hard on 20/04/2021.
// Copyright © 2021 Curtis Hard. All rights reserved.
//
#import "IJSVGColorType.h"
@implementation IJSVGColorType
- (void)dealloc
{
(void)[_color release], _color = nil;
[super dealloc];
}
+ (IJSVGColorType*)typeWithColor:(NSColor*)color
flags:(IJSVGColorTypeFlags)mask
{
IJSVGColorType* type = [[[self alloc] init] autorelease];
type.color = color;
type.flags = mask;
return type;
}
- (BOOL)isEqual:(id)object
{
if([object isKindOfClass:IJSVGColorType.class] == NO) {
return NO;
}
return [self.color isEqual:((IJSVGColorType*)object).color];
}
- (NSUInteger)hash
{
return self.color.hash;
}
@end
@@ -0,0 +1,61 @@
//
// IJSVGCommand.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGCommandParser.h>
#import <IJSVG/IJSVGPath.h>
#import <Foundation/Foundation.h>
static const NSInteger IJSVGCustomVariableParameterCount = NSNotFound;
typedef NS_ENUM(NSInteger, IJSVGCommandType) {
kIJSVGCommandTypeAbsolute,
kIJSVGCommandTypeRelative
};
@interface IJSVGCommand : NSObject {
@private
NSInteger _currentIndex;
}
@property (nonatomic, copy) NSString* commandString;
@property (nonatomic, assign) char command;
@property (nonatomic, assign) CGFloat* parameters;
@property (nonatomic, assign) NSInteger parameterCount;
@property (nonatomic, assign) IJSVGCommandType type;
@property (nonatomic, retain) NSArray<IJSVGCommand*>* subCommands;
@property (nonatomic, assign) IJSVGCommand* previousCommand;
@property (nonatomic, assign) BOOL isSubCommand;
+ (Class)commandClassForCommandChar:(char)aChar;
+ (NSInteger)requiredParameterCount;
+ (NSPoint)readCoordinatePair:(CGFloat*)pairs
index:(NSInteger)index;
+ (IJSVGPathDataSequence*)pathDataSequence;
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path;
+ (void)parseParams:(CGFloat*)params
paramCount:(NSInteger)paramCount
intoArray:(NSMutableArray<IJSVGCommand*>*)commands
parentCommand:(IJSVGCommand*)parentCommand;
- (id)initWithCommandStringBuffer:(const char*)str
dataStream:(IJSVGPathDataStream*)dataStream;
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
paramCount:(NSInteger)paramCount
previousCommand:(IJSVGCommand*)command;
- (CGFloat)readFloat;
- (NSPoint)readPoint;
- (BOOL)readBOOL;
- (void)resetRead;
@end
@@ -0,0 +1,217 @@
//
// IJSVGCommand.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommand.h"
#import "IJSVGUtils.h"
#import "IJSVGCommandClose.h"
#import "IJSVGCommandCurve.h"
#import "IJSVGCommandEllipticalArc.h"
#import "IJSVGCommandHorizontalLine.h"
#import "IJSVGCommandLineTo.h"
#import "IJSVGCommandMove.h"
#import "IJSVGCommandQuadraticCurve.h"
#import "IJSVGCommandSmoothCurve.h"
#import "IJSVGCommandSmoothQuadraticCurve.h"
#import "IJSVGCommandVerticalLine.h"
@implementation IJSVGCommand
+ (BOOL)requiresCustomParameterParsing
{
return NO;
}
+ (NSInteger)requiredParameterCount
{
return 1;
}
+ (IJSVGPathDataSequence*)pathDataSequence
{
return NULL;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
}
+ (void)parseParams:(CGFloat*)params
paramCount:(NSInteger)paramCount
intoArray:(NSMutableArray<IJSVGCommand*>*)commands
parentCommand:(IJSVGCommand*)parentCommand
{
}
+ (NSPoint)readCoordinatePair:(CGFloat*)pairs
index:(NSInteger)index
{
return NSMakePoint(pairs[index * 2], pairs[index * 2 + 1]);
}
+ (void)load
{
// register here...
}
+ (Class)commandClassForCommandChar:(char)aChar
{
aChar = tolower(aChar);
switch (aChar) {
case 'a':
return IJSVGCommandEllipticalArc.class;
case 'c':
return IJSVGCommandCurve.class;
case 'h':
return IJSVGCommandHorizontalLine.class;
case 'l':
return IJSVGCommandLineTo.class;
case 'm':
return IJSVGCommandMove.class;
case 'q':
return IJSVGCommandQuadraticCurve.class;
case 's':
return IJSVGCommandSmoothCurve.class;
case 't':
return IJSVGCommandSmoothQuadraticCurve.class;
case 'v':
return IJSVGCommandVerticalLine.class;
case 'z':
return IJSVGCommandClose.class;
}
return nil;
}
- (void)dealloc
{
(void)([_commandString release]), _commandString = nil;
(void)([_subCommands release]), _subCommands = nil;
if (_parameters) {
(void)(free(_parameters)), _parameters = nil;
}
[super dealloc];
}
- (id)initWithCommandStringBuffer:(const char*)str
dataStream:(IJSVGPathDataStream*)dataStream
{
if ((self = [super init]) != nil) {
// work out the basics
_currentIndex = 0;
_command = str[0];
_type = [IJSVGUtils typeForCommandChar:_command];
NSInteger sets = 0;
NSInteger paramCount = [self.class requiredParameterCount];
IJSVGPathDataSequence* sequence = [self.class pathDataSequence];
_parameters = IJSVGParsePathDataStreamSequence(str, strlen(str),
dataStream, sequence, [self.class requiredParameterCount], &sets);
if (sets <= 1) {
CGFloat* subParams = [self parametersFromIndexOffset:0];
IJSVGCommand* command = [self subcommandWithParameters:subParams
paramCount:paramCount
previousCommand:nil];
_subCommands = @[ command ].retain;
} else {
NSMutableArray<IJSVGCommand*>* subCommandArray = nil;
subCommandArray = [[NSMutableArray alloc] initWithCapacity:sets].autorelease;
// interate over the sets
IJSVGCommand* lastCommand = nil;
for (NSInteger i = 0; i < sets; i++) {
// memory for this will be handled by the created subcommand
CGFloat* subParams = [self parametersFromIndexOffset:i];
// generate the subcommand
IJSVGCommand* command = [self subcommandWithParameters:subParams
paramCount:paramCount
previousCommand:lastCommand];
// make sure we assign the last command or hell breaks
// lose and the firey demons will run wild, namely, commands will break
// if they are multiples of a set
lastCommand = command;
[subCommandArray addObject:command];
}
// store the retained value
_subCommands = subCommandArray.copy;
}
}
return self;
}
- (CGFloat*)parametersFromIndexOffset:(NSInteger)index
{
CGFloat* subParams = 0;
NSInteger req = [self.class requiredParameterCount];
if (req != 0) {
subParams = (CGFloat*)malloc(req * sizeof(CGFloat));
memcpy(subParams, &self.parameters[index * req], sizeof(CGFloat) * req);
}
return subParams;
}
- (IJSVGCommand*)subcommandWithParameters:(CGFloat*)subParams
paramCount:(NSInteger)paramCount
previousCommand:(IJSVGCommand*)aPreviousCommand
{
// create a subcommand per set
IJSVGCommand* c = [[[self.class alloc] init] autorelease];
c.parameterCount = paramCount;
c.parameters = subParams;
c.type = self.type;
c.command = self.command;
c.previousCommand = aPreviousCommand;
c.isSubCommand = aPreviousCommand != nil;
return c;
}
- (CGFloat)readFloat
{
CGFloat f = _parameters[_currentIndex];
_currentIndex++;
return f;
}
- (NSPoint)readPoint
{
CGFloat x = _parameters[_currentIndex];
CGFloat y = _parameters[_currentIndex + 1];
_currentIndex += 2;
return NSMakePoint(x, y);
}
- (BOOL)readBOOL
{
return [self readFloat] == 1;
}
- (void)resetRead
{
_currentIndex = 0;
}
- (NSString *)description
{
NSMutableString* str = [[[NSMutableString alloc] init] autorelease];
[str appendFormat:@"%c ",_command];
NSMutableArray* args = [[[NSMutableArray alloc] initWithCapacity:_parameterCount] autorelease];
for(int i = 0; i < _parameterCount; i++) {
[args addObject:[NSString stringWithFormat:@"%f",_parameters[i]]];
}
[str appendString:[args componentsJoinedByString:@", "]];
return str;
}
@end
@@ -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,38 @@
//
// IJSVGCommandCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandCurve.h"
@implementation IJSVGCommandCurve
+ (NSInteger)requiredParameterCount
{
return 6;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddCurveToPoint(path.path, NULL, params[0], params[1],
params[2], params[3],
params[4], params[5]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddCurveToPoint(path.path, NULL,
currentPoint.x + params[0], currentPoint.y + params[1],
currentPoint.x + params[2], currentPoint.y + params[3],
currentPoint.x + params[4], currentPoint.y + params[5]);
}
@end
@@ -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
@@ -0,0 +1,138 @@
//
// IJSVGCommandArc.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandEllipticalArc.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandEllipticalArc
static IJSVGPathDataSequence* _sequence;
+ (NSInteger)requiredParameterCount
{
return 7;
}
+ (IJSVGPathDataSequence*)pathDataSequence
{
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;
}
// modified from https://github.com/SVGKit/SVGKit/blob/880c94a5b77b6f22beb491a7a7e02ace220c32af/Source/Parsers/SVGKPointsAndPathsParser.m
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
CGPoint radii = CGPointZero;
CGPoint arcEndPoint = CGPointZero;
CGPoint pathCurrentPoint = path.currentPoint;
CGFloat xAxisRotation = 0.f;
BOOL largeArcFlag = NO;
BOOL sweepFlag = NO;
radii = [currentCommand readPoint];
xAxisRotation = [currentCommand readFloat];
largeArcFlag = [currentCommand readBOOL];
sweepFlag = [currentCommand readBOOL];
arcEndPoint = [currentCommand readPoint];
CGFloat rx = fabs(radii.x);
CGFloat ry = fabs(radii.y);
xAxisRotation *= M_PI / 180.f;
xAxisRotation = fmod(xAxisRotation, 2.f * M_PI);
if (type == kIJSVGCommandTypeRelative) {
arcEndPoint.x += pathCurrentPoint.x;
arcEndPoint.y += pathCurrentPoint.y;
}
CGFloat x1 = pathCurrentPoint.x;
CGFloat y1 = pathCurrentPoint.y;
CGFloat x2 = arcEndPoint.x;
CGFloat y2 = arcEndPoint.y;
if (rx == 0.f || ry == 0.f) {
CGPathAddLineToPoint(path.path, NULL, x2, y2);
return;
}
CGFloat cosPhi = cos(xAxisRotation);
CGFloat sinPhi = sin(xAxisRotation);
CGFloat x1p = cosPhi * (x1 - x2) / 2.f + sinPhi * (y1 - y2) / 2.f;
CGFloat y1p = -sinPhi * (x1 - x2) / 2.f + cosPhi * (y1 - y2) / 2.f;
CGFloat rx_2 = rx * rx;
CGFloat ry_2 = ry * ry;
CGFloat xp_2 = x1p * x1p;
CGFloat yp_2 = y1p * y1p;
CGFloat delta = xp_2 / rx_2 + yp_2 / ry_2;
if (delta > 1.f) {
rx *= sqrt(delta);
ry *= sqrt(delta);
rx_2 = rx * rx;
ry_2 = ry * ry;
}
CGFloat sign = (largeArcFlag == sweepFlag) ? -1.f : 1.f;
CGFloat numerator = MAX(0.f, rx_2 * ry_2 - rx_2 * yp_2 - ry_2 * xp_2);
CGFloat denom = rx_2 * yp_2 + ry_2 * xp_2;
CGFloat lhs = denom == 0.f ? 0.f : sign * sqrt(numerator / denom);
CGFloat cxp = lhs * (rx * y1p) / ry;
CGFloat cyp = lhs * -((ry * x1p) / rx);
CGFloat cx = cosPhi * cxp + -sinPhi * cyp + (x1 + x2) / 2.f;
CGFloat cy = cxp * sinPhi + cyp * cosPhi + (y1 + y2) / 2.f;
CGAffineTransform transform = CGAffineTransformMakeScale(1.f / rx, 1.f / ry);
transform = CGAffineTransformRotate(transform, -xAxisRotation);
transform = CGAffineTransformTranslate(transform, -cx, -cy);
CGPoint arcPt1 = CGPointApplyAffineTransform(CGPointMake(x1, y1), transform);
CGPoint arcPt2 = CGPointApplyAffineTransform(CGPointMake(x2, y2), transform);
CGFloat startAngle = atan2(arcPt1.y, arcPt1.x);
CGFloat endAngle = atan2(arcPt2.y, arcPt2.x);
CGFloat angleDelta = endAngle - startAngle;;
if (sweepFlag == YES) {
if (angleDelta < 0.f) {
angleDelta += 2.f * M_PI;
}
} else if (angleDelta > 0.f) {
angleDelta = angleDelta - 2.f * M_PI;
}
transform = CGAffineTransformMakeTranslation(cx, cy);
transform = CGAffineTransformRotate(transform, xAxisRotation);
transform = CGAffineTransformScale(transform, rx, ry);
CGPathAddRelativeArc(path.path, &transform, 0.f, 0.f, 1.f,
startAngle, angleDelta);
}
@end
@@ -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,34 @@
//
// IJSVGCommandHorizontalLine.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandHorizontalLine.h"
@implementation IJSVGCommandHorizontalLine
+ (NSInteger)requiredParameterCount
{
return 1;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddLineToPoint(path.path, NULL, params[0], path.currentPoint.y);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddLineToPoint(path.path, NULL, currentPoint.x + params[0],
path.currentPoint.y);
}
@end
@@ -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) {
CGPathAddLineToPoint(path.path, NULL, params[0], params[1]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddLineToPoint(path.path, NULL, currentPoint.x + params[0],
currentPoint.y + params[1]);
}
@end
@@ -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
@@ -0,0 +1,54 @@
//
// IJSVGCommandMove.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandLineTo.h"
#import "IJSVGCommandMove.h"
@implementation IJSVGCommandMove
+ (NSInteger)requiredParameterCount
{
return 2;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
// move to's allow more then one move to, but if there are more then one,
// we need to run the line to instead...who knew!
if (command.class == self.class && currentCommand.isSubCommand == YES) {
[IJSVGCommandLineTo runWithParams:params
paramCount:count
command:currentCommand
previousCommand:command
type:type
path:path];
return;
}
// actual move to command - do a moveToPoint only
// if the type is absolute, or its possible the type is
// relative but there is no previous command which means
// there is no current point. Asking for current point on an empty
// path will result in an exception being thrown
if (type == kIJSVGCommandTypeAbsolute || command == nil) {
CGPathMoveToPoint(path.path, NULL,
params[0], params[1]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathMoveToPoint(path.path, NULL,
currentPoint.x + params[0],
currentPoint.y + params[1]);
}
@end
@@ -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
@@ -0,0 +1,37 @@
//
// IJSVGCommandQuadraticCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandQuadraticCurve.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandQuadraticCurve
+ (NSInteger)requiredParameterCount
{
return 4;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddQuadCurveToPoint(path.path, NULL, params[0], params[1],
params[2], params[3]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddQuadCurveToPoint(path.path, NULL,
currentPoint.x + params[0], currentPoint.y + params[1],
currentPoint.x + params[2], currentPoint.y + params[3]);
}
@end
@@ -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
{
CGPoint currentPoint = path.currentPoint;
CGPoint firstControl = CGPointMake(currentPoint.x, currentPoint.y);
if (command != nil) {
if (command.class == [IJSVGCommandCurve class] || command.class == self.class) {
if (command.class == [IJSVGCommandCurve class]) {
if (command.type == kIJSVGCommandTypeAbsolute) {
firstControl = CGPointMake(-1 * command.parameters[2] + 2 * currentPoint.x,
-1 * command.parameters[3] + 2 * currentPoint.y);
} else {
NSPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[4],
currentPoint.y - command.parameters[5]);
firstControl = CGPointMake(-1 * (command.parameters[2] + oldPoint.x) + 2 * currentPoint.x,
-1 * (command.parameters[3] + oldPoint.y) + 2 * currentPoint.y);
}
} else {
if (command.type == kIJSVGCommandTypeAbsolute) {
firstControl = CGPointMake(-1 * command.parameters[0] + 2 * currentPoint.x,
-1 * command.parameters[1] + 2 * currentPoint.y);
} else {
NSPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[2],
currentPoint.y - command.parameters[3]);
firstControl = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * currentPoint.x,
-1 * (command.parameters[1] + oldPoint.y) + 2 * currentPoint.y);
}
}
}
}
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddCurveToPoint(path.path, NULL, firstControl.x, firstControl.y,
params[0], params[1], params[2], params[3]);
return;
}
CGPathAddCurveToPoint(path.path, NULL, firstControl.x, firstControl.y,
currentPoint.x + params[0], currentPoint.y + params[1],
currentPoint.x + params[2], currentPoint.y + params[3]);
}
@end
@@ -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,57 @@
//
// IJSVGCommandCommandQuadraticCurve.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandQuadraticCurve.h"
#import "IJSVGCommandSmoothQuadraticCurve.h"
#import "IJSVGUtils.h"
@implementation IJSVGCommandSmoothQuadraticCurve
+ (NSInteger)requiredParameterCount
{
return 2;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
CGPoint currentPoint = path.currentPoint;
CGPoint commandPoint = CGPointMake(currentPoint.x, currentPoint.y);
if (command != nil) {
if (command.class == IJSVGCommandQuadraticCurve.class) {
// quadratic curve
if (command.type == kIJSVGCommandTypeAbsolute) {
commandPoint = NSMakePoint(-1 * command.parameters[0] + 2 * currentPoint.x,
-1 * command.parameters[1] + 2 * currentPoint.y);
} else {
CGPoint oldPoint = CGPointMake(currentPoint.x - command.parameters[2],
currentPoint.y - command.parameters[3]);
commandPoint = CGPointMake(-1 * (command.parameters[0] + oldPoint.x) + 2 * (currentPoint.x),
-1 * (command.parameters[1] + oldPoint.y) + 2 * currentPoint.y);
}
} else if (command.class == self.class) {
// smooth quadratic curve
commandPoint = CGPointMake(-1 * (path.lastControlPoint.x) + 2 * (currentPoint.x),
-1 * (path.lastControlPoint.y) + 2 * currentPoint.y);
}
}
path.lastControlPoint = commandPoint;
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddQuadCurveToPoint(path.path, NULL, commandPoint.x, commandPoint.y,
params[0], params[1]);
return;
}
CGPathAddQuadCurveToPoint(path.path, NULL, commandPoint.x, commandPoint.y,
currentPoint.x + params[0], currentPoint.y + params[1]);
}
@end
@@ -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,33 @@
//
// IJSVGCommandVerticalLine.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandVerticalLine.h"
@implementation IJSVGCommandVerticalLine
+ (NSInteger)requiredParameterCount
{
return 1;
}
+ (void)runWithParams:(CGFloat*)params
paramCount:(NSInteger)count
command:(IJSVGCommand*)currentCommand
previousCommand:(IJSVGCommand*)command
type:(IJSVGCommandType)type
path:(IJSVGPath*)path
{
if (type == kIJSVGCommandTypeAbsolute) {
CGPathAddLineToPoint(path.path, NULL, path.currentPoint.x, params[0]);
return;
}
CGPoint currentPoint = path.currentPoint;
CGPathAddLineToPoint(path.path, NULL, currentPoint.x, currentPoint.y + params[0]);
}
@end
+184
View File
@@ -0,0 +1,184 @@
//
// IJSVGImage.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColorList.h>
#import <IJSVG/IJSVGExporter.h>
#import <IJSVG/IJSVGGradientLayer.h>
#import <IJSVG/IJSVGGroupLayer.h>
#import <IJSVG/IJSVGImageLayer.h>
#import <IJSVG/IJSVGLayerTree.h>
#import <IJSVG/IJSVGParser.h>
#import <IJSVG/IJSVGRendering.h>
#import <IJSVG/IJSVGRenderingStyle.h>
#import <IJSVG/IJSVGTransaction.h>
#import <Foundation/Foundation.h>
@class IJSVG;
typedef NS_OPTIONS(NSInteger, IJSVGMatchPropertiesMask) {
IJSVGMatchPropertyNone = 0,
IJSVGMatchPropertyContainsMaskedElement = 1 << 0,
IJSVGMatchPropertyContainsStrokedElement = 1 << 1
};
@protocol IJSVGDelegate <NSObject, IJSVGParserDelegate>
@optional
- (BOOL)svg:(IJSVG*)svg
shouldHandleForeignObject:(IJSVGForeignObject*)foreignObject;
- (void)svg:(IJSVG*)svg
handleForeignObject:(IJSVGForeignObject*)foreignObject
document:(NSXMLDocument*)document;
- (void)svg:(IJSVG*)svg
foundSubSVG:(IJSVG*)subSVG
withSVGString:(NSString*)subSVGString;
@end
@interface IJSVG : NSObject <NSPasteboardWriting, IJSVGParserDelegate> {
@private
IJSVGParser* _group;
CGFloat _scale;
CGFloat _clipScale;
id<IJSVGDelegate> _delegate;
IJSVGLayer* _layerTree;
CGRect _viewBox;
CGFloat _backingScaleFactor;
CGFloat _lastProposedBackingScale;
IJSVGRenderQuality _lastProposedRenderQuality;
CGFloat _backingScale;
NSMutableDictionary* _replacementColors;
struct {
unsigned int shouldHandleForeignObject : 1;
unsigned int handleForeignObject : 1;
unsigned int shouldHandleSubSVG : 1;
} _respondsTo;
}
// set this to be called when the layer is about to draw, it will call this
// and ask for the scale of the backing store where its going to be drawn
// and apply the scale to each layer that has custom drawing against it, mainly
// pattern and gradient layers
@property (nonatomic, copy) IJSVGRenderingBackingScaleFactorHelper renderingBackingScaleHelper;
// global overwriting rules for when rendering an SVG, this will overide any
// fillColor, strokeColor, pattern and gradient fill
@property (nonatomic, assign) IJSVGRenderQuality renderQuality;
@property (nonatomic, assign) BOOL clipToViewport;
@property (nonatomic, retain) IJSVGRenderingStyle* renderingStyle;
@property (nonatomic, readonly) IJSVGUnitSize * intrinsicSize;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;
- (void)prepForDrawingInView:(NSView*)view;
- (BOOL)isFont;
- (IJSVGGroup*)rootNode;
- (NSRect)viewBox;
- (NSArray<IJSVGPath*>*)glyphs;
- (NSString*)identifier;
- (IJSVGLayer*)layer;
- (IJSVGLayer*)layerWithTree:(IJSVGLayerTree*)tree;
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive;
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options;
- (NSString*)SVGStringWithOptions:(IJSVGExporterOptions)options
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (CGFloat)computeBackingScale:(CGFloat)scale;
- (void)discardDOM;
+ (id)svgNamed:(NSString*)string;
+ (id)svgNamed:(NSString*)string
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithImage:(NSImage*)image;
- (id)initWithSVGLayer:(IJSVGGroupLayer*)group
viewBox:(NSRect)viewBox;
- (id)initWithSVGString:(NSString*)string
error:(NSError**)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithSVGString:(NSString*)string;
- (id)initWithSVGString:(NSString*)string
error:(NSError**)error;
- (id)initWithSVGData:(NSData*)data;
- (id)initWithSVGData:(NSData*)data
error:(NSError**)error;
- (id)initWithFile:(NSString*)file;
- (id)initWithFile:(NSString*)file
error:(NSError**)error;
- (id)initWithFile:(NSString*)file
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFile:(NSString*)file
error:(NSError**)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFilePathURL:(NSURL*)aURL;
- (id)initWithFilePathURL:(NSURL*)aURL
error:(NSError**)error;
- (id)initWithFilePathURL:(NSURL*)aURL
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithFilePathURL:(NSURL*)aURL
error:(NSError**)error
delegate:(id<IJSVGDelegate>)delegate;
- (id)initWithDataAssetNamed:(NSDataAssetName)name
error:(NSError**)error;
- (id)initWithDataAssetNamed:(NSDataAssetName)name
bundle:(NSBundle*)bundle
error:(NSError**)error;
- (NSImage*)imageWithSize:(NSSize)aSize;
- (NSImage*)imageWithSize:(NSSize)aSize
error:(NSError**)error;
- (NSImage*)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped;
- (NSImage*)imageWithSize:(NSSize)aSize
flipped:(BOOL)flipped
error:(NSError**)error;
- (NSImage*)imageByMaintainingAspectRatioWithSize:(NSSize)aSize
flipped:(BOOL)flipped
error:(NSError**)error;
- (CGImageRef)newCGImageRefWithSize:(CGSize)size
flipped:(BOOL)flipped
error:(NSError**)error;
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)size;
- (BOOL)drawAtPoint:(NSPoint)point
size:(NSSize)aSize
error:(NSError**)error;
- (BOOL)drawInRect:(NSRect)rect;
- (BOOL)drawInRect:(NSRect)rect
error:(NSError**)error;
- (void)drawInRect:(NSRect)rect
context:(CGContextRef)context;
- (NSData*)PDFData;
- (NSData*)PDFData:(NSError**)error;
- (NSData*)PDFDataWithRect:(NSRect)rect;
- (NSData*)PDFDataWithRect:(NSRect)rect
error:(NSError**)error;
- (void)beginVectorDraw;
- (void)endVectorDraw;
- (NSRect)computeOriginalDrawingFrameWithSize:(NSSize)aSize;
- (void)setNeedsDisplay;
// colors
- (IJSVGColorList*)colorList;
- (void)performBlock:(dispatch_block_t)block;
// matching
- (BOOL)matchesPropertiesWithMask:(IJSVGMatchPropertiesMask)mask;
@end
File diff suppressed because it is too large Load Diff
@@ -8,9 +8,9 @@
#import <Foundation/Foundation.h>
static NSString * const IJSVGErrorDomain = @"IJSVGErrorDomain";
static NSString* const IJSVGErrorDomain = @"IJSVGErrorDomain";
NS_ENUM(NSInteger) {
NS_ENUM(NSInteger){
IJSVGErrorReadingFile,
IJSVGErrorParsingFile,
IJSVGErrorParsingSVG,
@@ -0,0 +1,29 @@
//
// IJSVGFontConverter.h
// IJSVGExample
//
// Created by Curtis Hard on 21/05/2015.
// Copyright (c) 2015 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVG.h>
#import <Foundation/Foundation.h>
typedef void (^IJSVGFontConverterEnumerateBlock)(NSString* unicode, IJSVG* svg);
@interface IJSVGFontConverter : NSObject {
@private
NSURL* _url;
NSFont* _font;
NSMutableDictionary<NSString*, id>* _transformedPaths;
}
- (id)initWithFontAtFileURL:(NSURL*)url;
- (NSFont*)font;
- (void)enumerateUsingBlock:(IJSVGFontConverterEnumerateBlock)block;
+ (IJSVG*)convertIJSVGPathToSVG:(IJSVGPath*)path;
+ (IJSVG*)convertPathToSVG:(CGPathRef)path;
@end
@@ -0,0 +1,127 @@
//
// IJSVGFontConverter.m
// IJSVGExample
//
// Created by Curtis Hard on 21/05/2015.
// Copyright (c) 2015 Curtis Hard. All rights reserved.
//
#import "IJSVGFontConverter.h"
#import "IJSVGShapeLayer.h"
@implementation IJSVGFontConverter
- (void)dealloc
{
(void)([_transformedPaths release]), _transformedPaths = nil;
(void)([_url release]), _url = nil;
(void)([_font release]), _font = nil;
[super dealloc];
}
- (id)initWithFontAtFileURL:(NSURL*)url
{
if ((self = [super init]) != nil) {
_url = [url copy];
// load the font
CGDataProviderRef dataProvider = CGDataProviderCreateWithURL((CFURLRef)_url);
CGFontRef fontRef = CGFontCreateWithDataProvider(dataProvider);
CTFontRef font = CTFontCreateWithGraphicsFont(fontRef, 30.f, NULL, NULL);
// toll free bridge between NSFont at CTFont :)
_font = [(NSFont*)font copy];
CGFontRelease(fontRef);
CGDataProviderRelease(dataProvider);
CFRelease(font);
}
return self;
}
- (NSFont*)font
{
return _font;
}
- (NSArray*)allCharacters
{
NSCharacterSet* charSet = _font.coveredCharacterSet;
NSMutableArray* array = [[[NSMutableArray alloc] init] autorelease];
NSStringEncoding encoding = NSUTF32LittleEndianStringEncoding;
for (int plane = 0; plane <= 16; plane++) {
if ([charSet hasMemberInPlane:plane]) {
UTF32Char c;
for (c = plane << 16; c < (plane + 1) << 16; c++) {
if ([charSet longCharacterIsMember:c]) {
UTF32Char c1 = NSSwapHostIntToLittle(c);
[array addObject:[[[NSString alloc] initWithBytes:&c1
length:4
encoding:encoding] autorelease]];
}
}
}
}
return array;
}
- (void)generateMap
{
CTFontRef font = (CTFontRef)_font;
for (NSString* charString in [self allCharacters]) {
// get the characters in each char
NSUInteger count = charString.length;
unichar characters[count];
[charString getCharacters:characters
range:NSMakeRange(0, count)];
// get the glyphs
CGGlyph glyphs[count];
CTFontGetGlyphsForCharacters(font, characters, glyphs, count);
CGPathRef path = CTFontCreatePathForGlyph(font, glyphs[0], NULL);
if (path != NULL) {
// add SVG to the dictionary
NSString* key = [NSString stringWithFormat:@"%04x", [charString characterAtIndex:0]];
CGPathRef flippedPath = [IJSVGUtils newFlippedCGPath:path];
_transformedPaths[key] = (id)flippedPath;
CGPathRelease(flippedPath);
}
CGPathRelease(path);
}
}
- (void)enumerateUsingBlock:(IJSVGFontConverterEnumerateBlock)block
{
if (_transformedPaths == nil) {
_transformedPaths = [[NSMutableDictionary alloc] init];
[self generateMap];
}
for (NSString* key in _transformedPaths.allKeys) {
block(key, [self.class convertPathToSVG:(CGPathRef)_transformedPaths[key]]);
}
}
+ (IJSVG*)convertIJSVGPathToSVG:(IJSVGPath*)path
{
CGPathRef flippedPath = [IJSVGUtils newFlippedCGPath:path.path];
IJSVG* svg = [self convertPathToSVG:flippedPath];
CGPathRelease(flippedPath);
return svg;
}
+ (IJSVG*)convertPathToSVG:(CGPathRef)path
{
IJSVGBeginTransaction();
__block IJSVG* svg = nil;
IJSVGGroupLayer* layer = [[[IJSVGGroupLayer alloc] init] autorelease];
IJSVGShapeLayer* shape = [[[IJSVGShapeLayer alloc] init] autorelease];
[layer addSublayer:shape];
shape.path = path;
CGRect box = CGPathGetPathBoundingBox(path);
svg = [[IJSVG alloc] initWithSVGLayer:layer
viewBox:box];
IJSVGEndTransaction();
return [svg autorelease];
}
@end
@@ -0,0 +1,25 @@
//
// IJSVGImageRep.h
// IJSVGExample
//
// Created by Curtis Hard on 15/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGParser.h"
#import <Cocoa/Cocoa.h>
@class IJSVG;
@interface IJSVGImageRep : NSImageRep {
@private
IJSVG* _svg;
}
- (instancetype)initWithData:(NSData*)data;
@property (nonatomic, readonly) CGRect viewBox;
@property (nonatomic, readonly) IJSVG* SVG;
@end
@@ -0,0 +1,115 @@
//
// IJSVGImageRep.m
// IJSVGExample
//
// Created by Curtis Hard on 15/03/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGImageRep.h"
@implementation IJSVGImageRep
+ (void)load
{
[NSBitmapImageRep registerImageRepClass:self];
}
+ (BOOL)canInitWithData:(NSData*)data
{
return [IJSVGParser isDataSVG:data];
}
+ (NSArray<NSString*>*)imageTypes
{
if (@available(macOS 10.10, *)) {
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
} else {
return @[ @"public.svg-image", @"svg" ];
}
}
+ (NSArray<NSString*>*)imageUnfilteredTypes
{
if (@available(macOS 10.10, *)) {
return @[ (NSString*)kUTTypeScalableVectorGraphics, @"svg" ];
} else {
return @[ @"public.svg-image", @"svg" ];
}
}
+ (NSArray<NSImageRep*>*)imageRepsWithData:(NSData*)data
{
IJSVGImageRep* instance = [self imageRepWithData:data];
if (instance == nil) {
return @[];
}
return @[ instance ];
}
+ (instancetype)imageRepWithData:(NSData*)data
{
return [[[self alloc] initWithData:data] autorelease];
}
- (void)dealloc
{
(void)([_svg release]), _svg = nil;
[super dealloc];
}
- (instancetype)initWithData:(NSData*)data
{
if ((self = [super init]) != nil) {
// grab the string from the data
// its more then likely UTF-8...
NSString* string = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
_svg = [[IJSVG alloc] initWithSVGString:string];
// no valid SVG, just return nil;
if (_svg == nil) {
[self release];
return nil;
}
// set default properties
self.pixelsWide = _svg.viewBox.size.width;
self.pixelsHigh = _svg.viewBox.size.height;
self.size = _svg.viewBox.size;
}
return self;
}
- (BOOL)draw
{
[_svg drawInRect:self.viewBox];
return YES;
}
- (BOOL)drawAtPoint:(NSPoint)point
{
[_svg drawAtPoint:point
size:_svg.viewBox.size];
return YES;
}
- (BOOL)drawInRect:(NSRect)rect
{
[_svg drawInRect:rect];
return YES;
}
- (CGRect)viewBox
{
return _svg.viewBox;
}
- (IJSVG*)SVG
{
return _svg;
}
@end
@@ -0,0 +1,25 @@
//
// IJSVGView.h
// IconJar
//
// Created by Curtis Hard on 04/04/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVG.h>
#import <Cocoa/Cocoa.h>
IB_DESIGNABLE
@interface IJSVGView : NSView {
IBInspectable NSString* imageName;
IBInspectable NSColor* tintColor;
IJSVG* SVG;
}
@property (nonatomic, retain) IJSVG* SVG;
+ (IJSVGView*)viewWithSVGNamed:(NSString*)name;
- (id)initWithSVG:(IJSVG*)anSvg;
@end
@@ -0,0 +1,80 @@
//
// IJSVGView.m
// IconJar
//
// Created by Curtis Hard on 04/04/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGView.h"
@implementation IJSVGView
@synthesize SVG;
- (void)dealloc
{
// make sure we call this, or block may get called for a view
// that doesnt exist
[SVG prepForDrawingInView:nil];
(void)([imageName release]), imageName = nil;
(void)([SVG release]), SVG = nil;
[super dealloc];
}
+ (IJSVGView*)viewWithSVGNamed:(NSString*)name
{
IJSVG* anSVG = [IJSVG svgNamed:name];
return [[[self alloc] initWithSVG:anSVG] autorelease];
}
- (id)initWithSVG:(IJSVG*)anSvg
{
if ((self = [super init]) != nil) {
self.SVG = anSvg;
}
return self;
}
- (void)awakeFromNib
{
// image was set via IB
if (imageName != nil) {
IJSVG* anSVG = [IJSVG svgNamed:imageName];
if (tintColor != nil) {
anSVG.renderingStyle.fillColor = tintColor;
}
self.SVG = anSVG;
}
}
- (void)setSVG:(IJSVG*)anSVG
{
// memory clean
if (SVG != nil) {
(void)([SVG release]), SVG = nil;
}
SVG = [anSVG retain];
// redisplay ourself!
[SVG prepForDrawingInView:self];
[self setNeedsDisplay:YES];
}
- (BOOL)isFlipped
{
return YES;
}
- (void)drawRect:(NSRect)dirtyRect
{
// only draw if there is actually an SVG
if (self.SVG == nil) {
return;
}
// draw the svg
[self.SVG drawInRect:self.bounds];
}
@end
@@ -0,0 +1,79 @@
//
// IJSVGExporter.h
// IJSVGExample
//
// Created by Curtis Hard on 06/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <IJSVG/IJSVGUtils.h>
@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,
IJSVGExporterOptionCenterWithinViewBox = 1 << 16,
IJSVGExporterOptionRemoveXMLDeclaration = 1 << 17,
IJSVGExporterOptionConvertArcs = 1 << 18,
IJSVGExporterOptionConvertShapesToPaths = 1 << 19,
IJSVGExporterOptionRoundTransforms = 1 << 20,
IJSVGExporterOptionRemoveDefaultValues = 1 << 21,
IJSVGExporterOptionAll = IJSVGExporterOptionRemoveUselessDef | IJSVGExporterOptionRemoveUselessGroups | IJSVGExporterOptionCreateUseForPaths | IJSVGExporterOptionMoveAttributesToGroup | IJSVGExporterOptionSortAttributes | IJSVGExporterOptionCollapseGroups | IJSVGExporterOptionCleanupPaths | IJSVGExporterOptionRemoveHiddenElements | IJSVGExporterOptionScaleToSizeIfNecessary | IJSVGExporterOptionCompressOutput | IJSVGExporterOptionCollapseGradients | IJSVGExporterOptionRemoveWidthHeightAttributes | IJSVGExporterOptionColorAllowRRGGBBAA | IJSVGExporterOptionRemoveComments | IJSVGExporterOptionCenterWithinViewBox | IJSVGExporterOptionRemoveXMLDeclaration | IJSVGExporterOptionConvertArcs | IJSVGExporterOptionConvertShapesToPaths | IJSVGExporterOptionRoundTransforms | IJSVGExporterOptionRemoveDefaultValues
};
BOOL IJSVGExporterHasOption(IJSVGExporterOptions options, NSInteger option);
void IJSVGEnumerateCGPathElements(CGPathRef path, IJSVGPathElementEnumerationBlock enumBlock);
const NSArray<NSString*>* IJSVGShortCharacterArray(void);
const NSDictionary<NSString*, NSString*>* IJSVGDefaultAttributes(void);
@interface IJSVGExporter : NSObject {
@private
IJSVG* _svg;
CGSize _size;
IJSVGExporterOptions _options;
NSXMLDocument* _dom;
NSXMLElement* _defElement;
NSInteger _idCount;
NSInteger _shortIdCount;
BOOL _appliedXLink;
}
@property (nonatomic, assign) IJSVGFloatingPointOptions floatingPointOptions;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;
- (id)initWithSVG:(IJSVG*)svg
size:(CGSize)size
options:(IJSVGExporterOptions)options;
- (id)initWithSVG:(IJSVG*)svg
size:(CGSize)size
options:(IJSVGExporterOptions)options
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (NSString*)SVGString;
- (NSData*)SVGData;
- (IJSVG*)SVG:(NSError**)error;
@end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,67 @@
//
// IJSVGExporterPathInstruction.h
// IconJar
//
// Created by Curtis Hard on 08/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef struct {
char instruction;
NSArray<NSString*>* params;
} IJSVGExporterPathInstructionCommand;
typedef struct {
CGPoint center;
CGFloat radius;
} IJSVGExporterPathInstructionCircle;
@interface IJSVGExporterPathInstruction : NSObject {
@private
NSInteger _dataCount;
CGFloat* _data;
CGFloat* _base;
CGFloat* _coords;
}
@property (nonatomic, assign) char instruction;
void IJSVGExporterPathInstructionRoundData(CGFloat* data, NSInteger length, IJSVGFloatingPointOptions options);
CGFloat IJSVGExporterPathFloatToFixed(CGFloat number, int precision);
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command);
void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand* _Nullable command);
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
- (id)initWithInstruction:(char)instruction
dataCount:(NSInteger)floatCount;
- (CGFloat*)data;
- (NSInteger)dataLength;
+ (NSArray<IJSVGExporterPathInstruction*>*)convertInstructionsCurves:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
+ (void)convertInstructionsToMixedAbsoluteRelative:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
+ (void)convertInstructionsDataToRounded:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions;
@end
NS_ASSUME_NONNULL_END
static NSInteger const kIJSVGExporterPathInstructionFloatPrecision = 3;
static CGFloat const kIJSVGExporterPathInstructionErrorThreshold = 1e-2;
#define IJ_SVG_EXPORT_ROUND(value) IJSVGExporterPathFloatToFixed(value, kIJSVGExporterPathInstructionFloatPrecision)
@@ -0,0 +1,629 @@
//
// IJSVGExporterPathInstruction.m
// IconJar
//
// Created by Curtis Hard on 08/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGExporter.h"
#import "IJSVGExporterPathInstruction.h"
#import "IJSVGUtils.h"
#import <math.h>
@implementation IJSVGExporterPathInstruction
@synthesize instruction = _instruction;
- (void)dealloc
{
if (_data != NULL) {
(void)free(_data), _data = NULL;
}
if (_base != NULL) {
(void)free(_base), _base = NULL;
}
if (_coords != NULL) {
(void)free(_coords), _coords = NULL;
}
[super dealloc];
}
- (id)initWithInstruction:(char)instruction
dataCount:(NSInteger)floatCount
{
if ((self = [super init]) != nil) {
_instruction = instruction;
// only allocate if not zero
if (floatCount != 0) {
_dataCount = floatCount;
_data = (CGFloat*)calloc(sizeof(CGFloat), floatCount);
}
// setup base and coords
_base = (CGFloat*)malloc(sizeof(CGFloat) * 2);
_coords = (CGFloat*)malloc(sizeof(CGFloat) * 2);
}
return self;
}
- (NSInteger)dataLength
{
return _dataCount;
}
- (CGFloat*)data
{
return _data;
}
- (CGFloat*)base
{
return _base;
}
- (CGFloat*)coords
{
return _coords;
}
IJSVGExporterPathInstructionCommand* IJSVGExporterPathInstructionCommandCopy(IJSVGExporterPathInstructionCommand command)
{
IJSVGExporterPathInstructionCommand* copy = NULL;
copy = (IJSVGExporterPathInstructionCommand*)malloc(sizeof(IJSVGExporterPathInstructionCommand));
copy->instruction = command.instruction;
copy->params = command.params;
return copy;
}
void IJSVGExporterPathInstructionCommandFree(IJSVGExporterPathInstructionCommand* _Nullable command)
{
if (command != NULL) {
free(command);
}
}
+ (NSString*)pathStringWithInstructionSet:(NSArray<NSValue*>*)instructionSets
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
IJSVGExporterPathInstructionCommand* lastCommand = NULL;
NSMutableString* string = [[[NSMutableString alloc] init] autorelease];
for (NSValue* value in instructionSets) {
// read back the bytes
IJSVGExporterPathInstructionCommand command;
[value getValue:&command];
// add on the instruction character only if there is no current command
// or the last command is not the same as the current command
// if they both are the same, we still need to seperate them via a space
if (lastCommand == nil || (lastCommand != nil && lastCommand->instruction != command.instruction)) {
[string appendFormat:@"%c", command.instruction];
} else {
[string appendString:@" "];
}
// compresses the floats
NSString* compressedFloats = IJSVGCompressFloatParameterArray(command.params);
[string appendString:compressedFloats];
// store last command
IJSVGExporterPathInstructionCommandFree(lastCommand);
lastCommand = IJSVGExporterPathInstructionCommandCopy(command);
}
IJSVGExporterPathInstructionCommandFree(lastCommand);
return string;
}
+ (NSString*)pathStringFromInstructions:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
NSMutableArray* pathInstructions = [[[NSMutableArray alloc] init] autorelease];
for (IJSVGExporterPathInstruction* instruction in instructions) {
CGFloat* data = instruction.data;
const char lowerInstruction = tolower(instruction.instruction);
NSArray<NSString*>* set = nil;
switch (lowerInstruction) {
case 't':
case 'm':
case 'l': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions)
];
break;
}
case 'v':
case 'h': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions)
];
break;
}
case 'c': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[3], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[4], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[5], floatingPointOptions)
];
break;
}
case 's':
case 'q': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[3], floatingPointOptions)
];
break;
}
case 'a': {
set = @[
IJSVGShortFloatStringWithOptions(data[0], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[1], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[2], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[3], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[4], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[5], floatingPointOptions),
IJSVGShortFloatStringWithOptions(data[6], floatingPointOptions),
];
break;
}
// close path
case 'z': {
set = @[];
}
}
// wrap into the command and give to the array
IJSVGExporterPathInstructionCommand wrapper;
wrapper.instruction = instruction.instruction;
wrapper.params = set ?: @[];
// encode and store
NSValue* value = [NSValue valueWithBytes:&wrapper
objCType:@encode(IJSVGExporterPathInstructionCommand)];
[pathInstructions addObject:value];
}
return [self pathStringWithInstructionSet:pathInstructions
floatingPointOptions:floatingPointOptions];
}
CGFloat IJSVGExporterPathFloatToFixed(CGFloat number, int precision)
{
return floorf(pow(10, precision) * number) / pow(10, precision);
}
void IJSVGExporterPathInstructionRoundData(CGFloat* data, NSInteger length,
IJSVGFloatingPointOptions options)
{
for (NSInteger i = length; i-- > 0;) {
CGFloat d = data[i];
CGFloat proposed = IJSVGExporterPathFloatToFixed(d, options.precision);
if (proposed != d) {
CGFloat rounded = +IJSVGExporterPathFloatToFixed(d, options.precision - 1);
data[i] = IJSVGExporterPathFloatToFixed(+fabs(rounded - d), options.precision + 1)
>= kIJSVGExporterPathInstructionErrorThreshold
? +IJSVGExporterPathFloatToFixed(d, options.precision)
: rounded;
}
}
}
+ (void)convertInstructionsToRoundRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
CGFloat relSubPoint[2] = { 0.f, 0.f };
for (IJSVGExporterPathInstruction* instruction in instructions) {
char instructionChar = instruction.instruction;
NSInteger length = instruction.dataLength;
CGFloat* data = instruction.data;
if (strchr("mltqsc", instructionChar) != NULL) {
for (NSInteger i = length; i--;) {
data[i] += instruction.base[i % 2] - relSubPoint[i % 2];
}
} else if (instructionChar == 'h') {
data[0] += instruction.base[0] - relSubPoint[0];
} else if (instructionChar == 'v') {
data[0] += instruction.base[1] - relSubPoint[1];
} else if (instructionChar == 'a') {
data[5] += instruction.base[0] - relSubPoint[0];
data[5] += instruction.base[1] - relSubPoint[1];
}
IJSVGExporterPathInstructionRoundData(data, length, floatingPointOptions);
if (instructionChar == 'h') {
relSubPoint[0] += data[0];
} else if (instructionChar == 'v') {
relSubPoint[1] += data[0];
} else {
relSubPoint[0] += data[length - 2];
relSubPoint[1] += data[length - 1];
}
IJSVGExporterPathInstructionRoundData(relSubPoint, 2, floatingPointOptions);
}
}
+ (void)convertInstructionsToMixedAbsoluteRelative:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
IJSVGExporterPathInstruction* prevInstruction = nil;
for (IJSVGExporterPathInstruction* instruction in instructions) {
if (prevInstruction == nil || instruction.dataLength == 0) {
prevInstruction = instruction;
continue;
}
char instructionChar = instruction.instruction;
CGFloat* data = instruction.data;
NSInteger length = instruction.dataLength;
CGFloat* adata = (CGFloat*)malloc(sizeof(CGFloat) * length);
memcpy(adata, data, sizeof(CGFloat) * length);
if (strchr("mltqsc", instructionChar) != NULL) {
for (NSInteger i = length; i--;) {
adata[i] += instruction.base[i % 2];
}
} else if (instructionChar == 'h') {
adata[0] += instruction.base[0];
} else if (instructionChar == 'v') {
adata[0] += instruction.base[1];
} else if (instructionChar == 'a') {
adata[5] += instruction.base[0];
adata[6] += instruction.base[1];
}
IJSVGExporterPathInstructionRoundData(adata, length, floatingPointOptions);
IJSVGExporterPathInstruction* ainstruction = nil;
ainstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:instructionChar
dataCount:length] autorelease];
memcpy(ainstruction.data, adata, sizeof(CGFloat) * length);
// run these through our default string runner
// to compare the outputs
NSString* orig = [self pathStringFromInstructions:@[ instruction ]
floatingPointOptions:floatingPointOptions];
NSString* comp = [self pathStringFromInstructions:@[ ainstruction ]
floatingPointOptions:floatingPointOptions];
if (comp.length < orig.length && !(instructionChar == prevInstruction.instruction && prevInstruction.instruction > 96 && comp.length == orig.length - 1 && data[0] < 0.f && fmod(prevInstruction.data[prevInstruction.dataLength - 1], 1) != 0.f)) {
instruction.instruction = toupper(instructionChar);
memcpy(data, adata, sizeof(CGFloat) * length);
}
(void)free(adata), adata = NULL;
prevInstruction = instruction;
}
}
+ (void)convertInstructionsDataToRounded:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
for (IJSVGExporterPathInstruction* instruction in instructions) {
CGFloat* data = instruction.data;
IJSVGExporterPathInstructionRoundData(data, instruction.dataLength,
floatingPointOptions);
}
}
+ (NSArray<IJSVGExporterPathInstruction*>*)convertInstructionsCurves:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
NSMutableArray<IJSVGExporterPathInstruction*>* nInstructions = nil;
nInstructions = [[[NSMutableArray alloc] initWithCapacity:instructions.count] autorelease];
IJSVGExporterPathInstruction* lastInstruction = nil;
for (IJSVGExporterPathInstruction* instruction in instructions) {
lastInstruction = nInstructions.lastObject;
if (lastInstruction == nil) {
[nInstructions addObject:instruction];
continue;
}
if (instruction.instruction == 'c') {
if (lastInstruction.instruction == 'c' && instruction.data[0] == -(lastInstruction.data[2] - lastInstruction.data[4]) && instruction.data[1] == -(lastInstruction.data[3] - lastInstruction.data[5])) {
IJSVGExporterPathInstruction* nInstruction = nil;
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'s'
dataCount:4] autorelease];
nInstruction.data[0] = instruction.data[2];
nInstruction.data[1] = instruction.data[3];
nInstruction.data[2] = instruction.data[4];
nInstruction.data[3] = instruction.data[5];
[nInstructions addObject:nInstruction];
continue;
} else if (lastInstruction.instruction == 's' && instruction.data[0] == -(lastInstruction.data[0] - lastInstruction.data[2]) && instruction.data[1] == -(lastInstruction.data[1] - lastInstruction.data[3])) {
IJSVGExporterPathInstruction* nInstruction = nil;
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'s'
dataCount:4] autorelease];
nInstruction.data[0] = instruction.data[2];
nInstruction.data[1] = instruction.data[3];
nInstruction.data[2] = instruction.data[4];
nInstruction.data[3] = instruction.data[5];
[nInstructions addObject:nInstruction];
continue;
} else if (lastInstruction.instruction != 'c' && lastInstruction.instruction != 's' && instruction.data[0] == 0.f && instruction.data[1] == 0.f) {
IJSVGExporterPathInstruction* nInstruction = nil;
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'s'
dataCount:4] autorelease];
nInstruction.data[0] = instruction.data[2];
nInstruction.data[1] = instruction.data[3];
nInstruction.data[2] = instruction.data[4];
nInstruction.data[3] = instruction.data[5];
[nInstructions addObject:nInstruction];
continue;
}
} else if (instruction.instruction == 'q') {
if (lastInstruction.instruction == 'q' && instruction.data[0] == (lastInstruction.data[2] - lastInstruction.data[0]) && instruction.data[1] == (lastInstruction.data[3] - lastInstruction.data[1])) {
IJSVGExporterPathInstruction* nInstruction = nil;
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'t'
dataCount:2] autorelease];
nInstruction.data[0] = instruction.data[3];
nInstruction.data[1] = instruction.data[4];
[nInstructions addObject:nInstruction];
continue;
} else if (lastInstruction.instruction == 't' && instruction.data[2] == lastInstruction.data[0] && instruction.data[3] == lastInstruction.data[1]) {
IJSVGExporterPathInstruction* nInstruction = nil;
nInstruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'t'
dataCount:2] autorelease];
nInstruction.data[0] = instruction.data[3];
nInstruction.data[1] = instruction.data[4];
[nInstructions addObject:nInstruction];
continue;
}
}
[nInstructions addObject:instruction];
}
return nInstructions;
}
+ (void)convertInstructionsToRelativeCoordinates:(NSArray<IJSVGExporterPathInstruction*>*)instructions
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
CGFloat point[2] = { 0, 0 };
CGFloat subpathPoint[2] = { 0, 0 };
IJSVGExporterPathInstruction* baseInstruction = nil;
IJSVGExporterPathInstruction* prevInstruction = nil;
NSInteger index = 0;
for (IJSVGExporterPathInstruction* anInstruction in instructions) {
char instruction = anInstruction.instruction;
CGFloat* data = anInstruction.data;
NSInteger length = anInstruction.dataLength;
if (data != NULL) {
// already relative
if (instruction == 'm' || instruction == 'c' || instruction == 's' || instruction == 'l' || instruction == 'q' || instruction == 't' || instruction == 'a') {
point[0] += data[length - 2];
point[1] += data[length - 1];
if (instruction == 'm') {
subpathPoint[0] = point[0];
subpathPoint[1] = point[1];
baseInstruction = anInstruction;
}
} else if (instruction == 'h') {
point[0] += data[0];
} else if (instruction == 'v') {
point[1] += data[0];
}
// convert absolute to relative
if (instruction == 'M') {
if (index > 0) {
instruction = 'm';
}
data[0] -= point[0];
data[1] -= point[1];
subpathPoint[0] = point[0] += data[0];
subpathPoint[1] = point[1] += data[1];
baseInstruction = anInstruction;
} else if (instruction == 'L' || instruction == 'T') {
instruction = tolower(instruction);
data[0] -= point[0];
data[1] -= point[1];
point[0] += data[0];
point[1] += data[1];
} else if (instruction == 'C') {
instruction = 'c';
data[0] -= point[0];
data[1] -= point[1];
data[2] -= point[0];
data[3] -= point[1];
data[4] -= point[0];
data[5] -= point[1];
point[0] += data[4];
point[1] += data[5];
} else if (instruction == 'S' || instruction == 'Q') {
instruction = tolower(instruction);
data[0] -= point[0];
data[1] -= point[1];
data[2] -= point[0];
data[3] -= point[1];
point[0] += data[2];
point[1] += data[3];
} else if (instruction == 'A') {
instruction = 'a';
data[5] -= point[0];
data[6] -= point[1];
point[0] += data[5];
point[1] += data[6];
} else if (instruction == 'H') {
instruction = 'h';
data[0] -= point[0];
point[0] += data[0];
} else if (instruction == 'V') {
instruction = 'v';
data[0] -= point[1];
point[1] += data[0];
}
// reset the instruction
anInstruction.instruction = instruction;
CGFloat* coords = anInstruction.coords;
coords[0] = point[0];
coords[1] = point[1];
} else if (instruction == 'Z' || instruction == 'z') {
if (baseInstruction != nil) {
CGFloat* coords = anInstruction.coords;
coords[0] = baseInstruction.coords[0];
coords[1] = baseInstruction.coords[1];
}
point[0] = subpathPoint[0];
point[1] = subpathPoint[1];
}
CGFloat* base = anInstruction.base;
if (prevInstruction != nil) {
base[0] = prevInstruction.coords[0];
base[1] = prevInstruction.coords[1];
} else {
base[0] = 0.f;
base[1] = 0.f;
}
// increment index
prevInstruction = anInstruction;
index++;
}
}
+ (NSArray<IJSVGExporterPathInstruction*>*)instructionsFromPath:(CGPathRef)path
floatingPointOptions:(IJSVGFloatingPointOptions)floatingPointOptions
{
// keep track of the current point
__block CGPoint currentPoint = CGPointZero;
NSMutableArray* instructions = [[[NSMutableArray alloc] init] autorelease];
// create the path callback
IJSVGCGPathHandler callback = ^(const CGPathElement* pathElement) {
IJSVGExporterPathInstruction* instruction = nil;
// work out what to do
switch (pathElement->type) {
case kCGPathElementMoveToPoint: {
// move to command
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'M'
dataCount:2] autorelease];
CGPoint point = pathElement->points[0];
instruction.data[0] = point.x;
instruction.data[1] = point.y;
currentPoint = point;
[instructions addObject:instruction];
break;
}
case kCGPathElementAddLineToPoint: {
// line to command
CGPoint point = pathElement->points[0];
if (point.x == currentPoint.x) {
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'V'
dataCount:1] autorelease];
instruction.data[0] = point.y;
} else if (point.y == currentPoint.y) {
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'H'
dataCount:1] autorelease];
instruction.data[0] = point.x;
} else {
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'L'
dataCount:2] autorelease];
instruction.data[0] = point.x;
instruction.data[1] = point.y;
}
currentPoint = point;
[instructions addObject:instruction];
break;
}
case kCGPathElementAddQuadCurveToPoint: {
// quad curve to command
CGPoint controlPoint = pathElement->points[0];
CGPoint point = pathElement->points[1];
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'Q'
dataCount:4] autorelease];
instruction.data[0] = controlPoint.x;
instruction.data[1] = controlPoint.y;
instruction.data[2] = point.x;
instruction.data[3] = point.y;
currentPoint = point;
[instructions addObject:instruction];
break;
}
case kCGPathElementAddCurveToPoint: {
// curve to command
CGPoint controlPoint1 = pathElement->points[0];
CGPoint controlPoint2 = pathElement->points[1];
CGPoint point = pathElement->points[2];
currentPoint = point;
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'C'
dataCount:6] autorelease];
instruction.data[0] = controlPoint1.x;
instruction.data[1] = controlPoint1.y;
instruction.data[2] = controlPoint2.x;
instruction.data[3] = controlPoint2.y;
instruction.data[4] = point.x;
instruction.data[5] = point.y;
[instructions addObject:instruction];
break;
}
case kCGPathElementCloseSubpath: {
// close command
instruction = [[[IJSVGExporterPathInstruction alloc] initWithInstruction:'Z'
dataCount:0] autorelease];
[instructions addObject:instruction];
break;
}
}
};
// apply the
CGPathApply(path, (__bridge void*)callback, IJSVGExporterPathCaller);
// remove last instruction if it was Z -> M
IJSVGExporterPathInstruction* lastInstruction = instructions.lastObject;
if (lastInstruction.instruction == 'M' || lastInstruction.instruction == 'm') {
if (instructions.count >= 2) {
NSInteger index = [instructions indexOfObject:lastInstruction] - 1;
IJSVGExporterPathInstruction* prevInstruction = instructions[index];
if (prevInstruction.instruction == 'z' || prevInstruction.instruction == 'Z') {
[instructions removeLastObject];
}
}
}
return instructions;
}
@end
@@ -0,0 +1,23 @@
//
// IJSVGGradientLayer.h
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGGradient.h>
#import <IJSVG/IJSVGLayer.h>
#import <IJSVG/IJSVGPath.h>
#import <QuartzCore/QuartzCore.h>
@interface IJSVGGradientLayer : IJSVGLayer {
}
@property (nonatomic, assign) CGRect viewBox;
@property (nonatomic, retain) IJSVGGradient* gradient;
@property (nonatomic, assign) CGAffineTransform absoluteTransform;
@property (nonatomic, assign) CGRect objectRect;
@end
@@ -0,0 +1,98 @@
//
// IJSVGGradientLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGGradientLayer.h"
@implementation IJSVGGradientLayer
- (void)dealloc
{
(void)([_gradient release]), _gradient = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
self.requiresBackingScaleHelp = YES;
self.shouldRasterize = YES;
}
return self;
}
- (void)setGradient:(IJSVGGradient*)newGradient
{
if (_gradient != nil) {
(void)([_gradient release]), _gradient = nil;
}
_gradient = [newGradient retain];
// lets check its alpha properties on the colors
BOOL hasAlphaChannel = NO;
NSInteger stops = _gradient.gradient.numberOfColorStops;
for (NSInteger i = 0; i < stops; i++) {
NSColor* color = nil;
[_gradient.gradient getColor:&color
location:NULL
atIndex:i];
if (color.alphaComponent != 1.f) {
hasAlphaChannel = YES;
break;
}
}
self.opaque = hasAlphaChannel == NO;
}
- (void)setOpacity:(float)opacity
{
if (opacity != 1.f) {
self.opaque = NO;
}
[super setOpacity:opacity];
}
- (void)setBackingScaleFactor:(CGFloat)backingScaleFactor
{
switch (self.renderQuality) {
case kIJSVGRenderQualityOptimized: {
backingScaleFactor = (backingScaleFactor * .35f);
break;
}
case kIJSVGRenderQualityLow: {
backingScaleFactor = (backingScaleFactor * .05f);
break;
}
default: {
break;
}
}
[super setBackingScaleFactor:backingScaleFactor];
}
- (void)drawInContext:(CGContextRef)ctx
{
[super drawInContext:ctx];
// nothing to do :(
if (self.gradient == nil) {
return;
}
// draw the gradient
CGAffineTransform trans = CGAffineTransformMakeTranslation(-CGRectGetMinX(_objectRect),
-CGRectGetMinY(_objectRect));
CGAffineTransform transform = CGAffineTransformConcat(_absoluteTransform, trans);
CGContextSaveGState(ctx);
[self.gradient drawInContextRef:ctx
objectRect:_objectRect
absoluteTransform:transform
viewPort:self.viewBox];
CGContextRestoreGState(ctx);
}
@end
@@ -6,9 +6,9 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGLayer.h>
#import <IJSVG/IJSVGShapeLayer.h>
#import <QuartzCore/QuartzCore.h>
#import "IJSVGLayer.h"
#import "IJSVGShapeLayer.h"
@interface IJSVGGroupLayer : IJSVGLayer
@@ -6,14 +6,14 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGLayer.h>
#import <AppKit/AppKit.h>
#import <QuartzCore/QuartzCore.h>
#import "IJSVGLayer.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,18 +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
@@ -0,0 +1,45 @@
//
// IJSVGLayer.h
// IJSVGExample
//
// Created by Curtis Hard on 07/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGRendering.h>
#import <IJSVG/IJSVGTransaction.h>
#import <QuartzCore/QuartzCore.h>
@class IJSVGShapeLayer;
@class IJSVGGradientLayer;
@class IJSVGPatternLayer;
@class IJSVGStrokeLayer;
@class IJSVGGroupLayer;
@interface IJSVGLayer : CALayer {
@private
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) 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, BOOL* stop))block;
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer*)sublayer
withOffset:(CGPoint)offset;
@end
@@ -0,0 +1,166 @@
//
// IJSVGLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 07/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGGroupLayer.h"
#import "IJSVGLayer.h"
#import "IJSVGShapeLayer.h"
@implementation IJSVGLayer
- (void)dealloc
{
(void)([_maskingLayer release]), _maskingLayer = nil;
[super dealloc];
}
+ (NSArray*)deepestSublayersOfLayer:(CALayer*)layer
{
NSMutableArray* arr = [[[NSMutableArray alloc] init] autorelease];
for (CALayer* subLayer in layer.sublayers) {
if (subLayer.sublayers.count != 0) {
NSArray* moreLayers = [self deepestSublayersOfLayer:(IJSVGLayer*)subLayer];
[arr addObjectsFromArray:moreLayers];
} else {
[arr addObject:subLayer];
}
}
return arr;
}
+ (void)recursivelyWalkLayer:(CALayer*)layer
withBlock:(void (^)(CALayer* layer, BOOL isMask, BOOL* stop))block
{
// call for layer and mask if there is one
BOOL stop = NO;
block(layer, NO, &stop);
if(stop == YES) {
return;
}
// do the mask too!
if (layer.mask != nil) {
block(layer.mask, YES, &stop);
if(stop == YES) {
return;
}
}
// sublayers!!
for (CALayer* aLayer in layer.sublayers) {
[self recursivelyWalkLayer:aLayer
withBlock:block];
}
}
- (void)setBackingScaleFactor:(CGFloat)newFactor
{
if (_backingScaleFactor == newFactor) {
return;
}
_backingScaleFactor = newFactor;
self.contentsScale = newFactor;
self.rasterizationScale = newFactor;
[self setNeedsDisplay];
}
- (void)_customRenderInContext:(CGContextRef)ctx
{
if (_convertMasksToPaths == YES && _maskingLayer != nil) {
CGContextSaveGState(ctx);
[self applySublayerMaskToContext:ctx
forSublayer:(IJSVGLayer*)self
withOffset:CGPointZero];
[super renderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[super renderInContext:ctx];
}
- (void)setConvertMasksToPaths:(BOOL)flag
{
if (_convertMasksToPaths == flag) {
return;
}
_convertMasksToPaths = flag;
if (flag == YES) {
if (_maskingLayer != nil) {
(void)([_maskingLayer release]), _maskingLayer = nil;
}
_maskingLayer = [(IJSVGLayer*)self.mask retain];
self.mask = nil;
} else {
self.mask = _maskingLayer;
(void)([_maskingLayer release]), _maskingLayer = nil;
}
}
- (void)applySublayerMaskToContext:(CGContextRef)context
forSublayer:(IJSVGLayer*)sublayer
withOffset:(CGPoint)offset
{
// apply any transforms needed
CGPoint layerOffset = offset;
CGAffineTransform sublayerTransform = CATransform3DGetAffineTransform(sublayer.transform);
CGContextConcatCTM(context, CGAffineTransformInvert(sublayerTransform));
// walk up the superlayer chain
CALayer* superlayer = self.superlayer;
if (IJSVGIsSVGLayer(superlayer) == YES) {
[(IJSVGLayer*)superlayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer*)self
withOffset:layerOffset];
}
// grab the masking layer
IJSVGShapeLayer* maskingLayer = [self maskingLayer];
// if its a group we need to get the lowest level children
// and walk up the chain again
if ([maskingLayer isKindOfClass:[IJSVGGroupLayer class]]) {
NSArray* subs = [IJSVGLayer deepestSublayersOfLayer:maskingLayer];
for (IJSVGLayer* subLayer in subs) {
[subLayer applySublayerMaskToContext:context
forSublayer:(IJSVGLayer*)self
withOffset:layerOffset];
}
} else if ([maskingLayer isKindOfClass:[IJSVGShapeLayer class]]) {
// is a shape, go for it!
CGPathRef maskPath = maskingLayer.path;
CGContextTranslateCTM(context, -layerOffset.x, -layerOffset.y);
CGContextAddPath(context, maskPath);
CGContextClip(context);
CGContextTranslateCTM(context, layerOffset.x, layerOffset.y);
}
CGContextConcatCTM(context, sublayerTransform);
}
- (IJSVGShapeLayer*)maskingLayer
{
return (IJSVGShapeLayer*)_maskingLayer ?: nil;
}
- (void)renderInContext:(CGContextRef)ctx
{
if (_blendingMode != kCGBlendModeNormal) {
CGContextSaveGState(ctx);
CGContextSetBlendMode(ctx, _blendingMode);
[self _customRenderInContext:ctx];
CGContextRestoreGState(ctx);
return;
}
[self _customRenderInContext:ctx];
}
- (id<CAAction>)actionForKey:(NSString*)event
{
return nil;
}
@end
@@ -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
@@ -10,54 +10,53 @@
@implementation IJSVGPatternLayer
@synthesize pattern;
@synthesize patternNode;
- (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 * _patternNode.width.value),
roundf(rect.size.height * _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,37 @@
//
// IJSVGShapeLayer.h
// IJSVGExample
//
// Created by Curtis Hard on 07/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGLayer.h>
#import <IJSVG/IJSVGUtils.h>
#import <QuartzCore/QuartzCore.h>
@interface IJSVGShapeLayer : CAShapeLayer {
@private
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) 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
withOffset:(CGPoint)offset;
@end
@@ -0,0 +1,137 @@
//
// IJSVGShapeLayer.m
// IJSVGExample
//
// Created by Curtis Hard on 07/01/2017.
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGGroupLayer.h"
#import "IJSVGShapeLayer.h"
@implementation IJSVGShapeLayer
- (void)dealloc
{
(void)([_maskingLayer release]), _maskingLayer = nil;
[super dealloc];
}
- (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];
}
- (CGPoint)absoluteOrigin
{
CGPoint point = CGPointZero;
CALayer* pLayer = self;
while (pLayer != nil) {
point.x += pLayer.frame.origin.x;
point.y += pLayer.frame.origin.y;
pLayer = pLayer.superlayer;
}
return point;
}
- (id<CAAction>)actionForKey:(NSString*)event
{
return nil;
}
@end
@@ -6,16 +6,16 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <Foundation/Foundation.h>
#import "IJSVGNode.h"
@interface IJSVGDef : IJSVGNode {
@interface IJSVGDef : NSObject {
@private
NSMutableDictionary * _dict;
NSMutableDictionary* _dict;
}
- (void)addDef:(IJSVGNode *)aDef;
- (void)addDef:(IJSVGNode*)aDef;
- (IJSVGDef*)defForID:(NSString*)anID;
@end
@@ -12,30 +12,29 @@
- (void)dealloc
{
[_dict release], _dict = nil;
(void)([_dict release]), _dict = nil;
[super dealloc];
}
- (id)init
{
if( ( self = [super initWithDef:NO] ) != nil ) {
if ((self = [super init]) != 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];
_dict[aDef.identifier] = aDef;
}
- (IJSVGDef *)defForID:(NSString *)anID
- (IJSVGDef*)defForID:(NSString*)anID
{
return [_dict objectForKey:anID];
return _dict[anID];
}
@end
@@ -7,14 +7,11 @@
//
#import <Foundation/Foundation.h>
#import "IJSVGNode.h"
#import <IJSVG/IJSVGNode.h>
@interface IJSVGForeignObject : IJSVGNode {
NSString * requiredExtension;
}
@property ( nonatomic, copy ) NSString * requiredExtension;
@property (nonatomic, copy) NSString* requiredExtension;
@end
@@ -10,11 +10,9 @@
@implementation IJSVGForeignObject
@synthesize requiredExtension;
- (void)dealloc
{
[requiredExtension release], requiredExtension = nil;
(void)([_requiredExtension release]), _requiredExtension = nil;
[super dealloc];
}
@@ -0,0 +1,41 @@
//
// IJSVGGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColorList.h>
#import <IJSVG/IJSVGDef.h>
#import <IJSVG/IJSVGTransform.h>
#import <IJSVG/IJSVGGroup.h>
#import <Foundation/Foundation.h>
@interface IJSVGGradient : IJSVGGroup
@property (nonatomic, retain) NSGradient* gradient;
@property (nonatomic, assign) CGGradientRef CGGradient;
@property (nonatomic, retain) IJSVGUnitLength* x1;
@property (nonatomic, retain) IJSVGUnitLength* x2;
@property (nonatomic, retain) IJSVGUnitLength* y1;
@property (nonatomic, retain) IJSVGUnitLength* y2;
@property (nonatomic, retain) IJSVGColorList* colorList;
+ (CGFloat*)computeColorStops:(IJSVGGradient*)gradient
colors:(NSArray**)someColors;
- (CGGradientRef)CGGradient;
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox;
- (void)_debugStart:(CGPoint)startPoint
end:(CGPoint)endPoint
context:(CGContextRef)ctx;
- (IJSVGColorList*)colorList;
- (IJSVGColorList*)computedColorList;
@end
@@ -0,0 +1,141 @@
//
// IJSVGGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGradient.h"
#import "IJSVGParser.h"
@implementation IJSVGGradient
@synthesize colorList = _privateColorList;
- (void)dealloc
{
(void)([_x1 release]), _x1 = nil;
(void)([_x2 release]), _x2 = nil;
(void)([_y1 release]), _y1 = nil;
(void)([_y2 release]), _y2 = nil;
(void)([_gradient release]), _gradient = nil;
(void)([_privateColorList release]), _privateColorList = nil;
if (_CGGradient != nil) {
CGGradientRelease(_CGGradient);
}
[super dealloc];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGGradient* clone = [super copyWithZone:zone];
clone.gradient = [[self.gradient copy] autorelease];
return clone;
}
- (void)setColorList:(IJSVGColorList*)list
{
(void)([_privateColorList release]), _privateColorList = nil;
_privateColorList = list.retain;
if (_CGGradient != nil) {
CGGradientRelease(_CGGradient);
}
}
+ (CGFloat *)computeColorStops:(IJSVGGradient*)gradient
colors:(NSArray**)someColors
{
NSArray<IJSVGNode*>* stops = gradient.childNodes;
NSMutableArray* colors = [[[NSMutableArray alloc] initWithCapacity:stops.count] autorelease];
CGFloat* stopsParams = (CGFloat*)malloc(stops.count * sizeof(CGFloat));
NSInteger i = 0;
for(IJSVGNode* stopNode in stops) {
NSColor* color = stopNode.fillColor;
CGFloat opacity = stopNode.fillOpacity.value;
CGFloat offset = stopNode.offset.value;
stopsParams[i++] = offset;
if(color == nil) {
color = [IJSVGColor colorFromHEXInteger:0x000000];
if(opacity != 1.f) {
color = [IJSVGColor changeAlphaOnColor:color
to:opacity];
}
}
[colors addObject:color];
}
*someColors = (NSArray*)colors;
return stopsParams;
}
- (IJSVGColorList*)colorList
{
IJSVGColorList* sheet = [[[IJSVGColorList alloc] init] autorelease];
NSInteger num = self.gradient.numberOfColorStops;
for (NSInteger i = 0; i < num; i++) {
NSColor* color;
[self.gradient getColor:&color
location:nil
atIndex:i];
IJSVGColorType* type = [IJSVGColorType typeWithColor:color
flags:IJSVGColorTypeFlagStop];
[sheet addColor:type];
}
return sheet;
}
- (IJSVGColorList*)computedColorList
{
return _privateColorList;
}
- (CGGradientRef)CGGradient
{
// store it in the cache
if (_CGGradient != nil) {
return _CGGradient;
}
// actually create the gradient
NSInteger num = self.gradient.numberOfColorStops;
CGFloat* locations = malloc(sizeof(CGFloat) * num);
CFMutableArrayRef colors = CFArrayCreateMutable(kCFAllocatorDefault, (CFIndex)num,
&kCFTypeArrayCallBacks);
for (NSInteger i = 0; i < num; i++) {
NSColor* color;
[self.gradient getColor:&color
location:&locations[i]
atIndex:i];
if (_privateColorList != nil) {
color = [_privateColorList proposedColorForColor:color];
}
CFArrayAppendValue(colors, color.CGColor);
}
CGGradientRef result = CGGradientCreateWithColors(self.gradient.colorSpace.CGColorSpace,
colors, locations);
CFRelease(colors);
free(locations);
return _CGGradient = result;
}
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox
{
}
- (void)_debugStart:(CGPoint)startPoint
end:(CGPoint)endPoint
context:(CGContextRef)ctx
{
CGContextSaveGState(ctx);
CGContextSetStrokeColorWithColor(ctx, NSColor.blackColor.CGColor);
CGContextSetLineWidth(ctx, 1.f);
CGContextMoveToPoint(ctx, startPoint.x, startPoint.y);
CGContextAddLineToPoint(ctx, endPoint.x, endPoint.y);
CGContextStrokePath(ctx);
}
@end
@@ -6,18 +6,18 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <IJSVG/IJSVGPath.h>
#import <Foundation/Foundation.h>
#import "IJSVGNode.h"
#import "IJSVGPath.h"
@interface IJSVGGroup : IJSVGNode {
NSMutableArray * children;
@private
NSMutableArray<IJSVGNode*>* _childNodes;
}
- (void)addChild:(id)child;
- (NSArray *)children;
- (void)addChild:(IJSVGNode*)child;
- (NSArray<IJSVGNode*>*)childNodes;
- (void)purgeChildren;
@end
@@ -0,0 +1,71 @@
//
// IJSVGGroup.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGroup.h"
@implementation IJSVGGroup
- (void)dealloc
{
(void)([_childNodes release]), _childNodes = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_childNodes = [[NSMutableArray alloc] init];
}
return self;
}
- (void)prepareFromCopy
{
if(_childNodes != nil) {
(void)[_childNodes release], _childNodes = nil;
}
_childNodes = [[NSMutableArray alloc] init];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGGroup* node = [super copyWithZone:zone];
[node prepareFromCopy];
for (IJSVGNode* childNode in _childNodes) {
childNode = [[childNode copy] autorelease];
childNode.parentNode = node;
[node addChild:childNode];
}
return node;
}
- (void)purgeChildren
{
[_childNodes removeAllObjects];
}
- (void)addChild:(IJSVGNode*)child
{
if (child != nil) {
[_childNodes addObject:child];
}
}
- (NSArray<IJSVGNode*>*)childNodes
{
return _childNodes;
}
- (NSString*)description
{
return [NSString stringWithFormat:@"%@ - %@",
[super description], self.childNodes];
}
@end
@@ -6,22 +6,22 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <Foundation/Foundation.h>
#import "IJSVGNode.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)loadFromString:(NSString*)encodedString;
- (void)loadFromURL:(NSURL*)aURL;
@end
@@ -0,0 +1,117 @@
//
// IJSVGImage.m
// IJSVGExample
//
// Created by Curtis Hard on 28/05/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVGImage.h"
#import "IJSVGPath.h"
#import "IJSVGTransform.h"
@implementation IJSVGImage
- (void)dealloc
{
(void)(CGImageRelease(CGImage)), CGImage = nil;
(void)([imagePath release]), imagePath = nil;
(void)([image release]), image = nil;
[super dealloc];
}
- (void)loadFromString:(NSString*)encodedString
{
if ([encodedString hasPrefix:@"data:"]) {
encodedString = [encodedString stringByReplacingOccurrencesOfString:@"\\s+"
withString:@""
options:NSRegularExpressionSearch
range:NSMakeRange(0, encodedString.length)];
}
NSURL* url = [NSURL URLWithString:encodedString];
if(url != nil) {
[self loadFromURL:url];
}
}
- (void)loadFromURL:(NSURL*)aURL
{
NSData* data = [NSData dataWithContentsOfURL:aURL];
// no data, just ignore...invalid probably
if (data == nil) {
return;
}
// set the image against the container
NSImage* anImage = [[[NSImage alloc] initWithData:data] autorelease];
[self setImage:anImage];
}
- (IJSVGPath*)path
{
if (imagePath == nil) {
// lazy load the path as it might not be needed
imagePath = [[IJSVGPath alloc] init];
CGRect rect = CGRectMake(0.f, 0.f, self.width.value, self.height.value);
CGPathAddRect(imagePath.path, NULL, rect);
[imagePath close];
}
return imagePath;
}
- (void)setImage:(NSImage*)anImage
{
if (image != nil) {
(void)([image release]), image = nil;
}
image = [anImage retain];
if (CGImage != nil) {
CGImageRelease(CGImage);
CGImage = nil;
}
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);
}
- (CGImageRef)CGImage
{
return CGImage;
}
- (void)drawInContextRef:(CGContextRef)context
path:(IJSVGPath*)path
{
// run the transforms
// draw the image
if (self.width.value == 0.f || self.height.value == 0.f) {
return;
}
// make sure path is set
if (path == nil) {
path = [self path];
}
CGRect rect = path.pathBoundingBox;
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);
CGContextScaleCTM(context, 1.f, -1.f);
CGContextDrawImage(context, bounds, CGImage);
}
CGContextRestoreGState(context);
}
@end
@@ -0,0 +1,17 @@
//
// IJSVGGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGGradient.h>
#import <Foundation/Foundation.h>
@interface IJSVGLinearGradient : IJSVGGradient
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGLinearGradient*)aGradient;
@end
@@ -0,0 +1,85 @@
//
// IJSVGGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGLinearGradient.h"
#import "IJSVGUtils.h"
#import "IJSVGParser.h"
@implementation IJSVGLinearGradient
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGLinearGradient*)aGradient
{
// just ask unit for the value
NSString* x1 = ([element attributeForName:IJSVGAttributeX1].stringValue ?: @"0");
NSString* x2 = ([element attributeForName:IJSVGAttributeX2].stringValue ?: @"100%");
NSString* y1 = ([element attributeForName:IJSVGAttributeY1].stringValue ?: @"0");
NSString* y2 = ([element attributeForName:IJSVGAttributeY2].stringValue ?: @"0");
aGradient.x1 = [IJSVGGradientUnitLength unitWithString:x1 fromUnitType:aGradient.units];
aGradient.x2 = [IJSVGGradientUnitLength unitWithString:x2 fromUnitType:aGradient.units];
aGradient.y1 = [IJSVGGradientUnitLength unitWithString:y1 fromUnitType:aGradient.units];
aGradient.y2 = [IJSVGGradientUnitLength unitWithString:y2 fromUnitType:aGradient.units];
// compute the color stops and colours
NSArray* colors = nil;
CGFloat* stopsParams = [self.class computeColorStops:aGradient
colors:&colors];
// create the gradient with the colours
NSGradient* grad = [[NSGradient alloc] initWithColors:colors
atLocations:stopsParams
colorSpace:IJSVGColor.defaultColorSpace];
free(stopsParams);
return [grad autorelease];
}
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox
{
BOOL inUserSpace = self.units == IJSVGUnitUserSpaceOnUse;
CGPoint gradientStartPoint = CGPointZero;
CGPoint gradientEndPoint = CGPointZero;
CGAffineTransform selfTransform = IJSVGConcatTransforms(self.transforms);
CGRect boundingBox = inUserSpace ? viewBox : objectRect;
// make sure we apply the absolute position to
// transform us back into the correct space
if (inUserSpace == YES) {
CGContextConcatCTM(ctx, absoluteTransform);
}
CGFloat width = CGRectGetWidth(boundingBox);
CGFloat height = CGRectGetHeight(boundingBox);
gradientStartPoint = CGPointMake([self.x1 computeValue:width],
[self.y1 computeValue:height]);
gradientEndPoint = CGPointMake([self.x2 computeValue:width],
[self.y2 computeValue:height]);
// transform the context
CGContextConcatCTM(ctx, selfTransform);
// draw the gradient
CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawLinearGradient(ctx, self.CGGradient, gradientStartPoint,
gradientEndPoint, options);
#ifdef IJSVG_DEBUG
[self _debugStart:gradientStartPoint
end:gradientEndPoint
context:ctx];
#endif
}
@end
@@ -0,0 +1,159 @@
//
// IJSVGNode.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGStyle.h>
#import <IJSVG/IJSVGUnitLength.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@class IJSVGNode;
@class IJSVG;
@class IJSVGGroup;
@class IJSVGDef;
@class IJSVGGradient;
@class IJSVGGroup;
@class IJSVGPattern;
@class IJSVGTransform;
typedef void (^IJSVGNodeWalkHandler)(IJSVGNode* node, BOOL* allowChildNodes, BOOL* stop);
typedef NS_ENUM(NSInteger, IJSVGNodeType) {
IJSVGNodeTypeGroup,
IJSVGNodeTypePath,
IJSVGNodeTypeDef,
IJSVGNodeTypePolygon,
IJSVGNodeTypePolyline,
IJSVGNodeTypeRect,
IJSVGNodeTypeLine,
IJSVGNodeTypeCircle,
IJSVGNodeTypeEllipse,
IJSVGNodeTypeUse,
IJSVGNodeTypeLinearGradient,
IJSVGNodeTypeRadialGradient,
IJSVGNodeTypeClipPath,
IJSVGNodeTypeFont,
IJSVGNodeTypeGlyph,
IJSVGNodeTypeMask,
IJSVGNodeTypeImage,
IJSVGNodeTypePattern,
IJSVGNodeTypeSVG,
IJSVGNodeTypeText,
IJSVGNodeTypeTextSpan,
IJSVGNodeTypeStyle,
IJSVGNodeTypeSwitch,
IJSVGNodeTypeTitle,
IJSVGNodeTypeDesc,
IJSVGNodeTypeStop,
IJSVGNodeTypeNotFound,
};
typedef NS_ENUM(NSInteger, IJSVGWindingRule) {
IJSVGWindingRuleNonZero,
IJSVGWindingRuleEvenOdd,
IJSVGWindingRuleInherit
};
typedef NS_ENUM(NSInteger, IJSVGLineCapStyle) {
IJSVGLineCapStyleNone,
IJSVGLineCapStyleButt,
IJSVGLineCapStyleRound,
IJSVGLineCapStyleSquare,
IJSVGLineCapStyleInherit
};
typedef NS_ENUM(NSInteger, IJSVGLineJoinStyle) {
IJSVGLineJoinStyleNone,
IJSVGLineJoinStyleMiter,
IJSVGLineJoinStyleRound,
IJSVGLineJoinStyleBevel,
IJSVGLineJoinStyleInherit
};
typedef NS_OPTIONS(NSInteger, IJSVGFontTraits) {
IJSVGFontTraitNone = 1 << 0,
IJSVGFontTraitBold = 1 << 1,
IJSVGFontTraitItalic = 1 << 2
};
typedef NS_ENUM(NSInteger, IJSVGBlendMode) {
IJSVGBlendModeNormal = kCGBlendModeNormal,
IJSVGBlendModeMultiply = kCGBlendModeMultiply,
IJSVGBlendModeScreen = kCGBlendModeScreen,
IJSVGBlendModeOverlay = kCGBlendModeOverlay,
IJSVGBlendModeDarken = kCGBlendModeDarken,
IJSVGBlendModeLighten = kCGBlendModeLighten,
IJSVGBlendModeColorDodge = kCGBlendModeColorDodge,
IJSVGBlendModeColorBurn = kCGBlendModeColorBurn,
IJSVGBlendModeHardLight = kCGBlendModeHardLight,
IJSVGBlendModeSoftLight = kCGBlendModeSoftLight,
IJSVGBlendModeDifference = kCGBlendModeDifference,
IJSVGBlendModeExclusion = kCGBlendModeExclusion,
IJSVGBlendModeHue = kCGBlendModeHue,
IJSVGBlendModeSaturation = kCGBlendModeSaturation,
IJSVGBlendModeColor = kCGBlendModeColor,
IJSVGBlendModeLuminosity = kCGBlendModeLuminosity
};
static CGFloat IJSVGInheritedFloatValue = -99.9999991;
@interface IJSVGNode : NSObject <NSCopying>
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* desc;
@property (nonatomic, assign) IJSVGNodeType type;
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* className;
@property (nonatomic, retain) NSArray* classNameList;
@property (nonatomic, copy) NSString* unicode;
@property (nonatomic, assign) BOOL shouldRender;
@property (nonatomic, assign) BOOL usesDefaultFillColor;
@property (nonatomic, retain) IJSVGUnitLength* x;
@property (nonatomic, retain) IJSVGUnitLength* y;
@property (nonatomic, retain) IJSVGUnitLength* width;
@property (nonatomic, retain) IJSVGUnitLength* height;
@property (nonatomic, retain) IJSVGUnitLength* opacity;
@property (nonatomic, retain) IJSVGUnitLength* fillOpacity;
@property (nonatomic, retain) IJSVGUnitLength* strokeOpacity;
@property (nonatomic, retain) IJSVGUnitLength* strokeWidth;
@property (nonatomic, retain) IJSVGUnitLength* offset;
@property (nonatomic, retain) NSColor* fillColor;
@property (nonatomic, retain) NSColor* strokeColor;
@property (nonatomic, copy) NSString* identifier;
@property (nonatomic, assign) IJSVGNode* parentNode;
@property (nonatomic, assign) IJSVGNode* intermediateParentNode;
@property (nonatomic, retain) IJSVGGroup* clipPath;
@property (nonatomic, retain) IJSVGGroup* mask;
@property (nonatomic, assign) IJSVGWindingRule windingRule;
@property (nonatomic, assign) IJSVGLineCapStyle lineCapStyle;
@property (nonatomic, assign) IJSVGLineJoinStyle lineJoinStyle;
@property (nonatomic, retain) NSArray<IJSVGTransform*>* transforms;
@property (nonatomic, retain) IJSVGDef* def;
@property (nonatomic, retain) IJSVGGradient* fillGradient;
@property (nonatomic, retain) IJSVGPattern* fillPattern;
@property (nonatomic, retain) IJSVGGradient* strokeGradient;
@property (nonatomic, retain) IJSVGPattern* strokePattern;
@property (nonatomic, assign) CGFloat* strokeDashArray;
@property (nonatomic, assign) NSInteger strokeDashArrayCount;
@property (nonatomic, retain) IJSVGUnitLength* strokeDashOffset;
@property (nonatomic, retain) IJSVG* svg;
@property (nonatomic, assign) IJSVGUnitType contentUnits;
@property (nonatomic, assign) IJSVGUnitType units;
@property (nonatomic, assign) IJSVGBlendMode blendMode;
+ (void)walkNodeTree:(IJSVGNode*)node
handler:(IJSVGNodeWalkHandler)handler;
+ (IJSVGNodeType)typeForString:(NSString*)string
kind:(NSXMLNodeKind)kind;
- (void)applyPropertiesFromNode:(IJSVGNode*)node;
- (id)initWithDef:(BOOL)flag;
- (void)addDef:(IJSVGNode*)aDef;
- (IJSVGDef*)defForID:(NSString*)anID;
@end
@@ -0,0 +1,427 @@
//
// IJSVGNode.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGDef.h"
#import "IJSVGNode.h"
#import "IJSVGUtils.h"
#import "IJSVGGroup.h"
@implementation IJSVGNode
- (void)dealloc
{
(void)free(_strokeDashArray), _strokeDashArray = NULL;
(void)([_x release]), _x = nil;
(void)([_y release]), _y = nil;
(void)([_width release]), _width = nil;
(void)([_height release]), _height = nil;
(void)([_opacity release]), _opacity = nil;
(void)([_offset release]), _offset = nil;
(void)([_fillOpacity release]), _fillOpacity = nil;
(void)([_strokeOpacity release]), _strokeOpacity = nil;
(void)([_strokeWidth release]), _strokeWidth = nil;
(void)([_strokeDashOffset release]), _strokeDashOffset = nil;
(void)([_unicode release]), _unicode = nil;
(void)([_fillGradient release]), _fillGradient = nil;
(void)([_strokeGradient release]), _strokeGradient = nil;
(void)([_strokePattern release]), _strokePattern = nil;
(void)([_transforms release]), _transforms = nil;
(void)([_fillColor release]), _fillColor = nil;
(void)([_strokeColor release]), _strokeColor = nil;
(void)([_identifier release]), _identifier = nil;
(void)([_def release]), _def = nil;
(void)([_name release]), _name = nil;
(void)([_title release]), _title = nil;
(void)([_desc release]), _desc = nil;
(void)([_className release]), _className = nil;
(void)([_classNameList release]), _classNameList = nil;
(void)([_fillPattern release]), _fillPattern = nil;
(void)([_clipPath release]), _clipPath = nil;
(void)([_svg release]), _svg = nil;
(void)([_mask release]), _mask = nil;
[super dealloc];
}
+ (IJSVGNodeType)typeForString:(NSString*)string
kind:(NSXMLNodeKind)kind
{
const char* name = string.UTF8String;
if(name == NULL) {
return IJSVGNodeTypeNotFound;
}
IJSVGCharBufferToLower((char*)name);
if (strcmp(name, "style") == 0) {
return IJSVGNodeTypeStyle;
}
if (strcmp(name, "switch") == 0) {
return IJSVGNodeTypeSwitch;
}
if (strcmp(name, "defs") == 0) {
return IJSVGNodeTypeDef;
}
if (strcmp(name, "g") == 0) {
return IJSVGNodeTypeGroup;
}
if (strcmp(name, "path") == 0) {
return IJSVGNodeTypePath;
}
if (strcmp(name, "polygon") == 0) {
return IJSVGNodeTypePolygon;
}
if (strcmp(name, "polyline") == 0) {
return IJSVGNodeTypePolyline;
}
if (strcmp(name, "rect") == 0) {
return IJSVGNodeTypeRect;
}
if (strcmp(name, "line") == 0) {
return IJSVGNodeTypeLine;
}
if (strcmp(name, "circle") == 0) {
return IJSVGNodeTypeCircle;
}
if (strcmp(name, "ellipse") == 0) {
return IJSVGNodeTypeEllipse;
}
if (strcmp(name, "use") == 0) {
return IJSVGNodeTypeUse;
}
if (strcmp(name, "lineargradient") == 0) {
return IJSVGNodeTypeLinearGradient;
}
if (strcmp(name, "radialgradient") == 0) {
return IJSVGNodeTypeRadialGradient;
}
if(strcmp(name, "stop") == 0) {
return IJSVGNodeTypeStop;
}
if (strcmp(name, "glyph") == 0) {
return IJSVGNodeTypeGlyph;
}
if (strcmp(name, "font") == 0) {
return IJSVGNodeTypeFont;
}
if (strcmp(name, "clippath") == 0) {
return IJSVGNodeTypeClipPath;
}
if (strcmp(name, "mask") == 0) {
return IJSVGNodeTypeMask;
}
if (strcmp(name, "image") == 0) {
return IJSVGNodeTypeImage;
}
if (strcmp(name, "pattern") == 0) {
return IJSVGNodeTypePattern;
}
if (strcmp(name, "svg") == 0) {
return IJSVGNodeTypeSVG;
}
if (strcmp(name, "text") == 0) {
return IJSVGNodeTypeText;
}
if (strcmp(name, "tspan") == 0 || kind == NSXMLTextKind) {
return IJSVGNodeTypeTextSpan;
}
if(strcmp(name, "title") == 0) {
return IJSVGNodeTypeTitle;
}
if(strcmp(name, "desc") == 0) {
return IJSVGNodeTypeDesc;
}
return IJSVGNodeTypeNotFound;
}
- (id)init
{
if ((self = [self initWithDef:YES]) != nil) {
self.opacity = [IJSVGUnitLength unitWithFloat:1];
}
return self;
}
+ (void)walkNodeTree:(IJSVGNode*)node
handler:(IJSVGNodeWalkHandler)handler
{
BOOL allowChildNodes = YES;
BOOL stop = NO;
[self _walkNodeTree:node
handler:handler
allowChildNodes:&allowChildNodes
stop:&stop];
}
+ (void)_walkNodeTree:(IJSVGNode*)node
handler:(IJSVGNodeWalkHandler)handler
allowChildNodes:(BOOL*)allowChildNodes
stop:(BOOL*)stop
{
// run the handler and instantly stop
// if stop is set
handler(node, allowChildNodes, stop);
if(*stop == YES) {
return;
}
// child nodes only work for nodes
// that are type group
if(*allowChildNodes == NO ||
[node isKindOfClass:IJSVGGroup.class] == NO) {
*allowChildNodes = YES;
return;
}
// iterate over the childnodes
IJSVGGroup* group = (IJSVGGroup*)node;
for(IJSVGNode* childNode in group.childNodes) {
[self _walkNodeTree:childNode
handler:handler
allowChildNodes:allowChildNodes
stop:stop];
if(*stop == YES) {
return;
}
}
}
- (void)applyPropertiesFromNode:(IJSVGNode*)node
{
self.title = node.title;
self.desc = node.desc;
self.name = node.name;
self.type = node.type;
self.unicode = node.unicode;
self.className = node.className;
self.classNameList = node.classNameList;
self.x = node.x;
self.y = node.y;
self.width = node.width;
self.height = node.height;
self.fillGradient = node.fillGradient;
self.fillPattern = node.fillPattern;
self.strokeGradient = node.strokeGradient;
self.strokePattern = node.strokePattern;
self.fillColor = node.fillColor;
self.strokeColor = node.strokeColor;
self.clipPath = node.clipPath;
self.units = node.units;
self.contentUnits = node.contentUnits;
self.opacity = node.opacity;
self.strokeWidth = node.strokeWidth;
self.fillOpacity = node.fillOpacity;
self.strokeOpacity = node.strokeOpacity;
self.identifier = node.identifier;
self.usesDefaultFillColor = node.usesDefaultFillColor;
self.transforms = node.transforms;
self.def = node.def;
self.windingRule = node.windingRule;
self.lineCapStyle = node.lineCapStyle;
self.lineJoinStyle = node.lineJoinStyle;
self.parentNode = node.parentNode;
self.shouldRender = node.shouldRender;
self.blendMode = node.blendMode;
// dash array needs physical memory copied
CGFloat* nStrokeDashArray = (CGFloat*)malloc(node.strokeDashArrayCount * sizeof(CGFloat));
memcpy(self.strokeDashArray, nStrokeDashArray, node.strokeDashArrayCount * sizeof(CGFloat));
self.strokeDashArray = nStrokeDashArray;
self.strokeDashArrayCount = node.strokeDashArrayCount;
self.strokeDashOffset = node.strokeDashOffset;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGNode* node = [self.class allocWithZone:zone];
[node applyPropertiesFromNode:self];
return node;
}
- (id)initWithDef:(BOOL)flag
{
if ((self = [super init]) != nil) {
self.opacity = [IJSVGUnitLength unitWithFloat:0.f];
self.fillOpacity = [IJSVGUnitLength unitWithFloat:1.f];
self.fillOpacity.inherit = YES;
self.strokeDashOffset = [IJSVGUnitLength unitWithFloat:0.f];
self.shouldRender = YES;
self.strokeOpacity = [IJSVGUnitLength unitWithFloat:1.f];
self.strokeOpacity.inherit = YES;
self.strokeWidth = [IJSVGUnitLength unitWithFloat:1.f];
self.strokeWidth.inherit = YES;
self.windingRule = IJSVGWindingRuleInherit;
self.lineCapStyle = IJSVGLineCapStyleInherit;
self.lineJoinStyle = IJSVGLineJoinStyleInherit;
self.units = IJSVGUnitInherit;
self.blendMode = IJSVGBlendModeNormal;
if (flag == YES) {
_def = [[IJSVGDef alloc] init];
}
}
return self;
}
- (IJSVGDef*)defForID:(NSString*)anID
{
IJSVGDef* aDef = nil;
if ((aDef = [_def defForID:anID]) != nil) {
return aDef;
}
if (_parentNode != nil) {
return [_parentNode defForID:anID];
}
return nil;
}
- (void)addDef:(IJSVGNode*)aDef
{
[_def addDef:aDef];
}
// winding rule can inherit..
- (IJSVGWindingRule)windingRule
{
if (_windingRule == IJSVGWindingRuleInherit && _parentNode != nil) {
return _parentNode.windingRule;
}
return _windingRule;
}
- (IJSVGLineCapStyle)lineCapStyle
{
if (_lineCapStyle == IJSVGLineCapStyleInherit) {
if (_parentNode != nil) {
return _parentNode.lineCapStyle;
}
}
return _lineCapStyle;
}
- (IJSVGLineJoinStyle)lineJoinStyle
{
if (_lineJoinStyle == IJSVGLineJoinStyleInherit) {
if (_parentNode != nil) {
return _parentNode.lineJoinStyle;
}
}
return _lineJoinStyle;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength*)opacity
{
if (_opacity.inherit && _parentNode != nil) {
return _parentNode.opacity;
}
return _opacity;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength*)fillOpacity
{
if (_fillOpacity.inherit && _parentNode != nil) {
return _parentNode.fillOpacity;
}
return _fillOpacity;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGUnitLength*)strokeWidth
{
if (_strokeWidth.inherit && _parentNode != nil) {
return _parentNode.strokeWidth;
}
return _strokeWidth;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (NSColor*)strokeColor
{
if (_strokeColor != nil)
return _strokeColor;
if (_strokeColor == nil && _parentNode != nil)
return _parentNode.strokeColor;
return nil;
}
- (IJSVGUnitLength*)strokeOpacity
{
if (_strokeOpacity.inherit && _parentNode != nil) {
return _parentNode.strokeOpacity;
}
return _strokeOpacity;
}
// even though the spec explicity states fill color
// must be on the path, it can also be on the
- (NSColor*)fillColor
{
if (_fillColor == nil && _parentNode != nil) {
return _parentNode.fillColor;
}
return _fillColor;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGGradient*)fillGradient
{
if (_fillGradient == nil && _parentNode != nil) {
return _parentNode.fillGradient;
}
return _fillGradient;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGPattern*)fillPattern
{
if (_fillPattern == nil && _parentNode != nil) {
return _parentNode.fillPattern;
}
return _fillPattern;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGGradient*)strokeGradient
{
if (_strokeGradient == nil && _parentNode != nil) {
return _parentNode.strokeGradient;
}
return _strokeGradient;
}
// these are all recursive, so go up the chain
// if they dont exist on this specific node
- (IJSVGPattern*)strokePattern
{
if (_strokePattern == nil && _parentNode != nil) {
return _parentNode.strokePattern;
}
return _strokePattern;
}
@end
@@ -0,0 +1,37 @@
//
// IJSVGPath.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <Foundation/Foundation.h>
@class IJSVGGroup;
typedef NS_ENUM(NSInteger, IJSVGPrimitivePathType) {
kIJSVGPrimitivePathTypePath,
kIJSVGPrimitivePathTypeRect,
kIJSVGPrimitivePathTypePolygon,
kIJSVGPrimitivePathTypePolyLine,
kIJSVGPrimitivePathTypeCircle,
kIJSVGPrimitivePathTypeEllipse,
kIJSVGPrimitivePathTypeLine
};
@interface IJSVGPath : IJSVGNode {
}
@property (nonatomic, assign) IJSVGPrimitivePathType primitiveType;
@property (nonatomic, assign) CGMutablePathRef path;
@property (nonatomic, assign) CGPoint lastControlPoint;
@property (nonatomic, readonly) CGRect controlPointBoundingBox;
@property (nonatomic, readonly) CGRect pathBoundingBox;
@property (nonatomic, assign, readonly) BOOL isStroked;
- (void)close;
- (NSPoint)currentPoint;
@end
@@ -0,0 +1,75 @@
//
// IJSVGPath.m
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGGroup.h"
#import "IJSVGPath.h"
@implementation IJSVGPath
- (void)dealloc
{
if(_path != NULL) {
(void)CGPathRelease(_path), _path = NULL;
}
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_primitiveType = kIJSVGPrimitivePathTypePath;
_path = CGPathCreateMutable();
}
return self;
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGPath* node = [super copyWithZone:zone];
node.path = _path;
return node;
}
- (void)setPath:(CGMutablePathRef)path
{
// this will automatically copy any path into a mutable path
// regardless of if it was a mutable path to begin with
if(_path != NULL) {
(void)CGPathRelease(_path), _path = NULL;
}
_path = CGPathCreateMutableCopy(path);
}
- (CGRect)pathBoundingBox
{
return CGPathGetPathBoundingBox(_path);
}
- (CGRect)controlPointBoundingBox
{
return CGPathGetBoundingBox(_path);
}
- (NSPoint)currentPoint
{
return CGPathGetCurrentPoint(_path);
}
- (void)close
{
CGPathCloseSubpath(_path);
}
- (BOOL)isStroked
{
return (self.strokeColor != nil && self.strokeColor.alphaComponent != 0.f) ||
self.strokePattern != nil ||
self.strokeGradient != nil;
}
@end
@@ -6,12 +6,11 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGGroup.h>
#import <IJSVG/IJSVGImage.h>
#import <Foundation/Foundation.h>
#import "IJSVGGroup.h"
#import "IJSVGImage.h"
@interface IJSVGPattern : IJSVGGroup {
}
@end
@@ -0,0 +1,23 @@
//
// IJSVGRadialGradient.h
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGGradient.h>
#import <Foundation/Foundation.h>
@interface IJSVGRadialGradient : IJSVGGradient
@property (nonatomic, retain) IJSVGUnitLength* cx;
@property (nonatomic, retain) IJSVGUnitLength* cy;
@property (nonatomic, retain) IJSVGUnitLength* fx;
@property (nonatomic, retain) IJSVGUnitLength* fy;
@property (nonatomic, retain) IJSVGUnitLength* radius;
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGRadialGradient*)gradient;
@end
@@ -0,0 +1,157 @@
//
// IJSVGRadialGradient.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGRadialGradient.h"
#import "IJSVGParser.h"
@implementation IJSVGRadialGradient
- (void)dealloc
{
(void)([_cx release]), _cx = nil;
(void)([_cy release]), _cy = nil;
(void)([_fx release]), _fx = nil;
(void)([_fy release]), _fy = nil;
(void)([_radius release]), _radius = nil;
[super dealloc];
}
- (id)copyWithZone:(NSZone*)zone
{
IJSVGRadialGradient* grad = [super copyWithZone:zone];
grad.fx = _fx;
grad.fy = _fy;
grad.cx = _cx;
grad.cy = _cy;
grad.radius = _radius;
return grad;
}
+ (NSGradient*)parseGradient:(NSXMLElement*)element
gradient:(IJSVGRadialGradient*)gradient
{
// cx defaults to 50% if not specified
NSDictionary* kv = @{
IJSVGAttributeCX : @"cx",
IJSVGAttributeCY : @"cy",
IJSVGAttributeR : @"radius" };
for (NSString* key in kv.allKeys) {
NSString* str = [element attributeForName:key].stringValue;
IJSVGUnitLength* unit = nil;
if (str != nil) {
unit = [IJSVGUnitLength unitWithString:str
fromUnitType:gradient.units];
} else {
// spec says to say 50% for missing property default
unit = [IJSVGUnitLength unitWithPercentageFloat:.5f];
}
[gradient setValue:unit
forKey:kv[key]];
}
// fx and fy are the same unless specified otherwise
gradient.fx = gradient.cx;
gradient.fy = gradient.cy;
// needs fixing
NSString* fx = [element attributeForName:IJSVGAttributeFX].stringValue;
if (fx != nil) {
gradient.fx = [IJSVGUnitLength unitWithString:fx
fromUnitType:gradient.units];
}
NSString* fy = [element attributeForName:IJSVGAttributeFY].stringValue;
if (fx != nil) {
gradient.fy = [IJSVGUnitLength unitWithString:fy
fromUnitType:gradient.units];
}
if (gradient.gradient != nil) {
return nil;
}
NSArray* colors = nil;
CGFloat* colorStops = [self.class computeColorStops:gradient
colors:&colors];
NSGradient* ret = [[[NSGradient alloc] initWithColors:colors
atLocations:colorStops
colorSpace:IJSVGColor.defaultColorSpace] autorelease];
free(colorStops);
return ret;
}
- (void)drawInContextRef:(CGContextRef)ctx
objectRect:(NSRect)objectRect
absoluteTransform:(CGAffineTransform)absoluteTransform
viewPort:(CGRect)viewBox
{
BOOL inUserSpace = self.units == IJSVGUnitUserSpaceOnUse;
CGFloat radius = 0.f;
CGPoint startPoint = CGPointZero;
CGPoint gradientStartPoint = CGPointZero;
CGPoint gradientEndPoint = CGPointZero;
// transforms
CGAffineTransform selfTransform = IJSVGConcatTransforms(self.transforms);
CGRect boundingBox = inUserSpace ? viewBox : objectRect;
// make sure we apply the absolute position to
// transform us back into the correct space
if (inUserSpace == YES) {
CGContextConcatCTM(ctx, absoluteTransform);
}
// compute size based on percentages
CGFloat x = [_cx computeValue:CGRectGetWidth(boundingBox)];
CGFloat y = [_cy computeValue:CGRectGetHeight(boundingBox)];
startPoint = CGPointMake(x, y);
CGFloat val = MIN(CGRectGetWidth(boundingBox),
CGRectGetHeight(boundingBox));
radius = [_radius computeValue:val];
CGFloat ex = [_fx computeValue:CGRectGetWidth(boundingBox)];
CGFloat ey = [_fy computeValue:CGRectGetHeight(boundingBox)];
gradientEndPoint = CGPointMake(ex, ey);
gradientStartPoint = startPoint;
// transform if width or height is not equal - this can only
// be done if we are using objectBoundingBox
if (inUserSpace == NO && CGRectGetWidth(boundingBox) != CGRectGetHeight(boundingBox)) {
CGAffineTransform tr = CGAffineTransformMakeTranslation(gradientStartPoint.x,
gradientStartPoint.y);
if (CGRectGetWidth(boundingBox) > CGRectGetHeight(boundingBox)) {
tr = CGAffineTransformScale(tr, CGRectGetWidth(boundingBox) / CGRectGetHeight(boundingBox), 1);
} else {
tr = CGAffineTransformScale(tr, 1.f, CGRectGetHeight(boundingBox) / CGRectGetWidth(boundingBox));
}
tr = CGAffineTransformTranslate(tr, -gradientStartPoint.x, -gradientStartPoint.y);
selfTransform = CGAffineTransformConcat(tr, selfTransform);
}
// transform the context
CGContextConcatCTM(ctx, selfTransform);
// draw the gradient
CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawRadialGradient(ctx, self.CGGradient,
gradientEndPoint, 0,
gradientStartPoint,
radius, options);
#ifdef IJSVG_DEBUG_GRADIENTS
[self _debugStart:gradientStartPoint
end:gradientEndPoint
context:ctx];
#endif
}
@end
@@ -6,14 +6,11 @@
// Copyright © 2017 Curtis Hard. All rights reserved.
//
#import "IJSVGGroup.h"
#import <IJSVG/IJSVGGroup.h>
@interface IJSVGText : IJSVGGroup {
NSString * text;
}
@property (nonatomic, copy) NSString * text;
@property (nonatomic, copy) NSString* text;
@end
@@ -10,18 +10,16 @@
@implementation IJSVGText
@synthesize text;
- (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];
node.text = self.text;
IJSVGText* node = [super copyWithZone:zone];
node.text = _text;
return node;
}
@@ -0,0 +1,42 @@
//
// IJSVGCommandParser.h
// IJSVG
//
// Created by Curtis Hard on 23/12/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import <Foundation/Foundation.h>
#include <xlocale.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, IJSVGPathDataSequence) {
kIJSVGPathDataSequenceTypeFloat,
kIJSVGPathDataSequenceTypeFlag
};
static NSUInteger const IJSVG_STREAM_FLOAT_BLOCK_SIZE = 50;
static NSUInteger const IJSVG_STREAM_CHAR_BLOCK_SIZE = 20;
typedef struct {
CGFloat* floatBuffer;
NSInteger floatCount;
char* charBuffer;
NSInteger charCount;
} IJSVGPathDataStream;
@interface IJSVGCommandParser : NSObject
IJSVGPathDataStream* IJSVGPathDataStreamCreateDefault(void);
IJSVGPathDataStream* IJSVGPathDataStreamCreate(NSUInteger floatCount, NSUInteger charCount);
void IJSVGPathDataStreamRelease(IJSVGPathDataStream* buffer);
IJSVGPathDataSequence* IJSVGPathDataSequenceCreateWithType(IJSVGPathDataSequence type, NSInteger length);
CGFloat* _Nullable IJSVGParsePathDataStreamSequence(const char* commandChars, NSInteger commandCharLength,
IJSVGPathDataStream* dataStream, IJSVGPathDataSequence* _Nullable sequence,
NSInteger commandLength, NSInteger* _Nullable commandsFound);
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,249 @@
//
// IJSVGCommandParser.m
// IJSVG
//
// Created by Curtis Hard on 23/12/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGCommandParser.h"
@implementation IJSVGCommandParser
#define VALID_DIGIT(c) ((c ^ '0') <= 9)
IJSVGPathDataSequence* IJSVGPathDataSequenceCreateWithType(IJSVGPathDataSequence type, NSInteger length)
{
size_t size = sizeof(IJSVGPathDataSequence) * length;
IJSVGPathDataSequence* sequence = (IJSVGPathDataSequence*)malloc(size);
memset(sequence, (int)type, size);
return sequence;
};
// Datastreams work by setting up one stream of bits/memory per SVG
// so that each SVG has a reusable memory block to read and parse paths into.
// As its all linear and one SVG per thread, this saves alot of memory allocation
// calls as we simple can just reuse the buffer that already exists - this also
// allows us to specify the default allocation size, so when parsing viewBox we
// can simply allocate (4*sizeof(CGFloat)) instead of the default 50 slots
IJSVGPathDataStream* IJSVGPathDataStreamCreateDefault(void)
{
return IJSVGPathDataStreamCreate(IJSVG_STREAM_FLOAT_BLOCK_SIZE,
IJSVG_STREAM_CHAR_BLOCK_SIZE);
}
IJSVGPathDataStream* IJSVGPathDataStreamCreate(NSUInteger floatCount, NSUInteger charCount)
{
floatCount = floatCount ?: IJSVG_STREAM_FLOAT_BLOCK_SIZE;
charCount = charCount ?: IJSVG_STREAM_CHAR_BLOCK_SIZE;
IJSVGPathDataStream* buffer = (IJSVGPathDataStream*)malloc(sizeof(IJSVGPathDataStream));
buffer->floatBuffer = (CGFloat*)malloc(sizeof(CGFloat) * floatCount);
buffer->floatCount = floatCount;
buffer->charBuffer = (char*)calloc(sizeof(char), charCount);
buffer->charCount = charCount;
return buffer;
}
void IJSVGPathDataStreamRelease(IJSVGPathDataStream* buffer)
{
free(buffer->charBuffer);
free(buffer->floatBuffer);
free(buffer);
};
CGFloat* _Nullable IJSVGParsePathDataStreamSequence(const char* commandChars, NSInteger commandCharLength,
IJSVGPathDataStream* dataStream, IJSVGPathDataSequence* _Nullable sequence,
NSInteger commandLength, NSInteger* _Nullable commandsFound)
{
// if no command length, its completely pointless function,
// so just return null and set commandsFound to 0, if we dont
// we get a arithmetic error later on due to zero
if (commandLength == 0) {
*commandsFound = 0;
return NULL;
}
// default memory size for the float
NSInteger i = 0;
NSInteger counter = 0;
const char* cString = commandChars;
const char* validChars = "+-.";
// this is much faster then doing strlen as it doesnt need
// to compute the length
NSInteger sLength = commandCharLength;
NSInteger sLengthMinusOne = sLength - 1;
bool isDecimal = false;
int bufferCount = 0;
while (i < sLength) {
char currentChar = *cString++;
// work out next char
char nextChar = (char)0;
if (i < sLengthMinusOne) {
nextChar = *cString++;
cString--;
}
// check for validator
bool isE = (currentChar | ('E' ^ 'e')) == 'e';
bool isValid = VALID_DIGIT(currentChar) || isE || strchr(validChars, currentChar) != NULL;
// in order to work out the split, its either because the next char is
// a hyphen or a plus, or next char is a decimal and the current number is a decimal
bool nIsSign = nextChar == '-' || nextChar == '+';
bool wantsEnd = nIsSign || (nextChar == '.' && isDecimal);
// work our what the sequence is...
IJSVGPathDataSequence seq = kIJSVGPathDataSequenceTypeFloat;
if (sequence != NULL) {
seq = sequence[counter % commandLength];
}
// is a flag, consists of one value
// if its invalid, make sure we free the memory
// and return null - or hell breaks lose
if (isValid == YES && seq == kIJSVGPathDataSequenceTypeFlag) {
if (bufferCount != 0 || (currentChar != '0' && currentChar != '1')) {
return NULL;
}
wantsEnd = YES;
}
// could be a float like 5.334e-5 so dont break on the hypen
if (wantsEnd && isE && nIsSign) {
wantsEnd = false;
}
// make sure its a valid string
if (isValid == YES) {
// alloc the buffer if needed
if ((bufferCount + 1) == dataStream->charCount) {
// realloc the buffer, incase the string is overflowing the
// allocated memory
dataStream->charCount += IJSVG_STREAM_CHAR_BLOCK_SIZE;
dataStream->charBuffer = (char*)realloc(dataStream->charBuffer,
sizeof(char) * dataStream->charCount);
}
// set the actual char against it
if (currentChar == '.') {
isDecimal = true;
}
dataStream->charBuffer[bufferCount++] = currentChar;
} else {
// if its an invalid char, just stop it
wantsEnd = true;
}
// is at end of string, or wants to be stopped
// buffer has to actually exist or its completly
// useless and will cause a crash
if (bufferCount != 0 && (wantsEnd || i == sLengthMinusOne)) {
// make sure there is enough room in the float pool
if ((counter + 1) == dataStream->floatCount) {
dataStream->floatCount += IJSVG_STREAM_FLOAT_BLOCK_SIZE;
dataStream->floatBuffer = (CGFloat*)realloc(dataStream->floatBuffer,
sizeof(CGFloat) * dataStream->floatCount);
}
// add the float - for performance reasons, we can simply set the
// null value of the end of the string instead of nulling out
// with memset \0 - huzzah!
dataStream->charBuffer[bufferCount] = '\0';
dataStream->floatBuffer[counter++] = IJSVGParseFloat(dataStream->charBuffer);
// reset
isDecimal = false;
bufferCount = 0;
}
i++;
}
// set commands found - only if there is one
if (commandsFound != NULL) {
*commandsFound = (NSInteger)round(counter / commandLength);
}
// allocate the new buffer from memory
CGFloat* floats = (CGFloat*)malloc(sizeof(CGFloat) * counter);
memcpy(floats, dataStream->floatBuffer, counter * sizeof(CGFloat));
// return the floats just set into the memory
return floats;
}
// this method is finely tuned to just handle the buffer
// that IJSVGParsePathDataSequence produces for each float
// it does not look or skip white space as the previous method
// handles this for us
// inspired and modified from http://www.leapsecond.com/tools/fast_atof.c
CGFloat IJSVGParseFloat(char* buffer)
{
int fraction;
double sign, value, scale;
// work out a sign, if any, might not be, who knows
sign = 1.f;
if (*buffer == '-') {
sign = -1.f;
buffer += 1;
} else if (*buffer == '+') {
buffer += 1;
}
// get numbers before decimal point or exponent
for (value = 0.f; VALID_DIGIT(*buffer); buffer += 1) {
value = value * 10.f + (*buffer - '0');
}
// get digits after decimal point
if (*buffer == '.') {
double pow10 = 10.f;
buffer += 1;
while (VALID_DIGIT(*buffer)) {
value += (*buffer - '0') / pow10;
pow10 *= 10.f;
buffer += 1;
}
}
// handle exponent
fraction = 0;
scale = 1.f;
if ((*buffer | ('E' ^ 'e')) == 'e') {
unsigned int exponent;
buffer += 1;
if (*buffer == '-') {
fraction = 1;
buffer += 1;
} else if (*buffer == '+') {
buffer += 1;
}
for (exponent = 0; VALID_DIGIT(*buffer); buffer += 1) {
exponent = exponent * 10 + (*buffer - '0');
}
if (exponent > 308) {
exponent = 308;
}
while (exponent >= 50) {
scale *= 1E50;
exponent -= 50;
}
while (exponent >= 8) {
scale *= 1E8;
exponent -= 8;
}
while (exponent > 0) {
scale *= 10.f;
exponent -= 1;
}
}
// make sure we cast this to a CGFloat before return
return (CGFloat)(sign * (fraction ? (value / scale) : (value * scale)));
}
@end
@@ -0,0 +1,136 @@
//
// IJSVGParser.h
// IconJar
//
// Created by Curtis Hard on 30/08/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColor.h>
#import <IJSVG/IJSVGCommand.h>
#import <IJSVG/IJSVGDef.h>
#import <IJSVG/IJSVGError.h>
#import <IJSVG/IJSVGForeignObject.h>
#import <IJSVG/IJSVGGroup.h>
#import <IJSVG/IJSVGImage.h>
#import <IJSVG/IJSVGLinearGradient.h>
#import <IJSVG/IJSVGPath.h>
#import <IJSVG/IJSVGPattern.h>
#import <IJSVG/IJSVGRadialGradient.h>
#import <IJSVG/IJSVGStyleSheet.h>
#import <IJSVG/IJSVGText.h>
#import <IJSVG/IJSVGTransform.h>
#import <IJSVG/IJSVGUnitRect.h>
#import <IJSVG/IJSVGUtils.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
extern NSString* const IJSVGAttributeViewBox;
extern NSString* const IJSVGAttributeID;
extern NSString* const IJSVGAttributeClass;
extern NSString* const IJSVGAttributeX;
extern NSString* const IJSVGAttributeY;
extern NSString* const IJSVGAttributeWidth;
extern NSString* const IJSVGAttributeHeight;
extern NSString* const IJSVGAttributeOpacity;
extern NSString* const IJSVGAttributeStrokeOpacity;
extern NSString* const IJSVGAttributeStrokeWidth;
extern NSString* const IJSVGAttributeStrokeDashOffset;
extern NSString* const IJSVGAttributeFillOpacity;
extern NSString* const IJSVGAttributeClipPath;
extern NSString* const IJSVGAttributeMask;
extern NSString* const IJSVGAttributeGradientUnits;
extern NSString* const IJSVGAttributeMaskUnits;
extern NSString* const IJSVGAttributeMaskContentUnits;
extern NSString* const IJSVGAttributeTransform;
extern NSString* const IJSVGAttributeGradientTransform;
extern NSString* const IJSVGAttributeUnicode;
extern NSString* const IJSVGAttributeStrokeLineCap;
extern NSString* const IJSVGAttributeLineJoin;
extern NSString* const IJSVGAttributeStroke;
extern NSString* const IJSVGAttributeStrokeDashArray;
extern NSString* const IJSVGAttributeFill;
extern NSString* const IJSVGAttributeFillRule;
extern NSString* const IJSVGAttributeBlendMode;
extern NSString* const IJSVGAttributeDisplay;
extern NSString* const IJSVGAttributeStyle;
extern NSString* const IJSVGAttributeD;
extern NSString* const IJSVGAttributeXLink;
extern NSString* const IJSVGAttributeX1;
extern NSString* const IJSVGAttributeX2;
extern NSString* const IJSVGAttributeY1;
extern NSString* const IJSVGAttributeY2;
extern NSString* const IJSVGAttributeRX;
extern NSString* const IJSVGAttributeRY;
extern NSString* const IJSVGAttributeCX;
extern NSString* const IJSVGAttributeCY;
extern NSString* const IJSVGAttributeR;
extern NSString* const IJSVGAttributeFX;
extern NSString* const IJSVGAttributeFY;
extern NSString* const IJSVGAttributePoints;
extern NSString* const IJSVGAttributeOffset;
extern NSString* const IJSVGAttributeStopColor;
extern NSString* const IJSVGAttributeStopOpacity;
extern NSString* const IJSVGAttributeHref;
@class IJSVGParser;
@protocol IJSVGParserDelegate <NSObject>
@optional
- (BOOL)svgParser:(IJSVGParser*)svg
shouldHandleForeignObject:(IJSVGForeignObject*)foreignObject;
- (void)svgParser:(IJSVGParser*)svg
handleForeignObject:(IJSVGForeignObject*)foreignObject
document:(NSXMLDocument*)document;
- (void)svgParser:(IJSVGParser*)svg
foundSubSVG:(IJSVG*)subSVG
withSVGString:(NSString*)string;
@end
@interface IJSVGParser : IJSVGGroup {
@private
id<IJSVGParserDelegate> _delegate;
NSXMLDocument* _document;
NSMutableArray<IJSVGPath*>* _glyphs;
IJSVGStyleSheet* _styleSheet;
NSMutableDictionary<NSString*, NSXMLElement*>* _defNodes;
NSMutableDictionary<NSString*, NSXMLElement*>* _baseDefNodes;
NSMutableArray<IJSVG*>* _svgs;
struct {
unsigned int shouldHandleForeignObject : 1;
unsigned int handleForeignObject : 1;
unsigned int handleSubSVG : 1;
} _respondsTo;
IJSVGPathDataStream* _commandDataStream;
}
@property (nonatomic, readonly) NSRect viewBox;
@property (nonatomic, readonly) IJSVGUnitSize* intrinsicSize;
+ (BOOL)isDataSVG:(NSData*)data;
- (id)initWithSVGString:(NSString*)string
error:(NSError**)error
delegate:(id<IJSVGParserDelegate>)delegate;
- (id)initWithFileURL:(NSURL*)aURL
error:(NSError**)error
delegate:(id<IJSVGParserDelegate>)delegate;
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL;
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL
delegate:(id<IJSVGParserDelegate>)delegate;
+ (IJSVGParser*)groupForFileURL:(NSURL*)aURL
error:(NSError**)error
delegate:(id<IJSVGParserDelegate>)delegate;
- (NSSize)size;
- (BOOL)isFont;
- (NSArray*)glyphs;
- (NSArray<IJSVG*>*)subSVGs:(BOOL)recursive;
@end
File diff suppressed because it is too large Load Diff
@@ -6,18 +6,18 @@
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGNode.h>
#import <IJSVG/IJSVGRenderingStyle.h>
#import <QuartzCore/QuartzCore.h>
#import "IJSVGNode.h"
@class IJSVGLayer;
@interface IJSVGLayerTree : NSObject {
}
@property (nonatomic, retain) NSColor * fillColor;
@property (nonatomic, retain) NSColor * strokeColor;
@property (nonatomic, assign) CGRect viewBox;
@property (nonatomic, retain) IJSVGRenderingStyle* style;
- (IJSVGLayer *)layerForNode:(IJSVGNode *)node;
- (IJSVGLayer*)layerForNode:(IJSVGNode*)node;
@end
@@ -0,0 +1,731 @@
//
// IJSVGLayerTree.m
// IJSVGExample
//
// Created by Curtis Hard on 29/12/2016.
// Copyright © 2016 Curtis Hard. All rights reserved.
//
#import "IJSVG.h"
#import "IJSVGGradient.h"
#import "IJSVGGradientLayer.h"
#import "IJSVGGroup.h"
#import "IJSVGGroupLayer.h"
#import "IJSVGImage.h"
#import "IJSVGImageLayer.h"
#import "IJSVGLayer.h"
#import "IJSVGLayerTree.h"
#import "IJSVGPath.h"
#import "IJSVGPattern.h"
#import "IJSVGPatternLayer.h"
#import "IJSVGShapeLayer.h"
#import "IJSVGStrokeLayer.h"
#import "IJSVGText.h"
#import "IJSVGTransform.h"
#import "IJSVGUtils.h"
@implementation IJSVGLayerTree
@synthesize style = _style;
- (void)dealloc
{
(void)([_style release]), _style = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
}
return self;
}
- (IJSVGLayer*)layerForNode:(IJSVGNode*)node
{
IJSVGLayer* layer = nil;
// is there a sub SVG?
if ([node isKindOfClass:[IJSVGPath class]]) {
// path
layer = [self layerForPath:(IJSVGPath*)node];
} else if ([node isKindOfClass:[IJSVGGroup class]]) {
// group
layer = [self layerForGroup:(IJSVGGroup*)node];
} else if ([node isKindOfClass:[IJSVGImage class]]) {
// image
layer = [self layerForImage:(IJSVGImage*)node];
}
[self applyDefaultsToLayer:layer fromNode:node];
// create the new layer
layer = [self applyTransforms:node.transforms
toLayer:layer
fromNode:node];
return layer;
}
- (IJSVGLayer*)applyTransforms:(NSArray<IJSVGTransform*>*)transforms
toLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
// any x and y?
CGRect frame = layer.bounds;
CGFloat x = [node.x computeValue:frame.size.width];
CGFloat y = [node.y computeValue:frame.size.height];
// no need to do anything if no transform, or x or y == 0
if (transforms.count == 0 && x == 0.f && y == 0.f) {
return layer;
}
// simply cascade all the transforms onto the identity
CGAffineTransform identity = CGAffineTransformIdentity;
if (x != 0.f || y != 0.f) {
identity = CGAffineTransformTranslate(identity, x, y);
}
// this used to be done with each transform being added to its own
// group layer, but we can simply use one and then apply
// the transforms in reverse order, has same outcome with less memory
IJSVGGroupLayer* parentLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
for(IJSVGTransform* transform in transforms.reverseObjectEnumerator) {
identity = CGAffineTransformConcat(identity, transform.CGAffineTransform);
}
parentLayer.affineTransform = identity;
[parentLayer addSublayer:layer];
return parentLayer;
}
- (void)applyDefaultsToLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
CGFloat opacity = node.opacity.value;
if(opacity != 1.f) {
layer.opacity = opacity;
}
// setup the blending mode
if (node.blendMode != IJSVGBlendModeNormal) {
layer.blendingMode = (CGBlendMode)node.blendMode;
}
// display?
if (node.shouldRender == NO) {
layer.hidden = YES;
}
}
- (IJSVGLayer*)layerForImage:(IJSVGImage*)image
{
IJSVGImageLayer* layer = [[[IJSVGImageLayer alloc] initWithCGImage:image.CGImage] autorelease];
layer.affineTransform = CGAffineTransformConcat(layer.affineTransform,
CGAffineTransformMakeScale(1.f, -1.f));
// make sure we set the width and height correctly,
// as this may not be exactly the same as the size of the
// given image
CGRect frame = layer.frame;
frame.size.width = image.width.value;
frame.size.height = image.height.value;
layer.frame = frame;
return layer;
}
- (IJSVGLayer*)layerForGroup:(IJSVGGroup*)group
{
// grab the sub layer tree from the SVG
if (group.svg != nil) {
return [self layerForGroup:group.svg.rootNode];
}
IJSVGGroupLayer* groupLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
for (IJSVGNode* node in group.childNodes) {
[groupLayer addSublayer:[self layerForNode:node]];
}
groupLayer.frame = (CGRect) {
.origin = CGPointZero,
.size = (CGSize) {
.width = group.width.value,
.height = group.height.value
}
};
// mask it - forgot groups can have masks too, doh! simple
// enough to apply though, recursion ftw!
[self maskLayer:groupLayer
fromNode:group];
return groupLayer;
}
- (CGRect)correctedBounds:(CGRect)bounds
{
if (bounds.origin.x >= INFINITY) {
bounds.origin.x = 0.f;
}
if (bounds.origin.y >= INFINITY) {
bounds.origin.y = 0.f;
}
if (bounds.size.width >= INFINITY) {
bounds.size.width = 0.f;
}
if (bounds.size.height >= INFINITY) {
bounds.size.height = 0.f;
}
return bounds;
}
- (IJSVGShapeLayer*)basicLayerForPath:(IJSVGPath*)path
originalBoundingBox:(CGRect*)originalBoundingBox
{
// setup path and layer
IJSVGShapeLayer* layer = [[[IJSVGShapeLayer alloc] init] autorelease];
layer.primitiveType = path.primitiveType;
CGPathRef introPath = path.path;
*originalBoundingBox = CGRectIntegral(CGPathGetBoundingBox(introPath));
layer.originalPathOrigin = (*originalBoundingBox).origin;
CGRect bounds = [self correctedBounds:*originalBoundingBox];
// zero back the path
CGAffineTransform trans = CGAffineTransformMakeTranslation(-bounds.origin.x,
-bounds.origin.y);
CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(introPath, &trans);
layer.path = transformedPath;
// clean up path memory
CGPathRelease(transformedPath);
// set the bounds
layer.frame = CGRectIntegral(bounds);
// basic fill color and rule
layer.fillColor = nil;
layer.fillRule = [self fillRule:path.windingRule];
return layer;
}
- (IJSVGShapeLayer*)layerMaskFromLayer:(CAShapeLayer*)layer
fromNode:(IJSVGNode*)node
{
IJSVGShapeLayer* mask = [[[IJSVGShapeLayer alloc] init] autorelease];
mask.fillColor = [NSColor blackColor].CGColor;
mask.path = layer.path;
return mask;
}
- (CGAffineTransform)absoluteTransform:(IJSVGNode*)node
{
CGAffineTransform parentAbsoluteTransform = CGAffineTransformIdentity;
IJSVGNode* intermediateNode = node.intermediateParentNode;
IJSVGNode* parentSVGNode = node;
while ((parentSVGNode = parentSVGNode.parentNode) != nil) {
if (node == intermediateNode) {
continue;
}
parentAbsoluteTransform = [self absoluteTransform:parentSVGNode];
}
return CGAffineTransformConcat(IJSVGConcatTransforms(node.transforms),
parentAbsoluteTransform);
}
- (IJSVGLayer*)layerForPath:(IJSVGPath*)path
{
// grab the basic shape layer
CGRect originalShapeBounds;
IJSVGShapeLayer* layer = [self basicLayerForPath:path
originalBoundingBox:&originalShapeBounds];
BOOL hasStroke = (path.strokeColor != nil || path.strokePattern != nil || path.strokeGradient != nil);
// any gradient?
if (_style.fillColor == nil && path.fillGradient != nil) {
// create the gradient
IJSVGGradientLayer* gradLayer = [self gradientLayerForLayer:layer
gradient:path.fillGradient
fromNode:path
objectRect:originalShapeBounds
shouldMask:YES];
// add the gradient and set it against the layer
[layer addSublayer:gradLayer];
layer.gradientFillLayer = gradLayer;
} else if (_style.fillColor == nil && path.fillPattern != nil) {
// create the pattern, this is actually not as easy as it may seem
IJSVGPatternLayer* patternLayer = [self patternLayerForLayer:layer
pattern:path.fillPattern
fromNode:path];
// add it
[layer addSublayer:patternLayer];
// apply offsets
[self applyOffsetsToLayer:patternLayer
fromNode:path.fillPattern];
layer.patternFillLayer = patternLayer;
} else {
// only use the global if its set and the current colors
// alpha channel is not 0.f, otherwise its a blank clear color,
// aka, not filled in
NSColor* fColor = path.fillColor;
BOOL hasColor = (fColor.alphaComponent == 0.f || fColor == nil) == NO;
BOOL hasFill = path.fillPattern != nil || path.fillGradient != nil;
// is there an overriding style in the sheet?
if (_style.fillColor && (hasFill || hasColor || fColor == nil)) {
fColor = _style.fillColor;
}
// if there is a color, change the opacity if required
if (fColor != nil && path.fillOpacity.value != 1.f) {
fColor = [IJSVGColor changeAlphaOnColor:fColor
to:path.fillOpacity.value];
}
// anything changed by user?
fColor = [_style.colorList proposedColorForColor:fColor];
// just set the color
if (fColor != nil) {
layer.fillColor = fColor.CGColor;
} else {
// use default color
NSColor* defColor = [IJSVGColor computeColorSpace:NSColor.blackColor];
if (path.fillOpacity.value != 1.f) {
defColor = [IJSVGColor changeAlphaOnColor:defColor
to:path.fillOpacity.value];
}
// work out if anything was changed by user
NSColor* proposedColor = [_style.colorList proposedColorForColor:defColor];
layer.fillColor = proposedColor.CGColor;
}
}
// stroke it
if (hasStroke == YES) {
// load the stroke layer
IJSVGStrokeLayer* strokeLayer = [self strokeLayer:layer
fromNode:path];
// reset the node
BOOL moveStrokeLayer = NO;
if (_style.strokeColor == nil && path.strokeGradient != nil) {
// force reset of the mask colour as we need to use the stroke layer
// as the mask for the stroke gradient
strokeLayer.strokeColor = [IJSVGColor computeColorSpace:NSColor.blackColor].CGColor;
// create the gradient
IJSVGGradientLayer* gradLayer = [self gradientStrokeLayerForLayer:layer
gradient:path.strokeGradient
fromNode:path
objectRect:originalShapeBounds];
moveStrokeLayer = YES;
gradLayer.mask = strokeLayer;
gradLayer.opacity = strokeLayer.opacity;
// add it
[layer addSublayer:gradLayer];
layer.strokeLayer = strokeLayer;
layer.gradientStrokeLayer = gradLayer;
} else if (_style.strokeColor == nil && path.strokePattern != nil) {
// force reset of the mask
strokeLayer.strokeColor = [IJSVGColor computeColorSpace:NSColor.blackColor].CGColor;
// create the pattern
IJSVGPatternLayer* patternLayer = [self patternStrokeLayerForLayer:layer
pattern:path.strokePattern
fromNode:path];
// set the mask for it
moveStrokeLayer = YES;
patternLayer.mask = strokeLayer;
patternLayer.opacity = strokeLayer.opacity;
// add it
[layer addSublayer:patternLayer];
layer.strokeLayer = strokeLayer;
layer.patternStrokeLayer = (IJSVGPatternLayer*)patternLayer;
} else {
// just add the coloured layer
[layer addSublayer:strokeLayer];
layer.strokeLayer = strokeLayer;
}
// if we required to move the stroke layer
// then move it in based on half of what the stroke
// width is, as strokes are draw on the center
if (moveStrokeLayer) {
CGFloat layerStrokeWidth = strokeLayer.lineWidth;
CGRect rect = strokeLayer.frame;
rect.origin.x += (layerStrokeWidth * .5f);
rect.origin.y += (layerStrokeWidth * .5f);
strokeLayer.frame = rect;
}
}
// apply masking
[self maskLayer:(IJSVGLayer*)layer
fromNode:path];
return (IJSVGLayer*)layer;
}
- (CGRect)correctBounds:(CGRect)bounds
forStrokedPath:(IJSVGNode*)path
{
// minus half the stroke width from x and y
// plus the stroke width to width and height
CGFloat val = path.strokeWidth.value;
bounds.origin.x -= (val * .5f);
bounds.origin.y -= (val * .5f);
bounds.size.width += val;
bounds.size.height += val;
return bounds;
}
- (IJSVGGradientLayer*)gradientStrokeLayerForLayer:(IJSVGShapeLayer*)layer
gradient:(IJSVGGradient*)gradient
fromNode:(IJSVGNode*)path
objectRect:(CGRect)objectRect
{
// the gradient drawing layer
IJSVGGradientLayer* gradLayer = [self gradientLayerForLayer:layer
gradient:gradient
fromNode:path
objectRect:objectRect
shouldMask:NO];
// set the bounds
CGRect bounds = CGPathGetBoundingBox(layer.path);
bounds = [self correctBounds:bounds forStrokedPath:path];
gradLayer.frame = bounds;
return gradLayer;
}
- (IJSVGGradientLayer*)gradientLayerForLayer:(IJSVGShapeLayer*)layer
gradient:(IJSVGGradient*)gradient
fromNode:(IJSVGNode*)path
objectRect:(CGRect)objectRect
shouldMask:(BOOL)shouldMask
{
// the gradient drawing layer
gradient.colorList = _style.colorList;
IJSVGGradientLayer* gradLayer = [[[IJSVGGradientLayer alloc] init] autorelease];
gradLayer.viewBox = _viewBox;
gradLayer.frame = layer.bounds;
gradLayer.gradient = gradient;
gradLayer.absoluteTransform = [self absoluteTransform:path];
gradLayer.objectRect = CGRectApplyAffineTransform(objectRect,
gradLayer.absoluteTransform);
if (shouldMask == YES) {
// add the mask
IJSVGShapeLayer* mask = [self layerMaskFromLayer:layer
fromNode:path];
gradLayer.mask = mask;
}
// is there a fill opacity?
if (path.fillOpacity.value != 0.f) {
gradLayer.opacity = path.fillOpacity.value;
}
gradLayer.masksToBounds = YES;
return gradLayer;
}
- (IJSVGPatternLayer*)patternStrokeLayerForLayer:(IJSVGShapeLayer*)layer
pattern:(IJSVGPattern*)pattern
fromNode:(IJSVGNode*)path
{
// create the pattern, this is actually not as easy as it may seem
IJSVGPatternLayer* patternLayer = [[[IJSVGPatternLayer alloc] init] autorelease];
patternLayer.patternNode = pattern;
patternLayer.pattern = [self layerForNode:pattern];
// is there a fill opacity?
if (path.fillOpacity.value != 0.f) {
patternLayer.opacity = path.fillOpacity.value;
}
// set the bounds
CGRect bounds = CGPathGetBoundingBox(layer.path);
bounds = [self correctBounds:bounds forStrokedPath:path];
patternLayer.frame = bounds;
patternLayer.masksToBounds = YES;
// display
[patternLayer setNeedsDisplay];
return patternLayer;
}
- (IJSVGPatternLayer*)patternLayerForLayer:(IJSVGShapeLayer*)layer
pattern:(IJSVGPattern*)pattern
fromNode:(IJSVGNode*)path
{
// create the pattern, this is actually not as easy as it may seem
IJSVGPatternLayer* patternLayer = [[[IJSVGPatternLayer alloc] init] autorelease];
patternLayer.patternNode = pattern;
patternLayer.pattern = [self layerForNode:pattern];
patternLayer.frame = CGPathGetBoundingBox(layer.path);
// is there a fill opacity?
if (path.fillOpacity.value != 0.f) {
patternLayer.opacity = path.fillOpacity.value;
}
// add the mask
patternLayer.mask = [self layerMaskFromLayer:layer
fromNode:path];
// display
[patternLayer setNeedsDisplay];
patternLayer.masksToBounds = YES;
return patternLayer;
}
- (void)applyOffsetsToLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
// make sure it has a superlayer
if (layer.superlayer == nil) {
return;
}
// grab the x and y
IJSVGUnitLength* x = nil;
IJSVGUnitLength* y = nil;
// sort out the rect
CGRect rect = layer.superlayer.frame;
CGRect frame = layer.frame;
// x
if ((x = node.x) != nil) {
frame.origin.x = [x computeValue:rect.size.width];
}
// y
if ((y = node.y) != nil) {
frame.origin.y = [y computeValue:rect.size.height];
}
// update the frame
if (CGRectEqualToRect(frame, layer.frame) == NO) {
layer.frame = frame;
}
}
- (IJSVGStrokeLayer*)strokeLayer:(IJSVGShapeLayer*)layer
fromNode:(IJSVGPath*)path
{
// same as fill, dont use global if the alpha is 0.f, but do use it
// if there is a pattern or gradient
NSColor* sColor = path.strokeColor;
if (_style.strokeColor != nil && ((sColor != nil && sColor.alphaComponent != 0.f) || path.strokePattern != nil || path.strokeGradient != nil)) {
sColor = _style.strokeColor;
}
sColor = [_style.colorList proposedColorForColor:sColor];
// stroke layer
IJSVGStrokeLayer* strokeLayer = [[[IJSVGStrokeLayer alloc] init] autorelease];
strokeLayer.path = layer.path;
strokeLayer.fillColor = nil;
strokeLayer.strokeColor = sColor.CGColor;
CGFloat lineWidth = 1.f;
if (_style.lineWidth != IJSVGInheritedFloatValue) {
lineWidth = _style.lineWidth;
} else {
lineWidth = path.strokeWidth.value;
}
// work out line styles
IJSVGLineCapStyle lCapStyle;
IJSVGLineJoinStyle lJoinStyle;
// forced cap style
if (_style.lineCapStyle != IJSVGLineCapStyleNone) {
lCapStyle = _style.lineCapStyle;
} else {
lCapStyle = path.lineCapStyle;
}
// forced join style
if (_style.lineJoinStyle != IJSVGLineJoinStyleNone) {
lJoinStyle = _style.lineJoinStyle;
} else {
lJoinStyle = path.lineJoinStyle;
}
// line styles
strokeLayer.lineWidth = lineWidth;
strokeLayer.lineCap = [self lineCap:lCapStyle];
strokeLayer.lineJoin = [self lineJoin:lJoinStyle];
CGFloat strokeOpacity = 1.f;
if (path.strokeOpacity.value != 0.f) {
strokeOpacity = path.strokeOpacity.value;
}
strokeLayer.opacity = strokeOpacity;
// dashing
strokeLayer.lineDashPhase = path.strokeDashOffset.value;
if(path.strokeDashArrayCount != 0.f) {
strokeLayer.lineDashPattern = [self lineDashPattern:path];
}
return strokeLayer;
}
- (void)maskLayer:(IJSVGLayer*)layer
fromNode:(IJSVGNode*)node
{
// any clippath?
if (node.clipPath != nil || node.mask != nil) {
IJSVGGroupLayer* maskLayer = [[[IJSVGGroupLayer alloc] init] autorelease];
// add clip mask
if (node.clipPath != nil) {
IJSVGLayer* clip = [self layerForNode:node.clipPath];
// adjust the frame
if (node.clipPath.units == IJSVGUnitObjectBoundingBox) {
[self adjustLayer:clip
toParentLayerFrame:layer];
}
// add the layer
[maskLayer addSublayer:clip];
}
// add the actual mask
if (node.mask != nil) {
IJSVGLayer* mask = [self layerForNode:node.mask];
// only move if bounding box
if (node.mask.units == IJSVGUnitObjectBoundingBox) {
[self adjustLayer:mask
toParentLayerFrame:layer];
}
// add the layer
[maskLayer addSublayer:mask];
}
// recursive colourize for each item
NSColor* color = [IJSVGColor computeColorSpace:NSColor.whiteColor];
[self _recursiveColorLayersFromLayer:maskLayer
withColor:color.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] initWithCapacity:node.strokeDashArrayCount] autorelease];
for (NSInteger i = 0; i < node.strokeDashArrayCount; i++) {
[arr addObject:@((CGFloat)node.strokeDashArray[i])];
}
return arr;
}
- (NSString*)lineJoin:(IJSVGLineJoinStyle)joinStyle
{
switch (joinStyle) {
default:
case IJSVGLineJoinStyleMiter: {
return kCALineJoinMiter;
}
case IJSVGLineJoinStyleBevel: {
return kCALineJoinBevel;
}
case IJSVGLineJoinStyleRound: {
return kCALineJoinRound;
}
}
}
- (NSString*)lineCap:(IJSVGLineCapStyle)capStyle
{
switch (capStyle) {
default:
case IJSVGLineCapStyleButt: {
return kCALineCapButt;
}
case IJSVGLineCapStyleRound: {
return kCALineCapRound;
}
case IJSVGLineCapStyleSquare: {
return kCALineCapSquare;
}
}
}
- (NSString*)fillRule:(IJSVGWindingRule)rule
{
switch (rule) {
case IJSVGWindingRuleEvenOdd: {
return kCAFillRuleEvenOdd;
}
default: {
return kCAFillRuleNonZero;
}
}
}
@end
@@ -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 <IJSVG/IJSVGColorList.h>
#import <IJSVG/IJSVGNode.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface IJSVGRenderingStyle : NSObject
@property (nonatomic, assign) IJSVGLineCapStyle lineCapStyle;
@property (nonatomic, assign) IJSVGLineJoinStyle lineJoinStyle;
@property (nonatomic, assign) CGFloat lineWidth;
@property (nonatomic, retain) IJSVGColorList* colorList;
@property (nonatomic, retain) NSColor* fillColor;
@property (nonatomic, retain) NSColor* strokeColor;
+ (NSArray<NSString*>*)observableProperties;
@end
@@ -0,0 +1,43 @@
//
// IJSVGStyleList.m
// IconJar
//
// Created by Curtis Hard on 09/07/2019.
// Copyright © 2019 Curtis Hard. All rights reserved.
//
#import "IJSVGRenderingStyle.h"
@implementation IJSVGRenderingStyle
- (void)dealloc
{
(void)([_fillColor release]), _fillColor = nil;
(void)([_strokeColor release]), _strokeColor = nil;
(void)([_colorList release]), _colorList = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_lineCapStyle = IJSVGLineCapStyleNone;
_lineJoinStyle = IJSVGLineJoinStyleNone;
_lineWidth = IJSVGInheritedFloatValue;
_colorList = [[IJSVGColorList alloc] init];
}
return self;
}
+ (NSArray<NSString*>*)observableProperties
{
static NSArray* array = nil;
if (array == nil) {
array = @[ @"lineCapStyle", @"lineJoinStyle", @"lineWidth",
@"colorList", @"fillColor", @"strokeColor" ]
.retain;
}
return array;
}
@end
@@ -6,22 +6,21 @@
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import <IJSVG/IJSVGColor.h>
#import <Foundation/Foundation.h>
#import "IJSVGColor.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
@@ -0,0 +1,128 @@
//
// IJSVGStyle.m
// IJSVGExample
//
// Created by Curtis Hard on 03/09/2014.
// Copyright (c) 2014 Curtis Hard. All rights reserved.
//
#import "IJSVGStyle.h"
#import "IJSVGUtils.h"
@implementation IJSVGStyle
- (void)dealloc
{
(void)([_dict release]), _dict = nil;
[super dealloc];
}
- (id)init
{
if ((self = [super init]) != nil) {
_dict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)setPropertyValue:(id)value
forProperty:(NSString*)key
{
[_dict setObject:value
forKey:key];
}
- (NSDictionary*)properties
{
return _dict;
}
- (id)property:(NSString*)key
{
return [_dict objectForKey:key];
}
+ (IJSVGStyle*)parseStyleString:(NSString*)string
{
IJSVGStyle* style = [[[self.class alloc] init] autorelease];
NSInteger length = string.length;
NSInteger index = 0;
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++) {
unichar c = [string characterAtIndex:i];
// find the key
if (c == ':') {
key = [string substringWithRange:NSMakeRange(index, (i - index))];
index = i + 1;
}
// find the value
else if (c == ';' || i == (length - 1)) {
NSInteger chomp;
if (i == (length - 1) && c != ';') {
chomp = (i - (index - 1));
} else {
chomp = (i - index);
}
value = [string substringWithRange:NSMakeRange(index, chomp)];
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]];
key = nil;
value = nil;
}
}
return style;
}
+ (NSString*)trimString:(NSString*)string
{
return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
+ (NSArray*)allowedColourKeys
{
return @[ @"fill", @"stroke-colour", @"stop-color", @"stroke" ];
}
- (void)setProperties:(NSDictionary*)properties
replaceAll:(BOOL)flag
{
if (flag) {
[_dict removeAllObjects];
}
[_dict addEntriesFromDictionary:properties];
}
- (NSString*)description
{
return [_dict description];
}
- (IJSVGStyle*)mergedStyle:(IJSVGStyle*)style
{
// create the new style
IJSVGStyle* newStyle = [[[IJSVGStyle alloc] init] autorelease];
// grab the current style
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];
return newStyle;
}
@end

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