Coverage Report

Created: 2026-09-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pcl/pcpatrn.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* pcpatrn.c - code for PCL and GL/2 patterns, including color */
18
19
#include "gx.h"
20
#include "gsuid.h"
21
#include "gsmatrix.h"
22
#include "gspcolor.h"
23
#include "gxdcolor.h"
24
#include "gxpcolor.h"
25
#include "gxstate.h"
26
#include "pccid.h"
27
#include "pcfont.h"
28
#include "pcpalet.h"
29
#include "pcfrgrnd.h"
30
#include "pcht.h"
31
#include "pcwhtidx.h"
32
#include "pcpatrn.h"
33
#include "pcbiptrn.h"
34
#include "pcuptrn.h"
35
#include "pcpatxfm.h"
36
#include "gzstate.h"    /* for gstate */
37
38
/*
39
 * The base color space for setting the color white. Unlike all other color
40
 * spaces in PCL, this uses the DeviceGray color space in the graphic library.
41
 *
42
 * A copy of the default halftone is also maintained for setting the color
43
 * "white". Since the halftone carries the device-specific color lookup tables,
44
 * a non-standard halftone might end up mapping white to black (definitely
45
 * undesirable).
46
 */
47
static const gs_paint_color white_paint = { {1.0, 0.0, 0.0, 0.0} };
48
49
/* RC routines */
50
gs_private_st_simple(st_ccolor_t, pcl_ccolor_t, "PCL client color");
51
52
/*
53
 * Convert a color value specified as a three-element byte array, or an index
54
 * to a palette, into a gs_paint_color structure.
55
 */
56
static void
57
convert_color_to_paint(const byte * pcomp, gs_paint_color * ppaint)
58
10.5M
{
59
10.5M
    ppaint->values[0] = (float)pcomp[0] / 255.0;
60
10.5M
    ppaint->values[1] = (float)pcomp[1] / 255.0;
61
10.5M
    ppaint->values[2] = (float)pcomp[2] / 255.0;
62
10.5M
    ppaint->values[3] = 0.0;
63
10.5M
}
64
65
static void
66
convert_index_to_paint(int indx, gs_paint_color * ppaint)
67
3.32M
{
68
3.32M
    ppaint->values[0] = (float)indx;
69
3.32M
    ppaint->values[1] = 0.0;
70
3.32M
    ppaint->values[2] = 0.0;
71
3.32M
    ppaint->values[3] = 0.0;
72
3.32M
}
73
74
/*
75
 * Free a PCL client color structure.
76
 */
77
static void
78
free_ccolor(gs_memory_t * pmem, void *pvccolor, client_name_t cname)
79
241k
{
80
241k
    pcl_ccolor_t *pccolor = (pcl_ccolor_t *) pvccolor;
81
82
241k
    pcl_pattern_data_release(pccolor->ppat_data);
83
241k
    pcl_cs_indexed_release(pccolor->pindexed);
84
241k
    pcl_cs_base_release(pccolor->pbase);
85
241k
    if (pccolor->prast != 0)
86
0
        gs_free_object(pmem, (void *)pccolor->prast, cname);
87
241k
    gs_pattern_reference(&(pccolor->ccolor), -1);
88
241k
    gs_free_object(pmem, pvccolor, cname);
89
241k
}
90
91
/*
92
 * Make a unique copy of a PCL client color structure. This function also
93
 * serves as the allocator function.
94
 *
95
 * Because the byte array pointed to by the prast structure is not reference
96
 * counted, the "copy" of the client color created this procedure will always
97
 * have this pointer set to NULL. This is unfortunate and ugly, as it implies
98
 * the copy cannot be used immediately as a client color, but it causes no
99
 * trouble in the current context because:
100
 *
101
 *     prast is non-null only for colored patterns
102
 *     the client color for a colored pattern would only be unshared
103
 *         if it was about to be rendered, in which case the prast
104
 *         array would need to be recreated.
105
 *
106
 * Newly created colors are solid white.
107
 */
108
static int
109
unshare_ccolor(pcl_state_t * pcs,
110
               pcl_ccolor_t ** ppccolor, gs_memory_t * pmem)
111
283k
{
112
283k
    pcl_ccolor_t *pold = *ppccolor;
113
283k
    pcl_ccolor_t *pnew = 0;
114
115
283k
    if ((pold != NULL) && (pold->rc.ref_count == 1)) {
116
41.8k
        if (pold->prast != 0)
117
0
            gs_free_object(pmem,
118
41.8k
                           (void *)pold->prast, "unshared PCL client color");
119
41.8k
        pold->prast = 0;
120
41.8k
        return 0;
121
41.8k
    }
122
241k
    rc_decrement(pold, "unshare PCL client color object");
123
124
241k
    rc_alloc_struct_1(pnew,
125
241k
                      pcl_ccolor_t,
126
241k
                      &st_ccolor_t,
127
241k
                      pmem, return e_Memory, "allocate PCL client color");
128
241k
    pnew->rc.free = free_ccolor;
129
241k
    pnew->prast = 0;
130
131
241k
    if (pold != 0) {
132
226k
        pnew->type = pold->type;
133
226k
        pcl_pattern_data_init_from(pnew->ppat_data, pold->ppat_data);
134
226k
        pcl_cs_indexed_init_from(pnew->pindexed, pold->pindexed);
135
226k
        pcl_cs_base_init_from(pnew->pbase, pold->pbase);
136
226k
        pnew->ccolor = pold->ccolor;
137
226k
        gs_pattern_reference(&(pnew->ccolor), 1);
138
226k
    } else {
139
14.8k
        int code = 0;
140
141
14.8k
        pnew->type = pcl_ccolor_unpatterned;
142
14.8k
        pnew->ppat_data = 0;
143
14.8k
        pnew->pindexed = 0;
144
145
        /* set the color space to pure white */
146
14.8k
        pnew->pbase = 0;
147
14.8k
        code = pcl_cs_base_build_white_cspace(pcs, &(pnew->pbase), pmem);
148
14.8k
        if (code < 0) {
149
0
            gs_free_object(pmem, pnew, "allocate PCL client color");
150
0
            return code;
151
0
        }
152
14.8k
        pnew->ccolor.paint = white_paint;
153
14.8k
        pnew->ccolor.pattern = 0;
154
14.8k
    }
155
156
241k
    *ppccolor = pnew;
157
241k
    return 0;
158
241k
}
159
160
/*
161
 * Set a solid color (unpattered) color. This is handled separately from
162
 * patterns as it will usually not be necessary to build a PCL client color
163
 * structure in this case.
164
 *
165
 * Exactly one of the pair of operands pbase and pindex shoud be non-null.
166
 */
167
static int
168
set_unpatterned_color(pcl_state_t * pcs,
169
                      pcl_cs_indexed_t * pindexed,
170
                      pcl_cs_base_t * pbase, const gs_paint_color * ppaint)
