diff options
-rw-r--r-- | graphics/java/android/graphics/fonts/Font.java | 18 | ||||
-rw-r--r-- | graphics/java/android/graphics/fonts/SystemFonts.java | 52 | ||||
-rw-r--r-- | libs/hwui/jni/fonts/Font.cpp | 20 |
3 files changed, 39 insertions, 51 deletions
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java index 69cd8bdb3e70..cd7936d50dff 100644 --- a/graphics/java/android/graphics/fonts/Font.java +++ b/graphics/java/android/graphics/fonts/Font.java @@ -46,7 +46,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.util.Arrays; +import java.util.Collections; +import java.util.IdentityHashMap; import java.util.Objects; +import java.util.Set; /** * A font class can be used for creating FontFamily. @@ -859,6 +862,18 @@ public final class Font { + "}"; } + /** @hide */ + public static Set<Font> getAvailableFonts() { + // The font uniqueness is already calculated in the native code. So use IdentityHashMap + // for avoiding hash/equals calculation. + IdentityHashMap<Font, Font> map = new IdentityHashMap<>(); + for (long nativePtr : nGetAvailableFontSet()) { + Font font = new Font(nativePtr); + map.put(font, font); + } + return Collections.unmodifiableSet(map.keySet()); + } + @CriticalNative private static native long nGetMinikinFontPtr(long font); @@ -900,4 +915,7 @@ public final class Font { @CriticalNative private static native long nGetAxisInfo(long fontPtr, int i); + + @FastNative + private static native long[] nGetAvailableFontSet(); } diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java index 8d69d447f4e0..6278c0e23f27 100644 --- a/graphics/java/android/graphics/fonts/SystemFonts.java +++ b/graphics/java/android/graphics/fonts/SystemFonts.java @@ -22,7 +22,6 @@ import android.graphics.FontListParser; import android.graphics.Typeface; import android.text.FontConfig; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -39,7 +38,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; /** @@ -61,36 +59,6 @@ public final class SystemFonts { private static @GuardedBy("sLock") Set<Font> sAvailableFonts; /** - * Helper wrapper class for skipping buffer equality check of Font#equals. - * - * Due to historical reasons, the Font#equals checks the byte-by-byte buffer equality which - * requires heavy IO work in getAvailableFonts. Since the fonts came from system are all regular - * file backed font instance and stored in the unique place, just comparing file path should be - * good enough for this case. - */ - private static final class SystemFontHashWrapper { - private final Font mFont; - SystemFontHashWrapper(Font font) { - mFont = font; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - // All system fonts are regular-file backed font instance, so no need to - // compare buffers. - return mFont.paramEquals(((SystemFontHashWrapper) o).mFont); - } - - @Override - public int hashCode() { - return Objects.hash(mFont); - } - } - - /** * Returns all available font files in the system. * * @return a set of system fonts @@ -98,25 +66,7 @@ public final class SystemFonts { public static @NonNull Set<Font> getAvailableFonts() { synchronized (LOCK) { if (sAvailableFonts == null) { - Set<SystemFontHashWrapper> set = new ArraySet<>(); - for (Typeface tf : Typeface.getSystemFontMap().values()) { - List<FontFamily> families = tf.getFallback(); - for (int i = 0; i < families.size(); ++i) { - FontFamily family = families.get(i); - for (int j = 0; j < family.getSize(); ++j) { - set.add(new SystemFontHashWrapper(family.getFont(j))); - } - } - } - - // Unwrapping font instance for Set<Font> interface. The ArraySet#add won't call - // Font#equals function if none of two objects has the same hash, so following - // unwrapping won't cause bad performance due to byte-by-byte equality check. - ArraySet<Font> result = new ArraySet(set.size()); - for (SystemFontHashWrapper wrapper : set) { - result.add(wrapper.mFont); - } - sAvailableFonts = Collections.unmodifiableSet(result); + sAvailableFonts = Font.getAvailableFonts(); } return sAvailableFonts; } diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp index 5a972f56ea87..bd3b7c93466c 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -35,6 +35,7 @@ #include <minikin/FontFamily.h> #include <minikin/FontFileParser.h> #include <minikin/LocaleList.h> +#include <minikin/SystemFonts.h> #include <ui/FatVector.h> #include <memory> @@ -282,6 +283,22 @@ static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { return font->font->typeface()->GetSourceId(); } +static jlongArray Font_getAvailableFontSet(JNIEnv* env, jobject) { + std::vector<jlong> refArray; + minikin::SystemFonts::getFontSet( + [&refArray](const std::vector<std::shared_ptr<minikin::Font>>& fontSet) { + refArray.reserve(fontSet.size()); + for (const auto& font : fontSet) { + std::shared_ptr<minikin::Font> fontRef = font; + refArray.push_back( + reinterpret_cast<jlong>(new FontWrapper(std::move(fontRef)))); + } + }); + jlongArray r = env->NewLongArray(refArray.size()); + env->SetLongArrayRegion(r, 0, refArray.size(), refArray.data()); + return r; +} + // Fast Native static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) { NPE_CHECK_RETURN_ZERO(env, buffer); @@ -373,6 +390,9 @@ static const JNINativeMethod gFontMethods[] = { {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount}, {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo}, {"nGetSourceId", "(J)I", (void*)Font_getSourceId}, + + // System font accessors + {"nGetAvailableFontSet", "()[J", (void*)Font_getAvailableFontSet}, }; static const JNINativeMethod gFontFileUtilMethods[] = { |