11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
88e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkEdgeBuilder.h"
98e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkPath.h"
108e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkEdge.h"
118e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkEdgeClipper.h"
128e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkLineClipper.h"
138e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkGeometry.h"
148e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
158e048c19870a898cecdde3b3c0d2d512e6f372c0Mike ReedSkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) {}
168e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
178e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedtemplate <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) {
188e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    return static_cast<T*>(alloc.allocThrow(sizeof(T)));
198e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
208e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
218e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed///////////////////////////////////////////////////////////////////////////////
228e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
238e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedvoid SkEdgeBuilder::addLine(const SkPoint pts[]) {
248e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc);
258e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    if (edge->setLine(pts[0], pts[1], NULL, fShiftUp)) {
268e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        fList.push(edge);
278e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    } else {
288e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        // TODO: unallocate edge from storage...
298e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    }
308e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
318e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
328e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedvoid SkEdgeBuilder::addQuad(const SkPoint pts[]) {
338e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc);
348e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    if (edge->setQuadratic(pts, fShiftUp)) {
358e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        fList.push(edge);
368e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    } else {
378e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        // TODO: unallocate edge from storage...
388e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    }
398e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
408e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
418e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedvoid SkEdgeBuilder::addCubic(const SkPoint pts[]) {
428e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc);
438e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    if (edge->setCubic(pts, NULL, fShiftUp)) {
448e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        fList.push(edge);
458e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    } else {
468e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        // TODO: unallocate edge from storage...
478e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    }
488e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
498e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
508e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedvoid SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) {
518e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkPoint      pts[4];
528e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkPath::Verb verb;
538e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
548e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) {
558e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        switch (verb) {
568e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            case SkPath::kLine_Verb:
578e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                this->addLine(pts);
588e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                break;
598e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            case SkPath::kQuad_Verb:
608e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                this->addQuad(pts);
618e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                break;
628e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            case SkPath::kCubic_Verb:
638e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                this->addCubic(pts);
648e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                break;
658e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            default:
668e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                break;
678e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        }
688e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    }
698e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
708e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
718e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed///////////////////////////////////////////////////////////////////////////////
728e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
738e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedstatic void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) {
748e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    dst->set(SkIntToScalar(src.fLeft >> shift),
758e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed             SkIntToScalar(src.fTop >> shift),
768e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed             SkIntToScalar(src.fRight >> shift),
778e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed             SkIntToScalar(src.fBottom >> shift));
788e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
798e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
808e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reedint SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip,
818e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                         int shiftUp) {
828e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    fAlloc.reset();
838e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    fList.reset();
848e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    fShiftUp = shiftUp;
858e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
868e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkPath::Iter    iter(path, true);
878e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkPoint         pts[4];
888e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    SkPath::Verb    verb;
898e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
908e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    if (iclip) {
918e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        SkRect clip;
928e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        setShiftedClip(&clip, *iclip, shiftUp);
938e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        SkEdgeClipper clipper;
948e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
958e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
968e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            switch (verb) {
978e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kMove_Verb:
988e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kClose_Verb:
998e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    // we ignore these, and just get the whole segment from
1008e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    // the corresponding line/quad/cubic verbs
1018e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1028e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kLine_Verb: {
1038e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    SkPoint lines[SkLineClipper::kMaxPoints];
1048e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    int lineCount = SkLineClipper::ClipLine(pts, clip, lines);
1058e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    for (int i = 0; i < lineCount; i++) {
1068e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                        this->addLine(&lines[i]);
1078e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    }
1088e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1098e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                }
1108e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kQuad_Verb:
1118e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    if (clipper.clipQuad(pts, clip)) {
1128e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                        this->addClipper(&clipper);
1138e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    }
1148e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1158e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kCubic_Verb:
1168e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    if (clipper.clipCubic(pts, clip)) {
1178e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                        this->addClipper(&clipper);
1188e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    }
1198e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1208e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                default:
1211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    SkDEBUGFAIL("unexpected verb");
1228e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1238e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            }
1248e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        }
1258e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    } else {
1268e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1278e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            switch (verb) {
1288e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kMove_Verb:
1298e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kClose_Verb:
1308e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    // we ignore these, and just get the whole segment from
1318e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    // the corresponding line/quad/cubic verbs
1328e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1338e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kLine_Verb:
1348e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    this->addLine(pts);
1358e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1368e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kQuad_Verb: {
1378e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    SkPoint monoX[5];
1388e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    int n = SkChopQuadAtYExtrema(pts, monoX);
1398e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    for (int i = 0; i <= n; i++) {
1408e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                        this->addQuad(&monoX[i * 2]);
1418e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    }
1428e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1438e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                }
1448e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                case SkPath::kCubic_Verb: {
1458e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    SkPoint monoY[10];
1468e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    int n = SkChopCubicAtYExtrema(pts, monoY);
1478e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    for (int i = 0; i <= n; i++) {
1488e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                        this->addCubic(&monoY[i * 3]);
1498e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    }
1508e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1518e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                }
1528e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                default:
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    SkDEBUGFAIL("unexpected verb");
1548e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed                    break;
1558e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed            }
1568e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed        }
1578e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    }
1588e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed    return fList.count();
1598e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed}
1608e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
1618e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed
162