1/*
2 * Copyright 2012 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
12#define STROKE_WIDTH    SkIntToScalar(20)
13
14static void draw_path(SkCanvas* canvas, const SkPath& path, const SkRect& rect,
15                      SkPaint::Join join, int doFill) {
16    SkPaint paint;
17    paint.setAntiAlias(true);
18    paint.setStyle(doFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
19
20    paint.setColor(SK_ColorGRAY);
21    paint.setStrokeWidth(STROKE_WIDTH);
22    paint.setStrokeJoin(join);
23    canvas->drawRect(rect, paint);
24
25    paint.setStyle(SkPaint::kStroke_Style);
26    paint.setStrokeWidth(0);
27    paint.setColor(SK_ColorRED);
28    canvas->drawPath(path, paint);
29
30    paint.setStrokeWidth(3);
31    paint.setStrokeJoin(SkPaint::kMiter_Join);
32    int n = path.countPoints();
33    SkAutoTArray<SkPoint> points(n);
34    path.getPoints(points.get(), n);
35    canvas->drawPoints(SkCanvas::kPoints_PointMode, n, points.get(), paint);
36}
37
38/*
39 *  Test calling SkStroker for rectangles. Cases to cover:
40 *
41 *  geometry: normal, small (smaller than stroke-width), empty, inverted
42 *  joint-type for the corners
43 */
44class StrokeRectGM : public skiagm::GM {
45public:
46    StrokeRectGM() {}
47
48protected:
49    virtual uint32_t onGetFlags() const SK_OVERRIDE {
50        return kSkipTiled_Flag;
51    }
52
53    virtual SkString onShortName() {
54        return SkString("strokerect");
55    }
56
57    virtual SkISize onISize() {
58        return SkISize::Make(1024, 740);
59    }
60
61    virtual void onDraw(SkCanvas* canvas) {
62        canvas->drawColor(SK_ColorWHITE);
63        canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
64
65        SkPaint paint;
66        paint.setStyle(SkPaint::kStroke_Style);
67        paint.setStrokeWidth(STROKE_WIDTH);
68
69        static const SkPaint::Join gJoins[] = {
70            SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join
71        };
72
73        static const SkScalar W = 80;
74        static const SkScalar H = 80;
75        static const SkRect gRects[] = {
76            { 0, 0, W, H },
77            { W, 0, 0, H },
78            { 0, H, W, 0 },
79            { 0, 0, STROKE_WIDTH, H },
80            { 0, 0, W, STROKE_WIDTH },
81            { 0, 0, STROKE_WIDTH/2, STROKE_WIDTH/2 },
82            { 0, 0, W, 0 },
83            { 0, 0, 0, H },
84            { 0, 0, 0, 0 },
85        };
86
87        for (int doFill = 0; doFill <= 1; ++doFill) {
88            for (size_t i = 0; i < SK_ARRAY_COUNT(gJoins); ++i) {
89                SkPaint::Join join = gJoins[i];
90                paint.setStrokeJoin(join);
91
92                SkAutoCanvasRestore acr(canvas, true);
93                for (size_t j = 0; j < SK_ARRAY_COUNT(gRects); ++j) {
94                    const SkRect& r = gRects[j];
95
96                    SkPath path, fillPath;
97                    path.addRect(r);
98                    paint.getFillPath(path, &fillPath);
99                    draw_path(canvas, fillPath, r, join, doFill);
100
101                    canvas->translate(W + 2 * STROKE_WIDTH, 0);
102                }
103                acr.restore();
104                canvas->translate(0, H + 2 * STROKE_WIDTH);
105            }
106            paint.setStyle(SkPaint::kStrokeAndFill_Style);
107        }
108    }
109
110private:
111    typedef GM INHERITED;
112};
113
114///////////////////////////////////////////////////////////////////////////////////////////////////
115
116DEF_GM(return new StrokeRectGM;)
117