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