From 8b585499667b5c18a1e11594dad53d2703ef14cb Mon Sep 17 00:00:00 2001 From: Bart Sears Date: Tue, 22 Dec 2015 09:06:03 +0000 Subject: Revert "Save all kind of script tags into FontLanguage." This reverts commit 5e995fb850c2b32631914c3815dfb421855fba9b. Change-Id: I761e0e41906742fbe3d3ac34170af3101e18042a --- include/minikin/FontFamily.h | 64 ++++++++- libs/minikin/Android.mk | 1 - libs/minikin/FontCollection.cpp | 10 +- libs/minikin/FontFamily.cpp | 120 ++++++++++++++++- libs/minikin/FontLanguage.cpp | 135 ------------------- libs/minikin/FontLanguage.h | 89 ------------- libs/minikin/FontLanguageListCache.cpp | 90 +------------ libs/minikin/FontLanguageListCache.h | 1 - libs/minikin/Layout.cpp | 13 +- tests/FontCollectionItemizeTest.cpp | 32 ++--- tests/FontFamilyTest.cpp | 232 ++++----------------------------- tests/FontLanguageListCacheTest.cpp | 18 +-- tests/FontTestUtils.cpp | 7 +- tests/ICUTestBase.h | 52 -------- 14 files changed, 225 insertions(+), 639 deletions(-) delete mode 100644 libs/minikin/FontLanguage.cpp delete mode 100644 libs/minikin/FontLanguage.h delete mode 100644 tests/ICUTestBase.h diff --git a/include/minikin/FontFamily.h b/include/minikin/FontFamily.h index aa2e0ac..00130e6 100644 --- a/include/minikin/FontFamily.h +++ b/include/minikin/FontFamily.h @@ -30,6 +30,62 @@ namespace android { class MinikinFont; +// FontLanguage is a compact representation of a bcp-47 language tag. It +// does not capture all possible information, only what directly affects +// font rendering. +class FontLanguage { + friend class FontStyle; + friend class FontLanguages; +public: + FontLanguage() : mBits(0) { } + + // Parse from string + FontLanguage(const char* buf, size_t size); + + bool operator==(const FontLanguage other) const { + return mBits != kUnsupportedLanguage && mBits == other.mBits; + } + operator bool() const { return mBits != 0; } + + bool isUnsupported() const { return mBits == kUnsupportedLanguage; } + bool hasEmojiFlag() const { return isUnsupported() ? false : (mBits & kEmojiFlag); } + + std::string getString() const; + + // 0 = no match, 1 = language matches + int match(const FontLanguage other) const; + +private: + explicit FontLanguage(uint32_t bits) : mBits(bits) { } + + uint32_t bits() const { return mBits; } + + static const uint32_t kUnsupportedLanguage = 0xFFFFFFFFu; + static const uint32_t kBaseLangMask = 0xFFFFFFu; + static const uint32_t kHansFlag = 1u << 24; + static const uint32_t kHantFlag = 1u << 25; + static const uint32_t kEmojiFlag = 1u << 26; + static const uint32_t kScriptMask = kHansFlag | kHantFlag | kEmojiFlag; + uint32_t mBits; +}; + +// A list of zero or more instances of FontLanguage, in the order of +// preference. Used for further resolution of rendering results. +class FontLanguages { +public: + FontLanguages() { mLangs.clear(); } + + // Parse from string, which is a comma-separated list of languages + FontLanguages(const char* buf, size_t size); + + const FontLanguage& operator[](size_t index) const { return mLangs.at(index); } + + size_t size() const { return mLangs.size(); } + +private: + std::vector mLangs; +}; + // FontStyle represents all style information needed to select an actual font // from a collection. The implementation is packed into two 32-bit words // so it can be efficiently copied, embedded in other objects, etc. @@ -102,9 +158,7 @@ class FontFamily : public MinikinRefCounted { public: FontFamily() : mHbFont(nullptr) { } - FontFamily(int variant); - - FontFamily(uint32_t langId, int variant) : mLangId(langId), mVariant(variant), mHbFont(nullptr) { + FontFamily(FontLanguage lang, int variant) : mLang(lang), mVariant(variant), mHbFont(nullptr) { } ~FontFamily(); @@ -115,7 +169,7 @@ public: void addFont(MinikinFont* typeface, FontStyle style); FakedFont getClosestMatch(FontStyle style) const; - uint32_t langId() const { return mLangId; } + FontLanguage lang() const { return mLang; } int variant() const { return mVariant; } // API's for enumerating the fonts in a family. These don't guarantee any particular order @@ -146,7 +200,7 @@ private: MinikinFont* typeface; FontStyle style; }; - uint32_t mLangId; + FontLanguage mLang; int mVariant; std::vector mFonts; diff --git a/libs/minikin/Android.mk b/libs/minikin/Android.mk index 42fdca3..4c945a6 100644 --- a/libs/minikin/Android.mk +++ b/libs/minikin/Android.mk @@ -21,7 +21,6 @@ minikin_src_files := \ CmapCoverage.cpp \ FontCollection.cpp \ FontFamily.cpp \ - FontLanguage.cpp \ FontLanguageListCache.cpp \ GraphemeBreak.cpp \ HbFaceCache.cpp \ diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp index 62c7031..bba2ef9 100644 --- a/libs/minikin/FontCollection.cpp +++ b/libs/minikin/FontCollection.cpp @@ -22,7 +22,6 @@ #include "unicode/unistr.h" #include "unicode/unorm2.h" -#include "FontLanguage.h" #include "FontLanguageListCache.h" #include "MinikinInternal.h" #include @@ -151,17 +150,14 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, // always use it. return family; } - - // TODO use all language in the list. - FontLanguage fontLang = FontLanguageListCache::getById(family->langId())[0]; - int score = lang.match(fontLang) * 2; + int score = lang.match(family->lang()) * 2; if (family->variant() == 0 || family->variant() == variant) { score++; } if (hasVSGlyph) { score += 8; - } else if (((vs == 0xFE0F) && fontLang.hasEmojiFlag()) || - ((vs == 0xFE0E) && !fontLang.hasEmojiFlag())) { + } else if (((vs == 0xFE0F) && family->lang().hasEmojiFlag()) || + ((vs == 0xFE0E) && !family->lang().hasEmojiFlag())) { score += 4; } if (score > bestScore) { diff --git a/libs/minikin/FontFamily.cpp b/libs/minikin/FontFamily.cpp index 1405789..7639831 100644 --- a/libs/minikin/FontFamily.cpp +++ b/libs/minikin/FontFamily.cpp @@ -16,6 +16,8 @@ #define LOG_TAG "Minikin" +#include + #include #include #include @@ -26,7 +28,6 @@ #include -#include "FontLanguage.h" #include "FontLanguageListCache.h" #include "HbFaceCache.h" #include "MinikinInternal.h" @@ -40,6 +41,117 @@ using std::vector; namespace android { +// Parse bcp-47 language identifier into internal structure +FontLanguage::FontLanguage(const char* buf, size_t size) { + uint32_t bits = 0; + size_t i; + for (i = 0; i < size; i++) { + uint16_t c = buf[i]; + if (c == '-' || c == '_') break; + } + if (i == 2) { + bits = uint8_t(buf[0]) | (uint8_t(buf[1]) << 8); + } else if (i == 3) { + bits = uint8_t(buf[0]) | (uint8_t(buf[1]) << 8) | (uint8_t(buf[2]) << 16); + } else { + mBits = kUnsupportedLanguage; + // We don't understand anything other than two-letter or three-letter + // language codes, so we skip parsing the rest of the string. + return; + } + size_t next; + for (i++; i < size; i = next + 1) { + for (next = i; next < size; next++) { + uint16_t c = buf[next]; + if (c == '-' || c == '_') break; + } + if (next - i == 4) { + if (buf[i] == 'H' && buf[i+1] == 'a' && buf[i+2] == 'n') { + if (buf[i+3] == 's') { + bits |= kHansFlag; + } else if (buf[i+3] == 't') { + bits |= kHantFlag; + } + } else if (buf[i] == 'Q' && buf[i+1] == 'a' && buf[i+2] == 'a'&& buf[i+3] == 'e') { + bits |= kEmojiFlag; + } + } + // TODO: this might be a good place to infer script from country (zh_TW -> Hant), + // but perhaps it's up to the client to do that, before passing a string. + } + mBits = bits; +} + +std::string FontLanguage::getString() const { + if (mBits == kUnsupportedLanguage) { + return "und"; + } + char buf[16]; + size_t i = 0; + if (mBits & kBaseLangMask) { + buf[i++] = mBits & 0xFFu; + buf[i++] = (mBits >> 8) & 0xFFu; + char third_letter = (mBits >> 16) & 0xFFu; + if (third_letter != 0) buf[i++] = third_letter; + } + if (mBits & kScriptMask) { + if (!i) { + // This should not happen, but as it apparently has, we fill the language code part + // with "und". + buf[i++] = 'u'; + buf[i++] = 'n'; + buf[i++] = 'd'; + } + buf[i++] = '-'; + if (mBits & kEmojiFlag) { + buf[i++] = 'Q'; + buf[i++] = 'a'; + buf[i++] = 'a'; + buf[i++] = 'e'; + } else { + buf[i++] = 'H'; + buf[i++] = 'a'; + buf[i++] = 'n'; + buf[i++] = (mBits & kHansFlag) ? 's' : 't'; + } + } + return std::string(buf, i); +} + +int FontLanguage::match(const FontLanguage other) const { + return *this == other; +} + +FontLanguages::FontLanguages(const char* buf, size_t size) { + std::unordered_set seen; + mLangs.clear(); + const char* bufEnd = buf + size; + const char* lastStart = buf; + bool isLastLang = false; + while (true) { + const char* commaLoc = static_cast( + memchr(lastStart, ',', bufEnd - lastStart)); + if (commaLoc == NULL) { + commaLoc = bufEnd; + isLastLang = true; + } + FontLanguage lang(lastStart, commaLoc - lastStart); + if (isLastLang && mLangs.size() == 0) { + // Make sure the list has at least one member + mLangs.push_back(lang); + return; + } + uint32_t bits = lang.bits(); + if (bits != FontLanguage::kUnsupportedLanguage && seen.count(bits) == 0) { + mLangs.push_back(lang); + if (isLastLang) return; + seen.insert(bits); + } + if (isLastLang) return; + lastStart = commaLoc + 1; + } +} + FontStyle::FontStyle(int variant, int weight, bool italic) : FontStyle(FontLanguageListCache::kEmptyListId, variant, weight, italic) { } @@ -65,9 +177,6 @@ uint32_t FontStyle::pack(int variant, int weight, bool italic) { return (weight & kWeightMask) | (italic ? kItalicMask : 0) | (variant << kVariantShift); } -FontFamily::FontFamily(int variant) : FontFamily(FontLanguageListCache::kEmptyListId, variant) { -} - FontFamily::~FontFamily() { for (size_t i = 0; i < mFonts.size(); i++) { mFonts[i].typeface->UnrefLocked(); @@ -101,8 +210,7 @@ void FontFamily::addFont(MinikinFont* typeface, FontStyle style) { addFontLocked(typeface, style); } -void FontFamily::addFontLocked(MinikinFont* typeface, FontStyle style) { - typeface->RefLocked(); +void FontFamily::addFontLocked(MinikinFont* typeface, FontStyle style) { typeface->RefLocked(); mFonts.push_back(Font(typeface, style)); mCoverageValid = false; } diff --git a/libs/minikin/FontLanguage.cpp b/libs/minikin/FontLanguage.cpp deleted file mode 100644 index 3c12e06..0000000 --- a/libs/minikin/FontLanguage.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "Minikin" - -#include "FontLanguage.h" - -#include -#include - -namespace android { - -#define SCRIPT_TAG(c1, c2, c3, c4) \ - ((uint32_t)(c1)) << 24 | ((uint32_t)(c2)) << 16 | ((uint32_t)(c3)) << 8 | ((uint32_t)(c4)) - -// Parse BCP 47 language identifier into internal structure -FontLanguage::FontLanguage(const char* buf, size_t length) : FontLanguage() { - size_t i; - for (i = 0; i < length; i++) { - char c = buf[i]; - if (c == '-' || c == '_') break; - } - if (i == 2 || i == 3) { // only accept two or three letter language code. - mLanguage = buf[0] | (buf[1] << 8) | ((i == 3) ? (buf[2] << 16) : 0); - } else { - // We don't understand anything other than two-letter or three-letter - // language codes, so we skip parsing the rest of the string. - mLanguage = 0ul; - return; - } - - size_t next; - for (i++; i < length; i = next + 1) { - for (next = i; next < length; next++) { - char c = buf[next]; - if (c == '-' || c == '_') break; - } - if (next - i == 4 && 'A' <= buf[i] && buf[i] <= 'Z') { - mScript = SCRIPT_TAG(buf[i], buf[i + 1], buf[i + 2], buf[i + 3]); - } - } - - mSubScriptBits = scriptToSubScriptBits(mScript); -} - -//static -uint8_t FontLanguage::scriptToSubScriptBits(uint32_t script) { - uint8_t subScriptBits = 0u; - switch (script) { - case SCRIPT_TAG('H', 'a', 'n', 'g'): - subScriptBits = kHangulFlag; - break; - case SCRIPT_TAG('H', 'a', 'n', 'i'): - subScriptBits = kHanFlag; - break; - case SCRIPT_TAG('H', 'a', 'n', 's'): - subScriptBits = kHanFlag | kSimplifiedChineseFlag; - break; - case SCRIPT_TAG('H', 'a', 'n', 't'): - subScriptBits = kHanFlag | kTraditionalChineseFlag; - break; - case SCRIPT_TAG('H', 'i', 'r', 'a'): - subScriptBits = kHiraganaFlag; - break; - case SCRIPT_TAG('H', 'r', 'k', 't'): - subScriptBits = kKatakanaFlag | kHiraganaFlag; - break; - case SCRIPT_TAG('J', 'p', 'a', 'n'): - subScriptBits = kHanFlag | kKatakanaFlag | kHiraganaFlag; - break; - case SCRIPT_TAG('K', 'a', 'n', 'a'): - subScriptBits = kKatakanaFlag; - break; - case SCRIPT_TAG('K', 'o', 'r', 'e'): - subScriptBits = kHanFlag | kHangulFlag; - break; - case SCRIPT_TAG('Q', 'a', 'a', 'e'): - subScriptBits = kEmojiFlag; - break; - } - return subScriptBits; -} - -std::string FontLanguage::getString() const { - if (mLanguage == 0ul) { - return "und"; - } - char buf[16]; - size_t i = 0; - buf[i++] = mLanguage & 0xFF ; - buf[i++] = (mLanguage >> 8) & 0xFF; - char third_letter = (mLanguage >> 16) & 0xFF; - if (third_letter != 0) buf[i++] = third_letter; - if (mScript != 0) { - buf[i++] = '-'; - buf[i++] = (mScript >> 24) & 0xFFu; - buf[i++] = (mScript >> 16) & 0xFFu; - buf[i++] = (mScript >> 8) & 0xFFu; - buf[i++] = mScript & 0xFFu; - } - return std::string(buf, i); -} - -bool FontLanguage::isEqualScript(const FontLanguage other) const { - return other.mScript == mScript; -} - -bool FontLanguage::supportsHbScript(hb_script_t script) const { - static_assert(SCRIPT_TAG('J', 'p', 'a', 'n') == HB_TAG('J', 'p', 'a', 'n'), - "The Minikin script and HarfBuzz hb_script_t have different encodings."); - if (script == mScript) return true; - uint8_t requestedBits = scriptToSubScriptBits(script); - return requestedBits != 0 && (mSubScriptBits & requestedBits) == requestedBits; -} - -int FontLanguage::match(const FontLanguage other) const { - // TODO: Use script for matching. - return *this == other; -} - -#undef SCRIPT_TAG -} // namespace android diff --git a/libs/minikin/FontLanguage.h b/libs/minikin/FontLanguage.h deleted file mode 100644 index abe7d13..0000000 --- a/libs/minikin/FontLanguage.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MINIKIN_FONT_LANGUAGE_H -#define MINIKIN_FONT_LANGUAGE_H - -#include -#include - -#include - -namespace android { - -// FontLanguage is a compact representation of a BCP 47 language tag. It -// does not capture all possible information, only what directly affects -// font rendering. -struct FontLanguage { -public: - // Default constructor creates the unsupported language. - FontLanguage() : mScript(0ul), mLanguage(0ul), mSubScriptBits(0ul) {} - - // Parse from string - FontLanguage(const char* buf, size_t length); - - bool operator==(const FontLanguage other) const { - return !isUnsupported() && isEqualScript(other) && isEqualLanguage(other); - } - - bool operator!=(const FontLanguage other) const { - return !(*this == other); - } - - bool isUnsupported() const { return mLanguage == 0ul; } - bool hasEmojiFlag() const { return mSubScriptBits & kEmojiFlag; } - - bool isEqualLanguage(const FontLanguage other) const { return mLanguage == other.mLanguage; } - bool isEqualScript(const FontLanguage other) const; - - // Returns true if this script supports the given script. For example, ja-Jpan supports Hira, - // ja-Hira doesn't support Jpan. - bool supportsHbScript(hb_script_t script) const; - - std::string getString() const; - - // 0 = no match, 1 = language matches - int match(const FontLanguage other) const; - - uint64_t getIdentifier() const { return (uint64_t)mScript << 32 | (uint64_t)mLanguage; } - -private: - // ISO 15924 compliant script code. The 4 chars script code are packed into a 32 bit integer. - uint32_t mScript; - - // ISO 639-1 or ISO 639-2 compliant language code. - // The two or three letter language code is packed into 32 bit integer. - // mLanguage = 0 means the FontLanguage is unsupported. - uint32_t mLanguage; - - // For faster comparing, use 7 bits for specific scripts. - static const uint8_t kEmojiFlag = 1u; - static const uint8_t kHanFlag = 1u << 1; - static const uint8_t kHangulFlag = 1u << 2; - static const uint8_t kHiraganaFlag = 1u << 3; - static const uint8_t kKatakanaFlag = 1u << 4; - static const uint8_t kSimplifiedChineseFlag = 1u << 5; - static const uint8_t kTraditionalChineseFlag = 1u << 6; - uint8_t mSubScriptBits; - - static uint8_t scriptToSubScriptBits(uint32_t script); -}; - -typedef std::vector FontLanguages; - -} // namespace android - -#endif // MINIKIN_FONT_LANGUAGE_H diff --git a/libs/minikin/FontLanguageListCache.cpp b/libs/minikin/FontLanguageListCache.cpp index 2d64998..e1c2343 100644 --- a/libs/minikin/FontLanguageListCache.cpp +++ b/libs/minikin/FontLanguageListCache.cpp @@ -19,92 +19,13 @@ #include "FontLanguageListCache.h" #include -#include -#include #include "MinikinInternal.h" -#include "FontLanguage.h" namespace android { const uint32_t FontLanguageListCache::kEmptyListId; -// Returns the text length of output. -static size_t toLanguageTag(char* output, size_t outSize, const std::string& locale) { - output[0] = '\0'; - if (locale.empty()) { - return 0; - } - - size_t outLength = 0; - UErrorCode uErr = U_ZERO_ERROR; - outLength = uloc_canonicalize(locale.c_str(), output, outSize, &uErr); - if (U_FAILURE(uErr)) { - // unable to build a proper language identifier - ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale.c_str(), u_errorName(uErr)); - output[0] = '\0'; - return 0; - } - - // Preserve "und" and "und-****" since uloc_addLikelySubtags changes "und" to "en-Latn-US". - if (strncmp(output, "und", 3) == 0 && - (outLength == 3 || (outLength == 8 && output[3] == '_'))) { - return outLength; - } - - char likelyChars[ULOC_FULLNAME_CAPACITY]; - uErr = U_ZERO_ERROR; - uloc_addLikelySubtags(output, likelyChars, ULOC_FULLNAME_CAPACITY, &uErr); - if (U_FAILURE(uErr)) { - // unable to build a proper language identifier - ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s", output, u_errorName(uErr)); - output[0] = '\0'; - return 0; - } - - uErr = U_ZERO_ERROR; - outLength = uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr); - if (U_FAILURE(uErr)) { - // unable to build a proper language identifier - ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars, u_errorName(uErr)); - output[0] = '\0'; - return 0; - } -#ifdef VERBOSE_DEBUG - ALOGD("ICU normalized '%s' to '%s'", locale.c_str(), output); -#endif - return outLength; -} - -static FontLanguages constructFontLanguages(const std::string& input) { - FontLanguages result; - size_t currentIdx = 0; - size_t commaLoc = 0; - char langTag[ULOC_FULLNAME_CAPACITY]; - std::unordered_set seen; - std::string locale(input.size(), 0); - - while ((commaLoc = input.find_first_of(',', currentIdx)) != std::string::npos) { - locale.assign(input, currentIdx, commaLoc - currentIdx); - currentIdx = commaLoc + 1; - size_t length = toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, locale); - FontLanguage lang(langTag, length); - uint64_t identifier = lang.getIdentifier(); - if (!lang.isUnsupported() && seen.count(identifier) == 0) { - result.push_back(lang); - seen.insert(identifier); - } - } - locale.assign(input, currentIdx, input.size() - currentIdx); - size_t length = toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, locale); - FontLanguage lang(langTag, length); - uint64_t identifier = lang.getIdentifier(); - if (!lang.isUnsupported() && seen.count(identifier) == 0) { - result.push_back(lang); - } - return result; -} - // static uint32_t FontLanguageListCache::getId(const std::string& languages) { FontLanguageListCache* inst = FontLanguageListCache::getInstance(); @@ -116,11 +37,7 @@ uint32_t FontLanguageListCache::getId(const std::string& languages) { // Given language list is not in cache. Insert it and return newly assigned ID. const uint32_t nextId = inst->mLanguageLists.size(); - FontLanguages fontLanguages = constructFontLanguages(languages); - if (fontLanguages.empty()) { - return kEmptyListId; - } - inst->mLanguageLists.push_back(fontLanguages); + inst->mLanguageLists.push_back(FontLanguages(languages.c_str(), languages.size())); inst->mLanguageListLookupTable.insert(std::make_pair(languages, nextId)); return nextId; } @@ -139,9 +56,8 @@ FontLanguageListCache* FontLanguageListCache::getInstance() { if (instance == nullptr) { instance = new FontLanguageListCache(); - // Insert an empty language list for mapping default language list to kEmptyListId. - // The default language list has only one FontLanguage and it is the unsupported language. - instance->mLanguageLists.push_back(FontLanguages({FontLanguage()})); + // Insert an empty language list for mapping empty language list to kEmptyListId. + instance->mLanguageLists.push_back(FontLanguages()); instance->mLanguageListLookupTable.insert(std::make_pair("", kEmptyListId)); } return instance; diff --git a/libs/minikin/FontLanguageListCache.h b/libs/minikin/FontLanguageListCache.h index c961882..7d627b5 100644 --- a/libs/minikin/FontLanguageListCache.h +++ b/libs/minikin/FontLanguageListCache.h @@ -20,7 +20,6 @@ #include #include -#include "FontLanguage.h" namespace android { diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp index 2e206a2..af5e6fe 100644 --- a/libs/minikin/Layout.cpp +++ b/libs/minikin/Layout.cpp @@ -34,7 +34,6 @@ #include #include -#include "FontLanguage.h" #include "FontLanguageListCache.h" #include "LayoutUtils.h" #include "HbFaceCache.h" @@ -747,15 +746,9 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t const FontLanguages& langList = FontLanguageListCache::getById(ctx->style.getLanguageListId()); if (langList.size() != 0) { - const FontLanguage* hbLanguage = &langList[0]; - for (size_t i = 0; i < langList.size(); ++i) { - if (langList[i].supportsHbScript(script)) { - hbLanguage = &langList[i]; - break; - } - } - hb_buffer_set_language(buffer, - hb_language_from_string(hbLanguage->getString().c_str(), -1)); + // TODO: use all languages in langList. + string lang = langList[0].getString(); + hb_buffer_set_language(buffer, hb_language_from_string(lang.c_str(), -1)); } hb_buffer_add_utf16(buffer, buf, bufSize, srunstart + start, srunend - srunstart); if (ctx->paint.hyphenEdit.hasHyphen() && srunend > srunstart) { diff --git a/tests/FontCollectionItemizeTest.cpp b/tests/FontCollectionItemizeTest.cpp index cf9b704..85d76af 100644 --- a/tests/FontCollectionItemizeTest.cpp +++ b/tests/FontCollectionItemizeTest.cpp @@ -16,9 +16,7 @@ #include -#include "FontLanguage.h" #include "FontTestUtils.h" -#include "ICUTestBase.h" #include "MinikinFontForTest.h" #include "UnicodeUtils.h" @@ -44,8 +42,6 @@ const char kColorEmojiFont[] = kTestFontDir "ColorEmojiFont.ttf"; const char kTextEmojiFont[] = kTestFontDir "TextEmojiFont.ttf"; const char kMixedEmojiFont[] = kTestFontDir "ColorTextMixedEmojiFont.ttf"; -typedef ICUTestBase FontCollectionItemizeTest; - // Utility function for calling itemize function. void itemize(FontCollection* collection, const char* str, FontStyle style, std::vector* result) { @@ -64,7 +60,7 @@ const std::string& getFontPath(const FontCollection::Run& run) { return ((MinikinFontForTest*)run.fakedFont.font)->fontPath(); } -TEST_F(FontCollectionItemizeTest, itemize_latin) { +TEST(FontCollectionItemizeTest, itemize_latin) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -134,7 +130,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) { EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); } -TEST_F(FontCollectionItemizeTest, itemize_emoji) { +TEST(FontCollectionItemizeTest, itemize_emoji) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -195,7 +191,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emoji) { EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic()); } -TEST_F(FontCollectionItemizeTest, itemize_non_latin) { +TEST(FontCollectionItemizeTest, itemize_non_latin) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -284,7 +280,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) { EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); } -TEST_F(FontCollectionItemizeTest, itemize_mixed) { +TEST(FontCollectionItemizeTest, itemize_mixed) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -323,7 +319,7 @@ TEST_F(FontCollectionItemizeTest, itemize_mixed) { EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeItalic()); } -TEST_F(FontCollectionItemizeTest, itemize_variationSelector) { +TEST(FontCollectionItemizeTest, itemize_variationSelector) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -462,7 +458,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) { EXPECT_EQ(kLatinFont, getFontPath(runs[0])); } -TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) { +TEST(FontCollectionItemizeTest, itemize_variationSelectorSupplement) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -587,7 +583,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) { EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0])); } -TEST_F(FontCollectionItemizeTest, itemize_no_crash) { +TEST(FontCollectionItemizeTest, itemize_no_crash) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -611,7 +607,7 @@ TEST_F(FontCollectionItemizeTest, itemize_no_crash) { itemize(collection.get(), "U+FE00 U+302D U+E0100", FontStyle(), &runs); } -TEST_F(FontCollectionItemizeTest, itemize_fakery) { +TEST(FontCollectionItemizeTest, itemize_fakery) { std::unique_ptr collection = getFontCollection(kTestFontDir, kItemizeFontXml); std::vector runs; @@ -651,18 +647,18 @@ TEST_F(FontCollectionItemizeTest, itemize_fakery) { EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic()); } -TEST_F(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) { +TEST(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) { // kVSTestFont supports U+717D U+FE02 but doesn't support U+717D. // kVSTestFont should be selected for U+717D U+FE02 even if it does not support the base code // point. const std::string kVSTestFont = kTestFontDir "VarioationSelectorTest-Regular.ttf"; std::vector families; - FontFamily* family1 = new FontFamily(android::VARIANT_DEFAULT); + FontFamily* family1 = new FontFamily(FontLanguage(), android::VARIANT_DEFAULT); family1->addFont(new MinikinFontForTest(kLatinFont)); families.push_back(family1); - FontFamily* family2 = new FontFamily(android::VARIANT_DEFAULT); + FontFamily* family2 = new FontFamily(FontLanguage(), android::VARIANT_DEFAULT); family2->addFont(new MinikinFontForTest(kVSTestFont)); families.push_back(family2); @@ -680,7 +676,7 @@ TEST_F(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) { family2->Unref(); } -TEST_F(FontCollectionItemizeTest, itemize_emojiSelection) { +TEST(FontCollectionItemizeTest, itemize_emojiSelection) { std::unique_ptr collection = getFontCollection(kTestFontDir, kEmojiXmlFile); std::vector runs; @@ -752,7 +748,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection) { EXPECT_TRUE(runs[0].fakedFont.font == NULL || kNoGlyphFont == getFontPath(runs[0])); } -TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) { +TEST(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) { std::unique_ptr collection = getFontCollection(kTestFontDir, kEmojiXmlFile); std::vector runs; @@ -834,7 +830,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) { EXPECT_EQ(kMixedEmojiFont, getFontPath(runs[0])); } -TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) { +TEST(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) { std::unique_ptr collection = getFontCollection(kTestFontDir, kEmojiXmlFile); std::vector runs; diff --git a/tests/FontFamilyTest.cpp b/tests/FontFamilyTest.cpp index ac7616f..fc44e6c 100644 --- a/tests/FontFamilyTest.cpp +++ b/tests/FontFamilyTest.cpp @@ -17,261 +17,74 @@ #include #include - -#include - #include "FontLanguageListCache.h" -#include "ICUTestBase.h" #include "MinikinFontForTest.h" #include "MinikinInternal.h" namespace android { -typedef ICUTestBase FontLanguagesTest; -typedef ICUTestBase FontLanguageTest; - -static FontLanguages createFontLanguages(const std::string& input) { - uint32_t langId = FontLanguageListCache::getId(input); - return FontLanguageListCache::getById(langId); -} - -static FontLanguage createFontLanguage(const std::string& input) { - uint32_t langId = FontLanguageListCache::getId(input); - return FontLanguageListCache::getById(langId)[0]; -} - -TEST_F(FontLanguageTest, basicTests) { - FontLanguage defaultLang; - FontLanguage emptyLang("", 0); - FontLanguage english = createFontLanguage("en"); - FontLanguage french = createFontLanguage("fr"); - FontLanguage und = createFontLanguage("und"); - FontLanguage undQaae = createFontLanguage("und-Qaae"); - - EXPECT_EQ(english, english); - EXPECT_EQ(french, french); - - EXPECT_TRUE(defaultLang != defaultLang); - EXPECT_TRUE(emptyLang != emptyLang); - EXPECT_TRUE(defaultLang != emptyLang); - EXPECT_TRUE(defaultLang != und); - EXPECT_TRUE(emptyLang != und); - EXPECT_TRUE(english != defaultLang); - EXPECT_TRUE(english != emptyLang); - EXPECT_TRUE(english != french); - EXPECT_TRUE(english != undQaae); - EXPECT_TRUE(und != undQaae); - EXPECT_TRUE(english != und); - - EXPECT_TRUE(defaultLang.isUnsupported()); - EXPECT_TRUE(emptyLang.isUnsupported()); - - EXPECT_FALSE(english.isUnsupported()); - EXPECT_FALSE(french.isUnsupported()); - EXPECT_FALSE(und.isUnsupported()); - EXPECT_FALSE(undQaae.isUnsupported()); -} - -TEST_F(FontLanguageTest, getStringTest) { - EXPECT_EQ("en-Latn", createFontLanguage("en").getString()); - EXPECT_EQ("en-Latn", createFontLanguage("en-Latn").getString()); - - // Capitalized language code or lowercased script should be normalized. - EXPECT_EQ("en-Latn", createFontLanguage("EN-LATN").getString()); - EXPECT_EQ("en-Latn", createFontLanguage("EN-latn").getString()); - EXPECT_EQ("en-Latn", createFontLanguage("en-latn").getString()); - - // Invalid script should be kept. - EXPECT_EQ("en-Xyzt", createFontLanguage("en-xyzt").getString()); - - EXPECT_EQ("en-Latn", createFontLanguage("en-Latn-US").getString()); - EXPECT_EQ("ja-Jpan", createFontLanguage("ja").getString()); - EXPECT_EQ("und", createFontLanguage("und").getString()); - EXPECT_EQ("und", createFontLanguage("UND").getString()); - EXPECT_EQ("und", createFontLanguage("Und").getString()); - EXPECT_EQ("und-Qaae", createFontLanguage("und-Qaae").getString()); - EXPECT_EQ("und-Qaae", createFontLanguage("Und-QAAE").getString()); - EXPECT_EQ("und-Qaae", createFontLanguage("Und-qaae").getString()); - - EXPECT_EQ("de-Latn", createFontLanguage("de-1901").getString()); - - // This is not a necessary desired behavior, just known behavior. - EXPECT_EQ("en-Latn", createFontLanguage("und-Abcdefgh").getString()); -} - -TEST_F(FontLanguageTest, ScriptEqualTest) { - EXPECT_TRUE(createFontLanguage("en").isEqualScript(createFontLanguage("en"))); - EXPECT_TRUE(createFontLanguage("en-Latn").isEqualScript(createFontLanguage("en"))); - EXPECT_TRUE(createFontLanguage("jp-Latn").isEqualScript(createFontLanguage("en-Latn"))); - EXPECT_TRUE(createFontLanguage("en-Jpan").isEqualScript(createFontLanguage("en-Jpan"))); - - EXPECT_FALSE(createFontLanguage("en-Jpan").isEqualScript(createFontLanguage("en-Hira"))); - EXPECT_FALSE(createFontLanguage("en-Jpan").isEqualScript(createFontLanguage("en-Hani"))); -} - -TEST_F(FontLanguageTest, ScriptMatchTest) { - const bool SUPPORTED = true; - const bool NOT_SUPPORTED = false; - - struct TestCase { - const std::string baseScript; - const std::string requestedScript; - bool isSupported; - } testCases[] = { - // Same scripts - { "en-Latn", "Latn", SUPPORTED }, - { "ja-Jpan", "Jpan", SUPPORTED }, - { "ja-Hira", "Hira", SUPPORTED }, - { "ja-Kana", "Kana", SUPPORTED }, - { "ja-Hrkt", "Hrkt", SUPPORTED }, - { "zh-Hans", "Hans", SUPPORTED }, - { "zh-Hant", "Hant", SUPPORTED }, - { "zh-Hani", "Hani", SUPPORTED }, - { "ko-Kore", "Kore", SUPPORTED }, - { "ko-Hang", "Hang", SUPPORTED }, - - // Japanese supports Hiragana, Katakanara, etc. - { "ja-Jpan", "Hira", SUPPORTED }, - { "ja-Jpan", "Kana", SUPPORTED }, - { "ja-Jpan", "Hrkt", SUPPORTED }, - { "ja-Hrkt", "Hira", SUPPORTED }, - { "ja-Hrkt", "Kana", SUPPORTED }, - - // Chinese supports Han. - { "zh-Hans", "Hani", SUPPORTED }, - { "zh-Hant", "Hani", SUPPORTED }, - - // Korean supports Hangul. - { "ko-Kore", "Hang", SUPPORTED }, - - // Different scripts - { "ja-Jpan", "Latn", NOT_SUPPORTED }, - { "en-Latn", "Jpan", NOT_SUPPORTED }, - { "ja-Jpan", "Hant", NOT_SUPPORTED }, - { "zh-Hant", "Jpan", NOT_SUPPORTED }, - { "ja-Jpan", "Hans", NOT_SUPPORTED }, - { "zh-Hans", "Jpan", NOT_SUPPORTED }, - { "ja-Jpan", "Kore", NOT_SUPPORTED }, - { "ko-Kore", "Jpan", NOT_SUPPORTED }, - { "zh-Hans", "Hant", NOT_SUPPORTED }, - { "zh-Hant", "Hans", NOT_SUPPORTED }, - { "zh-Hans", "Kore", NOT_SUPPORTED }, - { "ko-Kore", "Hans", NOT_SUPPORTED }, - { "zh-Hant", "Kore", NOT_SUPPORTED }, - { "ko-Kore", "Hant", NOT_SUPPORTED }, - - // Hiragana doesn't support Japanese, etc. - { "ja-Hira", "Jpan", NOT_SUPPORTED }, - { "ja-Kana", "Jpan", NOT_SUPPORTED }, - { "ja-Hrkt", "Jpan", NOT_SUPPORTED }, - { "ja-Hani", "Jpan", NOT_SUPPORTED }, - { "ja-Hira", "Hrkt", NOT_SUPPORTED }, - { "ja-Kana", "Hrkt", NOT_SUPPORTED }, - { "ja-Hani", "Hrkt", NOT_SUPPORTED }, - { "ja-Hani", "Hira", NOT_SUPPORTED }, - { "ja-Hani", "Kana", NOT_SUPPORTED }, - - // Kanji doesn't support Chinese, etc. - { "zh-Hani", "Hant", NOT_SUPPORTED }, - { "zh-Hani", "Hans", NOT_SUPPORTED }, - - // Hangul doesn't support Korean, etc. - { "ko-Hang", "Kore", NOT_SUPPORTED }, - { "ko-Hani", "Kore", NOT_SUPPORTED }, - { "ko-Hani", "Hang", NOT_SUPPORTED }, - { "ko-Hang", "Hani", NOT_SUPPORTED }, - }; - - for (auto testCase : testCases) { - hb_script_t script = hb_script_from_iso15924_tag( - HB_TAG(testCase.requestedScript[0], testCase.requestedScript[1], - testCase.requestedScript[2], testCase.requestedScript[3])); - if (testCase.isSupported) { - EXPECT_TRUE( - createFontLanguage(testCase.baseScript).supportsHbScript(script)) - << testCase.baseScript << " should support " << testCase.requestedScript; - } else { - EXPECT_FALSE( - createFontLanguage(testCase.baseScript).supportsHbScript(script)) - << testCase.baseScript << " shouldn't support " << testCase.requestedScript; - } - } -} - -TEST_F(FontLanguagesTest, basicTests) { +TEST(FontLanguagesTest, basicTests) { FontLanguages emptyLangs; EXPECT_EQ(0u, emptyLangs.size()); - FontLanguage english = createFontLanguage("en"); - FontLanguages singletonLangs = createFontLanguages("en"); + FontLanguage english("en", 2); + FontLanguages singletonLangs("en", 2); EXPECT_EQ(1u, singletonLangs.size()); EXPECT_EQ(english, singletonLangs[0]); - FontLanguage french = createFontLanguage("fr"); - FontLanguages twoLangs = createFontLanguages("en,fr"); + FontLanguage french("fr", 2); + FontLanguages twoLangs("en,fr", 5); EXPECT_EQ(2u, twoLangs.size()); EXPECT_EQ(english, twoLangs[0]); EXPECT_EQ(french, twoLangs[1]); } -TEST_F(FontLanguagesTest, unsupportedLanguageTests) { - FontLanguage unsupportedLang = createFontLanguage("abcd"); +TEST(FontLanguagesTest, unsupportedLanguageTests) { + FontLanguage unsupportedLang("x-example", 9); ASSERT_TRUE(unsupportedLang.isUnsupported()); - FontLanguages oneUnsupported = createFontLanguages("abcd-example"); + FontLanguages oneUnsupported("x-example", 9); EXPECT_EQ(1u, oneUnsupported.size()); EXPECT_TRUE(oneUnsupported[0].isUnsupported()); - FontLanguages twoUnsupporteds = createFontLanguages("abcd-example,abcd-example"); + FontLanguages twoUnsupporteds("x-example,x-example", 19); EXPECT_EQ(1u, twoUnsupporteds.size()); EXPECT_TRUE(twoUnsupporteds[0].isUnsupported()); - FontLanguage english = createFontLanguage("en"); - FontLanguages firstUnsupported = createFontLanguages("abcd-example,en"); + FontLanguage english("en", 2); + FontLanguages firstUnsupported("x-example,en", 12); EXPECT_EQ(1u, firstUnsupported.size()); EXPECT_EQ(english, firstUnsupported[0]); - FontLanguages lastUnsupported = createFontLanguages("en,abcd-example"); + FontLanguages lastUnsupported("en,x-example", 12); EXPECT_EQ(1u, lastUnsupported.size()); EXPECT_EQ(english, lastUnsupported[0]); } -TEST_F(FontLanguagesTest, repeatedLanguageTests) { - FontLanguage english = createFontLanguage("en"); - FontLanguage french = createFontLanguage("fr"); - FontLanguage englishInLatn = createFontLanguage("en-Latn"); +TEST(FontLanguagesTest, repeatedLanguageTests) { + FontLanguage english("en", 2); + FontLanguage englishInLatn("en-Latn", 2); ASSERT_TRUE(english == englishInLatn); - FontLanguages langs = createFontLanguages("en,en-Latn"); + FontLanguages langs("en,en-Latn", 10); EXPECT_EQ(1u, langs.size()); EXPECT_EQ(english, langs[0]); - - // Country codes are ignored. - FontLanguages fr = createFontLanguages("fr,fr-CA,fr-FR"); - EXPECT_EQ(1u, fr.size()); - EXPECT_EQ(french, fr[0]); - - // The order should be kept. - langs = createFontLanguages("en,fr,en-Latn"); - EXPECT_EQ(2u, langs.size()); - EXPECT_EQ(english, langs[0]); - EXPECT_EQ(french, langs[1]); } -TEST_F(FontLanguagesTest, undEmojiTests) { - FontLanguage emoji = createFontLanguage("und-Qaae"); +TEST(FontLanguagesTest, undEmojiTests) { + FontLanguage emoji("und-Qaae", 8); EXPECT_TRUE(emoji.hasEmojiFlag()); - FontLanguage und = createFontLanguage("und"); + FontLanguage und("und", 3); EXPECT_FALSE(und.hasEmojiFlag()); EXPECT_FALSE(emoji == und); - FontLanguage undExample = createFontLanguage("und-example"); + FontLanguage undExample("und-example", 10); EXPECT_FALSE(undExample.hasEmojiFlag()); EXPECT_FALSE(emoji == undExample); } -TEST_F(FontLanguagesTest, registerLanguageListTest) { +TEST(FontLanguagesTest, registerLanguageListTest) { EXPECT_EQ(0UL, FontStyle::registerLanguageList("")); EXPECT_NE(0UL, FontStyle::registerLanguageList("en")); EXPECT_NE(0UL, FontStyle::registerLanguageList("jp")); @@ -309,10 +122,9 @@ TEST_F(FontLanguagesTest, registerLanguageListTest) { // U+717D U+E0103 (VS20) const char kVsTestFont[] = kTestFontDir "VarioationSelectorTest-Regular.ttf"; -class FontFamilyTest : public ICUTestBase { +class FontFamilyTest : public testing::Test { public: virtual void SetUp() override { - ICUTestBase::SetUp(); if (access(kVsTestFont, R_OK) != 0) { FAIL() << "Unable to read " << kVsTestFont << ". " << "Please prepare the test data directory. " diff --git a/tests/FontLanguageListCacheTest.cpp b/tests/FontLanguageListCacheTest.cpp index f83988c..29757fe 100644 --- a/tests/FontLanguageListCacheTest.cpp +++ b/tests/FontLanguageListCacheTest.cpp @@ -17,15 +17,11 @@ #include #include - #include "FontLanguageListCache.h" -#include "ICUTestBase.h" namespace android { -typedef ICUTestBase FontLanguageListCacheTest; - -TEST_F(FontLanguageListCacheTest, getId) { +TEST(FontLanguageListCacheTest, getId) { EXPECT_EQ(0UL, FontLanguageListCache::getId("")); EXPECT_NE(0UL, FontStyle::registerLanguageList("en")); EXPECT_NE(0UL, FontStyle::registerLanguageList("jp")); @@ -46,15 +42,11 @@ TEST_F(FontLanguageListCacheTest, getId) { FontLanguageListCache::getId("en,zh-Hant")); } -TEST_F(FontLanguageListCacheTest, getById) { - uint32_t enLangId = FontLanguageListCache::getId("en"); - uint32_t jpLangId = FontLanguageListCache::getId("jp"); - FontLanguage english = FontLanguageListCache::getById(enLangId)[0]; - FontLanguage japanese = FontLanguageListCache::getById(jpLangId)[0]; +TEST(FontLanguageListCacheTest, getById) { + FontLanguage english("en", 2); + FontLanguage japanese("jp", 2); - FontLanguages defLangs = FontLanguageListCache::getById(0); - EXPECT_EQ(1UL, defLangs.size()); - EXPECT_TRUE(defLangs[0].isUnsupported()); + EXPECT_EQ(0UL, FontLanguageListCache::getById(0).size()); FontLanguages langs = FontLanguageListCache::getById(FontLanguageListCache::getId("en")); ASSERT_EQ(1UL, langs.size()); diff --git a/tests/FontTestUtils.cpp b/tests/FontTestUtils.cpp index 98dab51..8e1d184 100644 --- a/tests/FontTestUtils.cpp +++ b/tests/FontTestUtils.cpp @@ -20,8 +20,6 @@ #include #include - -#include "FontLanguage.h" #include "MinikinFontForTest.h" std::unique_ptr getFontCollection( @@ -46,10 +44,9 @@ std::unique_ptr getFontCollection( } xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang"); - uint32_t langId = android::FontStyle::registerLanguageList( - std::string((const char*)lang, xmlStrlen(lang))); - android::FontFamily* family = new android::FontFamily(langId, variant); + android::FontFamily* family = new android::FontFamily( + android::FontLanguage((const char*)lang, xmlStrlen(lang)), variant); for (xmlNode* fontNode = familyNode->children; fontNode; fontNode = fontNode->next) { if (xmlStrcmp(fontNode->name, (const xmlChar*)"font") != 0) { diff --git a/tests/ICUTestBase.h b/tests/ICUTestBase.h deleted file mode 100644 index 3bcfaf3..0000000 --- a/tests/ICUTestBase.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MINIKIN_TEST_ICU_TEST_BASE_H -#define MINIKIN_TEST_ICU_TEST_BASE_H - -#include -#include -#include - -// low level file access for mapping ICU data -#include -#include -#include - -class ICUTestBase : public testing::Test { -protected: - virtual void SetUp() override { - const char* fn = "/system/usr/icu/" U_ICUDATA_NAME ".dat"; - int fd = open(fn, O_RDONLY); - ASSERT_NE(-1, fd); - struct stat sb; - ASSERT_EQ(0, fstat(fd, &sb)); - void* data = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); - - UErrorCode errorCode = U_ZERO_ERROR; - udata_setCommonData(data, &errorCode); - ASSERT_TRUE(U_SUCCESS(errorCode)); - u_init(&errorCode); - ASSERT_TRUE(U_SUCCESS(errorCode)); - } - - virtual void TearDown() override { - u_cleanup(); - } -}; - - -#endif // MINIKIN_TEST_ICU_TEST_BASE_H -- cgit v1.2.3 From 3a2a4a99ce0189d9f28e5f7c2cbab8076f6fadeb Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Tue, 26 Jan 2016 00:44:02 -0800 Subject: Disable unsigned integer overflow sanitization until libc++ is fixed. Bug: http://b/26781196 Bug: http://b/25884483 Bug: http://b/26432628 Although this issue was first only manifesting on Fugu, it now affects N9 and N6p as well. This change disables unsigned overflow sanitization on all platforms. The real fix for libc++ (r257368) can't be committed until we have updated Clang at least one more time. Change-Id: I71e9c50d25ae4566d4c06f348183c4b22a4bb60a --- libs/minikin/Android.mk | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libs/minikin/Android.mk b/libs/minikin/Android.mk index 67ac9f7..769b5fc 100644 --- a/libs/minikin/Android.mk +++ b/libs/minikin/Android.mk @@ -64,9 +64,7 @@ LOCAL_SHARED_LIBRARIES := $(minikin_shared_libraries) LOCAL_CLANG := true LOCAL_SANITIZE := signed-integer-overflow # b/26432628. -ifeq ($(filter x86%,$(TARGET_ARCH)),) - LOCAL_SANITIZE += unsigned-integer-overflow -endif +#LOCAL_SANITIZE += unsigned-integer-overflow include $(BUILD_SHARED_LIBRARY) @@ -82,9 +80,7 @@ LOCAL_SHARED_LIBRARIES := $(minikin_shared_libraries) LOCAL_CLANG := true LOCAL_SANITIZE := signed-integer-overflow # b/26432628. -ifeq ($(filter x86%,$(TARGET_ARCH)),) - LOCAL_SANITIZE += unsigned-integer-overflow -endif +#LOCAL_SANITIZE += unsigned-integer-overflow include $(BUILD_STATIC_LIBRARY) -- cgit v1.2.3