2015-03-25 14:11:02 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2015 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
#ifndef DMSrcSink_DEFINED
|
|
|
|
#define DMSrcSink_DEFINED
|
|
|
|
|
|
|
|
#include "DMGpuSupport.h"
|
|
|
|
#include "SkBBHFactory.h"
|
|
|
|
#include "SkBBoxHierarchy.h"
|
|
|
|
#include "SkBitmap.h"
|
2015-11-06 16:56:32 +00:00
|
|
|
#include "SkBitmapRegionDecoder.h"
|
2015-01-15 18:56:12 +00:00
|
|
|
#include "SkCanvas.h"
|
|
|
|
#include "SkData.h"
|
|
|
|
#include "SkGPipe.h"
|
|
|
|
#include "SkPicture.h"
|
|
|
|
#include "gm.h"
|
|
|
|
|
|
|
|
namespace DM {
|
|
|
|
|
|
|
|
// This is just convenience. It lets you use either return "foo" or return SkStringPrintf(...).
|
|
|
|
struct ImplicitString : public SkString {
|
|
|
|
template <typename T>
|
|
|
|
ImplicitString(const T& s) : SkString(s) {}
|
2015-09-01 21:57:57 +00:00
|
|
|
ImplicitString() : SkString("") {}
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
typedef ImplicitString Name;
|
2015-01-30 19:42:31 +00:00
|
|
|
typedef ImplicitString Path;
|
2015-01-15 18:56:12 +00:00
|
|
|
|
2015-03-05 16:40:28 +00:00
|
|
|
class Error {
|
|
|
|
public:
|
|
|
|
Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
|
|
|
|
Error(const char* s) : fMsg(s), fFatal(!this->isEmpty()) {}
|
|
|
|
|
|
|
|
Error(const Error&) = default;
|
|
|
|
Error& operator=(const Error&) = default;
|
|
|
|
|
|
|
|
static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
|
|
|
|
static Error Nonfatal(const char* s) {
|
|
|
|
Error e(s);
|
|
|
|
e.fFatal = false;
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* c_str() const { return fMsg.c_str(); }
|
|
|
|
bool isEmpty() const { return fMsg.isEmpty(); }
|
|
|
|
bool isFatal() const { return fFatal; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
SkString fMsg;
|
|
|
|
bool fFatal;
|
|
|
|
};
|
|
|
|
|
2015-07-31 13:43:04 +00:00
|
|
|
struct SinkFlags {
|
|
|
|
enum { kNull, kGPU, kVector, kRaster } type;
|
|
|
|
enum { kDirect, kIndirect } approach;
|
|
|
|
};
|
2015-07-29 13:37:28 +00:00
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
struct Src {
|
|
|
|
// All Srcs must be thread safe.
|
|
|
|
virtual ~Src() {}
|
|
|
|
virtual Error SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
|
|
|
|
virtual SkISize size() const = 0;
|
|
|
|
virtual Name name() const = 0;
|
2015-05-27 20:23:23 +00:00
|
|
|
virtual void modifyGrContextOptions(GrContextOptions* options) const {}
|
2015-07-31 13:43:04 +00:00
|
|
|
virtual bool veto(SinkFlags) const { return false; }
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Sink {
|
|
|
|
virtual ~Sink() {}
|
2015-02-03 02:26:03 +00:00
|
|
|
// You may write to either the bitmap or stream. If you write to log, we'll print that out.
|
|
|
|
virtual Error SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log)
|
|
|
|
const = 0;
|
2015-01-15 18:56:12 +00:00
|
|
|
// Sinks in the same enclave (except kAnyThread_Enclave) will run serially on the same thread.
|
|
|
|
virtual int enclave() const = 0;
|
|
|
|
|
|
|
|
// File extension for the content draw() outputs, e.g. "png", "pdf".
|
|
|
|
virtual const char* fileExtension() const = 0;
|
2015-07-31 13:43:04 +00:00
|
|
|
|
|
|
|
virtual SinkFlags flags() const = 0;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
2015-02-20 15:21:05 +00:00
|
|
|
enum { kAnyThread_Enclave, kGPU_Enclave };
|
|
|
|
static const int kNumEnclaves = kGPU_Enclave + 1;
|
2015-01-15 18:56:12 +00:00
|
|
|
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
|
|
|
|
class GMSrc : public Src {
|
|
|
|
public:
|
|
|
|
explicit GMSrc(skiagm::GMRegistry::Factory);
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(SkCanvas*) const override;
|
|
|
|
SkISize size() const override;
|
|
|
|
Name name() const override;
|
2015-05-27 20:23:23 +00:00
|
|
|
void modifyGrContextOptions(GrContextOptions* options) const override;
|
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
|
|
|
skiagm::GMRegistry::Factory fFactory;
|
|
|
|
};
|
|
|
|
|
2015-03-19 13:03:39 +00:00
|
|
|
class CodecSrc : public Src {
|
|
|
|
public:
|
2015-03-25 20:48:49 +00:00
|
|
|
enum Mode {
|
2015-09-01 21:57:57 +00:00
|
|
|
kCodec_Mode,
|
2015-03-25 20:48:49 +00:00
|
|
|
kScanline_Mode,
|
2015-06-11 21:27:27 +00:00
|
|
|
kStripe_Mode, // Tests the skipping of scanlines
|
2015-07-22 14:16:20 +00:00
|
|
|
kSubset_Mode, // For codecs that support subsets directly.
|
2015-03-25 20:48:49 +00:00
|
|
|
};
|
2015-04-09 19:43:10 +00:00
|
|
|
enum DstColorType {
|
|
|
|
kGetFromCanvas_DstColorType,
|
|
|
|
kIndex8_Always_DstColorType,
|
|
|
|
kGrayscale_Always_DstColorType,
|
|
|
|
};
|
2015-06-11 21:27:27 +00:00
|
|
|
CodecSrc(Path, Mode, DstColorType, float);
|
2015-03-19 13:03:39 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(SkCanvas*) const override;
|
|
|
|
SkISize size() const override;
|
|
|
|
Name name() const override;
|
2015-07-31 13:43:04 +00:00
|
|
|
bool veto(SinkFlags) const override;
|
2015-03-19 13:03:39 +00:00
|
|
|
private:
|
2015-09-01 21:57:57 +00:00
|
|
|
Path fPath;
|
|
|
|
Mode fMode;
|
|
|
|
DstColorType fDstColorType;
|
|
|
|
float fScale;
|
2015-03-19 13:03:39 +00:00
|
|
|
};
|
|
|
|
|
2015-10-21 17:27:10 +00:00
|
|
|
class AndroidCodecSrc : public Src {
|
|
|
|
public:
|
|
|
|
enum Mode {
|
|
|
|
kFullImage_Mode,
|
|
|
|
// Splits the image into multiple subsets using a divisor and decodes the subsets
|
|
|
|
// separately.
|
|
|
|
kDivisor_Mode,
|
|
|
|
};
|
|
|
|
|
|
|
|
AndroidCodecSrc(Path, Mode, CodecSrc::DstColorType, int sampleSize);
|
|
|
|
|
|
|
|
Error draw(SkCanvas*) const override;
|
|
|
|
SkISize size() const override;
|
|
|
|
Name name() const override;
|
|
|
|
bool veto(SinkFlags) const override;
|
|
|
|
private:
|
|
|
|
Path fPath;
|
|
|
|
Mode fMode;
|
|
|
|
CodecSrc::DstColorType fDstColorType;
|
|
|
|
int fSampleSize;
|
|
|
|
};
|
|
|
|
|
2015-09-08 22:35:32 +00:00
|
|
|
// Allows for testing of various implementations of Android's BitmapRegionDecoder
|
|
|
|
class BRDSrc : public Src {
|
|
|
|
public:
|
|
|
|
enum Mode {
|
|
|
|
// Decode the entire image as one region.
|
|
|
|
kFullImage_Mode,
|
|
|
|
// Splits the image into multiple regions using a divisor and decodes the regions
|
|
|
|
// separately. Also, this test adds a border of a few pixels to each of the regions
|
|
|
|
// that it is decoding. This tests the behavior when a client asks for a region that
|
|
|
|
// does not fully fit in the image.
|
|
|
|
kDivisor_Mode,
|
|
|
|
};
|
|
|
|
|
2015-11-06 16:56:32 +00:00
|
|
|
BRDSrc(Path, SkBitmapRegionDecoder::Strategy, Mode, CodecSrc::DstColorType, uint32_t);
|
2015-09-08 22:35:32 +00:00
|
|
|
|
|
|
|
Error draw(SkCanvas*) const override;
|
|
|
|
SkISize size() const override;
|
|
|
|
Name name() const override;
|
|
|
|
bool veto(SinkFlags) const override;
|
|
|
|
private:
|
|
|
|
Path fPath;
|
2015-11-06 16:56:32 +00:00
|
|
|
SkBitmapRegionDecoder::Strategy fStrategy;
|
2015-09-08 22:35:32 +00:00
|
|
|
Mode fMode;
|
|
|
|
CodecSrc::DstColorType fDstColorType;
|
|
|
|
uint32_t fSampleSize;
|
|
|
|
};
|
2015-03-19 13:03:39 +00:00
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
class ImageSrc : public Src {
|
|
|
|
public:
|
2015-11-10 23:09:03 +00:00
|
|
|
explicit ImageSrc(Path path);
|
2015-01-15 18:56:12 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(SkCanvas*) const override;
|
|
|
|
SkISize size() const override;
|
|
|
|
Name name() const override;
|
2015-07-31 13:43:04 +00:00
|
|
|
bool veto(SinkFlags) const override;
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
2015-01-30 19:42:31 +00:00
|
|
|
Path fPath;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class SKPSrc : public Src {
|
|
|
|
public:
|
2015-01-30 19:42:31 +00:00
|
|
|
explicit SKPSrc(Path path);
|
2015-01-15 18:56:12 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(SkCanvas*) const override;
|
|
|
|
SkISize size() const override;
|
|
|
|
Name name() const override;
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
2015-01-30 19:42:31 +00:00
|
|
|
Path fPath;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
|
2015-02-13 23:11:10 +00:00
|
|
|
class NullSink : public Sink {
|
|
|
|
public:
|
|
|
|
NullSink() {}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override { return kAnyThread_Enclave; }
|
|
|
|
const char* fileExtension() const override { return ""; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
|
2015-02-13 23:11:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
class GPUSink : public Sink {
|
|
|
|
public:
|
2015-12-10 14:28:13 +00:00
|
|
|
GPUSink(GrContextFactory::GLContextType, GrContextFactory::GLContextOptions,
|
|
|
|
GrGLStandard, int samples, bool diText, bool threaded);
|
2015-01-15 18:56:12 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override;
|
|
|
|
const char* fileExtension() const override { return "png"; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect }; }
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
2015-12-10 14:28:13 +00:00
|
|
|
GrContextFactory::GLContextType fContextType;
|
|
|
|
GrContextFactory::GLContextOptions fContextOptions;
|
|
|
|
GrGLStandard fGpuAPI;
|
|
|
|
int fSampleCount;
|
|
|
|
bool fUseDIText;
|
|
|
|
bool fThreaded;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class PDFSink : public Sink {
|
|
|
|
public:
|
2015-09-28 18:51:54 +00:00
|
|
|
PDFSink(const char* rasterizer);
|
2015-01-15 18:56:12 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override { return kAnyThread_Enclave; }
|
|
|
|
const char* fileExtension() const override { return "pdf"; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
|
2015-09-28 18:51:54 +00:00
|
|
|
private:
|
|
|
|
const char* fRasterizer;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
2015-03-03 17:13:09 +00:00
|
|
|
class XPSSink : public Sink {
|
|
|
|
public:
|
|
|
|
XPSSink();
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override { return kAnyThread_Enclave; }
|
|
|
|
const char* fileExtension() const override { return "xps"; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
|
2015-03-03 17:13:09 +00:00
|
|
|
};
|
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
class RasterSink : public Sink {
|
|
|
|
public:
|
|
|
|
explicit RasterSink(SkColorType);
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override { return kAnyThread_Enclave; }
|
|
|
|
const char* fileExtension() const override { return "png"; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
|
|
|
SkColorType fColorType;
|
|
|
|
};
|
|
|
|
|
2015-01-28 19:35:18 +00:00
|
|
|
class SKPSink : public Sink {
|
|
|
|
public:
|
|
|
|
SKPSink();
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override { return kAnyThread_Enclave; }
|
|
|
|
const char* fileExtension() const override { return "skp"; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
|
2015-01-28 19:35:18 +00:00
|
|
|
};
|
|
|
|
|
2015-02-01 04:00:58 +00:00
|
|
|
class SVGSink : public Sink {
|
|
|
|
public:
|
|
|
|
SVGSink();
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
int enclave() const override { return kAnyThread_Enclave; }
|
|
|
|
const char* fileExtension() const override { return "svg"; }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
|
2015-02-01 04:00:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class Via : public Sink {
|
2015-01-15 18:56:12 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
explicit Via(Sink* sink) : fSink(sink) {}
|
2015-03-26 01:17:31 +00:00
|
|
|
const char* fileExtension() const override { return fSink->fileExtension(); }
|
2015-05-06 14:54:07 +00:00
|
|
|
int enclave() const override { return fSink->enclave(); }
|
2015-07-31 13:43:04 +00:00
|
|
|
SinkFlags flags() const override {
|
|
|
|
SinkFlags flags = fSink->flags();
|
|
|
|
flags.approach = SinkFlags::kIndirect;
|
|
|
|
return flags;
|
|
|
|
}
|
2015-05-06 14:54:07 +00:00
|
|
|
protected:
|
2015-01-15 18:56:12 +00:00
|
|
|
SkAutoTDelete<Sink> fSink;
|
|
|
|
};
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaMatrix : public Via {
|
2015-02-17 19:13:33 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
ViaMatrix(SkMatrix, Sink*);
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
2015-02-17 19:13:33 +00:00
|
|
|
private:
|
2015-05-06 14:54:07 +00:00
|
|
|
const SkMatrix fMatrix;
|
2015-02-17 19:13:33 +00:00
|
|
|
};
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaUpright : public Via {
|
2015-01-15 18:56:12 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
ViaUpright(SkMatrix, Sink*);
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
2015-05-06 14:54:07 +00:00
|
|
|
const SkMatrix fMatrix;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaPipe : public Via {
|
2015-05-05 15:11:33 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
explicit ViaPipe(Sink* sink) : Via(sink) {}
|
2015-05-05 15:11:33 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
};
|
|
|
|
|
2015-10-16 17:29:41 +00:00
|
|
|
class ViaRemote : public Via {
|
2015-01-15 18:56:12 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
ViaRemote(bool cache, Sink* sink) : Via(sink), fCache(cache) {}
|
2015-05-06 14:54:07 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
2015-10-16 17:29:41 +00:00
|
|
|
private:
|
|
|
|
bool fCache;
|
2015-05-06 14:54:07 +00:00
|
|
|
};
|
2015-01-15 18:56:12 +00:00
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaSerialization : public Via {
|
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
explicit ViaSerialization(Sink* sink) : Via(sink) {}
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
2015-01-15 18:56:12 +00:00
|
|
|
};
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaTiles : public Via {
|
2015-01-15 18:56:12 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
ViaTiles(int w, int h, SkBBHFactory*, Sink*);
|
2015-03-26 01:17:31 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
2015-01-15 18:56:12 +00:00
|
|
|
private:
|
|
|
|
const int fW, fH;
|
|
|
|
SkAutoTDelete<SkBBHFactory> fFactory;
|
|
|
|
};
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaSecondPicture : public Via {
|
2015-04-07 15:30:32 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
explicit ViaSecondPicture(Sink* sink) : Via(sink) {}
|
2015-04-07 15:30:32 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
};
|
|
|
|
|
2015-05-06 14:54:07 +00:00
|
|
|
class ViaSingletonPictures : public Via {
|
2015-05-05 19:59:56 +00:00
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
explicit ViaSingletonPictures(Sink* sink) : Via(sink) {}
|
2015-05-05 19:59:56 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
};
|
|
|
|
|
2015-05-06 18:35:40 +00:00
|
|
|
class ViaTwice : public Via {
|
|
|
|
public:
|
2015-12-10 23:14:27 +00:00
|
|
|
explicit ViaTwice(Sink* sink) : Via(sink) {}
|
2015-05-06 18:35:40 +00:00
|
|
|
Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
|
|
|
|
};
|
|
|
|
|
2015-01-15 18:56:12 +00:00
|
|
|
} // namespace DM
|
|
|
|
|
|
|
|
#endif//DMSrcSink_DEFINED
|