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 // skbug.com/7573 80 y += 200; 81 canvas->translate(0, y); 82 p.setAntiAlias(true); 83 path.reset(); 84 path.moveTo(1.98009784f, 9.0162744f); 85 path.lineTo(47.843992f, 10.1922744f); 86 path.lineTo(47.804008f, 11.7597256f); 87 path.lineTo(1.93990216f, 10.5837256f); 88 canvas->drawPath(path, p); 89 canvas->restore(); 90 } 91 92 private: 93 typedef skiagm::GM INHERITED; 94 }; 95 96 class AnalyticAntiAliasGeneralGM : public skiagm::GM { 97 public: AnalyticAntiAliasGeneralGM()98 AnalyticAntiAliasGeneralGM() {} 99 100 protected: 101 onShortName()102 SkString onShortName() override { 103 return SkString("analytic_antialias_general"); 104 } 105 onISize()106 SkISize onISize() override { 107 return SkISize::Make(W, H); 108 } 109 onDraw(SkCanvas * canvas)110 void onDraw(SkCanvas* canvas) override { 111 SkPaint p; 112 p.setColor(SK_ColorRED); 113 p.setAntiAlias(true); 114 115 canvas->clear(0xFFFFFFFF); 116 117 canvas->save(); 118 canvas->rotate(1); 119 const SkScalar R = 115.2f, C = 128.0f; 120 SkPath path; 121 path.moveTo(C + R, C); 122 for (int i = 1; i < 8; ++i) { 123 SkScalar a = 2.6927937f * i; 124 SkScalar cosine; 125 SkScalar sine = SkScalarSinCos(a, &cosine); 126 path.lineTo(C + R * cosine, C + R * sine); 127 } 128 canvas->drawPath(path, p); 129 canvas->restore(); 130 131 canvas->save(); 132 canvas->translate(200, 0); 133 canvas->rotate(1); 134 p.setStyle(SkPaint::kStroke_Style); 135 p.setStrokeWidth(5); 136 canvas->drawPath(path, p); 137 canvas->restore(); 138 139 140 // The following two paths test if we correctly cumulates the alpha on the middle pixel 141 // column where the left rect and the right rect abut. 142 p.setStyle(SkPaint::kFill_Style); 143 canvas->translate(0, 300); 144 path.reset(); 145 path.addRect({20, 20, 100.4999f, 100}); 146 path.addRect({100.5001f, 20, 200, 100}); 147 canvas->drawPath(path, p); 148 149 canvas->translate(300, 0); 150 path.reset(); 151 path.addRect({20, 20, 100.1f, 100}); 152 path.addRect({100.9f, 20, 200, 100}); 153 canvas->drawPath(path, p); 154 } 155 156 private: 157 typedef skiagm::GM INHERITED; 158 }; 159 160 class AnalyticAntiAliasInverseGM : public skiagm::GM { 161 public: AnalyticAntiAliasInverseGM()162 AnalyticAntiAliasInverseGM() {} 163 164 protected: 165 onShortName()166 SkString onShortName() override { 167 return SkString("analytic_antialias_inverse"); 168 } 169 onISize()170 SkISize onISize() override { 171 return SkISize::Make(W, H); 172 } 173 onDraw(SkCanvas * canvas)174 void onDraw(SkCanvas* canvas) override { 175 SkPaint p; 176 p.setColor(SK_ColorRED); 177 p.setAntiAlias(true); 178 179 canvas->save(); 180 181 SkPath path; 182 path.addCircle(100, 100, 30); 183 path.setFillType(SkPath::kInverseWinding_FillType); 184 canvas->drawPath(path, p); 185 canvas->restore(); 186 } 187 188 private: 189 typedef skiagm::GM INHERITED; 190 }; 191 192 DEF_GM( return new AnalyticAntiAliasConvexGM; ) 193 DEF_GM( return new AnalyticAntiAliasGeneralGM; ) 194 DEF_GM( return new AnalyticAntiAliasInverseGM; ) 195