blob: 5cb65b205c2d6dce1171cde8267721c234de1c0b [file] [log] [blame]
caryclark5fb6bd42014-06-23 11:25:00 -07001/*
2 * Copyright 2014 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
Cary Clark992c7b02014-07-31 08:58:44 -04008#include "Resources.h"
caryclark83ca6282015-06-10 09:31:09 -07009#include "SkFontMgr.h"
Cary Clark992c7b02014-07-31 08:58:44 -040010#include "SkOSFile.h"
11#include "SkTestScalerContext.h"
12#include "SkThread.h"
13#include "SkUtils.h"
14#include "sk_tool_utils.h"
caryclark5fb6bd42014-06-23 11:25:00 -070015
16namespace sk_tool_utils {
17
caryclark83ca6282015-06-10 09:31:09 -070018#include "test_font_monospace.cpp"
19#include "test_font_sans_serif.cpp"
20#include "test_font_serif.cpp"
21#include "test_font_index.cpp"
caryclark5fb6bd42014-06-23 11:25:00 -070022
Cary Clark992c7b02014-07-31 08:58:44 -040023static void release_portable_typefaces() {
24 // We'll clean this up in our own tests, but disable for clients.
25 // Chrome seems to have funky multi-process things going on in unit tests that
26 // makes this unsafe to delete when the main process atexit()s.
27 // SkLazyPtr does the same sort of thing.
28#if SK_DEVELOPER
caryclarkc2a48462014-07-31 06:36:45 -070029 for (int index = 0; index < gTestFontsCount; ++index) {
Cary Clark992c7b02014-07-31 08:58:44 -040030 SkTestFontData& fontData = gTestFonts[index];
31 SkSafeUnref(fontData.fFontCache);
32 }
33#endif
caryclark5fb6bd42014-06-23 11:25:00 -070034}
35
Cary Clark992c7b02014-07-31 08:58:44 -040036SK_DECLARE_STATIC_MUTEX(gTestFontMutex);
37
38SkTypeface* create_font(const char* name, SkTypeface::Style style) {
39 SkTestFontData* fontData = NULL;
40 const SubFont* sub;
41 if (name) {
caryclarkc2a48462014-07-31 06:36:45 -070042 for (int index = 0; index < gSubFontsCount; ++index) {
Cary Clark992c7b02014-07-31 08:58:44 -040043 sub = &gSubFonts[index];
44 if (!strcmp(name, sub->fName) && sub->fStyle == style) {
45 fontData = &sub->fFont;
46 break;
47 }
48 }
49 if (!fontData) {
caryclark83ca6282015-06-10 09:31:09 -070050 // Once all legacy callers to portable fonts are converted, replace this with
51 // SK_CRASH();
Cary Clark992c7b02014-07-31 08:58:44 -040052 SkDebugf("missing %s %d\n", name, style);
caryclark83ca6282015-06-10 09:31:09 -070053 // If we called SkTypeface::CreateFromName() here we'd recurse infinitely,
54 // so we reimplement its core logic here inline without the recursive aspect.
55 SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
56 return fm->legacyCreateTypeface(name, style);
Cary Clark992c7b02014-07-31 08:58:44 -040057 }
58 } else {
59 sub = &gSubFonts[gDefaultFontIndex];
60 fontData = &sub->fFont;
61 }
62 SkTestFont* font;
63 {
64 SkAutoMutexAcquire ac(gTestFontMutex);
65 if (fontData->fFontCache) {
66 font = SkSafeRef(fontData->fFontCache);
67 } else {
68 font = SkNEW_ARGS(SkTestFont, (*fontData));
69 SkDEBUGCODE(font->fDebugName = sub->fName);
70 SkDEBUGCODE(font->fDebugStyle = sub->fStyle);
71 fontData->fFontCache = SkSafeRef(font);
72 atexit(release_portable_typefaces);
73 }
74 }
bungemana4c4a2d2014-10-20 13:33:19 -070075 return SkNEW_ARGS(SkTestTypeface, (font, SkFontStyle(style)));
Cary Clark992c7b02014-07-31 08:58:44 -040076}
77
78
79SkTypeface* resource_font(const char* name, SkTypeface::Style style) {
80 const char* file = NULL;
81 if (name) {
caryclarkc2a48462014-07-31 06:36:45 -070082 for (int index = 0; index < gSubFontsCount; ++index) {
Cary Clark992c7b02014-07-31 08:58:44 -040083 const SubFont& sub = gSubFonts[index];
84 if (!strcmp(name, sub.fName) && sub.fStyle == style) {
85 file = sub.fFile;
86 break;
87 }
88 }
89 if (!file) {
90 return SkTypeface::CreateFromName(name, style);
91 }
92 } else {
93 file = gSubFonts[gDefaultFontIndex].fFile;
94 }
95 SkString filepath(GetResourcePath(file));
96 if (sk_exists(filepath.c_str())) {
97 return SkTypeface::CreateFromFile(filepath.c_str());
98 }
99 return SkTypeface::CreateFromName(name, style);
100}
101
102#ifdef SK_DEBUG
103#include <stdio.h>
104
105char const * const gStyleName[] = {
106 "",
107 "_Bold",
108 "_Italic",
109 "_BoldItalic",
110};
111
112static SkString strip_spaces(const char* str) {
113 SkString result;
114 int count = (int) strlen(str);
115 for (int index = 0; index < count; ++index) {
116 char c = str[index];
117 if (c != ' ' && c != '-') {
118 result += c;
119 }
120 }
121 return result;
122}
123
124const char gHeader[] =
125"/*\n"
126" * Copyright 2014 Google Inc.\n"
127" *\n"
128" * Use of this source code is governed by a BSD-style license that can be\n"
129" * found in the LICENSE file.\n"
130" */\n"
131"\n"
132"// Auto-generated by ";
133
134static FILE* font_header() {
135 SkString pathStr(GetResourcePath());
136 pathStr = SkOSPath::Join(pathStr.c_str(), "..");
137 pathStr = SkOSPath::Join(pathStr.c_str(), "tools");
138 pathStr = SkOSPath::Join(pathStr.c_str(), "test_font_data_chars.cpp");
139 FILE* out = fopen(pathStr.c_str(), "w");
140 fprintf(out, "%s%s\n\n", gHeader, SkOSPath::Basename(__FILE__).c_str());
141 return out;
142}
143
144void report_used_chars() {
145 FILE* out = font_header();
146 for (int index = 0; index < gTestFontsCount; ++index) {
147 SkTestFontData& fontData = gTestFonts[index];
148 SkTestFont* font = fontData.fFontCache;
149 if (!font) {
150 continue;
151 }
152 SkString name(strip_spaces(font->debugFontName()));
153 fprintf(out, "const char g%s%s[] =\n", name.c_str(), gStyleName[font->fDebugStyle]);
154 SkString used(" \"");
155 for (int c = ' '; c <= '~'; ++c) {
156 int bitOffset = c - ' ';
157 if (font->fDebugBits[bitOffset >> 3] & (1 << (bitOffset & 7))) {
158 if (c == '"' || c == '\\') {
159 used += '\\';
160 }
161 used += c;
162 }
163 }
164 if (used.size() > 1) {
165 fprintf(out, "%s\"", used.c_str());
166 }
167 int oIndex = 0;
168 while (font->fDebugOverage[oIndex]) {
169 uint16_t uni = font->fDebugOverage[oIndex];
170 size_t byteCount = SkUTF16_ToUTF8(&uni, 1, NULL);
171 SkAutoSTMalloc<10, char> utf8(byteCount);
172 SkUTF16_ToUTF8(&uni, 1, utf8);
173 for (unsigned byteIndex = 0; byteIndex < byteCount; ++byteIndex) {
174 char unibyte = utf8[byteIndex];
175 fprintf(out, " \"\\x%02X\"", (unsigned char) unibyte);
176 }
177 if (++oIndex >= (int) sizeof(font->fDebugOverage)) {
178 break;
179 }
180 }
181 fprintf(out, ";\n");
182 }
183 fclose(out);
184}
185#endif
186
caryclark5fb6bd42014-06-23 11:25:00 -0700187}