/**************************************************************************************

                File            : LINES.CPP
                Author      : Delattre Franck & Valérie Cluzel
                Last update : 27 August 1996

***************************************************************************************/

#include "TDE.h"

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawLine16
 VERSION : 2.0 / Valérie
           1.0 / Franck

 AIM : Draw a line
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vDrawLine16(GLD_tdpstViewportAttributes p_stViewAttrib,
                     long lFirstPointX, long lFirstPointY,
                     long lSecondPointX, long lSecondPointY, long lColor)
{
    long lPitchDest, lTemp, lXIncr, lYIncr, dx, dy, lX, lY, lDecal, FirstIncr, SecondIncr;
    TDE_tdxPixel *p_usDest;      

    lPitchDest = (p_stViewAttrib->lPitch)>>1;
    p_usDest = (TDE_tdxPixel *)p_stViewAttrib->p_cVirtualScreen;

    if (abs(lSecondPointX-lFirstPointX)<abs(lSecondPointY-lFirstPointY))
    {
        if (lFirstPointY>lSecondPointY)
        {
            lTemp=lSecondPointX; lSecondPointX=lFirstPointX; lFirstPointX=lTemp;
            lTemp=lSecondPointY; lSecondPointY=lFirstPointY; lFirstPointY=lTemp;
        }

        lXIncr = (lSecondPointX>lFirstPointX) ? 1 : -1;
        dy = lSecondPointY-lFirstPointY;
        dx = abs(lSecondPointX-lFirstPointX);
        lDecal = 2*dx-dy;
        FirstIncr = 2*(dx-dy);
        SecondIncr = 2*dx;
        lX = lFirstPointX;
        lY = lFirstPointY;
        *(p_usDest+lPitchDest*lY+lX) = lColor;

        for (lY=lFirstPointY+1; lY<=lSecondPointY; ++lY)
        {
                        
            if (lDecal>=0)
            {
                lX += lXIncr; 
                                lDecal += FirstIncr;
            }
            else lDecal+=SecondIncr;
            *(p_usDest+lPitchDest*lY+lX) = lColor;
        }
        }
    else
    {
        if (lFirstPointX>lSecondPointX)
        {
            lTemp=lSecondPointX; lSecondPointX=lFirstPointX; lFirstPointX=lTemp;
            lTemp=lSecondPointY; lSecondPointY=lFirstPointY; lFirstPointY=lTemp;            
        }
        lYIncr = (lSecondPointY>lFirstPointY) ? 1 : -1;
        dx = lSecondPointX-lFirstPointX;
        dy = abs(lSecondPointY-lFirstPointY);
        lDecal = 2*dy-dx;
        FirstIncr = 2*(dy-dx);
        SecondIncr = 2*dy;
        lX = lFirstPointX;
        lY = lFirstPointY;
        *(p_usDest+lPitchDest*lY+lX) = lColor;
        for (lX=lFirstPointX+1; lX<=lSecondPointX; ++lX)
        {
            if (lDecal>=0)
            {
                lY += lYIncr; 
                                lDecal += FirstIncr;
            }
            else lDecal+=SecondIncr;
            *(p_usDest+lPitchDest*lY+lX) = lColor;
        }          
    }              
}

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vCalculateIntermediatePoint
 VERSION : 2.0 / Valérie
           1.0 / Franck

 AIM : Calculate the clipped vertex between two points
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vCalculateIntermediatePoint(TDE_tdsVertex *Result_Point, TDE_tdsVertex *Point1, TDE_tdsVertex *Point2, TDE_tdxValue xValue1, TDE_tdxValue xValue2, TDE_tdxValue xInterValue)
{
  TDE_tdxValue xRate;

  xRate = TDE_M_Div((xInterValue-xValue2), (xValue1-xValue2));
  Result_Point->xX = Point2->xX + TDE_M_Mul((Point1->xX) - (Point2->xX), xRate);
  Result_Point->xY = Point2->xY + TDE_M_Mul((Point1->xY) - (Point2->xY), xRate);
}


/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawSuperObjectLine16
 VERSION : 2.0 / Valérie
           1.0 / Franck

 AIM : Draw a super object line
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vDrawSuperObjectLine16(GLD_tdpstViewportAttributes p_stViewAttrib,
                                TDE_tdsSuperObject *p_stSuperObject)
{
    TDE_tdxValue xViewPortW, xViewPortH;
    long lFirstPointX, lFirstPointY,
          lSecondPointX, lSecondPointY;
    TDE_tdsVertex stLineCoord[2]; 

    TDE_tdsLine  *p_stLine = p_stSuperObject->p_stLine;

    xViewPortW = TDE_M_LongToValue(p_stViewAttrib->dwWidth);
    xViewPortH = TDE_M_LongToValue(p_stViewAttrib->dwHeight);
        
    stLineCoord[0].xX = xViewPortW * p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX; 
    stLineCoord[0].xY = xViewPortH * p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY; 

    stLineCoord[1].xX = xViewPortW * p_stLine->xLength;
    stLineCoord[1].xY = 0;

    TDE_vMulMatrixByVertex(&(p_stSuperObject->stModifiedMatrix.a4_xRxS), &stLineCoord[1], &stLineCoord[1]);
    stLineCoord[1].xX += stLineCoord[0].xX;
    stLineCoord[1].xY += stLineCoord[0].xY;

    lFirstPointX = TDE_M_ValueToLong(stLineCoord[0].xX);
    lFirstPointY = TDE_M_ValueToLong(stLineCoord[0].xY);

    lSecondPointX = TDE_M_ValueToLong(stLineCoord[1].xX);
    lSecondPointY = TDE_M_ValueToLong(stLineCoord[1].xY);

    TDE_vDrawLine16(p_stViewAttrib, lFirstPointX, lFirstPointY, lSecondPointX, lSecondPointY, p_stLine->lColor);
}

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**
 NAME : TDE_vDrawSuperObjectClippedLine16
 VERSION : 2.0 / Valérie
           1.0 / Franck

 AIM : Draw a super object line with clipping
