From 2fe1ac2a83abfe9d0cd0f152aeb04cd88d78a0d2 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Tue, 11 Aug 2015 06:21:12 -0700 Subject: [PATCH] [Image] Fix invalid CGContext when one dimension of destination Image size == 0 Summary: Addresses #1534 When an image has a known width, but a height of 0 (which can happen if `flex: 1` is set on the `Image` element), `RCTDownloadManager` attempts to scale it to an invalid size, which results in a `NULL` `CGContextRef` and some scary warnings from UIKit: ``` : CGContextTranslateCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update. ``` This adds a check for zero width or height to the `RCTClipRect` function. If either dimension is zero, it is calculated based on the aspect ratio of the source image. This ensures that we don't try to create an invalid `CGContextRef`, and that images with an unknown dimension are still scaled, blended, etc. Closes https://github.com/facebook/react-native/pull/2278 Github Author: Yusef Napora --- Libraries/Image/RCTImageUtils.m | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Libraries/Image/RCTImageUtils.m b/Libraries/Image/RCTImageUtils.m index 7b2d88ebc..82a97a778 100644 --- a/Libraries/Image/RCTImageUtils.m +++ b/Libraries/Image/RCTImageUtils.m @@ -51,10 +51,20 @@ CGRect RCTClipRect(CGSize sourceSize, CGFloat sourceScale, sourceSize.width *= scale; sourceSize.height *= scale; - // Calculate aspect ratios if needed (don't bother if resizeMode == stretch) - CGFloat aspect = 0.0, targetAspect = 0.0; + CGFloat aspect = sourceSize.width / sourceSize.height; + // If only one dimension in destSize is non-zero (for example, an Image + // with `flex: 1` whose height is indeterminate), calculate the unknown + // dimension based on the aspect ratio of sourceSize + if (destSize.width == 0) { + destSize.width = destSize.height * aspect; + } + if (destSize.height == 0) { + destSize.height = destSize.width / aspect; + } + + // Calculate target aspect ratio if needed (don't bother if resizeMode == stretch) + CGFloat targetAspect = 0.0; if (resizeMode != UIViewContentModeScaleToFill) { - aspect = sourceSize.width / sourceSize.height; targetAspect = destSize.width / destSize.height; if (aspect == targetAspect) { resizeMode = UIViewContentModeScaleToFill;