/*
Copyright (c) 2004-2005, Dirk Krause
All rights reserved.

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 Dirk Krause nor the names of
  its 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.
*/

#define DKFIGSVG_C 1
#include "dkfig.h"

#line 40 "dkfigsvg.ctr"




#define drd(v,o,w) dkfig_tool2_drd(v,o,w)



/* {{{ data type definitions */

#define OI dkfig_svg_output_instruction
#define DRVE dk_fig_svg_drve
#define SVGPAT dk_fig_svg_pat
#define SVGSTY dk_fig_svg_style
#define OBJ dk_fig_object
#define AH dk_fig_arrow


typedef char *PCHAR;
typedef PCHAR *PPCHAR;

/* }}} */



/* {{{ output keywords */

static char *kw[] = {
/*  00 */ "\n",
/*  01 */ " ",
/*  02 */ "<",
/*  03 */ ">",
/*  04 */ "/",
/*  05 */ "svg",
/*  06 */ "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>",
/*  07 */ "!DOCTYPE svg PUBLIC",
/*  08 */ "\"-//W3C//DTD SVG 20010904//EN\"",
/*  09 */ "\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"",
/*  10 */ "xmlns=\"http://www.w3.org/2000/svg\"",
/*  11 */ "xmlns:xlink=\"http://www.w3.org/1999/xlink\"",
/*  12 */ "\"-//W3C//DTD SVG 1.1//EN\"",
/*  13 */ "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"",
/*  14 */ "x",
/*  15 */ "y",
/*  16 */ "width",
/*  17 */ "height",
/*  18 */ "viewBox",
/*  19 */ "=",
/*  20 */ "\"",
/*  21 */ "in",
/*  22 */ "px",
/*  23 */ "xmlns:svg=\"http://www.w3.org/2000/svg\"",
/*  24 */ ":",
/*  25 */ "title",
/*  26 */ "desc",
/*  27 */ "Converted by fig2vect, see http://fig2vect.sourceforge.net",
/*  28 */ "defs",
/*  29 */ "type=\"text/ecmascript\"",
/*  30 */ "<![CDATA[",
/*  31 */ "]]>",
/*  32 */ "script",
/*  33 */ "a",
/*  34 */ "g",
/*  35 */ "pattern",
/*  36 */ "id",
/*  37 */ "p",
/*  38 */ "style",
/*  39 */ "type=\"text/css\"",
/*  40 */ ".",
/*  41 */ "{",
/*  42 */ "}",
/*  43 */ ";",
/*  44 */ "c",
/*  45 */ "#",
/*  46 */ "font-family",
/*  47 */ "font-style",
/*  48 */ "font-weight",
/*  49 */ "font-size",
/*  50 */ "color",
/*  51 */ "text-anchor",
/*  52 */ "start",
/*  53 */ "middle",
/*  54 */ "end",
/*  55 */ ",",
/*  56 */ "serif",
/*  57 */ "sans-serif",
/*  58 */ "monospace",
/*  59 */ "normal",
/*  60 */ "italic",
/*  61 */ "bold",
/*  62 */ "fill",
/*  63 */ "stroke",
/*  64 */ "stroke-width",
/*  65 */ "none",
/*  66 */ "stroke-dasharray",
/*  67 */ "stroke-linecap",
/*  68 */ "butt",
/*  69 */ "round",
/*  70 */ "square",
/*  71 */ "stroke-linejoin",
/*  72 */ "miter",
/*  73 */ "bevel",
/*  74 */ "url",
/*  75 */ "(",
/*  76 */ ")",
/*  77 */ "text",
/*  78 */ "img",
/*  79 */ "rect",
/*  80 */ "class",
/*  81 */ "pt",
/*  82 */ "rx",
/*  83 */ "ry",
/*  84 */ "polygon",
/*  85 */ "polyline",
/*  86 */ "points",
/*  87 */ "cx",
/*  88 */ "cy",
/*  89 */ "r",
/*  90 */ "circle",
/*  91 */ "ellipse",
/*  92 */ "transform",
/*  93 */ "translate",
/*  94 */ "rotate",
/*  95 */ "rx",
/*  96 */ "ry",
/*  97 */ "-",
/*  98 */ "path",
/*  99 */ "d",
/* 100 */ "M",
/* 101 */ "L",
/* 102 */ "A",
/* 103 */ "0",
/* 104 */ "1",
/* 105 */ "z",
/* 106 */ "C",
/* 107 */ "'",
/* 108 */ "@font-face",
/* 109 */ "src: ",
/* 110 */ "format(svg)",
/* 111 */ "patternUnits=\"userSpaceOnUse\"",
/* 112 */ "image",
/* 113 */ "<!-- ",
/* 114 */ " -->",
/* 115 */ "line ",
/* 116 */ "layer ",
};
static size_t kw_num = sizeof(kw)/sizeof(PCHAR);

/* }}} */



/* {{{ configuration keywords */

static char *cmd00[] = { "js", "library", NULL };
static char *cmd01[] = { "id", NULL };
static char *cmd02[] = { "onfocusin", NULL };
static char *cmd03[] = { "onfocusout", NULL };
static char *cmd04[] = { "onactivate", NULL };
static char *cmd05[] = { "onclick", NULL };
static char *cmd06[] = { "onmousedown", NULL };
static char *cmd07[] = { "onmouseup", NULL };
static char *cmd08[] = { "onmouseover", NULL };
static char *cmd09[] = { "onmousemove", NULL };
static char *cmd10[] = { "onmouseout", NULL };
static char *cmd11[] = { "onload", NULL };
static char *cmd12[] = { "onunload", NULL };
static char *cmd13[] = { "onabort", NULL };
static char *cmd14[] = { "onerror", NULL };
static char *cmd15[] = { "onresize", NULL };
static char *cmd16[] = { "onscroll", NULL };
static char *cmd17[] = { "onzoom", NULL };
static char *cmd18[] = { "onbegin", NULL };
/* static char *cmd19[] = { "onened", NULL }; */
static char *cmd19[] = { "onend", NULL };
static char *cmd20[] = { "onrepeat", NULL };
static char *cmd21[] = { "gs", "svg-font", "directory", NULL };

static char **cmds[] = {
  /*  00 */	cmd00,	/* js library */
  /*  01 */	cmd01,	/* id */
  /*  02 */	cmd02,	/* onfocusin */
  /*  03 */	cmd03,	/* onfocusout */
  /*  04 */	cmd04,	/* onactivate */
  /*  05 */	cmd05,	/* onclick */
  /*  06 */	cmd06,	/* onmousedown */
  /*  07 */	cmd07,	/* onmouseup */
  /*  08 */	cmd08,	/* onmouseover */
  /*  09 */	cmd09,	/* onmousemove */
  /*  10 */	cmd10,	/* onmouseout */
  /*  11 */	cmd11,	/* onload */
  /*  12 */	cmd12,	/* onunload */
  /*  13 */	cmd13,	/* onabort */
  /*  14 */	cmd14,	/* onerror */
  /*  15 */	cmd15,	/* onresize */
  /*  16 */	cmd16,	/* onscroll */
  /*  17 */	cmd17,	/* onzoom */
  /*  18 */	cmd18,	/* onbegin */
  /*  19 */	cmd19,	/* onend */
  /*  20 */	cmd20,	/* onrepeat */
  /*  21 */	cmd21,	/* urw font directory */
  NULL
};
static size_t sz_cmds = (sizeof(cmds)/sizeof(PPCHAR)) - 1;

/* }}} */


/* {{{ String exploder pattern */
static char exploder_pattern[] = { " \t\r\n." };
/* }}} */


/* {{{ file open mode */
static char str_mode_open_read[] = { "r" };
/* }}} */




/* {{{ font family names for the URW fonts */

static char urw_svg_nimbus_roman_no9_l[] = {
  "Nimbus Roman No9 L"
};
static char urw_svg_urw_gothic_l[] = {
  "URW Gothic L"
};
static char urw_svg_urw_bookman_l[] = {
  "URW Bookman L"
};
static char urw_svg_nimbus_mono_l[] = {
  "Nimbus Mono L"
};
static char urw_svg_nimbus_sans_l[] = {
  "Nimbus Sans L"
};
static char urw_svg_nimbus_sans_condensed[] = {
  "Nimbus Sans L"
};
static char urw_svg_century_schoolbook_l[] = {
  "Century Schoolbook L"
};
static char urw_svg_urw_palladio_l[] = {
  "URW Palladio L"
};
static char urw_svg_standard_symbols_l[] = {
  "Standard Symbols L"
};
static char urw_svg_urw_chancery_l[] = {
  "URW Chancery L"
};
static char urw_svg_dingbats[] = {
  "Dingbats"
};

static char *urw_svg_font_families[] = {
/*  0 n021003l */	urw_svg_nimbus_roman_no9_l,
/*  1 n021023l */	urw_svg_nimbus_roman_no9_l,
/*  2 n021004l */	urw_svg_nimbus_roman_no9_l,
/*  3 n021004l */	urw_svg_nimbus_roman_no9_l,
/*  4 n021023l */	urw_svg_urw_gothic_l,
/*  5 a010033l */	urw_svg_urw_gothic_l,
/*  6 a010015l */	urw_svg_urw_gothic_l,
/*  7 a010035l */	urw_svg_urw_gothic_l,
/*  8 b018012l */	urw_svg_urw_bookman_l,
/*  9 b018032l */	urw_svg_urw_bookman_l,
/* 10 b018015l */	urw_svg_urw_bookman_l,
/* 11 b018035l */	urw_svg_urw_bookman_l,
/* 12 n022003l */	urw_svg_nimbus_mono_l,
/* 13 n022023l */	urw_svg_nimbus_mono_l,
/* 14 n022004l */	urw_svg_nimbus_mono_l,
/* 15 n022024l */	urw_svg_nimbus_mono_l,
/* 16 n019003l */	urw_svg_nimbus_sans_l,
/* 17 n019023l */	urw_svg_nimbus_sans_l,
/* 18 n019004l */	urw_svg_nimbus_sans_l,
/* 19 n019024l */	urw_svg_nimbus_sans_l,
/* 20 n019043l */	urw_svg_nimbus_sans_condensed,
/* 21 n019063l */	urw_svg_nimbus_sans_condensed,
/* 22 n019044l */	urw_svg_nimbus_sans_condensed,
/* 23 n019064l */	urw_svg_nimbus_sans_condensed,
/* 24 c059013l */	urw_svg_century_schoolbook_l,
/* 25 c059033l */	urw_svg_century_schoolbook_l,
/* 26 c059016l */	urw_svg_century_schoolbook_l,
/* 27 c059036l */	urw_svg_century_schoolbook_l,
/* 28 p052003l */	urw_svg_urw_palladio_l,
/* 29 p052023l */	urw_svg_urw_palladio_l,
/* 30 p052004l */	urw_svg_urw_palladio_l,
/* 31 p052024l */	urw_svg_urw_palladio_l,
/* 32 s050000l */	urw_svg_standard_symbols_l,
/* 33 z003034l */	urw_svg_urw_chancery_l,
/* 34 d050000l */	urw_svg_dingbats
};

/* }}} */



/* {{{ file name used when processing standard input */

static char name_stdin[] = { "standard input" };

/* }}} */



/* {{{ keywords for links */

static char *xlc00[] = { "xlink:href", NULL };
static char *xlc01[] = { "xlink:type", NULL };
static char *xlc02[] = { "xlink:role", NULL };
static char *xlc03[] = { "xlink:arcrole", NULL };
static char *xlc04[] = { "xlink:title", NULL };
static char *xlc05[] = { "xlink:show", NULL };
static char *xlc06[] = { "xlink:actuate", NULL };

static char **xlcmds[] = {
  xlc00,
  xlc01,
  xlc02,
  xlc03,
  xlc04,
  xlc05,
  xlc06,
  NULL
};

static size_t sz_xlcmds = (sizeof(xlcmds)/sizeof(PPCHAR)) - 1;

/* }}} */



/* {{{ Compare two values */

#define COMPARE(a,b) ((a > b) ? 1 : ((a < b) ? -1 : 0))

/* }}} */



/* {{{ round_down_digits

   Restrict number of digits after decimal dot, use
   downward rounding.

*/
static
double
round_down_digits DK_P2(double,x,unsigned,dig)
{
  double back, newval;
  unsigned cc, didcc;
  int errc;
  
  newval = back = x; cc = dig; didcc = 0; errc = 0;
  while (cc--) {
    newval = dkma_mul_double_ok(back, 10.0, &errc);
    if (errc) {
      cc = 0;
    } else {
      back = newval; didcc++;
    }
  }
  back = floor(back);
  while (didcc--) {
    back = back / 10.0;
  }
  
  return back;
} /* }}} */



/* {{{ dkfig_svg_comp_pat

   Compare two pattern information structures.

*/
int
dkfig_svg_comp_pat DK_P3(void *,l, void *,r, int,cr)
{
  int back = 0;
  SVGPAT *lp, *rp;
  
  lp = (SVGPAT *)l; rp = (SVGPAT *)r;
  switch(cr) {
    case 1: {
    } break;
    default: {
      if(l) {
        if(r) {
	  back = COMPARE((lp->flags),(rp->flags)) ;
	  if(!back) {
	    back = COMPARE((lp->pattp),(rp->pattp)) ;
	  }
	  /*
	  if(!back) {
	    back = COMPARE((lp->lw),(rp->lw)) ;
	  }
	  */
	  if(!back) {
	    back = COMPARE((lp->patrp),(rp->patrp)) ;
	  }
	  if(!back) {
	    back = COMPARE((lp->sred),(rp->sred)) ;
	  }
	  if(!back) {
	    back = COMPARE((lp->sgreen),(rp->sgreen)) ;
	  }
	  if(!back) {
	    back = COMPARE((lp->sblue),(rp->sblue)) ;
	  }
	  if((!back) && ((lp->flags) & 1UL)) {
	    back = COMPARE((lp->fred),(rp->fred)) ;
	  }
	  if((!back) && ((lp->flags) & 1UL)) {
	    back = COMPARE((lp->fgreen),(rp->fgreen)) ;
	  }
	  if((!back) && ((lp->flags) & 1UL)) {
	    back = COMPARE((lp->fblue),(rp->fblue)) ;
	  }
	} else {
	  back = 1;
	}
      } else {
        if(r) {
	  back = -1;
	}
      }
    } break;
  } 
  return back;
} /* }}} */



/* {{{ svg_pat_del

   Destroy pattern information structure.

*/
static
void
svg_pat_del DK_P1(SVGPAT *,p)
{
  
  if(p) {
    
    
    
    
    
    
    
    
    
    
    DK_MEMRES(p,sizeof(SVGPAT)) ;
    dk_delete(p);
  } 
} /* }}} */



/* {{{ svg_pat_null

   Initialize pattern information structure.

*/
static
void
svg_pat_null DK_P1(SVGPAT *,p)
{
  
  if(p) {
    DK_MEMRES(p,sizeof(SVGPAT)) ;
    
    
    
    
    
    
    
    
    
    
  } 
} /* }}} */



/* {{{ create_epsilon

   Create a tolerance value to compare two
   double values.

*/
static
double
create_epsilon DK_P2(double,d1, double,d2)
{
  double back = 0.000001;
  double x1, x2, min;
  x1 = fabs(d1); x2 = fabs(d2);
  min = x1;
  if(x2 < x1) { min = x2; }
  back = min * 0.000001;
  return back;
} /* }}} */



/* {{{ dkfig_svg_comp_style

   Compare two style information structures.

*/
int
dkfig_svg_comp_style DK_P3(void *,l, void *,r, int,cr)
{
  int back = 0;
  SVGSTY *lp, *rp;
  
  lp = (SVGSTY *)l; rp = (SVGSTY *)r;
  switch(cr) {
    case 1: {
      
    } break;
    default: {
      if(l) {
        if(r) {
	  
	  if(!back) {
	    back = COMPARE((lp->flags),(rp->flags)) ;
	  }
	  
	  
	  
	  
          if((lp->flags) & DKFIG_SVG_FL_TEXT) {
	    
	    if(!back) {
	      back = COMPARE((lp->sred),(rp->sred)) ;
	    }
	    if(!back) {
	      back = COMPARE((lp->sgreen),(rp->sgreen)) ;
	    }
	    if(!back) {
	      back = COMPARE((lp->sblue),(rp->sblue)) ;
	    }
	    /*
	      2004/11/22 Bugfix:
	      The following comparisons must be executed
	      only if there is no comparison result yet!
	    */
            if(!back) {
	      if(lp->fonth) {
	        if(rp->fonth) {
	          back = dkfig_fnt_comp_fonth(
		    (void *)(lp->fonth),(void *)(rp->fonth), 0
		  ); 
	        } else {
	          back = 1;
	        }
	      } else {
	        if(rp->fonth) {
	          back = -1;
	        }
	      }
	    }
	    if(!back) {
	      if(lp->talign > rp->talign) {
	        back = 1;
	      } else {
	        if(lp->talign < rp->talign) {
	          back = -1;
	        }
	      }
	    }
	  } else {
	    
	    if((lp->flags) & DKFIG_SVG_FL_STROKE) {
	      if(!back) {
	        back = COMPARE((lp->lw),(rp->lw)) ;
	      }
	      if(!back) {
	        back = COMPARE((lp->ls),(rp->ls)) ;
	      }
	      if(!back) {
	        back = COMPARE((lp->lc),(rp->lc)) ;
	      }
	      if(!back) {
	        back = COMPARE((lp->lj),(rp->lj)) ;
	      }
	      if(!back) {
	        back = COMPARE((lp->sred),(rp->sred)) ;
	      }
	      if(!back) {
	        back = COMPARE((lp->sgreen),(rp->sgreen)) ;
	      }
	      if(!back) {
	        back = COMPARE((lp->sblue),(rp->sblue)) ;
	      }
	      if(!back) {
	        double epsilon;
	        epsilon = create_epsilon(lp->sv, rp->sv);
	        if(lp->sv > (rp->sv + epsilon)) {
	          back = 1;
	        } else {
	          if(rp->sv > (lp->sv + epsilon)) {
		    back = -1;
		  }
	        }
	      }
	    }
	    if((!back) && ((lp->flags) & DKFIG_SVG_FL_FILL)) {
	      if(lp->pat) {
	        if(rp->pat) {
	          back = dkfig_svg_comp_pat((void *)(lp->pat),(void *)(rp->pat), 0);
	        } else {
	          back = 1;
	        }
	      } else {
	        if(rp->pat) {
	          back = -1;
	        } else {
	          back = COMPARE((lp->fred),(rp->fred)) ;
		  if(!back) {
		    back = COMPARE((lp->fgreen),(rp->fgreen)) ;
		  }
		  if(!back) {
		    back = COMPARE((lp->fblue),(rp->fblue)) ;
		  }
	        }
	      }
	    }
	  }
	} else { back = -1; }
      } else {
        if(r) { back = -1; }
      }
    } break;
  } 
  return back;
} /* }}} */



/* {{{ svg_style_del

   Destroy style information structure.

*/
static
void
svg_style_del DK_P1(SVGSTY *,s)
{
  
  if(s) {
    
    
    
    
    
    
    
    
    
    
    DK_MEMRES(s,sizeof(SVGSTY)) ;
    dk_delete(s);
  } 
} /* }}} */



/* {{{ svg_style_null

   Reset a style information structure.

*/
static
void
svg_style_null DK_P1(SVGSTY *,s)
{
  if(s) {
    DK_MEMRES(s,sizeof(SVGSTY)) ;
    s->pat = NULL;
    s->fonth = NULL;
    s->sv = 1.0;
  }
} /* }}} */



/* {{{ dkfig_svg_comp_attr

   Compare two attribute structures or compare
   one structure against a class id.

*/
int
dkfig_svg_comp_attr DK_P3(void *,l, void *,r, int,cr)
{
  int back = 0;
  dk_fig_svg_attr *lp, *rp; int *ip;
  if(l) {
    if(r) {
      lp = (dk_fig_svg_attr *)l;
      switch(cr) {
        case 1: {	/* search for classid */
	  ip = (int *)r;
	  if((lp->classid) > *ip) {
	    back = 1;
	  } else {
	    if((lp->classid) < *ip) {
	      back = -1;
	    }
	  }
	} break;
	default: {	/* compare by classid */
	  rp = (dk_fig_svg_attr *)r;
	  if((lp->classid) > (rp->classid)) {
	    back = 1;
	  } else {
	    if((lp->classid) < (rp->classid)) {
	      back = -1;
	    }
	  }
	} break;
      }
    } else {
      back = 1;
    }
  } else {
    if(r) { back = -1; }
  }
  return back;
} /* }}} */



