/*********************************************************************
 *
 *         EZWGL, the EZ Widget and Graphics Library
 *
 *             Copyright (C) 1996, 1997  Maorong Zou
 *  
 * 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.
 *
 **********************************************************************/
/*
 *  June 1996.  Beta Release.
 *  Sept 1996.  Release Version 1.0
 *  Dec 1996.  Release Version 1.1 Beta
 *  April 1997.  Release Version 1.2
 *  November 1997.  Release Version 1.3
 */
/***************************************************************
 *
 * Macros that deal with EdgeTables. These macros are
 * translated from the corresponding functions in EZ_PolyET.c
 */
#ifdef USE_GL_MACROS
#define BIG_NUMBER      12345678
#define SMALL_NUMBER  (-BIG_NUMBER)

/**************************************************************
 * 
 * Insert "edge" into an edge table "etb"
 */
#define EZ_Insert_Edge(i_etb, i_edge, i_scanline, i_place, i_iplace)\
{\
   int             scanline_i = (i_scanline); \
   EZ_Edge         *edge_i = (i_edge);\
   EZ_ETable       *etb_i = (i_etb);\
   EZ_Scanline     *place_i = (i_place);\
   int             *iplace_i = (i_iplace);\
   register EZ_Edge      *eptr_i, *eprev_i;\
   register EZ_Scanline  *sptr_i, *sprev_i;\
\
   sprev_i = &etb_i->slines;\
     sptr_i = sprev_i->next;\
       while(sptr_i && (sptr_i->sline < scanline_i))\
	 {\
	    sprev_i = sptr_i;\
            sptr_i = sptr_i->next;\
	}\
\
  if( (!sptr_i) || (sptr_i->sline > scanline_i))\
    {\
      sptr_i = &(place_i[(*iplace_i)++]);\
      sptr_i->next = sprev_i->next;\
      sptr_i->edgelist = (EZ_Edge *)NULL;\
      sprev_i->next = sptr_i;\
    }\
  sptr_i->sline = scanline_i;\
\
  eprev_i = (EZ_Edge *)NULL;\
  eptr_i  = sptr_i->edgelist;\
  while(eptr_i && (eptr_i->info.x < edge_i->info.x))\
    {\
      eprev_i = eptr_i;\
      eptr_i = eptr_i->next;\
    }\
  edge_i->next = eptr_i;\
  if(eprev_i)   eprev_i->next = edge_i;\
  else        sptr_i->edgelist = edge_i;\
}

/**************************************************************
 *
 * create and initialize Edge Table and Active Edge Table
 */

