Files
yoga/java/com/facebook/csslayout/CSSNode.java
Emil Sjolander b59ce09109 BREAKING - Change measure() api to remove need for MeasureOutput allocation
Summary: This is an API breaking change done to allow us to avoid an allocation during measurement. Instead we do the same trick as is done when passing measure results to C, we path them into a long.

Reviewed By: splhack

Differential Revision: D4081037

fbshipit-source-id: 28adbcdd160cbd3f59a0fdd4b9f1200ae18678f1
2016-10-27 10:52:57 -07:00

518 lines
16 KiB
Java

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.csslayout;
import javax.annotation.Nullable;
import java.util.List;
import java.util.ArrayList;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.soloader.SoLoader;
public class CSSNode implements CSSNodeAPI<CSSNode> {
static {
try {
SoLoader.loadLibrary("csslayout");
} catch (Exception ignored) {
// The user probably didn't call SoLoader.init(). Fall back to System.loadLibrary() instead.
System.out.println("Falling back to System.loadLibrary()");
System.loadLibrary("csslayout");
}
}
/**
* Get native instance count. Useful for testing only.
*/
static native int jni_CSSNodeGetInstanceCount();
private CSSNode mParent;
private List<CSSNode> mChildren;
private MeasureFunction mMeasureFunction;
private long mNativePointer;
private Object mData;
private boolean mHasSetPadding = false;
private boolean mHasSetMargin = false;
private boolean mHasSetBorder = false;
private boolean mHasSetPosition = false;
private native long jni_CSSNodeNew();
public CSSNode() {
mNativePointer = jni_CSSNodeNew();
if (mNativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory");
}
mChildren = new ArrayList<>(4);
}
private native void jni_CSSNodeFree(long nativePointer);
@Override
protected void finalize() throws Throwable {
try {
jni_CSSNodeFree(mNativePointer);
} finally {
super.finalize();
}
}
private native void jni_CSSNodeReset(long nativePointer);
@Override
public void reset() {
mHasSetPadding = false;
mHasSetMargin = false;
mHasSetBorder = false;
mHasSetPosition = false;
mMeasureFunction = null;
mData = null;
jni_CSSNodeReset(mNativePointer);
}
@Override
public int getChildCount() {
return mChildren.size();
}
@Override
public CSSNode getChildAt(int i) {
return mChildren.get(i);
}
private native void jni_CSSNodeInsertChild(long nativePointer, long childPointer, int index);
@Override
public void addChildAt(CSSNode child, int i) {
if (child.mParent != null) {
throw new IllegalStateException("Child already has a parent, it must be removed first.");
}
mChildren.add(i, child);
child.mParent = this;
jni_CSSNodeInsertChild(mNativePointer, child.mNativePointer, i);
}
private native void jni_CSSNodeRemoveChild(long nativePointer, long childPointer);
@Override
public CSSNode removeChildAt(int i) {
final CSSNode child = mChildren.remove(i);
child.mParent = null;
jni_CSSNodeRemoveChild(mNativePointer, child.mNativePointer);
return child;
}
@Override
public @Nullable
CSSNode getParent() {
return mParent;
}
@Override
public int indexOf(CSSNode child) {
return mChildren.indexOf(child);
}
private native void jni_CSSNodeSetIsTextNode(long nativePointer, boolean isTextNode);
@Override
public void setIsTextNode(boolean isTextNode) {
jni_CSSNodeSetIsTextNode(mNativePointer, isTextNode);
}
private native boolean jni_CSSNodeGetIsTextNode(long nativePointer);
@Override
public boolean isTextNode() {
return jni_CSSNodeGetIsTextNode(mNativePointer);
}
private native void jni_CSSNodeCalculateLayout(long nativePointer);
@Override
public void calculateLayout(CSSLayoutContext layoutContext) {
jni_CSSNodeCalculateLayout(mNativePointer);
}
private native boolean jni_CSSNodeHasNewLayout(long nativePointer);
@Override
public boolean hasNewLayout() {
return jni_CSSNodeHasNewLayout(mNativePointer);
}
private native void jni_CSSNodeMarkDirty(long nativePointer);
@Override
public void dirty() {
jni_CSSNodeMarkDirty(mNativePointer);
}
private native boolean jni_CSSNodeIsDirty(long nativePointer);
@Override
public boolean isDirty() {
return jni_CSSNodeIsDirty(mNativePointer);
}
private native void jni_CSSNodeMarkLayoutSeen(long nativePointer);
@Override
public void markLayoutSeen() {
jni_CSSNodeMarkLayoutSeen(mNativePointer);
}
private native int jni_CSSNodeStyleGetDirection(long nativePointer);
@Override
public CSSDirection getStyleDirection() {
return CSSDirection.values()[jni_CSSNodeStyleGetDirection(mNativePointer)];
}
private native void jni_CSSNodeStyleSetDirection(long nativePointer, int direction);
@Override
public void setDirection(CSSDirection direction) {
jni_CSSNodeStyleSetDirection(mNativePointer, direction.ordinal());
}
private native int jni_CSSNodeLayoutGetDirection(long nativePointer);
@Override
public CSSDirection getLayoutDirection() {
return CSSDirection.values()[jni_CSSNodeLayoutGetDirection(mNativePointer)];
}
private native int jni_CSSNodeStyleGetFlexDirection(long nativePointer);
@Override
public CSSFlexDirection getFlexDirection() {
return CSSFlexDirection.values()[jni_CSSNodeStyleGetFlexDirection(mNativePointer)];
}
private native void jni_CSSNodeStyleSetFlexDirection(long nativePointer, int flexDirection);
@Override
public void setFlexDirection(CSSFlexDirection flexDirection) {
jni_CSSNodeStyleSetFlexDirection(mNativePointer, flexDirection.ordinal());
}
private native int jni_CSSNodeStyleGetJustifyContent(long nativePointer);
@Override
public CSSJustify getJustifyContent() {
return CSSJustify.values()[jni_CSSNodeStyleGetJustifyContent(mNativePointer)];
}
private native void jni_CSSNodeStyleSetJustifyContent(long nativePointer, int justifyContent);
@Override
public void setJustifyContent(CSSJustify justifyContent) {
jni_CSSNodeStyleSetJustifyContent(mNativePointer, justifyContent.ordinal());
}
private native int jni_CSSNodeStyleGetAlignItems(long nativePointer);
@Override
public CSSAlign getAlignItems() {
return CSSAlign.values()[jni_CSSNodeStyleGetAlignItems(mNativePointer)];
}
private native void jni_CSSNodeStyleSetAlignItems(long nativePointer, int alignItems);
@Override
public void setAlignItems(CSSAlign alignItems) {
jni_CSSNodeStyleSetAlignItems(mNativePointer, alignItems.ordinal());
}
private native int jni_CSSNodeStyleGetAlignSelf(long nativePointer);
@Override
public CSSAlign getAlignSelf() {
return CSSAlign.values()[jni_CSSNodeStyleGetAlignSelf(mNativePointer)];
}
private native void jni_CSSNodeStyleSetAlignSelf(long nativePointer, int alignSelf);
@Override
public void setAlignSelf(CSSAlign alignSelf) {
jni_CSSNodeStyleSetAlignSelf(mNativePointer, alignSelf.ordinal());
}
private native int jni_CSSNodeStyleGetAlignContent(long nativePointer);
@Override
public CSSAlign getAlignContent() {
return CSSAlign.values()[jni_CSSNodeStyleGetAlignContent(mNativePointer)];
}
private native void jni_CSSNodeStyleSetAlignContent(long nativePointer, int alignContent);
@Override
public void setAlignContent(CSSAlign alignContent) {
jni_CSSNodeStyleSetAlignContent(mNativePointer, alignContent.ordinal());
}
private native int jni_CSSNodeStyleGetPositionType(long nativePointer);
@Override
public CSSPositionType getPositionType() {
return CSSPositionType.values()[jni_CSSNodeStyleGetPositionType(mNativePointer)];
}
private native void jni_CSSNodeStyleSetPositionType(long nativePointer, int positionType);
@Override
public void setPositionType(CSSPositionType positionType) {
jni_CSSNodeStyleSetPositionType(mNativePointer, positionType.ordinal());
}
private native void jni_CSSNodeStyleSetFlexWrap(long nativePointer, int wrapType);
@Override
public void setWrap(CSSWrap flexWrap) {
jni_CSSNodeStyleSetFlexWrap(mNativePointer, flexWrap.ordinal());
}
private native int jni_CSSNodeStyleGetOverflow(long nativePointer);
@Override
public CSSOverflow getOverflow() {
return CSSOverflow.values()[jni_CSSNodeStyleGetOverflow(mNativePointer)];
}
private native void jni_CSSNodeStyleSetOverflow(long nativePointer, int overflow);
@Override
public void setOverflow(CSSOverflow overflow) {
jni_CSSNodeStyleSetOverflow(mNativePointer, overflow.ordinal());
}
private native void jni_CSSNodeStyleSetFlex(long nativePointer, float flex);
@Override
public void setFlex(float flex) {
jni_CSSNodeStyleSetFlex(mNativePointer, flex);
}
private native float jni_CSSNodeStyleGetFlexGrow(long nativePointer);
@Override
public float getFlexGrow() {
return jni_CSSNodeStyleGetFlexGrow(mNativePointer);
}
private native void jni_CSSNodeStyleSetFlexGrow(long nativePointer, float flexGrow);
@Override
public void setFlexGrow(float flexGrow) {
jni_CSSNodeStyleSetFlexGrow(mNativePointer, flexGrow);
}
private native float jni_CSSNodeStyleGetFlexShrink(long nativePointer);
@Override
public float getFlexShrink() {
return jni_CSSNodeStyleGetFlexShrink(mNativePointer);
}
private native void jni_CSSNodeStyleSetFlexShrink(long nativePointer, float flexShrink);
@Override
public void setFlexShrink(float flexShrink) {
jni_CSSNodeStyleSetFlexShrink(mNativePointer, flexShrink);
}
private native float jni_CSSNodeStyleGetFlexBasis(long nativePointer);
@Override
public float getFlexBasis() {
return jni_CSSNodeStyleGetFlexBasis(mNativePointer);
}
private native void jni_CSSNodeStyleSetFlexBasis(long nativePointer, float flexBasis);
@Override
public void setFlexBasis(float flexBasis) {
jni_CSSNodeStyleSetFlexBasis(mNativePointer, flexBasis);
}
private native float jni_CSSNodeStyleGetMargin(long nativePointer, int edge);
@Override
public float getMargin(int spacingType) {
if (!mHasSetMargin) {
return spacingType < Spacing.START ? 0 : CSSConstants.UNDEFINED;
}
return jni_CSSNodeStyleGetMargin(mNativePointer, spacingType);
}
private native void jni_CSSNodeStyleSetMargin(long nativePointer, int edge, float margin);
@Override
public void setMargin(int spacingType, float margin) {
mHasSetMargin = true;
jni_CSSNodeStyleSetMargin(mNativePointer, spacingType, margin);
}
private native float jni_CSSNodeStyleGetPadding(long nativePointer, int edge);
@Override
public float getPadding(int spacingType) {
if (!mHasSetPadding) {
return spacingType < Spacing.START ? 0 : CSSConstants.UNDEFINED;
}
return jni_CSSNodeStyleGetPadding(mNativePointer, spacingType);
}
private native void jni_CSSNodeStyleSetPadding(long nativePointer, int edge, float padding);
@Override
public void setPadding(int spacingType, float padding) {
mHasSetPadding = true;
jni_CSSNodeStyleSetPadding(mNativePointer, spacingType, padding);
}
private native float jni_CSSNodeStyleGetBorder(long nativePointer, int edge);
@Override
public float getBorder(int spacingType) {
if (!mHasSetBorder) {
return spacingType < Spacing.START ? 0 : CSSConstants.UNDEFINED;
}
return jni_CSSNodeStyleGetBorder(mNativePointer, spacingType);
}
private native void jni_CSSNodeStyleSetBorder(long nativePointer, int edge, float border);
@Override
public void setBorder(int spacingType, float border) {
mHasSetBorder = true;
jni_CSSNodeStyleSetBorder(mNativePointer, spacingType, border);
}
private native float jni_CSSNodeStyleGetPosition(long nativePointer, int edge);
@Override
public float getPosition(int spacingType) {
if (!mHasSetPosition) {
return CSSConstants.UNDEFINED;
}
return jni_CSSNodeStyleGetPosition(mNativePointer, spacingType);
}
private native void jni_CSSNodeStyleSetPosition(long nativePointer, int edge, float position);
@Override
public void setPosition(int spacingType, float position) {
mHasSetPosition = true;
jni_CSSNodeStyleSetPosition(mNativePointer, spacingType, position);
}
private native float jni_CSSNodeStyleGetWidth(long nativePointer);
@Override
public float getStyleWidth() {
return jni_CSSNodeStyleGetWidth(mNativePointer);
}
private native void jni_CSSNodeStyleSetWidth(long nativePointer, float width);
@Override
public void setStyleWidth(float width) {
jni_CSSNodeStyleSetWidth(mNativePointer, width);
}
private native float jni_CSSNodeStyleGetHeight(long nativePointer);
@Override
public float getStyleHeight() {
return jni_CSSNodeStyleGetHeight(mNativePointer);
}
private native void jni_CSSNodeStyleSetHeight(long nativePointer, float height);
@Override
public void setStyleHeight(float height) {
jni_CSSNodeStyleSetHeight(mNativePointer, height);
}
private native float jni_CSSNodeStyleGetMinWidth(long nativePointer);
@Override
public float getStyleMinWidth() {
return jni_CSSNodeStyleGetMinWidth(mNativePointer);
}
private native void jni_CSSNodeStyleSetMinWidth(long nativePointer, float minWidth);
@Override
public void setStyleMinWidth(float minWidth) {
jni_CSSNodeStyleSetMinWidth(mNativePointer, minWidth);
}
private native float jni_CSSNodeStyleGetMinHeight(long nativePointer);
@Override
public float getStyleMinHeight() {
return jni_CSSNodeStyleGetMinHeight(mNativePointer);
}
private native void jni_CSSNodeStyleSetMinHeight(long nativePointer, float minHeight);
@Override
public void setStyleMinHeight(float minHeight) {
jni_CSSNodeStyleSetMinHeight(mNativePointer, minHeight);
}
private native float jni_CSSNodeStyleGetMaxWidth(long nativePointer);
@Override
public float getStyleMaxWidth() {
return jni_CSSNodeStyleGetMaxWidth(mNativePointer);
}
private native void jni_CSSNodeStyleSetMaxWidth(long nativePointer, float maxWidth);
@Override
public void setStyleMaxWidth(float maxWidth) {
jni_CSSNodeStyleSetMaxWidth(mNativePointer, maxWidth);
}
private native float jni_CSSNodeStyleGetMaxHeight(long nativePointer);
@Override
public float getStyleMaxHeight() {
return jni_CSSNodeStyleGetMaxHeight(mNativePointer);
}
private native void jni_CSSNodeStyleSetMaxHeight(long nativePointer, float maxheight);
@Override
public void setStyleMaxHeight(float maxheight) {
jni_CSSNodeStyleSetMaxHeight(mNativePointer, maxheight);
}
private native float jni_CSSNodeLayoutGetLeft(long nativePointer);
@Override
public float getLayoutX() {
return jni_CSSNodeLayoutGetLeft(mNativePointer);
}
private native float jni_CSSNodeLayoutGetTop(long nativePointer);
@Override
public float getLayoutY() {
return jni_CSSNodeLayoutGetTop(mNativePointer);
}
private native float jni_CSSNodeLayoutGetWidth(long nativePointer);
@Override
public float getLayoutWidth() {
return jni_CSSNodeLayoutGetWidth(mNativePointer);
}
private native float jni_CSSNodeLayoutGetHeight(long nativePointer);
@Override
public float getLayoutHeight() {
return jni_CSSNodeLayoutGetHeight(mNativePointer);
}
private native void jni_CSSNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc);
@Override
public void setMeasureFunction(MeasureFunction measureFunction) {
mMeasureFunction = measureFunction;
jni_CSSNodeSetHasMeasureFunc(mNativePointer, measureFunction != null);
}
@DoNotStrip
public 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,
CSSMeasureMode.values()[widthMode],
height,
CSSMeasureMode.values()[heightMode]);
}
@Override
public boolean isMeasureDefined() {
return mMeasureFunction != null;
}
@Override
public boolean valuesEqual(float f1, float f2) {
return FloatUtil.floatsEqual(f1, f2);
}
@Override
public void setData(Object data) {
mData = data;
}
@Override
public Object getData() {
return mData;
}
}