Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gximono.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
/* General mono-component image rendering */
18
#include "gx.h"
19
#include "memory_.h"
20
#include "gpcheck.h"
21
#include "gserrors.h"
22
#include "gxfixed.h"
23
#include "gxarith.h"
24
#include "gxmatrix.h"
25
#include "gsccolor.h"
26
#include "gspaint.h"
27
#include "gsutil.h"
28
#include "gxdevice.h"
29
#include "gxcmap.h"
30
#include "gxdcolor.h"
31
#include "gxgstate.h"
32
#include "gxdevmem.h"
33
#include "gdevmem.h"            /* for mem_mono_device */
34
#include "gxcpath.h"
35
#include "gximage.h"
36
#include "gzht.h"
37
#include "gsicc.h"
38
#include "gsicc_cache.h"
39
#include "gsicc_cms.h"
40
#include "gxcie.h"
41
#include "gscie.h"
42
#include "gxht_thresh.h"
43
#include "gxdda.h"
44
#include "gxdevsop.h"
45
#ifdef WITH_CAL
46
#include "cal.h"
47
#endif
48
49
#define fastfloor(x) (((int)(x)) - (((x)<0) && ((x) != (float)(int)(x))))
50
51
/* Enable the following define to perform a little extra work to stop
52
 * spurious valgrind errors. The code should perform perfectly even without
53
 * this enabled, but enabling it makes debugging much easier.
54
 */
55
/* #define PACIFY_VALGRIND */
56
57
/* ------ Strategy procedure ------ */
58
59
/* Check the prototype. */
60
iclass_proc(gs_image_class_3_mono);
61
62
static irender_proc(image_render_mono);
63
#ifndef WITH_CAL
64
static irender_proc(image_render_mono_ht);
65
#else
66
static irender_proc(image_render_mono_ht_cal);
67
static int image_render_mono_ht_cal_skip_line(gx_image_enum *penum,
68
                gx_device *dev);
69
70
static void
71
halftone_callback(cal_halftone_data_t *ht, void *arg)
72
{
73
    gx_device *dev = arg;
74
    gx_color_index dev_white = gx_device_white(dev);
75
    gx_color_index dev_black = gx_device_black(dev);
76
77
    if (dev->num_planar_planes) {
78
        (*dev_proc(dev, copy_planes)) (dev, ht->data, ht->x + (ht->offset_x<<3), ht->raster,
79
            gx_no_bitmap_id, ht->x, ht->y, ht->w, ht->h,
80
            ht->plane_raster);
81
    } else {
82
        (*dev_proc(dev, copy_mono)) (dev, ht->data, ht->x + (ht->offset_x<<3), ht->raster,
83
            gx_no_bitmap_id, ht->x, ht->y, ht->w, ht->h, dev_white,
84
            dev_black);
85
    }
86
}
87
88
static cal_halftone*
89
halftone_init(gx_image_enum *penum)
90
{
91
    cal_halftone *cal_ht = NULL;
92
    gx_dda_fixed dda_ht;
93
    int k;
94
    gx_ht_order *d_order;
95
    int code;
96
    byte *cache = (penum->color_cache != NULL ? penum->color_cache->device_contone : NULL);
97
    cal_matrix matrix;
98
    int clip_x, clip_y;
99
    gx_device_halftone *pdht = gx_select_dev_ht(penum->pgs);
100
101
    if (!gx_device_must_halftone(penum->dev))
102
        return NULL;
103
104
    if (penum->pgs == NULL || pdht == NULL)
105
        return NULL;
106
107
    dda_ht = penum->dda.pixel0.x;
108
    if (penum->dxx > 0)
109
        dda_translate(dda_ht, -fixed_epsilon);
110
    matrix.xx = penum->matrix.xx;
111
    matrix.xy = penum->matrix.xy;
112
    matrix.yx = penum->matrix.yx;
113
    matrix.yy = penum->matrix.yy;
114
    matrix.tx = penum->matrix.tx + matrix.xx * penum->rect.x + matrix.yx * penum->rect.y;
115
    matrix.ty = penum->matrix.ty + matrix.xy * penum->rect.x + matrix.yy * penum->rect.y;
116
117
    clip_x = fixed2int(penum->clip_outer.p.x);
118
    clip_y = fixed2int(penum->clip_outer.p.y);
119
    cal_ht = cal_halftone_init(penum->memory->gs_lib_ctx->core->cal_ctx,
120
                               penum->memory->non_gc_memory,
121
                               penum->rect.w,
122
                               penum->rect.h,
123
                               &matrix,
124
                               penum->dev->color_info.num_components,
125
                               cache,
126
                               clip_x,
127
                               clip_y,
128
                               fixed2int_ceiling(penum->clip_outer.q.x) - clip_x,
129
                               fixed2int_ceiling(penum->clip_outer.q.y) - clip_y,
130
                               penum->adjust);
131
    if (cal_ht == NULL)
132
        goto fail;
133
134
    for (k = 0; k < pdht->num_comp; k++) {
135
        d_order = &(pdht->components[k].corder);
136
        code = gx_ht_construct_threshold(d_order, penum->dev, penum->pgs, k);
137
        if (code < 0)
138
            goto fail;
139
        if (cal_halftone_add_screen(penum->memory->gs_lib_ctx->core->cal_ctx,
140
                                    penum->memory->non_gc_memory,
141
                                    cal_ht,
142
                                    pdht->components[k].corder.threshold_inverted,
143
                                    pdht->components[k].corder.width,
144
                                    pdht->components[k].corder.full_height,
145
                                    penum->pgs->screen_phase[k].x,
146
                                    -penum->pgs->screen_phase[k].y,
147
                                    pdht->components[k].corder.threshold) < 0)
148
            goto fail;
149
    }
150
151
    return cal_ht;
152
153
fail:
154
    cal_halftone_fin(cal_ht, penum->memory->non_gc_memory);
155
    return NULL;
156
}
157
#endif
158
159
int
160
gs_image_class_3_mono(gx_image_enum * penum, irender_proc_t *render_fn)
161
1.32M
{
162
1.32M
#if USE_FAST_HT_CODE
163
1.32M
    bool use_fast_code = true;
164
#else
165
    bool use_fast_code = false;
166
#endif
167
1.32M
    int code = 0;
168
    /* Set up the link now */
169
1.32M
    const gs_color_space *pcs;
170
1.32M
    gsicc_rendering_param_t rendering_params;
171
1.32M
    cmm_dev_profile_t *dev_profile;
172
1.32M
    bool dev_color_ok = false;
173
1.32M
    bool is_planar_dev = penum->dev->num_planar_planes;
174
175
1.32M
    if (penum->spp == 1) {
176
        /* At this point in time, only use the ht approach if our device
177
           uses halftoning, and our source image is a reasonable size.  We
178
           probably don't want to do this if we have a bunch of tiny little
179
           images.  Then the rect fill approach is probably not all that bad.
180
           Also for now avoid images that include a type3 image mask.  Due
181
           to the limited precision and mismatch of the stepping space in which
182
           the interpolations occur this can cause a minor mismatch at large
183
           scalings */
184
185
        /* Allow this for CMYK planar and mono binary halftoned devices */
186
653k
        dev_color_ok = ((penum->dev->color_info.num_components == 1 &&
187
635k
                         penum->dev->color_info.depth == 1) ||
188
#if 0
189
                         /* Don't allow CMYK Planar devices just yet */
190
                         0);
191
#else
192
291k
                        (penum->dev->color_info.num_components == 4 &&
193
587
                         penum->dev->color_info.depth == 4 && is_planar_dev));
194
653k
#endif
195
196
653k
        if (use_fast_code && penum->pcs != NULL && dev_color_ok &&
197
109k
            penum->bps == 8 && (penum->posture == image_portrait
198
129
            || penum->posture == image_landscape) &&
199
106k
            penum->image_parent_type == gs_image_type1 &&
200
105k
            gx_transfer_is_monotonic(penum->pgs, 0)) {
201
105k
            penum->icc_setup.need_decode = false;
202
            /* Check if we need to do any decoding.  */
203
105k
            if ( penum->map[0].decoding != sd_none ) {
204
1.88k
                if (!(penum->map[0].decoding == sd_compute
205
1.88k
                     && penum->map[0].decode_factor == 1.0 &&
206
1.86k
                        penum->map[0].decode_lookup[0] == 0.0)) {
207
18
                    penum->icc_setup.need_decode = true;
208
18
                }
209
1.88k
            }
210
105k
            code = dev_proc(penum->dev, get_profile)(penum->dev, &dev_profile);
211
105k
            if (code < 0)
212
0
                return code;
213
214
            /* Define the rendering intents */
215
105k
            rendering_params.black_point_comp = penum->pgs->blackptcomp;
216
105k
            rendering_params.graphics_type_tag = GS_IMAGE_TAG;
217
105k
            rendering_params.override_icc = false;
218
105k
            rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
219
105k
            rendering_params.rendering_intent = penum->pgs->renderingintent;
220
105k
            rendering_params.cmm = gsCMM_DEFAULT;
221
105k
            if (gs_color_space_get_index(penum->pcs) ==
222
105k
                gs_color_space_index_Indexed) {
223
1.88k
                pcs = penum->pcs->base_space;
224
103k
            } else {
225
103k
                pcs = penum->pcs;
226
103k
            }
227
105k
            if (gs_color_space_is_PSCIE(pcs) && pcs->icc_equivalent != NULL) {
228
0
                pcs = pcs->icc_equivalent;
229
0
            }
230
231
            /* The code below falls over if cmm->icc_profile_data is NULL.
232
             * For now, just drop out. Michael can review this when he
233
             * returns. */
234
105k
            if (pcs->cmm_icc_profile_data == NULL)
235
31
                goto not_fast_halftoning;
236
237
105k
            penum->icc_setup.is_lab = pcs->cmm_icc_profile_data->islab;
238
105k
            penum->icc_setup.must_halftone = gx_device_must_halftone(penum->dev);
239
            /* The effective transfer is built into the threshold array */
240
105k
            penum->icc_setup.has_transfer = false;
241
105k
            if (penum->icc_setup.is_lab)
242
59
                penum->icc_setup.need_decode = false;
243
105k
            if (penum->icc_link == NULL) {
244
105k
                penum->icc_link = gsicc_get_link(penum->pgs, penum->dev, pcs, NULL,
245
105k
                    &rendering_params, penum->memory);
246
105k
            }
247
            /* PS CIE color spaces may have addition decoding that needs to
248
               be performed to ensure that the range of 0 to 1 is provided
249
               to the CMM since ICC profiles are restricted to that range
250
               but the PS color spaces are not. */
251
105k
            penum->use_cie_range = false;
252
105k
            if (gs_color_space_is_PSCIE(penum->pcs) &&
253
0
                penum->pcs->icc_equivalent != NULL) {
254
                /* We have a PS CIE space.  Check the range */
255
0
                if ( !check_cie_range(penum->pcs) ) {
256
                    /* It is not 0 to 1.  We will be doing decode
257
                       plus an additional linear adjustment */
258
0
                    penum->use_cie_range = (get_cie_range(penum->pcs) != NULL);
259
0
                }
260
0
            }
261
            /* If the image has more than 256 pixels then go ahead and
262
               precompute the contone device colors for all of our 256 source
263
               values.  We should not be taking this path for cases where
264
               we have lots of tiny little images.  Mark those that are
265
               transparent or masked also at this time.  Since halftoning will
266
               be done via thresholding we will keep clues in continuous tone */
267
105k
            code = image_init_color_cache(penum, penum->bps, penum->spp);
268
105k
            if (code >= 0) {
269
#ifdef WITH_CAL
270
                penum->cal_ht = halftone_init(penum);
271
                if (penum->cal_ht != NULL)
272
                {
273
                    penum->skip_next_line = image_render_mono_ht_cal_skip_line;
274
                    *render_fn = &image_render_mono_ht_cal;
275
                    return code;
276
                }
277
#else
278
105k
                code = gxht_thresh_image_init(penum);
279
105k
                if (code >= 0) {
280
104k
                    *render_fn = &image_render_mono_ht;
281
104k
                    return code;
282
104k
                }
283
105k
#endif
284
105k
            }
285
105k
        }
286
548k
not_fast_halftoning:
287
        /*
288
         * Use the slow loop for imagemask with a halftone or a non-default
289
         * logical operation.
290
         */
291
548k
        penum->slow_loop =
292
548k
            (penum->masked && !color_is_pure(penum->icolor0)) ||
293
548k
            penum->use_rop;
294
        /* We can bypass X clipping for portrait mono-component images. */
295
548k
        if (!(penum->slow_loop || penum->posture != image_portrait))
296
516k
            penum->clip_image &= ~(image_clip_xmin | image_clip_xmax);
297
548k
        if_debug0m('b', penum->memory, "[b]render=mono\n");
298
        /* Precompute values needed for rasterizing. */
299
548k
        penum->dxx =
300
548k
            float2fixed(penum->matrix.xx + fixed2float(fixed_epsilon) / 2);
301
        /*
302
         * Scale the mask colors to match the scaling of each sample to a
303
         * full byte.  Also, if black or white is transparent, reset icolor0
304
         * or icolor1, which are used directly in the fast case loop.
305
         */
306
548k
        if (penum->use_mask_color) {
307
1.87k
            gx_image_scale_mask_colors(penum, 0);
308
1.87k
            if (penum->mask_color.values[0] <= 0)
309
1.86k
                color_set_null(penum->icolor0);
310
1.87k
            if (penum->mask_color.values[1] >= 255)
311
0
                color_set_null(penum->icolor1);
312
1.87k
        }
313
        /* Reset the clues here, rather than in image_render_mono as
314
         * previously. Even doing so this often may be overzealous. */
315
548k
        image_init_clues(penum, penum->bps, penum->spp);
316
548k
        *render_fn = &image_render_mono;
317
548k
    }
