Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 117cbebe authored by Raph Levien's avatar Raph Levien
Browse files

New weight-aware font config

Parse new fonts.xml config file, and resolve weight selection based on
the base weight of the font (as defined by a weight alias specified in
the config file) and the requested bold flag. This change improves the
appearance of bold spans for alternate weights of Roboto.

In addition, this patch enables weight selection for fallback fonts.
For example, if an additional font with a weight of 100 is added to the
Hebrew font family in the fallback list, then requesting
"sans-serif-thin" would select that font for Hebrew text.

Bug: 14538154
Change-Id: I99a04fad4f7bf01c75726e760d42735dd9003496
parent 0db4f35e
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -62,10 +62,26 @@ static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr,
        ALOGE("addFont failed to create font %s", str.c_str());
        return false;
    }
    FontFamily* fontFamily = (FontFamily*)familyPtr;
    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
    return addSkTypeface(fontFamily, face);
}

static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr,
        jstring path, jint weight, jboolean isItalic) {
    NPE_CHECK_RETURN_ZERO(env, path);
    ScopedUtfChars str(env, path);
    SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
    if (face == NULL) {
        ALOGE("addFont failed to create font %s", str.c_str());
        return false;
    }
    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
    MinikinFont* minikinFont = new MinikinFontSkia(face);
    fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic));
    minikinFont->Unref();
    return true;
}

static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
        jobject jassetMgr, jstring jpath) {
    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
@@ -92,7 +108,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt
        ALOGE("addFontFromAsset failed to create font %s", str.c_str());
        return false;
    }
    FontFamily* fontFamily = (FontFamily*)familyPtr;
    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
    return addSkTypeface(fontFamily, face);
}

@@ -102,6 +118,7 @@ static JNINativeMethod gFontFamilyMethods[] = {
    { "nCreateFamily",         "(Ljava/lang/String;I)J", (void*)FontFamily_create },
    { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
    { "nAddFont",              "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
    { "nAddFontWeightStyle",   "(JLjava/lang/String;IZ)Z", (void*)FontFamily_addFontWeightStyle },
    { "nAddFontFromAsset",     "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
                                           (void*)FontFamily_addFontFromAsset },
};
+7 −0
Original line number Diff line number Diff line
@@ -41,6 +41,12 @@ static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandl
    return reinterpret_cast<jlong>(face);
}

static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
    TypefaceImpl* family = reinterpret_cast<TypefaceImpl*>(familyHandle);
    TypefaceImpl* face = TypefaceImpl_createWeightAlias(family, weight);
    return reinterpret_cast<jlong>(face);
}

static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
    TypefaceImpl* face = reinterpret_cast<TypefaceImpl*>(faceHandle);
    TypefaceImpl_unref(face);
