~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/rinkj/rinkj-epson870.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied, modified
8
 
   or distributed except as expressly authorized under the terms of that
9
 
   license.  Refer to licensing information at http://www.artifex.com/
10
 
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11
 
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
 
*/
13
 
 
14
 
/*$Id: rinkj-epson870.c 8865 2008-07-22 21:03:07Z ray $ */
15
 
/* A Rinkj driver for a number of variable-dot Epson devices. */
16
 
 
17
 
#include <stdlib.h>
18
 
#include <stdio.h>
19
 
#include <string.h>
20
 
 
21
 
#include "rinkj-byte-stream.h"
22
 
#include "rinkj-device.h"
23
 
#include "rinkj-config.h"
24
 
#include "rinkj-epson870.h"
25
 
 
26
 
typedef struct _RinkjEscp RinkjEscp;
27
 
 
28
 
struct _RinkjEscp {
29
 
  RinkjDevice super;
30
 
  RinkjByteStream *out;
31
 
  int width;
32
 
  int height;
33
 
  int y;
34
 
 
35
 
  char *manufacturer;
36
 
  char *model;
37
 
 
38
 
  int num_chan;
39
 
  int bps;       /* bits per sample */
40
 
 
41
 
  int xres;      /* resolution of input image */
42
 
  int yres;
43
 
 
44
 
  int head_bps;
45
 
  int head_xres; /* x resolution of printhead in dpi */
46
 
  int head_yres; /* y resolution of printhead in dpi */
47
 
 
48
 
  /* Number of passes for a single scanline */
49
 
  int passes_per_scan;
50
 
 
51
 
  /* parameters for controlling microweaving */
52
 
  int spacing;
53
 
  int n_pins;
54
 
 
55
 
  int plane_offsets[6];
56
 
  int max_offset;
57
 
 
58
 
  char *buf;
59
 
  unsigned char *buf_linevalid;
60
 
  int bufheight;
61
 
  int rowstride;
62
 
  int planestride;
63
 
  int pass;
64
 
 
65
 
  int vertpos; /* for ESC ( v */
66
 
 
67
 
  /* parameters passed into ESCP2 */
68
 
  int autocut;
69
 
  int blankskip;
70
 
  int microdot;
71
 
  int unidir;
72
 
  int printer_weave;
73
 
};
74
 
 
75
 
static int
76
 
rinkj_escp_set (RinkjDevice *self, const char *config)
77
 
{
78
 
  RinkjEscp *z = (RinkjEscp *)self;
79
 
  const char *p, *next;
80
 
  char *key, *val;
81
 
 
82
 
  for (p = config; (key = rinkj_config_keyval (p, &val, &next)); p = next)
83
 
    {
84
 
      if (!strcmp (key, "Resolution"))
85
 
        {
86
 
          char *p;
87
 
 
88
 
          z->xres = atoi (val);
89
 
          p = strchr (val, 'x');
90
 
          if (p != NULL)
91
 
            z->yres = atoi (p + 1);
92
 
          else
93
 
            z->yres = z->xres;
94
 
#ifdef VERBOSE
95
 
          fprintf (stderr, "Resolution = %d x %d\n", z->xres, z->yres);
96
 
#endif
97
 
        }
98
 
      else if (!strcmp (key, "Manufacturer"))
99
 
        {
100
 
          if (z->manufacturer)
101
 
            free (z->manufacturer);
102
 
          z->manufacturer = val;
103
 
          val = NULL;
104
 
        }
105
 
      else if (!strcmp (key, "Model"))
106
 
        {
107
 
          if (z->model)
108
 
            free (z->model);
109
 
          z->model = val;
110
 
          val = NULL;
111
 
        }
112
 
      else if (!strcmp (key, "BitsPerSample"))
113
 
        {
114
 
          z->bps = atoi (val);
115
 
#ifdef VERBOSE
116
 
          fprintf (stderr, "BitsPerSample = %d\n", z->bps);
117
 
#endif
118
 
        }
119
 
      else if (!strcmp (key, "NumChan"))
120
 
        {
121
 
          /* This is in params, but should become a setting. */
122
 
          z->num_chan = atoi (val);
123
 
#ifdef VERBOSE
124
 
          fprintf (stderr, "NumChan = %d\n", z->num_chan);
125
 
#endif
126
 
        }
127
 
      else if (!strcmp (key, "PrinterWeave"))
128
 
        {
129
 
          z->printer_weave = atoi (val);
130
 
        }
131
 
      else if (!strcmp (key, "Microdot"))
132
 
        {
133
 
          z->microdot = atoi (val);
134
 
        }
135
 
      else if (!strcmp (key, "Unidirectional"))
136
 
        {
137
 
          z->unidir = atoi (val);
138
 
        }
139
 
      else if (!strcmp (key, "AutoCut"))
140
 
        {
141
 
          z->autocut = atoi (val);
142
 
        }
143
 
      else if (!strcmp (key, "BlankSkip"))
144
 
        {
145
 
          z->blankskip = atoi (val);
146
 
        }
147
 
      free (key);
148
 
      if (val)
149
 
        free (val);
150
 
    }
151
 
  return 0;
152
 
}
153
 
 
154
 
static int
155
 
rinkj_escp_ytop (RinkjEscp *z, int pass, int *p_x_pass)
156
 