318
1.21M
    return 0;
319
1.32M
}
320
321
#define USE_SET_GRAY_FUNCTION 0
322
#if USE_SET_GRAY_FUNCTION
323
/* Temporary function to make it easier to debug the uber-macro below */
324
static inline int
325
image_set_gray(byte sample_value, const bool masked, uint mask_base,
326
                uint mask_limit, gx_device_color **ppdevc, gs_client_color *cc,
327
                const gs_color_space *pcs, const gs_gstate *pgs,
328
                gx_device * dev, gs_color_select_t gs_color_select_source,
329
                gx_image_enum * penum)
330
{
331
   cs_proc_remap_color((*remap_color));
332
   int code;
333
   gx_device_color *pdevc;
334
   pdevc = *ppdevc = &penum->clues[sample_value].dev_color;
335
336
   if (!color_is_set(pdevc)) {
337
       if ((uint)(sample_value - mask_base) < mask_limit) {
338
           color_set_null(pdevc);
339
       } else {
340
            switch ( penum->map[0].decoding )
341
            {
342
            case sd_none:
343
            cc->paint.values[0] = (sample_value) * (1.0f / 255.0f);  /* faster than / */
344
            break;
345
            case sd_lookup:     /* <= 4 significant bits */
346
            cc->paint.values[0] =
347
              penum->map[0].decode_lookup[(sample_value) >> 4];
348
            break;
349
            case sd_compute:
350
            cc->paint.values[0] =
351
              penum->map[0].decode_base + (sample_value) * penum->map[0].decode_factor;
352
            }
353
            remap_color = pcs->type->remap_color;
354
            code = (*remap_color)(cc, pcs, pdevc, pgs, dev, gs_color_select_source);
355
            return(code);
356
        }
357
    } else if (!color_is_pure(pdevc)) {
358
        code = gx_color_load_select(pdevc, pgs, dev, gs_color_select_source);
359
        if (code < 0)
360
            return(code);
361
    }
362
    return(0);
363
}
364
#endif
365
366
/*
367
 * Rendering procedure for general mono-component images, dealing with
368
 * multiple bit-per-sample images, general transformations, arbitrary
369
 * single-component color spaces (DeviceGray, DevicePixel, CIEBasedA,
370
 * Separation, Indexed), and color masking. This procedure handles a
371
 * single scan line.
372
 */
