|  | /* | 
|  | * 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/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 <utility> | 
|  |  | 
|  | static SkPath generate_square(SkScalar cx, SkScalar cy, SkScalar w) { | 
|  | SkRect rect = SkRect::MakeXYWH(cx - w / 2, cy - w / 2, w, w); | 
|  | SkPath path; | 
|  | path.addRect(rect); | 
|  | return path; | 
|  | } | 
|  |  | 
|  | static SkPath generate_rect_line(SkScalar cx, SkScalar cy, SkScalar l) { | 
|  | SkRect rect = SkRect::MakeXYWH(cx - l / 2, cy, l, 0); | 
|  | SkPath path; | 
|  | path.addRect(rect); | 
|  | return path; | 
|  | } | 
|  |  | 
|  | static SkPath generate_circle(SkScalar cx, SkScalar cy, SkScalar d) { | 
|  | SkPath path; | 
|  | path.addCircle(cx, cy, d/2, SkPath::kCW_Direction); | 
|  | return path; | 
|  | } | 
|  |  | 
|  | static SkPath generate_line(SkScalar cx, SkScalar cy, SkScalar l) { | 
|  | SkPath path; | 
|  | path.moveTo(cx - l / 2, cy); | 
|  | path.lineTo(cx + l / 2, cy); | 
|  | return path; | 
|  | } | 
|  |  | 
|  | 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, 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(SkPath::kInverseWinding_FillType); | 
|  | canvas->drawPath(path, paint); | 
|  |  | 
|  | path.setFillType(SkPath::kWinding_FillType); | 
|  | canvas->drawPath(path, outlinePaint); | 
|  |  | 
|  | canvas->restore(); | 
|  | canvas->translate(dx, 0); | 
|  | } | 
|  | } | 
|  | canvas->restore(); | 
|  | canvas->translate(0, dy); | 
|  | } | 
|  | } | 
|  | } |