| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "gm/gm.h" |
| #include "include/core/SkBitmap.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkColor.h" |
| #include "include/core/SkImage.h" |
| #include "include/core/SkImageInfo.h" |
| #include "include/core/SkMatrix.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkPath.h" |
| #include "include/core/SkPoint.h" |
| #include "include/core/SkRect.h" |
| #include "include/core/SkRefCnt.h" |
| #include "include/core/SkScalar.h" |
| #include "include/core/SkShader.h" |
| #include "include/core/SkSize.h" |
| #include "include/core/SkString.h" |
| #include "include/core/SkSurface.h" |
| #include "include/core/SkTileMode.h" |
| #include "include/core/SkTypes.h" |
| #include "include/effects/SkGradientShader.h" |
| #include "tools/DecodeUtils.h" |
| #include "tools/ToolUtils.h" |
| |
| static sk_sp<SkImage> make_image(SkCanvas* origCanvas, int w, int h) { |
| SkImageInfo info = SkImageInfo::MakeN32Premul(w, h); |
| auto surface(ToolUtils::makeSurface(origCanvas, info)); |
| SkCanvas* canvas = surface->getCanvas(); |
| |
| ToolUtils::draw_checkerboard(canvas, SK_ColorRED, SK_ColorGREEN, w / 10); |
| return surface->makeImageSnapshot(); |
| } |
| |
| namespace skiagm { |
| |
| class PerspShadersGM : public GM { |
| public: |
| PerspShadersGM(bool doAA) : fDoAA(doAA) { } |
| |
| protected: |
| SkString getName() const override { |
| SkString name; |
| name.printf("persp_shaders_%s", |
| fDoAA ? "aa" : "bw"); |
| return name; |
| } |
| |
| SkISize getISize() override { |
| return SkISize::Make(kCellSize*kNumCols, kCellSize*kNumRows); |
| } |
| |
| void onOnceBeforeDraw() override { |
| fBitmapImage = ToolUtils::create_checkerboard_image( |
| kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10); |
| |
| SkPoint pts1[] = { |
| { 0, 0 }, |
| { SkIntToScalar(kCellSize), SkIntToScalar(kCellSize) } |
| }; |
| SkPoint pts2[] = { |
| { 0, 0 }, |
| { 0, SkIntToScalar(kCellSize) } |
| }; |
| constexpr SkColor colors[] = { |
| SK_ColorRED, SK_ColorGREEN, SK_ColorRED, SK_ColorGREEN, SK_ColorRED |
| }; |
| constexpr SkScalar pos[] = { 0, 0.25f, 0.5f, 0.75f, SK_Scalar1 }; |
| |
| fLinearGrad1 = SkGradientShader::MakeLinear(pts1, colors, pos, std::size(colors), |
| SkTileMode::kClamp); |
| fLinearGrad2 = SkGradientShader::MakeLinear(pts2, colors, pos, std::size(colors), |
| SkTileMode::kClamp); |
| |
| fPerspMatrix.reset(); |
| fPerspMatrix.setPerspY(SK_Scalar1 / 50); |
| |
| fPath.moveTo(0, 0); |
| fPath.lineTo(0, SkIntToScalar(kCellSize)); |
| fPath.lineTo(kCellSize/2.0f, kCellSize/2.0f); |
| fPath.lineTo(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize)); |
| fPath.lineTo(SkIntToScalar(kCellSize), 0); |
| fPath.close(); |
| } |
| |
| void drawRow(SkCanvas* canvas, const SkSamplingOptions& sampling) { |
| SkPaint filterPaint; |
| filterPaint.setAntiAlias(fDoAA); |
| |
| SkPaint pathPaint; |
| pathPaint.setShader(fBitmapImage->makeShader(sampling)); |
| pathPaint.setAntiAlias(fDoAA); |
| |
| SkPaint gradPaint1; |
| gradPaint1.setShader(fLinearGrad1); |
| gradPaint1.setAntiAlias(fDoAA); |
| SkPaint gradPaint2; |
| gradPaint2.setShader(fLinearGrad2); |
| gradPaint2.setAntiAlias(fDoAA); |
| |
| SkRect r = SkRect::MakeWH(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize)); |
| |
| canvas->save(); |
| |
| canvas->save(); |
| canvas->concat(fPerspMatrix); |
| canvas->drawImageRect(fBitmapImage, r, sampling, &filterPaint); |
| canvas->restore(); |
| |
| canvas->translate(SkIntToScalar(kCellSize), 0); |
| canvas->save(); |
| canvas->concat(fPerspMatrix); |
| canvas->drawImage(fImage.get(), 0, 0, sampling, &filterPaint); |
| canvas->restore(); |
| |
| canvas->translate(SkIntToScalar(kCellSize), 0); |
| canvas->save(); |
| canvas->concat(fPerspMatrix); |
| canvas->drawRect(r, pathPaint); |
| canvas->restore(); |
| |
| canvas->translate(SkIntToScalar(kCellSize), 0); |
| canvas->save(); |
| canvas->concat(fPerspMatrix); |
| canvas->drawPath(fPath, pathPaint); |
| canvas->restore(); |
| |
| canvas->translate(SkIntToScalar(kCellSize), 0); |
| canvas->save(); |
| canvas->concat(fPerspMatrix); |
| canvas->drawRect(r, gradPaint1); |
| canvas->restore(); |
| |
| canvas->translate(SkIntToScalar(kCellSize), 0); |
| canvas->save(); |
| canvas->concat(fPerspMatrix); |
| canvas->drawPath(fPath, gradPaint2); |
| canvas->restore(); |
| |
| canvas->restore(); |
| } |
| |
| void onDraw(SkCanvas* canvas) override { |
| if (!fImage || !fImage->isValid(canvas->recordingContext())) { |
| fImage = make_image(canvas, kCellSize, kCellSize); |
| } |
| |
| this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kNearest)); |
| canvas->translate(0, SkIntToScalar(kCellSize)); |
| this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear)); |
| canvas->translate(0, SkIntToScalar(kCellSize)); |
| this->drawRow(canvas, SkSamplingOptions(SkFilterMode::kLinear, |
| SkMipmapMode::kNearest)); |
| canvas->translate(0, SkIntToScalar(kCellSize)); |
| this->drawRow(canvas, SkSamplingOptions(SkCubicResampler::Mitchell())); |
| canvas->translate(0, SkIntToScalar(kCellSize)); |
| this->drawRow(canvas, SkSamplingOptions::Aniso(16)); |
| canvas->translate(0, SkIntToScalar(kCellSize)); |
| } |
| private: |
| inline static constexpr int kCellSize = 50; |
| inline static constexpr int kNumRows = 5; |
| inline static constexpr int kNumCols = 6; |
| |
| bool fDoAA; |
| SkPath fPath; |
| sk_sp<SkShader> fLinearGrad1; |
| sk_sp<SkShader> fLinearGrad2; |
| SkMatrix fPerspMatrix; |
| sk_sp<SkImage> fImage; |
| sk_sp<SkImage> fBitmapImage; |
| |
| using INHERITED = GM; |
| }; |
| DEF_GM(return new PerspShadersGM(true);) |
| DEF_GM(return new PerspShadersGM(false);) |
| } // namespace skiagm |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| #include "tools/Resources.h" |
| |
| static SkPath make_path() { |
| SkRandom rand; |
| auto rand_pt = [&rand]() { |
| auto x = rand.nextF(); |
| auto y = rand.nextF(); |
| return SkPoint{x * 400, y * 400}; |
| }; |
| |
| SkPath path; |
| for (int i = 0; i < 4; ++i) { |
| SkPoint pts[6]; |
| for (auto& p : pts) { |
| p = rand_pt(); |
| } |
| path.moveTo(pts[0]).quadTo(pts[1], pts[2]).quadTo(pts[3], pts[4]).lineTo(pts[5]); |
| } |
| return path; |
| } |
| |
| DEF_SIMPLE_GM(perspective_clip, canvas, 800, 800) { |
| SkPath path = make_path(); |
| auto shader = ToolUtils::GetResourceAsImage("images/mandrill_128.png") |
| ->makeShader(SkSamplingOptions(), SkMatrix::Scale(3, 3)); |
| |
| SkPaint paint; |
| paint.setColor({0.75, 0.75, 0.75, 1}); |
| canvas->drawPath(path, paint); |
| |
| // This is a crazy perspective matrix, derived from halfplanes3, to draw a shape where |
| // part of it is "behind" the viewer, hence showing the need for "half-plane" clipping |
| // when in perspective. |
| SkMatrix mx; |
| const SkScalar array[] = { |
| -1.7866f, 1.3357f, 273.0295f, |
| -1.0820f, 1.3186f, 135.5196f, |
| -0.0047f, -0.0015f, 2.1485f, |
| }; |
| mx.set9(array); |
| |
| paint.setShader(shader); |
| canvas->concat(mx); |
| canvas->drawPath(path, paint); |
| } |