171
13.6M
{
172
13.6M
    pcl_ccolor_t *pcur = pcs->pids->pccolor;
173
13.6M
    int code = 0;
174
13.6M
    pcl_ccolor_type_t type;
175
176
13.6M
    if_debug3m('c', pcs->memory, "[c]set unpatterned color %f %f %f\n",
177
13.6M
               ppaint->values[0], ppaint->values[1], ppaint->values[2]);
178
179
13.6M
    if (pcur != 0)
180
13.6M
        type = pcur->type;
181
10.1k
    else
182
10.1k
        type = pcl_ccolor_unpatterned;
183
184
13.6M
    if ((pcur != 0) &&
185
13.6M
        (type == pcl_ccolor_unpatterned) &&
186
13.4M
        (pcur->pindexed == pindexed) &&
187
13.4M
        (pcur->pbase == pbase) &&
188
13.3M
        (pcur->ccolor.paint.values[0] == ppaint->values[0]) &&
189
13.3M
        (pcur->ccolor.paint.values[1] == ppaint->values[1]) &&
190
13.3M
        (pcur->ccolor.paint.values[2] == ppaint->values[2]))
191
13.3M
        return 0;
192
193
277k
    if ((code = unshare_ccolor(pcs, &(pcs->pids->pccolor), pcs->memory)) < 0)
194
0
        return code;
195
277k
    pcur = pcs->pids->pccolor;
196
197
277k
    pcur->type = pcl_ccolor_unpatterned;
198
277k
    if (pcur->ppat_data != 0) {
199
191k
        pcl_pattern_data_release(pcur->ppat_data);
200
191k
        pcur->ppat_data = 0;
201
191k
    }
202
203
277k
    if (pindexed != 0) {
204
226k
        if ((type != pcl_ccolor_unpatterned) || (pcur->pindexed != pindexed))
205
196k
            code = pcl_cs_indexed_install(&pindexed, pcs);
206
226k
    } else {                    /* pbase != 0 */
207
51.0k
        if ((type != pcl_ccolor_unpatterned) || (pcur->pbase != pbase))
208
51.0k
            code = pcl_cs_base_install(&pbase, pcs);
209
51.0k
    }
210
277k
    if (code < 0)
211
0
        return code;
212
277k
    pcl_cs_indexed_copy_from(pcur->pindexed, pindexed);
213
277k
    pcl_cs_base_copy_from(pcur->pbase, pbase);
214
215
277k
    gs_pattern_reference(&(pcur->ccolor), -1);
216
277k
    pcur->ccolor.pattern = 0;
217
277k
    pcur->ccolor.paint = *ppaint;
218
277k
    return gs_setcolor(pcs->pgs, &(pcur->ccolor));
219
277k
}
220
221
/*
222
 * Set a patterned color space. Note that this is a substantially different
223
 * operation from setting a solid (unpatterned) color.
224
 */
225
static int
226
set_patterned_color(pcl_state_t * pcs, pcl_ccolor_t * pnew)
227
235k
{
228
235k
    pcl_ccolor_t *pcur = pcs->pids->pccolor;
229
235k
    int code = 0;
230
231
    /* check if already set */
232
235k
    if (pcur == pnew)
233
38.8k
        return 0;
234
235
    /* set a base color space for the pattern, if necessary */
236
196k
    if (pnew->type == pcl_ccolor_mask_pattern) {
237
238
5.07k
        if ((pnew->pindexed != 0) &&
239
2.06k
            ((pcur == 0) || (pcur->pindexed != pnew->pindexed)))
240
364
            code = pcl_cs_indexed_install(&(pnew->pindexed), pcs);
241
242
5.07k
        if (code < 0)
243
0
            return code;
244
245
5.07k
        if ((pnew->pbase != 0) &&
246
3.01k
            ((pcur == 0) || (pcur->pbase != pnew->pbase)))
247
1.78k
            code = pcl_cs_base_install(&(pnew->pbase), pcs);
248
5.07k
    }
249
196k
    if (code < 0)
250
0
        return code;
251
252
    /* set the pattern instance */
253
196k
    if ((code = gs_setpattern(pcs->pgs, &(pnew->ccolor))) >= 0)
254
196k
        pcl_ccolor_copy_from(pcs->pids->pccolor, pnew);
255
196k
    return code;
256
196k
}
257
258
/*
259
 * Check if the pattern pointed to by pptrn has a rendering and, if so, whether
260
 * or not that rendering is appropriate for the curren environment.
261
 *
262
 * If the rendering is appropriate, install the conrresponding color; otherwise
263
 * return false.
264
 *
265
 * The case of GL uncolored patterns rendered with patterns opaque is unique.
266
 * In this case the pattern must be generated as a colored pattern (mask
267
 * patterns are always transparent), with a specially generated 2-entry
268
 * indexed color space. The cache_id field identifies the palette that gave
269
 * rise to this pattern, but not the entry from that palette that was used
270
 * as the foreground color. Hence, for this case alone there must be a match
271
 * on the pen number key. To avoid the need for a much qualified check in this
272
 * case, we use the convention that the pen number field is zero in all but
273
 * this case.
274
 *
275
 * Note that a difference in the paint color does not require re-rendering;
276
 * these fields are ignored for colored patterns, and for mask patterns changes
277
 * only require another call to gs_setpattern.
278
 */
279
static bool
280
check_pattern_rendering(pcl_state_t * pcs, pcl_pattern_t * pptrn, bool use_frgrnd,      /* else use palette */
281
                        uint pen_num,
282
                        bool colored, const gs_paint_color * ppaint)
283
235k
{
284
235k
    pcl_ccolor_t *pccolor = 0;
285
286
    /* check the common parameters first */
287
235k
    if ((pptrn == NULL) ||
288
235k
        (pptrn->orient != pcs->pat_orient) ||
289
232k
        (pptrn->ref_pt.x != pcs->pat_ref_pt.x) ||
290
230k
        (pptrn->ref_pt.y != pcs->pat_ref_pt.y))
291
5.03k
        return false;
292
293
230k
    if (colored) {
294
205k
        pcl_gsid_t cache_id = (use_frgrnd ? pcs->pfrgrnd->id
295
205k
                               : pcs->ppalet->id);
296
297
        /* check that there is a rendering in the appropriate environment */
298
205k
        if (((pccolor = pptrn->pcol_ccolor) == 0) ||
299
205k
            (pptrn->transp != pcs->pattern_transparent) ||
300
205k
            (pptrn->cache_id != cache_id) || (pptrn->pen != pen_num))
301
26
            return false;
302
303
205k
    } else {                    /* mask pattern */
304
24.8k
        pcl_cs_indexed_t *pindexed = (use_frgrnd ? 0 : pcs->ppalet->pindexed);
305
24.8k
        pcl_cs_base_t *pbase = (use_frgrnd ? pcs->pfrgrnd->pbase : 0);
306
307
        /* check if there is a rendering */
308
24.8k
        if ((pccolor = pptrn->pmask_ccolor) == 0)
309
6
            return false;
310
311
        /* handle changes in the "foreground" color or color space */
312
24.8k
        if ((pccolor->ccolor.paint.values[0] != ppaint->values[0]) ||
313
24.8k
            (pccolor->ccolor.paint.values[1] != ppaint->values[1]) ||
314
24.8k
            (pccolor->ccolor.paint.values[2] != ppaint->values[2]) ||
315
24.8k
            (pccolor->pindexed != pindexed) || (pccolor->pbase != pbase)) {
316
317
            /* get a unique copy, and update the painting information */
318
43
            if (unshare_ccolor(pcs, &(pptrn->pmask_ccolor), pcs->memory) < 0)
319
0
                return false;
320
43
            pccolor = pptrn->pmask_ccolor;
321
322
43
            pcl_cs_indexed_copy_from(pccolor->pindexed, pindexed);
323
43
            pcl_cs_base_copy_from(pccolor->pbase, pbase);
324
43
            pccolor->ccolor.paint = *ppaint;
325
43
        }
326
24.8k
    }
327
328
230k
    return (set_patterned_color(pcs, pccolor) == 0);
329
230k
}
330
331
/*
332
 * Render and set a pattern.
333
 *
334
 * In a somewhat unfortunate division of labor, this code sets some but not
335
 * all of the cache keys in the pattern. The fields set are transparency,
336
 * orientation, and reference point. The caller is responsible for setting
337
 * the cache_id and pen number.
338
 *
339
 * If this routine is called, it may be assumed that the pattern needs to be
340
 * rendered.
341
 *
342
 */