{
157
 
  int ytop;
158
 
  int x_pass, y_pass;
159
 
  int passes_per_scan = z->passes_per_scan;
160
 
  int spacing = z->spacing;
161
 
  int n_cycle = spacing * passes_per_scan;
162
 
  int mod_pass = pass % n_cycle;
163
 
  int y_modulo;
164
 
  const int four[4] = { 0, 3, 1, 2 };
165
 
  const int six[6] = { 0, 3, 2, 5, 1, 4 };
166
 
 
167
 
  ytop = mod_pass * z->n_pins * spacing / n_cycle;
168
 
#if 1
169
 
  x_pass = mod_pass / spacing;
170
 
  y_pass = mod_pass % spacing;
171
 
  if (passes_per_scan == 4)
172
 
    x_pass = four[x_pass];
173
 
#else
174
 
  x_pass = mod_pass % passes_per_scan;
175
 
  y_pass = (mod_pass / passes_per_scan + x_pass * (spacing - 1)) % spacing;
176
 
#endif
177
 
 
178
 
  switch (spacing)
179
 
    {
180
 
    case 4:
181
 
      y_modulo = four[y_pass];
182
 
      break;
183
 
    case 6:
184
 
      y_modulo = six[y_pass];
185
 
      break;
186
 
    case 8:
187
 
      y_modulo = y_pass * 3;
188
 
      break;
189
 
    default:
190
 
      y_modulo = y_pass;
191
 
      break;
192
 
    }
193
 
 
194
 
  ytop += (spacing + y_modulo - ytop % spacing) % spacing;
195
 
  ytop += (pass / n_cycle) * spacing * z->n_pins;
196
 
 
197
 
  if (spacing == 4 && passes_per_scan == 4 && z->n_pins == 96)
198
 
    {
199
 
      const int sixteen[] = { 0, 3, 1, 0, 3, 1, 2, 3, 1, 2, 0, 1, 2, 0, 3, 2 };
200
 
      x_pass = sixteen[mod_pass & 15];
201
 
      ytop = pass * 23;
202
 
    }
203
 
 
204
 
#ifdef VERBOSE
205
 
  fprintf (stderr, "pass %d: ytop = %d, x_pass = %d\n", pass, ytop, x_pass);
206
 
#endif
207
 
 
208
 
  if (p_x_pass)
209
 
    *p_x_pass = x_pass;
210
 
  return ytop;
211
 
}
212
 
 
213
 
static int
214
 
rinkj_epson_headres (RinkjEscp *z, int baseres)
215
 
{
216
 
  return rinkj_byte_stream_printf (z->out, "\033(D\004%c%c%c%c%c", 0,
217
 
                                   baseres & 255, baseres >> 8,
218
 
                                   baseres / z->head_yres,
219
 
                                   baseres / z->head_xres);
220
 
}
221
 
 
222
 
static int
223
 
rinkj_epson_units (RinkjEscp *z, int xres, int yres, int baseres)
224
 
{
225
 
  return rinkj_byte_stream_printf (z->out, "\033(U\005%c%c%c%c%c%c", 0,
226
 
                                   baseres / yres,
227
 
                                   baseres / yres,
228
 
                                   baseres / xres,
229
 
                                   baseres & 255, baseres >> 8);
230
 
}
231
 
 
232
 
static int
233
 
rinkj_epson_set_common (RinkjEscp *z)
234
 
{
235
 
  int status = 0;
236
 
 
237
 
  if (z->printer_weave >= 0)
238
 
    /* set microweave */
239
 
    status = rinkj_byte_stream_printf (z->out, "\033(i\001%c%c", 0,
240
 
                                       z->printer_weave);
241
 
 
242
 
  if (status == 0 && z->unidir >= 0)
243
 
    /* set unidirectional */
244
 
    status = rinkj_byte_stream_printf (z->out, "\033U%c", z->unidir);
245
 
 
246
 
  if (status == 0 && z->microdot >= 0)
247
 
    /* set dot size */
248
 
    status = rinkj_byte_stream_printf (z->out, "\033(e\002%c%c%c", 0, 0,
249
 
                                       z->microdot);
250
 
 
251
 
  return status;
252
 
}
253
 
 
254
 
/**
255
 
 * Spit out a command string to resemble the gimp-print output as much
256
 
 * as possible.
257
 
 **/
258
 
static int
259
 
rinkj_epson870_init (RinkjDevice *self, const RinkjDeviceParams *params)
260
 
{
261
 
  RinkjEscp *z = (RinkjEscp *)self;
262
 
 
263
 
  rinkj_byte_stream_printf (z->out,
264
 
                            "%c%c%c\033\001@EJL 1284.4\n", 0, 0, 0);
265
 
  rinkj_byte_stream_printf (z->out, "@EJL     \n\033@\033@");
266
 
 
267
 
  /* remote string goes here, but is probably optional */
268
 
 
269
 
  /* set graphics mode */
270
 
  rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
271
 
 
272
 
  /* set units to 1/720" */
273
 
  rinkj_byte_stream_printf (z->out, "\033(U\005%c\002\002\002\240\005", 0);
274
 
 
275
 
  rinkj_epson_set_common(z);
276
 
 
277
 
  /* set page length to about 22.377 inches */
278
 
  rinkj_byte_stream_printf (z->out, "\033(C\002%cx\037", 0);
279
 
 
280
 
  /* ESC ( c */
281
 
 
282
 
  /* ESC ( S */
283
 
 
284
 
  /* set resolution to 360 x 120 dpi - should probably generate this
285
 
     string from head_xres and head_yres */
286
 
  rinkj_byte_stream_printf (z->out, "\033(D\004%c@8x(", 0);
287
 
 
288
 
  /* ESC ( v */
289
 
 
290
 
  /* ESC \ */
291
 
  return 0;
292
 
}
293
 
 
294
 
/**
295
 
 * Spit out a command string to resemble the gimp-print output as much
296
 
 * as possible.
297
 
 **/
298
 
static int
299
 
rinkj_epson2200_init (RinkjDevice *self, const RinkjDeviceParams *params)
300
 
