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/SkFont.h" 14cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h" 15cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 16cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 17cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 18cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 19cb93a386Sopenharmony_ci#include "include/core/SkShader.h" 20cb93a386Sopenharmony_ci#include "include/core/SkSize.h" 21cb93a386Sopenharmony_ci#include "include/core/SkString.h" 22cb93a386Sopenharmony_ci#include "include/core/SkTileMode.h" 23cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 24cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 25cb93a386Sopenharmony_ci#include "include/utils/SkTextUtils.h" 26cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_cienum SrcType { 29cb93a386Sopenharmony_ci //! A WxH image with a rectangle in the lower right. 30cb93a386Sopenharmony_ci kRectangleImage_SrcType = 0x01, 31cb93a386Sopenharmony_ci //! kRectangleImage_SrcType with an alpha of 34.5%. 32cb93a386Sopenharmony_ci kRectangleImageWithAlpha_SrcType = 0x02, 33cb93a386Sopenharmony_ci //! kRectnagleImageWithAlpha_SrcType scaled down by half. 34cb93a386Sopenharmony_ci kSmallRectangleImageWithAlpha_SrcType = 0x04, 35cb93a386Sopenharmony_ci //! kRectangleImage_SrcType drawn directly instead in an image. 36cb93a386Sopenharmony_ci kRectangle_SrcType = 0x08, 37cb93a386Sopenharmony_ci //! Two rectangles, first on the right half, second on the bottom half. 38cb93a386Sopenharmony_ci kQuarterClear_SrcType = 0x10, 39cb93a386Sopenharmony_ci //! kQuarterClear_SrcType in a layer. 40cb93a386Sopenharmony_ci kQuarterClearInLayer_SrcType = 0x20, 41cb93a386Sopenharmony_ci //! A W/2xH/2 transparent image. 42cb93a386Sopenharmony_ci kSmallTransparentImage_SrcType = 0x40, 43cb93a386Sopenharmony_ci //! kRectangleImage_SrcType drawn directly with a mask. 44cb93a386Sopenharmony_ci kRectangleWithMask_SrcType = 0x80, 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci kAll_SrcType = 0xFF, //!< All the source types. 47cb93a386Sopenharmony_ci kBasic_SrcType = 0x03, //!< Just basic source types. 48cb93a386Sopenharmony_ci}; 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ciconst struct { 51cb93a386Sopenharmony_ci SkBlendMode fMode; 52cb93a386Sopenharmony_ci int fSourceTypeMask; // The source types to use this 53cb93a386Sopenharmony_ci // mode with. See draw_mode for 54cb93a386Sopenharmony_ci // an explanation of each type. 55cb93a386Sopenharmony_ci // PDF has to play some tricks 56cb93a386Sopenharmony_ci // to support the base modes, 57cb93a386Sopenharmony_ci // test those more extensively. 58cb93a386Sopenharmony_ci} gModes[] = { 59cb93a386Sopenharmony_ci { SkBlendMode::kClear, kAll_SrcType }, 60cb93a386Sopenharmony_ci { SkBlendMode::kSrc, kAll_SrcType }, 61cb93a386Sopenharmony_ci { SkBlendMode::kDst, kAll_SrcType }, 62cb93a386Sopenharmony_ci { SkBlendMode::kSrcOver, kAll_SrcType }, 63cb93a386Sopenharmony_ci { SkBlendMode::kDstOver, kAll_SrcType }, 64cb93a386Sopenharmony_ci { SkBlendMode::kSrcIn, kAll_SrcType }, 65cb93a386Sopenharmony_ci { SkBlendMode::kDstIn, kAll_SrcType }, 66cb93a386Sopenharmony_ci { SkBlendMode::kSrcOut, kAll_SrcType }, 67cb93a386Sopenharmony_ci { SkBlendMode::kDstOut, kAll_SrcType }, 68cb93a386Sopenharmony_ci { SkBlendMode::kSrcATop, kAll_SrcType }, 69cb93a386Sopenharmony_ci { SkBlendMode::kDstATop, kAll_SrcType }, 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci { SkBlendMode::kXor, kBasic_SrcType }, 72cb93a386Sopenharmony_ci { SkBlendMode::kPlus, kBasic_SrcType }, 73cb93a386Sopenharmony_ci { SkBlendMode::kModulate, kAll_SrcType }, 74cb93a386Sopenharmony_ci { SkBlendMode::kScreen, kBasic_SrcType }, 75cb93a386Sopenharmony_ci { SkBlendMode::kOverlay, kBasic_SrcType }, 76cb93a386Sopenharmony_ci { SkBlendMode::kDarken, kBasic_SrcType }, 77cb93a386Sopenharmony_ci { SkBlendMode::kLighten, kBasic_SrcType }, 78cb93a386Sopenharmony_ci { SkBlendMode::kColorDodge, kBasic_SrcType }, 79cb93a386Sopenharmony_ci { SkBlendMode::kColorBurn, kBasic_SrcType }, 80cb93a386Sopenharmony_ci { SkBlendMode::kHardLight, kBasic_SrcType }, 81cb93a386Sopenharmony_ci { SkBlendMode::kSoftLight, kBasic_SrcType }, 82cb93a386Sopenharmony_ci { SkBlendMode::kDifference, kBasic_SrcType }, 83cb93a386Sopenharmony_ci { SkBlendMode::kExclusion, kBasic_SrcType }, 84cb93a386Sopenharmony_ci { SkBlendMode::kMultiply, kAll_SrcType }, 85cb93a386Sopenharmony_ci { SkBlendMode::kHue, kBasic_SrcType }, 86cb93a386Sopenharmony_ci { SkBlendMode::kSaturation, kBasic_SrcType }, 87cb93a386Sopenharmony_ci { SkBlendMode::kColor, kBasic_SrcType }, 88cb93a386Sopenharmony_ci { SkBlendMode::kLuminosity, kBasic_SrcType }, 89cb93a386Sopenharmony_ci}; 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_cistatic void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst, 92cb93a386Sopenharmony_ci SkBitmap* transparent) { 93cb93a386Sopenharmony_ci src->allocN32Pixels(w, h); 94cb93a386Sopenharmony_ci src->eraseColor(SK_ColorTRANSPARENT); 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci SkPaint p; 97cb93a386Sopenharmony_ci p.setAntiAlias(true); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci SkRect r; 100cb93a386Sopenharmony_ci SkScalar ww = SkIntToScalar(w); 101cb93a386Sopenharmony_ci SkScalar hh = SkIntToScalar(h); 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci { 104cb93a386Sopenharmony_ci SkCanvas c(*src); 105cb93a386Sopenharmony_ci p.setColor(ToolUtils::color_to_565(0xFFFFCC44)); 106cb93a386Sopenharmony_ci r.setWH(ww*3/4, hh*3/4); 107cb93a386Sopenharmony_ci c.drawOval(r, p); 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci dst->allocN32Pixels(w, h); 111cb93a386Sopenharmony_ci dst->eraseColor(SK_ColorTRANSPARENT); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci { 114cb93a386Sopenharmony_ci SkCanvas c(*dst); 115cb93a386Sopenharmony_ci p.setColor(ToolUtils::color_to_565(0xFF66AAFF)); 116cb93a386Sopenharmony_ci r.setLTRB(ww/3, hh/3, ww*19/20, hh*19/20); 117cb93a386Sopenharmony_ci c.drawRect(r, p); 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci transparent->allocN32Pixels(w, h); 121cb93a386Sopenharmony_ci transparent->eraseColor(SK_ColorTRANSPARENT); 122cb93a386Sopenharmony_ci} 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_cistatic uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ciclass XfermodesGM : public skiagm::GM { 127cb93a386Sopenharmony_ci SkBitmap fBG; 128cb93a386Sopenharmony_ci SkBitmap fSrcB, fDstB, fTransparent; 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci /* The srcType argument indicates what to draw for the source part. Skia 131cb93a386Sopenharmony_ci * uses the implied shape of the drawing command and these modes 132cb93a386Sopenharmony_ci * demonstrate that. 133cb93a386Sopenharmony_ci */ 134cb93a386Sopenharmony_ci void draw_mode(SkCanvas* canvas, SkBlendMode mode, SrcType srcType, SkScalar x, SkScalar y) { 135cb93a386Sopenharmony_ci SkPaint p; 136cb93a386Sopenharmony_ci SkSamplingOptions sampling; 137cb93a386Sopenharmony_ci SkMatrix m; 138cb93a386Sopenharmony_ci bool restoreNeeded = false; 139cb93a386Sopenharmony_ci m.setTranslate(x, y); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci canvas->drawImage(fSrcB.asImage(), x, y, sampling, &p); 142cb93a386Sopenharmony_ci p.setBlendMode(mode); 143cb93a386Sopenharmony_ci switch (srcType) { 144cb93a386Sopenharmony_ci case kSmallTransparentImage_SrcType: { 145cb93a386Sopenharmony_ci m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci SkAutoCanvasRestore acr(canvas, true); 148cb93a386Sopenharmony_ci canvas->concat(m); 149cb93a386Sopenharmony_ci canvas->drawImage(fTransparent.asImage(), 0, 0, sampling, &p); 150cb93a386Sopenharmony_ci break; 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci case kQuarterClearInLayer_SrcType: { 153cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeXYWH(x, y, SkIntToScalar(W), 154cb93a386Sopenharmony_ci SkIntToScalar(H)); 155cb93a386Sopenharmony_ci canvas->saveLayer(&bounds, &p); 156cb93a386Sopenharmony_ci restoreNeeded = true; 157cb93a386Sopenharmony_ci p.setBlendMode(SkBlendMode::kSrcOver); 158cb93a386Sopenharmony_ci [[fallthrough]]; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci case kQuarterClear_SrcType: { 161cb93a386Sopenharmony_ci SkScalar halfW = SkIntToScalar(W) / 2; 162cb93a386Sopenharmony_ci SkScalar halfH = SkIntToScalar(H) / 2; 163cb93a386Sopenharmony_ci p.setColor(ToolUtils::color_to_565(0xFF66AAFF)); 164cb93a386Sopenharmony_ci SkRect r = SkRect::MakeXYWH(x + halfW, y, halfW, 165cb93a386Sopenharmony_ci SkIntToScalar(H)); 166cb93a386Sopenharmony_ci canvas->drawRect(r, p); 167cb93a386Sopenharmony_ci p.setColor(ToolUtils::color_to_565(0xFFAA66FF)); 168cb93a386Sopenharmony_ci r = SkRect::MakeXYWH(x, y + halfH, SkIntToScalar(W), halfH); 169cb93a386Sopenharmony_ci canvas->drawRect(r, p); 170cb93a386Sopenharmony_ci break; 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci case kRectangleWithMask_SrcType: { 173cb93a386Sopenharmony_ci canvas->save(); 174cb93a386Sopenharmony_ci restoreNeeded = true; 175cb93a386Sopenharmony_ci SkScalar w = SkIntToScalar(W); 176cb93a386Sopenharmony_ci SkScalar h = SkIntToScalar(H); 177cb93a386Sopenharmony_ci SkRect r = SkRect::MakeXYWH(x, y + h / 4, w, h * 23 / 60); 178cb93a386Sopenharmony_ci canvas->clipRect(r); 179cb93a386Sopenharmony_ci [[fallthrough]]; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci case kRectangle_SrcType: { 182cb93a386Sopenharmony_ci SkScalar w = SkIntToScalar(W); 183cb93a386Sopenharmony_ci SkScalar h = SkIntToScalar(H); 184cb93a386Sopenharmony_ci SkRect r = SkRect::MakeXYWH(x + w / 3, y + h / 3, 185cb93a386Sopenharmony_ci w * 37 / 60, h * 37 / 60); 186cb93a386Sopenharmony_ci p.setColor(ToolUtils::color_to_565(0xFF66AAFF)); 187cb93a386Sopenharmony_ci canvas->drawRect(r, p); 188cb93a386Sopenharmony_ci break; 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci case kSmallRectangleImageWithAlpha_SrcType: 191cb93a386Sopenharmony_ci m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y); 192cb93a386Sopenharmony_ci [[fallthrough]]; 193cb93a386Sopenharmony_ci case kRectangleImageWithAlpha_SrcType: 194cb93a386Sopenharmony_ci p.setAlpha(0x88); 195cb93a386Sopenharmony_ci [[fallthrough]]; 196cb93a386Sopenharmony_ci case kRectangleImage_SrcType: { 197cb93a386Sopenharmony_ci SkAutoCanvasRestore acr(canvas, true); 198cb93a386Sopenharmony_ci canvas->concat(m); 199cb93a386Sopenharmony_ci canvas->drawImage(fDstB.asImage(), 0, 0, sampling, &p); 200cb93a386Sopenharmony_ci break; 201cb93a386Sopenharmony_ci } 202cb93a386Sopenharmony_ci default: 203cb93a386Sopenharmony_ci break; 204cb93a386Sopenharmony_ci } 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci if (restoreNeeded) { 207cb93a386Sopenharmony_ci canvas->restore(); 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 212cb93a386Sopenharmony_ci fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType, 213cb93a386Sopenharmony_ci kOpaque_SkAlphaType), 214cb93a386Sopenharmony_ci gData, 4); 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci make_bitmaps(W, H, &fSrcB, &fDstB, &fTransparent); 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_cipublic: 220cb93a386Sopenharmony_ci const static int W = 64; 221cb93a386Sopenharmony_ci const static int H = 64; 222cb93a386Sopenharmony_ci XfermodesGM() {} 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ciprotected: 225cb93a386Sopenharmony_ci SkString onShortName() override { 226cb93a386Sopenharmony_ci return SkString("xfermodes"); 227cb93a386Sopenharmony_ci } 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ci SkISize onISize() override { 230cb93a386Sopenharmony_ci return SkISize::Make(1990, 570); 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci void onDraw(SkCanvas* canvas) override { 234cb93a386Sopenharmony_ci canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci const SkScalar w = SkIntToScalar(W); 237cb93a386Sopenharmony_ci const SkScalar h = SkIntToScalar(H); 238cb93a386Sopenharmony_ci SkMatrix m; 239cb93a386Sopenharmony_ci m.setScale(SkIntToScalar(6), SkIntToScalar(6)); 240cb93a386Sopenharmony_ci auto s = fBG.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, 241cb93a386Sopenharmony_ci SkSamplingOptions(), m); 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci SkPaint labelP; 244cb93a386Sopenharmony_ci labelP.setAntiAlias(true); 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci SkFont font(ToolUtils::create_portable_typeface()); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci const int kWrap = 5; 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci SkScalar x0 = 0; 251cb93a386Sopenharmony_ci SkScalar y0 = 0; 252cb93a386Sopenharmony_ci for (int sourceType = 1; sourceType & kAll_SrcType; sourceType <<= 1) { 253cb93a386Sopenharmony_ci SkScalar x = x0, y = y0; 254cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) { 255cb93a386Sopenharmony_ci if ((gModes[i].fSourceTypeMask & sourceType) == 0) { 256cb93a386Sopenharmony_ci continue; 257cb93a386Sopenharmony_ci } 258cb93a386Sopenharmony_ci SkRect r{ x, y, x+w, y+h }; 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci SkPaint p; 261cb93a386Sopenharmony_ci p.setStyle(SkPaint::kFill_Style); 262cb93a386Sopenharmony_ci p.setShader(s); 263cb93a386Sopenharmony_ci canvas->drawRect(r, p); 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_ci canvas->saveLayer(&r, nullptr); 266cb93a386Sopenharmony_ci draw_mode(canvas, gModes[i].fMode, static_cast<SrcType>(sourceType), 267cb93a386Sopenharmony_ci r.fLeft, r.fTop); 268cb93a386Sopenharmony_ci canvas->restore(); 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci r.inset(-SK_ScalarHalf, -SK_ScalarHalf); 271cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 272cb93a386Sopenharmony_ci p.setShader(nullptr); 273cb93a386Sopenharmony_ci canvas->drawRect(r, p); 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci#if 1 276cb93a386Sopenharmony_ci const char* label = SkBlendMode_Name(gModes[i].fMode); 277cb93a386Sopenharmony_ci SkTextUtils::DrawString(canvas, label, x + w/2, y - font.getSize()/2, 278cb93a386Sopenharmony_ci font, labelP, SkTextUtils::kCenter_Align); 279cb93a386Sopenharmony_ci#endif 280cb93a386Sopenharmony_ci x += w + SkIntToScalar(10); 281cb93a386Sopenharmony_ci if ((i % kWrap) == kWrap - 1) { 282cb93a386Sopenharmony_ci x = x0; 283cb93a386Sopenharmony_ci y += h + SkIntToScalar(30); 284cb93a386Sopenharmony_ci } 285cb93a386Sopenharmony_ci } 286cb93a386Sopenharmony_ci if (y < 320) { 287cb93a386Sopenharmony_ci if (x > x0) { 288cb93a386Sopenharmony_ci y += h + SkIntToScalar(30); 289cb93a386Sopenharmony_ci } 290cb93a386Sopenharmony_ci y0 = y; 291cb93a386Sopenharmony_ci } else { 292cb93a386Sopenharmony_ci x0 += SkIntToScalar(400); 293cb93a386Sopenharmony_ci y0 = 0; 294cb93a386Sopenharmony_ci } 295cb93a386Sopenharmony_ci } 296cb93a386Sopenharmony_ci } 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_ciprivate: 299cb93a386Sopenharmony_ci using INHERITED = GM; 300cb93a386Sopenharmony_ci}; 301cb93a386Sopenharmony_ciDEF_GM( return new XfermodesGM; ) 302