1 /* 2 * Copyright 2014 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 "SkPath.h" 10 #include "SkScan.h" 11 12 #define W 800 13 #define H 800 14 15 class AnalyticAntiAliasConvexGM : public skiagm::GM { 16 public: AnalyticAntiAliasConvexGM()17 AnalyticAntiAliasConvexGM() {} 18 19 protected: 20 onShortName()21 SkString onShortName() override { 22 return SkString("analytic_antialias_convex"); 23 } 24 onISize()25 SkISize onISize() override { 26 return SkISize::Make(W, H); 27 } 28 onDraw(SkCanvas * canvas)29 void onDraw(SkCanvas* canvas) override { 30 SkPaint p; 31 p.setColor(SK_ColorRED); 32 p.setAntiAlias(true); 33 34 canvas->clear(0xFFFFFFFF); 35 36 canvas->save(); 37 38 SkScalar y = 0; 39 40 canvas->translate(0, y); 41 canvas->rotate(1); 42 canvas->drawRect({ 20, 20, 200, 200 }, p); 43 canvas->restore(); 44 45 y += 200; 46 47 canvas->translate(0, y); 48 canvas->rotate(1); 49 canvas->drawRect({ 20, 20, 20.2f, 200 }, p); 50 canvas->drawRect({ 20, 200, 200, 200.1f }, p); 51 canvas->drawCircle(100, 100, 30, p); 52 canvas->restore(); 53 54 // The following path is empty but it'll reveal bug chrome:662914 55 SkPath path; 56 path.moveTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041)); // 77.8073f, 231.626f 57 // 77.8075f, 231.626f, 77.8074f, 231.625f, 77.8073f, 231.625f 58 path.cubicTo(SkBits2Float(0x429b9d71), SkBits2Float(0x4367a022), 59 SkBits2Float(0x429b9d64), SkBits2Float(0x4367a009), 60 SkBits2Float(0x429b9d50), SkBits2Float(0x43679ff2)); 61 path.lineTo(SkBits2Float(0x429b9d5c), SkBits2Float(0x4367a041)); // 77.8073f, 231.626f 62 path.close(); 63 canvas->drawPath(path, p); 64 65 // The following path reveals a subtle SkAnalyticQuadraticEdge::updateQuadratic bug: 66 // we should not use any snapped y for the intermediate values whose error may accumulate; 67 // snapping should only be allowed once before updateLine. 68 path.reset(); 69 path.moveTo(SkBits2Float(0x434ba71e), SkBits2Float(0x438a06d0)); // 203.653f, 276.053f 70 path.lineTo(SkBits2Float(0x43492a74), SkBits2Float(0x4396d70d)); // 201.166f, 301.68f 71 // 200.921f, 304.207f, 196.939f, 303.82f, 0.707107f 72 path.conicTo(SkBits2Float(0x4348ebaf), SkBits2Float(0x43981a75), 73 SkBits2Float(0x4344f079), SkBits2Float(0x4397e900), SkBits2Float(0x3f3504f3)); 74 path.close(); 75 // Manually setting convexity is required. Otherwise, this path will be considered concave. 76 path.setConvexity(SkPath::kConvex_Convexity); 77 canvas->drawPath(path, p); 78 } 79 80 private: 81 typedef skiagm::GM INHERITED; 82 }; 83 84 class AnalyticAntiAliasGeneralGM : public skiagm::GM { 85 public: AnalyticAntiAliasGeneralGM()86 AnalyticAntiAliasGeneralGM() {} 87 88 protected: 89 onShortName()90 SkString onShortName() override { 91 return SkString("analytic_antialias_general"); 92 } 93 onISize()94 SkISize onISize() override { 95 return SkISize::Make(W, H); 96 } 97 onDraw(SkCanvas * canvas)98 void onDraw(SkCanvas* canvas) override { 99 SkPaint p; 100 p.setColor(SK_ColorRED); 101 p.setAntiAlias(true); 102 103 canvas->clear(0xFFFFFFFF); 104 105 canvas->save(); 106 canvas->rotate(1); 107 const SkScalar R = 115.2f, C = 128.0f; 108 SkPath path; 109 path.moveTo(C + R, C); 110 for (int i = 1; i < 8; ++i) { 111 SkScalar a = 2.6927937f * i; 112 SkScalar cosine; 113 SkScalar sine = SkScalarSinCos(a, &cosine); 114 path.lineTo(C + R * cosine, C + R * sine); 115 } 116 canvas->drawPath(path, p); 117 canvas->restore(); 118 119 canvas->save(); 120 canvas->translate(200, 0); 121 canvas->rotate(1); 122 p.setStyle(SkPaint::kStroke_Style); 123 p.setStrokeWidth(5); 124 canvas->drawPath(path, p); 125 canvas->restore(); 126 127 128 // The following two paths test if we correctly cumulates the alpha on the middle pixel 129 // column where the left rect and the right rect abut. 130 p.setStyle(SkPaint::kFill_Style); 131 canvas->translate(0, 300); 132 path.reset(); 133 path.addRect({20, 20, 100.4999f, 100}); 134 path.addRect({100.5001f, 20, 200, 100}); 135 canvas->drawPath(path, p); 136 137 canvas->translate(300, 0); 138 path.reset(); 139 path.addRect({20, 20, 100.1f, 100}); 140 path.addRect({100.9f, 20, 200, 100}); 141 canvas->drawPath(path, p); 142 } 143 144 private: 145 typedef skiagm::GM INHERITED; 146 }; 147 148 class AnalyticAntiAliasInverseGM : public skiagm::GM { 149 public: AnalyticAntiAliasInverseGM()150 AnalyticAntiAliasInverseGM() {} 151 152 protected: 153 onShortName()154 SkString onShortName() override { 155 return SkString("analytic_antialias_inverse"); 156 } 157 onISize()158 SkISize onISize() override { 159 return SkISize::Make(W, H); 160 } 161 onDraw(SkCanvas * canvas)162 void onDraw(SkCanvas* canvas) override { 163 SkPaint p; 164 p.setColor(SK_ColorRED); 165 p.setAntiAlias(true); 166 167 canvas->save(); 168 169 SkPath path; 170 path.addCircle(100, 100, 30); 171 path.setFillType(SkPath::kInverseWinding_FillType); 172 canvas->drawPath(path, p); 173 canvas->restore(); 174 } 175 176 private: 177 typedef skiagm::GM INHERITED; 178 }; 179 180 DEF_GM( return new AnalyticAntiAliasConvexGM; ) 181 DEF_GM( return new AnalyticAntiAliasGeneralGM; ) 182 DEF_GM( return new AnalyticAntiAliasInverseGM; ) 183