Bug 1157064 - implementation of font-display. r=heycam,khuey

This commit is contained in:
John Daggett 2016-01-07 14:03:05 +09:00
parent 40dd7eed07
commit ade0c810ea
13 changed files with 235 additions and 73 deletions

View File

@ -19,6 +19,7 @@ dictionary FontFaceDescriptors {
DOMString unicodeRange = "U+0-10FFFF";
DOMString variant = "normal";
DOMString featureSettings = "normal";
DOMString display = "auto";
};
enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" };
@ -37,6 +38,7 @@ interface FontFace {
[SetterThrows] attribute DOMString unicodeRange;
[SetterThrows] attribute DOMString variant;
[SetterThrows] attribute DOMString featureSettings;
[SetterThrows, Pref="layout.css.font-display.enabled"] attribute DOMString display;
readonly attribute FontFaceLoadStatus status;

View File

@ -111,11 +111,13 @@ gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet* aFontSet,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
: gfxFontEntry(NS_LITERAL_STRING("userfont")),
mUserFontLoadState(STATUS_NOT_LOADED),
mFontDataLoadingState(NOT_LOADING),
mUnsupportedFormat(false),
mFontDisplay(aFontDisplay),
mLoader(nullptr),
mFontSet(aFontSet)
{
@ -146,7 +148,8 @@ gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
return mWeight == aWeight &&
mStretch == aStretch &&
@ -154,6 +157,7 @@ gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
mFeatureSettings == aFeatureSettings &&
mLanguageOverride == aLanguageOverride &&
mSrcList == aFontFaceSrcList &&
mFontDisplay == aFontDisplay &&
((!aUnicodeRanges && !mCharacterMap) ||
(aUnicodeRanges && mCharacterMap && mCharacterMap->Equals(aUnicodeRanges)));
}
@ -727,7 +731,8 @@ gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
mLoader = nullptr;
// download successful, make platform font using font data
if (NS_SUCCEEDED(aDownloadStatus)) {
if (NS_SUCCEEDED(aDownloadStatus) &&
mFontDataLoadingState != LOADING_TIMED_OUT) {
bool loaded = LoadPlatformFont(aFontData, aLength);
aFontData = nullptr;
@ -739,7 +744,9 @@ gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
} else {
// download failed
mFontSet->LogMessage(this,
"download failed", nsIScriptError::errorFlag,
(mFontDataLoadingState != LOADING_TIMED_OUT ?
"download failed" : "download timed out"),
nsIScriptError::errorFlag,
aDownloadStatus);
}
@ -747,8 +754,10 @@ gfxUserFontEntry::FontDataDownloadComplete(const uint8_t* aFontData,
free((void*)aFontData);
}
// error occurred, load next src
LoadNextSrc();
// error occurred, load next src if load not yet timed out
if (mFontDataLoadingState != LOADING_TIMED_OUT) {
LoadNextSrc();
}
// We ignore the status returned by LoadNext();
// even if loading failed, we need to bump the font-set generation
@ -795,7 +804,8 @@ gfxUserFontSet::FindOrCreateUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
RefPtr<gfxUserFontEntry> entry;
@ -810,13 +820,14 @@ gfxUserFontSet::FindOrCreateUserFontEntry(
entry = FindExistingUserFontEntry(family, aFontFaceSrcList, aWeight,
aStretch, aStyle,
aFeatureSettings, aLanguageOverride,
aUnicodeRanges);
aUnicodeRanges, aFontDisplay);
}
if (!entry) {
entry = CreateUserFontEntry(aFontFaceSrcList, aWeight, aStretch,
aStyle, aFeatureSettings,
aLanguageOverride, aUnicodeRanges);
aLanguageOverride, aUnicodeRanges,
aFontDisplay);
entry->mFamilyName = aFamilyName;
}
@ -831,13 +842,14 @@ gfxUserFontSet::CreateUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
RefPtr<gfxUserFontEntry> userFontEntry =
new gfxUserFontEntry(this, aFontFaceSrcList, aWeight,
aStretch, aStyle, aFeatureSettings,
aLanguageOverride, aUnicodeRanges);
aLanguageOverride, aUnicodeRanges, aFontDisplay);
return userFontEntry.forget();
}
@ -850,7 +862,8 @@ gfxUserFontSet::FindExistingUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
MOZ_ASSERT(aWeight != 0,
"aWeight must not be 0; use NS_FONT_WEIGHT_NORMAL instead");
@ -867,7 +880,7 @@ gfxUserFontSet::FindExistingUserFontEntry(
if (!existingUserFontEntry->Matches(aFontFaceSrcList,
aWeight, aStretch, aStyle,
aFeatureSettings, aLanguageOverride,
aUnicodeRanges)) {
aUnicodeRanges, aFontDisplay)) {
continue;
}
@ -886,11 +899,12 @@ gfxUserFontSet::AddUserFontEntry(const nsAString& aFamilyName,
if (LOG_ENABLED()) {
LOG(("userfonts (%p) added to \"%s\" (%p) style: %s weight: %d "
"stretch: %d",
"stretch: %d display: %d",
this, NS_ConvertUTF16toUTF8(aFamilyName).get(), aUserFontEntry,
(aUserFontEntry->IsItalic() ? "italic" :
(aUserFontEntry->IsOblique() ? "oblique" : "normal")),
aUserFontEntry->Weight(), aUserFontEntry->Stretch()));
aUserFontEntry->Weight(), aUserFontEntry->Stretch(),
aUserFontEntry->GetFontDisplay()));
}
}