373
static int
374
image_render_mono(gx_image_enum * penum, const byte * buffer, int data_x,
375
                  uint w, int h, gx_device * dev)
376
7.95M
{
377
7.95M
    const gs_gstate *pgs = penum->pgs;
378
7.95M
    gs_logical_operation_t lop = penum->log_op;
379
7.95M
    const bool masked = penum->masked;
380
7.95M
    const gs_color_space *pcs = NULL;   /* only set for non-masks */
381
7.95M
    cs_proc_remap_color((*remap_color)) = NULL; /* ditto */
382
7.95M
    gs_client_color cc;
383
7.95M
    gx_device_color *pdevc = penum->icolor1;    /* color for masking */
384
7.95M
    uint mask_base =            /* : 0 to pacify Valgrind */
385
7.95M
        (penum->use_mask_color ? penum->mask_color.values[0] : 0);
386
7.95M
    uint mask_limit =
387
7.95M
        (penum->use_mask_color ?
388
7.93M
         penum->mask_color.values[1] - mask_base + 1 : 0);
389
/*
390
 * Free variables of IMAGE_SET_GRAY:
391
 *   Read: penum, pgs, dev, mask_base, mask_limit
392
 *   Set: pdevc, code, cc
393
 */
394
7.95M
#define IMAGE_SET_GRAY(sample_value)\
395
64.4M
  BEGIN\
396
64.4M
    pdevc = &penum->clues[sample_value].dev_color;\
397
64.4M
    if (!color_is_set(pdevc)) {\
398
4.56M
        if ((uint)(sample_value - mask_base) < mask_limit)\
399
4.56M
            color_set_null(pdevc);\
400
4.56M
        else {\
401
4.56M
            decode_sample(sample_value, cc, 0);\
402
4.56M
            code = (*remap_color)(&cc, pcs, pdevc, pgs, dev, gs_color_select_source);\
403
4.56M
            if (code < 0)\
404
4.56M
                goto err;\
405
4.56M
            pdevc->tag = device_current_tag(dev);\
406
4.56M
        }\
407
56.6M
    } else if (!color_is_pure(pdevc)) {\
408
16.9M
        code = gx_color_load_select(pdevc, pgs, dev, gs_color_select_source);\
409
16.9M
        if (code < 0)\
410
16.9M
            goto err;\
411
16.9M
    }\
412
64.4M
  END
413
7.95M
    gx_dda_fixed_point next;    /* (y not used in fast loop) */
414
7.95M
    gx_dda_step_fixed dxx2, dxx3, dxx4;         /* (not used in all loops) */
415
7.95M
    const byte *psrc_initial = buffer + data_x;
416
7.95M
    const byte *psrc = psrc_initial;
417
7.95M
    const byte *rsrc = psrc;    /* psrc at start of run */
418
7.95M
    const byte *endp = psrc + w;
419
7.95M
    const byte *stop = endp;
420
7.95M
    fixed xrun;                 /* x at start of run */
421
7.95M
    byte run;           /* run value */
422
7.95M
    int htrun = (masked ? 255 : -2);            /* halftone run value */
423
7.95M
    int i, code = 0;
424
425
7.95M
    if (h == 0)
426
1.05M
        return 0;
427
    /*
428
     * Make sure the cache setup matches the graphics state.  Also determine
429
     * whether all tiles fit in the cache.  We may bypass the latter check
430
     * for masked images with a pure color.
431
     */
432
433
6.90M
    next = penum->dda.pixel0;
434
6.90M
    xrun = dda_current(next.x);
435
6.90M
    if (!masked) {
436
2.66M
        pcs = penum->pcs;       /* (may not be set for masks) */
437
2.66M
        remap_color = pcs->type->remap_color;
438
2.66M
    }
439
6.90M
    run = *psrc;
440
    /* Find the last transition in the input. */
441
6.90M
    if (masked &&
442
4.24M
        (penum->posture != image_portrait) &&
443
1.00M
        (penum->posture != image_landscape)) {
444
        /* No need to calculate stop */
445
5.90M
    } else {
446
5.90M
        byte last = stop[-1];
447
448
691M
        while (stop > psrc && stop[-1] == last)
449
685M
            --stop;
450
5.90M
    }
451
6.90M
    if (penum->slow_loop || penum->posture != image_portrait) {
452
453
        /**************************************************************
454
         * Slow case (skewed, rotated, or imagemask with a halftone). *
455
         **************************************************************/
456
457
1.01M
        fixed yrun;
458
1.01M
        const fixed pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
459
1.01M
        const fixed pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
460
1.01M
        dev_proc_fill_parallelogram((*fill_pgram)) =
461
1.01M
            dev_proc(dev, fill_parallelogram);
462
463
52.1M
#define xl dda_current(next.x)
464
53.1M
#define ytf dda_current(next.y)
465
1.01M
        yrun = ytf;
466
1.01M
        if (masked) {
467
468
            /**********************
469
             * Slow case, masked. *
470
             **********************/
471
472
1.00M
            pdevc = penum->icolor1;
473
1.00M
            code = gx_color_load(pdevc, pgs, dev);
474
1.00M
            if (code < 0)
475
0
                return code;
476
1.00M
            if ((stop <= psrc) && (penum->adjust == 0) &&
477
0
                ((penum->posture == image_portrait) ||
478
0
                 (penum->posture == image_landscape)))
479
0
                goto last;
480
1.00M
            if (penum->posture == image_portrait) {
481
482
                /********************************
483
                 * Slow case, masked, portrait. *
484
                 ********************************/
485
486
                /*
487
                 * We don't have to worry about the Y DDA, and the fill
488
                 * regions are rectangles.  Calculate multiples of the DDA
489
                 * step.
490
                 */
491
0
                fixed ax =
492
0
                    (penum->matrix.xx < 0 ? -penum->adjust : penum->adjust);
493
0
                fixed ay =
494
0
                    (pdyy < 0 ? -penum->adjust : penum->adjust);
495
0
                fixed dyy = pdyy + (ay << 1);
496
497
0
                yrun -= ay;
498
0
                dda_translate(next.x, -ax);
499
0
                ax <<= 1;
500
0
                dxx2 = next.x.step;
501
0
                dda_step_add(dxx2, next.x.step);
502
0
                dxx3 = dxx2;
503
0
                dda_step_add(dxx3, next.x.step);
504
0
                dxx4 = dxx3;
505
0
                dda_step_add(dxx4, next.x.step);
506
0
                for (;;) {      /* Skip a run of zeros. */
507
0
                    while (!psrc[0])
508
0
                        if (psrc + 4 <= endp) {
509
                            /* We can use fast skipping */
510
0
                            if (!psrc[1]) {
511
0
                                if (!psrc[2]) {
512
0
                                    if (!psrc[3]) {
513
0
                                        psrc += 4;
514
0
                                        dda_state_next(next.x.state, dxx4);
515
0
                                        if (psrc >= endp)
516
0
                                            break;
517
0
                                        continue;
518
0
                                    }
519
0
                                    psrc += 3;
520
0
                                    dda_state_next(next.x.state, dxx3);
521
0
                                    break;
522
0
                                }
523
0
                                psrc += 2;
524
0
                                dda_state_next(next.x.state, dxx2);
525
0
                                break;
526
0
                            } else {
527
0
                                ++psrc;
528
0
                                dda_next(next.x);
529
0
                                break;
530
0
                            }
531
0
                        } else {
532
                            /* We're too close to the end - skip 1 at a time */
533
0
                            while (!psrc[0]) {
534
0
                                ++psrc;
535
0
                                dda_next(next.x);
536
0
                                if (psrc >= endp)
537
0
                                    break;
538
0
                            }
539
0
                            if (psrc >= endp)
540
0
                                break;
541
0
                        }
542
0
                    xrun = xl;
543
0
                    if (psrc >= stop)
544
0
                        break;
545
0
                    for (; psrc < endp && *psrc; ++psrc)
546
0
                        dda_next(next.x);
547
0
                    code = (*fill_pgram)(dev, xrun, yrun,
548
0
                                         xl - xrun + ax, fixed_0, fixed_0, dyy,
549
0
                                         pdevc, lop);
550
0
                    if (code < 0)
551
0
                        goto err;
552
0
                    rsrc = psrc;
553
0
                    if (psrc >= stop)
554
0
                        break;
555
0
                }
556
557
1.00M
            } else if (penum->posture == image_landscape) {
558
559
                /*********************************
560
                 * Slow case, masked, landscape. *
561
                 *********************************/
562
563
                /*
564
                 * We don't have to worry about the X DDA.  However, we do
565
                 * have to take adjustment into account.  We don't bother to
566
                 * optimize this as heavily as the portrait case.
567
                 */
568
0
                fixed ax =
569
0
                    (pdyx < 0 ? -penum->adjust : penum->adjust);
570
0
                fixed dyx = pdyx + (ax << 1);
571
0
                fixed ay =
572
0
                    (penum->matrix.xy < 0 ? -penum->adjust : penum->adjust);
573
574
0
                xrun -= ax;
575
0
                dda_translate(next.y, -ay);
576
0
                ay <<= 1;
577
0
                for (;;) {
578
0
                    for (; psrc < endp && !*psrc; ++psrc)
579
0
                        dda_next(next.y);
580
0
                    yrun = ytf;
581
0
                    if (psrc >= stop)
582
0
                        break;
583
0
                    for (; psrc < endp && *psrc; ++psrc)
584
0
                        dda_next(next.y);
585
0
                    code = (*fill_pgram)(dev, xrun, yrun, fixed_0,
586
0
                                         ytf - yrun + ay, dyx, fixed_0,
587
0
                                         pdevc, lop);
588
0
                    if (code < 0)
589
0
                        goto err;
590
0
                    rsrc = psrc;
591
0
                    if (psrc >= stop)
592
0
                        break;
593
0
                }
594
595
1.00M
            } else {
596
597
                /**************************************
598
                 * Slow case, masked, not orthogonal. *
599
                 **************************************/
600
                /* FIXME: RJW: This code doesn't do adjustment. Should it?
601
                 * In the grand scheme of things it almost certainly doesn't
602
                 * matter (as adjust should only be used when plotting chars,
603
                 * and we use freetype now), but we record the fact that this
604
                 * may be a defect here. */
605
                /* Previous code here used to skip blocks of matching pixels
606
                 * and plot them all in one go. We can't do that, as it can
607
                 * cause rounding errors and mismatches with the image pixels
608
                 * that will be plotted after us. */
609
1.00M
                stop = endp;
610
3.21M
                for (;;) {
611
                    /* skip forward until we find a 1 bit */
612
28.7M
                    for (; psrc < stop && !*psrc; ++psrc) {
613
25.4M
                        dda_next(next.x);
614
25.4M
                        dda_next(next.y);
615
25.4M
                    }
616
3.21M
                    if (psrc >= endp) /* Note, endp NOT stop! */
617
1.00M
                        break;
618
                    /* Then draw the pgram and step forward until we find a
619
                     * 0 bit. */
620
16.1M
                    do {
621
16.1M
                        yrun = ytf;
622
16.1M
                        xrun = xl;
623
16.1M
                        dda_next(next.x);
624
16.1M
                        dda_next(next.y);
625
16.1M
                        code = (*fill_pgram)(dev, xrun, yrun, xl - xrun,
626
16.1M
                                             ytf - yrun, pdyx, pdyy, pdevc, lop);
627
16.1M
                        if (code < 0)
628
0
                            goto err;
629
16.1M
                        psrc++;
630
16.1M
                        rsrc = psrc;
631
16.1M
                        if (psrc >= stop)
632
218k
                            break;
633
16.1M
                    } while (*psrc);
634
2.21M
                }
635
636
1.00M
            }
637
638
1.00M
        } else if (penum->posture == image_portrait) {
639
            /**************************************
640
             * Slow case, not masked, portrait. *
641
             **************************************/
642
2.92k
            dev_proc_fill_rectangle((*fill_proc)) =
643
2.92k
                dev_proc(dev, fill_rectangle);
644
2.92k
            int iy = fixed2int_pixround(yrun);
645
2.92k
            int ih = fixed2int_pixround(yrun + pdyy) - iy;
646
2.92k
            if (ih < 0)
647
358
                iy += ih, ih = -ih;
648
649
            /* In this case, we can fill runs quickly. */
650
            /****** DOESN'T DO ADJUSTMENT ******/
651
2.92k
            if (stop <= psrc)
652
331
                goto last;
653
706k
            for (;;) {
654
706k
                byte c = *psrc++;
655
706k
                if (c != run) {
656
104k
                    int ix = fixed2int_pixround(xrun);
657
104k
                    int iw = fixed2int_pixround(xl) - ix;
658
104k
                    if (iw < 0)
659
13.2k
                        ix += iw, iw = -iw;
660
104k
                    switch (run)
661
104k
                    {
662
52.3k
                    case 0:
663
52.3k
                        if (!color_is_pure(penum->icolor0))
664
44.6k
                            goto ht_port;
665
7.71k
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
666
7.71k
                                             penum->icolor0->colors.pure);
667
7.71k
                        break;
668
37.8k
                    case 0xff:
669
37.8k
                        if (!color_is_pure(penum->icolor1))
670
0
                            goto ht_port;
671
37.8k
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
672
37.8k
                                             penum->icolor1->colors.pure);
673
37.8k
                        break;
674
14.6k
                    default:
675
59.3k
                        ht_port:
676
59.3k
                        if (run != htrun) {
677
30.8k
                            htrun = run;
678
#if USE_SET_GRAY_FUNCTION
679
                            code = image_set_gray(run,masked,mask_base,mask_limit,&pdevc,
680
                                    &cc,pcs,pgs,dev,gs_color_select_source,penum);
681
                            if (code < 0)
682
                                goto err;
683
#else
684
30.8k
                            IMAGE_SET_GRAY(run);
685
30.8k
#endif
686
30.8k
                        }
687
59.3k
                        code = gx_fill_rectangle_device_rop(ix, iy, iw, ih,
688
104k
                                                            pdevc, dev, lop);
689
104k
                    }
690
104k
                    if (code < 0)
691
0
                        goto err;
692
104k
                    xrun = xl;
693
104k
                    rsrc = psrc;
694
104k
                    if (psrc > stop)
695
2.59k
                        break;
696
102k
                    run = c;
697
102k
                }
698
703k
                dda_next(next.x);
699
703k
                if (psrc >= endp)
700
0
                    break;
701
703k
            }
702
15.3k
        } else if (penum->posture == image_landscape) {
703
704
            /**************************************
705
             * Slow case, not masked, landscape. *
706
             **************************************/
707
2.55k
            dev_proc_fill_rectangle((*fill_proc)) =
708
2.55k
                dev_proc(dev, fill_rectangle);
709
2.55k
            int ix = fixed2int_pixround(xrun);
710
2.55k
            int iw = fixed2int_pixround(xrun + pdyx) - ix;
711
2.55k
            if (iw < 0)
712
866
                ix += iw, iw = -iw;
713
714
            /* In this case, we can fill runs quickly. */
715
            /****** DOESN'T DO ADJUSTMENT ******/
716
2.55k
            if (stop <= psrc)
717
245
                goto last;
718
510k
            for (;;) {
719
510k
                byte c = *psrc++;
720
510k
                if (c != run) {
721
89.3k
                    int iy = fixed2int_pixround(yrun);
722
89.3k
                    int ih = fixed2int_pixround(ytf) - iy;
723
89.3k
                    if (ih < 0)
724
31.7k
                        iy += ih, ih = -ih;
725
89.3k
                    switch (run)
726
89.3k
                    {
727
29.3k
                    case 0:
728
29.3k
                        if (!color_is_pure(penum->icolor0))
729
29.2k
                            goto ht_land;
730
74
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
731
74
                                             penum->icolor0->colors.pure);
732
74
                        break;
733
14.1k
                    case 0xff:
734
14.1k
                        if (!color_is_pure(penum->icolor1))
735
6
                            goto ht_land;
736
14.1k
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
737
14.1k
                                             penum->icolor1->colors.pure);
738
14.1k
                        break;
739
45.8k
                    default:
740
75.1k
                        ht_land:
741
75.1k
                        if (run != htrun) {
742
62.0k
                            htrun = run;
743
#if USE_SET_GRAY_FUNCTION
744
                            code = image_set_gray(run,masked,mask_base,mask_limit,&pdevc,
745
                                    &cc,pcs,pgs,dev,gs_color_select_source,penum);
746
                            if (code < 0)
747
                                goto err;
748
#else
749
62.0k
                            IMAGE_SET_GRAY(run);
750
62.0k
#endif
751
62.0k
                        }
752
75.1k
                        code = gx_fill_rectangle_device_rop(ix, iy, iw, ih,
753
89.3k
                                                            pdevc, dev, lop);
754
89.3k
                    }
755
89.3k
                    if (code < 0)
756
0
                        goto err;
757
89.3k
                    yrun = ytf;
758
89.3k
                    rsrc = psrc;
759
89.3k
                    if (psrc > stop)
760
2.31k
                        break;
761
87.0k
                    run = c;
762
87.0k
                }
