/*
Copyright (c) 2000-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.
*/



/**	@file	b2eps.c
	Conversion to EPS.
*/



/** Inside the b2eps.c module. */
#define B2EPS_C	1
#include "bmepsi.h"




#line 52 "b2eps.ctr"




/**	Keywords used in output.
*/
static char *kw[] = {
  /*   0 */	"\r\n",
  /*   1 */	" ",
  /*   2 */	"%!PS-Adobe",
  /*   3 */	"%%BoundingBox: ",
  /*   4 */	"EPSF",
  /*   5 */	"%%Creator: bmeps",
  /*   6 */	"%%Title: ",
  /*   7 */	"%%Pages: ",
  /*   8 */	"%%PageOrder: Ascend",
  /*   9 */	"%%DocumentData: Clean7Bit",
  /*  10 */	"%%EndComments",
  /*  11 */	"%%BeginProlog",
  /*  12 */	"%%EndProlog",
  /*  13 */	"%%BeginSetup",
  /*  14 */	"%%EndSetup",
  /*  15 */	"%%Trailer",
  /*  16 */	"%%EOF",
  /*  17 */	"unnamed",
  /*  18 */	"%%Page: ",
  /*  19 */	"showpage",
  /*  20 */	"gsave",
  /*  21 */	"grestore",
  /*  22 */	"13 dict begin",	/* see below for 13 */
  /*  23 */	"end",
  /*  24 */	"1 vmreclaim",
  /*  25 */	"translate",
  /*  26 */	"scale",
  /*  27 */	"sr",
  /*  28 */	"sg",
  /*  29 */	"sb",
  /*  30 */	"/",
  /*  31 */	"string",
  /*  32 */	"def",
  /*  33 */	"f",
  /*  34 */	"a",
  /*  35 */	"b",
  /*  36 */	"c",
  /*  37 */	"filter",
  /*  38 */	"/ASCIIHexDecode",
  /*  39 */	"/ASCII85Decode",
  /*  40 */	"currentfile",
  /*  41 */	"/LZWDecode",
  /*  42 */	"/FlateDecode",
  /*  43 */	"/RunLengthDecode",
  /*  44 */	"closefile",
  /*  45 */	"flushfile",
  /*  46 */	"currentdict",
  /*  47 */	"undef",
  /*  48 */	"{",
  /*  49 */	"}",
  /*  50 */	"exec",
  /*  51 */	"flushfile",
  /*  52 */	"/DeviceRGB",
  /*  53 */	"/DeviceGray",
  /*  54 */	"setcolorspace",
  /*  55 */	"readstring",
  /*  56 */	"pop",
  /*  57 */	"true",
  /*  58 */	"false",
  /*  59 */	"3",
  /*  60 */	"colorimage",
  /*  61 */	"image",
  /*  62 */	"sm",		/* for mask and level 1 gray */
  /*  63 */	"readhexstring",
  /*  64 */	"<<",
  /*  65 */	">>",
  /*  66 */	"/ImageType",
  /*  67 */	"/Width",
  /*  68 */	"/Height",
  /*  69 */	"/ImageMatrix",
  /*  70 */	"/MultipleDataSources",
  /*  71 */	"/DataSource",
  /*  72 */	"/BitsPerComponent",
  /*  73 */	"/Decode",
  /*  74 */	"[0 1]",
  /*  75 */	"[0 1 0 1 0 1]",
  /*  76 */	"/Interpolate",
  /*  77 */	"[",
  /*  78 */	"]",
  /*  79 */	"/DataDict",
  /*  80 */	"/MaskDict",
  /*  81 */	"/InterleaveType",
  /*  82 */	"/DCTDecode",
  /*  83 */	"rotate",
  /*  84 */	"-",
  /*  85 */	"/DeviceCMYK",
  /*  86 */	"[0 1 0 1 0 1 0 1]",
  /*  87 */	"[1 0 1 0 1 0 1 0]",
  /*  88 */	"newpath",
  /*  89 */	"moveto",
  /*  90 */	"lineto",
  /*  91 */	"closepath",
  /*  92 */	"fill",
  /*  93 */	"setgray",
  /*  94 */	"setrgbcolor",
  /*  95 */	"%%HiResBoundingBox: ",
  NULL
};

/**	Number of keywords.
*/
size_t lgt_kw = sizeof(kw)/sizeof(PCHAR);

/*	Why 13 entries in the dict:
	3 names for files (ASCIIHex/ASCII85, LZW/flate, run-length)
	3 names for strings (R, G, B)
	3 names for procedures (R, G, B)
	1 name  for string (image mask)
	1 name  for procedure (image mask)
*/




/**	Write keyword to output.
	@param	bj	Bmeps job.
	@param	n	Index of keyword to write.
*/
static
void
kw_out DK_P2(BJ *,bj, size_t, n)
{
  if(n < lgt_kw) {
    dkstream_puts(bj->os, kw[n]);
  }
}



/**	Show bounding box.
	@param	bj	Bmeps job.
*/
void
bmeps_eps_bb DK_P1(BJ *,bj)
{
  long fno;		/* Current frame number. */
  long x0;		/* Lower left x. */
  long y0;		/* Lower left y. */
  long x1;		/* Upper right x. */
  long y1;		/* Upper right y. */
  int have_data = 0;	/* Flag: Have data. */
  char buffer[128];	/* Buffer for bounding box output. */
  
  fno = bj->frame_s;
  x0 = y0 = x1 = y1 = 0UL;
  buffer[0] = 0x00;
  while(fno <= bj->frame_e) {
    
    if(dkbif_set_frame(bj->bif, fno)) {
      bmeps_tool_calculate_areas(bj);
      if(have_data) {
        if( (bj->trans).bb.x0 < x0 ) {
	  x0 = (bj->trans).bb.x0;
	}
	if( (bj->trans).bb.y0 < y0 ) {
	  y0 = (bj->trans).bb.y0;
	}
	if( (bj->trans).bb.x1 > x1 ) {
	  x1 = (bj->trans).bb.x1;
	}
	if( (bj->trans).bb.y1 > y1 ) {
	  y1 = (bj->trans).bb.y1;
	}
      } else {
        x0 = (bj->trans).bb.x0;
	x1 = (bj->trans).bb.x1;
	y0 = (bj->trans).bb.y0;
	y1 = (bj->trans).bb.y1;
        have_data = 1;
      } 
#if VEERSION_BEFORE_2006_11_04
      sprintf(buffer, "%ld %ld %ld %ld", x0, y0, x1, y1);
      dkstream_puts(bj->os, kw[3]);
      dkstream_puts(bj->os, buffer);
      dkstream_puts(bj->os, kw[0]);
#endif
    } else {
      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 71); bj->exval = 1;
    }
    fno++;
    
  }
  
  sprintf(buffer, "%ld %ld %ld %ld", x0, y0, x1, y1);
  kw_out(bj, 3); dkstream_puts(bj->os, buffer); kw_out(bj, 0);
  
  if(bmeps_tool_how_to_handle_bb(bj) == 1) {
    
    kw_out(bj, 95);
    dkstream_puts(bj->os, buffer);
    dkstream_puts_double(bj->os, 0.0);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, 0.0);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, ((bj->trans).iu.x1 - (bj->trans).iu.x0));
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, ((bj->trans).iu.y1 - (bj->trans).iu.y0));
    kw_out(bj, 0);
  }
  
}



