1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Resources.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAutoMalloc.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkEndian.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFontStream.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSFile.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypeface.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Test.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define DUMP_TABLES
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define DUMP_TTC_TABLES
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define kFontTableTag_head          SkSetFourByteTag('h', 'e', 'a', 'd')
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define kFontTableTag_hhea          SkSetFourByteTag('h', 'h', 'e', 'a')
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define kFontTableTag_maxp          SkSetFourByteTag('m', 'a', 'x', 'p')
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const struct TagSize {
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontTableTag  fTag;
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t          fSize;
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} gKnownTableSizes[] = {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {   kFontTableTag_head,         54 },
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {   kFontTableTag_hhea,         36 },
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test that getUnitsPerEm() agrees with a direct lookup in the 'head' table
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// (if that table is available).
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_unitsPerEm(skiatest::Reporter* reporter, const sk_sp<SkTypeface>& face) {
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int nativeUPEM = face->getUnitsPerEm();
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int tableUPEM = -1;
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t size = face->getTableSize(kFontTableTag_head);
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (size) {
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // unitsPerEm is at offset 18 into the 'head' table.
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint16_t rawUPEM;
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        face->getTableData(kFontTableTag_head, 18, sizeof(rawUPEM), &rawUPEM);
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        tableUPEM = SkEndian_SwapBE16(rawUPEM);
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (tableUPEM >= 0) {
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, tableUPEM == nativeUPEM);
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test that countGlyphs() agrees with a direct lookup in the 'maxp' table
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// (if that table is available).
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_countGlyphs(skiatest::Reporter* reporter, const sk_sp<SkTypeface>& face) {
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int nativeGlyphs = face->countGlyphs();
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int tableGlyphs = -1;
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t size = face->getTableSize(kFontTableTag_maxp);
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (size) {
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // glyphs is at offset 4 into the 'maxp' table.
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint16_t rawGlyphs;
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        face->getTableData(kFontTableTag_maxp, 4, sizeof(rawGlyphs), &rawGlyphs);
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        tableGlyphs = SkEndian_SwapBE16(rawGlyphs);
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (tableGlyphs >= 0) {
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, tableGlyphs == nativeGlyphs);
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// The following three are all the same code points in various encodings.
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// a中Яיו��a��
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint8_t utf8Chars[] = { 0x61, 0xE4,0xB8,0xAD, 0xD0,0xAF, 0xD7,0x99, 0xD7,0x95, 0xF0,0x9D,0x84,0x9E, 0x61, 0xF0,0xA0,0xAE,0x9F };
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint16_t utf16Chars[] = { 0x0061, 0x4E2D, 0x042F, 0x05D9, 0x05D5, 0xD834,0xDD1E, 0x0061, 0xD842,0xDF9F };
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint32_t utf32Chars[] = { 0x00000061, 0x00004E2D, 0x0000042F, 0x000005D9, 0x000005D5, 0x0001D11E, 0x00000061, 0x00020B9F };
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct CharsToGlyphs_TestData {
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const void* chars;
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int charCount;
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t charsByteLength;
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTypeface::Encoding typefaceEncoding;
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* name;
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} static charsToGlyphs_TestData[] = {
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { utf8Chars, 8, sizeof(utf8Chars), SkTypeface::kUTF8_Encoding, "Simple UTF-8" },
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { utf16Chars, 8, sizeof(utf16Chars), SkTypeface::kUTF16_Encoding, "Simple UTF-16" },
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { utf32Chars, 8, sizeof(utf32Chars), SkTypeface::kUTF32_Encoding, "Simple UTF-32" },
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Test that SkPaint::textToGlyphs agrees with SkTypeface::charsToGlyphs.
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_charsToGlyphs(skiatest::Reporter* reporter, const sk_sp<SkTypeface>& face) {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t paintGlyphIds[256];
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t faceGlyphIds[256];
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (size_t testIndex = 0; testIndex < SK_ARRAY_COUNT(charsToGlyphs_TestData); ++testIndex) {
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        CharsToGlyphs_TestData& test = charsToGlyphs_TestData[testIndex];
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setTypeface(face);
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setTextEncoding((SkPaint::TextEncoding)test.typefaceEncoding);
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.textToGlyphs(test.chars, test.charsByteLength, paintGlyphIds);
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        face->charsToGlyphs(test.chars, test.typefaceEncoding, faceGlyphIds, test.charCount);
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < test.charCount; ++i) {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkString name;
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            face->getFamilyName(&name);
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkString a;
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            a.appendf("%s, paintGlyphIds[%d] = %d, faceGlyphIds[%d] = %d, face = %s",
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      test.name, i, (int)paintGlyphIds[i], i, (int)faceGlyphIds[i], name.c_str());
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paintGlyphIds[i] == faceGlyphIds[i], a.c_str());
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_fontstream(skiatest::Reporter* reporter, SkStream* stream, int ttcIndex) {
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int n = SkFontStream::GetTableTags(stream, ttcIndex, nullptr);
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoTArray<SkFontTableTag> array(n);
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int n2 = SkFontStream::GetTableTags(stream, ttcIndex, array.get());
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    REPORTER_ASSERT(reporter, n == n2);
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < n; ++i) {
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef DUMP_TTC_TABLES
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString str;
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkFontTableTag t = array[i];
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str.appendUnichar((t >> 24) & 0xFF);
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str.appendUnichar((t >> 16) & 0xFF);
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str.appendUnichar((t >>  8) & 0xFF);
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str.appendUnichar((t >>  0) & 0xFF);
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("[%d:%d] '%s'\n", ttcIndex, i, str.c_str());
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t size = SkFontStream::GetTableSize(stream, ttcIndex, array[i]);
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t j = 0; j < SK_ARRAY_COUNT(gKnownTableSizes); ++j) {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (gKnownTableSizes[j].fTag == array[i]) {
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, gKnownTableSizes[j].fSize == size);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_fontstream(skiatest::Reporter* reporter) {
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::unique_ptr<SkStreamAsset> stream(GetResourceAsStream("fonts/test.ttc"));
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!stream) {
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Skipping FontHostTest::test_fontstream\n");
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int count = SkFontStream::CountTTCEntries(stream.get());
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef DUMP_TTC_TABLES
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("CountTTCEntries %d\n", count);
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < count; ++i) {
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        test_fontstream(reporter, stream.get(), i);
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_symbolfont(skiatest::Reporter* reporter) {
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkUnichar c = 0xf021;
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t g;
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTypeface(MakeResourceAsTypeface("fonts/SpiderSymbol.ttf"));
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.textToGlyphs(&c, 4, &g);
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!paint.getTypeface()) {
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("Skipping FontHostTest::test_symbolfont\n");
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    REPORTER_ASSERT(reporter, g == 3);
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_tables(skiatest::Reporter* reporter, const sk_sp<SkTypeface>& face) {
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (false) { // avoid bit rot, suppress warning
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkFontID fontID = face->uniqueID();
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, fontID);
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int count = face->countTables();
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoTMalloc<SkFontTableTag> storage(count);
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkFontTableTag* tags = storage.get();
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int count2 = face->getTableTags(tags);
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    REPORTER_ASSERT(reporter, count2 == count);
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < count; ++i) {
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t size = face->getTableSize(tags[i]);
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, size > 0);
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef DUMP_TABLES
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char name[5];
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name[0] = (tags[i] >> 24) & 0xFF;
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name[1] = (tags[i] >> 16) & 0xFF;
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name[2] = (tags[i] >>  8) & 0xFF;
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name[3] = (tags[i] >>  0) & 0xFF;
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name[4] = 0;
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("%s %d\n", name, size);
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t j = 0; j < SK_ARRAY_COUNT(gKnownTableSizes); ++j) {
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (gKnownTableSizes[j].fTag == tags[i]) {
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, gKnownTableSizes[j].fSize == size);
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // do we get the same size from GetTableData and GetTableSize
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkAutoMalloc data(size);
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            size_t size2 = face->getTableData(tags[i], 0, size, data.get());
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, size2 == size);
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_tables(skiatest::Reporter* reporter) {
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const char* const gNames[] = {
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        nullptr,   // default font
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Helvetica", "Arial",
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Times", "Times New Roman",
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Courier", "Courier New",
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Terminal", "MS Sans Serif",
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Hiragino Mincho ProN", "MS PGothic",
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<SkTypeface> face(SkTypeface::MakeFromName(gNames[i], SkFontStyle()));
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (face) {
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef DUMP_TABLES
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("%s\n", gNames[i]);
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            test_tables(reporter, face);
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            test_unitsPerEm(reporter, face);
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            test_countGlyphs(reporter, face);
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            test_charsToGlyphs(reporter, face);
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Verifies that the advance values returned by generateAdvance and
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * generateMetrics match.
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void test_advances(skiatest::Reporter* reporter) {
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const char* const faces[] = {
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        nullptr,   // default font
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        "Courier New", "Verdana", "monospace",
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const struct {
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint::Hinting    hinting;
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        unsigned            flags;
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } settings[] = {
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kNo_Hinting,     0                               },
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kNo_Hinting,     SkPaint::kLinearText_Flag       },
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kNo_Hinting,     SkPaint::kSubpixelText_Flag     },
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kSlight_Hinting, 0                               },
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kSlight_Hinting, SkPaint::kLinearText_Flag       },
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kSlight_Hinting, SkPaint::kSubpixelText_Flag     },
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kNormal_Hinting, 0                               },
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kNormal_Hinting, SkPaint::kLinearText_Flag       },
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SkPaint::kNormal_Hinting, SkPaint::kSubpixelText_Flag     },
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const struct {
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar    fScaleX;
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar    fSkewX;
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } gScaleRec[] = {
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SK_Scalar1, 0 },
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SK_Scalar1/2, 0 },
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // these two exercise obliquing (skew)
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SK_Scalar1, -SK_Scalar1/4 },
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        { SK_Scalar1/2, -SK_Scalar1/4 },
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char txt[] = "long.text.with.lots.of.dots.";
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (size_t i = 0; i < SK_ARRAY_COUNT(faces); i++) {
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setTypeface(SkTypeface::MakeFromName(faces[i], SkFontStyle()));
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t j = 0; j  < SK_ARRAY_COUNT(settings); j++) {
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setHinting(settings[j].hinting);
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setLinearText((settings[j].flags & SkPaint::kLinearText_Flag) != 0);
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint.setSubpixelText((settings[j].flags & SkPaint::kSubpixelText_Flag) != 0);
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (size_t k = 0; k < SK_ARRAY_COUNT(gScaleRec); ++k) {
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setTextScaleX(gScaleRec[k].fScaleX);
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paint.setTextSkewX(gScaleRec[k].fSkewX);
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkRect bounds;
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // For no hinting and light hinting this should take the
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // optimized generateAdvance path.
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalar width1 = paint.measureText(txt, strlen(txt));
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Requesting the bounds forces a generateMetrics call.
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalar width2 = paint.measureText(txt, strlen(txt), &bounds);
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // SkDebugf("Font: %s, generateAdvance: %f, generateMetrics: %f\n",
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                //    faces[i], SkScalarToFloat(width1), SkScalarToFloat(width2));
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, width1 == width2);
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(FontHost, reporter) {
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    test_tables(reporter);
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    test_fontstream(reporter);
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    test_advances(reporter);
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    test_symbolfont(reporter);
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// need tests for SkStrSearch
318