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
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index f2d1708..983c8d2 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1586,6 +1586,95 @@
///////////////////////////////////////////////////////////////////////////////
+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 afd5bd3..8818dc0 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
draw.drawPosText((const char*)text, byteLength, pos, constY,
scalarsPerPos, paint);
} else {
- SkAutoExtMatrix aem(draw.fExtMatrix);
SkDraw myDraw(draw);
GrPaint grPaint;
@@ -1213,7 +1187,7 @@
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);