diff options
author | Ben Wagner <bungeman@google.com> | 2017-06-15 15:41:42 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-15 21:37:51 +0000 |
commit | 453888f1c37e07e30f0179d5770f29e621262de5 (patch) | |
tree | fb62ef383b5ead0f27404785e254400ea4f6c9c0 /src/core/SkScalerContext.cpp | |
parent | 2bd381bffd36cdcffacf606d952547ce66fed7e9 (diff) |
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 <lsalzman@mozilla.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
Diffstat (limited to 'src/core/SkScalerContext.cpp')
-rw-r--r-- | src/core/SkScalerContext.cpp | 47 |
1 files changed, 20 insertions, 27 deletions
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: |