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