/*
Copyright (c) 2009-2010, 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
  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.
*/


/* ********************************************************************* */
/* *                                                                   * */
/* * Java output module.                                               * */
/* *                                                                   * */
/* ********************************************************************* */

#line 40 "dkfigjav.ctr"


/**	@file	dkfigjav.c	Java output driver module. */

/** Inside the dkfigjav module.
*/
#define DKFIGJAV_C	1

#include "fig2vect.h"
#include "dkfig.h"
#include "dktools-version.h"



#line 53 "dkfigjav.ctr"



/** Abbreviation.
*/
#define OI dkfig_java_output_instruction


/**	Very small value used in comparisons.
*/
static double epsilon = 0.000001;


/** Names of packages to import.
*/
static char *packages_to_import[] = {
"java.awt.Font",
"java.awt.FontMetrics",
"java.awt.Color",
"java.awt.Graphics",
"java.awt.Graphics2D",
"java.awt.BasicStroke",
"java.awt.geom.GeneralPath",
"java.awt.geom.Rectangle2D",
"java.awt.geom.RoundRectangle2D",
"java.awt.geom.Ellipse2D",
"java.awt.geom.Arc2D",
"java.awt.print.Printable",
"java.awt.print.PageFormat",
"java.awt.Image",
"java.awt.image.ImageObserver",
"java.awt.image.BufferedImage",
"java.net.URL",
"java.io.InputStream",
"java.io.FileInputStream",
"javax.imageio.ImageIO",
NULL
};


/** Keywords for output.
*/
static char *kw[] = {
/*   0 */	"\n",
/*   1 */	" ",
/*   2 */	"{",
/*   3 */	"}",
/*   4 */	".",
/*   5 */	",",
/*   6 */	"public class",
/*   7 */	"implements Printable",
/*   8 */	"FigPrintable",
/*   9 */	"import",
/*  10 */	";",
/*  11 */	"// Created by fig2vect.",
/*  12 */	"// See http://dktools.sourceforge.net/fig2vect.html",
/*  13 */	"/** Printable created from Fig drawing. */",
/*  14 */	"java",
/*  15 */	"  /** Image width. */",
/*  16 */	"  public static final double w = ",
/*  17 */	"  /** Image height. */",
/*  18 */	"  public static final double h = ",
/*  19 */	"  /** Color ",
/*  20 */	". */",
/*  21 */	"  private Color c",
/*  22 */	" = null;",
/*  23 */	"  /** Font ",
/*  24 */	"  private Font f",
/*  25 */	"  /** Stroke ",
/*  26 */	"  private BasicStroke l",
/*  27 */	"  /** Image ",
/*  28 */	"  private Image i",
/*  29 */	"        c",
/*  30 */	" = new Color(",
/*  31 */	");",
/*  32 */	".0",
/*  33 */	"      try {",
/*  34 */	"      } catch(Exception e) { back = false; e.printStackTrace(); }",
/*  35 */	"        f",
/*  36 */	" = findFont(",
/*  37 */	"  /** Font file names. */",
/*  38 */	"  public static final String[][] n = {",
/*  39 */	"  };",
/*  40 */	"    {",
/*  41 */	"    }",
/*  42 */	"//",
/*  43 */	"  /** Logical names for fonts. */",
/*  44 */	"  public static final String[][] l = {",
/*  45 */	"      ",
/*  46 */	"\"",
/*  47 */	".pfb",
/*  48 */	"n",
/*  49 */	"l",
/*  50 */	"[",
/*  51 */	"]",
/*  52 */	"Font.SERIF",
/*  53 */	"Font.SANS_SERIF",
/*  54 */	"Font.MONOSPACED",
/*  55 */	"Font.PLAIN",
/*  56 */	"Font.BOLD",
/*  57 */	"Font.ITALIC",
/*  58 */	"(Font.BOLD | Font.ITALIC)",
/*  59 */	"        l",
/*  60 */	" = new BasicStroke(",
/*  61 */	"f",
/*  62 */	"BasicStroke.CAP_BUTT",
/*  63 */	"BasicStroke.CAP_ROUND",
/*  64 */	"BasicStroke.CAP_SQUARE",
/*  65 */	"BasicStroke.JOIN_ROUND",
/*  66 */	"BasicStroke.JOIN_BEVEL",
/*  67 */	"BasicStroke.JOIN_MITER",
/*  68 */	"\n                 new float[]{",
/*  69 */	"LANG",
/*  70 */	"UTF-8",
/*  71 */	"/ui/lang",
/*  72 */	"  /** Search strings. */",
/*  73 */	"  public static final String[] s1 = {",
/*  74 */	"  /** Print Strings. */",
/*  75 */	"  private String[] s2 = {",
/*  76 */	"    ",
/*  77 */	"/* ",
/*  78 */	" */ ",
/*  79 */	"\"",
/*  80 */	"        i",
/*  81 */	" = findImage(\"",
/*  82 */	"\\\"",
/*  83 */	"\\\\",
/*  84 */	"      FontMetrics m",
/*  85 */	" = g.getFontMetrics(f",
/*  86 */	"      {",
/*  87 */	"      }",
/*  88 */	"        Graphics2D g2 = (Graphics2D)(g.create());",
/*  89 */	"        ",
/*  90 */	"g",
/*  91 */	"2",
/*  92 */	".setFont(f",
/*  93 */	".setColor(c",
/*  94 */	"placeText(g",
/*  95 */	"s2",
/*  96 */	"m",
/*  97 */	"ALIGN_H_LEFT",
/*  98 */	"ALIGN_H_CENTERED",
/*  99 */	"ALIGN_H_RIGHT",
/* 100 */	"g2.rotate(",
/* 101 */	"g2.translate(",
/* 102 */	"package ",
/* 103 */	"g.fill(p);",
/* 104 */	"g2.fill(p);",
/* 105 */	"g.draw(p);",
/* 106 */	"g2.draw(p);",
/* 107 */	"Rectangle2D.Double p = new Rectangle2D.Double(",
/* 108 */	"RoundRectangle2D.Double p = new RoundRectangle2D.Double(",
/* 109 */	"GeneralPath p = new GeneralPath();",
/* 110 */	"p.moveTo(",
/* 111 */	"p.lineTo(",
/* 112 */	"p.closePath();",
/* 113 */	".setStroke(l",
/* 114 */	"Ellipse2D.Double p = new Ellipse2D.Double(",
/* 115 */	"GeneralPath ahf = new GeneralPath();",
/* 116 */       "GeneralPath ahb = new GeneralPath();",
/* 117 */	"ahf",
/* 118 */	"ahb",
/* 119 */	".moveTo(",
/* 120 */	".lineTo(",
/* 121 */	".closePath();",
/* 122 */	"g.setColor(Color.WHITE);",
/* 123 */	".fill(",
/* 124 */	".draw(",
/* 125 */	"p.curveTo(",
/* 126 */	"Arc2D.Double p = new Arc2D.Double(",
/* 127 */	"Arc2D.OPEN",
/* 128 */	"Arc2D.PIE",
/* 129 */	"          ",
/* 130 */	"ALIGN_V_CENTERED",
/* 131 */	"ALIGN_V_TOP",
/* 132 */	"ALIGN_V_BOTTOM",
/* 133 */	"placeImage(g, ",
/* 134 */	"i",
/* 135 */
"// RESOURCES NEEDED BY THIS MODULE (should be packaged into the jar archive):",
/* 136 */
"// --------------------------------------------------------------------------",
/* 137 */	"// Font ",
/* 138 */	":",
/* 139 */	" = ",
/* 140 */	", ",
/* 141 */	"// Image ",
/* 142 */	"/",
/* 143 */	"http://",
/* 144 */	"0",
/* 145 */	"private boolean[] se = {",
/* 146 */	"/** Flags: String enabled. */",
/* 147 */	"true",
/* 148 */	"        if(se[",
/* 149 */	"]) { ",
/* 150 */	"/** String layers. */",
/* 151 */	"private int[] sl = {",
/* 152 */	"private LayerInfo[] la = {",
/* 153 */	"null",
/* 154 */	"/** Layer bounding box information. */",
/* 155 */	"new LayerInfo(",
/* 156 */	")",
/* 157 */	"// <editor-fold defaultstate=\"collapsed\" desc=\"Package import\">",
/* 158 */	"// </editor-fold>",
/* 159 */	"// <editor-fold defaultstate=\"collapsed\" desc=\"Colors, fonts, strokes and image variables\">",
/* 160 */	"// <editor-fold defaultstate=\"collapsed\" desc=\"Font names and font file names\">",
/* 161 */	"// <editor-fold defaultstate=\"collapsed\" desc=\"Texts\">",
/* 162 */	"// <editor-fold defaultstate=\"collapsed\" desc=\"Graphics size and page align\">",
/* 163 */	"  /** Horizontal alignment of the graphics on the page. */",
/* 164 */	"  private int alignH = ",
/* 165 */	"  /** Vertical alignment of the graphics on the page. */",
/* 166 */	"  private int alignV = ",
/* 167 */	"// <editor-fold defaultstate=\"collapsed\" desc=\"Used ranges in layers\">",
/* 168 */	"import dirk_krause.tools.DkTool;",
/* 169 */	"import dirk_krause.wstools.DkTool;",
/* 170 */	"public ",
/* 171 */	"(DkTool d)",
/* 172 */	" = dkt.findBufferedImage(this, \"",
/* 173 */	" = dkt.findFont(this, ",
/* 174 */	"utf8",
};



/**	Documentation header for a class definition.
*/
static char *class_docu_1[] = {
"/**\n",
" * Drawing class.\n",
" * This file was generated automatically from a Fig file\n",
" * (created by XFig, jFig, WinFig or others) using the\n",
" * fig2vect " VERSNUMB " program. See\n",
" *   http://dktools.sourceforge.net/fig2vect.html\n",
" * for more information about fig2vect.\n",
" *\n",
" * Be carefully when applying changes to this file,\n",
" * your changes may be lost if fig2vect is run again.\n",
" *\n",
NULL
};


/**	Comment for additional font/image directories.
*/
static char *class_docu_2[] = {
" * If you want to specify additional locations for font\n",
" * and image search, use the addFontBase() and\n",
" * addImageBase() functions. You can specify \"http://\"\n",
" * and \"file://\" locations. When using this class in a\n",
" * webstart application use \"http://\" URLs only, not\n",
" * \"file://\", webstart applications are not allowed to access\n",
" * local files.\n",
" *\n",
" * If you use the same code for both an application and a\n",
" * webstart application use setRunAsJnlp() to inform the object\n",
" * that it is running in a webstart application. If the JNLP\n",
" * flag is turned on the object skips \"file://\" locations\n",
" * in font and image search.\n",
" *\n",
" * If you use one of the addFontBase(), addImageBase() or\n",
" * setRunAsJnlp() functions call these functions before you\n",
" * use initialize() and pass the object to a print service.\n",
NULL
};


/**	And a newline.
*/
static char *class_docu_3[] = {
" */\n",
NULL
};

/** Section containing the variables of the Java class.
*/
static char *member_variables_1[] = {
"\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"LayerInfo class\">\n",
"\n",
"  /** Information about used ranges in layers. */\n",
"  class LayerInfo {\n",
"    /** Layer number. */\n",
"    protected int ln;\n",
"  \n",
"    /** Minimum x value. */\n",
"    protected double xmin;\n",
"  \n",
"    /** Maximum x value. */\n",
"    protected double xmax;\n",
"  \n",
"    /** Minimum y value. */\n",
"    protected double ymin;\n",
"  \n",
"    /** Maximum y value. */\n",
"    protected double ymax;\n",
"  \n",
"    /**\n",
"     * Constructor.\n",
"     * @param l	Layer number.\n",
"     * @param x0	Minimum x value.\n",
"     * @param x1	Maximum x value.\n",
"     * @param y0	Minimum y value.\n",
"     * @param y1	Maximum y value.\n",
"     */\n",
"    public LayerInfo(\n",
"      int l,\n",
"      double x0, double x1, double y0, double y1\n",
"    )\n",
"    {\n",
"      ln = l; xmin = x0; xmax = x1; ymin = y0; ymax = y1;\n",
"    }\n",
"\n",
"    /**\n",
"     * Get used rectangle on layer.\n",
"     * @return	Rectangle for used range on layer.\n",
"     */\n",
"    public Rectangle2D.Double getRectangle()\n",
"    {\n",
"      Rectangle2D.Double back;\n",
"      back = new Rectangle2D.Double(\n",
"        xmin, ymin, (xmax - xmin), (ymax - ymin)\n",
"      );\n",
"      return back;\n",
"    }\n",
"  \n",
"  }\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Error code definitions\">\n",
"\n",
"  /** Error code: Page too small. */\n",
"  public static final int ERROR_PAGE_TOO_SMALL = 1;\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Alignment definitions\">\n",
"\n",
"  /** Horizontal align: left. */\n",
"  public static final int ALIGN_H_LEFT = 0;\n",
"\n",
"  /** Horizontal align: centered. */\n",
"  public static final int ALIGN_H_CENTERED = 1;\n",
"\n",
"  /** Horizontal align: right. */\n",
"  public static final int ALIGN_H_RIGHT = 2;\n",
"\n",
"  /** Vertical align: top. */\n",
"  public static final int ALIGN_V_TOP = 0;\n",
"\n",
"  /** Vertical align: centered. */\n",
"  public static final int ALIGN_V_CENTERED = 1;\n",
"\n",
"  /** Vertical align: bottom. */\n",
"  public static final int ALIGN_V_BOTTOM = 2;\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Internal variables\">\n",
"\n",
"  /** Flag: The structure is completely initialized. */\n",
"  private boolean is_initialized = false;\n",
"  \n",
"  /** Flag: Initialization was already attempted. */\n",
"  private boolean initialization_attempted = false;\n",
"\n",
"  /** Border at the left page side. */\n",
"  private double leftBorder = 0.0;\n",
"\n",
"  /** Border at the top side. */\n",
"  private double topBorder = 0.0;\n",
"\n",
"  /** Last error occured. */\n",
"  private int errorCode = 0;\n",
"\n",
NULL
};


/**	Font and images base directory.
*/
static char *member_variables_2a[] = {
"  /** Resource directories for fonts. */\n",
"  private String[] fontBases = null;\n",
"\n",
"  /** Resource directories for images. */\n",
"  private String[] imageBases = null;\n",
"\n",
"  /** Flag: Running as applet or webstart application (no file://). */\n",
"  private boolean isJnlp = false;\n",
"\n",
NULL
};



/**	The DkTool object.
*/
static char *member_variables_2b[] = {
"  /** General tool. */\n",
"  private DkTool dkt = null;\n",
"\n",
NULL
};



/**	Finish editor fold.
*/
static char *member_variables_3[] = {
"// </editor-fold>\n",
"\n\n\n",
NULL
};

/** Section containing the member functions of the Java class.
*/
static char *member_functions_1[] = {
"// <editor-fold defaultstate=\"collapsed\" desc=\"Search for resources\">\n",
"\n",
"  /**\n",
"   * Attempt to find a font\n",
"   * @param ffn Array of font file name suggestions to search for.\n",
"   * @param fn  Array of font family names to use.\n",
"   * @param fb  Fallback font, ie Font.SERIF.\n",
"   * @param fe  Font features (bold, italic).\n",
"   * @param fs  Font size.\n",
"   * @return    Font reference or null.\n",
"   */\n",
"  private Font findFont(String[] ffn, String[] fn, String fb, int fe, float fs)\n",
"  {\n",
"    Font back = null;\n",
"    InputStream is = null;\n",
"    Font xf = null;\n",
"    int i;\n",
"    String[] fbas = null;\n",
"    boolean jnlp = false;\n",
"    synchronized(this) { fbas = fontBases; jnlp = isJnlp; }\n",
"    if(ffn != null) {\n",
"      for(i = 0; ((i < ffn.length) && (back == null)); i++) {\n",
"        if(ffn[i] != null) {\n",
"          is = null;\n",
"          xf = null;\n",
"          int ft = Font.TYPE1_FONT;\n",
"          if((ffn[i].endsWith(\".ttf\")) || (ffn[i].endsWith(\".TTF\"))) {\n",
"            ft = Font.TRUETYPE_FONT;\n",
"          }\n",
"          if(ffn[i].startsWith(\"http://\")) {\n",
"            try {\n",
"              is = (new URL(ffn[i])).openStream();\n",
"              xf = Font.createFont(ft, is);\n",
"            } catch(Exception e) { xf = null; } finally {\n",
"              try { is.close(); } catch(Exception e) {}\n",
"            }\n",
"          } else {\n",
"            if(ffn[i].startsWith(\"file://\")) {\n",
"              if(!jnlp) {\n",
"                try {\n",
"                  is = (new URL(ffn[i])).openStream();\n",
"                  xf = Font.createFont(ft, is);\n",
"                } catch(Exception e) { xf = null; } finally {\n",
"                  try { is.close(); } catch(Exception e) {}\n",
"                }\n",
"              }\n",
"            } else {\n",
"              try {\n",
"                is = getClass().getResourceAsStream( \"/\" + ffn[i]);\n",
"                xf = Font.createFont(ft, is);\n",
"              } catch(Exception e) { xf = null; } finally {\n",
"                try { is.close(); } catch(Exception e) {}\n",
"              }\n",
"              if(xf == null) {\n",
"                if(fbas != null) {\n",
"                  for(int j = 0; ((j < fbas.length) && (xf == null)); j++) {\n",
"                    String urlname;\n",
"                    if(ffn[i].startsWith(\"/\")) {\n",
"                      urlname = fbas[j] + ffn[i];\n",
"                    } else {\n",
"                      urlname = fbas[j] + \"/\" + ffn[i];\n",
"                    }\n",
"                    is = null;\n",
"                    if(urlname.startsWith(\"http://\")) {\n",
"                      try {\n",
"                        is = (new URL(urlname)).openStream();\n",
"                        xf = Font.createFont(ft, is);\n",
"                      } catch(Exception e) { xf = null; } finally {\n",
"                        try { is.close(); } catch(Exception e) {}\n",
"                      }\n",
"                    } else {\n",
"                      if(urlname.startsWith(\"file://\")) {\n",
"                        if(!jnlp) {\n",
"                          try {\n",
"                            is = (new URL(urlname)).openStream();\n",
"                            xf = Font.createFont(ft, is);\n",
"                          } catch(Exception e) { xf = null; } finally {\n",
"                            try { is.close(); } catch(Exception e) {}\n",
"                          }\n",
"                        }\n",
"                      } else {\n",
"                        try {\n",
"                          is = getClass().getResourceAsStream(urlname);\n",
"                          xf = Font.createFont(ft, is);\n",
"                        } catch(Exception e) { xf = null; } finally {\n",
"                          try { is.close(); } catch(Exception e) {}\n",
"                        }\n",
"                      }\n",
"                    }\n",
"                  }\n",
"                }\n",
"              }\n",
"              if(xf == null) {\n",
"                if(!jnlp) {\n",
"                  FileInputStream fis = null;\n",
"                  try {\n",
"                    fis = new FileInputStream(ffn[i]);\n",
"                    xf = Font.createFont(ft, fis);\n",
"                  }\n",
"                  catch(Exception e) {\n",
"                    xf = null;\n",
"                  }\n",
"                  finally {\n",
"                    try { fis.close(); } catch(Exception e) {}\n",
"                  }\n",
"                }\n",
"              }\n",
"            }\n",
"          }\n",
"          if(xf != null) {\n",
"            try {\n",
"              back = xf.deriveFont(fs);\n",
"            } catch(Exception e) { back = null; }\n",
"          }\n",
"        }\n",
"      }\n",
"    }\n",
"    if(fn != null) {\n",
"      for(i = 0; ((i < fn.length) && (back == null)); i++) {\n",
"        if(fn[i] != null) {\n",
"          try {\n",
"            xf = new Font(fn[i], fe, (int)fs);\n",
"            back = xf.deriveFont(fs);\n",
"          } catch(Exception e) { back = null; }\n",
"        }\n",
"      }\n",
"    }\n",
"    if(back == null) {\n",
"      if(fb != null) {\n",
"        try {\n",
"          xf = new Font(fb, fe, (int)fs);\n",
"          back = xf.deriveFont(fs);\n",
"        } catch(Exception e) { back = null; }\n",
"      }\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n",
"  /**\n",
"   * Attempt to find a font\n",
"   * @param ffn Array of font file name suggestions to search for.\n",
"   * @param fn  Array of font family names to use.\n",
"   * @param fb  Fallback font, ie Font.SERIF.\n",
"   * @param fe  Font features (bold, italic).\n",
"   * @param fs  Font size.\n",
"   * @return    Font reference or null.\n",
"   */\n",
"  private Font findFont(String[] ffn, String[] fn, String fb, int fe, double fs)\n",
"  {\n",
"    Font back = findFont(ffn, fn, fb, fe, (float)fs);\n",
"    return back;\n",
"  }\n",
"\n",
"  /**	Find image.\n",
"   *	@param	n	Image file name or URL.\n",
"   *	@return	The image found or null.\n",
"   */\n",
"  BufferedImage findImage(String n) {\n",
"    BufferedImage back = null;\n",
"    InputStream is = null;\n",
"    String[] ib = null;\n",
"    boolean jnlp = false;\n",
"    synchronized(this) { jnlp = isJnlp; }\n",
"    if(n.startsWith(\"http://\")) {\n",
"      try {\n",
"        is = (new URL(n)).openStream();\n",
"        back = ImageIO.read(is);\n",
"      } catch(Exception e) { back = null; } finally {\n",
"        try { is.close(); } catch(Exception e) {}\n",
"      }\n",
"    } else {\n",
"      if(n.startsWith(\"file://\")) {\n",
"        if(!jnlp) {\n",
"          try {\n",
"            is = (new URL(n)).openStream();\n",
"            back = ImageIO.read(is);\n",
"          } catch(Exception e) { back = null; } finally {\n",
"            try { is.close(); } catch(Exception e) {}\n",
"          }\n",
"        }\n",
"      } else {\n",
"        try {\n",
"          is = getClass().getResourceAsStream(\"/\" + n);\n",
"          back = ImageIO.read(is);\n",
"        } catch(Exception e) { back = null; } finally {\n",
"          try { is.close(); } catch(Exception e) {}\n",
"        }\n",
"        if(back == null) {\n",
"          String urlname;\n",
"          synchronized(this) { ib = imageBases; }\n",
"          if(ib != null) {\n",
"            for(int i = 0; ((i < ib.length) && (back == null)); i++) {\n",
"              is = null;\n",
"              if(n.startsWith(\"/\")) {\n",
"                urlname = ib[i] + n;\n",
"              } else {\n",
"                urlname = ib[i] + \"/\" + n;\n",
"              }\n",
"              if(urlname.startsWith(\"http://\")) {\n",
"                try {\n",
"                  is = (new URL(urlname)).openStream();\n",
"                  back = ImageIO.read(is);\n",
"                } catch(Exception e) {\n",
"                  back = null;\n",
"                } finally {\n",
"                  try { is.close(); } catch(Exception e) {}\n",
"                }\n",
"              } else {\n",
"                if(urlname.startsWith(\"file://\")) {\n",
"                  if(!jnlp) {\n",
"                    try {\n",
"                      is = (new URL(urlname)).openStream();\n",
"                      back = ImageIO.read(is);\n",
"                    } catch(Exception e) { back = null; } finally {\n",
"                      try { is.close(); } catch(Exception e) {}\n",
"                    }\n",
"                  }\n",
"                } else {\n",
"                  try {\n",
"                    is = getClass().getResourceAsStream(urlname);\n",
"                    back = ImageIO.read(is);\n",
"                  } catch(Exception e) {\n",
"                    back = null;\n",
"                  } finally {\n",
"                    try { is.close(); } catch(Exception e) {}\n",
"                  }\n",
"                }\n",
"              }\n",
"            }\n",
"          }\n",
"          if(back == null) {\n",
"            if(!jnlp) {\n",
"              FileInputStream fis = null;\n",
"              try {\n",
"                fis = new FileInputStream(n);\n",
"                back = ImageIO.read(fis);\n",
"              }\n",
"              catch(Exception e) {\n",
"                back = null;\n",
"              }\n",
"              finally {\n",
"                try { fis.close(); } catch(Exception e) {}\n",
"              }\n",
"            }\n",
"          }\n",
"        }\n",
"      }\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n",
" /**\n",
"  * Add font base directory.\n",
"  * @param s New font base.\n",
"  */\n",
" public void addFontBase(String s) {\n",
"   String[] fb = null;\n",
"   String[] nfb = null;\n",
"   int i;\n",
"   if(s != null) {",
"     synchronized(this) { fb = fontBases; }\n",
"     if(fb != null) {\n",
"       nfb = new String[1 + fb.length];\n",
"       for(i = 0; i < fb.length; i++) {\n",
"         nfb[i] = fb[i];\n",
"       }\n",
"       nfb[i] = new String(s);\n",
"     } else {\n",
"       nfb = new String[1];\n",
"       nfb[0] = new String(s);\n",
"     }\n",
"     synchronized(this) { fontBases = nfb; }\n",
"   }",
" }\n",
"\n",
" /**\n",
"  * Add image base directory.\n",
"  * @param s	New image base.\n",
"  */\n",
" public void addImageBase(String s) {\n",
"   String[] ib = null;\n",
"   String[] nib = null;\n",
"   int i;\n",
"   if(s != null) {",
"     synchronized(this) { ib = imageBases; }\n",
"     if(ib != null) {\n",
"       nib = new String[1 + ib.length];\n",
"       for(i = 0; i < ib.length; i++) {\n",
"         nib[i] = ib[i];\n",
"       }\n",
"       nib[i] = new String(s);\n",
"     } else {\n",
"       nib = new String[1];\n",
"       nib[0] = new String(s);\n",
"     }\n",
"     synchronized(this) { imageBases = nib; }\n",
"   }",
" }\n",
"\n",
"// </editor-fold>\n",
NULL
};



/**	Member functions for text and graphics placement.
*/
static char *member_functions_2[] = {
"\n",
"\n",
"\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Place text\">\n",
"\n",
"  /**	Place text.\n",
"   *	@param	g	Graphics context.\n",
"   *	@param	t	Text to place.\n",
"   *	@param	m	Font metrics of current font.\n",
"   *	@param	x	X position.\n",
"   *	@param	y	y position.\n",
"   *	@param	align	Text alignment (ALIGN_H_xxx).\n",
"   */\n",
"  private void placeText(\n",
"    Graphics2D g, String t, FontMetrics m,\n",
"    double x, double y, int align\n",
"  )\n",
"  {\n",
"    Rectangle2D r = m.getStringBounds(t, g);\n",
"    double wi = r.getWidth();\n",
"    switch(align) {\n",
"      case ALIGN_H_CENTERED: {\n",
"        wi = 0.5 * wi;\n",
"      } break;\n",
"      case ALIGN_H_LEFT: {\n",
"        wi = 0.0;\n",
"      } break;\n",
"    }\n",
"    g.drawString(t, (float)(x - wi), (float)y);\n",
"  }\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Place image\">\n\n",
"\n",
"  /**   Place image into range.\n",
"   *    @param  g   Graphics context.\n",
"   *    @param  x0  Left x.\n",
"   *    @param  y0  Top y.\n",
"   *    @param  x1  Right x.\n",
"   *    @param  y1  Bottom y.\n",
"   *    @param  i   Image to draw.\n",
"   *    @param  ah  Horizontal alignment.\n",
"   *    @param  av  Vertical aligment.\n",
"   *    @return Flag to indicate success.\n",
"   */\n",
"  private boolean placeImage(\n",
"    Graphics2D g,\n",
"    double x0, double y0, double x1, double y1,\n",
"    Image i,\n",
"    int ah, int av\n",
"  )\n",
"  {\n",
"    boolean back = true;\n",
"    double  xs   = x0;\n",
"    double  ys   = y0;\n",
"    double  sf;\n",
"    try {\n",
"      double iw = (double)i.getWidth(null);\n",
"      double ih = (double)i.getHeight(null);\n",
"      double sfx = (x1 - x0) / iw;\n",
"      double sfy = (y1 - y0) / ih;\n",
"      if(sfx < sfy) {\n",
"        sf = sfx;\n",
"        switch(av) {\n",
"          case ALIGN_V_CENTERED: {\n",
"            ys = ys + 0.5 * (y1 - y0 - sf * ih);\n",
"          } break;\n",
"          case ALIGN_V_BOTTOM: {\n",
"            ys = y1 - sf * ih;\n",
"          } break;\n",
"        }\n",
"      } else {\n",
"        sf = sfy;\n",
"        switch(ah) {\n",
"          case ALIGN_H_CENTERED: {\n",
"            xs = xs + 0.5 * (x1 - x0 - sf * iw);\n",
"          } break;\n",
"          case ALIGN_H_RIGHT: {\n",
"            xs = x1 - sf * iw;\n",
"          } break;\n",
"        }\n",
"      }\n",
"      Graphics2D g2 = (Graphics2D)(g.create());\n",
"      g2.translate(xs, ys);\n",
"      g2.scale(sf, sf);\n",
"      g2.drawImage(i, 0, 0, null);\n",
"    } catch(Exception e) { back = false; }\n",
"    return back;\n",
"  }\n\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Page setup and printing\">\n",
"\n",
"  /**\n",
"   * Print graphics to a printer page.\n",
"   * @param g           Graphics context.\n",
"   * @param pageFormat  Page format structure.\n",
"   * @param pageIndex   Index of the page (must be 0).\n",
"   * @return            Indicator whether or not the pageIndex is ok.\n",
"   */\n",
"  @Override\n",
"  public int print(Graphics g, PageFormat pageFormat, int pageIndex) {\n",
"    int back = Printable.NO_SUCH_PAGE;\n",
"    double  xmin;\n",
"    double  xmax;\n",
"    double  ymin;\n",
"    double  ymax;\n",
"    if(pageIndex == 0) {\n",
"      if(initialize()) {\n",
"        Graphics2D g2 = (Graphics2D)g;\n",
"        Graphics2D g3 = (Graphics2D)(g2.create());\n",
"        xmin = pageFormat.getImageableX();\n",
"        xmax = xmin + pageFormat.getImageableWidth();\n",
"        ymin = pageFormat.getImageableY();\n",
"        ymax = ymin + pageFormat.getImageableHeight();\n",
"        if(leftBorder > xmin) { xmin = leftBorder; }\n",
"        if(topBorder > ymin) { ymin = topBorder; }\n",
"        if(((xmax - xmin) >= w) && ((ymax - ymin) >= h)) {\n",
"          double tx = xmin;\n",
"          double ty = ymin;\n",
"          if((alignH != ALIGN_H_LEFT) || (alignV != ALIGN_V_TOP)) {\n",
"            switch(alignH) {\n",
"              case ALIGN_H_CENTERED: {\n",
"                tx = xmin + (xmax - xmin - w) / 2.0;\n",
"              } break;\n",
"              case ALIGN_H_RIGHT: {\n",
"                tx = xmax - w;\n",
"              } break;\n",
"            }\n",
"            switch(alignV) {\n",
"              case ALIGN_V_CENTERED: {\n",
"                ty = ymin + (ymax - ymin - h) / 2.0;\n",
"              } break;\n",
"              case ALIGN_V_BOTTOM: {\n",
"                ty = ymax - h;\n",
"              } break;\n",
"            }\n",
"          }\n",
"          g3.translate(tx, ty);\n",
"          if(p(g3)) { back = Printable.PAGE_EXISTS; }\n",
"        } else {\n",
"          double tx = xmin;\n",
"          double ty = ymin;\n",
"          double sc = 1.0;\n",
"          double nw = w;\n",
"          double nh = h;\n",
"          try {\n",
"            double osx = (xmax - xmin) / w;\n",
"            double osy = (ymax - ymin) / h;\n",
"            if((osx > 0.0) && (osy > 0.0)) {\n",
"              if(osy < osx) {\n",
"                sc = osy;\n",
"                nw = sc * w;\n",
"                switch(alignH) {\n",
"                  case ALIGN_H_CENTERED: {\n",
"                    tx = tx + (xmax - xmin - nw) / 2.0;\n",
"                  } break;\n",
"                  case ALIGN_H_RIGHT: {\n",
"                     tx = xmax - nw;\n",
"                  } break;\n",
"                }\n",
"              } else {\n",
"                sc = osx;\n",
"                nh = sc * h;\n",
"                switch(alignV) {\n",
"                  case ALIGN_V_CENTERED: {\n",
"                    ty = ty + (ymax - ymin - nh) / 2.0;\n",
"                  } break;\n",
"                  case ALIGN_V_BOTTOM: {\n",
"                    ty = ymax - nh;\n",
"                  } break;\n",
"                }\n",
"              }\n",
"              g3.translate(tx, ty);\n",
"              g3.scale(sc, sc);\n",
"              if(p(g3)) { back = Printable.PAGE_EXISTS; }\n",
"            }\n",
"          } catch(Exception e) {\n",
"            back = Printable.NO_SUCH_PAGE; e.printStackTrace();\n",
"          }\n",
"        }\n",
"      }\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Text modification for form handling\">\n",
"\n",
"  /**\n",
"   * Enable or disable one text printout.\n",
"   * @param s	Original text of the string.\n",
"   * @param f	Flag whether or not to print the string.\n",
"   */\n",
"  public void setTextEnabled(String s, boolean f) {\n",
"    int i;\n",
"    for(i = 0; i < s1.length; i++) {\n",
"      if(s.equals(s1[i])) {\n",
"        se[i] = f;\n",
"      }\n",
"    }\n",
"  }\n",
"\n",
"  /**\n",
"   * Enable or disable all texts in a specific layer.\n",
"   * @param l	Layer number.\n",
"   * @param f	Flag whether to enable or disable the texts.\n",
"   */\n",
"  public void setTextInLayerEnabled(int l, boolean f) {\n",
"    int i;\n",
"    for(i = 0; i < s1.length; i++) {\n",
"      if(sl[i] == l) {\n",
"        se[i] = f;\n",
"      }\n",
"    }\n",
"  }\n",
"\n",
"  /**\n",
"   * Enable all texts.\n",
"   */\n",
"  public void enableAllTexts() {\n",
"    int i;\n",
"    for(i = 0; i < se.length; i++) {\n",
"      se[i] = true;\n",
"    }\n",
"  }\n",
"\n",
"  /**\n",
"   * Replace one of the label strings.\n",
"   * @param k   Original label text from Fig file.\n",
"   * @param v   New label text.\n",
"   * @return    Flag whether or not the text was found.\n",
"   */\n",
"  public boolean replaceText(String k, String v) {\n",
"    boolean back = false;\n",
"    int i;\n",
"    for(i = 0; i < s1.length; i++) {\n",
"      if(k.equals(s1[i])) {\n",
"        s2[i] = v; back = true;\n",
"      }\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Border and alignment settings\">\n",
"\n",
"  /**\n",
"   * Set top border.\n",
"   * @param d   New minimum top border.\n",
"   */\n",
"  public void setLeftBorder(double d) {\n",
"    leftBorder = d;\n",
"  }\n",
"\n",
"  /**	Set left border.\n",
"   *	@param d   New minimum left border.\n",
"   */\n",
"  public void setTopBorder(double d) {\n",
"    topBorder = d;\n",
"  }\n",
"\n",
"  /**\n",
"   * Set horizontal alignment.\n",
"   * @param a	New horizontal alignment.\n",
"   */\n",
"  public void setHorizontalAlignment(int a) {\n",
"    alignH = a;\n",
"    if((a != ALIGN_H_LEFT) && (a != ALIGN_H_RIGHT)) {\n",
"      alignH = ALIGN_H_CENTERED;\n",
"    }\n",
"  }\n",
"\n",
"  /**\n",
"   * Set vertical alignment.\n",
"   * @param a	New vertical alignment.\n",
"   */\n",
"  public void setVerticalAlignment(int a) {\n",
"    alignV = a;\n",
"    if((a != ALIGN_V_TOP) && (a != ALIGN_V_BOTTOM)) {\n",
"      alignV = ALIGN_V_CENTERED;\n",
"    }\n",
"  }\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Error handling\">\n",
"\n",
"  /**	Retrieve error code for last error.\n",
"   *	@return	Error code for last error.\n",
"   */\n",
"  public int getLastError() {\n",
"    return errorCode;\n",
"  }\n",
"\n",
"  /**	Reset error code.  */\n",
"  public void resetError() {\n",
"    errorCode = 0;\n",
"  }\n",
"\n",
"// </editor-fold>\n",
"\n\n\n",
"// <editor-fold defaultstate=\"collapsed\" desc=\"Functions for over-drawing\">\n",
"\n",
"  /**\n",
"   * Retrieve used range for a layer.\n",
"   * @param l	Layer number.\n",
"   * @return Rectangle on success (layer not found),\n",
"   * null on error (layer not found).\n",
"   */\n",
"  public Rectangle2D.Double getLayerRectangle(int l) {\n",
"    Rectangle2D.Double back = null;\n",
"    int i;\n",
"    for(i = 0; ((i < la.length) && (back == null)); i++) {\n",
"      if(la[i] != null) {\n",
"        if(la[i].ln == l) {\n",
"	  back = la[i].getRectangle();\n",
"	}\n",
"      }\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n",
"  /**\n",
"   * Create graphics context with transformations applied.\n",
"   * @param g           Original graphics context.\n",
"   * @param pageFormat  Page format structure.\n",
"   * @return            New graphics context with translations or null.\n",
"   */\n",
"  public Graphics2D getTransformedGraphics(\n",
"    Graphics g, PageFormat pageFormat)\n",
"  {\n",
"    Graphics2D back = null;\n",
"    double  xmin;\n",
"    double  xmax;\n",
"    double  ymin;\n",
"    double  ymax;\n",
"    Graphics2D g2 = (Graphics2D)g;\n",
"    Graphics2D g3 = (Graphics2D)(g2.create());\n",
"    xmin = pageFormat.getImageableX();\n",
"    xmax = xmin + pageFormat.getImageableWidth();\n",
"    ymin = pageFormat.getImageableY();\n",
"    ymax = ymin + pageFormat.getImageableHeight();\n",
"    if(leftBorder > xmin) { xmin = leftBorder; }\n",
"    if(topBorder > ymin) { ymin = topBorder; }\n",
"    if(((xmax - xmin) >= w) && ((ymax - ymin) >= h)) {\n",
"      double tx = xmin;\n",
"      double ty = ymin;\n",
"      if((alignH != ALIGN_H_LEFT) || (alignV != ALIGN_V_TOP)) {\n",
"        switch(alignH) {\n",
"          case ALIGN_H_CENTERED: {\n",
"            tx = xmin + (xmax - xmin - w) / 2.0;\n",
"          } break;\n",
"          case ALIGN_H_RIGHT: {\n",
"            tx = xmax - w;\n",
"          } break;\n",
"        }\n",
"        switch(alignV) {\n",
"          case ALIGN_V_CENTERED: {\n",
"            ty = ymin + (ymax - ymin - h) / 2.0;\n",
"          } break;\n",
"          case ALIGN_V_BOTTOM: {\n",
"            ty = ymax - h;\n",
"          } break;\n",
"        }\n",
"      }\n",
"      g3.translate(tx, ty);\n",
"      back = g3;\n",
"    } else {\n",
"      double tx = xmin;\n",
"      double ty = ymin;\n",
"      double sc = 1.0;\n",
"      double nw = w;\n",
"      double nh = h;\n",
"      try {\n",
"        double osx = (xmax - xmin) / w;\n",
"        double osy = (ymax - ymin) / h;\n",
"        if((osx > 0.0) && (osy > 0.0)) {\n",
"          if(osy < osx) {\n",
"            sc = osy;\n",
"            nw = sc * w;\n",
"            switch(alignH) {\n",
"              case ALIGN_H_CENTERED: {\n",
"                tx = tx + (xmax - xmin - nw) / 2.0;\n",
"              } break;\n",
"              case ALIGN_H_RIGHT: {\n",
"                 tx = xmax - nw;\n",
"              } break;\n",
"            }\n",
"          } else {\n",
"            sc = osx;\n",
"            nh = sc * h;\n",
"            switch(alignV) {\n",
"              case ALIGN_V_CENTERED: {\n",
"                ty = ty + (ymax - ymin - nh) / 2.0;\n",
"              } break;\n",
"              case ALIGN_V_BOTTOM: {\n",
"                ty = ymax - nh;\n",
"              } break;\n",
"            }\n",
"          }\n",
"          g3.translate(tx, ty);\n",
"          g3.scale(sc, sc);\n",
"          back = g3;\n",
"        }\n",
"      } catch(Exception e) {\n",
"        back = null;\n",
"      }\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n",
NULL
};



