From 28ebc4ac6a45e2d43c970c6f408be9c7ddf4f94a Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 13 May 2026 06:55:46 -0700 Subject: [PATCH] Migrate YogaNodeJNIBase.java to Kotlin (#56780) Summary: X-link: https://github.com/facebook/yoga/pull/1939 Pull Request resolved: https://github.com/facebook/react-native/pull/56780 Migrate YogaNodeJNIBase.java to YogaNodeJNIBase.kt, the last hand-written Java source file in the Yoga core library. This required converting all function overrides to Kotlin property overrides where the abstract YogaNode class declares them as val/var properties. Also changed nativePointer visibility in YogaConfigJNIBase from protected to internal to maintain same-module access that Java protected provided via package access. Changelog: [Internal] - Differential Revision: D104666335 --- .../main/java/com/facebook/yoga/YogaNode.kt | 4 +- .../com/facebook/yoga/YogaNodeJNIBase.java | 928 ------------------ .../java/com/facebook/yoga/YogaNodeJNIBase.kt | 724 ++++++++++++++ .../com/facebook/yoga/YogaNodeJNIFinalizer.kt | 8 +- .../main/java/com/facebook/yoga/YogaProps.kt | 4 +- 5 files changed, 732 insertions(+), 936 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt index fbd06f2e1bc9..a807dc5ccee1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.kt @@ -226,9 +226,9 @@ public abstract class YogaNode : YogaProps { public abstract val layoutDirection: YogaDirection - abstract override fun setMeasureFunction(measureFunction: YogaMeasureFunction) + abstract override fun setMeasureFunction(measureFunction: YogaMeasureFunction?) - abstract override fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction) + abstract override fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction?) public abstract val isMeasureDefined: Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java deleted file mode 100644 index c862389ba302..000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and 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.yoga; - -import com.facebook.yoga.annotations.DoNotStrip; -import java.util.ArrayList; -import java.util.List; -import javax.annotation.Nullable; - -@DoNotStrip -public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable { - - /* Those flags needs be in sync with YGJNI.h */ - private static final byte MARGIN = 1; - private static final byte PADDING = 2; - private static final byte BORDER = 4; - private static final byte HAS_NEW_LAYOUT = 16; - - private static final byte LAYOUT_EDGE_SET_FLAG_INDEX = 0; - private static final byte LAYOUT_WIDTH_INDEX = 1; - private static final byte LAYOUT_HEIGHT_INDEX = 2; - private static final byte LAYOUT_LEFT_INDEX = 3; - private static final byte LAYOUT_TOP_INDEX = 4; - private static final byte LAYOUT_DIRECTION_INDEX = 5; - private static final byte LAYOUT_MARGIN_START_INDEX = 6; - private static final byte LAYOUT_PADDING_START_INDEX = 10; - private static final byte LAYOUT_BORDER_START_INDEX = 14; - - @Nullable private YogaNodeJNIBase mOwner; - @Nullable private YogaConfig mConfig; - @Nullable private List mChildren; - @Nullable private YogaMeasureFunction mMeasureFunction; - @Nullable private YogaBaselineFunction mBaselineFunction; - protected long mNativePointer; - @Nullable private Object mData; - - @DoNotStrip private @Nullable float[] arr = null; - - @DoNotStrip private int mLayoutDirection = 0; - - private boolean mHasNewLayout = true; - - private YogaNodeJNIBase(long nativePointer) { - if (nativePointer == 0) { - throw new IllegalStateException("Failed to allocate native memory"); - } - mNativePointer = nativePointer; - } - - YogaNodeJNIBase() { - this(YogaNative.jni_YGNodeNewJNI()); - } - - YogaNodeJNIBase(YogaConfig config) { - this(YogaNative.jni_YGNodeNewWithConfigJNI(((YogaConfigJNIBase) config).nativePointer)); - mConfig = config; // makes sure the YogaConfig is not garbage collected - } - - @Override - public void reset() { - mMeasureFunction = null; - mBaselineFunction = null; - mData = null; - arr = null; - mHasNewLayout = true; - mLayoutDirection = 0; - - YogaNative.jni_YGNodeResetJNI(mNativePointer); - } - - @Override - public int getChildCount() { - return mChildren == null ? 0 : mChildren.size(); - } - - public YogaNodeJNIBase getChildAt(int i) { - if (mChildren == null) { - throw new IllegalStateException("YogaNode does not have children"); - } - return mChildren.get(i); - } - - @Override - public void addChildAt(YogaNode c, int i) { - if (!(c instanceof YogaNodeJNIBase)) { - return; - } - YogaNodeJNIBase child = (YogaNodeJNIBase) c; - if (child.mOwner != null) { - throw new IllegalStateException("Child already has a parent, it must be removed first."); - } - - if (mChildren == null) { - mChildren = new ArrayList<>(4); - } - mChildren.add(i, child); - child.mOwner = this; - YogaNative.jni_YGNodeInsertChildJNI(mNativePointer, child.mNativePointer, i); - } - - @Override - public void setIsReferenceBaseline(boolean isReferenceBaseline) { - YogaNative.jni_YGNodeSetIsReferenceBaselineJNI(mNativePointer, isReferenceBaseline); - } - - @Override - public boolean isReferenceBaseline() { - return YogaNative.jni_YGNodeIsReferenceBaselineJNI(mNativePointer); - } - - public void swapChildAt(YogaNode newChild, int position) { - if (!(newChild instanceof YogaNodeJNIBase)) { - return; - } - YogaNodeJNIBase child = (YogaNodeJNIBase) newChild; - mChildren.remove(position); - mChildren.add(position, child); - child.mOwner = this; - YogaNative.jni_YGNodeSwapChildJNI(mNativePointer, child.mNativePointer, position); - } - - @Override - public YogaNodeJNIBase cloneWithChildren() { - try { - YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone(); - if (clonedYogaNode.mChildren != null) { - clonedYogaNode.mChildren = new ArrayList<>(clonedYogaNode.mChildren); - } - long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer); - clonedYogaNode.mOwner = null; - clonedYogaNode.mNativePointer = clonedNativePointer; - for (int i = 0; i < clonedYogaNode.getChildCount(); i++) { - clonedYogaNode.swapChildAt(clonedYogaNode.getChildAt(i).cloneWithChildren(), i); - } - - return clonedYogaNode; - } catch (CloneNotSupportedException ex) { - // This class implements Cloneable, this should not happen - throw new RuntimeException(ex); - } - } - - @Override - public YogaNodeJNIBase cloneWithoutChildren() { - try { - YogaNodeJNIBase clonedYogaNode = (YogaNodeJNIBase) super.clone(); - long clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(mNativePointer); - clonedYogaNode.mOwner = null; - clonedYogaNode.mNativePointer = clonedNativePointer; - clonedYogaNode.clearChildren(); - return clonedYogaNode; - } catch (CloneNotSupportedException ex) { - // This class implements Cloneable, this should not happen - throw new RuntimeException(ex); - } - } - - private void clearChildren() { - mChildren = null; - YogaNative.jni_YGNodeRemoveAllChildrenJNI(mNativePointer); - } - - public YogaNodeJNIBase removeChildAt(int i) { - if (mChildren == null) { - throw new IllegalStateException( - "Trying to remove a child of a YogaNode that does not have children"); - } - final YogaNodeJNIBase child = mChildren.remove(i); - child.mOwner = null; - YogaNative.jni_YGNodeRemoveChildJNI(mNativePointer, child.mNativePointer); - return child; - } - - /** - * The owner is used to identify the YogaTree that a {@link YogaNode} belongs to. This method will - * return the parent of the {@link YogaNode} when the {@link YogaNode} only belongs to one - * YogaTree or null when the {@link YogaNode} is shared between two or more YogaTrees. - * - * @return the {@link YogaNode} that owns this {@link YogaNode}. - */ - @Nullable - public YogaNodeJNIBase getOwner() { - return mOwner; - } - - /** @deprecated Use #getOwner() instead. This will be removed in the next version. */ - @Deprecated - @Nullable - public YogaNodeJNIBase getParent() { - return getOwner(); - } - - @Override - public int indexOf(YogaNode child) { - return mChildren == null ? -1 : mChildren.indexOf(child); - } - - @Override - public void calculateLayout(float width, float height) { - long[] nativePointers = null; - YogaNodeJNIBase[] nodes = null; - - freeze(null); - - ArrayList n = new ArrayList<>(); - n.add(this); - for (int i = 0; i < n.size(); ++i) { - final YogaNodeJNIBase parent = n.get(i); - List children = parent.mChildren; - if (children != null) { - for (YogaNodeJNIBase child : children) { - child.freeze(parent); - n.add(child); - } - } - } - - nodes = n.toArray(new YogaNodeJNIBase[n.size()]); - nativePointers = new long[nodes.length]; - for (int i = 0; i < nodes.length; ++i) { - nativePointers[i] = nodes[i].mNativePointer; - } - - YogaNative.jni_YGNodeCalculateLayoutJNI(mNativePointer, width, height, nativePointers, nodes); - } - - private void freeze(YogaNode parent) { - Object data = getData(); - if (data instanceof Inputs) { - ((Inputs) data).freeze(this, parent); - } - } - - @Override - public void dirty() { - YogaNative.jni_YGNodeMarkDirtyJNI(mNativePointer); - } - - @Override - public boolean isDirty() { - return YogaNative.jni_YGNodeIsDirtyJNI(mNativePointer); - } - - @Override - public void copyStyle(YogaNode srcNode) { - if (!(srcNode instanceof YogaNodeJNIBase)) { - return; - } - YogaNative.jni_YGNodeCopyStyleJNI(mNativePointer, ((YogaNodeJNIBase) srcNode).mNativePointer); - } - - @Override - public YogaDirection getStyleDirection() { - return YogaDirection.fromInt(YogaNative.jni_YGNodeStyleGetDirectionJNI(mNativePointer)); - } - - @Override - public void setDirection(YogaDirection direction) { - YogaNative.jni_YGNodeStyleSetDirectionJNI(mNativePointer, direction.intValue()); - } - - @Override - public YogaFlexDirection getFlexDirection() { - return YogaFlexDirection.fromInt(YogaNative.jni_YGNodeStyleGetFlexDirectionJNI(mNativePointer)); - } - - @Override - public void setFlexDirection(YogaFlexDirection flexDirection) { - YogaNative.jni_YGNodeStyleSetFlexDirectionJNI(mNativePointer, flexDirection.intValue()); - } - - @Override - public YogaJustify getJustifyContent() { - return YogaJustify.fromInt(YogaNative.jni_YGNodeStyleGetJustifyContentJNI(mNativePointer)); - } - - @Override - public void setJustifyContent(YogaJustify justifyContent) { - YogaNative.jni_YGNodeStyleSetJustifyContentJNI(mNativePointer, justifyContent.intValue()); - } - - @Override - public YogaAlign getAlignItems() { - return YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignItemsJNI(mNativePointer)); - } - - @Override - public void setAlignItems(YogaAlign alignItems) { - YogaNative.jni_YGNodeStyleSetAlignItemsJNI(mNativePointer, alignItems.intValue()); - } - - @Override - public YogaAlign getAlignSelf() { - return YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignSelfJNI(mNativePointer)); - } - - @Override - public void setAlignSelf(YogaAlign alignSelf) { - YogaNative.jni_YGNodeStyleSetAlignSelfJNI(mNativePointer, alignSelf.intValue()); - } - - @Override - public YogaAlign getAlignContent() { - return YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignContentJNI(mNativePointer)); - } - - @Override - public void setAlignContent(YogaAlign alignContent) { - YogaNative.jni_YGNodeStyleSetAlignContentJNI(mNativePointer, alignContent.intValue()); - } - - @Override - public YogaPositionType getPositionType() { - return YogaPositionType.fromInt(YogaNative.jni_YGNodeStyleGetPositionTypeJNI(mNativePointer)); - } - - @Override - public void setPositionType(YogaPositionType positionType) { - YogaNative.jni_YGNodeStyleSetPositionTypeJNI(mNativePointer, positionType.intValue()); - } - - @Override - public YogaBoxSizing getBoxSizing() { - return YogaBoxSizing.fromInt(YogaNative.jni_YGNodeStyleGetBoxSizingJNI(mNativePointer)); - } - - @Override - public void setBoxSizing(YogaBoxSizing boxSizing) { - YogaNative.jni_YGNodeStyleSetBoxSizingJNI(mNativePointer, boxSizing.intValue()); - } - - @Override - public YogaWrap getWrap() { - return YogaWrap.fromInt(YogaNative.jni_YGNodeStyleGetFlexWrapJNI(mNativePointer)); - } - - @Override - public void setWrap(YogaWrap flexWrap) { - YogaNative.jni_YGNodeStyleSetFlexWrapJNI(mNativePointer, flexWrap.intValue()); - } - - @Override - public YogaOverflow getOverflow() { - return YogaOverflow.fromInt(YogaNative.jni_YGNodeStyleGetOverflowJNI(mNativePointer)); - } - - @Override - public void setOverflow(YogaOverflow overflow) { - YogaNative.jni_YGNodeStyleSetOverflowJNI(mNativePointer, overflow.intValue()); - } - - @Override - public YogaDisplay getDisplay() { - return YogaDisplay.fromInt(YogaNative.jni_YGNodeStyleGetDisplayJNI(mNativePointer)); - } - - @Override - public void setDisplay(YogaDisplay display) { - YogaNative.jni_YGNodeStyleSetDisplayJNI(mNativePointer, display.intValue()); - } - - @Override - public float getFlex() { - return YogaNative.jni_YGNodeStyleGetFlexJNI(mNativePointer); - } - - @Override - public void setFlex(float flex) { - YogaNative.jni_YGNodeStyleSetFlexJNI(mNativePointer, flex); - } - - @Override - public float getFlexGrow() { - return YogaNative.jni_YGNodeStyleGetFlexGrowJNI(mNativePointer); - } - - @Override - public void setFlexGrow(float flexGrow) { - YogaNative.jni_YGNodeStyleSetFlexGrowJNI(mNativePointer, flexGrow); - } - - @Override - public float getFlexShrink() { - return YogaNative.jni_YGNodeStyleGetFlexShrinkJNI(mNativePointer); - } - - @Override - public void setFlexShrink(float flexShrink) { - YogaNative.jni_YGNodeStyleSetFlexShrinkJNI(mNativePointer, flexShrink); - } - - @Override - public YogaValue getFlexBasis() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetFlexBasisJNI(mNativePointer)); - } - - @Override - public void setFlexBasis(float flexBasis) { - YogaNative.jni_YGNodeStyleSetFlexBasisJNI(mNativePointer, flexBasis); - } - - @Override - public void setFlexBasisPercent(float percent) { - YogaNative.jni_YGNodeStyleSetFlexBasisPercentJNI(mNativePointer, percent); - } - - @Override - public void setFlexBasisAuto() { - YogaNative.jni_YGNodeStyleSetFlexBasisAutoJNI(mNativePointer); - } - - @Override - public void setFlexBasisMaxContent() { - YogaNative.jni_YGNodeStyleSetFlexBasisMaxContentJNI(mNativePointer); - } - - @Override - public void setFlexBasisFitContent() { - YogaNative.jni_YGNodeStyleSetFlexBasisFitContentJNI(mNativePointer); - } - - @Override - public void setFlexBasisStretch() { - YogaNative.jni_YGNodeStyleSetFlexBasisStretchJNI(mNativePointer); - } - - @Override - public YogaValue getMargin(YogaEdge edge) { - return valueFromLong(YogaNative.jni_YGNodeStyleGetMarginJNI(mNativePointer, edge.intValue())); - } - - @Override - public void setMargin(YogaEdge edge, float margin) { - YogaNative.jni_YGNodeStyleSetMarginJNI(mNativePointer, edge.intValue(), margin); - } - - @Override - public void setMarginPercent(YogaEdge edge, float percent) { - YogaNative.jni_YGNodeStyleSetMarginPercentJNI(mNativePointer, edge.intValue(), percent); - } - - @Override - public void setMarginAuto(YogaEdge edge) { - YogaNative.jni_YGNodeStyleSetMarginAutoJNI(mNativePointer, edge.intValue()); - } - - @Override - public YogaValue getPadding(YogaEdge edge) { - return valueFromLong(YogaNative.jni_YGNodeStyleGetPaddingJNI(mNativePointer, edge.intValue())); - } - - @Override - public void setPadding(YogaEdge edge, float padding) { - YogaNative.jni_YGNodeStyleSetPaddingJNI(mNativePointer, edge.intValue(), padding); - } - - @Override - public void setPaddingPercent(YogaEdge edge, float percent) { - YogaNative.jni_YGNodeStyleSetPaddingPercentJNI(mNativePointer, edge.intValue(), percent); - } - - @Override - public float getBorder(YogaEdge edge) { - return YogaNative.jni_YGNodeStyleGetBorderJNI(mNativePointer, edge.intValue()); - } - - @Override - public void setBorder(YogaEdge edge, float border) { - YogaNative.jni_YGNodeStyleSetBorderJNI(mNativePointer, edge.intValue(), border); - } - - @Override - public YogaValue getPosition(YogaEdge edge) { - return valueFromLong(YogaNative.jni_YGNodeStyleGetPositionJNI(mNativePointer, edge.intValue())); - } - - @Override - public void setPosition(YogaEdge edge, float position) { - YogaNative.jni_YGNodeStyleSetPositionJNI(mNativePointer, edge.intValue(), position); - } - - @Override - public void setPositionPercent(YogaEdge edge, float percent) { - YogaNative.jni_YGNodeStyleSetPositionPercentJNI(mNativePointer, edge.intValue(), percent); - } - - @Override - public void setPositionAuto(YogaEdge edge) { - YogaNative.jni_YGNodeStyleSetPositionAutoJNI(mNativePointer, edge.intValue()); - } - - @Override - public YogaValue getWidth() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetWidthJNI(mNativePointer)); - } - - @Override - public void setWidth(float width) { - YogaNative.jni_YGNodeStyleSetWidthJNI(mNativePointer, width); - } - - @Override - public void setWidthPercent(float percent) { - YogaNative.jni_YGNodeStyleSetWidthPercentJNI(mNativePointer, percent); - } - - @Override - public void setWidthAuto() { - YogaNative.jni_YGNodeStyleSetWidthAutoJNI(mNativePointer); - } - - @Override - public void setWidthMaxContent() { - YogaNative.jni_YGNodeStyleSetWidthMaxContentJNI(mNativePointer); - } - - @Override - public void setWidthFitContent() { - YogaNative.jni_YGNodeStyleSetWidthFitContentJNI(mNativePointer); - } - - @Override - public void setWidthStretch() { - YogaNative.jni_YGNodeStyleSetWidthStretchJNI(mNativePointer); - } - - @Override - public YogaValue getHeight() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetHeightJNI(mNativePointer)); - } - - @Override - public void setHeight(float height) { - YogaNative.jni_YGNodeStyleSetHeightJNI(mNativePointer, height); - } - - @Override - public void setHeightPercent(float percent) { - YogaNative.jni_YGNodeStyleSetHeightPercentJNI(mNativePointer, percent); - } - - @Override - public void setHeightAuto() { - YogaNative.jni_YGNodeStyleSetHeightAutoJNI(mNativePointer); - } - - @Override - public void setHeightMaxContent() { - YogaNative.jni_YGNodeStyleSetHeightMaxContentJNI(mNativePointer); - } - - @Override - public void setHeightFitContent() { - YogaNative.jni_YGNodeStyleSetHeightFitContentJNI(mNativePointer); - } - - @Override - public void setHeightStretch() { - YogaNative.jni_YGNodeStyleSetHeightStretchJNI(mNativePointer); - } - - @Override - public YogaValue getMinWidth() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetMinWidthJNI(mNativePointer)); - } - - @Override - public void setMinWidth(float minWidth) { - YogaNative.jni_YGNodeStyleSetMinWidthJNI(mNativePointer, minWidth); - } - - @Override - public void setMinWidthPercent(float percent) { - YogaNative.jni_YGNodeStyleSetMinWidthPercentJNI(mNativePointer, percent); - } - - @Override - public void setMinWidthMaxContent() { - YogaNative.jni_YGNodeStyleSetMinWidthMaxContentJNI(mNativePointer); - } - - @Override - public void setMinWidthFitContent() { - YogaNative.jni_YGNodeStyleSetMinWidthFitContentJNI(mNativePointer); - } - - @Override - public void setMinWidthStretch() { - YogaNative.jni_YGNodeStyleSetMinWidthStretchJNI(mNativePointer); - } - - @Override - public YogaValue getMinHeight() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetMinHeightJNI(mNativePointer)); - } - - @Override - public void setMinHeight(float minHeight) { - YogaNative.jni_YGNodeStyleSetMinHeightJNI(mNativePointer, minHeight); - } - - @Override - public void setMinHeightPercent(float percent) { - YogaNative.jni_YGNodeStyleSetMinHeightPercentJNI(mNativePointer, percent); - } - - @Override - public void setMinHeightMaxContent() { - YogaNative.jni_YGNodeStyleSetMinHeightMaxContentJNI(mNativePointer); - } - - @Override - public void setMinHeightFitContent() { - YogaNative.jni_YGNodeStyleSetMinHeightFitContentJNI(mNativePointer); - } - - @Override - public void setMinHeightStretch() { - YogaNative.jni_YGNodeStyleSetMinHeightStretchJNI(mNativePointer); - } - - @Override - public YogaValue getMaxWidth() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxWidthJNI(mNativePointer)); - } - - @Override - public void setMaxWidth(float maxWidth) { - YogaNative.jni_YGNodeStyleSetMaxWidthJNI(mNativePointer, maxWidth); - } - - @Override - public void setMaxWidthPercent(float percent) { - YogaNative.jni_YGNodeStyleSetMaxWidthPercentJNI(mNativePointer, percent); - } - - @Override - public void setMaxWidthMaxContent() { - YogaNative.jni_YGNodeStyleSetMaxWidthMaxContentJNI(mNativePointer); - } - - @Override - public void setMaxWidthFitContent() { - YogaNative.jni_YGNodeStyleSetMaxWidthFitContentJNI(mNativePointer); - } - - @Override - public void setMaxWidthStretch() { - YogaNative.jni_YGNodeStyleSetMaxWidthStretchJNI(mNativePointer); - } - - @Override - public YogaValue getMaxHeight() { - return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxHeightJNI(mNativePointer)); - } - - @Override - public void setMaxHeight(float maxheight) { - YogaNative.jni_YGNodeStyleSetMaxHeightJNI(mNativePointer, maxheight); - } - - @Override - public void setMaxHeightPercent(float percent) { - YogaNative.jni_YGNodeStyleSetMaxHeightPercentJNI(mNativePointer, percent); - } - - @Override - public void setMaxHeightMaxContent() { - YogaNative.jni_YGNodeStyleSetMaxHeightMaxContentJNI(mNativePointer); - } - - @Override - public void setMaxHeightFitContent() { - YogaNative.jni_YGNodeStyleSetMaxHeightFitContentJNI(mNativePointer); - } - - @Override - public void setMaxHeightStretch() { - YogaNative.jni_YGNodeStyleSetMaxHeightStretchJNI(mNativePointer); - } - - @Override - public float getAspectRatio() { - return YogaNative.jni_YGNodeStyleGetAspectRatioJNI(mNativePointer); - } - - @Override - public void setAspectRatio(float aspectRatio) { - YogaNative.jni_YGNodeStyleSetAspectRatioJNI(mNativePointer, aspectRatio); - } - - @Override - public void setMeasureFunction(YogaMeasureFunction measureFunction) { - mMeasureFunction = measureFunction; - YogaNative.jni_YGNodeSetHasMeasureFuncJNI(mNativePointer, measureFunction != null); - } - - @Override - public void setAlwaysFormsContainingBlock(boolean alwaysFormsContainingBlock) { - YogaNative.jni_YGNodeSetAlwaysFormsContainingBlockJNI(mNativePointer, alwaysFormsContainingBlock); - } - - // Implementation Note: Why this method needs to stay final - // - // We cache the jmethodid for this method in Yoga code. This means that even if a subclass - // were to override measure, we'd still call this implementation from layout code since the - // overriding method will have a different jmethodid. This is final to prevent that mistake. - @DoNotStrip - public final long measure(float width, int widthMode, float height, int heightMode) { - if (!isMeasureDefined()) { - throw new RuntimeException("Measure function isn't defined!"); - } - - return mMeasureFunction.measure( - this, - width, - YogaMeasureMode.fromInt(widthMode), - height, - YogaMeasureMode.fromInt(heightMode)); - } - - @Override - public void setBaselineFunction(YogaBaselineFunction baselineFunction) { - mBaselineFunction = baselineFunction; - YogaNative.jni_YGNodeSetHasBaselineFuncJNI(mNativePointer, baselineFunction != null); - } - - @DoNotStrip - public final float baseline(float width, float height) { - return mBaselineFunction.baseline(this, width, height); - } - - @Override - public boolean isMeasureDefined() { - return mMeasureFunction != null; - } - - @Override - public boolean isBaselineDefined() { - return mBaselineFunction != null; - } - - @Override - public void setData(Object data) { - mData = data; - } - - @Override - public @Nullable Object getData() { - return mData; - } - - /** - * This method replaces the child at childIndex position with the newNode received by parameter. - * This is different than calling removeChildAt and addChildAt because this method ONLY replaces - * the child in the mChildren datastructure. @DoNotStrip: called from JNI - * - * @return the nativePointer of the newNode {@link YogaNode} - */ - @DoNotStrip - private final long replaceChild(YogaNodeJNIBase newNode, int childIndex) { - if (mChildren == null) { - throw new IllegalStateException("Cannot replace child. YogaNode does not have children"); - } - mChildren.remove(childIndex); - mChildren.add(childIndex, newNode); - newNode.mOwner = this; - return newNode.mNativePointer; - } - - private static YogaValue valueFromLong(long raw) { - return new YogaValue(Float.intBitsToFloat((int) raw), (int) (raw >> 32)); - } - - @Override - public float getLayoutX() { - return arr != null ? arr[LAYOUT_LEFT_INDEX] : 0; - } - - @Override - public float getLayoutY() { - return arr != null ? arr[LAYOUT_TOP_INDEX] : 0; - } - - @Override - public float getLayoutWidth() { - return arr != null ? arr[LAYOUT_WIDTH_INDEX] : 0; - } - - @Override - public float getLayoutHeight() { - return arr != null ? arr[LAYOUT_HEIGHT_INDEX] : 0; - } - - @Override - public float getLayoutMargin(YogaEdge edge) { - if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) { - switch (edge) { - case LEFT: - return arr[LAYOUT_MARGIN_START_INDEX]; - case TOP: - return arr[LAYOUT_MARGIN_START_INDEX + 1]; - case RIGHT: - return arr[LAYOUT_MARGIN_START_INDEX + 2]; - case BOTTOM: - return arr[LAYOUT_MARGIN_START_INDEX + 3]; - case START: - return getLayoutDirection() == YogaDirection.RTL - ? arr[LAYOUT_MARGIN_START_INDEX + 2] - : arr[LAYOUT_MARGIN_START_INDEX]; - case END: - return getLayoutDirection() == YogaDirection.RTL - ? arr[LAYOUT_MARGIN_START_INDEX] - : arr[LAYOUT_MARGIN_START_INDEX + 2]; - default: - throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands"); - } - } else { - return 0; - } - } - - @Override - public float getLayoutPadding(YogaEdge edge) { - if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) { - int paddingStartIndex = - LAYOUT_PADDING_START_INDEX - - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4); - switch (edge) { - case LEFT: - return arr[paddingStartIndex]; - case TOP: - return arr[paddingStartIndex + 1]; - case RIGHT: - return arr[paddingStartIndex + 2]; - case BOTTOM: - return arr[paddingStartIndex + 3]; - case START: - return getLayoutDirection() == YogaDirection.RTL - ? arr[paddingStartIndex + 2] - : arr[paddingStartIndex]; - case END: - return getLayoutDirection() == YogaDirection.RTL - ? arr[paddingStartIndex] - : arr[paddingStartIndex + 2]; - default: - throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands"); - } - } else { - return 0; - } - } - - @Override - public float getLayoutBorder(YogaEdge edge) { - if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) { - int borderStartIndex = - LAYOUT_BORDER_START_INDEX - - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4); - switch (edge) { - case LEFT: - return arr[borderStartIndex]; - case TOP: - return arr[borderStartIndex + 1]; - case RIGHT: - return arr[borderStartIndex + 2]; - case BOTTOM: - return arr[borderStartIndex + 3]; - case START: - return getLayoutDirection() == YogaDirection.RTL - ? arr[borderStartIndex + 2] - : arr[borderStartIndex]; - case END: - return getLayoutDirection() == YogaDirection.RTL - ? arr[borderStartIndex] - : arr[borderStartIndex + 2]; - default: - throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands"); - } - } else { - return 0; - } - } - - @Override - public YogaDirection getLayoutDirection() { - return YogaDirection.fromInt( - arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection); - } - - @Override - public boolean hasNewLayout() { - if (arr != null) { - return (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & HAS_NEW_LAYOUT) == HAS_NEW_LAYOUT; - } else { - return mHasNewLayout; - } - } - - @Override - public void markLayoutSeen() { - if (arr != null) { - arr[LAYOUT_EDGE_SET_FLAG_INDEX] = ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & ~(HAS_NEW_LAYOUT); - } - mHasNewLayout = false; - } - - @Override - public YogaValue getGap(YogaGutter gutter) { - return valueFromLong(YogaNative.jni_YGNodeStyleGetGapJNI(mNativePointer, gutter.intValue())); - } - - @Override - public void setGap(YogaGutter gutter, float gapLength) { - YogaNative.jni_YGNodeStyleSetGapJNI(mNativePointer, gutter.intValue(), gapLength); - } - - @Override - public void setGapPercent(YogaGutter gutter, float gapLength) { - YogaNative.jni_YGNodeStyleSetGapPercentJNI(mNativePointer, gutter.intValue(), gapLength); - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt new file mode 100644 index 000000000000..994ba0729de0 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt @@ -0,0 +1,724 @@ +/* + * Copyright (c) Meta Platforms, Inc. and 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.yoga + +import com.facebook.yoga.annotations.DoNotStrip + +@DoNotStrip +public abstract class YogaNodeJNIBase : YogaNode, Cloneable { + + private var owner: YogaNodeJNIBase? = null + private var config: YogaConfig? = null + private var children: MutableList? = null + private var measureFunction: YogaMeasureFunction? = null + private var baselineFunction: YogaBaselineFunction? = null + protected var nativePointer: Long = 0 + + // JNI-accessed field name — do not rename (see YGJNIVanilla.cpp) + @DoNotStrip private var arr: FloatArray? = null + + // JNI-accessed field name — do not rename (see YGJNIVanilla.cpp) + @DoNotStrip private var mLayoutDirection: Int = 0 + + private var hasNewLayoutField: Boolean = true + + private constructor(nativePtr: Long) { + if (nativePtr == 0L) { + throw IllegalStateException("Failed to allocate native memory") + } + nativePointer = nativePtr + } + + internal constructor() : this(YogaNative.jni_YGNodeNewJNI()) + + internal constructor( + yogaConfig: YogaConfig + ) : this( + YogaNative.jni_YGNodeNewWithConfigJNI((yogaConfig as YogaConfigJNIBase).getNativePointer()) + ) { + config = yogaConfig + } + + override fun reset() { + measureFunction = null + baselineFunction = null + data = null + arr = null + hasNewLayoutField = true + mLayoutDirection = 0 + + YogaNative.jni_YGNodeResetJNI(nativePointer) + } + + override val childCount: Int + get() = children?.size ?: 0 + + override fun getChildAt(i: Int): YogaNodeJNIBase { + return children?.get(i) ?: throw IllegalStateException("YogaNode does not have children") + } + + override fun addChildAt(child: YogaNode, i: Int) { + if (child !is YogaNodeJNIBase) { + return + } + if (child.owner != null) { + throw IllegalStateException("Child already has a parent, it must be removed first.") + } + + if (children == null) { + children = ArrayList(4) + } + children!!.add(i, child) + child.owner = this + YogaNative.jni_YGNodeInsertChildJNI(nativePointer, child.nativePointer, i) + } + + override fun setIsReferenceBaseline(isReferenceBaseline: Boolean) { + YogaNative.jni_YGNodeSetIsReferenceBaselineJNI(nativePointer, isReferenceBaseline) + } + + override val isReferenceBaseline: Boolean + get() = YogaNative.jni_YGNodeIsReferenceBaselineJNI(nativePointer) + + public fun swapChildAt(newChild: YogaNode, position: Int) { + if (newChild !is YogaNodeJNIBase) { + return + } + children!!.removeAt(position) + children!!.add(position, newChild) + newChild.owner = this + YogaNative.jni_YGNodeSwapChildJNI(nativePointer, newChild.nativePointer, position) + } + + override fun cloneWithChildren(): YogaNodeJNIBase { + try { + val clonedYogaNode = super.clone() as YogaNodeJNIBase + if (clonedYogaNode.children != null) { + clonedYogaNode.children = ArrayList(clonedYogaNode.children!!) + } + val clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(nativePointer) + clonedYogaNode.owner = null + clonedYogaNode.nativePointer = clonedNativePointer + for (i in 0 until clonedYogaNode.childCount) { + clonedYogaNode.swapChildAt(clonedYogaNode.getChildAt(i).cloneWithChildren(), i) + } + return clonedYogaNode + } catch (ex: CloneNotSupportedException) { + throw RuntimeException(ex) + } + } + + override fun cloneWithoutChildren(): YogaNodeJNIBase { + try { + val clonedYogaNode = super.clone() as YogaNodeJNIBase + val clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(nativePointer) + clonedYogaNode.owner = null + clonedYogaNode.nativePointer = clonedNativePointer + clonedYogaNode.clearChildren() + return clonedYogaNode + } catch (ex: CloneNotSupportedException) { + throw RuntimeException(ex) + } + } + + private fun clearChildren() { + children = null + YogaNative.jni_YGNodeRemoveAllChildrenJNI(nativePointer) + } + + override fun removeChildAt(i: Int): YogaNodeJNIBase { + val childList = + children + ?: throw IllegalStateException( + "Trying to remove a child of a YogaNode that does not have children" + ) + val child = childList.removeAt(i) + child.owner = null + YogaNative.jni_YGNodeRemoveChildJNI(nativePointer, child.nativePointer) + return child + } + + /** + * The owner is used to identify the YogaTree that a [YogaNode] belongs to. This method will + * return the parent of the [YogaNode] when the [YogaNode] only belongs to one YogaTree or null + * when the [YogaNode] is shared between two or more YogaTrees. + * + * @return the [YogaNode] that owns this [YogaNode]. + */ + override fun getOwner(): YogaNodeJNIBase? = owner + + @Deprecated("Use getOwner() instead. This will be removed in the next version.") + override fun getParent(): YogaNodeJNIBase? = getOwner() + + override fun indexOf(child: YogaNode): Int = children?.indexOf(child) ?: -1 + + override fun calculateLayout(width: Float, height: Float) { + freeze(null) + + val n = ArrayList() + n.add(this) + var i = 0 + while (i < n.size) { + val parent = n[i] + val children = parent.children + if (children != null) { + for (child in children) { + child.freeze(parent) + n.add(child) + } + } + ++i + } + + val nodes = n.toTypedArray() + val nativePointers = LongArray(nodes.size) + for (j in nodes.indices) { + nativePointers[j] = nodes[j].nativePointer + } + + YogaNative.jni_YGNodeCalculateLayoutJNI(nativePointer, width, height, nativePointers, nodes) + } + + private fun freeze(parent: YogaNode?) { + val d = data + if (d is Inputs) { + d.freeze(this, parent) + } + } + + override fun dirty() { + YogaNative.jni_YGNodeMarkDirtyJNI(nativePointer) + } + + override fun isDirty(): Boolean = YogaNative.jni_YGNodeIsDirtyJNI(nativePointer) + + override fun copyStyle(srcNode: YogaNode) { + if (srcNode !is YogaNodeJNIBase) { + return + } + YogaNative.jni_YGNodeCopyStyleJNI(nativePointer, srcNode.nativePointer) + } + + override val styleDirection: YogaDirection + get() = YogaDirection.fromInt(YogaNative.jni_YGNodeStyleGetDirectionJNI(nativePointer)) + + override fun setDirection(direction: YogaDirection) { + YogaNative.jni_YGNodeStyleSetDirectionJNI(nativePointer, direction.intValue()) + } + + override var flexDirection: YogaFlexDirection + get() = YogaFlexDirection.fromInt(YogaNative.jni_YGNodeStyleGetFlexDirectionJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetFlexDirectionJNI(nativePointer, value.intValue()) + } + + override var justifyContent: YogaJustify + get() = YogaJustify.fromInt(YogaNative.jni_YGNodeStyleGetJustifyContentJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetJustifyContentJNI(nativePointer, value.intValue()) + } + + override var alignItems: YogaAlign + get() = YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignItemsJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetAlignItemsJNI(nativePointer, value.intValue()) + } + + override var alignSelf: YogaAlign + get() = YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignSelfJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetAlignSelfJNI(nativePointer, value.intValue()) + } + + override var alignContent: YogaAlign + get() = YogaAlign.fromInt(YogaNative.jni_YGNodeStyleGetAlignContentJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetAlignContentJNI(nativePointer, value.intValue()) + } + + override var positionType: YogaPositionType + get() = YogaPositionType.fromInt(YogaNative.jni_YGNodeStyleGetPositionTypeJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetPositionTypeJNI(nativePointer, value.intValue()) + } + + override var boxSizing: YogaBoxSizing + get() = YogaBoxSizing.fromInt(YogaNative.jni_YGNodeStyleGetBoxSizingJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetBoxSizingJNI(nativePointer, value.intValue()) + } + + override var wrap: YogaWrap + get() = YogaWrap.fromInt(YogaNative.jni_YGNodeStyleGetFlexWrapJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetFlexWrapJNI(nativePointer, value.intValue()) + } + + override var overflow: YogaOverflow? + get() = YogaOverflow.fromInt(YogaNative.jni_YGNodeStyleGetOverflowJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetOverflowJNI( + nativePointer, + requireNotNull(value) { "overflow must not be null" }.intValue(), + ) + } + + override var display: YogaDisplay? + get() = YogaDisplay.fromInt(YogaNative.jni_YGNodeStyleGetDisplayJNI(nativePointer)) + set(value) { + YogaNative.jni_YGNodeStyleSetDisplayJNI( + nativePointer, + requireNotNull(value) { "display must not be null" }.intValue(), + ) + } + + override var flex: Float + get() = YogaNative.jni_YGNodeStyleGetFlexJNI(nativePointer) + set(value) { + YogaNative.jni_YGNodeStyleSetFlexJNI(nativePointer, value) + } + + override var flexGrow: Float + get() = YogaNative.jni_YGNodeStyleGetFlexGrowJNI(nativePointer) + set(value) { + YogaNative.jni_YGNodeStyleSetFlexGrowJNI(nativePointer, value) + } + + override var flexShrink: Float + get() = YogaNative.jni_YGNodeStyleGetFlexShrinkJNI(nativePointer) + set(value) { + YogaNative.jni_YGNodeStyleSetFlexShrinkJNI(nativePointer, value) + } + + override val flexBasis: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetFlexBasisJNI(nativePointer)) + + override fun setFlexBasis(flexBasis: Float) { + YogaNative.jni_YGNodeStyleSetFlexBasisJNI(nativePointer, flexBasis) + } + + override fun setFlexBasisPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetFlexBasisPercentJNI(nativePointer, percent) + } + + override fun setFlexBasisAuto() { + YogaNative.jni_YGNodeStyleSetFlexBasisAutoJNI(nativePointer) + } + + override fun setFlexBasisMaxContent() { + YogaNative.jni_YGNodeStyleSetFlexBasisMaxContentJNI(nativePointer) + } + + override fun setFlexBasisFitContent() { + YogaNative.jni_YGNodeStyleSetFlexBasisFitContentJNI(nativePointer) + } + + override fun setFlexBasisStretch() { + YogaNative.jni_YGNodeStyleSetFlexBasisStretchJNI(nativePointer) + } + + override fun getMargin(edge: YogaEdge): YogaValue = + valueFromLong(YogaNative.jni_YGNodeStyleGetMarginJNI(nativePointer, edge.intValue())) + + override fun setMargin(edge: YogaEdge, margin: Float) { + YogaNative.jni_YGNodeStyleSetMarginJNI(nativePointer, edge.intValue(), margin) + } + + override fun setMarginPercent(edge: YogaEdge, percent: Float) { + YogaNative.jni_YGNodeStyleSetMarginPercentJNI(nativePointer, edge.intValue(), percent) + } + + override fun setMarginAuto(edge: YogaEdge) { + YogaNative.jni_YGNodeStyleSetMarginAutoJNI(nativePointer, edge.intValue()) + } + + override fun getPadding(edge: YogaEdge): YogaValue = + valueFromLong(YogaNative.jni_YGNodeStyleGetPaddingJNI(nativePointer, edge.intValue())) + + override fun setPadding(edge: YogaEdge, padding: Float) { + YogaNative.jni_YGNodeStyleSetPaddingJNI(nativePointer, edge.intValue(), padding) + } + + override fun setPaddingPercent(edge: YogaEdge, percent: Float) { + YogaNative.jni_YGNodeStyleSetPaddingPercentJNI(nativePointer, edge.intValue(), percent) + } + + override fun getBorder(edge: YogaEdge): Float = + YogaNative.jni_YGNodeStyleGetBorderJNI(nativePointer, edge.intValue()) + + override fun setBorder(edge: YogaEdge, value: Float) { + YogaNative.jni_YGNodeStyleSetBorderJNI(nativePointer, edge.intValue(), value) + } + + override fun getPosition(edge: YogaEdge): YogaValue = + valueFromLong(YogaNative.jni_YGNodeStyleGetPositionJNI(nativePointer, edge.intValue())) + + override fun setPosition(edge: YogaEdge, position: Float) { + YogaNative.jni_YGNodeStyleSetPositionJNI(nativePointer, edge.intValue(), position) + } + + override fun setPositionPercent(edge: YogaEdge, percent: Float) { + YogaNative.jni_YGNodeStyleSetPositionPercentJNI(nativePointer, edge.intValue(), percent) + } + + override fun setPositionAuto(edge: YogaEdge) { + YogaNative.jni_YGNodeStyleSetPositionAutoJNI(nativePointer, edge.intValue()) + } + + override val width: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetWidthJNI(nativePointer)) + + override fun setWidth(width: Float) { + YogaNative.jni_YGNodeStyleSetWidthJNI(nativePointer, width) + } + + override fun setWidthPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetWidthPercentJNI(nativePointer, percent) + } + + override fun setWidthAuto() { + YogaNative.jni_YGNodeStyleSetWidthAutoJNI(nativePointer) + } + + override fun setWidthMaxContent() { + YogaNative.jni_YGNodeStyleSetWidthMaxContentJNI(nativePointer) + } + + override fun setWidthFitContent() { + YogaNative.jni_YGNodeStyleSetWidthFitContentJNI(nativePointer) + } + + override fun setWidthStretch() { + YogaNative.jni_YGNodeStyleSetWidthStretchJNI(nativePointer) + } + + override val height: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetHeightJNI(nativePointer)) + + override fun setHeight(height: Float) { + YogaNative.jni_YGNodeStyleSetHeightJNI(nativePointer, height) + } + + override fun setHeightPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetHeightPercentJNI(nativePointer, percent) + } + + override fun setHeightAuto() { + YogaNative.jni_YGNodeStyleSetHeightAutoJNI(nativePointer) + } + + override fun setHeightMaxContent() { + YogaNative.jni_YGNodeStyleSetHeightMaxContentJNI(nativePointer) + } + + override fun setHeightFitContent() { + YogaNative.jni_YGNodeStyleSetHeightFitContentJNI(nativePointer) + } + + override fun setHeightStretch() { + YogaNative.jni_YGNodeStyleSetHeightStretchJNI(nativePointer) + } + + override val minWidth: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetMinWidthJNI(nativePointer)) + + override fun setMinWidth(minWidth: Float) { + YogaNative.jni_YGNodeStyleSetMinWidthJNI(nativePointer, minWidth) + } + + override fun setMinWidthPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetMinWidthPercentJNI(nativePointer, percent) + } + + override fun setMinWidthMaxContent() { + YogaNative.jni_YGNodeStyleSetMinWidthMaxContentJNI(nativePointer) + } + + override fun setMinWidthFitContent() { + YogaNative.jni_YGNodeStyleSetMinWidthFitContentJNI(nativePointer) + } + + override fun setMinWidthStretch() { + YogaNative.jni_YGNodeStyleSetMinWidthStretchJNI(nativePointer) + } + + override val minHeight: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetMinHeightJNI(nativePointer)) + + override fun setMinHeight(minHeight: Float) { + YogaNative.jni_YGNodeStyleSetMinHeightJNI(nativePointer, minHeight) + } + + override fun setMinHeightPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetMinHeightPercentJNI(nativePointer, percent) + } + + override fun setMinHeightMaxContent() { + YogaNative.jni_YGNodeStyleSetMinHeightMaxContentJNI(nativePointer) + } + + override fun setMinHeightFitContent() { + YogaNative.jni_YGNodeStyleSetMinHeightFitContentJNI(nativePointer) + } + + override fun setMinHeightStretch() { + YogaNative.jni_YGNodeStyleSetMinHeightStretchJNI(nativePointer) + } + + override val maxWidth: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetMaxWidthJNI(nativePointer)) + + override fun setMaxWidth(maxWidth: Float) { + YogaNative.jni_YGNodeStyleSetMaxWidthJNI(nativePointer, maxWidth) + } + + override fun setMaxWidthPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetMaxWidthPercentJNI(nativePointer, percent) + } + + override fun setMaxWidthMaxContent() { + YogaNative.jni_YGNodeStyleSetMaxWidthMaxContentJNI(nativePointer) + } + + override fun setMaxWidthFitContent() { + YogaNative.jni_YGNodeStyleSetMaxWidthFitContentJNI(nativePointer) + } + + override fun setMaxWidthStretch() { + YogaNative.jni_YGNodeStyleSetMaxWidthStretchJNI(nativePointer) + } + + override val maxHeight: YogaValue + get() = valueFromLong(YogaNative.jni_YGNodeStyleGetMaxHeightJNI(nativePointer)) + + override fun setMaxHeight(maxHeight: Float) { + YogaNative.jni_YGNodeStyleSetMaxHeightJNI(nativePointer, maxHeight) + } + + override fun setMaxHeightPercent(percent: Float) { + YogaNative.jni_YGNodeStyleSetMaxHeightPercentJNI(nativePointer, percent) + } + + override fun setMaxHeightMaxContent() { + YogaNative.jni_YGNodeStyleSetMaxHeightMaxContentJNI(nativePointer) + } + + override fun setMaxHeightFitContent() { + YogaNative.jni_YGNodeStyleSetMaxHeightFitContentJNI(nativePointer) + } + + override fun setMaxHeightStretch() { + YogaNative.jni_YGNodeStyleSetMaxHeightStretchJNI(nativePointer) + } + + override var aspectRatio: Float + get() = YogaNative.jni_YGNodeStyleGetAspectRatioJNI(nativePointer) + set(value) { + YogaNative.jni_YGNodeStyleSetAspectRatioJNI(nativePointer, value) + } + + override fun setMeasureFunction(measureFunction: YogaMeasureFunction?) { + this.measureFunction = measureFunction + YogaNative.jni_YGNodeSetHasMeasureFuncJNI(nativePointer, measureFunction != null) + } + + override fun setAlwaysFormsContainingBlock(alwaysFormsContainingBlock: Boolean) { + YogaNative.jni_YGNodeSetAlwaysFormsContainingBlockJNI( + nativePointer, + alwaysFormsContainingBlock, + ) + } + + // This method must not be overridden: we cache the jmethodid for it in native Yoga code. + // Even if a subclass overrides measure, we'd still call this implementation from layout + // code since the overriding method will have a different jmethodid. In Kotlin, non-open + // methods are final by default, which enforces this constraint. + @DoNotStrip + public fun measure(width: Float, widthMode: Int, height: Float, heightMode: Int): Long { + if (!isMeasureDefined) { + throw RuntimeException("Measure function isn't defined!") + } + + return measureFunction!!.measure( + this, + width, + YogaMeasureMode.fromInt(widthMode), + height, + YogaMeasureMode.fromInt(heightMode), + ) + } + + override fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction?) { + baselineFunction = yogaBaselineFunction + YogaNative.jni_YGNodeSetHasBaselineFuncJNI(nativePointer, yogaBaselineFunction != null) + } + + // Same JNI jmethodid caching concern as measure() — must not be overridden. + @DoNotStrip + public fun baseline(width: Float, height: Float): Float = + baselineFunction!!.baseline(this, width, height) + + override val isMeasureDefined: Boolean + get() = measureFunction != null + + override val isBaselineDefined: Boolean + get() = baselineFunction != null + + override var data: Any? = null + + /** + * Replaces the child at [childIndex] with [newNode]. This is different than calling + * [removeChildAt] and [addChildAt] because this method ONLY replaces the child in the children + * data structure. Called from JNI. + * + * @return the nativePointer of the [newNode]. + */ + @DoNotStrip + private fun replaceChild(newNode: YogaNodeJNIBase, childIndex: Int): Long { + val childList = + children + ?: throw IllegalStateException("Cannot replace child. YogaNode does not have children") + childList.removeAt(childIndex) + childList.add(childIndex, newNode) + newNode.owner = this + return newNode.nativePointer + } + + override val layoutX: Float + get() = arr?.get(LAYOUT_LEFT_INDEX) ?: 0f + + override val layoutY: Float + get() = arr?.get(LAYOUT_TOP_INDEX) ?: 0f + + override val layoutWidth: Float + get() = arr?.get(LAYOUT_WIDTH_INDEX) ?: 0f + + override val layoutHeight: Float + get() = arr?.get(LAYOUT_HEIGHT_INDEX) ?: 0f + + override fun getLayoutMargin(edge: YogaEdge): Float { + val a = arr + if (a != null && (a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and MARGIN) == MARGIN) { + return when (edge) { + YogaEdge.LEFT -> a[LAYOUT_MARGIN_START_INDEX] + YogaEdge.TOP -> a[LAYOUT_MARGIN_START_INDEX + 1] + YogaEdge.RIGHT -> a[LAYOUT_MARGIN_START_INDEX + 2] + YogaEdge.BOTTOM -> a[LAYOUT_MARGIN_START_INDEX + 3] + YogaEdge.START -> + if (layoutDirection == YogaDirection.RTL) a[LAYOUT_MARGIN_START_INDEX + 2] + else a[LAYOUT_MARGIN_START_INDEX] + YogaEdge.END -> + if (layoutDirection == YogaDirection.RTL) a[LAYOUT_MARGIN_START_INDEX] + else a[LAYOUT_MARGIN_START_INDEX + 2] + else -> throw IllegalArgumentException("Cannot get layout margins of multi-edge shorthands") + } + } + return 0f + } + + override fun getLayoutPadding(edge: YogaEdge): Float { + val a = arr + if (a != null && (a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and PADDING) == PADDING) { + val paddingStartIndex = + LAYOUT_PADDING_START_INDEX - + (if ((a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and MARGIN) == MARGIN) 0 else 4) + return when (edge) { + YogaEdge.LEFT -> a[paddingStartIndex] + YogaEdge.TOP -> a[paddingStartIndex + 1] + YogaEdge.RIGHT -> a[paddingStartIndex + 2] + YogaEdge.BOTTOM -> a[paddingStartIndex + 3] + YogaEdge.START -> + if (layoutDirection == YogaDirection.RTL) a[paddingStartIndex + 2] + else a[paddingStartIndex] + YogaEdge.END -> + if (layoutDirection == YogaDirection.RTL) a[paddingStartIndex] + else a[paddingStartIndex + 2] + else -> + throw IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands") + } + } + return 0f + } + + override fun getLayoutBorder(edge: YogaEdge): Float { + val a = arr + if (a != null && (a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and BORDER) == BORDER) { + val borderStartIndex = + LAYOUT_BORDER_START_INDEX - + (if ((a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and MARGIN) == MARGIN) 0 else 4) - + (if ((a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and PADDING) == PADDING) 0 else 4) + return when (edge) { + YogaEdge.LEFT -> a[borderStartIndex] + YogaEdge.TOP -> a[borderStartIndex + 1] + YogaEdge.RIGHT -> a[borderStartIndex + 2] + YogaEdge.BOTTOM -> a[borderStartIndex + 3] + YogaEdge.START -> + if (layoutDirection == YogaDirection.RTL) a[borderStartIndex + 2] + else a[borderStartIndex] + YogaEdge.END -> + if (layoutDirection == YogaDirection.RTL) a[borderStartIndex] + else a[borderStartIndex + 2] + else -> throw IllegalArgumentException("Cannot get layout border of multi-edge shorthands") + } + } + return 0f + } + + override val layoutDirection: YogaDirection + get() = YogaDirection.fromInt(arr?.get(LAYOUT_DIRECTION_INDEX)?.toInt() ?: mLayoutDirection) + + override fun hasNewLayout(): Boolean { + val a = arr + return if (a != null) { + (a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and HAS_NEW_LAYOUT) == HAS_NEW_LAYOUT + } else { + hasNewLayoutField + } + } + + override fun markLayoutSeen() { + val a = arr + if (a != null) { + a[LAYOUT_EDGE_SET_FLAG_INDEX] = + (a[LAYOUT_EDGE_SET_FLAG_INDEX].toInt() and HAS_NEW_LAYOUT.inv()).toFloat() + } + hasNewLayoutField = false + } + + override fun getGap(gutter: YogaGutter): YogaValue = + valueFromLong(YogaNative.jni_YGNodeStyleGetGapJNI(nativePointer, gutter.intValue())) + + override fun setGap(gutter: YogaGutter, gapLength: Float) { + YogaNative.jni_YGNodeStyleSetGapJNI(nativePointer, gutter.intValue(), gapLength) + } + + override fun setGapPercent(gutter: YogaGutter, gapLength: Float) { + YogaNative.jni_YGNodeStyleSetGapPercentJNI(nativePointer, gutter.intValue(), gapLength) + } + + public companion object { + private const val MARGIN: Int = 1 + private const val PADDING: Int = 2 + private const val BORDER: Int = 4 + private const val HAS_NEW_LAYOUT: Int = 16 + + private const val LAYOUT_EDGE_SET_FLAG_INDEX: Int = 0 + private const val LAYOUT_WIDTH_INDEX: Int = 1 + private const val LAYOUT_HEIGHT_INDEX: Int = 2 + private const val LAYOUT_LEFT_INDEX: Int = 3 + private const val LAYOUT_TOP_INDEX: Int = 4 + private const val LAYOUT_DIRECTION_INDEX: Int = 5 + private const val LAYOUT_MARGIN_START_INDEX: Int = 6 + private const val LAYOUT_PADDING_START_INDEX: Int = 10 + private const val LAYOUT_BORDER_START_INDEX: Int = 14 + + @JvmStatic + private fun valueFromLong(raw: Long): YogaValue = + YogaValue(Float.fromBits(raw.toInt()), YogaUnit.fromInt((raw shr 32).toInt())) + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.kt index 64f261127be1..61e42a60be33 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIFinalizer.kt @@ -24,10 +24,10 @@ public class YogaNodeJNIFinalizer : YogaNodeJNIBase { } public fun freeNatives() { - if (mNativePointer != 0L) { - val nativePointer = mNativePointer - mNativePointer = 0 - YogaNative.jni_YGNodeFinalizeJNI(nativePointer) + if (nativePointer != 0L) { + val nativePtr = nativePointer + nativePointer = 0 + YogaNative.jni_YGNodeFinalizeJNI(nativePtr) } } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt index d29ef6bc60dc..0d22ced8ccba 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaProps.kt @@ -123,9 +123,9 @@ public interface YogaProps { public fun setIsReferenceBaseline(isReferenceBaseline: Boolean) - public fun setMeasureFunction(measureFunction: YogaMeasureFunction) + public fun setMeasureFunction(measureFunction: YogaMeasureFunction?) - public fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction) + public fun setBaselineFunction(yogaBaselineFunction: YogaBaselineFunction?) /* Mutable properties - getter and setter with matching types */