/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPDFDeviceFlattener.h"
#include "SkDraw.h"

static SkISize SkSizeToISize(const SkSize& size) {
    return SkISize::Make(SkScalarRoundToInt(size.width()), SkScalarRoundToInt(size.height()));
}

SkPDFDeviceFlattener::SkPDFDeviceFlattener(const SkSize& pageSize, const SkRect* trimBox)
            : SkPDFDevice(SkSizeToISize(pageSize),
                          SkSizeToISize(pageSize),
                          SkMatrix::I()) {
    // TODO(edisonn): store the trimbox on emit.
}

SkPDFDeviceFlattener::~SkPDFDeviceFlattener() {
}

static void flattenPaint(const SkDraw& d, SkPaint* paint) {
    if (paint->getShader()) {
        SkAutoTUnref<SkShader> lms(SkShader::CreateLocalMatrixShader(paint->getShader(),
                                                                     *d.fMatrix));
        paint->setShader(lms);
    }
}

void SkPDFDeviceFlattener::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
                                      size_t count, const SkPoint points[],
                                      const SkPaint& paint) {
    if (!mustFlatten(d)) {
        INHERITED::drawPoints(d, mode, count, points, paint);
        return;
    }

    SkPaint paintFlatten(paint);
    flattenPaint(d, &paintFlatten);

    SkPoint* flattenedPoints = SkNEW_ARRAY(SkPoint, count);
    d.fMatrix->mapPoints(flattenedPoints, points, SkToS32(count));
    SkDraw draw(d);
    SkMatrix identity = SkMatrix::I();
    draw.fMatrix = &identity;
    INHERITED::drawPoints(draw, mode, count, flattenedPoints, paintFlatten);
    SkDELETE_ARRAY(flattenedPoints);
}

void SkPDFDeviceFlattener::drawRect(const SkDraw& d, const SkRect& r, const SkPaint& paint) {
    if (!mustFlatten(d)) {
        INHERITED::drawRect(d, r, paint);
        return;
    }

    SkPath path;
    path.addRect(r);
    path.transform(*d.fMatrix);
    SkDraw draw(d);
    SkMatrix matrix = SkMatrix::I();
    draw.fMatrix = &matrix;

    SkPaint paintFlatten(paint);
    flattenPaint(d, &paintFlatten);

    INHERITED::drawPath(draw, path, paintFlatten, NULL, true);
}

void SkPDFDeviceFlattener::drawPath(const SkDraw& d, const SkPath& origPath,
                                    const SkPaint& paint, const SkMatrix* prePathMatrix,
                                    bool pathIsMutable) {
    if (!mustFlatten(d) && !(prePathMatrix && prePathMatrix->hasPerspective())) {
        INHERITED::drawPath(d, origPath, paint, prePathMatrix, pathIsMutable);
        return;
    }

    SkPath* pathPtr = (SkPath*)&origPath;
    SkPath tmpPath;

    if (!pathIsMutable) {
        tmpPath = origPath;
        pathPtr = &tmpPath;
    }

    if (prePathMatrix) {
        pathPtr->transform(*prePathMatrix);
    }

    SkPaint paintFlatten(paint);
    flattenPaint(d, &paintFlatten);

    bool fill = paintFlatten.getFillPath(*pathPtr, &tmpPath);
    SkDEBUGCODE(pathPtr = (SkPath*)0x12345678);  // Don't use pathPtr after this point.

    paintFlatten.setPathEffect(NULL);
    if (fill) {
        paintFlatten.setStyle(SkPaint::kFill_Style);
    } else {
        paintFlatten.setStyle(SkPaint::kStroke_Style);
        paintFlatten.setStrokeWidth(0);
    }

    tmpPath.transform(*d.fMatrix);

    SkDraw draw(d);
    SkMatrix matrix = SkMatrix::I();
    draw.fMatrix = &matrix;

    INHERITED::drawPath(draw, tmpPath, paintFlatten, NULL, true);
}

void SkPDFDeviceFlattener::drawText(const SkDraw& d, const void* text, size_t len,
                                    SkScalar x, SkScalar y, const SkPaint& paint) {
    if (mustPathText(d, paint)) {
        d.drawText_asPaths((const char*)text, len, x, y, paint);
        return;
    }

    INHERITED::drawText(d, text, len, x, y, paint);
}

void SkPDFDeviceFlattener::drawPosText(const SkDraw& d, const void* text, size_t len,
                                       const SkScalar pos[], SkScalar constY,
                                       int scalarsPerPos, const SkPaint& paint) {
    if (mustPathText(d, paint)) {
        d.drawPosText_asPaths((const char*)text, len, pos, constY, scalarsPerPos, paint);
        return;
    }
    INHERITED::drawPosText(d, text, len, pos, constY,scalarsPerPos, paint);
}

void SkPDFDeviceFlattener::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
                                          const SkPath& path, const SkMatrix* matrix,
                                          const SkPaint& paint) {
    if (mustPathText(d, paint) || (matrix && matrix->hasPerspective())) {
        d.drawTextOnPath((const char*)text, len, path, matrix, paint);
        return;
    }
    INHERITED::drawTextOnPath(d, text, len, path, matrix, paint);
}

bool SkPDFDeviceFlattener::mustFlatten(const SkDraw& d) const {
    // TODO(edisonn): testability, add flag to force return true.
    return d.fMatrix->hasPerspective();
}

bool SkPDFDeviceFlattener::mustPathText(const SkDraw& d, const SkPaint&) {
    // TODO(edisonn): testability, add flag to force return true.
    // TODO(edisonn): TBD: How to flatten MaskFilter.
    return d.fMatrix->hasPerspective();
}