/**	Set mode for web-start applications or applets.
*/
static char *member_functions_3[] = {
"  /**\n",
"   * Set webstart/applet mode. This mode is disabled by default.\n",
"   * In webstart/applet mode the findImage() and findFont() function\n",
"   * do not attempt to open file:// URLs.\n",
"   * @param b	Boolean flag to turn webstart/applet mode on or off.\n",
"   */\n",
"  public void setRunAsJnlp(boolean b) {\n",
"    synchronized(this) { isJnlp = b; }\n",
"  }\n",
"\n",
NULL
};



/**	Finish editor fold.
*/
static char *member_functions_4[] = {
"// </editor-fold>\n",
"\n\n\n",
NULL
};



/**	Start editor fold for DkTool object constructor.
*/
static char *dktool_constructor_p1[] = {
"// <editor-fold defaultstate=\"collapsed\" desc=\"Constructor\">\n",
"\n",
NULL
};



/**	Write construction code.
*/
static char *dktool_constructor_p2[] = {
"  {\n",
"    dkt = d;\n",
"  }\n",
"\n",
"// </editor-fold>\n",
NULL
};


/** Section for start of initialize() function.
*/
static char *init_begin[] = {
"// <editor-fold defaultstate=\"collapsed\" desc=\"Printable object initialization\">\n\n",
"  /**\n",
"   * Initialize (create fonts, strokes, colors).\n",
"   * @return    true on success, false on error.\n",
"   */\n",
"  public boolean initialize() {\n",
"    boolean back = is_initialized;\n",
"    if(!initialization_attempted) {\n",
"      back = true;\n",
NULL
};


/** Section for end of initialize() function.
*/
static char *init_end[] = {
"      is_initialized = back;\n",
"      initialization_attempted = true;\n",
"    }\n",
"    return back;\n",
"  }\n",
"\n// </editor-fold>\n\n\n",
NULL
};


/** Section for start of p() function.
*/
static char *p_begin[] = {
"// <editor-fold defaultstate=\"collapsed\" desc=\"Print\">\n\n",
"  /**\n",
"   * Print the graphics (do real printing).\n",
"   * @param g   Graphics context.\n",
"   * @return    True on success, false on error.\n",
"   */\n",
"  private boolean p(Graphics2D g) {\n",
"    boolean back = true;\n",
"    try {\n",
NULL
};



/** Section for end of p() function.
*/
static char *p_end[] = {
"    } catch(Exception e) { back = false; e.printStackTrace(); }\n",
"    return back;\n",
"  }\n",
"\n// </editor-fold>\n\n\n",
NULL
};


/** Pointer to character, used in size calculation.
*/
typedef char *PCHAR;

/** Size of \arg kw array.
*/
static size_t szkw = sizeof(kw)/sizeof(PCHAR);


/**	Write a double value explicitly as Java float value.
	@param	s	Output stream.
	@param	d	Value to write.
*/
static
void
force_double DK_P2(dk_stream_t *,s, double,d) {
  char buffer[256];
  sprintf(buffer, "%lg", d);
  dkstream_puts(s, buffer);
  if(!((strchr(buffer, 'e')) || (strchr(buffer, '.')))) {
    dkstream_puts(s, kw[32]);
  }
}



/**	Write one of the keywords to output.
	@param	oi	OI structure.
	@param	i	Index of keyword in kw.
*/
static
void
kw_out DK_P2(OI *,oi, size_t,i) {
  if(oi) {
    if(oi->s) {
      if(i < szkw) {
        dkstream_puts(oi->s, kw[i]);
      }
    }
  }
}


/**	Find the length (number of digits) for a number.
	@param	ul	Number to inspect.
	@return	Number of dights needed.
*/
static
size_t
number_length DK_P1(unsigned long,ul) {
  size_t back;
  char buffer[64];
  sprintf(buffer, "%lu", ul);
  back = strlen(buffer);
  return back;
}



/**	Write an entire section to output stream.
	@param	oi	Output sructure.
	@param	sp	Pointer to NULL-terminated array of strings.
*/
static
void
section_out DK_P2(OI *,oi, char **,sp) {
  char **ptr;
  ptr = sp;
  while(*ptr) {
    dkstream_puts(oi->s, *ptr);
    ptr++;
  }
}



/**	Write Java package name to output.
	@param	oi	Output structure.
*/
static
void
write_package_name DK_P1(OI *,oi) {
  int	ok = 0;	/* Flag: Finished. */
  int	isf;	/* Flag: First character to handle. */
  char	*ptr;
  char	*last;
  char	*prev;
  char	buffer[2];
  size_t mpl;
  char	*p;
  
  buffer[1] = '\0';
  if((oi->c)->ofn2) {	
    ptr = (oi->c)->ofn2; last = prev = NULL;
    while(*ptr) {
      if((*ptr == '\\') || (*ptr == '/')) {
        prev = last; last = ptr;
      }
      ptr++;
    }
    if(prev) {
      ptr = prev; ptr++; isf = 1;
      while((*ptr) && (*ptr != '\\') && (*ptr != '/')) {
        if(isf) {
	  kw_out(oi, 102);
	} isf = 0;
	buffer[0] = *ptr;
	dkstream_puts(oi->s, buffer);
	ok = 1;
	ptr++;
      }
    }
  }
  if(!ok) {
    if((oi->c)->ifn2) {	
      ptr = (oi->c)->ifn2; last = prev = NULL;
      while(*ptr) {
        if((*ptr == '\\') || (*ptr == '/')) {
          prev = last; last = ptr;
        }
        ptr++;
      }
      if(prev) {
        ptr = prev; ptr++; isf = 1;
        while((*ptr) && (*ptr != '\\') && (*ptr != '/')) {
          if(isf) {
	    kw_out(oi, 102);
	  } isf = 0;
	  buffer[0] = *ptr;
	  dkstream_puts(oi->s, buffer);
	  ok = 1;
	  ptr++;
        }
      }
    }
  }
  if(!ok) {
    mpl = (size_t)dksf_get_maxpathlen();
    p = dk_new(char,mpl);
    if(p) {
      if(dksf_getcwd(p,mpl)) {	
        ptr = p; last = NULL;
	while(*ptr) {
	  if((*ptr == '\\') || (*ptr == '/')) {
	    last = ptr;
	  }
	  ptr++;
	}
	if(last) {
	  ptr = last; ptr++;
	  kw_out(oi, 102);
	  dkstream_puts(oi->s, ptr);
	  ok = 1;
	}
      }
      dk_delete(p);
    }
  }
  if(ok) {
    kw_out(oi, 10); kw_out(oi, 0); kw_out(oi, 0);
  } 
}



/**	Write import instructions.
	@param	oi	OI structure.
*/
static
void
write_import_packages DK_P1(OI *,oi) {
  char **ptr;
  write_package_name(oi);
  if(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES) {
    if(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_WEBSTART) {
      kw_out(oi, 169);
    } else {
      kw_out(oi, 168);
    }
    kw_out(oi, 0); kw_out(oi, 0);
  }
  ptr = packages_to_import;
  kw_out(oi, 157); kw_out(oi, 0); kw_out(oi, 0);
  while(*ptr) {
    kw_out(oi, 9);
    kw_out(oi, 1);
    dkstream_puts(oi->s, *ptr);
    kw_out(oi, 10);
    kw_out(oi, 0);
    ptr++;
  }
  kw_out(oi, 0);
  kw_out(oi, 158); kw_out(oi, 0); kw_out(oi, 0); kw_out(oi, 0);
}


/**	Check whether the current object must be filled.
	@param	oi	Output structure.
	@return	Flag: must fill (1) or not (0).
*/
static
int
must_fill_object DK_P1(OI *,oi) {
  int back = 0;
  int wbgr = 0;
  if(((oi->o)->fpd).cl) {
    if(dkfig_tool_must_fill(((oi->o)->fpd).af, (oi->c)->opt1)
      || dkfig_tool_must_pattern(((oi->o)->fpd).af, (oi->c)->opt1))
    {
      back = 1;
    }
  }
  if(back) {
    if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) {
      if((oi->o)->subtype == 5) {
        if(!(((oi->c)->opt1) & DKFIG_OPT_FILL_BITMAP_AREA)) {
	  back = 0;
	}
      }
    }
    if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BG_RECTANGLE) {
      if(((oi->c)->opt2) & DKFIG_OPT_WHITE_BGRECT) {
        wbgr = 1;
      }
      if(dkfig_tool2_obj_is_bg_rect(oi->o, wbgr)) back = 0;
    }
    if(((oi->o)->fpd).fc == (oi->d)->transparent) {
      back = 0;
    }
  }

  return back;
}


/**	Check whether the current object must be stroked.
	@param	oi	Output structure.
	@return	Flag: must stroke (1) or not (0).
*/
static
int
must_stroke_object DK_P1(OI *,oi) {
  int back = 1;
  int wbgr = 0;
  if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) {
    if((oi->o)->subtype == 5) {
      if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BITMAP_BORDER) {
        back = 0;
      }
    }
  }
  if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_THIN_BORDERS) {
    if(((oi->o)->fpd).lt == 0L) {
      if(((oi->o)->fpd).cl) {
        if(dkfig_tool_must_fill(((oi->o)->fpd).af, (oi->c)->opt1)) {
	  back = 0;
	}
	if(dkfig_tool_must_pattern(((oi->o)->fpd).af, (oi->c)->opt1)) {
	  back = 0;
	}
      }
    }
  }
  if(((oi->c)->opt1) & DKFIG_OPT_REMOVE_BG_RECTANGLE) {
    if(((oi->c)->opt2) & DKFIG_OPT_WHITE_BGRECT) {
      wbgr = 1;
    }
    if(dkfig_tool2_obj_is_bg_rect(oi->o, wbgr)) back = 0;
  }
  if(((oi->o)->fpd).pc == (oi->d)->transparent) {
    back = 0;
  }
  return back;
}


/**	Convert a distance to Java.
	@param	oi	Output structure.
	@param	r	Radius to convert.
	@return	Value as used in Java.
*/
static
double
convertR DK_P2(OI *,oi, double,r) {
  double back;
  back = dkma_mul_double_ok(r, oi->xfactor, &(oi->me));
  return back;
}



/**	Convert x value to Java.
	@param	oi	Output structure.
	@param	x	Value to convert.
	@return	X-position as used in Java.
*/
static
double
convertX DK_P2(OI *,oi, double,x) {
  double back = x;
  back = dkma_add_double_ok(
    dkma_mul_double_ok(x, oi->xfactor, &(oi->me)),
    oi->xshift,
    &(oi->me)
  );
  return back;
}



/**	Convert y value to Java.
	@param	oi	Output structure.
	@param	y	Value to convert.
	@return	Y-position as used in Java.
*/
static
double
convertY DK_P2(OI *,oi, double,y) {
  double back;
  back = y * oi->yfactor + oi->yshift;
  back = dkma_add_double_ok(
    dkma_mul_double_ok(y, oi->yfactor, &(oi->me)),
    oi->yshift,
    &(oi->me)
  );
  return back;
}


/**	Convert distance value to Java.
	@param	oi	Output structure.
	@param	r	Value to convert.
	@return	Conversion result.
*/
static
double
convertRl DK_P2(OI *,oi, long,r) {
  double back;
  back = convertR(oi, dkma_l_to_double(r));
  return back;
}


/**	Convert x position to Java.
	@param	oi	Output structure.
	@param	x	Value to convert.
	@return	Conversion result.
*/
static
double
convertXl DK_P2(OI *,oi, long,x) {
  double back;
  back = convertX(oi, dkma_l_to_double(x));
  return back;
}


/**	Convert y position to Java.
	@param	oi	Output structure.
	@param	y	Value to convert.
	@return	Conversion result.
*/
static
double
convertYl DK_P2(OI *,oi, long,y) {
  double back;
  back = convertY(oi, dkma_l_to_double(y));
  return back;
}


/**	Convert point (long coordinates) and write it.
	@param	oi	Output structure.
	@param	x	x position.
	@param	y	y position.
*/
static
void
lpointout DK_P3(OI *,oi, long,x, long,y) {
  force_double(oi->s, convertXl(oi,x));
  kw_out(oi, 5); kw_out(oi, 1);
  force_double(oi->s, convertYl(oi,y));
}


/**	Convert point (double coordinates) and write it.
	@param	oi	Output structure.
	@param	x	x position.
	@param	y	y position.
*/
static
void
dpointout DK_P3(OI *,oi, double,x, double,y) {
  force_double(oi->s, convertX(oi,x));
  kw_out(oi, 5); kw_out(oi, 1);
  force_double(oi->s, convertY(oi,y));
}


/**	Compare two Java image objects.
	@param	l	Pointer to left object.
	@param	r	Pointer to right object.
	@param	cr	Comparison criteria (ignored).
	@return	Comparison result.
*/
int
image_compare DK_P3(void *,l, void *,r, int,cr) {
  int back = 0;
  dkfig_java_image *il, *ir;
  il = (dkfig_java_image *)l; ir = (dkfig_java_image *)r;
  if(l) {
    if(r) {
      if(il->filename) {
        if(ir->filename) {
	  back = strcmp(il->filename, ir->filename);
	} else { back = 1; }
      } else {
        if(ir->filename) { back = -1; }
      }
    } else { back = 1; }
  } else {
    if(r) { back = -1; }
  }
  return back;
}


/**	Compare two color objects.
	@param	l	Pointer to left object.
	@param	r	Pointer to right object.
	@param	c	Comparison criteria (ignored).
	@return	Comparison result.
*/
int
color_compare DK_P3(void *,l, void *,r, int,c) {
  int back = 0;
  dkfig_java_color *cl, *cr;
  cl = (dkfig_java_color *)l; cr = (dkfig_java_color *)r;
  if(l) {
    if(r) {
      if(cl->r > (cr->r + epsilon)) {
        back = 1;
      } else {
        if(cl->r < (cr->r - epsilon)) {
	  back = -1;
	}
      }
      if(back == 0) {
        if(cl->g > (cr->g + epsilon)) {
	  back = 1;
	} else {
	  if(cl->g < (cr->g - epsilon)) {
	    back = -1;
	  }
	}
      }
      if(back == 0) {
        if(cl->b > (cr->b + epsilon)) {
	  back = 1;
	} else {
	  if(cl->b < (cr->b - epsilon)) {
	    back = -1;
	  }
	}
      }
    } else { back = 1; }
  } else {
    if(r) { back = -1; }
  }
  return back;
}


/**	Compare two stroke objects.
	@param	l	Pointer to left object.
	@param	r	Pointer to right object.
	@param	cr	Comparison criteria (ignored).
	@return	Comparison result.
*/
int
stroke_compare DK_P3(void *,l, void *,r, int,cr) {
  int back = 0;
  dkfig_java_stroke *sl, *sr;
  sl = (dkfig_java_stroke *)l; sr = (dkfig_java_stroke *)r;
  if(l) {
    if(r) {
      if(sl->linewidth > (sr->linewidth + epsilon)) {
        back = 1;
      } else {
        if(sl->linewidth < (sr->linewidth - epsilon)) {
	  back = -1;
	}
      }
      if(back == 0) {
        if(sl->sv > (sr->sv + epsilon)) {
	  back = 1;
	} else {
	  if(sl->sv < (sr->sv - epsilon)) {
	    back = -1;
	  }
	}
      }
      if(back == 0) {
        if(sl->cap > sr->cap) back = 1;
	else {
	  if(sl->cap < sr->cap) back = -1;
	}
      }
      if(back == 0) {
        if(sl->join > sr->join) back = 1;
	else {
	  if(sl->join < sr->join) back = -1;
	}
      }
      if(back == 0) {
        if(sl->dash > sr->dash) back = 1;
	else {
	  if(sl->dash < sr->dash) back = -1;
	}
      }
    } else { back = 1; }
  } else {
    if(r) { back = -1; }
  }
  return back;
}



/**	Compare two font objects.
	@param	l	Pointer to left object.
	@param	r	Pointer to right object.
	@param	cr	Comparison criteria (ignored).
	@return	Comparison result.
*/
int
font_compare DK_P3(void *,l, void *,r, int,cr) {
  int back = 0;
  dkfig_java_font *fl, *fr;
  fl = (dkfig_java_font *)l; fr = (dkfig_java_font *)r;
  if(l) {
    if(r) {
      if(fl->font > fr->font) {
        back = 1;
      } else {
        if(fl->font < fr->font) {
	  back = -1;
	}
      }
      if(back == 0) {
        if(fl->size > (fr->size + epsilon)) {
	  back = 1;
	} else {
	  if(fl->size < (fr->size - epsilon)) {
	    back = -1;
	  }
	}
      }
    } else { back = 1; }
  } else {
    if(r) { back = -1; }
  }
  return back;
}



/**	Compare two layer objects.
	@param	l	Left layer object.
	@param	r	Right layer object.
	@param	cr	Comparison criteria (ignored).
*/
static
int
compare_layer DK_P3(void *,l, void *,r, int,cr) {
  int back = 0;
  dkfig_java_layer *ll, *lr;
  ll = (dkfig_java_layer *)l;
  lr = (dkfig_java_layer *)r;
  if(l) {
    if(r) {
      if(ll->layer > lr->layer) {
        back = 1;
      } else {
        if(ll->layer < lr->layer) {
	  back = -1;
	}
      }
    } else back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}


/**	Initialized image object.
	@param	p	Pointer to object.
*/
static
void
image_init DK_P1(dkfig_java_image *,p) {
  p->imgno = 0UL; p->filename = NULL;
}


/**	Release memory used by image object.
	@param	p	Pointer to object.
*/
static
void
image_delete DK_P1(dkfig_java_image *,p) {
  char *x;
  if(p) {
    p->imgno = 0UL;
    if(p->filename) {
      x = p->filename; dk_delete(x);
    } p->filename = NULL;
    dk_delete(p);
  }
}


/**	Create new image style object.
	@param	fn	Image file name.
	@return	Pointer to new object on success, NULL on error.
*/
static
dkfig_java_image *
image_new DK_P1(char *,fn) {
  dkfig_java_image *back = NULL;
  back = dk_new(dkfig_java_image,1);
  if(back) {
    image_init(back);
    back->filename = dkstr_dup(fn);
    if(!(back->filename)) {
      image_delete(back); back = NULL;
    }
  }
  return back;
}


/**	Initialize color object.
	@param	p	Pointer to object.
*/
static
void
color_init DK_P1(dkfig_java_color *,p) {
  p->colno = 0UL;
  p->r = 0.0; p->g = 0.0; p->b = 0.0;
}


/**	Release memory used by a color object.
	@param	p	Pointer to object.
*/
static
void
color_delete DK_P1(dkfig_java_color *,p) {
  if(p) {
    color_init(p);
    dk_delete(p);
  }
}


/**	Create new color object.
	@param	r	Red.
	@param	g	Green.
	@param	b	Blue.
	@return	Pointer to new object on success, NULL on error.
*/
static
dkfig_java_color *
color_new DK_P3(double,r, double,g, double,b) {
  dkfig_java_color *back = NULL;
  back = dk_new(dkfig_java_color,1);
  if(back) {
    color_init(back);
    back->r = r; back->g = g; back->b = b;
  }
  return back;
}


/**	Initialize font style object.
	@param	p	Pointer to object.
*/
static
void
font_init DK_P1(dkfig_java_font *,p) {
  p->fontno = 0UL;
  p->font = 0;
  p->size = 0.0;
}



/**	Release memory used by font style object.
	@param	p	Pointer to object.
*/
static
void
font_delete DK_P1(dkfig_java_font *,p) {
  if(p) {
    font_init(p);
    dk_delete(p);
  }
}


/**	Create font style object.
	@param	f	PS font index.
	@param	s	Font size.
	@return	Pointer to new object on success, NULL on error.
*/
static
dkfig_java_font *
font_new DK_P2(int, f, double,s) {
  dkfig_java_font *back = NULL;
  back = dk_new(dkfig_java_font,1);
  if(back) {
    font_init(back);
    back->font = f;
    back->size = s;
  }
  return back;
}


/**	Initialize stroke style object.
	@param	p	Pointer to object to initialize.
*/
static
void
stroke_init DK_P1(dkfig_java_stroke *,p) {
  p->strokeno = 0UL;
  p->linewidth = 0.0;
  p->cap = 0;
  p->join = 0;
  p->dash = 0;
}


/**	Release memory used by a stroke style object.
	@param	p	Pointer to stroke style object.
*/
static
void
stroke_delete DK_P1(dkfig_java_stroke *,p) {
  if(p) {
    stroke_init(p);
    dk_delete(p);
  }
}


/**	Create new stroke style object.
	@param	w	Line width.
	@param	sv	Style value (dash pattern length).
	@param	c	Line cap style.
	@param	j	Line join style.
	@param	d	Dash pattern index.
*/
static
dkfig_java_stroke *
stroke_new DK_P5(double,w, double,sv, int,c, int,j, int,d) {
  dkfig_java_stroke *back = NULL;
  back = dk_new(dkfig_java_stroke,1);
  if(back) {
    stroke_init(back);
    back->linewidth = w;
    back->sv = sv;
    back->cap = c;
    back->join = j;
    back->dash = d;
  }
  return back;
}


/**	Release memory allocated by OI.
	@param	oi	OI to release.
*/
static
void
delete_oi DK_P1(OI *,oi) {
  dkfig_java_stroke *stroke;
  dkfig_java_font *font;
  dkfig_java_color *color;
  dkfig_java_image *image;
  dkfig_java_layer *lay;
  
  if(oi) {
    oi->c = NULL;
    oi->d = NULL;
    oi->s = NULL;
    if(oi->fli) {
      dksto_it_close(oi->fli);
    } oi->fli = NULL;
    if(oi->fl) {
      dksto_close(oi->fl);
    } oi->fl = NULL;
    if(oi->i_c) {
      /* Release colors. */
      dksto_it_reset(oi->i_c);
      while((color = (dkfig_java_color *)dksto_it_next(oi->i_c)) != NULL) {
        
        color_delete(color);
      }
      dksto_it_close(oi->i_c);
    } oi->i_c = NULL;
    if(oi->s_c) {
      dksto_close(oi->s_c);
    } oi->s_c = NULL;
    if(oi->i_f) {
      /* Release fonts. */
      dksto_it_reset(oi->i_f);
      while((font = (dkfig_java_font *)dksto_it_next(oi->i_f)) != NULL) {
        
        font_delete(font);
      }
      dksto_it_close(oi->i_f);
    } oi->i_f = NULL;
    if(oi->s_f) {
      dksto_close(oi->s_f);
    } oi->s_f = NULL;
    if(oi->i_s) {
      /* Release strokes. */
      dksto_it_reset(oi->i_s);
      while((stroke = (dkfig_java_stroke *)dksto_it_next(oi->i_s)) != NULL) {
        
        stroke_delete(stroke);
      }
      dksto_it_close(oi->i_s);
    } oi->i_s = NULL;
    if(oi->s_s) {
      dksto_close(oi->s_s);
    } oi->s_s = NULL;
    if(oi->i_i) {
      /* Release images. */
      dksto_it_reset(oi->i_i);
      while((image = (dkfig_java_image *)dksto_it_next(oi->i_i)) != NULL) {
        
        image_delete(image);
      }
      dksto_it_close(oi->i_i);
    } oi->i_i = NULL;
    if(oi->s_i) {
      dksto_close(oi->s_i);
    } oi->s_i = NULL;
    if(oi->i_l) {
      dksto_it_reset(oi->i_l);
      while((lay = (dkfig_java_layer *)dksto_it_next(oi->i_l)) != NULL) {
        
        dk_delete(lay);
      }
      dksto_it_close(oi->i_l);
    } oi->i_l = NULL;
    if(oi->s_l) {
      dksto_close(oi->s_l);
    } oi->s_l = NULL;
    if(oi->fontmap) {
      dkfont_mapping_close(oi->fontmap);
    } oi->fontmap = NULL;
    dk_delete(oi);
  } 
}



/**	Initialize Java driver-specific object extension.
	@param	p	Pointer to DRVE.
*/
static
void
drve_init DK_P1(dkfig_java_drve *,p) {
  p->st = NULL; p->draw = NULL;
  p->fill = NULL; p->img = NULL;
  p->font = NULL; p->tn = 0UL;
}



/**	Release memory used by a Java driver-specific extension.
	@param	p	Pointer to DRVE.
*/
static
void
drve_delete DK_P1(dkfig_java_drve *,p) {
  if(p) {
    drve_init(p);
    dk_delete(p);
  }
}


/**	Create Java driver-specific extension.
	@return	Pointer to DRVE.
*/
static
dkfig_java_drve *
drve_new DK_P0() {
  dkfig_java_drve *back = NULL;
  back = dk_new(dkfig_java_drve,1);
  if(back) { drve_init(back); }
  return back;
}


/**	Check LANG environment variable whether or not to create the Java
	file in UTF-8 encoding.
	@param	oi	Output structure.
*/
static
void
check_utf8 DK_P1(OI *,oi) {
  char buffer[256], *ptr;
  if((oi->c)->app) {
    if(dkapp_get_pref_env((oi->c)->app,kw[71],buffer,sizeof(buffer),0,kw[69]))
    {
      ptr = strchr(buffer, '.');
      if(ptr) {
        ptr++;
	if((dkstr_casecmp(ptr,kw[70])==0) || (dkstr_casecmp(ptr,kw[174])==0)) {
	  oi->wr_utf8 = 1;
	}
      }
    }
  } else {
    ptr = getenv(kw[69]);
    if(ptr) {
      if(strlen(ptr) < sizeof(buffer)) {
        strcpy(buffer, ptr);
        ptr = strchr(buffer, '.');
        if(ptr) {
          ptr++;
	  if((dkstr_casecmp(ptr, kw[70])==0) || (dkstr_casecmp(ptr,kw[174])==0))
	  {
	    oi->wr_utf8 = 1;
	  }
        }
      }
    }
  }
}


/**	Initialize OI structure.
	@param	oi	OI to initialize.
	@param	c	Conversion structure.
	@return	1 on success, 0 on error.
*/
static
int
init_oi DK_P2(OI *,oi, dk_fig_conversion *,c) {
  int back = 0;
  
  oi->d = NULL;
  oi->c = c;
  oi->s = c->ostrm;
  oi->dro = c->drwng;
  oi->fl = NULL;
  oi->fli = NULL;
  oi->s_c = NULL; oi->i_c = NULL;
  oi->s_f = NULL; oi->i_f = NULL;
  oi->s_s = NULL; oi->i_f = NULL;
  oi->s_i = NULL; oi->i_i = NULL;
  oi->s_l = NULL; oi->i_l = NULL;
  oi->text_right = 0x00;
  oi->text_centered = 0x00;
  oi->ec = 0; oi->me = 0;
  oi->spcpass = 0;
  oi->xfactor = oi->yfactor = oi->xshift = oi->yshift = 0.0;
  oi->xleft = oi->xright = oi->ybottom = oi->ytop = 0.0;
  oi->n_c = oi->n_f = oi->n_s = oi->n_i = oi->n_t = 0UL;
  oi->l_c = oi->l_f = oi->l_s = oi->l_i = oi->l_t = 0;
  oi->wr_utf8 = 0;
  check_utf8(oi);
  oi->fontmap = NULL;
  if(c->drwng) {		
    oi->d = (dk_fig_drawing *)((oi->dro)->data);
    if((oi->s) && (oi->dro) && (oi->d)) {	
      oi->s_c = dksto_open(0);
      if(oi->s_c) {
        dksto_set_comp(oi->s_c, color_compare, 0);
        oi->i_c = dksto_it_open(oi->s_c);
	if(oi->i_c) {
	  oi->s_f = dksto_open(0);
	  if(oi->s_f) {
	    dksto_set_comp(oi->s_f, font_compare, 0);
	    oi->i_f = dksto_it_open(oi->s_f);
	    if(oi->i_f) {
	      oi->s_s = dksto_open(0);
	      if(oi->s_s) {
	        dksto_set_comp(oi->s_s, stroke_compare, 0);
	        oi->i_s = dksto_it_open(oi->s_s);
		if(oi->i_s) {
		  oi->s_i = dksto_open(0);
		  if(oi->s_i) {
		    dksto_set_comp(oi->s_i, image_compare, 0);
		    oi->i_i = dksto_it_open(oi->s_i);
		    if(oi->i_i) {
		      oi->s_l = dksto_open(0);
		      if(oi->s_l) {
		        dksto_set_comp(oi->s_l, compare_layer, 0);
		        oi->i_l = dksto_it_open(oi->s_l);
			if(oi->i_l) {
			  back = 1;	
			}
		      }
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }
  } 
  return back;
}



/**	Create new OI.
	@param	c	Conversion structure.
	@return	Pointer to new OI on success, NULL on error.
*/
static
OI *
new_oi DK_P1(dk_fig_conversion *,c) {
  OI *back = NULL;
  if(c) {
    back = dk_new(OI,1);
    if(back) {
      if(!init_oi(back, c)) {
        delete_oi(back); back = NULL;
      }
    }
  }
  return back;
}


/**	Handle special comments.
	@param	oi	EPS output instruction structure.
	@param	o	Fig object.
*/
static void
handle_special_comments DK_P2(dkfig_java_output_instruction *,oi, dk_fig_object *,o)
{
    int i;
    if((o->osc) && (o->osci)) {
      dk_fig_opt *speccom;
      
      dksto_it_reset(o->osci);
      while((speccom = (dk_fig_opt *)dksto_it_next(o->osci)) != NULL) {
        
        i = dkfig_opt_process_special_comment(
	  oi->c, speccom->name, kw[14], 0
	);
	if((oi->spcpass) == 0) {
	  dkfig_tool2_report_special_comment(oi->c, speccom, i);
	}
      }
    }
}



/**	Clean up (release memory used by dynamic objects).
*/
static
void
cleanup_pass DK_P1(OI *,oi) {
  dk_fig_object	*o;
  
  if(oi->fli) {
    dksto_it_reset(oi->fli);
    while((o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
      if(o->drve) {
        drve_delete(o->drve);
	o->drve = NULL;
      }
    }
    dksto_it_close(oi->fli);
  }
  if(oi->fl) { dksto_close(oi->fl); }
  oi->fl = NULL;
  oi->fli = NULL; 
}




/**	Find factors and shiftings for coord
   	transformations.
	@param	oi	EPS output instruction structure.
*/
static int
establish_coord_transformation DK_P1(dkfig_java_output_instruction *,oi)
{
  int back = 1;
  int math_error = 0;
  double xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0;
  double cxmin = 0.0, cxmax = 0.0, cymin = 0.0, cymax = 0.0;
  
  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)); 
  oi->xfactor = dkma_div_double_ok( 72.0, (oi->d)->fres, &math_error);
  oi->yfactor = dkma_div_double_ok( 72.0, (oi->d)->fres, &math_error);
  if(!dkfig_tool_invert_y(oi->d)) {
    oi->yfactor = 0.0 - oi->yfactor;
  } else {	
  }
  xmin = dkma_mul_double_ok(xmin, oi->xfactor, &math_error);
  xmax = dkma_mul_double_ok(xmax, oi->xfactor, &math_error);
  ymin = dkma_mul_double_ok(ymin, oi->yfactor, &math_error);
  ymax = dkma_mul_double_ok(ymax, oi->yfactor, &math_error);
  
  
  
  
  if(xmax < xmin) {
    cxmin = xmin; xmin = xmax; xmax = cxmin;
  }
  if(ymax < ymin) {
    cxmin = ymin; ymin = ymax; ymax = cxmin;
  }
#if FORCE_INTEGER
  cxmin = floor(xmin); cxmax = ceil(xmax);
  cymin = floor(ymin); cymax = ceil(ymax);
#else
  cxmin = xmin; cxmax = xmax;
  cymin = ymin; cymax = ymax;
#endif
  oi->xleft = 0.0; oi->ybottom = 0.0;
  oi->xright = dkma_sub_double_ok(cxmax, cxmin, &math_error);
  oi->ytop   = dkma_sub_double_ok(cymax, cymin, &math_error);
  oi->xshift = 0.5 * dkma_sub_double_ok(
    oi->xright,
    dkma_sub_double_ok(cxmax, cxmin, &math_error),
    &math_error
  );
  oi->yshift = 0.5 * dkma_sub_double_ok(
    oi->ytop,
    dkma_sub_double_ok(cymax, cymin, &math_error),
    &math_error
  );
  oi->xshift = dkma_sub_double_ok(oi->xshift, cxmin, &math_error);
  
  oi->yshift = dkma_sub_double_ok(oi->yshift, cymin, &math_error);
  
  if(math_error) {
    back = 0;
    dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 13);
  }
  
  
  return back;
}


/**	Get linewidth for object.
	@param	oi	EPS output instruction set.
	@param	ispat	Flag: Is pattern.
	@return	Linewidth.
*/
static
double
get_object_linewidth DK_P2(dkfig_java_output_instruction *,oi, int,ispat)
{
  double back = 0.0;
  back = dkma_mul_double_ok(
    dkma_l_to_double(((oi->o)->fpd).lt),
    0.9,
    &(oi->me)
  );
  if(ispat) {
    if(!(((oi->o)->fpd).lt)) {
      back = 0.9;
    }
    back = 0.9;
  }
  if(((oi->c)->opt1) & DKFIG_OPT_ENLIGHTEN_LOOK) {
    back = 0.5 * back;
  }
  return back;
}



/**	Register stroke and draw attributes for a path object.
	@param	oi	Output structure.
	@return	1 on success, 0 on error.
*/
static
int
register_stroke_and_draw DK_P1(OI *,oi) {
  int back = 1;
  int must_draw = 1;
  dkfig_java_drve		*drve;
  dk_fig_dcc			dcc;
  dkfig_java_color		col, *pcol;
  dkfig_java_stroke		str, *pstr;
  double lw;
  if(must_draw) {
    drve = (dkfig_java_drve *)((oi->o)->drve);
    dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).pc);
    col.r = dcc.red;
    col.g = dcc.green;
    col.b = dcc.blue;
    pcol = dksto_it_find_like(oi->i_c, (void *)(&col), 0);
    if(pcol) {
      drve->draw = pcol;
    } else {
      pcol = color_new(dcc.red, dcc.green, dcc.blue);
      if(pcol) {
        if(dksto_add(oi->s_c, (void *)pcol)) {
          drve->draw = pcol;
        } else {
          back = 0;
	  color_delete(pcol);
        }
      } else {
        back = 0;
      }
    }
    lw = get_object_linewidth(oi, 0);
    str.linewidth = lw;
    str.sv = ((oi->o)->fpd).sv;
    str.cap = ((oi->o)->fpd).cs;
    str.join = ((oi->o)->fpd).js;
    str.dash = ((oi->o)->fpd).ls;
    pstr = dksto_it_find_like(oi->i_s, (void *)(&str), 0);
    if(pstr) {
      drve->st = pstr;
    } else {
      pstr =
      stroke_new(lw, ((oi->o)->fpd).sv, ((oi->o)->fpd).cs, ((oi->o)->fpd).js, ((oi->o)->fpd).ls);
      if(pstr) {
        if(dksto_add(oi->s_s, (void *)pstr)) {
	  drve->st = pstr;
	} else {
	  back = 0; stroke_delete(pstr);
	}
      } else {
        back = 0;
      }
    }
  }
 
  return back;
}



/**	Write a number, use at least the required length.
	@param	s	Stream pointer.
	@param	u	The number to write.
	@param	l	The minimum length to use.
*/
static
void
num_with_length DK_P3(dk_stream_t *,s, unsigned long,u, size_t,l) {
  char buffer[256]; size_t i;
  sprintf(buffer, "%lu", u);
  i = strlen(buffer);
  while(i++ < l) dkstream_puts(s, kw[144]);
  dkstream_puts(s, buffer);
}



/**	Register fill style attribute for a path object.
	@param	oi	Output structure.
	@return	1 on success, 0 on error.
*/
static
int
register_fill DK_P1(OI *,oi) {
  int back = 1;
  int must_draw = 1;
  dkfig_java_drve		*drve;
  dk_fig_dcc			dcc;
  dkfig_java_color		col, *pcol;

  if(must_draw) {
    if(dkfig_tool_must_pattern(((oi->o)->fpd).af, (oi->c)->opt1)) {
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_WARNING, 140);
    }
    drve = (dkfig_java_drve *)((oi->o)->drve);
    dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).fc);
    dkfig_tool_correct_dcc(&dcc, ((oi->o)->fpd).fc, ((oi->o)->fpd).af);
    col.r = dcc.red; col.g = dcc.green; col.b = dcc.blue;
    pcol = dksto_it_find_like(oi->i_c, (void *)(&col), 0);
    if(pcol) {
      drve->fill = pcol;
    } else {
      pcol = color_new(dcc.red, dcc.green, dcc.blue);
      if(pcol) {
        if(dksto_add(oi->s_c, (void *)pcol)) {
	  drve->fill = pcol;
	} else {
	  back = 0; color_delete(pcol);
	}
      } else {
        back = 0;
      }
    }
  }
  return back;
}



/**	Register style attributes (font and color) for a text object.
	@param	oi	Output structure.
	@return	1 on success, 0 on error.
*/
static
int
register_font_and_color DK_P1(OI *,oi) {
  int back = 1;
  dkfig_java_font	fnt, *pfnt;
  dk_fig_text		*t;
  dkfig_java_drve	*drve;
  dk_fig_dcc		dcc;
  dkfig_java_color	col, *pcol;
  
  t = (dk_fig_text *)((oi->o)->data);
  drve = (dkfig_java_drve *)((oi->o)->drve);
  drve->tn = oi->n_t;
  oi->n_t += 1UL;
  if(t) {		
    if(!((t->font_flags) & 8)) {
      if((t->font_flags) & 2) {
        /* WARNUNG: Special text. */
	dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_WARNING, 139);
      }
      if((t->font_flags) & 4) {	/* PS font */
        fnt.font = t->font;
	if(t->font == -1) fnt.font = 0;
      } else {			/* LaTeX font */
        switch(t->font) {
	  case 2: { fnt.font =  2; } break;
	  case 3: { fnt.font =  1; } break;
	  case 4: { fnt.font = 16; } break;
	  case 5: { fnt.font = 12; } break;
	  default: { fnt.font = 0; } break;
	}
      }
      fnt.size = t->font_size;
      pfnt = dksto_it_find_like(oi->i_f, (void *)(&fnt), 0);
      if(pfnt) {
        drve->font = pfnt;
      } else {
        pfnt = font_new(t->font, t->font_size);
        if(pfnt) {
          if(dksto_add(oi->s_f, (void *)pfnt)) {
            drve->font = pfnt;
          } else {
            back = 0;
	    font_delete(pfnt);
          }
        } else {
          back = 0;
        }
      }
      dkfig_tool_fill_dcc(oi->d, &dcc, ((oi->o)->fpd).pc);
      col.r = dcc.red;
      col.g = dcc.green;
      col.b = dcc.blue;
      pcol = dksto_it_find_like(oi->i_c, (void *)(&col), 0);
      if(pcol) {
        drve->draw = pcol;
      } else {
        pcol = color_new(dcc.red, dcc.green, dcc.blue);
        if(pcol) {
          if(dksto_add(oi->s_c, (void *)pcol)) {
	    drve->draw = pcol;
	  } else {
	    back = 0;
	    color_delete(pcol);
	  }
        } else {
          back = 0;
        }
      }
    }
  } 
  return back;
}



/**	Register style attributes for an image (image name).
	@param	oi	Output structure.
	@return 1 on success, 0 on error.
*/
static
int
register_image DK_P1(OI *,oi) {
  int back = 1;
  dkfig_java_image img, *pimg;
  dkfig_java_drve *drve;
  dk_fig_polyline *p;
  p = (dk_fig_polyline *)((oi->o)->data);
  drve = (dkfig_java_drve *)((oi->o)->drve);
  if(p->imagename) {
    img.filename = p->imagename;
    pimg = dksto_it_find_like(oi->i_i, (void *)(&img), 0);
    if(pimg) {
      drve->img = pimg;
    } else {
      back = 0;
      pimg = image_new(p->imagename);
      if(pimg) {
        if(dksto_add(oi->s_i, (void *)pimg)) {
	  drve->img = pimg;
	  back = 1;
	} else {
	  image_delete(pimg);
	}
      }
    }
  }
  return back;
}



/**	Transfer current objects bb to layer bb.
	@param	oi	Output structure.
	@param	play	Layer object pointer.
*/
static
void
object_to_layer DK_P2(OI *,oi, dkfig_java_layer *,play) {
  dkfig_tool_bb_add_x(
    &(play->bb), dkfig_tool_bb_get_xmin(&((oi->o)->dbb))
  );
  dkfig_tool_bb_add_x(
    &(play->bb), dkfig_tool_bb_get_xmax(&((oi->o)->dbb))
  );
  dkfig_tool_bb_add_y(
    &(play->bb), dkfig_tool_bb_get_ymin(&((oi->o)->dbb))
  );
  dkfig_tool_bb_add_y(
    &(play->bb), dkfig_tool_bb_get_ymax(&((oi->o)->dbb))
  );
}



/**	Register object bounding box in layer bounding box.
	@param	oi	Output structure.
	@return	1 on success, 0 on error.
*/
static
int
register_layer_bb DK_P1(OI *,oi) {
  int back = 1;
  dkfig_java_layer	lay, *play;
  lay.layer = (oi->o)->layer;
  play = dksto_it_find_like(oi->i_l, (void *)(&lay), 0);
  if(play) {
    object_to_layer(oi, play);
  } else {
    back = 0;
    play = dk_new(dkfig_java_layer,1);
    if(play) {
      play->layer = (oi->o)->layer;
      dkfig_tool_bb_reset(&(play->bb));
      if(dksto_add(oi->s_l, (void *)play)) {
        back = 1;
	object_to_layer(oi, play);
      } else {
        dk_delete(play); play = NULL;
      }
    }
  }
  return back;
}



/**	Register object style attributes to style elements.
	@param	oi	Output structure.
	@return	1 on success, 0 on error (memory problem).
*/
static
int
register_object_attributes DK_P1(OI *,oi) {
  int back = 1;
  switch((oi->o)->objtype) {
    case DK_FIG_OBJ_TEXT: {
      back = register_font_and_color(oi);
    } break;
    case DK_FIG_OBJ_ARC:
    case DK_FIG_OBJ_ELLIPSE:
    case DK_FIG_OBJ_SPLINE:
    case DK_FIG_OBJ_POLYLINE:
    {
      if(must_stroke_object(oi)) {
        back = register_stroke_and_draw(oi);
      }
      if(must_fill_object(oi)) {
        if(!register_fill(oi)) { back = 0; }
      }
      if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) {
        if((oi->o)->subtype == 5) {
	  back = register_image(oi);
	}
      }
      if(!register_layer_bb(oi)) {
        back = 0;
      }
    } break;
  }
  return back;
}


