mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-12 00:50:40 +00:00
Backout bug 377950 due to startup crashes.
This commit is contained in:
parent
05b111e301
commit
a57f4060b6
@ -124,7 +124,7 @@ public:
|
||||
/**
|
||||
* Create the appropriate platform font group
|
||||
*/
|
||||
virtual gfxFontGroup *CreateFontGroup(const nsAString& aFamilies,
|
||||
virtual gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle) = 0;
|
||||
|
||||
/* Returns PR_TRUE if the given block of ARGB32 data really has alpha, otherwise PR_FALSE */
|
||||
|
@ -60,6 +60,45 @@
|
||||
|
||||
#define NO_RANGE_FOUND 126 // bit 126 in the font unicode ranges is required to be 0
|
||||
|
||||
/** @description Font Weights
|
||||
* Each available font weight is stored as as single bit inside a bitset.
|
||||
* e.g. The binary value 0000000000001000 indcates font weight 400 is available.
|
||||
* while the binary value 0000000000001001 indicates both font weight 100 and 400 are available
|
||||
*
|
||||
* The font weights which will be represented include {100, 200, 300, 400, 500, 600, 700, 800, 900}
|
||||
* The font weight specified in the mFont->weight may include values which are not an even multiple of 100.
|
||||
* If so, the font weight mod 100 indicates the number steps to lighten are make bolder.
|
||||
* This corresponds to the CSS lighter and bolder property values. If bolder is applied twice to the font which has
|
||||
* a font weight of 400 then the mFont->weight will contain the value 402.
|
||||
* If lighter is applied twice to a font of weight 400 then the mFont->weight will contain the value 398.
|
||||
* Only nine steps of bolder or lighter are allowed by the CSS XPCODE.
|
||||
*/
|
||||
// XXX change this from using a bitset to something cleaner eventually
|
||||
class WeightTable
|
||||
{
|
||||
public:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(WeightTable)
|
||||
|
||||
WeightTable() : mWeights(0) {}
|
||||
~WeightTable() {
|
||||
|
||||
}
|
||||
PRBool TriedWeight(PRUint8 aWeight) {
|
||||
return mWeights[aWeight - 1 + 10];
|
||||
}
|
||||
PRBool HasWeight(PRUint8 aWeight) {
|
||||
return mWeights[aWeight - 1];
|
||||
}
|
||||
void SetWeight(PRUint8 aWeight, PRBool aValue) {
|
||||
mWeights[aWeight - 1] = (aValue == PR_TRUE);
|
||||
mWeights[aWeight - 1 + 10] = PR_TRUE;
|
||||
}
|
||||
|
||||
private:
|
||||
std::bitset<20> mWeights;
|
||||
};
|
||||
|
||||
|
||||
/* Unicode subrange table
|
||||
* from: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_63ub.asp
|
||||
*
|
||||
@ -240,58 +279,6 @@ static PRUint8 CharRangeBit(PRUint32 ch) {
|
||||
return NO_RANGE_FOUND;
|
||||
}
|
||||
|
||||
|
||||
class gfxSparseBitSet {
|
||||
public:
|
||||
enum { BLOCK_SIZE = 32 };
|
||||
|
||||
PRBool test(PRUint32 aIndex) {
|
||||
PRUint32 blockIndex = aIndex/(BLOCK_SIZE*8);
|
||||
if (blockIndex >= mBlocks.Length())
|
||||
return PR_FALSE;
|
||||
Block *block = mBlocks[blockIndex];
|
||||
if (!block)
|
||||
return PR_FALSE;
|
||||
return ((block->mBits[(aIndex/8) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0;
|
||||
}
|
||||
|
||||
void set(PRUint32 aIndex) {
|
||||
PRUint32 blockIndex = aIndex/(BLOCK_SIZE*8);
|
||||
if (blockIndex >= mBlocks.Length()) {
|
||||
nsAutoPtr<Block> *blocks = mBlocks.AppendElements(blockIndex + 1 - mBlocks.Length());
|
||||
if (!blocks) // OOM
|
||||
return;
|
||||
}
|
||||
Block *block = mBlocks[blockIndex];
|
||||
if (!block) {
|
||||
block = new Block;
|
||||
if (!block) // OOM
|
||||
return;
|
||||
memset(block, 0, sizeof(Block));
|
||||
mBlocks[blockIndex] = block;
|
||||
}
|
||||
block->mBits[(aIndex/8) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
|
||||
}
|
||||
|
||||
PRUint32 getsize() {
|
||||
PRUint32 size = 0;
|
||||
for (PRUint32 i = 0; i < mBlocks.Length(); i++)
|
||||
if (mBlocks[i])
|
||||
size += sizeof(Block);
|
||||
return size;
|
||||
}
|
||||
|
||||
// If you want to set a lot of bits very fast, we could have Set variants
|
||||
// that set a lot of bits at once, e.g. Set(PRUint32 aStart, PRUint32 aLength)
|
||||
|
||||
private:
|
||||
struct Block {
|
||||
PRUint8 mBits[BLOCK_SIZE];
|
||||
};
|
||||
|
||||
nsTArray< nsAutoPtr<Block> > mBlocks;
|
||||
};
|
||||
|
||||
/**
|
||||
* FontEntry is a class that describes one of the fonts on the users system
|
||||
* It contains information such as the name, font type, charset table and unicode ranges.
|
||||
@ -304,8 +291,8 @@ public:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
|
||||
|
||||
FontEntry(const nsAString& aName, PRUint16 aFontType) :
|
||||
mName(aName), mFontType(aFontType), mDefaultWeight(0),
|
||||
mUnicodeFont(PR_FALSE), mCharset(0), mUnicodeRanges(0)
|
||||
mName(aName), mFontType(aFontType), mUnicodeFont(PR_FALSE),
|
||||
mCharset(0), mUnicodeRanges(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -398,32 +385,10 @@ public:
|
||||
return mUnicodeRanges[range];
|
||||
}
|
||||
|
||||
class WeightTable
|
||||
{
|
||||
public:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(WeightTable)
|
||||
|
||||
WeightTable() : mWeights(0) {}
|
||||
~WeightTable() {}
|
||||
PRBool TriedWeight(PRUint8 aWeight) {
|
||||
return mWeights[aWeight - 1 + 10];
|
||||
}
|
||||
PRBool HasWeight(PRUint8 aWeight) {
|
||||
return mWeights[aWeight - 1];
|
||||
}
|
||||
void SetWeight(PRUint8 aWeight, PRBool aValue) {
|
||||
mWeights[aWeight - 1] = aValue;
|
||||
mWeights[aWeight - 1 + 10] = PR_TRUE;
|
||||
}
|
||||
private:
|
||||
std::bitset<20> mWeights;
|
||||
};
|
||||
|
||||
// The family name of the font
|
||||
nsString mName;
|
||||
|
||||
PRUint16 mFontType;
|
||||
PRUint16 mDefaultWeight;
|
||||
|
||||
PRUint8 mFamily;
|
||||
PRUint8 mPitch;
|
||||
@ -431,10 +396,6 @@ public:
|
||||
|
||||
std::bitset<256> mCharset;
|
||||
std::bitset<128> mUnicodeRanges;
|
||||
|
||||
WeightTable mWeightTable;
|
||||
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
};
|
||||
|
||||
|
||||
@ -468,8 +429,6 @@ public:
|
||||
return mSpaceGlyph;
|
||||
};
|
||||
|
||||
FontEntry *GetFontEntry() { return mFontEntry; }
|
||||
|
||||
protected:
|
||||
HFONT MakeHFONT();
|
||||
cairo_font_face_t *MakeCairoFontFace();
|
||||
@ -493,7 +452,7 @@ private:
|
||||
|
||||
LOGFONTW mLogFont;
|
||||
|
||||
nsRefPtr<FontEntry> mFontEntry;
|
||||
nsRefPtr<WeightTable> mWeightTable;
|
||||
|
||||
virtual void SetupCairoFont(cairo_t *aCR);
|
||||
};
|
||||
|
@ -72,17 +72,11 @@ public:
|
||||
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle);
|
||||
|
||||
/* Given a string and a font we already have find the font that
|
||||
* supports the most code points and most closely resembles aFont
|
||||
*
|
||||
* this involves looking at the fonts on your machine and seeing which
|
||||
* code points they support as well as looking at things like the font
|
||||
* family, style, weight, etc.
|
||||
*/
|
||||
FontEntry *FindFontForString(const PRUnichar *aString, PRUint32 aLength, gfxWindowsFont *aFont);
|
||||
/* local methods */
|
||||
void FindOtherFonts(const PRUnichar *aString, PRUint32 aLength, const char *aLangGroup, const char *aGeneric, nsString& array);
|
||||
|
||||
/* Find a FontEntry object that represents a font on your system given a name */
|
||||
FontEntry *FindFontEntry(const nsAString& aName);
|
||||
WeightTable *GetFontWeightTable(const nsAString& aName);
|
||||
void PutFontWeightTable(const nsAString& aName, WeightTable *aWeightTable);
|
||||
|
||||
private:
|
||||
void Init();
|
||||
@ -91,10 +85,6 @@ private:
|
||||
const NEWTEXTMETRICEXW *metrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg);
|
||||
|
||||
static int CALLBACK FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *metrics,
|
||||
DWORD fontType, LPARAM data);
|
||||
@ -103,11 +93,12 @@ private:
|
||||
nsRefPtr<FontEntry>& aData,
|
||||
void* userArg);
|
||||
|
||||
static PLDHashOperator PR_CALLBACK FindFontForStringProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg);
|
||||
static PLDHashOperator PR_CALLBACK FindFontForChar(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg);
|
||||
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFonts;
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<WeightTable> > mFontWeights;
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFontAliases;
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mFontSubstitutes;
|
||||
nsStringArray mNonExistingFonts;
|
||||
|
@ -97,9 +97,6 @@ gfxWindowsFont::gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFont
|
||||
mFontFace(nsnull), mScaledFont(nsnull),
|
||||
mMetrics(nsnull)
|
||||
{
|
||||
// XXX we should work to get this passed in rather than having to find it again.
|
||||
mFontEntry = gfxWindowsPlatform::GetPlatform()->FindFontEntry(aName);
|
||||
NS_ASSERTION(mFontEntry, "Unable to find font entry for font. Something is whack.");
|
||||
}
|
||||
|
||||
gfxWindowsFont::~gfxWindowsFont()
|
||||
@ -178,6 +175,19 @@ gfxWindowsFont::MakeHFONT()
|
||||
if (mFont)
|
||||
return mFont;
|
||||
|
||||
if (!mWeightTable) {
|
||||
nsString name(mName);
|
||||
ToLowerCase(name);
|
||||
|
||||
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
||||
|
||||
mWeightTable = platform->GetFontWeightTable(name);
|
||||
if (!mWeightTable) {
|
||||
mWeightTable = new WeightTable();
|
||||
platform->PutFontWeightTable(name, mWeightTable);
|
||||
}
|
||||
}
|
||||
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
|
||||
@ -188,10 +198,10 @@ gfxWindowsFont::MakeHFONT()
|
||||
if (weightDistance >= 0) {
|
||||
|
||||
for (PRUint8 i = baseWeight, k = 0; i < 10; i++) {
|
||||
if (mFontEntry->mWeightTable.HasWeight(i)) {
|
||||
if (mWeightTable->HasWeight(i)) {
|
||||
k++;
|
||||
chosenWeight = i * 100;
|
||||
} else if (mFontEntry->mWeightTable.TriedWeight(i)) {
|
||||
} else if (mWeightTable->TriedWeight(i)) {
|
||||
continue;
|
||||
} else {
|
||||
const PRUint32 tryWeight = i * 100;
|
||||
@ -206,7 +216,7 @@ gfxWindowsFont::MakeHFONT()
|
||||
GetTextMetrics(dc, &metrics);
|
||||
|
||||
PRBool hasWeight = (metrics.tmWeight == tryWeight);
|
||||
mFontEntry->mWeightTable.SetWeight(i, hasWeight);
|
||||
mWeightTable->SetWeight(i, hasWeight);
|
||||
if (hasWeight) {
|
||||
chosenWeight = i * 100;
|
||||
k++;
|
||||
@ -318,7 +328,7 @@ gfxWindowsFont::ComputeMetrics()
|
||||
mMetrics->strikeoutOffset = (double)oMetrics.otmsStrikeoutPosition;
|
||||
mMetrics->underlineSize = PR_MAX(1, (double)oMetrics.otmsUnderscoreSize);
|
||||
mMetrics->underlineOffset = (double)oMetrics.otmsUnderscorePosition;
|
||||
|
||||
|
||||
const MAT2 kIdentityMatrix = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
|
||||
GLYPHMETRICS gm;
|
||||
DWORD len = GetGlyphOutlineW(dc, PRUnichar('x'), GGO_METRICS, &gm, 0, nsnull, &kIdentityMatrix);
|
||||
@ -664,7 +674,7 @@ SetupTextRunFromGlyphs(gfxTextRun *aRun, WCHAR *aGlyphs, HDC aDC,
|
||||
PRUint32 length = aRun->GetLength();
|
||||
if (IsAnyGlyphMissing(aGlyphs, length))
|
||||
return PR_FALSE;
|
||||
|
||||
|
||||
SIZE size;
|
||||
nsAutoTArray<int,500> partialWidthArray;
|
||||
if (!partialWidthArray.AppendElements(length))
|
||||
@ -926,6 +936,11 @@ public:
|
||||
free(mAlternativeString);
|
||||
}
|
||||
|
||||
const PRUnichar *GetString() const { return mString; }
|
||||
const PRUint32 GetStringLength() const { return mLength; }
|
||||
|
||||
|
||||
|
||||
static PRBool AddFontCallback(const nsAString& aName,
|
||||
const nsACString& aGenericName,
|
||||
void *closure) {
|
||||
@ -940,26 +955,53 @@ public:
|
||||
if (aName.Equals(item->mFonts[i]->GetName()))
|
||||
return PR_TRUE;
|
||||
|
||||
nsRefPtr<gfxWindowsFont> font = GetOrMakeFont(aName, item->mGroup->GetStyle());
|
||||
nsRefPtr<gfxWindowsFont> font =
|
||||
GetOrMakeFont(aName, item->mGroup->GetStyle());
|
||||
if (font) {
|
||||
item->mFonts.AppendElement(font);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
HRESULT Break() {
|
||||
HRESULT rv;
|
||||
|
||||
SCRIPT_LOGATTR *logAttrs = (SCRIPT_LOGATTR*)malloc(sizeof(SCRIPT_LOGATTR) * mLength);
|
||||
|
||||
rv = ScriptBreak(mString, mLength, &mScriptItem->a, logAttrs);
|
||||
|
||||
for (PRUint32 i = 0; i < mLength; ++i) {
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("0x%04x - %d %d %d %d %d",
|
||||
mString[i],
|
||||
logAttrs[i].fSoftBreak,
|
||||
logAttrs[i].fWhiteSpace,
|
||||
logAttrs[i].fCharStop,
|
||||
logAttrs[i].fWordStop,
|
||||
logAttrs[i].fInvalid));
|
||||
}
|
||||
|
||||
free(logAttrs);
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* possible return values:
|
||||
* S_OK - things succeeded
|
||||
* GDI_ERROR - things failed to shape. Might want to try again after calling DisableShaping()
|
||||
*/
|
||||
E_PENDING -- means script cache lookup failed, DC needs to be set and font selected in to it.
|
||||
USP_E_SCRIPT_NOT_IN_FONT -- this font doesn't support this text. keep trying new fonts.
|
||||
if you try all possible fonts, then go back to font 0 after calling DisableShaping and try again
|
||||
through all the fonts
|
||||
*/
|
||||
HRESULT Shape() {
|
||||
HRESULT rv;
|
||||
|
||||
HDC shapeDC = nsnull;
|
||||
|
||||
const PRUnichar *str = mAlternativeString ? mAlternativeString : mString;
|
||||
|
||||
while (PR_TRUE) {
|
||||
const PRUnichar *str =
|
||||
mAlternativeString ? mAlternativeString : mString;
|
||||
mScriptItem->a.fLogicalOrder = PR_TRUE;
|
||||
mScriptItem->a.s.fDisplayZWG = PR_TRUE;
|
||||
|
||||
rv = ScriptShape(shapeDC, mCurrentFont->ScriptCache(),
|
||||
str, mLength,
|
||||
@ -981,6 +1023,10 @@ public:
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0 // debugging only
|
||||
if (rv != USP_E_SCRIPT_NOT_IN_FONT && !shapeDC)
|
||||
printf("skipped select-shape %d\n", rv);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@ -997,19 +1043,30 @@ public:
|
||||
GenerateAlternativeString();
|
||||
}
|
||||
|
||||
/* this should only be called if there are no surrogates
|
||||
* in the string */
|
||||
PRBool IsMissingGlyphsCMap() {
|
||||
nsRefPtr<FontEntry> fe = GetCurrentFont()->GetFontEntry();
|
||||
for (PRUint32 i = 0; i < mLength; i++) {
|
||||
PRUint32 ch = mString[i];
|
||||
if ((i+1 < mLength) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(mString[i+1])) {
|
||||
i++;
|
||||
ch = SURROGATE_TO_UCS4(ch, mString[i]);
|
||||
}
|
||||
if (!fe->mCharacterMap.test(ch))
|
||||
return PR_TRUE;
|
||||
}
|
||||
HRESULT rv;
|
||||
HDC cmapDC = nsnull;
|
||||
|
||||
return PR_FALSE;
|
||||
while (PR_TRUE) {
|
||||
rv = ScriptGetCMap(cmapDC, mCurrentFont->ScriptCache(),
|
||||
mString, mLength, 0, mGlyphs);
|
||||
|
||||
if (rv == E_PENDING) {
|
||||
SelectFont();
|
||||
cmapDC = mDC;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rv == S_OK)
|
||||
return PR_FALSE;
|
||||
|
||||
PR_LOG(gFontLog, PR_LOG_WARNING, ("cmap is missing a glyph"));
|
||||
for (PRUint32 i = 0; i < mLength; i++)
|
||||
PR_LOG(gFontLog, PR_LOG_WARNING, (" - %d", mGlyphs[i]));
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool IsGlyphMissing(SCRIPT_FONTPROPERTIES *aSFP, PRUint32 aGlyphIndex) {
|
||||
@ -1018,6 +1075,22 @@ public:
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool IsMissingGlyphs() {
|
||||
SCRIPT_FONTPROPERTIES sfp;
|
||||
ScriptFontProperties(&sfp);
|
||||
PRUint32 charIndex = 0;
|
||||
for (int i = 0; i < mNumGlyphs; ++i) {
|
||||
if (IsGlyphMissing(&sfp, i))
|
||||
return PR_TRUE;
|
||||
#ifdef DEBUG_pavlov // excess debugging code
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("%04x %04x %04x", sfp.wgBlank, sfp.wgDefault, sfp.wgInvalid));
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("glyph%d - 0x%04x", i, mGlyphs[i]));
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("%04x -- %04x -- %04x", ScriptProperties()->fInvalidGlyph, mScriptItem->a.fNoGlyphIndex, mAttr[i].fZeroWidth));
|
||||
#endif
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
HRESULT Place() {
|
||||
HRESULT rv;
|
||||
|
||||
@ -1213,6 +1286,7 @@ TRY_AGAIN_HOPE_FOR_THE_BEST_2:
|
||||
goto TRY_AGAIN_HOPE_FOR_THE_BEST_2;
|
||||
} else if (!mTriedOtherFonts) {
|
||||
mTriedOtherFonts = PR_TRUE;
|
||||
nsString fonts;
|
||||
gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
|
||||
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) {
|
||||
@ -1228,16 +1302,22 @@ TRY_AGAIN_HOPE_FOR_THE_BEST_2:
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - 0x%04x", ch));
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<FontEntry> newFont = platform->FindFontForString(mString, mLength, mFonts[0]);
|
||||
|
||||
if (newFont) {
|
||||
|
||||
platform->FindOtherFonts(mString, mLength,
|
||||
nsPromiseFlatCString(mGroup->GetStyle()->langGroup).get(),
|
||||
nsPromiseFlatCString(mGroup->GetGenericFamily()).get(),
|
||||
fonts);
|
||||
if (!fonts.IsEmpty()) {
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("Got back: %s", NS_LossyConvertUTF16toASCII(newFont->mName).get()));
|
||||
|
||||
AddFontCallback(newFont->mName, EmptyCString(), this);
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("Got back: %s", NS_LossyConvertUTF16toASCII(fonts).get()));
|
||||
gfxFontGroup::ForEachFont(fonts, EmptyCString(), UniscribeItem::AddFontCallback, this);
|
||||
}
|
||||
goto TRY_AGAIN_HOPE_FOR_THE_BEST_2;
|
||||
} else {
|
||||
// const SCRIPT_PROPERTIES *sp = item->ScriptProperties();
|
||||
// We should try to look up the font based on sp.langgroup
|
||||
// if it isn't ambiguious. Would save us time over doing
|
||||
// character by character lookups at least for pref fonts
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
@ -1273,6 +1353,7 @@ TRY_AGAIN_HOPE_FOR_THE_BEST_2:
|
||||
mFontSelected = PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static PRInt32 GetCJKLangGroupIndex(const char *aLangGroup) {
|
||||
PRInt32 i;
|
||||
@ -1360,7 +1441,6 @@ private:
|
||||
mAlternativeString[i] = PRUnichar(0xFFFD);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<gfxContext> mContext;
|
||||
HDC mDC;
|
||||
@ -1401,6 +1481,7 @@ class Uniscribe
|
||||
public:
|
||||
Uniscribe(gfxContext *aContext, HDC aDC, const PRUnichar *aString, PRUint32 aLength, PRBool aIsRTL) :
|
||||
mContext(aContext), mDC(aDC), mString(aString), mLength(aLength), mIsRTL(aIsRTL),
|
||||
mIsComplex(ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK),
|
||||
mItems(nsnull) {
|
||||
}
|
||||
~Uniscribe() {
|
||||
@ -1460,6 +1541,8 @@ private:
|
||||
const PRUnichar *mString;
|
||||
const PRUint32 mLength;
|
||||
const PRBool mIsRTL;
|
||||
// XXX not used
|
||||
const PRBool mIsComplex;
|
||||
|
||||
SCRIPT_CONTROL mControl;
|
||||
SCRIPT_STATE mState;
|
||||
@ -1467,9 +1550,10 @@ private:
|
||||
int mNumItems;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
gfxWindowsFontGroup::InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString,
|
||||
PRUint32 aLength)
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsRefPtr<gfxASurface> surf = aContext->CurrentSurface();
|
||||
HDC aDC = GetDCFromSurface(surf);
|
||||
@ -1484,7 +1568,7 @@ gfxWindowsFontGroup::InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun
|
||||
/* itemize the string */
|
||||
int numItems = us.Itemize();
|
||||
|
||||
for (int i = 0; i < numItems; ++i) {
|
||||
for (int i=0; i < numItems; ++i) {
|
||||
PRUint32 fontIndex = 0;
|
||||
|
||||
SaveDC(aDC);
|
||||
@ -1500,46 +1584,59 @@ gfxWindowsFontGroup::InitTextRunUniscribe(gfxContext *aContext, gfxTextRun *aRun
|
||||
if (font) {
|
||||
/* set the curret font on the item */
|
||||
item->SetCurrentFont(font);
|
||||
|
||||
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("trying: %s", NS_LossyConvertUTF16toASCII(font->GetName()).get()));
|
||||
|
||||
if (!giveUp && item->IsMissingGlyphsCMap()) {
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - missing glyphs in cmap"));
|
||||
continue;
|
||||
|
||||
PRBool cmapHasGlyphs = PR_FALSE; // false means "maybe" here
|
||||
|
||||
if (!giveUp && !(aRun->GetFlags() & TEXT_HAS_SURROGATES)) {
|
||||
if (item->IsMissingGlyphsCMap())
|
||||
continue;
|
||||
else
|
||||
cmapHasGlyphs = PR_TRUE;
|
||||
}
|
||||
|
||||
SCRIPT_SHAPE:
|
||||
|
||||
rv = item->Shape();
|
||||
|
||||
|
||||
if (giveUp) {
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("%s - gave up", NS_LossyConvertUTF16toASCII(font->GetName()).get()));
|
||||
goto SCRIPT_PLACE;
|
||||
}
|
||||
|
||||
if (FAILED(rv)) {
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - shaping failed"));
|
||||
// we know we have the glyphs to display this font already
|
||||
// so Uniscribe just doesn't know how to shape the script.
|
||||
// Render the glyphs without shaping.
|
||||
item->DisableShaping();
|
||||
goto SCRIPT_SHAPE;
|
||||
}
|
||||
|
||||
if (FAILED(rv))
|
||||
continue;
|
||||
|
||||
if (!cmapHasGlyphs && item->IsMissingGlyphs())
|
||||
continue;
|
||||
|
||||
} else {
|
||||
#if 0
|
||||
/* code to try all the fonts again without shaping on.
|
||||
in general, if we couldn't shape we should probably just give up */
|
||||
if (item->ShapingEnabled()) {
|
||||
item->DisableShaping();
|
||||
item->ResetFontIndex();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
giveUp = PR_TRUE;
|
||||
item->DisableShaping();
|
||||
item->ResetFontIndex();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
||||
PR_LOG(gFontLog, PR_LOG_DEBUG, ("%s - worked", NS_LossyConvertUTF16toASCII(font->GetName()).get()));
|
||||
|
||||
|
||||
SCRIPT_PLACE:
|
||||
NS_ASSERTION(SUCCEEDED(rv), "Failed to shape -- we should never hit this");
|
||||
|
||||
#ifdef DEBUG_pavlov
|
||||
item->Break();
|
||||
#endif
|
||||
|
||||
rv = item->Place();
|
||||
if (FAILED(rv)) {
|
||||
if (PR_LOG_TEST(gFontLog, PR_LOG_WARNING))
|
||||
@ -1551,7 +1648,6 @@ SCRIPT_PLACE:
|
||||
}
|
||||
|
||||
item->SaveGlyphs(aRun);
|
||||
|
||||
delete item;
|
||||
|
||||
RestoreDC(aDC, -1);
|
||||
|
@ -54,21 +54,10 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
//#define DEBUG_CMAP_SIZE 1
|
||||
|
||||
/* Define this if we want to update the unicode range bitsets based
|
||||
* on the actual characters a font supports.
|
||||
*
|
||||
* Doing this can result in very large lists of fonts being returned.
|
||||
* Not doing this can let us prioritize fonts that do have the bit set
|
||||
* as they are more likely to provide better glyphs (in theory).
|
||||
*/
|
||||
//#define UPDATE_RANGES
|
||||
|
||||
|
||||
gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
{
|
||||
mFonts.Init(200);
|
||||
mFontWeights.Init(200);
|
||||
mFontAliases.Init(20);
|
||||
mFontSubstitutes.Init(50);
|
||||
UpdateFontList();
|
||||
@ -114,11 +103,13 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
// mark the charset bit
|
||||
fe->mCharset[metrics.tmCharSet] = 1;
|
||||
|
||||
// put the default weight in the weight table
|
||||
fe->mWeightTable.SetWeight(PR_MAX(1, PR_MIN(9, metrics.tmWeight / 100)), PR_TRUE);
|
||||
|
||||
// store the default font weight
|
||||
fe->mDefaultWeight = metrics.tmWeight;
|
||||
// put this in the weight table
|
||||
nsRefPtr<WeightTable> wt;
|
||||
if (!thisp->mFontWeights.Get(name, &wt)) {
|
||||
wt = new WeightTable();
|
||||
wt->SetWeight(PR_MAX(1, PR_MIN(9, metrics.tmWeight / 100)), PR_TRUE);
|
||||
thisp->mFontWeights.Put(name, wt);
|
||||
}
|
||||
|
||||
fe->mFamily = logFont.lfPitchAndFamily & 0xF0;
|
||||
fe->mPitch = logFont.lfPitchAndFamily & 0x0F;
|
||||
@ -145,227 +136,6 @@ gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline PRUint16
|
||||
ReadShortAt(const PRUint8 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
|
||||
}
|
||||
|
||||
static inline PRUint32
|
||||
ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) | (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 len, FontEntry *aFontEntry)
|
||||
{
|
||||
enum {
|
||||
OffsetFormat = 0,
|
||||
OffsetReserved = 2,
|
||||
OffsetTableLength = 4,
|
||||
OffsetLanguage = 8,
|
||||
OffsetNumberGroups = 12,
|
||||
OffsetGroups = 16,
|
||||
|
||||
SizeOfGroup = 12,
|
||||
|
||||
GroupOffsetStartCode = 0,
|
||||
GroupOffsetEndCode = 4
|
||||
};
|
||||
|
||||
NS_ENSURE_TRUE(ReadShortAt(aBuf, OffsetFormat) == 12, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(ReadShortAt(aBuf, OffsetReserved) == 0, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(ReadLongAt(aBuf, OffsetTableLength) != 0, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(ReadLongAt(aBuf, OffsetLanguage) == 0, NS_ERROR_FAILURE);
|
||||
|
||||
const PRUint32 numGroups = ReadLongAt(aBuf, OffsetNumberGroups);
|
||||
const PRUint8 *groups = aBuf + OffsetGroups;
|
||||
for (PRUint32 i = 0; i < numGroups; i++, groups += SizeOfGroup) {
|
||||
const PRUint32 startCharCode = ReadLongAt(groups, GroupOffsetStartCode);
|
||||
const PRUint32 endCharCode = ReadLongAt(groups, GroupOffsetEndCode);
|
||||
for (PRUint32 c = startCharCode; c <= endCharCode; ++c) {
|
||||
// XXX we should use a range setting functions on gfxSparseBitset
|
||||
// which could be a lot faster
|
||||
aFontEntry->mCharacterMap.set(c);
|
||||
#ifdef UPDATE_RANGES
|
||||
PRUint16 b = CharRangeBit(c);
|
||||
if (b != NO_RANGE_FOUND)
|
||||
aFontEntry->mUnicodeRanges.set(b, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, FontEntry *aFontEntry)
|
||||
{
|
||||
enum {
|
||||
OffsetFormat = 0,
|
||||
OffsetLength = 2,
|
||||
OffsetLanguage = 4,
|
||||
OffsetSegCountX2 = 6,
|
||||
};
|
||||
|
||||
NS_ENSURE_TRUE(ReadShortAt(aBuf, OffsetFormat) == 4, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(ReadShortAt(aBuf, OffsetLength) != 0, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(ReadShortAt(aBuf, OffsetLanguage) == 0, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint16 segCountX2 = ReadShortAt(aBuf, OffsetSegCountX2);
|
||||
const PRUint8 *endCounts = aBuf + 14;
|
||||
const PRUint8 *startCounts = endCounts + segCountX2 + 2;
|
||||
const PRUint8 *idDeltas = startCounts + segCountX2;
|
||||
const PRUint8 *idRangeOffsets = idDeltas + segCountX2;
|
||||
for (PRUint16 i = 0; i < segCountX2; i += 2) {
|
||||
const PRUint16 endCount = ReadShortAt(endCounts, i);
|
||||
const PRUint16 startCount = ReadShortAt(startCounts, i);
|
||||
const PRUint16 idRangeOffset = ReadShortAt(idRangeOffsets, i);
|
||||
if (idRangeOffset == 0) {
|
||||
for (PRUint32 c = startCount; c <= endCount; c++) {
|
||||
aFontEntry->mCharacterMap.set(c);
|
||||
#ifdef UPDATE_RANGES
|
||||
PRUint16 b = CharRangeBit(c);
|
||||
if (b != NO_RANGE_FOUND)
|
||||
aFontEntry->mUnicodeRanges.set(b, true);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
const PRUint8 *gdata = idRangeOffsets + i + idRangeOffset;
|
||||
for (PRUint16 c = startCount; c <= endCount; ++c, gdata += 2) {
|
||||
// make sure we have a glyph
|
||||
if (PRUint16 g = ReadShortAt(gdata, 0)) {
|
||||
aFontEntry->mCharacterMap.set(c);
|
||||
#ifdef UPDATE_RANGES
|
||||
PRUint16 b = CharRangeBit(c);
|
||||
if (b != NO_RANGE_FOUND)
|
||||
aFontEntry->mUnicodeRanges.set(b, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadCMAP(HDC hdc, FontEntry *aFontEntry)
|
||||
{
|
||||
const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
|
||||
|
||||
DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
|
||||
NS_ENSURE_TRUE(len != GDI_ERROR && len != 0, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoTArray<PRUint8,16384> buffer;
|
||||
if (!buffer.AppendElements(len))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
PRUint8 *buf = buffer.Elements();
|
||||
|
||||
DWORD newLen = GetFontData(hdc, kCMAP, 0, buf, len);
|
||||
NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
|
||||
|
||||
enum {
|
||||
OffsetVersion = 0,
|
||||
OffsetNumTables = 2,
|
||||
SizeOfHeader = 4,
|
||||
|
||||
TableOffsetPlatformID = 0,
|
||||
TableOffsetEncodingID = 2,
|
||||
TableOffsetOffset = 4,
|
||||
SizeOfTable = 8,
|
||||
|
||||
SubtableOffsetFormat = 0,
|
||||
};
|
||||
enum {
|
||||
PlatformIDMicrosoft = 3
|
||||
};
|
||||
enum {
|
||||
EncodingIDMicrosoft = 1,
|
||||
EncodingIDUCS4 = 10
|
||||
};
|
||||
|
||||
PRUint16 version = ReadShortAt(buf, OffsetVersion);
|
||||
PRUint16 numTables = ReadShortAt(buf, OffsetNumTables);
|
||||
|
||||
// save the format and offset we want here
|
||||
PRUint32 keepOffset;
|
||||
PRUint32 keepFormat;
|
||||
|
||||
PRUint8 *table = buf + SizeOfHeader;
|
||||
for (PRUint16 i = 0; i < numTables; ++i, table += SizeOfTable) {
|
||||
const PRUint16 platformID = ReadShortAt(table, TableOffsetPlatformID);
|
||||
if (platformID != PlatformIDMicrosoft)
|
||||
continue;
|
||||
|
||||
const PRUint16 encodingID = ReadShortAt(table, TableOffsetEncodingID);
|
||||
const PRUint32 offset = ReadLongAt(table, TableOffsetOffset);
|
||||
|
||||
const PRUint8 *subtable = buf + offset;
|
||||
const PRUint16 format = ReadShortAt(subtable, SubtableOffsetFormat);
|
||||
|
||||
if (format == 4 && encodingID == EncodingIDMicrosoft) {
|
||||
keepFormat = format;
|
||||
keepOffset = offset;
|
||||
}
|
||||
else if (format == 12 && encodingID == EncodingIDUCS4) {
|
||||
keepFormat = format;
|
||||
keepOffset = offset;
|
||||
break; // we don't want to try anything else when this format is available.
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (keepFormat == 12)
|
||||
rv = ReadCMAPTableFormat12(buf + keepOffset, len - keepOffset, aFontEntry);
|
||||
else if (keepFormat == 4)
|
||||
rv = ReadCMAPTableFormat4(buf + keepOffset, len - keepOffset, aFontEntry);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PLDHashOperator PR_CALLBACK
|
||||
gfxWindowsPlatform::FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg)
|
||||
{
|
||||
if (aFontEntry->IsCrappyFont())
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
HDC hdc = GetDC(nsnull);
|
||||
|
||||
LOGFONTW logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
PRUint32 l = PR_MIN(aFontEntry->mName.Length(), LF_FACESIZE - 1);
|
||||
memcpy(logFont.lfFaceName,
|
||||
nsPromiseFlatString(aFontEntry->mName).get(),
|
||||
l * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[l] = 0;
|
||||
|
||||
HFONT font = CreateFontIndirectW(&logFont);
|
||||
|
||||
if (font) {
|
||||
HFONT oldFont = (HFONT)SelectObject(hdc, font);
|
||||
|
||||
nsresult rv = ReadCMAP(hdc, aFontEntry);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
aFontEntry->mUnicodeFont = PR_FALSE;
|
||||
|
||||
SelectObject(hdc, oldFont);
|
||||
DeleteObject(font);
|
||||
}
|
||||
|
||||
ReleaseDC(nsnull, hdc);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
||||
struct FontListData {
|
||||
FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsStringArray& aListOfFonts) :
|
||||
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
|
||||
@ -437,17 +207,17 @@ gfxWindowsPlatform::UpdateFontList()
|
||||
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)this, 0);
|
||||
::ReleaseDC(nsnull, dc);
|
||||
|
||||
// Update all the fonts cmaps
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FontGetCMapDataProc, nsnull);
|
||||
|
||||
// Create the list of FontSubstitutes
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
nsCOMPtr<nsIWindowsRegKey> regKey =
|
||||
do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
||||
if (!regKey)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_NAMED_LITERAL_STRING(kFontSubstitutesKey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
|
||||
NS_NAMED_LITERAL_STRING(kFontSubstitutesKey,
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
|
||||
|
||||
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
|
||||
kFontSubstitutesKey, nsIWindowsRegKey::ACCESS_READ);
|
||||
nsresult rv =
|
||||
regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
|
||||
kFontSubstitutesKey, nsIWindowsRegKey::ACCESS_READ);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -581,86 +351,155 @@ gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
// XXX If the font has font link, we should add the linked font.
|
||||
}
|
||||
|
||||
struct FontMatch {
|
||||
FontMatch() : rank(0) {}
|
||||
PRBool operator <(const FontMatch& other) const { return (rank < other.rank); }
|
||||
PRBool operator >(const FontMatch& other) const { return (rank > other.rank); }
|
||||
PRBool operator ==(const FontMatch& other) const { return (rank == other.rank); }
|
||||
nsRefPtr<FontEntry> fontEntry;
|
||||
PRInt8 rank;
|
||||
};
|
||||
|
||||
struct FontSearch {
|
||||
FontSearch(const PRUnichar *aString, PRUint32 aLength, gfxWindowsFont *aFont) :
|
||||
string(aString), length(aLength), fontToMatch(aFont), matchRank(0) {
|
||||
FontSearch(PRUnichar aCh, PRUint8 aRange, const char *aLangGroup, const char *aFamily) :
|
||||
ch(aCh), langGroup(aLangGroup), family(aFamily), range(aRange), highestRank(0), fontMatches(25) {
|
||||
}
|
||||
const PRUnichar *string;
|
||||
const PRUint32 length;
|
||||
nsRefPtr<gfxWindowsFont> fontToMatch;
|
||||
PRInt32 matchRank;
|
||||
nsRefPtr<FontEntry> bestMatch;
|
||||
PRBool RankIsOK(PRUint32 rank) {
|
||||
return (rank >= (highestRank / 2) + 1);
|
||||
}
|
||||
const PRUint32 ch;
|
||||
const char *langGroup;
|
||||
const char *family;
|
||||
const PRUint8 range;
|
||||
PRInt8 highestRank;
|
||||
nsTArray<FontMatch> fontMatches;
|
||||
};
|
||||
|
||||
PLDHashOperator PR_CALLBACK
|
||||
gfxWindowsPlatform::FindFontForStringProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg)
|
||||
gfxWindowsPlatform::FindFontForChar(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontEntry>& aFontEntry,
|
||||
void* userArg)
|
||||
{
|
||||
// bitmap fonts suck
|
||||
if (aFontEntry->IsCrappyFont())
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
FontSearch *data = (FontSearch*)userArg;
|
||||
FontMatch fm;
|
||||
if (aFontEntry->SupportsRange(data->range))
|
||||
fm.rank += 20;
|
||||
|
||||
PRInt32 rank = 0;
|
||||
if (aFontEntry->SupportsLangGroup(nsDependentCString(data->langGroup)))
|
||||
fm.rank += 10;
|
||||
|
||||
for (PRUint32 i = 0; i < data->length; ++i) {
|
||||
PRUint32 ch = data->string[i];
|
||||
if (data->family && aFontEntry->MatchesGenericFamily(nsDependentCString(data->family)))
|
||||
fm.rank += 5;
|
||||
|
||||
if ((i+1 < data->length) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(data->string[i+1])) {
|
||||
i++;
|
||||
ch = SURROGATE_TO_UCS4(ch, data->string[i]);
|
||||
}
|
||||
// XXX this code doesn't really work like I would hope
|
||||
// we really just want to avoid non-unicode fonts.. i.e. wingdings, etc
|
||||
// find something better to replace it with
|
||||
/* rank symbol fonts lower than other stuff -- this might be a bad idea, but should
|
||||
* avoid things like wingdings showing up while rendering hindi scripts
|
||||
*/
|
||||
// if (aFontEntry->SupportsLangGroup(NS_LITERAL_CSTRING("x-symbol")))
|
||||
// fm.rank -= 5;
|
||||
|
||||
if (aFontEntry->mCharacterMap.test(ch)) {
|
||||
rank += 20;
|
||||
/* This will allow us to cut out some of the fonts, but not all
|
||||
* since some might get in early before we find the real highest rank.
|
||||
*/
|
||||
if (fm.rank > data->highestRank)
|
||||
data->highestRank = fm.rank;
|
||||
|
||||
// fonts that claim to support the range are more
|
||||
// likely to be "better fonts" than ones that don't... (in theory)
|
||||
if (aFontEntry->SupportsRange(CharRangeBit(ch)))
|
||||
rank += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't match any characters don't bother wasting more time.
|
||||
if (rank == 0)
|
||||
if (!data->RankIsOK(fm.rank))
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
|
||||
if (aFontEntry->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
|
||||
rank += 10;
|
||||
|
||||
if (data->fontToMatch->GetFontEntry()->mFamily == aFontEntry->mFamily)
|
||||
rank += 5;
|
||||
if (data->fontToMatch->GetFontEntry()->mFamily == aFontEntry->mPitch)
|
||||
rank += 5;
|
||||
|
||||
/* weight */
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
PRUint16 targetWeight = (baseWeight * 100) + (weightDistance * 100);
|
||||
if (targetWeight == aFontEntry->mDefaultWeight)
|
||||
rank += 5;
|
||||
|
||||
if (data->matchRank == 0 || rank > data->matchRank) {
|
||||
data->bestMatch = aFontEntry;
|
||||
data->matchRank = rank;
|
||||
if (fm.rank > 0) {
|
||||
fm.fontEntry = aFontEntry;
|
||||
data->fontMatches.AppendElement(fm);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
||||
FontEntry *
|
||||
gfxWindowsPlatform::FindFontForString(const PRUnichar *aString, PRUint32 aLength, gfxWindowsFont *aFont)
|
||||
void
|
||||
gfxWindowsPlatform::FindOtherFonts(const PRUnichar* aString, PRUint32 aLength, const char *aLangGroup, const char *aGeneric, nsString& fonts)
|
||||
{
|
||||
FontSearch data(aString, aLength, aFont);
|
||||
fonts.Truncate();
|
||||
|
||||
// find fonts that support the character
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FindFontForStringProc, &data);
|
||||
PRBool surrogates = PR_FALSE;
|
||||
|
||||
return data.bestMatch;
|
||||
std::bitset<128> ranges(0);
|
||||
|
||||
for (PRUint32 z = 0; z < aLength; ++z) {
|
||||
PRUint32 ch = aString[z];
|
||||
|
||||
if ((z+1 < aLength) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(aString[z+1])) {
|
||||
z++;
|
||||
ch = SURROGATE_TO_UCS4(ch, aString[z]);
|
||||
surrogates = PR_TRUE;
|
||||
}
|
||||
|
||||
PRUint8 range = CharRangeBit(ch);
|
||||
if (range != NO_RANGE_FOUND && !ranges[range]) {
|
||||
FontSearch data(ch, CharRangeBit(ch), aLangGroup, aGeneric);
|
||||
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FindFontForChar, &data);
|
||||
|
||||
data.fontMatches.Sort();
|
||||
|
||||
PRUint32 nmatches = data.fontMatches.Length();
|
||||
if (nmatches > 0) {
|
||||
//printf("%d matches for 0x%04x\n", nmatches, ch);
|
||||
for (PRUint32 i = nmatches - 1; i > 0; i--) {
|
||||
const FontMatch& fm = data.fontMatches[i];
|
||||
if (data.RankIsOK(fm.rank)) {
|
||||
if (!fonts.IsEmpty())
|
||||
fonts.AppendLiteral(", ");
|
||||
fonts.Append(fm.fontEntry->mName);
|
||||
}
|
||||
}
|
||||
}
|
||||
ranges[range] = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (surrogates) {
|
||||
// append fonts that support surrogates on to the list
|
||||
FontSearch data(0xd801, 57, aLangGroup, aGeneric);
|
||||
|
||||
mFonts.Enumerate(gfxWindowsPlatform::FindFontForChar, &data);
|
||||
|
||||
data.fontMatches.Sort();
|
||||
|
||||
PRUint32 nmatches = data.fontMatches.Length();
|
||||
if (nmatches > 0) {
|
||||
for (PRUint32 i = nmatches - 1; i > 0; i--) {
|
||||
const FontMatch& fm = data.fontMatches[i];
|
||||
if (data.RankIsOK(fm.rank)) {
|
||||
if (!fonts.IsEmpty())
|
||||
fonts.AppendLiteral(", ");
|
||||
fonts.Append(fm.fontEntry->mName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WeightTable *
|
||||
gfxWindowsPlatform::GetFontWeightTable(const nsAString& aName)
|
||||
{
|
||||
nsRefPtr<WeightTable> wt;
|
||||
if (!mFontWeights.Get(aName, &wt)) {
|
||||
return nsnull;
|
||||
}
|
||||
return wt;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::PutFontWeightTable(const nsAString& aName, WeightTable *aWeightTable)
|
||||
{
|
||||
mFontWeights.Put(aName, aWeightTable);
|
||||
}
|
||||
|
||||
gfxFontGroup *
|
||||
@ -669,18 +508,3 @@ gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
||||
{
|
||||
return new gfxWindowsFontGroup(aFamilies, aStyle);
|
||||
}
|
||||
|
||||
FontEntry *
|
||||
gfxWindowsPlatform::FindFontEntry(const nsAString& aName)
|
||||
{
|
||||
nsString name(aName);
|
||||
ToLowerCase(name);
|
||||
|
||||
nsRefPtr<FontEntry> fe;
|
||||
if (!mFonts.Get(name, &fe) &&
|
||||
!mFontSubstitutes.Get(name, &fe) &&
|
||||
!mFontAliases.Get(name, &fe)) {
|
||||
return nsnull;
|
||||
}
|
||||
return fe.get();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user