/*
 * 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.h"

#include "GrContext.h"
#include "GrContextOptions.h"
#include "SkPath.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(); )
