Coverage Report

Created: 2022-10-31 07:00

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