/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: dk3fig.ctr
*/

/*
Copyright (C) 2011-2013, Dirk Krause

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above opyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.
* Neither the name of the author nor the names of contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**	@file dk3fig.c The dk3fig module.
*/


#line 1084 "dk3fig.ctr"


#include "dk3all.h"
#include "dk3fig.h"




#line 1091 "dk3fig.ctr"



/**	Localized message texts.
*/
static dkChar const * const	dk3fig_messages[] = {
/* 0 */
dkT("dk3fig.str"),

/* 1 */
dkT("Syntax error in Fig input!"),

/* 2 */
dkT("Color redefined!"),

/* 3 */
dkT("Mathematical problem in arc calculation!"),

/* 4 */
dkT("Object processing failed!"),

/* 5 */
dkT("Arrowhead calculation failed!"),

/* 6 */
dkT("Error while reading input file!"),

/* 7 */
dkT("Color not found, using black as default color!"),

/* 8 */
dkT("Unknown object type!"),

NULL


#line 1135 "dk3fig.ctr"
};




dkChar const * const *
dk3fig_get_localized_messages(dk3_app_t *app)
{
  dkChar const * const	*back = NULL;
  if(app) {
    back = dk3app_messages(
      app, dk3fig_messages[0], (dkChar const **)dk3fig_messages
    );
  }
  return back;
}



