11f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com/*
21f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com * Copyright 2013 Google Inc.
31f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com *
41f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com * Use of this source code is governed by a BSD-style license that can be
51f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com * found in the LICENSE file.
61f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com */
71f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com
8209e4b1b70a5e9c2f504de15f038999ed9ee4ae5Hal Canary#include "SkAdvancedTypefaceMetrics.h"
96e45bda29edef867468cbdd7c062d0d99e884656bungeman#include "SkData.h"
10fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner#include "SkFixed.h"
11fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner#include "SkFontMgr.h"
12fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner#include "SkMakeUnique.h"
136e45bda29edef867468cbdd7c062d0d99e884656bungeman#include "SkOTTable_OS_2.h"
146e45bda29edef867468cbdd7c062d0d99e884656bungeman#include "SkSFNTHeader.h"
156e45bda29edef867468cbdd7c062d0d99e884656bungeman#include "SkStream.h"
1682a455f0e9a7a50a399a58be906b48c24aeec056bungeman#include "SkRefCnt.h"
171f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com#include "SkTypeface.h"
1882a455f0e9a7a50a399a58be906b48c24aeec056bungeman#include "SkTypefaceCache.h"
196e45bda29edef867468cbdd7c062d0d99e884656bungeman#include "Resources.h"
208f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
211f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com
226e45bda29edef867468cbdd7c062d0d99e884656bungeman#include <memory>
236e45bda29edef867468cbdd7c062d0d99e884656bungeman
246e45bda29edef867468cbdd7c062d0d99e884656bungemanstatic void TypefaceStyle_test(skiatest::Reporter* reporter,
256e45bda29edef867468cbdd7c062d0d99e884656bungeman                               uint16_t weight, uint16_t width, SkData* data)
266e45bda29edef867468cbdd7c062d0d99e884656bungeman{
276e45bda29edef867468cbdd7c062d0d99e884656bungeman    sk_sp<SkData> dataCopy;
2842943c8aa9c611c18ad0f1a30a27669f3d82239creed    if (!data->unique()) {
296e45bda29edef867468cbdd7c062d0d99e884656bungeman        dataCopy = SkData::MakeWithCopy(data->data(), data->size());
3042943c8aa9c611c18ad0f1a30a27669f3d82239creed        data = dataCopy.get();
316e45bda29edef867468cbdd7c062d0d99e884656bungeman    }
3242943c8aa9c611c18ad0f1a30a27669f3d82239creed    SkSFNTHeader* sfntHeader = static_cast<SkSFNTHeader*>(data->writable_data());
336e45bda29edef867468cbdd7c062d0d99e884656bungeman
346e45bda29edef867468cbdd7c062d0d99e884656bungeman    SkSFNTHeader::TableDirectoryEntry* tableEntry =
356e45bda29edef867468cbdd7c062d0d99e884656bungeman        SkTAfter<SkSFNTHeader::TableDirectoryEntry>(sfntHeader);
366e45bda29edef867468cbdd7c062d0d99e884656bungeman    SkSFNTHeader::TableDirectoryEntry* os2TableEntry = nullptr;
376e45bda29edef867468cbdd7c062d0d99e884656bungeman    int numTables = SkEndian_SwapBE16(sfntHeader->numTables);
386e45bda29edef867468cbdd7c062d0d99e884656bungeman    for (int tableEntryIndex = 0; tableEntryIndex < numTables; ++tableEntryIndex) {
396e45bda29edef867468cbdd7c062d0d99e884656bungeman        if (SkOTTableOS2::TAG == tableEntry[tableEntryIndex].tag) {
406e45bda29edef867468cbdd7c062d0d99e884656bungeman            os2TableEntry = tableEntry + tableEntryIndex;
416e45bda29edef867468cbdd7c062d0d99e884656bungeman            break;
426e45bda29edef867468cbdd7c062d0d99e884656bungeman        }
436e45bda29edef867468cbdd7c062d0d99e884656bungeman    }
446e45bda29edef867468cbdd7c062d0d99e884656bungeman    SkASSERT_RELEASE(os2TableEntry);
456e45bda29edef867468cbdd7c062d0d99e884656bungeman
466e45bda29edef867468cbdd7c062d0d99e884656bungeman    size_t os2TableOffset = SkEndian_SwapBE32(os2TableEntry->offset);
476e45bda29edef867468cbdd7c062d0d99e884656bungeman    SkOTTableOS2_V0* os2Table = SkTAddOffset<SkOTTableOS2_V0>(sfntHeader, os2TableOffset);
486e45bda29edef867468cbdd7c062d0d99e884656bungeman    os2Table->usWeightClass.value = SkEndian_SwapBE16(weight);
496e45bda29edef867468cbdd7c062d0d99e884656bungeman    using WidthType = SkOTTableOS2_V0::WidthClass::Value;
506e45bda29edef867468cbdd7c062d0d99e884656bungeman    os2Table->usWidthClass.value = static_cast<WidthType>(SkEndian_SwapBE16(width));
516e45bda29edef867468cbdd7c062d0d99e884656bungeman
5242943c8aa9c611c18ad0f1a30a27669f3d82239creed    sk_sp<SkTypeface> newTypeface(SkTypeface::MakeFromStream(new SkMemoryStream(sk_ref_sp(data))));
53cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein    if (!newTypeface) {
54cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein        // Not all SkFontMgr can MakeFromStream().
55cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein        return;
56cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein    }
576e45bda29edef867468cbdd7c062d0d99e884656bungeman
586e45bda29edef867468cbdd7c062d0d99e884656bungeman    SkFontStyle newStyle = newTypeface->fontStyle();
596e45bda29edef867468cbdd7c062d0d99e884656bungeman
606e45bda29edef867468cbdd7c062d0d99e884656bungeman    //printf("%d, %f\n", weight, (newStyle.weight() - (float)0x7FFF) / (float)0x7FFF);
616e45bda29edef867468cbdd7c062d0d99e884656bungeman    //printf("%d, %f\n", width , (newStyle.width()  - (float)0x7F)   / (float)0x7F);
626e45bda29edef867468cbdd7c062d0d99e884656bungeman    //printf("%d, %d\n", weight, newStyle.weight());
636e45bda29edef867468cbdd7c062d0d99e884656bungeman    //printf("%d, %d\n", width , newStyle.width());
646e45bda29edef867468cbdd7c062d0d99e884656bungeman
656e45bda29edef867468cbdd7c062d0d99e884656bungeman    // Some back-ends (CG, GDI, DW) support OS/2 version A which uses 0 - 10 (but all differently).
666e45bda29edef867468cbdd7c062d0d99e884656bungeman    REPORTER_ASSERT(reporter,
676e45bda29edef867468cbdd7c062d0d99e884656bungeman                    newStyle.weight() == weight ||
686e45bda29edef867468cbdd7c062d0d99e884656bungeman                    (weight <=   10 && newStyle.weight() == 100 * weight) ||
696e45bda29edef867468cbdd7c062d0d99e884656bungeman                    (weight ==    4 && newStyle.weight() == 350) ||  // GDI weirdness
706e45bda29edef867468cbdd7c062d0d99e884656bungeman                    (weight ==    5 && newStyle.weight() == 400) ||  // GDI weirdness
716e45bda29edef867468cbdd7c062d0d99e884656bungeman                    (weight ==    0 && newStyle.weight() ==   1) ||  // DW weirdness
726e45bda29edef867468cbdd7c062d0d99e884656bungeman                    (weight == 1000 && newStyle.weight() == 999)     // DW weirdness
736e45bda29edef867468cbdd7c062d0d99e884656bungeman    );
746e45bda29edef867468cbdd7c062d0d99e884656bungeman
756e45bda29edef867468cbdd7c062d0d99e884656bungeman    // Some back-ends (GDI) don't support width, ensure these always report 'medium'.
766e45bda29edef867468cbdd7c062d0d99e884656bungeman    REPORTER_ASSERT(reporter,
776e45bda29edef867468cbdd7c062d0d99e884656bungeman                    newStyle.width() == width ||
786e45bda29edef867468cbdd7c062d0d99e884656bungeman                    newStyle.width() == 5);
796e45bda29edef867468cbdd7c062d0d99e884656bungeman}
806e45bda29edef867468cbdd7c062d0d99e884656bungemanDEF_TEST(TypefaceStyle, reporter) {
8153e5e7d4ce9d203fadc36b6349bcbb68862f0d22Hal Canary    std::unique_ptr<SkStreamAsset> stream(GetResourceAsStream("fonts/Em.ttf"));
826e45bda29edef867468cbdd7c062d0d99e884656bungeman    if (!stream) {
8353e5e7d4ce9d203fadc36b6349bcbb68862f0d22Hal Canary        REPORT_FAILURE(reporter, "fonts/Em.ttf", SkString("Cannot load resource"));
846e45bda29edef867468cbdd7c062d0d99e884656bungeman        return;
856e45bda29edef867468cbdd7c062d0d99e884656bungeman    }
866e45bda29edef867468cbdd7c062d0d99e884656bungeman    sk_sp<SkData> data(SkData::MakeFromStream(stream.get(), stream->getLength()));
876e45bda29edef867468cbdd7c062d0d99e884656bungeman
886e45bda29edef867468cbdd7c062d0d99e884656bungeman    using SkFS = SkFontStyle;
896e45bda29edef867468cbdd7c062d0d99e884656bungeman    for (int weight = SkFS::kInvisible_Weight; weight <= SkFS::kExtraBlack_Weight; ++weight) {
906e45bda29edef867468cbdd7c062d0d99e884656bungeman        TypefaceStyle_test(reporter, weight, 5, data.get());
916e45bda29edef867468cbdd7c062d0d99e884656bungeman    }
92d783e08004e2daace50dfcfebb66727b4c13794ebungeman    for (int width = SkFS::kUltraCondensed_Width; width <= SkFS::kUltraExpanded_Width; ++width) {
936e45bda29edef867468cbdd7c062d0d99e884656bungeman        TypefaceStyle_test(reporter, 400, width, data.get());
946e45bda29edef867468cbdd7c062d0d99e884656bungeman    }
956e45bda29edef867468cbdd7c062d0d99e884656bungeman}
966e45bda29edef867468cbdd7c062d0d99e884656bungeman
97fc497343cbcbd526f77da913ae2feca0e1b1b866Ben WagnerDEF_TEST(TypefaceAxes, reporter) {
9853e5e7d4ce9d203fadc36b6349bcbb68862f0d22Hal Canary    std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("fonts/Distortable.ttf"));
99fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (!distortable) {
100fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        REPORT_FAILURE(reporter, "distortable", SkString());
101fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
102fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
1039aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    constexpr int numberOfAxesInDistortable = 1;
104fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
105fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    sk_sp<SkFontMgr> fm = SkFontMgr::RefDefault();
1069aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    // The position may be over specified. If there are multiple values for a given axis,
1079aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    // ensure the last one since that's what css-fonts-4 requires.
108fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    const SkFontArguments::VariationPosition::Coordinate position[] = {
1099aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman        { SkSetFourByteTag('w','g','h','t'), 1.618033988749895f },
1109aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman        { SkSetFourByteTag('w','g','h','t'), SK_ScalarSqrt2 },
111fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    };
112fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    SkFontArguments params;
113fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    params.setVariationDesignPosition({position, SK_ARRAY_COUNT(position)});
114fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    // TODO: if axes are set and the back-end doesn't support them, should we create the typeface?
115592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(distortable), params);
116fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
117cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein    if (!typeface) {
118cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein        // Not all SkFontMgr can makeFromStream().
119cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein        return;
120cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein    }
121cb6940bf42e39271afe0fb3c2bfdd9e28d12f504Mike Klein
122fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    int count = typeface->getVariationDesignPosition(nullptr, 0);
123fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (count == -1) {
124fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
125fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
1269aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    REPORTER_ASSERT(reporter, count == numberOfAxesInDistortable);
127fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
1289aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    SkFontArguments::VariationPosition::Coordinate positionRead[numberOfAxesInDistortable];
129fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    count = typeface->getVariationDesignPosition(positionRead, SK_ARRAY_COUNT(positionRead));
1309aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    REPORTER_ASSERT(reporter, count == SK_ARRAY_COUNT(positionRead));
131fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
1329aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    REPORTER_ASSERT(reporter, positionRead[0].axis == position[1].axis);
133fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
134fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    // Convert to fixed for "almost equal".
135fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    SkFixed fixedRead = SkScalarToFixed(positionRead[0].value);
1369aec8945f0e0cc88c33c2440f2163d36c7198bf6bungeman    SkFixed fixedOriginal = SkScalarToFixed(position[1].value);
137fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    REPORTER_ASSERT(reporter, fixedRead == fixedOriginal);
138fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner}
139fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
140fc497343cbcbd526f77da913ae2feca0e1b1b866Ben WagnerDEF_TEST(TypefaceVariationIndex, reporter) {
14153e5e7d4ce9d203fadc36b6349bcbb68862f0d22Hal Canary    std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("fonts/Distortable.ttf"));
142fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (!distortable) {
143fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        REPORT_FAILURE(reporter, "distortable", SkString());
144fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
145fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
146fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
147fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    sk_sp<SkFontMgr> fm = SkFontMgr::RefDefault();
148fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    SkFontArguments params;
149fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    // The first named variation position in Distortable is 'Thin'.
150fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    params.setCollectionIndex(0x00010000);
151592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(distortable), params);
152fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (!typeface) {
153fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        // FreeType is the only weird thing that supports this, Skia just needs to make sure if it
154fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        // gets one of these things make sense.
155fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
156fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
157fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
158fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    int count = typeface->getVariationDesignPosition(nullptr, 0);
159fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (!(count == 1)) {
160fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        REPORT_FAILURE(reporter, "count == 1", SkString());
161fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
162fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
163fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
164fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    SkFontArguments::VariationPosition::Coordinate positionRead[1];
165fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    count = typeface->getVariationDesignPosition(positionRead, SK_ARRAY_COUNT(positionRead));
166fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (count == -1) {
167fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
168fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
169fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    if (!(count == 1)) {
170fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        REPORT_FAILURE(reporter, "count == 1", SkString());
171fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return;
172fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
173fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    REPORTER_ASSERT(reporter, positionRead[0].axis == SkSetFourByteTag('w','g','h','t'));
174fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    REPORTER_ASSERT(reporter, positionRead[0].value == 0.5);
175fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner}
176fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner
177e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(Typeface, reporter) {
1781f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com
179ee6a9919a362e16c1d84a870ce867d1ad7b8a141mboc    sk_sp<SkTypeface> t1(SkTypeface::MakeFromName(nullptr, SkFontStyle()));
18067ef5d76406d702e7afe4ec5b490a75d9bcaba10Ben Wagner    sk_sp<SkTypeface> t2(SkTypeface::MakeDefault());
1811f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com
1821f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com    REPORTER_ASSERT(reporter, SkTypeface::Equal(t1.get(), t2.get()));
183a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    REPORTER_ASSERT(reporter, SkTypeface::Equal(nullptr, t1.get()));
184a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    REPORTER_ASSERT(reporter, SkTypeface::Equal(nullptr, t2.get()));
185a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    REPORTER_ASSERT(reporter, SkTypeface::Equal(t1.get(), nullptr));
186a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    REPORTER_ASSERT(reporter, SkTypeface::Equal(t2.get(), nullptr));
1871f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com}
18882a455f0e9a7a50a399a58be906b48c24aeec056bungeman
189a821af83890d3b365c7b871f939737d47c48139cbungemannamespace {
190a821af83890d3b365c7b871f939737d47c48139cbungeman
19182a455f0e9a7a50a399a58be906b48c24aeec056bungemanclass SkEmptyTypeface : public SkTypeface {
19282a455f0e9a7a50a399a58be906b48c24aeec056bungemanpublic:
193e3aea10428d1597838fd563c92340beaf969a9b4bungeman    static sk_sp<SkTypeface> Create() { return sk_sp<SkTypeface>(new SkEmptyTypeface()); }
19482a455f0e9a7a50a399a58be906b48c24aeec056bungemanprotected:
195e3aea10428d1597838fd563c92340beaf969a9b4bungeman    SkEmptyTypeface() : SkTypeface(SkFontStyle(), true) { }
19682a455f0e9a7a50a399a58be906b48c24aeec056bungeman
19782a455f0e9a7a50a399a58be906b48c24aeec056bungeman    SkStreamAsset* onOpenStream(int* ttcIndex) const override { return nullptr; }
19882a455f0e9a7a50a399a58be906b48c24aeec056bungeman    SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
19982a455f0e9a7a50a399a58be906b48c24aeec056bungeman                                           const SkDescriptor*) const override {
20082a455f0e9a7a50a399a58be906b48c24aeec056bungeman        return nullptr;
20182a455f0e9a7a50a399a58be906b48c24aeec056bungeman    }
20282a455f0e9a7a50a399a58be906b48c24aeec056bungeman    void onFilterRec(SkScalerContextRec*) const override { }
203209e4b1b70a5e9c2f504de15f038999ed9ee4ae5Hal Canary    std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
204209e4b1b70a5e9c2f504de15f038999ed9ee4ae5Hal Canary        return nullptr;
205209e4b1b70a5e9c2f504de15f038999ed9ee4ae5Hal Canary    }
20682a455f0e9a7a50a399a58be906b48c24aeec056bungeman    void onGetFontDescriptor(SkFontDescriptor*, bool*) const override { }
20782a455f0e9a7a50a399a58be906b48c24aeec056bungeman    virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
20882a455f0e9a7a50a399a58be906b48c24aeec056bungeman                                uint16_t glyphs[], int glyphCount) const override {
20982a455f0e9a7a50a399a58be906b48c24aeec056bungeman        SK_ABORT("unimplemented");
21082a455f0e9a7a50a399a58be906b48c24aeec056bungeman        return 0;
21182a455f0e9a7a50a399a58be906b48c24aeec056bungeman    }
212fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    int onCountGlyphs() const override { return 0; }
213fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    int onGetUPEM() const override { return 0; }
21482a455f0e9a7a50a399a58be906b48c24aeec056bungeman    void onGetFamilyName(SkString* familyName) const override { familyName->reset(); }
21582a455f0e9a7a50a399a58be906b48c24aeec056bungeman    SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override {
21682a455f0e9a7a50a399a58be906b48c24aeec056bungeman        SK_ABORT("unimplemented");
21782a455f0e9a7a50a399a58be906b48c24aeec056bungeman        return nullptr;
218fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    }
219fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
220fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner                                     int coordinateCount) const override
221fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    {
222fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner        return 0;
223fc497343cbcbd526f77da913ae2feca0e1b1b866Ben Wagner    }
22482a455f0e9a7a50a399a58be906b48c24aeec056bungeman    int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
22582a455f0e9a7a50a399a58be906b48c24aeec056bungeman    size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
22682a455f0e9a7a50a399a58be906b48c24aeec056bungeman};
22782a455f0e9a7a50a399a58be906b48c24aeec056bungeman
228a821af83890d3b365c7b871f939737d47c48139cbungeman}
229a821af83890d3b365c7b871f939737d47c48139cbungeman
23082a455f0e9a7a50a399a58be906b48c24aeec056bungemanstatic bool count_proc(SkTypeface* face, void* ctx) {
23182a455f0e9a7a50a399a58be906b48c24aeec056bungeman    int* count = static_cast<int*>(ctx);
23282a455f0e9a7a50a399a58be906b48c24aeec056bungeman    *count = *count + 1;
23382a455f0e9a7a50a399a58be906b48c24aeec056bungeman    return false;
23482a455f0e9a7a50a399a58be906b48c24aeec056bungeman}
23582a455f0e9a7a50a399a58be906b48c24aeec056bungemanstatic int count(skiatest::Reporter* reporter, const SkTypefaceCache& cache) {
23682a455f0e9a7a50a399a58be906b48c24aeec056bungeman    int count = 0;
23782a455f0e9a7a50a399a58be906b48c24aeec056bungeman    SkTypeface* none = cache.findByProcAndRef(count_proc, &count);
23882a455f0e9a7a50a399a58be906b48c24aeec056bungeman    REPORTER_ASSERT(reporter, none == nullptr);
23982a455f0e9a7a50a399a58be906b48c24aeec056bungeman    return count;
24082a455f0e9a7a50a399a58be906b48c24aeec056bungeman}
24182a455f0e9a7a50a399a58be906b48c24aeec056bungeman
24282a455f0e9a7a50a399a58be906b48c24aeec056bungemanDEF_TEST(TypefaceCache, reporter) {
243e3aea10428d1597838fd563c92340beaf969a9b4bungeman    sk_sp<SkTypeface> t1(SkEmptyTypeface::Create());
24482a455f0e9a7a50a399a58be906b48c24aeec056bungeman    {
24582a455f0e9a7a50a399a58be906b48c24aeec056bungeman        SkTypefaceCache cache;
24682a455f0e9a7a50a399a58be906b48c24aeec056bungeman        REPORTER_ASSERT(reporter, count(reporter, cache) == 0);
24782a455f0e9a7a50a399a58be906b48c24aeec056bungeman        {
248e3aea10428d1597838fd563c92340beaf969a9b4bungeman            sk_sp<SkTypeface> t0(SkEmptyTypeface::Create());
24982a455f0e9a7a50a399a58be906b48c24aeec056bungeman            cache.add(t0.get());
25082a455f0e9a7a50a399a58be906b48c24aeec056bungeman            REPORTER_ASSERT(reporter, count(reporter, cache) == 1);
25182a455f0e9a7a50a399a58be906b48c24aeec056bungeman            cache.add(t1.get());
25282a455f0e9a7a50a399a58be906b48c24aeec056bungeman            REPORTER_ASSERT(reporter, count(reporter, cache) == 2);
25382a455f0e9a7a50a399a58be906b48c24aeec056bungeman            cache.purgeAll();
25482a455f0e9a7a50a399a58be906b48c24aeec056bungeman            REPORTER_ASSERT(reporter, count(reporter, cache) == 2);
25582a455f0e9a7a50a399a58be906b48c24aeec056bungeman        }
25682a455f0e9a7a50a399a58be906b48c24aeec056bungeman        REPORTER_ASSERT(reporter, count(reporter, cache) == 2);
25782a455f0e9a7a50a399a58be906b48c24aeec056bungeman        cache.purgeAll();
25882a455f0e9a7a50a399a58be906b48c24aeec056bungeman        REPORTER_ASSERT(reporter, count(reporter, cache) == 1);
25982a455f0e9a7a50a399a58be906b48c24aeec056bungeman    }
26082a455f0e9a7a50a399a58be906b48c24aeec056bungeman    REPORTER_ASSERT(reporter, t1->unique());
26182a455f0e9a7a50a399a58be906b48c24aeec056bungeman}
262