diff options
author | Seigo Nonaka <nona@google.com> | 2015-09-16 20:31:35 +0900 |
---|---|---|
committer | Seigo Nonaka <nona@google.com> | 2015-09-18 15:40:51 +0900 |
commit | 1c2bd209d11e59ea3a31d49ec4e97725fd711bea (patch) | |
tree | 290928ff0b27b50803932f0e2549691bde976fd7 | |
parent | 4e3adc6fb2073d5b466b88b8f5329d281038aba1 (diff) | |
download | android_frameworks_minikin-1c2bd209d11e59ea3a31d49ec4e97725fd711bea.tar.gz android_frameworks_minikin-1c2bd209d11e59ea3a31d49ec4e97725fd711bea.tar.bz2 android_frameworks_minikin-1c2bd209d11e59ea3a31d49ec4e97725fd711bea.zip |
Introduce unit tests for FontCollection::itemize.
Introduced tests depend on installed font list in running device.
I verified these test passed on Nexus 5(hammerhead), Nexus 6(shamu)
and Nexus 9(volantis).
Bug: 11256006
Bug: 17759267
Change-Id: I6f806370e17f6c6d3dad8df0cb70bb475a827873
-rw-r--r-- | tests/Android.mk | 20 | ||||
-rw-r--r-- | tests/FontCollectionItemizeTest.cpp | 343 | ||||
-rw-r--r-- | tests/FontTestUtils.cpp | 81 | ||||
-rw-r--r-- | tests/FontTestUtils.h | 30 | ||||
-rw-r--r-- | tests/MinikinFontForTest.cpp | 62 | ||||
-rw-r--r-- | tests/MinikinFontForTest.h | 38 |
6 files changed, 569 insertions, 5 deletions
diff --git a/tests/Android.mk b/tests/Android.mk index 00847e3..680cbe9 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -27,18 +27,28 @@ LOCAL_STATIC_LIBRARIES := libminikin # pulled in by the build system (and thus sadly must be repeated). LOCAL_SHARED_LIBRARIES := \ - libharfbuzz_ng \ + libskia \ libft2 \ - liblog \ - libz \ + libharfbuzz_ng \ libicuuc \ - libutils + liblog \ + libutils \ + libz + +LOCAL_STATIC_LIBRARIES += \ + libxml2 LOCAL_SRC_FILES += \ + FontCollectionItemizeTest.cpp \ + FontTestUtils.cpp \ + MinikinFontForTest.cpp \ GraphemeBreakTests.cpp \ LayoutUtilsTest.cpp \ UnicodeUtils.cpp -LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libs/minikin/ +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/../libs/minikin/ \ + external/libxml2/include \ + external/skia/src/core \ include $(BUILD_NATIVE_TEST) diff --git a/tests/FontCollectionItemizeTest.cpp b/tests/FontCollectionItemizeTest.cpp new file mode 100644 index 0000000..cabc967 --- /dev/null +++ b/tests/FontCollectionItemizeTest.cpp @@ -0,0 +1,343 @@ +/* + * 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. + */ + +#include <gtest/gtest.h> + +#include "FontTestUtils.h" +#include "MinikinFontForTest.h" +#include "UnicodeUtils.h" + +using android::FontCollection; +using android::FontLanguage; +using android::FontStyle; + +const char kEmojiFont[] = "/system/fonts/NotoColorEmoji.ttf"; +const char kJAFont[] = "/system/fonts/NotoSansJP-Regular.otf"; +const char kKOFont[] = "/system/fonts/NotoSansKR-Regular.otf"; +const char kLatinBoldFont[] = "/system/fonts/Roboto-Bold.ttf"; +const char kLatinBoldItalicFont[] = "/system/fonts/Roboto-BoldItalic.ttf"; +const char kLatinFont[] = "/system/fonts/Roboto-Regular.ttf"; +const char kLatinItalicFont[] = "/system/fonts/Roboto-Italic.ttf"; +const char kZH_HansFont[] = "/system/fonts/NotoSansSC-Regular.otf"; +const char kZH_HantFont[] = "/system/fonts/NotoSansTC-Regular.otf"; + +// Utility function for calling itemize function. +void itemize(FontCollection* collection, const char* str, FontStyle style, + std::vector<FontCollection::Run>* result) { + const size_t BUF_SIZE = 256; + uint16_t buf[BUF_SIZE]; + size_t len; + + result->clear(); + ParseUnicode(buf, BUF_SIZE, str, &len, NULL); + collection->itemize(buf, len, style, result); +} + +// Utility function to obtain font path associated with run. +const std::string& getFontPath(const FontCollection::Run& run) { + return ((MinikinFontForTest*)run.fakedFont.font)->fontPath(); +} + +TEST(FontCollectionItemizeTest, itemize_latin) { + std::unique_ptr<FontCollection> collection = getFontCollection(); + std::vector<FontCollection::Run> runs; + + const FontStyle kRegularStyle = FontStyle(); + const FontStyle kItalicStyle = FontStyle(4, true); + const FontStyle kBoldStyle = FontStyle(7, false); + const FontStyle kBoldItalicStyle = FontStyle(7, true); + + itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kRegularStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kItalicStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kLatinItalicFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kBoldStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kLatinBoldFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kBoldItalicStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kLatinBoldItalicFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // Continue if the specific characters (e.g. hyphen, comma, etc.) is + // followed. + itemize(collection.get(), "'a' ',' '-' 'd' '!'", kRegularStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + itemize(collection.get(), "'a' ',' '-' 'd' '!'", kRegularStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // U+0301(COMBINING ACUTE ACCENT) must be in the same run with preceding + // chars if the font supports it. + itemize(collection.get(), "'a' U+0301", kRegularStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); +} + +TEST(FontCollectionItemizeTest, itemize_emoji) { + std::unique_ptr<FontCollection> collection = getFontCollection(); + std::vector<FontCollection::Run> runs; + + itemize(collection.get(), "U+1F469 U+1F467", FontStyle(), &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(4, runs[0].end); + EXPECT_EQ(kEmojiFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // U+20E3(COMBINING ENCLOSING KEYCAP) must be in the same run with preceding + // character if the font supports. + itemize(collection.get(), "'0' U+20E3", FontStyle(), &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kEmojiFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // Currently there is no fonts which has a glyph for 'a' + U+20E3, so they + // are splitted into two. + itemize(collection.get(), "'a' U+20E3", FontStyle(), &runs); + ASSERT_EQ(2U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(1, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(1, runs[1].start); + EXPECT_EQ(2, runs[1].end); + EXPECT_EQ(kEmojiFont, getFontPath(runs[1])); + EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic()); +} + +TEST(FontCollectionItemizeTest, itemize_non_latin) { + std::unique_ptr<FontCollection> collection = getFontCollection(); + std::vector<FontCollection::Run> runs; + + FontStyle kJAStyle = FontStyle(FontLanguage("ja_JP", 5)); + FontStyle kUSStyle = FontStyle(FontLanguage("en_US", 5)); + FontStyle kZH_HansStyle = FontStyle(FontLanguage("zh_Hans", 7)); + + // All Japanese Hiragana characters. + itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kUSStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kJAFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // All Korean Hangul characters. + itemize(collection.get(), "U+B300 U+D55C U+BBFC U+AD6D", kUSStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(4, runs[0].end); + EXPECT_EQ(kKOFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // All Han characters ja, zh-Hans font having. + // Japanese font should be selected if the specified language is Japanese. + itemize(collection.get(), "U+81ED U+82B1 U+5FCD", kJAStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(3, runs[0].end); + EXPECT_EQ(kJAFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // Simplified Chinese font should be selected if the specified language is Simplified + // Chinese. + itemize(collection.get(), "U+81ED U+82B1 U+5FCD", kZH_HansStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(3, runs[0].end); + EXPECT_EQ(kZH_HansFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // Fallbacks to other fonts if there is no glyph in the specified language's + // font. There is no character U+4F60 in Japanese. + itemize(collection.get(), "U+81ED U+4F60 U+5FCD", kJAStyle, &runs); + ASSERT_EQ(3U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(1, runs[0].end); + EXPECT_EQ(kJAFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(1, runs[1].start); + EXPECT_EQ(2, runs[1].end); + EXPECT_EQ(kZH_HansFont, getFontPath(runs[1])); + EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(2, runs[2].start); + EXPECT_EQ(3, runs[2].end); + EXPECT_EQ(kJAFont, getFontPath(runs[2])); + EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic()); + + // Tone mark. + itemize(collection.get(), "U+4444 U+302D", FontStyle(), &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kZH_HansFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); +} + +TEST(FontCollectionItemizeTest, itemize_mixed) { + std::unique_ptr<FontCollection> collection = getFontCollection(); + std::vector<FontCollection::Run> runs; + + FontStyle kUSStyle = FontStyle(FontLanguage("en_US", 5)); + + itemize(collection.get(), "'a' U+4F60 'b' U+4F60 'c'", kUSStyle, &runs); + ASSERT_EQ(5U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(1, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(1, runs[1].start); + EXPECT_EQ(2, runs[1].end); + EXPECT_EQ(kZH_HansFont, getFontPath(runs[1])); + EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(2, runs[2].start); + EXPECT_EQ(3, runs[2].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[2])); + EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(3, runs[3].start); + EXPECT_EQ(4, runs[3].end); + EXPECT_EQ(kZH_HansFont, getFontPath(runs[3])); + EXPECT_FALSE(runs[3].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[3].fakedFont.fakery.isFakeItalic()); + + EXPECT_EQ(4, runs[4].start); + EXPECT_EQ(5, runs[4].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[4])); + EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeItalic()); +} + +TEST(FontCollectionItemizeTest, itemize_no_crash) { + std::unique_ptr<FontCollection> collection = getFontCollection(); + std::vector<FontCollection::Run> runs; + + // Broken Surrogate pairs. Check only not crashing. + itemize(collection.get(), "'a' U+D83D 'a'", FontStyle(), &runs); + itemize(collection.get(), "'a' U+DC69 'a'", FontStyle(), &runs); + itemize(collection.get(), "'a' U+D83D U+D83D 'a'", FontStyle(), &runs); + itemize(collection.get(), "'a' U+DC69 U+DC69 'a'", FontStyle(), &runs); + + // Isolated variation selector. Check only not crashing. + itemize(collection.get(), "U+FE00 U+FE00", FontStyle(), &runs); + itemize(collection.get(), "U+E0100 U+E0100", FontStyle(), &runs); + itemize(collection.get(), "U+FE00 U+E0100", FontStyle(), &runs); + itemize(collection.get(), "U+E0100 U+FE00", FontStyle(), &runs); + + // Tone mark only. Check only not crashing. + itemize(collection.get(), "U+302D", FontStyle(), &runs); + itemize(collection.get(), "U+302D U+302D", FontStyle(), &runs); + + // Tone mark and variation selector mixed. Check only not crashing. + itemize(collection.get(), "U+FE00 U+302D U+E0100", FontStyle(), &runs); +} + +TEST(FontCollectionItemizeTest, itemize_fakery) { + std::unique_ptr<FontCollection> collection = getFontCollection(); + std::vector<FontCollection::Run> runs; + + FontStyle kJABoldStyle = FontStyle(FontLanguage("ja_JP", 5), 0, 7, false); + FontStyle kJAItalicStyle = FontStyle(FontLanguage("ja_JP", 5), 0, 5, true); + FontStyle kJABoldItalicStyle = FontStyle(FontLanguage("ja_JP", 5), 0, 7, true); + + // Currently there is no italic or bold font for Japanese. FontFakery has + // the differences between desired and actual font style. + + // All Japanese Hiragana characters. + itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kJAFont, getFontPath(runs[0])); + EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic()); + + // All Japanese Hiragana characters. + itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJAItalicStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kJAFont, getFontPath(runs[0])); + EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic()); + + // All Japanese Hiragana characters. + itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldItalicStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(5, runs[0].end); + EXPECT_EQ(kJAFont, getFontPath(runs[0])); + EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeBold()); + EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic()); +} + +// TODO(11256006): Add Variation Selector test cases once it is supported. diff --git a/tests/FontTestUtils.cpp b/tests/FontTestUtils.cpp new file mode 100644 index 0000000..e5d6c2a --- /dev/null +++ b/tests/FontTestUtils.cpp @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#include <libxml/tree.h> + +#include <minikin/FontCollection.h> +#include <minikin/FontFamily.h> + +#include "MinikinFontForTest.h" + +const char kFontDir[] = "/system/fonts/"; +const char kFontXml[] = "/system/etc/fonts.xml"; + +std::unique_ptr<android::FontCollection> getFontCollection() { + xmlDoc* doc = xmlReadFile(kFontXml, NULL, 0); + xmlNode* familySet = xmlDocGetRootElement(doc); + + std::vector<android::FontFamily*> families; + for (xmlNode* familyNode = familySet->children; familyNode; familyNode = familyNode->next) { + if (xmlStrcmp(familyNode->name, (const xmlChar*)"family") != 0) { + continue; + } + + xmlChar* variantXmlch = xmlGetProp(familyNode, (const xmlChar*)"variant"); + int variant = android::VARIANT_DEFAULT; + if (variantXmlch) { + if (xmlStrcmp(variantXmlch, (const xmlChar*)"elegant") == 0) { + variant = android::VARIANT_ELEGANT; + } else if (xmlStrcmp(variantXmlch, (const xmlChar*)"compact") == 0) { + variant = android::VARIANT_COMPACT; + } + } + + xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang"); + + 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) { + continue; + } + + int weight = atoi((const char*)(xmlGetProp(fontNode, (const xmlChar*)"weight"))) / 100; + bool italic = xmlStrcmp( + xmlGetProp(fontNode, (const xmlChar*)"style"), (const xmlChar*)"italic") == 0; + + xmlChar* fontFileName = xmlNodeListGetString(doc, fontNode->xmlChildrenNode, 1); + std::string fontPath = kFontDir + std::string((const char*)fontFileName); + xmlFree(fontFileName); + + if (access(fontPath.c_str(), R_OK) != 0) { + // Skip not accessible fonts. + continue; + } + + family->addFont(new MinikinFontForTest(fontPath), android::FontStyle(weight, italic)); + } + families.push_back(family); + } + xmlFreeDoc(doc); + + std::unique_ptr<android::FontCollection> r(new android::FontCollection(families)); + for (size_t i = 0; i < families.size(); ++i) { + families[i]->Unref(); + } + return r; +} diff --git a/tests/FontTestUtils.h b/tests/FontTestUtils.h new file mode 100644 index 0000000..d53956f --- /dev/null +++ b/tests/FontTestUtils.h @@ -0,0 +1,30 @@ +/* + * 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_TEST_UTILS_H +#define MINIKIN_FONT_TEST_UTILS_H + +#include <minikin/FontCollection.h> + +/** + * Returns FontCollection from installed fonts. + * + * This function reads /system/etc/fonts.xml and make font families and + * collections of them. MinikinFontForTest is used for FontFamily creation. + */ +std::unique_ptr<android::FontCollection> getFontCollection(); + +#endif // MINIKIN_FONT_TEST_UTILS_H diff --git a/tests/MinikinFontForTest.cpp b/tests/MinikinFontForTest.cpp new file mode 100644 index 0000000..2d29e80 --- /dev/null +++ b/tests/MinikinFontForTest.cpp @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#include "MinikinFontForTest.h" + +#include <minikin/MinikinFont.h> + +#include <SkTypeface.h> + +#include <cutils/log.h> + +MinikinFontForTest::MinikinFontForTest(const std::string& font_path) : mFontPath(font_path) { + mTypeface = SkTypeface::CreateFromFile(font_path.c_str()); +} + +MinikinFontForTest::~MinikinFontForTest() { +} + +bool MinikinFontForTest::GetGlyph(uint32_t codepoint, uint32_t *glyph) const { + LOG_ALWAYS_FATAL("MinikinFontForTest::GetGlyph is not yet implemented"); + return false; +} + +float MinikinFontForTest::GetHorizontalAdvance( + uint32_t glyph_id, const android::MinikinPaint &paint) const { + LOG_ALWAYS_FATAL("MinikinFontForTest::GetHorizontalAdvance is not yet implemented"); + return 0.0f; +} + +void MinikinFontForTest::GetBounds(android::MinikinRect* bounds, uint32_t glyph_id, + const android::MinikinPaint& paint) const { + LOG_ALWAYS_FATAL("MinikinFontForTest::GetBounds is not yet implemented"); +} + +bool MinikinFontForTest::GetTable(uint32_t tag, uint8_t *buf, size_t *size) { + if (buf == NULL) { + const size_t tableSize = mTypeface->getTableSize(tag); + *size = tableSize; + return tableSize != 0; + } else { + const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf); + *size = actualSize; + return actualSize != 0; + } +} + +int32_t MinikinFontForTest::GetUniqueId() const { + return mTypeface->uniqueID(); +} diff --git a/tests/MinikinFontForTest.h b/tests/MinikinFontForTest.h new file mode 100644 index 0000000..ecebb7e --- /dev/null +++ b/tests/MinikinFontForTest.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include <minikin/MinikinFont.h> + +class SkTypeface; + +class MinikinFontForTest : public android::MinikinFont { +public: + explicit MinikinFontForTest(const std::string& font_path); + ~MinikinFontForTest(); + + // MinikinFont overrides. + bool GetGlyph(uint32_t codepoint, uint32_t *glyph) const; + float GetHorizontalAdvance(uint32_t glyph_id, const android::MinikinPaint &paint) const; + void GetBounds(android::MinikinRect* bounds, uint32_t glyph_id, + const android::MinikinPaint& paint) const; + bool GetTable(uint32_t tag, uint8_t *buf, size_t *size); + int32_t GetUniqueId() const; + + const std::string& fontPath() const { return mFontPath; } +private: + SkTypeface *mTypeface; + const std::string mFontPath; +}; |