nsSVGPathGeometryElement.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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 "nsSVGPathGeometryElement.h"
  6. #include "gfxPlatform.h"
  7. #include "mozilla/gfx/2D.h"
  8. #include "nsComputedDOMStyle.h"
  9. #include "nsSVGUtils.h"
  10. #include "nsSVGLength2.h"
  11. #include "SVGContentUtils.h"
  12. using namespace mozilla;
  13. using namespace mozilla::gfx;
  14. //----------------------------------------------------------------------
  15. // Implementation
  16. nsSVGPathGeometryElement::nsSVGPathGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
  17. : nsSVGPathGeometryElementBase(aNodeInfo)
  18. {
  19. }
  20. nsresult
  21. nsSVGPathGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
  22. const nsAttrValue* aValue,
  23. const nsAttrValue* aOldValue, bool aNotify)
  24. {
  25. if (mCachedPath &&
  26. aNamespaceID == kNameSpaceID_None &&
  27. AttributeDefinesGeometry(aName)) {
  28. mCachedPath = nullptr;
  29. }
  30. return nsSVGPathGeometryElementBase::AfterSetAttr(aNamespaceID, aName,
  31. aValue, aOldValue, aNotify);
  32. }
  33. bool
  34. nsSVGPathGeometryElement::AttributeDefinesGeometry(const nsIAtom *aName)
  35. {
  36. // Check for nsSVGLength2 attribute
  37. LengthAttributesInfo info = GetLengthInfo();
  38. for (uint32_t i = 0; i < info.mLengthCount; i++) {
  39. if (aName == *info.mLengthInfo[i].mName) {
  40. return true;
  41. }
  42. }
  43. return false;
  44. }
  45. bool
  46. nsSVGPathGeometryElement::GeometryDependsOnCoordCtx()
  47. {
  48. // Check the nsSVGLength2 attribute
  49. LengthAttributesInfo info = const_cast<nsSVGPathGeometryElement*>(this)->GetLengthInfo();
  50. for (uint32_t i = 0; i < info.mLengthCount; i++) {
  51. if (info.mLengths[i].GetSpecifiedUnitType() == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. bool
  58. nsSVGPathGeometryElement::IsMarkable()
  59. {
  60. return false;
  61. }
  62. void
  63. nsSVGPathGeometryElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
  64. {
  65. }
  66. already_AddRefed<Path>
  67. nsSVGPathGeometryElement::GetOrBuildPath(const DrawTarget& aDrawTarget,
  68. FillRule aFillRule)
  69. {
  70. // We only cache the path if it matches the backend used for screen painting:
  71. bool cacheable = aDrawTarget.GetBackendType() ==
  72. gfxPlatform::GetPlatform()->GetDefaultContentBackend();
  73. // Checking for and returning mCachedPath before checking the pref means
  74. // that the pref is only live on page reload (or app restart for SVG in
  75. // chrome). The benefit is that we avoid causing a CPU memory cache miss by
  76. // looking at the global variable that the pref's stored in.
  77. if (cacheable && mCachedPath) {
  78. if (aDrawTarget.GetBackendType() == mCachedPath->GetBackendType()) {
  79. RefPtr<Path> path(mCachedPath);
  80. return path.forget();
  81. }
  82. }
  83. RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder(aFillRule);
  84. RefPtr<Path> path = BuildPath(builder);
  85. if (cacheable && NS_SVGPathCachingEnabled()) {
  86. mCachedPath = path;
  87. }
  88. return path.forget();
  89. }
  90. already_AddRefed<Path>
  91. nsSVGPathGeometryElement::GetOrBuildPathForMeasuring()
  92. {
  93. return nullptr;
  94. }
  95. FillRule
  96. nsSVGPathGeometryElement::GetFillRule()
  97. {
  98. FillRule fillRule = FillRule::FILL_WINDING; // Equivalent to StyleFillRule::Nonzero
  99. RefPtr<nsStyleContext> styleContext =
  100. nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr,
  101. nullptr);
  102. if (styleContext) {
  103. MOZ_ASSERT(styleContext->StyleSVG()->mFillRule == StyleFillRule::Nonzero ||
  104. styleContext->StyleSVG()->mFillRule == StyleFillRule::Evenodd);
  105. if (styleContext->StyleSVG()->mFillRule == StyleFillRule::Evenodd) {
  106. fillRule = FillRule::FILL_EVEN_ODD;
  107. }
  108. } else {
  109. // ReportToConsole
  110. NS_WARNING("Couldn't get style context for content in GetFillRule");
  111. }
  112. return fillRule;
  113. }