diff options
Diffstat (limited to 'graphics/java')
-rw-r--r-- | graphics/java/Android.bp | 17 | ||||
-rw-r--r-- | graphics/java/android/graphics/FontListParser.java | 62 | ||||
-rw-r--r-- | graphics/java/android/graphics/RecordingCanvas.java | 11 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/RippleAnimationSession.java | 37 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/RippleDrawable.java | 9 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/RippleShader.java | 102 |
6 files changed, 139 insertions, 99 deletions
diff --git a/graphics/java/Android.bp b/graphics/java/Android.bp new file mode 100644 index 000000000000..63d1f6d6f2d6 --- /dev/null +++ b/graphics/java/Android.bp @@ -0,0 +1,17 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +filegroup { + name: "framework-graphics-nonupdatable-sources", + srcs: [ + "**/*.java", + "**/*.aidl", + ], + visibility: ["//frameworks/base"], +} diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 95c7715a1688..6fdf5526edf5 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -25,8 +25,6 @@ import android.graphics.fonts.FontVariationAxis; import android.os.Build; import android.os.LocaleList; import android.text.FontConfig; -import android.text.TextUtils; -import android.util.TypedXmlSerializer; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; @@ -194,32 +192,6 @@ public class FontListParser { return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant); } - /** - * Write a family tag representing {@code fontFamily}. The tag should be started by the caller. - */ - public static void writeFamily(TypedXmlSerializer out, FontConfig.FontFamily fontFamily) - throws IOException { - if (!TextUtils.isEmpty(fontFamily.getName())) { - out.attribute(null, ATTR_NAME, fontFamily.getName()); - } - if (!fontFamily.getLocaleList().isEmpty()) { - out.attribute(null, ATTR_LANG, fontFamily.getLocaleList().toLanguageTags()); - } - switch (fontFamily.getVariant()) { - case FontConfig.FontFamily.VARIANT_COMPACT: - out.attribute(null, ATTR_VARIANT, VARIANT_COMPACT); - break; - case FontConfig.FontFamily.VARIANT_ELEGANT: - out.attribute(null, ATTR_VARIANT, VARIANT_ELEGANT); - break; - } - for (FontConfig.Font font : fontFamily.getFontList()) { - out.startTag(null, TAG_FONT); - writeFont(out, font); - out.endTag(null, TAG_FONT); - } - } - /** Matches leading and trailing XML whitespace. */ private static final Pattern FILENAME_WHITESPACE_PATTERN = Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$"); @@ -292,34 +264,6 @@ public class FontListParser { return null; } - private static void writeFont(TypedXmlSerializer out, FontConfig.Font font) - throws IOException { - if (font.getTtcIndex() != 0) { - out.attributeInt(null, ATTR_INDEX, font.getTtcIndex()); - } - if (font.getStyle().getWeight() != FontStyle.FONT_WEIGHT_NORMAL) { - out.attributeInt(null, ATTR_WEIGHT, font.getStyle().getWeight()); - } - if (font.getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC) { - out.attribute(null, ATTR_STYLE, STYLE_ITALIC); - } else { - out.attribute(null, ATTR_STYLE, STYLE_NORMAL); - } - if (!TextUtils.isEmpty(font.getFontFamilyName())) { - out.attribute(null, ATTR_FALLBACK_FOR, font.getFontFamilyName()); - } - out.text(font.getFile().getName()); - FontVariationAxis[] axes = - FontVariationAxis.fromFontVariationSettings(font.getFontVariationSettings()); - if (axes != null) { - for (FontVariationAxis axis : axes) { - out.startTag(null, TAG_AXIS); - writeAxis(out, axis); - out.endTag(null, TAG_AXIS); - } - } - } - private static FontVariationAxis readAxis(XmlPullParser parser) throws XmlPullParserException, IOException { String tagStr = parser.getAttributeValue(null, ATTR_TAG); @@ -328,12 +272,6 @@ public class FontListParser { return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr)); } - private static void writeAxis(TypedXmlSerializer out, FontVariationAxis axis) - throws IOException { - out.attribute(null, ATTR_TAG, axis.getTag()); - out.attributeFloat(null, ATTR_STYLEVALUE, axis.getStyleValue()); - } - /** * Reads alias elements */ diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java index 8dd7f317c842..6c03ddc4a12d 100644 --- a/graphics/java/android/graphics/RecordingCanvas.java +++ b/graphics/java/android/graphics/RecordingCanvas.java @@ -17,6 +17,7 @@ package android.graphics; import android.annotation.NonNull; +import android.os.SystemProperties; import android.util.Pools.SynchronizedPool; import dalvik.annotation.optimization.CriticalNative; @@ -36,7 +37,15 @@ public final class RecordingCanvas extends BaseRecordingCanvas { // view hierarchy because display lists are generated recursively. private static final int POOL_LIMIT = 25; - private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB + /** @hide */ + private static int getPanelFrameSize() { + final int DefaultSize = 100 * 1024 * 1024; // 100 MB; + return Math.max(SystemProperties.getInt("ro.hwui.max_texture_allocation_size", DefaultSize), + DefaultSize); + } + + /** @hide */ + public static final int MAX_BITMAP_SIZE = getPanelFrameSize(); private static final SynchronizedPool<RecordingCanvas> sPool = new SynchronizedPool<>(POOL_LIMIT); diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java index 94d5c2265372..9ee1ef1cadd3 100644 --- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java +++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java @@ -41,31 +41,20 @@ public final class RippleAnimationSession { private static final int ENTER_ANIM_DURATION = 450; private static final int EXIT_ANIM_DURATION = 300; private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - private static final Interpolator FAST_OUT_LINEAR_IN = - new PathInterpolator(0.4f, 0f, 1f, 1f); + private static final Interpolator FAST_OUT_SLOW_IN = + new PathInterpolator(0.4f, 0f, 0.2f, 1f); private Consumer<RippleAnimationSession> mOnSessionEnd; private final AnimationProperties<Float, Paint> mProperties; private AnimationProperties<CanvasProperty<Float>, CanvasProperty<Paint>> mCanvasProperties; private Runnable mOnUpdate; private long mStartTime; private boolean mForceSoftware; - private final ValueAnimator mSparkle = ValueAnimator.ofFloat(0, 1); + private boolean mAnimateSparkle; RippleAnimationSession(@NonNull AnimationProperties<Float, Paint> properties, boolean forceSoftware) { mProperties = properties; mForceSoftware = forceSoftware; - - mSparkle.addUpdateListener(anim -> { - final long now = AnimationUtils.currentAnimationTimeMillis(); - final long elapsed = now - mStartTime - ENTER_ANIM_DURATION; - final float phase = (float) elapsed / 800; - mProperties.getShader().setNoisePhase(phase); - notifyUpdate(); - }); - mSparkle.setDuration(ENTER_ANIM_DURATION); - mSparkle.setInterpolator(LINEAR_INTERPOLATOR); - mSparkle.setRepeatCount(ValueAnimator.INFINITE); } @NonNull RippleAnimationSession enter(Canvas canvas) { @@ -99,6 +88,16 @@ public final class RippleAnimationSession { return this; } + public boolean shouldAnimateSparkle() { + return mAnimateSparkle; + } + + public float getSparklePhase() { + final long now = AnimationUtils.currentAnimationTimeMillis(); + final long elapsed = now - mStartTime; + return (float) elapsed / 800; + } + private boolean isHwAccelerated(Canvas canvas) { return canvas.isHardwareAccelerated() && !mForceSoftware; } @@ -115,7 +114,7 @@ public final class RippleAnimationSession { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - mSparkle.end(); + mAnimateSparkle = false; Consumer<RippleAnimationSession> onEnd = mOnSessionEnd; if (onEnd != null) onEnd.accept(RippleAnimationSession.this); } @@ -149,7 +148,7 @@ public final class RippleAnimationSession { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - mSparkle.end(); + mAnimateSparkle = false; Consumer<RippleAnimationSession> onEnd = mOnSessionEnd; if (onEnd != null) onEnd.accept(RippleAnimationSession.this); } @@ -174,11 +173,9 @@ public final class RippleAnimationSession { private void startAnimation(Animator expand) { expand.setDuration(ENTER_ANIM_DURATION); expand.addListener(new AnimatorListener(this)); - expand.setInterpolator(FAST_OUT_LINEAR_IN); + expand.setInterpolator(FAST_OUT_SLOW_IN); expand.start(); - if (!mSparkle.isRunning()) { - mSparkle.start(); - } + mAnimateSparkle = true; } private void enterSoftware() { diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index f28b66d12688..8b8cbbc8a9a6 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -859,6 +859,15 @@ public class RippleDrawable extends LayerDrawable { } for (int i = 0; i < mRunningAnimations.size(); i++) { RippleAnimationSession s = mRunningAnimations.get(i); + if (s.shouldAnimateSparkle()) { + final float phase = s.getSparklePhase(); + if (useCanvasProps) { + s.getCanvasProperties().getShader().setNoisePhase(phase); + } else { + s.getProperties().getShader().setNoisePhase(phase); + } + invalidateSelf(); + } if (useCanvasProps) { RippleAnimationSession.AnimationProperties<CanvasProperty<Float>, CanvasProperty<Paint>> diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java index 98b9584f7b4a..a9b24470bbb5 100644 --- a/graphics/java/android/graphics/drawable/RippleShader.java +++ b/graphics/java/android/graphics/drawable/RippleShader.java @@ -31,6 +31,13 @@ final class RippleShader extends RuntimeShader { + "uniform vec2 in_noiseScale;\n" + "uniform float in_hasMask;\n" + "uniform float in_noisePhase;\n" + + "uniform float in_turbulencePhase;\n" + + "uniform vec2 in_tCircle1;\n" + + "uniform vec2 in_tCircle2;\n" + + "uniform vec2 in_tCircle3;\n" + + "uniform vec2 in_tRotation1;\n" + + "uniform vec2 in_tRotation2;\n" + + "uniform vec2 in_tRotation3;\n" + "uniform vec4 in_color;\n" + "uniform shader in_shader;\n"; private static final String SHADER_LIB = @@ -41,53 +48,81 @@ final class RippleShader extends RuntimeShader { + " return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;\n" + "}" + "const float PI = 3.1415926535897932384626;\n" + + "const float SPARKLE_OPACITY = 0.75;\n" + "\n" + "float sparkles(vec2 uv, float t) {\n" + " float n = triangleNoise(uv);\n" + " float s = 0.0;\n" + " for (float i = 0; i < 4; i += 1) {\n" + " float l = i * 0.01;\n" - + " float h = l + 0.1;\n" + + " float h = l + 0.2;\n" + " float o = smoothstep(n - l, h, n);\n" + " o *= abs(sin(PI * o * (t + 0.55 * i)));\n" + " s += o;\n" + " }\n" - + " return saturate(s);\n" + + " return saturate(s) * SPARKLE_OPACITY;\n" + "}\n" - + "\n" + "float softCircle(vec2 uv, vec2 xy, float radius, float blur) {\n" + " float blurHalf = blur * 0.5;\n" + " float d = distance(uv, xy);\n" + " return 1. - smoothstep(1. - blurHalf, 1. + blurHalf, d / radius);\n" + "}\n" + "float softRing(vec2 uv, vec2 xy, float radius, float progress, float blur) {\n" - + " float thickness = 0.2 * radius;\n" + + " float thickness = 0.3 * radius;\n" + " float currentRadius = radius * progress;\n" + " float circle_outer = softCircle(uv, xy, currentRadius + thickness, blur);\n" + " float circle_inner = softCircle(uv, xy, currentRadius - thickness, blur);\n" - + " return clamp(circle_outer - circle_inner, 0., 1.);\n" + + " return saturate(circle_outer - circle_inner);\n" + "}\n" + "float subProgress(float start, float end, float progress) {\n" + " float sub = clamp(progress, start, end);\n" + " return (sub - start) / (end - start); \n" + + "}\n" + + "mat2 rotate2d(vec2 rad){\n" + + " return mat2(rad.x, -rad.y, rad.y, rad.x);\n" + + "}\n" + + "float circle_grid(vec2 resolution, vec2 coord, float time, vec2 center,\n" + + " vec2 rotation, float cell_diameter) {\n" + + " coord = rotate2d(rotation) * (center - coord) + center;\n" + + " coord = mod(coord, cell_diameter) / resolution;\n" + + " float normal_radius = cell_diameter / resolution.y * 0.5;\n" + + " float radius = 0.65 * normal_radius;\n" + + " return softCircle(coord, vec2(normal_radius), radius, radius * 50.0);\n" + + "}\n" + + "float turbulence(vec2 uv, float t) {\n" + + " const vec2 scale = vec2(1.5);\n" + + " uv = uv * scale;\n" + + " float g1 = circle_grid(scale, uv, t, in_tCircle1, in_tRotation1, 0.17);\n" + + " float g2 = circle_grid(scale, uv, t, in_tCircle2, in_tRotation2, 0.2);\n" + + " float g3 = circle_grid(scale, uv, t, in_tCircle3, in_tRotation3, 0.275);\n" + + " float v = (g1 * g1 + g2 - g3) * 0.5;\n" + + " return saturate(0.45 + 0.8 * v);\n" + "}\n"; private static final String SHADER_MAIN = "vec4 main(vec2 p) {\n" - + " float fadeIn = subProgress(0., 0.175, in_progress);\n" - + " float fadeOutNoise = subProgress(0.375, 1., in_progress);\n" - + " float fadeOutRipple = subProgress(0.375, 0.75, in_progress);\n" - + " vec2 center = mix(in_touch, in_origin, fadeIn);\n" - + " float ring = softRing(p, center, in_maxRadius, fadeIn, 0.45);\n" - + " float alpha = 1. - fadeOutNoise;\n" + + " float fadeIn = subProgress(0., 0.1, in_progress);\n" + + " float scaleIn = subProgress(0., 0.45, in_progress);\n" + + " float fadeOutNoise = subProgress(0.5, 1., in_progress);\n" + + " float fadeOutRipple = subProgress(0.5, 0.75, in_progress);\n" + + " vec2 center = mix(in_touch, in_origin, scaleIn);\n" + + " float ring = softRing(p, center, in_maxRadius, scaleIn, 0.45);\n" + + " float alpha = min(fadeIn, 1. - fadeOutNoise);\n" + " vec2 uv = p * in_resolutionScale;\n" + " vec2 densityUv = uv - mod(uv, in_noiseScale);\n" - + " float sparkle = sparkles(densityUv, in_noisePhase) * ring * alpha;\n" + + " float turbulence = turbulence(uv, in_turbulencePhase);\n" + + " float sparkle = sparkles(densityUv, in_noisePhase) * ring * alpha " + + "* turbulence;\n" + " float fade = min(fadeIn, 1. - fadeOutRipple);\n" + " vec4 circle = in_color * (softCircle(p, center, in_maxRadius " - + " * fadeIn, 0.2) * fade);\n" + + " * scaleIn, 0.2) * fade);\n" + " float mask = in_hasMask == 1. ? sample(in_shader).a > 0. ? 1. : 0. : 1.;\n" + " return mix(circle, vec4(sparkle), sparkle) * mask;\n" + "}"; private static final String SHADER = SHADER_UNIFORMS + SHADER_LIB + SHADER_MAIN; + private static final double PI_ROTATE_RIGHT = Math.PI * 0.0078125; + private static final double PI_ROTATE_LEFT = Math.PI * -0.0078125; + + private float mNoisePhase; + private float mProgress; RippleShader() { super(SHADER, false); @@ -107,8 +142,10 @@ final class RippleShader extends RuntimeShader { /** * Continuous offset used as noise phase. */ - public void setNoisePhase(float t) { - setUniform("in_noisePhase", t); + public void setNoisePhase(float phase) { + mNoisePhase = phase; + setUniform("in_noisePhase", phase); + updateTurbulence(); } public void setOrigin(float x, float y) { @@ -120,7 +157,40 @@ final class RippleShader extends RuntimeShader { } public void setProgress(float progress) { + mProgress = progress; setUniform("in_progress", progress); + updateTurbulence(); + } + + private void updateTurbulence() { + final float turbulencePhase = (float) ((mProgress + mNoisePhase * 0.333f) * 5f * Math.PI); + setUniform("in_turbulencePhase", turbulencePhase); + + final float scale = 1.5f; + setUniform("in_tCircle1", new float[]{ + (float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.cos(scale * 0.55))), + (float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.sin(scale * 0.55))) + }); + setUniform("in_tCircle2", new float[]{ + (float) (scale * 0.2 + (turbulencePhase * -0.0066 * Math.cos(scale * 0.45))), + (float) (scale * 0.2 + (turbulencePhase * -0.0066 * Math.sin(scale * 0.45))) + }); + setUniform("in_tCircle3", new float[]{ + (float) (scale + (turbulencePhase * -0.0066 * Math.cos(scale * 0.35))), + (float) (scale + (turbulencePhase * -0.0066 * Math.sin(scale * 0.35))) + }); + final double rotation1 = turbulencePhase * PI_ROTATE_RIGHT + 1.7 * Math.PI; + setUniform("in_tRotation1", new float[]{ + (float) Math.cos(rotation1), (float) Math.sin(rotation1) + }); + final double rotation2 = turbulencePhase * PI_ROTATE_LEFT + 2 * Math.PI; + setUniform("in_tRotation2", new float[]{ + (float) Math.cos(rotation2), (float) Math.sin(rotation2) + }); + final double rotation3 = turbulencePhase * PI_ROTATE_RIGHT + 2.75 * Math.PI; + setUniform("in_tRotation3", new float[]{ + (float) Math.cos(rotation3), (float) Math.sin(rotation3) + }); } /** @@ -133,7 +203,7 @@ final class RippleShader extends RuntimeShader { } public void setResolution(float w, float h, int density) { - float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE * 0.5f; + final float densityScale = density * DisplayMetrics.DENSITY_DEFAULT_SCALE * 1.25f; setUniform("in_resolutionScale", new float[] {1f / w, 1f / h}); setUniform("in_noiseScale", new float[] {densityScale / w, densityScale / h}); } |