/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = XFORMS.C
 *
 * DESCRIPTIVE NAME = Contains transform code.
 *
 *
 * VERSION = V2.0
 *
 * DATE        : 03/20/88
 *
 * DESCRIPTION : This file contains PostScript driver transform code.
 *
 *
 * FUNCTIONS - utl_MemIsEqual
 *           - prdg_PointIsValid
 *           - prdg_NotifyTransformChange
 *           - prdg_GetDCOrigin
 *           - prdg_DeviceSetDCOrigin
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#include "inc\prdinclt.h"
#include "inc\prdgextf.h"
#include "inc\utl.h"
#include "inc\prdmath.h"
#include "inc\prderre.h"
#include "inc\pspagtun.h"             /* V2.174057  Page Tuning */


#define  CVTC_WORLD      1L
#define  CVTC_DEVICE     5L
#define  SIXTEENBITS_MAX 32767L
#define  OD_MEMORY       8L

extern PDDC EnterDriver (PDDC);
extern VOID ExitDriver (PDDC);

/***************************************************************************
 *
 * FUNCTION NAME = utl_MemIsEqual
 *
 * DESCRIPTION   = Compare two memory regions
 *
 * INPUT         = PB pb1 - Ptr to first memory region
 *                 PB pb2 - Ptr to the second memory region
 *                 int nb - The number of bytes to compare
 *
 * OUTPUT        = BOOL
 *
 * RETURN-NORMAL = TRUE
 * RETURN-ERROR  = FALSE
 *
 ****************************************************************************/

BOOL utl_MemIsEqual (PB pb1, PB pb2, int nb)

/*
** PB pb1;      Ptr to first memory region
** PB pb2;      Ptr to the second memory region
** int nb;      The number of bytes to compare
*/
{

  while (--nb >= 0)
  {
    if (*pb1++ != *pb2++)
    {
      return (FALSE);
    }
  }
  return (TRUE);
}


/***************************************************************************
 *
 * FUNCTION NAME = prdg_NotifyTransformChange
 *
 * DESCRIPTION   = The engine calls this routine when the transformation
 *                 matrix has been changed.
 *
 * INPUT         = HDC hdc
 *                 ULONG ulFlags
 *                 PNOTIFYTRANSFORMDATA pntdData
 *                 PDDC pddc
 *                 ULONG FunN
 *
 * OUTPUT        = ULONG
 *
 * RETURN-NORMAL = SUCCESS
 * RETURN-ERROR  = FAILURE
 *                                                                    
 *                                                                    
 *                                                                    
 *
 **************************************************************************/

