Backed out 7 changesets (bug 650372, bug 1784058) for causing reftest failures on variation-format-hint-1a.html CLOSED TREE

Backed out changeset c78a59ace7ec (bug 650372)
Backed out changeset eea47293ce56 (bug 650372)
Backed out changeset e978496c7ea0 (bug 650372)
Backed out changeset 597837e9753f (bug 1784058)
Backed out changeset 6d71bcfcc1a1 (bug 1784058)
Backed out changeset 5d21f6e4f8e0 (bug 1784058)
Backed out changeset 35634f66cb37 (bug 1784058)
This commit is contained in:
Cristian Tuns 2022-08-11 10:28:40 -04:00
Родитель 22cace401e
Коммит f124fa4b1e
17 изменённых файлов: 253 добавлений и 257 удалений

Просмотреть файл

@ -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,70 +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;
} // Non-standard values that Firefox accepted, for
// back-compat:
else 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();
@ -599,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>