/*
 * Copyright 2011 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/SkRect.h"
#include "include/core/SkString.h"

/* The hiragino_maru_goth_pro_e path was generated with Mac-specific code:
 *
 * paint.setTextSize(SkIntToScalar(100));
 * paint.setTypeface(SkTypeface::CreateFromName("Hiragino Maru Gothic Pro"));
 * paint.getTextPath("e", 1, 50, 50, &path);
 *
 * The path data is duplicated here to allow the test to
 * run on all platforms and to remove the bug dependency
 * should future Macs edit or delete the font.
 */
static SkPath hiragino_maru_goth_pro_e() {
    SkPathBuilder path;
    path.moveTo(98.6f, 24.7f);
    path.cubicTo(101.7f, 24.7f, 103.6f, 22.8f, 103.6f, 19.2f);
    path.cubicTo(103.6f, 18.9f, 103.6f, 18.7f, 103.6f, 18.4f);
    path.cubicTo(102.6f, 5.3f, 94.4f, -6.1f, 79.8f, -6.1f);
    path.cubicTo(63.5f, -6.1f, 54.5f, 6, 54.5f, 23.3f);
    path.cubicTo(54.5f, 40.6f, 64, 52.2f, 80.4f, 52.2f);
    path.cubicTo(93.4f, 52.2f, 99.2f, 45.6f, 102.4f, 39);
    path.cubicTo(102.8f, 38.4f, 102.9f, 37.8f, 102.9f, 37.2f);
    path.cubicTo(102.9f, 35.4f, 101.5f, 34.2f, 99.8f, 33.7f);
    path.cubicTo(99.1f, 33.5f, 98.4f, 33.3f, 97.7f, 33.3f);
    path.cubicTo(96.3f, 33.3f, 95, 34, 94.1f, 35.8f);
    path.cubicTo(91.7f, 41.1f, 87.7f, 44.7f, 80.5f, 44.7f);
    path.cubicTo(69.7f, 44.7f, 63.6f, 37, 63.4f, 24.7f);
    path.lineTo(98.6f, 24.7f);
    path.close();
    path.moveTo(63.7f, 17.4f);
    path.cubicTo(65, 7.6f, 70.2f, 1.2f, 79.8f, 1.2f);
    path.cubicTo(89, 1.2f, 93.3f, 8.5f, 94.5f, 15.6f);
    path.cubicTo(94.5f, 15.8f, 94.5f, 16, 94.5f, 16.1f);
    path.cubicTo(94.5f, 17, 94.1f, 17.4f, 93, 17.4f);
    path.lineTo(63.7f, 17.4f);
    path.close();
    return path.detach();
}

static void test_path(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    paint.setAntiAlias(true);
    canvas->drawPath(path, paint);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(SK_ColorRED);
    canvas->drawPath(path, paint);
}

static void test_rev(SkCanvas* canvas, const SkPath& path) {
    test_path(canvas, path);

    SkPath rev;
    rev.reverseAddPath(path);
    canvas->save();
    canvas->translate(150, 0);
    test_path(canvas, rev);
    canvas->restore();
}

DEF_SIMPLE_GM_BG_NAME(pathreverse, canvas, 640, 480, SK_ColorWHITE,
                      SkString("path-reverse")) {
        SkRect r = { 10, 10, 100, 60 };

        SkPath path;

        path.addRect(r); test_rev(canvas, path);

        canvas->translate(0, 100);
        path.offset(20, 20);
        path.addRect(r); test_rev(canvas, path);

        canvas->translate(0, 100);
        path.reset();
        path.moveTo(10, 10); path.lineTo(30, 30);
        path.addOval(r);
        r.offset(50, 20);
        path.addOval(r);
        test_rev(canvas, path);

        path = hiragino_maru_goth_pro_e();
        canvas->translate(0, 100);
        test_rev(canvas, path);
}
