1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.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. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkEdgeBuilder.h" 9909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkPath.h" 10909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkEdge.h" 11909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkEdgeClipper.h" 12909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkLineClipper.h" 13909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com#include "SkGeometry.h" 14909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 15909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comtemplate <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) { 16909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return static_cast<T*>(alloc.allocThrow(sizeof(T))); 17909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 18909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 19909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 20909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 21c8d640b1788822a8697816b645c327383a1d1f20reed@google.comSkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) { 22c8d640b1788822a8697816b645c327383a1d1f20reed@google.com fEdgeList = NULL; 23c8d640b1788822a8697816b645c327383a1d1f20reed@google.com} 24c8d640b1788822a8697816b645c327383a1d1f20reed@google.com 25909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeBuilder::addLine(const SkPoint pts[]) { 26909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); 27b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com if (edge->setLine(pts[0], pts[1], fShiftUp)) { 28909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fList.push(edge); 29909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 30909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // TODO: unallocate edge from storage... 31909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 32909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 33909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 34909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeBuilder::addQuad(const SkPoint pts[]) { 35909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); 36909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (edge->setQuadratic(pts, fShiftUp)) { 37909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fList.push(edge); 38909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 39909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // TODO: unallocate edge from storage... 40909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 41909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 42909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 43909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeBuilder::addCubic(const SkPoint pts[]) { 44909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); 45909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (edge->setCubic(pts, NULL, fShiftUp)) { 46909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fList.push(edge); 47909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 48909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // TODO: unallocate edge from storage... 49909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 50909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 51909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 52909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comvoid SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) { 53909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint pts[4]; 54909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPath::Verb verb; 55909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 56909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) { 57909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com switch (verb) { 58909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kLine_Verb: 59909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addLine(pts); 60909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 61909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kQuad_Verb: 62909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addQuad(pts); 63909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 64909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kCubic_Verb: 65909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addCubic(pts); 66909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 67909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com default: 68909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 69909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 70909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 71909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 72909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 73909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com/////////////////////////////////////////////////////////////////////////////// 74909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 75909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comstatic void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { 76909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com dst->set(SkIntToScalar(src.fLeft >> shift), 77909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkIntToScalar(src.fTop >> shift), 78909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkIntToScalar(src.fRight >> shift), 79909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkIntToScalar(src.fBottom >> shift)); 80909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 81909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 82c8d640b1788822a8697816b645c327383a1d1f20reed@google.comint SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, 83c8d640b1788822a8697816b645c327383a1d1f20reed@google.com int shiftUp) { 84c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkPath::Iter iter(path, true); 85c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkPoint pts[4]; 86c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkPath::Verb verb; 87fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 88c8d640b1788822a8697816b645c327383a1d1f20reed@google.com int maxEdgeCount = path.countPoints(); 89c8d640b1788822a8697816b645c327383a1d1f20reed@google.com if (iclip) { 90c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since 91c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // we turn portions that are clipped out on the left/right into vertical 92c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // segments. 93c8d640b1788822a8697816b645c327383a1d1f20reed@google.com maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments; 94c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 95c8d640b1788822a8697816b645c327383a1d1f20reed@google.com size_t maxEdgeSize = maxEdgeCount * sizeof(SkEdge); 96c8d640b1788822a8697816b645c327383a1d1f20reed@google.com size_t maxEdgePtrSize = maxEdgeCount * sizeof(SkEdge*); 97c8d640b1788822a8697816b645c327383a1d1f20reed@google.com 98c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // lets store the edges and their pointers in the same block 99c8d640b1788822a8697816b645c327383a1d1f20reed@google.com char* storage = (char*)fAlloc.allocThrow(maxEdgeSize + maxEdgePtrSize); 100c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkEdge* edge = reinterpret_cast<SkEdge*>(storage); 101c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkEdge** edgePtr = reinterpret_cast<SkEdge**>(storage + maxEdgeSize); 102c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // Record the beginning of our pointers, so we can return them to the caller 103c8d640b1788822a8697816b645c327383a1d1f20reed@google.com fEdgeList = edgePtr; 104c8d640b1788822a8697816b645c327383a1d1f20reed@google.com 105c8d640b1788822a8697816b645c327383a1d1f20reed@google.com if (iclip) { 106c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkRect clip; 107c8d640b1788822a8697816b645c327383a1d1f20reed@google.com setShiftedClip(&clip, *iclip, shiftUp); 108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 109c8d640b1788822a8697816b645c327383a1d1f20reed@google.com while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 110c8d640b1788822a8697816b645c327383a1d1f20reed@google.com switch (verb) { 111c8d640b1788822a8697816b645c327383a1d1f20reed@google.com case SkPath::kMove_Verb: 112c8d640b1788822a8697816b645c327383a1d1f20reed@google.com case SkPath::kClose_Verb: 113c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // we ignore these, and just get the whole segment from 114c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // the corresponding line/quad/cubic verbs 115c8d640b1788822a8697816b645c327383a1d1f20reed@google.com break; 116c8d640b1788822a8697816b645c327383a1d1f20reed@google.com case SkPath::kLine_Verb: { 117c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkPoint lines[SkLineClipper::kMaxPoints]; 118c8d640b1788822a8697816b645c327383a1d1f20reed@google.com int lineCount = SkLineClipper::ClipLine(pts, clip, lines); 119c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments); 120c8d640b1788822a8697816b645c327383a1d1f20reed@google.com for (int i = 0; i < lineCount; i++) { 121b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { 122c8d640b1788822a8697816b645c327383a1d1f20reed@google.com *edgePtr++ = edge++; 123c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 124c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 125c8d640b1788822a8697816b645c327383a1d1f20reed@google.com break; 126c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 127c8d640b1788822a8697816b645c327383a1d1f20reed@google.com default: 128c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkDEBUGFAIL("unexpected verb"); 129c8d640b1788822a8697816b645c327383a1d1f20reed@google.com break; 130c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 131c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 132c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } else { 133c8d640b1788822a8697816b645c327383a1d1f20reed@google.com while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 134c8d640b1788822a8697816b645c327383a1d1f20reed@google.com switch (verb) { 135c8d640b1788822a8697816b645c327383a1d1f20reed@google.com case SkPath::kMove_Verb: 136c8d640b1788822a8697816b645c327383a1d1f20reed@google.com case SkPath::kClose_Verb: 137c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // we ignore these, and just get the whole segment from 138c8d640b1788822a8697816b645c327383a1d1f20reed@google.com // the corresponding line/quad/cubic verbs 139c8d640b1788822a8697816b645c327383a1d1f20reed@google.com break; 140c8d640b1788822a8697816b645c327383a1d1f20reed@google.com case SkPath::kLine_Verb: 141b6a2ba7b483a164a59ec0ded0795590329eab923reed@google.com if (edge->setLine(pts[0], pts[1], shiftUp)) { 142c8d640b1788822a8697816b645c327383a1d1f20reed@google.com *edgePtr++ = edge++; 143c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 144c8d640b1788822a8697816b645c327383a1d1f20reed@google.com break; 145c8d640b1788822a8697816b645c327383a1d1f20reed@google.com default: 146c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkDEBUGFAIL("unexpected verb"); 147c8d640b1788822a8697816b645c327383a1d1f20reed@google.com break; 148c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 149c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 150c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 151c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkASSERT((char*)edge <= (char*)fEdgeList); 152c8d640b1788822a8697816b645c327383a1d1f20reed@google.com SkASSERT(edgePtr - fEdgeList <= maxEdgeCount); 153a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org return SkToInt(edgePtr - fEdgeList); 154c8d640b1788822a8697816b645c327383a1d1f20reed@google.com} 155c8d640b1788822a8697816b645c327383a1d1f20reed@google.com 156277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.comstatic void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) { 157277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkPoint monoX[5]; 158277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com int n = SkChopQuadAtYExtrema(pts, monoX); 159277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com for (int i = 0; i <= n; i++) { 160277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com builder->addQuad(&monoX[i * 2]); 161277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com } 162277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com} 163277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com 164909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comint SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, 165909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int shiftUp) { 166909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fAlloc.reset(); 167909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fList.reset(); 168909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com fShiftUp = shiftUp; 169909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 170277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkScalar conicTol = SK_ScalarHalf * (1 << shiftUp); 17126da7f00aedba107d4b3e382283034e265db09b6skia.committer@gmail.com 172c8d640b1788822a8697816b645c327383a1d1f20reed@google.com if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { 173c8d640b1788822a8697816b645c327383a1d1f20reed@google.com return this->buildPoly(path, iclip, shiftUp); 174c8d640b1788822a8697816b645c327383a1d1f20reed@google.com } 175c8d640b1788822a8697816b645c327383a1d1f20reed@google.com 176909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPath::Iter iter(path, true); 177909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint pts[4]; 178909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPath::Verb verb; 179909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 180909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (iclip) { 181909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkRect clip; 182909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com setShiftedClip(&clip, *iclip, shiftUp); 183909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkEdgeClipper clipper; 184909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 1854a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 186909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com switch (verb) { 187909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kMove_Verb: 188909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kClose_Verb: 189909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // we ignore these, and just get the whole segment from 190909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // the corresponding line/quad/cubic verbs 191909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 192909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kLine_Verb: { 193909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint lines[SkLineClipper::kMaxPoints]; 194909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int lineCount = SkLineClipper::ClipLine(pts, clip, lines); 195909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i < lineCount; i++) { 196909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addLine(&lines[i]); 197909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 198909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 199909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 200909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kQuad_Verb: 201909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (clipper.clipQuad(pts, clip)) { 202909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addClipper(&clipper); 203909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 204909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 205277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com case SkPath::kConic_Verb: { 206277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com const int MAX_POW2 = 4; 207277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com const int MAX_QUADS = 1 << MAX_POW2; 208277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com const int MAX_QUAD_PTS = 1 + 2 * MAX_QUADS; 209277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkPoint storage[MAX_QUAD_PTS]; 210277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com 211277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkConic conic; 212277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com conic.set(pts, iter.conicWeight()); 213277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com int pow2 = conic.computeQuadPOW2(conicTol); 214277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com pow2 = SkMin32(pow2, MAX_POW2); 215277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com int quadCount = conic.chopIntoQuadsPOW2(storage, pow2); 216277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkASSERT(quadCount <= MAX_QUADS); 217277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com for (int i = 0; i < quadCount; ++i) { 218277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com if (clipper.clipQuad(&storage[i * 2], clip)) { 219277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com this->addClipper(&clipper); 220277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com } 221277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com } 222277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com } break; 223909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kCubic_Verb: 224909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com if (clipper.clipCubic(pts, clip)) { 225909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addClipper(&clipper); 226909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 227909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 228909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com default: 2290c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected verb"); 230909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 231909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 232909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 233909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } else { 2344a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 235909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com switch (verb) { 236909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kMove_Verb: 237909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kClose_Verb: 238909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // we ignore these, and just get the whole segment from 239909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com // the corresponding line/quad/cubic verbs 240909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 241909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kLine_Verb: 242909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addLine(pts); 243909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 244909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kQuad_Verb: { 245277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com handle_quad(this, pts); 246909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 247909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 248277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com case SkPath::kConic_Verb: { 249277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com const int MAX_POW2 = 4; 250277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com const int MAX_QUADS = 1 << MAX_POW2; 251277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com const int MAX_QUAD_PTS = 1 + 2 * MAX_QUADS; 252277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkPoint storage[MAX_QUAD_PTS]; 25326da7f00aedba107d4b3e382283034e265db09b6skia.committer@gmail.com 254277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkConic conic; 255277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com conic.set(pts, iter.conicWeight()); 256277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com int pow2 = conic.computeQuadPOW2(conicTol); 257277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com pow2 = SkMin32(pow2, MAX_POW2); 258277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com int quadCount = conic.chopIntoQuadsPOW2(storage, pow2); 259277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkASSERT(quadCount <= MAX_QUADS); 260277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com for (int i = 0; i < quadCount; ++i) { 261277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com handle_quad(this, &storage[i * 2]); 262277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com } 263277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com } break; 264909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com case SkPath::kCubic_Verb: { 265909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkPoint monoY[10]; 266909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int n = SkChopCubicAtYExtrema(pts, monoY); 267909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com for (int i = 0; i <= n; i++) { 268909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com this->addCubic(&monoY[i * 3]); 269909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 270909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 271909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 272909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com default: 2730c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected verb"); 274909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com break; 275909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 276909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 277909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com } 278c8d640b1788822a8697816b645c327383a1d1f20reed@google.com fEdgeList = fList.begin(); 279909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com return fList.count(); 280909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com} 281