ULONG prdg_NotifyTransformChange (HDC hdc, ULONG ulFlags,
                                  PNOTIFYTRANSFORMDATA pntdData,
                                  PDDC pddc, ULONG FunN)
{
  MATRIX mxTransform;        /* Holds a transform in MATRIX format          */
  POINTL ptlCurrentPosition; /* Holds transformed current position          */
  XFORM  xformSave;
  ULONG  ulRet;

  EnterDriver (pddc);

  #if      DEBUG
    LogCall ("prdg_NotifyTransformChange()\n", ((PB)&hdc)+sizeof(hdc));
  #endif

  if (pddc->iType == OD_MEMORY)
  {
    if (!(ulRet = InnerGreSetModelXform (pddc->hdcMemory, &pntdData->xform,
                                         SX_OVERWRITE,
                                         (FunN & 0xFFFF0000) | NGreSetModelXform)))
    {
      RIP ("Prdl_NotifyTransformChange: GreSetModelXform failed");
    }
    else
    {
      ulRet = (*pfnlNotifyTransformChange) (hdc, ulFlags, pntdData, pddc,
                                            FunN);
    }

    ExitDriver (pddc);
    return (ulRet);
  }

  PrintLog ((PSZ)"flags = %08lx\n", ulFlags);
  PrintLog ((PSZ)"Matrix = [%f %f %f %f %ld %ld]\n", pntdData->xform.fxM11,
            pntdData->xform.fxM12, pntdData->xform.fxM21, pntdData->xform.fxM22,
            pntdData->xform.lM41, pntdData->xform.lM42);

  /*
  ** Don't do anything unless the transform has actually changed
  */
  if (utl_MemIsEqual ((PB) &pddc->pddcb->xformCTM, (PB) &pntdData->xform,
                      sizeof (pntdData->xform)))
  {
    ExitDriver (pddc);
    return (SUCCESS);
  }

  xformSave = pddc->pddcb->xformCTM;

  #if      DEBUG
    PrintLog ((PSZ)"The existing current position is %ld,%ld\n",
              pddc->pddcb->pen.ptlCur.x, pddc->pddcb->pen.ptlCur.y);

    if (!pddc->pddcb->bounds.fInit)
    {
      PrintLog ((PSZ)
         "Existing bounds xleft-xright-ytop-ybottom is %ld,%ld,%ld,%ld\n",
         pddc->pddcb->bounds.rcl.xLeft, pddc->pddcb->bounds.rcl.xRight,
         pddc->pddcb->bounds.rcl.yTop, pddc->pddcb->bounds.rcl.yBottom);
    }
    else
    {
      PrintLog ((PSZ)"Bounds haven't been initialized\n");
    }
  #endif

  /*
  ** Now install the new transform we've been given.
  */
  pddc->pddcb->xformCTM.fxM11 = pntdData->xform.fxM11;
  pddc->pddcb->xformCTM.fxM12 = pntdData->xform.fxM12;
  pddc->pddcb->xformCTM.fxM21 = pntdData->xform.fxM21;
  pddc->pddcb->xformCTM.fxM22 = pntdData->xform.fxM22;
  pddc->pddcb->xformCTM.lM41  = pntdData->xform.lM41;
  pddc->pddcb->xformCTM.lM42  = pntdData->xform.lM42;

  /*
  ** Check to see if the current position will overflow
  */
  /*
  **    if (!prdg_PointIsValid(pddc, pddc->pddcb->pen.ptlCur.x, pddc->pddcb->pen.ptlCur.y))
  **        goto RESTORE_TRANSFORM;
  */
  /*
  ** If all is well thus far, then hook back to the engine
  ** so it may perform optimizations or what not.
  */
  if ((*pfnlNotifyTransformChange) (hdc, ulFlags, pntdData, pddc, FunN))
  {
    /*
    **        if (!pddc->fHeaderSent) **  because you can't possibly output **
    **        {                       **  the transf matrix                 **
    **          return (SUCCESS);     **  it would be done at startdoc time **
    **        }
    */

    ps_setmatrix(pddc, (FIXED FAR *) &pntdData->xform);

    /*
    ** when the transform changes, force the pattern filling to be
    ** re-loaded so it knows of the change.
    */
    /*
    ** PTR : B724529                  RAVI : 09/07/91
    ** THE PATTERN FILL FOR THE PATTERNS PATSYM_HORIZ, PATSYM_VERT AND
    ** PATSYM_DIAG1 THRU PATSYM_DIAG4 WILL BE DRAWN AT PRINTER PEL
    ** (DEVICE COORDINATES).
    ** HENCE, THE THESE PATTERN FILL WILL NO LONGER BE DEPENDENT ON
    ** CTM AND XFX VALUE.
    **                                                            
    */
    /*
    ** ADDED FOR PTR @107  D. WALKER. 8-30-91
    ** WE ARE USING THE FIRST VALUE IN THE MATRIX TO SET THE FILL VALUE
    ** FOR THE CURRENT PATH.  THIS IS FINE UNLESS THE USER (APPLICATION)
    ** SETS THE MATRIX TO NULL OR IN EFFECT NO CHANGE.  IN THIS INSTANCE THIS
    ** VALUE IS 0.  SINCE XFX IS USED IN A DIVIDE OPERATION THIS CAN PRODUCE
    ** DISASTEROUS RESULTS (DIVIDING BY 0 IS A SIN).  THE SOLUTION IS TO FILTER
    ** OUT ZEROS, AND SINCE THE MATRIX DOES'NT CHANGE ANYWAY THIS HARMS NOTHING.
    **                                                             
    */
    /*
    ** if (pddc->pddcb->xformCTM.fxM11 != 0)
    **     PrintChannel(pddc, (PSZ)"/xfx %f def\n", pddc->pddcb->xformCTM.fxM11);
    **
    **
    ** pddc->pddcb->pat.usfFontLoaded &= !BASEPATLOADED;
    **
    */
    if (!ps_status (pddc))
    {
      goto RESTORE_TRANSFORM;
    }

    ExitDriver (pddc);
    return (SUCCESS);
  }

  /*
  **  Fall through to restore the transform
  */
RESTORE_TRANSFORM:

  pddc->pddcb->xformCTM = xformSave;
  ps_setmatrix (pddc, (FIXED FAR *) &pntdData->xform);
  ExitDriver (pddc);
  return (FAILURE);
}


/***************************************************************************
 *
 * FUNCTION NAME = prdg_GetDCOrigin
 *
 * DESCRIPTION   = This routine returns the DC origing (always zero).
 *
 * INPUT         = HDC hdc
 *                 PPOINTL pptl
 *                 PDDC pddc
 *                 ULONG ifn
 *
 * OUTPUT        = ULONG
 *
 * RETURN-NORMAL = SUCCESS
 * RETURN-ERROR  =
 *
 ****************************************************************************/


ULONG prdg_GetDCOrigin (HDC hdc, PPOINTL pptl, PDDC pddc, ULONG ifn)
{
  EnterDriver (pddc);

  /*
  ** DC origin is always Zero fo all DCs.
  */
  pptl->x = 0L;
  pptl->y = 0L;

  ExitDriver (pddc);
  return (SUCCESS);
}


/***************************************************************************
 *
 * FUNCTION NAME = prdg_DeviceSetDCOrigin
 *
 * DESCRIPTION   = This routine simply returns success.  We always leave the
 *                          DC origin at (0,0).
 *
 * INPUT         = HDC hdc
 *                 PPOINTL pptl
 *                 PDDC pddc
 *                 ULONG   FunN
 *
 * OUTPUT        =
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

ULONG prdg_DeviceSetDCOrigin (HDC hdc, PPOINTL pptl, PDDC pddc, ULONG FunN)
{
  EnterDriver (pddc);

  /*
  ** DC origin is always Zero fo all DCs.
  */
  #if      DEBUG
    LogCall("prdl_SetDcOrigin(%08lx, %lp, %lp, %08lx)", ((PB)&hdc)+sizeof(hdc));
  #endif

  PrintLog ((PSZ) "pptl = {%ld, %ld}\n", pptl->x, pptl->y);

  /*
  ** We don't have do do anything here because its all done
  ** through the transform mechanism.
  */
  ExitDriver (pddc);
  return (SUCCESS);
}