/**	Enumerate style elements.
	@param	oi	Output structure.
*/
static
void
enumerate_elements DK_P1(OI *,oi) {
  unsigned long n;
  dkfig_java_color *c;
  dkfig_java_font *f;
  dkfig_java_stroke *s;
  dkfig_java_image *i;
  
  dksto_it_reset(oi->i_c); n = 0UL;
  while((c = (dkfig_java_color *)dksto_it_next(oi->i_c)) != NULL) {
    c->colno = n;
    n++;
  }
  oi->n_c = n; oi->l_c = number_length(n);
  dksto_it_reset(oi->i_f); n = 0UL;
  while((f = (dkfig_java_font *)dksto_it_next(oi->i_f)) != NULL) {
    f->fontno = n;
    n++;
  }
  oi->n_f = n; oi->l_f = number_length(n);
  dksto_it_reset(oi->i_s); n = 0UL;
  while((s = (dkfig_java_stroke *)dksto_it_next(oi->i_s)) != NULL) {
    s->strokeno = n;
    n++;
  }
  oi->n_s = n; oi->l_s = number_length(2UL * n);
  dksto_it_reset(oi->i_i); n = 0UL;
  while((i = (dkfig_java_image *)dksto_it_next(oi->i_i)) != NULL) {
    i->imgno = n;
    n++;
  }
  oi->n_i = n; oi->l_i = number_length(n);
  
}


/**	Attempt to load a font map file.
	@param	oi	Output structure.
	@return	1 on success, 0 on error.
*/
static
int
load_font_map_file DK_P1(OI *,oi) {
  int back = 1;
  if((oi->c)->fcfg) {
    oi->fontmap = dkfig_tool2_read_font_mapping(oi->c);
    if(!(oi->fontmap)) {
      back = 0;
    }
  }
  return back;
}



/**	Gather all information needed for output.
	@param	oi	OI structure.
	@return	1 on success, 0 on error.
*/
static
int
preparation_pass DK_P1(OI *,oi) {
  int back = 0;
  int font_map_failed = 0;
  dk_fig_object *o;
  unsigned long backuplineno, backupopt1, backupopt2;
  int backupia;
  
  oi->fl = dkfig_flat_list(oi->c, (oi->c)->drwng);
  if(oi->fl) {
    oi->fli = dksto_it_open(oi->fl);
    if(oi->fli) {
      if(establish_coord_transformation(oi)) {
        back = 1;
        dksto_it_reset(oi->fli);
        while((o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
          oi->o = o;
	  backuplineno = dkapp_get_source_lineno((oi->c)->app);
	  dkapp_set_source_lineno((oi->c)->app, o->lineno);
	  backupopt1 = (oi->c)->opt1;
	  backupopt2 = (oi->c)->opt2;
	  backupia = (oi->c)->image_align;
	  if((oi->c)->app) { dkapp_set_source_lineno((oi->c)->app, o->lineno); }
	  handle_special_comments(oi, o);
	  o->drve = drve_new();
	  if(o->drve) {
	    if(!register_object_attributes(oi)) {
	      back = 0;
	    }
	  } else {
	    back = 0;
	  }
	  if(oi->me) {
	    back = 0; oi->me = 0;
	    dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 13);
	  }
	  (oi->c)->image_align = backupia;
	  (oi->c)->opt2 = backupopt2;
	  (oi->c)->opt1 = backupopt1;
	  dkapp_set_source_lineno((oi->c)->app, backuplineno);
        }
	oi->spcpass += 1;
	if((oi->c)->app) { dkapp_set_source_lineno((oi->c)->app, 0UL); }
	enumerate_elements(oi);
	if(!load_font_map_file(oi)) {
	  back = 0; font_map_failed = 1;
	}
      }
    } else {
    }
  } else {
  }
  if(back) {
    if(oi->me) {
      back = 0;
      /* ##### ERROR: Math. */
    }
  } else {
    if(font_map_failed) {
      /* ERROR: Failed to load font map file. */
      if((oi->c)->fcfg) {
        dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_ERROR, 134, 135, (oi->c)->fcfg);
      }
    } else {
      /* ERROR: Memory */
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
    }
  } 
  return back;
}



/**	Write file name as class name (remove directory and suffix).
	@param	oi	Output structure.
	@param	fn	File name.
	@return	1 on success, 0 on error.
*/
static
int
class_name_output DK_P2(OI *,oi, char *,fn) {
  char x[2];
  int back = 0;
  int cc ;
  char *ptr;
  char *last;
  
  ptr = fn; last = NULL;
  while(*ptr) { if((*ptr == '\\') || (*ptr == '/')) { last = ptr; } ptr++; }
  ptr = fn; cc = 1;
  if(last) { ptr = last; ptr++; }
  x[1] = '\0';
  while(cc) {
    if(*ptr) {
      if(*ptr != '.') {
        x[0] = *ptr;
        dkstream_puts(oi->s, x);
	back = 1;
      } else { cc = 0; }
      ptr++;
    } else { cc = 0; }
  } 
  return back;
}



/**	Write class name to Java output file.
	@param	oi	Output structure.
*/
static
void
print_class_name DK_P1(OI *,oi) {
  int ok = 0;
  
  if(oi->c) {
    if((oi->c)->ofn2) {
      ok = class_name_output(oi, (oi->c)->ofn2);
    } else {
      if((oi->c)->ifn2) {
        ok = class_name_output(oi, (oi->c)->ifn2);
      }
    }
  }
  if(!ok) {
    kw_out(oi, 8);
  } 
}



/**	Print graphics width and height.
	@param	oi	Output structure.
*/
static
void
wh_out DK_P1(OI *,oi) {
  kw_out(oi, 162); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 15); kw_out(oi, 0);
  kw_out(oi, 16); dkstream_puts_double(oi->s, oi->xright);
  kw_out(oi, 10);
  kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 17); kw_out(oi, 0);
  kw_out(oi, 18); dkstream_puts_double(oi->s, oi->ytop);
  kw_out(oi, 10);
  kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 163); kw_out(oi, 0);
  kw_out(oi, 164);
  /* h align. */
  switch((oi->c)->align_h) {
    case DKFIG_ALIGN_H_LEFT: {
      kw_out(oi, 97);
    } break;
    case DKFIG_ALIGN_H_RIGHT: {
      kw_out(oi, 99);
    } break;
    default: {
      kw_out(oi, 98);
    } break;
  }
  kw_out(oi, 10); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 165); kw_out(oi, 0);
  kw_out(oi, 166);
  /* v align. */
  switch((oi->c)->align_v) {
    case DKFIG_ALIGN_V_TOP: {
      kw_out(oi, 131);
    } break;
    case DKFIG_ALIGN_V_BOTTOM: {
      kw_out(oi, 132);
    } break;
    default: {
      kw_out(oi, 130);
    } break;
  }
  kw_out(oi, 10); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 158); kw_out(oi, 0); kw_out(oi, 0); kw_out(oi, 0);
}



/**	Write initialization function to Java output file.
	@param	oi	Output structure.
*/
static
int
init_out DK_P1(OI *,oi) {
  int back = 1;
  dkfig_java_color *c;
  dkfig_java_font *f;
  dkfig_java_stroke *s;
  dkfig_java_image *i;
  int		ft;
  int		ff;
  double	dv;
  double	dist;
  double	dashgap;
  char		*ptr;
  char		*found;
  oi->me = 0;
  kw_out(oi, 0);
  section_out(oi, init_begin);
  kw_out(oi, 33); kw_out(oi, 0);
  dksto_it_reset(oi->i_c);
  while((c = (dkfig_java_color *)dksto_it_next(oi->i_c)) != NULL) {
    kw_out(oi, 29);
    num_with_length(oi->s, c->colno, oi->l_c);
    kw_out(oi, 30);
    force_double(oi->s, c->r); kw_out(oi, 61);
    kw_out(oi, 5); kw_out(oi, 1);
    force_double(oi->s, c->g); kw_out(oi, 61);
    kw_out(oi, 5); kw_out(oi, 1);
    force_double(oi->s, c->b); kw_out(oi, 61);
    kw_out(oi, 31); kw_out(oi, 0);
  }
  dksto_it_reset(oi->i_f);
  while((f = (dkfig_java_font *)dksto_it_next(oi->i_f)) != NULL) {
    kw_out(oi, 35);
    num_with_length(oi->s, f->fontno, oi->l_f);
    if(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES) {
      kw_out(oi, 173);
    } else {
      kw_out(oi, 36);
    }
    kw_out(oi, 48); kw_out(oi, 50);
    dkstream_puts_ul(oi->s, (unsigned long)(f->font));
    kw_out(oi, 51);
    kw_out(oi, 5); kw_out(oi, 1);
    kw_out(oi, 49); kw_out(oi, 50);
    dkstream_puts_ul(oi->s, (unsigned long)(f->font));
    kw_out(oi, 51);
    kw_out(oi, 5); kw_out(oi, 1);
    ft = dkfont_get_features(f->font);
    switch(ft & (DK_FONT_FEATURE_BD | DK_FONT_FEATURE_IT)) {
      case DK_FONT_FEATURE_BD: {
        ff = 56;
      } break;
      case DK_FONT_FEATURE_IT: {
        ff = 57;
      } break;
      case (DK_FONT_FEATURE_BD | DK_FONT_FEATURE_IT) : {
        ff = 58;
      } break;
      default: {
        ff = 55;
      } break;
    }
    switch(ft & DK_FONT_FEATURE_TT) {
      case DK_FONT_FEATURE_TT: {
        ft = 54;
      } break;
      case DK_FONT_FEATURE_SF: {
        ft = 53;
      } break;
      default: {
        ft = 52;
      } break;
    }
    kw_out(oi, ft); kw_out(oi, 5); kw_out(oi, 1);
    kw_out(oi, ff); kw_out(oi, 5); kw_out(oi, 1);
    /* force_double(oi->s, f->size); */
    force_double(
      oi->s,
      dkma_double_restrict_digits(
        dkma_mul_double_ok(
	  f->size,
	  (oi->c)->fsf,
	  &(oi->me)
	),
	2
      )
    );
    if(oi->me) {
      back = 0;
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 13);
      oi->me = 0;
    }
    kw_out(oi, 61);
    kw_out(oi, 31);
    kw_out(oi, 0);
  }
  /* Object strokes */
  dksto_it_reset(oi->i_s);
  while((s = (dkfig_java_stroke *)dksto_it_next(oi->i_s)) != NULL) {
    /* Initialize stroke. */
    kw_out(oi, 59);
    num_with_length(oi->s, s->strokeno, oi->l_s);
    kw_out(oi, 60);
    force_double(oi->s, s->linewidth);
    kw_out(oi, 61); kw_out(oi, 5); kw_out(oi, 1);
    switch(s->cap) {
      case 2:  { kw_out(oi, 64); } break;
      case 1:  { kw_out(oi, 63); } break;
      default: { kw_out(oi, 62); } break;
    } kw_out(oi, 5); kw_out(oi, 1);
    switch(s->join) {
      case 2:  { kw_out(oi, 66); } break;
      case 1:  { kw_out(oi, 65); } break;
      default: { kw_out(oi, 67); } break;
    } kw_out(oi, 5); kw_out(oi, 1);
    if(((s->join != 1) && (s->join != 2)) || ((s->dash > 0) && (s->dash < 6))) {
      if((s->join != 1) && (s->join != 2)) {
        dv = s->linewidth * 10.0;
	if(dv < 10.0) dv = 10.0;
	force_double(oi->s, dv); kw_out(oi, 61);
      } else {
        force_double(oi->s, 0.0); kw_out(oi, 61);
      }
      if((s->dash > 0) && (s->dash < 6)) {
        dist = 0.9 * s->sv;
	dashgap = 0.1;
	if(s->linewidth > 0.0) dashgap = 0.1 * s->linewidth;
	if(((oi->c)->opt1) & DKFIG_OPT_DP_DOT_LW) {
	  dashgap = s->linewidth;
	}
        kw_out(oi, 5);
	kw_out(oi, 68);
	switch(s->dash) {
	  case 1: {
	    force_double(oi->s, dist); kw_out(oi, 61);
	    kw_out(oi, 5); kw_out(oi, 1);
	    force_double(oi->s, dist); kw_out(oi, 61);
	  } break;
	  case 2: {
	    force_double(oi->s, dashgap); kw_out(oi, 61);
	    kw_out(oi, 5); kw_out(oi, 1);
	    force_double(oi->s, dist); kw_out(oi, 61);
	  } break;
	  case 3: case 4: case 5: {
	    force_double(oi->s, dist); kw_out(oi, 61);
	    kw_out(oi, 5); kw_out(oi, 1);
	    force_double(oi->s, dist); kw_out(oi, 61);
	    kw_out(oi, 5); kw_out(oi, 1);
	    force_double(oi->s, dashgap); kw_out(oi, 61);
	    kw_out(oi, 5); kw_out(oi, 1);
	    force_double(oi->s, dist); kw_out(oi, 61);
	    if(s->dash > 3) {
	      kw_out(oi, 5); kw_out(oi, 1);
	      force_double(oi->s, dashgap); kw_out(oi, 61);
	      kw_out(oi, 5); kw_out(oi, 1);
	      force_double(oi->s, dist); kw_out(oi, 61);
	      if(s->dash > 4) {
	        kw_out(oi, 5); kw_out(oi, 1);
		force_double(oi->s, dashgap); kw_out(oi, 61);
		kw_out(oi, 5); kw_out(oi, 1);
		force_double(oi->s, dist); kw_out(oi, 61);
	      }
	    }
	  } break;
	}
	kw_out(oi, 3);
	kw_out(oi, 5); kw_out(oi, 1);
	force_double(oi->s, 0.0); kw_out(oi, 61);
      }
    }
    kw_out(oi, 31); kw_out(oi, 0);
  }
  /* Arrowhead strokes */
  dksto_it_reset(oi->i_s);
  while((s = (dkfig_java_stroke *)dksto_it_next(oi->i_s)) != NULL) {
    /* Initialize stroke. */
    kw_out(oi, 59);
    num_with_length(oi->s, (oi->n_s + s->strokeno), oi->l_s);
    kw_out(oi, 60);
    force_double(oi->s, s->linewidth);
    kw_out(oi, 61); kw_out(oi, 5); kw_out(oi, 1);
    kw_out(oi, 62); kw_out(oi, 5); kw_out(oi, 1);
    kw_out(oi, 67);
    kw_out(oi, 31); kw_out(oi, 0);
  }
  dksto_it_reset(oi->i_i);
  while((i = (dkfig_java_image *)dksto_it_next(oi->i_i)) != NULL) {
    
    /* Initialize image. */
    kw_out(oi, 80);
    num_with_length(oi->s, i->imgno, oi->l_i);
    if(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES) {
      kw_out(oi, 172);
    } else {
      kw_out(oi, 81);
    }
    if(i->filename) {
      ptr = i->filename; found = NULL;
      while(*ptr) {
        if((*ptr == '/') || (*ptr == '\\')) {
	  found = ptr;
	}
        ptr++;
      }
      if(found) found++;
      else found = i->filename;
      dkstream_puts(oi->s, found);
    }
    kw_out(oi, 46); kw_out(oi, 31); kw_out(oi, 0);
  }
  kw_out(oi, 34); kw_out(oi, 0);
  section_out(oi, init_end);
  return back;
}


