remove (unused) GatherPixelRefs
BUG=skia: Review URL: https://codereview.chromium.org/869463002
This commit is contained in:
parent
50282b4390
commit
b0dfb546f5
@ -59,8 +59,6 @@
|
||||
'<(skia_src_path)/utils/SkDumpCanvas.cpp',
|
||||
'<(skia_src_path)/utils/SkEventTracer.cpp',
|
||||
'<(skia_src_path)/utils/SkFloatUtils.h',
|
||||
'<(skia_src_path)/utils/SkGatherPixelRefsAndRects.cpp',
|
||||
'<(skia_src_path)/utils/SkGatherPixelRefsAndRects.h',
|
||||
'<(skia_src_path)/utils/SkInterpolator.cpp',
|
||||
'<(skia_src_path)/utils/SkLayer.cpp',
|
||||
'<(skia_src_path)/utils/SkMatrix22.cpp',
|
||||
|
@ -9,76 +9,9 @@
|
||||
#define SkPictureUtils_DEFINED
|
||||
|
||||
#include "SkPicture.h"
|
||||
#include "SkTDArray.h"
|
||||
|
||||
class SkData;
|
||||
struct SkRect;
|
||||
|
||||
class SK_API 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(const SkPicture* pict, const SkRect& area);
|
||||
|
||||
/**
|
||||
* SkPixelRefContainer provides a base class for more elaborate pixel ref
|
||||
* query structures (e.g., rtrees, quad-trees, etc.)
|
||||
*/
|
||||
class SkPixelRefContainer : public SkRefCnt {
|
||||
public:
|
||||
virtual void add(SkPixelRef* pr, const SkRect& rect) = 0;
|
||||
|
||||
// The returned array may contain duplicates
|
||||
virtual void query(const SkRect& queryRect, SkTDArray<SkPixelRef*> *result) = 0;
|
||||
|
||||
private:
|
||||
typedef SkRefCnt INHERITED;
|
||||
};
|
||||
|
||||
// Simple query structure that just stores a linked list of pixel refs
|
||||
// and rects.
|
||||
class SkPixelRefsAndRectsList : public SkPixelRefContainer {
|
||||
public:
|
||||
void add(SkPixelRef* pr, const SkRect& rect) SK_OVERRIDE {
|
||||
PixelRefAndRect *dst = fArray.append();
|
||||
|
||||
dst->fPixelRef = pr;
|
||||
dst->fRect = rect;
|
||||
}
|
||||
|
||||
void query(const SkRect& queryRect, SkTDArray<SkPixelRef*> *result) SK_OVERRIDE {
|
||||
for (int i = 0; i < fArray.count(); ++i) {
|
||||
if (SkRect::Intersects(fArray[i].fRect, queryRect)) {
|
||||
*result->append() = fArray[i].fPixelRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct PixelRefAndRect {
|
||||
SkPixelRef* fPixelRef;
|
||||
SkRect fRect;
|
||||
};
|
||||
|
||||
SkTDArray<PixelRefAndRect> fArray;
|
||||
|
||||
typedef SkPixelRefContainer INHERITED;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill the provided pixel ref container with the picture's pixel ref
|
||||
* and rect information.
|
||||
*/
|
||||
static void GatherPixelRefsAndRects(SkPicture* pict, SkPixelRefContainer* prCont);
|
||||
|
||||
/**
|
||||
* How many bytes are allocated to hold the SkPicture.
|
||||
* Includes operations, parameters, bounding data, deletion listeners;
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkGatherPixelRefsAndRects.h"
|
||||
#include "SkNoSaveLayerCanvas.h"
|
||||
#include "SkPictureUtils.h"
|
||||
|
||||
void SkPictureUtils::GatherPixelRefsAndRects(SkPicture* pict,
|
||||
SkPictureUtils::SkPixelRefContainer* prCont) {
|
||||
if (pict->cullRect().isEmpty()) {
|
||||
return ;
|
||||
}
|
||||
|
||||
SkGatherPixelRefsAndRectsDevice device(SkScalarCeilToInt(pict->cullRect().width()),
|
||||
SkScalarCeilToInt(pict->cullRect().height()),
|
||||
prCont);
|
||||
SkNoSaveLayerCanvas canvas(&device);
|
||||
|
||||
canvas.clipRect(pict->cullRect(), SkRegion::kIntersect_Op, false);
|
||||
canvas.drawPicture(pict);
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkGatherPixelRefsAndRects_DEFINED
|
||||
#define SkGatherPixelRefsAndRects_DEFINED
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkDraw.h"
|
||||
#include "SkPictureUtils.h"
|
||||
#include "SkRasterClip.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkRRect.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
// This GatherPixelRefs device passes all discovered pixel refs and their
|
||||
// device bounds to the user provided SkPixelRefContainer-derived object
|
||||
class SkGatherPixelRefsAndRectsDevice : public SkBaseDevice {
|
||||
public:
|
||||
SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice)
|
||||
|
||||
SkGatherPixelRefsAndRectsDevice(int width, int height,
|
||||
SkPictureUtils::SkPixelRefContainer* prCont) {
|
||||
fSize.set(width, height);
|
||||
fPRCont = prCont;
|
||||
SkSafeRef(fPRCont);
|
||||
fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
|
||||
}
|
||||
|
||||
virtual ~SkGatherPixelRefsAndRectsDevice() {
|
||||
SkSafeUnref(fPRCont);
|
||||
}
|
||||
|
||||
SkImageInfo imageInfo() const SK_OVERRIDE {
|
||||
return fEmptyBitmap.info();
|
||||
}
|
||||
|
||||
protected:
|
||||
void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
|
||||
SkBitmap bm;
|
||||
|
||||
if (GetBitmapFromPaint(paint, &bm)) {
|
||||
SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
|
||||
fPRCont->add(bm.pixelRef(), clipRect);
|
||||
}
|
||||
}
|
||||
virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
|
||||
const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
|
||||
SkBitmap bm;
|
||||
if (!GetBitmapFromPaint(paint, &bm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == count) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkPoint min = points[0];
|
||||
SkPoint max = points[0];
|
||||
for (size_t i = 1; i < count; ++i) {
|
||||
const SkPoint& point = points[i];
|
||||
|
||||
min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
|
||||
max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
|
||||
}
|
||||
|
||||
SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);
|
||||
|
||||
this->drawRect(draw, bounds, paint);
|
||||
}
|
||||
virtual void drawRect(const SkDraw& draw, const SkRect& rect,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
SkBitmap bm;
|
||||
if (GetBitmapFromPaint(paint, &bm)) {
|
||||
SkRect mappedRect;
|
||||
draw.fMatrix->mapRect(&mappedRect, rect);
|
||||
SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
|
||||
if (mappedRect.intersect(clipRect)) {
|
||||
fPRCont->add(bm.pixelRef(), mappedRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void drawOval(const SkDraw& draw, const SkRect& rect,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->drawRect(draw, rect, paint);
|
||||
}
|
||||
virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->drawRect(draw, rrect.rect(), paint);
|
||||
}
|
||||
virtual void drawPath(const SkDraw& draw, const SkPath& path,
|
||||
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||
bool pathIsMutable) SK_OVERRIDE {
|
||||
SkBitmap bm;
|
||||
if (!GetBitmapFromPaint(paint, &bm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SkRect pathBounds = path.getBounds();
|
||||
if (prePathMatrix) {
|
||||
prePathMatrix->mapRect(&pathBounds);
|
||||
}
|
||||
|
||||
this->drawRect(draw, pathBounds, paint);
|
||||
}
|
||||
virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
|
||||
SkMatrix totMatrix;
|
||||
totMatrix.setConcat(*draw.fMatrix, matrix);
|
||||
|
||||
SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
|
||||
SkIntToScalar(bitmap.height()));
|
||||
SkRect mappedRect;
|
||||
totMatrix.mapRect(&mappedRect, bitmapRect);
|
||||
fPRCont->add(bitmap.pixelRef(), mappedRect);
|
||||
|
||||
SkBitmap paintBitmap;
|
||||
if (GetBitmapFromPaint(paint, &paintBitmap)) {
|
||||
fPRCont->add(paintBitmap.pixelRef(), mappedRect);
|
||||
}
|
||||
}
|
||||
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
|
||||
int x, int y, const SkPaint& paint) SK_OVERRIDE {
|
||||
// Sprites aren't affected by current matrix, so we can't reuse drawRect.
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
|
||||
|
||||
SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
|
||||
SkIntToScalar(bitmap.height()));
|
||||
SkRect mappedRect;
|
||||
matrix.mapRect(&mappedRect, bitmapRect);
|
||||
fPRCont->add(bitmap.pixelRef(), mappedRect);
|
||||
|
||||
SkBitmap paintBitmap;
|
||||
if (GetBitmapFromPaint(paint, &paintBitmap)) {
|
||||
fPRCont->add(paintBitmap.pixelRef(), mappedRect);
|
||||
}
|
||||
}
|
||||
virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
const SkRect* srcOrNull, const SkRect& dst,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
|
||||
SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
|
||||
SkIntToScalar(bitmap.height()));
|
||||
SkMatrix matrix;
|
||||
matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
|
||||
this->drawBitmap(draw, bitmap, matrix, paint);
|
||||
}
|
||||
virtual void drawText(const SkDraw& draw, const void* text, size_t len,
|
||||
SkScalar x, SkScalar y,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
SkBitmap bitmap;
|
||||
if (!GetBitmapFromPaint(paint, &bitmap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Math is borrowed from SkBBoxRecord
|
||||
SkRect bounds;
|
||||
paint.measureText(text, len, &bounds);
|
||||
SkPaint::FontMetrics metrics;
|
||||
paint.getFontMetrics(&metrics);
|
||||
|
||||
if (paint.isVerticalText()) {
|
||||
SkScalar h = bounds.fBottom - bounds.fTop;
|
||||
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
|
||||
bounds.fTop -= h / 2;
|
||||
bounds.fBottom -= h / 2;
|
||||
}
|
||||
bounds.fBottom += metrics.fBottom;
|
||||
bounds.fTop += metrics.fTop;
|
||||
} else {
|
||||
SkScalar w = bounds.fRight - bounds.fLeft;
|
||||
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
|
||||
bounds.fLeft -= w / 2;
|
||||
bounds.fRight -= w / 2;
|
||||
} else if (paint.getTextAlign() == SkPaint::kRight_Align) {
|
||||
bounds.fLeft -= w;
|
||||
bounds.fRight -= w;
|
||||
}
|
||||
bounds.fTop = metrics.fTop;
|
||||
bounds.fBottom = metrics.fBottom;
|
||||
}
|
||||
|
||||
SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
|
||||
bounds.fLeft -= pad;
|
||||
bounds.fRight += pad;
|
||||
bounds.offset(x, y);
|
||||
|
||||
this->drawRect(draw, bounds, paint);
|
||||
}
|
||||
virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
|
||||
const SkScalar pos[], int scalarsPerPos,
|
||||
const SkPoint& offset, const SkPaint& paint) SK_OVERRIDE {
|
||||
SkBitmap bitmap;
|
||||
if (!GetBitmapFromPaint(paint, &bitmap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == len) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Similar to SkDraw asserts.
|
||||
SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
|
||||
|
||||
SkPoint min = SkPoint::Make(offset.x() + pos[0],
|
||||
offset.y() + (2 == scalarsPerPos ? pos[1] : 0));
|
||||
SkPoint max = min;
|
||||
|
||||
for (size_t i = 1; i < len; ++i) {
|
||||
SkScalar x = offset.x() + pos[i * scalarsPerPos];
|
||||
SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * 2 + 1] : 0);
|
||||
|
||||
min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
|
||||
max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
|
||||
}
|
||||
|
||||
SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());
|
||||
|
||||
// Math is borrowed from SkBBoxRecord
|
||||
SkPaint::FontMetrics metrics;
|
||||
paint.getFontMetrics(&metrics);
|
||||
|
||||
bounds.fTop += metrics.fTop;
|
||||
bounds.fBottom += metrics.fBottom;
|
||||
|
||||
SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
|
||||
bounds.fLeft -= pad;
|
||||
bounds.fRight += pad;
|
||||
|
||||
this->drawRect(draw, bounds, paint);
|
||||
}
|
||||
virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
|
||||
const SkPath& path, const SkMatrix* matrix,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
SkBitmap bitmap;
|
||||
if (!GetBitmapFromPaint(paint, &bitmap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Math is borrowed from SkBBoxRecord
|
||||
SkRect bounds = path.getBounds();
|
||||
SkPaint::FontMetrics metrics;
|
||||
paint.getFontMetrics(&metrics);
|
||||
|
||||
SkScalar pad = metrics.fTop;
|
||||
// TODO: inset?!
|
||||
bounds.fLeft += pad;
|
||||
bounds.fRight -= pad;
|
||||
bounds.fTop += pad;
|
||||
bounds.fBottom -= pad;
|
||||
|
||||
this->drawRect(draw, bounds, paint);
|
||||
}
|
||||
virtual void drawVertices(const SkDraw& draw, 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->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);
|
||||
}
|
||||
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
|
||||
const SkPaint&) SK_OVERRIDE {
|
||||
NothingToDo();
|
||||
}
|
||||
// TODO: allow this call to return failure, or move to SkBitmapDevice only.
|
||||
const SkBitmap& onAccessBitmap() SK_OVERRIDE {
|
||||
return fEmptyBitmap;
|
||||
}
|
||||
void lockPixels() SK_OVERRIDE { NothingToDo(); }
|
||||
void unlockPixels() SK_OVERRIDE { NothingToDo(); }
|
||||
bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
|
||||
bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
|
||||
virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
|
||||
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
SkPictureUtils::SkPixelRefContainer* fPRCont;
|
||||
SkISize fSize;
|
||||
|
||||
SkBitmap fEmptyBitmap; // legacy -- need to remove
|
||||
|
||||
static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
|
||||
SkShader* shader = paint.getShader();
|
||||
if (shader) {
|
||||
if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
|
||||
return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
|
||||
NotSupported();
|
||||
}
|
||||
|
||||
SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& info) SK_OVERRIDE {
|
||||
// we expect to only get called via savelayer, in which case it is fine.
|
||||
SkASSERT(kSaveLayer_Usage == info.fUsage);
|
||||
return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
|
||||
(info.fInfo.width(), info.fInfo.height(), fPRCont));
|
||||
}
|
||||
|
||||
static void NotSupported() {
|
||||
SkDEBUGFAIL("this method should never be called");
|
||||
}
|
||||
|
||||
static void NothingToDo() {}
|
||||
|
||||
typedef SkBaseDevice INHERITED;
|
||||
};
|
||||
|
||||
#endif // SkGatherPixelRefsAndRects_DEFINED
|
@ -6,214 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "SkBBoxHierarchy.h"
|
||||
#include "SkBitmapDevice.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkData.h"
|
||||
#include "SkNoSaveLayerCanvas.h"
|
||||
#include "SkPictureUtils.h"
|
||||
#include "SkPixelRef.h"
|
||||
#include "SkRRect.h"
|
||||
#include "SkRecord.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() {
|
||||
SkDEBUGFAIL("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.
|
||||
*/
|
||||
class GatherPixelRefDevice : public SkBaseDevice {
|
||||
public:
|
||||
SK_DECLARE_INST_COUNT(GatherPixelRefDevice)
|
||||
|
||||
GatherPixelRefDevice(int width, int height, PixelRefSet* prset) {
|
||||
fSize.set(width, height);
|
||||
fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
|
||||
fPRSet = prset;
|
||||
}
|
||||
|
||||
SkImageInfo imageInfo() const SK_OVERRIDE {
|
||||
return SkImageInfo::MakeUnknown(fSize.width(), fSize.height());
|
||||
}
|
||||
GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
|
||||
// TODO: allow this call to return failure, or move to SkBitmapDevice only.
|
||||
const SkBitmap& onAccessBitmap() SK_OVERRIDE {
|
||||
return fEmptyBitmap;
|
||||
}
|
||||
void lockPixels() SK_OVERRIDE { nothing_to_do(); }
|
||||
void unlockPixels() SK_OVERRIDE { nothing_to_do(); }
|
||||
bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
|
||||
bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
|
||||
virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
|
||||
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
|
||||
return false;
|
||||
}
|
||||
|
||||
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&,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawRRect(const SkDraw&, const SkRRect&,
|
||||
const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
virtual void drawOval(const SkDraw&, const SkRect&,
|
||||
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 SkMatrix&, const SkPaint& paint) SK_OVERRIDE {
|
||||
this->addBitmap(bitmap);
|
||||
if (kAlpha_8_SkColorType == bitmap.colorType()) {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
}
|
||||
virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap,
|
||||
const SkRect* srcOrNull, const SkRect& dst,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
|
||||
this->addBitmap(bitmap);
|
||||
if (kAlpha_8_SkColorType == bitmap.colorType()) {
|
||||
this->addBitmapFromPaint(paint);
|
||||
}
|
||||
}
|
||||
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[], int,
|
||||
const SkPoint&, 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&, SkBaseDevice*, int x, int y,
|
||||
const SkPaint&) SK_OVERRIDE {
|
||||
nothing_to_do();
|
||||
}
|
||||
|
||||
protected:
|
||||
void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
|
||||
not_supported();
|
||||
}
|
||||
SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& cinfo) SK_OVERRIDE {
|
||||
// we expect to only get called via savelayer, in which case it is fine.
|
||||
SkASSERT(kSaveLayer_Usage == cinfo.fUsage);
|
||||
return SkNEW_ARGS(GatherPixelRefDevice, (cinfo.fInfo.width(), cinfo.fInfo.height(), fPRSet));
|
||||
}
|
||||
void flush() SK_OVERRIDE {}
|
||||
|
||||
private:
|
||||
PixelRefSet* fPRSet;
|
||||
SkBitmap fEmptyBitmap; // legacy -- need to remove the need for this guy
|
||||
SkISize fSize;
|
||||
|
||||
void addBitmap(const SkBitmap& bm) {
|
||||
fPRSet->add(bm.pixelRef());
|
||||
}
|
||||
|
||||
void addBitmapFromPaint(const SkPaint& paint) {
|
||||
SkShader* shader = paint.getShader();
|
||||
if (shader) {
|
||||
SkBitmap bm;
|
||||
// Check whether the shader is a gradient in order to short-circuit
|
||||
// call to asABitmap to prevent generation of bitmaps from
|
||||
// gradient shaders, which implement asABitmap.
|
||||
if (SkShader::kNone_GradientType == shader->asAGradient(NULL) &&
|
||||
shader->asABitmap(&bm, NULL, NULL)) {
|
||||
fPRSet->add(bm.pixelRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef SkBaseDevice INHERITED;
|
||||
};
|
||||
|
||||
SkData* SkPictureUtils::GatherPixelRefs(const 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, pict->cullRect())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkTDArray<SkPixelRef*> array;
|
||||
PixelRefSet prset(&array);
|
||||
|
||||
GatherPixelRefDevice device(SkScalarCeilToInt(pict->cullRect().width()),
|
||||
SkScalarCeilToInt(pict->cullRect().height()),
|
||||
&prset);
|
||||
SkNoSaveLayerCanvas 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;
|
||||
}
|
||||
|
||||
struct MeasureRecords {
|
||||
template <typename T> size_t operator()(const T& op) { return 0; }
|
||||
size_t operator()(const SkRecords::DrawPicture& op) {
|
||||
|
@ -38,9 +38,6 @@
|
||||
#include "SkLumaColorFilter.h"
|
||||
#include "SkColorFilterImageFilter.h"
|
||||
|
||||
static const int gColorScale = 30;
|
||||
static const int gColorOffset = 60;
|
||||
|
||||
static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) {
|
||||
bm->allocN32Pixels(w, h);
|
||||
bm->eraseColor(color);
|
||||
@ -49,157 +46,10 @@ static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) {
|
||||
}
|
||||
}
|
||||
|
||||
static void make_checkerboard(SkBitmap* bm, int w, int h, bool immutable) {
|
||||
SkASSERT(w % 2 == 0);
|
||||
SkASSERT(h % 2 == 0);
|
||||
bm->allocPixels(SkImageInfo::Make(w, h, kAlpha_8_SkColorType,
|
||||
kPremul_SkAlphaType));
|
||||
SkAutoLockPixels lock(*bm);
|
||||
for (int y = 0; y < h; y += 2) {
|
||||
uint8_t* s = bm->getAddr8(0, y);
|
||||
for (int x = 0; x < w; x += 2) {
|
||||
*s++ = 0xFF;
|
||||
*s++ = 0x00;
|
||||
}
|
||||
s = bm->getAddr8(0, y + 1);
|
||||
for (int x = 0; x < w; x += 2) {
|
||||
*s++ = 0x00;
|
||||
*s++ = 0xFF;
|
||||
}
|
||||
}
|
||||
if (immutable) {
|
||||
bm->setImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
static void init_paint(SkPaint* paint, const SkBitmap &bm) {
|
||||
SkShader* shader = SkShader::CreateBitmapShader(bm,
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kClamp_TileMode);
|
||||
paint->setShader(shader)->unref();
|
||||
}
|
||||
|
||||
typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&,
|
||||
const SkBitmap&, const SkPoint&,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs);
|
||||
|
||||
static void drawpaint_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
canvas->drawPaint(paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawpoints_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
// draw a rect
|
||||
SkPoint points[5] = {
|
||||
{ pos.fX, pos.fY },
|
||||
{ pos.fX + bm.width() - 1, pos.fY },
|
||||
{ pos.fX + bm.width() - 1, pos.fY + bm.height() - 1 },
|
||||
{ pos.fX, pos.fY + bm.height() - 1 },
|
||||
{ pos.fX, pos.fY },
|
||||
};
|
||||
|
||||
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 5, points, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
||||
r.offset(pos.fX, pos.fY);
|
||||
|
||||
canvas->drawRect(r, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawoval_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
||||
r.offset(pos.fX, pos.fY);
|
||||
|
||||
canvas->drawOval(r, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawrrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
||||
r.offset(pos.fX, pos.fY);
|
||||
|
||||
SkRRect rr;
|
||||
rr.setRectXY(r, SkIntToScalar(bm.width())/4, SkIntToScalar(bm.height())/4);
|
||||
canvas->drawRRect(rr, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
SkPath path;
|
||||
path.lineTo(bm.width()/2.0f, SkIntToScalar(bm.height()));
|
||||
path.lineTo(SkIntToScalar(bm.width()), 0);
|
||||
path.close();
|
||||
path.offset(pos.fX, pos.fY);
|
||||
|
||||
canvas->drawPath(path, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
canvas->drawBitmap(bm, pos.fX, pos.fY, NULL);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawbitmap_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
// The bitmap in the paint is ignored unless we're drawing an A8 bitmap
|
||||
canvas->drawBitmap(altBM, pos.fX, pos.fY, &paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
*usedPixRefs->append() = altBM.pixelRef();
|
||||
}
|
||||
|
||||
static void drawsprite_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
const SkMatrix& ctm = canvas->getTotalMatrix();
|
||||
|
||||
SkPoint p(pos);
|
||||
ctm.mapPoints(&p, 1);
|
||||
|
||||
canvas->drawSprite(bm, (int)p.fX, (int)p.fY, NULL);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Although specifiable, this case doesn't seem to make sense (i.e., the
|
||||
// bitmap in the shader is never used).
|
||||
@ -220,368 +70,6 @@ static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
||||
|
||||
r.offset(pos.fX, pos.fY);
|
||||
canvas->drawBitmapRectToRect(bm, NULL, r, NULL);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawbitmaprect_withshader_proc(SkCanvas* canvas,
|
||||
const SkBitmap& bm,
|
||||
const SkBitmap& altBM,
|
||||
const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
||||
r.offset(pos.fX, pos.fY);
|
||||
|
||||
// The bitmap in the paint is ignored unless we're drawing an A8 bitmap
|
||||
canvas->drawBitmapRectToRect(altBM, NULL, r, &paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
*usedPixRefs->append() = altBM.pixelRef();
|
||||
}
|
||||
|
||||
static void drawtext_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
||||
|
||||
canvas->drawText("0", 1, pos.fX, pos.fY+bm.width(), paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawpostext_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
||||
|
||||
SkPoint point = { pos.fX, pos.fY + bm.height() };
|
||||
canvas->drawPosText("O", 1, &point, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawtextonpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
|
||||
init_paint(&paint, bm);
|
||||
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
||||
|
||||
SkPath path;
|
||||
path.lineTo(SkIntToScalar(bm.width()), 0);
|
||||
path.offset(pos.fX, pos.fY+bm.height());
|
||||
|
||||
canvas->drawTextOnPath("O", 1, path, NULL, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
static void drawverts_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||
const SkBitmap& altBM, const SkPoint& pos,
|
||||
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||
SkPaint paint;
|
||||
init_paint(&paint, bm);
|
||||
|
||||
SkPoint verts[4] = {
|
||||
{ pos.fX, pos.fY },
|
||||
{ pos.fX + bm.width(), pos.fY },
|
||||
{ pos.fX + bm.width(), pos.fY + bm.height() },
|
||||
{ pos.fX, pos.fY + bm.height() }
|
||||
};
|
||||
SkPoint texs[4] = { { 0, 0 },
|
||||
{ SkIntToScalar(bm.width()), 0 },
|
||||
{ SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) },
|
||||
{ 0, SkIntToScalar(bm.height()) } };
|
||||
uint16_t indices[6] = { 0, 1, 2, 0, 2, 3 };
|
||||
|
||||
canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 4, verts, texs, NULL, NULL,
|
||||
indices, 6, paint);
|
||||
*usedPixRefs->append() = bm.pixelRef();
|
||||
}
|
||||
|
||||
// Return a picture with the bitmaps drawn at the specified positions.
|
||||
static SkPicture* record_bitmaps(const SkBitmap bm[],
|
||||
const SkPoint pos[],
|
||||
SkTDArray<SkPixelRef*> analytic[],
|
||||
int count,
|
||||
DrawBitmapProc proc) {
|
||||
SkPictureRecorder recorder;
|
||||
SkCanvas* canvas = recorder.beginRecording(1000, 1000);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
analytic[i].rewind();
|
||||
canvas->save();
|
||||
SkRect clipRect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY,
|
||||
SkIntToScalar(bm[i].width()),
|
||||
SkIntToScalar(bm[i].height()));
|
||||
canvas->clipRect(clipRect, SkRegion::kIntersect_Op);
|
||||
proc(canvas, bm[i], bm[count+i], pos[i], &analytic[i]);
|
||||
canvas->restore();
|
||||
}
|
||||
return recorder.endRecording();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void draw(SkPicture* pic, int width, int height, SkBitmap* result) {
|
||||
make_bm(result, width, height, SK_ColorBLACK, false);
|
||||
|
||||
SkCanvas canvas(*result);
|
||||
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 that is inside 'subset', 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.
|
||||
// Note that gathering pixelRefs from rendered colors suffers from the problem
|
||||
// that multiple simultaneous textures (e.g., A8 for alpha and 8888 for color)
|
||||
// isn't easy to reconstruct.
|
||||
static void gather_from_image(const SkBitmap& bm, SkPixelRef* const refs[],
|
||||
int count, SkTDArray<SkPixelRef*>* array,
|
||||
const SkRect& subset) {
|
||||
SkIRect ir;
|
||||
subset.roundOut(&ir);
|
||||
|
||||
if (!ir.intersect(0, 0, bm.width()-1, bm.height()-1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 = ir.fTop; y < ir.fBottom; ++y) {
|
||||
for (int x = ir.fLeft; x < ir.fRight; ++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) {
|
||||
uint32_t index = SkGetPackedR32(pmc);
|
||||
SkASSERT(SkGetPackedG32(pmc) == index);
|
||||
SkASSERT(SkGetPackedB32(pmc) == index);
|
||||
if (0 == index) {
|
||||
continue; // background color
|
||||
}
|
||||
SkASSERT(0 == (index - gColorOffset) % gColorScale);
|
||||
index = (index - gColorOffset) / gColorScale;
|
||||
SkASSERT(static_cast<int>(index) < count);
|
||||
bitarray |= 1 << index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (bitarray & (1 << i)) {
|
||||
*array->append() = refs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gather_from_analytic(const SkPoint pos[], SkScalar w, SkScalar h,
|
||||
const SkTDArray<SkPixelRef*> analytic[],
|
||||
int count,
|
||||
SkTDArray<SkPixelRef*>* result,
|
||||
const SkRect& subset) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkRect rect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY, w, h);
|
||||
|
||||
if (SkRect::Intersects(subset, rect)) {
|
||||
result->append(analytic[i].count(), analytic[i].begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const struct {
|
||||
const DrawBitmapProc proc;
|
||||
const char* const desc;
|
||||
} gProcs[] = {
|
||||
{drawpaint_proc, "drawpaint"},
|
||||
{drawpoints_proc, "drawpoints"},
|
||||
{drawrect_proc, "drawrect"},
|
||||
{drawoval_proc, "drawoval"},
|
||||
{drawrrect_proc, "drawrrect"},
|
||||
{drawpath_proc, "drawpath"},
|
||||
{drawbitmap_proc, "drawbitmap"},
|
||||
{drawbitmap_withshader_proc, "drawbitmap_withshader"},
|
||||
{drawsprite_proc, "drawsprite"},
|
||||
#if 0
|
||||
{drawsprite_withshader_proc, "drawsprite_withshader"},
|
||||
#endif
|
||||
{drawbitmaprect_proc, "drawbitmaprect"},
|
||||
{drawbitmaprect_withshader_proc, "drawbitmaprect_withshader"},
|
||||
{drawtext_proc, "drawtext"},
|
||||
{drawpostext_proc, "drawpostext"},
|
||||
{drawtextonpath_proc, "drawtextonpath"},
|
||||
{drawverts_proc, "drawverts"},
|
||||
};
|
||||
|
||||
static void create_textures(SkBitmap* bm, SkPixelRef** refs, int num, int w, int h) {
|
||||
// Our convention is that the color components contain an encoding of
|
||||
// the index of their corresponding bitmap/pixelref. (0,0,0,0) is
|
||||
// reserved for the background
|
||||
for (int i = 0; i < num; ++i) {
|
||||
make_bm(&bm[i], w, h,
|
||||
SkColorSetARGB(0xFF,
|
||||
gColorScale*i+gColorOffset,
|
||||
gColorScale*i+gColorOffset,
|
||||
gColorScale*i+gColorOffset),
|
||||
true);
|
||||
refs[i] = bm[i].pixelRef();
|
||||
}
|
||||
|
||||
// The A8 alternate bitmaps are all BW checkerboards
|
||||
for (int i = 0; i < num; ++i) {
|
||||
make_checkerboard(&bm[num+i], w, h, true);
|
||||
refs[num+i] = bm[num+i].pixelRef();
|
||||
}
|
||||
}
|
||||
|
||||
static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
|
||||
const int IW = 32;
|
||||
const int IH = IW;
|
||||
const SkScalar W = SkIntToScalar(IW);
|
||||
const SkScalar H = W;
|
||||
|
||||
static const int N = 4;
|
||||
SkBitmap bm[2*N];
|
||||
SkPixelRef* refs[2*N];
|
||||
SkTDArray<SkPixelRef*> analytic[N];
|
||||
|
||||
const SkPoint pos[N] = {
|
||||
{ 0, 0 }, { W, 0 }, { 0, H }, { W, H }
|
||||
};
|
||||
|
||||
create_textures(bm, refs, N, IW, IH);
|
||||
|
||||
SkRandom rand;
|
||||
for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) {
|
||||
SkAutoTUnref<SkPicture> pic(
|
||||
record_bitmaps(bm, pos, analytic, N, gProcs[k].proc));
|
||||
|
||||
REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
|
||||
// quick check for a small piece of each quadrant, which should just
|
||||
// contain 1 or 2 bitmaps.
|
||||
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));
|
||||
if (!data) {
|
||||
ERRORF(reporter, "SkPictureUtils::GatherPixelRefs returned "
|
||||
"NULL for %s.", gProcs[k].desc);
|
||||
continue;
|
||||
}
|
||||
SkPixelRef** gatheredRefs = (SkPixelRef**)data->data();
|
||||
int count = static_cast<int>(data->size() / sizeof(SkPixelRef*));
|
||||
REPORTER_ASSERT(reporter, 1 == count || 2 == count);
|
||||
if (1 == count) {
|
||||
REPORTER_ASSERT(reporter, gatheredRefs[0] == refs[i]);
|
||||
} else if (2 == count) {
|
||||
REPORTER_ASSERT(reporter,
|
||||
(gatheredRefs[0] == refs[i] && gatheredRefs[1] == refs[i+N]) ||
|
||||
(gatheredRefs[1] == refs[i] && gatheredRefs[0] == refs[i+N]));
|
||||
}
|
||||
}
|
||||
|
||||
SkBitmap image;
|
||||
draw(pic, 2*IW, 2*IH, &image);
|
||||
|
||||
// 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);
|
||||
|
||||
SkTDArray<SkPixelRef*> fromImage;
|
||||
gather_from_image(image, refs, N, &fromImage, r);
|
||||
|
||||
SkTDArray<SkPixelRef*> fromAnalytic;
|
||||
gather_from_analytic(pos, W, H, analytic, N, &fromAnalytic, r);
|
||||
|
||||
SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
|
||||
size_t dataSize = data ? data->size() : 0;
|
||||
int gatherCount = static_cast<int>(dataSize / sizeof(SkPixelRef*));
|
||||
SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize);
|
||||
SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
|
||||
SkAutoDataUnref adu(data);
|
||||
|
||||
// Everything that we saw drawn should appear in the analytic list
|
||||
// but the analytic list may contain some pixelRefs that were not
|
||||
// seen in the image (e.g., A8 textures used as masks)
|
||||
for (int i = 0; i < fromImage.count(); ++i) {
|
||||
if (-1 == fromAnalytic.find(fromImage[i])) {
|
||||
ERRORF(reporter, "PixelRef missing %d %s",
|
||||
i, gProcs[k].desc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GatherPixelRefs is conservative, so it can return more bitmaps
|
||||
* than are strictly required. Thus our check here is only that
|
||||
* Gather didn't miss any that we actually needed. 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 < fromAnalytic.count(); ++i) {
|
||||
bool found = find(gatherRefs, fromAnalytic[i], gatherCount);
|
||||
if (!found) {
|
||||
ERRORF(reporter, "PixelRef missing %d %s",
|
||||
i, gProcs[k].desc);
|
||||
}
|
||||
#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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Hit a few SkPicture::Analysis cases not handled elsewhere. */
|
||||
static void test_analysis(skiatest::Reporter* reporter) {
|
||||
SkPictureRecorder recorder;
|
||||
@ -615,90 +103,6 @@ static void test_analysis(skiatest::Reporter* reporter) {
|
||||
}
|
||||
|
||||
|
||||
static void test_gatherpixelrefsandrects(skiatest::Reporter* reporter) {
|
||||
const int IW = 32;
|
||||
const int IH = IW;
|
||||
const SkScalar W = SkIntToScalar(IW);
|
||||
const SkScalar H = W;
|
||||
|
||||
static const int N = 4;
|
||||
SkBitmap bm[2*N];
|
||||
SkPixelRef* refs[2*N];
|
||||
SkTDArray<SkPixelRef*> analytic[N];
|
||||
|
||||
const SkPoint pos[N] = {
|
||||
{ 0, 0 }, { W, 0 }, { 0, H }, { W, H }
|
||||
};
|
||||
|
||||
create_textures(bm, refs, N, IW, IH);
|
||||
|
||||
SkRandom rand;
|
||||
for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) {
|
||||
SkAutoTUnref<SkPicture> pic(
|
||||
record_bitmaps(bm, pos, analytic, N, gProcs[k].proc));
|
||||
|
||||
REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
|
||||
|
||||
SkAutoTUnref<SkPictureUtils::SkPixelRefContainer> prCont(
|
||||
new SkPictureUtils::SkPixelRefsAndRectsList);
|
||||
|
||||
SkPictureUtils::GatherPixelRefsAndRects(pic, prCont);
|
||||
|
||||
// quick check for a small piece of each quadrant, which should just
|
||||
// contain 1 or 2 bitmaps.
|
||||
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);
|
||||
|
||||
SkTDArray<SkPixelRef*> gatheredRefs;
|
||||
prCont->query(r, &gatheredRefs);
|
||||
|
||||
int count = gatheredRefs.count();
|
||||
REPORTER_ASSERT(reporter, 1 == count || 2 == count);
|
||||
if (1 == count) {
|
||||
REPORTER_ASSERT(reporter, gatheredRefs[0] == refs[i]);
|
||||
} else if (2 == count) {
|
||||
REPORTER_ASSERT(reporter,
|
||||
(gatheredRefs[0] == refs[i] && gatheredRefs[1] == refs[i+N]) ||
|
||||
(gatheredRefs[1] == refs[i] && gatheredRefs[0] == refs[i+N]));
|
||||
}
|
||||
}
|
||||
|
||||
SkBitmap image;
|
||||
draw(pic, 2*IW, 2*IH, &image);
|
||||
|
||||
// Test a bunch of random (mostly) rects, and compare the gather results
|
||||
// with the analytic results and the pixel refs seen in a rendering.
|
||||
for (int j = 0; j < 100; ++j) {
|
||||
SkRect r;
|
||||
rand_rect(&r, rand, 2*W, 2*H);
|
||||
|
||||
SkTDArray<SkPixelRef*> fromImage;
|
||||
gather_from_image(image, refs, N, &fromImage, r);
|
||||
|
||||
SkTDArray<SkPixelRef*> fromAnalytic;
|
||||
gather_from_analytic(pos, W, H, analytic, N, &fromAnalytic, r);
|
||||
|
||||
SkTDArray<SkPixelRef*> gatheredRefs;
|
||||
prCont->query(r, &gatheredRefs);
|
||||
|
||||
// Everything that we saw drawn should appear in the analytic list
|
||||
// but the analytic list may contain some pixelRefs that were not
|
||||
// seen in the image (e.g., A8 textures used as masks)
|
||||
for (int i = 0; i < fromImage.count(); ++i) {
|
||||
REPORTER_ASSERT(reporter, -1 != fromAnalytic.find(fromImage[i]));
|
||||
}
|
||||
|
||||
// Everything in the analytic list should appear in the gathered
|
||||
// list.
|
||||
for (int i = 0; i < fromAnalytic.count(); ++i) {
|
||||
REPORTER_ASSERT(reporter, -1 != gatheredRefs.find(fromAnalytic[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// Ensure that deleting an empty SkPicture does not assert. Asserts only fire
|
||||
// in debug mode, so only run in debug mode.
|
||||
@ -1769,8 +1173,6 @@ DEF_TEST(Picture, reporter) {
|
||||
#endif
|
||||
test_has_text(reporter);
|
||||
test_analysis(reporter);
|
||||
test_gatherpixelrefs(reporter);
|
||||
test_gatherpixelrefsandrects(reporter);
|
||||
test_bitmap_with_encoded_data(reporter);
|
||||
test_clip_bound_opt(reporter);
|
||||
test_clip_expansion(reporter);
|
||||
|
@ -831,39 +831,4 @@ SkBBHFactory* PictureRenderer::getFactory() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GatherRenderer : public PictureRenderer {
|
||||
public:
|
||||
#if SK_SUPPORT_GPU
|
||||
GatherRenderer(const GrContext::Options& opts) : INHERITED(opts) { }
|
||||
#endif
|
||||
|
||||
bool render(SkBitmap** out = NULL) SK_OVERRIDE {
|
||||
SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->cullRect().width()),
|
||||
SkIntToScalar(fPicture->cullRect().height()));
|
||||
SkData* data = SkPictureUtils::GatherPixelRefs(fPicture, bounds);
|
||||
SkSafeUnref(data);
|
||||
|
||||
return (fWritePath.isEmpty()); // we don't have anything to write
|
||||
}
|
||||
|
||||
private:
|
||||
SkString getConfigNameInternal() SK_OVERRIDE {
|
||||
return SkString("gather_pixelrefs");
|
||||
}
|
||||
|
||||
typedef PictureRenderer INHERITED;
|
||||
};
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
PictureRenderer* CreateGatherPixelRefsRenderer(const GrContext::Options& opts) {
|
||||
return SkNEW_ARGS(GatherRenderer, (opts));
|
||||
}
|
||||
#else
|
||||
PictureRenderer* CreateGatherPixelRefsRenderer() {
|
||||
return SkNEW(GatherRenderer);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace sk_tools
|
||||
|
@ -131,12 +131,6 @@ sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) {
|
||||
} else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) {
|
||||
renderer.reset(SkNEW_ARGS(sk_tools::PlaybackCreationRenderer, RENDERER_ARGS));
|
||||
// undocumented
|
||||
} else if (0 == strcmp(mode, "gatherPixelRefs") && kBench_PictureTool == tool) {
|
||||
#if SK_SUPPORT_GPU
|
||||
renderer.reset(sk_tools::CreateGatherPixelRefsRenderer(grContextOpts));
|
||||
#else
|
||||
renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
|
||||
#endif
|
||||
} else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) {
|
||||
renderer.reset(SkNEW_ARGS(sk_tools::RecordPictureRenderer, RENDERER_ARGS));
|
||||
} else if (0 == strcmp(mode, "simple")) {
|
||||
|
Loading…
Reference in New Issue
Block a user