343
static int
344
render_pattern(pcl_state_t * pcs,
345
               pcl_pattern_t * pptrn,
346
               pcl_ccolor_type_t type,
347
               pcl_cs_indexed_t * pindexed,
348
               pcl_cs_base_t * pbase,
349
               const gs_paint_color * ppaint, int wht_indx, bool remap)
350
5.06k
{
351
5.06k
    int code = 0;
352
5.06k
    pcl_ccolor_t *pccolor = 0;
353
5.06k
    gs_color_space *pcspace;
354
5.06k
    gs_matrix mat;
355
5.06k
    gs_depth_bitmap pixinfo;
356
357
    /*
358
     * If the orientation or reference point has changed, discard both
359
     * renderings. Otherwise, just discard the one being modified.
360
     *
361
     * Note that the unshare function doubles as an allocator.
362
     */
363
5.06k
    if ((pptrn->orient != pcs->pat_orient) ||
364
1.86k
        (pptrn->ref_pt.x != pcs->pat_ref_pt.x) ||
365
5.03k
        (pptrn->ref_pt.y != pcs->pat_ref_pt.y)) {
366
5.03k
        if (type == pcl_ccolor_mask_pattern) {
367
2.09k
            pcl_ccolor_release(pptrn->pcol_ccolor);
368
2.09k
            pptrn->pcol_ccolor = 0;
369
2.93k
        } else {                /* type == pcl_ccolor_colored_pattern */
370
2.93k
            pcl_ccolor_release(pptrn->pmask_ccolor);
371
2.93k
            pptrn->pmask_ccolor = 0;
372
2.93k
        }
373
5.03k
    }
374
375
    /* un-share, or allocate, the appropriate client color */
376
5.06k
    if (type == pcl_ccolor_mask_pattern) {
377
2.10k
        code = unshare_ccolor(pcs, &(pptrn->pmask_ccolor), pcs->memory);
378
2.10k
        pccolor = pptrn->pmask_ccolor;
379
2.10k
        pcspace = 0;
380
2.96k
    } else {                    /* type == pcl_ccolor_colored_pattern */
381
2.96k
        code = unshare_ccolor(pcs, &(pptrn->pcol_ccolor), pcs->memory);
382
2.96k
        pccolor = pptrn->pcol_ccolor;
383
2.96k
        pcspace = pindexed->pcspace;
384
2.96k
        pptrn->transp = pcs->pattern_transparent;
385
2.96k
    }
386
5.06k
    if (code < 0)
387
0
        return code;
388
389
    /* discard the existing pattern instance */
390
5.06k
    gs_pattern_reference(&(pccolor->ccolor), -1);
391
5.06k
    pccolor->ccolor.pattern = 0;
392
393
    /* initialize the pattern data, if the client color is newly allocated */
394
5.06k
    pccolor->type = type;
395
5.06k
    pcl_pattern_data_copy_from(pccolor->ppat_data, pptrn->ppat_data);
396
397
    /* set up the transformation and transparency information */
398
5.06k
    pcl_xfm_get_pat_xfm(pcs, pptrn, &mat);
399
400
    /* set up the white index and remap as necessary */
401
5.06k
    if (remap) {
402
0
        code = pcl_cmap_map_raster(pindexed,
403
0
                                   &wht_indx,
404
0
                                   &(pptrn->ppat_data->pixinfo),
405
0
                                   &pixinfo, true, pcs->memory);
406
0
        if (code < 0)
407
0
            return code;
408
0
        pcspace = pindexed->pcspace;
409
0
        if (pixinfo.data != pptrn->ppat_data->pixinfo.data)
410
0
            pccolor->prast = pixinfo.data;
411
0
    } else
412
5.06k
        pixinfo = pptrn->ppat_data->pixinfo;
413
414
5.06k
    if (pcspace != 0)
415
2.96k
        code = pcl_cs_indexed_install(&pindexed, pcs);
416
5.06k
    if (code < 0)
417
0
        return code;
418
419
    /* the following is placed here until we have time to properly
420
       address this.  The makepixmappattern() procedure detects a
421
       pattern as opaque if the white index is the number of entries
422
       in the current palette (the index of an invalid color).
423
       The motivation for this is the white index has no purpose for
424
       opaque patterns.  Upon remapping (see above) the white index
425
       may be set to a white value in the palette, a valid color.  We
426
       restore the invariant here, if necessary. */
427
5.06k
    if ((type == pcl_ccolor_colored_pattern) && !pcs->pattern_transparent)
428
2.96k
        wht_indx = pindexed->num_entries;
429
430
5.06k
    code = gs_makepixmappattern(&(pccolor->ccolor),
431
5.06k
                                &pixinfo,
432
5.06k
                                (pcspace == 0),
433
5.06k
                                &mat,
434
5.06k
                                no_UniqueID,
435
5.06k
                                pcspace, wht_indx, pcs->pgs, pcs->memory);
436
437
    /* if all is OK, install the pattern; otherwise clear the pattern */
438
5.06k
    if (code >= 0) {
439
5.06k
        pcl_cs_indexed_copy_from(pccolor->pindexed, pindexed);
440
5.06k
        pcl_cs_base_copy_from(pccolor->pbase, pbase);
441
5.06k
        if (type == pcl_ccolor_mask_pattern)
442
2.10k
            pccolor->ccolor.paint = *ppaint;
443
5.06k
        code = set_patterned_color(pcs, pccolor);
444
5.06k
    }
445
5.06k
    return code;
446
5.06k
}
447
448
/*
449
 * Set a pattern using the foreground parameters.
450
 *
451
 * The for-image boolean indicates if the foreground is being set to render
452
 * a PCL raster. If so, and if the halftone/CRD combination for the foreground
453
 * is not the same as for the palette, a colored pattern must be generated.
454
 * This is because the CRD/halftone combination for the palette will be
455
 * current at the time the pattern is loaded into the cache, and thus the
456
 * color would be evaluated in the wrong context.
457
 *
458
 * Returns 0 on success, < 0 in the event of an error.
459
 */
460
static int
461
set_frgrnd_pattern(pcl_state_t * pcs, pcl_pattern_t * pptrn, bool for_image)
462
3.19k
{
463
3.19k
    pcl_frgrnd_t *pfrgrnd = pcs->pfrgrnd;
464
3.19k
    pcl_cs_base_t *pbase = pfrgrnd->pbase;
465
3.19k
    pcl_cs_indexed_t *pindexed = 0;
466
3.19k
    pcl_ccolor_type_t type = pcl_ccolor_mask_pattern;
467
3.19k
    gs_paint_color paint;
468
3.19k
    bool colored = false;
469
3.19k
    int code = 0;
470
3.19k
    int wht_indx = (pcs->pattern_transparent ? 0 : 2);
471
472
3.19k
    if (pfrgrnd->pht == pcs->ppalet->pht)
473
3.19k
        for_image = false;
474
475
3.19k
    colored = (for_image || !pcs->pattern_transparent);
476
477
3.19k
    convert_color_to_paint(pfrgrnd->color, &paint);
478
3.19k
    if (check_pattern_rendering(pcs, pptrn, true, 0, colored, &paint))
479
2.39k
        return 0;
480
481
    /* build the two-entry palette if necessary */
482
797
    if (colored) {
483
37
        code = pcl_cs_indexed_build_special(&pindexed,
484
37
                                            pbase,
485
37
                                            pfrgrnd->color, pcs->memory);
486
37
        if (code < 0)
487
0
            return code;
488
37
        pbase = 0;
489
37
        type = pcl_ccolor_colored_pattern;
490
37
    }
491
492
797
    code = render_pattern(pcs,
493
797
                          pptrn,
494
797
                          type, pindexed, pbase, &paint, wht_indx, false);
495
496
    /* release the extra reference to the indexed color space */
497
797
    if (colored) {
498
37
        pcl_cs_indexed_release(pindexed);
499
37
        if (code >= 0) {
500
37
            pptrn->pen = 0;
501
37
            pptrn->cache_id = pfrgrnd->id;
502
37
        }
503
37
    }
504
505
797
    return code;
506
797
}
507
508
/*
509
 * Set an uncolored pattern using the palette parameters and indicated pen
510
 * number.
511
 *
512
 * Returns 0 on success, < 0 in the event of an error.
513
 */
