OSDN Git Service

Fix unit tests
authorJohn Reck <jreck@google.com>
Fri, 11 Nov 2016 22:09:09 +0000 (14:09 -0800)
committerJohn Reck <jreck@google.com>
Fri, 11 Nov 2016 22:09:09 +0000 (14:09 -0800)
This is a partial revert of e2179925df2ce174d81dd6f7abae626cc859ce00
with the TODO comment replaced with why this can happen.

Test: Ran hwui's unit tests
Change-Id: I0d35eef773a401585bb8e75415da66de5aeb27d1

libs/hwui/hwui/Typeface.cpp

index 50bc6c3..59b1185 100644 (file)
@@ -49,10 +49,60 @@ 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. This happens if HWUI is used outside of zygote/app_process.
+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) {
-    LOG_ALWAYS_FATAL_IF(gDefaultTypeface == nullptr);
-    return src == nullptr ? gDefaultTypeface : src;
+    if (src == NULL) {
+        pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
+        return gDefaultTypeface;
+    } else {
+        return src;
+    }
 }
 
 Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {