~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to base/gdevpx.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: gdevpx.c 11306 2010-05-24 16:31:58Z mvrhel $ */
 
14
/* $Id$ */
15
15
/* H-P PCL XL driver */
16
16
#include "math_.h"
17
17
#include "memory_.h"
34
34
#include "gdevpcl.h" /* for gdev_pcl_mode3compress() */
35
35
#include <stdlib.h> /* abs() */
36
36
 
37
 
 
38
37
/* ---------------- Device definition ---------------- */
39
38
 
40
39
/* Define the default resolution. */
57
56
    /* Additional state information */
58
57
    pxeMediaSize_t media_size;
59
58
    bool ManualFeed;            /* map ps setpage commands to pxl */
60
 
    bool ManualFeed_set;         
 
59
    bool ManualFeed_set;
61
60
    int MediaPosition;          /* MediaPosition attribute */
62
61
    int MediaPosition_set;
63
62
    int page;                   /* Page number starting at 0 */
67
66
    gx_path_type_t clip_rule;   /* ditto */
68
67
    pxeColorSpace_t color_space;
69
68
    struct pal_ {
70
 
        int size;               /* # of bytes */
71
 
        byte data[256 * 3];     /* up to 8-bit samples */
 
69
        int size;               /* # of bytes */
 
70
        byte data[256 * 3];     /* up to 8-bit samples */
72
71
    } palette;
73
72
    struct pts_ {               /* buffer for accumulating path points */
74
 
        gs_int_point current;   /* current point as of start of data */
75
 
        point_type_t type;
76
 
        int count;
77
 
        gs_int_point data[NUM_POINTS];
 
73
        gs_int_point current;   /* current point as of start of data */
 
74
        point_type_t type;
 
75
        int count;
 
76
        gs_int_point data[NUM_POINTS];
78
77
    } points;
79
78
    struct ch_ {                /* cache for downloaded characters */
80
79
#define MAX_CACHED_CHARS 400
81
80
#define MAX_CHAR_DATA 500000
82
81
#define MAX_CHAR_SIZE 5000
83
82
#define CHAR_HASH_FACTOR 247
84
 
        ushort table[MAX_CACHED_CHARS * 3 / 2];
85
 
        struct cd_ {
86
 
            gs_id id;           /* key */
87
 
            uint size;
88
 
        } data[MAX_CACHED_CHARS];
89
 
        int next_in;            /* next data element to fill in */
90
 
        int next_out;           /* next data element to discard */
91
 
        int count;              /* of occupied data elements */
92
 
        ulong used;
 
83
        ushort table[MAX_CACHED_CHARS * 3 / 2];
 
84
        struct cd_ {
 
85
            gs_id id;           /* key */
 
86
            uint size;
 
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 */
 
91
        ulong used;
93
92
    } chars;
94
93
    bool font_set;
95
94
    int state_rotated; /* 0, 1, 2, -1, mutiple of 90 deg */
102
101
} gx_device_pclxl;
103
102
 
104
103
gs_public_st_suffix_add0_final(st_device_pclxl, gx_device_pclxl,
105
 
                               "gx_device_pclxl",
106
 
                               device_pclxl_enum_ptrs, device_pclxl_reloc_ptrs,
107
 
                               gx_device_finalize, st_device_vector);
 
104
                               "gx_device_pclxl",
 
105
                               device_pclxl_enum_ptrs, device_pclxl_reloc_ptrs,
 
106
                               gx_device_finalize, st_device_vector);
108
107
 
109
108
#define pclxl_device_body(dname, depth)\
110
109
  std_device_dci_type_body(gx_device_pclxl, 0, dname, &st_device_pclxl,\
111
 
                           DEFAULT_WIDTH_10THS * X_DPI / 10,\
112
 
                           DEFAULT_HEIGHT_10THS * Y_DPI / 10,\
113
 
                           X_DPI, Y_DPI,\
114
 
                           (depth > 8 ? 3 : 1), depth,\
115
 
                           (depth > 1 ? 255 : 1), (depth > 8 ? 255 : 0),\
116
 
                           (depth > 1 ? 256 : 2), (depth > 8 ? 256 : 1))
 
110
                           DEFAULT_WIDTH_10THS * X_DPI / 10,\
 
111
                           DEFAULT_HEIGHT_10THS * Y_DPI / 10,\
 
112
                           X_DPI, Y_DPI,\
 
113
                           (depth > 8 ? 3 : 1), depth,\
 
114
                           (depth > 1 ? 255 : 1), (depth > 8 ? 255 : 0),\
 
115
                           (depth > 1 ? 256 : 2), (depth > 8 ? 256 : 1))
117
116
 
118
117
/* Driver procedures */
119
118
static dev_proc_open_device(pclxl_open_device);
132
131
 
133
132
#define pclxl_device_procs(map_rgb_color, map_color_rgb)\
134
133
{\
135
 
        pclxl_open_device,\
136
 
        NULL,                   /* get_initial_matrix */\
137
 
        NULL,                   /* sync_output */\
138
 
        pclxl_output_page,\
139
 
        pclxl_close_device,\
140
 
        map_rgb_color,          /* differs */\
141
 
        map_color_rgb,          /* differs */\
142
 
        gdev_vector_fill_rectangle,\
143
 
        NULL,                   /* tile_rectangle */\
144
 
        pclxl_copy_mono,\
145
 
        pclxl_copy_color,\
146
 
        NULL,                   /* draw_line */\
147
 
        NULL,                   /* get_bits */\
148
 
        pclxl_get_params,\
149
 
        pclxl_put_params,\
150
 
        NULL,                   /* map_cmyk_color */\
151
 
        NULL,                   /* get_xfont_procs */\
152
 
        NULL,                   /* get_xfont_device */\
153
 
        NULL,                   /* map_rgb_alpha_color */\
154
 
        gx_page_device_get_page_device,\
155
 
        NULL,                   /* get_alpha_bits */\
156
 
        NULL,                   /* copy_alpha */\
157
 
        NULL,                   /* get_band */\
158
 
        NULL,                   /* copy_rop */\
159
 
        gdev_vector_fill_path,\
160
 
        gdev_vector_stroke_path,\
161
 
        pclxl_fill_mask,\
162
 
        gdev_vector_fill_trapezoid,\
163
 
        gdev_vector_fill_parallelogram,\
164
 
        gdev_vector_fill_triangle,\
165
 
        NULL /****** WRONG ******/,     /* draw_thin_line */\
166
 
        pclxl_begin_image,\
167
 
        NULL,                   /* image_data */\
168
 
        NULL,                   /* end_image */\
169
 
        NULL,                   /* strip_tile_rectangle */\
170
 
        pclxl_strip_copy_rop\
 
134
        pclxl_open_device,\
 
135
        NULL,                   /* get_initial_matrix */\
 
136
        NULL,                   /* sync_output */\
 
137
        pclxl_output_page,\
 
138
        pclxl_close_device,\
 
139
        map_rgb_color,          /* differs */\
 
140
        map_color_rgb,          /* differs */\
 
141
        gdev_vector_fill_rectangle,\
 
142
        NULL,                   /* tile_rectangle */\
 
143
        pclxl_copy_mono,\
 
144
        pclxl_copy_color,\
 
145
        NULL,                   /* draw_line */\
 
146
        NULL,                   /* get_bits */\
 
147
        pclxl_get_params,\
 
148
        pclxl_put_params,\
 
149
        NULL,                   /* map_cmyk_color */\
 
150
        NULL,                   /* get_xfont_procs */\
 
151
        NULL,                   /* get_xfont_device */\
 
152
        NULL,                   /* map_rgb_alpha_color */\
 
153
        gx_page_device_get_page_device,\
 
154
        NULL,                   /* get_alpha_bits */\
 
155
        NULL,                   /* copy_alpha */\
 
156
        NULL,                   /* get_band */\
 
157
        NULL,                   /* copy_rop */\
 
158
        gdev_vector_fill_path,\
 
159
        gdev_vector_stroke_path,\
 
160
        pclxl_fill_mask,\
 
161
        gdev_vector_fill_trapezoid,\
 
162
        gdev_vector_fill_parallelogram,\
 
163
        gdev_vector_fill_triangle,\
 
164
        NULL /****** WRONG ******/,     /* draw_thin_line */\
 
165
        pclxl_begin_image,\
 
166
        NULL,                   /* image_data */\
 
167
        NULL,                   /* end_image */\
 
168
        NULL,                   /* strip_tile_rectangle */\
 
169
        pclxl_strip_copy_rop\
171
170
}
172
171
 
173
172
const gx_device_pclxl gs_pxlmono_device = {
215
214
pclxl_set_color_space(gx_device_pclxl * xdev, pxeColorSpace_t color_space)
216
215
{
217
216
    if (xdev->color_space != color_space) {
218
 
        stream *s = pclxl_stream(xdev);
 
217
        stream *s = pclxl_stream(xdev);
219
218
 
220
 
        px_put_ub(s, (byte)color_space);
221
 
        px_put_ac(s, pxaColorSpace, pxtSetColorSpace);
222
 
        xdev->color_space = color_space;
223
 
        xdev->palette.size = 0; /* purge the cached palette */
 
219
        px_put_ub(s, (byte)color_space);
 
220
        px_put_ac(s, pxaColorSpace, pxtSetColorSpace);
 
221
        xdev->color_space = color_space;
 
222
        xdev->palette.size = 0; /* purge the cached palette */
224
223
    }
225
224
}
226
225
static void
227
226
pclxl_set_color_palette(gx_device_pclxl * xdev, pxeColorSpace_t color_space,
228
 
                        const byte * palette, uint palette_size)
 
227
                        const byte * palette, uint palette_size)
229
228
{
230
229
    if (xdev->color_space != color_space ||
231
 
        xdev->palette.size != palette_size ||
232
 
        memcmp(xdev->palette.data, palette, palette_size)
233
 
        ) {
234
 
        stream *s = pclxl_stream(xdev);
235
 
        static const byte csp_[] = {
236
 
            DA(pxaColorSpace),
237
 
            DUB(e8Bit), DA(pxaPaletteDepth),
238
 
            pxt_ubyte_array
239
 
        };
 
230
        xdev->palette.size != palette_size ||
 
231
        memcmp(xdev->palette.data, palette, palette_size)
 
232
        ) {
 
233
        stream *s = pclxl_stream(xdev);
 
234
        static const byte csp_[] = {
 
235
            DA(pxaColorSpace),
 
236
            DUB(e8Bit), DA(pxaPaletteDepth),
 
237
            pxt_ubyte_array
 
238
        };
240
239
 
241
 
        px_put_ub(s, (byte)color_space);
242
 
        PX_PUT_LIT(s, csp_);
243
 
        px_put_u(s, palette_size);
244
 
        px_put_bytes(s, palette, palette_size);
245
 
        px_put_ac(s, pxaPaletteData, pxtSetColorSpace);
246
 
        xdev->color_space = color_space;
247
 
        xdev->palette.size = palette_size;
248
 
        memcpy(xdev->palette.data, palette, palette_size);
 
240
        px_put_ub(s, (byte)color_space);
 
241
        PX_PUT_LIT(s, csp_);
 
242
        px_put_u(s, palette_size);
 
243
        px_put_bytes(s, palette, palette_size);
 
244
        px_put_ac(s, pxaPaletteData, pxtSetColorSpace);
 
245
        xdev->color_space = color_space;
 
246
        xdev->palette.size = palette_size;
 
247
        memcpy(xdev->palette.data, palette, palette_size);
249
248
    }
250
249
}
251
250
 
268
267
    if (op == pxtSetBrushSource) {
269
268
        if (xdev->brush_null)
270
269
            return 0;
271
 
        else 
 
270
        else
272
271
            xdev->brush_null = true;
273
272
    }
274
273
    px_put_uba(s, 0, (byte)null_source);
279
278
/* Set a drawing RGB color. */
280
279
static int
281
280
pclxl_set_color(gx_device_pclxl * xdev, const gx_drawing_color * pdc,
282
 
                px_attribute_t null_source, px_tag_t op)
 
281
                px_attribute_t null_source, px_tag_t op)
283
282
{
284
283
    stream *s = pclxl_stream(xdev);
285
284
 
286
285
    if (gx_dc_is_pure(pdc)) {
287
 
        gx_color_index color = gx_dc_pure_color(pdc);
288
 
 
289
 
        if (op == pxtSetPenSource)   xdev->pen_null   = false;
290
 
        if (op == pxtSetBrushSource) xdev->brush_null = false;
291
 
 
292
 
        if (xdev->color_info.num_components == 1 || RGB_IS_GRAY(color)) {
293
 
            pclxl_set_color_space(xdev, eGray);
294
 
            px_put_uba(s, (byte) color, pxaGrayLevel);
295
 
        } else {
296
 
            pclxl_set_color_space(xdev, eRGB);
297
 
            spputc(s, pxt_ubyte_array);
298
 
            px_put_ub(s, 3);
299
 
            spputc(s, (byte) (color >> 16));
300
 
            spputc(s, (byte) (color >> 8));
301
 
            spputc(s, (byte) color);
302
 
            px_put_a(s, pxaRGBColor);
303
 
        }
 
286
        gx_color_index color = gx_dc_pure_color(pdc);
 
287
 
 
288
        if (op == pxtSetPenSource)   xdev->pen_null   = false;
 
289
        if (op == pxtSetBrushSource) xdev->brush_null = false;
 
290
 
 
291
        if (xdev->color_info.num_components == 1 || RGB_IS_GRAY(color)) {
 
292
            pclxl_set_color_space(xdev, eGray);
 
293
            px_put_uba(s, (byte) color, pxaGrayLevel);
 
294
        } else {
 
295
            pclxl_set_color_space(xdev, eRGB);
 
296
            spputc(s, pxt_ubyte_array);
 
297
            px_put_ub(s, 3);
 
298
            spputc(s, (byte) (color >> 16));
 
299
            spputc(s, (byte) (color >> 8));
 
300
            spputc(s, (byte) color);
 
301
            px_put_a(s, pxaRGBColor);
 
302
        }
304
303
    } else if (gx_dc_is_null(pdc) || !color_is_set(pdc)) {
305
 
        if (op == pxtSetPenSource || op == pxtSetBrushSource)
306
 
            return pclxl_set_cached_nulls(xdev, null_source, op);
307
 
        else
308
 
            px_put_uba(s, 0, null_source);
 
304
        if (op == pxtSetPenSource || op == pxtSetBrushSource)
 
305
            return pclxl_set_cached_nulls(xdev, null_source, op);
 
306
        else
 
307
            px_put_uba(s, 0, null_source);
309
308
    } else
310
 
        return_error(gs_error_rangecheck);
 
309
        return_error(gs_error_rangecheck);
311
310
    spputc(s, (byte)op);
312
311
    return 0;
313
312
}
320
319
    gs_color_space_index index = gs_color_space_get_index(pcs);
