~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to devices/gdevxcf.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
 
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
7
   This software is distributed under license and may not be copied,
 
8
   modified or distributed except as expressly authorized under the terms
 
9
   of the license contained in the file LICENSE in this distribution.
 
10
 
 
11
   Refer to licensing information at http://www.artifex.com or contact
 
12
   Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
 
13
   CA  94903, U.S.A., +1(415)492-9861, for further information.
 
14
*/
 
15
 
 
16
 
 
17
/* Gimp (XCF) export device, supporting DeviceN color models. */
 
18
 
 
19
#include "math_.h"
 
20
#include "gdevprn.h"
 
21
#include "gsparam.h"
 
22
#include "gscrd.h"
 
23
#include "gscrdp.h"
 
24
#include "gxlum.h"
 
25
#include "gdevdcrd.h"
 
26
#include "gstypes.h"
 
27
#include "gxdcconv.h"
 
28
#include "gscms.h"
 
29
#include "gsicc_cache.h"
 
30
#include "gsicc_manage.h"
 
31
 
 
32
#ifndef cmm_gcmmhlink_DEFINED
 
33
    #define cmm_gcmmhlink_DEFINED
 
34
    typedef void* gcmmhlink_t;
 
35
#endif
 
36
 
 
37
#ifndef cmm_gcmmhprofile_DEFINED
 
38
    #define cmm_gcmmhprofile_DEFINED
 
39
    typedef void* gcmmhprofile_t;
 
40
#endif
 
41
 
 
42
#ifndef MAX_CHAN
 
43
#   define MAX_CHAN 8
 
44
#endif
 
45
 
 
46
/* Define the device parameters. */
 
47
#ifndef X_DPI
 
48
#  define X_DPI 72
 
49
#endif
 
50
#ifndef Y_DPI
 
51
#  define Y_DPI 72
 
52
#endif
 
53
 
 
54
/* The device descriptor */
 
55
static dev_proc_get_params(xcf_get_params);
 
56
static dev_proc_close_device(xcf_prn_close);
 
57
static dev_proc_put_params(xcf_put_params);
 
58
static dev_proc_print_page(xcf_print_page);
 
59
static dev_proc_map_color_rgb(xcf_map_color_rgb);
 
60
static dev_proc_get_color_mapping_procs(get_spotrgb_color_mapping_procs);
 
61
#if 0
 
62
static dev_proc_get_color_mapping_procs(get_spotcmyk_color_mapping_procs);
 
63
#endif
 
64
static dev_proc_get_color_mapping_procs(get_xcf_color_mapping_procs);
 
65
static dev_proc_get_color_comp_index(xcf_get_color_comp_index);
 
66
static dev_proc_encode_color(xcf_encode_color);
 
67
static dev_proc_decode_color(xcf_decode_color);
 
68
 
 
69
/*
 
70
 * Type definitions associated with the fixed color model names.
 
71
 */
 
72
typedef const char * fixed_colorant_name;
 
73
typedef fixed_colorant_name fixed_colorant_names_list[];
 
74
 
 
75
/*
 
76
 * Structure for holding SeparationNames and SeparationOrder elements.
 
77
 */
 
78
typedef struct gs_separation_names_s {
 
79
    int num_names;
 
80
    const gs_param_string * names[GX_DEVICE_COLOR_MAX_COMPONENTS];
 
81
} gs_separation_names;
 
82
 
 
83
/* This is redundant with color_info.cm_name. We may eliminate this
 
84
   typedef and use the latter string for everything. */
 
85
typedef enum {
 
86
    XCF_DEVICE_GRAY,
 
87
    XCF_DEVICE_RGB,
 
88
    XCF_DEVICE_CMYK,
 
89
    XCF_DEVICE_N
 
90
} xcf_color_model;
 
91
 
 
92
/*
 
93
 * A structure definition for a DeviceN type device
 
94
 */
 
95
typedef struct xcf_device_s {
 
96
    gx_device_common;
 
97
    gx_prn_device_common;
 
98
 
 
99
    /*        ... device-specific parameters ... */
 
100
 
 
101
    xcf_color_model color_model;
 
102
 
 
103
    /*
 
104
     * Bits per component (device colorant).  Currently only 1 and 8 are
 
105
     * supported.
 
106
     */
 
107
    int bitspercomponent;
 
108
 
 
109
    /*
 
110
     * Pointer to the colorant names for the color model.  This will be
 
111
     * null if we have DeviceN type device.  The actual possible colorant
 
112
     * names are those in this list plus those in the separation_names
 
113
     * list (below).
 
114
     */
 
115
    const fixed_colorant_names_list * std_colorant_names;
 
116
    int num_std_colorant_names; /* Number of names in list */
 
117
 
 
118
    /*
 
119
    * Separation names (if any).
 
120
    */
 
121
    gs_separation_names separation_names;
 
122
 
 
123
    /*
 
124
     * Separation Order (if specified).
 
125
     */
 
126
    gs_separation_names separation_order;
 
127
 
 
128
    /* ICC color profile objects, for color conversion.
 
129
       These are all device link profiles.  At least that
 
130
       is how it appears looking at how this code
 
131
       was written to work with the old icclib.  Just
 
132
       doing minimal updates here so that it works
 
133
       with the new CMM API.  I would be interested
 
134
       to hear how people are using this. */
 
135
 
 
136
    char profile_rgb_fn[256];
 
137
    cmm_profile_t *rgb_profile;
 
138
    gcmmhlink_t rgb_icc_link;
 
139
 
 
140
    char profile_cmyk_fn[256];
 
141
    cmm_profile_t *cmyk_profile;
 
142
    gcmmhlink_t cmyk_icc_link;
 
143
 
 
144
    char profile_out_fn[256];
 
145
    cmm_profile_t *output_profile;
 
146
    gcmmhlink_t output_icc_link;
 
147
 
 
148
} xcf_device;
 
149
 
 
150
/*
 
151
 * Macro definition for DeviceN procedures
 
152
 */
 
153
#define device_procs(get_color_mapping_procs)\
 
154
{       gdev_prn_open,\
 
155
        gx_default_get_initial_matrix,\
 
156
        NULL,                           /* sync_output */\
 
157
        /* Since the print_page doesn't alter the device, this device can print in the background */\
 
158
        gdev_prn_bg_output_page,                /* output_page */\
 
159
        xcf_prn_close,                  /* close */\
 
160
        NULL,                           /* map_rgb_color - not used */\
 
161
        xcf_map_color_rgb,              /* map_color_rgb */\
 
162
        NULL,                           /* fill_rectangle */\
 
163
        NULL,                           /* tile_rectangle */\
 
164
        NULL,                           /* copy_mono */\
 
165
        NULL,                           /* copy_color */\
 
166
        NULL,                           /* draw_line */\
 
167
        NULL,                           /* get_bits */\
 
168
        xcf_get_params,         /* get_params */\
 
169
        xcf_put_params,         /* put_params */\
 
170
        NULL,                           /* map_cmyk_color - not used */\
 
171
        NULL,                           /* get_xfont_procs */\
 
172
        NULL,                           /* get_xfont_device */\
 
173
        NULL,                           /* map_rgb_alpha_color */\
 
174
        gx_page_device_get_page_device, /* get_page_device */\
 
175
        NULL,                           /* get_alpha_bits */\
 
176
        NULL,                           /* copy_alpha */\
 
177
        NULL,                           /* get_band */\
 
178
        NULL,                           /* copy_rop */\
 
179
        NULL,                           /* fill_path */\
 
180
        NULL,                           /* stroke_path */\
 
181
        NULL,                           /* fill_mask */\
 
182
        NULL,                           /* fill_trapezoid */\
 
183
        NULL,                           /* fill_parallelogram */\
 
184
        NULL,                           /* fill_triangle */\
 
185
        NULL,                           /* draw_thin_line */\
 
186
        NULL,                           /* begin_image */\
 
187
        NULL,                           /* image_data */\
 
188
        NULL,                           /* end_image */\
 
189
        NULL,                           /* strip_tile_rectangle */\
 
190
        NULL,                           /* strip_copy_rop */\
 
191
        NULL,                           /* get_clipping_box */\
 
192
        NULL,                           /* begin_typed_image */\
 
193
        NULL,                           /* get_bits_rectangle */\
 
194
        NULL,                           /* map_color_rgb_alpha */\
 
195
        NULL,                           /* create_compositor */\
 
196
        NULL,                           /* get_hardware_params */\
 
197
        NULL,                           /* text_begin */\
 
198
        NULL,                           /* finish_copydevice */\
 
199
        NULL,                           /* begin_transparency_group */\
 
200
        NULL,                           /* end_transparency_group */\
 
201
        NULL,                           /* begin_transparency_mask */\
 
202
        NULL,                           /* end_transparency_mask */\
 
203
        NULL,                           /* discard_transparency_layer */\
 
204
        get_color_mapping_procs,        /* get_color_mapping_procs */\
 
205
        xcf_get_color_comp_index,       /* get_color_comp_index */\
 
206
        xcf_encode_color,               /* encode_color */\
 
207
        xcf_decode_color                /* decode_color */\
 
208
}
 
