Make SkBlitter hierarchy explicit about what needs to be implemented.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2053823002

Review-Url: https://codereview.chromium.org/2053823002
This commit is contained in:
herb 2016-06-10 13:01:27 -07:00 committed by Commit bot
parent a233620f9c
commit 7df9e4a87d
8 changed files with 68 additions and 33 deletions

View File

@ -38,14 +38,17 @@ const SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
return nullptr;
}
/*
void SkBlitter::blitH(int x, int y, int width) {
SkDEBUGFAIL("unimplemented");
}
void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
SkDEBUGFAIL("unimplemented");
}
*/
void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
if (alpha == 255) {

View File

@ -28,16 +28,18 @@ public:
virtual ~SkBlitter();
/// Blit a horizontal run of one or more pixels.
virtual void blitH(int x, int y, int width);
virtual void blitH(int x, int y, int width) = 0;
/// Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
/// zero-terminated run-length encoding of spans of constant alpha values.
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]);
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) = 0;
/// Blit a vertical run of pixels with a constant alpha value.
virtual void blitV(int x, int y, int height, SkAlpha alpha);
/// Blit a solid rectangle one or more pixels wide.
virtual void blitRect(int x, int y, int width, int height);
/** Blit a rectangle with one alpha-blended column on the left,
width (zero or more) opaque pixels, and one alpha-blended column
on the right.
@ -45,6 +47,7 @@ public:
*/
virtual void blitAntiRect(int x, int y, int width, int height,
SkAlpha leftAlpha, SkAlpha rightAlpha);
/// Blit a pattern of pixels defined by a rectangle-clipped mask;
/// typically used for text.
virtual void blitMask(const SkMask&, const SkIRect& clip);

View File

