Coverage Report

Created: 2018-09-25 14:53

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