/****
 *
 * Copyright (c) 1988 by Sun Microsystems, Inc.
 * @(#)sh_point.h 22.1 89/08/10 Copyright 1988 Sun Micro
 *
 * POINT.H - Shapes POINT structures and macros
 *
 ****/
#ifndef	_SH_POINT

/*
 * Point Types.
 * The defines below construct the possible values for the type
 * field of a POINT structure. The POINT type contains information
 * on what kind of coordinates and what kind of drawing operation.
 * The low-order 4 bits determine the coordinates, the next highest
 * 4 bits determine the opcode. Although the high order byte of the
 * point type is not currently being used, it is reserved for Shapes
 * future extensions. The high order word of the 32-bit point type
 * is available for device-specific use within PATHs.
 *
 *	07 06 05 04 03 02 01 00
 *	-- -- -- --------------
 *	    | |    |    |  |  |__ 2D/3D
 *	    | |    |    |  |_____ homogeneous
 *	    | |    |    |________ fract/float
 *	    | |    |_____________ opcode (move, line, ...)
 *	    | |__________________ relative/absolute
 *	    |____________________ more opcode
 *
 * Note: The generic implementation of Point_Transform and
 * InversePoint_Transform depends on the order of these bits.
 */
typedef short PT_type;

#define	PT_BIN2D	0	/* binary 2D */
#define	PT_BIN3D	1	/* binary 3D */
#define	PT_BIN2H	2	/* binary 2H */
#define	PT_BIN3H	3	/* binary 3H */
#define	PT_FLT2D	4	/* floating 2D */
#define	PT_FLT3D	5	/* floating 3D */
#define	PT_FLT2H	6	/* floating 2H */
#define	PT_FLT3H	7	/* floating 3H */

/*
 * POINT opcodes
 * PT_REL bit set for relative coordinates
 */
#define	PT_REL		PT_MOVEREL

#define	PT_MOVE		(0<<3)	/* move absolute */
#define	PT_LINE		(1<<3)	/* line absolute */
#define	PT_CURVE	(2<<3)	/* curve */
				/* padding to make rel/abs a bit */
#define	PT_MOVEREL	(4<<3)	/* move relative */
#define	PT_LINEREL	(5<<3)	/* line relative */
#define	PT_VTXNORM	(6<<3)	/* vertex normal vector */
#define	PT_AREANORM	(7<<3)	/* area (polygon) normal vector */
#define	PT_OP_MAX	(8<<3)	/* max opcode */

#define sh_path_op(o,t) ((o) | (t))

#define	Point_Op(p) ((((POINT_B2D *) (p))->t) & 0170)
#define	Point_Type(p) ((((POINT_B2D *) (p))->t) & 07)

/*
 * POINT path items
 */
#define	PT_LINE_B2D	sh_path_op(PT_LINE, PT_BIN2D)
#define	PT_LINE_B3D	sh_path_op(PT_LINE, PT_BIN3D)
#define	PT_LINE_F2D	sh_path_op(PT_LINE, PT_FLT2D)
#define	PT_LINE_F3D	sh_path_op(PT_LINE, PT_FLT3D)
#define	PT_MOVE_B2D	sh_path_op(PT_MOVE, PT_BIN2D)
#define	PT_MOVE_B3D	sh_path_op(PT_MOVE, PT_BIN3D)
#define	PT_MOVE_F2D	sh_path_op(PT_MOVE, PT_FLT2D)
#define	PT_MOVE_F3D	sh_path_op(PT_MOVE, PT_FLT3D)
#define	PT_LINEREL_B2D	sh_path_op(PT_LINEREL, PT_BIN2D)
#define	PT_LINEREL_B3D	sh_path_op(PT_LINEREL, PT_BIN3D)
#define	PT_LINEREL_F2D	sh_path_op(PT_LINEREL, PT_FLT2D)
#define	PT_LINEREL_F3D	sh_path_op(PT_LINEREL, PT_FLT3D)
#define	PT_MOVEREL_B2D	sh_path_op(PT_MOVEREL, PT_BIN2D)
#define	PT_MOVEREL_B3D	sh_path_op(PT_MOVEREL, PT_BIN3D)
#define	PT_MOVEREL_F2D	sh_path_op(PT_MOVEREL, PT_FLT2D)
#define	PT_MOVEREL_F3D	sh_path_op(PT_MOVEREL, PT_FLT3D)
#define	PT_CURVE_B2D	sh_path_op(PT_CURVE, PT_BIN2D)
#define	PT_CURVE_B2H	sh_path_op(PT_CURVE, PT_BIN2H)
#define	PT_CURVE_B3D	sh_path_op(PT_CURVE, PT_BIN3D)
#define	PT_CURVE_F2D	sh_path_op(PT_CURVE, PT_FLT2D)
#define	PT_CURVE_F2H	sh_path_op(PT_CURVE, PT_FLT2H)
#define	PT_CURVE_F3D	sh_path_op(PT_CURVE, PT_FLT3D)
#define	PT_CURVE_B3H	sh_path_op(PT_CURVE, PT_BIN3H)
#define	PT_CURVE_F3H	sh_path_op(PT_CURVE, PT_FLT3H)
#define	PT_VTXNORM_B3D	sh_path_op(PT_VTXNORM, PT_BIN3D)
#define	PT_VTXNORM_F3D	sh_path_op(PT_VTXNORM, PT_FLT3D)
#define	PT_AREANORM_B3D	sh_path_op(PT_AREANORM, PT_BIN3D)
#define	PT_AREANORM_F3D	sh_path_op(PT_AREANORM, PT_FLT3D)

