From 453888f1c37e07e30f0179d5770f29e621262de5 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Thu, 15 Jun 2017 15:41:42 -0400 Subject: Improve computeMatrices singular matrix handling. The existing singular matrix detection in computeMatrices is sufficient but not necessary. Since compute matrices is already doing a QR decomposition, use that to determine singularity instead. This is both faster and more accurate than the previous method for the common case. BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1305085 Change-Id: Iccef8368527b45e4eb565eddbebbbcf41ca66a2c Reviewed-on: https://skia-review.googlesource.com/20054 Reviewed-by: Lee Salzman Reviewed-by: Herb Derby Commit-Queue: Ben Wagner --- src/core/SkScalerContext.cpp | 47 +++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'src/core/SkScalerContext.cpp') diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index f310011dcf..b2860e8f5c 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -703,37 +703,11 @@ bool SkScalerContextRec::computeMatrices(PreMatrixScale preMatrixScale, SkVector *A_out = A; } - // If the 'total' matrix is singular, set the 'scale' to something finite and zero the matrices. - // All underlying ports have issues with zero text size, so use the matricies to zero. - - // Map the vectors [0,1], [1,0], [1,1] and [1,-1] (the EM) through the 'total' matrix. - // If the length of one of these vectors is less than 1/256 then an EM filling square will - // never affect any pixels. - SkVector diag[4] = { { A.getScaleX() , A.getSkewY() }, - { A.getSkewX(), A.getScaleY() }, - { A.getScaleX() + A.getSkewX(), A.getScaleY() + A.getSkewY() }, - { A.getScaleX() - A.getSkewX(), A.getScaleY() - A.getSkewY() }, }; - if (diag[0].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero || - diag[1].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero || - diag[2].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero || - diag[3].lengthSqd() <= SK_ScalarNearlyZero * SK_ScalarNearlyZero) - { - s->fX = SK_Scalar1; - s->fY = SK_Scalar1; - sA->setScale(0, 0); - if (GsA) { - GsA->setScale(0, 0); - } - if (G_inv) { - G_inv->reset(); - } - return false; - } - // GA is the matrix A with rotation removed. SkMatrix GA; bool skewedOrFlipped = A.getSkewX() || A.getSkewY() || A.getScaleX() < 0 || A.getScaleY() < 0; if (skewedOrFlipped) { + // QR by Givens rotations. G is Q^T and GA is R. G is rotational (no reflections). // h is where A maps the horizontal baseline. SkPoint h = SkPoint::Make(SK_Scalar1, 0); A.mapPoints(&h, 1); @@ -759,6 +733,25 @@ bool SkScalerContextRec::computeMatrices(PreMatrixScale preMatrixScale, SkVector } } + // If the 'total' matrix is singular, set the 'scale' to something finite and zero the matrices. + // All underlying ports have issues with zero text size, so use the matricies to zero. + // If one of the scale factors is less than 1/256 then an EM filling square will + // never affect any pixels. + if (SkScalarAbs(GA.get(SkMatrix::kMScaleX)) <= SK_ScalarNearlyZero || + SkScalarAbs(GA.get(SkMatrix::kMScaleY)) <= SK_ScalarNearlyZero) + { + s->fX = SK_Scalar1; + s->fY = SK_Scalar1; + sA->setScale(0, 0); + if (GsA) { + GsA->setScale(0, 0); + } + if (G_inv) { + G_inv->reset(); + } + return false; + } + // At this point, given GA, create s. switch (preMatrixScale) { case kFull_PreMatrixScale: -- cgit v1.2.3