{
301
 
  RinkjEscp *z = (RinkjEscp *)self;
302
 
 
303
 
  rinkj_byte_stream_printf (z->out,
304
 
                            "%c%c%c\033\001@EJL 1284.4\n", 0, 0, 0);
305
 
  rinkj_byte_stream_printf (z->out, "@EJL     \n\033@\033@");
306
 
 
307
 
  /* remote string */
308
 
  rinkj_byte_stream_printf( z->out,
309
 
                            "\033(R%c%c%cREMOTE1", 8, 0, 0);
310
 
  rinkj_byte_stream_printf( z->out,
311
 
                            "PP\003%c%c\002%cPH\002%c%c\001SN\003%c%c\004k",
312
 
                            0, 0, 0, 0, 0, 0, 0);
313
 
  rinkj_byte_stream_printf( z->out,
314
 
                            "\033%c%c%c", 0, 0, 0);
315
 
 
316
 
  /* set graphics mode */
317
 
  rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
318
 
 
319
 
  rinkj_epson_units(z, z->xres, z->yres, 2880);
320
 
 
321
 
  rinkj_epson_set_common(z);
322
 
 
323
 
  /* set page length to 40 inches */
324
 
  rinkj_byte_stream_printf (z->out, "\033(C\002%c\200p", 0);
325
 
 
326
 
  /* ESC ( c */
327
 
 
328
 
  /* ESC ( S */
329
 
 
330
 
  rinkj_epson_headres (z, 2880);
331
 
 
332
 
  /* ESC ( v */
333
 
 
334
 
  /* ESC \ */
335
 
  return 0;
336
 
}
337
 
 
338
 
/**
339
 
 * Spit out a command string to resemble the gimp-print output as much
340
 
 * as possible.
341
 
 **/
342
 
static int
343
 
rinkj_epson7600_init (RinkjDevice *self, const RinkjDeviceParams *params)
344
 
{
345
 
  RinkjEscp *z = (RinkjEscp *)self;
346
 
  int pl;
347
 
  int pw = 720 * 24; /* hardcode to 24 inch */
348
 
 
349
 
#if 0
350
 
  rinkj_byte_stream_printf (z->out,
351
 
                            "%c%c%c\033\001@EJL 1284.4\n", 0, 0, 0);
352
 
  rinkj_byte_stream_printf (z->out, "@EJL     \n");
353
 
#endif
354
 
  rinkj_byte_stream_printf (z->out, "\033@\033@");
355
 
 
356
 
#if 1
357
 
  /* remote string */
358
 
  rinkj_byte_stream_printf( z->out,
359
 
                            "\033(R%c%c%cREMOTE1", 8, 0, 0);
360
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 1, 0);
361
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 2, 6);
362
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 3, 0);
363
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 4, 129);
364
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 5, 51);
365
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 8, 0);
366
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 9, 2);
367
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 10, 0);
368
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 128, 1);
369
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 129, 0);
370
 
  if (z->autocut >= 0)
371
 
    rinkj_byte_stream_printf( z->out, "AC%c%c%c%c", 2, 0, 0, z->autocut);
372
 
  if (z->blankskip >= 0)
373
 
    rinkj_byte_stream_printf( z->out, "AC%c%c%c%c", 2, 0, 0, 64 + z->blankskip);
374
 
  rinkj_byte_stream_printf( z->out, "DR%c%c%c%c%c%c", 4, 0, 0, 1, 0, 0);
375
 
  rinkj_byte_stream_printf( z->out, "DR%c%c%c%c%c%c", 4, 0, 0, 0, 0, 0);
376
 
  rinkj_byte_stream_printf( z->out, "PH%c%c%c%c", 2, 0, 0, 0);
377
 
  rinkj_byte_stream_printf( z->out, "FP%c%c%c%c%c", 3, 0, 0, 0, 0);
378
 
  rinkj_byte_stream_printf( z->out, "AC%c%c%c%c", 2, 0, 0, 64);
379
 
  rinkj_byte_stream_printf( z->out, "SN%c%c%c%c%c", 3, 0, 0, 132, 1);
380
 
  rinkj_byte_stream_printf( z->out, "PP%c%c%c%c%c", 3, 0, 0, 3, 0);
381
 
  rinkj_byte_stream_printf( z->out, "IK%c%c%c%c", 2, 0, 0, 1);
382
 
  rinkj_byte_stream_printf( z->out, "EX%c%c%c%c%c%c%c%c", 6, 0, 0, 0, 0, 0, 20, 0);
383
 
  rinkj_byte_stream_printf( z->out,
384
 
                            "\033%c%c%c", 0, 0, 0);
385
 
#endif
386
 
 
387
 
  /* set graphics mode */
388
 
  rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
389
 
 
390
 
  /* set units to 1/720" */
391
 
  rinkj_byte_stream_printf (z->out, "\033(U\005%c\002\002\002\240\005", 0);
392
 
 
393
 
  rinkj_epson_set_common(z);
394
 
 
395
 
  pl = z->height * 720 / z->yres + 180;
396
 
  /* set page length to page height + 1/4 inch */
397
 
  rinkj_byte_stream_printf (z->out, "\033(S\010%c%c%c%c%c%c%c%c%c", 0,
398
 
                            pw & 255, (pw >> 8) & 255, (pw >> 16) & 255, pw >> 24,
399
 
                            pl & 255, (pl >> 8) & 255, (pl >> 16) & 255, pl >> 24);
400
 
 
401
 
  rinkj_byte_stream_printf (z->out, "\033(c\010%c%c%c%c%c%c%c%c%c", 0,
402
 
                            0, 0, 0, 0,
403
 
                            pl & 255, (pl >> 8) & 255, (pl >> 16) & 255, pl >> 24);
404
 
 
405
 
  rinkj_epson_headres (z, 2880);
406
 
 
407
 
  /* ESC ( v */
408
 
 
409
 
  /* ESC \ */
410
 
  return 0;
411
 
}
412
 
 
413
 
/**
414
 
 * Spit out a command string to resemble the gimp-print output as much
415
 
 * as possible.
416
 
 **/
417
 
static int
418
 
