Skip to content

Commit

Permalink
Fix low-quality masks on iOS (#1658)
Browse files Browse the repository at this point in the history
This PR fixes low-quality masks on iOS.

This was caused by the bitmap for the mask being created with [CGBitmapContextCreate()](https://developer.apple.com/documentation/coregraphics/1455939-cgbitmapcontextcreate) which does not take into account the device's pixel-density, unlike [UIGraphicsBeginImageContextWithOptions()](https://developer.apple.com/documentation/uikit/1623912-uigraphicsbeginimagecontextwitho).

To fix it, the pixel-density is retrieved using `[[UIScreen mainScreen] scale]` and it is used as a scale factor for the mask bitmap.
  • Loading branch information
simontreny authored Mar 1, 2022
1 parent f277c27 commit 59a48e7
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions apple/RNSVGRenderable.m
Original file line number Diff line number Diff line change
Expand Up @@ -202,18 +202,27 @@ - (void)renderTo:(CGContextRef)context rect:(CGRect)rect
CGSize boundsSize = bounds.size;
CGFloat height = boundsSize.height;
CGFloat width = boundsSize.width;
#if TARGET_OS_OSX
CGFloat scale = [[NSScreen mainScreen] backingScaleFactor];
#else
CGFloat scale = [[UIScreen mainScreen] scale];
#endif
NSUInteger iheight = (NSUInteger)height;
NSUInteger iwidth = (NSUInteger)width;
NSUInteger npixels = iheight * iwidth;
NSUInteger iscale = (NSUInteger)scale;
NSUInteger scaledHeight = iheight * iscale;
NSUInteger scaledWidth = iwidth * iscale;
NSUInteger npixels = scaledHeight * scaledWidth;
CGRect drawBounds = CGRectMake(0, 0, width, height);

// Allocate pixel buffer and bitmap context for mask
NSUInteger bytesPerPixel = 4;
NSUInteger bitsPerComponent = 8;
NSUInteger bytesPerRow = bytesPerPixel * iwidth;
NSUInteger bytesPerRow = bytesPerPixel * scaledWidth;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt32 * pixels = (UInt32 *) calloc(npixels, sizeof(UInt32));
CGContextRef bcontext = CGBitmapContextCreate(pixels, iwidth, iheight, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextRef bcontext = CGBitmapContextCreate(pixels, scaledWidth, scaledHeight, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextScaleCTM(bcontext, iscale, iscale);

// Clip to mask bounds and render the mask
CGFloat x = [self relativeOn:[_maskNode x]
Expand Down

0 comments on commit 59a48e7

Please sign in to comment.