| /* |
| * Copyright 2016 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/SkMatrix.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkPath.h" |
| #include "include/core/SkRect.h" |
| #include "include/core/SkScalar.h" |
| #include "include/core/SkSize.h" |
| #include "include/core/SkString.h" |
| #include "include/gpu/GrContextOptions.h" |
| #include "include/private/GrTypesPriv.h" |
| #include "include/private/SkTArray.h" |
| |
| /** This tests the GPU backend's caching of path coverage masks */ |
| class PathMaskCache : public skiagm::GM { |
| public: |
| PathMaskCache() {} |
| |
| protected: |
| SkString onShortName() override { return SkString("path_mask_cache"); } |
| |
| SkISize onISize() override { |
| return SkISize::Make(650, 950); |
| } |
| |
| void onDraw(SkCanvas* canvas) override { |
| static constexpr SkScalar kPad = 5.f; |
| |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| auto drawPathSet = [canvas] (const SkPath& path, const SkMatrix& m) { |
| SkPaint paint; |
| paint.setAntiAlias(true); |
| SkRect bounds = path.getBounds(); |
| m.mapRect(&bounds); |
| bounds.roundOut(); |
| canvas->save(); |
| canvas->translate(-bounds.fLeft, -bounds.fTop); |
| |
| canvas->save(); |
| canvas->concat(m); |
| canvas->drawPath(path, paint); |
| canvas->restore(); |
| |
| // translate by integer |
| canvas->translate(bounds.width() + kPad, 0.f); |
| canvas->save(); |
| canvas->concat(m); |
| canvas->drawPath(path, paint); |
| canvas->restore(); |
| |
| // translate by non-integer |
| canvas->translate(bounds.width() + kPad + 0.15f, 0.f); |
| canvas->save(); |
| canvas->concat(m); |
| canvas->drawPath(path, paint); |
| canvas->restore(); |
| |
| // translate again so total translate fraction is almost identical to previous. |
| canvas->translate(bounds.width() + kPad + 0.002f, 0.f); |
| canvas->save(); |
| canvas->concat(m); |
| canvas->drawPath(path, paint); |
| canvas->restore(); |
| canvas->restore(); |
| return bounds.fBottom + kPad; |
| }; |
| |
| |
| SkTArray<SkPath> paths; |
| paths.push_back(); |
| paths.back().moveTo(0.f, 0.f); |
| paths.back().lineTo(98.f, 100.f); |
| paths.back().lineTo(100.f, 100.f); |
| paths.back().conicTo(150.f, 50.f, 100.f, 0.f, 0.6f); |
| paths.back().conicTo(148.f, 50.f, 100.f, 100.f, 0.6f); |
| paths.back().conicTo(50.f, 30.f, 0.f, 100.f, 0.9f); |
| |
| paths.push_back(); |
| paths.back().addCircle(30.f, 30.f, 30.f); |
| paths.back().addRect(SkRect::MakeXYWH(45.f, 45.f, 50.f, 60.f)); |
| paths.back().setFillType(SkPath::kEvenOdd_FillType); |
| |
| canvas->translate(kPad, kPad); |
| |
| for (const SkPath& path : paths) { |
| SkScalar ty = drawPathSet(path, SkMatrix::I()); |
| canvas->translate(0, ty); |
| |
| // Non-uniform scale. |
| SkMatrix s; |
| s.setScale(0.5f, 2.f); |
| ty = drawPathSet(path, s); |
| canvas->translate(0.f, ty); |
| |
| // Rotation |
| SkMatrix r; |
| r.setRotate(60.f, path.getBounds().centerX(), path.getBounds().centerY()); |
| ty = drawPathSet(path, r); |
| canvas->translate(0.f, ty); |
| } |
| } |
| |
| void modifyGrContextOptions(GrContextOptions* options) override { |
| options->fGpuPathRenderers = GpuPathRenderers::kNone; |
| options->fAllowPathMaskCaching = true; |
| } |
| |
| private: |
| typedef GM INHERITED; |
| }; |
| |
| DEF_GM( return new PathMaskCache(); ) |