321
320
 
322
321
    if (index == gs_color_space_index_Indexed) {
323
 
        if (pcs->params.indexed.use_proc)
324
 
            return false;
325
 
        index =
326
 
            gs_color_space_get_index(gs_color_space_indexed_base_space(pcs));
 
322
        if (pcs->params.indexed.use_proc)
 
323
            return false;
 
324
        index =
 
325
            gs_color_space_get_index(gs_color_space_indexed_base_space(pcs));
327
326
    }
328
327
    return !(index == gs_color_space_index_Separation ||
329
 
             index == gs_color_space_index_Pattern ||
 
328
             index == gs_color_space_index_Pattern ||
330
329
             index == gs_color_space_index_ICC);
331
330
}
332
331
 
338
337
    gx_path_type_t rule = type & gx_path_type_rule;
339
338
 
340
339
    if (!(type & gx_path_type_fill) &&
341
 
        (color_is_set(&xdev->saved_fill_color.saved_dev_color) ||
342
 
        !gx_dc_is_null(&xdev->saved_fill_color.saved_dev_color) 
343
 
        )
344
 
        ) {
345
 
        pclxl_set_cached_nulls(xdev, pxaNullBrush, pxtSetBrushSource);
346
 
        color_set_null(&xdev->saved_fill_color.saved_dev_color);
347
 
        if (rule != xdev->fill_rule) {
348
 
            px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
349
 
                       eNonZeroWinding));
350
 
            px_put_ac(s, pxaFillMode, pxtSetFillMode);
351
 
            xdev->fill_rule = rule;
352
 
        }
 
340
        (color_is_set(&xdev->saved_fill_color.saved_dev_color) ||
 
341
        !gx_dc_is_null(&xdev->saved_fill_color.saved_dev_color)
 
342
        )
 
343
        ) {
 
344
        pclxl_set_cached_nulls(xdev, pxaNullBrush, pxtSetBrushSource);
 
345
        color_set_null(&xdev->saved_fill_color.saved_dev_color);
 
346
        if (rule != xdev->fill_rule) {
 
347
            px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
 
348
                       eNonZeroWinding));
 
349
            px_put_ac(s, pxaFillMode, pxtSetFillMode);
 
350
            xdev->fill_rule = rule;
 
351
        }
353
352
    }
354
353
    if (!(type & gx_path_type_stroke) &&
355
 
        (color_is_set(&xdev->saved_stroke_color.saved_dev_color) ||
356
 
        !gx_dc_is_null(&xdev->saved_stroke_color.saved_dev_color)
357
 
         )
358
 
        ) {
359
 
        pclxl_set_cached_nulls(xdev, pxaNullPen, pxtSetPenSource);
360
 
        color_set_null(&xdev->saved_stroke_color.saved_dev_color);
 
354
        (color_is_set(&xdev->saved_stroke_color.saved_dev_color) ||
 
355
        !gx_dc_is_null(&xdev->saved_stroke_color.saved_dev_color)
 
356
         )
 
357
        ) {
 
358
        pclxl_set_cached_nulls(xdev, pxaNullPen, pxtSetPenSource);
 
359
        color_set_null(&xdev->saved_stroke_color.saved_dev_color);
361
360
    }
362
361
}
363
362
 
439
438
    int count = xdev->points.count;
440
439
 
441
440
    if (count) {
442
 
        stream *s = pclxl_stream(xdev);
443
 
        px_tag_t op;
444
 
        int x = xdev->points.current.x, y = xdev->points.current.y;
445
 
        int uor = 0, sor = 0;
446
 
        pxeDataType_t data_type;
447
 
        int i, di;
448
 
        byte diffs[NUM_POINTS * 2];
449
 
        floatp x_scale = 1;
450
 
        floatp y_scale = 1;
451
 
        int temp_origin_x = 0, temp_origin_y = 0;
452
 
        int count_smalls = 0;
453
 
 
454
 
        if (xdev->points.type != POINTS_NONE) {
455
 
            for (i = 0; i < count; ++i) {
456
 
                if ((abs(xdev->points.data[i].x) > 0x7FFF) || (abs(xdev->points.data[i].y) > 0x7FFF))
457
 
                    xdev->scaled = true;
458
 
                if ((abs(xdev->points.data[i].x) < 0x8000) && (abs(xdev->points.data[i].y) < 0x8000)) {
459
 
                    if ((temp_origin_x != xdev->points.data[i].x) || (temp_origin_y != xdev->points.data[i].y)) {
460
 
                        temp_origin_x = xdev->points.data[i].x;
461
 
                        temp_origin_y = xdev->points.data[i].y;
462
 
                        count_smalls++;
463
 
                    }
464
 
                }
465
 
            }
466
 
            if (xdev->scaled) {
467
 
                /* if there are some points with small co-ordinates, we set origin to it
468
 
                   before scaling, an unset afterwards. This works around problems
469
 
                   for small co-ordinates being moved snapped to 32767 x 32767 grid points;
470
 
                   if there are more than 1, the other points
471
 
                   will be in-accurate, unfortunately */
472
 
                if (count_smalls) {
473
 
                    pclxl_set_page_origin(s, temp_origin_x, temp_origin_y);
474
 
                }
475
 
                for (i = 0; i < count; ++i) {
476
 
                    x_scale = max(((floatp) abs(xdev->points.data[i].x - temp_origin_x))/0x7FFF , x_scale);
477
 
                    y_scale = max(((floatp) abs(xdev->points.data[i].y - temp_origin_y))/0x7FFF , y_scale);
478
 
                }
479
 
                for (i = 0; i < count; ++i) {
480
 
                    xdev->points.data[i].x = (int)((xdev->points.data[i].x - temp_origin_x)/x_scale + 0.5);
481
 
                    xdev->points.data[i].y = (int)((xdev->points.data[i].y - temp_origin_y)/y_scale + 0.5);
482
 
                }
483
 
                x = (int)((x - temp_origin_x)/x_scale + 0.5);
484
 
                y = (int)((y - temp_origin_y)/y_scale + 0.5);
485
 
                pclxl_set_page_scale(xdev, x_scale, y_scale);
486
 
            } else {
487
 
                /* don't reset origin if we did not scale */
488
 
                count_smalls = 0;
489
 
            }
490
 
        }
491
 
        /*
492
 
         * Writing N lines using a point list requires 11 + 4*N or 11 +
493
 
         * 2*N bytes, as opposed to 8*N bytes using separate commands;
494
 
         * writing N curves requires 11 + 12*N or 11 + 6*N bytes
495
 
         * vs. 22*N.  So it's always shorter to write curves with a
496
 
         * list (except for N = 1 with full-size coordinates, but since
497
 
         * the difference is only 1 byte, we don't bother to ever use
498
 
         * the non-list form), but lines are shorter only if N >= 3
499
 
         * (again, with a 1-byte difference if N = 2 and byte
500
 
         * coordinates).
501
 
         */
502
 
        switch (xdev->points.type) {
503
 
            case POINTS_NONE:
504
 
                return 0;
505
 
            case POINTS_LINES:
506
 
                op = pxtLinePath;
507
 
                if (count < 3) {
508
 
                    for (i = 0; i < count; ++i) {
509
 
                        px_put_ssp(s, xdev->points.data[i].x,
510
 
                                xdev->points.data[i].y);
511
 
                        px_put_a(s, pxaEndPoint);
512
 
                        spputc(s, (byte)op);
513
 
                    }
514
 
                    pclxl_unset_page_scale(xdev);
515
 
                    if (count_smalls)
516
 
                        pclxl_set_page_origin(s, -temp_origin_x, -temp_origin_y);
517
 
                    goto zap;
518
 
                }
519
 
                /* See if we can use byte values. */
520
 
                for (i = di = 0; i < count; ++i, di += 2) {
521
 
                    int dx = xdev->points.data[i].x - x;
522
 
                    int dy = xdev->points.data[i].y - y;
523
 
 
524
 
                    diffs[di] = (byte) dx;
525
 
                    diffs[di + 1] = (byte) dy;
526
 
                    uor |= dx | dy;
527
 
                    sor |= (dx + 0x80) | (dy + 0x80);
528
 
                    x += dx, y += dy;
529
 
                }
530
 
                if (!(uor & ~0xff))
531
 
                    data_type = eUByte;
532
 
                else if (!(sor & ~0xff))
533
 
                    data_type = eSByte;
534
 
                else
535
 
                    break;
536
 
                op = pxtLineRelPath;
537
 
                /* Use byte values. */
538
 
              useb:px_put_np(s, count, data_type);
539
 
                spputc(s, (byte)op);
540
 
                px_put_data_length(s, count * 2);       /* 2 bytes per point */
541
 
                px_put_bytes(s, diffs, count * 2);
542
 
                pclxl_unset_page_scale(xdev);
543
 
                if (count_smalls)
544
 
                    pclxl_set_page_origin(s, -temp_origin_x, -temp_origin_y);
545
 
                goto zap;
546
 
            case POINTS_CURVES:
547
 
                op = pxtBezierPath;
548
 
                /* See if we can use byte values. */
549
 
                for (i = di = 0; i < count; i += 3, di += 6) {
550
 
                    int dx1 = xdev->points.data[i].x - x;
551
 
                    int dy1 = xdev->points.data[i].y - y;
552
 
                    int dx2 = xdev->points.data[i + 1].x - x;
553
 
                    int dy2 = xdev->points.data[i + 1].y - y;
554
 
                    int dx = xdev->points.data[i + 2].x - x;
555
 
                    int dy = xdev->points.data[i + 2].y - y;
556
 
 
557
 
                    diffs[di] = (byte) dx1;
558
 
                    diffs[di + 1] = (byte) dy1;
559
 
                    diffs[di + 2] = (byte) dx2;
560
 
                    diffs[di + 3] = (byte) dy2;
561
 
                    diffs[di + 4] = (byte) dx;
562
 
                    diffs[di + 5] = (byte) dy;
563
 
                    uor |= dx1 | dy1 | dx2 | dy2 | dx | dy;
564
 
                    sor |= (dx1 + 0x80) | (dy1 + 0x80) |
565
 
                        (dx2 + 0x80) | (dy2 + 0x80) |
566
 
                        (dx + 0x80) | (dy + 0x80);
567
 
                    x += dx, y += dy;
568
 
                }
569
 
                if (!(uor & ~0xff))
570
 
                    data_type = eUByte;
571
 
                else if (!(sor & ~0xff))
572
 
                    data_type = eSByte;
573
 
                else
574
 
                    break;
575
 
                op = pxtBezierRelPath;
576
 
                goto useb;
577
 
            default:            /* can't happen */
578
 
                return_error(gs_error_unknownerror);
579
 
        }
580
 
        px_put_np(s, count, eSInt16);
581
 
        spputc(s, (byte)op);
582
 
        px_put_data_length(s, count * 4);       /* 2 UInt16s per point */
583
 
        for (i = 0; i < count; ++i) {
584
 
            px_put_s(s, xdev->points.data[i].x);
585
 
            px_put_s(s, xdev->points.data[i].y);
586
 
        }
587
 
        pclxl_unset_page_scale(xdev);
588
 
        if (count_smalls)
589
 
            pclxl_set_page_origin(s, -temp_origin_x, -temp_origin_y);
 
441
        stream *s = pclxl_stream(xdev);
 
442
        px_tag_t op;
 
443
        int x = xdev->points.current.x, y = xdev->points.current.y;
 
444
        int uor = 0, sor = 0;
 
445
        pxeDataType_t data_type;
 
446
        int i, di;
 
447
        byte diffs[NUM_POINTS * 2];
 
448
        floatp x_scale = 1;
 
449
        floatp y_scale = 1;
 
450
        int temp_origin_x = 0, temp_origin_y = 0;
 
451
        int count_smalls = 0;
 
452
 
 
453
        if (xdev->points.type != POINTS_NONE) {
 
454
            for (i = 0; i < count; ++i) {
 
455
                if ((abs(xdev->points.data[i].x) > 0x7FFF) || (abs(xdev->points.data[i].y) > 0x7FFF))
 
456
                    xdev->scaled = true;
 
457
                if ((abs(xdev->points.data[i].x) < 0x8000) && (abs(xdev->points.data[i].y) < 0x8000)) {
 
458
                    if ((temp_origin_x != xdev->points.data[i].x) || (temp_origin_y != xdev->points.data[i].y)) {
 
459
                        temp_origin_x = xdev->points.data[i].x;
 
460
                        temp_origin_y = xdev->points.data[i].y;
 
461
                        count_smalls++;
 
462
                    }
 
463
                }
 
464
            }
 
465
            if (xdev->scaled) {
 
466
                /* if there are some points with small co-ordinates, we set origin to it
 
467
                   before scaling, an unset afterwards. This works around problems
 
468
                   for small co-ordinates being moved snapped to 32767 x 32767 grid points;
 
469
                   if there are more than 1, the other points
 
470
                   will be in-accurate, unfortunately */
 
471
                if (count_smalls) {
 
472
                    pclxl_set_page_origin(s, temp_origin_x, temp_origin_y);
 
473
                }
 
474
                for (i = 0; i < count; ++i) {
 
475
                    x_scale = max(((floatp) abs(xdev->points.data[i].x - temp_origin_x))/0x7FFF , x_scale);
 
476
                    y_scale = max(((floatp) abs(xdev->points.data[i].y - temp_origin_y))/0x7FFF , y_scale);
 
477
                }
 
478
                for (i = 0; i < count; ++i) {
 
479
                    xdev->points.data[i].x = (int)((xdev->points.data[i].x - temp_origin_x)/x_scale + 0.5);
 
480
                    xdev->points.data[i].y = (int)((xdev->points.data[i].y - temp_origin_y)/y_scale + 0.5);
 
481
                }
 
482
                x = (int)((x - temp_origin_x)/x_scale + 0.5);
 
483
                y = (int)((y - temp_origin_y)/y_scale + 0.5);
 
484
                pclxl_set_page_scale(xdev, x_scale, y_scale);
 
485
            } else {
 
486
                /* don't reset origin if we did not scale */
 
487
                count_smalls = 0;
 
488
            }
 
489
        }
 
490
        /*
 
491
         * Writing N lines using a point list requires 11 + 4*N or 11 +
 
492
         * 2*N bytes, as opposed to 8*N bytes using separate commands;
 
493
         * writing N curves requires 11 + 12*N or 11 + 6*N bytes
 
494
         * vs. 22*N.  So it's always shorter to write curves with a
 
495
         * list (except for N = 1 with full-size coordinates, but since
 
496
         * the difference is only 1 byte, we don't bother to ever use
 
497
         * the non-list form), but lines are shorter only if N >= 3
 
498
         * (again, with a 1-byte difference if N = 2 and byte
 
499
         * coordinates).
 
500
         */
 
501
        switch (xdev->points.type) {
 
502
            case POINTS_NONE:
 
503
                return 0;
 
504
            case POINTS_LINES:
 
505
                op = pxtLinePath;
 
506
                if (count < 3) {
 
507
                    for (i = 0; i < count; ++i) {
 
508
                        px_put_ssp(s, xdev->points.data[i].x,
 
509
                                xdev->points.data[i].y);
 
510
                        px_put_a(s, pxaEndPoint);
 
511
                        spputc(s, (byte)op);
 
512
                    }
 
513
                    pclxl_unset_page_scale(xdev);
 
514
                    if (count_smalls)
 
515
                        pclxl_set_page_origin(s, -temp_origin_x, -temp_origin_y);
 
516
                    goto zap;
 
517
                }
 
518
                /* See if we can use byte values. */
 
519
                for (i = di = 0; i < count; ++i, di += 2) {
 
520
                    int dx = xdev->points.data[i].x - x;
 
521
                    int dy = xdev->points.data[i].y - y;
 
522
 
 
523
                    diffs[di] = (byte) dx;
 
524
                    diffs[di + 1] = (byte) dy;
 
525
                    uor |= dx | dy;
 
526
                    sor |= (dx + 0x80) | (dy + 0x80);
 
527
                    x += dx, y += dy;
 
528
                }
 
529
                if (!(uor & ~0xff))
 
530
                    data_type = eUByte;
 
531
                else if (!(sor & ~0xff))
 
532
                    data_type = eSByte;
 
533
                else
 
534
                    break;
 
535
                op = pxtLineRelPath;
 
536
                /* Use byte values. */
 
537
              useb:px_put_np(s, count, data_type);
 
538
                spputc(s, (byte)op);
 
539
                px_put_data_length(s, count * 2);       /* 2 bytes per point */
 
540
                px_put_bytes(s, diffs, count * 2);
 
541
                pclxl_unset_page_scale(xdev);
 
542
                if (count_smalls)
 
543
                    pclxl_set_page_origin(s, -temp_origin_x, -temp_origin_y);
 
544
                goto zap;
 
545
            case POINTS_CURVES:
 
546
                op = pxtBezierPath;
 
547
                /* See if we can use byte values. */
 
548
                for (i = di = 0; i < count; i += 3, di += 6) {
 
549
                    int dx1 = xdev->points.data[i].x - x;
 
550
                    int dy1 = xdev->points.data[i].y - y;
 
551
                    int dx2 = xdev->points.data[i + 1].x - x;
 
552
                    int dy2 = xdev->points.data[i + 1].y - y;
 
553
                    int dx = xdev->points.data[i + 2].x - x;
 
554
                    int dy = xdev->points.data[i + 2].y - y;
 
555
 
 
556
                    diffs[di] = (byte) dx1;
 
557
                    diffs[di + 1] = (byte) dy1;
 
558
                    diffs[di + 2] = (byte) dx2;
 
559
                    diffs[di + 3] = (byte) dy2;
 
560
                    diffs[di + 4] = (byte) dx;
 
561
                    diffs[di + 5] = (byte) dy;
 
562
                    uor |= dx1 | dy1 | dx2 | dy2 | dx | dy;
 
563
                    sor |= (dx1 + 0x80) | (dy1 + 0x80) |
 
564
                        (dx2 + 0x80) | (dy2 + 0x80) |
 
565
                        (dx + 0x80) | (dy + 0x80);
 
566
                    x += dx, y += dy;
 
567
                }
 
568
                if (!(uor & ~0xff))
 
569
                    data_type = eUByte;
 
570
                else if (!(sor & ~0xff))
 
571
                    data_type = eSByte;
 
572
                else
 
573
                    break;
 
574
                op = pxtBezierRelPath;
 
575
                goto useb;
 
576
            default:            /* can't happen */
 
577
                return_error(gs_error_unknownerror);
 
578
        }
 
579
        px_put_np(s, count, eSInt16);
 
580
        spputc(s, (byte)op);
 
581
        px_put_data_length(s, count * 4);       /* 2 UInt16s per point */
 
582
        for (i = 0; i < count; ++i) {
 
583
            px_put_s(s, xdev->points.data[i].x);
 
584
            px_put_s(s, xdev->points.data[i].y);
 
585
        }
 
586
        pclxl_unset_page_scale(xdev);
 
587
        if (count_smalls)
 
588
            pclxl_set_page_origin(s, -temp_origin_x, -temp_origin_y);
590
589
      zap:xdev->points.type = POINTS_NONE;
591
 
        xdev->points.count = 0;
 
590
        xdev->points.count = 0;
592
591
    }
