/* * Copyright 2013 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/SkImageFilter.h" #include "include/core/SkMatrix.h" #include "include/core/SkPaint.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" #include "include/core/SkScalar.h" #include "include/core/SkSize.h" #include "include/core/SkString.h" #include "include/effects/SkImageFilters.h" #include "src/core/SkImageFilter_Base.h" #include "tools/ToolUtils.h" #include #define WIDTH 600 #define HEIGHT 100 #define MARGIN 12 class OffsetImageFilterGM : public skiagm::GM { public: OffsetImageFilterGM() { this->setBGColor(0xFF000000); } protected: SkString onShortName() override { return SkString("offsetimagefilter"); } SkISize onISize() override { return SkISize::Make(WIDTH, HEIGHT); } void onOnceBeforeDraw() override { fBitmap = ToolUtils::create_string_image(80, 80, 0xD000D000, 15, 65, 96, "e"); fCheckerboard = ToolUtils::create_checkerboard_image(80, 80, 0xFFA0A0A0, 0xFF404040, 8); } void onDraw(SkCanvas* canvas) override { canvas->clear(SK_ColorBLACK); SkPaint paint; for (int i = 0; i < 4; i++) { sk_sp image = (i & 0x01) ? fCheckerboard : fBitmap; SkIRect cropRect = SkIRect::MakeXYWH(i * 12, i * 8, image->width() - i * 8, image->height() - i * 12); sk_sp tileInput(SkImageFilters::Image(image)); SkScalar dx = SkIntToScalar(i*5); SkScalar dy = SkIntToScalar(i*10); paint.setImageFilter(SkImageFilters::Offset(dx, dy, std::move(tileInput), &cropRect)); DrawClippedImage(canvas, image.get(), paint, 1, cropRect); canvas->translate(SkIntToScalar(image->width() + MARGIN), 0); } SkIRect cropRect = SkIRect::MakeXYWH(0, 0, 100, 100); paint.setImageFilter(SkImageFilters::Offset(-5, -10, nullptr, &cropRect)); DrawClippedImage(canvas, fBitmap.get(), paint, 2, cropRect); } private: static void DrawClippedImage(SkCanvas* canvas, const SkImage* image, const SkPaint& paint, SkScalar scale, const SkIRect& cropRect) { SkRect clipRect = SkRect::MakeIWH(image->width(), image->height()); canvas->save(); canvas->clipRect(clipRect); canvas->scale(scale, scale); canvas->drawImage(image, 0, 0, &paint); canvas->restore(); // Draw a boundary rect around the intersection of the clip rect and crop rect. SkRect cropRectFloat; SkMatrix::Scale(scale, scale).mapRect(&cropRectFloat, SkRect::Make(cropRect)); if (clipRect.intersect(cropRectFloat)) { SkPaint strokePaint; strokePaint.setStyle(SkPaint::kStroke_Style); strokePaint.setStrokeWidth(2); strokePaint.setColor(SK_ColorRED); canvas->drawRect(clipRect, strokePaint); } } sk_sp fBitmap, fCheckerboard; using INHERITED = skiagm::GM; }; DEF_GM( return new OffsetImageFilterGM; ) ////////////////////////////////////////////////////////////////////////////// class SimpleOffsetImageFilterGM : public skiagm::GM { public: SimpleOffsetImageFilterGM() {} protected: SkString onShortName() override { return SkString("simple-offsetimagefilter"); } SkISize onISize() override { return SkISize::Make(640, 200); } void doDraw(SkCanvas* canvas, const SkRect& r, sk_sp imgf, const SkRect* clipR = nullptr) { SkPaint p; if (clipR) { p.setColor(0xFF00FF00); p.setStyle(SkPaint::kStroke_Style); canvas->drawRect(clipR->makeInset(SK_ScalarHalf, SK_ScalarHalf), p); p.setStyle(SkPaint::kFill_Style); } // Visualize the crop rect for debugging if (imgf && as_IFB(imgf)->cropRectIsSet()) { SkImageFilter::CropRect cr = as_IFB(imgf)->getCropRect(); p.setColor(0x66FF00FF); p.setStyle(SkPaint::kStroke_Style); canvas->drawRect(cr.rect().makeInset(SK_ScalarHalf, SK_ScalarHalf), p); p.setStyle(SkPaint::kFill_Style); } p.setColor(0x660000FF); canvas->drawRect(r, p); if (clipR) { canvas->save(); canvas->clipRect(*clipR); } if (imgf) { p.setImageFilter(std::move(imgf)); } p.setColor(0x66FF0000); canvas->drawRect(r, p); if (clipR) { canvas->restore(); } } void onDraw(SkCanvas* canvas) override { SkIRect cr0 = SkIRect::MakeWH(40, 40); SkIRect cr1 = SkIRect::MakeWH(20, 20); SkIRect cr2 = SkIRect::MakeXYWH(40, 0, 40, 40); const SkRect r = SkRect::Make(cr0); const SkRect r2 = SkRect::Make(cr2); canvas->translate(40, 40); canvas->save(); this->doDraw(canvas, r, nullptr); canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr)); canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr, &cr0)); canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr), &r); canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr, &cr1)); SkRect clipR = SkRect::MakeXYWH(40, 40, 40, 40); canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr, nullptr), &clipR); canvas->restore(); // 2nd row canvas->translate(0, 80); /* * combos of clip and crop rects that align with src and dst */ // crop==clip==src this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr0), &r); // crop==src, clip==dst canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr0), &r2); // crop==dst, clip==src canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr2), &r); // crop==clip==dst canvas->translate(100, 0); this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr2), &r2); } private: using INHERITED = skiagm::GM; }; DEF_GM( return new SimpleOffsetImageFilterGM; )