123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkStream.h"
- #include "include/core/SkString.h"
- #include "include/core/SkTypeface.h"
- #include "src/core/SkFontDescriptor.h"
- #include "src/core/SkOpts.h"
- #include "src/sfnt/SkOTUtils.h"
- #include "src/utils/SkUTF.h"
- #include "SkWhitelistChecksums.inc"
- #define WHITELIST_DEBUG 0
- extern void WhitelistSerializeTypeface(const SkTypeface*, SkWStream* );
- sk_sp<SkTypeface> WhitelistDeserializeTypeface(SkStream* );
- extern bool CheckChecksums();
- extern bool GenerateChecksums();
- #if WHITELIST_DEBUG
- static bool timesNewRomanSerializedNameOnly = false;
- #endif
- #define SUBNAME_PREFIX "sk_"
- static bool font_name_is_local(const char* fontName, SkFontStyle style) {
- if (!strcmp(fontName, "DejaVu Sans")) {
- return true;
- }
- sk_sp<SkTypeface> defaultFace(SkTypeface::MakeFromName(nullptr, style));
- sk_sp<SkTypeface> foundFace(SkTypeface::MakeFromName(fontName, style));
- return defaultFace != foundFace;
- }
- static int whitelist_name_index(const SkTypeface* tf) {
- SkString fontNameStr;
- sk_sp<SkTypeface::LocalizedStrings> nameIter =
- SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*tf);
- SkTypeface::LocalizedString familyNameLocalized;
- while (nameIter->next(&familyNameLocalized)) {
- fontNameStr = familyNameLocalized.fString;
- // check against permissible list of names
- for (int i = 0; i < whitelistCount; ++i) {
- if (fontNameStr.equals(whitelist[i].fFontName)) {
- return i;
- }
- }
- }
- #if WHITELIST_DEBUG
- sk_sp<SkTypeface::LocalizedStrings> debugIter =
- SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*tf);
- while (debugIter->next(&familyNameLocalized)) {
- SkDebugf("no match fontName=\"%s\"\n", familyNameLocalized.fString.c_str());
- }
- #endif
- return -1;
- }
- static uint32_t compute_checksum(const SkTypeface* tf) {
- std::unique_ptr<SkFontData> fontData = tf->makeFontData();
- if (!fontData) {
- return 0;
- }
- SkStreamAsset* fontStream = fontData->getStream();
- if (!fontStream) {
- return 0;
- }
- SkTDArray<char> data;
- size_t length = fontStream->getLength();
- if (!length) {
- return 0;
- }
- data.setCount((int) length);
- if (!fontStream->peek(data.begin(), length)) {
- return 0;
- }
- return SkOpts::hash(data.begin(), length);
- }
- static void serialize_sub(const char* fontName, SkFontStyle style, SkWStream* wstream) {
- SkFontDescriptor desc;
- SkString subName(SUBNAME_PREFIX);
- subName.append(fontName);
- const char* familyName = subName.c_str();
- desc.setFamilyName(familyName);
- desc.setStyle(style);
- desc.serialize(wstream);
- #if WHITELIST_DEBUG
- for (int i = 0; i < whitelistCount; ++i) {
- if (!strcmp(fontName, whitelist[i].fFontName)) {
- if (!whitelist[i].fSerializedSub) {
- whitelist[i].fSerializedSub = true;
- SkDebugf("%s %s\n", __FUNCTION__, familyName);
- }
- break;
- }
- }
- #endif
- }
- static bool is_local(const SkTypeface* tf) {
- bool isLocal = false;
- SkFontDescriptor desc;
- tf->getFontDescriptor(&desc, &isLocal);
- return isLocal;
- }
- static void serialize_full(const SkTypeface* tf, SkWStream* wstream) {
- bool isLocal = false;
- SkFontDescriptor desc;
- tf->getFontDescriptor(&desc, &isLocal);
- // Embed font data if it's a local font.
- if (isLocal && !desc.hasFontData()) {
- desc.setFontData(tf->makeFontData());
- }
- desc.serialize(wstream);
- }
- static void serialize_name_only(const SkTypeface* tf, SkWStream* wstream) {
- bool isLocal = false;
- SkFontDescriptor desc;
- tf->getFontDescriptor(&desc, &isLocal);
- SkASSERT(!isLocal);
- #if WHITELIST_DEBUG
- const char* familyName = desc.getFamilyName();
- if (familyName) {
- if (!strcmp(familyName, "Times New Roman")) {
- if (!timesNewRomanSerializedNameOnly) {
- timesNewRomanSerializedNameOnly = true;
- SkDebugf("%s %s\n", __FUNCTION__, familyName);
- }
- } else {
- for (int i = 0; i < whitelistCount; ++i) {
- if (!strcmp(familyName, whitelist[i].fFontName)) {
- if (!whitelist[i].fSerializedNameOnly) {
- whitelist[i].fSerializedNameOnly = true;
- SkDebugf("%s %s\n", __FUNCTION__, familyName);
- }
- break;
- }
- }
- }
- }
- #endif
- desc.serialize(wstream);
- }
- void WhitelistSerializeTypeface(const SkTypeface* tf, SkWStream* wstream) {
- if (!is_local(tf)) {
- serialize_name_only(tf, wstream);
- return;
- }
- int whitelistIndex = whitelist_name_index(tf);
- if (whitelistIndex < 0) {
- serialize_full(tf, wstream);
- return;
- }
- const char* fontName = whitelist[whitelistIndex].fFontName;
- if (!font_name_is_local(fontName, tf->fontStyle())) {
- #if WHITELIST_DEBUG
- SkDebugf("name not found locally \"%s\" style=%d\n", fontName, tf->style());
- #endif
- serialize_full(tf, wstream);
- return;
- }
- uint32_t checksum = compute_checksum(tf);
- if (whitelist[whitelistIndex].fChecksum != checksum) {
- #if WHITELIST_DEBUG
- if (whitelist[whitelistIndex].fChecksum) {
- SkDebugf("!!! checksum changed !!!\n");
- }
- SkDebugf("checksum updated\n");
- SkDebugf(" { \"%s\", 0x%08x },\n", fontName, checksum);
- #endif
- whitelist[whitelistIndex].fChecksum = checksum;
- }
- serialize_sub(fontName, tf->fontStyle(), wstream);
- }
- sk_sp<SkTypeface> WhitelistDeserializeTypeface(SkStream* stream) {
- SkFontDescriptor desc;
- if (!SkFontDescriptor::Deserialize(stream, &desc)) {
- return nullptr;
- }
- std::unique_ptr<SkFontData> data = desc.detachFontData();
- if (data) {
- sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData(std::move(data)));
- if (typeface) {
- return typeface;
- }
- }
- const char* familyName = desc.getFamilyName();
- if (!strncmp(SUBNAME_PREFIX, familyName, sizeof(SUBNAME_PREFIX) - 1)) {
- familyName += sizeof(SUBNAME_PREFIX) - 1;
- }
- return SkTypeface::MakeFromName(familyName, desc.getStyle());
- }
- bool CheckChecksums() {
- for (int i = 0; i < whitelistCount; ++i) {
- const char* fontName = whitelist[i].fFontName;
- sk_sp<SkTypeface> tf(SkTypeface::MakeFromName(fontName, SkFontStyle()));
- uint32_t checksum = compute_checksum(tf.get());
- if (whitelist[i].fChecksum != checksum) {
- return false;
- }
- }
- return true;
- }
- const char checksumFileName[] = "SkWhitelistChecksums.inc";
- const char checksumHeader[] =
- "/*" "\n"
- " * Copyright 2015 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"
- " * %s() in %s generated %s." "\n"
- " * Run 'whitelist_typefaces --generate' to create anew." "\n"
- " */" "\n"
- "" "\n"
- "#include \"SkTDArray.h\"" "\n"
- "" "\n"
- "struct Whitelist {" "\n"
- " const char* fFontName;" "\n"
- " uint32_t fChecksum;" "\n"
- " bool fSerializedNameOnly;" "\n"
- " bool fSerializedSub;" "\n"
- "};" "\n"
- "" "\n"
- "static Whitelist whitelist[] = {" "\n";
- const char checksumEntry[] =
- " { \"%s\", 0x%08x, false, false }," "\n";
- const char checksumTrailer[] =
- "};" "\n"
- "" "\n"
- "static const int whitelistCount = (int) SK_ARRAY_COUNT(whitelist);" "\n";
- #include "src/core/SkOSFile.h"
- bool GenerateChecksums() {
- FILE* file = sk_fopen(checksumFileName, kWrite_SkFILE_Flag);
- if (!file) {
- SkDebugf("Can't open %s for writing.\n", checksumFileName);
- return false;
- }
- SkString line;
- line.printf(checksumHeader, __FUNCTION__, __FILE__, checksumFileName);
- sk_fwrite(line.c_str(), line.size(), file);
- for (int i = 0; i < whitelistCount; ++i) {
- const char* fontName = whitelist[i].fFontName;
- sk_sp<SkTypeface> tf(SkTypeface::MakeFromName(fontName, SkFontStyle()));
- uint32_t checksum = compute_checksum(tf.get());
- line.printf(checksumEntry, fontName, checksum);
- sk_fwrite(line.c_str(), line.size(), file);
- }
- sk_fwrite(checksumTrailer, sizeof(checksumTrailer) - 1, file);
- sk_fclose(file);
- return true;
- }
|