rinkj_epsonc80_init (RinkjDevice *self, const RinkjDeviceParams *params)
419
 
{
420
 
  RinkjEscp *z = (RinkjEscp *)self;
421
 
 
422
 
  rinkj_byte_stream_printf (z->out,
423
 
                            "%c%c%c\033\001@EJL 1284.4\n", 0, 0, 0);
424
 
  rinkj_byte_stream_printf (z->out, "@EJL     \n\033@\033@");
425
 
 
426
 
  /* remote string goes here, but is probably optional */
427
 
 
428
 
  /* set graphics mode */
429
 
  rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
430
 
 
431
 
  /* set units to 1/720" */
432
 
  rinkj_byte_stream_printf (z->out, "\033(U\005%c\002\002\002\240\005", 0);
433
 
 
434
 
  rinkj_epson_set_common(z);
435
 
 
436
 
  /* set page length to about 22.377 inches */
437
 
  rinkj_byte_stream_printf (z->out, "\033(C\002%cx\037", 0);
438
 
 
439
 
  /* set margins (magic) */
440
 
  rinkj_byte_stream_printf (z->out, "\033(c\010%c\040\376\377\377\376\036%c%c",
441
 
                            0, 0, 0);
442
 
 
443
 
  /* ESC ( c */
444
 
 
445
 
  /* ESC ( S */
446
 
 
447
 
  /* set resolution to 360 x 180 dpi - should probably generate this
448
 
     string from head_xres and head_yres */
449
 
  rinkj_byte_stream_printf (z->out, "\033(D\004%c@8P(", 0);
450
 
 
451
 
  /* ESC ( v */
452
 
 
453
 
  /* ESC \ */
454
 
  return 0;
455
 
}
456
 
 
457
 
static int
458
 
rinkj_escp_init (RinkjDevice *self, const RinkjDeviceParams *params)
459
 
{
460
 
  RinkjEscp *z = (RinkjEscp *)self;
461
 
  int resolution = 720; /* todo: make settable */
462
 
  int uweave;
463
 
  int height, top, bottom;
464
 
  int i;
465
 
 
466
 
  z->width = params->width;
467
 
  z->height = params->height;
468
 
  z->num_chan = params->n_planes;
469
 
 
470
 
  /* weaving stuff */
471
 
  z->pass = 0;
472
 
 
473
 
  /* 0 inch margins on top, 0.5 on bottom */
474
 
  top = 0 * resolution;
475
 
  bottom = params->height + 0.5 * resolution;
476
 
  height = params->height * resolution + resolution;
477
 
 
478
 
  /* some defaults */
479
 
  for (i = 0; i < sizeof(z->plane_offsets) / sizeof(z->plane_offsets[0]); i++)
480
 
    z->plane_offsets[i] = 0;
481
 
 
482
 
#ifdef VERBOSE
483
 
  fprintf (stderr, "Manufacturer: %s; Model; %s\n", z->manufacturer,
484
 
           z->model);
485
 
#endif
486
 
 
487
 
  if (z->model && !strcmp (z->model, "Stylus Photo 870"))
488
 
    {
489
 
      z->head_xres = 360;
490
 
      z->head_yres = 120;
491
 
      z->head_bps = 2;
492
 
      z->n_pins = 48;
493
 
      z->printer_weave = 0;
494
 
    }
495
 
  else if (z->model && !strcmp (z->model, "Stylus Photo 2200"))
496
 
    {
497
 
      z->head_xres = 360;
498
 
      z->head_yres = 180;
499
 
      z->head_bps = 2;
500
 
      if (z->xres == 2880)
501
 
        {
502
 
          z->head_xres = 720;
503
 
          z->head_bps = 1;
504
 
        }
505
 
      z->n_pins = 96;
506
 
      z->printer_weave = 0;
507
 
      z->plane_offsets[4] = z->yres / 360;
508
 
      z->plane_offsets[5] = z->yres / 360;
509
 
      z->plane_offsets[6] = z->yres / 360;
510
 
    }
511
 
  else if (z->model && !strcmp (z->model, "Stylus Photo 7600"))
512
 
    {
513
 
      z->head_xres = z->xres;
514
 
      z->head_yres = z->yres;
515
 
      z->head_bps = z->bps;
516
 
      z->n_pins = 1;
517
 
    }
518
 
  else if (z->model && !strcmp (z->model, "Stylus C80"))
519
 
    {
520
 
      z->head_xres = 360;
521
 
      z->head_yres = 180;
522
 
      z->head_bps = 2;
523
 
      z->n_pins = 60;
524
 
      z->printer_weave = 0;
525
 
      z->plane_offsets[0] = 480;
526
 
      z->plane_offsets[1] = 240;
527
 
      z->plane_offsets[2] = 480;
528
 
    }
529
 
  else
530
 
    {
531
 
      z->spacing = 1;
532
 
      z->n_pins = 1;
533
 
    }
534
 
 
535
 
  z->spacing = z->yres / z->head_yres;
536
 
  z->passes_per_scan = z->xres / z->head_xres;
537
 
 
538
 
  /* microweave */
539
 
  uweave = (z->n_pins == 1);
540
 
 
541
 
  z->max_offset = 0;
542
 
  for (i = 0; i < sizeof(z->plane_offsets) / sizeof(z->plane_offsets[0]); i++)
543
 
    if (z->plane_offsets[i] > z->max_offset)
544
 
      z->max_offset = z->plane_offsets[i];
545
 
 
546
 
  z->y = rinkj_escp_ytop (z, z->spacing * z->passes_per_scan - 1, NULL) -
547
 
    (z->spacing - 1) + z->max_offset;
548
 
 
549
 
  z->planestride = (z->width * z->bps + 7) >> 3;
550
 
  z->rowstride = z->planestride * z->num_chan;
551
 
  z->bufheight = 2048; /* todo: compute */
552
 
  z->buf = (char *)calloc (z->rowstride,  z->bufheight);
553
 
  z->buf_linevalid = (unsigned char *)calloc (z->num_chan, z->bufheight);
554
 
  z->vertpos = -1;
555
 
 
556
 
  if (z->model && !strcmp (z->model, "Stylus Photo 870"))
557
 
    rinkj_epson870_init (self, params);
558
 
  else if (z->model && !strcmp (z->model, "Stylus Photo 2200"))
559
 
    rinkj_epson2200_init (self, params);
560
 
  else if (z->model && !strcmp (z->model, "Stylus Photo 7600"))
561
 
    rinkj_epson7600_init (self, params);
562
 
  else if (z->model && !strcmp (z->model, "Stylus C80"))
563
 
    rinkj_epsonc80_init (self, params);
564
 
 
565
 
  /* todo: error checking */
566
 
  return 0;
567
 
    
568
 
}
569
 
 
570
 
