Bug 502906 part 1: eliminate backend-specific gfxFontGroup subclasses on Mac OS X. r=jdaggett

This commit is contained in:
Jonathan Kew 2009-10-07 16:26:58 +01:00
parent 2de2187247
commit 04d2aac3f3
21 changed files with 1290 additions and 1825 deletions

View File

@ -51,8 +51,6 @@
#include <Carbon/Carbon.h>
class gfxAtsuiFontGroup;
class MacOSFontEntry;
#define kLiGothicBadCharUnicode 0x775B // ATSUI failure on 10.6 (bug 532346)
@ -87,11 +85,6 @@ public:
virtual void SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID,
PRBool aNeedTight, gfxGlyphExtents *aExtents);
PRBool TestCharacterMap(PRUint32 aCh);
MacOSFontEntry* GetFontEntry();
PRBool Valid() { return mIsValid; }
protected:
const gfxFontStyle *mFontStyle;
@ -112,107 +105,14 @@ protected:
void InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef);
virtual void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength);
virtual PRBool SetupCairoFont(gfxContext *aContext);
};
class THEBES_API gfxAtsuiFontGroup : public gfxFontGroup {
public:
gfxAtsuiFontGroup(const nsAString& families,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet);
virtual ~gfxAtsuiFontGroup() {};
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
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
void MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
PRBool aWrapped, gfxTextRun *aTextRun);
gfxAtsuiFont* GetFontAt(PRInt32 aFontIndex) {
// If it turns out to be hard for all clients that cache font
// groups to call UpdateFontList at appropriate times, we could
// instead consider just calling UpdateFontList from someplace
// more central (such as here).
NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
"Whoever was caching this font group should have "
"called UpdateFontList on it");
return static_cast<gfxAtsuiFont*>(static_cast<gfxFont*>(mFonts[aFontIndex]));
}
PRBool HasFont(ATSFontRef aFontRef);
inline gfxAtsuiFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList,
PRUint32 aCh)
{
PRUint32 len = aFontList.Length();
for (PRUint32 i = 0; i < len; i++) {
gfxAtsuiFont* font = static_cast<gfxAtsuiFont*>(aFontList.ElementAt(i).get());
if (font->TestCharacterMap(aCh))
return font;
}
return nsnull;
}
// search through pref fonts for a character, return nsnull if no matching pref font
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
void UpdateFontList();
protected:
static PRBool FindATSFont(const nsAString& aName,
const nsACString& aGenericName,
void *closure);
PRUint32 GuessMaximumStringLength();
/**
* @param aRun the text run to fill in
* @param aString the complete text including all wrapper characters
* @param aLength the length of aString
* @param aLayoutStart the first character of aString that should be
* at the start of the ATSUI layout; this skips any wrapper character
* used to override direction
* @param aLayoutLength the length of the characters that should be
* in the ATSUI layout; this excludes any trailing wrapper character
* used to override direction
* @param aTrailingCharsToIgnore the number of trailing characters
* in the ATSUI layout that are not part of the text run
* (characters added to ensure correct RTL and kerning behaviour)
* @param aTextRunOffset the character offset in the textrun where
* the glyph data from the ATSUI layout should be copied
* @return true for success
*/
PRBool InitTextRun(gfxTextRun *aRun,
const PRUnichar *aString, PRUint32 aLength,
PRUint32 aLayoutStart, PRUint32 aLayoutLength,
PRUint32 aOffsetInTextRun, PRUint32 aLengthInTextRun);
/**
* Function to reinitialize our mFonts array and any other data
* that depends on mFonts.
*/
void InitFontList();
// cache the most recent pref font to avoid general pref font lookup
nsRefPtr<gfxFontFamily> mLastPrefFamily;
nsRefPtr<gfxAtsuiFont> mLastPrefFont;
eFontPrefLang mLastPrefLang; // lang group for last pref font
PRBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
eFontPrefLang mPageLang;
};
#endif /* not __LP64__ */
#endif /* GFX_ATSUIFONTS_H */

View File

@ -49,8 +49,6 @@
#include <Carbon/Carbon.h>
class gfxCoreTextFontGroup;
class MacOSFontEntry;
class gfxCoreTextFont : public gfxFont {
@ -101,14 +99,10 @@ public:
MacOSFontEntry* GetFontEntry();
PRBool Valid() {
return mIsValid;
}
// clean up static objects that may have been cached
static void Shutdown();
static CTFontRef CreateCTFontWithDisabledLigatures(ATSFontRef aFont, CGFloat aSize);
static CTFontRef CreateCTFontWithDisabledLigatures(ATSFontRef aFontRef, CGFloat aSize);
protected:
const gfxFontStyle *mFontStyle;
@ -131,6 +125,17 @@ protected:
void InitMetrics();
virtual void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength);
nsresult SetGlyphsFromRun(gfxTextRun *aTextRun,
CTRunRef aCTRun,
PRInt32 aStringOffset,
PRInt32 aLayoutStart,
PRInt32 aLayoutLength);
virtual PRBool SetupCairoFont(gfxContext *aContext);
static void CreateDefaultFeaturesDescriptor();
@ -147,83 +152,4 @@ protected:
static CTFontDescriptorRef sDisableLigaturesDescriptor;
};
class THEBES_API gfxCoreTextFontGroup : public gfxFontGroup {
public:
gfxCoreTextFontGroup(const nsAString& families,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet);
virtual ~gfxCoreTextFontGroup() {};
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
virtual gfxTextRun *MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const Parameters* aParams, PRUint32 aFlags);
virtual gfxTextRun *MakeTextRun(const PRUint8* aString, PRUint32 aLength,
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
void MakeTextRunInternal(const PRUnichar *aString, PRUint32 aLength,
PRBool aWrapped, gfxTextRun *aTextRun);
gfxCoreTextFont* GetFontAt(PRInt32 aFontIndex) {
return static_cast<gfxCoreTextFont*>(static_cast<gfxFont*>(mFonts[aFontIndex]));
}
PRBool HasFont(ATSFontRef aFontRef);
inline gfxCoreTextFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList,
PRUint32 aCh)
{
PRUint32 len = aFontList.Length();
for (PRUint32 i = 0; i < len; i++) {
gfxCoreTextFont* font = static_cast<gfxCoreTextFont*>(aFontList.ElementAt(i).get());
if (font->TestCharacterMap(aCh))
return font;
}
return nsnull;
}
// search through pref fonts for a character, return nsnull if no matching pref font
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
void UpdateFontList();
protected:
static PRBool FindCTFont(const nsAString& aName,
const nsACString& aGenericName,
void *closure);
/**
* @param aTextRun the text run to fill in
* @param aString the complete text including all wrapper characters
* @param aTotalLength the length of aString
* @param aLayoutStart the first "real" character of aString, skipping any dir override
* @param aLayoutLength the length of the characters that should be actually used
*/
void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aTotalLength,
PRUint32 aLayoutStart,
PRUint32 aLayoutLength);
nsresult SetGlyphsFromRun(gfxTextRun *aTextRun,
CTRunRef aCTRun,
const PRPackedBool *aUnmatched,
PRInt32 aLayoutStart,
PRInt32 aLayoutLength);
// cache the most recent pref font to avoid general pref font lookup
nsRefPtr<gfxFontFamily> mLastPrefFamily;
nsRefPtr<gfxCoreTextFont> mLastPrefFont;
eFontPrefLang mLastPrefLang; // lang group for last pref font
PRBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
eFontPrefLang mPageLang;
};
#endif /* GFX_CORETEXTFONTS_H */

