1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/SVGTests.h"
8 #include "DOMSVGStringList.h"
9 #include "nsIContent.h"
10 #include "nsIContentInlines.h"
11 #include "mozilla/dom/SVGSwitchElement.h"
12 #include "nsCharSeparatedTokenizer.h"
13 #include "nsStyleUtil.h"
14 #include "mozilla/Preferences.h"
16 namespace mozilla::dom
{
18 nsStaticAtom
* const SVGTests::sStringListNames
[2] = {
19 nsGkAtoms::requiredExtensions
,
20 nsGkAtoms::systemLanguage
,
23 SVGTests::SVGTests() {
24 mStringListAttributes
[LANGUAGE
].SetIsCommaSeparated(true);
27 already_AddRefed
<DOMSVGStringList
> SVGTests::RequiredExtensions() {
28 return DOMSVGStringList::GetDOMWrapper(&mStringListAttributes
[EXTENSIONS
],
29 AsSVGElement(), true, EXTENSIONS
);
32 already_AddRefed
<DOMSVGStringList
> SVGTests::SystemLanguage() {
33 return DOMSVGStringList::GetDOMWrapper(&mStringListAttributes
[LANGUAGE
],
34 AsSVGElement(), true, LANGUAGE
);
37 bool SVGTests::HasExtension(const nsAString
& aExtension
) const {
38 #define SVG_SUPPORTED_EXTENSION(str) \
39 if (aExtension.EqualsLiteral(str)) return true;
40 SVG_SUPPORTED_EXTENSION("http://www.w3.org/1999/xhtml")
41 nsNameSpaceManager
* nameSpaceManager
= nsNameSpaceManager::GetInstance();
42 if (AsSVGElement()->IsInChromeDocument() ||
43 !nameSpaceManager
->mMathMLDisabled
) {
44 SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
46 #undef SVG_SUPPORTED_EXTENSION
51 bool SVGTests::IsConditionalProcessingAttribute(
52 const nsAtom
* aAttribute
) const {
53 for (uint32_t i
= 0; i
< ArrayLength(sStringListNames
); i
++) {
54 if (aAttribute
== sStringListNames
[i
]) {
61 int32_t SVGTests::GetBestLanguagePreferenceRank(
62 const nsAString
& aAcceptLangs
) const {
63 if (!mStringListAttributes
[LANGUAGE
].IsExplicitlySet()) {
67 int32_t lowestRank
= -1;
69 for (uint32_t i
= 0; i
< mStringListAttributes
[LANGUAGE
].Length(); i
++) {
71 for (const nsAString
& languageToken
:
72 nsCharSeparatedTokenizer(aAcceptLangs
, ',').ToRange()) {
73 bool exactMatch
= languageToken
.Equals(mStringListAttributes
[LANGUAGE
][i
],
74 nsCaseInsensitiveStringComparator
);
75 bool prefixOnlyMatch
=
76 !exactMatch
&& nsStyleUtil::DashMatchCompare(
77 mStringListAttributes
[LANGUAGE
][i
], languageToken
,
78 nsCaseInsensitiveStringComparator
);
79 if (index
== 0 && exactMatch
) {
80 // best possible match
83 if ((exactMatch
|| prefixOnlyMatch
) &&
84 (lowestRank
== -1 || 2 * index
+ prefixOnlyMatch
< lowestRank
)) {
85 lowestRank
= 2 * index
+ prefixOnlyMatch
;
93 bool SVGTests::PassesConditionalProcessingTestsIgnoringSystemLanguage() const {
94 // Required Extensions
96 // The requiredExtensions attribute defines a list of required language
97 // extensions. Language extensions are capabilities within a user agent that
98 // go beyond the feature set defined in the SVG specification.
99 // Each extension is identified by a URI reference.
100 // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
101 if (mStringListAttributes
[EXTENSIONS
].IsExplicitlySet()) {
102 if (mStringListAttributes
[EXTENSIONS
].IsEmpty()) {
105 for (uint32_t i
= 0; i
< mStringListAttributes
[EXTENSIONS
].Length(); i
++) {
106 if (!HasExtension(mStringListAttributes
[EXTENSIONS
][i
])) {
114 bool SVGTests::PassesConditionalProcessingTests() const {
115 if (!PassesConditionalProcessingTestsIgnoringSystemLanguage()) {
121 // Evaluates to "true" if one of the languages indicated by user preferences
122 // exactly equals one of the languages given in the value of this parameter,
123 // or if one of the languages indicated by user preferences exactly equals a
124 // prefix of one of the languages given in the value of this parameter such
125 // that the first tag character following the prefix is "-".
126 if (mStringListAttributes
[LANGUAGE
].IsExplicitlySet()) {
127 if (mStringListAttributes
[LANGUAGE
].IsEmpty()) {
131 // Get our language preferences
132 nsAutoString acceptLangs
;
133 Preferences::GetLocalizedString("intl.accept_languages", acceptLangs
);
135 if (acceptLangs
.IsEmpty()) {
137 "no default language specified for systemLanguage conditional test");
141 for (uint32_t i
= 0; i
< mStringListAttributes
[LANGUAGE
].Length(); i
++) {
142 nsCharSeparatedTokenizer
languageTokenizer(acceptLangs
, ',');
143 while (languageTokenizer
.hasMoreTokens()) {
144 if (nsStyleUtil::DashMatchCompare(mStringListAttributes
[LANGUAGE
][i
],
145 languageTokenizer
.nextToken(),
146 nsCaseInsensitiveStringComparator
)) {
157 bool SVGTests::ParseConditionalProcessingAttribute(nsAtom
* aAttribute
,
158 const nsAString
& aValue
,
159 nsAttrValue
& aResult
) {
160 for (uint32_t i
= 0; i
< ArrayLength(sStringListNames
); i
++) {
161 if (aAttribute
== sStringListNames
[i
]) {
162 nsresult rv
= mStringListAttributes
[i
].SetValue(aValue
);
164 mStringListAttributes
[i
].Clear();
173 void SVGTests::UnsetAttr(const nsAtom
* aAttribute
) {
174 for (uint32_t i
= 0; i
< ArrayLength(sStringListNames
); i
++) {
175 if (aAttribute
== sStringListNames
[i
]) {
176 mStringListAttributes
[i
].Clear();
183 nsStaticAtom
* SVGTests::GetAttrName(uint8_t aAttrEnum
) const {
184 return sStringListNames
[aAttrEnum
];
187 void SVGTests::GetAttrValue(uint8_t aAttrEnum
, nsAttrValue
& aValue
) const {
188 MOZ_ASSERT(aAttrEnum
< ArrayLength(sStringListNames
),
189 "aAttrEnum out of range");
190 aValue
.SetTo(mStringListAttributes
[aAttrEnum
], nullptr);
193 void SVGTests::MaybeInvalidate() {
194 nsIContent
* parent
= AsSVGElement()->GetFlattenedTreeParent();
196 if (auto* svgSwitch
= SVGSwitchElement::FromNodeOrNull(parent
)) {
197 svgSwitch
->MaybeInvalidate();
201 } // namespace mozilla::dom