diff --git a/Libraries/Image/RCTImageBlurUtils.m b/Libraries/Image/RCTImageBlurUtils.m index 4dc2c7654f..d40cd2d0da 100644 --- a/Libraries/Image/RCTImageBlurUtils.m +++ b/Libraries/Image/RCTImageBlurUtils.m @@ -22,10 +22,13 @@ UIImage *RCTBlurredImageWithRadius(UIImage *inputImage, CGFloat radius) if (CGImageGetBitsPerPixel(imageRef) != 32 || CGImageGetBitsPerComponent(imageRef) != 8 || !((CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask))) { - UIGraphicsBeginImageContextWithOptions(inputImage.size, NO, inputImage.scale); - [inputImage drawAtPoint:CGPointZero]; - imageRef = UIGraphicsGetImageFromCurrentImageContext().CGImage; - UIGraphicsEndImageContext(); + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + rendererFormat.scale = inputImage.scale; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:inputImage.size format:rendererFormat]; + + imageRef = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull context) { + [inputImage drawAtPoint:CGPointZero]; + }].CGImage; } vImage_Buffer buffer1, buffer2; @@ -51,7 +54,7 @@ UIImage *RCTBlurredImageWithRadius(UIImage *inputImage, CGFloat radius) //create temp buffer vImage_Error tempBufferSize = vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize, - NULL, kvImageGetTempBufferSize | kvImageEdgeExtend); + NULL, kvImageGetTempBufferSize | kvImageEdgeExtend); if (tempBufferSize < 0) { free(buffer1.data); free(buffer2.data); diff --git a/Libraries/Image/RCTImageUtils.m b/Libraries/Image/RCTImageUtils.m index d75b6f12d9..2724a3d6c0 100644 --- a/Libraries/Image/RCTImageUtils.m +++ b/Libraries/Image/RCTImageUtils.m @@ -370,13 +370,14 @@ UIImage *__nullable RCTTransformImage(UIImage *image, } BOOL opaque = !RCTImageHasAlpha(image.CGImage); - UIGraphicsBeginImageContextWithOptions(destSize, opaque, destScale); - CGContextRef currentContext = UIGraphicsGetCurrentContext(); - CGContextConcatCTM(currentContext, transform); - [image drawAtPoint:CGPointZero]; - UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return result; + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + rendererFormat.opaque = opaque; + rendererFormat.scale = destScale; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:destSize format:rendererFormat]; + return [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull context) { + CGContextConcatCTM(context.CGContext, transform); + [image drawAtPoint:CGPointZero]; + }]; } BOOL RCTImageHasAlpha(CGImageRef image) diff --git a/React/Views/RCTBorderDrawing.m b/React/Views/RCTBorderDrawing.m index 140b9877f6..df3d9e1cd9 100644 --- a/React/Views/RCTBorderDrawing.m +++ b/React/Views/RCTBorderDrawing.m @@ -172,13 +172,15 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn return RCTPathCreateWithRoundedRect(rect, RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero), NULL); } -static CGContextRef -RCTUIGraphicsBeginImageContext(CGSize size, CGColorRef backgroundColor, BOOL hasCornerRadii, BOOL drawToEdge) +static UIGraphicsImageRenderer * +RCTUIGraphicsImageRenderer(CGSize size, CGColorRef backgroundColor, BOOL hasCornerRadii, BOOL drawToEdge) { const CGFloat alpha = CGColorGetAlpha(backgroundColor); const BOOL opaque = (drawToEdge || !hasCornerRadii) && alpha == 1.0; - UIGraphicsBeginImageContextWithOptions(size, opaque, 0.0); - return UIGraphicsGetCurrentContext(); + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + rendererFormat.opaque = opaque; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:rendererFormat]; + return renderer; } static UIImage *RCTGetSolidBorderImage( @@ -229,164 +231,166 @@ static UIImage *RCTGetSolidBorderImage( edgeInsets.top + 1 + edgeInsets.bottom } : viewSize; - CGContextRef ctx = RCTUIGraphicsBeginImageContext(size, backgroundColor, hasCornerRadii, drawToEdge); - const CGRect rect = {.size = size}; - CGPathRef path = RCTPathCreateOuterOutline(drawToEdge, rect, cornerRadii); + UIGraphicsImageRenderer *const imageRenderer = + RCTUIGraphicsImageRenderer(size, backgroundColor, hasCornerRadii, drawToEdge); + UIImage *image = [imageRenderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) { + const CGContextRef context = rendererContext.CGContext; + const CGRect rect = {.size = size}; + CGPathRef path = RCTPathCreateOuterOutline(drawToEdge, rect, cornerRadii); - if (backgroundColor) { - CGContextSetFillColorWithColor(ctx, backgroundColor); - CGContextAddPath(ctx, path); - CGContextFillPath(ctx); - } + if (backgroundColor) { + CGContextSetFillColorWithColor(context, backgroundColor); + CGContextAddPath(context, path); + CGContextFillPath(context); + } - CGContextAddPath(ctx, path); - CGPathRelease(path); + CGContextAddPath(context, path); + CGPathRelease(path); - CGPathRef insetPath = RCTPathCreateWithRoundedRect(UIEdgeInsetsInsetRect(rect, borderInsets), cornerInsets, NULL); + CGPathRef insetPath = RCTPathCreateWithRoundedRect(UIEdgeInsetsInsetRect(rect, borderInsets), cornerInsets, NULL); - CGContextAddPath(ctx, insetPath); - CGContextEOClip(ctx); + CGContextAddPath(context, insetPath); + CGContextEOClip(context); - BOOL hasEqualColors = RCTBorderColorsAreEqual(borderColors); - if ((drawToEdge || !hasCornerRadii) && hasEqualColors) { - CGContextSetFillColorWithColor(ctx, borderColors.left); - CGContextAddRect(ctx, rect); - CGContextAddPath(ctx, insetPath); - CGContextEOFillPath(ctx); + BOOL hasEqualColors = RCTBorderColorsAreEqual(borderColors); + if ((drawToEdge || !hasCornerRadii) && hasEqualColors) { + CGContextSetFillColorWithColor(context, borderColors.left); + CGContextAddRect(context, rect); + CGContextAddPath(context, insetPath); + CGContextEOFillPath(context); - } else { - CGPoint topLeft = (CGPoint){borderInsets.left, borderInsets.top}; - if (cornerInsets.topLeft.width > 0 && cornerInsets.topLeft.height > 0) { - CGPoint points[2]; - RCTEllipseGetIntersectionsWithLine( - (CGRect){topLeft, {2 * cornerInsets.topLeft.width, 2 * cornerInsets.topLeft.height}}, - CGPointZero, - topLeft, - points); - if (!isnan(points[1].x) && !isnan(points[1].y)) { - topLeft = points[1]; + } else { + CGPoint topLeft = (CGPoint){borderInsets.left, borderInsets.top}; + if (cornerInsets.topLeft.width > 0 && cornerInsets.topLeft.height > 0) { + CGPoint points[2]; + RCTEllipseGetIntersectionsWithLine( + (CGRect){topLeft, {2 * cornerInsets.topLeft.width, 2 * cornerInsets.topLeft.height}}, + CGPointZero, + topLeft, + points); + if (!isnan(points[1].x) && !isnan(points[1].y)) { + topLeft = points[1]; + } } - } - CGPoint bottomLeft = (CGPoint){borderInsets.left, size.height - borderInsets.bottom}; - if (cornerInsets.bottomLeft.width > 0 && cornerInsets.bottomLeft.height > 0) { - CGPoint points[2]; - RCTEllipseGetIntersectionsWithLine( - (CGRect){ - {bottomLeft.x, bottomLeft.y - 2 * cornerInsets.bottomLeft.height}, - {2 * cornerInsets.bottomLeft.width, 2 * cornerInsets.bottomLeft.height}}, - (CGPoint){0, size.height}, - bottomLeft, - points); - if (!isnan(points[1].x) && !isnan(points[1].y)) { - bottomLeft = points[1]; + CGPoint bottomLeft = (CGPoint){borderInsets.left, size.height - borderInsets.bottom}; + if (cornerInsets.bottomLeft.width > 0 && cornerInsets.bottomLeft.height > 0) { + CGPoint points[2]; + RCTEllipseGetIntersectionsWithLine( + (CGRect){ + {bottomLeft.x, bottomLeft.y - 2 * cornerInsets.bottomLeft.height}, + {2 * cornerInsets.bottomLeft.width, 2 * cornerInsets.bottomLeft.height}}, + (CGPoint){0, size.height}, + bottomLeft, + points); + if (!isnan(points[1].x) && !isnan(points[1].y)) { + bottomLeft = points[1]; + } } - } - CGPoint topRight = (CGPoint){size.width - borderInsets.right, borderInsets.top}; - if (cornerInsets.topRight.width > 0 && cornerInsets.topRight.height > 0) { - CGPoint points[2]; - RCTEllipseGetIntersectionsWithLine( - (CGRect){ - {topRight.x - 2 * cornerInsets.topRight.width, topRight.y}, - {2 * cornerInsets.topRight.width, 2 * cornerInsets.topRight.height}}, - (CGPoint){size.width, 0}, - topRight, - points); - if (!isnan(points[0].x) && !isnan(points[0].y)) { - topRight = points[0]; + CGPoint topRight = (CGPoint){size.width - borderInsets.right, borderInsets.top}; + if (cornerInsets.topRight.width > 0 && cornerInsets.topRight.height > 0) { + CGPoint points[2]; + RCTEllipseGetIntersectionsWithLine( + (CGRect){ + {topRight.x - 2 * cornerInsets.topRight.width, topRight.y}, + {2 * cornerInsets.topRight.width, 2 * cornerInsets.topRight.height}}, + (CGPoint){size.width, 0}, + topRight, + points); + if (!isnan(points[0].x) && !isnan(points[0].y)) { + topRight = points[0]; + } } - } - CGPoint bottomRight = (CGPoint){size.width - borderInsets.right, size.height - borderInsets.bottom}; - if (cornerInsets.bottomRight.width > 0 && cornerInsets.bottomRight.height > 0) { - CGPoint points[2]; - RCTEllipseGetIntersectionsWithLine( - (CGRect){ - {bottomRight.x - 2 * cornerInsets.bottomRight.width, bottomRight.y - 2 * cornerInsets.bottomRight.height}, - {2 * cornerInsets.bottomRight.width, 2 * cornerInsets.bottomRight.height}}, - (CGPoint){size.width, size.height}, - bottomRight, - points); - if (!isnan(points[0].x) && !isnan(points[0].y)) { - bottomRight = points[0]; + CGPoint bottomRight = (CGPoint){size.width - borderInsets.right, size.height - borderInsets.bottom}; + if (cornerInsets.bottomRight.width > 0 && cornerInsets.bottomRight.height > 0) { + CGPoint points[2]; + RCTEllipseGetIntersectionsWithLine( + (CGRect){ + {bottomRight.x - 2 * cornerInsets.bottomRight.width, + bottomRight.y - 2 * cornerInsets.bottomRight.height}, + {2 * cornerInsets.bottomRight.width, 2 * cornerInsets.bottomRight.height}}, + (CGPoint){size.width, size.height}, + bottomRight, + points); + if (!isnan(points[0].x) && !isnan(points[0].y)) { + bottomRight = points[0]; + } } - } - CGColorRef currentColor = NULL; + CGColorRef currentColor = NULL; - // RIGHT - if (borderInsets.right > 0) { - const CGPoint points[] = { - (CGPoint){size.width, 0}, - topRight, - bottomRight, - (CGPoint){size.width, size.height}, - }; + // RIGHT + if (borderInsets.right > 0) { + const CGPoint points[] = { + (CGPoint){size.width, 0}, + topRight, + bottomRight, + (CGPoint){size.width, size.height}, + }; - currentColor = borderColors.right; - CGContextAddLines(ctx, points, sizeof(points) / sizeof(*points)); - } - - // BOTTOM - if (borderInsets.bottom > 0) { - const CGPoint points[] = { - (CGPoint){0, size.height}, - bottomLeft, - bottomRight, - (CGPoint){size.width, size.height}, - }; - - if (!CGColorEqualToColor(currentColor, borderColors.bottom)) { - CGContextSetFillColorWithColor(ctx, currentColor); - CGContextFillPath(ctx); - currentColor = borderColors.bottom; + currentColor = borderColors.right; + CGContextAddLines(context, points, sizeof(points) / sizeof(*points)); } - CGContextAddLines(ctx, points, sizeof(points) / sizeof(*points)); - } - // LEFT - if (borderInsets.left > 0) { - const CGPoint points[] = { - CGPointZero, - topLeft, - bottomLeft, - (CGPoint){0, size.height}, - }; + // BOTTOM + if (borderInsets.bottom > 0) { + const CGPoint points[] = { + (CGPoint){0, size.height}, + bottomLeft, + bottomRight, + (CGPoint){size.width, size.height}, + }; - if (!CGColorEqualToColor(currentColor, borderColors.left)) { - CGContextSetFillColorWithColor(ctx, currentColor); - CGContextFillPath(ctx); - currentColor = borderColors.left; + if (!CGColorEqualToColor(currentColor, borderColors.bottom)) { + CGContextSetFillColorWithColor(context, currentColor); + CGContextFillPath(context); + currentColor = borderColors.bottom; + } + CGContextAddLines(context, points, sizeof(points) / sizeof(*points)); } - CGContextAddLines(ctx, points, sizeof(points) / sizeof(*points)); - } - // TOP - if (borderInsets.top > 0) { - const CGPoint points[] = { - CGPointZero, - topLeft, - topRight, - (CGPoint){size.width, 0}, - }; + // LEFT + if (borderInsets.left > 0) { + const CGPoint points[] = { + CGPointZero, + topLeft, + bottomLeft, + (CGPoint){0, size.height}, + }; - if (!CGColorEqualToColor(currentColor, borderColors.top)) { - CGContextSetFillColorWithColor(ctx, currentColor); - CGContextFillPath(ctx); - currentColor = borderColors.top; + if (!CGColorEqualToColor(currentColor, borderColors.left)) { + CGContextSetFillColorWithColor(context, currentColor); + CGContextFillPath(context); + currentColor = borderColors.left; + } + CGContextAddLines(context, points, sizeof(points) / sizeof(*points)); } - CGContextAddLines(ctx, points, sizeof(points) / sizeof(*points)); + + // TOP + if (borderInsets.top > 0) { + const CGPoint points[] = { + CGPointZero, + topLeft, + topRight, + (CGPoint){size.width, 0}, + }; + + if (!CGColorEqualToColor(currentColor, borderColors.top)) { + CGContextSetFillColorWithColor(context, currentColor); + CGContextFillPath(context); + currentColor = borderColors.top; + } + CGContextAddLines(context, points, sizeof(points) / sizeof(*points)); + } + + CGContextSetFillColorWithColor(context, currentColor); + CGContextFillPath(context); } - CGContextSetFillColorWithColor(ctx, currentColor); - CGContextFillPath(ctx); - } - - CGPathRelease(insetPath); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); + CGPathRelease(insetPath); + }]; if (makeStretchable) { image = [image resizableImageWithCapInsets:edgeInsets]; @@ -477,42 +481,41 @@ static UIImage *RCTGetDashedOrDottedBorderImage( } const BOOL hasCornerRadii = RCTCornerRadiiAreAboveThreshold(cornerRadii); - CGContextRef ctx = RCTUIGraphicsBeginImageContext(viewSize, backgroundColor, hasCornerRadii, drawToEdge); - const CGRect rect = {.size = viewSize}; + UIGraphicsImageRenderer *const imageRenderer = + RCTUIGraphicsImageRenderer(viewSize, backgroundColor, hasCornerRadii, drawToEdge); + return [imageRenderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull rendererContext) { + const CGContextRef context = rendererContext.CGContext; + const CGRect rect = {.size = viewSize}; - if (backgroundColor) { - CGPathRef outerPath = RCTPathCreateOuterOutline(drawToEdge, rect, cornerRadii); - CGContextAddPath(ctx, outerPath); - CGPathRelease(outerPath); + if (backgroundColor) { + CGPathRef outerPath = RCTPathCreateOuterOutline(drawToEdge, rect, cornerRadii); + CGContextAddPath(context, outerPath); + CGPathRelease(outerPath); - CGContextSetFillColorWithColor(ctx, backgroundColor); - CGContextFillPath(ctx); - } + CGContextSetFillColorWithColor(context, backgroundColor); + CGContextFillPath(context); + } - // Stroking means that the width is divided in half and grows in both directions - // perpendicular to the path, that's why we inset by half the width, so that it - // reaches the edge of the rect. - CGRect pathRect = CGRectInset(rect, lineWidth / 2.0, lineWidth / 2.0); - CGPathRef path = RCTPathCreateWithRoundedRect(pathRect, RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero), NULL); + // Stroking means that the width is divided in half and grows in both directions + // perpendicular to the path, that's why we inset by half the width, so that it + // reaches the edge of the rect. + CGRect pathRect = CGRectInset(rect, lineWidth / 2.0, lineWidth / 2.0); + CGPathRef path = RCTPathCreateWithRoundedRect(pathRect, RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero), NULL); - CGFloat dashLengths[2]; - dashLengths[0] = dashLengths[1] = (borderStyle == RCTBorderStyleDashed ? 3 : 1) * lineWidth; + CGFloat dashLengths[2]; + dashLengths[0] = dashLengths[1] = (borderStyle == RCTBorderStyleDashed ? 3 : 1) * lineWidth; - CGContextSetLineWidth(ctx, lineWidth); - CGContextSetLineDash(ctx, 0, dashLengths, sizeof(dashLengths) / sizeof(*dashLengths)); + CGContextSetLineWidth(context, lineWidth); + CGContextSetLineDash(context, 0, dashLengths, sizeof(dashLengths) / sizeof(*dashLengths)); - CGContextSetStrokeColorWithColor(ctx, [UIColor yellowColor].CGColor); + CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor); - CGContextAddPath(ctx, path); - CGContextSetStrokeColorWithColor(ctx, borderColors.top); - CGContextStrokePath(ctx); + CGContextAddPath(context, path); + CGContextSetStrokeColorWithColor(context, borderColors.top); + CGContextStrokePath(context); - CGPathRelease(path); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; + CGPathRelease(path); + }]; } UIImage *RCTGetBorderImage( diff --git a/packages/rn-tester/NativeModuleExample/Screenshot.m b/packages/rn-tester/NativeModuleExample/Screenshot.m index 7953f2f5d0..ceb28ac6d0 100644 --- a/packages/rn-tester/NativeModuleExample/Screenshot.m +++ b/packages/rn-tester/NativeModuleExample/Screenshot.m @@ -19,65 +19,69 @@ RCT_EXPORT_METHOD(takeScreenshot : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) { - [self.bridge.uiManager - addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - // Get view - UIView *view; - if (target == nil || [target isEqual:@"window"]) { - view = RCTKeyWindow(); - } else if ([target isKindOfClass:[NSNumber class]]) { - view = viewRegistry[target]; - if (!view) { - RCTLogError(@"No view found with reactTag: %@", target); - return; - } - } + [self.bridge.uiManager addUIBlock:^( + __unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { + // Get view + UIView *view; + if (target == nil || [target isEqual:@"window"]) { + view = RCTKeyWindow(); + } else if ([target isKindOfClass:[NSNumber class]]) { + view = viewRegistry[target]; + if (!view) { + RCTLogError(@"No view found with reactTag: %@", target); + return; + } + } - // Get options - CGSize size = [RCTConvert CGSize:options]; - NSString *format = [RCTConvert NSString:options[@"format"] ?: @"png"]; + // Get options + CGSize size = [RCTConvert CGSize:options]; + NSString *format = [RCTConvert NSString:options[@"format"] ?: @"png"]; - // Capture image - if (size.width < 0.1 || size.height < 0.1) { - size = view.bounds.size; - } - UIGraphicsBeginImageContextWithOptions(size, NO, 0); - BOOL success = [view drawViewHierarchyInRect:(CGRect){CGPointZero, size} afterScreenUpdates:YES]; - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); + // Capture image + if (size.width < 0.1 || size.height < 0.1) { + size = view.bounds.size; + } - if (!success || !image) { - reject(RCTErrorUnspecified, @"Failed to capture view snapshot.", nil); + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:rendererFormat]; + + __block BOOL success = NO; + UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull context) { + success = [view drawViewHierarchyInRect:(CGRect){CGPointZero, size} afterScreenUpdates:YES]; + }]; + + if (!success || !image) { + reject(RCTErrorUnspecified, @"Failed to capture view snapshot.", nil); + return; + } + + // Convert image to data (on a background thread) + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSData *data; + if ([format isEqualToString:@"png"]) { + data = UIImagePNGRepresentation(image); + } else if ([format isEqualToString:@"jpeg"]) { + CGFloat quality = [RCTConvert CGFloat:options[@"quality"] ?: @1]; + data = UIImageJPEGRepresentation(image, quality); + } else { + RCTLogError(@"Unsupported image format: %@", format); + return; + } + + // Save to a temp file + NSError *error = nil; + NSString *tempFilePath = RCTTempFilePath(format, &error); + if (tempFilePath) { + if ([data writeToFile:tempFilePath options:(NSDataWritingOptions)0 error:&error]) { + resolve(tempFilePath); return; } + } - // Convert image to data (on a background thread) - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSData *data; - if ([format isEqualToString:@"png"]) { - data = UIImagePNGRepresentation(image); - } else if ([format isEqualToString:@"jpeg"]) { - CGFloat quality = [RCTConvert CGFloat:options[@"quality"] ?: @1]; - data = UIImageJPEGRepresentation(image, quality); - } else { - RCTLogError(@"Unsupported image format: %@", format); - return; - } - - // Save to a temp file - NSError *error = nil; - NSString *tempFilePath = RCTTempFilePath(format, &error); - if (tempFilePath) { - if ([data writeToFile:tempFilePath options:(NSDataWritingOptions)0 error:&error]) { - resolve(tempFilePath); - return; - } - } - - // If we reached here, something went wrong - reject(RCTErrorUnspecified, error.localizedDescription, error); - }); - }]; + // If we reached here, something went wrong + reject(RCTErrorUnspecified, error.localizedDescription, error); + }); + }]; } @end diff --git a/packages/rn-tester/RCTTest/FBSnapshotTestCase/FBSnapshotTestController.m b/packages/rn-tester/RCTTest/FBSnapshotTestCase/FBSnapshotTestController.m index 8f544ae53b..3aefe13faf 100644 --- a/packages/rn-tester/RCTTest/FBSnapshotTestCase/FBSnapshotTestController.m +++ b/packages/rn-tester/RCTTest/FBSnapshotTestCase/FBSnapshotTestController.m @@ -325,23 +325,14 @@ typedef NS_ENUM(NSInteger, FBTestSnapshotFileNameType) { NSAssert1(CGRectGetWidth(bounds), @"Zero width for view %@", view); NSAssert1(CGRectGetHeight(bounds), @"Zero height for view %@", view); - UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); - CGContextRef context = UIGraphicsGetCurrentContext(); - NSAssert1(context, @"Could not generate context for view %@", view); + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:bounds.size + format:rendererFormat]; - UIGraphicsPushContext(context); - CGContextSaveGState(context); - { + return [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull context) { BOOL success = [view drawViewHierarchyInRect:bounds afterScreenUpdates:YES]; NSAssert1(success, @"Could not create snapshot for view %@", view); - } - CGContextRestoreGState(context); - UIGraphicsPopContext(); - - UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return snapshot; + }]; } @end diff --git a/packages/rn-tester/RCTTest/FBSnapshotTestCase/UIImage+Diff.m b/packages/rn-tester/RCTTest/FBSnapshotTestCase/UIImage+Diff.m index e09ffebc9e..5713d4b74c 100644 --- a/packages/rn-tester/RCTTest/FBSnapshotTestCase/UIImage+Diff.m +++ b/packages/rn-tester/RCTTest/FBSnapshotTestCase/UIImage+Diff.m @@ -15,19 +15,22 @@ return nil; } CGSize imageSize = CGSizeMake(MAX(self.size.width, image.size.width), MAX(self.size.height, image.size.height)); - UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0.0); - CGContextRef context = UIGraphicsGetCurrentContext(); - [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; - CGContextSetAlpha(context, 0.5f); - CGContextBeginTransparencyLayer(context, NULL); - [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; - CGContextSetBlendMode(context, kCGBlendModeDifference); - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextFillRect(context, CGRectMake(0, 0, self.size.width, self.size.height)); - CGContextEndTransparencyLayer(context); - UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return returnImage; + + UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat]; + rendererFormat.opaque = YES; + UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:imageSize + format:rendererFormat]; + + return [renderer imageWithActions:^(UIGraphicsImageRendererContext *_Nonnull context) { + [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; + CGContextSetAlpha(context.CGContext, 0.5f); + CGContextBeginTransparencyLayer(context.CGContext, NULL); + [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; + CGContextSetBlendMode(context.CGContext, kCGBlendModeDifference); + CGContextSetFillColorWithColor(context.CGContext, [UIColor whiteColor].CGColor); + CGContextFillRect(context.CGContext, CGRectMake(0, 0, self.size.width, self.size.height)); + CGContextEndTransparencyLayer(context.CGContext); + }]; } @end