@ -9,7 +9,8 @@
#include "SkSmallAllocator.h"
#include "SkSpriteBlitter.h"
SkSpriteBlitter::SkSpriteBlitter(const SkPixmap& source) : fSource(source) {}
SkSpriteBlitter::SkSpriteBlitter(const SkPixmap& source)
: fSource(source) {}
void SkSpriteBlitter::setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) {
fDst = dst;
@ -18,24 +19,32 @@ void SkSpriteBlitter::setup(const SkPixmap& dst, int left, int top, const SkPain
fPaint = &paint;
}
#ifdef SK_DEBUG
void SkSpriteBlitter::blitH(int x, int y, int width) {
SkDEBUGFAIL("how did we get here?");
// Fallback to blitRect.
this->blitRect(x, y, width, 1);
}
void SkSpriteBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
void SkSpriteBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) {
SkDEBUGFAIL("how did we get here?");
// No fallback strategy.
}
void SkSpriteBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
SkDEBUGFAIL("how did we get here?");
// Fall back to superclass if the code gets here in release mode.
INHERITED::blitV(x, y, height, alpha);
}
void SkSpriteBlitter::blitMask(const SkMask&, const SkIRect& clip) {
void SkSpriteBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
SkDEBUGFAIL("how did we get here?");
// Fall back to superclass if the code gets here in release mode.
INHERITED::blitMask(mask, clip);
}
#endif
///////////////////////////////////////////////////////////////////////////////
@ -44,7 +53,7 @@ void SkSpriteBlitter::blitMask(const SkMask&, const SkIRect& clip) {
// 2. paint has no modifiers (i.e. alpha, colorfilter, etc.)
// 3. xfermode needs no blending: e.g. kSrc_Mode or kSrcOver_Mode + opaque src
//
class SkSpriteBlitter_Src_SrcOver : public SkSpriteBlitter {
class SkSpriteBlitter_Src_SrcOver final : public SkSpriteBlitter {
public:
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) {
if (dst.colorType() != src.colorType()) {
@ -80,7 +89,8 @@ public:
return SkXfermode::kSrcOver_Mode == mode;
}
SkSpriteBlitter_Src_SrcOver(const SkPixmap& src) : INHERITED(src) {}
SkSpriteBlitter_Src_SrcOver(const SkPixmap& src)
: INHERITED(src) {}
void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
SkASSERT(Supports(dst, fSource, paint));

View File

@ -428,6 +428,7 @@ private:
PixelAccessor<colorType, colorProfile> fStrategy;
};
// -- BilerpSampler --------------------------------------------------------------------------------
// BilerpSampler - use a bilerp filter to create runs of destination pixels.
template<SkColorType colorType, SkColorProfileType colorProfile, typename Next>
class BilerpSampler : public SkLinearBitmapPipeline::SampleProcessorInterface {

View File

@ -45,6 +45,9 @@ public:
void copyToRgn(SkRegion::RunType runs[]) const;
void blitH(int x, int y, int width) override;
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
SkDEBUGFAIL("blitAntiH not implemented");
}
#ifdef SK_DEBUG
void dump() const {

View File

@ -15,18 +15,23 @@
class SkPaint;
// SkSpriteBlitter specializes SkBlitter in a way to move large rectangles of pixels around.
// Because of this use, the main primitive shifts from blitH style things to the more efficient
// blitRect.
class SkSpriteBlitter : public SkBlitter {
public:
SkSpriteBlitter(const SkPixmap& source);
virtual void setup(const SkPixmap& dst, int left, int top, const SkPaint&);
#ifdef SK_DEBUG
// blitH, blitAntiH, blitV and blitMask should not be called on an SkSpriteBlitter.
void blitH(int x, int y, int width) override;
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override;
void blitV(int x, int y, int height, SkAlpha alpha) override;
void blitMask(const SkMask&, const SkIRect& clip) override;
#endif
// A SkSpriteBlitter must implement blitRect.
void blitRect(int x, int y, int width, int height) override = 0;
static SkSpriteBlitter* ChooseD16(const SkPixmap& source, const SkPaint&, SkTBlitterAllocator*);
static SkSpriteBlitter* ChooseL32(const SkPixmap& source, const SkPaint&, SkTBlitterAllocator*);
@ -38,6 +43,9 @@ protected:
const SkPixmap fSource;
int fLeft, fTop;
const SkPaint* fPaint;
private:
typedef SkBlitter INHERITED;
};
#endif

View File

@ -24,6 +24,10 @@ public:
REPORTER_ASSERT(fReporter, right > fBounds.fLeft && right <= fBounds.fRight);
}
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
SkDEBUGFAIL("blitAntiH not implemented");
}
private:
SkIRect fBounds;
skiatest::Reporter* fReporter;

View File

@ -12,34 +12,37 @@
#include "Test.h"
struct FakeBlitter : public SkBlitter {
FakeBlitter()
: m_blitCount(0)
{}
FakeBlitter()
: m_blitCount(0) { }
virtual void blitH(int x, int y, int width) {
m_blitCount++;
}
void blitH(int x, int y, int width) override {
m_blitCount++;
}
int m_blitCount;
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
SkDEBUGFAIL("blitAntiH not implemented");
}
int m_blitCount;
};
// http://code.google.com/p/skia/issues/detail?id=87
// Lines which is not clipped by boundary based clipping,
// but skipped after tessellation, should be cleared by the blitter.
DEF_TEST(FillPathInverse, reporter) {
FakeBlitter blitter;
SkIRect clip;
SkPath path;
int height = 100;
int width = 200;
int expected_lines = 5;
clip.set(0, height - expected_lines, width, height);
path.moveTo(0.0f, 0.0f);
path.quadTo(SkIntToScalar(width/2), SkIntToScalar(height),
FakeBlitter blitter;
SkIRect clip;
SkPath path;
int height = 100;
int width = 200;
int expected_lines = 5;
clip.set(0, height - expected_lines, width, height);
path.moveTo(0.0f, 0.0f);
path.quadTo(SkIntToScalar(width/2), SkIntToScalar(height),
SkIntToScalar(width), 0.0f);
path.close();
path.setFillType(SkPath::kInverseWinding_FillType);
SkScan::FillPath(path, clip, &blitter);
path.close();
path.setFillType(SkPath::kInverseWinding_FillType);
SkScan::FillPath(path, clip, &blitter);
REPORTER_ASSERT(reporter, blitter.m_blitCount == expected_lines);
REPORTER_ASSERT(reporter, blitter.m_blitCount == expected_lines);
}