Skip to content

Commit 72fc5ba

Browse files
authored
fix: resolve false positives with isPixelTransparent helper (#250)
We changed this logic in #245 to workaround a specific bug for Metal-backed views. However, it returns false positives. For example a black pixel is also seen as transparent, because the all four (checked) bytes are `0`. This PR actually combines the two approaches into a combined more foolproof approach. It uses the snapshot approach to capture the pixel, but it uses the old approach of parsing it into a pixel array.
1 parent 83352e7 commit 72fc5ba

1 file changed

Lines changed: 33 additions & 4 deletions

File tree

ios/Sources/CapacitorGoogleMaps/Utilities/UIView+isPixelTransparent.swift

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,32 @@ import UIKit
22

33
extension UIView {
44
func isPixelTransparent(at point: CGPoint) -> Bool {
5+
var pixel: [UInt8] = [0, 0, 0, 0]
6+
let colorSpace = CGColorSpaceCreateDeviceRGB()
7+
let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue
8+
9+
guard let context = CGContext(
10+
data: &pixel,
11+
width: 1,
12+
height: 1,
13+
bitsPerComponent: 8,
14+
bytesPerRow: 4,
15+
space: colorSpace,
16+
bitmapInfo: bitmapInfo
17+
) else {
18+
return false
19+
}
20+
21+
/**
22+
* We could now do as follows:
23+
* ```
24+
* context.translateBy(x: -point.x, y: -point.y)
25+
* self.layer.render(in: context)
26+
* ```
27+
* However, it seems that that approach doesn't work on some Metal-backed devices.
28+
* So instead, we do it like the code below
29+
*/
30+
531
let scale = window?.screen.scale ?? contentScaleFactor
632
let rect = CGRect(x: floor(point.x), y: floor(point.y), width: 1/scale, height: 1/scale)
733

@@ -12,10 +38,13 @@ extension UIView {
1238
let img = UIGraphicsImageRenderer(bounds: rect, format: format).image { _ in
1339
drawHierarchy(in: bounds, afterScreenUpdates: false)
1440
}
15-
guard let cg = img.cgImage,
16-
let data = cg.dataProvider?.data,
17-
let bytes = CFDataGetBytePtr(data) else { return false }
1841

19-
return bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0 && bytes[3] == 0
42+
guard let cgImage = img.cgImage else {
43+
return false
44+
}
45+
46+
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: 1, height: 1))
47+
48+
return pixel[3] == 0
2049
}
2150
}

0 commit comments

Comments
 (0)