Loading graphics/java/android/graphics/fonts/Font.java +18 −0 Original line number Original line Diff line number Diff line Loading @@ -46,7 +46,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.IdentityHashMap; import java.util.Objects; import java.util.Objects; import java.util.Set; /** /** * A font class can be used for creating FontFamily. * A font class can be used for creating FontFamily. Loading Loading @@ -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 @CriticalNative private static native long nGetMinikinFontPtr(long font); private static native long nGetMinikinFontPtr(long font); Loading Loading @@ -900,4 +915,7 @@ public final class Font { @CriticalNative @CriticalNative private static native long nGetAxisInfo(long fontPtr, int i); private static native long nGetAxisInfo(long fontPtr, int i); @FastNative private static native long[] nGetAvailableFontSet(); } } graphics/java/android/graphics/fonts/SystemFonts.java +1 −51 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.graphics.FontListParser; import android.graphics.Typeface; import android.graphics.Typeface; import android.text.FontConfig; import android.text.FontConfig; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; Loading @@ -39,7 +38,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Set; /** /** Loading @@ -60,36 +58,6 @@ public final class SystemFonts { private static final Object LOCK = new Object(); private static final Object LOCK = new Object(); private static @GuardedBy("sLock") Set<Font> sAvailableFonts; 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. * Returns all available font files in the system. * * Loading @@ -98,25 +66,7 @@ public final class SystemFonts { public static @NonNull Set<Font> getAvailableFonts() { public static @NonNull Set<Font> getAvailableFonts() { synchronized (LOCK) { synchronized (LOCK) { if (sAvailableFonts == null) { if (sAvailableFonts == null) { Set<SystemFontHashWrapper> set = new ArraySet<>(); sAvailableFonts = Font.getAvailableFonts(); 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); } } return sAvailableFonts; return sAvailableFonts; } } Loading libs/hwui/jni/fonts/Font.cpp +20 −0 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <minikin/FontFamily.h> #include <minikin/FontFamily.h> #include <minikin/FontFileParser.h> #include <minikin/FontFileParser.h> #include <minikin/LocaleList.h> #include <minikin/LocaleList.h> #include <minikin/SystemFonts.h> #include <ui/FatVector.h> #include <ui/FatVector.h> #include <memory> #include <memory> Loading Loading @@ -282,6 +283,22 @@ static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { return font->font->typeface()->GetSourceId(); 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 // Fast Native static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) { static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) { NPE_CHECK_RETURN_ZERO(env, buffer); NPE_CHECK_RETURN_ZERO(env, buffer); Loading Loading @@ -373,6 +390,9 @@ static const JNINativeMethod gFontMethods[] = { {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount}, {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount}, {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo}, {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo}, {"nGetSourceId", "(J)I", (void*)Font_getSourceId}, {"nGetSourceId", "(J)I", (void*)Font_getSourceId}, // System font accessors {"nGetAvailableFontSet", "()[J", (void*)Font_getAvailableFontSet}, }; }; static const JNINativeMethod gFontFileUtilMethods[] = { static const JNINativeMethod gFontFileUtilMethods[] = { Loading Loading
graphics/java/android/graphics/fonts/Font.java +18 −0 Original line number Original line Diff line number Diff line Loading @@ -46,7 +46,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.IdentityHashMap; import java.util.Objects; import java.util.Objects; import java.util.Set; /** /** * A font class can be used for creating FontFamily. * A font class can be used for creating FontFamily. Loading Loading @@ -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 @CriticalNative private static native long nGetMinikinFontPtr(long font); private static native long nGetMinikinFontPtr(long font); Loading Loading @@ -900,4 +915,7 @@ public final class Font { @CriticalNative @CriticalNative private static native long nGetAxisInfo(long fontPtr, int i); private static native long nGetAxisInfo(long fontPtr, int i); @FastNative private static native long[] nGetAvailableFontSet(); } }
graphics/java/android/graphics/fonts/SystemFonts.java +1 −51 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.graphics.FontListParser; import android.graphics.Typeface; import android.graphics.Typeface; import android.text.FontConfig; import android.text.FontConfig; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; Loading @@ -39,7 +38,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Set; /** /** Loading @@ -60,36 +58,6 @@ public final class SystemFonts { private static final Object LOCK = new Object(); private static final Object LOCK = new Object(); private static @GuardedBy("sLock") Set<Font> sAvailableFonts; 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. * Returns all available font files in the system. * * Loading @@ -98,25 +66,7 @@ public final class SystemFonts { public static @NonNull Set<Font> getAvailableFonts() { public static @NonNull Set<Font> getAvailableFonts() { synchronized (LOCK) { synchronized (LOCK) { if (sAvailableFonts == null) { if (sAvailableFonts == null) { Set<SystemFontHashWrapper> set = new ArraySet<>(); sAvailableFonts = Font.getAvailableFonts(); 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); } } return sAvailableFonts; return sAvailableFonts; } } Loading
libs/hwui/jni/fonts/Font.cpp +20 −0 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <minikin/FontFamily.h> #include <minikin/FontFamily.h> #include <minikin/FontFileParser.h> #include <minikin/FontFileParser.h> #include <minikin/LocaleList.h> #include <minikin/LocaleList.h> #include <minikin/SystemFonts.h> #include <ui/FatVector.h> #include <ui/FatVector.h> #include <memory> #include <memory> Loading Loading @@ -282,6 +283,22 @@ static jint Font_getSourceId(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { return font->font->typeface()->GetSourceId(); 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 // Fast Native static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) { static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) { NPE_CHECK_RETURN_ZERO(env, buffer); NPE_CHECK_RETURN_ZERO(env, buffer); Loading Loading @@ -373,6 +390,9 @@ static const JNINativeMethod gFontMethods[] = { {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount}, {"nGetAxisCount", "(J)I", (void*)Font_getAxisCount}, {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo}, {"nGetAxisInfo", "(JI)J", (void*)Font_getAxisInfo}, {"nGetSourceId", "(J)I", (void*)Font_getSourceId}, {"nGetSourceId", "(J)I", (void*)Font_getSourceId}, // System font accessors {"nGetAvailableFontSet", "()[J", (void*)Font_getAvailableFontSet}, }; }; static const JNINativeMethod gFontFileUtilMethods[] = { static const JNINativeMethod gFontFileUtilMethods[] = { Loading