/* {{{ dkfig_svg_attr_del

   Destroy attribute structure, release memory
   associated with it.

*/
static
void
dkfig_svg_attr_del DK_P1(dk_fig_svg_attr *,a)
{
  char *ptr;
  
  if(a) {
    if(a->value) {
      ptr = a->value; 
      dk_delete(ptr);
      a->value = NULL;
    }
    dk_delete(a);
  } 
} /* }}} */



/* {{{ dkfig_svg_attr_new

   Create new attribute structure, initialize it.

*/
static
dk_fig_svg_attr *
dkfig_svg_attr_new DK_P2(int,clid, char *,v)
{
  dk_fig_svg_attr *back = NULL;
  
  if(v) {
    back = dk_new(dk_fig_svg_attr,1);
    if(back) {
      back->classid = clid;
      back->value = dkstr_dup(v);
      if(!(back->value)) {
        dkfig_svg_attr_del(back);
	back = NULL;
      }
    }
  } 
  return back;
} /* }}} */



/* {{{ kw_out

   Write one keyword from the list.

*/
static
int
kw_out DK_P2(OI *,oi,size_t,kn)
{
  int back = 0;
  if(kn < kw_num) {
    dkstream_puts(oi->s, kw[kn]);
    back = 1;
  }
  return back;
} /* }}} */



/* {{{ put_double

   Put double to output.

*/
static
void
put_double DK_P3(OI *,oi, double,x, int,w)
{
  dkstream_puts_double(oi->s, drd(x, oi->c, w));
} /* }}} */



/* {{{ convert coordinates from Fig space to SVG space */


/* {{{ double values */

/* x */
static
double
ccdx DK_P2(OI *,oi, double,x)
{
  double back;
  back = dkma_add_double_ok(
    dkma_mul_double_ok(oi->mx, x, &(oi->me)),
    oi->nx,
    &(oi->me)
  );
  return back;
}

/* y */
static
double
ccdy DK_P2(OI *,oi, double,y)
{
  double back;
  back = dkma_add_double_ok(
    dkma_mul_double_ok(oi->my, y, &(oi->me)),
    oi->ny,
    &(oi->me)
  );
  return back;
}

/* radius */
static
double
ccdr DK_P2(OI *,oi, double,r)
{
  double back;
  back = dkma_mul_double_ok(oi->mx, r, &(oi->me));
  return back;
}

/* line width */
static
double
ccdl DK_P3(OI *,oi, double,w, int,use_enl)
{
  double back;
  back = 0.9 * w;
  if(use_enl) {
    if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
      back = 0.5 * back;
    }
  }
  return back;
}

/* }}} */


/* {{{ long values */

/* x */
static
double
cclx DK_P2(OI *,oi, long,x)
{
  double back;
  back = ccdx(oi, dkma_l_to_double(x));
  return back;
}

/* y */
static
double
ccly DK_P2(OI *,oi, long,y)
{
  double back;
  back = ccdy(oi, dkma_l_to_double(y));
  return back;
}

/* radius */
static
double
cclr DK_P2(OI *,oi, long,r)
{
  double back;
  back = ccdr(oi, dkma_l_to_double(r));
  return back;
}

/* line width */
static
double
ccll DK_P3(OI *,oi, long,w, int,use_enl)
{
  double back;
  back = ccdl(oi, dkma_l_to_double(w), use_enl);
  return back;
}
/* }}} */

/* }}} */



/* {{{ svg_drve_init

   Initialize DRVE structure.

*/
static
void
svg_drve_init DK_P1(dk_fig_svg_drve *,p)
{
  
  if(p) {
    p->st1 = p->st2 = p->st3 = NULL;
    p->attr = NULL; p->attri = NULL;
    p->xl   = NULL; p->xli   = NULL;
  }
  
} /* }}} */



#define MEMFREE(x) if(x) { ptr = x; dk_delete(ptr); } x = NULL;



/* {{{ svg_drve_delete

   Destroy DRVE structure, release memory associated
   with it.

*/
static
void
svg_drve_delete DK_P1(dk_fig_svg_drve *,p)
{
  dk_fig_svg_attr *a;
  
  if(p) {
    p->st1 = p->st2 = p->st3 = NULL;
    if(p->attri) {
      
      dksto_it_reset(p->attri);
      while((a = (dk_fig_svg_attr *)dksto_it_next(p->attri)) != NULL) {
        dkfig_svg_attr_del(a);
      }
      dksto_it_close(p->attri);
    } p->attri = NULL;
    if(p->attr) {
      dksto_close(p->attr);
    } p->attr = NULL;
    if(p->xli) {
      
      dksto_it_reset(p->xli);
      while((a = (dk_fig_svg_attr *)dksto_it_next(p->xli)) != NULL) {
        dkfig_svg_attr_del(a);
      }
      dksto_it_close(p->xli);
    } p->xli = NULL;
    if(p->xl) {
      dksto_close(p->xl);
    } p->xl = NULL;
    dk_delete(p);
  } 
} /* }}} */



/* {{{ svg_drve_new

   Create new DRVE structure, initialize it.

*/
static
dk_fig_svg_drve *
svg_drve_new DK_P0()
{
  dk_fig_svg_drve *back = NULL;
  
  back = dk_new(dk_fig_svg_drve,1);
  if(back) {
    svg_drve_init(back);
  } 
  return back;
} /* }}} */



/* {{{ svg_drve_add_xla

   Add <a xlink:...="..."> attribute to DRVE.
*/
static
int
svg_drve_add_xla DK_P4(OI *,oi,\
  dk_fig_svg_drve *,dr, int,clid, char *,v\
)
{
  int back = 0; dk_fig_svg_attr *a; char *nn;
  
  if(dr) {
    if(!(dr->xl)) {
      dr->xl = dksto_open(0);
      if(dr->xl) {
        dksto_set_comp(dr->xl, dkfig_svg_comp_attr, 0);
      }
    }
    if(dr->xl) {
      if(!(dr->xli)) {
        dr->xli = dksto_it_open(dr->xl);
      }
      if(dr->xli) {
        if(v) {
	  a = (dk_fig_svg_attr *)dksto_it_find_like(
	    dr->xli, (void *)(&clid), 1
	  );
	  if(a) {
	    nn = dkstr_dup(v);
	    if(nn) {
	      if(a->value) {
	        char *ptr;
		ptr = a->value;
		/* WARNING: Already defined */
		dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_WARNING, 93, 92, (xlcmds[clid])[0]);
		dk_delete(ptr);
		a->value = NULL;
	      }
	      a->value = nn; back = 1;
	    }
	  } else {
            a = dkfig_svg_attr_new(clid, v);
	    if(a) {		
	      if(dksto_add(dr->xl, (void *)a)) {
	        back = 1;	
	      } else {	
	        dkfig_svg_attr_del(a);
	      }
	    }
	  }
	}
      }
    }
  } 
  return back;
} /* }}} */



/* {{{ svg_drve_add_attr

   Add attribute to DRVE.

*/
static
int
svg_drve_add_attr DK_P4(OI *,oi,\
  dk_fig_svg_drve *,dr, int,clid, char *,v\
)
{
  int back = 0; dk_fig_svg_attr *a; char *nn;
  
  if(dr) {
    if(!(dr->attr)) {	
      dr->attr = dksto_open(0);
      if(dr->attr) {	
        dksto_set_comp(dr->attr, dkfig_svg_comp_attr, 0);
      }
    }
    if(dr->attr) {	
      if(!(dr->attri)) {	
        dr->attri = dksto_it_open(dr->attr);
      }
      if(dr->attri) {	
        if(v) {		
	  a = (dk_fig_svg_attr *)dksto_it_find_like(
	    dr->attri, (void *)(&clid), 1
	  );
	  if(a) {
	    nn = dkstr_dup(v);
	    if(nn) {
	      if(a->value) {
	        char *ptr;
		
		/* WARNING: Already defined */
		dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_WARNING, 93, 92, (cmds[clid])[0]);
		ptr = a->value;
		dk_delete(ptr);
		a->value = NULL;
	      }
	      a->value = nn;
	      back = 1;
	    }
	  } else {
            a = dkfig_svg_attr_new(clid, v);
	    if(a) {		
	      if(dksto_add(dr->attr, (void *)a)) {
	        back = 1;	
	      } else {	
	        dkfig_svg_attr_del(a);
	      }
	    }
	  }
        }
      }
    }
  } 
  return back;
} /* }}} */



/* {{{ begin_tag

   Start a new tag.

*/
static
void
begin_tag DK_P2(OI *,oi, size_t,n)
{
  
  kw_out(oi, 2);
  if(((oi->c)->opt1) & DKFIG_OPT_SVG_EMBEDDED) {
    kw_out(oi, 5);
    kw_out(oi, 24);
  }
  kw_out(oi, n);
  
} /* }}} */



/* {{{ finish_tag

   Finish a tag.

*/
static
void
finish_tag DK_P1(OI *,oi)
{
  
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);
  
} /* }}} */



/* {{{ end_tag

   Write a closing tag.

*/
static
void
end_tag DK_P2(OI *,oi, size_t,n)
{
  
  kw_out(oi, 2); kw_out(oi, 4);
  if(((oi->c)->opt1) & DKFIG_OPT_SVG_EMBEDDED) {
    kw_out(oi, 5); kw_out(oi, 24);
  }
  kw_out(oi, n); kw_out(oi, 3); kw_out(oi, 0);
  
} /* }}} */



/* {{{ null_oi

   Reset OI structure.

*/
static
void
null_oi DK_P1(OI *,oi)
{
  
  oi->c = NULL;
  oi->d = NULL;
  oi->s = NULL;
  oi->dro = NULL;
  oi->xmin = oi->xmax = oi->ymin = oi->ymax = 0L;
  oi->mx = oi->nx = oi->my = oi->ny = 0.0;
  oi->me = 0;
  oi->fl = NULL;
  oi->fli = NULL;
  oi->pat = NULL;
  oi->pati = NULL;
  oi->sty = NULL;
  oi->styi = NULL;
  oi->o = NULL;
  oi->jsl = NULL; oi->jsli = NULL; oi->njsl = 0UL;
  oi->spcp = 0;
  oi->errprinted = 0;
  oi->npat = oi->nsty = 0UL;
  oi->lpat = oi->lsty = (size_t)0;
  oi->urw_dir = NULL;
  oi->fnused = NULL;
  oi->prep_mods = 0;
  oi->spcpass = 0;
  oi->fontmap = NULL;
  
} /* }}} */



/* {{{ establish_coord_transformation

   Calculate coefficients for transformations.

*/
static
int
establish_coord_transformation DK_P1(OI *,oi)
{
  int back = 1;
  double xmin, xmax, ymin, ymax, cxmin, cxmax, cymin, cymax;
  
  oi->me = 0;
  /*
    Get minima and maxima in Fig resolution.
  */
  xmin = dkfig_tool_bb_get_xmin(&(oi->d->dbb));
  xmax = dkfig_tool_bb_get_xmax(&(oi->d->dbb));
  ymin = dkfig_tool_bb_get_ymin(&(oi->d->dbb));
  ymax = dkfig_tool_bb_get_ymax(&(oi->d->dbb));
  /*
    Set scale factors to switch from Fig resolution
    to normal resolution.
  */
  oi->mx = dkma_div_double_ok( 72.0, (oi->d)->fres, &(oi->me));
  oi->my = oi->mx;
  if(!dkfig_tool_invert_y(oi->d)) {
    oi->my = 0.0 - oi->my;
  } 
  /*
    Calculate minima and maxima after resolution change.
  */
  xmin = dkma_mul_double_ok(xmin, oi->mx, &(oi->me));
  xmax = dkma_mul_double_ok(xmax, oi->mx, &(oi->me));
  ymin = dkma_mul_double_ok(ymin, oi->my, &(oi->me));
  ymax = dkma_mul_double_ok(ymax, oi->my, &(oi->me));
  /*
    Maximum/minimum swap if necessary.
  */
  if(xmax < xmin) {
    cxmin = xmin; xmin = xmax; xmax = cxmin;
  }
  if(ymax < ymin) {
    cxmin = ymin; ymin = ymax; ymax = cxmin;
  }
  /*
    Change to int values.
  */
  
  if(((oi->c)->svgs) == DKFIG_SVG_VP_INCHES) {
    /*
      Rounding in multiples of 9 produces 1/8 inch.
      So width/height specification in inches is restricted
      to 3 digits after decimal dot.
    */
    
    cxmin = dkma_mul_double_ok(9.0, floor(xmin/9.0), &(oi->me));
    cymin = dkma_mul_double_ok(9.0, floor(ymin/9.0), &(oi->me));
    cxmax = dkma_mul_double_ok(9.0, ceil(xmax/9.0), &(oi->me));
    cymax = dkma_mul_double_ok(9.0, ceil(ymax/9.0), &(oi->me));
    
  } else {
    /*
      Simple rounding if no inches.
    */
    cxmin = floor(xmin); cxmax = ceil(xmax);
    cymin = floor(ymin); cymax = ceil(ymax);
  }
  
  
  /*
    Calculate shiftings.
    First move xmin to 0, add half of the empty space to get
    figure centered in output file.
  */
  oi->nx = dkma_add_double_ok(
    dkma_sub_double_ok(0.0, xmin, &(oi->me)),
    (0.5 * dkma_sub_double_ok(
      dkma_sub_double_ok(cxmax, cxmin, &(oi->me)),
      dkma_sub_double_ok(xmax, xmin, &(oi->me)),
      &(oi->me)
    )),
    &(oi->me)
  );
  oi->ny = dkma_add_double_ok(
    dkma_sub_double_ok(0.0, ymin, &(oi->me)),
    (0.5 * dkma_sub_double_ok(
      dkma_sub_double_ok(cymax, cymin, &(oi->me)),
      dkma_sub_double_ok(ymax, ymin, &(oi->me)),
      &(oi->me)
    )),
    &(oi->me)
  );
  
  
  
  oi->xmin = 0L;
  oi->ymin = 0L;
  oi->xmax = dkma_double_to_l(ceil(dkma_sub_double_ok(cxmax, cxmin, &(oi->me))));
  oi->ymax = dkma_double_to_l(ceil(dkma_sub_double_ok(cymax, cymin, &(oi->me))));
  if(oi->me) { back = 0; }
  
  return back;
} /* }}} */



/* {{{ get_how

   Decide how to process an object.
   0 = "normal" object (polyline/polygon, spline, arc, ellipse)
   1 = text object
   2 = included image.

*/
static
int
get_how DK_P1(dk_fig_object *,o)
{
  int back = 0;
  if(o->objtype == DK_FIG_OBJ_TEXT) {
    back = 1;
  }
  if((o->objtype == DK_FIG_OBJ_POLYLINE) && (o->subtype == 5)) {
    back = 2;
  }
  return back;
} /* }}} */



/* {{{ svg_pat_register

   Register pattern. Return a pointer to an existing
   pattern in the pattern collection or add a new
   pattern to the collection.

*/
static
SVGPAT *
svg_pat_register DK_P2(OI *,oi, SVGPAT *,src)
{
  SVGPAT *back = NULL;
  
  
  
  
  
  
  
  
  
  
  
  back = (dk_fig_svg_pat *)dksto_it_find_like(oi->pati, (void *)src, 0);
  if(!back) {	
    back = dk_new(SVGPAT,1);
    if(back) {	
      
      
      
      
      
      
      
      
      
      
      DK_MEMCPY(back,src,sizeof(SVGPAT)) ;
      
      
      
      
      
      
      
      
      
      
      if(!dksto_add(oi->pat, (void *)back)) {
        
        dk_delete(back); back = NULL;
      }
    }
  } 
  return back;
} /* }}} */



/* {{{ svg_style_register

   Register an SVG style in the style collection.
   Create a new entry in the collection if necessary
   or return pointer to an existing entry.

*/
static
SVGSTY *
svg_style_register DK_P2(OI *,oi, SVGSTY *,st)
{
  SVGSTY *back = NULL;
  
  back = (dk_fig_svg_style *)dksto_it_find_like(oi->styi, (void *)st, 0);
  if(!back) {	
    back = dk_new(SVGSTY,1);
    if(back) {	
      DK_MEMCPY(back,st,sizeof(SVGSTY)) ;
      if(!dksto_add(oi->sty, (void *)back)) {
        
        dk_delete(back); back = NULL;
      }
    }
  }
  
  
  if(back) {
    
    
  }
  
  return back;
} /* }}} */