/**	Compare two text objects.
	This function is used to sort text objects.
	@param	pl	Left text object.
	@param	pr	Right text object.
	@return	Comparison result.
*/
static
int
dk3fig_obj_text_compare(dk3_fig_obj_t *pl, dk3_fig_obj_t *pr)
{
  int		 back = 0;
  /*
          Non-special texts before special texts.
  */
  if(((pl->dt).txt.ff) & DK3_FIG_FONT_FLAG_SPECIAL) {
    if(!(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_SPECIAL)) {
      back = 1;
    }
  } else {
    if(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_SPECIAL) {
      back = -1;
    }
  }
  /*
          Font selection type.
  */
  if(0 == back) {
    if(((pl->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS) {
      if(!(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS)) {
        back = 1;
      }
    } else {
      if(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS) {
        back = -1;
      }
    }
  }
  /*
          Font number.
  */
  if(0 == back) {
    if((pl->dt).txt.fo > (pr->dt).txt.fo) {
      back = 1;
    } else {
      if((pl->dt).txt.fo < (pr->dt).txt.fo) {
        back = -1;
      }
    }
  }
  /*
          Font size.
  */
  if(0 == back) {
    if((pl->dt).txt.fs > (pr->dt).txt.fs) {
      back = 1;
    } else {
      if((pl->dt).txt.fs < (pr->dt).txt.fs) {
        back = -1;
      }
    }
  }
  /*
  	Text string.
  */
  if(0 == back) {
    back = dk3str_c8_cmp((pl->dt).txt.st, (pr->dt).txt.st);
    if(back < -1) back = -1;
    if(back >  1) back =  1;
  }
  return back;
}



/**	Compare two non-text objects.
	@param	pl	Left object.
	@param	pr	Right object.
	@return	Comparison result.
*/
static
int
dk3fig_obj_path_compare(dk3_fig_obj_t *pl, dk3_fig_obj_t *pr)
{
  int		 back = 0;
  /*
  	Line width.
  */
  if(0 == back) {
    if(pl->lw > pr->lw)	{ back = 1; }
    else		{ if(pl->lw < pr->lw) { back = -1; } }
  }
  /*
  	Pen color.
  */
  if(0 == back) {
    if(pl->pc > pr->pc)	{ back = 1; }
    else		{ if(pl->pc < pr->pc) { back = -1; } } 
  }
  /*
  	Line cap.
  */
  if(0 == back) {
    if(pl->cs > pr->cs)	{ back = 1; }
    else		{ if(pl->cs < pr->cs) { back = -1; } }
  }
  /*
  	Line join.
  */
  if(0 == back) {
    if(pl->js > pr->js) { back = 1; }
    else		{ if(pl->js < pr->js) { back = -1; } }
  }
  /*
  	Line style, style value for equal line style.
  */
  if(0 == back) {
    if(pl->ls > pr->ls) { back = 1; }
    else		{ if(pl->ls < pr->ls) { back = -1; } }
    if(0 == back) {
      if(pl->sv > pr->sv)	{ back = 1; }
      else			{ if(pl->sv < pr->sv) { back = -1; } }
    }
  }
  /*
  	Non-closed before closed.
  */
  if(0 == back) {
    if(pl->cl) {
      if(pr->cl) {
        /*
      	  Fill color.
        */
	if(pl->fc > pr->fc)	{ back = 1; }
	else			{ if(pl->fc < pr->fc) { back = -1; } }
        /*
      	  Fill style.
        */
	if(0 == back) {
	  if(pl->fi > pr->fi)	{ back = 1; }
	  else			{ if(pl->fi < pr->fi) { back = -1; } }
	}
      } else {
        back = 1;
      }
    } else {
      if(pr->cl) {
        back = -1;
      }
    }
  }
  /*
  	Object type.
  */
  if(0 == back) {
    if(pl->ot > pr->ot)	{ back = 1; }
    else		{ if(pl->ot < pr->ot) { back = -1; } }
  }
  /*
  	Sub type.
  */
  if(0 == back) {
    if(pl->st > pr->st)	{ back = 1; }
    else		{ if(pl->st < pr->st) { back = -1; } }
  }
  return back;
}



/**	Compare two Fig objects for sorted storing.
	We must draw the deepest layer elements first (by definition).
	Additionally we sort elements by multiple attributes
	(non-text elements before texts, pen color, fill color and type,
	line style, line width, cap style, join style) to group elements
	with equal attributes. This is done to minimize instructions
	for writing colors, line style, line width...
	@param	l	Left Fig object.
	@param	r	Right Fig object.
	@param	cr	Comparison criteria (ignored).
	@return	Comparison result.
*/
static
int
dk3fig_obj_compare(void *l, void *r, int cr)
{
  int		 back = 0;
  dk3_fig_obj_t	*pl;
  dk3_fig_obj_t	*pr;
  if(l) {
    if(r) {
      pl = (dk3_fig_obj_t *)l;
      pr = (dk3_fig_obj_t *)r;
      /*
      	Deepest layers first.
      */
      if(pl->la > pr->la)	{ back = -1; }
      else			{ if(pl->la < pr->la) { back = 1; } }
      /*
      	Non-texts before texts.
      */
      if(0 == back) {
        if(DK3_FIG_OBJ_TEXT == pl->ot) {
          if(!(DK3_FIG_OBJ_TEXT == pr->ot)) {
	    back = 1;
	  } else {
	    back = dk3fig_obj_text_compare(pl, pr);
	  }
        } else {
          if(DK3_FIG_OBJ_TEXT == pr->ot) {
	    back = -1;
	  } else {
	    back = dk3fig_obj_path_compare(pl, pr);
	  }
        }
      }
      /*
      	Line number of definition.
      */
      if(0 == back) {
        if(pl->li > pr->li)	{ back = 1; }
	else			{ if(pl->li < pr->li) { back = -1; } }
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}



/**	Destroy arrowhead, release memory.
	@param	ah	Arrowhead to destroy.
*/
static
void
dk3fig_ah_delete(dk3_fig_ah_t *ah)
{
  

#line 1393 "dk3fig.ctr"
  if(ah) {
    if(ah->o1) {				

#line 1395 "dk3fig.ctr"
      dk3fig_obj_delete((dk3_fig_obj_t *)(ah->o1));
    }
    if(ah->o2) {				

#line 1398 "dk3fig.ctr"
      dk3fig_obj_delete((dk3_fig_obj_t *)(ah->o2));
    }
    dk3_delete(ah)
  } 

#line 1402 "dk3fig.ctr"
}



/**	Create new arrowhead structure.
	@param	app	Application structure for diagnostics.
	@return	Pointer to new structure on success, NULL on error.
*/
static
dk3_fig_ah_t *
dk3fig_ah_new(dk3_app_t *app)
{
  dk3_fig_ah_t		*back	= NULL;
  back = dk3_new_app(dk3_fig_ah_t,1,app);
  if(back) {
    back->o1 = NULL;
    back->o2 = NULL;
    back->wi = 0.0;
    back->he = 0.0;
    back->as = 0;
    back->af = 0;
  }
  return back;
}



void
dk3fig_obj_delete(dk3_fig_obj_t *obj)
{
  

#line 1433 "dk3fig.ctr"
  if(obj) {
    if(obj->af) {				

#line 1435 "dk3fig.ctr"
      dk3fig_ah_delete(obj->af);
    }
    if(obj->ab) {				

#line 1438 "dk3fig.ctr"
      dk3fig_ah_delete(obj->ab);
    }
    switch(obj->ot) {
      case DK3_FIG_OBJ_TEXT: {			

#line 1442 "dk3fig.ctr"
        if((obj->dt).txt.st) {
	  dk3_release((obj->dt).txt.st)
	}
      } break;
      case DK3_FIG_OBJ_SPLINE: {		

#line 1447 "dk3fig.ctr"
        if((obj->dt).spl.po) {
	  dk3_release((obj->dt).spl.po)
	}
	if((obj->dt).spl.fslc) {
	  dk3_release((obj->dt).spl.fslc)
	}
      } break;
      case DK3_FIG_OBJ_POLYLINE: {		

#line 1455 "dk3fig.ctr"
        if((obj->dt).pol.po) {
	  dk3_release((obj->dt).pol.po)
	}
	if((obj->dt).pol.fn) {
	  dk3_release((obj->dt).pol.fn)
	}
      } break;
    }
    obj->af = NULL;
    obj->ab = NULL;
    dk3_delete(obj)
  } 

#line 1467 "dk3fig.ctr"
}



/**	Reset all members of a drawing object.
	@param	drw	Drawing object to reset.
*/
static
void
dk3fig_initialize_empty_drawing(dk3_fig_drawing_t *drw)
{
  

#line 1479 "dk3fig.ctr"
  dk3bb_reset(&(drw->bb));
  drw->msg  = NULL;
  drw->app  = NULL;
  drw->sobj = NULL;
  drw->iobj = NULL;
  drw->scol = NULL;
  drw->icol = NULL;
  drw->cobj = NULL;
  drw->dsd  = NULL;
  drw->res  = 1200.0;
  drw->lineno = 0UL;
  drw->lres = 0;
  drw->cind = 0;
  drw->cxy = 0;
  drw->state = 0;
  drw->ec   = 0;
  drw->srctype = DK3_FIG_SRCTYPE_UNKNOWN;
  drw->xssbs = 8;
  drw->qbs = 4;
  drw->transcol = -2;
  drw->lighten = 0;
  drw->coah = 0;
  drw->cosp = 0;
  drw->bbts = 0;
  drw->arcspp = 8.0;
  drw->splspp = 8.0;
  drw->minspp = 4;
  drw->codi = 3;
  drw->xsprec = 0.04;	/* originally 1200.0 / 25400.0 */
  

#line 1509 "dk3fig.ctr"
}



/**	Compare two Fig colors.
	@param	l	Left object.
	@param	r	Right color object or number.
	@param	cr	Comparison criteria (0=color/color, 1=color/number).
	@return	Comparison result.
*/
static
int
dk3fig_color_compare(void *l, void *r, int cr)
{
  int			 back = 0;
  dk3_fig_color_t	*pl;
  dk3_fig_color_t	*pr;
  int			*ip;
  if(l) {
    if(r) {
      pl = (dk3_fig_color_t *)l;
      pr = (dk3_fig_color_t *)r;
      ip = (int *)r;
      switch(cr) {
        case 1: {
	  if(pl->i > (*ip)) {
	    back = 1;
	  } else {
	    if(pl->i < (*ip)) {
	      back = -1;
	    }
	  }
	} break;
	default: {
	  if(pl->i > pr->i) {
	    back = 1;
	  } else {
	    if(pl->i < pr->i) {
	      back = -1;
	    }
	  }
	} break;
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}


dk3_fig_drawing_t *
dk3fig_drawing_new(dk3_app_t *app, dkChar const * const *msg)
{
  dk3_fig_drawing_t		*back	= NULL;
  

#line 1565 "dk3fig.ctr"
  if(app) {
    back = dk3_new_app(dk3_fig_drawing_t,1,app);
    if(back) {
      dk3fig_initialize_empty_drawing(back);
      back->app = app;
      back->msg = msg;
      back->sobj = dk3sto_open_app(app);
      if(back->sobj) {
        dk3sto_set_comp(back->sobj, dk3fig_obj_compare, 0);
	back->iobj = dk3sto_it_open(back->sobj);
	if(back->iobj) {
	  back->scol = dk3sto_open_app(app);
	  if(back->scol) {
	    dk3sto_set_comp(back->scol, dk3fig_color_compare, 0);
	    back->icol = dk3sto_it_open(back->scol);
	    if(back->icol) {
	      /* Place for further initialization here */
	    } else {				

#line 1583 "dk3fig.ctr"
	      dk3fig_drawing_delete(back);
	      back = NULL;
	    }
	  } else {				

#line 1587 "dk3fig.ctr"
	    dk3fig_drawing_delete(back);
	    back = NULL;
	  }
	} else {				

#line 1591 "dk3fig.ctr"
	  dk3fig_drawing_delete(back);
	  back = NULL;
	}
      } else {					

#line 1595 "dk3fig.ctr"
        dk3fig_drawing_delete(back);
	back = NULL;
      }
    } else {					

#line 1599 "dk3fig.ctr"
    }
  } 

#line 1601 "dk3fig.ctr"
  return back;
}



void
dk3fig_drawing_delete(dk3_fig_drawing_t *drw)
{
  dk3_fig_color_t *co;	/* Current color to release. */
  dk3_fig_obj_t	*po;	/* Current Fig object to release. */
  

#line 1612 "dk3fig.ctr"
  if(drw) {
    /*
    	Remove all objects.
    */
    if(drw->sobj) {
      if(drw->iobj) {
        dk3sto_it_reset(drw->iobj);
	while(NULL != (po = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) {
	  dk3fig_obj_delete(po);
	}
        dk3sto_it_close(drw->iobj);
      }
      dk3sto_close(drw->sobj);
    }
    /*
    	Remove all colors.
    */
    if(drw->scol) {
      if(drw->icol) {
        dk3sto_it_reset(drw->icol);
	while(NULL != (co = (dk3_fig_color_t *)dk3sto_it_next(drw->icol))) {
	  

#line 1634 "dk3fig.ctr"
	  dk3_delete(co)
	}
	dk3sto_it_close(drw->icol);
      }
      dk3sto_close(drw->scol);
    }
    /*
    	Reset all members.
    */
    dk3fig_initialize_empty_drawing(drw);
    /*
    	Release memory.
    */
    drw->app = NULL;
    drw->msg = NULL;
    dk3_delete(drw)
  } 

#line 1651 "dk3fig.ctr"
}



/**	Internal function to create Fig object and initialize it.
	@param	li	Line number of object definition in file.
	@param	la	Layer number.
	@param	ot	Object type.
	@param	st	Object subtype.
	@param	lw	Line width.
	@param	pc	Pen color.
	@param	fc	Fill color.
	@param	fi	Fill type.
	@param	cs	Cap style.
	@param	js	Join style.
	@param	ls	Line style.
	@param	sv	Style value.
	@param	af	Flag: Arrowhead forward.
	@param	ab	Flag: Arrowhead backward.
	@param	po	Flag: Path object (non-text object).
	@param	cl	Flag: Closed path object.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Pointer to new object on success, NULL on error.
*/
static
dk3_fig_obj_t *
dk3fig_obj_internal_new(
  unsigned long		 li,
  int			 la,
  int			 ot,
  int			 st,
  int			 lw,
  int			 pc,
  int			 fc,
  int			 fi,
  int			 cs,
  int			 js,
  int			 ls,
  double		 sv,
  int			 af,
  int			 ab,
  int			 po,
  int			 cl,
  dk3_app_t		*app
)
{
  dk3_fig_obj_t		*back = NULL;
  

#line 1699 "dk3fig.ctr"
  back = dk3_new_app(dk3_fig_obj_t,1,app);
  if(back) {		

#line 1701 "dk3fig.ctr"
    back->af = NULL;
    back->ab = NULL;
    back->dsd = NULL;
    back->sv = sv;
    back->li = li;
    back->la = la;
    back->ot = ot;
    back->st = st;
    back->lw = lw;
    back->pc = pc;
    back->fc = fc;
    back->fi = fi;
    back->cs = cs;
    back->js = js;
    back->ls = ls;
    back->cl = ((cl) ? 0x01 : 0x00);	

#line 1717 "dk3fig.ctr"
    if(back->lw < 0) {
      back->lw = 0;
      if(po) {			

#line 1720 "dk3fig.ctr"
        /* +++++ Warning: Illegal line width corrected! */
      }
    }
    if(back->pc < -1) {		

#line 1724 "dk3fig.ctr"
      back->pc = -1;
        /* +++++ Warning: Illegal pen color definition corrected! */
    }
    if(back->fc < DK3_FIG_COLOR_DEFAULT) {
      back->fc = DK3_FIG_COLOR_DEFAULT;
      if((po) && (cl)) {	

#line 1730 "dk3fig.ctr"
	/* +++++ Warning: Illegal fill color definition corrected! */
      }
    }
    if(back->fi < DK3_FIG_COLOR_DEFAULT) {
      back->fi = DK3_FIG_COLOR_DEFAULT;
      if((po) && (cl)) {	

#line 1736 "dk3fig.ctr"
        /* +++++ Warning: Illegal fill style corrected! */
      }
    } else {
      if(back->fi > 62) {
        back->fi = 62;
	if((po) && (cl)) {	

#line 1742 "dk3fig.ctr"
	  /* +++++ Warning: Illegal fill style corrected! */
	}
      } else {
        if((DK3_FIG_COLOR_BLACK == fc) || (DK3_FIG_COLOR_WHITE == fc)) {
	  if((back->fi >= 21) && (back->fi <= 40)) {
	    back->fi = 20;
	    if((po) && (cl)) {	

#line 1749 "dk3fig.ctr"
	      /* +++++ Warning: Illegal fill style corrected! */
	    }
	  }
	}
      }
    }
    if(DK3_FIG_LC_BUTT != back->cs) {
      if(DK3_FIG_LC_ROUND != back->cs) {
        if(DK3_FIG_LC_PROJECTING != back->cs) {
	  back->cs = DK3_FIG_LC_BUTT;
	  if(po) {		

#line 1760 "dk3fig.ctr"
	    /* +++++ Warning: Illegal line cap style corrected! */
	  }
	}
      }
    }
    if(DK3_FIG_LJ_MITER != back->js) {
      if(DK3_FIG_LJ_ROUND != back->js) {
        if(DK3_FIG_LJ_BEVEL != back->js) {
	  back->js = DK3_FIG_LJ_MITER;
	  if(po) {		

#line 1770 "dk3fig.ctr"
	    /* +++++ Warning: Illegal line join style corrected! */
	  }
	}
      }
    }
    if(back->ls < DK3_FIG_LS_SOLID) {
      back->ls = DK3_FIG_LS_SOLID;
      if(ls < DK3_FIG_LS_DEFAULT) {
        if(po) {		

#line 1779 "dk3fig.ctr"
	  /* +++++ Warning: Illegal line style corrected! */
	}
      }
    } else {
      if(back->ls > DK3_FIG_LS_DASH_TRIPLE_DOTTED) {
        back->ls = DK3_FIG_LS_SOLID;
	if(po) {		

#line 1786 "dk3fig.ctr"
	  /* +++++ Warning: Illegal line style corrected! */
	}
      }
    }
  } else {			

#line 1791 "dk3fig.ctr"
  }
  if((po) && (!(cl))) {		

#line 1793 "dk3fig.ctr"
    if(back) {
      if(af) {			

#line 1795 "dk3fig.ctr"
        back->af = dk3fig_ah_new(app);
        if(!(back->af)) {
	  dk3fig_obj_delete(back);
	  back = NULL;
        }
      }
      if(ab) {			

#line 1802 "dk3fig.ctr"
        back->ab = dk3fig_ah_new(app);
        if(!(back->ab)) {
	  dk3fig_obj_delete(back);
	  back = NULL;
        }
      }
    }
  } else {			

#line 1810 "dk3fig.ctr"
    if((af) || (ab)) {	

#line 1811 "dk3fig.ctr"
      /* +++++ Warning: Arrowhead ignored for closed path! */
    }
  } 

#line 1814 "dk3fig.ctr"
  return back;
}



/**	Initialize details for arc.
	@param	obj	Object to initialize.
*/
static
void
dk3fig_initialize_arc_details(dk3_fig_obj_t *obj)
{
  (obj->dt).arc.xc = 0.0;
  (obj->dt).arc.yc = 0.0;
  (obj->dt).arc.ra = 0.0;
  (obj->dt).arc.x1 = 0.0;
  (obj->dt).arc.y1 = 0.0;
  (obj->dt).arc.x2 = 0.0;
  (obj->dt).arc.y2 = 0.0;
  (obj->dt).arc.x3 = 0.0;
  (obj->dt).arc.y3 = 0.0;
  (obj->dt).arc.as = 0.0;
  (obj->dt).arc.ae = 0.0;
  (obj->dt).arc.di = 0x00;
}



/**	Initialize ellipse details.
	@param	obj	Object to initialize.
*/
static
void
dk3fig_initialize_ellipse_details(dk3_fig_obj_t *obj)
{
  (obj->dt).ell.an = 0.0;
  (obj->dt).ell.cx = 0.0;
  (obj->dt).ell.cy = 0.0;
  (obj->dt).ell.rx = 0.0;
  (obj->dt).ell.ry = 0.0;
}



/**	Initialize polyline details.
	@param	obj	Object to initialize.
	@param	np	Number of points.
	@param	app	Application structure for diagnostics.
	@return	1 on success, 0 on error (not enough memory).
*/
static
int
dk3fig_initialize_polyline_details(dk3_fig_obj_t *obj,size_t np,dk3_app_t *app)
{
  int		 back = 0;
  (obj->dt).pol.fn = NULL;
  (obj->dt).pol.po = NULL;
  (obj->dt).pol.ra = 0.0;
  (obj->dt).pol.xs = 0.0;
  (obj->dt).pol.ys = 0.0;
  (obj->dt).pol.xe = 0.0;
  (obj->dt).pol.ye = 0.0;
  (obj->dt).pol.np = np;
  (obj->dt).pol.flf = 0;
  (obj->dt).pol.po = dk3_new_app(dk3_fig_poly_point_t,np,app);
  if((obj->dt).pol.po) {
    back = 1;
  }
  return back;
}



/**	Initialize spline details.
	@param	obj	Object to initialize.
	@param	np	Number of spline points.
	@param	app	Application structure for diagnostics.
	@return	1 on success, 0 on error (not enough memory).
*/
static
int
dk3fig_initialize_spline_details(dk3_fig_obj_t *obj,size_t np,dk3_app_t *app)
{
  double	*xptr;
  size_t	 i;
  int		 back = 0;
  (obj->dt).spl.po = NULL;
  (obj->dt).spl.fslc = NULL;
  (obj->dt).spl.ts = -1.0;
  (obj->dt).spl.te = -1.0;
  (obj->dt).spl.np = np;
  (obj->dt).spl.po = dk3_new_app(dk3_fig_spline_point_t, np, app);
  if((obj->dt).spl.po) {
    back = 1;
    switch(obj->st) {
      case 0: case 2: case 4: {
        if(((obj->af) || (obj->ab)) && (2 <= np)) {
	  (obj->dt).spl.fslc = dk3_new_app(double, (np-1), app);
	  if((obj->dt).spl.fslc) {
	    /* Initialize cache to -1 */
	    xptr = (obj->dt).spl.fslc;
	    i = np - 1;
	    while(i--) { *(xptr++) = -1.0; }
	  } else {
	    back = 0;
	  }
	}
      } break;
    }
  }
  return back;
}



/**	Initialize text details.
	@param	obj	Object to initialize.
	@param	tx	Text for text object.
	@param	app	Application structure for diagnostics.
	@return	1 on success, 0 on error (not enough memory).
*/
static
int
dk3fig_initialize_text_details(dk3_fig_obj_t *obj,char const *tx,dk3_app_t *app)
{
  int		 back = 0;
  (obj->dt).txt.st = NULL;
  (obj->dt).txt.x  = 0.0;
  (obj->dt).txt.y  = 0.0;
  (obj->dt).txt.an = 0.0;
  (obj->dt).txt.fs = 0.0;
  (obj->dt).txt.he = 0.0;
  (obj->dt).txt.wi = 0.0;
  (obj->dt).txt.fo = 0;
  (obj->dt).txt.ff = 0;
  (obj->dt).txt.st = dk3str_c8_dup_app(tx, app);
  if((obj->dt).txt.st) {
    back = 1;
  }
  return back;
}



dk3_fig_obj_t *
dk3fig_obj_new(
  unsigned long	 li,
  int		 la,
  int		 ot,
  int		 st,
  int		 lw,
  int		 pc,
  int		 fc,
  int		 fi,
  int		 cs,
  int		 js,
  int		 ls,
  double	 sv,
  int		 af,
  int		 ab,
  size_t	 np,
  char const	*txt,
  dk3_app_t	*app
)
{
  dk3_fig_obj_t		*back	= NULL;
  

#line 1981 "dk3fig.ctr"
  if((la < 0) || (la > 999)) {
    /* +++++ Warning: Illegal layer number! */
  }
  switch(ot) {
    case DK3_FIG_OBJ_ARC: {		

#line 1986 "dk3fig.ctr"
      switch(st) {
        case DK3_FIG_OBJ_SUB_ARC_OPEN: {	

#line 1988 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_ARC_CLOSED: {	

#line 1993 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case 0: {				

#line 1998 "dk3fig.ctr"
	  /* +++++ Warning: jFig closed arc bug. */
	  back = dk3fig_obj_internal_new(
	    li, la, ot, DK3_FIG_OBJ_SUB_ARC_CLOSED,
	    lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
	default: {				

#line 2005 "dk3fig.ctr"
	  /* +++++ Warning: Illegal sub type corrected! */
	  back = dk3fig_obj_internal_new(
	    li, la, ot, DK3_FIG_OBJ_SUB_ARC_CLOSED,
	    lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
      }
      if(back) {
        dk3fig_initialize_arc_details(back);
      }
    } break;
    case DK3_FIG_OBJ_ELLIPSE: {		

#line 2017 "dk3fig.ctr"
      switch(st) {
        case DK3_FIG_OBJ_SUB_ELL_RADII: {	

#line 2019 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_ELL_DIAMETERS: {	

#line 2024 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_CIR_RADIUS: {	

#line 2029 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_CIR_DIAMETER: {	

#line 2034 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	default: {				

#line 2039 "dk3fig.ctr"
	  /* +++++ Warning: Illegal sub type corrected! */
	  back = dk3fig_obj_internal_new(
	    li, la, ot, DK3_FIG_OBJ_SUB_ELL_RADII,
	    lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
      }
      if(back) {
        dk3fig_initialize_ellipse_details(back);
      }
    } break;
    case DK3_FIG_OBJ_POLYLINE: {	

#line 2051 "dk3fig.ctr"
      switch(st) {
        case DK3_FIG_OBJ_SUB_POLYLINE: {	

#line 2053 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_BOX: {		

#line 2058 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_POLYGON: {		

#line 2063 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_ARCBOX: {		

#line 2068 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_IMAGE: {		

#line 2073 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	default: {				

#line 2078 "dk3fig.ctr"
	  /* +++++ Warning: Illegal sub type corrected! */
	  back = dk3fig_obj_internal_new(
	    li, la, ot, DK3_FIG_OBJ_SUB_POLYLINE,
	    lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
      }
      if(back) {
	if(!dk3fig_initialize_polyline_details(back, np, app)) {
	  dk3fig_obj_delete(back);
	  back = NULL;
	}
      }
    } break;
    case DK3_FIG_OBJ_SPLINE: {		

#line 2093 "dk3fig.ctr"
      switch(st) {
        case DK3_FIG_OBJ_SUB_OPEN_APPRO: {	

#line 2095 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_CLOSED_APPRO: {	

#line 2100 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_OPEN_INT: {	

#line 2105 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_CLOSED_INT: {	

#line 2110 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_OPEN_X: {		

#line 2115 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
	case DK3_FIG_OBJ_SUB_CLOSED_X: {	

#line 2120 "dk3fig.ctr"
	  back = dk3fig_obj_internal_new(
	    li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
	  );
	} break;
	default: {				

#line 2125 "dk3fig.ctr"
	  /* +++++ Warning: Illegal sub type corrected! */
	  back = dk3fig_obj_internal_new(
	    li, la, ot, DK3_FIG_OBJ_SUB_OPEN_X,
	    lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
	  );
	} break;
      }
      if(back) {
        if(!dk3fig_initialize_spline_details(back, np, app)) {
	  dk3fig_obj_delete(back);
	  back = NULL;
	}
      }
    } break;
    case DK3_FIG_OBJ_TEXT: {		

#line 2140 "dk3fig.ctr"
      if(txt) {				

#line 2141 "dk3fig.ctr"
	back = dk3fig_obj_internal_new(
	  li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 0, 0, app
	);
	if(back) {
	  if(!dk3fig_initialize_text_details(back, txt, app)) {
	    dk3fig_obj_delete(back);
	    back = NULL;
	  }
	}
      } else {				

#line 2151 "dk3fig.ctr"
        /* +++++ ERROR: No text specified! */
      }
    } break;
    case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: {	

#line 2155 "dk3fig.ctr"
      back = dk3fig_obj_internal_new(
        li, la, ot, ((st) ? 1 : 0),
        lw, pc, fc, fi, cs, js, ls, sv, af, ab, 0,
	((st) ? 1 : 0),
	app
      );
    } break;
    default: {				

#line 2163 "dk3fig.ctr"
      /* +++++ ERROR: Can not create object! */
    } break;
  } 

#line 2166 "dk3fig.ctr"
  return back;
}


void
dk3fig_obj_init(dk3_fig_obj_t *obj)
{
  if(obj) {
    dk3mem_res((void *)obj, sizeof(dk3_fig_obj_t));
    obj->af = NULL;
    obj->ab = NULL;
    obj->dsd = NULL;
    obj->sv = 0.0;
  }
}



void
dk3fig_set_options_bsegs(dk3_fig_drawing_t *drw, size_t xssbs, size_t qbs)
{
  if(drw) {
    drw->xssbs = xssbs;
    drw->qbs = qbs;
    if(xssbs < 2) drw->xssbs = 2;
    if(qbs < 2) drw->qbs = 2;
  }
}



void
dk3fig_set_options_lighten(dk3_fig_drawing_t *drw, int val)
{
  if(drw) {
    drw->lighten = ((val) ? 1 : 0);
  }
}




void
dk3fig_set_options_coah(dk3_fig_drawing_t *drw, int val)
{
  if(drw) {
    drw->coah = ((val) ? 1 : 0);
  }
}



void
dk3fig_set_options_cosp(dk3_fig_drawing_t *drw, int val)
{
  if(drw) {
    drw->cosp = ((val) ? 1 : 0);
  }
}



void
dk3fig_set_options_bbts(dk3_fig_drawing_t *drw, int val)
{
  if(drw) {
    drw->bbts = ((val) ? 1 : 0);
  }
}



void
dk3fig_set_options_srctype(dk3_fig_drawing_t *drw, int val)
{
  if(drw) {
    drw->srctype = val;
  }
}



void
dk3fig_set_options_arrows(
  dk3_fig_drawing_t	*drw,
  double		 arcspp,
  double		 splspp,
  size_t		 minspp
)
{
  if(drw) {
    drw->arcspp = arcspp;
    if(drw->arcspp < 2.0) { drw->arcspp = 2.0; }
    drw->splspp = splspp;
    if(drw->splspp < 2.0) { drw->splspp = 2.0; }
    drw->minspp = minspp;
    if(drw->minspp < 2) { drw->minspp = 2; }
  }
}



void
dk3fig_set_options_iteration_precision(
  dk3_fig_drawing_t	*drw,
  double		 prec
)
{
  if(drw) {
    drw->xsprec = fabs(prec);
    if(drw->xsprec < 1.0e-24) {
      drw->xsprec = 1.0e-24;
    }
  }
}


void
dk3fig_gs_init(dk3_graphics_state_t *gs)
{
  if(gs) {
    (gs->c1).r = (gs->c1).g = (gs->c1).b = 0.0;
    (gs->c2).r = (gs->c2).g = (gs->c2).b = 0.0;
    gs->lw  = -1.0;
    gs->sv  = -1.0;
    gs->slw = -1.0;
    gs->lc  = gs->lj = gs->ls = 0;
    gs->hc1 = gs->hc2 = gs->hlc = gs->hlj = gs->hlw = gs->hls = 0;
    gs->hfn = 0; gs->fs = -1.0; gs->fn = -1;
  }
}



void
dk3fig_set_options_codi(
  dk3_fig_drawing_t	*drw,
  size_t		 codi
)
{
  if(drw) {
    drw->codi = codi;
  }
}



void
dk3fig_set_ec(dk3_fig_drawing_t *drw, int ec)
{
  if(drw) {
    if(0 == drw->ec) {
      drw->ec = ec;
    }
  }
}


