Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gximono.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 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.99M
{
162
1.99M
#if USE_FAST_HT_CODE
163
1.99M
    bool use_fast_code = true;
164
#else
165
    bool use_fast_code = false;
166
#endif
167
1.99M
    int code = 0;
168
    /* Set up the link now */
169
1.99M
    const gs_color_space *pcs;
170
1.99M
    gsicc_rendering_param_t rendering_params;
171
1.99M
    cmm_dev_profile_t *dev_profile;
172
1.99M
    bool dev_color_ok = false;
173
1.99M
    bool is_planar_dev = penum->dev->num_planar_planes;
174
175
1.99M
    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
705k
        dev_color_ok = ((penum->dev->color_info.num_components == 1 &&
187
705k
                         penum->dev->color_info.depth == 1) ||
188
#if 0
189
                         /* Don't allow CMYK Planar devices just yet */
190
                         0);
191
#else
192
705k
                        (penum->dev->color_info.num_components == 4 &&
193
594k
                         penum->dev->color_info.depth == 4 && is_planar_dev));
194
705k
#endif
195
196
705k
        if (use_fast_code && penum->pcs != NULL && dev_color_ok &&
197
705k
            penum->bps == 8 && (penum->posture == image_portrait
198
85.4k
            || penum->posture == image_landscape) &&
199
705k
            penum->image_parent_type == gs_image_type1 &&
200
705k
            gx_transfer_is_monotonic(penum->pgs, 0)) {
201
85.4k
            penum->icc_setup.need_decode = false;
202
            /* Check if we need to do any decoding.  */
203
85.4k
            if ( penum->map[0].decoding != sd_none ) {
204
1.77k
                if (!(penum->map[0].decoding == sd_compute
205
1.77k
                     && penum->map[0].decode_factor == 1.0 &&
206
1.77k
                        penum->map[0].decode_lookup[0] == 0.0)) {
207
13
                    penum->icc_setup.need_decode = true;
208
13
                }
209
1.77k
            }
210
85.4k
            code = dev_proc(penum->dev, get_profile)(penum->dev, &dev_profile);
211
85.4k
            if (code < 0)
212
0
                return code;
213
214
            /* Define the rendering intents */
215
85.4k
            rendering_params.black_point_comp = penum->pgs->blackptcomp;
216
85.4k
            rendering_params.graphics_type_tag = GS_IMAGE_TAG;
217
85.4k
            rendering_params.override_icc = false;
218
85.4k
            rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
219
85.4k
            rendering_params.rendering_intent = penum->pgs->renderingintent;
220
85.4k
            rendering_params.cmm = gsCMM_DEFAULT;
221
85.4k
            if (gs_color_space_get_index(penum->pcs) ==
222
85.4k
                gs_color_space_index_Indexed) {
223
1.77k
                pcs = penum->pcs->base_space;
224
83.6k
            } else {
225
83.6k
                pcs = penum->pcs;
226
83.6k
            }
227
85.4k
            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
85.4k
            if (pcs->cmm_icc_profile_data == NULL)
235
26
                goto not_fast_halftoning;
236
237
85.3k
            penum->icc_setup.is_lab = pcs->cmm_icc_profile_data->islab;
238
85.3k
            penum->icc_setup.must_halftone = gx_device_must_halftone(penum->dev);
239
            /* The effective transfer is built into the threshold array */
240
85.3k
            penum->icc_setup.has_transfer = false;
241
85.3k
            if (penum->icc_setup.is_lab)
242
34
                penum->icc_setup.need_decode = false;
243
85.3k
            if (penum->icc_link == NULL) {
244
85.3k
                penum->icc_link = gsicc_get_link(penum->pgs, penum->dev, pcs, NULL,
245
85.3k
                    &rendering_params, penum->memory);
246
85.3k
            }
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
85.3k
            penum->use_cie_range = false;
252
85.3k
            if (gs_color_space_is_PSCIE(penum->pcs) &&
253
85.3k
                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
85.3k
            code = image_init_color_cache(penum, penum->bps, penum->spp);
268
85.3k
            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
85.3k
                code = gxht_thresh_image_init(penum);
279
85.3k
                if (code >= 0) {
280
85.3k
                    *render_fn = &image_render_mono_ht;
281
85.3k
                    return code;
282
85.3k
                }
283
85.3k
#endif
284
85.3k
            }
285
85.3k
        }
286
620k
not_fast_halftoning:
287
        /*
288
         * Use the slow loop for imagemask with a halftone or a non-default
289
         * logical operation.
290
         */
291
620k
        penum->slow_loop =
292
620k
            (penum->masked && !color_is_pure(penum->icolor0)) ||
293
620k
            penum->use_rop;
294
        /* We can bypass X clipping for portrait mono-component images. */
295
620k
        if (!(penum->slow_loop || penum->posture != image_portrait))
296
504k
            penum->clip_image &= ~(image_clip_xmin | image_clip_xmax);
297
620k
        if_debug0m('b', penum->memory, "[b]render=mono\n");
298
        /* Precompute values needed for rasterizing. */
299
620k
        penum->dxx =
300
620k
            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
620k
        if (penum->use_mask_color) {
307
11
            gx_image_scale_mask_colors(penum, 0);
308
11
            if (penum->mask_color.values[0] <= 0)
309
0
                color_set_null(penum->icolor0);
310
11
            if (penum->mask_color.values[1] >= 255)
311
0
                color_set_null(penum->icolor1);
312
11
        }
313
        /* Reset the clues here, rather than in image_render_mono as
314
         * previously. Even doing so this often may be overzealous. */
315
620k
        image_init_clues(penum, penum->bps, penum->spp);
316
620k
        *render_fn = &image_render_mono;
