Index: src/core/SkRemote.cpp |
diff --git a/src/core/SkRemote.cpp b/src/core/SkRemote.cpp |
index 3966aaccc0318afba694f8775f00fdb6617d4eb4..8efeb8b8451f766dacc295c0d487e427fad741ea 100644 |
--- a/src/core/SkRemote.cpp |
+++ b/src/core/SkRemote.cpp |
@@ -97,15 +97,16 @@ namespace SkRemote { |
Cache* Cache::CreateNeverCache() { |
struct NeverCache final : public Cache { |
NeverCache() |
- : fNextMatrix(Type::kMatrix) |
- , fNextMisc (Type::kMisc) |
- , fNextPath (Type::kPath) |
- , fNextStroke(Type::kStroke) |
+ : fNextMatrix (Type::kMatrix) |
+ , fNextMisc (Type::kMisc) |
+ , fNextPath (Type::kPath) |
+ , fNextStroke (Type::kStroke) |
+ , fNextXfermode(Type::kXfermode) |
{} |
void cleanup(Encoder*) override {} |
static bool Helper(ID* next, ID* id, LookupScope* ls) { |
- *id = (*next)++; |
+ *id = ++(*next); |
ls->undefineWhenDone(*id); |
return false; |
} |
@@ -122,65 +123,120 @@ namespace SkRemote { |
bool lookup(const Stroke&, ID* id, LookupScope* ls) override { |
return Helper(&fNextStroke, id, ls); |
} |
+ bool lookup(const SkXfermode* xfermode, ID* id, LookupScope* ls) override { |
+ if (!xfermode) { |
+ *id = ID(Type::kXfermode); |
+ return true; // Null IDs are always defined. |
+ } |
+ return Helper(&fNextXfermode, id, ls); |
+ } |
ID fNextMatrix, |
fNextMisc, |
fNextPath, |
- fNextStroke; |
+ fNextStroke, |
+ fNextXfermode; |
}; |
return new NeverCache; |
} |
- // Can't be declared locally inside AlwaysCache because of the templating. :( |
- template <typename T, typename Map> |
- static bool always_cache_helper(const T& val, Map* map, ID* next, ID* id) { |
- if (ID* found = map->find(val)) { |
- *id = *found; |
- return true; |
+ // These can't be declared locally inside AlwaysCache because of the templating. :( |
+ namespace { |
+ template <typename T, typename Map> |
+ static bool always_cache_lookup(const T& val, Map* map, ID* next, ID* id) { |
+ if (const ID* found = map->find(val)) { |
+ *id = *found; |
+ return true; |
+ } |
+ *id = ++(*next); |
+ map->set(val, *id); |
+ return false; |
} |
- *id = (*next)++; |
- map->set(val, *id); |
- return false; |
- } |
+ |
+ struct Undefiner { |
+ Encoder* fEncoder; |
+ |
+ template <typename T> |
+ void operator()(const T&, ID* id) const { fEncoder->undefine(*id); } |
+ }; |
+ |
+ // Maps const T* -> ID, and refs the key. nullptr always maps to ID(kType). |
+ template <typename T, Type kType> |
+ class RefKeyMap { |
+ public: |
+ RefKeyMap() {} |
+ ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { key->unref(); }); } |
+ |
+ void set(const T* key, const ID& id) { |
+ SkASSERT(key && id.type() == kType); |
+ fMap.set(SkRef(key), id); |
+ } |
+ |
+ void remove(const T* key) { |
+ SkASSERT(key); |
+ fMap.remove(key); |
+ key->unref(); |
+ } |
+ |
+ const ID* find(const T* key) const { |
+ static const ID nullID(kType); |
+ return key ? fMap.find(key) : &nullID; |
+ } |
+ |
+ template <typename Fn> |
+ void foreach(const Fn& fn) { fMap.foreach(fn); } |
+ private: |
+ SkTHashMap<const T*, ID> fMap; |
+ }; |
+ } // namespace |
Cache* Cache::CreateAlwaysCache() { |
struct AlwaysCache final : public Cache { |
AlwaysCache() |
- : fNextMatrix(Type::kMatrix) |
- , fNextMisc (Type::kMisc) |
- , fNextPath (Type::kPath) |
- , fNextStroke(Type::kStroke) |
+ : fNextMatrix (Type::kMatrix) |
+ , fNextMisc (Type::kMisc) |
+ , fNextPath (Type::kPath) |
+ , fNextStroke (Type::kStroke) |
+ , fNextXfermode(Type::kXfermode) |
{} |
void cleanup(Encoder* encoder) override { |
- fMatrix.foreach([=](const SkMatrix&, ID* id) { encoder->undefine(*id); }); |
- fMisc .foreach([=](const Misc&, ID* id) { encoder->undefine(*id); }); |
- fPath .foreach([=](const SkPath&, ID* id) { encoder->undefine(*id); }); |
- fStroke.foreach([=](const Stroke&, ID* id) { encoder->undefine(*id); }); |
+ Undefiner undef{encoder}; |
+ fMatrix .foreach(undef); |
+ fMisc .foreach(undef); |
+ fPath .foreach(undef); |
+ fStroke .foreach(undef); |
+ fXfermode.foreach(undef); |
} |
bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override { |
- return always_cache_helper(matrix, &fMatrix, &fNextMatrix, id); |
+ return always_cache_lookup(matrix, &fMatrix, &fNextMatrix, id); |
} |
bool lookup(const Misc& misc, ID* id, LookupScope*) override { |
- return always_cache_helper(misc, &fMisc, &fNextMisc, id); |
+ return always_cache_lookup(misc, &fMisc, &fNextMisc, id); |
} |
bool lookup(const SkPath& path, ID* id, LookupScope*) override { |
- return always_cache_helper(path, &fPath, &fNextPath, id); |
+ return always_cache_lookup(path, &fPath, &fNextPath, id); |
} |
bool lookup(const Stroke& stroke, ID* id, LookupScope*) override { |
- return always_cache_helper(stroke, &fStroke, &fNextStroke, id); |
+ return always_cache_lookup(stroke, &fStroke, &fNextStroke, id); |
} |
+ bool lookup(const SkXfermode* xfermode, ID* id, LookupScope*) override { |
+ return always_cache_lookup(xfermode, &fXfermode, &fNextXfermode, id); |
+ } |
+ |
+ SkTHashMap<SkMatrix, ID> fMatrix; |
+ SkTHashMap<Misc, ID, MiscHash> fMisc; |
+ SkTHashMap<SkPath, ID> fPath; |
+ SkTHashMap<Stroke, ID> fStroke; |
+ RefKeyMap<SkXfermode, Type::kXfermode> fXfermode; |
- SkTHashMap<SkMatrix, ID> fMatrix; |
- SkTHashMap<Misc, ID, MiscHash> fMisc; |
- SkTHashMap<SkPath, ID> fPath; |
- SkTHashMap<Stroke, ID> fStroke; |
ID fNextMatrix, |
fNextMisc, |
fNextPath, |
- fNextStroke; |
+ fNextStroke, |
+ fNextXfermode; |
}; |
return new AlwaysCache; |
} |
@@ -236,13 +292,14 @@ namespace SkRemote { |
void Client::onDrawPath(const SkPath& path, const SkPaint& paint) { |
LookupScope ls(fCache, fEncoder); |
ID p = ls.lookup(path), |
- m = ls.lookup(Misc::CreateFrom(paint)); |
+ m = ls.lookup(Misc::CreateFrom(paint)), |
+ x = ls.lookup(paint.getXfermode()); |
if (paint.getStyle() == SkPaint::kFill_Style) { |
- fEncoder->fillPath(p, m); |
+ fEncoder->fillPath(p, m, x); |
} else { |
// TODO: handle kStrokeAndFill_Style |
- fEncoder->strokePath(p, m, ls.lookup(Stroke::CreateFrom(paint))); |
+ fEncoder->strokePath(p, m, x, ls.lookup(Stroke::CreateFrom(paint))); |
} |
} |
@@ -302,17 +359,19 @@ namespace SkRemote { |
Server::Server(SkCanvas* canvas) : fCanvas(canvas) {} |
- void Server::define(ID id, const SkMatrix& v) { fMatrix.set(id, v); } |
- void Server::define(ID id, const Misc& v) { fMisc .set(id, v); } |
- void Server::define(ID id, const SkPath& v) { fPath .set(id, v); } |
- void Server::define(ID id, const Stroke& v) { fStroke.set(id, v); } |
+ void Server::define(ID id, const SkMatrix& v) { fMatrix .set(id, v); } |
+ void Server::define(ID id, const Misc& v) { fMisc .set(id, v); } |
+ void Server::define(ID id, const SkPath& v) { fPath .set(id, v); } |
+ void Server::define(ID id, const Stroke& v) { fStroke .set(id, v); } |
+ void Server::define(ID id, SkXfermode* v) { fXfermode.set(id, v); } |
void Server::undefine(ID id) { |
switch(id.type()) { |
- case Type::kMatrix: return fMatrix.remove(id); |
- case Type::kMisc: return fMisc .remove(id); |
- case Type::kPath: return fPath .remove(id); |
- case Type::kStroke: return fStroke.remove(id); |
+ case Type::kMatrix: return fMatrix .remove(id); |
+ case Type::kMisc: return fMisc .remove(id); |
+ case Type::kPath: return fPath .remove(id); |
+ case Type::kStroke: return fStroke .remove(id); |
+ case Type::kXfermode: return fXfermode.remove(id); |
case Type::kNone: SkASSERT(false); |
}; |
@@ -326,17 +385,19 @@ namespace SkRemote { |
void Server::clipPath(ID path, SkRegion::Op op, bool aa) { |
fCanvas->clipPath(fPath.find(path), op, aa); |
} |
- void Server::fillPath(ID path, ID misc) { |
+ void Server::fillPath(ID path, ID misc, ID xfermode) { |
SkPaint paint; |
paint.setStyle(SkPaint::kFill_Style); |
fMisc.find(misc).applyTo(&paint); |
+ paint.setXfermode(fXfermode.find(xfermode)); |
fCanvas->drawPath(fPath.find(path), paint); |
} |
- void Server::strokePath(ID path, ID misc, ID stroke) { |
+ void Server::strokePath(ID path, ID misc, ID xfermode, ID stroke) { |
SkPaint paint; |
paint.setStyle(SkPaint::kStroke_Style); |
fMisc .find(misc ).applyTo(&paint); |
fStroke.find(stroke).applyTo(&paint); |
+ paint.setXfermode(fXfermode.find(xfermode)); |
fCanvas->drawPath(fPath.find(path), paint); |
} |