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