/* {{{ attach_drve

   Attach a new driver-specific extension to each
   drawing object.

*/
static
int
attach_drve DK_P1(OI *,oi)
{
  int back = 1; 
  dk_fig_object *o;
  
  dksto_it_reset(oi->fli);
  while((o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
    oi->o = o;
    
    if((oi->c)->app) {
      dkapp_set_source_lineno((oi->c)->app, o->lineno);
    }
    o->drve = svg_drve_new();
    if(!(o->drve)) {
      back = 0;	
      /* MEMORY */
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
    }
    if((oi->c)->app) {
      dkapp_set_source_lineno((oi->c)->app, 0UL);
    }
  }
  if(!((oi->dro)->drve)) {
    (oi->dro)->drve = svg_drve_new();
    if(!((oi->dro)->drve)) {
      back = 0;
      /* MEMORY */
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
    }
  }
  
  return back;
} /* }}} */



/* {{{ set_js_library

   Store the name of a file containing JavaScript code.

*/
static
int
set_js_library DK_P2(OI *,oi, char *,vptr)
{
  int back = 0;
  dk_fig_opt *fo;
  
  if(vptr) {
    back = 1;
    if(!(oi->jsl)) {
      oi->jsl = dksto_open(0);
      if(oi->jsl) {
        dksto_set_comp(oi->jsl, dkfig_opt_compare, 0);
      }
    }
    if(oi->jsl) {
      if(!(oi->jsli)) {
        oi->jsli = dksto_it_open(oi->jsl);
      }
      if(oi->jsli) {
        fo = dkfig_opt_new(oi->njsl, vptr);
	oi->njsl += 1UL;
	if(fo) {
	  if(!dksto_add(oi->jsl, (void *)fo)) {
	    back = 0;
	    dkfig_opt_delete(fo); fo = NULL;
	    /* MEMORY */
	    dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
	  }
	} else {
	  back = 0;
	  /* MEMORY */
	  dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
	}
      } else {
        back = 0;
	/* MEMORY */
	dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
      }
    } else {
      back = 0;
      /* MEMORY */
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
    }
  } 
  return back;
} /* }}} */



/* {{{ set_urw_dir

   Save the name of the directory containing
   SVG fonts derived from the URW fonts.

*/
static
int
set_urw_dir DK_P2(OI *,oi, char *,vptr)
{
  int back = 0;
  char *cptr, *nn;
  if(vptr) {
    nn = dkstr_dup(vptr);
    if(nn) {
      back = 1;
      if(oi->urw_dir) {
        cptr = oi->urw_dir;
	dk_delete(cptr);
	oi->urw_dir = NULL;
      }
      oi->urw_dir = nn;
    }
  }
  return back;
} /* }}} */



/* {{{ scan_it_options

   Process one storage containing saved options from
   the configuration file to check for
   driver-specific options.
   There are separated storages for global options,
   for the base driver, the configuration-specific
   options and command line options.

*/
static
int
scan_it_options DK_P2(OI *,oi, dk_storage_iterator_t *,it)
{
  int back = 1;
  dk_fig_opt *fo;
  char *buffer, *sptr, *vptr; size_t sz;
  char *parts[16]; size_t xsz; int i;
  
  sz = 1 + ((oi->c)->lcfge);
  buffer = dk_new(char,sz);
  if(buffer) {
    dksto_it_reset(it);
    while((fo = (dk_fig_opt *)dksto_it_next(it)) != NULL) {
      if(fo->name) { 
        if((oi->c)->app) {
	  
	  dkapp_set_source_lineno((oi->c)->app, fo->number);
	}
        if(strlen(fo->name) < sz) {	
	  strcpy(buffer, fo->name);
	  vptr = sptr = NULL;
	  vptr = dkstr_chr(buffer, '=');
	  if(vptr) {			
	    *vptr++ = '\0';
	    vptr = dkstr_start(vptr, NULL);
	    if(vptr) { dkstr_chomp(vptr, NULL); }
	  }
	  sptr = dkstr_start(buffer, NULL);
	  if(sptr) {			
	    dkstr_chomp(sptr, NULL);
	    xsz = sizeof(parts)/sizeof(PCHAR);
            if(dkstr_explode(parts,xsz,sptr,exploder_pattern)) {
	      
	      i = dkstr_find_multi_part_abbr(parts, cmds, '$', 1);
	      
	      switch(i) {
	        case 0: {	/* js library */
		  back = set_js_library(oi, vptr);
		  fo->used = 0x01;
		  oi->prep_mods = 1;
		} break;
		case 21: {	/* URW font directory */
		  back = set_urw_dir(oi, vptr);
		  fo->used = 0x01;
		} break;
	      }
	    }
	  }
	}
      }
    }
    dk_delete(buffer); buffer = NULL; sz = 0;
  } else {
    back = 0;
    if((oi->c)->app) {
      dkapp_err_memory((oi->c)->app, 1, sz);
    }
  } 
  return back;
} /* }}} */



/* {{{ scan_options

   Re-read the saved options from the configuration
   file to process the driver-specific options.

*/
static
int
scan_options DK_P1(OI *,oi)
{
  int back = 1;
  char *oldsrcfile; unsigned long oldsrcno;
  
  if((oi->c)->app) {
    oldsrcfile = dkapp_get_source_filename((oi->c)->app);
    oldsrcno = dkapp_get_source_lineno((oi->c)->app);
    dkapp_set_source_filename((oi->c)->app, (oi->c)->cfgfn);
    dkapp_set_source_lineno((oi->c)->app, 0UL);
  }
  if(((oi->c)->optg) && ((oi->c)->optgi)) {
    if(!scan_it_options(oi, (oi->c)->optgi)) { back = 0; }
  }
  if(((oi->c)->optb) && ((oi->c)->optbi)) {
    if(!scan_it_options(oi, (oi->c)->optbi)) { back = 0; }
  }
  if(((oi->c)->optd) && ((oi->c)->optdi)) {
    if(!scan_it_options(oi, (oi->c)->optdi)) { back = 0; }
  }
  if((oi->c)->app) {
    dkapp_set_source_filename((oi->c)->app, NULL);
  }
  if(((oi->c)->opt) && ((oi->c)->opti)) {
    if(!scan_it_options(oi, (oi->c)->opti)) { back = 0; }
  }
  if((oi->c)->app) {
    dkapp_set_source_filename((oi->c)->app, oldsrcfile);
    dkapp_set_source_lineno((oi->c)->app, oldsrcno);
  }
  
  return back;
} /* }}} */



/* {{{ handle_spc_for_object

   Handle special comments attached to an object.

*/
static
int
handle_spc_for_object DK_P5(\
  OI *,oi, dk_fig_object *,obj,\
  dk_storage_iterator_t *,it, int,docroot, int,use_svg_spec\
)
{
  int back = 1;
  dk_fig_opt *fo;
  char mybuffer[128], *parts[16], *myline, *lptr, *cptr, *vptr;
  size_t sz; int i;
  int handled;
  unsigned long oldsrcno = 0UL;
  
  if((oi->c)->app) {
    oldsrcno = dkapp_get_source_lineno((oi->c)->app);
  }
  if(it) {
    dksto_it_reset(it);
    while((fo = (dk_fig_opt *)dksto_it_next(it)) != NULL) {
      if((oi->c)->app) {
        dkapp_set_source_lineno((oi->c)->app, fo->number);
      }
      myline = NULL; handled = 0;
      if(fo->name) {
        sz = strlen(fo->name);
	if(sz < sizeof(mybuffer)) {
	  strcpy(mybuffer, fo->name);
	  lptr = mybuffer;
	} else {
	  myline = dkstr_dup(fo->name);
	  lptr = myline;
	}
	if(lptr) {
	  cptr = dkfig_opt_special_comment_contents(lptr, kw[5]);
	  if((cptr) && (use_svg_spec)) {
	    vptr = dkstr_chr(cptr, '=');
	    if(vptr) {
	      *(vptr++) = '\0';
	      vptr = dkstr_start(vptr, NULL);
	      if(vptr) { dkstr_chomp(vptr, NULL); }
	      cptr = dkstr_start(cptr, NULL);
	      if(cptr) {
	        dkstr_chomp(cptr, NULL);
		sz = sizeof(parts)/sizeof(PCHAR);
		if(dkstr_explode(parts,sz,cptr,exploder_pattern)) {
		  i = dkstr_find_multi_part_abbr(parts,cmds,'$',1);
		  switch(i) {
		    case -1: {	/* not in cmds list */
		      int j;
		      j = dkstr_find_multi_part_abbr(parts,xlcmds,'$',1);
		      if(j > -1) {
		        if(svg_drve_add_xla(oi, (DRVE *)(obj->drve), j, vptr)) {
			  handled = 1;
			} else {
			  back = 0;
			  /* ERROR: MEMORY */
			  dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
			}
		      }
		    } break;
		    case 0: {	/* js library */
		      handled = 1;
		      if(docroot) {
		        
		        back = set_js_library(oi, vptr);
			oi->prep_mods = 1;
		      } else {
		        /* ERROR: Only in document level comments */
			dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_WARNING, 94);
		      }
		    } break;
		    case 21: {	/* URW font directory */
		      back = set_urw_dir(oi, vptr);
		      handled = 1;
		    } break;
		    default: {
		      if(svg_drve_add_attr(oi, (DRVE *)(obj->drve), i, vptr)) {
		        handled = 1;
		      } else {
		        back = 0;
			/* ERROR: MEMORY */
			dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
		      }
		      if((i >= 2) && (i <= 20)) {
		        oi->prep_mods = 1;
		      }
		    } break;
		  }
		}
	      }
	    }
	  }
	}
      }
      if(myline) {
        dk_delete(myline); myline = NULL;
      }
      if(!handled) {
        i = dkfig_opt_process_special_comment(oi->c, fo->name, kw[5], docroot);
	if((oi->spcpass) == 0) {
	  dkfig_tool2_report_special_comment(oi->c, fo, i);
	}
#if VERSION_BEFORE_2005_06_03
        /* just a warning is enough, do not bail out */
	switch(i) {
	  case 0:
	  case -3: {
	    if(use_svg_spec) { back = 0; }
	  } break;
	}
#endif
      }
    }
  }
  if((oi->c)->app) {
    dkapp_set_source_lineno((oi->c)->app, oldsrcno);
  }
  
  return back;
} /* }}} */



/* {{{ use_dlscp

   Process the document level special comments.

*/
static
int
use_dlspc DK_P1(OI *,oi)
{
  int back = 1;
  
  back = handle_spc_for_object(oi, oi->dro, (oi->d)->dlsci, 1, 1);
  
  return back;
} /* }}} */



/* {{{ prepare_objects

   Prepare each object for output.
   Create references to patterns and styles in
   the pattern and style collections, create new
   collection entries if necessary.

*/
static
int
prepare_objects DK_P1(OI *,oi)
{
  int back = 1;
  unsigned long backupopt1;
  int how, must_draw;
  dk_fig_object *o;
  SVGSTY style, *pstyle; SVGPAT pattern, *ppattern;
  dk_fig_dcc dcc;
  
  dksto_it_reset(oi->fli);
  while((oi->o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
    o = oi->o;
    if(back) {
      backupopt1 = (oi->c)->opt1;
      if((oi->c)->app) {
        dkapp_set_source_lineno((oi->c)->app, (oi->o)->lineno);
      }
      oi->me = 0;
      if((oi->o)->osci) {
        if(!handle_spc_for_object(oi, oi->o, (oi->o)->osci, 0, 1)) {
          back = 0;	
        }
      }
      if(back) {
        how = 0; must_draw = 1;
        if(o->drve) {
          svg_style_null(&style);
          svg_pat_null(&pattern);
          how = get_how(o);
          switch(how) {
            case 1: {	/* text */
  	    dk_fig_text *t;
  	    svg_style_null(&style);
  	    style.flags = DKFIG_SVG_FL_TEXT;
  	    dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
	    /*
	      2004/11/22
	      style.fred = ...
	      Fig files store the text color as pen color,
	      SVG needs it as fill color.
	    */
  	    style.fred = style.sred = dcc.ired;
  	    style.fgreen = style.sgreen = dcc.igreen;
  	    style.fblue = style.sblue = dcc.iblue;
	    
  	    t = (dk_fig_text *)(o->data);
  	    if(t) {
  	      style.fonth = t->font_handling;
  	    }
  	    switch((style.fonth)->handling) {
  	      case 2: case 3: case 4: case 5: {
  	        if(!((oi->errprinted) & 1)) {
  	          dkfig_tool2_svg_error_message(oi, 85);
  		  if(!(((oi->c)->opt1) & DKFIG_OPT_REPORT_MULTIPLE)) {
  		    oi->errprinted |= 1;
  		  }
  	        }
  	      } break;
  	      default: {
  	        style.talign = o->subtype;
  	        if((style.fonth)->fontno < 0) {
  	          (style.fonth)->fontno = 0;
  	        }
  	        if((style.fonth)->fontno > 35) {
  	          (style.fonth)->fontno = 35;
  	        }
		(oi->fnused)[(style.fonth)->fontno] = '+';
  	        ((dk_fig_svg_drve *)(o->drve))->st1
  	        = svg_style_register(oi, &style);
  	        if(!(((dk_fig_svg_drve *)(o->drve))->st1)) {
  	          back = 0; 
  	        } else {
		  SVGSTY *stptr;
		  stptr = ((dk_fig_svg_drve *)(o->drve))->st1;
		  
		}
  	      } break;
  	    }
  	  } break;
  	  case 2: {	/* included image */
  	    svg_style_null(&style);
  	    /* filling */
            if(((oi->c)->opt1) & DKFIG_OPT_FILL_BITMAP_AREA) {
              if(dkfig_tool_must_fill((o->fpd).af, (oi->c)->opt1)
                 || dkfig_tool_must_pattern((o->fpd).af, (oi->c)->opt1))
              {
  	        style.flags |= DKFIG_SVG_FL_FILL;
  	        dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).fc);
  	        dkfig_tool_correct_dcc(&dcc, (o->fpd).fc, (o->fpd).af);
  	        if(dkfig_tool_must_pattern((o->fpd).af, (oi->c)->opt1)
  	           && ((o->fpd).pc != (oi->d)->transparent)
		   && (((oi->c)->opt1) & DKFIG_OPT_FILL_PATTERNS))
  	        {
  	          /* fill patterns */
  	          svg_pat_null(&pattern);
                    pattern.pattp = (o->fpd).af;
  	          /* pattern.lw = (o->fpd).lt; */
  	          pattern.patrp = (oi->c)->patrp;
  	          if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
  	            pattern.flags |= DKFIG_SVG_FL_ENLIGHTEN;
  	          }
  	          if((o->fpd).fc != (oi->d)->transparent) {
  	            pattern.flags |= DKFIG_SVG_FL_FILL;
  	            pattern.fred = dcc.ired;
  		    pattern.fgreen = dcc.igreen;
  		    pattern.fblue = dcc.iblue;
  	          }
  	          pattern.flags |= DKFIG_SVG_FL_STROKE;
  	          dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
  	          pattern.sred = dcc.ired;
  	          pattern.sgreen = dcc.igreen;
  	          pattern.sblue = dcc.iblue;
  	          style.pat = svg_pat_register(oi, &pattern);
  	          if(!(style.pat)) {
  	            back = 0;	
  	          }
  	        } else {
  	          /* color fill */
  	          style.fred = dcc.ired;
  	          style.fgreen = dcc.igreen;
  	          style.fblue = dcc.iblue;
  	        }
  	        ((dk_fig_svg_drve *)(o->drve))->st1
  	        = svg_style_register(oi, &style);
  	        if(!(((dk_fig_svg_drve *)(o->drve))->st1)) {
  	          back = 0;	
  	        }
              }
	    }
  	    svg_style_null(&style);
  	    /* stroking */
  	    must_draw = 1;
  	    if(o->objtype == DK_FIG_OBJ_POLYLINE) {
  	      if(o->subtype == 5) {
  	        if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BITMAP_BORDER) {
  	          must_draw = 0;
  	        }
  	      }
  	    }
  	    if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_THIN_BORDERS) {
  	      if((o->fpd).lt == 0L) {
  	        if((o->fpd).cl) {
  	          if(dkfig_tool_must_fill((o->fpd).af, (oi->c)->opt1)) {
  	            must_draw = 0;
  	          }
  	          if(dkfig_tool_must_pattern((o->fpd).af, (oi->c)->opt1)) {
  	            must_draw = 0;
  	          }
  	        }
  	      }
  	    }
  	    if((o->fpd).pc == (oi->d)->transparent) {
  	      must_draw = 0;
  	    }
            if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BG_RECTANGLE) {
	      int wbgr = 0;
	      if(((oi->c)->opt2) & DKFIG_OPT_WHITE_BGRECT) {
	        wbgr = 1;
	      }
              if(dkfig_tool2_obj_is_bg_rect(oi->o, wbgr)) { must_draw = 0; }
            } 
  	    if(must_draw) {
  	      dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
  	      style.ls = (o->fpd).ls;	
  	      style.lw = (o->fpd).lt;
  	      style.sred = dcc.ired;
  	      style.sgreen = dcc.igreen;
  	      style.sblue = dcc.iblue;
  	      style.flags |= DKFIG_SVG_FL_STROKE;
  	      if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
  	        style.flags |= DKFIG_SVG_FL_ENLIGHTEN;
  	      }
  	      style.sv = (o->fpd).sv;
	      style.lc = (o->fpd).cs;
	      style.lj = (o->fpd).js;
  	      ((dk_fig_svg_drve *)(o->drve))->st2
  	      = svg_style_register(oi, &style);
  	      if(!(((dk_fig_svg_drve *)(o->drve))->st2)) {
  	        back = 0; 
  	      }
  	    }
  	  } break;
  	  default: {	/* regular path object */
  	    svg_style_null(&style);
  	    /* filling */
            if(dkfig_tool_must_fill((o->fpd).af, (oi->c)->opt1)
               || dkfig_tool_must_pattern((o->fpd).af, (oi->c)->opt1))
            {
  	      style.flags |= DKFIG_SVG_FL_FILL;
  	      dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).fc);
  	      dkfig_tool_correct_dcc(&dcc, (o->fpd).fc, (o->fpd).af);
  	      if(dkfig_tool_must_pattern((o->fpd).af, (oi->c)->opt1)
  	         && ((o->fpd).pc != (oi->d)->transparent))
  	      {
  	        /* fill patterns */
  	        svg_pat_null(&pattern);
                pattern.pattp = (o->fpd).af;
  	        /* pattern.lw = (o->fpd).lt; */
  	        pattern.patrp = (oi->c)->patrp;
  	        if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
  	          pattern.flags |= DKFIG_SVG_FL_ENLIGHTEN;
  	        }
  	        if((o->fpd).fc != (oi->d)->transparent) {
  	          pattern.flags |= DKFIG_SVG_FL_FILL;
  	          pattern.fred = dcc.ired;
  		  pattern.fgreen = dcc.igreen;
  		  pattern.fblue = dcc.iblue;
  	        }
  	        pattern.flags |= DKFIG_SVG_FL_STROKE;
  	        dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
  	        pattern.sred = dcc.ired;
  	        pattern.sgreen = dcc.igreen;
  	        pattern.sblue = dcc.iblue;
  	        style.pat = svg_pat_register(oi, &pattern);
  	        if(!(style.pat)) {
  	          back = 0;	
  	        }
  	      } else {
  	        /* color fill */
  	        style.fred = dcc.ired;
  	        style.fgreen = dcc.igreen;
  	        style.fblue = dcc.iblue;
  	      }
            }
  	    /* stroking */
  	    must_draw = 1;
  	    if(o->objtype == DK_FIG_OBJ_POLYLINE) {
  	      if(o->subtype == 5) {
  	        if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BITMAP_BORDER) {
  	          must_draw = 0; 
  	        }
  	      }
  	    }
  	    if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_THIN_BORDERS) {
  	      if((o->fpd).lt == 0L) {
  	        if((o->fpd).cl) {
  	          if(dkfig_tool_must_fill((o->fpd).af, (oi->c)->opt1)) {
  	            must_draw = 0; 
  	          }
  	          if(dkfig_tool_must_pattern((o->fpd).af, (oi->c)->opt1)) {
  	            must_draw = 0; 
  	          }
  	        }
  	      }
  	    }
  	    if((o->fpd).pc == (oi->d)->transparent) {
  	      must_draw = 0;	
  	    }
            if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BG_RECTANGLE) {
	      int wbgr = 0;
	      if(((oi->c)->opt2) & DKFIG_OPT_WHITE_BGRECT) {
	        wbgr = 1;
	      }
              if(dkfig_tool2_obj_is_bg_rect(oi->o, wbgr)) { must_draw = 0; }
            } 
  	    if(must_draw) {	
  	      dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
  	      style.ls = (o->fpd).ls;	
  	      style.lw = (o->fpd).lt;
  	      style.sred = dcc.ired;
  	      style.sgreen = dcc.igreen;
  	      style.sblue = dcc.iblue;
  	      style.flags |= DKFIG_SVG_FL_STROKE;
  	      if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
  	        style.flags |= DKFIG_SVG_FL_ENLIGHTEN;
  	      }
  	      style.sv = (o->fpd).sv;
	      style.lc = (o->fpd).cs;
	      style.lj = (o->fpd).js;
  	    }
  	    ((dk_fig_svg_drve *)(o->drve))->st1
  	    = svg_style_register(oi, &style);
  	    if(!(((dk_fig_svg_drve *)(o->drve))->st1)) {
  	      back = 0;	
  	    }
  	    if(((o->fpd).ar) & 1) {	/* forward arrowhead */
              svg_style_null(&style);
  	      dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
  	      style.lw = (o->fpd).lt;
  	      style.sred = dcc.ired;
  	      style.sgreen = dcc.igreen;
  	      style.sblue = dcc.iblue;
  	      style.flags |= DKFIG_SVG_FL_STROKE;
  	      if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
  	        style.flags |= DKFIG_SVG_FL_ENLIGHTEN;
  	      }
  	      if(((o->fpd).ahf).type > 0) {
	        style.flags |= DKFIG_SVG_FL_FILL;
  	        if(((o->fpd).ahf).style > 0) {
  		  style.fred = style.sred;
  		  style.fgreen = style.sgreen;
  		  style.fblue = style.sblue;
  	        } else {
		  style.fred = style.fgreen = style.fblue = 255;
		}
  	      }
	      style.lj = (oi->c)->ahlj;
  	      ((dk_fig_svg_drve *)(o->drve))->st2
  	      = svg_style_register(oi, &style);
  	      if(!(((dk_fig_svg_drve *)(o->drve))->st2)) {
  	        back = 0;	
  	      }
  	    }
  	    if(((o->fpd).ar) & 2) {	/* backward arrowhead */
  	      svg_style_null(&style);
  	      dkfig_tool_fill_dcc(oi->d, &dcc, (o->fpd).pc);
  	      style.lw = (o->fpd).lt;
  	      style.sred = dcc.ired;
  	      style.sgreen = dcc.igreen;
  	      style.sblue = dcc.iblue;
  	      style.flags |= DKFIG_SVG_FL_STROKE;
  	      if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
  	        style.flags |= DKFIG_SVG_FL_ENLIGHTEN;
  	      }
  	      if(((o->fpd).ahb).type > 0) {
	        style.flags |= DKFIG_SVG_FL_FILL;
  	        if(((o->fpd).ahb).style > 0) {
  		  style.fred = style.sred;
  		  style.fgreen = style.sgreen;
  		  style.fblue = style.sblue;
  	        } else {
		  style.fred = style.fgreen = style.fblue = 255;
		}
  	      }
	      style.lj = (oi->c)->ahlj;
  	      ((dk_fig_svg_drve *)(o->drve))->st3
  	      = svg_style_register(oi, &style);
  	      if(!(((dk_fig_svg_drve *)(o->drve))->st3)) {
  	        back = 0;	
  	      }
  	    }
  	  } break;
          }
        } else {
          back = 0;	
          /* MEMORY */
	  dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
        }
      }
      if(oi->me) {
        /* MATH PROBLEM */
	dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 13);
      } oi->me = 0;
      if((oi->c)->app) {
        dkapp_set_source_lineno((oi->c)->app, 0UL);
      }
      (oi->c)->opt1 = backupopt1;
    }
  }
  oi->spcpass = 1;
  if(back) {
    oi->npat = 0UL;
    dksto_it_reset(oi->pati);
    while((ppattern = (SVGPAT *)dksto_it_next(oi->pati)) != NULL) {
      ppattern->patno = oi->npat;
      oi->npat += 1UL;
    }
    oi->nsty = 0UL;
    dksto_it_reset(oi->styi);
    while((pstyle = (SVGSTY *)dksto_it_next(oi->styi)) != NULL) {
      pstyle->classno = oi->nsty;
      oi->nsty += 1UL;
    }
    oi->lpat = dkfig_dt_needed_alpha(oi->npat);
    
    oi->lsty = dkfig_dt_needed_alpha(oi->nsty);
    
  }
  
  return back;
} /* }}} */




