/*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.                                */
/*                                                                           */
/*****************************************************************************/
#pragma  pagesize(55)

/**************************************************************************
 *
 * SOURCE FILE NAME =  BOUNDS.C
 *
 * DESCRIPTIVE NAME =  File contains functions dealing with bounds
 *                     accumulation.
 *
 *
 *
 * VERSION = V2.0
 *
 * DATE        09/18/88
 *
 * DESCRIPTION Plotter Driver Functions dealing with bounds accumulation.
 *
 *
 * FUNCTIONS   accumulate_line_bounds Determine the bounding box of the
 *                                    line whose end points are passed
 *
 *             AccumulateBounds()     Add the given bounds
 *
 *             GetBounsdData()        Returns bounds data to user
 *             ResetBounds            Reset either or both of the sets
 *                                    of bounding data.
 *
 *
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#include "plotters.h"
#include "bounds.h"
#include "error.h"
#include "xforms.h"
#include "dispatch.h"

/***************************************************************************
 *
 * FUNCTION NAME = accumulate_line_bounds
 *
 * DESCRIPTION   = Determine the bounding box of the line whose end
 *                 points are passed
 *
 *
 *
 *
 *
 * INPUT         = PDDC      pDDC;
 *                 PPOINTL   pPtsA;
 *                 PPOINTL   pPtsB;
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = The value from AccumulateBounds()
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

BOOL  accumulate_line_bounds ( HDC hDC, PDDC pDDC, PPOINTL pPtsA,
                               PPOINTL   pPtsB )

/*HDC       hDC;           DC handle */
/*PPOINTL   pPtsA;         One end point of line */
/*PPOINTL   pPtsB;         The other end point */
{
  RECTL Bounds;

  /*
  ** Processing is simple.  Determine the lesser of the two x values,
  ** and this determines the xLeft and xRight values of the bouning box.
  ** Similiarly,  the lesser y determines the yBottom and yTop values.
  */

  if (pPtsA->x < pPtsB->x)
  {
    Bounds.xLeft = pPtsA->x;
    Bounds.xRight = pPtsB->x;
  }
  else
  {
    Bounds.xLeft = pPtsB->x;
    Bounds.xRight = pPtsA->x;
  }

  if (pPtsA->y < pPtsB->y)
  {
    Bounds.yBottom = pPtsA->y;
    Bounds.yTop = pPtsB->y;
  }
  else
  {
    Bounds.yBottom = pPtsB->y;
    Bounds.yTop = pPtsA->y;
  }
  return  AccumulateBounds(hDC, &Bounds, pDDC,
                           MAKEULONG(NGreAccumulateBounds,
                           HIUSHORT(COM_TRANSFORM)));/*                  @MV*/
}

/***************************************************************************
 *
 * FUNCTION NAME = AccumulateBounds()
 *
 * DESCRIPTION   = Add the given bounds
 *                 Add the given bounds into the existing bounds,
 *                 extending as required.
 *
 *
 *
 *
 * INPUT         = HDC     hDC;
 *                 PRECTL  pRect;
 *                 PDDC    pDDC;
 *                 ULONG   FunN;
 *
 *
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =  GPI_OK
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

BOOL  AccumulateBounds(HDC hDC,PRECTL pRect,PDDC pDDC,ULONG FunN)
{

  /*
  ** Coordinates are passed to us in device coordinates,  so they need
  ** to be converted to model for GpiBounds.  Other than that,  all
  ** that happens here is to extend the existing bounds to include the
  ** new rectangle,  or to initialise them if reset upon entry.
  */

  RECTL rectlConv;
  ULONG ulReturn;
  if (!EnterDriver(pDDC))
      return(GPI_ERROR);
  /*
  **          In case of MEMORYDC Dispatch to Graphics Engine
  */
  if (pDDC->usDCType == OD_MEMORY)
  {
    ulReturn = GreAccumulateBounds(pDDC->hdcMemory, pRect );
    LeaveDriver( pDDC );
    return( ulReturn );
  }
  rectlConv = *pRect;

  if (FunN & COM_TRANSFORM)
    convert_device_to_model(hDC, &rectlConv, 2L, pDDC);

  /*
  **  GpiBounds are accumulated in model coordinates
  */
  if (pDDC->bGpiBoundsIsReset)
  {
    pDDC->bGpiBoundsIsReset = FALSE;
    pDDC->GpiBounds = rectlConv;
  }
  else
  {
    /*
    ** Extend the existing rectangle - set new value if "bigger"
    */
    if (rectlConv.xLeft < pDDC->GpiBounds.xLeft)
      pDDC->GpiBounds.xLeft = rectlConv.xLeft;

    if (rectlConv.xRight > pDDC->GpiBounds.xRight)
      pDDC->GpiBounds.xRight = rectlConv.xRight;

    if (rectlConv.yTop > pDDC->GpiBounds.yTop)
      pDDC->GpiBounds.yTop = rectlConv.yTop;

    if (rectlConv.yBottom < pDDC->GpiBounds.yBottom)
      pDDC->GpiBounds.yBottom = rectlConv.yBottom;
  }

  /*
  **  UserBounds are accumulated in device coordinates - passed to us
  */
  if (pDDC->bUserBoundsIsReset)
  {
    pDDC->bUserBoundsIsReset = FALSE;
    pDDC->UserBounds = *pRect;
  }
  else
  {
    if (pRect->xLeft < pDDC->UserBounds.xLeft)
      pDDC->UserBounds.xLeft = pRect->xLeft;

    if (pRect->xRight > pDDC->UserBounds.xRight)
      pDDC->UserBounds.xRight = pRect->xRight;

    if (pRect->yTop > pDDC->UserBounds.yTop)
      pDDC->UserBounds.yTop = pRect->yTop;

    if (pRect->yBottom < pDDC->UserBounds.yBottom)
      pDDC->UserBounds.yBottom = pRect->yBottom;
  }
  LeaveDriver(pDDC);
  return  GPI_OK;
}

