SkEdgeClipper.cpp revision 7d173403f47bb85cfd5c42b69c734668e25e47f9
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2009 The Android Open Source Project 4909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 8909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 10909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkEdgeClipper.h" 11909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkGeometry.h" 12909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 13909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool quick_reject(const SkRect& bounds, const SkRect& clip) { 14909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return bounds.fTop >= clip.fBottom || bounds.fBottom <= clip.fTop; 15909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 16909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 17909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic inline void clamp_le(SkScalar& value, SkScalar max) { 18909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (value > max) { 19909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com value = max; 20909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 21909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 22909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 23909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic inline void clamp_ge(SkScalar& value, SkScalar min) { 24909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (value < min) { 25909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com value = min; 26909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 27909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 28909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 29909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/* src[] must be monotonic in Y. This routine copies src into dst, and sorts 30909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com it to be increasing in Y. If it had to reverse the order of the points, 31909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com it returns true, otherwise it returns false 32909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 33909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool sort_increasing_Y(SkPoint dst[], const SkPoint src[], int count) { 34909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // we need the data to be monotonically increasing in Y 35909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (src[0].fY > src[count - 1].fY) { 36909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < count; i++) { 37909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com dst[i] = src[count - i - 1]; 38909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 39909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return true; 40909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 41909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(dst, src, count * sizeof(SkPoint)); 42909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return false; 43909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 44909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 45909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 46909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 47909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 48909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoQuadAt(SkScalar c0, SkScalar c1, SkScalar c2, 49909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar target, SkScalar* t) { 50909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2 51909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * We solve for t, using quadratic equation, hence we have to rearrange 52909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * our cooefficents to look like At^2 + Bt + C 53909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 54909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar A = c0 - c1 - c1 + c2; 55909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar B = 2*(c1 - c0); 56909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar C = c0 - target; 57fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 58909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar roots[2]; // we only expect one, but make room for 2 for safety 59909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int count = SkFindUnitQuadRoots(A, B, C, roots); 60909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (count) { 61909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *t = roots[0]; 62909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return true; 63909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 64909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return false; 65909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 66909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 67909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar* t) { 68909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return chopMonoQuadAt(pts[0].fY, pts[1].fY, pts[2].fY, y, t); 69909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 70909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 71909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoQuadAtX(SkPoint pts[3], SkScalar x, SkScalar* t) { 72909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return chopMonoQuadAt(pts[0].fX, pts[1].fX, pts[2].fX, x, t); 73909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 74909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 75909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// Modify pts[] in place so that it is clipped in Y to the clip rect 76909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void chop_quad_in_Y(SkPoint pts[3], const SkRect& clip) { 77909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar t; 78909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint tmp[5]; // for SkChopQuadAt 79909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 80909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially above 81909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fY < clip.fTop) { 82909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtY(pts, clip.fTop, &t)) { 83909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // take the 2nd chopped quad 84909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 85e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com // clamp to clean up imprecise numerics in the chop 86e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com tmp[2].fY = clip.fTop; 87909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[3].fY, clip.fTop); 88e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com 89909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[2]; 90909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[3]; 91909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 92909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 93909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the top 94909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 3; i++) { 95909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[i].fY < clip.fTop) { 96909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[i].fY = clip.fTop; 97909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 98909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 99909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 100909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 102909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially below 103909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fY > clip.fBottom) { 104909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtY(pts, clip.fBottom, &t)) { 105909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 106e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com // clamp to clean up imprecise numerics in the chop 107909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[1].fY, clip.fBottom); 108e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com tmp[2].fY = clip.fBottom; 109e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com 110909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[1]; 111909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[2]; 112909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 113909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 114909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the bottom 115909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 3; i++) { 116909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[i].fY > clip.fBottom) { 117909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[i].fY = clip.fBottom; 118909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 119909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 120909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 121909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 122909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 123909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 124909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// srcPts[] must be monotonic in X and Y 125909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) { 126909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint pts[3]; 127909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bool reverse = sort_increasing_Y(pts, srcPts, 3); 128909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 129909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we completely above or below 130909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { 131909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 132909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 133fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 134909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop so that pts is contained within clip in Y 135909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com chop_quad_in_Y(pts, clip); 136909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 137909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX > pts[2].fX) { 138909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkPoint>(pts[0], pts[2]); 139909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com reverse = !reverse; 140909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 141909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(pts[0].fX <= pts[1].fX); 142909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(pts[1].fX <= pts[2].fX); 143909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 144909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop in X has needed, and record the segments 145909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 146909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fX <= clip.fLeft) { // wholly to the left 147909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[2].fY, reverse); 148909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 149909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 150909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX >= clip.fRight) { // wholly to the right 15131223e0cb74f47f63b094520a9830c525b72fe87reed if (!this->canCullToTheRight()) { 15231223e0cb74f47f63b094520a9830c525b72fe87reed this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse); 15331223e0cb74f47f63b094520a9830c525b72fe87reed } 154909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 155909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 156909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 157909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar t; 158909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint tmp[5]; // for SkChopQuadAt 159909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 160909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the left 161909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX < clip.fLeft) { 162909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtX(pts, clip.fLeft, &t)) { 163909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 164909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, tmp[0].fY, tmp[2].fY, reverse); 165e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com // clamp to clean up imprecise numerics in the chop 166e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com tmp[2].fX = clip.fLeft; 167909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[3].fX, clip.fLeft); 168e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com 169909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[2]; 170909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[3]; 171909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 172909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 173909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the left 174909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[2].fY, reverse); 175181172d5642fce4a4c1d339a6e3c5e4a8079b11areed@android.com return; 176909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 177909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 178fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 179909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the right 180909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fX > clip.fRight) { 181909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtX(pts, clip.fRight, &t)) { 182909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 183e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com // clamp to clean up imprecise numerics in the chop 184909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[1].fX, clip.fRight); 185e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com tmp[2].fX = clip.fRight; 186e01403096cc8fc15217d7de08c476c2056d8b9d0reed@google.com 187909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendQuad(tmp, reverse); 188909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, tmp[2].fY, tmp[4].fY, reverse); 189909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 190909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 191909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the right 1923f0785e0c675c906c0bd704702e122149c5ee951reed@android.com this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse); 193909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 194909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { // wholly inside the clip 195909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendQuad(pts, reverse); 196909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 197909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 198909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 199909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.combool SkEdgeClipper::clipQuad(const SkPoint srcPts[3], const SkRect& clip) { 200909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 201909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 202909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 203909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkRect bounds; 204909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bounds.set(srcPts, 3); 205fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 206909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (!quick_reject(bounds, clip)) { 207909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoY[5]; 208909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countY = SkChopQuadAtYExtrema(srcPts, monoY); 209909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int y = 0; y <= countY; y++) { 210909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoX[5]; 211909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countX = SkChopQuadAtXExtrema(&monoY[y * 2], monoX); 212909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int x = 0; x <= countX; x++) { 213909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->clipMonoQuad(&monoX[x * 2], clip); 214909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrVerb - fVerbs < kMaxVerbs); 215909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrPoint - fPoints <= kMaxPoints); 216909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 217909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 218909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 219909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 220909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb = SkPath::kDone_Verb; 221909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 222909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 223909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return SkPath::kDone_Verb != fVerbs[0]; 224909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 225909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 226909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 227909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 228909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// Modify pts[] in place so that it is clipped in Y to the clip rect 229909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { 230fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 231909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially above 232909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fY < clip.fTop) { 233dc3088570f945ed0ede84f0af0016eedc267dda3reed SkPoint tmp[7]; 234dc3088570f945ed0ede84f0af0016eedc267dda3reed if (SkChopMonoCubicAtY(pts, clip.fTop, tmp)) { 235dc3088570f945ed0ede84f0af0016eedc267dda3reed // tmp[3, 4].fY should all be to the below clip.fTop. 23603ca64b832819564d958b70ee27a2134ff88c9c6reed@google.com // Since we can't trust the numerics of 2376da3d1757cfee75c25a86b580834dc49d8b53f05reed@google.com // the chopper, we force those conditions now 23815161620bee33efcb706685486c9ce0fb51a72bbreed@android.com tmp[3].fY = clip.fTop; 239a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com clamp_ge(tmp[4].fY, clip.fTop); 2406da3d1757cfee75c25a86b580834dc49d8b53f05reed@google.com 241909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[3]; 242909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[4]; 243909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[5]; 244909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 245909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoCubicAtY failed, then we may have hit inexact numerics 246909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the top 247909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 4; i++) { 248909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(pts[i].fY, clip.fTop); 249909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 250909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 251909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 252fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 253909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially below 254909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fY > clip.fBottom) { 255dc3088570f945ed0ede84f0af0016eedc267dda3reed SkPoint tmp[7]; 256dc3088570f945ed0ede84f0af0016eedc267dda3reed if (SkChopMonoCubicAtY(pts, clip.fBottom, tmp)) { 257a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com tmp[3].fY = clip.fBottom; 258909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[2].fY, clip.fBottom); 259a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com 260909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[1]; 261909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[2]; 262909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[3] = tmp[3]; 263909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 264909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoCubicAtY failed, then we may have hit inexact numerics 265909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the bottom 266909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 4; i++) { 267909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(pts[i].fY, clip.fBottom); 268909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 269909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 270909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 271909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 272909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 2737d173403f47bb85cfd5c42b69c734668e25e47f9caryclarkstatic void chop_mono_cubic_at_x(SkPoint pts[4], SkScalar x, SkPoint tmp[7]) { 2747d173403f47bb85cfd5c42b69c734668e25e47f9caryclark if (SkChopMonoCubicAtX(pts, x, tmp)) { 2757d173403f47bb85cfd5c42b69c734668e25e47f9caryclark return; 2767d173403f47bb85cfd5c42b69c734668e25e47f9caryclark } 2777d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar t = 0.5f; 2787d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar lastT; 2797d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar bestT SK_INIT_TO_AVOID_WARNING; 2807d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar step = 0.25f; 2817d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar D = pts[0].fX; 2827d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar A = pts[3].fX + 3*(pts[1].fX - pts[2].fX) - D; 2837d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar B = 3*(pts[2].fX - pts[1].fX - pts[1].fX + D); 2847d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar C = 3*(pts[1].fX - D); 2857d173403f47bb85cfd5c42b69c734668e25e47f9caryclark x -= D; 2867d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar closest = SK_ScalarMax; 2877d173403f47bb85cfd5c42b69c734668e25e47f9caryclark do { 2887d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar loc = ((A * t + B) * t + C) * t; 2897d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkScalar dist = SkScalarAbs(loc - x); 2907d173403f47bb85cfd5c42b69c734668e25e47f9caryclark if (closest > dist) { 2917d173403f47bb85cfd5c42b69c734668e25e47f9caryclark closest = dist; 2927d173403f47bb85cfd5c42b69c734668e25e47f9caryclark bestT = t; 2937d173403f47bb85cfd5c42b69c734668e25e47f9caryclark } 2947d173403f47bb85cfd5c42b69c734668e25e47f9caryclark lastT = t; 2957d173403f47bb85cfd5c42b69c734668e25e47f9caryclark t += loc < x ? step : -step; 2967d173403f47bb85cfd5c42b69c734668e25e47f9caryclark step *= 0.5f; 2977d173403f47bb85cfd5c42b69c734668e25e47f9caryclark } while (closest > 0.25f && lastT != t); 2987d173403f47bb85cfd5c42b69c734668e25e47f9caryclark SkChopCubicAt(pts, tmp, bestT); 2997d173403f47bb85cfd5c42b69c734668e25e47f9caryclark} 3007d173403f47bb85cfd5c42b69c734668e25e47f9caryclark 301909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// srcPts[] must be monotonic in X and Y 302909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { 303909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint pts[4]; 304909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bool reverse = sort_increasing_Y(pts, src, 4); 305fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 306909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we completely above or below 307909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { 308909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 309909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 31015161620bee33efcb706685486c9ce0fb51a72bbreed@android.com 311909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop so that pts is contained within clip in Y 312909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com chop_cubic_in_Y(pts, clip); 31315161620bee33efcb706685486c9ce0fb51a72bbreed@android.com 314909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX > pts[3].fX) { 315909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkPoint>(pts[0], pts[3]); 316909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkPoint>(pts[1], pts[2]); 317909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com reverse = !reverse; 318909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 320909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop in X has needed, and record the segments 321fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 322909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fX <= clip.fLeft) { // wholly to the left 323909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse); 324909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 325909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 326909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX >= clip.fRight) { // wholly to the right 32731223e0cb74f47f63b094520a9830c525b72fe87reed if (!this->canCullToTheRight()) { 32831223e0cb74f47f63b094520a9830c525b72fe87reed this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); 32931223e0cb74f47f63b094520a9830c525b72fe87reed } 330909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 331909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 3326da3d1757cfee75c25a86b580834dc49d8b53f05reed@google.com 333909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the left 334909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX < clip.fLeft) { 335dc3088570f945ed0ede84f0af0016eedc267dda3reed SkPoint tmp[7]; 3367d173403f47bb85cfd5c42b69c734668e25e47f9caryclark chop_mono_cubic_at_x(pts, clip.fLeft, tmp); 3377d173403f47bb85cfd5c42b69c734668e25e47f9caryclark this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); 3387d173403f47bb85cfd5c42b69c734668e25e47f9caryclark 3397d173403f47bb85cfd5c42b69c734668e25e47f9caryclark // tmp[3, 4].fX should all be to the right of clip.fLeft. 3407d173403f47bb85cfd5c42b69c734668e25e47f9caryclark // Since we can't trust the numerics of 3417d173403f47bb85cfd5c42b69c734668e25e47f9caryclark // the chopper, we force those conditions now 3427d173403f47bb85cfd5c42b69c734668e25e47f9caryclark tmp[3].fX = clip.fLeft; 3437d173403f47bb85cfd5c42b69c734668e25e47f9caryclark clamp_ge(tmp[4].fX, clip.fLeft); 3447d173403f47bb85cfd5c42b69c734668e25e47f9caryclark 3457d173403f47bb85cfd5c42b69c734668e25e47f9caryclark pts[0] = tmp[3]; 3467d173403f47bb85cfd5c42b69c734668e25e47f9caryclark pts[1] = tmp[4]; 3477d173403f47bb85cfd5c42b69c734668e25e47f9caryclark pts[2] = tmp[5]; 348909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 349fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 350909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the right 351909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fX > clip.fRight) { 352dc3088570f945ed0ede84f0af0016eedc267dda3reed SkPoint tmp[7]; 3537d173403f47bb85cfd5c42b69c734668e25e47f9caryclark chop_mono_cubic_at_x(pts, clip.fRight, tmp); 3547d173403f47bb85cfd5c42b69c734668e25e47f9caryclark tmp[3].fX = clip.fRight; 3557d173403f47bb85cfd5c42b69c734668e25e47f9caryclark clamp_le(tmp[2].fX, clip.fRight); 356a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com 3577d173403f47bb85cfd5c42b69c734668e25e47f9caryclark this->appendCubic(tmp, reverse); 3587d173403f47bb85cfd5c42b69c734668e25e47f9caryclark this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); 359909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { // wholly inside the clip 360909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendCubic(pts, reverse); 361909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 362909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 363909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 364909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.combool SkEdgeClipper::clipCubic(const SkPoint srcPts[4], const SkRect& clip) { 365909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 366909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 367fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 368909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkRect bounds; 369909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bounds.set(srcPts, 4); 370fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 371909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (!quick_reject(bounds, clip)) { 372909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoY[10]; 373909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countY = SkChopCubicAtYExtrema(srcPts, monoY); 374909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int y = 0; y <= countY; y++) { 375909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoX[10]; 376909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countX = SkChopCubicAtXExtrema(&monoY[y * 3], monoX); 377909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int x = 0; x <= countX; x++) { 378909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->clipMonoCubic(&monoX[x * 3], clip); 379909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrVerb - fVerbs < kMaxVerbs); 380909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrPoint - fPoints <= kMaxPoints); 381909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 382909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 383909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 384fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 385909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb = SkPath::kDone_Verb; 386909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 387909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 388909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return SkPath::kDone_Verb != fVerbs[0]; 389909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 390909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 391909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 392909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 393909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::appendVLine(SkScalar x, SkScalar y0, SkScalar y1, 394909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bool reverse) { 395909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb++ = SkPath::kLine_Verb; 396fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 397909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (reverse) { 398909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkScalar>(y0, y1); 399909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 400909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[0].set(x, y0); 401909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[1].set(x, y1); 402909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 2; 403909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 404909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 405909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::appendQuad(const SkPoint pts[3], bool reverse) { 406909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb++ = SkPath::kQuad_Verb; 407fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 408909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (reverse) { 409909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[0] = pts[2]; 410909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[2] = pts[0]; 411909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 412909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[0] = pts[0]; 413909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[2] = pts[2]; 414909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 415909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[1] = pts[1]; 416909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 3; 417909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 418909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 419909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::appendCubic(const SkPoint pts[4], bool reverse) { 420909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb++ = SkPath::kCubic_Verb; 421fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 422909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (reverse) { 423909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 4; i++) { 424909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[i] = pts[3 - i]; 425909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 426909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 427909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(fCurrPoint, pts, 4 * sizeof(SkPoint)); 428909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 429909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 4; 430909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 431909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 432909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comSkPath::Verb SkEdgeClipper::next(SkPoint pts[]) { 433909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPath::Verb verb = *fCurrVerb; 434909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 435909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com switch (verb) { 436909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kLine_Verb: 437909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(pts, fCurrPoint, 2 * sizeof(SkPoint)); 438909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 2; 439909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb += 1; 440909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 441909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kQuad_Verb: 442909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(pts, fCurrPoint, 3 * sizeof(SkPoint)); 443909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 3; 444909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb += 1; 445909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 446909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kCubic_Verb: 447909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(pts, fCurrPoint, 4 * sizeof(SkPoint)); 448909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 4; 449909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb += 1; 450909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 451909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kDone_Verb: 452909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 453909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com default: 4540c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected verb in quadclippper2 iter"); 455909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 456909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 457909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return verb; 458909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 459909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 460909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 461909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 462909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#ifdef SK_DEBUG 463909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void assert_monotonic(const SkScalar coord[], int count) { 464909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (coord[0] > coord[(count - 1) * 2]) { 465909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 1; i < count; i++) { 466909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(coord[2 * (i - 1)] >= coord[i * 2]); 467909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 468909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else if (coord[0] < coord[(count - 1) * 2]) { 469909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 1; i < count; i++) { 470909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(coord[2 * (i - 1)] <= coord[i * 2]); 471909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 472909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 473909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 1; i < count; i++) { 474909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(coord[2 * (i - 1)] == coord[i * 2]); 475909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 476909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 477909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 478909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 479909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid sk_assert_monotonic_y(const SkPoint pts[], int count) { 480909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (count > 1) { 481909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com assert_monotonic(&pts[0].fY, count); 482909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 483909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 484909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 485909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid sk_assert_monotonic_x(const SkPoint pts[], int count) { 486909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (count > 1) { 487909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com assert_monotonic(&pts[0].fX, count); 488909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 489909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 490909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#endif 491