зеркало из https://github.com/mozilla/pjs.git
Bug 710727. Share cmaps across all fonts. r=jkew, a=tracking-firefox
This commit is contained in:
Родитель
254b7db74e
Коммит
6359697534
|
@ -375,84 +375,77 @@ gfxDWriteFontEntry::ReadCMAP()
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
// attempt this once, if errors occur leave a blank cmap
|
// attempt this once, if errors occur leave a blank cmap
|
||||||
if (mCmapInitialized)
|
if (mCharacterMap) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
mCmapInitialized = true;
|
}
|
||||||
|
|
||||||
|
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||||
|
|
||||||
// if loading via GDI, just use GetFontTable
|
// if loading via GDI, just use GetFontTable
|
||||||
if (mFont && gfxDWriteFontList::PlatformFontList()->UseGDIFontTableAccess()) {
|
if (mFont && gfxDWriteFontList::PlatformFontList()->UseGDIFontTableAccess()) {
|
||||||
const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
|
||||||
|
|
||||||
if (GetFontTable(kCmapTag, buffer) != NS_OK)
|
AutoFallibleTArray<PRUint8,16384> cmap;
|
||||||
return NS_ERROR_FAILURE;
|
rv = GetFontTable(kCMAP, cmap);
|
||||||
PRUint8 *cmap = buffer.Elements();
|
|
||||||
|
|
||||||
bool unicodeFont = false, symbolFont = false;
|
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||||
rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
|
|
||||||
mCharacterMap, mUVSOffset,
|
if (NS_SUCCEEDED(rv)) {
|
||||||
unicodeFont, symbolFont);
|
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||||
#ifdef PR_LOGGING
|
*charmap, mUVSOffset,
|
||||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
unicodeFont, symbolFont);
|
||||||
NS_ConvertUTF16toUTF8(mName).get(),
|
}
|
||||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
} else {
|
||||||
if (LOG_CMAPDATA_ENABLED()) {
|
// loading using dwrite, don't use GetFontTable to avoid copy
|
||||||
char prefix[256];
|
nsRefPtr<IDWriteFontFace> fontFace;
|
||||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||||
NS_ConvertUTF16toUTF8(mName).get());
|
|
||||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
const PRUint32 kCmapTag = DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p');
|
||||||
|
PRUint8 *tableData;
|
||||||
|
PRUint32 len;
|
||||||
|
void *tableContext = NULL;
|
||||||
|
BOOL exists;
|
||||||
|
hr = fontFace->TryGetFontTable(kCmapTag, (const void**)&tableData,
|
||||||
|
&len, &tableContext, &exists);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
bool isSymbol = fontFace->IsSymbolFont();
|
||||||
|
bool isUnicode = true;
|
||||||
|
if (exists) {
|
||||||
|
rv = gfxFontUtils::ReadCMAP(tableData, len, *charmap,
|
||||||
|
mUVSOffset, isUnicode,
|
||||||
|
isSymbol);
|
||||||
|
}
|
||||||
|
fontFace->ReleaseFontTable(tableContext);
|
||||||
|
} else {
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loading using dwrite, don't use GetFontTable to avoid copy
|
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||||
nsRefPtr<IDWriteFontFace> fontFace;
|
if (mHasCmapTable) {
|
||||||
rv = CreateFontFace(getter_AddRefs(fontFace));
|
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||||
|
mCharacterMap = pfl->FindCharMap(charmap);
|
||||||
if (NS_FAILED(rv)) {
|
} else {
|
||||||
return rv;
|
// if error occurred, initialize to null cmap
|
||||||
|
mCharacterMap = new gfxCharacterMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint8 *tableData;
|
|
||||||
PRUint32 len;
|
|
||||||
void *tableContext = NULL;
|
|
||||||
BOOL exists;
|
|
||||||
hr = fontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p'),
|
|
||||||
(const void**)&tableData,
|
|
||||||
&len,
|
|
||||||
&tableContext,
|
|
||||||
&exists);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSymbol = fontFace->IsSymbolFont();
|
|
||||||
bool isUnicode = true;
|
|
||||||
if (exists) {
|
|
||||||
rv = gfxFontUtils::ReadCMAP(tableData,
|
|
||||||
len,
|
|
||||||
mCharacterMap,
|
|
||||||
mUVSOffset,
|
|
||||||
isUnicode,
|
|
||||||
isSymbol);
|
|
||||||
}
|
|
||||||
fontFace->ReleaseFontTable(tableContext);
|
|
||||||
|
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
||||||
NS_ConvertUTF16toUTF8(mName).get(),
|
NS_ConvertUTF16toUTF8(mName).get(),
|
||||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
||||||
|
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
||||||
if (LOG_CMAPDATA_ENABLED()) {
|
if (LOG_CMAPDATA_ENABLED()) {
|
||||||
char prefix[256];
|
char prefix[256];
|
||||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||||
NS_ConvertUTF16toUTF8(mName).get());
|
NS_ConvertUTF16toUTF8(mName).get());
|
||||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
charmap->Dump(prefix, eGfxLog_cmapdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -343,12 +343,11 @@ FT2FontEntry::CairoFontFace()
|
||||||
nsresult
|
nsresult
|
||||||
FT2FontEntry::ReadCMAP()
|
FT2FontEntry::ReadCMAP()
|
||||||
{
|
{
|
||||||
if (mCmapInitialized) {
|
if (mCharacterMap) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// attempt this once, if errors occur leave a blank cmap
|
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||||
mCmapInitialized = true;
|
|
||||||
|
|
||||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
AutoFallibleTArray<PRUint8,16384> buffer;
|
||||||
nsresult rv = GetFontTable(TTAG_cmap, buffer);
|
nsresult rv = GetFontTable(TTAG_cmap, buffer);
|
||||||
|
@ -357,11 +356,18 @@ FT2FontEntry::ReadCMAP()
|
||||||
bool unicodeFont;
|
bool unicodeFont;
|
||||||
bool symbolFont;
|
bool symbolFont;
|
||||||
rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
|
rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
|
||||||
mCharacterMap, mUVSOffset,
|
*charmap, mUVSOffset,
|
||||||
unicodeFont, symbolFont);
|
unicodeFont, symbolFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||||
|
if (mHasCmapTable) {
|
||||||
|
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||||
|
mCharacterMap = pfl->FindCharMap(charmap);
|
||||||
|
} else {
|
||||||
|
// if error occurred, initialize to null cmap
|
||||||
|
mCharacterMap = new gfxCharacterMap();
|
||||||
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,16 @@ static PRUint32 gGlyphExtentsSetupLazyTight = 0;
|
||||||
static PRUint32 gGlyphExtentsSetupFallBackToTight = 0;
|
static PRUint32 gGlyphExtentsSetupFallBackToTight = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxCharacterMap::NotifyReleased()
|
||||||
|
{
|
||||||
|
gfxPlatformFontList *fontlist = gfxPlatformFontList::PlatformFontList();
|
||||||
|
if (mShared) {
|
||||||
|
fontlist->RemoveCmap(this);
|
||||||
|
}
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
gfxFontEntry::~gfxFontEntry()
|
gfxFontEntry::~gfxFontEntry()
|
||||||
{
|
{
|
||||||
delete mUserFontData;
|
delete mUserFontData;
|
||||||
|
@ -115,18 +125,20 @@ bool gfxFontEntry::IsSymbolFont()
|
||||||
|
|
||||||
bool gfxFontEntry::TestCharacterMap(PRUint32 aCh)
|
bool gfxFontEntry::TestCharacterMap(PRUint32 aCh)
|
||||||
{
|
{
|
||||||
if (!mCmapInitialized) {
|
if (!mCharacterMap) {
|
||||||
ReadCMAP();
|
ReadCMAP();
|
||||||
|
NS_ASSERTION(mCharacterMap, "failed to initialize character map");
|
||||||
}
|
}
|
||||||
return mCharacterMap.test(aCh);
|
return mCharacterMap->test(aCh);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult gfxFontEntry::InitializeUVSMap()
|
nsresult gfxFontEntry::InitializeUVSMap()
|
||||||
{
|
{
|
||||||
// mUVSOffset will not be initialized
|
// mUVSOffset will not be initialized
|
||||||
// until cmap is initialized.
|
// until cmap is initialized.
|
||||||
if (!mCmapInitialized) {
|
if (!mCharacterMap) {
|
||||||
ReadCMAP();
|
ReadCMAP();
|
||||||
|
NS_ASSERTION(mCharacterMap, "failed to initialize character map");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mUVSOffset) {
|
if (!mUVSOffset) {
|
||||||
|
@ -170,7 +182,8 @@ PRUint16 gfxFontEntry::GetUVSGlyph(PRUint32 aCh, PRUint32 aVS)
|
||||||
|
|
||||||
nsresult gfxFontEntry::ReadCMAP()
|
nsresult gfxFontEntry::ReadCMAP()
|
||||||
{
|
{
|
||||||
mCmapInitialized = true;
|
NS_ASSERTION(false, "using default no-op implementation of ReadCMAP");
|
||||||
|
mCharacterMap = new gfxCharacterMap();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +446,12 @@ gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||||
FontListSizes* aSizes) const
|
FontListSizes* aSizes) const
|
||||||
{
|
{
|
||||||
aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||||
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
|
||||||
|
// cmaps are shared so only non-shared cmaps are included here
|
||||||
|
if (mCharacterMap && mCharacterMap->mBuildOnTheFly) {
|
||||||
|
aSizes->mCharMapsSize +=
|
||||||
|
mCharacterMap->SizeOfIncludingThis(aMallocSizeOf);
|
||||||
|
}
|
||||||
aSizes->mFontTableCacheSize +=
|
aSizes->mFontTableCacheSize +=
|
||||||
mFontTableCache.SizeOfExcludingThis(
|
mFontTableCache.SizeOfExcludingThis(
|
||||||
FontTableHashEntry::SizeOfEntryExcludingThis,
|
FontTableHashEntry::SizeOfEntryExcludingThis,
|
||||||
|
@ -770,7 +788,7 @@ CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
||||||
void
|
void
|
||||||
gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
||||||
{
|
{
|
||||||
if (mCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
|
if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) {
|
||||||
// none of the faces in the family support the required char,
|
// none of the faces in the family support the required char,
|
||||||
// so bail out immediately
|
// so bail out immediately
|
||||||
return;
|
return;
|
||||||
|
@ -1028,7 +1046,8 @@ gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||||
{
|
{
|
||||||
aSizes->mFontListSize +=
|
aSizes->mFontListSize +=
|
||||||
mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||||
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
aSizes->mCharMapsSize +=
|
||||||
|
mFamilyCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
||||||
|
|
||||||
aSizes->mFontListSize +=
|
aSizes->mFontListSize +=
|
||||||
mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf);
|
mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||||
|
@ -3649,7 +3668,9 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
|
||||||
|
|
||||||
// check other faces of the family
|
// check other faces of the family
|
||||||
gfxFontFamily *family = font->GetFontEntry()->Family();
|
gfxFontFamily *family = font->GetFontEntry()->Family();
|
||||||
if (family && family->TestCharacterMap(aCh)) {
|
if (family && !font->GetFontEntry()->mIsProxy &&
|
||||||
|
family->TestCharacterMap(aCh))
|
||||||
|
{
|
||||||
GlobalFontMatch matchData(aCh, aRunScript, &mStyle);
|
GlobalFontMatch matchData(aCh, aRunScript, &mStyle);
|
||||||
family->SearchAllFontsForChar(&matchData);
|
family->SearchAllFontsForChar(&matchData);
|
||||||
gfxFontEntry *fe = matchData.mBestMatch;
|
gfxFontEntry *fe = matchData.mBestMatch;
|
||||||
|
|
|
@ -198,6 +198,56 @@ struct THEBES_API gfxFontStyle {
|
||||||
static PRUint32 ParseFontLanguageOverride(const nsString& aLangTag);
|
static PRUint32 ParseFontLanguageOverride(const nsString& aLangTag);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class gfxCharacterMap : public gfxSparseBitSet {
|
||||||
|
public:
|
||||||
|
nsrefcnt AddRef() {
|
||||||
|
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
|
||||||
|
++mRefCnt;
|
||||||
|
NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
|
||||||
|
return mRefCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsrefcnt Release() {
|
||||||
|
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||||
|
--mRefCnt;
|
||||||
|
NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
|
||||||
|
if (mRefCnt == 0) {
|
||||||
|
NotifyReleased();
|
||||||
|
// |this| has been deleted.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return mRefCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxCharacterMap() :
|
||||||
|
mHash(0), mBuildOnTheFly(false), mShared(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void CalcHash() { mHash = GetChecksum(); }
|
||||||
|
|
||||||
|
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||||
|
return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hash of the cmap bitvector
|
||||||
|
PRUint32 mHash;
|
||||||
|
|
||||||
|
// if cmap is built on the fly it's never shared
|
||||||
|
bool mBuildOnTheFly;
|
||||||
|
|
||||||
|
// cmap is shared globally
|
||||||
|
bool mShared;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NotifyReleased();
|
||||||
|
|
||||||
|
nsAutoRefCnt mRefCnt;
|
||||||
|
|
||||||
|
private:
|
||||||
|
gfxCharacterMap(const gfxCharacterMap&);
|
||||||
|
gfxCharacterMap& operator=(const gfxCharacterMap&);
|
||||||
|
};
|
||||||
|
|
||||||
class gfxFontEntry {
|
class gfxFontEntry {
|
||||||
public:
|
public:
|
||||||
NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
|
NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
|
||||||
|
@ -216,7 +266,6 @@ public:
|
||||||
mCheckedForGraphiteTables(false),
|
mCheckedForGraphiteTables(false),
|
||||||
#endif
|
#endif
|
||||||
mHasCmapTable(false),
|
mHasCmapTable(false),
|
||||||
mCmapInitialized(false),
|
|
||||||
mUVSOffset(0), mUVSData(nsnull),
|
mUVSOffset(0), mUVSData(nsnull),
|
||||||
mUserFontData(nsnull),
|
mUserFontData(nsnull),
|
||||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||||
|
@ -259,16 +308,17 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline bool HasCmapTable() {
|
inline bool HasCmapTable() {
|
||||||
if (!mCmapInitialized) {
|
if (!mCharacterMap) {
|
||||||
ReadCMAP();
|
ReadCMAP();
|
||||||
|
NS_ASSERTION(mCharacterMap, "failed to initialize character map");
|
||||||
}
|
}
|
||||||
return mHasCmapTable;
|
return mHasCmapTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool HasCharacter(PRUint32 ch) {
|
inline bool HasCharacter(PRUint32 ch) {
|
||||||
if (mCharacterMap.test(ch))
|
if (mCharacterMap && mCharacterMap->test(ch)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return TestCharacterMap(ch);
|
return TestCharacterMap(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,8 +394,7 @@ public:
|
||||||
bool mCheckedForGraphiteTables;
|
bool mCheckedForGraphiteTables;
|
||||||
#endif
|
#endif
|
||||||
bool mHasCmapTable;
|
bool mHasCmapTable;
|
||||||
bool mCmapInitialized;
|
nsRefPtr<gfxCharacterMap> mCharacterMap;
|
||||||
gfxSparseBitSet mCharacterMap;
|
|
||||||
PRUint32 mUVSOffset;
|
PRUint32 mUVSOffset;
|
||||||
nsAutoArrayPtr<PRUint8> mUVSData;
|
nsAutoArrayPtr<PRUint8> mUVSData;
|
||||||
gfxUserFontData* mUserFontData;
|
gfxUserFontData* mUserFontData;
|
||||||
|
@ -375,7 +424,6 @@ protected:
|
||||||
mCheckedForGraphiteTables(false),
|
mCheckedForGraphiteTables(false),
|
||||||
#endif
|
#endif
|
||||||
mHasCmapTable(false),
|
mHasCmapTable(false),
|
||||||
mCmapInitialized(false),
|
|
||||||
mUVSOffset(0), mUVSData(nsnull),
|
mUVSOffset(0), mUVSData(nsnull),
|
||||||
mUserFontData(nsnull),
|
mUserFontData(nsnull),
|
||||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||||
|
@ -529,7 +577,7 @@ public:
|
||||||
mHasStyles(false),
|
mHasStyles(false),
|
||||||
mIsSimpleFamily(false),
|
mIsSimpleFamily(false),
|
||||||
mIsBadUnderlineFamily(false),
|
mIsBadUnderlineFamily(false),
|
||||||
mCharacterMapInitialized(false)
|
mFamilyCharacterMapInitialized(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual ~gfxFontFamily() {
|
virtual ~gfxFontFamily() {
|
||||||
|
@ -607,26 +655,27 @@ public:
|
||||||
PRUint32 i, numFonts = mAvailableFonts.Length();
|
PRUint32 i, numFonts = mAvailableFonts.Length();
|
||||||
for (i = 0; i < numFonts; i++) {
|
for (i = 0; i < numFonts; i++) {
|
||||||
gfxFontEntry *fe = mAvailableFonts[i];
|
gfxFontEntry *fe = mAvailableFonts[i];
|
||||||
if (!fe) {
|
// don't try to load cmaps for downloadable fonts not yet loaded
|
||||||
|
if (!fe || fe->mIsProxy) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fe->ReadCMAP();
|
fe->ReadCMAP();
|
||||||
mCharacterMap.Union(fe->mCharacterMap);
|
mFamilyCharacterMap.Union(*(fe->mCharacterMap));
|
||||||
}
|
}
|
||||||
mCharacterMap.Compact();
|
mFamilyCharacterMap.Compact();
|
||||||
mCharacterMapInitialized = true;
|
mFamilyCharacterMapInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestCharacterMap(PRUint32 aCh) {
|
bool TestCharacterMap(PRUint32 aCh) {
|
||||||
if (!mCharacterMapInitialized) {
|
if (!mFamilyCharacterMapInitialized) {
|
||||||
ReadAllCMAPs();
|
ReadAllCMAPs();
|
||||||
}
|
}
|
||||||
return mCharacterMap.test(aCh);
|
return mFamilyCharacterMap.test(aCh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetCharacterMap() {
|
void ResetCharacterMap() {
|
||||||
mCharacterMap.reset();
|
mFamilyCharacterMap.reset();
|
||||||
mCharacterMapInitialized = false;
|
mFamilyCharacterMapInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark this family as being in the "bad" underline offset blacklist
|
// mark this family as being in the "bad" underline offset blacklist
|
||||||
|
@ -675,14 +724,14 @@ protected:
|
||||||
|
|
||||||
nsString mName;
|
nsString mName;
|
||||||
nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
|
nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
|
||||||
gfxSparseBitSet mCharacterMap;
|
gfxSparseBitSet mFamilyCharacterMap;
|
||||||
bool mOtherFamilyNamesInitialized;
|
bool mOtherFamilyNamesInitialized : 1;
|
||||||
bool mHasOtherFamilyNames;
|
bool mHasOtherFamilyNames : 1;
|
||||||
bool mFaceNamesInitialized;
|
bool mFaceNamesInitialized : 1;
|
||||||
bool mHasStyles;
|
bool mHasStyles : 1;
|
||||||
bool mIsSimpleFamily;
|
bool mIsSimpleFamily : 1;
|
||||||
bool mIsBadUnderlineFamily;
|
bool mIsBadUnderlineFamily : 1;
|
||||||
bool mCharacterMapInitialized;
|
bool mFamilyCharacterMapInitialized : 1;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// for "simple" families, the faces are stored in mAvailableFonts
|
// for "simple" families, the faces are stored in mAvailableFonts
|
||||||
|
|
|
@ -58,6 +58,8 @@
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsIStreamBufferAccess.h"
|
#include "nsIStreamBufferAccess.h"
|
||||||
|
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
/* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
|
/* Bug 341128 - w32api defines min/max which causes problems with <bitset> */
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
#undef min
|
#undef min
|
||||||
|
@ -87,6 +89,28 @@ public:
|
||||||
mBlocks[i] = new Block(*block);
|
mBlocks[i] = new Block(*block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Equals(const gfxSparseBitSet *aOther) const {
|
||||||
|
if (mBlocks.Length() != aOther->mBlocks.Length()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size_t n = mBlocks.Length();
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
const Block *b1 = mBlocks[i];
|
||||||
|
const Block *b2 = aOther->mBlocks[i];
|
||||||
|
if (!b1 != !b2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!b1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (memcmp(&b1->mBits, &b2->mBits, BLOCK_SIZE) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool test(PRUint32 aIndex) const {
|
bool test(PRUint32 aIndex) const {
|
||||||
NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
|
NS_ASSERTION(mBlocks.DebugGetHeader(), "mHdr is null, this is bad");
|
||||||
PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
|
PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
|
||||||
|
@ -321,6 +345,18 @@ public:
|
||||||
mBlocks.Compact();
|
mBlocks.Compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRUint32 GetChecksum() const {
|
||||||
|
PRUint32 check = adler32(0, Z_NULL, 0);
|
||||||
|
for (PRUint32 i = 0; i < mBlocks.Length(); i++) {
|
||||||
|
if (mBlocks[i]) {
|
||||||
|
const Block *block = mBlocks[i];
|
||||||
|
check = adler32(check, (PRUint8*) (&i), 4);
|
||||||
|
check = adler32(check, (PRUint8*) block, sizeof(Block));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsTArray< nsAutoPtr<Block> > mBlocks;
|
nsTArray< nsAutoPtr<Block> > mBlocks;
|
||||||
};
|
};
|
||||||
|
|
|
@ -201,7 +201,7 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
|
||||||
: gfxFontEntry(aFaceName),
|
: gfxFontEntry(aFaceName),
|
||||||
mWindowsFamily(0), mWindowsPitch(0),
|
mWindowsFamily(0), mWindowsPitch(0),
|
||||||
mFontType(aFontType),
|
mFontType(aFontType),
|
||||||
mForceGDI(false), mUnknownCMAP(false),
|
mForceGDI(false),
|
||||||
mCharset(), mUnicodeRanges()
|
mCharset(), mUnicodeRanges()
|
||||||
{
|
{
|
||||||
mUserFontData = aUserFontData;
|
mUserFontData = aUserFontData;
|
||||||
|
@ -218,43 +218,62 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
|
||||||
nsresult
|
nsresult
|
||||||
GDIFontEntry::ReadCMAP()
|
GDIFontEntry::ReadCMAP()
|
||||||
{
|
{
|
||||||
|
// attempt this once, if errors occur leave a blank cmap
|
||||||
|
if (mCharacterMap) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// skip non-SFNT fonts completely
|
// skip non-SFNT fonts completely
|
||||||
if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE &&
|
if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE &&
|
||||||
mFontType != GFX_FONT_TYPE_TT_OPENTYPE &&
|
mFontType != GFX_FONT_TYPE_TT_OPENTYPE &&
|
||||||
mFontType != GFX_FONT_TYPE_TRUETYPE)
|
mFontType != GFX_FONT_TYPE_TRUETYPE)
|
||||||
{
|
{
|
||||||
|
mCharacterMap = new gfxCharacterMap();
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// attempt this once, if errors occur leave a blank cmap
|
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||||
if (mCmapInitialized)
|
|
||||||
return NS_OK;
|
|
||||||
mCmapInitialized = true;
|
|
||||||
|
|
||||||
const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
nsresult rv;
|
||||||
if (GetFontTable(kCmapTag, buffer) != NS_OK)
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
PRUint8 *cmap = buffer.Elements();
|
|
||||||
|
|
||||||
bool unicodeFont = false, symbolFont = false;
|
AutoFallibleTArray<PRUint8,16384> cmap;
|
||||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
|
rv = GetFontTable(kCMAP, cmap);
|
||||||
mCharacterMap, mUVSOffset,
|
|
||||||
unicodeFont, symbolFont);
|
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||||
|
*charmap, mUVSOffset,
|
||||||
|
unicodeFont, symbolFont);
|
||||||
|
}
|
||||||
mSymbolFont = symbolFont;
|
mSymbolFont = symbolFont;
|
||||||
|
|
||||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||||
|
if (mHasCmapTable) {
|
||||||
|
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||||
|
mCharacterMap = pfl->FindCharMap(charmap);
|
||||||
|
} else {
|
||||||
|
// if error occurred, initialize to null cmap
|
||||||
|
mCharacterMap = new gfxCharacterMap();
|
||||||
|
// For fonts where we failed to read the character map,
|
||||||
|
// we can take a slow path to look up glyphs character by character
|
||||||
|
mCharacterMap->mBuildOnTheFly = true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
||||||
NS_ConvertUTF16toUTF8(mName).get(),
|
NS_ConvertUTF16toUTF8(mName).get(),
|
||||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
||||||
|
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
||||||
if (LOG_CMAPDATA_ENABLED()) {
|
if (LOG_CMAPDATA_ENABLED()) {
|
||||||
char prefix[256];
|
char prefix[256];
|
||||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||||
NS_ConvertUTF16toUTF8(mName).get());
|
NS_ConvertUTF16toUTF8(mName).get());
|
||||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
charmap->Dump(prefix, eGfxLog_cmapdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,13 +365,12 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
|
||||||
bool
|
bool
|
||||||
GDIFontEntry::TestCharacterMap(PRUint32 aCh)
|
GDIFontEntry::TestCharacterMap(PRUint32 aCh)
|
||||||
{
|
{
|
||||||
if (ReadCMAP() != NS_OK) {
|
if (!mCharacterMap) {
|
||||||
// For fonts where we failed to read the character map,
|
nsresult rv = ReadCMAP();
|
||||||
// we can take a slow path to look up glyphs character by character
|
NS_ASSERTION(mCharacterMap, "failed to initialize a character map");
|
||||||
mUnknownCMAP = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mUnknownCMAP) {
|
if (mCharacterMap->mBuildOnTheFly) {
|
||||||
if (aCh > 0xFFFF)
|
if (aCh > 0xFFFF)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -404,12 +422,12 @@ GDIFontEntry::TestCharacterMap(PRUint32 aCh)
|
||||||
ReleaseDC(NULL, dc);
|
ReleaseDC(NULL, dc);
|
||||||
|
|
||||||
if (hasGlyph) {
|
if (hasGlyph) {
|
||||||
mCharacterMap.set(aCh);
|
mCharacterMap->set(aCh);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// font had a cmap so simply check that
|
// font had a cmap so simply check that
|
||||||
return mCharacterMap.test(aCh);
|
return mCharacterMap->test(aCh);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -293,7 +293,6 @@ public:
|
||||||
|
|
||||||
gfxWindowsFontType mFontType;
|
gfxWindowsFontType mFontType;
|
||||||
bool mForceGDI : 1;
|
bool mForceGDI : 1;
|
||||||
bool mUnknownCMAP : 1;
|
|
||||||
|
|
||||||
gfxSparseBitSet mCharset;
|
gfxSparseBitSet mCharset;
|
||||||
gfxSparseBitSet mUnicodeRanges;
|
gfxSparseBitSet mUnicodeRanges;
|
||||||
|
|
|
@ -189,93 +189,98 @@ nsresult
|
||||||
MacOSFontEntry::ReadCMAP()
|
MacOSFontEntry::ReadCMAP()
|
||||||
{
|
{
|
||||||
// attempt this once, if errors occur leave a blank cmap
|
// attempt this once, if errors occur leave a blank cmap
|
||||||
if (mCmapInitialized) {
|
if (mCharacterMap) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
mCmapInitialized = true;
|
|
||||||
|
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||||
|
|
||||||
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
AutoFallibleTArray<PRUint8,16384> cmap;
|
AutoFallibleTArray<PRUint8,16384> cmap;
|
||||||
if (GetFontTable(kCMAP, cmap) != NS_OK) {
|
rv = GetFontTable(kCMAP, cmap);
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||||
|
*charmap, mUVSOffset,
|
||||||
|
unicodeFont, symbolFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unicodeFont, symbolFont; // currently ignored
|
if (NS_SUCCEEDED(rv)) {
|
||||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
// for layout support, check for the presence of mort/morx and/or
|
||||||
mCharacterMap, mUVSOffset,
|
// opentype layout tables
|
||||||
unicodeFont, symbolFont);
|
bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) ||
|
||||||
if (NS_FAILED(rv)) {
|
HasFontTable(TRUETYPE_TAG('m','o','r','t'));
|
||||||
mCharacterMap.reset();
|
bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B'));
|
||||||
return rv;
|
bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S'));
|
||||||
}
|
|
||||||
mHasCmapTable = true;
|
|
||||||
|
|
||||||
CGFontRef fontRef = GetFontRef();
|
if (hasAATLayout && !(hasGSUB || hasGPOS)) {
|
||||||
if (!fontRef) {
|
mRequiresAAT = true; // prefer CoreText if font has no OTL tables
|
||||||
return NS_ERROR_FAILURE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// for layout support, check for the presence of mort/morx and/or
|
PRUint32 numScripts =
|
||||||
// opentype layout tables
|
sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange);
|
||||||
bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) ||
|
|
||||||
HasFontTable(TRUETYPE_TAG('m','o','r','t'));
|
|
||||||
bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B'));
|
|
||||||
bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S'));
|
|
||||||
|
|
||||||
if (hasAATLayout && !(hasGSUB || hasGPOS)) {
|
for (PRUint32 s = 0; s < numScripts; s++) {
|
||||||
mRequiresAAT = true; // prefer CoreText if font has no OTL tables
|
eComplexScript whichScript = gScriptsThatRequireShaping[s].script;
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32 numScripts =
|
// check to see if the cmap includes complex script codepoints
|
||||||
sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange);
|
if (charmap->TestRange(gScriptsThatRequireShaping[s].rangeStart,
|
||||||
|
gScriptsThatRequireShaping[s].rangeEnd)) {
|
||||||
|
bool omitRange = true;
|
||||||
|
|
||||||
for (PRUint32 s = 0; s < numScripts; s++) {
|
if (hasAATLayout) {
|
||||||
eComplexScript whichScript = gScriptsThatRequireShaping[s].script;
|
|
||||||
|
|
||||||
// check to see if the cmap includes complex script codepoints
|
|
||||||
if (mCharacterMap.TestRange(gScriptsThatRequireShaping[s].rangeStart,
|
|
||||||
gScriptsThatRequireShaping[s].rangeEnd)) {
|
|
||||||
bool omitRange = true;
|
|
||||||
|
|
||||||
if (hasAATLayout) {
|
|
||||||
omitRange = false;
|
|
||||||
// prefer CoreText for Apple's complex-script fonts,
|
|
||||||
// even if they also have some OpenType tables
|
|
||||||
// (e.g. Geeza Pro Bold on 10.6; see bug 614903)
|
|
||||||
mRequiresAAT = true;
|
|
||||||
} else if (whichScript == eComplexScriptArabic) {
|
|
||||||
// special-case for Arabic:
|
|
||||||
// even if there's no morph table, CoreText can shape Arabic
|
|
||||||
// using OpenType layout; or if it's a downloaded font,
|
|
||||||
// assume the site knows what it's doing (as harfbuzz will
|
|
||||||
// be able to shape even though the font itself lacks tables
|
|
||||||
// stripped during sanitization).
|
|
||||||
// We check for GSUB here, as GPOS alone would not be ok
|
|
||||||
// for Arabic shaping.
|
|
||||||
if (hasGSUB || (mIsUserFont && !mIsLocalUserFont)) {
|
|
||||||
// TODO: to be really thorough, we could check that the
|
|
||||||
// GSUB table actually supports the 'arab' script tag.
|
|
||||||
omitRange = false;
|
omitRange = false;
|
||||||
|
// prefer CoreText for Apple's complex-script fonts,
|
||||||
|
// even if they also have some OpenType tables
|
||||||
|
// (e.g. Geeza Pro Bold on 10.6; see bug 614903)
|
||||||
|
mRequiresAAT = true;
|
||||||
|
} else if (whichScript == eComplexScriptArabic) {
|
||||||
|
// special-case for Arabic:
|
||||||
|
// even if there's no morph table, CoreText can shape Arabic
|
||||||
|
// using OpenType layout; or if it's a downloaded font,
|
||||||
|
// assume the site knows what it's doing (as harfbuzz will
|
||||||
|
// be able to shape even though the font itself lacks tables
|
||||||
|
// stripped during sanitization).
|
||||||
|
// We check for GSUB here, as GPOS alone would not be ok
|
||||||
|
// for Arabic shaping.
|
||||||
|
if (hasGSUB || (mIsUserFont && !mIsLocalUserFont)) {
|
||||||
|
// TODO: to be really thorough, we could check that the
|
||||||
|
// GSUB table actually supports the 'arab' script tag.
|
||||||
|
omitRange = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (omitRange) {
|
if (omitRange) {
|
||||||
mCharacterMap.ClearRange(gScriptsThatRequireShaping[s].rangeStart,
|
charmap->ClearRange(gScriptsThatRequireShaping[s].rangeStart,
|
||||||
gScriptsThatRequireShaping[s].rangeEnd);
|
gScriptsThatRequireShaping[s].rangeEnd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||||
|
if (mHasCmapTable) {
|
||||||
|
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
||||||
|
mCharacterMap = pfl->FindCharMap(charmap);
|
||||||
|
} else {
|
||||||
|
// if error occurred, initialize to null cmap
|
||||||
|
mCharacterMap = new gfxCharacterMap();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
||||||
NS_ConvertUTF16toUTF8(mName).get(),
|
NS_ConvertUTF16toUTF8(mName).get(),
|
||||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
||||||
|
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
||||||
if (LOG_CMAPDATA_ENABLED()) {
|
if (LOG_CMAPDATA_ENABLED()) {
|
||||||
char prefix[256];
|
char prefix[256];
|
||||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||||
NS_ConvertUTF16toUTF8(mName).get());
|
NS_ConvertUTF16toUTF8(mName).get());
|
||||||
mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
|
charmap->Dump(prefix, eGfxLog_cmapdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -213,10 +213,13 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
||||||
gFontListPrefObserver = new gfxFontListPrefObserver();
|
gFontListPrefObserver = new gfxFontListPrefObserver();
|
||||||
NS_ADDREF(gFontListPrefObserver);
|
NS_ADDREF(gFontListPrefObserver);
|
||||||
Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs);
|
Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs);
|
||||||
|
|
||||||
|
mSharedCmaps.Init(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxPlatformFontList::~gfxPlatformFontList()
|
gfxPlatformFontList::~gfxPlatformFontList()
|
||||||
{
|
{
|
||||||
|
mSharedCmaps.Clear();
|
||||||
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
|
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
|
||||||
Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
|
Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
|
||||||
NS_RELEASE(gFontListPrefObserver);
|
NS_RELEASE(gFontListPrefObserver);
|
||||||
|
@ -714,6 +717,41 @@ gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString
|
||||||
return !aFamilyName.IsEmpty();
|
return !aFamilyName.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfxCharacterMap*
|
||||||
|
gfxPlatformFontList::FindCharMap(gfxCharacterMap *aCmap)
|
||||||
|
{
|
||||||
|
aCmap->CalcHash();
|
||||||
|
gfxCharacterMap *cmap = AddCmap(aCmap);
|
||||||
|
cmap->mShared = true;
|
||||||
|
return cmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a cmap to the shared cmap set
|
||||||
|
gfxCharacterMap*
|
||||||
|
gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap)
|
||||||
|
{
|
||||||
|
CharMapHashKey *found =
|
||||||
|
mSharedCmaps.PutEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
||||||
|
return found->GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the cmap from the shared cmap set
|
||||||
|
void
|
||||||
|
gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
|
||||||
|
{
|
||||||
|
// skip lookups during teardown
|
||||||
|
if (mSharedCmaps.Count() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cmap needs to match the entry *and* be the same ptr before removing
|
||||||
|
CharMapHashKey *found =
|
||||||
|
mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
||||||
|
if (found && found->GetKey() == aCharMap) {
|
||||||
|
mSharedCmaps.RemoveEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxPlatformFontList::InitLoader()
|
gfxPlatformFontList::InitLoader()
|
||||||
{
|
{
|
||||||
|
@ -830,6 +868,21 @@ SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry,
|
||||||
return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
SizeOfSharedCmapExcludingThis(CharMapHashKey* aHashEntry,
|
||||||
|
nsMallocSizeOfFun aMallocSizeOf,
|
||||||
|
void* aUserArg)
|
||||||
|
{
|
||||||
|
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
|
||||||
|
|
||||||
|
PRUint32 size = aHashEntry->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
|
||||||
|
sizes->mCharMapsSize += size;
|
||||||
|
|
||||||
|
// we return zero here because the measurements have been added directly
|
||||||
|
// to the relevant fields of the FontListSizes record
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||||
FontListSizes* aSizes) const
|
FontListSizes* aSizes) const
|
||||||
|
@ -865,6 +918,10 @@ gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||||
aSizes->mFontListSize +=
|
aSizes->mFontListSize +=
|
||||||
mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
|
mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
|
||||||
aMallocSizeOf);
|
aMallocSizeOf);
|
||||||
|
|
||||||
|
aSizes->mFontListSize +=
|
||||||
|
mSharedCmaps.SizeOfExcludingThis(SizeOfSharedCmapExcludingThis,
|
||||||
|
aMallocSizeOf, aSizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -50,6 +50,53 @@
|
||||||
#include "nsIMemoryReporter.h"
|
#include "nsIMemoryReporter.h"
|
||||||
#include "mozilla/FunctionTimer.h"
|
#include "mozilla/FunctionTimer.h"
|
||||||
|
|
||||||
|
class CharMapHashKey : public PLDHashEntryHdr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef gfxCharacterMap* KeyType;
|
||||||
|
typedef const gfxCharacterMap* KeyTypePointer;
|
||||||
|
|
||||||
|
CharMapHashKey(const gfxCharacterMap *aCharMap) :
|
||||||
|
mCharMap(const_cast<gfxCharacterMap*>(aCharMap))
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(CharMapHashKey);
|
||||||
|
}
|
||||||
|
CharMapHashKey(const CharMapHashKey& toCopy) :
|
||||||
|
mCharMap(toCopy.mCharMap)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(CharMapHashKey);
|
||||||
|
}
|
||||||
|
~CharMapHashKey()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(CharMapHashKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxCharacterMap* GetKey() const { return mCharMap; }
|
||||||
|
|
||||||
|
bool KeyEquals(const gfxCharacterMap *aCharMap) const {
|
||||||
|
NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly,
|
||||||
|
"custom cmap used in shared cmap hashtable");
|
||||||
|
// cmaps built on the fly never match
|
||||||
|
if (aCharMap->mHash != mCharMap->mHash)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return mCharMap->Equals(aCharMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gfxCharacterMap* KeyToPointer(gfxCharacterMap *aCharMap) {
|
||||||
|
return aCharMap;
|
||||||
|
}
|
||||||
|
static PLDHashNumber HashKey(const gfxCharacterMap *aCharMap) {
|
||||||
|
return aCharMap->mHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { ALLOW_MEMMOVE = true };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
gfxCharacterMap *mCharMap;
|
||||||
|
};
|
||||||
|
|
||||||
// gfxPlatformFontList is an abstract class for the global font list on the system;
|
// gfxPlatformFontList is an abstract class for the global font list on the system;
|
||||||
// concrete subclasses for each platform implement the actual interface to the system fonts.
|
// concrete subclasses for each platform implement the actual interface to the system fonts.
|
||||||
// This class exists because we cannot rely on the platform font-finding APIs to behave
|
// This class exists because we cannot rely on the platform font-finding APIs to behave
|
||||||
|
@ -155,6 +202,16 @@ public:
|
||||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||||
FontListSizes* aSizes) const;
|
FontListSizes* aSizes) const;
|
||||||
|
|
||||||
|
// search for existing cmap that matches the input
|
||||||
|
// return the input if no match is found
|
||||||
|
gfxCharacterMap* FindCharMap(gfxCharacterMap *aCmap);
|
||||||
|
|
||||||
|
// add a cmap to the shared cmap set
|
||||||
|
gfxCharacterMap* AddCmap(const gfxCharacterMap *aCharMap);
|
||||||
|
|
||||||
|
// remove the cmap from the shared cmap set
|
||||||
|
void RemoveCmap(const gfxCharacterMap *aCharMap);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class MemoryReporter
|
class MemoryReporter
|
||||||
: public nsIMemoryMultiReporter
|
: public nsIMemoryMultiReporter
|
||||||
|
@ -264,6 +321,10 @@ protected:
|
||||||
|
|
||||||
nsTHashtable<nsStringHashKey> mBadUnderlineFamilyNames;
|
nsTHashtable<nsStringHashKey> mBadUnderlineFamilyNames;
|
||||||
|
|
||||||
|
// character map data shared across families
|
||||||
|
// contains weak ptrs to cmaps shared by font entry objects
|
||||||
|
nsTHashtable<CharMapHashKey> mSharedCmaps;
|
||||||
|
|
||||||
// data used as part of the font cmap loading process
|
// data used as part of the font cmap loading process
|
||||||
nsTArray<nsRefPtr<gfxFontFamily> > mFontFamiliesToLoad;
|
nsTArray<nsRefPtr<gfxFontFamily> > mFontFamiliesToLoad;
|
||||||
PRUint32 mStartIndex;
|
PRUint32 mStartIndex;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче