/****
 *
 * Copyright (c) 1988 by Sun Microsystems, Inc.
 * @(#)sh_PATH.h 22.1 89/08/10 Copyright 1988 Sun Micro
 *
 * PATH.H - PATH object information
 *
 ****/
#ifndef	_SH_CLASS_PATH

/*
 * PATH attributes.
 */
typedef enum
  {
   PATH_TYPE,		/* type of path */
   PATH_ORG,		/* origin of path bounding box */
   PATH_DIM,		/* dimensions of path bounding box */
   PATH_STATUS,		/* path status */
   PATH_SIZE,		/* path size */
   PATH_AREA_SIZE,	/* path area size */
  } PATH_attr;

#define PATH_ATTRS	((int) PATH_DIM)

/*
 * PATH types.
 */
#define	PATH_GENERIC	0
#define	PATH_IMMEDIATE	1

typedef Unsgn8 PATH_type;

/*
 * Clear_Path arguments, path status values
 */
#define	PATH_EMPTY	0	/* no geometry, no area */
#define	PATH_AREA	1	/* clear area */
#define	PATH_GEOMETRY	2	/* clear only geometry */
#define	PATH_INIT	4	/* reset geometry */
#define	PATH_ALL	3	/* clear geometry, clear area */
#define	PATH_RESET	5	/* reset geometry, clear area */

/*
 * PATH_STATUS bit values
 *
 * PATH_AREA		set if path has area
 * PATH_GEOMETRY	set if path has area
 * PATH_AREA_RECT	set if path area is rectangular
 *
 * otherwise, value is PATH_EMPTY
 */
#define	PATH_AREA_RECT	4	/* path area is rectangular */

/*
 * Path file information
 */
#define	PATH_FILE_NAME	0	/* file name specified */
#define	PATH_FILE_FD	1	/* file descriptor specified */
#define	PATH_FILE_NOCLOSE 2	/* don't close file */

/*
 * Read_Path information
 *
 * PATH_ITEM		generic path item
 * PATH_ITEM_TYPE	type of path item (any opcode)
 * PATHREADER		path readback handle
 *
 * Path_Item_Type(pi)	returns opcode (PATH_ITEM_TYPE) of path item
 * Path_Item_Point(pi)	returns 1 if path item is point, else 0
 */
#define	PATH_READ_POINTS 0	/* read all opcodes */
#define	PATH_READ_ALL	1	/* read only points */
#define	PATH_READ_AREA	2	/* read path area */
#define	PATH_READ_ABORT	3	/* abort path readback */

typedef struct { Unsgn32 t; } PATH_ITEM_TYPE;

/*
 * Apply_Path arguments
 * CTX_APPLY_MODEL	apply model transform
 * CTX_APPLY_VIEW	apply view transform
 * CTX_APPLY_VDC	apply vdc transform
 * CTX_APPLY_CLIP	apply view clip (clip to view volume)
 * CTX_APPLY_LINE_STYLE	apply line pattern (dash the path)
 * CTX_APPLY_LINE_SIZE	apply line size (widen the path)
 * CTX_APPLY_FLATNESS	apply flatness (flatten the path)
 */
#define	CTX_APPLY_LINE_STYLE	0x20
#define	CTX_APPLY_LINE_SIZE	0x40
#define	CTX_APPLY_FLATNESS	0x80

/*
 * Curve forms
 */
typedef enum
  {
   PATH_CURVE_BEZIER,		/* Bezier curves */
   PATH_CURVE_BSPLINE,		/* B-spline curves */
  } PATH_curve_form;

#define	PATH_CURVE_MAX_ORDER	4
#ifdef	LITTLEENDIAN
typedef struct
  {
   unsigned short  t, dd ;
   PATH_curve_form form : 8;
   unsigned char   order;
  } PATH_ITEM_CURVE;
#else	/* LITTLEENDIAN */
typedef struct
  {
   unsigned short  dd, t;
   PATH_curve_form form : 8;
   unsigned char   order;
  } PATH_ITEM_CURVE;
#endif	/* LITTLEENDIAN */

