Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASImageNode]fix incorrect backing size calculation #1189

Merged
merged 9 commits into from
Mar 29, 2019
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## master
* Add your own contributions to the next release on the line below this with your name.
- [ASImageNode] Fix incorrect backing size calculation. [Junjie Lu](https://github.com/junjielu). [#1189](https://github.com/TextureGroup/Texture/pull/1189)
- [ASDisplayNode.m] Make sure node is loaded before enter visible. [Max Wang](https://github.com/wsdwsd0829). [#886](https://github.com/TextureGroup/Texture/pull/886)
- [ASTextNode2] Add improved support for all line-break modes in experimental text node. [Kevin Smith](https://github.com/wiseoldduck). [#1150](https://github.com/TextureGroup/Texture/pull/1150)
- [ASExperimentalFeatures.m] Fix mismatch name in experimental features. [Max Wang](https://github.com/wsdwsd0829). [#1159](https://github.com/TextureGroup/Texture/pull/1159)
Expand Down
47 changes: 24 additions & 23 deletions Source/Private/ASImageNode+CGExtras.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,27 @@ void ASCroppedImageBackingSizeAndDrawRectInBounds(CGSize sourceImageSize,
// Per the API contract as commented in the header, we will adjust input parameters (destinationWidth, destinationHeight) to ensure that the image is not upscaled on the CPU.
CGFloat boundsAspectRatio = (CGFloat)destinationWidth / (CGFloat)destinationHeight;

CGSize scaledSizeForImage = sourceImageSize;
CGSize minimumDestinationSize = sourceImageSize;
BOOL cropToRectDimensions = !CGRectIsEmpty(cropRect);

// Given image size and container ratio, calculate minimum container size for the image under different contentMode
if (cropToRectDimensions) {
scaledSizeForImage = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height);
minimumDestinationSize = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height);
} else {
if (contentMode == UIViewContentModeScaleAspectFill)
scaledSizeForImage = _ASSizeFillWithAspectRatio(boundsAspectRatio, sourceImageSize);
minimumDestinationSize = _ASSizeFitWithAspectRatio(boundsAspectRatio, sourceImageSize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is of course the meat of the fix

else if (contentMode == UIViewContentModeScaleAspectFit)
scaledSizeForImage = _ASSizeFitWithAspectRatio(boundsAspectRatio, sourceImageSize);
minimumDestinationSize = _ASSizeFillWithAspectRatio(boundsAspectRatio, sourceImageSize);
}

// If fitting the desired aspect ratio to the image size actually results in a larger buffer, use the input values.
// However, if there is a pixel savings (e.g. we would have to upscale the image), override the function arguments.
if (CGSizeEqualToSize(CGSizeZero, forcedSize) == NO) {
destinationWidth = (size_t)round(forcedSize.width);
destinationHeight = (size_t)round(forcedSize.height);
} else if (forceUpscaling == NO && (scaledSizeForImage.width * scaledSizeForImage.height) < (destinationWidth * destinationHeight)) {
destinationWidth = (size_t)round(scaledSizeForImage.width);
destinationHeight = (size_t)round(scaledSizeForImage.height);
} else if (forceUpscaling == NO && (minimumDestinationSize.width * minimumDestinationSize.height) < (destinationWidth * destinationHeight)) {
destinationWidth = (size_t)round(minimumDestinationSize.width);
destinationHeight = (size_t)round(minimumDestinationSize.height);
if (destinationWidth == 0 || destinationHeight == 0) {
*outBackingSize = CGSizeZero;
*outDrawRect = CGRectZero;
Expand All @@ -82,39 +83,39 @@ void ASCroppedImageBackingSizeAndDrawRectInBounds(CGSize sourceImageSize,

// Figure out the scaled size within the destination bounds.
CGFloat sourceImageAspectRatio = sourceImageSize.width / sourceImageSize.height;
CGSize scaledSizeForDestination = CGSizeMake(destinationWidth, destinationHeight);
CGSize scaledSizeForImage = CGSizeMake(destinationWidth, destinationHeight);

if (cropToRectDimensions) {
scaledSizeForDestination = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height);
scaledSizeForImage = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height);
} else {
if (contentMode == UIViewContentModeScaleAspectFill)
scaledSizeForDestination = _ASSizeFillWithAspectRatio(sourceImageAspectRatio, scaledSizeForDestination);
scaledSizeForImage = _ASSizeFillWithAspectRatio(sourceImageAspectRatio, scaledSizeForImage);
else if (contentMode == UIViewContentModeScaleAspectFit)
scaledSizeForDestination = _ASSizeFitWithAspectRatio(sourceImageAspectRatio, scaledSizeForDestination);
scaledSizeForImage = _ASSizeFitWithAspectRatio(sourceImageAspectRatio, scaledSizeForImage);
}

// Figure out the rectangle into which to draw the image.
CGRect drawRect = CGRectZero;
if (cropToRectDimensions) {
drawRect = CGRectMake(-cropRect.origin.x * scaledSizeForDestination.width,
-cropRect.origin.y * scaledSizeForDestination.height,
scaledSizeForDestination.width,
scaledSizeForDestination.height);
drawRect = CGRectMake(-cropRect.origin.x * scaledSizeForImage.width,
-cropRect.origin.y * scaledSizeForImage.height,
scaledSizeForImage.width,
scaledSizeForImage.height);
} else {
// We want to obey the origin of cropRect in aspect-fill mode.
if (contentMode == UIViewContentModeScaleAspectFill) {
drawRect = CGRectMake(((destinationWidth - scaledSizeForDestination.width) * cropRect.origin.x),
((destinationHeight - scaledSizeForDestination.height) * cropRect.origin.y),
scaledSizeForDestination.width,
scaledSizeForDestination.height);
drawRect = CGRectMake(((destinationWidth - scaledSizeForImage.width) * cropRect.origin.x),
((destinationHeight - scaledSizeForImage.height) * cropRect.origin.y),
scaledSizeForImage.width,
scaledSizeForImage.height);

}
// And otherwise just center it.
else {
drawRect = CGRectMake(((destinationWidth - scaledSizeForDestination.width) / 2.0),
((destinationHeight - scaledSizeForDestination.height) / 2.0),
scaledSizeForDestination.width,
scaledSizeForDestination.height);
drawRect = CGRectMake(((destinationWidth - scaledSizeForImage.width) / 2.0),
((destinationHeight - scaledSizeForImage.height) / 2.0),
scaledSizeForImage.width,
scaledSizeForImage.height);
}
}

Expand Down