1 /* 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 8 #include "Resources.h" 9 #include "SkOSFile.h" 10 #include "SkTestScalerContext.h" 11 #include "SkThread.h" 12 #include "SkUtils.h" 13 #include "sk_tool_utils.h" 14 15 namespace sk_tool_utils { 16 17 #include "test_font_data.cpp" 18 19 static void release_portable_typefaces() { 20 // We'll clean this up in our own tests, but disable for clients. 21 // Chrome seems to have funky multi-process things going on in unit tests that 22 // makes this unsafe to delete when the main process atexit()s. 23 // SkLazyPtr does the same sort of thing. 24 #if SK_DEVELOPER 25 for (int index = 0; index < gTestFontsCount; ++index) { 26 SkTestFontData& fontData = gTestFonts[index]; 27 SkSafeUnref(fontData.fFontCache); 28 } 29 #endif 30 } 31 32 SK_DECLARE_STATIC_MUTEX(gTestFontMutex); 33 34 SkTypeface* create_font(const char* name, SkTypeface::Style style) { 35 SkTestFontData* fontData = NULL; 36 const SubFont* sub; 37 if (name) { 38 for (int index = 0; index < gSubFontsCount; ++index) { 39 sub = &gSubFonts[index]; 40 if (!strcmp(name, sub->fName) && sub->fStyle == style) { 41 fontData = &sub->fFont; 42 break; 43 } 44 } 45 if (!fontData) { 46 SkDebugf("missing %s %d\n", name, style); 47 return SkTypeface::CreateFromName(name, style); 48 } 49 } else { 50 sub = &gSubFonts[gDefaultFontIndex]; 51 fontData = &sub->fFont; 52 } 53 SkTestFont* font; 54 { 55 SkAutoMutexAcquire ac(gTestFontMutex); 56 if (fontData->fFontCache) { 57 font = SkSafeRef(fontData->fFontCache); 58 } else { 59 font = SkNEW_ARGS(SkTestFont, (*fontData)); 60 SkDEBUGCODE(font->fDebugName = sub->fName); 61 SkDEBUGCODE(font->fDebugStyle = sub->fStyle); 62 fontData->fFontCache = SkSafeRef(font); 63 atexit(release_portable_typefaces); 64 } 65 } 66 return SkNEW_ARGS(SkTestTypeface, (font, style)); 67 } 68 69 70 SkTypeface* resource_font(const char* name, SkTypeface::Style style) { 71 const char* file = NULL; 72 if (name) { 73 for (int index = 0; index < gSubFontsCount; ++index) { 74 const SubFont& sub = gSubFonts[index]; 75 if (!strcmp(name, sub.fName) && sub.fStyle == style) { 76 file = sub.fFile; 77 break; 78 } 79 } 80 if (!file) { 81 return SkTypeface::CreateFromName(name, style); 82 } 83 } else { 84 file = gSubFonts[gDefaultFontIndex].fFile; 85 } 86 SkString filepath(GetResourcePath(file)); 87 if (sk_exists(filepath.c_str())) { 88 return SkTypeface::CreateFromFile(filepath.c_str()); 89 } 90 return SkTypeface::CreateFromName(name, style); 91 } 92 93 #ifdef SK_DEBUG 94 #include <stdio.h> 95 96 char const * const gStyleName[] = { 97 "", 98 "_Bold", 99 "_Italic", 100 "_BoldItalic", 101 }; 102 103 static SkString strip_spaces(const char* str) { 104 SkString result; 105 int count = (int) strlen(str); 106 for (int index = 0; index < count; ++index) { 107 char c = str[index]; 108 if (c != ' ' && c != '-') { 109 result += c; 110 } 111 } 112 return result; 113 } 114 115 const char gHeader[] = 116 "/*\n" 117 " * Copyright 2014 Google Inc.\n" 118 " *\n" 119 " * Use of this source code is governed by a BSD-style license that can be\n" 120 " * found in the LICENSE file.\n" 121 " */\n" 122 "\n" 123 "// Auto-generated by "; 124 125 static FILE* font_header() { 126 SkString pathStr(GetResourcePath()); 127 pathStr = SkOSPath::Join(pathStr.c_str(), ".."); 128 pathStr = SkOSPath::Join(pathStr.c_str(), "tools"); 129 pathStr = SkOSPath::Join(pathStr.c_str(), "test_font_data_chars.cpp"); 130 FILE* out = fopen(pathStr.c_str(), "w"); 131 fprintf(out, "%s%s\n\n", gHeader, SkOSPath::Basename(__FILE__).c_str()); 132 return out; 133 } 134 135 void report_used_chars() { 136 FILE* out = font_header(); 137 for (int index = 0; index < gTestFontsCount; ++index) { 138 SkTestFontData& fontData = gTestFonts[index]; 139 SkTestFont* font = fontData.fFontCache; 140 if (!font) { 141 continue; 142 } 143 SkString name(strip_spaces(font->debugFontName())); 144 fprintf(out, "const char g%s%s[] =\n", name.c_str(), gStyleName[font->fDebugStyle]); 145 SkString used(" \""); 146 for (int c = ' '; c <= '~'; ++c) { 147 int bitOffset = c - ' '; 148 if (font->fDebugBits[bitOffset >> 3] & (1 << (bitOffset & 7))) { 149 if (c == '"' || c == '\\') { 150 used += '\\'; 151 } 152 used += c; 153 } 154 } 155 if (used.size() > 1) { 156 fprintf(out, "%s\"", used.c_str()); 157 } 158 int oIndex = 0; 159 while (font->fDebugOverage[oIndex]) { 160 uint16_t uni = font->fDebugOverage[oIndex]; 161 size_t byteCount = SkUTF16_ToUTF8(&uni, 1, NULL); 162 SkAutoSTMalloc<10, char> utf8(byteCount); 163 SkUTF16_ToUTF8(&uni, 1, utf8); 164 for (unsigned byteIndex = 0; byteIndex < byteCount; ++byteIndex) { 165 char unibyte = utf8[byteIndex]; 166 fprintf(out, " \"\\x%02X\"", (unsigned char) unibyte); 167 } 168 if (++oIndex >= (int) sizeof(font->fDebugOverage)) { 169 break; 170 } 171 } 172 fprintf(out, ";\n"); 173 } 174 fclose(out); 175 } 176 #endif 177 178 } 179