/src/mozilla-central/dom/svg/SVGSwitchElement.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #include "mozilla/dom/SVGSwitchElement.h" |
8 | | |
9 | | #include "nsLayoutUtils.h" |
10 | | #include "nsSVGUtils.h" |
11 | | #include "mozilla/Preferences.h" |
12 | | #include "mozilla/dom/SVGSwitchElementBinding.h" |
13 | | |
14 | | class nsIFrame; |
15 | | |
16 | | NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Switch) |
17 | | |
18 | | namespace mozilla { |
19 | | namespace dom { |
20 | | |
21 | | JSObject* |
22 | | SVGSwitchElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) |
23 | 0 | { |
24 | 0 | return SVGSwitchElement_Binding::Wrap(aCx, this, aGivenProto); |
25 | 0 | } |
26 | | |
27 | | //---------------------------------------------------------------------- |
28 | | // nsISupports methods |
29 | | |
30 | | NS_IMPL_CYCLE_COLLECTION_INHERITED(SVGSwitchElement, SVGSwitchElementBase, |
31 | | mActiveChild) |
32 | | |
33 | | NS_IMPL_ADDREF_INHERITED(SVGSwitchElement,SVGSwitchElementBase) |
34 | | NS_IMPL_RELEASE_INHERITED(SVGSwitchElement,SVGSwitchElementBase) |
35 | | |
36 | 0 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGSwitchElement) |
37 | 0 | NS_INTERFACE_MAP_END_INHERITING(SVGSwitchElementBase) |
38 | | |
39 | | //---------------------------------------------------------------------- |
40 | | // Implementation |
41 | | |
42 | | SVGSwitchElement::SVGSwitchElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) |
43 | | : SVGSwitchElementBase(std::move(aNodeInfo)) |
44 | 0 | { |
45 | 0 | } |
46 | | |
47 | | SVGSwitchElement::~SVGSwitchElement() |
48 | 0 | { |
49 | 0 | } |
50 | | |
51 | | void |
52 | | SVGSwitchElement::MaybeInvalidate() |
53 | 0 | { |
54 | 0 | // We must not change mActiveChild until after |
55 | 0 | // InvalidateAndScheduleBoundsUpdate has been called, otherwise |
56 | 0 | // it will not correctly invalidate the old mActiveChild area. |
57 | 0 |
|
58 | 0 | nsIContent *newActiveChild = FindActiveChild(); |
59 | 0 |
|
60 | 0 | if (newActiveChild == mActiveChild) { |
61 | 0 | return; |
62 | 0 | } |
63 | 0 | |
64 | 0 | nsIFrame *frame = GetPrimaryFrame(); |
65 | 0 | if (frame) { |
66 | 0 | nsLayoutUtils::PostRestyleEvent( |
67 | 0 | this, nsRestyleHint(0), |
68 | 0 | nsChangeHint_InvalidateRenderingObservers); |
69 | 0 | nsSVGUtils::ScheduleReflowSVG(frame); |
70 | 0 | } |
71 | 0 |
|
72 | 0 | mActiveChild = newActiveChild; |
73 | 0 | } |
74 | | |
75 | | //---------------------------------------------------------------------- |
76 | | // nsINode methods |
77 | | |
78 | | |
79 | | NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSwitchElement) |
80 | | |
81 | | //---------------------------------------------------------------------- |
82 | | // nsINode methods |
83 | | |
84 | | nsresult |
85 | | SVGSwitchElement::InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis, |
86 | | bool aNotify) |
87 | 0 | { |
88 | 0 | nsresult rv = |
89 | 0 | SVGSwitchElementBase::InsertChildBefore(aKid, aBeforeThis, aNotify); |
90 | 0 | if (NS_SUCCEEDED(rv)) { |
91 | 0 | MaybeInvalidate(); |
92 | 0 | } |
93 | 0 | return rv; |
94 | 0 | } |
95 | | |
96 | | void |
97 | | SVGSwitchElement::RemoveChildNode(nsIContent* aKid, bool aNotify) |
98 | 0 | { |
99 | 0 | SVGSwitchElementBase::RemoveChildNode(aKid, aNotify); |
100 | 0 | MaybeInvalidate(); |
101 | 0 | } |
102 | | |
103 | | //---------------------------------------------------------------------- |
104 | | // nsIContent methods |
105 | | |
106 | | NS_IMETHODIMP_(bool) |
107 | | SVGSwitchElement::IsAttributeMapped(const nsAtom* name) const |
108 | 0 | { |
109 | 0 | static const MappedAttributeEntry* const map[] = { |
110 | 0 | sFEFloodMap, |
111 | 0 | sFiltersMap, |
112 | 0 | sFontSpecificationMap, |
113 | 0 | sGradientStopMap, |
114 | 0 | sLightingEffectsMap, |
115 | 0 | sMarkersMap, |
116 | 0 | sTextContentElementsMap, |
117 | 0 | sViewportsMap |
118 | 0 | }; |
119 | 0 |
|
120 | 0 | return FindAttributeDependence(name, map) || |
121 | 0 | SVGSwitchElementBase::IsAttributeMapped(name); |
122 | 0 | } |
123 | | |
124 | | //---------------------------------------------------------------------- |
125 | | // Implementation Helpers: |
126 | | |
127 | | nsIContent * |
128 | | SVGSwitchElement::FindActiveChild() const |
129 | 0 | { |
130 | 0 | nsAutoString acceptLangs; |
131 | 0 | Preferences::GetLocalizedString("intl.accept_languages", acceptLangs); |
132 | 0 |
|
133 | 0 | if (!acceptLangs.IsEmpty()) { |
134 | 0 | int32_t bestLanguagePreferenceRank = -1; |
135 | 0 | nsIContent *bestChild = nullptr; |
136 | 0 | nsIContent *defaultChild = nullptr; |
137 | 0 | for (nsIContent* child = nsINode::GetFirstChild(); |
138 | 0 | child; |
139 | 0 | child = child->GetNextSibling()) { |
140 | 0 |
|
141 | 0 | if (!child->IsElement()) { |
142 | 0 | continue; |
143 | 0 | } |
144 | 0 | nsCOMPtr<SVGTests> tests(do_QueryInterface(child)); |
145 | 0 | if (tests) { |
146 | 0 | if (tests->PassesConditionalProcessingTests( |
147 | 0 | SVGTests::kIgnoreSystemLanguage)) { |
148 | 0 | int32_t languagePreferenceRank = |
149 | 0 | tests->GetBestLanguagePreferenceRank(acceptLangs); |
150 | 0 | switch (languagePreferenceRank) { |
151 | 0 | case 0: |
152 | 0 | // best possible match |
153 | 0 | return child; |
154 | 0 | case -1: |
155 | 0 | // no match |
156 | 0 | break; |
157 | 0 | case -2: |
158 | 0 | // no systemLanguage attribute. If there's nothing better |
159 | 0 | // we'll use the first such child. |
160 | 0 | if (!defaultChild) { |
161 | 0 | defaultChild = child; |
162 | 0 | } |
163 | 0 | break; |
164 | 0 | default: |
165 | 0 | if (bestLanguagePreferenceRank == -1 || |
166 | 0 | languagePreferenceRank < bestLanguagePreferenceRank) { |
167 | 0 | bestLanguagePreferenceRank = languagePreferenceRank; |
168 | 0 | bestChild = child; |
169 | 0 | } |
170 | 0 | break; |
171 | 0 | } |
172 | 0 | } |
173 | 0 | } else if (!bestChild) { |
174 | 0 | bestChild = child; |
175 | 0 | } |
176 | 0 | } |
177 | 0 | return bestChild ? bestChild : defaultChild; |
178 | 0 | } |
179 | 0 | |
180 | 0 | for (nsIContent* child = nsINode::GetFirstChild(); |
181 | 0 | child; |
182 | 0 | child = child->GetNextSibling()) { |
183 | 0 | if (!child->IsElement()) { |
184 | 0 | continue; |
185 | 0 | } |
186 | 0 | nsCOMPtr<SVGTests> tests(do_QueryInterface(child)); |
187 | 0 | if (!tests || tests->PassesConditionalProcessingTests(&acceptLangs)) { |
188 | 0 | return child; |
189 | 0 | } |
190 | 0 | } |
191 | 0 | return nullptr; |
192 | 0 | } |
193 | | |
194 | | } // namespace dom |
195 | | } // namespace mozilla |
196 | | |