317
620k
    }
318
1.90M
    return 0;
319
1.99M
}
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
10.0M
{
377
10.0M
    const gs_gstate *pgs = penum->pgs;
378
10.0M
    gs_logical_operation_t lop = penum->log_op;
379
10.0M
    const bool masked = penum->masked;
380
10.0M
    const gs_color_space *pcs = NULL;   /* only set for non-masks */
381
10.0M
    cs_proc_remap_color((*remap_color)) = NULL; /* ditto */
382
10.0M
    gs_client_color cc;
383
10.0M
    gx_device_color *pdevc = penum->icolor1;    /* color for masking */
384
10.0M
    uint mask_base =            /* : 0 to pacify Valgrind */
385
10.0M
        (penum->use_mask_color ? penum->mask_color.values[0] : 0);
386
10.0M
    uint mask_limit =
387
10.0M
        (penum->use_mask_color ?
388
10.0M
         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
10.0M
#define IMAGE_SET_GRAY(sample_value)\
395
106M
  BEGIN\
396
106M
    pdevc = &penum->clues[sample_value].dev_color;\
397
106M
    if (!color_is_set(pdevc)) {\
398
11.0M
        if ((uint)(sample_value - mask_base) < mask_limit)\
399
11.0M
            color_set_null(pdevc);\
400
11.0M
        else {\
401
11.0M
            decode_sample(sample_value, cc, 0);\
402
11.0M
            code = (*remap_color)(&cc, pcs, pdevc, pgs, dev, gs_color_select_source);\
403
11.0M
            if (code < 0)\
404
11.0M
                goto err;\
405
11.0M
            pdevc->tag = device_current_tag(dev);\
406
11.0M
        }\
407
91.2M
    } else if (!color_is_pure(pdevc)) {\
408
21.7M
        code = gx_color_load_select(pdevc, pgs, dev, gs_color_select_source);\
409
21.7M
        if (code < 0)\
410
21.7M
            goto err;\
411
21.7M
    }\
412
106M
  END
413
10.0M
    gx_dda_fixed_point next;    /* (y not used in fast loop) */
414
10.0M
    gx_dda_step_fixed dxx2, dxx3, dxx4;         /* (not used in all loops) */
415
10.0M
    const byte *psrc_initial = buffer + data_x;
416
10.0M
    const byte *psrc = psrc_initial;
417
10.0M
    const byte *rsrc = psrc;    /* psrc at start of run */
418
10.0M
    const byte *endp = psrc + w;
419
10.0M
    const byte *stop = endp;
420
10.0M
    fixed xrun;                 /* x at start of run */
421
10.0M
    byte run;           /* run value */
422
10.0M
    int htrun = (masked ? 255 : -2);            /* halftone run value */
423
10.0M
    int i, code = 0;
424
425
10.0M
    if (h == 0)
426
1.23M
        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
8.82M
    next = penum->dda.pixel0;
434
8.82M
    xrun = dda_current(next.x);
435
8.82M
    if (!masked) {
436
4.46M
        pcs = penum->pcs;       /* (may not be set for masks) */
437
4.46M
        remap_color = pcs->type->remap_color;
438
4.46M
    }
439
8.82M
    run = *psrc;
440
    /* Find the last transition in the input. */
441
8.82M
    if (masked &&
442
8.82M
        (penum->posture != image_portrait) &&
443
8.82M
        (penum->posture != image_landscape)) {
444
        /* No need to calculate stop */
445
4.48M
    } else {
446
4.48M
        byte last = stop[-1];
447
448
857M
        while (stop > psrc && stop[-1] == last)
449
852M
            --stop;
450
4.48M
    }
451
8.82M
    if (penum->slow_loop || penum->posture != image_portrait) {
452
453
        /**************************************************************
454
         * Slow case (skewed, rotated, or imagemask with a halftone). *
455
         **************************************************************/
456
457
4.36M
        fixed yrun;
458
4.36M
        const fixed pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
459
4.36M
        const fixed pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
460
4.36M
        dev_proc_fill_parallelogram((*fill_pgram)) =
461
4.36M
            dev_proc(dev, fill_parallelogram);
462
463
190M
#define xl dda_current(next.x)
464
195M
#define ytf dda_current(next.y)
465
4.36M
        yrun = ytf;
466
4.36M
        if (masked) {
467
468
            /**********************
469
             * Slow case, masked. *
470
             **********************/
471
472
4.34M
            pdevc = penum->icolor1;
473
4.34M
            code = gx_color_load(pdevc, pgs, dev);
474
4.34M
            if (code < 0)
475
0
                return code;
476
4.34M
            if ((stop <= psrc) && (penum->adjust == 0) &&
477
4.34M
                ((penum->posture == image_portrait) ||
478
0
                 (penum->posture == image_landscape)))
479
0
                goto last;
480
4.34M
            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
4.34M
            } 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
2
                fixed ax =
569
2
                    (pdyx < 0 ? -penum->adjust : penum->adjust);
570
2
                fixed dyx = pdyx + (ax << 1);
571
2
                fixed ay =
572
2
                    (penum->matrix.xy < 0 ? -penum->adjust : penum->adjust);
573
574
2
                xrun -= ax;
575
2
                dda_translate(next.y, -ay);
576
2
                ay <<= 1;
577
3
                for (;;) {
578
41
                    for (; psrc < endp && !*psrc; ++psrc)
579
38
                        dda_next(next.y);
580
3
                    yrun = ytf;
581
3
                    if (psrc >= stop)
582
1
                        break;
583
14
                    for (; psrc < endp && *psrc; ++psrc)
584
12
                        dda_next(next.y);
585
2
                    code = (*fill_pgram)(dev, xrun, yrun, fixed_0,
586
2
                                         ytf - yrun + ay, dyx, fixed_0,
587
2
                                         pdevc, lop);
588
2
                    if (code < 0)
589
0
                        goto err;
590
2
                    rsrc = psrc;
591
2
                    if (psrc >= stop)
592
1
                        break;
593
2
                }
594
595
4.34M
            } 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
4.34M
                stop = endp;
610
19.9M
                for (;;) {
611
                    /* skip forward until we find a 1 bit */
612
140M
                    for (; psrc < stop && !*psrc; ++psrc) {
613
120M
                        dda_next(next.x);
614
120M
                        dda_next(next.y);
615
120M
                    }
616
19.9M
                    if (psrc >= endp) /* Note, endp NOT stop! */
617
4.34M
                        break;
618
                    /* Then draw the pgram and step forward until we find a
619
                     * 0 bit. */
620
62.1M
                    do {
621
62.1M
                        yrun = ytf;
622
62.1M
                        xrun = xl;
623
62.1M
                        dda_next(next.x);
624
62.1M
                        dda_next(next.y);
625
62.1M
                        code = (*fill_pgram)(dev, xrun, yrun, xl - xrun,
626
62.1M
                                             ytf - yrun, pdyx, pdyy, pdevc, lop);
627
62.1M
                        if (code < 0)
628
0
                            goto err;
629
62.1M
                        psrc++;
630
62.1M
                        rsrc = psrc;
631
62.1M
                        if (psrc >= stop)
632
1.59M
                            break;
633
62.1M
                    } while (*psrc);
634
15.5M
                }
635
636
4.34M
            }
637
638
4.34M
        } else if (penum->posture == image_portrait) {
639
            /**************************************
640
             * Slow case, not masked, portrait. *
641
             **************************************/
642
0
            dev_proc_fill_rectangle((*fill_proc)) =
643
0
                dev_proc(dev, fill_rectangle);
644
0
            int iy = fixed2int_pixround(yrun);
645
0
            int ih = fixed2int_pixround(yrun + pdyy) - iy;
646
0
            if (ih < 0)
647
0
                iy += ih, ih = -ih;
648
649
            /* In this case, we can fill runs quickly. */
650
            /****** DOESN'T DO ADJUSTMENT ******/
651
0
            if (stop <= psrc)
652
0
                goto last;
653
0
            for (;;) {
654
0
                byte c = *psrc++;
655
0
                if (c != run) {
656
0
                    int ix = fixed2int_pixround(xrun);
657
0
                    int iw = fixed2int_pixround(xl) - ix;
658
0
                    if (iw < 0)
659
0
                        ix += iw, iw = -iw;
660
0
                    switch (run)
661
0
                    {
662
0
                    case 0:
663
0
                        if (!color_is_pure(penum->icolor0))
664
0
                            goto ht_port;
665
0
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
666
0
                                             penum->icolor0->colors.pure);
667
0
                        break;
668
0
                    case 0xff:
669
0
                        if (!color_is_pure(penum->icolor1))
670
0
                            goto ht_port;
671
0
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
672
0
                                             penum->icolor1->colors.pure);
673
0
                        break;
674
0
                    default:
675
0
                        ht_port:
676
0
                        if (run != htrun) {
677
0
                            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
0
                            IMAGE_SET_GRAY(run);
685
0
#endif
686
0
                        }
687
0
                        code = gx_fill_rectangle_device_rop(ix, iy, iw, ih,
688
0
                                                            pdevc, dev, lop);
689
0
                    }
690
0
                    if (code < 0)
691
0
                        goto err;
692
0
                    xrun = xl;
693
0
                    rsrc = psrc;
694
0
                    if (psrc > stop)
695
0
                        break;
696
0
                    run = c;
697
0
                }