/**
571
 
 * rinkj_escp_shuffle_dblx: Shuffle bits for doubled X resolution.
572
 
 * @dst: Where to store shuffled bits.
573
 
 * @src: Source of bits.
574
 
 * @pass: Pass number.
575
 
 * @n_bytes: Number of bytes in @src.
576
 
 *
577
 
 * Samples half of the bits in @src, finely interleaved for Epson Stylus
578
 
 * Color 1440 x 720 modes. If @pass is 0, then it selects bits 7, 5, 3, 1.
579
 
 * If @pass is 1, then 6, 4, 2, 0.
580
 
 *
581
 
 * The number of bytes in @dst should be (@n_bytes + 1) >> 1.
582
 
 **/
583
 
static void
584
 
rinkj_escp_shuffle_dblx (char *dst, const char *src, int pass, int n_bytes)
585
 
{
586
 
  int i;
587
 
  int n_dst;
588
 
  unsigned char s0, s1;
589
 
 
590
 
  n_dst = n_bytes >> 1;
591
 
  for (i = 0; i < n_dst; i++)
592
 
    {
593
 
      s0 = src[i * 2] << pass;
594
 
      s1 = src[i * 2 + 1] << pass;
595
 
      dst[i] = (s0 & 0x80) | ((s0 & 0x20) << 1) | ((s0 & 8) << 2) | ((s0 & 2) << 3) |
596
 
        ((s1 & 0x80) >> 4) | ((s1 & 0x20) >> 3) | ((s1 & 8) >> 2) | ((s1 & 2) >> 1);
597
 
    }
598
 
  if (n_bytes & 1)
599
 
    {
600
 
      s0 = src[n_bytes - 1] << pass;
601
 
      dst[n_dst] = (s0 & 0x80) | ((s0 & 0x20) << 1) | ((s0 & 8) << 2) | ((s0 & 2) << 3);
602
 
    }
603
 
}
604
 
 
605
 
/**
606
 
 * rinkj_escp_shuffle_4pass_2bit: Shuffle bits for quadrupled X resolution.
607
 
 * @dst: Where to store shuffled bits.
608
 
 * @src: Source of bits.
609
 
 * @pass: Pass number.
610
 
 * @n_bytes: Number of bytes in @src.
611
 
 *
612
 
 * Samples the bits in @src for 4-pass, 1-bit operation.
613
 
 *
614
 
 * The number of bytes in @dst should be (@n_bytes + 1) >> 1.
615
 
 **/
616
 
static void
617
 
rinkj_escp_shuffle_4pass_1bit (char *dst, const char *src, int pass, int n_bytes)
618
 
{
619
 
  int i;
620
 
  int n_dst;
621
 
  unsigned char s0, s1, s2, s3;
622
 
  int shift = pass;
623
 
 
624
 
  n_dst = n_bytes >> 2;
625
 
  for (i = 0; i < n_dst; i++)
626
 
    {
627
 
      s0 = src[i * 4] << shift;
628
 
      s1 = src[i * 4 + 1] << shift;
629
 
      s2 = src[i * 4 + 2] << shift;
630
 
      s3 = src[i * 4 + 3] << shift;
631
 
      dst[i] = (s0 & 0x80) | ((s0 & 8) << 3) |
632
 
        ((s1 & 0x80) >> 2) | ((s1 & 8) << 1) |
633
 
        ((s2 & 0x80) >> 4) | ((s2 & 8) >> 1) |
634
 
        ((s3 & 0x80) >> 6) | ((s3 & 8) >> 3);
635
 
    }
636
 
  if (n_bytes & 3)
637
 
    {
638
 
      char d = 0;
639
 
 
640
 
      for (i = 0; i < (n_bytes & 3); i++)
641
 
        {
642
 
          s0 = src[n_dst * 4 + i] << shift;
643
 
          d |= ((s0 & 0x80) | ((s0 & 8) << 3)) >> (i << 1);
644
 
        }
645
 
      dst[n_dst] = d;
646
 
    }
647
 
}
648
 
 
649
 
/**
650
 
 * rinkj_escp_shuffle_2pass_2bit: Shuffle bits for doubled X resolution.
651
 
 * @dst: Where to store shuffled bits.
652
 
 * @src: Source of bits.
653
 
 * @pass: Pass number.
654
 
 * @n_bytes: Number of bytes in @src.
655
 
 *
656
 
 * Samples the bits in @src for 2-pass, 2-bit operation.
657
 
 *
658
 
 * The number of bytes in @dst should be (@n_bytes + 1) >> 1.
659
 
 **/
660
 
static void
661
 
rinkj_escp_shuffle_2pass_2bit (char *dst, const char *src, int pass, int n_bytes)
662
 