View File

@ -214,7 +214,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges) = 0;
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay) = 0;
// creates a font face for the specified family, or returns an existing
// matching entry on the family if there is one
@ -226,7 +227,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
// add in a font face for which we have the gfxUserFontEntry already
void AddUserFontEntry(const nsAString& aFamilyName,
@ -508,7 +510,8 @@ protected:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
// creates a new gfxUserFontFamily in mFontFamilies, or returns an existing
// family if there is one
@ -551,7 +554,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
virtual ~gfxUserFontEntry();
@ -562,7 +566,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges);
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay);
virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle,
bool aNeedsBold);
@ -591,6 +596,8 @@ public:
return mCharacterMap.get();
}
uint8_t GetFontDisplay() const { return mFontDisplay; }
// load the font - starts the loading of sources which continues until
// a valid font resource is found or all sources fail
void Load();
@ -661,11 +668,13 @@ protected:
// so keep hiding fallback font
LOADING_SLOWLY, // timeout happened and we're not nearly done,
// so use the fallback font
LOADING_TIMED_OUT, // font load took too long
LOADING_FAILED // failed to load any source: use fallback
};
FontDataLoadingState mFontDataLoadingState;
bool mUnsupportedFormat;
uint8_t mFontDisplay; // timing of userfont fallback
RefPtr<gfxFontEntry> mPlatformFontEntry;
nsTArray<gfxFontFaceSrc> mSrcList;

View File