View File

@ -53,6 +53,7 @@
#include "gfxRect.h"
#include "nsExpirationTracker.h"
#include "gfxFontConstants.h"
#include "gfxPlatform.h"
#ifdef DEBUG
#include <stdio.h>
@ -220,6 +221,8 @@ public:
const nsString& FamilyName();
already_AddRefed<gfxFont> GetOrMakeFont(const gfxFontStyle *aStyle, PRBool aNeedsBold);
nsString mName;
PRPackedBool mItalic : 1;
@ -261,6 +264,11 @@ protected:
return NS_ERROR_FAILURE; // all platform subclasses should reimplement this!
}
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold) {
NS_NOTREACHED("oops, somebody didn't override CreateFontInstance");
return nsnull;
}
gfxFontFamily *mFamily;
};
@ -663,6 +671,10 @@ protected:
public:
virtual ~gfxFont();
PRBool Valid() {
return mIsValid;
}
// options for the kind of bounding box to return from measurement
typedef enum {
LOOSE_INK_EXTENTS,
@ -852,6 +864,13 @@ public:
return mFontEntry->HasCharacter(ch);
}
virtual void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength) {
NS_NOTREACHED("oops, somebody didn't override InitTextRun");
}
protected:
nsRefPtr<gfxFontEntry> mFontEntry;
@ -1685,10 +1704,9 @@ private:
};
class THEBES_API gfxFontGroup : public gfxTextRunFactory {
protected:
public:
gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet = nsnull);
public:
virtual ~gfxFontGroup();
virtual gfxFont *GetFontAt(PRInt32 i) {
@ -1715,7 +1733,7 @@ public:
const gfxFontStyle *GetStyle() const { return &mStyle; }
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle) = 0;
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
/**
* The listed characters should not be passed in to MakeTextRun and should
@ -1741,7 +1759,7 @@ public:
* This calls FetchGlyphExtents on the textrun.
*/
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags) = 0;
const Parameters *aParams, PRUint32 aFlags);
/**
* Make a textrun for a given string.
* If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
@ -1749,7 +1767,7 @@ public:
* This calls FetchGlyphExtents on the textrun.
*/
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags) = 0;
const Parameters *aParams, PRUint32 aFlags);
/* helper function for splitting font families on commas and
* calling a function for each family to fill the mFonts array
@ -1763,6 +1781,12 @@ public:
void *closure);
PRBool ForEachFont(FontCreationCallback fc, void *closure);
/**
* Check whether a given font (specified by its gfxFontEntry)
* is already in the fontgroup's list of actual fonts
*/
PRBool HasFont(const gfxFontEntry *aFontEntry);
const nsString& GetFamilies() { return mFamilies; }
// This returns the preferred underline for this font group.
@ -1779,9 +1803,10 @@ public:
already_AddRefed<gfxFont> FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFont *aPrevMatchedFont);
virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh) { return nsnull; }
// search through pref fonts for a character, return nsnull if no matching pref font
virtual already_AddRefed<gfxFont> WhichPrefFontSupportsChar(PRUint32 aCh);
virtual already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh) { return nsnull; }
virtual already_AddRefed<gfxFont> WhichSystemFontSupportsChar(PRUint32 aCh);
void ComputeRanges(nsTArray<gfxTextRange>& mRanges, const PRUnichar *aString, PRUint32 begin, PRUint32 end);
@ -1795,7 +1820,7 @@ public:
// If there is a user font set, check to see whether the font list or any
// caches need updating.
virtual void UpdateFontList() { }
virtual void UpdateFontList();
protected:
nsString mFamilies;
@ -1806,6 +1831,13 @@ protected:
gfxUserFontSet* mUserFontSet;
PRUint64 mCurrGeneration; // track the current user font set generation, rebuild font list if needed
// cache the most recent pref font to avoid general pref font lookup
nsRefPtr<gfxFontFamily> mLastPrefFamily;
nsRefPtr<gfxFont> mLastPrefFont;
eFontPrefLang mLastPrefLang; // lang group for last pref font
PRBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
eFontPrefLang mPageLang;
// Used for construction/destruction. Not intended to change the font set
// as invalidation of font lists and caches is not considered.
void SetUserFontSet(gfxUserFontSet *aUserFontSet);
@ -1815,6 +1847,10 @@ protected:
// you should call this with the *first* bad font.
void InitMetricsForBadFont(gfxFont* aBadFont);
void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aLength);
/* If aResolveGeneric is true, then CSS/Gecko generic family names are
* replaced with preferred fonts.
*
@ -1832,10 +1868,14 @@ protected:
static PRBool FontResolverProc(const nsAString& aName, void *aClosure);
static PRBool FindPlatformFont(const nsAString& aName,
const nsACString& aGenericName,
void *closure);
inline gfxFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList, PRUint32 aCh) {
PRUint32 len = aFontList.Length();
for (PRUint32 i = 0; i < len; i++) {
gfxFont* font = aFontList.ElementAt(i).get();
gfxFont* font = aFontList.ElementAt(i);
if (font && font->HasCharacter(aCh))
return font;
}

View File

@ -557,6 +557,43 @@ public:
return (ch == 0xFFFD);
}
// Font code may want to know if there is the potential for bidi behavior
// to be triggered by any of the characters in a text run; this can be
// used to test that possibility.
enum {
kUnicodeBidiScriptsStart = 0x0590,
kUnicodeBidiScriptsEnd = 0x08FF,
kUnicodeBidiPresentationStart = 0xFB1D,
kUnicodeBidiPresentationEnd = 0xFEFC,
kUnicodeFirstHighSurrogateBlock = 0xD800,
kUnicodeRLM = 0x200F,
kUnicodeRLE = 0x202B,
kUnicodeRLO = 0x202E
};
static inline PRBool PotentialRTLChar(PRUnichar aCh) {
if (aCh >= kUnicodeBidiScriptsStart && aCh <= kUnicodeBidiScriptsEnd)
// bidi scripts Hebrew, Arabic, Syriac, Thaana, N'Ko are all encoded together
return PR_TRUE;
if (aCh == kUnicodeRLM || aCh == kUnicodeRLE || aCh == kUnicodeRLO)
// directional controls that trigger bidi layout
return PR_TRUE;
if (aCh >= kUnicodeBidiPresentationStart &&
aCh <= kUnicodeBidiPresentationEnd)
// presentation forms of Arabic and Hebrew letters
return PR_TRUE;
if ((aCh & 0xFF00) == kUnicodeFirstHighSurrogateBlock)
// surrogate that could be part of a bidi supplementary char
// (Cypriot, Aramaic, Phoenecian, etc)
return PR_TRUE;
// otherwise we know this char cannot trigger bidi reordering
return PR_FALSE;
}
static PRUint8 CharRangeBit(PRUint32 ch);
// for a given font list pref name, set up a list of font names

View File

@ -61,6 +61,7 @@ class gfxUserFontSet;
class gfxFontEntry;
class gfxProxyFontEntry;
class gfxPlatformFontList;
class gfxTextRun;
class nsIURI;
// pref lang id's for font prefs
@ -150,6 +151,8 @@ public:
* Font bits
*/
virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
/**
* Fill aListOfFonts with the results of querying the list of font names
* that correspond to the given language group or generic font family
@ -231,6 +234,9 @@ public:
void GetPrefFonts(const char *aLangGroup, nsString& array, PRBool aAppendUnicode = PR_TRUE);
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
void GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
/**
* Iterate over pref fonts given a list of lang groups. For a single lang
* group, multiple pref fonts are possible. If error occurs, returns PR_FALSE,
@ -248,6 +254,9 @@ public:
// convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW ==> "zh-TW")
static const char* GetPrefLangName(eFontPrefLang aLang);
// map a Unicode range (based on char code) to a font language for Preferences
static eFontPrefLang GetFontPrefLangFor(PRUint8 aUnicodeRange);
// returns true if a pref lang is CJK
static PRBool IsLangCJK(eFontPrefLang aLang);
@ -318,6 +327,9 @@ protected:
gfxPlatform() { }
virtual ~gfxPlatform();
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
/**
* Initialize any needed display metrics (such as DPI)
*/
@ -327,6 +339,8 @@ protected:
private:
virtual qcms_profile* GetPlatformCMSOutputProfile();
nsTArray<PRUint32> mCJKPrefLangs;
nsCOMPtr<nsIObserver> overrideObserver;
};