/***************************************************************************
 *
 * FUNCTION NAME = GetBounsdData()
 *
 * DESCRIPTION   = Returns bounds data to user, units according to
 *                 parameters.
 *
 *
 *
 *
 *
 * INPUT         = HDC     hDC;
 *                 ULONG   Style;
 *                 PRECTL  pBoundsData;
 *                 PDDC    pDDC;
 *                 ULONG   FunN;
 *
 *
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = GPI_OK  Data as requested.
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

LONG  GetBoundsData(HDC hDC,ULONG Style,PRECTL pBoundsData,PDDC pDDC,
                    ULONG FunN)
{
  ULONG ulRet;

  if (!EnterDriver(pDDC))
      return(GPI_ERROR);

  /*
  **          In case of MEMORYDC Dispatch to Graphics Engine
  */
  if (pDDC->usDCType == OD_MEMORY)
  {
    ulRet = GreGetBoundsData(pDDC->hdcMemory, Style,pBoundsData );
    LeaveDriver( pDDC );
    return( ulRet );
  }

  /*
  ** GPI data is returned in model space coordinates,  USER bounds in
  ** device coordinates.  Driver keeps track of both.
  */

  if (Style == GBD_GPI)
    *pBoundsData = pDDC->GpiBounds;
  else
    if (Style == GBD_USER)
      *pBoundsData = pDDC->UserBounds;
  LeaveDriver(pDDC);
  return  GPI_OK;
}

/***************************************************************************
 *
 * FUNCTION NAME = ResetBounds
 *
 * DESCRIPTION   = Reset either or both of the sets of bounding data.
 *
 *
 *
 *
 *
 *
 * INPUT         = HDC     hDC;
 *                 ULONG   Flags;
 *                 PDDC    pDDC;
 *                 ULONG   FunN;
 *
 *
 *
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = GPI_OK    - Function succeeded
 * RETURN-ERROR  = NONE
 *
 **************************************************************************/

LONG  ResetBounds(HDC hDC,ULONG Flags,PDDC pDDC,ULONG FunN)
{

  if (!EnterDriver(pDDC))
      return(GPI_ERROR);

  /*
  **          In case of MEMORYDC Dispatch to Graphics Engine
  */
  if (pDDC->usDCType == OD_MEMORY)
  {
    GreResetBounds( pDDC->hdcMemory, Flags );
    LeaveDriver( pDDC );
    return( 1L );
  }

  if (Flags&RB_GPI)
  {
    /*
    **  GPI bounds - model space
    */
    pDDC->bGpiBoundsIsReset = TRUE;
    pDDC->GpiBounds.xLeft = pDDC->GpiBounds.yBottom = MAX_BOUNDS;
    pDDC->GpiBounds.xRight = pDDC->GpiBounds.yTop = MIN_BOUNDS;
  }

  if (Flags&RB_USER)
  {
    /*
    ** USER bounds - device space
    */
    pDDC->bUserBoundsIsReset = TRUE;
    pDDC->UserBounds.xLeft = pDDC->UserBounds.yBottom = MAX_BOUNDS;
    pDDC->UserBounds.xRight = pDDC->UserBounds.yTop = MIN_BOUNDS;
  }
  LeaveDriver(pDDC);
  return  GPI_OK;
}