/**	Translate and scale the image depending on the options.
	@param	bj	Bmeps job.
	@param	w	Ignored.
	@param	h	Ignored.
	@param	origw	Ignored.
	@param	origh	Ignored.
	@param	buffer	Ignored.
*/
static
void
translate_and_scale_if_necessary DK_P6( \
  BJ *,bj, unsigned long,w, unsigned long,h, \
  unsigned long,origw, unsigned long,origh, char *,buffer)
{
  switch(bmeps_tool_how_to_handle_bb(bj)) {
    case 2: {	/* paper size */
      if((bj->trans).must_rotate) {
        w = origh; h = origw;
      }
      
      dkstream_puts_double(bj->os, (bj->trans).iu.x0);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, (bj->trans).iu.y0);
      kw_out(bj, 1); kw_out(bj, 25); kw_out(bj, 0);
      dkstream_puts_double(bj->os, (bj->trans).sfx);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, (bj->trans).sfy);
      kw_out(bj, 1); kw_out(bj, 26); kw_out(bj, 0);
    } break;
    case 1: {	/* pHY chunk */
      if((bj->trans).must_scale) {
        
	if(0) {	/* remove these 5 lines if EPS output ok */
	  dkstream_puts_double(bj->os, (bj->trans).iu.x0);
	  kw_out(bj, 1);
	  dkstream_puts_double(bj->os, (bj->trans).iu.y0);
          kw_out(bj, 1); kw_out(bj, 25); kw_out(bj, 0);
	}
	
	dkstream_puts_double(bj->os, (bj->trans).sfx);
	kw_out(bj, 1);
	dkstream_puts_double(bj->os, (bj->trans).sfy);
        kw_out(bj, 1); kw_out(bj, 26); kw_out(bj, 0);
      }
    } break;
    default: {	/* 1:1 */
    } break;
  }
}



