Merge "Calculate set of available fonts in native" into sc-dev

This commit is contained in:
Seigo Nonaka
2021-06-03 23:26:17 +00:00
committed by Android (Google) Code Review
3 changed files with 39 additions and 51 deletions

View File

@@ -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();
}

View File

@@ -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;
/**
@@ -60,36 +58,6 @@ public final class SystemFonts {
private static final Object LOCK = new Object();
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.
*
@@ -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;
}

View File

@@ -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[] = {