**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~**/
void TDE_vDrawSuperObjectClippedLine16(GLD_tdpstViewportAttributes p_stViewAttrib,
                                                                                TDE_tdsSuperObject *p_stSuperObject)
{
        TDE_tdxValue xViewPortW, xViewPortH;

    long          lFirstPointX, lFirstPointY,
                   lSecondPointX, lSecondPointY;
    TDE_tdsVertex  stLineCoord[2]; 
    short         si;    

    TDE_tdsLine  *p_stLine = p_stSuperObject->p_stLine;

    xViewPortW = TDE_M_LongToValue(p_stViewAttrib->dwWidth);
    xViewPortH = TDE_M_LongToValue(p_stViewAttrib->dwHeight);
        
        stLineCoord[0].xX = xViewPortW * p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX; 
        stLineCoord[0].xY = xViewPortH * p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY; 

        stLineCoord[1].xX = xViewPortW * p_stLine->xLength;
        stLineCoord[1].xY = 0;

    TDE_vMulMatrixByVertex(&(p_stSuperObject->stModifiedMatrix.a4_xRxS), &stLineCoord[1], &stLineCoord[1]);
    stLineCoord[1].xX += stLineCoord[0].xX;
    stLineCoord[1].xY += stLineCoord[0].xY;

    // X Clipping
    if ((stLineCoord[0].xX<0)&&(stLineCoord[1].xX<0)) return; 
    if ((stLineCoord[0].xX>xViewPortW)&&(stLineCoord[1].xX>xViewPortW)) return; 
        for (si=0; si<2; si++)
    {
                if (stLineCoord[si].xX<0)
                        TDE_vCalculateIntermediatePoint(&stLineCoord[si], &stLineCoord[0], &stLineCoord[1], stLineCoord[0].xX, stLineCoord[1].xX, 0);
        }
        for (si=0; si<2; si++)
    {
                if (stLineCoord[si].xX>xViewPortW)
                        TDE_vCalculateIntermediatePoint(&stLineCoord[si], &stLineCoord[0], &stLineCoord[1], stLineCoord[0].xX, stLineCoord[1].xX, xViewPortW);
        }

    // Y Clipping
    if ((stLineCoord[0].xY<0)&&(stLineCoord[1].xY<0)) return; 
    if ((stLineCoord[0].xY>xViewPortH)&&(stLineCoord[1].xY>xViewPortH)) return; 
        for (si=0; si<2; si++)
    {
                if (stLineCoord[si].xY<0)
                        TDE_vCalculateIntermediatePoint(&stLineCoord[si], &stLineCoord[0], &stLineCoord[1], stLineCoord[0].xY, stLineCoord[1].xY, 0);
        }
        for (si=0; si<2; si++)
    {
                if (stLineCoord[si].xY>xViewPortH)
                        TDE_vCalculateIntermediatePoint(&stLineCoord[si], &stLineCoord[0], &stLineCoord[1], stLineCoord[0].xY, stLineCoord[1].xY, xViewPortH);
        }

        lFirstPointX = TDE_M_ValueToLong(stLineCoord[0].xX);
        lFirstPointY = TDE_M_ValueToLong(stLineCoord[0].xY);

        lSecondPointX = TDE_M_ValueToLong(stLineCoord[1].xX);
        lSecondPointY = TDE_M_ValueToLong(stLineCoord[1].xY);

        TDE_vDrawLine16(p_stViewAttrib, lFirstPointX, lFirstPointY,
                                    lSecondPointX, lSecondPointY, p_stLine->lColor);
}

void TDE_vDrawSuperObjectLineAbs(GLD_tdpstViewportAttributes p_stViewAttrib,
                                 TDE_tdsSuperObject *p_stSuperObject)
{
    TDE_tdxValue xViewPortW, xViewPortH;
    long lFirstPointX, lFirstPointY,
         lSecondPointX, lSecondPointY;
    TDE_tdsVertex stLineCoord[2]; 

    TDE_tdsLine  *p_stLine = p_stSuperObject->p_stLine;

    xViewPortW = TDE_M_LongToValue(p_stViewAttrib->dwWidth);
    xViewPortH = TDE_M_LongToValue(p_stViewAttrib->dwHeight);
        
    stLineCoord[0].xX = p_stSuperObject->stModifiedMatrix.stTranslateVertex.xX; 
    stLineCoord[0].xY = p_stSuperObject->stModifiedMatrix.stTranslateVertex.xY; 

    stLineCoord[1].xX = p_stLine->xLength;
    stLineCoord[1].xY = 0;

    TDE_vMulMatrixByVertex(&(p_stSuperObject->stModifiedMatrix.a4_xRxS), &stLineCoord[1], &stLineCoord[1]);
    stLineCoord[1].xX += stLineCoord[0].xX;
    stLineCoord[1].xY += stLineCoord[0].xY;

    lFirstPointX = TDE_M_ValueToLong(stLineCoord[0].xX);
    lFirstPointY = TDE_M_ValueToLong(stLineCoord[0].xY);

    lSecondPointX = TDE_M_ValueToLong(stLineCoord[1].xX);
    lSecondPointY = TDE_M_ValueToLong(stLineCoord[1].xY);

    TDE_vDrawLine16(p_stViewAttrib, lFirstPointX, lFirstPointY, lSecondPointX, lSecondPointY, p_stLine->lColor);    
}
