blob: eab7bc4246def544e2e7743c6132a25e08e43384 [file] [log] [blame]
reed@google.com17aa07d2012-02-23 14:51:10 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Test.h"
9#include "SkTypeface.h"
10#include "SkFontHost.h"
11
12//#define DUMP_TABLES
13
14#define kFontTableTag_head SkSetFourByteTag('h', 'e', 'a', 'd')
15#define kFontTableTag_hhea SkSetFourByteTag('h', 'h', 'e', 'a')
reed@google.com17aa07d2012-02-23 14:51:10 +000016#define kFontTableTag_maxp SkSetFourByteTag('m', 'a', 'x', 'p')
17
18static const struct TagSize {
19 SkFontTableTag fTag;
20 size_t fSize;
21} gKnownTableSizes[] = {
22 { kFontTableTag_head, 54 },
23 { kFontTableTag_hhea, 36 },
reed@google.com17aa07d2012-02-23 14:51:10 +000024 { kFontTableTag_maxp, 32 },
25};
26
27static void test_tables(skiatest::Reporter* reporter, SkTypeface* face) {
28 SkFontID fontID = face->uniqueID();
29
30 int count = SkFontHost::CountTables(fontID);
reed@google.com17aa07d2012-02-23 14:51:10 +000031
32 SkAutoTMalloc<SkFontTableTag> storage(count);
33 SkFontTableTag* tags = storage.get();
reed@google.comfbd033d2012-02-23 16:15:58 +000034
35 int count2 = SkFontHost::GetTableTags(fontID, tags);
36 REPORTER_ASSERT(reporter, count2 == count);
reed@google.com17aa07d2012-02-23 14:51:10 +000037
38 for (int i = 0; i < count; ++i) {
39 size_t size = SkFontHost::GetTableSize(fontID, tags[i]);
40 REPORTER_ASSERT(reporter, size > 0);
41
42#ifdef DUMP_TABLES
43 char name[5];
44 name[0] = (tags[i] >> 24) & 0xFF;
45 name[1] = (tags[i] >> 16) & 0xFF;
46 name[2] = (tags[i] >> 8) & 0xFF;
47 name[3] = (tags[i] >> 0) & 0xFF;
48 name[4] = 0;
49 SkDebugf("%s %d\n", name, size);
50#endif
51
52 for (size_t j = 0; j < SK_ARRAY_COUNT(gKnownTableSizes); ++j) {
53 if (gKnownTableSizes[j].fTag == tags[i]) {
54 REPORTER_ASSERT(reporter, gKnownTableSizes[j].fSize == size);
55 }
56 }
reed@google.comfbd033d2012-02-23 16:15:58 +000057
58 // do we get the same size from GetTableData and GetTableSize
59 {
60 SkAutoMalloc data(size);
61 size_t size2 = SkFontHost::GetTableData(fontID, tags[i], 0, size,
62 data.get());
63 REPORTER_ASSERT(reporter, size2 == size);
64 }
reed@google.com17aa07d2012-02-23 14:51:10 +000065 }
66}
67
68static void test_tables(skiatest::Reporter* reporter) {
69 static const char* const gNames[] = {
70 NULL, // default font
71 "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
72 "Courier New",
73 };
74
75 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
76 SkTypeface* face = SkTypeface::CreateFromName(gNames[i],
77 SkTypeface::kNormal);
78 if (face) {
79#ifdef DUMP_TABLES
80 SkDebugf("%s\n", gNames[i]);
81#endif
82 test_tables(reporter, face);
83 face->unref();
84 }
85 }
86}
87
bungeman@google.com34f10262012-03-23 18:11:47 +000088/*
89 * Verifies that the advance values returned by generateAdvance and
90 * generateMetrics match.
91 */
92static void test_advances(skiatest::Reporter* reporter) {
93 static const char* const faces[] = {
94 NULL, // default font
95 "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
96 "Courier New", "Verdana", "monospace",
97 };
98
99 static const struct {
100 SkPaint::Hinting hinting;
101 unsigned flags;
102 } settings[] = {
103 { SkPaint::kNo_Hinting, 0 },
104 { SkPaint::kNo_Hinting, SkPaint::kLinearText_Flag },
105 { SkPaint::kNo_Hinting, SkPaint::kSubpixelText_Flag },
106 { SkPaint::kSlight_Hinting, 0 },
107 { SkPaint::kSlight_Hinting, SkPaint::kLinearText_Flag },
108 { SkPaint::kSlight_Hinting, SkPaint::kSubpixelText_Flag },
109 { SkPaint::kNormal_Hinting, 0 },
110 { SkPaint::kNormal_Hinting, SkPaint::kLinearText_Flag },
111 { SkPaint::kNormal_Hinting, SkPaint::kSubpixelText_Flag },
112 };
113
114 SkPaint paint;
115 char txt[] = "long.text.with.lots.of.dots.";
116
117 for (size_t i = 0; i < SK_ARRAY_COUNT(faces); i++) {
118 SkTypeface* face = SkTypeface::CreateFromName(faces[i], SkTypeface::kNormal);
119 paint.setTypeface(face);
120
121 for (size_t j = 0; j < SK_ARRAY_COUNT(settings); j++) {
122 paint.setHinting(settings[j].hinting);
123 paint.setLinearText((settings[j].flags & SkPaint::kLinearText_Flag) != 0);
124 paint.setSubpixelText((settings[j].flags & SkPaint::kSubpixelText_Flag) != 0);
125
126 SkRect bounds;
127
128 // For no hinting and light hinting this should take the
129 // optimized generateAdvance path.
130 SkScalar width1 = paint.measureText(txt, strlen(txt));
131
132 // Requesting the bounds forces a generateMetrics call.
133 SkScalar width2 = paint.measureText(txt, strlen(txt), &bounds);
134
135 // SkDebugf("Font: %s, generateAdvance: %f, generateMetrics: %f\n",
136 // faces[i], SkScalarToFloat(width1), SkScalarToFloat(width2));
137
138 REPORTER_ASSERT(reporter, width1 == width2);
139 }
140 }
141}
142
reed@google.com17aa07d2012-02-23 14:51:10 +0000143static void TestFontHost(skiatest::Reporter* reporter) {
144 test_tables(reporter);
bungeman@google.com34f10262012-03-23 18:11:47 +0000145 test_advances(reporter);
reed@google.com17aa07d2012-02-23 14:51:10 +0000146}
147
148// need tests for SkStrSearch
149
150#include "TestClassDef.h"
151DEFINE_TESTCLASS("FontHost", FontHostTestClass, TestFontHost)