diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java index 195ef8fd4..0cfa1ce97 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java @@ -16,6 +16,9 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.DashPathEffect; +import android.graphics.LinearGradient; +import android.graphics.Shader; +import android.graphics.Color; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; @@ -42,9 +45,16 @@ public class ARTShapeShadowNode extends ARTVirtualNode { private static final int PATH_TYPE_LINETO = 2; private static final int PATH_TYPE_MOVETO = 0; + // For color type JS and ObjectiveC definitions counterparts + // refer to ReactNativeART.js and RCTConvert+ART.m + private static final int COLOR_TYPE_SOLID_COLOR = 0; + private static final int COLOR_TYPE_LINEAR_GRADIENT = 1; + private static final int COLOR_TYPE_RADIAL_GRADIENT = 2; + private static final int COLOR_TYPE_PATTERN = 3; + protected @Nullable Path mPath; private @Nullable float[] mStrokeColor; - private @Nullable float[] mFillColor; + private @Nullable float[] mBrushData; private @Nullable float[] mStrokeDash; private float mStrokeWidth = 1; private int mStrokeCap = CAP_ROUND; @@ -71,7 +81,7 @@ public class ARTShapeShadowNode extends ARTVirtualNode { @ReactProp(name = "fill") public void setFill(@Nullable ReadableArray fillColors) { - mFillColor = PropHelper.toFloatArray(fillColors); + mBrushData = PropHelper.toFloatArray(fillColors); markUpdated(); } @@ -169,21 +179,60 @@ public class ARTShapeShadowNode extends ARTVirtualNode { * if the fill should be drawn, {@code false} if not. */ protected boolean setupFillPaint(Paint paint, float opacity) { - if (mFillColor != null && mFillColor.length > 0) { + if (mBrushData != null && mBrushData.length > 0) { paint.reset(); paint.setFlags(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.FILL); - int colorType = (int) mFillColor[0]; + int colorType = (int) mBrushData[0]; switch (colorType) { - case 0: + case COLOR_TYPE_SOLID_COLOR: paint.setARGB( - (int) (mFillColor.length > 4 ? mFillColor[4] * opacity * 255 : opacity * 255), - (int) (mFillColor[1] * 255), - (int) (mFillColor[2] * 255), - (int) (mFillColor[3] * 255)); + (int) (mBrushData.length > 4 ? mBrushData[4] * opacity * 255 : opacity * 255), + (int) (mBrushData[1] * 255), + (int) (mBrushData[2] * 255), + (int) (mBrushData[3] * 255)); break; + case COLOR_TYPE_LINEAR_GRADIENT: + // For mBrushData format refer to LinearGradient and insertColorStopsIntoArray functions in ReactNativeART.js + if (mBrushData.length < 5) { + FLog.w(ReactConstants.TAG, + "[ARTShapeShadowNode setupFillPaint] expects 5 elements, received " + + mBrushData.length); + return false; + } + float gradientStartX = mBrushData[1] * mScale; + float gradientStartY = mBrushData[2] * mScale; + float gradientEndX = mBrushData[3] * mScale; + float gradientEndY = mBrushData[4] * mScale; + int stops = (mBrushData.length - 5) / 5; + int[] colors = null; + float[] positions = null; + if (stops > 0) { + colors = new int[stops]; + positions = new float[stops]; + for (int i=0; i