593
592
    return 0;
594
593
}
604
603
/* Begin an image. */
605
604
static void
606
605
pclxl_write_begin_image(gx_device_pclxl * xdev, uint width, uint height,
607
 
                        uint dest_width, uint dest_height)
 
606
                        uint dest_width, uint dest_height)
608
607
{
609
608
    stream *s = pclxl_stream(xdev);
610
609
 
620
619
/* RLE version */
621
620
static void
622
621
pclxl_write_image_data_RLE(gx_device_pclxl * xdev, const byte * base, int data_bit,
623
 
                       uint raster, uint width_bits, int y, int height)
 
622
                       uint raster, uint width_bits, int y, int height)
624
623
{
625
624
    stream *s = pclxl_stream(xdev);
626
625
    uint width_bytes = (width_bits + 7) >> 3;
634
633
    px_put_usa(s, y, pxaStartLine);
635
634
    px_put_usa(s, height, pxaBlockHeight);
636
635
    if (compress) {
637
 
        stream_RLE_state rlstate;
638
 
        stream_cursor_write w;
639
 
        stream_cursor_read r;
640
 
 
641
 
        /*
642
 
         * H-P printers require that all the data for an operator be
643
 
         * contained in a single data block.  Thus, we must allocate a
644
 
         * temporary buffer for the compressed data.  Currently we don't go
645
 
         * to the trouble of doing two passes if we can't allocate a buffer
646
 
         * large enough for the entire transfer.
647
 
         */
648
 
        byte *buf = gs_alloc_bytes(xdev->v_memory, num_bytes,
649
 
                                   "pclxl_write_image_data");
650
 
 
651
 
        if (buf == 0)
652
 
            goto nc;
653
 
        s_RLE_set_defaults_inline(&rlstate);
654
 
        rlstate.EndOfData = false;
655
 
        s_RLE_init_inline(&rlstate);
656
 
        w.ptr = buf - 1;
657
 
        w.limit = w.ptr + num_bytes;
658
 
        /*
659
 
         * If we ever overrun the buffer, it means that the compressed
660
 
         * data was larger than the uncompressed.  If this happens,
661
 
         * write the data uncompressed.
662
 
         */
663
 
        for (i = 0; i < height; ++i) {
664
 
            r.ptr = data + i * raster - 1;
665
 
            r.limit = r.ptr + width_bytes;
666
 
            if ((*s_RLE_template.process)
667
 
                ((stream_state *) & rlstate, &r, &w, true) != 0 ||
668
 
                r.ptr != r.limit
669
 
                )
670
 
                goto ncfree;
671
 
            r.ptr = (const byte *)"\000\000\000\000\000";
672
 
            r.limit = r.ptr + (-(int)width_bytes & 3);
673
 
            if ((*s_RLE_template.process)
674
 
                ((stream_state *) & rlstate, &r, &w, true) != 0 ||
675
 
                r.ptr != r.limit
676
 
                )
677
 
                goto ncfree;
678
 
        }
679
 
        r.ptr = r.limit;
680
 
        if ((*s_RLE_template.process)
681
 
            ((stream_state *) & rlstate, &r, &w, true) != 0
682
 
            )
683
 
            goto ncfree;
684
 
        {
685
 
            uint count = w.ptr + 1 - buf;
686
 
 
687
 
            px_put_ub(s, eRLECompression);
688
 
            px_put_ac(s, pxaCompressMode, pxtReadImage);
689
 
            px_put_data_length(s, count);
690
 
            px_put_bytes(s, buf, count);
691
 
        }
692
 
        gs_free_object(xdev->v_memory, buf, "pclxl_write_image_data");
693
 
        return;
 
636
        stream_RLE_state rlstate;
 
637
        stream_cursor_write w;
 
638
        stream_cursor_read r;
 
639
 
 
640
        /*
 
641
         * H-P printers require that all the data for an operator be
 
642
         * contained in a single data block.  Thus, we must allocate a
 
643
         * temporary buffer for the compressed data.  Currently we don't go
 
644
         * to the trouble of doing two passes if we can't allocate a buffer
 
645
         * large enough for the entire transfer.
 
646
         */
 
647
        byte *buf = gs_alloc_bytes(xdev->v_memory, num_bytes,
 
648
                                   "pclxl_write_image_data");
 
649
 
 
650
        if (buf == 0)
 
651
            goto nc;
 
652
        s_RLE_set_defaults_inline(&rlstate);
 
653
        rlstate.EndOfData = false;
 
654
        s_RLE_init_inline(&rlstate);
 
655
        w.ptr = buf - 1;
 
656
        w.limit = w.ptr + num_bytes;
 
657
        /*
 
658
         * If we ever overrun the buffer, it means that the compressed
 
659
         * data was larger than the uncompressed.  If this happens,
 
660
         * write the data uncompressed.
 
661
         */
 
662
        for (i = 0; i < height; ++i) {
 
663
            r.ptr = data + i * raster - 1;
 
664
            r.limit = r.ptr + width_bytes;
 
665
            if ((*s_RLE_template.process)
 
666
                ((stream_state *) & rlstate, &r, &w, true) != 0 ||
 
667
                r.ptr != r.limit
 
668
                )
 
669
                goto ncfree;
 
670
            r.ptr = (const byte *)"\000\000\000\000\000";
 
671
            r.limit = r.ptr + (-(int)width_bytes & 3);
 
672
            if ((*s_RLE_template.process)
 
673
                ((stream_state *) & rlstate, &r, &w, true) != 0 ||
 
674
                r.ptr != r.limit
 
675
                )
 
676
                goto ncfree;
 
677
        }
 
678
        r.ptr = r.limit;
 
679
        if ((*s_RLE_template.process)
 
680
            ((stream_state *) & rlstate, &r, &w, true) != 0
 
681
            )
 
682
            goto ncfree;
 
683
        {
 
684
            uint count = w.ptr + 1 - buf;
 
685
 
 
686
            px_put_ub(s, eRLECompression);
 
687
            px_put_ac(s, pxaCompressMode, pxtReadImage);
 
688
            px_put_data_length(s, count);
 
689
            px_put_bytes(s, buf, count);
 
690
        }
 
691
        gs_free_object(xdev->v_memory, buf, "pclxl_write_image_data");
 
692
        return;
694
693
      ncfree:gs_free_object(xdev->v_memory, buf, "pclxl_write_image_data");
695
694
    }
696
695
 nc:
699
698
    px_put_ac(s, pxaCompressMode, pxtReadImage);
700
699
    px_put_data_length(s, num_bytes);
701
700
    for (i = 0; i < height; ++i) {
702
 
        px_put_bytes(s, data + i * raster, width_bytes);
703
 
        px_put_bytes(s, (const byte *)"\000\000\000\000", -(int)width_bytes & 3);
 
701
        px_put_bytes(s, data + i * raster, width_bytes);
 
702
        px_put_bytes(s, (const byte *)"\000\000\000\000", -(int)width_bytes & 3);
704
703
    }
705
704
}
706
705
/* DeltaRow compression (also called "mode 3"):
712
711
 */
