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 15namespace sk_tool_utils { 16 17#include "test_font_data.cpp" 18 19static 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 32SK_DECLARE_STATIC_MUTEX(gTestFontMutex); 33 34SkTypeface* 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, SkFontStyle(style))); 67} 68 69 70SkTypeface* 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 96char const * const gStyleName[] = { 97 "", 98 "_Bold", 99 "_Italic", 100 "_BoldItalic", 101}; 102 103static 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 115const 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 125static 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 135void 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