/**	Run non-DCT-passthrough conversion.
	@param	bj	Bmeps job.
*/
static
void
internal_conventional DK_P1(BJ *,bj)
{
  char buffer[128];		/* Buffer to construct output line. */
  char slbuffer[32];		/* Buffer for string and procedure defs. */
  unsigned long origw;		/* Original image width. */
  unsigned long origh;		/* original image height. */
  unsigned long w;		/* Image width after scale and rotate. */
  unsigned long h;		/* Image height after scale and rotate. */
  unsigned long sl;		/* String length (bits/8). */
  unsigned long iy;		/* Current row in output image. */
  unsigned long j;		/* Current Column in output image. */
  unsigned long x;		/* Current x position in input image. */
  unsigned long y;		/* Current y position in input image. */
  unsigned long bpc;		/* Bits per component for output. */
  unsigned long bits;		/* Bits for one output image row. */
  unsigned short bpcs;		/* Temporary bits per component for input. */
  int me = 0;			/* Flag: Math error. */
  int number_of_filters = 0;	/* Number of compression/encoding filters. */
  int i = 0;			/* Current data stream (0=r,1=g,2=b). */
  dk_stream_t *ofs = NULL;	/* Output stream to write to. */
  dk_bitshift_t *obs = NULL;	/* Bit shifter on output stream. */
  
  origw = w = dkbif_get_width(bj->bif);
  origh = h = dkbif_get_height(bj->bif);
  if((bj->trans).must_rotate) {
    w = origh; h = origw;
  }
  /*
  	calculations and setup
  */
  /* retrieve and correct bits per component */
  bpcs = dkbif_get_bits_per_component(bj->bif);
  bpcs = bmeps_tool_eps_output_bits(bpcs);
  bpc = (unsigned long)bpcs;
  /* no colored output for gray images */
  switch(dkbif_get_channels(bj->bif)) {
    case 1: case 2: {
      (bj->bo2)->opt &= (~(BMEPS_OPT_COLOR_OUTPUT));
      (bj->bo2)->opt &= (~(BMEPS_OPT_SEPARATED_DATA));
    } break;
  }
  /* level 1 allows 8 bits per pixel only */
  if((bj->bo2)->l == BMEPS_PS_LEVEL_1) {
    if(bpcs > 8) {
      bpcs = 8; bpc = 8UL;
    }
  }
  dkbif_set_bits_per_component(bj->bif, bpcs);
  /* calculate string size for separated data sources */
  bits = dkma_mul_ulong_ok(w, bpc, &me);
  sl = bits / 8UL;
  if(sl * 8UL < bits) sl = dkma_add_ulong_ok(sl, 1UL, &me);
  /* string length is restricted */
  if((me != 0) || (sl >= 16384UL)) {
    (bj->bo2)->opt &= (~(BMEPS_OPT_SEPARATED_DATA));
  }
  /* set up image mask and mask level */
  switch(dkbif_get_channels(bj->bif)) {
    case 2: case 4: {	/* alpha channel */
      
      if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
        dkbif_set_mask_trigger_level(bj->bif, (bj->bo2)->mtl);
      }
      if((bj->bo2)->opt & BMEPS_OPT_ALPHA_MIX) {
        
        dkbif_set_mixing(bj->bif,
	  (((bj->bo2)->opt & BMEPS_OPT_PREFER_SPEC_BG) ? 2 : 1),
	  (bj->bo2)->dbgr, (bj->bo2)->dbgg, (bj->bo2)->dbgb
	);
      }
    } break;
    default: {	/* no alpha channel */
      
      (bj->bo2)->opt &= (~(BMEPS_OPT_IMAGE_MASK));
      (bj->bo2)->opt &= (~(BMEPS_OPT_ALPHA_MIX));
      (bj->bo2)->opt &= (~(BMEPS_OPT_PREFER_SPEC_BG));
    } break;
  }
  if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
    (bj->bo2)->opt &= (~(BMEPS_OPT_SEPARATED_DATA));
  }
  /* final corrections on bo2 */
  bmeps_tool_correct_bo(bj->bo2);
  /* calculate number of file names in dictionary */
  number_of_filters = 1;
  if((bj->bo2)->enc & (BMEPS_ENCODING_FLATE)) {
    number_of_filters++;
  }
  if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
    number_of_filters++;
  }
  /*
  	image operator (and arguments)
  */
  /* file definitions */
  kw_out(bj, 48); kw_out(bj, 0);
  kw_out(bj, 20); kw_out(bj, 0);
  translate_and_scale_if_necessary(bj, w, h, origw, origh, buffer);
  if((bj->bo2)->opt & BMEPS_OPT_DICTIONARY) {
    kw_out(bj, 22); kw_out(bj, 0);
  }
  if((bj->bo2)->l > BMEPS_PS_LEVEL_1) {	/* PS level >= 2 */
    kw_out(bj, 30); kw_out(bj, 33); kw_out(bj, 34); kw_out(bj, 1);
    kw_out(bj, 40); kw_out(bj, 1);
    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
      kw_out(bj, 39);
    } else {
      kw_out(bj, 38);
    }
    kw_out(bj, 1); kw_out(bj, 37); kw_out(bj, 1); kw_out(bj, 32);
    kw_out(bj, 0);
    number_of_filters = 1;
    if((bj->bo2)->enc & (BMEPS_ENCODING_FLATE)) {
      kw_out(bj, 30); kw_out(bj, 33); kw_out(bj, 35); kw_out(bj, 1);
      kw_out(bj, 33); kw_out(bj, 34); kw_out(bj, 1);
      if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
        kw_out(bj, 42);
      } else {
        kw_out(bj, 41);
      }
      kw_out(bj, 1); kw_out(bj, 37); kw_out(bj, 1); kw_out(bj, 32);
      kw_out(bj, 0);
      number_of_filters++;
    }
    if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
      
      kw_out(bj, 30); kw_out(bj, 33);
      kw_out(bj, (34 + number_of_filters)); kw_out(bj, 1);
      kw_out(bj, 33); kw_out(bj, (33 + number_of_filters));
      kw_out(bj, 1); kw_out(bj, 43);
      kw_out(bj, 1); kw_out(bj, 37); kw_out(bj, 1); kw_out(bj, 32);
      kw_out(bj, 0);
      number_of_filters++;
    }
  } else {				/* PS level = 1 */
  }
  /* string and procedure definitions, only for separated sources */

  sprintf(slbuffer, "%lu", sl);
  if((bj->bo2)->l > BMEPS_PS_LEVEL_1) {
    if((bj->bo2)->opt & BMEPS_OPT_SEPARATED_DATA) {
      for(i = 0; i < 3; i++) {
        kw_out(bj, 30); kw_out(bj, 27+i); kw_out(bj, 1);
        dkstream_puts(bj->os, slbuffer); kw_out(bj, 1);
        kw_out(bj, 31); kw_out(bj, 1); kw_out(bj, 32); kw_out(bj, 0);
      }
    }
  } else {
    kw_out(bj, 30); kw_out(bj, 62); kw_out(bj, 1);
    dkstream_puts(bj->os, slbuffer); kw_out(bj, 1);
    kw_out(bj, 31); kw_out(bj, 1); kw_out(bj, 32); kw_out(bj, 0);
  }
  /* image operator */
  if((bj->bo2)->l > BMEPS_PS_LEVEL_1) {
    if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
      kw_out(bj, 52);
    } else {
      kw_out(bj, 53);
    }
    kw_out(bj, 1); kw_out(bj, 54); kw_out(bj, 0);
  }
  
  sprintf(buffer, "0 %lu", h);
  dkstream_puts(bj->os, buffer); kw_out(bj, 1);
  kw_out(bj, 25); kw_out(bj, 1);
  sprintf(buffer, "%lu %lu", w, h);
  dkstream_puts(bj->os, buffer); kw_out(bj, 1);
  kw_out(bj, 26); kw_out(bj, 0);
  if((bj->bo2)->opt & BMEPS_OPT_OPERATOR_DICTIONARY) {
    if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
      kw_out(bj, 64); kw_out(bj, 0);
      kw_out(bj, 66); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, 3UL); kw_out(bj, 0);
      kw_out(bj, 79); kw_out(bj, 0); kw_out(bj, 64); kw_out(bj, 0);
      /* datadict */
      kw_out(bj, 66); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, 1UL); kw_out(bj, 0);
      kw_out(bj, 67); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, w); kw_out(bj, 0);
      kw_out(bj, 68); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, h); kw_out(bj, 0);
      kw_out(bj, 69); kw_out(bj, 1);
      sprintf(buffer, "[%lu 0 0 -%lu 0 0]", w, h);
      dkstream_puts(bj->os, buffer); kw_out(bj, 0);
      kw_out(bj, 70); kw_out(bj, 1); kw_out(bj, 58);
      kw_out(bj, 0);
      kw_out(bj, 71); kw_out(bj, 1);
      kw_out(bj, 33);
      kw_out(bj, (33 + number_of_filters));
      kw_out(bj, 0);
      kw_out(bj, 72); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, (unsigned long)bpc); kw_out(bj, 0);
      kw_out(bj, 73); kw_out(bj, 1);
      kw_out(bj, (((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) ? 75 : 74));
      if(bmeps_tool_interpolate(bj))
      {
        kw_out(bj, 76); kw_out(bj, 1); kw_out(bj, 57); kw_out(bj, 0);
      }
      kw_out(bj, 0);
      kw_out(bj, 65); kw_out(bj, 0);
      kw_out(bj, 80); kw_out(bj, 0); kw_out(bj, 64); kw_out(bj, 0);
      /* maskdict */
      kw_out(bj, 66); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, 1UL); kw_out(bj, 0);
      kw_out(bj, 67); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, w); kw_out(bj, 0);
      kw_out(bj, 68); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, h); kw_out(bj, 0);
      kw_out(bj, 69); kw_out(bj, 1);
      dkstream_puts(bj->os, buffer); kw_out(bj, 0);
      kw_out(bj, 72); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, (unsigned long)bpc); kw_out(bj, 0);
      kw_out(bj, 73); kw_out(bj, 1); kw_out(bj, 74); kw_out(bj, 0);
      kw_out(bj, 65); kw_out(bj, 0);
      kw_out(bj, 81); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, 1UL); kw_out(bj, 0);
      kw_out(bj, 65); kw_out(bj, 0);
      kw_out(bj, 61); kw_out(bj, 0);
    } else {
      kw_out(bj, 64); kw_out(bj, 0);
      kw_out(bj, 66); kw_out(bj, 1); dkstream_puts_ul(bj->os, 1UL);
      kw_out(bj, 0);
      
      kw_out(bj, 67); kw_out(bj, 1); dkstream_puts_ul(bj->os, w); kw_out(bj, 1);
      kw_out(bj, 68); kw_out(bj, 1); dkstream_puts_ul(bj->os, h); kw_out(bj, 1);
      kw_out(bj, 69); kw_out(bj, 1);
      
      sprintf(buffer, "[%lu 0 0 -%lu 0 0]", w, h);
      dkstream_puts(bj->os, buffer); kw_out(bj, 0);
      if((bj->bo2)->opt & BMEPS_OPT_SEPARATED_DATA) {
        kw_out(bj, 70); kw_out(bj, 1); kw_out(bj, 57); kw_out(bj, 0);
      }
      
      kw_out(bj, 71); kw_out(bj, 1);
      if((bj->bo2)->opt & BMEPS_OPT_SEPARATED_DATA) {
        kw_out(bj, 77); kw_out(bj, 0);
	for(i = 0; i < 3; i++) {
	  kw_out(bj, 48);
	  kw_out(bj, 1);
	  kw_out(bj, 33); kw_out(bj, (33 + number_of_filters));
	  kw_out(bj, 1); kw_out(bj, (27 + i)); kw_out(bj, 1);
	  kw_out(bj, 55); kw_out(bj, 1); kw_out(bj, 56);
	  kw_out(bj, 1);
	  kw_out(bj, 49); kw_out(bj, 0);
	}
	kw_out(bj, 78);
	
      } else {
        kw_out(bj, 33); kw_out(bj, (33 + number_of_filters));
	
      } kw_out(bj, 0);
      
      kw_out(bj, 72); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, (unsigned long)bpc); kw_out(bj, 0);
      
      kw_out(bj, 73); kw_out(bj, 1);
      if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
        kw_out(bj, 75);
      } else {
        kw_out(bj, 74);
      } kw_out(bj, 0);
      
      if(bmeps_tool_interpolate(bj))
      {
        kw_out(bj, 76); kw_out(bj, 1); kw_out(bj, 57); kw_out(bj, 0);
      }
      kw_out(bj, 65); kw_out(bj, 0);
      kw_out(bj, 61); kw_out(bj, 0);
    }
  } else {
    sprintf(buffer, "%lu %lu %u [%lu 0 0 -%lu 0 0]", w, h, (unsigned)bpc, w, h);
    dkstream_puts(bj->os, buffer);
    
    if((bj->bo2)->opt & BMEPS_OPT_SEPARATED_DATA) {
      
      kw_out(bj, 0);
      for(i = 0; i < 3; i++) {
        
        kw_out(bj, 48);
	kw_out(bj, 1);
	kw_out(bj, 33); kw_out(bj, (33 + number_of_filters)); kw_out(bj, 1);
	kw_out(bj, (27 + i)); kw_out(bj, 1);
	kw_out(bj, 1); kw_out(bj, 55); kw_out(bj, 1); kw_out(bj, 56);
	kw_out(bj, 1);
	kw_out(bj, 49); kw_out(bj, 0);
      }
      kw_out(bj, 57); kw_out(bj, 1);
      kw_out(bj, 59); kw_out(bj, 1);
      kw_out(bj, 60); kw_out(bj, 0);
    } else {
      
      if((bj->bo2)->l > BMEPS_PS_LEVEL_1) {	/* PS level >= 2 */
        kw_out(bj, 1);
        kw_out(bj, 33); kw_out(bj, (33 + number_of_filters));
        kw_out(bj, 1);
        if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
          kw_out(bj, 58);
	  kw_out(bj, 1);
	  kw_out(bj, 59);
	  kw_out(bj, 1);
	  kw_out(bj, 60);
        } else {
	  kw_out(bj, 61);
        }
	kw_out(bj, 0);
      } else {					/* PS level = 1 */
        kw_out(bj, 0);
	kw_out(bj, 48);
	kw_out(bj, 1);
	kw_out(bj, 40);
	kw_out(bj, 1);
	kw_out(bj, 62);
	kw_out(bj, 1);
	kw_out(bj, 63);
	kw_out(bj, 1);
	kw_out(bj, 56);
	kw_out(bj, 1);
	kw_out(bj, 49);
	kw_out(bj, 0);
	kw_out(bj, 61);
	kw_out(bj, 0);
      }
    }
  }
  /*
  	cleanup
  */
  /* destroy strings */
  if(!((bj->bo2)->opt & BMEPS_OPT_DICTIONARY)) {
    if((bj->bo2)->opt & BMEPS_OPT_SEPARATED_DATA) {
      for(i = 0; i < 3; i++) {
        kw_out(bj, 46); kw_out(bj, 1);
        kw_out(bj, 30); kw_out(bj, 27+2-i); kw_out(bj, 1);
        kw_out(bj, 47); kw_out(bj, 0);
      }
    }
  }
  /* close files and destroy file definitions */
  if((bj->bo2)->l > BMEPS_PS_LEVEL_1) {	/* PS level >= 2 */
    i = number_of_filters;
    while(i > 0) {
      if(i == 1) {
        kw_out(bj, 33); kw_out(bj, (33+i)); kw_out(bj, 1);
        kw_out(bj, 51); kw_out(bj, 1);
      }
      kw_out(bj, 33); kw_out(bj, (33+i)); kw_out(bj, 1);
      kw_out(bj, 44); kw_out(bj, 0);
      i--;
    }
    if(!((bj->bo2)->opt & BMEPS_OPT_DICTIONARY)) {
      i = number_of_filters;
      while(i > 0) {
        kw_out(bj, 46); kw_out(bj, 1);
        kw_out(bj, 30); kw_out(bj, 33); kw_out(bj, (33+i));
        kw_out(bj, 1); kw_out(bj, 47); kw_out(bj, 0);
        i--;
      }
    }
  } else {				/* PS level = 1 */
  }
  if((bj->bo2)->opt & BMEPS_OPT_DICTIONARY) {
    kw_out(bj, 23);
    if((bj->bo2)->opt & BMEPS_OPT_VMRECLAIM) {
      kw_out(bj, 1); kw_out(bj, 24);
    }
    kw_out(bj, 0);
  }
  kw_out(bj, 21); kw_out(bj, 0);
  if((bj->bo2)->opt & BMEPS_OPT_SHOWPAGE) {
    kw_out(bj, 19); kw_out(bj, 0);
  }
  kw_out(bj, 49); kw_out(bj, 1); kw_out(bj, 50); kw_out(bj, 0);
  /*
  	data for image
  */
  ofs = dkof_open(bj->os, (1 + number_of_filters));
  if(ofs) {
    obs = NULL;
    dkof_set(ofs, 0, DK_OF_TYPE_BUFFERED);
    i = 1;
    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
      dkof_set(ofs, 1, DK_OF_TYPE_ASCII85);
    } else {
      dkof_set(ofs, 1, DK_OF_TYPE_ASCIIHEX);
    }
    i++;
    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
      dkof_set(ofs, i, DK_OF_TYPE_FLATE); i++;
    } else {
    }
    if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
      dkof_set(ofs, i, DK_OF_TYPE_PSRL); i++;
    }
    dkof_set_crnl(ofs, 1);
    if((bj->bo2)->l == BMEPS_PS_LEVEL_1) {
      dkof_set_finalizing(ofs, 0);
    }
    if(dkof_start_chunk(ofs)) {
      if((bpc != 8) || ((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK)) {
        obs = dkof_bs_open(ofs);
      }
      if((obs != NULL)
        || ((bpc == 8) && (!((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK))))
      {
        
#if INTERLEAVE_TYPE_1
        if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
	  /* mask data */
	  for(iy = 0UL; iy < h; iy++) {
	    for(j = 0UL; j < w; j++) {
	      y = iy; x = j;
	      if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
	      
	      if(obs) {
	        dkof_bs_put(obs, (dkbif_get_mask(bj->bif, x, y) ? 1 : 0), 1);
	      }
	    }
	    if(obs) {
	      dkof_bs_flush(obs);
	    }
	  }
	}
#endif
	if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
	  if((bj->bo2)->opt & BMEPS_OPT_SEPARATED_DATA) {
	    
	    /* color data separated */
	    for(iy = 0UL; iy < h; iy++) {
	      
	      
	      for(j = 0UL; j < w; j++) {
	         y = iy; x = j;
		 if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		 
		 if((bpc != 8) && (obs)) {
		   
		   dkof_bs_put(
		     obs, dkbif_get_red(bj->bif, x, y),
		     (unsigned short)bpc
		   );
		 } else {
		   
		   buffer[0] = (unsigned char)dkbif_get_red(bj->bif, x, y);
		   dkstream_write(ofs, buffer, 1);
		 }
	      }
	      if((bpc != 8) && (obs)) {
	        
	        dkof_bs_flush(obs);
	      }
	      
	      for(j = 0UL; j < w; j++) {
	         y = iy; x = j;
		 if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		 
		 if((bpc != 8) && (obs)) {
		   
		   dkof_bs_put(
		     obs, dkbif_get_green(bj->bif, x, y),
		     (unsigned short)bpc
		   );
		 } else {
		   
		   buffer[0] = (unsigned char)dkbif_get_green(bj->bif, x, y);
		   dkstream_write(ofs, buffer, 1);
		 }
	      }
	      if((bpc != 8) && (obs)) {
	        
	        dkof_bs_flush(obs);
	      }
	      
	      for(j = 0UL; j < w; j++) {
	         y = iy; x = j;
		 if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		 
		 if((bpc != 8) && (obs)) {
		   
		   dkof_bs_put(
		     obs, dkbif_get_blue(bj->bif, x, y),
		     (unsigned short)bpc
		   );
		 } else {
		   
		   buffer[0] = (unsigned char)dkbif_get_blue(bj->bif, x, y);
		   dkstream_write(ofs, buffer, 1);
		 }
	      }
	      if((bpc != 8) && (obs)) {
	        
	        dkof_bs_flush(obs);
	      }
	    }
	  } else {
	    /* color data per pixel, interleaved */
            for(iy = 0UL; iy < h; iy++) {
	      for(j = 0UL; j < w; j++) {
	         y = iy; x = j;
		 if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		 
		 if((bpc != 8) && (obs)) {
		   if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
		     dkof_bs_put(
		       obs, dkbif_get_mask(bj->bif, x, y),
		       (unsigned short)bpc
		     );
		   }
		   dkof_bs_put(
		     obs, dkbif_get_red(bj->bif, x, y),
		     (unsigned short)bpc
		   );
		   dkof_bs_put(
		     obs, dkbif_get_green(bj->bif, x, y),
		     (unsigned short)bpc
		   );
		   dkof_bs_put(
		     obs, dkbif_get_blue(bj->bif, x, y),
		     (unsigned short)bpc
		   );
		 } else {
		   /* 8 bits per pixel */
		   if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
		     buffer[0] = (unsigned char)dkbif_get_mask(bj->bif, x, y);
		     buffer[1] = (unsigned char)dkbif_get_red(bj->bif, x, y);
		     buffer[2] = (unsigned char)dkbif_get_green(bj->bif, x, y);
		     buffer[3] = (unsigned char)dkbif_get_blue(bj->bif, x, y);
		     dkstream_write(ofs, buffer, 4);
		   } else {
		     buffer[0] = (unsigned char)dkbif_get_red(bj->bif, x, y);
		     buffer[1] = (unsigned char)dkbif_get_green(bj->bif, x, y);
		     buffer[2] = (unsigned char)dkbif_get_blue(bj->bif, x, y);
		     dkstream_write(ofs, buffer, 3);
		   }
		 }
	      }
	      if((bpc != 8) && (obs)) {
	        dkof_bs_flush(obs);
	      }
	    }
	  }
	} else {
	  /* gray data */
	  for(iy = 0UL; iy < h; iy++) {
	    for(j = 0UL; j < w; j++) {
	      y = iy; x = j;
	      if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
	      
	      if((bpc != 8) && (obs)) {
	        if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
		  dkof_bs_put(
		    obs, dkbif_get_mask(bj->bif, x, y),
		    (unsigned short)bpc
		  );
		}
		dkof_bs_put(
		  obs, dkbif_get_gray(bj->bif, x, y),
		  (unsigned short)bpc
		);
	      } else {
	        if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
		  buffer[0] = (unsigned char)dkbif_get_mask(bj->bif, x, y);
		  buffer[1] = (unsigned char)dkbif_get_gray(bj->bif, x, y);
		  dkstream_write(ofs, buffer, 2);
		} else {
		  buffer[0] = (unsigned char)dkbif_get_gray(bj->bif, x, y);
		  dkstream_write(ofs, buffer, 1);
		}
	      }
	    }
	    if((bpc != 8) && (obs)) {
	      dkof_bs_flush(obs);
	    }
	  }
	}
      } else {
	bmeps_tool_error_memory(bj); bj->exval = 1;
      }
      if(obs) { dkof_bs_close(obs); obs = NULL; }
      dkof_end_chunk(ofs);
    } else {
      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 68); bj->exval = 1;
    }
    dkof_close(ofs); ofs = NULL;
  } else {
    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70); bj->exval = 1;
  }
  
}