713
712
static void
714
713
pclxl_write_image_data_DeltaRow(gx_device_pclxl * xdev, const byte * base, int data_bit,
715
 
                       uint raster, uint width_bits, int y, int height)
 
714
                       uint raster, uint width_bits, int y, int height)
716
715
{
717
716
    stream *s = pclxl_stream(xdev);
718
717
    uint width_bytes = (width_bits + 7) >> 3;
732
731
    /* the RLE routine can write uncompressed without extra-allocation */
733
732
    if ((buf == 0) || (prow == 0)) {
734
733
        pclxl_write_image_data_RLE(xdev, data, data_bit, raster, width_bits, y, height);
735
 
        return;
 
734
        return;
736
735
    }
737
736
    /* initialize the seed row */
738
737
    memset(prow, 0, width_bytes);
759
758
 
760
759
static void
761
760
pclxl_write_image_data(gx_device_pclxl * xdev, const byte * data, int data_bit,
762
 
                       uint raster, uint width_bits, int y, int height)
 
761
                       uint raster, uint width_bits, int y, int height)
763
762
{
764
763
    /* If we only have 1 line, it does not make sense to do DeltaRow */
765
764
    if (height < 2) {
792
791
px_put_string(stream * s, const byte * data, uint len, bool wide)
793
792
{
794
793
    if (wide) {
795
 
        spputc(s, pxt_uint16_array);
796
 
        px_put_u(s, len);
797
 
        px_put_bytes(s, data, len * 2);
 
794
        spputc(s, pxt_uint16_array);
 
795
        px_put_u(s, len);
 
796
        px_put_bytes(s, data, len * 2);
798
797
    } else {
799
 
        spputc(s, pxt_ubyte_array);
800
 
        px_put_u(s, len);
801
 
        px_put_bytes(s, data, len);
 
798
        spputc(s, pxt_ubyte_array);
 
799
        px_put_u(s, len);
 
800
        px_put_bytes(s, data, len);
802
801
    }
803
802
}
804
803
 
817
816
{
818
817
    stream *s = pclxl_stream(xdev);
819
818
    static const byte bfh_[] = {
820
 
        DA(pxaFontName), DUB(0), DA(pxaFontFormat),
821
 
        pxtBeginFontHeader,
822
 
        DUS(8 + 6 + 4 + 6), DA(pxaFontHeaderLength),
823
 
        pxtReadFontHeader,
824
 
        pxt_dataLengthByte, 8 + 6 + 4 + 6,
825
 
        0, 0, 0, 0,
826
 
        254, 0, (MAX_CACHED_CHARS + 255) >> 8, 0,
827
 
        'B', 'R', 0, 0, 0, 4
 
819
        DA(pxaFontName), DUB(0), DA(pxaFontFormat),
 
820
        pxtBeginFontHeader,
 
821
        DUS(8 + 6 + 4 + 6), DA(pxaFontHeaderLength),
 
822
        pxtReadFontHeader,
 
823
        pxt_dataLengthByte, 8 + 6 + 4 + 6,
 
824
        0, 0, 0, 0,
 
825
        254, 0, (MAX_CACHED_CHARS + 255) >> 8, 0,
 
826
        'B', 'R', 0, 0, 0, 4
828
827
    };
829
828
    static const byte efh_[] = {
830
 
        0xff, 0xff, 0, 0, 0, 0,
831
 
        pxtEndFontHeader
 
829
        0xff, 0xff, 0, 0, 0, 0,
 
830
        pxtEndFontHeader
832
831
    };
833
832
 
834
833
    PX_PUT_LIT(s, bfh_);
844
843
{
845
844
    stream *s = pclxl_stream(xdev);
846
845
    static const byte sf_[] = {
847
 
        DA(pxaFontName), DUB(1), DA(pxaCharSize), DUS(0), DA(pxaSymbolSet),
848
 
        pxtSetFont
 
846
        DA(pxaFontName), DUB(1), DA(pxaCharSize), DUS(0), DA(pxaSymbolSet),
 
847
        pxtSetFont
849
848
    };
850
849
 
851
850
    PX_PUT_LIT(s, sf_);
855
854
/* with the font name immediately before calling this procedure. */
856
855
static void
857
856
pclxl_define_bitmap_char(gx_device_pclxl * xdev, uint ccode,
858
 
               const byte * data, uint raster, uint width_bits, uint height)
 
857
               const byte * data, uint raster, uint width_bits, uint height)
859
858
{
860
859
    stream *s = pclxl_stream(xdev);
861
860
    uint width_bytes = (width_bits + 7) >> 3;
866
865
    px_put_u(s, ccode);
867
866
    px_put_a(s, pxaCharCode);
868
867
    if (size > 0xffff) {
869
 
        spputc(s, pxt_uint32);
870
 
        px_put_l(s, (ulong) size);
 
868
        spputc(s, pxt_uint32);
 
869
        px_put_l(s, (ulong) size);
871
870
    } else
872
 
        px_put_us(s, size);
 
871
        px_put_us(s, size);
873
872
    px_put_ac(s, pxaCharDataSize, pxtReadChar);
874
873
    px_put_data_length(s, size);
875
874
    px_put_bytes(s, (const byte *)"\000\000\000\000\000\000", 6);
876
875
    px_put_us_be(s, width_bits);
877
876
    px_put_us_be(s, height);
878
877
    for (i = 0; i < height; ++i)
879
 
        px_put_bytes(s, data + i * raster, width_bytes);
 
878
        px_put_bytes(s, data + i * raster, width_bytes);
880
879
    spputc(s, pxtEndChar);
881
880
}
882
881
 
898
897
    uint ccode;
899
898
 
900
899
    for (i = (id * CHAR_HASH_FACTOR) % countof(xdev->chars.table);;
901
 
         i = (i == 0 ? countof(xdev->chars.table) : i) - 1
902
 
        ) {
903
 
        ccode = xdev->chars.table[i];
904
 
        if (ccode == 0)
905
 
            return (i_empty >= 0 ? i_empty : i);
906
 
        else if (ccode == 1) {
907
 
            if (i_empty < 0)
908
 
                i_empty = i;
909
 
            else if (i == i_empty)      /* full table */
910
 
                return i;
911
 
        } else if (xdev->chars.data[ccode].id == id)
912
 
            return i;
 
900
         i = (i == 0 ? countof(xdev->chars.table) : i) - 1
 
901
        ) {
 
902
        ccode = xdev->chars.table[i];
 
903
        if (ccode == 0)
 
904
            return (i_empty >= 0 ? i_empty : i);
 
905
        else if (ccode == 1) {
 
906
            if (i_empty < 0)
 
907
                i_empty = i;
 
908
            else if (i == i_empty)      /* full table */
 
909
                return i;
 
910
        } else if (xdev->chars.data[ccode].id == id)
 
911
            return i;
913
912
    }
914
913
}
915
914
 
921
920
    int i;
922
921
 
923
922
    if (ccode < 2)
924
 
        return;
 
923
        return;
925
924
    xdev->chars.count--;
926
925
    xdev->chars.used -= xdev->chars.data[ccode].size;
927
926
    xdev->chars.table[index] = 1;       /* mark as deleted */
928
927
    i = (index == 0 ? countof(xdev->chars.table) : index) - 1;
929
928
    if (xdev->chars.table[i] == 0) {
930
 
        /* The next slot in probe order is empty. */
931
 
        /* Mark this slot and any deleted predecessors as empty. */
932
 
        for (i = index; xdev->chars.table[i] == 1;
933
 
             i = (i == countof(xdev->chars.table) - 1 ? 0 : i + 1)
934
 
            )
935
 
            xdev->chars.table[i] = 0;
 
929
        /* The next slot in probe order is empty. */
 
930
        /* Mark this slot and any deleted predecessors as empty. */
 
931
        for (i = index; xdev->chars.table[i] == 1;
 
932
             i = (i == countof(xdev->chars.table) - 1 ? 0 : i + 1)
 
933
            )
 
934
            xdev->chars.table[i] = 0;
936
935
    }
937
936
}
938
937
 
941
940
/* We know id != gs_no_id. */
942
941
static int
943
942
pclxl_copy_text_char(gx_device_pclxl * xdev, const byte * data,
944
 
                     int raster, gx_bitmap_id id, int w, int h)
 
943
                     int raster, gx_bitmap_id id, int w, int h)
945
944
{
946
945
    uint width_bytes = (w + 7) >> 3;
947
946
    uint size = width_bytes * h;
950
949
    stream *s = pclxl_stream(xdev);
951
950
 
952
951
    if (size > MAX_CHAR_SIZE)
953
 
        return -1;
 
952
        return -1;
954
953
    index = pclxl_char_index(xdev, id);
955
954
    if ((ccode = xdev->chars.table[index]) < 2) {
956
 
        /* Enter the character in the table. */
957
 
        while (xdev->chars.used + size > MAX_CHAR_DATA ||
958
 
               xdev->chars.count >= MAX_CACHED_CHARS - 2
959
 
            ) {
960
 
            ccode = xdev->chars.next_out;
961
 
            index = pclxl_char_index(xdev, xdev->chars.data[ccode].id);
962
 
            pclxl_remove_char(xdev, index);
963
 
            xdev->chars.next_out =
964
 
                (ccode == MAX_CACHED_CHARS - 1 ? 2 : ccode + 1);
965
 
        }
966
 
        index = pclxl_char_index(xdev, id);
967
 
        ccode = xdev->chars.next_in;
968
 
        xdev->chars.data[ccode].id = id;
969
 
        xdev->chars.data[ccode].size = size;
970
 
        xdev->chars.table[index] = ccode;
971
 
        xdev->chars.next_in =
972
 
            (ccode == MAX_CACHED_CHARS - 1 ? 2 : ccode + 1);
973
 
        if (!xdev->chars.count++) {
974
 
            /* This is the very first character. */
975
 
            pclxl_write_font_name(xdev);
976
 
            pclxl_define_bitmap_font(xdev);
977
 
        }
978
 
        xdev->chars.used += size;
979
 
        pclxl_write_font_name(xdev);
980
 
        pclxl_define_bitmap_char(xdev, ccode, data, raster, w, h);
 
955
        /* Enter the character in the table. */
 
956
        while (xdev->chars.used + size > MAX_CHAR_DATA ||
 
957
               xdev->chars.count >= MAX_CACHED_CHARS - 2
 
958
            ) {
 
959
            ccode = xdev->chars.next_out;
 
960
            index = pclxl_char_index(xdev, xdev->chars.data[ccode].id);
 
961
            pclxl_remove_char(xdev, index);
 
962
            xdev->chars.next_out =
 
963
                (ccode == MAX_CACHED_CHARS - 1 ? 2 : ccode + 1);
 
964
        }
 
965
        index = pclxl_char_index(xdev, id);
 
966
        ccode = xdev->chars.next_in;
 
967
        xdev->chars.data[ccode].id = id;
 
968
        xdev->chars.data[ccode].size = size;
 
969
        xdev->chars.table[index] = ccode;
 
970
        xdev->chars.next_in =
 
971
            (ccode == MAX_CACHED_CHARS - 1 ? 2 : ccode + 1);
 
972
        if (!xdev->chars.count++) {
 
973
            /* This is the very first character. */
 
974
            pclxl_write_font_name(xdev);
 
975
            pclxl_define_bitmap_font(xdev);
 
976
        }
 
977
        xdev->chars.used += size;
 
978
        pclxl_write_font_name(xdev);
 
979
        pclxl_define_bitmap_char(xdev, ccode, data, raster, w, h);
981
980
    }
982
981
    if (!xdev->font_set) {
983
 
        pclxl_write_font_name(xdev);
984
 
        pclxl_set_font(xdev);
985
 
        xdev->font_set = true;
 
982
        pclxl_write_font_name(xdev);
 
983
        pclxl_set_font(xdev);
 
984
        xdev->font_set = true;
986
985
    } {
987
 
        byte cc_bytes[2];
 
986
        byte cc_bytes[2];
988
987
 
989
 
        cc_bytes[0] = (byte) ccode;
990
 
        cc_bytes[1] = ccode >> 8;
991
 
        px_put_string(s, cc_bytes, 1, cc_bytes[1] != 0);
 
988
        cc_bytes[0] = (byte) ccode;
 
989
        cc_bytes[1] = ccode >> 8;
 
990
        px_put_string(s, cc_bytes, 1, cc_bytes[1] != 0);
992
991
    }
993
992
    px_put_ac(s, pxaTextData, pxtText);
994
993
    return 0;
1017
1016
 
1018
1017
    px_write_page_header(s, (const gx_device *)vdev);
1019
1018
 
1020
 
    if (xdev->ManualFeed_set && xdev->ManualFeed) 
1021
 
        media_source = 2;
 
1019
    if (xdev->ManualFeed_set && xdev->ManualFeed)
 
1020
        media_source = 2;
1022
1021
    else if (xdev->MediaPosition_set && xdev->MediaPosition >= 0 )
1023
 
        media_source = xdev->MediaPosition;
1024
 
 
 
1022
        media_source = xdev->MediaPosition;
 
1023
 
1025
1024
    px_write_select_media(s, (const gx_device *)vdev, &xdev->media_size,
1026
 
                          &media_source,
 
1025
                          &media_source,
1027
1026
                          xdev->page, xdev->Duplex, xdev->Tumble);
1028
1027
 
1029
1028
    spputc(s, pxtBeginPage);
1085
1084
 
1086
1085
static int
1087
1086
pclxl_setdash(gx_device_vector * vdev, const float *pattern, uint count,
1088
 
              floatp offset)
 
1087
              floatp offset)
