SkCornerPathEffect.cpp revision 4a3b714d73e585a3985d614600c6b79d5c8b1f1e
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 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 */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCornerPathEffect.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBuffer.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCornerPathEffect::~SkCornerPathEffect() 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 233334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgstatic bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, 243334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org SkPoint* step) { 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar dist = SkPoint::Distance(a, b); 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->set(b.fX - a.fX, b.fY - a.fY); 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (dist <= radius * 2) { 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SK_ScalarHalf); 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 323334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SkScalarDiv(radius, dist)); 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 383334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgbool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, 393334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org SkScalar* width) { 403334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (fRadius == 0) { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 423334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Iter iter(src, false); 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Verb verb, prevVerb = (SkPath::Verb)-1; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[4]; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool closed; 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint moveTo, lastCorner; 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector firstStep, step; 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool prevIsValid = true; 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // to avoid warnings 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com moveTo.set(0, 0); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep.set(0, 0); 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner.set(0, 0); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 594a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com switch (verb = iter.next(pts, false)) { 603334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kMove_Verb: 613334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // close out the previous (open) contour 623334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (SkPath::kLine_Verb == prevVerb) { 633334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->lineTo(lastCorner); 643334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 653334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org closed = iter.isClosedContour(); 663334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (closed) { 673334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org moveTo = pts[0]; 683334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = false; 693334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 703334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 713334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 723334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 733334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 743334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kLine_Verb: { 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // prev corner 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!prevIsValid) { 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(moveTo + step); 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 803334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 813334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, 823334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org pts[0].fY + step.fY); 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (drawSegment) { 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner = pts[1]; 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 893334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 913334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kQuad_Verb: 923334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // TBD - just replicate the curve for now 933334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (!prevIsValid) { 943334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 953334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 963334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 973334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(pts[1], pts[2]); 983334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner = pts[2]; 993334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org firstStep.set(0, 0); 1003334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1013334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kCubic_Verb: 1023334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (!prevIsValid) { 1033334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 1043334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 1053334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1063334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // TBD - just replicate the curve for now 1073334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->cubicTo(pts[1], pts[2], pts[3]); 1083334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner = pts[3]; 1093334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org firstStep.set(0, 0); 1103334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1113334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kClose_Verb: 1123334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (firstStep.fX || firstStep.fY) { 1133334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(lastCorner.fX, lastCorner.fY, 1143334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner.fX + firstStep.fX, 1153334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner.fY + firstStep.fY); 1163334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1173334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->close(); 1183334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1193334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kDone_Verb: 1203334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org goto DONE; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1233334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (SkPath::kMove_Verb == prevVerb) { 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep = step; 1253334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevVerb = verb; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDONE: 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13254924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.comvoid SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 13354924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com this->INHERITED::flatten(buffer); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.writeScalar(fRadius); 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1373334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) { 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = buffer.readScalar(); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 141d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR(SkCornerPathEffect) 1426bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 143