SkCornerPathEffect.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
1/* libs/graphics/effects/SkCornerPathEffect.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkCornerPathEffect.h" 19#include "SkPath.h" 20#include "SkPoint.h" 21#include "SkBuffer.h" 22 23SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) 24{ 25} 26 27SkCornerPathEffect::~SkCornerPathEffect() 28{ 29} 30 31static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, SkPoint* step) 32{ 33 SkScalar dist = SkPoint::Distance(a, b); 34 35 step->set(b.fX - a.fX, b.fY - a.fY); 36 37 if (dist <= radius * 2) { 38 step->scale(SK_ScalarHalf); 39 return false; 40 } 41 else { 42 step->scale(SkScalarDiv(radius, dist)); 43 return true; 44 } 45} 46 47bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* width) 48{ 49 if (fRadius == 0) 50 return false; 51 52 SkPath::Iter iter(src, false); 53 SkPath::Verb verb, prevVerb = (SkPath::Verb)-1; 54 SkPoint pts[4]; 55 56 bool closed; 57 SkPoint moveTo, lastCorner; 58 SkVector firstStep, step; 59 bool prevIsValid = true; 60 61 // to avoid warnings 62 moveTo.set(0, 0); 63 firstStep.set(0, 0); 64 lastCorner.set(0, 0); 65 66 for (;;) { 67 switch (verb = iter.next(pts)) { 68 case SkPath::kMove_Verb: 69 closed = iter.isClosedContour(); 70 if (closed) { 71 moveTo = pts[0]; 72 prevIsValid = false; 73 } 74 else { 75 dst->moveTo(pts[0]); 76 prevIsValid = true; 77 } 78 break; 79 case SkPath::kLine_Verb: 80 { 81 bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); 82 // prev corner 83 if (!prevIsValid) { 84 dst->moveTo(moveTo + step); 85 prevIsValid = true; 86 } 87 else { 88 dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, pts[0].fY + step.fY); 89 } 90 if (drawSegment) { 91 dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); 92 } 93 lastCorner = pts[1]; 94 prevIsValid = true; 95 } 96 break; 97 case SkPath::kQuad_Verb: 98 // TBD - just replicate the curve for now 99 if (!prevIsValid) 100 { 101 dst->moveTo(pts[0]); 102 prevIsValid = true; 103 } 104 dst->quadTo(pts[1], pts[2]); 105 lastCorner = pts[2]; 106 firstStep.set(0, 0); 107 break; 108 case SkPath::kCubic_Verb: 109 if (!prevIsValid) 110 { 111 dst->moveTo(pts[0]); 112 prevIsValid = true; 113 } 114 // TBD - just replicate the curve for now 115 dst->cubicTo(pts[1], pts[2], pts[3]); 116 lastCorner = pts[3]; 117 firstStep.set(0, 0); 118 break; 119 case SkPath::kClose_Verb: 120 if (firstStep.fX || firstStep.fY) 121 dst->quadTo(lastCorner.fX, lastCorner.fY, 122 lastCorner.fX + firstStep.fX, 123 lastCorner.fY + firstStep.fY); 124 dst->close(); 125 break; 126 case SkPath::kDone_Verb: 127 goto DONE; 128 } 129 130 if (SkPath::kMove_Verb == prevVerb) 131 firstStep = step; 132 prevVerb = verb; 133 } 134DONE: 135 return true; 136} 137 138SkFlattenable::Factory SkCornerPathEffect::getFactory() 139{ 140 return CreateProc; 141} 142 143void SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) 144{ 145 buffer.writeScalar(fRadius); 146} 147 148SkFlattenable* SkCornerPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) 149{ 150 return SkNEW_ARGS(SkCornerPathEffect, (buffer)); 151} 152 153SkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) 154{ 155 fRadius = buffer.readScalar(); 156} 157 158