Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "gm.h"
      9 #include "sk_tool_utils.h"
     10 #include "SkCanvas.h"
     11 #include "SkGradientShader.h"
     12 #include "SkGraphics.h"
     13 #include "SkPath.h"
     14 #include "SkRegion.h"
     15 #include "SkShader.h"
     16 
     17 static void make_bitmap(SkBitmap* bitmap) {
     18     bitmap->allocN32Pixels(64, 64);
     19 
     20     SkCanvas canvas(*bitmap);
     21 
     22     canvas.drawColor(SK_ColorRED);
     23     SkPaint paint;
     24     paint.setAntiAlias(true);
     25     const SkPoint pts[] = { { 0, 0 }, { 64, 64 } };
     26     const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
     27     paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2,
     28                                                  SkShader::kClamp_TileMode));
     29     canvas.drawCircle(32, 32, 32, paint);
     30 }
     31 
     32 class DrawBitmapRect2 : public skiagm::GM {
     33     bool fUseIRect;
     34 public:
     35     DrawBitmapRect2(bool useIRect) : fUseIRect(useIRect) {
     36     }
     37 
     38 protected:
     39     SkString onShortName() override {
     40         SkString str;
     41         str.printf("bitmaprect_%s", fUseIRect ? "i" : "s");
     42         return str;
     43     }
     44 
     45     SkISize onISize() override {
     46         return SkISize::Make(640, 480);
     47     }
     48 
     49     void onDraw(SkCanvas* canvas) override {
     50         canvas->drawColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
     51 
     52         const SkIRect src[] = {
     53             { 0, 0, 32, 32 },
     54             { 0, 0, 80, 80 },
     55             { 32, 32, 96, 96 },
     56             { -32, -32, 32, 32, }
     57         };
     58 
     59         SkPaint paint;
     60         paint.setStyle(SkPaint::kStroke_Style);
     61 
     62         SkBitmap bitmap;
     63         make_bitmap(&bitmap);
     64 
     65         SkRect dstR = { 0, 200, 128, 380 };
     66 
     67         canvas->translate(16, 40);
     68         for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
     69             SkRect srcR;
     70             srcR.set(src[i]);
     71 
     72             canvas->drawBitmap(bitmap, 0, 0, &paint);
     73             if (!fUseIRect) {
     74                 canvas->drawBitmapRect(bitmap, srcR, dstR, &paint,
     75                                        SkCanvas::kStrict_SrcRectConstraint);
     76             } else {
     77                 canvas->drawBitmapRect(bitmap, src[i], dstR, &paint);
     78             }
     79 
     80             canvas->drawRect(dstR, paint);
     81             canvas->drawRect(srcR, paint);
     82 
     83             canvas->translate(160, 0);
     84         }
     85     }
     86 
     87 private:
     88     typedef skiagm::GM INHERITED;
     89 };
     90 
     91 //////////////////////////////////////////////////////////////////////////////
     92 
     93 static void make_3x3_bitmap(SkBitmap* bitmap) {
     94     const int xSize = 3;
     95     const int ySize = 3;
     96 
     97     const SkColor textureData[xSize][ySize] = {
     98         { SK_ColorRED,    SK_ColorWHITE, SK_ColorBLUE },
     99         { SK_ColorGREEN,  SK_ColorBLACK, SK_ColorCYAN },
    100         { SK_ColorYELLOW, SK_ColorGRAY,  SK_ColorMAGENTA }
    101     };
    102 
    103     bitmap->allocN32Pixels(xSize, ySize, true);
    104     SkCanvas canvas(*bitmap);
    105     SkPaint paint;
    106 
    107     for (int y = 0; y < ySize; y++) {
    108         for (int x = 0; x < xSize; x++) {
    109             paint.setColor(textureData[x][y]);
    110             canvas.drawIRect(SkIRect::MakeXYWH(x, y, 1, 1), paint);
    111         }
    112     }
    113 }
    114 
    115 // This GM attempts to make visible any issues drawBitmapRect may have
    116 // with partial source rects. In this case the eight pixels on the border
    117 // should be half the width/height of the central pixel, i.e.:
    118 //                         __|____|__
    119 //                           |    |
    120 //                         __|____|__
    121 //                           |    |
    122 class DrawBitmapRect3 : public skiagm::GM {
    123 public:
    124     DrawBitmapRect3() {
    125         this->setBGColor(SK_ColorBLACK);
    126     }
    127 
    128 protected:
    129     SkString onShortName() override {
    130         SkString str;
    131         str.printf("3x3bitmaprect");
    132         return str;
    133     }
    134 
    135     SkISize onISize() override {
    136         return SkISize::Make(640, 480);
    137     }
    138 
    139     void onDraw(SkCanvas* canvas) override {
    140 
    141         SkBitmap bitmap;
    142         make_3x3_bitmap(&bitmap);
    143 
    144         SkRect srcR = { 0.5f, 0.5f, 2.5f, 2.5f };
    145         SkRect dstR = { 100, 100, 300, 200 };
    146 
    147         canvas->drawBitmapRect(bitmap, srcR, dstR, nullptr, SkCanvas::kStrict_SrcRectConstraint);
    148     }
    149 
    150 private:
    151     typedef skiagm::GM INHERITED;
    152 };
    153 
    154 //////////////////////////////////////////////////////////////////////////////
    155 static void make_big_bitmap(SkBitmap* bitmap) {
    156 
    157     constexpr int gXSize = 4096;
    158     constexpr int gYSize = 4096;
    159     constexpr int gBorderWidth = 10;
    160 
    161     bitmap->allocN32Pixels(gXSize, gYSize);
    162     for (int y = 0; y < gYSize; ++y) {
    163         for (int x = 0; x < gXSize; ++x) {
    164             if (x <= gBorderWidth || x >= gXSize-gBorderWidth ||
    165                 y <= gBorderWidth || y >= gYSize-gBorderWidth) {
    166                 *bitmap->getAddr32(x, y) = SkPreMultiplyColor(0x88FFFFFF);
    167             } else {
    168                 *bitmap->getAddr32(x, y) = SkPreMultiplyColor(0x88FF0000);
    169             }
    170         }
    171     }
    172 }
    173 
    174 // This GM attempts to reveal any issues we may have when the GPU has to
    175 // break up a large texture in order to draw it. The XOR transfer mode will
    176 // create stripes in the image if there is imprecision in the destination
    177 // tile placement.
    178 class DrawBitmapRect4 : public skiagm::GM {
    179     bool fUseIRect;
    180     SkBitmap fBigBitmap;
    181 
    182 public:
    183     DrawBitmapRect4(bool useIRect) : fUseIRect(useIRect) {
    184         this->setBGColor(0x88444444);
    185     }
    186 
    187 protected:
    188     SkString onShortName() override {
    189         SkString str;
    190         str.printf("bigbitmaprect_%s", fUseIRect ? "i" : "s");
    191         return str;
    192     }
    193 
    194     SkISize onISize() override {
    195         return SkISize::Make(640, 480);
    196     }
    197 
    198     void onOnceBeforeDraw() override {
    199         make_big_bitmap(&fBigBitmap);
    200     }
    201 
    202     void onDraw(SkCanvas* canvas) override {
    203         SkPaint paint;
    204         paint.setAlpha(128);
    205         paint.setBlendMode(SkBlendMode::kXor);
    206 
    207         SkRect srcR1 = { 0.0f, 0.0f, 4096.0f, 2040.0f };
    208         SkRect dstR1 = { 10.1f, 10.1f, 629.9f, 400.9f };
    209 
    210         SkRect srcR2 = { 4085.0f, 10.0f, 4087.0f, 12.0f };
    211         SkRect dstR2 = { 10, 410, 30, 430 };
    212 
    213         if (!fUseIRect) {
    214             canvas->drawBitmapRect(fBigBitmap, srcR1, dstR1, &paint,
    215                                    SkCanvas::kStrict_SrcRectConstraint);
    216             canvas->drawBitmapRect(fBigBitmap, srcR2, dstR2, &paint,
    217                                    SkCanvas::kStrict_SrcRectConstraint);
    218         } else {
    219             canvas->drawBitmapRect(fBigBitmap, srcR1.roundOut(), dstR1, &paint);
    220             canvas->drawBitmapRect(fBigBitmap, srcR2.roundOut(), dstR2, &paint);
    221         }
    222     }
    223 
    224 private:
    225     typedef skiagm::GM INHERITED;
    226 };
    227 
    228 class BitmapRectRounding : public skiagm::GM {
    229     SkBitmap fBM;
    230 
    231 public:
    232     BitmapRectRounding() {}
    233 
    234 protected:
    235     SkString onShortName() override {
    236         SkString str;
    237         str.printf("bitmaprect_rounding");
    238         return str;
    239     }
    240 
    241     SkISize onISize() override {
    242         return SkISize::Make(640, 480);
    243     }
    244 
    245     void onOnceBeforeDraw() override {
    246         fBM.allocN32Pixels(10, 10);
    247         fBM.eraseColor(SK_ColorBLUE);
    248     }
    249 
    250     // This choice of coordinates and matrix land the bottom edge of the clip (and bitmap dst)
    251     // at exactly 1/2 pixel boundary. However, drawBitmapRect may lose precision along the way.
    252     // If it does, we may see a red-line at the bottom, instead of the bitmap exactly matching
    253     // the clip (in which case we should see all blue).
    254     // The correct image should be all blue.
    255     void onDraw(SkCanvas* canvas) override {
    256         SkPaint paint;
    257         paint.setColor(SK_ColorRED);
    258 
    259         const SkRect r = SkRect::MakeXYWH(1, 1, 110, 114);
    260         canvas->scale(0.9f, 0.9f);
    261 
    262         // the drawRect shows the same problem as clipRect(r) followed by drawcolor(red)
    263         canvas->drawRect(r, paint);
    264         canvas->drawBitmapRect(fBM, r, nullptr);
    265     }
    266 
    267 private:
    268     typedef skiagm::GM INHERITED;
    269 };
    270 DEF_GM( return new BitmapRectRounding; )
    271 
    272 //////////////////////////////////////////////////////////////////////////////
    273 
    274 DEF_GM( return new DrawBitmapRect2(false); )
    275 DEF_GM( return new DrawBitmapRect2(true); )
    276 DEF_GM( return new DrawBitmapRect3(); )
    277 
    278 #ifndef SK_BUILD_FOR_ANDROID
    279 DEF_GM( return new DrawBitmapRect4(false); )
    280 DEF_GM( return new DrawBitmapRect4(true); )
    281 #endif
    282