diff options
author | John Reck <jreck@google.com> | 2017-11-17 15:06:24 -0800 |
---|---|---|
committer | John Reck <jreck@google.com> | 2018-01-31 11:28:11 -0800 |
commit | d8be4a0abe7e2439813b384482346d1ccf11ef53 (patch) | |
tree | 0b0900e26d868b1c3c42e4e3572ff35c84f7f181 | |
parent | e53c1a1b6bb37e9356121d5d3a6e979c125432ff (diff) |
Add API to set tonal shadow color
Bug: 68211332
Test: HwAccelerationTests's coloredshadow demo & CTS test in topic
Change-Id: I09f5d1067b3200564a9d47219f70985edf3a2527
-rw-r--r-- | api/current.txt | 6 | ||||
-rw-r--r-- | core/java/android/view/RenderNode.java | 29 | ||||
-rw-r--r-- | core/java/android/view/View.java | 63 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 26 | ||||
-rw-r--r-- | core/res/res/values/attrs.xml | 22 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 2 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.h | 19 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp | 8 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | tests/HwAccelerationTest/res/values/styles.xml | 7 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java | 30 |
11 files changed, 193 insertions, 22 deletions
diff --git a/api/current.txt b/api/current.txt index e85beab85e72..0fabba2bbe62 100644 --- a/api/current.txt +++ b/api/current.txt @@ -968,7 +968,9 @@ package android { field public static final int orderingFromXml = 16843239; // 0x10101e7 field public static final int orientation = 16842948; // 0x10100c4 field public static final int outAnimation = 16843128; // 0x1010178 + field public static final int outlineAmbientShadowColor = 16844162; // 0x1010582 field public static final int outlineProvider = 16843960; // 0x10104b8 + field public static final int outlineSpotShadowColor = 16844161; // 0x1010581 field public static final int overScrollFooter = 16843459; // 0x10102c3 field public static final int overScrollHeader = 16843458; // 0x10102c2 field public static final int overScrollMode = 16843457; // 0x10102c1 @@ -46716,7 +46718,9 @@ package android.view { method public int getNextFocusRightId(); method public int getNextFocusUpId(); method public android.view.View.OnFocusChangeListener getOnFocusChangeListener(); + method public int getOutlineAmbientShadowColor(); method public android.view.ViewOutlineProvider getOutlineProvider(); + method public int getOutlineSpotShadowColor(); method public int getOverScrollMode(); method public android.view.ViewOverlay getOverlay(); method public int getPaddingBottom(); @@ -47038,7 +47042,9 @@ package android.view { method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener); method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener); method public void setOnTouchListener(android.view.View.OnTouchListener); + method public void setOutlineAmbientShadowColor(int); method public void setOutlineProvider(android.view.ViewOutlineProvider); + method public void setOutlineSpotShadowColor(int); method public void setOverScrollMode(int); method public void setPadding(int, int, int, int); method public void setPaddingRelative(int, int, int, int); diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 5070151815f5..ce7e8f3b55b5 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -353,9 +353,24 @@ public class RenderNode { return nHasShadow(mNativeRenderNode); } - /** setShadowColor */ - public boolean setShadowColor(int color) { - return nSetShadowColor(mNativeRenderNode, color); + /** setSpotShadowColor */ + public boolean setSpotShadowColor(int color) { + return nSetSpotShadowColor(mNativeRenderNode, color); + } + + /** setAmbientShadowColor */ + public boolean setAmbientShadowColor(int color) { + return nSetAmbientShadowColor(mNativeRenderNode, color); + } + + /** getSpotShadowColor */ + public int getSpotShadowColor() { + return nGetSpotShadowColor(mNativeRenderNode); + } + + /** getAmbientShadowColor */ + public int getAmbientShadowColor() { + return nGetAmbientShadowColor(mNativeRenderNode); } /** @@ -915,7 +930,13 @@ public class RenderNode { @CriticalNative private static native boolean nHasShadow(long renderNode); @CriticalNative - private static native boolean nSetShadowColor(long renderNode, int color); + private static native boolean nSetSpotShadowColor(long renderNode, int color); + @CriticalNative + private static native boolean nSetAmbientShadowColor(long renderNode, int color); + @CriticalNative + private static native int nGetSpotShadowColor(long renderNode); + @CriticalNative + private static native int nGetAmbientShadowColor(long renderNode); @CriticalNative private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); @CriticalNative diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a2ecfc469182..c63cb404189c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -724,6 +724,8 @@ import java.util.function.Predicate; * @attr ref android.R.styleable#View_nextFocusRight * @attr ref android.R.styleable#View_nextFocusUp * @attr ref android.R.styleable#View_onClick + * @attr ref android.R.styleable#View_outlineSpotShadowColor + * @attr ref android.R.styleable#View_outlineAmbientShadowColor * @attr ref android.R.styleable#View_padding * @attr ref android.R.styleable#View_paddingHorizontal * @attr ref android.R.styleable#View_paddingVertical @@ -5443,6 +5445,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setAccessibilityPaneTitle(a.getString(attr)); } break; + case R.styleable.View_outlineSpotShadowColor: + setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK)); + break; + case R.styleable.View_outlineAmbientShadowColor: + setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK)); + break; } } @@ -15442,14 +15450,61 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * @hide + * Sets the color of the spot shadow that is drawn when the view has a positive Z or + * elevation value. + * <p> + * By default the shadow color is black. Generally, this color will be opaque so the intensity + * of the shadow is consistent between different views with different colors. + * <p> + * The opacity of the final spot shadow is a function of the shadow caster height, the + * alpha channel of the outlineSpotShadowColor (typically opaque), and the + * {@link android.R.attr#spotShadowAlpha} theme attribute. + * + * @attr ref android.R.styleable#View_outlineSpotShadowColor + * @param color The color this View will cast for its elevation spot shadow. */ - public void setShadowColor(@ColorInt int color) { - if (mRenderNode.setShadowColor(color)) { + public void setOutlineSpotShadowColor(@ColorInt int color) { + if (mRenderNode.setSpotShadowColor(color)) { invalidateViewProperty(true, true); } } + /** + * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing + * was set + */ + public @ColorInt int getOutlineSpotShadowColor() { + return mRenderNode.getSpotShadowColor(); + } + + /** + * Sets the color of the ambient shadow that is drawn when the view has a positive Z or + * elevation value. + * <p> + * By default the shadow color is black. Generally, this color will be opaque so the intensity + * of the shadow is consistent between different views with different colors. + * <p> + * The opacity of the final ambient shadow is a function of the shadow caster height, the + * alpha channel of the outlineAmbientShadowColor (typically opaque), and the + * {@link android.R.attr#ambientShadowAlpha} theme attribute. + * + * @attr ref android.R.styleable#View_outlineAmbientShadowColor + * @param color The color this View will cast for its elevation shadow. + */ + public void setOutlineAmbientShadowColor(@ColorInt int color) { + if (mRenderNode.setAmbientShadowColor(color)) { + invalidateViewProperty(true, true); + } + } + + /** + * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if + * nothing was set + */ + public @ColorInt int getOutlineAmbientShadowColor() { + return mRenderNode.getAmbientShadowColor(); + } + /** @hide */ public void setRevealClip(boolean shouldClip, float x, float y, float radius) { @@ -26898,6 +26953,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); + stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor()); + stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor()); // focus stream.addProperty("focus:hasFocus", hasFocus()); diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 37ff8c8cefd2..8770d788fc37 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -174,8 +174,25 @@ static jboolean android_view_RenderNode_hasShadow(jlong renderNodePtr) { return renderNode->stagingProperties().hasShadow(); } -static jboolean android_view_RenderNode_setShadowColor(jlong renderNodePtr, jint shadowColor) { - return SET_AND_DIRTY(setShadowColor, static_cast<SkColor>(shadowColor), RenderNode::GENERIC); +static jboolean android_view_RenderNode_setSpotShadowColor(jlong renderNodePtr, jint shadowColor) { + return SET_AND_DIRTY(setSpotShadowColor, + static_cast<SkColor>(shadowColor), RenderNode::GENERIC); +} + +static jint android_view_RenderNode_getSpotShadowColor(jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + return renderNode->stagingProperties().getSpotShadowColor(); +} + +static jboolean android_view_RenderNode_setAmbientShadowColor(jlong renderNodePtr, + jint shadowColor) { + return SET_AND_DIRTY(setAmbientShadowColor, + static_cast<SkColor>(shadowColor), RenderNode::GENERIC); +} + +static jint android_view_RenderNode_getAmbientShadowColor(jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + return renderNode->stagingProperties().getAmbientShadowColor(); } static jboolean android_view_RenderNode_setClipToOutline(jlong renderNodePtr, @@ -575,7 +592,10 @@ static const JNINativeMethod gMethods[] = { { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow }, - { "nSetShadowColor", "(JI)Z", (void*) android_view_RenderNode_setShadowColor }, + { "nSetSpotShadowColor", "(JI)Z", (void*) android_view_RenderNode_setSpotShadowColor }, + { "nGetSpotShadowColor", "(J)I", (void*) android_view_RenderNode_getSpotShadowColor }, + { "nSetAmbientShadowColor","(JI)Z", (void*) android_view_RenderNode_setAmbientShadowColor }, + { "nGetAmbientShadowColor","(J)I", (void*) android_view_RenderNode_getAmbientShadowColor }, { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, { "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip }, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 354d65811164..ef339a6517a8 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3036,6 +3036,28 @@ <!-- The title this view should present to accessibility as a pane title. See {@link android.view.View#setAccessibilityPaneTitle(CharSequence)} --> <attr name="accessibilityPaneTitle" format="string" /> + + <!-- Sets the color of the spot shadow that is drawn when the view has a positive Z or + elevation value. + <p> + By default the shadow color is black. Generally, this color will be opaque so the + intensity of the shadow is consistent between different views with different colors. + <p> + The opacity of the final spot shadow is a function of the shadow caster height, the + alpha channel of the outlineSpotShadowColor (typically opaque), and the + {@link android.R.attr#spotShadowAlpha} theme attribute. --> + <attr name="outlineSpotShadowColor" format="color" /> + + <!-- Sets the color of the ambient shadow that is drawn when the view has a positive Z + or elevation value. + <p> + By default the shadow color is black. Generally, this color will be opaque so the + intensity of the shadow is consistent between different views with different colors. + <p> + The opacity of the final ambient shadow is a function of the shadow caster height, + the alpha channel of the outlineAmbientShadowColor (typically opaque), and the + {@link android.R.attr#ambientShadowAlpha} theme attribute. --> + <attr name="outlineAmbientShadowColor" format="color" /> </declare-styleable> <!-- Attributes that can be assigned to a tag for a particular View. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 9cdf5531225b..bb7e04094529 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2866,6 +2866,8 @@ <public name="lastBaselineToBottomHeight" /> <public name="lineHeight" /> <public name="accessibilityHeading" /> + <public name="outlineSpotShadowColor" /> + <public name="outlineAmbientShadowColor" /> </public-group> <public-group type="style" first-id="0x010302e0"> diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 3d2c2520624b..55f4d895265c 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -507,12 +507,20 @@ public: getOutline().getAlpha() != 0.0f; } - SkColor getShadowColor() const { - return mPrimitiveFields.mShadowColor; + SkColor getSpotShadowColor() const { + return mPrimitiveFields.mSpotShadowColor; } - bool setShadowColor(SkColor shadowColor) { - return RP_SET(mPrimitiveFields.mShadowColor, shadowColor); + bool setSpotShadowColor(SkColor shadowColor) { + return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor); + } + + SkColor getAmbientShadowColor() const { + return mPrimitiveFields.mAmbientShadowColor; + } + + bool setAmbientShadowColor(SkColor shadowColor) { + return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor); } bool fitsOnLayer() const { @@ -538,7 +546,8 @@ private: int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0; int mWidth = 0, mHeight = 0; int mClippingFlags = CLIP_TO_BOUNDS; - SkColor mShadowColor = SK_ColorBLACK; + SkColor mSpotShadowColor = SK_ColorBLACK; + SkColor mAmbientShadowColor = SK_ColorBLACK; float mAlpha = 1; float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0; float mElevation = 0; diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp index 7b59ccf3eec7..25c51f2716e6 100644 --- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp @@ -111,6 +111,10 @@ void EndReorderBarrierDrawable::onDraw(SkCanvas* canvas) { } } +static SkColor multiplyAlpha(SkColor color, float alpha) { + return SkColorSetA(color, alpha * SkColorGetA(color)); +} + // copied from FrameBuilder::deferShadow void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) { const RenderProperties& casterProperties = caster->getNodeProperties(); @@ -187,9 +191,11 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* } else { zParams = SkPoint3::Make(0, 0, casterProperties.getZ()); } + SkColor ambientColor = multiplyAlpha(casterProperties.getAmbientShadowColor(), ambientAlpha); + SkColor spotColor = multiplyAlpha(casterProperties.getSpotShadowColor(), spotAlpha); SkShadowUtils::DrawShadow( canvas, *casterPath, zParams, skiaLightPos, SkiaPipeline::getLightRadius(), - ambientAlpha, spotAlpha, casterProperties.getShadowColor(), + ambientColor, spotColor, casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0); } diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index ebf5f6854c6f..c8f96c9f0670 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -285,7 +285,8 @@ <activity android:name="ColoredShadowsActivity" - android:label="View/ColoredShadows"> + android:label="View/ColoredShadows" + android:theme="@style/ThemeColoredShadows"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="com.android.test.hwui.TEST" /> diff --git a/tests/HwAccelerationTest/res/values/styles.xml b/tests/HwAccelerationTest/res/values/styles.xml index 108709bd76b2..fa5437f38ace 100644 --- a/tests/HwAccelerationTest/res/values/styles.xml +++ b/tests/HwAccelerationTest/res/values/styles.xml @@ -34,4 +34,11 @@ <item name="android:translationZ">400dp</item> <item name="android:layout_alignParentBottom">true</item> </style> + + <style name="ThemeColoredShadows" parent="@android:style/Theme.Material.Light"> + <!-- + <item name="android:ambientShadowAlpha">0</item> + <item name="android:spotShadowAlpha">1</item> + --> + </style> </resources> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java index 135c93c97af2..901d90eed70a 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredShadowsActivity.java @@ -17,6 +17,9 @@ package com.android.test.hwui; import android.app.Activity; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; @@ -36,7 +39,9 @@ public class ColoredShadowsActivity extends Activity { private void setShadowColors(ViewGroup row, int rowIndex) { for (int i = 0; i < row.getChildCount(); i++) { View view = row.getChildAt(i); - view.setShadowColor(shadowColorFor(view)); + //view.setBackground(new MyHackyBackground()); + view.setOutlineSpotShadowColor(shadowColorFor(view)); + view.setOutlineAmbientShadowColor(shadowColorFor(view)); view.setElevation(6.0f * (rowIndex + 1)); } } @@ -44,12 +49,27 @@ public class ColoredShadowsActivity extends Activity { private int shadowColorFor(View view) { switch (view.getId()) { case R.id.grey: return 0xFF3C4043; - case R.id.blue: return 0xFF185ABC; - case R.id.red: return 0xFFB31412; - case R.id.yellow: return 0xFFEA8600; - case R.id.green: return 0xFF137333; + case R.id.blue: return Color.BLUE; + case R.id.red: return 0xFFEA4335; + case R.id.yellow: return 0xFFFBBC04; + case R.id.green: return 0xFF34A853; default: return 0xFF000000; } } + private static class MyHackyBackground extends ColorDrawable { + MyHackyBackground() { + super(0); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public int getAlpha() { + return 254; + } + } } |