209
 
 
210
static const fixed_colorant_names_list DeviceGrayComponents = {
 
211
        "Gray",
 
212
        0               /* List terminator */
 
213
};
 
214
 
 
215
static const fixed_colorant_names_list DeviceRGBComponents = {
 
216
        "Red",
 
217
        "Green",
 
218
        "Blue",
 
219
        0               /* List terminator */
 
220
};
 
221
 
 
222
static const fixed_colorant_names_list DeviceCMYKComponents = {
 
223
        "Cyan",
 
224
        "Magenta",
 
225
        "Yellow",
 
226
        "Black",
 
227
        0               /* List terminator */
 
228
};
 
229
 
 
230
/*
 
231
 * Example device with RGB and spot color support
 
232
 */
 
233
static const gx_device_procs spot_rgb_procs = device_procs(get_spotrgb_color_mapping_procs);
 
234
 
 
235
const xcf_device gs_xcf_device =
 
236
{
 
237
    prn_device_body_extended(xcf_device, spot_rgb_procs, "xcf",
 
238
         DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
 
239
         X_DPI, Y_DPI,          /* X and Y hardware resolution */
 
240
         0, 0, 0, 0,            /* margins */
 
241
         GX_DEVICE_COLOR_MAX_COMPONENTS, 3,     /* MaxComponents, NumComp */
 
242
         GX_CINFO_POLARITY_ADDITIVE,            /* Polarity */
 
243
         24, 0,                 /* Depth, Gray_index, */
 
244
         255, 255, 256, 256,    /* MaxGray, MaxColor, DitherGray, DitherColor */
 
245
         GX_CINFO_UNKNOWN_SEP_LIN, /* Let check_device_separable set up values */
 
246
         "DeviceN",             /* Process color model name */
 
247
         xcf_print_page),       /* Printer page print routine */
 
248
    /* DeviceN device specific parameters */
 
249
    XCF_DEVICE_RGB,             /* Color model */
 
250
    8,                          /* Bits per color - must match ncomp, depth, etc. above */
 
251
    (&DeviceRGBComponents),     /* Names of color model colorants */
 
252
    3,                          /* Number colorants for RGB */
 
253
    {0},                        /* SeparationNames */
 
254
    {0}                         /* SeparationOrder names */
 
255
};
 
256
 
 
257
static const gx_device_procs spot_cmyk_procs = device_procs(get_xcf_color_mapping_procs);
 
258
 
 
259
const xcf_device gs_xcfcmyk_device =
 
260
{
 
261
    prn_device_body_extended(xcf_device, spot_cmyk_procs, "xcfcmyk",
 
262
         DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
 
263
         X_DPI, Y_DPI,          /* X and Y hardware resolution */
 
264
         0, 0, 0, 0,            /* margins */
 
265
         GX_DEVICE_COLOR_MAX_COMPONENTS, 4,     /* MaxComponents, NumComp */
 
266
         GX_CINFO_POLARITY_SUBTRACTIVE,         /* Polarity */
 
267
         32, 0,                 /* Depth, Gray_index, */
 
268
         255, 255, 256, 256,    /* MaxGray, MaxColor, DitherGray, DitherColor */
 
269
         GX_CINFO_UNKNOWN_SEP_LIN, /* Let check_device_separable set up values */
 
270
         "DeviceN",             /* Process color model name */
 
271
         xcf_print_page),       /* Printer page print routine */
 
272
    /* DeviceN device specific parameters */
 
273
    XCF_DEVICE_CMYK,            /* Color model */
 
274
    8,                          /* Bits per color - must match ncomp, depth, etc. above */
 
275
    (&DeviceCMYKComponents),    /* Names of color model colorants */
 
276
    4,                          /* Number colorants for RGB */
 
277
    {0},                        /* SeparationNames */
 
278
    {0}                         /* SeparationOrder names */
 
279
};
 
280
 
 
281
/*
 
282
 * The following procedures are used to map the standard color spaces into
 
283
 * the color components for the spotrgb device.
 
284
 */
 
285
static void
 
286
gray_cs_to_spotrgb_cm(gx_device * dev, frac gray, frac out[])
 
287
{
 
288
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
289
    int i = ((xcf_device *)dev)->separation_names.num_names;
 
290
 
 
291
    out[0] = out[1] = out[2] = gray;
 
292
    for(; i>0; i--)                     /* Clear spot colors */
 
293
        out[2 + i] = 0;
 
294
}
 
295
 
 
296
static void
 
297
rgb_cs_to_spotrgb_cm(gx_device * dev, const gs_imager_state *pis,
 
298
                                  frac r, frac g, frac b, frac out[])
 
299
{
 
300
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
301
    int i = ((xcf_device *)dev)->separation_names.num_names;
 
302
 
 
303
    out[0] = r;
 
304
    out[1] = g;
 
305
    out[2] = b;
 
306
    for(; i>0; i--)                     /* Clear spot colors */
 
307
        out[2 + i] = 0;
 
308
}
 
309
 
 
310
static void
 
311
cmyk_cs_to_spotrgb_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
 
312
{
 
313
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
314
    int i = ((xcf_device *)dev)->separation_names.num_names;
 
315
 
 
316
    color_cmyk_to_rgb(c, m, y, k, NULL, out, dev->memory);
 
317
    for(; i>0; i--)                     /* Clear spot colors */
 
318
        out[2 + i] = 0;
 
319
}
 
320
 
 
321
static void
 
322
gray_cs_to_spotcmyk_cm(gx_device * dev, frac gray, frac out[])
 
323
{
 
324
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
325
    int i = ((xcf_device *)dev)->separation_names.num_names;
 
326
 
 
327
    out[0] = out[1] = out[2] = 0;
 
328
    out[3] = frac_1 - gray;
 
329
    for(; i>0; i--)                     /* Clear spot colors */
 
330
        out[3 + i] = 0;
 
331
}
 
332
 
 
333
static void
 
334
rgb_cs_to_spotcmyk_cm(gx_device * dev, const gs_imager_state *pis,
 
335
                                   frac r, frac g, frac b, frac out[])
 
336
{
 
337
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
338
    xcf_device *xdev = (xcf_device *)dev;
 
339
    int n = xdev->separation_names.num_names;
 
340
    int i;
 
341
 
 
342
    color_rgb_to_cmyk(r, g, b, pis, out, dev->memory);
 
343
    for(i = 0; i < n; i++)                      /* Clear spot colors */
 
344
        out[4 + i] = 0;
 
345
}
 
346
 
 
347
static void
 
348
cmyk_cs_to_spotcmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
 
349
{
 
350
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
351
    xcf_device *xdev = (xcf_device *)dev;
 
352
    int n = xdev->separation_names.num_names;
 
353
    int i;
 
354
 
 
355
    out[0] = c;
 
356
    out[1] = m;
 
357
    out[2] = y;
 
358
    out[3] = k;
 
359
    for(i = 0; i < n; i++)                      /* Clear spot colors */
 
360
        out[4 + i] = 0;
 
361
}
 
362
 
 
363
static void
 
364
cmyk_cs_to_spotn_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
 
