From da94513967737d605b58bffbaccbe90b1f152e1c Mon Sep 17 00:00:00 2001 From: Tyler Freeman Date: Thu, 13 Apr 2023 23:57:08 +0000 Subject: [PATCH] feat(non linear font scaling): add FontScaleConverterFactory.isNonLinearFontScalingActive() This helps us determine if we can skip certain calculations as a performance optimization, for instance when calculating line height proportionally. Bug: 273326061 Test: atest frameworks/base/core/java/android/content/res/FontScaleConverterFactory.java Change-Id: I364a978b457c9b7a7073b34fa8cc1f3abaeabbac --- .../res/FontScaleConverterFactory.java | 26 ++++++++++++++++--- .../res/FontScaleConverterFactoryTest.kt | 16 ++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java index 6b09c303e3cd7..5eb65262918d6 100644 --- a/core/java/android/content/res/FontScaleConverterFactory.java +++ b/core/java/android/content/res/FontScaleConverterFactory.java @@ -34,6 +34,8 @@ public class FontScaleConverterFactory { @VisibleForTesting static final SparseArray LOOKUP_TABLES = new SparseArray<>(); + private static float sMinScaleBeforeCurvesApplied = 1.05f; + static { // These were generated by frameworks/base/tools/fonts/font-scaling-array-generator.js and // manually tweaked for optimum readability. @@ -82,10 +84,29 @@ public class FontScaleConverterFactory { new float[] { 16f, 20f, 24f, 26f, 30f, 34f, 36f, 38f, 100}) ); + sMinScaleBeforeCurvesApplied = getScaleFromKey(LOOKUP_TABLES.keyAt(0)) - 0.02f; + if (sMinScaleBeforeCurvesApplied <= 1.0f) { + throw new IllegalStateException( + "You should only apply non-linear scaling to font scales > 1" + ); + } } private FontScaleConverterFactory() {} + /** + * Returns true if non-linear font scaling curves would be in effect for the given scale, false + * if the scaling would follow a linear curve or for no scaling. + * + *

Example usage: + * isNonLinearFontScalingActive(getResources().getConfiguration().fontScale) + * + * @hide + */ + public static boolean isNonLinearFontScalingActive(float fontScale) { + return fontScale >= sMinScaleBeforeCurvesApplied; + } + /** * Finds a matching FontScaleConverter for the given fontScale factor. * @@ -97,10 +118,7 @@ public class FontScaleConverterFactory { */ @Nullable public static FontScaleConverter forScale(float fontScale) { - if (fontScale <= 1) { - // We don't need non-linear curves for shrinking text or for 100%. - // Also, fontScale==0 should not have a curve either. - // And ignore negative font scales; that's just silly. + if (!isNonLinearFontScalingActive(fontScale)) { return null; } diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt index a0d8dcf830e87..ba6c8fab48d4d 100644 --- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt +++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt @@ -122,6 +122,22 @@ class FontScaleConverterFactoryTest { } } + @SmallTest + fun testIsNonLinearFontScalingActive() { + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1f)).isFalse() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(0f)).isFalse() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(-1f)).isFalse() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(0.85f)).isFalse() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.02f)).isFalse() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.10f)).isFalse() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.15f)).isTrue() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.1499999f)) + .isTrue() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(1.5f)).isTrue() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(2f)).isTrue() + assertThat(FontScaleConverterFactory.isNonLinearFontScalingActive(3f)).isTrue() + } + @LargeTest @Test fun allFeasibleScalesAndConversionsDoNotCrash() {