Coverage Report

Created: 2018-09-25 14:53

/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