static char *suffix_types[] = {
  (char *)".gz",
  (char *)".bz2",
  NULL
};


static
int
compression_type DK_P1(char *,n)
{
  int back = -1; char *suffixptr;
  suffixptr = dksf_get_file_type_dot(n);
  if(n) {
    back = dkstr_array_index(suffix_types, suffixptr, 0);
  }
  return back;
}



static
dk_stream_t *
open_the_mapping_file DK_P2(OI *,oi, char *,n)
{
  dk_stream_t *back = NULL;
  switch(compression_type(n)) {
    case 0: {
#if DK_HAVE_ZLIB_H
      if((oi->c)->app) {
        back = dkapp_stream_opengz((oi->c)->app, n, str_mode_open_read);
      } else {
        back = dkstream_opengz(n, str_mode_open_read, 0, NULL);
      }
#else
      dkapp_err_no_zlib_support_for((oi->c)->app, n);
#endif
    } break;
    case 1: {
#if DK_HAVE_BZLIB_H
      if((oi->c)->app) {
        back = dkapp_stream_openbz2((oi->c)->app, n, str_mode_open_read);
      } else {
        back = dkstream_openbz2(n, str_mode_open_read, 0, NULL);
      }
#else
     dkapp_err_no_bzlib_support_for((oi->c)->app, n);
#endif
    } break;
    default: {
      if((oi->c)->app) {
        back = dkapp_stream_openfile((oi->c)->app, n, str_mode_open_read);
      } else {
        back = dkstream_openfile(n, str_mode_open_read, 0, NULL);
      }
    } break;
  }
  return back;
}



static
int
get_fontmap DK_P1(OI *,oi)
{
  int back = 0; dk_stream_t *st;
  char *fmname; size_t szfmname;
  
  szfmname = (size_t)dksf_get_maxpathlen();
  fmname = dk_new(char,szfmname);
  if(fmname) {
    if((oi->c)->app) {
      if(dkapp_find_file((oi->c)->app, (oi->c)->fcfg, fmname, szfmname)) {
        
        oi->fontmap = dkfont_mapping_open();
        if(oi->fontmap) {
          st = open_the_mapping_file(oi, fmname);
	  if(st) {
	    if(dkfont_mapping_add_stream(oi->fontmap, st)) {
	      back = 1;	
	    } else {
	      char *oldsourcefilename; unsigned long oldsourcelineno;
	      oldsourcefilename = dkapp_get_source_filename((oi->c)->app);
	      oldsourcelineno = dkapp_get_source_lineno((oi->c)->app);
	      dkapp_set_source_filename((oi->c)->app, fmname);
	      dkapp_set_source_lineno((oi->c)->app, dkfont_get_error_lineno(oi->fontmap));
	      switch(dkfont_get_error_code(oi->fontmap)) {
	        case DK_ERR_NOMEM: {
		  dkfig_tool2_simple_error_message(oi->c, 11);
		} break;
		default: {
		  dkfig_tool2_simple_error_message(oi->c, 12);
		} break;
	      }
	      dkapp_set_source_lineno((oi->c)->app, oldsourcelineno);
	      dkapp_set_source_filename((oi->c)->app, oldsourcefilename);
	      dkfont_mapping_close(oi->fontmap); oi->fontmap = NULL;
	    }
	    dkstream_close(st);
	  } else {
	    dkapp_err_fopenr((oi->c)->app, fmname);
	  }
        } else {
	  dkapp_err_memory((oi->c)->app, 1, 1);
        }
        back = 1;
      } else {
	dkapp_err_matchfile((oi->c)->app, (oi->c)->fcfg);
      }
    } else {
      oi->fontmap = dkfont_mapping_open();
      if(oi->fontmap) {
        st = open_the_mapping_file(oi, (oi->c)->fcfg);
	if(st) {
	  if(dkfont_mapping_add_stream(oi->fontmap, st)) {
	    back = 1;
	  } else {
	    dkfont_mapping_close(oi->fontmap); oi->fontmap = NULL;
	  }
	  dkstream_close(st);
	} else {
	}
      } else {
      }
    }
    dk_delete(fmname);
  } else {
    if((oi->c)->app) {
      dkapp_err_memory((oi->c)->app, 1, szfmname);
    }
  } 
  return back;
}



/* {{{ preparation_pass

   Prepare for output.

*/
static
int
preparation_pass DK_P1(OI *,oi)
{
  int back = 0;
  
  oi->fl = dkfig_flat_list(oi->c, (oi->c)->drwng);
  oi->pat = dksto_open(0);
  oi->sty = dksto_open(0);
  if((oi->fl) && (oi->pat) && (oi->sty)) {
    dksto_set_comp(oi->pat, dkfig_svg_comp_pat, 0);
    dksto_set_comp(oi->sty, dkfig_svg_comp_style, 0);
    oi->fli = dksto_it_open(oi->fl);
    oi->pati = dksto_it_open(oi->pat);
    oi->styi = dksto_it_open(oi->sty);
    if((oi->fli) && (oi->pati) && (oi->styi)) {
      if(attach_drve(oi)) {	
        if(scan_options(oi)) {
	  if(establish_coord_transformation(oi)) {
	    if(use_dlspc(oi)) {	
              dkfig_tool2_report_unused_options(oi->c);
	      back = prepare_objects(oi);
	      if((oi->c)->fcfg) {	
	        back = get_fontmap(oi);
	      } else {			
	        back = 1;
	      }
	    } else {		
	    }
	  } else {		
	  }
	} else {		
	}
      } else {			
      }
    }
  }
  
  return back;
} /* }}} */



/* {{{ svg_document_type

   Write the SVG document type.

*/
static
void
svg_document_type DK_P1(OI *,oi)
{
  
  switch((oi->c)->svgv) {
    case DKFIG_SVG_VERS_12: /* HIER NOCH SCHAUEN, WIE DEFINIERT ##### */
    case DKFIG_SVG_VERS_10: {
      kw_out(oi, 6); kw_out(oi, 0); kw_out(oi, 2); kw_out(oi, 7);
      kw_out(oi, 1); kw_out(oi, 8); kw_out(oi, 0); kw_out(oi, 9);
      kw_out(oi, 0); kw_out(oi, 3); kw_out(oi, 0);
    } break;
    default: {
      kw_out(oi, 6); kw_out(oi, 0); kw_out(oi, 2); kw_out(oi, 7);
      kw_out(oi, 1); kw_out(oi, 12); kw_out(oi, 0); kw_out(oi, 13);
      kw_out(oi, 0); kw_out(oi, 3); kw_out(oi, 0);
    } break;
  } 
} /* }}} */



/* {{{ print_lgt

   Print a length, maybee either in inches or pixels.

*/
static
void
print_lgt DK_P4(OI *,oi, double,v, int,h, size_t,w)
{
  
  kw_out(oi, w);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, v, 1);
  switch(h) {
    case DKFIG_SVG_VP_PIXELS: {
      kw_out(oi, 22);
    } break;
    case DKFIG_SVG_VP_INCHES: {
      kw_out(oi, 21);
    } break;
  }
  kw_out(oi, 20); 
} /* }}} */



/* {{{ print_width

   Print width of SVG either in inches or
   in pixels (without unit).
*/
static
void
print_width DK_P3(OI *,oi, double,v, int,h)
{
  print_lgt(oi,v,h,16);
  
} /* }}} */



/* {{{ print_height

   Print height of SVG either in inches or
   in pixels (without unit).

*/
static
void
print_height DK_P3(OI *,oi, double,v, int,h)
{
  print_lgt(oi,v,h,17);
  
} /* }}} */



/* {{{ svg_drve_write

   Write data attached to the entire drawing.

*/
static
int
svg_drve_write DK_P4(\
  OI *,oi, dk_fig_object *,o, DRVE *,drve, int,isroot\
)
{
  int back = 1;
  int i, is_first;
  dk_fig_svg_attr *a;
  char *ptr, **pptr;
  
  is_first = 1;
  if(drve->attri) {
    for(i = 1; i < (int)sz_cmds; i++) {
      a = (dk_fig_svg_attr *)dksto_it_find_like(drve->attri, (void *)(&i), 1);
      if(a) {
        if(a->value) {
	  if(is_first) {
	    if(!isroot) {
	      kw_out(oi, 0);
	    }
	  }
	  pptr = cmds[i];
	  ptr = *pptr;
	  dkstream_puts(oi->s, ptr);
	  kw_out(oi, 19);
	  kw_out(oi, 20);
	  dkstream_puts(oi->s, a->value);
	  kw_out(oi, 20);
	  kw_out(oi, 0);
	  is_first = 0;
	}
      }
    }
  }
  
  return back;
} /* }}} */



/* {{{ svg_start_tag

   Write opening SVG tag.

*/
static
void
svg_start_tag DK_P1(OI *,oi)
{
  double w, h, wp, hp;
  
  begin_tag(oi, 5); kw_out(oi, 1);
  wp = dkma_sub_double_ok(
    dkma_l_to_double(oi->xmax),
    dkma_l_to_double(oi->xmin),
    &(oi->me)
  );
  hp = dkma_sub_double_ok(
    dkma_l_to_double(oi->ymax),
    dkma_l_to_double(oi->ymin),
    &(oi->me)
  );
  h = hp; w = wp;
  if(((oi->c)->svgs) == DKFIG_SVG_VP_INCHES) {
    h = h / 72.0; w = w / 72.0;
  }
  hp = dkma_double_restrict_digits(hp, 0);
  wp = dkma_double_restrict_digits(wp, 0);
  h  = drd(h, oi->c, 1);
  w  = drd(w, oi->c, 1);
  print_width(oi, w, (oi->c)->svgs); kw_out(oi, 1);
  print_height(oi, h, (oi->c)->svgs); kw_out(oi, 1);
  kw_out(oi, 18); kw_out(oi, 19); kw_out(oi, 20);
  dkstream_puts_ul(oi->s, 0UL); kw_out(oi, 1);
  dkstream_puts_ul(oi->s, 0UL); kw_out(oi, 1);
  dkstream_puts_long(oi->s, dkma_double_to_l(wp));
  kw_out(oi, 1);
  dkstream_puts_long(oi->s, dkma_double_to_l(hp));
  kw_out(oi, 20);
  if(!(((oi->c)->opt1) & DKFIG_OPT_SVG_EMBEDDED)) {
    kw_out(oi, 0);
    switch((oi->c)->svgv) {
      case DKFIG_SVG_VERS_10: {
        if(((oi->c)->opt1) & DKFIG_OPT_SVG_EMBEDDED) {
          kw_out(oi, 23);
        } else {
          kw_out(oi, 10);
        }
        kw_out(oi, 0); kw_out(oi, 11); kw_out(oi, 0);
      } break;
      case DKFIG_SVG_VERS_11: {
        if(((oi->c)->opt1) & DKFIG_OPT_SVG_EMBEDDED) {
          kw_out(oi, 23);
        } else {
          kw_out(oi, 10);
        }
        kw_out(oi, 0); kw_out(oi, 11); kw_out(oi, 0);
      } break;
    }
  }
  svg_drve_write(oi, oi->dro, (DRVE *)((oi->dro)->drve), 1);
  kw_out(oi, 3); kw_out(oi, 0); 
} /* }}} */



/* {{{ svg_end_tag

   Finish svg output.

*/
static
void
svg_end_tag DK_P1(OI *,oi)
{
  end_tag(oi, 5); 
} /* }}} */



static char hex_digits[] = { "0123456789ABCDEF" };


/* {{{ hex_out

   Write a byt as two hex digits.

*/
static
void
hex_out DK_P2(OI *,oi, int,i)
{
  size_t sz;
  char buffer[3];
  sz = (i >> 4) & 15;
  buffer[0] = hex_digits[sz];
  sz = i & 15;
  buffer[1] = hex_digits[sz];
  buffer[2] = '\0';
  dkstream_puts(oi->s, buffer);
} /* }}} */



/* {{{ color_out

   Write a color in hexadecimal notation,
   i.e. "#FF0000".

*/
static
void
color_out DK_P4(OI *,oi, int,r, int,g, int,b)
{
  kw_out(oi, 45);
  hex_out(oi, r);
  hex_out(oi, g);
  hex_out(oi, b);
} /* }}} */



/* {{{ pattern_style

   Write style information for pattern stroke.

*/
static
void
pattern_style DK_P3(OI *,oi, SVGPAT *,pat, int,st)
{
  double dlw;
  /* if(st) { dlw = ccll(oi, ((pat->lw) ? pat->lw : 1L), 1); } */
  if(st) { dlw = ccll(oi, 1L, 1); }
  kw_out(oi, 38);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, (st ? 62 : 63)); kw_out(oi, 24); kw_out(oi, 1);
  kw_out(oi, 65); kw_out(oi, 43);
  kw_out(oi, 1);
  kw_out(oi, (st ? 63 : 62)); kw_out(oi, 24); kw_out(oi, 1);
  color_out(oi, pat->sred, pat->sgreen, pat->sblue);
  kw_out(oi, 43);
  if(st) {
    kw_out(oi, 1);
    kw_out(oi, 64); kw_out(oi, 24); kw_out(oi, 1);
    put_double(oi, dlw, 1);
    kw_out(oi, 43);
    kw_out(oi, 1);
    kw_out(oi, 67); kw_out(oi, 24); kw_out(oi, 1);
    kw_out(oi, 69);
    kw_out(oi, 43);
  }
  kw_out(oi, 20);
} /* }}} */



/* {{{ points_out

   Write points="..." for polyline/polygon.

*/
static
void
points_out DK_P4(OI *,oi, double *,co, size_t,n, int,cl)
{
  size_t max;
  size_t i;
  max = 2 * n;
  kw_out(oi, 86);
  kw_out(oi, 19);
  kw_out(oi, 20);
  for(i = 0; i < max; i++) {
    if(i) { kw_out(oi, ((i % 2) ? 55 : 0)); }
    put_double(oi, co[i], 1);
  }
  kw_out(oi, 20);
} /* }}} */



/* {{{ pattern_line_or_fill
  
   Draw and fill operations for pattern strokes.

*/
static
void
pattern_line_or_fill DK_P6(\
  OI *,oi, double *,co, size_t,np, int,cl, SVGPAT *,pat, int,lof\
)
{
  begin_tag(oi, ((lof && cl) ? 84 : 85));
  kw_out(oi, 0);
  pattern_style(oi, pat, lof);
  kw_out(oi, 0);
  points_out(oi, co, np, cl);
  kw_out(oi, 0);
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);
} /* }}} */



/* {{{ pattern_line

   Write pattern strokes as a polyline/polygon.

*/
static
void
pattern_line DK_P5(\
  OI *,oi, double *,co, size_t,np, int,cl, SVGPAT *,pat\
)
{
  pattern_line_or_fill(oi, co, np, cl, pat, 1);
} /* }}} */



/* {{{ pattern_area

   Write pattern strokes as a filled polygon.

*/
static
void
pattern_area DK_P5(\
  OI *,oi, double *,co, size_t,np, int,cl, SVGPAT *,pat\
)
{
  pattern_line_or_fill(oi, co, np, cl, pat, 0);
} /* }}} */



/* {{{ do_fish_scales

   Write strokes for the fish scales patterns.

*/
static
void
do_fish_scales DK_P7(\
  OI *,oi, SVGPAT *,pat,\
  double,xstep, double,ystep, double,x1, double,y1,\
  double,r\
)
{
  begin_tag(oi, 98);
  kw_out(oi, 0);
  pattern_style(oi, pat, 1);
  kw_out(oi, 0);
  kw_out(oi, 99);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 100);
  kw_out(oi, 103);
  kw_out(oi, 55);
  kw_out(oi, 103);
  kw_out(oi, 102);
  put_double(oi, r, 2);
  kw_out(oi, 1);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  put_double(oi, xstep, 1);
  kw_out(oi, 55);
  put_double(oi, 0.0, 1);
  kw_out(oi, 20);
  kw_out(oi, 0);
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);
  begin_tag(oi, 98);
  kw_out(oi, 0);
  pattern_style(oi, pat, 1);
  kw_out(oi, 0);
  kw_out(oi, 99);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 100);
  kw_out(oi, 103);
  kw_out(oi, 55);
  put_double(oi, ystep, 1);
  kw_out(oi, 102);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  put_double(oi, x1, 1);
  kw_out(oi, 55);
  put_double(oi, y1, 1);
  kw_out(oi, 20);
  kw_out(oi, 0);
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);
  begin_tag(oi, 98);
  kw_out(oi, 0);
  pattern_style(oi, pat, 1);
  kw_out(oi, 0);
  kw_out(oi, 99);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 100);
  put_double(oi, x1, 1);
  kw_out(oi, 55);
  put_double(oi, y1, 1);
  kw_out(oi, 102);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  put_double(oi, xstep, 1);
  kw_out(oi, 55);
  put_double(oi, ystep, 1);
  kw_out(oi, 20);
  kw_out(oi, 0);
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);

  begin_tag(oi, 98);
  kw_out(oi, 0);
  pattern_style(oi, pat, 1);
  kw_out(oi, 0);
  kw_out(oi, 99);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 100);
  kw_out(oi, 103);
  kw_out(oi, 55);
  kw_out(oi, 103);
  kw_out(oi, 102);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  put_double(oi, x1, 1);
  kw_out(oi, 55);
  put_double(oi, (0.0 - y1), 1);
  kw_out(oi, 20);
  kw_out(oi, 0);
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);
  begin_tag(oi, 98);
  kw_out(oi, 0);
  pattern_style(oi, pat, 1);
  kw_out(oi, 0);
  kw_out(oi, 99);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 100);
  put_double(oi, x1, 1);
  kw_out(oi, 55);
  put_double(oi, (0.0 - y1), 1);
  kw_out(oi, 102);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  put_double(oi, r, 1);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  kw_out(oi, 103);
  kw_out(oi, 1);
  put_double(oi, xstep, 1);
  kw_out(oi, 55);
  kw_out(oi, 103);
  kw_out(oi, 20);
  kw_out(oi, 0);
  kw_out(oi, 4);
  kw_out(oi, 3);
  kw_out(oi, 0);
} /* }}} */



