1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 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/SkCanvas.h" 11cb93a386Sopenharmony_ci#include "include/core/SkClipOp.h" 12cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 13cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 14cb93a386Sopenharmony_ci#include "include/core/SkFontTypes.h" 15cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 16cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 17cb93a386Sopenharmony_ci#include "include/core/SkPathBuilder.h" 18cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 19cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 20cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 21cb93a386Sopenharmony_ci#include "include/core/SkShader.h" 22cb93a386Sopenharmony_ci#include "include/core/SkSize.h" 23cb93a386Sopenharmony_ci#include "include/core/SkString.h" 24cb93a386Sopenharmony_ci#include "include/core/SkTileMode.h" 25cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 26cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 27cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h" 28cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_cistatic sk_sp<SkImage> make_img(int w, int h) { 31cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRaster(SkImageInfo::MakeN32(w, h, kOpaque_SkAlphaType)); 32cb93a386Sopenharmony_ci auto canvas = surf->getCanvas(); 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci SkScalar wScalar = SkIntToScalar(w); 35cb93a386Sopenharmony_ci SkScalar hScalar = SkIntToScalar(h); 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci SkPoint pt = { wScalar / 2, hScalar / 2 }; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci SkScalar radius = 3 * std::max(wScalar, hScalar); 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci SkColor colors[] = {SK_ColorDKGRAY, 42cb93a386Sopenharmony_ci ToolUtils::color_to_565(0xFF222255), 43cb93a386Sopenharmony_ci ToolUtils::color_to_565(0xFF331133), 44cb93a386Sopenharmony_ci ToolUtils::color_to_565(0xFF884422), 45cb93a386Sopenharmony_ci ToolUtils::color_to_565(0xFF000022), 46cb93a386Sopenharmony_ci SK_ColorWHITE, 47cb93a386Sopenharmony_ci ToolUtils::color_to_565(0xFFAABBCC)}; 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci SkScalar pos[] = {0, 50cb93a386Sopenharmony_ci SK_Scalar1 / 6, 51cb93a386Sopenharmony_ci 2 * SK_Scalar1 / 6, 52cb93a386Sopenharmony_ci 3 * SK_Scalar1 / 6, 53cb93a386Sopenharmony_ci 4 * SK_Scalar1 / 6, 54cb93a386Sopenharmony_ci 5 * SK_Scalar1 / 6, 55cb93a386Sopenharmony_ci SK_Scalar1}; 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci SkPaint paint; 58cb93a386Sopenharmony_ci SkRect rect = SkRect::MakeWH(wScalar, hScalar); 59cb93a386Sopenharmony_ci SkMatrix mat = SkMatrix::I(); 60cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 61cb93a386Sopenharmony_ci paint.setShader(SkGradientShader::MakeRadial( 62cb93a386Sopenharmony_ci pt, radius, 63cb93a386Sopenharmony_ci colors, pos, 64cb93a386Sopenharmony_ci SK_ARRAY_COUNT(colors), 65cb93a386Sopenharmony_ci SkTileMode::kRepeat, 66cb93a386Sopenharmony_ci 0, &mat)); 67cb93a386Sopenharmony_ci canvas->drawRect(rect, paint); 68cb93a386Sopenharmony_ci rect.inset(wScalar / 8, hScalar / 8); 69cb93a386Sopenharmony_ci mat.preTranslate(6 * wScalar, 6 * hScalar); 70cb93a386Sopenharmony_ci mat.postScale(SK_Scalar1 / 3, SK_Scalar1 / 3); 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci SkFont font(ToolUtils::create_portable_typeface(), wScalar / 2.2f); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci paint.setShader(nullptr); 76cb93a386Sopenharmony_ci paint.setColor(SK_ColorLTGRAY); 77cb93a386Sopenharmony_ci constexpr char kTxt[] = "Skia"; 78cb93a386Sopenharmony_ci SkPoint texPos = { wScalar / 17, hScalar / 2 + font.getSize() / 2.5f }; 79cb93a386Sopenharmony_ci canvas->drawSimpleText(kTxt, SK_ARRAY_COUNT(kTxt)-1, SkTextEncoding::kUTF8, 80cb93a386Sopenharmony_ci texPos.fX, texPos.fY, font, paint); 81cb93a386Sopenharmony_ci paint.setColor(SK_ColorBLACK); 82cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 83cb93a386Sopenharmony_ci paint.setStrokeWidth(SK_Scalar1); 84cb93a386Sopenharmony_ci canvas->drawSimpleText(kTxt, SK_ARRAY_COUNT(kTxt)-1, SkTextEncoding::kUTF8, 85cb93a386Sopenharmony_ci texPos.fX, texPos.fY, font, paint); 86cb93a386Sopenharmony_ci return surf->makeImageSnapshot(); 87cb93a386Sopenharmony_ci} 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_cinamespace skiagm { 90cb93a386Sopenharmony_ci/** 91cb93a386Sopenharmony_ci * This GM tests convex polygon clips. 92cb93a386Sopenharmony_ci */ 93cb93a386Sopenharmony_ciclass ConvexPolyClip : public GM { 94cb93a386Sopenharmony_cipublic: 95cb93a386Sopenharmony_ci ConvexPolyClip() { 96cb93a386Sopenharmony_ci this->setBGColor(0xFFFFFFFF); 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ciprotected: 100cb93a386Sopenharmony_ci SkString onShortName() override { 101cb93a386Sopenharmony_ci return SkString("convex_poly_clip"); 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci SkISize onISize() override { 105cb93a386Sopenharmony_ci // When benchmarking the saveLayer set of draws is skipped. 106cb93a386Sopenharmony_ci int w = 435; 107cb93a386Sopenharmony_ci if (kBench_Mode != this->getMode()) { 108cb93a386Sopenharmony_ci w *= 2; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci return SkISize::Make(w, 540); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 114cb93a386Sopenharmony_ci // On < c++17, emplace_back() returns a void :( 115cb93a386Sopenharmony_ci auto emplace_back = [](std::vector<Clip>& clips) -> Clip& { 116cb93a386Sopenharmony_ci clips.emplace_back(); 117cb93a386Sopenharmony_ci return clips.back(); 118cb93a386Sopenharmony_ci }; 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci emplace_back(fClips).setPath(SkPath::Polygon({ 121cb93a386Sopenharmony_ci { 5.f, 5.f}, 122cb93a386Sopenharmony_ci {100.f, 20.f}, 123cb93a386Sopenharmony_ci { 15.f, 100.f}, 124cb93a386Sopenharmony_ci }, false)); 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci SkPathBuilder hexagon; 127cb93a386Sopenharmony_ci constexpr SkScalar kRadius = 45.f; 128cb93a386Sopenharmony_ci const SkPoint center = { kRadius, kRadius }; 129cb93a386Sopenharmony_ci for (int i = 0; i < 6; ++i) { 130cb93a386Sopenharmony_ci SkScalar angle = 2 * SK_ScalarPI * i / 6; 131cb93a386Sopenharmony_ci SkPoint point = { SkScalarCos(angle), SkScalarSin(angle) }; 132cb93a386Sopenharmony_ci point.scale(kRadius); 133cb93a386Sopenharmony_ci point = center + point; 134cb93a386Sopenharmony_ci if (0 == i) { 135cb93a386Sopenharmony_ci hexagon.moveTo(point); 136cb93a386Sopenharmony_ci } else { 137cb93a386Sopenharmony_ci hexagon.lineTo(point); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci emplace_back(fClips).setPath(hexagon.snapshot()); 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci SkMatrix scaleM; 143cb93a386Sopenharmony_ci scaleM.setScale(1.1f, 0.4f, kRadius, kRadius); 144cb93a386Sopenharmony_ci emplace_back(fClips).setPath(hexagon.detach().makeTransform(scaleM)); 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci emplace_back(fClips).setRect(SkRect::MakeXYWH(8.3f, 11.6f, 78.2f, 72.6f)); 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci SkRect rect = SkRect::MakeLTRB(10.f, 12.f, 80.f, 86.f); 149cb93a386Sopenharmony_ci SkMatrix rotM; 150cb93a386Sopenharmony_ci rotM.setRotate(23.f, rect.centerX(), rect.centerY()); 151cb93a386Sopenharmony_ci emplace_back(fClips).setPath(SkPath::Rect(rect).makeTransform(rotM)); 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci fImg = make_img(100, 100); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci void onDraw(SkCanvas* canvas) override { 157cb93a386Sopenharmony_ci SkScalar y = 0; 158cb93a386Sopenharmony_ci constexpr SkScalar kMargin = 10.f; 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci SkPaint bgPaint; 161cb93a386Sopenharmony_ci bgPaint.setAlpha(0x15); 162cb93a386Sopenharmony_ci SkISize size = canvas->getBaseLayerSize(); 163cb93a386Sopenharmony_ci canvas->drawImageRect(fImg, SkRect::MakeIWH(size.fWidth, size.fHeight), 164cb93a386Sopenharmony_ci SkSamplingOptions(), &bgPaint); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci constexpr char kTxt[] = "Clip Me!"; 167cb93a386Sopenharmony_ci SkFont font(ToolUtils::create_portable_typeface(), 23); 168cb93a386Sopenharmony_ci SkScalar textW = font.measureText(kTxt, SK_ARRAY_COUNT(kTxt)-1, SkTextEncoding::kUTF8); 169cb93a386Sopenharmony_ci SkPaint txtPaint; 170cb93a386Sopenharmony_ci txtPaint.setColor(SK_ColorDKGRAY); 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci SkScalar startX = 0; 173cb93a386Sopenharmony_ci int testLayers = kBench_Mode != this->getMode(); 174cb93a386Sopenharmony_ci for (int doLayer = 0; doLayer <= testLayers; ++doLayer) { 175cb93a386Sopenharmony_ci for (const Clip& clip : fClips) { 176cb93a386Sopenharmony_ci SkScalar x = startX; 177cb93a386Sopenharmony_ci for (int aa = 0; aa < 2; ++aa) { 178cb93a386Sopenharmony_ci if (doLayer) { 179cb93a386Sopenharmony_ci SkRect bounds; 180cb93a386Sopenharmony_ci clip.getBounds(&bounds); 181cb93a386Sopenharmony_ci bounds.outset(2, 2); 182cb93a386Sopenharmony_ci bounds.offset(x, y); 183cb93a386Sopenharmony_ci canvas->saveLayer(&bounds, nullptr); 184cb93a386Sopenharmony_ci } else { 185cb93a386Sopenharmony_ci canvas->save(); 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci canvas->translate(x, y); 188cb93a386Sopenharmony_ci clip.setOnCanvas(canvas, SkClipOp::kIntersect, SkToBool(aa)); 189cb93a386Sopenharmony_ci canvas->drawImage(fImg, 0, 0); 190cb93a386Sopenharmony_ci canvas->restore(); 191cb93a386Sopenharmony_ci x += fImg->width() + kMargin; 192cb93a386Sopenharmony_ci } 193cb93a386Sopenharmony_ci for (int aa = 0; aa < 2; ++aa) { 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci SkPaint clipOutlinePaint; 196cb93a386Sopenharmony_ci clipOutlinePaint.setAntiAlias(true); 197cb93a386Sopenharmony_ci clipOutlinePaint.setColor(0x50505050); 198cb93a386Sopenharmony_ci clipOutlinePaint.setStyle(SkPaint::kStroke_Style); 199cb93a386Sopenharmony_ci clipOutlinePaint.setStrokeWidth(0); 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci if (doLayer) { 202cb93a386Sopenharmony_ci SkRect bounds; 203cb93a386Sopenharmony_ci clip.getBounds(&bounds); 204cb93a386Sopenharmony_ci bounds.outset(2, 2); 205cb93a386Sopenharmony_ci bounds.offset(x, y); 206cb93a386Sopenharmony_ci canvas->saveLayer(&bounds, nullptr); 207cb93a386Sopenharmony_ci } else { 208cb93a386Sopenharmony_ci canvas->save(); 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci canvas->translate(x, y); 211cb93a386Sopenharmony_ci SkPath closedClipPath = clip.asClosedPath(); 212cb93a386Sopenharmony_ci canvas->drawPath(closedClipPath, clipOutlinePaint); 213cb93a386Sopenharmony_ci clip.setOnCanvas(canvas, SkClipOp::kIntersect, SkToBool(aa)); 214cb93a386Sopenharmony_ci canvas->scale(1.f, 1.8f); 215cb93a386Sopenharmony_ci canvas->drawSimpleText(kTxt, SK_ARRAY_COUNT(kTxt)-1, SkTextEncoding::kUTF8, 216cb93a386Sopenharmony_ci 0, 1.5f * font.getSize(), font, txtPaint); 217cb93a386Sopenharmony_ci canvas->restore(); 218cb93a386Sopenharmony_ci x += textW + 2 * kMargin; 219cb93a386Sopenharmony_ci } 220cb93a386Sopenharmony_ci y += fImg->height() + kMargin; 221cb93a386Sopenharmony_ci } 222cb93a386Sopenharmony_ci y = 0; 223cb93a386Sopenharmony_ci startX += 2 * fImg->width() + SkScalarCeilToInt(2 * textW) + 6 * kMargin; 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci bool runAsBench() const override { return true; } 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ciprivate: 230cb93a386Sopenharmony_ci class Clip { 231cb93a386Sopenharmony_ci public: 232cb93a386Sopenharmony_ci enum ClipType { 233cb93a386Sopenharmony_ci kNone_ClipType, 234cb93a386Sopenharmony_ci kPath_ClipType, 235cb93a386Sopenharmony_ci kRect_ClipType 236cb93a386Sopenharmony_ci }; 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci Clip () : fClipType(kNone_ClipType) {} 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ci void setOnCanvas(SkCanvas* canvas, SkClipOp op, bool aa) const { 241cb93a386Sopenharmony_ci switch (fClipType) { 242cb93a386Sopenharmony_ci case kPath_ClipType: 243cb93a386Sopenharmony_ci canvas->clipPath(fPathBuilder.snapshot(), op, aa); 244cb93a386Sopenharmony_ci break; 245cb93a386Sopenharmony_ci case kRect_ClipType: 246cb93a386Sopenharmony_ci canvas->clipRect(fRect, op, aa); 247cb93a386Sopenharmony_ci break; 248cb93a386Sopenharmony_ci case kNone_ClipType: 249cb93a386Sopenharmony_ci SkDEBUGFAIL("Uninitialized Clip."); 250cb93a386Sopenharmony_ci break; 251cb93a386Sopenharmony_ci } 252cb93a386Sopenharmony_ci } 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci SkPath asClosedPath() const { 255cb93a386Sopenharmony_ci switch (fClipType) { 256cb93a386Sopenharmony_ci case kPath_ClipType: 257cb93a386Sopenharmony_ci return SkPathBuilder(fPathBuilder).close().detach(); 258cb93a386Sopenharmony_ci break; 259cb93a386Sopenharmony_ci case kRect_ClipType: 260cb93a386Sopenharmony_ci return SkPath::Rect(fRect); 261cb93a386Sopenharmony_ci case kNone_ClipType: 262cb93a386Sopenharmony_ci SkDEBUGFAIL("Uninitialized Clip."); 263cb93a386Sopenharmony_ci break; 264cb93a386Sopenharmony_ci } 265cb93a386Sopenharmony_ci return SkPath(); 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci void setPath(const SkPath& path) { 269cb93a386Sopenharmony_ci fClipType = kPath_ClipType; 270cb93a386Sopenharmony_ci fPathBuilder = path; 271cb93a386Sopenharmony_ci } 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci void setRect(const SkRect& rect) { 274cb93a386Sopenharmony_ci fClipType = kRect_ClipType; 275cb93a386Sopenharmony_ci fRect = rect; 276cb93a386Sopenharmony_ci fPathBuilder.reset(); 277cb93a386Sopenharmony_ci } 278cb93a386Sopenharmony_ci 279cb93a386Sopenharmony_ci ClipType getType() const { return fClipType; } 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ci void getBounds(SkRect* bounds) const { 282cb93a386Sopenharmony_ci switch (fClipType) { 283cb93a386Sopenharmony_ci case kPath_ClipType: 284cb93a386Sopenharmony_ci *bounds = fPathBuilder.computeBounds(); 285cb93a386Sopenharmony_ci break; 286cb93a386Sopenharmony_ci case kRect_ClipType: 287cb93a386Sopenharmony_ci *bounds = fRect; 288cb93a386Sopenharmony_ci break; 289cb93a386Sopenharmony_ci case kNone_ClipType: 290cb93a386Sopenharmony_ci SkDEBUGFAIL("Uninitialized Clip."); 291cb93a386Sopenharmony_ci break; 292cb93a386Sopenharmony_ci } 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci private: 296cb93a386Sopenharmony_ci ClipType fClipType; 297cb93a386Sopenharmony_ci SkPathBuilder fPathBuilder; 298cb93a386Sopenharmony_ci SkRect fRect; 299cb93a386Sopenharmony_ci }; 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_ci std::vector<Clip> fClips; 302cb93a386Sopenharmony_ci sk_sp<SkImage> fImg;; 303cb93a386Sopenharmony_ci 304cb93a386Sopenharmony_ci using INHERITED = GM; 305cb93a386Sopenharmony_ci}; 306cb93a386Sopenharmony_ci 307cb93a386Sopenharmony_ciDEF_GM(return new ConvexPolyClip;) 308cb93a386Sopenharmony_ci} // namespace skiagm 309