Fix getOpacity() for drawables (#47103)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47103

`getOpacity()` is supposed to return a PixelFormat enum instead of a value between 0..255.
https://developer.android.com/reference/android/graphics/drawable/Drawable#getOpacity()

Also, I'm taking the value from the paint instead of the color's alpha since the paint might've been modified by setAlpha by this point and otherwise the paint will hold the alpha set by the color anyway since setAlpha() on Paints is just a helper for setColor() (https://developer.android.com/reference/android/graphics/Paint#setAlpha(int))

Changelog: [Internal]

Reviewed By: NickGerleman

Differential Revision: D64273014

fbshipit-source-id: e2c524f1d816ee3705c5118232be759898e666ea
This commit is contained in:
Jorge Cabiedes Acosta
2024-10-17 17:37:25 -07:00
committed by Facebook GitHub Bot
parent 02e4f3e16a
commit 398512a4ed
4 changed files with 32 additions and 10 deletions
@@ -18,6 +18,7 @@ import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
@@ -189,7 +190,15 @@ public class CSSBackgroundDrawable extends Drawable {
@Override
public int getOpacity() {
return (Color.alpha(mColor) * mAlpha) >> 8;
int alpha = (Color.alpha(mColor) * mAlpha) >> 8;
switch (alpha) {
case 255:
return PixelFormat.OPAQUE;
case 0:
return PixelFormat.TRANSPARENT;
default:
return PixelFormat.TRANSLUCENT;
}
}
/* Android's elevation implementation requires this to be implemented to know where to draw the shadow. */
@@ -385,7 +394,7 @@ public class CSSBackgroundDrawable extends Drawable {
canvas.clipPath(Preconditions.checkNotNull(mOuterClipPathForBorderRadius), Region.Op.INTERSECT);
// Draws the View without its border first (with background color fill)
int useColor = ColorUtils.setAlphaComponent(mColor, getOpacity());
int useColor = ColorUtils.setAlphaComponent(mColor, (Color.alpha(mColor) * mAlpha) >> 8);
if (Color.alpha(useColor) != 0) {
mPaint.setColor(useColor);
mPaint.setStyle(Paint.Style.FILL);
@@ -75,9 +75,12 @@ internal class InsetBoxShadowDrawable(
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int {
val alpha = Color.alpha(shadowColor)
return if (alpha == 0) PixelFormat.TRANSPARENT
else ((shadowPaint.alpha / 255f) / (alpha / 255f) * 255f).roundToInt()
val alpha = shadowPaint.alpha
return when (alpha) {
255 -> PixelFormat.OPAQUE
in 1..254 -> PixelFormat.TRANSLUCENT
else -> PixelFormat.TRANSPARENT
}
}
override fun draw(canvas: Canvas) {
@@ -15,6 +15,7 @@ import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PathEffect
import android.graphics.PixelFormat
import android.graphics.RectF
import android.graphics.drawable.Drawable
import com.facebook.react.uimanager.PixelUtil.dpToPx
@@ -104,8 +105,14 @@ internal class OutlineDrawable(
}
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int =
((outlinePaint.alpha / 255f) / (Color.alpha(outlineColor) / 255f) * 255f).roundToInt()
override fun getOpacity(): Int {
val alpha = outlinePaint.alpha
return when (alpha) {
255 -> PixelFormat.OPAQUE
in 1..254 -> PixelFormat.TRANSLUCENT
else -> PixelFormat.TRANSPARENT
}
}
override fun draw(canvas: Canvas) {
if (outlineWidth == 0f) {
@@ -71,9 +71,12 @@ internal class OutsetBoxShadowDrawable(
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int {
val alpha = Color.alpha(shadowColor)
return if (alpha == 0) PixelFormat.TRANSPARENT
else ((shadowPaint.alpha / 255f) / (alpha / 255f) * 255f).roundToInt()
val alpha = shadowPaint.alpha
return when (alpha) {
255 -> PixelFormat.OPAQUE
in 1..254 -> PixelFormat.TRANSLUCENT
else -> PixelFormat.TRANSPARENT
}
}
override fun draw(canvas: Canvas) {