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