From e2179925df2ce174d81dd6f7abae626cc859ce00 Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Thu, 27 Oct 2016 18:06:39 +0900 Subject: [PATCH] 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 --- core/java/android/widget/TextView.java | 5 +++ libs/hwui/hwui/Typeface.cpp | 56 +------------------------- 2 files changed, 7 insertions(+), 54 deletions(-) diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 2f9c97b38afa2..9c48cf8e88060 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -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"); } diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index 33ee108430e0f..50bc6c383a0fe 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -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::vectortypefaces; - 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 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) {