1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
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.
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. */
21
#include "rinkj-byte-stream.h"
22
#include "rinkj-device.h"
23
#include "rinkj-config.h"
24
#include "rinkj-epson870.h"
26
typedef struct _RinkjEscp RinkjEscp;
39
int bps; /* bits per sample */
41
int xres; /* resolution of input image */
45
int head_xres; /* x resolution of printhead in dpi */
46
int head_yres; /* y resolution of printhead in dpi */
48
/* Number of passes for a single scanline */
51
/* parameters for controlling microweaving */
59
unsigned char *buf_linevalid;
65
int vertpos; /* for ESC ( v */
67
/* parameters passed into ESCP2 */
76
rinkj_escp_set (RinkjDevice *self, const char *config)
78
RinkjEscp *z = (RinkjEscp *)self;
82
for (p = config; (key = rinkj_config_keyval (p, &val, &next)); p = next)
84
if (!strcmp (key, "Resolution"))
89
p = strchr (val, 'x');
91
z->yres = atoi (p + 1);
95
fprintf (stderr, "Resolution = %d x %d\n", z->xres, z->yres);
98
else if (!strcmp (key, "Manufacturer"))
101
free (z->manufacturer);
102
z->manufacturer = val;
105
else if (!strcmp (key, "Model"))
112
else if (!strcmp (key, "BitsPerSample"))
116
fprintf (stderr, "BitsPerSample = %d\n", z->bps);
119
else if (!strcmp (key, "NumChan"))
121
/* This is in params, but should become a setting. */
122
z->num_chan = atoi (val);
124
fprintf (stderr, "NumChan = %d\n", z->num_chan);
127
else if (!strcmp (key, "PrinterWeave"))
129
z->printer_weave = atoi (val);
131
else if (!strcmp (key, "Microdot"))
133
z->microdot = atoi (val);
135
else if (!strcmp (key, "Unidirectional"))
137
z->unidir = atoi (val);
139
else if (!strcmp (key, "AutoCut"))
141
z->autocut = atoi (val);
143
else if (!strcmp (key, "BlankSkip"))
145
z->blankskip = atoi (val);
155
rinkj_escp_ytop (RinkjEscp *z, int pass, int *p_x_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;
164
const int four[4] = { 0, 3, 1, 2 };
165
const int six[6] = { 0, 3, 2, 5, 1, 4 };
167
ytop = mod_pass * z->n_pins * spacing / n_cycle;
169
x_pass = mod_pass / spacing;
170
y_pass = mod_pass % spacing;
171
if (passes_per_scan == 4)
172
x_pass = four[x_pass];
174
x_pass = mod_pass % passes_per_scan;
175
y_pass = (mod_pass / passes_per_scan + x_pass * (spacing - 1)) % spacing;
181
y_modulo = four[y_pass];
184
y_modulo = six[y_pass];
187
y_modulo = y_pass * 3;
194
ytop += (spacing + y_modulo - ytop % spacing) % spacing;
195
ytop += (pass / n_cycle) * spacing * z->n_pins;
197
if (spacing == 4 && passes_per_scan == 4 && z->n_pins == 96)
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];
205
fprintf (stderr, "pass %d: ytop = %d, x_pass = %d\n", pass, ytop, x_pass);
214
rinkj_epson_headres (RinkjEscp *z, int baseres)
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);
223
rinkj_epson_units (RinkjEscp *z, int xres, int yres, int baseres)
225
return rinkj_byte_stream_printf (z->out, "\033(U\005%c%c%c%c%c%c", 0,
229
baseres & 255, baseres >> 8);
233
rinkj_epson_set_common (RinkjEscp *z)
237
if (z->printer_weave >= 0)
239
status = rinkj_byte_stream_printf (z->out, "\033(i\001%c%c", 0,
242
if (status == 0 && z->unidir >= 0)
243
/* set unidirectional */
244
status = rinkj_byte_stream_printf (z->out, "\033U%c", z->unidir);
246
if (status == 0 && z->microdot >= 0)
248
status = rinkj_byte_stream_printf (z->out, "\033(e\002%c%c%c", 0, 0,
255
* Spit out a command string to resemble the gimp-print output as much
259
rinkj_epson870_init (RinkjDevice *self, const RinkjDeviceParams *params)
261
RinkjEscp *z = (RinkjEscp *)self;
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@");
267
/* remote string goes here, but is probably optional */
269
/* set graphics mode */
270
rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
272
/* set units to 1/720" */
273
rinkj_byte_stream_printf (z->out, "\033(U\005%c\002\002\002\240\005", 0);
275
rinkj_epson_set_common(z);
277
/* set page length to about 22.377 inches */
278
rinkj_byte_stream_printf (z->out, "\033(C\002%cx\037", 0);
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);
295
* Spit out a command string to resemble the gimp-print output as much
299
rinkj_epson2200_init (RinkjDevice *self, const RinkjDeviceParams *params)
301
RinkjEscp *z = (RinkjEscp *)self;
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@");
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);
316
/* set graphics mode */
317
rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
319
rinkj_epson_units(z, z->xres, z->yres, 2880);
321
rinkj_epson_set_common(z);
323
/* set page length to 40 inches */
324
rinkj_byte_stream_printf (z->out, "\033(C\002%c\200p", 0);
330
rinkj_epson_headres (z, 2880);
339
* Spit out a command string to resemble the gimp-print output as much
343
rinkj_epson7600_init (RinkjDevice *self, const RinkjDeviceParams *params)
345
RinkjEscp *z = (RinkjEscp *)self;
347
int pw = 720 * 24; /* hardcode to 24 inch */
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");
354
rinkj_byte_stream_printf (z->out, "\033@\033@");
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);
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);
387
/* set graphics mode */
388
rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
390
/* set units to 1/720" */
391
rinkj_byte_stream_printf (z->out, "\033(U\005%c\002\002\002\240\005", 0);
393
rinkj_epson_set_common(z);
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);
401
rinkj_byte_stream_printf (z->out, "\033(c\010%c%c%c%c%c%c%c%c%c", 0,
403
pl & 255, (pl >> 8) & 255, (pl >> 16) & 255, pl >> 24);
405
rinkj_epson_headres (z, 2880);
414
* Spit out a command string to resemble the gimp-print output as much
418
rinkj_epsonc80_init (RinkjDevice *self, const RinkjDeviceParams *params)
420
RinkjEscp *z = (RinkjEscp *)self;
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@");
426
/* remote string goes here, but is probably optional */
428
/* set graphics mode */
429
rinkj_byte_stream_printf (z->out, "\033(G\001%c\001", 0);
431
/* set units to 1/720" */
432
rinkj_byte_stream_printf (z->out, "\033(U\005%c\002\002\002\240\005", 0);
434
rinkj_epson_set_common(z);
436
/* set page length to about 22.377 inches */
437
rinkj_byte_stream_printf (z->out, "\033(C\002%cx\037", 0);
439
/* set margins (magic) */
440
rinkj_byte_stream_printf (z->out, "\033(c\010%c\040\376\377\377\376\036%c%c",
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);
458
rinkj_escp_init (RinkjDevice *self, const RinkjDeviceParams *params)
460
RinkjEscp *z = (RinkjEscp *)self;
461
int resolution = 720; /* todo: make settable */
463
int height, top, bottom;
466
z->width = params->width;
467
z->height = params->height;
468
z->num_chan = params->n_planes;
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;
479
for (i = 0; i < sizeof(z->plane_offsets) / sizeof(z->plane_offsets[0]); i++)
480
z->plane_offsets[i] = 0;
483
fprintf (stderr, "Manufacturer: %s; Model; %s\n", z->manufacturer,
487
if (z->model && !strcmp (z->model, "Stylus Photo 870"))
493
z->printer_weave = 0;
495
else if (z->model && !strcmp (z->model, "Stylus Photo 2200"))
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;
511
else if (z->model && !strcmp (z->model, "Stylus Photo 7600"))
513
z->head_xres = z->xres;
514
z->head_yres = z->yres;
515
z->head_bps = z->bps;
518
else if (z->model && !strcmp (z->model, "Stylus C80"))
524
z->printer_weave = 0;
525
z->plane_offsets[0] = 480;
526
z->plane_offsets[1] = 240;
527
z->plane_offsets[2] = 480;
535
z->spacing = z->yres / z->head_yres;
536
z->passes_per_scan = z->xres / z->head_xres;
539
uweave = (z->n_pins == 1);
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];
546
z->y = rinkj_escp_ytop (z, z->spacing * z->passes_per_scan - 1, NULL) -
547
(z->spacing - 1) + z->max_offset;
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);
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);
565
/* todo: error checking */
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.
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.
581
* The number of bytes in @dst should be (@n_bytes + 1) >> 1.
584
rinkj_escp_shuffle_dblx (char *dst, const char *src, int pass, int n_bytes)
588
unsigned char s0, s1;
590
n_dst = n_bytes >> 1;
591
for (i = 0; i < n_dst; i++)
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);
600
s0 = src[n_bytes - 1] << pass;
601
dst[n_dst] = (s0 & 0x80) | ((s0 & 0x20) << 1) | ((s0 & 8) << 2) | ((s0 & 2) << 3);
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.
612
* Samples the bits in @src for 4-pass, 1-bit operation.
614
* The number of bytes in @dst should be (@n_bytes + 1) >> 1.
617
rinkj_escp_shuffle_4pass_1bit (char *dst, const char *src, int pass, int n_bytes)
621
unsigned char s0, s1, s2, s3;
624
n_dst = n_bytes >> 2;
625
for (i = 0; i < n_dst; i++)
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);
640
for (i = 0; i < (n_bytes & 3); i++)
642
s0 = src[n_dst * 4 + i] << shift;
643
d |= ((s0 & 0x80) | ((s0 & 8) << 3)) >> (i << 1);
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.
656
* Samples the bits in @src for 2-pass, 2-bit operation.
658
* The number of bytes in @dst should be (@n_bytes + 1) >> 1.
661
rinkj_escp_shuffle_2pass_2bit (char *dst, const char *src, int pass, int n_bytes)
665
unsigned char s0, s1;
666
int shift = pass << 1;
668
n_dst = n_bytes >> 1;
669
for (i = 0; i < n_dst; i++)
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);
678
s0 = src[n_bytes - 1] << shift;
679
dst[i] = (s0 & 0xc0) | ((s0 & 0x0c) << 2);
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.
690
* Samples the bits in @src for 4-pass, 2-bit operation.
692
* The number of bytes in @dst should be (@n_bytes + 1) >> 1.
695
rinkj_escp_shuffle_4pass_2bit (char *dst, const char *src, int pass, int n_bytes)
699
unsigned char s0, s1, s2, s3;
700
int shift = pass << 1;
702
n_dst = n_bytes >> 2;
703
for (i = 0; i < n_dst; i++)
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);
716
for (i = 0; i < (n_bytes & 3); i++)
717
d |= ((src[n_dst * 4 + i] << shift) & 0xc0) >> (i << 1);
725
rinkj_escp_1pass_dblx (char *dst, const char *src, int n_bytes)
729
/* todo: may need half-byte fixup */
730
for (i = 0; i < n_bytes; i ++)
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;
741
rinkj_escp_select_dblx (char *dst, const char *src, int x_pass, int n_bytes)
745
for (i = 0; i < n_bytes; i++)
746
dst[i] = (src[i] >> (1 - x_pass) & 0x55) * DOT;
750
rinkj_escp_sel_shuffle_dblx (char *dst, const char *src, int pass, int n_bytes)
754
unsigned char s0, s1;
756
n_dst = n_bytes >> 1;
757
for (i = 0; i < n_dst; i++)
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;
766
s0 = src[n_bytes - 1] << pass;
767
dst[n_dst] = (((s0 & 0x80) >> 1) | ((s0 & 8) << 1)) * DOT;
772
rinkj_escp_shuffle (char *dst, const char *src, int pass, int n_bytes,
773
int passes_per_scan, int bps, int head_bps)
775
if (bps == 2 && head_bps == 2)
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);
784
else if (bps == 1 && head_bps == 2)
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);
793
else if (bps == 1 && head_bps == 1)
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);
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.
810
* Compresses a chunk of data using ESCP/2 runlength encoding. @dst must be
811
* at least @n + ((@n + 127) >> 7) bytes long.
813
* Return value: size of @dst in bytes.
816
rinkj_escp_compress_rle (char *dst, const char *src, int n)
823
for (i = 0; i < n; i += run)
826
for (run = 1; run < 129 && i + run < n; run++)
827
if (b != src[i + run])
831
dst[j++] = 257 - run;
836
for (run = 1; run < 128 && i + run < n; run++)
839
if (i + run + 2 < n &&
840
b == src[i + run + 1] && b == src[i + run + 2])
844
memcpy (dst + j, src + i, run);
853
rinkj_escp_flush (RinkjEscp *z)
858
const int plane[7] = {3, 1, 0, 2, 5, 4, 6};
859
const int color[7] = {0, 1, 2, 4, 17, 18, 16};
864
char *compress_buf = NULL;
870
ytop = rinkj_escp_ytop (z, z->pass, &x_pass);
871
pass_mask = 1 << x_pass;
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);
878
xsb = (z->width * z->bps + 7) >> 3;
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);
884
thisbuf = malloc (xsb_out);
886
compress_buf = malloc (xsb_out + ((xsb_out + 127) >> 7));
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);
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);
900
if (status < 0) return status;
902
for (i = 0; i < z->num_chan; i++)
904
int plane_off = z->plane_offsets[i];
906
m = (z->y - ytop + z->spacing - 1 - plane_off) / z->spacing;
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",
923
if (status < 0) return status;
926
status = rinkj_byte_stream_printf (z->out, "\033i%c%c%c%c%c%c%c",
931
(xsb_out >> 8) & 0xff,
933
if (status < 0) return status;
934
for (j = 0; j < m; j++)
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);
944
memset (thisbuf, 0, xsb_out);
945
z->buf_linevalid[bufy * z->num_chan + i] &= ~pass_mask;
947
if (i == 0 && j == 0)
949
fprintf (stderr, "flush line[0] = %d shuffled[0] = %d\n",
950
line[0], thisbuf[0]);
957
nbytes = rinkj_escp_compress_rle (compress_buf, thisbuf, xsb_out);
958
status = rinkj_byte_stream_write (z->out, compress_buf, nbytes);
961
status = rinkj_byte_stream_write (z->out, thisbuf, xsb_out);
963
if (status < 0) return status;
965
status = rinkj_byte_stream_puts (z->out, "\r");
966
if (status < 0) return status;
978
rinkj_escp_flush_bottom (RinkjEscp *z)
985
ytop = rinkj_escp_ytop (z, z->pass, NULL);
988
status = rinkj_escp_flush (z);
996
rinkj_escp_free (RinkjEscp *z)
999
free (z->manufacturer);
1003
free (z->buf_linevalid);
1008
rinkj_escp_write (RinkjDevice *self, const char **data)
1010
RinkjEscp *z = (RinkjEscp *)self;
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);
1029
xsb = (z->width * z->bps + 7) >> 3;
1030
bufy = z->y % z->bufheight;
1031
for (i = 0; i < z->num_chan; i++)
1033
memcpy (z->buf + bufy * z->rowstride + i * z->planestride, data[i], xsb);
1034
z->buf_linevalid[bufy * z->num_chan + i] = 0xff;
1039
ytop = rinkj_escp_ytop (z, z->pass, &dblx_pass);
1041
if (z->y < ytop + (z->n_pins - 1) * z->spacing + 1 + z->max_offset)
1044
return rinkj_escp_flush (z);
1048
rinkj_epson870_new (RinkjByteStream *out)
1052
result = (RinkjEscp *)malloc (sizeof (RinkjEscp));
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;
1061
result->num_chan = 4;
1064
result->manufacturer = NULL;
1065
result->model = NULL;
1067
result->autocut = -1;
1068
result->microdot = -1;
1069
result->unidir = -1;
1070
result->printer_weave = -1;
1072
return &result->super;