Merge "Introduce getSourceIdentifier instead of isSameSource."

This commit is contained in:
TreeHugger Robot
2020-11-05 22:19:27 +00:00
committed by Android (Google) Code Review
4 changed files with 88 additions and 15 deletions

View File

@@ -16424,9 +16424,9 @@ package android.graphics.fonts {
method public float getGlyphBounds(@IntRange(from=0) int, @NonNull android.graphics.Paint, @Nullable android.graphics.RectF);
method @NonNull public android.os.LocaleList getLocaleList();
method public void getMetrics(@NonNull android.graphics.Paint, @Nullable android.graphics.Paint.FontMetrics);
method public int getSourceIdentifier();
method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
method public boolean isSameSource(@NonNull android.graphics.fonts.Font);
}
public static final class Font.Builder {

View File

@@ -16406,9 +16406,9 @@ package android.graphics.fonts {
method public float getGlyphBounds(@IntRange(from=0) int, @NonNull android.graphics.Paint, @Nullable android.graphics.RectF);
method @NonNull public android.os.LocaleList getLocaleList();
method public void getMetrics(@NonNull android.graphics.Paint, @Nullable android.graphics.Paint.FontMetrics);
method public int getSourceIdentifier();
method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
method public boolean isSameSource(@NonNull android.graphics.fonts.Font);
}
public static final class Font.Builder {

View File

@@ -28,6 +28,7 @@ import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.TypedValue;
import com.android.internal.annotations.GuardedBy;
@@ -69,6 +70,11 @@ public final class Font {
private static final LongSparseArray<WeakReference<Font>> FONT_PTR_MAP =
new LongSparseArray<>();
private static final Object SOURCE_ID_LOCK = new Object();
@GuardedBy("SOURCE_ID_LOCK")
private static final LongSparseLongArray FONT_SOURCE_ID_MAP =
new LongSparseLongArray(300); // System font has 200 fonts, so 300 should be enough.
/**
* A builder class for creating new Font.
*/
@@ -465,13 +471,24 @@ public final class Font {
final String filePath = mFile == null ? "" : mFile.getAbsolutePath();
long ptr;
int fontIdentifier;
if (mFont == null) {
ptr = nBuild(builderPtr, readonlyBuffer, filePath, mWeight, italic, mTtcIndex);
long fontBufferPtr = nGetFontBufferAddress(ptr);
synchronized (SOURCE_ID_LOCK) {
long id = FONT_SOURCE_ID_MAP.get(fontBufferPtr, -1);
if (id == -1) {
id = FONT_SOURCE_ID_MAP.size();
FONT_SOURCE_ID_MAP.put(fontBufferPtr, id);
}
fontIdentifier = (int) id;
}
} else {
ptr = nClone(mFont.getNativePtr(), builderPtr, mWeight, italic, mTtcIndex);
fontIdentifier = mFont.mSourceIdentifier;
}
final Font font = new Font(ptr, readonlyBuffer, mFile,
new FontStyle(mWeight, slant), mTtcIndex, mAxes, mLocaleList);
new FontStyle(mWeight, slant), mTtcIndex, mAxes, mLocaleList, fontIdentifier);
sFontRegistry.registerNativeAllocation(font, ptr);
return font;
}
@@ -500,13 +517,15 @@ public final class Font {
private final @IntRange(from = 0) int mTtcIndex;
private final @Nullable FontVariationAxis[] mAxes;
private final @NonNull String mLocaleList;
private final int mSourceIdentifier; // An identifier of font source data.
/**
* Use Builder instead
*/
private Font(long nativePtr, @NonNull ByteBuffer buffer, @Nullable File file,
@NonNull FontStyle fontStyle, @IntRange(from = 0) int ttcIndex,
@Nullable FontVariationAxis[] axes, @NonNull String localeList) {
@Nullable FontVariationAxis[] axes, @NonNull String localeList,
int sourceIdentifier) {
mBuffer = buffer;
mFile = file;
mFontStyle = fontStyle;
@@ -514,6 +533,7 @@ public final class Font {
mTtcIndex = ttcIndex;
mAxes = axes;
mLocaleList = localeList;
mSourceIdentifier = sourceIdentifier;
synchronized (MAP_LOCK) {
FONT_PTR_MAP.append(nGetNativeFontPtr(mNativePtr), new WeakReference<>(this));
@@ -626,6 +646,62 @@ public final class Font {
return mNativePtr;
}
/**
* Returns the unique ID of the source font data.
*
* You can use this identifier as a key of the cache or checking if two fonts can be
* interpolated with font variation settings.
* <pre>
* <code>
* // Following three Fonts, fontA, fontB, fontC have the same identifier.
* Font fontA = new Font.Builder("/path/to/font").build();
* Font fontB = new Font.Builder(fontA).setTtcIndex(1).build();
* Font fontC = new Font.Builder(fontB).setFontVariationSettings("'wght' 700).build();
*
* // Following fontD has the different identifier from above three.
* Font fontD = new Font.Builder("/path/to/another/font").build();
*
* // Following fontE has different identifier from above four even the font path is the same.
* // To get the same identifier, please create new Font instance from existing fonts.
* Font fontE = new Font.Builder("/path/to/font").build();
* </code>
* </pre>
*
* Here is an example of caching font object that has
* <pre>
* <code>
* private LongSparseArray<SparseArray<Font>> mCache = new LongSparseArray<>();
*
* private Font getFontWeightVariation(Font font, int weight) {
* // Different collection index is treated as different font.
* long key = ((long) font.getSourceIdentifier()) << 32 | (long) font.getTtcIndex();
*
* SparseArray<Font> weightCache = mCache.get(key);
* if (weightCache == null) {
* weightCache = new SparseArray<>();
* mCache.put(key, weightCache);
* }
*
* Font cachedFont = weightCache.get(weight);
* if (cachedFont != null) {
* return cachedFont;
* }
*
* Font newFont = new Font.Builder(cachedFont)
* .setFontVariationSettings("'wght' " + weight);
* .build();
*
* weightCache.put(weight, newFont);
* return newFont;
* }
* </code>
* </pre>
* @return an unique identifier for the font source data.
*/
public int getSourceIdentifier() {
return mSourceIdentifier;
}
/**
* Returns true if the given font is created from the same source data from this font.
*
@@ -643,7 +719,7 @@ public final class Font {
* @param other a font object to be compared.
* @return true if given font is created from the same source from this font. Otherwise false.
*/
public boolean isSameSource(@NonNull Font other) {
private boolean isSameSource(@NonNull Font other) {
Objects.requireNonNull(other);
// Shortcut for the same instance.
@@ -660,7 +736,7 @@ public final class Font {
// underlying native font object holds buffer address, check if this buffer points exactly
// the same address as a shortcut of equality. For being compatible with of API30 or before,
// check buffer position even if the buffer points the same address.
if (nIsSameBufferAddress(mNativePtr, other.mNativePtr)
if (mSourceIdentifier == other.mSourceIdentifier
&& mBuffer.position() == other.mBuffer.position()) {
return true;
}
@@ -788,5 +864,5 @@ public final class Font {
private static native long nGetNativeFontPtr(long ptr);
@CriticalNative
private static native boolean nIsSameBufferAddress(long lFontPtr, long rFontPtr);
private static native long nGetFontBufferAddress(long font);
}

View File

@@ -239,13 +239,10 @@ static jlong Font_getNativeFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
}
// Critical Native
static jboolean Font_isSameBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong lFontHandle,
jlong rFontHandle) {
FontWrapper* lFont = reinterpret_cast<FontWrapper*>(lFontHandle);
FontWrapper* rFont = reinterpret_cast<FontWrapper*>(rFontHandle);
const void* lBufferPtr = lFont->font->typeface()->GetFontData();
const void* rBufferPtr = rFont->font->typeface()->GetFontData();
return lBufferPtr == rBufferPtr;
static jlong Font_GetBufferAddress(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
const void* bufferPtr = font->font->typeface()->GetFontData();
return reinterpret_cast<jlong>(bufferPtr);
}
///////////////////////////////////////////////////////////////////////////////
@@ -297,7 +294,7 @@ static const JNINativeMethod gFontMethods[] = {
{ "nGetAxisInfo", "(JI)J", (void*) Font_getAxisInfo },
{ "nGetFontPath", "(J)Ljava/lang/String;", (void*) Font_getFontPath },
{ "nGetNativeFontPtr", "(J)J", (void*) Font_getNativeFontPtr },
{ "nIsSameBufferAddress", "(JJ)Z", (void*) Font_isSameBufferAddress },
{ "nGetFontBufferAddress", "(J)J", (void*) Font_GetBufferAddress },
};
static const JNINativeMethod gFontBufferHelperMethods[] = {