Fix double bolding

resolveStyle increases minikinStyle's weight value based on Skia's style
value. Since we compute Skia's style based on given weight value, we
should not add extra bold weight to minikinStyle.

This CL also fixes misunderstanding of base weight.
The base weight is only used for computing weight relative to the
weighted alias. Thus, base weight should not be updated except for
createWeightAlias method.

To be clear, this CL changes the function names but keeps the same
semantics as before.

Test: adb shell /data/nativetest/hwui_unit_tests/hwui_unit_tests
Test: am instrument -w -e class android.graphics.cts.TypefaceTest\
      android.graphics.cts/android.support.test.runner.AndroidJUnitRunner
Bug: 37880319

Change-Id: Ied73189b11792fb062da46f45afd2db664e6ecb4
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 1d358f6..acf8883 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -334,6 +334,7 @@
         "tests/unit/TestUtilsTests.cpp",
         "tests/unit/TextDropShadowCacheTests.cpp",
         "tests/unit/TextureCacheTests.cpp",
+	"tests/unit/TypefaceTests.cpp",
         "tests/unit/VectorDrawableTests.cpp",
     ],
 }
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 4fb4b533..f66bb04 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -36,28 +36,33 @@
 #include <minikin/FontFamily.h>
 #include <minikin/Layout.h>
 #include <utils/Log.h>
+#include <utils/MathUtils.h>
 
 namespace android {
 
-// This indicates that the passed information should be resolved by OS/2 table.
-// This value must be the same as the android.graphics.Typeface$Builder.RESOLVE_BY_FONT_TABLE.
-constexpr int RESOLVE_BY_FONT_TABLE = -1;
+static SkTypeface::Style computeSkiaStyle(int weight, bool italic) {
+    // This bold detection comes from SkTypeface.h
+    if (weight >= SkFontStyle::kSemiBold_Weight) {
+        return italic ? SkTypeface::kBoldItalic : SkTypeface::kBold;
+    } else {
+        return italic ? SkTypeface::kItalic : SkTypeface::kNormal;
+    }
+}
 
-// Resolve the 1..10 weight based on base weight and bold flag
-static void resolveStyle(Typeface* typeface) {
+static minikin::FontStyle computeMinikinStyle(int weight, bool italic) {
     // TODO: Better to use raw base weight value for font selection instead of dividing by 100.
-    int weight = (typeface->fBaseWeight + 50) / 100;
-    if (typeface->fSkiaStyle & SkTypeface::kBold) {
-        weight += 3;
+    const int minikinWeight = uirenderer::MathUtils::clamp((weight + 50) / 100, 1, 10);
+    return minikin::FontStyle(minikinWeight, italic);
+}
+
+// Resolve the relative weight from the baseWeight and target style.
+static minikin::FontStyle computeRelativeStyle(int baseWeight, SkTypeface::Style relativeStyle) {
+    int weight = baseWeight;
+    if ((relativeStyle & SkTypeface::kBold) != 0) {
+        weight += 300;
     }
-    if (weight > 10) {
-        weight = 10;
-    }
-    if (weight < 1) {
-        weight = 1;
-    }
-    bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
-    typeface->fStyle = minikin::FontStyle(weight, italic);
+    bool italic = (relativeStyle & SkTypeface::kItalic) != 0;
+    return computeMinikinStyle(weight, italic);
 }
 
 Typeface* gDefaultTypeface = NULL;
@@ -67,26 +72,26 @@
     return src == nullptr ? gDefaultTypeface : src;
 }
 
-Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
+Typeface* Typeface::createRelative(Typeface* src, SkTypeface::Style style) {
     Typeface* resolvedFace = Typeface::resolveDefault(src);
     Typeface* result = new Typeface;
     if (result != nullptr) {
         result->fFontCollection = resolvedFace->fFontCollection;
-        result->fSkiaStyle = style;
         result->fBaseWeight = resolvedFace->fBaseWeight;
-        resolveStyle(result);
+        result->fSkiaStyle = style;
+        result->fStyle = computeRelativeStyle(result->fBaseWeight, style);
     }
     return result;
 }
 
-Typeface* Typeface::createFromTypefaceWithStyle(Typeface* base, int weight, bool italic) {
+Typeface* Typeface::createAbsolute(Typeface* base, int weight, bool italic) {
     Typeface* resolvedFace = Typeface::resolveDefault(base);
     Typeface* result = new Typeface();
     if (result != nullptr) {
         result->fFontCollection = resolvedFace->fFontCollection;
-        result->fBaseWeight = weight;
-        result->fStyle = minikin::FontStyle(weight / 100, italic);
-        result->fSkiaStyle = resolvedFace->fSkiaStyle;
+        result->fBaseWeight = resolvedFace->fBaseWeight;
+        result->fSkiaStyle = computeSkiaStyle(weight, italic);
+        result->fStyle = computeMinikinStyle(weight, italic);
     }
     return result;
 }
@@ -103,21 +108,23 @@
             // So we will reuse the same collection with incrementing reference count.
             result->fFontCollection = resolvedFace->fFontCollection;
         }
-        result->fSkiaStyle = resolvedFace->fSkiaStyle;
+        // Do not update styles.
+        // TODO: We may want to update base weight if the 'wght' is specified.
         result->fBaseWeight = resolvedFace->fBaseWeight;
-        resolveStyle(result);
+        result->fSkiaStyle = resolvedFace->fSkiaStyle;
+        result->fStyle = resolvedFace->fStyle;
     }
     return result;
 }
 
-Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
+Typeface* Typeface::createWithDifferentBaseWeight(Typeface* src, int weight) {
     Typeface* resolvedFace = Typeface::resolveDefault(src);
     Typeface* result = new Typeface;
     if (result != nullptr) {
         result->fFontCollection = resolvedFace->fFontCollection;
-        result->fSkiaStyle = resolvedFace->fSkiaStyle;
         result->fBaseWeight = weight;
-        resolveStyle(result);
+        result->fSkiaStyle = resolvedFace->fSkiaStyle;
+        result->fStyle = computeRelativeStyle(weight, result->fSkiaStyle);
     }
     return result;
 }
@@ -160,14 +167,8 @@
     }
 
     result->fBaseWeight = weight;
-    // This bold detection comes from SkTypefae.h
-    const bool isBold = weight >= SkFontStyle::kSemiBold_Weight;
-    const bool isItalic = italic == 1;
-    // TODO: remove fSkiaStyle
-    result->fSkiaStyle = isBold ?
-            (isItalic ? SkTypeface::kBoldItalic : SkTypeface::kBold) :
-            (isItalic ? SkTypeface::kItalic : SkTypeface::kNormal);
-    resolveStyle(result);
+    result->fSkiaStyle = computeSkiaStyle(weight, italic);
+    result->fStyle = computeMinikinStyle(weight, italic);
     return result;
 }
 
@@ -197,7 +198,7 @@
     Typeface* hwTypeface = new Typeface();
     hwTypeface->fFontCollection = collection;
     hwTypeface->fSkiaStyle = SkTypeface::kNormal;