698
0
                dda_next(next.x);
699
0
                if (psrc >= endp)
700
0
                    break;
701
0
            }
702
24.2k
        } else if (penum->posture == image_landscape) {
703
704
            /**************************************
705
             * Slow case, not masked, landscape. *
706
             **************************************/
707
540
            dev_proc_fill_rectangle((*fill_proc)) =
708
540
                dev_proc(dev, fill_rectangle);
709
540
            int ix = fixed2int_pixround(xrun);
710
540
            int iw = fixed2int_pixround(xrun + pdyx) - ix;
711
540
            if (iw < 0)
712
207
                ix += iw, iw = -iw;
713
714
            /* In this case, we can fill runs quickly. */
715
            /****** DOESN'T DO ADJUSTMENT ******/
716
540
            if (stop <= psrc)
717
9
                goto last;
718
43.1k
            for (;;) {
719
43.1k
                byte c = *psrc++;
720
43.1k
                if (c != run) {
721
34.9k
                    int iy = fixed2int_pixround(yrun);
722
34.9k
                    int ih = fixed2int_pixround(ytf) - iy;
723
34.9k
                    if (ih < 0)
724
13.1k
                        iy += ih, ih = -ih;
725
34.9k
                    switch (run)
726
34.9k
                    {
727
196
                    case 0:
728
196
                        if (!color_is_pure(penum->icolor0))
729
154
                            goto ht_land;
730
42
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
731
42
                                             penum->icolor0->colors.pure);
732
42
                        break;
733
47
                    case 0xff:
734
47
                        if (!color_is_pure(penum->icolor1))
735
6
                            goto ht_land;
736
41
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
737
41
                                             penum->icolor1->colors.pure);
738
41
                        break;
739
34.6k
                    default:
740
34.8k
                        ht_land:
741
34.8k
                        if (run != htrun) {
742
34.7k
                            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
34.7k
                            IMAGE_SET_GRAY(run);
750
34.7k
#endif
751
34.7k
                        }
752
34.8k
                        code = gx_fill_rectangle_device_rop(ix, iy, iw, ih,
753
34.9k
                                                            pdevc, dev, lop);
754
34.9k
                    }
755
34.9k
                    if (code < 0)
756
0
                        goto err;
757
34.9k
                    yrun = ytf;
758
34.9k
                    rsrc = psrc;
759
34.9k
                    if (psrc > stop)
760
531
                        break;
761
34.3k
                    run = c;
762
34.3k
                }
