201 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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 <utility>
 | |
| 
 | |
| 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<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(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);
 | |
|     }
 | |
| }
 |