| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "Resources.h" |
| #include "SkOSFile.h" |
| #include "SkTestScalerContext.h" |
| #include "SkThread.h" |
| #include "SkUtils.h" |
| #include "sk_tool_utils.h" |
| |
| namespace sk_tool_utils { |
| |
| #include "test_font_data.cpp" |
| |
| static void release_portable_typefaces() { |
| // We'll clean this up in our own tests, but disable for clients. |
| // Chrome seems to have funky multi-process things going on in unit tests that |
| // makes this unsafe to delete when the main process atexit()s. |
| // SkLazyPtr does the same sort of thing. |
| #if SK_DEVELOPER |
| for (int index = 0; index < gTestFontsCount; ++index) { |
| SkTestFontData& fontData = gTestFonts[index]; |
| SkSafeUnref(fontData.fFontCache); |
| } |
| #endif |
| } |
| |
| SK_DECLARE_STATIC_MUTEX(gTestFontMutex); |
| |
| SkTypeface* create_font(const char* name, SkTypeface::Style style) { |
| SkTestFontData* fontData = NULL; |
| const SubFont* sub; |
| if (name) { |
| for (int index = 0; index < gSubFontsCount; ++index) { |
| sub = &gSubFonts[index]; |
| if (!strcmp(name, sub->fName) && sub->fStyle == style) { |
| fontData = &sub->fFont; |
| break; |
| } |
| } |
| if (!fontData) { |
| SkDebugf("missing %s %d\n", name, style); |
| return SkTypeface::CreateFromName(name, style); |
| } |
| } else { |
| sub = &gSubFonts[gDefaultFontIndex]; |
| fontData = &sub->fFont; |
| } |
| SkTestFont* font; |
| { |
| SkAutoMutexAcquire ac(gTestFontMutex); |
| if (fontData->fFontCache) { |
| font = SkSafeRef(fontData->fFontCache); |
| } else { |
| font = SkNEW_ARGS(SkTestFont, (*fontData)); |
| SkDEBUGCODE(font->fDebugName = sub->fName); |
| SkDEBUGCODE(font->fDebugStyle = sub->fStyle); |
| fontData->fFontCache = SkSafeRef(font); |
| atexit(release_portable_typefaces); |
| } |
| } |
| return SkNEW_ARGS(SkTestTypeface, (font, style)); |
| } |
| |
| |
| SkTypeface* resource_font(const char* name, SkTypeface::Style style) { |
| const char* file = NULL; |
| if (name) { |
| for (int index = 0; index < gSubFontsCount; ++index) { |
| const SubFont& sub = gSubFonts[index]; |
| if (!strcmp(name, sub.fName) && sub.fStyle == style) { |
| file = sub.fFile; |
| break; |
| } |
| } |
| if (!file) { |
| return SkTypeface::CreateFromName(name, style); |
| } |
| } else { |
| file = gSubFonts[gDefaultFontIndex].fFile; |
| } |
| SkString filepath(GetResourcePath(file)); |
| if (sk_exists(filepath.c_str())) { |
| return SkTypeface::CreateFromFile(filepath.c_str()); |
| } |
| return SkTypeface::CreateFromName(name, style); |
| } |
| |
| #ifdef SK_DEBUG |
| #include <stdio.h> |
| |
| char const * const gStyleName[] = { |
| "", |
| "_Bold", |
| "_Italic", |
| "_BoldItalic", |
| }; |
| |
| static SkString strip_spaces(const char* str) { |
| SkString result; |
| int count = (int) strlen(str); |
| for (int index = 0; index < count; ++index) { |
| char c = str[index]; |
| if (c != ' ' && c != '-') { |
| result += c; |
| } |
| } |
| return result; |
| } |
| |
| const char gHeader[] = |
| "/*\n" |
| " * Copyright 2014 Google Inc.\n" |
| " *\n" |
| " * Use of this source code is governed by a BSD-style license that can be\n" |
| " * found in the LICENSE file.\n" |
| " */\n" |
| "\n" |
| "// Auto-generated by "; |
| |
| static FILE* font_header() { |
| SkString pathStr(GetResourcePath()); |
| pathStr = SkOSPath::Join(pathStr.c_str(), ".."); |
| pathStr = SkOSPath::Join(pathStr.c_str(), "tools"); |
| pathStr = SkOSPath::Join(pathStr.c_str(), "test_font_data_chars.cpp"); |
| FILE* out = fopen(pathStr.c_str(), "w"); |
| fprintf(out, "%s%s\n\n", gHeader, SkOSPath::Basename(__FILE__).c_str()); |
| return out; |
| } |
| |
| void report_used_chars() { |
| FILE* out = font_header(); |
| for (int index = 0; index < gTestFontsCount; ++index) { |
| SkTestFontData& fontData = gTestFonts[index]; |
| SkTestFont* font = fontData.fFontCache; |
| if (!font) { |
| continue; |
| } |
| SkString name(strip_spaces(font->debugFontName())); |
| fprintf(out, "const char g%s%s[] =\n", name.c_str(), gStyleName[font->fDebugStyle]); |
| SkString used(" \""); |
| for (int c = ' '; c <= '~'; ++c) { |
| int bitOffset = c - ' '; |
| if (font->fDebugBits[bitOffset >> 3] & (1 << (bitOffset & 7))) { |
| if (c == '"' || c == '\\') { |
| used += '\\'; |
| } |
| used += c; |
| } |
| } |
| if (used.size() > 1) { |
| fprintf(out, "%s\"", used.c_str()); |
| } |
| int oIndex = 0; |
| while (font->fDebugOverage[oIndex]) { |
| uint16_t uni = font->fDebugOverage[oIndex]; |
| size_t byteCount = SkUTF16_ToUTF8(&uni, 1, NULL); |
| SkAutoSTMalloc<10, char> utf8(byteCount); |
| SkUTF16_ToUTF8(&uni, 1, utf8); |
| for (unsigned byteIndex = 0; byteIndex < byteCount; ++byteIndex) { |
| char unibyte = utf8[byteIndex]; |
| fprintf(out, " \"\\x%02X\"", (unsigned char) unibyte); |
| } |
| if (++oIndex >= (int) sizeof(font->fDebugOverage)) { |
| break; |
| } |
| } |
| fprintf(out, ";\n"); |
| } |
| fclose(out); |
| } |
| #endif |
| |
| } |