/* gtkDPSgeomentry.h -- geometry calculation codes that comes from gyve
 * Copyright (C) 1999 GYVE Development Team
 *
 * Author:  Masatake YAMATO<masata-y@is.aist-nara.ac.jp>
 * Time-stamp: <99/11/13 17:32:40 masata-y> 
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef GTK_DPS_GEOMETRY_H
#define GTK_DPS_GEOMETRY_H 

#include <glib.h>
#include <gdk/gdk.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Declare types */
typedef struct _GdkDPSCoordtr   GdkDPSCoordtr;
typedef struct _GdkDPSPoint     GdkDPSPoint;
typedef struct _GdkDPSRectangle GdkDPSRectangle;
typedef struct _GdkDPSBBox      GdkDPSBBox;
typedef gfloat GdkDPSMatrix[6];

/* World */
typedef enum
{
  GDK_DPS_WORLD_DPS,
  GDK_DPS_WORLD_X
} GdkDPSWorld; 

typedef enum
{
  GDK_DPS_TRDIR_DPS2X,
  GDK_DPS_TRDIR_X2DPS
} GdkDPSTrDirection; 

typedef enum
{
  GDK_DPS_EDGE_MIN = 0,
  GDK_DPS_EDGE_MID,
  GDK_DPS_EDGE_MAX
} GdkDPSEdge;

/* Coord translator */
struct _GdkDPSCoordtr
{
  gfloat ctm[6];
  gfloat invctm[6];
  gint x_offset;
  gint y_offset;
  gboolean data_dirty;
};


/* Point */
struct _GdkDPSPoint
{
  gfloat x;
  gfloat y;
};

/* Rectangle */
struct _GdkDPSRectangle
{
  gfloat x;
  gfloat y;
  gfloat width;
  gfloat height;
};

/* BBox */
struct _GdkDPSBBox
{
  gfloat llx;
  gfloat lly;
  gfloat urx;
  gfloat ury;
};

/*  Matrix
    
   A  C  TX
      
   B  D  TY
 
   0  0   1 */

typedef enum
{
  GDK_DPS_MELT_MIN = 0,
  GDK_DPS_MELT_A = GDK_DPS_MELT_MIN, 
  GDK_DPS_MELT_B = 1, 
  GDK_DPS_MELT_C = 2 , 
  GDK_DPS_MELT_D = 3, 
  GDK_DPS_MELT_TX = 4, 
  GDK_DPS_MELT_TY = 5,
  GDK_DPS_MELT_MAX = GDK_DPS_MELT_TY
} GdkDPSMelt;			/* Matrix ELeMent */

/****
 * Coordtr
 */
void gdk_dps_coordtr_init(GdkDPSCoordtr*);
void gdk_dps_coordtr_copy(GdkDPSCoordtr* from, GdkDPSCoordtr * to);
gboolean gdk_dps_coordtr_equal(GdkDPSCoordtr* a, GdkDPSCoordtr * b);
void gdk_dps_coordtr_make_dirty(GdkDPSCoordtr* );
void gdk_dps_coordtr_make_clean(GdkDPSCoordtr* ); /* For this package only */
gboolean gdk_dps_coordtr_is_dirty(GdkDPSCoordtr*);
void gdk_dps_coordtr_point(GdkDPSCoordtr* coordtr,
			   GdkDPSTrDirection trdir, 
			   gpointer src, 
			   gpointer dist);

void gdk_dps_coordtr_point_x2dps(GdkDPSCoordtr* coordtr,
				 GdkPoint * x_src,
				 GdkDPSPoint* dps_dist);
void gdk_dps_coordtr_point_dps2x(GdkDPSCoordtr* coordtr,
				 GdkDPSPoint * dps_src,
				 GdkPoint* x_dist);

void gdk_dps_coordtr_rectangle(GdkDPSCoordtr* coordtr,
			       GdkDPSTrDirection trdir, 
			       gpointer src, 
			       gpointer dist);

void gdk_dps_coordtr_rectangle_x2dps(GdkDPSCoordtr*,
      			       GdkRectangle * x_src,
      			       GdkDPSRectangle* dps_dist);
void gdk_dps_coordtr_rectangle_dps2x(GdkDPSCoordtr*,
				     GdkDPSRectangle * dps_src,
				     GdkRectangle * x_dist);

gfloat gdk_dps_coordtr_width(GdkDPSCoordtr* coordtr,
			     GdkDPSTrDirection trdir, 
			     gfloat width);
gfloat gdk_dps_coordtr_height(GdkDPSCoordtr* coordtr,
			      GdkDPSTrDirection trdir, 
			      gfloat height);

/****
 * Point
 */
GdkDPSPoint * gdk_dps_point_new(gfloat x, gfloat y);
void gdk_dps_point_free(GdkDPSPoint * point);
void gdk_dps_point_set(GdkDPSPoint * point, gfloat x, gfloat y);
GdkDPSPoint gdk_dps_point_edge(GdkDPSPoint * a, GdkDPSPoint * b, 
			       GdkDPSEdge x_edge, GdkDPSEdge y_edge);
gboolean gdk_dps_point_equal(GdkDPSPoint * a, GdkDPSPoint * b);
gboolean gdk_dps_point_is_origin(GdkDPSPoint * point);
gfloat gdk_dps_point_distance(GdkDPSPoint * a, GdkDPSPoint * b);
void gdk_dps_point_message(GdkDPSPoint * point, gchar * message);

/* void NSPoint_diff (NSPoint * a, NSPoint * b, NSPoint * result);
   void NSPoint_add (NSPoint * a, NSPoint * b, NSPoint * result); */

