Loading core/java/android/view/RenderNode.java +4 −1 Original line number Diff line number Diff line Loading @@ -346,7 +346,9 @@ public class RenderNode { * Deep copies the data into native to simplify reference ownership. */ public boolean setOutline(Outline outline) { if (outline == null || outline.isEmpty()) { if (outline == null) { return nSetOutlineNone(mNativeRenderNode); } else if (outline.isEmpty()) { return nSetOutlineEmpty(mNativeRenderNode); } else if (outline.mRect != null) { return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top, Loading Loading @@ -878,6 +880,7 @@ public class RenderNode { int right, int bottom, float radius); private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath); private static native boolean nSetOutlineEmpty(long renderNode); private static native boolean nSetOutlineNone(long renderNode); private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); private static native boolean nSetRevealClip(long renderNode, boolean shouldClip, boolean inverseClip, float x, float y, float radius); Loading core/jni/android_view_RenderNode.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,14 @@ static jboolean android_view_RenderNode_setOutlineEmpty(JNIEnv* env, return true; } static jboolean android_view_RenderNode_setOutlineNone(JNIEnv* env, jobject clazz, jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setNone(); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); return true; } static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean clipToOutline) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); Loading Loading @@ -486,6 +494,7 @@ static JNINativeMethod gMethods[] = { { "nSetOutlineRoundRect", "(JIIIIF)Z", (void*) android_view_RenderNode_setOutlineRoundRect }, { "nSetOutlineConvexPath", "(JJ)Z", (void*) android_view_RenderNode_setOutlineConvexPath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, { "nSetRevealClip", "(JZZFFF)Z", (void*) android_view_RenderNode_setRevealClip }, Loading graphics/java/android/graphics/Outline.java +16 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,11 @@ public final class Outline { * Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)} */ public void setRoundRect(int left, int top, int right, int bottom, float radius) { if (left >= right || top >= bottom) { setEmpty(); return; } if (mRect == null) mRect = new Rect(); mRect.set(left, top, right, bottom); mRadius = radius; Loading @@ -173,11 +178,17 @@ public final class Outline { * Sets the outline to the oval defined by input rect. */ public void setOval(int left, int top, int right, int bottom) { if (left >= right || top >= bottom) { setEmpty(); return; } if ((bottom - top) == (right - left)) { // represent circle as round rect, for efficiency, and to enable clipping setRoundRect(left, top, right, bottom, (bottom - top) / 2.0f); return; } if (mPath == null) mPath = new Path(); mPath.reset(); mPath.addOval(left, top, right, bottom, Path.Direction.CW); Loading @@ -196,6 +207,11 @@ public final class Outline { * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}. */ public void setConvexPath(@NonNull Path convexPath) { if (convexPath.isEmpty()) { setEmpty(); return; } if (!convexPath.isConvex()) { throw new IllegalArgumentException("path must be convex"); } Loading libs/hwui/Outline.h +12 −6 Original line number Diff line number Diff line Loading @@ -49,15 +49,20 @@ public: mBounds.set(outline->getBounds()); } bool isEmpty() const { return mType == kOutlineType_None; void setEmpty() { mType = kOutlineType_Empty; mPath.reset(); } void setEmpty() { void setNone() { mType = kOutlineType_None; mPath.reset(); } bool isEmpty() const { return mType == kOutlineType_Empty; } void setShouldClip(bool clip) { mShouldClip = clip; } Loading @@ -81,7 +86,7 @@ public: } const SkPath* getPath() const { if (mType == kOutlineType_None) return NULL; if (mType == kOutlineType_None || mType == kOutlineType_Empty) return NULL; return &mPath; } Loading @@ -89,8 +94,9 @@ public: private: enum OutlineType { kOutlineType_None = 0, kOutlineType_ConvexPath = 1, kOutlineType_RoundRect = 2 kOutlineType_Empty = 1, kOutlineType_ConvexPath = 2, kOutlineType_RoundRect = 3 }; bool mShouldClip; Loading libs/hwui/RenderNode.cpp +13 −6 Original line number Diff line number Diff line Loading @@ -581,7 +581,7 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslate template <class T> void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) { if (properties().getAlpha() <= 0.0f || properties().getOutline().isEmpty()) return; if (properties().getAlpha() <= 0.0f || !properties().getOutline().getPath()) return; mat4 shadowMatrixXY(transformFromParent); applyViewPropertyTransforms(shadowMatrixXY); Loading Loading @@ -776,17 +776,24 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& */ template <class T> void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { const int level = handler.level(); if (mDisplayListData->isEmpty()) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName()); return; } const bool drawLayer = (mLayer && (&renderer != mLayer->renderer)); // If we are updating the contents of mLayer, we don't want to apply any of // the RenderNode's properties to this issueOperations pass. Those will all // be applied when the layer is drawn, aka when this is true. const bool useViewProperties = (!mLayer || drawLayer); const int level = handler.level(); if (mDisplayListData->isEmpty() || (useViewProperties && properties().getAlpha() <= 0)) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName()); if (useViewProperties) { const Outline& outline = properties().getOutline(); if (properties().getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty())) { DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", level * 2, "", this, getName()); return; } } handler.startMark(getName()); Loading Loading
core/java/android/view/RenderNode.java +4 −1 Original line number Diff line number Diff line Loading @@ -346,7 +346,9 @@ public class RenderNode { * Deep copies the data into native to simplify reference ownership. */ public boolean setOutline(Outline outline) { if (outline == null || outline.isEmpty()) { if (outline == null) { return nSetOutlineNone(mNativeRenderNode); } else if (outline.isEmpty()) { return nSetOutlineEmpty(mNativeRenderNode); } else if (outline.mRect != null) { return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top, Loading Loading @@ -878,6 +880,7 @@ public class RenderNode { int right, int bottom, float radius); private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath); private static native boolean nSetOutlineEmpty(long renderNode); private static native boolean nSetOutlineNone(long renderNode); private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); private static native boolean nSetRevealClip(long renderNode, boolean shouldClip, boolean inverseClip, float x, float y, float radius); Loading
core/jni/android_view_RenderNode.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,14 @@ static jboolean android_view_RenderNode_setOutlineEmpty(JNIEnv* env, return true; } static jboolean android_view_RenderNode_setOutlineNone(JNIEnv* env, jobject clazz, jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutableOutline().setNone(); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); return true; } static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env, jobject clazz, jlong renderNodePtr, jboolean clipToOutline) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); Loading Loading @@ -486,6 +494,7 @@ static JNINativeMethod gMethods[] = { { "nSetOutlineRoundRect", "(JIIIIF)Z", (void*) android_view_RenderNode_setOutlineRoundRect }, { "nSetOutlineConvexPath", "(JJ)Z", (void*) android_view_RenderNode_setOutlineConvexPath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, { "nSetRevealClip", "(JZZFFF)Z", (void*) android_view_RenderNode_setRevealClip }, Loading
graphics/java/android/graphics/Outline.java +16 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,11 @@ public final class Outline { * Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)} */ public void setRoundRect(int left, int top, int right, int bottom, float radius) { if (left >= right || top >= bottom) { setEmpty(); return; } if (mRect == null) mRect = new Rect(); mRect.set(left, top, right, bottom); mRadius = radius; Loading @@ -173,11 +178,17 @@ public final class Outline { * Sets the outline to the oval defined by input rect. */ public void setOval(int left, int top, int right, int bottom) { if (left >= right || top >= bottom) { setEmpty(); return; } if ((bottom - top) == (right - left)) { // represent circle as round rect, for efficiency, and to enable clipping setRoundRect(left, top, right, bottom, (bottom - top) / 2.0f); return; } if (mPath == null) mPath = new Path(); mPath.reset(); mPath.addOval(left, top, right, bottom, Path.Direction.CW); Loading @@ -196,6 +207,11 @@ public final class Outline { * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}. */ public void setConvexPath(@NonNull Path convexPath) { if (convexPath.isEmpty()) { setEmpty(); return; } if (!convexPath.isConvex()) { throw new IllegalArgumentException("path must be convex"); } Loading
libs/hwui/Outline.h +12 −6 Original line number Diff line number Diff line Loading @@ -49,15 +49,20 @@ public: mBounds.set(outline->getBounds()); } bool isEmpty() const { return mType == kOutlineType_None; void setEmpty() { mType = kOutlineType_Empty; mPath.reset(); } void setEmpty() { void setNone() { mType = kOutlineType_None; mPath.reset(); } bool isEmpty() const { return mType == kOutlineType_Empty; } void setShouldClip(bool clip) { mShouldClip = clip; } Loading @@ -81,7 +86,7 @@ public: } const SkPath* getPath() const { if (mType == kOutlineType_None) return NULL; if (mType == kOutlineType_None || mType == kOutlineType_Empty) return NULL; return &mPath; } Loading @@ -89,8 +94,9 @@ public: private: enum OutlineType { kOutlineType_None = 0, kOutlineType_ConvexPath = 1, kOutlineType_RoundRect = 2 kOutlineType_Empty = 1, kOutlineType_ConvexPath = 2, kOutlineType_RoundRect = 3 }; bool mShouldClip; Loading
libs/hwui/RenderNode.cpp +13 −6 Original line number Diff line number Diff line Loading @@ -581,7 +581,7 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslate template <class T> void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) { if (properties().getAlpha() <= 0.0f || properties().getOutline().isEmpty()) return; if (properties().getAlpha() <= 0.0f || !properties().getOutline().getPath()) return; mat4 shadowMatrixXY(transformFromParent); applyViewPropertyTransforms(shadowMatrixXY); Loading Loading @@ -776,17 +776,24 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& */ template <class T> void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { const int level = handler.level(); if (mDisplayListData->isEmpty()) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName()); return; } const bool drawLayer = (mLayer && (&renderer != mLayer->renderer)); // If we are updating the contents of mLayer, we don't want to apply any of // the RenderNode's properties to this issueOperations pass. Those will all // be applied when the layer is drawn, aka when this is true. const bool useViewProperties = (!mLayer || drawLayer); const int level = handler.level(); if (mDisplayListData->isEmpty() || (useViewProperties && properties().getAlpha() <= 0)) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName()); if (useViewProperties) { const Outline& outline = properties().getOutline(); if (properties().getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty())) { DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", level * 2, "", this, getName()); return; } } handler.startMark(getName()); Loading