SkCornerPathEffect.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
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 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, SkPoint* step) 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 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; 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SkScalarDiv(radius, dist)); 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fRadius == 0) 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 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)) { 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kMove_Verb: 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com closed = iter.isClosedContour(); 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (closed) { 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com moveTo = pts[0]; 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = false; 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(pts[0]); 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kLine_Verb: 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // prev corner 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!prevIsValid) { 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(moveTo + step); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, pts[0].fY + step.fY); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (drawSegment) { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner = pts[1]; 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kQuad_Verb: 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TBD - just replicate the curve for now 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!prevIsValid) 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(pts[0]); 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(pts[1], pts[2]); 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner = pts[2]; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep.set(0, 0); 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kCubic_Verb: 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!prevIsValid) 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(pts[0]); 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TBD - just replicate the curve for now 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->cubicTo(pts[1], pts[2], pts[3]); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner = pts[3]; 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep.set(0, 0); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kClose_Verb: 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (firstStep.fX || firstStep.fY) 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(lastCorner.fX, lastCorner.fY, 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner.fX + firstStep.fX, 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner.fY + firstStep.fY); 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->close(); 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kDone_Verb: 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto DONE; 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkPath::kMove_Verb == prevVerb) 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep = step; 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevVerb = verb; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDONE: 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenable::Factory SkCornerPathEffect::getFactory() 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return CreateProc; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.writeScalar(fRadius); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFlattenable* SkCornerPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkNEW_ARGS(SkCornerPathEffect, (buffer)); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = buffer.readScalar(); 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 158