| /* |
| * Copyright 2019 Google LLC. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkXform_DEFINED |
| #define SkXform_DEFINED |
| |
| #include "include/core/SkClipOp.h" |
| #include "include/core/SkMatrix.h" |
| #include "include/core/SkPath.h" |
| #include "include/core/SkRRect.h" |
| #include "include/core/SkRect.h" |
| #include "include/core/SkRefCnt.h" |
| |
| #include "include/private/SkTDArray.h" |
| |
| class XformResolver { |
| public: |
| virtual ~XformResolver() {} |
| |
| virtual void concat(const SkMatrix&) = 0; |
| virtual void clipRect(const SkRect&, SkClipOp) = 0; |
| virtual void clipRRect(const SkRRect&, SkClipOp) = 0; |
| virtual void clipPath(const SkPath&, SkClipOp) = 0; |
| }; |
| |
| class ClipCache : public SkRefCnt { |
| public: |
| ClipCache() {} |
| }; |
| |
| class Xform : public SkRefCnt { |
| public: |
| typedef uint32_t GenID; |
| |
| Xform* parent() const { return fParent.get(); } |
| void setParent(sk_sp<Xform> p); |
| |
| void visit(XformResolver* resolver); |
| |
| GenID genID() const { return fGenID; } |
| |
| bool isCached() const { return !!fClip; } |
| void invalidateCaches(); |
| |
| const SkMatrix& ctm() const { return fCTM; } |
| ClipCache* clip() const { return fClip.get(); } |
| |
| void setCache(const SkMatrix&, sk_sp<ClipCache>); |
| |
| protected: |
| Xform(sk_sp<Xform> parent = nullptr) { |
| if (parent) { |
| this->setParent(std::move(parent)); |
| } |
| } |
| |
| virtual void onVisit(XformResolver*) {} |
| |
| private: |
| sk_sp<Xform> fParent; |
| |
| // unowned bare pointers |
| SkTDArray<Xform*> fChildren; |
| |
| // cache |
| SkMatrix fCTM; |
| sk_sp<ClipCache> fClip; |
| |
| uint32_t fGenID = 0; |
| |
| static GenID NextGenID(); |
| |
| void internalInvalidateCaches() { fClip = nullptr; } |
| void internalAddChild(Xform*); |
| void internalRemoveChild(Xform*); |
| |
| #ifdef SK_DEBUG |
| void debugValidate() const; |
| #else |
| void debugValidate() const {} |
| #endif |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| class MatrixXF : public Xform { |
| public: |
| static sk_sp<MatrixXF> Make(sk_sp<Xform> parent = nullptr) { |
| return sk_sp<MatrixXF>(new MatrixXF(std::move(parent))); |
| } |
| |
| MatrixXF(sk_sp<Xform> parent) : Xform(std::move(parent)) { |
| fLocalMatrix.reset(); |
| } |
| |
| void setLocalMatrix(const SkMatrix& m) { |
| fLocalMatrix = m; |
| } |
| void setTranslate(SkScalar sx, SkScalar sy) { |
| fLocalMatrix.setTranslate(sx, sy); |
| } |
| void setScale(SkScalar sx, SkScalar sy) { |
| fLocalMatrix.setScale(sx, sy); |
| } |
| void setRotate(SkScalar degrees) { |
| fLocalMatrix.setRotate(degrees); |
| } |
| |
| protected: |
| void onVisit(XformResolver* resolver) override; |
| |
| private: |
| SkMatrix fLocalMatrix; |
| }; |
| |
| class ClipXF : public Xform { |
| public: |
| ClipXF(sk_sp<Xform> parent = nullptr) : Xform(std::move(parent)) {} |
| ClipXF(sk_sp<Xform> parent, const SkRect& r, SkClipOp op = SkClipOp::kIntersect) |
| : Xform(std::move(parent)) |
| , fRect(r) |
| , fOp(op) |
| {} |
| |
| void setRect(const SkRect& r, SkClipOp op = SkClipOp::kIntersect) { |
| fRect = r; |
| fOp = op; |
| } |
| |
| protected: |
| void onVisit(XformResolver* resolver) override; |
| |
| private: |
| SkRect fRect; |
| SkClipOp fOp; |
| }; |
| |
| #endif |