Implemented linear gradient fill in Android

Summary:
Partial implementation of "TODO(6352048): Support gradients etc.": linear gradient fill implemented.

We implemented a custom Color Picker based on ReactART.

<img width="268" alt="screen shot 2016-12-19 at 12 27 09 pm" src="https://cloud.githubusercontent.com/assets/18415611/21309512/5033b5a4-c5e7-11e6-9558-5571d18210e9.png">
Closes https://github.com/facebook/react-native/pull/11541

Differential Revision: D5061836

Pulled By: ericvicenti

fbshipit-source-id: ec8b7a0a6f3d2d1a2c1b394d4960d3365ad6fb44
This commit is contained in:
Dmitry Petukhov 2017-05-15 23:50:59 -07:00 committed by Facebook Github Bot
parent dc339f77f3
commit 36405d13ff
1 changed files with 59 additions and 10 deletions

View File

@ -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<stops; i++) {
positions[i] = mBrushData[5 + 4*stops + i];
int r = (int) (255 * mBrushData[5 + 4*i + 0]);
int g = (int) (255 * mBrushData[5 + 4*i + 1]);
int b = (int) (255 * mBrushData[5 + 4*i + 2]);
int a = (int) (255 * mBrushData[5 + 4*i + 3]);
colors[i] = Color.argb(a, r, g, b);
}
}
paint.setShader(
new LinearGradient(
gradientStartX, gradientStartY,
gradientEndX, gradientEndY,
colors, positions,
Shader.TileMode.CLAMP
)
);
break;
case COLOR_TYPE_RADIAL_GRADIENT:
// TODO(6352048): Support radial gradient etc.
case COLOR_TYPE_PATTERN:
// TODO(6352048): Support patterns etc.
default:
// TODO(6352048): Support gradients etc.
FLog.w(ReactConstants.TAG, "ART: Color type " + colorType + " not supported!");
}
return true;