mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 04:58:00 +00:00
Bug 357637 Loading time (Tp) of pages with Chinese text is unbearable r=stuart
This commit is contained in:
parent
8ef6d01e4d
commit
6f373b9474
@ -137,6 +137,8 @@ private:
|
||||
nsTArray<PRInt32> mUTF8Spacing;
|
||||
};
|
||||
|
||||
struct TextSegment;
|
||||
|
||||
class THEBES_API gfxPangoTextRun : public gfxTextRun {
|
||||
public:
|
||||
gfxPangoTextRun(const nsAString& aString, gfxPangoFontGroup *aFontGroup);
|
||||
@ -149,7 +151,8 @@ public:
|
||||
virtual const nsTArray<gfxFloat> *const GetSpacing() const;
|
||||
|
||||
private:
|
||||
nsString mString;
|
||||
nsString mString;
|
||||
nsCString mUTF8String;
|
||||
|
||||
gfxPangoFontGroup *mGroup;
|
||||
|
||||
@ -158,14 +161,15 @@ private:
|
||||
|
||||
int MeasureOrDraw(gfxContext *aContext, PRBool aDraw, gfxPoint aPt);
|
||||
int MeasureOrDrawFast(gfxContext *aContext, PRBool aDraw,
|
||||
gfxPoint aPt, nsAFlatCString &aUTF8Str,
|
||||
PRBool aIsRTL, gfxPangoFont *aFont);
|
||||
gfxPoint aPt, PRBool aIsRTL, gfxPangoFont *aFont);
|
||||
int MeasureOrDrawItemizing(gfxContext *aContext, PRBool aDraw,
|
||||
gfxPoint aPt, nsAFlatCString &aUTF8Str,
|
||||
PRBool aIsRTL, gfxPangoFont *aFont);
|
||||
gfxPoint aPt, PRBool aIsRTL,
|
||||
gfxPangoFont *aFont);
|
||||
int DrawFromCache(gfxContext *aContext, gfxPoint aPt);
|
||||
|
||||
nsTArray<gfxFloat> mSpacing;
|
||||
nsTArray<PRInt32> mUTF8Spacing;
|
||||
nsTArray<gfxFloat> mSpacing;
|
||||
nsTArray<PRInt32> mUTF8Spacing;
|
||||
nsTArray<TextSegment> mSegments;
|
||||
};
|
||||
|
||||
#endif /* GFX_PANGOFONTS_H */
|
||||
|
@ -838,13 +838,27 @@ DrawCairoGlyphs(gfxContext* ctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
struct TextSegment {
|
||||
nsRefPtr<gfxPangoFont> mFont;
|
||||
PRUint32 mOffset;
|
||||
PRUint32 mLength;
|
||||
int mWidth;
|
||||
PangoGlyphString *mGlyphString;
|
||||
};
|
||||
|
||||
gfxPangoTextRun::gfxPangoTextRun(const nsAString& aString, gfxPangoFontGroup *aGroup)
|
||||
: mString(aString), mGroup(aGroup), mWidth(-1)
|
||||
{
|
||||
mUTF8String = NS_ConvertUTF16toUTF8(aString);
|
||||
}
|
||||
|
||||
gfxPangoTextRun::~gfxPangoTextRun()
|
||||
{
|
||||
for (PRUint32 i = 0; i < mSegments.Length(); ++i) {
|
||||
if (mSegments[i].mGlyphString)
|
||||
pango_glyph_string_free(mSegments[i].mGlyphString);
|
||||
}
|
||||
mSegments.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
@ -871,7 +885,6 @@ gfxPangoTextRun::MeasureOrDraw(gfxContext *aContext,
|
||||
{
|
||||
gfxMatrix mat;
|
||||
nsRefPtr<gfxPangoFont> pf = mGroup->GetFontAt(0);
|
||||
NS_ConvertUTF16toUTF8 u8str(mString);
|
||||
PRBool isRTL = IsRightToLeft();
|
||||
pango_context_set_base_dir(pf->GetPangoContext(),
|
||||
isRTL ? PANGO_DIRECTION_RTL :
|
||||
@ -896,13 +909,17 @@ gfxPangoTextRun::MeasureOrDraw(gfxContext *aContext,
|
||||
|
||||
int result;
|
||||
|
||||
if (mSegments.IsEmpty()) {
|
||||
#ifdef DISABLE_PANGO_FAST
|
||||
result = MeasureOrDrawItemizing(aContext, aDraw, aPt, u8str, isRTL, pf);
|
||||
result = MeasureOrDrawItemizing(aContext, aDraw, aPt, isRTL, pf);
|
||||
#else
|
||||
result = MeasureOrDrawFast(aContext, aDraw, aPt, u8str, isRTL, pf);
|
||||
if (result < 0)
|
||||
result = MeasureOrDrawItemizing(aContext, aDraw, aPt, u8str, isRTL, pf);
|
||||
result = MeasureOrDrawFast(aContext, aDraw, aPt, isRTL, pf);
|
||||
if (result < 0)
|
||||
result = MeasureOrDrawItemizing(aContext, aDraw, aPt, isRTL, pf);
|
||||
#endif
|
||||
} else {
|
||||
result = DrawFromCache(aContext, aPt);
|
||||
}
|
||||
|
||||
if (aDraw)
|
||||
aContext->SetMatrix(mat);
|
||||
@ -910,13 +927,37 @@ gfxPangoTextRun::MeasureOrDraw(gfxContext *aContext,
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
gfxPangoTextRun::DrawFromCache(gfxContext *aContext, gfxPoint aPt)
|
||||
{
|
||||
int result = 0;
|
||||
int drawingOffset = 0;
|
||||
for (PRUint32 i = 0; i < mSegments.Length(); i++) {
|
||||
PangoGlyphString *glyphString = mSegments[i].mGlyphString;
|
||||
if (glyphString->num_glyphs > 0) {
|
||||
#ifndef THEBES_USE_PANGO_CAIRO
|
||||
DrawCairoGlyphs(aContext, mSegments[i].mFont->GetPangoFont(),
|
||||
gfxPoint(drawingOffset/FLOAT_PANGO_SCALE, 0.0),
|
||||
glyphString);
|
||||
#else
|
||||
aContext->MoveTo(aPt); // XXX Do we need?
|
||||
pango_cairo_show_glyph_string(aContext->GetCairo(),
|
||||
mSegments[i].mFont->GetPangoFont(),
|
||||
glyphString);
|
||||
#endif
|
||||
drawingOffset += mSegments[i].mWidth;
|
||||
}
|
||||
result += mSegments[i].mWidth;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define IS_MISSING_GLYPH(g) (((g) & 0x10000000) || (g) == 0x0FFFFFFF)
|
||||
|
||||
int
|
||||
gfxPangoTextRun::MeasureOrDrawFast(gfxContext *aContext,
|
||||
PRBool aDraw,
|
||||
gfxPoint aPt,
|
||||
nsAFlatCString &aUTF8Str,
|
||||
PRBool aIsRTL,
|
||||
gfxPangoFont *aFont)
|
||||
{
|
||||
@ -964,7 +1005,8 @@ gfxPangoTextRun::MeasureOrDrawFast(gfxContext *aContext,
|
||||
ch);
|
||||
|
||||
PangoGlyphString* glyphString = pango_glyph_string_new();
|
||||
pango_shape(aUTF8Str.get(), aUTF8Str.Length(), &analysis, glyphString);
|
||||
pango_shape(mUTF8String.get(), mUTF8String.Length(),
|
||||
&analysis, glyphString);
|
||||
|
||||
gint num_glyphs = glyphString->num_glyphs;
|
||||
gint *clusters = glyphString->log_clusters;
|
||||
@ -986,7 +1028,7 @@ gfxPangoTextRun::MeasureOrDrawFast(gfxContext *aContext,
|
||||
geometry->x_offset = spacingOffset;
|
||||
spacingOffset += mUTF8Spacing[j] - geometry->width;
|
||||
}
|
||||
if (aUTF8Str[j] == ' ')
|
||||
if (mUTF8String[j] == ' ')
|
||||
geometry->width = spaceWidth;
|
||||
width += geometry->width;
|
||||
}
|
||||
@ -1004,17 +1046,17 @@ gfxPangoTextRun::MeasureOrDrawFast(gfxContext *aContext,
|
||||
#endif
|
||||
}
|
||||
|
||||
pango_glyph_string_free(glyphString);
|
||||
TextSegment segment;
|
||||
segment.mFont = aFont;
|
||||
segment.mOffset = 0;
|
||||
segment.mLength = mUTF8String.Length();
|
||||
segment.mWidth = width;
|
||||
segment.mGlyphString = glyphString;
|
||||
mSegments.AppendElement(segment);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
struct TextSegment {
|
||||
PangoFont *mFont;
|
||||
PRUint32 mOffset;
|
||||
PRUint32 mLength;
|
||||
PangoGlyphString *mGlyphString;
|
||||
};
|
||||
|
||||
class FontSelector
|
||||
{
|
||||
public:
|
||||
@ -1032,11 +1074,6 @@ public:
|
||||
InitSegments(0, mLength, mFontIndex);
|
||||
}
|
||||
~FontSelector() {
|
||||
for (PRUint32 i = 0; i < mSegmentStack.Length(); ++i) {
|
||||
SegmentData segment = mSegmentStack[i];
|
||||
if (segment.mGlyphString)
|
||||
pango_glyph_string_free(segment.mGlyphString);
|
||||
}
|
||||
mSegmentStack.Clear();
|
||||
mFonts.Clear();
|
||||
}
|
||||
@ -1082,6 +1119,7 @@ public:
|
||||
aTextSegment->mFont = segment.mFont;
|
||||
aTextSegment->mOffset = mSegmentOffset;
|
||||
aTextSegment->mLength = segment.mLength;
|
||||
aTextSegment->mWidth = 0;
|
||||
aTextSegment->mGlyphString = segment.mGlyphString;
|
||||
mSegmentOffset += segment.mLength;
|
||||
if (aTextSegment->mGlyphString)
|
||||
@ -1089,7 +1127,7 @@ public:
|
||||
|
||||
aTextSegment->mGlyphString = pango_glyph_string_new();
|
||||
PangoFont *tmpFont = mItem->analysis.font;
|
||||
mItem->analysis.font = segment.mFont;
|
||||
mItem->analysis.font = segment.mFont->GetPangoFont();
|
||||
pango_shape(mString + aTextSegment->mOffset, aTextSegment->mLength,
|
||||
&mItem->analysis, aTextSegment->mGlyphString);
|
||||
mItem->analysis.font = tmpFont;
|
||||
@ -1108,9 +1146,9 @@ private:
|
||||
PRInt32 mLength;
|
||||
|
||||
struct SegmentData {
|
||||
PRUint32 mLength;
|
||||
PangoFont *mFont;
|
||||
PangoGlyphString *mGlyphString;
|
||||
PRUint32 mLength;
|
||||
nsRefPtr<gfxPangoFont> mFont;
|
||||
PangoGlyphString *mGlyphString;
|
||||
};
|
||||
PRUint32 mSegmentOffset;
|
||||
PRUint32 mSegmentIndex;
|
||||
@ -1134,19 +1172,19 @@ private:
|
||||
PRUint32 foundGlyphs = 0;
|
||||
|
||||
RetryNextFont:
|
||||
PangoFont *font = GetNextFont();
|
||||
nsRefPtr<gfxPangoFont> font = GetNextFont();
|
||||
|
||||
// If we cannot found the font that has the current character glyph,
|
||||
// we should return default font's missing data.
|
||||
if (!font) {
|
||||
font = mFonts[betterFontIndex]->GetPangoFont();
|
||||
font = mFonts[betterFontIndex];
|
||||
checkMissingGlyph = PR_FALSE;
|
||||
}
|
||||
|
||||
// Shaping
|
||||
PangoGlyphString *glyphString = pango_glyph_string_new();
|
||||
PangoFont *tmpFont = mItem->analysis.font;
|
||||
mItem->analysis.font = font;
|
||||
mItem->analysis.font = font->GetPangoFont();
|
||||
pango_shape(current, aLength, &mItem->analysis, glyphString);
|
||||
mItem->analysis.font = tmpFont;
|
||||
|
||||
@ -1235,11 +1273,10 @@ RetryNextFont:
|
||||
mSegmentStack.AppendElement(segment);
|
||||
}
|
||||
|
||||
PangoFont *GetNextFont() {
|
||||
gfxPangoFont *GetNextFont() {
|
||||
TRY_AGAIN_HOPE_FOR_THE_BEST_2:
|
||||
if (mFontIndex < mFonts.Length()) {
|
||||
nsRefPtr<gfxPangoFont> font = mFonts[mFontIndex++];
|
||||
return font->GetPangoFont();
|
||||
return mFonts[mFontIndex++];
|
||||
} else if (!mTriedPrefFonts) {
|
||||
mTriedPrefFonts = PR_TRUE;
|
||||
nsCAutoString mozLang;
|
||||
@ -1346,12 +1383,11 @@ int
|
||||
gfxPangoTextRun::MeasureOrDrawItemizing(gfxContext *aContext,
|
||||
PRBool aDraw,
|
||||
gfxPoint aPt,
|
||||
nsAFlatCString &aUTF8Str,
|
||||
PRBool aIsRTL,
|
||||
gfxPangoFont *aFont)
|
||||
{
|
||||
GList *items = pango_itemize(aFont->GetPangoContext(), aUTF8Str.get(), 0,
|
||||
aUTF8Str.Length(), NULL, NULL);
|
||||
GList *items = pango_itemize(aFont->GetPangoContext(), mUTF8String.get(), 0,
|
||||
mUTF8String.Length(), NULL, NULL);
|
||||
if (items) {
|
||||
GList *tmp = items;
|
||||
items = pango_reorder_items(tmp);
|
||||
@ -1373,7 +1409,7 @@ gfxPangoTextRun::MeasureOrDrawItemizing(gfxContext *aContext,
|
||||
isRTL ? PANGO_DIRECTION_RTL :
|
||||
PANGO_DIRECTION_LTR);
|
||||
}
|
||||
FontSelector fs(aContext, aUTF8Str.get() + item->offset,
|
||||
FontSelector fs(aContext, mUTF8String.get() + item->offset,
|
||||
item->length, mGroup, item, isRTL);
|
||||
TextSegment segment;
|
||||
while (fs.GetNextSegment(&segment)) {
|
||||
@ -1388,28 +1424,34 @@ gfxPangoTextRun::MeasureOrDrawItemizing(gfxContext *aContext,
|
||||
geometry->x_offset = spacingOffset;
|
||||
spacingOffset += mUTF8Spacing[j] - geometry->width;
|
||||
}
|
||||
if (aUTF8Str[j] == ' ')
|
||||
if (mUTF8String[j] == ' ')
|
||||
geometry->width = spaceWidth;
|
||||
currentWidth += geometry->width;
|
||||
}
|
||||
|
||||
#ifdef THEBES_USE_PANGO_CAIRO
|
||||
// XXX Do we need?
|
||||
glyphString->glyphs[0].geometry.x_offset += drawingOffset;
|
||||
#endif
|
||||
|
||||
// drawing
|
||||
if (aDraw && glyphString->num_glyphs > 0) {
|
||||
#ifndef THEBES_USE_PANGO_CAIRO
|
||||
DrawCairoGlyphs(aContext, segment.mFont,
|
||||
DrawCairoGlyphs(aContext, segment.mFont->GetPangoFont(),
|
||||
gfxPoint(drawingOffset/FLOAT_PANGO_SCALE, 0.0),
|
||||
glyphString);
|
||||
#else
|
||||
aContext->MoveTo(aPt); // XXX Do we need?
|
||||
glyphString->glyphs[0].geometry.x_offset += drawingOffset;
|
||||
pango_cairo_show_glyph_string(aContext->GetCairo(),
|
||||
segment.mFont,
|
||||
segment.mFont->GetPangoFont(),
|
||||
glyphString);
|
||||
#endif
|
||||
drawingOffset += currentWidth;
|
||||
}
|
||||
|
||||
width += currentWidth;
|
||||
segment.mWidth = currentWidth;
|
||||
mSegments.AppendElement(segment);
|
||||
}
|
||||
|
||||
pango_item_free(item);
|
||||
|
Loading…
x
Reference in New Issue
Block a user