365
{
 
366
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
367
    xcf_device *xdev = (xcf_device *)dev;
 
368
    int n = xdev->separation_names.num_names;
 
369
 
 
370
    gcmmhlink_t link = xdev->cmyk_icc_link;
 
371
    int i;
 
372
 
 
373
    if (link != NULL) {
 
374
        unsigned short in[4];
 
375
        unsigned short tmp[MAX_CHAN];
 
376
        int outn = xdev->cmyk_profile->num_comps_out;
 
377
 
 
378
        in[0] = frac2ushort(c);
 
379
        in[1] = frac2ushort(m);
 
380
        in[2] = frac2ushort(y);
 
381
        in[3] = frac2ushort(k);
 
382
 
 
383
        gscms_transform_color(dev, link, &(in[0]), &(tmp[0]), 2);
 
384
        for (i = 0; i < outn; i++)
 
385
            out[i] = ushort2frac(tmp[i]);
 
386
        for (; i < n + 4; i++)
 
387
            out[i] = 0;
 
388
 
 
389
    } else {
 
390
        /* If no profile given, assume CMYK */
 
391
        out[0] = c;
 
392
        out[1] = m;
 
393
        out[2] = y;
 
394
        out[3] = k;
 
395
        for(i = 0; i < n; i++)                  /* Clear spot colors */
 
396
            out[4 + i] = 0;
 
397
    }
 
398
}
 
399
 
 
400
static void
 
401
gray_cs_to_spotn_cm(gx_device * dev, frac gray, frac out[])
 
402
{
 
403
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
404
 
 
405
    cmyk_cs_to_spotn_cm(dev, 0, 0, 0, frac_1 - gray, out);
 
406
}
 
407
 
 
408
static void
 
409
rgb_cs_to_spotn_cm(gx_device * dev, const gs_imager_state *pis,
 
410
                                   frac r, frac g, frac b, frac out[])
 
411
{
 
412
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
413
    xcf_device *xdev = (xcf_device *)dev;
 
414
    int n = xdev->separation_names.num_names;
 
415
    gcmmhlink_t link = xdev->rgb_icc_link;
 
416
    int i;
 
417
 
 
418
    if (link != NULL) {
 
419
        unsigned short in[3];
 
420
        unsigned short tmp[MAX_CHAN];
 
421
        int outn = xdev->rgb_profile->num_comps_out;
 
422
 
 
423
        in[0] = frac2ushort(r);
 
424
        in[1] = frac2ushort(g);
 
425
        in[2] = frac2ushort(b);
 
426
 
 
427
        gscms_transform_color(dev, link, &(in[0]), &(tmp[0]), 2);
 
428
 
 
429
        for (i = 0; i < outn; i++)
 
430
            out[i] = ushort2frac(tmp[i]);
 
431
        for (; i < n + 4; i++)
 
432
            out[i] = 0;
 
433
    } else {
 
434
        frac cmyk[4];
 
435
 
 
436
        color_rgb_to_cmyk(r, g, b, pis, cmyk, dev->memory);
 
437
        cmyk_cs_to_spotn_cm(dev, cmyk[0], cmyk[1], cmyk[2], cmyk[3],
 
438
                            out);
 
439
    }
 
440
}
 
441
 
 
442
static const gx_cm_color_map_procs spotRGB_procs = {
 
443
    gray_cs_to_spotrgb_cm, rgb_cs_to_spotrgb_cm, cmyk_cs_to_spotrgb_cm
 
444
};
 
445
 
 
446
static const gx_cm_color_map_procs spotCMYK_procs = {
 
447
    gray_cs_to_spotcmyk_cm, rgb_cs_to_spotcmyk_cm, cmyk_cs_to_spotcmyk_cm
 
448
};
 
449
 
 
450
static const gx_cm_color_map_procs spotN_procs = {
 
451
    gray_cs_to_spotn_cm, rgb_cs_to_spotn_cm, cmyk_cs_to_spotn_cm
 
452
};
 
453
 
 
454
/*
 
455
 * These are the handlers for returning the list of color space
 
456
 * to color model conversion routines.
 
457
 */
 
458
static const gx_cm_color_map_procs *
 
459
get_spotrgb_color_mapping_procs(const gx_device * dev)
 
460
{
 
461
    return &spotRGB_procs;
 
462
}
 
463
 
 
464
#if 0
 
465
static const gx_cm_color_map_procs *
 
466
get_spotcmyk_color_mapping_procs(const gx_device * dev)
 
467
{
 
468
    return &spotCMYK_procs;
 
469
}
 
470
#endif
 
471
 
 
472
static const gx_cm_color_map_procs *
 
473
get_xcf_color_mapping_procs(const gx_device * dev)
 
474
{
 
475
    const xcf_device *xdev = (const xcf_device *)dev;
 
476
 
 
477
    if (xdev->color_model == XCF_DEVICE_RGB)
 
478
        return &spotRGB_procs;
 
479
    else if (xdev->color_model == XCF_DEVICE_CMYK)
 
480
        return &spotCMYK_procs;
 
481
    else if (xdev->color_model == XCF_DEVICE_N)
 
482
        return &spotN_procs;
 
483
    else
 
484
        return NULL;
 
485
}
 
486
 
 
487
/*
 
488
 * Encode a list of colorant values into a gx_color_index_value.
 
489
 */
 
490
static gx_color_index
 
491
xcf_encode_color(gx_device *dev, const gx_color_value colors[])
 
492
{
 
493
    int bpc = ((xcf_device *)dev)->bitspercomponent;
 
494
    gx_color_index color = 0;
 
495
    int i = 0;
 
496
    int ncomp = dev->color_info.num_components;
 
497
    COLROUND_VARS;
 
498
 
 
499
    COLROUND_SETUP(bpc);
 
500
    for (; i<ncomp; i++) {
 
501
        color <<= bpc;
 
502
        color |= COLROUND_ROUND(colors[i]);
 
503
    }
 
504
    return (color == gx_no_color_index ? color ^ 1 : color);
 
505
}
 
506
 
 
507
/*
 
508
 * Decode a gx_color_index value back to a list of colorant values.
 
509
 */
 
510
static int
 
511
xcf_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
 
512
{
 
513
    int bpc = ((xcf_device *)dev)->bitspercomponent;
 
514
    int mask = (1 << bpc) - 1;
 
515
    int i = 0;
 
516
    int ncomp = dev->color_info.num_components;
 
517
    COLDUP_VARS;
 
518
 
 
519
    COLDUP_SETUP(bpc);
 
520
    for (; i<ncomp; i++) {
 
521
        out[ncomp - i - 1] = COLDUP_DUP(color & mask);
 
522
        color >>= bpc;
 
523
    }
 
524
    return 0;
 
525
}
 
526
 
 
527
/*
 
528
 * Convert a gx_color_index to RGB.
 
529
 */
 
530
static int
 
531
xcf_map_color_rgb(gx_device *dev, gx_color_index color, gx_color_value rgb[3])
 
532
{
 
533
    xcf_device *xdev = (xcf_device *)dev;
 
534
 
 
535
    if (xdev->color_model == XCF_DEVICE_RGB)
 
536
        return xcf_decode_color(dev, color, rgb);
 
537
    /* TODO: return reasonable values. */
 
538
    rgb[0] = 0;
 
539
    rgb[1] = 0;
 
540
    rgb[2] = 0;
 
541
    return 0;
 
542
}
 
543
 
 
544
/*
 
545
 * This routine will extract a specified set of bits from a buffer and pack
 
546
 * them into a given buffer.
 
547
 *
 
548
 * Parameters:
 
549
 *   source - The source of the data
 
550
 *   dest - The destination for the data
 
551
 *   depth - The size of the bits per pixel - must be a multiple of 8
 
552
 *   first_bit - The location of the first data bit (LSB).
 
553
 *   bit_width - The number of bits to be extracted.
 
554
 *   npixel - The number of pixels.
 
555
 *
 
556
 * Returns:
 
557
 *   Length of the output line (in bytes)
 
558
 *   Data in dest.
 
559
 */
 
560
#if 0
 
561
static int
 
562
repack_data(byte * source, byte * dest, int depth, int first_bit,
 
563
                int bit_width, int npixel)
 
