This source file includes following definitions.
- fontContainsCharacter
- minSizeForAntiAlias
- fontRequiresFullHinting
- platformFallbackForCharacter
- equalIgnoringCase
- typefacesMatchesFamily
- createFontPlatformData
#include "config.h"
#include "platform/fonts/FontCache.h"
#include "RuntimeEnabledFeatures.h"
#include "SkFontMgr.h"
#include "SkTypeface_win.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/harfbuzz/FontPlatformDataHarfbuzz.h"
#include "platform/fonts/win/FontFallbackWin.h"
namespace WebCore {
FontCache::FontCache()
: m_purgePreventCount(0)
{
SkFontMgr* fontManager;
if (s_useDirectWrite) {
fontManager = SkFontMgr_New_DirectWrite(s_directWriteFactory);
} else {
fontManager = SkFontMgr_New_GDI();
s_useSubpixelPositioning = false;
}
ASSERT(fontManager);
m_fontManager = adoptPtr(fontManager);
}
static bool fontContainsCharacter(const FontPlatformData* fontData, const wchar_t* family, UChar32 character)
{
SkPaint paint;
fontData->setupPaint(&paint);
paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
uint16_t glyph;
paint.textToGlyphs(&character, sizeof(character), &glyph);
return glyph;
}
static unsigned minSizeForAntiAlias(UScriptCode script)
{
switch (script) {
case USCRIPT_TRADITIONAL_HAN:
return 24;
case USCRIPT_SIMPLIFIED_HAN:
case USCRIPT_HIRAGANA:
case USCRIPT_KATAKANA:
case USCRIPT_KATAKANA_OR_HIRAGANA:
case USCRIPT_HANGUL:
case USCRIPT_BENGALI:
return 16;
case USCRIPT_THAI:
case USCRIPT_HEBREW:
case USCRIPT_ARABIC:
case USCRIPT_DEVANAGARI:
case USCRIPT_GURMUKHI:
case USCRIPT_GUJARATI:
case USCRIPT_TAMIL:
case USCRIPT_TELUGU:
case USCRIPT_KANNADA:
case USCRIPT_GEORGIAN:
case USCRIPT_ARMENIAN:
case USCRIPT_THAANA:
case USCRIPT_CANADIAN_ABORIGINAL:
case USCRIPT_CHEROKEE:
case USCRIPT_MONGOLIAN:
default:
return 0;
}
}
static bool fontRequiresFullHinting(const AtomicString& familyName)
{
DEFINE_STATIC_LOCAL(AtomicString, courierNew, ("Courier New", AtomicString::ConstructFromLiteral));
if (equalIgnoringCase(familyName, courierNew))
return true;
return false;
}
PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 character, const SimpleFontData*)
{
UScriptCode script;
const wchar_t* family = getFallbackFamily(character,
fontDescription.genericFamily(),
&script);
FontPlatformData* data = 0;
if (family)
data = getFontPlatformData(fontDescription, AtomicString(family, wcslen(family)));
const static wchar_t* const cjkFonts[] = {
L"arial unicode ms",
L"ms pgothic",
L"simsun",
L"gulim",
L"pmingliu",
L"wenquanyi zen hei",
L"ar pl shanheisun uni",
L"ar pl zenkai uni",
L"han nom a",
L"code2000"
};
const static wchar_t* const commonFonts[] = {
L"tahoma",
L"arial unicode ms",
L"lucida sans unicode",
L"microsoft sans serif",
L"palatino linotype",
L"dejavu serif",
L"dejavu sasns",
L"freeserif",
L"freesans",
L"gentium",
L"gentiumalt",
L"ms pgothic",
L"simsun",
L"gulim",
L"pmingliu",
L"code2000"
};
const wchar_t* const* panUniFonts = 0;
int numFonts = 0;
if (script == USCRIPT_HAN) {
panUniFonts = cjkFonts;
numFonts = WTF_ARRAY_LENGTH(cjkFonts);
} else {
panUniFonts = commonFonts;
numFonts = WTF_ARRAY_LENGTH(commonFonts);
}
int i;
for (i = 0; (!data || !fontContainsCharacter(data, family, character)) && i < numFonts; ++i) {
family = panUniFonts[i];
data = getFontPlatformData(fontDescription, AtomicString(family, wcslen(family)));
}
if (i <= numFonts) {
if (s_useDirectWrite)
data->setMinSizeForAntiAlias(minSizeForAntiAlias(script));
return fontDataFromFontPlatformData(data, DoNotRetain);
}
return nullptr;
}
static inline bool equalIgnoringCase(const AtomicString& a, const SkString& b)
{
return equalIgnoringCase(a, AtomicString::fromUTF8(b.c_str()));
}
static bool typefacesMatchesFamily(const SkTypeface* tf, const AtomicString& family)
{
SkTypeface::LocalizedStrings* actualFamilies = tf->createFamilyNameIterator();
bool matchesRequestedFamily = false;
SkTypeface::LocalizedString actualFamily;
while (actualFamilies->next(&actualFamily)) {
if (equalIgnoringCase(family, actualFamily.fString)) {
matchesRequestedFamily = true;
break;
}
}
actualFamilies->unref();
if (!matchesRequestedFamily) {
SkString familyName;
tf->getFamilyName(&familyName);
if (equalIgnoringCase(family, familyName))
matchesRequestedFamily = true;
}
return matchesRequestedFamily;
}
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family, float fontSize)
{
CString name;
RefPtr<SkTypeface> tf = createTypeface(fontDescription, family, name);
if (!tf)
return 0;
if (!typefacesMatchesFamily(tf.get(), family)) {
return 0;
}
FontPlatformData* result = new FontPlatformData(tf,
name.data(),
fontSize,
fontDescription.weight() >= FontWeightBold && !tf->isBold() || fontDescription.isSyntheticBold(),
fontDescription.style() == FontStyleItalic && !tf->isItalic() || fontDescription.isSyntheticItalic(),
fontDescription.orientation(),
s_useSubpixelPositioning);
if (s_useDirectWrite) {
result->setMinSizeForAntiAlias(
minSizeForAntiAlias(fontDescription.script()));
if (fontRequiresFullHinting(family))
result->setHinting(SkPaint::kFull_Hinting);
}
return result;
}
}