From 535e3b2025d3244c2ca48982d14d1d31f1d23c1f Mon Sep 17 00:00:00 2001 From: humper Date: Mon, 27 Oct 2014 10:32:06 -0700 Subject: [PATCH] Fix the way we patch up the matrix for scaled images that aren't clamp/clamp BUG=skia:2904 TBR=reed Review URL: https://codereview.chromium.org/675823002 --- gm/tiledscaledbitmap.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++ gyp/gmslides.gypi | 1 + src/core/SkBitmapProcState.cpp | 28 ++++++-------- 3 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 gm/tiledscaledbitmap.cpp diff --git a/gm/tiledscaledbitmap.cpp b/gm/tiledscaledbitmap.cpp new file mode 100644 index 0000000..3ea110c --- /dev/null +++ b/gm/tiledscaledbitmap.cpp @@ -0,0 +1,88 @@ + +/* + * 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 "gm.h" + +#include "Resources.h" +#include "SkBitmap.h" +#include "SkImageDecoder.h" +#include "SkPaint.h" +#include "SkShader.h" +#include "SkStream.h" + + + /*** + * + * This GM reproduces Skia bug 2904, in which a tiled bitmap shader was failing to draw correctly + * when fractional image scaling was ignored by the high quality bitmap scaler. + * + ***/ + +namespace skiagm { + +class TiledScaledBitmapGM : public GM { +public: + + TiledScaledBitmapGM() { + } + +protected: + virtual SkString onShortName() { + return SkString("tiledscaledbitmap"); + } + + virtual SkISize onISize() { + return SkISize::Make(1016, 616); + } + + virtual uint32_t onGetFlags() const SK_OVERRIDE { + return kSkipTiled_Flag; + } + + static SkBitmap make_bm(int width, int height) { + SkBitmap bm; + bm.allocN32Pixels(width, height); + bm.eraseColor(SK_ColorTRANSPARENT); + SkCanvas canvas(bm); + SkPaint paint; + paint.setAntiAlias(true); + canvas.drawCircle(width/2.f, height/2.f, width/4.f, paint); + return bm; + } + + virtual void onOnceBeforeDraw() SK_OVERRIDE { + fBitmap = make_bm(360, 288); + } + + virtual void onDraw(SkCanvas* canvas) { + SkPaint paint; + + paint.setAntiAlias(true); + paint.setFilterLevel(SkPaint::kHigh_FilterLevel); + + SkMatrix mat; + mat.setScale(121.f/360.f, 93.f/288.f); + mat.postTranslate(-72, -72); + + SkShader *shader = SkShader::CreateBitmapShader(fBitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &mat); + paint.setShader(shader); + + SkSafeUnref(shader); + canvas->drawRectCoords(8,8,1008, 608, paint); + } + +private: + SkBitmap fBitmap; + + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +DEF_GM(return SkNEW(TiledScaledBitmapGM);) + +} diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 261300e..b9ff1d9 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -185,6 +185,7 @@ '../gm/texturedomaineffect.cpp', '../gm/thinrects.cpp', '../gm/thinstrokedrects.cpp', + '../gm/tiledscaledbitmap.cpp', '../gm/tileimagefilter.cpp', '../gm/tilemodes.cpp', '../gm/tilemodes_scaled.cpp', diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp index b1b50b0..656e0c4 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -131,8 +131,6 @@ static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { bool SkBitmapProcState::possiblyScaleImage() { SkASSERT(NULL == fBitmap); - fAdjustedMatrix = false; - if (fFilterLevel <= SkPaint::kLow_FilterLevel) { return false; } @@ -198,19 +196,10 @@ bool SkBitmapProcState::possiblyScaleImage() { SkASSERT(fScaledBitmap.getPixels()); fBitmap = &fScaledBitmap; - // set the inv matrix type to translate-only; - fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(), - fInvMatrix.getTranslateY() / fInvMatrix.getScaleY()); - -#ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING - // reintroduce any fractional scaling missed by our integral scale done above. + // clean up the inverse matrix by incorporating the scale we just performed. - float fractionalScaleX = roundedDestWidth/trueDestWidth; - float fractionalScaleY = roundedDestHeight/trueDestHeight; - - fInvMatrix.postScale(fractionalScaleX, fractionalScaleY); -#endif - fAdjustedMatrix = true; + fInvMatrix.postScale(roundedDestWidth / fOrigBitmap.width(), + roundedDestHeight / fOrigBitmap.height()); // Set our filter level to low -- the only post-filtering this // image might require is some interpolation if the translation @@ -374,8 +363,15 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY; - if (!(fAdjustedMatrix || clampClamp || trivialMatrix)) { - fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); + // Most of the scanline procs deal with "unit" texture coordinates, as this + // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generate + // those, we divide the matrix by its dimensions here. + // + // We don't do this if we're either trivial (can ignore the matrix) or clamping + // in both X and Y since clamping to width,height is just as easy as to 0xFFFF. + + if (!(clampClamp || trivialMatrix)) { + fInvMatrix.postIDiv(fBitmap->width(), fBitmap->height()); } // Now that all possible changes to the matrix have taken place, check -- 2.7.4