skia2/include/private/SkM44.h
Mike Reed 403c807971 Revert "Revert "Extend SkCanvas matrix stack to be 4x4, but with (basically) the same public API.""
The reason for the assert was breaking an assert, that if the CTM was scale/translate, that after
a preTranslate, it should still be that.

This is true... unless the new translate values are non-finite. In that case, we might turn a zero
into a NaN, (0 * non_finite --> nan), so we either have to require finite args (which we don't
at the moment) or we can't make this assert. This re-land removes that assert.

This reverts commit 268ed57d71.

Change-Id: I3c48a0aa17649351a246c1fbab5449f2d59aaf84
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/263023
Commit-Queue: Mike Reed <reed@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: Mike Reed <reed@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
2020-01-08 16:13:51 +00:00

172 lines
5.2 KiB
C++

/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkM44_DEFINED
#define SkM44_DEFINED
#include "include/core/SkScalar.h"
class SkMatrix;
class SkM44 {
public:
SkM44(const SkM44& src) = default;
SkM44& operator=(const SkM44& src) = default;
constexpr SkM44()
: fMat{1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1}
{}
SkM44(const SkM44& a, const SkM44& b) {
this->setConcat(a, b);
}
/**
* Parameters are treated as row-major.
*/
SkM44(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12,
SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13,
SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15)
{
fMat[0] = m0; fMat[4] = m4; fMat[8] = m8; fMat[12] = m12;
fMat[1] = m1; fMat[5] = m5; fMat[9] = m9; fMat[13] = m13;
fMat[2] = m2; fMat[6] = m6; fMat[10] = m10; fMat[14] = m14;
fMat[3] = m3; fMat[7] = m7; fMat[11] = m11; fMat[15] = m15;
}
static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z = 0) {
return SkM44(1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1);
}
static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z = 1) {
return SkM44(x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1);
}
bool operator==(const SkM44& other) const;
bool operator!=(const SkM44& other) const {
return !(other == *this);
}
void getColMajor(SkScalar v[]) const {
memcpy(v, fMat, sizeof(fMat));
}
void getRowMajor(SkScalar v[]) const;
SkM44& setColMajor(const SkScalar v[]) {
memcpy(fMat, v, sizeof(fMat));
return *this;
}
SkM44& setRowMajor(const SkScalar v[]);
/* Parameters are treated as row-major.
*/
SkM44& setRowMajor(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12,
SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13,
SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15) {
fMat[0] = m0; fMat[4] = m4; fMat[8] = m8; fMat[12] = m12;
fMat[1] = m1; fMat[5] = m5; fMat[9] = m9; fMat[13] = m13;
fMat[2] = m2; fMat[6] = m6; fMat[10] = m10; fMat[14] = m14;
fMat[3] = m3; fMat[7] = m7; fMat[11] = m11; fMat[15] = m15;
return *this;
}
SkScalar atColMajor(int index) const {
SkASSERT(index >= 0 && index < 16);
return fMat[index];
}
SkM44& setIdentity() {
return this->setRowMajor(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
}
SkM44& setTranslate(SkScalar x, SkScalar y, SkScalar z = 0) {
return this->setRowMajor(1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1);
}
SkM44& setScale(SkScalar x, SkScalar y, SkScalar z = 1) {
return this->setRowMajor(x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1);
}
SkM44& setConcat(const SkM44& a, const SkM44& b);
friend SkM44 operator*(const SkM44& a, const SkM44& b) {
return SkM44(a, b);
}
/** If this is invertible, return that in inverse and return true. If it is
* not invertible, return false and leave the inverse parameter unchanged.
*/
bool invert(SkM44* inverse) const;
void dump() const;
////////////////////// Converting to/from SkMatrix
/* When converting from SkM44 to SkMatrix, the third row and
* column is dropped. When converting from SkMatrix to SkM44
* the third row and column remain as identity:
* [ a b c ] [ a b 0 c ]
* [ d e f ] -> [ d e 0 f ]
* [ g h i ] [ 0 0 1 0 ]
* [ g h 0 i ]
*/
SkMatrix asM33() const {
return SkMatrix::MakeAll(fMat[0], fMat[4], fMat[12],
fMat[1], fMat[5], fMat[13],
fMat[3], fMat[7], fMat[15]);
}
SkM44(const SkMatrix& src)
: SkM44(src[SkMatrix::kMScaleX], src[SkMatrix::kMSkewX], 0, src[SkMatrix::kMTransX],
src[SkMatrix::kMSkewY], src[SkMatrix::kMScaleY], 0, src[SkMatrix::kMTransY],
0, 0, 1, 0,
src[SkMatrix::kMPersp0], src[SkMatrix::kMPersp1], 0, src[SkMatrix::kMPersp2])
{}
SkM44& operator=(const SkMatrix& src) {
*this = SkM44(src);
return *this;
}
SkM44& preTranslate(SkScalar x, SkScalar y);
SkM44& preConcat(const SkMatrix&);
private:
/* Stored in column-major.
* Indices
* 0 4 8 12 1 0 0 trans_x
* 1 5 9 13 e.g. 0 1 0 trans_y
* 2 6 10 14 0 0 1 trans_z
* 3 7 11 15 0 0 0 1
*/
SkScalar fMat[16];
double determinant() const;
};
#endif