nsSVGEnum.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 "nsError.h"
  6. #include "nsSVGAttrTearoffTable.h"
  7. #include "nsSVGEnum.h"
  8. #include "nsIAtom.h"
  9. #include "nsSVGElement.h"
  10. #include "nsSMILValue.h"
  11. #include "SMILEnumType.h"
  12. using namespace mozilla;
  13. using namespace mozilla::dom;
  14. static nsSVGAttrTearoffTable<nsSVGEnum, nsSVGEnum::DOMAnimatedEnum>
  15. sSVGAnimatedEnumTearoffTable;
  16. nsSVGEnumMapping *
  17. nsSVGEnum::GetMapping(nsSVGElement *aSVGElement)
  18. {
  19. nsSVGElement::EnumAttributesInfo info = aSVGElement->GetEnumInfo();
  20. NS_ASSERTION(info.mEnumCount > 0 && mAttrEnum < info.mEnumCount,
  21. "mapping request for a non-attrib enum");
  22. return info.mEnumInfo[mAttrEnum].mMapping;
  23. }
  24. nsresult
  25. nsSVGEnum::SetBaseValueAtom(const nsIAtom* aValue, nsSVGElement *aSVGElement)
  26. {
  27. nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
  28. while (mapping && mapping->mKey) {
  29. if (aValue == *(mapping->mKey)) {
  30. mIsBaseSet = true;
  31. if (mBaseVal != mapping->mVal) {
  32. mBaseVal = mapping->mVal;
  33. if (!mIsAnimated) {
  34. mAnimVal = mBaseVal;
  35. }
  36. else {
  37. aSVGElement->AnimationNeedsResample();
  38. }
  39. // We don't need to call DidChange* here - we're only called by
  40. // nsSVGElement::ParseAttribute under Element::SetAttr,
  41. // which takes care of notifying.
  42. }
  43. return NS_OK;
  44. }
  45. mapping++;
  46. }
  47. // only a warning since authors may mistype attribute values
  48. NS_WARNING("unknown enumeration key");
  49. return NS_ERROR_DOM_SYNTAX_ERR;
  50. }
  51. nsIAtom*
  52. nsSVGEnum::GetBaseValueAtom(nsSVGElement *aSVGElement)
  53. {
  54. nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
  55. while (mapping && mapping->mKey) {
  56. if (mBaseVal == mapping->mVal) {
  57. return *mapping->mKey;
  58. }
  59. mapping++;
  60. }
  61. NS_ERROR("unknown enumeration value");
  62. return nsGkAtoms::_empty;
  63. }
  64. nsresult
  65. nsSVGEnum::SetBaseValue(uint16_t aValue,
  66. nsSVGElement *aSVGElement)
  67. {
  68. nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
  69. while (mapping && mapping->mKey) {
  70. if (mapping->mVal == aValue) {
  71. mIsBaseSet = true;
  72. if (mBaseVal != uint8_t(aValue)) {
  73. mBaseVal = uint8_t(aValue);
  74. if (!mIsAnimated) {
  75. mAnimVal = mBaseVal;
  76. }
  77. else {
  78. aSVGElement->AnimationNeedsResample();
  79. }
  80. aSVGElement->DidChangeEnum(mAttrEnum);
  81. }
  82. return NS_OK;
  83. }
  84. mapping++;
  85. }
  86. return NS_ERROR_DOM_SYNTAX_ERR;
  87. }
  88. void
  89. nsSVGEnum::SetAnimValue(uint16_t aValue, nsSVGElement *aSVGElement)
  90. {
  91. if (mIsAnimated && aValue == mAnimVal) {
  92. return;
  93. }
  94. mAnimVal = aValue;
  95. mIsAnimated = true;
  96. aSVGElement->DidAnimateEnum(mAttrEnum);
  97. }
  98. already_AddRefed<SVGAnimatedEnumeration>
  99. nsSVGEnum::ToDOMAnimatedEnum(nsSVGElement* aSVGElement)
  100. {
  101. RefPtr<DOMAnimatedEnum> domAnimatedEnum =
  102. sSVGAnimatedEnumTearoffTable.GetTearoff(this);
  103. if (!domAnimatedEnum) {
  104. domAnimatedEnum = new DOMAnimatedEnum(this, aSVGElement);
  105. sSVGAnimatedEnumTearoffTable.AddTearoff(this, domAnimatedEnum);
  106. }
  107. return domAnimatedEnum.forget();
  108. }
  109. nsSVGEnum::DOMAnimatedEnum::~DOMAnimatedEnum()
  110. {
  111. sSVGAnimatedEnumTearoffTable.RemoveTearoff(mVal);
  112. }
  113. nsISMILAttr*
  114. nsSVGEnum::ToSMILAttr(nsSVGElement *aSVGElement)
  115. {
  116. return new SMILEnum(this, aSVGElement);
  117. }
  118. nsresult
  119. nsSVGEnum::SMILEnum::ValueFromString(const nsAString& aStr,
  120. const dom::SVGAnimationElement* /*aSrcElement*/,
  121. nsSMILValue& aValue,
  122. bool& aPreventCachingOfSandwich) const
  123. {
  124. nsIAtom *valAtom = NS_GetStaticAtom(aStr);
  125. if (valAtom) {
  126. nsSVGEnumMapping *mapping = mVal->GetMapping(mSVGElement);
  127. while (mapping && mapping->mKey) {
  128. if (valAtom == *(mapping->mKey)) {
  129. nsSMILValue val(SMILEnumType::Singleton());
  130. val.mU.mUint = mapping->mVal;
  131. aValue = val;
  132. aPreventCachingOfSandwich = false;
  133. return NS_OK;
  134. }
  135. mapping++;
  136. }
  137. }
  138. // only a warning since authors may mistype attribute values
  139. NS_WARNING("unknown enumeration key");
  140. return NS_ERROR_FAILURE;
  141. }
  142. nsSMILValue
  143. nsSVGEnum::SMILEnum::GetBaseValue() const
  144. {
  145. nsSMILValue val(SMILEnumType::Singleton());
  146. val.mU.mUint = mVal->mBaseVal;
  147. return val;
  148. }
  149. void
  150. nsSVGEnum::SMILEnum::ClearAnimValue()
  151. {
  152. if (mVal->mIsAnimated) {
  153. mVal->mIsAnimated = false;
  154. mVal->mAnimVal = mVal->mBaseVal;
  155. mSVGElement->DidAnimateEnum(mVal->mAttrEnum);
  156. }
  157. }
  158. nsresult
  159. nsSVGEnum::SMILEnum::SetAnimValue(const nsSMILValue& aValue)
  160. {
  161. NS_ASSERTION(aValue.mType == SMILEnumType::Singleton(),
  162. "Unexpected type to assign animated value");
  163. if (aValue.mType == SMILEnumType::Singleton()) {
  164. MOZ_ASSERT(aValue.mU.mUint <= USHRT_MAX,
  165. "Very large enumerated value - too big for uint16_t");
  166. mVal->SetAnimValue(uint16_t(aValue.mU.mUint), mSVGElement);
  167. }
  168. return NS_OK;
  169. }