1089
1088
{
1090
1089
    stream *s = gdev_vector_stream(vdev);
1091
1090
 
1092
1091
    if (count == 0) {
1093
 
        static const byte nac_[] = {
1094
 
            DUB(0), DA(pxaSolidLine)
1095
 
        };
 
1092
        static const byte nac_[] = {
 
1093
            DUB(0), DA(pxaSolidLine)
 
1094
        };
1096
1095
 
1097
 
        PX_PUT_LIT(s, nac_);
 
1096
        PX_PUT_LIT(s, nac_);
1098
1097
    } else if (count > 255)
1099
 
        return_error(gs_error_limitcheck);
 
1098
        return_error(gs_error_limitcheck);
1100
1099
    else {
1101
 
        uint i;
 
1100
        uint i;
1102
1101
 
1103
 
        /*
1104
 
         * Astoundingly, PCL XL doesn't allow real numbers here.
1105
 
         * Do the best we can.
1106
 
         */
1107
 
        spputc(s, pxt_uint16_array);
1108
 
        px_put_ub(s, (byte)count);
1109
 
        for (i = 0; i < count; ++i)
1110
 
            px_put_s(s, (uint)pattern[i]);
1111
 
        px_put_a(s, pxaLineDashStyle);
1112
 
        if (offset != 0)
1113
 
            px_put_usa(s, (uint)offset, pxaDashOffset);
 
1102
        /*
 
1103
         * Astoundingly, PCL XL doesn't allow real numbers here.
 
1104
         * Do the best we can.
 
1105
         */
 
1106
        spputc(s, pxt_uint16_array);
 
1107
        px_put_ub(s, (byte)count);
 
1108
        for (i = 0; i < count; ++i)
 
1109
            px_put_s(s, (uint)pattern[i]);
 
1110
        px_put_a(s, pxaLineDashStyle);
 
1111
        if (offset != 0)
 
1112
            px_put_usa(s, (uint)offset, pxaDashOffset);
1114
1113
    }
1115
1114
    spputc(s, pxtSetLineDash);
1116
1115
    return 0;
1118
1117
 
1119
1118
static int
1120
1119
pclxl_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop,
1121
 
               gs_logical_operation_t diff)
 
1120
               gs_logical_operation_t diff)
1122
1121
{
1123
1122
    stream *s = gdev_vector_stream(vdev);
1124
1123
 
1125
1124
    if (diff & lop_S_transparent) {
1126
 
        px_put_ub(s, (byte)(lop & lop_S_transparent ? 1 : 0));
1127
 
        px_put_ac(s, pxaTxMode, pxtSetSourceTxMode);
 
1125
        px_put_ub(s, (byte)(lop & lop_S_transparent ? 1 : 0));
 
1126
        px_put_ac(s, pxaTxMode, pxtSetSourceTxMode);
1128
1127
    }
1129
1128
    if (diff & lop_T_transparent) {
1130
 
        px_put_ub(s, (byte)(lop & lop_T_transparent ? 1 : 0));
1131
 
        px_put_ac(s, pxaTxMode, pxtSetPaintTxMode);
 
1129
        px_put_ub(s, (byte)(lop & lop_T_transparent ? 1 : 0));
 
1130
        px_put_ac(s, pxaTxMode, pxtSetPaintTxMode);
1132
1131
    }
1133
1132
    if (lop_rop(diff)) {
1134
 
        px_put_ub(s, (byte)lop_rop(lop));
1135
 
        px_put_ac(s, pxaROP3, pxtSetROP);
 
1133
        px_put_ub(s, (byte)lop_rop(lop));
 
1134
        px_put_ac(s, pxaROP3, pxtSetROP);
1136
1135
    }
1137
1136
    return 0;
1138
1137
}
1139
1138
 
1140
1139
static int
1141
 
pclxl_can_handle_hl_color(gx_device_vector * vdev, const gs_imager_state * pis, 
 
1140
pclxl_can_handle_hl_color(gx_device_vector * vdev, const gs_imager_state * pis,
1142
1141
                   const gx_drawing_color * pdc)
1143
1142
{
1144
1143
    return false;
1145
1144
}
1146
1145
 
1147
1146
static int
1148
 
pclxl_setfillcolor(gx_device_vector * vdev, const gs_imager_state * pis, 
 
1147
pclxl_setfillcolor(gx_device_vector * vdev, const gs_imager_state * pis,
1149
1148
                   const gx_drawing_color * pdc)
1150
1149
{
1151
1150
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1154
1153
}
1155
1154
 
1156
1155
static int
1157
 
pclxl_setstrokecolor(gx_device_vector * vdev, const gs_imager_state * pis, 
 
1156
pclxl_setstrokecolor(gx_device_vector * vdev, const gs_imager_state * pis,
1158
1157
                     const gx_drawing_color * pdc)
1159
1158
{
1160
1159
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1164
1163
 
1165
1164
static int
1166
1165
pclxl_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1,
1167
 
             fixed y1, gx_path_type_t type)
 
1166
             fixed y1, gx_path_type_t type)
1168
1167
{
1169
1168
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1170
1169
    stream *s = gdev_vector_stream(vdev);
1172
1171
    /* Check for out-of-range points. */
1173
1172
#define OUT_OF_RANGE(v) (v < 0 || v >= int2fixed(0x10000))
1174
1173
    if (OUT_OF_RANGE(x0) || OUT_OF_RANGE(y0) ||
1175
 
        OUT_OF_RANGE(x1) || OUT_OF_RANGE(y1)
1176
 
        )
1177
 
        return_error(gs_error_rangecheck);
 
1174
        OUT_OF_RANGE(x1) || OUT_OF_RANGE(y1)
 
1175
        )
 
1176
        return_error(gs_error_rangecheck);
1178
1177
#undef OUT_OF_RANGE
1179
1178
    if (type & (gx_path_type_fill | gx_path_type_stroke)) {
1180
 
        pclxl_set_paints(xdev, type);
1181
 
        px_put_usq_fixed(s, x0, y0, x1, y1);
1182
 
        px_put_ac(s, pxaBoundingBox, pxtRectangle);
 
1179
        pclxl_set_paints(xdev, type);
 
1180
        px_put_usq_fixed(s, x0, y0, x1, y1);
 
1181
        px_put_ac(s, pxaBoundingBox, pxtRectangle);
1183
1182
    }
1184
1183
    if (type & gx_path_type_clip) {
1185
 
        static const byte cr_[] = {
1186
 
            DA(pxaBoundingBox),
1187
 
            DUB(eInterior), DA(pxaClipRegion),
1188
 
            pxtSetClipRectangle
1189
 
        };
 
1184
        static const byte cr_[] = {
 
1185
            DA(pxaBoundingBox),
 
1186
            DUB(eInterior), DA(pxaClipRegion),
 
1187
            pxtSetClipRectangle
 
1188
        };
1190
1189
 
1191
 
        px_put_usq_fixed(s, x0, y0, x1, y1);
1192
 
        PX_PUT_LIT(s, cr_);
 
1190
        px_put_usq_fixed(s, x0, y0, x1, y1);
 
1191
        PX_PUT_LIT(s, cr_);
1193
1192
    }
1194
1193
    return 0;
1195
1194
}
1208
1207
 
1209
1208
static int
1210
1209
pclxl_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
1211
 
             gx_path_type_t type)
 
1210
             gx_path_type_t type)
1212
1211
{
1213
1212
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1214
1213
    int code = pclxl_flush_points(xdev);
1215
1214
 
1216
1215
    if (code < 0)
1217
 
        return code;
 
1216
        return code;
1218
1217
    return pclxl_set_cursor(xdev,
1219
 
                            xdev->points.current.x = (int)(x+0.5),
1220
 
                            xdev->points.current.y = (int)(y+0.5));
 
1218
                            xdev->points.current.x = (int)(x+0.5),
 
1219
                            xdev->points.current.y = (int)(y+0.5));
1221
1220
}
1222
1221
 
1223
1222
static int
1224
1223
pclxl_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
1225
 
             gx_path_type_t type)
 
1224
             gx_path_type_t type)
1226
1225
{
1227
1226
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1228
1227
 
1229
1228
    if (xdev->points.type != POINTS_LINES ||
1230
 
        xdev->points.count >= NUM_POINTS
1231
 
        ) {
1232
 
        if (xdev->points.type != POINTS_NONE) {
1233
 
            int code = pclxl_flush_points(xdev);
 
1229
        xdev->points.count >= NUM_POINTS
 
1230
        ) {
 
1231
        if (xdev->points.type != POINTS_NONE) {
 
1232
            int code = pclxl_flush_points(xdev);
1234
1233
 
1235
 
            if (code < 0)
1236
 
                return code;
1237
 
        }
1238
 
        xdev->points.current.x = (int)(x0+0.5);
1239
 
        xdev->points.current.y = (int)(y0+0.5);
1240
 
        xdev->points.type = POINTS_LINES;
 
1234
            if (code < 0)
 
1235
                return code;
 
1236
        }
 
1237
        xdev->points.current.x = (int)(x0+0.5);
 
1238
        xdev->points.current.y = (int)(y0+0.5);
 
1239
        xdev->points.type = POINTS_LINES;
1241
1240
    } {
1242
 
        gs_int_point *ppt = &xdev->points.data[xdev->points.count++];
 
1241
        gs_int_point *ppt = &xdev->points.data[xdev->points.count++];
1243
1242
 
1244
 
        ppt->x = (int)(x+0.5), ppt->y = (int)(y+0.5);
 
1243
        ppt->x = (int)(x+0.5), ppt->y = (int)(y+0.5);
1245
1244
    }
1246
1245
    return 0;
1247
1246
}
1248
1247
 
1249
1248
static int
1250
1249
pclxl_curveto(gx_device_vector * vdev, floatp x0, floatp y0,
1251
 
           floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3,
1252
 
              gx_path_type_t type)
 
1250
           floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3,
 
1251
              gx_path_type_t type)
1253
1252
{
1254
1253
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1255
1254
 
1256
1255
    if (xdev->points.type != POINTS_CURVES ||
1257
 
        xdev->points.count >= NUM_POINTS - 2
1258
 
        ) {
1259
 
        if (xdev->points.type != POINTS_NONE) {
1260
 
            int code = pclxl_flush_points(xdev);
 
1256
        xdev->points.count >= NUM_POINTS - 2
 
1257
        ) {
 
1258
        if (xdev->points.type != POINTS_NONE) {
 
1259
            int code = pclxl_flush_points(xdev);
1261
1260
 
1262
 
            if (code < 0)
1263
 
                return code;
1264
 
        }
1265
 
        xdev->points.current.x = (int)(x0+0.5);
1266
 
        xdev->points.current.y = (int)(y0+0.5);
1267
 
        xdev->points.type = POINTS_CURVES;
 
1261
            if (code < 0)
 
1262
                return code;
 
1263
        }
 
1264
        xdev->points.current.x = (int)(x0+0.5);
 
1265
        xdev->points.current.y = (int)(y0+0.5);
 
1266
        xdev->points.type = POINTS_CURVES;
1268
1267
    }
1269
1268
    {
1270
 
        gs_int_point *ppt = &xdev->points.data[xdev->points.count];
 
1269
        gs_int_point *ppt = &xdev->points.data[xdev->points.count];
1271
1270
 
1272
 
        ppt->x = (int)(x1+0.5), ppt->y = (int)(y1+0.5), ++ppt;
1273
 
        ppt->x = (int)(x2+0.5), ppt->y = (int)(y2+0.5), ++ppt;
1274
 
        ppt->x = (int)(x3+0.5), ppt->y = (int)(y3+0.5);
 
1271
        ppt->x = (int)(x1+0.5), ppt->y = (int)(y1+0.5), ++ppt;
 
1272
        ppt->x = (int)(x2+0.5), ppt->y = (int)(y2+0.5), ++ppt;
 
1273
        ppt->x = (int)(x3+0.5), ppt->y = (int)(y3+0.5);
1275
1274
    }
1276
1275
    xdev->points.count += 3;
1277
1276
    return 0;
1279
1278
 
1280
1279
static int
1281
1280
pclxl_closepath(gx_device_vector * vdev, floatp x, floatp y,
1282
 
                floatp x_start, floatp y_start, gx_path_type_t type)
 
1281
                floatp x_start, floatp y_start, gx_path_type_t type)
1283
1282
{
1284
1283
    gx_device_pclxl *const xdev = (gx_device_pclxl *)vdev;
1285
1284
    stream *s = gdev_vector_stream(vdev);
1286
1285
    int code = pclxl_flush_points(xdev);
1287
1286
 
1288
1287
    if (code < 0)
1289
 
        return code;
 
1288
        return code;
1290
1289
    spputc(s, pxtCloseSubPath);
1291
1290
    xdev->points.current.x = (int)(x_start+0.5);
1292
1291
    xdev->points.current.y = (int)(y_start+0.5);
1302
1301
    gx_path_type_t rule = type & gx_path_type_rule;
1303
1302
 
1304
1303
    if (code < 0)
1305
 
        return code;
 
1304
        return code;
1306
1305
    if (type & (gx_path_type_fill | gx_path_type_stroke)) {
1307
 
        if (rule != xdev->fill_rule) {
1308
 
            px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
1309
 
                       eNonZeroWinding));
1310
 
            px_put_ac(s, pxaFillMode, pxtSetFillMode);
1311
 
            xdev->fill_rule = rule;
1312
 
        }
1313
 
        pclxl_set_paints(xdev, type);
1314
 
        spputc(s, pxtPaintPath);
 
1306
        if (rule != xdev->fill_rule) {
 
1307
            px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
 
1308
                       eNonZeroWinding));
 
1309
            px_put_ac(s, pxaFillMode, pxtSetFillMode);
 
1310
            xdev->fill_rule = rule;
 
1311
        }
 
1312
        pclxl_set_paints(xdev, type);
 
1313
        spputc(s, pxtPaintPath);
1315
1314
    }
