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 
     11 static sk_sp<SkSurface> make_surface(SkCanvas* root, int N, int padLeft, int padTop,
     12                                      int padRight, int padBottom) {
     13     SkImageInfo info = SkImageInfo::MakeN32Premul(N + padLeft + padRight, N + padTop + padBottom);
     14     auto surface = root->makeSurface(info);
     15     if (!surface) {
     16         surface = SkSurface::MakeRaster(info);
     17     }
     18 
     19     return surface;
     20 }
     21 
     22 static sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs, int padLeft, int padTop,
     23                                  int padRight, int padBottom) {
     24     const int kCap = 28;
     25     const int kMid = 8;
     26     const int kSize = 2*kCap + 3*kMid;
     27 
     28     auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom));
     29     SkCanvas* canvas = surface->getCanvas();
     30     canvas->translate((float) padLeft, (float) padTop);
     31 
     32     SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
     33     const SkScalar strokeWidth = SkIntToScalar(6);
     34     const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2;
     35 
     36     xDivs[0] = kCap + padLeft;
     37     yDivs[0] = kCap + padTop;
     38     xDivs[1] = kCap + kMid + padLeft;
     39     yDivs[1] = kCap + kMid + padTop;
     40     xDivs[2] = kCap + 2 * kMid + padLeft;
     41     yDivs[2] = kCap + 2 * kMid + padTop;
     42     xDivs[3] = kCap + 3 * kMid + padLeft;
     43     yDivs[3] = kCap + 3 * kMid + padTop;
     44 
     45     SkPaint paint;
     46     paint.setAntiAlias(true);
     47 
     48     paint.setColor(0xFFFFFF00);
     49     canvas->drawRoundRect(r, radius, radius, paint);
     50 
     51     r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
     52     paint.setColor(0x8800FF00);
     53     canvas->drawRect(r, paint);
     54     r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
     55     paint.setColor(0x880000FF);
     56     canvas->drawRect(r, paint);
     57     r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize));
     58     paint.setColor(0x88FF00FF);
     59     canvas->drawRect(r, paint);
     60 
     61     r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid));
     62     paint.setColor(0x8800FF00);
     63     canvas->drawRect(r, paint);
     64     r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
     65     paint.setColor(0x880000FF);
     66     canvas->drawRect(r, paint);
     67     r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid));
     68     paint.setColor(0x88FF00FF);
     69     canvas->drawRect(r, paint);
     70 
     71     return surface->makeImageSnapshot();
     72 }
     73 
     74 static void image_to_bitmap(const SkImage* image, SkBitmap* bm) {
     75     SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height());
     76     bm->allocPixels(info);
     77     image->readPixels(info, bm->getPixels(), bm->rowBytes(), 0, 0);
     78 }
     79 
     80 /**
     81  *  This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more
     82  *  than nine patches.
     83  */
     84 class LatticeGM : public skiagm::GM {
     85 public:
     86     LatticeGM() {}
     87 
     88 protected:
     89     SkString onShortName() override {
     90         return SkString("lattice");
     91     }
     92 
     93     SkISize onISize() override {
     94         return SkISize::Make(800, 800);
     95     }
     96 
     97     void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom) {
     98         canvas->save();
     99 
    100         int xDivs[5];
    101         int yDivs[5];
    102         xDivs[0] = padLeft;
    103         yDivs[0] = padTop;
    104 
    105         SkBitmap bitmap;
    106         sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop,
    107                                           padRight, padBottom);
    108         image_to_bitmap(image.get(), &bitmap);
    109 
    110         const SkSize size[] = {
    111             {  50,  50, }, // shrink in both axes
    112             {  50, 200, }, // shrink in X
    113             { 200,  50, }, // shrink in Y
    114             { 200, 200, },
    115         };
    116 
    117         canvas->drawImage(image, 10, 10, nullptr);
    118 
    119         SkScalar x = SkIntToScalar(100);
    120         SkScalar y = SkIntToScalar(100);
    121 
    122         SkCanvas::Lattice lattice;
    123         lattice.fXCount = 4;
    124         lattice.fXDivs = xDivs + 1;
    125         lattice.fYCount = 4;
    126         lattice.fYDivs = yDivs + 1;
    127         lattice.fFlags = nullptr;
    128 
    129         SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop,
    130                                            image->width() - padRight, image->height() - padBottom);
    131         lattice.fBounds = (bounds == SkIRect::MakeWH(image->width(), image->height())) ?
    132                 nullptr : &bounds;
    133 
    134         for (int iy = 0; iy < 2; ++iy) {
    135             for (int ix = 0; ix < 2; ++ix) {
    136                 int i = ix * 2 + iy;
    137                 SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
    138                                             size[i].width(), size[i].height());
    139                 canvas->drawBitmapLattice(bitmap, lattice, r);
    140             }
    141         }
    142 
    143         // Include the degenerate first div.  While normally the first patch is "scalable",
    144         // this will mean that the first non-degenerate patch is "fixed".
    145         lattice.fXCount = 5;
    146         lattice.fXDivs = xDivs;
    147         lattice.fYCount = 5;
    148         lattice.fYDivs = yDivs;
    149 
    150         // Let's skip a few rects.
    151         SkCanvas::Lattice::Flags flags[36];
    152         sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::Flags));
    153         flags[4] = SkCanvas::Lattice::kTransparent_Flags;
    154         flags[9] = SkCanvas::Lattice::kTransparent_Flags;
    155         flags[12] = SkCanvas::Lattice::kTransparent_Flags;
    156         flags[19] = SkCanvas::Lattice::kTransparent_Flags;
    157         lattice.fFlags = flags;
    158 
    159         canvas->translate(400, 0);
    160         for (int iy = 0; iy < 2; ++iy) {
    161             for (int ix = 0; ix < 2; ++ix) {
    162                 int i = ix * 2 + iy;
    163                 SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60,
    164                                             size[i].width(), size[i].height());
    165                 canvas->drawImageLattice(image.get(), lattice, r);
    166             }
    167         }
    168 
    169         canvas->restore();
    170     }
    171 
    172     void onDraw(SkCanvas* canvas) override {
    173         this->onDrawHelper(canvas, 0, 0, 0, 0);
    174         canvas->translate(0.0f, 400.0f);
    175         this->onDrawHelper(canvas, 3, 7, 4, 11);
    176     }
    177 
    178 private:
    179     typedef skiagm::GM INHERITED;
    180 };
    181 DEF_GM( return new LatticeGM; )
    182