{
663
 
  int i;
664
 
  int n_dst;
665
 
  unsigned char s0, s1;
666
 
  int shift = pass << 1;
667
 
 
668
 
  n_dst = n_bytes >> 1;
669
 
  for (i = 0; i < n_dst; i++)
670
 
    {
671
 
      s0 = src[i * 2] << shift;
672
 
      s1 = src[i * 2 + 1] << shift;
673
 
      dst[i] = (s0 & 0xc0) | ((s0 & 0x0c) << 2) |
674
 
        ((s1 & 0xc0) >> 4) | ((s1 & 0x0c) >> 2);
675
 
    }
676
 
  if (n_bytes & 1)
677
 
    {
678
 
      s0 = src[n_bytes - 1] << shift;
679
 
      dst[i] = (s0 & 0xc0) | ((s0 & 0x0c) << 2);
680
 
    }
681
 
}
682
 
 
683
 
/**
684
 
 * rinkj_escp_shuffle_4pass_2bit: Shuffle bits for quadrupled X resolution.
685
 
 * @dst: Where to store shuffled bits.
686
 
 * @src: Source of bits.
687
 
 * @pass: Pass number.
688
 
 * @n_bytes: Number of bytes in @src.
689
 
 *
690
 
 * Samples the bits in @src for 4-pass, 2-bit operation.
691
 
 *
692
 
 * The number of bytes in @dst should be (@n_bytes + 1) >> 1.
693
 
 **/
694
 
static void
695
 
rinkj_escp_shuffle_4pass_2bit (char *dst, const char *src, int pass, int n_bytes)
696
 
{
697
 
  int i;
698
 
  int n_dst;
699
 
  unsigned char s0, s1, s2, s3;
700
 
  int shift = pass << 1;
701
 
 
702
 
  n_dst = n_bytes >> 2;
703
 
  for (i = 0; i < n_dst; i++)
704
 
    {
705
 
      s0 = src[i * 4] << shift;
706
 
      s1 = src[i * 4 + 1] << shift;
707
 
      s2 = src[i * 4 + 2] << shift;
708
 
      s3 = src[i * 4 + 3] << shift;
709
 
      dst[i] = (s0 & 0xc0) | ((s1 & 0xc0) >> 2) |
710
 
        ((s2 & 0xc0) >> 4) | ((s3 & 0xc0) >> 6);
711
 
    }
712
 
  if (n_bytes & 3)
713
 
    {
714
 
      char d = 0;
715
 
 
716
 
      for (i = 0; i < (n_bytes & 3); i++)
717
 
        d |= ((src[n_dst * 4 + i] << shift) & 0xc0) >> (i << 1);
718
 
      dst[n_dst] = d;
719
 
    }
720
 
}
721
 
 
722
 
#define DOT 3
723
 
 
724
 
static void
725
 
rinkj_escp_1pass_dblx (char *dst, const char *src, int n_bytes)
726
 
{
727
 
  int i;
728
 
 
729
 
  /* todo: may need half-byte fixup */
730
 
  for (i = 0; i < n_bytes; i ++)
731
 
    {
732
 
      unsigned char s = src[i];
733
 
      dst[i * 2] = (((s & 0x80) >> 1) | ((s & 0x40) >> 2) |
734
 
                    ((s & 0x20) >> 3) | ((s & 0x10) >> 4)) * DOT;
735
 
      dst[i * 2 + 1] = (((s & 8) << 3) | ((s & 4) << 2) |
736
 
                    ((s & 2) << 1) | (s & 1)) * DOT;
737
 
    }
738
 
}
739
 
 
740
 
static void
741
 
rinkj_escp_select_dblx (char *dst, const char *src, int x_pass, int n_bytes)
742
 
{
743
 
  int i;
744
 
 
745
 
  for (i = 0; i < n_bytes; i++)
746
 
    dst[i] = (src[i] >> (1 - x_pass) & 0x55) * DOT;
747
 
}
748
 
 
749
 
static void
750
 
rinkj_escp_sel_shuffle_dblx (char *dst, const char *src, int pass, int n_bytes)
751
 
{
752
 
  int i;
753
 
  int n_dst;
754
 
  unsigned char s0, s1;
755
 
 
756
 
  n_dst = n_bytes >> 1;
757
 
  for (i = 0; i < n_dst; i++)
758
 
    {
759
 
      s0 = src[i * 2] << pass;
760
 
      s1 = src[i * 2 + 1] << pass;
761
 
      dst[i] = (((s0 & 0x80) >> 1) | ((s0 & 8) << 1) |
762
 
        ((s1 & 0x80) >> 5) | ((s1 & 0x8) >> 3)) * DOT;
763
 
    }
764
 
  if (n_bytes & 1)
765
 
    {
766
 
      s0 = src[n_bytes - 1] << pass;
767
 
      dst[n_dst] = (((s0 & 0x80) >> 1) | ((s0 & 8) << 1)) * DOT;
768
 
    }
769
 
}
770
 
 
771
 
static void
772
 
rinkj_escp_shuffle (char *dst, const char *src, int pass, int n_bytes,
773
 
                    int passes_per_scan, int bps, int head_bps)
774
 
{
775
 
  if (bps == 2 && head_bps == 2)
776
 
    {
777
 
      if (passes_per_scan == 1)
778
 
        memcpy (dst, src, n_bytes);
779
 
      else if (passes_per_scan == 2)
780
 
        rinkj_escp_shuffle_2pass_2bit (dst, src, pass, n_bytes);
781
 
      else if (passes_per_scan == 4)
782
 
        rinkj_escp_shuffle_4pass_2bit (dst, src, pass, n_bytes);
783
 
    }
784
 
  else if (bps == 1 && head_bps == 2)
785
 
    {
786
 
      if (passes_per_scan == 1)
787
 
        rinkj_escp_1pass_dblx (dst, src, n_bytes);
788
 
      if (passes_per_scan == 2)
789
 
        rinkj_escp_select_dblx (dst, src, pass, n_bytes);
790
 
      else if (passes_per_scan == 4)
791
 
        rinkj_escp_sel_shuffle_dblx (dst, src, pass, n_bytes);
792
 
    }
793
 
  else if (bps == 1 && head_bps == 1)
794
 
    {
795
 
      if (passes_per_scan == 1)
796
 
        memcpy (dst, src, n_bytes);
797
 
      else if (passes_per_scan == 2)
798
 
        rinkj_escp_shuffle_dblx (dst, src, pass, n_bytes);
799
 
      else if (passes_per_scan == 4)
800
 
        rinkj_escp_shuffle_4pass_1bit (dst, src, pass, n_bytes);
801
 
    }
802
 
}
803
 
 
804
 
