Bug 962440 - load font info for GDI font list. r=bas

This commit is contained in:
John Daggett 2014-01-29 16:39:01 +09:00
Родитель bcf6b6943a
Коммит 63e909a581
2 изменённых файлов: 186 добавлений и 0 удалений

Просмотреть файл

@ -915,3 +915,187 @@ gfxGDIFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
aSizes->mFontListSize += aMallocSizeOf(this);
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
}
// used to load system-wide font info on off-main thread
class GDIFontInfo : public FontInfoData {
public:
GDIFontInfo(bool aLoadOtherNames,
bool aLoadFaceNames,
bool aLoadCmaps) :
FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps)
{}
virtual ~GDIFontInfo() {}
virtual void Load() {
mHdc = GetDC(nullptr);
SetGraphicsMode(mHdc, GM_ADVANCED);
FontInfoData::Load();
ReleaseDC(nullptr, mHdc);
}
// loads font data for all members of a given family
virtual void LoadFontFamilyData(const nsAString& aFamilyName);
// callback for GDI EnumFontFamiliesExW call
static int CALLBACK EnumerateFontsForFamily(const ENUMLOGFONTEXW *lpelfe,
const NEWTEXTMETRICEXW *nmetrics,
DWORD fontType, LPARAM data);
HDC mHdc;
};
struct EnumerateFontsForFamilyData {
EnumerateFontsForFamilyData(const nsAString& aFamilyName,
GDIFontInfo& aFontInfo)
: mFamilyName(aFamilyName), mFontInfo(aFontInfo)
{}
nsString mFamilyName;
nsTArray<nsString> mOtherFamilyNames;
GDIFontInfo& mFontInfo;
nsString mPreviousFontName;
};
int CALLBACK GDIFontInfo::EnumerateFontsForFamily(
const ENUMLOGFONTEXW *lpelfe,
const NEWTEXTMETRICEXW *nmetrics,
DWORD fontType, LPARAM data)
{
EnumerateFontsForFamilyData *famData =
reinterpret_cast<EnumerateFontsForFamilyData*>(data);
HDC hdc = famData->mFontInfo.mHdc;
LOGFONTW logFont = lpelfe->elfLogFont;
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
AutoSelectFont font(hdc, &logFont);
if (!font.IsValid()) {
return 1;
}
FontFaceData fontData;
nsDependentString fontName(lpelfe->elfFullName);
// callback called for each style-charset so return if style already seen
if (fontName.Equals(famData->mPreviousFontName)) {
return 1;
}
famData->mPreviousFontName = fontName;
famData->mFontInfo.mLoadStats.fonts++;
// read name table info
bool nameDataLoaded = false;
if (famData->mFontInfo.mLoadFaceNames || famData->mFontInfo.mLoadOtherNames) {
uint32_t kNAME =
NativeEndian::swapToBigEndian(TRUETYPE_TAG('n','a','m','e'));
uint32_t nameSize;
nsAutoTArray<uint8_t, 1024> nameData;
nameSize = ::GetFontData(hdc, kNAME, 0, nullptr, 0);
if (nameSize != GDI_ERROR &&
nameSize > 0 &&
nameData.SetLength(nameSize)) {
::GetFontData(hdc, kNAME, 0, nameData.Elements(), nameSize);
// face names
if (famData->mFontInfo.mLoadFaceNames) {
gfxFontUtils::ReadCanonicalName((const char*)(nameData.Elements()), nameSize,
gfxFontUtils::NAME_ID_FULL,
fontData.mFullName);
gfxFontUtils::ReadCanonicalName((const char*)(nameData.Elements()), nameSize,
gfxFontUtils::NAME_ID_POSTSCRIPT,
fontData.mPostscriptName);
nameDataLoaded = true;
famData->mFontInfo.mLoadStats.facenames++;
}
// other family names
if (famData->mFontInfo.mLoadOtherNames) {
gfxFontFamily::ReadOtherFamilyNamesForFace(famData->mFamilyName,
(const char*)(nameData.Elements()),
nameSize,
famData->mOtherFamilyNames,
false);
}
}
}
// read cmap
bool cmapLoaded = false;
gfxWindowsFontType feType =
GDIFontEntry::DetermineFontType(metrics, fontType);
if (famData->mFontInfo.mLoadCmaps &&
(feType == GFX_FONT_TYPE_PS_OPENTYPE ||
feType == GFX_FONT_TYPE_TT_OPENTYPE ||
feType == GFX_FONT_TYPE_TRUETYPE))
{
uint32_t kCMAP =
NativeEndian::swapToBigEndian(TRUETYPE_TAG('c','m','a','p'));
uint32_t cmapSize;
nsAutoTArray<uint8_t, 1024> cmapData;
cmapSize = ::GetFontData(hdc, kCMAP, 0, nullptr, 0);
if (cmapSize != GDI_ERROR &&
cmapSize > 0 &&
cmapData.SetLength(cmapSize)) {
::GetFontData(hdc, kCMAP, 0, cmapData.Elements(), cmapSize);
bool cmapLoaded = false;
bool unicodeFont = false, symbolFont = false;
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
uint32_t offset;
if (NS_SUCCEEDED(gfxFontUtils::ReadCMAP(cmapData.Elements(),
cmapSize, *charmap,
offset, unicodeFont,
symbolFont))) {
fontData.mCharacterMap = charmap;
fontData.mUVSOffset = offset;
fontData.mSymbolFont = symbolFont;
cmapLoaded = true;
famData->mFontInfo.mLoadStats.cmaps++;
}
}
}
if (cmapLoaded || nameDataLoaded) {
famData->mFontInfo.mFontFaceData.Put(fontName, fontData);
}
return 1;
}
void
GDIFontInfo::LoadFontFamilyData(const nsAString& aFamilyName)
{
// iterate over the family
LOGFONTW logFont;
memset(&logFont, 0, sizeof(LOGFONTW));
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfPitchAndFamily = 0;
uint32_t l = std::min<uint32_t>(aFamilyName.Length(), LF_FACESIZE - 1);
memcpy(logFont.lfFaceName, aFamilyName.BeginReading(), l * sizeof(char16_t));
EnumerateFontsForFamilyData data(aFamilyName, *this);
EnumFontFamiliesExW(mHdc, &logFont,
(FONTENUMPROCW)GDIFontInfo::EnumerateFontsForFamily,
(LPARAM)(&data), 0);
// if found other names, insert them
if (data.mOtherFamilyNames.Length() != 0) {
mOtherFamilyNames.Put(aFamilyName, data.mOtherFamilyNames);
mLoadStats.othernames += data.mOtherFamilyNames.Length();
}
}
already_AddRefed<FontInfoData>
gfxGDIFontList::CreateFontInfoData()
{
bool loadCmaps = !UsesSystemFallback() ||
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
nsRefPtr<GDIFontInfo> fi =
new GDIFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
return fi.forget();
}

Просмотреть файл

@ -339,6 +339,8 @@ private:
DWORD fontType,
LPARAM lParam);
virtual already_AddRefed<FontInfoData> CreateFontInfoData();
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
FontTable mFontSubstitutes;