Coverage Report

Created: 2026-07-24 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/cups/gdevcups.c
Line
Count
Source
1
/*
2
 *
3
 *   GNU Ghostscript raster output driver for the Common UNIX Printing
4
 *   System (CUPS).
5
 *
6
 *   Copyright 1993-2006 by Easy Software Products.
7
 *
8
 *   These coded instructions, statements, and computer programs are the
9
 *   property of Easy Software Products and are protected by Federal
10
 *   copyright law.  Distribution and use rights are outlined in the file
11
 *   "LICENSE.txt" which should have been included with this file.  If this
12
 *   file is missing or damaged please contact Easy Software Products
13
 *   at:
14
 *
15
 *       Attn: CUPS Licensing Information
16
 *       Easy Software Products
17
 *       44141 Airport View Drive, Suite 204
18
 *       Hollywood, Maryland 20636 USA
19
 *
20
 *       Voice: (301) 373-9600
21
 *       EMail: cups-info@cups.org
22
 *         WWW: http://www.cups.org/
23
 *
24
 *   This code and any derivative of it may be used and distributed
25
 *   freely under the terms of the GNU General Public License when
26
 *   used with GNU Ghostscript or its derivatives.  Use of the code
27
 *   (or any derivative of it) with software other than GNU
28
 *   GhostScript (or its derivatives) is governed by the CUPS license
29
 *   agreement.
30
 *
31
 * Contents:
32
 *
33
 *   cups_close()            - Close the output file.
34
 *   cups_decode_color()     - Decode a color value.
35
 *   cups_encode_color()     - Encode a color value.
36
 *   cups_get_color_comp_index()
37
 *                           - Color component to index
38
 *   cups_get_color_mapping_procs()
39
 *                           - Get the list of color mapping procedures.
40
 *   cups_get_matrix()       - Generate the default page matrix.
41
 *   cups_get_params()       - Get pagedevice parameters.
42
 *   cups_get_space_params() - Get space parameters from the RIP_CACHE env var.
43
 *   cups_map_cielab()       - Map CIE Lab transformation...
44
 *   cups_map_cmyk()         - Map a CMYK color value to device colors.
45
 *   cups_map_gray()         - Map a grayscale value to device colors.
46
 *   cups_map_rgb()          - Map a RGB color value to device colors.
47
 *   cups_map_cmyk_color()   - Map a CMYK color to a color index.
48
 *   cups_map_color_rgb()    - Map a color index to an RGB color.
49
 *   cups_map_rgb_color()    - Map an RGB color to a color index.  We map the
50
 *                             RGB color to the output colorspace & bits (we
51
 *                             figure out the format when we output a page).
52
 *   cups_open()             - Open the output file and initialize things.
53
 *   cups_print_pages()      - Send one or more pages to the output file.
54
 *   cups_put_params()       - Set pagedevice parameters.
55
 *   cups_set_color_info()   - Set the color information structure based on
56
 *                             the required output.
57
 *   cups_sync_output()      - Keep the user informed of our status...
58
 *   cups_print_chunked()    - Print a page of chunked pixels.
59
 *   cups_print_banded()     - Print a page of banded pixels.
60
 *   cups_print_planar()     - Print a page of planar pixels.
61
 */
62
63
/* prevent gp.h redefining fopen */
64
0
#define sprintf sprintf
65
66
/*
67
 * Include necessary headers...
68
 */
69
70
#include "std.h"                /* to stop stdlib.h redefining types */
71
#include "gdevprn.h"
72
#include "gsparam.h"
73
#include "gxdevsop.h"
74
#include "arch.h"
75
#include "gsicc_manage.h"
76
77
#include <stdlib.h>
78
#include <ctype.h>
79
80
#ifdef __GNUC__
81
#pragma GCC diagnostic push
82
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
83
#endif
84
85
/* Recent cups releases on OSX pull in printf in a header file
86
   so we need to allow it. This may well end up being required
87
   on other platforms, too.
88
 */
89
#ifdef __APPLE__
90
#undef printf
91
#define printf printf
92
#endif
93
94
#include <cups/raster.h>
95
#include <cups/ppd.h>
96
#include <math.h>
97
98
/* the extremely noisy DEBUG2 messages are now dependent on CUPS_DEBUG2 */
99
/* this can be enabled during the 'make' or by uncommenting the following */
100
/* #define CUPS_DEBUG2 */
101
102
#undef private
103
#define private
104
105
#ifdef WIN32
106
#define cbrt(arg) pow(arg, 1.0/3)
107
#define strcasecmp _stricmp
108
#define strncasecmp _strnicmp
109
#endif
110
111
/* This should go into gdevprn.h, or, better yet, gdevprn should
112
   acquire an API for changing resolution. */
113
int gdev_prn_maybe_realloc_memory(gx_device_printer *pdev,
114
                                  gdev_space_params *old_space,
115
                                  int old_width, int old_height,
116
                                  bool old_page_uses_transparency);
117
118
/* Strings for cups_put/get_params */
119
static const char * const cups_Integer_strings[] =
120
{
121
  "cupsInteger0",
122
  "cupsInteger1",
123
  "cupsInteger2",
124
  "cupsInteger3",
125
  "cupsInteger4",
126
  "cupsInteger5",
127
  "cupsInteger6",
128
  "cupsInteger7",
129
  "cupsInteger8",
130
  "cupsInteger9",
131
  "cupsInteger10",
132
  "cupsInteger11",
133
  "cupsInteger12",
134
  "cupsInteger13",
135
  "cupsInteger14",
136
  "cupsInteger15",
137
  NULL
138
};
139
140
static const char * const cups_Real_strings[] =
141
{
142
  "cupsReal0",
143
  "cupsReal1",
144
  "cupsReal2",
145
  "cupsReal3",
146
  "cupsReal4",
147
  "cupsReal5",
148
  "cupsReal6",
149
  "cupsReal7",
150
  "cupsReal8",
151
  "cupsReal9",
152
  "cupsReal10",
153
  "cupsReal11",
154
  "cupsReal12",
155
  "cupsReal13",
156
  "cupsReal14",
157
  "cupsReal15",
158
  NULL
159
};
160
161
static const char * const cups_String_strings[] =
162
{
163
  "cupsString0",
164
  "cupsString1",
165
  "cupsString2",
166
  "cupsString3",
167
  "cupsString4",
168
  "cupsString5",
169
  "cupsString6",
170
  "cupsString7",
171
  "cupsString8",
172
  "cupsString9",
173
  "cupsString10",
174
  "cupsString11",
175
  "cupsString12",
176
  "cupsString13",
177
  "cupsString14",
178
  "cupsString15",
179
  NULL
180
};
181
182
/*
183
 * Check if we are compiling against CUPS 1.2.  If so, enable
184
 * certain extended attributes and use a different page header
185
 * structure and write function...
186
 */
187
188
#ifdef CUPS_RASTER_SYNCv1
189
#  define cups_page_header_t cups_page_header2_t
190
24.1k
#  define cupsRasterWriteHeader cupsRasterWriteHeader2
191
#else
192
/* The RGBW, SW, SRGB, and ADOBERGB colorspaces is not defined until
193
   CUPS 1.2... */
194
#  define CUPS_CSPACE_RGBW 17
195
#  define CUPS_CSPACE_SW 18
196
#  define CUPS_CSPACE_SRGB 19
197
#  define CUPS_CSPACE_ADOBERGB 20
198
#endif /* CUPS_RASTER_SYNCv1 */
199
200
#if !defined(CUPS_RASTER_WRITE_PWG)
201
0
    #define CUPS_RASTER_WRITE_PWG 3
202
#endif
203
204
/*
205
 * CIE XYZ color constants...
206
 */
207
208
4.11M
#define D65_X (0.412453 + 0.357580 + 0.180423)
209
12.3M
#define D65_Y (0.212671 + 0.715160 + 0.072169)
210
4.11M
#define D65_Z (0.019334 + 0.119193 + 0.950227)
211
212
213
/*
214
 * Size of a tile in pixels...
215
 */
216
217
0
#define CUPS_TILE_SIZE  256
218
219
220
/*
221
 * Size of profile LUTs...
222
 */
223
224
#ifdef dev_t_proc_encode_color
225
9.62G
#  define CUPS_MAX_VALUE  frac_1
226
#else
227
#  define CUPS_MAX_VALUE  gx_max_color_value
228
#endif /* dev_t_proc_encode_color */
229
230
231
/*
232
 * Macros...
233
 */
234
235
#define x_dpi   (pdev->HWResolution[0])
236
#define y_dpi   (pdev->HWResolution[1])
237
36.5G
#define cups    ((gx_device_cups *)pdev)
238
239
/*
240
 * Macros from <macros.h>; we can't include <macros.h> because it also
241
 * defines DEBUG, one of our flags to insert various debugging code.
242
 */
243
244
#ifndef max
245
#  define max(a,b)  ((a)<(b) ? (b) : (a))
246
#endif /* !max */
247
248
#ifndef min
249
#  define min(a,b)  ((a)>(b) ? (b) : (a))
250
#endif /* !min */
251
252
#ifndef abs
253
#  define abs(x)  ((x)>=0 ? (x) : -(x))
254
#endif /* !abs */
255
256
257
/*
258
 * Procedures
259
 */
260
261
private dev_proc_close_device(cups_close);
262
private dev_proc_get_initial_matrix(cups_get_matrix);
263
private int cups_get_params(gx_device *, gs_param_list *);
264
private dev_proc_open_device(cups_open);
265
private dev_proc_output_page(cups_output_page);
266
private int cups_print_pages(gx_device_printer *, gp_file *, int);
267
private int cups_put_params(gx_device *, gs_param_list *);
268
private int cups_set_color_info(gx_device *);
269
private dev_proc_sync_output(cups_sync_output);
270
private prn_dev_proc_get_space_params(cups_get_space_params);
271
private int cups_spec_op(gx_device *dev_, int op, void *data, int datasize);
272
273
#ifdef dev_t_proc_encode_color
274
private cm_map_proc_gray(cups_map_gray);
275
private cm_map_proc_rgb(cups_map_rgb);
276
private cm_map_proc_cmyk(cups_map_cmyk);
277
private dev_proc_decode_color(cups_decode_color);
278
private dev_proc_encode_color(cups_encode_color);
279
private dev_proc_get_color_comp_index(cups_get_color_comp_index);
280
private dev_proc_get_color_mapping_procs(cups_get_color_mapping_procs);
281
282
static const gx_cm_color_map_procs cups_color_mapping_procs =
283
{
284
  cups_map_gray,
285
  cups_map_rgb,
286
  cups_map_cmyk
287
};
288
#else
289
private dev_proc_map_cmyk_color(cups_map_cmyk_color);
290
private dev_proc_map_color_rgb(cups_map_color_rgb);
291
private dev_proc_map_rgb_color(cups_map_rgb_color);
292
#endif /* dev_t_proc_encode_color */
293
294
295
/*
296
 * The device descriptors...
297
 */
298
299
typedef struct gx_device_cups_s
300
{
301
  gx_device_common;     /* Standard GhostScript device stuff */
302
  gx_prn_device_common;     /* Standard printer device stuff */
303
  int     page;   /* Page number */
304
  cups_raster_t   *stream;  /* Raster stream */
305
  cups_page_header_t  header;   /* PostScript page device info */
306
  int     landscape;  /* Non-zero if this is landscape */
307
  int     lastpage;
308
  int     HaveProfile;  /* Has a color profile been defined? */
309
  char      *Profile; /* Current simple color profile string */
310
  ppd_file_t    *PPD;   /* PPD file for this device */
311
  unsigned char   RevLower1[16];  /* Lower 1-bit reversal table */
312
  unsigned char   RevUpper1[16];  /* Upper 1-bit reversal table */
313
  unsigned char   RevLower2[16];  /* Lower 2-bit reversal table */
314
  unsigned char   RevUpper2[16];  /* Upper 2-bit reversal table */
315
#ifdef GX_COLOR_INDEX_TYPE
316
  gx_color_value  DecodeLUT[65536];/* Output color to RGB value LUT */
317
#else
318
  gx_color_value  DecodeLUT[256]; /* Output color to RGB value LUT */
319
#endif /* GX_COLOR_INDEX_TYPE */
320
  unsigned short  EncodeLUT[gx_max_color_value + 1];/* RGB value to output color LUT */
321
  int     Density[CUPS_MAX_VALUE + 1];/* Density LUT */
322
  int     Matrix[3][3][CUPS_MAX_VALUE + 1];/* Color transform matrix LUT */
323
  int                   user_icc;
324
  int                   cupsRasterVersion;
325
  char                  cupsBackSideOrientation[64];
326
  int                   cupsBackSideFlipMargins;
327
  int                   cupsManualCopies;
328
  char                  pageSizeRequested[64];
329
330
  /* Used by cups_put_params(): */
331
} gx_device_cups;
332
333
static void
334
cups_initialize_device_procs(gx_device *dev)
335
29.4k
{
336
29.4k
    set_dev_proc(dev, open_device, cups_open);
337
29.4k
    set_dev_proc(dev, get_initial_matrix, cups_get_matrix);
338
29.4k
    set_dev_proc(dev, sync_output, cups_sync_output);
339
29.4k
    set_dev_proc(dev, output_page, cups_output_page);
340
29.4k
    set_dev_proc(dev, close_device, cups_close);
341
29.4k
#ifdef dev_t_proc_encode_color
342
29.4k
    set_dev_proc(dev, get_color_mapping_procs, cups_get_color_mapping_procs);
343
29.4k
    set_dev_proc(dev, get_color_comp_index, cups_get_color_comp_index);
344
29.4k
    set_dev_proc(dev, encode_color, cups_encode_color);
345
29.4k
    set_dev_proc(dev, decode_color, cups_decode_color);
346
#else
347
    set_dev_proc(dev, map_rgb_color, cups_map_rgb_color);
348
    set_dev_proc(dev, map_color_rgb, cups_map_color_rgb);
349
    set_dev_proc(dev, map_cmyk_color, cups_map_cmyk_color);
350
#endif
351
29.4k
    set_dev_proc(dev, get_params, cups_get_params);
352
29.4k
    set_dev_proc(dev, put_params, cups_put_params);
353
29.4k
    set_dev_proc(dev, get_page_device, gx_page_device_get_page_device);
354
29.4k
    set_dev_proc(dev, dev_spec_op, cups_spec_op);
355
29.4k
}
356
357
#define prn_device_body_copies(dtype, init, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_pages)\
358
  std_device_full_body_type(dtype, init, dname, &st_device_printer,\
359
    (int)((long)(w10) * (xdpi) / 10),\
360
    (int)((long)(h10) * (ydpi) / 10),\
361
    xdpi, ydpi,\
362
    ncomp, depth, mg, mc, dg, dc,\
363
    -(lo) * (xdpi), -(to) * (ydpi),\
364
    (lm) * 72.0, (bm) * 72.0,\
365
    (rm) * 72.0, (tm) * 72.0\
366
  ),\
367
  prn_device_body_copies_rest_(print_pages)
368
369
370
371
#ifdef CUPS_RASTER_SYNCv1
372
#define RASTER_SYNCv1_ENTRIES \
373
    ,\
374
    1,                                  /* cupsNumColors */\
375
    1.0,                                /* cupsBorderlessScalingFactor */\
376
    { 612.0, 792.0 },                   /* cupsPageSize */\
377
    { 0.0, 0.0, 612.0, 792.0 },         /* cupsImagingBBox */\
378
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* cupsInteger */\
379
    { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\
380
      0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, /* cupsReal */\
381
    { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },\
382
                                        /* cupsString */\
383
    "",                                 /* cupsMarkerType */\
384
    "",                                 /* cupsRenderingIntent */\
385
    ""                                  /* cupsPageSizeName */
386
#else
387
#define RASTER_SYNCv1_ENTRIES
388
#endif /* CUPS_RASTER_SYNCv1 */
389
390
#define gs_xxx_device(dname, mediaclass)\
391
  prn_device_body_copies(gx_device_cups,/* type */\
392
                         cups_initialize_device_procs,/* init */\
393
       dname,   /* device name */\
394
       85,    /* initial width */\
395
       110,   /* initial height */\
396
       100,   /* initial x resolution */\
397
       100,   /* initial y resolution */\
398
                         0,   /* initial left offset */\
399
       0,   /* initial top offset */\
400
       0,   /* initial left margin */\
401
       0,   /* initial bottom margin */\
402
       0,   /* initial right margin */\
403
       0,   /* initial top margin */\
404
       1,   /* number of color components */\
405
       1,   /* number of color bits */\
406
       1,   /* maximum gray value */\
407
       0,   /* maximum color value */\
408
       2,   /* number of gray values */\
409
       0,   /* number of color values */\
410
       cups_print_pages),\
411
          /* print procedure */\
412
  0,          /* page */\
413
  NULL,         /* stream */\
414
  {         /* header */\
415
    mediaclass,       /* MediaClass */\
416
    "",         /* MediaColor */\
417
    "",         /* MediaType */\
418
    "",         /* OutputType */\
419
    0,          /* AdvanceDistance */\
420
    CUPS_ADVANCE_NONE,      /* AdvanceMedia */\
421
    CUPS_FALSE,       /* Collate */\
422
    CUPS_CUT_NONE,      /* CutMedia */\
423
    CUPS_FALSE,       /* Duplex */\
424
    { 100, 100 },     /* HWResolution */\
425
    { 0, 0, 612, 792 },     /* ImagingBoundingBox */\
426
    CUPS_FALSE,       /* InsertSheet */\
427
    CUPS_JOG_NONE,      /* Jog */\
428
    CUPS_EDGE_TOP,      /* LeadingEdge */\
429
    { 0, 0 },       /* Margins */\
430
    CUPS_FALSE,       /* ManualFeed */\
431
    0,          /* MediaPosition */\
432
    0,          /* MediaWeight */\
433
    CUPS_FALSE,       /* MirrorPrint */\
434
    CUPS_FALSE,       /* NegativePrint */\
435
    1,          /* NumCopies */\
436
    CUPS_ORIENT_0,      /* Orientation */\
437
    CUPS_FALSE,       /* OutputFaceUp */\
438
    { 612, 792 },     /* PageSize */\
439
    CUPS_FALSE,       /* Separations */\
440
    CUPS_FALSE,       /* TraySwitch */\
441
    CUPS_FALSE,       /* Tumble */\
442
    850,        /* cupsWidth */\
443
    1100,       /* cupsHeight */\
444
    0,          /* cupsMediaType */\
445
    1,          /* cupsBitsPerColor */\
446
    1,          /* cupsBitsPerPixel */\
447
    107,        /* cupsBytesPerLine */\
448
    CUPS_ORDER_CHUNKED,     /* cupsColorOrder */\
449
    CUPS_CSPACE_K,      /* cupsColorSpace */\
450
    0,          /* cupsCompression */\
451
    0,          /* cupsRowCount */\
452
    0,          /* cupsRowFeed */\
453
    0         /* cupsRowStep */\
454
    RASTER_SYNCv1_ENTRIES, /* See above */\
455
  },\
456
  0,                                    /* landscape */\
457
  0,                                    /* lastpage */\
458
  0,                                    /* HaveProfile */\
459
  NULL,                                 /* Profile */\
460
  NULL,                                 /* PPD */\
461
  { 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,\
462
    0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f },/* RevLower1 */\
463
  { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,\
464
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0 },/* RevUpper1 */\
465
  { 0x00, 0x04, 0x08, 0x0c, 0x01, 0x05, 0x09, 0x0d,\
466
    0x02, 0x06, 0x0a, 0x0e, 0x03, 0x07, 0x0b, 0x0f },/* RevLower2 */\
467
  { 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,\
468
    0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0 },/* RevUpper2 */\
469
  {0x00},                                  /* DecodeLUT */\
470
  {0x00},                                  /* EncodeLUT */\
471
  {0x00},                                  /* Density */\
472
  {{{0x00},{0x00},{0x00}},\
473
   {{0x00},{0x00},{0x00}},\
474
   {{0x00},{0x00},{0x00}}},                /* Matrix */\
475
  0,                                       /* user_icc */\
476
  3,                                     /* cupsRasterVersion */\
477
  "Normal",                                /* cupsBackSideOrientation */\
478
  0,                                       /* cupsBackSideFlipMargins */\
479
  0,                                       /* cupsManualCopies */\
480
  ""                                     /* pageSizeRequested */
481
482
gx_device_cups  gs_cups_device = { gs_xxx_device("cups", "") };
483
gx_device_cups  gs_pwgraster_device = { gs_xxx_device("pwgraster",
484
                  "PwgRaster") };
485
#if defined(CUPS_RASTER_HAVE_APPLERASTER)
486
gx_device_cups  gs_appleraster_device = { gs_xxx_device("appleraster",
487
              "PwgRaster") };
488
gx_device_cups  gs_urf_device = { gs_xxx_device("urf",
489
            "PwgRaster") };
490
#endif
491
492
/*
493
 * Local functions...
494
 */
495
496
static double cups_map_cielab(double, double);
497
static int  cups_print_chunked(gx_device_printer *, unsigned char *,
498
                       unsigned char *, int);
499
static int  cups_print_banded(gx_device_printer *, unsigned char *,
500
                      unsigned char *, int);
501
static int  cups_print_planar(gx_device_printer *, unsigned char *,
502
                      unsigned char *, int);
503
504
/*static void cups_set_margins(gx_device *);*/
505
506
507
/*
508
 * 'cups_close()' - Close the output file.
509
 */
510
511
private int
512
cups_close(gx_device *pdev)   /* I - Device info */
513
29.4k
{
514
#ifdef CUPS_DEBUG2
515
  dmprintf1(pdev->memory, "DEBUG2: cups_close(%p)\n", pdev);
516
#endif /* CUPS_DEBUG2 */
517
518
29.4k
  dmprintf(pdev->memory, "INFO: Rendering completed\n");
519
520
29.4k
  if (cups->stream != NULL)
521
15.6k
  {
522
15.6k
    cupsRasterClose(cups->stream);
523
15.6k
    cups->stream = NULL;
524
15.6k
  }
525
526
#if 0 /* Can't do this here because put_params() might close the device */
527
  if (cups->PPD != NULL)
528
  {
529
    ppdClose(cups->PPD);
530
    cups->PPD = NULL;
531
  }
532
533
  if (cups->Profile != NULL)
534
  {
535
    free(cups->Profile);
536
    cups->Profile = NULL;
537
  }
538
#endif /* 0 */
539
540
29.4k
  return (gdev_prn_close(pdev));
541
29.4k
}
542
543
544
#ifdef dev_t_proc_encode_color
545
/*
546
 * 'cups_decode_color()' - Decode a color value.
547
 */
548
549
private int       /* O - Status (0 = OK) */
550
cups_decode_color(gx_device      *pdev, /* I - Device info */
551
                  gx_color_index ci,  /* I - Color index */
552
                  gx_color_value *cv) /* O - Colors */
553
0
{
554
0
  int     i;    /* Looping var */
555
0
  int     shift;    /* Bits to shift */
556
0
  int     mask;   /* Bits to mask */
557
558
559
0
  if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
560
0
      cups->header.cupsBitsPerColor == 1)
561
0
  {
562
   /*
563
    * KCMYcm data is represented internally by Ghostscript as CMYK...
564
    */
565
566
0
    cv[0] = (ci & 0x20) ? frac_1 : frac_0;
567
0
    cv[1] = (ci & 0x12) ? frac_1 : frac_0;
568
0
    cv[2] = (ci & 0x09) ? frac_1 : frac_0;
569
0
    cv[3] = (ci & 0x04) ? frac_1 : frac_0;
570
0
  }
571
0
  else
572
0
  {
573
0
    shift = cups->header.cupsBitsPerColor;
574
0
    mask  = (1 << shift) - 1;
575
576
0
    for (i = cups->color_info.num_components - 1; i > 0; i --, ci >>= shift)
577
0
      cv[i] = cups->DecodeLUT[ci & mask];
578
579
0
    cv[0] = cups->DecodeLUT[ci & mask];
580
0
  }
581
582
0
  return (0);
583
0
}
584
585
586
/*
587
 * 'cups_encode_color()' - Encode a color value.
588
 */
589
590
private gx_color_index      /* O - Color index */
591
cups_encode_color(gx_device            *pdev,
592
          /* I - Device info */
593
                  const gx_color_value *cv)
594
          /* I - Colors */
595
662M
{
596
662M
  int     i;    /* Looping var */
597
662M
  gx_color_index  ci;   /* Color index */
598
662M
  int     shift;    /* Bits to shift */
599
600
601
 /*
602
  * Encode the color index...
603
  */
604
605
662M
  shift = cups->header.cupsBitsPerColor;
606
607
662M
  for (ci = cups->EncodeLUT[cv[0]], i = 1;
608
1.97G
       i < cups->color_info.num_components;
609
1.31G
       i ++)
610
1.31G
    ci = (ci << shift) | cups->EncodeLUT[cv[i]];
611
612
#ifdef CUPS_DEBUG2
613
  dmprintf2(pdev->memory, "DEBUG2: cv[0]=%d -> %llx\n", cv[0], ci);
614
#endif /* CUPS_DEBUG2 */
615
616
 /*
617
  * Handle 6-color output...
618
  */
619
620
662M
  if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
621
22.9k
      cups->header.cupsBitsPerColor == 1)
622
22.9k
  {
623
   /*
624
    * Welcome to hackville, where we map CMYK data to the
625
    * light inks in draft mode...  Map blue to light magenta and
626
    * cyan and green to light cyan and yellow...
627
    */
628
629
22.9k
    ci <<= 2;       /* Leave room for light inks */
630
631
22.9k
    if (ci == 0x18)      /* Blue */
632
36
      ci = 0x11;      /* == cyan + light magenta */
633
22.8k
    else if (ci == 0x14)    /* Green */
634
20
      ci = 0x06;     /* == light cyan + yellow */
635
22.9k
  }
636
637
  /* The entire manner that cups does its color mapping needs some serious
638
     rework.  In the case of the output RGBW color space, it takes a source
639
     CMYK value which gs maps to RGB, cups then maps the RGB to CMYK and then
640
     from there to RGBW and finally it does an encode.  Unfortunately, the
641
     number of color values for RGBW is 3 since it is using an RGB ICC profile
642
     this means that the W mapping value from cups is lost in cmap_rgb_direct
643
     So here we ensure that the W is always set to on (else we end up with a
644
     blue background cast).  The ideal way
645
     to fix this is to move some of these odd color spaces of cups to the
646
     separation device model ensuring that things are handled properly. */
647
662M
  if (cups->header.cupsColorSpace == CUPS_CSPACE_RGBW) {
648
9.00k
      ci = (ci << shift) | cups->EncodeLUT[gx_max_color_value];
649
9.00k
  }
650
651
 /*
652
  * Range check the return value...
653
  */
654
655
662M
  if (ci == gx_no_color_index)
656
0
    ci --;
657
658
 /*
659
  * Return the color index...
660
  */
661
662
662M
  return (ci);
663
662M
}
664
665
/*
666
 * 'cups_get_color_comp_index()' - Color component to index
667
 */
668
669
#define compare_color_names(pname, name_size, name_str) \
670
5.82M
    (name_size == (int)strlen(name_str) && strncasecmp(pname, name_str, name_size) == 0)
671
672
int                                     /* O - Index of the named color in
673
             the color space */
674
cups_get_color_comp_index(gx_device * pdev, const char * pname,
675
        int name_size, int component_type)
676
1.17M
{
677
1.17M
  switch (cups->header.cupsColorSpace)
678
1.17M
  {
679
7.18k
    case CUPS_CSPACE_K :
680
7.18k
        if (compare_color_names(pname, name_size, "Black") ||
681
7.18k
      compare_color_names(pname, name_size, "Gray") ||
682
6.15k
      compare_color_names(pname, name_size, "Grey"))
683
1.02k
      return 0;
684
6.15k
  else
685
6.15k
      return -1; /* Indicate that the component name is "unknown" */
686
0
        break;
687
130k
    case CUPS_CSPACE_W :
688
135k
    case CUPS_CSPACE_SW :
689
161k
    case CUPS_CSPACE_WHITE :
690
161k
        if (compare_color_names(pname, name_size, "White") ||
691
161k
      compare_color_names(pname, name_size, "Luminance") ||
692
161k
      compare_color_names(pname, name_size, "Gray") ||
693
138k
      compare_color_names(pname, name_size, "Grey"))
694
23.0k
      return 0;
695
138k
  else
696
138k
      return -1;
697
0
        break;
698
6.98k
    case CUPS_CSPACE_RGBA :
699
6.98k
        if (compare_color_names(pname, name_size, "Alpha") ||
700
6.98k
      compare_color_names(pname, name_size, "Transparent") ||
701
6.98k
      compare_color_names(pname, name_size, "Transparency"))
702
0
      return 3;
703
        /* fall through */
704
20.0k
    case CUPS_CSPACE_RGBW :
705
20.0k
        if (compare_color_names(pname, name_size, "Red"))
706
4.00k
      return 0;
707
16.0k
  if (compare_color_names(pname, name_size, "Green"))
708
4.00k
      return 1;
709
12.0k
  if (compare_color_names(pname, name_size, "Blue"))
710
4.00k
            return 2;
711
8.00k
  if (compare_color_names(pname, name_size, "White"))
712
0
            return 3;
713
8.00k
  else
714
8.00k
      return -1;
715
0
        break;
716
336k
    case CUPS_CSPACE_RGB :
717
339k
    case CUPS_CSPACE_SRGB :
718
378k
    case CUPS_CSPACE_ADOBERGB :
719
378k
        if (compare_color_names(pname, name_size, "Red"))
720
73.5k
      return 0;
721
304k
  if (compare_color_names(pname, name_size, "Green"))
722
73.5k
      return 1;
723
231k
  if (compare_color_names(pname, name_size, "Blue"))
724
73.5k
            return 2;
725
157k
        break;
726
157k
    case CUPS_CSPACE_CMYK :
727
33.0k
#  ifdef CUPS_RASTER_HAVE_COLORIMETRIC
728
33.0k
    case CUPS_CSPACE_CIEXYZ :
729
33.0k
    case CUPS_CSPACE_CIELab :
730
33.0k
    case CUPS_CSPACE_ICC1 :
731
33.0k
    case CUPS_CSPACE_ICC2 :
732
33.0k
    case CUPS_CSPACE_ICC3 :
733
33.0k
    case CUPS_CSPACE_ICC4 :
734
33.0k
    case CUPS_CSPACE_ICC5 :
735
33.0k
    case CUPS_CSPACE_ICC6 :
736
33.0k
    case CUPS_CSPACE_ICC7 :
737
33.0k
    case CUPS_CSPACE_ICC8 :
738
33.0k
    case CUPS_CSPACE_ICC9 :
739
33.0k
    case CUPS_CSPACE_ICCA :
740
33.0k
    case CUPS_CSPACE_ICCB :
741
33.0k
    case CUPS_CSPACE_ICCC :
742
33.0k
    case CUPS_CSPACE_ICCD :
743
33.0k
    case CUPS_CSPACE_ICCE :
744
33.0k
    case CUPS_CSPACE_ICCF :
745
33.0k
#  endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
746
33.0k
        if (compare_color_names(pname, name_size, "Black"))
747
11.7k
      return 3;
748
        /* fall through */
749
26.8k
    case CUPS_CSPACE_CMY :
750
26.8k
        if (compare_color_names(pname, name_size, "Cyan"))
751
4.29k
      return 0;
752
22.5k
  if (compare_color_names(pname, name_size, "Magenta"))
753
4.29k
      return 1;
754
18.2k
  if (compare_color_names(pname, name_size, "Yellow"))
755
4.29k
      return 2;
756
13.9k
  else
757
13.9k
      return -1;
758
0
        break;
759
119k
    case CUPS_CSPACE_GMCS :
760
119k
        if (compare_color_names(pname, name_size, "Silver") ||
761
119k
      compare_color_names(pname, name_size, "Silver Foil"))
762
0
      return 3;
763
        /* fall through */
764
339k
    case CUPS_CSPACE_GMCK :
765
339k
        if (compare_color_names(pname, name_size, "Gold") ||
766
339k
      compare_color_names(pname, name_size, "Gold Foil"))
767
0
      return 0;
768
        /* fall through */
769
357k
    case CUPS_CSPACE_YMCK :
770
357k
        if (compare_color_names(pname, name_size, "Black"))
771
120k
      return 3;
772
        /* fall through */
773
240k
    case CUPS_CSPACE_YMC :
774
240k
  if (compare_color_names(pname, name_size, "Yellow"))
775
53.5k
      return 0;
776
186k
  if (compare_color_names(pname, name_size, "Magenta"))
777
53.5k
      return 1;
778
133k
        if (compare_color_names(pname, name_size, "Cyan"))
779
53.5k
      return 2;
780
79.7k
  else
781
79.7k
      return -1;
782
0
        break;
783
122k
    case CUPS_CSPACE_KCMYcm :
784
122k
        if (compare_color_names(pname, name_size, "Light Cyan") ||
785
122k
      compare_color_names(pname, name_size, "Photo Cyan"))
786
0
      return 4;
787
122k
        if (compare_color_names(pname, name_size, "Light Magenta") ||
788
122k
      compare_color_names(pname, name_size, "Photo Magenta"))
789
0
      return 5;
790
156k
    case CUPS_CSPACE_KCMY :
791
156k
        if (compare_color_names(pname, name_size, "Black"))
792
52.1k
      return 0;
793
104k
        if (compare_color_names(pname, name_size, "Cyan"))
794
22.8k
      return 1;
795
81.3k
  if (compare_color_names(pname, name_size, "Magenta"))
796
22.8k
      return 2;
797
58.5k
  if (compare_color_names(pname, name_size, "Yellow"))
798
22.8k
      return 3;
799
35.6k
  else
800
35.6k
      return -1;
801
0
        break;
802
30.8k
    case CUPS_CSPACE_GOLD :
803
30.8k
        if (compare_color_names(pname, name_size, "Gold") ||
804
30.8k
      compare_color_names(pname, name_size, "Gold Foil"))
805
0
      return 0;
806
30.8k
  else
807
30.8k
      return -1;
808
0
        break;
809
20.4k
    case CUPS_CSPACE_SILVER :
810
20.4k
        if (compare_color_names(pname, name_size, "Silver") ||
811
20.4k
      compare_color_names(pname, name_size, "Silver Foil"))
812
0
      return 0;
813
20.4k
  else
814
20.4k
      return -1;
815
0
        break;
816
0
    default:
817
0
        break;
818
1.17M
  }
819
157k
  return -1;
820
1.17M
}
821
822
/*
823
 * 'cups_get_color_mapping_procs()' - Get the list of color mapping procedures.
824
 */
825
826
private const gx_cm_color_map_procs * /* O - List of device procedures */
827
cups_get_color_mapping_procs(const gx_device *pdev, const gx_device **tdev)
828
          /* I - Device info */
829
125M
{
830
125M
  *tdev = pdev;
831
125M
  return (&cups_color_mapping_procs);
832
125M
}
833
#endif /* dev_t_proc_encode_color */
834
835
836
/*
837
 * 'cups_get_matrix()' - Generate the default page matrix.
838
 */
839
840
private void
841
cups_get_matrix(gx_device *pdev,  /* I - Device info */
842
                gs_matrix *pmat)  /* O - Physical transform matrix */
843
61.3M
{
844
#ifdef CUPS_DEBUG2
845
  dmprintf2(pdev->memory, "DEBUG2: cups_get_matrix(%p, %p)\n", pdev, pmat);
846
#endif /* CUPS_DEBUG2 */
847
848
 /*
849
  * Set the raster width and height...
850
  */
851
852
61.3M
  cups->header.cupsWidth  = cups->width;
853
61.3M
  cups->header.cupsHeight = cups->height;
854
855
 /*
856
  * Set the transform matrix...
857
  */
858
859
61.3M
  if (cups->landscape)
860
0
  {
861
   /*
862
    * Do landscape orientation...
863
    */
864
#ifdef CUPS_DEBUG2
865
    dprintf("DEBUG2: Landscape matrix: XX=0 XY=+1 YX=+1 YY=0\n");
866
#endif /* CUPS_DEBUG2 */
867
0
    pmat->xx = 0.0;
868
0
    pmat->xy = (float)cups->header.HWResolution[1] / 72.0;
869
0
    pmat->yx = (float)cups->header.HWResolution[0] / 72.0;
870
0
    pmat->yy = 0.0;
871
0
    pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[1] / 72.0;
872
0
    pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[0] / 72.0;
873
0
  }
874
61.3M
  else
875
61.3M
  {
876
   /*
877
    * Do portrait orientation...
878
    */
879
#ifdef CUPS_DEBUG2
880
    dmprintf(pdev->memory, "DEBUG2: Portrait matrix: XX=+1 XY=0 YX=0 YY=-1\n");
881
#endif /* CUPS_DEBUG2 */
882
61.3M
    pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
883
61.3M
    pmat->xy = 0.0;
884
61.3M
    pmat->yx = 0.0;
885
61.3M
    pmat->yy = -(float)cups->header.HWResolution[1] / 72.0;
886
61.3M
    pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
887
61.3M
    pmat->ty = (float)cups->header.HWResolution[1] *
888
61.3M
               ((float)cups->header.PageSize[1] - pdev->HWMargins[3]) / 72.0;
889
61.3M
  }
890
891
61.3M
#ifdef CUPS_RASTER_SYNCv1
892
61.3M
  if (cups->header.cupsBorderlessScalingFactor > 1.0)
893
0
  {
894
0
    pmat->xx *= cups->header.cupsBorderlessScalingFactor;
895
0
    pmat->xy *= cups->header.cupsBorderlessScalingFactor;
896
0
    pmat->yx *= cups->header.cupsBorderlessScalingFactor;
897
0
    pmat->yy *= cups->header.cupsBorderlessScalingFactor;
898
0
    pmat->tx *= cups->header.cupsBorderlessScalingFactor;
899
0
    pmat->ty *= cups->header.cupsBorderlessScalingFactor;
900
0
  }
901
61.3M
#endif /* CUPS_RASTER_SYNCv1 */
902
903
#ifdef CUPS_DEBUG2
904
  dmprintf2(pdev->memory, "DEBUG2: width = %d, height = %d\n", cups->header.cupsWidth,
905
            cups->header.cupsHeight);
906
  dmprintf4(pdev->memory, "DEBUG2: PageSize = [ %d %d ], HWResolution = [ %d %d ]\n",
907
            cups->header.PageSize[0], cups->header.PageSize[1],
908
            cups->header.HWResolution[0], cups->header.HWResolution[1]);
909
  dmprintf4(pdev->memory, "DEBUG2: HWMargins = [ %.3f %.3f %.3f %.3f ]\n",
910
            pdev->HWMargins[0], pdev->HWMargins[1], pdev->HWMargins[2],
911
            pdev->HWMargins[3]);
912
  dmprintf6(pdev->memory, "DEBUG2: matrix = [ %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
913
            pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
914
#endif /* CUPS_DEBUG2 */
915
61.3M
}
916
917
918
/*
919
 * 'cups_get_params()' - Get pagedevice parameters.
920
 */
921
922
private int       /* O - Error status */
923
cups_get_params(gx_device     *pdev,  /* I - Device info */
924
                gs_param_list *plist) /* I - Parameter list */
925
877k
{
926
877k
  int     code;   /* Return code */
927
877k
  gs_param_string s;    /* Temporary string value */
928
877k
  bool      b;    /* Temporary boolean value */
929
877k
#ifdef CUPS_RASTER_SYNCv1
930
877k
  int     i;    /* Looping var */
931
877k
#endif /* CUPS_RASTER_SYNCv1 */
932
933
934
#ifdef CUPS_DEBUG2
935
  dmprintf2(pdev->memory, "DEBUG2: cups_get_params(%p, %p)\n", pdev, plist);
936
#endif /* CUPS_DEBUG2 */
937
938
 /*
939
  * First process the "standard" page device parameters...
940
  */
941
942
#ifdef CUPS_DEBUG2
943
  dmprintf(pdev->memory, "DEBUG2: before gdev_prn_get_params()\n");
944
#endif /* CUPS_DEBUG2 */
945
946
877k
  if ((code = gdev_prn_get_params(pdev, plist)) < 0)
947
0
    goto done;
948
949
#ifdef CUPS_DEBUG2
950
  dmprintf(pdev->memory, "DEBUG2: after gdev_prn_get_params()\n");
951
#endif /* CUPS_DEBUG2 */
952
953
 /*
954
  * Then write the CUPS parameters...
955
  */
956
957
877k
  param_string_from_transient_string(s, cups->header.MediaClass);
958
877k
  if ((code = param_write_string(plist, "MediaClass", &s)) < 0)
959
0
    goto done;
960
961
877k
  param_string_from_transient_string(s, cups->header.MediaColor);
962
877k
  if ((code = param_write_string(plist, "MediaColor", &s)) < 0)
963
0
    goto done;
964
965
877k
  param_string_from_transient_string(s, cups->header.MediaType);
966
877k
  if ((code = param_write_string(plist, "MediaType", &s)) < 0)
967
0
    goto done;
968
969
877k
  param_string_from_transient_string(s, cups->header.OutputType);
970
877k
  if ((code = param_write_string(plist, "OutputType", &s)) < 0)
971
0
    goto done;
972
973
877k
  if ((code = param_write_int(plist, "AdvanceDistance",
974
877k
                              (int *)&(cups->header.AdvanceDistance))) < 0)
975
0
    goto done;
976
977
877k
  if ((code = param_write_int(plist, "AdvanceMedia",
978
877k
                              (int *)&(cups->header.AdvanceMedia))) < 0)
979
0
    goto done;
980
981
877k
  b = cups->header.Collate;
982
877k
  if ((code = param_write_bool(plist, "Collate", &b)) < 0)
983
0
    goto done;
984
985
877k
  if ((code = param_write_int(plist, "CutMedia",
986
877k
                              (int *)&(cups->header.CutMedia))) < 0)
987
0
    goto done;
988
989
877k
  b = cups->header.Duplex;
990
877k
  if ((code = param_write_bool(plist, "Duplex", &b)) < 0)
991
0
    goto done;
992
993
877k
  b = cups->header.InsertSheet;
994
877k
  if ((code = param_write_bool(plist, "InsertSheet", &b)) < 0)
995
0
    goto done;
996
997
877k
  if ((code = param_write_int(plist, "Jog",
998
877k
                              (int *)&(cups->header.Jog))) < 0)
999
0
    goto done;
1000
1001
877k
  b = cups->header.ManualFeed;
1002
877k
  if ((code = param_write_bool(plist, "ManualFeed", &b)) < 0)
1003
0
    goto done;
1004
1005
877k
  if ((code = param_write_int(plist, "MediaPosition",
1006
877k
                              (int *)&(cups->header.MediaPosition))) < 0)
1007
0
    goto done;
1008
1009
877k
  if ((code = param_write_int(plist, "MediaWeight",
1010
877k
                              (int *)&(cups->header.MediaWeight))) < 0)
1011
0
    goto done;
1012
1013
877k
  b = cups->header.MirrorPrint;
1014
877k
  if ((code = param_write_bool(plist, "MirrorPrint", &b)) < 0)
1015
0
    goto done;
1016
1017
877k
  b = cups->header.NegativePrint;
1018
877k
  if ((code = param_write_bool(plist, "NegativePrint", &b)) < 0)
1019
0
    goto done;
1020
1021
877k
  b = cups->header.OutputFaceUp;
1022
877k
  if ((code = param_write_bool(plist, "OutputFaceUp", &b)) < 0)
1023
0
    goto done;
1024
1025
877k
  b = cups->header.Separations;
1026
877k
  if ((code = param_write_bool(plist, "Separations", &b)) < 0)
1027
0
    goto done;
1028
1029
877k
  b = cups->header.TraySwitch;
1030
877k
  if ((code = param_write_bool(plist, "TraySwitch", &b)) < 0)
1031
0
    goto done;
1032
1033
877k
  b = cups->header.Tumble;
1034
877k
  if ((code = param_write_bool(plist, "Tumble", &b)) < 0)
1035
0
    goto done;
1036
1037
#if 0 /* Don't include read-only parameters... */
1038
  if ((code = param_write_int(plist, "cupsWidth",
1039
                              (int *)&(cups->header.cupsWidth))) < 0)
1040
    goto done;
1041
1042
  if ((code = param_write_int(plist, "cupsHeight",
1043
                              (int *)&(cups->header.cupsHeight))) < 0)
1044
    goto done;
1045
1046
  if ((code = param_write_int(plist, "cupsBitsPerPixel",
1047
                              (int *)&(cups->header.cupsBitsPerPixel))) < 0)
1048
    goto done;
1049
1050
  if ((code = param_write_int(plist, "cupsBytesPerLine",
1051
                              (int *)&(cups->header.cupsBytesPerLine))) < 0)
1052
    goto done;
1053
#endif /* 0 */
1054
1055
877k
  if ((code = param_write_int(plist, "cupsMediaType",
1056
877k
                              (int *)&(cups->header.cupsMediaType))) < 0)
1057
0
    goto done;
1058
1059
877k
  if ((code = param_write_int(plist, "cupsBitsPerColor",
1060
877k
                              (int *)&(cups->header.cupsBitsPerColor))) < 0)
1061
0
    goto done;
1062
1063
877k
  if ((code = param_write_int(plist, "cupsColorOrder",
1064
877k
                              (int *)&(cups->header.cupsColorOrder))) < 0)
1065
0
    goto done;
1066
1067
877k
  if ((code = param_write_int(plist, "cupsColorSpace",
1068
877k
                              (int *)&(cups->header.cupsColorSpace))) < 0)
1069
0
    goto done;
1070
1071
877k
  if ((code = param_write_int(plist, "cupsCompression",
1072
877k
                              (int *)&(cups->header.cupsCompression))) < 0)
1073
0
    goto done;
1074
1075
877k
  if ((code = param_write_int(plist, "cupsRowCount",
1076
877k
                              (int *)&(cups->header.cupsRowCount))) < 0)
1077
0
    goto done;
1078
1079
877k
  if ((code = param_write_int(plist, "cupsRowFeed",
1080
877k
                              (int *)&(cups->header.cupsRowFeed))) < 0)
1081
0
    goto done;
1082
1083
877k
  if ((code = param_write_int(plist, "cupsRowStep",
1084
877k
                              (int *)&(cups->header.cupsRowStep))) < 0)
1085
0
    goto done;
1086
1087
877k
#ifdef CUPS_RASTER_SYNCv1
1088
#if 0 /* Don't include read-only parameters... */
1089
  if ((code = param_write_int(plist, "cupsNumColors",
1090
                              (int *)&(cups->header.cupsNumColors))) < 0)
1091
    goto done;
1092
#endif /* 0 */
1093
1094
877k
  if ((code = param_write_float(plist, "cupsBorderlessScalingFactor",
1095
877k
                          &(cups->header.cupsBorderlessScalingFactor))) < 0)
1096
0
    goto done;
1097
1098
14.9M
  for (i = 0; cups_Integer_strings[i] != NULL; i ++)
1099
14.0M
  {
1100
14.0M
    if ((code = param_write_int(plist, cups_Integer_strings[i],
1101
14.0M
                          (int *)(cups->header.cupsInteger + i))) < 0)
1102
0
      goto done;
1103
14.0M
  }
1104
1105
14.9M
  for (i = 0; cups_Real_strings[i] != NULL; i ++)
1106
14.0M
  {
1107
14.0M
    if ((code = param_write_float(plist, cups_Real_strings[i],
1108
14.0M
                            cups->header.cupsReal + i)) < 0)
1109
0
      goto done;
1110
14.0M
  }
1111
1112
14.9M
  for (i = 0; cups_String_strings[i] != NULL; i ++)
1113
14.0M
  {
1114
14.0M
    param_string_from_transient_string(s, cups->header.cupsString[i]);
1115
14.0M
    if ((code = param_write_string(plist, cups_String_strings[i], &s)) < 0)
1116
0
      goto done;
1117
14.0M
  }
1118
1119
877k
  param_string_from_transient_string(s, cups->header.cupsMarkerType);
1120
877k
  if ((code = param_write_string(plist, "cupsMarkerType", &s)) < 0)
1121
0
    goto done;
1122
1123
877k
  param_string_from_transient_string(s, cups->header.cupsRenderingIntent);
1124
877k
  if ((code = param_write_string(plist, "cupsRenderingIntent", &s)) < 0)
1125
0
    goto done;
1126
1127
877k
  param_string_from_transient_string(s, cups->header.cupsPageSizeName);
1128
877k
  if ((code = param_write_string(plist, "cupsPageSizeName", &s)) < 0)
1129
0
    goto done;
1130
877k
#endif /* CUPS_RASTER_SYNCv1 */
1131
1132
 /*
1133
  * Variables for PPD-less use only. If these settings are defined in the
1134
  * PPD file, the PPD file's definitions get priority.
1135
  */
1136
1137
877k
  if ((code = param_write_int(plist, "cupsRasterVersion",
1138
877k
            (int *)&(cups->cupsRasterVersion))) < 0)
1139
0
    goto done;
1140
1141
877k
  param_string_from_transient_string(s, cups->cupsBackSideOrientation);
1142
877k
  if ((code = param_write_string(plist, "cupsBackSideOrientation", &s)) < 0)
1143
0
    goto done;
1144
1145
877k
  b = cups->cupsBackSideFlipMargins;
1146
877k
  if ((code = param_write_bool(plist, "cupsBackSideFlipMargins", &b)) < 0)
1147
0
    goto done;
1148
1149
877k
  b = cups->cupsManualCopies;
1150
877k
  if ((code = param_write_bool(plist, "cupsManualCopies", &b)) < 0)
1151
0
    goto done;
1152
1153
877k
done:
1154
1155
#ifdef CUPS_DEBUG2
1156
  dmprintf(pdev->memory, "DEBUG2: Leaving cups_get_params()\n");
1157
#endif /* CUPS_DEBUG2 */
1158
1159
877k
  return code;
1160
877k
}
1161
1162
1163
/*
1164
 * 'cups_get_space_params()' - Get space parameters from the RIP_CACHE env var.
1165
 */
1166
1167
void
1168
cups_get_space_params(const gx_device_printer *pdev,
1169
          /* I - Printer device */
1170
                            gdev_space_params *space_params)
1171
          /* O - Space parameters */
1172
70.4k
{
1173
70.4k
  float cache_size;     /* Size of tile cache in bytes */
1174
70.4k
  char  *cache_env,     /* Cache size environment variable */
1175
70.4k
  cache_units[255];   /* Cache size units */
1176
1177
1178
#ifdef CUPS_DEBUG2
1179
  dmprintf2(pdev->memory, "DEBUG2: cups_get_space_params(%p, %p)\n", pdev, space_params);
1180
#endif /* CUPS_DEBUG2 */
1181
1182
70.4k
  if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL)
1183
0
  {
1184
0
    switch (sscanf(cache_env, "%f%254s", &cache_size, cache_units))
1185
0
    {
1186
0
      case 0 :
1187
0
          return;
1188
0
      case 1 :
1189
0
          cache_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
1190
0
    break;
1191
0
      case 2 :
1192
0
          if (tolower(cache_units[0]) == 'g')
1193
0
      cache_size *= 1024 * 1024 * 1024;
1194
0
          else if (tolower(cache_units[0]) == 'm')
1195
0
      cache_size *= 1024 * 1024;
1196
0
    else if (tolower(cache_units[0]) == 'k')
1197
0
      cache_size *= 1024;
1198
0
    else if (tolower(cache_units[0]) == 't')
1199
0
      cache_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
1200
0
    break;
1201
0
    }
1202
0
  }
1203
70.4k
  else
1204
70.4k
    return;
1205
1206
0
  if (cache_size == 0)
1207
0
    return;
1208
1209
#ifdef CUPS_DEBUG2
1210
  dmprintf1(pdev->memory, "DEBUG2: cache_size = %.0f\n", cache_size);
1211
#endif /* CUPS_DEBUG2 */
1212
1213
0
  space_params->MaxBitmap   = (long)cache_size;
1214
0
  space_params->BufferSpace = (long)cache_size;
1215
0
}
1216
1217
1218
/*
1219
 * 'cups_map_cielab()' - Map CIE Lab transformation...
1220
 */
1221
1222
static double       /* O - Adjusted color value */
1223
cups_map_cielab(double x,   /* I - Raw color value */
1224
                double xn)    /* I - Whitepoint color value */
1225
16.4M
{
1226
16.4M
  double x_xn;        /* Fraction of whitepoint */
1227
1228
1229
16.4M
  x_xn = x / xn;
1230
1231
16.4M
  if (x_xn > 0.008856)
1232
8.22M
    return (cbrt(x_xn));
1233
8.21M
  else
1234
8.21M
    return (7.787 * x_xn + 16.0 / 116.0);
1235
16.4M
}
1236
1237
1238
#ifdef dev_t_proc_encode_color
1239
/*
1240
 * 'cups_map_cmyk()' - Map a CMYK color value to device colors.
1241
 */
1242
1243
private void
1244
cups_map_cmyk(const gx_device *pdev,    /* I - Device info */
1245
              frac      c,    /* I - Cyan value */
1246
        frac      m,    /* I - Magenta value */
1247
        frac      y,    /* I - Yellow value */
1248
        frac      k,    /* I - Black value */
1249
        frac      *out)   /* O - Device colors */
1250
125M
{
1251
125M
  int c0 = 0, c1 = 0,
1252
125M
        c2 = 0, c3 = 0;     /* Temporary color values */
1253
125M
  float rr, rg, rb,     /* Real RGB colors */
1254
125M
  ciex, ciey, ciez,   /* CIE XYZ colors */
1255
125M
  ciey_yn,      /* Normalized luminance */
1256
125M
  ciel, ciea, cieb;   /* CIE Lab colors */
1257
1258
1259
#ifdef CUPS_DEBUG2
1260
  dmprintf6(pdev->memory, "DEBUG2: cups_map_cmyk(%p, %d, %d, %d, %d, %p)\n",
1261
            pdev, c, m, y, k, out);
1262
#endif /* CUPS_DEBUG2 */
1263
1264
 /*
1265
  * Convert the CMYK color to the destination colorspace...
1266
  */
1267
1268
125M
  switch (cups->header.cupsColorSpace)
1269
125M
  {
1270
222k
    case CUPS_CSPACE_W :
1271
225k
    case CUPS_CSPACE_SW :
1272
225k
        c0 = (c * 31 + m * 61 + y * 8) / 100 + k;
1273
1274
225k
  if (c0 < 0)
1275
0
    c0 = 0;
1276
225k
  else if (c0 > frac_1)
1277
0
    c0 = frac_1;
1278
225k
  out[0] = frac_1 - (frac)cups->Density[c0];
1279
225k
        break;
1280
1281
4.46k
    case CUPS_CSPACE_RGBA :
1282
4.46k
        out[3] = frac_1;
1283
1284
118M
    case CUPS_CSPACE_RGB :
1285
118M
    case CUPS_CSPACE_SRGB :
1286
120M
    case CUPS_CSPACE_ADOBERGB :
1287
120M
    case CUPS_CSPACE_RGBW :
1288
120M
        c0 = c + k;
1289
120M
        c1 = m + k;
1290
120M
        c2 = y + k;
1291
120M
        if (cups->header.cupsColorSpace == CUPS_CSPACE_RGBW) {
1292
8.42k
    if ((k >= frac_1 - 1) ||
1293
5.51k
        ((c0 >= frac_1) && (c1 >= frac_1) && (c2 >= frac_1))) {
1294
5.51k
      c0 = frac_1;
1295
5.51k
      c1 = frac_1;
1296
5.51k
      c2 = frac_1;
1297
5.51k
      c3 = frac_1;
1298
5.51k
    } else
1299
2.91k
      c3 = 0;
1300
8.42k
  }
1301
1302
120M
        if (c0 < 0)
1303
0
    c0 = 0;
1304
120M
  else if (c0 > frac_1)
1305
0
    c0 = frac_1;
1306
120M
  out[0] = frac_1 - (frac)cups->Density[c0];
1307
1308
120M
        if (c1 < 0)
1309
0
    c1 = 0;
1310
120M
  else if (c1 > frac_1)
1311
0
    c1 = frac_1;
1312
120M
  out[1] = frac_1 - (frac)cups->Density[c1];
1313
1314
120M
        if (c2 < 0)
1315
0
    c2 = 0;
1316
120M
  else if (c2 > frac_1)
1317
0
    c2 = frac_1;
1318
120M
  out[2] = frac_1 - (frac)cups->Density[c2];
1319
1320
120M
        if (cups->header.cupsColorSpace == CUPS_CSPACE_RGBW) {
1321
8.42k
    if (c3 == 0)
1322
2.91k
      out[3] = frac_1;
1323
5.51k
    else if (c3 == frac_1)
1324
5.51k
      out[3] = 0;
1325
8.42k
  }
1326
120M
        break;
1327
1328
39.1k
    default :
1329
44.0k
    case CUPS_CSPACE_K :
1330
44.0k
        c0 = (c * 31 + m * 61 + y * 8) / 100 + k;
1331
1332
44.0k
  if (c0 < 0)
1333
0
    out[0] = 0;
1334
44.0k
  else if (c0 > frac_1)
1335
0
    out[0] = (frac)cups->Density[frac_1];
1336
44.0k
  else
1337
44.0k
    out[0] = (frac)cups->Density[c0];
1338
44.0k
        break;
1339
1340
66.3k
    case CUPS_CSPACE_CMY :
1341
66.3k
        c0 = c + k;
1342
66.3k
  c1 = m + k;
1343
66.3k
  c2 = y + k;
1344
1345
66.3k
        if (c0 < 0)
1346
0
    out[0] = 0;
1347
66.3k
  else if (c0 > frac_1)
1348
0
    out[0] = (frac)cups->Density[frac_1];
1349
66.3k
  else
1350
66.3k
    out[0] = (frac)cups->Density[c0];
1351
1352
66.3k
        if (c1 < 0)
1353
0
    out[1] = 0;
1354
66.3k
  else if (c1 > frac_1)
1355
0
    out[1] = (frac)cups->Density[frac_1];
1356
66.3k
  else
1357
66.3k
    out[1] = (frac)cups->Density[c1];
1358
1359
66.3k
        if (c2 < 0)
1360
0
    out[2] = 0;
1361
66.3k
  else if (c2 > frac_1)
1362
0
    out[2] = (frac)cups->Density[frac_1];
1363
66.3k
  else
1364
66.3k
    out[2] = (frac)cups->Density[c2];
1365
66.3k
        break;
1366
1367
3.03k
    case CUPS_CSPACE_YMC :
1368
3.03k
        c0 = y + k;
1369
3.03k
  c1 = m + k;
1370
3.03k
  c2 = c + k;
1371
1372
3.03k
        if (c0 < 0)
1373
0
    out[0] = 0;
1374
3.03k
  else if (c0 > frac_1)
1375
0
    out[0] = (frac)cups->Density[frac_1];
1376
3.03k
  else
1377
3.03k
    out[0] = (frac)cups->Density[c0];
1378
1379
3.03k
        if (c1 < 0)
1380
0
    out[1] = 0;
1381
3.03k
  else if (c1 > frac_1)
1382
0
    out[1] = (frac)cups->Density[frac_1];
1383
3.03k
  else
1384
3.03k
    out[1] = (frac)cups->Density[c1];
1385
1386
3.03k
        if (c2 < 0)
1387
0
    out[2] = 0;
1388
3.03k
  else if (c2 > frac_1)
1389
0
    out[2] = (frac)cups->Density[frac_1];
1390
3.03k
  else
1391
3.03k
    out[2] = (frac)cups->Density[c2];
1392
3.03k
        break;
1393
1394
275k
    case CUPS_CSPACE_CMYK :
1395
275k
        if (c < 0)
1396
0
    out[0] = 0;
1397
275k
  else if (c > frac_1)
1398
0
    out[0] = (frac)cups->Density[frac_1];
1399
275k
  else
1400
275k
    out[0] = (frac)cups->Density[c];
1401
1402
275k
        if (m < 0)
1403
0
    out[1] = 0;
1404
275k
  else if (m > frac_1)
1405
0
    out[1] = (frac)cups->Density[frac_1];
1406
275k
  else
1407
275k
    out[1] = (frac)cups->Density[m];
1408
1409
275k
        if (y < 0)
1410
0
    out[2] = 0;
1411
275k
  else if (y > frac_1)
1412
0
    out[2] = (frac)cups->Density[frac_1];
1413
275k
  else
1414
275k
    out[2] = (frac)cups->Density[y];
1415
1416
275k
        if (k < 0)
1417
0
    out[3] = 0;
1418
275k
  else if (k > frac_1)
1419
0
    out[3] = (frac)cups->Density[frac_1];
1420
275k
  else
1421
275k
    out[3] = (frac)cups->Density[k];
1422
275k
        break;
1423
1424
5.15k
    case CUPS_CSPACE_YMCK :
1425
123k
    case CUPS_CSPACE_GMCK :
1426
137k
    case CUPS_CSPACE_GMCS :
1427
137k
        if (y < 0)
1428
0
    out[0] = 0;
1429
137k
  else if (y > frac_1)
1430
0
    out[0] = (frac)cups->Density[frac_1];
1431
137k
  else
1432
137k
    out[0] = (frac)cups->Density[y];
1433
1434
137k
        if (m < 0)
1435
0
    out[1] = 0;
1436
137k
  else if (m > frac_1)
1437
0
    out[1] = (frac)cups->Density[frac_1];
1438
137k
  else
1439
137k
    out[1] = (frac)cups->Density[m];
1440
1441
137k
        if (c < 0)
1442
0
    out[2] = 0;
1443
137k
  else if (c > frac_1)
1444
0
    out[2] = (frac)cups->Density[frac_1];
1445
137k
  else
1446
137k
    out[2] = (frac)cups->Density[c];
1447
1448
137k
        if (k < 0)
1449
0
    out[3] = 0;
1450
137k
  else if (k > frac_1)
1451
0
    out[3] = (frac)cups->Density[frac_1];
1452
137k
  else
1453
137k
    out[3] = (frac)cups->Density[k];
1454
137k
        break;
1455
1456
22.0k
    case CUPS_CSPACE_KCMYcm :
1457
31.2k
    case CUPS_CSPACE_KCMY :
1458
31.2k
        if (k < 0)
1459
0
    out[0] = 0;
1460
31.2k
  else if (k > frac_1)
1461
0
    out[0] = (frac)cups->Density[frac_1];
1462
31.2k
  else
1463
31.2k
    out[0] = (frac)cups->Density[k];
1464
1465
31.2k
        if (c < 0)
1466
0
    out[1] = 0;
1467
31.2k
  else if (c > frac_1)
1468
0
    out[1] = (frac)cups->Density[frac_1];
1469
31.2k
  else
1470
31.2k
    out[1] = (frac)cups->Density[c];
1471
1472
31.2k
        if (m < 0)
1473
0
    out[2] = 0;
1474
31.2k
  else if (m > frac_1)
1475
0
    out[2] = (frac)cups->Density[frac_1];
1476
31.2k
  else
1477
31.2k
    out[2] = (frac)cups->Density[m];
1478
1479
31.2k
        if (y < 0)
1480
0
    out[3] = 0;
1481
31.2k
  else if (y > frac_1)
1482
0
    out[3] = (frac)cups->Density[frac_1];
1483
31.2k
  else
1484
31.2k
    out[3] = (frac)cups->Density[y];
1485
31.2k
        break;
1486
1487
0
#  ifdef CUPS_RASTER_HAVE_COLORIMETRIC
1488
0
    case CUPS_CSPACE_CIEXYZ :
1489
1.83k
    case CUPS_CSPACE_CIELab :
1490
3.15M
    case CUPS_CSPACE_ICC1 :
1491
3.15M
    case CUPS_CSPACE_ICC2 :
1492
3.16M
    case CUPS_CSPACE_ICC3 :
1493
3.16M
    case CUPS_CSPACE_ICC4 :
1494
3.19M
    case CUPS_CSPACE_ICC5 :
1495
4.06M
    case CUPS_CSPACE_ICC6 :
1496
4.06M
    case CUPS_CSPACE_ICC7 :
1497
4.06M
    case CUPS_CSPACE_ICC8 :
1498
4.07M
    case CUPS_CSPACE_ICC9 :
1499
4.07M
    case CUPS_CSPACE_ICCA :
1500
4.08M
    case CUPS_CSPACE_ICCB :
1501
4.08M
    case CUPS_CSPACE_ICCC :
1502
4.08M
    case CUPS_CSPACE_ICCD :
1503
4.08M
    case CUPS_CSPACE_ICCE :
1504
4.11M
    case CUPS_CSPACE_ICCF :
1505
       /*
1506
        * Convert CMYK to sRGB...
1507
  */
1508
1509
4.11M
        c0 = frac_1 - c - k;
1510
4.11M
  c1 = frac_1 - m - k;
1511
4.11M
  c2 = frac_1 - y - k;
1512
1513
4.11M
        if (c0 < 0)
1514
0
    c0 = 0;
1515
1516
4.11M
        if (c1 < 0)
1517
0
    c1 = 0;
1518
1519
4.11M
        if (c2 < 0)
1520
0
    c2 = 0;
1521
1522
       /*
1523
        * Convert sRGB to linear RGB...
1524
  */
1525
1526
4.11M
  rr = pow(((double)c0 / (double)frac_1 + 0.055) / 1.055, 2.4);
1527
4.11M
  rg = pow(((double)c1 / (double)frac_1 + 0.055) / 1.055, 2.4);
1528
4.11M
  rb = pow(((double)c2 / (double)frac_1 + 0.055) / 1.055, 2.4);
1529
1530
       /*
1531
        * Convert to CIE XYZ...
1532
  */
1533
1534
4.11M
  ciex = 0.412453 * rr + 0.357580 * rg + 0.180423 * rb;
1535
4.11M
  ciey = 0.212671 * rr + 0.715160 * rg + 0.072169 * rb;
1536
4.11M
  ciez = 0.019334 * rr + 0.119193 * rg + 0.950227 * rb;
1537
1538
4.11M
        if (cups->header.cupsColorSpace == CUPS_CSPACE_CIEXYZ)
1539
0
  {
1540
   /*
1541
    * Convert to an integer XYZ color value...
1542
    */
1543
1544
0
          if (cups->header.cupsBitsPerColor == 8)
1545
0
    {
1546
0
      if (ciex <= 0.0f)
1547
0
        c0 = 0;
1548
0
      else if (ciex < 1.1)
1549
0
        c0 = (int)(ciex * 231.8181 + 0.5);
1550
0
      else
1551
0
        c0 = 255;
1552
1553
0
      if (ciey <= 0.0f)
1554
0
        c1 = 0;
1555
0
      else if (ciey < 1.1)
1556
0
        c1 = (int)(ciey * 231.8181 + 0.5);
1557
0
      else
1558
0
        c1 = 255;
1559
1560
0
      if (ciez <= 0.0f)
1561
0
        c2 = 0;
1562
0
      else if (ciez < 1.1)
1563
0
        c2 = (int)(ciez * 231.8181 + 0.5);
1564
0
      else
1565
0
        c2 = 255;
1566
0
    }
1567
0
    else
1568
0
    {
1569
0
      if (ciex <= 0.0f)
1570
0
        c0 = 0;
1571
0
      else if (ciex < 1.1)
1572
0
        c0 = (int)(ciex * 59577.2727 + 0.5);
1573
0
      else
1574
0
        c0 = 65535;
1575
1576
0
      if (ciey <= 0.0f)
1577
0
        c1 = 0;
1578
0
      else if (ciey < 1.1)
1579
0
        c1 = (int)(ciey * 59577.2727 + 0.5);
1580
0
      else
1581
0
        c1 = 65535;
1582
1583
0
      if (ciez <= 0.0f)
1584
0
        c2 = 0;
1585
0
      else if (ciez < 1.1)
1586
0
        c2 = (int)(ciez * 59577.2727 + 0.5);
1587
0
      else
1588
0
        c2 = 65535;
1589
0
    }
1590
0
  }
1591
4.11M
  else
1592
4.11M
  {
1593
   /*
1594
    * Convert CIE XYZ to Lab...
1595
    */
1596
1597
4.11M
    ciey_yn = ciey / D65_Y;
1598
1599
4.11M
    if (ciey_yn > 0.008856)
1600
2.05M
      ciel = 116 * cbrt(ciey_yn) - 16;
1601
2.05M
    else
1602
2.05M
      ciel = 903.3 * ciey_yn;
1603
1604
4.11M
    ciea = 500 * (cups_map_cielab(ciex, D65_X) -
1605
4.11M
                  cups_map_cielab(ciey, D65_Y));
1606
4.11M
    cieb = 200 * (cups_map_cielab(ciey, D65_Y) -
1607
4.11M
                  cups_map_cielab(ciez, D65_Z));
1608
1609
4.11M
          if (cups->header.cupsBitsPerColor == 8)
1610
4.11M
    {
1611
           /*
1612
      * Scale the L value and bias the a and b values by 128
1613
      * so that all values are in the range of 0 to 255.
1614
      */
1615
1616
4.11M
      ciel = ciel * 2.55 + 0.5;
1617
4.11M
      ciea += 128.5;
1618
4.11M
      cieb += 128.5;
1619
1620
4.11M
      if (ciel <= 0.0)
1621
0
        c0 = 0;
1622
4.11M
      else if (ciel < 255.0)
1623
2.13M
        c0 = (int)ciel;
1624
1.97M
      else
1625
1.97M
        c0 = 255;
1626
1627
4.11M
      if (ciea <= 0.0)
1628
0
        c1 = 0;
1629
4.11M
      else if (ciea < 255.0)
1630
4.11M
        c1 = (int)ciea;
1631
0
      else
1632
0
        c1 = 255;
1633
1634
4.11M
      if (cieb <= 0.0)
1635
0
        c2 = 0;
1636
4.11M
      else if (cieb < 255.0)
1637
4.11M
        c2 = (int)cieb;
1638
0
      else
1639
0
        c2 = 255;
1640
4.11M
          }
1641
0
    else
1642
0
    {
1643
     /*
1644
      * Scale the L value and bias the a and b values by 128 so that all
1645
      * numbers are from 0 to 65535.
1646
      */
1647
1648
0
      ciel = ciel * 655.35 + 0.5;
1649
0
      ciea = (ciea + 128.0) * 256.0 + 0.5;
1650
0
      cieb = (cieb + 128.0) * 256.0 + 0.5;
1651
1652
     /*
1653
      * Output 16-bit values...
1654
      */
1655
1656
0
      if (ciel <= 0.0)
1657
0
        c0 = 0;
1658
0
      else if (ciel < 65535.0)
1659
0
        c0 = (int)ciel;
1660
0
      else
1661
0
        c0 = 65535;
1662
1663
0
      if (ciea <= 0.0)
1664
0
        c1 = 0;
1665
0
      else if (ciea < 65535.0)
1666
0
        c1 = (int)ciea;
1667
0
      else
1668
0
        c1 = 65535;
1669
1670
0
      if (cieb <= 0.0)
1671
0
        c2 = 0;
1672
0
      else if (cieb < 65535.0)
1673
0
        c2 = (int)cieb;
1674
0
      else
1675
0
        c2 = 65535;
1676
0
    }
1677
4.11M
  }
1678
1679
4.11M
        out[0] = cups->DecodeLUT[c0];
1680
4.11M
        out[1] = cups->DecodeLUT[c1];
1681
4.11M
        out[2] = cups->DecodeLUT[c2];
1682
4.11M
        break;
1683
125M
#  endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
1684
125M
  }
1685
1686
#ifdef CUPS_DEBUG2
1687
  switch (cups->color_info.num_components)
1688
  {
1689
    default :
1690
    case 1 :
1691
        dmprintf1(pdev->memory, "DEBUG2:   \\=== COLOR %d\n", out[0]);
1692
  break;
1693
1694
    case 3 :
1695
        dmprintf3(pdev->memory, "DEBUG2:   \\=== COLOR %d, %d, %d\n",
1696
                  out[0], out[1], out[2]);
1697
  break;
1698
1699
    case 4 :
1700
        dmprintf4(pdev->memory, "DEBUG2:   \\=== COLOR %d, %d, %d, %d\n",
1701
                  out[0], out[1], out[2], out[3]);
1702
  break;
1703
  }
1704
#endif /* CUPS_DEBUG2 */
1705
125M
}
1706
1707
1708
/*
1709
 * 'cups_map_gray()' - Map a grayscale value to device colors.
1710
 */
