Merge "Introduce setFallbackTypeface" into oc-dev
am: 729a515e5e
Change-Id: I3e88a1d51b8a8be7f932964917218a28ae23c5c9
This commit is contained in:
@@ -13783,6 +13783,7 @@ package android.graphics {
|
||||
ctor public Typeface.Builder(java.lang.String);
|
||||
ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
|
||||
method public android.graphics.Typeface build();
|
||||
method public android.graphics.Typeface.Builder setFallback(java.lang.String);
|
||||
method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
|
||||
method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
|
||||
method public android.graphics.Typeface.Builder setItalic(boolean);
|
||||
|
||||
@@ -14550,6 +14550,7 @@ package android.graphics {
|
||||
ctor public Typeface.Builder(java.lang.String);
|
||||
ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
|
||||
method public android.graphics.Typeface build();
|
||||
method public android.graphics.Typeface.Builder setFallback(java.lang.String);
|
||||
method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
|
||||
method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
|
||||
method public android.graphics.Typeface.Builder setItalic(boolean);
|
||||
|
||||
@@ -13825,6 +13825,7 @@ package android.graphics {
|
||||
ctor public Typeface.Builder(java.lang.String);
|
||||
ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
|
||||
method public android.graphics.Typeface build();
|
||||
method public android.graphics.Typeface.Builder setFallback(java.lang.String);
|
||||
method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
|
||||
method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
|
||||
method public android.graphics.Typeface.Builder setItalic(boolean);
|
||||
|
||||
@@ -592,15 +592,11 @@ public class FontsContract {
|
||||
int weight, boolean italic, @Nullable String fallbackFontName) {
|
||||
final Map<Uri, ByteBuffer> uriBuffer =
|
||||
prepareFontData(context, fonts, cancellationSignal);
|
||||
Typeface typeface = new Typeface.Builder(fonts, uriBuffer)
|
||||
return new Typeface.Builder(fonts, uriBuffer)
|
||||
.setFallback(fallbackFontName)
|
||||
.setWeight(weight)
|
||||
.setItalic(italic)
|
||||
.build();
|
||||
// TODO: Use Typeface fallback instead.
|
||||
if (typeface == null) {
|
||||
typeface = Typeface.create(fallbackFontName, Typeface.NORMAL);
|
||||
}
|
||||
return typeface;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,21 +45,24 @@ namespace android {
|
||||
constexpr jint RESOLVE_BY_FONT_TABLE = -1;
|
||||
|
||||
struct NativeFamilyBuilder {
|
||||
NativeFamilyBuilder(uint32_t langId, int variant)
|
||||
: langId(langId), variant(variant), allowUnsupportedFont(false) {}
|
||||
uint32_t langId;
|
||||
int variant;
|
||||
bool allowUnsupportedFont;
|
||||
std::vector<minikin::Font> fonts;
|
||||
std::vector<minikin::FontVariation> axes;
|
||||
};
|
||||
|
||||
static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) {
|
||||
NativeFamilyBuilder* builder = new NativeFamilyBuilder();
|
||||
NativeFamilyBuilder* builder;
|
||||
if (lang != nullptr) {
|
||||
ScopedUtfChars str(env, lang);
|
||||
builder->langId = minikin::FontStyle::registerLanguageList(str.c_str());
|
||||
builder = new NativeFamilyBuilder(
|
||||
minikin::FontStyle::registerLanguageList(str.c_str()), variant);
|
||||
} else {
|
||||
builder->langId = minikin::FontStyle::registerLanguageList("");
|
||||
builder = new NativeFamilyBuilder(minikin::FontStyle::registerLanguageList(""), variant);
|
||||
}
|
||||
builder->variant = variant;
|
||||
return reinterpret_cast<jlong>(builder);
|
||||
}
|
||||
|
||||
@@ -67,12 +70,22 @@ static jlong FontFamily_create(jlong builderPtr) {
|
||||
if (builderPtr == 0) {
|
||||
return 0;
|
||||
}
|
||||
std::unique_ptr<NativeFamilyBuilder> builder(
|
||||
reinterpret_cast<NativeFamilyBuilder*>(builderPtr));
|
||||
std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
|
||||
builder->langId, builder->variant, std::move(builder->fonts));
|
||||
if (family->getCoverage().length() == 0 && !builder->allowUnsupportedFont) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
|
||||
}
|
||||
|
||||
static void FontFamily_allowUnsupportedFont(jlong builderPtr) {
|
||||
if (builderPtr == 0) {
|
||||
return;
|
||||
}
|
||||
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
|
||||
FontFamilyWrapper* family = new FontFamilyWrapper(
|
||||
std::make_shared<minikin::FontFamily>(
|
||||
builder->langId, builder->variant, std::move(builder->fonts)));
|
||||
delete builder;
|
||||
return reinterpret_cast<jlong>(family);
|
||||
builder->allowUnsupportedFont = true;
|
||||
}
|
||||
|
||||
static void FontFamily_abort(jlong builderPtr) {
|
||||
@@ -258,6 +271,7 @@ static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
|
||||
static const JNINativeMethod gFontFamilyMethods[] = {
|
||||
{ "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
|
||||
{ "nCreateFamily", "(J)J", (void*)FontFamily_create },
|
||||
{ "nAllowUnsupportedFont", "(J)V", (void*)FontFamily_allowUnsupportedFont },
|
||||
{ "nAbort", "(J)V", (void*)FontFamily_abort },
|
||||
{ "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
|
||||
{ "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
|
||||
|
||||
@@ -42,6 +42,13 @@ static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandl
|
||||
return reinterpret_cast<jlong>(face);
|
||||
}
|
||||
|
||||
static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
|
||||
jint weight, jboolean italic) {
|
||||
Typeface* baseTypeface = reinterpret_cast<Typeface*>(nativeInstance);
|
||||
return reinterpret_cast<jlong>(
|
||||
Typeface::createFromTypefaceWithStyle(baseTypeface, weight, italic));
|
||||
}
|
||||
|
||||
static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
|
||||
jobject listOfAxis) {
|
||||
std::vector<minikin::FontVariation> variations;
|
||||
@@ -75,6 +82,11 @@ static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
|
||||
return face->fSkiaStyle;
|
||||
}
|
||||
|
||||
static jint Typeface_getBaseWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
|
||||
Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
|
||||
return face->fBaseWeight;
|
||||
}
|
||||
|
||||
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
|
||||
ScopedLongArrayRO families(env, familyArray);
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
|
||||
@@ -113,11 +125,14 @@ static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle)
|
||||
|
||||
static const JNINativeMethod gTypefaceMethods[] = {
|
||||
{ "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
|
||||
{ "nativeCreateFromTypefaceWithExactStyle", "(JIZ)J",
|
||||
(void*)Typeface_createFromTypefaceWithExactStyle },
|
||||
{ "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
|
||||
(void*)Typeface_createFromTypefaceWithVariation },
|
||||
{ "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias },
|
||||
{ "nativeUnref", "(J)V", (void*)Typeface_unref },
|
||||
{ "nativeGetStyle", "(J)I", (void*)Typeface_getStyle },
|
||||
{ "nativeGetBaseWeight", "(J)I", (void*)Typeface_getBaseWeight },
|
||||
{ "nativeCreateFromArray", "([J)J",
|
||||
(void*)Typeface_createFromArray },
|
||||
{ "nativeSetDefault", "(J)V", (void*)Typeface_setDefault },
|
||||
|
||||
@@ -52,12 +52,19 @@ public class FontFamily {
|
||||
mBuilderPtr = nInitBuilder(lang, variant);
|
||||
}
|
||||
|
||||
public void freeze() {
|
||||
/**
|
||||
* Finalize the FontFamily creation.
|
||||
*
|
||||
* @return boolean returns false if some error happens in native code, e.g. broken font file is
|
||||
* passed, etc.
|
||||
*/
|
||||
public boolean freeze() {
|
||||
if (mBuilderPtr == 0) {
|
||||
throw new IllegalStateException("This FontFamily is already frozen");
|
||||
}
|
||||
mNativePtr = nCreateFamily(mBuilderPtr);
|
||||
mBuilderPtr = 0;
|
||||
return mNativePtr != 0;
|
||||
}
|
||||
|
||||
public void abortCreation() {
|
||||
@@ -143,6 +150,25 @@ public class FontFamily {
|
||||
isItalic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow creating unsupported FontFamily.
|
||||
*
|
||||
* For compatibility reasons, we still need to create a FontFamily object even if Minikin failed
|
||||
* to find any usable 'cmap' table for some reasons, e.g. broken 'cmap' table, no 'cmap' table
|
||||
* encoded with Unicode code points, etc. Without calling this method, the freeze() method will
|
||||
* return null if Minikin fails to find any usable 'cmap' table. By calling this method, the
|
||||
* freeze() won't fail and will create an empty FontFamily. This empty FontFamily is placed at
|
||||
* the top of the fallback chain but is never used. if we don't create this empty FontFamily
|
||||
* and put it at top, bad things (performance regressions, unexpected glyph selection) will
|
||||
* happen.
|
||||
*/
|
||||
public void allowUnsupportedFont() {
|
||||
if (mBuilderPtr == 0) {
|
||||
throw new IllegalStateException("Unable to allow unsupported font.");
|
||||
}
|
||||
nAllowUnsupportedFont(mBuilderPtr);
|
||||
}
|
||||
|
||||
// TODO: Remove once internal user stop using private API.
|
||||
private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
|
||||
return nAddFont(builderPtr, font, ttcIndex, -1, -1);
|
||||
@@ -153,6 +179,9 @@ public class FontFamily {
|
||||
@CriticalNative
|
||||
private static native long nCreateFamily(long mBuilderPtr);
|
||||
|
||||
@CriticalNative
|
||||
private static native void nAllowUnsupportedFont(long builderPtr);
|
||||
|
||||
@CriticalNative
|
||||
private static native void nAbort(long mBuilderPtr);
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ public class Typeface {
|
||||
/**
|
||||
* Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
|
||||
*/
|
||||
@GuardedBy("sLock")
|
||||
private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
|
||||
|
||||
static Typeface sDefaultTypeface;
|
||||
@@ -129,6 +130,7 @@ public class Typeface {
|
||||
public static final int BOLD_ITALIC = 3;
|
||||
|
||||
private int mStyle = 0;
|
||||
private int mBaseWeight = 0;
|
||||
|
||||
// Value for weight and italic. Indicates the value is resolved by font metadata.
|
||||
// Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
|
||||
@@ -180,7 +182,9 @@ public class Typeface {
|
||||
if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */,
|
||||
0 /* ttcIndex */, RESOLVE_BY_FONT_TABLE /* weight */,
|
||||
RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
|
||||
fontFamily.freeze();
|
||||
if (!fontFamily.freeze()) {
|
||||
return null;
|
||||
}
|
||||
FontFamily[] families = {fontFamily};
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
@@ -241,6 +245,10 @@ public class Typeface {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Due to backward compatibility, even if the font is not supported by our font stack,
|
||||
// we need to place the empty font at the first place. The typeface with empty font
|
||||
// behaves different from default typeface especially in fallback font selection.
|
||||
fontFamily.allowUnsupportedFont();
|
||||
fontFamily.freeze();
|
||||
FontFamily[] familyChain = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(familyChain);
|
||||
@@ -393,7 +401,11 @@ public class Typeface {
|
||||
IoUtils.closeQuietly(fd);
|
||||
}
|
||||
}
|
||||
fontFamily.freeze();
|
||||
if (!fontFamily.freeze()) {
|
||||
callback.onTypefaceRequestFailed(
|
||||
FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
|
||||
return;
|
||||
}
|
||||
Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily });
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
String key = createProviderUid(request.getProviderAuthority(), request.getQuery());
|
||||
@@ -526,6 +538,7 @@ public class Typeface {
|
||||
|
||||
private FontsContract.FontInfo[] mFonts;
|
||||
private Map<Uri, ByteBuffer> mFontBuffers;
|
||||
|
||||
private String mFallbackFamilyName;
|
||||
|
||||
private int mWeight = RESOLVE_BY_FONT_TABLE;
|
||||
@@ -665,6 +678,33 @@ public class Typeface {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a fallback family name.
|
||||
*
|
||||
* By specifying a fallback family name, a fallback Typeface will be returned if the
|
||||
* {@link #build} method fails to create a Typeface from the provided font. The fallback
|
||||
* family will be resolved with the provided weight and italic information specified by
|
||||
* {@link #setWeight} and {@link #setItalic}.
|
||||
*
|
||||
* If {@link #setWeight} is not called, the fallback family keeps the default weight.
|
||||
* Similary, if {@link #setItalic} is not called, the fallback family keeps the default
|
||||
* italic information. For example, calling {@code builder.setFallback("sans-serif-light")}
|
||||
* is equivalent to calling {@code builder.setFallback("sans-serif").setWeight(300)} in
|
||||
* terms of fallback. The default weight and italic information are overridden by calling
|
||||
* {@link #setWeight} and {@link #setItalic}. For example, if a Typeface is constructed
|
||||
* using {@code builder.setFallback("sans-serif-light").setWeight(700)}, the fallback text
|
||||
* will render as sans serif bold.
|
||||
*
|
||||
* @param familyName A family name to be used for fallback if the provided font can not be
|
||||
* used. By passing {@code null}, build() returns {@code null}.
|
||||
* If {@link #setFallback} is not called on the builder, {@code null}
|
||||
* is assumed.
|
||||
*/
|
||||
public Builder setFallback(@Nullable String familyName) {
|
||||
mFallbackFamilyName = familyName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique id for a given AssetManager and asset path.
|
||||
*
|
||||
@@ -697,6 +737,54 @@ public class Typeface {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final Object sLock = new Object();
|
||||
// TODO: Unify with Typeface.sTypefaceCache.
|
||||
@GuardedBy("sLock")
|
||||
private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
|
||||
new LongSparseArray<>(3);
|
||||
|
||||
private Typeface resolveFallbackTypeface() {
|
||||
if (mFallbackFamilyName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Typeface base = sSystemFontMap.get(mFallbackFamilyName);
|
||||
if (base == null) {
|
||||
base = sDefaultTypeface;
|
||||
}
|
||||
|
||||
if (mWeight == RESOLVE_BY_FONT_TABLE && mItalic == RESOLVE_BY_FONT_TABLE) {
|
||||
return base;
|
||||
}
|
||||
|
||||
final int weight = (mWeight == RESOLVE_BY_FONT_TABLE) ? base.mBaseWeight : mWeight;
|
||||
final boolean italic =
|
||||
(mItalic == RESOLVE_BY_FONT_TABLE) ? (base.mStyle & ITALIC) != 0 : mItalic == 1;
|
||||
final int key = weight << 1 | (italic ? 1 : 0);
|
||||
|
||||
Typeface typeface;
|
||||
synchronized(sLock) {
|
||||
SparseArray<Typeface> innerCache = sTypefaceCache.get(base.native_instance);
|
||||
if (innerCache != null) {
|
||||
typeface = innerCache.get(key);
|
||||
if (typeface != null) {
|
||||
return typeface;
|
||||
}
|
||||
}
|
||||
|
||||
typeface = new Typeface(
|
||||
nativeCreateFromTypefaceWithExactStyle(
|
||||
base.native_instance, weight, italic));
|
||||
|
||||
if (innerCache == null) {
|
||||
innerCache = new SparseArray<>(4); // [regular, bold] x [upright, italic]
|
||||
sTypefaceCache.put(base.native_instance, innerCache);
|
||||
}
|
||||
innerCache.put(key, typeface);
|
||||
}
|
||||
return typeface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new Typeface from specified configuration.
|
||||
*
|
||||
@@ -712,26 +800,30 @@ public class Typeface {
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
if (!fontFamily.addFontFromBuffer(buffer, mTtcIndex, mAxes, mWeight, mItalic)) {
|
||||
fontFamily.abortCreation();
|
||||
return null;
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
if (!fontFamily.freeze()) {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
fontFamily.freeze();
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
} else if (mAssetManager != null) { // set source by setSourceFromAsset()
|
||||
final String key = createAssetUid(mAssetManager, mPath, mTtcIndex, mAxes);
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
synchronized (sLock) {
|
||||
Typeface typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) return typeface;
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
if (!fontFamily.addFontFromAssetManager(mAssetManager, mPath, mTtcIndex,
|
||||
true /* isAsset */, mTtcIndex, mWeight, mItalic, mAxes)) {
|
||||
fontFamily.abortCreation();
|
||||
return null;
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
if (!fontFamily.freeze()) {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
fontFamily.freeze();
|
||||
FontFamily[] families = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
@@ -741,9 +833,11 @@ public class Typeface {
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
if (!fontFamily.addFont(mPath, mTtcIndex, mAxes, mWeight, mItalic)) {
|
||||
fontFamily.abortCreation();
|
||||
return null;
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
if (!fontFamily.freeze()) {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
fontFamily.freeze();
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
} else if (mFonts != null) {
|
||||
@@ -870,12 +964,34 @@ public class Typeface {
|
||||
throw new NullPointerException(); // for backward compatibility
|
||||
}
|
||||
if (sFallbackFonts != null) {
|
||||
Typeface typeface = new Builder(mgr, path).build();
|
||||
if (typeface != null) {
|
||||
return typeface;
|
||||
synchronized (sLock) {
|
||||
Typeface typeface = new Builder(mgr, path).build();
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
|
||||
null /* axes */);
|
||||
typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
if (fontFamily.addFontFromAssetManager(mgr, path, 0, true /* isAsset */,
|
||||
0 /* ttc index */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE,
|
||||
null /* axes */)) {
|
||||
// Due to backward compatibility, even if the font is not supported by our font
|
||||
// stack, we need to place the empty font at the first place. The typeface with
|
||||
// empty font behaves different from default typeface especially in fallback
|
||||
// font selection.
|
||||
fontFamily.allowUnsupportedFont();
|
||||
fontFamily.freeze();
|
||||
final FontFamily[] families = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
return typeface;
|
||||
} else {
|
||||
fontFamily.abortCreation();
|
||||
}
|
||||
}
|
||||
}
|
||||
// For the compatibility reasons, throw runtime exception if failed to create Typeface.
|
||||
throw new RuntimeException("Font asset not found " + path);
|
||||
}
|
||||
|
||||
@@ -910,17 +1026,20 @@ public class Typeface {
|
||||
* @return The new typeface.
|
||||
*/
|
||||
public static Typeface createFromFile(@Nullable String path) {
|
||||
if (path == null) {
|
||||
// For the compatibility reasons, need to throw NPE if the argument is null.
|
||||
// See android.graphics.cts.TypefaceTest#testCreateFromFileByFileNameNull
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (sFallbackFonts != null) {
|
||||
Typeface typeface = new Builder(path).build();
|
||||
if (typeface != null) {
|
||||
// For the compatibility reasons, throw runtime exception if failed to create
|
||||
// Typeface.
|
||||
return typeface;
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
if (fontFamily.addFont(path, 0 /* ttcIndex */, null /* axes */,
|
||||
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE)) {
|
||||
// Due to backward compatibility, even if the font is not supported by our font
|
||||
// stack, we need to place the empty font at the first place. The typeface with
|
||||
// empty font behaves different from default typeface especially in fallback font
|
||||
// selection.
|
||||
fontFamily.allowUnsupportedFont();
|
||||
fontFamily.freeze();
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
} else {
|
||||
fontFamily.abortCreation();
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Font not found " + path);
|
||||
@@ -964,6 +1083,7 @@ public class Typeface {
|
||||
|
||||
native_instance = ni;
|
||||
mStyle = nativeGetStyle(ni);
|
||||
mBaseWeight = nativeGetBaseWeight(ni);
|
||||
}
|
||||
|
||||
private static FontFamily makeFamilyFromParsed(FontConfig.Family family,
|
||||
@@ -988,7 +1108,11 @@ public class Typeface {
|
||||
Log.e(TAG, "Error creating font " + fullPathName + "#" + font.getTtcIndex());
|
||||
}
|
||||
}
|
||||
fontFamily.freeze();
|
||||
if (!fontFamily.freeze()) {
|
||||
// Treat as system error since reaching here means that a system pre-installed font
|
||||
// can't be used by our font stack.
|
||||
Log.e(TAG, "Unable to load Family: " + family.getName() + ":" + family.getLanguage());
|
||||
}
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
@@ -1129,12 +1253,15 @@ public class Typeface {
|
||||
}
|
||||
|
||||
private static native long nativeCreateFromTypeface(long native_instance, int style);
|
||||
private static native long nativeCreateFromTypefaceWithExactStyle(
|
||||
long native_instance, int weight, boolean italic);
|
||||
// TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
|
||||
private static native long nativeCreateFromTypefaceWithVariation(
|
||||
long native_instance, List<FontVariationAxis> axes);
|
||||
private static native long nativeCreateWeightAlias(long native_instance, int weight);
|
||||
private static native void nativeUnref(long native_instance);
|
||||
private static native int nativeGetStyle(long native_instance);
|
||||
private static native int nativeGetBaseWeight(long native_instance);
|
||||
private static native long nativeCreateFromArray(long[] familyArray);
|
||||
private static native void nativeSetDefault(long native_instance);
|
||||
private static native int[] nativeGetSupportedAxes(long native_instance);
|
||||
|
||||
@@ -71,6 +71,18 @@ Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Typeface* Typeface::createFromTypefaceWithStyle(Typeface* base, int weight, bool italic) {
|
||||
Typeface* resolvedFace = Typeface::resolveDefault(base);
|
||||
Typeface* result = new Typeface();
|
||||
if (result != nullptr) {
|
||||
result->fFontCollection = resolvedFace->fFontCollection;
|
||||
result->fBaseWeight = weight;
|
||||
result->fStyle = minikin::FontStyle(weight / 100, italic);
|
||||
result->fSkiaStyle = resolvedFace->fSkiaStyle;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
|
||||
const std::vector<minikin::FontVariation>& variations) {
|
||||
Typeface* resolvedFace = Typeface::resolveDefault(src);
|
||||
|
||||
@@ -42,6 +42,8 @@ struct ANDROID_API Typeface {
|
||||
|
||||
static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
|
||||
|
||||
static Typeface* createFromTypefaceWithStyle(Typeface* base, int weight, bool italic);
|
||||
|
||||
static Typeface* createFromTypefaceWithVariation(Typeface* src,
|
||||
const std::vector<minikin::FontVariation>& variations);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user