1316
1315
    if (type & gx_path_type_clip) {
1317
 
        static const byte scr_[] = {
1318
 
            DUB(eInterior), DA(pxaClipRegion), pxtSetClipReplace
1319
 
        };
 
1316
        static const byte scr_[] = {
 
1317
            DUB(eInterior), DA(pxaClipRegion), pxtSetClipReplace
 
1318
        };
1320
1319
 
1321
 
        if (rule != xdev->clip_rule) {
1322
 
            px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
1323
 
                       eNonZeroWinding));
1324
 
            px_put_ac(s, pxaClipMode, pxtSetClipMode);
1325
 
            xdev->clip_rule = rule;
1326
 
        }
1327
 
        PX_PUT_LIT(s, scr_);
 
1320
        if (rule != xdev->clip_rule) {
 
1321
            px_put_ub(s, (byte)(rule == gx_path_type_even_odd ? eEvenOdd :
 
1322
                       eNonZeroWinding));
 
1323
            px_put_ac(s, pxaClipMode, pxtSetClipMode);
 
1324
            xdev->clip_rule = rule;
 
1325
        }
 
1326
        PX_PUT_LIT(s, scr_);
1328
1327
    }
1329
1328
    return 0;
1330
1329
}
1332
1331
/* Vector implementation procedures */
1333
1332
 
1334
1333
static const gx_device_vector_procs pclxl_vector_procs = {
1335
 
        /* Page management */
 
1334
        /* Page management */
1336
1335
    pclxl_beginpage,
1337
 
        /* Imager state */
 
1336
        /* Imager state */
1338
1337
    pclxl_setlinewidth,
1339
1338
    pclxl_setlinecap,
1340
1339
    pclxl_setlinejoin,
1342
1341
    pclxl_setdash,
1343
1342
    gdev_vector_setflat,
1344
1343
    pclxl_setlogop,
1345
 
        /* Other state */
 
1344
        /* Other state */
1346
1345
    pclxl_can_handle_hl_color,
1347
1346
    pclxl_setfillcolor,
1348
1347
    pclxl_setstrokecolor,
1349
 
        /* Paths */
 
1348
        /* Paths */
1350
1349
    gdev_vector_dopath,
1351
1350
    pclxl_dorect,
1352
1351
    pclxl_beginpath,
1372
1371
    vdev->v_memory = dev->memory;       /****** WRONG ******/
1373
1372
    vdev->vec_procs = &pclxl_vector_procs;
1374
1373
    code = gdev_vector_open_file_options(vdev, 512,
1375
 
                                         VECTOR_OPEN_FILE_SEQUENTIAL);
 
1374
                                         VECTOR_OPEN_FILE_SEQUENTIAL);
1376
1375
    if (code < 0)
1377
 
        return code;
 
1376
        return code;
1378
1377
 
1379
1378
    pclxl_page_init(xdev);
1380
1379
    px_write_file_header(vdev->strm, dev);
1394
1393
 
1395
1394
    /* Note that unlike close_device, end_page must not omit blank pages. */
1396
1395
    if (!xdev->in_page)
1397
 
        pclxl_beginpage((gx_device_vector *)dev);
 
1396
        pclxl_beginpage((gx_device_vector *)dev);
1398
1397
    s = xdev->strm;
1399
1398
    px_put_usa(s, (uint)num_copies, pxaPageCopies);     /* num_copies */
1400
1399
    spputc(s, pxtEndPage);
1401
1400
    sflush(s);
1402
1401
    pclxl_page_init(xdev);
1403
1402
    if (ferror(xdev->file))
1404
 
        return_error(gs_error_ioerror);
 
1403
        return_error(gs_error_ioerror);
1405
1404
    return gx_finish_output_page(dev, num_copies, flush);
1406
1405
}
1407
1406
 
1415
1414
    FILE *file = xdev->file;
1416
1415
 
1417
1416
    if (xdev->strm != NULL)
1418
 
        sflush(xdev->strm);
 
1417
        sflush(xdev->strm);
1419
1418
    if (xdev->in_page)
1420
 
        fputc(pxtEndPage, file);
 
1419
        fputc(pxtEndPage, file);
1421
1420
    px_write_file_trailer(file);
1422
1421
    return gdev_vector_close_file((gx_device_vector *)dev);
1423
1422
}
1431
1430
/* Copy a monochrome bitmap. */
1432
1431
static int
1433
1432
pclxl_copy_mono(gx_device * dev, const byte * data, int data_x, int raster,
1434
 
                gx_bitmap_id id, int x, int y, int w, int h,
1435
 
                gx_color_index zero, gx_color_index one)
 
1433
                gx_bitmap_id id, int x, int y, int w, int h,
 
1434
                gx_color_index zero, gx_color_index one)
1436
1435
{
1437
1436
    gx_device_vector *const vdev = (gx_device_vector *)dev;
1438
1437
    gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1449
1448
    fit_copy(dev, data, data_x, raster, id, x, y, w, h);
1450
1449
    code = gdev_vector_update_clip_path(vdev, NULL);
1451
1450
    if (code < 0)
1452
 
        return code;
 
1451
        return code;
1453
1452
 
1454
1453
    /* write_image_data() needs byte-alignment,
1455
1454
     * and gx_default_copy_* is more efficient than pxlcl_*
1456
1455
     * for small rasters. See details in copy_color().
1457
1456
     */
1458
1457
    if ( ((data_x & 7) != 0) || (h == 1) || (w == 1) )
1459
 
        return gx_default_copy_mono(dev, data, data_x, raster, id, 
1460
 
                                    x, y, w, h, zero, one);
 
1458
        return gx_default_copy_mono(dev, data, data_x, raster, id,
 
1459
                                    x, y, w, h, zero, one);
1461
1460
 
1462
1461
    pclxl_set_cursor(xdev, x, y);
1463
1462
    if (id != gs_no_id && zero == gx_no_color_index &&
1464
 
        one != gx_no_color_index && data_x == 0
1465
 
        ) {
1466
 
        gx_drawing_color dcolor;
1467
 
 
1468
 
        code = gdev_vector_update_log_op(vdev, rop3_T|lop_T_transparent);
1469
 
        if (code < 0)
1470
 
            return 0;
1471
 
 
1472
 
        set_nonclient_dev_color(&dcolor, one);
1473
 
        pclxl_setfillcolor(vdev, NULL, &dcolor);
1474
 
        if (pclxl_copy_text_char(xdev, data, raster, id, w, h) >= 0)
1475
 
            return 0;
 
1463
        one != gx_no_color_index && data_x == 0
 
1464
        ) {
 
1465
        gx_drawing_color dcolor;
 
1466
 
 
1467
        code = gdev_vector_update_log_op(vdev, rop3_T|lop_T_transparent);
 
1468
        if (code < 0)
 
1469
            return 0;
 
1470
 
 
1471
        set_nonclient_dev_color(&dcolor, one);
 
1472
        pclxl_setfillcolor(vdev, NULL, &dcolor);
 
1473
        if (pclxl_copy_text_char(xdev, data, raster, id, w, h) >= 0)
 
1474
            return 0;
1476
1475
    }
1477
1476
    /*
1478
1477
     * The following doesn't work if we're writing white with a mask.
1494
1493
     *
1495
1494
     * There is a further refinement to this algorithm - it appears that
1496
1495
     * black+mask is treated specially by the vector driver core (rendered
1497
 
     * as transparent on white), and does not work as non-white + mask. 
 
1496
     * as transparent on white), and does not work as non-white + mask.
1498
1497
     * So Instead we set mask color to white and do (S & D) (i.e. draw
1499
1498
     * background on mask, instead of transparent on mask).
1500
1499
     *
1501
1500
     */
1502
1501
    if (zero == gx_no_color_index) {
1503
 
        if (one == gx_no_color_index)
1504
 
            return 0;
1505
 
        if (one != white) {
1506
 
            if (one == black) {
1507
 
                lop = (rop3_S & rop3_D);
1508
 
            } else {
1509
 
        lop = rop3_S | lop_S_transparent;
1510
 
            }
1511
 
            color0 = white;
1512
 
        } else {
1513
 
            lop = rop3_S | (rop3_D & rop3_not(rop3_S));
1514
 
            color0 = black;
1515
 
        }
 
1502
        if (one == gx_no_color_index)
 
1503
            return 0;
 
1504
        if (one != white) {
 
1505
            if (one == black) {
 
1506
                lop = (rop3_S & rop3_D);
 
1507
            } else {
 
1508
        lop = rop3_S | lop_S_transparent;
 
1509
            }
 
1510
            color0 = white;
 
1511
        } else {
 
1512
            lop = rop3_S | (rop3_D & rop3_not(rop3_S));
 
1513
            color0 = black;
 
1514
        }
1516
1515
    } else if (one == gx_no_color_index) {
1517
 
        if (zero != white) {
1518
 
            if (zero == black) {
1519
 
                lop = (rop3_S & rop3_D);
1520
 
            } else {
1521
 
        lop = rop3_S | lop_S_transparent;
1522
 
            }
1523
 
            color1 = white;
1524
 
        } else {
1525
 
            lop = rop3_S | (rop3_D & rop3_not(rop3_S));
1526
 
            color1 = black;
1527
 
        }
 
1516
        if (zero != white) {
 
1517
            if (zero == black) {
 
1518
                lop = (rop3_S & rop3_D);
 
1519
            } else {
 
1520
        lop = rop3_S | lop_S_transparent;
 
1521
            }
 
1522
            color1 = white;
 
1523
        } else {
 
1524
            lop = rop3_S | (rop3_D & rop3_not(rop3_S));
 
1525
            color1 = black;
 
1526
        }
1528
1527
    } else {
1529
 
        lop = rop3_S;
 
1528
        lop = rop3_S;
1530
1529
    }
1531
1530
 
1532
1531
    if (dev->color_info.num_components == 1 ||
1533
 
        (RGB_IS_GRAY(color0) && RGB_IS_GRAY(color1))
1534
 
        ) {
1535
 
        palette[0] = (byte) color0;
1536
 
        palette[1] = (byte) color1;
1537
 
        palette_size = 2;
1538
 
        color_space = eGray;
1539
 
        if_debug2('b', "color palette %02X %02X\n", palette[0], palette[1]);
 
1532
        (RGB_IS_GRAY(color0) && RGB_IS_GRAY(color1))
 
1533
        ) {
 
1534
        palette[0] = (byte) color0;
 
1535
        palette[1] = (byte) color1;
 
1536
        palette_size = 2;
 
1537
        color_space = eGray;
 
1538
        if_debug2('b', "color palette %02X %02X\n", palette[0], palette[1]);
1540
1539
    } else {
1541
 
        palette[0] = (byte) (color0 >> 16);
1542
 
        palette[1] = (byte) (color0 >> 8);
1543
 
        palette[2] = (byte) color0;
1544
 
        palette[3] = (byte) (color1 >> 16);
1545
 
        palette[4] = (byte) (color1 >> 8);
1546
 
        palette[5] = (byte) color1;
1547
 
        palette_size = 6;
1548
 
        color_space = eRGB;
 
1540
        palette[0] = (byte) (color0 >> 16);
 
1541
        palette[1] = (byte) (color0 >> 8);
 
1542
        palette[2] = (byte) color0;
 
1543
        palette[3] = (byte) (color1 >> 16);
 
1544
        palette[4] = (byte) (color1 >> 8);
 
1545
        palette[5] = (byte) color1;
 
1546
        palette_size = 6;
 
1547
        color_space = eRGB;
1549
1548
    }
1550
1549
    code = gdev_vector_update_log_op(vdev, lop);
1551
1550
    if (code < 0)
1552
 
        return 0;
 
1551
        return 0;
1553
1552
    pclxl_set_color_palette(xdev, color_space, palette, palette_size);
1554
1553
    s = pclxl_stream(xdev);
1555
1554
    {
1556
 
        static const byte mi_[] = {
1557
 
            DUB(e1Bit), DA(pxaColorDepth),
1558
 
            DUB(eIndexedPixel), DA(pxaColorMapping)
1559
 
        };
 
1555
        static const byte mi_[] = {
 
1556
            DUB(e1Bit), DA(pxaColorDepth),
 
1557
            DUB(eIndexedPixel), DA(pxaColorMapping)
 
1558
        };
1560
1559
 
1561
 
        PX_PUT_LIT(s, mi_);
 
1560
        PX_PUT_LIT(s, mi_);
1562
1561
    }
1563
1562
    pclxl_write_begin_image(xdev, w, h, w, h);
1564
1563
    pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h);
1569
1568
/* Copy a color bitmap. */
1570
1569
static int
1571
1570
pclxl_copy_color(gx_device * dev,
1572
 
                 const byte * base, int sourcex, int raster, gx_bitmap_id id,
1573
 
                 int x, int y, int w, int h)
 
1571
                 const byte * base, int sourcex, int raster, gx_bitmap_id id,
 
1572
                 int x, int y, int w, int h)