1711
1712
private void
1713
cups_map_gray(const gx_device *pdev,    /* I - Device info */
1714
              frac      g,    /* I - Grayscale value */
1715
        frac      *out)   /* O - Device colors */
1716
295k
{
1717
#ifdef CUPS_DEBUG22
1718
  dmprintf3(pdev->memory, "DEBUG2: cups_map_gray(%p, %d, %p)\n",
1719
            pdev, g, out);
1720
#endif /* CUPS_DEBUG22 */
1721
1722
 /*
1723
  * Just use the CMYK mapper...
1724
  */
1725
1726
295k
  cups_map_cmyk(pdev, 0, 0, 0, frac_1 - g, out);
1727
295k
}
1728
1729
1730
/*
1731
 * 'cups_map_rgb()' - Map a RGB color value to device colors.
1732
 */
1733
1734
private void
1735
cups_map_rgb(const gx_device             *pdev,
1736
          /* I - Device info */
1737
             const gs_gstate        *pgs,/* I - Device state */
1738
             frac                  r, /* I - Red value */
1739
       frac                  g, /* I - Green value */
1740
       frac                  b, /* I - Blue value */
1741
       frac                  *out)/* O - Device colors */
1742
124M
{
1743
124M
  frac    c, m, y, k;   /* CMYK values */
1744
124M
  frac    mk;     /* Maximum K value */
1745
124M
  int   tc, tm, ty;   /* Temporary color values */
1746
1747
1748
#ifdef CUPS_DEBUG2
1749
  dmprintf6(pdev->memory, "DEBUG2: cups_map_rgb(%p, %p, %d, %d, %d, %p)\n",
1750
            pdev, pgs, r, g, b, out);
1751
#endif /* CUPS_DEBUG2 */
1752
1753
 /*
1754
  * Compute CMYK values...
1755
  */
1756
1757
124M
  c = frac_1 - r;
1758
124M
  m = frac_1 - g;
1759
124M
  y = frac_1 - b;
1760
124M
  k = min(c, min(m, y));
1761
1762
124M
  if ((mk = max(c, max(m, y))) > k)
1763
62.8M
    k = (int)((float)k * (float)k * (float)k / ((float)mk * (float)mk));
1764
1765
124M
  c -= k;
1766
124M
  m -= k;
1767
124M
  y -= k;
1768
1769
 /*
1770
  * Do color correction as needed...
1771
  */
1772
1773
124M
  if (cups->HaveProfile)
1774
0
  {
1775
   /*
1776
    * Color correct CMY...
1777
    */
1778
1779
0
    tc = cups->Matrix[0][0][c] +
1780
0
         cups->Matrix[0][1][m] +
1781
0
   cups->Matrix[0][2][y];
1782
0
    tm = cups->Matrix[1][0][c] +
1783
0
         cups->Matrix[1][1][m] +
1784
0
   cups->Matrix[1][2][y];
1785
0
    ty = cups->Matrix[2][0][c] +
1786
0
         cups->Matrix[2][1][m] +
1787
0
   cups->Matrix[2][2][y];
1788
1789
0
    if (tc < 0)
1790
0
      c = 0;
1791
0
    else if (tc > frac_1)
1792
0
      c = frac_1;
1793
0
    else
1794
0
      c = (frac)tc;
1795
1796
0
    if (tm < 0)
1797
0
      m = 0;
1798
0
    else if (tm > frac_1)
1799
0
      m = frac_1;
1800
0
    else
1801
0
      m = (frac)tm;
1802
1803
0
    if (ty < 0)
1804
0
      y = 0;
1805
0
    else if (ty > frac_1)
1806
0
      y = frac_1;
1807
0
    else
1808
0
      y = (frac)ty;
1809
0
  }
1810
1811
 /*
1812
  * Use the CMYK mapping function to produce the device colors...
1813
  */
1814
1815
124M
  cups_map_cmyk(pdev, c, m, y, k, out);
1816
124M
}
1817
#else
1818
/*
1819
 * 'cups_map_cmyk_color()' - Map a CMYK color to a color index.
1820
 *
1821
 * This function is only called when a 4 or 6 color colorspace is
1822
 * selected for output.  CMYK colors are *not* corrected but *are*
1823
 * density adjusted.
1824
 */
1825
1826
private gx_color_index      /* O - Color index */
1827
cups_map_cmyk_color(gx_device      *pdev,
1828
          /* I - Device info */
1829
                    const gx_color_value cv[4])/* I - CMYK color values */
1830
{
1831
  gx_color_index  i;    /* Temporary index */
1832
  gx_color_value  c, m, y, k;
1833
  gx_color_value  ic, im, iy, ik; /* Integral CMYK values */
1834
1835
  c = cv[0];
1836
  m = cv[1];
1837
  y = cv[2];
1838
  k = cv[3];
1839
1840
#ifdef CUPS_DEBUG2
1841
  dmprintf5(pdev->memory, "DEBUG2: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n",
1842
            pdev, c, m, y, k);
1843
#endif /* CUPS_DEBUG2 */
1844
1845
 /*
1846
  * Setup the color info data as needed...
1847
  */
1848
1849
  if (pdev->color_info.num_components == 0) {
1850
    if (cups_set_color_info(pdev) < 0)
1851
      return(gx_no_color_index);
1852
  }
1853
1854
 /*
1855
  * Density correct...
1856
  */
1857
1858
  if (cups->HaveProfile)
1859
  {
1860
    c = cups->Density[c];
1861
    m = cups->Density[m];
1862
    y = cups->Density[y];
1863
    k = cups->Density[k];
1864
  }
1865
1866
  ic = cups->EncodeLUT[c];
1867
  im = cups->EncodeLUT[m];
1868
  iy = cups->EncodeLUT[y];
1869
  ik = cups->EncodeLUT[k];
1870
1871
 /*
1872
  * Convert the CMYK color to a color index...
1873
  */
1874
1875
  switch (cups->header.cupsColorSpace)
1876
  {
1877
    default :
1878
        switch (cups->header.cupsBitsPerColor)
1879
        {
1880
          default :
1881
              i = (((((ic << 1) | im) << 1) | iy) << 1) | ik;
1882
              break;
1883
          case 2 :
1884
              i = (((((ic << 2) | im) << 2) | iy) << 2) | ik;
1885
              break;
1886
          case 4 :
1887
              i = (((((ic << 4) | im) << 4) | iy) << 4) | ik;
1888
              break;
1889
          case 8 :
1890
              i = (((((ic << 8) | im) << 8) | iy) << 8) | ik;
1891
              break;
1892
#ifdef GX_COLOR_INDEX_TYPE
1893
    case 16 :
1894
        i = (((((ic << 16) | im) << 16) | iy) << 16) | ik;
1895
        break;
1896
#endif /* GX_COLOR_INDEX_TYPE */
1897
        }
1898
        break;
1899
1900
    case CUPS_CSPACE_YMCK :
1901
    case CUPS_CSPACE_GMCK :
1902
    case CUPS_CSPACE_GMCS :
1903
        switch (cups->header.cupsBitsPerColor)
1904
        {
1905
          default :
1906
              i = (((((iy << 1) | im) << 1) | ic) << 1) | ik;
1907
              break;
1908
          case 2 :
1909
              i = (((((iy << 2) | im) << 2) | ic) << 2) | ik;
1910
              break;
1911
          case 4 :
1912
              i = (((((iy << 4) | im) << 4) | ic) << 4) | ik;
1913
              break;
1914
          case 8 :
1915
              i = (((((iy << 8) | im) << 8) | ic) << 8) | ik;
1916
              break;
1917
#ifdef GX_COLOR_INDEX_TYPE
1918
    case 16 :
1919
        i = (((((iy << 16) | im) << 16) | ic) << 16) | ik;
1920
        break;
1921
#endif /* GX_COLOR_INDEX_TYPE */
1922
        }
1923
        break;
1924
1925
    case CUPS_CSPACE_KCMYcm :
1926
        if (cups->header.cupsBitsPerColor == 1)
1927
  {
1928
    if (ik)
1929
      i = 32;
1930
    else
1931
      i = 0;
1932
1933
    if (ic && im)
1934
      i |= 17;
1935
    else if (ic && iy)
1936
      i |= 6;
1937
    else if (im && iy)
1938
      i |= 12;
1939
    else if (ic)
1940
      i |= 16;
1941
    else if (im)
1942
      i |= 8;
1943
    else if (iy)
1944
      i |= 4;
1945
    break;
1946
  }
1947
1948
    case CUPS_CSPACE_KCMY :
1949
        switch (cups->header.cupsBitsPerColor)
1950
        {
1951
          default :
1952
              i = (((((ik << 1) | ic) << 1) | im) << 1) | iy;
1953
              break;
1954
          case 2 :
1955
              i = (((((ik << 2) | ic) << 2) | im) << 2) | iy;
1956
              break;
1957
          case 4 :
1958
              i = (((((ik << 4) | ic) << 4) | im) << 4) | iy;
1959
              break;
1960
          case 8 :
1961
              i = (((((ik << 8) | ic) << 8) | im) << 8) | iy;
1962
              break;
1963
#ifdef GX_COLOR_INDEX_TYPE
1964
    case 16 :
1965
        i = (((((ik << 16) | ic) << 16) | im) << 16) | iy;
1966
        break;
1967
#endif /* GX_COLOR_INDEX_TYPE */
1968
        }
1969
        break;
1970
  }
1971
1972
#ifdef CUPS_DEBUG2
1973
  dmprintf9(pdev->memory, "DEBUG2: CMYK (%d,%d,%d,%d) -> CMYK %08x (%d,%d,%d,%d)\n",
1974
            c, m, y, k, (unsigned)i, ic, im, iy, ik);
1975
#endif /* CUPS_DEBUG2 */
1976
1977
 /*
1978
  * Make sure we don't get a CMYK color of 255, 255, 255, 255...
1979
  */
1980
1981
  if (i == gx_no_color_index)
1982
    i --;
1983
1984
  return (i);
1985
}
1986
1987
1988
/*
1989
 * 'cups_map_color_rgb()' - Map a color index to an RGB color.
1990
 */
1991
1992
private int
1993
cups_map_color_rgb(gx_device      *pdev,/* I - Device info */
1994
                   gx_color_index color,/* I - Color index */
1995
       gx_color_value prgb[3])
1996
          /* O - RGB values */
1997
{
1998
  unsigned char   c0, c1, c2, c3; /* Color index components */
1999
  gx_color_value  c, m, y, k, divk; /* Colors, Black & divisor */
2000
2001
2002
#ifdef CUPS_DEBUG2
2003
  dmprintf3(pdev->memory, "DEBUG2: cups_map_color_rgb(%p, %d, %p)\n", pdev,
2004
            (unsigned)color, prgb);
2005
#endif /* CUPS_DEBUG2 */
2006
2007
 /*
2008
  * Setup the color info data as needed...
2009
  */
2010
2011
  if (pdev->color_info.num_components == 0) {
2012
    if (cups_set_color_info(pdev) < 0)
2013
      return(gx_no_color_index);
2014
  }
2015
2016
#ifdef CUPS_DEBUG2
2017
  dmprintf1(pdev->memory, "DEBUG2: COLOR %08x = ", (unsigned)color);
2018
#endif /* CUPS_DEBUG2 */
2019
2020
 /*
2021
  * Extract the color components from the color index...
2022
  */
2023
2024
  switch (cups->header.cupsBitsPerColor)
2025
  {
2026
    default :
2027
        c3 = color & 1;
2028
        color >>= 1;
2029
        c2 = color & 1;
2030
        color >>= 1;
2031
        c1 = color & 1;
2032
        color >>= 1;
2033
        c0 = color;
2034
        break;
2035
    case 2 :
2036
        c3 = color & 3;
2037
        color >>= 2;
2038
        c2 = color & 3;
2039
        color >>= 2;
2040
        c1 = color & 3;
2041
        color >>= 2;
2042
        c0 = color;
2043
        break;
2044
    case 4 :
2045
        c3 = color & 15;
2046
        color >>= 4;
2047
        c2 = color & 15;
2048
        color >>= 4;
2049
        c1 = color & 15;
2050
        color >>= 4;
2051
        c0 = color;
2052
        break;
2053
    case 8 :
2054
        c3 = color & 255;
2055
        color >>= 8;
2056
        c2 = color & 255;
2057
        color >>= 8;
2058
        c1 = color & 255;
2059
        color >>= 8;
2060
        c0 = color;
2061
        break;
2062
#ifdef GX_COLOR_INDEX_TYPE
2063
    case 16 :
2064
        c3 = color & 0xffff;
2065
        color >>= 16;
2066
        c2 = color & 0xffff;
2067
        color >>= 16;
2068
        c1 = color & 0xffff;
2069
        color >>= 16;
2070
        c0 = color;
2071
        break;
2072
#endif /* GX_COLOR_INDEX_TYPE */
2073
  }
2074
2075
 /*
2076
  * Convert the color components to RGB...
2077
  */
2078
2079
  switch (cups->header.cupsColorSpace)
2080
  {
2081
    case CUPS_CSPACE_K :
2082
    case CUPS_CSPACE_WHITE :
2083
    case CUPS_CSPACE_GOLD :
2084
    case CUPS_CSPACE_SILVER :
2085
        prgb[0] =
2086
        prgb[1] =
2087
        prgb[2] = cups->DecodeLUT[c3];
2088
        break;
2089
2090
    case CUPS_CSPACE_W :
2091
    case CUPS_CSPACE_SW :
2092
        prgb[0] =
2093
        prgb[1] =
2094
        prgb[2] = cups->DecodeLUT[c3];
2095
        break;
2096
2097
    case CUPS_CSPACE_RGB :
2098
    case CUPS_CSPACE_SRGB :
2099
    case CUPS_CSPACE_ADOBERGB :
2100
        prgb[0] = cups->DecodeLUT[c1];
2101
        prgb[1] = cups->DecodeLUT[c2];
2102
        prgb[2] = cups->DecodeLUT[c3];
2103
        break;
2104
2105
    case CUPS_CSPACE_RGBA :
2106
        prgb[0] = cups->DecodeLUT[c0];
2107
        prgb[1] = cups->DecodeLUT[c1];
2108
        prgb[2] = cups->DecodeLUT[c2];
2109
        break;
2110
2111
    case CUPS_CSPACE_CMY :
2112
        prgb[0] = cups->DecodeLUT[c1];
2113
        prgb[1] = cups->DecodeLUT[c2];
2114
        prgb[2] = cups->DecodeLUT[c3];
2115
        break;
2116
2117
    case CUPS_CSPACE_YMC :
2118
        prgb[0] = cups->DecodeLUT[c3];
2119
        prgb[1] = cups->DecodeLUT[c2];
2120
        prgb[2] = cups->DecodeLUT[c1];
2121
        break;
2122
2123
    case CUPS_CSPACE_KCMY :
2124
    case CUPS_CSPACE_KCMYcm :
2125
        k    = cups->DecodeLUT[c0];
2126
        divk = gx_max_color_value - k;
2127
        if (divk == 0)
2128
        {
2129
          prgb[0] = 0;
2130
          prgb[1] = 0;
2131
          prgb[2] = 0;
2132
        }
2133
        else
2134
        {
2135
          prgb[0] = gx_max_color_value + divk -
2136
                    gx_max_color_value * c1 / divk;
2137
          prgb[1] = gx_max_color_value + divk -
2138
                    gx_max_color_value * c2 / divk;
2139
          prgb[2] = gx_max_color_value + divk -
2140
                    gx_max_color_value * c3 / divk;
2141
        }
2142
        break;
2143
2144
    case CUPS_CSPACE_RGBW :
2145
       /*
2146
        * cups->DecodeLUT actually maps to RGBW, not CMYK...
2147
  */
2148
2149
        if (c3 == 0) {
2150
    c = 0;
2151
    m = 0;
2152
    y = 0;
2153
  } else {
2154
    c = cups->DecodeLUT[c0];
2155
    m = cups->DecodeLUT[c1];
2156
    y = cups->DecodeLUT[c2];
2157
  }
2158
2159
        if (c > gx_max_color_value)
2160
    prgb[0] = gx_max_color_value;
2161
  else if (c < 0)
2162
          prgb[0] = 0;
2163
        else
2164
    prgb[0] = c;
2165
2166
        if (m > gx_max_color_value)
2167
    prgb[1] = gx_max_color_value;
2168
        else if (m < 0)
2169
          prgb[1] = 0;
2170
  else
2171
    prgb[1] = m;
2172
2173
        if (y > gx_max_color_value)
2174
    prgb[2] = gx_max_color_value;
2175
  else if (y < 0)
2176
          prgb[2] = 0;
2177
        else
2178
    prgb[2] = y;
2179
        break;
2180
2181
    case CUPS_CSPACE_CMYK :
2182
        k    = cups->DecodeLUT[c3];
2183
        divk = gx_max_color_value - k;
2184
        if (divk == 0)
2185
        {
2186
          prgb[0] = 0;
2187
          prgb[1] = 0;
2188
          prgb[2] = 0;
2189
        }
2190
        else
2191
        {
2192
          prgb[0] = gx_max_color_value + divk -
2193
                    gx_max_color_value * c0 / divk;
2194
          prgb[1] = gx_max_color_value + divk -
2195
                    gx_max_color_value * c1 / divk;
2196
          prgb[2] = gx_max_color_value + divk -
2197
                    gx_max_color_value * c2 / divk;
2198
        }
2199
        break;
2200
2201
    case CUPS_CSPACE_YMCK :
2202
    case CUPS_CSPACE_GMCK :
2203
    case CUPS_CSPACE_GMCS :
2204
        k    = cups->DecodeLUT[c3];
2205
        divk = gx_max_color_value - k;
2206
        if (divk == 0)
2207
        {
2208
          prgb[0] = 0;
2209
          prgb[1] = 0;
2210
          prgb[2] = 0;
2211
        }
2212
        else
2213
        {
2214
          prgb[0] = gx_max_color_value + divk -
2215
                    gx_max_color_value * c2 / divk;
2216
          prgb[1] = gx_max_color_value + divk -
2217
                    gx_max_color_value * c1 / divk;
2218
          prgb[2] = gx_max_color_value + divk -
2219
                    gx_max_color_value * c0 / divk;
2220
        }
2221
        break;
2222
2223
#  ifdef CUPS_RASTER_HAVE_COLORIMETRIC
2224
    case CUPS_CSPACE_CIEXYZ :
2225
    case CUPS_CSPACE_CIELab :
2226
    case CUPS_CSPACE_ICC1 :
2227
    case CUPS_CSPACE_ICC2 :
2228
    case CUPS_CSPACE_ICC3 :
2229
    case CUPS_CSPACE_ICC4 :
2230
    case CUPS_CSPACE_ICC5 :
2231
    case CUPS_CSPACE_ICC6 :
2232
    case CUPS_CSPACE_ICC7 :
2233
    case CUPS_CSPACE_ICC8 :
2234
    case CUPS_CSPACE_ICC9 :
2235
    case CUPS_CSPACE_ICCA :
2236
    case CUPS_CSPACE_ICCB :
2237
    case CUPS_CSPACE_ICCC :
2238
    case CUPS_CSPACE_ICCD :
2239
    case CUPS_CSPACE_ICCE :
2240
    case CUPS_CSPACE_ICCF :
2241
        break;
2242
#  endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
2243
  }
2244
2245
#ifdef CUPS_DEBUG2
2246
  dmprintf3(pdev->memory, "DEBUG2: RGB values: %d,%d,%d\n",
2247
            prgb[0], prgb[1], prgb[2]);
2248
#endif /* CUPS_DEBUG2 */
2249
2250
  return (0);
2251
}
2252
2253
2254
/*
2255
 * 'cups_map_rgb_color()' - Map an RGB color to a color index.  We map the
2256
 *                          RGB color to the output colorspace & bits (we
2257
 *                          figure out the format when we output a page).
2258
 */
2259
2260
private gx_color_index      /* O - Color index */
2261
cups_map_rgb_color(gx_device      *pdev,/* I - Device info */
2262
                   const gx_color_value cv[3])/* I - RGB color values */
2263
{
2264
  gx_color_index  i;    /* Temporary index */
2265
  gx_color_value        r, g, b;
2266
  gx_color_value  ic, im, iy, ik; /* Integral CMYK values */
2267
  gx_color_value  mk;   /* Maximum K value */
2268
  int     tc, tm, ty; /* Temporary color values */
2269
  float     rr, rg, rb, /* Real RGB colors */
2270
      ciex, ciey, ciez,
2271
          /* CIE XYZ colors */
2272
      ciey_yn,  /* Normalized luminance */
2273
      ciel, ciea, cieb;
2274
          /* CIE Lab colors */
2275
2276
  r = cv[0];
2277
  g = cv[1];
2278
  b = cv[2];
2279
2280
#ifdef CUPS_DEBUG2
2281
  dmprintf4(pdev->memory, "DEBUG2: cups_map_rgb_color(%p, %d, %d, %d)\n",
2282
            pdev, r, g, b);
2283
#endif /* CUPS_DEBUG2 */
2284
2285
 /*
2286
  * Setup the color info data as needed...
2287
  */
2288
2289
  if (pdev->color_info.num_components == 0) {
2290
    if (cups_set_color_info(pdev) < 0)
2291
        return(gx_no_color_index);
2292
  }
2293
2294
 /*
2295
  * Do color correction as needed...
2296
  */
2297
2298
  if (cups->HaveProfile)
2299
  {
2300
   /*
2301
    * Compute CMYK values...
2302
    */
2303
2304
    ic = gx_max_color_value - r;
2305
    im = gx_max_color_value - g;
2306
    iy = gx_max_color_value - b;
2307
    ik = min(ic, min(im, iy));
2308
2309
    if ((mk = max(ic, max(im, iy))) > ik)
2310
      ik = (int)((float)ik * (float)ik * (float)ik / ((float)mk * (float)mk));
2311
2312
    ic -= ik;
2313
    im -= ik;
2314
    iy -= ik;
2315
2316
   /*
2317
    * Color correct CMY...
2318
    */
2319
2320
    tc = cups->Matrix[0][0][ic] +
2321
         cups->Matrix[0][1][im] +
2322
   cups->Matrix[0][2][iy] +
2323
   ik;
2324
    tm = cups->Matrix[1][0][ic] +
2325
         cups->Matrix[1][1][im] +
2326
   cups->Matrix[1][2][iy] +
2327
   ik;
2328
    ty = cups->Matrix[2][0][ic] +
2329
         cups->Matrix[2][1][im] +
2330
   cups->Matrix[2][2][iy] +
2331
   ik;
2332
2333
   /*
2334
    * Density correct combined CMYK...
2335
    */
2336
2337
    if (tc < 0)
2338
      r = gx_max_color_value;
2339
    else if (tc > gx_max_color_value)
2340
      r = gx_max_color_value - cups->Density[gx_max_color_value];
2341
    else
2342
      r = gx_max_color_value - cups->Density[tc];
2343
2344
    if (tm < 0)
2345
      g = gx_max_color_value;
2346
    else if (tm > gx_max_color_value)
2347
      g = gx_max_color_value - cups->Density[gx_max_color_value];
2348
    else
2349
      g = gx_max_color_value - cups->Density[tm];
2350
2351
    if (ty < 0)
2352
      b = gx_max_color_value;
2353
    else if (ty > gx_max_color_value)
2354
      b = gx_max_color_value - cups->Density[gx_max_color_value];
2355
    else
2356
      b = gx_max_color_value - cups->Density[ty];
2357
  }
2358
2359
 /*
2360
  * Convert the RGB color to a color index...
2361
  */
2362
2363
  switch (cups->header.cupsColorSpace)
2364
  {
2365
    case CUPS_CSPACE_W :
2366
    case CUPS_CSPACE_SW :
2367
        i = cups->EncodeLUT[(r * 31 + g * 61 + b * 8) / 100];
2368
        break;
2369
2370
    case CUPS_CSPACE_RGB :
2371
    case CUPS_CSPACE_SRGB :
2372
    case CUPS_CSPACE_ADOBERGB :
2373
        ic = cups->EncodeLUT[r];
2374
        im = cups->EncodeLUT[g];
2375
        iy = cups->EncodeLUT[b];
2376
2377
        switch (cups->header.cupsBitsPerColor)
2378
        {
2379
          default :
2380
              i = (((ic << 1) | im) << 1) | iy;
2381
              break;
2382
          case 2 :
2383
              i = (((ic << 2) | im) << 2) | iy;
2384
              break;
2385
          case 4 :
2386
              i = (((ic << 4) | im) << 4) | iy;
2387
              break;
2388
          case 8 :
2389
              i = (((ic << 8) | im) << 8) | iy;
2390
              break;
2391
#ifdef GX_COLOR_INDEX_TYPE
2392
    case 16 :
2393
        i = (((ic << 16) | im) << 16) | iy;
2394
        break;
2395
#endif /* GX_COLOR_INDEX_TYPE */
2396
        }
2397
        break;
2398
2399
    case CUPS_CSPACE_RGBW :
2400
        if (!r && !g && !b)
2401
  {
2402
   /*
2403
    * Map black to W...
2404
    */
2405
2406
          switch (cups->header.cupsBitsPerColor)
2407
          {
2408
            default :
2409
          i = 0x00;
2410
          break;
2411
            case 2 :
2412
          i = 0x00;
2413
          break;
2414
            case 4 :
2415
          i = 0x0000;
2416
          break;
2417
            case 8 :
2418
          i = 0x00000000;
2419
          break;
2420
#ifdef GX_COLOR_INDEX_TYPE
2421
      case 16 :
2422
    i = 0x0000000000000000;
2423
    break;
2424
#endif /* GX_COLOR_INDEX_TYPE */
2425
          }
2426
    break;
2427
  }
2428
2429
    case CUPS_CSPACE_RGBA :
2430
        ic = cups->EncodeLUT[r];
2431
        im = cups->EncodeLUT[g];
2432
        iy = cups->EncodeLUT[b];
2433
2434
        switch (cups->header.cupsBitsPerColor)
2435
        {
2436
          default :
2437
              i = (((((ic << 1) | im) << 1) | iy) << 1) | 0x01;
2438
              break;
2439
          case 2 :
2440
              i = (((((ic << 2) | im) << 2) | iy) << 2) | 0x03;
2441
              break;
2442
          case 4 :
2443
              i = (((((ic << 4) | im) << 4) | iy) << 4) | 0x0f;
2444
              break;
2445
          case 8 :
2446
              i = (((((ic << 8) | im) << 8) | iy) << 8) | 0xff;
2447
              break;
2448
#ifdef GX_COLOR_INDEX_TYPE
2449
    case 16 :
2450
        i = (((((ic << 16) | im) << 16) | iy) << 16) | 0xffff;
2451
        break;
2452
#endif /* GX_COLOR_INDEX_TYPE */
2453
        }
2454
        break;
2455
2456
    default :
2457
        i = cups->EncodeLUT[gx_max_color_value - (r * 31 + g * 61 + b * 8) / 100];
2458
        break;
2459
2460
    case CUPS_CSPACE_CMY :
2461
        ic = cups->EncodeLUT[gx_max_color_value - r];
2462
        im = cups->EncodeLUT[gx_max_color_value - g];
2463
        iy = cups->EncodeLUT[gx_max_color_value - b];
2464
2465
        switch (cups->header.cupsBitsPerColor)
2466
        {
2467
          default :
2468
              i = (((ic << 1) | im) << 1) | iy;
2469
              break;
2470
          case 2 :
2471
              i = (((ic << 2) | im) << 2) | iy;
2472
              break;
2473
          case 4 :
2474
              i = (((ic << 4) | im) << 4) | iy;
2475
              break;
2476
          case 8 :
2477
              i = (((ic << 8) | im) << 8) | iy;
2478
              break;
2479
#ifdef GX_COLOR_INDEX_TYPE
2480
    case 16 :
2481
        i = (((ic << 16) | im) << 16) | iy;
2482
        break;
2483
#endif /* GX_COLOR_INDEX_TYPE */
2484
        }
2485
        break;
2486
2487
    case CUPS_CSPACE_YMC :
2488
        ic = cups->EncodeLUT[gx_max_color_value - r];
2489
        im = cups->EncodeLUT[gx_max_color_value - g];
2490
        iy = cups->EncodeLUT[gx_max_color_value - b];
2491
2492
        switch (cups->header.cupsBitsPerColor)
2493
        {
2494
          default :
2495
              i = (((iy << 1) | im) << 1) | ic;
2496
              break;
2497
          case 2 :
2498
              i = (((iy << 2) | im) << 2) | ic;
2499
              break;
2500
          case 4 :
2501
              i = (((iy << 4) | im) << 4) | ic;
2502
              break;
2503
          case 8 :
2504
              i = (((iy << 8) | im) << 8) | ic;
2505
              break;
2506
        }
2507
        break;
2508
2509
    case CUPS_CSPACE_CMYK :
2510
  ic = gx_max_color_value - r;
2511
  im = gx_max_color_value - g;
2512
  iy = gx_max_color_value - b;
2513
        ik = min(ic, min(im, iy));
2514
2515
  if ((mk = max(ic, max(im, iy))) > ik)
2516
    ik = (int)((float)ik * (float)ik * (float)ik /
2517
               ((float)mk * (float)mk));
2518
2519
        ic = cups->EncodeLUT[ic - ik];
2520
        im = cups->EncodeLUT[im - ik];
2521
        iy = cups->EncodeLUT[iy - ik];
2522
        ik = cups->EncodeLUT[ik];
2523
2524
        switch (cups->header.cupsBitsPerColor)
2525
        {
2526
          default :
2527
              i = (((((ic << 1) | im) << 1) | iy) << 1) | ik;
2528
              break;
2529
          case 2 :
2530
              i = (((((ic << 2) | im) << 2) | iy) << 2) | ik;
2531
              break;
2532
          case 4 :
2533
              i = (((((ic << 4) | im) << 4) | iy) << 4) | ik;
2534
              break;
2535
          case 8 :
2536
              i = (((((ic << 8) | im) << 8) | iy) << 8) | ik;
2537
              break;
2538
#ifdef GX_COLOR_INDEX_TYPE
2539
    case 16 :
2540
        i = (((((ic << 16) | im) << 16) | iy) << 16) | ik;
2541
        break;
2542
#endif /* GX_COLOR_INDEX_TYPE */
2543
        }
2544
2545
#ifdef CUPS_DEBUG2
2546
        dmprintf8(pdev->memory, "DEBUG2: CMY (%d,%d,%d) -> CMYK %08x (%d,%d,%d,%d)\n",
2547
                  r, g, b, (unsigned)i, ic, im, iy, ik);
2548
#endif /* CUPS_DEBUG2 */
2549
        break;
2550
2551
    case CUPS_CSPACE_YMCK :
2552
    case CUPS_CSPACE_GMCK :
2553
    case CUPS_CSPACE_GMCS :
2554
  ic = gx_max_color_value - r;
2555
  im = gx_max_color_value - g;
2556
  iy = gx_max_color_value - b;
2557
        ik = min(ic, min(im, iy));
2558
2559
  if ((mk = max(ic, max(im, iy))) > ik)
2560
    ik = (int)((float)ik * (float)ik * (float)ik /
2561
               ((float)mk * (float)mk));
2562
2563
        ic = cups->EncodeLUT[ic - ik];
2564
        im = cups->EncodeLUT[im - ik];
2565
        iy = cups->EncodeLUT[iy - ik];
2566
        ik = cups->EncodeLUT[ik];
2567
2568
        switch (cups->header.cupsBitsPerColor)
2569
        {
2570
          default :
2571
              i = (((((iy << 1) | im) << 1) | ic) << 1) | ik;
2572
              break;
2573
          case 2 :
2574
              i = (((((iy << 2) | im) << 2) | ic) << 2) | ik;
2575
              break;
2576
          case 4 :
2577
              i = (((((iy << 4) | im) << 4) | ic) << 4) | ik;
2578
              break;
2579
          case 8 :
2580
              i = (((((iy << 8) | im) << 8) | ic) << 8) | ik;
2581
              break;
2582
#ifdef GX_COLOR_INDEX_TYPE
2583
    case 16 :
2584
        i = (((((iy << 16) | im) << 16) | ic) << 16) | ik;
2585
        break;
2586
#endif /* GX_COLOR_INDEX_TYPE */
2587
        }
2588
        break;
2589
2590
    case CUPS_CSPACE_KCMYcm :
2591
        if (cups->header.cupsBitsPerColor == 1)
2592
  {
2593
    ic = gx_max_color_value - r;
2594
    im = gx_max_color_value - g;
2595
    iy = gx_max_color_value - b;
2596
          ik = min(ic, min(im, iy));
2597
2598
    if ((mk = max(ic, max(im, iy))) > ik)
2599
      ik = (int)((float)ik * (float)ik * (float)ik /
2600
                 ((float)mk * (float)mk));
2601
2602
          ic = cups->EncodeLUT[ic - ik];
2603
          im = cups->EncodeLUT[im - ik];
2604
          iy = cups->EncodeLUT[iy - ik];
2605
          ik = cups->EncodeLUT[ik];
2606
    if (ik)
2607
      i = 32;
2608
    else if (ic && im)
2609
      i = 17;
2610
    else if (ic && iy)
2611
      i = 6;
2612
    else if (im && iy)
2613
      i = 12;
2614
    else if (ic)
2615
      i = 16;
2616
    else if (im)
2617
      i = 8;
2618
    else if (iy)
2619
      i = 4;
2620
    else
2621
      i = 0;
2622
    break;
2623
  }
2624
2625
    case CUPS_CSPACE_KCMY :
2626
  ic = gx_max_color_value - r;
2627
  im = gx_max_color_value - g;
2628
  iy = gx_max_color_value - b;
2629
        ik = min(ic, min(im, iy));
2630
2631
  if ((mk = max(ic, max(im, iy))) > ik)
2632
    ik = (int)((float)ik * (float)ik * (float)ik /
2633
               ((float)mk * (float)mk));
2634
2635
        ic = cups->EncodeLUT[ic - ik];
2636
        im = cups->EncodeLUT[im - ik];
2637
        iy = cups->EncodeLUT[iy - ik];
2638
        ik = cups->EncodeLUT[ik];
2639
2640
        switch (cups->header.cupsBitsPerColor)
2641
        {
2642
          default :
2643
              i = (((((ik << 1) | ic) << 1) | im) << 1) | iy;
2644
              break;
2645
          case 2 :
2646
              i = (((((ik << 2) | ic) << 2) | im) << 2) | iy;
2647
              break;
2648
          case 4 :
2649
              i = (((((ik << 4) | ic) << 4) | im) << 4) | iy;
2650
              break;
2651
          case 8 :
2652
              i = (((((ik << 8) | ic) << 8) | im) << 8) | iy;
2653
              break;
2654
#ifdef GX_COLOR_INDEX_TYPE
2655
    case 16 :
2656
        i = (((((ik << 16) | ic) << 16) | im) << 16) | iy;
2657
        break;
2658
#endif /* GX_COLOR_INDEX_TYPE */
2659
        }
2660
        break;
2661
2662
#  ifdef CUPS_RASTER_HAVE_COLORIMETRIC
2663
    case CUPS_CSPACE_CIEXYZ :
2664
    case CUPS_CSPACE_CIELab :
2665
    case CUPS_CSPACE_ICC1 :
2666
    case CUPS_CSPACE_ICC2 :
2667
    case CUPS_CSPACE_ICC3 :
2668
    case CUPS_CSPACE_ICC4 :
2669
    case CUPS_CSPACE_ICC5 :
2670
    case CUPS_CSPACE_ICC6 :
2671
    case CUPS_CSPACE_ICC7 :
2672
    case CUPS_CSPACE_ICC8 :
2673
    case CUPS_CSPACE_ICC9 :
2674
    case CUPS_CSPACE_ICCA :
2675
    case CUPS_CSPACE_ICCB :
2676
    case CUPS_CSPACE_ICCC :
2677
    case CUPS_CSPACE_ICCD :
2678
    case CUPS_CSPACE_ICCE :
2679
    case CUPS_CSPACE_ICCF :
2680
       /*
2681
        * Convert sRGB to linear RGB...
2682
  */
2683
2684
  rr = pow(((double)r / (double)gx_max_color_value + 0.055) / 1.055, 2.4);
2685
  rg = pow(((double)g / (double)gx_max_color_value + 0.055) / 1.055, 2.4);
2686
  rb = pow(((double)b / (double)gx_max_color_value + 0.055) / 1.055, 2.4);
2687
2688
       /*
2689
        * Convert to CIE XYZ...
2690
  */
2691
2692
  ciex = 0.412453 * rr + 0.357580 * rg + 0.180423 * rb;
2693
  ciey = 0.212671 * rr + 0.715160 * rg + 0.072169 * rb;
2694
  ciez = 0.019334 * rr + 0.119193 * rg + 0.950227 * rb;
2695
2696
        if (cups->header.cupsColorSpace == CUPS_CSPACE_CIEXYZ)
2697
  {
2698
   /*
2699
    * Convert to an integer XYZ color value...
2700
    */
2701
2702
          if (ciex > 1.1)
2703
      ic = 255;
2704
    else if (ciex > 0.0)
2705
      ic = (int)(ciex / 1.1 * 255.0 + 0.5);
2706
    else
2707
      ic = 0;
2708
2709
          if (ciey > 1.1)
2710
      im = 255;
2711
    else if (ciey > 0.0)
2712
      im = (int)(ciey / 1.1 * 255.0 + 0.5);
2713
    else
2714
      im = 0;
2715
2716
          if (ciez > 1.1)
2717
      iy = 255;
2718
    else if (ciez > 0.0)
2719
      iy = (int)(ciez / 1.1 * 255.0 + 0.5);
2720
    else
2721
      iy = 0;
2722
  }
2723
  else
2724
  {
2725
   /*
2726
    * Convert CIE XYZ to Lab...
2727
    */
2728
2729
    ciey_yn = ciey / D65_Y;
2730
2731
    if (ciey_yn > 0.008856)
2732
      ciel = 116 * cbrt(ciey_yn) - 16;
2733
    else
2734
      ciel = 903.3 * ciey_yn;
2735
2736
    ciea = 500 * (cups_map_cielab(ciex, D65_X) -
2737
                  cups_map_cielab(ciey, D65_Y));
2738
    cieb = 200 * (cups_map_cielab(ciey, D65_Y) -
2739
                  cups_map_cielab(ciez, D65_Z));
2740
2741
         /*
2742
    * Scale the L value and bias the a and b values by 128
2743
    * so that all values are in the range of 0 to 255.
2744
    */
2745
2746
    ciel = ciel * 2.55 + 0.5;
2747
    ciea += 128.5;
2748
    cieb += 128.5;
2749
2750
         /*
2751
    * Convert to 8-bit values...
2752
    */
2753
2754
          if (ciel < 0.0)
2755
      ic = 0;
2756
    else if (ciel < 255.0)
2757
      ic = (int)ciel;
2758
    else
2759
      ic = 255;
2760
2761
          if (ciea < 0.0)
2762
      im = 0;
2763
    else if (ciea < 255.0)
2764
      im = (int)ciea;
2765
    else
2766
      im = 255;
2767
2768
          if (cieb < 0.0)
2769
      iy = 0;
2770
    else if (cieb < 255.0)
2771
      iy = (int)cieb;
2772
    else
2773
      iy = 255;
2774
  }
2775
2776
       /*
2777
        * Put the final color value together...
2778
  */
2779
2780
        switch (cups->header.cupsBitsPerColor)
2781
        {
2782
          default :
2783
              i = (((ic << 1) | im) << 1) | iy;
2784
              break;
2785
          case 2 :
2786
              i = (((ic << 2) | im) << 2) | iy;
2787
              break;
2788
          case 4 :
2789
              i = (((ic << 4) | im) << 4) | iy;
2790
              break;
2791
          case 8 :
2792
              i = (((ic << 8) | im) << 8) | iy;
2793
              break;
2794
#ifdef GX_COLOR_INDEX_TYPE
2795
    case 16 :
2796
        i = (((ic << 16) | im) << 16) | iy;
2797
        break;
2798
#endif /* GX_COLOR_INDEX_TYPE */
2799
        }
2800
        break;
2801
#  endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
2802
  }
2803
2804
#ifdef CUPS_DEBUG2
2805
  dmprintf4(pdev->memory, "DEBUG2: RGB %d,%d,%d = %08x\n",
2806
            r, g, b, (unsigned)i);
2807
#endif /* CUPS_DEBUG2 */
2808
2809
  return (i);
2810
}
2811
#endif /* dev_t_proc_encode_color */
2812
2813
2814
/*
2815
 * 'cups_open()' - Open the output file and initialize things.
2816
 */
