mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Move ART Android files to FB internal
Summary: ## Changelog: [General] [Changed] - Moves ART android files from RN to internal react shell. Reviewed By: cpojer Differential Revision: D21261077 fbshipit-source-id: 1d3dc404313192540d64991911e3599e3e86351b
This commit is contained in:
committed by
Facebook GitHub Bot
parent
81bdeade54
commit
423b55b2d7
@@ -51,7 +51,6 @@ rn_android_library(
|
||||
react_native_target("java/com/facebook/react/modules/websocket:websocket"),
|
||||
react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"),
|
||||
react_native_target("java/com/facebook/react/uimanager:uimanager"),
|
||||
react_native_target("java/com/facebook/react/views/art:art"),
|
||||
react_native_target("java/com/facebook/react/views/drawer:drawer"),
|
||||
react_native_target("java/com/facebook/react/views/image:image"),
|
||||
react_native_target("java/com/facebook/react/views/modal:modal"),
|
||||
|
||||
@@ -43,8 +43,6 @@ import com.facebook.react.modules.vibration.VibrationModule;
|
||||
import com.facebook.react.modules.websocket.WebSocketModule;
|
||||
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.views.art.ARTRenderableViewManager;
|
||||
import com.facebook.react.views.art.ARTSurfaceViewManager;
|
||||
import com.facebook.react.views.drawer.ReactDrawerLayoutManager;
|
||||
import com.facebook.react.views.image.ReactImageManager;
|
||||
import com.facebook.react.views.modal.ReactModalHostManager;
|
||||
@@ -174,9 +172,6 @@ public class MainReactPackage extends TurboReactPackage {
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
List<ViewManager> viewManagers = new ArrayList<>();
|
||||
|
||||
viewManagers.add(ARTRenderableViewManager.createARTGroupViewManager());
|
||||
viewManagers.add(ARTRenderableViewManager.createARTShapeViewManager());
|
||||
viewManagers.add(ARTRenderableViewManager.createARTTextViewManager());
|
||||
viewManagers.add(new ReactDialogPickerManager());
|
||||
viewManagers.add(new ReactDrawerLayoutManager());
|
||||
viewManagers.add(new ReactDropdownPickerManager());
|
||||
@@ -189,7 +184,6 @@ public class MainReactPackage extends TurboReactPackage {
|
||||
viewManagers.add(new SwipeRefreshLayoutManager());
|
||||
|
||||
// Native equivalents
|
||||
viewManagers.add(new ARTSurfaceViewManager());
|
||||
viewManagers.add(new FrescoBasedReactTextInlineImageViewManager());
|
||||
viewManagers.add(new ReactImageManager());
|
||||
viewManagers.add(new ReactModalHostManager());
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/** Shadow node for virtual ARTGroup view */
|
||||
public class ARTGroupShadowNode extends ARTVirtualNode {
|
||||
|
||||
protected @Nullable RectF mClipping;
|
||||
|
||||
public ARTGroupShadowNode() {}
|
||||
|
||||
@ReactProp(name = "clipping")
|
||||
public void setClipping(@Nullable ReadableArray clippingDims) {
|
||||
float[] clippingData = PropHelper.toFloatArray(clippingDims);
|
||||
if (clippingData != null) {
|
||||
mClipping = createClipping(clippingData);
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
opacity *= mOpacity;
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
saveAndSetupCanvas(canvas);
|
||||
|
||||
if (mClipping != null) {
|
||||
canvas.clipRect(
|
||||
mClipping.left * mScale,
|
||||
mClipping.top * mScale,
|
||||
mClipping.right * mScale,
|
||||
mClipping.bottom * mScale);
|
||||
}
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
ARTVirtualNode child = (ARTVirtualNode) getChildAt(i);
|
||||
child.draw(canvas, paint, opacity);
|
||||
child.markUpdateSeen();
|
||||
}
|
||||
|
||||
restoreCanvas(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RectF} from an array of dimensions (e.g. [x, y, width, height])
|
||||
*
|
||||
* @param data the array of dimensions
|
||||
* @return the {@link RectF} that can used to clip the canvas
|
||||
*/
|
||||
private static RectF createClipping(float[] data) {
|
||||
if (data.length != 4) {
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Clipping should be array of length 4 (e.g. [x, y, width, height])");
|
||||
}
|
||||
RectF clippingRect = new RectF(data[0], data[1], data[0] + data[2], data[1] + data[3]);
|
||||
return clippingRect;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
/** ViewManager for shadowed ART group views. */
|
||||
@ReactModule(name = ARTRenderableViewManager.CLASS_GROUP)
|
||||
public class ARTGroupViewManager extends ARTRenderableViewManager {
|
||||
|
||||
/* package */ ARTGroupViewManager() {
|
||||
super(CLASS_GROUP);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.view.View;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
/**
|
||||
* ViewManager for all shadowed ART views: Group, Shape and Text. Since these never get rendered
|
||||
* into native views and don't need any logic (all the logic is in {@link ARTSurfaceView}), this
|
||||
* "stubbed" ViewManager is used for all of them.
|
||||
*/
|
||||
public class ARTRenderableViewManager extends ViewManager<View, ReactShadowNode> {
|
||||
|
||||
public static final String CLASS_GROUP = "ARTGroup";
|
||||
public static final String CLASS_SHAPE = "ARTShape";
|
||||
public static final String CLASS_TEXT = "ARTText";
|
||||
|
||||
private final String mClassName;
|
||||
|
||||
public static ARTRenderableViewManager createARTGroupViewManager() {
|
||||
return new ARTGroupViewManager();
|
||||
}
|
||||
|
||||
public static ARTRenderableViewManager createARTShapeViewManager() {
|
||||
return new ARTShapeViewManager();
|
||||
}
|
||||
|
||||
public static ARTRenderableViewManager createARTTextViewManager() {
|
||||
return new ARTTextViewManager();
|
||||
}
|
||||
|
||||
/* package */ ARTRenderableViewManager(String className) {
|
||||
mClassName = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return mClassName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactShadowNode createShadowNodeInstance() {
|
||||
if (CLASS_GROUP.equals(mClassName)) {
|
||||
return new ARTGroupShadowNode();
|
||||
} else if (CLASS_SHAPE.equals(mClassName)) {
|
||||
return new ARTShapeShadowNode();
|
||||
} else if (CLASS_TEXT.equals(mClassName)) {
|
||||
return new ARTTextShadowNode();
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected type " + mClassName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ReactShadowNode> getShadowNodeClass() {
|
||||
if (CLASS_GROUP.equals(mClassName)) {
|
||||
return ARTGroupShadowNode.class;
|
||||
} else if (CLASS_SHAPE.equals(mClassName)) {
|
||||
return ARTShapeShadowNode.class;
|
||||
} else if (CLASS_TEXT.equals(mClassName)) {
|
||||
return ARTTextShadowNode.class;
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected type " + mClassName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View createViewInstance(ThemedReactContext reactContext) {
|
||||
throw new IllegalStateException("ARTShape does not map into a native view");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExtraData(View root, Object extraData) {
|
||||
throw new IllegalStateException("ARTShape does not map into a native view");
|
||||
}
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.DashPathEffect;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/** Shadow node for virtual ARTShape view */
|
||||
public class ARTShapeShadowNode extends ARTVirtualNode {
|
||||
|
||||
private static final int CAP_BUTT = 0;
|
||||
private static final int CAP_ROUND = 1;
|
||||
private static final int CAP_SQUARE = 2;
|
||||
|
||||
private static final int JOIN_BEVEL = 2;
|
||||
private static final int JOIN_MITER = 0;
|
||||
private static final int JOIN_ROUND = 1;
|
||||
|
||||
private static final int PATH_TYPE_ARC = 4;
|
||||
private static final int PATH_TYPE_CLOSE = 1;
|
||||
private static final int PATH_TYPE_CURVETO = 3;
|
||||
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[] mBrushData;
|
||||
private @Nullable float[] mStrokeDash;
|
||||
private float mStrokeWidth = 1;
|
||||
private int mStrokeCap = CAP_ROUND;
|
||||
private int mStrokeJoin = JOIN_ROUND;
|
||||
|
||||
public ARTShapeShadowNode() {}
|
||||
|
||||
@ReactProp(name = "d")
|
||||
public void setShapePath(@Nullable ReadableArray shapePath) {
|
||||
float[] pathData = PropHelper.toFloatArray(shapePath);
|
||||
mPath = createPath(pathData);
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "stroke")
|
||||
public void setStroke(@Nullable ReadableArray strokeColors) {
|
||||
mStrokeColor = PropHelper.toFloatArray(strokeColors);
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "strokeDash")
|
||||
public void setStrokeDash(@Nullable ReadableArray strokeDash) {
|
||||
mStrokeDash = PropHelper.toFloatArray(strokeDash);
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "fill")
|
||||
public void setFill(@Nullable ReadableArray fillColors) {
|
||||
mBrushData = PropHelper.toFloatArray(fillColors);
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "strokeWidth", defaultFloat = 1f)
|
||||
public void setStrokeWidth(float strokeWidth) {
|
||||
mStrokeWidth = strokeWidth;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "strokeCap", defaultInt = CAP_ROUND)
|
||||
public void setStrokeCap(int strokeCap) {
|
||||
mStrokeCap = strokeCap;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "strokeJoin", defaultInt = JOIN_ROUND)
|
||||
public void setStrokeJoin(int strokeJoin) {
|
||||
mStrokeJoin = strokeJoin;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
opacity *= mOpacity;
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
saveAndSetupCanvas(canvas);
|
||||
if (mPath == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Shapes should have a valid path (d) prop");
|
||||
}
|
||||
if (setupFillPaint(paint, opacity)) {
|
||||
canvas.drawPath(mPath, paint);
|
||||
}
|
||||
if (setupStrokePaint(paint, opacity)) {
|
||||
canvas.drawPath(mPath, paint);
|
||||
}
|
||||
restoreCanvas(canvas);
|
||||
}
|
||||
markUpdateSeen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up {@link #mPaint} according to the props set on a shadow view. Returns {@code true} if
|
||||
* the stroke should be drawn, {@code false} if not.
|
||||
*/
|
||||
protected boolean setupStrokePaint(Paint paint, float opacity) {
|
||||
if (mStrokeWidth == 0 || mStrokeColor == null || mStrokeColor.length == 0) {
|
||||
return false;
|
||||
}
|
||||
paint.reset();
|
||||
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
switch (mStrokeCap) {
|
||||
case CAP_BUTT:
|
||||
paint.setStrokeCap(Paint.Cap.BUTT);
|
||||
break;
|
||||
case CAP_SQUARE:
|
||||
paint.setStrokeCap(Paint.Cap.SQUARE);
|
||||
break;
|
||||
case CAP_ROUND:
|
||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||
break;
|
||||
default:
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"strokeCap " + mStrokeCap + " unrecognized");
|
||||
}
|
||||
switch (mStrokeJoin) {
|
||||
case JOIN_MITER:
|
||||
paint.setStrokeJoin(Paint.Join.MITER);
|
||||
break;
|
||||
case JOIN_BEVEL:
|
||||
paint.setStrokeJoin(Paint.Join.BEVEL);
|
||||
break;
|
||||
case JOIN_ROUND:
|
||||
paint.setStrokeJoin(Paint.Join.ROUND);
|
||||
break;
|
||||
default:
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"strokeJoin " + mStrokeJoin + " unrecognized");
|
||||
}
|
||||
paint.setStrokeWidth(mStrokeWidth * mScale);
|
||||
paint.setARGB(
|
||||
(int) (mStrokeColor.length > 3 ? mStrokeColor[3] * opacity * 255 : opacity * 255),
|
||||
(int) (mStrokeColor[0] * 255),
|
||||
(int) (mStrokeColor[1] * 255),
|
||||
(int) (mStrokeColor[2] * 255));
|
||||
if (mStrokeDash != null && mStrokeDash.length > 0) {
|
||||
paint.setPathEffect(new DashPathEffect(mStrokeDash, 0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up {@link #mPaint} according to the props set on a shadow view. Returns {@code true} if
|
||||
* the fill should be drawn, {@code false} if not.
|
||||
*/
|
||||
protected boolean setupFillPaint(Paint paint, float opacity) {
|
||||
if (mBrushData != null && mBrushData.length > 0) {
|
||||
paint.reset();
|
||||
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
int colorType = (int) mBrushData[0];
|
||||
switch (colorType) {
|
||||
case COLOR_TYPE_SOLID_COLOR:
|
||||
paint.setARGB(
|
||||
(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:
|
||||
FLog.w(ReactConstants.TAG, "ART: Color type " + colorType + " not supported!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the floor modulus of the float arguments. Java modulus will return a negative remainder
|
||||
* when the divisor is negative. Modulus should always be positive. This mimics the behavior of
|
||||
* Math.floorMod, introduced in Java 8.
|
||||
*/
|
||||
private float modulus(float x, float y) {
|
||||
float remainder = x % y;
|
||||
float modulus = remainder;
|
||||
if (remainder < 0) {
|
||||
modulus += y;
|
||||
}
|
||||
return modulus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Path} from an array of instructions constructed by JS (see
|
||||
* ARTSerializablePath.js). Each instruction starts with a type (see PATH_TYPE_*) followed by
|
||||
* arguments for that instruction. For example, to create a line the instruction will be 2
|
||||
* (PATH_LINE_TO), x, y. This will draw a line from the last draw point (or 0,0) to x,y.
|
||||
*
|
||||
* @param data the array of instructions
|
||||
* @return the {@link Path} that can be drawn to a canvas
|
||||
*/
|
||||
private Path createPath(float[] data) {
|
||||
Path path = new Path();
|
||||
path.moveTo(0, 0);
|
||||
int i = 0;
|
||||
while (i < data.length) {
|
||||
int type = (int) data[i++];
|
||||
switch (type) {
|
||||
case PATH_TYPE_MOVETO:
|
||||
path.moveTo(data[i++] * mScale, data[i++] * mScale);
|
||||
break;
|
||||
case PATH_TYPE_CLOSE:
|
||||
path.close();
|
||||
break;
|
||||
case PATH_TYPE_LINETO:
|
||||
path.lineTo(data[i++] * mScale, data[i++] * mScale);
|
||||
break;
|
||||
case PATH_TYPE_CURVETO:
|
||||
path.cubicTo(
|
||||
data[i++] * mScale,
|
||||
data[i++] * mScale,
|
||||
data[i++] * mScale,
|
||||
data[i++] * mScale,
|
||||
data[i++] * mScale,
|
||||
data[i++] * mScale);
|
||||
break;
|
||||
case PATH_TYPE_ARC:
|
||||
{
|
||||
float x = data[i++] * mScale;
|
||||
float y = data[i++] * mScale;
|
||||
float r = data[i++] * mScale;
|
||||
float start = (float) Math.toDegrees(data[i++]);
|
||||
float end = (float) Math.toDegrees(data[i++]);
|
||||
|
||||
boolean counterClockwise = !(data[i++] == 1f);
|
||||
float sweep = end - start;
|
||||
if (Math.abs(sweep) >= 360) {
|
||||
path.addCircle(x, y, r, counterClockwise ? Path.Direction.CCW : Path.Direction.CW);
|
||||
} else {
|
||||
sweep = modulus(sweep, 360);
|
||||
if (counterClockwise && sweep < 360) {
|
||||
// Counter-clockwise sweeps are negative
|
||||
sweep = -1 * (360 - sweep);
|
||||
}
|
||||
|
||||
RectF oval = new RectF(x - r, y - r, x + r, y + r);
|
||||
path.arcTo(oval, start, sweep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Unrecognized drawing instruction " + type);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
/** ViewManager for shadowed ART shape views. */
|
||||
@ReactModule(name = ARTRenderableViewManager.CLASS_SHAPE)
|
||||
public class ARTShapeViewManager extends ARTRenderableViewManager {
|
||||
|
||||
/* package */ ARTShapeViewManager() {
|
||||
super(CLASS_SHAPE);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.TextureView;
|
||||
|
||||
/** Custom {@link View} implementation that draws an ARTSurface React view and its children. */
|
||||
public class ARTSurfaceView extends TextureView {
|
||||
public ARTSurfaceView(Context context) {
|
||||
super(context);
|
||||
setOpaque(false);
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.BaseViewManager;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.yoga.YogaMeasureFunction;
|
||||
import com.facebook.yoga.YogaMeasureMode;
|
||||
import com.facebook.yoga.YogaNode;
|
||||
|
||||
/**
|
||||
* ViewManager for ARTSurfaceView React views. Renders as a {@link ARTSurfaceView} and handles
|
||||
* invalidating the native view on shadow view updates happening in the underlying tree.
|
||||
*/
|
||||
@ReactModule(name = ARTSurfaceViewManager.REACT_CLASS)
|
||||
public class ARTSurfaceViewManager
|
||||
extends BaseViewManager<ARTSurfaceView, ARTSurfaceViewShadowNode> {
|
||||
|
||||
public static final String REACT_CLASS = "ARTSurfaceView";
|
||||
|
||||
private static final YogaMeasureFunction MEASURE_FUNCTION =
|
||||
new YogaMeasureFunction() {
|
||||
@Override
|
||||
public long measure(
|
||||
YogaNode node,
|
||||
float width,
|
||||
YogaMeasureMode widthMode,
|
||||
float height,
|
||||
YogaMeasureMode heightMode) {
|
||||
throw new IllegalStateException("SurfaceView should have explicit width and height set");
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ARTSurfaceViewShadowNode createShadowNodeInstance() {
|
||||
ARTSurfaceViewShadowNode node = new ARTSurfaceViewShadowNode();
|
||||
node.setMeasureFunction(MEASURE_FUNCTION);
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ARTSurfaceViewShadowNode> getShadowNodeClass() {
|
||||
return ARTSurfaceViewShadowNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ARTSurfaceView createViewInstance(ThemedReactContext reactContext) {
|
||||
return new ARTSurfaceView(reactContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExtraData(ARTSurfaceView root, Object extraData) {
|
||||
ARTSurfaceViewShadowNode shadowNode = (ARTSurfaceViewShadowNode) extraData;
|
||||
shadowNode.setupSurfaceTextureListener(root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(ARTSurfaceView view, int backgroundColor) {
|
||||
// As of Android N TextureView does not support calling setBackground on it.
|
||||
// It will also throw an exception when target SDK is set to N or higher.
|
||||
|
||||
// Setting the background color for this view is handled in the shadow node.
|
||||
}
|
||||
}
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Build;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/** Shadow node for ART virtual tree root - ARTSurfaceView */
|
||||
public class ARTSurfaceViewShadowNode extends LayoutShadowNode
|
||||
implements TextureView.SurfaceTextureListener, LifecycleEventListener {
|
||||
|
||||
private @Nullable Surface mSurface;
|
||||
|
||||
private @Nullable Integer mBackgroundColor;
|
||||
|
||||
@ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color")
|
||||
public void setBackgroundColor(Integer color) {
|
||||
mBackgroundColor = color;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAnchor() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
|
||||
super.onCollectExtraUpdates(uiUpdater);
|
||||
drawOutput(false);
|
||||
uiUpdater.enqueueUpdateExtraData(getReactTag(), this);
|
||||
}
|
||||
|
||||
private void drawOutput(boolean markAsUpdated) {
|
||||
if (mSurface == null || !mSurface.isValid()) {
|
||||
markChildrenUpdatesSeen(this);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Canvas canvas = mSurface.lockCanvas(null);
|
||||
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||
if (mBackgroundColor != null) {
|
||||
canvas.drawColor(mBackgroundColor);
|
||||
}
|
||||
|
||||
Paint paint = new Paint();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
ARTVirtualNode child = (ARTVirtualNode) getChildAt(i);
|
||||
child.draw(canvas, paint, 1f);
|
||||
if (markAsUpdated) {
|
||||
child.markUpdated();
|
||||
} else {
|
||||
child.markUpdateSeen();
|
||||
}
|
||||
}
|
||||
|
||||
if (mSurface == null) {
|
||||
return;
|
||||
}
|
||||
mSurface.unlockCanvasAndPost(canvas);
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
FLog.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost");
|
||||
}
|
||||
}
|
||||
|
||||
public void setupSurfaceTextureListener(ARTSurfaceView surfaceView) {
|
||||
SurfaceTexture surface = surfaceView.getSurfaceTexture();
|
||||
surfaceView.setSurfaceTextureListener(this);
|
||||
if (surface != null && mSurface == null) {
|
||||
mSurface = new Surface(surface);
|
||||
drawOutput(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) {
|
||||
for (int i = 0; i < shadowNode.getChildCount(); i++) {
|
||||
ReactShadowNode child = shadowNode.getChildAt(i);
|
||||
child.markUpdateSeen();
|
||||
markChildrenUpdatesSeen(child);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThemedContext(ThemedReactContext themedContext) {
|
||||
super.setThemedContext(themedContext);
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
|
||||
themedContext.addLifecycleEventListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
|
||||
getThemedContext().removeLifecycleEventListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostResume() {
|
||||
drawOutput(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostPause() {}
|
||||
|
||||
@Override
|
||||
public void onHostDestroy() {}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
|
||||
mSurface = new Surface(surface);
|
||||
drawOutput(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
|
||||
mSurface.release();
|
||||
mSurface = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/** Shadow node for virtual ARTText view */
|
||||
public class ARTTextShadowNode extends ARTShapeShadowNode {
|
||||
|
||||
private static final String PROP_LINES = "lines";
|
||||
|
||||
private static final String PROP_FONT = "font";
|
||||
private static final String PROP_FONT_FAMILY = "fontFamily";
|
||||
private static final String PROP_FONT_SIZE = "fontSize";
|
||||
private static final String PROP_FONT_STYLE = "fontStyle";
|
||||
private static final String PROP_FONT_WEIGHT = "fontWeight";
|
||||
|
||||
private static final int DEFAULT_FONT_SIZE = 12;
|
||||
|
||||
private static final int TEXT_ALIGNMENT_CENTER = 2;
|
||||
private static final int TEXT_ALIGNMENT_LEFT = 0;
|
||||
private static final int TEXT_ALIGNMENT_RIGHT = 1;
|
||||
|
||||
private @Nullable ReadableMap mFrame;
|
||||
private int mTextAlignment = TEXT_ALIGNMENT_LEFT;
|
||||
|
||||
public ARTTextShadowNode() {}
|
||||
|
||||
@ReactProp(name = "frame")
|
||||
public void setFrame(@Nullable ReadableMap frame) {
|
||||
mFrame = frame;
|
||||
}
|
||||
|
||||
@ReactProp(name = "alignment", defaultInt = TEXT_ALIGNMENT_LEFT)
|
||||
public void setAlignment(int alignment) {
|
||||
mTextAlignment = alignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
if (mFrame == null) {
|
||||
return;
|
||||
}
|
||||
opacity *= mOpacity;
|
||||
if (opacity <= MIN_OPACITY_FOR_DRAW) {
|
||||
return;
|
||||
}
|
||||
if (!mFrame.hasKey(PROP_LINES)) {
|
||||
return;
|
||||
}
|
||||
ReadableArray linesProp = mFrame.getArray(PROP_LINES);
|
||||
if (linesProp == null || linesProp.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// only set up the canvas if we have something to draw
|
||||
saveAndSetupCanvas(canvas);
|
||||
String[] lines = new String[linesProp.size()];
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
lines[i] = linesProp.getString(i);
|
||||
}
|
||||
String text = TextUtils.join("\n", lines);
|
||||
if (setupStrokePaint(paint, opacity)) {
|
||||
applyTextPropertiesToPaint(paint);
|
||||
if (mPath == null) {
|
||||
canvas.drawText(text, 0, -paint.ascent(), paint);
|
||||
} else {
|
||||
canvas.drawTextOnPath(text, mPath, 0, 0, paint);
|
||||
}
|
||||
}
|
||||
if (setupFillPaint(paint, opacity)) {
|
||||
applyTextPropertiesToPaint(paint);
|
||||
if (mPath == null) {
|
||||
canvas.drawText(text, 0, -paint.ascent(), paint);
|
||||
} else {
|
||||
canvas.drawTextOnPath(text, mPath, 0, 0, paint);
|
||||
}
|
||||
}
|
||||
restoreCanvas(canvas);
|
||||
markUpdateSeen();
|
||||
}
|
||||
|
||||
private void applyTextPropertiesToPaint(Paint paint) {
|
||||
int alignment = mTextAlignment;
|
||||
switch (alignment) {
|
||||
case TEXT_ALIGNMENT_LEFT:
|
||||
paint.setTextAlign(Paint.Align.LEFT);
|
||||
break;
|
||||
case TEXT_ALIGNMENT_RIGHT:
|
||||
paint.setTextAlign(Paint.Align.RIGHT);
|
||||
break;
|
||||
case TEXT_ALIGNMENT_CENTER:
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
break;
|
||||
}
|
||||
if (mFrame != null) {
|
||||
if (mFrame.hasKey(PROP_FONT)) {
|
||||
ReadableMap font = mFrame.getMap(PROP_FONT);
|
||||
if (font != null) {
|
||||
float fontSize = DEFAULT_FONT_SIZE;
|
||||
if (font.hasKey(PROP_FONT_SIZE)) {
|
||||
fontSize = (float) font.getDouble(PROP_FONT_SIZE);
|
||||
}
|
||||
paint.setTextSize(fontSize * mScale);
|
||||
boolean isBold =
|
||||
font.hasKey(PROP_FONT_WEIGHT) && "bold".equals(font.getString(PROP_FONT_WEIGHT));
|
||||
boolean isItalic =
|
||||
font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE));
|
||||
int fontStyle;
|
||||
if (isBold && isItalic) {
|
||||
fontStyle = Typeface.BOLD_ITALIC;
|
||||
} else if (isBold) {
|
||||
fontStyle = Typeface.BOLD;
|
||||
} else if (isItalic) {
|
||||
fontStyle = Typeface.ITALIC;
|
||||
} else {
|
||||
fontStyle = Typeface.NORMAL;
|
||||
}
|
||||
// NB: if the font family is null / unsupported, the default one will be used
|
||||
paint.setTypeface(Typeface.create(font.getString(PROP_FONT_FAMILY), fontStyle));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
/** ViewManager for shadowed ART text views. */
|
||||
@ReactModule(name = ARTRenderableViewManager.CLASS_TEXT)
|
||||
public class ARTTextViewManager extends ARTRenderableViewManager {
|
||||
|
||||
/* package */ ARTTextViewManager() {
|
||||
super(CLASS_TEXT);
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.ReactShadowNodeImpl;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/**
|
||||
* Base class for ARTView virtual nodes: {@link ARTGroupShadowNode}, {@link ARTShapeShadowNode} and
|
||||
* indirectly for {@link ARTTextShadowNode}.
|
||||
*/
|
||||
public abstract class ARTVirtualNode extends ReactShadowNodeImpl {
|
||||
|
||||
protected static final float MIN_OPACITY_FOR_DRAW = 0.01f;
|
||||
|
||||
private static final float[] sMatrixData = new float[9];
|
||||
private static final float[] sRawMatrix = new float[9];
|
||||
|
||||
protected float mOpacity = 1f;
|
||||
private @Nullable Matrix mMatrix = new Matrix();
|
||||
|
||||
protected final float mScale;
|
||||
|
||||
public ARTVirtualNode() {
|
||||
mScale = DisplayMetricsHolder.getWindowDisplayMetrics().density;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract void draw(Canvas canvas, Paint paint, float opacity);
|
||||
|
||||
/**
|
||||
* Sets up the transform matrix on the canvas before an element is drawn.
|
||||
*
|
||||
* <p>NB: for perf reasons this does not apply opacity, as that would mean creating a new canvas
|
||||
* layer (which allocates an offscreen bitmap) and having it composited afterwards. Instead, the
|
||||
* drawing code should apply opacity recursively.
|
||||
*
|
||||
* @param canvas the canvas to set up
|
||||
*/
|
||||
protected final void saveAndSetupCanvas(Canvas canvas) {
|
||||
canvas.save();
|
||||
if (mMatrix != null) {
|
||||
canvas.concat(mMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the canvas after an element was drawn. This is always called in mirror with {@link
|
||||
* #saveAndSetupCanvas}.
|
||||
*
|
||||
* @param canvas the canvas to restore
|
||||
*/
|
||||
protected void restoreCanvas(Canvas canvas) {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@ReactProp(name = "opacity", defaultFloat = 1f)
|
||||
public void setOpacity(float opacity) {
|
||||
mOpacity = opacity;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "transform")
|
||||
public void setTransform(@Nullable ReadableArray transformArray) {
|
||||
if (transformArray != null) {
|
||||
int matrixSize = PropHelper.toFloatArray(transformArray, sMatrixData);
|
||||
if (matrixSize == 6) {
|
||||
setupMatrix();
|
||||
} else if (matrixSize != -1) {
|
||||
throw new JSApplicationIllegalArgumentException("Transform matrices must be of size 6");
|
||||
}
|
||||
} else {
|
||||
mMatrix = null;
|
||||
}
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
protected void setupMatrix() {
|
||||
sRawMatrix[0] = sMatrixData[0];
|
||||
sRawMatrix[1] = sMatrixData[2];
|
||||
sRawMatrix[2] = sMatrixData[4] * mScale;
|
||||
sRawMatrix[3] = sMatrixData[1];
|
||||
sRawMatrix[4] = sMatrixData[3];
|
||||
sRawMatrix[5] = sMatrixData[5] * mScale;
|
||||
sRawMatrix[6] = 0;
|
||||
sRawMatrix[7] = 0;
|
||||
sRawMatrix[8] = 1;
|
||||
if (mMatrix == null) {
|
||||
mMatrix = new Matrix();
|
||||
}
|
||||
mMatrix.setValues(sRawMatrix);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "YOGA_TARGET", "react_native_dep", "react_native_target", "rn_android_library")
|
||||
|
||||
rn_android_library(
|
||||
name = "art",
|
||||
srcs = glob(["*.java"]),
|
||||
is_androidx = True,
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
YOGA_TARGET,
|
||||
react_native_dep("third-party/android/androidx:annotation"),
|
||||
react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"),
|
||||
react_native_dep("third-party/java/jsr-305:jsr-305"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/common:common"),
|
||||
react_native_target("java/com/facebook/react/module/annotations:annotations"),
|
||||
react_native_target("java/com/facebook/react/uimanager:uimanager"),
|
||||
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
|
||||
],
|
||||
)
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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.art;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
|
||||
/** Contains static helper methods for accessing props. */
|
||||
/* package */ class PropHelper {
|
||||
|
||||
/**
|
||||
* Converts {@link ReadableArray} to an array of {@code float}. Returns newly created array.
|
||||
*
|
||||
* @return a {@code float[]} if converted successfully, or {@code null} if {@param value} was
|
||||
* {@code null}.
|
||||
*/
|
||||
/*package*/ static @Nullable float[] toFloatArray(@Nullable ReadableArray value) {
|
||||
if (value != null) {
|
||||
float[] result = new float[value.size()];
|
||||
toFloatArray(value, result);
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts given {@link ReadableArray} to an array of {@code float}. Writes result to the array
|
||||
* passed in {@param into}. This method will write to the output array up to the number of items
|
||||
* from the input array. If the input array is longer than output the remaining part of the input
|
||||
* will not be converted.
|
||||
*
|
||||
* @param value input array
|
||||
* @param into output array
|
||||
* @return number of items copied from input to the output array
|
||||
*/
|
||||
/*package*/ static int toFloatArray(ReadableArray value, float[] into) {
|
||||
int length = value.size() > into.length ? into.length : value.size();
|
||||
for (int i = 0; i < length; i++) {
|
||||
into[i] = (float) value.getDouble(i);
|
||||
}
|
||||
return value.size();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user