nsSVGTransform.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 "nsSVGTransform.h"
  7. #include "nsContentUtils.h" // for NS_ENSURE_FINITE
  8. #include "nsTextFormatter.h"
  9. namespace {
  10. const double kRadPerDegree = 2.0 * M_PI / 360.0;
  11. } // namespace
  12. namespace mozilla {
  13. void
  14. nsSVGTransform::GetValueAsString(nsAString& aValue) const
  15. {
  16. char16_t buf[256];
  17. switch (mType) {
  18. case SVG_TRANSFORM_TRANSLATE:
  19. // The spec say that if Y is not provided, it is assumed to be zero.
  20. if (mMatrix._32 != 0)
  21. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  22. u"translate(%g, %g)",
  23. mMatrix._31, mMatrix._32);
  24. else
  25. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  26. u"translate(%g)",
  27. mMatrix._31);
  28. break;
  29. case SVG_TRANSFORM_ROTATE:
  30. if (mOriginX != 0.0f || mOriginY != 0.0f)
  31. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  32. u"rotate(%g, %g, %g)",
  33. mAngle, mOriginX, mOriginY);
  34. else
  35. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  36. u"rotate(%g)", mAngle);
  37. break;
  38. case SVG_TRANSFORM_SCALE:
  39. if (mMatrix._11 != mMatrix._22)
  40. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  41. u"scale(%g, %g)", mMatrix._11, mMatrix._22);
  42. else
  43. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  44. u"scale(%g)", mMatrix._11);
  45. break;
  46. case SVG_TRANSFORM_SKEWX:
  47. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  48. u"skewX(%g)", mAngle);
  49. break;
  50. case SVG_TRANSFORM_SKEWY:
  51. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  52. u"skewY(%g)", mAngle);
  53. break;
  54. case SVG_TRANSFORM_MATRIX:
  55. nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
  56. u"matrix(%g, %g, %g, %g, %g, %g)",
  57. mMatrix._11, mMatrix._12,
  58. mMatrix._21, mMatrix._22,
  59. mMatrix._31, mMatrix._32);
  60. break;
  61. default:
  62. buf[0] = '\0';
  63. NS_ERROR("unknown transformation type");
  64. break;
  65. }
  66. aValue.Assign(buf);
  67. }
  68. void
  69. nsSVGTransform::SetMatrix(const gfxMatrix& aMatrix)
  70. {
  71. mType = SVG_TRANSFORM_MATRIX;
  72. mMatrix = aMatrix;
  73. // We set the other members here too, since operator== requires it and
  74. // the DOM requires it for mAngle.
  75. mAngle = 0.f;
  76. mOriginX = 0.f;
  77. mOriginY = 0.f;
  78. }
  79. void
  80. nsSVGTransform::SetTranslate(float aTx, float aTy)
  81. {
  82. mType = SVG_TRANSFORM_TRANSLATE;
  83. mMatrix.Reset();
  84. mMatrix._31 = aTx;
  85. mMatrix._32 = aTy;
  86. mAngle = 0.f;
  87. mOriginX = 0.f;
  88. mOriginY = 0.f;
  89. }
  90. void
  91. nsSVGTransform::SetScale(float aSx, float aSy)
  92. {
  93. mType = SVG_TRANSFORM_SCALE;
  94. mMatrix.Reset();
  95. mMatrix._11 = aSx;
  96. mMatrix._22 = aSy;
  97. mAngle = 0.f;
  98. mOriginX = 0.f;
  99. mOriginY = 0.f;
  100. }
  101. void
  102. nsSVGTransform::SetRotate(float aAngle, float aCx, float aCy)
  103. {
  104. mType = SVG_TRANSFORM_ROTATE;
  105. mMatrix.Reset();
  106. mMatrix.Translate(aCx, aCy);
  107. mMatrix.Rotate(aAngle*kRadPerDegree);
  108. mMatrix.Translate(-aCx, -aCy);
  109. mAngle = aAngle;
  110. mOriginX = aCx;
  111. mOriginY = aCy;
  112. }
  113. nsresult
  114. nsSVGTransform::SetSkewX(float aAngle)
  115. {
  116. double ta = tan(aAngle*kRadPerDegree);
  117. NS_ENSURE_FINITE(ta, NS_ERROR_RANGE_ERR);
  118. mType = SVG_TRANSFORM_SKEWX;
  119. mMatrix.Reset();
  120. mMatrix._21 = ta;
  121. mAngle = aAngle;
  122. mOriginX = 0.f;
  123. mOriginY = 0.f;
  124. return NS_OK;
  125. }
  126. nsresult
  127. nsSVGTransform::SetSkewY(float aAngle)
  128. {
  129. double ta = tan(aAngle*kRadPerDegree);
  130. NS_ENSURE_FINITE(ta, NS_ERROR_RANGE_ERR);
  131. mType = SVG_TRANSFORM_SKEWY;
  132. mMatrix.Reset();
  133. mMatrix._12 = ta;
  134. mAngle = aAngle;
  135. mOriginX = 0.f;
  136. mOriginY = 0.f;
  137. return NS_OK;
  138. }
  139. SVGTransformSMILData::SVGTransformSMILData(const nsSVGTransform& aTransform)
  140. : mTransformType(aTransform.Type())
  141. {
  142. MOZ_ASSERT(mTransformType >= SVG_TRANSFORM_MATRIX &&
  143. mTransformType <= SVG_TRANSFORM_SKEWY,
  144. "Unexpected transform type");
  145. for (uint32_t i = 0; i < NUM_STORED_PARAMS; ++i) {
  146. mParams[i] = 0.f;
  147. }
  148. switch (mTransformType) {
  149. case SVG_TRANSFORM_MATRIX: {
  150. const gfxMatrix& mx = aTransform.GetMatrix();
  151. mParams[0] = static_cast<float>(mx._11);
  152. mParams[1] = static_cast<float>(mx._12);
  153. mParams[2] = static_cast<float>(mx._21);
  154. mParams[3] = static_cast<float>(mx._22);
  155. mParams[4] = static_cast<float>(mx._31);
  156. mParams[5] = static_cast<float>(mx._32);
  157. break;
  158. }
  159. case SVG_TRANSFORM_TRANSLATE: {
  160. const gfxMatrix& mx = aTransform.GetMatrix();
  161. mParams[0] = static_cast<float>(mx._31);
  162. mParams[1] = static_cast<float>(mx._32);
  163. break;
  164. }
  165. case SVG_TRANSFORM_SCALE: {
  166. const gfxMatrix& mx = aTransform.GetMatrix();
  167. mParams[0] = static_cast<float>(mx._11);
  168. mParams[1] = static_cast<float>(mx._22);
  169. break;
  170. }
  171. case SVG_TRANSFORM_ROTATE:
  172. mParams[0] = aTransform.Angle();
  173. aTransform.GetRotationOrigin(mParams[1], mParams[2]);
  174. break;
  175. case SVG_TRANSFORM_SKEWX:
  176. case SVG_TRANSFORM_SKEWY:
  177. mParams[0] = aTransform.Angle();
  178. break;
  179. default:
  180. NS_NOTREACHED("Unexpected transform type");
  181. break;
  182. }
  183. }
  184. nsSVGTransform
  185. SVGTransformSMILData::ToSVGTransform() const
  186. {
  187. nsSVGTransform result;
  188. switch (mTransformType) {
  189. case SVG_TRANSFORM_MATRIX:
  190. result.SetMatrix(gfxMatrix(mParams[0], mParams[1],
  191. mParams[2], mParams[3],
  192. mParams[4], mParams[5]));
  193. break;
  194. case SVG_TRANSFORM_TRANSLATE:
  195. result.SetTranslate(mParams[0], mParams[1]);
  196. break;
  197. case SVG_TRANSFORM_SCALE:
  198. result.SetScale(mParams[0], mParams[1]);
  199. break;
  200. case SVG_TRANSFORM_ROTATE:
  201. result.SetRotate(mParams[0], mParams[1], mParams[2]);
  202. break;
  203. case SVG_TRANSFORM_SKEWX:
  204. result.SetSkewX(mParams[0]);
  205. break;
  206. case SVG_TRANSFORM_SKEWY:
  207. result.SetSkewY(mParams[0]);
  208. break;
  209. default:
  210. NS_NOTREACHED("Unexpected transform type");
  211. break;
  212. }
  213. return result;
  214. }
  215. } // namespace mozilla