Generalized image decoding and resizing logic

Summary:
public

Standardises the image decoding logic for all image sources, meaning we get the benefits of efficient downscaling of images from all sources, not just ALAssets.

Reviewed By: javache

Differential Revision: D2647083

fb-gh-sync-id: e41456f838e4c6ab709b1c1523f651a86ff6e623
This commit is contained in:
Nick Lockwood
2016-01-20 11:03:22 -08:00
committed by facebook-github-bot-5
parent 9b87e6c860
commit 21fcbbc32c
30 changed files with 510 additions and 379 deletions

View File

@@ -103,8 +103,15 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (void)setCapInsets:(UIEdgeInsets)capInsets
{
if (!UIEdgeInsetsEqualToEdgeInsets(_capInsets, capInsets)) {
_capInsets = capInsets;
[self updateImage];
if (UIEdgeInsetsEqualToEdgeInsets(_capInsets, UIEdgeInsetsZero) ||
UIEdgeInsetsEqualToEdgeInsets(capInsets, UIEdgeInsetsZero)) {
_capInsets = capInsets;
// Need to reload image when enabling or disabling capInsets
[self reloadImage];
} else {
_capInsets = capInsets;
[self updateImage];
}
}
}
@@ -126,12 +133,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (BOOL)sourceNeedsReload
{
NSString *scheme = _source.imageURL.scheme;
return
[scheme isEqualToString:@"http"] ||
[scheme isEqualToString:@"https"] ||
[scheme isEqualToString:@"assets-library"] ||
[scheme isEqualToString:@"ph"];
// If capInsets are set, image doesn't need reloading when resized
return UIEdgeInsetsEqualToEdgeInsets(_capInsets, UIEdgeInsetsZero);
}
- (void)setContentMode:(UIViewContentMode)contentMode
@@ -179,14 +182,22 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
};
}
CGSize imageSize = self.bounds.size;
CGFloat imageScale = RCTScreenScale();
if (!UIEdgeInsetsEqualToEdgeInsets(_capInsets, UIEdgeInsetsZero)) {
// Don't resize images that use capInsets
imageSize = CGSizeZero;
imageScale = _source.scale;
}
RCTImageSource *source = _source;
__weak RCTImageView *weakSelf = self;
_reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithTag:_source.imageURL.absoluteString
size:self.bounds.size
scale:RCTScreenScale()
resizeMode:self.contentMode
progressBlock:progressHandler
completionBlock:^(NSError *error, UIImage *image) {
_reloadImageCancellationBlock = [_bridge.imageLoader loadImageWithoutClipping:_source.imageURL.absoluteString
size:imageSize
scale:imageScale
resizeMode:(RCTResizeMode)self.contentMode
progressBlock:progressHandler
completionBlock:^(NSError *error, UIImage *image) {
dispatch_async(dispatch_get_main_queue(), ^{
RCTImageView *strongSelf = weakSelf;
if (![source isEqual:strongSelf.source]) {
@@ -227,14 +238,15 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
[self reloadImage];
} else if ([self sourceNeedsReload]) {
CGSize imageSize = self.image.size;
CGSize idealSize = RCTTargetSize(imageSize, self.image.scale, frame.size, RCTScreenScale(), self.contentMode, YES);
CGSize idealSize = RCTTargetSize(imageSize, self.image.scale, frame.size,
RCTScreenScale(), (RCTResizeMode)self.contentMode, YES);
if (RCTShouldReloadImageForSizeChange(imageSize, idealSize)) {
if (RCTShouldReloadImageForSizeChange(_targetSize, idealSize)) {
RCTLogInfo(@"[PERF IMAGEVIEW] Reloading image %@ as size %@", _source.imageURL, NSStringFromCGSize(idealSize));
// If the existing image or an image being loaded are not the right size, reload the asset in case there is a
// better size available.
// If the existing image or an image being loaded are not the right
// size, reload the asset in case there is a better size available.
_targetSize = idealSize;
[self reloadImage];
}
@@ -251,8 +263,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
[super didMoveToWindow];
if (!self.window) {
// Don't keep self alive through the asynchronous dispatch, if the intention was to remove the view so it would
// deallocate.
// Don't keep self alive through the asynchronous dispatch, if the intention
// was to remove the view so it would deallocate.
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
@@ -261,7 +273,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return;
}
// If we haven't been re-added to a window by this run loop iteration, clear out the image to save memory.
// If we haven't been re-added to a window by this run loop iteration,
// clear out the image to save memory.
if (!strongSelf.window) {
[strongSelf clearImage];
}