2817
2818
private int       /* O - Error status */
2819
cups_open(gx_device *pdev)    /* I - Device info */
2820
29.4k
{
2821
29.4k
  int code;       /* Return status */
2822
2823
#ifdef CUPS_DEBUG2
2824
  dmprintf1(pdev->memory, "DEBUG2: cups_open(%p)\n", pdev);
2825
#endif /* CUPS_DEBUG2 */
2826
2827
29.4k
  dmprintf(pdev->memory, "INFO: Start rendering...\n");
2828
29.4k
  cups->printer_procs.get_space_params = cups_get_space_params;
2829
2830
29.4k
  if (cups->page == 0)
2831
29.4k
  {
2832
29.4k
    dmprintf(pdev->memory, "INFO: Processing page 1...\n");
2833
29.4k
    cups->page = 1;
2834
29.4k
  }
2835
2836
29.4k
  if ((code = cups_set_color_info(pdev)) < 0) {
2837
13
    return(code);
2838
13
  }
2839
2840
  /* Establish the default LeadingEdge in the cups header */
2841
29.4k
  cups->header.LeadingEdge = (cups_edge_t)(pdev->LeadingEdge & LEADINGEDGE_MASK);
2842
2843
29.4k
  if ((code = gdev_prn_open(pdev)) != 0)
2844
0
    return(code);
2845
2846
29.4k
  if (cups->PPD == NULL)
2847
29.4k
    cups->PPD = ppdOpenFile(getenv("PPD"));
2848
2849
29.4k
  if (cups->pageSizeRequested[0] == '\0') {
2850
29.4k
    (void) snprintf(cups->pageSizeRequested, sizeof(cups->pageSizeRequested), "%s", cups->header.cupsPageSizeName);
2851
#ifdef CUPS_DEBUG
2852
    dmprintf1(pdev->memory, "DEBUG: Page size requested: %s\n",
2853
        cups->header.cupsPageSizeName);
2854
#endif /* CUPS_DEBUG */
2855
29.4k
  }
2856
2857
29.4k
  return (0);
2858
29.4k
}
2859
2860
2861
/*
2862
 * 'cups_output_page()' - Send one or more pages to the output file.
2863
 * The changes to the cups->page are done here for background printing
2864
 * but testing shows some regressions, so BGPrint is not used for now.
2865
 */
2866
2867
private int       /* O - 0 if everything is OK */
2868
cups_output_page(gx_device *pdev, int num_copies, int flush)
2869
24.1k
{
2870
24.1k
  int   code = 0;   /* Error code */
2871
2872
  /* FIXME: We would like to support BGPrint=true and call gdev_prn_bg_output_page */
2873
  /* but there must still be other things that prevent this. */
2874
24.1k
  if ((code = gdev_prn_output_page(pdev, num_copies, flush)) < 0)
2875
5
      return code;
2876
2877
24.1k
  cups->page ++;
2878
24.1k
  dmprintf1(pdev->memory, "INFO: Processing page %d...\n", cups->page);
2879
2880
24.1k
  return (0);
2881
24.1k
}
2882
2883
2884
/*
2885
 * 'cups_print_pages()' - Send one or more pages to the output file.
2886
 */
2887
2888
private int       /* O - 0 if everything is OK */
2889
cups_print_pages(gx_device_printer *pdev,
2890
          /* I - Device info */
2891
                 gp_file           *fp, /* I - Output file */
2892
     int               num_copies)
2893
          /* I - Number of copies */
2894
24.1k
{
2895
24.1k
  int   code = 0;   /* Error code */
2896
24.1k
  int   copy;     /* Copy number */
2897
24.1k
  int   srcbytes;   /* Byte width of scanline */
2898
24.1k
  unsigned char *src,     /* Scanline data */
2899
24.1k
    *dst;     /* Bitmap data */
2900
24.1k
  ppd_attr_t    *RasterVersion = NULL;  /* CUPS Raster version read from PPD
2901
             file */
2902
2903
24.1k
  (void)fp; /* reference unused file pointer to prevent compiler warning */
2904
2905
#ifdef CUPS_DEBUG2
2906
  dmprintf3(pdev->memory, "DEBUG2: cups_print_pages(%p, %p, %d)\n", pdev, fp,
2907
            num_copies);
2908
#endif /* CUPS_DEBUG2 */
2909
2910
 /*
2911
  * Figure out the number of bytes per line...
2912
  */
2913
2914
24.1k
  switch (cups->header.cupsColorOrder)
2915
24.1k
  {
2916
24.1k
    case CUPS_ORDER_CHUNKED :
2917
24.1k
        cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel *
2918
24.1k
                                   cups->header.cupsWidth + 7) / 8;
2919
24.1k
        break;
2920
2921
0
    case CUPS_ORDER_BANDED :
2922
0
        if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
2923
0
      cups->header.cupsBitsPerColor == 1)
2924
0
          cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
2925
0
                                           cups->header.cupsWidth + 7) / 8 * 6;
2926
0
        else
2927
0
          cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
2928
0
                                           cups->header.cupsWidth + 7) / 8 *
2929
0
                  cups->color_info.num_components;
2930
0
        break;
2931
2932
0
    case CUPS_ORDER_PLANAR :
2933
0
        cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
2934
0
                                   cups->header.cupsWidth + 7) / 8;
2935
0
        break;
2936
24.1k
  }
2937
2938
 /*
2939
  * Compute the width of a scanline and allocate input/output buffers...
2940
  */
2941
2942
24.1k
  srcbytes = gdev_prn_raster(pdev);
2943
2944
#ifdef CUPS_DEBUG2
2945
  dmprintf4(pdev->memory, "DEBUG2: cupsBitsPerPixel = %d, cupsWidth = %d, cupsBytesPerLine = %d, srcbytes = %d\n",
2946
            cups->header.cupsBitsPerPixel, cups->header.cupsWidth,
2947
            cups->header.cupsBytesPerLine, srcbytes);
2948
#endif /* CUPS_DEBUG2 */
2949
2950
24.1k
  src = (unsigned char *)gs_malloc(pdev->memory->non_gc_memory, srcbytes, 1, "cups_print_pages");
2951
2952
24.1k
  if (src == NULL)  /* can't allocate input buffer */
2953
0
    return_error(gs_error_VMerror);
2954
2955
24.1k
  memset(src, 0, srcbytes);
2956
2957
 /*
2958
  * Need an output buffer, too...
2959
  */
2960
2961
24.1k
  dst = (unsigned char *)gs_malloc(pdev->memory->non_gc_memory, cups->header.cupsBytesPerLine, 2,
2962
24.1k
                                   "cups_print_pages");
2963
2964
24.1k
  if (dst == NULL)  /* can't allocate working area */
2965
0
    return_error(gs_error_VMerror);
2966
2967
24.1k
  memset(dst, 0, 2 * cups->header.cupsBytesPerLine);
2968
2969
 /*
2970
  * See if the stream has been initialized yet...
2971
  */
2972
2973
24.1k
  if (cups->stream == NULL)
2974
15.6k
  {
2975
15.6k
    RasterVersion = ppdFindAttr(cups->PPD, "cupsRasterVersion", NULL);
2976
15.6k
    if (RasterVersion) {
2977
#ifdef CUPS_DEBUG2
2978
      dmprintf1(pdev->memory, "DEBUG2: cupsRasterVersion = %s\n",
2979
                RasterVersion->value);
2980
#endif /* CUPS_DEBUG2 */
2981
0
      cups->cupsRasterVersion = atoi(RasterVersion->value);
2982
0
      if ((cups->cupsRasterVersion != 2) &&
2983
0
    (cups->cupsRasterVersion != 3)) {
2984
0
        dmprintf1(pdev->memory, "ERROR: Unsupported CUPS Raster Version: %s",
2985
0
                  RasterVersion->value);
2986
0
  return_error(gs_error_unknownerror);
2987
0
      }
2988
0
    }
2989
    /* NOTE: PWG Raster output is only available with shared CUPS CUPS and
2990
       CUPS image libraries as the built-in libraries of Ghostscript do not
2991
       contain the new code needed for PWG Raster output. This conditional
2992
       is a temporary workaround for the time being until up-to-date CUPS
2993
       libraries get included. */
2994
15.6k
    if ((cups->stream = cupsRasterOpen(fileno(gp_get_file(cups->file)),
2995
15.6k
#if defined(CUPS_RASTER_HAVE_PWGRASTER)
2996
15.6k
                                       (strcasecmp(cups->header.MediaClass,
2997
15.6k
               "PwgRaster") == 0 ?
2998
0
#if defined(CUPS_RASTER_HAVE_APPLERASTER)
2999
0
          (!strcmp(cups->dname, "appleraster") ||
3000
0
           !strcmp(cups->dname, "urf") ?
3001
0
           CUPS_RASTER_WRITE_APPLE :
3002
0
           CUPS_RASTER_WRITE_PWG) :
3003
#else
3004
          CUPS_RASTER_WRITE_PWG :
3005
#endif
3006
15.6k
          (cups->cupsRasterVersion == 3 ?
3007
15.6k
           CUPS_RASTER_WRITE :
3008
15.6k
           CUPS_RASTER_WRITE_COMPRESSED)))) ==
3009
15.6k
  NULL)
3010
#else
3011
                                       (cups->cupsRasterVersion == 3 ?
3012
          CUPS_RASTER_WRITE :
3013
          CUPS_RASTER_WRITE_COMPRESSED))) == NULL)
3014
#endif
3015
0
    {
3016
0
      perror("ERROR: Unable to open raster stream - ");
3017
0
      return_error(gs_error_ioerror);
3018
0
    }
3019
15.6k
  }
3020
3021
 /*
3022
  * Output a page of graphics...
3023
  */
3024
3025
24.1k
  if (num_copies < 1)
3026
0
    num_copies = 1;
3027
3028
24.1k
  if ((cups->PPD == NULL && !cups->cupsManualCopies) ||
3029
0
      (cups->PPD != NULL && !cups->PPD->manual_copies))
3030
24.1k
  {
3031
24.1k
    cups->header.NumCopies = num_copies;
3032
24.1k
    num_copies = 1;
3033
24.1k
  }
3034
3035
#ifdef CUPS_DEBUG
3036
  dmprintf3(pdev->memory, "DEBUG2: cupsWidth = %d, cupsHeight = %d, cupsBytesPerLine = %d\n",
3037
            cups->header.cupsWidth, cups->header.cupsHeight,
3038
            cups->header.cupsBytesPerLine);
3039
#endif /* CUPS_DEBUG */
3040
3041
48.2k
  for (copy = num_copies; copy > 0; copy --)
3042
24.1k
  {
3043
24.1k
    cupsRasterWriteHeader(cups->stream, &(cups->header));
3044
3045
24.1k
    if (pdev->color_info.num_components == 1)
3046
2.21k
      code = cups_print_chunked(pdev, src, dst, srcbytes);
3047
21.9k
    else
3048
21.9k
      switch (cups->header.cupsColorOrder)
3049
21.9k
      {
3050
21.9k
  case CUPS_ORDER_CHUNKED :
3051
21.9k
            code = cups_print_chunked(pdev, src, dst, srcbytes);
3052
21.9k
      break;
3053
0
  case CUPS_ORDER_BANDED :
3054
0
            code = cups_print_banded(pdev, src, dst, srcbytes);
3055
0
      break;
3056
0
  case CUPS_ORDER_PLANAR :
3057
0
            code = cups_print_planar(pdev, src, dst, srcbytes);
3058
0
      break;
3059
21.9k
      }
3060
24.1k
    if (code < 0)
3061
5
      break;
3062
24.1k
  }
3063
3064
 /*
3065
  * Free temporary storage and return...
3066
  */
3067
3068
24.1k
  gs_free(pdev->memory->non_gc_memory, (char *)src, srcbytes, 1, "cups_print_pages");
3069
24.1k
  gs_free(pdev->memory->non_gc_memory, (char *)dst, cups->header.cupsBytesPerLine, 1, "cups_print_pages");
3070
3071
24.1k
 return (code);
3072
24.1k
}
3073
3074
3075
/*
3076
 * 'cups_put_params()' - Set pagedevice parameters.
3077
 */
3078
3079
private int       /* O - Error status */
3080
cups_put_params(gx_device     *pdev,  /* I - Device info */
3081
                gs_param_list *plist) /* I - Parameter list */
