SVGMotionSMILPathUtils.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 "SVGMotionSMILPathUtils.h"
  6. #include "nsCharSeparatedTokenizer.h"
  7. #include "nsContentUtils.h" // for NS_ENSURE_FINITE2
  8. #include "SVGContentUtils.h"
  9. #include "SVGLength.h"
  10. using namespace mozilla::gfx;
  11. namespace mozilla {
  12. //----------------------------------------------------------------------
  13. // PathGenerator methods
  14. // For the dummy 'from' value used in pure by-animation & to-animation
  15. void
  16. SVGMotionSMILPathUtils::PathGenerator::
  17. MoveToOrigin()
  18. {
  19. MOZ_ASSERT(!mHaveReceivedCommands,
  20. "Not expecting requests for mid-path MoveTo commands");
  21. mHaveReceivedCommands = true;
  22. mPathBuilder->MoveTo(Point(0, 0));
  23. }
  24. // For 'from' and the first entry in 'values'.
  25. bool
  26. SVGMotionSMILPathUtils::PathGenerator::
  27. MoveToAbsolute(const nsAString& aCoordPairStr)
  28. {
  29. MOZ_ASSERT(!mHaveReceivedCommands,
  30. "Not expecting requests for mid-path MoveTo commands");
  31. mHaveReceivedCommands = true;
  32. float xVal, yVal;
  33. if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
  34. return false;
  35. }
  36. mPathBuilder->MoveTo(Point(xVal, yVal));
  37. return true;
  38. }
  39. // For 'to' and every entry in 'values' except the first.
  40. bool
  41. SVGMotionSMILPathUtils::PathGenerator::
  42. LineToAbsolute(const nsAString& aCoordPairStr, double& aSegmentDistance)
  43. {
  44. mHaveReceivedCommands = true;
  45. float xVal, yVal;
  46. if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
  47. return false;
  48. }
  49. Point initialPoint = mPathBuilder->CurrentPoint();
  50. mPathBuilder->LineTo(Point(xVal, yVal));
  51. aSegmentDistance = NS_hypot(initialPoint.x - xVal, initialPoint.y -yVal);
  52. return true;
  53. }
  54. // For 'by'.
  55. bool
  56. SVGMotionSMILPathUtils::PathGenerator::
  57. LineToRelative(const nsAString& aCoordPairStr, double& aSegmentDistance)
  58. {
  59. mHaveReceivedCommands = true;
  60. float xVal, yVal;
  61. if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
  62. return false;
  63. }
  64. mPathBuilder->LineTo(mPathBuilder->CurrentPoint() + Point(xVal, yVal));
  65. aSegmentDistance = NS_hypot(xVal, yVal);
  66. return true;
  67. }
  68. already_AddRefed<Path>
  69. SVGMotionSMILPathUtils::PathGenerator::GetResultingPath()
  70. {
  71. return mPathBuilder->Finish();
  72. }
  73. //----------------------------------------------------------------------
  74. // Helper / protected methods
  75. bool
  76. SVGMotionSMILPathUtils::PathGenerator::
  77. ParseCoordinatePair(const nsAString& aCoordPairStr,
  78. float& aXVal, float& aYVal)
  79. {
  80. nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
  81. tokenizer(aCoordPairStr, ',',
  82. nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
  83. SVGLength x, y;
  84. if (!tokenizer.hasMoreTokens() ||
  85. !x.SetValueFromString(tokenizer.nextToken())) {
  86. return false;
  87. }
  88. if (!tokenizer.hasMoreTokens() ||
  89. !y.SetValueFromString(tokenizer.nextToken())) {
  90. return false;
  91. }
  92. if (tokenizer.separatorAfterCurrentToken() || // Trailing comma.
  93. tokenizer.hasMoreTokens()) { // More text remains
  94. return false;
  95. }
  96. float xRes = x.GetValueInUserUnits(mSVGElement, SVGContentUtils::X);
  97. float yRes = y.GetValueInUserUnits(mSVGElement, SVGContentUtils::Y);
  98. NS_ENSURE_FINITE2(xRes, yRes, false);
  99. aXVal = xRes;
  100. aYVal = yRes;
  101. return true;
  102. }
  103. //----------------------------------------------------------------------
  104. // MotionValueParser methods
  105. bool
  106. SVGMotionSMILPathUtils::MotionValueParser::
  107. Parse(const nsAString& aValueStr)
  108. {
  109. bool success;
  110. if (!mPathGenerator->HaveReceivedCommands()) {
  111. // Interpret first value in "values" attribute as the path's initial MoveTo
  112. success = mPathGenerator->MoveToAbsolute(aValueStr);
  113. if (success) {
  114. success = !!mPointDistances->AppendElement(0.0, fallible);
  115. }
  116. } else {
  117. double dist;
  118. success = mPathGenerator->LineToAbsolute(aValueStr, dist);
  119. if (success) {
  120. mDistanceSoFar += dist;
  121. success = !!mPointDistances->AppendElement(mDistanceSoFar, fallible);
  122. }
  123. }
  124. return success;
  125. }
  126. } // namespace mozilla