Add API to set tonal shadow color

Bug: 68211332
Test: HwAccelerationTests's coloredshadow demo & CTS test in topic
Change-Id: I09f5d1067b3200564a9d47219f70985edf3a2527
This commit is contained in:
John Reck
2017-11-17 15:06:24 -08:00
parent e53c1a1b6b
commit d8be4a0abe
11 changed files with 193 additions and 22 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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());

View File

@@ -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 },

View File

@@ -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. -->

View File

@@ -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">

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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;
}
}
}