514
static int
515
set_uncolored_palette_pattern(pcl_state_t * pcs,
516
                              pcl_pattern_t * pptrn, int pen)
517
232k
{
518
232k
    pcl_cs_indexed_t *pindexed = pcs->ppalet->pindexed;
519
232k
    pcl_ccolor_type_t type = pcl_ccolor_mask_pattern;
520
232k
    gs_paint_color paint;
521
232k
    bool colored = !pcs->pattern_transparent;
522
232k
    int code = 0;
523
524
232k
    convert_index_to_paint(pen, &paint);
525
232k
    if (check_pattern_rendering(pcs, pptrn, false, pen, colored, &paint))
526
228k
        return 0;
527
528
    /* build the two-entry palette if necessary */
529
4.27k
    if (colored) {
530
2.92k
        code = pcl_cs_indexed_build_special(&pindexed,
531
2.92k
                                            pindexed->pbase,
532
2.92k
                                            &(pindexed->palette.
533
2.92k
                                              data[3 * pen]), pcs->memory);
534
2.92k
        if (code < 0)
535
0
            return code;
536
2.92k
        type = pcl_ccolor_colored_pattern;
537
2.92k
    }
538
539
4.27k
    code = render_pattern(pcs, pptrn, type, pindexed, NULL, &paint, 2, false);
540
541
    /* release the extra reference to the indexed color space */
542
4.27k
    if (colored) {
543
2.92k
        pcl_cs_indexed_release(pindexed);
544
2.92k
        if (code >= 0) {
545
2.92k
            pptrn->pen = pen;
546
2.92k
            pptrn->cache_id = pcs->ppalet->id;
547
2.92k
        }
548
2.92k
    }
549
550
4.27k
    return code;
551
4.27k
}
552
553
/*
554
 * Set a colored pattern.
555
 *
556
 * Returns 0 on success, < 0 in the event of an error.
557
 */
558
static int
559
set_colored_pattern(pcl_state_t * pcs, pcl_pattern_t * pptrn)
560
0
{
561
0
    pcl_cs_indexed_t *pindexed = pcs->ppalet->pindexed;
562
0
    pcl_gsid_t cache_id = pcs->ppalet->id;
563
0
    int code = 0;
564
565
0
    if (check_pattern_rendering(pcs, pptrn, false, 0, true, NULL))
566
0
        return 0;
567
568
    /* note we always remap the white point.  The remapping procedure
569
       serves the dual purpose of remapping the white point which may
570
       be necessary in the transparent case and resizing the palette
571
       which may be needed for either transparent or opaque
572
       patterns. */
573
0
    code = render_pattern(pcs, pptrn, pcl_ccolor_colored_pattern, pindexed, NULL, &white_paint, 0, true /* remap */
574
0
        );
575
0
    if (code >= 0) {
576
0
        pptrn->pen = 0;
577
0
        pptrn->cache_id = cache_id;
578
0
    }
579
580
0
    return code;
581
0
}
582
583
/*
584
 * Routines to set the current color space to a specific pattern. Since patterns
585
 * have different sources, each with its own system of identifiers, there are
586
 * several such routines. Each routine takes the current PCL state (including
587
 * the GL/2 state) as an operand; the additional operands, if any, vary by
588
 * routine type.
589
 *
590
 *    pattern_set_white     No additional operands. This routine
591
 *                          will set the color space to DeviceRGB, the
592
 *                          color to white, but will not override the
593
 *                          source or pattern transparency. A special
594
 *                          halftone with a null transfer function is used,
595
 *                          to avoid possible re-mapping of white to some
596
 *                          other color.
597
 *
598
 *    pattern_set_pen       Two additional operand: the pen number and a flag
599
 *                          to suppress use of unsolid patterns. GL pens Use
600
 *                          the indexed color space from the current palette
601
 *                          as the color space, and the pen number operand as
602
 *                          the index into this palette. The halftone and color
603
 *                          rendering dictionaries are taken from the current
604
 *                          palette.
605
 *
606
 *                          This routine is also used to set up the color to
607
 *                          be used for PCL rasters. This is necessary because,
608
 *                          while images in the graphic library carry their
609
 *                          own color space, this space must be installed in
610
 *                          a graphic state at least once inorder to be used
611
 *                          (specifically, CIE color spaces have this
612
 *                          requirement). In this situation, the use of the
613
 *                          "unsolid pattern" for transparency, which is
614
 *                          specific to GL, must be suppressed.
615
 *
616
 *                          Note that this routine does NOT set the current
617
 *                          line width (it does not have sufficient
618
 *                          information to convert the dimensions).
619
 *
620
 *    pattern_set_frgrnd    One additional operands. Sets currect base
621
 *                          color space as the color space, and the
622
 *                          foreground color as the current color.
623
 *                          The third (NOT second) operand indicates if the
624
 *                          foreground is being set to render a PCL raster.
625
 *                          The latter case involves special considerations;
626
 *                          see the paragraphs at the bottom of this comment
627
 *                          for additional information.
628
 *
629
 *    pattern_set_shade_pcl
630
 *                          Two additional operands, the shade indensity
631
 *                          value and whether or not the shade pattern is
632
 *                          being set to render a PCL raster.
633
 *
634
 *                          This procedure is intended to be used by PCL.
635
 *                          It generates the shade as a colored pattern from
636
 *                          a two-element color palette consisting of the
637
 *                          canonical white for the current base color space
638
 *                          and the foreground color. The color space in the
639
 *                          graphic state is set to Pattern color space and
640
 *                          the current color is set to be the generated
641
 *                          pattern. The halftone and color rendering dictionary
642
 *                          objects are also taken from the current
643
 *                          foreground.
644
 *
645
 *                          Special considerations apply if the pattern is
646
 *                          being set to render a PCL raster. See the
647
 *                          paragraphs at the bottom of this comment for
648
 *                          additional information.
649
 *
650
 *    pattern_set_shade_gl  Two additional operands; the first provides
651
 *                          the pattern intensity, the latter the pen
652
 *                          number to be be used as the foreground color.
653
 *                          This routine generates the pattern using a two
654
 *                          entry palette consisting of canonical white in
655
 *                          the current base color space, and the operand
656
 *                          pen color from the current palette as the
657
 *                          second. The color space in the graphic state
658
 *                          is set to Pattern color space and the current
659
 *                          color is set to the generated pattern.  The
660
 *                          halftone and color rendering dictionary objects
661
 *                          are taken from the current palette.
662
 *
663
 *    pattern_set_hatch_pcl
664
 *                          Two additional operands, the index of the cross
665
 *                          hatch pattern and an indication of whether or not
666
 *                          the pattern is being set to render a PCL raster.
667
 *
668
 *                          Similar to pcl_pattern_set_shade_pcl, but for
669
 *                          cross-hatch patterns.
670
 *
671
 *    pattern_set_hatch_gl  Two additional operands; the first provides
672
 *                          the index of the cross hatch pattern, the
673
 *                          latter the pen number to be used as the
674
 *                          foreground color. Similar to
675
 *                          pcl_pattern_set_shade_gl, but for cross hatch
676
 *                          patterns.
677
 *
678
 *    pattern_set_user_pcl
679
 *                          Two additional operands, the user pattern id. and
680
 *                          and indicator of whether or not the pattern is being
681
 *                          set to render a PCL raster.
682
 *
683
 *                          Handling is based on whether the pattern is
684
 *                          colored or uncolored.
685
 *
686
 *                          For uncolored patterns, handling is similar
687
 *                          to pcl_pattern_set_shade_pcl. The special
688
 *                          consideration for rasters apply only in this case.
689
 *
690
 *                          For colored patterns, the pattern is generated
691
 *                          using the indexed color space in the current
692
 *                          color palette. The color space in the graphic
693
 *                          state is set to Pattern color space, the current
694
 *                          color is set to the generated pattern, and the
695
 *                          halftone and color rendering dictionary objects
696
 *                          are taken from the current palette.
697
 *
698
 *    pattern_set_user_gl   Two additional operands. The first provides the
699
 *                          PCL user-defined pattern id. The second is the
700
 *                          current pen. Handling is base on whether the
701
 *                          pattern is colored or uncolored.
702
 *
703
 *                          For uncolored patterns, handling is similar
704
 *                          to pcl_pattern_set_shade_gl.
705
 *
706
 *                          For colored patterns, handling is similar to
707
 *                          pcl_pattern_set_user_pcl.
708
 *
709
 *    pattern_set_gl_RF     Two additional operands, the index of the
710
 *                          GL/2 user defined pattern (created with the
711
 *                          RF command), and the current pen number. The
712
 *                          latter is used only for unoclored RF patterns.
713
 *
714
 *                          To keep life interesting, HP inserted a very
715
 *                          odd feature into the behavior of uncolored
716
 *                          RF patterns. Generally, the applicable SV or
717
 *                          FT command determines whether the current pen
718
 *                          or pen 1 is to be used for the foreground pixels.
719
 *                          However, if the reference pattern does not exist,
720
 *                          the current pen is always used.
721
 *
722
 *                          To accommodate this behavior within the current
723
 *                          scheme, the current pen is passed as a negative
724
 *                          number if pen 1 is for a pattern that exists.
725
 *
726
 * All procedures return 0 on success, < 0 in the event of an error.
727
 *
728
 * If that did not seem to make things complex enough, some additional
729
 * complications arise for transparency in GL/2 and for PCL rasters.
730
 *
731
 * GL/2 has a concept of transparency similar to PCL's, though what GL terms
732
 * "source" transparency corresponds to PCL's pattern transparency (all GL/2
733
 * objects are mask; hence, they have neither color nor background, so the
734
 * PCL concept of source transparency is irrelevant for them). Unlike PCL,
735
 * however, uncolored patterns in GL/2 are fully transparent if the current
736
 * pen is white. The normal code for uncolored patterns is not equipped to
737
 * handle this situation, and it make little sense to modify it for what is
738
 * not a particular useful case. Hence, a special "unsolid" uncolored pattern
739
 * is provided. This pattern has only background, and thus is fully transparent.
740
 *
741
 * The difficulty with PCL rasters is that, being colored objects, they make
742
 * use of a CRD and a halftone to render. Rasters may also interact with the
743
 * current color, which may be using a different CRD and halftone.
744
 *
745
 * The CRD and halftone to be used with rasters are taken from the current
746
 * PCL palette. If the current pattern is either solid foreground (the most
747
 * typical case) or an uncolored pattern, the current "texture" is generated
748
 * using the CRD and halftone from the PCL foreground. The two may not be the
749
 * same, and unfortunately there is room for only one of each in the graphic
750
 * state.
751
 *
752
 * The solution is to make use of an additional graphic state. Patterns in the
753
 * graphic library have their own graphic state. Hence, but converting a solid
754
 * foreground into an uncolored pattern which happens to be "on" everywhere, it
755
 * is possible to achieve the desired result. For performance reasons, this
756
 * should be done only when necessary.
757
 */