763
507k
                dda_next(next.y);
764
507k
                if (psrc >= endp)
765
0
                    break;
766
507k
            }
767
12.8k
        } else {
768
769
            /******************************************
770
             * Slow case, not masked, not orthogonal. *
771
             ******************************************/
772
773
            /*
774
             * Since we have to check for the end after every pixel
775
             * anyway, we may as well avoid the last-run code.
776
             */
777
12.8k
            stop = endp;
778
9.87M
            for (;;) {
779
                /* We can't skip large constant regions quickly, */
780
                /* because this leads to rounding errors. */
781
                /* Just fill the region between xrun and xl. */
782
9.87M
                if (run != htrun) {
783
208k
                    htrun = run;
784
#if USE_SET_GRAY_FUNCTION
785
                    code = image_set_gray(run,masked,mask_base,mask_limit,&pdevc,
786
                        &cc,pcs,pgs,dev,gs_color_select_source,penum);
787
                    if (code < 0)
788
                        goto err;
789
#else
790
208k
                    IMAGE_SET_GRAY(run);
791
208k
#endif
792
208k
                }
793
9.87M
                code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
794
9.87M
                                      ytf - yrun, pdyx, pdyy, pdevc, lop);
795
9.87M
                if (code < 0)
796
0
                    goto err;
797
9.87M
                yrun = ytf;
798
9.87M
                xrun = xl;
799
9.87M
                rsrc = psrc;
800
9.87M
                if (psrc >= stop)
801
12.8k
                    break;
802
9.86M
                run = *psrc++;
803
9.86M
                dda_next(next.x);
804
9.86M
                dda_next(next.y);       /* harmless if no skew */
805
9.86M
            }
