/*
 * 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(); )
