Fix the way we patch up the matrix for scaled images that aren't
authorhumper <humper@google.com>
Mon, 27 Oct 2014 17:32:06 +0000 (10:32 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 27 Oct 2014 17:32:07 +0000 (10:32 -0700)
clamp/clamp

BUG=skia:2904
TBR=reed

Review URL: https://codereview.chromium.org/675823002

gm/tiledscaledbitmap.cpp [new file with mode: 0644]
gyp/gmslides.gypi
src/core/SkBitmapProcState.cpp

diff --git a/gm/tiledscaledbitmap.cpp b/gm/tiledscaledbitmap.cpp
new file mode 100644 (file)
index 0000000..3ea110c
--- /dev/null
@@ -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);)
+
+}
index 261300e..b9ff1d9 100644 (file)
         '../gm/texturedomaineffect.cpp',
         '../gm/thinrects.cpp',
         '../gm/thinstrokedrects.cpp',
+        '../gm/tiledscaledbitmap.cpp',
         '../gm/tileimagefilter.cpp',
         '../gm/tilemodes.cpp',
         '../gm/tilemodes_scaled.cpp',
index b1b50b0..656e0c4 100644 (file)
@@ -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