Merge "Use provided style for fallback font selection" into oc-dev
am: 43112fd26e
Change-Id: I15c19e1f5ff7919895af967f3ebf2d9564e0ce89
This commit is contained in:
@ -87,7 +87,8 @@ static jint Typeface_getBaseWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
|
||||
return face->fBaseWeight;
|
||||
}
|
||||
|
||||
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
|
||||
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
|
||||
int weight, int italic) {
|
||||
ScopedLongArrayRO families(env, familyArray);
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
|
||||
familyVec.reserve(families.size());
|
||||
@ -95,7 +96,8 @@ static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArr
|
||||
FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
|
||||
familyVec.emplace_back(family->family);
|
||||
}
|
||||
return reinterpret_cast<jlong>(Typeface::createFromFamilies(std::move(familyVec)));
|
||||
return reinterpret_cast<jlong>(
|
||||
Typeface::createFromFamilies(std::move(familyVec), weight, italic));
|
||||
}
|
||||
|
||||
static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
|
||||
@ -133,7 +135,7 @@ static const JNINativeMethod gTypefaceMethods[] = {
|
||||
{ "nativeUnref", "(J)V", (void*)Typeface_unref },
|
||||
{ "nativeGetStyle", "(J)I", (void*)Typeface_getStyle },
|
||||
{ "nativeGetBaseWeight", "(J)I", (void*)Typeface_getBaseWeight },
|
||||
{ "nativeCreateFromArray", "([J)J",
|
||||
{ "nativeCreateFromArray", "([JII)J",
|
||||
(void*)Typeface_createFromArray },
|
||||
{ "nativeSetDefault", "(J)V", (void*)Typeface_setDefault },
|
||||
{ "nativeGetSupportedAxes", "(J)[I", (void*)Typeface_getSupportedAxes },
|
||||
|
@ -173,7 +173,8 @@ public class Typeface {
|
||||
if (sFallbackFonts != null) {
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
final String key = Builder.createAssetUid(
|
||||
mgr, path, 0 /* ttcIndex */, null /* axes */);
|
||||
mgr, path, 0 /* ttcIndex */, null /* axes */,
|
||||
RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);
|
||||
Typeface typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
@ -186,7 +187,8 @@ public class Typeface {
|
||||
return null;
|
||||
}
|
||||
FontFamily[] families = {fontFamily};
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
typeface = createFromFamiliesWithDefault(families,
|
||||
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
return typeface;
|
||||
}
|
||||
@ -251,10 +253,12 @@ public class Typeface {
|
||||
fontFamily.allowUnsupportedFont();
|
||||
fontFamily.freeze();
|
||||
FontFamily[] familyChain = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(familyChain);
|
||||
typeface = createFromFamiliesWithDefault(familyChain,
|
||||
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
|
||||
null /* axes */);
|
||||
null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */,
|
||||
RESOLVE_BY_FONT_TABLE /* italic */);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
}
|
||||
return typeface;
|
||||
@ -268,7 +272,8 @@ public class Typeface {
|
||||
*/
|
||||
public static Typeface findFromCache(AssetManager mgr, String path) {
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */);
|
||||
final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */,
|
||||
RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);
|
||||
Typeface typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) {
|
||||
return typeface;
|
||||
@ -406,7 +411,9 @@ public class Typeface {
|
||||
FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
|
||||
return;
|
||||
}
|
||||
Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily });
|
||||
Typeface typeface = Typeface.createFromFamiliesWithDefault(
|
||||
new FontFamily[] { fontFamily },
|
||||
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
|
||||
synchronized (sDynamicTypefaceCache) {
|
||||
String key = createProviderUid(request.getProviderAuthority(), request.getQuery());
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
@ -715,7 +722,7 @@ public class Typeface {
|
||||
* @return Unique id for a given AssetManager and asset path.
|
||||
*/
|
||||
private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
|
||||
@Nullable FontVariationAxis[] axes) {
|
||||
@Nullable FontVariationAxis[] axes, int weight, int italic) {
|
||||
final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final int size = pkgs.size();
|
||||
@ -727,6 +734,10 @@ public class Typeface {
|
||||
builder.append("-");
|
||||
builder.append(Integer.toString(ttcIndex));
|
||||
builder.append("-");
|
||||
builder.append(Integer.toString(weight));
|
||||
builder.append("-");
|
||||
builder.append(Integer.toString(italic));
|
||||
builder.append("-");
|
||||
if (axes != null) {
|
||||
for (FontVariationAxis axis : axes) {
|
||||
builder.append(axis.getTag());
|
||||
@ -791,7 +802,7 @@ public class Typeface {
|
||||
* @return Newly created Typeface. May return null if some parameters are invalid.
|
||||
*/
|
||||
public Typeface build() {
|
||||
if (mFd != null) { // set source by setSourceFromFile(FileDescriptor)
|
||||
if (mFd != null) { // Builder is created with file descriptor.
|
||||
try (FileInputStream fis = new FileInputStream(mFd)) {
|
||||
FileChannel channel = fis.getChannel();
|
||||
long size = channel.size();
|
||||
@ -806,12 +817,13 @@ public class Typeface {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
return createFromFamiliesWithDefault(families, mWeight, mItalic);
|
||||
} catch (IOException e) {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
} else if (mAssetManager != null) { // set source by setSourceFromAsset()
|
||||
final String key = createAssetUid(mAssetManager, mPath, mTtcIndex, mAxes);
|
||||
} else if (mAssetManager != null) { // Builder is created with asset manager.
|
||||
final String key = createAssetUid(
|
||||
mAssetManager, mPath, mTtcIndex, mAxes, mWeight, mItalic);
|
||||
synchronized (sLock) {
|
||||
Typeface typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) return typeface;
|
||||
@ -825,11 +837,11 @@ public class Typeface {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
FontFamily[] families = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
typeface = createFromFamiliesWithDefault(families, mWeight, mItalic);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
return typeface;
|
||||
}
|
||||
} else if (mPath != null) { // set source by setSourceFromFile(File)
|
||||
} else if (mPath != null) { // Builder is created with file path.
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
if (!fontFamily.addFont(mPath, mTtcIndex, mAxes, mWeight, mItalic)) {
|
||||
fontFamily.abortCreation();
|
||||
@ -839,7 +851,7 @@ public class Typeface {
|
||||
return resolveFallbackTypeface();
|
||||
}
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
return createFromFamiliesWithDefault(families, mWeight, mItalic);
|
||||
} else if (mFonts != null) {
|
||||
final FontFamily fontFamily = new FontFamily();
|
||||
boolean atLeastOneFont = false;
|
||||
@ -865,7 +877,7 @@ public class Typeface {
|
||||
}
|
||||
fontFamily.freeze();
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
return createFromFamiliesWithDefault(families, mWeight, mItalic);
|
||||
}
|
||||
|
||||
// Must not reach here.
|
||||
@ -969,7 +981,7 @@ public class Typeface {
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
|
||||
null /* axes */);
|
||||
null /* axes */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
|
||||
typeface = sDynamicTypefaceCache.get(key);
|
||||
if (typeface != null) return typeface;
|
||||
|
||||
@ -984,7 +996,8 @@ public class Typeface {
|
||||
fontFamily.allowUnsupportedFont();
|
||||
fontFamily.freeze();
|
||||
final FontFamily[] families = { fontFamily };
|
||||
typeface = createFromFamiliesWithDefault(families);
|
||||
typeface = createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE,
|
||||
RESOLVE_BY_FONT_TABLE);
|
||||
sDynamicTypefaceCache.put(key, typeface);
|
||||
return typeface;
|
||||
} else {
|
||||
@ -1037,7 +1050,8 @@ public class Typeface {
|
||||
fontFamily.allowUnsupportedFont();
|
||||
fontFamily.freeze();
|
||||
FontFamily[] families = { fontFamily };
|
||||
return createFromFamiliesWithDefault(families);
|
||||
return createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE,
|
||||
RESOLVE_BY_FONT_TABLE);
|
||||
} else {
|
||||
fontFamily.abortCreation();
|
||||
}
|
||||
@ -1055,16 +1069,25 @@ public class Typeface {
|
||||
for (int i = 0; i < families.length; i++) {
|
||||
ptrArray[i] = families[i].mNativePtr;
|
||||
}
|
||||
return new Typeface(nativeCreateFromArray(ptrArray));
|
||||
return new Typeface(nativeCreateFromArray(
|
||||
ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new typeface from an array of font families, including
|
||||
* also the font families in the fallback list.
|
||||
*
|
||||
* @param weight the weight for this family. {@link RESOLVE_BY_FONT_TABLE} can be used. In that
|
||||
* case, the table information in the first family's font is used. If the first
|
||||
* family has multiple fonts, the closest to the regular weight and upright font
|
||||
* is used.
|
||||
* @param italic the italic information for this family. {@link RESOLVE_BY_FONT_TABLE} can be
|
||||
* used. In that case, the table information in the first family's font is used.
|
||||
* If the first family has multiple fonts, the closest to the regular weight and
|
||||
* upright font is used.
|
||||
* @param families array of font families
|
||||
*/
|
||||
private static Typeface createFromFamiliesWithDefault(FontFamily[] families) {
|
||||
private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
|
||||
int weight, int italic) {
|
||||
long[] ptrArray = new long[families.length + sFallbackFonts.length];
|
||||
for (int i = 0; i < families.length; i++) {
|
||||
ptrArray[i] = families[i].mNativePtr;
|
||||
@ -1072,7 +1095,7 @@ public class Typeface {
|
||||
for (int i = 0; i < sFallbackFonts.length; i++) {
|
||||
ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr;
|
||||
}
|
||||
return new Typeface(nativeCreateFromArray(ptrArray));
|
||||
return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
|
||||
}
|
||||
|
||||
// don't allow clients to call this directly
|
||||
@ -1155,7 +1178,8 @@ public class Typeface {
|
||||
} else {
|
||||
FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath);
|
||||
FontFamily[] families = { fontFamily };
|
||||
typeface = Typeface.createFromFamiliesWithDefault(families);
|
||||
typeface = Typeface.createFromFamiliesWithDefault(families,
|
||||
RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
|
||||
}
|
||||
systemFonts.put(f.getName(), typeface);
|
||||
}
|
||||
@ -1262,7 +1286,7 @@ public class Typeface {
|
||||
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 long nativeCreateFromArray(long[] familyArray, int weight, int italic);
|
||||
private static native void nativeSetDefault(long native_instance);
|
||||
private static native int[] nativeGetSupportedAxes(long native_instance);
|
||||
}
|
||||
|
@ -39,14 +39,22 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
// Resolve the 1..9 weight based on base weight and bold flag
|
||||
// This indicates that the passed information should be resolved by OS/2 table.
|
||||
// This value must be the same as the android.graphics.Typeface$Builder.RESOLVE_BY_FONT_TABLE.
|
||||
constexpr int RESOLVE_BY_FONT_TABLE = -1;
|
||||
|
||||
// Resolve the 1..10 weight based on base weight and bold flag
|
||||
static void resolveStyle(Typeface* typeface) {
|
||||
int weight = typeface->fBaseWeight / 100;
|
||||
// TODO: Better to use raw base weight value for font selection instead of dividing by 100.
|
||||
int weight = (typeface->fBaseWeight + 50) / 100;
|
||||
if (typeface->fSkiaStyle & SkTypeface::kBold) {
|
||||
weight += 3;
|
||||
}
|
||||
if (weight > 9) {
|
||||
weight = 9;
|
||||
if (weight > 10) {
|
||||
weight = 10;
|
||||
}
|
||||
if (weight < 1) {
|
||||
weight = 1;
|
||||
}
|
||||
bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
|
||||
typeface->fStyle = minikin::FontStyle(weight, italic);
|
||||
@ -115,26 +123,50 @@ Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
|
||||
}
|
||||
|
||||
Typeface* Typeface::createFromFamilies(
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>>&& families) {
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
|
||||
int weight, int italic) {
|
||||
Typeface* result = new Typeface;
|
||||
result->fFontCollection.reset(new minikin::FontCollection(families));
|
||||
if (families.empty()) {
|
||||
ALOGW("createFromFamilies creating empty collection");
|
||||
result->fSkiaStyle = SkTypeface::kNormal;
|
||||
} else {
|
||||
|
||||
if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) {
|
||||
int weightFromFont;
|
||||
bool italicFromFont;
|
||||
|
||||
const minikin::FontStyle defaultStyle;
|
||||
const std::shared_ptr<minikin::FontFamily>& firstFamily = families[0];
|
||||
const minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
|
||||
const minikin::MinikinFont* mf =
|
||||
families.empty() ? nullptr : families[0]->getClosestMatch(defaultStyle).font;
|
||||
if (mf != nullptr) {
|
||||
SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
|
||||
// TODO: probably better to query more precise style from family, will be important
|
||||
// when we open up API to access 100..900 weights
|
||||
result->fSkiaStyle = skTypeface->style();
|
||||
const SkFontStyle& style = skTypeface->fontStyle();
|
||||
weightFromFont = style.weight();
|
||||
italicFromFont = style.slant() != SkFontStyle::kUpright_Slant;
|
||||
} else {
|
||||
result->fSkiaStyle = SkTypeface::kNormal;
|
||||
// We can't obtain any information from fonts. Just use default values.
|
||||
weightFromFont = SkFontStyle::kNormal_Weight;
|
||||
italicFromFont = false;
|
||||
}
|
||||
|
||||
if (weight == RESOLVE_BY_FONT_TABLE) {
|
||||
weight = weightFromFont;
|
||||
}
|
||||
if (italic == RESOLVE_BY_FONT_TABLE) {
|
||||
italic = italicFromFont? 1 : 0;
|
||||
}
|
||||
}
|
||||
result->fBaseWeight = 400;
|
||||
|
||||
// Sanitize the invalid value passed from public API.
|
||||
if (weight < 0) {
|
||||
weight = SkFontStyle::kNormal_Weight;
|
||||
}
|
||||
|
||||
result->fBaseWeight = weight;
|
||||
// This bold detection comes from SkTypefae.h
|
||||
const bool isBold = weight >= SkFontStyle::kSemiBold_Weight;
|
||||
const bool isItalic = italic == 1;
|
||||
// TODO: remove fSkiaStyle
|
||||
result->fSkiaStyle = isBold ?
|
||||
(isItalic ? SkTypeface::kBoldItalic : SkTypeface::kBold) :
|
||||
(isItalic ? SkTypeface::kItalic : SkTypeface::kNormal);
|
||||
resolveStyle(result);
|
||||
return result;
|
||||
}
|
||||
@ -165,7 +197,7 @@ void Typeface::setRobotoTypefaceForTest() {
|
||||
Typeface* hwTypeface = new Typeface();
|
||||
hwTypeface->fFontCollection = collection;
|
||||
hwTypeface->fSkiaStyle = SkTypeface::kNormal;
|
||||
hwTypeface->fBaseWeight = 400;
|
||||
hwTypeface->fBaseWeight = SkFontStyle::kSemiBold_Weight;
|
||||
hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);
|
||||
|
||||
Typeface::setDefault(hwTypeface);
|
||||
|
@ -50,7 +50,8 @@ struct ANDROID_API Typeface {
|
||||
static Typeface* createWeightAlias(Typeface* src, int baseweight);
|
||||
|
||||
static Typeface* createFromFamilies(
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>>&& families);
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
|
||||
int weight, int italic);
|
||||
|
||||
static void setDefault(Typeface* face);
|
||||
|
||||
|
Reference in New Issue
Block a user