зеркало из https://github.com/mozilla/pjs.git
Bug 368182. Add Xft path to gfxPangoTextRun to hopefully improve performance for 8bit text (rendering should be the same as it used to be pre-gfxPangoTextRun). r=pavlov
This commit is contained in:
Родитель
621c842938
Коммит
72cd3052d0
|
@ -46,7 +46,12 @@
|
||||||
#include <pango/pango.h>
|
#include <pango/pango.h>
|
||||||
#include <X11/Xft/Xft.h>
|
#include <X11/Xft/Xft.h>
|
||||||
|
|
||||||
//#define USE_XFT_FOR_ASCII
|
// Control when we use Xft directly, bypassing Pango
|
||||||
|
// Enable this to use Xft to glyph-convert 8bit-only textruns, but use Pango
|
||||||
|
// to shape any textruns with non-8bit characters
|
||||||
|
#define ENABLE_XFT_FAST_PATH_8BIT
|
||||||
|
// Enable this to use Xft to glyph-convert all textruns
|
||||||
|
// #define ENABLE_XFT_FAST_PATH_ALWAYS
|
||||||
|
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
|
|
||||||
|
@ -133,52 +138,6 @@ private:
|
||||||
nsTArray<gfxFontStyle> mAdditionalStyles;
|
nsTArray<gfxFontStyle> mAdditionalStyles;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_XFT_FOR_ASCII
|
|
||||||
|
|
||||||
class THEBES_API gfxXftTextRun : public gfxTextRun {
|
|
||||||
public:
|
|
||||||
gfxXftTextRun(gfxPangoFontGroup *aGroup,
|
|
||||||
const char* aString, PRInt32 aLength, PRUint32 aFlags);
|
|
||||||
~gfxXftTextRun();
|
|
||||||
|
|
||||||
virtual nsresult Init(PRBool aIsRTL, nsIAtom* aLangGroup,
|
|
||||||
gfxFloat aPixelsToUnits,
|
|
||||||
gfxSkipChars* aSkipChars, void* aUserData);
|
|
||||||
virtual void GetCharFlags(PRUint32 aStart, PRUint32 aLength,
|
|
||||||
PRUint8* aFlags);
|
|
||||||
virtual PRUint8 GetCharFlag(PRUint32 aOffset);
|
|
||||||
virtual void Draw(gfxContext* aContext, gfxPoint aPt,
|
|
||||||
PRUint32 aStart, PRUint32 aLength,
|
|
||||||
const gfxRect* aDirtyRect,
|
|
||||||
PropertyProvider* aBreakProvider,
|
|
||||||
gfxFloat* aAdvanceWidth);
|
|
||||||
virtual void Draw(gfxContext *aContext, gfxPoint aPt,
|
|
||||||
SpecialString aString);
|
|
||||||
virtual Metrics MeasureText(PRUint32 aStart, PRUint32 aLength,
|
|
||||||
PRBool aTightBoundingBox,
|
|
||||||
PropertyProvider* aBreakProvider);
|
|
||||||
virtual Metrics MeasureText(SpecialString aString,
|
|
||||||
PRBool aTightBoundingBox);
|
|
||||||
virtual gfxFloat GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
|
|
||||||
PropertyProvider* aBreakProvider);
|
|
||||||
virtual gfxFloat GetAdvanceWidth(SpecialString aString);
|
|
||||||
virtual gfxFont::Metrics& GetDecorationMetrics();
|
|
||||||
virtual PRUint32 BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
|
|
||||||
gfxFloat aWidth,
|
|
||||||
PropertyProvider* aBreakProvider,
|
|
||||||
PRBool aSuppressInitialBreak,
|
|
||||||
Metrics* aMetrics, PRBool aTightBoundingBox,
|
|
||||||
PRBool* aUsedHyphenation,
|
|
||||||
PRUint32* aLastBreak);
|
|
||||||
virtual void FlushSpacingCache(PRUint32 aStart, PRUint32 aLength);
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsString mWString;
|
|
||||||
nsCString mCString;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct TextSegment;
|
struct TextSegment;
|
||||||
|
|
||||||
class THEBES_API gfxPangoTextRun : public gfxTextRun {
|
class THEBES_API gfxPangoTextRun : public gfxTextRun {
|
||||||
|
@ -385,6 +344,7 @@ private:
|
||||||
void SetupClusterBoundaries(const gchar* aUTF8, PRUint32 aUTF8Length,
|
void SetupClusterBoundaries(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
PRUint32 aUTF16Offset, PangoAnalysis* aAnalysis);
|
PRUint32 aUTF16Offset, PangoAnalysis* aAnalysis);
|
||||||
nsresult AddGlyphRun(PangoFont* aFont, PRUint32 aUTF16Offset);
|
nsresult AddGlyphRun(PangoFont* aFont, PRUint32 aUTF16Offset);
|
||||||
|
DetailedGlyph* AllocateDetailedGlyphs(PRUint32 aIndex, PRUint32 aCount);
|
||||||
// Returns NS_ERROR_FAILURE if there's a missing glyph
|
// Returns NS_ERROR_FAILURE if there's a missing glyph
|
||||||
nsresult SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
nsresult SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
PRUint32* aUTF16Offset, PangoGlyphString* aGlyphs,
|
PRUint32* aUTF16Offset, PangoGlyphString* aGlyphs,
|
||||||
|
@ -396,7 +356,9 @@ private:
|
||||||
const PRUnichar* aUTF16Text, PRUint32 aUTF16Length);
|
const PRUnichar* aUTF16Text, PRUint32 aUTF16Length);
|
||||||
void CreateGlyphRunsItemizing(const gchar* aUTF8, PRUint32 aUTF8Length,
|
void CreateGlyphRunsItemizing(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
PRUint32 aUTF8HeaderLength);
|
PRUint32 aUTF8HeaderLength);
|
||||||
|
#if defined(ENABLE_XFT_FAST_PATH_8BIT) || defined(ENABLE_XFT_FAST_PATH_ALWAYS)
|
||||||
|
void CreateGlyphRunsXft(const gchar* aUTF8, PRUint32 aUTF8Length);
|
||||||
|
#endif
|
||||||
// **** general helpers ****
|
// **** general helpers ****
|
||||||
|
|
||||||
void SetupPangoContextDirection();
|
void SetupPangoContextDirection();
|
||||||
|
|
|
@ -39,15 +39,13 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#define PANGO_ENABLE_BACKEND
|
|
||||||
#define PANGO_ENABLE_ENGINE
|
|
||||||
|
|
||||||
//#define DISABLE_PANGO_FAST
|
|
||||||
|
|
||||||
#ifdef XP_BEOS
|
#ifdef XP_BEOS
|
||||||
#define THEBES_USE_PANGO_CAIRO
|
#define THEBES_USE_PANGO_CAIRO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PANGO_ENABLE_ENGINE
|
||||||
|
#define PANGO_ENABLE_BACKEND
|
||||||
|
|
||||||
#include "prtypes.h"
|
#include "prtypes.h"
|
||||||
#include "prlink.h"
|
#include "prlink.h"
|
||||||
#include "gfxTypes.h"
|
#include "gfxTypes.h"
|
||||||
|
@ -628,234 +626,6 @@ GetCJKLangGroupIndex(const char *aLangGroup)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
** gfxXftTextRun
|
|
||||||
**/
|
|
||||||
#ifdef USE_XFT_FOR_ASCII
|
|
||||||
|
|
||||||
gfxXftTextRun::gfxXftTextRun(const nsAString& aString, gfxPangoFontGroup *aGroup)
|
|
||||||
: mWString(aString), mIsWide(PR_TRUE), mGroup(aGroup), mWidth(-1), mHeight(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxXftTextRun::gfxXftTextRun(const nsACString& aString, gfxPangoFontGroup *aGroup)
|
|
||||||
: mCString(aString), mIsWide(PR_FALSE), mGroup(aGroup), mWidth(-1), mHeight(-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxXftTextRun::~gfxXftTextRun()
|
|
||||||
{
|
|
||||||
if (mOwnsText) {
|
|
||||||
delete[] mText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
gfxXftTextRun::Init(PRBool aIsRTL, nsIAtom* aLangGroup,
|
|
||||||
gfxFloat aPixelsToUnits,
|
|
||||||
gfxSkipChars* aSkipChars, void* aUserData)
|
|
||||||
{
|
|
||||||
nsresult rv = gfxTextRun::Init(aIsRTL, aLangGroup, aPixelsToUnits,
|
|
||||||
aSkipChars, aUserData);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
if (!mText)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gfxXftTextRun::GetCharFlags(PRUint32 aStart, PRUint32 aLength,
|
|
||||||
PRUint8* aFlags)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint8
|
|
||||||
gfxXftTextRun::GetCharFlag(PRUint32 aOffset)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gfxXftTextRun::Draw(gfxContext* aContext, gfxPoint aPt,
|
|
||||||
PRUint32 aStart, PRUint32 aLength,
|
|
||||||
gfxRect aDirtyRect,
|
|
||||||
PropertyProvider* aBreakProvider,
|
|
||||||
gfxFloat* aAdvanceWidth)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gfxXftTextRun::Draw(gfxContext *aContext, gfxPoint aPt,
|
|
||||||
SpecialString aString)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxTextRun::Metrics
|
|
||||||
gfxXftTextRun::MeasureText(PRUint32 aStart, PRUint32 aLength,
|
|
||||||
PRBool aTightBoundingBox,
|
|
||||||
PropertyProvider* aBreakProvider)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxTextRun::Metrics
|
|
||||||
gfxXftTextRun::MeasureText(SpecialString aString,
|
|
||||||
PRBool aTightBoundingBox)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxFloat
|
|
||||||
gfxXftTextRun::GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
|
|
||||||
PropertyProvider* aBreakProvider)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxFloat
|
|
||||||
gfxXftTextRun::GetAdvanceWidth(SpecialString aString)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const gfxFont::Metrics&
|
|
||||||
gfxXftTextRun::GetDecorationMetrics()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PRUint32
|
|
||||||
gfxXftTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
|
|
||||||
gfxFloat aWidth,
|
|
||||||
PropertyProvider* aBreakProvider,
|
|
||||||
PRBool aSuppressInitialBreak,
|
|
||||||
Metrics* aMetrics, PRBool aTightBoundingBox,
|
|
||||||
PRBool* aUsedHyphenation,
|
|
||||||
PRUint32* aLastBreak)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gfxXftTextRun::FlushSpacingCache(PRUint32 aStart, PRUint32 aLength)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gfxXftTextRun::Draw(gfxContext *aContext, gfxPoint pt)
|
|
||||||
{
|
|
||||||
nsRefPtr<gfxPangoFont> pf = mGroup->GetFontAt(0);
|
|
||||||
//printf("2. %s\n", nsPromiseFlatCString(mString).get());
|
|
||||||
XftFont * xfont = pf->GetXftFont();
|
|
||||||
//XftDraw * xdraw = pf->GetXftDraw();
|
|
||||||
|
|
||||||
|
|
||||||
cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(xfont->pattern);
|
|
||||||
cairo_set_font_face(aContext->GetCairo(), font);
|
|
||||||
|
|
||||||
double size;
|
|
||||||
if (FcPatternGetDouble(xfont->pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch)
|
|
||||||
size = 12.0;
|
|
||||||
|
|
||||||
cairo_set_font_size(aContext->GetCairo(), size);
|
|
||||||
|
|
||||||
//aContext->MoveTo(pt);
|
|
||||||
|
|
||||||
size_t len = mIsWide ? mWString.Length() : mCString.Length();
|
|
||||||
|
|
||||||
|
|
||||||
gfxFloat offset = 0;
|
|
||||||
cairo_glyph_t autoGlyphs[AUTO_GLYPHBUF_SIZE];
|
|
||||||
cairo_glyph_t* glyphs = autoGlyphs;
|
|
||||||
if (len > AUTO_GLYPHBUF_SIZE)
|
|
||||||
glyphs = new cairo_glyph_t[len];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
FT_UInt glyph = mIsWide ?
|
|
||||||
XftCharIndex(GDK_DISPLAY(), xfont, mWString[i]) :
|
|
||||||
XftCharIndex(GDK_DISPLAY(), xfont, mCString[i]);
|
|
||||||
|
|
||||||
glyphs[i].index = glyph;
|
|
||||||
glyphs[i].x = pt.x + offset;
|
|
||||||
glyphs[i].y = pt.y;
|
|
||||||
|
|
||||||
XGlyphInfo info;
|
|
||||||
XftGlyphExtents(GDK_DISPLAY(), xfont, &glyph, 1, &info);
|
|
||||||
offset += !mUTF8Spacing.IsEmpty() ? mUTF8Spacing[i] : info.xOff;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_show_glyphs(aContext->GetCairo(), glyphs, len);
|
|
||||||
|
|
||||||
if (len > AUTO_GLYPHBUF_SIZE)
|
|
||||||
delete [] glyphs;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (mIsWide)
|
|
||||||
cairo_show_text (aContext->GetCairo(), (const char *) NS_ConvertUTF16toUTF8(mWString).Data());
|
|
||||||
else
|
|
||||||
cairo_show_text (aContext->GetCairo(), nsCString(mCString).Data());
|
|
||||||
*/
|
|
||||||
|
|
||||||
cairo_font_face_destroy(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxFloat
|
|
||||||
gfxXftTextRun::Measure(gfxContext *aContext)
|
|
||||||
{
|
|
||||||
nsRefPtr<gfxPangoFont> pf = mGroup->GetFontAt(0);
|
|
||||||
|
|
||||||
XftFont * font = pf->GetXftFont();
|
|
||||||
if (font)
|
|
||||||
{
|
|
||||||
XGlyphInfo extents;
|
|
||||||
Display * dpy = GDK_DISPLAY ();
|
|
||||||
if (dpy) {
|
|
||||||
if (mIsWide) {
|
|
||||||
XftTextExtents16(dpy, font, (FcChar16 *) mWString.Data(), mWString.Length(), &extents);
|
|
||||||
} else {
|
|
||||||
XftTextExtents8(dpy, font, (FcChar8 *) mCString.Data(), mCString.Length(), &extents);
|
|
||||||
}
|
|
||||||
mWidth = extents.xOff;
|
|
||||||
} else {
|
|
||||||
NS_ERROR ("Textruns with no Display");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
printf ("didn't get font!\n");
|
|
||||||
mWidth = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gfxXftTextRun::SetSpacing(const nsTArray<gfxFloat>& spacingArray)
|
|
||||||
{
|
|
||||||
mSpacing = spacingArray;
|
|
||||||
|
|
||||||
//size_t len = mWString.Length();
|
|
||||||
|
|
||||||
if (mIsWide) {
|
|
||||||
NS_ConvertUTF16toUTF8 str(mWString);
|
|
||||||
|
|
||||||
mUTF8Spacing.Clear();
|
|
||||||
const char *curChar = str.get();
|
|
||||||
const char *prevChar = curChar;
|
|
||||||
for (unsigned int i = 0; i < mWString.Length(); i++) {
|
|
||||||
for (; prevChar + 1 < curChar; prevChar++)
|
|
||||||
mUTF8Spacing.AppendElement(0);
|
|
||||||
mUTF8Spacing.AppendElement((PRInt32)NSToCoordRound(mSpacing[i]));
|
|
||||||
if (NS_IS_HIGH_SURROGATE(mWString[i]))
|
|
||||||
i++;
|
|
||||||
prevChar = curChar;
|
|
||||||
curChar = g_utf8_find_next_char(curChar, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const nsTArray<gfxFloat> *const
|
|
||||||
gfxXftTextRun::GetSpacing() const
|
|
||||||
{
|
|
||||||
return &mSpacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** gfxPangoTextRun
|
** gfxPangoTextRun
|
||||||
*
|
*
|
||||||
|
@ -908,10 +678,13 @@ gfxPangoTextRun::gfxPangoTextRun(gfxPangoFontGroup *aGroup,
|
||||||
if (!mCharacterGlyphs)
|
if (!mCharacterGlyphs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
NS_ASSERTION(mFlags & gfxTextRunFactory::TEXT_IS_8BIT,
|
||||||
|
"Someone should have set the 8-bit flag already");
|
||||||
|
|
||||||
const gchar* utf8Chars = NS_REINTERPRET_CAST(const gchar*, aString);
|
const gchar* utf8Chars = NS_REINTERPRET_CAST(const gchar*, aString);
|
||||||
|
|
||||||
PRBool isRTL = IsRightToLeft();
|
PRBool isRTL = IsRightToLeft();
|
||||||
if ((mFlags & gfxTextRunFactory::TEXT_IS_ASCII) && !isRTL) {
|
if (!isRTL) {
|
||||||
// We don't need to send an override character here, the characters must be all
|
// We don't need to send an override character here, the characters must be all
|
||||||
// LTR
|
// LTR
|
||||||
Init(aParams, utf8Chars, aLength, 0, nsnull, 0);
|
Init(aParams, utf8Chars, aLength, 0, nsnull, 0);
|
||||||
|
@ -960,12 +733,22 @@ gfxPangoTextRun::Init(gfxTextRunFactory::Parameters* aParams, const gchar* aUTF8
|
||||||
PRUint32 aUTF8Length, PRUint32 aUTF8HeaderLength,
|
PRUint32 aUTF8Length, PRUint32 aUTF8HeaderLength,
|
||||||
const PRUnichar* aUTF16Text, PRUint32 aUTF16Length)
|
const PRUnichar* aUTF16Text, PRUint32 aUTF16Length)
|
||||||
{
|
{
|
||||||
|
#if defined(ENABLE_XFT_FAST_PATH_ALWAYS)
|
||||||
|
CreateGlyphRunsXft(aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
|
||||||
|
#else
|
||||||
|
#if defined(ENABLE_XFT_FAST_PATH_8BIT)
|
||||||
|
if (mFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
|
||||||
|
CreateGlyphRunsXft(aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
SetupPangoContextDirection();
|
SetupPangoContextDirection();
|
||||||
nsresult rv = CreateGlyphRunsFast(aUTF8Text + aUTF8HeaderLength,
|
nsresult rv = CreateGlyphRunsFast(aUTF8Text + aUTF8HeaderLength,
|
||||||
aUTF8Length - aUTF8HeaderLength, aUTF16Text, aUTF16Length);
|
aUTF8Length - aUTF8HeaderLength, aUTF16Text, aUTF16Length);
|
||||||
if (rv == NS_ERROR_FAILURE) {
|
if (rv == NS_ERROR_FAILURE) {
|
||||||
CreateGlyphRunsItemizing(aUTF8Text, aUTF8Length, aUTF8HeaderLength);
|
CreateGlyphRunsItemizing(aUTF8Text, aUTF8Length, aUTF8HeaderLength);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2222,6 +2005,31 @@ gfxPangoTextRun::AddGlyphRun(PangoFont* aFont, PRUint32 aUTF16Offset)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfxPangoTextRun::DetailedGlyph*
|
||||||
|
gfxPangoTextRun::AllocateDetailedGlyphs(PRUint32 aIndex, PRUint32 aCount)
|
||||||
|
{
|
||||||
|
if (!mDetailedGlyphs) {
|
||||||
|
mDetailedGlyphs = new nsAutoArrayPtr<DetailedGlyph>[mCharacterCount];
|
||||||
|
if (!mDetailedGlyphs)
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
DetailedGlyph* details = new DetailedGlyph[aCount];
|
||||||
|
if (!details)
|
||||||
|
return nsnull;
|
||||||
|
mDetailedGlyphs[aIndex] = details;
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SetSkipMissingGlyph(gfxPangoTextRun::DetailedGlyph* aDetails)
|
||||||
|
{
|
||||||
|
aDetails->mIsLastGlyph = PR_TRUE;
|
||||||
|
aDetails->mGlyphID = gfxPangoTextRun::DetailedGlyph::DETAILED_MISSING_GLYPH;
|
||||||
|
aDetails->mAdvance = 0;
|
||||||
|
aDetails->mXOffset = 0;
|
||||||
|
aDetails->mYOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxPangoTextRun::SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
gfxPangoTextRun::SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
PRUint32* aUTF16Offset, PangoGlyphString* aGlyphs,
|
PRUint32* aUTF16Offset, PangoGlyphString* aGlyphs,
|
||||||
|
@ -2246,20 +2054,10 @@ gfxPangoTextRun::SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
|
|
||||||
if (aUTF8[index] == 0) {
|
if (aUTF8[index] == 0) {
|
||||||
// treat this null byte like a missing glyph with no advance
|
// treat this null byte like a missing glyph with no advance
|
||||||
if (!mDetailedGlyphs) {
|
DetailedGlyph* details = AllocateDetailedGlyphs(utf16Offset, 1);
|
||||||
mDetailedGlyphs = new nsAutoArrayPtr<DetailedGlyph>[mCharacterCount];
|
|
||||||
if (!mDetailedGlyphs)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
DetailedGlyph* details = new DetailedGlyph[1];
|
|
||||||
if (!details)
|
if (!details)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
mDetailedGlyphs[utf16Offset] = details;
|
SetSkipMissingGlyph(details);
|
||||||
details->mIsLastGlyph = PR_TRUE;
|
|
||||||
details->mGlyphID = DetailedGlyph::DETAILED_MISSING_GLYPH;
|
|
||||||
details->mAdvance = 0;
|
|
||||||
details->mXOffset = 0;
|
|
||||||
details->mYOffset = 0;
|
|
||||||
} else if (glyphCount == numGlyphs ||
|
} else if (glyphCount == numGlyphs ||
|
||||||
PRUint32(logClusters[glyphIndex]) > index) {
|
PRUint32(logClusters[glyphIndex]) > index) {
|
||||||
// No glyphs for this cluster, and it's not a null byte. It must be a ligature.
|
// No glyphs for this cluster, and it's not a null byte. It must be a ligature.
|
||||||
|
@ -2304,15 +2102,9 @@ gfxPangoTextRun::SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
} else {
|
} else {
|
||||||
// Note that missing-glyph IDs are not simple glyph IDs, so we'll
|
// Note that missing-glyph IDs are not simple glyph IDs, so we'll
|
||||||
// always get here when a glyph is missing
|
// always get here when a glyph is missing
|
||||||
if (!mDetailedGlyphs) {
|
DetailedGlyph* details = AllocateDetailedGlyphs(utf16Offset, glyphClusterCount);
|
||||||
mDetailedGlyphs = new nsAutoArrayPtr<DetailedGlyph>[mCharacterCount];
|
|
||||||
if (!mDetailedGlyphs)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
DetailedGlyph* details = new DetailedGlyph[glyphClusterCount];
|
|
||||||
if (!details)
|
if (!details)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
mDetailedGlyphs[utf16Offset] = details;
|
|
||||||
PRUint32 i;
|
PRUint32 i;
|
||||||
for (i = 0; i < glyphClusterCount; ++i) {
|
for (i = 0; i < glyphClusterCount; ++i) {
|
||||||
details->mIsLastGlyph = i == glyphClusterCount - 1;
|
details->mIsLastGlyph = i == glyphClusterCount - 1;
|
||||||
|
@ -2344,6 +2136,67 @@ gfxPangoTextRun::SetGlyphs(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ENABLE_XFT_FAST_PATH_8BIT) || defined(ENABLE_XFT_FAST_PATH_ALWAYS)
|
||||||
|
void
|
||||||
|
gfxPangoTextRun::CreateGlyphRunsXft(const gchar* aUTF8, PRUint32 aUTF8Length)
|
||||||
|
{
|
||||||
|
const gchar* p = aUTF8;
|
||||||
|
Display* dpy = GDK_DISPLAY();
|
||||||
|
gfxPangoFont* font = mFontGroup->GetFontAt(0);
|
||||||
|
XftFont* xfont = font->GetXftFont();
|
||||||
|
PRUint32 utf16Offset = 0;
|
||||||
|
|
||||||
|
while (p < aUTF8 + aUTF8Length) {
|
||||||
|
gunichar ch = g_utf8_get_char(p);
|
||||||
|
p = g_utf8_next_char(p);
|
||||||
|
|
||||||
|
if (ch == 0) {
|
||||||
|
// treat this null byte like a missing glyph with no advance
|
||||||
|
DetailedGlyph* details = AllocateDetailedGlyphs(utf16Offset, 1);
|
||||||
|
if (!details)
|
||||||
|
return;
|
||||||
|
SetSkipMissingGlyph(details);
|
||||||
|
} else {
|
||||||
|
FT_UInt glyph = XftCharIndex(dpy, xfont, ch);
|
||||||
|
XGlyphInfo info;
|
||||||
|
XftGlyphExtents(dpy, xfont, &glyph, 1, &info);
|
||||||
|
if (info.yOff > 0) {
|
||||||
|
NS_WARNING("vertical offsets not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.xOff >= 0 &&
|
||||||
|
CompressedGlyph::IsSimpleAdvance(info.xOff) &&
|
||||||
|
CompressedGlyph::IsSimpleGlyphID(glyph)) {
|
||||||
|
mCharacterGlyphs[utf16Offset].SetSimpleGlyph(info.xOff, glyph);
|
||||||
|
} else {
|
||||||
|
// Note that missing-glyph IDs are not simple glyph IDs, so we'll
|
||||||
|
// always get here when a glyph is missing
|
||||||
|
DetailedGlyph* details = AllocateDetailedGlyphs(utf16Offset, 1);
|
||||||
|
if (!details)
|
||||||
|
return;
|
||||||
|
details->mIsLastGlyph = PR_TRUE;
|
||||||
|
details->mGlyphID = glyph;
|
||||||
|
NS_ASSERTION(details->mGlyphID == glyph,
|
||||||
|
"Seriously weird glyph ID detected!");
|
||||||
|
if (IS_MISSING_GLYPH(glyph)) {
|
||||||
|
details->mGlyphID = DetailedGlyph::DETAILED_MISSING_GLYPH;
|
||||||
|
}
|
||||||
|
details->mAdvance = float(info.xOff);
|
||||||
|
details->mXOffset = 0;
|
||||||
|
details->mYOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++utf16Offset;
|
||||||
|
if (utf16Offset < mCharacterCount &&
|
||||||
|
mCharacterGlyphs[utf16Offset].IsLowSurrogate()) {
|
||||||
|
++utf16Offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddGlyphRun(font->GetPangoFont(), 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
gfxPangoTextRun::CreateGlyphRunsFast(const gchar* aUTF8, PRUint32 aUTF8Length,
|
gfxPangoTextRun::CreateGlyphRunsFast(const gchar* aUTF8, PRUint32 aUTF8Length,
|
||||||
const PRUnichar* aUTF16, PRUint32 aUTF16Length)
|
const PRUnichar* aUTF16, PRUint32 aUTF16Length)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче