/* * Copyright 2019 Google LLC. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "experimental/xform/SkXform.h" static std::atomic gGenID{1}; Xform::GenID Xform::NextGenID() { return gGenID++; } #ifdef SK_DEBUG void Xform::debugValidate() const { if (this->isCached() && fParent) { SkASSERT(fParent->isCached()); } for (auto c : fChildren) { SkASSERT(c->parent() == this); c->debugValidate(); } } #endif void Xform::setParent(sk_sp parent) { if (parent == fParent) { return; } if (fParent) { fParent->internalRemoveChild(this); } if (parent) { parent->internalAddChild(this); } fParent = std::move(parent); // Potentially we could skip this if knew that our old and new parents // were both cached, and they started us in the same state... // For now, we conservatively always inval this->invalidateCaches(); this->debugValidate(); } void Xform::internalAddChild(Xform* child) { SkASSERT(fChildren.find(child) < 0); fChildren.push_back(child); } void Xform::internalRemoveChild(Xform* child) { int index = fChildren.find(child); SkASSERT(index >= 0); fChildren.removeShuffle(index); } void Xform::invalidateCaches() { fGenID = 0; if (this->isCached()) { this->internalInvalidateCaches(); for (auto c : fChildren) { c->invalidateCaches(); } } } void Xform::visit(XformResolver* resolver) { this->onVisit(resolver); } void Xform::setCache(const SkMatrix& ctm, sk_sp clip) { fCTM = ctm; fClip = std::move(clip); fGenID = NextGenID(); } ////////////////////////////////////////////////////////////////////////////////////////////////// void MatrixXF::onVisit(XformResolver* resolver) { resolver->concat(fLocalMatrix); } void ClipXF::onVisit(XformResolver* resolver) { resolver->clipRect(fRect, fOp); }