758
759
static int
760
pattern_set_white(pcl_state_t * pcs, int arg1,  /* ignored */
761
                  int arg2      /* ignored */
762
    )
763
30.0k
{
764
30.0k
    int code = 0;
765
30.0k
    pcl_cs_base_t *pwhite_cs = 0;
766
30.0k
    pcl_ht_t *pdflt_ht = 0;
767
768
30.0k
    if_debug0m('c', pcs->memory, "[c]pattern_set_white\n");
769
770
    /* build the pure white color space and default halftone if necessary */
771
30.0k
    if ((code =
772
30.0k
         pcl_cs_base_build_white_cspace(pcs, &pwhite_cs, pcs->memory)) >= 0)
773
30.0k
        code = pcl_ht_build_default_ht(pcs, &pdflt_ht, pcs->memory);
774
775
    /* set the halftone and color space */
776
30.0k
    if (code >= 0) {
777
30.0k
        code = pcl_ht_set_halftone(pcs);
778
30.0k
        pcl_ht_release(pdflt_ht);       /* decrement reference to local ptr */
779
30.0k
    }
780
781
30.0k
    if (code >= 0)
782
30.0k
        code = set_unpatterned_color(pcs, NULL, pwhite_cs, &white_paint);
783
30.0k
    pcl_cs_base_release(pwhite_cs);
784
30.0k
    return code;
785
30.0k
}
786
787
static int pattern_set_shade_gl(pcl_state_t * pcs, int inten,   /* intensity value */
788
                                int pen /* pen number for foreground */
789
    );
790
791
static int
792
pattern_set_pen(pcl_state_t * pcs, int pen, int for_pcl_raster)
793
3.29M
{
794
3.29M
    pcl_cs_indexed_t *pindexed = pcs->ppalet->pindexed;
795
3.29M
    int num_entries = pindexed->num_entries;
796
3.29M
    int code = 0;
797
798
3.29M
    if_debug3m('c', pcs->memory,
799
3.29M
               "[c]pattern_set_pen pen=%d, for raster=%d entries=%d\n", pen,
800
3.29M
               for_pcl_raster, num_entries);
801
802
    /* put the pen number in the proper range */
803
3.29M
    if ((pen >= num_entries) &&
804
0
        ((pen = (pen % num_entries) + 1) == num_entries))
805
0
        pen = 1;
806
807
    /* check if the current pen is white; if so, use the "unsolid" pattern */
808
809
3.29M
    if (!for_pcl_raster && pcl_cs_indexed_is_white(pindexed, pen)) {
810
        /* Optimization for a special case where we don't need the
811
           unsolid pattern, drawing an opaque white rectangle with
812
           simple rops (we only check for 2 common rops).  */
813
220k
        if (!pcs->g.source_transparent &&
814
204k
            (pcs->logical_op == rop3_default || pcs->logical_op == rop3_T))
815
15.5k
            goto skip_unsolid;
816
204k
        else {
817
204k
            code = pattern_set_shade_gl(pcs, 1, pen);
818
204k
            if (code >= 0) {
819
204k
                code = gx_set_dev_color(pcs->pgs);
820
204k
                if (code == gs_error_Remap_Color) {
821
0
                    code = pixmap_high_level_pattern(pcs->pgs);
822
0
                    if (code < 0)
823
0
                        return code;
824
0
                    return pattern_set_shade_gl(pcs, 1, pen);
825
0
                }
826
204k
            }
827
204k
            return code;
828
204k
        }
829
220k
    }
830
831
    /* set halftone and crd from the palette */
832
3.08M
  skip_unsolid:
833
3.08M
    {
834
3.08M
        gs_paint_color paint = { {0, 0, 0, 0}
835
3.08M
        };
836
837
3.08M
        convert_index_to_paint(pen, &paint);
838
3.08M
        code = set_unpatterned_color(pcs, pindexed, NULL, &paint);
839
3.08M
    }
840
3.08M
    return code;
841
3.29M
}
842
843
static int
844
pattern_set_frgrnd(pcl_state_t * pcs, int arg1, /* ignored */
845
                   int for_image)