3082
264k
{
3083
264k
  int     i;    /* Looping var */
3084
264k
  float     mediasize[2]; /* Physical size of print */
3085
264k
  float     margins[4]; /* Physical margins of print */
3086
264k
  float     cups_mediasize[2]; /* Media size to use in Raster */
3087
264k
  float     cups_margins[4]; /* Margins to use in Raster */
3088
264k
  ppd_size_t    *size;    /* Page size */
3089
264k
  int     code;   /* Error code */
3090
264k
  int     intval;   /* Integer value */
3091
264k
  bool      boolval;  /* Boolean value */
3092
264k
  float     floatval; /* Floating point value */
3093
264k
  gs_param_string stringval;  /* String value */
3094
264k
  gs_param_float_array  arrayval; /* Float array value */
3095
264k
  int     margins_set;  /* Were the margins set? */
3096
264k
  int     size_set; /* Was the size set? */
3097
264k
  int     color_set;  /* Were the color attrs set? */
3098
264k
  gdev_space_params sp_old;         /* Space parameter data */
3099
264k
  int     width,    /* New width of page */
3100
264k
                        height,   /* New height of page */
3101
264k
                        width_old = 0,  /* Previous width of page */
3102
264k
                        height_old = 0; /* Previous height of page */
3103
264k
  bool                  transp_old = 0; /* Previous transparency usage state */
3104
264k
  ppd_attr_t            *backside = NULL,
3105
264k
                        *backsiderequiresflippedmargins = NULL;
3106
264k
  float                 swap;
3107
264k
  int                   xflip = 0,
3108
264k
                        yflip = 0;
3109
264k
  int                   found = 0;
3110
264k
  long                  best_score = -1,
3111
264k
                        score = 0;
3112
264k
  ppd_size_t            *best_size = NULL;
3113
264k
  int                   size_matched = 0,
3114
264k
                        margins_matched = 0,
3115
264k
                        imageable_area_matched = 0;
3116
#ifdef CUPS_DEBUG
3117
  int                   name_requested_matched = 0;
3118
#endif
3119
264k
  float long_edge_mismatch, short_edge_mismatch;
3120
264k
  gs_param_string icc_pro_dummy;
3121
264k
  int old_cmps = cups->color_info.num_components;
3122
264k
  int old_depth = cups->color_info.depth;
3123
264k
#ifdef CUPS_RASTER_SYNCv1
3124
264k
  float     sf;   /* cupsBorderlessScalingFactor */
3125
264k
#endif /* CUPS_RASTER_SYNCv1 */
3126
3127
#ifdef CUPS_DEBUG
3128
  dmprintf2(pdev->memory, "DEBUG2: cups_put_params(%p, %p)\n", pdev, plist);
3129
#endif /* CUPS_DEBUG */
3130
3131
 /*
3132
  * Process other options for CUPS...
3133
  */
3134
3135
264k
#define stringoption(name, sname) \
3136
6.08M
  if ((code = param_read_string(plist, sname, &stringval)) < 0) \
3137
6.08M
  { \
3138
0
    dmprintf1(pdev->memory, "ERROR: Error setting %s...\n", sname);        \
3139
0
    param_signal_error(plist, sname, code); \
3140
0
    goto done; \
3141
0
  } \
3142
6.08M
  else if (code == 0) \
3143
6.08M
  { \
3144
415k
    size_t _copylen = stringval.size; \
3145
415k
    if (_copylen > sizeof(cups->header.name) - 1) \
3146
415k
      _copylen = sizeof(cups->header.name) - 1; \
3147
415k
    strncpy(cups->header.name, (const char *)(stringval.data),  \
3148
415k
            _copylen); \
3149
415k
    cups->header.name[_copylen] = '\0'; \
3150
415k
  }
3151
3152
264k
#define intoption(name, sname, type) \
3153
8.46M
  if ((code = param_read_int(plist, sname, &intval)) < 0) \
3154
8.46M
  { \
3155
0
    dmprintf1(pdev->memory, "ERROR: Error setting %s ...\n", sname); \
3156
0
    param_signal_error(plist, sname, code); \
3157
0
    goto done; \
3158
0
  } \
3159
8.46M
  else if (code == 0) \
3160
8.46M
  { \
3161
600k
    cups->header.name = (type)intval; \
3162
600k
  }
3163
3164
264k
#define floatoption(name, sname) \
3165
4.49M
  if ((code = param_read_float(plist, sname, &floatval)) < 0) \
3166
4.49M
  { \
3167
0
    dmprintf1(pdev->memory, "ERROR: Error setting %s ...\n", sname); \
3168
0
    param_signal_error(plist, sname, code); \
3169
0
    goto done; \
3170
0
  } \
3171
4.49M
  else if (code == 0) \
3172
4.49M
  { \
3173
306k
    cups->header.name = (float)floatval; \
3174
306k
  }
3175
3176
264k
#define booloption(name, sname) \
3177
2.64M
  if ((code = param_read_bool(plist, sname, &boolval)) < 0) \
3178
2.64M
  { \
3179
0
    if ((code = param_read_null(plist, sname)) < 0) \
3180
0
    { \
3181
0
      dmprintf1(pdev->memory, "ERROR: Error setting %s ...\n", sname); \
3182
0
      param_signal_error(plist, sname, code); \
3183
0
      goto done; \
3184
0
    } \
3185
0
    if (code == 0) \
3186
0
      cups->header.name = CUPS_FALSE; \
3187
0
  } \
3188
2.64M
  else if (code == 0) \
3189
2.64M
  { \
3190
180k
    cups->header.name = (cups_bool_t)boolval; \
3191
180k
  }
3192
3193
264k
#define arrayoption(name, sname, count) \
3194
528k
  if ((code = param_read_float_array(plist, sname, &arrayval)) < 0) \
3195
528k
  { \
3196
0
    if ((code = param_read_null(plist, sname)) < 0) \
3197
0
    { \
3198
0
      dmprintf1(pdev->memory, "ERROR: Error setting %s...\n", sname); \
3199
0
      param_signal_error(plist, sname, code); \
3200
0
      goto done; \
3201
0
    } \
3202
0
    if (code == 0) \
3203
0
    { \
3204
0
      for (i = 0; i < count; i ++) \
3205
0
  cups->header.name[i] = 0; \
3206
0
    } \
3207
0
  } \
3208
528k
  else if (code == 0) \
3209
528k
  { \
3210
54.1k
    for (i = 0; i < count; i ++) { \
3211
36.1k
      cups->header.name[i] = (unsigned)(arrayval.data[i]); \
3212
36.1k
    } \
3213
18.0k
  }
3214
3215
264k
  sp_old = ((gx_device_printer *)pdev)->space_params;
3216
264k
  width_old = pdev->width;
3217
264k
  height_old = pdev->height;
3218
264k
  transp_old = cups->page_uses_transparency;
3219
264k
  size_set    = param_read_float_array(plist, ".MediaSize", &arrayval) == 0 ||
3220
79.7k
                param_read_float_array(plist, "PageSize", &arrayval) == 0;
3221
264k
  margins_set = param_read_float_array(plist, "Margins", &arrayval) == 0;
3222
264k
  color_set   = param_read_int(plist, "cupsColorSpace", &intval) == 0 ||
3223
216k
                param_read_int(plist, "cupsBitsPerColor", &intval) == 0;
3224
3225
264k
  if (!cups->user_icc) {
3226
237k
      cups->user_icc = param_read_string(plist, "OutputICCProfile", &icc_pro_dummy) == 0;
3227
237k
  }
3228
3229
  /* We also recompute page size and margins if we simply get onto a new
3230
     page without necessarily having a page size change in the PostScript
3231
     code, as for some printers margins have to be flipped on the back sides of
3232
     the sheets (even pages) when printing duplex */
3233
264k
  if (cups->page != cups->lastpage) {
3234
43.4k
    size_set = 1;
3235
43.4k
    cups->lastpage = cups->page;
3236
43.4k
  }
3237
3238
264k
  stringoption(MediaClass, "MediaClass")
3239
264k
  stringoption(MediaColor, "MediaColor")
3240
264k
  stringoption(MediaType, "MediaType")
3241
264k
  stringoption(OutputType, "OutputType")
3242
264k
  intoption(AdvanceDistance, "AdvanceDistance", unsigned)
3243
264k
  intoption(AdvanceMedia, "AdvanceMedia", cups_adv_t)
3244
264k
  booloption(Collate, "Collate")
3245
264k
  intoption(CutMedia, "CutMedia", cups_cut_t)
3246
264k
  booloption(Duplex, "Duplex")
3247
264k
  arrayoption(ImagingBoundingBox, "ImagingBoundingBox", 4)
3248
264k
  booloption(InsertSheet, "InsertSheet")
3249
264k
  intoption(Jog, "Jog", cups_jog_t)
3250
264k
  arrayoption(Margins, "Margins", 2)
3251
264k
  booloption(ManualFeed, "ManualFeed")
3252
264k
  intoption(MediaPosition, "cupsMediaPosition", unsigned) /* Compatibility */
3253
264k
  intoption(MediaPosition, "MediaPosition", unsigned)
3254
264k
  intoption(MediaWeight, "MediaWeight", unsigned)
3255
264k
  booloption(MirrorPrint, "MirrorPrint")
3256
264k
  booloption(NegativePrint, "NegativePrint")
3257
264k
  intoption(Orientation, "Orientation", cups_orient_t)
3258
264k
  switch (cups->header.Orientation)
3259
264k
  {
3260
264k
    case CUPS_ORIENT_0:
3261
264k
    case CUPS_ORIENT_90:
3262
264k
    case CUPS_ORIENT_180:
3263
264k
    case CUPS_ORIENT_270:
3264
264k
      break;
3265
0
    default:
3266
0
      dmprintf(pdev->memory, "ERROR: Error setting Orientation...\n");
3267
0
      param_signal_error(plist, "Orientation", gs_error_rangecheck);
3268
0
      goto done;
3269
0
      break;
3270
264k
  }
3271
3272
264k
  booloption(OutputFaceUp, "OutputFaceUp")
3273
264k
  booloption(Separations, "Separations")
3274
264k
  booloption(TraySwitch, "TraySwitch")
3275
264k
  booloption(Tumble, "Tumble")
3276
264k
  intoption(cupsMediaType, "cupsMediaType", unsigned)
3277
3278
264k
  intoption(cupsBitsPerColor, "cupsBitsPerColor", unsigned)
3279
264k
  switch (cups->header.cupsBitsPerColor)
3280
264k
  {
3281
212k
    case 1:
3282
212k
    case 2:
3283
212k
    case 4:
3284
264k
    case 8:
3285
264k
#ifdef GX_COLOR_INDEX_TYPE
3286
264k
    case 16:
3287
264k
#endif /* GX_COLOR_INDEX_TYPE */
3288
264k
      break;
3289
3290
0
    default:
3291
0
      dmprintf(pdev->memory, "ERROR: Error setting cupsBitsPerColor...\n");
3292
0
      param_signal_error(plist, "cupsBitsPerColor", gs_error_rangecheck);
3293
0
      goto done;
3294
0
      break;
3295
264k
  }
3296
3297
264k
  intoption(cupsColorOrder, "cupsColorOrder", cups_order_t)
3298
264k
  switch (cups->header.cupsColorOrder)
3299
264k
  {
3300
264k
    case CUPS_ORDER_CHUNKED :
3301
264k
    case CUPS_ORDER_BANDED :
3302
264k
    case CUPS_ORDER_PLANAR :
3303
264k
      break;
3304
0
    default:
3305
0
      dmprintf(pdev->memory, "ERROR: Error setting cupsColorOrder...\n");
3306
0
      param_signal_error(plist, "cupsColorOrder", gs_error_rangecheck);
3307
0
      goto done;
3308
0
      break;
3309
264k
  }
3310
3311
264k
  intoption(cupsColorSpace, "cupsColorSpace", cups_cspace_t)
3312
264k
  switch (cups->header.cupsColorSpace)
3313
264k
  {
3314
32.5k
    case CUPS_CSPACE_K:
3315
36.2k
    case CUPS_CSPACE_WHITE:
3316
40.2k
    case CUPS_CSPACE_GOLD:
3317
42.8k
    case CUPS_CSPACE_SILVER:
3318
62.6k
    case CUPS_CSPACE_W:
3319
63.3k
    case CUPS_CSPACE_SW:
3320
158k
    case CUPS_CSPACE_RGB:
3321
158k
    case CUPS_CSPACE_SRGB:
3322
169k
    case CUPS_CSPACE_ADOBERGB:
3323
170k
    case CUPS_CSPACE_RGBA:
3324
171k
    case CUPS_CSPACE_CMY:
3325
171k
    case CUPS_CSPACE_YMC:
3326
173k
    case CUPS_CSPACE_KCMY:
3327
180k
    case CUPS_CSPACE_KCMYcm:
3328
183k
    case CUPS_CSPACE_RGBW:
3329
186k
    case CUPS_CSPACE_CMYK:
3330
187k
    case CUPS_CSPACE_YMCK:
3331
203k
    case CUPS_CSPACE_GMCK:
3332
205k
    case CUPS_CSPACE_GMCS:
3333
205k
#  ifdef CUPS_RASTER_HAVE_COLORIMETRIC
3334
205k
    case CUPS_CSPACE_CIEXYZ:
3335
206k
    case CUPS_CSPACE_CIELab:
3336
236k
    case CUPS_CSPACE_ICC1:
3337
237k
    case CUPS_CSPACE_ICC2:
3338
239k
    case CUPS_CSPACE_ICC3:
3339
242k
    case CUPS_CSPACE_ICC4:
3340
251k
    case CUPS_CSPACE_ICC5:
3341
256k
    case CUPS_CSPACE_ICC6:
3342
257k
    case CUPS_CSPACE_ICC7:
3343
258k
    case CUPS_CSPACE_ICC8:
3344
259k
    case CUPS_CSPACE_ICC9:
3345
260k
    case CUPS_CSPACE_ICCA:
3346
261k
    case CUPS_CSPACE_ICCB:
3347
261k
    case CUPS_CSPACE_ICCC:
3348
262k
    case CUPS_CSPACE_ICCD:
3349
263k
    case CUPS_CSPACE_ICCE:
3350
264k
    case CUPS_CSPACE_ICCF:
3351
264k
        break;
3352
0
#  endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
3353
13
    default:
3354
13
      dmprintf(pdev->memory, "ERROR: Error setting cupsColorSpace...\n");
3355
13
      param_signal_error(plist, "cupsColorSpace", gs_error_rangecheck);
3356
13
      goto done;
3357
0
      break;
3358
264k
  }
3359
3360
264k
  intoption(cupsCompression, "cupsCompression", unsigned)
3361
264k
  intoption(cupsRowCount, "cupsRowCount", unsigned)
3362
264k
  intoption(cupsRowFeed, "cupsRowFeed", unsigned)
3363
264k
  intoption(cupsRowStep, "cupsRowStep", unsigned)
3364
3365
264k
#ifdef GX_COLOR_INDEX_TYPE
3366
 /*
3367
  * Support cupsPreferredBitsPerColor - basically, allows you to
3368
  * request 16-bits per color in a backwards-compatible way...
3369
  */
3370
3371
264k
  if (!param_read_int(plist, "cupsPreferredBitsPerColor", &intval))
3372
0
    if (intval > cups->header.cupsBitsPerColor && intval <= 16)
3373
0
      cups->header.cupsBitsPerColor = intval;
3374
264k
#endif /* GX_COLOR_INDEX_TYPE */
3375
3376
264k
#ifdef CUPS_RASTER_SYNCv1
3377
264k
  floatoption(cupsBorderlessScalingFactor, "cupsBorderlessScalingFactor");
3378
3379
4.49M
  for (i = 0; cups_Integer_strings[i] != NULL; i ++)
3380
4.23M
  {
3381
4.23M
    intoption(cupsInteger[i], cups_Integer_strings[i], unsigned)
3382
4.23M
  }
3383
3384
4.49M
  for (i = 0; cups_Real_strings[i] != NULL; i ++)
3385
4.23M
  {
3386
4.23M
    floatoption(cupsReal[i], cups_Real_strings[i])
3387
4.23M
  }
3388
3389
4.49M
  for (i = 0; cups_String_strings[i] != NULL; i ++)
3390
4.23M
  {
3391
4.23M
    stringoption(cupsString[i], cups_String_strings[i])
3392
4.23M
  }
3393
3394
264k
  stringoption(cupsMarkerType, "cupsMarkerType");
3395
264k
  stringoption(cupsRenderingIntent, "cupsRenderingIntent");
3396
264k
  stringoption(cupsPageSizeName, "cupsPageSizeName");
3397
264k
#endif /* CUPS_RASTER_SYNCv1 */
3398
3399
264k
  if ((code = param_read_string(plist, "cupsProfile", &stringval)) < 0)
3400
0
  {
3401
0
    param_signal_error(plist, "cupsProfile", code);
3402
0
    goto done;
3403
0
  }
3404
264k
  else if (code == 0)
3405
0
  {
3406
0
    if (cups->Profile != NULL)
3407
0
      free(cups->Profile);
3408
3409
0
    cups->Profile = strdup((char *)stringval.data);
3410
0
  }
3411
3412
264k
  if ((code = cups_set_color_info(pdev)) < 0) {
3413
2
      goto done;
3414
2
  }
3415
3416
 /*
3417
  * Variables for PPD-less use only. If these settings are defined in the
3418
  * PPD file, the PPD file's definitions get priority.
3419
  */
3420
3421
264k
  if ((code = param_read_int(plist, "cupsRasterVersion", &intval)) < 0)
3422
0
  {
3423
0
    dmprintf1(pdev->memory, "ERROR: Error setting %s ...\n",
3424
0
        "cupsRasterVersion");
3425
0
    param_signal_error(plist, "cupsRasterVersion", code); \
3426
0
    goto done;
3427
0
  }
3428
264k
  else if (code == 0)
3429
18.0k
    cups->cupsRasterVersion = (int)intval;
3430
3431
264k
  if ((code = param_read_string(plist, "cupsBackSideOrientation",
3432
264k
        &stringval)) < 0)
3433
0
  {
3434
0
    dmprintf1(pdev->memory, "ERROR: Error setting %s...\n",
3435
0
        "cupsBackSideOrientation");
3436
0
    param_signal_error(plist, "cupsBackSideOrientation", code);
3437
0
    goto done;
3438
0
  }
3439
264k
  else if (code == 0)
3440
18.0k
  {
3441
18.0k
    intval = min(sizeof(cups->cupsBackSideOrientation) - 1, stringval.size);
3442
18.0k
    strncpy(cups->cupsBackSideOrientation, (const char *)(stringval.data),
3443
18.0k
      intval);
3444
18.0k
    cups->cupsBackSideOrientation[intval] = '\0';
3445
18.0k
  }
3446
3447
264k
  if ((code = param_read_bool(plist, "cupsBackSideFlipMargins",
3448
264k
            &boolval)) < 0)
3449
0
  {
3450
0
    if ((code = param_read_null(plist, "cupsBackSideFlipMargins")) < 0)
3451
0
    {
3452
0
      dmprintf1(pdev->memory, "ERROR: Error setting %s ...\n",
3453
0
    "cupsBackSideFlipMargins");
3454
0
      param_signal_error(plist, "cupsBackSideFlipMargins", code);
3455
0
      goto done;
3456
0
    }
3457
0
    if (code == 0)
3458
0
      cups->cupsBackSideFlipMargins = CUPS_FALSE;
3459
0
  }
3460
264k
  else if (code == 0)
3461
18.0k
    cups->cupsBackSideFlipMargins = (cups_bool_t)boolval;
3462
3463
264k
  if ((code = param_read_bool(plist, "cupsManualCopies",
3464
264k
            &boolval)) < 0)
3465
0
  {
3466
0
    if ((code = param_read_null(plist, "cupsManualCopies")) < 0)
3467
0
    {
3468
0
      dmprintf1(pdev->memory, "ERROR: Error setting %s ...\n",
3469
0
    "cupsManualCopies");
3470
0
      param_signal_error(plist, "cupsManualCopies", code);
3471
0
      goto done;
3472
0
    }
3473
0
    if (code == 0)
3474
0
      cups->cupsManualCopies = CUPS_FALSE;
3475
0
  }
3476
264k
  else if (code == 0)
3477
18.0k
    cups->cupsManualCopies = (cups_bool_t)boolval;
3478
3479
  /*
3480
  * Then process standard page device options...
3481
  */
3482
3483
264k
  if ((code = gdev_prn_put_params(pdev, plist)) < 0)
3484
68
    goto done;
3485
3486
264k
  cups->header.LeadingEdge = (cups_edge_t)(pdev->LeadingEdge & LEADINGEDGE_MASK);
3487
3488
  /* If cups_set_color_info() changed the color model of the device we want to
3489
   * force the raster memory to be recreated/reinitialized
3490
   */
3491
264k
  if (cups->color_info.num_components != old_cmps || cups->color_info.depth != old_depth) {
3492
26.2k
      width_old = 0;
3493
26.2k
      height_old = 0;
3494
26.2k
  }
3495
238k
  else {
3496
  /* pdev->width/height may have been changed by the call to
3497
   * gdev_prn_put_params()
3498
   */
3499
238k
     width_old = pdev->width;
3500
238k
     height_old = pdev->height;
3501
238k
  }
3502
 /*
3503
  * Update margins/sizes as needed...
3504
  */
3505
3506
264k
  if (size_set)
3507
185k
  {
3508
   /*
3509
    * Compute the page margins...
3510
    */
3511
3512
#ifdef CUPS_DEBUG
3513
    dmprintf2(pdev->memory, "DEBUG: Updating PageSize to [%.0f %.0f]...\n",
3514
              cups->MediaSize[0], cups->MediaSize[1]);
3515
#endif /* CUPS_DEBUG */
3516
3517
185k
    memset(margins, 0, sizeof(margins));
3518
3519
185k
    cups->landscape = 0;
3520
3521
185k
    if (cups->PPD != NULL)
3522
0
    {
3523
#ifdef CUPS_DEBUG
3524
      dmprintf1(pdev->memory, "DEBUG2: cups->header.Duplex = %d\n", cups->header.Duplex);
3525
      dmprintf1(pdev->memory, "DEBUG2: cups->header.Tumble = %d\n", cups->header.Tumble);
3526
      dmprintf1(pdev->memory, "DEBUG2: cups->page = %d\n", cups->page);
3527
      dmprintf1(pdev->memory, "DEBUG2: cups->PPD = %p\n", cups->PPD);
3528
#endif /* CUPS_DEBUG */
3529
3530
0
      backside = ppdFindAttr(cups->PPD, "cupsBackSide", NULL);
3531
0
      if (backside) {
3532
#ifdef CUPS_DEBUG
3533
        dmprintf1(pdev->memory, "DEBUG2: cupsBackSide = %s\n", backside->value);
3534
#endif /* CUPS_DEBUG */
3535
0
  cups->PPD->flip_duplex = 0;
3536
0
      }
3537
#ifdef CUPS_DEBUG
3538
      dmprintf1(pdev->memory, "DEBUG2: cups->PPD->flip_duplex = %d\n", cups->PPD->flip_duplex);
3539
#endif /* CUPS_DEBUG */
3540
3541
0
      backsiderequiresflippedmargins =
3542
0
  ppdFindAttr(cups->PPD, "APDuplexRequiresFlippedMargin", NULL);
3543
#ifdef CUPS_DEBUG
3544
      if (backsiderequiresflippedmargins)
3545
        dmprintf1(pdev->memory, "DEBUG2: APDuplexRequiresFlippedMargin = %s\n",
3546
                  backsiderequiresflippedmargins->value);
3547
#endif /* CUPS_DEBUG */
3548
3549
0
      if (cups->header.Duplex &&
3550
0
    (cups->header.Tumble &&
3551
0
     (backside && !strcasecmp(backside->value, "Flipped"))) &&
3552
0
    !(cups->page & 1))
3553
0
      {
3554
0
  xflip = 1;
3555
0
  if (backsiderequiresflippedmargins &&
3556
0
      !strcasecmp(backsiderequiresflippedmargins->value, "False")) {
3557
#ifdef CUPS_DEBUG
3558
          dmprintf(pdev->memory, "DEBUG2: (1) Flip: X=1 Y=0\n");
3559
#endif /* CUPS_DEBUG */
3560
0
    yflip = 0;
3561
0
  } else {
3562
#ifdef CUPS_DEBUG
3563
          dmprintf(pdev->memory, "DEBUG2: (1) Flip: X=1 Y=1\n");
3564
#endif /* CUPS_DEBUG */
3565
0
    yflip = 1;
3566
0
  }
3567
0
      }
3568
0
      else if (cups->header.Duplex &&
3569
0
         (!cups->header.Tumble &&
3570
0
    (backside && !strcasecmp(backside->value, "Flipped"))) &&
3571
0
         !(cups->page & 1))
3572
0
      {
3573
0
  xflip = 0;
3574
0
  if (backsiderequiresflippedmargins &&
3575
0
      !strcasecmp(backsiderequiresflippedmargins->value, "False")) {
3576
#ifdef CUPS_DEBUG
3577
          dmprintf(pdev->memory, "DEBUG2: (2) Flip: X=0 Y=1\n");
3578
#endif /* CUPS_DEBUG */
3579
0
    yflip = 1;
3580
0
  } else {
3581
#ifdef CUPS_DEBUG
3582
          dmprintf(pdev->memory, "DEBUG2: (2) Flip: X=0 Y=0\n");
3583
#endif /* CUPS_DEBUG */
3584
0
    yflip = 0;
3585
0
  }
3586
0
      }
3587
0
      else if (cups->header.Duplex &&
3588
0
         ((!cups->header.Tumble &&
3589
0
     (cups->PPD->flip_duplex ||
3590
0
      (backside && !strcasecmp(backside->value, "Rotated")))) ||
3591
0
    (cups->header.Tumble &&
3592
0
     (backside && !strcasecmp(backside->value, "ManualTumble")))) &&
3593
0
         !(cups->page & 1))
3594
0
      {
3595
0
  xflip = 1;
3596
0
  if (backsiderequiresflippedmargins &&
3597
0
      !strcasecmp(backsiderequiresflippedmargins->value, "True")) {
3598
#ifdef CUPS_DEBUG
3599
          dmprintf(pdev->memory, "DEBUG2: (3) Flip: X=1 Y=0\n");
3600
#endif /* CUPS_DEBUG */
3601
0
    yflip = 0;
3602
0
  } else {
3603
#ifdef CUPS_DEBUG
3604
          dmprintf(pdev->memory, "DEBUG2: (3) Flip: X=1 Y=1\n");
3605
#endif /* CUPS_DEBUG */
3606
0
    yflip = 1;
3607
0
  }
3608
0
      }
3609
0
      else
3610
0
      {
3611
#ifdef CUPS_DEBUG
3612
        dmprintf(pdev->memory, "DEBUG2: (4) Flip: X=0 Y=0\n");
3613
#endif /* CUPS_DEBUG */
3614
0
  xflip = 0;
3615
0
  yflip = 0;
3616
0
      }
3617
3618
     /*
3619
      * Find the matching page size...
3620
      */
3621
3622
0
#define LONG_EDGE_LENGTH_MATCH_LIMIT  0.01
3623
0
#define SHORT_EDGE_LENGTH_MATCH_LIMIT 0.01
3624
0
#define PAGESIZE_SCORE_SIZE_MARGINS   2
3625
0
#define PAGESIZE_SCORE_SIZE           1
3626
3627
0
      best_score = -1;
3628
0
      best_size = NULL;
3629
      /* Match against the PPD's page size only if the page size name does
3630
   not suggest that we use a custom page size */
3631
0
      if (strncasecmp(cups->header.cupsPageSizeName, "Custom", 6) != 0 ||
3632
0
    (cups->header.cupsPageSizeName[6] != '\0' &&
3633
0
     cups->header.cupsPageSizeName[6] != '.'))
3634
0
      {
3635
0
#ifdef CUPS_RASTER_SYNCv1
3636
       /*
3637
  * Chack whether cupsPageSizeName has a valid value
3638
  */
3639
3640
0
  if (strlen(cups->header.cupsPageSizeName) != 0) {
3641
0
    found = 0;
3642
0
    for (i = cups->PPD->num_sizes, size = cups->PPD->sizes;
3643
0
         i > 0;
3644
0
         i --, size ++)
3645
0
      if (strcasecmp(cups->header.cupsPageSizeName, size->name) == 0) {
3646
0
        found = 1;
3647
0
        break;
3648
0
      }
3649
0
    if (found == 0) cups->header.cupsPageSizeName[0] = '\0';
3650
0
  }
3651
#ifdef CUPS_DEBUG
3652
  dmprintf1(pdev->memory, "DEBUG2: cups->header.cupsPageSizeName = %s\n",
3653
      cups->header.cupsPageSizeName);
3654
#endif /* CUPS_DEBUG */
3655
0
#endif /* CUPS_RASTER_SYNCv1 */
3656
3657
0
  for (i = cups->PPD->num_sizes, size = cups->PPD->sizes;
3658
0
       i > 0;
3659
0
       i --, size ++)
3660
0
        {
3661
0
    if (size->length == 0 || size->width == 0) continue;
3662
3663
0
    score = 0;
3664
0
    size_matched = 0;
3665
0
    margins_matched = 0;
3666
0
    imageable_area_matched = 0;
3667
#ifdef CUPS_DEBUG
3668
    name_requested_matched = 0;
3669
#endif
3670
3671
0
    long_edge_mismatch =
3672
0
      fabs(cups->MediaSize[1] - size->length)/size->length +
3673
0
      LONG_EDGE_LENGTH_MATCH_LIMIT / 100;
3674
0
    short_edge_mismatch =
3675
0
      fabs(cups->MediaSize[0] - size->width)/size->width +
3676
0
      SHORT_EDGE_LENGTH_MATCH_LIMIT / 100;
3677
0
    if (size->length < size->width)
3678
0
    {
3679
0
      swap = long_edge_mismatch;
3680
0
      long_edge_mismatch = short_edge_mismatch;
3681
0
      short_edge_mismatch = swap;
3682
0
    }
3683
3684
0
    if (long_edge_mismatch < LONG_EDGE_LENGTH_MATCH_LIMIT &&
3685
0
        short_edge_mismatch < SHORT_EDGE_LENGTH_MATCH_LIMIT)
3686
0
    {
3687
0
      size_matched = 1;
3688
      /* If two sizes match within the limits, take the one with less
3689
         mismatch */
3690
0
      score = (long)(9999.0 -
3691
0
         long_edge_mismatch * short_edge_mismatch * 9999.0 /
3692
0
         LONG_EDGE_LENGTH_MATCH_LIMIT /
3693
0
         SHORT_EDGE_LENGTH_MATCH_LIMIT);
3694
0
      if (score < 0) score = 0;
3695
      /* We check whether all 4 margins match with the margin info
3696
         of the page size in the PPD. Here we check also for swapped
3697
         left/right and top/bottom margins as the cups->HWMargins
3698
         info can be from the previous page and there the margins
3699
         can be swapped due to duplex printing requirements */
3700
0
      if (!margins_set ||
3701
0
    (((fabs(cups->HWMargins[0] - size->left) < 1.0 &&
3702
0
       fabs(cups->HWMargins[2] - size->width + size->right) < 1.0) ||
3703
0
      (fabs(cups->HWMargins[0] - size->width + size->right) < 1.0 &&
3704
0
       fabs(cups->HWMargins[2] - size->left) < 1.0)) &&
3705
0
     ((fabs(cups->HWMargins[1] - size->bottom) < 1.0 &&
3706
0
       fabs(cups->HWMargins[3] - size->length + size->top) < 1.0) ||
3707
0
      (fabs(cups->HWMargins[1] - size->length + size->top) < 1.0 &&
3708
0
       fabs(cups->HWMargins[3] - size->bottom) < 1.0))))
3709
0
        margins_matched = 1;
3710
0
    } else {
3711
      /* Compare the dimensions of the imageable area against the
3712
         the input page size */
3713
0
      long_edge_mismatch =
3714
0
        fabs(cups->MediaSize[1] - size->top + size->bottom)/size->length +
3715
0
        LONG_EDGE_LENGTH_MATCH_LIMIT / 100;
3716
0
      short_edge_mismatch =
3717
0
        fabs(cups->MediaSize[0] - size->right + size->left)/size->width +
3718
0
        SHORT_EDGE_LENGTH_MATCH_LIMIT / 100;
3719
0
      if (size->length < size->width)
3720
0
      {
3721
0
        swap = long_edge_mismatch;
3722
0
        long_edge_mismatch = short_edge_mismatch;
3723
0
        short_edge_mismatch = swap;
3724
0
      }
3725
3726
0
      if (long_edge_mismatch < LONG_EDGE_LENGTH_MATCH_LIMIT &&
3727
0
    short_edge_mismatch < SHORT_EDGE_LENGTH_MATCH_LIMIT)
3728
0
      {
3729
0
        imageable_area_matched = 1;
3730
        /* If two sizes match within the limits, take the one with less
3731
     mismatch */
3732
0
        score = (long)(4999.0 -
3733
0
           long_edge_mismatch * short_edge_mismatch * 4999.0 /
3734
0
           LONG_EDGE_LENGTH_MATCH_LIMIT /
3735
0
           SHORT_EDGE_LENGTH_MATCH_LIMIT);
3736
0
        if (score < 0) score = 0;
3737
0
      }
3738
0
    }
3739
3740
0
    if (margins_matched)
3741
0
      score += PAGESIZE_SCORE_SIZE_MARGINS * 10000;
3742
0
    else if (size_matched)
3743
0
      score += PAGESIZE_SCORE_SIZE * 10000;
3744
3745
0
    if (size_matched || imageable_area_matched) {
3746
0
      if (!strcasecmp(cups->pageSizeRequested, size->name))
3747
0
      {
3748
#ifdef CUPS_DEBUG
3749
        name_requested_matched = 1;
3750
#endif
3751
0
      }
3752
0
      else
3753
0
        score -= 1000;
3754
0
    }
3755
3756
0
    if (score > best_score)
3757
0
    {
3758
0
      best_score = score;
3759
0
      if (score > 0)
3760
0
        best_size = size;
3761
0
    }
3762
#ifdef CUPS_DEBUG
3763
    dmprintf1(pdev->memory, "DEBUG2: Checking against PPD page size (portrait): %s\n",
3764
        size->name);
3765
    dmprintf2(pdev->memory, "DEBUG2:    Width: %.2f; Height: %.2f\n",
3766
        size->width, size->length);
3767
    dmprintf4(pdev->memory, "DEBUG2:    Margins: Left: %.2f; Right: %.2f; Top: %.2f; Bottom: %.2f\n",
3768
        size->left, size->right, size->top, size->bottom);
3769
    dmprintf4(pdev->memory, "DEBUG2:    Size mismatch: Long Edge (%.3f): %.5f; Short Edge (%.3f): %.5f\n",
3770
        LONG_EDGE_LENGTH_MATCH_LIMIT, long_edge_mismatch,
3771
        SHORT_EDGE_LENGTH_MATCH_LIMIT, short_edge_mismatch);
3772
    dmprintf4(pdev->memory, "DEBUG2:    Match: Size: %d; Margins: %d; Imageable Area: %d; Name requested: %d\n",
3773
        size_matched, margins_matched, imageable_area_matched,
3774
        name_requested_matched);
3775
    dmprintf2(pdev->memory, "DEBUG2:    Score: %ld; Best Score: %ld\n",
3776
        score, best_score);
3777
#endif /* CUPS_DEBUG */
3778
0
  }
3779
3780
0
  if (best_size)
3781
0
  {
3782
   /*
3783
    * Standard size...
3784
    */
3785
3786
#ifdef CUPS_DEBUG
3787
    dmprintf1(pdev->memory, "DEBUG: size = %s\n", best_size->name);
3788
#endif /* CUPS_DEBUG */
3789
3790
0
    mediasize[0] = best_size->width;
3791
0
    mediasize[1] = best_size->length;
3792
3793
0
    cups->landscape = 0;
3794
3795
0
#ifdef CUPS_RASTER_SYNCv1
3796
0
    strncpy(cups->header.cupsPageSizeName, best_size->name,
3797
0
      sizeof(cups->header.cupsPageSizeName));
3798
0
    cups->header.cupsPageSizeName[sizeof(cups->header.cupsPageSizeName) - 1] =
3799
0
      '\0';
3800
3801
0
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
3802
0
    {
3803
0
#endif
3804
0
      margins[0] = best_size->left / 72.0;
3805
0
      margins[1] = best_size->bottom / 72.0;
3806
0
      margins[2] = (best_size->width - best_size->right) / 72.0;
3807
0
      margins[3] = (best_size->length - best_size->top) / 72.0;
3808
0
      if (xflip == 1)
3809
0
      {
3810
0
        swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
3811
0
      }
3812
0
      if (yflip == 1)
3813
0
      {
3814
0
        swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
3815
0
      }
3816
0
#ifdef CUPS_RASTER_SYNCv1
3817
0
    }
3818
0
    else
3819
0
    {
3820
0
      margins[0] = 0.0;
3821
0
      margins[1] = 0.0;
3822
0
      margins[2] = 0.0;
3823
0
      margins[3] = 0.0;
3824
0
    }
3825
0
#endif
3826
0
  }
3827
0
  else
3828
0
  {
3829
   /*
3830
    * No matching portrait size; look for a matching size in
3831
    * landscape orientation...
3832
    */
3833
3834
0
    best_score = -1;
3835
0
    best_size = NULL;
3836
0
    for (i = cups->PPD->num_sizes, size = cups->PPD->sizes;
3837
0
         i > 0;
3838
0
         i --, size ++)
3839
0
    {
3840
0
      if (size->length == 0 || size->width == 0) continue;
3841
3842
0
      score = 0;
3843
0
      size_matched = 0;
3844
0
      margins_matched = 0;
3845
0
      imageable_area_matched = 0;
3846
#ifdef CUPS_DEBUG
3847
      name_requested_matched = 0;
3848
#endif
3849
3850
0
      long_edge_mismatch =
3851
0
        fabs(cups->MediaSize[0] - size->length)/size->length +
3852
0
        LONG_EDGE_LENGTH_MATCH_LIMIT / 100;
3853
0
      short_edge_mismatch =
3854
0
        fabs(cups->MediaSize[1] - size->width)/size->width +
3855
0
        SHORT_EDGE_LENGTH_MATCH_LIMIT / 100;
3856
0
      if (size->length < size->width)
3857
0
      {
3858
0
        swap = long_edge_mismatch;
3859
0
        long_edge_mismatch = short_edge_mismatch;
3860
0
        short_edge_mismatch = swap;
3861
0
      }
3862
3863
0
      if (long_edge_mismatch < LONG_EDGE_LENGTH_MATCH_LIMIT &&
3864
0
    short_edge_mismatch < SHORT_EDGE_LENGTH_MATCH_LIMIT)
3865
0
      {
3866
0
        size_matched = 1;
3867
        /* If two sizes match within the limits, take the one with less
3868
     mismatch */
3869
0
        score = (long)(9999.0 -
3870
0
           long_edge_mismatch * short_edge_mismatch * 9999.0 /
3871
0
           LONG_EDGE_LENGTH_MATCH_LIMIT /
3872
0
           SHORT_EDGE_LENGTH_MATCH_LIMIT);
3873
0
        if (score < 0) score = 0;
3874
        /* We check whether all 4 margins match with the margin info
3875
     of the page size in the PPD. Here we check also for swapped
3876
     left/right and top/bottom margins as the cups->HWMargins
3877
     info can be from the previous page and there the margins
3878
     can be swapped due to duplex printing requirements */
3879
0
        if (!margins_set ||
3880
0
      (((fabs(cups->HWMargins[1] - size->left) < 1.0 &&
3881
0
         fabs(cups->HWMargins[3] - size->width + size->right) < 1.0)||
3882
0
        (fabs(cups->HWMargins[1] - size->width + size->right) < 1.0 &&
3883
0
         fabs(cups->HWMargins[3] - size->left) < 1.0)) &&
3884
0
       ((fabs(cups->HWMargins[0] - size->bottom) < 1.0 &&
3885
0
         fabs(cups->HWMargins[2] - size->length + size->top) < 1.0) ||
3886
0
        (fabs(cups->HWMargins[0] - size->length + size->top) < 1.0 &&
3887
0
         fabs(cups->HWMargins[2] - size->bottom) < 1.0))))
3888
0
    margins_matched = 1;
3889
0
      } else {
3890
        /* Compare the dimensions of the imageable area against the
3891
     the input page size */
3892
0
        long_edge_mismatch =
3893
0
    fabs(cups->MediaSize[0] - size->top + size->bottom)/size->length +
3894
0
    LONG_EDGE_LENGTH_MATCH_LIMIT / 100;
3895
0
        short_edge_mismatch =
3896
0
    fabs(cups->MediaSize[1] - size->right + size->left)/size->width +
3897
0
    SHORT_EDGE_LENGTH_MATCH_LIMIT / 100;
3898
0
        if (size->length < size->width)
3899
0
        {
3900
0
    swap = long_edge_mismatch;
3901
0
    long_edge_mismatch = short_edge_mismatch;
3902
0
    short_edge_mismatch = swap;
3903
0
        }
3904
3905
0
        if (long_edge_mismatch < LONG_EDGE_LENGTH_MATCH_LIMIT &&
3906
0
      short_edge_mismatch < SHORT_EDGE_LENGTH_MATCH_LIMIT)
3907
0
        {
3908
0
    imageable_area_matched = 1;
3909
    /* If two sizes match within the limits, take the one with less
3910
       mismatch */
3911
0
    score = (long)(4999.0 -
3912
0
             long_edge_mismatch * short_edge_mismatch * 4999.0 /
3913
0
             LONG_EDGE_LENGTH_MATCH_LIMIT /
3914
0
             SHORT_EDGE_LENGTH_MATCH_LIMIT);
3915
0
    if (score < 0) score = 0;
3916
0
        }
3917
0
      }
3918
3919
0
      if (margins_matched)
3920
0
        score += PAGESIZE_SCORE_SIZE_MARGINS * 10000;
3921
0
      else if (size_matched)
3922
0
        score += PAGESIZE_SCORE_SIZE * 10000;
3923
3924
0
      if (size_matched || imageable_area_matched) {
3925
0
        if (!strcasecmp(cups->pageSizeRequested, size->name))
3926
0
        {
3927
#ifdef CUPS_DEBUG
3928
    name_requested_matched = 1;
3929
#endif
3930
0
        }
3931
0
        else
3932
0
    score -= 1000;
3933
0
      }
3934
3935
0
      if (score > best_score)
3936
0
      {
3937
0
        best_score = score;
3938
0
        if (score > 0)
3939
0
    best_size = size;
3940
0
      }
3941
#ifdef CUPS_DEBUG
3942
      dmprintf1(pdev->memory, "DEBUG2: Checking against PPD page size (landscape): %s\n",
3943
          size->name);
3944
      dmprintf2(pdev->memory, "DEBUG2:    Width: %.2f; Height: %.2f\n",
3945
          size->width, size->length);
3946
      dmprintf4(pdev->memory, "DEBUG2:    Margins: Left: %.2f; Right: %.2f; Top: %.2f; Bottom: %.2f\n",
3947
          size->left, size->right, size->top, size->bottom);
3948
      dmprintf4(pdev->memory, "DEBUG2:    Size mismatch: Long Edge (%.3f): %.5f; Short Edge (%.3f): %.5f\n",
3949
          LONG_EDGE_LENGTH_MATCH_LIMIT, long_edge_mismatch,
3950
          SHORT_EDGE_LENGTH_MATCH_LIMIT, short_edge_mismatch);
3951
      dmprintf4(pdev->memory, "DEBUG2:    Match: Size: %d; Margins: %d; Imageable Area: %d; Name requested: %d\n",
3952
          size_matched, margins_matched, imageable_area_matched,
3953
          name_requested_matched);
3954
      dmprintf2(pdev->memory, "DEBUG2:    Score: %ld; Best Score: %ld\n",
3955
          score, best_score);
3956
#endif /* CUPS_DEBUG */
3957
0
    }
3958
3959
0
    if (best_size)
3960
0
    {
3961
     /*
3962
      * Standard size in landscape orientation...
3963
      */
3964
3965
#ifdef CUPS_DEBUG
3966
      dmprintf1(pdev->memory, "DEBUG: landscape size = %s\n", best_size->name);
3967
#endif /* CUPS_DEBUG */
3968
3969
0
      mediasize[0] = best_size->length;
3970
0
      mediasize[1] = best_size->width;
3971
3972
0
      cups->landscape = 1;
3973
3974
0
#ifdef CUPS_RASTER_SYNCv1
3975
0
      strncpy(cups->header.cupsPageSizeName, best_size->name,
3976
0
        sizeof(cups->header.cupsPageSizeName));
3977
0
      cups->header.cupsPageSizeName[sizeof(cups->header.cupsPageSizeName) - 1] =
3978
0
        '\0';
3979
3980
0
      if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
3981
0
      {
3982
0
#endif
3983
0
        margins[0] = (best_size->length - best_size->top) / 72.0;
3984
0
        margins[1] = best_size->left / 72.0;
3985
0
        margins[2] = best_size->bottom / 72.0;
3986
0
        margins[3] = (best_size->width - best_size->right) / 72.0;
3987
0
        if (xflip == 1)
3988
0
        {
3989
0
    swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
3990
0
        }
3991
0
        if (yflip == 1)
3992
0
        {
3993
0
    swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
3994
0
        }
3995
0
#ifdef CUPS_RASTER_SYNCv1
3996
0
      }
3997
0
      else
3998
0
      {
3999
0
        margins[0] = 0.0;
4000
0
        margins[1] = 0.0;
4001
0
        margins[2] = 0.0;
4002
0
        margins[3] = 0.0;
4003
0
      }
4004
0
#endif
4005
0
    }
4006
0
  }
4007
0
      }
4008
4009
0
      if (!best_size)
4010
0
      {
4011
       /*
4012
  * Custom size...
4013
  */
4014
4015
#ifdef CUPS_DEBUG
4016
  dmprintf(pdev->memory, "DEBUG: size = Custom\n");
4017
#endif /* CUPS_DEBUG */
4018
4019
0
#ifdef CUPS_RASTER_SYNCv1
4020
0
  snprintf(cups->header.cupsPageSizeName,
4021
0
     sizeof(cups->header.cupsPageSizeName),
4022
0
     "Custom.%.2fx%.2f",
4023
0
     cups->MediaSize[0], cups->MediaSize[1]);
4024
0
#endif
4025
4026
  /* Rotate page if it only fits into the printer's dimensions
4027
     when rotated */
4028
0
  if (((cups->MediaSize[0] > cups->PPD->custom_max[0]) ||
4029
0
       (cups->MediaSize[1] > cups->PPD->custom_max[1])) &&
4030
0
      ((cups->MediaSize[0] <= cups->PPD->custom_max[1]) &&
4031
0
       (cups->MediaSize[1] <= cups->PPD->custom_max[0]))) {
4032
    /* Rotate */
4033
0
    mediasize[0] = cups->MediaSize[1];
4034
0
    mediasize[1] = cups->MediaSize[0];
4035
4036
0
    cups->landscape = 1;
4037
4038
0
#ifdef CUPS_RASTER_SYNCv1
4039
0
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4040
0
    {
4041
0
#endif
4042
0
      margins[0] = cups->PPD->custom_margins[3] / 72.0;
4043
0
      margins[1] = cups->PPD->custom_margins[0] / 72.0;
4044
0
      margins[2] = cups->PPD->custom_margins[1] / 72.0;
4045
0
      margins[3] = cups->PPD->custom_margins[2] / 72.0;
4046
0
      if (xflip == 1)
4047
0
      {
4048
0
        swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
4049
0
      }
4050
0
      if (yflip == 1)
4051
0
      {
4052
0
        swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
4053
0
      }
4054
0
#ifdef CUPS_RASTER_SYNCv1
4055
0
    }
4056
0
    else
4057
0
    {
4058
0
      margins[0] = 0.0;
4059
0
      margins[1] = 0.0;
4060
0
      margins[2] = 0.0;
4061
0
      margins[3] = 0.0;
4062
0
    }
4063
0
#endif
4064
0
  }
4065
0
  else
4066
0
  {
4067
    /* Do not rotate */
4068
0
    mediasize[0] = cups->MediaSize[0];
4069
0
    mediasize[1] = cups->MediaSize[1];
4070
4071
0
    cups->landscape = 0;
4072
4073
0
#ifdef CUPS_RASTER_SYNCv1
4074
0
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4075
0
    {
4076
0
#endif
4077
0
      for (i = 0; i < 4; i ++)
4078
0
        margins[i] = cups->PPD->custom_margins[i] / 72.0;
4079
0
      if (xflip == 1)
4080
0
      {
4081
0
        swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
4082
0
      }
4083
0
      if (yflip == 1)
4084
0
      {
4085
0
        swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
4086
0
      }
4087
0
#ifdef CUPS_RASTER_SYNCv1
4088
0
    }
4089
0
    else
4090
0
    {
4091
0
      margins[0] = 0.0;
4092
0
      margins[1] = 0.0;
4093
0
      margins[2] = 0.0;
4094
0
      margins[3] = 0.0;
4095
0
    }
4096
0
#endif
4097
0
  }
4098
0
      }
4099
4100
#ifdef CUPS_DEBUG
4101
      dmprintf4(pdev->memory, "DEBUG: margins[] = [ %f %f %f %f ]\n",
4102
                margins[0], margins[1], margins[2], margins[3]);
4103
#endif /* CUPS_DEBUG */
4104
0
    }
4105
185k
    else
4106
185k
    {
4107
      /* No PPD file available */
4108
#ifdef CUPS_DEBUG
4109
      dmprintf1(pdev->memory, "DEBUG2: cups->header.Duplex = %d\n", cups->header.Duplex);
4110
      dmprintf1(pdev->memory, "DEBUG2: cups->header.Tumble = %d\n", cups->header.Tumble);
4111
      dmprintf1(pdev->memory, "DEBUG2: cups->page = %d\n", cups->page);
4112
#endif /* CUPS_DEBUG */
4113
4114
#ifdef CUPS_DEBUG
4115
      dmprintf1(pdev->memory, "DEBUG2: cupsBackSideOrientation = %s\n",
4116
    cups->cupsBackSideOrientation);
4117
#endif /* CUPS_DEBUG */
4118
4119
#ifdef CUPS_DEBUG
4120
      if (cups->cupsBackSideFlipMargins)
4121
        dmprintf0(pdev->memory, "DEBUG2: Duplex requires flipped margins\n");
4122
#endif /* CUPS_DEBUG */
4123
4124
185k
      if (cups->header.Duplex &&
4125
0
    (cups->header.Tumble &&
4126
0
     (!strcasecmp(cups->cupsBackSideOrientation, "Flipped"))) &&
4127
0
    !(cups->page & 1))
4128
0
      {
4129
0
  xflip = 1;
4130
0
  if (!cups->cupsBackSideFlipMargins) {
4131
#ifdef CUPS_DEBUG
4132
          dmprintf(pdev->memory, "DEBUG2: (1) Flip: X=1 Y=0\n");
4133
#endif /* CUPS_DEBUG */
4134
0
    yflip = 0;
4135
0
  } else {
4136
#ifdef CUPS_DEBUG
4137
          dmprintf(pdev->memory, "DEBUG2: (1) Flip: X=1 Y=1\n");
4138
#endif /* CUPS_DEBUG */
4139
0
    yflip = 1;
4140
0
  }
4141
0
      }
4142
185k
      else if (cups->header.Duplex &&
4143
0
         (!cups->header.Tumble &&
4144
0
    (!strcasecmp(cups->cupsBackSideOrientation, "Flipped"))) &&
4145
0
         !(cups->page & 1))
4146
0
      {
4147
0
  xflip = 0;
4148
0
  if (!cups->cupsBackSideFlipMargins) {
4149
#ifdef CUPS_DEBUG
4150
          dmprintf(pdev->memory, "DEBUG2: (2) Flip: X=0 Y=1\n");
4151
#endif /* CUPS_DEBUG */
4152
0
    yflip = 1;
4153
0
  } else {
4154
#ifdef CUPS_DEBUG
4155
          dmprintf(pdev->memory, "DEBUG2: (2) Flip: X=0 Y=0\n");
4156
#endif /* CUPS_DEBUG */
4157
0
    yflip = 0;
4158
0
  }
4159
0
      }
4160
185k
      else if (cups->header.Duplex &&
4161
0
         ((!cups->header.Tumble &&
4162
0
     (!strcasecmp(cups->cupsBackSideOrientation, "Rotated"))) ||
4163
0
    (cups->header.Tumble &&
4164
0
     (!strcasecmp(cups->cupsBackSideOrientation, "ManualTumble")))) &&
4165
0
         !(cups->page & 1))
4166
0
      {
4167
0
  xflip = 1;
4168
0
  if (cups->cupsBackSideFlipMargins) {
4169
#ifdef CUPS_DEBUG
4170
          dmprintf(pdev->memory, "DEBUG2: (3) Flip: X=1 Y=0\n");
4171
#endif /* CUPS_DEBUG */
4172
0
    yflip = 0;
4173
0
  } else {
4174
#ifdef CUPS_DEBUG
4175
          dmprintf(pdev->memory, "DEBUG2: (3) Flip: X=1 Y=1\n");
4176
#endif /* CUPS_DEBUG */
4177
0
    yflip = 1;
4178
0
  }
4179
0
      }
4180
185k
      else
4181
185k
      {
4182
#ifdef CUPS_DEBUG
4183
        dmprintf(pdev->memory, "DEBUG2: (4) Flip: X=0 Y=0\n");
4184
#endif /* CUPS_DEBUG */
4185
185k
  xflip = 0;
4186
185k
  yflip = 0;
4187
185k
      }
4188
185k
      mediasize[0] = cups->MediaSize[0];
4189
185k
      mediasize[1] = cups->MediaSize[1];
4190
185k
#ifdef CUPS_RASTER_SYNCv1
4191
185k
      if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4192
185k
      {
4193
185k
#endif
4194
  /* If we do not have a PPD file, make sure that margins given via the
4195
     input file or via something like
4196
     "-c '<</.HWMargins[12 12 12 12] /Margins[0 0]>>setpagedevice'"
4197
     on the command line are conserved */
4198
185k
  margins[0] = pdev->HWMargins[0] / 72.0;
4199
185k
  margins[1] = pdev->HWMargins[1] / 72.0;
4200
185k
  margins[2] = pdev->HWMargins[2] / 72.0;
4201
185k
  margins[3] = pdev->HWMargins[3] / 72.0;
4202
185k
  if (xflip == 1)
4203
0
  {
4204
0
    swap = margins[0]; margins[0] = margins[2]; margins[2] = swap;
4205
0
  }
4206
185k
  if (yflip == 1)
4207
0
  {
4208
0
    swap = margins[1]; margins[1] = margins[3]; margins[3] = swap;
4209
0
  }
4210
185k
#ifdef CUPS_RASTER_SYNCv1
4211
185k
      }
4212
0
      else
4213
0
      {
4214
0
  margins[0] = 0.0;
4215
0
  margins[1] = 0.0;
4216
0
  margins[2] = 0.0;
4217
0
  margins[3] = 0.0;
4218
0
      }
4219
185k
#endif
4220
185k
    }
4221
4222
   /*
4223
    * Set the media size and margins to update the bitmap size...
4224
    */
4225
4226
556k
    for (i = 0; i < 2; i ++)
4227
371k
      cups_mediasize[i] = mediasize[i];
4228
927k
    for (i = 0; i < 4; i ++)
4229
742k
      cups_margins[i] = margins[i] * 72.0;
4230
185k
    if (best_score > 0 && best_score < 5000) {
4231
#ifdef CUPS_DEBUG
4232
      dmputs(pdev->memory, "DEBUG: Imageable area fit!\n");
4233
#endif /* CUPS_DEBUG */
4234
      /* Page size matched by imageable area */
4235
0
      for (i = 0; i < 2; i ++)
4236
0
  mediasize[i] = cups->MediaSize[i];
4237
0
      for (i = 0; i < 4; i ++)
4238
0
  margins[i] = 0.0;
4239
0
    }
4240
185k
    gx_device_set_media_size(pdev, mediasize[0], mediasize[1]);
4241
185k
    gx_device_set_margins(pdev, margins, false);
4242
185k
  } else {
4243
    /* No size change, use the current size in CUPS Raster header */
4244
236k
    for (i = 0; i < 2; i ++)
4245
157k
      cups_mediasize[i] = pdev->MediaSize[i];
4246
394k
    for (i = 0; i < 4; i ++)
4247
315k
      cups_margins[i] = pdev->HWMargins[i];
4248
78.8k
  }
4249
4250
 /*
4251
  * Reallocate memory if the size or color depth was changed...
4252
  */
4253
4254
264k
  if (color_set || size_set)
4255
215k
  {
4256
   /*
4257
    * Make sure the page image is the correct size - current Ghostscript
4258
    * does not keep track of the margins in the bitmap size...
4259
    */
4260
4261
215k
    if (cups->landscape)
4262
0
    {
4263
0
      width  = (int)((pdev->MediaSize[1] - pdev->HWMargins[1] - pdev->HWMargins[3]) *
4264
0
                     pdev->HWResolution[0] / 72.0f + 0.499f);
4265
0
      height = (int)((pdev->MediaSize[0] - pdev->HWMargins[0] - pdev->HWMargins[2]) *
4266
0
                     pdev->HWResolution[1] / 72.0f + 0.499f);
4267
0
    }
4268
215k
    else
4269
215k
    {
4270
215k
      width  = (int)((pdev->MediaSize[0] - pdev->HWMargins[0] - pdev->HWMargins[2]) *
4271
215k
                     pdev->HWResolution[0] / 72.0f + 0.499f);
4272
215k
      height = (int)((pdev->MediaSize[1] - pdev->HWMargins[1] - pdev->HWMargins[3]) *
4273
215k
                     pdev->HWResolution[1] / 72.0f + 0.499f);
4274
215k
    }
4275
4276
215k
    if (width <= 0 || height <= 0) {
4277
2
      dmprintf(pdev->memory, "ERROR: page margins overlap\n");
4278
2
      return_error(gs_error_rangecheck);
4279
2
    }
4280
4281
214k
#ifdef CUPS_RASTER_SYNCv1
4282
214k
    if (cups->header.cupsBorderlessScalingFactor > 1.0)
4283
0
    {
4284
0
      width  = (int)(width * cups->header.cupsBorderlessScalingFactor);
4285
0
      height = (int)(height * cups->header.cupsBorderlessScalingFactor);
4286
0
    }
4287
214k
#endif /* CUPS_RASTER_SYNCv1 */
4288
4289
214k
    pdev->width  = width;
4290
214k
    pdev->height = height;
4291
4292
   /*
4293
    * Don't reallocate memory unless the device has been opened...
4294
    * Also reallocate only if the size has actually changed...
4295
    */
4296
4297
214k
    if (pdev->is_open)
4298
185k
    {
4299
4300
     /*
4301
      * Device is open and size has changed, so reallocate...
4302
      */
4303
4304
#ifdef CUPS_DEBUG
4305
      dmprintf4(pdev->memory, "DEBUG2: Reallocating memory, [%.0f %.0f] = %dx%d pixels...\n",
4306
                pdev->MediaSize[0], pdev->MediaSize[1], width, height);
4307
#endif /* CUPS_DEBUG */
4308
4309
185k
      if ((code = gdev_prn_maybe_realloc_memory((gx_device_printer *)pdev,
4310
185k
                                                &sp_old,
4311
185k
            width_old, height_old,
4312
185k
            transp_old))
4313
185k
    < 0)
4314
0
        goto done;
4315
#ifdef CUPS_DEBUG
4316
      dmprintf4(pdev->memory, "DEBUG2: Reallocated memory, [%.0f %.0f] = %dx%d pixels...\n",
4317
                pdev->MediaSize[0], pdev->MediaSize[1], width, height);
4318
#endif /* CUPS_DEBUG */
4319
185k
    }
4320
29.4k
    else
4321
29.4k
    {
4322
     /*
4323
      * Device isn't yet open, so just save the new width and height...
4324
      */
4325
4326
#ifdef CUPS_DEBUG
4327
      dmprintf4(pdev->memory, "DEBUG: Setting initial media size, [%.0f %.0f] = %dx%d pixels...\n",
4328
                pdev->MediaSize[0], pdev->MediaSize[1], width, height);
4329
#endif /* CUPS_DEBUG */
4330
4331
29.4k
      pdev->width  = width;
4332
29.4k
      pdev->height = height;
4333
29.4k
    }
4334
214k
  }
4335
4336
 /*
4337
  * Set CUPS raster header values...
4338
  */
4339
4340
264k
  cups->header.HWResolution[0] = (unsigned int)pdev->HWResolution[0];
4341
264k
  cups->header.HWResolution[1] = (unsigned int)pdev->HWResolution[1];
4342
4343
264k
#ifdef CUPS_RASTER_SYNCv1
4344
4345
264k
  if (cups->landscape)
4346
0
  {
4347
0
    cups->header.cupsPageSize[0] = cups_mediasize[1];
4348
0
    cups->header.cupsPageSize[1] = cups_mediasize[0];
4349
4350
0
    if ((sf = cups->header.cupsBorderlessScalingFactor) < 1.0)
4351
0
      sf = 1.0;
4352
4353
0
    cups->header.PageSize[0] = (unsigned int)((cups_mediasize[1] * sf) + 0.5);
4354
0
    cups->header.PageSize[1] = (unsigned int)((cups_mediasize[0] * sf) + 0.5);
4355
4356
0
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4357
0
    {
4358
0
      cups->header.Margins[0] = (unsigned int)((cups_margins[1] * sf) + 0.5);
4359
0
      cups->header.Margins[1] = (unsigned int)((cups_margins[2] * sf) + 0.5);
4360
0
      cups->header.ImagingBoundingBox[0] =
4361
0
                                (unsigned int)((cups_margins[1] * sf) + 0.5);
4362
0
      cups->header.ImagingBoundingBox[1] =
4363
0
                                (unsigned int)((cups_margins[2] * sf) + 0.5);
4364
0
      cups->header.ImagingBoundingBox[2] =
4365
0
                                (unsigned int)(((cups_mediasize[1] -
4366
0
                                                 cups_margins[3]) * sf) + 0.5);
4367
0
      cups->header.ImagingBoundingBox[3] =
4368
0
                                (unsigned int)(((cups_mediasize[0] -
4369
0
                                                 cups_margins[0]) * sf) + 0.5);
4370
0
      cups->header.cupsImagingBBox[0] = cups_margins[1];
4371
0
      cups->header.cupsImagingBBox[1] = cups_margins[2];
4372
0
      cups->header.cupsImagingBBox[2] = cups_mediasize[1] - cups_margins[3];
4373
0
      cups->header.cupsImagingBBox[3] = cups_mediasize[0] - cups_margins[0];
4374
0
    }
4375
0
    else
4376
0
    {
4377
0
      for (i = 0; i < 2; i ++)
4378
0
  cups->header.Margins[i] = 0;
4379
0
      for (i = 0; i < 4; i ++)
4380
0
      {
4381
0
  cups->header.ImagingBoundingBox[i] = 0;
4382
0
  cups->header.cupsImagingBBox[i] = 0.0;
4383
0
      }
4384
0
    }
4385
0
  }
4386
264k
  else
4387
264k
  {
4388
264k
    cups->header.cupsPageSize[0] = cups_mediasize[0];
4389
264k
    cups->header.cupsPageSize[1] = cups_mediasize[1];
4390
4391
264k
    if ((sf = cups->header.cupsBorderlessScalingFactor) < 1.0)
4392
0
      sf = 1.0;
4393
4394
264k
    cups->header.PageSize[0] = (unsigned int)((cups_mediasize[0] * sf) + 0.5);
4395
264k
    cups->header.PageSize[1] = (unsigned int)((cups_mediasize[1] * sf) + 0.5);
4396
4397
264k
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4398
264k
    {
4399
264k
      cups->header.Margins[0] = (cups_margins[0] * sf) + 0.5;
4400
264k
      cups->header.Margins[1] = (cups_margins[1] * sf) + 0.5;
4401
264k
      cups->header.ImagingBoundingBox[0] =
4402
264k
                               (unsigned int)((cups_margins[0] * sf) + 0.5);
4403
264k
      cups->header.ImagingBoundingBox[1] =
4404
264k
                               (unsigned int)((cups_margins[1] * sf) + 0.5);
4405
264k
      cups->header.ImagingBoundingBox[2] =
4406
264k
                               (unsigned int)(((cups_mediasize[0] -
4407
264k
                                                cups_margins[2]) * sf) + 0.5);
4408
264k
      cups->header.ImagingBoundingBox[3] =
4409
264k
                               (unsigned int)(((cups_mediasize[1] -
4410
264k
                                                cups_margins[3]) * sf) + 0.5);
4411
264k
      cups->header.cupsImagingBBox[0] = cups_margins[0];
4412
264k
      cups->header.cupsImagingBBox[1] = cups_margins[1];
4413
264k
      cups->header.cupsImagingBBox[2] = cups_mediasize[0] - cups_margins[2];
4414
264k
      cups->header.cupsImagingBBox[3] = cups_mediasize[1] - cups_margins[3];
4415
264k
    }
4416
0
    else
4417
0
    {
4418
0
      for (i = 0; i < 2; i ++)
4419
0
  cups->header.Margins[i] = 0;
4420
0
      for (i = 0; i < 4; i ++)
4421
0
      {
4422
0
  cups->header.ImagingBoundingBox[i] = 0;
4423
0
  cups->header.cupsImagingBBox[i] = 0.0;
4424
0
      }
4425
0
    }
4426
264k
  }
4427
4428
#else
4429
4430
  if (cups->landscape)
4431
  {
4432
    cups->header.PageSize[0] = cups_mediasize[1] + 0.5;
4433
    cups->header.PageSize[1] = cups_mediasize[0] + 0.5;
4434
4435
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4436
    {
4437
      cups->header.Margins[0] = (cups_margins[1]) + 0.5;
4438
      cups->header.Margins[1] = (cups_margins[2]) + 0.5;
4439
      cups->header.ImagingBoundingBox[0] = (cups_margins[1]) + 0.5;
4440
      cups->header.ImagingBoundingBox[1] = (cups_margins[0]) + 0.5;
4441
      cups->header.ImagingBoundingBox[2] = (cups_mediasize[1] -
4442
              cups_margins[3]) + 0.5;
4443
      cups->header.ImagingBoundingBox[3] = (cups_mediasize[0] -
4444
              cups_margins[2]) + 0.5;
4445
    }
4446
    else
4447
    {
4448
      for (i = 0; i < 2; i ++)
4449
  cups->header.Margins[i] = 0;
4450
      for (i = 0; i < 4; i ++)
4451
  cups->header.ImagingBoundingBox[i] = 0;
4452
    }
4453
  }
4454
  else
4455
  {
4456
    cups->header.PageSize[0] = cups_mediasize[0] + 0.5;
4457
    cups->header.PageSize[1] = cups_mediasize[1] + 0.5;
4458
4459
    if (strcasecmp(cups->header.MediaClass, "PwgRaster") != 0)
4460
    {
4461
      cups->header.Margins[0] = (cups_margins[0]) + 0.5;
4462
      cups->header.Margins[1] = (cups_margins[1]) + 0.5;
4463
      cups->header.ImagingBoundingBox[0] = (cups_margins[0]) + 0.5;
4464
      cups->header.ImagingBoundingBox[1] = (cups_margins[3]) + 0.5;
4465
      cups->header.ImagingBoundingBox[2] = (cups_mediasize[0] -
4466
              cups_margins[2]) + 0.5;
4467
      cups->header.ImagingBoundingBox[3] = (cups_mediasize[1] -
4468
              cups_margins[1]) + 0.5;
4469
    }
4470
    else
4471
    {
4472
      for (i = 0; i < 2; i ++)
4473
  cups->header.Margins[i] = 0;
4474
      for (i = 0; i < 4; i ++)
4475
  cups->header.ImagingBoundingBox[i] = 0;
4476
    }
4477
  }
4478
4479
#endif /* CUPS_RASTER_SYNCv1 */
4480
264k
  cups->header.cupsWidth  = cups->width;
4481
264k
  cups->header.cupsHeight = cups->height;
4482
4483
#ifdef CUPS_DEBUG
4484
  if (size_set) {
4485
    dmprintf2(pdev->memory, "DEBUG2: mediasize = [ %.3f %.3f ]\n",
4486
              mediasize[0], mediasize[1]);
4487
    dmprintf4(pdev->memory, "DEBUG2: margins = [ %.3f %.3f %.3f %.3f ]\n",
4488
              margins[0], margins[1], margins[2], margins[3]);
4489
  }
4490
  dmprintf2(pdev->memory, "DEBUG2: cups_mediasize = [ %.3f %.3f ]\n",
4491
      cups_mediasize[0], cups_mediasize[1]);
4492
  dmprintf4(pdev->memory, "DEBUG2: cups_margins = [ %.3f %.3f %.3f %.3f ]\n",
4493
      cups_margins[0], cups_margins[1], cups_margins[2], cups_margins[3]);
4494
  dmprintf1(pdev->memory, "DEBUG2: ppd = %p\n", cups->PPD);
4495
  dmprintf2(pdev->memory, "DEBUG2: PageSize = [ %.3f %.3f ]\n",
4496
            pdev->MediaSize[0], pdev->MediaSize[1]);
4497
  dmprintf2(pdev->memory, "DEBUG2: HWResolution = [ %.3f %.3f ]\n",
4498
            pdev->HWResolution[0], pdev->HWResolution[1]);
4499
  dmprintf2(pdev->memory, "DEBUG2: width = %d, height = %d\n",
4500
            pdev->width, pdev->height);
4501
  dmprintf4(pdev->memory, "DEBUG2: HWMargins = [ %.3f %.3f %.3f %.3f ]\n",
4502
            pdev->HWMargins[0], pdev->HWMargins[1],
4503
            pdev->HWMargins[2], pdev->HWMargins[3]);
4504
  dmprintf2(pdev->memory, "DEBUG2: cups->header.cupsWidth = %d, cups->header.cupsHeight = %d\n",
4505
            cups->header.cupsWidth, cups->header.cupsHeight);
4506
  dmprintf2(pdev->memory, "DEBUG2: cups->header.PageSize[0] = %d, cups->header.PageSize[1] = %d\n",
4507
            cups->header.PageSize[0], cups->header.PageSize[1]);
4508
  dmprintf4(pdev->memory, "DEBUG2: cups->header.ImagingBoundingBox = [ %d %d %d %d ]\n",
4509
            cups->header.ImagingBoundingBox[0],
4510
      cups->header.ImagingBoundingBox[1],
4511
            cups->header.ImagingBoundingBox[2],
4512
      cups->header.ImagingBoundingBox[3]);
4513
#ifdef CUPS_RASTER_SYNCv1
4514
  dmprintf2(pdev->memory, "DEBUG2: cups->header.cupsPageSize[0] = %.3f, cups->header.cupsPageSize[1] = %.3f\n",
4515
            cups->header.cupsPageSize[0], cups->header.cupsPageSize[1]);
4516
  dmprintf4(pdev->memory, "DEBUG2: cups->header.cupsImagingBBox = [ %.3f %.3f %.3f %.3f ]\n",
4517
            cups->header.cupsImagingBBox[0], cups->header.cupsImagingBBox[1],
4518
            cups->header.cupsImagingBBox[2], cups->header.cupsImagingBBox[3]);
4519
  dmprintf1(pdev->memory, "DEBUG2: cups->header.cupsBorderlessScalingFactor = %.3f\n",
4520
            cups->header.cupsBorderlessScalingFactor);
4521
#endif /* CUPS_RASTER_SYNCv1 */
4522
#endif /* CUPS_DEBUG */
4523
4524
264k
done:
4525
264k
  return code;
4526
264k
}
4527
4528
/*
4529
 * 'cups_set_color_info()' - Set the color information structure based on
4530
 *                           the required output.
4531
 */