#if 0
/**	Transfer input file directly.
	@param	bj	Bmeps job.
	@param	ofs	Output filter stream.
*/
static
void
transfer_file_contents DK_P2(BJ *,bj, dk_stream_t *,ofs)
{
  char ibuffer[512];		/* Input buffer. */
  size_t l1;			/* Line size 1. */
  size_t l2;			/* Line size 1. */
  int cc = 0;			/* Flag: Can continue. */
  int write_error = 0;		/* Flag: Write error. */
  
  if(0) {	
  } else {	
    rewind(bj->inf);
    cc = 1;
    while(cc) {
      l1 = fread((void *)ibuffer, 1, 512, bj->inf);
      if(l1 > 0) {
        l2 = dkstream_write(ofs, ibuffer, l1);
	if(l2 < l1) {
	  cc = 0;
	  write_error = 1;
	  
	}
      } else {
        cc = 0;
      }
    }
  }
  if(write_error) {
    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 53);
  }
  
}
#endif



/**	Convert to EPS, use DCT-encoded data directly.
	@param	bj	Bmeps job.
*/
static
void
internal_dct DK_P1(BJ *,bj)
{
#if DK_HAVE_JPEGLIB_H
  unsigned long w;		/* Output image width. */
  unsigned long h;		/* Output image height. */
  unsigned long origw;		/* Input image width. */
  unsigned long origh;		/* Input image height. */
  unsigned long bpc;		/* Bits per component (output). */
  unsigned short bpcs;		/* Bits per component (input). */
  dk_stream_t *ofs = NULL;	/* Output filtering stream. */
  char buffer[256];		/* Buffer to construct output lines .*/
  
  origw = w = dkbif_get_width(bj->bif);
  origh = h = dkbif_get_height(bj->bif);
  bpcs = dkbif_get_bits_per_component(bj->bif);
  bpc = (unsigned long)bpcs;
  kw_out(bj, 48); kw_out(bj, 0);
  kw_out(bj, 20); kw_out(bj, 0);
  switch(bmeps_tool_how_to_handle_bb(bj)) {
    case 2: {	/* paper size */
      dkstream_puts_double(bj->os, (bj->trans).iu.x0);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, (bj->trans).iu.y1);
      kw_out(bj, 1); kw_out(bj, 25); kw_out(bj, 1);
      kw_out(bj, 84);
      dkstream_puts_ul(bj->os, 90UL); kw_out(bj, 1); kw_out(bj, 83);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, (bj->trans).sfy);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, (bj->trans).sfx);
      kw_out(bj, 1); kw_out(bj, 26); kw_out(bj, 0);
    } break;
    case 1: {	/* resolution chunk */
      if(0) {	/* remove these 5 lines if output is ok */
	dkstream_puts_double(bj->os, (bj->trans).iu.x0);
	kw_out(bj, 1);
	dkstream_puts_double(bj->os, (bj->trans).iu.y0);
        kw_out(bj, 1); kw_out(bj, 25); kw_out(bj, 0);
      }
      dkstream_puts_double(bj->os, (bj->trans).sfx);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, (bj->trans).sfy);
      kw_out(bj, 1); kw_out(bj, 26); kw_out(bj, 0);
    } break;
  }
  dkstream_puts_ul(bj->os, 0UL); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, h); kw_out(bj, 1);
  kw_out(bj, 25); kw_out(bj, 0);
  dkstream_puts_ul(bj->os, w); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, h); kw_out(bj, 1);
  kw_out(bj, 26); kw_out(bj, 0);
  if((bj->bo2)->opt & BMEPS_OPT_DICTIONARY) {
    kw_out(bj, 22); kw_out(bj, 0);
  }
  kw_out(bj, 30); kw_out(bj, 33); kw_out(bj, 34);
  kw_out(bj, 1); kw_out(bj, 40); kw_out(bj, 1);
  if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
    kw_out(bj, 39);
  } else {
    kw_out(bj, 38);
  }
  kw_out(bj, 1);  kw_out(bj, 37); kw_out(bj, 1);
  kw_out(bj, 32); kw_out(bj, 0);
  kw_out(bj, 30); kw_out(bj, 33); kw_out(bj, 35); kw_out(bj, 1);
  kw_out(bj, 33); kw_out(bj, 34); kw_out(bj, 1);
  kw_out(bj, 64); kw_out(bj, 1); kw_out(bj, 65); kw_out(bj, 1);
  kw_out(bj, 82); kw_out(bj, 1); kw_out(bj, 37); kw_out(bj, 1);
  kw_out(bj, 32); kw_out(bj, 0);
  if(((bj->bif)->d).jpg.jpgana.components > 0x01) {
    if(((bj->bif)->d).jpg.jpgana.components == 0x03) {
      kw_out(bj, 52);
    } else {
      kw_out(bj, 85);
    }
  } else {
    kw_out(bj, 53);
  }
  kw_out(bj, 1); kw_out(bj, 54); kw_out(bj, 0);
  kw_out(bj, 64); kw_out(bj, 0);
  kw_out(bj, 66); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, 1UL); kw_out(bj, 0);
  kw_out(bj, 67); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, w); kw_out(bj, 0);
  kw_out(bj, 68); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, h); kw_out(bj, 0);
  sprintf(buffer, "[%lu 0 0 -%lu 0 0]", w, h);
  kw_out(bj, 69); kw_out(bj, 1); dkstream_puts(bj->os, buffer); kw_out(bj, 0);
  kw_out(bj, 70); kw_out(bj, 1); kw_out(bj, 58); kw_out(bj, 0);
  kw_out(bj, 71); kw_out(bj, 1); kw_out(bj, 33); kw_out(bj, 35); kw_out(bj, 0);
  kw_out(bj, 72); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, 8UL); kw_out(bj, 0);
  kw_out(bj, 73); kw_out(bj, 1);
  if(((bj->bif)->d).jpg.jpgana.components > 0x01) {
    if(((bj->bif)->d).jpg.jpgana.components == 0x03) {
      kw_out(bj, 75);
    } else {
      if(((bj->bif)->d).jpg.jpgana.adobe_marker_found) {
        kw_out(bj, 87);
      } else {
        kw_out(bj, 86);
      }
    }
  } else {
    kw_out(bj, 74);
  } kw_out(bj, 0);
  kw_out(bj, 65); kw_out(bj, 0);
  kw_out(bj, 61); kw_out(bj, 0);
  kw_out(bj, 33); kw_out(bj, 35); kw_out(bj, 1);
  kw_out(bj, 44); kw_out(bj, 0);
  kw_out(bj, 33); kw_out(bj, 34); kw_out(bj, 1);
  kw_out(bj, 45); kw_out(bj, 1);
  kw_out(bj, 33); kw_out(bj, 34); kw_out(bj, 1);
  kw_out(bj, 44); kw_out(bj, 0);
  if((bj->bo2)->opt & BMEPS_OPT_SHOWPAGE) {
    kw_out(bj, 19); kw_out(bj, 0);
  }
  if((bj->bo2)->opt & BMEPS_OPT_DICTIONARY) {
    kw_out(bj, 23);
    if((bj->bo2)->opt & BMEPS_OPT_VMRECLAIM) {
      kw_out(bj, 1); kw_out(bj, 24);
    }
    kw_out(bj, 0);
  }
  kw_out(bj, 21); kw_out(bj, 0);
  kw_out(bj, 49); kw_out(bj, 1);
  kw_out(bj, 50); kw_out(bj, 0);
  /* image data */
  ofs = dkof_open(bj->os, 2);
  if(ofs) {
    dkof_set(ofs, 0, DK_OF_TYPE_BUFFERED);
    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
      dkof_set(ofs, 1, DK_OF_TYPE_ASCII85);
    } else {
      dkof_set(ofs, 1, DK_OF_TYPE_ASCIIHEX);
    }
    dkof_set_crnl(ofs, 1);
    if(dkof_start_chunk(ofs)) {
      /* transfer_file_contents(bj, ofs); */
      rewind(bj->inf);
      /*
      ((bj->bif)->d).jpg.jpgana.is_printing = 1;
      ((bj->bif)->d).jpg.jpgana.inputfile = bj->inf;
      ((bj->bif)->d).jpg.jpgana.os = ofs;
      ((bj->bif)->d).jpg.jpgana.a = NULL;
      dkbif_jfif_analyze(&(((bj->bif)->d).jpg.jpgana));
      */
      dkbif_jfif_transfer(ofs, bj->inf);

      if(!dkof_end_chunk(ofs)) {
	bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 69);
	bj->exval = 1;
      }
    } else {
       bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 68);
       bj->exval = 1;
    }
    dkof_close(ofs); ofs = NULL;
  } else {
    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70);
    bj->exval = 1;
  }
  