564
{
 
565
    int in_nbyte = depth >> 3;          /* Number of bytes per input pixel */
 
566
    int out_nbyte = bit_width >> 3;     /* Number of bytes per output pixel */
 
567
    gx_color_index mask = 1;
 
568
    gx_color_index data;
 
569
    int i, j, length = 0;
 
570
    int in_byte_loc = 0, out_byte_loc = 0;
 
571
    byte temp;
 
572
    byte * out = dest;
 
573
    int max_bit_byte = 8 - bit_width;
 
574
 
 
575
    mask = (mask << bit_width) - 1;
 
576
    for (i=0; i<npixel; i++) {
 
577
        /* Get the pixel data */
 
578
        if (!in_nbyte) {                /* Multiple pixels per byte */
 
579
            data = *source;
 
580
            data >>= in_byte_loc;
 
581
            in_byte_loc += depth;
 
582
            if (in_byte_loc >= 8) {     /* If finished with byte */
 
583
                in_byte_loc = 0;
 
584
                source++;
 
585
            }
 
586
        }
 
587
        else {                          /* One or more bytes per pixel */
 
588
            data = *source++;
 
589
            for (j=1; j<in_nbyte; j++)
 
590
                data = (data << 8) + *source++;
 
591
        }
 
592
        data >>= first_bit;
 
593
        data &= mask;
 
594
 
 
595
        /* Put the output data */
 
596
        if (!out_nbyte) {               /* Multiple pixels per byte */
 
597
            temp = *out & ~(mask << out_byte_loc);
 
598
            *out = temp | (data << out_byte_loc);
 
599
            out_byte_loc += bit_width;
 
600
            if (out_byte_loc > max_bit_byte) {  /* If finished with byte */
 
601
                out_byte_loc = 0;
 
602
                out++;
 
603
            }
 
604
        }
 
605
        else {                          /* One or more bytes per pixel */
 
606
            *out++ = data >> ((out_nbyte - 1) * 8);
 
607
            for (j=1; j<out_nbyte; j++) {
 
608
                *out++ = data >> ((out_nbyte - 1 - j) * 8);
 
609
            }
 
610
        }
 
611
    }
 
612
    /* Return the number of bytes in the destination buffer. */
 
613
    length = out - dest;
 
614
    if (out_byte_loc)                   /* If partially filled last byte */
 
615
        length++;
 
616
    return length;
 
617
}
 
618
#endif /* 0 */
 
619
 
 
620
static int
 
621
xcf_open_profile(const char *profile_out_fn, cmm_profile_t *icc_profile, gcmmhlink_t icc_link, gs_memory_t *memory)
 
622
{
 
623
 
 
624
    gsicc_rendering_param_t rendering_params;
 
625
 
 
626
    icc_profile = gsicc_get_profile_handle_file(profile_out_fn,
 
627
                    strlen(profile_out_fn), memory);
 
628
 
 
629
    if (icc_profile == NULL)
 
630
        return gs_throw(-1, "Could not create profile for xcf device");
 
631
 
 
632
    /* Set up the rendering parameters */
 
633
 
 
634
    rendering_params.black_point_comp = gsBPNOTSPECIFIED;
 
635
    rendering_params.graphics_type_tag = GS_UNKNOWN_TAG;  /* Already rendered */
 
636
    rendering_params.rendering_intent = gsPERCEPTUAL;
 
637
 
 
638
    /* Call with a NULL destination profile since we are using a device link profile here */
 
639
    icc_link = gscms_get_link(icc_profile,
 
640
                              NULL, &rendering_params, memory);
 
641
 
 
642
    if (icc_link == NULL)
 
643
        return gs_throw(-1, "Could not create link handle for xdev device");
 
644
 
 
645
    return(0);
 
646
 
 
647
}
 
648
 
 
649
static int
 
650
xcf_open_profiles(xcf_device *xdev)
 
651
{
 
652
    int code = 0;
 
653
 
 
654
    if (xdev->output_icc_link == NULL && xdev->profile_out_fn[0]) {
 
655
 
 
656
        code = xcf_open_profile(xdev->profile_out_fn, xdev->output_profile,
 
657
            xdev->output_icc_link, xdev->memory);
 
658
 
 
659
    }
 
660
 
 
661
    if (code >= 0 && xdev->rgb_icc_link == NULL && xdev->profile_rgb_fn[0]) {
 
662
 
 
663
        code = xcf_open_profile(xdev->profile_rgb_fn, xdev->rgb_profile,
 
664
            xdev->rgb_icc_link, xdev->memory);
 
665
 
 
666
    }
 
667
 
 
668
    if (code >= 0 && xdev->cmyk_icc_link == NULL && xdev->profile_cmyk_fn[0]) {
 
669
 
 
670
        code = xcf_open_profile(xdev->profile_cmyk_fn, xdev->cmyk_profile,
 
671
            xdev->cmyk_icc_link, xdev->memory);
 
672
 
 
673
    }
 
674
 
 
675
    return code;
 
676
}
 
677
 
 
678
#define set_param_array(a, d, s)\
 
679
  (a.data = d, a.size = s, a.persistent = false);
 
680
 
 
681
/* Get parameters.  We provide a default CRD. */
 
682
static int
 
683
xcf_get_params(gx_device * pdev, gs_param_list * plist)
 
