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