763
42.5k
                dda_next(next.y);
764
42.5k
                if (psrc >= endp)
765
0
                    break;
766
42.5k
            }
767
23.7k
        } 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
23.7k
            stop = endp;
778
33.1M
            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
33.1M
                if (run != htrun) {
783
336k
                    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
336k
                    IMAGE_SET_GRAY(run);
791
336k
#endif
792
336k
                }
793
33.1M
                code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
794
33.1M
                                      ytf - yrun, pdyx, pdyy, pdevc, lop);
795
33.1M
                if (code < 0)
796
0
                    goto err;
797
33.1M
                yrun = ytf;
798
33.1M
                xrun = xl;
799
33.1M
                rsrc = psrc;
800
33.1M
                if (psrc >= stop)
801
23.7k
                    break;
802
33.1M
                run = *psrc++;
803
33.1M
                dda_next(next.x);
804
33.1M
                dda_next(next.y);       /* harmless if no skew */
805
33.1M
            }
806
807
23.7k
        }
808
        /* Fill the last run. */
809
4.36M
      last:if (stop < endp && (*stop || !masked)) {
810
541
            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
540
                    IMAGE_SET_GRAY(*stop);
818
540
#endif
819
540
            }
820
541
            dda_advance(next.x, endp - stop);
821
541
            dda_advance(next.y, endp - stop);
822
541
            code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
823
541
                                  ytf - yrun, pdyx, pdyy, pdevc, lop);
824
541
        }
825
4.36M
#undef xl
826
4.36M
#undef ytf
827
828
4.46M
    } else {
829
830
        /**********************************************************
831
         * Fast case: no skew, and not imagemask with a halftone. *
832
         **********************************************************/
833
834
4.46M
        const fixed adjust = penum->adjust;
835
4.46M
        const fixed dxx = penum->dxx;
836
4.46M
        fixed xa = (dxx >= 0 ? adjust : -adjust);
837
4.46M
        const int yt = penum->yci, iht = penum->hci;
838
839
4.46M
        dev_proc_fill_rectangle((*fill_proc)) =
840
4.46M
            dev_proc(dev, fill_rectangle);
841
4.46M
        int xmin = fixed2int_pixround(penum->clip_outer.p.x);
842
4.46M
        int xmax = fixed2int_pixround(penum->clip_outer.q.x);
843
187M
#define xl dda_current(next.x)
844
845
4.46M
        if_debug2m('b', penum->memory, "[b]image y=%d  dda.y.Q=%lg\n",
846
4.46M
                   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
4.46M
        xrun = xrun - xa + (fixed_half - fixed_epsilon);
850
4.46M
        dda_translate(next.x, xa + (fixed_half - fixed_epsilon));
851
4.46M
        xa <<= 1;
852
        /* Calculate multiples of the DDA step. */
853
4.46M
        dxx2 = next.x.step;
854
4.46M
        dda_step_add(dxx2, next.x.step);
855
4.46M
        dxx3 = dxx2;
856
4.46M
        dda_step_add(dxx3, next.x.step);
857
4.46M
        dxx4 = dxx3;
858
4.46M
        dda_step_add(dxx4, next.x.step);
859
4.46M
        if (stop > psrc)
860
187M
            for (;;) {          /* Skip large constant regions quickly, */
861
                /* but don't slow down transitions too much. */
862
429M
              skf:if (psrc[0] == run) {
863
323M
                    if (psrc[1] == run) {
864
282M
                        if (psrc[2] == run) {
865
257M
                            if (psrc[3] == run) {
866
241M
                                psrc += 4;
867
241M
                                dda_state_next(next.x.state, dxx4);
868
241M
                                if (psrc >= endp)
869
0
                                    break;
870
241M
                                goto skf;
871
241M
                            } else {
872
15.2M
                                psrc += 4;
873
15.2M
                                dda_state_next(next.x.state, dxx3);
874
15.2M
                            }
875
257M
                        } else {
876
25.4M
                            psrc += 3;
877
25.4M
                            dda_state_next(next.x.state, dxx2);
878
25.4M
                        }
879
282M
                    } else {
880
40.8M
                        psrc += 2;
881
40.8M
                        dda_next(next.x);
882
40.8M
                    }
883
323M
                } else
884
105M
                    psrc++;
885
187M
                {               /* Now fill the region between xrun and xl. */
886
187M
                    int xi = fixed2int_var(xrun);
887
187M
                    int wi = fixed2int_var(xl) - xi;
888
187M
                    int xei;
889
890
187M
                    if (wi <= 0) {
891
7.74M
                        if (wi == 0)
892
7.67M
                            goto mt;
893
69.2k
                        xi += wi, wi = -wi;
894
69.2k
                    }
895
179M
                    if ((xei = xi + wi) > xmax || xi < xmin) {  /* Do X clipping */
896
121k
                        if (xi < xmin)
897
57.8k
                            wi -= xmin - xi, xi = xmin;
898
121k
                        if (xei > xmax)
899
64.9k
                            wi -= xei - xmax;
900
121k
                        if (wi <= 0)
901
91.7k
                            goto mt;
902
121k
                    }
903
179M
                    switch (run) {
904
39.3M
                        case 0:
905
39.3M
                            if (masked)
906
7.02k
                                goto mt;
907
39.3M
                            if (!color_is_pure(penum->icolor0))
908
497k
                                goto ht;
909
38.8M
                            code = (*fill_proc) (dev, xi, yt, wi, iht,
910
38.8M
                                                 penum->icolor0->colors.pure);
911
38.8M
                            break;
912
40.2M
                        case 255:       /* just for speed */
913
40.2M
                            if (!color_is_pure(penum->icolor1))
914
686k
                                goto ht;
915
39.5M
                            code = (*fill_proc) (dev, xi, yt, wi, iht,
916
39.5M
                                                 penum->icolor1->colors.pure);
917
39.5M
                            break;
918
100M
                        default:
919
101M
                          ht:   /* Use halftone if needed */
920
101M
                            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
97.4M
                                IMAGE_SET_GRAY(run);
928
97.4M
#endif
929
97.4M
                                htrun = run;
930
97.4M
                            }
931
101M
                            code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
932
179M
                                                                 pdevc, dev, lop);
933
179M
                    }
934
179M
                    if (code < 0)
935
0
                        goto err;
936
187M
                  mt:xrun = xl - xa;    /* original xa << 1 */
937
187M
                    rsrc = psrc - 1;
938
187M
                    if (psrc > stop) {
939
2.54M
                        --psrc;
940
2.54M
                        break;
941
2.54M
                    }
942
184M
                    run = psrc[-1];
943
184M
                }
944
184M
                dda_next(next.x);
945
184M
            }