@@ -65,6 +71,7 @@ static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {

static JNINativeMethod gTypefaceMethods[] = {
    { "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
    { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
    { "nativeUnref",              "(J)V",  (void*)Typeface_unref },
    { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
    { "nativeCreateFromArray",    "([J)J",
+32 −32
Original line number Diff line number Diff line
@@ -39,14 +39,17 @@

namespace android {

// Any weight greater than or equal to this is considered "bold" for
// legacy API.
static const int kBoldThreshold = 6;

static FontStyle styleFromSkiaStyle(SkTypeface::Style skiaStyle) {
    int weight = (skiaStyle & SkTypeface::kBold) != 0 ? 7 : 4;
    bool italic = (skiaStyle & SkTypeface::kItalic) != 0;
    return FontStyle(weight, italic);
// Resolve the 1..9 weight based on base weight and bold flag
static void resolveStyle(TypefaceImpl* typeface) {
    int weight = typeface->fBaseWeight / 100;
    if (typeface->fSkiaStyle & SkTypeface::kBold) {
        weight += 3;
    }
    if (weight > 9) {
        weight = 9;
    }
    bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
    typeface->fStyle = FontStyle(weight, italic);
}

TypefaceImpl* gDefaultTypeface = NULL;
@@ -90,7 +93,9 @@ static void getDefaultTypefaceOnce() {
        // default so we can make progress before that happens.
        gDefaultTypeface = new TypefaceImpl;
        gDefaultTypeface->fFontCollection = makeFontCollection();
        gDefaultTypeface->fStyle = FontStyle();
        gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
        gDefaultTypeface->fBaseWeight = 400;
        resolveStyle(gDefaultTypeface);
    }
}

@@ -109,25 +114,23 @@ TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Sty
    if (result != 0) {
        result->fFontCollection = resolvedFace->fFontCollection;
        result->fFontCollection->Ref();
        result->fStyle = styleFromSkiaStyle(style);
        result->fSkiaStyle = style;
        result->fBaseWeight = resolvedFace->fBaseWeight;
        resolveStyle(result);
    }
    return result;
}

static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
    if (typeface == NULL) {
        return NULL;
    }
    MinikinFont* minikinFont = new MinikinFontSkia(typeface);
    std::vector<FontFamily *> typefaces;
    FontFamily* family = new FontFamily();
    family->addFont(minikinFont);
    minikinFont->Unref();
    typefaces.push_back(family);
TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
    TypefaceImpl* result = new TypefaceImpl;
    result->fFontCollection = new FontCollection(typefaces);
    family->Unref();
    result->fStyle = FontStyle();  // TODO: improve
    if (result != 0) {
        result->fFontCollection = resolvedFace->fFontCollection;
        result->fFontCollection->Ref();
        result->fSkiaStyle = resolvedFace->fSkiaStyle;
        result->fBaseWeight = weight;
        resolveStyle(result);
    }
    return result;
}

@@ -141,7 +144,7 @@ TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size
    result->fFontCollection = new FontCollection(familyVec);
    if (size == 0) {
        ALOGW("createFromFamilies creating empty collection");
        result->fStyle = FontStyle();
        result->fSkiaStyle = SkTypeface::kNormal;
    } else {
        const FontStyle defaultStyle;
        FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
@@ -150,11 +153,13 @@ TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size
            SkTypeface* skTypeface = reinterpret_cast<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->fStyle = styleFromSkiaStyle(skTypeface->style());
            result->fSkiaStyle = skTypeface->style();
        } else {
            result->fStyle = defaultStyle;
            result->fSkiaStyle = SkTypeface::kNormal;
        }
    }
    result->fBaseWeight = 400;
    resolveStyle(result);
    return result;
}

@@ -166,12 +171,7 @@ void TypefaceImpl_unref(TypefaceImpl* face) {
}

int TypefaceImpl_getStyle(TypefaceImpl* face) {
    FontStyle style = face->fStyle;
    int result = style.getItalic() ? SkTypeface::kItalic : 0;
    if (style.getWeight() >= kBoldThreshold) {
        result |= SkTypeface::kBold;
    }
    return result;
    return face->fSkiaStyle;
}

void TypefaceImpl_setDefault(TypefaceImpl* face) {
+9 −0
Original line number Diff line number Diff line
@@ -28,6 +28,13 @@ namespace android {

struct TypefaceImpl {
    FontCollection *fFontCollection;

    // style used for constructing and querying Typeface objects
    SkTypeface::Style fSkiaStyle;
    // base weight in CSS-style units, 100..900
    int fBaseWeight;

    // resolved style actually used for rendering
    FontStyle fStyle;
};

@@ -41,6 +48,8 @@ TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src);

TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style);

TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int baseweight);

// When we remove the USE_MINIKIN ifdef, probably a good idea to move the casting
// (from jlong to FontFamily*) to the caller in Typeface.cpp.
TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size);
+4 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    NOTE: this file is the legacy format, for compatibility with apps. The new,
    more flexible format is fonts.xml. Please keep the two in sync until the legacy
    format can be fully removed.

    Fallback Fonts

    This file specifies the fonts, and the priority order, that will be searched for any
Loading