/*
 * PATH flags
 * PT_FLT2D (4, float) and PT_BIN3D (1, 3D) must be the values
 * of PATH_HAS_3D and PATH_HAS_FLOAT so they can be or-ed in
 * for dispatching later.
 */
#define	PATH_HAS_CLOSE	2
#define	PATH_HAS_3D	PT_BIN3D
#define	PATH_HAS_FLOAT	PT_FLT2D

typedef union
  {
   PATH_ITEM_TYPE type;
   COLOR 	  color;
   POINT 	  point;
   short	  rect;
   PATH_ITEM_CURVE curve;
  } PATH_ITEM;

#define	Path_Item_Type(pi) (((PATH_POINT *) (pi))->b.t)
#define	Path_Item_Point(pi) (Path_Item_Type(pi) < PT_OP_MAX)

/*
 * External PATH operators.
 *
 * Next_Path((PATHREADER *) pr)		read next path item
 *
 * PATH Create_Path()			create a PATH object
 * Destroy_Path(path)			destroy a path
 * Get_Path(path, attr)			get path attribute
 * Set_Path(path, attr, val)		set path attribute
 * Clear_Path(path,what)		remove all elements from the path
 * Transform_Path(path, trans)		transform path
 * Union_Path(dst, src1, src2)		union paths
 * Intersect_Path(dst, src1, src2)	intersect paths
 * Differ_Path(dst, src1, src2)		difference paths
 * Area_Path(path, obj)			find area of path w/r to ctx or ras
 * Read_Path(path, pr, how)		setup for path readback
 * Display_Path(path, ctx)		display path in context
 * Copy_Path(src, dst, what)		make copy of path
 * Overlap_Path(path1, path2)		determine if paths overlap
 * PointIn_Path(path, pt)		determine if point within path
 * Translate_Path(path, pt)		translate path by point.
 * ReadFile_Path(path, file, opt)	read path from file
 * WriteFile_Path(path, file, opt)	write path into file
 *
 * Print_Path(path, what)		print path elements and/or area
 * Extend_Path(path, size)		extend path data area
 * Update_Path(path, ctx)		update untransformed path points
 * Inside_Path(path, org, dim)		check if box inside path area
 * Attach_Path(path, ctx)		attach path to coontext
 * Pen_Path(path, point)		return last pen position untransformed
 * RasterPen_Path(path, point)		return last pen position transformed
 */
#define	PATH_OP_Destroy		0
#define	PATH_OP_Init		1
#define	PATH_OP_Get		2
#define	PATH_OP_Set		3
#define	PATH_OP_Print		4
#define	PATH_OP_Clear		5
#define	PATH_OP_Transform	6
#define	PATH_OP_Union		7
#define	PATH_OP_Intersect	8
#define	PATH_OP_Differ		9
#define	PATH_OP_Area		10
#define	PATH_OP_Read		11
#define	PATH_OP_Copy		12
#define	PATH_OP_Overlap		13
#define	PATH_OP_PointIn		14
#define PATH_OP_Translate	15

#define	PATH_OP_Inside		16
#define	PATH_OP_Attach		17
#define	PATH_OP_Extend		18
#define	PATH_OP_ReadFile	19	
#define	PATH_OP_WriteFile	20
#define	PATH_OP_Pen		21
#define	PATH_OP_RasterPen	22
#define	PATH_OP_Apply		23
#define	PATH_OP_ReadArea	24
#define	PATH_OP_Clone		25
#define	PATH_OPERS		26

#define	Create_Path	sh_Create_Path
#define	Temp_Path	sh_Temp_Path
extern	PATH	sh_Create_Path();
extern	PATH	sh_Temp_Path();

