• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "SkQuadClipper.h"
18 #include "SkGeometry.h"
19 
chopMonoQuadAtY(SkPoint pts[3],SkScalar y,SkScalar * t)20 static bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar* t) {
21     /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2
22      *  We solve for t, using quadratic equation, hence we have to rearrange
23      * our cooefficents to look like At^2 + Bt + C
24      */
25     SkScalar A = pts[0].fY - pts[1].fY - pts[1].fY + pts[2].fY;
26     SkScalar B = 2*(pts[1].fY - pts[0].fY);
27     SkScalar C = pts[0].fY - y;
28 
29     SkScalar roots[2];  // we only expect one, but make room for 2 for safety
30     int count = SkFindUnitQuadRoots(A, B, C, roots);
31     if (count) {
32         *t = roots[0];
33         return true;
34     }
35     return false;
36 }
37 
SkQuadClipper()38 SkQuadClipper::SkQuadClipper() {}
39 
setClip(const SkIRect & clip)40 void SkQuadClipper::setClip(const SkIRect& clip) {
41     // conver to scalars, since that's where we'll see the points
42     fClip.set(clip);
43 }
44 
45 /*  If we somehow returned the fact that we had to flip the pts in Y, we could
46     communicate that to setQuadratic, and then avoid having to flip it back
47     here (only to have setQuadratic do the flip again)
48  */
clipQuad(const SkPoint srcPts[3],SkPoint dst[3])49 bool SkQuadClipper::clipQuad(const SkPoint srcPts[3], SkPoint dst[3]) {
50     bool reverse;
51 
52     // we need the data to be monotonically descending in Y
53     if (srcPts[0].fY > srcPts[2].fY) {
54         dst[0] = srcPts[2];
55         dst[1] = srcPts[1];
56         dst[2] = srcPts[0];
57         reverse = true;
58     } else {
59         memcpy(dst, srcPts, 3 * sizeof(SkPoint));
60         reverse = false;
61     }
62 
63     // are we completely above or below
64     const SkScalar ctop = fClip.fTop;
65     const SkScalar cbot = fClip.fBottom;
66     if (dst[2].fY <= ctop || dst[0].fY >= cbot) {
67         return false;
68     }
69 
70     SkScalar t;
71     SkPoint tmp[5]; // for SkChopQuadAt
72 
73     // are we partially above
74     if (dst[0].fY < ctop && chopMonoQuadAtY(dst, ctop, &t)) {
75         SkChopQuadAt(dst, tmp, t);
76         dst[0] = tmp[2];
77         dst[1] = tmp[3];
78     }
79 
80     // are we partially below
81     if (dst[2].fY > cbot && chopMonoQuadAtY(dst, cbot, &t)) {
82         SkChopQuadAt(dst, tmp, t);
83         dst[1] = tmp[1];
84         dst[2] = tmp[2];
85     }
86 
87     if (reverse) {
88         SkTSwap<SkPoint>(dst[0], dst[2]);
89     }
90     return true;
91 }
92 
93