/* {{{ pattern_out

   Write one pattern.

*/
static
void
pattern_out DK_P2(OI *,oi, SVGPAT *,pat)
{
  double patrp, xstep, ystep, a, b, dlw;
  double x1, y1, x2, y2, x3, y3, x4, y4;
  double co[32];
  
  xstep = ystep = 10.0; a = b = 0.0;
  /* dlw = ccll(oi, ((pat->lw) ? pat->lw : 1L), 1); */
  dlw = ccll(oi, 1L, 1);
  if((oi->c)->patrp) {
    patrp = 0.9 * dkma_l_to_double((oi->c)->patrp);
  } else {
    patrp = 3.6;
  } patrp = fabs(patrp);
  xstep = ystep = patrp;
  switch(pat->pattp) {
    case 41: case 42: case 43: {
      xstep = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      ystep = dkma_mul_double_ok(patrp, sqrt(4.0/3.0), &(oi->me));
    } break;
    case 44: case 45: case 46: {	/* FourtyFiveLeft */
      xstep = dkma_mul_double_ok(patrp, sqrt(2.0), &(oi->me));
      ystep = xstep;
    } break;
    case 47: {	/* HorizontalBricks */
      x1    = patrp;
      patrp = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      x2    = dkma_add_double_ok(x1, patrp, &(oi->me));
      x3    = dkma_add_double_ok(x2, patrp, &(oi->me));
      x4    = dkma_add_double_ok(x3, patrp, &(oi->me));
      y1    = patrp;
      ystep = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      xstep = dkma_mul_double_ok(ystep, 2.0, &(oi->me));
    } break;
    case 48: {	/* VerticalBricks */
      y1    = patrp;
      patrp = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      y2    = dkma_add_double_ok(y1, patrp, &(oi->me));
      y3    = dkma_add_double_ok(y2, patrp, &(oi->me));
      y4    = dkma_add_double_ok(y3, patrp, &(oi->me));
      x1    = patrp;
      xstep = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      ystep = dkma_mul_double_ok(xstep, 2.0, &(oi->me));
    } break;
    case 49: {	/* HorizontalLines */
    } break;
    case 50: {	/* VerticalLines */
    } break;
    case 51: {	/* CrossHatch */
    } break;
    case 52: case 53: {	/* HorizShinglesRight, Left... */
      ystep = dkma_mul_double_ok(patrp, 8.0, &(oi->me));
      xstep = dkma_mul_double_ok(patrp, 4.0, &(oi->me));
      x1 = patrp;
      x2 = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      x3 = dkma_mul_double_ok(patrp, 3.0, &(oi->me));
      a  = 0.5 * dlw;
      y1 = x2;
      y2 = xstep;
      y3 = dkma_mul_double_ok(patrp, 6.0, &(oi->me));
    } break;
    case 54: case 55: {	/* VertShinglesOne */
      ystep = dkma_mul_double_ok(patrp, 4.0, &(oi->me));
      xstep = dkma_mul_double_ok(patrp, 8.0, &(oi->me));
      y1 = patrp;
      y2 = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      y3 = dkma_mul_double_ok(patrp, 3.0, &(oi->me));
      a  = 0.5 * dlw;
      x1 = y2;
      x2 = ystep;
      x3 = dkma_mul_double_ok(patrp, 6.0, &(oi->me));
    } break;
    case 56: {	/* FishScales */
      a = dkma_mul_double_ok(patrp, 2.5, &(oi->me));
      b = 1.881618;
      xstep = dkma_mul_double_ok(
        2.0,
	dkma_mul_double_ok(a, sin(0.5*b), &(oi->me)),
	&(oi->me)
      );
      ystep = dkma_mul_double_ok(
        (1.0 - cos(0.5*b)),
	a,
	&(oi->me)
      );
      ystep = dkma_mul_double_ok(ystep, 2.0, &(oi->me));
      xstep = round_down_digits(xstep, 4);
      ystep = round_down_digits(ystep, 4);
      x1 = 0.5 * xstep; y1 = 0.5 * ystep;
    } break;
    case 57: {	/* SmallFishScales */
      a = patrp;
      b = M_PI;
      xstep = dkma_mul_double_ok(
        2.0,
	dkma_mul_double_ok(a, sin(0.5*b), &(oi->me)),
	&(oi->me)
      );
      ystep = dkma_mul_double_ok(
        (1.0 - cos(0.5*b)),
	a,
	&(oi->me)
      );
      ystep = dkma_mul_double_ok(ystep, 2.0, &(oi->me));
      xstep = round_down_digits(xstep, 4);
      ystep = round_down_digits(ystep, 4);
      x1 = 0.5 * xstep; y1 = 0.5 * ystep;
    } break;
    case 58: {	/* Circles */
      a = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
      xstep = ystep = dkma_mul_double_ok(patrp, 4.0, &(oi->me));
    } break;
    case 59: {	/* Hexagons */
      xstep = dkma_mul_double_ok(patrp, 6.0, &(oi->me));
      y1 = ystep = dkma_mul_double_ok(patrp, sqrt(3.0), &(oi->me));
      ystep = dkma_mul_double_ok(ystep, 2.0, &(oi->me));
      x1 = patrp;
      x2 = dkma_mul_double_ok(patrp, 3.0, &(oi->me));
      x3 = dkma_mul_double_ok(patrp, 4.0, &(oi->me));
      x4 = dkma_add_double_ok(xstep, patrp, &(oi->me));
    } break;
    case 60: {	/* Octagons */
      patrp = dkma_mul_double_ok(patrp, 4.0, &(oi->me));
      xstep = ystep = patrp;
      a = xstep / (2.0+sqrt(2.0));
    } break;
    case 61: case 62: {	/* HorizontalTireTreads, Vertical... */
      xstep = ystep = dkma_mul_double_ok(patrp, 2.0, &(oi->me));
    } break;
  }
  begin_tag(oi, 35);
  kw_out(oi, 1);
  kw_out(oi, 36);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 37);
  dkfig_tool_num_as_string(oi->s, pat->patno, oi->lpat);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 14);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 103);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 15);
  kw_out(oi, 19);
  kw_out(oi, 20);
  kw_out(oi, 103);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 16);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, xstep, 1);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 17);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, ystep, 1);
  kw_out(oi, 20);
  kw_out(oi, 0);
  kw_out(oi, 111);
  kw_out(oi, 0);
  kw_out(oi, 3); kw_out(oi, 0);
  if((pat->flags) & DKFIG_SVG_FL_FILL) {
    begin_tag(oi, 79);
    kw_out(oi, 1);
    kw_out(oi, 14);
    kw_out(oi, 19);
    kw_out(oi, 20);
    kw_out(oi, 103);
    kw_out(oi, 20);
    kw_out(oi, 1);
    kw_out(oi, 15);
    kw_out(oi, 19);
    kw_out(oi, 20);
    kw_out(oi, 103);
    kw_out(oi, 20);
    kw_out(oi, 1);
    kw_out(oi, 16);
    kw_out(oi, 19);
    kw_out(oi, 20);
    put_double(oi, xstep, 1);
    kw_out(oi, 20);
    kw_out(oi, 1);
    kw_out(oi, 17);
    kw_out(oi, 19);
    kw_out(oi, 20);
    put_double(oi, ystep, 1);
    kw_out(oi, 20);
    kw_out(oi, 0);
    kw_out(oi, 38);
    kw_out(oi, 19);
    kw_out(oi, 20);
    kw_out(oi, 62); kw_out(oi, 24); kw_out(oi, 1);
    color_out(oi, pat->fred, pat->fgreen, pat->fblue);
    kw_out(oi, 43);
    kw_out(oi, 1);
    kw_out(oi, 63); kw_out(oi, 24); kw_out(oi, 1);
    kw_out(oi, 65);
    kw_out(oi, 43);
    kw_out(oi, 20);
    kw_out(oi, 0);
    kw_out(oi, 4);
    kw_out(oi, 3);
    kw_out(oi, 0);
  }
  if((pat->flags) & DKFIG_SVG_FL_STROKE) {
    switch(pat->pattp) {
      case 41: {	/* ThirtyLeft */
	a = dlw; b = dlw / sqrt(3.0);
	co[0] = 0.0; co[1] = 0.0; co[2] = a; co[3] = 0.0;
	co[4] = xstep;
	co[5] = dkma_sub_double_ok(ystep, b, &(oi->me));
	co[6] = xstep; co[7] = ystep;
	co[8] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[9] = ystep; co[10] = 0.0; co[11] = b;
	pattern_area(oi, co, 6, 0, pat);
	co[0] = 0.0;
	co[1] = dkma_sub_double_ok(ystep, b, &(oi->me));
	co[2] = a; co[3] = ystep; co[4] = 0.0; co[5] = ystep;
	pattern_area(oi, co, 3, 0, pat);
	co[0] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[1] = 0.0; co[2] = xstep; co[3] = b; co[4] = xstep;
	co[5] = 0.0;
	pattern_area(oi, co, 3, 0, pat);
      } break;
      case 42: {	/* ThirtyRight */
	a = dlw; b = dlw / sqrt(3.0);
	co[0] = 0.0; co[1] = ystep; co[2] = a; co[3] = ystep;
	co[4] = xstep; co[5] = b; co[6] = xstep; co[7] = 0.0;
	co[8] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[9] = 0.0; co[10] = 0.0;
	co[11] = dkma_sub_double_ok(ystep, b, &(oi->me));
	pattern_area(oi, co, 6, 0, pat);
	co[0] = 0.0; co[1] = b; co[2] = a; co[3] = 0.0;
	co[4] = 0.0; co[5] = 0.0;
	pattern_area(oi, co, 3, 0, pat);
	co[0] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[1] = ystep; co[2] = xstep; co[3] = ystep;
	co[4] = xstep;
	co[5] = dkma_sub_double_ok(ystep, b, &(oi->me));
	pattern_area(oi, co, 3, 0, pat);
      } break;
      case 43: case 46: {	/* ThirtyHatch, FourtyFiveHatch */
        co[0] = 0.0; co[1] = 0.0; co[2] = xstep; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0; co[1] = ystep; co[2] = xstep; co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 44: {	/* FourtyFiveLeft */
	a = dlw / sqrt(2.0); b = dlw / sqrt(2.0);
	co[0] = 0.0; co[1] = 0.0; co[2] = a; co[3] = 0.0;
	co[4] = xstep;
	co[5] = dkma_sub_double_ok(ystep, b, &(oi->me));
	co[6] = xstep; co[7] = ystep;
	co[8] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[9] = ystep; co[10] = 0.0; co[11] = b;
	pattern_area(oi, co, 6, 0, pat);
	co[0] = 0.0;
	co[1] = dkma_sub_double_ok(ystep, b, &(oi->me));
	co[2] = a; co[3] = ystep; co[4] = 0.0; co[5] = ystep;
	pattern_area(oi, co, 3, 0, pat);
	co[0] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[1] = 0.0; co[2] = xstep; co[3] = b; co[4] = xstep;
	co[5] = 0.0;
	pattern_area(oi, co, 3, 0, pat);
      } break;
      case 45: {	/* FourtyFiveRight */
	a = dlw / sqrt(2.0); b = dlw / sqrt(2.0);
	co[0] = 0.0; co[1] = ystep; co[2] = a; co[3] = ystep;
	co[4] = xstep; co[5] = b; co[6] = xstep; co[7] = 0.0;
	co[8] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[9] = 0.0; co[10] = 0.0;
	co[11] = dkma_sub_double_ok(ystep, b, &(oi->me));
	pattern_area(oi, co, 6, 0, pat);
	co[0] = 0.0; co[1] = b; co[2] = a; co[3] = 0.0;
	co[4] = 0.0; co[5] = 0.0;
	pattern_area(oi, co, 3, 0, pat);
	co[0] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[1] = ystep; co[2] = xstep; co[3] = ystep;
	co[4] = xstep;
	co[5] = dkma_sub_double_ok(ystep, b, &(oi->me));
	pattern_area(oi, co, 3, 0, pat);
      } break;
      case 47: {	/* HorizontalBricks */
        co[0] = x1; co[1] = 0.0; co[2] = x1; co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = x3; co[1] = 0.0; co[2] = x3; co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = x2; co[1] = y1; co[2] = x2; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = x4; co[1] = y1; co[2] = x4; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = 0.0; co[1] = 0.0; co[2] = xstep; co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = 0.0; co[1] = ystep; co[2] = xstep; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = 0.0; co[1] = y1; co[2] = xstep; co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 48: {	/* VerticalBricks */
        co[0] = 0.0; co[1] = y1; co[2] = x1; co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = 0.0; co[1] = y3; co[2] = x1; co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = x1; co[1] = y2; co[2] = xstep; co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = x1; co[1] = y4; co[2] = xstep; co[3] = y4;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = 0.0; co[1] = 0.0; co[2] = 0.0; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = x1; co[1] = 0.0; co[2] = x1; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = xstep; co[1] = 0.0; co[2] = xstep; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);

      } break;
      case 49: {	/* HorizontalLines */
        co[0] = 0.0; co[1] = 0.0;
	co[2] = xstep; co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0; co[1] = ystep;
	co[2] = xstep; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 50: {	/* VerticalLines */
        co[0] = 0.0; co[1] = 0.0;
	co[2] = 0.0; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = xstep; co[1] = 0.0;
	co[2] = xstep; co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 51: {	/* CrossHatch */
        co[0] = 0.0; co[1] = 0.0;
	co[2] = 0.0; co[3] = ystep;
	co[4] = xstep; co[5] = ystep;
	co[6] = xstep; co[7] = 0.0;
	pattern_line(oi, co, 4, 1, pat);
      } break;
      case 52: {	/* HorizShinglesRight */
        co[0] = a;
	co[1] = y1;
	co[2] = dkma_sub_double_ok(x1, a, &(oi->me));
	co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = dkma_add_double_ok(x1, a, &(oi->me));
	co[1] = y2;
	co[2] = dkma_sub_double_ok(x2, a, &(oi->me));
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = dkma_add_double_ok(x2, a, &(oi->me));
	co[1] = y3;
	co[2] = dkma_sub_double_ok(x3, a, &(oi->me));
	co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = dkma_add_double_ok(x3, a, &(oi->me));
	co[1] = ystep;
	co[2] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = 0.0;
	co[2] = xstep;
	co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = y1;
	co[2] = xstep;
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = y2;
	co[2] = xstep;
	co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = y3;
	co[2] = xstep;
	co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = ystep;
	co[2] = xstep;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 53: {	/* HorizShinglesLeft */
        co[0] = 0.0;
	co[1] = 0.0;
	co[2] = x1;
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x3;
	co[1] = y1;
	co[2] = xstep;
	co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x2;
	co[1] = y2;
	co[2] = x3;
	co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x1;
	co[1] = y3;
	co[2] = x2;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = 0.0;
	co[2] = xstep;
	co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = y1;
	co[2] = xstep;
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = y2;
	co[2] = xstep;
	co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = y3;
	co[2] = xstep;
	co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = ystep;
	co[2] = xstep;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 54: {	/* VertShinglesOne */
        co[0] = 0.0;
	co[1] = y3;
	co[2] = x1;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x1;
	co[1] = y2;
	co[2] = x2;
	co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x2;
	co[1] = y1;
	co[2] = x3;
	co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x3;
	co[1] = 0.0;
	co[2] = xstep;
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = 0.0;
	co[2] = 0.0;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x1;
	co[1] = 0.0;
	co[2] = x1;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x2;
	co[1] = 0.0;
	co[2] = x2;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x3;
	co[1] = 0.0;
	co[2] = x3;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = xstep;
	co[1] = 0.0;
	co[2] = xstep;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 55: {	/* VertShinglesOther */
        co[0] = 0.0;
	co[1] = ystep;
	co[2] = x1;
	co[3] = y3;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x1;
	co[1] = y1;
	co[2] = x2;
	co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x2;
	co[1] = y2;
	co[2] = x3;
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x3;
	co[1] = y3;
	co[2] = xstep;
	co[3] = y2;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = 0.0;
	co[1] = 0.0;
	co[2] = 0.0;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x1;
	co[1] = 0.0;
	co[2] = x1;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x2;
	co[1] = 0.0;
	co[2] = x2;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = x3;
	co[1] = 0.0;
	co[2] = x3;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
        co[0] = xstep;
	co[1] = 0.0;
	co[2] = xstep;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 56: {	/* FishScales */
        do_fish_scales(oi, pat, xstep, ystep, x1, y1, a);
      } break;
      case 57: {	/* SmallFishScales */
        do_fish_scales(oi, pat, xstep, ystep, x1, y1, a);
      } break;
      case 58: {	/* Circles */
        begin_tag(oi, 90);
	kw_out(oi, 1);
        kw_out(oi, 87);
	kw_out(oi, 19);
	kw_out(oi, 20);
        put_double(oi, a, 1);
	kw_out(oi, 20);
	kw_out(oi, 1);
	kw_out(oi, 88);
	kw_out(oi, 19);
	kw_out(oi, 20);
        put_double(oi, a, 1);
	kw_out(oi, 20);
	kw_out(oi, 1);
	kw_out(oi, 89);
	kw_out(oi, 19);
	kw_out(oi, 20);
        put_double(oi, a, 1);
	kw_out(oi, 20);
	kw_out(oi, 0);
	pattern_style(oi, pat, 1);
	kw_out(oi, 0);
        kw_out(oi, 4);
	kw_out(oi, 3);
	kw_out(oi, 0);
      } break;
      case 59: {	/* Hexagons */
        co[0] = x1;
	co[1] = 0.0;
	co[2] = 0.0;
	co[3] = y1;
	co[4] = x1;
	co[5] = ystep;
	co[6] = x2;
	co[7] = ystep;
	co[8] = x3;
	co[9] = y1;
	co[10] = x2;
	co[11] = 0.0;
	pattern_line(oi, co, 6, 1, pat);
	co[0] = x3;
	co[1] = y1;
	co[2] = xstep;
	co[3] = y1;
	pattern_line(oi, co, 2, 0, pat);
	/* for the line ends at the right border */
	co[0] = xstep;
	co[1] = y1;
	co[2] = x4;
	co[3] = 0.0;
	pattern_line(oi, co, 2, 0, pat);
	co[0] = xstep;
	co[1] = y1;
	co[2] = x4;
	co[3] = ystep;
	pattern_line(oi, co, 2, 0, pat);
      } break;
      case 60: {	/* Octagons */
        co[0] = 0.0; co[1] = a;
	co[2] = a; co[3] = 0.0;
	co[4] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[5] = 0.0;
	co[6] = xstep; co[7] = a;
	co[8] = xstep;
	co[9] = dkma_sub_double_ok(ystep, a, &(oi->me));
	co[10] = dkma_sub_double_ok(xstep, a, &(oi->me));
	co[11] = ystep;
	co[12] = a; co[13] = ystep;
	co[14] = 0.0;
	co[15] = dkma_sub_double_ok(ystep, a, &(oi->me));
	pattern_line(oi, co, 8, 1, pat);
      } break;
      case 61: {	/* HorizontalTireTreads */
        y1 = 0.5 * patrp;
	y2 = dkma_mul_double_ok(patrp, 1.5, &(oi->me));
	co[0] = 0.0;
	co[1] = y1;
	co[2] = patrp;
	co[3] = y2;
	co[4] = xstep;
	co[5] = y1;
	pattern_line(oi, co, 3, 0, pat);
      } break;
      case 62: {	/* VerticalTireTreads */
        x1 = 0.5 * patrp;
	x2 = dkma_mul_double_ok(patrp, 1.5, &(oi->me));
	co[0] = x1;
	co[1] = 0.0;
	co[2] = x2;
	co[3] = patrp;
	co[4] = x1;
	co[5] = ystep;
	pattern_line(oi, co, 3, 0, pat);
      } break;
    }
  }
  end_tag(oi, 35);
  
} /* }}} */



static double pt_to_bp = DKFIG_BP_PER_INCH / DKFIG_PT_PER_INCH;

static
void
put_font_size DK_P2(OI *,oi, SVGSTY *,sty)
{
  if(((oi->c)->opt2) & DKFIG_OPT_SVG_FONTSIZE_UNIT) {
    switch((oi->c)->svgs) {
      case DKFIG_SVG_VP_INCHES: {
        dkstream_puts_double(
          oi->s,
          drd(
	    dkma_mul_double_ok((sty->fonth)->fontsize, (oi->c)->fsf, &(oi->me)),
	    oi->c, 1
          )
        );
	kw_out(oi, 81);
      } break;
      case DKFIG_SVG_VP_PIXELS: {
        dkstream_puts_double(
          oi->s,
          drd(
            (pt_to_bp *
	     dkma_mul_double_ok((sty->fonth)->fontsize, (oi->c)->fsf, &(oi->me))
	    ),
	    oi->c, 1
          )
        );
	kw_out(oi, 22);
      } break;
      default: {
        dkstream_puts_double(
          oi->s,
          drd(
            (pt_to_bp *
	     dkma_mul_double_ok((sty->fonth)->fontsize, (oi->c)->fsf, &(oi->me))
	    ),
	    oi->c, 1
          )
        );
      } break;
    }
  } else {
    dkstream_puts_double(
      oi->s,
      drd(
        (pt_to_bp *
	 dkma_mul_double_ok((sty->fonth)->fontsize, (oi->c)->fsf, &(oi->me))
	),
	oi->c, 1
      )
    );
  }
}



/* {{{ style_out

   Write style information (style contents).
   The iscss flag indicates whether we are in
   a <style type="text/css"> section or in
   a <... style="..."> string.

*/
static
void
style_out DK_P3(OI *,oi, SVGSTY *,sty, int,iscss)
{
  double dotlgt;
  int had_entry;
  dk_one_font_mapping_t	*pofm;
  dk_font_replacement_t *pfr;
  char *fontfamilyname;
  
  dotlgt = 0.0;
  if(oi->prep_mods) {
    if(!iscss) {
      if((sty->flags) & DKFIG_SVG_FL_TEXT) {
        if(sty->fonth) {
          switch((sty->fonth)->handling) {
            case 2: case 3: case 4: case 5: { } break;
  	  default: {
  	    char *ptr; int ft;
            /* font-family */
  	    if(iscss) { kw_out(oi, 0); }
  	    kw_out(oi, 46); kw_out(oi, 19); kw_out(oi, 20);
            ptr = dkfont_get_svg_family_name((size_t)((sty->fonth)->fontno));
	    
  	    if(oi->urw_dir) {
  	      if(((sty->fonth)->fontno) >= 0) {
  	        if(((sty->fonth)->fontno) < 35) {
  	          ptr = urw_svg_font_families[(sty->fonth)->fontno];
		  
  	        }
  	      }
  	    }
  	    ft = dkfont_get_features((size_t)((sty->fonth)->fontno));
	    had_entry = 0;
	    if(oi->fontmap) {
	      pofm = dkfont_get_one_font(oi->fontmap, (sty->fonth)->fontno);
	      if(pofm) {
	        dkfont_one_font_reset(pofm);
		while((pfr = dkfont_one_font_get(pofm)) != NULL) {
		  if(dkfont_rep_check_driver(pfr, kw[5])) {
		    fontfamilyname = dkfont_rep_get_family(pfr);
		    if(fontfamilyname) {
		      if(had_entry) {
		        kw_out(oi, 55);
		      }
  	              kw_out(oi, (iscss ? 20 : 107));
		      dkstream_puts(oi->s, fontfamilyname);
  	              kw_out(oi, (iscss ? 20 : 107));
		      had_entry = 1;
		    }
		  }
		}
	      }
	    } else {
  	      if(ptr) {
	        
  	        kw_out(oi, (iscss ? 20 : 107));
  	        dkstream_puts(oi->s, ptr);
  	        kw_out(oi, (iscss ? 20 : 107));
		had_entry = 1;
  	      }
	    }
	    if(had_entry) {
	      kw_out(oi, 55);
	    }
  	    switch(ft & DK_FONT_FEATURE_FAMILY) {
  	      case DK_FONT_FEATURE_TT: {
  	        kw_out(oi, 58);
  	      } break;
  	      case DK_FONT_FEATURE_SF: {
  	        kw_out(oi, 57);
  	      } break;
  	      default: {
  	        kw_out(oi, 56);
  	      } break;
  	    }
  	    kw_out(oi, 20);


  	    kw_out(oi, 0);
  	    kw_out(oi, 47); kw_out(oi, 19); kw_out(oi, 20);
  	    kw_out(oi, ((ft & DK_FONT_FEATURE_IT) ? 60 : 59));
  	    kw_out(oi, 20);
  	    kw_out(oi, 1);
  	    kw_out(oi, 48); kw_out(oi, 19); kw_out(oi, 20);
  	    kw_out(oi, ((ft & DK_FONT_FEATURE_BD) ? 61 : 59));
  	    kw_out(oi, 20);
  	    kw_out(oi, 1);
  	    kw_out(oi, 49); kw_out(oi, 19); kw_out(oi, 20);
	    /*
	      font size
	    */
#if VERSION_BEFORE_2006_03_24
  	    dkstream_puts_double(
  	      oi->s,
  	      drd(
  	        dkma_mul_double_ok((sty->fonth)->fontsize, (oi->c)->fsf, &(oi->me)),
		oi->c, 1
  	      )
  	    );
#else
	    put_font_size(oi, sty);
#endif
  	    /* kw_out(oi, 81); */
  	    kw_out(oi, 20);
  	    kw_out(oi, 0);
              /* align */
  	    kw_out(oi, 51); kw_out(oi, 19); kw_out(oi, 20);
  	    switch(sty->talign) {
  	      case 1: {
  	        kw_out(oi, 53);
  	      } break;
  	      case 2: {
  	        kw_out(oi, 54);
  	      } break;
  	      default: {
  	        kw_out(oi, 52);
  	      } break;
  	    }
  	    kw_out(oi, 20);
  	    kw_out(oi, 1);
              /* color */
  	    /* kw_out(oi, 50); */
  	    kw_out(oi, 62); kw_out(oi, 19); kw_out(oi, 20);
  	    color_out(oi, sty->sred, sty->sgreen, sty->sblue);
  	    kw_out(oi, 20);
	    kw_out(oi, 0);
  	  } break;
          }
        }
      } else {
        if(iscss) { kw_out(oi, 0); }
        kw_out(oi, 62); kw_out(oi, 19); kw_out(oi, 20);
        if((sty->flags) & DKFIG_SVG_FL_FILL) {
          if(sty->pat) {
            kw_out(oi, 74);
  	    kw_out(oi, 75);
  	    kw_out(oi, 45);
            kw_out(oi, 37);
            dkfig_tool_num_as_string(oi->s, (sty->pat)->patno, oi->lpat);
  	    kw_out(oi, 76);
          } else {
            color_out(oi, sty->fred, sty->fgreen, sty->fblue);
          }
        } else {
          kw_out(oi, 65);
        }
        kw_out(oi, 20);
        kw_out(oi, 1);
        kw_out(oi, 63); kw_out(oi, 19); kw_out(oi, 20);
        if((sty->flags) & DKFIG_SVG_FL_STROKE) {
          double mylw;
          color_out(oi, sty->sred, sty->sgreen, sty->sblue);
          kw_out(oi, 20);
          kw_out(oi, 1);
          mylw = ccll(oi, sty->lw, 1);
          /*
          mylw = dkma_l_to_double(sty->lw);
          mylw = dkma_mul_double_ok(mylw, oi->mx, &(oi->me));
          if((sty->flags) & DKFIG_SVG_FL_ENLIGHTEN) {
            mylw = mylw * 0.5;
          }
          */
          kw_out(oi, 64); kw_out(oi, 19); kw_out(oi, 20);
          put_double(oi, mylw, 1);
          kw_out(oi, 20);
          if(sty->lc) {
            kw_out(oi, 0);
            kw_out(oi, 67); kw_out(oi, 19); kw_out(oi, 20);
            switch(sty->lc) {
              case 2: {
  	      kw_out(oi, 70);
  	    } break;
  	    case 1: {
  	      kw_out(oi, 69);
  	    } break;
  	    default: {
  	      kw_out(oi, 68);
  	    } break;
            }
            kw_out(oi, 20);
          }
          if(sty->lj) {
            kw_out(oi, 0);
            kw_out(oi, 71); kw_out(oi, 19); kw_out(oi, 20);
            switch(sty->lj) {
              case 2: {
  	      kw_out(oi, 73);
  	    } break;
  	    case 1: {
  	      kw_out(oi, 69);
  	    } break;
  	    default: {
  	      kw_out(oi, 72);
  	    } break;
            }
            kw_out(oi, 20);
          }
          if((sty->ls) > 0) {
            /* double mylw; */
  	  kw_out(oi, 0);
  	  mylw = ccdl(oi, sty->sv, 0);
	  dotlgt = 0.0;
	  if(((oi->c)->opt1) & DKFIG_OPT_DP_DOT_LW) {
	    dotlgt = ccll(oi, ((sty->lw) ? sty->lw : 1L), 1);
	    dotlgt = drd(dotlgt, oi->c, 1);
	  }
  	  /*
            mylw = dkma_l_to_double(sty->sv);
            mylw = dkma_mul_double_ok(mylw, oi->mx, &(oi->me));
  	  */
            mylw = drd(mylw, oi->c, 1);
            kw_out(oi, 66); kw_out(oi, 19); kw_out(oi, 20);
            switch(sty->ls) {
              case 1: {
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	    } break;
  	    case 2: {
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	    } break;
  	    case 3: {
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	    } break;
  	    case 4: {
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	    } break;
  	    case 5: {
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s,dotlgt);
  	      kw_out(oi, 55);
  	      dkstream_puts_double(oi->s, mylw);
  	    } break;
            }
            kw_out(oi, 20);
          }
        } else {
          kw_out(oi, 65); kw_out(oi, 20);
        }
	kw_out(oi, 0);
      }
    }
  } else {
    if(iscss) {
      kw_out(oi, 40);
      kw_out(oi, 44);
      
      dkfig_tool_num_as_string(oi->s, sty->classno, oi->lsty);
      
      kw_out(oi, 1);
      kw_out(oi, 41);
    } else {
      kw_out(oi, 38);
      kw_out(oi, 19);
      kw_out(oi, 20);
    }
    if((sty->flags) & DKFIG_SVG_FL_TEXT) {
      if(sty->fonth) {
        switch((sty->fonth)->handling) {
          case 2: case 3: case 4: case 5: { } break;
  	default: {
  	  char *ptr; int ft;
          /* font-family */
  	  if(iscss) { kw_out(oi, 0); }
  	  kw_out(oi, 46); kw_out(oi, 24); kw_out(oi, 1);
          ptr = dkfont_get_svg_family_name((size_t)((sty->fonth)->fontno));
	  
  	  if(oi->urw_dir) {
  	    if(((sty->fonth)->fontno) >= 0) {
  	      if(((sty->fonth)->fontno) < 35) {
  	        ptr = urw_svg_font_families[(sty->fonth)->fontno];
		
  	      }
  	    }
  	  }
  	  ft = dkfont_get_features((size_t)((sty->fonth)->fontno));
	  had_entry = 0;
	  if(oi->fontmap) {
	    pofm = dkfont_get_one_font(oi->fontmap, (sty->fonth)->fontno);
	    if(pofm) {
	        dkfont_one_font_reset(pofm);
		while((pfr = dkfont_one_font_get(pofm)) != NULL) {
		  if(dkfont_rep_check_driver(pfr, kw[5])) {
		    fontfamilyname = dkfont_rep_get_family(pfr);
		    if(fontfamilyname) {	
		      if(had_entry) {
		        kw_out(oi, 55);
		      }
  	              kw_out(oi, (iscss ? 20 : 107));
		      dkstream_puts(oi->s, fontfamilyname);
  	              kw_out(oi, (iscss ? 20 : 107));
		      had_entry = 1;
		    }
		  }
		}
	    }
	  } else {
  	    if(ptr) {
	        
  	        kw_out(oi, (iscss ? 20 : 107));
  	        dkstream_puts(oi->s, ptr);
  	        kw_out(oi, (iscss ? 20 : 107));
		had_entry = 1;
  	    }
	  }
	  if(had_entry) {
	      kw_out(oi, 55);
	  }
  	  switch(ft & DK_FONT_FEATURE_FAMILY) {
  	      case DK_FONT_FEATURE_TT: {
  	        kw_out(oi, 58);
  	      } break;
  	      case DK_FONT_FEATURE_SF: {
  	        kw_out(oi, 57);
  	      } break;
  	      default: {
  	        kw_out(oi, 56);
  	      } break;
  	  }
  	  kw_out(oi, 43);
  	  kw_out(oi, (iscss ? 0 : 1));
  	  kw_out(oi, 47); kw_out(oi, 24); kw_out(oi, 1);
  	  kw_out(oi, ((ft & DK_FONT_FEATURE_IT) ? 60 : 59));
  	  kw_out(oi, 43);
  	  kw_out(oi, (iscss ? 0 : 1));
  	  kw_out(oi, 48); kw_out(oi, 24); kw_out(oi, 1);
  	  kw_out(oi, ((ft & DK_FONT_FEATURE_BD) ? 61 : 59));
  	  kw_out(oi, 43);
  	  kw_out(oi, 0);
  	  kw_out(oi, 49); kw_out(oi, 24); kw_out(oi, 1);
	  /*
	    font size
	  */
#if VERSION_BEFORE_2006_03_24
  	  dkstream_puts_double(
  	    oi->s,
  	    drd(
  	      dkma_mul_double_ok((sty->fonth)->fontsize, (oi->c)->fsf, &(oi->me)),
  	      oi->c, 1
  	    )
  	  );
#else
	  put_font_size(oi, sty);
#endif
  	  /* kw_out(oi, 81); */
  	  kw_out(oi, 43);
  	  kw_out(oi, (iscss ? 0 : 1));
            /* align */
  	  kw_out(oi, 51); kw_out(oi, 24); kw_out(oi, 1);
  	  switch(sty->talign) {
  	    case 1: {
  	      kw_out(oi, 53);
  	    } break;
  	    case 2: {
  	      kw_out(oi, 54);
  	    } break;
  	    default: {
  	      kw_out(oi, 52);
  	    } break;
  	  }
  	  kw_out(oi, 43);
  	  kw_out(oi, (iscss ? 0 : 1));
            /* color */
  	  /* kw_out(oi, 50); */
  	  kw_out(oi, 62); kw_out(oi, 24); kw_out(oi, 1);
  	  color_out(oi, sty->sred, sty->sgreen, sty->sblue);
  	  kw_out(oi, 43);
  	} break;
        }
      }
    } else {
      if(iscss) { kw_out(oi, 0); }
      kw_out(oi, 62); kw_out(oi, 24); kw_out(oi, 1);
      if((sty->flags) & DKFIG_SVG_FL_FILL) {
        if(sty->pat) {
          kw_out(oi, 74);
  	  kw_out(oi, 75);
  	  kw_out(oi, 45);
          kw_out(oi, 37);
          dkfig_tool_num_as_string(oi->s, (sty->pat)->patno, oi->lpat);
  	  kw_out(oi, 76);
        } else {
          color_out(oi, sty->fred, sty->fgreen, sty->fblue);
        }
      } else {
        kw_out(oi, 65);
      }
      kw_out(oi, 43);
      kw_out(oi, (iscss ? 0 : 1));
      kw_out(oi, 63); kw_out(oi, 24); kw_out(oi, 1);
      if((sty->flags) & DKFIG_SVG_FL_STROKE) {
        double mylw;
        color_out(oi, sty->sred, sty->sgreen, sty->sblue);
        kw_out(oi, 43);
        kw_out(oi, (iscss ? 0 : 1));
        mylw = ccll(oi, sty->lw, 1);
        /*
        mylw = dkma_l_to_double(sty->lw);
        mylw = dkma_mul_double_ok(mylw, oi->mx, &(oi->me));
        if((sty->flags) & DKFIG_SVG_FL_ENLIGHTEN) {
          mylw = mylw * 0.5;
        }
        */
        kw_out(oi, 64); kw_out(oi, 24); kw_out(oi, 1);
        put_double(oi, mylw, 1);
        kw_out(oi, 43);
        if(sty->lc) {
          kw_out(oi, (iscss ? 0 : 1));
          kw_out(oi, 67); kw_out(oi, 24); kw_out(oi, 1);
          switch(sty->lc) {
            case 2: {
  	    kw_out(oi, 70);
  	  } break;
  	  case 1: {
  	    kw_out(oi, 69);
  	  } break;
  	  default: {
  	    kw_out(oi, 68);
  	  } break;
          }
          kw_out(oi, 43);
        }
        if(sty->lj) {
          kw_out(oi, 0);
          kw_out(oi, 71); kw_out(oi, 24); kw_out(oi, 1);
          switch(sty->lj) {
            case 2: {
  	    kw_out(oi, 73);
  	  } break;
  	  case 1: {
  	    kw_out(oi, 69);
  	  } break;
  	  default: {
  	    kw_out(oi, 72);
  	  } break;
          }
          kw_out(oi, 43);
        }
        if((sty->ls) > 0) {
          /* double mylw; */
  	kw_out(oi, 0);
  	mylw = ccdl(oi, sty->sv, 0);
	dotlgt = 0.0;
	if(((oi->c)->opt1) & DKFIG_OPT_DP_DOT_LW) {
	  dotlgt = ccll(oi, ((sty->lw) ? sty->lw : 1L), 1);
	  dotlgt = drd(dotlgt, oi->c, 1);
	}
  	/*
          mylw = dkma_l_to_double(sty->sv);
          mylw = dkma_mul_double_ok(mylw, oi->mx, &(oi->me));
  	*/
          mylw = drd(mylw, oi->c, 1);
          kw_out(oi, 66); kw_out(oi, 24); kw_out(oi, 1);
          switch(sty->ls) {
            case 1: {
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	  } break;
  	  case 2: {
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	  } break;
  	  case 3: {
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	  } break;
  	  case 4: {
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	  } break;
  	  case 5: {
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s,dotlgt);
  	    kw_out(oi, 55);
  	    dkstream_puts_double(oi->s, mylw);
  	  } break;
          }
          kw_out(oi, 43);
        }
      } else {
        kw_out(oi, 65); kw_out(oi, 43);
      }
    }
    if(iscss) {
      kw_out(oi, 0);
      kw_out(oi, 42);
      kw_out(oi, 0);
    } else {
      kw_out(oi, 20);
      kw_out(oi, 0);
    }
  }
  
} /* }}} */



/* {{{ check_link

   Check whether or not an object has a link
   attached.

*/
static
int
check_link DK_P1(DRVE *,drve)
{
  int back = 0;
  if(drve) {
    if(drve->xli) {
      dksto_it_reset(drve->xli);
      if(dksto_it_next(drve->xli)) {
        back = 1;
      }
    }
  }
  return back;
} /* }}} */



/* {{{ print_a_contents

   Write the hyperlink for an object.

*/
static
void
print_a_contents DK_P2(OI *,oi, DRVE *,drve)
{
  dk_fig_svg_attr *a;
  if(drve->xli) {
    dksto_it_reset(drve->xli);
    while((a = (dk_fig_svg_attr *)dksto_it_next(drve->xli)) != NULL) {
      if((a->classid >= 0) && ((size_t)(a->classid) < sz_xlcmds) && (a->value)) {
        kw_out(oi, 0);
        dkstream_puts(oi->s, *(xlcmds[a->classid]));
	kw_out(oi, 19);
	kw_out(oi, 20);
	dkstream_puts(oi->s, a->value);
	kw_out(oi, 20);
      }
    }
  }
} /* }}} */



/* {{{ check_group

   Check whether we need to create a group for an
   object.
   This is usefull if SVGs are imported into a
   drawing application. In this case we want to
   copy/move not only lines/splines/arcs but also the
   arrowheads attached to them.

*/
static
int
check_group DK_P1(OI *,oi)
{
  int back = 0, how;
  how = get_how(oi->o);
  switch(how) {
    case 1: {
    } break;
    case 2: {
      if(((DRVE *)((oi->o)->drve))->st1) {
        back = 1;
      }
      if(((DRVE *)((oi->o)->drve))->st2) {
        back = 1;
      }
    } break;
    default: {
      if(!(((oi->o)->fpd).cl)) {
        if((((oi->o)->fpd).ar) & 3) {
	  back = 1;
	}
      }
    } break;
  }
  return back;
} /* }}} */



static char default_encoding[] = { "&#x  ;" };



/* {{{ print_utf8_encoded

   Transfer text contents to output, encode characters
   if necessary.

*/
static
void
print_utf8_encoded DK_P2(OI *,oi, char,*s)
{
  /*
  char buffer[10], c, *ptr;
  unsigned char uc; size_t sz;
  int must_encode;
  ptr = s;
  while(*ptr) {
    c = *ptr;
    must_encode = 1;
    if((c >= 'a') && (c <= 'z')) {
      must_encode = 0;
    } else {
      if((c >= 'A') && (c <= 'Z')) {
        must_encode = 0;
      } else {
        if((c >= '0') && (c <= '9')) {
	  must_encode = 0;
	} else {
	  switch(c) {
	    case '|':
	    case '@':
	    case '^':
	    case '!':
	    case '$':
	    case '%':
	    case '/':
	    case '(':
	    case ')':
	    case '=':
	    case '?':
	    case '~':
	    case '*':
	    case '#':
	    case '_':
	    case '+':
	    case '-':
	    case ':':
	    case ';':
	    case ',':
	    case '.':
	    case ' ': {
	      must_encode = 0;
	    } break;
	  }
	}
      }
    }
    if(must_encode) {
      uc = (unsigned char)c; sz = (size_t)uc;
      strcpy(buffer, default_encoding);
      buffer[3] = hex_digits[(sz >> 4) & 15];
      buffer[4] = hex_digits[sz & 15];
      dkstream_puts(oi->s, buffer);
    } else {
      buffer[0] = c;
      buffer[1] = '\0';
      dkstream_puts(oi->s, buffer);
    }
    ptr++;
  }
  */

  dk_udword ucb; unsigned char uc; char chr; int i;
  int cc, must_encode;
  char buffer[16];
  size_t max, used, avail, step;
  cc = 1; max = strlen(s); avail = max; used = 0;
  while(cc) {
    cc = 0;
    if(avail) {
      step = 0;
      cc = dkenc_utf82uc(&ucb, (unsigned char *)(&(s[used])), avail, &step);
      if(cc) {
        used += step;
	if(avail > step) {
	  avail = avail - step;
	} else {
	  avail = 0;
	}
	uc = (unsigned char)ucb; chr = (char)uc; i = (int)chr;
	must_encode = 1;
	if((chr >= 'a') && (chr <= 'z')) {
	  must_encode = 0;
	} else {
	  if((chr >= 'A') && (chr <= 'Z')) {
	    must_encode = 0;
	  } else {
	    if((chr >= '0') && (chr <= '9')) {
	      must_encode = 0;
	    } else {
	      switch(chr) {
	        case '|':
	        case '@':
	        case '^':
	        case '!':
	        case '$':
	        case '%':
	        case '/':
	        case '(':
	        case ')':
	        case '=':
	        case '?':
	        case '~':
	        case '*':
	        case '#':
	        case '_':
	        case '+':
	        case '-':
	        case ':':
	        case ';':
	        case ',':
	        case '.':
	        case ' ': {
	          must_encode = 0;
	        } break;
	      }
	    }
	  }
	}
	if(must_encode) {
	  /*
	  sz = size_t uc;
	  strcpy(buffer, default_encoding);
	  buffer[3] = hex_digits[(sz >> 4) & 15];
	  buffer[4] = hex_digits[sz & 15];
	  */
	  if(ucb > 0x000000FFUL) {
	    if(ucb > 0x0000FFFFUL) {
	      if(ucb > 0x00FFFFFFUL) {
#if DK_HAVE_SNPRINTF || HAVE_SNPRINTF
	        snprintf(buffer, sizeof(buffer), "&#x%08lX;", ucb);
		buffer[sizeof(buffer)-1] = '\0';
#else
	        sprintf(buffer, "&#x%08lX;", ucb);
#endif
	      } else {	/* 6 */
#if DK_HAVE_SNPRINTF || HAVE_SNPRINTF
	        snprintf(buffer, sizeof(buffer), "&#x%06lX;", ucb);
		buffer[sizeof(buffer)-1] = '\0';
#else
	        sprintf(buffer, "&#x%06lX;", ucb);
#endif
	      }
	    } else {	/* 4 */
#if DK_HAVE_SNPRINTF || HAVE_SNPRINTF
              snprintf(buffer, sizeof(buffer), "&#x%04lX;", ucb);
	      buffer[sizeof(buffer)-1] = '\0';
#else
	      sprintf(buffer, "&#x%04lX;", ucb);
#endif
	    }
	  } else {	/* 2 */
#if DK_HAVE_SNPRINTF || HAVE_SNPRINTF
            snprintf(buffer, sizeof(buffer), "&#x%02lX;", ucb);
	    buffer[sizeof(buffer)-1] = '\0';
#else
            sprintf(buffer, "&#x%02lX;", ucb);
#endif
	  }
	} else {
	  buffer[0] = chr; buffer[1] = '\0';
	}
	dkstream_puts(oi->s, buffer);
      }
    }
  }
} /* }}} */



/* {{{ print_text_encoded

   Transfer text contents to output, encode characters
   if necessary.

*/
static
void
print_text_encoded DK_P2(OI *,oi, char,*s)
{
  char buffer[10], c, *ptr;
  unsigned char uc; size_t sz;
  int must_encode;
  ptr = s;
  while(*ptr) {
    c = *ptr;
    must_encode = 1;
    if((c >= 'a') && (c <= 'z')) {
      must_encode = 0;
    } else {
      if((c >= 'A') && (c <= 'Z')) {
        must_encode = 0;
      } else {
        if((c >= '0') && (c <= '9')) {
	  must_encode = 0;
	} else {
	  switch(c) {
	    case '|':
	    case '@':
	    case '^':
	    case '!':
	    case '$':
	    case '%':
	    case '/':
	    case '(':
	    case ')':
	    case '=':
	    case '?':
	    case '~':
	    case '*':
	    case '#':
	    case '_':
	    case '+':
	    case '-':
	    case ':':
	    case ';':
	    case ',':
	    case '.':
	    case ' ': {
	      must_encode = 0;
	    } break;
	  }
	}
      }
    }
    if(must_encode) {
      uc = (unsigned char)c; sz = (size_t)uc;
      strcpy(buffer, default_encoding);
      buffer[3] = hex_digits[(sz >> 4) & 15];
      buffer[4] = hex_digits[sz & 15];
      dkstream_puts(oi->s, buffer);
    } else {
      buffer[0] = c;
      buffer[1] = '\0';
      dkstream_puts(oi->s, buffer);
    }
    ptr++;
  }
} /* }}} */



/* {{{ style_or_class

   Write either style="..." parameter or
   class="..." reference.

*/
static
void
style_or_class DK_P2(OI *,oi, SVGSTY *,s)
{
  if(oi->prep_mods) {
    kw_out(oi, 0);
    style_out(oi, s, 0);
  } else {
    if(((oi->c)->opt1) & DKFIG_OPT_USE_CSS) {
      kw_out(oi, 1);
      kw_out(oi, 80);
      kw_out(oi, 19);
      kw_out(oi, 20);
      kw_out(oi, 44);
      dkfig_tool_num_as_string(oi->s, s->classno, oi->lsty);
      kw_out(oi, 20);
      kw_out(oi, 0);
    } else {
      kw_out(oi, 0);
      style_out(oi, s, 0);
    }
  }
} /* }}} */




/* {{{ print_text

   Generate output for a text.

*/
static
int
print_text DK_P2(OI *,oi, int,ug)
{
  int back = 0;
  dk_fig_text *t = NULL;
  dk_fig_fonth_t *f = NULL;
  DRVE *d = NULL;
  SVGSTY *s = NULL;
  t = (dk_fig_text *)((oi->o)->data);
  d = (DRVE *)((oi->o)->drve);
  if(d) {
    s = d->st1;
  }
  if((t) && (s)) {
    if(t->text) {
      f = t->font_handling;
      switch(f->handling) {
        case 2: case 3: case 4: case 5: {} break;
        default: {
          back = 1;
          begin_tag(oi, 77);
	  kw_out(oi, 1);
	  if(fabs(t->angle) > DKFIG_EPSILON) {
	    kw_out(oi, 92); kw_out(oi, 19);
	    kw_out(oi, 20);
	    kw_out(oi, 93);
            kw_out(oi, 75);
	    put_double(oi, cclx(oi, t->x), 1);
	    kw_out(oi, 1);
	    put_double(oi, ccly(oi, t->y), 1);
	    kw_out(oi, 76);
	    kw_out(oi, 1);
            kw_out(oi, 94);
	    kw_out(oi, 75);
	    kw_out(oi, 97);
	    dkstream_puts_double(oi->s, 
	      drd(
	        dkma_div_double_ok(
		  dkma_mul_double_ok(180.0, t->angle, &(oi->me)),
		  M_PI,
		  &(oi->me)
		),
	        oi->c, 1
	      )
	    );
	    kw_out(oi, 76);
	    kw_out(oi, 20);
	    kw_out(oi, 1);
	    kw_out(oi, 14);
	    kw_out(oi, 19);
	    kw_out(oi, 20);
	    kw_out(oi, 103);
	    kw_out(oi, 20);
	    kw_out(oi, 1);
	    kw_out(oi, 15);
	    kw_out(oi, 19);
	    kw_out(oi, 20);
	    kw_out(oi, 103);
	    kw_out(oi, 20);
	  } else {
	    kw_out(oi, 14);
	    kw_out(oi, 19);
	    kw_out(oi, 20);
	    put_double(oi, cclx(oi, t->x), 1);
	    kw_out(oi, 20);
	    kw_out(oi, 1);
	    kw_out(oi, 15);
	    kw_out(oi, 19);
	    kw_out(oi, 20);
	    put_double(oi, ccly(oi, t->y), 1);
	    kw_out(oi, 20);
	  }
	  style_or_class(oi, s);
	  if(!ug) {
	    svg_drve_write(oi, oi->o, (DRVE *)((oi->o)->drve), 0);
	  }
          kw_out(oi, 3);
	  if(((oi->c)->opt2) & DKFIG_OPT_UTF_8) {
	    /* UTF-8 encoded */
	    print_utf8_encoded(oi, t->text);
	  } else {
	    print_text_encoded(oi, t->text);
	  }
          end_tag(oi, 77);
        } break;
      }
    }
  }
  return back;
} /* }}} */



/* {{{ point_double

   Write point specified by double coordinates
   in Fig space.

*/
static
void
point_double DK_P4(OI *,oi, double,x, double,y, int,w)
{
  put_double(
    oi,
    ccdx(oi, x),
    w
  );
  kw_out(oi, 55);
  put_double(
    oi,
    ccdy(oi, y),
    w
  );
} /* }}} */



/* {{{ point_long

   Write point specified by long coordinates
   in Fig space.

*/
static
void
point_long DK_P3(OI *,oi, long,x, long,y)
{
  point_double(
    oi,
    dkma_l_to_double(x),
    dkma_l_to_double(y),
    1
  );
} /* }}} */



/* {{{ print_rect_arc_bb

   Print rectangle/arc box specified by
   bounding box information b, style s.
   If da is non-zero, we have an arc box,
   radius is a.
   b and a are in output space.

*/
static
void
print_rect_arc_bb DK_P5(\
  OI *,oi, dk_fig_bb *,b, SVGSTY *,s, int,da, double,a\
)
{
  begin_tag(oi, 79);
  kw_out(oi, 1);
  kw_out(oi, 14);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, b->xmin, 1);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 15);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, b->ymin, 1);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 16);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, (b->xmax - b->xmin), 1);
  kw_out(oi, 20);
  kw_out(oi, 1);
  kw_out(oi, 17);
  kw_out(oi, 19);
  kw_out(oi, 20);
  put_double(oi, (b->ymax - b->ymin), 1);
  kw_out(oi, 20);
  if(da) {
    kw_out(oi, 0);
    kw_out(oi, 82);
    kw_out(oi, 19);
    kw_out(oi, 20);
    put_double(oi, a, 1);
    kw_out(oi, 20);
    kw_out(oi, 1);
    kw_out(oi, 83);
    kw_out(oi, 19);
    kw_out(oi, 20);
    put_double(oi, a, 1);
    kw_out(oi, 20);
  }
  style_or_class(oi, s);
  finish_tag(oi);
} /* }}} */



