| /* | |
| * 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/SkBlurTypes.h" | |
| #include "include/core/SkCanvas.h" | |
| #include "include/core/SkMaskFilter.h" | |
| #include "include/core/SkPaint.h" | |
| #include "include/core/SkPath.h" | |
| #include "include/core/SkPathBuilder.h" | |
| #include "include/core/SkPathEffect.h" | |
| #include "include/core/SkRect.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkScalar.h" | |
| #include "include/core/SkTypes.h" | |
| #include "include/effects/SkDashPathEffect.h" | |
| #include "include/effects/SkImageFilters.h" | |
| #include <array> | |
| #include <utility> | |
| static SkPath generate_square(SkScalar cx, SkScalar cy, SkScalar w) { | |
| return SkPath::Rect(SkRect::MakeXYWH(cx - w / 2, cy - w / 2, w, w)); | |
| } | |
| static SkPath generate_rect_line(SkScalar cx, SkScalar cy, SkScalar l) { | |
| return SkPath::Rect(SkRect::MakeXYWH(cx - l / 2, cy, l, 0)); | |
| } | |
| static SkPath generate_circle(SkScalar cx, SkScalar cy, SkScalar d) { | |
| return SkPath::Circle(cx, cy, d/2, SkPathDirection::kCW); | |
| } | |
| static SkPath generate_line(SkScalar cx, SkScalar cy, SkScalar l) { | |
| return SkPath::Line({cx - l / 2, cy}, {cx + l / 2, cy}); | |
| } | |
| namespace { | |
| struct Style { | |
| Style(SkPaint::Style paintStyle, sk_sp<SkPathEffect> pe = sk_sp<SkPathEffect>()) | |
| : fPaintStyle(paintStyle) | |
| , fPathEffect(std::move(pe)) {} | |
| SkPaint::Style fPaintStyle; | |
| sk_sp<SkPathEffect> fPathEffect; | |
| }; | |
| sk_sp<SkPathEffect> make_dash() { | |
| constexpr SkScalar kIntervals[] = { 4.f, 3.f }; | |
| return SkDashPathEffect::Make(kIntervals, 0); | |
| } | |
| auto styles = std::to_array<Style>({ | |
| Style{SkPaint::kStroke_Style}, | |
| Style{SkPaint::kStrokeAndFill_Style}, | |
| Style{SkPaint::kFill_Style}, | |
| Style{SkPaint::kStroke_Style, make_dash()}, | |
| }); | |
| auto pathSizes = std::to_array<SkScalar>({40, 10, 0}); | |
| auto strokeWidths = std::to_array<SkScalar>({10, 0}); | |
| auto paths = std::to_array<SkPath (*)(SkScalar, SkScalar, SkScalar)>({ | |
| generate_square, | |
| generate_rect_line, | |
| generate_circle, | |
| generate_line, | |
| }); | |
| const SkScalar slideWidth = 90, slideHeight = 90; | |
| const SkScalar slideBoundary = 5; | |
| } // namespace | |
| DEF_SIMPLE_GM(inverse_paths, canvas, 800, 1200) { | |
| SkScalar cx = slideWidth / 2 + slideBoundary; | |
| SkScalar cy = slideHeight / 2 + slideBoundary; | |
| SkScalar dx = slideWidth + 2 * slideBoundary; | |
| SkScalar dy = slideHeight + 2 * slideBoundary; | |
| SkRect clipRect = SkRect::MakeLTRB(slideBoundary, slideBoundary, | |
| slideBoundary + slideWidth, | |
| slideBoundary + slideHeight); | |
| SkPaint clipPaint; | |
| clipPaint.setStyle(SkPaint::kStroke_Style); | |
| clipPaint.setStrokeWidth(SkIntToScalar(2)); | |
| SkPaint outlinePaint; | |
| outlinePaint.setColor(0x40000000); | |
| outlinePaint.setStyle(SkPaint::kStroke_Style); | |
| outlinePaint.setStrokeWidth(SkIntToScalar(0)); | |
| for (size_t styleIndex = 0; styleIndex < std::size(styles); | |
| styleIndex++) { | |
| for (size_t sizeIndex = 0; sizeIndex < std::size(pathSizes); | |
| sizeIndex++) { | |
| SkScalar size = pathSizes[sizeIndex]; | |
| canvas->save(); | |
| for (size_t widthIndex = 0; | |
| widthIndex < std::size(strokeWidths); | |
| widthIndex++) { | |
| SkPaint paint; | |
| paint.setColor(0xff007000); | |
| paint.setStrokeWidth(strokeWidths[widthIndex]); | |
| paint.setStyle(styles[styleIndex].fPaintStyle); | |
| paint.setPathEffect(styles[styleIndex].fPathEffect); | |
| for (size_t pathIndex = 0; | |
| pathIndex < std::size(paths); | |
| pathIndex++) { | |
| canvas->drawRect(clipRect, clipPaint); | |
| canvas->save(); | |
| canvas->clipRect(clipRect); | |
| SkPath path = paths[pathIndex](cx, cy, size); | |
| path.setFillType(SkPathFillType::kInverseWinding); | |
| canvas->drawPath(path, paint); | |
| path.setFillType(SkPathFillType::kWinding); | |
| canvas->drawPath(path, outlinePaint); | |
| canvas->restore(); | |
| canvas->translate(dx, 0); | |
| } | |
| } | |
| canvas->restore(); | |
| canvas->translate(0, dy); | |
| } | |
| } | |
| } | |
| DEF_SIMPLE_GM(inverse_fill_filters, canvas, 384, 128) { | |
| auto draw = [canvas](const SkPaint& paint) { | |
| SkPath path = SkPath::Circle(65.f, 65.f, 30.f); | |
| path.setFillType(SkPathFillType::kInverseWinding); | |
| canvas->save(); | |
| canvas->clipRect({0, 0, 128, 128}); | |
| canvas->drawPath(path, paint); | |
| canvas->restore(); | |
| SkPaint stroke; | |
| stroke.setStyle(SkPaint::kStroke_Style); | |
| stroke.setColor(SK_ColorWHITE); | |
| canvas->drawRect({0, 0, 128, 128}, stroke); | |
| }; | |
| SkPaint paint; | |
| paint.setAntiAlias(true); | |
| draw(paint); | |
| canvas->translate(128, 0); | |
| paint.setImageFilter(SkImageFilters::Blur(5.f, 5.f, nullptr)); | |
| draw(paint); | |
| canvas->translate(128, 0); | |
| paint.setImageFilter(nullptr); | |
| paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5)); | |
| draw(paint); | |
| } | |
| DEF_SIMPLE_GM(inverse_windingmode_filters, canvas, 256, 100) { | |
| SkPath path = SkPathBuilder() | |
| .addRect({10, 10, 30, 30}, SkPathDirection::kCW) | |
| .addRect({20, 20, 40, 40}, SkPathDirection::kCW) | |
| .addRect({10, 60, 30, 80}, SkPathDirection::kCW) | |
| .addRect({20, 70, 40, 90}, SkPathDirection::kCCW) | |
| .detach(); | |
| SkPaint strokePaint; | |
| strokePaint.setStyle(SkPaint::kStroke_Style); | |
| SkRect clipRect = {0, 0, 51, 99}; | |
| canvas->drawPath(path, strokePaint); | |
| SkPaint fillPaint; | |
| fillPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 1.0f)); | |
| for (auto fillType : { SkPathFillType::kWinding, | |
| SkPathFillType::kEvenOdd, | |
| SkPathFillType::kInverseWinding, | |
| SkPathFillType::kInverseEvenOdd } ) { | |
| canvas->translate(51, 0); | |
| canvas->save(); | |
| canvas->clipRect(clipRect); | |
| path.setFillType(fillType); | |
| canvas->drawPath(path, fillPaint); | |
| canvas->restore(); | |
| SkPaint clipPaint; | |
| clipPaint.setColor(SK_ColorRED); | |
| clipPaint.setStyle(SkPaint::kStroke_Style); | |
| clipPaint.setStrokeWidth(1.f); | |
| canvas->drawRect(clipRect, clipPaint); | |
| } | |
| } |