1574
1573
{
1575
1574
    gx_device_vector *const vdev = (gx_device_vector *)dev;
1576
1575
    gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1581
1580
    fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
1582
1581
    code = gdev_vector_update_clip_path(vdev, NULL);
1583
1582
    if (code < 0)
1584
 
        return code;
1585
 
 
 
1583
        return code;
1586
1584
 
1587
1585
    source_bit = sourcex * dev->color_info.depth;
1588
1586
 
1603
1601
     * than images.
1604
1602
     */
1605
1603
    if ( ((source_bit & 7) != 0) || (w == 1) || (h == 1) )
1606
 
        return gx_default_copy_color(dev, base, sourcex, raster, id,
1607
 
                                     x, y, w, h);
 
1604
        return gx_default_copy_color(dev, base, sourcex, raster, id,
 
1605
                                     x, y, w, h);
1608
1606
    code = gdev_vector_update_log_op(vdev, rop3_S);
1609
1607
    if(code < 0)
1610
1608
        return 0;
1611
1609
    pclxl_set_cursor(xdev, x, y);
1612
1610
    s = pclxl_stream(xdev);
1613
1611
    {
1614
 
        static const byte ci_[] = {
1615
 
            DA(pxaColorDepth),
1616
 
            DUB(eDirectPixel), DA(pxaColorMapping)
1617
 
        };
 
1612
        static const byte ci_[] = {
 
1613
            DA(pxaColorDepth),
 
1614
            DUB(eDirectPixel), DA(pxaColorMapping)
 
1615
        };
1618
1616
 
1619
 
        px_put_ub(s, eBit_values[dev->color_info.depth /
1620
 
                                 dev->color_info.num_components]);
1621
 
        PX_PUT_LIT(s, ci_);
 
1617
        px_put_ub(s, eBit_values[dev->color_info.depth /
 
1618
                                 dev->color_info.num_components]);
 
1619
        PX_PUT_LIT(s, ci_);
1622
1620
    }
1623
1621
    pclxl_write_begin_image(xdev, w, h, w, h);
1624
1622
    pclxl_write_image_data(xdev, base, source_bit, raster,
1625
 
                           w * dev->color_info.depth, 0, h);
 
1623
                           w * dev->color_info.depth, 0, h);
1626
1624
    pclxl_write_end_image(xdev);
1627
1625
    return 0;
1628
1626
}
1630
1628
/* Fill a mask. */
1631
1629
static int
1632
1630
pclxl_fill_mask(gx_device * dev,
1633
 
                const byte * data, int data_x, int raster, gx_bitmap_id id,
1634
 
                int x, int y, int w, int h,
1635
 
                const gx_drawing_color * pdcolor, int depth,
1636
 
                gs_logical_operation_t lop, const gx_clip_path * pcpath)
 
1631
                const byte * data, int data_x, int raster, gx_bitmap_id id,
 
1632
                int x, int y, int w, int h,
 
1633
                const gx_drawing_color * pdcolor, int depth,
 
1634
                gs_logical_operation_t lop, const gx_clip_path * pcpath)
1637
1635
{
1638
1636
    gx_device_vector *const vdev = (gx_device_vector *)dev;
1639
1637
    gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1647
1645
     * for small rasters. See details in copy_color().
1648
1646
     */
1649
1647
    if ((data_x & 7) != 0 || !gx_dc_is_pure(pdcolor) || depth > 1 || (w == 1) || (h == 1) )
1650
 
        return gx_default_fill_mask(dev, data, data_x, raster, id,
1651
 
                                    x, y, w, h, pdcolor, depth,
1652
 
                                    lop, pcpath);
 
1648
        return gx_default_fill_mask(dev, data, data_x, raster, id,
 
1649
                                    x, y, w, h, pdcolor, depth,
 
1650
                                    lop, pcpath);
1653
1651
    code = gdev_vector_update_clip_path(vdev, pcpath);
1654
1652
    foreground = gx_dc_pure_color(pdcolor);
1655
1653
    if (code < 0)
1656
 
        return code;
 
1654
        return code;
1657
1655
    code = gdev_vector_update_fill_color(vdev, NULL, pdcolor);
1658
1656
    if (code < 0)
1659
 
        return 0;
 
1657
        return 0;
1660
1658
    pclxl_set_cursor(xdev, x, y);
1661
1659
    if (id != gs_no_id && data_x == 0) {
1662
 
        code = gdev_vector_update_log_op(vdev, lop);
1663
 
        if (code < 0)
1664
 
            return 0;
1665
 
        if (pclxl_copy_text_char(xdev, data, raster, id, w, h) >= 0)
1666
 
            return 0;
 
1660
        code = gdev_vector_update_log_op(vdev, lop);
 
1661
        if (code < 0)
 
1662
            return 0;
 
1663
        if (pclxl_copy_text_char(xdev, data, raster, id, w, h) >= 0)
 
1664
            return 0;
1667
1665
    }
1668
1666
    /* This is similiar to the copy_mono white-on-mask,
1669
1667
     * except we are drawing white on the black of a black/white mask,
1675
1673
    }else lop |= rop3_S | lop_S_transparent;
1676
1674
 
1677
1675
    code = gdev_vector_update_log_op(vdev,
1678
 
                                     lop);
 
1676
                                     lop);
1679
1677
    if (code < 0)
1680
 
        return 0;
 
1678
        return 0;
1681
1679
    pclxl_set_color_palette(xdev, eGray, (const byte *)"\377\000", 2);
1682
1680
    s = pclxl_stream(xdev);
1683
1681
    {
1684
 
        static const byte mi_[] = {
1685
 
            DUB(e1Bit), DA(pxaColorDepth),
1686
 
            DUB(eIndexedPixel), DA(pxaColorMapping)
1687
 
        };
 
1682
        static const byte mi_[] = {
 
1683
            DUB(e1Bit), DA(pxaColorDepth),
 
1684
            DUB(eIndexedPixel), DA(pxaColorMapping)
 
1685
        };
1688
1686
 
1689
 
        PX_PUT_LIT(s, mi_);
 
1687
        PX_PUT_LIT(s, mi_);
1690
1688
    }
1691
1689
    pclxl_write_begin_image(xdev, w, h, w, h);
1692
1690
    pclxl_write_image_data(xdev, data, data_x, raster, w, 0, h);
1697
1695
/* Do a RasterOp. */
1698
1696
static int
1699
1697
pclxl_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
1700
 
                     uint sraster, gx_bitmap_id id,
1701
 
                     const gx_color_index * scolors,
1702
 
                     const gx_strip_bitmap * textures,
1703
 
                     const gx_color_index * tcolors,
1704
 
                     int x, int y, int width, int height,
1705
 
                     int phase_x, int phase_y, gs_logical_operation_t lop)
 
1698
                     uint sraster, gx_bitmap_id id,
 
1699
                     const gx_color_index * scolors,
 
1700
                     const gx_strip_bitmap * textures,
 
1701
                     const gx_color_index * tcolors,
 
1702
                     int x, int y, int width, int height,
 
1703
                     int phase_x, int phase_y, gs_logical_operation_t lop)
1706
1704
{                               /* We can't do general RasterOps yet. */
1707
1705
/****** WORK IN PROGRESS ******/
1708
1706
    return 0;
1715
1713
    gdev_vector_image_enum_common;
1716
1714
    gs_matrix mat;
1717
1715
    struct ir_ {
1718
 
        byte *data;
1719
 
        int num_rows;           /* # of allocated rows */
1720
 
        int first_y;
1721
 
        uint raster;
 
1716
        byte *data;
 
1717
        int num_rows;           /* # of allocated rows */
 
1718
        int first_y;
 
1719
        uint raster;
1722
1720
    } rows;
1723
1721
} pclxl_image_enum_t;
1724
1722
gs_private_st_suffix_add1(st_pclxl_image_enum, pclxl_image_enum_t,
1725
 
                          "pclxl_image_enum_t", pclxl_image_enum_enum_ptrs,
1726
 
                          pclxl_image_enum_reloc_ptrs, st_vector_image_enum,
1727
 
                          rows.data);
 
1723
                          "pclxl_image_enum_t", pclxl_image_enum_enum_ptrs,
 
1724
                          pclxl_image_enum_reloc_ptrs, st_vector_image_enum,
 
1725
                          rows.data);
1728
1726
 
1729
1727
/* Start processing an image. */
1730
1728
static int
1731
1729
pclxl_begin_image(gx_device * dev,
1732
 
                  const gs_imager_state * pis, const gs_image_t * pim,
1733
 
                  gs_image_format_t format, const gs_int_rect * prect,
1734
 
                  const gx_drawing_color * pdcolor,
1735
 
                  const gx_clip_path * pcpath, gs_memory_t * mem,
1736
 
                  gx_image_enum_common_t ** pinfo)
 
1730
                  const gs_imager_state * pis, const gs_image_t * pim,
 
1731
                  gs_image_format_t format, const gs_int_rect * prect,
 
1732
                  const gx_drawing_color * pdcolor,
 
1733
                  const gx_clip_path * pcpath, gs_memory_t * mem,
 
1734
                  gx_image_enum_common_t ** pinfo)
1737
1735
{
1738
1736
    gx_device_vector *const vdev = (gx_device_vector *)dev;
1739
1737
    gx_device_pclxl *const xdev = (gx_device_pclxl *)dev;
1747
1745
     * images, i.e., num_planes = 1.
1748
1746
     */
1749
1747
    int bits_per_pixel =
1750
 
        (pim->ImageMask ? 1 :
1751
 
         pim->BitsPerComponent * gs_color_space_num_components(pcs));
 
1748
        (pim->ImageMask ? 1 :
 
1749
         pim->BitsPerComponent * gs_color_space_num_components(pcs));
1752
1750
    gs_matrix mat;
1753
1751
    int code;
1754
1752
 
1766
1764
     */
1767
1765
    if ((!((mat.xx * mat.yy > 0) && (mat.xy == 0) && (mat.yx == 0)) &&
1768
1766
         !((mat.xx == 0) && (mat.yy == 0) && (mat.xy * mat.yx < 0))) ||
1769
 
        (pim->ImageMask ?
1770
 
         (!gx_dc_is_pure(pdcolor) || pim->CombineWithColor) :
1771
 
         (!pclxl_can_handle_color_space(pim->ColorSpace) ||
1772
 
          (bits_per_pixel != 1 && bits_per_pixel != 4 &&
1773
 
           bits_per_pixel != 8 && bits_per_pixel !=24))) ||
1774
 
        format != gs_image_format_chunky || pim->Interpolate ||
1775
 
        prect
1776
 
        )
1777
 
        goto use_default;
 
1767
        (pim->ImageMask ?
 
1768
         (!gx_dc_is_pure(pdcolor) || pim->CombineWithColor) :
 
1769
         (!pclxl_can_handle_color_space(pim->ColorSpace) ||
 
1770
          (bits_per_pixel != 1 && bits_per_pixel != 4 &&
 
1771
           bits_per_pixel != 8 && bits_per_pixel !=24))) ||
 
1772
        format != gs_image_format_chunky || pim->Interpolate ||
 
1773
        prect
 
1774
        )
 
1775
        goto use_default;
1778
1776
    row_raster = (bits_per_pixel * pim->Width + 7) >> 3;
1779
1777
    num_rows = MAX_ROW_DATA / row_raster;
1780
1778
    if (num_rows > pim->Height)
1781
 
        num_rows = pim->Height;
 
1779
        num_rows = pim->Height;
1782
1780
    if (num_rows <= 0)
1783
 
        num_rows = 1;
 
1781
        num_rows = 1;
1784
1782
    pie = gs_alloc_struct(mem, pclxl_image_enum_t, &st_pclxl_image_enum,
1785
 
                          "pclxl_begin_image");
 
1783
                          "pclxl_begin_image");
1786
1784
    row_data = gs_alloc_bytes(mem, num_rows * row_raster,
1787
 
                              "pclxl_begin_image(rows)");
 
1785
                              "pclxl_begin_image(rows)");
1788
1786
    if (pie == 0 || row_data == 0) {
1789
 
        code = gs_note_error(gs_error_VMerror);
1790
 
        goto fail;
 
1787
        code = gs_note_error(gs_error_VMerror);
 
1788
        goto fail;
1791
1789
    }
1792
1790
    code = gdev_vector_begin_image(vdev, pis, pim, format, prect,
1793
 
                                   pdcolor, pcpath, mem,
1794
 
                                   &pclxl_image_enum_procs,
1795
 
                                   (gdev_vector_image_enum_t *)pie);
 
1791
                                   pdcolor, pcpath, mem,
 
1792
                                   &pclxl_image_enum_procs,
 
1793
                                   (gdev_vector_image_enum_t *)pie);
1796
1794
    if (code < 0)
1797
 
        return code;
 
1795
        return code;
1798
1796
 
1799
1797
    /* emit a PXL XL rotation and adjust mat correspondingly */
