Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2016 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 "SkSurface.h"
     10 #include "sk_tool_utils.h"
     11 
     12 static sk_sp<SkSurface> make_surface(SkCanvas* root, int N, int padLeft, int padTop,
     13                                      int padRight, int padBottom) {
     14     SkImageInfo info = SkImageInfo::MakeN32Premul(N + padLeft + padRight, N + padTop + padBottom);
     15     return sk_tool_utils::makeSurface(root, info);
     16 }
     17 
     18 static sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs, int padLeft, int padTop,
     19                                  int padRight, int padBottom) {
     20     const int kCap = 28;
     21     const int kMid = 8;
     22     const int kSize = 2*kCap + 3*kMid;
     23 
     24     auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
     25     SkCanvas* canvas = surface->getCanvas();
     26     canvas->translate((float) padLeft, (float) padTop);
     27 
     28     SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
     29     const SkScalar strokeWidth = SkIntToScalar(6);
     30     const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2;
     31 
     32     xDivs[0] = kCap + padLeft;
     33     yDivs[0] = kCap + padTop;
     34     xDivs[1] = kCap + kMid + padLeft;
     35     yDivs[1] = kCap + kMid + padTop;
     36     xDivs[2] = kCap + 2 * kMid + padLeft;
     37     yDivs[2] = kCap + 2 * kMid + padTop;
     38     xDivs[3] = kCap + 3 * kMid + padLeft;
     39     yDivs[3] = kCap + 3 * kMid + padTop;
     40 
     41     SkPaint paint;
     42     paint.setAntiAlias(true);
     43 
     44     paint.setColor(0xFFFFFF00);
     45     canvas->drawRoundRect(r, radius, radius, paint);
     46 
     47     r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
     48     paint.setColor(0x8800FF00);
     49     canvas->drawRect(r, paint);
     50     r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
     51     paint.setColor(0x880000FF);
     52     canvas->drawRect(r, paint);
     53     r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
     54     paint.setColor(0x88FF00FF);
     55     canvas->drawRect(r, paint);
     56 
     57     r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid));
     58     paint.setColor(0x8800FF00);
     59     canvas->drawRect(r, paint);
     60     r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
     61     paint.setColor(0x880000FF);
     62     canvas->drawRect(r, paint);
     63     r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
     64     paint.setColor(0x88FF00FF);
     65     canvas->drawRect(r, paint);
     66 
     67     return surface->makeImageSnapshot();
     68 }
     69 
     70 static void image_to_bitmap(const SkImage* image, SkBitmap* bm) {
     71     SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height());
     72     bm->allocPixels(info);
     73     image->readPixels(info, bm->getPixels(), bm->rowBytes(), 0, 0);
     74 }
     75 
     76 /**
     77  *  This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more
     78  *  than nine patches.
     79  */
     80 class LatticeGM : public skiagm::GM {
     81 public:
     82     LatticeGM() {}
     83 
     84 protected:
     85     SkString onShortName() override {
     86         return SkString("lattice");
     87     }
     88 
     89     SkISize onISize() override {
     90         return SkISize::Make(800, 800);
     91     }
     92 
     93     void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom) {
     94         canvas->save();
     95 
     96         int xDivs[5];
     97         int yDivs[5];
     98         xDivs[0] = padLeft;
     99         yDivs[0] = padTop;
    100 
    101         SkBitmap bitmap;
    102         sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop,
    103                                           padRight, padBottom);
    104         image_to_bitmap(image.get(), &bitmap);
    105 
    106         const SkSize size[] = {
    107             {  50,  50, }, // shrink in both axes
    108             {  50, 200, }, // shrink in X
    109             { 200,  50, }, // shrink in Y
    110             { 200, 200, },
    111         };
    112 
    113         canvas->drawImage(image, 10, 10, nullptr);
    114 
    115         SkScalar x = SkIntToScalar(100);
    116         SkScalar y = SkIntToScalar(100);
    117 
    118         SkCanvas::Lattice lattice;
    119         lattice.fXCount = 4;
    120         lattice.fXDivs = xDivs + 1;
    121         lattice.fYCount = 4;
    122         lattice.fYDivs = yDivs + 1;
    123         lattice.fRectTypes = nullptr;
    124         lattice.fColors = nullptr;
    125 
    126         SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop,
    127                                            image->width() - padRight, image->height() - padBottom);
    128         lattice.fBounds = (bounds == SkIRect::MakeWH(image->width(), image->height())) ?
    129                 nullptr : &bounds;
    130 
    131         for (int iy = 0; iy < 2; ++iy) {
    132             for (int ix = 0; ix < 2; ++ix) {
    133                 int i = ix * 2 + iy;
    134                 SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
    135                                             size[i].width(), size[i].height());
    136                 canvas->drawBitmapLattice(bitmap, lattice, r);
    137             }
    138         }
    139 
    140         // Provide hints about 3 solid color rects. These colors match
    141         // what was already in the bitmap.
    142         int fixedColorX[3] = {2, 4, 1};
    143         int fixedColorY[3] = {1, 1, 2};
    144         SkColor fixedColor[3] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
    145         const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType,
    146                                                    kUnpremul_SkAlphaType);
    147         for (int rectNum = 0; rectNum < 3; rectNum++) {
    148             int srcX = xDivs[fixedColorX[rectNum]-1];
    149             int srcY = yDivs[fixedColorY[rectNum]-1];
    150             image->readPixels(info, &fixedColor[rectNum], 4, srcX, srcY);
    151         }
    152 
    153         // Include the degenerate first div.  While normally the first patch is "scalable",
    154         // this will mean that the first non-degenerate patch is "fixed".
    155         lattice.fXCount = 5;
    156         lattice.fXDivs = xDivs;
    157         lattice.fYCount = 5;
    158         lattice.fYDivs = yDivs;
    159 
    160         // Let's skip a few rects.
    161         SkCanvas::Lattice::RectType flags[36];
    162         sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::RectType));
    163         flags[4] = SkCanvas::Lattice::kTransparent;
    164         flags[9] = SkCanvas::Lattice::kTransparent;
    165         flags[12] = SkCanvas::Lattice::kTransparent;
    166         flags[19] = SkCanvas::Lattice::kTransparent;
    167         for (int rectNum = 0; rectNum < 3; rectNum++) {
    168             flags[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
    169                    = SkCanvas::Lattice::kFixedColor;
    170         }
    171         lattice.fRectTypes = flags;
    172 
    173         SkColor colors[36];
    174         sk_bzero(colors, 36 * sizeof(SkColor));
    175         for (int rectNum = 0; rectNum < 3; rectNum++) {
    176             colors[fixedColorY[rectNum]*6 + fixedColorX[rectNum]]
    177                    = fixedColor[rectNum];
    178         }
    179 
    180         lattice.fColors = colors;
    181 
    182         canvas->translate(400, 0);
    183         for (int iy = 0; iy < 2; ++iy) {
    184             for (int ix = 0; ix < 2; ++ix) {
    185                 int i = ix * 2 + iy;
    186                 SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
    187                                             size[i].width(), size[i].height());
    188                 canvas->drawImageLattice(image.get(), lattice, r);
    189             }
    190         }
    191 
    192         canvas->restore();
    193     }
    194 
    195     void onDraw(SkCanvas* canvas) override {
    196         this->onDrawHelper(canvas, 0, 0, 0, 0);
    197         canvas->translate(0.0f, 400.0f);
    198         this->onDrawHelper(canvas, 3, 7, 4, 11);
    199     }
    200 
    201 private:
    202     typedef skiagm::GM INHERITED;
    203 };
    204 DEF_GM( return new LatticeGM; )
    205 
    206 
    207 // LatticeGM2 exercises code paths that draw fixed color and 1x1 rectangles.
    208 class LatticeGM2 : public skiagm::GM {
    209 public:
    210     LatticeGM2() {}
    211     SkString onShortName() override {
    212         return SkString("lattice2");
    213     }
    214 
    215     SkISize onISize() override {
    216         return SkISize::Make(800, 800);
    217     }
    218 
    219     sk_sp<SkImage> makeImage(SkCanvas* root, int padLeft, int padTop, int padRight, int padBottom) {
    220         const int kSize = 80;
    221         auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
    222         SkCanvas* canvas = surface->getCanvas();;
    223         SkPaint paint;
    224         paint.setAntiAlias(false);
    225         SkRect r;
    226 
    227         //first line
    228         r.setXYWH(0, 0, 4, 1);  //4x1 green rect
    229         paint.setColor(0xFF00FF00);
    230         canvas->drawRect(r, paint);
    231 
    232         r.setXYWH(4, 0, 1, 1); //1x1 blue pixel -> draws as rectangle
    233         paint.setColor(0xFF0000FF);
    234         canvas->drawRect(r, paint);
    235 
    236         r.setXYWH(5, 0, kSize-5, 1); //the rest of the line is red
    237         paint.setColor(0xFFFF0000);
    238         canvas->drawRect(r, paint);
    239 
    240 
    241         //second line -> draws as fixed color rectangles
    242         r.setXYWH(0, 1, 4, 1);  //4x1 red rect
    243         paint.setColor(0xFFFF0000);
    244         canvas->drawRect(r, paint);
    245 
    246         r.setXYWH(4, 1, 1, 1); //1x1 blue pixel with alpha
    247         paint.setColor(0x880000FF);
    248         canvas->drawRect(r, paint);
    249 
    250         r.setXYWH(5, 1, kSize-5, 1); //the rest of the line is green
    251         paint.setColor(0xFF00FF00);
    252         canvas->drawRect(r, paint);
    253 
    254 
    255         //third line - does not draw, because it is transparent
    256         r.setXYWH(0, 2, 4, kSize-2);  //4x78 green rect
    257         paint.setColor(0xFF00FF00);
    258         canvas->drawRect(r, paint);
    259 
    260         r.setXYWH(4, 2, 1, kSize-2); //1x78 red pixel with alpha
    261         paint.setColor(0x88FF0000);
    262         canvas->drawRect(r, paint);
    263 
    264         r.setXYWH(5, 2, kSize-5, kSize-2); //the rest of the image is blue
    265         paint.setColor(0xFF0000FF);
    266         canvas->drawRect(r, paint);
    267 
    268         return surface->makeImageSnapshot();
    269     }
    270 
    271     void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom,
    272                       SkPaint& paint) {
    273         int xDivs[2] = {4, 5};
    274         int yDivs[2] = {1, 2};
    275 
    276         canvas->save();
    277 
    278         sk_sp<SkImage> image = makeImage(canvas, padLeft, padTop, padRight, padBottom);
    279 
    280         canvas->drawImage(image, 10, 10, nullptr);
    281 
    282         SkCanvas::Lattice lattice;
    283         lattice.fXCount = 2;
    284         lattice.fXDivs = xDivs;
    285         lattice.fYCount = 2;
    286         lattice.fYDivs = yDivs;
    287         lattice.fBounds = nullptr;
    288 
    289         SkCanvas::Lattice::RectType flags[9];
    290         sk_bzero(flags, 9 * sizeof(SkCanvas::Lattice::RectType));
    291         flags[3] = SkCanvas::Lattice::kFixedColor;
    292         flags[4] = SkCanvas::Lattice::kFixedColor;
    293         flags[5] = SkCanvas::Lattice::kFixedColor;
    294 
    295         flags[6] = SkCanvas::Lattice::kTransparent;
    296         flags[7] = SkCanvas::Lattice::kTransparent;
    297         flags[8] = SkCanvas::Lattice::kTransparent;
    298         lattice.fRectTypes = flags;
    299 
    300         SkColor colors[9] = {SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK,
    301                              0xFFFF0000, 0x880000FF, 0xFF00FF00,
    302                              SK_ColorBLACK, SK_ColorBLACK, SK_ColorBLACK};
    303         lattice.fColors = colors;
    304         paint.setColor(0xFFFFFFFF);
    305         canvas->drawImageLattice(image.get(), lattice,
    306                                  SkRect::MakeXYWH(100, 100, 200, 200), &paint);
    307 
    308         //draw the same content with alpha
    309         canvas->translate(400, 0);
    310         paint.setColor(0x80000FFF);
    311         canvas->drawImageLattice(image.get(), lattice,
    312                                  SkRect::MakeXYWH(100, 100, 200, 200), &paint);
    313 
    314         canvas->restore();
    315     }
    316 
    317     void onDraw(SkCanvas* canvas) override {
    318 
    319         //draw a rectangle in the background with transparent pixels
    320         SkPaint paint;
    321         paint.setColor(0x7F123456);
    322         paint.setBlendMode(SkBlendMode::kSrc);
    323         canvas->drawRect( SkRect::MakeXYWH(300, 0, 300, 800), paint);
    324 
    325         //draw image lattice with kSrcOver blending
    326         paint.setBlendMode(SkBlendMode::kSrcOver);
    327         this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
    328 
    329         //draw image lattice with kSrcATop blending
    330         canvas->translate(0.0f, 400.0f);
    331         paint.setBlendMode(SkBlendMode::kSrcATop);
    332         this->onDrawHelper(canvas, 0, 0, 0, 0, paint);
    333     }
    334 
    335 private:
    336     typedef skiagm::GM INHERITED;
    337 };
    338 DEF_GM( return new LatticeGM2; )
    339 
    340 
    341 
    342