1e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian/*
2e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian * Copyright 2014 Google Inc.
3e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian *
4e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian * Use of this source code is governed by a BSD-style license that can be
5e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian * found in the LICENSE file.
6e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian */
7e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
8e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian#include "gm.h"
9e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian#include "SkPath.h"
10e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian#include "SkScan.h"
11e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
12e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian#define W   800
13e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian#define H   800
14e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
15e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianclass AnalyticAntiAliasConvexGM : public skiagm::GM {
16e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianpublic:
17e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    AnalyticAntiAliasConvexGM() {}
18e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
19e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianprotected:
20e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
21e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    SkString onShortName() override {
22e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        return SkString("analytic_antialias_convex");
23e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    }
24e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
25e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    SkISize onISize() override {
26e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        return SkISize::Make(W, H);
27e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    }
28e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
29e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    void onDraw(SkCanvas* canvas) override {
30e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        SkPaint p;
31e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        p.setColor(SK_ColorRED);
32e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        p.setAntiAlias(true);
33e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
34e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->clear(0xFFFFFFFF);
35e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
36e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->save();
37e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
38e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        SkScalar y = 0;
39e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
40e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->translate(0, y);
41e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->rotate(1);
423661bc997620899695041010a750d11dbe8a972dMike Reed        canvas->drawRect({ 20, 20, 200, 200 }, p);
43e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->restore();
44e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
45e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        y += 200;
46e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
47e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->translate(0, y);
48e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->rotate(1);
493661bc997620899695041010a750d11dbe8a972dMike Reed        canvas->drawRect({ 20, 20, 20.2f, 200 }, p);
503661bc997620899695041010a750d11dbe8a972dMike Reed        canvas->drawRect({ 20, 200, 200, 200.1f }, p);
51e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->drawCircle(100, 100, 30, p);
52e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian        canvas->restore();
53451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian
54451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        // The following path is empty but it'll reveal bug chrome:662914
55451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        SkPath path;
56451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        path.moveTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041));  // 77.8073f, 231.626f
57451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        // 77.8075f, 231.626f, 77.8074f, 231.625f, 77.8073f, 231.625f
58451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        path.cubicTo(SkBits2Float(0x429b9d71), SkBits2Float(0x4367a022),
59451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian                SkBits2Float(0x429b9d64), SkBits2Float(0x4367a009),
60451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian                SkBits2Float(0x429b9d50), SkBits2Float(0x43679ff2));
61451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        path.lineTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041));  // 77.8073f, 231.626f
62451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        path.close();
63451ceba3544fa1ff810378f1e9a47c7d20f48a9fliyuqian        canvas->drawPath(path, p);
640038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li
650038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        // The following path reveals a subtle SkAnalyticQuadraticEdge::updateQuadratic bug:
660038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        // we should not use any snapped y for the intermediate values whose error may accumulate;
670038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        // snapping should only be allowed once before updateLine.
680038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        path.reset();
690038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        path.moveTo(SkBits2Float(0x434ba71e), SkBits2Float(0x438a06d0));  // 203.653f, 276.053f
700038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        path.lineTo(SkBits2Float(0x43492a74), SkBits2Float(0x4396d70d));  // 201.166f, 301.68f
710038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        // 200.921f, 304.207f, 196.939f, 303.82f, 0.707107f
720038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        path.conicTo(SkBits2Float(0x4348ebaf), SkBits2Float(0x43981a75),
730038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li                SkBits2Float(0x4344f079), SkBits2Float(0x4397e900), SkBits2Float(0x3f3504f3));
740038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        path.close();
750038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        // Manually setting convexity is required. Otherwise, this path will be considered concave.
760038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        path.setConvexity(SkPath::kConvex_Convexity);
770038b7feaaa3d2337b2e44938a11bd0f475cd525Yuqian Li        canvas->drawPath(path, p);
78e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    }
79e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
80e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianprivate:
81e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian    typedef skiagm::GM INHERITED;
82e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian};
83e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqian
84131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Liclass AnalyticAntiAliasGeneralGM : public skiagm::GM {
85131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Lipublic:
86131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    AnalyticAntiAliasGeneralGM() {}
87131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
88131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Liprotected:
89131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
90131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    SkString onShortName() override {
91131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        return SkString("analytic_antialias_general");
92131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    }
93131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
94131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    SkISize onISize() override {
95131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        return SkISize::Make(W, H);
96131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    }
97131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
98131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    void onDraw(SkCanvas* canvas) override {
99131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        SkPaint p;
100131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        p.setColor(SK_ColorRED);
101131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        p.setAntiAlias(true);
102131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
103131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->clear(0xFFFFFFFF);
104131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
105131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->save();
106131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->rotate(1);
107131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        const SkScalar R = 115.2f, C = 128.0f;
108131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        SkPath path;
109131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        path.moveTo(C + R, C);
110131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        for (int i = 1; i < 8; ++i) {
111131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li            SkScalar a = 2.6927937f * i;
112131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li            SkScalar cosine;
113131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li            SkScalar sine = SkScalarSinCos(a, &cosine);
114131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li            path.lineTo(C + R * cosine, C + R * sine);
115131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        }
116131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->drawPath(path, p);
117131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->restore();
118131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
119131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->save();
120131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->translate(200, 0);
121131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->rotate(1);
122131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        p.setStyle(SkPaint::kStroke_Style);
123131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        p.setStrokeWidth(5);
124131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->drawPath(path, p);
125131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->restore();
126131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    }
127131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
128131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Liprivate:
129131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    typedef skiagm::GM INHERITED;
130131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li};
131131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
132131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Liclass AnalyticAntiAliasInverseGM : public skiagm::GM {
133131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Lipublic:
134131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    AnalyticAntiAliasInverseGM() {}
135131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
136131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Liprotected:
137131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
138131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    SkString onShortName() override {
139131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        return SkString("analytic_antialias_inverse");
140131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    }
141131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
142131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    SkISize onISize() override {
143131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        return SkISize::Make(W, H);
144131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    }
145131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
146131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    void onDraw(SkCanvas* canvas) override {
147131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        SkPaint p;
148131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        p.setColor(SK_ColorRED);
149131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        p.setAntiAlias(true);
150131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
151131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->save();
152131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
153131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        SkPath path;
154131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        path.addCircle(100, 100, 30);
155131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        path.setFillType(SkPath::kInverseWinding_FillType);
156131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->drawPath(path, p);
157131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li        canvas->restore();
158131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    }
159131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
160131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Liprivate:
161131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li    typedef skiagm::GM INHERITED;
162131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li};
163131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian Li
164e60d85597f803c4dff6329840215af1d1d9a8fdcliyuqianDEF_GM( return new AnalyticAntiAliasConvexGM; )
165131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian LiDEF_GM( return new AnalyticAntiAliasGeneralGM; )
166131c1fb96328ee00cb18f629eddfb665b36e9463Yuqian LiDEF_GM( return new AnalyticAntiAliasInverseGM; )
167