/**
 * Vlib is a 3-D aware graphical library.
 * 
 * @file
 */

#ifndef _VLIB_H
#define _VLIB_H

#include <stdlib.h>

#include "Vlibmath.h"
#include "Alib.h"

#ifdef Vlib_IMPORT
	#define EXTERN
#else
	#define EXTERN extern
#endif

/*
 *  Viewport flags (must be changed manually after VOpenViewport for now)
 */

#define	VPClip		1      /* polygons should be clipped before drawing */
#define VPPerspective	2      /* Z coordinate used for depth information */

typedef struct {
	gui_Type * gui;
	Alib_Window  *w;                /* performs 2-D drawing and z-buffer */
	Alib_Rect      rect;             /* view rectangle inside w */
	Alib_Point     focus;            /* infinite sight point (pixel) */
	double    dist;             /* distance from eye to focus (m) */
	Alib_Point     Middl;            /* focus point *4 (pixels) */
	double    xres;             /* x screen resolution (pixels/m) */
	double    yres;             /* y screen resolution (pixels/m) */
	VPoint    Scale;            /* scaling factor *4 */
	int       flags;            /* (see VP* constants above) */
	VMatrix   eyeSpace;         /* transforms from world to eyeSpace system */
	VPolygon *clipPoly;         /* planes to clip viewed polygons */
	VPoint    clipNormals[4];   /* normal vectors corresponding to clipPoly */
} Viewport;


/**
 * Return a new 3-D rectangular area (view_rect) on the given window (w).
 * The focus is the focus of the projection in screen coordinates (pixel).
 * The distance of the eye from the focus of the view_rect (dist, meters)
 * must also be given.
 * 
 * Note that the AWindow must be already set, and that there may be
 * several Viewport on the same AWindow.
 * 
 * Must be released with memory_dispose().
 */
EXTERN Viewport * Vlib_new(gui_Type *gui, Alib_Window *w, Alib_Rect *view_rect,
		Alib_Point *focus, double dist);

/**
 * Change size and projection infos. Basically does the same as
 * VOpenViewport(), with the only difference that it operates on an
 * existing Viewport. Note that the AWindow is not affected.
 */
EXTERN void VResizeViewport(Viewport *v, Alib_Rect *view_rect, Alib_Point *focus,
	double dist);

/**
 * Set the clipping rectangular region in the AWindow to which this
 * Viewport is linked. The resulting clipping rectangle is the
 * intersection among the Viewport rectangle and the AWindow rectangle,
 * possibly empty.
 */
EXTERN void VSetClipRect(Viewport *v, Alib_Rect *r);

EXTERN void VExposeBuffer(Viewport *);

/**
 * Transform a 3-D point in the eye space system into viewable
 * coordinates. The function returns 1 if the x,y information is
 * displayable (probably displayable, that is).
 */
EXTERN int VEyeToScreen(Viewport * v, VPoint * p, int *x, int *y);

/**
 * Transform a 3-D point in the world system into viewable coordinates.
 * The function returns 1 if the x,y information is displayable
 * (probably displayable, that is).
 */
EXTERN int VWorldToScreen(Viewport * v, VPoint * p, int *x, int *y);

EXTERN void VDrawSegments(Viewport * v, Alib_Segment * seg, int nseg, Alib_Pixel color);

EXTERN void VFillRectangle(Viewport *v, Alib_Rect *r, Alib_Pixel c);

EXTERN void VDrawPolygon(Viewport * v, VPolygon * poly);

EXTERN void VFillPolygon(Viewport * v, VPolygon * poly);

EXTERN void VDrawString(Viewport * v, VPoint * p, char *str, int len);

EXTERN int VFontWidthPixels(Viewport * v, int scale);

EXTERN void VDrawStrokeString(Viewport * v, int x, int y,
	char *str, int len, int scale, Alib_Pixel color);

EXTERN void VGetStrokeString(Viewport * v, int x, int y, 
	Alib_Segment * seg, int *nseg, char *str, int len, int scale);

/**
 * Set the perspective projection transformation. Vectors does not need to be
 * normalized to the unity length.
 * @param vp    Position of the eye in XYZ world frame.
 * @param fwd   The point the eye is looking at in XYZ world frame.
 * @param up    Eye's up direction in XYZ world frame.
 */
EXTERN void VGetEyeSpace(Viewport * v, VPoint EyePt, VPoint CntrInt, VPoint up);

EXTERN VPolygon *VGetPlanes(VPolygon * poly);

/**
 * We'll create the notion of a viewport-specific color tweaking
 * procedure.  This procedure allows some user code to get control
 * just before we hand the color name to XParseColor() so that we
 * might alter the name a bit.  Why use it?  It allows us to shrink
 * down the color space a bit on color-poor screens.
 */
EXTERN void VSetColorTweakProc(Viewport * v, void (*proc) ( /** ???  */ ));

EXTERN void VForceWindowRedraw(Viewport * v);

#undef EXTERN
#endif
