зеркало из https://github.com/mozilla/gecko-dev.git
bug 668813 pt 2 - maintain a character coverage map for gfxFontFamily. r=jdaggett
This commit is contained in:
Родитель
c7b249e538
Коммит
911e9c3811
|
@ -692,12 +692,15 @@ void gfxFontFamily::LocalizedName(nsAString& aLocalizedName)
|
|||
void
|
||||
gfxFontFamily::FindFontForChar(FontSearch *aMatchData)
|
||||
{
|
||||
if (!mHasStyles)
|
||||
if (!mHasStyles) {
|
||||
FindStyleVariations();
|
||||
}
|
||||
|
||||
// xxx - optimization point - keep a bit vector with the union of supported unicode ranges
|
||||
// by all fonts for this family and bail immediately if the character is not in any of
|
||||
// this family's cmaps
|
||||
if (!TestCharacterMap(aMatchData->mCh)) {
|
||||
// none of the faces in the family support the required char,
|
||||
// so bail out immediately
|
||||
return;
|
||||
}
|
||||
|
||||
// iterate over fonts
|
||||
PRUint32 numFonts = mAvailableFonts.Length();
|
||||
|
@ -3366,11 +3369,8 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
|
|||
return font.forget();
|
||||
}
|
||||
// check other faces of the family
|
||||
// XXX optimization point: give the family a charmap that is the union
|
||||
// of the char maps of all its faces, so we can quickly test whether
|
||||
// it's worth doing this search
|
||||
gfxFontFamily *family = font->GetFontEntry()->Family();
|
||||
if (family) {
|
||||
if (family && family->TestCharacterMap(aCh)) {
|
||||
FontSearch matchData(aCh, font);
|
||||
family->FindFontForChar(&matchData);
|
||||
gfxFontEntry *fe = matchData.mBestMatch;
|
||||
|
|
|
@ -510,7 +510,8 @@ public:
|
|||
mFaceNamesInitialized(false),
|
||||
mHasStyles(false),
|
||||
mIsSimpleFamily(false),
|
||||
mIsBadUnderlineFamily(false)
|
||||
mIsBadUnderlineFamily(false),
|
||||
mCharacterMapInitialized(false)
|
||||
{ }
|
||||
|
||||
virtual ~gfxFontFamily() {
|
||||
|
@ -583,10 +584,28 @@ public:
|
|||
// read in cmaps for all the faces
|
||||
void ReadCMAP() {
|
||||
PRUint32 i, numFonts = mAvailableFonts.Length();
|
||||
// called from RunLoader BEFORE CheckForSimpleFamily so that there cannot
|
||||
// be any NULL entries in mAvailableFonts
|
||||
for (i = 0; i < numFonts; i++)
|
||||
mAvailableFonts[i]->ReadCMAP();
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe) {
|
||||
continue;
|
||||
}
|
||||
fe->ReadCMAP();
|
||||
mCharacterMap.Union(fe->mCharacterMap);
|
||||
}
|
||||
mCharacterMap.Compact();
|
||||
mCharacterMapInitialized = true;
|
||||
}
|
||||
|
||||
bool TestCharacterMap(PRUint32 aCh) {
|
||||
if (!mCharacterMapInitialized) {
|
||||
ReadCMAP();
|
||||
}
|
||||
return mCharacterMap.test(aCh);
|
||||
}
|
||||
|
||||
void ResetCharacterMap() {
|
||||
mCharacterMap.reset();
|
||||
mCharacterMapInitialized = false;
|
||||
}
|
||||
|
||||
// mark this family as being in the "bad" underline offset blacklist
|
||||
|
@ -629,12 +648,14 @@ protected:
|
|||
|
||||
nsString mName;
|
||||
nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
bool mOtherFamilyNamesInitialized;
|
||||
bool mHasOtherFamilyNames;
|
||||
bool mFaceNamesInitialized;
|
||||
bool mHasStyles;
|
||||
bool mIsSimpleFamily;
|
||||
bool mIsBadUnderlineFamily;
|
||||
bool mCharacterMapInitialized;
|
||||
|
||||
enum {
|
||||
// for "simple" families, the faces are stored in mAvailableFonts
|
||||
|
|
|
@ -315,7 +315,7 @@ gfxFontUtils::ReadCMAPTableFormat12(const PRUint8 *aBuf, PRUint32 aLength,
|
|||
prevEndCharCode = endCharCode;
|
||||
}
|
||||
|
||||
aCharacterMap.mBlocks.Compact();
|
||||
aCharacterMap.Compact();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ gfxFontUtils::ReadCMAPTableFormat4(const PRUint8 *aBuf, PRUint32 aLength,
|
|||
}
|
||||
}
|
||||
|
||||
aCharacterMap.mBlocks.Compact();
|
||||
aCharacterMap.Compact();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -165,8 +165,6 @@ public:
|
|||
Block *block = mBlocks[blockIndex];
|
||||
if (!block) {
|
||||
block = new Block;
|
||||
if (NS_UNLIKELY(!block)) // OOM
|
||||
return;
|
||||
mBlocks[blockIndex] = block;
|
||||
}
|
||||
block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
|
||||
|
@ -201,9 +199,6 @@ public:
|
|||
fullBlock = true;
|
||||
|
||||
block = new Block(fullBlock ? 0xFF : 0);
|
||||
|
||||
if (NS_UNLIKELY(!block)) // OOM
|
||||
return;
|
||||
mBlocks[i] = block;
|
||||
|
||||
if (fullBlock)
|
||||
|
@ -279,7 +274,44 @@ public:
|
|||
for (i = 0; i < mBlocks.Length(); i++)
|
||||
mBlocks[i] = nsnull;
|
||||
}
|
||||
|
||||
|
||||
// set this bitset to the union of its current contents and another
|
||||
void Union(const gfxSparseBitSet& aBitset) {
|
||||
// ensure mBlocks is large enough
|
||||
PRUint32 blockCount = aBitset.mBlocks.Length();
|
||||
if (blockCount > mBlocks.Length()) {
|
||||
PRUint32 needed = blockCount - mBlocks.Length();
|
||||
nsAutoPtr<Block> *blocks = mBlocks.AppendElements(needed);
|
||||
if (NS_UNLIKELY(!blocks)) { // OOM
|
||||
return;
|
||||
}
|
||||
}
|
||||
// for each block that may be present in aBitset...
|
||||
for (PRUint32 i = 0; i < blockCount; ++i) {
|
||||
// if it is missing (implicitly empty), just skip
|
||||
if (!aBitset.mBlocks[i]) {
|
||||
continue;
|
||||
}
|
||||
// if the block is missing in this set, just copy the other
|
||||
if (!mBlocks[i]) {
|
||||
mBlocks[i] = new Block(*aBitset.mBlocks[i]);
|
||||
continue;
|
||||
}
|
||||
// else set existing block to the union of both
|
||||
PRUint32 *dst = reinterpret_cast<PRUint32*>(mBlocks[i]->mBits);
|
||||
const PRUint32 *src =
|
||||
reinterpret_cast<const PRUint32*>(aBitset.mBlocks[i]->mBits);
|
||||
for (PRUint32 j = 0; j < BLOCK_SIZE / 4; ++j) {
|
||||
dst[j] |= src[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compact() {
|
||||
mBlocks.Compact();
|
||||
}
|
||||
|
||||
private:
|
||||
nsTArray< nsAutoPtr<Block> > mBlocks;
|
||||
};
|
||||
|
||||
|
|
|
@ -110,10 +110,11 @@ public:
|
|||
nsRefPtr<gfxFontEntry> fe = aFontEntry;
|
||||
mAvailableFonts.AppendElement(fe);
|
||||
aFontEntry->SetFamily(this);
|
||||
ResetCharacterMap();
|
||||
}
|
||||
|
||||
void ReplaceFontEntry(gfxFontEntry *aOldFontEntry, gfxFontEntry *aNewFontEntry)
|
||||
{
|
||||
void ReplaceFontEntry(gfxFontEntry *aOldFontEntry,
|
||||
gfxFontEntry *aNewFontEntry) {
|
||||
PRUint32 numFonts = mAvailableFonts.Length();
|
||||
for (PRUint32 i = 0; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
|
@ -123,22 +124,23 @@ public:
|
|||
// other reference to it except from its family
|
||||
mAvailableFonts[i] = aNewFontEntry;
|
||||
aNewFontEntry->SetFamily(this);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ResetCharacterMap();
|
||||
}
|
||||
|
||||
void RemoveFontEntry(gfxFontEntry *aFontEntry)
|
||||
{
|
||||
void RemoveFontEntry(gfxFontEntry *aFontEntry) {
|
||||
PRUint32 numFonts = mAvailableFonts.Length();
|
||||
for (PRUint32 i = 0; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (fe == aFontEntry) {
|
||||
aFontEntry->SetFamily(nsnull);
|
||||
mAvailableFonts.RemoveElementAt(i);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ResetCharacterMap();
|
||||
}
|
||||
|
||||
// clear family pointer for all entries and remove them from the family;
|
||||
|
|
Загрузка…
Ссылка в новой задаче