846
10.5M
{
847
10.5M
    pcl_frgrnd_t *pfrgrnd = pcs->pfrgrnd;
848
10.5M
    pcl_palette_t *ppalet = pcs->ppalet;
849
10.5M
    int code = 0;
850
851
10.5M
    if_debug1m('c', pcs->memory, "[c]pattern_set_frgrnd for image=%d\n",
852
10.5M
               for_image);
853
854
    /* check if a solid pattern should be substituted */
855
10.5M
    if (for_image) {
856
6.34k
        if (pfrgrnd->pht != ppalet->pht) {
857
0
            code =
858
0
                set_frgrnd_pattern(pcs, pcl_pattern_get_solid_pattern(pcs),
859
0
                                   true);
860
0
            return code;
861
0
        } else
862
6.34k
            if ((ppalet->pindexed->original_cspace == 1 && !pfrgrnd->is_cmy)
863
6.34k
                || (ppalet->pindexed->original_cspace != 1
864
6.34k
                    && pfrgrnd->is_cmy)) {
865
0
            const byte blk[] = { 0, 0, 0 };
866
0
            gs_paint_color paint;
867
868
            /* NB: HP forces black foreground, as they can't handle different
869
             * colorspaces in foreground and raster palette
870
             */
871
0
            convert_color_to_paint(blk, &paint);
872
0
            code = set_unpatterned_color(pcs, NULL, pfrgrnd->pbase, &paint);
873
0
            return code;
874
0
        }
875
6.34k
    }
876
10.5M
    {
877
10.5M
        gs_paint_color paint;
878
879
10.5M
        convert_color_to_paint(pfrgrnd->color, &paint);
880
10.5M
        code = set_unpatterned_color(pcs, NULL, pfrgrnd->pbase, &paint);
881
10.5M
    }
882
883
10.5M
    return code;
884
10.5M
}
885
886
static int
887
pattern_set_shade_pcl(pcl_state_t * pcs, int inten,     /* intensity value */
888
                      int for_image)
889
53.6k
{
890
53.6k
    pcl_pattern_t *pptrn = pcl_pattern_get_shade(pcs, inten);
891
892
53.6k
    if_debug2m('c', pcs->memory,
893
53.6k
               "[c]pattern_set_shade_pcl intensity=%d, for raster=%d\n",
894
53.6k
               inten, for_image);
895
53.6k
    if (pptrn == 0)
896
51.1k
        return (inten > 0 ? pattern_set_frgrnd(pcs, 0, for_image)
897
51.1k
                : pattern_set_white(pcs, 0, 0));
898
2.56k
    else {
899
2.56k
        pcl_xfm_pcl_set_pat_ref_pt(pcs);
900
2.56k
        return set_frgrnd_pattern(pcs, pptrn, for_image);
901
2.56k
    }
902
53.6k
}
903
904
static int
905
pattern_set_shade_gl(pcl_state_t * pcs, int inten,      /* intensity value */
906
                     int pen    /* pen number for foreground */
907
    )
908
205k
{
909
205k
    pcl_pattern_t *pptrn = pcl_pattern_get_shade(pcs, inten);
910
911
205k
    if_debug2m('c', pcs->memory,
912
205k
               "[c]pattern_set_shade_gl intensity=%d, pen=%d\n", inten, pen);
913
914
    /* check if the current pen is white or the pattern is transparent
915
       and the intensity is 0 (white) and if so use the unsolid
916
       pattern */
917
205k
    if (pcl_cs_indexed_is_white(pcs->ppalet->pindexed, pen) ||
918
1.00k
        (pcs->pattern_transparent && inten == 0))
919
204k
        pptrn = pcl_pattern_get_unsolid_pattern(pcs);
920
921
205k
    if (pptrn == NULL)
922
44
        return (inten > 0 ? pattern_set_pen(pcs, pen, false)
923
44
                : pattern_set_white(pcs, 0, 0));
924
925
205k
    pcl_xfm_gl_set_pat_ref_pt(pcs);
926
205k
    return set_uncolored_palette_pattern(pcs, pptrn, pen);
927
205k
}
928
929
static int
930
pattern_set_hatch_pcl(pcl_state_t * pcs, int indx,      /* cross-hatch pattern index */
931
                      int for_image)
932
630
{
933
630
    pcl_pattern_t *pptrn = pcl_pattern_get_cross(pcs, indx);
934
935
630
    if_debug2m('c', pcs->memory,
936
630
               "[c]pattern_set_hatch_pcl index=%d, for raster=%d\n", indx,
937
630
               for_image);
938
939
630
    if (pptrn == 0)
940
0
        return pattern_set_frgrnd(pcs, 0, for_image);
941
630
    else {
942
630
        pcl_xfm_pcl_set_pat_ref_pt(pcs);
943
630
        return set_frgrnd_pattern(pcs, pptrn, for_image);
944
630
    }
945
630
}
946
947
static int
948
pattern_set_hatch_gl(pcl_state_t * pcs, int indx,       /* cross-hatch pattern index */
949
                     int pen    /* pen number for foreground */
950
    )
951
0
{
952
0
    pcl_pattern_t *pptrn = pcl_pattern_get_cross(pcs, indx);
953
954
0
    if_debug2m('c', pcs->memory, "[c]pattern_set_hatch_gl index=%d pen=%d\n",
955
0
               indx, pen);
956
    /* check if the current pen is white; if so, use the "unsolid" pattern */
957
0
    if (pcl_cs_indexed_is_white(pcs->ppalet->pindexed, pen))
958
0
        pptrn = pcl_pattern_get_unsolid_pattern(pcs);
959
960
0
    if (pptrn == NULL)
961
0
        return pattern_set_pen(pcs, pen, false);
962
963
0
    pcl_xfm_gl_set_pat_ref_pt(pcs);
964
0
    return set_uncolored_palette_pattern(pcs, pptrn, pen);
965
0
}
966
967
static int
968
pattern_set_user_pcl(pcl_state_t * pcs, int id, /* pattern id. */
969
                     int for_image)
970
0
{
971
0
    pcl_pattern_t *pptrn = pcl_pattern_get_pcl_uptrn(pcs, id);
972
973
0
    if_debug2m('c', pcs->memory, "[c]pattern_set_user_pcl id=%d raster=%d\n",
974
0
               id, for_image);
975
976
0
    if (pptrn == 0)
977
0
        return pattern_set_frgrnd(pcs, 0, for_image);
978
0
    else {
979
0
        pcl_xfm_pcl_set_pat_ref_pt(pcs);
980
0
        if (pptrn->ppat_data->type == pcl_pattern_uncolored)
981
0
            return set_frgrnd_pattern(pcs, pptrn, for_image);
982
0
        else
983
0
            return set_colored_pattern(pcs, pptrn);
984
0
    }
985
0
}
986
987
static int
988
pattern_set_user_gl(pcl_state_t * pcs, int id,  /* pattern id. */
989
                    int pen     /* pen to use for foreground */
990
    )