684
{
 
685
    xcf_device *xdev = (xcf_device *)pdev;
 
686
    int code;
 
687
    bool seprs = false;
 
688
    gs_param_string_array scna;
 
689
    gs_param_string pos;
 
690
    gs_param_string prgbs;
 
691
    gs_param_string pcmyks;
 
692
 
 
693
    set_param_array(scna, NULL, 0);
 
694
 
 
695
    if ( (code = gdev_prn_get_params(pdev, plist)) < 0 ||
 
696
         (code = sample_device_crd_get_params(pdev, plist, "CRDDefault")) < 0 ||
 
697
         (code = param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
 
698
         (code = param_write_bool(plist, "Separations", &seprs)) < 0)
 
699
        return code;
 
700
 
 
701
    pos.data = (const byte *)xdev->profile_out_fn,
 
702
        pos.size = strlen(xdev->profile_out_fn),
 
703
        pos.persistent = false;
 
704
    code = param_write_string(plist, "ProfileOut", &pos);
 
705
    if (code < 0)
 
706
        return code;
 
707
 
 
708
    prgbs.data = (const byte *)xdev->profile_rgb_fn,
 
709
        prgbs.size = strlen(xdev->profile_rgb_fn),
 
710
        prgbs.persistent = false;
 
711
    code = param_write_string(plist, "ProfileRgb", &prgbs);
 
712
 
 
713
    pcmyks.data = (const byte *)xdev->profile_cmyk_fn,
 
714
        pcmyks.size = strlen(xdev->profile_cmyk_fn),
 
715
        pcmyks.persistent = false;
 
716
    code = param_write_string(plist, "ProfileCmyk", &prgbs);
 
717
 
 
718
    return code;
 
719
}
 
720
#undef set_param_array
 
721
 
 
722
#define compare_color_names(name, name_size, str, str_size) \
 
723
    (name_size == str_size && \
 
724
        (strncmp((const char *)name, (const char *)str, name_size) == 0))
 
725
 
 
726
/*
 
727
 * This routine will check if a name matches any item in a list of process model
 
728
 * color component names.
 
729
 */
 
730
static bool
 
731
check_process_color_names(const fixed_colorant_names_list * pcomp_list,
 
732
                          const gs_param_string * pstring)
 
733
{
 
734
    if (pcomp_list) {
 
735
        const fixed_colorant_name * plist = *pcomp_list;
 
736
        uint size = pstring->size;
 
737
 
 
738
        while( *plist) {
 
739
            if (compare_color_names(*plist, strlen(*plist), pstring->data, size)) {
 
740
                return true;
 
741
            }
 
742
            plist++;
 
743
        }
 
744
    }
 
745
    return false;
 
746
}
 
747
 
 
748
/*
 
749
 * This utility routine calculates the number of bits required to store
 
750
 * color information.  In general the values are rounded up to an even
 
751
 * byte boundary except those cases in which mulitple pixels can evenly
 
752
 * into a single byte.
 
753
 *
 
754
 * The parameter are:
 
755
 *   ncomp - The number of components (colorants) for the device.  Valid
 
756
 *      values are 1 to GX_DEVICE_COLOR_MAX_COMPONENTS
 
757
 *   bpc - The number of bits per component.  Valid values are 1, 2, 4, 5,
 
758
 *      and 8.
 
759
 * Input values are not tested for validity.
 
760
 */
 
761
static int
 
762
bpc_to_depth(int ncomp, int bpc)
 
763
{
 
764
    static const byte depths[4][8] = {
 
765
        {1, 2, 0, 4, 8, 0, 0, 8},
 
766
        {2, 4, 0, 8, 16, 0, 0, 16},
 
767
        {4, 8, 0, 16, 16, 0, 0, 24},
 
768
        {4, 8, 0, 16, 32, 0, 0, 32}
 
769
    };
 
770
 
 
771
    if (ncomp <=4 && bpc <= 8)
 
772
        return depths[ncomp -1][bpc-1];
 
773
    else
 
774
        return (ncomp * bpc + 7) & ~7;
 
775
}
 
776
 
 
777
#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
 
778
    BEGIN\
 
779
    switch (code = pread(plist, (param_name = pname), &(pa))) {\
 
780
      case 0:\
 
781
        if ((pa).size != psize) {\
 
782
          ecode = gs_note_error(gs_error_rangecheck);\
 
783
          (pa).data = 0;        /* mark as not filled */\
 
784
        } else
 
785
#define END_ARRAY_PARAM(pa, e)\
 
786
        goto e;\
 
787
      default:\
 
788
        ecode = code;\
 
789
e:      param_signal_error(plist, param_name, ecode);\
 
790
      case 1:\
 
791
        (pa).data = 0;          /* mark as not filled */\
 
792
    }\
 
793
    END
 
794
 
 
795
static int
 
796
xcf_param_read_fn(gs_param_list *plist, const char *name,
 
797
                  gs_param_string *pstr, int max_len)
 
798
{
 
799
    int code = param_read_string(plist, name, pstr);
 
800
 
 
801
    if (code == 0) {
 
802
        if (pstr->size >= max_len)
 
803
            param_signal_error(plist, name, code = gs_error_rangecheck);
 
804
    } else {
 
805
        pstr->data = 0;
 
806
    }
 
807
    return code;
 
808
}
 
809
 
 
810
/* Compare a C string and a gs_param_string. */
 
811
static bool
 
812
param_string_eq(const gs_param_string *pcs, const char *str)
 
813
{
 
814
    return (strlen(str) == pcs->size &&
 
815
            !strncmp(str, (const char *)pcs->data, pcs->size));
 
816
}
 
817
 
 
818
static int
 
819
xcf_set_color_model(xcf_device *xdev, xcf_color_model color_model)
 
820
{
 
821
    xdev->color_model = color_model;
 
822
    if (color_model == XCF_DEVICE_GRAY) {
 
823
        xdev->std_colorant_names = &DeviceGrayComponents;
 
824
        xdev->num_std_colorant_names = 1;
 
825
        xdev->color_info.cm_name = "DeviceGray";
 
826
        xdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
 
827
    } else if (color_model == XCF_DEVICE_RGB) {
 
828
        xdev->std_colorant_names = &DeviceRGBComponents;
 
829
        xdev->num_std_colorant_names = 3;
 
830
        xdev->color_info.cm_name = "DeviceRGB";
 
831
        xdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
 
832
    } else if (color_model == XCF_DEVICE_CMYK) {
 
833
        xdev->std_colorant_names = &DeviceCMYKComponents;
 
834
        xdev->num_std_colorant_names = 4;
 
835
        xdev->color_info.cm_name = "DeviceCMYK";
 
836
        xdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
 
837
    } else if (color_model == XCF_DEVICE_N) {
 
838
        xdev->std_colorant_names = &DeviceCMYKComponents;
 
839
        xdev->num_std_colorant_names = 4;
 
840
        xdev->color_info.cm_name = "DeviceN";
 
841
        xdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
 
842
    } else {
 
843
        return -1;
 
844
    }
 
845
 
 
846
    return 0;
 
847
}
 
848
 
 
849
/*
 
850
 * Close device and clean up ICC structures.
 
851
 */
 
852
 
 
853
static int
 
854
xcf_prn_close(gx_device *dev)
 
855
{
 
856
    xcf_device * const xdev = (xcf_device *) dev;
 
857
 
 
858
    if (xdev->cmyk_icc_link != NULL) {
 
859
        gscms_release_link(xdev->cmyk_icc_link);
 
860
        rc_decrement(xdev->cmyk_profile, "xcf_prn_close");
 
861
    }
 
862
 
 
863
    if (xdev->rgb_icc_link != NULL) {
 
864
        gscms_release_link(xdev->rgb_icc_link);
 
865
        rc_decrement(xdev->rgb_profile, "xcf_prn_close");
 
866
    }
 
867
 
 
868
    if (xdev->output_icc_link != NULL) {
 
869
        gscms_release_link(xdev->output_icc_link);
 
870
        rc_decrement(xdev->output_profile, "xcf_prn_close");
 
871
    }
 
872
 
 
873
    return gdev_prn_close(dev);
 
874
}
 
875
 
 
876
/* Set parameters.  We allow setting the number of bits per component. */
 
877
static int
 
878
xcf_put_params(gx_device * pdev, gs_param_list * plist)
 
879
{
 
880
    xcf_device * const pdevn = (xcf_device *) pdev;
 
881
    gx_device_color_info save_info;
 
882
    gs_param_name param_name;
 
883
    int npcmcolors;
 
884
    int num_spot = pdevn->separation_names.num_names;
 
885
    int ecode = 0;
 
886
    int code;
 
887
    gs_param_string_array scna;
 
888
    gs_param_string po;
 
889
    gs_param_string prgb;
 
890
    gs_param_string pcmyk;
 
891
    gs_param_string pcm;
 
892
    xcf_color_model color_model = pdevn->color_model;
 
893
 
 
894
    BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames", scna, scna.size, scne) {
 
895
        break;
 
896
    } END_ARRAY_PARAM(scna, scne);
 
897
 
 
898
    if (code >= 0)
 
899
        code = xcf_param_read_fn(plist, "ProfileOut", &po,
 
900
                                 sizeof(pdevn->profile_out_fn));
 
901
    if (code >= 0)
 
902
        code = xcf_param_read_fn(plist, "ProfileRgb", &prgb,
 
903
                                 sizeof(pdevn->profile_rgb_fn));
 
904
    if (code >= 0)
 
905
        code = xcf_param_read_fn(plist, "ProfileCmyk", &pcmyk,
 
906
                                 sizeof(pdevn->profile_cmyk_fn));
 
907
 
 
908
    if (code >= 0)
 
909
        code = param_read_name(plist, "ProcessColorModel", &pcm);
 
910
    if (code == 0) {
 
911
        if (param_string_eq (&pcm, "DeviceGray"))
 
912
            color_model = XCF_DEVICE_GRAY;
 
913
        else if (param_string_eq (&pcm, "DeviceRGB"))
 
914
            color_model = XCF_DEVICE_RGB;
 
915
        else if (param_string_eq (&pcm, "DeviceCMYK"))
 
916
            color_model = XCF_DEVICE_CMYK;
 
917
        else if (param_string_eq (&pcm, "DeviceN"))
 
918
            color_model = XCF_DEVICE_N;
 
919
        else {
 
920
            param_signal_error(plist, "ProcessColorModel",
 
921
                               code = gs_error_rangecheck);
 
922
        }
 
923
    }
 
924
    if (code < 0)
 
925
        ecode = code;
 
926
 
 
927
    /*
 
928
     * Save the color_info in case gdev_prn_put_params fails, and for
 
929
     * comparison.
 
930
     */
 
931
    save_info = pdevn->color_info;
 
932
    ecode = xcf_set_color_model(pdevn, color_model);
 
933
    if (ecode == 0)
 
934
        ecode = gdev_prn_put_params(pdev, plist);
 
935
    if (ecode < 0) {
 
936
        pdevn->color_info = save_info;
 
937
        return ecode;
 
938
    }
 
939
 
 
940
    /* Separations are only valid with a subrtractive color model */
 
941
    if (pdev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
 
942
        /*
 
943
         * Process the separation color names.  Remove any names that already
 
944
         * match the process color model colorant names for the device.
 
945
         */
 
946
        if (scna.data != 0) {
 
947
            int i;
 
948
            int num_names = scna.size;
 
949
            const fixed_colorant_names_list * pcomp_names =
 
950
                                ((xcf_device *)pdev)->std_colorant_names;
 
951
 
 
952
            for (i = num_spot = 0; i < num_names; i++) {
 
953
                if (!check_process_color_names(pcomp_names, &scna.data[i]))
 
954
                    pdevn->separation_names.names[num_spot++] = &scna.data[i];
 
955
            }
 
956
            pdevn->separation_names.num_names = num_spot;
 
957
            if (pdevn->is_open)
 
958
                gs_closedevice(pdev);
 
959
        }
 
960
        npcmcolors = pdevn->num_std_colorant_names;
 
961
        pdevn->color_info.num_components = npcmcolors + num_spot;
 
962
        /*
 
963
         * The DeviceN device can have zero components if nothing has been
 
964
         * specified.  This causes some problems so force at least one
 
965
         * component until something is specified.
 
966
         */
 
967
        if (!pdevn->color_info.num_components)
 
968
            pdevn->color_info.num_components = 1;
 
969
        pdevn->color_info.depth = bpc_to_depth(pdevn->color_info.num_components,
 
970
                                                pdevn->bitspercomponent);
 
971
        if (pdevn->color_info.depth != save_info.depth) {
 
972
            gs_closedevice(pdev);
 
973
        }
 
974
    }
 
975
 
 
976
    if (po.data != 0) {
 
977
        memcpy(pdevn->profile_out_fn, po.data, po.size);
 
978
        pdevn->profile_out_fn[po.size] = 0;
 
979
    }
 
980
    if (prgb.data != 0) {
 
981
        memcpy(pdevn->profile_rgb_fn, prgb.data, prgb.size);
 
982
        pdevn->profile_rgb_fn[prgb.size] = 0;
 
983
    }
 
984
    if (pcmyk.data != 0) {
 
985
        memcpy(pdevn->profile_cmyk_fn, pcmyk.data, pcmyk.size);
 
986
        pdevn->profile_cmyk_fn[pcmyk.size] = 0;
 
987
    }
 
988
    code = xcf_open_profiles(pdevn);
 
989
 
 
990
    return code;
 
991
}
 
