# ('Poppler random failures'): ignore any Poppler failures, for now
pdf-poppler
+# Added by bsalomon, test case added in https://codereview.chromium.org/30593003
+imagefiltersgraph
\ No newline at end of file
#include "gm.h"
+#include "SkArithmeticMode.h"
#include "SkBitmapSource.h"
#include "SkBlurImageFilter.h"
#include "SkColorFilter.h"
#include "SkColorMatrixFilter.h"
#include "SkColorFilterImageFilter.h"
+#include "SkFlattenableBuffers.h"
#include "SkMergeImageFilter.h"
#include "SkMorphologyImageFilter.h"
+#include "SkOnce.h"
#include "SkXfermodeImageFilter.h"
#include "SkTestImageFilters.h"
///////////////////////////////////////////////////////////////////////////////
+namespace {
+// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
+// perform a draw and this one does.
+class SimpleOffsetFilter : public SkImageFilter {
+public:
+ SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
+ : SkImageFilter(input), fDX(dx), fDY(dy) {}
+
+ virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
+ SkBitmap* dst, SkIPoint* offset) SK_OVERRIDE {
+ SkBitmap source = src;
+ SkImageFilter* input = getInput(0);
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
+ return false;
+ }
+
+ SkIRect bounds;
+ source.getBounds(&bounds);
+
+ if (!this->applyCropRect(&bounds, ctm)) {
+ return false;
+ }
+
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
+ SkCanvas canvas(device);
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
+ *dst = device->accessBitmap(false);
+ offset->fX += bounds.left();
+ offset->fY += bounds.top();
+ return true;
+ }
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
+
+protected:
+ explicit SimpleOffsetFilter(SkFlattenableReadBuffer& buffer)
+ : SkImageFilter(buffer) {
+ fDX = buffer.readScalar();
+ fDY = buffer.readScalar();
+ }
+
+ virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ this->SkImageFilter::flatten(buffer);
+ buffer.writeScalar(fDX);
+ buffer.writeScalar(fDY);
+ }
+
+private:
+ SkScalar fDX, fDY;
+};
+}
+
+static void init_flattenable(int*) {
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter)
+}
+
class ImageFiltersGraphGM : public skiagm::GM {
public:
- ImageFiltersGraphGM() : fInitialized(false) {}
+ ImageFiltersGraphGM() : fInitialized(false) {
+ int dummy;
+ SK_DECLARE_STATIC_ONCE(once);
+ SkOnce(&once, init_flattenable, &dummy);
+ }
protected:
virtual SkString onShortName() {
canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
}
- virtual SkISize onISize() { return SkISize::Make(200, 100); }
+ virtual SkISize onISize() { return SkISize::Make(500, 150); }
virtual void onDraw(SkCanvas* canvas) {
if (!fInitialized) {
paint.setImageFilter(blendColor);
canvas->drawBitmap(fBitmap, 100, 0, &paint);
}
+ {
+ SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
+ 0, SK_Scalar1, 0, 0, 0,
+ 0, 0, SK_Scalar1, 0, 0,
+ 0, 0, 0, SkFloatToScalar(0.5f), 0 };
+ SkColorMatrixFilter matrixCF(matrix);
+ SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(&matrixCF));
+ SimpleOffsetFilter offsetFilter(SkIntToScalar(10), SkIntToScalar(10), matrixFilter);
+
+ SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
+ SkXfermodeImageFilter arithFilter(arith, matrixFilter, &offsetFilter);
+
+ SkPaint paint;
+ paint.setImageFilter(&arithFilter);
+ canvas->drawSprite(fBitmap, 200, 0, &paint);
+ }
}
private:
const SkRect* srcRectPtr) const;
void internalDrawBitmap(const SkBitmap&,
const SkRect&,
- const SkMatrix&,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags);
void drawTiledBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
- const SkMatrix& m,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags);
bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
const SkBitmap& src, const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset) {
+ // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
+ // matrix with no clip and that the matrix, clip, and render target set before this function was
+ // called are restored before we return to the caller.
+ GrContext* context = src.getTexture()->getContext();
+ GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
if (!filter) {
*result = src;
return true;
} else {
if (filter->filterImage(proxy, src, ctm, result, offset)) {
if (!result->getTexture()) {
- GrContext* context = ((GrTexture *) src.getTexture())->getContext();
- GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context,
- *result, NULL);
+ GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
result->setPixelRef(new SkGrPixelRef(resultTex))->unref();
GrUnlockAndUnrefCachedBitmapTexture(resultTex);
}
return;
}
+ fContext->concatMatrix(m);
+
GrTextureParams params;
SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
GrTextureParams::FilterMode textureFilterMode;
if (!this->shouldTileBitmap(bitmap, params, srcRectPtr)) {
// take the simple case
- this->internalDrawBitmap(bitmap, srcRect, m, params, paint, flags);
+ this->internalDrawBitmap(bitmap, srcRect, params, paint, flags);
} else {
- this->drawTiledBitmap(bitmap, srcRect, m, params, paint, flags);
+ this->drawTiledBitmap(bitmap, srcRect, params, paint, flags);
}
}
// been determined to be too large to fit in VRAM
void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
- const SkMatrix& m,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) {
if (!fContext->getClip()->fClipStack->intersectRectWithClip(&clipRect)) {
return;
}
- SkMatrix matrix, inverse;
- matrix.setConcat(fContext->getMatrix(), m);
- if (!matrix.invert(&inverse)) {
+ SkMatrix inverse;
+ if (!fContext->getMatrix().invert(&inverse)) {
return;
}
inverse.mapRect(&clipRect);
if (bitmap.extractSubset(&tmpB, iTileR)) {
// now offset it to make it "local" to our tmp bitmap
tileR.offset(-offset.fX, -offset.fY);
- SkMatrix tmpM(m);
- tmpM.preTranslate(offset.fX, offset.fY);
-
- this->internalDrawBitmap(tmpB, tileR, tmpM, params, paint, flags);
+ SkMatrix tmpM;
+ tmpM.setTranslate(offset.fX, offset.fY);
+ GrContext::AutoMatrix am;
+ am.setPreConcat(fContext, tmpM);
+ this->internalDrawBitmap(tmpB, tileR, params, paint, flags);
}
}
}
*/
void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
const SkRect& srcRect,
- const SkMatrix& m,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) {
// Need texture domain if drawing a sub rect.
needsTextureDomain = srcRect.width() < bitmap.width() ||
srcRect.height() < bitmap.height();
- if (needsTextureDomain && m.rectStaysRect() && fContext->getMatrix().rectStaysRect()) {
+ if (needsTextureDomain && fContext->getMatrix().rectStaysRect()) {
+ const SkMatrix& matrix = fContext->getMatrix();
// sampling is axis-aligned
SkRect transformedRect;
- SkMatrix srcToDeviceMatrix(m);
- srcToDeviceMatrix.postConcat(fContext->getMatrix());
- srcToDeviceMatrix.mapRect(&transformedRect, srcRect);
-
+ matrix.mapRect(&transformedRect, srcRect);
+
if (has_aligned_samples(srcRect, transformedRect)) {
// We could also turn off filtering here (but we already did a cache lookup with
// params).
needsTextureDomain = false;
} else {
- needsTextureDomain = may_color_bleed(srcRect, transformedRect, m);
+ needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix);
}
}
}
return;
}
- fContext->drawRectToRect(grPaint, dstRect, paintRect, &m);
+ fContext->drawRectToRect(grPaint, dstRect, paintRect, NULL);
}
static bool filter_texture(SkBaseDevice* device, GrContext* context,