View File

@ -91,9 +91,6 @@ public:
nsTArray<nsString>& aListOfFonts);
nsresult UpdateFontList();
// in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
void GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
// Returns the OS X version as returned from Gestalt(gestaltSystemVersion, ...)
// Ex: Mac OS X 10.4.x ==> 0x104x
PRInt32 OSXVersion();
@ -110,21 +107,14 @@ public:
#endif
// record Unicode cluster boundaries in the text run
static void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
// map a Unicode range (based on char code) to a font language for Preferences
static eFontPrefLang GetFontPrefLangFor(PRUint8 aUnicodeRange);
virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
private:
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen,
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
virtual qcms_profile* GetPlatformCMSOutputProfile();
// read in the pref value for the lower threshold on font anti-aliasing
static PRUint32 ReadAntiAliasingThreshold();
nsTArray<PRUint32> mCJKPrefLangs;
PRInt32 mOSXVersion;
PRUint32 mFontAntiAliasingThreshold;

View File

@ -242,6 +242,8 @@ public:
virtual ~gfxProxyFontEntry();
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
PRPackedBool mIsLoading;
nsTArray<gfxFontFaceSrc> mSrcList;
PRUint32 mSrcIndex; // index of loading src item

View File

@ -95,6 +95,11 @@ public:
PRBool IsValid() { GetMetrics(); return mIsValid; }
GDIFontEntry *GetFontEntry();
virtual void InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength);
static already_AddRefed<gfxWindowsFont>
GetOrMakeFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle,
PRBool aNeedsBold = PR_FALSE);

View File

