зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 7 changesets (bug 1784058, bug 650372) for causing wpt failures on format-specifiers-variations.html. CLOSED TREE
Backed out changeset 2aa97ebc8593 (bug 650372) Backed out changeset 41d1c62f11ac (bug 650372) Backed out changeset 8340c08ff8b6 (bug 650372) Backed out changeset cbe59d9bbcbb (bug 1784058) Backed out changeset 40b00a214019 (bug 1784058) Backed out changeset 714d84a2680a (bug 1784058) Backed out changeset e5b24489d365 (bug 1784058)
This commit is contained in:
Родитель
8bd35b4844
Коммит
6794af9029
|
@ -1799,30 +1799,23 @@ bool gfxPlatform::UseGraphiteShaping() {
|
|||
return StaticPrefs::gfx_font_rendering_graphite_enabled();
|
||||
}
|
||||
|
||||
bool gfxPlatform::IsFontFormatSupported(
|
||||
StyleFontFaceSourceFormatKeyword aHint) {
|
||||
switch (aHint) {
|
||||
case StyleFontFaceSourceFormatKeyword::None:
|
||||
return true;
|
||||
case StyleFontFaceSourceFormatKeyword::Collection:
|
||||
return false;
|
||||
case StyleFontFaceSourceFormatKeyword::Opentype:
|
||||
case StyleFontFaceSourceFormatKeyword::Truetype:
|
||||
return true;
|
||||
case StyleFontFaceSourceFormatKeyword::EmbeddedOpentype:
|
||||
return false;
|
||||
case StyleFontFaceSourceFormatKeyword::Svg:
|
||||
return false;
|
||||
case StyleFontFaceSourceFormatKeyword::Woff:
|
||||
return true;
|
||||
case StyleFontFaceSourceFormatKeyword::Woff2:
|
||||
return true;
|
||||
case StyleFontFaceSourceFormatKeyword::Unknown:
|
||||
return false;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("bad format hint!");
|
||||
return false;
|
||||
bool gfxPlatform::IsFontFormatSupported(uint32_t aFormatFlags) {
|
||||
// check for strange format flags
|
||||
MOZ_ASSERT(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
|
||||
"strange font format hint set");
|
||||
|
||||
// accept "common" formats that we support on all platforms
|
||||
if (aFormatFlags & gfxUserFontSet::FLAG_FORMATS_COMMON) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// reject all other formats, known and unknown
|
||||
if (aFormatFlags != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// no format hint set, need to look at data
|
||||
return true;
|
||||
}
|
||||
|
||||
gfxFontGroup* gfxPlatform::CreateFontGroup(
|
||||
|
|
|
@ -497,8 +497,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
// Check whether format is supported on a platform (if unclear, returns true).
|
||||
// Default implementation checks for "common" formats that we support across
|
||||
// all platforms, but individual platform implementations may override.
|
||||
virtual bool IsFontFormatSupported(
|
||||
mozilla::StyleFontFaceSourceFormatKeyword aFormatHint);
|
||||
virtual bool IsFontFormatSupported(uint32_t aFormatFlags);
|
||||
|
||||
virtual bool DidRenderingDeviceReset(
|
||||
DeviceResetReason* aResetReason = nullptr) {
|
||||
|
|
|
@ -179,6 +179,20 @@ already_AddRefed<gfxASurface> gfxPlatformMac::CreateOffscreenSurface(
|
|||
return newSurface.forget();
|
||||
}
|
||||
|
||||
bool gfxPlatformMac::IsFontFormatSupported(uint32_t aFormatFlags) {
|
||||
if (gfxPlatform::IsFontFormatSupported(aFormatFlags)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the generic method rejected the format hint, then check for any
|
||||
// platform-specific format we know about.
|
||||
if (aFormatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void gfxPlatformMac::GetCommonFallbackFonts(uint32_t aCh, Script aRunScript,
|
||||
eFontPresentation aPresentation,
|
||||
nsTArray<const char*>& aFontList) {
|
||||
|
|
|
@ -44,6 +44,8 @@ class gfxPlatformMac : public gfxPlatform {
|
|||
|
||||
void ReadSystemFontList(mozilla::dom::SystemFontList* aFontList) override;
|
||||
|
||||
bool IsFontFormatSupported(uint32_t aFormatFlags) override;
|
||||
|
||||
void GetCommonFallbackFonts(uint32_t aCh, Script aRunScript,
|
||||
eFontPresentation aPresentation,
|
||||
nsTArray<const char*>& aFontList) override;
|
||||
|
|
|
@ -231,7 +231,7 @@ void gfxUserFontEntry::StoreUserFontData(gfxFontEntry* aFontEntry,
|
|||
break;
|
||||
}
|
||||
userFontData->mPrivate = aPrivate;
|
||||
userFontData->mFormatHint = src.mFormatHint;
|
||||
userFontData->mFormat = src.mFormatFlags;
|
||||
userFontData->mRealName = aOriginalName;
|
||||
if (aMetadata) {
|
||||
userFontData->mMetadata = std::move(*aMetadata);
|
||||
|
@ -469,7 +469,7 @@ void gfxUserFontEntry::DoLoadNextSrc(bool aForceAsync) {
|
|||
// src url ==> start the load process
|
||||
else if (currSrc.mSourceType == gfxFontFaceSrc::eSourceType_URL) {
|
||||
if (gfxPlatform::GetPlatform()->IsFontFormatSupported(
|
||||
currSrc.mFormatHint)) {
|
||||
currSrc.mFormatFlags)) {
|
||||
if (ServoStyleSet* set = gfxFontUtils::CurrentServoStyleSet()) {
|
||||
// Only support style worker threads synchronously getting
|
||||
// entries from the font cache when it's not a data: URI
|
||||
|
|
|
@ -77,8 +77,10 @@ struct gfxFontFaceSrc {
|
|||
// if url, whether to use the origin principal or not
|
||||
bool mUseOriginPrincipal = false;
|
||||
|
||||
// Format hint, if any was specified.
|
||||
mozilla::StyleFontFaceSourceFormatKeyword mFormatHint;
|
||||
// format hint flags, union of all possible formats
|
||||
// (e.g. TrueType, EOT, SVG, etc.)
|
||||
// see FLAG_FORMAT_* enum values below
|
||||
uint32_t mFormatFlags;
|
||||
|
||||
nsCString mLocalName; // full font name if local
|
||||
RefPtr<gfxFontSrcURI> mURI; // uri if url
|
||||
|
@ -113,7 +115,7 @@ inline bool operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b) {
|
|||
return false;
|
||||
}
|
||||
bool equals;
|
||||
return a.mFormatHint == b.mFormatHint &&
|
||||
return a.mFormatFlags == b.mFormatFlags &&
|
||||
(a.mURI == b.mURI || a.mURI->Equals(b.mURI)) &&
|
||||
NS_SUCCEEDED(a.mReferrerInfo->Equals(b.mReferrerInfo, &equals)) &&
|
||||
equals;
|
||||
|
@ -135,8 +137,8 @@ class gfxUserFontData {
|
|||
public:
|
||||
gfxUserFontData()
|
||||
: mSrcIndex(0),
|
||||
mFormat(0),
|
||||
mMetaOrigLen(0),
|
||||
mFormatHint(mozilla::StyleFontFaceSourceFormatKeyword::None),
|
||||
mCompression(kUnknownCompression),
|
||||
mPrivate(false),
|
||||
mIsBuffer(false) {}
|
||||
|
@ -151,12 +153,11 @@ class gfxUserFontData {
|
|||
nsCString mLocalName; // font name used for the source, if local()
|
||||
nsCString mRealName; // original fullname from the font resource
|
||||
uint32_t mSrcIndex; // index in the rule's source list
|
||||
uint32_t mFormat; // format hint for the source used, if any
|
||||
uint32_t mMetaOrigLen; // length needed to decompress metadata
|
||||
mozilla::StyleFontFaceSourceFormatKeyword
|
||||
mFormatHint; // format hint for the source used, if any
|
||||
uint8_t mCompression; // compression type
|
||||
bool mPrivate; // whether font belongs to a private window
|
||||
bool mIsBuffer; // whether the font source was a buffer
|
||||
uint8_t mCompression; // compression type
|
||||
bool mPrivate; // whether font belongs to a private window
|
||||
bool mIsBuffer; // whether the font source was a buffer
|
||||
|
||||
enum {
|
||||
kUnknownCompression = 0,
|
||||
|
@ -238,6 +239,34 @@ class gfxUserFontSet {
|
|||
|
||||
void Destroy();
|
||||
|
||||
enum {
|
||||
// no flags ==> no hint set
|
||||
// unknown ==> unknown format hint set
|
||||
FLAG_FORMAT_UNKNOWN = 1,
|
||||
FLAG_FORMAT_OPENTYPE = 1 << 1,
|
||||
FLAG_FORMAT_TRUETYPE = 1 << 2,
|
||||
FLAG_FORMAT_TRUETYPE_AAT = 1 << 3,
|
||||
FLAG_FORMAT_EOT = 1 << 4,
|
||||
FLAG_FORMAT_SVG = 1 << 5,
|
||||
FLAG_FORMAT_WOFF = 1 << 6,
|
||||
FLAG_FORMAT_WOFF2 = 1 << 7,
|
||||
|
||||
FLAG_FORMAT_OPENTYPE_VARIATIONS = 1 << 8,
|
||||
FLAG_FORMAT_TRUETYPE_VARIATIONS = 1 << 9,
|
||||
FLAG_FORMAT_WOFF_VARIATIONS = 1 << 10,
|
||||
FLAG_FORMAT_WOFF2_VARIATIONS = 1 << 11,
|
||||
|
||||
// the common formats that we support everywhere
|
||||
FLAG_FORMATS_COMMON =
|
||||
FLAG_FORMAT_OPENTYPE | FLAG_FORMAT_TRUETYPE | FLAG_FORMAT_WOFF |
|
||||
FLAG_FORMAT_WOFF2 | FLAG_FORMAT_OPENTYPE_VARIATIONS |
|
||||
FLAG_FORMAT_TRUETYPE_VARIATIONS | FLAG_FORMAT_WOFF_VARIATIONS |
|
||||
FLAG_FORMAT_WOFF2_VARIATIONS,
|
||||
|
||||
// mask of all unused bits, update when adding new formats
|
||||
FLAG_FORMAT_NOT_USED = ~((1 << 12) - 1)
|
||||
};
|
||||
|
||||
// creates a font face without adding it to a particular family
|
||||
// weight - [100, 900] (multiples of 100)
|
||||
// stretch = [FontStretch::UltraCondensed(), FontStretch::UltraExpanded()]
|
||||
|
|
|
@ -120,37 +120,50 @@ void InspectorFontFace::GetLocalName(nsAString& aLocalName) {
|
|||
}
|
||||
}
|
||||
|
||||
static void AppendToFormat(nsAString& aResult, const char* aFormat) {
|
||||
if (!aResult.IsEmpty()) {
|
||||
aResult.Append(',');
|
||||
}
|
||||
aResult.AppendASCII(aFormat);
|
||||
}
|
||||
|
||||
void InspectorFontFace::GetFormat(nsAString& aFormat) {
|
||||
aFormat.Truncate();
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
|
||||
switch (mFontEntry->mUserFontData->mFormatHint) {
|
||||
case StyleFontFaceSourceFormatKeyword::None:
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Collection:
|
||||
aFormat.AssignLiteral("collection");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Opentype:
|
||||
aFormat.AssignLiteral("opentype");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Truetype:
|
||||
aFormat.AssignLiteral("truetype");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::EmbeddedOpentype:
|
||||
aFormat.AssignLiteral("embedded-opentype");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Svg:
|
||||
aFormat.AssignLiteral("svg");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Woff:
|
||||
aFormat.AssignLiteral("woff");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Woff2:
|
||||
aFormat.AssignLiteral("woff2");
|
||||
break;
|
||||
case StyleFontFaceSourceFormatKeyword::Unknown:
|
||||
aFormat.AssignLiteral("unknown!");
|
||||
break;
|
||||
uint32_t formatFlags = mFontEntry->mUserFontData->mFormat;
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE) {
|
||||
AppendToFormat(aFormat, "opentype");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE) {
|
||||
AppendToFormat(aFormat, "truetype");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) {
|
||||
AppendToFormat(aFormat, "truetype-aat");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_EOT) {
|
||||
AppendToFormat(aFormat, "embedded-opentype");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_SVG) {
|
||||
AppendToFormat(aFormat, "svg");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF) {
|
||||
AppendToFormat(aFormat, "woff");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2) {
|
||||
AppendToFormat(aFormat, "woff2");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE_VARIATIONS) {
|
||||
AppendToFormat(aFormat, "opentype-variations");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_VARIATIONS) {
|
||||
AppendToFormat(aFormat, "truetype-variations");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF_VARIATIONS) {
|
||||
AppendToFormat(aFormat, "woff-variations");
|
||||
}
|
||||
if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2_VARIATIONS) {
|
||||
AppendToFormat(aFormat, "woff2-variations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,13 @@ fails == name-override-1.html name-override-1-ref.html
|
|||
random-if(winWidget||gtkWidget) == src-list-2-big-otf.html src-list-2-big-ref.html # bug 470713
|
||||
== src-list-format-1.html src-list-format-1-ref.html
|
||||
== src-list-format-2.html src-list-format-2-ref.html
|
||||
== src-list-format-3.html src-list-format-3-ref.html
|
||||
== src-list-format-4.html src-list-format-1-ref.html
|
||||
== src-list-format-5.html src-list-format-2-ref.html
|
||||
== src-list-format-7.html src-list-format-3-ref.html
|
||||
== src-list-format-6.html src-list-format-3-ref.html
|
||||
# assumes AAT fonts are only supported on MacOS
|
||||
random-if(cocoaWidget) == src-list-format-7.html src-list-format-2-ref.html
|
||||
random-if(!cocoaWidget) == src-list-format-7.html src-list-format-3-ref.html
|
||||
fails-if(Android) == src-list-local-full.html src-list-local-full-ref.html
|
||||
fails-if(Android) == src-list-local-full-quotes.html src-list-local-full-ref.html
|
||||
== src-list-local-fallback.html src-list-local-fallback-ref.html
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
font-family: "One";
|
||||
src: url(../fonts/markA.ttf) format("unknown", "truetype"), url(../fonts/mark2A.ttf) format("truetype");
|
||||
}
|
||||
|
||||
body { font-family: "One"; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>ABC</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<style type="text/css">
|
||||
|
||||
@font-face {
|
||||
font-family: "One";
|
||||
/* assumes we don't support embedded-opentype and thus wouldn't try to load it */
|
||||
src: url(../fonts/markA.ttf) format("embedded-opentype", "truetype"), url(../fonts/mark2A.ttf) format("truetype");
|
||||
}
|
||||
|
||||
body { font-family: "One"; }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>ABC</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -503,10 +503,9 @@ FontFaceSetImpl::FindOrCreateUserFontEntryFromFontFace(
|
|||
face->mLocalName.Append(nsAtomCString(atom));
|
||||
face->mSourceType = gfxFontFaceSrc::eSourceType_Local;
|
||||
face->mURI = nullptr;
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::None;
|
||||
face->mFormatFlags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case StyleFontFaceSourceListComponent::Tag::Url: {
|
||||
face->mSourceType = gfxFontFaceSrc::eSourceType_URL;
|
||||
const StyleCssUrl* url = component.AsUrl();
|
||||
|
@ -527,72 +526,58 @@ FontFaceSetImpl::FindOrCreateUserFontEntryFromFontFace(
|
|||
}
|
||||
|
||||
face->mLocalName.Truncate();
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::None;
|
||||
face->mFormatFlags = 0;
|
||||
|
||||
if (i + 1 < len) {
|
||||
// Check for a format hint.
|
||||
const auto& next = sourceListComponents[i + 1];
|
||||
switch (next.tag) {
|
||||
case StyleFontFaceSourceListComponent::Tag::FormatHintKeyword:
|
||||
face->mFormatHint = next.format_hint_keyword._0;
|
||||
i++;
|
||||
break;
|
||||
case StyleFontFaceSourceListComponent::Tag::FormatHintString: {
|
||||
nsDependentCSubstring valueString(
|
||||
reinterpret_cast<const char*>(
|
||||
next.format_hint_string.utf8_bytes),
|
||||
next.format_hint_string.length);
|
||||
|
||||
if (valueString.LowerCaseEqualsASCII("woff")) {
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::Woff;
|
||||
} else if (valueString.LowerCaseEqualsASCII("woff2")) {
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::Woff2;
|
||||
} else if (valueString.LowerCaseEqualsASCII("opentype")) {
|
||||
face->mFormatHint =
|
||||
StyleFontFaceSourceFormatKeyword::Opentype;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
|
||||
face->mFormatHint =
|
||||
StyleFontFaceSourceFormatKeyword::Truetype;
|
||||
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
|
||||
face->mFormatHint =
|
||||
StyleFontFaceSourceFormatKeyword::Truetype;
|
||||
} else if (valueString.LowerCaseEqualsASCII(
|
||||
"embedded-opentype")) {
|
||||
face->mFormatHint =
|
||||
StyleFontFaceSourceFormatKeyword::EmbeddedOpentype;
|
||||
} else if (valueString.LowerCaseEqualsASCII("svg")) {
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::Svg;
|
||||
} else if (StaticPrefs::layout_css_font_variations_enabled()) {
|
||||
// Non-standard values that Firefox accepted, for back-compat;
|
||||
// these are superseded by the tech() function.
|
||||
if (valueString.LowerCaseEqualsASCII("woff-variations")) {
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::Woff;
|
||||
} else if (valueString.LowerCaseEqualsASCII(
|
||||
"woff2-variations")) {
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::Woff2;
|
||||
} else if (valueString.LowerCaseEqualsASCII(
|
||||
"opentype-variations")) {
|
||||
face->mFormatHint =
|
||||
StyleFontFaceSourceFormatKeyword::Opentype;
|
||||
} else if (valueString.LowerCaseEqualsASCII(
|
||||
"truetype-variations")) {
|
||||
face->mFormatHint =
|
||||
StyleFontFaceSourceFormatKeyword::Truetype;
|
||||
}
|
||||
} else {
|
||||
// unknown format specified, mark to distinguish from the
|
||||
// case where no format hints are specified
|
||||
face->mFormatHint = StyleFontFaceSourceFormatKeyword::Unknown;
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
case StyleFontFaceSourceListComponent::Tag::Local:
|
||||
case StyleFontFaceSourceListComponent::Tag::Url:
|
||||
break;
|
||||
while (i + 1 < len) {
|
||||
const auto& maybeFontFormat = sourceListComponents[i + 1];
|
||||
if (maybeFontFormat.tag !=
|
||||
StyleFontFaceSourceListComponent::Tag::FormatHint) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsDependentCSubstring valueString(
|
||||
reinterpret_cast<const char*>(
|
||||
maybeFontFormat.format_hint.utf8_bytes),
|
||||
maybeFontFormat.format_hint.length);
|
||||
|
||||
if (valueString.LowerCaseEqualsASCII("woff")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF;
|
||||
} else if (valueString.LowerCaseEqualsASCII("woff2")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF2;
|
||||
} else 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;
|
||||
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
||||
valueString.LowerCaseEqualsASCII("woff-variations")) {
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF_VARIATIONS;
|
||||
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
||||
valueString.LowerCaseEqualsASCII("woff2-variations")) {
|
||||
face->mFormatFlags |=
|
||||
gfxUserFontSet::FLAG_FORMAT_WOFF2_VARIATIONS;
|
||||
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
||||
valueString.LowerCaseEqualsASCII(
|
||||
"opentype-variations")) {
|
||||
face->mFormatFlags |=
|
||||
gfxUserFontSet::FLAG_FORMAT_OPENTYPE_VARIATIONS;
|
||||
} else if (StaticPrefs::layout_css_font_variations_enabled() &&
|
||||
valueString.LowerCaseEqualsASCII(
|
||||
"truetype-variations")) {
|
||||
face->mFormatFlags |=
|
||||
gfxUserFontSet::FLAG_FORMAT_TRUETYPE_VARIATIONS;
|
||||
} else {
|
||||
// unknown format specified, mark to distinguish from the
|
||||
// case where no format hints are specified
|
||||
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_UNKNOWN;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!face->mURI) {
|
||||
// if URI not valid, omit from src array
|
||||
srcArray.RemoveLastElement();
|
||||
|
@ -601,9 +586,7 @@ FontFaceSetImpl::FindOrCreateUserFontEntryFromFontFace(
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case StyleFontFaceSourceListComponent::Tag::FormatHintKeyword:
|
||||
case StyleFontFaceSourceListComponent::Tag::FormatHintString:
|
||||
case StyleFontFaceSourceListComponent::Tag::FormatHint:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Should always come after a URL source, and be consumed already");
|
||||
break;
|
||||
|
|
|
@ -78,9 +78,8 @@ void FontPreloader::PrioritizeAsPreload(nsIChannel* aChannel) {
|
|||
|
||||
// For WOFF and WOFF2, we should tell servers/proxies/etc NOT to try
|
||||
// and apply additional compression at the content-encoding layer
|
||||
if (aFontFaceSrc->mFormatHint == StyleFontFaceSourceFormatKeyword::Woff ||
|
||||
aFontFaceSrc->mFormatHint ==
|
||||
StyleFontFaceSourceFormatKeyword::Woff2) {
|
||||
if (aFontFaceSrc->mFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF |
|
||||
gfxUserFontSet::FLAG_FORMAT_WOFF2)) {
|
||||
rv = aHttpChannel->SetRequestHeader("Accept-Encoding"_ns, "identity"_ns,
|
||||
false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -91,13 +91,16 @@ var gCSSFontFaceDescriptors = {
|
|||
'url("404.eot")',
|
||||
"url('404.otf')",
|
||||
'url(404.ttf) format("truetype")',
|
||||
'url(404.ttf) format("truetype", "opentype")',
|
||||
'url(404.ttf) format("truetype", "opentype"), url(\'404.eot\')',
|
||||
"local(Times New Roman)",
|
||||
"local('Times New Roman')",
|
||||
'local("Times New Roman")',
|
||||
'local("serif")',
|
||||
"url(404.ttf) format(truetype)",
|
||||
'url(404.ttf) format("truetype", "unknown"), local(Times New Roman), url(\'404.eot\')',
|
||||
],
|
||||
invalid_values: [
|
||||
"url(404.ttf) format(truetype)",
|
||||
'url(404.ttf) format("truetype" "opentype")',
|
||||
'url(404.ttf) format("truetype",)',
|
||||
'local("Times New" Roman)',
|
||||
|
@ -106,9 +109,6 @@ var gCSSFontFaceDescriptors = {
|
|||
"url(404.ttf) ) foo",
|
||||
"url(404.ttf) ! important",
|
||||
"url(404.ttf) ! hello",
|
||||
'url(404.ttf) format("truetype", "opentype")',
|
||||
'url(404.ttf) format("truetype", "opentype"), url(\'404.eot\')',
|
||||
'url(404.ttf) format("truetype", "unknown"), local(Times New Roman), url(\'404.eot\')',
|
||||
],
|
||||
},
|
||||
"unicode-range": {
|
||||
|
|
|
@ -103,6 +103,8 @@ function runTest() {
|
|||
|
||||
{ rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\");"),
|
||||
d: { "src" : "url(\"/fonts/Mouse\") format(\"truetype\")" } },
|
||||
{ rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\", \"opentype\");"),
|
||||
d: { "src" : "url(\"/fonts/Mouse\") format(\"truetype\", \"opentype\")" } },
|
||||
|
||||
{ rule: _("src: url(\"/fonts/Mouse\"), url(\"/fonts/Rat\");"),
|
||||
d: { "src" : "url(\"/fonts/Mouse\"), url(\"/fonts/Rat\")" } },
|
||||
|
@ -117,9 +119,6 @@ function runTest() {
|
|||
{ rule: _("src: local(\"老鼠\"), url(\"/fonts/Mouse\") format(\"truetype\");"),
|
||||
d: { "src" : "local(\"老鼠\"), url(\"/fonts/Mouse\") format(\"truetype\")" } },
|
||||
|
||||
{ rule: _("src: url(\"/fonts/Mouse\") format(truetype);"),
|
||||
d: { "src" : "url(\"/fonts/Mouse\") format(truetype)" } },
|
||||
|
||||
// Correct but unusual src:
|
||||
{ rule: _("src: local(Hoefler Text);"),
|
||||
d: {"src" : "local(Hoefler Text)"}, noncanonical: true },
|
||||
|
@ -128,13 +127,13 @@ function runTest() {
|
|||
{ rule: _("src:"), d: {} },
|
||||
{ rule: _("src: \"/fonts/Mouse\";"), d: {} },
|
||||
{ rule: _("src: /fonts/Mouse;"), d: {} },
|
||||
{ rule: _("src: url(\"/fonts/Mouse\") format(truetype);"), d: {} },
|
||||
{ rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\",opentype);"), d: {} },
|
||||
{ rule: _("src: local(*);"), d: {} },
|
||||
{ rule: _("src: format(\"truetype\");"), d: {} },
|
||||
{ rule: _("src: local(Mouse) format(\"truetype\");"), d: {} },
|
||||
{ rule: _("src: local(Mouse, Rat);"), d: {} },
|
||||
{ rule: _("src: local(sans-serif);"), d: {} },
|
||||
{ rule: _("src: url(\"/fonts/Mouse\") format(\"truetype\", \"opentype\");"), d: {} },
|
||||
|
||||
// Repeated descriptors
|
||||
{ rule: _("font-weight: 700; font-weight: 200;"),
|
||||
|
|
|
@ -28,6 +28,7 @@ use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
|||
use cssparser::{CowRcStr, SourceLocation};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::values::SequenceWriter;
|
||||
use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
|
||||
use style_traits::{StyleParseErrorKind, ToCss};
|
||||
|
||||
|
@ -46,51 +47,22 @@ impl OneOrMoreSeparated for Source {
|
|||
type S = Comma;
|
||||
}
|
||||
|
||||
/// Keywords for the font-face src descriptor's format() function.
|
||||
/// ('None' and 'Unknown' are for internal use in gfx, not exposed to CSS.)
|
||||
#[derive(Clone, Copy, Debug, Eq, Parse, PartialEq, ToCss, ToShmem)]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum FontFaceSourceFormatKeyword {
|
||||
#[css(skip)]
|
||||
None,
|
||||
Collection,
|
||||
EmbeddedOpentype,
|
||||
Opentype,
|
||||
Svg,
|
||||
Truetype,
|
||||
Woff,
|
||||
Woff2,
|
||||
#[css(skip)]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// A POD representation for Gecko. All pointers here are non-owned and as such
|
||||
/// can't outlive the rule they came from, but we can't enforce that via C++.
|
||||
///
|
||||
/// All the strings are of course utf8.
|
||||
#[cfg(feature = "gecko")]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum FontFaceSourceListComponent {
|
||||
Url(*const crate::gecko::url::CssUrl),
|
||||
Local(*mut crate::gecko_bindings::structs::nsAtom),
|
||||
FormatHintKeyword(FontFaceSourceFormatKeyword),
|
||||
FormatHintString {
|
||||
FormatHint {
|
||||
length: usize,
|
||||
utf8_bytes: *const u8,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum FontFaceSourceFormat {
|
||||
Keyword(FontFaceSourceFormatKeyword),
|
||||
String(String),
|
||||
}
|
||||
|
||||
/// A `UrlSource` represents a font-face source that has been specified with a
|
||||
/// `url()` function.
|
||||
///
|
||||
|
@ -100,8 +72,8 @@ pub enum FontFaceSourceFormat {
|
|||
pub struct UrlSource {
|
||||
/// The specified url.
|
||||
pub url: SpecifiedUrl,
|
||||
/// The format hint specified with the `format()` function, if present.
|
||||
pub format_hint: Option<FontFaceSourceFormat>,
|
||||
/// The format hints specified with the `format()` function.
|
||||
pub format_hints: Vec<String>,
|
||||
}
|
||||
|
||||
impl ToCss for UrlSource {
|
||||
|
@ -110,9 +82,14 @@ impl ToCss for UrlSource {
|
|||
W: fmt::Write,
|
||||
{
|
||||
self.url.to_css(dest)?;
|
||||
if let Some(hint) = &self.format_hint {
|
||||
if !self.format_hints.is_empty() {
|
||||
dest.write_str(" format(")?;
|
||||
hint.to_css(dest)?;
|
||||
{
|
||||
let mut writer = SequenceWriter::new(dest, ", ");
|
||||
for hint in self.format_hints.iter() {
|
||||
writer.item(hint)?;
|
||||
}
|
||||
}
|
||||
dest.write_char(')')?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -357,11 +334,14 @@ impl<'a> FontFace<'a> {
|
|||
.rev()
|
||||
.filter(|source| {
|
||||
if let Source::Url(ref url_source) = **source {
|
||||
let hints = &url_source.format_hints;
|
||||
// We support only opentype fonts and truetype is an alias for
|
||||
// that format. Sources without format hints need to be
|
||||
// downloaded in case we support them.
|
||||
url_source.format_hint.as_ref().map_or(true,
|
||||
|hint| hint == "truetype" || hint == "opentype" || hint == "woff")
|
||||
hints.is_empty() ||
|
||||
hints.iter().any(|hint| {
|
||||
hint == "truetype" || hint == "opentype" || hint == "woff"
|
||||
})
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -413,25 +393,20 @@ impl Parse for Source {
|
|||
let url = SpecifiedUrl::parse(context, input)?;
|
||||
|
||||
// Parsing optional format()
|
||||
let format_hint = if input
|
||||
let format_hints = if input
|
||||
.try_parse(|input| input.expect_function_matching("format"))
|
||||
.is_ok()
|
||||
{
|
||||
input.parse_nested_block(|input| {
|
||||
if let Ok(kw) = input.try_parse(FontFaceSourceFormatKeyword::parse) {
|
||||
Ok(Some(FontFaceSourceFormat::Keyword(kw)))
|
||||
} else {
|
||||
let s = input.expect_string()?.as_ref().to_owned();
|
||||
Ok(Some(FontFaceSourceFormat::String(s)))
|
||||
}
|
||||
input.parse_comma_separated(|input| Ok(input.expect_string()?.as_ref().to_owned()))
|
||||
})?
|
||||
} else {
|
||||
None
|
||||
vec![]
|
||||
};
|
||||
|
||||
Ok(Source::Url(UrlSource {
|
||||
url: url,
|
||||
format_hint: format_hint,
|
||||
format_hints: format_hints,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ use style::data::{self, ElementStyles};
|
|||
use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
|
||||
use style::driver;
|
||||
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use style::font_face::{self, FontFaceSourceListComponent, FontFaceSourceFormat, Source};
|
||||
use style::font_face::{self, FontFaceSourceListComponent, Source};
|
||||
use style::font_metrics::{get_metrics_provider_for_product, FontMetricsProvider};
|
||||
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||
|
@ -3253,7 +3253,8 @@ pub unsafe extern "C" fn Servo_FontFaceRule_GetSources(
|
|||
};
|
||||
let len = sources.iter().fold(0, |acc, src| {
|
||||
acc + match *src {
|
||||
Source::Url(ref url) => if url.format_hint.is_some() { 2 } else { 1 },
|
||||
// Each format hint takes one position in the array of mSrc.
|
||||
Source::Url(ref url) => url.format_hints.len() + 1,
|
||||
Source::Local(_) => 1,
|
||||
}
|
||||
});
|
||||
|
@ -3271,16 +3272,11 @@ pub unsafe extern "C" fn Servo_FontFaceRule_GetSources(
|
|||
match *source {
|
||||
Source::Url(ref url) => {
|
||||
set_next(FontFaceSourceListComponent::Url(&url.url));
|
||||
if let Some(hint) = &url.format_hint {
|
||||
match hint {
|
||||
FontFaceSourceFormat::Keyword(kw) =>
|
||||
set_next(FontFaceSourceListComponent::FormatHintKeyword(*kw)),
|
||||
FontFaceSourceFormat::String(s) =>
|
||||
set_next(FontFaceSourceListComponent::FormatHintString {
|
||||
length: s.len(),
|
||||
utf8_bytes: s.as_ptr(),
|
||||
}),
|
||||
}
|
||||
for hint in url.format_hints.iter() {
|
||||
set_next(FontFaceSourceListComponent::FormatHint {
|
||||
length: hint.len(),
|
||||
utf8_bytes: hint.as_ptr(),
|
||||
});
|
||||
}
|
||||
},
|
||||
Source::Local(ref name) => {
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Fonts 4 test: parsing the format() function in the src descriptor</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-fonts/#font-face-src-parsing">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style id="testStyle">
|
||||
</style>
|
||||
<script>
|
||||
const sheet = testStyle.sheet;
|
||||
tests = [
|
||||
// No format() function
|
||||
{ src: 'url("foo.ttf")', valid: true },
|
||||
// Empty format() is not valid
|
||||
{ src: 'url("foo.ttf") format()', valid: false },
|
||||
// Quoted strings in format()
|
||||
{ src: 'url("foo.ttf") format("collection")', valid: true },
|
||||
{ src: 'url("foo.ttf") format("embedded-opentype")', valid: true },
|
||||
{ src: 'url("foo.ttf") format("opentype")', valid: true },
|
||||
{ src: 'url("foo.ttf") format("svg")', valid: true },
|
||||
{ src: 'url("foo.ttf") format("truetype")', valid: true },
|
||||
{ src: 'url("foo.ttf") format("woff")', valid: true },
|
||||
{ src: 'url("foo.ttf") format("woff2")', valid: true },
|
||||
// Multiple strings (was valid in CSS Fonts 3, but not allowed in Fonts 4)
|
||||
{ src: 'url("foo.ttf") format("opentype", "truetype")', valid: false },
|
||||
// Unknown format string still matches the grammar, although it won't be loaded
|
||||
{ src: 'url("foo.ttf") format("xyzzy")', valid: true },
|
||||
// Keywords (new in Fonts 4)
|
||||
{ src: 'url("foo.ttf") format(collection)', valid: true },
|
||||
{ src: 'url("foo.ttf") format(embedded-opentype)', valid: true },
|
||||
{ src: 'url("foo.ttf") format(opentype)', valid: true },
|
||||
{ src: 'url("foo.ttf") format(svg)', valid: true },
|
||||
{ src: 'url("foo.ttf") format(truetype)', valid: true },
|
||||
{ src: 'url("foo.ttf") format(woff)', valid: true },
|
||||
{ src: 'url("foo.ttf") format(woff2)', valid: true },
|
||||
// Multiple keywords are not accepted
|
||||
{ src: 'url("foo.ttf") format(opentype, truetype)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(opentype truetype)', valid: false },
|
||||
// Invalid format keywords should be a parse error
|
||||
{ src: 'url("foo.ttf") format(auto)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(default)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(inherit)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(initial)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(none)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(normal)', valid: false },
|
||||
{ src: 'url("foo.ttf") format(xyzzy)', valid: false },
|
||||
];
|
||||
|
||||
for (let t of tests) {
|
||||
test(() => {
|
||||
assert_equals(sheet.cssRules.length, 0, "testSheet should initially be empty");
|
||||
sheet.insertRule("@font-face { src: " + t.src + "}");
|
||||
try {
|
||||
assert_equals(sheet.cssRules[0].style.getPropertyValue("src") != "", t.valid);
|
||||
} finally {
|
||||
sheet.deleteRule(0);
|
||||
}
|
||||
}, "Check that src: " + t.src + " is " + (t.valid ? "valid" : "invalid"));
|
||||
}
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче