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