1 /* 2 * Copyright 2016 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/SkMatrix.h" 11 #include "include/core/SkPaint.h" 12 #include "include/core/SkPath.h" 13 #include "include/core/SkRect.h" 14 #include "include/core/SkScalar.h" 15 #include "include/core/SkSize.h" 16 #include "include/core/SkString.h" 17 #include "include/gpu/GrContextOptions.h" 18 #include "include/private/GrTypesPriv.h" 19 #include "include/private/SkTArray.h" 20 21 /** This tests the GPU backend's caching of path coverage masks */ 22 class PathMaskCache : public skiagm::GM { 23 public: PathMaskCache()24 PathMaskCache() {} 25 26 protected: onShortName()27 SkString onShortName() override { return SkString("path_mask_cache"); } 28 onISize()29 SkISize onISize() override { 30 return SkISize::Make(650, 950); 31 } 32 onDraw(SkCanvas * canvas)33 void onDraw(SkCanvas* canvas) override { 34 static constexpr SkScalar kPad = 5.f; 35 36 SkPaint paint; 37 paint.setAntiAlias(true); 38 auto drawPathSet = [canvas] (const SkPath& path, const SkMatrix& m) { 39 SkPaint paint; 40 paint.setAntiAlias(true); 41 SkRect bounds = path.getBounds(); 42 m.mapRect(&bounds); 43 bounds.roundOut(); 44 canvas->save(); 45 canvas->translate(-bounds.fLeft, -bounds.fTop); 46 47 canvas->save(); 48 canvas->concat(m); 49 canvas->drawPath(path, paint); 50 canvas->restore(); 51 52 // translate by integer 53 canvas->translate(bounds.width() + kPad, 0.f); 54 canvas->save(); 55 canvas->concat(m); 56 canvas->drawPath(path, paint); 57 canvas->restore(); 58 59 // translate by non-integer 60 canvas->translate(bounds.width() + kPad + 0.15f, 0.f); 61 canvas->save(); 62 canvas->concat(m); 63 canvas->drawPath(path, paint); 64 canvas->restore(); 65 66 // translate again so total translate fraction is almost identical to previous. 67 canvas->translate(bounds.width() + kPad + 0.002f, 0.f); 68 canvas->save(); 69 canvas->concat(m); 70 canvas->drawPath(path, paint); 71 canvas->restore(); 72 canvas->restore(); 73 return bounds.fBottom + kPad; 74 }; 75 76 77 SkTArray<SkPath> paths; 78 paths.push_back(); 79 paths.back().moveTo(0.f, 0.f); 80 paths.back().lineTo(98.f, 100.f); 81 paths.back().lineTo(100.f, 100.f); 82 paths.back().conicTo(150.f, 50.f, 100.f, 0.f, 0.6f); 83 paths.back().conicTo(148.f, 50.f, 100.f, 100.f, 0.6f); 84 paths.back().conicTo(50.f, 30.f, 0.f, 100.f, 0.9f); 85 86 paths.push_back(); 87 paths.back().addCircle(30.f, 30.f, 30.f); 88 paths.back().addRect(SkRect::MakeXYWH(45.f, 45.f, 50.f, 60.f)); 89 paths.back().setFillType(SkPathFillType::kEvenOdd); 90 91 canvas->translate(kPad, kPad); 92 93 for (const SkPath& path : paths) { 94 SkScalar ty = drawPathSet(path, SkMatrix::I()); 95 canvas->translate(0, ty); 96 97 // Non-uniform scale. 98 SkMatrix s; 99 s.setScale(0.5f, 2.f); 100 ty = drawPathSet(path, s); 101 canvas->translate(0.f, ty); 102 103 // Rotation 104 SkMatrix r; 105 r.setRotate(60.f, path.getBounds().centerX(), path.getBounds().centerY()); 106 ty = drawPathSet(path, r); 107 canvas->translate(0.f, ty); 108 } 109 } 110 modifyGrContextOptions(GrContextOptions * options)111 void modifyGrContextOptions(GrContextOptions* options) override { 112 options->fGpuPathRenderers = GpuPathRenderers::kNone; 113 options->fAllowPathMaskCaching = true; 114 } 115 116 private: 117 using INHERITED = GM; 118 }; 119 120 DEF_GM( return new PathMaskCache(); ) 121