gfx/skia/trunk/src/effects/SkCornerPathEffect.cpp

changeset 0
6474c204b198
     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 +}

mercurial