#endif
}



/**	Create EPS draft.
	@param	bj	Bmeps job.
*/
static
void
internal_draft DK_P1(BJ *,bj)
{
  DI dinner;	/* Inner coordinates. */
  DI douter;	/* Outer coordinates. */
  double r = 0.7;	/* Red. */
  double g = 0.0;	/* Green. */
  double b = 0.0;	/* Blue. */
  double gray = 0.9;	/* Gray. */
  double black = 0.0;	/* Black. */
  
  if(bmeps_tool_calc_di(bj, &dinner, &douter, 0.05, 0.01)) {
    /* outer rectangle */
    /* --- 0.8 setgray */
    if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
      dkstream_puts_double(bj->os, r);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, g);
      kw_out(bj, 1);
      dkstream_puts_double(bj->os, b);
      kw_out(bj, 1);
      kw_out(bj, 94);
    } else {
      dkstream_puts_double(bj->os, black); kw_out(bj, 1);
      kw_out(bj, 93);
    } kw_out(bj, 0);
    /* --- newpath */
    kw_out(bj, 88); kw_out(bj, 0);
    /* --- x0 y0 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0);
    kw_out(bj, 1);
    kw_out(bj, 89); kw_out(bj, 0);
    /* --- x1 y0 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x0 y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- closepath */
    kw_out(bj, 91); kw_out(bj, 1);
    /* --- fill */
    kw_out(bj, 92); kw_out(bj, 0);
    /* middle rectangle */
    /* --- 0.8 setgray */
    dkstream_puts_double(bj->os, gray); kw_out(bj, 1);
    kw_out(bj, 93); kw_out(bj, 0);
    /* --- newpath */
    kw_out(bj, 88); kw_out(bj, 0);
    /* --- x0 y0 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + douter.d);
    kw_out(bj, 1);
    kw_out(bj, 89); kw_out(bj, 0);
    /* --- x1 y0 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x0 y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- closepath */
    kw_out(bj, 91); kw_out(bj, 1);
    /* --- fill */
    kw_out(bj, 92); kw_out(bj, 0);
    /* inner rectangle */
    /* --- 1.0 setgray */
    dkstream_puts_double(bj->os, 1.0); kw_out(bj, 1);
    kw_out(bj, 93); kw_out(bj, 0);
    /* --- newpath */
    kw_out(bj, 88); kw_out(bj, 0);
    /* --- x0 y0 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + dinner.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + dinner.d);
    kw_out(bj, 1);
    kw_out(bj, 89); kw_out(bj, 0);
    /* --- x1 y0 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - dinner.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + dinner.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - dinner.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - dinner.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x0 y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + dinner.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - dinner.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- closepath */
    kw_out(bj, 91); kw_out(bj, 1);
    /* --- fill */
    kw_out(bj, 92); kw_out(bj, 0);
    /* outer diagonal lines */
    /* --- 0.8 setgray */
    dkstream_puts_double(bj->os, gray); kw_out(bj, 1);
    kw_out(bj, 93); kw_out(bj, 0);
    /* --- newpath */
    kw_out(bj, 88); kw_out(bj, 0);
    /* --- x0 y0 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + douter.d);
    kw_out(bj, 1);
    kw_out(bj, 89); kw_out(bj, 0);
    /* --- x0+deltax y0 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + dinner.deltax + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + douter.d);
    kw_out(bj, 1); kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y1-deltay moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - dinner.deltay - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 1); kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y1 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 1); kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1-deltax y1 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - dinner.deltax - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 1); kw_out(bj, 90); kw_out(bj, 0);
    /* --- x0 y0+deltay moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + dinner.deltay + douter.d);
    kw_out(bj, 1);
    kw_out(bj, 1); kw_out(bj, 90); kw_out(bj, 0);
    /* --- closepath */
    kw_out(bj, 91); kw_out(bj, 1);
    /* --- fill */
    kw_out(bj, 92); kw_out(bj, 0);
    /* --- newpath */
    kw_out(bj, 88); kw_out(bj, 0);
    /* --- x0 y1 moveto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 89); kw_out(bj, 0);
    /* --- x0+deltax y1 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + dinner.deltax + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y0+deltay lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + dinner.deltay - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1 y0 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x1-deltax y0 lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x1 - dinner.deltax - douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y0 + douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- x0 y1-deltay lineto */
    dkstream_puts_double(bj->os, (bj->trans).iu.x0 + douter.d);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, (bj->trans).iu.y1 - dinner.deltay - douter.d);
    kw_out(bj, 1);
    kw_out(bj, 90); kw_out(bj, 0);
    /* --- closepath */
    kw_out(bj, 91); kw_out(bj, 1);
    /* --- fill */
    kw_out(bj, 92); kw_out(bj, 0);
    if((bj->bo2)->opt & BMEPS_OPT_SHOWPAGE) {
      kw_out(bj, 19); kw_out(bj, 0);
    }
  } else {
    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 72); bj->exval = 1;
  }
  
}