991
0
{
992
0
    pcl_pattern_t *pptrn = pcl_pattern_get_pcl_uptrn(pcs, id);
993
994
0
    if_debug2m('c', pcs->memory, "[c]pattern_set_user_gl id=%d, pen=%d\n", id,
995
0
               pen);
996
997
0
    if (pptrn == 0)
998
0
        return pattern_set_pen(pcs, 0, false);
999
0
    else {
1000
1001
0
        pcl_xfm_gl_set_pat_ref_pt(pcs);
1002
0
        if (pptrn->ppat_data->type == pcl_pattern_uncolored) {
1003
1004
            /* check if the current pen is white */
1005
0
            if (pcl_cs_indexed_is_white(pcs->ppalet->pindexed, pen)) {
1006
0
                pptrn = pcl_pattern_get_unsolid_pattern(pcs);
1007
0
                if (pptrn == NULL) return e_Memory;
1008
0
            }
1009
0
            return set_uncolored_palette_pattern(pcs, pptrn, pen);
1010
1011
0
        } else
1012
0
            return set_colored_pattern(pcs, pptrn);
1013
0
    }
1014
0
}
1015
1016
static int
1017
pattern_set_gl_RF(pcl_state_t * pcs, int indx,  /* GL/2 RF pattern index */
1018
                  int pen       /* used only for uncolored patterns */
1019
    )
1020
31.8k
{
1021
31.8k
    pcl_pattern_t *pptrn = pcl_pattern_get_gl_uptrn(pcs, indx);
1022
1023
31.8k
    if_debug2m('c', pcs->memory, "[c]pattern_set_gl_RF index=%d pen=%d\n",
1024
31.8k
               indx, pen);
1025
    /*
1026
     * HACK - if pen 1 is to be use for actual uncolored RF patterns, the pen
1027
     * operand will be the opposite of the current pen number. This allows us
1028
     * to use the current pen if the pattern does not exist.
1029
     */
1030
31.8k
    if (pptrn == 0)
1031
5.10k
        return pattern_set_pen(pcs, (pen < 0 ? -pen : pen), false);
1032
26.7k
    else {
1033
26.7k
        if (pen < 0)
1034
0
            pen = 1;
1035
1036
26.7k
        pcl_xfm_gl_set_pat_ref_pt(pcs);
1037
26.7k
        if (pptrn != NULL && pptrn->ppat_data != NULL) {
1038
26.7k
            if (pptrn->ppat_data->type == pcl_pattern_uncolored) {
1039
1040
                /* check if the current pen is white */
1041
26.7k
                if (pcl_cs_indexed_is_white(pcs->ppalet->pindexed, pen)) {
1042
0
                    pptrn = pcl_pattern_get_unsolid_pattern(pcs);
1043
0
                    if (pptrn == NULL) return e_Memory;
1044
0
                }
1045
26.7k
                return set_uncolored_palette_pattern(pcs, pptrn, pen);
1046
1047
26.7k
            } else
1048
0
                return set_colored_pattern(pcs, pptrn);
1049
26.7k
        } else
1050
0
            return e_Syntax;
1051
26.7k
    }
1052
31.8k
}
1053
1054
/*
1055
 * Return the appropriate "set" procedure, given a PCL pattern type.
1056
 */
1057
pcl_pattern_set_proc_t
1058
pcl_pattern_get_proc_PCL(pcl_pattern_source_t pattern_source)
1059
10.5M
{
1060
10.5M
    static const pcl_pattern_set_proc_t procs[] = { pattern_set_frgrnd,
1061
10.5M
        pattern_set_white,
1062
10.5M
        pattern_set_shade_pcl,
1063
10.5M
        pattern_set_hatch_pcl,
1064
10.5M
        pattern_set_user_pcl,
1065
10.5M
        0,
1066
10.5M
        pattern_set_pen
1067
10.5M
    };
1068
1069
10.5M
    return procs[(int)pattern_source];
1070
10.5M
}
1071
1072
/*
1073
 * Returen the appropriate "set" procedure, given a GL fill type specification.
1074
 */
1075
pcl_pattern_set_proc_t
1076
pcl_pattern_get_proc_FT(hpgl_FT_pattern_source_t pattern_source)
1077
1.05M
{
1078
1.05M
    if ((pattern_source == hpgl_FT_pattern_solid_pen1) ||
1079
32.8k
        (pattern_source == hpgl_FT_pattern_solid_pen2))
1080
1.02M
        return pattern_set_pen;
1081
32.8k
    else if (pattern_source == hpgl_FT_pattern_shading)
1082
1.00k
        return pattern_set_shade_gl;
1083
31.8k
    else if (pattern_source == hpgl_FT_pattern_RF)
1084
31.8k
        return pattern_set_gl_RF;
1085
11
    else if (pattern_source == hpgl_FT_pattern_cross_hatch)
1086
0
        return pattern_set_hatch_gl;
1087
11
    else if (pattern_source == hpgl_FT_pattern_user_defined)
1088
0
        return pattern_set_user_gl;
1089
11
    else
1090
11
        return 0;
1091
1.05M
}
1092
1093
/*
1094
 * Returen the appropriate "set" procedure, given a GL screened vector
1095
 * specification.
1096
 */
1097
pcl_pattern_set_proc_t
1098
pcl_pattern_get_proc_SV(hpgl_SV_pattern_source_t pattern_source)
1099
2.26M
{
1100
2.26M
    if (pattern_source == hpgl_SV_pattern_solid_pen)
1101
2.26M
        return pattern_set_pen;
1102
0
    else if (pattern_source == hpgl_SV_pattern_shade)
1103
0
        return pattern_set_shade_gl;
1104
0
    else if (pattern_source == hpgl_SV_pattern_RF)
1105
0
        return pattern_set_gl_RF;
1106
0
    else if (pattern_source == hpgl_SV_pattern_cross_hatch)
1107
0
        return pattern_set_hatch_gl;
1108
0
    else if (pattern_source == hpgl_SV_pattern_user_defined)
1109
0
        return pattern_set_user_gl;
1110
0
    else
1111
0
        return 0;
1112
2.26M
}
1113
1114
/*
1115
 * ESC * c <#/id> G
1116
 *
1117
 * Set the pattern id.
1118
 */
1119
static int
1120
set_pattern_id(pcl_args_t * pargs, pcl_state_t * pcs)
1121
3.93k
{
1122
3.93k
    pcs->pattern_id = int_arg(pargs);
1123
3.93k
    return 0;
1124
3.93k
}
1125
1126
/*
1127
 * ESC * v <bool> N
1128
 *
1129
 * Set source transparency mode
1130
 */
1131
static int
1132
set_source_transparency_mode(pcl_args_t * pargs, pcl_state_t * pcs)
1133
1.59k
{
1134
1.59k
    int code = 0;
1135
1.59k
    uint i = uint_arg(pargs);
1136
1137
1.59k
    if (i <= 1) {
1138
1.59k
        code = pcl_break_underline(pcs);
1139
1.59k
        pcs->source_transparent = (i == 0);
1140
1.59k
    }
1141
1.59k
    return code;
1142
1.59k
}
1143
1144
/*
1145
 * ESC * v <bool> O
1146
 *
1147
 * Set pattern transparency mode.
1148
 */
1149
static int
1150
set_pattern_transparency_mode(pcl_args_t * pargs, pcl_state_t * pcs)
1151
3.41k
{
1152
3.41k
    int code = 0;
1153
3.41k
    uint i = uint_arg(pargs);
1154
1155
3.41k
    if (i <= 1) {
1156
3.39k
        code = pcl_break_underline(pcs);
1157
3.39k
        pcs->pcl_pattern_transparent = (i == 0);
1158
3.39k
    }
1159
3.41k
    return code;
1160
3.41k
}
1161
1162
/*
1163
 * ESC * v # T
1164
 *
1165
 * Set current pattern id.
1166
 */
1167
static int
1168
select_current_pattern(pcl_args_t * pargs, pcl_state_t * pcs)
1169
515
{
1170
515
    int code = 0;
1171
515
    uint i = uint_arg(pargs);
1172
1173
515
    if (i <= (int)pcl_pattern_user_defined) {
1174
514
        code = pcl_break_underline(pcs);
1175
514
        pcs->current_pattern_id = pcs->pattern_id;
1176
514
        pcs->pattern_type = (pcl_pattern_source_t) i;
1177
514
    }
1178
515
    return code;
1179
515
}
1180
1181
/*
1182
 * ESC * o # W
1183
 *
1184
 * Driver configuration command.  A partial implementation to show
1185
 * that we are parsing the command correctly.  The lightness and
1186
 * saturation parameters are not documented so we do not believe this
1187
 * command will be used by an application or driver.
1188
 *
1189
 */
