SkEdgeClipper.cpp revision 181172d5642fce4a4c1d339a6e3c5e4a8079b11a
1909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/* 2909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * Copyright (C) 2009 The Android Open Source Project 3909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * 4909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * Licensed under the Apache License, Version 2.0 (the "License"); 5909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * you may not use this file except in compliance with the License. 6909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * You may obtain a copy of the License at 7909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * 8909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * http://www.apache.org/licenses/LICENSE-2.0 9909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * 10909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * Unless required by applicable law or agreed to in writing, software 11909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * distributed under the License is distributed on an "AS IS" BASIS, 12909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * See the License for the specific language governing permissions and 14909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * limitations under the License. 15909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 16909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 17909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkEdgeClipper.h" 18909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkGeometry.h" 19909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 20909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool quick_reject(const SkRect& bounds, const SkRect& clip) { 21909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return bounds.fTop >= clip.fBottom || bounds.fBottom <= clip.fTop; 22909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 23909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 24909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic inline void clamp_le(SkScalar& value, SkScalar max) { 25909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (value > max) { 26909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com value = max; 27909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 28909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 29909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 30909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic inline void clamp_ge(SkScalar& value, SkScalar min) { 31909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (value < min) { 32909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com value = min; 33909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 34909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 35909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 36909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/* src[] must be monotonic in Y. This routine copies src into dst, and sorts 37909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com it to be increasing in Y. If it had to reverse the order of the points, 38909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com it returns true, otherwise it returns false 39909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 40909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool sort_increasing_Y(SkPoint dst[], const SkPoint src[], int count) { 41909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // we need the data to be monotonically increasing in Y 42909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (src[0].fY > src[count - 1].fY) { 43909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < count; i++) { 44909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com dst[i] = src[count - i - 1]; 45909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 46909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return true; 47909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 48909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(dst, src, count * sizeof(SkPoint)); 49909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return false; 50909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 51909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 52909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 53909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 54909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 55909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoQuadAt(SkScalar c0, SkScalar c1, SkScalar c2, 56909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar target, SkScalar* t) { 57909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2 58909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * We solve for t, using quadratic equation, hence we have to rearrange 59909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com * our cooefficents to look like At^2 + Bt + C 60909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 61909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar A = c0 - c1 - c1 + c2; 62909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar B = 2*(c1 - c0); 63909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar C = c0 - target; 64909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 65909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar roots[2]; // we only expect one, but make room for 2 for safety 66909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int count = SkFindUnitQuadRoots(A, B, C, roots); 67909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (count) { 68909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *t = roots[0]; 69909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return true; 70909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 71909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return false; 72909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 73909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 74909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar* t) { 75909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return chopMonoQuadAt(pts[0].fY, pts[1].fY, pts[2].fY, y, t); 76909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 77909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 78909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoQuadAtX(SkPoint pts[3], SkScalar x, SkScalar* t) { 79909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return chopMonoQuadAt(pts[0].fX, pts[1].fX, pts[2].fX, x, t); 80909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 81909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 82909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// Modify pts[] in place so that it is clipped in Y to the clip rect 83909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void chop_quad_in_Y(SkPoint pts[3], const SkRect& clip) { 84909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar t; 85909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint tmp[5]; // for SkChopQuadAt 86909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 87909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially above 88909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fY < clip.fTop) { 89909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtY(pts, clip.fTop, &t)) { 90909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // take the 2nd chopped quad 91909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 92909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[2].fY, clip.fTop); 93909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[3].fY, clip.fTop); 94909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[2]; 95909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[3]; 96909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 97909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 98909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the top 99909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 3; i++) { 100909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[i].fY < clip.fTop) { 101909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[i].fY = clip.fTop; 102909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 103909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 104909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 105909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 106909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 107909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially below 108909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fY > clip.fBottom) { 109909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtY(pts, clip.fBottom, &t)) { 110909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 111909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[1].fY, clip.fBottom); 112909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[2].fY, clip.fBottom); 113909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[1]; 114909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[2]; 115909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 116909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 117909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the bottom 118909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 3; i++) { 119909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[i].fY > clip.fBottom) { 120909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[i].fY = clip.fBottom; 121909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 122909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 123909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 124909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 125909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 126909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 127909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// srcPts[] must be monotonic in X and Y 128909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) { 129909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint pts[3]; 130909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bool reverse = sort_increasing_Y(pts, srcPts, 3); 131909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 132909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we completely above or below 133909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { 134909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 135909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 136909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 137909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop so that pts is contained within clip in Y 138909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com chop_quad_in_Y(pts, clip); 139909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 140909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX > pts[2].fX) { 141909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkPoint>(pts[0], pts[2]); 142909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com reverse = !reverse; 143909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 144909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(pts[0].fX <= pts[1].fX); 145909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(pts[1].fX <= pts[2].fX); 146909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 147909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop in X has needed, and record the segments 148909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 149909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fX <= clip.fLeft) { // wholly to the left 150909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[2].fY, reverse); 151909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 152909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 153909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX >= clip.fRight) { // wholly to the right 154909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse); 155909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 156909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 157909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 158909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar t; 159909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint tmp[5]; // for SkChopQuadAt 160909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 161909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the left 162909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX < clip.fLeft) { 163909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtX(pts, clip.fLeft, &t)) { 164909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 165909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, tmp[0].fY, tmp[2].fY, reverse); 166909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[2].fX, clip.fLeft); 167909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[3].fX, clip.fLeft); 168909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[2]; 169909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[3]; 170909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 171909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 172909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the left 173909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[2].fY, reverse); 174181172d5642fce4a4c1d339a6e3c5e4a8079b11areed@android.com return; 175909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 176909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 177909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 178909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the right 179909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[2].fX > clip.fRight) { 180909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoQuadAtX(pts, clip.fRight, &t)) { 181909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopQuadAt(pts, tmp, t); 182909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[1].fX, clip.fRight); 183909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[2].fX, clip.fRight); 184909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendQuad(tmp, reverse); 185909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, tmp[2].fY, tmp[4].fY, reverse); 186909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 187909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoQuadAtY failed, then we may have hit inexact numerics 188909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the right 189909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); 190909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 191909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { // wholly inside the clip 192909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendQuad(pts, reverse); 193909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 194909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 195909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 196909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.combool SkEdgeClipper::clipQuad(const SkPoint srcPts[3], const SkRect& clip) { 197909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 198909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 199909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 200909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkRect bounds; 201909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bounds.set(srcPts, 3); 202909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 203909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (!quick_reject(bounds, clip)) { 204909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoY[5]; 205909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countY = SkChopQuadAtYExtrema(srcPts, monoY); 206909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int y = 0; y <= countY; y++) { 207909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoX[5]; 208909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countX = SkChopQuadAtXExtrema(&monoY[y * 2], monoX); 209909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int x = 0; x <= countX; x++) { 210909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->clipMonoQuad(&monoX[x * 2], clip); 211909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrVerb - fVerbs < kMaxVerbs); 212909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrPoint - fPoints <= kMaxPoints); 213909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 214909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 215909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 216909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 217909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb = SkPath::kDone_Verb; 218909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 219909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 220909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return SkPath::kDone_Verb != fVerbs[0]; 221909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 222909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 223909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 224909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 225909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic SkScalar eval_cubic_coeff(SkScalar A, SkScalar B, SkScalar C, 226909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar D, SkScalar t) { 227909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return SkScalarMulAdd(SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C), t, D); 228909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 229909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 230909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/* Given 4 cubic points (either Xs or Ys), and a target X or Y, compute the 231909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com t value such that cubic(t) = target 232909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com */ 233909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoCubicAt(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3, 234909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar target, SkScalar* t) { 235909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // SkASSERT(c0 <= c1 && c1 <= c2 && c2 <= c3); 236909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(c0 < target && target < c3); 237909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 238909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar D = c0; 239909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar A = c3 + 3*(c1 - c2) - c0; 240909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar B = 3*(c2 - c1 - c1 + c0); 241909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar C = 3*(c1 - c0); 242909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 243909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar minT = 0; 244909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar maxT = SK_Scalar1; 245909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 8; i++) { 246909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar mid = SkScalarAve(minT, maxT); 247909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar coord = eval_cubic_coeff(A, B, C, D, mid); 248909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (coord < target) { 249909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com minT = mid; 250909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 251909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com maxT = mid; 252909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 253909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 254909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *t = SkScalarAve(minT, maxT); 255909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return true; 256909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 257909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 258909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoCubicAtY(SkPoint pts[4], SkScalar y, SkScalar* t) { 259909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return chopMonoCubicAt(pts[0].fY, pts[1].fY, pts[2].fY, pts[3].fY, y, t); 260909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 261909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 262909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic bool chopMonoCubicAtX(SkPoint pts[4], SkScalar x, SkScalar* t) { 263909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return chopMonoCubicAt(pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX, x, t); 264909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 265909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 266909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// Modify pts[] in place so that it is clipped in Y to the clip rect 267909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { 268909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar t; 269909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint tmp[7]; // for SkChopCubicAt 270909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 271909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially above 272909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fY < clip.fTop) { 273909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoCubicAtY(pts, clip.fTop, &t)) { 274909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopCubicAt(pts, tmp, t); 275909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[3].fY, clip.fTop); 276909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[4].fY, clip.fTop); 277909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[5].fY, clip.fTop); 278909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[3]; 279909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[4]; 280909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[5]; 281909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 282909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoCubicAtY failed, then we may have hit inexact numerics 283909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the top 284909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 4; i++) { 285909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(pts[i].fY, clip.fTop); 286909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 287909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 288909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 289909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 290909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially below 291909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fY > clip.fBottom) { 292909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoCubicAtY(pts, clip.fBottom, &t)) { 293909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopCubicAt(pts, tmp, t); 294909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[1].fY, clip.fBottom); 295909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[2].fY, clip.fBottom); 296909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[3].fY, clip.fBottom); 297909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[1]; 298909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[2]; 299909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[3] = tmp[3]; 300909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 301909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoCubicAtY failed, then we may have hit inexact numerics 302909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the bottom 303909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 4; i++) { 304909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(pts[i].fY, clip.fBottom); 305909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 306909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 307909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 308909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 309909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 310909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com// srcPts[] must be monotonic in X and Y 311909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { 312909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint pts[4]; 313909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bool reverse = sort_increasing_Y(pts, src, 4); 314909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 315909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we completely above or below 316909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fY <= clip.fTop || pts[0].fY >= clip.fBottom) { 317909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 318909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 319909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 320909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop so that pts is contained within clip in Y 321909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com chop_cubic_in_Y(pts, clip); 322909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 323909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX > pts[3].fX) { 324909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkPoint>(pts[0], pts[3]); 325909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkPoint>(pts[1], pts[2]); 326909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com reverse = !reverse; 327909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 328909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 329909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // Now chop in X has needed, and record the segments 330909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 331909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fX <= clip.fLeft) { // wholly to the left 332909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse); 333909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 334909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 335909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX >= clip.fRight) { // wholly to the right 336909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); 337909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return; 338909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 339909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 340909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkScalar t; 341909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint tmp[7]; 342909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 343909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the left 344909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[0].fX < clip.fLeft) { 345909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoCubicAtX(pts, clip.fLeft, &t)) { 346909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopCubicAt(pts, tmp, t); 347909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); 348909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[3].fX, clip.fLeft); 349909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[4].fX, clip.fLeft); 350909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_ge(tmp[5].fX, clip.fLeft); 351909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[0] = tmp[3]; 352909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[1] = tmp[4]; 353909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com pts[2] = tmp[5]; 354909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 355909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonocubicAtY failed, then we may have hit inexact numerics 356909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the left 357909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fLeft, pts[0].fY, pts[3].fY, reverse); 358181172d5642fce4a4c1d339a6e3c5e4a8079b11areed@android.com return; 359909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 360909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 361909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 362909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // are we partially to the right 363909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (pts[3].fX > clip.fRight) { 364909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (chopMonoCubicAtX(pts, clip.fRight, &t)) { 365909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkChopCubicAt(pts, tmp, t); 366909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[1].fX, clip.fRight); 367909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[2].fX, clip.fRight); 368909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com clamp_le(tmp[3].fX, clip.fRight); 369909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendCubic(tmp, reverse); 370909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); 371909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 372909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // if chopMonoCubicAtX failed, then we may have hit inexact numerics 373909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // so we just clamp against the right 374909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendVLine(clip.fRight, pts[0].fY, pts[3].fY, reverse); 375909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 376909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { // wholly inside the clip 377909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->appendCubic(pts, reverse); 378909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 379909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 380909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 381909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.combool SkEdgeClipper::clipCubic(const SkPoint srcPts[4], const SkRect& clip) { 382909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 383909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 384909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 385909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkRect bounds; 386909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bounds.set(srcPts, 4); 387909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 388909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (!quick_reject(bounds, clip)) { 389909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoY[10]; 390909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countY = SkChopCubicAtYExtrema(srcPts, monoY); 391909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int y = 0; y <= countY; y++) { 392909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // sk_assert_monotonic_y(&monoY[y * 3], 4); 393909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoX[10]; 394909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int countX = SkChopCubicAtXExtrema(&monoY[y * 3], monoX); 395909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int x = 0; x <= countX; x++) { 396909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // sk_assert_monotonic_y(&monoX[x * 3], 4); 397909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // sk_assert_monotonic_x(&monoX[x * 3], 4); 398909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->clipMonoCubic(&monoX[x * 3], clip); 399909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrVerb - fVerbs < kMaxVerbs); 400909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(fCurrPoint - fPoints <= kMaxPoints); 401909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 402909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 403909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 404909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 405909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb = SkPath::kDone_Verb; 406909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint = fPoints; 407909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb = fVerbs; 408909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return SkPath::kDone_Verb != fVerbs[0]; 409909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 410909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 411909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 412909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 413909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::appendVLine(SkScalar x, SkScalar y0, SkScalar y1, 414909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com bool reverse) { 415909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb++ = SkPath::kLine_Verb; 416909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 417909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (reverse) { 418909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkTSwap<SkScalar>(y0, y1); 419909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 420909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[0].set(x, y0); 421909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[1].set(x, y1); 422909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 2; 423909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 424909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 425909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::appendQuad(const SkPoint pts[3], bool reverse) { 426909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb++ = SkPath::kQuad_Verb; 427909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 428909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (reverse) { 429909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[0] = pts[2]; 430909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[2] = pts[0]; 431909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 432909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[0] = pts[0]; 433909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[2] = pts[2]; 434909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 435909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[1] = pts[1]; 436909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 3; 437909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 438909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 439909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeClipper::appendCubic(const SkPoint pts[4], bool reverse) { 440909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com *fCurrVerb++ = SkPath::kCubic_Verb; 441909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 442909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (reverse) { 443909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < 4; i++) { 444909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint[i] = pts[3 - i]; 445909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 446909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 447909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(fCurrPoint, pts, 4 * sizeof(SkPoint)); 448909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 449909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 4; 450909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 451909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 452909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comSkPath::Verb SkEdgeClipper::next(SkPoint pts[]) { 453909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPath::Verb verb = *fCurrVerb; 454909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 455909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com switch (verb) { 456909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kLine_Verb: 457909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(pts, fCurrPoint, 2 * sizeof(SkPoint)); 458909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 2; 459909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb += 1; 460909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 461909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kQuad_Verb: 462909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(pts, fCurrPoint, 3 * sizeof(SkPoint)); 463909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 3; 464909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb += 1; 465909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 466909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kCubic_Verb: 467909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com memcpy(pts, fCurrPoint, 4 * sizeof(SkPoint)); 468909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrPoint += 4; 469909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fCurrVerb += 1; 470909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 471909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kDone_Verb: 472909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 473909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com default: 474909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(!"unexpected verb in quadclippper2 iter"); 475909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 476909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 477909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return verb; 478909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 479909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 480909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 481909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 482909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#ifdef SK_DEBUG 483909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void assert_monotonic(const SkScalar coord[], int count) { 484909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (coord[0] > coord[(count - 1) * 2]) { 485909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 1; i < count; i++) { 486909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(coord[2 * (i - 1)] >= coord[i * 2]); 487909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 488909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else if (coord[0] < coord[(count - 1) * 2]) { 489909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 1; i < count; i++) { 490909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(coord[2 * (i - 1)] <= coord[i * 2]); 491909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 492909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 493909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 1; i < count; i++) { 494909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkASSERT(coord[2 * (i - 1)] == coord[i * 2]); 495909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 496909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 497909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 498909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 499909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid sk_assert_monotonic_y(const SkPoint pts[], int count) { 500909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (count > 1) { 501909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com assert_monotonic(&pts[0].fY, count); 502909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 503909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 504909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 505909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid sk_assert_monotonic_x(const SkPoint pts[], int count) { 506909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (count > 1) { 507909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com assert_monotonic(&pts[0].fX, count); 508909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 509909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 510909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#endif 511