/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.react.views.view import android.annotation.SuppressLint import android.graphics.Canvas import android.os.Build import java.lang.reflect.InvocationTargetException import java.lang.reflect.Method /** * Copied from * [ Compose canvas utils ](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt;drc=3b2dde134afab8d58b9c39ad4820eaf9a6e014a9) */ internal object CanvasUtil { private var reorderBarrierMethod: Method? = null private var inorderBarrierMethod: Method? = null private var orderMethodsFetched = false /** * Enables Z support for the Canvas. The method is publicly available starting from API 29 and was * hidden before, so we have to resort to reflection tricks to ensure we can use this API. */ @SuppressLint("SoonBlockedPrivateApi", "PrivateApi") @JvmStatic fun enableZ(canvas: Canvas, enable: Boolean) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (enable) { canvas.enableZ() } else { canvas.disableZ() } } else { fetchOrderMethods() try { if (enable && reorderBarrierMethod != null) { checkNotNull(reorderBarrierMethod).invoke(canvas) } if (!enable && inorderBarrierMethod != null) { checkNotNull(inorderBarrierMethod).invoke(canvas) } } catch (ignore: IllegalAccessException) { // Do nothing } catch (ignore: InvocationTargetException) { // Do nothing } } } private fun fetchOrderMethods() { if (!orderMethodsFetched) { try { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) { // use double reflection to avoid grey list on P val getDeclaredMethod = Class::class .java .getDeclaredMethod( "getDeclaredMethod", String::class.java, Array::class.java, ) reorderBarrierMethod = getDeclaredMethod.invoke( Canvas::class.java, "insertReorderBarrier", arrayOfNulls>(0), ) as Method inorderBarrierMethod = getDeclaredMethod.invoke( Canvas::class.java, "insertInorderBarrier", arrayOfNulls>(0), ) as Method } else { reorderBarrierMethod = Canvas::class.java.getDeclaredMethod("insertReorderBarrier") inorderBarrierMethod = Canvas::class.java.getDeclaredMethod("insertInorderBarrier") } if (reorderBarrierMethod == null || inorderBarrierMethod == null) { return } reorderBarrierMethod?.isAccessible = true inorderBarrierMethod?.isAccessible = true } catch (ignore: IllegalAccessException) { // Do nothing } catch (ignore: InvocationTargetException) { // Do nothing } catch (ignore: NoSuchMethodException) { // Do nothing } orderMethodsFetched = true } } }