/*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 = BOUNDS.C
 *
 * DESCRIPTIVE NAME = Contains bounds related routines.
 *
 *
 * VERSION = V2.0
 *
 * DATE      04/19/88
 *
 * DESCRIPTION  This file contains AccumulateBounds, GetBoundsData, ResetBounds,
 *              ExpandBounds and support routines.
 *
 * FUNCTIONS
 *
 *    prdl_AccumulateBounds This routine causes the driver to add an additional
 *    prdl_GetBoundsData    Returns the current bounds rectangle
 *    prdl_ResetBounds()    This routine resets the driver's bounds accumulation.
 *    prdl_ExpandBounds()   The bounds rectangle in the DC instance is stretched
 *
 *
 *
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

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

#define  OD_MEMORY  8L
extern PDDC EnterDriver(PDDC);
extern VOID ExitDriver(PDDC);
/***************************************************************************
 *
 * FUNCTION NAME = prdl_AccumulateBounds
 *
 * DESCRIPTION   = This routine causes the driver to add an additional
 *                 rectangle to the bounds that its accumulating.
 *
 * INPUT         = hdc, prcl, pddc, FunN
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = SUCCESS
 *
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

ULONG prdg_AccumulateBounds( HDC hdc, PRECTL prcl, PDDC pddc, ULONG FunN )
  /* HDC hdc;                              The dc handle                     */
  /* PRECTL prcl;                          Ptr to the rectangle to add to    */
  /*                                       the bounds                        */
  /* PDDC pddc;                            Ptr to the DC instance data       */
{
  ULONG tl;

  EnterDriver( pddc);

  #if      DEBUG
    LogCall( "prdg_AccumulateBounds(%08lx, %lp, %lp, %08lx)\n",
             ((PB)&hdc)+sizeof(hdc) );
  #endif                                 /* DEBUG */

  /*
  ** dispatch to gre in case of memory dc
  */
  if (pddc->iType == OD_MEMORY)
  {
    tl = GreAccumulateBounds(pddc->hdcMemory, prcl );
    ExitDriver( pddc );
    return( tl );
  }

  /*
  ** Enable bounds accumulation if COM_BOUND is turned on.
  */
  pddc->pddcb->bounds.fAccumulate = (FunN) &COM_BOUND;

  /*
  ** Expand the bounds rectangle so that two corners on a diagnal
  ** of the new rectangle are contained in it.
  */
  prdl_ExpandBounds( pddc, prcl->xLeft, prcl->yTop );
  prdl_ExpandBounds( pddc, prcl->xRight, prcl->yBottom );
  ExitDriver( pddc );
  return( SUCCESS );
}

/***************************************************************************
 *
 * FUNCTION NAME = prdl_GetBoundsData
 *
 * DESCRIPTION   = Returns the current bounds rectangle
 *
 *                 This routine returns the current bounds rectangle that
 *                 the driver has been accumulating.  A default rectangle
 *                 is returned if no bounds data has been accumulated yet.
 *
 * INPUT         = hdc, ulStyle, prcl, pddc, FunN
 *
 * OUTPUT        = NONE
 * RETURN-NORMAL = SUCCESS
 *
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

ULONG prdg_GetBoundsData( HDC hdc, ULONG ulStyle, PRECTL prcl, PDDC pddc, ULONG FunN )
  /* HDC hdc;                              The dc handle                     */
  /* ULONG ulStyle;                        The bounds style (Gpi or User)    */
  /* PRECTL prcl;                          Place to put the bounds rectangle */
  /* PDDC pddc;                            Ptr to the DC instance data       */
{
  ULONG tl;

  EnterDriver( pddc );

  #if      DEBUG
    LogCall( "prdg_GetBoundsData(%08lx, %d, %lp, %lp, %08lx)\n",
             ((PB)&hdc)+sizeof(hdc) );
  #endif                                 /* DEBUG */

  /*
  ** dispatch to gre in case of memory dc
  */
  if (pddc->iType == OD_MEMORY)
  {
    tl = GreGetBoundsData(pddc->hdcMemory, ulStyle,prcl );
    ExitDriver( pddc );
    return( tl );
  }

  /*
  ** Check to see if any information has been deposited in the
  ** bounds rectangle.  If not, then return a default bounds
  ** rectangle IS empty.  Otherwise the driver just returns a copy
  ** of the bounds rectangle that the driver accumulated.
  */
  if (pddc->pddcb->bounds.fInit)
  {
    prcl->xLeft   = pddc->pdv->canvas.rcl.xLeft;
    prcl->yTop    = pddc->pdv->canvas.rcl.yTop;
    prcl->xRight  = pddc->pdv->canvas.rcl.xRight;
    prcl->yBottom = pddc->pdv->canvas.rcl.yBottom;
  }
  else
  {
    prcl[0] = pddc->pddcb->bounds.rcl;
  }

  ExitDriver( pddc );
  return( SUCCESS );
}

/***************************************************************************
 *
 * FUNCTION NAME = prdl_ResetBounds( )
 *
 * DESCRIPTION   = This routine resets the driver's bounds accumulation.
 *
 * INPUT         = hdc, ArgFlags, pddc, FunN
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = SUCCESS
 *
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

ULONG prdg_ResetBounds( HDC hdc, Dword ArgFlags, PDDC pddc, Dword FunN )
  /* PDDC pddc;                           Ptr to the DC instance data       */
{
  EnterDriver( pddc );

  /*
  ** dispatch to gre in case of memory dc
  */
  if (pddc->iType == OD_MEMORY)
  {
    GreResetBounds( pddc->hdcMemory, ArgFlags );
    ExitDriver( pddc );
    return( SUCCESS );
  }

  /*
  ** Just set the initialize bounds flag.
  */
  pddc->pddcb->bounds.fInit = TRUE;

  ExitDriver( pddc );
  return( SUCCESS );
}

/***************************************************************************
 *
 * FUNCTION NAME = prdl_ExpandBounds( )
 *
 * DESCRIPTION   = The bounds rectangle in the DC instance is stretched
 *
 *                 This routine is the essential primative for
 *                 implementing accumulate bounds.  The bounds
 *                 rectangle in the DC instance is stretched so
 *                 that it contains the new point passed in as
 *                 a parameter.
 *
 * INPUT         = pddc, x, y
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

void prdl_ExpandBounds( PDDC pddc, LONG x, LONG y )
{
  PRECTL prcl;

  /*
  ** If bounds accumulation is turned off, do nothing.
  */
  if (!pddc->pddcb->bounds.fAccumulate)
  {
    return;
  }

  /*
  ** Get a temporary pointer to the bounds rectangle.
  */
  prcl = &pddc->pddcb->bounds.rcl;

  /*
  ** If this is the first time that bounds accumulation has been
  ** done, then the bounds rectangle is initialized to be empty
  ** and centered at the given point.
  ** If there is already a valid bounds rectangle, then it is
  ** expanded if the point lies outside of it.
  */
  if (pddc->pddcb->bounds.fInit)
  {
    pddc->pddcb->bounds.fInit = FALSE;
    prcl->xLeft = x;
    prcl->xRight = x;
    prcl->yTop = y;
    prcl->yBottom = y;
  }
  else
  {
    if (x < prcl->xLeft)
    {
      prcl->xLeft = x;
    }
    else if (x > prcl->xRight)
    {
      prcl->xRight = x;
    }

    if (y < prcl->yBottom)
    {
      prcl->yBottom = y;
    }
    else if (y > prcl->yTop)
    {
      prcl->yTop = y;
    }
  }
}