/*
 * COLOR path items
 */
#define COL_INDEX	sh_path_op(PT_OP_MAX, 0)	/* color is an index */
#define COL_RGB		sh_path_op(PT_OP_MAX, 1)	/* color is RGB */
#define COL_HSV    	sh_path_op(PT_OP_MAX, 2)	/* color is HSV */

/*
 * Non-coordinate, non-color PATH items
 */
#define PATH_CLOSE	sh_path_op(PT_OP_MAX, 3)	/* path closure */
#define PATH_CLOSE_SUB	sh_path_op(PT_OP_MAX, 4)	/* subpath closure */
#define PATH_CURVE	sh_path_op(PT_OP_MAX, 5)	/* curve type,order */
#define PT_W		sh_path_op(PT_OP_MAX, 6)	/* homogeneous coord. */
#define PATH_END	sh_path_op(PT_OP_MAX, 7)	/* path end */

/*
 * POINT - typed coordinate data
 * All Shapes points are typed and the following structures are
 * used to represent them. All structures begin with a type field
 * telling what kind of coordinates follow. The X, Y, Z and W
 * coordinates are always in the same place in all structures
 * whether they are integer of floating. The type of a point
 * actually has 2 parts - the coordinate type and the opcode type.
 */
typedef struct { unsigned int t; int   x, y; } POINT_B2D;
typedef struct { unsigned int t; int   x, y, z; } POINT_B3D;
typedef struct { unsigned int t; int   x, y, z, w; } POINT_B2H;
typedef struct { unsigned int t; int   x, y, z, w; } POINT_B3H;
typedef struct { unsigned int t; float x, y; } POINT_F2D;
typedef struct { unsigned int t; float x, y, z; } POINT_F3D;
typedef struct { unsigned int t; float x, y, z, w; } POINT_F2H;
typedef struct { unsigned int t; float x, y, z, w; } POINT_F3H;

typedef union
  {
   POINT_F3H f;
   POINT_B3H b;
   POINT_B3D i;
  } POINT;

/*
 * POSSIBLE PORTABILITY PROBLEM: WORD ORDER.  These definitions work
 * for both little- and big- endian machines. */

#ifdef	SH_SMALL
#ifdef	LITTLEENDIAN
typedef union
  {
   struct { unsigned short t, dd; int x, y; } b;
   struct { unsigned short t, dd; float x, y; } f;
  } PATH_POINT;
#else	/* LITTLEENDIAN */
typedef union
  {
   struct { unsigned short dd, t; int x, y; } b;
   struct { unsigned short dd, t; float x, y; } f;
  } PATH_POINT;
#endif	/* LITTLEENDIAN */
#else	/* SH_SMALL */
#ifdef	LITTLEENDIAN
typedef union
  {
   struct { unsigned short t, dd; int x, y, z; } b;
   struct { unsigned short t, dd; float x, y, z; } f;
  } PATH_POINT;
#else	/* LITTLEENDIAN */
typedef union
  {
   struct { unsigned short dd, t; int x, y, z; } b;
   struct { unsigned short dd, t; float x, y, z; } f;
  } PATH_POINT;
#endif	/* LITTLEENDIAN */
#endif /* SH_SMALL */

/*
 * The following coordinate type is for internal use only, it is not a public
 * coordinate type.
 */
typedef struct { short x, y; } COORD_2D;


