SkCornerPathEffect.cpp revision 6bac947cd5bc460dd9166ada6310d678fd2e39f8
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
313334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgstatic bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius,
323334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                        SkPoint* step) {
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;
403334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    } else {
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        step->scale(SkScalarDiv(radius, dist));
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
463334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgbool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src,
473334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                                    SkScalar* width) {
483334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    if (fRadius == 0) {
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
503334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org    }
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)) {
683334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            case SkPath::kMove_Verb:
693334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    // close out the previous (open) contour
703334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                if (SkPath::kLine_Verb == prevVerb) {
713334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    dst->lineTo(lastCorner);
723334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
733334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                closed = iter.isClosedContour();
743334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                if (closed) {
753334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    moveTo = pts[0];
763334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    prevIsValid = false;
773334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                } else {
783334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    dst->moveTo(pts[0]);
793334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    prevIsValid = true;
803334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
813334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                break;
823334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            case SkPath::kLine_Verb: {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step);
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // prev corner
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (!prevIsValid) {
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    dst->moveTo(moveTo + step);
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    prevIsValid = true;
883334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                } else {
893334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX,
903334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                                pts[0].fY + step.fY);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (drawSegment) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                lastCorner = pts[1];
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                prevIsValid = true;
973334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                break;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
993334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            case SkPath::kQuad_Verb:
1003334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                // TBD - just replicate the curve for now
1013334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                if (!prevIsValid) {
1023334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    dst->moveTo(pts[0]);
1033334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    prevIsValid = true;
1043334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
1053334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                dst->quadTo(pts[1], pts[2]);
1063334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                lastCorner = pts[2];
1073334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                firstStep.set(0, 0);
1083334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                break;
1093334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            case SkPath::kCubic_Verb:
1103334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                if (!prevIsValid) {
1113334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    dst->moveTo(pts[0]);
1123334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    prevIsValid = true;
1133334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
1143334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                // TBD - just replicate the curve for now
1153334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                dst->cubicTo(pts[1], pts[2], pts[3]);
1163334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                lastCorner = pts[3];
1173334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                firstStep.set(0, 0);
1183334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                break;
1193334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            case SkPath::kClose_Verb:
1203334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                if (firstStep.fX || firstStep.fY) {
1213334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    dst->quadTo(lastCorner.fX, lastCorner.fY,
1223334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                                lastCorner.fX + firstStep.fX,
1233334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                                lastCorner.fY + firstStep.fY);
1243334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    }
1253334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                dst->close();
1263334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                break;
1273334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            case SkPath::kDone_Verb:
1283334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                goto DONE;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1313334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        if (SkPath::kMove_Verb == prevVerb) {
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            firstStep = step;
1333334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        }
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevVerb = verb;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDONE:
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1403334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkFlattenable::Factory SkCornerPathEffect::getFactory() {
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return CreateProc;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1443334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgvoid SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    buffer.writeScalar(fRadius);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1483334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkFlattenable* SkCornerPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkNEW_ARGS(SkCornerPathEffect, (buffer));
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1523334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.orgSkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) {
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRadius = buffer.readScalar();
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1566bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com///////////////////////////////////////////////////////////////////////////////
1576bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com
1586bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comstatic SkFlattenable::Registrar gReg("SkCornerPathEffect",
1596bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com                                     SkCornerPathEffect::CreateProc);
1606bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com
161