4532
4533
private int
4534
cups_set_color_info(gx_device *pdev)  /* I - Device info */
4535
293k
{
4536
293k
  int   i, j, k;    /* Looping vars */
4537
293k
  int   max_lut;    /* Maximum LUT value */
4538
293k
  float   d, g;     /* Density and gamma correction */
4539
293k
  float   m[3][3];    /* Color correction matrix */
4540
293k
  char    resolution[41];   /* Resolution string */
4541
293k
  ppd_profile_t *profile;   /* Color profile information */
4542
293k
  int           code = 0;
4543
4544
#ifdef CUPS_DEBUG
4545
  dmprintf1(pdev->memory, "DEBUG2: cups_set_color_info(%p)\n", pdev);
4546
#endif /* CUPS_DEBUG */
4547
4548
#ifndef GX_COLOR_INDEX_TYPE
4549
  if (cups->header.cupsBitsPerColor > 8)
4550
    cups->header.cupsBitsPerColor = 8;
4551
#endif /* !GX_COLOR_INDEX_TYPE */
4552
4553
293k
#ifdef GX_COLOR_INDEX_TYPE
4554
293k
  if (cups->header.cupsBitsPerColor > 16)
4555
0
    cups->header.cupsBitsPerColor = 16;
4556
293k
#endif /* GX_COLOR_INDEX_TYPE */
4557
4558
293k
  switch (cups->header.cupsColorSpace)
4559
293k
  {
4560
13
    default :
4561
21.5k
    case CUPS_CSPACE_W :
4562
22.3k
    case CUPS_CSPACE_SW :
4563
55.1k
    case CUPS_CSPACE_K :
4564
59.3k
    case CUPS_CSPACE_WHITE :
4565
63.8k
    case CUPS_CSPACE_GOLD :
4566
66.5k
    case CUPS_CSPACE_SILVER :
4567
66.5k
#ifdef CUPS_RASTER_SYNCv1
4568
66.5k
  cups->header.cupsNumColors      = 1;
4569
66.5k
#endif /* CUPS_RASTER_SYNCv1 */
4570
66.5k
        cups->header.cupsBitsPerPixel   = cups->header.cupsBitsPerColor;
4571
66.5k
        cups->color_info.depth          = cups->header.cupsBitsPerPixel;
4572
66.5k
        cups->color_info.num_components = 1;
4573
66.5k
        cups->color_info.dither_grays = 1L << cups->header.cupsBitsPerColor;
4574
66.5k
        cups->color_info.dither_colors = 1L << cups->header.cupsBitsPerColor;
4575
66.5k
        cups->color_info.max_gray = cups->color_info.dither_grays - 1;
4576
66.5k
        cups->color_info.max_color = cups->color_info.dither_grays - 1;
4577
66.5k
        break;
4578
4579
826
    case CUPS_CSPACE_CMY :
4580
1.34k
    case CUPS_CSPACE_YMC :
4581
111k
    case CUPS_CSPACE_RGB :
4582
112k
    case CUPS_CSPACE_SRGB :
4583
123k
    case CUPS_CSPACE_ADOBERGB :
4584
123k
#ifdef CUPS_RASTER_SYNCv1
4585
123k
  cups->header.cupsNumColors      = 3;
4586
123k
#endif /* CUPS_RASTER_SYNCv1 */
4587
123k
        if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
4588
0
          cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
4589
123k
  else if (cups->header.cupsBitsPerColor < 8)
4590
123k
    cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
4591
0
  else
4592
0
    cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor;
4593
4594
123k
  if (cups->header.cupsBitsPerColor < 8)
4595
123k
    cups->color_info.depth = 4 * cups->header.cupsBitsPerColor;
4596
0
  else
4597
0
    cups->color_info.depth = 3 * cups->header.cupsBitsPerColor;
4598
4599
123k
        cups->color_info.num_components = 3;
4600
123k
        break;
4601
4602
6.95k
    case CUPS_CSPACE_KCMYcm :
4603
6.95k
        if (cups->header.cupsBitsPerColor == 1)
4604
6.95k
  {
4605
6.95k
#ifdef CUPS_RASTER_SYNCv1
4606
6.95k
    cups->header.cupsNumColors      = 6;
4607
6.95k
#endif /* CUPS_RASTER_SYNCv1 */
4608
6.95k
    cups->header.cupsBitsPerPixel   = 8;
4609
6.95k
    cups->color_info.depth          = 8;
4610
6.95k
    cups->color_info.num_components = 4;
4611
6.95k
    break;
4612
6.95k
  }
4613
4614
1.64k
    case CUPS_CSPACE_RGBA :
4615
4.59k
    case CUPS_CSPACE_RGBW :
4616
4.59k
#ifdef CUPS_RASTER_SYNCv1
4617
4.59k
        cups->header.cupsNumColors = 4;
4618
4.59k
#endif /* CUPS_RASTER_SYNCv1 */
4619
4.59k
        if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
4620
0
            cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
4621
4.59k
        else
4622
4.59k
            cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
4623
4624
4.59k
        cups->color_info.depth = 4 * cups->header.cupsBitsPerColor;
4625
4.59k
        cups->color_info.num_components = 3;
4626
4.59k
        break;
4627
4628
2.82k
    case CUPS_CSPACE_CMYK :
4629
4.51k
    case CUPS_CSPACE_YMCK :
4630
7.09k
    case CUPS_CSPACE_KCMY :
4631
24.0k
    case CUPS_CSPACE_GMCK :
4632
26.7k
    case CUPS_CSPACE_GMCS :
4633
26.7k
#ifdef CUPS_RASTER_SYNCv1
4634
26.7k
  cups->header.cupsNumColors = 4;
4635
26.7k
#endif /* CUPS_RASTER_SYNCv1 */
4636
26.7k
        if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
4637
0
            cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
4638
26.7k
      else
4639
26.7k
        cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
4640
4641
26.7k
        cups->color_info.depth          = 4 * cups->header.cupsBitsPerColor;
4642
26.7k
        cups->color_info.num_components = 4;
4643
26.7k
        break;
4644
4645
0
#ifdef CUPS_RASTER_HAVE_COLORIMETRIC
4646
2
    case CUPS_CSPACE_CIEXYZ :
4647
683
    case CUPS_CSPACE_CIELab :
4648
34.1k
    case CUPS_CSPACE_ICC1 :
4649
34.9k
    case CUPS_CSPACE_ICC2 :
4650
37.1k
    case CUPS_CSPACE_ICC3 :
4651
40.1k
    case CUPS_CSPACE_ICC4 :
4652
49.6k
    case CUPS_CSPACE_ICC5 :
4653
56.6k
    case CUPS_CSPACE_ICC6 :
4654
57.2k
    case CUPS_CSPACE_ICC7 :
4655
57.8k
    case CUPS_CSPACE_ICC8 :
4656
60.1k
    case CUPS_CSPACE_ICC9 :
4657
61.1k
    case CUPS_CSPACE_ICCA :
4658
61.9k
    case CUPS_CSPACE_ICCB :
4659
62.5k
    case CUPS_CSPACE_ICCC :
4660
63.1k
    case CUPS_CSPACE_ICCD :
4661
64.9k
    case CUPS_CSPACE_ICCE :
4662
65.7k
    case CUPS_CSPACE_ICCF :
4663
       /*
4664
  * Colorimetric color spaces currently are implemented as 24-bit
4665
  * mapping to XYZ or Lab, which are then converted as needed to
4666
  * the final representation...
4667
  *
4668
  * This code enforces a minimum output depth of 8 bits per
4669
  * component...
4670
  */
4671
4672
65.7k
#ifdef CUPS_RASTER_SYNCv1
4673
65.7k
  cups->header.cupsNumColors = 3;
4674
65.7k
#endif /* CUPS_RASTER_SYNCv1 */
4675
4676
65.7k
  if (cups->header.cupsBitsPerColor < 8)
4677
7.13k
          cups->header.cupsBitsPerColor = 8;
4678
4679
65.7k
  if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
4680
0
          cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
4681
65.7k
  else
4682
65.7k
          cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor;
4683
4684
65.7k
  cups->color_info.depth          = 24;
4685
65.7k
  cups->color_info.num_components = 3;
4686
65.7k
  break;
4687
293k
#endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
4688
293k
  }
4689
4690
293k
#ifdef dev_t_proc_encode_color
4691
293k
  switch (cups->header.cupsColorSpace)
4692
293k
  {
4693
193k
    default :
4694
193k
        cups->color_info.gray_index = GX_CINFO_COMP_NO_INDEX;
4695
193k
  break;
4696
4697
21.4k
    case CUPS_CSPACE_W :
4698
22.3k
    case CUPS_CSPACE_SW :
4699
26.5k
    case CUPS_CSPACE_WHITE :
4700
59.2k
    case CUPS_CSPACE_K :
4701
63.8k
    case CUPS_CSPACE_GOLD :
4702
66.5k
    case CUPS_CSPACE_SILVER :
4703
73.4k
    case CUPS_CSPACE_KCMYcm :
4704
76.0k
    case CUPS_CSPACE_KCMY :
4705
76.0k
        cups->color_info.gray_index = 0;
4706
76.0k
  break;
4707
4708
2.82k
    case CUPS_CSPACE_CMYK :
4709
4.51k
    case CUPS_CSPACE_YMCK :
4710
21.5k
    case CUPS_CSPACE_GMCK :
4711
24.2k
    case CUPS_CSPACE_GMCS :
4712
24.2k
        cups->color_info.gray_index = 3;
4713
24.2k
  break;
4714
293k
  }
4715
4716
293k
  switch (cups->header.cupsColorSpace)
4717
293k
  {
4718
13
    default :
4719
2.96k
    case CUPS_CSPACE_RGBW :
4720
24.4k
    case CUPS_CSPACE_W :
4721
25.2k
    case CUPS_CSPACE_SW :
4722
29.4k
    case CUPS_CSPACE_WHITE :
4723
139k
    case CUPS_CSPACE_RGB :
4724
140k
    case CUPS_CSPACE_CMY:
4725
141k
    case CUPS_CSPACE_YMC:
4726
141k
    case CUPS_CSPACE_SRGB :
4727
152k
    case CUPS_CSPACE_ADOBERGB :
4728
154k
    case CUPS_CSPACE_RGBA :
4729
154k
#  ifdef CUPS_RASTER_HAVE_COLORIMETRIC
4730
154k
    case CUPS_CSPACE_CIEXYZ :
4731
155k
    case CUPS_CSPACE_CIELab :
4732
188k
    case CUPS_CSPACE_ICC1 :
4733
189k
    case CUPS_CSPACE_ICC2 :
4734
191k
    case CUPS_CSPACE_ICC3 :
4735
194k
    case CUPS_CSPACE_ICC4 :
4736
203k
    case CUPS_CSPACE_ICC5 :
4737
211k
    case CUPS_CSPACE_ICC6 :
4738
211k
    case CUPS_CSPACE_ICC7 :
4739
212k
    case CUPS_CSPACE_ICC8 :
4740
214k
    case CUPS_CSPACE_ICC9 :
4741
215k
    case CUPS_CSPACE_ICCA :
4742
216k
    case CUPS_CSPACE_ICCB :
4743
216k
    case CUPS_CSPACE_ICCC :
4744
217k
    case CUPS_CSPACE_ICCD :
4745
219k
    case CUPS_CSPACE_ICCE :
4746
220k
    case CUPS_CSPACE_ICCF :
4747
220k
#  endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
4748
220k
        cups->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
4749
220k
        break;
4750
4751
32.7k
    case CUPS_CSPACE_K :
4752
37.3k
    case CUPS_CSPACE_GOLD :
4753
40.0k
    case CUPS_CSPACE_SILVER :
4754
46.9k
    case CUPS_CSPACE_KCMYcm :
4755
49.8k
    case CUPS_CSPACE_CMYK :
4756
51.4k
    case CUPS_CSPACE_YMCK :
4757
54.0k
    case CUPS_CSPACE_KCMY :
4758
71.0k
    case CUPS_CSPACE_GMCK :
4759
73.7k
    case CUPS_CSPACE_GMCS :
4760
73.7k
        cups->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
4761
73.7k
        break;
4762
293k
  }
4763
4764
293k
  cups->color_info.separable_and_linear = GX_CINFO_SEP_LIN_NONE;
4765
293k
#endif /* dev_t_proc_encode_color */
4766
4767
293k
  i       = cups->header.cupsBitsPerColor;
4768
293k
  max_lut = (1 << i) - 1;
4769
4770
293k
  switch (cups->color_info.num_components)
4771
293k
  {
4772
0
    default :
4773
66.5k
    case 1 :
4774
66.5k
  cups->color_info.max_gray      = max_lut;
4775
66.5k
  cups->color_info.max_color     = 0;
4776
66.5k
  cups->color_info.dither_grays  = max_lut + 1;
4777
66.5k
  cups->color_info.dither_colors = 0;
4778
66.5k
        break;
4779
4780
193k
    case 3 :
4781
193k
  cups->color_info.max_gray      = 0;
4782
193k
  cups->color_info.max_color     = max_lut;
4783
193k
  cups->color_info.dither_grays  = 0;
4784
193k
  cups->color_info.dither_colors = max_lut + 1;
4785
193k
  break;
4786
4787
33.7k
    case 4 :
4788
33.7k
  cups->color_info.max_gray      = max_lut;
4789
33.7k
  cups->color_info.max_color     = max_lut;
4790
33.7k
  cups->color_info.dither_grays  = max_lut + 1;
4791
33.7k
  cups->color_info.dither_colors = max_lut + 1;
4792
33.7k
  break;
4793
293k
  }
4794
4795
 /*
4796
  * Enable/disable CMYK color support...
4797
  */
4798
4799
293k
#ifdef dev_t_proc_encode_color
4800
293k
  cups->color_info.max_components = cups->color_info.num_components;
4801
293k
#endif /* dev_t_proc_encode_color */
4802
4803
 /*
4804
  * Tell Ghostscript to forget any colors it has cached...
4805
  */
4806
4807
293k
  gx_device_decache_colors(pdev);
4808
4809
 /*
4810
  * Compute the lookup tables...
4811
  */
4812
4813
19.2G
  for (i = 0; i <= gx_max_color_value; i ++)
4814
19.2G
  {
4815
19.2G
    j = (max_lut * i + gx_max_color_value / 2) / gx_max_color_value;
4816
4817
19.2G
#if !ARCH_IS_BIG_ENDIAN
4818
19.2G
    if (max_lut > 255)
4819
0
      j = ((j & 255) << 8) | ((j >> 8) & 255);
4820
19.2G
#endif /* !ARCH_IS_BIG_ENDIAN */
4821
4822
19.2G
    cups->EncodeLUT[i] = j;
4823
4824
#ifdef CUPS_DEBUG2
4825
    if (i == 0 || cups->EncodeLUT[i] != cups->EncodeLUT[i - 1])
4826
      dmprintf2(pdev->memory, "DEBUG2: cups->EncodeLUT[%d] = %d\n", i,
4827
                (int)cups->EncodeLUT[i]);
4828
#endif /* CUPS_DEBUG2 */
4829
19.2G
  }
4830
4831
#ifdef CUPS_DEBUG2
4832
  dmprintf1(pdev->memory, "DEBUG2: cups->EncodeLUT[0] = %d\n", (int)cups->EncodeLUT[0]);
4833
  dmprintf2(pdev->memory, "DEBUG2: cups->EncodeLUT[%d] = %d\n", gx_max_color_value,
4834
            (int)cups->EncodeLUT[gx_max_color_value]);
4835
#endif /* CUPS_DEBUG2 */
4836
4837
494k
  for (i = 0; i < cups->color_info.dither_grays; i ++) {
4838
200k
    j = i;
4839
200k
#if !ARCH_IS_BIG_ENDIAN
4840
200k
    if (max_lut > 255)
4841
0
      j = ((j & 255) << 8) | ((j >> 8) & 255);
4842
200k
#endif /* !ARCH_IS_BIG_ENDIAN */
4843
200k
    cups->DecodeLUT[i] = gx_max_color_value * j / max_lut;
4844
200k
  }
4845
4846
#ifdef CUPS_DEBUG
4847
  dmprintf2(pdev->memory, "DEBUG: num_components = %d, depth = %d\n",
4848
            cups->color_info.num_components, cups->color_info.depth);
4849
  dmprintf2(pdev->memory, "DEBUG: cupsColorSpace = %d, cupsColorOrder = %d\n",
4850
            cups->header.cupsColorSpace, cups->header.cupsColorOrder);
4851
  dmprintf2(pdev->memory, "DEBUG: cupsBitsPerPixel = %d, cupsBitsPerColor = %d\n",
4852
            cups->header.cupsBitsPerPixel, cups->header.cupsBitsPerColor);
4853
  dmprintf2(pdev->memory, "DEBUG: max_gray = %d, dither_grays = %d\n",
4854
            cups->color_info.max_gray, cups->color_info.dither_grays);
4855
  dmprintf2(pdev->memory, "DEBUG: max_color = %d, dither_colors = %d\n",
4856
            cups->color_info.max_color, cups->color_info.dither_colors);
4857
#endif /* CUPS_DEBUG */
4858
4859
 /*
4860
  * Set the color profile as needed...
4861
  */
4862
4863
293k
  cups->HaveProfile = 0;
4864
4865
293k
#ifdef dev_t_proc_encode_color
4866
293k
  if (cups->Profile)
4867
#else
4868
  if (cups->Profile && cups->header.cupsBitsPerColor == 8)
4869
#endif /* dev_t_proc_encode_color */
4870
0
  {
4871
#ifdef CUPS_DEBUG
4872
    dmprintf1(pdev->memory, "DEBUG: Using user-defined profile \"%s\"...\n", cups->Profile);
4873
#endif /* CUPS_DEBUG */
4874
4875
0
    if (sscanf(cups->Profile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", &d, &g,
4876
0
               m[0] + 0, m[0] + 1, m[0] + 2,
4877
0
               m[1] + 0, m[1] + 1, m[1] + 2,
4878
0
               m[2] + 0, m[2] + 1, m[2] + 2) != 11)
4879
0
      dmprintf(pdev->memory, "ERROR: User-defined profile does not contain 11 integers!\n");
4880
0
    else
4881
0
    {
4882
0
      cups->HaveProfile = 1;
4883
4884
0
      d       *= 0.001f;
4885
0
      g       *= 0.001f;
4886
0
      m[0][0] *= 0.001f;
4887
0
      m[0][1] *= 0.001f;
4888
0
      m[0][2] *= 0.001f;
4889
0
      m[1][0] *= 0.001f;
4890
0
      m[1][1] *= 0.001f;
4891
0
      m[1][2] *= 0.001f;
4892
0
      m[2][0] *= 0.001f;
4893
0
      m[2][1] *= 0.001f;
4894
0
      m[2][2] *= 0.001f;
4895
0
    }
4896
0
  }
4897
293k
#ifdef dev_t_proc_encode_color
4898
293k
  else if (cups->PPD)
4899
#else
4900
  else if (cups->PPD && cups->header.cupsBitsPerColor == 8)
4901
#endif /* dev_t_proc_encode_color */
4902
0
  {
4903
   /*
4904
    * Find the appropriate color profile...
4905
    */
4906
4907
0
    if (pdev->HWResolution[0] != pdev->HWResolution[1])
4908
0
      sprintf(resolution, "%.0fx%.0fdpi", pdev->HWResolution[0],
4909
0
              pdev->HWResolution[1]);
4910
0
    else
4911
0
      sprintf(resolution, "%.0fdpi", pdev->HWResolution[0]);
4912
4913
0
    for (i = 0, profile = cups->PPD->profiles;
4914
0
         i < cups->PPD->num_profiles;
4915
0
   i ++, profile ++)
4916
0
      if ((strcmp(profile->resolution, resolution) == 0 ||
4917
0
           profile->resolution[0] == '-') &&
4918
0
          (strcmp(profile->media_type, cups->header.MediaType) == 0 ||
4919
0
           profile->media_type[0] == '-'))
4920
0
  break;
4921
4922
   /*
4923
    * If we found a color profile, use it!
4924
    */
4925
4926
0
    if (i < cups->PPD->num_profiles)
4927
0
    {
4928
#ifdef CUPS_DEBUG
4929
      dmprintf(pdev->memory, "DEBUG: Using color profile in PPD file!\n");
4930
#endif /* CUPS_DEBUG */
4931
4932
0
      cups->HaveProfile = 1;
4933
4934
0
      d = profile->density;
4935
0
      g = profile->gamma;
4936
4937
0
      memcpy(m, profile->matrix, sizeof(m));
4938
0
    }
4939
0
  }
4940
4941
293k
  if (cups->HaveProfile)
4942
0
  {
4943
0
    for (i = 0; i < 3; i ++)
4944
0
      for (j = 0; j < 3; j ++)
4945
0
  for (k = 0; k <= CUPS_MAX_VALUE; k ++)
4946
0
  {
4947
0
          cups->Matrix[i][j][k] = (int)((float)k * m[i][j] + 0.5);
4948
4949
#ifdef CUPS_DEBUG
4950
          if ((k & 4095) == 0)
4951
            dmprintf4(pdev->memory, "DEBUG2: cups->Matrix[%d][%d][%d] = %d\n",
4952
                      i, j, k, cups->Matrix[i][j][k]);
4953
#endif /* CUPS_DEBUG */
4954
0
        }
4955
4956
4957
0
    for (k = 0; k <= CUPS_MAX_VALUE; k ++)
4958
0
    {
4959
0
      cups->Density[k] = (int)((float)CUPS_MAX_VALUE * d *
4960
0
                       pow((float)k / (float)CUPS_MAX_VALUE, g) +
4961
0
           0.5);
4962
4963
#ifdef CUPS_DEBUG
4964
      if ((k & 4095) == 0)
4965
        dmprintf2(pdev->memory, "DEBUG2: cups->Density[%d] = %d\n", k, cups->Density[k]);
4966
#endif /* CUPS_DEBUG */
4967
0
    }
4968
0
  }
4969
293k
  else
4970
293k
  {
4971
9.62G
    for (k = 0; k <= CUPS_MAX_VALUE; k ++)
4972
9.62G
      cups->Density[k] = k;
4973
293k
  }
4974
293k
  if (!cups->user_icc) {
4975
    /* Set up the ICC profile for ghostscript to use based upon the color space.
4976
       This is different than the PPD profile above which appears to be some sort
4977
       of matrix based TRC profile */
4978
251k
    switch (cups->header.cupsColorSpace)
4979
251k
    {
4980
13
      default :
4981
2.72k
      case CUPS_CSPACE_RGBW :
4982
89.5k
      case CUPS_CSPACE_RGB :
4983
90.3k
      case CUPS_CSPACE_SRGB :
4984
93.9k
      case CUPS_CSPACE_ADOBERGB :
4985
95.5k
      case CUPS_CSPACE_RGBA :
4986
96.3k
      case CUPS_CSPACE_CMY :
4987
96.8k
      case CUPS_CSPACE_YMC :
4988
96.8k
#    ifdef CUPS_RASTER_HAVE_COLORIMETRIC
4989
97.5k
      case CUPS_CSPACE_CIELab :
4990
128k
      case CUPS_CSPACE_ICC1 :
4991
129k
      case CUPS_CSPACE_ICC2 :
4992
131k
      case CUPS_CSPACE_ICC3 :
4993
133k
      case CUPS_CSPACE_ICC4 :
4994
142k
      case CUPS_CSPACE_ICC5 :
4995
148k
      case CUPS_CSPACE_ICC6 :
4996
149k
      case CUPS_CSPACE_ICC7 :
4997
149k
      case CUPS_CSPACE_ICC8 :
4998
151k
      case CUPS_CSPACE_ICC9 :
4999
152k
      case CUPS_CSPACE_ICCA :
5000
153k
      case CUPS_CSPACE_ICCB :
5001
154k
      case CUPS_CSPACE_ICCC :
5002
154k
      case CUPS_CSPACE_ICCD :
5003
156k
      case CUPS_CSPACE_ICCE :
5004
157k
      case CUPS_CSPACE_ICCF :
5005
157k
#    endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
5006
157k
        if (!pdev->icc_struct || (pdev->icc_struct &&
5007
157k
             pdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsRGB)) {
5008
5009
23.9k
          if (pdev->icc_struct) {
5010
23.9k
              rc_decrement(pdev->icc_struct, "cups_set_color_info");
5011
23.9k
          }
5012
23.9k
          pdev->icc_struct = gsicc_new_device_profile_array(pdev);
5013
5014
23.9k
          code = gsicc_set_device_profile(pdev, pdev->memory,
5015
23.9k
              (char *)DEFAULT_RGB_ICC, gsDEFAULTPROFILE);
5016
23.9k
          }
5017
157k
        break;
5018
5019
18.3k
      case CUPS_CSPACE_W :
5020
19.1k
      case CUPS_CSPACE_SW :
5021
22.3k
      case CUPS_CSPACE_WHITE :
5022
55.0k
      case CUPS_CSPACE_K :
5023
59.3k
      case CUPS_CSPACE_GOLD :
5024
61.4k
      case CUPS_CSPACE_SILVER :
5025
61.4k
        if (!pdev->icc_struct || (pdev->icc_struct &&
5026
32.0k
             pdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsGRAY)) {
5027
5028
29.4k
          if (pdev->icc_struct) {
5029
0
              rc_decrement(pdev->icc_struct, "cups_set_color_info");
5030
0
          }
5031
29.4k
          pdev->icc_struct = gsicc_new_device_profile_array(pdev);
5032
5033
29.4k
          code = gsicc_set_device_profile(pdev, pdev->memory->non_gc_memory,
5034
29.4k
              (char *)DEFAULT_GRAY_ICC, gsDEFAULTPROFILE);
5035
29.4k
        }
5036
61.4k
        break;
5037
6.83k
      case CUPS_CSPACE_KCMYcm :
5038
6.83k
#    ifdef CUPS_RASTER_HAVE_COLORIMETRIC
5039
6.83k
      case CUPS_CSPACE_CIEXYZ :
5040
6.83k
#endif
5041
9.60k
      case CUPS_CSPACE_CMYK :
5042
11.2k
      case CUPS_CSPACE_YMCK :
5043
13.7k
      case CUPS_CSPACE_KCMY :
5044
30.3k
      case CUPS_CSPACE_GMCK :
5045
32.9k
      case CUPS_CSPACE_GMCS :
5046
32.9k
        if (!pdev->icc_struct || (pdev->icc_struct &&
5047
32.9k
             pdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs != gsCMYK)) {
5048
5049
2.27k
          if (pdev->icc_struct) {
5050
2.27k
              rc_decrement(pdev->icc_struct, "cups_set_color_info");
5051
2.27k
          }
5052
2.27k
          pdev->icc_struct = gsicc_new_device_profile_array(pdev);
5053
5054
2.27k
          code = gsicc_set_device_profile(pdev, pdev->memory,
5055
2.27k
              (char *)DEFAULT_CMYK_ICC, gsDEFAULTPROFILE);
5056
2.27k
          }
5057
32.9k
        break;
5058
251k
    }
5059
251k
  }
5060
293k
  return(code);
5061
293k
}
5062
5063
/*
5064
 * 'cups_sync_output()' - Keep the user informed of our status...
5065
 */