/* {{{ print_rect_bb

   Draw a rectangle as specified in the
   bounding-box structure b (specified
   in output space).

*/
static
void
print_rect_bb DK_P3(OI *,oi, dk_fig_bb *,b, SVGSTY *,s)
{
  print_rect_arc_bb(oi,b,s,0,0.0);
} /* }}} */



/* {{{ print_image

   Draw included image.

*/
static
int
print_image DK_P2(OI *,oi, int,ug)
{
  int back = 0;
  dk_fig_bb ibb;
  dk_fig_polyline *p;
  long *xptr, *yptr; size_t i;
  SVGSTY *s;
  double xmin, xmax, ymin, ymax;
  double ori_width, ori_height, xstart, ystart;
  double new_width, new_height;
  unsigned long w, h;
  int res;

  p = (dk_fig_polyline *)((oi->o)->data);
  if(p) {
    if(p->imagename) {
      dkfig_tool_bb_reset(&ibb);
      xptr = p->xvalues; yptr = p->yvalues;
      for(i = 0; i < p->npoints; i++) {
        dkfig_tool_bb_add_x(&ibb, cclx(oi, *xptr));
        dkfig_tool_bb_add_y(&ibb, ccly(oi, *yptr));
        xptr++; yptr++;
      }
      if(p->npoints > 0) {
        back = 1;
        if(((DRVE *)((oi->o)->drve))->st1) {
          s = ((DRVE *)((oi->o)->drve))->st1;
          print_rect_bb(oi, &ibb, s);
        }
        xmin = dkfig_tool_bb_get_xmin(&ibb);
        xmax = dkfig_tool_bb_get_xmax(&ibb);
        ymin = dkfig_tool_bb_get_ymin(&ibb);
        ymax = dkfig_tool_bb_get_ymax(&ibb);
        if(((DRVE *)((oi->o)->drve))->st2) {
          double lwh;
	  lwh = 0.5 * ccll(oi, (((DRVE *)((oi->o)->drve))->st2)->lw, 1);
	  xmin = dkma_add_double_ok(xmin, lwh, &(oi->me));
	  xmax = dkma_sub_double_ok(xmax, lwh, &(oi->me));
	  ymin = dkma_add_double_ok(ymin, lwh, &(oi->me));
	  ymax = dkma_sub_double_ok(ymax, lwh, &(oi->me));
        }
        ori_width = dkma_sub_double_ok(xmax, xmin, &(oi->me));
        ori_height = dkma_sub_double_ok(ymax, ymin, &(oi->me));
	new_width = ori_width; new_height = ori_height;
	xstart = xmin; ystart = ymin;
	
        res = dkfig_tool2_get_image_size(oi->c, p->imagename, &w, &h);
	if(res) {
	  if(((oi->c)->opt1) & DKFIG_OPT_KEEP_BITMAP_WH_RATIO) {
	    double ls, rs;
	    
	    ls = dkma_div_double_ok(
	      dkma_l_to_double(h),
	      dkma_l_to_double(w),
	      &(oi->me)
	    );
	    rs = dkma_div_double_ok(ori_height, ori_width, &(oi->me));
	    if(ls > rs) {
	      new_width = dkma_mul_double_ok(
	        new_height,
		dkma_div_double_ok(
		  dkma_l_to_double(w),
		  dkma_l_to_double(h),
		  &(oi->me)
		),
		&(oi->me)
	      );
	      xstart = dkma_add_double_ok(
	        xstart,
		(0.5 * dkma_sub_double_ok(ori_width, new_width, &(oi->me))),
		&(oi->me)
	      );
	    } else {
	      new_height = dkma_mul_double_ok(
	        new_width,
		dkma_div_double_ok(
		  dkma_l_to_double(h),
		  dkma_l_to_double(w),
		  &(oi->me)
		),
		&(oi->me)
	      );
	      ystart = dkma_add_double_ok(
	        ystart,
		(0.5 * dkma_sub_double_ok(ori_height, new_height, &(oi->me))),
		&(oi->me)
	      );
	    }
	  }
	} else {
	  dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_WARNING, 95, 92, p->imagename);
	}
	
	begin_tag(oi, 112);
	kw_out(oi, 1);
        kw_out(oi, 14);
	kw_out(oi, 19);
	kw_out(oi, 20);
	put_double(oi, xstart, 1);
	kw_out(oi, 20);
	kw_out(oi, 1);
        kw_out(oi, 15);
	kw_out(oi, 19);
	kw_out(oi, 20);
	put_double(oi, ystart, 1);
	kw_out(oi, 20);
        kw_out(oi, 1);
        kw_out(oi, 16);
	kw_out(oi, 19);
	kw_out(oi, 20);
	put_double(oi, new_width, 1);
	kw_out(oi, 20);
        kw_out(oi, 1);
        kw_out(oi, 17);
	kw_out(oi, 19);
	kw_out(oi, 20);
	put_double(oi, new_height, 1);
	kw_out(oi, 20);
	kw_out(oi, 0);
	dkstream_puts(oi->s, xlc00[0]);
	kw_out(oi, 19);
	kw_out(oi, 20);
	dkstream_puts(oi->s, p->imagename);
	kw_out(oi, 20);
	kw_out(oi, 0);
	kw_out(oi, 4);
	kw_out(oi, 3);
	kw_out(oi, 0);
        if(((DRVE *)((oi->o)->drve))->st2) {
	  s = ((DRVE *)((oi->o)->drve))->st2;
	  print_rect_bb(oi, &ibb, s);
        }
      }
    }
  }
  return back;
} /* }}} */



