mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 20:49:27 +00:00
Bug 441473. Implement user font set object. r+sr=roc
This commit is contained in:
parent
1d2fd423b4
commit
37c61248d6
@ -1975,7 +1975,7 @@ nsCanvasRenderingContext2D::SetFont(const nsAString& font)
|
||||
fontStyle->mFont.systemFont,
|
||||
fontStyle->mFont.familyNameQuirks);
|
||||
|
||||
CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style);
|
||||
CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style, presShell->GetPresContext()->GetUserFontSet());
|
||||
NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");
|
||||
CurrentState().font = font;
|
||||
return NS_OK;
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
virtual nsresult Init(nsIDeviceContext* aContext);
|
||||
virtual nsresult GetDeviceContext(nsIDeviceContext *&aContext) const;
|
||||
virtual nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIFontMetrics *&aMetrics);
|
||||
nsIFontMetrics *&aMetrics, gfxUserFontSet *aUserFontSet = nsnull);
|
||||
|
||||
nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
|
||||
nsresult Compact();
|
||||
@ -100,8 +100,9 @@ public:
|
||||
NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext);
|
||||
|
||||
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIFontMetrics*& aMetrics);
|
||||
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics);
|
||||
nsIFontMetrics*& aMetrics, gfxUserFontSet *aUserFontSet = nsnull);
|
||||
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics,
|
||||
gfxUserFontSet *aUserFontSet = nsnull);
|
||||
|
||||
NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName);
|
||||
|
||||
|
@ -52,6 +52,7 @@ class nsIFontMetrics;
|
||||
class nsIWidget;
|
||||
class nsIDeviceContextSpec;
|
||||
class nsIAtom;
|
||||
class gfxUserFontSet;
|
||||
|
||||
struct nsFont;
|
||||
|
||||
@ -330,19 +331,23 @@ public:
|
||||
* @param aFont font description to obtain metrics for
|
||||
* @param aLangGroup the language group of the document
|
||||
* @param aMetrics out parameter for font metrics
|
||||
* @param aUserFontSet user font set
|
||||
* @return error status
|
||||
*/
|
||||
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIFontMetrics*& aMetrics) = 0;
|
||||
nsIFontMetrics*& aMetrics,
|
||||
gfxUserFontSet *aUserFontSet = nsnull) = 0;
|
||||
|
||||
/**
|
||||
* Get the nsIFontMetrics that describe the properties of
|
||||
* an nsFont.
|
||||
* @param aFont font description to obtain metrics for
|
||||
* @param aMetrics out parameter for font metrics
|
||||
* @param aUserFontSet user font set
|
||||
* @return error status
|
||||
*/
|
||||
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics) = 0;
|
||||
NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics,
|
||||
gfxUserFontSet *aUserFontSet = nsnull) = 0;
|
||||
|
||||
/**
|
||||
* Check to see if a particular named font exists.
|
||||
|
@ -45,6 +45,7 @@
|
||||
class nsString;
|
||||
class nsIDeviceContext;
|
||||
class nsIAtom;
|
||||
class gfxUserFontSet;
|
||||
|
||||
// IID for the nsIFontMetrics interface
|
||||
#define NS_IFONT_METRICS_IID \
|
||||
@ -87,7 +88,7 @@ public:
|
||||
* @see nsIDeviceContext#GetMetricsFor()
|
||||
*/
|
||||
NS_IMETHOD Init(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIDeviceContext *aContext) = 0;
|
||||
nsIDeviceContext *aContext, gfxUserFontSet *aUserFontSet = nsnull) = 0;
|
||||
|
||||
/**
|
||||
* Destroy this font metrics. This breaks the association between
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIRenderingContext.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS3(DeviceContextImpl, nsIDeviceContext, nsIObserver, nsISupportsWeakReference)
|
||||
|
||||
@ -213,7 +214,7 @@ DeviceContextImpl::GetLocaleLangGroup(void)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
|
||||
nsIAtom* aLangGroup, nsIFontMetrics*& aMetrics)
|
||||
nsIAtom* aLangGroup, nsIFontMetrics*& aMetrics, gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
if (nsnull == mFontCache) {
|
||||
nsresult rv = CreateFontCache();
|
||||
@ -230,10 +231,12 @@ NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
|
||||
aLangGroup = mLocaleLangGroup;
|
||||
}
|
||||
|
||||
return mFontCache->GetMetricsFor(aFont, aLangGroup, aMetrics);
|
||||
return mFontCache->GetMetricsFor(aFont, aLangGroup, aMetrics, aUserFontSet);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont, nsIFontMetrics*& aMetrics)
|
||||
NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont,
|
||||
nsIFontMetrics*& aMetrics,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
if (nsnull == mFontCache) {
|
||||
nsresult rv = CreateFontCache();
|
||||
@ -244,7 +247,8 @@ NS_IMETHODIMP DeviceContextImpl::GetMetricsFor(const nsFont& aFont, nsIFontMetri
|
||||
// XXX temporary fix for performance problem -- erik
|
||||
GetLocaleLangGroup();
|
||||
}
|
||||
return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aMetrics);
|
||||
return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup,
|
||||
aMetrics, aUserFontSet);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DeviceContextImpl::GetDepth(PRUint32& aDepth)
|
||||
@ -469,7 +473,7 @@ nsFontCache::GetDeviceContext(nsIDeviceContext *&aContext) const
|
||||
|
||||
nsresult
|
||||
nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIFontMetrics *&aMetrics)
|
||||
nsIFontMetrics *&aMetrics, gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
// First check our cache
|
||||
// start from the end, which is where we put the most-recent-used element
|
||||
@ -497,7 +501,7 @@ nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
aMetrics = nsnull;
|
||||
nsresult rv = CreateFontMetricsInstance(&fm);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fm->Init(aFont, aLangGroup, mContext);
|
||||
rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// the mFontMetrics list has the "head" at the end, because append is
|
||||
// cheaper than insert
|
||||
@ -516,7 +520,7 @@ nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
Compact();
|
||||
rv = CreateFontMetricsInstance(&fm);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = fm->Init(aFont, aLangGroup, mContext);
|
||||
rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mFontMetrics.AppendElement(fm);
|
||||
aMetrics = fm;
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#include "gfxTextRunCache.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsThebesFontMetrics, nsIFontMetrics)
|
||||
|
||||
@ -63,7 +64,8 @@ nsThebesFontMetrics::~nsThebesFontMetrics()
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIDeviceContext *aContext)
|
||||
nsIDeviceContext *aContext,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
mFont = aFont;
|
||||
mLangGroup = aLangGroup;
|
||||
@ -86,7 +88,8 @@ nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
aFont.familyNameQuirks);
|
||||
|
||||
mFontGroup =
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle);
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle,
|
||||
aUserFontSet);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -57,7 +57,8 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Init(const nsFont& aFont, nsIAtom* aLangGroup,
|
||||
nsIDeviceContext *aContext);
|
||||
nsIDeviceContext *aContext,
|
||||
gfxUserFontSet *aUserFontSet = nsnull);
|
||||
NS_IMETHOD Destroy();
|
||||
NS_IMETHOD GetXHeight(nscoord& aResult);
|
||||
NS_IMETHOD GetSuperscriptOffset(nscoord& aResult);
|
||||
|
@ -31,6 +31,7 @@ EXPORTS = gfxASurface.h \
|
||||
gfxTextRunCache.h \
|
||||
gfxTextRunWordCache.h \
|
||||
gfxUtils.h \
|
||||
gfxUserFontSet.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS += gfxFontTest.h
|
||||
|
@ -113,7 +113,8 @@ protected:
|
||||
class THEBES_API gfxAtsuiFontGroup : public gfxFontGroup {
|
||||
public:
|
||||
gfxAtsuiFontGroup(const nsAString& families,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
virtual ~gfxAtsuiFontGroup() {};
|
||||
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
@ -137,7 +138,9 @@ public:
|
||||
|
||||
PRBool HasFont(ATSUFontID fid);
|
||||
|
||||
inline gfxAtsuiFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList, PRUint32 aCh) {
|
||||
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());
|
||||
@ -147,10 +150,12 @@ public:
|
||||
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);
|
||||
// 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 FindATSUFont(const nsAString& aName,
|
||||
|
@ -51,8 +51,6 @@
|
||||
#include "gfxSkipChars.h"
|
||||
#include "gfxRect.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
@ -63,6 +61,8 @@ class gfxTextRun;
|
||||
class nsIAtom;
|
||||
class gfxFont;
|
||||
class gfxFontGroup;
|
||||
class gfxUserFontSet;
|
||||
class gfxUserFontData;
|
||||
|
||||
#define FONT_STYLE_NORMAL 0
|
||||
#define FONT_STYLE_ITALIC 1
|
||||
@ -140,20 +140,24 @@ struct THEBES_API gfxFontStyle {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class gfxFontEntry {
|
||||
public:
|
||||
THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry)
|
||||
|
||||
gfxFontEntry(const nsAString& aName) :
|
||||
mName(aName), mCmapInitialized(PR_FALSE)
|
||||
mName(aName), mIsProxy(PR_FALSE), mIsValid(PR_TRUE),
|
||||
mIsBadUnderlineFont(PR_FALSE),
|
||||
mCmapInitialized(PR_FALSE), mUserFontData(nsnull)
|
||||
{ }
|
||||
|
||||
gfxFontEntry(const gfxFontEntry& aEntry) :
|
||||
mName(aEntry.mName), mItalic(aEntry.mItalic), mFixedPitch(aEntry.mFixedPitch),
|
||||
mUnicodeFont(aEntry.mUnicodeFont), mSymbolFont(aEntry.mSymbolFont), mTrueType(aEntry.mTrueType),
|
||||
mIsType1(aEntry.mIsType1), mWeight(aEntry.mWeight), mCmapInitialized(aEntry.mCmapInitialized),
|
||||
mCharacterMap(aEntry.mCharacterMap)
|
||||
mName(aEntry.mName), mItalic(aEntry.mItalic),
|
||||
mFixedPitch(aEntry.mFixedPitch), mUnicodeFont(aEntry.mUnicodeFont),
|
||||
mSymbolFont(aEntry.mSymbolFont), mTrueType(aEntry.mTrueType),
|
||||
mIsType1(aEntry.mIsType1), mIsProxy(aEntry.mIsProxy),
|
||||
mIsValid(aEntry.mIsValid), mIsBadUnderlineFont(aEntry.mIsBadUnderlineFont),
|
||||
mWeight(aEntry.mWeight), mCmapInitialized(aEntry.mCmapInitialized),
|
||||
mCharacterMap(aEntry.mCharacterMap), mUserFontData(aEntry.mUserFontData)
|
||||
{ }
|
||||
|
||||
virtual ~gfxFontEntry();
|
||||
@ -165,7 +169,7 @@ public:
|
||||
|
||||
PRBool IsFixedPitch() { return mFixedPitch; }
|
||||
PRBool IsItalic() { return mItalic; }
|
||||
PRBool IsBold() { return mWeight >= 6; } // bold == weights 600 and above
|
||||
PRBool IsBold() { return mWeight >= 600; } // bold == weights 600 and above
|
||||
|
||||
inline PRBool HasCharacter(PRUint32 ch) {
|
||||
if (mCharacterMap.test(ch))
|
||||
@ -177,7 +181,7 @@ public:
|
||||
virtual PRBool TestCharacterMap(PRUint32 aCh);
|
||||
virtual nsresult ReadCMAP() { return 0; }
|
||||
|
||||
nsString mName;
|
||||
nsString mName;
|
||||
|
||||
PRPackedBool mItalic : 1;
|
||||
PRPackedBool mFixedPitch : 1;
|
||||
@ -186,11 +190,23 @@ public:
|
||||
PRPackedBool mSymbolFont : 1;
|
||||
PRPackedBool mTrueType : 1;
|
||||
PRPackedBool mIsType1 : 1;
|
||||
PRPackedBool mIsProxy : 1;
|
||||
PRPackedBool mIsValid : 1;
|
||||
|
||||
PRPackedBool mIsBadUnderlineFont : 1;
|
||||
|
||||
PRUint16 mWeight;
|
||||
PRUint16 mStretch;
|
||||
|
||||
PRPackedBool mCmapInitialized;
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
gfxUserFontData* mUserFontData;
|
||||
|
||||
protected:
|
||||
gfxFontEntry() :
|
||||
mIsProxy(PR_FALSE), mIsValid(PR_TRUE),
|
||||
mCmapInitialized(PR_FALSE), mUserFontData(nsnull)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@ -205,12 +221,17 @@ public:
|
||||
|
||||
const nsString& Name() { return mName; }
|
||||
|
||||
// choose a specific face to match a style using CSS font matching rules (weight matching occurs here)
|
||||
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle, PRBool& aNeedsBold);
|
||||
// choose a specific face to match a style using CSS font matching
|
||||
// rules (weight matching occurs here)
|
||||
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
|
||||
PRBool& aNeedsBold);
|
||||
|
||||
protected:
|
||||
// fills in an array with weights of faces that match style, returns number of weights in array
|
||||
virtual PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gfxFontStyle& aFontStyle) { return PR_FALSE; }
|
||||
// fills in an array with weights of faces that match style, returns
|
||||
// number of weights in array
|
||||
virtual PRBool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
|
||||
const gfxFontStyle& aFontStyle)
|
||||
{ return PR_FALSE; }
|
||||
|
||||
nsString mName;
|
||||
};
|
||||
@ -351,7 +372,7 @@ public:
|
||||
PRUint16 GetContainedGlyphWidthAppUnits(PRUint32 aGlyphID) const {
|
||||
return mContainedGlyphWidths.Get(aGlyphID);
|
||||
}
|
||||
|
||||
|
||||
PRBool IsGlyphKnown(PRUint32 aGlyphID) const {
|
||||
return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
|
||||
mTightGlyphExtents.GetEntry(aGlyphID) != nsnull;
|
||||
@ -638,7 +659,7 @@ public:
|
||||
|
||||
PRBool IsSyntheticBold() { return mSyntheticBoldOffset != 0; }
|
||||
PRUint32 GetSyntheticBoldOffset() { return mSyntheticBoldOffset; }
|
||||
|
||||
|
||||
gfxFontEntry *GetFontEntry() { return mFontEntry.get(); }
|
||||
PRBool HasCharacter(PRUint32 ch) {
|
||||
if (!mIsValid)
|
||||
@ -675,7 +696,7 @@ public:
|
||||
PLATFORM_TEXT_FLAGS = 0x0000F000,
|
||||
TEXTRUN_TEXT_FLAGS = 0x00000FFF,
|
||||
SETTABLE_FLAGS = CACHE_TEXT_FLAGS | USER_TEXT_FLAGS,
|
||||
|
||||
|
||||
/**
|
||||
* When set, the text string pointer used to create the text run
|
||||
* is guaranteed to be available during the lifetime of the text run.
|
||||
@ -1385,6 +1406,9 @@ public:
|
||||
PRPackedBool mClipBeforePart;
|
||||
PRPackedBool mClipAfterPart;
|
||||
};
|
||||
|
||||
// user font set generation when text run was created
|
||||
PRUint64 GetUserFontSetGeneration() { return mUserFontSetGeneration; }
|
||||
|
||||
#ifdef DEBUG
|
||||
// number of entries referencing this textrun in the gfxTextRunWordCache
|
||||
@ -1488,16 +1512,15 @@ private:
|
||||
PRUint32 mFlags;
|
||||
PRUint32 mCharacterCount;
|
||||
PRUint32 mHashCode;
|
||||
PRUint64 mUserFontSetGeneration; // user font set generation when text run created
|
||||
};
|
||||
|
||||
class THEBES_API gfxFontGroup : public gfxTextRunFactory {
|
||||
protected:
|
||||
gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle);
|
||||
gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet = nsnull);
|
||||
|
||||
public:
|
||||
virtual ~gfxFontGroup() {
|
||||
mFonts.Clear();
|
||||
}
|
||||
virtual ~gfxFontGroup();
|
||||
|
||||
virtual gfxFont *GetFontAt(PRInt32 i) {
|
||||
return static_cast<gfxFont*>(mFonts[i]);
|
||||
@ -1519,20 +1542,8 @@ public:
|
||||
* The listed characters should not be passed in to MakeTextRun and should
|
||||
* be treated as invisible and zero-width.
|
||||
*/
|
||||
static PRBool IsInvalidChar(PRUnichar ch) {
|
||||
if (ch >= 32) {
|
||||
return ch == 0x0085/*NEL*/ ||
|
||||
((ch & 0xFF00) == 0x2000 /* Unicode control character */ &&
|
||||
(ch == 0x200B/*ZWSP*/ || ch == 0x2028/*LSEP*/ || ch == 0x2029/*PSEP*/ ||
|
||||
IS_BIDI_CONTROL_CHAR(ch)));
|
||||
}
|
||||
// We could just blacklist all control characters, but it seems better
|
||||
// to only blacklist the ones we know cause problems for native font
|
||||
// engines.
|
||||
return ch == 0x0B || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\f' ||
|
||||
(ch >= 0x1c && ch <= 0x1f);
|
||||
}
|
||||
|
||||
static PRBool IsInvalidChar(PRUnichar ch);
|
||||
|
||||
/**
|
||||
* Make a textrun for an empty string. This is fast; if you call it,
|
||||
* don't bother caching the result.
|
||||
@ -1567,7 +1578,7 @@ public:
|
||||
typedef PRBool (*FontCreationCallback) (const nsAString& aName,
|
||||
const nsACString& aGenericName,
|
||||
void *closure);
|
||||
static PRBool ForEachFont(const nsAString& aFamilies,
|
||||
/*static*/ PRBool ForEachFont(const nsAString& aFamilies,
|
||||
const nsACString& aLangGroup,
|
||||
FontCreationCallback fc,
|
||||
void *closure);
|
||||
@ -1595,6 +1606,16 @@ public:
|
||||
|
||||
void ComputeRanges(nsTArray<gfxTextRange>& mRanges, const PRUnichar *aString, PRUint32 begin, PRUint32 end);
|
||||
|
||||
gfxUserFontSet* GetUserFontSet();
|
||||
void SetUserFontSet(gfxUserFontSet *aUserFontSet);
|
||||
|
||||
// With downloadable fonts, the composition of the font group can change as fonts are downloaded
|
||||
// for each change in state of the user font set, the generation value is bumped to avoid picking up
|
||||
// previously created text runs in the text run word cache. For font groups based on stylesheets
|
||||
// with no @font-face rule, this always returns 0.
|
||||
PRUint64 GetGeneration();
|
||||
|
||||
virtual void UpdateFontList() { }
|
||||
|
||||
protected:
|
||||
nsString mFamilies;
|
||||
@ -1602,6 +1623,9 @@ protected:
|
||||
nsTArray< nsRefPtr<gfxFont> > mFonts;
|
||||
gfxFloat mUnderlineOffset;
|
||||
|
||||
gfxUserFontSet* mUserFontSet;
|
||||
PRUint64 mCurrGeneration; // track the current user font set generation, rebuild font list if needed
|
||||
|
||||
// Init this font group's font metrics. If there no bad fonts, you don't need to call this.
|
||||
// But if there are one or more bad fonts which have bad underline offset,
|
||||
// you should call this with the *first* bad font.
|
||||
@ -1615,7 +1639,7 @@ protected:
|
||||
* family name in aFamilies (after resolving CSS/Gecko generic family names
|
||||
* if aResolveGeneric).
|
||||
*/
|
||||
static PRBool ForEachFontInternal(const nsAString& aFamilies,
|
||||
/*static*/ PRBool ForEachFontInternal(const nsAString& aFamilies,
|
||||
const nsACString& aLangGroup,
|
||||
PRBool aResolveGeneric,
|
||||
PRBool aResolveFontName,
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "cairo.h"
|
||||
|
||||
#include "gfxFont.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
struct THEBES_API gfxFontTestItem {
|
||||
gfxFontTestItem(const nsCString& fontName,
|
||||
|
@ -312,18 +312,32 @@ public:
|
||||
static inline PRUint32
|
||||
ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) | (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
|
||||
return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
|
||||
(aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
|
||||
ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength,
|
||||
gfxSparseBitSet& aCharacterMap);
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
|
||||
ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength,
|
||||
gfxSparseBitSet& aCharacterMap);
|
||||
|
||||
static nsresult
|
||||
ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
|
||||
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// given a TrueType/OpenType data file, produce a EOT-format header
|
||||
// for use with Windows T2Embed API AddFontResource type API's
|
||||
// effectively hide existing fonts with matching names aHeaderLen is
|
||||
// the size of the header buffer on input, the actual size of the
|
||||
// EOT header on output aIsCFF returns whether the font has PS style
|
||||
// glyphs or not (as opposed to TrueType glyphs)
|
||||
static nsresult
|
||||
MakeEOTHeader(nsIFile *aFontData, nsTArray<PRUint8> *aHeader, PRBool *aIsCFF);
|
||||
#endif
|
||||
|
||||
static inline bool IsJoiner(PRUint32 ch) {
|
||||
return (ch == 0x200C ||
|
||||
@ -338,7 +352,8 @@ public:
|
||||
static PRUint8 CharRangeBit(PRUint32 ch);
|
||||
|
||||
// for a given font list pref name, set up a list of font names
|
||||
static void GetPrefsFontList(const char *aPrefName, nsTArray<nsString>& aFontList);
|
||||
static void GetPrefsFontList(const char *aPrefName,
|
||||
nsTArray<nsString>& aFontList);
|
||||
|
||||
};
|
||||
|
||||
@ -400,7 +415,8 @@ public:
|
||||
InitLoader();
|
||||
|
||||
// start timer
|
||||
mTimer->InitWithFuncCallback(LoaderTimerCallback, this, aDelay, nsITimer::TYPE_REPEATING_SLACK);
|
||||
mTimer->InitWithFuncCallback(LoaderTimerCallback, this, aDelay,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
// cancel the timer and cleanup
|
||||
|
@ -95,7 +95,7 @@ private:
|
||||
|
||||
class THEBES_API gfxOS2FontGroup : public gfxFontGroup {
|
||||
public:
|
||||
gfxOS2FontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle);
|
||||
gfxOS2FontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle, gfxUserFontSet *aUserFontSet);
|
||||
virtual ~gfxOS2FontGroup();
|
||||
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
|
@ -71,7 +71,8 @@ public:
|
||||
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
|
||||
|
||||
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
// Given a string and a font we already have, find the font that
|
||||
// supports the most code points and most closely resembles aFont.
|
||||
|
@ -73,7 +73,8 @@ public:
|
||||
class THEBES_API gfxPangoFontGroup : public gfxFontGroup {
|
||||
public:
|
||||
gfxPangoFontGroup (const nsAString& families,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
virtual ~gfxPangoFontGroup ();
|
||||
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
|
@ -59,6 +59,10 @@ class gfxImageSurface;
|
||||
class gfxFont;
|
||||
class gfxFontGroup;
|
||||
struct gfxFontStyle;
|
||||
class gfxUserFontSet;
|
||||
struct gfxDownloadedFontData;
|
||||
class gfxFontEntry;
|
||||
class nsIURI;
|
||||
|
||||
// pref lang id's for font prefs
|
||||
// !!! needs to match the list of pref font.default.xx entries listed in all.js !!!
|
||||
@ -184,7 +188,30 @@ public:
|
||||
* Create the appropriate platform font group
|
||||
*/
|
||||
virtual gfxFontGroup *CreateFontGroup(const nsAString& aFamilies,
|
||||
const gfxFontStyle *aStyle) = 0;
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Look up a local platform font using the full font face name (needed to support @font-face src local() )
|
||||
*/
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName) { return nsnull; }
|
||||
|
||||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
*
|
||||
* Note: MakePlatformFont implementation is responsible for removing font file data, since data may need to
|
||||
* persist beyond this call.
|
||||
*/
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData) { return nsnull; }
|
||||
|
||||
/**
|
||||
* Whether to allow downloadable fonts via @font-face rules
|
||||
*/
|
||||
virtual PRBool DownloadableFontsEnabled();
|
||||
|
||||
// check whether format is supported on a platform or not (if unclear, returns true)
|
||||
virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags) { return PR_FALSE; }
|
||||
|
||||
void GetPrefFonts(const char *aLangGroup, nsString& array, PRBool aAppendUnicode = PR_TRUE);
|
||||
|
||||
|
@ -79,7 +79,8 @@ public:
|
||||
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
|
||||
|
||||
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
#ifndef MOZ_PANGO
|
||||
FontFamily *FindFontFamily(const nsAString& aName);
|
||||
|
@ -66,7 +66,14 @@ public:
|
||||
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
|
||||
|
||||
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
|
||||
|
||||
gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData);
|
||||
|
||||
PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
|
||||
|
||||
nsresult GetFontList(const nsACString& aLangGroup,
|
||||
const nsACString& aGenericFamily,
|
||||
|
@ -83,7 +83,7 @@ class FontFamily : public gfxFontFamily
|
||||
{
|
||||
public:
|
||||
FontFamily(const nsAString& aName) :
|
||||
gfxFontFamily(aName), mHasStyles(PR_FALSE), mIsBadUnderlineFont(PR_FALSE) { }
|
||||
gfxFontFamily(aName), mIsBadUnderlineFontFamily(PR_FALSE), mHasStyles(PR_FALSE) { }
|
||||
|
||||
FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
|
||||
|
||||
@ -101,18 +101,18 @@ protected:
|
||||
|
||||
public:
|
||||
nsTArray<nsRefPtr<FontEntry> > mVariations;
|
||||
PRPackedBool mIsBadUnderlineFont;
|
||||
PRPackedBool mIsBadUnderlineFontFamily;
|
||||
|
||||
private:
|
||||
PRBool mHasStyles;
|
||||
PRPackedBool mHasStyles;
|
||||
};
|
||||
|
||||
class FontEntry : public gfxFontEntry
|
||||
{
|
||||
public:
|
||||
FontEntry(const nsString& aFaceName) :
|
||||
FontEntry(const nsAString& aFaceName) :
|
||||
gfxFontEntry(aFaceName), mFontType(GFX_FONT_TYPE_UNKNOWN),
|
||||
mIsBadUnderlineFont(PR_FALSE), mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
|
||||
mForceGDI(PR_FALSE), mUnknownCMAP(PR_FALSE),
|
||||
mCharset(0), mUnicodeRanges(0)
|
||||
{
|
||||
mUnicodeFont = PR_FALSE;
|
||||
@ -124,7 +124,6 @@ public:
|
||||
mWindowsFamily(aFontEntry.mWindowsFamily),
|
||||
mWindowsPitch(aFontEntry.mWindowsPitch),
|
||||
mFontType(aFontEntry.mFontType),
|
||||
mIsBadUnderlineFont(aFontEntry.mIsBadUnderlineFont),
|
||||
mForceGDI(aFontEntry.mForceGDI),
|
||||
mUnknownCMAP(aFontEntry.mUnknownCMAP),
|
||||
mCharset(aFontEntry.mCharset),
|
||||
@ -133,6 +132,31 @@ public:
|
||||
|
||||
}
|
||||
|
||||
static FontEntry* CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, PRBool aItalic, PRUint16 aWeight, gfxUserFontData* aUserFontData, HDC hdc = 0, LOGFONTW *aLogFont = nsnull);
|
||||
|
||||
static void FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize, PRBool aItalic);
|
||||
|
||||
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, DWORD fontType)
|
||||
{
|
||||
gfxWindowsFontType feType;
|
||||
if (metrics.ntmFlags & NTM_TYPE1)
|
||||
feType = GFX_FONT_TYPE_TYPE1;
|
||||
else if (metrics.ntmFlags & NTM_PS_OPENTYPE)
|
||||
feType = GFX_FONT_TYPE_PS_OPENTYPE;
|
||||
else if (metrics.ntmFlags & NTM_TT_OPENTYPE)
|
||||
feType = GFX_FONT_TYPE_TT_OPENTYPE;
|
||||
else if (fontType == TRUETYPE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_TRUETYPE;
|
||||
else if (fontType == RASTER_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_RASTER;
|
||||
else if (fontType == DEVICE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_DEVICE;
|
||||
else
|
||||
feType = GFX_FONT_TYPE_UNKNOWN;
|
||||
|
||||
return feType;
|
||||
}
|
||||
|
||||
PRBool IsType1() const {
|
||||
return (mFontType == GFX_FONT_TYPE_TYPE1);
|
||||
}
|
||||
@ -232,16 +256,12 @@ public:
|
||||
return mUnicodeRanges[range];
|
||||
}
|
||||
|
||||
// whether this font family is in "bad" underline offset blacklist.
|
||||
PRBool IsBadUnderlineFont() { return mIsBadUnderlineFont != 0; }
|
||||
|
||||
PRBool TestCharacterMap(PRUint32 aCh);
|
||||
|
||||
PRUint8 mWindowsFamily;
|
||||
PRUint8 mWindowsPitch;
|
||||
|
||||
gfxWindowsFontType mFontType;
|
||||
PRPackedBool mIsBadUnderlineFont : 1;
|
||||
PRPackedBool mForceGDI : 1;
|
||||
PRPackedBool mUnknownCMAP : 1;
|
||||
|
||||
@ -317,7 +337,7 @@ private:
|
||||
class THEBES_API gfxWindowsFontGroup : public gfxFontGroup {
|
||||
|
||||
public:
|
||||
gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle);
|
||||
gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle* aStyle, gfxUserFontSet *aUserFontSet);
|
||||
virtual ~gfxWindowsFontGroup();
|
||||
|
||||
virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
|
||||
@ -349,8 +369,10 @@ public:
|
||||
const nsCString& aLangGroup,
|
||||
nsTArray<nsRefPtr<FontEntry> > *list);
|
||||
|
||||
void UpdateFontList();
|
||||
|
||||
protected:
|
||||
void InitFontList();
|
||||
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const char *aString, PRUint32 aLength);
|
||||
void InitTextRunGDI(gfxContext *aContext, gfxTextRun *aRun, const PRUnichar *aString, PRUint32 aLength);
|
||||
|
||||
|
@ -75,7 +75,23 @@ public:
|
||||
nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
|
||||
|
||||
gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet);
|
||||
|
||||
/**
|
||||
* Look up a local platform font using the full font face name (needed to support @font-face src local() )
|
||||
*/
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
|
||||
|
||||
/**
|
||||
* Activate a platform font (needed to support @font-face src url() )
|
||||
*/
|
||||
virtual gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData);
|
||||
|
||||
/**
|
||||
* Check whether format is supported on a platform or not (if unclear, returns true)
|
||||
*/
|
||||
virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
|
||||
|
||||
/* Given a string and a font we already have find the font that
|
||||
* supports the most code points and most closely resembles aFont
|
||||
|
@ -38,6 +38,7 @@ CPPSRCS = \
|
||||
gfxSkipChars.cpp \
|
||||
gfxTextRunCache.cpp \
|
||||
gfxTextRunWordCache.cpp \
|
||||
gfxUserFontSet.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
|
@ -58,6 +58,7 @@
|
||||
|
||||
#include "gfxQuartzSurface.h"
|
||||
#include "gfxQuartzFontCache.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include "nsUnicodeRange.h"
|
||||
|
||||
@ -322,7 +323,7 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef)
|
||||
if (glyphID == 0) // no zero in this font
|
||||
mMetrics.zeroOrAveCharWidth = mMetrics.aveCharWidth;
|
||||
|
||||
SanitizeMetrics(&mMetrics, GetFontEntry()->FamilyEntry()->IsBadUnderlineFontFamily());
|
||||
SanitizeMetrics(&mMetrics, GetFontEntry()->mIsBadUnderlineFont);
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "Font: %p size: %f (fixed: %d)", this, size, gfxQuartzFontCache::SharedFontCache()->IsFixedPitch(aFontID));
|
||||
@ -501,9 +502,11 @@ GetOrMakeFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aStyle, PRBool aNe
|
||||
return static_cast<gfxAtsuiFont *>(f);
|
||||
}
|
||||
|
||||
|
||||
gfxAtsuiFontGroup::gfxAtsuiFontGroup(const nsAString& families,
|
||||
const gfxFontStyle *aStyle)
|
||||
: gfxFontGroup(families, aStyle)
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: gfxFontGroup(families, aStyle, aUserFontSet)
|
||||
{
|
||||
ForEachFont(FindATSUFont, this);
|
||||
|
||||
@ -536,7 +539,7 @@ gfxAtsuiFontGroup::gfxAtsuiFontGroup(const nsAString& families,
|
||||
if (!mStyle.systemFont) {
|
||||
for (PRUint32 i = 0; i < mFonts.Length(); ++i) {
|
||||
gfxAtsuiFont* font = static_cast<gfxAtsuiFont*>(mFonts[i].get());
|
||||
if (font->GetFontEntry()->FamilyEntry()->IsBadUnderlineFontFamily()) {
|
||||
if (font->GetFontEntry()->mIsBadUnderlineFont) {
|
||||
gfxFloat first = mFonts[0]->GetMetrics().underlineOffset;
|
||||
gfxFloat bad = font->GetMetrics().underlineOffset;
|
||||
mUnderlineOffset = PR_MIN(first, bad);
|
||||
@ -554,10 +557,23 @@ gfxAtsuiFontGroup::FindATSUFont(const nsAString& aName,
|
||||
gfxAtsuiFontGroup *fontGroup = (gfxAtsuiFontGroup*) closure;
|
||||
const gfxFontStyle *fontStyle = fontGroup->GetStyle();
|
||||
|
||||
gfxQuartzFontCache *fc = gfxQuartzFontCache::SharedFontCache();
|
||||
|
||||
PRBool needsBold;
|
||||
MacOSFontEntry *fe = fc->FindFontForFamily(aName, fontStyle, needsBold);
|
||||
MacOSFontEntry *fe = nsnull;
|
||||
|
||||
// first, look up in the user font set
|
||||
gfxUserFontSet *fs = fontGroup->GetUserFontSet();
|
||||
gfxFontEntry *gfe;
|
||||
if (fs && (gfe = fs->FindFontEntry(aName, *fontStyle, needsBold))) {
|
||||
// assume for now platform font if not SVG
|
||||
fe = static_cast<MacOSFontEntry*> (gfe);
|
||||
}
|
||||
|
||||
// nothing in the user font set ==> check system fonts
|
||||
if (!fe) {
|
||||
gfxQuartzFontCache *fc = gfxQuartzFontCache::SharedFontCache();
|
||||
fe = fc->FindFontForFamily(aName, fontStyle, needsBold);
|
||||
}
|
||||
|
||||
if (fe && !fontGroup->HasFont(fe->GetFontID())) {
|
||||
nsRefPtr<gfxAtsuiFont> font = GetOrMakeFont(fe, fontStyle, needsBold);
|
||||
@ -572,7 +588,7 @@ gfxAtsuiFontGroup::FindATSUFont(const nsAString& aName,
|
||||
gfxFontGroup *
|
||||
gfxAtsuiFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
{
|
||||
return new gfxAtsuiFontGroup(mFamilies, aStyle);
|
||||
return new gfxAtsuiFontGroup(mFamilies, aStyle, mUserFontSet);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -933,6 +949,19 @@ gfxAtsuiFontGroup::WhichSystemFontSupportsChar(PRUint32 aCh)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
gfxAtsuiFontGroup::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();
|
||||
ForEachFont(FindATSUFont, this);
|
||||
mCurrGeneration = GetGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple wrapper for ATSU "direct data arrays"
|
||||
*/
|
||||
@ -1392,8 +1421,8 @@ gfxAtsuiFontGroup::InitTextRun(gfxTextRun *aRun,
|
||||
("InitTextRun %p fontgroup %p (%s) lang: %s len %d TEXTRUN \"%s\" ENDTEXTRUN\n",
|
||||
aRun, this, families.get(), mStyle.langGroup.get(), aLengthInTextRun, str.get()) );
|
||||
PR_LOG(gAtsuiTextRunLog, PR_LOG_DEBUG,
|
||||
("InitTextRun font: %s\n",
|
||||
NS_ConvertUTF16toUTF8(firstFont->GetUniqueName()).get()) );
|
||||
("InitTextRun font: %s user font set: %p (%8.8x)\n",
|
||||
NS_ConvertUTF16toUTF8(firstFont->GetUniqueName()).get(), mUserFontSet, PRUint32(mCurrGeneration)) );
|
||||
#endif
|
||||
|
||||
if (aRun->GetFlags() & TEXT_DISABLE_OPTIONAL_LIGATURES) {
|
||||
|
@ -49,7 +49,9 @@
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxFontMissingGlyphs.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "gfxFontTest.h"
|
||||
@ -74,8 +76,10 @@ static PRUint32 gGlyphExtentsSetupLazyTight = 0;
|
||||
static PRUint32 gGlyphExtentsSetupFallBackToTight = 0;
|
||||
#endif
|
||||
|
||||
gfxFontEntry::~gfxFontEntry() {
|
||||
|
||||
gfxFontEntry::~gfxFontEntry()
|
||||
{
|
||||
if (mUserFontData)
|
||||
delete mUserFontData;
|
||||
}
|
||||
|
||||
|
||||
@ -91,7 +95,9 @@ gfxFontEntry *gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle, PR
|
||||
|
||||
aNeedsBold = PR_FALSE;
|
||||
|
||||
FindWeightsForStyle(weightList, aFontStyle);
|
||||
PRBool foundWeights = FindWeightsForStyle(weightList, aFontStyle);
|
||||
if (!foundWeights)
|
||||
return nsnull;
|
||||
|
||||
PRInt8 baseWeight, weightDistance;
|
||||
aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
||||
@ -856,10 +862,32 @@ gfxGlyphExtents::SetTightGlyphExtents(PRUint32 aGlyphID, const gfxRect& aExtents
|
||||
entry->height = aExtentsAppUnits.size.height;
|
||||
}
|
||||
|
||||
gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
|
||||
gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet)
|
||||
: mFamilies(aFamilies), mStyle(*aStyle), mUnderlineOffset(UNDERLINE_OFFSET_NOT_SET)
|
||||
{
|
||||
mUserFontSet = nsnull;
|
||||
SetUserFontSet(aUserFontSet);
|
||||
}
|
||||
|
||||
gfxFontGroup::~gfxFontGroup() {
|
||||
mFonts.Clear();
|
||||
SetUserFontSet(nsnull);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
gfxFontGroup::IsInvalidChar(PRUnichar ch) {
|
||||
if (ch >= 32) {
|
||||
return ch == 0x0085/*NEL*/ ||
|
||||
((ch & 0xFF00) == 0x2000 /* Unicode control character */ &&
|
||||
(ch == 0x200B/*ZWSP*/ || ch == 0x2028/*LSEP*/ || ch == 0x2029/*PSEP*/ ||
|
||||
IS_BIDI_CONTROL_CHAR(ch)));
|
||||
}
|
||||
// We could just blacklist all control characters, but it seems better
|
||||
// to only blacklist the ones we know cause problems for native font
|
||||
// engines.
|
||||
return ch == 0x0B || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\f' ||
|
||||
(ch >= 0x1c && ch <= 0x1f);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -989,11 +1017,18 @@ gfxFontGroup::ForEachFontInternal(const nsAString& aFamilies,
|
||||
NS_LossyConvertUTF16toASCII gf(genericFamily);
|
||||
if (aResolveFontName) {
|
||||
ResolveData data(fc, gf, closure);
|
||||
PRBool aborted;
|
||||
gfxPlatform *pf = gfxPlatform::GetPlatform();
|
||||
nsresult rv = pf->ResolveFontName(family,
|
||||
PRBool aborted, needsBold;
|
||||
nsresult rv;
|
||||
|
||||
if (mUserFontSet && mUserFontSet->FindFontEntry(family, mStyle, needsBold)) {
|
||||
gfxFontGroup::FontResolverProc(family, &data);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
gfxPlatform *pf = gfxPlatform::GetPlatform();
|
||||
rv = pf->ResolveFontName(family,
|
||||
gfxFontGroup::FontResolverProc,
|
||||
&data, aborted);
|
||||
}
|
||||
if (NS_FAILED(rv) || aborted)
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -1089,7 +1124,7 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh, PRUint32 aNextCh,
|
||||
// if match, return
|
||||
if (selectedFont)
|
||||
return selectedFont.forget();
|
||||
|
||||
|
||||
// if character is in Private Use Area, don't do matching against pref or system fonts
|
||||
if ((aCh >= 0xE000 && aCh <= 0xF8FF) || (aCh >= 0xF0000 && aCh <= 0x10FFFD))
|
||||
return nsnull;
|
||||
@ -1169,6 +1204,29 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges, const PRUnicha
|
||||
aRanges[aRanges.Length()-1].end = len;
|
||||
}
|
||||
|
||||
gfxUserFontSet*
|
||||
gfxFontGroup::GetUserFontSet()
|
||||
{
|
||||
return mUserFontSet;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontGroup::SetUserFontSet(gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
NS_IF_RELEASE(mUserFontSet);
|
||||
mUserFontSet = aUserFontSet;
|
||||
NS_IF_ADDREF(mUserFontSet);
|
||||
mCurrGeneration = GetGeneration();
|
||||
}
|
||||
|
||||
PRUint64
|
||||
gfxFontGroup::GetGeneration()
|
||||
{
|
||||
if (!mUserFontSet)
|
||||
return 0;
|
||||
return mUserFontSet->GetGeneration();
|
||||
}
|
||||
|
||||
|
||||
#define DEFAULT_PIXEL_FONT_SIZE 16.0f
|
||||
|
||||
@ -1331,6 +1389,8 @@ gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void
|
||||
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
|
||||
AccountStorageForTextRun(this, 1);
|
||||
#endif
|
||||
|
||||
mUserFontSetGeneration = mFontGroup->GetGeneration();
|
||||
}
|
||||
|
||||
gfxTextRun::~gfxTextRun()
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIStreamBufferAccess.h"
|
||||
#include "nsILocalFile.h"
|
||||
|
||||
#define NO_RANGE_FOUND 126 // bit 126 in the font unicode ranges is required to be 0
|
||||
|
||||
@ -469,4 +471,558 @@ void gfxFontUtils::GetPrefsFontList(const char *aPrefName, nsTArray<nsString>& a
|
||||
|
||||
}
|
||||
|
||||
// for now, this is only needed on Windows
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
// TrueType/OpenType table handling code
|
||||
|
||||
// need byte aligned structs
|
||||
#pragma pack(1)
|
||||
|
||||
struct AutoSwap_PRUint16 {
|
||||
operator PRUint16() { return NS_SWAP16(value); }
|
||||
operator PRUint32() { return NS_SWAP16(value); }
|
||||
PRUint16 value;
|
||||
};
|
||||
|
||||
struct AutoSwap_PRInt16 {
|
||||
operator PRInt16() { return NS_SWAP16(value); }
|
||||
operator PRUint32() { return NS_SWAP16(value); }
|
||||
PRInt16 value;
|
||||
};
|
||||
|
||||
struct AutoSwap_PRUint32 {
|
||||
operator PRUint32() { return NS_SWAP32(value); }
|
||||
PRUint32 value;
|
||||
};
|
||||
|
||||
struct AutoSwap_PRUint64 {
|
||||
operator PRUint64() { return NS_SWAP64(value); }
|
||||
PRUint64 value;
|
||||
};
|
||||
|
||||
struct SFNTHeader {
|
||||
AutoSwap_PRUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0.
|
||||
AutoSwap_PRUint16 numTables; // Number of tables.
|
||||
AutoSwap_PRUint16 searchRange; // (Maximum power of 2 <= numTables) x 16.
|
||||
AutoSwap_PRUint16 entrySelector; // Log2(maximum power of 2 <= numTables).
|
||||
AutoSwap_PRUint16 rangeShift; // NumTables x 16-searchRange.
|
||||
};
|
||||
|
||||
struct TableDirEntry {
|
||||
AutoSwap_PRUint32 tag; // 4 -byte identifier.
|
||||
AutoSwap_PRUint32 checkSum; // CheckSum for this table.
|
||||
AutoSwap_PRUint32 offset; // Offset from beginning of TrueType font file.
|
||||
AutoSwap_PRUint32 length; // Length of this table.
|
||||
};
|
||||
|
||||
struct HeadTable {
|
||||
enum {
|
||||
HEAD_MAGIC_NUMBER = 0x5F0F3CF5
|
||||
};
|
||||
|
||||
AutoSwap_PRUint32 tableVersionNumber; // Fixed, 0x00010000 for version 1.0.
|
||||
AutoSwap_PRUint32 fontRevision; // Set by font manufacturer.
|
||||
AutoSwap_PRUint32 checkSumAdjustment; // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
|
||||
AutoSwap_PRUint32 magicNumber; // Set to 0x5F0F3CF5.
|
||||
AutoSwap_PRUint16 flags;
|
||||
AutoSwap_PRUint16 unitsPerEm; // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
|
||||
AutoSwap_PRUint64 created; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
|
||||
AutoSwap_PRUint64 modified; // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
|
||||
AutoSwap_PRInt16 xMin; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 yMin; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 xMax; // For all glyph bounding boxes.
|
||||
AutoSwap_PRInt16 yMax; // For all glyph bounding boxes.
|
||||
AutoSwap_PRUint16 macStyle; // Bit 0: Bold (if set to 1);
|
||||
AutoSwap_PRUint16 lowestRecPPEM; // Smallest readable size in pixels.
|
||||
AutoSwap_PRInt16 fontDirectionHint;
|
||||
AutoSwap_PRInt16 indexToLocFormat;
|
||||
AutoSwap_PRInt16 glyphDataFormat;
|
||||
};
|
||||
|
||||
// name table has a header, followed by name records, followed by string data
|
||||
struct NameHeader {
|
||||
AutoSwap_PRUint16 format; // Format selector (=0).
|
||||
AutoSwap_PRUint16 count; // Number of name records.
|
||||
AutoSwap_PRUint16 stringOffset; // Offset to start of string storage (from start of table)
|
||||
};
|
||||
|
||||
struct NameRecord {
|
||||
AutoSwap_PRUint16 platformID; // Platform ID
|
||||
AutoSwap_PRUint16 encodingID; // Platform-specific encoding ID
|
||||
AutoSwap_PRUint16 languageID; // Language ID
|
||||
AutoSwap_PRUint16 nameID; // Name ID.
|
||||
AutoSwap_PRUint16 length; // String length (in bytes).
|
||||
AutoSwap_PRUint16 offset; // String offset from start of storage area (in bytes).
|
||||
|
||||
enum {
|
||||
NAME_ID_FAMILY = 1,
|
||||
NAME_ID_STYLE = 2,
|
||||
NAME_ID_FULL = 4,
|
||||
NAME_ID_VERSION = 5,
|
||||
PLATFORM_ID_UNICODE = 0, // Mac OS uses this typically
|
||||
PLATFORM_ID_MICROSOFT = 3,
|
||||
ENCODING_ID_MICROSOFT_UNICODEBMP = 1, // with Microsoft platformID, BMP-only Unicode encoding
|
||||
LANG_ID_MICROSOFT_EN_US = 0x0409 // with Microsoft platformID, EN US lang code
|
||||
};
|
||||
};
|
||||
|
||||
struct OS2Table {
|
||||
AutoSwap_PRUint16 version; // 0004 = OpenType 1.5
|
||||
AutoSwap_PRInt16 xAvgCharWidth;
|
||||
AutoSwap_PRUint16 usWeightClass;
|
||||
AutoSwap_PRUint16 usWidthClass;
|
||||
AutoSwap_PRUint16 fsType;
|
||||
AutoSwap_PRInt16 ySubscriptXSize;
|
||||
AutoSwap_PRInt16 ySubscriptYSize;
|
||||
AutoSwap_PRInt16 ySubscriptXOffset;
|
||||
AutoSwap_PRInt16 ySubscriptYOffset;
|
||||
AutoSwap_PRInt16 ySuperscriptXSize;
|
||||
AutoSwap_PRInt16 ySuperscriptYSize;
|
||||
AutoSwap_PRInt16 ySuperscriptXOffset;
|
||||
AutoSwap_PRInt16 ySuperscriptYOffset;
|
||||
AutoSwap_PRInt16 yStrikeoutSize;
|
||||
AutoSwap_PRInt16 yStrikeoutPosition;
|
||||
AutoSwap_PRInt16 sFamilyClass;
|
||||
PRUint8 panose[10];
|
||||
AutoSwap_PRUint32 unicodeRange1;
|
||||
AutoSwap_PRUint32 unicodeRange2;
|
||||
AutoSwap_PRUint32 unicodeRange3;
|
||||
AutoSwap_PRUint32 unicodeRange4;
|
||||
PRUint8 achVendID[4];
|
||||
AutoSwap_PRUint16 fsSelection;
|
||||
AutoSwap_PRUint16 usFirstCharIndex;
|
||||
AutoSwap_PRUint16 usLastCharIndex;
|
||||
AutoSwap_PRInt16 sTypoAscender;
|
||||
AutoSwap_PRInt16 sTypoDescender;
|
||||
AutoSwap_PRInt16 sTypoLineGap;
|
||||
AutoSwap_PRUint16 usWinAscent;
|
||||
AutoSwap_PRUint16 usWinDescent;
|
||||
AutoSwap_PRUint32 codePageRange1;
|
||||
AutoSwap_PRUint32 codePageRange2;
|
||||
AutoSwap_PRInt16 sxHeight;
|
||||
AutoSwap_PRInt16 sCapHeight;
|
||||
AutoSwap_PRUint16 usDefaultChar;
|
||||
AutoSwap_PRUint16 usBreakChar;
|
||||
AutoSwap_PRUint16 usMaxContext;
|
||||
};
|
||||
|
||||
// Embedded OpenType (EOT) handling
|
||||
// needed for dealing with downloadable fonts on Windows
|
||||
//
|
||||
// EOT version 0x00020001
|
||||
// based on http://www.w3.org/Submission/2008/SUBM-EOT-20080305/
|
||||
//
|
||||
// EOT header consists of a fixed-size portion containing general font
|
||||
// info, followed by a variable-sized portion containing name data,
|
||||
// followed by the actual TT/OT font data (non-byte values are always
|
||||
// stored in big-endian format)
|
||||
//
|
||||
// EOT header is stored in *little* endian order!!
|
||||
|
||||
struct EOTFixedHeader {
|
||||
|
||||
PRUint32 eotSize; // Total structure length in PRUint8s (including string and font data)
|
||||
PRUint32 fontDataSize; // Length of the OpenType font (FontData) in PRUint8s
|
||||
PRUint32 version; // Version number of this format - 0x00010000
|
||||
PRUint32 flags; // Processing Flags
|
||||
PRUint8 panose[10]; // The PANOSE value for this font - See http://www.microsoft.com/typography/otspec/os2.htm#pan
|
||||
PRUint8 charset; // In Windows this is derived from TEXTMETRIC.tmCharSet. This value specifies the character set of the font. DEFAULT_CHARSET (0x01) indicates no preference. - See http://msdn2.microsoft.com/en-us/library/ms534202.aspx
|
||||
PRUint8 italic; // If the bit for ITALIC is set in OS/2.fsSelection, the value will be 0x01 - See http://www.microsoft.com/typography/otspec/os2.htm#fss
|
||||
PRUint32 weight; // The weight value for this font - See http://www.microsoft.com/typography/otspec/os2.htm#wtc
|
||||
PRUint16 fsType; // Type flags that provide information about embedding permissions - See http://www.microsoft.com/typography/otspec/os2.htm#fst
|
||||
PRUint16 magicNumber; // Magic number for EOT file - 0x504C. Used to check for data corruption.
|
||||
PRUint32 unicodeRange1; // OS/2.UnicodeRange1 (bits 0-31) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
|
||||
PRUint32 unicodeRange2; // OS/2.UnicodeRange2 (bits 32-63) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
|
||||
PRUint32 unicodeRange3; // OS/2.UnicodeRange3 (bits 64-95) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
|
||||
PRUint32 unicodeRange4; // OS/2.UnicodeRange4 (bits 96-127) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
|
||||
PRUint32 codePageRange1; // CodePageRange1 (bits 0-31) - See http://www.microsoft.com/typography/otspec/os2.htm#cpr
|
||||
PRUint32 codePageRange2; // CodePageRange2 (bits 32-63) - See http://www.microsoft.com/typography/otspec/os2.htm#cpr
|
||||
PRUint32 checkSumAdjustment; // head.CheckSumAdjustment - See http://www.microsoft.com/typography/otspec/head.htm
|
||||
PRUint32 reserved[4]; // Reserved - must be 0
|
||||
PRUint16 padding1; // Padding to maintain long alignment. Padding value must always be set to 0x0000.
|
||||
|
||||
enum {
|
||||
EOT_VERSION = 0x00020001,
|
||||
EOT_MAGIC_NUMBER = 0x504c,
|
||||
EOT_DEFAULT_CHARSET = 0x01,
|
||||
EOT_EMBED_PRINT_PREVIEW = 0x0004,
|
||||
EOT_FAMILY_NAME_INDEX = 0, // order of names in variable portion of EOT header
|
||||
EOT_STYLE_NAME_INDEX = 1,
|
||||
EOT_VERSION_NAME_INDEX = 2,
|
||||
EOT_FULL_NAME_INDEX = 3,
|
||||
EOT_NUM_NAMES = 4
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// EOT variable-sized header (version 0x00020001 - contains 4 name
|
||||
// fields, each with the structure):
|
||||
//
|
||||
// // number of bytes in the name array
|
||||
// PRUint16 size;
|
||||
// // array of UTF-16 chars, total length = <size> bytes
|
||||
// // note: english version of name record string
|
||||
// PRUint8 name[size];
|
||||
//
|
||||
// This structure is used for the following names, each separated by two
|
||||
// bytes of padding (always 0 with no padding after the rootString):
|
||||
//
|
||||
// familyName - based on name ID = 1
|
||||
// styleName - based on name ID = 2
|
||||
// versionName - based on name ID = 5
|
||||
// fullName - based on name ID = 4
|
||||
// rootString - used to restrict font usage to a specific domain
|
||||
//
|
||||
|
||||
class AutoCloseFile {
|
||||
public:
|
||||
AutoCloseFile(PRFileDesc *aFileDesc)
|
||||
: mFile(aFileDesc) { }
|
||||
~AutoCloseFile() { PR_Close(mFile); }
|
||||
PRFileDesc *mFile;
|
||||
};
|
||||
|
||||
static PRFileDesc *
|
||||
OpenFontFile(nsIFile *aFontData)
|
||||
{
|
||||
// open up the font file
|
||||
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFontData);
|
||||
if (!localFile)
|
||||
return nsnull;
|
||||
|
||||
PRFileDesc *fd;
|
||||
nsresult rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
|
||||
if (NS_FAILED(rv) || !fd)
|
||||
return nsnull;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
IsValidVersion(PRUint32 version)
|
||||
{
|
||||
// normally 0x00010000, CFF-style OT fonts == 'OTTO' and Apple TT fonts = 'true'
|
||||
return version == 0x10000 || version == 'OTTO' || version == 'true';
|
||||
}
|
||||
|
||||
// copy and swap UTF-16 values, assume no surrogate pairs, can be in place
|
||||
static void
|
||||
CopySwapUTF16(PRUint16 *aInBuf, PRUint16 *aOutBuf, PRUint32 aLen)
|
||||
{
|
||||
PRUint16 *end = aInBuf + aLen;
|
||||
while (aInBuf < end) {
|
||||
PRUint16 value = *aInBuf;
|
||||
*aOutBuf = (value >> 8) | (value & 0xff) << 8;
|
||||
aOutBuf++;
|
||||
aInBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
// name table stores set of name record structures, followed by
|
||||
// large block containing all the strings. name record offset and length
|
||||
// indicates the offset and length within that block.
|
||||
// http://www.microsoft.com/typography/otspec/name.htm
|
||||
struct NameRecordData {
|
||||
PRUint32 offset;
|
||||
PRUint32 length;
|
||||
};
|
||||
|
||||
#if DEBUG
|
||||
static void DumpEOTHeader(PRUint8 *aHeader, PRUint32 aHeaderLen)
|
||||
{
|
||||
PRUint32 offset = 0;
|
||||
PRUint8 *ch = aHeader;
|
||||
|
||||
printf("\n\nlen == %d\n\n", aHeaderLen);
|
||||
while (offset < aHeaderLen) {
|
||||
printf("%7.7x ", offset);
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
printf("%2.2x ", *ch++);
|
||||
}
|
||||
printf("\n");
|
||||
offset += 16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::MakeEOTHeader(nsIFile *aFontData, nsTArray<PRUint8> *aHeader,
|
||||
PRBool *aIsCFF)
|
||||
{
|
||||
PRInt32 bytesRead;
|
||||
|
||||
// assume TrueType
|
||||
*aIsCFF = PR_FALSE;
|
||||
|
||||
NS_ASSERTION(aHeader, "null header");
|
||||
NS_ASSERTION(aHeader->Length() == 0, "non-empty header passed in");
|
||||
NS_ASSERTION(aIsCFF, "null boolean ptr");
|
||||
|
||||
if (!aHeader->AppendElements(sizeof(EOTFixedHeader)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
EOTFixedHeader *eotHeader = reinterpret_cast<EOTFixedHeader*> (aHeader->Elements());
|
||||
memset(eotHeader, 0, sizeof(EOTFixedHeader));
|
||||
|
||||
// open the font file
|
||||
PRFileDesc *fd = OpenFontFile(aFontData);
|
||||
if (!fd)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
AutoCloseFile autoCloseFile(fd);
|
||||
|
||||
PRFileInfo64 fileInfo;
|
||||
if (PR_GetOpenFileInfo64(fd, &fileInfo) != PR_SUCCESS
|
||||
|| fileInfo.size > PRInt64(0xFFFFFFFF))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 fontDataSize = PRUint32(fileInfo.size);
|
||||
|
||||
// set up header fields
|
||||
eotHeader->fontDataSize = fontDataSize;
|
||||
eotHeader->version = EOTFixedHeader::EOT_VERSION;
|
||||
eotHeader->flags = 0; // don't specify any special processing
|
||||
eotHeader->charset = EOTFixedHeader::EOT_DEFAULT_CHARSET;
|
||||
eotHeader->fsType = EOTFixedHeader::EOT_EMBED_PRINT_PREVIEW;
|
||||
eotHeader->magicNumber = EOTFixedHeader::EOT_MAGIC_NUMBER;
|
||||
|
||||
// read in the sfnt header
|
||||
SFNTHeader sfntHeader;
|
||||
bytesRead = PR_Read(fd, &sfntHeader, sizeof(SFNTHeader));
|
||||
if (bytesRead != sizeof(SFNTHeader) || !IsValidVersion(sfntHeader.sfntVersion))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// iterate through the table headers to find the head, name and OS/2 tables
|
||||
PRBool foundHead = PR_FALSE, foundOS2 = PR_FALSE, foundName = PR_FALSE, foundGlyphs = PR_FALSE;
|
||||
PRUint32 headOffset, headLen, nameOffset, nameLen, os2Offset, os2Len;
|
||||
PRUint32 i, numTables;
|
||||
|
||||
numTables = sfntHeader.numTables;
|
||||
for (i = 0; i < numTables; i++) {
|
||||
TableDirEntry dirEntry;
|
||||
bytesRead = PR_Read(fd, &dirEntry, sizeof(TableDirEntry));
|
||||
if (bytesRead != sizeof(TableDirEntry))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
switch (dirEntry.tag) {
|
||||
|
||||
case 'head':
|
||||
foundHead = PR_TRUE;
|
||||
headOffset = dirEntry.offset;
|
||||
headLen = dirEntry.length;
|
||||
if (headLen < sizeof(HeadTable))
|
||||
return NS_ERROR_FAILURE;
|
||||
break;
|
||||
|
||||
case 'name':
|
||||
foundName = PR_TRUE;
|
||||
nameOffset = dirEntry.offset;
|
||||
nameLen = dirEntry.length;
|
||||
break;
|
||||
|
||||
case 'OS/2':
|
||||
foundOS2 = PR_TRUE;
|
||||
os2Offset = dirEntry.offset;
|
||||
os2Len = dirEntry.length;
|
||||
break;
|
||||
|
||||
case 'glyf': // TrueType-style quadratic glyph table
|
||||
foundGlyphs = PR_TRUE;
|
||||
break;
|
||||
|
||||
case 'CFF ': // PS-style cubic glyph table
|
||||
foundGlyphs = PR_TRUE;
|
||||
*aIsCFF = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (foundHead && foundName && foundOS2 && foundGlyphs)
|
||||
break;
|
||||
}
|
||||
|
||||
// require these three tables on Windows
|
||||
if (!foundHead || !foundName || !foundOS2)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// read in the data from those tables
|
||||
PROffset64 offset;
|
||||
|
||||
// -- head table data
|
||||
HeadTable headData;
|
||||
offset = PR_Seek64(fd, PROffset64(headOffset), PR_SEEK_SET);
|
||||
if (offset == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
bytesRead = PR_Read(fd, &headData, sizeof(HeadTable));
|
||||
if (bytesRead != sizeof(HeadTable) || headData.magicNumber != HeadTable::HEAD_MAGIC_NUMBER)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
eotHeader->checkSumAdjustment = headData.checkSumAdjustment;
|
||||
|
||||
// -- name table data
|
||||
|
||||
// -- first, read name table header
|
||||
NameHeader nameHeader;
|
||||
|
||||
offset = PR_Seek64(fd, PROffset64(nameOffset), PR_SEEK_SET);
|
||||
if (offset == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
bytesRead = PR_Read(fd, &nameHeader, sizeof(NameHeader));
|
||||
if (bytesRead != sizeof(NameHeader))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// -- seek point is now at the start of name records
|
||||
|
||||
// -- iterate through name records, look for specific name ids with
|
||||
// matching platform/encoding/etc. and store offset/lengths
|
||||
NameRecordData names[EOTFixedHeader::EOT_NUM_NAMES] = {0};
|
||||
PRUint32 nameCount = nameHeader.count;
|
||||
|
||||
for (i = 0; i < nameCount; i++) {
|
||||
NameRecord nameRecord;
|
||||
|
||||
bytesRead = PR_Read(fd, &nameRecord, sizeof(NameRecord));
|
||||
if (bytesRead != sizeof(NameRecord))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// looking for Microsoft English US name strings, skip others
|
||||
if (PRUint32(nameRecord.platformID) != NameRecord::PLATFORM_ID_MICROSOFT ||
|
||||
PRUint32(nameRecord.encodingID) != NameRecord::ENCODING_ID_MICROSOFT_UNICODEBMP ||
|
||||
PRUint32(nameRecord.languageID) != NameRecord::LANG_ID_MICROSOFT_EN_US)
|
||||
continue;
|
||||
|
||||
switch ((PRUint32)nameRecord.nameID) {
|
||||
|
||||
case NameRecord::NAME_ID_FAMILY:
|
||||
names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].offset = nameRecord.offset;
|
||||
names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length = nameRecord.length;
|
||||
break;
|
||||
|
||||
case NameRecord::NAME_ID_STYLE:
|
||||
names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].offset = nameRecord.offset;
|
||||
names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length = nameRecord.length;
|
||||
break;
|
||||
|
||||
case NameRecord::NAME_ID_FULL:
|
||||
names[EOTFixedHeader::EOT_FULL_NAME_INDEX].offset = nameRecord.offset;
|
||||
names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length = nameRecord.length;
|
||||
break;
|
||||
|
||||
case NameRecord::NAME_ID_VERSION:
|
||||
names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].offset = nameRecord.offset;
|
||||
names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length = nameRecord.length;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length &&
|
||||
names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length &&
|
||||
names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length &&
|
||||
names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length &&
|
||||
names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length &&
|
||||
names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length &&
|
||||
names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length))
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// -- expand buffer if needed to include variable-length portion
|
||||
PRUint32 eotVariableLength = 0;
|
||||
eotVariableLength = (names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length & (~1)) +
|
||||
(names[EOTFixedHeader::EOT_STYLE_NAME_INDEX].length & (~1)) +
|
||||
(names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length & (~1)) +
|
||||
(names[EOTFixedHeader::EOT_VERSION_NAME_INDEX].length & (~1)) +
|
||||
EOTFixedHeader::EOT_NUM_NAMES * (2 /* size */
|
||||
+ 2 /* padding */) +
|
||||
2 /* null root string size */;
|
||||
|
||||
if (!aHeader->AppendElements(eotVariableLength))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// append the string data to the end of the EOT header
|
||||
PRUint8 *eotEnd = aHeader->Elements() + sizeof(EOTFixedHeader);
|
||||
PROffset64 strOffset;
|
||||
PRUint32 strLen;
|
||||
|
||||
for (i = 0; i < EOTFixedHeader::EOT_NUM_NAMES; i++) {
|
||||
PRUint32 namelen = names[i].length;
|
||||
PRUint32 nameoff = names[i].offset; // offset from base of string storage
|
||||
|
||||
strOffset = nameOffset + PRUint32(nameHeader.stringOffset) + nameoff;
|
||||
offset = PR_Seek64(fd, strOffset, PR_SEEK_SET);
|
||||
if (offset == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// output 2-byte str size
|
||||
strLen = namelen & (~1); // UTF-16 string len must be even
|
||||
*((PRUint16*) eotEnd) = PRUint16(strLen);
|
||||
eotEnd += 2;
|
||||
|
||||
// read in actual string and swap bytes from big-endian
|
||||
// (TrueType/OpenType) to little-endian (EOT)
|
||||
bytesRead = PR_Read(fd, eotEnd, strLen);
|
||||
if (PRUint32(bytesRead) != strLen)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// length is number of UTF-16 chars, not bytes
|
||||
CopySwapUTF16(reinterpret_cast<PRUint16*>(eotEnd),
|
||||
reinterpret_cast<PRUint16*>(eotEnd),
|
||||
(strLen >> 1));
|
||||
eotEnd += strLen;
|
||||
|
||||
// add 2-byte zero padding to the end of each string
|
||||
*eotEnd++ = 0;
|
||||
*eotEnd++ = 0;
|
||||
|
||||
// Note: Microsoft's WEFT tool produces name strings which
|
||||
// include an extra null at the end of each string, in addition
|
||||
// to the 2-byte zero padding that separates the string fields.
|
||||
// Don't think this is important to imitate...
|
||||
}
|
||||
|
||||
// append null root string size
|
||||
*eotEnd++ = 0;
|
||||
*eotEnd++ = 0;
|
||||
|
||||
NS_ASSERTION(eotEnd == aHeader->Elements() + aHeader->Length(),
|
||||
"header length calculation incorrect");
|
||||
|
||||
// -- OS/2 table data
|
||||
OS2Table os2Data;
|
||||
offset = PR_Seek64(fd, PROffset64(os2Offset), PR_SEEK_SET);
|
||||
if (offset == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
bytesRead = PR_Read(fd, &os2Data, sizeof(OS2Table));
|
||||
if (bytesRead != sizeof(OS2Table))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
memcpy(eotHeader->panose, os2Data.panose, sizeof(eotHeader->panose));
|
||||
|
||||
eotHeader->italic = (PRUint16) os2Data.fsSelection & 0x01;
|
||||
eotHeader->weight = os2Data.usWeightClass;
|
||||
eotHeader->unicodeRange1 = os2Data.unicodeRange1;
|
||||
eotHeader->unicodeRange2 = os2Data.unicodeRange2;
|
||||
eotHeader->unicodeRange3 = os2Data.unicodeRange3;
|
||||
eotHeader->unicodeRange4 = os2Data.unicodeRange4;
|
||||
eotHeader->codePageRange1 = os2Data.codePageRange1;
|
||||
eotHeader->codePageRange2 = os2Data.codePageRange2;
|
||||
|
||||
eotHeader->eotSize = aHeader->Length() + fontDataSize;
|
||||
|
||||
// DumpEOTHeader(aHeader->Elements(), aHeader->Length());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -457,8 +457,9 @@ already_AddRefed<gfxOS2Font> gfxOS2Font::GetOrMakeFont(const nsAString& aName,
|
||||
**********************************************************************/
|
||||
|
||||
gfxOS2FontGroup::gfxOS2FontGroup(const nsAString& aFamilies,
|
||||
const gfxFontStyle* aStyle)
|
||||
: gfxFontGroup(aFamilies, aStyle)
|
||||
const gfxFontStyle* aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: gfxFontGroup(aFamilies, aStyle, aUserFontSet)
|
||||
{
|
||||
#ifdef DEBUG_thebes_2
|
||||
printf("gfxOS2FontGroup[%#x]::gfxOS2FontGroup(\"%s\", %#x)\n",
|
||||
@ -510,7 +511,7 @@ gfxOS2FontGroup::~gfxOS2FontGroup()
|
||||
|
||||
gfxFontGroup *gfxOS2FontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
{
|
||||
return new gfxOS2FontGroup(mFamilies, aStyle);
|
||||
return new gfxOS2FontGroup(mFamilies, aStyle, mUserFontSet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,9 +164,10 @@ gfxOS2Platform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFa
|
||||
|
||||
gfxFontGroup *
|
||||
gfxOS2Platform::CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle)
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
return new gfxOS2FontGroup(aFamilies, aStyle);
|
||||
return new gfxOS2FontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxOS2Font>
|
||||
|
@ -784,8 +784,9 @@ FontCallback (const nsAString& fontName, const nsACString& genericName,
|
||||
}
|
||||
|
||||
gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
|
||||
const gfxFontStyle *aStyle)
|
||||
: gfxFontGroup(families, aStyle),
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: gfxFontGroup(families, aStyle, aUserFontSet),
|
||||
mBasePangoFont(nsnull), mAdjustedSize(0)
|
||||
{
|
||||
mFonts.AppendElements(1);
|
||||
@ -800,7 +801,7 @@ gfxPangoFontGroup::~gfxPangoFontGroup()
|
||||
gfxFontGroup *
|
||||
gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
{
|
||||
return new gfxPangoFontGroup(mFamilies, aStyle);
|
||||
return new gfxPangoFontGroup(mFamilies, aStyle, mUserFontSet);
|
||||
}
|
||||
|
||||
// A string of family names suitable for fontconfig
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxTextRunCache.h"
|
||||
#include "gfxTextRunWordCache.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
@ -304,6 +305,29 @@ gfxPlatform::UpdateFontList()
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
|
||||
|
||||
PRBool
|
||||
gfxPlatform::DownloadableFontsEnabled()
|
||||
{
|
||||
static PRBool initialized = PR_FALSE;
|
||||
static PRBool allowDownloadableFonts = PR_FALSE;
|
||||
|
||||
if (initialized == PR_FALSE) {
|
||||
initialized = PR_TRUE;
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
PRBool allow;
|
||||
nsresult rv = prefs->GetBoolPref(GFX_DOWNLOADABLE_FONTS_ENABLED, &allow);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
allowDownloadableFonts = allow;
|
||||
}
|
||||
}
|
||||
|
||||
return allowDownloadableFonts;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
AppendGenericFontFromPref(nsString& aFonts, const char *aLangGroup, const char *aGenericName)
|
||||
{
|
||||
|
@ -267,9 +267,10 @@ gfxPlatformGtk::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFa
|
||||
|
||||
gfxFontGroup *
|
||||
gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle)
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
return new gfxPangoFontGroup(aFamilies, aStyle);
|
||||
return new gfxPangoFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#include "gfxQuartzFontCache.h"
|
||||
#include "gfxAtsuiFonts.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
@ -115,9 +116,36 @@ gfxPlatformMac::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFa
|
||||
|
||||
gfxFontGroup *
|
||||
gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle)
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
return new gfxAtsuiFontGroup(aFamilies, aStyle);
|
||||
return new gfxAtsuiFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformMac::LookupLocalFont(const nsAString& aFontName)
|
||||
{
|
||||
return gfxQuartzFontCache::SharedFontCache()->LookupLocalFont(aFontName);
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformMac::MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData)
|
||||
{
|
||||
return gfxQuartzFontCache::SharedFontCache()->MakePlatformFont(aProxyEntry, aFontData);
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
|
||||
{
|
||||
// reject based on format flags
|
||||
if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// reject based on filetype in URI
|
||||
|
||||
// otherwise, return true
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -83,13 +83,15 @@ public:
|
||||
ATSUFontID GetFontID();
|
||||
nsresult ReadCMAP();
|
||||
|
||||
MacOSFamilyEntry* FamilyEntry() { return mFamily; }
|
||||
protected:
|
||||
// for use with data fonts
|
||||
MacOSFontEntry(ATSUFontID aFontID, PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle, gfxUserFontData *aUserFontData);
|
||||
|
||||
PRUint32 mTraits;
|
||||
MacOSFamilyEntry *mFamily;
|
||||
|
||||
PRPackedBool mATSUIDInitialized;
|
||||
ATSUFontID mATSUFontID;
|
||||
PRPackedBool mATSUIDInitialized;
|
||||
};
|
||||
|
||||
// helper class for adding other family names back into font cache
|
||||
@ -103,9 +105,8 @@ public:
|
||||
friend class gfxQuartzFontCache;
|
||||
|
||||
// name is canonical font family name returned from NSFontManager
|
||||
MacOSFamilyEntry(nsString &aName) :
|
||||
gfxFontFamily(aName), mOtherFamilyNamesInitialized(PR_FALSE), mHasOtherFamilyNames(PR_FALSE),
|
||||
mIsBadUnderlineFontFamily(PR_FALSE)
|
||||
MacOSFamilyEntry(nsAString &aName) :
|
||||
gfxFontFamily(aName), mOtherFamilyNamesInitialized(PR_FALSE), mHasOtherFamilyNames(PR_FALSE)
|
||||
{}
|
||||
|
||||
virtual ~MacOSFamilyEntry() {}
|
||||
@ -132,7 +133,7 @@ public:
|
||||
virtual void ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFamilyFunctor);
|
||||
|
||||
// search for a specific face using the Postscript name
|
||||
MacOSFontEntry* FindFont(const nsString& aPostscriptName);
|
||||
MacOSFontEntry* FindFont(const nsAString& aPostscriptName);
|
||||
|
||||
// read in cmaps for all the faces
|
||||
void ReadCMAP() {
|
||||
@ -141,9 +142,12 @@ public:
|
||||
mAvailableFonts[i]->ReadCMAP();
|
||||
}
|
||||
|
||||
|
||||
// whether this font family is in "bad" underline offset blacklist.
|
||||
PRBool IsBadUnderlineFontFamily() { return mIsBadUnderlineFontFamily != 0; }
|
||||
// set whether this font family is in "bad" underline offset blacklist.
|
||||
void SetBadUnderlineFont(PRBool aIsBadUnderlineFont) {
|
||||
PRUint32 i, numFonts = mAvailableFonts.Length();
|
||||
for (i = 0; i < numFonts; i++)
|
||||
mAvailableFonts[i]->mIsBadUnderlineFont = aIsBadUnderlineFont;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@ -158,14 +162,13 @@ protected:
|
||||
nsTArray<nsRefPtr<MacOSFontEntry> > mAvailableFonts;
|
||||
PRPackedBool mOtherFamilyNamesInitialized;
|
||||
PRPackedBool mHasOtherFamilyNames;
|
||||
PRPackedBool mIsBadUnderlineFontFamily;
|
||||
};
|
||||
|
||||
// special-case situation where specific faces need to be treated as separate font family
|
||||
class SingleFaceFamily : public MacOSFamilyEntry
|
||||
{
|
||||
public:
|
||||
SingleFaceFamily(nsString &aName) :
|
||||
SingleFaceFamily(nsAString &aName) :
|
||||
MacOSFamilyEntry(aName)
|
||||
{}
|
||||
|
||||
@ -222,6 +225,10 @@ public:
|
||||
|
||||
void AddOtherFamilyName(MacOSFamilyEntry *aFamilyEntry, nsAString& aOtherFamilyName);
|
||||
|
||||
gfxFontEntry* LookupLocalFont(const nsAString& aFontName);
|
||||
|
||||
gfxFontEntry* MakePlatformFont(const gfxFontEntry *aProxyEntry, const gfxDownloadedFontData* aFontData);
|
||||
|
||||
private:
|
||||
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<MacOSFamilyEntry>& aFamilyEntry,
|
||||
@ -244,7 +251,7 @@ private:
|
||||
// commonly used fonts for which the name table should be loaded at startup
|
||||
void PreloadNamesList();
|
||||
|
||||
// initialize the MacOSFamilyEntry::mIsBadUnderlineFontFamily from pref.
|
||||
// initialize the bad underline blacklist from pref.
|
||||
void InitBadUnderlineList();
|
||||
|
||||
// eliminate faces which have the same ATSUI id
|
||||
@ -293,6 +300,13 @@ private:
|
||||
PRUint32 mStartIndex;
|
||||
PRUint32 mIncrement;
|
||||
PRUint32 mNumFamilies;
|
||||
|
||||
// keep track of ATS generation to prevent unneeded updates when loading downloaded fonts
|
||||
PRUint32 mATSGeneration;
|
||||
|
||||
enum {
|
||||
kATSGenerationInitial = -1
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* GFXQUARTZFONTCACHE_H_ */
|
||||
|
@ -44,10 +44,18 @@
|
||||
#include "gfxPlatformMac.h"
|
||||
#include "gfxQuartzFontCache.h"
|
||||
#include "gfxAtsuiFonts.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include "nsIPref.h" // for pref changes callback notification
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
// _atsFontID is private; add it in our new category to NSFont
|
||||
@interface NSFont (MozillaCategory)
|
||||
- (ATSUFontID)_atsFontID;
|
||||
@ -113,12 +121,47 @@ MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
|
||||
: gfxFontEntry(aPostscriptName), mTraits(aTraits), mFamily(aFamily), mATSUFontID(0),
|
||||
mATSUIDInitialized(0)
|
||||
{
|
||||
mWeight = gfxQuartzFontCache::AppleWeightToCSSWeight(aAppleWeight);
|
||||
mWeight = gfxQuartzFontCache::AppleWeightToCSSWeight(aAppleWeight) * 100;
|
||||
|
||||
mItalic = (mTraits & NSItalicFontMask ? 1 : 0);
|
||||
mFixedPitch = (mTraits & NSFixedPitchFontMask ? 1 : 0);
|
||||
}
|
||||
|
||||
MacOSFontEntry::MacOSFontEntry(ATSUFontID aFontID, PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle, gfxUserFontData *aUserFontData)
|
||||
{
|
||||
// xxx - stretch is basically ignored for now
|
||||
|
||||
mATSUIDInitialized = PR_TRUE;
|
||||
mATSUFontID = aFontID;
|
||||
mUserFontData = aUserFontData;
|
||||
mWeight = aWeight;
|
||||
mStretch = aStretch;
|
||||
mFixedPitch = PR_FALSE; // xxx - do we need this for downloaded fonts?
|
||||
mItalic = (aItalicStyle & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
|
||||
|
||||
mTraits = (mItalic ? NSItalicFontMask : NSUnitalicFontMask) |
|
||||
(mFixedPitch ? NSFixedPitchFontMask : 0) |
|
||||
(mWeight >= 600 ? NSBoldFontMask : NSUnboldFontMask);
|
||||
|
||||
// get the postscript name
|
||||
OSStatus err;
|
||||
NSString *psname = NULL;
|
||||
|
||||
// now lookup the Postscript name
|
||||
err = ATSFontGetPostScriptName((ATSFontRef) aFontID, kATSOptionFlagsDefault, (CFStringRef*) (&psname));
|
||||
if (err == noErr) {
|
||||
GetStringForNSString(psname, mName);
|
||||
[psname release];
|
||||
} else {
|
||||
mIsValid = PR_FALSE;
|
||||
#if DEBUG
|
||||
char warnBuf[1024];
|
||||
sprintf(warnBuf, "ATSFontGetPostScriptName err = %d", (PRInt32)err);
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
const nsString&
|
||||
MacOSFontEntry::FamilyName()
|
||||
{
|
||||
@ -174,7 +217,14 @@ MacOSFontEntry::ReadCMAP()
|
||||
|
||||
status = ATSFontGetTable(fontID, 'cmap', 0, 0, 0, &size);
|
||||
cmapSize = size;
|
||||
//printf( "cmap size: %s %d\n", NS_ConvertUTF16toUTF8(mName).get(), size );
|
||||
//printf( "cmap size: %s %d", NS_ConvertUTF16toUTF8(mName).get(), size );
|
||||
#if DEBUG
|
||||
if (status != noErr) {
|
||||
char warnBuf[1024];
|
||||
sprintf(warnBuf, "ATSFontGetTable returned %d for (%s)", (PRInt32)status, NS_ConvertUTF16toUTF8(mName).get());
|
||||
NS_WARNING(warnBuf);
|
||||
}
|
||||
#endif
|
||||
NS_ENSURE_TRUE(status == noErr, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoTArray<PRUint8,16384> buffer;
|
||||
@ -298,7 +348,7 @@ MacOSFamilyEntry::FindFont(const gfxFontStyle* aStyle, PRBool& aNeedsBold)
|
||||
}
|
||||
|
||||
MacOSFontEntry*
|
||||
MacOSFamilyEntry::FindFont(const nsString& aPostscriptName)
|
||||
MacOSFamilyEntry::FindFont(const nsAString& aPostscriptName)
|
||||
{
|
||||
// find the font using a simple linear search
|
||||
PRUint32 numFonts = mAvailableFonts.Length();
|
||||
@ -339,7 +389,7 @@ MacOSFamilyEntry::FindFontForChar(FontSearch *aMatchData)
|
||||
|
||||
// italics
|
||||
if (fe->IsItalic() &&
|
||||
(style->style == FONT_STYLE_ITALIC || style->style == FONT_STYLE_ITALIC)) {
|
||||
(style->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0) {
|
||||
rank += 5;
|
||||
}
|
||||
|
||||
@ -351,7 +401,7 @@ MacOSFamilyEntry::FindFontForChar(FontSearch *aMatchData)
|
||||
// the "next bolder/lighter face"
|
||||
PRUint32 targetWeight = (baseWeight * 100) + (weightDistance * 100);
|
||||
|
||||
PRUint32 entryWeight = fe->Weight() * 100;
|
||||
PRUint32 entryWeight = fe->Weight();
|
||||
if (entryWeight == targetWeight) {
|
||||
rank += 5;
|
||||
} else {
|
||||
@ -393,7 +443,8 @@ MacOSFamilyEntry::FindFontsWithTraits(gfxFontEntry* aFontsForWeights[], PRUint32
|
||||
|
||||
// aPosTraitsMask == 0 ==> match all
|
||||
if ((!aPosTraitsMask || (traits & aPosTraitsMask)) && !(traits & aNegTraitsMask)) {
|
||||
PRInt32 weight = fe->Weight();
|
||||
PRInt32 weight = fe->Weight() / 100;
|
||||
NS_ASSERTION(weight >= 1 && weight <= 9, "bogus font weight value!");
|
||||
|
||||
// always prefer the first font for a given weight, helps deal a bit with
|
||||
// families with lots of faces (e.g. Minion Pro)
|
||||
@ -412,13 +463,14 @@ MacOSFamilyEntry::FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gf
|
||||
// short-circuit the single face per family case
|
||||
if (mAvailableFonts.Length() == 1) {
|
||||
MacOSFontEntry *fe = mAvailableFonts[0];
|
||||
PRUint32 weight = fe->Weight();
|
||||
PRUint32 weight = fe->Weight() / 100;
|
||||
NS_ASSERTION(weight >= 1 && weight <= 9, "bogus font weight value!");
|
||||
aFontsForWeights[weight] = fe;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool found = PR_FALSE;
|
||||
PRBool isItalic = (aFontStyle.style == FONT_STYLE_ITALIC || aFontStyle.style == FONT_STYLE_OBLIQUE);
|
||||
PRBool isItalic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
|
||||
|
||||
// match italic faces
|
||||
if (isItalic) {
|
||||
@ -629,6 +681,8 @@ gfxQuartzFontCache *gfxQuartzFontCache::sSharedFontCache = nsnull;
|
||||
gfxQuartzFontCache::gfxQuartzFontCache()
|
||||
: mStartIndex(0), mIncrement(kNumFontsPerSlice), mNumFamilies(0)
|
||||
{
|
||||
mATSGeneration = PRUint32(kATSGenerationInitial);
|
||||
|
||||
mFontFamilies.Init(100);
|
||||
mOtherFamilyNames.Init(30);
|
||||
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||
@ -652,6 +706,15 @@ const PRUint32 kNonNormalTraits = NSItalicFontMask | NSBoldFontMask | NSNarrowFo
|
||||
void
|
||||
gfxQuartzFontCache::InitFontList()
|
||||
{
|
||||
ATSGeneration currentGeneration = ATSGeneration();
|
||||
|
||||
// need to ignore notifications after adding each font
|
||||
if (mATSGeneration == currentGeneration)
|
||||
return;
|
||||
|
||||
mATSGeneration = currentGeneration;
|
||||
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit) updating to generation: %d", mATSGeneration));
|
||||
|
||||
mFontFamilies.Clear();
|
||||
mOtherFamilyNames.Clear();
|
||||
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||
@ -918,7 +981,7 @@ gfxQuartzFontCache::InitBadUnderlineList()
|
||||
|
||||
MacOSFamilyEntry *familyEntry = mFontFamilies.GetWeak(key, &found);
|
||||
if (familyEntry)
|
||||
familyEntry->mIsBadUnderlineFontFamily = 1;
|
||||
familyEntry->SetBadUnderlineFont(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,6 +1268,158 @@ gfxQuartzFontCache::AddOtherFamilyName(MacOSFamilyEntry *aFamilyEntry, nsAString
|
||||
}
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxQuartzFontCache::LookupLocalFont(const nsAString& aFontName)
|
||||
{
|
||||
NSString *faceName = GetNSStringForString(aFontName);
|
||||
NSFont *font = [NSFont fontWithName:faceName size:0.0];
|
||||
|
||||
if (font) {
|
||||
nsAutoString availableFamilyName;
|
||||
NSString *availableFamily = [font familyName];
|
||||
GetStringForNSString(availableFamily, availableFamilyName);
|
||||
|
||||
MacOSFamilyEntry *familyEntry = FindFamily(availableFamilyName);
|
||||
if (familyEntry) {
|
||||
MacOSFontEntry *fontEntry = familyEntry->FindFont(aFontName);
|
||||
return fontEntry;
|
||||
}
|
||||
}
|
||||
|
||||
// didn't find the font
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// grumble, another non-publised Apple API dependency (found in Webkit code)
|
||||
// activated with this value, font will not be found via system lookup routines
|
||||
// it can only be used via the created ATSUFontID
|
||||
// needed to prevent one doc from finding a font used in a separate doc
|
||||
|
||||
enum {
|
||||
kPrivateATSFontContextPrivate = 3
|
||||
};
|
||||
|
||||
class MacOSUserFontData : public gfxUserFontData {
|
||||
public:
|
||||
MacOSUserFontData(ATSFontContainerRef aContainerRef, nsIFile *aFontFile,
|
||||
nsISupports *aDownloader)
|
||||
: mContainerRef(aContainerRef), mFontFile(aFontFile),
|
||||
mDownloader(aDownloader)
|
||||
{ }
|
||||
|
||||
virtual ~MacOSUserFontData()
|
||||
{
|
||||
// deactivate font
|
||||
if (mContainerRef)
|
||||
ATSFontDeactivate(mContainerRef, NULL, kATSOptionFlagsDefault);
|
||||
|
||||
if (mFontFile) {
|
||||
mFontFile->Remove(PR_FALSE); // ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
ATSFontContainerRef mContainerRef;
|
||||
nsCOMPtr<nsIFile> mFontFile;
|
||||
|
||||
// maintaining a ref to this keeps temp file around or cache file pinned
|
||||
nsCOMPtr<nsISupports> mDownloader;
|
||||
};
|
||||
|
||||
static OSStatus
|
||||
MakeFSSpec(FSSpec *aFSSpec, NSString *path)
|
||||
{
|
||||
FSRef fsref;
|
||||
OSStatus err = FSPathMakeRef((UInt8*)([path fileSystemRepresentation]), &fsref, NULL);
|
||||
|
||||
if (err == noErr)
|
||||
err = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, aFSSpec, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxQuartzFontCache::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
||||
const gfxDownloadedFontData* aFontData)
|
||||
{
|
||||
OSStatus err;
|
||||
FSSpec spec;
|
||||
nsAutoString filePath;
|
||||
|
||||
NS_ASSERTION(aFontData && aFontData->mFontFile,
|
||||
"MakePlatformFont called with null file ptr");
|
||||
|
||||
if (!aFontData->mFontFile)
|
||||
return nsnull;
|
||||
|
||||
aFontData->mFontFile->GetPath(filePath);
|
||||
|
||||
NSString *path = GetNSStringForString(filePath);
|
||||
if (!path)
|
||||
return nsnull;
|
||||
|
||||
// assumption: filename is already in the form xxx.ttf, otherwise
|
||||
// ATS will reject
|
||||
|
||||
err = MakeFSSpec(&spec, path);
|
||||
if (err != noErr)
|
||||
return nsnull;
|
||||
|
||||
ATSUFontID fontID;
|
||||
ATSFontContainerRef containerRef;
|
||||
|
||||
err = ATSFontActivateFromFileSpecification(&spec,
|
||||
kPrivateATSFontContextPrivate,
|
||||
kATSFontFormatUnspecified,
|
||||
NULL,
|
||||
kATSOptionFlagsDoNotNotify,
|
||||
&containerRef);
|
||||
if (err != noErr)
|
||||
return nsnull;
|
||||
|
||||
mATSGeneration = ATSGeneration();
|
||||
|
||||
// ignoring containers with multiple fonts, use the first face only for now
|
||||
err = ATSFontFindFromContainer(containerRef, kATSOptionFlagsDefault, 1,
|
||||
(ATSFontRef*)&fontID, NULL);
|
||||
if (err != noErr)
|
||||
return nsnull;
|
||||
|
||||
// font entry will own this
|
||||
MacOSUserFontData *userFontData = new MacOSUserFontData(containerRef,
|
||||
aFontData->mFontFile,
|
||||
aFontData->mDownloader);
|
||||
if (!userFontData)
|
||||
return nsnull;
|
||||
|
||||
PRUint16 w = aProxyEntry->mWeight;
|
||||
NS_ASSERTION(w >= 100 && w <= 900, "bogus font weight value!");
|
||||
|
||||
MacOSFontEntry *newFontEntry =
|
||||
new MacOSFontEntry(fontID, w, aProxyEntry->mStretch,
|
||||
(PRUint32(aProxyEntry->mItalic) ?
|
||||
FONT_STYLE_ITALIC :
|
||||
FONT_STYLE_NORMAL),
|
||||
userFontData);
|
||||
|
||||
// if something is funky about this font, delete immediately
|
||||
if (newFontEntry && !newFontEntry->mIsValid) {
|
||||
#if DEBUG
|
||||
char warnBuf[1024];
|
||||
const gfxProxyFontEntry *proxyEntry =
|
||||
static_cast<const gfxProxyFontEntry*> (aProxyEntry);
|
||||
sprintf(warnBuf, "downloaded font not loaded properly, removed (%s) for (%s)",
|
||||
[path UTF8String],
|
||||
NS_ConvertUTF16toUTF8(proxyEntry->mFamily->Name()).get());
|
||||
NS_WARNING(warnBuf);
|
||||
#endif
|
||||
delete newFontEntry;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return newFontEntry;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gfxQuartzFontCache::InitLoader()
|
||||
{
|
||||
|
@ -113,6 +113,7 @@ protected:
|
||||
PRUint32 mLength;
|
||||
PRUint32 mAppUnitsPerDevUnit;
|
||||
PRUint32 mStringHash;
|
||||
PRUint64 mUserFontSetGeneration;
|
||||
PRPackedBool mIsDoubleByteText;
|
||||
PRPackedBool mIsRTL;
|
||||
PRPackedBool mEnabledOptionalLigatures;
|
||||
@ -124,6 +125,7 @@ protected:
|
||||
mLength(aLength),
|
||||
mAppUnitsPerDevUnit(aBaseTextRun->GetAppUnitsPerDevUnit()),
|
||||
mStringHash(aHash),
|
||||
mUserFontSetGeneration(aBaseTextRun->GetUserFontSetGeneration()),
|
||||
mIsDoubleByteText((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) == 0),
|
||||
mIsRTL(aBaseTextRun->IsRightToLeft()),
|
||||
mEnabledOptionalLigatures((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0),
|
||||
@ -197,14 +199,17 @@ HashMix(PRUint32 aHash, PRUnichar aCh)
|
||||
|
||||
// If the substring of the textrun is rendered entirely in the first font
|
||||
// of the textrun's fontgroup, then return that font. Otherwise return the
|
||||
// fontgroup.
|
||||
// fontgroup. When a user font set is in use, always return the font group.
|
||||
static void *GetWordFontOrGroup(gfxTextRun *aTextRun, PRUint32 aOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
|
||||
if (fontGroup->GetUserFontSet() != nsnull)
|
||||
return fontGroup;
|
||||
|
||||
PRUint32 glyphRunCount;
|
||||
const gfxTextRun::GlyphRun *glyphRuns = aTextRun->GetGlyphRuns(&glyphRunCount);
|
||||
PRUint32 glyphRunIndex = aTextRun->FindFirstGlyphRunContaining(aOffset);
|
||||
gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
|
||||
gfxFont *firstFont = fontGroup->GetFontAt(0);
|
||||
if (glyphRuns[glyphRunIndex].mFont != firstFont)
|
||||
return fontGroup;
|
||||
@ -260,8 +265,11 @@ TextRunWordCache::LookupWord(gfxTextRun *aTextRun, gfxFont *aFirstFont,
|
||||
{
|
||||
if (aEnd <= aStart)
|
||||
return PR_TRUE;
|
||||
|
||||
gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
|
||||
|
||||
CacheHashKey key(aTextRun, aFirstFont, aStart, aEnd - aStart, aHash);
|
||||
PRBool useFontGroup = (fontGroup->GetUserFontSet() != nsnull);
|
||||
CacheHashKey key(aTextRun, (useFontGroup ? (void*)fontGroup : (void*)aFirstFont), aStart, aEnd - aStart, aHash);
|
||||
CacheHashEntry *fontEntry = mCache.PutEntry(key);
|
||||
if (!fontEntry)
|
||||
return PR_FALSE;
|
||||
@ -269,7 +277,10 @@ TextRunWordCache::LookupWord(gfxTextRun *aTextRun, gfxFont *aFirstFont,
|
||||
|
||||
if (fontEntry->mTextRun) {
|
||||
existingEntry = fontEntry;
|
||||
} else if (useFontGroup) {
|
||||
PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): added using font group", aTextRun, aStart, aEnd - aStart, aHash));
|
||||
} else {
|
||||
// test to see if this can be found using the font group instead
|
||||
PR_LOG(gWordCacheLog, PR_LOG_DEBUG, ("%p(%d-%d,%d): added using font", aTextRun, aStart, aEnd - aStart, aHash));
|
||||
key.mFontOrGroup = aTextRun->GetFontGroup();
|
||||
CacheHashEntry *groupEntry = mCache.GetEntry(key);
|
||||
@ -304,7 +315,8 @@ TextRunWordCache::LookupWord(gfxTextRun *aTextRun, gfxFont *aFirstFont,
|
||||
// entry, we'll copy within our own textrun
|
||||
fontEntry->mTextRun = aTextRun;
|
||||
fontEntry->mWordOffset = aStart;
|
||||
fontEntry->mHashedByFont = PR_TRUE;
|
||||
if (!useFontGroup)
|
||||
fontEntry->mHashedByFont = PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
@ -331,6 +343,11 @@ TextRunWordCache::FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun,
|
||||
PRUint32 i;
|
||||
gfxFontGroup *fontGroup = aTextRun->GetFontGroup();
|
||||
gfxFont *font = fontGroup->GetFontAt(0);
|
||||
|
||||
// need to use the font group when user font set is around, since
|
||||
// the first font may change as the result of a font download
|
||||
PRBool useFontGroup = (fontGroup->GetUserFontSet() != nsnull);
|
||||
|
||||
// copy deferred words from various sources into destination textrun
|
||||
for (i = 0; i < aDeferredWords.Length(); ++i) {
|
||||
const DeferredWord *word = &aDeferredWords[i];
|
||||
@ -350,11 +367,11 @@ TextRunWordCache::FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun,
|
||||
// we need to remove that cache entry and replace it with an entry
|
||||
// keyed off the fontgroup.
|
||||
PRBool rekeyWithFontGroup =
|
||||
GetWordFontOrGroup(aNewRun, word->mSourceOffset, word->mLength) != font;
|
||||
GetWordFontOrGroup(aNewRun, word->mSourceOffset, word->mLength) != font && !useFontGroup;
|
||||
if (!aSuccessful || rekeyWithFontGroup ||
|
||||
wordStartsInsideCluster || wordStartsInsideLigature) {
|
||||
// We need to remove the current placeholder cache entry
|
||||
CacheHashKey key(aTextRun, font, word->mDestOffset, word->mLength,
|
||||
CacheHashKey key(aTextRun, (useFontGroup ? (void*)fontGroup : (void*)font), word->mDestOffset, word->mLength,
|
||||
word->mHash);
|
||||
NS_ASSERTION(mCache.GetEntry(key),
|
||||
"This entry should have been added previously!");
|
||||
@ -459,6 +476,9 @@ TextRunWordCache::MakeTextRun(const PRUnichar *aText, PRUint32 aLength,
|
||||
const gfxFontGroup::Parameters *aParams,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
// update font list when using user fonts (assures generation is current)
|
||||
aFontGroup->UpdateFontList();
|
||||
|
||||
if (aFontGroup->GetStyle()->size == 0) {
|
||||
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
|
||||
// them, and always create at least size 1 fonts, i.e. they still
|
||||
@ -530,7 +550,7 @@ TextRunWordCache::MakeTextRun(const PRUnichar *aText, PRUint32 aLength,
|
||||
nsAutoPtr<gfxTextRun> newRun;
|
||||
newRun = aFontGroup->MakeTextRun(tempString.Elements(), tempString.Length(),
|
||||
¶ms, aFlags | gfxTextRunFactory::TEXT_IS_PERSISTENT);
|
||||
|
||||
|
||||
FinishTextRun(textRun, newRun, aParams, deferredWords, newRun != nsnull);
|
||||
return textRun.forget();
|
||||
}
|
||||
@ -541,6 +561,9 @@ TextRunWordCache::MakeTextRun(const PRUint8 *aText, PRUint32 aLength,
|
||||
const gfxFontGroup::Parameters *aParams,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
// update font list when using user fonts (assures generation is current)
|
||||
aFontGroup->UpdateFontList();
|
||||
|
||||
if (aFontGroup->GetStyle()->size == 0) {
|
||||
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
|
||||
// them, and always create at least size 1 fonts, i.e. they still
|
||||
@ -628,6 +651,7 @@ TextRunWordCache::RemoveWord(gfxTextRun *aTextRun, PRUint32 aStart,
|
||||
PRUint32 length = aEnd - aStart;
|
||||
CacheHashKey key(aTextRun, GetWordFontOrGroup(aTextRun, aStart, length),
|
||||
aStart, length, aHash);
|
||||
|
||||
CacheHashEntry *entry = mCache.GetEntry(key);
|
||||
if (entry && entry->mTextRun == aTextRun) {
|
||||
// XXX would like to use RawRemoveEntry here plus some extra method
|
||||
@ -710,7 +734,8 @@ TextRunWordCache::CacheHashEntry::KeyEquals(const KeyTypePointer aKey) const
|
||||
aKey->mAppUnitsPerDevUnit != mTextRun->GetAppUnitsPerDevUnit() ||
|
||||
aKey->mIsRTL != mTextRun->IsRightToLeft() ||
|
||||
aKey->mEnabledOptionalLigatures != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0) ||
|
||||
aKey->mOptimizeSpeed != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0))
|
||||
aKey->mOptimizeSpeed != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0) ||
|
||||
aKey->mUserFontSetGeneration != (mTextRun->GetUserFontSetGeneration()))
|
||||
return PR_FALSE;
|
||||
|
||||
if (mTextRun->GetFlags() & gfxFontGroup::TEXT_IS_8BIT) {
|
||||
@ -731,7 +756,12 @@ TextRunWordCache::CacheHashEntry::KeyEquals(const KeyTypePointer aKey) const
|
||||
PLDHashNumber
|
||||
TextRunWordCache::CacheHashEntry::HashKey(const KeyTypePointer aKey)
|
||||
{
|
||||
return aKey->mStringHash + (long)aKey->mFontOrGroup + aKey->mAppUnitsPerDevUnit +
|
||||
// only use lower 32 bits of generation counter in hash key,
|
||||
// since these vary the most
|
||||
PRUint32 fontSetGen;
|
||||
LL_L2UI(fontSetGen, aKey->mUserFontSetGeneration);
|
||||
|
||||
return aKey->mStringHash + fontSetGen + (long)aKey->mFontOrGroup + aKey->mAppUnitsPerDevUnit +
|
||||
aKey->mIsDoubleByteText + aKey->mIsRTL*2 + aKey->mEnabledOptionalLigatures*4 +
|
||||
aKey->mOptimizeSpeed*8;
|
||||
}
|
||||
|
@ -192,21 +192,8 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
||||
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
||||
|
||||
gfxWindowsFontType feType;
|
||||
if (metrics.ntmFlags & NTM_TYPE1)
|
||||
feType = GFX_FONT_TYPE_TYPE1;
|
||||
else if (metrics.ntmFlags & (NTM_PS_OPENTYPE))
|
||||
feType = GFX_FONT_TYPE_PS_OPENTYPE;
|
||||
else if (metrics.ntmFlags & (NTM_TT_OPENTYPE))
|
||||
feType = GFX_FONT_TYPE_TT_OPENTYPE;
|
||||
else if (fontType == TRUETYPE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_TRUETYPE;
|
||||
else if (fontType == RASTER_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_RASTER;
|
||||
else if (fontType == DEVICE_FONTTYPE)
|
||||
feType = GFX_FONT_TYPE_DEVICE;
|
||||
else
|
||||
feType = GFX_FONT_TYPE_UNKNOWN;
|
||||
|
||||
gfxWindowsFontType feType = FontEntry::DetermineFontType(metrics, fontType);
|
||||
|
||||
FontEntry *fe = nsnull;
|
||||
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
|
||||
@ -232,15 +219,14 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
}
|
||||
}
|
||||
|
||||
fe = new FontEntry(ff->mName);
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfOutPrecision = FontTypeToOutPrecision(feType);
|
||||
fe = FontEntry::CreateFontEntry(ff->mName, feType, (logFont.lfItalic == 0xFF), (PRUint16) (logFont.lfWeight), nsnull, hdc, &logFont);
|
||||
|
||||
if (!fe)
|
||||
return 1;
|
||||
|
||||
ff->mVariations.AppendElement(fe);
|
||||
fe->mFontType = feType;
|
||||
|
||||
fe->mItalic = (logFont.lfItalic == 0xFF);
|
||||
fe->mWeight = logFont.lfWeight;
|
||||
|
||||
if (fe->IsType1())
|
||||
fe->mForceGDI = PR_TRUE;
|
||||
|
||||
// mark the charset bit
|
||||
fe->mCharset[metrics.tmCharSet] = 1;
|
||||
@ -263,39 +249,7 @@ FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
}
|
||||
}
|
||||
|
||||
fe->mIsBadUnderlineFont = ff->mIsBadUnderlineFont;
|
||||
|
||||
// read in the character map
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfOutPrecision = FontTypeToOutPrecision(fe->mFontType);
|
||||
|
||||
HFONT font = CreateFontIndirectW(&logFont);
|
||||
|
||||
NS_ASSERTION(font, "This font creation should never ever ever fail");
|
||||
if (font) {
|
||||
HFONT oldFont = (HFONT)SelectObject(hdc, font);
|
||||
|
||||
// ReadCMAP may change the values of mUnicodeFont and mSymbolFont
|
||||
if (NS_FAILED(ReadCMAP(hdc, fe))) {
|
||||
// Type1 fonts aren't necessarily Unicode but
|
||||
// this is the best guess we can make here
|
||||
if (fe->IsType1())
|
||||
fe->mUnicodeFont = PR_TRUE;
|
||||
else
|
||||
fe->mUnicodeFont = PR_FALSE;
|
||||
|
||||
// For fonts where we failed to read the character map,
|
||||
// we can take a slow path to look up glyphs character by character
|
||||
fe->mUnknownCMAP = PR_TRUE;
|
||||
|
||||
//printf("(fontinit-cmap) %s failed to get cmap, type1:%d \n", NS_ConvertUTF16toUTF8(fe->mFaceName).get(), (PRUint32)(fe->mIsType1));
|
||||
} else {
|
||||
//printf("(fontinit-cmap) %s cmap loaded, italic:%d, weight:%d\n", NS_ConvertUTF16toUTF8(fe->mFaceName).get(), (PRUint32)(fe->mItalic), (PRUint32)(fe->mWeight));
|
||||
}
|
||||
|
||||
SelectObject(hdc, oldFont);
|
||||
DeleteObject(font);
|
||||
}
|
||||
fe->mIsBadUnderlineFont = ff->mIsBadUnderlineFontFamily;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -393,6 +347,102 @@ FontFamily::FindWeightsForStyle(gfxFontEntry* aFontsForWeights[], const gfxFontS
|
||||
return matchesSomething;
|
||||
}
|
||||
|
||||
FontEntry*
|
||||
FontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, PRBool aItalic, PRUint16 aWeight, gfxUserFontData* aUserFontData, HDC hdc, LOGFONTW *aLogFont)
|
||||
{
|
||||
LOGFONTW logFont;
|
||||
PRBool needRelease = PR_FALSE;
|
||||
|
||||
// jtdfix - need to set charset, unicode ranges, pitch/family
|
||||
|
||||
FontEntry *fe;
|
||||
|
||||
fe = new FontEntry(aName);
|
||||
fe->mFontType = aFontType;
|
||||
fe->mUserFontData = aUserFontData;
|
||||
|
||||
fe->mItalic = aItalic;
|
||||
fe->mWeight = aWeight;
|
||||
|
||||
if (fe->IsType1())
|
||||
fe->mForceGDI = PR_TRUE;
|
||||
|
||||
if (!aLogFont) {
|
||||
aLogFont = &logFont;
|
||||
FontEntry::FillLogFont(aLogFont, fe, 0, aItalic);
|
||||
}
|
||||
|
||||
if (!hdc) {
|
||||
hdc = GetDC(nsnull);
|
||||
SetGraphicsMode(hdc, GM_ADVANCED);
|
||||
needRelease = PR_TRUE;
|
||||
}
|
||||
|
||||
HFONT font = CreateFontIndirectW(aLogFont);
|
||||
|
||||
if (font) {
|
||||
HFONT oldFont = (HFONT)SelectObject(hdc, font);
|
||||
|
||||
// ReadCMAP may change the values of mUnicodeFont and mSymbolFont
|
||||
if (NS_FAILED(::ReadCMAP(hdc, fe))) {
|
||||
// Type1 fonts aren't necessarily Unicode but
|
||||
// this is the best guess we can make here
|
||||
if (fe->IsType1())
|
||||
fe->mUnicodeFont = PR_TRUE;
|
||||
else
|
||||
fe->mUnicodeFont = PR_FALSE;
|
||||
|
||||
// For fonts where we failed to read the character map,
|
||||
// we can take a slow path to look up glyphs character by character
|
||||
fe->mUnknownCMAP = PR_TRUE;
|
||||
|
||||
}
|
||||
|
||||
SelectObject(hdc, oldFont);
|
||||
DeleteObject(font);
|
||||
}
|
||||
|
||||
if (needRelease)
|
||||
ReleaseDC(nsnull, hdc);
|
||||
|
||||
return fe;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FontEntry::FillLogFont(LOGFONTW *aLogFont, FontEntry *aFontEntry, gfxFloat aSize, PRBool aItalic)
|
||||
{
|
||||
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
||||
|
||||
aLogFont->lfHeight = (LONG)-ROUND(aSize);
|
||||
|
||||
if (aLogFont->lfHeight == 0)
|
||||
aLogFont->lfHeight = -1;
|
||||
|
||||
// Fill in logFont structure
|
||||
aLogFont->lfWidth = 0;
|
||||
aLogFont->lfEscapement = 0;
|
||||
aLogFont->lfOrientation = 0;
|
||||
aLogFont->lfUnderline = FALSE;
|
||||
aLogFont->lfStrikeOut = FALSE;
|
||||
aLogFont->lfCharSet = DEFAULT_CHARSET;
|
||||
aLogFont->lfOutPrecision = FontTypeToOutPrecision(aFontEntry->mFontType);
|
||||
aLogFont->lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
||||
aLogFont->lfQuality = DEFAULT_QUALITY;
|
||||
aLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||
// always force lfItalic if we want it. Font selection code will
|
||||
// do its best to give us an italic font entry, but if no face exists
|
||||
// it may give us a regular one based on weight. Windows should
|
||||
// do fake italic for us in that case.
|
||||
aLogFont->lfItalic = aItalic;
|
||||
aLogFont->lfWeight = aFontEntry->mWeight;
|
||||
|
||||
int len = PR_MIN(aFontEntry->Name().Length(), LF_FACESIZE - 1);
|
||||
memcpy(aLogFont->lfFaceName, nsPromiseFlatString(aFontEntry->Name()).get(), len * 2);
|
||||
aLogFont->lfFaceName[len] = '\0';
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
FontEntry::TestCharacterMap(PRUint32 aCh)
|
||||
{
|
||||
@ -664,40 +714,13 @@ gfxWindowsFont::ComputeMetrics()
|
||||
|
||||
ReleaseDC((HWND)nsnull, dc);
|
||||
|
||||
SanitizeMetrics(mMetrics, GetFontEntry()->IsBadUnderlineFont());
|
||||
SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsFont::FillLogFont(gfxFloat aSize)
|
||||
{
|
||||
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
||||
|
||||
mLogFont.lfHeight = (LONG)-ROUND(aSize);
|
||||
|
||||
if (mLogFont.lfHeight == 0)
|
||||
mLogFont.lfHeight = -1;
|
||||
|
||||
// Fill in logFont structure
|
||||
mLogFont.lfWidth = 0;
|
||||
mLogFont.lfEscapement = 0;
|
||||
mLogFont.lfOrientation = 0;
|
||||
mLogFont.lfUnderline = FALSE;
|
||||
mLogFont.lfStrikeOut = FALSE;
|
||||
mLogFont.lfCharSet = DEFAULT_CHARSET;
|
||||
mLogFont.lfOutPrecision = FontTypeToOutPrecision(GetFontEntry()->mFontType);
|
||||
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
||||
mLogFont.lfQuality = DEFAULT_QUALITY;
|
||||
mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||
// always force lfItalic if we want it. Font selection code will
|
||||
// do its best to give us an italic font entry, but if no face exists
|
||||
// it may give us a regular one based on weight. Windows should
|
||||
// do fake italic for us in that case.
|
||||
mLogFont.lfItalic = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
|
||||
mLogFont.lfWeight = GetFontEntry()->mWeight;
|
||||
|
||||
int len = PR_MIN(GetName().Length(), LF_FACESIZE - 1);
|
||||
memcpy(mLogFont.lfFaceName, nsPromiseFlatString(mFontEntry->Name()).get(), len * 2);
|
||||
mLogFont.lfFaceName[len] = '\0';
|
||||
FontEntry::FillLogFont(&mLogFont, GetFontEntry(), aSize, (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
|
||||
}
|
||||
|
||||
|
||||
@ -806,6 +829,7 @@ AddFontNameToArray(const nsAString& aName,
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gfxWindowsFontGroup::GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list)
|
||||
{
|
||||
@ -814,8 +838,25 @@ gfxWindowsFontGroup::GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *
|
||||
|
||||
PRUint32 len = fonts.Length();
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], mStyle);
|
||||
list->AppendElement(fe);
|
||||
nsRefPtr<FontEntry> fe;
|
||||
|
||||
// first, look up in the user font set
|
||||
gfxFontEntry *gfe;
|
||||
PRBool needsBold;
|
||||
if (mUserFontSet && (gfe = mUserFontSet->FindFontEntry(fonts[i], mStyle, needsBold))) {
|
||||
// assume for now platform font if not SVG
|
||||
fe = static_cast<FontEntry*> (gfe);
|
||||
}
|
||||
|
||||
// nothing in the user font set ==> check system fonts
|
||||
if (!fe) {
|
||||
fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], mStyle);
|
||||
}
|
||||
|
||||
// if found, add to the list
|
||||
if (fe) {
|
||||
list->AppendElement(fe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -835,8 +876,50 @@ gfxWindowsFontGroup::FamilyListToArrayList(const nsString& aFamilies,
|
||||
}
|
||||
}
|
||||
|
||||
gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
|
||||
: gfxFontGroup(aFamilies, aStyle)
|
||||
gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet)
|
||||
: gfxFontGroup(aFamilies, aStyle, aUserFontSet)
|
||||
{
|
||||
InitFontList();
|
||||
}
|
||||
|
||||
gfxWindowsFontGroup::~gfxWindowsFontGroup()
|
||||
{
|
||||
}
|
||||
|
||||
gfxWindowsFont *
|
||||
gfxWindowsFontGroup::GetFontAt(PRInt32 i)
|
||||
{
|
||||
if (!mFonts[i]) {
|
||||
nsRefPtr<gfxWindowsFont> font =
|
||||
gfxWindowsFont::GetOrMakeFont(mFontEntries[i], &mStyle);
|
||||
mFonts[i] = font;
|
||||
}
|
||||
|
||||
return static_cast<gfxWindowsFont*>(mFonts[i].get());
|
||||
}
|
||||
|
||||
gfxFontGroup *
|
||||
gfxWindowsFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
{
|
||||
return new gfxWindowsFontGroup(mFamilies, aStyle, mUserFontSet);
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsFontGroup::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();
|
||||
mFontEntries.Clear();
|
||||
InitFontList();
|
||||
mCurrGeneration = GetGeneration();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsFontGroup::InitFontList()
|
||||
{
|
||||
GroupFamilyListToArrayList(&mFontEntries);
|
||||
|
||||
@ -892,7 +975,7 @@ gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFo
|
||||
|
||||
if (!mStyle.systemFont) {
|
||||
for (PRUint32 i = 0; i < mFontEntries.Length(); ++i) {
|
||||
if (mFontEntries[i]->IsBadUnderlineFont()) {
|
||||
if (mFontEntries[i]->mIsBadUnderlineFont) {
|
||||
gfxFloat first = GetFontAt(0)->GetMetrics().underlineOffset;
|
||||
gfxFloat bad = GetFontAt(i)->GetMetrics().underlineOffset;
|
||||
mUnderlineOffset = PR_MIN(first, bad);
|
||||
@ -900,28 +983,7 @@ gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfxWindowsFontGroup::~gfxWindowsFontGroup()
|
||||
{
|
||||
}
|
||||
|
||||
gfxWindowsFont *
|
||||
gfxWindowsFontGroup::GetFontAt(PRInt32 i)
|
||||
{
|
||||
if (!mFonts[i]) {
|
||||
nsRefPtr<gfxWindowsFont> font =
|
||||
gfxWindowsFont::GetOrMakeFont(mFontEntries[i], &mStyle);
|
||||
mFonts[i] = font;
|
||||
}
|
||||
|
||||
return static_cast<gfxWindowsFont*>(mFonts[i].get());
|
||||
}
|
||||
|
||||
gfxFontGroup *
|
||||
gfxWindowsFontGroup::Copy(const gfxFontStyle *aStyle)
|
||||
{
|
||||
return new gfxWindowsFontGroup(mFamilies, aStyle);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
|
@ -49,14 +49,18 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "nsIWindowsRegKey.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "plbase64.h"
|
||||
|
||||
#include "gfxWindowsFonts.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
#include "lcms.h"
|
||||
|
||||
//#define DEBUG_CMAP_SIZE 1
|
||||
static void InitializeFontEmbeddingProcs();
|
||||
|
||||
// font info loader constants
|
||||
static const PRUint32 kDelayBeforeLoadingCmaps = 8 * 1000; // 8secs
|
||||
@ -96,6 +100,8 @@ gfxWindowsPlatform::gfxWindowsPlatform()
|
||||
pref->RegisterCallback("font.name-list.", PrefChangedCallback, this);
|
||||
pref->RegisterCallback("intl.accept_languages", PrefChangedCallback, this);
|
||||
// don't bother unregistering. We'll get shutdown after the pref service
|
||||
|
||||
InitializeFontEmbeddingProcs();
|
||||
}
|
||||
|
||||
gfxWindowsPlatform::~gfxWindowsPlatform()
|
||||
@ -319,7 +325,7 @@ gfxWindowsPlatform::InitBadUnderlineList()
|
||||
FontFamily *ff = FindFontFamily(resolved);
|
||||
if (!ff)
|
||||
continue;
|
||||
ff->mIsBadUnderlineFont = 1;
|
||||
ff->mIsBadUnderlineFontFamily = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,9 +523,364 @@ gfxWindowsPlatform::FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont)
|
||||
|
||||
gfxFontGroup *
|
||||
gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
||||
const gfxFontStyle *aStyle)
|
||||
const gfxFontStyle *aStyle,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
return new gfxWindowsFontGroup(aFamilies, aStyle);
|
||||
return new gfxWindowsFontGroup(aFamilies, aStyle, aUserFontSet);
|
||||
}
|
||||
|
||||
|
||||
struct FullFontNameSearch {
|
||||
FullFontNameSearch(const nsAString& aFullName)
|
||||
: mFound(PR_FALSE), mFullName(aFullName), mDC(nsnull), mFontEntry(nsnull)
|
||||
{ }
|
||||
|
||||
PRPackedBool mFound;
|
||||
nsString mFullName;
|
||||
nsString mFamilyName;
|
||||
HDC mDC;
|
||||
gfxFontEntry *mFontEntry;
|
||||
};
|
||||
|
||||
// callback called for each face within a single family
|
||||
// match against elfFullName
|
||||
|
||||
static int CALLBACK
|
||||
FindFullNameForFace(const ENUMLOGFONTEXW *lpelfe,
|
||||
const NEWTEXTMETRICEXW *nmetrics,
|
||||
DWORD fontType, LPARAM userArg)
|
||||
{
|
||||
FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
|
||||
|
||||
// does the full name match?
|
||||
if (!data->mFullName.Equals(nsDependentString(lpelfe->elfFullName)))
|
||||
return 1; // continue
|
||||
|
||||
// found match, create a new font entry
|
||||
data->mFound = PR_TRUE;
|
||||
|
||||
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
||||
LOGFONTW logFont = lpelfe->elfLogFont;
|
||||
|
||||
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
||||
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
||||
|
||||
gfxWindowsFontType feType = FontEntry::DetermineFontType(metrics, fontType);
|
||||
|
||||
data->mFontEntry = FontEntry::CreateFontEntry(data->mFamilyName, feType, (logFont.lfItalic == 0xFF), (PRUint16) (logFont.lfWeight), nsnull, data->mDC, &logFont);
|
||||
|
||||
return 0; // stop iteration
|
||||
}
|
||||
|
||||
|
||||
// callback called for each family name, based on the assumption that the
|
||||
// first part of the full name is the family name
|
||||
|
||||
static PLDHashOperator PR_CALLBACK
|
||||
FindFullName(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<FontFamily>& aFontFamily,
|
||||
void* userArg)
|
||||
{
|
||||
FullFontNameSearch *data = reinterpret_cast<FullFontNameSearch*>(userArg);
|
||||
|
||||
// does the family name match up to the length of the family name?
|
||||
const nsString& family = aFontFamily->Name();
|
||||
|
||||
nsString fullNameFamily;
|
||||
data->mFullName.Left(fullNameFamily, family.Length());
|
||||
|
||||
// if so, iterate over faces in this family to see if there is a match
|
||||
if (family.Equals(fullNameFamily)) {
|
||||
HDC hdc;
|
||||
|
||||
if (!data->mDC) {
|
||||
data->mDC= GetDC(nsnull);
|
||||
SetGraphicsMode(data->mDC, GM_ADVANCED);
|
||||
}
|
||||
hdc = data->mDC;
|
||||
|
||||
LOGFONTW logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfPitchAndFamily = 0;
|
||||
PRUint32 l = PR_MIN(family.Length(), LF_FACESIZE - 1);
|
||||
memcpy(logFont.lfFaceName,
|
||||
nsPromiseFlatString(family).get(),
|
||||
l * sizeof(PRUnichar));
|
||||
logFont.lfFaceName[l] = 0;
|
||||
data->mFamilyName.Assign(family);
|
||||
|
||||
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)FindFullNameForFace, (LPARAM)data, 0);
|
||||
}
|
||||
|
||||
if (data->mFound)
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxWindowsPlatform::LookupLocalFont(const nsAString& aFontName)
|
||||
{
|
||||
// walk over list of names
|
||||
FullFontNameSearch data(aFontName);
|
||||
|
||||
// find fonts that support the character
|
||||
mFonts.Enumerate(FindFullName, &data);
|
||||
|
||||
if (data.mDC)
|
||||
ReleaseDC(nsnull, data.mDC);
|
||||
|
||||
return data.mFontEntry;
|
||||
}
|
||||
|
||||
// make a unique font name, limited on Windows to 31 two-byte characters
|
||||
static void MakeUniqueFontName(PRUnichar aName[LF_FACESIZE])
|
||||
{
|
||||
static PRUint32 fontCount = 0;
|
||||
++fontCount;
|
||||
PRUint32 time = (PRUint32) _time32(nsnull);
|
||||
|
||||
char buf[LF_FACESIZE];
|
||||
|
||||
sprintf(buf, "mozfont%8.8x%8.8x", time, fontCount); // slightly retarded, figure something better later...
|
||||
|
||||
nsCAutoString fontName(buf);
|
||||
|
||||
PRUint32 nameLen = PR_MIN(fontName.Length(), LF_FACESIZE - 1);
|
||||
memcpy(aName, nsPromiseFlatString(NS_ConvertUTF8toUTF16(fontName)).get(), nameLen * 2);
|
||||
aName[nameLen] = 0;
|
||||
}
|
||||
|
||||
// from t2embapi.h, included in Platform SDK 6.1 but not 6.0
|
||||
|
||||
#ifndef __t2embapi__
|
||||
|
||||
#define TTLOAD_PRIVATE 0x00000001
|
||||
#define LICENSE_PREVIEWPRINT 0x0004
|
||||
#define E_NONE 0x0000L
|
||||
|
||||
typedef unsigned long( WINAPIV *READEMBEDPROC ) ( void*, void*, const unsigned long );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short usStructSize; // size in bytes of structure client should set to sizeof(TTLOADINFO)
|
||||
unsigned short usRefStrSize; // size in wide characters of pusRefStr including NULL terminator
|
||||
unsigned short *pusRefStr; // reference or actual string.
|
||||
}TTLOADINFO;
|
||||
|
||||
LONG WINAPI TTLoadEmbeddedFont
|
||||
(
|
||||
__out HANDLE* phFontReference, // on completion, contains handle to identify embedded font installed
|
||||
// on system
|
||||
__in ULONG ulFlags, // flags specifying the request
|
||||
__out ULONG* pulPrivStatus, // on completion, contains the embedding status
|
||||
__in ULONG ulPrivs, // allows for the reduction of licensing privileges
|
||||
__out ULONG* pulStatus, // on completion, may contain status flags for request
|
||||
__in READEMBEDPROC lpfnReadFromStream, // callback function for doc/disk reads
|
||||
__in LPVOID lpvReadStream, // the input stream tokin
|
||||
__in_opt LPWSTR szWinFamilyName, // the new 16 bit windows family name can be NULL
|
||||
__in_opt LPSTR szMacFamilyName, // the new 8 bit mac family name can be NULL
|
||||
__in_opt TTLOADINFO* pTTLoadInfo // optional security
|
||||
);
|
||||
|
||||
#endif // __t2embapi__
|
||||
|
||||
typedef LONG( WINAPI *TTLoadEmbeddedFontProc ) (HANDLE* phFontReference, ULONG ulFlags, ULONG* pulPrivStatus, ULONG ulPrivs, ULONG* pulStatus,
|
||||
READEMBEDPROC lpfnReadFromStream, LPVOID lpvReadStream, LPWSTR szWinFamilyName,
|
||||
LPSTR szMacFamilyName, TTLOADINFO* pTTLoadInfo);
|
||||
|
||||
typedef LONG( WINAPI *TTDeleteEmbeddedFontProc ) (HANDLE hFontReference, ULONG ulFlags, ULONG* pulStatus);
|
||||
|
||||
|
||||
static TTLoadEmbeddedFontProc TTLoadEmbeddedFontPtr = nsnull;
|
||||
static TTDeleteEmbeddedFontProc TTDeleteEmbeddedFontPtr = nsnull;
|
||||
|
||||
static void InitializeFontEmbeddingProcs()
|
||||
{
|
||||
HMODULE fontlib = LoadLibrary("t2embed.dll");
|
||||
if (!fontlib)
|
||||
return;
|
||||
TTLoadEmbeddedFontPtr = (TTLoadEmbeddedFontProc) GetProcAddress(fontlib, "TTLoadEmbeddedFont");
|
||||
TTDeleteEmbeddedFontPtr = (TTDeleteEmbeddedFontProc) GetProcAddress(fontlib, "TTDeleteEmbeddedFont");
|
||||
}
|
||||
|
||||
class WinUserFontData : public gfxUserFontData {
|
||||
public:
|
||||
WinUserFontData(HANDLE aFontRef)
|
||||
: mFontRef(aFontRef)
|
||||
{ }
|
||||
|
||||
virtual ~WinUserFontData()
|
||||
{
|
||||
ULONG pulStatus;
|
||||
TTDeleteEmbeddedFontPtr(mFontRef, 0, &pulStatus);
|
||||
}
|
||||
|
||||
HANDLE mFontRef;
|
||||
};
|
||||
|
||||
// used to control stream read by Windows TTLoadEmbeddedFont API
|
||||
|
||||
class EOTFontStreamReader {
|
||||
public:
|
||||
EOTFontStreamReader(nsILocalFile *aFontFile, PRUint8 *aEOTHeader,
|
||||
PRUint32 aEOTHeaderLen)
|
||||
: mFontFile(aFontFile), mFd(nsnull), mOpenError(PR_FALSE),
|
||||
mInHeader(PR_TRUE), mHeaderOffset(0), mEOTHeader(aEOTHeader),
|
||||
mEOTHeaderLen(aEOTHeaderLen)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~EOTFontStreamReader()
|
||||
{
|
||||
if (mFd) {
|
||||
PR_Close(mFd);
|
||||
}
|
||||
|
||||
mFontFile->Remove(PR_FALSE);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILocalFile> mFontFile;
|
||||
PRFileDesc *mFd;
|
||||
PRPackedBool mOpenError;
|
||||
PRPackedBool mInHeader;
|
||||
PRUint32 mHeaderOffset;
|
||||
PRUint8 *mEOTHeader;
|
||||
PRUint32 mEOTHeaderLen;
|
||||
|
||||
PRBool OpenFontFile()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mFontFile->OpenNSPRFileDesc(PR_RDONLY, 0, &mFd);
|
||||
if (NS_FAILED(rv) || !mFd)
|
||||
return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
unsigned long Read(void *outBuffer, const unsigned long aBytesToRead)
|
||||
{
|
||||
PRUint32 bytesLeft = aBytesToRead;
|
||||
PRUint8 *out = static_cast<PRUint8*> (outBuffer);
|
||||
|
||||
if (mOpenError)
|
||||
return 0;
|
||||
|
||||
if (!mFd) {
|
||||
if (!OpenFontFile()) {
|
||||
mOpenError = PR_TRUE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read from EOT header
|
||||
if (mInHeader) {
|
||||
PRUint32 toCopy = PR_MIN(aBytesToRead, mEOTHeaderLen - mHeaderOffset);
|
||||
memcpy(out, mEOTHeader + mHeaderOffset, toCopy);
|
||||
bytesLeft -= toCopy;
|
||||
mHeaderOffset += toCopy;
|
||||
out += toCopy;
|
||||
if (mHeaderOffset == mEOTHeaderLen)
|
||||
mInHeader = PR_FALSE;
|
||||
}
|
||||
|
||||
if (bytesLeft) {
|
||||
PRInt32 bytesRead = PR_Read(mFd, out, bytesLeft);
|
||||
if (bytesRead > 0)
|
||||
bytesLeft -= bytesRead;
|
||||
}
|
||||
|
||||
return aBytesToRead - bytesLeft;
|
||||
}
|
||||
|
||||
static unsigned long ReadEOTStream(void *aReadStream, void *outBuffer,
|
||||
const unsigned long aBytesToRead)
|
||||
{
|
||||
EOTFontStreamReader *eotReader =
|
||||
static_cast<EOTFontStreamReader*> (aReadStream);
|
||||
return eotReader->Read(outBuffer, aBytesToRead);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
gfxFontEntry*
|
||||
gfxWindowsPlatform::MakePlatformFont(const gfxFontEntry *aProxyEntry,
|
||||
const gfxDownloadedFontData* aFontData)
|
||||
{
|
||||
// if calls aren't available, bail
|
||||
if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
|
||||
return nsnull;
|
||||
|
||||
// create an eot header
|
||||
nsAutoTArray<PRUint8,2048> eotHeader;
|
||||
PRUint8 *buffer;
|
||||
PRUint32 eotlen;
|
||||
PRUnichar fontName[LF_FACESIZE];
|
||||
PRBool isCFF;
|
||||
|
||||
nsresult rv;
|
||||
HANDLE fontRef;
|
||||
PRInt32 ret;
|
||||
|
||||
{
|
||||
nsCOMPtr<nsILocalFile> fontFile(do_QueryInterface(aFontData->mFontFile, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
rv = gfxFontUtils::MakeEOTHeader(fontFile, &eotHeader, &isCFF);
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
// load in embedded font data
|
||||
eotlen = eotHeader.Length();
|
||||
buffer = reinterpret_cast<PRUint8*> (eotHeader.Elements());
|
||||
|
||||
ULONG privStatus, pulStatus;
|
||||
MakeUniqueFontName(fontName);
|
||||
EOTFontStreamReader eotReader(fontFile, buffer, eotlen);
|
||||
|
||||
ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus,
|
||||
LICENSE_PREVIEWPRINT, &pulStatus,
|
||||
EOTFontStreamReader::ReadEOTStream,
|
||||
&eotReader, fontName, 0, 0);
|
||||
}
|
||||
|
||||
if (ret != E_NONE)
|
||||
return nsnull;
|
||||
|
||||
// make a new font entry using the unique name
|
||||
WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
|
||||
PRUint16 w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
|
||||
|
||||
return FontEntry::CreateFontEntry(nsDependentString(fontName),
|
||||
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
||||
PRUint32(aProxyEntry->mItalic ? FONT_STYLE_ITALIC : FONT_STYLE_NORMAL),
|
||||
w, winUserFontData);
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
|
||||
{
|
||||
// reject based on format flags
|
||||
if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// exclude AAT fonts on platforms other than Mac OS X, this allows
|
||||
// fonts for complex scripts which require AAT tables to be omitted
|
||||
// on other platforms
|
||||
if ((aFormatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT)
|
||||
&& !(aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | gfxUserFontSet::FLAG_FORMAT_TRUETYPE))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// reject based on filetype in URI
|
||||
|
||||
// otherwise, return true
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
FontFamily *
|
||||
|
@ -52,7 +52,9 @@ REQUIRES = \
|
||||
cairo \
|
||||
pref \
|
||||
lcms \
|
||||
necko \
|
||||
unicharutil \
|
||||
nspr \
|
||||
$(NULL)
|
||||
|
||||
# All platforms
|
||||
|
@ -288,7 +288,7 @@ PRBool
|
||||
RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
nsRefPtr<gfxFontGroup> fontGroup;
|
||||
|
||||
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle);
|
||||
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle, nsnull);
|
||||
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
|
@ -96,7 +96,7 @@ RunTest (TestEntry *test, gfxContext *ctx) {
|
||||
0.0,
|
||||
PR_FALSE, PR_FALSE);
|
||||
|
||||
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16);
|
||||
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nsnull);
|
||||
}
|
||||
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
|
@ -163,7 +163,7 @@ main (int argc, char **argv) {
|
||||
PR_FALSE, PR_FALSE);
|
||||
|
||||
nsRefPtr<gfxFontGroup> fontGroup =
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("Geneva, MS Sans Serif, Helvetica,serif"), &style);
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("Geneva, MS Sans Serif, Helvetica,serif"), &style, nsnull);
|
||||
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
ctx, nsnull, nsnull, nsnull, 0, 60
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include "nsIWidget.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
#include "nsSVGUtils.h"
|
||||
@ -1493,10 +1494,13 @@ nsresult
|
||||
nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext,
|
||||
nsIFontMetrics** aFontMetrics)
|
||||
{
|
||||
return aStyleContext->PresContext()->DeviceContext()->
|
||||
GetMetricsFor(aStyleContext->GetStyleFont()->mFont,
|
||||
// pass the user font set object into the device context to pass along to CreateFontGroup
|
||||
gfxUserFontSet* fs = aStyleContext->PresContext()->GetUserFontSet();
|
||||
|
||||
return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor(
|
||||
aStyleContext->GetStyleFont()->mFont,
|
||||
aStyleContext->GetStyleVisibility()->mLangGroup,
|
||||
*aFontMetrics);
|
||||
*aFontMetrics, fs);
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
|
@ -83,6 +83,7 @@
|
||||
#include "nsStyleChangeList.h"
|
||||
#include "nsRuleNode.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
||||
#ifdef IBMBIDI
|
||||
#include "nsBidiPresUtils.h"
|
||||
@ -226,6 +227,7 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
||||
mNeverAnimate = PR_FALSE;
|
||||
}
|
||||
NS_ASSERTION(mDocument, "Null document");
|
||||
mUserFontSet = nsnull;
|
||||
}
|
||||
|
||||
nsPresContext::~nsPresContext()
|
||||
@ -283,6 +285,8 @@ nsPresContext::~nsPresContext()
|
||||
NS_IF_RELEASE(mDeviceContext);
|
||||
NS_IF_RELEASE(mLookAndFeel);
|
||||
NS_IF_RELEASE(mLangGroup);
|
||||
|
||||
SetUserFontSet(nsnull);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
|
||||
@ -1576,6 +1580,19 @@ nsPresContext::HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask)
|
||||
HasAuthorSpecifiedRules(aFrame->GetStyleContext(), ruleTypeMask);
|
||||
}
|
||||
|
||||
gfxUserFontSet*
|
||||
nsPresContext::GetUserFontSet() {
|
||||
return mUserFontSet;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::SetUserFontSet(gfxUserFontSet *aUserFontSet)
|
||||
{
|
||||
NS_IF_RELEASE(mUserFontSet);
|
||||
mUserFontSet = aUserFontSet;
|
||||
NS_IF_ADDREF(mUserFontSet);
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::FireDOMPaintEvent()
|
||||
{
|
||||
|
@ -66,6 +66,7 @@
|
||||
// This also pulls in gfxTypes.h, which we cannot include directly.
|
||||
#include "gfxRect.h"
|
||||
#include "nsRegion.h"
|
||||
|
||||
class nsImageLoader;
|
||||
#ifdef IBMBIDI
|
||||
class nsBidiPresUtils;
|
||||
@ -91,6 +92,7 @@ class nsIAtom;
|
||||
struct nsStyleBackground;
|
||||
template <class T> class nsRunnableMethod;
|
||||
class nsIRunnable;
|
||||
class gfxUserFontSet;
|
||||
|
||||
#ifdef MOZ_REFLOW_PERF
|
||||
class nsIRenderingContext;
|
||||
@ -778,6 +780,9 @@ public:
|
||||
}
|
||||
|
||||
PRBool SupressingResizeReflow() const { return mSupressResizeReflow; }
|
||||
|
||||
gfxUserFontSet* GetUserFontSet();
|
||||
void SetUserFontSet(gfxUserFontSet *aUserFontSet);
|
||||
|
||||
void NotifyInvalidation(const nsRect& aRect, PRBool aIsCrossDoc);
|
||||
void FireDOMPaintEvent();
|
||||
@ -845,6 +850,9 @@ protected:
|
||||
nsRegion mSameDocDirtyRegion;
|
||||
nsRegion mCrossDocDirtyRegion;
|
||||
|
||||
// container for per-context fonts (downloadable, SVG, etc.)
|
||||
gfxUserFontSet* mUserFontSet;
|
||||
|
||||
nsLanguageSpecificTransformType mLanguageSpecificTransformType;
|
||||
PRInt32 mFontScaler;
|
||||
nscoord mMinimumFontSize;
|
||||
|
@ -151,6 +151,7 @@ CPPSRCS = \
|
||||
nsDOMCSSRGBColor.cpp \
|
||||
nsDOMCSSRect.cpp \
|
||||
nsDOMCSSValueList.cpp \
|
||||
nsFontFaceLoader.cpp \
|
||||
nsHTMLCSSStyleSheet.cpp \
|
||||
nsHTMLStyleSheet.cpp \
|
||||
nsInspectorCSSUtils.cpp \
|
||||
|
@ -82,6 +82,10 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIMediaList.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "nsCSSRules.h"
|
||||
#include "nsFontFaceLoader.h"
|
||||
|
||||
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
||||
static nsTArray< nsCOMPtr<nsIAtom> >* sSystemMetrics = 0;
|
||||
@ -2292,6 +2296,129 @@ struct CascadeEnumData {
|
||||
PLArenaPool& mArena;
|
||||
};
|
||||
|
||||
static void
|
||||
InsertFontFaceRule(nsICSSRule* aRule, gfxUserFontSet* fs)
|
||||
{
|
||||
nsCSSFontFaceRule *fontFace = static_cast<nsCSSFontFaceRule*> (aRule);
|
||||
PRInt32 type;
|
||||
NS_ASSERTION(NS_SUCCEEDED(aRule->GetType(type))
|
||||
&& type == nsICSSRule::FONT_FACE_RULE,
|
||||
"InsertFontFaceRule passed a non-fontface CSS rule");
|
||||
|
||||
// fontFace->List();
|
||||
|
||||
nsAutoString fontfamily, valueString;
|
||||
nsCSSValue val;
|
||||
|
||||
PRUint32 unit;
|
||||
PRUint32 weight = NS_STYLE_FONT_WEIGHT_NORMAL;
|
||||
PRUint32 stretch = NS_STYLE_FONT_STRETCH_NORMAL;
|
||||
PRUint32 italicStyle = FONT_STYLE_NORMAL;
|
||||
|
||||
// set up family name
|
||||
fontFace->GetDesc(eCSSFontDesc_Family, val);
|
||||
unit = val.GetUnit();
|
||||
if (unit == eCSSUnit_String) {
|
||||
val.GetStringValue(fontfamily);
|
||||
fontfamily.Trim("\"");
|
||||
} else {
|
||||
NS_ASSERTION(unit == eCSSUnit_String,
|
||||
"@font-face family name has non-string unit type");
|
||||
return;
|
||||
}
|
||||
|
||||
// set up weight
|
||||
fontFace->GetDesc(eCSSFontDesc_Weight, val);
|
||||
unit = val.GetUnit();
|
||||
if (unit != eCSSUnit_Null) {
|
||||
if (unit == eCSSUnit_Normal) {
|
||||
weight = NS_STYLE_FONT_WEIGHT_NORMAL;
|
||||
} else {
|
||||
weight = val.GetIntValue();
|
||||
}
|
||||
}
|
||||
|
||||
// set up stretch
|
||||
fontFace->GetDesc(eCSSFontDesc_Stretch, val);
|
||||
unit = val.GetUnit();
|
||||
if (unit != eCSSUnit_Null) {
|
||||
if (unit == eCSSUnit_Normal) {
|
||||
stretch = NS_STYLE_FONT_STRETCH_NORMAL;
|
||||
} else {
|
||||
stretch = val.GetIntValue();
|
||||
}
|
||||
}
|
||||
|
||||
// set up font style
|
||||
fontFace->GetDesc(eCSSFontDesc_Style, val);
|
||||
if (val.GetUnit() != eCSSUnit_Null) {
|
||||
if (val.GetUnit() == eCSSUnit_Normal) {
|
||||
italicStyle = FONT_STYLE_NORMAL;
|
||||
} else {
|
||||
italicStyle = val.GetIntValue();
|
||||
}
|
||||
}
|
||||
|
||||
// set up src array
|
||||
nsTArray<gfxFontFaceSrc> srcArray;
|
||||
|
||||
fontFace->GetDesc(eCSSFontDesc_Src, val);
|
||||
unit = val.GetUnit();
|
||||
if (unit == eCSSUnit_Array) {
|
||||
nsCSSValue::Array *srcArr = val.GetArrayValue();
|
||||
PRUint32 i, numSrc = srcArr->Count(), faceIndex = 0;
|
||||
|
||||
for (i = 0; i < numSrc; i++) {
|
||||
val = srcArr->Item(i);
|
||||
unit = val.GetUnit();
|
||||
gfxFontFaceSrc *face = srcArray.AppendElements(1);
|
||||
if (!face)
|
||||
return;
|
||||
|
||||
switch (unit) {
|
||||
|
||||
case eCSSUnit_Local_Font:
|
||||
val.GetStringValue(face->mLocalName);
|
||||
face->mIsLocal = PR_TRUE;
|
||||
face->mURI = nsnull;
|
||||
face->mFormatFlags = 0;
|
||||
break;
|
||||
case eCSSUnit_URL:
|
||||
face->mIsLocal = PR_FALSE;
|
||||
face->mURI = val.GetURLValue();
|
||||
face->mLocalName.Truncate();
|
||||
face->mFormatFlags = 0;
|
||||
while (i + 1 < numSrc && (val = srcArr->Item(i+1),
|
||||
val.GetUnit() == eCSSUnit_Font_Format)) {
|
||||
nsDependentString valueString(val.GetStringBufferValue());
|
||||
if (valueString.LowerCaseEqualsASCII("opentype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT;
|
||||
} else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;
|
||||
} else if (valueString.LowerCaseEqualsASCII("svg")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
|
||||
"strange unit type in font-face src array");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fontfamily.IsEmpty() && srcArray.Length() > 0) {
|
||||
fs->AddFontFace(fontfamily, srcArray, weight, stretch, italicStyle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static PRBool
|
||||
InsertRuleByWeight(nsICSSRule* aRule, void* aData)
|
||||
{
|
||||
@ -2325,10 +2452,28 @@ InsertRuleByWeight(nsICSSRule* aRule, void* aData)
|
||||
if (!groupRule->EnumerateRulesForwards(InsertRuleByWeight, aData))
|
||||
return PR_FALSE;
|
||||
}
|
||||
else if (nsICSSRule::FONT_FACE_RULE == type
|
||||
&& gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
|
||||
nsPresContext *presContext = data->mPresContext;
|
||||
gfxUserFontSet *fs = presContext->GetUserFontSet();
|
||||
if (!fs) {
|
||||
nsFontFaceLoaderContext *loaderCtx = new nsFontFaceLoaderContext(presContext);
|
||||
if (!loaderCtx)
|
||||
return PR_FALSE;
|
||||
fs = new gfxUserFontSet(loaderCtx); // user font set owns loader context
|
||||
if (!fs) {
|
||||
delete loaderCtx;
|
||||
return PR_FALSE;
|
||||
}
|
||||
presContext->SetUserFontSet(fs);
|
||||
}
|
||||
|
||||
InsertFontFaceRule(aRule, fs);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static PRBool
|
||||
CascadeSheetRulesInto(nsICSSStyleSheet* aSheet, void* aData)
|
||||
{
|
||||
|
@ -1253,7 +1253,7 @@ nsSVGGlyphFrame::EnsureTextRun(float *aDrawScale, float *aMetricsScale,
|
||||
font.familyNameQuirks);
|
||||
|
||||
nsRefPtr<gfxFontGroup> fontGroup =
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(font.name, &fontStyle);
|
||||
gfxPlatform::GetPlatform()->CreateFontGroup(font.name, &fontStyle, presContext->GetUserFontSet());
|
||||
|
||||
PRUint32 flags = gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX |
|
||||
nsLayoutUtils::GetTextRunFlagsForStyle(GetStyleContext(), GetStyleText(), GetStyleFont());
|
||||
|
@ -134,6 +134,9 @@ pref("gfx.color_management.mode", 2);
|
||||
pref("gfx.color_management.display_profile", "");
|
||||
pref("gfx.color_management.rendering_intent", 0);
|
||||
|
||||
pref("gfx.downloadable_fonts.enabled", true);
|
||||
pref("gfx.downloadable_fonts.enforce_same_site_origin", true);
|
||||
|
||||
pref("accessibility.browsewithcaret", false);
|
||||
pref("accessibility.warn_on_browsewithcaret", true);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user