Move annotations to canvas virtual (patchset #8 id:140001 of https://codereview.chromium.org/1744103002/ )"
Need to land chrome change first https://codereview.chromium.org/1766723003/
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1758023003
TBR=
Review URL: https://codereview.chromium.org/1758023003
diff --git a/src/core/SkAnnotation.cpp b/src/core/SkAnnotation.cpp
index 84d41fc..09a6296 100644
--- a/src/core/SkAnnotation.cpp
+++ b/src/core/SkAnnotation.cpp
@@ -6,38 +6,10 @@
*/
#include "SkAnnotation.h"
-#include "SkData.h"
-#include "SkPaint.h"
+#include "SkAnnotationKeys.h"
+#include "SkCanvas.h"
#include "SkPoint.h"
-#include "SkReadBuffer.h"
-#include "SkWriteBuffer.h"
-
-SkAnnotation::SkAnnotation(const char key[], SkData* value) : fKey(key) {
- if (nullptr == value) {
- value = SkData::NewEmpty();
- } else {
- value->ref();
- }
- fData = value;
-}
-
-SkAnnotation::~SkAnnotation() {
- fData->unref();
-}
-
-SkData* SkAnnotation::find(const char key[]) const {
- return fKey.equals(key) ? fData : nullptr;
-}
-
-SkAnnotation::SkAnnotation(SkReadBuffer& buffer) {
- buffer.readString(&fKey);
- fData = buffer.readByteArrayAsData();
-}
-
-void SkAnnotation::writeToBuffer(SkWriteBuffer& buffer) const {
- buffer.writeString(fKey.c_str());
- buffer.writeDataAsByteArray(fData);
-}
+#include "SkRect.h"
const char* SkAnnotationKeys::URL_Key() {
return "SkAnnotationKey_URL";
@@ -51,37 +23,26 @@
return "SkAnnotationKey_Link_Named_Dest";
};
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkCanvas.h"
-
-static void annotate_paint(SkPaint& paint, const char* key, SkData* value) {
- paint.setAnnotation(SkAnnotation::Create(key, value))->unref();
-}
+//////////////////////////////////////////////////////////////////////////////////////////////////
void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) {
if (nullptr == value) {
return;
}
- SkPaint paint;
- annotate_paint(paint, SkAnnotationKeys::URL_Key(), value);
- canvas->drawRect(rect, paint);
+ canvas->drawAnnotation(rect, SkAnnotationKeys::URL_Key(), value);
}
void SkAnnotateNamedDestination(SkCanvas* canvas, const SkPoint& point, SkData* name) {
if (nullptr == name) {
return;
}
- SkPaint paint;
- annotate_paint(paint, SkAnnotationKeys::Define_Named_Dest_Key(), name);
- canvas->drawPoint(point.x(), point.y(), paint);
+ const SkRect rect = SkRect::MakeXYWH(point.x(), point.y(), 0, 0);
+ canvas->drawAnnotation(rect, SkAnnotationKeys::Define_Named_Dest_Key(), name);
}
void SkAnnotateLinkToDestination(SkCanvas* canvas, const SkRect& rect, SkData* name) {
if (nullptr == name) {
return;
}
- SkPaint paint;
- annotate_paint(paint, SkAnnotationKeys::Link_Named_Dest_Key(), name);
- canvas->drawRect(rect, paint);
+ canvas->drawAnnotation(rect, SkAnnotationKeys::Link_Named_Dest_Key(), name);
}
diff --git a/src/core/SkAnnotationKeys.h b/src/core/SkAnnotationKeys.h
new file mode 100644
index 0000000..dff9338
--- /dev/null
+++ b/src/core/SkAnnotationKeys.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnnotationKeys_DEFINED
+#define SkAnnotationKeys_DEFINED
+
+#include "SkTypes.h"
+
+class SkAnnotationKeys {
+public:
+ /**
+ * Returns the canonical key whose payload is a URL
+ */
+ static const char* URL_Key();
+
+ /**
+ * Returns the canonical key whose payload is the name of a destination to
+ * be defined.
+ */
+ static const char* Define_Named_Dest_Key();
+
+ /**
+ * Returns the canonical key whose payload is the name of a destination to
+ * be linked to.
+ */
+ static const char* Link_Named_Dest_Key();
+};
+
+#endif
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 8c3c562..d5dfcc1 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -20,9 +20,6 @@
class SkColorTable;
-#define CHECK_FOR_ANNOTATION(paint) \
- do { if (paint.getAnnotation()) { return; } } while (0)
-
static bool valid_for_bitmap_device(const SkImageInfo& info,
SkAlphaType* newAlphaType) {
if (info.width() < 0 || info.height() < 0) {
@@ -204,18 +201,14 @@
void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
const SkPoint pts[], const SkPaint& paint) {
- CHECK_FOR_ANNOTATION(paint);
draw.drawPoints(mode, count, pts, paint);
}
void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
- CHECK_FOR_ANNOTATION(paint);
draw.drawRect(r, paint);
}
void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
- CHECK_FOR_ANNOTATION(paint);
-
SkPath path;
path.addOval(oval);
// call the VIRTUAL version, so any subclasses who do handle drawPath aren't
@@ -224,8 +217,6 @@
}
void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
- CHECK_FOR_ANNOTATION(paint);
-
#ifdef SK_IGNORE_BLURRED_RRECT_OPT
SkPath path;
@@ -241,7 +232,6 @@
void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
const SkPaint& paint, const SkMatrix* prePathMatrix,
bool pathIsMutable) {
- CHECK_FOR_ANNOTATION(paint);
draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
}
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index a628105..f3f3838 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1973,6 +1973,12 @@
this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
}
+void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
+ if (key) {
+ this->onDrawAnnotation(rect, key, value);
+ }
+}
+
void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint constraint) {
if (src) {
@@ -2725,6 +2731,17 @@
LOOPER_END
}
+void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
+ SkASSERT(key);
+
+ SkPaint paint;
+ LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
+ while (iter.next()) {
+ iter.fDevice->drawAnnotation(iter, rect, key, value);
+ }
+ LOOPER_END
+}
+
//////////////////////////////////////////////////////////////////////////////
// These methods are NOT virtual, and therefore must call back into virtual
// methods, rather than actually drawing themselves.
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 017662f..cdfb110 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -6,7 +6,6 @@
*/
#include "SkPaint.h"
-#include "SkAnnotation.h"
#include "SkAutoKern.h"
#include "SkChecksum.h"
#include "SkColorFilter.h"
@@ -54,7 +53,6 @@
fRasterizer = nullptr;
fLooper = nullptr;
fImageFilter = nullptr;
- fAnnotation = nullptr;
fTextSize = SkPaintDefaults_TextSize;
fTextScaleX = SK_Scalar1;
@@ -87,7 +85,6 @@
REF_COPY(fRasterizer);
REF_COPY(fLooper);
REF_COPY(fImageFilter);
- REF_COPY(fAnnotation);
COPY(fTextSize);
COPY(fTextScaleX);
@@ -114,7 +111,6 @@
REF_MOVE(fRasterizer);
REF_MOVE(fLooper);
REF_MOVE(fImageFilter);
- REF_MOVE(fAnnotation);
MOVE(fTextSize);
MOVE(fTextScaleX);
@@ -138,7 +134,6 @@
SkSafeUnref(fRasterizer);
SkSafeUnref(fLooper);
SkSafeUnref(fImageFilter);
- SkSafeUnref(fAnnotation);
}
SkPaint& SkPaint::operator=(const SkPaint& src) {
@@ -158,7 +153,6 @@
REF_COPY(fRasterizer);
REF_COPY(fLooper);
REF_COPY(fImageFilter);
- REF_COPY(fAnnotation);
COPY(fTextSize);
COPY(fTextScaleX);
@@ -191,7 +185,6 @@
REF_MOVE(fRasterizer);
REF_MOVE(fLooper);
REF_MOVE(fImageFilter);
- REF_MOVE(fAnnotation);
MOVE(fTextSize);
MOVE(fTextScaleX);
@@ -218,7 +211,6 @@
&& EQUAL(fRasterizer)
&& EQUAL(fLooper)
&& EQUAL(fImageFilter)
- && EQUAL(fAnnotation)
&& EQUAL(fTextSize)
&& EQUAL(fTextScaleX)
&& EQUAL(fTextSkewX)
@@ -420,11 +412,6 @@
return imageFilter;
}
-SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
- SkRefCnt_SafeAssign(fAnnotation, annotation);
- return annotation;
-}
-
///////////////////////////////////////////////////////////////////////////////
static SkScalar mag2(SkScalar x, SkScalar y) {
@@ -1897,7 +1884,6 @@
asint(this->getColorFilter()) |
asint(this->getRasterizer()) |
asint(this->getLooper()) |
- asint(this->getAnnotation()) |
asint(this->getImageFilter())) {
flatFlags |= kHasEffects_FlatFlag;
}
@@ -1931,13 +1917,6 @@
buffer.writeFlattenable(this->getRasterizer());
buffer.writeFlattenable(this->getLooper());
buffer.writeFlattenable(this->getImageFilter());
-
- if (fAnnotation) {
- buffer.writeBool(true);
- fAnnotation->writeToBuffer(buffer);
- } else {
- buffer.writeBool(false);
- }
}
}
@@ -1981,8 +1960,14 @@
SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
- if (buffer.readBool()) {
- this->setAnnotation(SkAnnotation::Create(buffer))->unref();
+ if (buffer.isVersionLT(SkReadBuffer::kAnnotationsMovedToCanvas_Version)) {
+ // We used to store annotations here (string+skdata) if this bool was true
+ if (buffer.readBool()) {
+ // Annotations have moved to drawAnnotation, so we just drop this one on the floor.
+ SkString key;
+ buffer.readString(&key);
+ SkSafeUnref(buffer.readByteArrayAsData());
+ }
}
} else {
this->setPathEffect(nullptr);
@@ -2205,12 +2190,6 @@
str->append("</dd>");
}
- SkAnnotation* annotation = this->getAnnotation();
- if (annotation) {
- str->append("<dt>Annotation:</dt><dd>");
- str->append("</dd>");
- }
-
str->append("<dt>Color:</dt><dd>0x");
SkColor color = this->getColor();
str->appendHex(color);
@@ -2437,7 +2416,7 @@
uint32_t SkPaint::getHash() const {
// We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
// so fBitfields should be 10 pointers and 6 32-bit values from the start.
- static_assert(offsetof(SkPaint, fBitfields) == 10 * sizeof(void*) + 6 * sizeof(uint32_t),
+ static_assert(offsetof(SkPaint, fBitfields) == 9 * sizeof(void*) + 6 * sizeof(uint32_t),
"SkPaint_notPackedTightly");
return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this),
offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 4eee04f..00b7c2b 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -78,7 +78,9 @@
SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016,
SAVE_LAYER_SAVELAYERREC,
- LAST_DRAWTYPE_ENUM = SAVE_LAYER_SAVELAYERREC,
+ DRAW_ANNOTATION,
+
+ LAST_DRAWTYPE_ENUM = DRAW_ANNOTATION,
};
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index a5dd814..e8497da 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -175,6 +175,12 @@
canvas->concat(matrix);
break;
}
+ case DRAW_ANNOTATION: {
+ const SkRect& rect = reader->skipT<SkRect>();
+ const char* key = reader->readString();
+ SkAutoTUnref<SkData> value(reader->readData());
+ canvas->drawAnnotation(rect, key, value);
+ } break;
case DRAW_ATLAS: {
const SkPaint* paint = fPictureData->getPaint(reader);
const SkImage* atlas = fPictureData->getImage(reader);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 2822a1a..2718ee9 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -777,6 +777,18 @@
this->validate(initialOffset, size);
}
+void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
+ size_t keyLen = fWriter.WriteStringSize(key);
+ size_t valueLen = fWriter.WriteDataSize(value);
+ size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
+
+ size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
+ this->addRect(rect);
+ fWriter.writeString(key);
+ fWriter.writeData(value);
+ this->validate(initialOffset, size);
+}
+
///////////////////////////////////////////////////////////////////////////////
SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 2e1e62a..607f6f1 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -204,6 +204,7 @@
void onClipRegion(const SkRegion&, SkRegion::Op) override;
void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+ void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
int addPathToHeap(const SkPath& path); // does not write to ops stream
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index 3d6dd36..b9b3094 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -60,6 +60,7 @@
kBitmapSourceFilterQuality_Version = 41,
kPictureShaderHasPictureBool_Version = 42,
kHasDrawImageOpCodes_Version = 43,
+ kAnnotationsMovedToCanvas_Version = 44,
};
/**
diff --git a/src/core/SkReader32.h b/src/core/SkReader32.h
index 68dda23..645d64c 100644
--- a/src/core/SkReader32.h
+++ b/src/core/SkReader32.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2008 The Android Open Source Project
*
@@ -10,6 +9,7 @@
#ifndef SkReader32_DEFINED
#define SkReader32_DEFINED
+#include "SkData.h"
#include "SkMatrix.h"
#include "SkPath.h"
#include "SkRegion.h"
@@ -135,6 +135,14 @@
*/
size_t readIntoString(SkString* copy);
+ SkData* readData() {
+ uint32_t byteLength = this->readU32();
+ if (0 == byteLength) {
+ return SkData::NewEmpty();
+ }
+ return SkData::NewWithCopy(this->skip(byteLength), byteLength);
+ }
+
private:
template <typename T> bool readObjectFromMemory(T* obj) {
size_t size = obj->readFromMemory(this->peek(), this->available());
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 5ca9517..0e4b5af 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -117,6 +117,7 @@
DRAW(DrawAtlas, drawAtlas(r.atlas, r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint));
DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
r.xmode, r.indices, r.indexCount, r.paint));
+DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value));
#undef DRAW
template <> void Draw::draw(const DrawDrawable& r) {
@@ -517,6 +518,10 @@
return this->adjustAndMap(op.worstCaseBounds, nullptr);
}
+ Bounds bounds(const DrawAnnotation& op) const {
+ return this->adjustAndMap(op.rect, nullptr);
+ }
+
static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) {
#ifdef SK_DEBUG
SkRect correct = *rect;
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 01c28df..f9fd8bb 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -332,6 +332,10 @@
this->copy(cull));
}
+void SkRecorder::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
+ APPEND(DrawAnnotation, rect, SkString(key), value);
+}
+
void SkRecorder::willSave() {
APPEND(Save);
}
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index cd5bc8a..7372e54 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -120,6 +120,7 @@
void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) override;
void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+ void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override { return nullptr; }
diff --git a/src/core/SkRemote.cpp b/src/core/SkRemote.cpp
index 22185cd..9b0383d 100644
--- a/src/core/SkRemote.cpp
+++ b/src/core/SkRemote.cpp
@@ -5,7 +5,6 @@
* found in the LICENSE file.
*/
-#include "SkAnnotation.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkDrawLooper.h"
@@ -127,7 +126,6 @@
fIDs.rasterizer = fEncoder->define(paint.getRasterizer());
fIDs.looper = fEncoder->define(paint.getLooper());
fIDs.imagefilter = fEncoder->define(paint.getImageFilter());
- fIDs.annotation = fEncoder->define(paint.getAnnotation());
}
~AutoCommonIDs() {
if (fEncoder) {
@@ -140,7 +138,6 @@
fEncoder->undefine(fIDs.rasterizer);
fEncoder->undefine(fIDs.looper);
fEncoder->undefine(fIDs.imagefilter);
- fEncoder->undefine(fIDs.annotation);
}
}
@@ -461,7 +458,6 @@
ID define(SkRasterizer* v)O{return this->define(Type::kRasterizer, &fRasterizer, v);}
ID define(SkDrawLooper* v)O{return this->define(Type::kDrawLooper, &fDrawLooper, v);}
ID define(SkImageFilter* v)O{return this->define(Type::kImageFilter, &fImageFilter, v);}
- ID define(SkAnnotation* v)O{return this->define(Type::kAnnotation, &fAnnotation, v);}
#undef O
@@ -480,7 +476,6 @@
case Type::kRasterizer: return fRasterizer .remove(id);
case Type::kDrawLooper: return fDrawLooper .remove(id);
case Type::kImageFilter: return fImageFilter.remove(id);
- case Type::kAnnotation: return fAnnotation .remove(id);
};
}
@@ -494,7 +489,6 @@
paint->setRasterizer (fRasterizer .find(common.rasterizer));
paint->setLooper (fDrawLooper .find(common.looper));
paint->setImageFilter(fImageFilter.find(common.imagefilter));
- paint->setAnnotation (fAnnotation .find(common.annotation));
}
void save() override { fCanvas->save(); }
@@ -617,7 +611,6 @@
ReffedIDMap<SkRasterizer , Type::kRasterizer > fRasterizer;
ReffedIDMap<SkDrawLooper , Type::kDrawLooper > fDrawLooper;
ReffedIDMap<SkImageFilter , Type::kImageFilter> fImageFilter;
- ReffedIDMap<SkAnnotation , Type::kAnnotation > fAnnotation;
SkCanvas* fCanvas;
uint64_t fNextID = 0;
@@ -653,7 +646,6 @@
fRasterizer .foreach(undef);
fDrawLooper .foreach(undef);
fImageFilter.foreach(undef);
- fAnnotation .foreach(undef);
}
template <typename Map, typename T>
@@ -679,7 +671,6 @@
ID define(SkRasterizer* v) override { return this->define(&fRasterizer , v); }
ID define(SkDrawLooper* v) override { return this->define(&fDrawLooper , v); }
ID define(SkImageFilter* v) override { return this->define(&fImageFilter, v); }
- ID define(SkAnnotation* v) override { return this->define(&fAnnotation , v); }
void undefine(ID) override {}
@@ -749,7 +740,6 @@
RefKeyMap<SkRasterizer , Type::kRasterizer > fRasterizer;
RefKeyMap<SkDrawLooper , Type::kDrawLooper > fDrawLooper;
RefKeyMap<SkImageFilter , Type::kImageFilter> fImageFilter;
- RefKeyMap<SkAnnotation , Type::kAnnotation > fAnnotation;
Encoder* fWrapped;
};
diff --git a/src/core/SkRemote.h b/src/core/SkRemote.h
index a1b1405..a8126d6 100644
--- a/src/core/SkRemote.h
+++ b/src/core/SkRemote.h
@@ -79,14 +79,13 @@
virtual ID define(SkRasterizer*) = 0;
virtual ID define(SkDrawLooper*) = 0;
virtual ID define(SkImageFilter*) = 0;
- virtual ID define(SkAnnotation*) = 0;
virtual void undefine(ID) = 0;
// TODO: do these all belong here in CommonIDs?
struct CommonIDs {
ID misc, patheffect, shader, xfermode, maskfilter,
- colorfilter, rasterizer, looper, imagefilter, annotation;
+ colorfilter, rasterizer, looper, imagefilter;
};
virtual void save() = 0;
diff --git a/src/core/SkRemote_protocol.h b/src/core/SkRemote_protocol.h
index 19bdc33..825a1c2 100644
--- a/src/core/SkRemote_protocol.h
+++ b/src/core/SkRemote_protocol.h
@@ -28,7 +28,6 @@
kRasterizer,
kDrawLooper,
kImageFilter,
- kAnnotation,
};
} // namespace SkRemote