/* {{{ check_rx

   Check the corner radius for arc boxes, correct
   (decrease) radius if necessary.

*/
static
double
check_rx DK_P4(double,rx, OI *,oi, double,mini, double,maxi)
{
  double back, distance;
  back = rx;
  if(back < 0.0) { back = 0.0 - back; }
  distance = fabs(dkma_sub_double_ok(maxi, mini, &(oi->me)));
  if(back > (0.5 * distance)) {
    back = 0.5 * distance;
  }
  return back;
} /* }}} */



/* {{{ print_path_object

   This function is the entry point to draw a
   polyline/polygon, spline, ellipse or arc.
   (Everything except text or included image)

*/
static
int
print_path_object DK_P2(OI *,oi, int,ug)
{
  int back = 0;
  dk_fig_arc *pa;
  dk_fig_spline *ps;
  dk_fig_polyline *pp;
  dk_fig_ellipse *pe;
  DRVE *d = NULL; SVGSTY *s = NULL;
  d = (DRVE *)((oi->o)->drve);
  if(d) {
    s = d->st1;
    if(s) {
      switch((oi->o)->objtype) {
        case DK_FIG_OBJ_ARC: {
          pa = (dk_fig_arc *)((oi->o)->data);
          if(pa) {
	    double aa, ae, p1x, p1y, p2x, p2y, r;
	    int    islong;
	    aa = ae = p1x = p1y = p2x = p2y = 0.0;
	    islong = 0;
	    r = ccdr(oi, (pa->calc).ra);
	    aa = (pa->calc).astart;
	    if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 2)) {
	      aa = dkma_add_double_ok(aa, pa->lba, &(oi->me));
	    }
	    ae = dkma_add_double_ok(
	      (pa->calc).astart, (pa->calc).alength, &(oi->me)
	    );
	    if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 1)) {
	      ae = dkma_sub_double_ok(ae, pa->rba, &(oi->me));
	    }
	    p1x = dkma_add_double_ok(
	      (pa->calc).xm,
	      (((pa->calc).ra) * cos(aa)),
	      &(oi->me)
	    );
	    p2x = dkma_add_double_ok(
	      (pa->calc).xm,
	      (((pa->calc).ra) * cos(ae)),
	      &(oi->me)
	    );
	    if(dkfig_tool_invert_y(oi->d)) {
	      p1y = dkma_sub_double_ok(
	        (pa->calc).ym,
		(((pa->calc).ra) * sin(aa)),
		&(oi->me)
	      );
	      p2y = dkma_sub_double_ok(
	        (pa->calc).ym,
		(((pa->calc).ra) * sin(ae)),
		&(oi->me)
	      );
	    } else {
	      p1y = dkma_add_double_ok(
	        (pa->calc).ym,
		(((pa->calc).ra) * sin(aa)),
		&(oi->me)
	      );
	      p2y = dkma_add_double_ok(
	        (pa->calc).ym,
		(((pa->calc).ra) * sin(ae)),
		&(oi->me)
	      );
	    }
	    while(ae < aa) {
	      ae = dkma_add_double_ok(ae, (2.0 * M_PI), &(oi->me));
	    }
	    if(dkma_sub_double_ok(ae, aa, &(oi->me)) >= M_PI) {
	      islong = 1;
	    } else {
	      islong = 0;
	    }
	    back = 1;
	    begin_tag(oi, 98);
	    style_or_class(oi, s);
	    kw_out(oi, 99);
	    kw_out(oi, 19);
	    kw_out(oi, 20);
	    if(((oi->o)->fpd).cl) {	/* pie-wedge */
	      kw_out(oi, 100);
	      point_double(oi, (pa->calc).xm, (pa->calc).ym, 1);
	      kw_out(oi, 1);
	      kw_out(oi, 101);
	      point_double(oi, p1x, p1y, 1);
	      kw_out(oi, 0);
	    } else {			/* open arc */
	      kw_out(oi, 100);
	      point_double(oi, p1x, p1y, 1);
	    }
	    kw_out(oi, 1);
	    kw_out(oi, 102);
	    put_double(oi, r, 1);
	    kw_out(oi, 1);
	    put_double(oi, r, 1);
	    kw_out(oi, 1);
	    kw_out(oi, 103);
	    kw_out(oi, 1);
	    kw_out(oi, (islong ? 104 : 103));
	    kw_out(oi, 1);
	    kw_out(oi, 103);
	    kw_out(oi, 1);
	    point_double(oi, p2x, p2y, 1);
	    if(((oi->o)->fpd).cl) {	/* pie-wedge */
	      kw_out(oi, 0);
	      kw_out(oi, 101);
	      point_double(oi, (pa->calc).xm, (pa->calc).ym, 1);
	      kw_out(oi, 105);
	    }
	    kw_out(oi, 20);
	    kw_out(oi, 0);
	    finish_tag(oi);
          }
        } break;
        case DK_FIG_OBJ_SPLINE: {
	  dk_fig_bezier_point *bpptr;
          size_t nsegs, li, ri, maxli;
          ps = (dk_fig_spline *)((oi->o)->data);
          if(ps) {
	    if((ps->nbpoints) >= 2) {
              begin_tag(oi, 98);
	      style_or_class(oi, s);
	      kw_out(oi, 99);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
	      bpptr = ps->bpoints;
	      nsegs = ps->nbpoints - 1;
	      if(((oi->o)->fpd).cl) { nsegs = ps->nbpoints; }
	      if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 2)) {
	        /* moveto point pa */
		kw_out(oi, 100);
		point_double(oi,(ps->pa).value.x,(ps->pa).value.y, 1);
		kw_out(oi, 0);
		/* bezier to point pa2 */
		kw_out(oi, 106);
		point_double(oi, (ps->pa).rcontrol.x, (ps->pa).rcontrol.y, 1);
		kw_out(oi, 1);
		point_double(oi, (ps->pa2).lcontrol.x, (ps->pa2).lcontrol.y, 1);
		kw_out(oi, 1);
		point_double(oi, (ps->pa2).value.x, (ps->pa2).value.y, 1);
		li = ps->normals;
	      } else {
	        /* moveto point 0 */
		kw_out(oi, 100);
		point_double(oi,bpptr[0].value.x,bpptr[0].value.y, 1);
		li = 0;
	      }
	      kw_out(oi, 0);
              if((ps->normale > 0)||(((oi->o)->fpd).cl)||(!((((oi->o)->fpd).ar) & 1))) 
	      {
                maxli = ps->nbpoints - 2;
                if(((oi->o)->fpd).cl) { maxli = ps->nbpoints - 1; }
                if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 1)) {
                  maxli = ps->normale - 1;
                }
		while(li <= maxli) {
		  ri = li + 1;
		  if(ri >= ps->nbpoints) { ri = 0; }
		  kw_out(oi, 106);
		  point_double(oi, bpptr[li].rcontrol.x, bpptr[li].rcontrol.y, 1);
		  kw_out(oi, 1);
		  point_double(oi, bpptr[ri].lcontrol.x, bpptr[ri].lcontrol.y, 1);
		  kw_out(oi, 1);
		  point_double(oi, bpptr[ri].value.x, bpptr[ri].value.y, 1);
		  kw_out(oi, 0);
		  li++;
		}
              }
	      if(((oi->o)->fpd).cl) {
	        kw_out(oi, 105);
	      } else {
	        if((((oi->o)->fpd).ar) & 1) {
		  kw_out(oi, 106);
		  point_double(oi, (ps->pe2).rcontrol.x, (ps->pe2).rcontrol.y, 1);
		  kw_out(oi, 1);
		  point_double(oi, (ps->pe).lcontrol.x, (ps->pe).lcontrol.y, 1);
		  kw_out(oi, 1);
		  point_double(oi, (ps->pe).value.x, (ps->pe).value.y, 1);
		  kw_out(oi, 0);
		}
	      }
	      kw_out(oi, 20);
	      kw_out(oi, 0);
	      finish_tag(oi);
	    }
          }
        } break;
        case DK_FIG_OBJ_POLYLINE: {
          pp = (dk_fig_polyline *)((oi->o)->data);
          if(pp) {
	    long *xptr, *yptr; size_t i, npoints;
	    double rx; int urx, wr_nl, wr_no;
            dk_fig_bb ibb;
	    urx = 0; rx = 0.0;
	    switch((oi->o)->subtype) {
	      case 5: {	/* image, handled somewhere else */
	      } break;
	      case 2:	/* box */
	      case 4: {	/* arc-box */
                dkfig_tool_bb_reset(&ibb);
                xptr = pp->xvalues; yptr = pp->yvalues;
                for(i = 0; i < pp->npoints; i++) {
                  dkfig_tool_bb_add_x(&ibb, cclx(oi, *xptr));
                  dkfig_tool_bb_add_y(&ibb, ccly(oi, *yptr));
                  xptr++; yptr++;
                }
		if(pp->npoints > 0) {
		  if((oi->o)->subtype == 4) {
		    if(pp->radius > 0L) {
		      urx = 1;
		      rx = ccll(oi, pp->radius, 0);
		      rx = check_rx(rx, oi, ibb.xmin, ibb.xmax);
		      rx = check_rx(rx, oi, ibb.ymin, ibb.ymax);
		    }
		  }
		  print_rect_arc_bb(oi, &ibb, s, urx, rx);
		  back = 1;
		}
	      } break;
	      case 3: {	/* polygon */
	        xptr = pp->xvalues; yptr = pp->yvalues;
		npoints = pp->npoints;
		if(npoints) {
		  back = 1;
		  if(xptr[0] == xptr[npoints-1]) {
		    if(yptr[0] == yptr[npoints-1]) {
		      npoints--;
		    }
		  }
		  begin_tag(oi, 84);
		  style_or_class(oi, s);
		  kw_out(oi, 86);
		  kw_out(oi, 19);
		  kw_out(oi, 20);
		  wr_nl = 0; wr_no = 0;
		  for(i = 0; i < npoints; i++) {
		    if(i) {
		      /*
		      kw_out(oi, (wr_nl ? 0 : 1));
		      if(wr_nl) { wr_nl = 0; }
		      if(wr_no >= 3) {
		        wr_no = 0; wr_nl = 1;
		      } else {
		        wr_no++;
		      }
		      */
		      kw_out(oi, 0);
		    }
		    point_long(oi, xptr[i], yptr[i]);
		  }
		  kw_out(oi, 20);
		  kw_out(oi, 0);
		  finish_tag(oi);
		}
	      } break;
	      case 1: {	/* polyline */
	        xptr = pp->xvalues; yptr = pp->yvalues;
		npoints = pp->npoints;
		if(npoints) {
		  back = 1;
		  begin_tag(oi, 85);
		  style_or_class(oi, s);
		  kw_out(oi, 86);
		  kw_out(oi, 19);
		  kw_out(oi, 20);
		  wr_nl = 0; wr_no = 0;
		  for(i = 0; i < npoints; i++) {
		    if(i) {
		      /* 
		      kw_out(oi, (wr_nl ? 0 : 1));
		      if(wr_nl) { wr_nl = 0; }
		      if(wr_no >= 3) {
		        wr_no = 0; wr_nl = 1;
		      } else {
		        wr_no++;
		      }
		      */
		      kw_out(oi, 0);
		    }
		    if((i == 0) && ((((oi->o)->fpd).ar) & 2)) {
		      point_double(oi, (pp->pa).x, (pp->pa).y, 1);
		    } else {
		      if((i == (npoints - 1)) && ((((oi->o)->fpd).ar) & 1)) {
		        point_double(oi, (pp->pe).x, (pp->pe).y, 1);
		      } else {
		        point_long(oi, xptr[i], yptr[i]);
		      }
		    }
		  }
		  kw_out(oi, 20);
		  kw_out(oi, 0);
		  finish_tag(oi);
		}
	      } break;
	    }
          }
        } break;
        case DK_FIG_OBJ_ELLIPSE: {
          pe = (dk_fig_ellipse *)((oi->o)->data);
          if(pe) {
	    if((pe->radiusx) == (pe->radiusy)) {
	      begin_tag(oi, 90);
	      kw_out(oi, 1);
	      kw_out(oi, 87);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
	      put_double(oi, cclx(oi, pe->centerx), 1);
	      kw_out(oi, 20);
	      kw_out(oi, 1);
	      kw_out(oi, 88);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
	      /* cy */
	      put_double(oi, ccly(oi, pe->centery), 1);
	      kw_out(oi, 20);
	      kw_out(oi, 1);
	      kw_out(oi, 89);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
	      /* r */
	      put_double(oi, cclr(oi, pe->radiusx), 1);
	      kw_out(oi, 20);
	      style_or_class(oi, s);
	      if(!ug) {
	        svg_drve_write(oi, oi->o, (DRVE *)((oi->o)->drve), 0);
	      }
	      finish_tag(oi);
	    } else {
	      begin_tag(oi, 91);
	      kw_out(oi, 1);
	      kw_out(oi, 92);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
              kw_out(oi, 93);
	      kw_out(oi, 75);
	      put_double(oi, cclx(oi, pe->centerx), 1);
	      kw_out(oi, 1);
	      put_double(oi, ccly(oi, pe->centery), 1);
	      kw_out(oi, 76);
	      if(fabs(pe->angle) > DKFIG_EPSILON) {
	        kw_out(oi, 1);
		kw_out(oi, 94);
		kw_out(oi, 75);
		kw_out(oi, 97);
		put_double(
		  oi,
		  dkma_mul_double_ok(
		    pe->angle,
		    dkma_div_double_ok(180.0, M_PI, &(oi->me)),
		    &(oi->me)
		  ),
		  1
		);
		kw_out(oi, 76);
	      }
	      kw_out(oi, 20);
	      kw_out(oi, 0);
	      kw_out(oi, 95);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
	      put_double(oi, cclr(oi, pe->radiusx), 1);
	      kw_out(oi, 20);
	      kw_out(oi, 1);
	      kw_out(oi, 96);
	      kw_out(oi, 19);
	      kw_out(oi, 20);
	      put_double(oi, cclr(oi, pe->radiusy), 1);
	      kw_out(oi, 20);
	      style_or_class(oi, s);
	      if(!ug) {
	        svg_drve_write(oi, oi->o, (DRVE *)((oi->o)->drve), 0);
	      }
	      finish_tag(oi);
	    }
          }
        } break;
      }
    }
  }
  return back;
} /* }}} */



