 /*
  * Khoros: $Id: area.c,v 1.2 1991/12/18 09:08:07 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: area.c,v 1.2 1991/12/18 09:08:07 dkhoros Exp $";
#endif

 /*
  * $Log: area.c,v $
 * Revision 1.2  1991/12/18  09:08:07  dkhoros
 * HellPatch3
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.

 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "overlay.h"


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name: area.c
   >>>>               
   >>>>   description: annotation utilities 
   >>>>               
   >>>>      routines:
   >>>>			restore_area
   >>>>			save_area
   >>>>			create_area
   >>>>			destroy_area
   >>>>			fill_area
   >>>>			copy_area
   >>>>			create_region
   >>>>			destroy_region
   >>>>              
   >>>> modifications:
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

extern XObject *obj_list;

/********************************************************
*
*  Routine Name:  restore_area
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


restore_area(widget, gc, object)

Widget	widget;
GC	gc;
XObject	*object;
{
	Display	 *display = XtDisplay(widget);
	Window	 window   = XtWindow(widget);


	if (object->area != NULL)
	{
	   XSetFunction(display, gc, GXcopy);
	   XSetRegion(display, gc, object->region);

	   XCopyArea(display, object->area, window, gc, 0, 0, object->width,
		     object->height, object->x, object->y);
	}
}



/********************************************************
*
*  Routine Name:  save_area
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


save_area(widget, gc, object)

Widget	widget;
GC	gc;
XObject	*object;
{
	Display	 *display = XtDisplay(widget);
	Window	 window   = XtWindow(widget);

	if (object->area == NULL)
	   create_area(widget, object);

	if (object->area != NULL)
	{
	   XSetFunction(display, gc, GXcopy);
	   XSetClipMask(display, gc, None);

	   XCopyArea(display, window, object->area, gc, object->x, object->y,
		     object->width, object->height, 0, 0);
	}
}



/********************************************************
*
*  Routine Name:  create_area
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


create_area(widget, object)

Widget	widget;
XObject	*object;
{
	Display	 *display = XtDisplay(widget);
	Window	 window   = XtWindow(widget);

	Window	  root;
	int	  wx, wy;
	unsigned  int width, height, border_width, depth;

	if (object->area != NULL)
	   destroy_area(widget, object);

	if ( !XGetGeometry(display, window, &root, &wx, &wy, &width, &height,
			   &border_width, &depth))
	{
	   xvf_error_wait("Window does not exist.","create_area", NULL);
	   object->area = NULL;
           return;
        }

	width  = ABS(object->width);
	height = ABS(object->height);
	if (width < 5)
	   width = 5;
	if (height < 5)
	   height = 5;

	object->area = XCreatePixmap(display, window, width, height, depth);

	if ( !XGetGeometry(display, object->area, &root, &wx, &wy, &width,
			   &height, &border_width, &depth))
	{
	   xvf_error_wait("Warning! Unable to create object area.  XObject may \
cause garbage to be displayed to the overlay window.","create_area", NULL);
	   object->area = NULL;
	}
}



/********************************************************
*
*  Routine Name:  destroy_area
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


destroy_area(widget, object)

Widget	widget;
XObject	*object;
{
	Display	 *display = XtDisplay(widget);

	if (object->area != NULL)
	   XFreePixmap(display, object->area);
}



/********************************************************
*
*  Routine Name:  fill_area
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


fill_area(widget, gc, pixel, object)

Widget	 widget;
GC	 gc;
unsigned long pixel;
XObject	 *object;
{
	Display	 *display = XtDisplay(widget);
	unsigned int  width, height;


	if (object->area != NULL)
	{
	   width  = ABS(object->width);
	   height = ABS(object->height);

	   if (object->type == IMAGE)
	      XSetRegion(display, gc, object->region);

	   XSetForeground(display, gc, pixel);
	   XFillRectangle(display, object->area, gc, 0, 0, width, height);
	}
}



/********************************************************
*
*  Routine Name:  copy_area
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


copy_area(widget, gc, object1, object2)

Widget	widget;
GC	gc;
XObject	*object1, *object2;
{
	Display	 *display = XtDisplay(widget);

	int	 x, y, screen = XDefaultScreen(display);
	unsigned int  width, height;

	if (object1->area == NULL)
	   return;

	if (object2->area == NULL)
	{
	   create_area(widget, object2);
	   if (object2->area == NULL) return;
	}

	width  = MIN(object1->width,  object2->width);
	height = MIN(object1->height, object2->height);

	if (object2->width > object1->width)
	   x = object2->width - object1->width/2;
	else
	   x = 0;

	if (object2->height > object1->height)
	   y = (object2->height - object1->height)/2;
	else
	   y = 0;

	fill_area(widget, gc, XBlackPixel(display, screen), object2);
	XCopyArea(display, (Drawable) object1, (Drawable) object2, gc, 0, 0, 
		width, height, x, y);
}



/********************************************************
*
*  Routine Name:  create_region
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


create_region(widget, object)

Widget	widget;
XObject	*object;
{
	int	 rule;
	XPoint	 points[4];

	if (object->region != NULL)
	   destroy_region(widget, object);

	if (((object->type == POLYGON && object->isfilled)
	   || object->type == IMAGE) && object->num > 2)
	{
	   if (object->type == POLYGON)
	      rule = EvenOddRule;
	   else
	      rule = WindingRule;

	   object->region = XPolygonRegion(object->points, object->num, rule);
	}
	else
	{
	   points[0].x = points[3].x = object->x;
	   points[1].x = points[2].x = object->x + object->width;

	   points[0].y = points[1].y = object->y;
	   points[3].y = points[2].y = object->y + object->height;

	   object->region = XPolygonRegion(points, 4, WindingRule);
	}
}




/********************************************************
*
*  Routine Name:  destroy_region
*
*       Purpose:
*
*         Input: 
*
*        Output:
*
*     Called By: internal routine
*
*   Written By:  Mark Young
*
********************************************************/


destroy_region(widget, object)

Widget	widget;
XObject	*object;
{
	if (object->region != NULL)
	   XDestroyRegion(object->region);
}
