Bug 1691109 [wpt PR 27513] - Increase timeout duration for wpt/fetch/api/basic/keepal...
[gecko.git] / dom / svg / SVGSwitchElement.cpp
blobd7609bd1eeac494e938bcf4d3d96915aa8be5dff
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/SVGSwitchElement.h"
9 #include "nsLayoutUtils.h"
10 #include "mozilla/Preferences.h"
11 #include "mozilla/SVGUtils.h"
12 #include "mozilla/dom/SVGSwitchElementBinding.h"
14 class nsIFrame;
16 NS_IMPL_NS_NEW_SVG_ELEMENT(Switch)
18 namespace mozilla {
19 namespace dom {
21 JSObject* SVGSwitchElement::WrapNode(JSContext* aCx,
22 JS::Handle<JSObject*> aGivenProto) {
23 return SVGSwitchElement_Binding::Wrap(aCx, this, aGivenProto);
26 //----------------------------------------------------------------------
27 // nsISupports methods
29 NS_IMPL_CYCLE_COLLECTION_INHERITED(SVGSwitchElement, SVGSwitchElementBase,
30 mActiveChild)
32 NS_IMPL_ADDREF_INHERITED(SVGSwitchElement, SVGSwitchElementBase)
33 NS_IMPL_RELEASE_INHERITED(SVGSwitchElement, SVGSwitchElementBase)
35 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGSwitchElement)
36 NS_INTERFACE_MAP_END_INHERITING(SVGSwitchElementBase)
38 //----------------------------------------------------------------------
39 // Implementation
41 SVGSwitchElement::SVGSwitchElement(
42 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
43 : SVGSwitchElementBase(std::move(aNodeInfo)) {}
45 void SVGSwitchElement::MaybeInvalidate() {
46 // We must not change mActiveChild until after
47 // InvalidateAndScheduleBoundsUpdate has been called, otherwise
48 // it will not correctly invalidate the old mActiveChild area.
50 nsIContent* newActiveChild = FindActiveChild();
52 if (newActiveChild == mActiveChild) {
53 return;
56 nsIFrame* frame = GetPrimaryFrame();
57 if (frame) {
58 nsLayoutUtils::PostRestyleEvent(this, RestyleHint{0},
59 nsChangeHint_InvalidateRenderingObservers);
60 SVGUtils::ScheduleReflowSVG(frame);
63 mActiveChild = newActiveChild;
66 //----------------------------------------------------------------------
67 // nsINode methods
69 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSwitchElement)
71 //----------------------------------------------------------------------
72 // nsINode methods
74 nsresult SVGSwitchElement::InsertChildBefore(nsIContent* aKid,
75 nsIContent* aBeforeThis,
76 bool aNotify) {
77 nsresult rv =
78 SVGSwitchElementBase::InsertChildBefore(aKid, aBeforeThis, aNotify);
79 if (NS_SUCCEEDED(rv)) {
80 MaybeInvalidate();
82 return rv;
85 void SVGSwitchElement::RemoveChildNode(nsIContent* aKid, bool aNotify) {
86 SVGSwitchElementBase::RemoveChildNode(aKid, aNotify);
87 MaybeInvalidate();
90 //----------------------------------------------------------------------
91 // nsIContent methods
93 NS_IMETHODIMP_(bool)
94 SVGSwitchElement::IsAttributeMapped(const nsAtom* name) const {
95 static const MappedAttributeEntry* const map[] = {sFEFloodMap,
96 sFiltersMap,
97 sFontSpecificationMap,
98 sGradientStopMap,
99 sLightingEffectsMap,
100 sMarkersMap,
101 sTextContentElementsMap,
102 sViewportsMap};
104 return FindAttributeDependence(name, map) ||
105 SVGSwitchElementBase::IsAttributeMapped(name);
108 //----------------------------------------------------------------------
109 // Implementation Helpers:
111 nsIContent* SVGSwitchElement::FindActiveChild() const {
112 nsAutoString acceptLangs;
113 Preferences::GetLocalizedString("intl.accept_languages", acceptLangs);
115 int32_t bestLanguagePreferenceRank = -1;
116 nsIContent* bestChild = nullptr;
117 nsIContent* defaultChild = nullptr;
118 for (nsIContent* child = nsINode::GetFirstChild(); child;
119 child = child->GetNextSibling()) {
120 if (!child->IsElement()) {
121 continue;
123 nsCOMPtr<SVGTests> tests(do_QueryInterface(child));
124 if (tests) {
125 if (tests->PassesConditionalProcessingTestsIgnoringSystemLanguage()) {
126 int32_t languagePreferenceRank =
127 tests->GetBestLanguagePreferenceRank(acceptLangs);
128 switch (languagePreferenceRank) {
129 case 0:
130 // best possible match
131 return child;
132 case -1:
133 // no match
134 break;
135 case -2:
136 // no systemLanguage attribute. If there's nothing better
137 // we'll use the first such child.
138 if (!defaultChild) {
139 defaultChild = child;
141 break;
142 default:
143 if (bestLanguagePreferenceRank == -1 ||
144 languagePreferenceRank < bestLanguagePreferenceRank) {
145 bestLanguagePreferenceRank = languagePreferenceRank;
146 bestChild = child;
148 break;
151 } else if (!bestChild) {
152 bestChild = child;
155 return bestChild ? bestChild : defaultChild;
158 } // namespace dom
159 } // namespace mozilla