gfx/skia/trunk/src/core/SkQuadClipper.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  * Copyright 2009 The Android Open Source Project
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkQuadClipper.h"
     9 #include "SkGeometry.h"
    11 SkQuadClipper::SkQuadClipper() {
    12     fClip.setEmpty();
    13 }
    15 void SkQuadClipper::setClip(const SkIRect& clip) {
    16     // conver to scalars, since that's where we'll see the points
    17     fClip.set(clip);
    18 }
    20 ///////////////////////////////////////////////////////////////////////////////
    22 static bool chopMonoQuadAt(SkScalar c0, SkScalar c1, SkScalar c2,
    23                            SkScalar target, SkScalar* t) {
    24     /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2
    25      *  We solve for t, using quadratic equation, hence we have to rearrange
    26      * our cooefficents to look like At^2 + Bt + C
    27      */
    28     SkScalar A = c0 - c1 - c1 + c2;
    29     SkScalar B = 2*(c1 - c0);
    30     SkScalar C = c0 - target;
    32     SkScalar roots[2];  // we only expect one, but make room for 2 for safety
    33     int count = SkFindUnitQuadRoots(A, B, C, roots);
    34     if (count) {
    35         *t = roots[0];
    36         return true;
    37     }
    38     return false;
    39 }
    41 static bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar* t) {
    42     return chopMonoQuadAt(pts[0].fY, pts[1].fY, pts[2].fY, y, t);
    43 }
    45 ///////////////////////////////////////////////////////////////////////////////
    47 /*  If we somehow returned the fact that we had to flip the pts in Y, we could
    48  communicate that to setQuadratic, and then avoid having to flip it back
    49  here (only to have setQuadratic do the flip again)
    50  */
    51 bool SkQuadClipper::clipQuad(const SkPoint srcPts[3], SkPoint dst[3]) {
    52     bool reverse;
    54     // we need the data to be monotonically increasing in Y
    55     if (srcPts[0].fY > srcPts[2].fY) {
    56         dst[0] = srcPts[2];
    57         dst[1] = srcPts[1];
    58         dst[2] = srcPts[0];
    59         reverse = true;
    60     } else {
    61         memcpy(dst, srcPts, 3 * sizeof(SkPoint));
    62         reverse = false;
    63     }
    65     // are we completely above or below
    66     const SkScalar ctop = fClip.fTop;
    67     const SkScalar cbot = fClip.fBottom;
    68     if (dst[2].fY <= ctop || dst[0].fY >= cbot) {
    69         return false;
    70     }
    72     SkScalar t;
    73     SkPoint tmp[5]; // for SkChopQuadAt
    75     // are we partially above
    76     if (dst[0].fY < ctop) {
    77         if (chopMonoQuadAtY(dst, ctop, &t)) {
    78             // take the 2nd chopped quad
    79             SkChopQuadAt(dst, tmp, t);
    80             dst[0] = tmp[2];
    81             dst[1] = tmp[3];
    82         } else {
    83             // if chopMonoQuadAtY failed, then we may have hit inexact numerics
    84             // so we just clamp against the top
    85             for (int i = 0; i < 3; i++) {
    86                 if (dst[i].fY < ctop) {
    87                     dst[i].fY = ctop;
    88                 }
    89             }
    90         }
    91     }
    93     // are we partially below
    94     if (dst[2].fY > cbot) {
    95         if (chopMonoQuadAtY(dst, cbot, &t)) {
    96             SkChopQuadAt(dst, tmp, t);
    97             dst[1] = tmp[1];
    98             dst[2] = tmp[2];
    99         } else {
   100             // if chopMonoQuadAtY failed, then we may have hit inexact numerics
   101             // so we just clamp against the bottom
   102             for (int i = 0; i < 3; i++) {
   103                 if (dst[i].fY > cbot) {
   104                     dst[i].fY = cbot;
   105                 }
   106             }
   107         }
   108     }
   110     if (reverse) {
   111         SkTSwap<SkPoint>(dst[0], dst[2]);
   112     }
   113     return true;
   114 }

mercurial