SkCornerPathEffect.cpp revision 6bac947cd5bc460dd9166ada6310d678fd2e39f8
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/effects/SkCornerPathEffect.cpp 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Copyright 2006, The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Licensed under the Apache License, Version 2.0 (the "License"); 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** you may not use this file except in compliance with the License. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** You may obtain a copy of the License at 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** http://www.apache.org/licenses/LICENSE-2.0 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Unless required by applicable law or agreed to in writing, software 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** distributed under the License is distributed on an "AS IS" BASIS, 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** See the License for the specific language governing permissions and 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** limitations under the License. 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCornerPathEffect.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPoint.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBuffer.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCornerPathEffect::~SkCornerPathEffect() 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 313334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgstatic bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, 323334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org SkPoint* step) { 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar dist = SkPoint::Distance(a, b); 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->set(b.fX - a.fX, b.fY - a.fY); 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (dist <= radius * 2) { 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SK_ScalarHalf); 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 403334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SkScalarDiv(radius, dist)); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 463334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgbool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, 473334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org SkScalar* width) { 483334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (fRadius == 0) { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 503334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Iter iter(src, false); 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Verb verb, prevVerb = (SkPath::Verb)-1; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[4]; 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool closed; 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint moveTo, lastCorner; 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector firstStep, step; 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool prevIsValid = true; 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // to avoid warnings 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com moveTo.set(0, 0); 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep.set(0, 0); 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner.set(0, 0); 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (verb = iter.next(pts)) { 683334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kMove_Verb: 693334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // close out the previous (open) contour 703334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (SkPath::kLine_Verb == prevVerb) { 713334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->lineTo(lastCorner); 723334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 733334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org closed = iter.isClosedContour(); 743334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (closed) { 753334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org moveTo = pts[0]; 763334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = false; 773334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 783334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 793334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 803334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 813334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 823334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kLine_Verb: { 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // prev corner 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!prevIsValid) { 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(moveTo + step); 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 883334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 893334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, 903334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org pts[0].fY + step.fY); 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (drawSegment) { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner = pts[1]; 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 973334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 993334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kQuad_Verb: 1003334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // TBD - just replicate the curve for now 1013334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (!prevIsValid) { 1023334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 1033334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 1043334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1053334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(pts[1], pts[2]); 1063334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner = pts[2]; 1073334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org firstStep.set(0, 0); 1083334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1093334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kCubic_Verb: 1103334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (!prevIsValid) { 1113334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 1123334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 1133334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1143334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // TBD - just replicate the curve for now 1153334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->cubicTo(pts[1], pts[2], pts[3]); 1163334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner = pts[3]; 1173334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org firstStep.set(0, 0); 1183334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1193334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kClose_Verb: 1203334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (firstStep.fX || firstStep.fY) { 1213334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(lastCorner.fX, lastCorner.fY, 1223334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner.fX + firstStep.fX, 1233334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner.fY + firstStep.fY); 1243334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1253334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->close(); 1263334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1273334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kDone_Verb: 1283334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org goto DONE; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1313334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (SkPath::kMove_Verb == prevVerb) { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep = step; 1333334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevVerb = verb; 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDONE: 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1403334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkFlattenable::Factory SkCornerPathEffect::getFactory() { 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return CreateProc; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1443334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgvoid SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) { 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.writeScalar(fRadius); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1483334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkFlattenable* SkCornerPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) { 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkNEW_ARGS(SkCornerPathEffect, (buffer)); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1523334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) { 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = buffer.readScalar(); 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1566bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com/////////////////////////////////////////////////////////////////////////////// 1576bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 1586bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comstatic SkFlattenable::Registrar gReg("SkCornerPathEffect", 1596bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com SkCornerPathEffect::CreateProc); 1606bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 161