1 /*
2  * Copyright 2019 Google LLC.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "experimental/xform/SkXform.h"
9 
10 static std::atomic<uint32_t> gGenID{1};
NextGenID()11 Xform::GenID Xform::NextGenID() {
12     return gGenID++;
13 }
14 
15 #ifdef SK_DEBUG
debugValidate() const16 void Xform::debugValidate() const {
17     if (this->isCached() && fParent) {
18         SkASSERT(fParent->isCached());
19     }
20     for (auto c : fChildren) {
21         SkASSERT(c->parent() == this);
22         c->debugValidate();
23     }
24 }
25 #endif
26 
setParent(sk_sp<Xform> parent)27 void Xform::setParent(sk_sp<Xform> parent) {
28     if (parent == fParent) {
29         return;
30     }
31 
32     if (fParent) {
33         fParent->internalRemoveChild(this);
34     }
35     if (parent) {
36         parent->internalAddChild(this);
37     }
38     fParent = std::move(parent);
39 
40     // Potentially we could skip this if knew that our old and new parents
41     // were both cached, and they started us in the same state...
42     // For now, we conservatively always inval
43     this->invalidateCaches();
44 
45     this->debugValidate();
46 }
47 
internalAddChild(Xform * child)48 void Xform::internalAddChild(Xform* child) {
49     SkASSERT(fChildren.find(child) < 0);
50     fChildren.push_back(child);
51 }
52 
internalRemoveChild(Xform * child)53 void Xform::internalRemoveChild(Xform* child) {
54     int index = fChildren.find(child);
55     SkASSERT(index >= 0);
56     fChildren.removeShuffle(index);
57 }
58 
invalidateCaches()59 void Xform::invalidateCaches() {
60     fGenID = 0;
61     if (this->isCached()) {
62         this->internalInvalidateCaches();
63         for (auto c : fChildren) {
64             c->invalidateCaches();
65         }
66     }
67 }
68 
visit(XformResolver * resolver)69 void Xform::visit(XformResolver* resolver) {
70     this->onVisit(resolver);
71 }
72 
setCache(const SkMatrix & ctm,sk_sp<ClipCache> clip)73 void Xform::setCache(const SkMatrix& ctm, sk_sp<ClipCache> clip) {
74     fCTM = ctm;
75     fClip = std::move(clip);
76     fGenID = NextGenID();
77 }
78 
79 //////////////////////////////////////////////////////////////////////////////////////////////////
80 
onVisit(XformResolver * resolver)81 void MatrixXF::onVisit(XformResolver* resolver) {
82     resolver->concat(fLocalMatrix);
83 }
84 
onVisit(XformResolver * resolver)85 void ClipXF::onVisit(XformResolver* resolver) {
86     resolver->clipRect(fRect, fOp);
87 }
88