992
 
 
993
/*
 
994
 * This routine will check to see if the color component name  match those
 
995
 * that are available amoung the current device's color components.
 
996
 *
 
997
 * Parameters:
 
998
 *   dev - pointer to device data structure.
 
999
 *   pname - pointer to name (zero termination not required)
 
1000
 *   nlength - length of the name
 
1001
 *
 
1002
 * This routine returns a positive value (0 to n) which is the device colorant
 
1003
 * number if the name is found.  It returns a negative value if not found.
 
1004
 */
 
1005
static int
 
1006
xcf_get_color_comp_index(gx_device * dev, const char * pname, int name_size,
 
1007
                                        int component_type)
 
1008
{
 
1009
/* TO_DO_DEVICEN  This routine needs to include the effects of the SeparationOrder array */
 
1010
    const fixed_colorant_names_list * list = ((const xcf_device *)dev)->std_colorant_names;
 
1011
    const fixed_colorant_name * pcolor = *list;
 
1012
    int color_component_number = 0;
 
1013
    int i;
 
1014
 
 
1015
    /* Check if the component is in the implied list. */
 
1016
    if (pcolor) {
 
1017
        while( *pcolor) {
 
1018
            if (compare_color_names(pname, name_size, *pcolor, strlen(*pcolor)))
 
1019
                return color_component_number;
 
1020
            pcolor++;
 
1021
            color_component_number++;
 
1022
        }
 
1023
    }
 
1024
 
 
1025
    /* Check if the component is in the separation names list. */
 
1026
    {
 
1027
        const gs_separation_names * separations = &((const xcf_device *)dev)->separation_names;
 
1028
        int num_spot = separations->num_names;
 
1029
 
 
1030
        for (i=0; i<num_spot; i++) {
 
1031
            if (compare_color_names((const char *)separations->names[i]->data,
 
1032
                  separations->names[i]->size, pname, name_size)) {
 
1033
                return color_component_number;
 
1034
            }
 
1035
            color_component_number++;
 
1036
        }
 
1037
    }
 
1038
 
 
1039
    return -1;
 
1040
}
 
1041
 
 
1042
/* ------ Private definitions ------ */
 
1043
 
 
1044
/* All two-byte quantities are stored MSB-first! */
 
1045
#if arch_is_big_endian
 
1046
#  define assign_u16(a,v) a = (v)
 
1047
#  define assign_u32(a,v) a = (v)
 
1048
#else
 
1049
#  define assign_u16(a,v) a = ((v) >> 8) + ((v) << 8)
 
1050
#  define assign_u32(a,v) a = (((v) >> 24) & 0xff) + (((v) >> 8) & 0xff00) + (((v) & 0xff00) << 8) + (((v) & 0xff) << 24)
 
1051
#endif
 
1052
 
 
1053
typedef struct {
 
1054
    FILE *f;
 
1055
    int offset;
 
1056
 
 
1057
    int width;
 
1058
    int height;
 
1059
    int base_bytes_pp; /* almost always 3 (rgb) */
 
1060
    int n_extra_channels;
 
1061
 
 
1062
    int n_tiles_x;
 
1063
    int n_tiles_y;
 
1064
    int n_tiles;
 
1065
    int n_levels;
 
1066
 
 
1067
    /* byte offset of image data */
 
1068
    int image_data_off;
 
1069
} xcf_write_ctx;
 
1070
 
 
1071
#define TILE_WIDTH 64
 
1072
#define TILE_HEIGHT 64
 
1073
 
 
1074
static int
 
1075
xcf_calc_levels(int size, int tile_size)
 
1076
{
 
1077
    int levels = 1;
 
1078
    while (size > tile_size) {
 
1079
        size >>= 1;
 
1080
        levels++;
 
1081
    }
 
1082
    return levels;
 
1083
}
 
1084
 
 
1085
static int
 
1086
xcf_setup_tiles(xcf_write_ctx *xc, xcf_device *dev)
 
1087
{
 
1088
    xc->base_bytes_pp = 3;
 
1089
    xc->n_extra_channels = dev->separation_names.num_names;
 
1090
    xc->width = dev->width;
 
1091
    xc->height = dev->height;
 
1092
    xc->n_tiles_x = (dev->width + TILE_WIDTH - 1) / TILE_WIDTH;
 
1093
    xc->n_tiles_y = (dev->height + TILE_HEIGHT - 1) / TILE_HEIGHT;
 
1094
    xc->n_tiles = xc->n_tiles_x * xc->n_tiles_y;
 
1095
    xc->n_levels = max(xcf_calc_levels(dev->width, TILE_WIDTH),
 
1096
                       xcf_calc_levels(dev->height, TILE_HEIGHT));
 
1097
 
 
1098
    return 0;
 
1099
}
 
1100
 
 
1101
/* Return value: Size of tile in pixels. */
 
1102
static int
 
1103
xcf_tile_sizeof(xcf_write_ctx *xc, int tile_idx)
 
1104
{
 
1105
    int tile_i = tile_idx % xc->n_tiles_x;
 
1106
    int tile_j = tile_idx / xc->n_tiles_x;
 
1107
    int tile_size_x = min(TILE_WIDTH, xc->width - tile_i * TILE_WIDTH);
 
1108
    int tile_size_y = min(TILE_HEIGHT, xc->height - tile_j * TILE_HEIGHT);
 
1109
    return tile_size_x * tile_size_y;
 
1110
}
 
1111
 
 
1112
static int
 
1113
xcf_write(xcf_write_ctx *xc, const byte *buf, int size) {
 
1114
    int code;
 
1115
 
 
1116
    code = fwrite(buf, 1, size, xc->f);
 
1117
    if (code < 0)
 
1118
        return code;
 
1119
    xc->offset += code;
 
1120
    return 0;
 
1121
}
 
1122
 
 
1123
static int
 
1124
xcf_write_32(xcf_write_ctx *xc, bits32 v)
 
1125
{
 
1126
    bits32 buf;
 
1127
 
 
1128
    assign_u32(buf, v);
 
1129
    return xcf_write(xc, (byte *)&buf, 4);
 
1130
}
 
1131
 
 
1132
static int
 
1133
xcf_write_image_props(xcf_write_ctx *xc)
 
1134
{
 
1135
    int code = 0;
 
1136
 
 
1137
    xcf_write_32(xc, 0);
 
1138
    xcf_write_32(xc, 0);
 
1139
 
 
1140
    return code;
 
1141
}
 
