8#include "matrix/SMatrix.h"
9#include "matrix/SFloatBits.h"
26#define SK_LEGACY_MATRIX_MATH_ORDER
27#define SiToU8(x) ((uint8_t)(x))
30static inline float SkDoubleToFloat(
double x)
32 return static_cast<float>(x);
37 memcpy(
fMat, data, 9 *
sizeof(
float));
38 setTypeMask(kUnknown_Mask);
64static const int32_t kScalar1Int = 0x3f800000;
66uint8_t SMatrix::computePerspectiveTypeMask()
const
71 if (
fMat[kMPersp0] != 0 ||
fMat[kMPersp1] != 0 ||
fMat[kMPersp2] != 1)
77 return SiToU8(kORableMasks);
80 return SiToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask);
83uint8_t SMatrix::computeTypeMask()
const
87 if (
fMat[kMPersp0] != 0 ||
fMat[kMPersp1] != 0 ||
fMat[kMPersp2] != 1)
91 return SiToU8(kORableMasks);
94 if (
fMat[kMTransX] != 0 ||
fMat[kMTransY] != 0)
99 int m00 = SFloatAs2sCompliment(
fMat[kMScaleX]);
100 int m01 = SFloatAs2sCompliment(
fMat[kMSkewX]);
101 int m10 = SFloatAs2sCompliment(
fMat[kMSkewY]);
102 int m11 = SFloatAs2sCompliment(
fMat[kMScaleY]);
122 int dp0 = 0 == (m00 | m11);
125 mask |= (dp0 & ds1) << kRectStaysRect_Shift;
131 if ((m00 - kScalar1Int) | (m11 - kScalar1Int))
145 mask |= (m00 & m11) << kRectStaysRect_Shift;
155 const float *ma = a.
fMat;
156 const float *mb = b.
fMat;
158 return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8];
164static inline bool is_degenerate_2x2(
float scaleX,
float skewX,
float skewY,
float scaleY)
166 float perp_dot = scaleX * scaleY - skewX * skewY;
167 return SFloatNearlyZero(perp_dot, SK_ScalarNearlyZero * SK_ScalarNearlyZero);
185 float mx =
fMat[kMScaleX];
186 float my =
fMat[kMScaleY];
190 return !SFloatNearlyZero(mx) && SFloatNearlyEqual(SFloatAbs(mx), SFloatAbs(my));
192 float sx =
fMat[kMSkewX];
193 float sy =
fMat[kMSkewY];
195 if (is_degenerate_2x2(mx, sx, sy, my))
202 return (SFloatNearlyEqual(mx, my, tol) && SFloatNearlyEqual(sx, -sy, tol)) || (SFloatNearlyEqual(mx, -my, tol) && SFloatNearlyEqual(sx, sy, tol));
221 float mx =
fMat[kMScaleX];
222 float my =
fMat[kMScaleY];
223 float sx =
fMat[kMSkewX];
224 float sy =
fMat[kMSkewY];
226 if (is_degenerate_2x2(mx, sx, sy, my))
236 return SFloatNearlyZero(vec[0].dot(vec[1]), SFloatSquare(tol));
241static inline float sdot(
float a,
float b,
float c,
float d)
243 return a * b + c * d;
246static inline float sdot(
float a,
float b,
float c,
float d,
float e,
float f)
248 return a * b + c * d + e * f;
251static inline float scross(
float a,
float b,
float c,
float d)
253 return a * b - c * d;
289 fMat[kMTransX] += sdot(
fMat[kMScaleX], dx,
fMat[kMSkewX], dy);
290 fMat[kMTransY] += sdot(
fMat[kMSkewY], dx,
fMat[kMScaleY], dy);
291 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
315 fMat[kMTransX] += dx;
316 fMat[kMTransY] += dy;
317 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
325 if (1 == sx && 1 == sy)
333 fMat[kMTransX] = px - sx * px;
334 fMat[kMTransY] = py - sy * py;
345 if (1 == sx && 1 == sy)
357 this->setTypeMask(
kScale_Mask | kRectStaysRect_Mask);
367 this->
setScale(SFloatInvert(divx), SFloatInvert(divy));
373 if (1 == sx && 1 == sy)
385 if (1 == sx && 1 == sy)
395 fMat[kMScaleX] *= sx;
397 fMat[kMPersp0] *= sx;
400 fMat[kMScaleY] *= sy;
401 fMat[kMPersp1] *= sy;
413 if (1 == sx && 1 == sy)
424 if (1 == sx && 1 == sy)
437 if (divx == 0 || divy == 0)
442 const float invX = 1.f / divx;
443 const float invY = 1.f / divy;
445 fMat[kMScaleX] *= invX;
446 fMat[kMSkewX] *= invX;
447 fMat[kMTransX] *= invX;
449 fMat[kMScaleY] *= invY;
450 fMat[kMSkewY] *= invY;
451 fMat[kMTransY] *= invY;
453 this->setTypeMask(kUnknown_Mask);
461 const float oneMinusCosV = 1 - cosV;
463 fMat[kMScaleX] = cosV;
464 fMat[kMSkewX] = -sinV;
465 fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px);
467 fMat[kMSkewY] = sinV;
468 fMat[kMScaleY] = cosV;
469 fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py);
471 fMat[kMPersp0] =
fMat[kMPersp1] = 0;
474 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
477float SMatrix::SFloatSinCos(
float radians,
float *cosValue)
479 float sinValue = sk_float_sin(radians);
483 *cosValue = sk_float_cos(radians);
484 if (SFloatNearlyZero(*cosValue))
490 if (SFloatNearlyZero(sinValue))
499 fMat[kMScaleX] = cosV;
500 fMat[kMSkewX] = -sinV;
503 fMat[kMSkewY] = sinV;
504 fMat[kMScaleY] = cosV;
507 fMat[kMPersp0] =
fMat[kMPersp1] = 0;
510 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
516 sinV = SFloatSinCos(SkDegreesToRadians(degrees), &cosV);
523 sinV = SFloatSinCos(SkDegreesToRadians(degrees), &cosV);
561 fMat[kMTransX] = -sx * py;
565 fMat[kMTransY] = -sy * px;
567 fMat[kMPersp0] =
fMat[kMPersp1] = 0;
570 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
583 fMat[kMPersp0] =
fMat[kMPersp1] = 0;
586 this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
629 memset(
fMat, 0, 8 *
sizeof(
float));
630 this->setTypeMask(
kScale_Mask | kRectStaysRect_Mask);
634 float tx, sx = dst.width() / src.width();
635 float ty, sy = dst.height() / src.height();
636 bool xLarger =
false;
651 tx = dst.fLeft - src.fLeft * sx;
652 ty = dst.fTop - src.fTop * sy;
659 diff = dst.width() - src.width() * sy;
663 diff = dst.height() - src.height() * sy;
668 diff = SFloatHalf(diff);
687 unsigned mask = kRectStaysRect_Mask;
688 if (sx != 1 || sy != 1)
696 this->setTypeMask(mask);
705static inline float muladdmul(
float a,
float b,
float c,
float d)
707 return SkDoubleToFloat((
double)a * b + (
double)c * d);
710static inline float rowcol3(
const float row[],
const float col[])
712 return row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
715static void normalize_perspective(
float mat[9])
717 if (SFloatAbs(mat[kMPersp2]) > 1)
719 for (
int i = 0; i < 9; i++)
720 mat[i] = SFloatHalf(mat[i]);
726 TypeMask aType = a.getPerspectiveTypeMaskOnly();
727 TypeMask bType = b.getPerspectiveTypeMaskOnly();
729 if (a.isTriviallyIdentity())
733 else if (b.isTriviallyIdentity())
753 normalize_perspective(tmp.
fMat);
754 tmp.setTypeMask(kUnknown_Mask);
758 tmp.
fMat[kMScaleX] = muladdmul(a.
fMat[kMScaleX], b.
fMat[kMScaleX], a.
fMat[kMSkewX], b.
fMat[kMSkewY]);
760 tmp.
fMat[kMSkewX] = muladdmul(a.
fMat[kMScaleX], b.
fMat[kMSkewX], a.
fMat[kMSkewX], b.
fMat[kMScaleY]);
762 tmp.
fMat[kMTransX] = muladdmul(a.
fMat[kMScaleX], b.
fMat[kMTransX], a.
fMat[kMSkewX], b.
fMat[kMTransY]);
764 tmp.
fMat[kMTransX] += a.
fMat[kMTransX];
766 tmp.
fMat[kMSkewY] = muladdmul(a.
fMat[kMSkewY], b.
fMat[kMScaleX], a.
fMat[kMScaleY], b.
fMat[kMSkewY]);
768 tmp.
fMat[kMScaleY] = muladdmul(a.
fMat[kMSkewY], b.
fMat[kMSkewX], a.
fMat[kMScaleY], b.
fMat[kMScaleY]);
770 tmp.
fMat[kMTransY] = muladdmul(a.
fMat[kMSkewY], b.
fMat[kMTransX], a.
fMat[kMScaleY], b.
fMat[kMTransY]);
772 tmp.
fMat[kMTransY] += a.
fMat[kMTransY];
773 tmp.
fMat[kMPersp0] = tmp.
fMat[kMPersp1] = 0;
774 tmp.
fMat[kMPersp2] = 1;
777 tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
811static inline float scross_dscale(
float a,
float b,
float c,
float d,
double scale)
813 return SkDoubleToScalar(scross(a, b, c, d) * scale);
816static inline double dcross(
double a,
double b,
double c,
double d)
818 return a * b - c * d;
821static inline float dcross_dscale(
double a,
double b,
double c,
double d,
double scale)
823 return SkDoubleToScalar(dcross(a, b, c, d) * scale);
826static double sk_inv_determinant(
const float mat[9],
int isPerspective)
832 det = mat[kMScaleX] * dcross(mat[kMScaleY], mat[kMPersp2], mat[kMTransY], mat[kMPersp1]) + mat[kMSkewX] * dcross(mat[kMTransY], mat[kMPersp0], mat[kMSkewY], mat[kMPersp2]) + mat[kMTransX] * dcross(mat[kMSkewY], mat[kMPersp1], mat[kMScaleY], mat[kMPersp0]);
836 det = dcross(mat[kMScaleX], mat[kMScaleY], mat[kMSkewX], mat[kMSkewY]);
842 if (SFloatNearlyZero((
float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero))
851 affine[kAScaleX] = 1;
854 affine[kAScaleY] = 1;
855 affine[kATransX] = 0;
856 affine[kATransY] = 0;
867 affine[kAScaleX] = this->
fMat[kMScaleX];
868 affine[kASkewY] = this->
fMat[kMSkewY];
869 affine[kASkewX] = this->
fMat[kMSkewX];
870 affine[kAScaleY] = this->
fMat[kMScaleY];
871 affine[kATransX] = this->
fMat[kMTransX];
872 affine[kATransY] = this->
fMat[kMTransY];
877bool SMatrix::invertNonIdentity(
SMatrix *inv)
const
885 bool invertible =
true;
890 float invX =
fMat[kMScaleX];
891 float invY =
fMat[kMScaleY];
892 if (0 == invX || 0 == invY)
896 invX = SFloatInvert(invX);
897 invY = SFloatInvert(invY);
902 inv->
fMat[kMSkewX] = inv->
fMat[kMSkewY] = inv->
fMat[kMPersp0] = inv->
fMat[kMPersp1] = 0;
904 inv->
fMat[kMScaleX] = invX;
905 inv->
fMat[kMScaleY] = invY;
906 inv->
fMat[kMPersp2] = 1;
907 inv->
fMat[kMTransX] = -
fMat[kMTransX] * invX;
908 inv->
fMat[kMTransY] = -
fMat[kMTransY] * invY;
910 inv->setTypeMask(mask | kRectStaysRect_Mask);
920 if (!
fMat[kMScaleX] || !
fMat[kMScaleY])
929 double scale = sk_inv_determinant(
fMat, isPersp);
960 inv->
fMat[kMScaleX] = SkDoubleToScalar(
fMat[kMScaleY] *
scale);
961 inv->
fMat[kMSkewX] = SkDoubleToScalar(-
fMat[kMSkewX] *
scale);
964 inv->
fMat[kMSkewY] = SkDoubleToScalar(-
fMat[kMSkewY] *
scale);
965 inv->
fMat[kMScaleY] = SkDoubleToScalar(
fMat[kMScaleX] *
scale);
968 inv->
fMat[kMPersp0] = 0;
969 inv->
fMat[kMPersp1] = 0;
970 inv->
fMat[kMPersp2] = 1;
973 inv->setTypeMask(fTypeMask);
985void SMatrix::Identity_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
989 if (dst != src && count > 0)
990 memcpy(dst, src, count *
sizeof(SPoint));
993void SMatrix::Trans_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
999 float tx = m.
fMat[kMTransX];
1000 float ty = m.
fMat[kMTransY];
1003 dst->fY = src->fY + ty;
1004 dst->fX = src->fX + tx;
1011void SMatrix::Scale_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
1017 float mx = m.
fMat[kMScaleX];
1018 float my = m.
fMat[kMScaleY];
1021 dst->fY = src->fY * my;
1022 dst->fX = src->fX * mx;
1029void SMatrix::ScaleTrans_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
1035 float mx = m.
fMat[kMScaleX];
1036 float my = m.
fMat[kMScaleY];
1037 float tx = m.
fMat[kMTransX];
1038 float ty = m.
fMat[kMTransY];
1041 dst->fY = src->fY * my + ty;
1042 dst->fX = src->fX * mx + tx;
1049void SMatrix::Rot_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
1055 float mx = m.
fMat[kMScaleX];
1056 float my = m.
fMat[kMScaleY];
1057 float kx = m.
fMat[kMSkewX];
1058 float ky = m.
fMat[kMSkewY];
1064 dst->fY = sdot(sx, ky, sy, my);
1065 dst->fX = sdot(sx, mx, sy, kx);
1071void SMatrix::RotTrans_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
1077 float mx = m.
fMat[kMScaleX];
1078 float my = m.
fMat[kMScaleY];
1079 float kx = m.
fMat[kMSkewX];
1080 float ky = m.
fMat[kMSkewY];
1081 float tx = m.
fMat[kMTransX];
1082 float ty = m.
fMat[kMTransY];
1088#ifdef SK_LEGACY_MATRIX_MATH_ORDER
1089 dst->fY = sx * ky + (sy * my + ty);
1090 dst->fX = sx * mx + (sy * kx + tx);
1092 dst->fY = sdot(sx, ky, sy, my) + ty;
1093 dst->fX = sdot(sx, mx, sy, kx) + tx;
1100void SMatrix::Persp_pts(
const SMatrix &m, SPoint dst[],
const SPoint src[],
int count)
1112 float x = sdot(sx, m.
fMat[kMScaleX], sy, m.
fMat[kMSkewX]) + m.
fMat[kMTransX];
1113 float y = sdot(sx, m.
fMat[kMSkewY], sy, m.
fMat[kMScaleY]) + m.
fMat[kMTransY];
1114#ifdef SK_LEGACY_MATRIX_MATH_ORDER
1115 float z = sx * m.
fMat[kMPersp0] + (sy * m.
fMat[kMPersp1] + m.
fMat[kMPersp2]);
1117 float z = sdot(sx, m.
fMat[kMPersp0], sy, m.
fMat[kMPersp1]) + m.
fMat[kMPersp2];
1121 z = SFloatFastInvert(z);
1131const SMatrix::MapPtsProc SMatrix::gMapPtsProcs[] = { SMatrix::Identity_pts, SMatrix::Trans_pts, SMatrix::Scale_pts, SMatrix::ScaleTrans_pts, SMatrix::Rot_pts, SMatrix::RotTrans_pts, SMatrix::Rot_pts, SMatrix::RotTrans_pts,
1133 SMatrix::Persp_pts, SMatrix::Persp_pts, SMatrix::Persp_pts, SMatrix::Persp_pts, SMatrix::Persp_pts, SMatrix::Persp_pts, SMatrix::Persp_pts, SMatrix::Persp_pts };
1137 SASSERT((dst && src && count > 0) || 0 == count);
1139 SASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
1146static int32_t SkAbs32(int32_t value)
1157 SASSERT((dst && src && count > 0) || 0 == count);
1159 SASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= 3 * count);
1165 memcpy(dst, src, 3 * count *
sizeof(
float));
1175 float x = sdot(sx,
fMat[kMScaleX], sy,
fMat[kMSkewX], sw,
fMat[kMTransX]);
1176 float y = sdot(sx,
fMat[kMSkewY], sy,
fMat[kMScaleY], sw,
fMat[kMTransY]);
1177 float w = sdot(sx,
fMat[kMPersp0], sy,
fMat[kMPersp1], sw,
fMat[kMPersp2]);
1196 proc(*
this, 0, 0, &origin);
1198 for (
int i = count - 1; i >= 0; --i)
1202 proc(*
this, src[i].fX, src[i].fY, &tmp);
1203 dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
1210 tmp.
fMat[kMTransX] = tmp.
fMat[kMTransY] = 0;
1222 this->
mapPoints((SPoint *)dst, (
const SPoint *)&src, 2);
1241 vec[0].set(radius, 0);
1242 vec[1].set(0, radius);
1245 float d0 = vec[0].length();
1246 float d1 = vec[1].length();
1249 return SFloatSqrt(d0 * d1);
1254void SMatrix::Persp_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1258 float x = sdot(sx, m.
fMat[kMScaleX], sy, m.
fMat[kMSkewX]) + m.
fMat[kMTransX];
1259 float y = sdot(sx, m.
fMat[kMSkewY], sy, m.
fMat[kMScaleY]) + m.
fMat[kMTransY];
1260 float z = sdot(sx, m.
fMat[kMPersp0], sy, m.
fMat[kMPersp1]) + m.
fMat[kMPersp2];
1263 z = SFloatFastInvert(z);
1269void SMatrix::RotTrans_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1273#ifdef SK_LEGACY_MATRIX_MATH_ORDER
1274 pt->fX = sx * m.
fMat[kMScaleX] + (sy * m.
fMat[kMSkewX] + m.
fMat[kMTransX]);
1275 pt->fY = sx * m.
fMat[kMSkewY] + (sy * m.
fMat[kMScaleY] + m.
fMat[kMTransY]);
1277 pt->fX = sdot(sx, m.
fMat[kMScaleX], sy, m.
fMat[kMSkewX]) + m.
fMat[kMTransX];
1278 pt->fY = sdot(sx, m.
fMat[kMSkewY], sy, m.
fMat[kMScaleY]) + m.
fMat[kMTransY];
1282void SMatrix::Rot_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1285 SASSERT(0 == m.
fMat[kMTransX]);
1286 SASSERT(0 == m.
fMat[kMTransY]);
1288#ifdef SK_LEGACY_MATRIX_MATH_ORDER
1289 pt->fX = sx * m.
fMat[kMScaleX] + (sy * m.
fMat[kMSkewX] + m.
fMat[kMTransX]);
1290 pt->fY = sx * m.
fMat[kMSkewY] + (sy * m.
fMat[kMScaleY] + m.
fMat[kMTransY]);
1292 pt->fX = sdot(sx, m.
fMat[kMScaleX], sy, m.
fMat[kMSkewX]) + m.
fMat[kMTransX];
1293 pt->fY = sdot(sx, m.
fMat[kMSkewY], sy, m.
fMat[kMScaleY]) + m.
fMat[kMTransY];
1297void SMatrix::ScaleTrans_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1301 pt->fX = sx * m.
fMat[kMScaleX] + m.
fMat[kMTransX];
1302 pt->fY = sy * m.
fMat[kMScaleY] + m.
fMat[kMTransY];
1305void SMatrix::Scale_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1308 SASSERT(0 == m.
fMat[kMTransX]);
1309 SASSERT(0 == m.
fMat[kMTransY]);
1311 pt->fX = sx * m.
fMat[kMScaleX];
1312 pt->fY = sy * m.
fMat[kMScaleY];
1315void SMatrix::Trans_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1319 pt->fX = sx + m.
fMat[kMTransX];
1320 pt->fY = sy + m.
fMat[kMTransY];
1323void SMatrix::Identity_xy(
const SMatrix &m,
float sx,
float sy, SPoint *pt)
1331const SMatrix::MapXYProc SMatrix::gMapXYProcs[] = { SMatrix::Identity_xy, SMatrix::Trans_xy, SMatrix::Scale_xy, SMatrix::ScaleTrans_xy, SMatrix::Rot_xy, SMatrix::RotTrans_xy, SMatrix::Rot_xy, SMatrix::RotTrans_xy,
1333 SMatrix::Persp_xy, SMatrix::Persp_xy, SMatrix::Persp_xy, SMatrix::Persp_xy, SMatrix::Persp_xy, SMatrix::Persp_xy, SMatrix::Persp_xy, SMatrix::Persp_xy };
1338#define PerspNearlyZero(x) SFloatNearlyZero(x, (1.0f / (1 << 26)))
1342static inline bool checkForZero(
float x)
1347static inline bool poly_to_point(SPoint *pt,
const SPoint poly[],
int count)
1354 pt1.fX = poly[1].fX - poly[0].fX;
1355 pt1.fY = poly[1].fY - poly[0].fY;
1356 y = SPoint::Length(pt1.fX, pt1.fY);
1357 if (checkForZero(y))
1366 pt2.fX = poly[0].fY - poly[2].fY;
1367 pt2.fY = poly[2].fX - poly[0].fX;
1370 pt2.fX = poly[0].fY - poly[3].fY;
1371 pt2.fY = poly[3].fX - poly[0].fX;
1373 x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
1381bool SMatrix::Poly2Proc(
const SPoint srcPt[],
SMatrix *dst,
const SPoint &scale)
1383 float invScale = 1 /
scale.fY;
1385 dst->
fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1386 dst->
fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
1387 dst->
fMat[kMPersp0] = 0;
1388 dst->
fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1389 dst->
fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1390 dst->
fMat[kMPersp1] = 0;
1391 dst->
fMat[kMTransX] = srcPt[0].fX;
1392 dst->
fMat[kMTransY] = srcPt[0].fY;
1393 dst->
fMat[kMPersp2] = 1;
1394 dst->setTypeMask(kUnknown_Mask);
1398bool SMatrix::Poly3Proc(
const SPoint srcPt[],
SMatrix *dst,
const SPoint &scale)
1400 float invScale = 1 /
scale.fX;
1401 dst->
fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
1402 dst->
fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
1403 dst->
fMat[kMPersp0] = 0;
1405 invScale = 1 /
scale.fY;
1406 dst->
fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1407 dst->
fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1408 dst->
fMat[kMPersp1] = 0;
1410 dst->
fMat[kMTransX] = srcPt[0].fX;
1411 dst->
fMat[kMTransY] = srcPt[0].fY;
1412 dst->
fMat[kMPersp2] = 1;
1413 dst->setTypeMask(kUnknown_Mask);
1417bool SMatrix::Poly4Proc(
const SPoint srcPt[],
SMatrix *dst,
const SPoint &scale)
1420 float x0, y0, x1, y1, x2, y2;
1422 x0 = srcPt[2].fX - srcPt[0].fX;
1423 y0 = srcPt[2].fY - srcPt[0].fY;
1424 x1 = srcPt[2].fX - srcPt[1].fX;
1425 y1 = srcPt[2].fY - srcPt[1].fY;
1426 x2 = srcPt[2].fX - srcPt[3].fX;
1427 y2 = srcPt[2].fY - srcPt[3].fY;
1430 if (x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2)
1432 float denom = SFloatMulDiv(x1, y2, x2) - y1;
1433 if (checkForZero(denom))
1437 a1 = (SFloatMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom;
1441 float denom = x1 - SFloatMulDiv(y1, x2, y2);
1442 if (checkForZero(denom))
1446 a1 = (x0 - x1 - SFloatMulDiv(y0 - y1, x2, y2)) / denom;
1450 if (x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1)
1452 float denom = y2 - SFloatMulDiv(x2, y1, x1);
1453 if (checkForZero(denom))
1457 a2 = (y0 - y2 - SFloatMulDiv(x0 - x2, y1, x1)) / denom;
1461 float denom = SFloatMulDiv(y2, x1, y1) - x2;
1462 if (checkForZero(denom))
1466 a2 = (SFloatMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom;
1469 float invScale = SFloatInvert(
scale.fX);
1470 dst->
fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
1471 dst->
fMat[kMSkewY] = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
1472 dst->
fMat[kMPersp0] = a2 * invScale;
1474 invScale = SFloatInvert(
scale.fY);
1475 dst->
fMat[kMSkewX] = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
1476 dst->
fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
1477 dst->
fMat[kMPersp1] = a1 * invScale;
1479 dst->
fMat[kMTransX] = srcPt[0].fX;
1480 dst->
fMat[kMTransY] = srcPt[0].fY;
1481 dst->
fMat[kMPersp2] = 1;
1482 dst->setTypeMask(kUnknown_Mask);
1486typedef bool (*PolyMapProc)(
const SPoint[],
SMatrix *,
const SPoint &);
1492 if ((
unsigned)count > 4)
1505 this->
setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
1510 if (!poly_to_point(&
scale, src, count) || SFloatNearlyZero(
scale.fX) || SFloatNearlyZero(
scale.fY))
1515 static const PolyMapProc gPolyMapProcs[] = { SMatrix::Poly2Proc, SMatrix::Poly3Proc, SMatrix::Poly4Proc };
1516 PolyMapProc proc = gPolyMapProcs[count - 2];
1519 tempMap.setTypeMask(kUnknown_Mask);
1521 if (!proc(src, &tempMap,
scale))
1525 if (!tempMap.
invert(&result))
1529 if (!proc(dst, &tempMap,
scale))
1546template <MinMaxOrBoth MIN_MAX_OR_BOTH>
1547bool get_scale_factor(
SMatrix::TypeMask typeMask,
const float m[9],
float results[])
1555 results[0] = SK_Scalar1;
1556 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1558 results[1] = SK_Scalar1;
1564 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1566 results[0] = SkMinScalar(SFloatAbs(m[kMScaleX]), SFloatAbs(m[kMScaleY]));
1568 else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1570 results[0] = SkMaxScalar(SFloatAbs(m[kMScaleX]), SFloatAbs(m[kMScaleY]));
1574 results[0] = SFloatAbs(m[kMScaleX]);
1575 results[1] = SFloatAbs(m[kMScaleY]);
1576 if (results[0] > results[1])
1578 STSwap(results[0], results[1]);
1586 float a = sdot(m[kMScaleX], m[kMScaleX], m[kMSkewY], m[kMSkewY]);
1587 float b = sdot(m[kMScaleX], m[kMSkewX], m[kMScaleY], m[kMSkewY]);
1588 float c = sdot(m[kMSkewX], m[kMSkewX], m[kMScaleY], m[kMScaleY]);
1596 if (bSqd <= SK_ScalarNearlyZero * SK_ScalarNearlyZero)
1598 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1600 results[0] = SkMinScalar(a, c);
1602 else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1604 results[0] = SkMaxScalar(a, c);
1610 if (results[0] > results[1])
1612 STSwap(results[0], results[1]);
1618 float aminusc = a - c;
1619 float apluscdiv2 = SFloatHalf(a + c);
1620 float x = SFloatHalf(SFloatSqrt(aminusc * aminusc + 4 * bSqd));
1621 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1623 results[0] = apluscdiv2 - x;
1625 else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1627 results[0] = apluscdiv2 + x;
1631 results[0] = apluscdiv2 - x;
1632 results[1] = apluscdiv2 + x;
1635 SASSERT(results[0] >= 0);
1636 results[0] = SFloatSqrt(results[0]);
1637 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH)
1639 SASSERT(results[1] >= 0);
1640 results[1] = SFloatSqrt(results[1]);
1648 if (get_scale_factor<kMin_MinMaxOrBoth>(this->
getType(),
fMat, &factor))
1661 if (get_scale_factor<kMax_MinMaxOrBoth>(this->
getType(),
fMat, &factor))
1673 return get_scale_factor<kBoth_MinMaxOrBoth>(this->
getType(),
fMat, scaleFactors);
1684 const SMatrix &asSkMatrix()
const
1686 return *
reinterpret_cast<const SMatrix *
>(
this);
1693 static const PODMatrix identity = { { SK_Scalar1, 0, 0, 0, SK_Scalar1, 0, 0, 0, SK_Scalar1 },
kIdentity_Mask | kRectStaysRect_Mask };
1694 SASSERT(identity.asSkMatrix().isIdentity());
1695 return identity.asSkMatrix();
1702 return invalid.asSkMatrix();
1744 fTypeMask = src.fTypeMask;
1748void SMatrix::setTypeMask(
int mask)
1751 SASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask || ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
1752 fTypeMask = SiToU8(mask);
1755void SMatrix::orTypeMask(
int mask)
1757 SASSERT((mask & kORableMasks) == mask);
1758 fTypeMask = SiToU8(fTypeMask | mask);
1763 memcpy(this->fMat,
fMat,
sizeof(this->fMat));
1764 this->setTypeMask(matType);
1774 return (IxForm *)
this;
The SMatrix class holds a 3x3 matrix for transforming coordinates. SMatrix does not have a constructo...
bool getMinMaxScales(float scaleFactors[2]) const
Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max is scale...
float getMinScale() const
Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper left 2x2....
void postRotate(float degrees, float px, float py)
Post-concats the matrix with the specified rotation.
bool invert(SMatrix *inverse) const
If this matrix can be inverted, return true and if inverse is not null, set inverse to be the inverse...
void postTranslate(float dx, float dy)
Post-concats the matrix with the specified translation.
float mapRadius(float radius) const
Return the mean radius of a circle after it has been mapped by this matrix. NOTE: in perspective this...
bool asAffine(float affine[6]) const
Fills the passed array with the affine values in column major order. If the matrix is a perspective t...
SMatrix operator*(const SMatrix &src) const
Multiplies the matrix by another matrix.
static void SetAffineIdentity(float affine[6])
Fills the passed array with affine identity values in column major order.
bool setIDiv(int divx, int divy)
Sets the matrix to scale by 1/divx and 1/divy.
SMatrix & operator*=(const SMatrix &src)
Multiplies the matrix by another matrix.
static const SMatrix & InvalidMatrix()
Return a reference to a const matrix that is "invalid", one that could never be used.
void setSkew(float kx, float ky) OVERRIDE
Sets the matrix to a skew.
void mapPoints(SPoint dst[], const SPoint src[], int count) const
Apply this matrix to the array of points specified by src, and write the transformed points into the ...
void preScale(float sx, float sy, float px, float py)
Pre-concats the matrix with the specified scale.
bool preservesRightAngles(float tol=((1.0f)/(1<< 12))) const
Checks if the matrix contains only translation, rotation/reflection, or scale (non-uniform scale is a...
bool hasPerspective() const
Checks if the matrix contains perspective elements.
void preTranslate(float dx, float dy)
Pre-concats the matrix with the specified translation.
float getMaxScale() const
Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper left 2x2....
void setRotate2(float degrees, float px, float py) OVERRIDE
Sets the matrix to a rotation with pivot point.
IxForm * Data() SCONST OVERRIDE
Returns a pointer to the matrix data.
void setMatrix(const float data[9], int matType=kUnknown_Mask)
Sets the matrix to the specified data array.
static const SMatrix & I()
Return a reference to a const identity matrix.
void preConcat(const SMatrix &other)
Pre-concats the matrix with the specified matrix.
bool mapRect(SRect *dst, const SRect &src) const
Apply this matrix to the src rectangle, and write the transformed rectangle into dst....
void setSkew2(float kx, float ky, float px, float py) OVERRIDE
Sets the matrix to a skew with pivot point.
bool setPolyToPoly(const SPoint src[], const SPoint dst[], int count)
Set the matrix such that the specified src points would map to the specified dst points....
void reset() OVERRIDE
Resets the matrix to the identity matrix.
TypeMask getType() const
Returns a bitfield describing the transformations the matrix may perform. The bitfield is computed co...
void preRotate(float degrees, float px, float py)
Pre-concats the matrix with the specified rotation.
MapPtsProc getMapPtsProc() const
Get the appropriate MapPtsProc for this matrix.
void setConcat(const SMatrix &a, const SMatrix &b)
Sets the matrix to the concatenation of the two specified matrices.
bool rectStaysRect() const
Returns true if the matrix will map a rectangle to another rectangle. This can be true if the matrix ...
ScaleToFit
Enum for scale-to-fit options.
bool postIDiv(int divx, int divy)
Post-concats the matrix by dividing it by the specified integers.
void preSkew(float kx, float ky, float px, float py)
Pre-concats the matrix with the specified skew.
SMatrix & scale(float sx, float sy)
Post-concats the matrix with a scale.
BOOL isIdentity() SCONST OVERRIDE
Checks if the matrix is the identity matrix.
SMatrix & operator=(const SMatrix &src)
Assignment operator.
void postSkew(float kx, float ky, float px, float py)
Post-concats the matrix with the specified skew.
void setSinCos(float sinValue, float cosValue, float px, float py)
Sets the matrix to rotate by the specified sine and cosine values, with a pivot point at (px,...
void postConcat(const SMatrix &other)
Post-concats the matrix with the specified matrix.
void setRotate(float degrees) OVERRIDE
Sets the matrix to a rotation.
bool isSimilarity(float tol=((1.0f)/(1<< 12))) const
Checks if the matrix contains only translation, rotation/reflection, or uniform scale....
void setTranslate(float dx, float dy) OVERRIDE
Sets the matrix to a translation.
bool setRectToRect(const SRect &src, const SRect &dst, ScaleToFit stf)
Set the matrix to the scale and translate values that map the source rectangle to the destination rec...
MapXYProc getMapXYProc() const
Get the appropriate MapXYProc for this matrix.
void mapHomogeneousPoints(float dst[], const float src[], int count) const
Apply this matrix to the array of homogeneous points, specified by src, where a homogeneous point is ...
void postScale(float sx, float sy, float px, float py)
Post-concats the matrix with the specified scale.
TypeMask
Enum of bit fields for the mask returned by getType(). Use this to identify the complexity of the mat...
@ kAffine_Mask
Set if the matrix skews or rotates.
@ kPerspective_Mask
Set if the matrix is in perspective.
@ kScale_Mask
Set if the matrix has X or Y scale.
@ kIdentity_Mask
Set if the matrix is identity.
@ kTranslate_Mask
Set if the matrix has translation.
void(* MapXYProc)(const SMatrix &mat, float x, float y, SPoint *result)
Function pointer type for mapping a single point (x, y) to a transformed point.
void setScale(float sx, float sy) OVERRIDE
Sets the matrix to a scale.
void setIdentity() OVERRIDE
Sets the matrix to the identity matrix.
friend bool operator==(const SMatrix &a, const SMatrix &b)
Equality operator.
void mapVectors(SVector2D dst[], const SVector2D src[], int count) const
Apply this matrix to the array of vectors specified by src, and write the transformed vectors into th...
void(* MapPtsProc)(const SMatrix &mat, SPoint dst[], const SPoint src[], int count)
Function pointer type for mapping an array of points.
SMatrix()
Default constructor, initializes the matrix to identity.
void setScale2(float sx, float sy, float px, float py) OVERRIDE
Sets the matrix to a scale with pivot point.