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" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comSkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) {} 17548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comSkCornerPathEffect::~SkCornerPathEffect() {} 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 193334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgstatic bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, 203334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org SkPoint* step) { 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar dist = SkPoint::Distance(a, b); 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->set(b.fX - a.fX, b.fY - a.fY); 24fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (dist <= radius * 2) { 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SK_ScalarHalf); 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 283334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com step->scale(SkScalarDiv(radius, dist)); 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 343334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgbool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, 354bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkStrokeRec*, const SkRect*) const { 36548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com if (0 == fRadius) { 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 383334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Iter iter(src, false); 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Verb verb, prevVerb = (SkPath::Verb)-1; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[4]; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool closed; 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint moveTo, lastCorner; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector firstStep, step; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool prevIsValid = true; 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // to avoid warnings 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com moveTo.set(0, 0); 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep.set(0, 0); 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner.set(0, 0); 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 554a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com switch (verb = iter.next(pts, false)) { 563334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kMove_Verb: 573334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // close out the previous (open) contour 583334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (SkPath::kLine_Verb == prevVerb) { 593334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->lineTo(lastCorner); 603334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 613334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org closed = iter.isClosedContour(); 623334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (closed) { 633334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org moveTo = pts[0]; 643334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = false; 653334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 663334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 673334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 683334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 693334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 703334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kLine_Verb: { 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // prev corner 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!prevIsValid) { 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(moveTo + step); 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 763334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } else { 773334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, 783334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org pts[0].fY + step.fY); 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (drawSegment) { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastCorner = pts[1]; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevIsValid = true; 853334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 873334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kQuad_Verb: 883334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // TBD - just replicate the curve for now 893334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (!prevIsValid) { 903334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 913334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 923334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 933334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(pts[1], pts[2]); 943334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner = pts[2]; 953334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org firstStep.set(0, 0); 963334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 973334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kCubic_Verb: 983334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (!prevIsValid) { 993334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->moveTo(pts[0]); 1003334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org prevIsValid = true; 1013334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1023334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org // TBD - just replicate the curve for now 1033334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->cubicTo(pts[1], pts[2], pts[3]); 1043334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner = pts[3]; 1053334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org firstStep.set(0, 0); 1063334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 1073334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kClose_Verb: 1083334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (firstStep.fX || firstStep.fY) { 1093334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->quadTo(lastCorner.fX, lastCorner.fY, 1103334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner.fX + firstStep.fX, 1113334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org lastCorner.fY + firstStep.fY); 1123334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1133334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org dst->close(); 1143334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org break; 115277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com case SkPath::kConic_Verb: 116277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com SkASSERT(0); 117277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com break; 1183334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org case SkPath::kDone_Verb: 1193334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org goto DONE; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1223334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org if (SkPath::kMove_Verb == prevVerb) { 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstStep = step; 1243334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org } 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevVerb = verb; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDONE: 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkCornerPathEffect::flatten(SkWriteBuffer& buffer) const { 13254924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com this->INHERITED::flatten(buffer); 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.writeScalar(fRadius); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1368b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkCornerPathEffect::SkCornerPathEffect(SkReadBuffer& buffer) { 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = buffer.readScalar(); 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 139