diff options
Diffstat (limited to 'dom/svg/SVGTests.cpp')
-rw-r--r-- | dom/svg/SVGTests.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/dom/svg/SVGTests.cpp b/dom/svg/SVGTests.cpp new file mode 100644 index 000000000..963ac27e4 --- /dev/null +++ b/dom/svg/SVGTests.cpp @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/SVGTests.h" +#include "DOMSVGStringList.h" +#include "nsSVGFeatures.h" +#include "mozilla/dom/SVGSwitchElement.h" +#include "nsCharSeparatedTokenizer.h" +#include "nsStyleUtil.h" +#include "mozilla/Preferences.h" + +namespace mozilla { +namespace dom { + +nsIAtom** SVGTests::sStringListNames[3] = +{ + &nsGkAtoms::requiredFeatures, + &nsGkAtoms::requiredExtensions, + &nsGkAtoms::systemLanguage, +}; + +SVGTests::SVGTests() +{ + mStringListAttributes[LANGUAGE].SetIsCommaSeparated(true); +} + +already_AddRefed<DOMSVGStringList> +SVGTests::RequiredFeatures() +{ + nsCOMPtr<nsIDOMSVGElement> elem = do_QueryInterface(this); + nsSVGElement* element = static_cast<nsSVGElement*>(elem.get()); + return DOMSVGStringList::GetDOMWrapper( + &mStringListAttributes[FEATURES], element, true, FEATURES); +} + +already_AddRefed<DOMSVGStringList> +SVGTests::RequiredExtensions() +{ + nsCOMPtr<nsIDOMSVGElement> elem = do_QueryInterface(this); + nsSVGElement* element = static_cast<nsSVGElement*>(elem.get()); + return DOMSVGStringList::GetDOMWrapper( + &mStringListAttributes[EXTENSIONS], element, true, EXTENSIONS); +} + +already_AddRefed<DOMSVGStringList> +SVGTests::SystemLanguage() +{ + nsCOMPtr<nsIDOMSVGElement> elem = do_QueryInterface(this); + nsSVGElement* element = static_cast<nsSVGElement*>(elem.get()); + return DOMSVGStringList::GetDOMWrapper( + &mStringListAttributes[LANGUAGE], element, true, LANGUAGE); +} + +bool +SVGTests::HasExtension(const nsAString& aExtension) +{ + return nsSVGFeatures::HasExtension(aExtension, IsInChromeDoc()); +} + +bool +SVGTests::IsConditionalProcessingAttribute(const nsIAtom* aAttribute) const +{ + for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) { + if (aAttribute == *sStringListNames[i]) { + return true; + } + } + return false; +} + +int32_t +SVGTests::GetBestLanguagePreferenceRank(const nsSubstring& aAcceptLangs) const +{ + const nsDefaultStringComparator defaultComparator; + + if (!mStringListAttributes[LANGUAGE].IsExplicitlySet()) { + return -2; + } + + int32_t lowestRank = -1; + + for (uint32_t i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) { + nsCharSeparatedTokenizer languageTokenizer(aAcceptLangs, ','); + int32_t index = 0; + while (languageTokenizer.hasMoreTokens()) { + const nsSubstring &languageToken = languageTokenizer.nextToken(); + bool exactMatch = (languageToken == mStringListAttributes[LANGUAGE][i]); + bool prefixOnlyMatch = + !exactMatch && + nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i], + languageTokenizer.nextToken(), + defaultComparator); + if (index == 0 && exactMatch) { + // best possible match + return 0; + } + if ((exactMatch || prefixOnlyMatch) && + (lowestRank == -1 || 2 * index + prefixOnlyMatch < lowestRank)) { + lowestRank = 2 * index + prefixOnlyMatch; + } + ++index; + } + } + return lowestRank; +} + +const nsString * const SVGTests::kIgnoreSystemLanguage = (nsString *) 0x01; + +bool +SVGTests::PassesConditionalProcessingTests(const nsString *aAcceptLangs) const +{ + // Required Extensions + // + // The requiredExtensions attribute defines a list of required language + // extensions. Language extensions are capabilities within a user agent that + // go beyond the feature set defined in the SVG specification. + // Each extension is identified by a URI reference. + // For now, claim that mozilla's SVG implementation supports XHTML and MathML. + if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) { + if (mStringListAttributes[EXTENSIONS].IsEmpty()) { + return false; + } + for (uint32_t i = 0; i < mStringListAttributes[EXTENSIONS].Length(); i++) { + if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i], IsInChromeDoc())) { + return false; + } + } + } + + if (aAcceptLangs == kIgnoreSystemLanguage) { + return true; + } + + // systemLanguage + // + // Evaluates to "true" if one of the languages indicated by user preferences + // exactly equals one of the languages given in the value of this parameter, + // or if one of the languages indicated by user preferences exactly equals a + // prefix of one of the languages given in the value of this parameter such + // that the first tag character following the prefix is "-". + if (mStringListAttributes[LANGUAGE].IsExplicitlySet()) { + if (mStringListAttributes[LANGUAGE].IsEmpty()) { + return false; + } + + // Get our language preferences + const nsAutoString acceptLangs(aAcceptLangs ? *aAcceptLangs : + Preferences::GetLocalizedString("intl.accept_languages")); + + if (acceptLangs.IsEmpty()) { + NS_WARNING("no default language specified for systemLanguage conditional test"); + return false; + } + + const nsDefaultStringComparator defaultComparator; + + for (uint32_t i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) { + nsCharSeparatedTokenizer languageTokenizer(acceptLangs, ','); + while (languageTokenizer.hasMoreTokens()) { + if (nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i], + languageTokenizer.nextToken(), + defaultComparator)) { + return true; + } + } + } + return false; + } + + return true; +} + +bool +SVGTests::ParseConditionalProcessingAttribute(nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) { + if (aAttribute == *sStringListNames[i]) { + nsresult rv = mStringListAttributes[i].SetValue(aValue); + if (NS_FAILED(rv)) { + mStringListAttributes[i].Clear(); + } + MaybeInvalidate(); + return true; + } + } + return false; +} + +void +SVGTests::UnsetAttr(const nsIAtom* aAttribute) +{ + for (uint32_t i = 0; i < ArrayLength(sStringListNames); i++) { + if (aAttribute == *sStringListNames[i]) { + mStringListAttributes[i].Clear(); + MaybeInvalidate(); + return; + } + } +} + +nsIAtom* +SVGTests::GetAttrName(uint8_t aAttrEnum) const +{ + return *sStringListNames[aAttrEnum]; +} + +void +SVGTests::GetAttrValue(uint8_t aAttrEnum, nsAttrValue& aValue) const +{ + MOZ_ASSERT(aAttrEnum < ArrayLength(sStringListNames), + "aAttrEnum out of range"); + aValue.SetTo(mStringListAttributes[aAttrEnum], nullptr); +} + +void +SVGTests::MaybeInvalidate() +{ + nsCOMPtr<nsIDOMSVGElement> elem = do_QueryInterface(this); + nsSVGElement* element = static_cast<nsSVGElement*>(elem.get()); + + nsIContent* parent = element->GetFlattenedTreeParent(); + + if (parent && + parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) { + static_cast<dom::SVGSwitchElement*>(parent)->MaybeInvalidate(); + } +} + +} // namespace dom +} // namespace mozilla |