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 10static std::atomic<uint32_t> gGenID{1}; 11Xform::GenID Xform::NextGenID() { 12 return gGenID++; 13} 14 15#ifdef SK_DEBUG 16void 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 27void 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 48void Xform::internalAddChild(Xform* child) { 49 SkASSERT(fChildren.find(child) < 0); 50 fChildren.push_back(child); 51} 52 53void Xform::internalRemoveChild(Xform* child) { 54 int index = fChildren.find(child); 55 SkASSERT(index >= 0); 56 fChildren.removeShuffle(index); 57} 58 59void Xform::invalidateCaches() { 60 fGenID = 0; 61 if (this->isCached()) { 62 this->internalInvalidateCaches(); 63 for (auto c : fChildren) { 64 c->invalidateCaches(); 65 } 66 } 67} 68 69void Xform::visit(XformResolver* resolver) { 70 this->onVisit(resolver); 71} 72 73void Xform::setCache(const SkMatrix& ctm, sk_sp<ClipCache> clip) { 74 fCTM = ctm; 75 fClip = std::move(clip); 76 fGenID = NextGenID(); 77} 78 79////////////////////////////////////////////////////////////////////////////////////////////////// 80 81void MatrixXF::onVisit(XformResolver* resolver) { 82 resolver->concat(fLocalMatrix); 83} 84 85void ClipXF::onVisit(XformResolver* resolver) { 86 resolver->clipRect(fRect, fOp); 87} 88