• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 Google LLC.
2 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3 
4 #ifndef Fake_DEFINED
5 #define Fake_DEFINED
6 
7 #include "experimental/sorttoy/sorttypes.h"
8 
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkTypes.h"
14 
15 #include <vector>
16 
17 class Cmd;
18 class ClipCmd;
19 class FakeCanvas;
20 class SkBitmap;
21 class SkCanvas;
22 
23 constexpr SkColor SK_ColorUNUSED       = SkColorSetARGB(0x00, 0xFF, 0xFF, 0xFF);
24 
25 // This is roughly equivalent to a moment in time of an SkClipStack. It is snapped off of a
26 // FakeStateTracker.
27 class FakeMCBlob : public SkRefCnt {
28 public:
29     class MCState {
30     public:
MCState()31         MCState() {}
32 
33         void addClip(sk_sp<ClipCmd> clipCmd);
34 
translate(SkIPoint trans)35         void translate(SkIPoint trans) {
36             fTrans += trans;
37             fCached = nullptr;
38         }
39 
getTrans()40         SkIPoint getTrans() const { return fTrans; }
41 
42         bool operator==(const MCState& other) const;
43 
cmds()44         const std::vector<sk_sp<ClipCmd>>& cmds() const { return fCmds; }
45 
getCached()46         sk_sp<FakeMCBlob> getCached() const {
47             return fCached;
48         }
setCached(sk_sp<FakeMCBlob> cached)49         void setCached(sk_sp<FakeMCBlob> cached) {
50             fCached = cached;
51         }
52 
53         void aboutToBePopped(PaintersOrder paintersOrderWhenPopped);
54 
55     protected:
56         friend class FakeMCBlob;
57 
58         SkIPoint              fTrans { 0, 0 };
59         // The clip rects in the ClipCmds have been transformed into the 'parent' space of this
60         // MCState (i.e., in the coordinate frame of the MCState prior to this one in 'fStack').
61         // Alternatively, the 'fTrans' in effect when they were added has already been applied.
62         std::vector<sk_sp<ClipCmd>> fCmds;
63         sk_sp<FakeMCBlob>           fCached;
64     };
65 
66     FakeMCBlob(const std::vector<MCState>& stack);
67 
count()68     int count() const { return fStack.size(); }
id()69     int id() const { return fID; }
ctm()70     SkIPoint ctm() const { return fCTM; }
mcStates()71     const std::vector<MCState>& mcStates() const { return fStack; }
72     const MCState& operator[](int index) const { return fStack[index]; }
scissor()73     SkIRect scissor() const { return fScissor; }
74 
75 private:
NextID()76     static int NextID() {
77         static int sID = 1;
78         return sID++;
79     }
80 
81     const int            fID;
82     SkIPoint             fCTM { 0, 0 };
83     SkIRect              fScissor;
84     std::vector<MCState> fStack;
85 };
86 
87 class FakeStateTracker {
88 public:
FakeStateTracker()89     FakeStateTracker() {
90         fStack.push_back(FakeMCBlob::MCState());
91     }
92 
snapState()93     sk_sp<FakeMCBlob> snapState() {
94         sk_sp<FakeMCBlob> tmp = fStack.back().getCached();
95         if (tmp) {
96             return tmp;
97         }
98 
99         tmp = sk_make_sp<FakeMCBlob>(fStack);
100         fStack.back().setCached(tmp);
101         return tmp;
102     }
103 
push()104     void push() {
105         fStack.push_back(FakeMCBlob::MCState());
106     }
107 
clip(sk_sp<ClipCmd> clipCmd)108     void clip(sk_sp<ClipCmd> clipCmd) {
109         fStack.back().addClip(std::move(clipCmd));
110     }
111 
112     // For now we only store translates - in the full Skia this would be the whole 4x4 matrix
translate(SkIPoint trans)113     void translate(SkIPoint trans) {
114         fStack.back().translate(trans);
115     }
116 
pop(PaintersOrder paintersOrderWhenPopped)117     void pop(PaintersOrder paintersOrderWhenPopped) {
118         SkASSERT(fStack.size() > 0);
119         fStack.back().aboutToBePopped(paintersOrderWhenPopped);
120         fStack.pop_back();
121     }
122 
123 protected:
124 
125 private:
126     std::vector<FakeMCBlob::MCState> fStack;
127 };
128 
129 // The FakePaint simulates two aspects of the SkPaint:
130 //
131 // Batching based on FP context changes:
132 //   There are three types of paint (solid color, linear gradient and radial gradient) and,
133 //   ideally, they would all be batched together
134 //
135 // Transparency:
136 //   The transparent objects need to be draw back to front.
137 class FakePaint {
138 public:
FakePaint()139     FakePaint() {}
FakePaint(SkColor c)140     FakePaint(SkColor c)
141         : fType(Type::kNormal)
142         , fColor0(c)
143         , fColor1(SK_ColorUNUSED) {
144     }
145 
setColor(SkColor c)146     void setColor(SkColor c) {
147         fType = Type::kNormal;
148         fColor0 = c;
149         fColor1 = SK_ColorUNUSED;
150     }
getColor()151     SkColor getColor() const {
152         SkASSERT(fType == Type::kNormal);
153         return fColor0;
154     }
155 
setLinear(SkColor c0,SkColor c1)156     void setLinear(SkColor c0, SkColor c1) {
157         fType = Type::kLinear;
158         fColor0 = c0;
159         fColor1 = c1;
160     }
161 
setRadial(SkColor c0,SkColor c1)162     void setRadial(SkColor c0, SkColor c1) {
163         fType = Type::kRadial;
164         fColor0 = c0;
165         fColor1 = c1;
166     }
167 
c0()168     SkColor c0() const { return fColor0; }
c1()169     SkColor c1() const { return fColor1; }
170 
isTransparent()171     bool isTransparent() const {
172         if (fType == Type::kNormal) {
173             return 0xFF != SkColorGetA(fColor0);
174         } else {
175             return 0xFF != SkColorGetA(fColor0) && 0xFF != SkColorGetA(fColor1);
176         }
177     }
178 
179     // Get a material id for this paint that should be jammed into the sort key
180     int toID() const;
181 
182     SkColor evalColor(int x, int y) const;
183 
184 protected:
185 
186 private:
187     enum class Type {
188         kNormal,
189         kLinear,
190         kRadial
191     };
192 
193     Type    fType   = Type::kNormal;
194     SkColor fColor0 = SK_ColorBLACK;
195     SkColor fColor1 = SK_ColorBLACK;
196 };
197 
198 class FakeDevice {
199 public:
FakeDevice(SkBitmap bm)200     FakeDevice(SkBitmap bm) : fBM(bm) {
201         SkASSERT(bm.width() == 256 && bm.height() == 256);
202 
203         memset(fZBuffer, 0, sizeof(fZBuffer));
204     }
205 
~FakeDevice()206     ~FakeDevice() {}
207 
208     void save();
209     void drawShape(ID, PaintersOrder, Shape, SkIRect, FakePaint);
210     void clipShape(ID, PaintersOrder, Shape, SkIRect);
translate(SkIPoint trans)211     void translate(SkIPoint trans) {
212         fTracker.translate(trans);
213     }
214 
215     void restore(PaintersOrder paintersOrderWhenPopped);
216 
217     void finalize();
218 
219     void getOrder(std::vector<ID>*) const;
snapState()220     sk_sp<FakeMCBlob> snapState() { return fTracker.snapState(); }
221 
222 protected:
223 
224 private:
225     void sort();
226 
227     bool                    fFinalized = false;
228     std::vector<sk_sp<Cmd>> fSortedCmds;
229 
230     FakeStateTracker        fTracker;
231     SkBitmap                fBM;
232     uint32_t                fZBuffer[256][256];
233 };
234 
235 class FakeCanvas {
236 public:
FakeCanvas(SkBitmap & bm)237     FakeCanvas(SkBitmap& bm) {
238         fDeviceStack.push_back(std::make_unique<FakeDevice>(bm));
239     }
240 
saveLayer()241     void saveLayer() {
242         SkASSERT(!fFinalized);
243 
244         // TODO: implement
245     }
246 
save()247     void save() {
248         SkASSERT(!fFinalized);
249         fDeviceStack.back()->save();
250     }
251 
252     void drawShape(ID, Shape, SkIRect, FakePaint);
253 
254     void clipShape(ID, Shape, SkIRect);
255 
translate(SkIPoint trans)256     void translate(SkIPoint trans) {
257         SkASSERT(!fFinalized);
258 
259         fDeviceStack.back()->translate(trans);
260     }
261 
restore()262     void restore() {
263         SkASSERT(!fFinalized);
264         fDeviceStack.back()->restore(this->peekPaintersOrder());
265     }
266 
267     void finalize();
268 
269     std::vector<ID> getOrder() const;
snapState()270     sk_sp<FakeMCBlob> snapState() {
271         return fDeviceStack.back()->snapState();
272     }
273 
274 protected:
275 
276 private:
nextPaintersOrder()277     PaintersOrder nextPaintersOrder() {
278         return PaintersOrder(fNextPaintersOrder++);
279     }
peekPaintersOrder()280     PaintersOrder peekPaintersOrder() const {
281         return PaintersOrder(fNextPaintersOrder);
282     }
283 
284     uint32_t                                 fNextPaintersOrder = 1;
285     bool                                     fFinalized = false;
286     std::vector<std::unique_ptr<FakeDevice>> fDeviceStack;
287 };
288 
289 
290 #endif // Fake_DEFINED
291