@ -134,6 +134,10 @@ public:
*/
virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
#ifndef MOZ_FT2_FONTS
virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
#endif
/* Find a FontFamily/FontEntry object that represents a font on your system given a name */
gfxFontFamily *FindFontFamily(const nsAString& aName);
gfxFontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@
#include "gfxPlatformFontList.h"
#include "nsMathUtils.h"
#include "nsBidiUtils.h"
#include "nsUnicodeRange.h"
#include "cairo.h"
#include "gfxFontTest.h"
@ -109,6 +110,27 @@ const nsString& gfxFontEntry::FamilyName()
return mFamily->Name();
}
already_AddRefed<gfxFont>
gfxFontEntry::GetOrMakeFont(const gfxFontStyle *aStyle, PRBool aNeedsBold)
{
// the font entry name is the psname, not the family name
nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(Name(), aStyle);
if (!font) {
gfxFont *newFont = CreateFontInstance(aStyle, aNeedsBold);
if (!newFont)
return nsnull;
if (!newFont->Valid()) {
delete newFont;
return nsnull;
}
font = newFont;
gfxFontCache::GetCache()->AddNew(font);
}
gfxFont *f = nsnull;
font.swap(f);
return f;
}
// we consider faces with mStandardFace == PR_TRUE to be "greater than" those with PR_FALSE,
// because during style matching, later entries will replace earlier ones
class FontEntryStandardFaceComparator {
@ -1327,6 +1349,83 @@ gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyl
{
mUserFontSet = nsnull;
SetUserFontSet(aUserFontSet);
// "#if" to be removed once all platforms are moved to gfxPlatformFontList interface
// and subclasses of gfxFontGroup eliminated
#if defined(XP_MACOSX) || defined(XP_WIN)
ForEachFont(FindPlatformFont, this);
if (mFonts.Length() == 0) {
PRBool needsBold;
gfxFontEntry *defaultFont =
gfxPlatformFontList::PlatformFontList()->GetDefaultFont(aStyle, needsBold);
NS_ASSERTION(defaultFont, "invalid default font returned by GetDefaultFont");
nsRefPtr<gfxFont> font = defaultFont->GetOrMakeFont(aStyle, needsBold);
if (font) {
mFonts.AppendElement(font);
}
}
mPageLang = gfxPlatform::GetFontPrefLangFor(mStyle.langGroup.get());
if (!mStyle.systemFont) {
for (PRUint32 i = 0; i < mFonts.Length(); ++i) {
gfxFont* font = mFonts[i];
if (font->GetFontEntry()->mIsBadUnderlineFont) {
gfxFloat first = mFonts[0]->GetMetrics().underlineOffset;
gfxFloat bad = font->GetMetrics().underlineOffset;
mUnderlineOffset = PR_MIN(first, bad);
break;
}
}
}
#endif
}
PRBool
gfxFontGroup::FindPlatformFont(const nsAString& aName,
const nsACString& aGenericName,
void *aClosure)
{
gfxFontGroup *fontGroup = static_cast<gfxFontGroup*>(aClosure);
const gfxFontStyle *fontStyle = fontGroup->GetStyle();
PRBool needsBold;
gfxFontEntry *fe = nsnull;
// first, look up in the user font set
gfxUserFontSet *fs = fontGroup->GetUserFontSet();
if (fs) {
fe = fs->FindFontEntry(aName, *fontStyle, needsBold);
}
// nothing in the user font set ==> check system fonts
if (!fe) {
fe = gfxPlatformFontList::PlatformFontList()->
FindFontForFamily(aName, fontStyle, needsBold);
}
// add to the font group, unless it's already there
if (fe && !fontGroup->HasFont(fe)) {
nsRefPtr<gfxFont> font = fe->GetOrMakeFont(fontStyle, needsBold);
if (font) {
fontGroup->mFonts.AppendElement(font);
}
}
return PR_TRUE;
}
PRBool
gfxFontGroup::HasFont(const gfxFontEntry *aFontEntry)
{
for (PRUint32 i = 0; i < mFonts.Length(); ++i) {
if (mFonts.ElementAt(i)->GetFontEntry() == aFontEntry)
return PR_TRUE;
}
return PR_FALSE;
}
gfxFontGroup::~gfxFontGroup() {
@ -1334,6 +1433,11 @@ gfxFontGroup::~gfxFontGroup() {
SetUserFontSet(nsnull);
}
gfxFontGroup *
gfxFontGroup::Copy(const gfxFontStyle *aStyle)
{
return new gfxFontGroup(mFamilies, aStyle, mUserFontSet);
}
PRBool
gfxFontGroup::IsInvalidChar(PRUnichar ch) {
@ -1557,6 +1661,151 @@ gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, PRUint32 aFlags)
return textRun.forget();
}
#define UNICODE_LRO 0x202d
#define UNICODE_RLO 0x202e
#define UNICODE_PDF 0x202c
inline void
AppendDirectionalIndicatorStart(PRUint32 aFlags, nsAString& aString)
{
static const PRUnichar overrides[2] = { UNICODE_LRO, UNICODE_RLO };
aString.Append(overrides[(aFlags & gfxTextRunFactory::TEXT_IS_RTL) != 0]);
aString.Append(' ');
}
inline void
AppendDirectionalIndicatorEnd(PRBool aNeedDirection, nsAString& aString)
{
// append a space (always, for consistent treatment of last char,
// and a direction control if required (we skip this for 8-bit text,
// which is known to be unidirectional LTR, unless the direction was
// forced RTL via overrides)
aString.Append(' ');
if (!aNeedDirection)
return;
aString.Append('.');
aString.Append(UNICODE_PDF);
}
gfxTextRun *
gfxFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags)
{
NS_ASSERTION(aLength > 0, "should use MakeEmptyTextRun for zero-length text");
NS_ASSERTION(aFlags & TEXT_IS_8BIT, "should be marked 8bit");
gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
if (!textRun)
return nsnull;
nsDependentCSubstring cString(reinterpret_cast<const char*>(aString),
reinterpret_cast<const char*>(aString) + aLength);
nsAutoString utf16;
AppendASCIItoUTF16(cString, utf16);
InitTextRun(textRun, utf16.get(), utf16.Length());
textRun->FetchGlyphExtents(aParams->mContext);
return textRun;
}
gfxTextRun *
gfxFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags)
{
NS_ASSERTION(aLength > 0, "should use MakeEmptyTextRun for zero-length text");
gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
if (!textRun)
return nsnull;
gfxPlatform::GetPlatform()->SetupClusterBoundaries(textRun, aString);
InitTextRun(textRun, aString, aLength);
textRun->FetchGlyphExtents(aParams->mContext);
return textRun;
}
#define SMALL_GLYPH_RUN 128 // preallocated size of our auto arrays for per-glyph data;
// some testing indicates that 90%+ of glyph runs will fit
// without requiring a separate allocation
void
gfxFontGroup::InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aLength)
{
gfxFont *mainFont = mFonts[0].get();
PRUint32 runStart = 0;
nsAutoTArray<gfxTextRange,3> fontRanges;
ComputeRanges(fontRanges, aString, 0, aLength);
PRUint32 numRanges = fontRanges.Length();
nsAutoTArray<PRPackedBool,SMALL_GLYPH_RUN> unmatchedArray;
PRPackedBool *unmatched = NULL;
for (PRUint32 r = 0; r < numRanges; r++) {
const gfxTextRange& range = fontRanges[r];
PRUint32 matchedLength = range.Length();
gfxFont *matchedFont = (range.font ? range.font.get() : nsnull);
if (matchedFont) {
// create the glyph run for this range
aTextRun->AddGlyphRun(matchedFont, runStart, (matchedLength > 0));
// do glyph layout and record the resulting positioned glyphs in the run
matchedFont->InitTextRun(aTextRun, aString, runStart, matchedLength);
} else {
// no font available, so record missing glyph info instead
if (unmatched == NULL) {
if (unmatchedArray.SetLength(aLength)) {
unmatched = unmatchedArray.Elements();
::memset(unmatched, PR_FALSE, aLength*sizeof(PRPackedBool));
}
}
// create the glyph run before calling SetMissing Glyph
aTextRun->AddGlyphRun(mainFont, runStart, matchedLength);
for (PRUint32 index = runStart; index < runStart + matchedLength; index++) {
// Record the char code so we can draw a box with the Unicode value
if (NS_IS_HIGH_SURROGATE(aString[index]) &&
index + 1 < aLength &&
NS_IS_LOW_SURROGATE(aString[index+1])) {
aTextRun->SetMissingGlyph(index,
SURROGATE_TO_UCS4(aString[index],
aString[index+1]));
index++;
} else {
aTextRun->SetMissingGlyph(index, aString[index]);
}
}
// We have to remember the indices of unmatched chars to avoid overwriting
// their glyph (actually char code) data with the space glyph later,
// while we're retrieving actual glyph data from CoreText runs.
if (unmatched)
::memset(unmatched + runStart, PR_TRUE, matchedLength);
}
runStart += matchedLength;
}
// It's possible for CoreText to omit glyph runs if it decides they contain
// only invisibles (e.g., U+FEFF, see reftest 474417-1). In this case, we
// need to eliminate them from the glyph run array to avoid drawing "partial
// ligatures" with the wrong font.
aTextRun->SanitizeGlyphRuns();
// Is this actually necessary? Without it, gfxTextRun::CopyGlyphDataFrom may assert
// "Glyphruns not coalesced", but does that matter?
aTextRun->SortGlyphRuns();
}
already_AddRefed<gfxFont>
@ -1686,6 +1935,129 @@ gfxFontGroup::GetGeneration()
return mUserFontSet->GetGeneration();
}
void
gfxFontGroup::UpdateFontList()
{
// if user font set is set, check to see if font list needs updating
if (mUserFontSet && mCurrGeneration != GetGeneration()) {
// xxx - can probably improve this to detect when all fonts were found, so no need to update list
mFonts.Clear();
mUnderlineOffset = UNDERLINE_OFFSET_NOT_SET;
ForEachFont(FindPlatformFont, this);
mCurrGeneration = GetGeneration();
}
}
struct PrefFontCallbackData {
PrefFontCallbackData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamiliesArray)
: mPrefFamilies(aFamiliesArray)
{}
nsTArray<nsRefPtr<gfxFontFamily> >& mPrefFamilies;
static PRBool AddFontFamilyEntry(eFontPrefLang aLang, const nsAString& aName, void *aClosure)
{
PrefFontCallbackData *prefFontData = static_cast<PrefFontCallbackData*>(aClosure);
gfxFontFamily *family = gfxPlatformFontList::PlatformFontList()->FindFamily(aName);
if (family) {
prefFontData->mPrefFamilies.AppendElement(family);
}
return PR_TRUE;
}
};
already_AddRefed<gfxFont>
gfxFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
{
gfxFont *font;
// FindCharUnicodeRange only supports BMP character points and there are no non-BMP fonts in prefs
if (aCh > 0xFFFF)
return nsnull;
// get the pref font list if it hasn't been set up already
PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
eFontPrefLang charLang = gfxPlatform::GetPlatform()->GetFontPrefLangFor(unicodeRange);
// if the last pref font was the first family in the pref list, no need to recheck through a list of families
if (mLastPrefFont && charLang == mLastPrefLang &&
mLastPrefFirstFont && mLastPrefFont->HasCharacter(aCh)) {
font = mLastPrefFont;
NS_ADDREF(font);
return font;
}
// based on char lang and page lang, set up list of pref lang fonts to check
eFontPrefLang prefLangs[kMaxLenPrefLangList];
PRUint32 i, numLangs = 0;
gfxPlatform::GetPlatform()->GetLangPrefs(prefLangs, numLangs, charLang, mPageLang);
for (i = 0; i < numLangs; i++) {
nsAutoTArray<nsRefPtr<gfxFontFamily>, 5> families;
eFontPrefLang currentLang = prefLangs[i];
gfxPlatformFontList *fontList = gfxPlatformFontList::PlatformFontList();
// get the pref families for a single pref lang
if (!fontList->GetPrefFontFamilyEntries(currentLang, &families)) {
eFontPrefLang prefLangsToSearch[1] = { currentLang };
PrefFontCallbackData prefFontData(families);
gfxPlatform::ForEachPrefFont(prefLangsToSearch, 1, PrefFontCallbackData::AddFontFamilyEntry,
&prefFontData);
fontList->SetPrefFontFamilyEntries(currentLang, families);
}
// find the first pref font that includes the character
PRUint32 i, numPrefs;
numPrefs = families.Length();
for (i = 0; i < numPrefs; i++) {
// look up the appropriate face
gfxFontFamily *family = families[i];
if (!family) continue;
// if a pref font is used, it's likely to be used again in the same text run.
// the style doesn't change so the face lookup can be cached rather than calling
// GetOrMakeFont repeatedly. speeds up FindFontForChar lookup times for subsequent
// pref font lookups
if (family == mLastPrefFamily && mLastPrefFont->HasCharacter(aCh)) {
font = mLastPrefFont;
NS_ADDREF(font);
return font;
}
PRBool needsBold;
gfxFontEntry *fe = family->FindFontForStyle(mStyle, needsBold);
// if ch in cmap, create and return a gfxFont
if (fe && fe->TestCharacterMap(aCh)) {
nsRefPtr<gfxFont> prefFont = fe->GetOrMakeFont(&mStyle, needsBold);
if (!prefFont) continue;
mLastPrefFamily = family;
mLastPrefFont = prefFont;
mLastPrefLang = charLang;
mLastPrefFirstFont = (i == 0);
return prefFont.forget();
}
}
}
return nsnull;
}
already_AddRefed<gfxFont>
gfxFontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
{
gfxFontEntry *fe =
gfxPlatformFontList::PlatformFontList()->FindFontForChar(aCh, GetFontAt(0));
if (fe) {
nsRefPtr<gfxFont> font = fe->GetOrMakeFont(&mStyle, PR_FALSE); // ignore bolder considerations in system fallback case...
return font.forget();
}
return nsnull;
}
#define DEFAULT_PIXEL_FONT_SIZE 16.0f

