SVGSwitchElement.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/SVGSwitchElement.h"
  6. #include "nsLayoutUtils.h"
  7. #include "nsSVGUtils.h"
  8. #include "mozilla/Preferences.h"
  9. #include "mozilla/dom/SVGSwitchElementBinding.h"
  10. class nsIFrame;
  11. NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Switch)
  12. namespace mozilla {
  13. namespace dom {
  14. JSObject*
  15. SVGSwitchElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
  16. {
  17. return SVGSwitchElementBinding::Wrap(aCx, this, aGivenProto);
  18. }
  19. //----------------------------------------------------------------------
  20. // nsISupports methods
  21. NS_IMPL_CYCLE_COLLECTION_INHERITED(SVGSwitchElement, SVGSwitchElementBase,
  22. mActiveChild)
  23. NS_IMPL_ADDREF_INHERITED(SVGSwitchElement,SVGSwitchElementBase)
  24. NS_IMPL_RELEASE_INHERITED(SVGSwitchElement,SVGSwitchElementBase)
  25. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SVGSwitchElement)
  26. NS_INTERFACE_MAP_END_INHERITING(SVGSwitchElementBase)
  27. //----------------------------------------------------------------------
  28. // Implementation
  29. SVGSwitchElement::SVGSwitchElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
  30. : SVGSwitchElementBase(aNodeInfo)
  31. {
  32. }
  33. SVGSwitchElement::~SVGSwitchElement()
  34. {
  35. }
  36. void
  37. SVGSwitchElement::MaybeInvalidate()
  38. {
  39. // We must not change mActiveChild until after
  40. // InvalidateAndScheduleBoundsUpdate has been called, otherwise
  41. // it will not correctly invalidate the old mActiveChild area.
  42. nsIContent *newActiveChild = FindActiveChild();
  43. if (newActiveChild == mActiveChild) {
  44. return;
  45. }
  46. nsIFrame *frame = GetPrimaryFrame();
  47. if (frame) {
  48. nsLayoutUtils::PostRestyleEvent(
  49. this, nsRestyleHint(0),
  50. nsChangeHint_InvalidateRenderingObservers);
  51. nsSVGUtils::ScheduleReflowSVG(frame);
  52. }
  53. mActiveChild = newActiveChild;
  54. }
  55. //----------------------------------------------------------------------
  56. // nsIDOMNode methods
  57. NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSwitchElement)
  58. //----------------------------------------------------------------------
  59. // nsINode methods
  60. nsresult
  61. SVGSwitchElement::InsertChildAt(nsIContent* aKid,
  62. uint32_t aIndex,
  63. bool aNotify)
  64. {
  65. nsresult rv = SVGSwitchElementBase::InsertChildAt(aKid, aIndex, aNotify);
  66. if (NS_SUCCEEDED(rv)) {
  67. MaybeInvalidate();
  68. }
  69. return rv;
  70. }
  71. void
  72. SVGSwitchElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
  73. {
  74. SVGSwitchElementBase::RemoveChildAt(aIndex, aNotify);
  75. MaybeInvalidate();
  76. }
  77. //----------------------------------------------------------------------
  78. // nsIContent methods
  79. NS_IMETHODIMP_(bool)
  80. SVGSwitchElement::IsAttributeMapped(const nsIAtom* name) const
  81. {
  82. static const MappedAttributeEntry* const map[] = {
  83. sFEFloodMap,
  84. sFiltersMap,
  85. sFontSpecificationMap,
  86. sGradientStopMap,
  87. sLightingEffectsMap,
  88. sMarkersMap,
  89. sTextContentElementsMap,
  90. sViewportsMap
  91. };
  92. return FindAttributeDependence(name, map) ||
  93. SVGSwitchElementBase::IsAttributeMapped(name);
  94. }
  95. //----------------------------------------------------------------------
  96. // Implementation Helpers:
  97. nsIContent *
  98. SVGSwitchElement::FindActiveChild() const
  99. {
  100. const nsAdoptingString& acceptLangs =
  101. Preferences::GetLocalizedString("intl.accept_languages");
  102. if (!acceptLangs.IsEmpty()) {
  103. int32_t bestLanguagePreferenceRank = -1;
  104. nsIContent *bestChild = nullptr;
  105. nsIContent *defaultChild = nullptr;
  106. for (nsIContent* child = nsINode::GetFirstChild();
  107. child;
  108. child = child->GetNextSibling()) {
  109. if (!child->IsElement()) {
  110. continue;
  111. }
  112. nsCOMPtr<SVGTests> tests(do_QueryInterface(child));
  113. if (tests) {
  114. if (tests->PassesConditionalProcessingTests(
  115. SVGTests::kIgnoreSystemLanguage)) {
  116. int32_t languagePreferenceRank =
  117. tests->GetBestLanguagePreferenceRank(acceptLangs);
  118. switch (languagePreferenceRank) {
  119. case 0:
  120. // best possible match
  121. return child;
  122. case -1:
  123. // no match
  124. break;
  125. case -2:
  126. // no systemLanguage attribute. If there's nothing better
  127. // we'll use the first such child.
  128. if (!defaultChild) {
  129. defaultChild = child;
  130. }
  131. break;
  132. default:
  133. if (bestLanguagePreferenceRank == -1 ||
  134. languagePreferenceRank < bestLanguagePreferenceRank) {
  135. bestLanguagePreferenceRank = languagePreferenceRank;
  136. bestChild = child;
  137. }
  138. break;
  139. }
  140. }
  141. } else if (!bestChild) {
  142. bestChild = child;
  143. }
  144. }
  145. return bestChild ? bestChild : defaultChild;
  146. }
  147. for (nsIContent* child = nsINode::GetFirstChild();
  148. child;
  149. child = child->GetNextSibling()) {
  150. if (!child->IsElement()) {
  151. continue;
  152. }
  153. nsCOMPtr<SVGTests> tests(do_QueryInterface(child));
  154. if (!tests || tests->PassesConditionalProcessingTests(&acceptLangs)) {
  155. return child;
  156. }
  157. }
  158. return nullptr;
  159. }
  160. } // namespace dom
  161. } // namespace mozilla