@ -355,6 +355,20 @@ FontFace::SetFeatureSettings(const nsAString& aValue, ErrorResult& aRv)
SetDescriptor(eCSSFontDesc_FontFeatureSettings, aValue, aRv);
}
void
FontFace::GetDisplay(nsString& aResult)
{
mFontFaceSet->FlushUserFontSet();
GetDesc(eCSSFontDesc_Display, eCSSProperty_UNKNOWN, aResult);
}
void
FontFace::SetDisplay(const nsAString& aValue, ErrorResult& aRv)
{
mFontFaceSet->FlushUserFontSet();
SetDescriptor(eCSSFontDesc_Display, aValue, aRv);
}
FontFaceLoadStatus
FontFace::Status()
{
@ -548,7 +562,10 @@ FontFace::SetDescriptors(const nsAString& aFamily,
mDescriptors->mUnicodeRange) ||
!ParseDescriptor(eCSSFontDesc_FontFeatureSettings,
aDescriptors.mFeatureSettings,
mDescriptors->mFontFeatureSettings)) {
mDescriptors->mFontFeatureSettings) ||
!ParseDescriptor(eCSSFontDesc_Display,
aDescriptors.mDisplay,
mDescriptors->mDisplay)) {
// XXX Handle font-variant once we support it (bug 1055385).
// If any of the descriptors failed to parse, none of them should be set
@ -584,6 +601,7 @@ FontFace::GetDesc(nsCSSFontDesc aDescID,
nsString& aResult) const
{
MOZ_ASSERT(aDescID == eCSSFontDesc_UnicodeRange ||
aDescID == eCSSFontDesc_Display ||
aPropID != eCSSProperty_UNKNOWN,
"only pass eCSSProperty_UNKNOWN for eCSSFontDesc_UnicodeRange");
@ -596,6 +614,8 @@ FontFace::GetDesc(nsCSSFontDesc aDescID,
if (value.GetUnit() == eCSSUnit_Null) {
if (aDescID == eCSSFontDesc_UnicodeRange) {
aResult.AssignLiteral("U+0-10FFFF");
} else if (aDescID == eCSSFontDesc_Display) {
aResult.AssignLiteral("auto");
} else if (aDescID != eCSSFontDesc_Family &&
aDescID != eCSSFontDesc_Src) {
aResult.AssignLiteral("normal");
@ -607,6 +627,10 @@ FontFace::GetDesc(nsCSSFontDesc aDescID,
// Since there's no unicode-range property, we can't use
// nsCSSValue::AppendToString to serialize this descriptor.
nsStyleUtil::AppendUnicodeRange(value, aResult);
} else if (aDescID == eCSSFontDesc_Display) {
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(value.GetIntValue(),
nsCSSProps::kFontDisplayKTable),
aResult);
} else {
value.AppendToString(aPropID, aResult, nsCSSValue::eNormalized);
}

View File

@ -47,10 +47,11 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
: gfxUserFontEntry(aFontSet, aFontFaceSrcList, aWeight, aStretch,
aStyle, aFeatureSettings, aLanguageOverride,
aUnicodeRanges) {}
aUnicodeRanges, aFontDisplay) {}
virtual void SetLoadState(UserFontLoadState aLoadState) override;
virtual void GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult) override;
@ -148,6 +149,8 @@ public:
void SetVariant(const nsAString& aValue, mozilla::ErrorResult& aRv);
void GetFeatureSettings(nsString& aResult);
void SetFeatureSettings(const nsAString& aValue, mozilla::ErrorResult& aRv);
void GetDisplay(nsString& aResult);
void SetDisplay(const nsAString& aValue, mozilla::ErrorResult& aRv);
mozilla::dom::FontFaceLoadStatus Status();
mozilla::dom::Promise* Load(mozilla::ErrorResult& aRv);

View File

@ -976,6 +976,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
int32_t stretch = NS_STYLE_FONT_STRETCH_NORMAL;
uint8_t italicStyle = NS_STYLE_FONT_STYLE_NORMAL;
uint32_t languageOverride = NO_FONT_LANGUAGE_OVERRIDE;
uint8_t fontDisplay = NS_FONT_DISPLAY_AUTO;
// set up weight
aFontFace->GetDesc(eCSSFontDesc_Weight, val);
@ -1016,6 +1017,16 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
"@font-face style has unexpected unit");
}
// set up font display
aFontFace->GetDesc(eCSSFontDesc_Display, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Enumerated) {
fontDisplay = val.GetIntValue();
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face style has unexpected unit");
}
// set up font features
nsTArray<gfxFontFeature> featureSettings;
aFontFace->GetDesc(eCSSFontDesc_FontFeatureSettings, val);
@ -1161,7 +1172,7 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName,
stretch, italicStyle,
featureSettings,
languageOverride,
unicodeRanges);
unicodeRanges, fontDisplay);
return entry.forget();
}
@ -1805,11 +1816,13 @@ FontFaceSet::UserFontSet::CreateUserFontEntry(
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges)
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay)
{
RefPtr<gfxUserFontEntry> entry =
new FontFace::Entry(this, aFontFaceSrcList, aWeight, aStretch, aStyle,
aFeatureSettings, aLanguageOverride, aUnicodeRanges);
aFeatureSettings, aLanguageOverride, aUnicodeRanges,
aFontDisplay);
return entry.forget();
}

