diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/.travis.yml b/.travis.yml index 2254036..8c77552 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode10.2 +osx_image: xcode11 addons: homebrew: @@ -37,12 +37,13 @@ script: - pod lib lint --allow-warnings - echo Build as dynamic frameworks - - carthage update --platform ios,tvos,macos --configuration DEBUG + - carthage update --configuration DEBUG - xcodebuild build clean -project SDWebImageSVGCoder.xcodeproj -scheme 'SDWebImageSVGCoder iOS' -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Debug | xcpretty -c - xcodebuild build clean -project SDWebImageSVGCoder.xcodeproj -scheme 'SDWebImageSVGCoder tvOS' -sdk appletvsimulator -configuration Debug | xcpretty -c - xcodebuild build clean -project SDWebImageSVGCoder.xcodeproj -scheme 'SDWebImageSVGCoder macOS' -sdk macosx -configuration Debug | xcpretty -c + - xcodebuild build clean -project SDWebImageSVGCoder.xcodeproj -scheme 'SDWebImageSVGCoder watchOS' -sdk watchsimulator -configuration Debug | xcpretty -c - echo Build example - pod install --project-directory=Example - - xcodebuild build -workspace Example/SDWebImageSVGCoder.xcworkspace -scheme 'SDWebImageSVGCoder-Example' -sdk iphonesimulator -destination 'name=iPhone 6s' -configuration Debug | xcpretty -c + - xcodebuild build -workspace Example/SDWebImageSVGCoder.xcworkspace -scheme 'SDWebImageSVGCoder-Example' -sdk iphonesimulator -destination 'name=iPhone 8' -configuration Debug | xcpretty -c - xcodebuild build -workspace Example/SDWebImageSVGCoder.xcworkspace -scheme 'SDWebImageSVGCoder-Example macOS' -sdk macosx -configuration Debug | xcpretty -c diff --git a/Cartfile b/Cartfile index 14a02bb..9a360e8 100644 --- a/Cartfile +++ b/Cartfile @@ -1,2 +1 @@ -github "SDWebImage/SDWebImage" ~> 5.0 -github "SVGKit/SVGKit" >= 2.1 \ No newline at end of file +github "SDWebImage/SDWebImage" ~> 5.0 \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved index 933f89c..ef05d0c 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1 @@ -github "CocoaLumberjack/CocoaLumberjack" "3.5.2" -github "SDWebImage/SDWebImage" "5.0.0" -github "SVGKit/SVGKit" "2.1.0" +github "SDWebImage/SDWebImage" "5.3.1" diff --git a/Example/Podfile b/Example/Podfile index ed9ba38..a9585d9 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,9 +1,8 @@ use_frameworks! target 'SDWebImageSVGCoder_Example' do - platform :ios, '9.3' + platform :ios, '13.0' pod 'SDWebImageSVGCoder', :path => '../' - pod 'SVGKit', :git => 'https://github.com/SVGKit/SVGKit.git', :branch => '3.x' target 'SDWebImageSVGCoder_Tests' do inherit! :search_paths @@ -13,6 +12,6 @@ target 'SDWebImageSVGCoder_Example' do end target 'SDWebImageSVGCoder_Example macOS' do - platform :osx, '10.13' + platform :osx, '10.15' pod 'SDWebImageSVGCoder', :path => '../' end \ No newline at end of file diff --git a/Example/Podfile.lock b/Example/Podfile.lock index a9df539..b88666a 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,41 +1,23 @@ PODS: - - CocoaLumberjack (3.5.3): - - CocoaLumberjack/Core (= 3.5.3) - - CocoaLumberjack/Core (3.5.3) - - SDWebImage/Core (5.0.2) - - SDWebImageSVGCoder (0.2.0): + - SDWebImage/Core (5.3.1) + - SDWebImageSVGCoder (0.3.0): - SDWebImage/Core (~> 5.0) - - SVGKit (>= 2.1) - - SVGKit (2.1.0): - - CocoaLumberjack (~> 3.0) DEPENDENCIES: - SDWebImageSVGCoder (from `../`) - - SVGKit (from `https://github.com/SVGKit/SVGKit.git`, branch `3.x`) SPEC REPOS: - https://github.com/cocoapods/specs.git: - - CocoaLumberjack + trunk: - SDWebImage EXTERNAL SOURCES: SDWebImageSVGCoder: :path: "../" - SVGKit: - :branch: 3.x - :git: https://github.com/SVGKit/SVGKit.git - -CHECKOUT OPTIONS: - SVGKit: - :commit: cf32da55633e370e66a7ba6e003224bd67296c16 - :git: https://github.com/SVGKit/SVGKit.git SPEC CHECKSUMS: - CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947 - SDWebImage: 6764b5fa0f73c203728052955dbefa2bf1f33282 - SDWebImageSVGCoder: 61f60a3064db079de646a34a5f5aa8d3ac258345 - SVGKit: 8a2fc74258bdb2abb54d3b65f3dd68b0277a9c4d + SDWebImage: 7137d57385fb632129838c1e6ab9528a22c666cc + SDWebImageSVGCoder: 23a0505a7d34193abf93e9c1afda1dd5c12134d4 -PODFILE CHECKSUM: 8107c7193dd0c4844a782937610f415caa6ef482 +PODFILE CHECKSUM: 84f51f25230f3de246edc2d26479a6b409c99fb1 -COCOAPODS: 1.6.1 +COCOAPODS: 1.8.4 diff --git a/Example/SDWebImageSVGCoder-Example-macOS/ViewController.m b/Example/SDWebImageSVGCoder-Example-macOS/ViewController.m index f17f800..ec9d42b 100644 --- a/Example/SDWebImageSVGCoder-Example-macOS/ViewController.m +++ b/Example/SDWebImageSVGCoder-Example-macOS/ViewController.m @@ -18,28 +18,30 @@ - (void)viewDidLoad { // Do any additional setup after loading the view. SDImageSVGCoder *SVGCoder = [SDImageSVGCoder sharedCoder]; [[SDImageCodersManager sharedManager] addCoder:SVGCoder]; - NSURL *SVGURL = [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/1/14/Mahuri.svg"]; - NSURL *SVGURL2 = [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/6/67/Firefox_Logo%2C_2017.svg"]; + NSURL *svgURL = [NSURL URLWithString:@"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg"]; + NSURL *svgURL2 = [NSURL URLWithString:@"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/wikimedia.svg"]; CGSize screenSize = self.view.bounds.size; - SVGKImageView *imageView1 = [[SVGKFastImageView alloc] initWithSVGKImage:nil]; + UIImageView *imageView1 = [[UIImageView alloc] init]; imageView1.frame = CGRectMake(0, 0, screenSize.width / 2, screenSize.height); + imageView1.imageScaling = NSImageScaleProportionallyUpOrDown; - SVGKImageView *imageView2 = [[SVGKLayeredImageView alloc] initWithSVGKImage:nil]; + UIImageView *imageView2 = [[UIImageView alloc] init]; imageView2.frame = CGRectMake(screenSize.width / 2, 0, screenSize.width / 2, screenSize.height); + imageView2.imageScaling = NSImageScaleProportionallyUpOrDown; [self.view addSubview:imageView1]; [self.view addSubview:imageView2]; - [imageView1 sd_setImageWithURL:SVGURL placeholderImage:nil options:SDWebImageRetryFailed completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + [imageView1 sd_setImageWithURL:svgURL placeholderImage:nil options:SDWebImageRetryFailed completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { if (image) { NSLog(@"SVG load success"); NSData *svgData = [image sd_imageDataAsFormat:SDImageFormatSVG]; NSAssert(svgData.length > 0, @"SVG Data should exist"); } }]; - [imageView2 sd_setImageWithURL:SVGURL2 placeholderImage:nil options:SDWebImageRetryFailed context:@{SDWebImageContextSVGImageSize : @(imageView2.bounds.size)} progress:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + [imageView2 sd_setImageWithURL:svgURL2 placeholderImage:nil options:SDWebImageRetryFailed completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { if (image) { NSLog(@"SVG load animation success"); [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) { diff --git a/Example/SDWebImageSVGCoder.xcodeproj/project.pbxproj b/Example/SDWebImageSVGCoder.xcodeproj/project.pbxproj index 557636e..1e3a125 100644 --- a/Example/SDWebImageSVGCoder.xcodeproj/project.pbxproj +++ b/Example/SDWebImageSVGCoder.xcodeproj/project.pbxproj @@ -429,17 +429,13 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-SDWebImageSVGCoder_Example/Pods-SDWebImageSVGCoder_Example-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/CocoaLumberjack-iOS/CocoaLumberjack.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage-iOS/SDWebImage.framework", "${BUILT_PRODUCTS_DIR}/SDWebImageSVGCoder-iOS/SDWebImageSVGCoder.framework", - "${BUILT_PRODUCTS_DIR}/SVGKit-iOS/SVGKit.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageSVGCoder.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SVGKit.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -451,23 +447,15 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-SDWebImageSVGCoder_Example macOS/Pods-SDWebImageSVGCoder_Example macOS-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/CocoaLumberjack-macOS/CocoaLumberjack.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage-macOS/SDWebImage.framework", "${BUILT_PRODUCTS_DIR}/SDWebImageSVGCoder-macOS/SDWebImageSVGCoder.framework", - "${BUILT_PRODUCTS_DIR}/SVGKit-macOS/SVGKit.framework", ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - ); outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageSVGCoder.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SVGKit.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/Example/SDWebImageSVGCoder.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Example/SDWebImageSVGCoder.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index 949b678..6b30c74 100644 --- a/Example/SDWebImageSVGCoder.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/Example/SDWebImageSVGCoder.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -4,5 +4,7 @@ BuildSystemType Original + PreviewsEnabled + diff --git a/Example/SDWebImageSVGCoder/SDViewController.m b/Example/SDWebImageSVGCoder/SDViewController.m index 2bc2b5d..2815bf9 100644 --- a/Example/SDWebImageSVGCoder/SDViewController.m +++ b/Example/SDWebImageSVGCoder/SDViewController.m @@ -8,7 +8,6 @@ #import "SDViewController.h" #import -#import @interface SDViewController () @@ -23,26 +22,22 @@ - (void)viewDidLoad SDImageSVGCoder *SVGCoder = [SDImageSVGCoder sharedCoder]; [[SDImageCodersManager sharedManager] addCoder:SVGCoder]; - NSURL *svgURL = [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/1/14/Mahuri.svg"]; - NSURL *svgURL2 = [NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2d/Sample_SVG_file%2C_signature.svg"]; + NSURL *svgURL = [NSURL URLWithString:@"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg"]; + NSURL *svgURL2 = [NSURL URLWithString:@"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/wikimedia.svg"]; NSURL *svgURL3 = [NSURL URLWithString:@"https://simpleicons.org/icons/github.svg"]; CGSize screenSize = [UIScreen mainScreen].bounds.size; - // `SVGKLayeredImageView`, best on performance and do actually vector image rendering (translate SVG to CALayer tree). - SVGKImageView *imageView1 = [[SVGKLayeredImageView alloc] initWithSVGKImage:nil]; + UIImageView *imageView1 = [[UIImageView alloc] init]; imageView1.frame = CGRectMake(0, 0, screenSize.width, screenSize.height / 2); - imageView1.sd_adjustContentMode = YES; // make `contentMode` works - imageView1.contentMode = UIViewContentModeScaleAspectFill; - imageView1.clipsToBounds = YES; + imageView1.contentMode = UIViewContentModeScaleAspectFit; - // `SVGKFastImageView`, draw SVG as bitmap dynamically when size changed. - SVGKImageView *imageView2 = [[SVGKFastImageView alloc] initWithSVGKImage:nil]; + UIImageView *imageView2 = [[UIImageView alloc] init]; imageView2.frame = CGRectMake(0, screenSize.height / 2, screenSize.width, screenSize.height / 2); - imageView2.clipsToBounds = YES; + imageView2.contentMode = UIViewContentModeScaleAspectFill; - // `UIImageView`, draw SVG as bitmap image with fixed size, like PNG. UIImageView *imageView3 = [[UIImageView alloc] initWithFrame:CGRectMake(screenSize.width - 100, screenSize.height - 100, 100, 100)]; + imageView2.contentMode = UIViewContentModeScaleToFill; [self.view addSubview:imageView1]; [self.view addSubview:imageView2]; @@ -60,10 +55,16 @@ - (void)viewDidLoad NSLog(@"SVGKFastImageView SVG load success"); } }]; - // For `UIImageView`, you can specify a desired SVG size instead of original SVG viewport (which may be small) - [imageView3 sd_setImageWithURL:svgURL3 placeholderImage:nil options:SDWebImageRetryFailed context:@{SDWebImageContextSVGImageSize : @(CGSizeMake(100, 100))} progress:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { + [imageView3 sd_setImageWithURL:svgURL3 placeholderImage:nil options:SDWebImageRetryFailed context:nil progress:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { if (image) { - NSLog(@"UIImageView SVG load success"); + NSLog(@"SVG load animation success"); + [UIView animateWithDuration:2 animations:^{ + imageView3.bounds = CGRectMake(0, 0, 300, 300); + } completion:^(BOOL finished) { + [UIView animateWithDuration:2 animations:^{ + imageView3.bounds = CGRectMake(0, 0, 100, 100); + }]; + }]; } }]; } diff --git a/Example/Screenshot/SVGDemo-macOS.png b/Example/Screenshot/SVGDemo-macOS.png index ab2ec0d..d8e8790 100644 Binary files a/Example/Screenshot/SVGDemo-macOS.png and b/Example/Screenshot/SVGDemo-macOS.png differ diff --git a/Example/Screenshot/SVGDemo.png b/Example/Screenshot/SVGDemo.png index 326a991..de4da05 100644 Binary files a/Example/Screenshot/SVGDemo.png and b/Example/Screenshot/SVGDemo.png differ diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 0000000..d5a1c70 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "SDWebImage", + "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", + "state": { + "branch": null, + "revision": "7adc385b7d9aa758fb5073bcea478f31293c4e40", + "version": "5.3.1" + } + } + ] + }, + "version": 1 +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..2347174 --- /dev/null +++ b/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version:5.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SDWebImageSVGCoder", + platforms: [ + .macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6) + ], + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "SDWebImageSVGCoder", + targets: ["SDWebImageSVGCoder"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.1.0") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "SDWebImageSVGCoder", + dependencies: ["SDWebImage"], + path: ".", + sources: ["SDWebImageSVGCoder/Classes"], + publicHeadersPath: "SDWebImageSVGCoder/Classes" + ) + ] +) diff --git a/README.md b/README.md index e1eac35..2e476e0 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,17 @@ ## What's for -SDWebImageSVGCoder is a SVG coder plugin for [SDWebImage](https://github.com/rs/SDWebImage/) framework, which provide the image loading support for [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) using [SVGKit](https://github.com/SVGKit/SVGKit) SVG engine. +SDWebImageSVGCoder is a SVG coder plugin for [SDWebImage](https://github.com/rs/SDWebImage/) framework, which provide the image loading support for [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics). -## Note about SVG on iOS +The SVG rendering is done using Apple's framework CoreSVG.framework (introduced in iOS 13/macOS 10.15). -From iOS 13 and Xcode 11, Apple provide the built-in support for SVG. You can use Xcode Asset Catalog to import your SVG files the same as PDF. (Click `Keep Vector Data`) +## Note for SVGKit user -But however, the new SVG framework (`CoreSVG.framework`) is still in Private API. If you're interested in this, you can try to use [iOS13_SVG](https://github.com/SDWebImage/SDWebImageSVGCoder/tree/iOS13_SVG) branch. Which bring the built-in SVG support for `UIImageView` and vector rendering, without the relay on SVGKit. +Previously before 1.0.0 version, this SVG Coder is powered by third party library [SVGKit](https://github.com/SVGKit/SVGKit). Which support iOS 8+(macOS 10.10+) as well. + +However, due to the lack support of that third party library, which contains massive issues without community's help, no clarity of version release, makes a pain for us to maintain. So, We decide to deprecate SVGKit support and move it into another repo: [SDWebImageSVGKitPlugin](https://github.com/SDWebImage/SDWebImageSVGKitPlugin). + +User who use SVGKit or have to support iOS 8+ can still use that SVGKit plugin instead, you can also mix these two SVG coder at the same time. But since Apple already provide a built-in framework support. We prefer to use that as well, which can reduce complicated dependency, code size, and get polished from Apple's system upgrade. ## Example @@ -24,9 +28,10 @@ You can modify the code or use some other SVG files to check the compatibility. ## Requirements -+ iOS 8 -+ tvOS 9 -+ macOS 10.10 ++ iOS 13+ ++ tvOS 13+ ++ macOS 10.15+ ++ watchOS 6+ ## Installation @@ -53,80 +58,75 @@ SDWebImageSVGCoder is available through [Carthage](https://github.com/Carthage/C github "SDWebImage/SDWebImageSVGCoder" ``` +#### Swift Package Manager + +SDWebImageSVGCoder is available through [Swift Package Manager](https://swift.org/package-manager). + +```swift +let package = Package( + dependencies: [ + .package(url: "https://github.com/SDWebImage/SDWebImageSVGCoder.git", from: "1.0") + ] +) +``` + ## Usage -### Use UIImageView (render SVG as bitmap image) +### Use UIImageView -To use SVG coder, you should firstly add the `SDImageSVGCoder` to the coders manager. Then you can call the View Category method to start load SVG images. +To use SVG coder, you should firstly add the `SDImageSVGCoder` to the coders manager. Then you can call the View Category method to start load SVG images. See [Wiki - Coder Usage](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#coder-usage) here for these steps. -Because SVG is a [vector image](https://en.wikipedia.org/wiki/Vector_graphics) format, which means it does not have a fixed bitmap size. However, `UIImage` or `CGImage` are all [bitmap image](https://en.wikipedia.org/wiki/Raster_graphics). For `UIImageView`, we will only parse SVG with a fixed image size (from the SVG viewPort information). But we also support you to specify a desired size during image loading using `SVGImageSize` context option. And you can specify whether or not to keep aspect ratio during scale using `SVGImagePreserveAspectRatio` context option. +Note SVG is a [vector image](https://en.wikipedia.org/wiki/Vector_graphics) format, and UIImageView/NSImageView support rendering vector image as well. Which means you can change the size without losing any details. + Objective-C ```objectivec +// register coder, on AppDelegate SDImageSVGCoder *SVGCoder = [SDImageSVGCoder sharedCoder]; [[SDImageCodersManager sharedManager] addCoder:SVGCoder]; +// load SVG url UIImageView *imageView; -// this arg is optional, if don't provide, use the viewport size instead -CGSize SVGImageSize = CGSizeMake(100, 100); -[imageView sd_setImageWithURL:url placeholderImage:nil options:0 context:@{SDWebImageContextSVGImageSize : @(SVGImageSize)]; +[imageView sd_setImageWithURL:url] +// Changing size +CGRect rect = imageView.frame; +rect.size.width = 200; +rect.size.height = 200; +imageView.frame = rect; ``` + Swift ```swift +// register coder, on AppDelegate let SVGCoder = SDImageSVGCoder.shared SDImageCodersManager.shared.addCoder(SVGCoder) +// load SVG url let imageView: UIImageView imageView.sd_setImage(with: url) -// this arg is optional, if don't provide, use the viewport size instead -let SVGImageSize = CGSize(width: 100, height: 100) -imageView.sd_setImage(with: url, placeholderImage: nil, options: [], context: [.svgImageSize : SVGImageSize]) +// Changing size +var rect = imageView.frame +rect.size.width = 200 +rect.size.height = 200 +imageView.frame = rect ``` -### Use SVGKImageView (render SVG as vector image) - -[SVGKit](https://github.com/SVGKit/SVGKit) also provide some built-in image view class for vector image loading (scale to any size without losing detail). The `SVGKLayeredImageView` && `SVGKFastImageView` are the subclass of `SVGKImageView` base class. We supports these image view class as well. You can just use the same API like normal `UIImageView`. - -For the documentation about `SVGKLayeredImageView`, `SVGKFastImageView` or `SVGKImageView`, check [SVGKit](https://github.com/SVGKit/SVGKit) repo for more information. - -**Note**: If you only use these image view class and don't use SVG on `UIImageView`, you don't need to register the SVG coder to coders manager. These image view loading was using the [Custom Image Class](https://github.com/rs/SDWebImage/wiki/Advanced-Usage#customization) feature of SDWebImage. - -**Attention**: These built-in image view class does not works well on `UIView.contentMode` property, you need to re-scale the layer tree after image was loaded. We provide a simple out-of-box solution to support it. Set the `sd_adjustContentMode` property to `YES` then all things done. - -+ Objective-C - -```objectivec -SVGKImageView *imageView; // can be either `SVGKLayeredImageView` or `SVGKFastImageView` -imageView.contentMode = UIViewContentModeScaleAspectFill; -imageView.sd_adjustContentMode = YES; // make `contentMode` works -[imageView sd_setImageWithURL:url]; -``` - -+ Swift: - -```swift -let imageView: SVGKImageView // can be either `SVGKLayeredImageView` or `SVGKFastImageView` -imageView.contentMode = .aspectFill -imageView.sd_adjustContentMode = true // make `contentMode` works -imageView.sd_setImage(with: url) -``` +Note since UIImageView/NSImageView support this vector rendering, it means this coder plugin can be compatible for [SwiftUI](https://developer.apple.com/xcode/swiftui/). Check [SDWebImageSwiftUI](https://github.com/SDWebImage/SDWebImageSwiftUI/issues/50) for usage. ## Export SVG data -`SDWebImageSVGCoder` provide an easy way to export the SVG image generated from framework, to the original SVG data. +`SDWebImageSVGCoder` provide an easy way to export the SVG image generated by this coder plugin, to the original SVG data. + Objective-C ```objectivec -UIImage *image; // Image generated from SDWebImage framework, actually a `SDSVGImage` instance. +UIImage *image = imageView.image; // Image generated by this coder plugin NSData *imageData = [image sd_imageDataAsFormat:SDImageFormatSVG]; ``` + Swift ```swift -let image; // Image generated from SDWebImage framework, actually a `SDSVGImage` instance. +let image = imageView.image // Image generated by this coder plugin let imageData = image.sd_imageData(as: .SVG) ``` diff --git a/SDWebImageSVGCoder.podspec b/SDWebImageSVGCoder.podspec index 6daca08..76ac835 100644 --- a/SDWebImageSVGCoder.podspec +++ b/SDWebImageSVGCoder.podspec @@ -26,13 +26,13 @@ TODO: Add long description of the pod here. s.author = { 'lizhuoli1126@126.com' => 'lizhuoli1126@126.com' } s.source = { :git => 'https://github.com/SDWebImage/SDWebImageSVGCoder.git', :tag => s.version.to_s } - s.ios.deployment_target = '8.0' - s.tvos.deployment_target = '9.0' - s.osx.deployment_target = '10.10' + s.ios.deployment_target = '13.0' + s.tvos.deployment_target = '13.0' + s.osx.deployment_target = '10.15' + s.watchos.deployment_target = '6.0' s.source_files = 'SDWebImageSVGCoder/Classes/**/*', 'SDWebImageSVGCoder/Module/SDWebImageSVGCoder.h' s.module_map = 'SDWebImageSVGCoder/Module/SDWebImageSVGCoder.modulemap' s.dependency 'SDWebImage/Core', '~> 5.0' - s.dependency 'SVGKit', '>= 2.1' end diff --git a/SDWebImageSVGCoder.xcodeproj/project.pbxproj b/SDWebImageSVGCoder.xcodeproj/project.pbxproj index f0d6c1f..1d421e1 100644 --- a/SDWebImageSVGCoder.xcodeproj/project.pbxproj +++ b/SDWebImageSVGCoder.xcodeproj/project.pbxproj @@ -7,42 +7,27 @@ objects = { /* Begin PBXBuildFile section */ + 3212D8F7237BEF3A00F6C7DA /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32407BFC23799AC400F9AFA4 /* SDWebImage.framework */; }; + 32407BF723799A8A00F9AFA4 /* SDImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133C2170AB0F00DBD6ED /* SDImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32407BF823799A8A00F9AFA4 /* SDImageSVGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B613372170AB0F00DBD6ED /* SDImageSVGCoder.m */; }; + 32407BFB23799A9200F9AFA4 /* SDWebImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613492170AB1600DBD6ED /* SDWebImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 328C14BE2184CEE7006B0C4A /* SDImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133C2170AB0F00DBD6ED /* SDImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 328C14BF2184CEE7006B0C4A /* SDImageSVGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B613372170AB0F00DBD6ED /* SDImageSVGCoder.m */; }; - 328C14C02184CEE7006B0C4A /* SDSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133E2170AB0F00DBD6ED /* SDSVGImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14C12184CEE7006B0C4A /* SDSVGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133A2170AB0F00DBD6ED /* SDSVGImage.m */; }; - 328C14C22184CEE7006B0C4A /* SDWebImageSVGCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133B2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14C32184CEE7006B0C4A /* SDWebImageSVGCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133D2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m */; }; - 328C14C42184CEE7006B0C4A /* SVGKImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613392170AB0F00DBD6ED /* SVGKImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14C52184CEE7006B0C4A /* SVGKImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133F2170AB0F00DBD6ED /* SVGKImageView+WebCache.m */; }; 328C14C62184CEE8006B0C4A /* SDImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133C2170AB0F00DBD6ED /* SDImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 328C14C72184CEE8006B0C4A /* SDImageSVGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B613372170AB0F00DBD6ED /* SDImageSVGCoder.m */; }; - 328C14C82184CEE8006B0C4A /* SDSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133E2170AB0F00DBD6ED /* SDSVGImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14C92184CEE8006B0C4A /* SDSVGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133A2170AB0F00DBD6ED /* SDSVGImage.m */; }; - 328C14CA2184CEE8006B0C4A /* SDWebImageSVGCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133B2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14CB2184CEE8006B0C4A /* SDWebImageSVGCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133D2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m */; }; - 328C14CC2184CEE8006B0C4A /* SVGKImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613392170AB0F00DBD6ED /* SVGKImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14CD2184CEE8006B0C4A /* SVGKImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133F2170AB0F00DBD6ED /* SVGKImageView+WebCache.m */; }; 328C14CE2184CEF3006B0C4A /* SDWebImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613492170AB1600DBD6ED /* SDWebImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 328C14CF2184CEF3006B0C4A /* SDWebImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613492170AB1600DBD6ED /* SDWebImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 328C14D52184D131006B0C4A /* SVGKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 328C14D42184D131006B0C4A /* SVGKit.framework */; }; 328C14D72184D13B006B0C4A /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 328C14D62184D13B006B0C4A /* SDWebImage.framework */; }; - 328C14D82184D148006B0C4A /* SVGKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 328C14D22184D11F006B0C4A /* SVGKit.framework */; }; 328C14D92184D151006B0C4A /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 328C14D02184D111006B0C4A /* SDWebImage.framework */; }; 32B613402170AB0F00DBD6ED /* SDImageSVGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B613372170AB0F00DBD6ED /* SDImageSVGCoder.m */; }; - 32B613422170AB0F00DBD6ED /* SVGKImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613392170AB0F00DBD6ED /* SVGKImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32B613432170AB0F00DBD6ED /* SDSVGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133A2170AB0F00DBD6ED /* SDSVGImage.m */; }; - 32B613442170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133B2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32B613452170AB0F00DBD6ED /* SDImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133C2170AB0F00DBD6ED /* SDImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32B613462170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133D2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m */; }; - 32B613472170AB0F00DBD6ED /* SDSVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B6133E2170AB0F00DBD6ED /* SDSVGImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32B613482170AB0F00DBD6ED /* SVGKImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B6133F2170AB0F00DBD6ED /* SVGKImageView+WebCache.m */; }; 32B6134A2170AB1600DBD6ED /* SDWebImageSVGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B613492170AB1600DBD6ED /* SDWebImageSVGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32B6134D2170B16400DBD6ED /* SVGKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32B6134C2170B16400DBD6ED /* SVGKit.framework */; }; 32B6134F2170B17200DBD6ED /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32B6134E2170B17200DBD6ED /* SDWebImage.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 32407BEF23799A5900F9AFA4 /* SDWebImageSVGCoder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSVGCoder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 32407BFC23799AC400F9AFA4 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/watchOS/SDWebImage.framework; sourceTree = ""; }; 328C14B62184C856006B0C4A /* SDWebImageSVGCoder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSVGCoder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 328C14D02184D111006B0C4A /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/tvOS/SDWebImage.framework; sourceTree = ""; }; 328C14D22184D11F006B0C4A /* SVGKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVGKit.framework; path = Carthage/Build/tvOS/SVGKit.framework; sourceTree = ""; }; @@ -51,28 +36,27 @@ 32B613192170AA2900DBD6ED /* SDWebImageSVGCoder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSVGCoder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 32B613242170AA9300DBD6ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Module/Info.plist; sourceTree = ""; }; 32B613372170AB0F00DBD6ED /* SDImageSVGCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDImageSVGCoder.m; sourceTree = ""; }; - 32B613392170AB0F00DBD6ED /* SVGKImageView+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SVGKImageView+WebCache.h"; sourceTree = ""; }; - 32B6133A2170AB0F00DBD6ED /* SDSVGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDSVGImage.m; sourceTree = ""; }; - 32B6133B2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageSVGCoderDefine.h; sourceTree = ""; }; 32B6133C2170AB0F00DBD6ED /* SDImageSVGCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDImageSVGCoder.h; sourceTree = ""; }; - 32B6133D2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageSVGCoderDefine.m; sourceTree = ""; }; - 32B6133E2170AB0F00DBD6ED /* SDSVGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDSVGImage.h; sourceTree = ""; }; - 32B6133F2170AB0F00DBD6ED /* SVGKImageView+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SVGKImageView+WebCache.m"; sourceTree = ""; }; 32B613492170AB1600DBD6ED /* SDWebImageSVGCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDWebImageSVGCoder.h; path = Module/SDWebImageSVGCoder.h; sourceTree = ""; }; 32B6134C2170B16400DBD6ED /* SVGKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVGKit.framework; path = Carthage/Build/iOS/SVGKit.framework; sourceTree = ""; }; 32B6134E2170B17200DBD6ED /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/iOS/SDWebImage.framework; sourceTree = ""; }; 32B613552170B19800DBD6ED /* SDWebImageSVGCoder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSVGCoder.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 32B613572170B19800DBD6ED /* SDWebImageSVGCoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageSVGCoder.h; sourceTree = ""; }; - 32B613582170B19800DBD6ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 32407BEC23799A5900F9AFA4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3212D8F7237BEF3A00F6C7DA /* SDWebImage.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 328C14B32184C856006B0C4A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 328C14D72184D13B006B0C4A /* SDWebImage.framework in Frameworks */, - 328C14D52184D131006B0C4A /* SVGKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -81,7 +65,6 @@ buildActionMask = 2147483647; files = ( 32B6134F2170B17200DBD6ED /* SDWebImage.framework in Frameworks */, - 32B6134D2170B16400DBD6ED /* SVGKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -90,7 +73,6 @@ buildActionMask = 2147483647; files = ( 328C14D92184D151006B0C4A /* SDWebImage.framework in Frameworks */, - 328C14D82184D148006B0C4A /* SVGKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -101,7 +83,6 @@ isa = PBXGroup; children = ( 32B6131B2170AA2900DBD6ED /* SDWebImageSVGCoder */, - 32B613562170B19800DBD6ED /* SDWebImageSVGCoder */, 32B6131A2170AA2900DBD6ED /* Products */, 32B6134B2170B16400DBD6ED /* Frameworks */, ); @@ -113,6 +94,7 @@ 32B613192170AA2900DBD6ED /* SDWebImageSVGCoder.framework */, 32B613552170B19800DBD6ED /* SDWebImageSVGCoder.framework */, 328C14B62184C856006B0C4A /* SDWebImageSVGCoder.framework */, + 32407BEF23799A5900F9AFA4 /* SDWebImageSVGCoder.framework */, ); name = Products; sourceTree = ""; @@ -132,12 +114,6 @@ children = ( 32B6133C2170AB0F00DBD6ED /* SDImageSVGCoder.h */, 32B613372170AB0F00DBD6ED /* SDImageSVGCoder.m */, - 32B6133E2170AB0F00DBD6ED /* SDSVGImage.h */, - 32B6133A2170AB0F00DBD6ED /* SDSVGImage.m */, - 32B6133B2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h */, - 32B6133D2170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m */, - 32B613392170AB0F00DBD6ED /* SVGKImageView+WebCache.h */, - 32B6133F2170AB0F00DBD6ED /* SVGKImageView+WebCache.m */, ); path = Classes; sourceTree = ""; @@ -146,6 +122,7 @@ isa = PBXGroup; children = ( 328C14D62184D13B006B0C4A /* SDWebImage.framework */, + 32407BFC23799AC400F9AFA4 /* SDWebImage.framework */, 328C14D22184D11F006B0C4A /* SVGKit.framework */, 328C14D42184D131006B0C4A /* SVGKit.framework */, 32B6134E2170B17200DBD6ED /* SDWebImage.framework */, @@ -155,26 +132,23 @@ name = Frameworks; sourceTree = ""; }; - 32B613562170B19800DBD6ED /* SDWebImageSVGCoder */ = { - isa = PBXGroup; - children = ( - 32B613572170B19800DBD6ED /* SDWebImageSVGCoder.h */, - 32B613582170B19800DBD6ED /* Info.plist */, - ); - path = SDWebImageSVGCoder; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 32407BEA23799A5900F9AFA4 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 32407BFB23799A9200F9AFA4 /* SDWebImageSVGCoder.h in Headers */, + 32407BF723799A8A00F9AFA4 /* SDImageSVGCoder.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 328C14B12184C856006B0C4A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 328C14CC2184CEE8006B0C4A /* SVGKImageView+WebCache.h in Headers */, - 328C14C82184CEE8006B0C4A /* SDSVGImage.h in Headers */, 328C14C62184CEE8006B0C4A /* SDImageSVGCoder.h in Headers */, - 328C14CA2184CEE8006B0C4A /* SDWebImageSVGCoderDefine.h in Headers */, 328C14CE2184CEF3006B0C4A /* SDWebImageSVGCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -183,10 +157,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 32B613472170AB0F00DBD6ED /* SDSVGImage.h in Headers */, - 32B613442170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.h in Headers */, 32B613452170AB0F00DBD6ED /* SDImageSVGCoder.h in Headers */, - 32B613422170AB0F00DBD6ED /* SVGKImageView+WebCache.h in Headers */, 32B6134A2170AB1600DBD6ED /* SDWebImageSVGCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -195,17 +166,32 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 328C14C22184CEE7006B0C4A /* SDWebImageSVGCoderDefine.h in Headers */, 328C14BE2184CEE7006B0C4A /* SDImageSVGCoder.h in Headers */, - 328C14C42184CEE7006B0C4A /* SVGKImageView+WebCache.h in Headers */, 328C14CF2184CEF3006B0C4A /* SDWebImageSVGCoder.h in Headers */, - 328C14C02184CEE7006B0C4A /* SDSVGImage.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 32407BEE23799A5900F9AFA4 /* SDWebImageSVGCoder watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 32407BF423799A5900F9AFA4 /* Build configuration list for PBXNativeTarget "SDWebImageSVGCoder watchOS" */; + buildPhases = ( + 32407BEA23799A5900F9AFA4 /* Headers */, + 32407BEB23799A5900F9AFA4 /* Sources */, + 32407BEC23799A5900F9AFA4 /* Frameworks */, + 32407BED23799A5900F9AFA4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SDWebImageSVGCoder watchOS"; + productName = "SDWebImageSVGCoder watchOS"; + productReference = 32407BEF23799A5900F9AFA4 /* SDWebImageSVGCoder.framework */; + productType = "com.apple.product-type.framework"; + }; 328C14B52184C856006B0C4A /* SDWebImageSVGCoder macOS */ = { isa = PBXNativeTarget; buildConfigurationList = 328C14BB2184C856006B0C4A /* Build configuration list for PBXNativeTarget "SDWebImageSVGCoder macOS" */; @@ -269,6 +255,9 @@ LastUpgradeCheck = 1000; ORGANIZATIONNAME = SDWebImageSVGCoder; TargetAttributes = { + 32407BEE23799A5900F9AFA4 = { + CreatedOnToolsVersion = 11.2; + }; 328C14B52184C856006B0C4A = { CreatedOnToolsVersion = 10.0; }; @@ -295,11 +284,19 @@ 32B613182170AA2900DBD6ED /* SDWebImageSVGCoder iOS */, 32B613542170B19800DBD6ED /* SDWebImageSVGCoder tvOS */, 328C14B52184C856006B0C4A /* SDWebImageSVGCoder macOS */, + 32407BEE23799A5900F9AFA4 /* SDWebImageSVGCoder watchOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 32407BED23799A5900F9AFA4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 328C14B42184C856006B0C4A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -324,14 +321,19 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 32407BEB23799A5900F9AFA4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 32407BF823799A8A00F9AFA4 /* SDImageSVGCoder.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 328C14B22184C856006B0C4A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 328C14CB2184CEE8006B0C4A /* SDWebImageSVGCoderDefine.m in Sources */, - 328C14CD2184CEE8006B0C4A /* SVGKImageView+WebCache.m in Sources */, 328C14C72184CEE8006B0C4A /* SDImageSVGCoder.m in Sources */, - 328C14C92184CEE8006B0C4A /* SDSVGImage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -339,10 +341,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 32B613462170AB0F00DBD6ED /* SDWebImageSVGCoderDefine.m in Sources */, - 32B613482170AB0F00DBD6ED /* SVGKImageView+WebCache.m in Sources */, 32B613402170AB0F00DBD6ED /* SDImageSVGCoder.m in Sources */, - 32B613432170AB0F00DBD6ED /* SDSVGImage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -350,16 +349,71 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 328C14C32184CEE7006B0C4A /* SDWebImageSVGCoderDefine.m in Sources */, - 328C14C52184CEE7006B0C4A /* SVGKImageView+WebCache.m in Sources */, 328C14BF2184CEE7006B0C4A /* SDImageSVGCoder.m in Sources */, - 328C14C12184CEE7006B0C4A /* SDSVGImage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ + 32407BF523799A5900F9AFA4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/watchOS", + ); + INFOPLIST_FILE = "$(SRCROOT)/SDWebImageSVGCoder/Module/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImageSVGCoder-watchOS"; + PRODUCT_NAME = SDWebImageSVGCoder; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 6.0; + }; + name = Debug; + }; + 32407BF623799A5900F9AFA4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/watchOS", + ); + INFOPLIST_FILE = "$(SRCROOT)/SDWebImageSVGCoder/Module/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImageSVGCoder-watchOS"; + PRODUCT_NAME = SDWebImageSVGCoder; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 6.0; + }; + name = Release; + }; 328C14BC2184C856006B0C4A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -382,7 +436,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.10; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SDWebImageSVGCoder; PRODUCT_NAME = SDWebImageSVGCoder; SDKROOT = macosx; @@ -412,7 +466,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.10; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SDWebImageSVGCoder; PRODUCT_NAME = SDWebImageSVGCoder; SDKROOT = macosx; @@ -553,7 +607,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/SDWebImageSVGCoder/Module/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -581,7 +635,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/SDWebImageSVGCoder/Module/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -619,7 +673,7 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 13.0; }; name = Debug; }; @@ -648,13 +702,22 @@ SDKROOT = appletvos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.0; + TVOS_DEPLOYMENT_TARGET = 13.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 32407BF423799A5900F9AFA4 /* Build configuration list for PBXNativeTarget "SDWebImageSVGCoder watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 32407BF523799A5900F9AFA4 /* Debug */, + 32407BF623799A5900F9AFA4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 328C14BB2184C856006B0C4A /* Build configuration list for PBXNativeTarget "SDWebImageSVGCoder macOS" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/SDWebImageSVGCoder.xcodeproj/xcshareddata/xcschemes/SDWebImageSVGCoder watchOS.xcscheme b/SDWebImageSVGCoder.xcodeproj/xcshareddata/xcschemes/SDWebImageSVGCoder watchOS.xcscheme new file mode 100644 index 0000000..b9e04b5 --- /dev/null +++ b/SDWebImageSVGCoder.xcodeproj/xcshareddata/xcschemes/SDWebImageSVGCoder watchOS.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SDWebImageSVGCoder/Classes/SDImageSVGCoder.h b/SDWebImageSVGCoder/Classes/SDImageSVGCoder.h index ba6c5c2..0dddf06 100644 --- a/SDWebImageSVGCoder/Classes/SDImageSVGCoder.h +++ b/SDWebImageSVGCoder/Classes/SDImageSVGCoder.h @@ -5,7 +5,7 @@ // Created by DreamPiggy on 2018/9/27. // -#import +@import SDWebImage; NS_ASSUME_NONNULL_BEGIN diff --git a/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m b/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m index 2fe7df5..2c8a1d9 100644 --- a/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m +++ b/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m @@ -6,12 +6,45 @@ // #import "SDImageSVGCoder.h" -#import "SDSVGImage.h" -#import "SDWebImageSVGCoderDefine.h" -#import +#import +#import #define kSVGTagEnd @"" +typedef struct CF_BRIDGED_TYPE(id) CGSVGDocument *CGSVGDocumentRef; +static CGSVGDocumentRef (*CGSVGDocumentCreateFromDataProvider)(CGDataProviderRef provider, CFDictionaryRef options); +static CGSVGDocumentRef (*CGSVGDocumentRetain)(CGSVGDocumentRef); +static void (*CGSVGDocumentRelease)(CGSVGDocumentRef); +static void (*CGSVGDocumentWriteToData)(CGSVGDocumentRef document, CFDataRef data, CFDictionaryRef options); + +#if SD_UIKIT || SD_WATCH + +@interface UIImage (PrivateSVGSupport) + +- (instancetype)_initWithCGSVGDocument:(CGSVGDocumentRef)document; +- (instancetype)_initWithCGSVGDocument:(CGSVGDocumentRef)document scale:(double)scale orientation:(UIImageOrientation)orientation; ++ (instancetype)_imageWithCGSVGDocument:(CGSVGDocumentRef)document; ++ (instancetype)_imageWithCGSVGDocument:(CGSVGDocumentRef)document scale:(double)scale orientation:(UIImageOrientation)orientation; +- (CGSVGDocumentRef)_CGSVGDocument; + +@end + +#endif + +#if SD_MAC + +#define NSSVGImageRepClass @"_NSSVGImageRep" + +@protocol NSSVGImageRepProtocol + +- (instancetype)initWithSVGDocument:(CGSVGDocumentRef)document; +- (instancetype)initWithData:(NSData *)data; +- (CGSVGDocumentRef)_document; + +@end + +#endif + @implementation SDImageSVGCoder + (SDImageSVGCoder *)sharedCoder { @@ -23,6 +56,13 @@ + (SDImageSVGCoder *)sharedCoder { return coder; } ++ (void)initialize { + CGSVGDocumentCreateFromDataProvider = dlsym(RTLD_DEFAULT, "CGSVGDocumentCreateFromDataProvider"); + CGSVGDocumentRetain = dlsym(RTLD_DEFAULT, "CGSVGDocumentRetain"); + CGSVGDocumentRelease = dlsym(RTLD_DEFAULT, "CGSVGDocumentRelease"); + CGSVGDocumentWriteToData = dlsym(RTLD_DEFAULT, "CGSVGDocumentWriteToData"); +} + #pragma mark - Decode - (BOOL)canDecodeFromData:(NSData *)data { @@ -33,44 +73,30 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(SDImageCoderOptions *) if (!data) { return nil; } - // Parse SVG - SVGKImage *svgImage = [[SVGKImage alloc] initWithData:data]; - if (!svgImage) { + if (![self.class supportsVectorSVGImage]) { return nil; } - CGSize imageSize = CGSizeZero; - BOOL preserveAspectRatio = YES; - // Parse args - SDWebImageContext *context = options[SDImageCoderWebImageContext]; - if (context[SDWebImageContextSVGImageSize]) { - NSValue *sizeValue = context[SDWebImageContextSVGImageSize]; -#if SD_UIKIT - imageSize = sizeValue.CGSizeValue; -#else - imageSize = sizeValue.sizeValue; -#endif - } - if (context[SDWebImageContextSVGImagePreserveAspectRatio]) { - preserveAspectRatio = [context[SDWebImageContextSVGImagePreserveAspectRatio] boolValue]; - } - - if (!CGSizeEqualToSize(imageSize, CGSizeZero)) { - if (preserveAspectRatio) { - [svgImage scaleToFitInside:imageSize]; - } else { - svgImage.size = imageSize; - } +#if SD_MAC + Class imageRepClass = NSClassFromString(NSSVGImageRepClass); + NSImageRep *imageRep = [[imageRepClass alloc] initWithData:data]; + if (!imageRep) { + return nil; } - - UIImage *image = svgImage.UIImage; - if (!image) { + NSImage *image = [[NSImage alloc] initWithSize:imageRep.size]; + [image addRepresentation:imageRep]; +#else + CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); + if (!provider) { + return nil; + }; + CGSVGDocumentRef document = CGSVGDocumentCreateFromDataProvider(provider, NULL); + if (!document) { return nil; } - - // SVG is vector image, so no need scale factor - image.sd_imageFormat = SDImageFormatSVG; - + UIImage *image = [UIImage _imageWithCGSVGDocument:document]; + CGSVGDocumentRelease(document); +#endif return image; } @@ -81,24 +107,58 @@ - (BOOL)canEncodeToFormat:(SDImageFormat)format { } - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format options:(SDImageCoderOptions *)options { - // Only support SVGKImage wrapper - if (![image isKindOfClass:SDSVGImage.class]) { + if (!image) { return nil; } - SVGKImage *svgImage = ((SDSVGImage *)image).SVGImage; - if (!svgImage) { + if (![self.class supportsVectorSVGImage]) { return nil; } - SVGKSource *source = svgImage.source; - // Should be NSData type source - if (![source isKindOfClass:SVGKSourceNSData.class]) { + NSMutableData *data = [NSMutableData data]; + CGSVGDocumentRef document = NULL; +#if SD_MAC + NSRect imageRect = NSMakeRect(0, 0, image.size.width, image.size.height); + NSImageRep *imageRep = [image bestRepresentationForRect:imageRect context:nil hints:nil]; + if ([imageRep isKindOfClass:NSClassFromString(NSSVGImageRepClass)]) { + Ivar ivar = class_getInstanceVariable(imageRep.class, "_document"); + document = (__bridge CGSVGDocumentRef)(object_getIvar(imageRep, ivar)); + } +#else + document = [image _CGSVGDocument]; +#endif + if (!document) { return nil; } - return ((SVGKSourceNSData *)source).rawData; + + CGSVGDocumentWriteToData(document, (__bridge CFDataRef)data, NULL); + + return [data copy]; } #pragma mark - Helper ++ (BOOL)supportsVectorSVGImage { + static dispatch_once_t onceToken; + static BOOL supports; + dispatch_once(&onceToken, ^{ +#if SD_MAC + // macOS 10.15+ supports SVG built-in rendering, use selector to check is more accurate + if (NSClassFromString(NSSVGImageRepClass)) { + supports = YES; + } else { + supports = NO; + } +#else + // iOS 13+ supports SVG built-in rendering, use selector to check is more accurate + if ([UIImage respondsToSelector:@selector(_imageWithCGSVGDocument:)]) { + supports = YES; + } else { + supports = NO; + } +#endif + }); + return supports; +} + + (BOOL)isSVGFormatForData:(NSData *)data { if (!data) { return NO; diff --git a/SDWebImageSVGCoder/Classes/SDSVGImage.h b/SDWebImageSVGCoder/Classes/SDSVGImage.h deleted file mode 100644 index c3b31bd..0000000 --- a/SDWebImageSVGCoder/Classes/SDSVGImage.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// SDSVGImage.h -// SDWebImageSVGCoder -// -// Created by DreamPiggy on 2018/10/10. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SDSVGImage : UIImage - -@property (nonatomic, strong, nullable, readonly) SVGKImage *SVGImage; - -/** - Create the wrapper with specify `SVGKImage` instance. The instance should be nonnull. - This is a convenience method for some use cases, for example, create a placeholder with `SVGKImage`. - - @param image The `SVGKImage` instance - @return An initialized object - */ -- (nonnull instancetype)initWithSVGImage:(nonnull SVGKImage *)image; - -// This class override these methods from UIImage -// You should use these methods to create a new SVG image. Use other methods just call super instead. -+ (nullable instancetype)imageWithContentsOfFile:(nonnull NSString *)path; -+ (nullable instancetype)imageWithData:(nonnull NSData *)data; -+ (nullable instancetype)imageWithData:(nonnull NSData *)data scale:(CGFloat)scale; -- (nullable instancetype)initWithContentsOfFile:(nonnull NSString *)path; -- (nullable instancetype)initWithData:(nonnull NSData *)data; -- (nullable instancetype)initWithData:(nonnull NSData *)data scale:(CGFloat)scale; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SDWebImageSVGCoder/Classes/SDSVGImage.m b/SDWebImageSVGCoder/Classes/SDSVGImage.m deleted file mode 100644 index 12112b0..0000000 --- a/SDWebImageSVGCoder/Classes/SDSVGImage.m +++ /dev/null @@ -1,107 +0,0 @@ -// -// SDSVGImage.m -// SDWebImageSVGCoder -// -// Created by DreamPiggy on 2018/10/10. -// - -#import "SDSVGImage.h" -#import "SDWebImageSVGCoderDefine.h" - -@interface SDSVGImage () - -@property (nonatomic, strong, nullable) SVGKImage *SVGImage; - -@end - -@implementation SDSVGImage - -- (instancetype)initWithSVGImage:(SVGKImage *)image { - NSParameterAssert(image); - UIImage *posterImage = image.UIImage; -#if SD_UIKIT - UIImageOrientation imageOrientation = posterImage.imageOrientation; -#else - CGImagePropertyOrientation imageOrientation = kCGImagePropertyOrientationUp; -#endif - self = [super initWithCGImage:posterImage.CGImage scale:posterImage.scale orientation:imageOrientation]; - if (self) { - self.SVGImage = image; - } - return self; -} - -+ (instancetype)imageWithContentsOfFile:(NSString *)path { - return [[self alloc] initWithContentsOfFile:path]; -} - -+ (instancetype)imageWithData:(NSData *)data { - return [[self alloc] initWithData:data]; -} - -+ (instancetype)imageWithData:(NSData *)data scale:(CGFloat)scale { - return [[self alloc] initWithData:data scale:scale]; -} - -- (instancetype)initWithData:(NSData *)data { - return [self initWithData:data scale:1]; -} - -- (instancetype)initWithContentsOfFile:(NSString *)path { - NSData *data = [NSData dataWithContentsOfFile:path]; - return [self initWithData:data]; -} - -- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale { - return [self initWithData:data scale:scale options:nil]; -} - -- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale options:(SDImageCoderOptions *)options { - SVGKImage *svgImage = [[SVGKImage alloc] initWithData:data]; - if (!svgImage) { - return nil; - } - // Check specified image size - SDWebImageContext *context = options[SDImageCoderWebImageContext]; - if (context[SDWebImageContextSVGImageSize]) { - NSValue *sizeValue = context[SDWebImageContextSVGImageSize]; -#if SD_UIKIT - CGSize imageSize = sizeValue.CGSizeValue; -#else - CGSize imageSize = sizeValue.sizeValue; -#endif - if (!CGSizeEqualToSize(imageSize, CGSizeZero)) { - svgImage.size = imageSize; - } - } - return [self initWithSVGImage:svgImage]; -} - -- (instancetype)initWithAnimatedCoder:(id)animatedCoder scale:(CGFloat)scale { - // Does not support progressive load for SVG images at all - return nil; -} - -#pragma mark - SDAnimatedImageProvider - -- (nullable NSData *)animatedImageData { - return nil; -} - -- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { - return 0; -} - -- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { - return nil; -} - -- (NSUInteger)animatedImageFrameCount { - return 0; -} - -- (NSUInteger)animatedImageLoopCount { - return 0; -} - -@end diff --git a/SDWebImageSVGCoder/Classes/SDWebImageSVGCoderDefine.h b/SDWebImageSVGCoder/Classes/SDWebImageSVGCoderDefine.h deleted file mode 100644 index 22497a3..0000000 --- a/SDWebImageSVGCoder/Classes/SDWebImageSVGCoderDefine.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// SDWebImageSVGCoderDefine.h -// SDWebImageSVGCoder -// -// Created by DreamPiggy on 2018/10/11. -// - -#import - -@class SVGKImage; - -#if SD_UIKIT -/** - Adjust `SVGKImage`'s viewPort && viewBox to match the specify `contentMode` of view size. - @note Though this util method can be used outside this framework. For simple SVG image loading, it's recommaned to use `sd_adjustContentMode` property on `SVGKImageView+WebCache`. - - @param svgImage `SVGKImage` instance, should not be nil. - @param contentMode The contentMode to be applied. All possible contentMode are supported. - @param viewSize Target view size, typically specify the `view.bounds.size`. - */ -FOUNDATION_EXPORT void SDAdjustSVGContentMode(SVGKImage * __nonnull svgImage, UIViewContentMode contentMode, CGSize viewSize); -#endif - -/** - A CGSize raw value which specify the desired SVG image size during image loading. Because vector image like SVG format, may not contains a fixed size, or you want to get a larger size bitmap representation UIImage. (NSValue) - If you don't provide this value, use viewBox size of SVG for default value; - */ -FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextSVGImageSize; - -/** - A BOOL value which specify the whether SVG image should keep aspect ratio during image loading. Because when you specify image size via `SDWebImageContextSVGImageSize`, we need to know whether to keep aspect ratio or not when image size aspect ratio is not equal to SVG viewBox size aspect ratio. (NSNumber) - If you don't provide this value, use YES for default value. - */ -FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextSVGImagePreserveAspectRatio; diff --git a/SDWebImageSVGCoder/Classes/SDWebImageSVGCoderDefine.m b/SDWebImageSVGCoder/Classes/SDWebImageSVGCoderDefine.m deleted file mode 100644 index 64ba935..0000000 --- a/SDWebImageSVGCoder/Classes/SDWebImageSVGCoderDefine.m +++ /dev/null @@ -1,156 +0,0 @@ -// -// SDWebImageSVGCoderDefine.m -// SDWebImageSVGCoder -// -// Created by DreamPiggy on 2018/10/11. -// - -#import "SDWebImageSVGCoderDefine.h" -#import - -#if SD_UIKIT -void SDAdjustSVGContentMode(SVGKImage * svgImage, UIViewContentMode contentMode, CGSize viewSize) { - NSCParameterAssert(svgImage); - if (!svgImage.hasSize) { - // `SVGKImage` does not has size, specify the content size, earily return - svgImage.size = viewSize; - return; - } - CGSize imageSize = svgImage.size; - if (imageSize.height == 0 || viewSize.height == 0) { - return; - } - CGFloat wScale = viewSize.width / imageSize.width; - CGFloat hScale = viewSize.height / imageSize.height; - CGFloat imageAspect = imageSize.width / imageSize.height; - CGFloat viewAspect = viewSize.width / viewSize.height; - CGFloat xPosition; - CGFloat yPosition; - - // Geometry calculation - switch (contentMode) { - case UIViewContentModeScaleToFill: { - svgImage.size = viewSize; - } - break; - case UIViewContentModeScaleAspectFit: { - CGFloat scale; - if (imageAspect > viewAspect) { - // scale width - scale = wScale; - } else { - // scale height - scale = hScale; - } - CGSize targetSize = CGSizeApplyAffineTransform(imageSize, CGAffineTransformMakeScale(scale, scale)); - if (imageAspect > viewAspect) { - // need center y as well - xPosition = 0; - yPosition = ABS(targetSize.height - viewSize.height) / 2; - } else { - // need center x as well - xPosition = ABS(targetSize.width - viewSize.width) / 2; - yPosition = 0; - } - svgImage.size = targetSize; - svgImage.DOMTree.viewport = SVGRectMake(xPosition, yPosition, targetSize.width, targetSize.height); - // masksToBounds to clip the sublayer which beyond the viewport to match `UIImageView` behavior - svgImage.CALayerTree.masksToBounds = YES; - } - break; - case UIViewContentModeScaleAspectFill: { - CGFloat scale; - if (imageAspect < viewAspect) { - // scale width - scale = wScale; - } else { - // scale height - scale = hScale; - } - CGSize targetSize = CGSizeApplyAffineTransform(imageSize, CGAffineTransformMakeScale(scale, scale)); - if (imageAspect < viewAspect) { - // need center y as well - xPosition = 0; - yPosition = ABS(targetSize.height - viewSize.height) / 2; - } else { - // need center x as well - xPosition = ABS(targetSize.width - viewSize.width) / 2; - yPosition = 0; - } - svgImage.size = targetSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeTop: { - xPosition = (imageSize.width - viewSize.width) / 2; - yPosition = 0; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeTopLeft: { - xPosition = 0; - yPosition = 0; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeTopRight: { - xPosition = imageSize.width - viewSize.width; - yPosition = 0; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeCenter: { - xPosition = (imageSize.width - viewSize.width) / 2; - yPosition = (imageSize.height - viewSize.height) / 2; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeLeft: { - xPosition = 0; - yPosition = (imageSize.height - viewSize.height) / 2; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeRight: { - xPosition = imageSize.width - viewSize.width; - yPosition = (imageSize.height - viewSize.height) / 2; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeBottom: { - xPosition = (imageSize.width - viewSize.width) / 2; - yPosition = imageSize.height - viewSize.height; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeBottomLeft: { - xPosition = 0; - yPosition = imageSize.height - viewSize.height; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeBottomRight: { - xPosition = imageSize.width - viewSize.width; - yPosition = imageSize.height - viewSize.height; - svgImage.size = imageSize; - svgImage.DOMTree.viewBox = SVGRectMake(xPosition, yPosition, imageSize.width, imageSize.height); - } - break; - case UIViewContentModeRedraw: { - svgImage.CALayerTree.needsDisplayOnBoundsChange = YES; - } - break; - } -} -#endif - -SDWebImageContextOption _Nonnull const SDWebImageContextSVGImageSize = @"svgImageSize"; -SDWebImageContextOption _Nonnull const SDWebImageContextSVGImagePreserveAspectRatio = @"svgImagePreserveAspectRatio"; diff --git a/SDWebImageSVGCoder/Classes/SVGKImageView+WebCache.h b/SDWebImageSVGCoder/Classes/SVGKImageView+WebCache.h deleted file mode 100644 index 415614f..0000000 --- a/SDWebImageSVGCoder/Classes/SVGKImageView+WebCache.h +++ /dev/null @@ -1,169 +0,0 @@ -// -// SVGKImageView+WebCache.h -// SDWebImageSVGCoder -// -// Created by DreamPiggy on 2018/10/10. -// - -#import -#import "SDWebImageSVGCoderDefine.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SVGKImageView (WebCache) - -/** - * Unlike `UIView`, `SVGKImageView`'s subclass does not follows `UIView.contentMode` property, the position of SVG vector image is controled by `SVGKImage` instance with SVG's viewport && viewbox information. You can adjust it after image was loading, however it's not so convenient. - * So we provide a simple solution. If you want the same behavior like UIImageView to use `contentMode` property to position SVG images, set this value to YES and we'll resize the SVG image to correspond `contentMode` of `SVGKImageView` during image loading. - */ -@property (nonatomic, assign) BOOL sd_adjustContentMode API_UNAVAILABLE(macos); - -/** - * Set the imageView `image` with an `url`. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT; - -/** - * Set the imageView `image` with an `url` and a placeholder. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @see sd_setImageWithURL:placeholderImage:options: - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT; - -/** - * Set the imageView `image` with an `url`, placeholder and custom options. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT; - -/** - * Set the imageView `image` with an `url`, placeholder, custom options and context. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. - * @param context A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - options:(SDWebImageOptions)options - context:(nullable SDWebImageContext *)context; - -/** - * Set the imageView `image` with an `url`. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param completedBlock A block called when operation has been completed. This block has no return value - * and takes the requested UIImage as first parameter. In case of error the image parameter - * is nil and the second parameter may contain an NSError. The third parameter is a Boolean - * indicating if the image was retrieved from the local cache or from the network. - * The fourth parameter is the original image url. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - completed:(nullable SDExternalCompletionBlock)completedBlock; - -/** - * Set the imageView `image` with an `url`, placeholder. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @param completedBlock A block called when operation has been completed. This block has no return value - * and takes the requested UIImage as first parameter. In case of error the image parameter - * is nil and the second parameter may contain an NSError. The third parameter is a Boolean - * indicating if the image was retrieved from the local cache or from the network. - * The fourth parameter is the original image url. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - completed:(nullable SDExternalCompletionBlock)completedBlock NS_REFINED_FOR_SWIFT; - -/** - * Set the imageView `image` with an `url`, placeholder and custom options. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. - * @param completedBlock A block called when operation has been completed. This block has no return value - * and takes the requested UIImage as first parameter. In case of error the image parameter - * is nil and the second parameter may contain an NSError. The third parameter is a Boolean - * indicating if the image was retrieved from the local cache or from the network. - * The fourth parameter is the original image url. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - options:(SDWebImageOptions)options - completed:(nullable SDExternalCompletionBlock)completedBlock; - -/** - * Set the imageView `image` with an `url`, placeholder and custom options. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. - * @param progressBlock A block called while image is downloading - * @note the progress block is executed on a background queue - * @param completedBlock A block called when operation has been completed. This block has no return value - * and takes the requested UIImage as first parameter. In case of error the image parameter - * is nil and the second parameter may contain an NSError. The third parameter is a Boolean - * indicating if the image was retrieved from the local cache or from the network. - * The fourth parameter is the original image url. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - options:(SDWebImageOptions)options - progress:(nullable SDImageLoaderProgressBlock)progressBlock - completed:(nullable SDExternalCompletionBlock)completedBlock; - -/** - * Set the imageView `image` with an `url`, placeholder, custom options and context. - * - * The download is asynchronous and cached. - * - * @param url The url for the image. - * @param placeholder The image to be set initially, until the image request finishes. - * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values. - * @param context A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold. - * @param progressBlock A block called while image is downloading - * @note the progress block is executed on a background queue - * @param completedBlock A block called when operation has been completed. This block has no return value - * and takes the requested UIImage as first parameter. In case of error the image parameter - * is nil and the second parameter may contain an NSError. The third parameter is a Boolean - * indicating if the image was retrieved from the local cache or from the network. - * The fourth parameter is the original image url. - */ -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - options:(SDWebImageOptions)options - context:(nullable SDWebImageContext *)context - progress:(nullable SDImageLoaderProgressBlock)progressBlock - completed:(nullable SDExternalCompletionBlock)completedBlock; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SDWebImageSVGCoder/Classes/SVGKImageView+WebCache.m b/SDWebImageSVGCoder/Classes/SVGKImageView+WebCache.m deleted file mode 100644 index 53fec56..0000000 --- a/SDWebImageSVGCoder/Classes/SVGKImageView+WebCache.m +++ /dev/null @@ -1,102 +0,0 @@ -// -// SVGKImageView+WebCache.m -// SDWebImageSVGCoder -// -// Created by DreamPiggy on 2018/10/10. -// - -#import "SVGKImageView+WebCache.h" -#import "SDSVGImage.h" -#import - -@implementation SVGKImageView (WebCache) - -- (void)setSd_adjustContentMode:(BOOL)sd_adjustContentMode { - objc_setAssociatedObject(self, @selector(sd_adjustContentMode), @(sd_adjustContentMode), OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (BOOL)sd_adjustContentMode { - NSNumber *value = objc_getAssociatedObject(self, @selector(sd_adjustContentMode)); - return value.boolValue; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url { - [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder { - [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options { - [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context { - [self sd_setImageWithURL:url placeholderImage:placeholder options:options context:context progress:nil completed:nil]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock { - [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock { - [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock { - [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options progress:(nullable SDImageLoaderProgressBlock)progressBlock completed:(nullable SDExternalCompletionBlock)completedBlock { - [self sd_setImageWithURL:url placeholderImage:placeholder options:options context:nil progress:progressBlock completed:completedBlock]; -} - -- (void)sd_setImageWithURL:(nullable NSURL *)url - placeholderImage:(nullable UIImage *)placeholder - options:(SDWebImageOptions)options - context:(nullable SDWebImageContext *)context - progress:(nullable SDImageLoaderProgressBlock)progressBlock - completed:(nullable SDExternalCompletionBlock)completedBlock { - Class imageClass = [SDSVGImage class]; - SDWebImageMutableContext *mutableContext; - if (context) { - mutableContext = [context mutableCopy]; - } else { - mutableContext = [NSMutableDictionary dictionary]; - } - mutableContext[SDWebImageContextAnimatedImageClass] = imageClass; - __weak typeof(self)weakSelf = self; - [self sd_internalSetImageWithURL:url - placeholderImage:placeholder - options:options - context:mutableContext - setImageBlock:^(UIImage * _Nullable image, NSData * _Nullable imageData, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { - __strong typeof(weakSelf)strongSelf = weakSelf; - if (!strongSelf) { - return; - } - SVGKImage *svgImage; - if ([image isKindOfClass:[SDSVGImage class]]) { - svgImage = ((SDSVGImage *)image).SVGImage; - } - if (svgImage) { -#if SD_UIKIT - if (self.sd_adjustContentMode) { - SDAdjustSVGContentMode(svgImage, strongSelf.contentMode, strongSelf.bounds.size); - } -#endif - strongSelf.image = svgImage; - } else { - strongSelf.image = nil; - } - } - progress:progressBlock - completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { - if (completedBlock) { - completedBlock(image, error, cacheType, imageURL); - } - }]; -} - -@end diff --git a/SDWebImageSVGCoder/Module/SDWebImageSVGCoder.h b/SDWebImageSVGCoder/Module/SDWebImageSVGCoder.h index 831c1bb..f5feebe 100644 --- a/SDWebImageSVGCoder/Module/SDWebImageSVGCoder.h +++ b/SDWebImageSVGCoder/Module/SDWebImageSVGCoder.h @@ -10,9 +10,6 @@ #endif #import -#import -#import -#import FOUNDATION_EXPORT double SDWebImageSVGCoderVersionNumber; FOUNDATION_EXPORT const unsigned char SDWebImageSVGCoderVersionString[];