/**	Set font.
	@param	oi	Output structure.
	@param	isc	Flag: Use copy g2 (1) or original (0).
	@param	fontno	Index of new current font.
*/
static
void
set_font DK_P3(OI *,oi, int,isc, unsigned long,fontno) {
  kw_out(oi, 89);
  kw_out(oi, 90);
  if(isc) kw_out(oi, 91);
  kw_out(oi, 92);
  num_with_length(oi->s, fontno, oi->l_f);
  kw_out(oi, 31);
  kw_out(oi, 0);
}


/**	Set color.
	@param	oi	Output structure.
	@param	isc	Flag: Use copy g2 (1) or original (0).
	@param	colno	Index of the new current color.
*/
static
void
set_color DK_P3(OI *,oi, int,isc, unsigned long,colno) {
  kw_out(oi, 89);
  kw_out(oi, 90);
  if(isc) kw_out(oi, 91);
  kw_out(oi, 93);
  num_with_length(oi->s, colno, oi->l_c);
  kw_out(oi, 31);
  kw_out(oi, 0);
}


/**	Set new current font, keep font number in mind.
	@param	oi	Output structure.
	@param	f	Font structure.
*/
static
void
set_registered_font DK_P2(OI *,oi, dkfig_java_font *,f) {
  if((!(oi->h_f)) || (oi->c_f != f->fontno)) {
    set_font(oi, 0, f->fontno);
    oi->h_f = 0x01; oi->c_f = f->fontno;
  }
}


/**	Set stroke.
	@param	oi	Output structure.
	@param	isc	Flag: Use copy g2 (1) or original (0).
	@param	n	Index of the new current stroke.
*/
static
void
set_stroke DK_P3(OI *,oi, int,isc, unsigned long,n) {
  kw_out(oi, 89);
  kw_out(oi, 90);
  if(isc) kw_out(oi, 91);
  kw_out(oi, 113);
  num_with_length(oi->s, n, oi->l_s);
  kw_out(oi, 31); kw_out(oi, 0);
}


/**	Set new current stroke, keep number in mind.
	@param	oi	Output structure.
	@param	s	Index of new current stroke.
*/
static
void
set_registered_stroke_number DK_P2(OI *,oi, unsigned long,s) {
  if((!(oi->h_s)) || (oi->c_s != s)) {
    set_stroke(oi, 0, s);
    oi->h_s = 0x01; oi->c_s = s;
  }
}


/**	Set new current stroke, keep number in mind.
	@param	oi	Output structure.
	@param	s	New current stroke.
*/
static
void
set_registered_stroke DK_P2(OI *,oi, dkfig_java_stroke *,s) {
  set_registered_stroke_number(oi, s->strokeno);
}


/**	Set new current color, keep number in mind.
	@param	oi	Output structure.
	@param	c	Index of the new current color.
*/
static
void
set_registered_color_number DK_P2(OI *,oi, unsigned long,c) {
  if((!(oi->h_c)) || (oi->c_c != c)) {
    set_color(oi, 0, c);
    oi->h_c = 0x01; oi->c_c = c;
  }
}


/**	Set new current color, keep number in mind.
	@param	oi	Output structure.
	@param	c	New current color.
*/
static
void
set_registered_color DK_P2(OI *,oi, dkfig_java_color *,c) {
  set_registered_color_number(oi, c->colno);
}


/**	Write current object (text object).
	@param	oi	Output structure.
	@return	Graphics context to use: 1=g, 2=g2.
*/
static
int
print_text_object DK_P1(OI *,oi) {
  int back = 1;
  dk_fig_text *t;
  dkfig_java_drve *drve;
  dkfig_java_font *f;
  dkfig_java_color *c;
  t = (dk_fig_text *)((oi->o)->data);
  drve = (dkfig_java_drve *)((oi->o)->drve);
  f = drve->font; c = drve->draw;
  if(!((t->font_flags) & 8)) {
    if((f) && (c)) {
      kw_out(oi, 86); kw_out(oi, 0);
      set_registered_font(oi, f);
      set_registered_color(oi, c);
      if(fabs(t->angle) > epsilon) {
	kw_out(oi, 88); kw_out(oi, 0);
	kw_out(oi, 89);
	kw_out(oi, 101);
	lpointout(oi, t->x, t->y);
	kw_out(oi, 31); kw_out(oi, 0);
	kw_out(oi, 89);
	kw_out(oi, 100);
	force_double(oi->s, (0.0 - t->angle));
	kw_out(oi, 31); kw_out(oi, 0);
	kw_out(oi, 148);
	dkstream_puts_ul(oi->s, drve->tn);
	kw_out(oi, 149);
	kw_out(oi, 94); kw_out(oi, 91); kw_out(oi, 5); kw_out(oi, 1);
	kw_out(oi, 95); kw_out(oi, 50);
	dkstream_puts_ul(oi->s, drve->tn);
	kw_out(oi, 51); kw_out(oi, 5); kw_out(oi, 1);
	kw_out(oi, 96); num_with_length(oi->s, f->fontno, oi->l_f);
	kw_out(oi, 5); kw_out(oi, 1);
	force_double(oi->s, 0.0);
	kw_out(oi, 5); kw_out(oi, 1);
	force_double(oi->s, 0.0);
	kw_out(oi, 5); kw_out(oi, 1);
	switch((oi->o)->subtype) {
	  case 2: {
	    kw_out(oi, 99);
	  } break;
	  case 1: {
	    kw_out(oi, 98);
	  } break;
	  default: {
	    kw_out(oi, 97);
	  } break;
	}
	kw_out(oi, 31); kw_out(oi, 1); kw_out(oi, 3); kw_out(oi, 0);
      } else {
        kw_out(oi, 148);
	dkstream_puts_ul(oi->s, drve->tn);
	kw_out(oi, 149);
	kw_out(oi, 94); kw_out(oi, 5); kw_out(oi, 1);
	kw_out(oi, 95); kw_out(oi, 50);
	dkstream_puts_ul(oi->s, drve->tn);
	kw_out(oi, 51); kw_out(oi, 5); kw_out(oi, 1);
	kw_out(oi, 96); num_with_length(oi->s, f->fontno, oi->l_f);
	kw_out(oi, 5); kw_out(oi, 1);
	dpointout(oi, t->x, t->y);
	kw_out(oi, 5); kw_out(oi, 1);
	switch((oi->o)->subtype) {
	  case 2: {
	    kw_out(oi, 99);
	  } break;
	  case 1: {
	    kw_out(oi, 98);
	  } break;
	  default: {
	    kw_out(oi, 97);
	  } break;
	}
	kw_out(oi, 31); kw_out(oi, 1); kw_out(oi, 3); kw_out(oi, 0);
      }
      kw_out(oi, 87); kw_out(oi, 0);
    } else {
      /* ##### Internal error. */
      back = 0;
    }
  }
  return back;
}


/**	Write current object (arc object).
	@param	oi	Output structure.
	@return	Graphics context to use: 1=g, 2=g2.
*/
static
int
write_arc DK_P1(OI *,oi) {
  int back = 0;
  dk_fig_arc *a;
  dk_fig_bb	bbdest;
  double		w;
  double		h;
  double		x0;
  double		y0;
  a = (dk_fig_arc *)((oi->o)->data);
  if(a) {
    back = 1;
    dkfig_tool_bb_reset(&bbdest);
    dkfig_tool_bb_add_x(
      &bbdest,
      dkma_sub_double_ok(
	convertX(oi, (a->calc).xm), convertR(oi, (a->calc).ra), &(oi->me)
      )
    );
    dkfig_tool_bb_add_x(
      &bbdest,
      dkma_add_double_ok(
	convertX(oi, (a->calc).xm), convertR(oi, (a->calc).ra), &(oi->me)
      )
    );
    dkfig_tool_bb_add_y(
      &bbdest,
      dkma_sub_double_ok(
        convertY(oi, (a->calc).ym), convertR(oi, (a->calc).ra), &(oi->me)
      )
    );
    dkfig_tool_bb_add_y(
      &bbdest,
      dkma_add_double_ok(
        convertY(oi, (a->calc).ym), convertR(oi, (a->calc).ra), &(oi->me)
      )
    );
    x0 = bbdest.xmin; y0 = bbdest.ymin;
    w = dkma_sub_double_ok(bbdest.xmax, bbdest.xmin, &(oi->me));
    h = dkma_sub_double_ok(bbdest.ymax, bbdest.ymin, &(oi->me));
    kw_out(oi, 89); kw_out(oi, 126); kw_out(oi, 0); kw_out(oi, 129);
    force_double(oi->s, x0); kw_out(oi, 5); kw_out(oi, 1);
    force_double(oi->s, y0);
    kw_out(oi, 5); kw_out(oi, 1);
    force_double(oi->s, w);
    kw_out(oi, 5); kw_out(oi, 1);
    force_double(oi->s, h);
    kw_out(oi, 5); kw_out(oi, 1);
    force_double(
      oi->s,
      dkma_mul_double_ok(
        360.0,
	dkma_div_double_ok((a->calc).astart, 2 * M_PI, &(oi->me)),
	&(oi->me)
      )
    );
    kw_out(oi, 5); kw_out(oi, 1);
    force_double(
      oi->s,
      dkma_mul_double_ok(
        360.0,
	dkma_div_double_ok((a->calc).alength, 2 * M_PI, &(oi->me)),
	&(oi->me)
      )
    );
    kw_out(oi, 5); kw_out(oi, 0); kw_out(oi, 129);
    kw_out(oi, (((oi->o)->subtype == 1) ? 127 : 128));
    kw_out(oi, 0); kw_out(oi, 89);
    kw_out(oi, 31); kw_out(oi, 0);
  }
  return back;
}


/**	Write current object (spline object).
	@param	oi	Output structure.
	@return	Graphics context to use: 1=g, 2=g2.
*/
static
int
write_spline DK_P1(OI *,oi) {
  int back = 0;
  dk_fig_spline *s;
  dk_fig_bezier_point *bpptr;
  size_t	nsegs;		/* Segments */
  size_t	li;		/* Left border of current segment. */
  size_t	ri;		/* Right border of current segment. */
  size_t	maxli;		/* Maximum for left li. */
  s = (dk_fig_spline *)((oi->o)->data);
  if(s) {
    back = 1;
    bpptr = s->bpoints;
    nsegs = s->nbpoints - 1;
    if(((oi->o)->fpd).cl) { nsegs = s->nbpoints; }
    kw_out(oi, 89); kw_out(oi, 109); kw_out(oi, 0);
    if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 2)) {
      kw_out(oi, 89); kw_out(oi, 110);
      dpointout(oi, (s->pa).value.x, (s->pa).value.y);
      kw_out(oi, 31); kw_out(oi, 0);
      kw_out(oi, 89); kw_out(oi, 125);
      dpointout(oi, (s->pa).rcontrol.x, (s->pa).rcontrol.y);
      kw_out(oi, 5); kw_out(oi, 1);
      dpointout(oi, (s->pa2).lcontrol.x, (s->pa2).lcontrol.y);
      kw_out(oi, 5); kw_out(oi, 1);
      dpointout(oi, (s->pa2).value.x, (s->pa2).value.y);
      kw_out(oi, 31); kw_out(oi, 0);
      li = s->normals;
    } else {
      kw_out(oi, 89); kw_out(oi, 110);
      dpointout(oi, bpptr[0].value.x, bpptr[0].value.y);
      kw_out(oi, 31); kw_out(oi, 0);
      li = 0;
    }
    if((s->normale > 0) || (((oi->o)->fpd).cl) || (!((((oi->o)->fpd).ar) & 1))) {
      maxli = s->nbpoints - 2;
      if(((oi->o)->fpd).cl) { maxli = s->nbpoints - 1; }
      if((!(((oi->o)->fpd).cl)) && (((oi->o)->fpd).ar & 1)) {
        maxli = s->normale - 1;
      }
      while(li <= maxli) {
        ri = li + 1;
	if(ri >= s->nbpoints) { ri = 0; }
	kw_out(oi, 89); kw_out(oi, 125);
	dpointout(oi, bpptr[li].rcontrol.x, bpptr[li].rcontrol.y);
	kw_out(oi, 5); kw_out(oi, 1);
	dpointout(oi, bpptr[ri].lcontrol.x, bpptr[ri].lcontrol.y);
	kw_out(oi, 5); kw_out(oi, 1);
	dpointout(oi, bpptr[ri].value.x,    bpptr[ri].value.y);
	kw_out(oi, 31); kw_out(oi, 0);
	li++;
      }
    }
    if(((oi->o)->fpd).cl) {
      kw_out(oi, 89); kw_out(oi, 112); kw_out(oi, 0);
    } else {
      if((((oi->o)->fpd).ar) & 1) {
        kw_out(oi, 89); kw_out(oi, 125);
	dpointout(oi, (s->pe2).rcontrol.x, (s->pe2).rcontrol.y);
	kw_out(oi, 5); kw_out(oi, 1);
	dpointout(oi, (s->pe).lcontrol.x, (s->pe).lcontrol.y);
	kw_out(oi, 5); kw_out(oi, 1);
	dpointout(oi, (s->pe).value.x, (s->pe).value.y);
	kw_out(oi, 31); kw_out(oi, 0);
      }
    }
    back = 1;
  }
  return back;
}


/**	Write current object (polyline object).
	@param	oi	Output structure.
	@return	Graphics context to use: 1=g, 2=g2.
*/
static
int
write_polyline DK_P1(OI *,oi) {
  int back = 0;
  dk_fig_polyline *p;
  long	*xptr;
  long	*yptr;
  dk_fig_bb	bbdest;
  double	x0;
  double	y0;
  double	w;
  double	h;
  double	r;
  size_t	i;
  p = (dk_fig_polyline *)((oi->o)->data);
  if(p) {
    back = 1;
    xptr = p->xvalues; yptr = p->yvalues;
    switch((oi->o)->subtype) {
      case 2: case 4: case 5: {		/* rectangle */
        dkfig_tool_bb_reset(&bbdest);
	for(i = 0; i < p->npoints; i++) {
	  dkfig_tool_bb_add_x(&bbdest, convertXl(oi, *(xptr++)));
	  dkfig_tool_bb_add_y(&bbdest, convertYl(oi, *(yptr++)));
	}
	x0 = bbdest.xmin;
	y0 = bbdest.ymin;
	w = dkma_sub_double_ok(bbdest.xmax, bbdest.xmin, &(oi->me));
	h = dkma_sub_double_ok(bbdest.ymax, bbdest.ymin, &(oi->me));
	if((oi->o)->subtype == 4) {	/* arc rectangle */
	  r = 0.9 * dkma_l_to_double(p->radius);
	  if(r > (0.5 * w)) r = 0.5 * w;
	  if(r > (0.5 * h)) r = 0.5 * h;
	  kw_out(oi, 89);
	  kw_out(oi, 108); kw_out(oi, 0); kw_out(oi, 129);
	  force_double(oi->s, x0); kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, y0); kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, w);  kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, h);  kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, r);  kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, r);  kw_out(oi, 0); kw_out(oi, 89);
	  kw_out(oi, 31); kw_out(oi, 0);
	  back = 1;
	} else {			/* normal rectangle */
	  kw_out(oi, 89);
	  kw_out(oi, 107); kw_out(oi, 0); kw_out(oi, 129);
	  force_double(oi->s, x0); kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, y0); kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, w);  kw_out(oi, 5); kw_out(oi, 1);
	  force_double(oi->s, h);  kw_out(oi, 0); kw_out(oi, 89);
	  kw_out(oi, 31); kw_out(oi, 0);
	  back = 1;
	}
      } break;
      default: {			/* real polygon or polyline */
        kw_out(oi, 89); kw_out(oi, 109); kw_out(oi, 0);
	for(i = 0; i < p->npoints; i++) {
	  kw_out(oi, 89);
	  if(i == 0) {			/* first point */
	    kw_out(oi, 110);
	    if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 2)) {
	      dpointout(oi, (p->pa).x, (p->pa).y);
	    } else {
	      lpointout(oi, xptr[i], yptr[i]);
	    }
	    kw_out(oi, 31); kw_out(oi, 0);
	  } else {
	    kw_out(oi, 111);
	    if(i == (p->npoints - 1)) {	/* last point */
	      if((!(((oi->o)->fpd).cl)) && ((((oi->o)->fpd).ar) & 1)) {
		dpointout(oi, (p->pe).x, (p->pe).y);
	      } else {
		lpointout(oi, xptr[i], yptr[i]);
	      }
	    } else {			/* inner point */
	      lpointout(oi, xptr[i], yptr[i]);
	    }
	    kw_out(oi, 31); kw_out(oi, 0);
	  }
	}
	if(((oi->o)->fpd).cl) {
	  kw_out(oi, 89); kw_out(oi, 112); kw_out(oi, 0);
	}
      } break;
    }
  }
  return back;
}


/**	Write current object (ellipse object).
	@param	oi	Output structure.
	@return	Graphics context to use: 1=g, 2=g2.
*/
static
int
write_ellipse DK_P1(OI *,oi) {
  int back = 0;
  dk_fig_ellipse *e;
  dk_fig_bb	bbdest;
  double		w;
  double		h;
  double		x0;
  double		y0;
  e = (dk_fig_ellipse *)((oi->o)->data);
  if(e) {
    back = 1;
    dkfig_tool_bb_reset(&bbdest);
    dkfig_tool_bb_add_x(
      &bbdest,
      dkma_sub_double_ok(
	convertXl(oi, e->centerx), convertRl(oi, e->radiusx), &(oi->me)
      )
    );
    dkfig_tool_bb_add_x(
      &bbdest,
      dkma_add_double_ok(
	convertXl(oi, e->centerx), convertRl(oi, e->radiusx), &(oi->me)
      )
    );
    dkfig_tool_bb_add_y(
      &bbdest,
      dkma_sub_double_ok(
        convertYl(oi, e->centery), convertRl(oi, e->radiusy), &(oi->me)
      )
    );
    dkfig_tool_bb_add_y(
      &bbdest,
      dkma_add_double_ok(
        convertYl(oi, e->centery), convertRl(oi, e->radiusy), &(oi->me)
      )
    );
    x0 = bbdest.xmin; y0 = bbdest.ymin;
    w = dkma_sub_double_ok(bbdest.xmax, bbdest.xmin, &(oi->me));
    h = dkma_sub_double_ok(bbdest.ymax, bbdest.ymin, &(oi->me));
    if((e->radiusx != e->radiusy) && (fabs(e->angle) > epsilon)) {
      back = 2;
      kw_out(oi, 88);
      kw_out(oi, 101);
      lpointout(oi, e->centerx, e->centery);
      kw_out(oi, 31); kw_out(oi, 0);
      kw_out(oi, 100);
      force_double(oi->s, (0.0 - e->angle));
      kw_out(oi, 31); kw_out(oi, 0);
      kw_out(oi, 89); kw_out(oi, 114); kw_out(oi, 0); kw_out(oi, 129);
      force_double(oi->s, (0.0 - 0.5 * w)); kw_out(oi, 5); kw_out(oi, 1);
      force_double(oi->s, (0.0 - 0.5 * h)); kw_out(oi, 5); kw_out(oi, 1);
      force_double(oi->s,  w); kw_out(oi, 5); kw_out(oi, 1);
      force_double(oi->s,  h); kw_out(oi, 0); kw_out(oi, 89);
      kw_out(oi, 31); kw_out(oi, 0);
    } else {
      kw_out(oi, 89); kw_out(oi, 114); kw_out(oi, 0); kw_out(oi, 129);
      force_double(oi->s, x0); kw_out(oi, 5); kw_out(oi, 1);
      force_double(oi->s, y0); kw_out(oi, 5); kw_out(oi, 1);
      force_double(oi->s,  w); kw_out(oi, 5); kw_out(oi, 1);
      force_double(oi->s,  h); kw_out(oi, 0); kw_out(oi, 89);
      kw_out(oi, 31); kw_out(oi, 0);
    }
  }
  return back;
}