-    hwTypeface->fBaseWeight = SkFontStyle::kSemiBold_Weight;
+    hwTypeface->fBaseWeight = SkFontStyle::kNormal_Weight;
     hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);
 
     Typeface::setDefault(hwTypeface);
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index e35a7b4..db0b2cd 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -27,28 +27,53 @@
 
 namespace android {
 
-struct ANDROID_API Typeface {
-    std::shared_ptr<minikin::FontCollection> fFontCollection;
+// This indicates that the weight or italic information should be resolved by OS/2 table.
+// This value must be the same as the android.graphics.Typeface$Builder.RESOLVE_BY_FONT_TABLE.
+constexpr int RESOLVE_BY_FONT_TABLE = -1;
 
-    // style used for constructing and querying Typeface objects
-    SkTypeface::Style fSkiaStyle;
-    // base weight in CSS-style units, 100..900
-    int fBaseWeight;
+struct ANDROID_API Typeface {
+ public:
+    std::shared_ptr<minikin::FontCollection> fFontCollection;
 
     // resolved style actually used for rendering
     minikin::FontStyle fStyle;
 
+    // style used for constructing and querying Typeface objects
+    SkTypeface::Style fSkiaStyle;
+
     static Typeface* resolveDefault(Typeface* src);
 
-    static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
-
-    static Typeface* createFromTypefaceWithStyle(Typeface* base, int weight, bool italic);
+    // The following three functions create new Typeface from an existing Typeface with a different
+    // style. There is a base weight concept which is used for calculating relative style from an
+    // existing Typeface.
+    // The createRelative method creates a new Typeface with a style relative to the base Typeface.
+    // For example, if the base Typeface has a base weight of 400 and the desired style is bold, the
+    // resulting Typeface renders the text with a weight of 700. This function doesn't change the
+    // base weight, so even if you create a new Typeface from the bold Typeface specifying bold on
+    // it again, the text is still rendered with a weight of 700.
+    // You can create another base weight Typeface from an existing Typeface with
+    // createWithDifferentBaseWeight. The Typeface created with this function renders the text with
+    // a specified base weight.
+    // The createAbsolute method creates a new Typeface ignoring the base weight.
+    // Here is an example:
+    //   Typeface* base = resolveDefault(nullptr);  // Usually this has a weight of 400.
+    //   Typeface* bold = createRelative(base, Bold);  // Rendered with a weight of 700.
+    //   Typeface* bold2 = createRelative(bold, Bold); // Rendered with a weight of 700.
+    //
+    //   Typeface* boldBase = createWithDifferentBaseWeight(base, 700);  // With a weight of 700.
+    //   Typeface* boldBold = createRelative(boldBase, Bold);  // Rendered with a weight of 1000.
+    //
+    //   Typeface* lightBase = createWithDifferentBaseWeight(base, 300);  // With a weight of 300.
+    //   Typeface* lightBold = createRelative(lightBase, Bold);  // Rendered with a weight of 600.
+    //
+    //   Typeface* black = createAbsolute(base, 900, false);  // Rendered with a weight of 900.
+    static Typeface* createWithDifferentBaseWeight(Typeface* src, int baseweight);
+    static Typeface* createRelative(Typeface* src, SkTypeface::Style desiredStyle);
+    static Typeface* createAbsolute(Typeface* base, int weight, bool italic);
 
     static Typeface* createFromTypefaceWithVariation(Typeface* src,
             const std::vector<minikin::FontVariation>& variations);
 
-    static Typeface* createWeightAlias(Typeface* src, int baseweight);
-
     static Typeface* createFromFamilies(
             std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
             int weight, int italic);
@@ -57,6 +82,10 @@
 
     // Sets roboto font as the default typeface for testing purpose.
     static void setRobotoTypefaceForTest();
+ private:
+    // base weight in CSS-style units, 1..1000
+    int fBaseWeight;
+
 };
 
 }
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
new file mode 100644
index 0000000..c90b6f0
--- /dev/null
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2017 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 <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <utils/Log.h>
+
+#include "SkFontMgr.h"
+#include "SkStream.h"
+
+#include "hwui/MinikinSkia.h"
+#include "hwui/Typeface.h"
+
+using namespace android;
+
+namespace {
+
+constexpr char kRobotoRegular[] = "/system/fonts/Roboto-Regular.ttf";
+constexpr char kRobotoBold[] = "/system/fonts/Roboto-Bold.ttf";
+constexpr char kRobotoItalic[] = "/system/fonts/Roboto-Italic.ttf";
+constexpr char kRobotoBoldItalic[] = "/system/fonts/Roboto-BoldItalic.ttf";
+
+void unmap(const void* ptr, void* context) {
+    void* p = const_cast<void*>(ptr);
+    size_t len = reinterpret_cast<size_t>(context);
+    munmap(p, len);
+}
+
+std::shared_ptr<minikin::FontFamily> buildFamily(const char* fileName) {
+    int fd = open(fileName, O_RDONLY);
+    LOG_ALWAYS_FATAL_IF(fd == -1, "Failed to open file %s", fileName);
+    struct stat st = {};
+    LOG_ALWAYS_FATAL_IF(fstat(fd, &st) == -1, "Failed to stat file %s", fileName);
+    void* data = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+    sk_sp<SkData> skData =
+            SkData::MakeWithProc(data, st.st_size, unmap, reinterpret_cast<void*>(st.st_size));
+    std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(skData));
+    sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
+    sk_sp<SkTypeface> typeface(fm->createFromStream(fontData.release()));
+    LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", fileName);
+    std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
+            std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
+    return std::make_shared<minikin::FontFamily>(
+            std::vector<minikin::Font>({ minikin::Font(std::move(font), minikin::FontStyle()) }));
+}
+
+std::vector<std::shared_ptr<minikin::FontFamily>> makeSingleFamlyVector(const char* fileName) {
+    return std::vector<std::shared_ptr<minikin::FontFamily>>({ buildFamily(fileName) });
+}
+
+TEST(TypefaceTest, resolveDefault_and_setDefaultTest) {
+    std::unique_ptr<Typeface> regular(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoRegular),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(regular.get(), Typeface::resolveDefault(regular.get()));
+
+    Typeface* old = Typeface::resolveDefault(nullptr);  // Keep the original to restore it later.
+    ASSERT_NE(nullptr, old);
+
+    Typeface::setDefault(regular.get());
+    EXPECT_EQ(regular.get(), Typeface::resolveDefault(nullptr));
+
+    Typeface::setDefault(old);  // Restore to the original.
+}
+
+TEST(TypefaceTest, createWithDifferentBaseWeight) {
+    std::unique_ptr<Typeface> bold(Typeface::createWithDifferentBaseWeight(nullptr, 700));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, bold->fSkiaStyle);
+
+    std::unique_ptr<Typeface> light(Typeface::createWithDifferentBaseWeight(nullptr, 300));
+    EXPECT_EQ(3, light->fStyle.getWeight());
+    EXPECT_FALSE(light->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, light->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createRelativeTest_fromRegular) {
+    // In Java, Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
+    std::unique_ptr<Typeface> normal(Typeface::createRelative(nullptr, SkTypeface::kNormal));
+    EXPECT_EQ(4, normal->fStyle.getWeight());
+    EXPECT_FALSE(normal->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.DEFAULT, Typeface.BOLD);
+    std::unique_ptr<Typeface> bold(Typeface::createRelative(nullptr, SkTypeface::kBold));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.DEFAULT, Typeface.ITALIC);
+    std::unique_ptr<Typeface> italic(Typeface::createRelative(nullptr, SkTypeface::kItalic));
+    EXPECT_EQ(4, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.DEFAULT, Typeface.BOLD_ITALIC);
+    std::unique_ptr<Typeface> boldItalic(
+            Typeface::createRelative(nullptr, SkTypeface::kBoldItalic));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createRelativeTest_BoldBase) {
+    std::unique_ptr<Typeface> base(Typeface::createWithDifferentBaseWeight(nullptr, 700));
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.NORMAL);
+    std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
+    EXPECT_EQ(7, normal->fStyle.getWeight());
+    EXPECT_FALSE(normal->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.BOLD);
+    std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
+    EXPECT_EQ(10, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.ITALIC);
+    std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
+    EXPECT_EQ(7, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-bold"), Typeface.BOLD_ITALIC);
+    std::unique_ptr<Typeface>
+            boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
+    EXPECT_EQ(10, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createRelativeTest_LightBase) {
+    std::unique_ptr<Typeface> base(Typeface::createWithDifferentBaseWeight(nullptr, 300));
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.NORMAL);
+    std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
+    EXPECT_EQ(3, normal->fStyle.getWeight());
+    EXPECT_FALSE(normal->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.BOLD);
+    std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
+    EXPECT_EQ(6, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.ITLIC);
+    std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
+    EXPECT_EQ(3, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create("sans-serif-light"), Typeface.BOLD_ITALIC);
+    std::unique_ptr<Typeface>
+            boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
+    EXPECT_EQ(6, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createRelativeTest_fromBoldStyled) {
+    std::unique_ptr<Typeface> base(Typeface::createRelative(nullptr, SkTypeface::kBold));
+
+    // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.NORMAL);
+    std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
+    EXPECT_EQ(4, normal->fStyle.getWeight());
+    EXPECT_FALSE(normal->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+
+    // In Java Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.BOLD);
+    std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.ITALIC);
+    std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
+    EXPECT_EQ(4, normal->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java,
+    // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.BOLD), Typeface.BOLD_ITALIC);
+    std::unique_ptr<Typeface>
+            boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createRelativeTest_fromItalicStyled) {
+    std::unique_ptr<Typeface> base(Typeface::createRelative(nullptr, SkTypeface::kItalic));
+
+    // In Java,
+    // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.NORMAL);
+    std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
+    EXPECT_EQ(4, normal->fStyle.getWeight());
+    EXPECT_FALSE(normal->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+
+    // In Java, Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.BOLD);
+    std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java,
+    // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.ITALIC);
+    std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
+    EXPECT_EQ(4, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java,
+    // Typeface.create(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC), Typeface.BOLD_ITALIC);
+    std::unique_ptr<Typeface>
+            boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createRelativeTest_fromSpecifiedStyled) {
+    std::unique_ptr<Typeface> base(Typeface::createAbsolute(nullptr, 400, false));
+
+    // In Java,
+    // Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
+    //     .setWeight(700).setItalic(false).build();
+    // Typeface.create(typeface, Typeface.NORMAL);
+    std::unique_ptr<Typeface> normal(Typeface::createRelative(base.get(), SkTypeface::kNormal));
+    EXPECT_EQ(4, normal->fStyle.getWeight());
+    EXPECT_FALSE(normal->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, normal->fSkiaStyle);
+
+    // In Java,
+    // Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
+    //     .setWeight(700).setItalic(false).build();
+    // Typeface.create(typeface, Typeface.BOLD);
+    std::unique_ptr<Typeface> bold(Typeface::createRelative(base.get(), SkTypeface::kBold));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java,
+    // Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
+    //     .setWeight(700).setItalic(false).build();
+    // Typeface.create(typeface, Typeface.ITALIC);
+    std::unique_ptr<Typeface> italic(Typeface::createRelative(base.get(), SkTypeface::kItalic));
+    EXPECT_EQ(4, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java,
+    // Typeface typeface = new Typeface.Builder(invalid).setFallback("sans-serif")
+    //     .setWeight(700).setItalic(false).build();
+    // Typeface.create(typeface, Typeface.BOLD_ITALIC);
+    std::unique_ptr<Typeface>
+            boldItalic(Typeface::createRelative(base.get(), SkTypeface::kBoldItalic));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createAbsolute) {
+    // In Java,
+    // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(400).setItalic(false)
+    //     .build();
+    std::unique_ptr<Typeface> regular(Typeface::createAbsolute(nullptr, 400, false));
+    EXPECT_EQ(4, regular->fStyle.getWeight());
+    EXPECT_FALSE(regular->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, regular->fSkiaStyle);
+
+    // In Java,
+    // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(700).setItalic(false)
+    //     .build();
+    std::unique_ptr<Typeface> bold(Typeface::createAbsolute(nullptr, 700, false));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java,
+    // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(400).setItalic(true)
+    //     .build();
+    std::unique_ptr<Typeface> italic(Typeface::createAbsolute(nullptr, 400, true));
+    EXPECT_EQ(4, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java,
+    // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(700).setItalic(true)
+    //     .build();
+    std::unique_ptr<Typeface> boldItalic(Typeface::createAbsolute(nullptr, 700, true));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBoldItalic, boldItalic->fSkiaStyle);
+
+    // In Java,
+    // new Typeface.Builder(invalid).setFallback("sans-serif").setWeight(1100).setItalic(true)
+    //     .build();
+    std::unique_ptr<Typeface> over1000(Typeface::createAbsolute(nullptr, 1100, false));
+    EXPECT_EQ(10, over1000->fStyle.getWeight());
+    EXPECT_FALSE(over1000->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, over1000->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createFromFamilies_Single) {
+    // In Java, new Typeface.Builder("Roboto-Regular.ttf").setWeight(400).setItalic(false).build();
+    std::unique_ptr<Typeface> regular(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoRegular), 400, false));
+    EXPECT_EQ(4, regular->fStyle.getWeight());
+    EXPECT_FALSE(regular->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, regular->fSkiaStyle);
+
+    // In Java, new Typeface.Builder("Roboto-Bold.ttf").setWeight(700).setItalic(false).build();
+    std::unique_ptr<Typeface> bold(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBold), 700, false));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java, new Typeface.Builder("Roboto-Italic.ttf").setWeight(400).setItalic(true).build();
+    std::unique_ptr<Typeface> italic(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoItalic), 400, true));
+    EXPECT_EQ(4, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java,
+    // new Typeface.Builder("Roboto-BoldItalic.ttf").setWeight(700).setItalic(true).build();
+    std::unique_ptr<Typeface> boldItalic(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBoldItalic), 700, true));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java,
+    // new Typeface.Builder("Roboto-BoldItalic.ttf").setWeight(1100).setItalic(false).build();
+    std::unique_ptr<Typeface> over1000(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBold), 1100, false));
+    EXPECT_EQ(10, over1000->fStyle.getWeight());
+    EXPECT_FALSE(over1000->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, over1000->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createFromFamilies_Single_resolveByTable) {
+    // In Java, new Typeface.Builder("Roboto-Regular.ttf").build();
+    std::unique_ptr<Typeface> regular(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoRegular),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(4, regular->fStyle.getWeight());
+    EXPECT_FALSE(regular->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kNormal, regular->fSkiaStyle);
+
+    // In Java, new Typeface.Builder("Roboto-Bold.ttf").build();
+    std::unique_ptr<Typeface> bold(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBold),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(7, bold->fStyle.getWeight());
+    EXPECT_FALSE(bold->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kBold, bold->fSkiaStyle);
+
+    // In Java, new Typeface.Builder("Roboto-Italic.ttf").build();
+    std::unique_ptr<Typeface> italic(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoItalic),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(4, italic->fStyle.getWeight());
+    EXPECT_TRUE(italic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+
+    // In Java, new Typeface.Builder("Roboto-BoldItalic.ttf").build();
+    std::unique_ptr<Typeface> boldItalic(
+            Typeface::createFromFamilies(makeSingleFamlyVector(kRobotoBoldItalic),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(7, boldItalic->fStyle.getWeight());
+    EXPECT_TRUE(boldItalic->fStyle.getItalic());
+    EXPECT_EQ(SkTypeface::kItalic, italic->fSkiaStyle);
+}
+
+TEST(TypefaceTest, createFromFamilies_Family) {
+    std::vector<std::shared_ptr<minikin::FontFamily>> families = {
+            buildFamily(kRobotoRegular), buildFamily(kRobotoBold), buildFamily(kRobotoItalic),
+            buildFamily(kRobotoBoldItalic)
+    };
+    std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(std::move(families),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(4, typeface->fStyle.getWeight());
+    EXPECT_FALSE(typeface->fStyle.getItalic());
+}
+
+TEST(TypefaceTest, createFromFamilies_Family_withoutRegular) {
+    std::vector<std::shared_ptr<minikin::FontFamily>> families = {
+            buildFamily(kRobotoBold), buildFamily(kRobotoItalic), buildFamily(kRobotoBoldItalic)
+    };
+    std::unique_ptr<Typeface> typeface(Typeface::createFromFamilies(std::move(families),
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
+    EXPECT_EQ(7, typeface->fStyle.getWeight());
+    EXPECT_FALSE(typeface->fStyle.getItalic());
+}
+
+}  // namespace