From 0b5c6430442067cae8f01e17b2deb405468abe6a Mon Sep 17 00:00:00 2001 From: John Reck Date: Fri, 11 Nov 2016 14:09:09 -0800 Subject: [PATCH] Fix unit tests 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 | 54 +++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index 50bc6c383a0fe..59b1185d90057 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -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::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) { - 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) {