1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/effects/SkCornerPathEffect.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,138 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkCornerPathEffect.h" 1.14 +#include "SkPath.h" 1.15 +#include "SkPoint.h" 1.16 +#include "SkReadBuffer.h" 1.17 +#include "SkWriteBuffer.h" 1.18 + 1.19 +SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) {} 1.20 +SkCornerPathEffect::~SkCornerPathEffect() {} 1.21 + 1.22 +static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, 1.23 + SkPoint* step) { 1.24 + SkScalar dist = SkPoint::Distance(a, b); 1.25 + 1.26 + step->set(b.fX - a.fX, b.fY - a.fY); 1.27 + 1.28 + if (dist <= radius * 2) { 1.29 + step->scale(SK_ScalarHalf); 1.30 + return false; 1.31 + } else { 1.32 + step->scale(SkScalarDiv(radius, dist)); 1.33 + return true; 1.34 + } 1.35 +} 1.36 + 1.37 +bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, 1.38 + SkStrokeRec*, const SkRect*) const { 1.39 + if (0 == fRadius) { 1.40 + return false; 1.41 + } 1.42 + 1.43 + SkPath::Iter iter(src, false); 1.44 + SkPath::Verb verb, prevVerb = (SkPath::Verb)-1; 1.45 + SkPoint pts[4]; 1.46 + 1.47 + bool closed; 1.48 + SkPoint moveTo, lastCorner; 1.49 + SkVector firstStep, step; 1.50 + bool prevIsValid = true; 1.51 + 1.52 + // to avoid warnings 1.53 + moveTo.set(0, 0); 1.54 + firstStep.set(0, 0); 1.55 + lastCorner.set(0, 0); 1.56 + 1.57 + for (;;) { 1.58 + switch (verb = iter.next(pts, false)) { 1.59 + case SkPath::kMove_Verb: 1.60 + // close out the previous (open) contour 1.61 + if (SkPath::kLine_Verb == prevVerb) { 1.62 + dst->lineTo(lastCorner); 1.63 + } 1.64 + closed = iter.isClosedContour(); 1.65 + if (closed) { 1.66 + moveTo = pts[0]; 1.67 + prevIsValid = false; 1.68 + } else { 1.69 + dst->moveTo(pts[0]); 1.70 + prevIsValid = true; 1.71 + } 1.72 + break; 1.73 + case SkPath::kLine_Verb: { 1.74 + bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); 1.75 + // prev corner 1.76 + if (!prevIsValid) { 1.77 + dst->moveTo(moveTo + step); 1.78 + prevIsValid = true; 1.79 + } else { 1.80 + dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, 1.81 + pts[0].fY + step.fY); 1.82 + } 1.83 + if (drawSegment) { 1.84 + dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); 1.85 + } 1.86 + lastCorner = pts[1]; 1.87 + prevIsValid = true; 1.88 + break; 1.89 + } 1.90 + case SkPath::kQuad_Verb: 1.91 + // TBD - just replicate the curve for now 1.92 + if (!prevIsValid) { 1.93 + dst->moveTo(pts[0]); 1.94 + prevIsValid = true; 1.95 + } 1.96 + dst->quadTo(pts[1], pts[2]); 1.97 + lastCorner = pts[2]; 1.98 + firstStep.set(0, 0); 1.99 + break; 1.100 + case SkPath::kCubic_Verb: 1.101 + if (!prevIsValid) { 1.102 + dst->moveTo(pts[0]); 1.103 + prevIsValid = true; 1.104 + } 1.105 + // TBD - just replicate the curve for now 1.106 + dst->cubicTo(pts[1], pts[2], pts[3]); 1.107 + lastCorner = pts[3]; 1.108 + firstStep.set(0, 0); 1.109 + break; 1.110 + case SkPath::kClose_Verb: 1.111 + if (firstStep.fX || firstStep.fY) { 1.112 + dst->quadTo(lastCorner.fX, lastCorner.fY, 1.113 + lastCorner.fX + firstStep.fX, 1.114 + lastCorner.fY + firstStep.fY); 1.115 + } 1.116 + dst->close(); 1.117 + break; 1.118 + case SkPath::kConic_Verb: 1.119 + SkASSERT(0); 1.120 + break; 1.121 + case SkPath::kDone_Verb: 1.122 + goto DONE; 1.123 + } 1.124 + 1.125 + if (SkPath::kMove_Verb == prevVerb) { 1.126 + firstStep = step; 1.127 + } 1.128 + prevVerb = verb; 1.129 + } 1.130 +DONE: 1.131 + return true; 1.132 +} 1.133 + 1.134 +void SkCornerPathEffect::flatten(SkWriteBuffer& buffer) const { 1.135 + this->INHERITED::flatten(buffer); 1.136 + buffer.writeScalar(fRadius); 1.137 +} 1.138 + 1.139 +SkCornerPathEffect::SkCornerPathEffect(SkReadBuffer& buffer) { 1.140 + fRadius = buffer.readScalar(); 1.141 +}