/**	Write path and optionally new graphics context g2.
	@param	oi	Output structure.
	@return	0=no draw, 1=g, 2=g2.
*/
static
int
write_path DK_P1(OI *,oi) {
  int back = 0;
  switch((oi->o)->objtype) {
    case DK_FIG_OBJ_ELLIPSE: {
      back = write_ellipse(oi);
    } break;
    case DK_FIG_OBJ_POLYLINE: {
      back = write_polyline(oi);
    } break;
    case DK_FIG_OBJ_SPLINE: {
      back = write_spline(oi);
    } break;
    case DK_FIG_OBJ_ARC: {
      back = write_arc(oi);
    } break;
  }
  return back;
}



/**	Write arrowhead path.
	@param	oi	Output structure.
	@param	a	Arrowhead data.
	@param	ai	Arrowhead index (0=forward, 1=backward).
*/
static
void
path_arrowhead DK_P3(OI *,oi, dk_fig_arrow *,a, int,ai) {
  kw_out(oi, 89);
  kw_out(oi, (115+ai)); kw_out(oi, 0);
  kw_out(oi, 89);
  kw_out(oi, (117+ai));
  kw_out(oi, 119);
  dpointout(oi, (a->p1).x, (a->p1).y);
  kw_out(oi, 31); kw_out(oi, 0);
  kw_out(oi, 89);
  kw_out(oi, (117+ai));
  kw_out(oi, 120);
  dpointout(oi, (a->p2).x, (a->p2).y);
  kw_out(oi, 31); kw_out(oi, 0);
  kw_out(oi, 89);
  kw_out(oi, (117+ai));
  kw_out(oi, 120);
  dpointout(oi, (a->p3).x, (a->p3).y);
  kw_out(oi, 31); kw_out(oi, 0);
  if(a->type > 1) {	/* 4 points */
    kw_out(oi, 89);
    kw_out(oi, (117+ai));
    kw_out(oi, 120);
    dpointout(oi, (a->p4).x, (a->p4).y);
    kw_out(oi, 31); kw_out(oi, 0);
  }
  if(a->type > 0) {	/* closepath */
    kw_out(oi, 89); kw_out(oi, (117+ai));
    kw_out(oi, 121); kw_out(oi, 0);
  }
}


/**	Write arrowhead.
	@param	oi	Output structure.
	@param	a	Arrowhead data.
	@param	ai	Arrowhead index (0=forward, 1=backward).
	@param	c	Draw color object number.
	@param	s	Stroke object number.
*/
static
void
arrowhead DK_P5(\
  OI *,oi, dk_fig_arrow *,a, int,ai, unsigned long,c, unsigned long,s)
{
  
  path_arrowhead(oi, a, ai);
  if(a->type > 0) {
    if(a->style == 0) { 
      /* set color white */
      kw_out(oi, 89); kw_out(oi, 122); kw_out(oi, 0);
      oi->h_c = 0x00;
    } else {		
      set_registered_color_number(oi, c);
    }
    /* fill */
    kw_out(oi, 89);
    kw_out(oi, 90);
    kw_out(oi, 123);
    kw_out(oi, (117+ai));
    kw_out(oi, 31);
    kw_out(oi, 0);
  }
  /* set draw color */
  set_registered_color_number(oi, c);
  set_registered_stroke_number(oi, (oi->n_s + s));
  /* draw arrowhead */
  kw_out(oi, 89);
  kw_out(oi, 90);
  kw_out(oi, 124);
  kw_out(oi, (117+ai));
  kw_out(oi, 31);
  kw_out(oi, 0); 
}


/**	Show image.
	@param	oi	Output structure.
*/
static
void
show_image DK_P1(OI *,oi) {
  dk_fig_polyline *p;
  dkfig_java_drve *drve;
  long	*xptr;
  long	*yptr;
  dk_fig_bb	bbdest;
  double	x0;
  double	y0;
  double	x1;
  double	y1;
  size_t	i;
  
  p = (dk_fig_polyline *)((oi->o)->data);
  drve = (dkfig_java_drve *)((oi->o)->drve);
  if((p) && (drve)) {		
    if(drve->img) {		
      xptr = p->xvalues; yptr = p->yvalues;
      dkfig_tool_bb_reset(&bbdest);
      for(i = 0; i < p->npoints; i++) {
        dkfig_tool_bb_add_x(&bbdest, convertXl(oi, *(xptr++)));
        dkfig_tool_bb_add_y(&bbdest, convertYl(oi, *(yptr++)));
      }
      x0 = bbdest.xmin;
      y0 = bbdest.ymin;
      x1 = bbdest.xmax;
      y1 = bbdest.ymax; 
      if(must_stroke_object(oi)) {
        if(drve->st) {
          x0 = dkma_add_double_ok(x0, (0.5 * (drve->st)->linewidth), &(oi->me));
	  y0 = dkma_add_double_ok(y0, (0.5 * (drve->st)->linewidth), &(oi->me));
	  x1 = dkma_sub_double_ok(x1, (0.5 * (drve->st)->linewidth), &(oi->me));
	  y1 = dkma_sub_double_ok(y1, (0.5 * (drve->st)->linewidth), &(oi->me));
        }
      } 
      if((y1 > y0) && (x1 > x0)) {	
	kw_out(oi, 89);
	kw_out(oi, 133); kw_out(oi, 0); kw_out(oi, 129);
	force_double(oi->s, x0);
	kw_out(oi, 5); kw_out(oi, 1);
	force_double(oi->s, y0);
	kw_out(oi, 5); kw_out(oi, 1);
	force_double(oi->s, x1);
	kw_out(oi, 5); kw_out(oi, 1);
	force_double(oi->s, y1);
	kw_out(oi, 5); kw_out(oi, 0); kw_out(oi, 129);
	kw_out(oi, 134);
	num_with_length(oi->s, (drve->img)->imgno, oi->l_i);
	kw_out(oi, 5); kw_out(oi, 1);
	switch(((oi->c)->image_align) & 3) {
	  case DKFIG_ALIGN_H_LEFT: { 
	    kw_out(oi, 97);
	  } break;
	  case DKFIG_ALIGN_H_RIGHT: {	
	    kw_out(oi, 99);
	  } break;
	  default: {			
	    kw_out(oi, 98);
	  } break;
	} kw_out(oi, 5); kw_out(oi, 1);
	switch((((oi->c)->image_align) >> 2) & 3) {
	  case DKFIG_ALIGN_V_TOP: {	
	    kw_out(oi, 131);
	  } break;
	  case DKFIG_ALIGN_V_BOTTOM: {	
	    kw_out(oi, 132);
	  } break;
	  default: {			
	    kw_out(oi, 130);
	  } break;
	}
	kw_out(oi, 0); kw_out(oi, 89); kw_out(oi, 31);
	kw_out(oi, 0);
      }
    }
  } 
}


/**	Print path object.
	@param	oi	Output structure.
	@return 1 on success, 0 on error.
*/
static
int
print_path_object DK_P1(OI *,oi) {
  int back = 1;
  dkfig_java_drve	*drve;
  int	mf = 0;	/* Must fill object. */
  int	ms = 0;	/* Must stroke object. */
  int	mi = 0;	/* Must show image file. */
  int	ng = 0;	/* 0/1/2 = no/g/g2 */
  
  drve = (oi->o)->drve;
  mf = must_fill_object(oi);
  ms = must_stroke_object(oi);
  if((oi->o)->objtype == DK_FIG_OBJ_POLYLINE) {
    if((oi->o)->subtype == 5) {
      mi = 1;	
    }
  }
  if((mf) || (ms) || (mi)) {
    kw_out(oi, 86); kw_out(oi, 0);
    if((mf) || (ms)) {
      ng = write_path(oi);
    }
    if(mf) {
      switch(ng) {
        case 1: {	/* fill g */
	  /* Fill color */
	  if(drve->fill) {
	    set_registered_color(oi, drve->fill);
	  }
	  /* Fill path */
	  kw_out(oi, 89); kw_out(oi, 103); kw_out(oi, 0);
	} break;
	case 2: {	/* fill g2 */
	  /* Fill color */
	  if(drve->fill) {
	    set_color(oi, 1, (drve->fill)->colno);
	  }
	  /* Fill path */
	  kw_out(oi, 89); kw_out(oi, 104); kw_out(oi, 0);
	} break;
      }
    }
    if(mi) {
      show_image(oi);
    }
    if(ms) {
      switch(ng) {
        case 1: {	/* stroke g */
	  /* Stroke color */
	  if(drve->draw) {
	    set_registered_color(oi, drve->draw);
	  }
	  if(drve->st) {
	    set_registered_stroke(oi, drve->st);
	  }
	  /* Stroke path */
	  kw_out(oi, 89); kw_out(oi, 105); kw_out(oi, 0);
	} break;
	case 2: {	/* stroke g2 */
	  /* Stroke color */
	  if(drve->draw) {
	    set_color(oi, 1, (drve->draw)->colno);
	  }
	  /* Stroke path */
	  if(drve->st) {
	    set_stroke(oi, 1, (drve->st)->strokeno);
	  }
	  kw_out(oi, 89); kw_out(oi, 106); kw_out(oi, 0);
	} break;
      }
      if((((oi->o)->fpd).ar) & 1) {
        arrowhead(
	  oi, &(((oi->o)->fpd).ahf), 0,
	  (drve->draw)->colno, (drve->st)->strokeno
	);
      }
      if((((oi->o)->fpd).ar) & 2) {
        arrowhead(
	  oi, &(((oi->o)->fpd).ahb), 1,
	  (drve->draw)->colno, (drve->st)->strokeno
	);
      }
    }
    kw_out(oi, 87); kw_out(oi, 0);
  } 
  return back;
}


/**	Print current object.
	@param	oi	Output structure.
*/
static
int
print_object DK_P1(OI *,oi) {
  int back = 1;
  if((oi->o)->objtype == DK_FIG_OBJ_TEXT) {
    back = print_text_object(oi);
  } else {
    back = print_path_object(oi);
  }
  return back;
}



/**	Print output.
	@param	oi	Output structure.
*/
static
int
print_out DK_P1(OI *,oi) {
  int back = 1;
  dkfig_java_font *f;
  unsigned long backupopt1;
  unsigned long backupopt2;
  unsigned long backuplineno;
  int backupia;
  oi->me = 0;
  kw_out(oi, 0);
  section_out(oi, p_begin);
  /* Create font metrics for all the fonts. */
  dksto_it_reset(oi->i_f);
  while((f = (dkfig_java_font *)dksto_it_next(oi->i_f)) != NULL) {
    kw_out(oi, 84); num_with_length(oi->s, f->fontno, oi->l_f);
    kw_out(oi, 85); num_with_length(oi->s, f->fontno, oi->l_f);
    kw_out(oi, 31); kw_out(oi, 0);
  }
  dksto_it_reset(oi->fli);
  while((oi->o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
    backuplineno = dkapp_get_source_lineno((oi->c)->app);
    dkapp_set_source_lineno((oi->c)->app, (oi->o)->lineno);
    backupopt1 = (oi->c)->opt1;
    backupopt2 = (oi->c)->opt2;
    backupia = (oi->c)->image_align;	
    oi->me  = 0;
    handle_special_comments(oi, oi->o);	
    if(!print_object(oi)) { back = 0; }
    if(oi->me) {
      back = 0;
      dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 13);
    }
    (oi->c)->image_align = backupia;	
    (oi->c)->opt2 = backupopt2;
    (oi->c)->opt1 = backupopt1;
    dkapp_set_source_lineno((oi->c)->app, backuplineno);
  }
  section_out(oi, p_end);
  kw_out(oi, 0);
  return back;
}





/**	Put character to Java string.
	@param	st	Stream to write to.
	@param	c	Character to write.
*/
static
void
put_java_char DK_P2(dk_stream_t *,st, char,c) {
  switch(c) {
    case '"': {
      dkstream_puts(st, kw[82]);
    } break;
    case '\\': {
      dkstream_puts(st, kw[83]);
    } break;
    default: {
      dkstream_write(st, &c, 1);
    } break;
  }
}



static
void
put_java_escaped_char DK_P2(dk_stream_t *,st, unsigned char,c) {
  unsigned u;
  char buffer[16];
  if(c < 0x80) {
    put_java_char(st, (char)c);
  } else {
    u = (unsigned)c;
    sprintf(buffer, "\\u%04X", u);
    dkstream_puts(st, buffer);
  }
}



/**	Put a text as Java string.
	@param	st	Stream to write to.
	@param	s	String to print.
*/
static
void
put_java_string DK_P2(dk_stream_t *,st, char *,s) {
  char *ptr;
  ptr = s;
  while(*ptr) {
    put_java_char(st, *ptr);
    ptr++;
  }
}


/**	Put a text as Java string.
	@param	st	Stream to write to.
	@param	s	String to print.
*/
static
void
put_java_escaped_string DK_P2(dk_stream_t *,st, char *,s) {
  char *ptr;
  ptr = s;
  while(*ptr) {
    put_java_escaped_char(st, (unsigned char)(*ptr));
    ptr++;
  }
}



/**	Convert text string from UTF-8 to ISO and write it to
	Java output file as Java string.
	@param	oi	Output structure.
	@param	t	Text to write.
*/
static
void
utf8_to_iso DK_P2(OI *,oi, char *,t) {
  dk_udword	ucb;
  int		cc;
  unsigned char	uc;
  size_t	max;
  size_t	used;
  size_t	avail;
  size_t	step;
  size_t	curpos;
  cc = 1; max = strlen(t); used = 0; avail = max; curpos = 0;
  while(cc) {
    cc = 0;
    if(avail > 0) {
      step = 0;
      cc = dkenc_utf82uc(&ucb, (unsigned char *)(&(t[used])), avail, &step);
      if(cc) {
        used = used + step;
	if(avail > step) { avail = avail - step; } else { avail = 0; }
	if(ucb < 256UL) {
	  uc = (unsigned char)ucb;
	  put_java_char(oi->s, (char)uc);
	} else {	
	  /* ##### ERROR: Character out of range. */
	}
      }
    }
  }
}


#if VERSION_BEFORE_20101205
/**	Convert text string from UTF-8 to ISO and write it to
	Java output file as Java string.
	@param	oi	Output structure.
	@param	t	Text to write.
*/
static
void
utf8_to_escaped DK_P2(OI *,oi, char *,t) {
  dk_udword	ucb;
  int		cc;
  unsigned char	uc;
  size_t	max;
  size_t	used;
  size_t	avail;
  size_t	step;
  size_t	curpos;
  char		buffer[16];
  cc = 1; max = strlen(t); used = 0; avail = max; curpos = 0;
  while(cc) {
    cc = 0;
    if(avail > 0) {
      step = 0;
      cc = dkenc_utf82uc(&ucb, (unsigned char *)(&(t[used])), avail, &step);
      if(cc) {
        used = used + step;
	if(avail > step) { avail = avail - step; } else { avail = 0; }
	if(ucb < 256UL) {
	  uc = (unsigned char)ucb;
	  put_java_escaped_char(oi->s, (char)uc);
	} else {	
	  if(ucb > 0xFFFFUL) {
	    if(ucb < 0x00110000UL) {
	      sprintf(buffer, "\\U%06lX", ucb);
	      dkstream_puts(oi->s, buffer);
	    } else {
	      /* ##### ERROR: Character too large */
	    }
	  } else {
	    sprintf(buffer, "\\u%04lX", ucb);
	    dkstream_puts(oi->s, buffer);
	  }
	}
      }
    }
  }
}
#endif
/* if VERSION_BEFORE_20101205 */




/**	Write all string elements to output.
	@param	oi	Output structure.
	@param	kwi	Index of declaration in kw.
*/
static
void
all_strings_out DK_P2(OI *,oi, size_t,kwi) {
  int	is_not_first = 0;
  dk_fig_object *o;
  dkfig_java_drve *drve;
  dk_fig_text *t;
  unsigned long backupopt1, backupopt2;
  int backupia;
  char buffer[32], *ptr;
  unsigned char uc;
  dk_udword udw;
  size_t sz;
  kw_out(oi, kwi); kw_out(oi, 0);
  kw_out(oi, (kwi+1));
  dksto_it_reset(oi->fli);
  while((o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
    oi->o = o;
    if((oi->o)->objtype == DK_FIG_OBJ_TEXT) {
      backupopt1 = (oi->c)->opt1;
      backupopt2 = (oi->c)->opt2;
      backupia = (oi->c)->image_align;
      drve = (dkfig_java_drve *)(o->drve);
      t = (dk_fig_text *)(o->data);
      if(t) {
        if(is_not_first) {
          kw_out(oi, 5);
        } is_not_first = 1;
        kw_out(oi, 0);
        kw_out(oi, 76);
        kw_out(oi, 77);
        num_with_length(oi->s, drve->tn, oi->l_t);
        kw_out(oi, 78);
        kw_out(oi, 79);
	if(t->text) {
	  if(((oi->c)->opt2) & DKFIG_OPT_JAVA_UNICODE) {
	    if(((oi->c)->opt2) & DKFIG_OPT_UTF_8) {
	    } else {
	      put_java_escaped_string(oi->s, t->text);
	    }
	  } else {
            if(oi->wr_utf8) {
              if(((oi->c)->opt2) & DKFIG_OPT_UTF_8) {
	        put_java_string(oi->s, t->text);
	      } else {
	        /* size_t  dkenc_uc2utf8 DK_PR((dk_udword c, dk_ubyte *u8p, size_t u8l)); */
	        ptr = t->text;
	        while(*ptr) {
	          uc = (unsigned char)(*ptr);
		  udw = (dk_udword)uc;
		  sz = dkenc_uc2utf8(udw, (dk_ubyte *)buffer, sizeof(buffer));
		  if(sz > 0) {
		    buffer[sz] = '\0';
		    put_java_string(oi->s, buffer);
		  }
	          ptr++;
	        }
	      }
            } else {
              if(((oi->c)->opt2) & DKFIG_OPT_UTF_8) {
	        utf8_to_iso(oi, t->text);
	      } else {
	        put_java_string(oi->s, t->text);
	      }
            }
	  }
	}
        kw_out(oi, 79);
        (oi->c)->image_align = backupia;
        (oi->c)->opt2 = backupopt2;
        (oi->c)->opt1 = backupopt1;
      }
    }
  }
  kw_out(oi, 0); kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 3); kw_out(oi, 10);
  kw_out(oi, 0); kw_out(oi, 0);
}



/**	Write booleans (string enabled).
	@param	oi	Output structure.
*/
static
void
string_booleans_out DK_P1(OI *,oi) {
  int is_not_first = 0;
  dk_fig_object *o;
  kw_out(oi, 1); kw_out(oi, 1); kw_out(oi, 146); kw_out(oi, 0);
  kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 145);
  dksto_it_reset(oi->fli);
  while((o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
    oi->o = o;
    if((oi->o)->objtype == DK_FIG_OBJ_TEXT) {
      if(is_not_first) {
        kw_out(oi, 5);
      } is_not_first = 1;
      kw_out(oi, 0);
      kw_out(oi, 76);
      kw_out(oi, 147);
    }
  }
  kw_out(oi, 0); kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 3); kw_out(oi, 10);
  kw_out(oi, 0); kw_out(oi, 0);
}



