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