/**
805
 
 * rinkj_escp_compress_rle: Compress a chunk of data using runlengths.
806
 
 * @dst: Where to store compressed data.
807
 
 * @src: Source of data.
808
 
 * @n: Size of @src in bytes.
809
 
 *
810
 
 * Compresses a chunk of data using ESCP/2 runlength encoding. @dst must be
811
 
 * at least @n + ((@n + 127) >> 7) bytes long.
812
 
 *
813
 
 * Return value: size of @dst in bytes.
814
 
 **/
815
 
static int
816
 
rinkj_escp_compress_rle (char *dst, const char *src, int n)
817
 
{
818
 
  int i, j;
819
 
  int b;
820
 
  int run;
821
 
 
822
 
  j = 0;
823
 
  for (i = 0; i < n; i += run)
824
 
    {
825
 
      b = src[i];
826
 
      for (run = 1; run < 129 && i + run < n; run++)
827
 
        if (b != src[i + run])
828
 
          break;
829
 
      if (run > 2)
830
 
        {
831
 
          dst[j++] = 257 - run;
832
 
          dst[j++] = b;
833
 
        }
834
 
      else
835
 
        {
836
 
          for (run = 1; run < 128 && i + run < n; run++)
837
 
            {
838
 
              b = src[i + run];
839
 
              if (i + run + 2 < n &&
840
 
                  b == src[i + run + 1] && b == src[i + run + 2])
841
 
                break;
842
 
            }
843
 
          dst[j++] = run - 1;
844
 
          memcpy (dst + j, src + i, run);
845
 
          j += run;
846
 
        }
847
 
    }
848
 
 
849
 
  return j;
850
 
}
851
 
 
852
 
static int
853
 
rinkj_escp_flush (RinkjEscp *z)
854
 
{
855
 
  int xsb, xsb_out;
856
 
  int xs_out;
857
 
  int status;
858
 
  const int plane[7] = {3, 1, 0, 2, 5, 4, 6};
859
 
  const int color[7] = {0, 1, 2, 4, 17, 18, 16};
860
 
  int i, j;
861
 
  int ytop, ysc;
862
 
  int bufy;
863
 
  char *thisbuf;
864
 
  char *compress_buf = NULL;
865
 
  int rle = 1;
866
 
  int x_pass;
867
 
  char pass_mask;
868
 
  int m;
869
 
 
870
 
  ytop = rinkj_escp_ytop (z, z->pass, &x_pass);
871
 
  pass_mask = 1 << x_pass;
872
 
 
873
 
#ifdef VERBOSE
874
 
  fprintf (stderr, "flush pass %d: ytop = %d (= %d mod %d), x_pass = %d\n",
875
 
           z->pass, ytop, ytop % z->spacing, z->spacing, x_pass);
876
 
#endif
877
 
 
878
 
  xsb = (z->width * z->bps + 7) >> 3;
879
 
 
880
 
  xs_out = (z->width + z->passes_per_scan - 1) / (z->passes_per_scan);
881
 
  xsb_out = (((z->width * z->head_bps + 7) >> 3) + z->passes_per_scan - 1) /
882
 
    (z->passes_per_scan);
883
 
 
884
 
  thisbuf = malloc (xsb_out);
885
 
  if (rle)
886
 
    compress_buf = malloc (xsb_out + ((xsb_out + 127) >> 7));
887
 
  ysc = ytop;
888
 
  if (z->vertpos == -1)
889
 
    status = rinkj_byte_stream_printf (z->out, "\033(V%c%c%c%c",
890
 
                                       2, 0, ysc & 0xff, (ysc >> 8) & 0xff);
891
 
  else
892
 
    {
893
 
      int yrel = ysc - z->vertpos;
894
 
      status = rinkj_byte_stream_printf (z->out, "\033(v%c%c%c%c%c%c",
895
 
                                         4, 0, yrel & 0xff, (yrel >> 8) & 0xff, (yrel >> 16) & 0xff, (yrel >> 24) & 0xff);
896
 
    }
897
 
 
898
 
  z->vertpos = ysc;
899
 
 
900
 
  if (status < 0) return status;
901
 
 
902
 
  for (i = 0; i < z->num_chan; i++)
903
 
    {
904
 
      int plane_off = z->plane_offsets[i];
905
 
 
906
 
      m = (z->y - ytop + z->spacing - 1 - plane_off) / z->spacing;
907
 
      if (m > z->n_pins)
908
 
        m = z->n_pins;
909
 
 
910
 
      if (m <= 0)
911
 
        continue;
912
 
 
913
 
      if (1)
914
 
        {
915
 
          /* todo: make this calculation fully agile */
916
 
          int x = (x_pass & 3);
917
 
          status = rinkj_byte_stream_printf (z->out, "\033($\4%c%c%c%c%c",
918
 
                                             0, x & 0xff,
919
 
                                             (x >> 8) & 0xff,
920
 
                                             (x >> 16) & 0xff,
921
 
                                             (x >> 24) & 0xff);
922
 
 
923
 
          if (status < 0) return status;
924
 
        }
925
 
 
926
 
      status = rinkj_byte_stream_printf (z->out, "\033i%c%c%c%c%c%c%c",
927
 
                                         color[i],
928
 
                                         rle,
929
 
                                         z->head_bps,
930
 
                                         xsb_out & 0xff,
931
 
                                         (xsb_out >> 8) & 0xff,
932
 
                                         m & 0xff, m >> 8);
933
 
      if (status < 0) return status;
934
 
      for (j = 0; j < m; j++)
935
 
        {
936
 
          const char *line;
937
 
 
938
 
          bufy = (ytop + j * z->spacing + plane_off) % z->bufheight;
939
 
          line = z->buf + bufy * z->rowstride + plane[i] * z->planestride;
940
 
          if (z->buf_linevalid[bufy * z->num_chan + i] & pass_mask)
941
 
            rinkj_escp_shuffle (thisbuf, line, x_pass, xsb,
942
 
                                z->passes_per_scan, z->bps, z->head_bps);
943
 
          else
944
 
            memset (thisbuf, 0, xsb_out);
945
 
          z->buf_linevalid[bufy * z->num_chan + i] &= ~pass_mask;
946
 
#ifdef VERBOSE
947
 
          if (i == 0 && j == 0)
948
 
            {
949
 
              fprintf (stderr, "flush line[0] = %d shuffled[0] = %d\n",
950
 
                       line[0], thisbuf[0]);
951
 
            }
952
 
#endif
953
 
          if (rle)
954
 
            {
955
 
              int nbytes;
956
 
 
957
 
              nbytes = rinkj_escp_compress_rle (compress_buf, thisbuf, xsb_out);
958
 
              status = rinkj_byte_stream_write (z->out, compress_buf, nbytes);
959
 
            }
960
 
          else
961
 
            status = rinkj_byte_stream_write (z->out, thisbuf, xsb_out);
962
 
        }
963
 
      if (status < 0) return status;
964
 
#if 0
965
 
      status = rinkj_byte_stream_puts (z->out, "\r");
966
 
      if (status < 0) return status;
967
 
#endif
968
 
    }
969
 
 
970
 
  z->pass++;
971
 
  if (rle)
972
 
    free (compress_buf);
973
 
  free (thisbuf);
974
 
  return status;
975
 
}
976
 
 
977
 