View File

@ -89,7 +89,8 @@ public:
uint8_t aStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet* aUnicodeRanges) override;
gfxSparseBitSet* aUnicodeRanges,
uint8_t aFontDisplay) override;
private:
RefPtr<FontFaceSet> mFontFaceSet;

View File

@ -31,6 +31,18 @@ using namespace mozilla::dom;
#define LOG_ENABLED() MOZ_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), \
LogLevel::Debug)
static uint32_t
GetFallbackDelay()
{
return Preferences::GetInt("gfx.downloadable_fonts.fallback_delay", 3000);
}
static uint32_t
GetShortFallbackDelay()
{
return Preferences::GetInt("gfx.downloadable_fonts.fallback_delay_short", 100);
}
nsFontFaceLoader::nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry,
nsIURI* aFontURI,
FontFaceSet* aFontFaceSet,
@ -60,8 +72,15 @@ nsFontFaceLoader::~nsFontFaceLoader()
void
nsFontFaceLoader::StartedLoading(nsIStreamLoader* aStreamLoader)
{
int32_t loadTimeout =
Preferences::GetInt("gfx.downloadable_fonts.fallback_delay", 3000);
int32_t loadTimeout;
uint8_t fontDisplay = GetFontDisplay();
if (fontDisplay == NS_FONT_DISPLAY_AUTO ||
fontDisplay == NS_FONT_DISPLAY_BLOCK) {
loadTimeout = GetFallbackDelay();
} else {
loadTimeout = GetShortFallbackDelay();
}
if (loadTimeout > 0) {
mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mLoadTimer) {
@ -87,39 +106,72 @@ nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
}
gfxUserFontEntry* ufe = loader->mUserFontEntry.get();
bool updateUserFontSet = true;
uint8_t fontDisplay = loader->GetFontDisplay();
// If the entry is loading, check whether it's >75% done; if so,
// we allow another timeout period before showing a fallback font.
if (ufe->mFontDataLoadingState == gfxUserFontEntry::LOADING_STARTED) {
int64_t contentLength;
uint32_t numBytesRead;
if (NS_SUCCEEDED(loader->mChannel->GetContentLength(&contentLength)) &&
contentLength > 0 &&
contentLength < UINT32_MAX &&
NS_SUCCEEDED(loader->mStreamLoader->GetNumBytesRead(&numBytesRead)) &&
numBytesRead > 3 * (uint32_t(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.
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_ALMOST_DONE;
uint32_t delay;
loader->mLoadTimer->GetDelay(&delay);
loader->mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
static_cast<void*>(loader),
delay >> 1,
nsITimer::TYPE_ONE_SHOT);
updateUserFontSet = false;
LOG(("userfonts (%p) 75%% done, resetting timer\n", loader));
// Depending upon the value of the font-display descriptor for the font,
// their may be one or two timeouts associated with each font. The LOADING_SLOWLY
// state indicates that the fallback font is shown. The LOADING_TIMED_OUT
// state indicates that the fallback font is shown *and* the downloaded font
// resource will not replace the fallback font when the load completes.
bool updateUserFontSet = true;
switch (fontDisplay) {
case NS_FONT_DISPLAY_AUTO:
case NS_FONT_DISPLAY_BLOCK:
// If the entry is loading, check whether it's >75% done; if so,
// we allow another timeout period before showing a fallback font.
if (ufe->mFontDataLoadingState == gfxUserFontEntry::LOADING_STARTED) {
int64_t contentLength;
uint32_t numBytesRead;
if (NS_SUCCEEDED(loader->mChannel->GetContentLength(&contentLength)) &&
contentLength > 0 &&
contentLength < UINT32_MAX &&
NS_SUCCEEDED(loader->mStreamLoader->GetNumBytesRead(&numBytesRead)) &&
numBytesRead > 3 * (uint32_t(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.
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_ALMOST_DONE;
uint32_t delay;
loader->mLoadTimer->GetDelay(&delay);
loader->mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
static_cast<void*>(loader),
delay >> 1,
nsITimer::TYPE_ONE_SHOT);
updateUserFontSet = false;
LOG(("userfonts (%p) 75%% done, resetting timer\n", loader));
}
}
if (updateUserFontSet) {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
}
break;
case NS_FONT_DISPLAY_SWAP:
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
break;
case NS_FONT_DISPLAY_FALLBACK: {
if (ufe->mFontDataLoadingState == gfxUserFontEntry::LOADING_STARTED) {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
} else {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_TIMED_OUT;
updateUserFontSet = false;
}
break;
}
case NS_FONT_DISPLAY_OPTIONAL:
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_TIMED_OUT;
break;
default:
NS_NOTREACHED("strange font-display value");
break;
}
// 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) {
ufe->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
nsTArray<gfxUserFontSet*> fontSets;
ufe->GetUserFontSets(fontSets);
for (gfxUserFontSet* fontSet : fontSets) {
@ -127,8 +179,8 @@ nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
if (ctx) {
fontSet->IncrementGeneration();
ctx->UserFontSetUpdated(ufe);
LOG(("userfonts (%p) timeout reflow for pres context %p\n",
loader, ctx));
LOG(("userfonts (%p) timeout reflow for pres context %p display %d\n",
loader, ctx, fontDisplay));
}
}
}
@ -155,6 +207,16 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
uint32_t downloadTimeMS = uint32_t(downloadTime.ToMilliseconds());
Telemetry::Accumulate(Telemetry::WEBFONT_DOWNLOAD_TIME, downloadTimeMS);
if (GetFontDisplay() == NS_FONT_DISPLAY_FALLBACK) {
uint32_t loadTimeout = GetFallbackDelay();
if (downloadTimeMS > loadTimeout &&
(mUserFontEntry->mFontDataLoadingState ==
gfxUserFontEntry::LOADING_SLOWLY)) {
mUserFontEntry->mFontDataLoadingState =
gfxUserFontEntry::LOADING_TIMED_OUT;
}
}
if (LOG_ENABLED()) {
nsAutoCString fontURI;
mFontURI->GetSpec(fontURI);
@ -271,3 +333,13 @@ nsFontFaceLoader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
return NS_OK;
}
uint8_t
nsFontFaceLoader::GetFontDisplay()
{
uint8_t fontDisplay = NS_FONT_DISPLAY_AUTO;
if (Preferences::GetBool("layout.css.font-display.enabled")) {
fontDisplay = mUserFontEntry->GetFontDisplay();
}
return fontDisplay;
}

View File

@ -50,6 +50,9 @@ public:
protected:
virtual ~nsFontFaceLoader();
// helper method for determining the font-display value
uint8_t GetFontDisplay();
private:
RefPtr<gfxUserFontEntry> mUserFontEntry;
nsCOMPtr<nsIURI> mFontURI;

View File

@ -63,5 +63,10 @@ var gCSSFontFaceDescriptors = {
domProp: null,
values: [ "U+0-10FFFF", "U+3-7B3", "U+3??", "U+6A", "U+3????", "U+???", "U+302-302", "U+0-7,U+A-C", "U+100-17F,U+200-17F", "U+3??, U+500-513 ,U+612 , U+4????", "U+1FFF,U+200-27F" ],
invalid_values: [ "U+1????-2????", "U+0-7,A-C", "U+100-17F,200-17F", "U+6A!important", "U+6A)" ]
},
"font-display": {
domProp: null,
values: [ "auto", "block", "swap", "fallback", "optional" ],
invalid_values: [ "normal", "initial" ]
}
}

View File

@ -91,19 +91,27 @@ function test_descriptor(descriptor)
// To avoid triggering the slow script dialog, we have to test one
// descriptor at a time.
SimpleTest.waitForExplicitFinish();
var descs = [];
for (var desc in gCSSFontFaceDescriptors)
descs.push(desc);
descs = descs.reverse();
function do_one() {
if (descs.length == 0) {
SimpleTest.finish();
return;
function runTest() {
var descs = [];
for (var desc in gCSSFontFaceDescriptors)
descs.push(desc);
descs = descs.reverse();
function do_one() {
if (descs.length == 0) {
SimpleTest.finish();
return;
}
test_descriptor(descs.pop());
SimpleTest.executeSoon(do_one);
}
test_descriptor(descs.pop());
SimpleTest.executeSoon(do_one);
}
SimpleTest.executeSoon(do_one);
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(5);
SpecialPowers.pushPrefEnv({ set: [["layout.css.font-display.enabled", true]] },
runTest);
</script>
</pre>

View File

@ -19,7 +19,8 @@ var descriptorNames = {
stretch: "font-stretch",
unicodeRange: "unicode-range",
variant: "font-variant",
featureSettings: "font-feature-settings"
featureSettings: "font-feature-settings",
display: "font-display"
};
// Default values for the FontFace descriptor attributes other than family, as
@ -30,7 +31,8 @@ var defaultValues = {
stretch: "normal",
unicodeRange: "U+0-10FFFF",
variant: "normal",
featureSettings: "normal"
featureSettings: "normal",
display: "auto"
};
// Non-default values for the FontFace descriptor attributes other than family
@ -42,7 +44,8 @@ var nonDefaultValues = {
stretch: ["Ultra-Condensed", "ultra-condensed"],
unicodeRange: ["U+3??", "U+300-3FF"],
variant: ["Small-Caps", "small-caps"],
featureSettings: ["'dlig' on", "\"dlig\""]
featureSettings: ["'dlig' on", "\"dlig\""],
display: ["Block", "block"]
};
// Invalid values for the FontFace descriptor attributes other than family.
@ -52,7 +55,8 @@ var invalidValues = {
stretch: "wider",
unicodeRange: "U+1????-2????",
variant: "inherit",
featureSettings: "dlig"
featureSettings: "dlig",
display: "normal"
};
// Invalid font family names.
@ -159,8 +163,6 @@ function awaitRefresh() {
}
function runTest() {
SimpleTest.waitForExplicitFinish();
// Document and window from inside the display:none iframe.
var nframe = document.getElementById("n");
var ndocument = nframe.contentDocument;
@ -1859,11 +1861,16 @@ function runTest() {
function start() {
if (SpecialPowers.getBoolPref("layout.css.font-loading-api.enabled")) {
runTest();
SpecialPowers.pushPrefEnv({ set: [["layout.css.font-display.enabled", true]] },
runTest);
} else {
ok(true, "CSS Font Loading API is not enabled.");
}
}
SimpleTest.waitForExplicitFinish();
SimpleTest.requestLongerTimeout(5);
</script>
<style></style>

View File

@ -630,6 +630,7 @@ pref("gfx.color_management.enablev4", false);
pref("gfx.downloadable_fonts.enabled", true);
pref("gfx.downloadable_fonts.fallback_delay", 3000);
pref("gfx.downloadable_fonts.fallback_delay_short", 100);
// disable downloadable font cache so that behavior is consistently
// the uncached load behavior across pages (useful for testing reflow problems)