/* * 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/SkCanvas.h" #include "include/core/SkMaskFilter.h" #include "include/core/SkPaint.h" #include "include/core/SkPath.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 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 pe = sk_sp()) : fPaintStyle(paintStyle) , fPathEffect(std::move(pe)) {} SkPaint::Style fPaintStyle; sk_sp fPathEffect; }; sk_sp make_dash() { constexpr SkScalar kIntervals[] = { 4.f, 3.f }; return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), 0); } Style styles[] { {SkPaint::kStroke_Style}, {SkPaint::kStrokeAndFill_Style}, {SkPaint::kFill_Style}, {SkPaint::kStroke_Style, make_dash()}, }; SkScalar pathSizes[] = { 40, 10, 0 }; SkScalar strokeWidths[] = { 10, 0 }; SkPath (*paths[])(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 < SK_ARRAY_COUNT(styles); styleIndex++) { for (size_t sizeIndex = 0; sizeIndex < SK_ARRAY_COUNT(pathSizes); sizeIndex++) { SkScalar size = pathSizes[sizeIndex]; canvas->save(); for (size_t widthIndex = 0; widthIndex < SK_ARRAY_COUNT(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 < SK_ARRAY_COUNT(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; path.addRect({10, 10, 30, 30}, SkPathDirection::kCW); path.addRect({20, 20, 40, 40}, SkPathDirection::kCW); path.addRect({10, 60, 30, 80}, SkPathDirection::kCW); path.addRect({20, 70, 40, 90}, SkPathDirection::kCCW); 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); } }