//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// Copyright (c) Samsung Electronics. Co. LTD. All rights reserved.

/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:

    line.cpp

Abstract:

    draws accelerated lines

Functions:

Notes:

--*/

#include "precomp.h"
#include <dispperf.h>

#define SIMPLE_LINEACCEL        //< This option enable Only Horizontal/Vertical Acceleration with 2D HW

SCODE SMDKDisp::WrappedEmulatedLine(GPELineParms *pLineParms)
{
    SCODE retval;
    RECT  bounds;
    int   N_plus_1;                // Minor length of bounding rect + 1

    DEBUG_2D_MSG(GPE_ZONE_LINE, (TEXT("++%s()\r\n"), _T(__FUNCTION__)));
    // calculate the bounding-rect to determine overlap with cursor
    if (pLineParms->dN)            // The line has a diagonal component (we'll refresh the bounding rect)
    {
        N_plus_1 = 2 + ((pLineParms->cPels * pLineParms->dN) / pLineParms->dM);
    }
    else
    {
        N_plus_1 = 1;
    }

    switch(pLineParms->iDir)
    {
    case 0:
        bounds.left = pLineParms->xStart;
        bounds.top = pLineParms->yStart;
        bounds.right = pLineParms->xStart + pLineParms->cPels + 1;
        bounds.bottom = bounds.top + N_plus_1;
        break;

    case 1:
        bounds.left = pLineParms->xStart;
        bounds.top = pLineParms->yStart;
        bounds.bottom = pLineParms->yStart + pLineParms->cPels + 1;
        bounds.right = bounds.left + N_plus_1;
        break;

    case 2:
        bounds.right = pLineParms->xStart + 1;
        bounds.top = pLineParms->yStart;
        bounds.bottom = pLineParms->yStart + pLineParms->cPels + 1;
        bounds.left = bounds.right - N_plus_1;
        break;

    case 3:
        bounds.right = pLineParms->xStart + 1;
        bounds.top = pLineParms->yStart;
        bounds.left = pLineParms->xStart - pLineParms->cPels;
        bounds.bottom = bounds.top + N_plus_1;
        break;

    case 4:
        bounds.right = pLineParms->xStart + 1;
        bounds.bottom = pLineParms->yStart + 1;
        bounds.left = pLineParms->xStart - pLineParms->cPels;
        bounds.top = bounds.bottom - N_plus_1;
        break;

    case 5:
        bounds.right = pLineParms->xStart + 1;
        bounds.bottom = pLineParms->yStart + 1;
        bounds.top = pLineParms->yStart - pLineParms->cPels;
        bounds.left = bounds.right - N_plus_1;
        break;

    case 6:
        bounds.left = pLineParms->xStart;
        bounds.bottom = pLineParms->yStart + 1;
        bounds.top = pLineParms->yStart - pLineParms->cPels;
        bounds.right = bounds.left + N_plus_1;
        break;

    case 7:
        bounds.left = pLineParms->xStart;
        bounds.bottom = pLineParms->yStart + 1;
        bounds.right = pLineParms->xStart + pLineParms->cPels + 1;
        bounds.top = bounds.bottom - N_plus_1;
        break;

    default:
        RETAIL_2D_MSG(DISP_ZONE_ERROR,(_T("[DISPDRV:ERR] WrappedEmulatedLine() : Invalid Direction %d\n\r"), pLineParms->iDir));
        return E_INVALIDARG;
    }
    // check for line overlap with cursor and turn off cursor if overlaps
    if (m_CursorVisible && !m_CursorDisabled)
    {
        RotateRectl(&m_CursorRect);
        if (m_CursorRect.top < bounds.bottom && m_CursorRect.bottom > bounds.top &&
            m_CursorRect.left < bounds.right && m_CursorRect.right > bounds.left)
        {
            RotateRectlBack(&m_CursorRect);
            CursorOff();
            m_CursorForcedOff = TRUE;
        }
        else
            RotateRectlBack(&m_CursorRect);
    }

        // do emulated line
        retval = EmulatedLine (pLineParms);

    // se if cursor was forced off because of overlap with line bouneds and turn back on
        if (m_CursorForcedOff)
    {
        m_CursorForcedOff = FALSE;
        CursorOn();
    }

    DEBUG_2D_MSG(GPE_ZONE_LINE, (TEXT("--%s()\r\n"), _T(__FUNCTION__)));

    return retval;
}


SCODE
SMDKDisp::Line(GPELineParms *pLineParms, EGPEPhase phase)
{
    DEBUG_2D_MSG (GPE_ZONE_LINE, (TEXT("++%s()\r\n"), _T(__FUNCTION__)));

    if (phase == gpeSingle || phase == gpePrepare)
    {
        DispPerfStart(ROP_LINE);
        pLineParms->pLine = (SCODE (GPE::*)(struct GPELineParms *))&SMDKDisp::WrappedEmulatedLine;
    }
    else if (phase == gpeComplete)
    {
        DispPerfEnd(0);
    }
    DEBUG_2D_MSG(GPE_ZONE_LINE, (TEXT("--%s()\r\n"), _T(__FUNCTION__)));

    return S_OK;
}
