Pull in Chromium's version of GatherPixelRefs
https://codereview.chromium.org/134473002/ git-svn-id: http://skia.googlecode.com/svn/trunk@13038 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
15ac322aae
commit
56bf6e4bce
@ -42,6 +42,7 @@
|
|||||||
'../include/utils/SkDebugUtils.h',
|
'../include/utils/SkDebugUtils.h',
|
||||||
'../include/utils/SkDeferredCanvas.h',
|
'../include/utils/SkDeferredCanvas.h',
|
||||||
'../include/utils/SkDumpCanvas.h',
|
'../include/utils/SkDumpCanvas.h',
|
||||||
|
'../include/utils/SkGatherPixelRefsAndRects.h',
|
||||||
'../include/utils/SkInterpolator.h',
|
'../include/utils/SkInterpolator.h',
|
||||||
'../include/utils/SkLayer.h',
|
'../include/utils/SkLayer.h',
|
||||||
'../include/utils/SkMatrix44.h',
|
'../include/utils/SkMatrix44.h',
|
||||||
@ -76,6 +77,7 @@
|
|||||||
'../src/utils/SkDeferredCanvas.cpp',
|
'../src/utils/SkDeferredCanvas.cpp',
|
||||||
'../src/utils/SkDumpCanvas.cpp',
|
'../src/utils/SkDumpCanvas.cpp',
|
||||||
'../src/utils/SkFloatUtils.h',
|
'../src/utils/SkFloatUtils.h',
|
||||||
|
'../src/utils/SkGatherPixelRefsAndRects.cpp',
|
||||||
'../src/utils/SkInterpolator.cpp',
|
'../src/utils/SkInterpolator.cpp',
|
||||||
'../src/utils/SkLayer.cpp',
|
'../src/utils/SkLayer.cpp',
|
||||||
'../src/utils/SkMatrix44.cpp',
|
'../src/utils/SkMatrix44.cpp',
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define SkPictureUtils_DEFINED
|
#define SkPictureUtils_DEFINED
|
||||||
|
|
||||||
#include "SkPicture.h"
|
#include "SkPicture.h"
|
||||||
|
#include "SkTDArray.h"
|
||||||
|
|
||||||
class SkData;
|
class SkData;
|
||||||
struct SkRect;
|
struct SkRect;
|
||||||
@ -26,6 +27,57 @@ public:
|
|||||||
* and remains unchanged.
|
* and remains unchanged.
|
||||||
*/
|
*/
|
||||||
static SkData* GatherPixelRefs(SkPicture* pict, const SkRect& area);
|
static SkData* GatherPixelRefs(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:
|
||||||
|
virtual void add(SkPixelRef* pr, const SkRect& rect) SK_OVERRIDE {
|
||||||
|
PixelRefAndRect *dst = fArray.append();
|
||||||
|
|
||||||
|
dst->fPixelRef = pr;
|
||||||
|
dst->fRect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
25
src/utils/SkGatherPixelRefsAndRects.cpp
Normal file
25
src/utils/SkGatherPixelRefsAndRects.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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 (0 == pict->width() || 0 == pict->height()) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkGatherPixelRefsAndRectsDevice device(pict->width(), pict->height(), prCont);
|
||||||
|
SkNoSaveLayerCanvas canvas(&device);
|
||||||
|
|
||||||
|
canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()),
|
||||||
|
SkIntToScalar(pict->height())),
|
||||||
|
SkRegion::kIntersect_Op, false);
|
||||||
|
canvas.drawPicture(*pict);
|
||||||
|
}
|
353
src/utils/SkGatherPixelRefsAndRects.h
Normal file
353
src/utils/SkGatherPixelRefsAndRects.h
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
* 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.setConfig(SkBitmap::kNo_Config, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~SkGatherPixelRefsAndRectsDevice() {
|
||||||
|
SkSafeUnref(fPRCont);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { return 0; }
|
||||||
|
|
||||||
|
virtual int width() const SK_OVERRIDE { return fSize.width(); }
|
||||||
|
virtual int height() const SK_OVERRIDE { return fSize.height(); }
|
||||||
|
virtual bool isOpaque() const SK_OVERRIDE { return false; }
|
||||||
|
virtual SkBitmap::Config config() const SK_OVERRIDE {
|
||||||
|
return SkBitmap::kNo_Config;
|
||||||
|
}
|
||||||
|
virtual void writePixels(const SkBitmap& bitmap, int x, int y,
|
||||||
|
SkCanvas::Config8888 config8888) SK_OVERRIDE {
|
||||||
|
NotSupported();
|
||||||
|
}
|
||||||
|
virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void clear(SkColor color) SK_OVERRIDE {
|
||||||
|
NothingToDo();
|
||||||
|
}
|
||||||
|
virtual 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());
|
||||||
|
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 (NULL != 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[], SkScalar constY,
|
||||||
|
int scalarsPerPos, 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, max;
|
||||||
|
if (1 == scalarsPerPos) {
|
||||||
|
min.set(pos[0], constY);
|
||||||
|
max.set(pos[0], constY);
|
||||||
|
} else if (2 == scalarsPerPos) {
|
||||||
|
min.set(pos[0], constY + pos[1]);
|
||||||
|
max.set(pos[0], constY + pos[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 1; i < len; ++i) {
|
||||||
|
SkScalar x = pos[i * scalarsPerPos];
|
||||||
|
SkScalar y = constY;
|
||||||
|
if (2 == scalarsPerPos) {
|
||||||
|
y += pos[i * scalarsPerPos + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
|
||||||
|
return fEmptyBitmap;
|
||||||
|
}
|
||||||
|
virtual bool onReadPixels(const SkBitmap& bitmap,
|
||||||
|
int x, int y,
|
||||||
|
SkCanvas::Config8888 config8888) SK_OVERRIDE {
|
||||||
|
NotSupported();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
|
||||||
|
virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
|
||||||
|
virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
|
||||||
|
virtual bool canHandleImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
|
||||||
|
virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
|
||||||
|
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 (NULL != shader) {
|
||||||
|
if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
|
||||||
|
return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
|
||||||
|
NotSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
|
||||||
|
int width, int height,
|
||||||
|
bool isOpaque,
|
||||||
|
Usage usage) SK_OVERRIDE {
|
||||||
|
// we expect to only get called via savelayer, in which case it is fine.
|
||||||
|
SkASSERT(kSaveLayer_Usage == usage);
|
||||||
|
return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice, (width, height, fPRCont));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush() SK_OVERRIDE {}
|
||||||
|
|
||||||
|
static void NotSupported() {
|
||||||
|
SkDEBUGFAIL("this method should never be called");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NothingToDo() {}
|
||||||
|
|
||||||
|
typedef SkBaseDevice INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SkGatherPixelRefsAndRects_DEFINED
|
||||||
|
|
@ -50,6 +50,8 @@ static void nothing_to_do() {}
|
|||||||
*/
|
*/
|
||||||
class GatherPixelRefDevice : public SkBaseDevice {
|
class GatherPixelRefDevice : public SkBaseDevice {
|
||||||
public:
|
public:
|
||||||
|
SK_DECLARE_INST_COUNT(GatherPixelRefDevice)
|
||||||
|
|
||||||
GatherPixelRefDevice(int width, int height, PixelRefSet* prset) {
|
GatherPixelRefDevice(int width, int height, PixelRefSet* prset) {
|
||||||
fSize.set(width, height);
|
fSize.set(width, height);
|
||||||
fEmptyBitmap.setConfig(SkBitmap::kNo_Config, width, height);
|
fEmptyBitmap.setConfig(SkBitmap::kNo_Config, width, height);
|
||||||
|
@ -65,35 +65,42 @@ static void init_paint(SkPaint* paint, const SkBitmap &bm) {
|
|||||||
paint->setShader(shader)->unref();
|
paint->setShader(shader)->unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&, const SkBitmap&, const SkPoint&);
|
typedef void (*DrawBitmapProc)(SkCanvas*, const SkBitmap&,
|
||||||
|
const SkBitmap&, const SkPoint&,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs);
|
||||||
|
|
||||||
static void drawpaint_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawpaint_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
canvas->drawPaint(paint);
|
canvas->drawPaint(paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawpoints_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawpoints_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
// draw a slightly inset rect
|
// draw a rect
|
||||||
SkPoint points[5] = {
|
SkPoint points[5] = {
|
||||||
{ pos.fX + 1, pos.fY + 1 },
|
{ pos.fX, pos.fY },
|
||||||
{ pos.fX + bm.width() - 2, pos.fY + 1 },
|
{ pos.fX + bm.width() - 1, pos.fY },
|
||||||
{ pos.fX + bm.width() - 2, pos.fY + bm.height() - 2 },
|
{ pos.fX + bm.width() - 1, pos.fY + bm.height() - 1 },
|
||||||
{ pos.fX + 1, pos.fY + bm.height() - 2 },
|
{ pos.fX, pos.fY + bm.height() - 1 },
|
||||||
{ pos.fX + 1, pos.fY + 1 },
|
{ pos.fX, pos.fY },
|
||||||
};
|
};
|
||||||
|
|
||||||
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 5, points, paint);
|
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 5, points, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
@ -101,10 +108,12 @@ static void drawrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
r.offset(pos.fX, pos.fY);
|
r.offset(pos.fX, pos.fY);
|
||||||
|
|
||||||
canvas->drawRect(r, paint);
|
canvas->drawRect(r, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawoval_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawoval_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
@ -112,10 +121,12 @@ static void drawoval_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
r.offset(pos.fX, pos.fY);
|
r.offset(pos.fX, pos.fY);
|
||||||
|
|
||||||
canvas->drawOval(r, paint);
|
canvas->drawOval(r, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawrrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawrrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
@ -125,10 +136,12 @@ static void drawrrect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
SkRRect rr;
|
SkRRect rr;
|
||||||
rr.setRectXY(r, SkIntToScalar(bm.width())/4, SkIntToScalar(bm.height())/4);
|
rr.setRectXY(r, SkIntToScalar(bm.width())/4, SkIntToScalar(bm.height())/4);
|
||||||
canvas->drawRRect(rr, paint);
|
canvas->drawRRect(rr, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
@ -139,37 +152,46 @@ static void drawpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
path.offset(pos.fX, pos.fY);
|
path.offset(pos.fX, pos.fY);
|
||||||
|
|
||||||
canvas->drawPath(path, paint);
|
canvas->drawPath(path, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawbitmap_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
canvas->drawBitmap(bm, pos.fX, pos.fY, NULL);
|
canvas->drawBitmap(bm, pos.fX, pos.fY, NULL);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawbitmap_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawbitmap_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
// The bitmap in the paint is ignored unless we're drawing an A8 bitmap
|
// The bitmap in the paint is ignored unless we're drawing an A8 bitmap
|
||||||
canvas->drawBitmap(altBM, pos.fX, pos.fY, &paint);
|
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,
|
static void drawsprite_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
const SkMatrix& ctm = canvas->getTotalMatrix();
|
const SkMatrix& ctm = canvas->getTotalMatrix();
|
||||||
|
|
||||||
SkPoint p(pos);
|
SkPoint p(pos);
|
||||||
ctm.mapPoints(&p, 1);
|
ctm.mapPoints(&p, 1);
|
||||||
|
|
||||||
canvas->drawSprite(bm, (int)p.fX, (int)p.fY, NULL);
|
canvas->drawSprite(bm, (int)p.fX, (int)p.fY, NULL);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Although specifiable, this case doesn't seem to make sense (i.e., the
|
// Although specifiable, this case doesn't seem to make sense (i.e., the
|
||||||
// bitmap in the shader is never used).
|
// bitmap in the shader is never used).
|
||||||
static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
@ -179,21 +201,26 @@ static void drawsprite_withshader_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
ctm.mapPoints(&p, 1);
|
ctm.mapPoints(&p, 1);
|
||||||
|
|
||||||
canvas->drawSprite(altBM, (int)p.fX, (int)p.fY, &paint);
|
canvas->drawSprite(altBM, (int)p.fX, (int)p.fY, &paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
|
*usedPixRefs->append() = altBM.pixelRef();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawbitmaprect_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
SkRect r = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
|
||||||
|
|
||||||
r.offset(pos.fX, pos.fY);
|
r.offset(pos.fX, pos.fY);
|
||||||
canvas->drawBitmapRectToRect(bm, NULL, r, NULL);
|
canvas->drawBitmapRectToRect(bm, NULL, r, NULL);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawbitmaprect_withshader_proc(SkCanvas* canvas,
|
static void drawbitmaprect_withshader_proc(SkCanvas* canvas,
|
||||||
const SkBitmap& bm,
|
const SkBitmap& bm,
|
||||||
const SkBitmap& altBM,
|
const SkBitmap& altBM,
|
||||||
const SkPoint& pos) {
|
const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
@ -202,29 +229,36 @@ static void drawbitmaprect_withshader_proc(SkCanvas* canvas,
|
|||||||
|
|
||||||
// The bitmap in the paint is ignored unless we're drawing an A8 bitmap
|
// The bitmap in the paint is ignored unless we're drawing an A8 bitmap
|
||||||
canvas->drawBitmapRectToRect(altBM, NULL, r, &paint);
|
canvas->drawBitmapRectToRect(altBM, NULL, r, &paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
|
*usedPixRefs->append() = altBM.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawtext_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawtext_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
||||||
|
|
||||||
canvas->drawText("0", 1, pos.fX, pos.fY+bm.width(), paint);
|
canvas->drawText("0", 1, pos.fX, pos.fY+bm.width(), paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawpostext_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawpostext_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
paint.setTextSize(SkIntToScalar(1.5*bm.width()));
|
||||||
|
|
||||||
SkPoint point = { pos.fX, pos.fY + bm.height() };
|
SkPoint point = { pos.fX, pos.fY + bm.height() };
|
||||||
canvas->drawPosText("O", 1, &point, paint);
|
canvas->drawPosText("O", 1, &point, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawtextonpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawtextonpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
|
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
@ -235,18 +269,20 @@ static void drawtextonpath_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
path.offset(pos.fX, pos.fY+bm.height());
|
path.offset(pos.fX, pos.fY+bm.height());
|
||||||
|
|
||||||
canvas->drawTextOnPath("O", 1, path, NULL, paint);
|
canvas->drawTextOnPath("O", 1, path, NULL, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawverts_proc(SkCanvas* canvas, const SkBitmap& bm,
|
static void drawverts_proc(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
const SkBitmap& altBM, const SkPoint& pos) {
|
const SkBitmap& altBM, const SkPoint& pos,
|
||||||
|
SkTDArray<SkPixelRef*>* usedPixRefs) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
init_paint(&paint, bm);
|
init_paint(&paint, bm);
|
||||||
|
|
||||||
SkPoint verts[4] = {
|
SkPoint verts[4] = {
|
||||||
{ pos.fX+1, pos.fY+1 },
|
{ pos.fX, pos.fY },
|
||||||
{ pos.fX + bm.width()-1, pos.fY+1 },
|
{ pos.fX + bm.width(), pos.fY },
|
||||||
{ pos.fX + bm.width()-1, pos.fY + bm.height()-1 },
|
{ pos.fX + bm.width(), pos.fY + bm.height() },
|
||||||
{ pos.fX+1, pos.fY + bm.height()-1 }
|
{ pos.fX, pos.fY + bm.height() }
|
||||||
};
|
};
|
||||||
SkPoint texs[4] = { { 0, 0 },
|
SkPoint texs[4] = { { 0, 0 },
|
||||||
{ SkIntToScalar(bm.width()), 0 },
|
{ SkIntToScalar(bm.width()), 0 },
|
||||||
@ -256,20 +292,25 @@ static void drawverts_proc(SkCanvas* canvas, const SkBitmap& bm,
|
|||||||
|
|
||||||
canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 4, verts, texs, NULL, NULL,
|
canvas->drawVertices(SkCanvas::kTriangles_VertexMode, 4, verts, texs, NULL, NULL,
|
||||||
indices, 6, paint);
|
indices, 6, paint);
|
||||||
|
*usedPixRefs->append() = bm.pixelRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a picture with the bitmaps drawn at the specified positions.
|
// Return a picture with the bitmaps drawn at the specified positions.
|
||||||
static SkPicture* record_bitmaps(const SkBitmap bm[], const SkPoint pos[],
|
static SkPicture* record_bitmaps(const SkBitmap bm[],
|
||||||
int count, DrawBitmapProc proc) {
|
const SkPoint pos[],
|
||||||
|
SkTDArray<SkPixelRef*> analytic[],
|
||||||
|
int count,
|
||||||
|
DrawBitmapProc proc) {
|
||||||
SkPicture* pic = new SkPicture;
|
SkPicture* pic = new SkPicture;
|
||||||
SkCanvas* canvas = pic->beginRecording(1000, 1000);
|
SkCanvas* canvas = pic->beginRecording(1000, 1000);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
|
analytic[i].rewind();
|
||||||
canvas->save();
|
canvas->save();
|
||||||
SkRect clipRect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY,
|
SkRect clipRect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY,
|
||||||
SkIntToScalar(bm[i].width()),
|
SkIntToScalar(bm[i].width()),
|
||||||
SkIntToScalar(bm[i].height()));
|
SkIntToScalar(bm[i].height()));
|
||||||
canvas->clipRect(clipRect, SkRegion::kIntersect_Op);
|
canvas->clipRect(clipRect, SkRegion::kIntersect_Op);
|
||||||
proc(canvas, bm[i], bm[count+i], pos[i]);
|
proc(canvas, bm[i], bm[count+i], pos[i], &analytic[i]);
|
||||||
canvas->restore();
|
canvas->restore();
|
||||||
}
|
}
|
||||||
pic->endRecording();
|
pic->endRecording();
|
||||||
@ -363,40 +404,21 @@ static void gather_from_image(const SkBitmap& bm, SkPixelRef* const refs[],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
|
void gather_from_analytic(const SkPoint pos[], SkScalar w, SkScalar h,
|
||||||
const int IW = 32;
|
const SkTDArray<SkPixelRef*> analytic[],
|
||||||
const int IH = IW;
|
int count,
|
||||||
const SkScalar W = SkIntToScalar(IW);
|
SkTDArray<SkPixelRef*>* result,
|
||||||
const SkScalar H = W;
|
const SkRect& subset) {
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
SkRect rect = SkRect::MakeXYWH(pos[i].fX, pos[i].fY, w, h);
|
||||||
|
|
||||||
static const int N = 4;
|
if (SkRect::Intersects(subset, rect)) {
|
||||||
SkBitmap bm[2*N];
|
result->append(analytic[i].count(), analytic[i].begin());
|
||||||
SkPixelRef* refs[2*N];
|
}
|
||||||
|
}
|
||||||
const SkPoint pos[N] = {
|
|
||||||
{ 0, 0 }, { W, 0 }, { 0, H }, { W, 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 < N; ++i) {
|
|
||||||
make_bm(&bm[i], IW, IH,
|
|
||||||
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
|
static const DrawBitmapProc gProcs[] = {
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
make_checkerboard(&bm[N+i], IW, IH, true);
|
|
||||||
refs[N+i] = bm[N+i].pixelRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
static const DrawBitmapProc procs[] = {
|
|
||||||
drawpaint_proc,
|
drawpaint_proc,
|
||||||
drawpoints_proc,
|
drawpoints_proc,
|
||||||
drawrect_proc,
|
drawrect_proc,
|
||||||
@ -417,13 +439,51 @@ static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
|
|||||||
drawverts_proc,
|
drawverts_proc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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;
|
SkRandom rand;
|
||||||
for (size_t k = 0; k < SK_ARRAY_COUNT(procs); ++k) {
|
for (size_t k = 0; k < SK_ARRAY_COUNT(gProcs); ++k) {
|
||||||
SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, N, procs[k]));
|
SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, analytic, N, gProcs[k]));
|
||||||
|
|
||||||
REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
|
REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
|
||||||
// quick check for a small piece of each quadrant, which should just
|
// quick check for a small piece of each quadrant, which should just
|
||||||
// contain 1 bitmap.
|
// contain 1 or 2 bitmaps.
|
||||||
for (size_t i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
|
for (size_t i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
|
||||||
SkRect r;
|
SkRect r;
|
||||||
r.set(2, 2, W - 2, H - 2);
|
r.set(2, 2, W - 2, H - 2);
|
||||||
@ -453,7 +513,11 @@ static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
|
|||||||
SkRect r;
|
SkRect r;
|
||||||
rand_rect(&r, rand, 2*W, 2*H);
|
rand_rect(&r, rand, 2*W, 2*H);
|
||||||
|
|
||||||
SkTDArray<SkPixelRef*> array;
|
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);
|
SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
|
||||||
size_t dataSize = data ? data->size() : 0;
|
size_t dataSize = data ? data->size() : 0;
|
||||||
@ -462,18 +526,22 @@ static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
|
|||||||
SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
|
SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
|
||||||
SkAutoDataUnref adu(data);
|
SkAutoDataUnref adu(data);
|
||||||
|
|
||||||
gather_from_image(image, refs, N, &array, r);
|
// 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]));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GatherPixelRefs is conservative, so it can return more bitmaps
|
* GatherPixelRefs is conservative, so it can return more bitmaps
|
||||||
* that we actually can see (usually because of conservative bounds
|
* than are strictly required. Thus our check here is only that
|
||||||
* inflation for antialiasing). Thus our check here is only that
|
* Gather didn't miss any that we actually needed. Even that isn't
|
||||||
* 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
|
* a strict requirement on Gather, which is meant to be quick and
|
||||||
* only mostly-correct, but at the moment this test should work.
|
* only mostly-correct, but at the moment this test should work.
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < array.count(); ++i) {
|
for (int i = 0; i < fromAnalytic.count(); ++i) {
|
||||||
bool found = find(gatherRefs, array[i], gatherCount);
|
bool found = find(gatherRefs, fromAnalytic[i], gatherCount);
|
||||||
REPORTER_ASSERT(reporter, found);
|
REPORTER_ASSERT(reporter, found);
|
||||||
#if 0
|
#if 0
|
||||||
// enable this block of code to debug failures, as it will rerun
|
// enable this block of code to debug failures, as it will rerun
|
||||||
@ -488,6 +556,89 @@ static void test_gatherpixelrefs(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]));
|
||||||
|
|
||||||
|
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
|
#ifdef SK_DEBUG
|
||||||
// Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only
|
// Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only
|
||||||
// run in debug mode.
|
// run in debug mode.
|
||||||
@ -875,6 +1026,7 @@ DEF_TEST(Picture, reporter) {
|
|||||||
#endif
|
#endif
|
||||||
test_peephole();
|
test_peephole();
|
||||||
test_gatherpixelrefs(reporter);
|
test_gatherpixelrefs(reporter);
|
||||||
|
test_gatherpixelrefsandrects(reporter);
|
||||||
test_bitmap_with_encoded_data(reporter);
|
test_bitmap_with_encoded_data(reporter);
|
||||||
test_clone_empty(reporter);
|
test_clone_empty(reporter);
|
||||||
test_clip_bound_opt(reporter);
|
test_clip_bound_opt(reporter);
|
||||||
|
Loading…
Reference in New Issue
Block a user