diff --git a/CHANGELOG.md b/CHANGELOG.md index 5581835e..4ffa6a72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. Items under ## [Unreleased] +## [2.7.0] +### New Features +- Support for `viewBox` tag. [Alessio Prosperi](https://github.com/NeedNap) + and [Ariel Elkin](https://github.com/arielelkin) [#181](https://github.com/pocketsvg/PocketSVG/pull/181) and [#185](https://github.com/pocketsvg/PocketSVG/pull/185). + ## [2.6.0] ### New Features - Xcode 12 and SPM Support. [Ariel Elkin](https://github.com/arielelkin), [#178](https://github.com/pocketsvg/PocketSVG/pull/178/) diff --git a/Demos/Demo-macOS/Demo-macOS/MacDemo.swift b/Demos/Demo-macOS/Demo-macOS/MacDemo.swift index 99d19347..5d23f2a8 100644 --- a/Demos/Demo-macOS/Demo-macOS/MacDemo.swift +++ b/Demos/Demo-macOS/Demo-macOS/MacDemo.swift @@ -15,7 +15,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {} class DemoController: NSViewController { override func loadView() { let url = Bundle.main.url(forResource: "iceland", withExtension: "svg")! - view = SVGImageView.init(contentsOf: url) + let j = SVGImageView.init(contentsOf: url) + print(j.viewBox == .null) + view = j + view.frame = NSRect(x: 0, y: 0, width: 300, height: 200) } } diff --git a/PocketSVG.podspec b/PocketSVG.podspec index 597e4228..943191e1 100644 --- a/PocketSVG.podspec +++ b/PocketSVG.podspec @@ -4,7 +4,7 @@ Pod::Spec.new do |s| s.summary = "Easily convert your SVG files into CGPaths, CAShapeLayers, and UIBezierPaths" s.homepage = "https://github.com/pocketsvg/PocketSVG" s.authors = { "Ponderwell, Fjölnir Ásgeirsson, Ariel Elkin, and Contributors" => "https://github.com/pocketsvg/PocketSVG" } - s.ios.deployment_target = '8.1' + s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' s.license = { :type => 'MIT', diff --git a/Sources/SVGBezierPath.mm b/Sources/SVGBezierPath.mm index c9249abb..b86925ba 100644 --- a/Sources/SVGBezierPath.mm +++ b/Sources/SVGBezierPath.mm @@ -205,6 +205,16 @@ - (void)applyTransform:(CGAffineTransform)cgTransform [self transformUsingAffineTransform:transform]; } #endif + +- (CGRect) viewBox { + NSString *viewBoxString = _svgAttributes[@"viewBox"]; + NSArray *stringArray = [viewBoxString componentsSeparatedByString:@" "]; + if (stringArray && stringArray.count == 4) { + return CGRectMake(CGFloat([stringArray[0] doubleValue]), CGFloat([stringArray[1] doubleValue]), CGFloat([stringArray[2] doubleValue]), CGFloat([stringArray[3] doubleValue])); + } else { + return CGRectNull; + } +} @end diff --git a/Sources/SVGEngine.mm b/Sources/SVGEngine.mm index 96793431..b112a29d 100755 --- a/Sources/SVGEngine.mm +++ b/Sources/SVGEngine.mm @@ -81,6 +81,7 @@ @interface SVGAttributeSet () { @public NSMapTable *_attributes; + CGRect _viewBox; } @end @@ -118,7 +119,7 @@ @interface SVGAttributeSet () { else if(type == XML_READER_TYPE_END_ELEMENT) --depthWithinUnknownElement; } else if(type == XML_READER_TYPE_ELEMENT && strcasecmp(tag, "svg") == 0) { - // recognize the root svg element but we don't need to do anything with it + pushGroup(readAttributes()); } else if(type == XML_READER_TYPE_ELEMENT && strcasecmp(tag, "path") == 0) path = readPathTag(); else if(type == XML_READER_TYPE_ELEMENT && strcasecmp(tag, "polyline") == 0) @@ -996,6 +997,9 @@ - (id)mutableCopyWithZone:(NSZone *)zone } return copy; } +- (CGRect) viewBox { + return _viewBox; +} @end @implementation SVGMutableAttributeSet diff --git a/Sources/SVGImageView.m b/Sources/SVGImageView.m index fac8e04d..4f9dc923 100644 --- a/Sources/SVGImageView.m +++ b/Sources/SVGImageView.m @@ -190,4 +190,8 @@ - (CGSize)intrinsicContentSize { return [self sizeThatFits:CGSizeZero]; } + +- (CGRect) viewBox { + return _svgLayer.viewBox; +} @end diff --git a/Sources/SVGLayer.m b/Sources/SVGLayer.m index 21a2cc9e..641c865b 100644 --- a/Sources/SVGLayer.m +++ b/Sources/SVGLayer.m @@ -56,6 +56,10 @@ - (void)dealloc CGColorRelease(_strokeColor); } +- (CGRect) viewBox { + return [[_paths firstObject] viewBox]; +} + - (void)setPaths:(NSArray *)paths { [self willChangeValueForKey:@"paths"]; diff --git a/Sources/include/SVGBezierPath.h b/Sources/include/SVGBezierPath.h index dd0eda11..1814c046 100644 --- a/Sources/include/SVGBezierPath.h +++ b/Sources/include/SVGBezierPath.h @@ -65,6 +65,13 @@ FOUNDATION_EXTERN void SVGDrawPathsWithBlock(NSArray * const pat */ - (SVGBezierPath *)pathBySettingSVGAttributes:(NSDictionary *)attributes; +/*! + * @brief The value of the SVG's viewBox attribute, expressed as a CGRect. If there is + * no viewBox attribute, this property will be CGRect.null + * + */ +@property(nonatomic, readonly) CGRect viewBox; + #if !TARGET_OS_IPHONE @property(nonatomic, readonly) CGPathRef CGPath; #endif diff --git a/Sources/include/SVGEngine.h b/Sources/include/SVGEngine.h index 6b2e435d..073f8c03 100755 --- a/Sources/include/SVGEngine.h +++ b/Sources/include/SVGEngine.h @@ -51,6 +51,7 @@ NSString *SVGStringFromCGPaths(NSArray *paths, SVGAttributeSet *attributes); @interface SVGAttributeSet : NSObject - (NSDictionary *)attributesForPath:(CGPathRef)path; +@property(nonatomic, readonly) CGRect viewBox; @end @interface SVGMutableAttributeSet : SVGAttributeSet - (void)setAttributes:(NSDictionary *)attributes forPath:(CGPathRef)path; diff --git a/Sources/include/SVGImageView.h b/Sources/include/SVGImageView.h index 22793ea4..369bee60 100644 --- a/Sources/include/SVGImageView.h +++ b/Sources/include/SVGImageView.h @@ -59,5 +59,12 @@ IB_DESIGNABLE */ @property(nonatomic) IBInspectable BOOL scaleLineWidth; +/*! + * @brief The value of the SVG's viewBox attribute, expressed as a CGRect. If there is + * no viewBox attribute, this property will be CGRect.null + * + */ +@property(nonatomic, readonly) CGRect viewBox; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/include/SVGLayer.h b/Sources/include/SVGLayer.h index 57682170..0d597fd1 100644 --- a/Sources/include/SVGLayer.h +++ b/Sources/include/SVGLayer.h @@ -60,5 +60,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property(nonatomic) BOOL scaleLineWidth; + +/*! + * @brief The value of the SVG's viewBox attribute, expressed as a CGRect. If there is + * no viewBox attribute, this property will be CGRect.null + * + */ +@property(nonatomic, readonly) CGRect viewBox; + @end NS_ASSUME_NONNULL_END diff --git a/Tests/PocketSVGTests.swift b/Tests/PocketSVGTests.swift index 2ea1a387..41a3445e 100644 --- a/Tests/PocketSVGTests.swift +++ b/Tests/PocketSVGTests.swift @@ -98,7 +98,7 @@ class PocketSVGTests: XCTestCase { XCTAssert(paths.count == 1) let rectanglePath = paths[0] - let representation = "\n \n\n\n" + let representation = "\n \n\n\n" XCTAssertEqual(rectanglePath.svgRepresentation, representation) }