diff options
author | Nader Jawad <njawad@google.com> | 2021-03-17 15:12:58 -0700 |
---|---|---|
committer | Nader Jawad <njawad@google.com> | 2021-03-18 22:41:42 -0700 |
commit | a225d21f7d586d1484af38a55f8d949d076a4d5c (patch) | |
tree | f5dc60ec0ec35c4d8adb69a3a476020d2874ced6 | |
parent | 78af4257ecebcf73c113ef927942a062aefef3e6 (diff) |
Updated EdgeEffect parameters for overscroll stretch
Added dampening logic to caluclate the distance to
overscroll.
Updated StretchEffect to support independent
maximum stretch amounts for the x/y axis
Removed debugging parameters to configure
stretch distance since they are no longer
used. Removed hidden API calls to configure
stretch distance in ScrollView/HorizontalScrollView
Bug: 179047472
Test: re-ran EdgeEffectTests
Change-Id: I4698669273d364695a21c2cce00ec2cfec41b2cc
11 files changed, 67 insertions, 107 deletions
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java index 3c411126627f..5f55887d6019 100644 --- a/core/java/android/widget/EdgeEffect.java +++ b/core/java/android/widget/EdgeEffect.java @@ -130,7 +130,11 @@ public class EdgeEffect { public @interface EdgeEffectType { } - private static final float DEFAULT_MAX_STRETCH_INTENSITY = 0.08f; + private static final float LINEAR_STRETCH_INTENSITY = 0.03f; + + private static final float EXP_STRETCH_INTENSITY = 0.02f; + + private static final float SCROLL_DIST_AFFECTED_BY_EXP_STRETCH = 0.4f; @SuppressWarnings("UnusedDeclaration") private static final String TAG = "EdgeEffect"; @@ -176,9 +180,6 @@ public class EdgeEffect { private long mStartTime; private float mDuration; - private float mStretchIntensity = DEFAULT_MAX_STRETCH_INTENSITY; - private float mStretchDistanceFraction = 1f; - private float mStretchDistance = -1f; private final Interpolator mInterpolator = new DecelerateInterpolator(); @@ -269,16 +270,6 @@ public class EdgeEffect { } /** - * Configure the distance in pixels to stretch the content. This is only consumed as part - * if {@link #setType(int)} is set to {@link #TYPE_STRETCH} - * @param stretchDistance Stretch distance in pixels when the target View is overscrolled - * @hide - */ - public void setStretchDistance(float stretchDistance) { - mStretchDistance = stretchDistance; - } - - /** * Reports if this EdgeEffect's animation is finished. If this method returns false * after a call to {@link #draw(Canvas)} the host widget should schedule another * drawing pass to continue the animation. @@ -520,13 +511,6 @@ public class EdgeEffect { } /** - * @hide - */ - public void setMaxStretchIntensity(float stretchIntensity) { - mStretchIntensity = stretchIntensity; - } - - /** * Set or clear the blend mode. A blend mode defines how source pixels * (generated by a drawing command) are composited with the destination pixels * (content of the render target). @@ -642,22 +626,19 @@ public class EdgeEffect { // assume rotations of increments of 90 degrees float x = mTmpPoints[10] - mTmpPoints[8]; float width = right - left; - float vecX = Math.max(-1f, Math.min(1f, x / width)); + float vecX = dampStretchVector(Math.max(-1f, Math.min(1f, x / width))); float y = mTmpPoints[11] - mTmpPoints[9]; float height = bottom - top; - float vecY = Math.max(-1f, Math.min(1f, y / height)); + float vecY = dampStretchVector(Math.max(-1f, Math.min(1f, y / height))); renderNode.stretch( left, top, right, bottom, - vecX * mStretchIntensity, - vecY * mStretchIntensity, - // TODO (njawad/mount) figure out proper stretch distance from UX - // for now leverage placeholder logic if no stretch distance is provided to - // consume the displacement ratio times the minimum of the width or height - mStretchDistance > 0 ? mStretchDistance : - (mStretchDistanceFraction * Math.max(mWidth, mHeight)) + vecX, + vecY, + mWidth, + mHeight ); } @@ -794,4 +775,13 @@ public class EdgeEffect { return Math.abs(mVelocity) < VELOCITY_THRESHOLD && Math.abs(displacement) < VALUE_THRESHOLD; } + + private float dampStretchVector(float normalizedVec) { + float sign = normalizedVec > 0 ? 1f : -1f; + float overscroll = Math.abs(normalizedVec); + float linearIntensity = LINEAR_STRETCH_INTENSITY * overscroll; + double scalar = Math.E / SCROLL_DIST_AFFECTED_BY_EXP_STRETCH; + double expIntensity = EXP_STRETCH_INTENSITY * (1 - Math.exp(-overscroll * scalar)); + return sign * (float) (linearIntensity + expIntensity); + } } diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index bf552e2a501c..23915e06335a 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -249,26 +249,6 @@ public class HorizontalScrollView extends FrameLayout { } /** - * API used for prototyping stretch effect parameters in framework sample apps - * @hide - */ - public void setEdgeEffectIntensity(float intensity) { - mEdgeGlowLeft.setMaxStretchIntensity(intensity); - mEdgeGlowRight.setMaxStretchIntensity(intensity); - invalidate(); - } - - /** - * API used for prototyping stretch effect parameters in the framework sample apps - * @hide - */ - public void setStretchDistance(float distance) { - mEdgeGlowLeft.setStretchDistance(distance); - mEdgeGlowRight.setStretchDistance(distance); - invalidate(); - } - - /** * Sets the right edge effect color. * * @param color The color for the right edge effect. diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 30067296f967..65f3da79afe0 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -281,26 +281,6 @@ public class ScrollView extends FrameLayout { } /** - * API used for prototyping stretch effect parameters in framework sample apps - * @hide - */ - public void setEdgeEffectIntensity(float intensity) { - mEdgeGlowTop.setMaxStretchIntensity(intensity); - mEdgeGlowBottom.setMaxStretchIntensity(intensity); - invalidate(); - } - - /** - * API used for prototyping stretch effect parameters in the framework sample apps - * @hide - */ - public void setStretchDistance(float distance) { - mEdgeGlowTop.setStretchDistance(distance); - mEdgeGlowBottom.setStretchDistance(distance); - invalidate(); - } - - /** * Sets the bottom edge effect color. * * @param color The color for the bottom edge effect. diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index da5162b9e15e..6fcd8d09a770 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -275,6 +275,8 @@ public final class RenderNode { * Call to apply a stretch effect to any child SurfaceControl layers * * TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls? + * (njawad) update to consume different stretch parameters for horizontal/vertical stretch + * to ensure SkiaGLRenderEngine can also apply the same stretch to a surface * * @hide */ @@ -718,7 +720,7 @@ public final class RenderNode { /** @hide */ public boolean stretch(float left, float top, float right, float bottom, - float vecX, float vecY, float maxStretchAmount) { + float vecX, float vecY, float maxStretchAmountX, float maxStretchAmountY) { if (Float.isInfinite(vecX) || Float.isNaN(vecX)) { throw new IllegalArgumentException("vecX must be a finite, non-NaN value " + vecX); } @@ -730,9 +732,13 @@ public final class RenderNode { "Stretch region must not be empty, got " + new RectF(left, top, right, bottom).toString()); } - if (maxStretchAmount <= 0.0f) { + if (maxStretchAmountX <= 0.0f) { throw new IllegalArgumentException( - "The max stretch amount must be >0, got " + maxStretchAmount); + "The max horizontal stretch amount must be >0, got " + maxStretchAmountX); + } + if (maxStretchAmountY <= 0.0f) { + throw new IllegalArgumentException( + "The max vertical stretch amount must be >0, got " + maxStretchAmountY); } return nStretch( mNativeRenderNode, @@ -742,7 +748,8 @@ public final class RenderNode { bottom, vecX, vecY, - maxStretchAmount + maxStretchAmountX, + maxStretchAmountY ); } @@ -1695,7 +1702,7 @@ public final class RenderNode { @CriticalNative private static native boolean nStretch(long renderNode, float left, float top, float right, - float bottom, float vecX, float vecY, float maxStretch); + float bottom, float vecX, float vecY, float maxStretchX, float maxStretchY); @CriticalNative private static native boolean nHasShadow(long renderNode); diff --git a/libs/hwui/effects/StretchEffect.cpp b/libs/hwui/effects/StretchEffect.cpp index d4fd1053b17f..9e4fb8fc9b35 100644 --- a/libs/hwui/effects/StretchEffect.cpp +++ b/libs/hwui/effects/StretchEffect.cpp @@ -33,7 +33,8 @@ static const SkString stretchShader = SkString(R"( uniform float uMaxStretchIntensity; // Maximum percentage to stretch beyond bounds of target - uniform float uStretchAffectedDist; + uniform float uStretchAffectedDistX; + uniform float uStretchAffectedDistY; // Distance stretched as a function of the normalized overscroll times // scale intensity @@ -138,7 +139,7 @@ static const SkString stretchShader = SkString(R"( outU, inU, uOverscrollX, - uStretchAffectedDist, + uStretchAffectedDistX, uDistanceStretchedX, uDistDiffX ); @@ -146,7 +147,7 @@ static const SkString stretchShader = SkString(R"( outV, inV, uOverscrollY, - uStretchAffectedDist, + uStretchAffectedDistY, uDistanceStretchedY, uDistDiffY ); @@ -166,16 +167,14 @@ sk_sp<SkImageFilter> StretchEffect::getImageFilter(const sk_sp<SkImage>& snapsho return mStretchFilter; } - float distanceNotStretchedX = maxStretchAmount / stretchArea.width(); - float distanceNotStretchedY = maxStretchAmount / stretchArea.height(); - float normOverScrollDistX = mStretchDirection.x(); - float normOverScrollDistY = mStretchDirection.y(); - float distanceStretchedX = maxStretchAmount / (1 + abs(normOverScrollDistX)); - float distanceStretchedY = maxStretchAmount / (1 + abs(normOverScrollDistY)); - float diffX = distanceStretchedX - distanceNotStretchedX; - float diffY = distanceStretchedY - distanceNotStretchedY; float viewportWidth = stretchArea.width(); float viewportHeight = stretchArea.height(); + float normOverScrollDistX = mStretchDirection.x(); + float normOverScrollDistY = mStretchDirection.y(); + float distanceStretchedX = maxStretchAmountX / (1 + abs(normOverScrollDistX)); + float distanceStretchedY = maxStretchAmountY / (1 + abs(normOverScrollDistY)); + float diffX = distanceStretchedX; + float diffY = distanceStretchedY; if (mBuilder == nullptr) { mBuilder = std::make_unique<SkRuntimeShaderBuilder>(getStretchEffect()); @@ -183,7 +182,8 @@ sk_sp<SkImageFilter> StretchEffect::getImageFilter(const sk_sp<SkImage>& snapsho mBuilder->child("uContentTexture") = snapshotImage->makeShader( SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear)); - mBuilder->uniform("uStretchAffectedDist").set(&maxStretchAmount, 1); + mBuilder->uniform("uStretchAffectedDistX").set(&maxStretchAmountX, 1); + mBuilder->uniform("uStretchAffectedDistY").set(&maxStretchAmountY, 1); mBuilder->uniform("uDistanceStretchedX").set(&distanceStretchedX, 1); mBuilder->uniform("uDistanceStretchedY").set(&distanceStretchedY, 1); mBuilder->uniform("uDistDiffX").set(&diffX, 1); diff --git a/libs/hwui/effects/StretchEffect.h b/libs/hwui/effects/StretchEffect.h index d2da06b31f68..8221b41ff4e5 100644 --- a/libs/hwui/effects/StretchEffect.h +++ b/libs/hwui/effects/StretchEffect.h @@ -33,8 +33,12 @@ public: SmoothStep, }; - StretchEffect(const SkRect& area, const SkVector& direction, float maxStretchAmount) - : stretchArea(area), maxStretchAmount(maxStretchAmount), mStretchDirection(direction) {} + StretchEffect(const SkRect& area, const SkVector& direction, float maxStretchAmountX, + float maxStretchAmountY) + : stretchArea(area) + , maxStretchAmountX(maxStretchAmountX) + , maxStretchAmountY(maxStretchAmountY) + , mStretchDirection(direction) {} StretchEffect() {} @@ -50,7 +54,8 @@ public: this->stretchArea = other.stretchArea; this->mStretchDirection = other.mStretchDirection; this->mStretchFilter = nullptr; - this->maxStretchAmount = other.maxStretchAmount; + this->maxStretchAmountX = other.maxStretchAmountX; + this->maxStretchAmountY = other.maxStretchAmountY; return *this; } @@ -67,13 +72,15 @@ public: return setEmpty(); } stretchArea.join(other.stretchArea); - maxStretchAmount = std::max(maxStretchAmount, other.maxStretchAmount); + maxStretchAmountX = std::max(maxStretchAmountX, other.maxStretchAmountX); + maxStretchAmountY = std::max(maxStretchAmountY, other.maxStretchAmountY); } sk_sp<SkImageFilter> getImageFilter(const sk_sp<SkImage>& snapshotImage) const; SkRect stretchArea {0, 0, 0, 0}; - float maxStretchAmount = 0; + float maxStretchAmountX = 0; + float maxStretchAmountY = 0; void setStretchDirection(const SkVector& direction) { mStretchFilter = nullptr; diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index fc7d0d181949..fffa80614370 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -181,9 +181,10 @@ static jboolean android_view_RenderNode_clearStretch(CRITICAL_JNI_PARAMS_COMMA j static jboolean android_view_RenderNode_stretch(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr, jfloat left, jfloat top, jfloat right, - jfloat bottom, jfloat vX, jfloat vY, jfloat max) { - StretchEffect effect = - StretchEffect(SkRect::MakeLTRB(left, top, right, bottom), {.fX = vX, .fY = vY}, max); + jfloat bottom, jfloat vX, jfloat vY, jfloat maxX, + jfloat maxY) { + StretchEffect effect = StretchEffect(SkRect::MakeLTRB(left, top, right, bottom), + {.fX = vX, .fY = vY}, maxX, maxY); RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); renderNode->mutateStagingProperties().mutateLayerProperties().mutableStretchEffect().mergeWith( effect); @@ -662,7 +663,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, env->CallVoidMethod(localref, gPositionListener_ApplyStretchMethod, info.canvasContext.getFrameNumber(), area.left, area.top, area.right, area.bottom, stretchDirection.fX, stretchDirection.fY, - effect->maxStretchAmount); + effect->maxStretchAmountX, effect->maxStretchAmountY); #endif env->DeleteLocalRef(localref); } @@ -738,7 +739,7 @@ static const JNINativeMethod gMethods[] = { {"nSetOutlineEmpty", "(J)Z", (void*)android_view_RenderNode_setOutlineEmpty}, {"nSetOutlineNone", "(J)Z", (void*)android_view_RenderNode_setOutlineNone}, {"nClearStretch", "(J)Z", (void*)android_view_RenderNode_clearStretch}, - {"nStretch", "(JFFFFFFF)Z", (void*)android_view_RenderNode_stretch}, + {"nStretch", "(JFFFFFFFF)Z", (void*)android_view_RenderNode_stretch}, {"nHasShadow", "(J)Z", (void*)android_view_RenderNode_hasShadow}, {"nSetSpotShadowColor", "(JI)Z", (void*)android_view_RenderNode_setSpotShadowColor}, {"nGetSpotShadowColor", "(J)I", (void*)android_view_RenderNode_getSpotShadowColor}, diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java index f0e6299f09e9..c4b0072eaff8 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/EdgeEffectStretchActivity.java @@ -18,8 +18,6 @@ package com.android.test.hwui; import android.app.Activity; import android.os.Bundle; -import android.widget.HorizontalScrollView; -import android.widget.ScrollView; public class EdgeEffectStretchActivity extends Activity { @@ -27,10 +25,5 @@ public class EdgeEffectStretchActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.stretch_layout); - HorizontalScrollView hsv = findViewById(R.id.horizontal_scroll_view); - hsv.setStretchDistance(50f); - - ScrollView sv = findViewById(R.id.scroll_view); - sv.setStretchDistance(50f); } } diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java index 65d7363ad628..6b6287da2711 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java @@ -75,11 +75,11 @@ public class PositionListenerActivity extends Activity { // Although we could do this in a single call, the real one won't be - so mimic that if (dir.x != 0f) { node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(), - dir.x, 0f, maxStretchAmount); + dir.x, 0f, maxStretchAmount, maxStretchAmount); } if (dir.y != 0f) { node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(), - 0f, dir.y, maxStretchAmount); + 0f, dir.y, maxStretchAmount, maxStretchAmount); } } }; diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java index 9bd933afa07d..912aee686924 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java @@ -415,6 +415,7 @@ public class StretchShaderActivity extends Activity { bounds.height(), mOverScrollX, mOverScrollY, + mStretchDistance, mStretchDistance ); } diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java index d6042445c2d8..67b9be580ba6 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java @@ -99,7 +99,8 @@ public class StretchySurfaceViewActivity extends Activity implements Callback { super.onDraw(canvas); RenderNode node = ((RecordingCanvas) canvas).mNode; - node.stretch(0f, 0f, getWidth(), getHeight() / 2f, 0f, 1f, 400f); + node.stretch(0f, 0f, getWidth(), getHeight() / 2f, 0f, + 1f, 400f, 400f); } }; |