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: gdevpx.c 9239 2008-11-24 19:15:04Z till $ */
15
/* H-P PCL XL driver */
24
#include "gxcspace.h" /* for color mapping for images */
37
/* ---------------- Device definition ---------------- */
39
/* Define the default resolution. */
47
/* Structure definition */
48
#define NUM_POINTS 40 /* must be >= 3 and <= 255 */
54
typedef struct gx_device_pclxl_s {
55
gx_device_vector_common;
56
/* Additional state information */
57
pxeMediaSize_t media_size;
58
bool ManualFeed; /* map ps setpage commands to pxl */
60
int MediaPosition; /* MediaPosition attribute */
61
int MediaPosition_set;
62
int page; /* Page number starting at 0 */
63
bool Duplex; /* Duplex attribute */
64
bool Tumble; /* Tumble attribute */
65
gx_path_type_t fill_rule; /* ...winding_number or ...even_odd */
66
gx_path_type_t clip_rule; /* ditto */
67
pxeColorSpace_t color_space;
69
int size; /* # of bytes */
70
byte data[256 * 3]; /* up to 8-bit samples */
72
struct pts_ { /* buffer for accumulating path points */
73
gs_int_point current; /* current point as of start of data */
76
gs_int_point data[NUM_POINTS];
78
struct ch_ { /* cache for downloaded characters */
79
#define MAX_CACHED_CHARS 400
80
#define MAX_CHAR_DATA 500000
81
#define MAX_CHAR_SIZE 5000
82
#define CHAR_HASH_FACTOR 247
83
ushort table[MAX_CACHED_CHARS * 3 / 2];
87
} data[MAX_CACHED_CHARS];
88
int next_in; /* next data element to fill in */
89
int next_out; /* next data element to discard */
90
int count; /* of occupied data elements */
96
gs_public_st_suffix_add0_final(st_device_pclxl, gx_device_pclxl,
98
device_pclxl_enum_ptrs, device_pclxl_reloc_ptrs,
99
gx_device_finalize, st_device_vector);
101
#define pclxl_device_body(dname, depth)\
102
std_device_dci_type_body(gx_device_pclxl, 0, dname, &st_device_pclxl,\
103
DEFAULT_WIDTH_10THS * X_DPI / 10,\
104
DEFAULT_HEIGHT_10THS * Y_DPI / 10,\
106
(depth > 8 ? 3 : 1), depth,\
107
(depth > 1 ? 255 : 1), (depth > 8 ? 255 : 0),\
108
(depth > 1 ? 256 : 2), (depth > 8 ? 256 : 1))
110
/* Driver procedures */
111
static dev_proc_open_device(pclxl_open_device);
112
static dev_proc_output_page(pclxl_output_page);
113
static dev_proc_close_device(pclxl_close_device);
114
static dev_proc_copy_mono(pclxl_copy_mono);
115
static dev_proc_copy_color(pclxl_copy_color);
116
static dev_proc_fill_mask(pclxl_fill_mask);
118
static dev_proc_get_params(pclxl_get_params);
119
static dev_proc_put_params(pclxl_put_params);
121
/*static dev_proc_draw_thin_line(pclxl_draw_thin_line); */
122
static dev_proc_begin_image(pclxl_begin_image);
123
static dev_proc_strip_copy_rop(pclxl_strip_copy_rop);
125
#define pclxl_device_procs(map_rgb_color, map_color_rgb)\
128
NULL, /* get_initial_matrix */\
129
NULL, /* sync_output */\
132
map_rgb_color, /* differs */\
133
map_color_rgb, /* differs */\
134
gdev_vector_fill_rectangle,\
135
NULL, /* tile_rectangle */\
138
NULL, /* draw_line */\
139
NULL, /* get_bits */\
142
NULL, /* map_cmyk_color */\
143
NULL, /* get_xfont_procs */\
144
NULL, /* get_xfont_device */\
145
NULL, /* map_rgb_alpha_color */\
146
gx_page_device_get_page_device,\
147
NULL, /* get_alpha_bits */\
148
NULL, /* copy_alpha */\
149
NULL, /* get_band */\
150
NULL, /* copy_rop */\
151
gdev_vector_fill_path,\
152
gdev_vector_stroke_path,\
154
gdev_vector_fill_trapezoid,\
155
gdev_vector_fill_parallelogram,\
156
gdev_vector_fill_triangle,\
157
NULL /****** WRONG ******/, /* draw_thin_line */\
159
NULL, /* image_data */\
160
NULL, /* end_image */\
161
NULL, /* strip_tile_rectangle */\
162
pclxl_strip_copy_rop\
165
const gx_device_pclxl gs_pxlmono_device = {
166
pclxl_device_body("pxlmono", 8),
167
pclxl_device_procs(gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb)
170
const gx_device_pclxl gs_pxlcolor_device = {
171
pclxl_device_body("pxlcolor", 24),
172
pclxl_device_procs(gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb)
175
/* ---------------- Other utilities ---------------- */
177
static inline stream *
178
pclxl_stream(gx_device_pclxl *xdev)
180
return gdev_vector_stream((gx_device_vector *)xdev);
183
/* Initialize for a page. */
185
pclxl_page_init(gx_device_pclxl * xdev)
187
gdev_vector_init((gx_device_vector *)xdev);
188
xdev->in_page = false;
189
xdev->fill_rule = gx_path_type_winding_number;
190
xdev->clip_rule = gx_path_type_winding_number;
191
xdev->color_space = eNoColorSpace;
192
xdev->palette.size = 0;
193
xdev->font_set = false;
196
/* Test whether a RGB color is actually a gray shade. */
197
#define RGB_IS_GRAY(ci) ((ci) >> 8 == ((ci) & 0xffff))
199
/* Set the color space and (optionally) palette. */
201
pclxl_set_color_space(gx_device_pclxl * xdev, pxeColorSpace_t color_space)
203
if (xdev->color_space != color_space) {
204
stream *s = pclxl_stream(xdev);
206
px_put_ub(s, (byte)color_space);
207
px_put_ac(s, pxaColorSpace, pxtSetColorSpace);
208
xdev->color_space = color_space;
212
pclxl_set_color_palette(gx_device_pclxl * xdev, pxeColorSpace_t color_space,
213
const byte * palette, uint palette_size)
215
if (xdev->color_space != color_space ||
216
xdev->palette.size != palette_size ||
217
memcmp(xdev->palette.data, palette, palette_size)
219
stream *s = pclxl_stream(xdev);
220
static const byte csp_[] = {
222
DUB(e8Bit), DA(pxaPaletteDepth),
226
px_put_ub(s, (byte)color_space);
228
px_put_u(s, palette_size);
229
px_put_bytes(s, palette, palette_size);
230
px_put_ac(s, pxaPaletteData, pxtSetColorSpace);
231
xdev->color_space = color_space;
232
xdev->palette.size = palette_size;
233
memcpy(xdev->palette.data, palette, palette_size);
237
/* Set a drawing RGB color. */
239
pclxl_set_color(gx_device_pclxl * xdev, const gx_drawing_color * pdc,
240
px_attribute_t null_source, px_tag_t op)
242
stream *s = pclxl_stream(xdev);
244
if (gx_dc_is_pure(pdc)) {
245
gx_color_index color = gx_dc_pure_color(pdc);
247
if (xdev->color_info.num_components == 1 || RGB_IS_GRAY(color)) {
248
pclxl_set_color_space(xdev, eGray);
249
px_put_uba(s, (byte) color, pxaGrayLevel);
251
pclxl_set_color_space(xdev, eRGB);
252
spputc(s, pxt_ubyte_array);
254
spputc(s, (byte) (color >> 16));
255
spputc(s, (byte) (color >> 8));
256
spputc(s, (byte) color);
257
px_put_a(s, pxaRGBColor);
259
} else if (gx_dc_is_null(pdc) || !color_is_set(pdc))
260
px_put_uba(s, 0, null_source);
262
return_error(gs_error_rangecheck);
267
/* Test whether we can handle a given color space in an image. */
268
/* We cannot handle ICCBased color spaces. */
270
pclxl_can_handle_color_space(const gs_color_space * pcs)
272
gs_color_space_index index = gs_color_space_get_index(pcs);
274
if (index == gs_color_space_index_Indexed) {
275
if (pcs->params.indexed.use_proc)
278
gs_color_space_get_index(gs_color_space_indexed_base_space(pcs));
280
return !(index == gs_color_space_index_Separation ||
281
index == gs_color_space_index_Pattern ||
282
index == gs_color_space_index_CIEICC);
285
/* Set brush, pen, and mode for painting a path. */
287
pclxl_set_paints(gx_device_pclxl * xdev, gx_path_type_t type)
289
stream *s = pclxl_stream(xdev);
290
gx_path_type_t rule = type & gx_path_type_rule;
292
if (!(type & gx_path_type_fill) &&
293
(color_is_set(&xdev->saved_fill_color.saved_dev_color) ||
294
!gx_dc_is_null(&xdev->saved_fill_color.saved_dev_color)
297
static const byte nac_[] = {
298
DUB(0), DA(pxaNullBrush), pxtSetBrushSource
302
color_set_null(&xdev->saved_fill_color.saved_dev_color);
303
if (rule != xdev->fill_rule) {
304
px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
306
px_put_ac(s, pxaFillMode, pxtSetFillMode);
307
xdev->fill_rule = rule;
310
if (!(type & gx_path_type_stroke) &&
311
(color_is_set(&xdev->saved_stroke_color.saved_dev_color) ||
312
!gx_dc_is_null(&xdev->saved_fill_color.saved_dev_color)
315
static const byte nac_[] = {
316
DUB(0), DA(pxaNullPen), pxtSetPenSource
320
color_set_null(&xdev->saved_stroke_color.saved_dev_color);
324
/* Set the cursor. */
326
pclxl_set_cursor(gx_device_pclxl * xdev, int x, int y)
328
stream *s = pclxl_stream(xdev);
331
px_put_ac(s, pxaPoint, pxtSetCursor);
335
/* ------ Paths ------ */
337
/* Flush any buffered path points. */
339
px_put_np(stream * s, int count, pxeDataType_t dtype)
341
px_put_uba(s, (byte)count, pxaNumberOfPoints);
342
px_put_uba(s, (byte)dtype, pxaPointType);
345
pclxl_flush_points(gx_device_pclxl * xdev)
347
int count = xdev->points.count;
350
stream *s = pclxl_stream(xdev);
352
int x = xdev->points.current.x, y = xdev->points.current.y;
353
int uor = 0, sor = 0;
354
pxeDataType_t data_type;
356
byte diffs[NUM_POINTS * 2];
359
* Writing N lines using a point list requires 11 + 4*N or 11 +
360
* 2*N bytes, as opposed to 8*N bytes using separate commands;
361
* writing N curves requires 11 + 12*N or 11 + 6*N bytes
362
* vs. 22*N. So it's always shorter to write curves with a
363
* list (except for N = 1 with full-size coordinates, but since
364
* the difference is only 1 byte, we don't bother to ever use
365
* the non-list form), but lines are shorter only if N >= 3
366
* (again, with a 1-byte difference if N = 2 and byte
369
switch (xdev->points.type) {
375
for (i = 0; i < count; ++i) {
376
px_put_ssp(s, xdev->points.data[i].x,
377
xdev->points.data[i].y);
378
px_put_a(s, pxaEndPoint);
383
/* See if we can use byte values. */
384
for (i = di = 0; i < count; ++i, di += 2) {
385
int dx = xdev->points.data[i].x - x;
386
int dy = xdev->points.data[i].y - y;
388
diffs[di] = (byte) dx;
389
diffs[di + 1] = (byte) dy;
391
sor |= (dx + 0x80) | (dy + 0x80);
396
else if (!(sor & ~0xff))
401
/* Use byte values. */
402
useb:px_put_np(s, count, data_type);
404
px_put_data_length(s, count * 2); /* 2 bytes per point */
405
px_put_bytes(s, diffs, count * 2);
409
/* See if we can use byte values. */
410
for (i = di = 0; i < count; i += 3, di += 6) {
411
int dx1 = xdev->points.data[i].x - x;
412
int dy1 = xdev->points.data[i].y - y;
413
int dx2 = xdev->points.data[i + 1].x - x;
414
int dy2 = xdev->points.data[i + 1].y - y;
415
int dx = xdev->points.data[i + 2].x - x;
416
int dy = xdev->points.data[i + 2].y - y;
418
diffs[di] = (byte) dx1;
419
diffs[di + 1] = (byte) dy1;
420
diffs[di + 2] = (byte) dx2;
421
diffs[di + 3] = (byte) dy2;
422
diffs[di + 4] = (byte) dx;
423
diffs[di + 5] = (byte) dy;
424
uor |= dx1 | dy1 | dx2 | dy2 | dx | dy;
425
sor |= (dx1 + 0x80) | (dy1 + 0x80) |
426
(dx2 + 0x80) | (dy2 + 0x80) |
427
(dx + 0x80) | (dy + 0x80);
432
else if (!(sor & ~0xff))
436
op = pxtBezierRelPath;
438
default: /* can't happen */
439
return_error(gs_error_unknownerror);
441
px_put_np(s, count, eSInt16);
443
px_put_data_length(s, count * 4); /* 2 UInt16s per point */
444
for (i = 0; i < count; ++i) {
445
px_put_s(s, xdev->points.data[i].x);
446
px_put_s(s, xdev->points.data[i].y);
448
zap:xdev->points.type = POINTS_NONE;
449
xdev->points.count = 0;
454
/* ------ Images ------ */
456
static image_enum_proc_plane_data(pclxl_image_plane_data);
457
static image_enum_proc_end_image(pclxl_image_end_image);
458
static const gx_image_enum_procs_t pclxl_image_enum_procs = {
459
pclxl_image_plane_data, pclxl_image_end_image
462
/* Begin an image. */
464
pclxl_write_begin_image(gx_device_pclxl * xdev, uint width, uint height,
465
uint dest_width, uint dest_height)
467
stream *s = pclxl_stream(xdev);
469
px_put_usa(s, width, pxaSourceWidth);
470
px_put_usa(s, height, pxaSourceHeight);
471
px_put_usp(s, dest_width, dest_height);
472
px_put_ac(s, pxaDestinationSize, pxtBeginImage);
475
/* Write rows of an image. */
476
/****** IGNORES data_bit ******/
478
pclxl_write_image_data(gx_device_pclxl * xdev, const byte * data, int data_bit,
479
uint raster, uint width_bits, int y, int height)
481
stream *s = pclxl_stream(xdev);
482
uint width_bytes = (width_bits + 7) >> 3;
483
uint num_bytes = ROUND_UP(width_bytes, 4) * height;
484
bool compress = num_bytes >= 8;
487
px_put_usa(s, y, pxaStartLine);
488
px_put_usa(s, height, pxaBlockHeight);
490
stream_RLE_state rlstate;
491
stream_cursor_write w;
492
stream_cursor_read r;
495
* H-P printers require that all the data for an operator be
496
* contained in a single data block. Thus, we must allocate a
497
* temporary buffer for the compressed data. Currently we don't go
498
* to the trouble of doing two passes if we can't allocate a buffer
499
* large enough for the entire transfer.
501
byte *buf = gs_alloc_bytes(xdev->v_memory, num_bytes,
502
"pclxl_write_image_data");
506
s_RLE_set_defaults_inline(&rlstate);
507
rlstate.EndOfData = false;
508
s_RLE_init_inline(&rlstate);
510
w.limit = w.ptr + num_bytes;
512
* If we ever overrun the buffer, it means that the compressed
513
* data was larger than the uncompressed. If this happens,
514
* write the data uncompressed.
516
for (i = 0; i < height; ++i) {
517
r.ptr = data + i * raster - 1;
518
r.limit = r.ptr + width_bytes;
519
if ((*s_RLE_template.process)
520
((stream_state *) & rlstate, &r, &w, true) != 0 ||
524
r.ptr = (const byte *)"\000\000\000\000\000";
525
r.limit = r.ptr + (-(int)width_bytes & 3);
526
if ((*s_RLE_template.process)
527
((stream_state *) & rlstate, &r, &w, true) != 0 ||
533
if ((*s_RLE_template.process)
534
((stream_state *) & rlstate, &r, &w, true) != 0
538
uint count = w.ptr + 1 - buf;
540
px_put_ub(s, eRLECompression);
541
px_put_ac(s, pxaCompressMode, pxtReadImage);
542
px_put_data_length(s, count);
543
px_put_bytes(s, buf, count);
545
gs_free_object(xdev->v_memory, buf, "pclxl_write_image_data");
547
ncfree:gs_free_object(xdev->v_memory, buf, "pclxl_write_image_data");
550
/* Write the data uncompressed. */
551
px_put_ub(s, eNoCompression);
552
px_put_ac(s, pxaCompressMode, pxtReadImage);
553
px_put_data_length(s, num_bytes);
554
for (i = 0; i < height; ++i) {
555
px_put_bytes(s, data + i * raster, width_bytes);
556
px_put_bytes(s, (const byte *)"\000\000\000\000", -(int)width_bytes & 3);
562
pclxl_write_end_image(gx_device_pclxl * xdev)
564
spputc(xdev->strm, pxtEndImage);
567
/* ------ Fonts ------ */
569
/* Write a string (single- or double-byte). */
571
px_put_string(stream * s, const byte * data, uint len, bool wide)
574
spputc(s, pxt_uint16_array);
576
px_put_bytes(s, data, len * 2);
578
spputc(s, pxt_ubyte_array);
580
px_put_bytes(s, data, len);
584
/* Write a 16-bit big-endian value. */
586
px_put_us_be(stream * s, uint i)
588
spputc(s, (byte) (i >> 8));
592
/* Define a bitmap font. The client must call px_put_string */
593
/* with the font name immediately before calling this procedure. */
595
pclxl_define_bitmap_font(gx_device_pclxl * xdev)
597
stream *s = pclxl_stream(xdev);
598
static const byte bfh_[] = {
599
DA(pxaFontName), DUB(0), DA(pxaFontFormat),
601
DUS(8 + 6 + 4 + 6), DA(pxaFontHeaderLength),
603
pxt_dataLengthByte, 8 + 6 + 4 + 6,
605
254, 0, (MAX_CACHED_CHARS + 255) >> 8, 0,
608
static const byte efh_[] = {
609
0xff, 0xff, 0, 0, 0, 0,
614
px_put_us_be(s, (uint) (xdev->HWResolution[0] + 0.5));
615
px_put_us_be(s, (uint) (xdev->HWResolution[1] + 0.5));
619
/* Set the font. The client must call px_put_string */
620
/* with the font name immediately before calling this procedure. */
622
pclxl_set_font(gx_device_pclxl * xdev)
624
stream *s = pclxl_stream(xdev);
625
static const byte sf_[] = {
626
DA(pxaFontName), DUB(1), DA(pxaCharSize), DUS(0), DA(pxaSymbolSet),
633
/* Define a character in a bitmap font. The client must call px_put_string */
634
/* with the font name immediately before calling this procedure. */
636
pclxl_define_bitmap_char(gx_device_pclxl * xdev, uint ccode,
637
const byte * data, uint raster, uint width_bits, uint height)
639
stream *s = pclxl_stream(xdev);
640
uint width_bytes = (width_bits + 7) >> 3;
641
uint size = 10 + width_bytes * height;
644
px_put_ac(s, pxaFontName, pxtBeginChar);
646
px_put_a(s, pxaCharCode);
648
spputc(s, pxt_uint32);
649
px_put_l(s, (ulong) size);
652
px_put_ac(s, pxaCharDataSize, pxtReadChar);
653
px_put_data_length(s, size);
654
px_put_bytes(s, (const byte *)"\000\000\000\000\000\000", 6);
655
px_put_us_be(s, width_bits);
656
px_put_us_be(s, height);
657
for (i = 0; i < height; ++i)
658
px_put_bytes(s, data + i * raster, width_bytes);
659
spputc(s, pxtEndChar);
662
/* Write the name of the only font we define. */
664
pclxl_write_font_name(gx_device_pclxl * xdev)
666
stream *s = pclxl_stream(xdev);
668
px_put_string(s, (const byte *)"@", 1, false);
671
/* Look up a bitmap id, return the index in the character table. */
672
/* If the id is missing, return an index for inserting. */
674
pclxl_char_index(gx_device_pclxl * xdev, gs_id id)
679
for (i = (id * CHAR_HASH_FACTOR) % countof(xdev->chars.table);;
680
i = (i == 0 ? countof(xdev->chars.table) : i) - 1
682
ccode = xdev->chars.table[i];
684
return (i_empty >= 0 ? i_empty : i);
685
else if (ccode == 1) {
688
else if (i == i_empty) /* full table */
690
} else if (xdev->chars.data[ccode].id == id)
695
/* Remove the character table entry at a given index. */
697
pclxl_remove_char(gx_device_pclxl * xdev, int index)
699
uint ccode = xdev->chars.table[index];
705
xdev->chars.used -= xdev->chars.data[ccode].size;
706
xdev->chars.table[index] = 1; /* mark as deleted */
707
i = (index == 0 ? countof(xdev->chars.table) : index) - 1;
708
if (xdev->chars.table[i] == 0) {
709
/* The next slot in probe order is empty. */
710
/* Mark this slot and any deleted predecessors as empty. */
711
for (i = index; xdev->chars.table[i] == 1;
712
i = (i == countof(xdev->chars.table) - 1 ? 0 : i + 1)
714
xdev->chars.table[i] = 0;
718
/* Write a bitmap as a text character if possible. */
719
/* The caller must set the color, cursor, and RasterOp. */
720
/* We know id != gs_no_id. */
722
pclxl_copy_text_char(gx_device_pclxl * xdev, const byte * data,
723
int raster, gx_bitmap_id id, int w, int h)
725
uint width_bytes = (w + 7) >> 3;
726
uint size = width_bytes * h;
729
stream *s = pclxl_stream(xdev);
731
if (size > MAX_CHAR_SIZE)
733
index = pclxl_char_index(xdev, id);
734
if ((ccode = xdev->chars.table[index]) < 2) {
735
/* Enter the character in the table. */
736
while (xdev->chars.used + size > MAX_CHAR_DATA ||
737
xdev->chars.count >= MAX_CACHED_CHARS - 2
739
ccode = xdev->chars.next_out;
740
index = pclxl_char_index(xdev, xdev->chars.data[ccode].id);
741
pclxl_remove_char(xdev, index);
742
xdev->chars.next_out =
743
(ccode == MAX_CACHED_CHARS - 1 ? 2 : ccode + 1);
745
index = pclxl_char_index(xdev, id);
746
ccode = xdev->chars.next_in;
747
xdev->chars.data[ccode].id = id;
748
xdev->chars.data[ccode].size = size;
749
xdev->chars.table[index] = ccode;
750
xdev->chars.next_in =
751
(ccode == MAX_CACHED_CHARS - 1 ? 2 : ccode + 1);
752
if (!xdev->chars.count++) {
753
/* This is the very first character. */
754
pclxl_write_font_name(xdev);
755
pclxl_define_bitmap_font(xdev);
757
xdev->chars.used += size;
758
pclxl_write_font_name(xdev);
759
pclxl_define_bitmap_char(xdev, ccode, data, raster, w, h);
761
if (!xdev->font_set) {
762
pclxl_write_font_name(xdev);
763
pclxl_set_font(xdev);
764
xdev->font_set = true;
768
cc_bytes[0] = (byte) ccode;
769
cc_bytes[1] = ccode >> 8;
770
px_put_string(s, cc_bytes, 1, cc_bytes[1] != 0);
772
px_put_ac(s, pxaTextData, pxtText);
776
/* ---------------- Vector implementation procedures ---------------- */
779
pclxl_beginpage(gx_device_vector * vdev)
781
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
783
* We can't use gdev_vector_stream here, because this may be called
784
* from there before in_page is set.
786
stream *s = vdev->strm;
787
byte media_source = eAutoSelect; /* default */
792
errprintf("PAGE: %d %d\n", xdev->page, xdev->NumCopies);
793
errprintf("INFO: Printing page %d...\n", xdev->page);
797
px_write_page_header(s, (const gx_device *)vdev);
799
if (xdev->ManualFeed_set && xdev->ManualFeed)
801
else if (xdev->MediaPosition_set && xdev->MediaPosition >= 0 )
802
media_source = xdev->MediaPosition;
804
px_write_select_media(s, (const gx_device *)vdev, &xdev->media_size,
806
xdev->page, xdev->Duplex, xdev->Tumble);
808
spputc(s, pxtBeginPage);
813
pclxl_setlinewidth(gx_device_vector * vdev, floatp width)
815
stream *s = gdev_vector_stream(vdev);
817
px_put_us(s, (uint) width);
818
px_put_ac(s, pxaPenWidth, pxtSetPenWidth);
823
pclxl_setlinecap(gx_device_vector * vdev, gs_line_cap cap)
825
stream *s = gdev_vector_stream(vdev);
827
/* The PCL XL cap styles just happen to be identical to PostScript. */
828
px_put_ub(s, (byte) cap);
829
px_put_ac(s, pxaLineCapStyle, pxtSetLineCap);
834
pclxl_setlinejoin(gx_device_vector * vdev, gs_line_join join)
836
stream *s = gdev_vector_stream(vdev);
838
/* The PCL XL join styles just happen to be identical to PostScript. */
839
px_put_ub(s, (byte) join);
840
px_put_ac(s, pxaLineJoinStyle, pxtSetLineJoin);
845
pclxl_setmiterlimit(gx_device_vector * vdev, floatp limit)
847
stream *s = gdev_vector_stream(vdev);
849
* Amazingly enough, the PCL XL specification doesn't allow real
850
* numbers for the miter limit.
852
int i_limit = (int)(limit + 0.5);
854
px_put_u(s, max(i_limit, 1));
855
px_put_ac(s, pxaMiterLength, pxtSetMiterLimit);
860
pclxl_setdash(gx_device_vector * vdev, const float *pattern, uint count,
863
stream *s = gdev_vector_stream(vdev);
866
static const byte nac_[] = {
867
DUB(0), DA(pxaSolidLine)
871
} else if (count > 255)
872
return_error(gs_error_limitcheck);
877
* Astoundingly, PCL XL doesn't allow real numbers here.
878
* Do the best we can.
880
spputc(s, pxt_uint16_array);
881
px_put_ub(s, (byte)count);
882
for (i = 0; i < count; ++i)
883
px_put_s(s, (uint)pattern[i]);
884
px_put_a(s, pxaLineDashStyle);
886
px_put_usa(s, (uint)offset, pxaDashOffset);
888
spputc(s, pxtSetLineDash);
893
pclxl_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop,
894
gs_logical_operation_t diff)
896
stream *s = gdev_vector_stream(vdev);
898
if (diff & lop_S_transparent) {
899
px_put_ub(s, (byte)(lop & lop_S_transparent ? 1 : 0));
900
px_put_ac(s, pxaTxMode, pxtSetSourceTxMode);
902
if (diff & lop_T_transparent) {
903
px_put_ub(s, (byte)(lop & lop_T_transparent ? 1 : 0));
904
px_put_ac(s, pxaTxMode, pxtSetPaintTxMode);
907
px_put_ub(s, (byte)lop_rop(lop));
908
px_put_ac(s, pxaROP3, pxtSetROP);
914
pclxl_can_handle_hl_color(gx_device_vector * vdev, const gs_imager_state * pis,
915
const gx_drawing_color * pdc)
921
pclxl_setfillcolor(gx_device_vector * vdev, const gs_imager_state * pis,
922
const gx_drawing_color * pdc)
924
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
926
return pclxl_set_color(xdev, pdc, pxaNullBrush, pxtSetBrushSource);
930
pclxl_setstrokecolor(gx_device_vector * vdev, const gs_imager_state * pis,
931
const gx_drawing_color * pdc)
933
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
935
return pclxl_set_color(xdev, pdc, pxaNullPen, pxtSetPenSource);
939
pclxl_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1,
940
fixed y1, gx_path_type_t type)
942
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
943
stream *s = gdev_vector_stream(vdev);
945
/* Check for out-of-range points. */
946
#define OUT_OF_RANGE(v) (v < 0 || v >= int2fixed(0x10000))
947
if (OUT_OF_RANGE(x0) || OUT_OF_RANGE(y0) ||
948
OUT_OF_RANGE(x1) || OUT_OF_RANGE(y1)
950
return_error(gs_error_rangecheck);
952
if (type & (gx_path_type_fill | gx_path_type_stroke)) {
953
pclxl_set_paints(xdev, type);
954
px_put_usq_fixed(s, x0, y0, x1, y1);
955
px_put_ac(s, pxaBoundingBox, pxtRectangle);
957
if (type & gx_path_type_clip) {
958
static const byte cr_[] = {
960
DUB(eInterior), DA(pxaClipRegion),
964
px_put_usq_fixed(s, x0, y0, x1, y1);
971
pclxl_beginpath(gx_device_vector * vdev, gx_path_type_t type)
973
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
974
stream *s = gdev_vector_stream(vdev);
976
spputc(s, pxtNewPath);
977
xdev->points.type = POINTS_NONE;
978
xdev->points.count = 0;
983
pclxl_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
986
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
987
int code = pclxl_flush_points(xdev);
991
return pclxl_set_cursor(xdev,
992
xdev->points.current.x = (int)x,
993
xdev->points.current.y = (int)y);
997
pclxl_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
1000
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1002
if (xdev->points.type != POINTS_LINES ||
1003
xdev->points.count >= NUM_POINTS
1005
if (xdev->points.type != POINTS_NONE) {
1006
int code = pclxl_flush_points(xdev);
1011
xdev->points.current.x = (int)x0;
1012
xdev->points.current.y = (int)y0;
1013
xdev->points.type = POINTS_LINES;
1015
gs_int_point *ppt = &xdev->points.data[xdev->points.count++];
1017
ppt->x = (int)x, ppt->y = (int)y;
1023
pclxl_curveto(gx_device_vector * vdev, floatp x0, floatp y0,
1024
floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3,
1025
gx_path_type_t type)
1027
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1029
if (xdev->points.type != POINTS_CURVES ||
1030
xdev->points.count >= NUM_POINTS - 2
1032
if (xdev->points.type != POINTS_NONE) {
1033
int code = pclxl_flush_points(xdev);
1038
xdev->points.current.x = (int)x0;
1039
xdev->points.current.y = (int)y0;
1040
xdev->points.type = POINTS_CURVES;
1043
gs_int_point *ppt = &xdev->points.data[xdev->points.count];
1045
ppt->x = (int)x1, ppt->y = (int)y1, ++ppt;
1046
ppt->x = (int)x2, ppt->y = (int)y2, ++ppt;
1047
ppt->x = (int)x3, ppt->y = (int)y3;
1049
xdev->points.count += 3;
1054
pclxl_closepath(gx_device_vector * vdev, floatp x, floatp y,
1055
floatp x_start, floatp y_start, gx_path_type_t type)
1057
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1058
stream *s = gdev_vector_stream(vdev);
1059
int code = pclxl_flush_points(xdev);
1063
spputc(s, pxtCloseSubPath);
1064
xdev->points.current.x = (int)x_start;
1065
xdev->points.current.y = (int)y_start;
1070
pclxl_endpath(gx_device_vector * vdev, gx_path_type_t type)
1072
gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1073
stream *s = gdev_vector_stream(vdev);
1074
int code = pclxl_flush_points(xdev);
1075
gx_path_type_t rule = type & gx_path_type_rule;
1079
if (type & (gx_path_type_fill | gx_path_type_stroke)) {
1080
if (rule != xdev->fill_rule) {
1081
px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
1083
px_put_ac(s, pxaFillMode, pxtSetFillMode);
1084
xdev->fill_rule = rule;
1086
pclxl_set_paints(xdev, type);
1087
spputc(s, pxtPaintPath);
1089
if (type & gx_path_type_clip) {
1090
static const byte scr_[] = {
1091
DUB(eInterior), DA(pxaClipRegion), pxtSetClipReplace
1094
if (rule != xdev->clip_rule) {
1095
px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
1097
px_put_ac(s, pxaClipMode, pxtSetClipMode);
1098
xdev->clip_rule = rule;
1100
PX_PUT_LIT(s, scr_);
1105
/* Vector implementation procedures */
1107
static const gx_device_vector_procs pclxl_vector_procs = {
1108
/* Page management */
1114
pclxl_setmiterlimit,
1116
gdev_vector_setflat,
1119
pclxl_can_handle_hl_color,
1121
pclxl_setstrokecolor,
1133
/* ---------------- Driver procedures ---------------- */
1135
/* ------ Open/close/page ------ */
1137
/* Open the device. */
1139
pclxl_open_device(gx_device * dev)
1141
gx_device_vector *const vdev = (gx_device_vector *)dev;
1142
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1145
vdev->v_memory = dev->memory; /****** WRONG ******/
1146
vdev->vec_procs = &pclxl_vector_procs;
1147
code = gdev_vector_open_file_options(vdev, 512,
1148
VECTOR_OPEN_FILE_SEQUENTIAL);
1152
pclxl_page_init(xdev);
1153
px_write_file_header(vdev->strm, dev);
1154
xdev->media_size = pxeMediaSize_next; /* no size selected */
1155
memset(&xdev->chars, 0, sizeof(xdev->chars));
1156
xdev->chars.next_in = xdev->chars.next_out = 2;
1160
/* Wrap up ("output") a page. */
1161
/* We only support flush = true */
1163
pclxl_output_page(gx_device * dev, int num_copies, int flush)
1165
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1168
/* Note that unlike close_device, end_page must not omit blank pages. */
1170
pclxl_beginpage((gx_device_vector *)dev);
1172
px_put_usa(s, (uint)num_copies, pxaPageCopies); /* num_copies */
1173
spputc(s, pxtEndPage);
1175
pclxl_page_init(xdev);
1176
if (ferror(xdev->file))
1177
return_error(gs_error_ioerror);
1178
return gx_finish_output_page(dev, num_copies, flush);
1181
/* Close the device. */
1182
/* Note that if this is being called as a result of finalization, */
1183
/* the stream may no longer exist. */
1185
pclxl_close_device(gx_device * dev)
1187
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1188
FILE *file = xdev->file;
1191
fputc(pxtEndPage, file);
1192
px_write_file_trailer(file);
1193
return gdev_vector_close_file((gx_device_vector *)dev);
1196
/* ------ One-for-one images ------ */
1198
static const byte eBit_values[] = {
1199
0, e1Bit, 0, 0, e4Bit, 0, 0, 0, e8Bit
1202
/* Copy a monochrome bitmap. */
1204
pclxl_copy_mono(gx_device * dev, const byte * data, int data_x, int raster,
1205
gx_bitmap_id id, int x, int y, int w, int h,
1206
gx_color_index zero, gx_color_index one)
1208
gx_device_vector *const vdev = (gx_device_vector *)dev;
1209
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1212
gx_color_index color0 = zero, color1 = one;
1213
gs_logical_operation_t lop;
1214
byte palette[2 * 3];
1216
pxeColorSpace_t color_space;
1218
fit_copy(dev, data, data_x, raster, id, x, y, w, h);
1219
code = gdev_vector_update_clip_path(vdev, NULL);
1224
return gx_default_copy_mono(dev, data, data_x, raster, id,
1225
x, y, w, h, zero, one);
1227
pclxl_set_cursor(xdev, x, y);
1228
if (id != gs_no_id && zero == gx_no_color_index &&
1229
one != gx_no_color_index && data_x == 0
1231
gx_drawing_color dcolor;
1233
set_nonclient_dev_color(&dcolor, one);
1234
pclxl_setfillcolor(vdev, NULL, &dcolor);
1235
if (pclxl_copy_text_char(xdev, data, raster, id, w, h) >= 0)
1239
* The following doesn't work if we're writing white with a mask.
1240
* We'll fix it eventually.
1242
* This is a slightly better version than before (see bug 688372).
1245
if (zero == gx_no_color_index) {
1246
/* one != gx_no_color_index */
1247
lop = rop3_S | lop_S_transparent;
1248
color0 = (1 << dev->color_info.depth) - 1;
1249
} else if (one == gx_no_color_index) {
1250
/* zero != gx_no_color_index */
1251
lop = rop3_S | lop_S_transparent;
1252
color1 = (1 << dev->color_info.depth) - 1;
1254
/* both != no_color_index */
1258
if_debug3('b', "zero %d one %d noidx %08X\n", zero, one, gx_no_color_index);
1259
if ((zero == gx_no_color_index) &&
1260
(one == gx_no_color_index))
1262
lop = lop_T_transparent |rop3_S;
1267
if (dev->color_info.num_components == 1 ||
1268
(RGB_IS_GRAY(color0) && RGB_IS_GRAY(color1))
1270
palette[0] = (byte) color0;
1271
palette[1] = (byte) color1;
1273
color_space = eGray;
1274
if_debug2('b', "color palette %02X %02X\n", palette[0], palette[1]);
1276
palette[0] = (byte) (color0 >> 16);
1277
palette[1] = (byte) (color0 >> 8);
1278
palette[2] = (byte) color0;
1279
palette[3] = (byte) (color1 >> 16);
1280
palette[4] = (byte) (color1 >> 8);
1281
palette[5] = (byte) color1;
1285
code = gdev_vector_update_log_op(vdev, lop);
1288
pclxl_set_color_palette(xdev, color_space, palette, palette_size);
1289
s = pclxl_stream(xdev);
1291
static const byte mi_[] = {
1292
DUB(e1Bit), DA(pxaColorDepth),
1293
DUB(eIndexedPixel), DA(pxaColorMapping)
1298
pclxl_write_begin_image(xdev, w, h, w, h);
1299
pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h);
1300
pclxl_write_end_image(xdev);
1304
/* Copy a color bitmap. */
1306
pclxl_copy_color(gx_device * dev,
1307
const byte * base, int sourcex, int raster, gx_bitmap_id id,
1308
int x, int y, int w, int h)
1310
gx_device_vector *const vdev = (gx_device_vector *)dev;
1311
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1316
fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
1317
code = gdev_vector_update_clip_path(vdev, NULL);
1322
source_bit = sourcex * dev->color_info.depth;
1323
if ((source_bit & 7) != 0)
1324
return gx_default_copy_color(dev, base, sourcex, raster, id,
1326
gdev_vector_update_log_op(vdev, rop3_S);
1327
pclxl_set_cursor(xdev, x, y);
1328
s = pclxl_stream(xdev);
1330
static const byte ci_[] = {
1332
DUB(eDirectPixel), DA(pxaColorMapping)
1335
px_put_ub(s, eBit_values[dev->color_info.depth /
1336
dev->color_info.num_components]);
1339
pclxl_write_begin_image(xdev, w, h, w, h);
1340
pclxl_write_image_data(xdev, base, source_bit, raster,
1341
w * dev->color_info.depth, 0, h);
1342
pclxl_write_end_image(xdev);
1348
pclxl_fill_mask(gx_device * dev,
1349
const byte * data, int data_x, int raster, gx_bitmap_id id,
1350
int x, int y, int w, int h,
1351
const gx_drawing_color * pdcolor, int depth,
1352
gs_logical_operation_t lop, const gx_clip_path * pcpath)
1354
gx_device_vector *const vdev = (gx_device_vector *)dev;
1355
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1359
fit_copy(dev, data, data_x, raster, id, x, y, w, h);
1360
if ((data_x & 7) != 0 || !gx_dc_is_pure(pdcolor) || depth > 1)
1361
return gx_default_fill_mask(dev, data, data_x, raster, id,
1362
x, y, w, h, pdcolor, depth,
1364
code = gdev_vector_update_clip_path(vdev, pcpath);
1367
code = gdev_vector_update_fill_color(vdev, NULL, pdcolor);
1370
pclxl_set_cursor(xdev, x, y);
1371
if (id != gs_no_id && data_x == 0) {
1372
code = gdev_vector_update_log_op(vdev, lop);
1375
if (pclxl_copy_text_char(xdev, data, raster, id, w, h) >= 0)
1378
code = gdev_vector_update_log_op(vdev,
1379
lop | rop3_S | lop_S_transparent);
1382
pclxl_set_color_palette(xdev, eGray, (const byte *)"\377\000", 2);
1383
s = pclxl_stream(xdev);
1385
static const byte mi_[] = {
1386
DUB(e1Bit), DA(pxaColorDepth),
1387
DUB(eIndexedPixel), DA(pxaColorMapping)
1392
pclxl_write_begin_image(xdev, w, h, w, h);
1393
pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h);
1394
pclxl_write_end_image(xdev);
1398
/* Do a RasterOp. */
1400
pclxl_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
1401
uint sraster, gx_bitmap_id id,
1402
const gx_color_index * scolors,
1403
const gx_strip_bitmap * textures,
1404
const gx_color_index * tcolors,
1405
int x, int y, int width, int height,
1406
int phase_x, int phase_y, gs_logical_operation_t lop)
1407
{ /* We can't do general RasterOps yet. */
1408
/****** WORK IN PROGRESS ******/
1412
/* ------ High-level images ------ */
1414
#define MAX_ROW_DATA 500000 /* arbitrary */
1415
typedef struct pclxl_image_enum_s {
1416
gdev_vector_image_enum_common;
1420
int num_rows; /* # of allocated rows */
1424
} pclxl_image_enum_t;
1425
gs_private_st_suffix_add1(st_pclxl_image_enum, pclxl_image_enum_t,
1426
"pclxl_image_enum_t", pclxl_image_enum_enum_ptrs,
1427
pclxl_image_enum_reloc_ptrs, st_vector_image_enum,
1430
/* Start processing an image. */
1432
pclxl_begin_image(gx_device * dev,
1433
const gs_imager_state * pis, const gs_image_t * pim,
1434
gs_image_format_t format, const gs_int_rect * prect,
1435
const gx_drawing_color * pdcolor,
1436
const gx_clip_path * pcpath, gs_memory_t * mem,
1437
gx_image_enum_common_t ** pinfo)
1439
gx_device_vector *const vdev = (gx_device_vector *)dev;
1440
gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1441
const gs_color_space *pcs = pim->ColorSpace;
1442
pclxl_image_enum_t *pie;
1447
* Following should divide by num_planes, but we only handle chunky
1448
* images, i.e., num_planes = 1.
1450
int bits_per_pixel =
1451
(pim->ImageMask ? 1 :
1452
pim->BitsPerComponent * gs_color_space_num_components(pcs));
1457
* Check whether we can handle this image. PCL XL 1.0 and 2.0 only
1458
* handle orthogonal transformations.
1460
gs_matrix_invert(&pim->ImageMatrix, &mat);
1461
gs_matrix_multiply(&mat, &ctm_only(pis), &mat);
1462
/* Currently we only handle portrait transformations. */
1463
if (mat.xx <= 0 || mat.xy != 0 || mat.yx != 0 || mat.yy <= 0 ||
1465
(!gx_dc_is_pure(pdcolor) || pim->CombineWithColor) :
1466
(!pclxl_can_handle_color_space(pim->ColorSpace) ||
1467
(bits_per_pixel != 1 && bits_per_pixel != 4 &&
1468
bits_per_pixel != 8 && bits_per_pixel !=24))) ||
1469
format != gs_image_format_chunky ||
1473
row_raster = (bits_per_pixel * pim->Width + 7) >> 3;
1474
num_rows = MAX_ROW_DATA / row_raster;
1475
if (num_rows > pim->Height)
1476
num_rows = pim->Height;
1479
pie = gs_alloc_struct(mem, pclxl_image_enum_t, &st_pclxl_image_enum,
1480
"pclxl_begin_image");
1481
row_data = gs_alloc_bytes(mem, num_rows * row_raster,
1482
"pclxl_begin_image(rows)");
1483
if (pie == 0 || row_data == 0) {
1484
code = gs_note_error(gs_error_VMerror);
1487
code = gdev_vector_begin_image(vdev, pis, pim, format, prect,
1488
pdcolor, pcpath, mem,
1489
&pclxl_image_enum_procs,
1490
(gdev_vector_image_enum_t *)pie);
1494
pie->rows.data = row_data;
1495
pie->rows.num_rows = num_rows;
1496
pie->rows.first_y = 0;
1497
pie->rows.raster = row_raster;
1498
*pinfo = (gx_image_enum_common_t *) pie;
1500
gs_logical_operation_t lop = pis->log_op;
1502
if (pim->ImageMask) {
1503
const byte *palette = (const byte *)
1504
(pim->Decode[0] ? "\377\000" : "\000\377");
1506
code = gdev_vector_update_fill_color(vdev,
1507
NULL, /* use process color */
1511
code = gdev_vector_update_log_op
1512
(vdev, lop | rop3_S | lop_S_transparent);
1515
pclxl_set_color_palette(xdev, eGray, palette, 2);
1517
if (bits_per_pixel == 24 ) {
1518
stream *s = pclxl_stream(xdev);
1519
if (dev->color_info.num_components == 1) {
1520
pclxl_set_color_space(xdev, eGray);
1521
px_put_uba(s, (byte) 0x00, pxaGrayLevel);
1523
pclxl_set_color_space(xdev, eRGB);
1524
spputc(s, pxt_ubyte_array);
1526
spputc(s, (byte) 0x00);
1527
spputc(s, (byte) 0x00);
1528
spputc(s, (byte) 0x00);
1529
px_put_a(s, pxaRGBColor);
1531
spputc(s, (byte) pxtSetBrushSource);
1533
int bpc = pim->BitsPerComponent;
1534
int num_components = pie->plane_depths[0] * pie->num_planes / bpc;
1535
int sample_max = (1 << bpc) - 1;
1536
byte palette[256 * 3];
1539
code = gdev_vector_update_log_op
1540
(vdev, (pim->CombineWithColor ? lop : rop3_know_T_0(lop)));
1543
for (i = 0; i < 1 << bits_per_pixel; ++i) {
1545
gx_device_color devc;
1549
for (j = num_components - 1; j >= 0; cv >>= bpc, --j)
1550
cc.paint.values[j] = pim->Decode[j * 2] +
1552
(pim->Decode[j * 2 + 1] - pim->Decode[j * 2]) /
1554
(*pcs->type->remap_color)
1555
(&cc, pcs, &devc, pis, dev, gs_color_select_source);
1556
if (!gx_dc_is_pure(&devc))
1557
return_error(gs_error_Fatal);
1558
ci = gx_dc_pure_color(&devc);
1559
if (dev->color_info.num_components == 1) {
1560
palette[i] = (byte)ci;
1562
byte *ppal = &palette[i * 3];
1564
ppal[0] = (byte) (ci >> 16);
1565
ppal[1] = (byte) (ci >> 8);
1566
ppal[2] = (byte) ci;
1569
if (dev->color_info.num_components == 1)
1570
pclxl_set_color_palette(xdev, eGray, palette,
1571
1 << bits_per_pixel);
1573
pclxl_set_color_palette(xdev, eRGB, palette,
1574
3 << bits_per_pixel);
1580
gs_free_object(mem, row_data, "pclxl_begin_image(rows)");
1581
gs_free_object(mem, pie, "pclxl_begin_image");
1583
if (dev->color_info.num_components == 1)
1584
pclxl_set_color_space(xdev, eGray);
1586
pclxl_set_color_space(xdev, eRGB);
1587
return gx_default_begin_image(dev, pis, pim, format, prect,
1588
pdcolor, pcpath, mem, pinfo);
1591
/* Write one strip of an image, from pie->rows.first_y to pie->y. */
1593
image_transform_x(const pclxl_image_enum_t *pie, int sx)
1595
return (int)((pie->mat.tx + sx * pie->mat.xx + 0.5) /
1596
((const gx_device_pclxl *)pie->dev)->scale.x);
1599
image_transform_y(const pclxl_image_enum_t *pie, int sy)
1601
return (int)((pie->mat.ty + sy * pie->mat.yy + 0.5) /
1602
((const gx_device_pclxl *)pie->dev)->scale.y);
1606
pclxl_image_write_rows(pclxl_image_enum_t *pie)
1608
gx_device_pclxl *const xdev = (gx_device_pclxl *)pie->dev;
1609
stream *s = pclxl_stream(xdev);
1610
int y = pie->rows.first_y;
1612
int xo = image_transform_x(pie, 0);
1613
int yo = image_transform_y(pie, y);
1614
int dw = image_transform_x(pie, pie->width) - xo;
1615
int dh = image_transform_y(pie, y + h) - yo;
1616
int rows_raster=pie->rows.raster;
1618
if (dw <= 0 || dh <= 0)
1620
pclxl_set_cursor(xdev, xo, yo);
1621
if (pie->bits_per_pixel==24) {
1622
static const byte ci_[] = {
1624
DUB(eDirectPixel), DA(pxaColorMapping)
1627
px_put_ub(s, eBit_values[8]);
1629
if (xdev->color_info.depth==8) {
1630
byte *in=pie->rows.data;
1631
byte *out=pie->rows.data;
1635
for (j=0; j<h; j++) {
1636
for (i=0; i<rows_raster; i++) {
1637
*out = (byte)( ((*(in+0) * (ulong) lum_red_weight) +
1638
(*(in+1) * (ulong) lum_green_weight) +
1639
(*(in+3) * (ulong) lum_blue_weight) +
1640
(lum_all_weights / 2)) / lum_all_weights);
1647
static const byte ii_[] = {
1649
DUB(eIndexedPixel), DA(pxaColorMapping)
1651
px_put_ub(s, eBit_values[pie->bits_per_pixel]);
1654
pclxl_write_begin_image(xdev, pie->width, h, dw, dh);
1655
pclxl_write_image_data(xdev, pie->rows.data, 0, rows_raster,
1656
rows_raster << 3, 0, h);
1657
pclxl_write_end_image(xdev);
1661
/* Process the next piece of an image. */
1663
pclxl_image_plane_data(gx_image_enum_common_t * info,
1664
const gx_image_plane_t * planes, int height,
1667
pclxl_image_enum_t *pie = (pclxl_image_enum_t *) info;
1668
int data_bit = planes[0].data_x * info->plane_depths[0];
1669
int width_bits = pie->width * info->plane_depths[0];
1672
/****** SHOULD HANDLE NON-BYTE-ALIGNED DATA ******/
1673
if (width_bits != pie->bits_per_row || (data_bit & 7) != 0)
1674
return_error(gs_error_rangecheck);
1675
if (height > pie->height - pie->y)
1676
height = pie->height - pie->y;
1677
for (i = 0; i < height; pie->y++, ++i) {
1678
if (pie->y - pie->rows.first_y == pie->rows.num_rows) {
1679
int code = pclxl_image_write_rows(pie);
1683
pie->rows.first_y = pie->y;
1685
memcpy(pie->rows.data +
1686
pie->rows.raster * (pie->y - pie->rows.first_y),
1687
planes[0].data + planes[0].raster * i + (data_bit >> 3),
1690
*rows_used = height;
1691
return pie->y >= pie->height;
1694
/* Clean up by releasing the buffers. */
1696
pclxl_image_end_image(gx_image_enum_common_t * info, bool draw_last)
1698
pclxl_image_enum_t *pie = (pclxl_image_enum_t *) info;
1701
/* Write the final strip, if any. */
1702
if (pie->y > pie->rows.first_y && draw_last)
1703
code = pclxl_image_write_rows(pie);
1704
gs_free_object(pie->memory, pie->rows.data, "pclxl_end_image(rows)");
1705
gx_image_free_enum(&info);
1710
* 'pclxl_get_params()' - Get pagedevice parameters.
1713
static int /* O - Error status */
1714
pclxl_get_params(gx_device *dev, /* I - Device info */
1715
gs_param_list *plist) /* I - Parameter list */
1717
gx_device_pclxl *xdev; /* PCL XL device */
1718
int code; /* Return code */
1722
* First process the "standard" page device parameters...
1725
if ((code = gdev_vector_get_params(dev, plist)) < 0)
1729
* Then write the PCL-XL parameters...
1732
xdev = (gx_device_pclxl *)dev;
1734
if ((code = param_write_bool(plist, "Duplex", &(xdev->Duplex))) < 0)
1737
if ((code = param_write_int(plist, "MediaPosition",
1738
&(xdev->MediaPosition))) < 0)
1741
if ((code = param_write_bool(plist, "Tumble", &(xdev->Tumble))) < 0)
1749
* 'pclxl_put_params()' - Set pagedevice parameters.
1752
static int /* O - Error status */
1753
pclxl_put_params(gx_device *dev, /* I - Device info */
1754
gs_param_list *plist) /* I - Parameter list */
1756
gx_device_pclxl *xdev; /* PCL XL device */
1757
int code; /* Error code */
1758
int intval; /* Integer value */
1759
bool boolval; /* Boolean value */
1763
* Process PCL-XL driver parameters...
1766
xdev = (gx_device_pclxl *)dev;
1768
#define intoption(name, sname, type) \
1769
if ((code = param_read_int(plist, sname, &intval)) < 0) \
1771
param_signal_error(plist, sname, code); \
1774
else if (code == 0) \
1776
xdev->name = (type)intval; \
1779
#define booloption(name, sname) \
1780
if ((code = param_read_bool(plist, sname, &boolval)) < 0) \
1782
if ((code = param_read_null(plist, sname)) < 0) \
1784
param_signal_error(plist, sname, code); \
1788
xdev->name = false; \
1790
else if (code == 0) \
1791
xdev->name = (bool)boolval;
1793
booloption(Duplex, "Duplex")
1794
intoption(MediaPosition, "MediaPosition", int)
1795
if (code == 0) xdev->MediaPosition_set = true;
1796
booloption(Tumble, "Tumble")
1799
* Then process standard page device parameters...
1802
if ((code = gdev_vector_put_params(dev, plist)) < 0)