/****
 * Rectangle 
 */
/* Constructor and Destructor */
GdkDPSRectangle * gdk_dps_rectangle_new(gfloat x, gfloat y, 
					gfloat width, gfloat height);
void gdk_dps_rectangle_free(GdkDPSRectangle * rect);

/* Accessors */
void gdk_dps_rectangle_set(GdkDPSRectangle * rect, 
			   gfloat x, gfloat y, 
			   gfloat width, gfloat height);
void gdk_dps_rectangle_set_from_points(GdkDPSRectangle * rect, 
				       GdkDPSPoint * a,
				       GdkDPSPoint * b);
void gdk_dps_rectangle_set_from_center(GdkDPSRectangle * rect, 
				       GdkDPSPoint * center,
				       gfloat width,
				       gfloat height);
GdkDPSPoint gdk_dps_rectangle_get_point(GdkDPSRectangle * rect,
					GdkDPSEdge x_edge,
					GdkDPSEdge y_edge);

/* Predicators */
gboolean gdk_dps_rectangle_equal(GdkDPSRectangle * a, GdkDPSRectangle * b);
gboolean gdk_dps_rectangle_is_empty(GdkDPSRectangle * rect);
gboolean gdk_dps_rectangle_is_normalized(GdkDPSRectangle * rect);

/* Hit detect */
gboolean gdk_dps_rectangle_contains_point(GdkDPSRectangle * rect, 
				  GdkDPSPoint * point,
				  gboolean accept_on_line);
gboolean gdk_dps_rectangle_contains_rectangle(GdkDPSRectangle * super_rect, 
					      GdkDPSRectangle * sub_rect,
					      gboolean accept_on_line);


/* Operators */
void gdk_dps_rectangle_union(GdkDPSRectangle * a, GdkDPSRectangle * b,
			     GdkDPSRectangle * dest);
gboolean gdk_dps_rectangle_intesect(GdkDPSRectangle * a, GdkDPSRectangle * b,
			     GdkDPSRectangle * dest);

void gdk_dps_rectangle_enlarge_by_delta(GdkDPSRectangle * rect, gfloat dx, gfloat dy);
void gdk_dps_rectangle_enlarge_by_point(GdkDPSRectangle * rect, GdkDPSPoint * point);
void gdk_dps_rectangle_enlarge_size(GdkDPSRectangle * rect, gfloat dx, gfloat dy);
void gdk_dps_rectangle_shrink(GdkDPSRectangle * rect, gfloat dx, gfloat dy);
void gdk_dps_rectangle_shrink_size(GdkDPSRectangle * rect, gfloat dx, gfloat dy);

/* Returns a rectangle obtained by expanding ARECT minimally
 * so that all four of its defining components are integers. 
 * -- comments from GNUStep/base/NSGeometry.h */
void gdk_dps_rectangle_integral(GdkDPSRectangle * rect);

/* Returns the rectangle obtained by translating ARECT
 * horizontally by DX and vertically by DY. 
 * -- comments from GNUStep/base/NSGeometry.h */
void gdk_dps_rectangle_move(GdkDPSRectangle * rect, gfloat dx, gfloat dy);

/* NSRect NSInsetRect(NSRect aRect, float dX, float dY);
   NSDivideRect(NSRect aRect,
	       NSRect *slice,
	       NSRect *remainder,
	       float amount, NSRectEdge edge) ;  */

/* Utilities */
void gdk_dps_rectangle_to_bbox(GdkDPSRectangle * rect, GdkDPSBBox * bbox);
void gdk_dps_rectangle_message(GdkDPSRectangle * rect, gchar * message);

/****
 * BBox
 */
/* Constructor and Destructor */
GdkDPSBBox * gdk_dps_bbox_new(gfloat llx, gfloat lly, 
				   gfloat urx, gfloat ury);
void gdk_dps_bbox_free(GdkDPSBBox * bbox);
void gdk_dps_bbox_to_rectangle(GdkDPSBBox * bbox, GdkDPSRectangle * rect);
void gdk_dps_bbox_set(GdkDPSBBox * bbox, 
		      gfloat llx, gfloat lly, 
		      gfloat urx, gfloat ury);
void gdk_dps_bbox_set_from_points(GdkDPSBBox * bbox, 
				  GdkDPSPoint * a,
				  GdkDPSPoint * b);
void gdk_dps_bbox_set_from_rectangle(GdkDPSBBox * bbox, 
				     GdkDPSRectangle * rect);
void gdk_dps_bbox_message(GdkDPSBBox * bbox, gchar * message);

/****
 * Matrix
 * typedef gfloat[6] GdkDPSMatrix;
 */

gboolean gdk_dps_melt_in_range(int index);
void gdk_dps_matrix_init(GdkDPSMatrix);
void gdk_dps_matrix_copy(GdkDPSMatrix src, GdkDPSMatrix dist);
gboolean gdk_dps_matrix_equal(GdkDPSMatrix a, GdkDPSMatrix b);
void gdk_dps_matrix_apply(GdkDPSMatrix matrix, GdkDPSPoint * point);
void gdk_dps_matrix_message(GdkDPSMatrix matrix, gchar * message);
/* void matrix_apply_on_matrix(float * matrix, float * target);
   void matrix_apply_on_bbox(float * matrix, struct bbox * target);
   BOOL matrix_invert(float * base_matrix, float * new_invert_matrix); */


#ifdef __cplusplus
}
#endif
#endif /* Not def: GTK_D_P_SGEOMETRY_H */
