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

Commit e2179925 authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Make sure the Typeface is loaded before calling measureText.

This is a clean up CL by resolving TODO in hwui/Typeface.cpp

Usually Typeface is listed in preloaded-classes and loaded during Zygote
initialization. However, on some devices, class preloading is disabled.
Paint.measureText can not be called before Typeface static initializer
and it may not load Typeface class.

To ensure that the font preloading happens in ZygoteInit even on such
devices, refer Typeface.DEFAULT static field in TextView.preloadFontCache
in TextView which also happens during zygote initialization.

Bug: 32374752
Test: Manually done
Change-Id: I773c154671c170bebad3aa0f9c04eee5a664b849
parent 4e55f8a4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -672,6 +672,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    public static void preloadFontCache() {
        Paint p = new Paint();
        p.setAntiAlias(true);
        // Ensure that the Typeface is loaded here.
        // Typically, Typeface is preloaded by zygote but not on all devices, e.g. Android Auto.
        // So, sets Typeface.DEFAULT explicitly here for ensuring that the Typeface is loaded here
        // since Paint.measureText can not be called without Typeface static initializer.
        p.setTypeface(Typeface.DEFAULT);
        // We don't care about the result, just the side-effect of measuring.
        p.measureText("H");
    }
+2 −54
Original line number Diff line number Diff line
@@ -49,62 +49,10 @@ static void resolveStyle(Typeface* typeface) {
}

Typeface* gDefaultTypeface = NULL;
pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;

// This installs a default typeface (from a hardcoded path) that allows
// layouts to work (not crash on null pointer) before the default
// typeface is set.
// TODO: investigate why layouts are being created before Typeface.java
// class initialization.
static minikin::FontCollection *makeFontCollection() {
    std::vector<minikin::FontFamily *>typefaces;
    const char *fns[] = {
        "/system/fonts/Roboto-Regular.ttf",
    };

    minikin::FontFamily *family = new minikin::FontFamily();
    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
        const char *fn = fns[i];
        ALOGD("makeFontCollection adding %s", fn);
        sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn);
        if (skFace != NULL) {
            // TODO: might be a nice optimization to get access to the underlying font
            // data, but would require us opening the file ourselves and passing that
            // to the appropriate Create method of SkTypeface.
            minikin::MinikinFont *font = new MinikinFontSkia(std::move(skFace), NULL, 0, 0);
            family->addFont(font);
            font->Unref();
        } else {
            ALOGE("failed to create font %s", fn);
        }
    }
    typefaces.push_back(family);

    minikin::FontCollection *result = new minikin::FontCollection(typefaces);
    family->Unref();
    return result;
}

static void getDefaultTypefaceOnce() {
  minikin::Layout::init();
    if (gDefaultTypeface == NULL) {
        // We expect the client to set a default typeface, but provide a
        // default so we can make progress before that happens.
        gDefaultTypeface = new Typeface;
        gDefaultTypeface->fFontCollection = makeFontCollection();
        gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
        gDefaultTypeface->fBaseWeight = 400;
        resolveStyle(gDefaultTypeface);
    }
}

Typeface* Typeface::resolveDefault(Typeface* src) {
    if (src == NULL) {
        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
        return gDefaultTypeface;
    } else {
        return src;
    }
    LOG_ALWAYS_FATAL_IF(gDefaultTypeface == nullptr);
    return src == nullptr ? gDefaultTypeface : src;
}

Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {