/* * 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.h" #include "SkCanvas.h" #include "SkPath.h" #include "SkDashPathEffect.h" 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 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(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); } } }