1142
 
 
1143
/**
 
1144
 * Return value: Number of bytes needed to write layer.
 
1145
 **/
 
1146
static int
 
1147
xcf_base_size(xcf_write_ctx *xc, const char *layer_name)
 
1148
{
 
1149
    int bytes_pp = xc->base_bytes_pp + xc->n_extra_channels;
 
1150
 
 
1151
    return 17 + strlen (layer_name) +           /* header and name */
 
1152
        8 +                                     /* layer props */
 
1153
        12 + xc->n_levels * 16 +                /* layer tile hierarchy */
 
1154
        12 + xc->n_tiles * 4 +                  /* tile offsets */
 
1155
        xc->width * xc->height * bytes_pp;      /* image data */
 
1156
}
 
1157
 
 
1158
static int
 
1159
xcf_channel_size(xcf_write_ctx *xc, int name_size)
 
1160
{
 
1161
    return 17 + name_size +                     /* header and name */
 
1162
        8 +                                     /* channel props */
 
1163
        4 + xc->n_levels * 16 +                 /* channel tile hiearchy */
 
1164
        12 + xc->n_tiles * 4;                   /* tile offsets */
 
1165
}
 
1166
 
 
1167
static int
 
1168
xcf_write_header(xcf_write_ctx *xc, xcf_device *pdev)
 
1169
{
 
1170
    int code = 0;
 
1171
    const char *layer_name = "Background";
 
1172
    int level;
 
1173
    int tile_offset;
 
1174
    int tile_idx;
 
1175
    int n_extra_channels = xc->n_extra_channels;
 
1176
    int bytes_pp = xc->base_bytes_pp + n_extra_channels;
 
1177
    int channel_idx;
 
1178
 
 
1179
    xcf_write(xc, (const byte *)"gimp xcf file", 14);
 
1180
    xcf_write_32(xc, xc->width);
 
1181
    xcf_write_32(xc, xc->height);
 
1182
    xcf_write_32(xc, 0);
 
1183
 
 
1184
    xcf_write_image_props(xc);
 
1185
 
 
1186
    /* layer offsets */
 
1187
    xcf_write_32(xc, xc->offset + 12 + 4 * n_extra_channels);
 
1188
    xcf_write_32(xc, 0);
 
1189
 
 
1190
    /* channel offsets */
 
1191
    tile_offset = xc->offset + 4 + 4 * n_extra_channels +
 
1192
        xcf_base_size(xc, layer_name);
 
1193
    for (channel_idx = 0; channel_idx < n_extra_channels; channel_idx++) {
 
1194
        const gs_param_string *separation_name =
 
1195
            pdev->separation_names.names[channel_idx];
 
1196
        dmlprintf1(pdev->memory, "tile offset: %d\n", tile_offset);
 
1197
        xcf_write_32(xc, tile_offset);
 
1198
        tile_offset += xcf_channel_size(xc, separation_name->size);
 
1199
    }
 
1200
    xcf_write_32(xc, 0);
 
1201
 
 
1202
    /* layer */
 
1203
    xcf_write_32(xc, xc->width);
 
1204
    xcf_write_32(xc, xc->height);
 
1205
    xcf_write_32(xc, 0);
 
1206
    xcf_write_32(xc, strlen(layer_name) + 1);
 
1207
    xcf_write(xc, (const byte *)layer_name, strlen(layer_name) + 1);
 
1208
 
 
1209
    /* layer props */
 
1210
    xcf_write_32(xc, 0);
 
1211
    xcf_write_32(xc, 0);
 
1212
 
 
1213
    /* layer tile hierarchy */
 
1214
    xcf_write_32(xc, xc->offset + 8);
 
1215
    xcf_write_32(xc, 0);
 
1216
 
 
1217
    xcf_write_32(xc, xc->width);
 
1218
    xcf_write_32(xc, xc->height);
 
1219
    xcf_write_32(xc, xc->base_bytes_pp);
 
1220
    xcf_write_32(xc, xc->offset + (1 + xc->n_levels) * 4);
 
1221
    tile_offset = xc->offset + xc->width * xc->height * bytes_pp +
 
1222
        xc->n_tiles * 4 + 12;
 
1223
    for (level = 1; level < xc->n_levels; level++) {
 
1224
        xcf_write_32(xc, tile_offset);
 
1225
        tile_offset += 12;
 
1226
    }
 
1227
    xcf_write_32(xc, 0);
 
1228
 
 
1229
    /* layer tile offsets */
 
1230
    xcf_write_32(xc, xc->width);
 
1231
    xcf_write_32(xc, xc->height);
 
1232
    tile_offset = xc->offset + (xc->n_tiles + 1) * 4;
 
1233
    for (tile_idx = 0; tile_idx < xc->n_tiles; tile_idx++) {
 
1234
        xcf_write_32(xc, tile_offset);
 
1235
        tile_offset += xcf_tile_sizeof(xc, tile_idx) * bytes_pp;
 
1236
    }
 
1237
    xcf_write_32(xc, 0);
 
1238
 
 
1239
    xc->image_data_off = xc->offset;
 
1240
 
 
1241
    return code;
 
1242
}
 
1243
 
 
1244
static void
 
1245
xcf_shuffle_to_tile(xcf_write_ctx *xc, byte **tile_data, const byte *row,
 
1246
                    int y)
 
1247
{
 
1248
    int tile_j = y / TILE_HEIGHT;
 
1249
    int yrem = y % TILE_HEIGHT;
 
1250
    int tile_i;
 
1251
    int base_bytes_pp = xc->base_bytes_pp;
 
1252
    int n_extra_channels = xc->n_extra_channels;
 
1253
    int row_idx = 0;
 
1254
 
 
1255
    for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
 
1256
        int x;
 
1257
        int tile_width = min(TILE_WIDTH, xc->width - tile_i * TILE_WIDTH);
 
1258
        int tile_height = min(TILE_HEIGHT, xc->height - tile_j * TILE_HEIGHT);
 
1259
        byte *base_ptr = tile_data[tile_i] +
 
1260
            yrem * tile_width * base_bytes_pp;
 
1261
        int extra_stride = tile_width * tile_height;
 
1262
        byte *extra_ptr = tile_data[tile_i] + extra_stride * base_bytes_pp +
 
1263
            yrem * tile_width;
 
1264
 
 
1265
        int base_idx = 0;
 
1266
 
 
1267
        for (x = 0; x < tile_width; x++) {
 
1268
            int plane_idx;
 
1269
            for (plane_idx = 0; plane_idx < base_bytes_pp; plane_idx++)
 
1270
                base_ptr[base_idx++] = row[row_idx++];
 
1271
            for (plane_idx = 0; plane_idx < n_extra_channels; plane_idx++)
 
1272
                extra_ptr[plane_idx * extra_stride + x] = 255 ^ row[row_idx++];
 
1273
        }
 
1274
    }
 
1275
}
 
1276
 
 
1277
static void
 
1278
xcf_icc_to_tile(gx_device_printer *pdev, xcf_write_ctx *xc, byte **tile_data, const byte *row,
 
1279
                    int y, gcmmhlink_t link)
 
1280
{
 
1281
    int tile_j = y / TILE_HEIGHT;
 
1282
    int yrem = y % TILE_HEIGHT;
 
1283
    int tile_i;
 
1284
    int base_bytes_pp = xc->base_bytes_pp;
 
1285
    int n_extra_channels = xc->n_extra_channels;
 
1286
    int row_idx = 0;
 
1287
 
 
1288
    for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
 
1289
        int x;
 
1290
        int tile_width = min(TILE_WIDTH, xc->width - tile_i * TILE_WIDTH);
 
1291
        int tile_height = min(TILE_HEIGHT, xc->height - tile_j * TILE_HEIGHT);
 
1292
        byte *base_ptr = tile_data[tile_i] +
 
1293
            yrem * tile_width * base_bytes_pp;
 
1294
        int extra_stride = tile_width * tile_height;
 
1295
        byte *extra_ptr = tile_data[tile_i] + extra_stride * base_bytes_pp +
 
1296
            yrem * tile_width;
 
1297
 
 
1298
        int base_idx = 0;
 
1299
 
 
1300
        for (x = 0; x < tile_width; x++) {
 
1301
 
 
1302
            int plane_idx;
 
1303
 
 
1304
                /* This loop could be optimized.  I don't quite
 
1305
                   understand what is going on in the loop
 
1306
                   with the 255^row[row_idx++] operation */
 
1307
 
 
1308
            gscms_transform_color((gx_device*) pdev, link, 
 
1309
                                  (void *) (&(row[row_idx])),
 
1310
                                   &(base_ptr[base_idx]), 1);
 
1311
 
 
1312
            for (plane_idx = 0; plane_idx < n_extra_channels; plane_idx++)
 
1313
                extra_ptr[plane_idx * extra_stride + x] = 255 ^ row[row_idx++];
 
1314
        }
 
1315
    }
 
