summaryrefslogtreecommitdiff
path: root/graphics/java
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/java')
-rw-r--r--graphics/java/Android.bp17
-rw-r--r--graphics/java/android/graphics/FontListParser.java62
-rw-r--r--graphics/java/android/graphics/RecordingCanvas.java11
-rw-r--r--graphics/java/android/graphics/drawable/RippleAnimationSession.java37
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java9
-rw-r--r--graphics/java/android/graphics/drawable/RippleShader.java102
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});
}