5066
5067
private int       /* O - Error status */
5068
cups_sync_output(gx_device *pdev) /* I - Device info */
5069
0
{
5070
0
  dmprintf1(pdev->memory, "INFO: Processing page %d...\n", cups->page);
5071
5072
0
  return (0);
5073
0
}
5074
5075
5076
/*
5077
 * 'cups_print_chunked()' - Print a page of chunked pixels.
5078
 */
5079
5080
static int
5081
cups_print_chunked(gx_device_printer *pdev,
5082
          /* I - Printer device */
5083
                   unsigned char     *src,
5084
          /* I - Scanline buffer */
5085
       unsigned char     *dst,
5086
          /* I - Bitmap buffer */
5087
       int               srcbytes)
5088
          /* I - Number of bytes in src */
5089
24.1k
{
5090
24.1k
  int   y;      /* Looping var */
5091
24.1k
  unsigned char *srcptr,    /* Pointer to data */
5092
24.1k
    *dstptr;    /* Pointer to bits */
5093
24.1k
  int   count;      /* Count for loop */
5094
24.1k
  int   xflip,      /* Flip scanline? */
5095
#ifdef CUPS_DEBUG
5096
                yflip,      /* Reverse scanline order? */
5097
#endif
5098
24.1k
                ystart, yend, ystep;    /* Loop control for scanline order */
5099
24.1k
  ppd_attr_t    *backside = NULL;
5100
24.1k
  const char    *backside_str = "Normal";
5101
24.1k
  int           flip_duplex = 0;
5102
5103
#ifdef CUPS_DEBUG
5104
  dmprintf1(pdev->memory, "DEBUG2: cups->header.Duplex = %d\n", cups->header.Duplex);
5105
  dmprintf1(pdev->memory, "DEBUG2: cups->header.Tumble = %d\n", cups->header.Tumble);
5106
  dmprintf1(pdev->memory, "DEBUG2: cups->page = %d\n", cups->page);
5107
  dmprintf1(pdev->memory, "DEBUG2: cups->PPD = %p\n", cups->PPD);
5108
#endif /* CUPS_DEBUG */
5109
5110
24.1k
  if (cups->PPD) {
5111
0
    backside = ppdFindAttr(cups->PPD, "cupsBackSide", NULL);
5112
0
    if (backside) {
5113
0
      backside_str = backside->value;
5114
0
      cups->PPD->flip_duplex = 0;
5115
0
    }
5116
0
    flip_duplex = cups->PPD->flip_duplex;
5117
0
  }
5118
24.1k
  else
5119
24.1k
    backside_str = cups->cupsBackSideOrientation;
5120
#ifdef CUPS_DEBUG
5121
  dmprintf1(pdev->memory, "DEBUG2: Back side orientation: %s\n", backside_str);
5122
#endif /* CUPS_DEBUG */
5123
24.1k
  if (cups->header.Duplex &&
5124
0
      ((!cups->header.Tumble &&
5125
0
  (flip_duplex ||
5126
0
   (!strcasecmp(backside_str, "Rotated")))) ||
5127
0
       (cups->header.Tumble &&
5128
0
  ((!strcasecmp(backside_str, "Flipped") ||
5129
0
    !strcasecmp(backside_str, "ManualTumble"))))) &&
5130
0
      !(cups->page & 1))
5131
0
    xflip = 1;
5132
24.1k
  else
5133
24.1k
    xflip = 0;
5134
24.1k
  if (cups->header.Duplex &&
5135
0
      ((!cups->header.Tumble &&
5136
0
  (flip_duplex ||
5137
0
   ((!strcasecmp(backside_str, "Flipped") ||
5138
0
     !strcasecmp(backside_str, "Rotated"))))) ||
5139
0
       (cups->header.Tumble &&
5140
0
  (!strcasecmp(backside_str, "ManualTumble")))) &&
5141
0
      !(cups->page & 1)) {
5142
#ifdef CUPS_DEBUG
5143
    yflip = 1;
5144
#endif
5145
0
    ystart = cups->height - 1;
5146
0
    yend = -1;
5147
0
    ystep = -1;
5148
24.1k
  } else {
5149
#ifdef CUPS_DEBUG
5150
    yflip = 0;
5151
#endif
5152
24.1k
    ystart = 0;
5153
24.1k
    yend = cups->height;
5154
24.1k
    ystep = 1;
5155
24.1k
  }
5156
5157
#ifdef CUPS_DEBUG
5158
  dmprintf3(pdev->memory, "DEBUG: cups_print_chunked: xflip = %d, yflip = %d, height = %d\n",
5159
            xflip, yflip, cups->height);
5160
#endif /* CUPS_DEBUG */
5161
5162
 /*
5163
  * Loop through the page bitmap and write chunked pixels, reversing as
5164
  * needed...
5165
  */
5166
58.6M
  for (y = ystart; y != yend; y += ystep)
5167
58.6M
  {
5168
   /*
5169
    * Grab the scanline data...
5170
    */
5171
5172
58.6M
    if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
5173
5
    {
5174
5
      dmprintf1(pdev->memory, "ERROR: Unable to get scanline %d!\n", y);
5175
5
      return_error(gs_error_unknownerror);
5176
5
    }
5177
5178
58.6M
    if (xflip)
5179
0
    {
5180
     /*
5181
      * Flip the raster data before writing it...
5182
      */
5183
5184
0
      if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
5185
0
  memset(dst, 0, cups->header.cupsBytesPerLine);
5186
0
      else
5187
0
      {
5188
0
        dstptr = dst;
5189
0
  count  = srcbytes;
5190
5191
0
  switch (cups->color_info.depth)
5192
0
  {
5193
0
          case 1 : /* B&W bitmap */
5194
0
        for (srcptr += srcbytes - 1;
5195
0
             count > 0;
5196
0
       count --, srcptr --, dstptr ++)
5197
0
        {
5198
0
          *dstptr = cups->RevUpper1[*srcptr & 15] |
5199
0
              cups->RevLower1[*srcptr >> 4];
5200
0
              }
5201
0
        break;
5202
5203
0
    case 2 : /* 2-bit W/K image */
5204
0
        for (srcptr += srcbytes - 1;
5205
0
             count > 0;
5206
0
       count --, srcptr --, dstptr ++)
5207
0
        {
5208
0
          *dstptr = cups->RevUpper2[*srcptr & 15] |
5209
0
              cups->RevLower2[*srcptr >> 4];
5210
0
              }
5211
0
        break;
5212
5213
0
    case 4 : /* 1-bit RGB/CMY/CMYK bitmap or 4-bit W/K image */
5214
0
        for (srcptr += srcbytes - 1;
5215
0
             count > 0;
5216
0
       count --, srcptr --, dstptr ++)
5217
0
          *dstptr = (*srcptr >> 4) | (*srcptr << 4);
5218
0
        break;
5219
5220
0
          case 8 : /* 2-bit RGB/CMY/CMYK or 8-bit W/K image */
5221
0
        for (srcptr += srcbytes - 1;
5222
0
             count > 0;
5223
0
       count --, srcptr --, dstptr ++)
5224
0
          *dstptr = *srcptr;
5225
0
        break;
5226
5227
0
          case 16 : /* 4-bit RGB/CMY/CMYK or 16-bit W/K image */
5228
0
        for (srcptr += srcbytes - 2;
5229
0
             count > 0;
5230
0
       count -= 2, srcptr -= 2, dstptr += 2)
5231
0
        {
5232
0
          dstptr[0] = srcptr[0];
5233
0
          dstptr[1] = srcptr[1];
5234
0
              }
5235
0
        break;
5236
5237
0
          case 24 : /* 8-bit RGB or CMY image */
5238
0
        for (srcptr += srcbytes - 3;
5239
0
             count > 0;
5240
0
       count -= 3, srcptr -= 3, dstptr += 3)
5241
0
        {
5242
0
          dstptr[0] = srcptr[0];
5243
0
          dstptr[1] = srcptr[1];
5244
0
          dstptr[2] = srcptr[2];
5245
0
              }
5246
0
        break;
5247
5248
0
          case 32 : /* 8-bit CMYK image */
5249
0
        for (srcptr += srcbytes - 4;
5250
0
             count > 0;
5251
0
       count -= 4, srcptr -= 4, dstptr += 4)
5252
0
        {
5253
0
          dstptr[0] = srcptr[0];
5254
0
          dstptr[1] = srcptr[1];
5255
0
          dstptr[2] = srcptr[2];
5256
0
          dstptr[3] = srcptr[3];
5257
0
              }
5258
0
        break;
5259
5260
0
          case 48 : /* 16-bit RGB or CMY image */
5261
0
        for (srcptr += srcbytes - 6;
5262
0
             count > 0;
5263
0
       count -= 6, srcptr -= 6, dstptr += 6)
5264
0
        {
5265
0
          dstptr[0] = srcptr[0];
5266
0
          dstptr[1] = srcptr[1];
5267
0
          dstptr[2] = srcptr[2];
5268
0
          dstptr[3] = srcptr[3];
5269
0
          dstptr[4] = srcptr[4];
5270
0
          dstptr[5] = srcptr[5];
5271
0
              }
5272
0
        break;
5273
5274
0
          case 64 : /* 16-bit CMYK image */
5275
0
        for (srcptr += srcbytes - 8;
5276
0
             count > 0;
5277
0
       count -= 8, srcptr -= 8, dstptr += 8)
5278
0
        {
5279
0
          dstptr[0] = srcptr[0];
5280
0
          dstptr[1] = srcptr[1];
5281
0
          dstptr[2] = srcptr[2];
5282
0
          dstptr[3] = srcptr[3];
5283
0
          dstptr[4] = srcptr[4];
5284
0
          dstptr[5] = srcptr[5];
5285
0
          dstptr[6] = srcptr[6];
5286
0
          dstptr[7] = srcptr[7];
5287
0
              }
5288
0
        break;
5289
0
        }
5290
0
      }
5291
5292
     /*
5293
      * Write the bitmap data to the raster stream...
5294
      */
5295
5296
0
      cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
5297
0
    }
5298
58.6M
    else
5299
58.6M
    {
5300
     /*
5301
      * Write the scanline data to the raster stream...
5302
      */
5303
5304
58.6M
      cupsRasterWritePixels(cups->stream, srcptr, cups->header.cupsBytesPerLine);
5305
58.6M
    }
5306
58.6M
  }
5307
24.1k
  return (0);
5308
24.1k
}
5309
5310
5311
/*
5312
 * 'cups_print_banded()' - Print a page of banded pixels.
5313
 */
5314
5315
static int
5316
cups_print_banded(gx_device_printer *pdev,
5317
          /* I - Printer device */
5318
                  unsigned char     *src,
5319
          /* I - Scanline buffer */
5320
      unsigned char     *dst,
5321
          /* I - Bitmap buffer */
5322
      int               srcbytes)
5323
          /* I - Number of bytes in src */
5324
0
{
5325
0
  int   x;      /* Looping var */
5326
0
  int   y;      /* Looping var */
5327
0
  int   bandbytes;    /* Bytes per band */
5328
0
  unsigned char bit;      /* Current bit */
5329
0
  unsigned char temp;     /* Temporary variable */
5330
0
  unsigned char *srcptr;    /* Pointer to data */
5331
0
  unsigned char *cptr, *mptr, *yptr,  /* Pointer to components */
5332
0
    *kptr, *lcptr, *lmptr;  /* ... */
5333
0
  int   xflip,      /* Flip scanline? */
5334
#ifdef CUPS_DEBUG
5335
                yflip,      /* Reverse scanline order? */
5336
#endif
5337
0
                ystart, yend, ystep;    /* Loop control for scanline order */
5338
0
  ppd_attr_t    *backside = NULL;
5339
0
  const char     *backside_str = "Normal";
5340
0
  int           flip_duplex = 0;
5341
5342
5343
#ifdef CUPS_DEBUG
5344
  dmprintf1(pdev->memory, "DEBUG2: cups->header.Duplex = %d\n", cups->header.Duplex);
5345
  dmprintf1(pdev->memory, "DEBUG2: cups->header.Tumble = %d\n", cups->header.Tumble);
5346
  dmprintf1(pdev->memory, "DEBUG2: cups->page = %d\n", cups->page);
5347
  dmprintf1(pdev->memory, "DEBUG2: cups->PPD = %p\n", cups->PPD);
5348
#endif /* CUPS_DEBUG */
5349
5350
0
  if (cups->PPD) {
5351
0
    backside = ppdFindAttr(cups->PPD, "cupsBackSide", NULL);
5352
0
    if (backside) {
5353
0
      backside_str = backside->value;
5354
0
      cups->PPD->flip_duplex = 0;
5355
0
    }
5356
0
    flip_duplex = cups->PPD->flip_duplex;
5357
0
  }
5358
0
  else
5359
0
    backside_str = cups->cupsBackSideOrientation;
5360
#ifdef CUPS_DEBUG
5361
  dmprintf1(pdev->memory, "DEBUG2: Back side orientation: %s\n", backside_str);
5362
#endif /* CUPS_DEBUG */
5363
0
  if (cups->header.Duplex &&
5364
0
      ((!cups->header.Tumble &&
5365
0
  (flip_duplex ||
5366
0
   (!strcasecmp(backside_str, "Rotated")))) ||
5367
0
       (cups->header.Tumble &&
5368
0
  ((!strcasecmp(backside_str, "Flipped") ||
5369
0
    !strcasecmp(backside_str, "ManualTumble"))))) &&
5370
0
      !(cups->page & 1))
5371
0
    xflip = 1;
5372
0
  else
5373
0
    xflip = 0;
5374
0
  if (cups->header.Duplex &&
5375
0
      ((!cups->header.Tumble &&
5376
0
  (flip_duplex ||
5377
0
   ((!strcasecmp(backside_str, "Flipped") ||
5378
0
     !strcasecmp(backside_str, "Rotated"))))) ||
5379
0
       (cups->header.Tumble &&
5380
0
  (!strcasecmp(backside_str, "ManualTumble")))) &&
5381
0
      !(cups->page & 1)) {
5382
#ifdef CUPS_DEBUG
5383
    yflip = 1;
5384
#endif
5385
0
    ystart = cups->height - 1;
5386
0
    yend = -1;
5387
0
    ystep = -1;
5388
0
  } else {
5389
#ifdef CUPS_DEBUG
5390
    yflip = 0;
5391
#endif
5392
0
    ystart = 0;
5393
0
    yend = cups->height;
5394
0
    ystep = 1;
5395
0
  }
5396
5397
#ifdef CUPS_DEBUG
5398
  dmprintf3(pdev->memory, "DEBUG: cups_print_chunked: xflip = %d, yflip = %d, height = %d\n",
5399
            xflip, yflip, cups->height);
5400
#endif /* CUPS_DEBUG */
5401
5402
 /*
5403
  * Loop through the page bitmap and write banded pixels...  We have
5404
  * to separate each chunked color as needed...
5405
  */
5406
5407
0
#ifdef CUPS_RASTER_SYNCv1
5408
0
  bandbytes = cups->header.cupsBytesPerLine / cups->header.cupsNumColors;
5409
#else
5410
  if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
5411
      cups->header.cupsBitsPerColor == 1)
5412
    bandbytes = cups->header.cupsBytesPerLine / 6;
5413
  else
5414
    bandbytes = cups->header.cupsBytesPerLine / cups->color_info.num_components;
5415
#endif /* CUPS_RASTER_SYNCv1 */
5416
5417
0
  for (y = ystart; y != yend; y += ystep)
