Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  SkCornerPathEffect.cpp

  Sprache: C
 

/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "include/effects/SkCornerPathEffect.h"

#include "include/core/SkFlattenable.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkFloatingPoint.h"
#include "src/core/SkPathEffectBase.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"

class SkMatrix;
class SkStrokeRec;
struct SkRect;

static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius,
                        SkPoint* step) {
    SkScalar dist = SkPoint::Distance(a, b);

    *step = b - a;
    if (dist <= radius * 2) {
        *step *= SK_ScalarHalf;
        return false;
    } else {
        *step *= radius / dist;
        return true;
    }
}

class SkCornerPathEffectImpl : public SkPathEffectBase {
public:
    explicit SkCornerPathEffectImpl(SkScalar radius) : fRadius(radius) {
        SkASSERT(radius > 0);
    }

    bool onFilterPath(SkPathBuilder* dst, const SkPath& src, SkStrokeRec*, const SkRect*,
                      const SkMatrix&) const override {
        if (fRadius <= 0) {
            return false;
        }

        // just need a value that won't match when we compare it initially
        SkPathVerb   prevVerb = static_cast<SkPathVerb>(0xFF);

        bool        closed;
        SkPoint     moveTo, lastCorner;
        SkVector    firstStep, step;
        bool        prevIsValid = true;

        // to avoid warnings
        step.set(00);
        moveTo.set(00);
        firstStep.set(00);
        lastCorner.set(00);

        SkPath::Iter iter(src, false);
        while (auto rec = iter.next()) {
            SkSpan<const SkPoint> pts = rec->fPoints;
            switch (rec->fVerb) {
                case SkPathVerb::kMove:
                    // close out the previous (open) contour
                    if (SkPathVerb::kLine == prevVerb) {
                        dst->lineTo(lastCorner);
                    }
                    closed = iter.isClosedContour();
                    if (closed) {
                        moveTo = pts[0];
                        prevIsValid = false;
                    } else {
                        dst->moveTo(pts[0]);
                        prevIsValid = true;
                    }
                    break;
                case SkPathVerb::kLine: {
                    bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step);
                    // prev corner
                    if (!prevIsValid) {
                        dst->moveTo(moveTo + step);
                        prevIsValid = true;
                    } else {
                        dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX,
                                    pts[0].fY + step.fY);
                    }
                    if (drawSegment) {
                        dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY);
                    }
                    lastCorner = pts[1];
                    prevIsValid = true;
                    break;
                }
                case SkPathVerb::kQuad:
                    // TBD - just replicate the curve for now
                    if (!prevIsValid) {
                        dst->moveTo(pts[0]);
                        prevIsValid = true;
                    }
                    dst->quadTo(pts[1], pts[2]);
                    lastCorner = pts[2];
                    firstStep.set(00);
                    break;
                case SkPathVerb::kConic:
                    // TBD - just replicate the curve for now
                    if (!prevIsValid) {
                        dst->moveTo(pts[0]);
                        prevIsValid = true;
                    }
                    dst->conicTo(pts[1], pts[2], rec->conicWeight());
                    lastCorner = pts[2];
                    firstStep.set(00);
                    break;
                case SkPathVerb::kCubic:
                    if (!prevIsValid) {
                        dst->moveTo(pts[0]);
                        prevIsValid = true;
                    }
                    // TBD - just replicate the curve for now
                    dst->cubicTo(pts[1], pts[2], pts[3]);
                    lastCorner = pts[3];
                    firstStep.set(00);
                    break;
                case SkPathVerb::kClose:
                    if (firstStep.fX || firstStep.fY) {
                        dst->quadTo(lastCorner.fX, lastCorner.fY,
                                    lastCorner.fX + firstStep.fX,
                                    lastCorner.fY + firstStep.fY);
                    }
                    dst->close();
                    prevIsValid = false;
                    break;
            }
            if (SkPathVerb::kMove == prevVerb) {
                firstStep = step;
            }
            prevVerb = rec->fVerb;
        }
        if (prevIsValid) {
            dst->lineTo(lastCorner);
        }
        return true;
    }

    bool computeFastBounds(SkRect*) const override {
        // Rounding sharp corners within a path produces a new path that is still contained within
        // the original's bounds, so leave 'bounds' unmodified.
        return true;
    }

    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
        return SkCornerPathEffect::Make(buffer.readScalar());
    }

    void flatten(SkWriteBuffer& buffer) const override {
        buffer.writeScalar(fRadius);
    }

    Factory getFactory() const override { return CreateProc; }
    const char* getTypeName() const override { return "SkCornerPathEffect"; }

private:
    const SkScalar fRadius;

    using INHERITED = SkPathEffectBase;
};

//////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkPathEffect> SkCornerPathEffect::Make(SkScalar radius) {
    return SkIsFinite(radius) && (radius > 0) ?
            sk_sp<SkPathEffect>(new SkCornerPathEffectImpl(radius)) : nullptr;
}

void SkCornerPathEffect::RegisterFlattenables() {
    SkFlattenable::Register("SkCornerPathEffect", SkCornerPathEffectImpl::CreateProc);
}

Messung V0.5 in Prozent
C=93 H=96 G=94

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002