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

#ifndef SkMatrixPriv_DEFINE
#define SkMatrixPriv_DEFINE

#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkVx.h"

#include <cstdint>
#include <cstring>
struct SkPoint3;

class SkMatrixPriv {
public:
    enum {
        // writeTo/readFromMemory will never return a value larger than this
        kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t),
    };

    static size_t WriteToMemory(const SkMatrix& matrix, void* buffer) {
        return matrix.writeToMemory(buffer);
    }

    static size_t ReadFromMemory(SkMatrix* matrix, const void* buffer, size_t length) {
        return matrix->readFromMemory(buffer, length);
    }

    typedef SkMatrix::MapXYProc MapXYProc;
    typedef SkMatrix::MapPtsProc MapPtsProc;


    static MapPtsProc GetMapPtsProc(const SkMatrix& matrix) {
        return SkMatrix::GetMapPtsProc(matrix.getType());
    }

    static MapXYProc GetMapXYProc(const SkMatrix& matrix) {
        return SkMatrix::GetMapXYProc(matrix.getType());
    }

    /**
     *  Attempt to map the rect through the inverse of the matrix. If it is not invertible,
     *  then this returns false and dst is unchanged.
     */
    static bool SK_WARN_UNUSED_RESULT InverseMapRect(const SkMatrix& mx,
                                                     SkRect* dst, const SkRect& src) {
        if (mx.getType() <= SkMatrix::kTranslate_Mask) {
            SkScalar tx = mx.getTranslateX();
            SkScalar ty = mx.getTranslateY();
            skvx::float4 trans(tx, ty, tx, ty);
            (skvx::float4::Load(&src.fLeft) - trans).store(&dst->fLeft);
            return true;
        }
        // Insert other special-cases here (e.g. scale+translate)

        // general case
        SkMatrix inverse;
        if (mx.invert(&inverse)) {
            inverse.mapRect(dst, src);
            return true;
        }
        return false;
    }

    /** Maps count pts, skipping stride bytes to advance from one SkPoint to the next.
        Points are mapped by multiplying each SkPoint by SkMatrix. Given:

                     | A B C |        | x |
            Matrix = | D E F |,  pt = | y |
                     | G H I |        | 1 |

        each resulting pts SkPoint is computed as:

                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I

        @param mx      matrix used to map the points
        @param pts     storage for mapped points
        @param stride  size of record starting with SkPoint, in bytes
        @param count   number of points to transform
    */
    static void MapPointsWithStride(const SkMatrix& mx, SkPoint pts[], size_t stride, int count) {
        SkASSERT(stride >= sizeof(SkPoint));
        SkASSERT(0 == stride % sizeof(SkScalar));

        SkMatrix::TypeMask tm = mx.getType();

        if (SkMatrix::kIdentity_Mask == tm) {
            return;
        }
        if (SkMatrix::kTranslate_Mask == tm) {
            const SkScalar tx = mx.getTranslateX();
            const SkScalar ty = mx.getTranslateY();
            skvx::float2 trans(tx, ty);
            for (int i = 0; i < count; ++i) {
                (skvx::float2::Load(&pts->fX) + trans).store(&pts->fX);
                pts = (SkPoint*)((intptr_t)pts + stride);
            }
            return;
        }
        // Insert other special-cases here (e.g. scale+translate)

        // general case
        SkMatrix::MapXYProc proc = mx.getMapXYProc();
        for (int i = 0; i < count; ++i) {
            proc(mx, pts->fX, pts->fY, pts);
            pts = (SkPoint*)((intptr_t)pts + stride);
        }
    }

    /** Maps src SkPoint array of length count to dst SkPoint array, skipping stride bytes
        to advance from one SkPoint to the next.
        Points are mapped by multiplying each SkPoint by SkMatrix. Given:

                     | A B C |         | x |
            Matrix = | D E F |,  src = | y |
                     | G H I |         | 1 |

        each resulting dst SkPoint is computed as:

                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I

        @param mx      matrix used to map the points
        @param dst     storage for mapped points
        @param src     points to transform
        @param stride  size of record starting with SkPoint, in bytes
        @param count   number of points to transform
    */
    static void MapPointsWithStride(const SkMatrix& mx, SkPoint dst[], size_t dstStride,
                                    const SkPoint src[], size_t srcStride, int count) {
        SkASSERT(srcStride >= sizeof(SkPoint));
        SkASSERT(dstStride >= sizeof(SkPoint));
        SkASSERT(0 == srcStride % sizeof(SkScalar));
        SkASSERT(0 == dstStride % sizeof(SkScalar));
        for (int i = 0; i < count; ++i) {
            mx.mapPoints(dst, src, 1);
            src = (SkPoint*)((intptr_t)src + srcStride);
            dst = (SkPoint*)((intptr_t)dst + dstStride);
        }
    }

    static void MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[], size_t dstStride,
                                               const SkPoint3 src[], size_t srcStride, int count);

    static bool PostIDiv(SkMatrix* matrix, int divx, int divy) {
        return matrix->postIDiv(divx, divy);
    }

    static bool CheapEqual(const SkMatrix& a, const SkMatrix& b) {
        return &a == &b || 0 == memcmp(a.fMat, b.fMat, sizeof(a.fMat));
    }

    static const SkScalar* M44ColMajor(const SkM44& m) { return m.fMat; }

    // This is legacy functionality that only checks the 3x3 portion. The matrix could have Z-based
    // shear, or other complex behavior. Only use this if you're planning to use the information
    // to accelerate some purely 2D operation.
    static bool IsScaleTranslateAsM33(const SkM44& m) {
        return m.rc(1,0) == 0 && m.rc(3,0) == 0 &&
               m.rc(0,1) == 0 && m.rc(3,1) == 0 &&
               m.rc(3,3) == 1;

    }

    // Map the four corners of 'r' and return the bounding box of those points. The four corners of
    // 'r' are assumed to have z = 0 and w = 1. If the matrix has perspective, the returned
    // rectangle will be the bounding box of the projected points after being clipped to w > 0.
    static SkRect MapRect(const SkM44& m, const SkRect& r);

    // Returns the differential area scale factor for a local point 'p' that will be transformed
    // by 'm' (which may have perspective). If 'm' does not have perspective, this scale factor is
    // constant regardless of 'p'; when it does have perspective, it is specific to that point.
    //
    // This can be crudely thought of as "device pixel area" / "local pixel area" at 'p'.
    //
    // Returns positive infinity if the transformed homogeneous point has w <= 0.
    static SkScalar DifferentialAreaScale(const SkMatrix& m, const SkPoint& p);

    // Determines if the transformation m applied to the bounds can be approximated by
    // an affine transformation, i.e., the perspective part of the transformation has little
    // visible effect.
    bool NearlyAffine(const SkMatrix& m,
                      const SkRect& bounds,
                      SkScalar tolerance = SK_ScalarNearlyZero);

    static SkScalar ComputeResScaleForStroking(const SkMatrix& matrix);
};

#endif
