1c573a40ed5024b463e47088d307e3164a486dba5msarett/* 2c573a40ed5024b463e47088d307e3164a486dba5msarett * Copyright 2016 Google Inc. 3c573a40ed5024b463e47088d307e3164a486dba5msarett * 4c573a40ed5024b463e47088d307e3164a486dba5msarett * Use of this source code is governed by a BSD-style license that can be 5c573a40ed5024b463e47088d307e3164a486dba5msarett * found in the LICENSE file. 6c573a40ed5024b463e47088d307e3164a486dba5msarett */ 7c573a40ed5024b463e47088d307e3164a486dba5msarett 8c573a40ed5024b463e47088d307e3164a486dba5msarett#include "gm.h" 9c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkSurface.h" 10c573a40ed5024b463e47088d307e3164a486dba5msarett 1171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarettstatic sk_sp<SkSurface> make_surface(SkCanvas* root, int N, int padLeft, int padTop, 1271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int padRight, int padBottom) { 1371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett SkImageInfo info = SkImageInfo::MakeN32Premul(N + padLeft + padRight, N + padTop + padBottom); 14c573a40ed5024b463e47088d307e3164a486dba5msarett auto surface = root->makeSurface(info); 15c573a40ed5024b463e47088d307e3164a486dba5msarett if (!surface) { 16c573a40ed5024b463e47088d307e3164a486dba5msarett surface = SkSurface::MakeRaster(info); 17c573a40ed5024b463e47088d307e3164a486dba5msarett } 1871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett 19c573a40ed5024b463e47088d307e3164a486dba5msarett return surface; 20c573a40ed5024b463e47088d307e3164a486dba5msarett} 21c573a40ed5024b463e47088d307e3164a486dba5msarett 2271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarettstatic sk_sp<SkImage> make_image(SkCanvas* root, int* xDivs, int* yDivs, int padLeft, int padTop, 2371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett int padRight, int padBottom) { 24c573a40ed5024b463e47088d307e3164a486dba5msarett const int kCap = 28; 25c573a40ed5024b463e47088d307e3164a486dba5msarett const int kMid = 8; 26c573a40ed5024b463e47088d307e3164a486dba5msarett const int kSize = 2*kCap + 3*kMid; 27c573a40ed5024b463e47088d307e3164a486dba5msarett 2871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett auto surface(make_surface(root, kSize, padLeft, padTop, padRight, padBottom)); 29c573a40ed5024b463e47088d307e3164a486dba5msarett SkCanvas* canvas = surface->getCanvas(); 3071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett canvas->translate((float) padLeft, (float) padTop); 31c573a40ed5024b463e47088d307e3164a486dba5msarett 32c573a40ed5024b463e47088d307e3164a486dba5msarett SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize)); 33c573a40ed5024b463e47088d307e3164a486dba5msarett const SkScalar strokeWidth = SkIntToScalar(6); 34c573a40ed5024b463e47088d307e3164a486dba5msarett const SkScalar radius = SkIntToScalar(kCap) - strokeWidth/2; 35c573a40ed5024b463e47088d307e3164a486dba5msarett 3671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett xDivs[0] = kCap + padLeft; 3771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett yDivs[0] = kCap + padTop; 3871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett xDivs[1] = kCap + kMid + padLeft; 3971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett yDivs[1] = kCap + kMid + padTop; 4071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett xDivs[2] = kCap + 2 * kMid + padLeft; 4171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett yDivs[2] = kCap + 2 * kMid + padTop; 4271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett xDivs[3] = kCap + 3 * kMid + padLeft; 4371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett yDivs[3] = kCap + 3 * kMid + padTop; 44c573a40ed5024b463e47088d307e3164a486dba5msarett 45c573a40ed5024b463e47088d307e3164a486dba5msarett SkPaint paint; 46c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setAntiAlias(true); 47c573a40ed5024b463e47088d307e3164a486dba5msarett 48c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0xFFFFFF00); 49c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRoundRect(r, radius, radius, paint); 50c573a40ed5024b463e47088d307e3164a486dba5msarett 51c573a40ed5024b463e47088d307e3164a486dba5msarett r.setXYWH(SkIntToScalar(kCap), 0, SkIntToScalar(kMid), SkIntToScalar(kSize)); 52c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0x8800FF00); 53c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRect(r, paint); 54c573a40ed5024b463e47088d307e3164a486dba5msarett r.setXYWH(SkIntToScalar(kCap + kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize)); 55c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0x880000FF); 56c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRect(r, paint); 57c573a40ed5024b463e47088d307e3164a486dba5msarett r.setXYWH(SkIntToScalar(kCap + 2*kMid), 0, SkIntToScalar(kMid), SkIntToScalar(kSize)); 58c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0x88FF00FF); 59c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRect(r, paint); 60c573a40ed5024b463e47088d307e3164a486dba5msarett 61c573a40ed5024b463e47088d307e3164a486dba5msarett r.setXYWH(0, SkIntToScalar(kCap), SkIntToScalar(kSize), SkIntToScalar(kMid)); 62c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0x8800FF00); 63c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRect(r, paint); 64c573a40ed5024b463e47088d307e3164a486dba5msarett r.setXYWH(0, SkIntToScalar(kCap + kMid), SkIntToScalar(kSize), SkIntToScalar(kMid)); 65c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0x880000FF); 66c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRect(r, paint); 67c573a40ed5024b463e47088d307e3164a486dba5msarett r.setXYWH(0, SkIntToScalar(kCap + 2*kMid), SkIntToScalar(kSize), SkIntToScalar(kMid)); 68c573a40ed5024b463e47088d307e3164a486dba5msarett paint.setColor(0x88FF00FF); 69c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawRect(r, paint); 70c573a40ed5024b463e47088d307e3164a486dba5msarett 71c573a40ed5024b463e47088d307e3164a486dba5msarett return surface->makeImageSnapshot(); 72c573a40ed5024b463e47088d307e3164a486dba5msarett} 73c573a40ed5024b463e47088d307e3164a486dba5msarett 74c573a40ed5024b463e47088d307e3164a486dba5msarettstatic void image_to_bitmap(const SkImage* image, SkBitmap* bm) { 75c573a40ed5024b463e47088d307e3164a486dba5msarett SkImageInfo info = SkImageInfo::MakeN32Premul(image->width(), image->height()); 76c573a40ed5024b463e47088d307e3164a486dba5msarett bm->allocPixels(info); 77c573a40ed5024b463e47088d307e3164a486dba5msarett image->readPixels(info, bm->getPixels(), bm->rowBytes(), 0, 0); 78c573a40ed5024b463e47088d307e3164a486dba5msarett} 79c573a40ed5024b463e47088d307e3164a486dba5msarett 80c573a40ed5024b463e47088d307e3164a486dba5msarett/** 81c573a40ed5024b463e47088d307e3164a486dba5msarett * This is similar to NinePatchStretchGM, but it also tests "ninepatch" images with more 82c573a40ed5024b463e47088d307e3164a486dba5msarett * than nine patches. 83c573a40ed5024b463e47088d307e3164a486dba5msarett */ 84c573a40ed5024b463e47088d307e3164a486dba5msarettclass LatticeGM : public skiagm::GM { 85c573a40ed5024b463e47088d307e3164a486dba5msarettpublic: 86c573a40ed5024b463e47088d307e3164a486dba5msarett LatticeGM() {} 87c573a40ed5024b463e47088d307e3164a486dba5msarett 88c573a40ed5024b463e47088d307e3164a486dba5msarettprotected: 89c573a40ed5024b463e47088d307e3164a486dba5msarett SkString onShortName() override { 90c573a40ed5024b463e47088d307e3164a486dba5msarett return SkString("lattice"); 91c573a40ed5024b463e47088d307e3164a486dba5msarett } 92c573a40ed5024b463e47088d307e3164a486dba5msarett 93c573a40ed5024b463e47088d307e3164a486dba5msarett SkISize onISize() override { 9471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett return SkISize::Make(800, 800); 95c573a40ed5024b463e47088d307e3164a486dba5msarett } 96c573a40ed5024b463e47088d307e3164a486dba5msarett 9771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett void onDrawHelper(SkCanvas* canvas, int padLeft, int padTop, int padRight, int padBottom) { 9871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett canvas->save(); 9971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett 100c573a40ed5024b463e47088d307e3164a486dba5msarett int xDivs[5]; 101c573a40ed5024b463e47088d307e3164a486dba5msarett int yDivs[5]; 10271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett xDivs[0] = padLeft; 10371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett yDivs[0] = padTop; 104c573a40ed5024b463e47088d307e3164a486dba5msarett 105c573a40ed5024b463e47088d307e3164a486dba5msarett SkBitmap bitmap; 10671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett sk_sp<SkImage> image = make_image(canvas, xDivs + 1, yDivs + 1, padLeft, padTop, 10771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett padRight, padBottom); 108c573a40ed5024b463e47088d307e3164a486dba5msarett image_to_bitmap(image.get(), &bitmap); 109c573a40ed5024b463e47088d307e3164a486dba5msarett 110c573a40ed5024b463e47088d307e3164a486dba5msarett const SkTSize<SkScalar> size[] = { 111c573a40ed5024b463e47088d307e3164a486dba5msarett { 50, 50, }, // shrink in both axes 112c573a40ed5024b463e47088d307e3164a486dba5msarett { 50, 200, }, // shrink in X 113c573a40ed5024b463e47088d307e3164a486dba5msarett { 200, 50, }, // shrink in Y 114c573a40ed5024b463e47088d307e3164a486dba5msarett { 200, 200, }, 115c573a40ed5024b463e47088d307e3164a486dba5msarett }; 116c573a40ed5024b463e47088d307e3164a486dba5msarett 117c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawImage(image, 10, 10, nullptr); 118c573a40ed5024b463e47088d307e3164a486dba5msarett 119c573a40ed5024b463e47088d307e3164a486dba5msarett SkScalar x = SkIntToScalar(100); 120c573a40ed5024b463e47088d307e3164a486dba5msarett SkScalar y = SkIntToScalar(100); 121c573a40ed5024b463e47088d307e3164a486dba5msarett 122c573a40ed5024b463e47088d307e3164a486dba5msarett SkCanvas::Lattice lattice; 123c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fXCount = 4; 124c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fXDivs = xDivs + 1; 125c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fYCount = 4; 126c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fYDivs = yDivs + 1; 1270764efe6a9ae65ad83992f614f57ca9db5b1f191msarett lattice.fFlags = nullptr; 128c573a40ed5024b463e47088d307e3164a486dba5msarett 12971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett SkIRect bounds = SkIRect::MakeLTRB(padLeft, padTop, 13071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett image->width() - padRight, image->height() - padBottom); 13171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett lattice.fBounds = (bounds == SkIRect::MakeWH(image->width(), image->height())) ? 13271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett nullptr : &bounds; 13371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett 134c573a40ed5024b463e47088d307e3164a486dba5msarett for (int iy = 0; iy < 2; ++iy) { 135c573a40ed5024b463e47088d307e3164a486dba5msarett for (int ix = 0; ix < 2; ++ix) { 136c573a40ed5024b463e47088d307e3164a486dba5msarett int i = ix * 2 + iy; 137c573a40ed5024b463e47088d307e3164a486dba5msarett SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60, 138c573a40ed5024b463e47088d307e3164a486dba5msarett size[i].width(), size[i].height()); 139c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawBitmapLattice(bitmap, lattice, r); 140c573a40ed5024b463e47088d307e3164a486dba5msarett } 141c573a40ed5024b463e47088d307e3164a486dba5msarett } 142c573a40ed5024b463e47088d307e3164a486dba5msarett 143c573a40ed5024b463e47088d307e3164a486dba5msarett // Include the degenerate first div. While normally the first patch is "scalable", 144c573a40ed5024b463e47088d307e3164a486dba5msarett // this will mean that the first non-degenerate patch is "fixed". 145c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fXCount = 5; 146c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fXDivs = xDivs; 147c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fYCount = 5; 148c573a40ed5024b463e47088d307e3164a486dba5msarett lattice.fYDivs = yDivs; 149c573a40ed5024b463e47088d307e3164a486dba5msarett 1500764efe6a9ae65ad83992f614f57ca9db5b1f191msarett // Let's skip a few rects. 1510764efe6a9ae65ad83992f614f57ca9db5b1f191msarett SkCanvas::Lattice::Flags flags[36]; 1520764efe6a9ae65ad83992f614f57ca9db5b1f191msarett sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::Flags)); 1530764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags[4] = SkCanvas::Lattice::kTransparent_Flags; 1540764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags[9] = SkCanvas::Lattice::kTransparent_Flags; 1550764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags[12] = SkCanvas::Lattice::kTransparent_Flags; 1560764efe6a9ae65ad83992f614f57ca9db5b1f191msarett flags[19] = SkCanvas::Lattice::kTransparent_Flags; 1570764efe6a9ae65ad83992f614f57ca9db5b1f191msarett lattice.fFlags = flags; 1580764efe6a9ae65ad83992f614f57ca9db5b1f191msarett 159c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->translate(400, 0); 160c573a40ed5024b463e47088d307e3164a486dba5msarett for (int iy = 0; iy < 2; ++iy) { 161c573a40ed5024b463e47088d307e3164a486dba5msarett for (int ix = 0; ix < 2; ++ix) { 162c573a40ed5024b463e47088d307e3164a486dba5msarett int i = ix * 2 + iy; 163c573a40ed5024b463e47088d307e3164a486dba5msarett SkRect r = SkRect::MakeXYWH(x + ix * 60, y + iy * 60, 164c573a40ed5024b463e47088d307e3164a486dba5msarett size[i].width(), size[i].height()); 165c573a40ed5024b463e47088d307e3164a486dba5msarett canvas->drawImageLattice(image.get(), lattice, r); 166c573a40ed5024b463e47088d307e3164a486dba5msarett } 167c573a40ed5024b463e47088d307e3164a486dba5msarett } 16871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett 16971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett canvas->restore(); 17071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett } 17171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett 17271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett void onDraw(SkCanvas* canvas) override { 17371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett this->onDrawHelper(canvas, 0, 0, 0, 0); 17471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett canvas->translate(0.0f, 400.0f); 17571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett this->onDrawHelper(canvas, 3, 7, 4, 11); 176c573a40ed5024b463e47088d307e3164a486dba5msarett } 177c573a40ed5024b463e47088d307e3164a486dba5msarett 178c573a40ed5024b463e47088d307e3164a486dba5msarettprivate: 179c573a40ed5024b463e47088d307e3164a486dba5msarett typedef skiagm::GM INHERITED; 180c573a40ed5024b463e47088d307e3164a486dba5msarett}; 181c573a40ed5024b463e47088d307e3164a486dba5msarettDEF_GM( return new LatticeGM; ) 182