Skip to content

Commit a716809

Browse files
reed-at-googleSkia Commit-Bot
authored andcommitted
try resolver pattern
Change-Id: I32c5dbf4cacce9112df42a6f29800859625dc4a9 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/218965 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com> Auto-Submit: Mike Reed <reed@google.com>
1 parent bba5aa7 commit a716809

File tree

7 files changed

+650
-0
lines changed

7 files changed

+650
-0
lines changed

BUILD.gn

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ declare_args() {
2121
skia_use_angle = false
2222
skia_use_egl = false
2323
skia_use_expat = true
24+
skia_use_experimental_xform = false
2425
skia_use_ffmpeg = false
2526
skia_use_fontconfig = is_linux
2627
skia_use_fonthost_mac = is_mac
@@ -1749,6 +1750,17 @@ if (skia_enable_tools) {
17491750
}
17501751
}
17511752

1753+
test_lib("experimental_xform") {
1754+
sources = [
1755+
"experimental/xform/SkShape.cpp",
1756+
"experimental/xform/SkXform.cpp",
1757+
"experimental/xform/XContext.cpp",
1758+
]
1759+
deps = [
1760+
":skia",
1761+
]
1762+
}
1763+
17521764
if (skia_use_lua) {
17531765
test_lib("lua") {
17541766
sources = [
@@ -2377,6 +2389,10 @@ if (skia_enable_tools) {
23772389
"modules/sksg:samples",
23782390
"//third_party/imgui",
23792391
]
2392+
if (skia_use_experimental_xform) {
2393+
deps += [ ":experimental_xform" ]
2394+
sources += [ "gm/xform.cpp" ]
2395+
}
23802396
}
23812397

23822398
if (!skia_use_angle && (is_linux || is_win || is_mac)) {

experimental/xform/SkShape.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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/SkShape.h"
9+
#include "experimental/xform/SkXform.h"
10+
#include "include/core/SkCanvas.h"
11+
12+
void GeoShape::draw(XContext* ctx) {
13+
ctx->drawRect(fRect, fPaint, this->xform());
14+
}
15+
16+
void GroupShape::draw(XContext* ctx) {
17+
if (fArray.count() == 0) {
18+
return;
19+
}
20+
21+
ctx->push(this->xform());
22+
for (auto s : fArray) {
23+
s->draw(ctx);
24+
}
25+
ctx->pop();
26+
}

experimental/xform/SkShape.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
#ifndef SkShape_DEFINED
9+
#define SkShape_DEFINED
10+
11+
#include "experimental/xform/SkXform.h"
12+
#include "include/core/SkPaint.h"
13+
14+
class SkCanvas;
15+
16+
class XContext {
17+
public:
18+
virtual ~XContext() {}
19+
20+
void push(Xform* parentXform) { this->onPush(parentXform); }
21+
void pop() { this->onPop(); }
22+
23+
void drawRect(const SkRect&, const SkPaint&, Xform* localXform);
24+
25+
static std::unique_ptr<XContext> Make(SkCanvas*);
26+
27+
protected:
28+
virtual void onPush(Xform*) = 0;
29+
virtual void onPop() = 0;
30+
31+
virtual void onDrawRect(const SkRect&, const SkPaint&, Xform*) = 0;
32+
};
33+
34+
class Shape : public SkRefCnt {
35+
sk_sp<Xform> fXform;
36+
37+
public:
38+
Shape(sk_sp<Xform> x = nullptr) : fXform(std::move(x)) {}
39+
40+
Xform* xform() const { return fXform.get(); }
41+
void setXform(sk_sp<Xform> x) {
42+
fXform = std::move(x);
43+
}
44+
45+
virtual void draw(XContext*) {}
46+
};
47+
48+
class GeoShape : public Shape {
49+
SkRect fRect;
50+
SkPaint fPaint;
51+
52+
GeoShape(sk_sp<Xform> x, const SkRect& r, SkColor c) : Shape(std::move(x)), fRect(r) {
53+
fPaint.setColor(c);
54+
}
55+
56+
public:
57+
static sk_sp<Shape> Make(sk_sp<Xform> x, const SkRect& r, SkColor c) {
58+
return sk_sp<Shape>(new GeoShape(std::move(x), r, c));
59+
}
60+
61+
void draw(XContext*) override;
62+
};
63+
64+
class GroupShape : public Shape {
65+
SkTDArray<Shape*> fArray;
66+
67+
GroupShape(sk_sp<Xform> x) : Shape(std::move(x)) {}
68+
69+
public:
70+
static sk_sp<GroupShape> Make(sk_sp<Xform> x = nullptr) {
71+
return sk_sp<GroupShape>(new GroupShape(std::move(x)));
72+
}
73+
74+
static sk_sp<GroupShape> Make(sk_sp<Xform> x, sk_sp<Shape> s) {
75+
auto g = sk_sp<GroupShape>(new GroupShape(std::move(x)));
76+
g->append(std::move(s));
77+
return g;
78+
}
79+
80+
~GroupShape() override {
81+
fArray.unrefAll();
82+
}
83+
84+
int count() const { return fArray.count(); }
85+
Shape* get(int index) const { return fArray[index]; }
86+
void set(int index, sk_sp<Shape> s) {
87+
fArray[index] = s.release();
88+
}
89+
90+
void append(sk_sp<Shape> s) {
91+
*fArray.append() = s.release();
92+
}
93+
void insert(int index, sk_sp<Shape> s) {
94+
*fArray.insert(index) = s.release();
95+
}
96+
void remove(int index) {
97+
SkSafeUnref(fArray[index]);
98+
fArray.remove(index);
99+
}
100+
101+
void draw(XContext*) override ;
102+
};
103+
104+
#endif

experimental/xform/SkXform.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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};
11+
Xform::GenID Xform::NextGenID() {
12+
return gGenID++;
13+
}
14+
15+
#ifdef SK_DEBUG
16+
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+
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+
48+
void Xform::internalAddChild(Xform* child) {
49+
SkASSERT(fChildren.find(child) < 0);
50+
fChildren.push_back(child);
51+
}
52+
53+
void Xform::internalRemoveChild(Xform* child) {
54+
int index = fChildren.find(child);
55+
SkASSERT(index >= 0);
56+
fChildren.removeShuffle(index);
57+
}
58+
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+
69+
void Xform::visit(XformResolver* resolver) {
70+
this->onVisit(resolver);
71+
}
72+
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+
81+
void MatrixXF::onVisit(XformResolver* resolver) {
82+
resolver->concat(fLocalMatrix);
83+
}
84+
85+
void ClipXF::onVisit(XformResolver* resolver) {
86+
resolver->clipRect(fRect, fOp);
87+
}

experimental/xform/SkXform.h

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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+
#ifndef SkXform_DEFINED
9+
#define SkXform_DEFINED
10+
11+
#include "include/core/SkRefCnt.h"
12+
#include "include/core/SkMatrix.h"
13+
#include "include/core/SkClipOp.h"
14+
#include "include/core/SkRect.h"
15+
#include "include/core/SkRRect.h"
16+
#include "include/core/SkPath.h"
17+
18+
#include "include/private/SkTDArray.h"
19+
20+
class XformResolver {
21+
public:
22+
virtual ~XformResolver() {}
23+
24+
virtual void concat(const SkMatrix&) = 0;
25+
virtual void clipRect(const SkRect&, SkClipOp) = 0;
26+
virtual void clipRRect(const SkRRect&, SkClipOp) = 0;
27+
virtual void clipPath(const SkPath&, SkClipOp) = 0;
28+
};
29+
30+
class ClipCache : public SkRefCnt {
31+
public:
32+
ClipCache() {}
33+
};
34+
35+
class Xform : public SkRefCnt {
36+
public:
37+
typedef uint32_t GenID;
38+
39+
Xform* parent() const { return fParent.get(); }
40+
void setParent(sk_sp<Xform> p);
41+
42+
void visit(XformResolver* resolver);
43+
44+
GenID genID() const { return fGenID; }
45+
46+
bool isCached() const { return !!fClip; }
47+
void invalidateCaches();
48+
49+
const SkMatrix& ctm() const { return fCTM; }
50+
ClipCache* clip() const { return fClip.get(); }
51+
52+
void setCache(const SkMatrix&, sk_sp<ClipCache>);
53+
54+
protected:
55+
Xform(sk_sp<Xform> parent = nullptr) {
56+
if (parent) {
57+
this->setParent(std::move(parent));
58+
}
59+
}
60+
61+
virtual void onVisit(XformResolver*) {}
62+
63+
private:
64+
sk_sp<Xform> fParent;
65+
66+
// unowned bare pointers
67+
SkTDArray<Xform*> fChildren;
68+
69+
// cache
70+
SkMatrix fCTM;
71+
sk_sp<ClipCache> fClip;
72+
73+
uint32_t fGenID = 0;
74+
75+
static GenID NextGenID();
76+
77+
void internalInvalidateCaches() { fClip = nullptr; }
78+
void internalAddChild(Xform*);
79+
void internalRemoveChild(Xform*);
80+
81+
#ifdef SK_DEBUG
82+
void debugValidate() const;
83+
#else
84+
void debugValidate() const {}
85+
#endif
86+
};
87+
88+
///////////////////////////////////////////////////////////////////////////////////////////////
89+
90+
class MatrixXF : public Xform {
91+
public:
92+
static sk_sp<MatrixXF> Make(sk_sp<Xform> parent = nullptr) {
93+
return sk_sp<MatrixXF>(new MatrixXF(std::move(parent)));
94+
}
95+
96+
MatrixXF(sk_sp<Xform> parent) : Xform(std::move(parent)) {
97+
fLocalMatrix.reset();
98+
}
99+
100+
void setLocalMatrix(const SkMatrix& m) {
101+
fLocalMatrix = m;
102+
}
103+
void setTranslate(SkScalar sx, SkScalar sy) {
104+
fLocalMatrix.setTranslate(sx, sy);
105+
}
106+
void setScale(SkScalar sx, SkScalar sy) {
107+
fLocalMatrix.setScale(sx, sy);
108+
}
109+
void setRotate(SkScalar degrees) {
110+
fLocalMatrix.setRotate(degrees);
111+
}
112+
113+
protected:
114+
void onVisit(XformResolver* resolver) override;
115+
116+
private:
117+
SkMatrix fLocalMatrix;
118+
};
119+
120+
class ClipXF : public Xform {
121+
public:
122+
ClipXF(sk_sp<Xform> parent = nullptr) : Xform(std::move(parent)) {}
123+
ClipXF(sk_sp<Xform> parent, const SkRect& r, SkClipOp op = SkClipOp::kIntersect)
124+
: Xform(std::move(parent))
125+
, fRect(r)
126+
, fOp(op)
127+
{}
128+
129+
void setRect(const SkRect& r, SkClipOp op = SkClipOp::kIntersect) {
130+
fRect = r;
131+
fOp = op;
132+
}
133+
134+
protected:
135+
void onVisit(XformResolver* resolver) override;
136+
137+
private:
138+
SkRect fRect;
139+
SkClipOp fOp;
140+
};
141+
142+
#endif

0 commit comments

Comments
 (0)