1190
1191
typedef struct driver_configuration_s
1192
{
1193
    byte device_id;
1194
    byte function_index;
1195
    char arguments;
1196
} driver_configuration_t;
1197
1198
static int
1199
set_driver_configuration(pcl_args_t * pargs,    /* ignored */
1200
                         pcl_state_t * pcs      /* ignored */
1201
    )
1202
0
{
1203
0
    uint count = uint_arg(pargs);
1204
1205
0
    driver_configuration_t *driver =
1206
0
        (driver_configuration_t *) arg_data(pargs);
1207
1208
#ifdef DEBUG
1209
    if (gs_debug_c('i')) {
1210
        pcl_debug_dump_data(pcs->memory, arg_data(pargs), uint_arg(pargs));
1211
    }
1212
#endif
1213
1214
0
    if (pcs->personality == pcl5e)
1215
0
        return 0;
1216
1217
0
    if (count != sizeof(driver_configuration_t))
1218
0
        return e_Range;
1219
1220
    /* the only device known to support this command */
1221
0
    if ((driver->device_id < 6) /* 6 == hp color laserjet */
1222
0
        ||                      /* 7 == hp clj 5 */
1223
0
        (driver->device_id > 8)) {      /* 8 == hp 4500 - 4550 */
1224
0
        dmprintf1(pcs->memory, "unknown device id %d\n", driver->device_id);
1225
0
        return e_Range;
1226
0
    }
1227
1228
0
    switch (driver->function_index) {
1229
0
        case 0:                /* lightness */
1230
0
            {
1231
0
                int code;
1232
1233
0
                if (driver->arguments < -100 || driver->arguments > 100)
1234
0
                    return e_Range;
1235
                /* map -100..100 to gamma setting 0.05..4.05 */
1236
0
                code =
1237
0
                    pcl_palette_set_gamma(pcs,
1238
0
                                          ((driver->arguments +
1239
0
                                            100.0) / 200.0) + 0.05);
1240
0
                if (code < 0)
1241
0
                    return code;
1242
0
            }
1243
0
            break;
1244
0
        case 1:                /* saturation */
1245
0
            {
1246
0
                int code;
1247
1248
0
                if (driver->arguments < -100 || driver->arguments > 100)
1249
0
                    return e_Range;
1250
                /* map -100..100 to gamma setting 0.05..4.05 */
1251
0
                code =
1252
0
                    pcl_palette_set_gamma(pcs,
1253
0
                                          ((driver->arguments +
1254
0
                                            100.0) / 200.0) + 0.05);
1255
0
                if (code < 0)
1256
0
                    return code;
1257
0
            }
1258
0
            break;
1259
0
        case 4:
1260
            /* driver arguments 3 & 6 are parsed, but not implemented.  In
1261
               our model where all data is treated as sRGB and color
1262
               conversion is expected to be done by the device, vivid
1263
               graphics (argument == 3) should set a device parameter to
1264
               disable color conversion.  We don't think there is any
1265
               demand for this feature, and it is not currently
1266
               supported. */
1267
0
            if (driver->arguments == 3) {
1268
0
                ;
1269
0
            } else if (driver->arguments == 6) {
1270
0
                ;
1271
0
            } else
1272
0
                return e_Range;
1273
0
            break;
1274
0
        default:
1275
0
            return e_Range;
1276
0
    }
1277
0
    return 0;
1278
0
}
1279
1280
/*
1281
 * Initialization and reset routines.
1282
 */
1283
static int
1284
pattern_do_registration(pcl_parser_state_t * pcl_parser_state,
1285
                        gs_memory_t * pmem)
1286
11.0k
{
1287
11.0k
    DEFINE_CLASS('*') {
1288
11.0k
        'c', 'G',
1289
11.0k
            PCL_COMMAND("Pattern ID",
1290
11.0k
                        set_pattern_id,
1291
11.0k
                        pca_neg_ignore | pca_big_ignore | pca_in_rtl)
1292
11.0k
    }, {
1293
11.0k
        'v', 'N',
1294
11.0k
            PCL_COMMAND("Source Transparency Mode",
1295
11.0k
                        set_source_transparency_mode,
1296
11.0k
                        pca_neg_ignore | pca_big_ignore | pca_in_rtl |
1297
11.0k
                        pca_dont_lockout_in_rtl)
1298
11.0k
    }, {
1299
11.0k
        'v', 'O',
1300
11.0k
            PCL_COMMAND("Pattern Transparency Mode",
1301
11.0k
                        set_pattern_transparency_mode,
1302
11.0k
                        pca_neg_ignore | pca_big_ignore | pca_in_rtl)
1303
11.0k
    }, {
1304
11.0k
        'v', 'T',
1305
11.0k
            PCL_COMMAND("Select Current Pattern",
1306
11.0k
                        select_current_pattern,
1307
11.0k
                        pca_neg_ignore | pca_big_ignore | pca_in_rtl)
1308
11.0k
    }, {
1309
11.0k
        'o', 'W',
1310
11.0k
            PCL_COMMAND("Driver Configuration Command",
1311
11.0k
                        set_driver_configuration, pca_bytes | pca_in_rtl)
1312
11.0k
    }, END_CLASS return 0;
1313
1314
11.0k
}
1315
1316
static int
1317
pattern_do_reset(pcl_state_t * pcs, pcl_reset_type_t type)
1318
44.0k
{
1319
44.0k
    static const uint mask = (pcl_reset_initial
1320
44.0k
                              | pcl_reset_cold
1321
44.0k
                              | pcl_reset_printer | pcl_reset_overlay);
1322
1323
44.0k
    if ((type & mask) != 0) {
1324
44.0k
        if ((type & pcl_reset_initial) != 0)
1325
11.0k
            pcl_pattern_init_bi_patterns(pcs);
1326
44.0k
        pcs->pcl_pattern_transparent = true;
1327
44.0k
        pcs->pattern_transparent = true;
1328
44.0k
        pcs->source_transparent = true;
1329
44.0k
        pcs->pattern_id = 0;
1330
44.0k
        pcs->current_pattern_id = 0;
1331
44.0k
        pcs->pattern_type = pcl_pattern_solid_frgrnd;
1332
44.0k
    }
1333
44.0k
    if (type & pcl_reset_permanent || type & pcl_reset_printer) {
1334
33.0k
        if (gstate_pattern_cache(pcs->pgs)) {
1335
660
            gs_gstate *pgs = pcs->pgs;
1336
1337
660
            (gstate_pattern_cache(pgs)->free_all) (gstate_pattern_cache(pgs));
1338
660
            gs_free_object(pcs->memory,
1339
660
                           gstate_pattern_cache(pgs)->tiles,
1340
660
                           "pattern_do_reset(tiles)");
1341
660
            gs_free_object(pcs->memory,
1342
660
                           gstate_pattern_cache(pgs),
1343
660
                           "pattern_do_reset(struct)");
1344
3.30k
            while (pgs) {
1345
2.64k
                gstate_set_pattern_cache(pgs, 0);
1346
2.64k
                pgs = gs_gstate_saved(pgs);
1347
2.64k
            }
1348
660
        }
1349
33.0k
    }
1350
44.0k
    return 0;
1351
44.0k
}
1352
1353
const pcl_init_t pcl_pattern_init =
1354
    { pattern_do_registration, pattern_do_reset, 0 };