946
        /* Fill the last run. */
947
4.46M
        if (*stop != 0 || !masked) {
948
4.44M
            int xi = fixed2int_var(xrun);
949
4.44M
            int wi, xei;
950
951
4.44M
            dda_advance(next.x, endp - stop);
952
4.44M
            wi = fixed2int_var(xl) - xi;
953
4.44M
            if (wi <= 0) {
954
20.0k
                if (wi == 0)
955
2.79k
                    goto lmt;
956
17.2k
                xi += wi, wi = -wi;
957
17.2k
            }
958
4.44M
            if ((xei = xi + wi) > xmax || xi < xmin) {  /* Do X clipping */
959
201k
                if (xi < xmin)
960
10.8k
                    wi -= xmin - xi, xi = xmin;
961
201k
                if (xei > xmax)
962
191k
                    wi -= xei - xmax;
963
201k
                if (wi <= 0)
964
22.5k
                    goto lmt;
965
201k
            }
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
4.44M
            IMAGE_SET_GRAY(*stop);
973
4.41M
#endif
974
4.41M
            code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
975
4.41M
                                                pdevc, dev, lop);
976
4.44M
          lmt:;
977
4.44M
        }
978
979
4.46M
    }
980
8.82M
#undef xl
981
8.82M
    if (code >= 0) {
982
8.82M
        code = 1;
983
8.82M
        goto done;
984
8.82M
    }
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
8.82M
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
2.26G
    for (i = 0; i < 256; i++) {
999
2.26G
        penum->clues[i].dev_color.colors.binary.b_tile = NULL;
1000
2.26G
    }
