| /* |
| * Copyright 2013 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "gm/gm.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkColor.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkPathBuilder.h" |
| #include "include/core/SkPoint.h" |
| #include "include/core/SkRect.h" |
| #include "include/core/SkScalar.h" |
| #include "include/core/SkSize.h" |
| #include "include/core/SkString.h" |
| #include "include/core/SkTypes.h" |
| #include "include/private/base/SkFloatBits.h" |
| #include "include/private/base/SkTArray.h" |
| |
| using namespace skia_private; |
| |
| class ConicPathsGM : public skiagm::GM { |
| protected: |
| |
| SkString onShortName() override { |
| return SkString("conicpaths"); |
| } |
| |
| SkISize onISize() override { |
| return SkISize::Make(920, 960); |
| } |
| |
| template <typename Proc> void append_path(Proc proc) { |
| SkPathBuilder b; |
| proc(&b); |
| fPaths.push_back(b.detach()); |
| } |
| |
| void onOnceBeforeDraw() override { |
| this->append_path([](SkPathBuilder* conicCircle) { |
| const SkScalar w = SkScalarSqrt(2)/2; |
| conicCircle->moveTo(0, 0); |
| conicCircle->conicTo(0, 50, 50, 50, w); |
| conicCircle->rConicTo(50, 0, 50, -50, w); |
| conicCircle->rConicTo(0, -50, -50, -50, w); |
| conicCircle->rConicTo(-50, 0, -50, 50, w); |
| }); |
| |
| this->append_path([](SkPathBuilder* hyperbola) { |
| hyperbola->moveTo(0, 0); |
| hyperbola->conicTo(0, 100, 100, 100, 2); |
| }); |
| |
| this->append_path([](SkPathBuilder* thinHyperbola) { |
| thinHyperbola->moveTo(0, 0); |
| thinHyperbola->conicTo(100, 100, 5, 0, 2); |
| }); |
| |
| this->append_path([](SkPathBuilder* veryThinHyperbola) { |
| veryThinHyperbola->moveTo(0, 0); |
| veryThinHyperbola->conicTo(100, 100, 1, 0, 2); |
| }); |
| |
| this->append_path([](SkPathBuilder* closedHyperbola) { |
| closedHyperbola->moveTo(0, 0); |
| closedHyperbola->conicTo(100, 100, 0, 0, 2); |
| }); |
| |
| this->append_path([](SkPathBuilder* nearParabola) { |
| // using 1 as weight defaults to using quadTo |
| nearParabola->moveTo(0, 0); |
| nearParabola->conicTo(0, 100, 100, 100, 0.999f); |
| }); |
| |
| this->append_path([](SkPathBuilder* thinEllipse) { |
| thinEllipse->moveTo(0, 0); |
| thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf); |
| }); |
| |
| this->append_path([](SkPathBuilder* veryThinEllipse) { |
| veryThinEllipse->moveTo(0, 0); |
| veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf); |
| }); |
| |
| this->append_path([](SkPathBuilder* closedEllipse) { |
| closedEllipse->moveTo(0, 0); |
| closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf); |
| }); |
| |
| { |
| SkPathBuilder b; |
| const SkScalar w = SkScalarSqrt(2)/2; |
| b.moveTo(2.1e+11f, -1.05e+11f); |
| b.conicTo(2.1e+11f, 0, 1.05e+11f, 0, w); |
| b.conicTo(0, 0, 0, -1.05e+11f, w); |
| b.conicTo(0, -2.1e+11f, 1.05e+11f, -2.1e+11f, w); |
| b.conicTo(2.1e+11f, -2.1e+11f, 2.1e+11f, -1.05e+11f, w); |
| fGiantCircle = b.detach(); |
| } |
| } |
| |
| void drawGiantCircle(SkCanvas* canvas) { |
| SkPaint paint; |
| canvas->drawPath(fGiantCircle, paint); |
| } |
| |
| void onDraw(SkCanvas* canvas) override { |
| const SkAlpha kAlphaValue[] = { 0xFF, 0x40 }; |
| |
| const SkScalar margin = 15; |
| canvas->translate(margin, margin); |
| |
| SkPaint paint; |
| for (int p = 0; p < fPaths.size(); ++p) { |
| canvas->save(); |
| for (size_t a = 0; a < std::size(kAlphaValue); ++a) { |
| paint.setARGB(kAlphaValue[a], 0, 0, 0); |
| for (int aa = 0; aa < 2; ++aa) { |
| paint.setAntiAlias(SkToBool(aa)); |
| for (int fh = 0; fh < 2; ++fh) { |
| paint.setStroke(fh != 0); |
| |
| const SkRect& bounds = fPaths[p].getBounds(); |
| canvas->save(); |
| canvas->translate(-bounds.fLeft, -bounds.fTop); |
| canvas->drawPath(fPaths[p], paint); |
| canvas->restore(); |
| |
| canvas->translate(110, 0); |
| } |
| } |
| } |
| canvas->restore(); |
| canvas->translate(0, 110); |
| } |
| canvas->restore(); |
| |
| this->drawGiantCircle(canvas); |
| } |
| |
| private: |
| TArray<SkPath> fPaths; |
| SkPath fGiantCircle; |
| using INHERITED = skiagm::GM; |
| }; |
| DEF_GM(return new ConicPathsGM;) |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| /* arc should be on top of circle */ |
| DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) { |
| canvas->translate(50, 100); |
| SkPoint c = { 1052.5390625f, 506.8760978034711f }; |
| SkScalar radius = 1096.702150363923f; |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setStroke(true); |
| canvas->drawCircle(c, radius, paint); |
| SkPath path = SkPathBuilder().moveTo(288.88884710654133f, -280.26680862609f) |
| .arcTo({0, 0}, {-39.00216443306411f, 400.6058925796476f}, radius) |
| .detach(); |
| paint.setColor(0xff007f00); |
| canvas->drawPath(path, paint); |
| } |
| |
| /* circle should be antialiased */ |
| DEF_SIMPLE_GM(largecircle, canvas, 250, 250) { |
| canvas->translate(50, 100); |
| SkPoint c = { 1052.5390625f, 506.8760978034711f }; |
| SkScalar radius = 1096.702150363923f; |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setStroke(true); |
| canvas->drawCircle(c, radius, paint); |
| } |
| |
| /* ovals should not be blurry */ |
| DEF_SIMPLE_GM(largeovals, canvas, 250, 250) { |
| // Test EllipseOp |
| SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000); |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| paint.setStroke(true); |
| paint.setStrokeWidth(100); |
| canvas->drawOval(r, paint); |
| r.offset(-15, -15); |
| paint.setColor(SK_ColorDKGRAY); |
| // we use stroke and fill to avoid falling into the SimpleFill path |
| paint.setStyle(SkPaint::kStrokeAndFill_Style); |
| paint.setStrokeWidth(1); |
| canvas->drawOval(r, paint); |
| |
| // Test DIEllipseOp |
| canvas->rotate(1.0f); |
| r.offset(55, 55); |
| paint.setColor(SK_ColorGRAY); |
| paint.setStroke(true); |
| paint.setStrokeWidth(100); |
| canvas->drawOval(r, paint); |
| r.offset(-15, -15); |
| paint.setColor(SK_ColorLTGRAY); |
| paint.setStyle(SkPaint::kStrokeAndFill_Style); |
| paint.setStrokeWidth(1); |
| canvas->drawOval(r, paint); |
| } |
| |
| DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) { |
| SkPathBuilder path; |
| path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 |
| path.lineTo(SkBits2Float(0x42cfd89a), SkBits2Float(0xc2700000)); // 103.923f, -60 |
| path.lineTo(SkBits2Float(0x42cfd899), SkBits2Float(0xc2700006)); // 103.923f, -60 |
| path.conicTo(SkBits2Float(0x42f00000), SkBits2Float(0xc2009d9c), |
| SkBits2Float(0x42f00001), SkBits2Float(0x00000000), |
| SkBits2Float(0x3f7746ea)); // 120, -32.1539f, 120, 0, 0.965926f |
| |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| canvas->translate(125, 125); |
| canvas->drawPath(path.detach(), paint); |
| } |