1 /* 2 * Copyright 2013 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/gm.h" 9 #include "include/core/SkCanvas.h" 10 #include "include/core/SkColor.h" 11 #include "include/core/SkPaint.h" 12 #include "include/core/SkPath.h" 13 #include "include/core/SkPoint.h" 14 #include "include/core/SkRect.h" 15 #include "include/core/SkScalar.h" 16 #include "include/core/SkSize.h" 17 #include "include/core/SkString.h" 18 #include "include/core/SkTypes.h" 19 #include "include/private/SkFloatBits.h" 20 #include "include/private/SkTArray.h" 21 22 class ConicPathsGM : public skiagm::GM { 23 protected: 24 onShortName()25 SkString onShortName() override { 26 return SkString("conicpaths"); 27 } 28 onISize()29 SkISize onISize() override { 30 return SkISize::Make(920, 960); 31 } 32 onOnceBeforeDraw()33 void onOnceBeforeDraw() override { 34 { 35 const SkScalar w = SkScalarSqrt(2)/2; 36 SkPath* conicCirlce = &fPaths.push_back(); 37 conicCirlce->moveTo(0, 0); 38 conicCirlce->conicTo(0, 50, 50, 50, w); 39 conicCirlce->rConicTo(50, 0, 50, -50, w); 40 conicCirlce->rConicTo(0, -50, -50, -50, w); 41 conicCirlce->rConicTo(-50, 0, -50, 50, w); 42 43 } 44 { 45 SkPath* hyperbola = &fPaths.push_back(); 46 hyperbola->moveTo(0, 0); 47 hyperbola->conicTo(0, 100, 100, 100, 2); 48 } 49 { 50 SkPath* thinHyperbola = &fPaths.push_back(); 51 thinHyperbola->moveTo(0, 0); 52 thinHyperbola->conicTo(100, 100, 5, 0, 2); 53 } 54 { 55 SkPath* veryThinHyperbola = &fPaths.push_back(); 56 veryThinHyperbola->moveTo(0, 0); 57 veryThinHyperbola->conicTo(100, 100, 1, 0, 2); 58 } 59 { 60 SkPath* closedHyperbola = &fPaths.push_back(); 61 closedHyperbola->moveTo(0, 0); 62 closedHyperbola->conicTo(100, 100, 0, 0, 2); 63 } 64 { 65 // using 1 as weight defaults to using quadTo 66 SkPath* nearParabola = &fPaths.push_back(); 67 nearParabola->moveTo(0, 0); 68 nearParabola->conicTo(0, 100, 100, 100, 0.999f); 69 } 70 { 71 SkPath* thinEllipse = &fPaths.push_back(); 72 thinEllipse->moveTo(0, 0); 73 thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf); 74 } 75 { 76 SkPath* veryThinEllipse = &fPaths.push_back(); 77 veryThinEllipse->moveTo(0, 0); 78 veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf); 79 } 80 { 81 SkPath* closedEllipse = &fPaths.push_back(); 82 closedEllipse->moveTo(0, 0); 83 closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf); 84 } 85 { 86 const SkScalar w = SkScalarSqrt(2)/2; 87 fGiantCircle.moveTo(2.1e+11f, -1.05e+11f); 88 fGiantCircle.conicTo(2.1e+11f, 0, 1.05e+11f, 0, w); 89 fGiantCircle.conicTo(0, 0, 0, -1.05e+11f, w); 90 fGiantCircle.conicTo(0, -2.1e+11f, 1.05e+11f, -2.1e+11f, w); 91 fGiantCircle.conicTo(2.1e+11f, -2.1e+11f, 2.1e+11f, -1.05e+11f, w); 92 93 } 94 } 95 drawGiantCircle(SkCanvas * canvas)96 void drawGiantCircle(SkCanvas* canvas) { 97 SkPaint paint; 98 canvas->drawPath(fGiantCircle, paint); 99 } 100 onDraw(SkCanvas * canvas)101 void onDraw(SkCanvas* canvas) override { 102 const SkAlpha kAlphaValue[] = { 0xFF, 0x40 }; 103 104 const SkScalar margin = 15; 105 canvas->translate(margin, margin); 106 107 SkPaint paint; 108 for (int p = 0; p < fPaths.count(); ++p) { 109 canvas->save(); 110 for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphaValue); ++a) { 111 paint.setARGB(kAlphaValue[a], 0, 0, 0); 112 for (int aa = 0; aa < 2; ++aa) { 113 paint.setAntiAlias(SkToBool(aa)); 114 for (int fh = 0; fh < 2; ++fh) { 115 paint.setStyle(fh ? SkPaint::kStroke_Style : SkPaint::kFill_Style); 116 117 const SkRect& bounds = fPaths[p].getBounds(); 118 canvas->save(); 119 canvas->translate(-bounds.fLeft, -bounds.fTop); 120 canvas->drawPath(fPaths[p], paint); 121 canvas->restore(); 122 123 canvas->translate(110, 0); 124 } 125 } 126 } 127 canvas->restore(); 128 canvas->translate(0, 110); 129 } 130 canvas->restore(); 131 132 this->drawGiantCircle(canvas); 133 } 134 135 private: 136 SkTArray<SkPath> fPaths; 137 SkPath fGiantCircle; 138 typedef skiagm::GM INHERITED; 139 }; 140 DEF_GM(return new ConicPathsGM;) 141 142 ////////////////////////////////////////////////////////////////////////////// 143 144 /* arc should be on top of circle */ 145 DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) { 146 canvas->translate(50, 100); 147 SkPoint c = { 1052.5390625f, 506.8760978034711f }; 148 SkScalar radius = 1096.702150363923f; 149 SkPaint paint; 150 paint.setAntiAlias(true); 151 paint.setStyle(SkPaint::kStroke_Style); 152 canvas->drawCircle(c, radius, paint); 153 SkPath path; 154 path.moveTo(288.88884710654133f, -280.26680862609f); 155 path.arcTo(0, 0, -39.00216443306411f, 400.6058925796476f, radius); 156 paint.setColor(0xff007f00); 157 canvas->drawPath(path, paint); 158 } 159 160 /* circle should be antialiased */ 161 DEF_SIMPLE_GM(largecircle, canvas, 250, 250) { 162 canvas->translate(50, 100); 163 SkPoint c = { 1052.5390625f, 506.8760978034711f }; 164 SkScalar radius = 1096.702150363923f; 165 SkPaint paint; 166 paint.setAntiAlias(true); 167 paint.setStyle(SkPaint::kStroke_Style); 168 canvas->drawCircle(c, radius, paint); 169 } 170 171 /* ovals should not be blurry */ 172 DEF_SIMPLE_GM(largeovals, canvas, 250, 250) { 173 // Test EllipseOp 174 SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000); 175 SkPaint paint; 176 paint.setAntiAlias(true); 177 paint.setStyle(SkPaint::kStroke_Style); 178 paint.setStrokeWidth(100); 179 canvas->drawOval(r, paint); 180 r.offset(-15, -15); 181 paint.setColor(SK_ColorDKGRAY); 182 // we use stroke and fill to avoid falling into the SimpleFill path 183 paint.setStyle(SkPaint::kStrokeAndFill_Style); 184 paint.setStrokeWidth(1); 185 canvas->drawOval(r, paint); 186 187 // Test DIEllipseOp 188 canvas->rotate(1.0f); 189 r.offset(55, 55); 190 paint.setColor(SK_ColorGRAY); 191 paint.setStyle(SkPaint::kStroke_Style); 192 paint.setStrokeWidth(100); 193 canvas->drawOval(r, paint); 194 r.offset(-15, -15); 195 paint.setColor(SK_ColorLTGRAY); 196 paint.setStyle(SkPaint::kStrokeAndFill_Style); 197 paint.setStrokeWidth(1); 198 canvas->drawOval(r, paint); 199 } 200 201 DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) { 202 SkPath path; 203 path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 204 path.lineTo(SkBits2Float(0x42cfd89a), SkBits2Float(0xc2700000)); // 103.923f, -60 205 path.lineTo(SkBits2Float(0x42cfd899), SkBits2Float(0xc2700006)); // 103.923f, -60 206 path.conicTo(SkBits2Float(0x42f00000), SkBits2Float(0xc2009d9c), 207 SkBits2Float(0x42f00001), SkBits2Float(0x00000000), 208 SkBits2Float(0x3f7746ea)); // 120, -32.1539f, 120, 0, 0.965926f 209 210 SkPaint paint; 211 paint.setAntiAlias(true); 212 canvas->translate(125, 125); 213 canvas->drawPath(path, paint); 214 } 215