Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 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 "SkCommandLineFlags.h"
      9 #include "SkFontMgr.h"
     10 #include "SkOTTable_name.h"
     11 #include "SkTypeface.h"
     12 #include "Test.h"
     13 
     14 #include <stddef.h>
     15 
     16 template <size_t R, size_t D> struct Format0NameTable {
     17     SkOTTableName header;
     18     SkOTTableName::Record nameRecord[R];
     19     char data[D];
     20 };
     21 
     22 template <size_t R, size_t L, size_t D> struct Format1NameTable {
     23     SkOTTableName header;
     24     SkOTTableName::Record nameRecord[R];
     25     struct {
     26         SkOTTableName::Format1Ext header;
     27         SkOTTableName::Format1Ext::LangTagRecord langTagRecord[L];
     28     } format1ext;
     29     char data[D];
     30 };
     31 
     32 typedef Format0NameTable<1, 9> SimpleFormat0NameTable;
     33 SimpleFormat0NameTable simpleFormat0NameTable = {
     34     /*header*/ {
     35         /*format*/ SkOTTableName::format_0,
     36         /*count*/ SkTEndianSwap16<1>::value,
     37         /*stringOffset*/ SkTEndianSwap16<offsetof(SimpleFormat0NameTable, data)>::value,
     38     },
     39     /*nameRecord[]*/ {
     40         /*Record*/ {
     41             /*platformID*/ { SkOTTableName::Record::PlatformID::Windows },
     42             /*encodingID*/ { SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2 },
     43             /*languageID*/ { SkOTTableName::Record::LanguageID::Windows::English_UnitedStates },
     44             /*nameID*/ { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
     45             /*length*/ SkTEndianSwap16<8>::value,
     46             /*offset*/ SkTEndianSwap16<0>::value,
     47         }
     48     },
     49     /*data*/ "\x0" "T" "\x0" "e" "\x0" "s" "\x0" "t",
     50 };
     51 
     52 typedef Format1NameTable<1, 1, 19> SimpleFormat1NameTable;
     53 SimpleFormat1NameTable simpleFormat1NameTable = {
     54     /*header*/ {
     55         /*format*/ SkOTTableName::format_1,
     56         /*count*/ SkTEndianSwap16<1>::value,
     57         /*stringOffset*/ SkTEndianSwap16<offsetof(SimpleFormat1NameTable, data)>::value,
     58     },
     59     /*nameRecord[]*/ {
     60         /*Record*/ {
     61             /*platformID*/ { SkOTTableName::Record::PlatformID::Windows },
     62             /*encodingID*/ { SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2 },
     63             /*languageID*/ { SkTEndianSwap16<0x8000 + 0>::value },
     64             /*nameID*/ { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
     65             /*length*/ SkTEndianSwap16<8>::value,
     66             /*offset*/ SkTEndianSwap16<0>::value,
     67         }
     68     },
     69     /*format1ext*/ {
     70         /*header*/ {
     71             /*langTagCount*/ SkTEndianSwap16<1>::value,
     72         },
     73         /*langTagRecord[]*/ {
     74             /*LangTagRecord*/ {
     75                 /*length*/ SkTEndianSwap16<10>::value,
     76                 /*offset*/ SkTEndianSwap16<8>::value,
     77             },
     78         },
     79     },
     80     /*data*/ "\x0" "T" "\x0" "e" "\x0" "s" "\x0" "t"
     81              "\x0" "e" "\x0" "n" "\x0" "-" "\x0" "U" "\x0" "S",
     82 };
     83 
     84 struct FontNamesTest {
     85     SkOTTableName* data;
     86     SkOTTableName::Record::NameID nameID;
     87     size_t nameCount;
     88     struct {
     89         const char* name;
     90         const char* language;
     91     } names[10];
     92 
     93 } test[] = {
     94     {
     95         (SkOTTableName*)&simpleFormat0NameTable,
     96         { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
     97         1,
     98         {
     99             { "Test", "en-US" },
    100         },
    101     },
    102     {
    103         (SkOTTableName*)&simpleFormat1NameTable,
    104         { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
    105         1,
    106         {
    107             { "Test", "en-US" },
    108         },
    109     },
    110 };
    111 
    112 static void test_synthetic(skiatest::Reporter* reporter, bool verbose) {
    113     for (size_t i = 0; i < SK_ARRAY_COUNT(test); ++i) {
    114         SkOTTableName::Iterator iter(*test[i].data, test[i].nameID.predefined.value);
    115         SkOTTableName::Iterator::Record record;
    116         size_t nameIndex = 0;
    117         while (nameIndex < test[i].nameCount && iter.next(record)) {
    118             REPORTER_ASSERT_MESSAGE(reporter,
    119                 strcmp(test[i].names[nameIndex].name, record.name.c_str()) == 0,
    120                 "Name did not match."
    121             );
    122 
    123             REPORTER_ASSERT_MESSAGE(reporter,
    124                 strcmp(test[i].names[nameIndex].language, record.language.c_str()) == 0,
    125                 "Language did not match."
    126             );
    127 
    128             //printf("%s <%s>\n", record.name.c_str(), record.language.c_str());
    129 
    130             ++nameIndex;
    131         }
    132 
    133         REPORTER_ASSERT_MESSAGE(reporter, nameIndex == test[i].nameCount,
    134                                 "Fewer names than expected.");
    135 
    136         REPORTER_ASSERT_MESSAGE(reporter, !iter.next(record),
    137                                 "More names than expected.");
    138     }
    139 }
    140 
    141 #define MAX_FAMILIES 1000
    142 static void test_systemfonts(skiatest::Reporter* reporter, bool verbose) {
    143     static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
    144 
    145     SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
    146     int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
    147     for (int i = 0; i < count; ++i) {
    148         SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
    149         for (int j = 0; j < set->count(); ++j) {
    150             SkString sname;
    151             SkFontStyle fs;
    152             set->getStyle(j, &fs, &sname);
    153 
    154             SkAutoTUnref<SkTypeface> typeface(set->createTypeface(j));
    155             if (NULL == typeface.get()) {
    156                 //TODO: SkFontMgr_fontconfig always returns NULL?
    157                 continue;
    158             }
    159 
    160             SkString familyName;
    161             typeface->getFamilyName(&familyName);
    162             if (verbose) {
    163                 SkDebugf("[%s]\n", familyName.c_str());
    164             }
    165 
    166             SkAutoTUnref<SkTypeface::LocalizedStrings> familyNamesIter(
    167                 typeface->createFamilyNameIterator());
    168             SkTypeface::LocalizedString familyNameLocalized;
    169             while (familyNamesIter->next(&familyNameLocalized)) {
    170                 if (verbose) {
    171                     SkDebugf("(%s) <%s>\n", familyNameLocalized.fString.c_str(),
    172                                           familyNameLocalized.fLanguage.c_str());
    173                 }
    174             }
    175 
    176             size_t nameTableSize = typeface->getTableSize(nameTag);
    177             if (0 == nameTableSize) {
    178                 continue;
    179             }
    180             SkAutoTMalloc<uint8_t> nameTableData(nameTableSize);
    181             size_t copied = typeface->getTableData(nameTag, 0, nameTableSize, nameTableData.get());
    182             if (copied != nameTableSize) {
    183                 continue;
    184             }
    185 
    186             SkOTTableName::Iterator::Record record;
    187             SkOTTableName::Iterator familyNameIter(*((SkOTTableName*)nameTableData.get()),
    188                 SkOTTableName::Record::NameID::Predefined::FontFamilyName);
    189             while (familyNameIter.next(record)) {
    190                 REPORTER_ASSERT_MESSAGE(reporter,
    191                     SkOTTableName::Record::NameID::Predefined::FontFamilyName == record.type,
    192                     "Requested family name, got something else."
    193                 );
    194                 if (verbose) {
    195                     SkDebugf("{%s} <%s>\n", record.name.c_str(), record.language.c_str());
    196                 }
    197             }
    198 
    199             SkOTTableName::Iterator styleNameIter(*((SkOTTableName*)nameTableData.get()),
    200                 SkOTTableName::Record::NameID::Predefined::FontSubfamilyName);
    201             while (styleNameIter.next(record)) {
    202                 REPORTER_ASSERT_MESSAGE(reporter,
    203                     SkOTTableName::Record::NameID::Predefined::FontSubfamilyName == record.type,
    204                     "Requested subfamily name, got something else."
    205                 );
    206                 if (verbose) {
    207                     SkDebugf("{{%s}} <%s>\n", record.name.c_str(), record.language.c_str());
    208                 }
    209             }
    210 
    211             if (verbose) {
    212                 SkDebugf("\n");
    213             }
    214         }
    215     }
    216 }
    217 
    218 DEFINE_bool(verboseFontNames, false, "verbose FontNames test.");
    219 
    220 DEF_TEST(FontNames, reporter) {
    221     test_synthetic(reporter, FLAGS_verboseFontNames);
    222     test_systemfonts(reporter, FLAGS_verboseFontNames);
    223 }
    224