mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 375760. Make a number of small changes to the gfxTextRun/gfxFont/gfxFontGroup APIs. r=vlad
This commit is contained in:
parent
bb057f50e6
commit
2898af075d
@ -275,9 +275,6 @@ public:
|
||||
StubPropertyProvider(const nscoord* aSpacing = nsnull)
|
||||
: mSpacing(aSpacing) {}
|
||||
|
||||
virtual void ForceRememberText() {
|
||||
NS_ERROR("This shouldn't be called because we already asked the textrun to remember");
|
||||
}
|
||||
virtual void GetHyphenationBreaks(PRUint32 aStart, PRUint32 aLength,
|
||||
PRPackedBool* aBreakBefore) {
|
||||
NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
|
||||
virtual const gfxFont::Metrics& GetMetrics();
|
||||
|
||||
float GetCharWidth(PRUnichar c);
|
||||
float GetCharWidth(PRUnichar c, PRUint32 *aGlyphID = nsnull);
|
||||
float GetCharHeight(PRUnichar c);
|
||||
|
||||
ATSUFontID GetATSUFontID() { return mATSUFontID; }
|
||||
@ -68,6 +68,8 @@ public:
|
||||
|
||||
virtual nsString GetUniqueName();
|
||||
|
||||
virtual PRUint32 GetSpaceGlyph() { return mSpaceGlyph; }
|
||||
|
||||
protected:
|
||||
const gfxFontStyle *mFontStyle;
|
||||
|
||||
@ -82,6 +84,8 @@ protected:
|
||||
gfxFont::Metrics mMetrics;
|
||||
|
||||
gfxFloat mAdjustedSize;
|
||||
PRUint32 mSpaceGlyph;
|
||||
|
||||
void InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef);
|
||||
|
||||
virtual void SetupCairoFont(cairo_t *aCR)
|
||||
@ -99,17 +103,17 @@ public:
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
|
||||
Parameters* aParams);
|
||||
const Parameters* aParams, PRUint32 aFlags);
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
|
||||
Parameters* aParams);
|
||||
const Parameters* aParams, PRUint32 aFlags);
|
||||
// When aWrapped is true, the string includes bidi control
|
||||
// characters. The first character will be LRO or LRO to force setting the
|
||||
// direction for all characters, the last character is PDF, and the
|
||||
// second to last character is a non-whitespace character --- to ensure
|
||||
// that there is no "trailing whitespace" in the string, see
|
||||
// http://weblogs.mozillazine.org/roc/archives/2007/02/superlaser_targ.html#comments
|
||||
gfxTextRun *MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped, Parameters *aParams);
|
||||
void MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped, gfxTextRun *aTextRun);
|
||||
|
||||
ATSUFontFallbacks *GetATSUFontFallbacksPtr() { return &mFallbacks; }
|
||||
|
||||
|
@ -414,6 +414,9 @@ public:
|
||||
// Expiration tracking
|
||||
nsExpirationState *GetExpirationState() { return &mExpirationState; }
|
||||
|
||||
// Get the glyphID of a space
|
||||
virtual PRUint32 GetSpaceGlyph() = 0;
|
||||
|
||||
protected:
|
||||
// The family name of the font
|
||||
nsString mName;
|
||||
@ -491,8 +494,6 @@ public:
|
||||
gfxContext *mContext;
|
||||
// Pointer to arbitrary user data (which should outlive the textrun)
|
||||
void *mUserData;
|
||||
// The language of the text, or null if not known
|
||||
nsIAtom *mLangGroup;
|
||||
// A description of which characters have been stripped from the original
|
||||
// DOM string to produce the characters in the textrun. May be null
|
||||
// if that information is not relevant.
|
||||
@ -503,24 +504,9 @@ public:
|
||||
PRUint32 mInitialBreakCount;
|
||||
// The ratio to use to convert device pixels to application layout units
|
||||
PRUint32 mAppUnitsPerDevUnit;
|
||||
// Flags --- see above
|
||||
PRUint32 mFlags;
|
||||
};
|
||||
|
||||
virtual ~gfxTextRunFactory() {}
|
||||
|
||||
/**
|
||||
* Create a gfxTextRun from Unicode text. The length is obtained from
|
||||
* aParams->mSkipChars->GetCharCount().
|
||||
*/
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
Parameters *aParams) = 0;
|
||||
/**
|
||||
* Create a gfxTextRun from 8-bit Unicode (UCS1?) text. The length is
|
||||
* obtained from aParams->mSkipChars->GetCharCount().
|
||||
*/
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
Parameters *aParams) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -542,15 +528,6 @@ public:
|
||||
* there are no line breaks. The textrun can record line breaks before or after
|
||||
* any given cluster. (Line breaks specified inside clusters are ignored.)
|
||||
*
|
||||
* gfxTextRuns don't need to remember their text ... often it's enough just to
|
||||
* convert text to glyphs and store glyphs plus some geometry data in packed
|
||||
* form. However sometimes gfxTextRuns will want to get the original text back
|
||||
* to handle some unusual situation. So gfxTextRuns have two modes: "not
|
||||
* remembering text" (initial state) and "remembering text". A call to
|
||||
* gfxTextRun::RememberText forces a transition from the former to latter state.
|
||||
* The text is never forgotten. A gfxTextRun call that receives a PropertyProvider
|
||||
* object may call ForceRememberText to request a transition to "remembering text".
|
||||
*
|
||||
* It is important that zero-length substrings are handled correctly. This will
|
||||
* be on the test!
|
||||
*
|
||||
@ -568,7 +545,7 @@ public:
|
||||
*/
|
||||
class THEBES_API gfxTextRun {
|
||||
public:
|
||||
~gfxTextRun() {}
|
||||
virtual ~gfxTextRun();
|
||||
|
||||
typedef gfxFont::RunMetrics Metrics;
|
||||
|
||||
@ -595,15 +572,6 @@ public:
|
||||
|
||||
// All coordinates are in layout/app units
|
||||
|
||||
/**
|
||||
* This can be called to force gfxTextRun to remember the text used
|
||||
* to create it and *never* call PropertyProvider::GetText again.
|
||||
*
|
||||
* Right now we don't implement these.
|
||||
*/
|
||||
void RememberText(const PRUnichar *aText, PRUint32 aLength) {}
|
||||
void RememberText(const PRUint8 *aText, PRUint32 aLength) {}
|
||||
|
||||
/**
|
||||
* Set the potential linebreaks for a substring of the textrun. These are
|
||||
* the "allow break before" points. Initially, there are no potential
|
||||
@ -631,16 +599,6 @@ public:
|
||||
*/
|
||||
class PropertyProvider {
|
||||
public:
|
||||
/**
|
||||
* Recover the text originally used to build the textrun. This should
|
||||
* only be requested infrequently as it may be slow. If you need to
|
||||
* call it a lot you should probably be saving the text in the text run
|
||||
* itself. It just forces the textrun user to call RememberText on the
|
||||
* text run. If you call this and RememberText doesn't get called,
|
||||
* then something has failed and you should handle it.
|
||||
*/
|
||||
virtual void ForceRememberText() = 0;
|
||||
|
||||
// Detect hyphenation break opportunities in the given range; breaks
|
||||
// not at cluster boundaries will be ignored.
|
||||
virtual void GetHyphenationBreaks(PRUint32 aStart, PRUint32 aLength,
|
||||
@ -757,7 +715,6 @@ public:
|
||||
*/
|
||||
virtual PRBool SetLineBreaks(PRUint32 aStart, PRUint32 aLength,
|
||||
PRBool aLineBreakBefore, PRBool aLineBreakAfter,
|
||||
PropertyProvider *aProvider,
|
||||
gfxFloat *aAdvanceWidthDelta);
|
||||
|
||||
/**
|
||||
@ -823,13 +780,30 @@ public:
|
||||
PRBool IsRightToLeft() const { return (mFlags & gfxTextRunFactory::TEXT_IS_RTL) != 0; }
|
||||
gfxFloat GetDirection() const { return (mFlags & gfxTextRunFactory::TEXT_IS_RTL) ? -1.0 : 1.0; }
|
||||
void *GetUserData() const { return mUserData; }
|
||||
void SetUserData(void *aUserData) { mUserData = aUserData; }
|
||||
PRUint32 GetFlags() const { return mFlags; }
|
||||
const gfxSkipChars& GetSkipChars() const { return mSkipChars; }
|
||||
PRUint32 GetAppUnitsPerDevUnit() const { return mAppUnitsPerDevUnit; }
|
||||
gfxFontGroup *GetFontGroup() const { return mFontGroup; }
|
||||
const PRUint8 *GetText8Bit() const
|
||||
{ return (mFlags & gfxTextRunFactory::TEXT_IS_8BIT) ? mText.mSingle : nsnull; }
|
||||
const PRUnichar *GetTextUnicode() const
|
||||
{ return (mFlags & gfxTextRunFactory::TEXT_IS_8BIT) ? nsnull : mText.mDouble; }
|
||||
|
||||
// The caller is responsible for initializing our glyphs after construction.
|
||||
// Initially all glyphs are such that GetCharacterGlyphs()[i].IsMissing() is true.
|
||||
gfxTextRun(gfxTextRunFactory::Parameters *aParams, PRUint32 aLength);
|
||||
// We take ownership of aText, which must have been allocated by new[] (it
|
||||
// may be null if aLength is zero).
|
||||
gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void *aText,
|
||||
PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags);
|
||||
|
||||
// Clone this textrun, according to the given parameters. This textrun's
|
||||
// glyph data is copied, so the text and length must be the same as this
|
||||
// textrun's. If there's a problem, return null. Actual linebreaks will
|
||||
// be set as per aParams; there will be no potential linebreaks.
|
||||
// If successful, we take ownership of aText, which must have been allocated by new[].
|
||||
virtual gfxTextRun *Clone(const gfxTextRunFactory::Parameters *aParams, const void *aText,
|
||||
PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags);
|
||||
|
||||
/**
|
||||
* This class records the information associated with a character in the
|
||||
@ -1050,6 +1024,8 @@ public:
|
||||
return mGlyphRuns.Elements();
|
||||
}
|
||||
|
||||
nsExpirationState *GetExpirationState() { return &mExpirationState; }
|
||||
|
||||
private:
|
||||
// **** general helpers ****
|
||||
|
||||
@ -1110,14 +1086,21 @@ private:
|
||||
// XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*,
|
||||
// for smaller size especially in the super-common one-glyphrun case
|
||||
nsAutoTArray<GlyphRun,1> mGlyphRuns;
|
||||
|
||||
void *mUserData;
|
||||
gfxSkipChars mSkipChars;
|
||||
// This is actually an integer, but we keep it in float form to reduce
|
||||
// the conversions required
|
||||
PRUint32 mAppUnitsPerDevUnit;
|
||||
PRUint32 mFlags;
|
||||
PRUint32 mCharacterCount;
|
||||
// When TEXT_IS_8BIT is set, we use mSingle, otherwise we use mDouble.
|
||||
// When TEXT_IS_PERSISTENT is set, we don't own the text, otherwise we
|
||||
// own the text and should delete it when we go away.
|
||||
// This text is not null-terminated.
|
||||
union {
|
||||
const PRUint8 *mSingle;
|
||||
const PRUnichar *mDouble;
|
||||
} mText;
|
||||
void *mUserData;
|
||||
gfxFontGroup *mFontGroup; // addrefed
|
||||
gfxSkipChars mSkipChars;
|
||||
nsExpirationState mExpirationState;
|
||||
PRUint32 mAppUnitsPerDevUnit;
|
||||
PRUint32 mFlags;
|
||||
PRUint32 mCharacterCount;
|
||||
};
|
||||
|
||||
class THEBES_API gfxFontGroup : public gfxTextRunFactory {
|
||||
@ -1144,13 +1127,31 @@ public:
|
||||
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle) = 0;
|
||||
|
||||
// These need to be repeated from gfxTextRunFactory because of C++'s
|
||||
// hiding rules!
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
|
||||
Parameters* aParams) = 0;
|
||||
// This function should set TEXT_IS_8BIT in aParams->mFlags.
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
|
||||
Parameters* aParams) = 0;
|
||||
/**
|
||||
* Make a textrun for an empty string. This is fast; if you call it,
|
||||
* don't bother caching the result.
|
||||
*/
|
||||
gfxTextRun *MakeEmptyTextRun(const Parameters *aParams, PRUint32 aFlags);
|
||||
/**
|
||||
* Make a textrun for a single ASCII space. This is fast; if you call it,
|
||||
* don't bother caching the result.
|
||||
*/
|
||||
gfxTextRun *MakeSpaceTextRun(const Parameters *aParams, PRUint32 aFlags);
|
||||
|
||||
/**
|
||||
* Make a textrun for a given string. Takes ownership of aString unless
|
||||
* aFlags & TEXT_IS_PERSISTENT --- in that case, the caller must destroy
|
||||
* the textrun before aString dies.
|
||||
*/
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags) = 0;
|
||||
/**
|
||||
* Make a textrun for a given string. Takes ownership of aString unless
|
||||
* aFlags & TEXT_IS_PERSISTENT --- in that case, the caller must destroy
|
||||
* the textrun before aString dies.
|
||||
*/
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags) = 0;
|
||||
|
||||
/* helper function for splitting font families on commas and
|
||||
* calling a function for each family to fill the mFonts array
|
||||
@ -1169,31 +1170,10 @@ public:
|
||||
|
||||
const nsString& GetFamilies() { return mFamilies; }
|
||||
|
||||
/**
|
||||
* Special strings are strings that we might need to draw/measure but aren't
|
||||
* actually substrings of DOM text. They never have extra spacing and
|
||||
* aren't involved in breaking.
|
||||
*/
|
||||
enum SpecialString {
|
||||
STRING_ELLIPSIS,
|
||||
STRING_HYPHEN,
|
||||
STRING_SPACE,
|
||||
STRING_MAX = STRING_SPACE
|
||||
};
|
||||
|
||||
// Get the textrun for the given special string. Ownership remains
|
||||
// with this gfxFontGroup. Copy relevant parameters from the template textrun.
|
||||
// SpecialString textruns do not use spacing and it's fine to pass null
|
||||
// as the PropertyProvider* in their methods.
|
||||
// This is stubbed out until we have full textrun support on all platforms.
|
||||
gfxTextRun *GetSpecialStringTextRun(SpecialString aString,
|
||||
gfxTextRun *aTemplate);
|
||||
|
||||
protected:
|
||||
nsString mFamilies;
|
||||
gfxFontStyle mStyle;
|
||||
nsTArray< nsRefPtr<gfxFont> > mFonts;
|
||||
nsAutoPtr<gfxTextRun> mSpecialStrings[STRING_MAX + 1];
|
||||
|
||||
static PRBool ForEachFontInternal(const nsAString& aFamilies,
|
||||
const nsACString& aLangGroup,
|
||||
|
@ -86,6 +86,12 @@ public:
|
||||
|
||||
virtual nsString GetUniqueName();
|
||||
|
||||
// Get the glyphID of a space
|
||||
virtual PRUint32 GetSpaceGlyph() {
|
||||
GetMetrics();
|
||||
return mSpaceGlyph;
|
||||
}
|
||||
|
||||
protected:
|
||||
PangoFontDescription *mPangoFontDesc;
|
||||
PangoContext *mPangoCtx;
|
||||
@ -93,13 +99,15 @@ protected:
|
||||
XftFont *mXftFont;
|
||||
cairo_scaled_font_t *mCairoFont;
|
||||
|
||||
PRBool mHasMetrics;
|
||||
Metrics mMetrics;
|
||||
PRBool mHasMetrics;
|
||||
PRUint32 mSpaceGlyph;
|
||||
Metrics mMetrics;
|
||||
gfxFloat mAdjustedSize;
|
||||
|
||||
void RealizeFont(PRBool force = PR_FALSE);
|
||||
void RealizeXftFont(PRBool force = PR_FALSE);
|
||||
void GetSize(const char *aString, PRUint32 aLength, gfxSize& inkSize, gfxSize& logSize);
|
||||
void GetSize(char aChar, gfxSize& inkSize, gfxSize& logSize,
|
||||
PRUint32 *aGlyphID = nsnull);
|
||||
|
||||
virtual void SetupCairoFont(cairo_t *aCR);
|
||||
};
|
||||
@ -116,9 +124,9 @@ public:
|
||||
|
||||
// Create and initialize a textrun using Pango (or Xft)
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
Parameters *aParams);
|
||||
const Parameters *aParams, PRUint32 aFlags);
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
Parameters *aParams);
|
||||
const Parameters *aParams, PRUint32 aFlags);
|
||||
|
||||
gfxPangoFont *GetFontAt(PRInt32 i) {
|
||||
return NS_STATIC_CAST(gfxPangoFont*,
|
||||
|
@ -91,6 +91,8 @@ protected:
|
||||
FontGroupAndStringT(gfxFontGroup *fg, const GenericString* str)
|
||||
: mFontGroup(fg), mString(str) { }
|
||||
|
||||
typedef typename RealString::char_type char_type;
|
||||
|
||||
FontGroupAndStringT(const FontGroupAndStringT<GenericString,RealString>& other)
|
||||
: mFontGroup(other.mFontGroup), mString(&mRealString)
|
||||
{
|
||||
@ -101,6 +103,9 @@ protected:
|
||||
mRealString.Assign(*mString);
|
||||
mString = &mRealString;
|
||||
}
|
||||
const char_type *GetRealString() {
|
||||
return mRealString.get();
|
||||
}
|
||||
|
||||
nsRefPtr<gfxFontGroup> mFontGroup;
|
||||
RealString mRealString;
|
||||
|
@ -424,14 +424,20 @@ public:
|
||||
gfxContext *aContext, PRBool aDrawToPath, gfxPoint *aBaselineOrigin,
|
||||
Spacing *aSpacing);
|
||||
|
||||
virtual PRUint32 GetSpaceGlyph() {
|
||||
ComputeMetrics();
|
||||
return mSpaceGlyph;
|
||||
};
|
||||
|
||||
protected:
|
||||
HFONT MakeHFONT();
|
||||
cairo_font_face_t *MakeCairoFontFace();
|
||||
cairo_scaled_font_t *MakeCairoScaledFont();
|
||||
void FillLogFont(gfxFloat aSize, PRInt16 aWeight);
|
||||
|
||||
HFONT mFont;
|
||||
HFONT mFont;
|
||||
gfxFloat mAdjustedSize;
|
||||
PRUint32 mSpaceGlyph;
|
||||
|
||||
private:
|
||||
void Destroy();
|
||||
@ -466,9 +472,9 @@ public:
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
|
||||
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
|
||||
Parameters* aParams);
|
||||
const Parameters* aParams, PRUint32 aFlags);
|
||||
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
|
||||
Parameters* aParams);
|
||||
const Parameters* aParams, PRUint32 aFlags);
|
||||
|
||||
const nsACString& GetGenericFamily() const {
|
||||
return mGenericFamily;
|
||||
|
@ -182,11 +182,12 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
|
||||
|
||||
mMetrics.maxAdvance = atsMetrics.maxAdvanceWidth * size;
|
||||
|
||||
float xWidth = GetCharWidth('x');
|
||||
if (atsMetrics.avgAdvanceWidth != 0.0)
|
||||
mMetrics.aveCharWidth =
|
||||
PR_MIN(atsMetrics.avgAdvanceWidth * size, GetCharWidth('x'));
|
||||
PR_MIN(atsMetrics.avgAdvanceWidth * size, xWidth);
|
||||
else
|
||||
mMetrics.aveCharWidth = GetCharWidth('x');
|
||||
mMetrics.aveCharWidth = xWidth;
|
||||
|
||||
mMetrics.underlineOffset = atsMetrics.underlinePosition * size;
|
||||
// ATSUI sometimes returns 0 for underline thickness, see bug 361576.
|
||||
@ -198,7 +199,9 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
|
||||
mMetrics.strikeoutOffset = mMetrics.xHeight / 2.0;
|
||||
mMetrics.strikeoutSize = mMetrics.underlineSize;
|
||||
|
||||
mMetrics.spaceWidth = GetCharWidth(' ');
|
||||
PRUint32 glyphID;
|
||||
mMetrics.spaceWidth = GetCharWidth(' ', &glyphID);
|
||||
mSpaceGlyph = glyphID;
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "Font: %p size: %f", this, size);
|
||||
@ -217,7 +220,7 @@ gfxAtsuiFont::GetUniqueName()
|
||||
}
|
||||
|
||||
float
|
||||
gfxAtsuiFont::GetCharWidth(PRUnichar c)
|
||||
gfxAtsuiFont::GetCharWidth(PRUnichar c, PRUint32 *aGlyphID)
|
||||
{
|
||||
// this sucks. There is a faster way to go from a char -> glyphs, but it
|
||||
// requires using oodles of apple private interfaces. If we start caching
|
||||
@ -236,6 +239,13 @@ gfxAtsuiFont::GetCharWidth(PRUnichar c)
|
||||
FixedToFloat(PR_MAX(trap.upperRight.x, trap.lowerRight.x)) -
|
||||
FixedToFloat(PR_MIN(trap.upperLeft.x, trap.lowerLeft.x));
|
||||
|
||||
if (aGlyphID) {
|
||||
ATSUGlyphInfoArray glyphInfo;
|
||||
ByteCount bytes = sizeof(glyphInfo);
|
||||
ATSUGetGlyphInfo(layout, 0, 1, &bytes, &glyphInfo);
|
||||
*aGlyphID = glyphInfo.glyphs[0].glyphID;
|
||||
}
|
||||
|
||||
ATSUDisposeTextLayout(layout);
|
||||
|
||||
return f;
|
||||
@ -412,25 +422,19 @@ SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
|
||||
UCDisposeTextBreakLocator(&locator);
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
void
|
||||
gfxAtsuiFontGroup::MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
|
||||
PRBool aWrapped, Parameters *aParams)
|
||||
PRBool aWrapped, gfxTextRun *aTextRun)
|
||||
{
|
||||
// NS_ASSERTION(!(aParams->mFlags & TEXT_NEED_BOUNDING_BOX),
|
||||
// "Glyph extents not yet supported");
|
||||
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aLength - (aWrapped ? 3 : 0));
|
||||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
const PRUnichar *realString = aString + (aWrapped ? 1 : 0);
|
||||
textRun->RecordSurrogates(realString);
|
||||
if (!(aParams->mFlags & TEXT_IS_8BIT)) {
|
||||
SetupClusterBoundaries(textRun, realString);
|
||||
aTextRun->RecordSurrogates(realString);
|
||||
if (!(aTextRun->GetFlags() & TEXT_IS_8BIT)) {
|
||||
SetupClusterBoundaries(aTextRun, realString);
|
||||
}
|
||||
|
||||
InitTextRun(textRun, aString, aLength, aWrapped);
|
||||
return textRun;
|
||||
InitTextRun(aTextRun, aString, aLength, aWrapped);
|
||||
}
|
||||
|
||||
#define UNICODE_LRO 0x202d
|
||||
@ -446,36 +450,46 @@ AppendDirectionalIndicator(PRUint32 aFlags, nsAString& aString)
|
||||
|
||||
gfxTextRun *
|
||||
gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
Parameters *aParams)
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aString, aLength, this, aFlags);
|
||||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
nsAutoString utf16;
|
||||
AppendDirectionalIndicator(aParams->mFlags, utf16);
|
||||
AppendDirectionalIndicator(aFlags, utf16);
|
||||
utf16.Append(aString, aLength);
|
||||
// Ensure that none of the whitespace in the run is considered "trailing"
|
||||
// by ATSUI's bidi algorithm
|
||||
utf16.Append('.');
|
||||
utf16.Append(UNICODE_PDF);
|
||||
return MakeTextRunInternal(utf16.get(), utf16.Length(), PR_TRUE, aParams);
|
||||
MakeTextRunInternal(utf16.get(), utf16.Length(), PR_TRUE, textRun);
|
||||
return textRun;
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
gfxAtsuiFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
Parameters *aParams)
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
aParams->mFlags |= TEXT_IS_8BIT;
|
||||
NS_ASSERTION(aFlags & TEXT_IS_8BIT, "should be marked 8bit");
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aString, aLength, this, aFlags);
|
||||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
nsDependentCSubstring cString(reinterpret_cast<const char*>(aString),
|
||||
reinterpret_cast<const char*>(aString + aLength));
|
||||
nsAutoString utf16;
|
||||
PRBool wrapBidi = (aParams->mFlags & TEXT_IS_RTL) != 0;
|
||||
PRBool wrapBidi = (aFlags & TEXT_IS_RTL) != 0;
|
||||
if (wrapBidi) {
|
||||
AppendDirectionalIndicator(aParams->mFlags, utf16);
|
||||
AppendDirectionalIndicator(aFlags, utf16);
|
||||
}
|
||||
AppendASCIItoUTF16(cString, utf16);
|
||||
if (wrapBidi) {
|
||||
utf16.Append('.');
|
||||
utf16.Append(UNICODE_PDF);
|
||||
}
|
||||
return MakeTextRunInternal(utf16.get(), utf16.Length(), wrapBidi, aParams);
|
||||
MakeTextRunInternal(utf16.get(), utf16.Length(), wrapBidi, textRun);
|
||||
return textRun;
|
||||
}
|
||||
|
||||
gfxAtsuiFont*
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxFontMissingGlyphs.h"
|
||||
#include "nsMathUtils.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "gfxFontTest.h"
|
||||
@ -518,61 +519,37 @@ gfxFontGroup::FindGenericFontFromStyle(FontCreationCallback fc,
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
gfxFontGroup::GetSpecialStringTextRun(SpecialString aString,
|
||||
gfxTextRun *aTemplate)
|
||||
gfxFontGroup::MakeEmptyTextRun(const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
NS_ASSERTION(aString <= gfxFontGroup::STRING_MAX,
|
||||
"Bad special string index");
|
||||
aFlags |= TEXT_IS_8BIT | TEXT_IS_ASCII | TEXT_IS_PERSISTENT;
|
||||
return new gfxTextRun(aParams, nsnull, 0, this, aFlags);
|
||||
}
|
||||
|
||||
if (mSpecialStrings[aString] &&
|
||||
mSpecialStrings[aString]->GetAppUnitsPerDevUnit() ==
|
||||
aTemplate->GetAppUnitsPerDevUnit())
|
||||
return mSpecialStrings[aString];
|
||||
|
||||
static const PRUnichar unicodeHyphen = 0x2010;
|
||||
static const PRUnichar unicodeEllipsis = 0x2026;
|
||||
gfxTextRun *
|
||||
gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
aFlags |= TEXT_IS_8BIT | TEXT_IS_ASCII | TEXT_IS_PERSISTENT;
|
||||
static const PRUint8 space = ' ';
|
||||
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
nsnull, nsnull, nsnull, nsnull, nsnull, 0,
|
||||
aTemplate->GetAppUnitsPerDevUnit(), TEXT_IS_PERSISTENT
|
||||
};
|
||||
gfxTextRun* textRun;
|
||||
gfxFont *font = GetFontAt(0);
|
||||
PRUint32 spaceGlyph = font->GetSpaceGlyph();
|
||||
float spaceWidth = font->GetMetrics().spaceWidth;
|
||||
PRUint32 spaceWidthAppUnits = NS_lroundf(spaceWidth*aParams->mAppUnitsPerDevUnit);
|
||||
if (!spaceGlyph ||
|
||||
!gfxTextRun::CompressedGlyph::IsSimpleGlyphID(spaceGlyph) ||
|
||||
!gfxTextRun::CompressedGlyph::IsSimpleAdvance(spaceWidthAppUnits))
|
||||
return MakeTextRun(&space, 1, aParams, aFlags);
|
||||
|
||||
switch (aString) {
|
||||
case STRING_HYPHEN:
|
||||
textRun = MakeTextRun(&unicodeHyphen, 1, ¶ms);
|
||||
break;
|
||||
case STRING_ELLIPSIS:
|
||||
textRun = MakeTextRun(&unicodeEllipsis, 1, ¶ms);
|
||||
break;
|
||||
default:
|
||||
case STRING_SPACE:
|
||||
textRun = MakeTextRun(&space, 1, ¶ms);
|
||||
break;
|
||||
}
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
textRun = new gfxTextRun(aParams, &space, 1, this, aFlags);
|
||||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
if (textRun->CountMissingGlyphs() > 0) {
|
||||
static const PRUint8 ASCIIEllipsis[] = {'.', '.', '.'};
|
||||
static const PRUint8 ASCIIHyphen = '-';
|
||||
|
||||
switch (aString) {
|
||||
case STRING_ELLIPSIS:
|
||||
textRun = MakeTextRun(ASCIIEllipsis, NS_ARRAY_LENGTH(ASCIIEllipsis), ¶ms);
|
||||
break;
|
||||
case STRING_HYPHEN:
|
||||
textRun = MakeTextRun(&ASCIIHyphen, 1, ¶ms);
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("This font doesn't support the space character? That's messed up");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mSpecialStrings[aString] = textRun;
|
||||
return textRun;
|
||||
if (NS_FAILED(textRun->AddGlyphRun(font, 0)))
|
||||
return nsnull;
|
||||
gfxTextRun::CompressedGlyph g;
|
||||
g.SetSimpleGlyph(spaceWidthAppUnits, spaceGlyph);
|
||||
textRun->SetCharacterGlyph(0, g);
|
||||
return textRun.forget();
|
||||
}
|
||||
|
||||
gfxFontStyle::gfxFontStyle(PRUint8 aStyle, PRUint8 aVariant,
|
||||
@ -637,20 +614,84 @@ gfxTextRun::GlyphRunIterator::NextRun() {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
gfxTextRun::gfxTextRun(gfxTextRunFactory::Parameters *aParams,
|
||||
PRUint32 aLength)
|
||||
gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void *aText,
|
||||
PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags)
|
||||
: mUserData(aParams->mUserData),
|
||||
mFontGroup(aFontGroup),
|
||||
mAppUnitsPerDevUnit(aParams->mAppUnitsPerDevUnit),
|
||||
mFlags(aParams->mFlags),
|
||||
mCharacterCount(aLength)
|
||||
mFlags(aFlags), mCharacterCount(aLength)
|
||||
{
|
||||
NS_ADDREF(mFontGroup);
|
||||
if (aParams->mSkipChars) {
|
||||
mSkipChars.TakeFrom(aParams->mSkipChars);
|
||||
}
|
||||
mCharacterGlyphs = new CompressedGlyph[aLength];
|
||||
if (mCharacterGlyphs) {
|
||||
memset(mCharacterGlyphs, 0, sizeof(CompressedGlyph)*aLength);
|
||||
if (aLength > 0) {
|
||||
mCharacterGlyphs = new CompressedGlyph[aLength];
|
||||
if (mCharacterGlyphs) {
|
||||
memset(mCharacterGlyphs, 0, sizeof(CompressedGlyph)*aLength);
|
||||
}
|
||||
}
|
||||
if (mFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
|
||||
mText.mSingle = NS_STATIC_CAST(const PRUint8 *, aText);
|
||||
} else {
|
||||
mText.mDouble = NS_STATIC_CAST(const PRUnichar *, aText);
|
||||
}
|
||||
}
|
||||
|
||||
gfxTextRun::~gfxTextRun()
|
||||
{
|
||||
if (!(mFlags & gfxTextRunFactory::TEXT_IS_PERSISTENT)) {
|
||||
if (mFlags & gfxTextRunFactory::TEXT_IS_8BIT) {
|
||||
delete[] mText.mSingle;
|
||||
} else {
|
||||
delete[] mText.mDouble;
|
||||
}
|
||||
}
|
||||
NS_RELEASE(mFontGroup);
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
gfxTextRun::Clone(const gfxTextRunFactory::Parameters *aParams, const void *aText,
|
||||
PRUint32 aLength, gfxFontGroup *aFontGroup, PRUint32 aFlags)
|
||||
{
|
||||
if (!mCharacterGlyphs)
|
||||
return nsnull;
|
||||
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
textRun = new gfxTextRun(aParams, aText, aLength, aFontGroup, aFlags);
|
||||
if (!textRun || !textRun->mCharacterGlyphs)
|
||||
return nsnull;
|
||||
|
||||
PRUint32 i;
|
||||
for (i = 0; i < mGlyphRuns.Length(); ++i) {
|
||||
if (NS_FAILED(textRun->AddGlyphRun(mGlyphRuns[i].mFont,
|
||||
mGlyphRuns[i].mCharacterOffset)))
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
CompressedGlyph g = mCharacterGlyphs[i];
|
||||
g.SetCanBreakBefore(PR_FALSE);
|
||||
textRun->mCharacterGlyphs[i] = g;
|
||||
}
|
||||
|
||||
if (mDetailedGlyphs) {
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
DetailedGlyph *details = mDetailedGlyphs[i];
|
||||
if (details) {
|
||||
PRUint32 glyphCount = 1;
|
||||
while (!details[glyphCount - 1].mIsLastGlyph) {
|
||||
++glyphCount;
|
||||
}
|
||||
DetailedGlyph *dest = textRun->AllocateDetailedGlyphs(i, glyphCount);
|
||||
if (!dest)
|
||||
return nsnull;
|
||||
memcpy(dest, details, sizeof(DetailedGlyph)*glyphCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return textRun.forget();
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -1368,7 +1409,6 @@ gfxTextRun::GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
|
||||
PRBool
|
||||
gfxTextRun::SetLineBreaks(PRUint32 aStart, PRUint32 aLength,
|
||||
PRBool aLineBreakBefore, PRBool aLineBreakAfter,
|
||||
PropertyProvider *aProvider,
|
||||
gfxFloat *aAdvanceWidthDelta)
|
||||
{
|
||||
// Do nothing because our shaping does not currently take linebreaks into
|
||||
|
@ -94,6 +94,8 @@
|
||||
|
||||
#define FLOAT_PANGO_SCALE ((gfxFloat)PANGO_SCALE)
|
||||
|
||||
#define IS_MISSING_GLYPH(g) (((g) & 0x10000000) || (g) == 0x0FFFFFFF)
|
||||
|
||||
static PangoLanguage *GetPangoLanguage(const nsACString& aLangGroup);
|
||||
static void GetMozLanguage(const PangoLanguage *aLang, nsACString &aMozLang);
|
||||
|
||||
@ -396,7 +398,7 @@ gfxPangoFont::RealizeFont(PRBool force)
|
||||
return;
|
||||
|
||||
gfxSize isz, lsz;
|
||||
GetSize("x", 1, isz, lsz);
|
||||
GetSize('x', isz, lsz);
|
||||
gfxFloat aspect = isz.height / GetStyle()->size;
|
||||
mAdjustedSize =
|
||||
PR_MAX(NS_round(GetStyle()->size*(GetStyle()->sizeAdjust/aspect)), 1.0);
|
||||
@ -419,12 +421,13 @@ gfxPangoFont::RealizeXftFont(PRBool force)
|
||||
}
|
||||
|
||||
void
|
||||
gfxPangoFont::GetSize(const char *aCharString, PRUint32 aLength, gfxSize& inkSize, gfxSize& logSize)
|
||||
gfxPangoFont::GetSize(char aChar, gfxSize& inkSize, gfxSize& logSize,
|
||||
PRUint32 *aGlyphID)
|
||||
{
|
||||
RealizeFont();
|
||||
|
||||
PangoAttrList *al = pango_attr_list_new();
|
||||
GList *items = pango_itemize(mPangoCtx, aCharString, 0, aLength, al, NULL);
|
||||
GList *items = pango_itemize(mPangoCtx, &aChar, 0, 1, al, NULL);
|
||||
pango_attr_list_unref(al);
|
||||
|
||||
if (!items || g_list_length(items) != 1)
|
||||
@ -433,7 +436,17 @@ gfxPangoFont::GetSize(const char *aCharString, PRUint32 aLength, gfxSize& inkSiz
|
||||
PangoItem *item = (PangoItem*) items->data;
|
||||
|
||||
PangoGlyphString *glstr = pango_glyph_string_new();
|
||||
pango_shape (aCharString, aLength, &(item->analysis), glstr);
|
||||
pango_shape (&aChar, 1, &(item->analysis), glstr);
|
||||
|
||||
if (aGlyphID) {
|
||||
*aGlyphID = 0;
|
||||
if (glstr->num_glyphs == 1) {
|
||||
PangoGlyph glyph = glstr->glyphs[0].glyph;
|
||||
if (!IS_MISSING_GLYPH(glyph)) {
|
||||
*aGlyphID = glyph;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PangoRectangle ink_rect, log_rect;
|
||||
pango_glyph_string_extents (glstr, item->analysis.font, &ink_rect, &log_rect);
|
||||
@ -464,6 +477,7 @@ gfxPangoFont::GetMetrics()
|
||||
return mMetrics;
|
||||
|
||||
RealizeFont();
|
||||
mSpaceGlyph = 0; // in case we error out below
|
||||
|
||||
PangoAttrList *al = pango_attr_list_new();
|
||||
GList *items = pango_itemize(mPangoCtx, "a", 0, 1, al, NULL);
|
||||
@ -508,12 +522,12 @@ gfxPangoFont::GetMetrics()
|
||||
mMetrics.maxAdvance = xftFont->max_advance_width;
|
||||
|
||||
gfxSize isz, lsz;
|
||||
GetSize(" ", 1, isz, lsz);
|
||||
GetSize(' ', isz, lsz, &mSpaceGlyph);
|
||||
mMetrics.spaceWidth = lsz.width;
|
||||
|
||||
// XXX do some FcCharSetHasChar work here to make sure
|
||||
// we have an "x"
|
||||
GetSize("x", 1, isz, lsz);
|
||||
GetSize('x', isz, lsz);
|
||||
mMetrics.xHeight = isz.height;
|
||||
mMetrics.aveCharWidth = isz.width;
|
||||
|
||||
@ -585,9 +599,9 @@ gfxPangoFont::GetMetrics()
|
||||
mMetrics.maxAdvance = pango_font_metrics_get_approximate_char_width(pfm) / FLOAT_PANGO_SCALE; // XXX
|
||||
|
||||
gfxSize isz, lsz;
|
||||
GetSize(" ", 1, isz, lsz);
|
||||
GetSize(' ', isz, lsz, &mSpaceGlyph);
|
||||
mMetrics.spaceWidth = lsz.width;
|
||||
GetSize("x", 1, isz, lsz);
|
||||
GetSize('x', isz, lsz);
|
||||
mMetrics.xHeight = isz.height;
|
||||
|
||||
mMetrics.aveCharWidth = pango_font_metrics_get_approximate_char_width(pfm) / FLOAT_PANGO_SCALE;
|
||||
@ -709,15 +723,15 @@ static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString
|
||||
|
||||
gfxTextRun *
|
||||
gfxPangoFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
Parameters *aParams)
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
aParams->mFlags |= TEXT_IS_8BIT;
|
||||
gfxTextRun *run = new gfxTextRun(aParams, aLength);
|
||||
NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set");
|
||||
gfxTextRun *run = new gfxTextRun(aParams, aString, aLength, this, aFlags);
|
||||
if (!run)
|
||||
return nsnull;
|
||||
|
||||
PRBool isRTL = run->IsRightToLeft();
|
||||
if ((aParams->mFlags & TEXT_IS_ASCII) && !isRTL) {
|
||||
if ((aFlags & TEXT_IS_ASCII) && !isRTL) {
|
||||
// We don't need to send an override character here, the characters must be all
|
||||
// LTR
|
||||
const gchar *utf8Chars = NS_REINTERPRET_CAST(const gchar*, aString);
|
||||
@ -739,9 +753,9 @@ gfxPangoFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
|
||||
gfxTextRun *
|
||||
gfxPangoFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
Parameters *aParams)
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
gfxTextRun *run = new gfxTextRun(aParams, aLength);
|
||||
gfxTextRun *run = new gfxTextRun(aParams, aString, aLength, this, aFlags);
|
||||
if (!run)
|
||||
return nsnull;
|
||||
|
||||
@ -891,8 +905,6 @@ gfxPangoFont::Measure(gfxTextRun *aTextRun,
|
||||
return GetPangoMetrics(&glyphs, GetPangoFont(), aTextRun->GetAppUnitsPerDevUnit(), clusterCount);
|
||||
}
|
||||
|
||||
#define IS_MISSING_GLYPH(g) (((g) & 0x10000000) || (g) == 0x0FFFFFFF)
|
||||
|
||||
static cairo_scaled_font_t*
|
||||
CreateScaledFont(cairo_t *aCR, cairo_matrix_t *aCTM, PangoFont *aPangoFont)
|
||||
{
|
||||
|
@ -133,22 +133,17 @@ gfxTextRunCache::GetOrMakeTextRun(gfxContext *aContext, gfxFontGroup *aFontGroup
|
||||
PRUint32 aAppUnitsPerDevUnit, PRBool aIsRTL,
|
||||
PRBool aEnableSpacing, PRBool *aCallerOwns)
|
||||
{
|
||||
gfxSkipChars skipChars;
|
||||
// Choose pessimistic flags since we don't want to bother analyzing the string
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
aContext, nsnull, nsnull, &skipChars, nsnull, 0, aAppUnitsPerDevUnit,
|
||||
ComputeFlags(aIsRTL, aEnableSpacing)
|
||||
aContext, nsnull, nsnull, nsnull, 0, aAppUnitsPerDevUnit
|
||||
};
|
||||
|
||||
if (IsAscii(aString, aLength))
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_IS_ASCII;
|
||||
// else if (Is8Bit(aString, aLength))
|
||||
// params.mFlags |= gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
|
||||
if (!(params.mFlags & gfxTextRunFactory::TEXT_IS_ASCII)) {
|
||||
PRUint32 flags = ComputeFlags(aIsRTL, aEnableSpacing);
|
||||
if (IsAscii(aString, aLength)) {
|
||||
flags |= gfxTextRunFactory::TEXT_IS_ASCII;
|
||||
} else {
|
||||
for (PRUint32 i = 0; i < aLength; ++i) {
|
||||
if (NS_IS_HIGH_SURROGATE(aString[i])) {
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_HAS_SURROGATES;
|
||||
flags |= gfxTextRunFactory::TEXT_HAS_SURROGATES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -176,9 +171,12 @@ gfxTextRunCache::GetOrMakeTextRun(gfxContext *aContext, gfxFontGroup *aFontGroup
|
||||
tr->SetContext(aContext);
|
||||
}
|
||||
} else {
|
||||
tr = aFontGroup->MakeTextRun(aString, aLength, ¶ms);
|
||||
entry = new TextRunEntry(tr);
|
||||
key.Realize();
|
||||
// Text is persistent since it's in the key, which will live as
|
||||
// long as this textrun.
|
||||
tr = aFontGroup->MakeTextRun(key.GetRealString(), aLength, ¶ms,
|
||||
flags | gfxTextRunFactory::TEXT_IS_PERSISTENT);
|
||||
entry = new TextRunEntry(tr);
|
||||
mHashTableUTF16.Put(key, entry);
|
||||
}
|
||||
}
|
||||
@ -188,11 +186,11 @@ gfxTextRunCache::GetOrMakeTextRun(gfxContext *aContext, gfxFontGroup *aFontGroup
|
||||
} else {
|
||||
// Textrun is not in the cache for some reason.
|
||||
*aCallerOwns = PR_TRUE;
|
||||
tr = aFontGroup->MakeTextRun(aString, aLength, ¶ms);
|
||||
}
|
||||
if (tr) {
|
||||
// We don't want to have to reconstruct the string
|
||||
tr->RememberText(aString, aLength);
|
||||
PRUnichar *newStr = new PRUnichar[aLength];
|
||||
if (newStr) {
|
||||
memcpy(newStr, aString, sizeof(PRUnichar)*aLength);
|
||||
tr = aFontGroup->MakeTextRun(aString, aLength, ¶ms, flags);
|
||||
}
|
||||
}
|
||||
|
||||
return tr;
|
||||
@ -204,16 +202,13 @@ gfxTextRunCache::GetOrMakeTextRun(gfxContext *aContext, gfxFontGroup *aFontGroup
|
||||
PRUint32 aAppUnitsPerDevUnit, PRBool aIsRTL,
|
||||
PRBool aEnableSpacing, PRBool *aCallerOwns)
|
||||
{
|
||||
gfxSkipChars skipChars;
|
||||
// Choose pessimistic flags since we don't want to bother analyzing the string
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
aContext, nsnull, nsnull, &skipChars, nsnull, 0, aAppUnitsPerDevUnit,
|
||||
ComputeFlags(aIsRTL, aEnableSpacing)
|
||||
aContext, nsnull, nsnull, nsnull, 0, aAppUnitsPerDevUnit
|
||||
};
|
||||
PRUint32 flags = ComputeFlags(aIsRTL, aEnableSpacing) | gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
if (IsAscii(aString, aLength))
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_IS_ASCII;
|
||||
else
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
flags |= gfxTextRunFactory::TEXT_IS_ASCII;
|
||||
|
||||
const PRUint8 *str = reinterpret_cast<const PRUint8*>(aString);
|
||||
|
||||
@ -239,9 +234,13 @@ gfxTextRunCache::GetOrMakeTextRun(gfxContext *aContext, gfxFontGroup *aFontGroup
|
||||
tr->SetContext(aContext);
|
||||
}
|
||||
} else {
|
||||
tr = aFontGroup->MakeTextRun(str, aLength, ¶ms);
|
||||
entry = new TextRunEntry(tr);
|
||||
key.Realize();
|
||||
// Text is persistent since it's in the key, which will live as
|
||||
// long as this textrun.
|
||||
tr = aFontGroup->MakeTextRun(reinterpret_cast<const PRUint8 *>(key.GetRealString()),
|
||||
aLength, ¶ms,
|
||||
flags | gfxTextRunFactory::TEXT_IS_PERSISTENT);
|
||||
entry = new TextRunEntry(tr);
|
||||
mHashTableASCII.Put(key, entry);
|
||||
}
|
||||
}
|
||||
@ -251,11 +250,11 @@ gfxTextRunCache::GetOrMakeTextRun(gfxContext *aContext, gfxFontGroup *aFontGroup
|
||||
} else {
|
||||
// Textrun is not in the cache for some reason.
|
||||
*aCallerOwns = PR_TRUE;
|
||||
tr = aFontGroup->MakeTextRun(str, aLength, ¶ms);
|
||||
}
|
||||
if (tr) {
|
||||
// We don't want to have to reconstruct the string
|
||||
tr->RememberText(str, aLength);
|
||||
PRUint8 *newStr = new PRUint8[aLength];
|
||||
if (newStr) {
|
||||
memcpy(newStr, str, aLength);
|
||||
tr = aFontGroup->MakeTextRun(newStr, aLength, ¶ms, flags);
|
||||
}
|
||||
}
|
||||
|
||||
return tr;
|
||||
|
@ -382,6 +382,16 @@ gfxWindowsFont::ComputeMetrics()
|
||||
GetTextExtentPoint32(dc, " ", 1, &size);
|
||||
mMetrics->spaceWidth = ROUND(size.cx);
|
||||
|
||||
mSpaceGlyph = 0;
|
||||
if (metrics.tmPitchAndFamily & TMPF_TRUETYPE) {
|
||||
WORD glyph;
|
||||
DWORD ret = GetGlyphIndicesA(dc, " ", 1, &glyph,
|
||||
GGI_MARK_NONEXISTING_GLYPHS);
|
||||
if (ret != GDI_ERROR && glyph != 0xFFFF) {
|
||||
mSpaceGlyph = glyph;
|
||||
}
|
||||
}
|
||||
|
||||
SelectObject(dc, oldFont);
|
||||
|
||||
ReleaseDC((HWND)nsnull, dc);
|
||||
@ -551,13 +561,13 @@ gfxWindowsFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
|
||||
gfxTextRun *
|
||||
gfxWindowsFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
Parameters *aParams)
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
// XXX comment out the assertion for now since it fires too much
|
||||
// NS_ASSERTION(!(aParams->mFlags & TEXT_NEED_BOUNDING_BOX),
|
||||
// "Glyph extents not yet supported");
|
||||
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aLength);
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aString, aLength, this, aFlags);
|
||||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
@ -579,10 +589,11 @@ gfxWindowsFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
|
||||
gfxTextRun *
|
||||
gfxWindowsFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
||||
Parameters *aParams)
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
{
|
||||
aParams->mFlags |= TEXT_IS_8BIT;
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aLength);
|
||||
NS_ASSERTION(aFlags & TEXT_IS_8BIT, "should be marked 8bit");
|
||||
|
||||
gfxTextRun *textRun = new gfxTextRun(aParams, aString, aLength, this, aFlags);
|
||||
if (!textRun)
|
||||
return nsnull;
|
||||
|
||||
|
@ -287,22 +287,22 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
ctx, nsnull, nsnull, nsnull, nsnull, 0, 60,
|
||||
gfxTextRunFactory::TEXT_IS_ASCII
|
||||
ctx, nsnull, nsnull, nsnull, 0, 60
|
||||
};
|
||||
PRUint32 flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
|
||||
if (test->isRTL) {
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_IS_RTL;
|
||||
flags |= gfxTextRunFactory::TEXT_IS_RTL;
|
||||
}
|
||||
PRUint32 length;
|
||||
if (test->stringType == S_ASCII) {
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_IS_ASCII;
|
||||
flags |= gfxTextRunFactory::TEXT_IS_ASCII | gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
length = strlen(test->string);
|
||||
textRun = fontGroup->MakeTextRun(NS_REINTERPRET_CAST(PRUint8*, test->string), length, ¶ms);
|
||||
textRun = fontGroup->MakeTextRun(NS_REINTERPRET_CAST(PRUint8*, test->string), length, ¶ms, flags);
|
||||
} else {
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case
|
||||
flags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case
|
||||
NS_ConvertUTF8toUTF16 str(nsDependentCString(test->string));
|
||||
length = str.Length();
|
||||
textRun = fontGroup->MakeTextRun(str.get(), length, ¶ms);
|
||||
textRun = fontGroup->MakeTextRun(str.get(), length, ¶ms, flags);
|
||||
}
|
||||
|
||||
gfxFontTestStore::NewStore();
|
||||
|
@ -110,19 +110,20 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
}
|
||||
}
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
ctx, nsnull, nsnull, nsnull, nsnull, 0, 60, 0
|
||||
ctx, nsnull, nsnull, nsnull, 0, 60
|
||||
};
|
||||
PRUint32 flags = gfxTextRunFactory::TEXT_IS_PERSISTENT;
|
||||
PRUint32 length;
|
||||
if (isASCII) {
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_IS_ASCII |
|
||||
gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
flags |= gfxTextRunFactory::TEXT_IS_ASCII |
|
||||
gfxTextRunFactory::TEXT_IS_8BIT;
|
||||
length = strlen(test->mString);
|
||||
textRun = fontGroup->MakeTextRun(NS_REINTERPRET_CAST(const PRUint8*, test->mString), length, ¶ms);
|
||||
textRun = fontGroup->MakeTextRun(NS_REINTERPRET_CAST(const PRUint8*, test->mString), length, ¶ms, flags);
|
||||
} else {
|
||||
params.mFlags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case
|
||||
flags |= gfxTextRunFactory::TEXT_HAS_SURROGATES; // just in case
|
||||
NS_ConvertUTF8toUTF16 str(nsDependentCString(test->mString));
|
||||
length = str.Length();
|
||||
textRun = fontGroup->MakeTextRun(str.get(), length, ¶ms);
|
||||
textRun = fontGroup->MakeTextRun(str.get(), length, ¶ms, flags);
|
||||
}
|
||||
|
||||
// Should we test drawing?
|
||||
|
@ -1352,14 +1352,14 @@ nsSVGGlyphFrame::GetTextRun(gfxContext *aCtx, const nsString &aText)
|
||||
|
||||
gfxTextRunFactory::Parameters params =
|
||||
{ aCtx, nsnull, nsnull,
|
||||
nsnull, nsnull, nsnull,
|
||||
1, // see note above
|
||||
0 };
|
||||
nsnull, nsnull,
|
||||
1 // see note above
|
||||
};
|
||||
|
||||
if (!mFontGroup)
|
||||
return nsnull;
|
||||
|
||||
return mFontGroup->MakeTextRun(aText.get(), aText.Length(), ¶ms);
|
||||
return mFontGroup->MakeTextRun(aText.get(), aText.Length(), ¶ms, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user