mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 19:09:49 +00:00
bug 499292 - hide fallback text for a short time while a font downloads. r=jdaggett a=beltzner
This commit is contained in:
parent
7d920d8376
commit
448ebf5098
@ -1955,6 +1955,8 @@ gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyl
|
||||
mUserFontSet = nsnull;
|
||||
SetUserFontSet(aUserFontSet);
|
||||
|
||||
mSkipDrawing = PR_FALSE;
|
||||
|
||||
mPageLang = gfxPlatform::GetFontPrefLangFor(mStyle.language);
|
||||
BuildFontList();
|
||||
}
|
||||
@ -2035,14 +2037,20 @@ gfxFontGroup::FindPlatformFont(const nsAString& aName,
|
||||
gfxFontGroup *fontGroup = static_cast<gfxFontGroup*>(aClosure);
|
||||
const gfxFontStyle *fontStyle = fontGroup->GetStyle();
|
||||
|
||||
|
||||
PRBool needsBold;
|
||||
gfxFontEntry *fe = nsnull;
|
||||
|
||||
// first, look up in the user font set
|
||||
gfxUserFontSet *fs = fontGroup->GetUserFontSet();
|
||||
if (fs) {
|
||||
fe = fs->FindFontEntry(aName, *fontStyle, needsBold);
|
||||
// if the fontSet matches the family, but the font has not yet finished
|
||||
// loading (nor has its load timeout fired), the fontGroup should wait
|
||||
// for the download, and not actually draw its text yet
|
||||
PRBool waitForUserFont = PR_FALSE;
|
||||
fe = fs->FindFontEntry(aName, *fontStyle, needsBold, waitForUserFont);
|
||||
if (!fe && waitForUserFont) {
|
||||
fontGroup->mSkipDrawing = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing in the user font set ==> check system fonts
|
||||
@ -2240,15 +2248,21 @@ gfxFontGroup::ForEachFontInternal(const nsAString& aFamilies,
|
||||
ResolveData data(fc, gf, closure);
|
||||
PRBool aborted = PR_FALSE, needsBold;
|
||||
nsresult rv;
|
||||
|
||||
if (mUserFontSet && mUserFontSet->FindFontEntry(family, mStyle, needsBold)) {
|
||||
PRBool waitForUserFont = PR_FALSE;
|
||||
if (mUserFontSet &&
|
||||
mUserFontSet->FindFontEntry(family, mStyle, needsBold,
|
||||
waitForUserFont))
|
||||
{
|
||||
gfxFontGroup::FontResolverProc(family, &data);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
if (waitForUserFont) {
|
||||
mSkipDrawing = PR_TRUE;
|
||||
}
|
||||
gfxPlatform *pf = gfxPlatform::GetPlatform();
|
||||
rv = pf->ResolveFontName(family,
|
||||
gfxFontGroup::FontResolverProc,
|
||||
&data, aborted);
|
||||
gfxFontGroup::FontResolverProc,
|
||||
&data, aborted);
|
||||
}
|
||||
if (NS_FAILED(rv) || aborted)
|
||||
return PR_FALSE;
|
||||
@ -2650,6 +2664,7 @@ gfxFontGroup::UpdateFontList()
|
||||
// xxx - can probably improve this to detect when all fonts were found, so no need to update list
|
||||
mFonts.Clear();
|
||||
mUnderlineOffset = UNDERLINE_OFFSET_NOT_SET;
|
||||
mSkipDrawing = PR_FALSE;
|
||||
|
||||
// bug 548184 - need to clean up FT2, OS/2 platform code to use BuildFontList
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
@ -3043,6 +3058,7 @@ gfxTextRun::gfxTextRun(const gfxTextRunFactory::Parameters *aParams, const void
|
||||
#endif
|
||||
|
||||
mUserFontSetGeneration = mFontGroup->GetGeneration();
|
||||
mSkipDrawing = mFontGroup->ShouldSkipDrawing();
|
||||
}
|
||||
|
||||
gfxTextRun::~gfxTextRun()
|
||||
@ -3472,6 +3488,21 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt,
|
||||
NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range");
|
||||
|
||||
gfxFloat direction = GetDirection();
|
||||
|
||||
if (mSkipDrawing) {
|
||||
// We're waiting for a user font to finish downloading;
|
||||
// but if the caller wants advance width, we need to compute it here
|
||||
if (aAdvanceWidth) {
|
||||
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
|
||||
gfxFont::LOOSE_INK_EXTENTS,
|
||||
aContext, aProvider);
|
||||
*aAdvanceWidth = metrics.mAdvanceWidth * direction;
|
||||
}
|
||||
|
||||
// return without drawing
|
||||
return;
|
||||
}
|
||||
|
||||
gfxPoint pt = aPt;
|
||||
|
||||
// synthetic bolding draws glyphs twice ==> colors with opacity won't draw correctly unless first drawn without alpha
|
||||
@ -4088,6 +4119,10 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, PRUint32 aStart,
|
||||
NS_ASSERTION(aDest + aLength <= GetLength(),
|
||||
"Destination substring out of range");
|
||||
|
||||
if (aSource->mSkipDrawing) {
|
||||
mSkipDrawing = PR_TRUE;
|
||||
}
|
||||
|
||||
// Copy base glyph data, and DetailedGlyph data where present
|
||||
for (PRUint32 i = 0; i < aLength; ++i) {
|
||||
CompressedGlyph g = aSource->mCharacterGlyphs[i + aStart];
|
||||
|
@ -2195,6 +2195,10 @@ private:
|
||||
PRUint32 mCharacterCount;
|
||||
PRUint32 mHashCode;
|
||||
PRUint64 mUserFontSetGeneration; // user font set generation when text run created
|
||||
|
||||
PRBool mSkipDrawing; // true if the font group we used had a user font
|
||||
// download that's in progress, so we should hide text
|
||||
// until the download completes (or timeout fires)
|
||||
};
|
||||
|
||||
class THEBES_API gfxFontGroup : public gfxTextRunFactory {
|
||||
@ -2322,6 +2326,10 @@ public:
|
||||
// caches need updating.
|
||||
virtual void UpdateFontList();
|
||||
|
||||
PRBool ShouldSkipDrawing() const {
|
||||
return mSkipDrawing;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsString mFamilies;
|
||||
gfxFontStyle mStyle;
|
||||
@ -2335,8 +2343,12 @@ protected:
|
||||
nsRefPtr<gfxFontFamily> mLastPrefFamily;
|
||||
nsRefPtr<gfxFont> mLastPrefFont;
|
||||
eFontPrefLang mLastPrefLang; // lang group for last pref font
|
||||
PRBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
|
||||
eFontPrefLang mPageLang;
|
||||
PRPackedBool mLastPrefFirstFont; // is this the first font in the list of pref fonts for this lang group?
|
||||
|
||||
PRPackedBool mSkipDrawing; // hide text while waiting for a font
|
||||
// download to complete (or fallback
|
||||
// timer to fire)
|
||||
|
||||
// Used for construction/destruction. Not intended to change the font set
|
||||
// as invalidation of font lists and caches is not considered.
|
||||
|
@ -1095,9 +1095,12 @@ public:
|
||||
explicit gfxFcFontSet(FcPattern *aPattern,
|
||||
gfxUserFontSet *aUserFontSet)
|
||||
: mSortPattern(aPattern), mUserFontSet(aUserFontSet),
|
||||
mFcFontSet(SortPreferredFonts()), mFcFontsTrimmed(0),
|
||||
mFcFontsTrimmed(0),
|
||||
mHaveFallbackFonts(PR_FALSE)
|
||||
{
|
||||
PRBool waitForUserFont;
|
||||
mFcFontSet = SortPreferredFonts(waitForUserFont);
|
||||
mWaitingForUserFont = waitForUserFont;
|
||||
}
|
||||
|
||||
// A reference is held by the FontSet.
|
||||
@ -1118,8 +1121,12 @@ public:
|
||||
|
||||
FcPattern *GetFontPatternAt(PRUint32 i);
|
||||
|
||||
PRBool WaitingForUserFont() const {
|
||||
return mWaitingForUserFont;
|
||||
}
|
||||
|
||||
private:
|
||||
nsReturnRef<FcFontSet> SortPreferredFonts();
|
||||
nsReturnRef<FcFontSet> SortPreferredFonts(PRBool& aWaitForUserFont);
|
||||
nsReturnRef<FcFontSet> SortFallbackFonts();
|
||||
|
||||
struct FontEntry {
|
||||
@ -1167,13 +1174,17 @@ private:
|
||||
// True iff fallback fonts are either stored in mFcFontSet or have been
|
||||
// trimmed and added to mFonts (so that mFcFontSet is NULL).
|
||||
PRPackedBool mHaveFallbackFonts;
|
||||
// True iff there was a user font set with pending downloads,
|
||||
// so the set may be updated when downloads complete
|
||||
PRPackedBool mWaitingForUserFont;
|
||||
};
|
||||
|
||||
// Find the FcPattern for an @font-face font suitable for CSS family |aFamily|
|
||||
// and style |aStyle| properties.
|
||||
static const nsTArray< nsCountedRef<FcPattern> >*
|
||||
FindFontPatterns(gfxUserFontSet *mUserFontSet,
|
||||
const nsACString &aFamily, PRUint8 aStyle, PRUint16 aWeight)
|
||||
const nsACString &aFamily, PRUint8 aStyle, PRUint16 aWeight,
|
||||
PRBool& aWaitForUserFont)
|
||||
{
|
||||
// Convert to UTF16
|
||||
NS_ConvertUTF8toUTF16 utf16Family(aFamily);
|
||||
@ -1188,13 +1199,15 @@ FindFontPatterns(gfxUserFontSet *mUserFontSet,
|
||||
style.weight = aWeight;
|
||||
|
||||
gfxUserFcFontEntry *fontEntry = static_cast<gfxUserFcFontEntry*>
|
||||
(mUserFontSet->FindFontEntry(utf16Family, style, needsBold));
|
||||
(mUserFontSet->FindFontEntry(utf16Family, style, needsBold,
|
||||
aWaitForUserFont));
|
||||
|
||||
// Accept synthetic oblique for italic and oblique.
|
||||
if (!fontEntry && aStyle != FONT_STYLE_NORMAL) {
|
||||
style.style = FONT_STYLE_NORMAL;
|
||||
fontEntry = static_cast<gfxUserFcFontEntry*>
|
||||
(mUserFontSet->FindFontEntry(utf16Family, style, needsBold));
|
||||
(mUserFontSet->FindFontEntry(utf16Family, style, needsBold,
|
||||
aWaitForUserFont));
|
||||
}
|
||||
|
||||
if (!fontEntry)
|
||||
@ -1270,8 +1283,10 @@ SizeIsAcceptable(FcPattern *aFont, double aRequestedSize)
|
||||
// Sorting only the preferred fonts first usually saves having to sort through
|
||||
// every font on the system.
|
||||
nsReturnRef<FcFontSet>
|
||||
gfxFcFontSet::SortPreferredFonts()
|
||||
gfxFcFontSet::SortPreferredFonts(PRBool &aWaitForUserFont)
|
||||
{
|
||||
aWaitForUserFont = PR_FALSE;
|
||||
|
||||
gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils();
|
||||
if (!utils)
|
||||
return nsReturnRef<FcFontSet>();
|
||||
@ -1350,8 +1365,13 @@ gfxFcFontSet::SortPreferredFonts()
|
||||
PRUint16 thebesWeight =
|
||||
gfxFontconfigUtils::GetThebesWeight(mSortPattern);
|
||||
|
||||
PRBool waitForUserFont;
|
||||
familyFonts = FindFontPatterns(mUserFontSet, cssFamily,
|
||||
thebesStyle, thebesWeight);
|
||||
thebesStyle, thebesWeight,
|
||||
waitForUserFont);
|
||||
if (waitForUserFont) {
|
||||
aWaitForUserFont = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1860,6 +1880,7 @@ gfxPangoFontGroup::UpdateFontList()
|
||||
mFontSets.Clear();
|
||||
mUnderlineOffset = UNDERLINE_OFFSET_NOT_SET;
|
||||
mCurrGeneration = newGeneration;
|
||||
mSkipDrawing = PR_FALSE;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFcFontSet>
|
||||
@ -1889,6 +1910,8 @@ gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
|
||||
nsRefPtr<gfxFcFontSet> fontset =
|
||||
new gfxFcFontSet(pattern, mUserFontSet);
|
||||
|
||||
mSkipDrawing = fontset->WaitingForUserFont();
|
||||
|
||||
if (aMatchPattern)
|
||||
aMatchPattern->steal(pattern);
|
||||
|
||||
|
@ -73,7 +73,8 @@ gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSr
|
||||
const nsTArray<gfxFontFeature>& aFeatureSettings,
|
||||
PRUint32 aLanguageOverride,
|
||||
gfxSparseBitSet *aUnicodeRanges)
|
||||
: gfxFontEntry(NS_LITERAL_STRING("Proxy"), aFamily), mIsLoading(PR_FALSE)
|
||||
: gfxFontEntry(NS_LITERAL_STRING("Proxy"), aFamily),
|
||||
mLoadingState(NOT_LOADING)
|
||||
{
|
||||
mIsProxy = PR_TRUE;
|
||||
mSrcList = aFontFaceSrcList;
|
||||
@ -162,25 +163,32 @@ gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
|
||||
gfxFontEntry*
|
||||
gfxUserFontSet::FindFontEntry(const nsAString& aName,
|
||||
const gfxFontStyle& aFontStyle,
|
||||
PRBool& aNeedsBold)
|
||||
PRBool& aNeedsBold,
|
||||
PRBool& aWaitForUserFont)
|
||||
{
|
||||
aWaitForUserFont = PR_FALSE;
|
||||
gfxMixedFontFamily *family = GetFamily(aName);
|
||||
|
||||
// no user font defined for this name
|
||||
if (!family)
|
||||
if (!family) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gfxFontEntry* fe = family->FindFontForStyle(aFontStyle, aNeedsBold);
|
||||
|
||||
// if not a proxy, font has already been loaded
|
||||
if (!fe->mIsProxy)
|
||||
if (!fe->mIsProxy) {
|
||||
return fe;
|
||||
}
|
||||
|
||||
gfxProxyFontEntry *proxyEntry = static_cast<gfxProxyFontEntry*> (fe);
|
||||
|
||||
// if currently loading, return null for now
|
||||
if (proxyEntry->mIsLoading)
|
||||
if (proxyEntry->mLoadingState > gfxProxyFontEntry::NOT_LOADING) {
|
||||
aWaitForUserFont =
|
||||
(proxyEntry->mLoadingState < gfxProxyFontEntry::LOADING_SLOWLY);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// hasn't been loaded yet, start the load process
|
||||
LoadStatus status;
|
||||
@ -189,10 +197,13 @@ gfxUserFontSet::FindFontEntry(const nsAString& aName,
|
||||
|
||||
// if the load succeeded immediately, the font entry was replaced so
|
||||
// search again
|
||||
if (status == STATUS_LOADED)
|
||||
if (status == STATUS_LOADED) {
|
||||
return family->FindFontForStyle(aFontStyle, aNeedsBold);
|
||||
}
|
||||
|
||||
// if either loading or an error occurred, return null
|
||||
aWaitForUserFont =
|
||||
(proxyEntry->mLoadingState < gfxProxyFontEntry::LOADING_SLOWLY);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -568,14 +579,12 @@ gfxUserFontSet::OnLoadComplete(gfxFontEntry *aFontToLoad,
|
||||
LoadStatus status;
|
||||
|
||||
status = LoadNext(pe);
|
||||
if (status == STATUS_LOADED) {
|
||||
// load may succeed if external font resource followed by
|
||||
// local font, in this case need to bump generation
|
||||
IncrementGeneration();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
// Even if loading failed, we need to bump the font-set generation
|
||||
// and return true in order to trigger reflow, so that fallback
|
||||
// will be used where the text was "masked" by the pending download
|
||||
IncrementGeneration();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -586,10 +595,13 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
|
||||
|
||||
NS_ASSERTION(aProxyEntry->mSrcIndex < numSrc, "already at the end of the src list for user font");
|
||||
|
||||
if (aProxyEntry->mIsLoading) {
|
||||
aProxyEntry->mSrcIndex++;
|
||||
if (aProxyEntry->mLoadingState == gfxProxyFontEntry::NOT_LOADING) {
|
||||
aProxyEntry->mLoadingState = gfxProxyFontEntry::LOADING_STARTED;
|
||||
} else {
|
||||
aProxyEntry->mIsLoading = PR_TRUE;
|
||||
// we were already loading; move to the next source,
|
||||
// but don't reset state - if we've already timed out,
|
||||
// that counts against the new download
|
||||
aProxyEntry->mSrcIndex++;
|
||||
}
|
||||
|
||||
// load each src entry in turn, until a local face is found or a download begins successfully
|
||||
|
@ -190,7 +190,8 @@ public:
|
||||
// lookup a font entry for a given style, returns null if not loaded
|
||||
gfxFontEntry *FindFontEntry(const nsAString& aName,
|
||||
const gfxFontStyle& aFontStyle,
|
||||
PRBool& aNeedsBold);
|
||||
PRBool& aNeedsBold,
|
||||
PRBool& aWaitForUserFont);
|
||||
|
||||
// initialize the process that loads external font data, which upon
|
||||
// completion will call OnLoadComplete method
|
||||
@ -211,14 +212,14 @@ public:
|
||||
// incremented so that the change can be recognized
|
||||
PRUint64 GetGeneration() { return mGeneration; }
|
||||
|
||||
// increment the generation on font load
|
||||
void IncrementGeneration();
|
||||
|
||||
protected:
|
||||
// for a given proxy font entry, attempt to load the next resource
|
||||
// in the src list
|
||||
LoadStatus LoadNext(gfxProxyFontEntry *aProxyEntry);
|
||||
|
||||
// increment the generation on font load
|
||||
void IncrementGeneration();
|
||||
|
||||
gfxMixedFontFamily *GetFamily(const nsAString& aName) const;
|
||||
|
||||
// remove family
|
||||
@ -249,9 +250,19 @@ public:
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
|
||||
|
||||
PRPackedBool mIsLoading;
|
||||
nsTArray<gfxFontFaceSrc> mSrcList;
|
||||
PRUint32 mSrcIndex; // index of loading src item
|
||||
// note that code depends on the ordering of these values!
|
||||
enum LoadingState {
|
||||
NOT_LOADING = 0, // not started to load any font resources yet
|
||||
LOADING_STARTED, // loading has started; hide fallback font
|
||||
LOADING_ALMOST_DONE, // timeout happened but we're nearly done,
|
||||
// so keep hiding fallback font
|
||||
LOADING_SLOWLY // timeout happened and we're not nearly done,
|
||||
// so use the fallback font
|
||||
};
|
||||
LoadingState mLoadingState;
|
||||
|
||||
nsTArray<gfxFontFaceSrc> mSrcList;
|
||||
PRUint32 mSrcIndex; // index of loading src item
|
||||
};
|
||||
|
||||
|
||||
|
@ -337,7 +337,15 @@ nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
|
||||
return NS_OK;
|
||||
if (!IsVisibleForPainting(aBuilder))
|
||||
return NS_OK;
|
||||
|
||||
|
||||
// Hide text decorations if we're currently hiding @font-face fallback text
|
||||
nsCOMPtr<nsIFontMetrics> fm;
|
||||
nsresult rv = nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
|
||||
if (tfm->GetThebesFontGroup()->ShouldSkipDrawing())
|
||||
return NS_OK;
|
||||
|
||||
// Do standards mode painting of 'text-decoration's: under+overline
|
||||
// behind children, line-through in front. For Quirks mode, see
|
||||
// nsTextFrame::PaintTextDecorations. (See bug 1777.)
|
||||
@ -353,25 +361,25 @@ nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
|
||||
// shadow applied to them. So draw the shadows as part of the display
|
||||
// list, underneath the text and all decorations.
|
||||
if (GetStyleText()->mTextShadow) {
|
||||
nsresult rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayTextShadow(aBuilder, this, decorations, aLine));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (decorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
|
||||
nsresult rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayTextDecoration(aBuilder, this, NS_STYLE_TEXT_DECORATION_UNDERLINE,
|
||||
underColor, aLine));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (decorations & NS_STYLE_TEXT_DECORATION_OVERLINE) {
|
||||
nsresult rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayTextDecoration(aBuilder, this, NS_STYLE_TEXT_DECORATION_OVERLINE,
|
||||
overColor, aLine));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (decorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
|
||||
nsresult rv = aAboveTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
rv = aAboveTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayTextDecoration(aBuilder, this, NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
|
||||
strikeColor, aLine));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -4310,6 +4310,10 @@ nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
|
||||
if (!decorations.HasDecorationlines())
|
||||
return;
|
||||
|
||||
// Hide text decorations if we're currently hiding @font-face fallback text
|
||||
if (aProvider.GetFontGroup()->ShouldSkipDrawing())
|
||||
return;
|
||||
|
||||
gfxFont* firstFont = aProvider.GetFontGroup()->GetFontAt(0);
|
||||
if (!firstFont)
|
||||
return; // OOM
|
||||
@ -4860,6 +4864,10 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
||||
PropertyProvider& aProvider, nsTextPaintStyle& aTextPaintStyle,
|
||||
SelectionDetails* aDetails, SelectionType aSelectionType)
|
||||
{
|
||||
// Hide text decorations if we're currently hiding @font-face fallback text
|
||||
if (aProvider.GetFontGroup()->ShouldSkipDrawing())
|
||||
return;
|
||||
|
||||
PRInt32 contentOffset = aProvider.GetStart().GetOriginalOffset();
|
||||
PRInt32 contentLength = aProvider.GetOriginalLength();
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIPrefService.h"
|
||||
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
@ -89,11 +90,94 @@ nsFontFaceLoader::nsFontFaceLoader(gfxFontEntry *aFontToLoad, nsIURI *aFontURI,
|
||||
|
||||
nsFontFaceLoader::~nsFontFaceLoader()
|
||||
{
|
||||
if (mLoadTimer) {
|
||||
mLoadTimer->Cancel();
|
||||
mLoadTimer = nsnull;
|
||||
}
|
||||
if (mFontSet) {
|
||||
mFontSet->RemoveLoader(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFontFaceLoader::StartedLoading(nsIStreamLoader *aStreamLoader)
|
||||
{
|
||||
PRInt32 loadTimeout = 3000;
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
prefs->GetIntPref("gfx.downloadable_fonts.fallback_delay", &loadTimeout);
|
||||
}
|
||||
if (loadTimeout > 0) {
|
||||
mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (mLoadTimer) {
|
||||
mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
|
||||
static_cast<void*>(this),
|
||||
loadTimeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
} else {
|
||||
gfxProxyFontEntry *pe =
|
||||
static_cast<gfxProxyFontEntry*>(mFontEntry.get());
|
||||
pe->mLoadingState = gfxProxyFontEntry::LOADING_SLOWLY;
|
||||
}
|
||||
mStreamLoader = aStreamLoader;
|
||||
}
|
||||
|
||||
void
|
||||
nsFontFaceLoader::LoadTimerCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
nsFontFaceLoader *loader = static_cast<nsFontFaceLoader*>(aClosure);
|
||||
|
||||
if (!loader->mFontEntry->mIsProxy) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfxProxyFontEntry *pe =
|
||||
static_cast<gfxProxyFontEntry*>(loader->mFontEntry.get());
|
||||
bool updateUserFontSet = true;
|
||||
|
||||
// If the entry is loading, check whether it's >75% done; if so,
|
||||
// we allow another timeout period before showing a fallback font.
|
||||
if (pe->mLoadingState == gfxProxyFontEntry::LOADING_STARTED) {
|
||||
PRInt32 contentLength;
|
||||
loader->mChannel->GetContentLength(&contentLength);
|
||||
PRUint32 numBytesRead;
|
||||
loader->mStreamLoader->GetNumBytesRead(&numBytesRead);
|
||||
|
||||
if (contentLength > 0 &&
|
||||
numBytesRead > 3 * (PRUint32(contentLength) >> 2))
|
||||
{
|
||||
// More than 3/4 the data has been downloaded, so allow 50% extra
|
||||
// time and hope the remainder will arrive before the additional
|
||||
// time expires.
|
||||
pe->mLoadingState = gfxProxyFontEntry::LOADING_ALMOST_DONE;
|
||||
PRUint32 delay;
|
||||
loader->mLoadTimer->GetDelay(&delay);
|
||||
loader->mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
|
||||
static_cast<void*>(loader),
|
||||
delay >> 1,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
updateUserFontSet = false;
|
||||
LOG(("fontdownloader (%p) 75%% done, resetting timer\n", loader));
|
||||
}
|
||||
}
|
||||
|
||||
// If the font is not 75% loaded, or if we've already timed out once
|
||||
// before, we mark this entry as "loading slowly", so the fallback
|
||||
// font will be used in the meantime, and tell the context to refresh.
|
||||
if (updateUserFontSet) {
|
||||
pe->mLoadingState = gfxProxyFontEntry::LOADING_SLOWLY;
|
||||
nsPresContext *ctx = loader->mFontSet->GetPresContext();
|
||||
NS_ASSERTION(ctx, "fontSet doesn't have a presContext?");
|
||||
gfxUserFontSet *fontSet;
|
||||
if (ctx && (fontSet = ctx->GetUserFontSet()) != nsnull) {
|
||||
fontSet->IncrementGeneration();
|
||||
ctx->UserFontSetUpdated();
|
||||
LOG(("fontdownloader (%p) timeout reflow\n", loader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFontFaceLoader, nsIStreamLoaderObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -156,6 +240,10 @@ void
|
||||
nsFontFaceLoader::Cancel()
|
||||
{
|
||||
mFontSet = nsnull;
|
||||
if (mLoadTimer) {
|
||||
mLoadTimer->Cancel();
|
||||
mLoadTimer = nsnull;
|
||||
}
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
@ -343,6 +431,7 @@ nsUserFontSet::StartLoad(gfxFontEntry *aFontToLoad,
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoaders.PutEntry(fontLoader);
|
||||
fontLoader->StartedLoading(streamLoader);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "nsIStreamLoader.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsITimer.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsTHashtable.h"
|
||||
@ -105,6 +106,10 @@ public:
|
||||
|
||||
void DropChannel() { mChannel = nsnull; }
|
||||
|
||||
void StartedLoading(nsIStreamLoader *aStreamLoader);
|
||||
|
||||
static void LoadTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
static nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
|
||||
nsIURI* aTargetURI,
|
||||
nsISupports* aContext);
|
||||
@ -114,6 +119,9 @@ private:
|
||||
nsCOMPtr<nsIURI> mFontURI;
|
||||
nsRefPtr<nsUserFontSet> mFontSet;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsCOMPtr<nsITimer> mLoadTimer;
|
||||
|
||||
nsIStreamLoader *mStreamLoader;
|
||||
};
|
||||
|
||||
#endif /* !defined(nsFontFaceLoader_h_) */
|
||||
|
@ -192,6 +192,7 @@ pref("gfx.color_management.display_profile", "");
|
||||
pref("gfx.color_management.rendering_intent", 0);
|
||||
|
||||
pref("gfx.downloadable_fonts.enabled", true);
|
||||
pref("gfx.downloadable_fonts.fallback_delay", 3000);
|
||||
pref("gfx.downloadable_fonts.sanitize", true);
|
||||
#ifdef XP_MACOSX
|
||||
pref("gfx.downloadable_fonts.sanitize.preserve_otl_tables", false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user