antialias matrix-image-filter to get smooth diagonals

BUG=skia:

Review URL: https://codereview.chromium.org/1134743003
This commit is contained in:
reed 2015-05-15 10:33:31 -07:00 committed by Commit bot
parent 5f68c34840
commit fa33f5a6b7
5 changed files with 25 additions and 7 deletions

View File

@ -81,6 +81,9 @@ public:
public:
virtual ~Proxy() {};
/**
* The returned device will be zero-initialized (transparent black)
*/
virtual SkBaseDevice* createDevice(int width, int height) = 0;
// returns true if the proxy can handle this filter natively
virtual bool canHandleImageFilter(const SkImageFilter*) = 0;
@ -344,6 +347,12 @@ protected:
private:
bool usesSrcInput() const { return fUsesSrcInput; }
// Hack to optimize how we saveLayer, remove when no longer needed by SkCanvas
bool mayDrawWithMatrix() const { return this->onMayDrawWithMatrix(); }
// Return true if the subclass may draw the src transformed (e.g. w/ matrix)
virtual bool onMayDrawWithMatrix() const { return false; }
friend class SkCanvas;
typedef SkFlattenable INHERITED;
int fInputCount;
SkImageFilter** fInputs;

View File

@ -992,6 +992,8 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
flags |= kClipToLayer_SaveFlag;
#endif
SkImageFilter* imgf = paint ? paint->getImageFilter() : NULL;
// do this before we create the layer. We don't call the public save() since
// that would invoke a possibly overridden virtual
this->internalSave();
@ -999,7 +1001,7 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
fDeviceCMDirty = true;
SkIRect ir;
if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
if (!this->clipRectBounds(bounds, flags, &ir, imgf)) {
return;
}
@ -1013,7 +1015,7 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
SkPixelGeometry geo = fProps.pixelGeometry();
if (paint) {
// TODO: perhaps add a query to filters so we might preserve opaqueness...
if (paint->getImageFilter() || paint->getColorFilter()) {
if (imgf || paint->getColorFilter()) {
isOpaque = false;
geo = kUnknown_SkPixelGeometry;
}
@ -1029,7 +1031,10 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
bool forceSpriteOnRestore = false;
{
const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
if (imgf && imgf->mayDrawWithMatrix()) {
usage = SkBaseDevice::kPossible_TileUsage;
}
const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo);
SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
if (NULL == newDev) {

View File

@ -21,6 +21,8 @@ public:
{}
SkBaseDevice* createDevice(int w, int h) override {
// Our contract is to return a zero-initialized device, so we request iPremul_AlphaType
// which is the signal to the fDevice to perform this init.
SkBaseDevice::CreateInfo cinfo(SkImageInfo::MakeN32Premul(w, h),
SkBaseDevice::kNever_TileUsage,
kUnknown_SkPixelGeometry,

View File

@ -76,13 +76,13 @@ bool SkMatrixImageFilter::onFilterImage(Proxy* proxy,
return false;
}
SkPaint paint;
paint.setFilterQuality(fFilterQuality);
paint.setAntiAlias(true); // since we may be rotated, we definitely want a smooth edge
SkCanvas canvas(device.get());
canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
canvas.concat(matrix);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setFilterQuality(fFilterQuality);
canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint);
*result = device.get()->accessBitmap(false);

View File

@ -57,6 +57,8 @@ protected:
SkIRect* dst) const override;
private:
bool onMayDrawWithMatrix() const override { return true; }
SkMatrix fTransform;
SkFilterQuality fFilterQuality;
typedef SkImageFilter INHERITED;