1800
1798
    if (mat.xx * mat.yy >  0) {
1841
1839
    pie->rows.raster = row_raster;
1842
1840
    *pinfo = (gx_image_enum_common_t *) pie;
1843
1841
    {
1844
 
        gs_logical_operation_t lop = pis->log_op;
1845
 
 
1846
 
        if (pim->ImageMask) {
1847
 
            const byte *palette = (const byte *)
1848
 
                (pim->Decode[0] ? "\377\000" : "\000\377");
1849
 
            gx_color_index foreground = gx_dc_pure_color(pdcolor);
1850
 
 
1851
 
            code = gdev_vector_update_fill_color(vdev, 
1852
 
                                     NULL, /* use process color */
1853
 
                                     pdcolor);
1854
 
            if (code < 0)
1855
 
                goto fail;
1856
 
            /* This is similiar to the copy_mono white-on-mask,
1857
 
             * except we are drawing white on the black of a black/white mask,
1858
 
             * so we invert source, compared to copy_mono */
1859
 
            if (foreground == (1 << dev->color_info.depth) - 1) { /* white */
1860
 
                lop = rop3_not(rop3_S) | (rop3_D & rop3_S);
1861
 
            }else if (foreground == 0) { /* black */
1862
 
                lop = (rop3_S & rop3_D);
1863
 
            }else lop |= rop3_S | lop_S_transparent;
1864
 
 
1865
 
            code = gdev_vector_update_log_op
1866
 
                (vdev, lop);
1867
 
            if (code < 0)
1868
 
                goto fail;
1869
 
            pclxl_set_color_palette(xdev, eGray, palette, 2);
1870
 
        } else {
 
1842
        gs_logical_operation_t lop = pis->log_op;
 
1843
 
 
1844
        if (pim->ImageMask) {
 
1845
            const byte *palette = (const byte *)
 
1846
                (pim->Decode[0] ? "\377\000" : "\000\377");
 
1847
            gx_color_index foreground = gx_dc_pure_color(pdcolor);
 
1848
 
 
1849
            code = gdev_vector_update_fill_color(vdev,
 
1850
                                     NULL, /* use process color */
 
1851
                                     pdcolor);
 
1852
            if (code < 0)
 
1853
                goto fail;
 
1854
            /* This is similiar to the copy_mono white-on-mask,
 
1855
             * except we are drawing white on the black of a black/white mask,
 
1856
             * so we invert source, compared to copy_mono */
 
1857
            if (foreground == (1 << dev->color_info.depth) - 1) { /* white */
 
1858
                lop = rop3_not(rop3_S) | (rop3_D & rop3_S);
 
1859
            }else if (foreground == 0) { /* black */
 
1860
                lop = (rop3_S & rop3_D);
 
1861
            }else lop |= rop3_S | lop_S_transparent;
 
1862
 
 
1863
            code = gdev_vector_update_log_op
 
1864
                (vdev, lop);
 
1865
            if (code < 0)
 
1866
                goto fail;
 
1867
            pclxl_set_color_palette(xdev, eGray, palette, 2);
 
1868
        } else {
1871
1869
            if (bits_per_pixel == 24 ) {
1872
1870
                code = gdev_vector_update_log_op
1873
1871
                    (vdev, (pim->CombineWithColor ? lop : rop3_know_T_0(lop)));
1879
1877
                    pclxl_set_color_space(xdev, eRGB);
1880
1878
                }
1881
1879
            } else {
1882
 
            int bpc = pim->BitsPerComponent;
1883
 
            int num_components = pie->plane_depths[0] * pie->num_planes / bpc;
1884
 
            int sample_max = (1 << bpc) - 1;
1885
 
            byte palette[256 * 3];
1886
 
            int i;
1887
 
 
1888
 
            code = gdev_vector_update_log_op
1889
 
                (vdev, (pim->CombineWithColor ? lop : rop3_know_T_0(lop)));
1890
 
            if (code < 0)
1891
 
                goto fail;
1892
 
            for (i = 0; i < 1 << bits_per_pixel; ++i) {
1893
 
                gs_client_color cc;
1894
 
                gx_device_color devc;
1895
 
                int cv = i, j;
1896
 
                gx_color_index ci;
1897
 
 
1898
 
                for (j = num_components - 1; j >= 0; cv >>= bpc, --j)
1899
 
                    cc.paint.values[j] = pim->Decode[j * 2] +
1900
 
                        (cv & sample_max) *
1901
 
                        (pim->Decode[j * 2 + 1] - pim->Decode[j * 2]) /
1902
 
                        sample_max;
1903
 
                (*pcs->type->remap_color)
1904
 
                    (&cc, pcs, &devc, pis, dev, gs_color_select_source);
1905
 
                if (!gx_dc_is_pure(&devc))
1906
 
                    return_error(gs_error_Fatal);
1907
 
                ci = gx_dc_pure_color(&devc);
1908
 
                if (dev->color_info.num_components == 1) {
1909
 
                    palette[i] = (byte)ci;
1910
 
                } else {
1911
 
                    byte *ppal = &palette[i * 3];
1912
 
 
1913
 
                    ppal[0] = (byte) (ci >> 16);
1914
 
                    ppal[1] = (byte) (ci >> 8);
1915
 
                    ppal[2] = (byte) ci;
1916
 
                }
1917
 
            }
1918
 
            if (dev->color_info.num_components == 1)
1919
 
                pclxl_set_color_palette(xdev, eGray, palette,
1920
 
                                        1 << bits_per_pixel);
1921
 
            else
1922
 
                pclxl_set_color_palette(xdev, eRGB, palette,
1923
 
                                        3 << bits_per_pixel);
1924
 
            }
1925
 
        }
 
1880
            int bpc = pim->BitsPerComponent;
 
1881
            int num_components = pie->plane_depths[0] * pie->num_planes / bpc;
 
1882
            int sample_max = (1 << bpc) - 1;
 
1883
            byte palette[256 * 3];
 
1884
            int i;
 
1885
 
 
1886
            code = gdev_vector_update_log_op
 
1887
                (vdev, (pim->CombineWithColor ? lop : rop3_know_T_0(lop)));
 
1888
            if (code < 0)
 
1889
                goto fail;
 
1890
            for (i = 0; i < 1 << bits_per_pixel; ++i) {
 
1891
                gs_client_color cc;
 
1892
                gx_device_color devc;
 
1893
                int cv = i, j;
 
1894
                gx_color_index ci;
 
1895
 
 
1896
                for (j = num_components - 1; j >= 0; cv >>= bpc, --j)
 
1897
                    cc.paint.values[j] = pim->Decode[j * 2] +
 
1898
                        (cv & sample_max) *
 
1899
                        (pim->Decode[j * 2 + 1] - pim->Decode[j * 2]) /
 
1900
                        sample_max;
 
1901
                (*pcs->type->remap_color)
 
1902
                    (&cc, pcs, &devc, pis, dev, gs_color_select_source);
 
1903
                if (!gx_dc_is_pure(&devc))
 
1904
                    return_error(gs_error_Fatal);
 
1905
                ci = gx_dc_pure_color(&devc);
 
1906
                if (dev->color_info.num_components == 1) {
 
1907
                    palette[i] = (byte)ci;
 
1908
                } else {
 
1909
                    byte *ppal = &palette[i * 3];
 
1910
 
 
1911
                    ppal[0] = (byte) (ci >> 16);
 
1912
                    ppal[1] = (byte) (ci >> 8);
 
1913
                    ppal[2] = (byte) ci;
 
1914
                }
 
1915
            }
 
1916
            if (dev->color_info.num_components == 1)
 
1917
                pclxl_set_color_palette(xdev, eGray, palette,
 
1918
                                        1 << bits_per_pixel);
 
1919
            else
 
1920
                pclxl_set_color_palette(xdev, eRGB, palette,
 
1921
                                        3 << bits_per_pixel);
 
1922
            }
 
1923
        }
1926
1924
    }
1927
1925
    return 0;
1928
1926
 fail:
1934
1932
    else
1935
1933
        pclxl_set_color_space(xdev, eRGB);
1936
1934
    return gx_default_begin_image(dev, pis, pim, format, prect,
1937
 
                                  pdcolor, pcpath, mem, pinfo);
 
1935
                                  pdcolor, pcpath, mem, pinfo);
1938
1936
}
1939
1937
 
1940
1938
/* Write one strip of an image, from pie->rows.first_y to pie->y. */
1942
1940
image_transform_x(const pclxl_image_enum_t *pie, int sx)
1943
1941
{
1944
1942
    return (int)((pie->mat.tx + sx * pie->mat.xx + 0.5) /
1945
 
                 ((const gx_device_pclxl *)pie->dev)->scale.x);
 
1943
                 ((const gx_device_pclxl *)pie->dev)->scale.x);
1946
1944
}
1947
1945
static int
1948
1946
image_transform_y(const pclxl_image_enum_t *pie, int sy)
1949
1947
{
1950
1948
    return (int)((pie->mat.ty + sy * pie->mat.yy + 0.5) /
1951
 
                 ((const gx_device_pclxl *)pie->dev)->scale.y);
 
1949
                 ((const gx_device_pclxl *)pie->dev)->scale.y);
1952
1950
}
1953
1951
 
1954
1952
static int
1965
1963
    int rows_raster=pie->rows.raster;
1966
1964
 
1967
1965
    if (dw <= 0 || dh <= 0)
1968
 
        return 0;
 
1966
        return 0;
1969
1967
    pclxl_set_cursor(xdev, xo, yo);
1970
1968
    if (pie->bits_per_pixel==24) {
1971
 
        static const byte ci_[] = {
1972
 
            DA(pxaColorDepth),
1973
 
            DUB(eDirectPixel), DA(pxaColorMapping)
1974
 
        };
 
1969
        static const byte ci_[] = {
 
1970
            DA(pxaColorDepth),
 
1971
            DUB(eDirectPixel), DA(pxaColorMapping)
 
1972
        };
1975
1973
 
1976
 
        px_put_ub(s, eBit_values[8]);
1977
 
        PX_PUT_LIT(s, ci_);
 
1974
        px_put_ub(s, eBit_values[8]);
 
1975
        PX_PUT_LIT(s, ci_);
1978
1976
        if (xdev->color_info.depth==8) {
1979
1977
          byte *in=pie->rows.data;
1980
1978
          byte *out=pie->rows.data;
1983
1981
          rows_raster/=3;
1984
1982
          for (j=0;  j<h;  j++) {
1985
1983
            for (i=0;  i<rows_raster;  i++) {
1986
 
              *out = (byte)( ((*(in+0) * (ulong) lum_red_weight) + 
1987
 
                              (*(in+1) * (ulong) lum_green_weight) + 
1988
 
                              (*(in+2) * (ulong) lum_blue_weight) + 
 
1984
              *out = (byte)( ((*(in+0) * (ulong) lum_red_weight) +
 
1985
                              (*(in+1) * (ulong) lum_green_weight) +
 
1986
                              (*(in+2) * (ulong) lum_blue_weight) +
1989
1987
                              (lum_all_weights / 2)) / lum_all_weights);
1990
1988
              in+=3;
1991
1989
              out++;
1994
1992
        }
1995
1993
    } else {
1996
1994
        static const byte ii_[] = {
1997
 
            DA(pxaColorDepth),
1998
 
            DUB(eIndexedPixel), DA(pxaColorMapping)
 
1995
            DA(pxaColorDepth),
 
1996
            DUB(eIndexedPixel), DA(pxaColorMapping)
1999
1997
        };
2000
1998
        px_put_ub(s, eBit_values[pie->bits_per_pixel]);
2001
1999
        PX_PUT_LIT(s, ii_);
2002
2000
    }
2003
2001
    pclxl_write_begin_image(xdev, pie->width, h, dw, dh);
2004
2002
    pclxl_write_image_data(xdev, pie->rows.data, 0, rows_raster,
2005
 
                           rows_raster << 3, 0, h);
 
2003
                           rows_raster << 3, 0, h);
2006
2004
    pclxl_write_end_image(xdev);
2007
2005
    return 0;
2008
2006
}
2010
2008
/* Process the next piece of an image. */
2011
2009
static int
2012
2010
pclxl_image_plane_data(gx_image_enum_common_t * info,
2013
 
                       const gx_image_plane_t * planes, int height,
2014
 
                       int *rows_used)
 
2011
                       const gx_image_plane_t * planes, int height,
 
2012
                       int *rows_used)
2015
2013
{
2016
2014
    pclxl_image_enum_t *pie = (pclxl_image_enum_t *) info;
2017
2015
    int data_bit = planes[0].data_x * info->plane_depths[0];
2020
2018
 
2021
2019
    /****** SHOULD HANDLE NON-BYTE-ALIGNED DATA ******/
2022
2020
    if (width_bits != pie->bits_per_row || (data_bit & 7) != 0)
2023
 
        return_error(gs_error_rangecheck);
 
2021
        return_error(gs_error_rangecheck);
2024
2022
    if (height > pie->height - pie->y)
2025
 
        height = pie->height - pie->y;
 
2023
        height = pie->height - pie->y;
2026
2024
    for (i = 0; i < height; pie->y++, ++i) {
2027
 
        if (pie->y - pie->rows.first_y == pie->rows.num_rows) {
2028
 
            int code = pclxl_image_write_rows(pie);
 
2025
        if (pie->y - pie->rows.first_y == pie->rows.num_rows) {
 
2026
            int code = pclxl_image_write_rows(pie);
2029
2027
 
2030
 
            if (code < 0)
2031
 
                return code;
2032
 
            pie->rows.first_y = pie->y;
2033
 
        }
2034
 
        memcpy(pie->rows.data +
2035
 
                 pie->rows.raster * (pie->y - pie->rows.first_y),
2036
 
               planes[0].data + planes[0].raster * i + (data_bit >> 3),
2037
 
               pie->rows.raster);
 
2028
            if (code < 0)
 
2029
                return code;
 
2030
            pie->rows.first_y = pie->y;
 
2031
        }
 
2032
        memcpy(pie->rows.data +
 
2033
                 pie->rows.raster * (pie->y - pie->rows.first_y),
 
2034
               planes[0].data + planes[0].raster * i + (data_bit >> 3),
 
2035
               pie->rows.raster);
2038
2036
    }
2039
2037
    *rows_used = height;
2040
2038
    return pie->y >= pie->height;
2049
2047
 
2050
2048
    /* Write the final strip, if any. */
2051
2049
    if (pie->y > pie->rows.first_y && draw_last)
2052
 
        code = pclxl_image_write_rows(pie);
 
2050
        code = pclxl_image_write_rows(pie);
2053
2051
    if (draw_last) {
2054
2052
        gx_device_pclxl *xdev = (gx_device_pclxl *)info->dev;
2055
2053
        stream *s = pclxl_stream(xdev);
2091
2089
  gx_device_pclxl       *xdev;          /* PCL XL device */
2092
2090
  int                   code;           /* Return code */
2093
2091
 
2094
 
 
2095
2092
 /*
2096
2093
  * First process the "standard" page device parameters...
2097
2094
  */
2122
2119
  return (0);
2123
2120
}
2124
2121
 
2125
 
 
2126
2122
/*
2127
2123
 * 'pclxl_put_params()' - Set pagedevice parameters.
2128
2124
 */
2136
2132
  int                   intval;         /* Integer value */
2137
2133
  bool                  boolval;        /* Boolean value */
2138
2134
 
2139
 
 
2140
2135
 /*
2141
2136
  * Process PCL-XL driver parameters...
2142
2137
  */