From 86393a67b499254cdf86d645de9c5aaa4ad31f5e Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 14 Dec 2020 16:26:44 +0800 Subject: [PATCH] Update the calculation of bitmap image based on more complicated rules for most use cases --- README.md | 13 ++++ SDWebImageSVGCoder/Classes/SDImageSVGCoder.m | 63 ++++++++++++++------ 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f971256..d4b59bf 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,19 @@ In most cases, vector SVG is preferred. But however, sometimes you may want the By default it use the SVG viewBox size. You can also specify a desired size during image loading using `.imageThumbnailPixelSize` context option. And you can specify whether or not to keep aspect ratio during scale using `.imagePreserveAspectRatio` context option. +Note: When using `imageThumbnailPixelSize`, pass 0 for width or height will remove the limit of this length. For example, given a SVG image which original size is `(40,50)`: + +| preserve aspect ratio | width | height | effect | +| --- | --- | --- | --- | +| true | 50 | 50 | (40,50) | +| true | 0 | 100 | (80,100) | +| true | 20 | 0 | (20,25) | +| true | 0 | 0 | (40,50) | +| false | 50 | 50 | (50,50) | +| false | 0 | 100 | (40,100) | +| false | 20 | 0 | (20,50) | +| false | 0 | 0 | (40,50) | + Note: Once you pass the `imageThumbnailPixelSize`, we will always generate the bitmap representation. If you do want the vector format, do not pass them, let `UIImageView` to dynamically stretch the SVG. + Objective-C diff --git a/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m b/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m index 84328ca..975a435 100644 --- a/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m +++ b/SDWebImageSVGCoder/Classes/SDImageSVGCoder.m @@ -192,28 +192,55 @@ - (UIImage *)createBitmapSVGWithData:(nonnull NSData *)data targetSize:(CGSize)t } CGSize size = SDCGSVGDocumentGetCanvasSize(document); - CGRect rect = CGRectMake(0, 0, size.width, size.height); - CGRect targetRect = rect; - if (!CGSizeEqualToSize(targetSize, CGSizeZero)) { - targetRect = CGRectMake(0, 0, targetSize.width, targetSize.height); + // Invalid size + if (size.width == 0 || size.height == 0) { + return nil; } - CGFloat xRatio = targetRect.size.width / rect.size.width; - CGFloat yRatio = targetRect.size.height / rect.size.height; - - // If we specify only one length of the size (width or height) we want to keep the ratio for that length - if (preserveAspectRatio) { - if (xRatio <= 0) { - xRatio = yRatio; - targetRect.size = CGSizeMake(rect.size.width * xRatio, targetSize.height); - } else if (yRatio <= 0) { - yRatio = xRatio; - targetRect.size = CGSizeMake(targetSize.width, rect.size.height * yRatio); + CGFloat xScale; + CGFloat yScale; + // Calculation for actual target size, see rules in documentation + if (targetSize.width <= 0 && targetSize.height <= 0) { + // Both width and height is 0, use original size + targetSize.width = size.width; + targetSize.height = size.height; + xScale = 1; + yScale = 1; + } else { + CGFloat xRatio = targetSize.width / size.width; + CGFloat yRatio = targetSize.height / size.height; + if (preserveAspectRatio) { + // If we specify only one length of the size (width or height) we want to keep the ratio for that length + if (targetSize.width <= 0) { + yScale = yRatio; + xScale = yRatio; + targetSize.width = size.width * yRatio; + } else if (targetSize.height <= 0) { + xScale = xRatio; + yScale = xRatio; + targetSize.height = size.height * xRatio; + } else { + xScale = MIN(xRatio, yRatio); + yScale = MIN(xRatio, yRatio); + } + } else { + // If we specify only one length of the size but don't keep the ratio, use original size + if (targetSize.width <= 0) { + targetSize.width = size.width; + yScale = yRatio; + xScale = 1; + } else if (targetSize.height <= 0) { + xScale = xRatio; + yScale = 1; + targetSize.height = size.height; + } else { + xScale = xRatio; + yScale = yRatio; + } } } - - CGFloat xScale = preserveAspectRatio ? MIN(xRatio, yRatio) : xRatio; - CGFloat yScale = preserveAspectRatio ? MIN(xRatio, yRatio) : yRatio; + CGRect rect = CGRectMake(0, 0, size.width, size.height); + CGRect targetRect = CGRectMake(0, 0, targetSize.width, targetSize.height); CGAffineTransform scaleTransform = CGAffineTransformMakeScale(xScale, yScale); CGAffineTransform transform = CGAffineTransformIdentity;