| /* |
| * 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 "tools/fonts/FontToolUtils.h" |
| |
| #include <utility> |
| |
| #define WIDTH 600 |
| #define HEIGHT 100 |
| #define MARGIN 12 |
| |
| class OffsetImageFilterGM : public skiagm::GM { |
| public: |
| OffsetImageFilterGM() { |
| this->setBGColor(0xFF000000); |
| } |
| |
| protected: |
| SkString getName() const override { return SkString("offsetimagefilter"); } |
| |
| SkISize getISize() override { return SkISize::Make(WIDTH, HEIGHT); } |
| |
| void onOnceBeforeDraw() override { |
| fBitmap = ToolUtils::CreateStringImage(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<SkImage> image = (i & 0x01) ? fCheckerboard : fBitmap; |
| SkIRect cropRect = SkIRect::MakeXYWH(i * 12, |
| i * 8, |
| image->width() - i * 8, |
| image->height() - i * 12); |
| sk_sp<SkImageFilter> tileInput(SkImageFilters::Image(image, SkFilterMode::kNearest)); |
| 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, SkSamplingOptions(), &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<SkImage> fBitmap, fCheckerboard; |
| |
| using INHERITED = skiagm::GM; |
| }; |
| DEF_GM( return new OffsetImageFilterGM; ) |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| class SimpleOffsetImageFilterGM : public skiagm::GM { |
| public: |
| SimpleOffsetImageFilterGM() {} |
| |
| protected: |
| SkString getName() const override { return SkString("simple-offsetimagefilter"); } |
| |
| SkISize getISize() override { return SkISize::Make(640, 200); } |
| |
| void doDraw(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imgf, |
| const SkIRect* cropR = nullptr, 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 && cropR) { |
| p.setColor(0x66FF00FF); |
| p.setStyle(SkPaint::kStroke_Style); |
| |
| SkRect cr = SkRect::Make(*cropR).makeInset(SK_ScalarHalf, SK_ScalarHalf); |
| canvas->drawRect(cr, 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), &cr0); |
| |
| canvas->translate(100, 0); |
| this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr), /* cropR */ nullptr, &r); |
| |
| canvas->translate(100, 0); |
| this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr, &cr1), &cr1); |
| |
| SkRect clipR = SkRect::MakeXYWH(40, 40, 40, 40); |
| canvas->translate(100, 0); |
| this->doDraw(canvas, r, SkImageFilters::Offset(20, 20, nullptr), /* cropR */ 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), &cr0, &r); |
| |
| // crop==src, clip==dst |
| canvas->translate(100, 0); |
| this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr0), &cr0, &r2); |
| |
| // crop==dst, clip==src |
| canvas->translate(100, 0); |
| this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr2), &cr2, &r); |
| |
| // crop==clip==dst |
| canvas->translate(100, 0); |
| this->doDraw(canvas, r, SkImageFilters::Offset(40, 0, nullptr, &cr2), &cr2, &r2); |
| } |
| |
| private: |
| using INHERITED = skiagm::GM; |
| }; |
| DEF_GM( return new SimpleOffsetImageFilterGM; ) |