Coverage Report

Created: 2026-10-28 08:05

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