blob: ddab4f1047f46388a0c00bd99f6513f6235a7df9 [file] [log] [blame]
/*
* 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<uint32_t> 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<Xform> 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<ClipCache> 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);
}