/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*                                                                    */
/*   Module          = EDDGCONV                                       */
/*                                                                    */
/*   Description     = Display Device Driver Subroutine call          */
/*                     Convert                                        */
/*                                                                    */
/*   Function        = Acts as a common interface to the Graphics     */
/*                     Engine Convert function handler for all        */
/*                     Display Device Driver routines.                */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
#define INCL_DDICOMFLAGS
#define INCL_GRE_XFORMS
#include <eddinclt.h>

#include <edddcone.h>
#include <edddtypt.h>
#include <eddgextf.h>

extern PPFNL            EnginesDispatchTable;
extern DDTType          DDT;


/**********************************************************************/
/* Convert converts co-ordinates between two coordinate spaces.       */
/*                                                                    */
/* Supported spaces are : World, Model, Default Page, Page, Device    */
/*                        and AI.                                     */
/*                                                                    */
/* The source and target co-ordinates may be stored as Words or Dwords*/
/*                                                                    */
/* The engine function is only called if the COM_TRANSFORM bit is set.*/
/*                                                                    */
/* The source data buffer is left unchanged (unless the same as the   */
/* target buffer)                                                     */
/**********************************************************************/
USHORT DRIVERCALL eddg_Convert (PULONG      SourceXY,
                                PULONG      TargetXY,
                                USHORT      Source,
                                USHORT      Target,
                                USHORT      n,
                                ULONG       command)
{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG              i;              /* loop control variable       */
    WcsPoint           Coord;          /* Dummy co-ord for calling    */
                                       /* engine with                 */
    /******************************************************************/
    /* Convert each pair of co-ordinates separately.                  */
    /*                                                                */
    /* NB, the engine function can convert multiple pairs, but this   */
    /* facility is not used to avoid allocating/freeing memory or     */
    /* overwritting the given data.                                   */
    /******************************************************************/
    for (i = 0; i < n; i++)
    {
        /**************************************************************/
        /* Put Source co-ordinate into temporary value                */
        /**************************************************************/
        if (Source & COORDS_ARE_WORDS)
        {
            /**********************************************************/
            /* Source co-ordinates stored as words                    */
            /**********************************************************/
            Coord.X = (LONG) (((PSHORT)SourceXY)[2*i]);
            Coord.Y = (LONG) (((PSHORT)SourceXY)[2*i+1]);
        }
        else
        {
            /**********************************************************/
            /* Source co-ordinates stored as dwords.                  */
            /**********************************************************/
            Coord.X = SourceXY[i*2];
            Coord.Y = SourceXY[i*2+1];
        }

        /**************************************************************/
        /* If source co-ordinates are AI then first convert to Device */
        /**************************************************************/
        if (Source & COORDS_ARE_AI)
        {
            Coord.Y = (LONG)pdc->DCIConvFactor - Coord.Y;
            Coord.X = Coord.X - (LONG)pdc->DCIOrigin.X;
        }

        /**************************************************************/
        /* Call engine convert function only if COM_TRANSFORM bit set */
        /* and different coordinate types are required                */
        /**************************************************************/
        if ( (!pdc->DCIXFrmSimple) &&
             (command & COM_TRANSFORM) &&
             ( (Source & COORDS_TYPE) != (Target & COORDS_TYPE) ) )
        {
            if ( OK != EnginesDispatchTable[NGreConvert & 0xff](
                                          pdc->DCIhdc,
                                          (ULONG)(Source & COORDS_TYPE),
                                          (ULONG)(Target & COORDS_TYPE),
                                          (pWcsPoint)&Coord,
                                          1,
                                          pdc,
                                          NGreConvert) )
            {
                return(ERROR_ZERO);
            }
        }

        /**************************************************************/
        /* If target co-ordinates are AI then convert from Device     */
        /**************************************************************/
        if (Target & COORDS_ARE_AI)
        {
            Coord.Y = (LONG)pdc->DCIConvFactor - Coord.Y;
            Coord.X = Coord.X + (LONG)pdc->DCIOrigin.X;
        }

        /**************************************************************/
        /* Save converted coordinate in target                        */
        /**************************************************************/
        if (Target & COORDS_ARE_WORDS)
        {
            /**********************************************************/
            /* Check that we are not going to lose any significant    */
            /* bits when we convert from a LONG to a SHORT.           */
            /* We can do this by casting the value to a SHORT, sign-  */
            /* extending it to a LONG, and then comparing the top     */
            /* 16 bits with the original 16 bits. If the upper bits   */
            /* are different then we are going to lose information    */
            /* when converting to a SHORT.                            */
            /**********************************************************/
            if ( ( HIUSHORT(Coord.X) !=
                                   HIUSHORT((LONG)((SHORT)Coord.X)) ) ||
                 ( HIUSHORT(Coord.Y) !=
                                   HIUSHORT((LONG)((SHORT)Coord.Y)) ) )
            {
                /******************************************************/
                /* We have an invalid coordinate. Log an error and    */
                /* return.                                            */
                /******************************************************/
                LogError(PMERR_COORDINATE_OVERFLOW);
                return(ERROR_ZERO);
            }

            /**********************************************************/
            /* target co-ordinates stored as words                    */
            /**********************************************************/
            ((PUSHORT)TargetXY)[2*i]   = (USHORT)Coord.X;
            ((PUSHORT)TargetXY)[2*i+1] = (USHORT)Coord.Y;
        }
        else
        {
            /**********************************************************/
            /* target co-ordinates stored as dwords                   */
            /**********************************************************/
            TargetXY[i*2]   = Coord.X;
            TargetXY[i*2+1] = Coord.Y;
        }
    }

    return(OK);
}


/**********************************************************************/
/* FastConvert is an optimized version of Convert for the following   */
/* situation:                                                         */
/*          Source values are in World co-ordinates and               */
/*            stored as Dwords                                        */
/*          Target values are to be in Device co-ordinates            */
/*            and stored as words                                     */
/*          Multiple pairs of co-ordinates are convertable            */
/*          Conversion is always done (ie no COM_TRANSFORM test)      */
/*                                                                    */
/* FastConvert does the convertting itself, without calling the       */
/* graphics engine                                                    */
/**********************************************************************/
USHORT DRIVERCALL eddg_FastConvert (pWcsPoint       SourceXY,
                                    pDevPoint       TargetXY,
                                    USHORT          n)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG         i;                   /* loop control variable       */
    LONG          temp;                /* conversion variable         */

    /******************************************************************/
    /* Do conversion                                                  */
    /******************************************************************/
    for (i = 0; i < n; i++, TargetXY++, SourceXY++)
    {
        temp = (LONG)pdc->DCITransform.fxM11 * (LONG)SourceXY->X +
               (LONG)pdc->DCITransform.fxM12 * (LONG)SourceXY->Y;
        TargetXY->X = (USHORT)(temp + (LONG)pdc->DCITransform.lM41);
        temp = (LONG)pdc->DCITransform.fxM21 * (LONG)SourceXY->X +
               (LONG)pdc->DCITransform.fxM22 * (LONG)SourceXY->Y;
        TargetXY->Y = (USHORT)(temp + (LONG)pdc->DCITransform.lM42);
    }

    return(OK);
}
