180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Sk1DPathEffect.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFlattenableBuffers.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPathMeasure.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src,
15d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                SkStrokeRec*, const SkRect*) const {
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPathMeasure   meas(src, false);
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar    length = meas.getLength();
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar    distance = this->begin(length);
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (distance < length) {
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScalar delta = this->next(dst, distance, meas);
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (delta <= 0) {
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            distance += delta;
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (meas.nextContour());
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPath1DPathEffect::SkPath1DPathEffect(const SkPath& path, SkScalar advance,
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar phase, Style style) : fPath(path)
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (advance <= 0 || path.isEmpty()) {
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGF(("SkPath1DPathEffect can't use advance <= 0\n"));
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fAdvance = 0;   // signals we can't draw anything
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fInitialOffset = 0;
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fStyle = kStyleCount;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // cleanup their phase parameter, inverting it so that it becomes an
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // offset along the path (to match the interpretation in PostScript)
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (phase < 0) {
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            phase = -phase;
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (phase > advance) {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                phase = SkScalarMod(phase, advance);
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (phase > advance) {
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                phase = SkScalarMod(phase, advance);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            phase = advance - phase;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // now catch the edge case where phase == advance (within epsilon)
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (phase >= advance) {
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            phase = 0;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(phase >= 0);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fAdvance = advance;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fInitialOffset = phase;
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((unsigned)style >= kStyleCount) {
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDEBUGF(("SkPath1DPathEffect style enum out of range %d\n", style));
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fStyle = style;
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPath1DPathEffect::filterPath(SkPath* dst, const SkPath& src,
72d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                            SkStrokeRec* rec, const SkRect* cullRect) const {
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fAdvance > 0) {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rec->setFillStyle();
75d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        return this->INHERITED::filterPath(dst, src, rec, cullRect);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool morphpoints(SkPoint dst[], const SkPoint src[], int count,
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkPathMeasure& meas, SkScalar dist) {
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < count; i++) {
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPoint pos;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkVector tangent;
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar sx = src[i].fX;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar sy = src[i].fY;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!meas.getPosTan(dist + sx, &pos, &tangent)) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkMatrix    matrix;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPoint     pt;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt.set(sx, sy);
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.setSinCos(tangent.fY, tangent.fX, 0, 0);
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.preTranslate(-sx, 0);
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.postTranslate(pos.fX, pos.fY);
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        matrix.mapPoints(&dst[i], &pt, 1);
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*  TODO
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruNeed differentially more subdivisions when the follow-path is curvy. Not sure how to
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudetermine that, but we need it. I guess a cheap answer is let the caller tell us,
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubut that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                      SkScalar dist) {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath::Iter    iter(src, false);
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPoint         srcP[4], dstP[3];
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkPath::Verb    verb;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (verb) {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkPath::kMove_Verb:
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (morphpoints(dstP, srcP, 1, meas, dist)) {
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst->moveTo(dstP[0]);
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkPath::kLine_Verb:
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                srcP[2] = srcP[1];
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                srcP[1].set(SkScalarAve(srcP[0].fX, srcP[2].fX),
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkScalarAve(srcP[0].fY, srcP[2].fY));
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // fall through to quad
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkPath::kQuad_Verb:
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (morphpoints(dstP, &srcP[1], 2, meas, dist)) {
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst->quadTo(dstP[0], dstP[1]);
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkPath::kCubic_Verb:
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (morphpoints(dstP, &srcP[1], 3, meas, dist)) {
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst->cubicTo(dstP[0], dstP[1], dstP[2]);
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkPath::kClose_Verb:
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst->close();
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDEBUGFAIL("unknown verb");
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPath1DPathEffect::SkPath1DPathEffect(SkFlattenableReadBuffer& buffer) {
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fAdvance = buffer.readScalar();
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fAdvance > 0) {
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.readPath(&fPath);
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fInitialOffset = buffer.readScalar();
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fStyle = (Style) buffer.readUInt();
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDEBUGF(("SkPath1DPathEffect can't use advance <= 0\n"));
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Make Coverity happy.
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fInitialOffset = 0;
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fStyle = kStyleCount;
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkScalar SkPath1DPathEffect::begin(SkScalar contourLength) const {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fInitialOffset;
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPath1DPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::flatten(buffer);
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeScalar(fAdvance);
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fAdvance > 0) {
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.writePath(fPath);
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.writeScalar(fInitialOffset);
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.writeUInt(fStyle);
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPath1DPathEffect::next(SkPath* dst, SkScalar distance,
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                                  SkPathMeasure& meas) const {
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (fStyle) {
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kTranslate_Style: {
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkPoint pos;
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (meas.getPosTan(distance, &pos, NULL)) {
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst->addPath(fPath, pos.fX, pos.fY);
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kRotate_Style: {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkMatrix matrix;
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (meas.getMatrix(distance, &matrix)) {
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst->addPath(fPath, matrix);
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kMorph_Style:
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            morphpath(dst, fPath, meas, distance);
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDEBUGFAIL("unknown Style enum");
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fAdvance;
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
201