add SkPictureUtils::GatherPixelRefs()
Review URL: https://codereview.appspot.com/6845106 git-svn-id: http://skia.googlecode.com/svn/trunk@6615 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
417bc1382e
commit
fe7b1ed30a
@ -70,6 +70,7 @@
|
||||
'../src/utils/SkParse.cpp',
|
||||
'../src/utils/SkParseColor.cpp',
|
||||
'../src/utils/SkParsePath.cpp',
|
||||
'../src/utils/SkPictureUtils.cpp',
|
||||
'../src/utils/SkProxyCanvas.cpp',
|
||||
'../src/utils/SkThreadUtils.h',
|
||||
'../src/utils/SkThreadUtils_pthread.cpp',
|
||||
|
31
include/utils/SkPictureUtils.h
Normal file
31
include/utils/SkPictureUtils.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkPictureUtils_DEFINED
|
||||
#define SkPictureUtils_DEFINED
|
||||
|
||||
#include "SkPicture.h"
|
||||
|
||||
class SkData;
|
||||
struct SkRect;
|
||||
|
||||
class SkPictureUtils {
|
||||
public:
|
||||
/**
|
||||
* Given a rectangular visible "window" into the picture, return an array
|
||||
* of SkPixelRefs that might intersect that area. To keep the call fast,
|
||||
* the returned list is not guaranteed to be exact, so it may miss some,
|
||||
* and it may return false positives.
|
||||
*
|
||||
* The pixelrefs returned in the SkData are already owned by the picture,
|
||||
* so the returned pointers are only valid while the picture is in scope
|
||||
* and remains unchanged.
|
||||
*/
|
||||
static SkData* GatherPixelRefs(SkPicture* pict, const SkRect& area);
|
||||
};
|
||||
|
||||
#endif
|
213
src/utils/SkPictureUtils.cpp
Normal file
213
src/utils/SkPictureUtils.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkPictureUtils.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkData.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkPixelRef.h"
|
||||
#include "SkShader.h"
|
||||
|
||||
class PixelRefSet {
|
||||
public:
|
||||
PixelRefSet(SkTDArray<SkPixelRef*>* array) : fArray(array) {}
|
||||
|
||||
// This does a linear search on existing pixelrefs, so if this list gets big
|
||||
// we should use a more complex sorted/hashy thing.
|
||||
//
|
||||
void add(SkPixelRef* pr) {
|
||||
uint32_t genID = pr->getGenerationID();
|
||||
if (fGenID.find(genID) < 0) {
|
||||
*fArray->append() = pr;
|
||||
*fGenID.append() = genID;
|
||||
// SkDebugf("--- adding [%d] %x %d\n", fArray->count() - 1, pr, genID);
|
||||
} else {
|
||||
// SkDebugf("--- already have %x %d\n", pr, genID);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkTDArray<SkPixelRef*>* fArray;
|
||||
SkTDArray<uint32_t> fGenID;
|
||||
};
|
||||
|
||||
static void not_supported() {
|
||||
SkASSERT(!"this method should never be called");
|
||||
}
|
||||
|
||||
static void nothing_to_do() {}
|
||||
|
||||
/**
|
||||
* This device will route all bitmaps (primitives and in shaders) to its PRSet.
|
||||
* It should never actually draw anything, so there need not be any pixels
|
||||
* behind its device-bitmap.
|
||||
*/
|
||||
class GatherPixelRefDevice : public SkDevice {
|
||||
private:
|
||||
PixelRefSet* fPRSet;
|
||||
|
||||
void addBitmap(const SkBitmap& bm) {
|
||||
fPRSet->add(bm.pixelRef());
|
||||
}
|
||||
|
||||
void addBitmapFromPaint(const SkPaint& paint) {
|
||||
SkShader* shader = paint.getShader();
|
||||
if (shader) {
|
||||
SkBitmap bm;
|
||||
if (shader->asABitmap(&bm, NULL, NULL)) {
|
||||
fPRSet->add(bm.pixelRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
GatherPixelRefDevice(const SkBitmap& bm, PixelRefSet* prset) : SkDevice(bm) {
|
||||
fPRSet = prset;
|
||||
}
|
||||
|
||||
virtual void clear(SkColor color) SK_OVERRIDE {
|
||||
nothing_to_do();
|
||||
}
|
||||
virtual void writePixels(const SkBitmap& bitmap, int x, int y,
|
||||
SkCanvas::Config8888 config8888) SK_OVERRIDE {
|
||||
not_supported();
|
||||
}
|
||||
|
||||
virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
|
||||
const SkPoint[], const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawRect(const SkDraw&, const SkRect& r,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawPath(const SkDraw&, const SkPath& path,
|
||||
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||
bool pathIsMutable) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
|
||||
const SkIRect* srcRectOrNull,
|
||||
const SkMatrix&, const SkPaint&) SK_OVERRIDE {
|
||||
this->addBitmap(bitmap);
|
||||
}
|
||||
virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap,
|
||||
const SkRect* srcOrNull, const SkRect& dst,
|
||||
const SkPaint&) SK_OVERRIDE {
|
||||
this->addBitmap(bitmap);
|
||||
}
|
||||
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
|
||||
int x, int y, const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmap(bitmap);
|
||||
}
|
||||
virtual void drawText(const SkDraw&, const void* text, size_t len,
|
||||
SkScalar x, SkScalar y,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawPosText(const SkDraw&, const void* text, size_t len,
|
||||
const SkScalar pos[], SkScalar constY,
|
||||
int, const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
|
||||
const SkPath& path, const SkMatrix* matrix,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
|
||||
const SkPoint verts[], const SkPoint texs[],
|
||||
const SkColor colors[], SkXfermode* xmode,
|
||||
const uint16_t indices[], int indexCount,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
|
||||
const SkPaint&) SK_OVERRIDE {
|
||||
nothing_to_do();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool onReadPixels(const SkBitmap& bitmap,
|
||||
int x, int y,
|
||||
SkCanvas::Config8888 config8888) SK_OVERRIDE {
|
||||
not_supported();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class NoSaveLayerCanvas : public SkCanvas {
|
||||
public:
|
||||
NoSaveLayerCanvas(SkDevice* device) : INHERITED(device) {}
|
||||
|
||||
// turn saveLayer() into save() for speed, should not affect correctness.
|
||||
virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
|
||||
SaveFlags flags) SK_OVERRIDE {
|
||||
|
||||
// Like SkPictureRecord, we don't want to create layers, but we do need
|
||||
// to respect the save and (possibly) its rect-clip.
|
||||
|
||||
int count = this->INHERITED::save(flags);
|
||||
if (bounds) {
|
||||
this->INHERITED::clipRectBounds(bounds, flags, NULL);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// disable aa for speed
|
||||
virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
|
||||
bool doAA) SK_OVERRIDE {
|
||||
return this->INHERITED::clipRect(rect, op, false);
|
||||
}
|
||||
|
||||
// for speed, just respect the bounds, and disable AA. May give us a few
|
||||
// false positives and negatives.
|
||||
virtual bool clipPath(const SkPath& path, SkRegion::Op op,
|
||||
bool doAA) SK_OVERRIDE {
|
||||
return this->INHERITED::clipRect(path.getBounds(), op, false);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef SkCanvas INHERITED;
|
||||
};
|
||||
|
||||
SkData* SkPictureUtils::GatherPixelRefs(SkPicture* pict, const SkRect& area) {
|
||||
if (NULL == pict) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this test also handles if either area or pict's width/height are empty
|
||||
if (!SkRect::Intersects(area,
|
||||
SkRect::MakeWH(SkIntToScalar(pict->width()),
|
||||
SkIntToScalar(pict->height())))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkTDArray<SkPixelRef*> array;
|
||||
PixelRefSet prset(&array);
|
||||
|
||||
SkBitmap emptyBitmap;
|
||||
emptyBitmap.setConfig(SkBitmap::kARGB_8888_Config, pict->width(), pict->height());
|
||||
// note: we do not set any pixels (shouldn't need to)
|
||||
|
||||
GatherPixelRefDevice device(emptyBitmap, &prset);
|
||||
NoSaveLayerCanvas canvas(&device);
|
||||
|
||||
canvas.clipRect(area, SkRegion::kIntersect_Op, false);
|
||||
canvas.drawPicture(*pict);
|
||||
|
||||
SkData* data = NULL;
|
||||
int count = array.count();
|
||||
if (count > 0) {
|
||||
data = SkData::NewFromMalloc(array.detach(), count * sizeof(SkPixelRef*));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -6,11 +6,232 @@
|
||||
*/
|
||||
#include "Test.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkData.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
#include "SkPictureUtils.h"
|
||||
|
||||
static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) {
|
||||
bm->setConfig(SkBitmap::kARGB_8888_Config, w, h);
|
||||
bm->allocPixels();
|
||||
bm->eraseColor(color);
|
||||
if (immutable) {
|
||||
bm->setImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&, const SkPoint&);
|
||||
|
||||
static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkPoint& pos) {
|
||||
canvas->drawBitmap(bm, pos.fX, pos.fY, NULL);
|
||||
}
|
||||
|
||||
static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkPoint& pos) {
|
||||
SkRect r = {
|
||||
0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height())
|
||||
};
|
||||
r.offset(pos.fX, pos.fY);
|
||||
canvas->drawBitmapRectToRect(bm, NULL, r, NULL);
|
||||
}
|
||||
|
||||
static void drawshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkPoint& pos) {
|
||||
SkRect r = {
|
||||
0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height())
|
||||
};
|
||||
r.offset(pos.fX, pos.fY);
|
||||
|
||||
SkShader* s = SkShader::CreateBitmapShader(bm,
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kClamp_TileMode);
|
||||
SkPaint paint;
|
||||
paint.setShader(s)->unref();
|
||||
canvas->drawRect(r, paint);
|
||||
}
|
||||
|
||||
// Return a picture with the bitmaps drawn at the specified positions.
|
||||
static SkPicture* record_bitmaps(const SkBitmap bm[], const SkPoint pos[],
|
||||
int count, DrawBitmapProc proc) {
|
||||
SkPicture* pic = new SkPicture;
|
||||
SkCanvas* canvas = pic->beginRecording(1000, 1000);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
proc(canvas, bm[i], pos[i]);
|
||||
}
|
||||
pic->endRecording();
|
||||
return pic;
|
||||
}
|
||||
|
||||
static void rand_rect(SkRect* rect, SkRandom& rand, SkScalar W, SkScalar H) {
|
||||
rect->fLeft = rand.nextRangeScalar(-W, 2*W);
|
||||
rect->fTop = rand.nextRangeScalar(-H, 2*H);
|
||||
rect->fRight = rect->fLeft + rand.nextRangeScalar(0, W);
|
||||
rect->fBottom = rect->fTop + rand.nextRangeScalar(0, H);
|
||||
|
||||
// we integralize rect to make our tests more predictable, since Gather is
|
||||
// a little sloppy.
|
||||
SkIRect ir;
|
||||
rect->round(&ir);
|
||||
rect->set(ir);
|
||||
}
|
||||
|
||||
// Allocate result to be large enough to hold subset, and then draw the picture
|
||||
// into it, offsetting by subset's top/left corner.
|
||||
static void draw(SkPicture* pic, const SkRect& subset, SkBitmap* result) {
|
||||
SkIRect ir;
|
||||
subset.roundOut(&ir);
|
||||
int w = ir.width();
|
||||
int h = ir.height();
|
||||
make_bm(result, w, h, 0, false);
|
||||
|
||||
SkCanvas canvas(*result);
|
||||
canvas.translate(-SkIntToScalar(ir.left()), -SkIntToScalar(ir.top()));
|
||||
canvas.drawPicture(*pic);
|
||||
}
|
||||
|
||||
template <typename T> int find_index(const T* array, T elem, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (array[i] == elem) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return true if 'ref' is found in array[]
|
||||
static bool find(SkPixelRef const * const * array, SkPixelRef const * ref, int count) {
|
||||
return find_index<const SkPixelRef*>(array, ref, count) >= 0;
|
||||
}
|
||||
|
||||
// Look at each pixel in bm, and if its color appears in colors[], find the
|
||||
// corresponding value in refs[] and append that ref into array, skipping
|
||||
// duplicates of the same value.
|
||||
static void gather_from_colors(const SkBitmap& bm, SkPixelRef* const refs[],
|
||||
int count, SkTDArray<SkPixelRef*>* array) {
|
||||
// Since we only want to return unique values in array, when we scan we just
|
||||
// set a bit for each index'd color found. In practice we only have a few
|
||||
// distinct colors, so we just use an int's bits as our array. Hence the
|
||||
// assert that count <= number-of-bits-in-our-int.
|
||||
SkASSERT((unsigned)count <= 32);
|
||||
uint32_t bitarray = 0;
|
||||
|
||||
SkAutoLockPixels alp(bm);
|
||||
|
||||
for (int y = 0; y < bm.height(); ++y) {
|
||||
for (int x = 0; x < bm.width(); ++x) {
|
||||
SkPMColor pmc = *bm.getAddr32(x, y);
|
||||
// the only good case where the color is not found would be if
|
||||
// the color is transparent, meaning no bitmap was drawn in that
|
||||
// pixel.
|
||||
if (pmc) {
|
||||
int index = SkGetPackedR32(pmc);
|
||||
SkASSERT(SkGetPackedG32(pmc) == index);
|
||||
SkASSERT(SkGetPackedB32(pmc) == index);
|
||||
SkASSERT(index < count);
|
||||
bitarray |= 1 << index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (bitarray & (1 << i)) {
|
||||
*array->append() = refs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
|
||||
const int IW = 8;
|
||||
const int IH = IW;
|
||||
const SkScalar W = SkIntToScalar(IW);
|
||||
const SkScalar H = W;
|
||||
|
||||
static const int N = 4;
|
||||
SkBitmap bm[N];
|
||||
SkPMColor pmcolors[N];
|
||||
SkPixelRef* refs[N];
|
||||
|
||||
const SkPoint pos[] = {
|
||||
{ 0, 0 }, { W, 0 }, { 0, H }, { W, H }
|
||||
};
|
||||
|
||||
// Our convention is that the color components contain the index of their
|
||||
// corresponding bitmap/pixelref
|
||||
for (int i = 0; i < N; ++i) {
|
||||
make_bm(&bm[i], IW, IH, SkColorSetARGB(0xFF, i, i, i), true);
|
||||
refs[i] = bm[i].pixelRef();
|
||||
}
|
||||
|
||||
static const DrawBitmapProc procs[] = {
|
||||
drawbitmap_proc, drawbitmaprect_proc, drawshader_proc
|
||||
};
|
||||
|
||||
SkRandom rand;
|
||||
for (size_t k = 0; k < SK_ARRAY_COUNT(procs); ++k) {
|
||||
SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, N, procs[k]));
|
||||
|
||||
// quick check for a small piece of each quadrant, which should just
|
||||
// contain 1 bitmap.
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
|
||||
SkRect r;
|
||||
r.set(2, 2, W - 2, H - 2);
|
||||
r.offset(pos[i].fX, pos[i].fY);
|
||||
SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r));
|
||||
REPORTER_ASSERT(reporter, data);
|
||||
int count = data->size() / sizeof(SkPixelRef*);
|
||||
REPORTER_ASSERT(reporter, 1 == count);
|
||||
REPORTER_ASSERT(reporter, *(SkPixelRef**)data->data() == refs[i]);
|
||||
}
|
||||
|
||||
// Test a bunch of random (mostly) rects, and compare the gather results
|
||||
// with a deduced list of refs by looking at the colors drawn.
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
SkRect r;
|
||||
rand_rect(&r, rand, 2*W, 2*H);
|
||||
|
||||
SkBitmap result;
|
||||
draw(pic, r, &result);
|
||||
SkTDArray<SkPixelRef*> array;
|
||||
|
||||
SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
|
||||
size_t dataSize = data ? data->size() : 0;
|
||||
int gatherCount = dataSize / sizeof(SkPixelRef*);
|
||||
SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize);
|
||||
SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
|
||||
SkAutoDataUnref adu(data);
|
||||
|
||||
gather_from_colors(result, refs, N, &array);
|
||||
|
||||
/*
|
||||
* GatherPixelRefs is conservative, so it can return more bitmaps
|
||||
* that we actually can see (usually because of conservative bounds
|
||||
* inflation for antialiasing). Thus our check here is only that
|
||||
* Gather didn't miss any that we actually saw. Even that isn't
|
||||
* a strict requirement on Gather, which is meant to be quick and
|
||||
* only mostly-correct, but at the moment this test should work.
|
||||
*/
|
||||
for (int i = 0; i < array.count(); ++i) {
|
||||
bool found = find(gatherRefs, array[i], gatherCount);
|
||||
REPORTER_ASSERT(reporter, found);
|
||||
#if 0
|
||||
// enable this block of code to debug failures, as it will rerun
|
||||
// the case that failed.
|
||||
if (!found) {
|
||||
SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
|
||||
size_t dataSize = data ? data->size() : 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only
|
||||
// run in debug mode.
|
||||
@ -91,6 +312,7 @@ static void TestPicture(skiatest::Reporter* reporter) {
|
||||
test_serializing_empty_picture();
|
||||
#endif
|
||||
test_peephole(reporter);
|
||||
test_gatherpixelrefs(reporter);
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "SkTDArray.h"
|
||||
#include "SkThreadUtils.h"
|
||||
#include "SkTypes.h"
|
||||
#include "SkData.h"
|
||||
#include "SkPictureUtils.h"
|
||||
|
||||
namespace sk_tools {
|
||||
|
||||
@ -658,4 +660,27 @@ SkPicture* PictureRenderer::createPicture() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GatherRenderer : public PictureRenderer {
|
||||
public:
|
||||
virtual bool render(const SkString* path) SK_OVERRIDE {
|
||||
SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
|
||||
SkIntToScalar(fPicture->height()));
|
||||
SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
|
||||
SkSafeUnref(data);
|
||||
|
||||
return NULL == path; // we don't have anything to write
|
||||
}
|
||||
|
||||
private:
|
||||
virtual SkString getConfigNameInternal() SK_OVERRIDE {
|
||||
return SkString("gather_pixelrefs");
|
||||
}
|
||||
};
|
||||
|
||||
PictureRenderer* CreateGatherPixelRefsRenderer() {
|
||||
return SkNEW(GatherRenderer);
|
||||
}
|
||||
|
||||
} // namespace sk_tools
|
||||
|
@ -367,6 +367,8 @@ private:
|
||||
typedef PictureRenderer INHERITED;
|
||||
};
|
||||
|
||||
extern PictureRenderer* CreateGatherPixelRefsRenderer();
|
||||
|
||||
}
|
||||
|
||||
#endif // PictureRenderer_DEFINED
|
||||
|
@ -413,6 +413,8 @@ static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>*
|
||||
} else if (0 == strcmp(*argv, "playbackCreation")) {
|
||||
renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
|
||||
gridSupported = true;
|
||||
} else if (0 == strcmp(*argv, "gatherPixelRefs")) {
|
||||
renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
|
||||
} else {
|
||||
SkString err;
|
||||
err.printf("%s is not a valid mode for --mode\n", *argv);
|
||||
|
Loading…
Reference in New Issue
Block a user