blob: 234d177e66190b22d8d89eb7a7ed65404a175f44 [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"
reed@google.com8b0a3352012-04-19 18:52:39 +00009#include "SkPaint.h"
reed@google.com17aa07d2012-02-23 14:51:10 +000010#include "SkTypeface.h"
reed@google.com17aa07d2012-02-23 14:51:10 +000011
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
reed@google.com8b0a3352012-04-19 18:52:39 +000030 int count = face->countTables();
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
reed@google.com8b0a3352012-04-19 18:52:39 +000035 int count2 = face->getTableTags(tags);
reed@google.comfbd033d2012-02-23 16:15:58 +000036 REPORTER_ASSERT(reporter, count2 == count);
reed@google.com17aa07d2012-02-23 14:51:10 +000037
38 for (int i = 0; i < count; ++i) {
reed@google.com8b0a3352012-04-19 18:52:39 +000039 size_t size = face->getTableSize(tags[i]);
reed@google.com17aa07d2012-02-23 14:51:10 +000040 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);
reed@google.com8b0a3352012-04-19 18:52:39 +000061 size_t size2 = face->getTableData(tags[i], 0, size, data.get());
reed@google.comfbd033d2012-02-23 16:15:58 +000062 REPORTER_ASSERT(reporter, size2 == size);
63 }
reed@google.com17aa07d2012-02-23 14:51:10 +000064 }
65}
66
67static void test_tables(skiatest::Reporter* reporter) {
68 static const char* const gNames[] = {
69 NULL, // default font
70 "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
71 "Courier New",
72 };
73
74 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
75 SkTypeface* face = SkTypeface::CreateFromName(gNames[i],
76 SkTypeface::kNormal);
77 if (face) {
78#ifdef DUMP_TABLES
79 SkDebugf("%s\n", gNames[i]);
80#endif
81 test_tables(reporter, face);
82 face->unref();
83 }
84 }
85}
86
bungeman@google.com34f10262012-03-23 18:11:47 +000087/*
88 * Verifies that the advance values returned by generateAdvance and
89 * generateMetrics match.
90 */
91static void test_advances(skiatest::Reporter* reporter) {
92 static const char* const faces[] = {
93 NULL, // default font
94 "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
95 "Courier New", "Verdana", "monospace",
96 };
97
98 static const struct {
99 SkPaint::Hinting hinting;
100 unsigned flags;
101 } settings[] = {
102 { SkPaint::kNo_Hinting, 0 },
103 { SkPaint::kNo_Hinting, SkPaint::kLinearText_Flag },
104 { SkPaint::kNo_Hinting, SkPaint::kSubpixelText_Flag },
105 { SkPaint::kSlight_Hinting, 0 },
106 { SkPaint::kSlight_Hinting, SkPaint::kLinearText_Flag },
107 { SkPaint::kSlight_Hinting, SkPaint::kSubpixelText_Flag },
108 { SkPaint::kNormal_Hinting, 0 },
109 { SkPaint::kNormal_Hinting, SkPaint::kLinearText_Flag },
110 { SkPaint::kNormal_Hinting, SkPaint::kSubpixelText_Flag },
111 };
112
113 SkPaint paint;
114 char txt[] = "long.text.with.lots.of.dots.";
115
116 for (size_t i = 0; i < SK_ARRAY_COUNT(faces); i++) {
117 SkTypeface* face = SkTypeface::CreateFromName(faces[i], SkTypeface::kNormal);
118 paint.setTypeface(face);
119
120 for (size_t j = 0; j < SK_ARRAY_COUNT(settings); j++) {
121 paint.setHinting(settings[j].hinting);
122 paint.setLinearText((settings[j].flags & SkPaint::kLinearText_Flag) != 0);
123 paint.setSubpixelText((settings[j].flags & SkPaint::kSubpixelText_Flag) != 0);
124
125 SkRect bounds;
126
127 // For no hinting and light hinting this should take the
128 // optimized generateAdvance path.
129 SkScalar width1 = paint.measureText(txt, strlen(txt));
130
131 // Requesting the bounds forces a generateMetrics call.
132 SkScalar width2 = paint.measureText(txt, strlen(txt), &bounds);
133
134 // SkDebugf("Font: %s, generateAdvance: %f, generateMetrics: %f\n",
135 // faces[i], SkScalarToFloat(width1), SkScalarToFloat(width2));
136
137 REPORTER_ASSERT(reporter, width1 == width2);
138 }
139 }
140}
141
reed@google.com17aa07d2012-02-23 14:51:10 +0000142static void TestFontHost(skiatest::Reporter* reporter) {
143 test_tables(reporter);
bungeman@google.com34f10262012-03-23 18:11:47 +0000144 test_advances(reporter);
reed@google.com17aa07d2012-02-23 14:51:10 +0000145}
146
147// need tests for SkStrSearch
148
149#include "TestClassDef.h"
150DEFINE_TESTCLASS("FontHost", FontHostTestClass, TestFontHost)