mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
b=514968; optimize FT2 textrun creation with glyph cache; r=jfkthame
This commit is contained in:
parent
141bc1831c
commit
718840c3e2
@ -127,7 +127,46 @@ public: // new functions
|
|||||||
static already_AddRefed<gfxFT2Font>
|
static already_AddRefed<gfxFT2Font>
|
||||||
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle);
|
GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle);
|
||||||
|
|
||||||
private:
|
struct CachedGlyphData {
|
||||||
|
CachedGlyphData()
|
||||||
|
: glyphIndex(0xffffffffU) { }
|
||||||
|
|
||||||
|
CachedGlyphData(PRUint32 gid)
|
||||||
|
: glyphIndex(gid) { }
|
||||||
|
|
||||||
|
PRUint32 glyphIndex;
|
||||||
|
PRInt32 lsbDelta;
|
||||||
|
PRInt32 rsbDelta;
|
||||||
|
PRInt32 xAdvance;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CachedGlyphData* GetGlyphDataForChar(PRUint32 ch) {
|
||||||
|
CharGlyphMapEntryType *entry = mCharGlyphCache.PutEntry(ch);
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
if (entry->mData.glyphIndex == 0xffffffffU) {
|
||||||
|
// this is a new entry, fill it
|
||||||
|
FillGlyphDataForChar(ch, &entry->mData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &entry->mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FaceLock {
|
||||||
|
public:
|
||||||
|
FaceLock(gfxFT2Font *font);
|
||||||
|
~FaceLock();
|
||||||
|
|
||||||
|
FT_Face Face() { return mFace; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cairo_scaled_font_t *mScaledFont;
|
||||||
|
FT_Face mFace;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
cairo_scaled_font_t *mScaledFont;
|
cairo_scaled_font_t *mScaledFont;
|
||||||
|
|
||||||
PRBool mHasSpaceGlyph;
|
PRBool mHasSpaceGlyph;
|
||||||
@ -135,6 +174,12 @@ private:
|
|||||||
PRBool mHasMetrics;
|
PRBool mHasMetrics;
|
||||||
Metrics mMetrics;
|
Metrics mMetrics;
|
||||||
gfxFloat mAdjustedSize;
|
gfxFloat mAdjustedSize;
|
||||||
|
|
||||||
|
void FillGlyphDataForChar(PRUint32 ch, CachedGlyphData *gd);
|
||||||
|
|
||||||
|
typedef nsBaseHashtableET<nsUint32HashKey, CachedGlyphData> CharGlyphMapEntryType;
|
||||||
|
typedef nsTHashtable<CharGlyphMapEntryType> CharGlyphMap;
|
||||||
|
CharGlyphMap mCharGlyphCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
class THEBES_API gfxFT2FontGroup : public gfxFontGroup {
|
class THEBES_API gfxFT2FontGroup : public gfxFontGroup {
|
||||||
|
@ -81,6 +81,14 @@ static const char *sCJKLangGroup[] = {
|
|||||||
#define CJK_LANG_ZH_HK sCJKLangGroup[3]
|
#define CJK_LANG_ZH_HK sCJKLangGroup[3]
|
||||||
#define CJK_LANG_ZH_TW sCJKLangGroup[4]
|
#define CJK_LANG_ZH_TW sCJKLangGroup[4]
|
||||||
|
|
||||||
|
// rounding and truncation functions for a Freetype floating point number
|
||||||
|
// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
|
||||||
|
// part and low 6 bits for the fractional part.
|
||||||
|
#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
|
||||||
|
#define MOZ_FT_TRUNC(x) ((x) >> 6)
|
||||||
|
#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
|
||||||
|
MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FontEntry
|
* FontEntry
|
||||||
*/
|
*/
|
||||||
@ -107,15 +115,15 @@ FontEntry::~FontEntry()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
FontEntry*
|
FontEntry*
|
||||||
FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
|
||||||
nsISupports *aLoader, const PRUint8 *aFontData,
|
nsISupports *aLoader, const PRUint8 *aFontData,
|
||||||
PRUint32 aLength) {
|
PRUint32 aLength) {
|
||||||
if (!gfxFontUtils::ValidateSFNTHeaders(aFontData, aLength))
|
if (!gfxFontUtils::ValidateSFNTHeaders(aFontData, aLength))
|
||||||
return nsnull;
|
return nsnull;
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
FT_Error error =
|
FT_Error error =
|
||||||
FT_New_Memory_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(),
|
FT_New_Memory_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(),
|
||||||
aFontData, aLength, 0, &face);
|
aFontData, aLength, 0, &face);
|
||||||
if (error != FT_Err_Ok)
|
if (error != FT_Err_Ok)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
@ -134,7 +142,7 @@ FTFontDestroyFunc(void *data)
|
|||||||
FT_Done_Face(face);
|
FT_Done_Face(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ FontEntry*
|
/* static */ FontEntry*
|
||||||
FontEntry::CreateFontEntryFromFace(FT_Face aFace) {
|
FontEntry::CreateFontEntryFromFace(FT_Face aFace) {
|
||||||
static cairo_user_data_key_t key;
|
static cairo_user_data_key_t key;
|
||||||
|
|
||||||
@ -322,7 +330,7 @@ gfxFT2FontGroup::gfxFT2FontGroup(const nsAString& families,
|
|||||||
#elif defined(XP_WIN)
|
#elif defined(XP_WIN)
|
||||||
HGDIOBJ hGDI = ::GetStockObject(SYSTEM_FONT);
|
HGDIOBJ hGDI = ::GetStockObject(SYSTEM_FONT);
|
||||||
LOGFONTW logFont;
|
LOGFONTW logFont;
|
||||||
if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont))
|
if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont))
|
||||||
familyArray.AppendElement(nsDependentString(logFont.lfFaceName));
|
familyArray.AppendElement(nsDependentString(logFont.lfFaceName));
|
||||||
#else
|
#else
|
||||||
#error "Platform not supported"
|
#error "Platform not supported"
|
||||||
@ -441,10 +449,10 @@ AddFontNameToArray(const nsAString& aName,
|
|||||||
if (list->IndexOf(aName) == list->NoIndex)
|
if (list->IndexOf(aName) == list->NoIndex)
|
||||||
list->AppendElement(aName);
|
list->AppendElement(aName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
gfxFT2FontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
||||||
const nsCString& aLangGroup,
|
const nsCString& aLangGroup,
|
||||||
@ -598,7 +606,7 @@ gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<nsRefPtr<FontEntry> >& aFo
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<gfxFont>
|
already_AddRefed<gfxFont>
|
||||||
gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
||||||
{
|
{
|
||||||
if (aCh > 0xFFFF)
|
if (aCh > 0xFFFF)
|
||||||
@ -617,8 +625,9 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
|||||||
|
|
||||||
/* special case CJK */
|
/* special case CJK */
|
||||||
if (unicodeRange == kRangeSetCJK) {
|
if (unicodeRange == kRangeSetCJK) {
|
||||||
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
|
if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) {
|
||||||
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
|
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
|
nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
|
||||||
GetCJKPrefFonts(fonts);
|
GetCJKPrefFonts(fonts);
|
||||||
@ -643,7 +652,7 @@ gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<gfxFont>
|
already_AddRefed<gfxFont>
|
||||||
gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
|
gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
|
||||||
{
|
{
|
||||||
nsRefPtr<gfxFont> selectedFont;
|
nsRefPtr<gfxFont> selectedFont;
|
||||||
@ -667,7 +676,7 @@ void gfxFT2FontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun)
|
|||||||
AddRange(aTextRun, font, mString.get(), offset, rangeLength);
|
AddRange(aTextRun, font, mString.get(), offset, rangeLength);
|
||||||
offset += rangeLength;
|
offset += rangeLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -675,10 +684,15 @@ gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnicha
|
|||||||
{
|
{
|
||||||
const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
|
const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
|
||||||
// we'll pass this in/figure it out dynamically, but at this point there can be only one face.
|
// we'll pass this in/figure it out dynamically, but at this point there can be only one face.
|
||||||
FT_Face face = cairo_ft_scaled_font_lock_face(font->CairoScaledFont());
|
gfxFT2Font::FaceLock faceLock(font);
|
||||||
|
FT_Face face = faceLock.Face();
|
||||||
|
|
||||||
gfxTextRun::CompressedGlyph g;
|
gfxTextRun::CompressedGlyph g;
|
||||||
|
|
||||||
|
const gfxFT2Font::CachedGlyphData *cgd = nsnull, *cgdNext = nsnull;
|
||||||
|
|
||||||
|
FT_UInt spaceGlyph = font->GetSpaceGlyph();
|
||||||
|
|
||||||
aTextRun->AddGlyphRun(font, offset);
|
aTextRun->AddGlyphRun(font, offset);
|
||||||
for (PRUint32 i = 0; i < len; i++) {
|
for (PRUint32 i = 0; i < len; i++) {
|
||||||
PRUint32 ch = str[offset + i];
|
PRUint32 ch = str[offset + i];
|
||||||
@ -690,12 +704,18 @@ gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnicha
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected");
|
NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected");
|
||||||
FT_UInt gid = FT_Get_Char_Index(face, ch); // find the glyph id
|
|
||||||
|
if (cgdNext) {
|
||||||
|
cgd = cgdNext;
|
||||||
|
cgdNext = nsnull;
|
||||||
|
} else {
|
||||||
|
cgd = font->GetGlyphDataForChar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_UInt gid = cgd->glyphIndex;
|
||||||
PRInt32 advance = 0;
|
PRInt32 advance = 0;
|
||||||
|
|
||||||
if (gid == font->GetSpaceGlyph()) {
|
if (gid == 0) {
|
||||||
advance = (int)(font->GetMetrics().spaceWidth * appUnitsPerDevUnit);
|
|
||||||
} else if (gid == 0) {
|
|
||||||
advance = -1; // trigger the missing glyphs case below
|
advance = -1; // trigger the missing glyphs case below
|
||||||
} else {
|
} else {
|
||||||
// find next character and its glyph -- in case they exist
|
// find next character and its glyph -- in case they exist
|
||||||
@ -707,32 +727,29 @@ gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnicha
|
|||||||
if (FT_HAS_KERNING(face) && i + 1 < len) {
|
if (FT_HAS_KERNING(face) && i + 1 < len) {
|
||||||
chNext = str[offset + i + 1];
|
chNext = str[offset + i + 1];
|
||||||
if (chNext != 0) {
|
if (chNext != 0) {
|
||||||
gidNext = FT_Get_Char_Index(face, chNext);
|
cgdNext = font->GetGlyphDataForChar(chNext);
|
||||||
if (gidNext && gidNext != font->GetSpaceGlyph()) {
|
gidNext = cgdNext->glyphIndex;
|
||||||
FT_Load_Glyph(face, gidNext, FT_LOAD_DEFAULT);
|
if (gidNext && gidNext != spaceGlyph)
|
||||||
lsbDeltaNext = face->glyph->lsb_delta;
|
lsbDeltaNext = cgdNext->lsbDelta;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now load the current glyph
|
advance = cgd->xAdvance;
|
||||||
FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load glyph into the slot
|
|
||||||
advance = face->glyph->advance.x;
|
|
||||||
|
|
||||||
// now add kerning to the current glyph's advance
|
// now add kerning to the current glyph's advance
|
||||||
if (chNext && gidNext) {
|
if (chNext && gidNext) {
|
||||||
FT_Vector kerning; kerning.x = 0;
|
FT_Vector kerning; kerning.x = 0;
|
||||||
FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning);
|
FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning);
|
||||||
advance += kerning.x;
|
advance += kerning.x;
|
||||||
if (face->glyph->rsb_delta - lsbDeltaNext >= 32) {
|
if (cgd->rsbDelta - lsbDeltaNext >= 32) {
|
||||||
advance -= 64;
|
advance -= 64;
|
||||||
} else if (face->glyph->rsb_delta - lsbDeltaNext < -32) {
|
} else if (cgd->rsbDelta - lsbDeltaNext < -32) {
|
||||||
advance += 64;
|
advance += 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now apply unit conversion and scaling
|
// now apply unit conversion and scaling
|
||||||
advance = (advance >> 6) * appUnitsPerDevUnit;
|
advance = MOZ_FT_TRUNC(advance) * appUnitsPerDevUnit;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_thebes_2
|
#ifdef DEBUG_thebes_2
|
||||||
printf(" gid=%d, advance=%d (%s)\n", gid, advance,
|
printf(" gid=%d, advance=%d (%s)\n", gid, advance,
|
||||||
@ -757,8 +774,20 @@ gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnicha
|
|||||||
aTextRun->SetGlyphs(offset + i, g, &details);
|
aTextRun->SetGlyphs(offset + i, g, &details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cairo_ft_scaled_font_unlock_face(font->CairoScaledFont());
|
/*
|
||||||
|
* Stack-based face lock helper
|
||||||
|
*/
|
||||||
|
gfxFT2Font::FaceLock::FaceLock(gfxFT2Font *font)
|
||||||
|
{
|
||||||
|
mScaledFont = font->CairoScaledFont();
|
||||||
|
mFace = cairo_ft_scaled_font_lock_face(mScaledFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxFT2Font::FaceLock::~FaceLock()
|
||||||
|
{
|
||||||
|
cairo_ft_scaled_font_unlock_face(mScaledFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -767,14 +796,16 @@ gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnicha
|
|||||||
gfxFT2Font::gfxFT2Font(FontEntry *aFontEntry,
|
gfxFT2Font::gfxFT2Font(FontEntry *aFontEntry,
|
||||||
const gfxFontStyle *aFontStyle)
|
const gfxFontStyle *aFontStyle)
|
||||||
: gfxFont(aFontEntry, aFontStyle),
|
: gfxFont(aFontEntry, aFontStyle),
|
||||||
mScaledFont(nsnull),
|
mScaledFont(nsnull),
|
||||||
mHasSpaceGlyph(PR_FALSE),
|
mHasSpaceGlyph(PR_FALSE),
|
||||||
mSpaceGlyph(0),
|
mSpaceGlyph(0),
|
||||||
mHasMetrics(PR_FALSE),
|
mHasMetrics(PR_FALSE),
|
||||||
mAdjustedSize(0)
|
mAdjustedSize(0)
|
||||||
{
|
{
|
||||||
mFontEntry = aFontEntry;
|
mFontEntry = aFontEntry;
|
||||||
NS_ASSERTION(mFontEntry, "Unable to find font entry for font. Something is whack.");
|
NS_ASSERTION(mFontEntry, "Unable to find font entry for font. Something is whack.");
|
||||||
|
|
||||||
|
mCharGlyphCache.Init(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxFT2Font::~gfxFT2Font()
|
gfxFT2Font::~gfxFT2Font()
|
||||||
@ -785,14 +816,6 @@ gfxFT2Font::~gfxFT2Font()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rounding and truncation functions for a Freetype floating point number
|
|
||||||
// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
|
|
||||||
// part and low 6 bits for the fractional part.
|
|
||||||
#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
|
|
||||||
#define MOZ_FT_TRUNC(x) ((x) >> 6)
|
|
||||||
#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
|
|
||||||
MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
|
|
||||||
|
|
||||||
const gfxFont::Metrics&
|
const gfxFont::Metrics&
|
||||||
gfxFT2Font::GetMetrics()
|
gfxFT2Font::GetMetrics()
|
||||||
{
|
{
|
||||||
@ -801,7 +824,8 @@ gfxFT2Font::GetMetrics()
|
|||||||
|
|
||||||
mMetrics.emHeight = GetStyle()->size;
|
mMetrics.emHeight = GetStyle()->size;
|
||||||
|
|
||||||
FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
|
gfxFT2Font::FaceLock faceLock(this);
|
||||||
|
FT_Face face = faceLock.Face();
|
||||||
|
|
||||||
if (!face) {
|
if (!face) {
|
||||||
// Abort here already, otherwise we crash in the following
|
// Abort here already, otherwise we crash in the following
|
||||||
@ -818,18 +842,9 @@ gfxFT2Font::GetMetrics()
|
|||||||
const double xScale = face->size->metrics.x_ppem / emUnit;
|
const double xScale = face->size->metrics.x_ppem / emUnit;
|
||||||
const double yScale = face->size->metrics.y_ppem / emUnit;
|
const double yScale = face->size->metrics.y_ppem / emUnit;
|
||||||
|
|
||||||
// properties of space
|
// cache properties of space
|
||||||
gid = FT_Get_Char_Index(face, ' ');
|
GetSpaceGlyph();
|
||||||
if (gid) {
|
|
||||||
FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
|
|
||||||
// face->glyph->metrics.width doesn't work for spaces, use advance.x instead
|
|
||||||
mMetrics.spaceWidth = face->glyph->advance.x >> 6;
|
|
||||||
// save the space glyph
|
|
||||||
mSpaceGlyph = gid;
|
|
||||||
} else {
|
|
||||||
NS_ERROR("blah");
|
|
||||||
}
|
|
||||||
|
|
||||||
// properties of 'x', also use its width as average width
|
// properties of 'x', also use its width as average width
|
||||||
gid = FT_Get_Char_Index(face, 'x'); // select the glyph
|
gid = FT_Get_Char_Index(face, 'x'); // select the glyph
|
||||||
if (gid) {
|
if (gid) {
|
||||||
@ -916,7 +931,6 @@ gfxFT2Font::GetMetrics()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// XXX mMetrics.height needs to be set.
|
// XXX mMetrics.height needs to be set.
|
||||||
cairo_ft_scaled_font_unlock_face(CairoScaledFont());
|
|
||||||
|
|
||||||
mHasMetrics = PR_TRUE;
|
mHasMetrics = PR_TRUE;
|
||||||
return mMetrics;
|
return mMetrics;
|
||||||
@ -932,19 +946,18 @@ gfxFT2Font::GetUniqueName()
|
|||||||
PRUint32
|
PRUint32
|
||||||
gfxFT2Font::GetSpaceGlyph()
|
gfxFT2Font::GetSpaceGlyph()
|
||||||
{
|
{
|
||||||
NS_ASSERTION (GetStyle ()->size != 0,
|
NS_ASSERTION (GetStyle()->size != 0, "forgot to short-circuit a text run with zero-sized font?");
|
||||||
"forgot to short-circuit a text run with zero-sized font?");
|
|
||||||
|
|
||||||
if(!mHasSpaceGlyph)
|
if (!mHasSpaceGlyph) {
|
||||||
{
|
const CachedGlyphData *gdata = GetGlyphDataForChar(' ');
|
||||||
FT_UInt gid = 0; // glyph ID
|
|
||||||
FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
|
mSpaceGlyph = gdata->glyphIndex;
|
||||||
gid = FT_Get_Char_Index(face, ' ');
|
NS_ASSERTION(mSpaceGlyph != 0, "Font has no space glyph!");
|
||||||
FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
|
|
||||||
mSpaceGlyph = gid;
|
mMetrics.spaceWidth = MOZ_FT_TRUNC(gdata->xAdvance);
|
||||||
mHasSpaceGlyph = PR_TRUE;
|
mHasSpaceGlyph = PR_TRUE;
|
||||||
cairo_ft_scaled_font_unlock_face(CairoScaledFont());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mSpaceGlyph;
|
return mSpaceGlyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,7 +1036,7 @@ gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
|
|||||||
{
|
{
|
||||||
FontEntry *fe = gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle);
|
FontEntry *fe = gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle);
|
||||||
if (!fe) {
|
if (!fe) {
|
||||||
printf("Failed to find font entry for %s\n", NS_ConvertUTF16toUTF8(aName).get());
|
NS_WARNING("Failed to find font entry for font!");
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1046,3 +1059,33 @@ gfxFT2Font::GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
|
|||||||
return static_cast<gfxFT2Font *>(f);
|
return static_cast<gfxFT2Font *>(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxFT2Font::FillGlyphDataForChar(PRUint32 ch, CachedGlyphData *gd)
|
||||||
|
{
|
||||||
|
gfxFT2Font::FaceLock faceLock(this);
|
||||||
|
FT_Face face = faceLock.Face();
|
||||||
|
|
||||||
|
FT_UInt gid = FT_Get_Char_Index(face, ch);
|
||||||
|
|
||||||
|
if (gid == 0) {
|
||||||
|
// this font doesn't support this char!
|
||||||
|
NS_ASSERTION(gid != 0, "We don't have a glyph, but font indicated that it supported this char in tables?");
|
||||||
|
gd->glyphIndex = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Error err = FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
// hmm, this is weird, we failed to load a glyph that we had?
|
||||||
|
NS_WARNING("Failed to load glyph that we got from Get_Char_index");
|
||||||
|
|
||||||
|
gd->glyphIndex = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gd->glyphIndex = gid;
|
||||||
|
gd->lsbDelta = face->glyph->lsb_delta;
|
||||||
|
gd->rsbDelta = face->glyph->rsb_delta;
|
||||||
|
gd->xAdvance = face->glyph->advance.x;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user