1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "gm/gm.h" 9#include "include/core/SkCanvas.h" 10#include "include/core/SkPaint.h" 11#include "include/core/SkPath.h" 12#include "include/core/SkPathEffect.h" 13#include "include/core/SkRect.h" 14#include "include/core/SkRefCnt.h" 15#include "include/core/SkScalar.h" 16#include "include/core/SkTypes.h" 17#include "include/effects/SkDashPathEffect.h" 18 19#include <utility> 20 21static SkPath generate_square(SkScalar cx, SkScalar cy, SkScalar w) { 22 return SkPath::Rect(SkRect::MakeXYWH(cx - w / 2, cy - w / 2, w, w)); 23} 24 25static SkPath generate_rect_line(SkScalar cx, SkScalar cy, SkScalar l) { 26 return SkPath::Rect(SkRect::MakeXYWH(cx - l / 2, cy, l, 0)); 27} 28 29static SkPath generate_circle(SkScalar cx, SkScalar cy, SkScalar d) { 30 return SkPath::Circle(cx, cy, d/2, SkPathDirection::kCW); 31} 32 33static SkPath generate_line(SkScalar cx, SkScalar cy, SkScalar l) { 34 return SkPath::Line({cx - l / 2, cy}, {cx + l / 2, cy}); 35} 36 37namespace { 38struct Style { 39 Style(SkPaint::Style paintStyle, sk_sp<SkPathEffect> pe = sk_sp<SkPathEffect>()) 40 : fPaintStyle(paintStyle) 41 , fPathEffect(std::move(pe)) {} 42 SkPaint::Style fPaintStyle; 43 sk_sp<SkPathEffect> fPathEffect; 44}; 45 46sk_sp<SkPathEffect> make_dash() { 47 constexpr SkScalar kIntervals[] = { 4.f, 3.f }; 48 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), 0); 49} 50 51Style styles[] { 52 {SkPaint::kStroke_Style}, 53 {SkPaint::kStrokeAndFill_Style}, 54 {SkPaint::kFill_Style}, 55 {SkPaint::kStroke_Style, make_dash()}, 56}; 57 58SkScalar pathSizes[] = { 59 40, 60 10, 61 0 62}; 63SkScalar strokeWidths[] = { 64 10, 65 0 66}; 67SkPath (*paths[])(SkScalar, SkScalar, SkScalar) = { 68 generate_square, 69 generate_rect_line, 70 generate_circle, 71 generate_line 72}; 73 74const SkScalar slideWidth = 90, slideHeight = 90; 75const SkScalar slideBoundary = 5; 76 77} // namespace 78 79DEF_SIMPLE_GM(inverse_paths, canvas, 800, 1200) { 80 SkScalar cx = slideWidth / 2 + slideBoundary; 81 SkScalar cy = slideHeight / 2 + slideBoundary; 82 SkScalar dx = slideWidth + 2 * slideBoundary; 83 SkScalar dy = slideHeight + 2 * slideBoundary; 84 85 SkRect clipRect = SkRect::MakeLTRB(slideBoundary, slideBoundary, 86 slideBoundary + slideWidth, 87 slideBoundary + slideHeight); 88 SkPaint clipPaint; 89 clipPaint.setStyle(SkPaint::kStroke_Style); 90 clipPaint.setStrokeWidth(SkIntToScalar(2)); 91 92 SkPaint outlinePaint; 93 outlinePaint.setColor(0x40000000); 94 outlinePaint.setStyle(SkPaint::kStroke_Style); 95 outlinePaint.setStrokeWidth(SkIntToScalar(0)); 96 97 for (size_t styleIndex = 0; styleIndex < SK_ARRAY_COUNT(styles); 98 styleIndex++) { 99 for (size_t sizeIndex = 0; sizeIndex < SK_ARRAY_COUNT(pathSizes); 100 sizeIndex++) { 101 SkScalar size = pathSizes[sizeIndex]; 102 103 canvas->save(); 104 105 for (size_t widthIndex = 0; 106 widthIndex < SK_ARRAY_COUNT(strokeWidths); 107 widthIndex++) { 108 SkPaint paint; 109 paint.setColor(0xff007000); 110 paint.setStrokeWidth(strokeWidths[widthIndex]); 111 paint.setStyle(styles[styleIndex].fPaintStyle); 112 paint.setPathEffect(styles[styleIndex].fPathEffect); 113 114 for (size_t pathIndex = 0; 115 pathIndex < SK_ARRAY_COUNT(paths); 116 pathIndex++) { 117 canvas->drawRect(clipRect, clipPaint); 118 119 canvas->save(); 120 canvas->clipRect(clipRect); 121 122 SkPath path = paths[pathIndex](cx, cy, size); 123 path.setFillType(SkPathFillType::kInverseWinding); 124 canvas->drawPath(path, paint); 125 126 path.setFillType(SkPathFillType::kWinding); 127 canvas->drawPath(path, outlinePaint); 128 129 canvas->restore(); 130 canvas->translate(dx, 0); 131 } 132 } 133 canvas->restore(); 134 canvas->translate(0, dy); 135 } 136 } 137} 138