skia2/tests/FontNamesTest.cpp
bungeman@google.com fab44db294 Clean up SkTypes.h.
This change removes sk_stdint.h since it is only needed for vs2008 and earlier.
This change removes SK_MMAP_SUPPORT define since it is no longer used.
This change removes the stdio.h include from SkTypes.h since on many systems
this is a very large header, few Skia files actually use it, it is
available everywhere standard, and SkDebugf should be used instead.

After this change there is no need for external users to put Skia's
include/config into their own list of includes, saving the headache
of having two header files of the same name and sometimes getting the
wrong one depending on include order.

R=bsalomon@google.com, djsollen@google.com

Review URL: https://codereview.chromium.org/27044002

git-svn-id: http://skia.googlecode.com/svn/trunk@11738 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-11 18:50:45 +00:00

228 lines
7.9 KiB
C++

/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#include "SkCommandLineFlags.h"
#include "SkFontMgr.h"
#include "SkOTTable_name.h"
#include "SkTypeface.h"
#include <stddef.h>
template <size_t R, size_t D> struct Format0NameTable {
SkOTTableName header;
SkOTTableName::Record nameRecord[R];
char data[D];
};
template <size_t R, size_t L, size_t D> struct Format1NameTable {
SkOTTableName header;
SkOTTableName::Record nameRecord[R];
struct {
SkOTTableName::Format1Ext header;
SkOTTableName::Format1Ext::LangTagRecord langTagRecord[L];
} format1ext;
char data[D];
};
typedef Format0NameTable<1, 9> SimpleFormat0NameTable;
SimpleFormat0NameTable simpleFormat0NameTable = {
/*header*/ {
/*format*/ SkOTTableName::format_0,
/*count*/ SkTEndianSwap16<1>::value,
/*stringOffset*/ SkTEndianSwap16<offsetof(SimpleFormat0NameTable, data)>::value,
},
/*nameRecord[]*/ {
/*Record*/ {
/*platformID*/ { SkOTTableName::Record::PlatformID::Windows },
/*encodingID*/ { SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2 },
/*languageID*/ { SkOTTableName::Record::LanguageID::Windows::English_UnitedStates },
/*nameID*/ { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
/*length*/ SkTEndianSwap16<8>::value,
/*offset*/ SkTEndianSwap16<0>::value,
}
},
/*data*/ "\x0" "T" "\x0" "e" "\x0" "s" "\x0" "t",
};
typedef Format1NameTable<1, 1, 19> SimpleFormat1NameTable;
SimpleFormat1NameTable simpleFormat1NameTable = {
/*header*/ {
/*format*/ SkOTTableName::format_1,
/*count*/ SkTEndianSwap16<1>::value,
/*stringOffset*/ SkTEndianSwap16<offsetof(SimpleFormat1NameTable, data)>::value,
},
/*nameRecord[]*/ {
/*Record*/ {
/*platformID*/ { SkOTTableName::Record::PlatformID::Windows },
/*encodingID*/ { SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2 },
/*languageID*/ { SkTEndianSwap16<0x8000 + 0>::value },
/*nameID*/ { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
/*length*/ SkTEndianSwap16<8>::value,
/*offset*/ SkTEndianSwap16<0>::value,
}
},
/*format1ext*/ {
/*header*/ {
/*langTagCount*/ SkTEndianSwap16<1>::value,
},
/*langTagRecord[]*/ {
/*LangTagRecord*/ {
/*length*/ SkTEndianSwap16<10>::value,
/*offset*/ SkTEndianSwap16<8>::value,
},
},
},
/*data*/ "\x0" "T" "\x0" "e" "\x0" "s" "\x0" "t"
"\x0" "e" "\x0" "n" "\x0" "-" "\x0" "U" "\x0" "S",
};
struct FontNamesTest {
SkOTTableName* data;
SkOTTableName::Record::NameID nameID;
size_t nameCount;
struct {
const char* name;
const char* language;
} names[10];
} test[] = {
{
(SkOTTableName*)&simpleFormat0NameTable,
{ SkOTTableName::Record::NameID::Predefined::FontFamilyName },
1,
{
{ "Test", "en-US" },
},
},
{
(SkOTTableName*)&simpleFormat1NameTable,
{ SkOTTableName::Record::NameID::Predefined::FontFamilyName },
1,
{
{ "Test", "en-US" },
},
},
};
static void test_synthetic(skiatest::Reporter* reporter, bool verbose) {
for (size_t i = 0; i < SK_ARRAY_COUNT(test); ++i) {
SkOTTableName::Iterator iter(*test[i].data, test[i].nameID.predefined.value);
SkOTTableName::Iterator::Record record;
size_t nameIndex = 0;
while (nameIndex < test[i].nameCount && iter.next(record)) {
REPORTER_ASSERT_MESSAGE(reporter,
strcmp(test[i].names[nameIndex].name, record.name.c_str()) == 0,
"Name did not match."
);
REPORTER_ASSERT_MESSAGE(reporter,
strcmp(test[i].names[nameIndex].language, record.language.c_str()) == 0,
"Language did not match."
);
//printf("%s <%s>\n", record.name.c_str(), record.language.c_str());
++nameIndex;
}
REPORTER_ASSERT_MESSAGE(reporter, nameIndex == test[i].nameCount,
"Fewer names than expected.");
REPORTER_ASSERT_MESSAGE(reporter, !iter.next(record),
"More names than expected.");
}
}
#define MAX_FAMILIES 1000
static void test_systemfonts(skiatest::Reporter* reporter, bool verbose) {
static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
int count = SkMin32(fm->countFamilies(), MAX_FAMILIES);
for (int i = 0; i < count; ++i) {
SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
for (int j = 0; j < set->count(); ++j) {
SkString sname;
SkFontStyle fs;
set->getStyle(j, &fs, &sname);
SkAutoTUnref<SkTypeface> typeface(set->createTypeface(j));
if (NULL == typeface.get()) {
//TODO: SkFontMgr_fontconfig always returns NULL?
continue;
}
SkString familyName;
typeface->getFamilyName(&familyName);
if (verbose) {
SkDebugf("[%s]\n", familyName.c_str());
}
SkAutoTUnref<SkTypeface::LocalizedStrings> familyNamesIter(
typeface->createFamilyNameIterator());
SkTypeface::LocalizedString familyNameLocalized;
while (familyNamesIter->next(&familyNameLocalized)) {
if (verbose) {
SkDebugf("(%s) <%s>\n", familyNameLocalized.fString.c_str(),
familyNameLocalized.fLanguage.c_str());
}
}
size_t nameTableSize = typeface->getTableSize(nameTag);
if (0 == nameTableSize) {
continue;
}
SkAutoTMalloc<uint8_t> nameTableData(nameTableSize);
size_t copied = typeface->getTableData(nameTag, 0, nameTableSize, nameTableData.get());
if (copied != nameTableSize) {
continue;
}
SkOTTableName::Iterator::Record record;
SkOTTableName::Iterator familyNameIter(*((SkOTTableName*)nameTableData.get()),
SkOTTableName::Record::NameID::Predefined::FontFamilyName);
while (familyNameIter.next(record)) {
REPORTER_ASSERT_MESSAGE(reporter,
SkOTTableName::Record::NameID::Predefined::FontFamilyName == record.type,
"Requested family name, got something else."
);
if (verbose) {
SkDebugf("{%s} <%s>\n", record.name.c_str(), record.language.c_str());
}
}
SkOTTableName::Iterator styleNameIter(*((SkOTTableName*)nameTableData.get()),
SkOTTableName::Record::NameID::Predefined::FontSubfamilyName);
while (styleNameIter.next(record)) {
REPORTER_ASSERT_MESSAGE(reporter,
SkOTTableName::Record::NameID::Predefined::FontSubfamilyName == record.type,
"Requested subfamily name, got something else."
);
if (verbose) {
SkDebugf("{{%s}} <%s>\n", record.name.c_str(), record.language.c_str());
}
}
if (verbose) {
SkDebugf("\n");
}
}
}
}
DEFINE_bool(verboseFontNames, false, "verbose FontNames test.");
static void TestFontNames(skiatest::Reporter* reporter) {
test_synthetic(reporter, FLAGS_verboseFontNames);
test_systemfonts(reporter, FLAGS_verboseFontNames);
}
#include "TestClassDef.h"
DEFINE_TESTCLASS("FontNames", FontNamesTestClass, TestFontNames)