1#include "SkEdgeBuilder.h" 2#include "SkPath.h" 3#include "SkEdge.h" 4#include "SkEdgeClipper.h" 5#include "SkLineClipper.h" 6#include "SkGeometry.h" 7 8SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) {} 9 10template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) { 11 return static_cast<T*>(alloc.allocThrow(sizeof(T))); 12} 13 14/////////////////////////////////////////////////////////////////////////////// 15 16void SkEdgeBuilder::addLine(const SkPoint pts[]) { 17 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); 18 if (edge->setLine(pts[0], pts[1], NULL, fShiftUp)) { 19 fList.push(edge); 20 } else { 21 // TODO: unallocate edge from storage... 22 } 23} 24 25void SkEdgeBuilder::addQuad(const SkPoint pts[]) { 26 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); 27 if (edge->setQuadratic(pts, fShiftUp)) { 28 fList.push(edge); 29 } else { 30 // TODO: unallocate edge from storage... 31 } 32} 33 34void SkEdgeBuilder::addCubic(const SkPoint pts[]) { 35 SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); 36 if (edge->setCubic(pts, NULL, fShiftUp)) { 37 fList.push(edge); 38 } else { 39 // TODO: unallocate edge from storage... 40 } 41} 42 43void SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) { 44 SkPoint pts[4]; 45 SkPath::Verb verb; 46 47 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) { 48 switch (verb) { 49 case SkPath::kLine_Verb: 50 this->addLine(pts); 51 break; 52 case SkPath::kQuad_Verb: 53 this->addQuad(pts); 54 break; 55 case SkPath::kCubic_Verb: 56 this->addCubic(pts); 57 break; 58 default: 59 break; 60 } 61 } 62} 63 64/////////////////////////////////////////////////////////////////////////////// 65 66static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { 67 dst->set(SkIntToScalar(src.fLeft >> shift), 68 SkIntToScalar(src.fTop >> shift), 69 SkIntToScalar(src.fRight >> shift), 70 SkIntToScalar(src.fBottom >> shift)); 71} 72 73int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, 74 int shiftUp) { 75 fAlloc.reset(); 76 fList.reset(); 77 fShiftUp = shiftUp; 78 79 SkPath::Iter iter(path, true); 80 SkPoint pts[4]; 81 SkPath::Verb verb; 82 83 if (iclip) { 84 SkRect clip; 85 setShiftedClip(&clip, *iclip, shiftUp); 86 SkEdgeClipper clipper; 87 88 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 89 switch (verb) { 90 case SkPath::kMove_Verb: 91 case SkPath::kClose_Verb: 92 // we ignore these, and just get the whole segment from 93 // the corresponding line/quad/cubic verbs 94 break; 95 case SkPath::kLine_Verb: { 96 SkPoint lines[SkLineClipper::kMaxPoints]; 97 int lineCount = SkLineClipper::ClipLine(pts, clip, lines); 98 for (int i = 0; i < lineCount; i++) { 99 this->addLine(&lines[i]); 100 } 101 break; 102 } 103 case SkPath::kQuad_Verb: 104 if (clipper.clipQuad(pts, clip)) { 105 this->addClipper(&clipper); 106 } 107 break; 108 case SkPath::kCubic_Verb: 109 if (clipper.clipCubic(pts, clip)) { 110 this->addClipper(&clipper); 111 } 112 break; 113 default: 114 SkASSERT(!"unexpected verb"); 115 break; 116 } 117 } 118 } else { 119 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 120 switch (verb) { 121 case SkPath::kMove_Verb: 122 case SkPath::kClose_Verb: 123 // we ignore these, and just get the whole segment from 124 // the corresponding line/quad/cubic verbs 125 break; 126 case SkPath::kLine_Verb: 127 this->addLine(pts); 128 break; 129 case SkPath::kQuad_Verb: { 130 SkPoint monoX[5]; 131 int n = SkChopQuadAtYExtrema(pts, monoX); 132 for (int i = 0; i <= n; i++) { 133 this->addQuad(&monoX[i * 2]); 134 } 135 break; 136 } 137 case SkPath::kCubic_Verb: { 138 SkPoint monoY[10]; 139 int n = SkChopCubicAtYExtrema(pts, monoY); 140 for (int i = 0; i <= n; i++) { 141 this->addCubic(&monoY[i * 3]); 142 } 143 break; 144 } 145 default: 146 SkASSERT(!"unexpected verb"); 147 break; 148 } 149 } 150 } 151 return fList.count(); 152} 153 154 155