Skip to content

Commit

Permalink
Merge pull request #29 from SDWebImage/update_vector_resize_behavior
Browse files Browse the repository at this point in the history
Update the calculation of bitmap image based on more complicated rules for most use cases
  • Loading branch information
dreampiggy authored Dec 16, 2020
2 parents 7251c34 + 86393a6 commit 5038c71
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 18 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 45 additions & 18 deletions SDWebImageSVGCoder/Classes/SDImageSVGCoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 5038c71

Please sign in to comment.