View File

@ -218,6 +218,23 @@ GDIFontEntry::ReadCMAP()
return rv;
}
gfxFont *
GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, PRBool /*aNeedsBold*/)
{
gfxFont *newFont;
newFont = new gfxWindowsFont(this, aFontStyle);
if (!newFont) {
return nsnull;
}
if (!newFont->Valid()) {
delete newFont;
return nsnull;
}
nsRefPtr<gfxFont> font = newFont;
gfxFontCache::GetCache()->AddNew(font);
return newFont;
}
nsresult
GDIFontEntry::GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer)
{

View File

@ -289,6 +289,8 @@ protected:
void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType);
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
LOGFONTW mLogFont;

View File

@ -82,6 +82,8 @@ protected:
virtual nsresult GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer);
virtual gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
ATSFontRef mATSFontRef;
PRPackedBool mATSFontRefInitialized;
#ifndef __LP64__

View File

@ -321,6 +321,35 @@ MacOSFontEntry::GetFontTable(PRUint32 aTableTag, nsTArray<PRUint8>& aBuffer)
return NS_OK;
}
gfxFont*
MacOSFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold)
{
gfxFont *newFont;
#ifdef __LP64__
newFont = new gfxCoreTextFont(this, aFontStyle, aNeedsBold);
#else
#ifdef MOZ_CORETEXT
if (gfxPlatformMac::GetPlatform()->UsingCoreText()) {
newFont = new gfxCoreTextFont(this, aFontStyle, aNeedsBold);
} else {
#endif
newFont = new gfxAtsuiFont(this, aFontStyle, aNeedsBold);
#ifdef MOZ_CORETEXT
}
#endif
#endif
if (!newFont) {
return nsnull;
}
if (!newFont->Valid()) {
delete newFont;
return nsnull;
}
nsRefPtr<gfxFont> font = newFont;
gfxFontCache::GetCache()->AddNew(font);
return newFont;
}
/* gfxMacFontFamily */
#pragma mark-