806
807
12.8k
        }
808
        /* Fill the last run. */
809
1.01M
      last:if (stop < endp && (*stop || !masked)) {
810
5.47k
            if (!masked) {
811
#if USE_SET_GRAY_FUNCTION
812
                    code = image_set_gray(*stop, masked,mask_base,mask_limit,&pdevc,
813
                        &cc,pcs,pgs,dev,gs_color_select_source,penum);
814
                    if (code < 0)
815
                        goto err;
816
#else
817
5.47k
                    IMAGE_SET_GRAY(*stop);
818
5.47k
#endif
819
5.47k
            }
820
5.47k
            dda_advance(next.x, endp - stop);
821
5.47k
            dda_advance(next.y, endp - stop);
822
5.47k
            code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
823
5.47k
                                  ytf - yrun, pdyx, pdyy, pdevc, lop);
824
5.47k
        }
825
1.01M
#undef xl
826
1.01M
#undef ytf
827
828
5.88M
    } else {
829
830
        /**********************************************************
831
         * Fast case: no skew, and not imagemask with a halftone. *
832
         **********************************************************/
833
834
5.88M
        const fixed adjust = penum->adjust;
835
5.88M
        const fixed dxx = penum->dxx;
836
5.88M
        fixed xa = (dxx >= 0 ? adjust : -adjust);
837
5.88M
        const int yt = penum->yci, iht = penum->hci;
838
839
5.88M
        dev_proc_fill_rectangle((*fill_proc)) =
840
5.88M
            dev_proc(dev, fill_rectangle);
841
5.88M
        int xmin = fixed2int_pixround(penum->clip_outer.p.x);
842
5.88M
        int xmax = fixed2int_pixround(penum->clip_outer.q.x);
843
117M
#define xl dda_current(next.x)
844
845
5.88M
        if_debug2m('b', penum->memory, "[b]image y=%d  dda.y.Q=%lg\n",
846
5.88M
                   penum->y + penum->rect.y, penum->dda.row.y.state.Q / 256.);
847
        /* Fold the adjustment into xrun and xl, */
848
        /* including the +0.5-epsilon for rounding. */
849
5.88M
        xrun = xrun - xa + (fixed_half - fixed_epsilon);
850
5.88M
        dda_translate(next.x, xa + (fixed_half - fixed_epsilon));
851
5.88M
        xa <<= 1;
852
        /* Calculate multiples of the DDA step. */
853
5.88M
        dxx2 = next.x.step;
854
5.88M
        dda_step_add(dxx2, next.x.step);
855
5.88M
        dxx3 = dxx2;
856
5.88M
        dda_step_add(dxx3, next.x.step);
857
5.88M
        dxx4 = dxx3;
858
5.88M
        dda_step_add(dxx4, next.x.step);
859
5.88M
        if (stop > psrc)
860
117M
            for (;;) {          /* Skip large constant regions quickly, */
861
                /* but don't slow down transitions too much. */
862
268M
              skf:if (psrc[0] == run) {
863
206M
                    if (psrc[1] == run) {
864
179M
                        if (psrc[2] == run) {
865
161M
                            if (psrc[3] == run) {
866
150M
                                psrc += 4;
867
150M
                                dda_state_next(next.x.state, dxx4);
868
150M
                                if (psrc >= endp)
869
0
                                    break;
870
150M
                                goto skf;
871
150M
                            } else {
872
10.9M
                                psrc += 4;
873
10.9M
                                dda_state_next(next.x.state, dxx3);
874
10.9M
                            }
875
161M
                        } else {
876
18.3M
                            psrc += 3;
877
18.3M
                            dda_state_next(next.x.state, dxx2);
878
18.3M
                        }
879
179M
                    } else {
880
27.0M
                        psrc += 2;
881
27.0M
                        dda_next(next.x);
882
27.0M
                    }
883
206M
                } else
884
61.4M
                    psrc++;
885
117M
                {               /* Now fill the region between xrun and xl. */
886
117M
                    int xi = fixed2int_var(xrun);
887
117M
                    int wi = fixed2int_var(xl) - xi;
888
117M
                    int xei;
889
890
117M
                    if (wi <= 0) {
891
3.64M
                        if (wi == 0)
892
3.58M
                            goto mt;
893
61.0k
                        xi += wi, wi = -wi;
894
61.0k
                    }
895
114M
                    if ((xei = xi + wi) > xmax || xi < xmin) {  /* Do X clipping */
896
81.2k
                        if (xi < xmin)
897
17.5k
                            wi -= xmin - xi, xi = xmin;
898
81.2k
                        if (xei > xmax)
899
63.7k
                            wi -= xei - xmax;
900
81.2k
                        if (wi <= 0)
901
60.4k
                            goto mt;
902
81.2k
                    }
903
114M
                    switch (run) {
904
28.3M
                        case 0:
905
28.3M
                            if (masked)
906
5.02M
                                goto mt;
907
23.3M
                            if (!color_is_pure(penum->icolor0))
908
398k
                                goto ht;
909
22.9M
                            code = (*fill_proc) (dev, xi, yt, wi, iht,
910
22.9M
                                                 penum->icolor0->colors.pure);
911
22.9M
                            break;
912
26.8M
                        case 255:       /* just for speed */
913
26.8M
                            if (!color_is_pure(penum->icolor1))
914
362k
                                goto ht;
915
26.4M
                            code = (*fill_proc) (dev, xi, yt, wi, iht,
916
26.4M
                                                 penum->icolor1->colors.pure);
917
26.4M
                            break;
918
58.9M
                        default:
919
59.7M
                          ht:   /* Use halftone if needed */
920
59.7M
                            if (run != htrun) {
921
#if USE_SET_GRAY_FUNCTION
922
                                code = image_set_gray(run, masked,mask_base,mask_limit,&pdevc,
923
                                    &cc,pcs,pgs,dev,gs_color_select_source,penum);
924
                                if (code < 0)
925
                                    goto err;
926
#else
927
57.7M
                                IMAGE_SET_GRAY(run);
928
57.7M
#endif
929
57.7M
                                htrun = run;
930
57.7M
                            }
931
59.7M
                            code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
932
114M
                                                                 pdevc, dev, lop);
933
114M
                    }
934
109M
                    if (code < 0)
935
0
                        goto err;
936
117M
                  mt:xrun = xl - xa;    /* original xa << 1 */
937
117M
                    rsrc = psrc - 1;
938
117M
                    if (psrc > stop) {
939
4.55M
                        --psrc;
940
4.55M
                        break;
941
4.55M
                    }
942
113M
                    run = psrc[-1];
943
113M
                }
944
113M
                dda_next(next.x);
945
113M
            }