1316
}
 
1317
 
 
1318
static int
 
1319
xcf_write_image_data(xcf_write_ctx *xc, gx_device_printer *pdev)
 
1320
{
 
1321
    int code = 0;
 
1322
    int raster = gdev_prn_raster(pdev);
 
1323
    int tile_i, tile_j;
 
1324
    byte **tile_data;
 
1325
    byte *line;
 
1326
    int base_bytes_pp = xc->base_bytes_pp;
 
1327
    int n_extra_channels = xc->n_extra_channels;
 
1328
    int bytes_pp = base_bytes_pp + n_extra_channels;
 
1329
    int chan_idx;
 
1330
    xcf_device *xdev = (xcf_device *)pdev;
 
1331
    gcmmhlink_t link = xdev->output_icc_link;
 
1332
 
 
1333
    line = gs_alloc_bytes(pdev->memory, raster, "xcf_write_image_data");
 
1334
    tile_data = (byte **)gs_alloc_bytes(pdev->memory,
 
1335
                                        xc->n_tiles_x * sizeof(byte *),
 
1336
                                        "xcf_write_image_data");
 
1337
    for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
 
1338
        int tile_bytes = xcf_tile_sizeof(xc, tile_i) * bytes_pp;
 
1339
 
 
1340
        tile_data[tile_i] = gs_alloc_bytes(pdev->memory, tile_bytes,
 
1341
                                           "xcf_write_image_data");
 
1342
    }
 
1343
    for (tile_j = 0; tile_j < xc->n_tiles_y; tile_j++) {
 
1344
        int y0, y1;
 
1345
        int y;
 
1346
        byte *row;
 
1347
 
 
1348
        y0 = tile_j * TILE_HEIGHT;
 
1349
        y1 = min(xc->height, y0 + TILE_HEIGHT);
 
1350
        for (y = y0; y < y1; y++) {
 
1351
            code = gdev_prn_get_bits(pdev, y, line, &row);
 
1352
            if (link == NULL)
 
1353
                xcf_shuffle_to_tile(xc, tile_data, row, y);
 
1354
            else
 
1355
                xcf_icc_to_tile(pdev, xc, tile_data, row, y, link);
 
1356
        }
 
1357
        for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
 
1358
            int tile_idx = tile_j * xc->n_tiles_x + tile_i;
 
1359
            int tile_size = xcf_tile_sizeof(xc, tile_idx);
 
1360
            int base_size = tile_size * base_bytes_pp;
 
1361
 
 
1362
            xcf_write(xc, tile_data[tile_i], base_size);
 
1363
            for (chan_idx = 0; chan_idx < n_extra_channels; chan_idx++) {
 
1364
                xcf_write(xc, tile_data[tile_i] + base_size +
 
1365
                          tile_size * chan_idx, tile_size);
 
1366
            }
 
1367
        }
 
1368
    }
 
1369
 
 
1370
    for (tile_i = 0; tile_i < xc->n_tiles_x; tile_i++) {
 
1371
        gs_free_object(pdev->memory, tile_data[tile_i],
 
1372
                "xcf_write_image_data");
 
1373
    }
 
1374
    gs_free_object(pdev->memory, tile_data, "xcf_write_image_data");
 
1375
    gs_free_object(pdev->memory, line, "xcf_write_image_data");
 
1376
    return code;
 
1377
}
 
1378
 
 
1379
static int
 
1380
xcf_write_fake_hierarchy(xcf_write_ctx *xc)
 
1381
{
 
1382
    int widthf = xc->width, heightf = xc->height;
 
1383
    int i;
 
1384
 
 
1385
    for (i = 1; i < xc->n_levels; i++) {
 
1386
        widthf >>= 1;
 
1387
        heightf >>= 1;
 
1388
        xcf_write_32(xc, widthf);
 
1389
        xcf_write_32(xc, heightf);
 
1390
        xcf_write_32(xc, 0);
 
1391
    }
 
1392
    return 0;
 
1393
}
 
1394
 
 
1395
static int
 
1396
xcf_write_footer(xcf_write_ctx *xc, xcf_device *pdev)
 
1397
{
 
1398
    int code = 0;
 
1399
    int base_bytes_pp = xc->base_bytes_pp;
 
1400
    int n_extra_channels = xc->n_extra_channels;
 
1401
    int bytes_pp = base_bytes_pp + n_extra_channels;
 
1402
    int chan_idx;
 
1403
 
 
1404
    xcf_write_fake_hierarchy(xc);
 
1405
 
 
1406
    for (chan_idx = 0; chan_idx < xc->n_extra_channels; chan_idx++) {
 
1407
        const gs_param_string *separation_name =
 
1408
            pdev->separation_names.names[chan_idx];
 
1409
        byte nullbyte[] = { 0 };
 
1410
        int level;
 
1411
        int offset;
 
1412
        int tile_idx;
 
1413
 
 
1414
        dmlprintf2(pdev->memory, "actual tile offset: %d %d\n", xc->offset, (int)arch_sizeof_color_index);
 
1415
        xcf_write_32(xc, xc->width);
 
1416
        xcf_write_32(xc, xc->height);
 
1417
        xcf_write_32(xc, separation_name->size + 1);
 
1418
        xcf_write(xc, separation_name->data, separation_name->size);
 
1419
        xcf_write(xc, nullbyte, 1);
 
1420
 
 
1421
        /* channel props */
 
1422
        xcf_write_32(xc, 0);
 
1423
        xcf_write_32(xc, 0);
 
1424
 
 
1425
        /* channel tile hierarchy */
 
1426
        xcf_write_32(xc, xc->offset + 4);
 
1427
 
 
1428
        xcf_write_32(xc, xc->width);
 
1429
        xcf_write_32(xc, xc->height);
 
1430
        xcf_write_32(xc, 1);
 
1431
        xcf_write_32(xc, xc->offset + xc->n_levels * 16 - 8);
 
1432
        offset = xc->offset + xc->n_levels * 4;
 
1433
        for (level = 1; level < xc->n_levels; level++) {
 
1434
            xcf_write_32(xc, offset);
 
1435
            offset += 12;
 
1436
        }
 
1437
        xcf_write_32(xc, 0);
 
1438
        xcf_write_fake_hierarchy(xc);
 
1439
 
 
1440
        /* channel tile offsets */
 
1441
        xcf_write_32(xc, xc->width);
 
1442
        xcf_write_32(xc, xc->height);
 
1443
        offset = xc->image_data_off;
 
1444
        for (tile_idx = 0; tile_idx < xc->n_tiles; tile_idx++) {
 
1445
            int tile_size = xcf_tile_sizeof(xc, tile_idx);
 
1446
 
 
1447
            xcf_write_32(xc, offset + (base_bytes_pp + chan_idx) * tile_size);
 
1448
            offset += bytes_pp * tile_size;
 
1449
        }
 
1450
        xcf_write_32(xc, 0);
 
1451
 
 
1452
    }
 
1453
    return code;
 
1454
}
 
1455
 
 
1456
static int
 
1457
xcf_print_page(gx_device_printer *pdev, FILE *file)
 
1458
{
 
1459
    xcf_write_ctx xc;
 
1460
 
 
1461
    xc.f = file;
 
1462
    xc.offset = 0;
 
1463
 
 
1464
    xcf_setup_tiles(&xc, (xcf_device *)pdev);
 
1465
    xcf_write_header(&xc, (xcf_device *)pdev);
 
1466
    xcf_write_image_data(&xc, pdev);
 
1467
    xcf_write_footer(&xc, (xcf_device *)pdev);
 
1468
 
 
1469
    return 0;
 
1470
}