#define	Destroy_Path(p)		Destroy_Obj(p)
#define	Next_Path(pr)		(*((pr)->prd_func))(pr)
#define	Clear_Path(p,w)		((void) GetOper_Obj(p, PATH_OP_Clear)(p,w))
#define	Transform_Path(p,t)	((PATH) GetOper_Obj(p, PATH_OP_Transform)(p,t))
#define	Union_Path(p,a,b)	((PATH) GetOper_Obj(p, PATH_OP_Union)(p,a,b))
#define	Differ_Path(p,a,b)	((PATH) GetOper_Obj(p, PATH_OP_Differ)(p,a,b))
#define	Area_Path(p,o)		((PATH) GetOper_Obj(p, PATH_OP_Area)(p,o))
#define	Read_Path(p,r,h)	((void) GetOper_Obj(p, PATH_OP_Read)(p,r,h))
#define	Copy_Path(s,d,w)	((PATH) GetOper_Obj(s, PATH_OP_Copy)(s,d,w))
#define	Clone_Path(s,d)		((PATH) GetOper_Obj(s, PATH_OP_Clone)(s,d))
#define	ReadFile_Path(p,f,o)	((PATH) GetOper_Obj(p, PATH_OP_ReadFile)(p,f,o))
#define	ReadArea_Path(p,f,n)	((int) GetOper_Obj(p, PATH_OP_ReadArea)(p,f,n))
#define	WriteFile_Path(p,f,o)	((PATH) GetOper_Obj(p, PATH_OP_WriteFile)(p,f,o))
#define	Intersect_Path(p,a,b)	((PATH) GetOper_Obj(p, PATH_OP_Intersect)(p,a,b))

#define	Print_Path(p,w)		((void) GetOper_Obj(p, PATH_OP_Print)(p,w))
#define	Extend_Path(p,s)	((PATH) GetOper_Obj(p, PATH_OP_Extend)(p,s))
#define	Inside_Path(p,o,d)	((PATH) GetOper_Obj(p, PATH_OP_Inside)(p,o,d))
#define	Attach_Path(p,c)	((PATH) GetOper_Obj(p, PATH_OP_Attach)(p,c))
#define	Overlap_Path(p1,p2)	((int) GetOper_Obj(p1, PATH_OP_Overlap)(p1,p2))
#define	PointIn_Path(p,pt)	((int) GetOper_Obj(p, PATH_OP_PointIn)(p,pt))
#define	Translate_Path(p,pt)	((void) GetOper_Obj(p, PATH_OP_Translate)(p,pt))
#define	Pen_Path(p,pen)		((int) GetOper_Obj(p, PATH_OP_Pen)(p,pen))
#define	RasterPen_Path(p,pen)	((int) GetOper_Obj(p, PATH_OP_RasterPen)(p,pen))
#define	Apply_Path(s,d,c,w)	((PATH) GetOper_Obj(s, PATH_OP_Apply)(s,d,c,w))

#ifdef	NO_PATH_IMM
#define	Display_Path(p,c) Path_Raster((c)->CTX_RASTER, p, (c), CTX_RENDER)

#else
#define	Display_Path(p,c) ((((c)->CTX_PATH->PATH_TYPE == PATH_IMMEDIATE) && \
	!Get_Context(c, CTX_EMPTY) &&					    \
	Path_Raster((c)->CTX_RASTER, (c)->CTX_PATH, (c), CTX_RENDER)),	    \
	Path_Raster((c)->CTX_RASTER, p, (c), CTX_RENDER))
#endif

/****
 *
 * Update_Path(path, ctx)
 * Transform the non-transformed contents of current path by
 * path construction transform.
 *
 ****/
#ifdef	NO_PATH_IMM
#ifdef	NO_RTM
#define	Update_Path(p,c) { int temp;				\
	if ((p->path_cur = c->ctx_buf_ptr - c->ctx_buf_top) && 	\
	    (p->path_cur > p->path_mark))			\
	  {							\
	   temp = p->path_mark;					\
	   Path_Transform(c->ctx_ctm, p, temp),			\
	   p->path_mark = p->path_cur;				\
	  } }

#else	/* NO_RTM */
#define	Update_Path(p,c) { int temp;				\
	if ((p->path_cur = c->ctx_buf_ptr - c->ctx_buf_top) && 	\
	    !(c->CTX_PIPELINE & CTX_APPLY_RENDER) &&		\
	    (p->path_cur > p->path_mark))			\
	  {							\
	   temp = p->path_mark;					\
	   Path_Transform(c->ctx_ctm, p, temp),			\
	   p->path_mark = p->path_cur;				\
	  } }

