From 23657ccf5bcab6c511903660b3c617c3b8248f20 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 30 Jul 2018 09:30:54 -0700 Subject: [PATCH] Add `YogaNodeProperties` implementation with `ByteBuffer` based setters Summary: @public Adds an implementation of `YogaNodeProperties` that sets style properties using a `ByteBuffer` rather than JNI calls. We hope for a speed improvement. Reviewed By: pasqualeanatriello Differential Revision: D9042225 fbshipit-source-id: c7f2b24eaeddd1190755bec85a5034079bd2f492 --- .../main/java/com/facebook/yoga/YogaNode.java | 29 +- .../yoga/YogaNodePropertiesHybrid.java | 261 ++++++++++++++++++ .../facebook/yoga/YogaNodePropertiesJNI.java | 10 +- .../jni/first-party/yogajni/jni/YGJNI.cpp | 11 + 4 files changed, 302 insertions(+), 9 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesHybrid.java diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java index 1729701937b119..1a765bc472e545 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java @@ -21,6 +21,9 @@ public class YogaNode implements Cloneable { SoLoader.loadLibrary("yoga"); } + public static final int BYTE_BUFFER = 1; + public static final int HYBRID = 2; + /** Get native instance count. Useful for testing only. */ static native int jni_YGNodeGetInstanceCount(); @@ -39,12 +42,30 @@ public YogaNode(YogaConfig config) { mDelegate = new YogaNodePropertiesJNI(this, config); } - public YogaNode(boolean unsafeClownyUseByteBufferValueDoesNotMatter) { - mDelegate = new YogaNodePropertiesByteBuffer(this); + public YogaNode(int storageType) { + switch (storageType) { + case BYTE_BUFFER: + mDelegate = new YogaNodePropertiesByteBuffer(this); + break; + case HYBRID: + mDelegate = new YogaNodePropertiesHybrid(this); + break; + default: + mDelegate = new YogaNodePropertiesJNI(this); + } } - public YogaNode(boolean unsafeClownyUseByteBufferValueDoesNotMatter, YogaConfig config) { - mDelegate = new YogaNodePropertiesByteBuffer(this, config); + public YogaNode(int storageType, YogaConfig config) { + switch (storageType) { + case BYTE_BUFFER: + mDelegate = new YogaNodePropertiesByteBuffer(this, config); + break; + case HYBRID: + mDelegate = new YogaNodePropertiesHybrid(this, config); + break; + default: + mDelegate = new YogaNodePropertiesJNI(this, config); + } } public long getNativePointer() { diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesHybrid.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesHybrid.java new file mode 100644 index 00000000000000..dc727cccd9023f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesHybrid.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * 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.yoga; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.soloader.SoLoader; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +@DoNotStrip +public class YogaNodePropertiesHybrid extends YogaNodePropertiesJNI { + + static { + SoLoader.loadLibrary("yoga"); + } + + private ByteBuffer mStyleBuffer; + + private static native ByteBuffer jni_getStyleBuffer(long nativePointer); + + public YogaNodePropertiesHybrid(YogaNode node) { + super(node); + mStyleBuffer = jni_getStyleBuffer(getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); + } + + public YogaNodePropertiesHybrid(YogaNode node, YogaConfig config) { + super(node, config); + mStyleBuffer = jni_getStyleBuffer(getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); + } + + @Override + public void setDirection(YogaDirection direction) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDirection, direction.intValue()); + } + + @Override + public void setFlexDirection(YogaFlexDirection flexDirection) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexDirection, flexDirection.intValue()); + } + + @Override + public void setJustifyContent(YogaJustify justifyContent) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleJustifyContent, justifyContent.intValue()); + } + + @Override + public void setAlignItems(YogaAlign alignItems) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignItems, alignItems.intValue()); + } + + @Override + public void setAlignSelf(YogaAlign alignSelf) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignSelf, alignSelf.intValue()); + } + + @Override + public void setAlignContent(YogaAlign alignContent) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleAlignContent, alignContent.intValue()); + } + + @Override + public void setPositionType(YogaPositionType positionType) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.stylePositionType, positionType.intValue()); + } + + @Override + public void setWrap(YogaWrap flexWrap) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleFlexWrap, flexWrap.intValue()); + } + + @Override + public void setOverflow(YogaOverflow overflow) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleOverflow, overflow.intValue()); + } + + @Override + public void setDisplay(YogaDisplay display) { + mStyleBuffer.putInt(YogaNodeMemoryLayout.styleDisplay, display.intValue()); + } + + @Override + public void setFlex(float flex) { + YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlex, flex); + } + + @Override + public void setFlexGrow(float flexGrow) { + YogaNodeMemoryLayout.putOptional(mStyleBuffer, YogaNodeMemoryLayout.styleFlexGrow, flexGrow); + } + + @Override + public void setFlexShrink(float flexShrink) { + YogaNodeMemoryLayout.putOptional( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexShrink, flexShrink); + } + + @Override + public void setFlexBasis(float flexBasis) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, flexBasis); + } + + @Override + public void setFlexBasisPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis, percent); + } + + @Override + public void setFlexBasisAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleFlexBasis); + } + + @Override + public void setMargin(YogaEdge edge, float margin) { + mEdgeSetFlag |= MARGIN; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), margin); + } + + @Override + public void setMarginPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= MARGIN; + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge), percent); + } + + @Override + public void setMarginAuto(YogaEdge edge) { + mEdgeSetFlag |= MARGIN; + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleMarginOffset(edge)); + } + + @Override + public void setPadding(YogaEdge edge, float padding) { + mEdgeSetFlag |= PADDING; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), padding); + } + + @Override + public void setPaddingPercent(YogaEdge edge, float percent) { + mEdgeSetFlag |= PADDING; + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePaddingOffset(edge), percent); + } + + @Override + public void setBorder(YogaEdge edge, float border) { + mEdgeSetFlag |= BORDER; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleBorderOffset(edge), border); + } + + @Override + public void setPosition(YogaEdge edge, float position) { + mHasSetPosition = true; + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), position); + } + + @Override + public void setPositionPercent(YogaEdge edge, float percent) { + mHasSetPosition = true; + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.stylePositionOffset(edge), percent); + } + + @Override + public void setWidth(float width) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, width); + } + + @Override + public void setWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth, percent); + } + + @Override + public void setWidthAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleWidth); + } + + @Override + public void setHeight(float height) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, height); + } + + @Override + public void setHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight, percent); + } + + @Override + public void setHeightAuto() { + YogaNodeMemoryLayout.putAutoValue(mStyleBuffer, YogaNodeMemoryLayout.styleHeight); + } + + @Override + public void setMinWidth(float minWidth) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, minWidth); + } + + @Override + public void setMinWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMinWidth, percent); + } + + @Override + public void setMinHeight(float minHeight) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, minHeight); + } + + @Override + public void setMinHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMinHeight, percent); + } + + @Override + public void setMaxWidth(float maxWidth) { + YogaNodeMemoryLayout.putPointValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, maxWidth); + } + + @Override + public void setMaxWidthPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue(mStyleBuffer, YogaNodeMemoryLayout.styleMaxWidth, percent); + } + + @Override + public void setMaxHeight(float maxHeight) { + YogaNodeMemoryLayout.putPointValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, maxHeight); + } + + @Override + public void setMaxHeightPercent(float percent) { + YogaNodeMemoryLayout.putPercentValue( + mStyleBuffer, YogaNodeMemoryLayout.styleMaxHeight, percent); + } + + @Override + public void setAspectRatio(float aspectRatio) { + YogaNodeMemoryLayout.putOptional( + mStyleBuffer, YogaNodeMemoryLayout.styleAspectRatio, aspectRatio); + } + + @Override + public YogaNodeProperties clone(YogaNode node) { + YogaNodePropertiesHybrid clone = (YogaNodePropertiesHybrid) super.clone(node); + clone.mStyleBuffer = + jni_getStyleBuffer(clone.getNativePointer()).order(ByteOrder.LITTLE_ENDIAN); + return clone; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesJNI.java b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesJNI.java index 3ce7b493b9b804..d7644ba5991187 100644 --- a/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesJNI.java +++ b/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodePropertiesJNI.java @@ -20,13 +20,13 @@ public class YogaNodePropertiesJNI implements Cloneable, YogaNodeProperties { private long mNativePointer; /* Those flags needs be in sync with YGJNI.cpp */ - private static final int MARGIN = 1; - private static final int PADDING = 2; - private static final int BORDER = 4; + protected static final int MARGIN = 1; + protected static final int PADDING = 2; + protected static final int BORDER = 4; - @DoNotStrip private int mEdgeSetFlag = 0; + @DoNotStrip protected int mEdgeSetFlag = 0; - private boolean mHasSetPosition = false; + protected boolean mHasSetPosition = false; @DoNotStrip private float mWidth = YogaConstants.UNDEFINED; @DoNotStrip private float mHeight = YogaConstants.UNDEFINED; diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp index d83f7034495ef0..8aa6565ee0ae22 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -33,6 +33,12 @@ struct JYogaNodePropertiesByteBuffer "Lcom/facebook/yoga/YogaNodePropertiesByteBuffer"; }; +struct JYogaNodePropertiesHybrid + : public JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/yoga/YogaNodePropertiesHybrid"; +}; + struct YGConfigContext { global_ref* logger; global_ref* config; @@ -858,5 +864,10 @@ jint JNI_OnLoad(JavaVM* vm, void*) { YGMakeNativeMethod(jni_getStyleBuffer), YGMakeNativeMethod(jni_getLayoutBuffer), }); + registerNatives( + "com/facebook/yoga/YogaNodePropertiesHybrid", + { + YGMakeNativeMethod(jni_getStyleBuffer), + }); }); }