static int
978
 
rinkj_escp_flush_bottom (RinkjEscp *z)
979
 
{
980
 
  int ytop;
981
 
  int status;
982
 
 
983
 
  for (;;)
984
 
    {
985
 
      ytop = rinkj_escp_ytop (z, z->pass, NULL);
986
 
      if (ytop >= z->y)
987
 
        break;
988
 
      status = rinkj_escp_flush (z);
989
 
      if (status != 0)
990
 
        return status;
991
 
    }
992
 
  return 0;
993
 
}
994
 
 
995
 
static void
996
 
rinkj_escp_free (RinkjEscp *z)
997
 
{
998
 
  if (z->manufacturer)
999
 
    free (z->manufacturer);
1000
 
  if (z->model)
1001
 
    free (z->model);
1002
 
  free (z->buf);
1003
 
  free (z->buf_linevalid);
1004
 
  free (z);
1005
 
}
1006
 
 
1007
 
static int
1008
 
rinkj_escp_write (RinkjDevice *self, const char **data)
1009
 
{
1010
 
  RinkjEscp *z = (RinkjEscp *)self;
1011
 
  int xsb;
1012
 
  int status;
1013
 
  int i;
1014
 
  int ytop;
1015
 
  int bufy;
1016
 
  int dblx_pass;
1017
 
 
1018
 
  if (data == NULL)
1019
 
    {
1020
 
      status = rinkj_escp_flush_bottom (z);
1021
 
      /* todo: check error */
1022
 
      status = rinkj_byte_stream_puts (z->out, "\f\033@");
1023
 
      /* todo: check error */
1024
 
      status = rinkj_byte_stream_close (z->out);
1025
 
      rinkj_escp_free (z);
1026
 
      return status;
1027
 
    }
1028
 
 
1029
 
  xsb = (z->width * z->bps + 7) >> 3;
1030
 
  bufy = z->y % z->bufheight;
1031
 
  for (i = 0; i < z->num_chan; i++)
1032
 
    {
1033
 
      memcpy (z->buf + bufy * z->rowstride + i * z->planestride, data[i], xsb);
1034
 
      z->buf_linevalid[bufy * z->num_chan + i] = 0xff;
1035
 
    }
1036
 
 
1037
 
  z->y++;
1038
 
 
1039
 
  ytop = rinkj_escp_ytop (z, z->pass, &dblx_pass);
1040
 
 
1041
 
  if (z->y < ytop + (z->n_pins - 1) * z->spacing + 1 + z->max_offset)
1042
 
    return 0;
1043
 
 
1044
 
  return rinkj_escp_flush (z);
1045
 
}
1046
 
 
1047
 
RinkjDevice *
1048
 
rinkj_epson870_new (RinkjByteStream *out)
1049
 
{
1050
 
  RinkjEscp *result;
1051
 
 
1052
 
  result = (RinkjEscp *)malloc (sizeof (RinkjEscp));
1053
 
 
1054
 
  result->super.set = rinkj_escp_set;
1055
 
  result->super.write = rinkj_escp_write;
1056
 
  result->super.init = rinkj_escp_init;
1057
 
  result->super.init_happened = 0;
1058
 
  result->width = 0;
1059
 
  result->out = out;
1060
 
 
1061
 
  result->num_chan = 4;
1062
 
  result->bps = 1;
1063
 
 
1064
 
  result->manufacturer = NULL;
1065
 
  result->model = NULL;
1066
 
 
1067
 
  result->autocut = -1;
1068
 
  result->microdot = -1;
1069
 
  result->unidir = -1;
1070
 
  result->printer_weave = -1;
1071
 
 
1072
 
  return &result->super;
1073
 
}