Skip to content

Commit 658dced

Browse files
zeyapfacebook-github-bot
authored andcommitted
make sure view width and height are non 0 before calling createBitmap() (facebook#56627)
Summary: ## Changelog: [Android] [Fixed] - make sure view width and height are non 0 before calling createBitmap() Reviewed By: Abbondanzo Differential Revision: D102657602
1 parent 44a4b1b commit 658dced

1 file changed

Lines changed: 22 additions & 11 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/ViewTransitionSnapshotManager.kt

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@ internal class ViewTransitionSnapshotManager(
3838
) : UIManagerListener {
3939

4040
companion object {
41-
private fun captureSoftwareBitmap(view: View): Bitmap {
42-
val bitmap = createBitmap(view.width, view.height)
43-
view.draw(Canvas(bitmap))
44-
return bitmap
41+
private fun captureSoftwareBitmap(view: View): Bitmap? {
42+
if (view.width > 0 && view.height > 0) {
43+
val bitmap = createBitmap(view.width, view.height)
44+
view.draw(Canvas(bitmap))
45+
return bitmap
46+
}
47+
return null
4548
}
4649
}
4750

@@ -96,7 +99,7 @@ internal class ViewTransitionSnapshotManager(
9699
} else {
97100
// Software fallback runs synchronously, so onBitmapCaptured always
98101
// completes before setViewSnapshot is called.
99-
onBitmapCaptured(reactTag, captureSoftwareBitmap(view))
102+
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
100103
}
101104
}
102105
}
@@ -106,9 +109,16 @@ internal class ViewTransitionSnapshotManager(
106109
val location = IntArray(2)
107110
view.getLocationInWindow(location)
108111

112+
val viewWidth = view.width
113+
val viewHeight = view.height
114+
115+
if (viewWidth <= 0 || viewHeight <= 0) {
116+
// Nothing to capture.
117+
return
118+
}
119+
109120
// The view's rect in window coordinates.
110-
val viewRect =
111-
Rect(location[0], location[1], location[0] + view.width, location[1] + view.height)
121+
val viewRect = Rect(location[0], location[1], location[0] + viewWidth, location[1] + viewHeight)
112122

113123
// Clamp to window bounds — PixelCopy only captures what's visible on the
114124
// window surface. Without clamping, off-screen portions are black/empty
@@ -144,23 +154,24 @@ internal class ViewTransitionSnapshotManager(
144154
if (copyResult == PixelCopy.SUCCESS) {
145155
// Compose the clamped capture into a full-size bitmap at the
146156
// correct offset so it aligns with the pseudo-element's bounds.
147-
val fullBitmap = createBitmap(view.width, view.height)
157+
val fullBitmap = createBitmap(viewWidth, viewHeight)
148158
Canvas(fullBitmap)
149159
.drawBitmap(clampedBitmap, offsetX.toFloat(), offsetY.toFloat(), null)
150160
clampedBitmap.recycle()
151161
onBitmapCaptured(reactTag, fullBitmap)
152162
} else {
163+
// Fall back to software rendering if the view is still valid.
153164
clampedBitmap.recycle()
154-
onBitmapCaptured(reactTag, captureSoftwareBitmap(view))
165+
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
155166
}
156167
},
157168
mainHandler,
158169
)
159170
} catch (e: IllegalArgumentException) {
160171
// Window surface may have been destroyed (e.g., device idle/sleep).
161-
// Fall back to software rendering.
172+
// Fall back to software rendering if the view is still valid.
162173
clampedBitmap.recycle()
163-
onBitmapCaptured(reactTag, captureSoftwareBitmap(view))
174+
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
164175
}
165176
}
166177

0 commit comments

Comments
 (0)