blob: 260956fe57913f2b17bd05fa649e9577500df618 [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();
caryclark@google.com42639cd2012-06-06 12:03:39 +000029 if (false) { // avoid bit rot, suppress warning
30 REPORTER_ASSERT(reporter, fontID);
31 }
reed@google.com17aa07d2012-02-23 14:51:10 +000032
reed@google.com8b0a3352012-04-19 18:52:39 +000033 int count = face->countTables();
reed@google.com17aa07d2012-02-23 14:51:10 +000034
35 SkAutoTMalloc<SkFontTableTag> storage(count);
36 SkFontTableTag* tags = storage.get();
reed@google.comfbd033d2012-02-23 16:15:58 +000037
reed@google.com8b0a3352012-04-19 18:52:39 +000038 int count2 = face->getTableTags(tags);
reed@google.comfbd033d2012-02-23 16:15:58 +000039 REPORTER_ASSERT(reporter, count2 == count);
reed@google.com17aa07d2012-02-23 14:51:10 +000040
41 for (int i = 0; i < count; ++i) {
reed@google.com8b0a3352012-04-19 18:52:39 +000042 size_t size = face->getTableSize(tags[i]);
reed@google.com17aa07d2012-02-23 14:51:10 +000043 REPORTER_ASSERT(reporter, size > 0);
44
45#ifdef DUMP_TABLES
46 char name[5];
47 name[0] = (tags[i] >> 24) & 0xFF;
48 name[1] = (tags[i] >> 16) & 0xFF;
49 name[2] = (tags[i] >> 8) & 0xFF;
50 name[3] = (tags[i] >> 0) & 0xFF;
51 name[4] = 0;
52 SkDebugf("%s %d\n", name, size);
53#endif
54
55 for (size_t j = 0; j < SK_ARRAY_COUNT(gKnownTableSizes); ++j) {
56 if (gKnownTableSizes[j].fTag == tags[i]) {
57 REPORTER_ASSERT(reporter, gKnownTableSizes[j].fSize == size);
58 }
59 }
reed@google.comfbd033d2012-02-23 16:15:58 +000060
61 // do we get the same size from GetTableData and GetTableSize
62 {
63 SkAutoMalloc data(size);
reed@google.com8b0a3352012-04-19 18:52:39 +000064 size_t size2 = face->getTableData(tags[i], 0, size, data.get());
reed@google.comfbd033d2012-02-23 16:15:58 +000065 REPORTER_ASSERT(reporter, size2 == size);
66 }
reed@google.com17aa07d2012-02-23 14:51:10 +000067 }
68}
69
70static void test_tables(skiatest::Reporter* reporter) {
71 static const char* const gNames[] = {
72 NULL, // default font
73 "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
74 "Courier New",
75 };
76
77 for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
78 SkTypeface* face = SkTypeface::CreateFromName(gNames[i],
79 SkTypeface::kNormal);
80 if (face) {
81#ifdef DUMP_TABLES
82 SkDebugf("%s\n", gNames[i]);
83#endif
84 test_tables(reporter, face);
85 face->unref();
86 }
87 }
88}
89
bungeman@google.com34f10262012-03-23 18:11:47 +000090/*
91 * Verifies that the advance values returned by generateAdvance and
92 * generateMetrics match.
93 */
94static void test_advances(skiatest::Reporter* reporter) {
95 static const char* const faces[] = {
96 NULL, // default font
97 "Arial", "Times", "Times New Roman", "Helvetica", "Courier",
98 "Courier New", "Verdana", "monospace",
99 };
100
101 static const struct {
102 SkPaint::Hinting hinting;
103 unsigned flags;
104 } settings[] = {
105 { SkPaint::kNo_Hinting, 0 },
106 { SkPaint::kNo_Hinting, SkPaint::kLinearText_Flag },
107 { SkPaint::kNo_Hinting, SkPaint::kSubpixelText_Flag },
108 { SkPaint::kSlight_Hinting, 0 },
109 { SkPaint::kSlight_Hinting, SkPaint::kLinearText_Flag },
110 { SkPaint::kSlight_Hinting, SkPaint::kSubpixelText_Flag },
111 { SkPaint::kNormal_Hinting, 0 },
112 { SkPaint::kNormal_Hinting, SkPaint::kLinearText_Flag },
113 { SkPaint::kNormal_Hinting, SkPaint::kSubpixelText_Flag },
114 };
115
reed@google.comd074c372012-07-18 13:45:58 +0000116 static const struct {
117 SkScalar fScaleX;
118 SkScalar fSkewX;
119 } gScaleRec[] = {
120 { SK_Scalar1, 0 },
121 { SK_Scalar1/2, 0 },
122 // these two exercise obliquing (skew)
123 { SK_Scalar1, -SK_Scalar1/4 },
124 { SK_Scalar1/2, -SK_Scalar1/4 },
125 };
126
bungeman@google.com34f10262012-03-23 18:11:47 +0000127 SkPaint paint;
128 char txt[] = "long.text.with.lots.of.dots.";
129
130 for (size_t i = 0; i < SK_ARRAY_COUNT(faces); i++) {
131 SkTypeface* face = SkTypeface::CreateFromName(faces[i], SkTypeface::kNormal);
132 paint.setTypeface(face);
133
134 for (size_t j = 0; j < SK_ARRAY_COUNT(settings); j++) {
reed@google.comd074c372012-07-18 13:45:58 +0000135 paint.setHinting(settings[j].hinting);
136 paint.setLinearText((settings[j].flags & SkPaint::kLinearText_Flag) != 0);
137 paint.setSubpixelText((settings[j].flags & SkPaint::kSubpixelText_Flag) != 0);
bungeman@google.com34f10262012-03-23 18:11:47 +0000138
reed@google.comd074c372012-07-18 13:45:58 +0000139 for (size_t k = 0; k < SK_ARRAY_COUNT(gScaleRec); ++k) {
140 paint.setTextScaleX(gScaleRec[k].fScaleX);
141 paint.setTextSkewX(gScaleRec[k].fSkewX);
bungeman@google.com34f10262012-03-23 18:11:47 +0000142
reed@google.comd074c372012-07-18 13:45:58 +0000143 SkRect bounds;
bungeman@google.com34f10262012-03-23 18:11:47 +0000144
reed@google.comd074c372012-07-18 13:45:58 +0000145 // For no hinting and light hinting this should take the
146 // optimized generateAdvance path.
147 SkScalar width1 = paint.measureText(txt, strlen(txt));
bungeman@google.com34f10262012-03-23 18:11:47 +0000148
reed@google.comd074c372012-07-18 13:45:58 +0000149 // Requesting the bounds forces a generateMetrics call.
150 SkScalar width2 = paint.measureText(txt, strlen(txt), &bounds);
bungeman@google.com34f10262012-03-23 18:11:47 +0000151
reed@google.comd074c372012-07-18 13:45:58 +0000152 // SkDebugf("Font: %s, generateAdvance: %f, generateMetrics: %f\n",
153 // faces[i], SkScalarToFloat(width1), SkScalarToFloat(width2));
154
155 REPORTER_ASSERT(reporter, width1 == width2);
156 }
bungeman@google.com34f10262012-03-23 18:11:47 +0000157 }
158 }
159}
160
reed@google.com17aa07d2012-02-23 14:51:10 +0000161static void TestFontHost(skiatest::Reporter* reporter) {
162 test_tables(reporter);
bungeman@google.com34f10262012-03-23 18:11:47 +0000163 test_advances(reporter);
reed@google.com17aa07d2012-02-23 14:51:10 +0000164}
165
166// need tests for SkStrSearch
167
168#include "TestClassDef.h"
169DEFINE_TESTCLASS("FontHost", FontHostTestClass, TestFontHost)