View File

@ -58,8 +58,12 @@
#include "gfxTextRunWordCache.h"
#include "gfxUserFontSet.h"
#include "nsUnicodeRange.h"
#include "nsServiceManagerUtils.h"
#include "nsTArray.h"
#include "nsIUGenCategory.h"
#include "nsUnicharUtilCIID.h"
#include "nsILocaleService.h"
#include "nsWeakReference.h"
@ -70,6 +74,7 @@
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIPrefBranch2.h"
#include "nsIPrefLocalizedString.h"
#include "nsCRT.h"
gfxPlatform *gPlatform = nsnull;
@ -488,6 +493,38 @@ gfxPlatform::GetPrefLangName(eFontPrefLang aLang)
return nsnull;
}
eFontPrefLang
gfxPlatform::GetFontPrefLangFor(PRUint8 aUnicodeRange)
{
switch (aUnicodeRange) {
case kRangeSetLatin: return eFontPrefLang_Western;
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
case kRangeGreek: return eFontPrefLang_Greek;
case kRangeTurkish: return eFontPrefLang_Turkish;
case kRangeHebrew: return eFontPrefLang_Hebrew;
case kRangeArabic: return eFontPrefLang_Arabic;
case kRangeBaltic: return eFontPrefLang_Baltic;
case kRangeThai: return eFontPrefLang_Thai;
case kRangeKorean: return eFontPrefLang_Korean;
case kRangeJapanese: return eFontPrefLang_Japanese;
case kRangeSChinese: return eFontPrefLang_ChineseCN;
case kRangeTChinese: return eFontPrefLang_ChineseTW;
case kRangeDevanagari: return eFontPrefLang_Devanagari;
case kRangeTamil: return eFontPrefLang_Tamil;
case kRangeArmenian: return eFontPrefLang_Armenian;
case kRangeBengali: return eFontPrefLang_Bengali;
case kRangeCanadian: return eFontPrefLang_Canadian;
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
case kRangeGeorgian: return eFontPrefLang_Georgian;
case kRangeGujarati: return eFontPrefLang_Gujarati;
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
case kRangeKhmer: return eFontPrefLang_Khmer;
case kRangeMalayalam: return eFontPrefLang_Malayalam;
case kRangeSetCJK: return eFontPrefLang_CJKSet;
default: return eFontPrefLang_Others;
}
}
const PRUint32 kFontPrefLangCJKMask = (1 << (PRUint32) eFontPrefLang_Japanese) | (1 << (PRUint32) eFontPrefLang_ChineseTW)
| (1 << (PRUint32) eFontPrefLang_ChineseCN) | (1 << (PRUint32) eFontPrefLang_ChineseHK)
| (1 << (PRUint32) eFontPrefLang_Korean) | (1 << (PRUint32) eFontPrefLang_CJKSet);
@ -497,6 +534,139 @@ gfxPlatform::IsLangCJK(eFontPrefLang aLang)
return kFontPrefLangCJKMask & (1 << (PRUint32) aLang);
}
void
gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
if (IsLangCJK(aCharLang)) {
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
} else {
AppendPrefLang(aPrefLangs, aLen, aCharLang);
}
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
}
void
gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
// prefer the lang specified by the page *if* CJK
if (IsLangCJK(aPageLang)) {
AppendPrefLang(aPrefLangs, aLen, aPageLang);
}
// if not set up, set up the default CJK order, based on accept lang settings and locale
if (mCJKPrefLangs.Length() == 0) {
// temp array
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
PRUint32 tempLen = 0;
// Add the CJK pref fonts from accept languages, the order should be same order
nsCAutoString list;
nsresult rv;
if (prefs) {
nsCOMPtr<nsIPrefLocalizedString> prefString;
rv = prefs->GetComplexValue("intl.accept_languages", NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(prefString));
if (prefString) {
nsAutoString temp;
prefString->ToString(getter_Copies(temp));
LossyCopyUTF16toASCII(temp, list);
}
}
if (NS_SUCCEEDED(rv) && !list.IsEmpty()) {
const char kComma = ',';
const char *p, *p_end;
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsCAutoString lang(Substring(start, p));
lang.CompressWhitespace(PR_FALSE, PR_TRUE);
eFontPrefLang fpl = gfxPlatform::GetFontPrefLangFor(lang.get());
switch (fpl) {
case eFontPrefLang_Japanese:
case eFontPrefLang_Korean:
case eFontPrefLang_ChineseCN:
case eFontPrefLang_ChineseHK:
case eFontPrefLang_ChineseTW:
AppendPrefLang(tempPrefLangs, tempLen, fpl);
break;
default:
break;
}
p++;
}
}
do { // to allow 'break' to abort this block if a call fails
nsresult rv;
nsCOMPtr<nsILocaleService> ls =
do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
break;
nsCOMPtr<nsILocale> appLocale;
rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
if (NS_FAILED(rv))
break;
nsString localeStr;
rv = appLocale->
GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
if (NS_FAILED(rv))
break;
const nsAString& lang = Substring(localeStr, 0, 2);
if (lang.EqualsLiteral("ja")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
} else if (lang.EqualsLiteral("zh")) {
const nsAString& region = Substring(localeStr, 3, 2);
if (region.EqualsLiteral("CN")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
} else if (region.EqualsLiteral("TW")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
} else if (region.EqualsLiteral("HK")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
}
} else if (lang.EqualsLiteral("ko")) {
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
}
} while (0);
// last resort... (the order is same as old gfx.)
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
// copy into the cached array
PRUint32 j;
for (j = 0; j < tempLen; j++) {
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
}
}
// append in cached CJK langs
PRUint32 i, numCJKlangs = mCJKPrefLangs.Length();
for (i = 0; i < numCJKlangs; i++) {
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
}
}
void
gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPrefLang aAddLang)
{
@ -793,3 +963,58 @@ gfxPlatform::InitDisplayCaps()
// Fall back to something sane
gfxPlatform::sDPI = 96;
}
// default SetupClusterBoundaries, based on Unicode properties;
// platform subclasses may override if they wish
static nsIUGenCategory* gGenCategory = nsnull;
static nsIUGenCategory*
GetGenCategory()
{
if (!gGenCategory) {
nsresult rv = CallGetService(NS_UNICHARUTIL_CONTRACTID, &gGenCategory);
if (NS_FAILED(rv)) {
NS_ERROR("Failed to get the Unicode character category service!");
gGenCategory = nsnull;
}
}
return gGenCategory;
}
void
gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString)
{
if (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) {
// 8-bit text doesn't have clusters.
// XXX is this true in all languages???
// behdad: don't think so. Czech for example IIRC has a
// 'ch' grapheme.
return;
}
nsIUGenCategory* gc = GetGenCategory();
if (!gc) {
NS_WARNING("No Unicode category service: cannot determine clusters");
return;
}
PRUint32 i, length = aTextRun->GetLength();
for (i = 0; i < length; ++i) {
PRBool surrogatePair = PR_FALSE;
PRUint32 ch = aString[i];
if (NS_IS_HIGH_SURROGATE(ch) &&
i < length - 1 && NS_IS_LOW_SURROGATE(aString[i+1])) {
ch = SURROGATE_TO_UCS4(ch, aString[i+1]);
surrogatePair = PR_TRUE;
}
if (i > 0 && gc->Get(aString[i]) == nsIUGenCategory::kMark) {
gfxTextRun::CompressedGlyph g;
aTextRun->SetGlyphs(i, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull);
}
if (surrogatePair) {
++i;
gfxTextRun::CompressedGlyph g;
aTextRun->SetGlyphs(i, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull);
}
}
}

