aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-10 13:52:42 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-10 13:52:42 +0000
commitcc4dac3dac215dc0dd56f7b30d07cc304671b033 (patch)
treedf2541be704a4c8db625028013a15aa763362336
parentee9aa304579b3d5314519372728187879456d49d (diff)
Make GrMatrix an alias of SkMatrix. Add new methods to SkMatrix.
Review URL: http://codereview.appspot.com/4538043/ Checked in on behalf of reed@ with some additional work (remove the do-nother sk->gr matrix converter). git-svn-id: http://skia.googlecode.com/svn/trunk@1289 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gpu/include/GrMatrix.h396
-rw-r--r--gpu/include/GrTextContext.h2
-rw-r--r--gpu/src/GrContext.cpp2
-rw-r--r--gpu/src/GrGpuGLFixed.cpp18
-rw-r--r--gpu/src/GrGpuGLShaders.cpp39
-rw-r--r--gpu/src/GrMatrix.cpp3
-rw-r--r--gpu/src/gr_unittests.cpp1
-rw-r--r--include/core/SkMatrix.h54
-rw-r--r--include/gpu/SkGr.h12
-rw-r--r--src/core/SkMatrix.cpp89
-rw-r--r--src/gpu/SkGpuDevice.cpp36
11 files changed, 182 insertions, 470 deletions
diff --git a/gpu/include/GrMatrix.h b/gpu/include/GrMatrix.h
index 19a6644bf7..a879ed043a 100644
--- a/gpu/include/GrMatrix.h
+++ b/gpu/include/GrMatrix.h
@@ -19,400 +19,8 @@
#define GrMatrix_DEFINED
#include "GrRect.h"
+#include "SkMatrix.h"
-/*
- * 3x3 matrix
- */
-class GrMatrix {
-public:
- static const GrMatrix& I() {
- static const GrMatrix I = GrMatrix(GR_Scalar1, 0, 0,
- 0, GR_Scalar1, 0,
- 0, 0, gRESCALE);
- return I;
- };
- static const GrMatrix& InvalidMatrix() {
- static const GrMatrix INV =
- GrMatrix(GR_ScalarMax, GR_ScalarMax, GR_ScalarMax,
- GR_ScalarMax, GR_ScalarMax, GR_ScalarMax,
- GR_ScalarMax, GR_ScalarMax, GR_ScalarMax);
- return INV;
- }
- /**
- * Handy index constants
- */
- enum {
- kScaleX,
- kSkewX,
- kTransX,
- kSkewY,
- kScaleY,
- kTransY,
- kPersp0,
- kPersp1,
- kPersp2
- };
-
- /**
- * Create an uninitialized matrix
- */
- GrMatrix() {
- fTypeMask = 0;
- }
-
- /**
- * Create a matrix from an array of values
- * @param values row-major array of matrix components
- */
- explicit GrMatrix(const GrScalar values[]) {
- setToArray(values);
- }
-
- /**
- * Create a matrix from values
- * @param scaleX (0,0) matrix element
- * @param skewX (0,1) matrix element
- * @param transX (0,2) matrix element
- * @param skewY (1,0) matrix element
- * @param scaleY (1,1) matrix element
- * @param transY (1,2) matrix element
- * @param persp0 (2,0) matrix element
- * @param persp1 (2,1) matrix element
- * @param persp2 (2,2) matrix element
- */
- GrMatrix(GrScalar scaleX,
- GrScalar skewX,
- GrScalar transX,
- GrScalar skewY,
- GrScalar scaleY,
- GrScalar transY,
- GrScalar persp0,
- GrScalar persp1,
- GrScalar persp2) {
- setAll(scaleX, skewX, transX,
- skewY, scaleY, transY,
- persp0, persp1, persp2);
- }
-
- /**
- * access matrix component
- * @return matrix component value
- */
- const GrScalar& operator[] (int idx) const {
- GrAssert((unsigned)idx < 9);
- return fM[idx];
- }
-
- /**
- * Set a matrix from an array of values
- * @param values row-major array of matrix components
- */
- void setToArray(const GrScalar values[]) {
- for (int i = 0; i < 9; ++i) {
- fM[i] = values[i];
- }
- this->computeTypeMask();
- }
-
- /**
- * Create a matrix from values
- * @param scaleX (0,0) matrix element
- * @param skewX (0,1) matrix element
- * @param transX (0,2) matrix element
- * @param skewY (1,0) matrix element
- * @param scaleY (1,1) matrix element
- * @param transY (1,2) matrix element
- * @param persp0 (2,0) matrix element
- * @param persp1 (2,1) matrix element
- * @param persp2 (2,2) matrix element
- */
- void setAll(GrScalar scaleX,
- GrScalar skewX,
- GrScalar transX,
- GrScalar skewY,
- GrScalar scaleY,
- GrScalar transY,
- GrScalar persp0,
- GrScalar persp1,
- GrScalar persp2) {
- fM[kScaleX] = scaleX;
- fM[kSkewX] = skewX;
- fM[kTransX] = transX;
- fM[kSkewY] = skewY;
- fM[kScaleY] = scaleY;
- fM[kTransY] = transY;
- fM[kPersp0] = persp0;
- fM[kPersp1] = persp1;
- fM[kPersp2] = persp2;
-
- this->computeTypeMask();
- }
-
- /**
- * set matrix component
- * @param idx index of component to set
- * @param value value to set component to
- */
- inline void set(int idx, GrScalar value);
-
- /**
- * make this matrix an identity matrix
- */
- void setIdentity();
-
- /**
- * overwrite entire matrix to be a translation matrix
- * @param dx amount to translate by in x
- * @param dy amount to translate by in y
- */
- void setTranslate(GrScalar dx, GrScalar dy);
-
- /**
- * overwrite entire matrix to be a scaling matrix
- * @param sx x scale factor
- * @param sy y scale factor
- */
- void setScale(GrScalar sx, GrScalar sy);
-
- /**
- * overwrite entire matrix to be a skew matrix
- * @param skx x skew factor
- * @param sky y skew factor
- */
- void setSkew(GrScalar skx, GrScalar sky);
-
- /**
- * set this matrix to be a concantenation of two
- * matrices (a*b). Either a, b, or both can be this matrix.
- * @param a first matrix to multiply
- * @param b second matrix to multiply
- */
- void setConcat(const GrMatrix& a, const GrMatrix& b);
-
- /**
- * Set this matrix to this*m
- * @param m matrix to concatenate
- */
- void preConcat(const GrMatrix& m);
-
- /**
- * Set this matrix to m*this
- * @param m matrix to concatenate
- */
- void postConcat(const GrMatrix& m);
-
- /**
- * Compute the inverse of this matrix, and return true if it is invertible,
- * or false if not.
- *
- * If inverted is not null, and the matrix is invertible, then the inverse
- * is written into it. If the matrix is not invertible (this method returns
- * false) then inverted is left unchanged.
- */
- bool invert(GrMatrix* inverted) const;
-
- /**
- * Transforms a point by the matrix
- *
- * @param src the point to transform
- * @return the transformed point
- */
- GrPoint mapPoint(const GrPoint& src) const {
- GrPoint result;
- (this->*gMapProcs[fTypeMask])(&result, &src, 1);
- return result;
- }
-
- /**
- * Transforms an array of points by the matrix.
- *
- * @param dstPts the array to write transformed points into
- * @param srcPts the array of points to transform
- @ @param count the number of points to transform
- */
- void mapPoints(GrPoint dstPts[],
- const GrPoint srcPts[],
- uint32_t count) const {
- (this->*gMapProcs[fTypeMask])(dstPts, srcPts, count);
- }
-
- /**
- * Transforms pts with arbitrary stride in place.
- *
- * @param start pointer to first point to transform
- * @param stride distance in bytes between consecutive points
- @ @param count the number of points to transform
- */
- void mapPointsWithStride(GrPoint* start,
- size_t stride,
- uint32_t count) const {
- for (uint32_t i = 0; i < count; ++i) {
- this->mapPoints(start, start, 1);
- start = (GrPoint*)((intptr_t)start + stride);
- }
- }
-
- /**
- * Transforms a vector by the matrix. Doesn't handle cases when a
- * homogeneous vector maps to a point (i.e. perspective transform).
- * In this case the desired answer is dependent on where the tail of
- * the vector is in space.
- */
- void mapVec(GrVec* vec) {
- GrAssert(!this->hasPerspective());
- if (!this->isIdentity()) {
- GrScalar x = vec->fX;
- vec->fX = (*this)[kScaleX] * x + (*this)[kSkewX] * vec->fY;
- vec->fY = (*this)[kSkewY ] * x + (*this)[kScaleY] * vec->fY;
- }
- }
-
- /**
- * Transform the 4 corners of the src rect, and return the bounding rect
- * in the dst rect. Note: src and dst may point to the same memory.
- */
- void mapRect(GrRect* dst, const GrRect& src) const;
-
- /**
- * Transform the 4 corners of the rect, and return their bounds in the rect
- */
- void mapRect(GrRect* rect) const {
- this->mapRect(rect, *rect);
- }
-
- /**
- * Checks if matrix is a perspective matrix.
- * @return true if third row is not (0, 0, 1)
- */
- bool hasPerspective() const;
-
- /**
- * Checks whether matrix is identity
- * @return true if matrix is idenity
- */
- bool isIdentity() const;
-
- /**
- * Do axis-aligned lines stay axis aligned? May do 90 degree rotation / mirroring.
- */
- bool preservesAxisAlignment() const;
-
- /**
- * Calculates the maximum stretching factor of the matrix. Only defined if
- * the matrix does not have perspective.
- *
- * @return maximum strecthing factor or negative if matrix has perspective.
- */
- GrScalar getMaxStretch() const;
-
- /**
- * Checks for matrix equality. Test is element-by-element equality,
- * not a homogeneous test.
- * @return true if matrices are equal, false otherwise
- */
- bool operator == (const GrMatrix& m) const;
-
- /**
- * Checks for matrix inequality. Test is element-by-element inequality,
- * not a homogeneous test.
- * @return true if matrices are not equal, false otherwise
- */
- bool operator != (const GrMatrix& m) const;
-
- static void UnitTest();
-
-private:
- static const GrScalar gRESCALE;
-
- void computeTypeMask() {
- fTypeMask = 0;
- if (0 != fM[kPersp0] || 0 != fM[kPersp1] || gRESCALE != fM[kPersp2]) {
- fTypeMask |= kPerspective_TypeBit;
- }
- if (GR_Scalar1 != fM[kScaleX] || GR_Scalar1 != fM[kScaleY]) {
- fTypeMask |= kScale_TypeBit;
- if (0 == fM[kScaleX] && 0 == fM[kScaleY]) {
- fTypeMask |= kZeroScale_TypeBit;
- }
- }
- if (0 != fM[kSkewX] || 0 != fM[kSkewY]) {
- fTypeMask |= kSkew_TypeBit;
- }
- if (0 != fM[kTransX] || 0 != fM[kTransY]) {
- fTypeMask |= kTranslate_TypeBit;
- }
- }
-
-
- double determinant() const;
-
- enum TypeBits {
- kScale_TypeBit = 1 << 0, // set if scales are not both 1
- kTranslate_TypeBit = 1 << 1, // set if translates are not both 0
- kSkew_TypeBit = 1 << 2, // set if skews are not both 0
- kPerspective_TypeBit = 1 << 3, // set if perspective
- kZeroScale_TypeBit = 1 << 4, // set if scales are both zero
- };
-
- void mapIdentity(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapScale(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapScaleAndSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapSkewAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapNonPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapZero(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapSetToTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapSwappedScale(GrPoint* dst, const GrPoint* src, uint32_t count) const;
- void mapSwappedScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const;
-
- void mapInvalid(GrPoint* dst, const GrPoint* src, uint32_t count) const;
-
- typedef void (GrMatrix::*MapProc) (GrPoint* dst, const GrPoint* src, uint32_t count) const;
- static const MapProc gMapProcs[];
-
- int fTypeMask;
-
- GrScalar fM[9];
-};
-
-void GrMatrix::set(int idx, GrScalar value) {
- GrAssert((unsigned)idx < 9);
- fM[idx] = value;
- if (idx > 5) {
- if (0 != fM[kPersp0] || 0 != fM[kPersp1] ||
- gRESCALE != fM[kPersp2]) {
- fTypeMask |= kPerspective_TypeBit;
- } else {
- fTypeMask &= ~kPerspective_TypeBit;
- }
- } else if (!(idx % 4)) {
- if ((GR_Scalar1 == fM[kScaleX] && GR_Scalar1 == fM[kScaleY])) {
- fTypeMask &= ~kScale_TypeBit;
- fTypeMask &= ~kZeroScale_TypeBit;
- } else {
- fTypeMask |= kScale_TypeBit;
- if ((0 == fM[kScaleX] && 0 == fM[kScaleY])) {
- fTypeMask |= kZeroScale_TypeBit;
- } else {
- fTypeMask &= ~kZeroScale_TypeBit;
- }
- }
- } else if (2 == (idx % 3)) {
- if (0 != fM[kTransX] || 0 != fM[kTransY]) {
- fTypeMask |= kTranslate_TypeBit;
- } else {
- fTypeMask &= ~kTranslate_TypeBit;
- }
- } else {
- if (0 != fM[kSkewX] || 0 != fM[kSkewY]) {
- fTypeMask |= kSkew_TypeBit;
- } else {
- fTypeMask &= ~kSkew_TypeBit;
- }
- }
-}
+typedef SkMatrix GrMatrix;
#endif
diff --git a/gpu/include/GrTextContext.h b/gpu/include/GrTextContext.h
index a5982517d2..b7a690e3fe 100644
--- a/gpu/include/GrTextContext.h
+++ b/gpu/include/GrTextContext.h
@@ -20,9 +20,9 @@
#include "GrGlyph.h"
#include "GrPaint.h"
+#include "GrMatrix.h"
struct GrGpuTextVertex;
-class GrMatrix;
class GrContext;
class GrTextStrike;
class GrFontScaler;
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 84611878e3..2d93e4bbd6 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -925,7 +925,7 @@ void GrContext::drawRect(const GrPaint& paint,
GrVec strokeSize;;
if (width > 0) {
strokeSize.set(width, width);
- combinedMatrix.mapVec(&strokeSize);
+ combinedMatrix.mapVectors(&strokeSize, 1);
strokeSize.setAbs(strokeSize);
} else {
strokeSize.set(GR_Scalar1, GR_Scalar1);
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index dbfac436c8..e197a82533 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -32,17 +32,17 @@ struct GrGpuMatrix {
void set(const GrMatrix& m) {
Gr_bzero(fMat, sizeof(fMat));
- fMat[0] = GrScalarToFloat(m[GrMatrix::kScaleX]);
- fMat[4] = GrScalarToFloat(m[GrMatrix::kSkewX]);
- fMat[12] = GrScalarToFloat(m[GrMatrix::kTransX]);
+ fMat[0] = GrScalarToFloat(m[GrMatrix::kMScaleX]);
+ fMat[4] = GrScalarToFloat(m[GrMatrix::kMSkewX]);
+ fMat[12] = GrScalarToFloat(m[GrMatrix::kMTransX]);
- fMat[1] = GrScalarToFloat(m[GrMatrix::kSkewY]);
- fMat[5] = GrScalarToFloat(m[GrMatrix::kScaleY]);
- fMat[13] = GrScalarToFloat(m[GrMatrix::kTransY]);
+ fMat[1] = GrScalarToFloat(m[GrMatrix::kMSkewY]);
+ fMat[5] = GrScalarToFloat(m[GrMatrix::kMScaleY]);
+ fMat[13] = GrScalarToFloat(m[GrMatrix::kMTransY]);
- fMat[3] = GrScalarToFloat(m[GrMatrix::kPersp0]);
- fMat[7] = GrScalarToFloat(m[GrMatrix::kPersp1]);
- fMat[15] = GrScalarToFloat(m[GrMatrix::kPersp2]);
+ fMat[3] = GrScalarToFloat(m[GrMatrix::kMPersp0]);
+ fMat[7] = GrScalarToFloat(m[GrMatrix::kMPersp1]);
+ fMat[15] = GrScalarToFloat(m[GrMatrix::kMPersp2]);
fMat[10] = 1.f; // z-scale
}
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index c2b89716de..3ce6e55d69 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -273,7 +273,8 @@ void GrGpuGLShaders::resetContext() {
void GrGpuGLShaders::flushViewMatrix() {
GrAssert(NULL != fCurrDrawState.fRenderTarget);
- GrMatrix m (
+ GrMatrix m;
+ m.setAll(
GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
0, 0, GrMatrix::I()[8]);
@@ -282,15 +283,15 @@ void GrGpuGLShaders::flushViewMatrix() {
// ES doesn't allow you to pass true to the transpose param,
// so do our own transpose
GrScalar mt[] = {
- m[GrMatrix::kScaleX],
- m[GrMatrix::kSkewY],
- m[GrMatrix::kPersp0],
- m[GrMatrix::kSkewX],
- m[GrMatrix::kScaleY],
- m[GrMatrix::kPersp1],
- m[GrMatrix::kTransX],
- m[GrMatrix::kTransY],
- m[GrMatrix::kPersp2]
+ m[GrMatrix::kMScaleX],
+ m[GrMatrix::kMSkewY],
+ m[GrMatrix::kMPersp0],
+ m[GrMatrix::kMSkewX],
+ m[GrMatrix::kMScaleY],
+ m[GrMatrix::kMPersp1],
+ m[GrMatrix::kMTransX],
+ m[GrMatrix::kMTransY],
+ m[GrMatrix::kMPersp2]
};
if (GrGLProgram::kSetAsAttribute ==
@@ -327,15 +328,15 @@ void GrGpuGLShaders::flushTextureMatrix(int s) {
// ES doesn't allow you to pass true to the transpose param,
// so do our own transpose
GrScalar mt[] = {
- m[GrMatrix::kScaleX],
- m[GrMatrix::kSkewY],
- m[GrMatrix::kPersp0],
- m[GrMatrix::kSkewX],
- m[GrMatrix::kScaleY],
- m[GrMatrix::kPersp1],
- m[GrMatrix::kTransX],
- m[GrMatrix::kTransY],
- m[GrMatrix::kPersp2]
+ m[GrMatrix::kMScaleX],
+ m[GrMatrix::kMSkewY],
+ m[GrMatrix::kMPersp0],
+ m[GrMatrix::kMSkewX],
+ m[GrMatrix::kMScaleY],
+ m[GrMatrix::kMPersp1],
+ m[GrMatrix::kMTransX],
+ m[GrMatrix::kMTransY],
+ m[GrMatrix::kMPersp2]
};
if (GrGLProgram::kSetAsAttribute ==
fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) {
diff --git a/gpu/src/GrMatrix.cpp b/gpu/src/GrMatrix.cpp
index c88c6e13f1..476d9a2293 100644
--- a/gpu/src/GrMatrix.cpp
+++ b/gpu/src/GrMatrix.cpp
@@ -19,6 +19,7 @@
#include "GrRect.h"
#include <stddef.h>
+#if 0
#if GR_SCALAR_IS_FLOAT
const GrScalar GrMatrix::gRESCALE(GR_Scalar1);
#else
@@ -688,6 +689,7 @@ void GrMatrix::UnitTest() {
}
///////////////////////////////////////////////////////////////////////////////
+#endif
int Gr_clz(uint32_t n) {
if (0 == n) {
@@ -716,4 +718,3 @@ int Gr_clz(uint32_t n) {
}
return count;
}
-
diff --git a/gpu/src/gr_unittests.cpp b/gpu/src/gr_unittests.cpp
index fd27f199a9..320dd15bd7 100644
--- a/gpu/src/gr_unittests.cpp
+++ b/gpu/src/gr_unittests.cpp
@@ -152,7 +152,6 @@ void gr_run_unittests() {
test_tdarray();
test_bsearch();
test_binHashKey();
- GrMatrix::UnitTest();
GrRedBlackTree<int>::UnitTest();
GrPath::ConvexUnitTest();
GrDrawTarget::VertexLayoutUnitTest();
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index 5ba9223058..7c779027be 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -70,6 +70,15 @@ public:
}
return (fTypeMask & kRectStaysRect_Mask) != 0;
}
+ // alias for rectStaysRect()
+ bool preservesAxisAlignment() const { return this->rectStaysRect(); }
+
+ /**
+ * Returns true if the perspective contains perspective elements.
+ */
+ bool hasPerspective() const {
+ return SkToBool(this->getType() & kPerspective_Mask);
+ }
enum {
kMScaleX,
@@ -123,10 +132,27 @@ public:
void setPerspX(SkScalar v) { this->set(kMPersp0, v); }
void setPerspY(SkScalar v) { this->set(kMPersp1, v); }
+ void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
+ SkScalar skewY, SkScalar scaleY, SkScalar transY,
+ SkScalar persp0, SkScalar persp1, SkScalar persp2) {
+ fMat[kMScaleX] = scaleX;
+ fMat[kMSkewX] = skewX;
+ fMat[kMTransX] = transX;
+ fMat[kMSkewY] = skewY;
+ fMat[kMScaleY] = scaleY;
+ fMat[kMTransY] = transY;
+ fMat[kMPersp0] = persp0;
+ fMat[kMPersp1] = persp1;
+ fMat[kMPersp2] = persp2;
+ this->setTypeMask(kUnknown_Mask);
+ }
+
/** Set the matrix to identity
*/
void reset();
-
+ // alias for reset()
+ void setIdentity() { this->reset(); }
+
/** Set the matrix to translate by (dx, dy).
*/
void setTranslate(SkScalar dx, SkScalar dy);
@@ -369,6 +395,13 @@ public:
return this->mapRect(rect, *rect);
}
+ void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
+ for (int i = 0; i < count; ++i) {
+ this->mapPoints(pts, pts, 1);
+ pts = (SkPoint*)((intptr_t)pts + stride);
+ }
+ }
+
/** Return the mean radius of a circle after it has been mapped by
this matrix. NOTE: in perspective this value assumes the circle
has its center at the origin.
@@ -425,6 +458,25 @@ public:
void dump() const;
void toDumpString(SkString*) const;
+ /**
+ * Calculates the maximum stretching factor of the matrix. Only defined if
+ * the matrix does not have perspective.
+ *
+ * @return maximum strecthing factor or negative if matrix has perspective.
+ */
+ SkScalar getMaxStretch() const;
+
+ /**
+ * Return a reference to a const identity matrix
+ */
+ static const SkMatrix& I();
+
+ /**
+ * Return a reference to a const matrix that is "invalid", one that could
+ * never be used.
+ */
+ static const SkMatrix& InvalidMatrix();
+
private:
enum {
/** Set if the matrix will map a rectangle to another rectangle. This
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index eef70b1287..75099b2df6 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -117,18 +117,6 @@ public:
return BitmapConfig2PixelConfig(bm.config(), bm.isOpaque());
}
- static void SkMatrix2GrMatrix(const SkMatrix& m, GrMatrix* g) {
- g->setAll(SkScalarToGrScalar(m[0]),
- SkScalarToGrScalar(m[1]),
- SkScalarToGrScalar(m[2]),
- SkScalarToGrScalar(m[3]),
- SkScalarToGrScalar(m[4]),
- SkScalarToGrScalar(m[5]),
- SkScalarToGrScalar(m[6]),
- SkScalarToGrScalar(m[7]),
- SkScalarToGrScalar(m[8]));
- }
-
static GrColor SkColor2GrColor(SkColor c) {
SkPMColor pm = SkPreMultiplyColor(c);
unsigned r = SkGetPackedR32(pm);
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index f2d1708114..983c8d21f2 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1586,6 +1586,95 @@ bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
///////////////////////////////////////////////////////////////////////////////
+SkScalar SkMatrix::getMaxStretch() const {
+ TypeMask mask = this->getType();
+
+ if (mask & kPerspective_Mask) {
+ return -SK_Scalar1;
+ }
+
+ SkScalar stretch;
+
+ if (this->isIdentity()) {
+ stretch = SK_Scalar1;
+ } else if (!(mask & kAffine_Mask)) {
+ stretch = SkMaxScalar(SkScalarAbs(fMat[kMScaleX]), SkScalarAbs(fMat[kMScaleY]));
+#if 0 // don't have this bit
+ } else if (mask & kZeroScale_TypeBit) {
+ stretch = SkMaxScalar(SkScalarAbs(fM[kSkewX]), SkScalarAbs(fM[kSkewY]));
+#endif
+ } else {
+ // ignore the translation part of the matrix, just look at 2x2 portion.
+ // compute singular values, take largest abs value.
+ // [a b; b c] = A^T*A
+ SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) + SkScalarMul(fMat[kMSkewY], fMat[kMSkewY]);
+ SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) + SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]);
+ SkScalar c = SkScalarMul(fMat[kMSkewX], fMat[kMSkewX]) + SkScalarMul(fMat[kMScaleY], fMat[kMScaleY]);
+ // eigenvalues of A^T*A are the squared singular values of A.
+ // characteristic equation is det((A^T*A) - l*I) = 0
+ // l^2 - (a + c)l + (ac-b^2)
+ // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
+ // and roots are guaraunteed to be pos and real).
+ SkScalar largerRoot;
+ SkScalar bSqd = SkScalarMul(b,b);
+ if (bSqd <= SkFloatToScalar(1e-10)) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math
+ largerRoot = SkMaxScalar(a, c);
+ } else {
+ SkScalar aminusc = a - c;
+ SkScalar apluscdiv2 = (a + c) / 2;
+ SkScalar x = SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd) / 2;
+ largerRoot = apluscdiv2 + x;
+ }
+
+ stretch = SkScalarSqrt(largerRoot);
+ }
+#if defined(SK_DEBUG) && 0
+ // test a bunch of vectors. None should be scaled by more than stretch
+ // (modulo some error) and we should find a vector that is scaled by almost
+ // stretch.
+ SkPoint pt;
+ SkScalar max = 0;
+ for (int i = 0; i < 1000; ++i) {
+ SkScalar x = (float)rand() / RAND_MAX;
+ SkScalar y = sqrtf(1 - (x*x));
+ pt.fX = fMat[kMScaleX]*x + fMat[kMSkewX]*y;
+ pt.fY = fMat[kMSkewY]*x + fMat[kMScaleY]*y;
+ SkScalar d = pt.distanceToOrigin();
+ SkASSERT(d <= (1.0001 * stretch));
+ if (max < pt.distanceToOrigin()) {
+ max = pt.distanceToOrigin();
+ }
+ }
+ SkASSERT((stretch - max) < .05*stretch);
+#endif
+ return stretch;
+}
+
+const SkMatrix& SkMatrix::I() {
+ static SkMatrix gIdentity;
+ static bool gOnce;
+ if (!gOnce) {
+ gIdentity.reset();
+ gOnce = true;
+ }
+ return gIdentity;
+};
+
+const SkMatrix& SkMatrix::InvalidMatrix() {
+ static SkMatrix gInvalid;
+ static bool gOnce;
+ if (!gOnce) {
+ gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
+ SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
+ SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
+ gInvalid.getType(); // force the type to be computed
+ gOnce = true;
+ }
+ return gInvalid;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
uint32_t SkMatrix::flatten(void* buffer) const {
// TODO write less for simple matrices
if (buffer) {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index afd5bd37ab..8818dc0b06 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -39,23 +39,6 @@
#define CHECK_SHOULD_DRAW(draw) this->prepareRenderTarget(draw)
#endif
-class SkAutoExtMatrix {
-public:
- SkAutoExtMatrix(const SkMatrix* extMatrix) {
- if (extMatrix) {
- SkGr::SkMatrix2GrMatrix(*extMatrix, &fMatrix);
- fExtMatrix = &fMatrix;
- } else {
- fExtMatrix = NULL;
- }
- }
- const GrMatrix* extMatrix() const { return fExtMatrix; }
-
-private:
- GrMatrix fMatrix;
- GrMatrix* fExtMatrix; // NULL or &fMatrix
-};
-
///////////////////////////////////////////////////////////////////////////////
SkGpuDevice::SkAutoCachedTexture::
@@ -279,9 +262,7 @@ static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
const SkClipStack& clipStack,
const SkRegion& clipRegion,
const SkIPoint& origin) {
- GrMatrix grmat;
- SkGr::SkMatrix2GrMatrix(matrix, &grmat);
- context->setMatrix(grmat);
+ context->setMatrix(matrix);
SkGrClipIterator iter;
iter.reset(clipStack);
@@ -460,9 +441,7 @@ bool SkGpuDevice::skPaint2GrPaintShader(const SkPaint& skPaint,
GrScalar s = GrFixedToScalar(GR_Fixed1 / bitmap.width());
matrix.postScale(s, s);
}
- GrMatrix grMat;
- SkGr::SkMatrix2GrMatrix(matrix, &grMat);
- grPaint->fSampler.setMatrix(grMat);
+ grPaint->fSampler.setMatrix(matrix);
return true;
}
@@ -975,10 +954,7 @@ void SkGpuDevice::internalDrawBitmap(const SkDraw& draw,
GrFixedToScalar((srcRect.fRight << 16) / bitmap.width()),
GrFixedToScalar((srcRect.fBottom << 16) / bitmap.height()));
- GrMatrix grMat;
- SkGr::SkMatrix2GrMatrix(m, &grMat);
-
- fContext->drawRectToRect(*grPaint, dstRect, paintRect, &grMat);
+ fContext->drawRectToRect(*grPaint, dstRect, paintRect, &m);
}
void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
@@ -1178,7 +1154,6 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
// this guy will just call our drawPath()
draw.drawText((const char*)text, byteLength, x, y, paint);
} else {
- SkAutoExtMatrix aem(draw.fExtMatrix);
SkDraw myDraw(draw);
GrPaint grPaint;
@@ -1187,7 +1162,7 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) {
return;
}
- GrTextContext context(fContext, grPaint, aem.extMatrix());
+ GrTextContext context(fContext, grPaint, draw.fExtMatrix);
myDraw.fProcs = this->initDrawForText(&context);
this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
}
@@ -1204,7 +1179,6 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
draw.drawPosText((const char*)text, byteLength, pos, constY,
scalarsPerPos, paint);
} else {
- SkAutoExtMatrix aem(draw.fExtMatrix);
SkDraw myDraw(draw);
GrPaint grPaint;
@@ -1213,7 +1187,7 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
return;
}
- GrTextContext context(fContext, grPaint, aem.extMatrix());
+ GrTextContext context(fContext, grPaint, draw.fExtMatrix);
myDraw.fProcs = this->initDrawForText(&context);
this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
scalarsPerPos, paint);