/**	Run conversion
	@param	bj	Bmeps job.
	@param	howto	0=normal,1=dct,2=draft.
*/
static
void
run_internal DK_P2(BJ *,bj, int,howto)
{
  BO bo;		/* Bmeps option set. */
  int l = 2;		/* EPS level. */
  size_t kwno;		/* Index to print multiple keywords. */
  long frameno;		/* Index to process multiple frames. */
  char buffer[64];	/* Buffer to print numbers. */
  char *ptr;		/* Last part of file name. */
  
  if(bj->os) {
    dkstream_set_double_no_exponent(bj->os, 1);
  }
  bj->bo2 = &bo;
  dkmem_cpy(bj->bo2, bj->bo, sizeof(BO));
  if(bj->frame_s != bj->frame_e) {
    (bj->bo2)->opt |= BMEPS_OPT_SHOWPAGE;
  }
  switch((bj->bo2)->l) {
    case BMEPS_PS_LEVEL_1: l = 1; break;
    case BMEPS_PS_LEVEL_3: l = 3; break;
    default: l = 2; break;
  }
  sprintf(buffer, "-%d.0",  l);
  kw_out(bj, 2);
  dkstream_puts(bj->os, buffer);
  if(((bj->bo2)->opt & BMEPS_OPT_DSC)
     && (!((bj->bo2)->opt & BMEPS_OPT_SHOWPAGE)))
  {
    kw_out(bj, 1); kw_out(bj, 4);
    dkstream_puts(bj->os, buffer);
  }
  kw_out(bj, 0);
  bmeps_eps_bb(bj);
  if((bj->bo2)->opt & BMEPS_OPT_DSC) {
    for(kwno = 5; kwno < 15; kwno++) {
      kw_out(bj, kwno);
      switch((int)kwno) {
        case 6: {
	  if(bj->infname) {
	    ptr = dksf_get_last_filename(bj->infname);
	    if(ptr) {
	      dkstream_puts(bj->os, ptr);
	    } else {
	      kw_out(bj, 17);
	    }
	  } else {
	    kw_out(bj, 17);
	  }
	} break;
	case 7: {
	  sprintf(
	    buffer, "%lu",
	    (1UL + bj->frame_e - bj->frame_s)
	  ); dkstream_puts(bj->os, buffer);
	} break;
      }
      kw_out(bj, 0);
    }
  }
  for(frameno = bj->frame_s; frameno <= bj->frame_e; frameno++) {
    
    if(dkbif_set_frame(bj->bif, frameno)) {
      bmeps_tool_calculate_areas(bj);
      if((bj->bo2)->opt & BMEPS_OPT_DSC) {
        unsigned long ul;
        ul = frameno - (bj->frame_s) + 1UL;
        sprintf(buffer, "%lu %lu", ul, ul);
        kw_out(bj, 18); dkstream_puts(bj->os, buffer); kw_out(bj, 0);
      }
      switch(howto) {
        case 1: {
#if DK_HAVE_JPEGLIB_H
          internal_dct(bj);
#else
	  internal_conventional(bj);
#endif
        } break;
        case 2: {
          internal_draft(bj);
        } break;
        default: {
          internal_conventional(bj);
        } break;
      }
    }
  }
  if((bj->bo2)->opt & BMEPS_OPT_DSC) {
    for(kwno = 15; kwno < 17; kwno++) { kw_out(bj, kwno); kw_out(bj, 0); }
  }
  bj->bo2 = NULL;
  
}




/**	Convert to PS/EPS, use traditional encoding (no DCT).
	@param	bj	Bmeps job.
*/
void
bmeps_eps_conventional DK_P1(BJ *,bj)
{
  
  run_internal(bj, 0);
  
}



/**	Convert to PS/EPS, use DCT-encoded data from
	JPEG file directly.
	@param	bj	Bmeps job.
*/
void
bmeps_eps_dct DK_P1(BJ *,bj)
{
  
  run_internal(bj, 1);
  
}



/**	Create PS/EPS draft.
	@param	bj	Bmeps job.
*/
void
bmeps_eps_draft DK_P1(BJ *,bj)
{
  
  run_internal(bj, 2);
  
}



