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