refactor code to apply the croprect

BUG=skia:

Review URL: https://codereview.chromium.org/1218993002
This commit is contained in:
reed 2015-07-16 13:17:13 -07:00 committed by Commit bot
parent dfa0ecf169
commit 189186337e
2 changed files with 98 additions and 58 deletions

View File

@ -32,24 +32,6 @@ struct SkIPoint;
*/
class SK_API SkImageFilter : public SkFlattenable {
public:
class CropRect {
public:
enum CropEdge {
kHasLeft_CropEdge = 0x01,
kHasTop_CropEdge = 0x02,
kHasRight_CropEdge = 0x04,
kHasBottom_CropEdge = 0x08,
kHasAll_CropEdge = 0x0F,
};
CropRect() {}
explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
uint32_t flags() const { return fFlags; }
const SkRect& rect() const { return fRect; }
private:
SkRect fRect;
uint32_t fFlags;
};
// This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
// (result, offset).
class Cache : public SkRefCnt {
@ -77,6 +59,41 @@ public:
Cache* fCache;
};
class CropRect {
public:
enum CropEdge {
kHasLeft_CropEdge = 0x01,
kHasTop_CropEdge = 0x02,
kHasRight_CropEdge = 0x04,
kHasBottom_CropEdge = 0x08,
kHasAll_CropEdge = 0x0F,
};
CropRect() {}
explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
: fRect(rect), fFlags(flags) {}
uint32_t flags() const { return fFlags; }
const SkRect& rect() const { return fRect; }
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const;
#endif
/**
* Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
* set, then the corresponding edge from imageBounds will be used.
*
* Note: imageBounds is in "device" space, as the output cropped rectangle will be,
* so the context's CTM is ignore for those. It is only applied the croprect's bounds.
*
* The resulting rect will be intersected with the context's clip. If that intersection is
* empty, then this returns false and cropped is unmodified.
*/
bool applyTo(const SkIRect& imageBounds, const Context&, SkIRect* cropped) const;
private:
SkRect fRect;
uint32_t fFlags;
};
class Proxy {
public:
Proxy(SkBaseDevice* device) : fDevice(device) { }
@ -182,7 +199,8 @@ public:
/**
* Returns whether any edges of the crop rect have been set. The crop
* rect is set at construction time, and determines which pixels from the
* input image will be processed. The size of the crop rect should be
* input image will be processed, and which pixels in the output image will be allowed.
* The size of the crop rect should be
* used as the size of the destination image. The origin of this rect
* should be used to offset access to the input images, and should also
* be added to the "offset" parameter in onFilterImage and

View File

@ -33,6 +33,64 @@
enum { kDefaultCacheSize = 128 * 1024 * 1024 };
#endif
#ifndef SK_IGNORE_TO_STRING
void SkImageFilter::CropRect::toString(SkString* str) const {
if (!fFlags) {
return;
}
str->appendf("cropRect (");
if (fFlags & CropRect::kHasLeft_CropEdge) {
str->appendf("%.2f, ", fRect.fLeft);
} else {
str->appendf("X, ");
}
if (fFlags & CropRect::kHasTop_CropEdge) {
str->appendf("%.2f, ", fRect.fTop);
} else {
str->appendf("X, ");
}
if (fFlags & CropRect::kHasRight_CropEdge) {
str->appendf("%.2f, ", fRect.fRight);
} else {
str->appendf("X, ");
}
if (fFlags & CropRect::kHasBottom_CropEdge) {
str->appendf("%.2f", fRect.fBottom);
} else {
str->appendf("X");
}
str->appendf(") ");
}
#endif
bool SkImageFilter::CropRect::applyTo(const SkIRect& imageBounds, const Context& ctx,
SkIRect* cropped) const {
*cropped = imageBounds;
if (fFlags) {
SkRect devCropR;
ctx.ctm().mapRect(&devCropR, fRect);
const SkIRect devICropR = devCropR.roundOut();
// Compute the left/top first, in case we have to read them to compute right/bottom
if (fFlags & kHasLeft_CropEdge) {
cropped->fLeft = devICropR.fLeft;
}
if (fFlags & kHasTop_CropEdge) {
cropped->fTop = devICropR.fTop;
}
if (fFlags & kHasRight_CropEdge) {
cropped->fRight = cropped->fLeft + devICropR.width();
}
if (fFlags & kHasBottom_CropEdge) {
cropped->fBottom = cropped->fTop + devICropR.height();
}
}
return cropped->intersect(ctx.clipBounds());
}
///////////////////////////////////////////////////////////////////////////////////////////////////
static int32_t next_image_filter_unique_id() {
static int32_t gImageFilterUniqueID;
@ -298,27 +356,7 @@ bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
SkIRect srcBounds;
src.getBounds(&srcBounds);
srcBounds.offset(srcOffset);
SkRect cropRect;
ctx.ctm().mapRect(&cropRect, fCropRect.rect());
const SkIRect cropRectI = cropRect.roundOut();
uint32_t flags = fCropRect.flags();
if (flags & CropRect::kHasLeft_CropEdge) {
srcBounds.fLeft = cropRectI.fLeft;
}
if (flags & CropRect::kHasTop_CropEdge) {
srcBounds.fTop = cropRectI.fTop;
}
if (flags & CropRect::kHasRight_CropEdge) {
srcBounds.fRight = srcBounds.fLeft + cropRectI.width();
}
if (flags & CropRect::kHasBottom_CropEdge) {
srcBounds.fBottom = srcBounds.fTop + cropRectI.height();
}
if (!srcBounds.intersect(ctx.clipBounds())) {
return false;
}
*bounds = srcBounds;
return true;
return fCropRect.applyTo(srcBounds, ctx, bounds);
}
bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
@ -326,26 +364,10 @@ bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitm
SkIRect srcBounds;
src.getBounds(&srcBounds);
srcBounds.offset(*srcOffset);
SkRect cropRect;
ctx.ctm().mapRect(&cropRect, fCropRect.rect());
const SkIRect cropRectI = cropRect.roundOut();
uint32_t flags = fCropRect.flags();
*bounds = srcBounds;
if (flags & CropRect::kHasLeft_CropEdge) {
bounds->fLeft = cropRectI.fLeft;
}
if (flags & CropRect::kHasTop_CropEdge) {
bounds->fTop = cropRectI.fTop;
}
if (flags & CropRect::kHasRight_CropEdge) {
bounds->fRight = bounds->fLeft + cropRectI.width();
}
if (flags & CropRect::kHasBottom_CropEdge) {
bounds->fBottom = bounds->fTop + cropRectI.height();
}
if (!bounds->intersect(ctx.clipBounds())) {
if (!fCropRect.applyTo(srcBounds, ctx, bounds)) {
return false;
}
if (srcBounds.contains(*bounds)) {
*dst = src;
return true;