946
        /* Fill the last run. */
947
5.88M
        if (*stop != 0 || !masked) {
948
3.32M
            int xi = fixed2int_var(xrun);
949
3.32M
            int wi, xei;
950
951
3.32M
            dda_advance(next.x, endp - stop);
952
3.32M
            wi = fixed2int_var(xl) - xi;
953
3.32M
            if (wi <= 0) {
954
127k
                if (wi == 0)
955
114k
                    goto lmt;
956
12.5k
                xi += wi, wi = -wi;
957
12.5k
            }
958
3.20M
            if ((xei = xi + wi) > xmax || xi < xmin) {  /* Do X clipping */
959
101k
                if (xi < xmin)
960
2.27k
                    wi -= xmin - xi, xi = xmin;
961
101k
                if (xei > xmax)
962
99.3k
                    wi -= xei - xmax;
963
101k
                if (wi <= 0)
964
12.6k
                    goto lmt;
965
101k
            }
966
#if USE_SET_GRAY_FUNCTION
967
            code = image_set_gray(*stop, masked,mask_base,mask_limit,&pdevc,
968
                &cc,pcs,pgs,dev,gs_color_select_source,penum);
969
            if (code < 0)
970
                goto err;
971
#else
972
3.20M
            IMAGE_SET_GRAY(*stop);
973
3.19M
#endif
974
3.19M
            code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
975
3.19M
                                                pdevc, dev, lop);
976
3.32M
          lmt:;
977
3.32M
        }
978
979
5.88M
    }
980
6.90M
#undef xl
981
6.90M
    if (code >= 0) {
982
6.90M
        code = 1;
983
6.90M
        goto done;
984
6.90M
    }
985
    /* Save position if error, in case we resume. */
986
0
err:
987
0
    penum->used.x = rsrc - psrc_initial;
988
0
    penum->used.y = 0;
989
6.90M
done:
990
    /* Since dev_color.binary.b_tile is just a pointer to an entry in the halftone tile "cache"
991
       we cannot leave it set in case the interpeter changes the halftone
992
       (whilst it shouldn't do it, it is possible for Postscript image data source
993
       procedure to execute setcreen or similar). This also doesn't really adversely
994
       affect performance, as we'll call gx_color_load_select() for all the samples
995
       from the next buffer, which will NULL the b_tile pointer anyway (it only gets
996
       set when we actually try to draw with it.
997
    */
998
1.77G
    for (i = 0; i < 256; i++) {
999
1.76G
        penum->clues[i].dev_color.colors.binary.b_tile = NULL;
1000
1.76G
    }
1001
6.90M
    return code;
1002
0
}
1003
1004
#ifdef WITH_CAL
1005
static int
1006
image_render_mono_ht_cal_skip_line(gx_image_enum *penum,
1007
                                   gx_device     *dev)
1008
{
1009
    return !cal_halftone_next_line_required(penum->cal_ht);
1010
}
1011
1012
static int
1013
image_render_mono_ht_cal(gx_image_enum * penum, const byte * buffer, int data_x,
1014
    uint w, int h, gx_device * dev)
1015
{
1016
    const byte *input = buffer + data_x;
1017
1018
    if (buffer == NULL)
1019
        return 0;
1020
1021
    return cal_halftone_process_planar(penum->cal_ht, penum->memory->non_gc_memory,
1022
                                       (const byte * const *)&input, halftone_callback, dev);
1023
}
1024
#else
1025
/*
1026
 An image render case where the source color is monochrome or indexed and
1027
 the output is to be halftoned.  If the source color requires decoding,
1028
 an index look-up or ICC color managment, these operations have already been
1029
 performed on the index values and we are ready now to halftone */
1030
static int
1031
image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x,
1032
                  uint w, int h, gx_device * dev)