1001
8.82M
    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.28M
{
1034
1.28M
    gx_image_enum *penum = penum_orig; /* const within proc */
1035
1.28M
    image_posture posture = penum->posture;
1036
1.28M
    int vdi;  /* amounts to replicate */
1037
1.28M
    fixed xrun;
1038
1.28M
    byte *thresh_align;
1039
1.28M
    int spp_out = penum->dev->color_info.num_components;
1040
1.28M
    byte *devc_contone[GX_DEVICE_COLOR_MAX_COMPONENTS];
1041
1.28M
    byte *devc_contone_gray;
1042
1.28M
    const byte *psrc = buffer + data_x;
1043
1.28M
    int dest_width, dest_height, data_length;
1044
1.28M
    byte *color_cache;
1045
1.28M
    int position, k, j;
1046
1.28M
    int offset_bits = penum->ht_offset_bits;
1047
1.28M
    int contone_stride = 0;  /* Not used in landscape case */
1048
1.28M
    fixed offset;
1049
1.28M
    int src_size;
1050
1.28M
    bool flush_buff = false;
1051
1.28M
    int offset_contone[GX_DEVICE_COLOR_MAX_COMPONENTS];    /* to ensure 128 bit boundary */
1052
1.28M
    int offset_threshold;  /* to ensure 128 bit boundary */
1053
1.28M
    gx_dda_fixed dda_ht;
1054
1.28M
    int xn, xr;   /* destination position (pixel, not contone buffer offset) */
1055
1.28M
    int code = 0;
1056
1.28M
    byte *dev_value;
1057
1058
1.28M
    if (h == 0 || penum->line_size == 0) {      /* line_size == 0, nothing to do */
1059
170k
        if (penum->ht_landscape.count == 0 || posture == image_portrait) {
1060
170k
            return 0;
1061
170k
        } else {
1062
            /* Need to flush the buffer */
1063
1
            offset_bits = penum->ht_landscape.count;
1064
1
            penum->ht_offset_bits = offset_bits;
1065
1
            penum->ht_landscape.offset_set = true;
1066
1
            flush_buff = true;
1067
1
        }
1068
170k
    }
1069
1.10M
    src_size = penum->rect.w;
1070
1071
    /* Set up the dda.  We could move this out but the cost is pretty small */
1072
1.10M
    dda_ht = (posture == image_portrait) ? penum->dda.pixel0.x : penum->dda.pixel0.y;
1073
1.10M
    if (penum->dxx > 0)
1074
1.10M
        dda_translate(dda_ht, -fixed_epsilon);      /* to match rounding in non-fast code */
1075
1076
1.10M
    switch (posture) {
1077
1.10M
        case image_portrait:
1078
            /* Figure out our offset in the contone and threshold data
1079
               buffers so that we ensure that we are on the 128bit
1080
               memory boundaries when we get offset_bits into the data. */
1081
            /* Can't do this earlier, as GC might move the buffers. */
1082
1.10M
            xrun = dda_current(dda_ht);
1083
1.10M
            dest_width = gxht_dda_length(&dda_ht, src_size);
1084
1.10M
            if (penum->x_extent.x < 0)
1085
0
                xrun += penum->x_extent.x;
1086
1.10M
            vdi = penum->hci;
1087
1.10M
            contone_stride = penum->line_size;
1088
1.10M
            offset_threshold = (- (((int)(intptr_t)(penum->thresh_buffer)) +
1089
1.10M
                                   penum->ht_offset_bits)) & 15;
1090
2.28M
            for (k = 0; k < spp_out; k ++) {
1091
1.17M
                offset_contone[k]   = (- (((int)(intptr_t)(penum->line)) +
1092
1.17M
                                           contone_stride * k +
1093
1.17M
                                           penum->ht_offset_bits)) & 15;
1094
1.17M
            }
1095
1.10M
            data_length = dest_width;
1096
1.10M
            dest_height = fixed2int_var_rounded(any_abs(penum->y_extent.y));
1097
#ifdef DEBUG
1098
            /* Help in spotting problems */
1099
            memset(penum->ht_buffer, 0x00, penum->ht_stride * vdi * spp_out);
1100
#endif
1101
1.10M
            break;
1102
2
        case image_landscape:
1103
2
        default:
1104
            /* Figure out our offset in the contone and threshold data buffers
1105
               so that we ensure that we are on the 128bit memory boundaries.
1106
               Can't do this earlier as GC may move the buffers.
1107
             */
1108
2
            vdi = penum->wci;
1109
2
            contone_stride = penum->line_size;
1110
2
            dest_width = fixed2int_var_rounded(any_abs(penum->y_extent.x));
1111
            /* match height in gxht_thresh.c dev_width calculation */
1112
2
            xrun = dda_current(dda_ht);            /* really yrun, but just used here for landscape */
1113
2
            dest_height = gxht_dda_length(&dda_ht, src_size);
1114
2
            data_length = dest_height;
1115
2
            offset_threshold = (-(int)(intptr_t)(penum->thresh_buffer)) & 15;
1116
4
            for (k = 0; k < spp_out; k ++) {
1117
2
                offset_contone[k] = (- ((int)(intptr_t)(penum->line) +
1118
2
                                        contone_stride * k)) & 15;
1119
2
            }
1120
            /* In the landscaped case, we want to accumulate multiple columns
1121
               of data before sending to the device.  We want to have a full
1122
               byte of HT data in one write.  This may not be possible at the
1123
               left or right and for those and for those we have so send partial
1124
               chunks */
1125
            /* Initialize our xstart and compute our partial bit chunk so
1126
               that we get in sync with the 1 bit mem device 16 bit positions
1127
               for the rest of the chunks */
1128
2
            if (penum->ht_landscape.count == 0) {
1129
                /* In the landscape case, the size depends upon
1130
                   if we are moving left to right or right to left with
1131
                   the image data.  This offset is to ensure that we  get
1132
                   aligned in our chunks along 16 bit boundaries */
1133
1
                penum->ht_landscape.offset_set = true;
1134
1
                if (penum->ht_landscape.index < 0) {
1135
0
                    penum->ht_landscape.xstart = penum->xci + vdi - 1;
1136
0
                    offset_bits = (penum->ht_landscape.xstart % 16) + 1;
1137
                    /* xci can be negative, so allow for that */
1138
0
                    if (offset_bits <= 0) offset_bits += 16;
1139
1
                } else {
1140
1
                    penum->ht_landscape.xstart = penum->xci;
1141
                    /* xci can be negative, see Bug 692569. */
1142
1
                    offset_bits = 16 - penum->xci % 16;
1143
1
                    if (offset_bits >= 16) offset_bits -= 16;
1144
1
                }
1145
1
                if (offset_bits == 0 || offset_bits == 16) {
1146
1
                    penum->ht_landscape.offset_set = false;
1147
1
                    penum->ht_offset_bits = 0;
1148
1
                } else {
1149
0
                    penum->ht_offset_bits = offset_bits;
1150
0
                }
1151
1
            }
1152
2
            break;
1153
1.10M
    }
1154
1.10M
    if (flush_buff)
1155
1
        goto flush;  /* All done */
1156
1157
    /* Get the pointers to our buffers */
1158
2.28M
    for (k = 0; k < spp_out; k++) {
1159
1.17M
        if (posture == image_portrait) {
1160
1.17M
            devc_contone[k] = penum->line + contone_stride * k +
1161
1.17M
                              offset_contone[k];
1162
1.17M
        } else {
1163
1
            devc_contone[k] = penum->line + offset_contone[k] +
1164
1
                              LAND_BITS * k * contone_stride;
1165
1
        }
1166
1.17M
    }
1167
1.10M
    xr = fixed2int_var_rounded(dda_current(dda_ht));  /* indexes in the destination (contone) */
1168
1169
1.10M
    devc_contone_gray = devc_contone[0];
1170
1.10M
    if (penum->color_cache == NULL) {
1171
        /* No look-up in the cache to fill the source buffer. Still need to
1172
           have the data at device resolution.  Do these in quick small
1173
           loops.  This likely could be a vectorized function.  Note that
1174
           since the color_cache is NULL we must be in a case where we
1175
           are going to a monochrome device. */
1176
922k
        switch (posture) {
1177
922k
            case image_portrait:
1178
922k
                if (penum->dst_width > 0) {
1179
922k
                    if (src_size == dest_width) {
1180
915k
                        memcpy(devc_contone_gray, psrc, data_length);
1181
915k
                    } else if (src_size * 2 == dest_width) {
1182
0
                        const byte *psrc_temp = psrc;
1183
0
                        for (k = 0; k < data_length; k+=2, devc_contone_gray+=2,
1184
0
                             psrc_temp++) {
1185
0
                            *devc_contone_gray = *(devc_contone_gray+1) = *psrc_temp;
1186
0
                        }
1187
7.52k
                    } else {
1188
                        /* Mono case, forward */
1189
1.43M
                        for (k=0; k<src_size; k++) {
1190
1.42M
                            byte c = *psrc++;
1191
1.42M
                            dda_next(dda_ht);
1192
1.42M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1193
4.52M
                            while (xr < xn) {
1194
3.09M
                                *devc_contone_gray++ = c;
1195
3.09M
                                xr++;
1196
3.09M
                            }           /* at loop exit xn will be >= xr */
1197
1.42M
                        }
1198
7.52k
                    }
1199
922k
                } else {
1200
                    /* Mono case, backwards */
1201
0
                    devc_contone_gray += (data_length - 1);
1202
0
                    for (k=0; k<src_size; k++) {
1203
0
                        byte c = *psrc++;
1204
0
                        dda_next(dda_ht);
1205
0
                        xn = fixed2int_var_rounded(dda_current(dda_ht));
1206
0
                        while (xr > xn) {
1207
0
                            *devc_contone_gray-- = c;
1208
0
                            xr--;
1209
0
                        }           /* at loop exit xn will be >= xr */
1210
0
                    }
1211
0
                }
1212
922k
                break;
1213
1
            case image_landscape:
1214
                /* We store the data at this point into a column. Depending
1215
                   upon our landscape direction we may be going left to right
1216
                   or right to left. */
1217
1
                if (penum->ht_landscape.flipy) {
1218
0
                    position = penum->ht_landscape.curr_pos +
1219
0
                                LAND_BITS * (data_length - 1);
1220
0
                    for (k=0; k<src_size; k++) {
1221
0
                        byte c = *psrc++;
1222
0
                        dda_next(dda_ht);
1223
0
                        xn = fixed2int_var_rounded(dda_current(dda_ht));
1224
0
                        while (xr > xn) {
1225
0
                            devc_contone_gray[position] = c;
1226
0
                            position -= LAND_BITS;
1227
0
                            xr--;
1228
0
                        }           /* at loop exit xn will be <= xr */
1229
0
                    }
1230
1
                } else {
1231
1
                    position = penum->ht_landscape.curr_pos;
1232
                    /* Code up special cases for when we have no scaling
1233
                       and 2x scaling which we will run into in 300 and
1234
                       600dpi devices and content */
1235
1
                    if (src_size == dest_height) {
1236
0
                        for (k = 0; k < data_length; k++) {
1237
0
                            devc_contone_gray[position] = psrc[k];
1238
0
                            position += LAND_BITS;
1239
0
                        }
1240
1
                    } else if (src_size*2 == dest_height) {
1241
0
                        for (k = 0; k < data_length; k+=2) {
1242
0
                            offset = fixed2int_rounded(fixed_half * k);
1243
0
                            devc_contone_gray[position] =
1244
0
                                devc_contone_gray[position + LAND_BITS] = psrc[offset];
1245
0
                            position += LAND_BITS*2;
1246
0
                        }
1247
1
                    } else {
1248
                        /* use dda */
1249
257
                        for (k=0; k<src_size; k++) {
1250
256
                            byte c = *psrc++;
1251
256
                            dda_next(dda_ht);
1252
256
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1253
259
                            while (xr < xn) {
1254
3
                                devc_contone_gray[position] = c;
1255
3
                                position += LAND_BITS;
1256
3
                                xr++;
1257
3
                            }           /* at loop exit xn will be >= xr */
1258
256
                        }
1259
1
                    }
1260
1
                }
1261
                /* Store the width information and update our counts */
1262
1
                penum->ht_landscape.count += vdi;
1263
1
                penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
1264
1
                penum->ht_landscape.curr_pos += penum->ht_landscape.index;
1265
1
                penum->ht_landscape.num_contones++;
1266
1
                break;
1267
0
            default:
1268
                /* error not allowed */
1269
0
                break;
1270
922k
            }
1271
922k
    } else {
1272
        /* look-up in the cache to fill the source buffer.  If our spp_out
1273
           is 4 then we need to write out the pixels in the color_cache into
1274
           the planes */
1275
186k
        color_cache = penum->color_cache->device_contone;
1276
186k
        switch (posture) {
1277
186k
            case image_portrait:
1278
186k
                if (penum->dst_width > 0) {
1279
                    /* loop filling contone values selected from the source */
1280
186k
                    if (spp_out == 1) {
1281
                        /* Mono case, forward */
1282
38.3M
                        for (k=0; k<src_size; k++) {
1283
38.1M
                            byte c = color_cache[*psrc++];
1284
38.1M
                            dda_next(dda_ht);
1285
38.1M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1286
105M
                            while (xr < xn) {
1287
67.1M
                                *devc_contone_gray++ = c;
1288
67.1M
                                xr++;
1289
67.1M
                            }           /* at loop exit xn will be >= xr */
1290
38.1M
                        }
1291
166k
                    } else {
1292
                        /* CMYK case, forward */
1293
6.25M
                        for (k=0; k<src_size; k++) {
1294
6.23M
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1295
6.23M
                            dda_next(dda_ht);
1296
6.23M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1297
20.1M
                            while (xr < xn) {
1298
69.4M
                                for (j = 0; j < spp_out; j++) {
1299
55.5M
                                    *(devc_contone[j])++ = dev_value[j];
1300
55.5M
                                }
1301
13.8M
                                xr++;
1302
13.8M
                            }           /* at loop exit xn will be >= xr */
1303
6.23M
                        }
1304
20.7k
                    }
1305
186k
                } else {
1306
0
                    if (spp_out == 1) {
1307
                        /* Mono case, backwards */
1308
0
                        devc_contone_gray += data_length - 1;   /* move to end */
1309
0
                        for (k=0; k<src_size; k++) {
1310
0
                            byte c = color_cache[*psrc++];
1311
0
                            dda_next(dda_ht);
1312
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1313
0
                            while (xr > xn) {
1314
0
                                *devc_contone_gray-- = c;
1315
0
                                xr--;
1316
0
                            }           /* at loop exit xn will be <= xr */
1317
0
                        }
1318
0
                    } else {
1319
                        /* CMYK case, backwards */
1320
                        /* Move to the other end and we will decrement */
1321
0
                        for (j = 0; j < spp_out; j++) {
1322
0
                            devc_contone[j] = devc_contone[j] + data_length - 1;
1323
0
                        }
1324
0
                        for (k=0; k<src_size; k++) {
1325
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1326
0
                            dda_next(dda_ht);
1327
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1328
0
                            while (xr > xn) {
1329
0
                                for (j = 0; j < spp_out; j++) {
1330
0
                                    *(devc_contone[j])-- = dev_value[j];
1331
0
                                }
1332
0
                                xr--;
1333
0
                            }           /* at loop exit xn will be <= xr */
1334
0
                        }
1335
0
                    }
1336
0
                }
1337
186k
                break;
1338
0
            case image_landscape:
1339
                /* We store the data at this point into a column. Depending
1340
                   upon our landscape direction we may be going left to right
1341
                   or right to left. */
1342
0
                if (penum->ht_landscape.flipy) {
1343
0
                    position = penum->ht_landscape.curr_pos +
1344
0
                                LAND_BITS * (data_length - 1);
1345
                    /* use dda */
1346
0
                    if (spp_out == 1) {
1347
                        /* Mono case */
1348
                        /* loop filling contone values selected from the source */
1349
0
                        for (k=0; k<src_size; k++) {
1350
0
                            byte c = color_cache[*psrc++];
1351
0
                            dda_next(dda_ht);
1352
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1353
0
                            while (xr > xn) {
1354
0
                                devc_contone_gray[position] = c;
1355
0
                                position -= LAND_BITS;
1356
0
                                xr--;
1357
0
                            }           /* at loop exit xn will be <= xr */
1358
0
                        }
1359
0
                    } else {
1360
                        /* CMYK case */
1361
0
                        for (k=0; k<src_size; k++) {
1362
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1363
0
                            dda_next(dda_ht);
1364
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1365
0
                            while (xr > xn) {
1366
0
                                for (j = 0; j < spp_out; j++) {
1367
0
                                    *(devc_contone[j] + position) = dev_value[j];
1368
0
                                }
1369
0
                                position -= LAND_BITS;
1370
0
                                xr--;
1371
0
                            }           /* at loop exit xn will be <= xr */
1372
0
                        }
1373
0
                    }
1374
0
                } else {  /* Not flipped in Y */
1375
0
                    position = penum->ht_landscape.curr_pos;
1376
                    /* use dda */
1377
0
                    if (spp_out == 1) {
1378
                        /* Mono case */
1379
                        /* loop filling contone values selected from the source */
1380
0
                        for (k=0; k<src_size; k++) {
1381
0
                            byte c = color_cache[*psrc++];
1382
0
                            dda_next(dda_ht);
1383
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1384
0
                            while (xr < xn) {
1385
0
                                devc_contone_gray[position] = c;
1386
0
                                position += LAND_BITS;
1387
0
                                xr++;
1388
0
                            }           /* at loop exit xn will be >= xr */
1389
0
                        }
1390
0
                    } else {
1391
                        /* CMYK case */
1392
                        /* Apply initial offset */
1393
0
                        for (k = 0; k < spp_out; k++) {
1394
0
                            devc_contone[k] = devc_contone[k] + position;
1395
0
                        }
1396
                        /* CMYK case */
1397
0
                        for (k=0; k<src_size; k++) {
1398
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1399
0
                            dda_next(dda_ht);
1400
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1401
0
                            while (xr < xn) {
1402
0
                                for (j = 0; j < spp_out; j++) {
1403
0
                                    *(devc_contone[j] + position) = dev_value[j];
1404
0
                                }
1405
0
                                position += LAND_BITS;
1406
0
                                xr++;
1407
0
                            }           /* at loop exit xn will be >= xr */
1408
0
                        }
1409
0
                    }
1410
0
                }
1411
                /* Store the width information and update our counts */
1412
0
                penum->ht_landscape.count += vdi;
1413
0
                penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
1414
0
                penum->ht_landscape.curr_pos += penum->ht_landscape.index;
1415
0
                penum->ht_landscape.num_contones++;
1416
0
                break;
1417
0
            default:
1418
                /* error not allowed */
1419
0
                break;
1420
186k
        }
1421
186k
    }
1422
    /* Apply threshold array to image data */
1423
1.10M
flush:
1424
1.10M
    thresh_align = penum->thresh_buffer + offset_threshold;
1425
1.10M
    code = gxht_thresh_planes(penum, xrun, dest_width, dest_height,
1426
1.10M
                              thresh_align, dev, offset_contone,
1427
1.10M
                              contone_stride);
1428
1.10M
    return code;
1429
1.10M
}
1430
#endif