View File

@ -43,7 +43,6 @@
#include "gfxQuartzImageSurface.h"
#include "gfxMacPlatformFontList.h"
#include "gfxAtsuiFonts.h"
#include "gfxUserFontSet.h"
#ifdef MOZ_CORETEXT
@ -165,15 +164,7 @@ gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies,
const gfxFontStyle *aStyle,
gfxUserFontSet *aUserFontSet)
{
#ifdef __LP64__
return new gfxCoreTextFontGroup(aFamilies, aStyle, aUserFontSet);
#else
#ifdef MOZ_CORETEXT
if (mUseCoreText)
return new gfxCoreTextFontGroup(aFamilies, aStyle, aUserFontSet);
#endif
return new gfxAtsuiFontGroup(aFamilies, aStyle, aUserFontSet);
#endif
return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
}
// these will move to gfxPlatform once all platforms support the fontlist
@ -253,115 +244,6 @@ gfxPlatformMac::OSXVersion()
return mOSXVersion;
}
void
gfxPlatformMac::GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
if (IsLangCJK(aCharLang)) {
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
} else {
AppendPrefLang(aPrefLangs, aLen, aCharLang);
}
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
}
void
gfxPlatformMac::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
// prefer the lang specified by the page *if* CJK
if (IsLangCJK(aPageLang)) {
AppendPrefLang(aPrefLangs, aLen, aPageLang);
}
// if not set up, set up the default CJK order, based on accept lang settings and system script
if (mCJKPrefLangs.Length() == 0) {
// temp array
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
PRUint32 tempLen = 0;
// Add the CJK pref fonts from accept languages, the order should be same order
nsCAutoString list;
nsresult rv;
if (prefs) {
nsCOMPtr<nsIPrefLocalizedString> prefString;
rv = prefs->GetComplexValue("intl.accept_languages", NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(prefString));
if (prefString) {
nsAutoString temp;
prefString->ToString(getter_Copies(temp));
LossyCopyUTF16toASCII(temp, list);
}
}
if (NS_SUCCEEDED(rv) && !list.IsEmpty()) {
const char kComma = ',';
const char *p, *p_end;
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsCAutoString lang(Substring(start, p));
lang.CompressWhitespace(PR_FALSE, PR_TRUE);
eFontPrefLang fpl = gfxPlatform::GetFontPrefLangFor(lang.get());
switch (fpl) {
case eFontPrefLang_Japanese:
case eFontPrefLang_Korean:
case eFontPrefLang_ChineseCN:
case eFontPrefLang_ChineseHK:
case eFontPrefLang_ChineseTW:
AppendPrefLang(tempPrefLangs, tempLen, fpl);
break;
default:
break;
}
p++;
}
}
// Prefer the system locale if it is CJK.
TextEncoding sysScript = ::GetApplicationTextEncoding();
// XXX Is not there the HK locale?
switch (sysScript) {
case kTextEncodingMacJapanese: AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese); break;
case kTextEncodingMacChineseTrad: AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW); break;
case kTextEncodingMacKorean: AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean); break;
case kTextEncodingMacChineseSimp: AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN); break;
default: break;
}
// last resort... (the order is same as old gfx.)
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
// copy into the cached array
PRUint32 j;
for (j = 0; j < tempLen; j++) {
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
}
}
// append in cached CJK langs
PRUint32 i, numCJKlangs = mCJKPrefLangs.Length();
for (i = 0; i < numCJKlangs; i++) {
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
}
}
PRUint32
gfxPlatformMac::ReadAntiAliasingThreshold()
{
@ -509,35 +391,3 @@ gfxPlatformMac::SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aS
UCDisposeTextBreakLocator(&locator);
}
eFontPrefLang
gfxPlatformMac::GetFontPrefLangFor(PRUint8 aUnicodeRange)
{
switch (aUnicodeRange) {
case kRangeSetLatin: return eFontPrefLang_Western;
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
case kRangeGreek: return eFontPrefLang_Greek;
case kRangeTurkish: return eFontPrefLang_Turkish;
case kRangeHebrew: return eFontPrefLang_Hebrew;
case kRangeArabic: return eFontPrefLang_Arabic;
case kRangeBaltic: return eFontPrefLang_Baltic;
case kRangeThai: return eFontPrefLang_Thai;
case kRangeKorean: return eFontPrefLang_Korean;
case kRangeJapanese: return eFontPrefLang_Japanese;
case kRangeSChinese: return eFontPrefLang_ChineseCN;
case kRangeTChinese: return eFontPrefLang_ChineseTW;
case kRangeDevanagari: return eFontPrefLang_Devanagari;
case kRangeTamil: return eFontPrefLang_Tamil;
case kRangeArmenian: return eFontPrefLang_Armenian;
case kRangeBengali: return eFontPrefLang_Bengali;
case kRangeCanadian: return eFontPrefLang_Canadian;
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
case kRangeGeorgian: return eFontPrefLang_Georgian;
case kRangeGujarati: return eFontPrefLang_Gujarati;
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
case kRangeKhmer: return eFontPrefLang_Khmer;
case kRangeMalayalam: return eFontPrefLang_Malayalam;
case kRangeSetCJK: return eFontPrefLang_CJKSet;
default: return eFontPrefLang_Others;
}
}