1033
1.53M
{
1034
1.53M
    gx_image_enum *penum = penum_orig; /* const within proc */
1035
1.53M
    image_posture posture = penum->posture;
1036
1.53M
    int vdi;  /* amounts to replicate */
1037
1.53M
    fixed xrun;
1038
1.53M
    byte *thresh_align;
1039
1.53M
    int spp_out = penum->dev->color_info.num_components;
1040
1.53M
    byte *devc_contone[GX_DEVICE_COLOR_MAX_COMPONENTS];
1041
1.53M
    byte *devc_contone_gray;
1042
1.53M
    const byte *psrc = buffer + data_x;
1043
1.53M
    int dest_width, dest_height, data_length;
1044
1.53M
    byte *color_cache;
1045
1.53M
    int position, k, j;
1046
1.53M
    int offset_bits = penum->ht_offset_bits;
1047
1.53M
    int contone_stride = 0;  /* Not used in landscape case */
1048
1.53M
    fixed offset;
1049
1.53M
    int src_size;
1050
1.53M
    bool flush_buff = false;
1051
1.53M
    int offset_contone[GX_DEVICE_COLOR_MAX_COMPONENTS];    /* to ensure 128 bit boundary */
1052
1.53M
    int offset_threshold;  /* to ensure 128 bit boundary */
1053
1.53M
    gx_dda_fixed dda_ht;
1054
1.53M
    int xn, xr;   /* destination position (pixel, not contone buffer offset) */
1055
1.53M
    int code = 0;
1056
1.53M
    byte *dev_value;
1057
1058
    /* Silence warnings */
1059
1.53M
    if (spp_out <= 0)
1060
0
        return 0;
1061
1062
1.53M
    if (h == 0 || penum->line_size == 0) {      /* line_size == 0, nothing to do */
1063
209k
        if (penum->ht_landscape.count == 0 || posture == image_portrait) {
1064
209k
            return 0;
1065
209k
        } else {
1066
            /* Need to flush the buffer */
1067
4
            offset_bits = penum->ht_landscape.count;
1068
4
            penum->ht_offset_bits = offset_bits;
1069
4
            penum->ht_landscape.offset_set = true;
1070
4
            flush_buff = true;
1071
4
        }
1072
209k
    }
1073
1.32M
    src_size = penum->rect.w;
1074
1075
    /* Set up the dda.  We could move this out but the cost is pretty small */
1076
1.32M
    dda_ht = (posture == image_portrait) ? penum->dda.pixel0.x : penum->dda.pixel0.y;
1077
1.32M
    if (penum->dxx > 0)
1078
1.32M
        dda_translate(dda_ht, -fixed_epsilon);      /* to match rounding in non-fast code */
1079
1080
1.32M
    switch (posture) {
1081
1.32M
        case image_portrait:
1082
            /* Figure out our offset in the contone and threshold data
1083
               buffers so that we ensure that we are on the 128bit
1084
               memory boundaries when we get offset_bits into the data. */
1085
            /* Can't do this earlier, as GC might move the buffers. */
1086
1.32M
            xrun = dda_current(dda_ht);
1087
1.32M
            dest_width = gxht_dda_length(&dda_ht, src_size);
1088
1.32M
            if (penum->x_extent.x < 0)
1089
21
                xrun += penum->x_extent.x;
1090
1.32M
            vdi = penum->hci;
1091
1.32M
            contone_stride = penum->line_size;
1092
1.32M
            offset_threshold = (- (((int)(intptr_t)(penum->thresh_buffer)) +
1093
1.32M
                                   penum->ht_offset_bits)) & 15;
1094
2.70M
            for (k = 0; k < spp_out; k ++) {
1095
1.38M
                offset_contone[k]   = (- (((int)(intptr_t)(penum->line)) +
1096
1.38M
                                           contone_stride * k +
1097
1.38M
                                           penum->ht_offset_bits)) & 15;
1098
1.38M
            }
1099
1.32M
            data_length = dest_width;
1100
1.32M
            dest_height = fixed2int_var_rounded(any_abs(penum->y_extent.y));
1101
#ifdef DEBUG
1102
            /* Help in spotting problems */
1103
            memset(penum->ht_buffer, 0x00, penum->ht_stride * vdi * spp_out);
1104
#endif
1105
1.32M
            break;
1106
9
        case image_landscape:
1107
9
        default:
1108
            /* Figure out our offset in the contone and threshold data buffers
1109
               so that we ensure that we are on the 128bit memory boundaries.
1110
               Can't do this earlier as GC may move the buffers.
1111
             */
1112
9
            vdi = penum->wci;
1113
9
            contone_stride = penum->line_size;
1114
9
            dest_width = fixed2int_var_rounded(any_abs(penum->y_extent.x));
1115
            /* match height in gxht_thresh.c dev_width calculation */
1116
9
            xrun = dda_current(dda_ht);            /* really yrun, but just used here for landscape */
1117
9
            dest_height = gxht_dda_length(&dda_ht, src_size);
1118
9
            data_length = dest_height;
1119
9
            offset_threshold = (-(int)(intptr_t)(penum->thresh_buffer)) & 15;
1120
18
            for (k = 0; k < spp_out; k ++) {
1121
9
                offset_contone[k] = (- ((int)(intptr_t)(penum->line) +
1122
9
                                        contone_stride * k)) & 15;
1123
9
            }
1124
            /* In the landscaped case, we want to accumulate multiple columns
1125
               of data before sending to the device.  We want to have a full
1126
               byte of HT data in one write.  This may not be possible at the
1127
               left or right and for those and for those we have so send partial
1128
               chunks */
1129
            /* Initialize our xstart and compute our partial bit chunk so
1130
               that we get in sync with the 1 bit mem device 16 bit positions
1131
               for the rest of the chunks */
1132
9
            if (penum->ht_landscape.count == 0) {
1133
                /* In the landscape case, the size depends upon
1134
                   if we are moving left to right or right to left with
1135
                   the image data.  This offset is to ensure that we  get
1136
                   aligned in our chunks along 16 bit boundaries */
1137
4
                penum->ht_landscape.offset_set = true;
1138
4
                if (penum->ht_landscape.index < 0) {
1139
0
                    penum->ht_landscape.xstart = penum->xci + vdi - 1;
1140
0
                    offset_bits = (penum->ht_landscape.xstart % 16) + 1;
1141
                    /* xci can be negative, so allow for that */
1142
0
                    if (offset_bits <= 0) offset_bits += 16;
1143
4
                } else {
1144
4
                    penum->ht_landscape.xstart = penum->xci;
1145
                    /* xci can be negative, see Bug 692569. */
1146
4
                    offset_bits = 16 - penum->xci % 16;
1147
4
                    if (offset_bits >= 16) offset_bits -= 16;
1148
4
                }
1149
4
                if (offset_bits == 0 || offset_bits == 16) {
1150
1
                    penum->ht_landscape.offset_set = false;
1151
1
                    penum->ht_offset_bits = 0;
1152
3
                } else {
1153
3
                    penum->ht_offset_bits = offset_bits;
1154
3
                }
1155
4
            }
1156
9
            break;
1157
1.32M
    }
1158
1.32M
    if (flush_buff)
1159
4
        goto flush;  /* All done */
1160
1161
    /* Get the pointers to our buffers */
1162
2.70M
    for (k = 0; k < spp_out; k++) {
1163
1.38M
        if (posture == image_portrait) {
1164
1.38M
            devc_contone[k] = penum->line + contone_stride * k +
1165
1.38M
                              offset_contone[k];
1166
1.38M
        } else {
1167
5
            devc_contone[k] = penum->line + offset_contone[k] +
1168
5
                              LAND_BITS * k * contone_stride;
1169
5
        }
1170
1.38M
    }
1171
1.32M
    xr = fixed2int_var_rounded(dda_current(dda_ht));  /* indexes in the destination (contone) */
1172
1173
1.32M
    devc_contone_gray = devc_contone[0];
1174
1.32M
    if (penum->color_cache == NULL) {
1175
        /* No look-up in the cache to fill the source buffer. Still need to
1176
           have the data at device resolution.  Do these in quick small
1177
           loops.  This likely could be a vectorized function.  Note that
1178
           since the color_cache is NULL we must be in a case where we
1179
           are going to a monochrome device. */
1180
1.13M
        switch (posture) {
1181
1.13M
            case image_portrait:
1182
1.13M
                if (penum->dst_width > 0) {
1183
1.13M
                    if (src_size == dest_width) {
1184
1.11M
                        memcpy(devc_contone_gray, psrc, data_length);
1185
1.11M
                    } else if (src_size * 2 == dest_width) {
1186
0
                        const byte *psrc_temp = psrc;
1187
0
                        for (k = 0; k < data_length; k+=2, devc_contone_gray+=2,
1188
0
                             psrc_temp++) {
1189
0
                            *devc_contone_gray = *(devc_contone_gray+1) = *psrc_temp;
1190
0
                        }
1191
11.4k
                    } else {
1192
                        /* Mono case, forward */
1193
7.36M
                        for (k=0; k<src_size; k++) {
1194
7.35M
                            byte c = *psrc++;
1195
7.35M
                            dda_next(dda_ht);
1196
7.35M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1197
14.2M
                            while (xr < xn) {
1198
6.89M
                                *devc_contone_gray++ = c;
1199
6.89M
                                xr++;
1200
6.89M
                            }           /* at loop exit xn will be >= xr */
1201
7.35M
                        }
1202
11.4k
                    }
1203
1.13M
                } else {
1204
                    /* Mono case, backwards */
1205
0
                    devc_contone_gray += (data_length - 1);
1206
0
                    for (k=0; k<src_size; k++) {
1207
0
                        byte c = *psrc++;
1208
0
                        dda_next(dda_ht);
1209
0
                        xn = fixed2int_var_rounded(dda_current(dda_ht));
1210
0
                        while (xr > xn) {
1211
0
                            *devc_contone_gray-- = c;
1212
0
                            xr--;
1213
0
                        }           /* at loop exit xn will be >= xr */
1214
0
                    }
1215
0
                }
1216
1.13M
                break;
1217
1
            case image_landscape:
1218
                /* We store the data at this point into a column. Depending
1219
                   upon our landscape direction we may be going left to right
1220
                   or right to left. */
1221
1
                if (penum->ht_landscape.flipy) {
1222
0
                    position = penum->ht_landscape.curr_pos +
1223
0
                                LAND_BITS * (data_length - 1);
1224
0
                    for (k=0; k<src_size; k++) {
1225
0
                        byte c = *psrc++;
1226
0
                        dda_next(dda_ht);
1227
0
                        xn = fixed2int_var_rounded(dda_current(dda_ht));
1228
0
                        while (xr > xn) {
1229
0
                            devc_contone_gray[position] = c;
1230
0
                            position -= LAND_BITS;
1231
0
                            xr--;
1232
0
                        }           /* at loop exit xn will be <= xr */
1233
0
                    }
1234
1
                } else {
1235
1
                    position = penum->ht_landscape.curr_pos;
1236
                    /* Code up special cases for when we have no scaling
1237
                       and 2x scaling which we will run into in 300 and
1238
                       600dpi devices and content */
1239
1
                    if (src_size == dest_height) {
1240
0
                        for (k = 0; k < data_length; k++) {
1241
0
                            devc_contone_gray[position] = psrc[k];
1242
0
                            position += LAND_BITS;
1243
0
                        }
1244
1
                    } else if (src_size*2 == dest_height) {
1245
0
                        for (k = 0; k < data_length; k+=2) {
1246
0
                            offset = fixed2int_rounded(fixed_half * k);
1247
0
                            devc_contone_gray[position] =
1248
0
                                devc_contone_gray[position + LAND_BITS] = psrc[offset];
1249
0
                            position += LAND_BITS*2;
1250
0
                        }
1251
1
                    } else {
1252
                        /* use dda */
1253
257
                        for (k=0; k<src_size; k++) {
1254
256
                            byte c = *psrc++;
1255
256
                            dda_next(dda_ht);
1256
256
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1257
259
                            while (xr < xn) {
1258
3
                                devc_contone_gray[position] = c;
1259
3
                                position += LAND_BITS;
1260
3
                                xr++;
1261
3
                            }           /* at loop exit xn will be >= xr */
1262
256
                        }
1263
1
                    }
1264
1
                }
1265
                /* Store the width information and update our counts */
1266
1
                penum->ht_landscape.count += vdi;
1267
1
                penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
1268
1
                penum->ht_landscape.curr_pos += penum->ht_landscape.index;
1269
1
                penum->ht_landscape.num_contones++;
1270
1
                break;
1271
0
            default:
1272
                /* error not allowed */
1273
0
                break;
1274
1.13M
            }
1275
1.13M
    } else {
1276
        /* look-up in the cache to fill the source buffer.  If our spp_out
1277
           is 4 then we need to write out the pixels in the color_cache into
1278
           the planes */
1279
189k
        color_cache = penum->color_cache->device_contone;
1280
189k
        switch (posture) {
1281
189k
            case image_portrait:
1282
189k
                if (penum->dst_width > 0) {
1283
                    /* loop filling contone values selected from the source */
1284
189k
                    if (spp_out == 1) {
1285
                        /* Mono case, forward */
1286
36.7M
                        for (k=0; k<src_size; k++) {
1287
36.5M
                            byte c = color_cache[*psrc++];
1288
36.5M
                            dda_next(dda_ht);
1289
36.5M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1290
105M
                            while (xr < xn) {
1291
69.1M
                                *devc_contone_gray++ = c;
1292
69.1M
                                xr++;
1293
69.1M
                            }           /* at loop exit xn will be >= xr */
1294
36.5M
                        }
1295
167k
                    } else {
1296
                        /* CMYK case, forward */
1297
7.29M
                        for (k=0; k<src_size; k++) {
1298
7.27M
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1299
7.27M
                            dda_next(dda_ht);
1300
7.27M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1301
24.4M
                            while (xr < xn) {
1302
85.7M
                                for (j = 0; j < spp_out; j++) {
1303
68.5M
                                    *(devc_contone[j])++ = dev_value[j];
1304
68.5M
                                }
1305
17.1M
                                xr++;
1306
17.1M
                            }           /* at loop exit xn will be >= xr */
1307
7.27M
                        }
1308
22.4k
                    }
1309
189k
                } else {
1310
21
                    if (spp_out == 1) {
1311
                        /* Mono case, backwards */
1312
21
                        devc_contone_gray += data_length - 1;   /* move to end */
1313
17.7k
                        for (k=0; k<src_size; k++) {
1314
17.7k
                            byte c = color_cache[*psrc++];
1315
17.7k
                            dda_next(dda_ht);
1316
17.7k
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1317
29.1k
                            while (xr > xn) {
1318
11.3k
                                *devc_contone_gray-- = c;
1319
11.3k
                                xr--;
1320
11.3k
                            }           /* at loop exit xn will be <= xr */
1321
17.7k
                        }
1322
21
                    } else {
1323
                        /* CMYK case, backwards */
1324
                        /* Move to the other end and we will decrement */
1325
0
                        for (j = 0; j < spp_out; j++) {
1326
0
                            devc_contone[j] = devc_contone[j] + data_length - 1;
1327
0
                        }
1328
0
                        for (k=0; k<src_size; k++) {
1329
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1330
0
                            dda_next(dda_ht);
1331
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1332
0
                            while (xr > xn) {
1333
0
                                for (j = 0; j < spp_out; j++) {
1334
0
                                    *(devc_contone[j])-- = dev_value[j];
1335
0
                                }
1336
0
                                xr--;
1337
0
                            }           /* at loop exit xn will be <= xr */
1338
0
                        }
1339
0
                    }
1340
21
                }
1341
189k
                break;
1342
4
            case image_landscape:
1343
                /* We store the data at this point into a column. Depending
1344
                   upon our landscape direction we may be going left to right
1345
                   or right to left. */
1346
4
                if (penum->ht_landscape.flipy) {
1347
4
                    position = penum->ht_landscape.curr_pos +
1348
4
                                LAND_BITS * (data_length - 1);
1349
                    /* use dda */
1350
4
                    if (spp_out == 1) {
1351
                        /* Mono case */
1352
                        /* loop filling contone values selected from the source */
1353
25.9k
                        for (k=0; k<src_size; k++) {
1354
25.9k
                            byte c = color_cache[*psrc++];
1355
25.9k
                            dda_next(dda_ht);
1356
25.9k
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1357
29.0k
                            while (xr > xn) {
1358
3.11k
                                devc_contone_gray[position] = c;
1359
3.11k
                                position -= LAND_BITS;
1360
3.11k
                                xr--;
1361
3.11k
                            }           /* at loop exit xn will be <= xr */
1362
25.9k
                        }
1363
4
                    } else {
1364
                        /* CMYK case */
1365
0
                        for (k=0; k<src_size; k++) {
1366
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1367
0
                            dda_next(dda_ht);
1368
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1369
0
                            while (xr > xn) {
1370
0
                                for (j = 0; j < spp_out; j++) {
1371
0
                                    *(devc_contone[j] + position) = dev_value[j];
1372
0
                                }
1373
0
                                position -= LAND_BITS;
1374
0
                                xr--;
1375
0
                            }           /* at loop exit xn will be <= xr */
1376
0
                        }
1377
0
                    }
1378
4
                } else {  /* Not flipped in Y */
1379
0
                    position = penum->ht_landscape.curr_pos;
1380
                    /* use dda */
1381
0
                    if (spp_out == 1) {
1382
                        /* Mono case */
1383
                        /* loop filling contone values selected from the source */
1384
0
                        for (k=0; k<src_size; k++) {
1385
0
                            byte c = color_cache[*psrc++];
1386
0
                            dda_next(dda_ht);
1387
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1388
0
                            while (xr < xn) {
1389
0
                                devc_contone_gray[position] = c;
1390
0
                                position += LAND_BITS;
1391
0
                                xr++;
1392
0
                            }           /* at loop exit xn will be >= xr */
1393
0
                        }
1394
0
                    } else {
1395
                        /* CMYK case */
1396
0
                        for (k=0; k<src_size; k++) {
1397
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1398
0
                            dda_next(dda_ht);
1399
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1400
0
                            while (xr < xn) {
1401
0
                                for (j = 0; j < spp_out; j++) {
1402
0
                                    *(devc_contone[j] + position) = dev_value[j];
1403
0
                                }
1404
0
                                position += LAND_BITS;
1405
0
                                xr++;
1406
0
                            }           /* at loop exit xn will be >= xr */
1407
0
                        }
1408
0
                    }
1409
0
                }
1410
                /* Store the width information and update our counts */
1411
4
                penum->ht_landscape.count += vdi;
1412
4
                penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
1413
4
                penum->ht_landscape.curr_pos += penum->ht_landscape.index;
1414
4
                penum->ht_landscape.num_contones++;
1415
4
                break;
1416
0
            default:
1417
                /* error not allowed */
1418
0
                break;
1419
189k
        }
1420
189k
    }
1421
    /* Apply threshold array to image data */
1422
1.32M
flush:
1423
1.32M
    thresh_align = penum->thresh_buffer + offset_threshold;
1424
1.32M
    code = gxht_thresh_planes(penum, xrun, dest_width, dest_height,
1425
1.32M
                              thresh_align, dev, offset_contone,
1426
1.32M
                              contone_stride);
1427
1.32M
    return code;
1428
1.32M
}
1429
#endif