summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--graphics/java/android/graphics/fonts/Font.java18
-rw-r--r--graphics/java/android/graphics/fonts/SystemFonts.java52
-rw-r--r--libs/hwui/jni/fonts/Font.cpp20
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[] = {