SkEdgeBuilder.cpp revision b6a2ba7b483a164a59ec0ded0795590329eab923
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;
87c8d640b1788822a8697816b645c327383a1d1f20reed@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);
108c8d640b1788822a8697816b645c327383a1d1f20reed@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);
153c8d640b1788822a8697816b645c327383a1d1f20reed@google.com    return edgePtr - fEdgeList;
154c8d640b1788822a8697816b645c327383a1d1f20reed@google.com}
155c8d640b1788822a8697816b645c327383a1d1f20reed@google.com
156909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.comint SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip,
157909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                         int shiftUp) {
158909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    fAlloc.reset();
159909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    fList.reset();
160909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    fShiftUp = shiftUp;
161909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com
162c8d640b1788822a8697816b645c327383a1d1f20reed@google.com    if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) {
163c8d640b1788822a8697816b645c327383a1d1f20reed@google.com        return this->buildPoly(path, iclip, shiftUp);
164c8d640b1788822a8697816b645c327383a1d1f20reed@google.com    }
165c8d640b1788822a8697816b645c327383a1d1f20reed@google.com
166909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    SkPath::Iter    iter(path, true);
167909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    SkPoint         pts[4];
168909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    SkPath::Verb    verb;
169909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com
170909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    if (iclip) {
171909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com        SkRect clip;
172909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com        setShiftedClip(&clip, *iclip, shiftUp);
173909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com        SkEdgeClipper clipper;
174909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com
1754a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
176909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com            switch (verb) {
177909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kMove_Verb:
178909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kClose_Verb:
179909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    // we ignore these, and just get the whole segment from
180909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    // the corresponding line/quad/cubic verbs
181909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
182909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kLine_Verb: {
183909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    SkPoint lines[SkLineClipper::kMaxPoints];
184909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    int lineCount = SkLineClipper::ClipLine(pts, clip, lines);
185909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    for (int i = 0; i < lineCount; i++) {
186909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                        this->addLine(&lines[i]);
187909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    }
188909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
189909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                }
190909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kQuad_Verb:
191909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    if (clipper.clipQuad(pts, clip)) {
192909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                        this->addClipper(&clipper);
193909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    }
194909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
195909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kCubic_Verb:
196909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    if (clipper.clipCubic(pts, clip)) {
197909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                        this->addClipper(&clipper);
198909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    }
199909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
200909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                default:
2010c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com                    SkDEBUGFAIL("unexpected verb");
202909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
203909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com            }
204909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com        }
205909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    } else {
2064a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com        while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) {
207909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com            switch (verb) {
208909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kMove_Verb:
209909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kClose_Verb:
210909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    // we ignore these, and just get the whole segment from
211909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    // the corresponding line/quad/cubic verbs
212909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
213909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kLine_Verb:
214909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    this->addLine(pts);
215909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
216909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kQuad_Verb: {
217909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    SkPoint monoX[5];
218909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    int n = SkChopQuadAtYExtrema(pts, monoX);
219909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    for (int i = 0; i <= n; i++) {
220909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                        this->addQuad(&monoX[i * 2]);
221909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    }
222909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
223909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                }
224909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                case SkPath::kCubic_Verb: {
225909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    SkPoint monoY[10];
226909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    int n = SkChopCubicAtYExtrema(pts, monoY);
227909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    for (int i = 0; i <= n; i++) {
228909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                        this->addCubic(&monoY[i * 3]);
229909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    }
230909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
231909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                }
232909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                default:
2330c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com                    SkDEBUGFAIL("unexpected verb");
234909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com                    break;
235909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com            }
236909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com        }
237909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    }
238c8d640b1788822a8697816b645c327383a1d1f20reed@google.com    fEdgeList = fList.begin();
239909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com    return fList.count();
240909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com}
241909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com
242