View File

@ -79,7 +79,13 @@ gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSr
gfxProxyFontEntry::~gfxProxyFontEntry()
{
}
gfxFont*
gfxProxyFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold)
{
// cannot create an actual font for a proxy entry
return nsnull;
}
gfxUserFontSet::gfxUserFontSet()

View File

@ -395,6 +395,15 @@ gfxWindowsFont::GetUniqueName()
return uniqueName;
}
void
gfxWindowsFont::InitTextRun(gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength)
{
NS_NOTREACHED("oops");
}
void
gfxWindowsFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
gfxContext *aContext, PRBool aDrawToPath, gfxPoint *aBaselineOrigin,

View File

@ -350,6 +350,67 @@ gfxWindowsPlatform::GetFTLibrary()
}
#endif
#ifndef MOZ_FT2_FONTS
void
gfxWindowsPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun,
const PRUnichar *aString)
{
NS_ABORT_IF_FALSE(sizeof(WCHAR) == sizeof(PRUnichar),
"WCHAR/PRUnichar not compatible");
PRUint32 length = aTextRun->GetLength();
nsAutoTArray<SCRIPT_ITEM,4> items;
PRUint32 maxItems = 4;
int numItems;
HRESULT result;
PRUint32 i, j;
do {
items.SetLength(maxItems);
result = ::ScriptItemize(aString, length,
maxItems - 1,
NULL,
NULL,
items.Elements(),
&numItems);
maxItems <<= 1;
if (maxItems > INT_MAX)
break;
} while (result == E_OUTOFMEMORY);
if (result != 0) {
return;
}
nsTArray<SCRIPT_LOGATTR> attrs;
for (i = 0; i < PRUint32(numItems); ++i) {
PRUint32 offset = items[i].iCharPos;
length = items[i + 1].iCharPos - offset;
if (attrs.Length() < length) {
attrs.SetLength(length);
}
result = ::ScriptBreak(aString + offset, length,
&items[i].a,
attrs.Elements());
if (result != 0) {
break;
}
for (j = 1; j < length; ++j) {
if (!attrs[j].fCharStop) {
gfxTextRun::CompressedGlyph g;
// Remember that this character is not the start of a cluster
// by setting its glyph data to "not a cluster start",
// "is a ligature start", with no glyphs.
aTextRun->SetGlyphs(offset + j,
g.SetComplex(PR_FALSE, PR_TRUE, 0),
nsnull);
}
}
}
}
#endif
void
gfxWindowsPlatform::InitDisplayCaps()
{