#endif	/* NO_RTM */

#else	/* NO_PATH_IMM */
#ifdef	NO_RTM
#define	Update_Path(p,c) { int temp;				\
	if ((p->path_cur = c->ctx_buf_ptr - c->ctx_buf_top) && 	\
	    ((p)->PATH_TYPE != PATH_IMMEDIATE) &&		\
	    (p->path_cur > p->path_mark))			\
	  {							\
	   temp = p->path_mark;					\
	   Path_Transform(c->ctx_ctm, p, temp),			\
	   p->path_mark = p->path_cur;				\
	  } }

#else	/* NO_RTM */
#define	Update_Path(p,c) { int temp;				\
	if ((p->path_cur = c->ctx_buf_ptr - c->ctx_buf_top) && 	\
	    !(c->CTX_PIPELINE & CTX_APPLY_RENDER) &&		\
	    ((p)->PATH_TYPE != PATH_IMMEDIATE) &&		\
	    (p->path_cur > p->path_mark))			\
	  {							\
	   temp = p->path_mark;					\
	   Path_Transform(c->ctx_ctm, p, temp),			\
	   p->path_mark = p->path_cur;				\
	  } }
#endif	/* NO_RTM */
#endif	/* NO_PATH_IMM */

struct class_PATH
  {
#include "sh_PATH.ah"
  };

typedef struct
  {
   PATH_ITEM	*(*prd_func)();	/* readback function */
   struct obj_hdr prd_obj;	/* path object header */
   struct class_PATH prd_path;	/* path we are reading back */
  } PATHREADER;

/*
 * Get_Path(path, attr)
 * Fast way to access path attributes.
 * This macro depends on the "attr" argument being a compile time constant.
 */
#ifndef	SH_MONITOR

#define	Get_Path(p,a)	CAT(a,get)((PATH)(p))

#else	/* SH_MONITOR */

#define	Get_Path(p,a)	CAT(a,get)((PATH)sh_Monitor_Get_Path(p))

#endif	/* SH_MONITOR */

#define PATH_TYPEget(p)	((p)->PATH_TYPE)
#define PATH_ORGget(p) ((POINT_B2D *) GetOper_Obj(p, PATH_OP_Get)(p, PATH_ORG))
#define PATH_DIMget(p) ((POINT_B2D *) GetOper_Obj(p, PATH_OP_Get)(p, PATH_DIM))
#define PATH_STATUSget(p) ((int) GetOper_Obj(p, PATH_OP_Get)(p, PATH_STATUS))
#define PATH_SIZEget(p) ((int) GetOper_Obj(p, PATH_OP_Get)(p, PATH_SIZE))
#define PATH_AREA_SIZEget(p) \
	((int) GetOper_Obj(p, PATH_OP_Get)(p, PATH_AREA_SIZE))

/* Set_Path is not yet a real operator */

#ifndef	SH_MONITOR

#define	Set_Path(p,a,v)	CAT(a,set)(p,v)

#else	/* SH_MONITOR */

#define	Set_Path(p,a,v)	CAT(a,set)((PATH)sh_Monitor_Set_Path(p),v)

#endif	/* SH_MONITOR */

#define	path_markset(p,v) (p->path_mark = v)
#define PATH_AREA_SIZEset(p,v) GetOper_Obj(p, PATH_OP_Set)(p, PATH_AREA_SIZE, v)
#define PATH_ORGset(p,v)  {POINT_B2D *t; t = (POINT_B2D *)(v); \
				p->PATH_ORG.x = t->x; \
				p->PATH_ORG.y = t->y;}
#define PATH_DIMset(p,v)  {POINT_B2D *t = v; t = (POINT_B2D *)(v); \
				p->PATH_DIM.x = t->x; \
				p->PATH_DIM.y = t->y;}
#define	PATH_SIZEset(p,v) \
	((p->path_end < v) && Extend_Path(p, v * sizeof(PATH_POINT)))

extern	SHAPE	sh_empty_shape;

#define	_SH_CLASS_PATH
#endif	/* _SH_CLASS_PATH */