#define EZ_Make_Edge_Table(m_n, m_vts, m_et, m_aet, m_edge_ptr, m_sline_storage)\
{\
   int          n_m = (m_n);\
   int          *vts_m = (m_vts);\
   EZ_ETable    *et_m = (m_et);\
   EZ_Edge      *aet_m = (m_aet);\
   EZ_Edge      *edge_ptr_m = (m_edge_ptr);\
   EZ_Scanline  *sline_storage_m = (m_sline_storage);\
   int          dy_m, dx_m, itmp_m;\
   int          sline_index_m = 0;\
   int          order_m, *prevptr_m, *currentptr_m;\
   int          current_vt_m, prev_vt_m;  \
   int          (*screen_m)[3];\
   register int *topptr_m, *bottomptr_m;\
\
  aet_m->next = (EZ_Edge *)NULL;\
  aet_m->prev = (EZ_Edge *)NULL;\
  aet_m->info.x = SMALL_NUMBER;\
\
  et_m->slines.next = (EZ_Scanline *)NULL;\
  et_m->ymin = BIG_NUMBER;\
  et_m->ymax = SMALL_NUMBER;\
  screen_m = EZ_VBuf.screen;\
\
  prev_vt_m = vts_m[n_m-1];\
  prevptr_m = screen_m[prev_vt_m];\
  while(n_m--)\
    {\
      current_vt_m = *vts_m++;\
      currentptr_m = screen_m[current_vt_m];\
\
      if(currentptr_m[1] != prevptr_m[1])\
	{\
	   if(currentptr_m[1] > prevptr_m[1])\
	     {\
		order_m = 0;\
		topptr_m = prevptr_m;\
		bottomptr_m = currentptr_m;\
	    }\
	   else\
	     {\
		order_m = 1;\
		topptr_m = currentptr_m;\
		bottomptr_m = prevptr_m;\
	    }\
\
	  edge_ptr_m->ymax = bottomptr_m[1] - 1;\
	  dy_m = bottomptr_m[1] - topptr_m[1];\
\
	  (edge_ptr_m->info).x = topptr_m[0];\
	  dx_m = bottomptr_m[0] - topptr_m[0];\
\
	  if( dx_m < 0) \
	    {\
	      itmp_m = dx_m/dy_m;\
	      (edge_ptr_m->info).s = itmp_m;\
	      itmp_m--;\
	      (edge_ptr_m->info).s1 = itmp_m;\
	      itmp_m = 2*(dy_m * itmp_m - dx_m);\
	      (edge_ptr_m->info).incr1 = itmp_m;\
	      (edge_ptr_m->info).incr2 = itmp_m + (dy_m << 1);\
	      (edge_ptr_m->info).d = itmp_m;\
	    } \
	  else\
	    { \
	      itmp_m = dx_m / dy_m;\
	      (edge_ptr_m->info).s = itmp_m; \
	      itmp_m++;\
	      (edge_ptr_m->info).s1 = itmp_m ;\
	      itmp_m = 2*(dx_m - itmp_m * dy_m); \
	      (edge_ptr_m->info).incr1 = itmp_m;\
	      (edge_ptr_m->info).d = (edge_ptr_m->info).incr2 = itmp_m + (dy_m << 1);\
	    }\
  	   itmp_m = EZ_AuxTable[dy_m];\
	   (edge_ptr_m->info).z = topptr_m[2];\
	   (edge_ptr_m->info).dz = ((bottomptr_m[2]- topptr_m[2]) >> AUX_SHIFT_BITS) * itmp_m;\
	   if(EZ_PolygonShadingMode == EZ_GOURAUD)\
	    {\
	      int (*rgbaptr_m)[4] = EZ_VBuf.rgba;\
	      int *topclr_m, *bottomclr_m;\
\
	      if(order_m)\
		{\
		  topclr_m = rgbaptr_m[current_vt_m];\
		  bottomclr_m = rgbaptr_m[prev_vt_m];\
		}\
	      else\
		{\
		  topclr_m = rgbaptr_m[prev_vt_m];\
		  bottomclr_m = rgbaptr_m[current_vt_m];\
		}\
	      if( EZ_ColorMode == EZ_RGB_MODE)\
	       {\
		  int dr_m, dg_m, db_m;\
		  (edge_ptr_m->info).clr.ri = topclr_m[0];\
		  (edge_ptr_m->info).clr.g =  topclr_m[1];\
		  (edge_ptr_m->info).clr.b =  topclr_m[2];\
		  dr_m = ((bottomclr_m[0] - topclr_m[0]) >> AUX_SHIFT_BITS);\
		  dg_m = ((bottomclr_m[1] - topclr_m[1]) >> AUX_SHIFT_BITS);\
		  db_m = ((bottomclr_m[2] - topclr_m[2]) >> AUX_SHIFT_BITS);\
		  (edge_ptr_m->info).clr.dri= (dr_m - (dr_m >> FIX_NEG1)) * itmp_m;\
		  (edge_ptr_m->info).clr.dg = (dg_m - (dg_m >> FIX_NEG1)) * itmp_m;\
		  (edge_ptr_m->info).clr.db = (db_m - (db_m >> FIX_NEG1)) * itmp_m;\
		}\
	       else\
	        {\
		  int dc_m;\
		  (edge_ptr_m->info).clr.ri = topclr_m[0];\
		  dc_m = ((bottomclr_m[0] - topclr_m[0]) >> AUX_SHIFT_BITS);\
		  (edge_ptr_m->info).clr.dri = (dc_m - (dc_m >> FIX_NEG1)) * itmp_m;\
	        }\
	   }\
\
	  EZ_Insert_Edge(et_m,edge_ptr_m, topptr_m[1], sline_storage_m, &sline_index_m);\
\
          itmp_m = prevptr_m[1];\
          if(itmp_m > et_m->ymax) et_m->ymax = itmp_m;\
	  if(itmp_m < et_m->ymin) et_m->ymin = itmp_m;\
\
	  edge_ptr_m++;\
	}\
      prev_vt_m = current_vt_m;\
      prevptr_m = currentptr_m;\
    }\
}

/**************************************************************
 *
 *  Load the edgelist 'edges' into the active edge table
 */

#define EZ_Load_Edge(l_aet, l_edges)\
{\
  register EZ_Edge *aet_b = (l_aet);\
  register EZ_Edge *edges_b = (l_edges);\
  register EZ_Edge *prev_b, *tmp_b;\
\
  prev_b = aet_b;\
  aet_b = aet_b->next;\
\
  while(edges_b)\
    {\
      while( aet_b && (aet_b->info.x < edges_b->info.x))\
	{\
	  prev_b = aet_b;\
	  aet_b = aet_b->next;\
	}\
      tmp_b = edges_b->next;\
      edges_b->next = aet_b;\
      if(aet_b) aet_b->prev = edges_b;\
      edges_b->prev = prev_b;\
      prev_b->next = edges_b;\
      prev_b = edges_b;\
      edges_b = tmp_b;\
    }\
}\

/**************************************************************
 *
 *  Sort the active edge table according to x coordinates
 */
#define  EZ_Sort_ActiveET(cur_aet_ptr) \
{\
  register EZ_Edge *tmpaet = (cur_aet_ptr);\
  register EZ_Edge *ptr;\
  register EZ_Edge *pinsert;\
  register EZ_Edge *prev;\
\
  tmpaet = tmpaet->next;\
  while(tmpaet)\
    {\
      ptr = tmpaet;\
      pinsert = tmpaet;\
      while( ptr->prev->info.x > tmpaet->info.x)\
	ptr = ptr->prev;\
      tmpaet = tmpaet->next;\
      if(ptr != pinsert)\
	{\
	  prev = ptr->prev;\
	  pinsert->prev->next = tmpaet;\
	  if(tmpaet) tmpaet->prev = pinsert->prev;\
	  pinsert->next = ptr;\
	  ptr->prev->next = pinsert;\
	  ptr->prev = pinsert;\
	  pinsert->prev = prev;\
	}\
    }\
}
#endif
/***************************************************************************/