5418
0
  {
5419
   /*
5420
    * Grab the scanline data...
5421
    */
5422
5423
0
    if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
5424
0
    {
5425
0
      dmprintf1(pdev->memory, "ERROR: Unable to get scanline %d!\n", y);
5426
0
      return_error(gs_error_unknownerror);
5427
0
    }
5428
5429
   /*
5430
    * Separate the chunked colors into their components...
5431
    */
5432
5433
0
    if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
5434
0
      memset(dst, 0, cups->header.cupsBytesPerLine);
5435
0
    else
5436
0
    {
5437
0
      if (xflip)
5438
0
        cptr = dst + bandbytes - 1;
5439
0
      else
5440
0
        cptr = dst;
5441
5442
0
      mptr  = cptr + bandbytes;
5443
0
      yptr  = mptr + bandbytes;
5444
0
      kptr  = yptr + bandbytes;
5445
0
      lcptr = kptr + bandbytes;
5446
0
      lmptr = lcptr + bandbytes;
5447
5448
0
      switch (cups->header.cupsBitsPerColor)
5449
0
      {
5450
0
  default :
5451
0
            memset(dst, 0, cups->header.cupsBytesPerLine);
5452
5453
0
            switch (cups->header.cupsColorSpace)
5454
0
      {
5455
0
        default :
5456
0
            for (x = cups->width, bit = xflip ? 1 << (x & 7) : 128;
5457
0
           x > 0;
5458
0
           x --, srcptr ++)
5459
0
      {
5460
0
        if (*srcptr & 0x40)
5461
0
          *cptr |= bit;
5462
0
        if (*srcptr & 0x20)
5463
0
          *mptr |= bit;
5464
0
        if (*srcptr & 0x10)
5465
0
          *yptr |= bit;
5466
5467
0
                    if (xflip)
5468
0
        {
5469
0
          if (bit < 128)
5470
0
      bit <<= 1;
5471
0
          else
5472
0
          {
5473
0
      cptr --;
5474
0
      mptr --;
5475
0
      yptr --;
5476
0
      bit = 1;
5477
0
          }
5478
0
        }
5479
0
        else
5480
0
          bit >>= 1;
5481
5482
0
        x --;
5483
0
        if (x == 0)
5484
0
          break;
5485
5486
0
        if (*srcptr & 0x4)
5487
0
          *cptr |= bit;
5488
0
        if (*srcptr & 0x2)
5489
0
          *mptr |= bit;
5490
0
        if (*srcptr & 0x1)
5491
0
          *yptr |= bit;
5492
5493
0
                    if (xflip)
5494
0
        {
5495
0
          if (bit < 128)
5496
0
      bit <<= 1;
5497
0
          else
5498
0
          {
5499
0
      cptr --;
5500
0
      mptr --;
5501
0
      yptr --;
5502
0
      bit = 1;
5503
0
          }
5504
0
        }
5505
0
        else if (bit > 1)
5506
0
          bit >>= 1;
5507
0
        else
5508
0
        {
5509
0
          cptr ++;
5510
0
          mptr ++;
5511
0
          yptr ++;
5512
0
          bit = 128;
5513
0
        }
5514
0
      }
5515
0
            break;
5516
0
        case CUPS_CSPACE_GMCK :
5517
0
        case CUPS_CSPACE_GMCS :
5518
0
        case CUPS_CSPACE_RGBA :
5519
0
        case CUPS_CSPACE_RGBW :
5520
0
        case CUPS_CSPACE_CMYK :
5521
0
        case CUPS_CSPACE_YMCK :
5522
0
        case CUPS_CSPACE_KCMY :
5523
0
            for (x = cups->width, bit = xflip ? 1 << (x & 7) : 128;
5524
0
           x > 0;
5525
0
           x --, srcptr ++)
5526
0
      {
5527
0
        if (*srcptr & 0x80)
5528
0
          *cptr |= bit;
5529
0
        if (*srcptr & 0x40)
5530
0
          *mptr |= bit;
5531
0
        if (*srcptr & 0x20)
5532
0
          *yptr |= bit;
5533
0
        if (*srcptr & 0x10)
5534
0
          *kptr |= bit;
5535
5536
0
                    if (xflip)
5537
0
        {
5538
0
          if (bit < 128)
5539
0
      bit <<= 1;
5540
0
          else
5541
0
          {
5542
0
      cptr --;
5543
0
      mptr --;
5544
0
      yptr --;
5545
0
      kptr --;
5546
0
      bit = 1;
5547
0
          }
5548
0
        }
5549
0
        else
5550
0
          bit >>= 1;
5551
5552
0
        x --;
5553
0
        if (x == 0)
5554
0
          break;
5555
5556
0
        if (*srcptr & 0x8)
5557
0
          *cptr |= bit;
5558
0
        if (*srcptr & 0x4)
5559
0
          *mptr |= bit;
5560
0
        if (*srcptr & 0x2)
5561
0
          *yptr |= bit;
5562
0
        if (*srcptr & 0x1)
5563
0
          *kptr |= bit;
5564
5565
0
                    if (xflip)
5566
0
        {
5567
0
          if (bit < 128)
5568
0
      bit <<= 1;
5569
0
          else
5570
0
          {
5571
0
      cptr --;
5572
0
      mptr --;
5573
0
      yptr --;
5574
0
      kptr --;
5575
0
      bit = 1;
5576
0
          }
5577
0
        }
5578
0
        else if (bit > 1)
5579
0
          bit >>= 1;
5580
0
        else
5581
0
        {
5582
0
          cptr ++;
5583
0
          mptr ++;
5584
0
          yptr ++;
5585
0
          kptr ++;
5586
0
          bit = 128;
5587
0
        }
5588
0
      }
5589
0
            break;
5590
0
        case CUPS_CSPACE_KCMYcm :
5591
0
            for (x = cups->width, bit = xflip ? 1 << (x & 7) : 128;
5592
0
           x > 0;
5593
0
           x --, srcptr ++)
5594
0
      {
5595
                   /*
5596
                    * Note: Because of the way the pointers are setup,
5597
                    *       the following code is correct even though
5598
                    *       the names don't match...
5599
                    */
5600
5601
0
        if (*srcptr & 0x20)
5602
0
          *cptr |= bit;
5603
0
        if (*srcptr & 0x10)
5604
0
          *mptr |= bit;
5605
0
        if (*srcptr & 0x08)
5606
0
          *yptr |= bit;
5607
0
        if (*srcptr & 0x04)
5608
0
          *kptr |= bit;
5609
0
        if (*srcptr & 0x02)
5610
0
          *lcptr |= bit;
5611
0
        if (*srcptr & 0x01)
5612
0
          *lmptr |= bit;
5613
5614
0
                    if (xflip)
5615
0
        {
5616
0
          if (bit < 128)
5617
0
      bit <<= 1;
5618
0
          else
5619
0
          {
5620
0
      cptr --;
5621
0
      mptr --;
5622
0
      yptr --;
5623
0
      kptr --;
5624
0
      lcptr --;
5625
0
      lmptr --;
5626
0
      bit = 1;
5627
0
          }
5628
0
        }
5629
0
        else if (bit > 1)
5630
0
          bit >>= 1;
5631
0
        else
5632
0
        {
5633
0
          cptr ++;
5634
0
          mptr ++;
5635
0
          yptr ++;
5636
0
          kptr ++;
5637
0
          lcptr ++;
5638
0
          lmptr ++;
5639
0
          bit = 128;
5640
0
        }
5641
0
      }
5642
0
            break;
5643
0
      }
5644
0
            break;
5645
5646
0
  case 2 :
5647
0
            memset(dst, 0, cups->header.cupsBytesPerLine);
5648
5649
0
            switch (cups->header.cupsColorSpace)
5650
0
      {
5651
0
        default :
5652
0
            for (x = cups->width, bit = xflip ? 3 << (2 * (x & 3)) : 0xc0;
5653
0
           x > 0;
5654
0
           x --, srcptr ++)
5655
0
        switch (bit)
5656
0
        {
5657
0
          case 0xc0 :
5658
0
        if ((temp = *srcptr & 0x30) != 0)
5659
0
          *cptr |= temp << 2;
5660
0
        if ((temp = *srcptr & 0x0c) != 0)
5661
0
          *mptr |= temp << 4;
5662
0
        if ((temp = *srcptr & 0x03) != 0)
5663
0
          *yptr |= temp << 6;
5664
5665
0
                          if (xflip)
5666
0
        {
5667
0
          bit = 0x03;
5668
0
          cptr --;
5669
0
          mptr --;
5670
0
          yptr --;
5671
0
        }
5672
0
        else
5673
0
          bit = 0x30;
5674
0
        break;
5675
0
          case 0x30 :
5676
0
        if ((temp = *srcptr & 0x30) != 0)
5677
0
          *cptr |= temp;
5678
0
        if ((temp = *srcptr & 0x0c) != 0)
5679
0
          *mptr |= temp << 2;
5680
0
        if ((temp = *srcptr & 0x03) != 0)
5681
0
          *yptr |= temp << 4;
5682
5683
0
        if (xflip)
5684
0
          bit = 0xc0;
5685
0
        else
5686
0
          bit = 0x0c;
5687
0
        break;
5688
0
          case 0x0c :
5689
0
        if ((temp = *srcptr & 0x30) != 0)
5690
0
          *cptr |= temp >> 2;
5691
0
        if ((temp = *srcptr & 0x0c) != 0)
5692
0
          *mptr |= temp;
5693
0
        if ((temp = *srcptr & 0x03) != 0)
5694
0
          *yptr |= temp << 2;
5695
5696
0
        if (xflip)
5697
0
          bit = 0x30;
5698
0
        else
5699
0
          bit = 0x03;
5700
0
        break;
5701
0
          case 0x03 :
5702
0
        if ((temp = *srcptr & 0x30) != 0)
5703
0
          *cptr |= temp >> 4;
5704
0
        if ((temp = *srcptr & 0x0c) != 0)
5705
0
          *mptr |= temp >> 2;
5706
0
        if ((temp = *srcptr & 0x03) != 0)
5707
0
          *yptr |= temp;
5708
5709
0
        if (xflip)
5710
0
          bit = 0x0c;
5711
0
        else
5712
0
        {
5713
0
          bit = 0xc0;
5714
0
          cptr ++;
5715
0
          mptr ++;
5716
0
          yptr ++;
5717
0
        }
5718
0
        break;
5719
0
                    }
5720
0
            break;
5721
0
        case CUPS_CSPACE_GMCK :
5722
0
        case CUPS_CSPACE_GMCS :
5723
0
        case CUPS_CSPACE_RGBA :
5724
0
        case CUPS_CSPACE_RGBW :
5725
0
        case CUPS_CSPACE_CMYK :
5726
0
        case CUPS_CSPACE_YMCK :
5727
0
        case CUPS_CSPACE_KCMY :
5728
0
        case CUPS_CSPACE_KCMYcm :
5729
0
            for (x = cups->width, bit = xflip ? 3 << (2 * (x & 3)) : 0xc0;
5730
0
           x > 0;
5731
0
           x --, srcptr ++)
5732
0
        switch (bit)
5733
0
        {
5734
0
          case 0xc0 :
5735
0
              if ((temp = *srcptr & 0xc0) != 0)
5736
0
          *cptr |= temp;
5737
0
        if ((temp = *srcptr & 0x30) != 0)
5738
0
          *mptr |= temp << 2;
5739
0
        if ((temp = *srcptr & 0x0c) != 0)
5740
0
          *yptr |= temp << 4;
5741
0
        if ((temp = *srcptr & 0x03) != 0)
5742
0
          *kptr |= temp << 6;
5743
5744
0
                          if (xflip)
5745
0
        {
5746
0
          bit = 0x03;
5747
0
          cptr --;
5748
0
          mptr --;
5749
0
          yptr --;
5750
0
          kptr --;
5751
0
        }
5752
0
        else
5753
0
          bit = 0x30;
5754
0
        break;
5755
0
          case 0x30 :
5756
0
              if ((temp = *srcptr & 0xc0) != 0)
5757
0
          *cptr |= temp >> 2;
5758
0
        if ((temp = *srcptr & 0x30) != 0)
5759
0
          *mptr |= temp;
5760
0
        if ((temp = *srcptr & 0x0c) != 0)
5761
0
          *yptr |= temp << 2;
5762
0
        if ((temp = *srcptr & 0x03) != 0)
5763
0
          *kptr |= temp << 4;
5764
5765
0
        if (xflip)
5766
0
          bit = 0xc0;
5767
0
        else
5768
0
          bit = 0x0c;
5769
0
        break;
5770
0
          case 0x0c :
5771
0
              if ((temp = *srcptr & 0xc0) != 0)
5772
0
          *cptr |= temp >> 4;
5773
0
        if ((temp = *srcptr & 0x30) != 0)
5774
0
          *mptr |= temp >> 2;
5775
0
        if ((temp = *srcptr & 0x0c) != 0)
5776
0
          *yptr |= temp;
5777
0
        if ((temp = *srcptr & 0x03) != 0)
5778
0
          *kptr |= temp << 2;
5779
5780
0
        if (xflip)
5781
0
          bit = 0x30;
5782
0
        else
5783
0
          bit = 0x03;
5784
0
        break;
5785
0
          case 0x03 :
5786
0
              if ((temp = *srcptr & 0xc0) != 0)
5787
0
          *cptr |= temp >> 6;
5788
0
        if ((temp = *srcptr & 0x30) != 0)
5789
0
          *mptr |= temp >> 4;
5790
0
        if ((temp = *srcptr & 0x0c) != 0)
5791
0
          *yptr |= temp >> 2;
5792
0
        if ((temp = *srcptr & 0x03) != 0)
5793
0
          *kptr |= temp;
5794
5795
0
        if (xflip)
5796
0
          bit = 0x0c;
5797
0
        else
5798
0
        {
5799
0
          bit = 0xc0;
5800
0
          cptr ++;
5801
0
          mptr ++;
5802
0
          yptr ++;
5803
0
          kptr ++;
5804
0
        }
5805
0
        break;
5806
0
                    }
5807
0
            break;
5808
0
      }
5809
0
            break;
5810
5811
0
  case 4 :
5812
0
            memset(dst, 0, cups->header.cupsBytesPerLine);
5813
5814
0
            switch (cups->header.cupsColorSpace)
5815
0
      {
5816
0
        default :
5817
0
            for (x = cups->width, bit = xflip && (x & 1) ? 0xf0 : 0x0f;
5818
0
           x > 0;
5819
0
           x --, srcptr += 2)
5820
0
        switch (bit)
5821
0
        {
5822
0
          case 0xf0 :
5823
0
        if ((temp = srcptr[0] & 0x0f) != 0)
5824
0
          *cptr |= temp << 4;
5825
0
        if ((temp = srcptr[1] & 0xf0) != 0)
5826
0
          *mptr |= temp;
5827
0
        if ((temp = srcptr[1] & 0x0f) != 0)
5828
0
          *yptr |= temp << 4;
5829
5830
0
        bit = 0x0f;
5831
5832
0
                          if (xflip)
5833
0
        {
5834
0
          cptr --;
5835
0
          mptr --;
5836
0
          yptr --;
5837
0
        }
5838
0
        break;
5839
0
          case 0x0f :
5840
0
        if ((temp = srcptr[0] & 0x0f) != 0)
5841
0
          *cptr |= temp;
5842
0
        if ((temp = srcptr[1] & 0xf0) != 0)
5843
0
          *mptr |= temp >> 4;
5844
0
        if ((temp = srcptr[1] & 0x0f) != 0)
5845
0
          *yptr |= temp;
5846
5847
0
        bit = 0xf0;
5848
5849
0
                          if (!xflip)
5850
0
        {
5851
0
          cptr ++;
5852
0
          mptr ++;
5853
0
          yptr ++;
5854
0
        }
5855
0
        break;
5856
0
                    }
5857
0
            break;
5858
0
        case CUPS_CSPACE_GMCK :
5859
0
        case CUPS_CSPACE_GMCS :
5860
0
        case CUPS_CSPACE_RGBA :
5861
0
        case CUPS_CSPACE_RGBW :
5862
0
        case CUPS_CSPACE_CMYK :
5863
0
        case CUPS_CSPACE_YMCK :
5864
0
        case CUPS_CSPACE_KCMY :
5865
0
        case CUPS_CSPACE_KCMYcm :
5866
0
            for (x = cups->width, bit = xflip && (x & 1) ? 0xf0 : 0x0f;
5867
0
           x > 0;
5868
0
           x --, srcptr += 2)
5869
0
        switch (bit)
5870
0
        {
5871
0
          case 0xf0 :
5872
0
              if ((temp = srcptr[0] & 0xf0) != 0)
5873
0
          *cptr |= temp;
5874
0
        if ((temp = srcptr[0] & 0x0f) != 0)
5875
0
          *mptr |= temp << 4;
5876
0
        if ((temp = srcptr[1] & 0xf0) != 0)
5877
0
          *yptr |= temp;
5878
0
        if ((temp = srcptr[1] & 0x0f) != 0)
5879
0
          *kptr |= temp << 4;
5880
5881
0
        bit = 0x0f;
5882
5883
0
                          if (xflip)
5884
0
        {
5885
0
          cptr --;
5886
0
          mptr --;
5887
0
          yptr --;
5888
0
          kptr --;
5889
0
        }
5890
0
        break;
5891
0
          case 0x0f :
5892
0
              if ((temp = srcptr[0] & 0xf0) != 0)
5893
0
          *cptr |= temp >> 4;
5894
0
        if ((temp = srcptr[0] & 0x0f) != 0)
5895
0
          *mptr |= temp;
5896
0
        if ((temp = srcptr[1] & 0xf0) != 0)
5897
0
          *yptr |= temp >> 4;
5898
0
        if ((temp = srcptr[1] & 0x0f) != 0)
5899
0
          *kptr |= temp;
5900
5901
0
        bit = 0xf0;
5902
5903
0
                          if (!xflip)
5904
0
        {
5905
0
          cptr ++;
5906
0
          mptr ++;
5907
0
          yptr ++;
5908
0
          kptr ++;
5909
0
        }
5910
0
        break;
5911
0
                    }
5912
0
            break;
5913
0
      }
5914
0
            break;
5915
5916
0
  case 8 :
5917
0
            switch (cups->header.cupsColorSpace)
5918
0
      {
5919
0
        default :
5920
0
            if (xflip)
5921
0
              for (x = cups->width; x > 0; x --)
5922
0
        {
5923
0
          *cptr-- = *srcptr++;
5924
0
          *mptr-- = *srcptr++;
5925
0
          *yptr-- = *srcptr++;
5926
0
        }
5927
0
      else
5928
0
              for (x = cups->width; x > 0; x --)
5929
0
        {
5930
0
          *cptr++ = *srcptr++;
5931
0
          *mptr++ = *srcptr++;
5932
0
          *yptr++ = *srcptr++;
5933
0
        }
5934
0
            break;
5935
0
        case CUPS_CSPACE_GMCK :
5936
0
        case CUPS_CSPACE_GMCS :
5937
0
        case CUPS_CSPACE_RGBA :
5938
0
        case CUPS_CSPACE_RGBW :
5939
0
        case CUPS_CSPACE_CMYK :
5940
0
        case CUPS_CSPACE_YMCK :
5941
0
        case CUPS_CSPACE_KCMY :
5942
0
        case CUPS_CSPACE_KCMYcm :
5943
0
            if (xflip)
5944
0
              for (x = cups->width; x > 0; x --)
5945
0
        {
5946
0
          *cptr-- = *srcptr++;
5947
0
          *mptr-- = *srcptr++;
5948
0
          *yptr-- = *srcptr++;
5949
0
          *kptr-- = *srcptr++;
5950
0
        }
5951
0
      else
5952
0
              for (x = cups->width; x > 0; x --)
5953
0
        {
5954
0
          *cptr++ = *srcptr++;
5955
0
          *mptr++ = *srcptr++;
5956
0
          *yptr++ = *srcptr++;
5957
0
          *kptr++ = *srcptr++;
5958
0
        }
5959
0
            break;
5960
0
      }
5961
0
            break;
5962
5963
0
  case 16 :
5964
0
            switch (cups->header.cupsColorSpace)
5965
0
      {
5966
0
        default :
5967
0
            if (xflip)
5968
0
              for (x = cups->width; x > 0; x --, srcptr += 6)
5969
0
        {
5970
0
          *cptr-- = srcptr[1];
5971
0
          *cptr-- = srcptr[0];
5972
0
          *mptr-- = srcptr[3];
5973
0
          *mptr-- = srcptr[2];
5974
0
          *yptr-- = srcptr[5];
5975
0
          *yptr-- = srcptr[4];
5976
0
        }
5977
0
      else
5978
0
              for (x = cups->width; x > 0; x --)
5979
0
        {
5980
0
          *cptr++ = *srcptr++;
5981
0
          *cptr++ = *srcptr++;
5982
0
          *mptr++ = *srcptr++;
5983
0
          *mptr++ = *srcptr++;
5984
0
          *yptr++ = *srcptr++;
5985
0
          *yptr++ = *srcptr++;
5986
0
        }
5987
0
            break;
5988
0
        case CUPS_CSPACE_GMCK :
5989
0
        case CUPS_CSPACE_GMCS :
5990
0
        case CUPS_CSPACE_RGBA :
5991
0
        case CUPS_CSPACE_RGBW :
5992
0
        case CUPS_CSPACE_CMYK :
5993
0
        case CUPS_CSPACE_YMCK :
5994
0
        case CUPS_CSPACE_KCMY :
5995
0
        case CUPS_CSPACE_KCMYcm :
5996
0
            if (xflip)
5997
0
              for (x = cups->width; x > 0; x --, srcptr += 8)
5998
0
        {
5999
0
          *cptr-- = srcptr[1];
6000
0
          *cptr-- = srcptr[0];
6001
0
          *mptr-- = srcptr[3];
6002
0
          *mptr-- = srcptr[2];
6003
0
          *yptr-- = srcptr[5];
6004
0
          *yptr-- = srcptr[4];
6005
0
          *kptr-- = srcptr[7];
6006
0
          *kptr-- = srcptr[6];
6007
0
        }
6008
0
      else
6009
0
              for (x = cups->width; x > 0; x --)
6010
0
        {
6011
0
          *cptr++ = *srcptr++;
6012
0
          *cptr++ = *srcptr++;
6013
0
          *mptr++ = *srcptr++;
6014
0
          *mptr++ = *srcptr++;
6015
0
          *yptr++ = *srcptr++;
6016
0
          *yptr++ = *srcptr++;
6017
0
          *kptr++ = *srcptr++;
6018
0
          *kptr++ = *srcptr++;
6019
0
        }
6020
0
            break;
6021
0
      }
6022
0
            break;
6023
0
      }
6024
0
    }
6025
6026
   /*
6027
    * Write the bitmap data to the raster stream...
6028
    */
6029
6030
0
    cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
6031
0
  }
6032
0
  return (0);
6033
0
}
6034
6035
6036
/*
6037
 * 'cups_print_planar()' - Print a page of planar pixels.
6038
 */
6039
6040
static int
6041
cups_print_planar(gx_device_printer *pdev,
6042
          /* I - Printer device */
6043
                  unsigned char     *src,
6044
          /* I - Scanline buffer */
6045
      unsigned char     *dst,
6046
          /* I - Bitmap buffer */
6047
      int               srcbytes)
6048
          /* I - Number of bytes in src */
6049
0
{
6050
0
  int   x;      /* Looping var */
6051
0
  int   y;      /* Looping var */
6052
0
  unsigned char z;      /* Looping var */
6053
0
  unsigned char srcbit;     /* Current source bit */
6054
0
  unsigned char dstbit;     /* Current destination bit */
6055
0
  unsigned char temp;     /* Temporary variable */
6056
0
  unsigned char *srcptr;    /* Pointer to data */
6057
0
  unsigned char *dstptr;    /* Pointer to bitmap */
6058
6059
6060
 /**** NOTE: Currently planar output doesn't support flipped duplex!!! ****/
6061
6062
 /*
6063
  * Loop through the page bitmap and write planar pixels...  We have
6064
  * to separate each chunked color as needed...
6065
  */
6066
6067
0
  for (z = 0; z < pdev->color_info.num_components; z ++)
6068
0
    for (y = 0; y < cups->height; y ++)
6069
0
    {
6070
     /*
6071
      * Grab the scanline data...
6072
      */
6073
6074
0
      if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
6075
0
      {
6076
0
        dmprintf1(pdev->memory, "ERROR: Unable to get scanline %d!\n", y);
6077
0
  return_error(gs_error_unknownerror);
6078
0
      }
6079
6080
     /*
6081
      * Pull the individual color planes out of the pixels...
6082
      */
6083
6084
0
      if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
6085
0
  memset(dst, 0, cups->header.cupsBytesPerLine);
6086
0
      else
6087
0
  switch (cups->header.cupsBitsPerColor)
6088
0
  {
6089
0
          default :
6090
0
        memset(dst, 0, cups->header.cupsBytesPerLine);
6091
6092
0
        switch (cups->header.cupsColorSpace)
6093
0
        {
6094
0
    default :
6095
0
              for (dstptr = dst, x = cups->width, srcbit = 64 >> z,
6096
0
                 dstbit = 128;
6097
0
       x > 0;
6098
0
       x --)
6099
0
        {
6100
0
          if (*srcptr & srcbit)
6101
0
      *dstptr |= dstbit;
6102
6103
0
                      if (srcbit >= 16)
6104
0
      srcbit >>= 4;
6105
0
          else
6106
0
          {
6107
0
      srcbit = 64 >> z;
6108
0
      srcptr ++;
6109
0
          }
6110
6111
0
                      if (dstbit > 1)
6112
0
      dstbit >>= 1;
6113
0
          else
6114
0
          {
6115
0
      dstbit = 128;
6116
0
      dstptr ++;
6117
0
          }
6118
0
        }
6119
0
              break;
6120
0
    case CUPS_CSPACE_GMCK :
6121
0
    case CUPS_CSPACE_GMCS :
6122
0
    case CUPS_CSPACE_RGBA :
6123
0
    case CUPS_CSPACE_RGBW :
6124
0
    case CUPS_CSPACE_CMYK :
6125
0
    case CUPS_CSPACE_YMCK :
6126
0
    case CUPS_CSPACE_KCMY :
6127
0
              for (dstptr = dst, x = cups->width, srcbit = 128 >> z,
6128
0
                 dstbit = 128;
6129
0
       x > 0;
6130
0
       x --)
6131
0
        {
6132
0
          if (*srcptr & srcbit)
6133
0
      *dstptr |= dstbit;
6134
6135
0
                      if (srcbit >= 16)
6136
0
      srcbit >>= 4;
6137
0
          else
6138
0
          {
6139
0
      srcbit = 128 >> z;
6140
0
      srcptr ++;
6141
0
          }
6142
6143
0
                      if (dstbit > 1)
6144
0
      dstbit >>= 1;
6145
0
          else
6146
0
          {
6147
0
      dstbit = 128;
6148
0
      dstptr ++;
6149
0
          }
6150
0
        }
6151
0
              break;
6152
0
    case CUPS_CSPACE_KCMYcm :
6153
0
              for (dstptr = dst, x = cups->width, srcbit = 32 >> z,
6154
0
                 dstbit = 128;
6155
0
       x > 0;
6156
0
       x --, srcptr ++)
6157
0
        {
6158
0
          if (*srcptr & srcbit)
6159
0
      *dstptr |= dstbit;
6160
6161
0
                      if (dstbit > 1)
6162
0
      dstbit >>= 1;
6163
0
          else
6164
0
          {
6165
0
      dstbit = 128;
6166
0
      dstptr ++;
6167
0
          }
6168
0
        }
6169
0
              break;
6170
0
              }
6171
0
        break;
6172
6173
0
    case 2 :
6174
0
        memset(dst, 0, cups->header.cupsBytesPerLine);
6175
6176
0
        switch (cups->header.cupsColorSpace)
6177
0
        {
6178
0
    default :
6179
0
              for (dstptr = dst, x = cups->width, srcbit = 48 >> (z * 2),
6180
0
                 dstbit = 0xc0;
6181
0
       x > 0;
6182
0
       x --, srcptr ++)
6183
0
        {
6184
0
          if ((temp = *srcptr & srcbit) != 0)
6185
0
          {
6186
0
      if (srcbit == dstbit)
6187
0
              *dstptr |= temp;
6188
0
            else
6189
0
      {
6190
0
              switch (srcbit)
6191
0
        {
6192
0
          case 0x30 :
6193
0
        temp >>= 4;
6194
0
        break;
6195
0
          case 0x0c :
6196
0
        temp >>= 2;
6197
0
        break;
6198
0
                          }
6199
6200
0
              switch (dstbit)
6201
0
        {
6202
0
          case 0xc0 :
6203
0
        *dstptr |= temp << 6;
6204
0
        break;
6205
0
          case 0x30 :
6206
0
        *dstptr |= temp << 4;
6207
0
        break;
6208
0
          case 0x0c :
6209
0
        *dstptr |= temp << 2;
6210
0
        break;
6211
0
          case 0x03 :
6212
0
        *dstptr |= temp;
6213
0
        break;
6214
0
                          }
6215
0
      }
6216
0
          }
6217
6218
0
          if (dstbit > 0x03)
6219
0
      dstbit >>= 2;
6220
0
          else
6221
0
          {
6222
0
      dstbit = 0xc0;
6223
0
      dstptr ++;
6224
0
          }
6225
0
        }
6226
0
              break;
6227
0
    case CUPS_CSPACE_GMCK :
6228
0
    case CUPS_CSPACE_GMCS :
6229
0
    case CUPS_CSPACE_RGBA :
6230
0
    case CUPS_CSPACE_RGBW :
6231
0
    case CUPS_CSPACE_CMYK :
6232
0
    case CUPS_CSPACE_YMCK :
6233
0
    case CUPS_CSPACE_KCMY :
6234
0
    case CUPS_CSPACE_KCMYcm :
6235
0
              for (dstptr = dst, x = cups->width, srcbit = 192 >> (z * 2),
6236
0
                 dstbit = 0xc0;
6237
0
       x > 0;
6238
0
       x --, srcptr ++)
6239
0
        {
6240
0
          if ((temp = *srcptr & srcbit) != 0)
6241
0
          {
6242
0
      if (srcbit == dstbit)
6243
0
              *dstptr |= temp;
6244
0
            else
6245
0
      {
6246
0
              switch (srcbit)
6247
0
        {
6248
0
          case 0xc0 :
6249
0
        temp >>= 6;
6250
0
        break;
6251
0
          case 0x30 :
6252
0
        temp >>= 4;
6253
0
        break;
6254
0
          case 0x0c :
6255
0
        temp >>= 2;
6256
0
        break;
6257
0
                          }
6258
6259
0
              switch (dstbit)
6260
0
        {
6261
0
          case 0xc0 :
6262
0
        *dstptr |= temp << 6;
6263
0
        break;
6264
0
          case 0x30 :
6265
0
        *dstptr |= temp << 4;
6266
0
        break;
6267
0
          case 0x0c :
6268
0
        *dstptr |= temp << 2;
6269
0
        break;
6270
0
          case 0x03 :
6271
0
        *dstptr |= temp;
6272
0
        break;
6273
0
                          }
6274
0
      }
6275
0
          }
6276
6277
0
          if (dstbit > 0x03)
6278
0
      dstbit >>= 2;
6279
0
          else
6280
0
          {
6281
0
      dstbit = 0xc0;
6282
0
      dstptr ++;
6283
0
          }
6284
0
        }
6285
0
              break;
6286
0
              }
6287
0
        break;
6288
6289
0
    case 4 :
6290
0
        memset(dst, 0, cups->header.cupsBytesPerLine);
6291
6292
0
        switch (cups->header.cupsColorSpace)
6293
0
        {
6294
0
    default :
6295
0
              if (z > 0)
6296
0
          srcptr ++;
6297
6298
0
        if (z == 1)
6299
0
          srcbit = 0xf0;
6300
0
        else
6301
0
          srcbit = 0x0f;
6302
6303
0
              for (dstptr = dst, x = cups->width, dstbit = 0xf0;
6304
0
       x > 0;
6305
0
       x --, srcptr += 2)
6306
0
        {
6307
0
          if ((temp = *srcptr & srcbit) != 0)
6308
0
          {
6309
0
      if (srcbit == dstbit)
6310
0
              *dstptr |= temp;
6311
0
            else
6312
0
      {
6313
0
              if (srcbit == 0xf0)
6314
0
                      temp >>= 4;
6315
6316
0
              if (dstbit == 0xf0)
6317
0
            *dstptr |= temp << 4;
6318
0
        else
6319
0
          *dstptr |= temp;
6320
0
      }
6321
0
          }
6322
6323
0
          if (dstbit == 0xf0)
6324
0
      dstbit = 0x0f;
6325
0
          else
6326
0
          {
6327
0
      dstbit = 0xf0;
6328
0
      dstptr ++;
6329
0
          }
6330
0
        }
6331
0
              break;
6332
0
    case CUPS_CSPACE_GMCK :
6333
0
    case CUPS_CSPACE_GMCS :
6334
0
    case CUPS_CSPACE_RGBA :
6335
0
    case CUPS_CSPACE_RGBW :
6336
0
    case CUPS_CSPACE_CMYK :
6337
0
    case CUPS_CSPACE_YMCK :
6338
0
    case CUPS_CSPACE_KCMY :
6339
0
    case CUPS_CSPACE_KCMYcm :
6340
0
              if (z > 1)
6341
0
          srcptr ++;
6342
6343
0
        if (z & 1)
6344
0
          srcbit = 0x0f;
6345
0
        else
6346
0
          srcbit = 0xf0;
6347
6348
0
              for (dstptr = dst, x = cups->width, dstbit = 0xf0;
6349
0
       x > 0;
6350
0
       x --, srcptr += 2)
6351
0
        {
6352
0
          if ((temp = *srcptr & srcbit) != 0)
6353
0
          {
6354
0
      if (srcbit == dstbit)
6355
0
              *dstptr |= temp;
6356
0
            else
6357
0
      {
6358
0
              if (srcbit == 0xf0)
6359
0
                      temp >>= 4;
6360
6361
0
              if (dstbit == 0xf0)
6362
0
            *dstptr |= temp << 4;
6363
0
        else
6364
0
          *dstptr |= temp;
6365
0
      }
6366
0
          }
6367
6368
0
          if (dstbit == 0xf0)
6369
0
      dstbit = 0x0f;
6370
0
          else
6371
0
          {
6372
0
      dstbit = 0xf0;
6373
0
      dstptr ++;
6374
0
          }
6375
0
        }
6376
0
              break;
6377
0
              }
6378
0
        break;
6379
6380
0
    case 8 :
6381
0
        for (srcptr += z, dstptr = dst, x = cups->header.cupsBytesPerLine;
6382
0
             x > 0;
6383
0
       srcptr += pdev->color_info.num_components, x --)
6384
0
    *dstptr++ = *srcptr;
6385
0
        break;
6386
6387
0
    case 16 :
6388
0
        for (srcptr += 2 * z, dstptr = dst, x = cups->header.cupsBytesPerLine;
6389
0
             x > 0;
6390
0
       srcptr += 2 * pdev->color_info.num_components, x --)
6391
0
              {
6392
0
    *dstptr++ = srcptr[0];
6393
0
    *dstptr++ = srcptr[1];
6394
0
        }
6395
0
        break;
6396
0
  }
6397
6398
     /*
6399
      * Write the bitmap data to the raster stream...
6400
      */
6401
6402
0
      cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
6403
0
    }
6404
0
  return (0);
6405
0
}
6406
6407
private int
6408
cups_spec_op(gx_device *dev_, int op, void *data, int datasize)
6409
35.4M
{
6410
35.4M
    return gx_default_dev_spec_op(dev_, op, data, datasize);
6411
35.4M
}
6412
6413
#ifdef __GNUC__
6414
#pragma GCC diagnostic pop
6415
#endif
6416
/*
6417
 */