/*
 * POINT macros.
 * The macros below define a POINT structure for all possible coordinate
 * types. The points defined by these macros cannot be used with Draw
 * because they have no draw opcodes, only coordinate types.
 *
 * The Point_Ixx and Coord_Ixx macros take integer coordinates
 * and product PT_BINxx points. They are included to make it easier
 * to specify integer coordinates. They do not represent another point type.
 *
 * Point_xxx - initializes point type and all coordinates
 * Coord_xxx - initializes only coordinates, assumes type is OK
 */
#define	Point_B2D(p,a,b) (((POINT_B2D *) p)->t = PT_BIN2D, Coord_B2D(p,a,b))
#define	Point_B3D(p,a,b,c) (((POINT_B3D *) p)->t = PT_BIN3D,\
		Coord_B3D(p,a,b,c))
#define	Point_B3H(p,a,b,c,d) (((POINT_B3H *) p)->t = PT_BIN3H,\
		Coord_B3H(p,a,b,c,d))
#define	Point_F2D(p,a,b) (((POINT_F2D *) p)->t = PT_FLT2D, Coord_F2D(p,a,b))
#define	Point_F3D(p,a,b,c) (((POINT_F3D *) p)->t = PT_FLT3D,\
		Coord_F3D(p,a,b,c))
#define	Point_F3H(p,a,b,c,d) (((POINT_F3H *) p)->t = PT_FLT3H,\
		Coord_F3H(p,a,b,c,d))
#define	Point_I2D(p,a,b) (((POINT_B2D *) p)->t = PT_BIN2D, Coord_I2D(p,a,b))
#define	Point_I3D(p,a,b,c) (((POINT_B3D *) p)->t = PT_BIN3D,\
		Coord_I3D(p,a,b,c))
#define	Point_I3H(p,a,b,c,d) (((POINT_B3H *) p)->t = PT_BIN3H,\
		Coord_I3H(p,a,b,c,d))

#define	Coord_2D(p, a, b) (((COORD_2D *) p)->x = a,\
		((COORD_2D *) p)->y = b, p)
#define	Coord_B2D(p, a, b) (((POINT_B2D *) p)->x = a,\
		((POINT_B2D *) p)->y = b, p)
#define	Coord_B2H(p, a, b, c) (((POINT_B2H *) p)->x = a,\
		((POINT_B2H *) p)->y = b,\
		((POINT_B2H *) p)->w = c, p)
#define	Coord_B3D(p, a, b, c) (((POINT_B3D *) p)->x = a,\
		((POINT_B3D *) p)->y = b,\
		((POINT_B3D *) p)->z = c, p)
#define	Coord_B3H(p, a, b, c, d) (((POINT_B3H *) p)->x = a,\
		((POINT_B3H *) p)->y = b,\
		((POINT_B3H *) p)->z = c,\
		((POINT_B3H *) p)->w = d, p)
#define	Coord_F2D(p, a, b) (((POINT_F2D *) p)->x = a,\
		((POINT_F2D *) p)->y = b, p)
#define	Coord_F2H(p, a, b, c) (((POINT_F2H *) p)->x = a,\
		((POINT_F2H *) p)->y = b,\
		((POINT_F2H *) p)->w = c, p)
#define	Coord_F3D(p, a, b, c) (((POINT_F3D *) p)->x = a,\
		((POINT_F3D *) p)->y = b,\
		((POINT_F3D *) p)->z = c, p)
#define	Coord_F3H(p, a, b, c, d) (((POINT_F3H *) p)->x = a,\
		((POINT_F3H *) p)->y = b,\
		((POINT_F3H *) p)->z = c,\
		((POINT_F3H *) p)->w = d, p)
#define	Coord_I2D(p, a, b) (((POINT_B2D *) p)->x = fracti(a),\
		((POINT_B2D *) p)->y = fracti(b), p)
#define	Coord_I2H(p, a, b, c) (((POINT_B2H *) p)->x = fracti(a),\
		((POINT_B2H *) p)->y = fracti(b),\
		((POINT_B2H *) p)->w = fracti(c), p)
#define	Coord_I3D(p, a, b, c) (((POINT_B3D *) p)->x = fracti(a),\
		((POINT_B3D *) p)->y = fracti(b),\
		((POINT_B3D *) p)->z = fracti(c), p)
#define	Coord_I3H(p, a, b, c, d) (((POINT_B3H *) p)->x = fracti(a),\
		((POINT_B3H *) p)->y = fracti(b),\
		((POINT_B3H *) p)->z = fracti(c),\
		((POINT_B3H *) p)->w = fracti(d), p)

#define	_SH_POINT
#endif	/* _SH_POINT */