/**	Write information about layers in which texts are placed.
	@param	oi	Output structure.
*/
static
void
string_layers_out DK_P1(OI *,oi) {
  int is_not_first = 0;
  dk_fig_object *o;
  char buffer[32];
  kw_out(oi, 1); kw_out(oi, 1); kw_out(oi, 150); kw_out(oi, 0);
  kw_out(oi, 1); kw_out(oi, 1); kw_out(oi, 151);
  dksto_it_reset(oi->fli);
  while((o = (dk_fig_object *)dksto_it_next(oi->fli)) != NULL) {
    oi->o = o;
    if((oi->o)->objtype == DK_FIG_OBJ_TEXT) {
      if(is_not_first) {
        kw_out(oi, 5);
      } is_not_first = 1;
      kw_out(oi, 0);
      sprintf(buffer, "%ld", o->layer);
      kw_out(oi, 76); dkstream_puts(oi->s, buffer);
    }
  }
  kw_out(oi, 0); kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 3); kw_out(oi, 10);
  kw_out(oi, 0); kw_out(oi, 0);
}


/**	Write all strings to output file.
	@param	oi	Output structure.
*/
static
void
strings_out DK_P1(OI *,oi) {
  kw_out(oi, 0);
  kw_out(oi, 161); kw_out(oi, 0); kw_out(oi, 0);
  oi->l_t = number_length(oi->n_t);
  all_strings_out(oi, 72);
  all_strings_out(oi, 74);
  string_booleans_out(oi);
  string_layers_out(oi);
  kw_out(oi, 0);
  kw_out(oi, 158); kw_out(oi, 0); kw_out(oi, 0); kw_out(oi, 0);
}


/**	Check whether a strings starts with a pattern.
	@param	s	String to test.
	@param	p	Pattern at start of string.
	@return	1 if \arg p is at the start of \arg s, otherwise 0.
*/
static 
int
string_starts_with DK_P2(char *,s, char *,p) {
  int back = 0;
  size_t	n;
  n = strlen(p);
  if(strlen(s) > n) {
    if(strncmp(s, p, n) == 0) {
      back = 1;
    }
  }
  return back;
}


/**	Write information about used ranges in layers.
	@param	oi	Output structure.
*/
static
void
layer_info_out DK_P1(OI *,oi) {
  dkfig_java_layer *l;
  int is_not_first = 0;
  double x1, x2, y1, y2, xmin, xmax, ymin, ymax;
  kw_out(oi, 0);
  kw_out(oi, 167); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 154); kw_out(oi, 0);
  kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 152);
  dksto_it_reset(oi->i_l);
  while((l = (dkfig_java_layer *)dksto_it_next(oi->i_l)) != NULL) {
    if(is_not_first) {
      kw_out(oi, 5);
    } is_not_first = 1;
    kw_out(oi, 0);
    kw_out(oi, 76);
    /*
    kw_out(oi, 153);
    */
    x1 = dkfig_tool_bb_get_xmin(&(l->bb));
    x2 = dkfig_tool_bb_get_xmax(&(l->bb));
    y1 = dkfig_tool_bb_get_ymin(&(l->bb));
    y2 = dkfig_tool_bb_get_ymax(&(l->bb));
    x1 = convertX(oi, x1);
    x2 = convertX(oi, x2);
    y1 = convertY(oi, y1);
    y2 = convertY(oi, y2);
    if(x1 < x2) { xmin = x1; xmax = x2; }
    else { xmin = x2; xmax = x1; }
    if(y1 < y2) { ymin = y1; ymax = y2; }
    else { ymin = y2; ymax = y1; }
    kw_out(oi, 155);
    dkstream_puts_ul(oi->s, (unsigned long)(l->layer));
    kw_out(oi, 5);
    kw_out(oi, 1);
    force_double(oi->s, xmin);
    kw_out(oi, 5);
    kw_out(oi, 1);
    force_double(oi->s, xmax);
    kw_out(oi, 5);
    kw_out(oi, 1);
    force_double(oi->s, ymin);
    kw_out(oi, 5);
    kw_out(oi, 1);
    force_double(oi->s, ymax);
    kw_out(oi, 156);
  }
  kw_out(oi, 0);
  kw_out(oi, 1); kw_out(oi, 1);
  kw_out(oi, 3); kw_out(oi, 10);
  kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 158); kw_out(oi, 0); kw_out(oi, 0); kw_out(oi, 0);
}


/**	Write variables section to output file.
	@param	oi	Output structure.
*/
static
int
variables_out DK_P1(OI *,oi) {
  int		back = 1;
  dkfig_java_color *c;
  dkfig_java_font *f;
  dkfig_java_stroke *s;
  dkfig_java_image *i;
  int	fontno;			/* Font index. */
  int	repno;			/* Replacement number. */
  char	*ptr;			/* Retrieve dkfont_xxx. */
  char	*bptr;			/* Pointer to font base directory. */
  dk_one_font_mapping_t *o;	/* One font mapping. */
  dk_font_replacement_t	    *r;	/* Font replacement. */

  kw_out(oi, 0);
  kw_out(oi, 159); kw_out(oi, 0); kw_out(oi, 0);
  dksto_it_reset(oi->i_c);
  while((c = (dkfig_java_color *)dksto_it_next(oi->i_c)) != NULL) {
    kw_out(oi, 19);
    dkstream_puts_ul(oi->s, c->colno);
    kw_out(oi, 20); kw_out(oi, 0);
    kw_out(oi, 21); num_with_length(oi->s, c->colno, oi->l_c);
    kw_out(oi, 22); kw_out(oi, 0); kw_out(oi, 0);
  }
  dksto_it_reset(oi->i_f);
  while((f = (dkfig_java_font *)dksto_it_next(oi->i_f)) != NULL) {
    kw_out(oi, 23);
    dkstream_puts_ul(oi->s, f->fontno);
    kw_out(oi, 20); kw_out(oi, 0);
    kw_out(oi, 24); num_with_length(oi->s, f->fontno, oi->l_f);
    kw_out(oi, 22); kw_out(oi, 0); kw_out(oi, 0);
  }
  dksto_it_reset(oi->i_s);
  while((s = (dkfig_java_stroke *)dksto_it_next(oi->i_s)) != NULL) {
    kw_out(oi, 25); dkstream_puts_ul(oi->s, s->strokeno);
    kw_out(oi, 20); kw_out(oi, 0);
    kw_out(oi, 26); num_with_length(oi->s, s->strokeno, oi->l_s);
    kw_out(oi, 22); kw_out(oi, 0); kw_out(oi, 0);
  }
  /* Arrowhead strokes */
  dksto_it_reset(oi->i_s);
  while((s = (dkfig_java_stroke *)dksto_it_next(oi->i_s)) != NULL) {
    kw_out(oi, 25); dkstream_puts_ul(oi->s, (oi->n_s + s->strokeno));
    kw_out(oi, 20); kw_out(oi, 0);
    kw_out(oi, 26); num_with_length(oi->s, (oi->n_s + s->strokeno), oi->l_s);
    kw_out(oi, 22); kw_out(oi, 0); kw_out(oi, 0);
  }
  dksto_it_reset(oi->i_i);
  while((i = (dkfig_java_image *)dksto_it_next(oi->i_i)) != NULL) {
    
    kw_out(oi, 27); dkstream_puts_ul(oi->s, i->imgno);
    
    kw_out(oi, 20); kw_out(oi, 0);
    
    kw_out(oi, 28); num_with_length(oi->s, i->imgno, oi->l_i);
    
    kw_out(oi, 22); kw_out(oi, 0); kw_out(oi, 0);
    
  }
  kw_out(oi, 158); kw_out(oi, 0); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 0);
  kw_out(oi, 160); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 37); kw_out(oi, 0);
  kw_out(oi, 38);
  for(fontno = 0; fontno < 35; fontno++) {
    if(fontno) { kw_out(oi, 5); }
    kw_out(oi, 0);
    kw_out(oi, 40);
    kw_out(oi, 1);
    kw_out(oi, 42);
    kw_out(oi, 1);
    dkstream_puts(oi->s, dkfont_get_ps_name(fontno));
    repno = 0;
    if(((oi->c)->opt2) & DKFIG_OPT_USE_GS_FONTS) {
      ptr = dkfont_get_gs_file_name(fontno);
      if(ptr) {
        kw_out(oi, 0);
	kw_out(oi, 45);
	kw_out(oi, 46);
	dkstream_puts(oi->s, ptr);
	kw_out(oi, 47);
	kw_out(oi, 46);
	repno++;
      }
      ptr = dkfont_get_new_gs_file_name(fontno);
      if(ptr) {
        if(repno) kw_out(oi, 5);
	kw_out(oi, 0);
	kw_out(oi, 45);
	kw_out(oi, 46);
	dkstream_puts(oi->s, ptr);
	kw_out(oi, 46);
        repno++;
      }
    }
    if(oi->fontmap) {
      o = dkfont_get_one_font(oi->fontmap, fontno);
      if(o) {
        dkfont_one_font_reset(o);
	while((r = dkfont_one_font_get(o)) != NULL) {
	  ptr = dkfont_rep_get_pfb_source_name(r);
	  if(ptr) {
            if(repno) kw_out(oi, 5);
	    kw_out(oi, 0);
	    kw_out(oi, 45);
	    kw_out(oi, 46);
	    dkstream_puts(oi->s, ptr);
	    kw_out(oi, 46);
            repno++;
	    bptr = dkfont_rep_get_pfb_location(r);
	    if(bptr) {
	      if(string_starts_with(bptr, kw[143])) {
	        if(repno) kw_out(oi, 5);
	        kw_out(oi, 0);
	        kw_out(oi, 45);
	        kw_out(oi, 46);
	        dkstream_puts(oi->s, bptr);
	        kw_out(oi, 142);
	        dkstream_puts(oi->s, ptr);
	        kw_out(oi, 46);
	        repno++;
	      }
	    }
	  }
	  ptr = dkfont_rep_get_ttf_source_name(r);
	  if(ptr) {
            if(repno) kw_out(oi, 5);
	    kw_out(oi, 0);
	    kw_out(oi, 45);
	    kw_out(oi, 46);
	    dkstream_puts(oi->s, ptr);
	    kw_out(oi, 46);
            repno++;
	    bptr = dkfont_rep_get_ttf_location(r);
	    if(bptr) {
	      if(string_starts_with(bptr, kw[143])) {
	        if(repno) kw_out(oi, 5);
	        kw_out(oi, 0);
	        kw_out(oi, 45);
	        kw_out(oi, 46);
	        dkstream_puts(oi->s, bptr);
	        kw_out(oi, 142);
	        dkstream_puts(oi->s, ptr);
	        kw_out(oi, 46);
	        repno++;
	      }
	    }
	  }
	}
      }
    }
    kw_out(oi, 0); kw_out(oi, 41);
  }
  kw_out(oi, 0); kw_out(oi, 39); kw_out(oi, 0); kw_out(oi, 0);
  kw_out(oi, 43); kw_out(oi, 0);
  kw_out(oi, 44);
  for(fontno = 0; fontno < 35; fontno++) {
    if(fontno) { kw_out(oi, 5); }
    kw_out(oi, 0);
    kw_out(oi, 40);
    kw_out(oi, 1);
    kw_out(oi, 42);
    kw_out(oi, 1);
    dkstream_puts(oi->s, dkfont_get_ps_name(fontno));
    repno = 0;
    ptr = dkfont_get_ps_name(fontno);
    if(ptr) {
        kw_out(oi, 0);
	kw_out(oi, 45);
	kw_out(oi, 46);
	dkstream_puts(oi->s, ptr);
	kw_out(oi, 46);
	repno++;
    }
    if(oi->fontmap) {
      o = dkfont_get_one_font(oi->fontmap, fontno);
      if(o) {
        dkfont_one_font_reset(o);
	while((r = dkfont_one_font_get(o)) != NULL) {
	  ptr = dkfont_rep_get_name(r);
	  if(ptr) {
            if(repno) kw_out(oi, 5);
	    kw_out(oi, 0);
	    kw_out(oi, 45);
	    kw_out(oi, 46);
	    dkstream_puts(oi->s, ptr);
	    kw_out(oi, 46);
            repno++;
	  }
	}
      }
    }
    kw_out(oi, 0); kw_out(oi, 41);
  }
  kw_out(oi, 0); kw_out(oi, 39); kw_out(oi, 0);
  kw_out(oi, 0);
  kw_out(oi, 158);
  kw_out(oi, 0); kw_out(oi, 0); kw_out(oi, 0);
  layer_info_out(oi);
  return back;
}


/**	Write needed resources to header of file.
	@param	oi	Output structure.
*/
static
void
header_for_resources DK_P1(OI *,oi) {
  kw_out(oi, 135); kw_out(oi, 0);
  kw_out(oi, 136); kw_out(oi, 0);
}


/**	List needed resources.
	@param	oi	Output structure.
	@return	1 on success, 0 on error.
*/
static
int
write_needed_resources DK_P1(OI *,oi) {
  int			 back = 1;
  dkfig_java_font	*f;
  int 			 i;
  int			 header_printed = 0;
  dk_one_font_mapping_t	 *o;
  dk_font_replacement_t	 *r;
  char			 *ptr, *last;
  int			 first_in_line;
  int			 font_found;
  int			 any_resource;
  dkfig_java_image	 *img;

  any_resource = 0;
  if(oi->fontmap) {
    dksto_it_reset(oi->i_f);
    while((f = (dkfig_java_font *)dksto_it_next(oi->i_f)) != NULL) {
      dkfont_set_used(oi->fontmap, f->font, 1);
    }
    for(i = 0; i < 35; i++) {
      first_in_line = 1;
      if(dkfont_get_used(oi->fontmap, i)) {
        font_found = 0;
        if(!header_printed) {
	  header_for_resources(oi);
	} header_printed = 1;
	kw_out(oi, 137); num_with_length(oi->s, (unsigned long)i, 2);
	kw_out(oi, 138); kw_out(oi, 1);
	kw_out(oi, 46);
	dkstream_puts(oi->s, dkfont_get_ps_name(i));
	kw_out(oi, 46);
	o = dkfont_get_one_font(oi->fontmap, i);
	if(o) {
	  dkfont_one_font_reset(o);
	  if(((oi->c)->opt2) & DKFIG_OPT_USE_GS_FONTS) {
	    font_found = 1;
	    ptr = dkfont_get_gs_file_name(i);
	    if(ptr) { 
	      if(first_in_line) {
	        kw_out(oi, 139);
	      } else {
	        kw_out(oi, 140);
	      } first_in_line = 0;
	      kw_out(oi, 46);
	      dkstream_puts(oi->s, ptr);
	      kw_out(oi, 47);
	      kw_out(oi, 46);
	    }
	    ptr = dkfont_get_new_gs_file_name(i);
	    if(ptr) { 
	      if(first_in_line) {
	        kw_out(oi, 139);
	      } else {
	        kw_out(oi, 140);
	      } first_in_line = 0;
	      kw_out(oi, 46);
	      dkstream_puts(oi->s, ptr);
	      kw_out(oi, 46);
	    }
	  }
	  while((r = dkfont_one_font_get(o)) != NULL) {
	    ptr = dkfont_rep_get_pfb_source_name(r);
	    if(ptr) {	
	      font_found = 1;
	      if(first_in_line) {
	        kw_out(oi, 139);
	      } else {
	        kw_out(oi, 140);
	      } first_in_line = 0;
	      kw_out(oi, 46);
	      dkstream_puts(oi->s, ptr);
	      kw_out(oi, 46);
	      dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_INFO, 136, 137, ptr);
	      any_resource = 1;
	    }
	    ptr = dkfont_rep_get_ttf_source_name(r);
	    if(ptr) {	
	      font_found = 1;
	      if(first_in_line) {
	        kw_out(oi, 139);
	      } else {
	        kw_out(oi, 140);
	      } first_in_line = 0;
	      kw_out(oi, 46);
	      dkstream_puts(oi->s, ptr);
	      kw_out(oi, 46);
	      dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_INFO, 136, 137, ptr);
	      any_resource = 1;
	    }
	  }
	}
	kw_out(oi, 0);
	if(!font_found) {
	  back = 0;
	  /* ##### ERROR: No data found for font! */
	}
      }
    }
  }
  dksto_it_reset(oi->i_i);
  while((img = (dkfig_java_image *)dksto_it_next(oi->i_i)) != NULL) {
    if(img->filename) {
      if(!header_printed) {
        header_for_resources(oi);
      } header_printed = 1;
      last = NULL; ptr = img->filename;
      while(*ptr) {
        if((*ptr == '\\') || (*ptr == '/')) {
	  last = ptr;
	}
        ptr++;
      }
      if(last) last++;
      else last = img->filename;
      kw_out(oi, 141);
      kw_out(oi, 46);
      dkstream_puts(oi->s, last);
      kw_out(oi, 46);
      kw_out(oi, 138);
      kw_out(oi, 1);
      kw_out(oi, 46);
      dkstream_puts(oi->s, img->filename);
      kw_out(oi, 46);
      kw_out(oi, 0);
      dkfig_tool2_msg3(oi->c, DK_LOG_LEVEL_INFO, 136, 137, last);
      any_resource = 1;
    }
  }
  if(header_printed) {
    kw_out(oi, 0);
  }
  if(any_resource) {
    dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_INFO, 138);
  }
  return back;
}


/**	Create output.
	@param	oi	OI structure.
	@return	1 on success, 0 on error.
*/
static
int
output_pass DK_P1(OI *,oi) {
  int back = 1;
  
  kw_out(oi, 11); kw_out(oi, 0);
  kw_out(oi, 12); kw_out(oi, 0); kw_out(oi, 0);
  if(!write_needed_resources(oi)) { back = 0; }
  write_import_packages(oi);
  kw_out(oi, 0);
/* 2010/01/30: Larger comment section added. */
#if 0
  kw_out(oi, 13); kw_out(oi, 0);
#endif
  kw_out(oi, 0);
  section_out(oi, class_docu_1);
  if(!(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES)) {
    section_out(oi, class_docu_2);
  }
  section_out(oi, class_docu_3);
  kw_out(oi, 6);
  kw_out(oi, 1);
  print_class_name(oi);
  kw_out(oi, 1);
  kw_out(oi, 7);
  kw_out(oi, 1);
  kw_out(oi, 2);
  kw_out(oi, 0);
  section_out(oi, member_variables_1);
  if(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES) {
    section_out(oi, member_variables_2b);
  } else {
    section_out(oi, member_variables_2a);
  }
  section_out(oi, member_variables_3);
  wh_out(oi);
  strings_out(oi);
  variables_out(oi);
  if(!init_out(oi)) { back = 0; }
  if(!print_out(oi)) { back = 0; }
  if(!(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES)) {
    section_out(oi, member_functions_1);
  }
  section_out(oi, member_functions_2);
  if(!(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES)) {
    section_out(oi, member_functions_3);
  }
  section_out(oi, member_functions_4);
  if(((oi->c)->opt2) & DKFIG_OPT_DKLIBSJ_LIBRARIES) {
    kw_out(oi, 0); kw_out(oi, 0);
    section_out(oi, dktool_constructor_p1);
    kw_out(oi, 1); kw_out(oi, 1);
    kw_out(oi, 170);
    print_class_name(oi);
    kw_out(oi, 171); kw_out(oi, 0);
    section_out(oi, dktool_constructor_p2);
    kw_out(oi, 0); kw_out(oi, 0);
  }
  kw_out(oi, 3);
  kw_out(oi, 0);	
  return back;
}



/**	Java output driver function.
	@param	c	Conversion job structure.
	@return	1 on success, 0 on error.
*/
int
dkfig_output_java DK_P1(dk_fig_conversion *,c) {
  int back = 0;
  OI  *oi;
  
  oi = new_oi(c);
  if(oi) {	
    if(preparation_pass(oi)) {
      back = output_pass(oi);
    }
    cleanup_pass(oi);
    delete_oi(oi);
  } else {
    dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, 11);
  }
  
  return back;
}