/* {{{ arrow_head

   Draw arrowhead, this is typically done after
   drawing the line.

*/
static
void
arrow_head DK_P5(OI *,oi, OBJ *,o, AH *,ah, DRVE *,d, SVGSTY *,s)
{
  if((ah->type) > 0) {
    begin_tag(oi, 84);
  } else {
    begin_tag(oi, 85);
  }
  style_or_class(oi, s);
  kw_out(oi, 86);
  kw_out(oi, 19);
  kw_out(oi, 20);
  point_double(oi, (ah->p1).x, (ah->p1).y, 1);
  kw_out(oi, 1);
  point_double(oi, (ah->p2).x, (ah->p2).y, 1);
  kw_out(oi, 1);
  point_double(oi, (ah->p3).x, (ah->p3).y, 1);
  if((ah->numpoints) > 3) {
    kw_out(oi, 1);
    point_double(oi, (ah->p4).x, (ah->p4).y, 1);
  }
  kw_out(oi, 20);
  kw_out(oi, 0);
  finish_tag(oi);
} /* }}} */



/* {{{ output_object

   Generate output for one graphics object.

*/
static
int
output_object DK_P1(OI *,oi)
{
  int back = 1;
  unsigned long backupopt1;
  int use_link, use_group, how;
  DRVE *d; SVGSTY *s;
  
  backupopt1 = (oi->c)->opt1;
  /* handle special comments */
  if((oi->o)->osci) {
    (void)handle_spc_for_object(oi, oi->o, (oi->o)->osci, 0, 0);
  }
  use_link = use_group = how = 0;
  use_link = check_link((DRVE *)((oi->o)->drve));
  use_group = check_group(oi);
  if(((oi->c)->opt1) & DKFIG_OPT_VERBOSE_OUTPUT) {
    kw_out(oi, 113);
    kw_out(oi, 115);
    dkstream_puts_ul(oi->s, (oi->o)->lineno);
    kw_out(oi, 55);
    kw_out(oi, 1);
    kw_out(oi, 116);
    dkstream_puts_ul(oi->s, (unsigned long)((oi->o)->layer));
    kw_out(oi, 114);
    kw_out(oi, 0);
  }
  if(use_link) {
    begin_tag(oi, 33);
    print_a_contents(oi, (DRVE *)((oi->o)->drve));
    kw_out(oi, 0); kw_out(oi, 3); kw_out(oi, 0);
  }
  if(use_group) {
    begin_tag(oi, 34);
    if(how != 2) {
      svg_drve_write(oi, oi->o, (DRVE *)((oi->o)->drve), 0);
    }
    kw_out(oi, 3); kw_out(oi, 0);
  }
  /* print object */
  how = get_how(oi->o);
  switch(how) {
    case 1: {	/* text */
      print_text(oi, use_group);
    } break;
    case 2: {	/* included image */
      print_image(oi, use_group);
    } break;
    default: {	/* path object */
      int must_draw = 1;
      if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BG_RECTANGLE) {
        int wbgr = 0;
	if(((oi->c)->opt2) & DKFIG_OPT_WHITE_BGRECT) {
	  wbgr = 1;
	}
	if(dkfig_tool2_obj_is_bg_rect(oi->o, wbgr)) {
	  must_draw = 0;
	}
      }
      if(must_draw) {
        print_path_object(oi, use_group);
      }
    } break;
  }
  /* forward arrow */
  if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 1)) {
    d = (DRVE *)((oi->o)->drve);
    if(d) {
      s = d->st2;
      if(s) {
        arrow_head(oi, oi->o, &(((oi->o)->fpd).ahf), d, s);
      }
    }
  }
  /* backward arrow */
  if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 2)) {
    d = (DRVE *)((oi->o)->drve);
    if(d) {
      s = d->st3;
      if(s) {
        arrow_head(oi, oi->o, &(((oi->o)->fpd).ahb), d, s);
      }
    }
  }
  if(use_group) {
    end_tag(oi, 34);
  }
  if(use_link) {
    end_tag(oi, 33);
  }
  (oi->c)->opt1 = backupopt1;
  
  return back;
} /* }}} */



/* {{{ svg_title_and_desc

   Write <title>...</title> and
   <desc>...</desc> sections.

*/
static
int
svg_title_and_desc DK_P1(OI *,oi)
{
  int back = 1;
  
  begin_tag(oi, 25); kw_out(oi, 3);
  dkstream_puts(oi->s, (((oi->c)->ifn2) ? ((oi->c)->ifn2) : (name_stdin)));
  end_tag(oi, 25);
  begin_tag(oi, 26); kw_out(oi, 3);
  kw_out(oi, 27);
  end_tag(oi, 26); 
  return back;
} /* }}} */



/* {{{ write_js_libraries

   Write JavaScript code from the named library files
   into the <defs>...</defs> section.

*/
static
int
write_js_libraries DK_P1(OI *,oi)
{
  int back = 1; int is_first;
  dk_fig_opt *fo;
  FILE *fipo;
  char inputline[512], *sptr;
  
  if((oi->jsl) && (oi->jsli)) {
    is_first = 1;
    dksto_it_reset(oi->jsli);
    while((fo = (dk_fig_opt *)dksto_it_next(oi->jsli)) != NULL) {
      if(fo->name) {
        if((oi->c)->app) {
	  fipo = dkapp_fopen((oi->c)->app, fo->name, str_mode_open_read);
	} else {
	  fipo = dksf_fopen(fo->name, str_mode_open_read);
	}
	if(fipo) {
	  if(is_first) {
	    begin_tag(oi, 32); kw_out(oi, 1);
	    kw_out(oi, 29); kw_out(oi, 3);
	    kw_out(oi, 30); kw_out(oi, 0);
	    is_first = 0;
	  }
	  while(fgets(inputline, sizeof(inputline), fipo)) {
	    sptr = dkstr_start(inputline, NULL);
	    if(sptr) {
	      dkstr_chomp(sptr, NULL);
	      dkstream_puts(oi->s, inputline);
	    }
	    kw_out(oi, 0);
	  }
	  fclose(fipo);
	} else {
	  /* Warning: Failed to read file */
	  if((oi->c)->app) {
	    dkapp_err_fopenr((oi->c)->app, fo->name);
	  }
	}
      }
    }
    if(!is_first) {
      kw_out(oi, 31); end_tag(oi, 32);
    }
  } 
  return back;
} /* }}} */



/* {{{ svg_defs

   Write file the <defs>...</defs> section
   which consists of patterns, fonts, styles
   and JavaScript code.

*/
static
int
svg_defs DK_P1(OI *,oi)
{
  int back = 1;
  int is_first;
  size_t i, ft;
  SVGPAT *pat; SVGSTY *sty;
  dk_one_font_mapping_t	*pofm;
  dk_font_replacement_t *pfr;
  char *fontfamilyname;
  char *fontlocation;
  char *fontfilename;
  char *fontid;
  char *fontformat;
  
  back = write_js_libraries(oi);
  begin_tag(oi, 28); kw_out(oi, 3); kw_out(oi, 0);
  if(oi->pati) {
    dksto_it_reset(oi->pati);
    while((pat = (SVGPAT *)dksto_it_next(oi->pati)) != NULL) {
      pattern_out(oi, pat);
    }
  }
  is_first = 1;
  if((oi->urw_dir) || (oi->fontmap)) {
    
    for(i = 0; i < 35; i++) {
      if((oi->fnused)[i]) {
        if(is_first) {
	  begin_tag(oi, 38);
	  kw_out(oi, 1);
	  kw_out(oi, 39);
	  kw_out(oi, 3);
	  kw_out(oi, 30);
	  kw_out(oi, 0);
	  is_first = 0;
        }
	if(oi->fontmap) {		
	  pofm = dkfont_get_one_font(oi->fontmap, i);
	  if(pofm) {			
	    dkfont_one_font_reset(pofm);
	    while((pfr = dkfont_one_font_get(pofm)) != NULL) {
	      
	      if(dkfont_rep_check_driver(pfr, kw[5])) {
	        
	        fontfamilyname = dkfont_rep_get_family(pfr);
		fontlocation = dkfont_rep_get_location(pfr);
		fontfilename = dkfont_rep_get_source_name(pfr);
		fontid = dkfont_rep_get_name(pfr);
		fontformat = dkfont_rep_get_font_type(pfr);
		if(fontfamilyname) {	
		if(fontlocation) {	
		if(fontfilename) {	
		if(fontid)  {		
		if(fontformat) {	
	          kw_out(oi, 108);
	          kw_out(oi, 1);
	          kw_out(oi, 41);
	          kw_out(oi, 0);
	          kw_out(oi, 46); kw_out(oi, 24); kw_out(oi, 1);
	          kw_out(oi, 107);
	          dkstream_puts(oi->s, fontfamilyname);
	          kw_out(oi, 107);
	          kw_out(oi, 43);
	          kw_out(oi, 0);
	          ft = dkfont_get_features(i);
	          kw_out(oi, 47); kw_out(oi, 24); kw_out(oi, 1);
	          kw_out(oi, ((ft & DK_FONT_FEATURE_IT) ? 60 : 59));
	          kw_out(oi, 43);
	          kw_out(oi, 0);
	          kw_out(oi, 48); kw_out(oi, 24); kw_out(oi, 1);
	          kw_out(oi, ((ft & DK_FONT_FEATURE_BD) ? 61 : 59));
	          kw_out(oi, 43);
	          kw_out(oi, 0);
	          kw_out(oi, 109);
	          kw_out(oi, 74);
	          kw_out(oi, 75);
	          kw_out(oi, 20);
	          dkstream_puts(oi->s, fontlocation);
	          kw_out(oi, 4);
	          dkstream_puts(oi->s, fontfilename);
	          kw_out(oi, 45);
	          dkstream_puts(oi->s, fontid);
	          kw_out(oi, 20);
	          kw_out(oi, 76);
	          kw_out(oi, 1);
	          kw_out(oi, 110);
	          kw_out(oi, 43);
	          kw_out(oi, 0);
	          kw_out(oi, 42);
	          kw_out(oi, 0);
		} else {		
		}
		} else {		
		}
		} else {		
		}
		} else {		
		}
		} else {		
		}
	      } else {			
	      }
	    }
	  } else {			
	  }
	} else {
	  kw_out(oi, 108);
	  kw_out(oi, 1);
	  kw_out(oi, 41);
	  kw_out(oi, 0);
	  kw_out(oi, 46); kw_out(oi, 24); kw_out(oi, 1);
	  kw_out(oi, 107);
	  dkstream_puts(oi->s, urw_svg_font_families[i]);
	  kw_out(oi, 107);
	  kw_out(oi, 43);
	  kw_out(oi, 0);
	  ft = dkfont_get_features(i);
	  kw_out(oi, 47); kw_out(oi, 24); kw_out(oi, 1);
	  k