Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gximono.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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->is_planar) {
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
315k
{
162
315k
#if USE_FAST_HT_CODE
163
315k
    bool use_fast_code = true;
164
#else
165
    bool use_fast_code = false;
166
#endif
167
315k
    int code = 0;
168
    /* Set up the link now */
169
315k
    const gs_color_space *pcs;
170
315k
    gsicc_rendering_param_t rendering_params;
171
315k
    cmm_dev_profile_t *dev_profile;
172
315k
    bool dev_color_ok = false;
173
315k
    bool is_planar_dev = penum->dev->is_planar;
174
175
315k
    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
79.3k
        dev_color_ok = ((penum->dev->color_info.num_components == 1 &&
187
79.3k
                         penum->dev->color_info.depth == 1) ||
188
#if 0
189
                         /* Don't allow CMYK Planar devices just yet */
190
                         0);
191
#else
192
79.3k
                        (penum->dev->color_info.num_components == 4 &&
193
79.1k
                         penum->dev->color_info.depth == 4 && is_planar_dev));
194
79.3k
#endif
195
196
79.3k
        if (use_fast_code && penum->pcs != NULL && dev_color_ok &&
197
79.3k
            penum->bps == 8 && (penum->posture == image_portrait
198
245
            || penum->posture == image_landscape) &&
199
79.3k
            penum->image_parent_type == gs_image_type1 &&
200
79.3k
            gx_transfer_is_monotonic(penum->pgs, 0)) {
201
245
            penum->icc_setup.need_decode = false;
202
            /* Check if we need to do any decoding.  */
203
245
            if ( penum->map[0].decoding != sd_none ) {
204
38
                if (!(penum->map[0].decoding == sd_compute
205
38
                     && penum->map[0].decode_factor == 1.0 &&
206
38
                        penum->map[0].decode_lookup[0] == 0.0)) {
207
0
                    penum->icc_setup.need_decode = true;
208
0
                }
209
38
            }
210
245
            code = dev_proc(penum->dev, get_profile)(penum->dev, &dev_profile);
211
245
            if (code < 0)
212
0
                return code;
213
214
            /* Define the rendering intents */
215
245
            rendering_params.black_point_comp = penum->pgs->blackptcomp;
216
245
            rendering_params.graphics_type_tag = GS_IMAGE_TAG;
217
245
            rendering_params.override_icc = false;
218
245
            rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
219
245
            rendering_params.rendering_intent = penum->pgs->renderingintent;
220
245
            rendering_params.cmm = gsCMM_DEFAULT;
221
245
            if (gs_color_space_get_index(penum->pcs) ==
222
245
                gs_color_space_index_Indexed) {
223
38
                pcs = penum->pcs->base_space;
224
207
            } else {
225
207
                pcs = penum->pcs;
226
207
            }
227
245
            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
245
            if (pcs->cmm_icc_profile_data == NULL)
235
0
                goto not_fast_halftoning;
236
237
245
            penum->icc_setup.is_lab = pcs->cmm_icc_profile_data->islab;
238
245
            penum->icc_setup.must_halftone = gx_device_must_halftone(penum->dev);
239
            /* The effective transfer is built into the threshold array */
240
245
            penum->icc_setup.has_transfer = false;
241
245
            if (penum->icc_setup.is_lab)
242
0
                penum->icc_setup.need_decode = false;
243
245
            if (penum->icc_link == NULL) {
244
245
                penum->icc_link = gsicc_get_link(penum->pgs, penum->dev, pcs, NULL,
245
245
                    &rendering_params, penum->memory);
246
245
            }
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
245
            penum->use_cie_range = false;
252
245
            if (gs_color_space_is_PSCIE(penum->pcs) &&
253
245
                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
245
            code = image_init_color_cache(penum, penum->bps, penum->spp);
268
245
            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
245
                code = gxht_thresh_image_init(penum);
279
245
                if (code >= 0) {
280
245
                    *render_fn = &image_render_mono_ht;
281
245
                    return code;
282
245
                }
283
245
#endif
284
245
            }
285
245
        }
286
79.1k
not_fast_halftoning:
287
        /*
288
         * Use the slow loop for imagemask with a halftone or a non-default
289
         * logical operation.
290
         */
291
79.1k
        penum->slow_loop =
292
79.1k
            (penum->masked && !color_is_pure(penum->icolor0)) ||
293
79.1k
            penum->use_rop;
294
        /* We can bypass X clipping for portrait mono-component images. */
295
79.1k
        if (!(penum->slow_loop || penum->posture != image_portrait))
296
77.1k
            penum->clip_image &= ~(image_clip_xmin | image_clip_xmax);
297
79.1k
        if_debug0m('b', penum->memory, "[b]render=mono\n");
298
        /* Precompute values needed for rasterizing. */
299
79.1k
        penum->dxx =
300
79.1k
            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
79.1k
        if (penum->use_mask_color) {
307
0
            gx_image_scale_mask_colors(penum, 0);
308
0
            if (penum->mask_color.values[0] <= 0)
309
0
                color_set_null(penum->icolor0);
310
0
            if (penum->mask_color.values[1] >= 255)
311
0
                color_set_null(penum->icolor1);
312
0
        }
313
        /* Reset the clues here, rather than in image_render_mono as
314
         * previously. Even doing so this often may be overzealous. */
315
79.1k
        image_init_clues(penum, penum->bps, penum->spp);
316
79.1k
        *render_fn = &image_render_mono;
317
79.1k
    }
318
315k
    return 0;
319
315k
}
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
1.05M
{
377
1.05M
    const gs_gstate *pgs = penum->pgs;
378
1.05M
    gs_logical_operation_t lop = penum->log_op;
379
1.05M
    const bool masked = penum->masked;
380
1.05M
    const gs_color_space *pcs = NULL;   /* only set for non-masks */
381
1.05M
    cs_proc_remap_color((*remap_color)) = NULL; /* ditto */
382
1.05M
    gs_client_color cc;
383
1.05M
    gx_device_color *pdevc = penum->icolor1;    /* color for masking */
384
1.05M
    uint mask_base =            /* : 0 to pacify Valgrind */
385
1.05M
        (penum->use_mask_color ? penum->mask_color.values[0] : 0);
386
1.05M
    uint mask_limit =
387
1.05M
        (penum->use_mask_color ?
388
1.05M
         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
1.05M
#define IMAGE_SET_GRAY(sample_value)\
395
27.6M
  BEGIN\
396
27.6M
    pdevc = &penum->clues[sample_value].dev_color;\
397
27.6M
    if (!color_is_set(pdevc)) {\
398
2.21M
        if ((uint)(sample_value - mask_base) < mask_limit)\
399
2.21M
            color_set_null(pdevc);\
400
2.21M
        else {\
401
2.21M
            decode_sample(sample_value, cc, 0);\
402
2.21M
            code = (*remap_color)(&cc, pcs, pdevc, pgs, dev, gs_color_select_source);\
403
2.21M
            if (code < 0)\
404
2.21M
                goto err;\
405
2.21M
            pdevc->tag = (dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS);\
406
2.21M
        }\
407
24.5M
    } else if (!color_is_pure(pdevc)) {\
408
4.59M
        code = gx_color_load_select(pdevc, pgs, dev, gs_color_select_source);\
409
4.59M
        if (code < 0)\
410
4.59M
            goto err;\
411
4.59M
    }\
412
27.6M
  END
413
1.05M
    gx_dda_fixed_point next;    /* (y not used in fast loop) */
414
1.05M
    gx_dda_step_fixed dxx2, dxx3, dxx4;         /* (not used in all loops) */
415
1.05M
    const byte *psrc_initial = buffer + data_x;
416
1.05M
    const byte *psrc = psrc_initial;
417
1.05M
    const byte *rsrc = psrc;    /* psrc at start of run */
418
1.05M
    const byte *endp = psrc + w;
419
1.05M
    const byte *stop = endp;
420
1.05M
    fixed xrun;                 /* x at start of run */
421
1.05M
    byte run;           /* run value */
422
1.05M
    int htrun = (masked ? 255 : -2);            /* halftone run value */
423
1.05M
    int code = 0;
424
425
1.05M
    if (h == 0)
426
157k
        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
898k
    next = penum->dda.pixel0;
434
898k
    xrun = dda_current(next.x);
435
898k
    if (!masked) {
436
857k
        pcs = penum->pcs;       /* (may not be set for masks) */
437
857k
        remap_color = pcs->type->remap_color;
438
857k
    }
439
898k
    run = *psrc;
440
    /* Find the last transition in the input. */
441
898k
    if (masked &&
442
898k
        (penum->posture != image_portrait) &&
443
898k
        (penum->posture != image_landscape)) {
444
        /* No need to calculate stop */
445
857k
    } else {
446
857k
        byte last = stop[-1];
447
448
122M
        while (stop > psrc && stop[-1] == last)
449
122M
            --stop;
450
857k
    }
451
898k
    if (penum->slow_loop || penum->posture != image_portrait) {
452
453
        /**************************************************************
454
         * Slow case (skewed, rotated, or imagemask with a halftone). *
455
         **************************************************************/
456
457
44.0k
        fixed yrun;
458
44.0k
        const fixed pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
459
44.0k
        const fixed pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
460
44.0k
        dev_proc_fill_parallelogram((*fill_pgram)) =
461
44.0k
            dev_proc(dev, fill_parallelogram);
462
463
1.45M
#define xl dda_current(next.x)
464
1.53M
#define ytf dda_current(next.y)
465
44.0k
        yrun = ytf;
466
44.0k
        if (masked) {
467
468
            /**********************
469
             * Slow case, masked. *
470
             **********************/
471
472
40.5k
            pdevc = penum->icolor1;
473
40.5k
            code = gx_color_load(pdevc, pgs, dev);
474
40.5k
            if (code < 0)
475
0
                return code;
476
40.5k
            if ((stop <= psrc) && (penum->adjust == 0) &&
477
40.5k
                ((penum->posture == image_portrait) ||
478
0
                 (penum->posture == image_landscape)))
479
0
                goto last;
480
40.5k
            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
40.5k
            } 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
40.5k
            } 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
40.5k
                stop = endp;
610
130k
                for (;;) {
611
                    /* skip forward until we find a 1 bit */
612
759k
                    for (; psrc < stop && !*psrc; ++psrc) {
613
629k
                        dda_next(next.x);
614
629k
                        dda_next(next.y);
615
629k
                    }
616
130k
                    if (psrc >= endp) /* Note, endp NOT stop! */
617
40.5k
                        break;
618
                    /* Then draw the pgram and step forward until we find a
619
                     * 0 bit. */
620
642k
                    do {
621
642k
                        yrun = ytf;
622
642k
                        xrun = xl;
623
642k
                        dda_next(next.x);
624
642k
                        dda_next(next.y);
625
642k
                        code = (*fill_pgram)(dev, xrun, yrun, xl - xrun,
626
642k
                                             ytf - yrun, pdyx, pdyy, pdevc, lop);
627
642k
                        if (code < 0)
628
0
                            goto err;
629
642k
                        psrc++;
630
642k
                        rsrc = psrc;
631
642k
                        if (psrc >= stop)
632
24.0k
                            break;
633
642k
                    } while (*psrc);
634
89.8k
                }
635
636
40.5k
            }
637
638
40.5k
        } 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
3.46k
        } else if (penum->posture == image_landscape) {
703
704
            /**************************************
705
             * Slow case, not masked, landscape. *
706
             **************************************/
707
563
            dev_proc_fill_rectangle((*fill_proc)) =
708
563
                dev_proc(dev, fill_rectangle);
709
563
            int ix = fixed2int_pixround(xrun);
710
563
            int iw = fixed2int_pixround(xrun + pdyx) - ix;
711
563
            if (iw < 0)
712
223
                ix += iw, iw = -iw;
713
714
            /* In this case, we can fill runs quickly. */
715
            /****** DOESN'T DO ADJUSTMENT ******/
716
563
            if (stop <= psrc)
717
10
                goto last;
718
44.8k
            for (;;) {
719
44.8k
                byte c = *psrc++;
720
44.8k
                if (c != run) {
721
36.2k
                    int iy = fixed2int_pixround(yrun);
722
36.2k
                    int ih = fixed2int_pixround(ytf) - iy;
723
36.2k
                    if (ih < 0)
724
14.1k
                        iy += ih, ih = -ih;
725
36.2k
                    switch (run)
726
36.2k
                    {
727
160
                    case 0:
728
160
                        if (!color_is_pure(penum->icolor0))
729
160
                            goto ht_land;
730
0
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
731
0
                                             penum->icolor0->colors.pure);
732
0
                        break;
733
0
                    case 0xff:
734
0
                        if (!color_is_pure(penum->icolor1))
735
0
                            goto ht_land;
736
0
                        code = (*fill_proc) (dev, ix, iy, iw, ih,
737
0
                                             penum->icolor1->colors.pure);
738
0
                        break;
739
36.0k
                    default:
740
36.2k
                        ht_land:
741
36.2k
                        if (run != htrun) {
742
36.2k
                            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
36.2k
                            IMAGE_SET_GRAY(run);
750
36.2k
#endif
751
36.2k
                        }
752
36.2k
                        code = gx_fill_rectangle_device_rop(ix, iy, iw, ih,
753
36.2k
                                                            pdevc, dev, lop);
754
36.2k
                    }
755
36.2k
                    if (code < 0)
756
0
                        goto err;
757
36.2k
                    yrun = ytf;
758
36.2k
                    rsrc = psrc;
759
36.2k
                    if (psrc > stop)
760
553
                        break;
761
35.6k
                    run = c;
762
35.6k
                }
763
44.2k
                dda_next(next.y);
764
44.2k
                if (psrc >= endp)
765
0
                    break;
766
44.2k
            }
767
2.90k
        } 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
2.90k
            stop = endp;
778
82.2k
            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
82.2k
                if (run != htrun) {
783
15.7k
                    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
15.7k
                    IMAGE_SET_GRAY(run);
791
15.7k
#endif
792
15.7k
                }
793
82.2k
                code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
794
82.2k
                                      ytf - yrun, pdyx, pdyy, pdevc, lop);
795
82.2k
                if (code < 0)
796
0
                    goto err;
797
82.2k
                yrun = ytf;
798
82.2k
                xrun = xl;
799
82.2k
                rsrc = psrc;
800
82.2k
                if (psrc >= stop)
801
2.90k
                    break;
802
79.3k
                run = *psrc++;
803
79.3k
                dda_next(next.x);
804
79.3k
                dda_next(next.y);       /* harmless if no skew */
805
79.3k
            }
806
807
2.90k
        }
808
        /* Fill the last run. */
809
44.0k
      last:if (stop < endp && (*stop || !masked)) {
810
563
            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
563
                    IMAGE_SET_GRAY(*stop);
818
563
#endif
819
563
            }
820
563
            dda_advance(next.x, endp - stop);
821
563
            dda_advance(next.y, endp - stop);
822
563
            code = (*fill_pgram) (dev, xrun, yrun, xl - xrun,
823
563
                                  ytf - yrun, pdyx, pdyy, pdevc, lop);
824
563
        }
825
44.0k
#undef xl
826
44.0k
#undef ytf
827
828
854k
    } else {
829
830
        /**********************************************************
831
         * Fast case: no skew, and not imagemask with a halftone. *
832
         **********************************************************/
833
834
854k
        const fixed adjust = penum->adjust;
835
854k
        const fixed dxx = penum->dxx;
836
854k
        fixed xa = (dxx >= 0 ? adjust : -adjust);
837
854k
        const int yt = penum->yci, iht = penum->hci;
838
839
854k
        dev_proc_fill_rectangle((*fill_proc)) =
840
854k
            dev_proc(dev, fill_rectangle);
841
854k
        int xmin = fixed2int_pixround(penum->clip_outer.p.x);
842
854k
        int xmax = fixed2int_pixround(penum->clip_outer.q.x);
843
33.4M
#define xl dda_current(next.x)
844
845
854k
        if_debug2m('b', penum->memory, "[b]image y=%d  dda.y.Q=%lg\n",
846
854k
                   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
854k
        xrun = xrun - xa + (fixed_half - fixed_epsilon);
850
854k
        dda_translate(next.x, xa + (fixed_half - fixed_epsilon));
851
854k
        xa <<= 1;
852
        /* Calculate multiples of the DDA step. */
853
854k
        dxx2 = next.x.step;
854
854k
        dda_step_add(dxx2, next.x.step);
855
854k
        dxx3 = dxx2;
856
854k
        dda_step_add(dxx3, next.x.step);
857
854k
        dxx4 = dxx3;
858
854k
        dda_step_add(dxx4, next.x.step);
859
854k
        if (stop > psrc)
860
33.4M
            for (;;) {          /* Skip large constant regions quickly, */
861
                /* but don't slow down transitions too much. */
862
65.9M
              skf:if (psrc[0] == run) {
863
40.7M
                    if (psrc[1] == run) {
864
36.3M
                        if (psrc[2] == run) {
865
34.1M
                            if (psrc[3] == run) {
866
32.5M
                                psrc += 4;
867
32.5M
                                dda_state_next(next.x.state, dxx4);
868
32.5M
                                if (psrc >= endp)
869
0
                                    break;
870
32.5M
                                goto skf;
871
32.5M
                            } else {
872
1.55M
                                psrc += 4;
873
1.55M
                                dda_state_next(next.x.state, dxx3);
874
1.55M
                            }
875
34.1M
                        } else {
876
2.22M
                            psrc += 3;
877
2.22M
                            dda_state_next(next.x.state, dxx2);
878
2.22M
                        }
879
36.3M
                    } else {
880
4.44M
                        psrc += 2;
881
4.44M
                        dda_next(next.x);
882
4.44M
                    }
883
40.7M
                } else
884
25.2M
                    psrc++;
885
33.4M
                {               /* Now fill the region between xrun and xl. */
886
33.4M
                    int xi = fixed2int_var(xrun);
887
33.4M
                    int wi = fixed2int_var(xl) - xi;
888
33.4M
                    int xei;
889
890
33.4M
                    if (wi <= 0) {
891
2.00M
                        if (wi == 0)
892
1.99M
                            goto mt;
893
7.21k
                        xi += wi, wi = -wi;
894
7.21k
                    }
895
31.4M
                    if ((xei = xi + wi) > xmax || xi < xmin) {  /* Do X clipping */
896
39.5k
                        if (xi < xmin)
897
6.92k
                            wi -= xmin - xi, xi = xmin;
898
39.5k
                        if (xei > xmax)
899
32.6k
                            wi -= xei - xmax;
900
39.5k
                        if (wi <= 0)
901
31.0k
                            goto mt;
902
39.5k
                    }
903
31.3M
                    switch (run) {
904
2.55M
                        case 0:
905
2.55M
                            if (masked)
906
650
                                goto mt;
907
2.55M
                            if (!color_is_pure(penum->icolor0))
908
129k
                                goto ht;
909
2.42M
                            code = (*fill_proc) (dev, xi, yt, wi, iht,
910
2.42M
                                                 penum->icolor0->colors.pure);
911
2.42M
                            break;
912
2.61M
                        case 255:       /* just for speed */
913
2.61M
                            if (!color_is_pure(penum->icolor1))
914
88.4k
                                goto ht;
915
2.52M
                            code = (*fill_proc) (dev, xi, yt, wi, iht,
916
2.52M
                                                 penum->icolor1->colors.pure);
917
2.52M
                            break;
918
26.2M
                        default:
919
26.4M
                          ht:   /* Use halftone if needed */
920
26.4M
                            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
25.8M
                                IMAGE_SET_GRAY(run);
928
25.8M
#endif
929
25.8M
                                htrun = run;
930
25.8M
                            }
931
26.4M
                            code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
932
31.3M
                                                                 pdevc, dev, lop);
933
31.3M
                    }
934
31.3M
                    if (code < 0)
935
0
                        goto err;
936
33.4M
                  mt:xrun = xl - xa;    /* original xa << 1 */
937
33.4M
                    rsrc = psrc - 1;
938
33.4M
                    if (psrc > stop) {
939
461k
                        --psrc;
940
461k
                        break;
941
461k
                    }
942
32.9M
                    run = psrc[-1];
943
32.9M
                }
944
32.9M
                dda_next(next.x);
945
32.9M
            }
946
        /* Fill the last run. */
947
854k
        if (*stop != 0 || !masked) {
948
853k
            int xi = fixed2int_var(xrun);
949
853k
            int wi, xei;
950
951
853k
            dda_advance(next.x, endp - stop);
952
853k
            wi = fixed2int_var(xl) - xi;
953
853k
            if (wi <= 0) {
954
2.33k
                if (wi == 0)
955
530
                    goto lmt;
956
1.80k
                xi += wi, wi = -wi;
957
1.80k
            }
958
853k
            if ((xei = xi + wi) > xmax || xi < xmin) {  /* Do X clipping */
959
56.7k
                if (xi < xmin)
960
1.39k
                    wi -= xmin - xi, xi = xmin;
961
56.7k
                if (xei > xmax)
962
55.5k
                    wi -= xei - xmax;
963
56.7k
                if (wi <= 0)
964
5.84k
                    goto lmt;
965
56.7k
            }
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
853k
            IMAGE_SET_GRAY(*stop);
973
847k
#endif
974
847k
            code = gx_fill_rectangle_device_rop(xi, yt, wi, iht,
975
847k
                                                pdevc, dev, lop);
976
853k
          lmt:;
977
853k
        }
978
979
854k
    }
980
898k
#undef xl
981
898k
    if (code >= 0)
982
898k
        return 1;
983
    /* Save position if error, in case we resume. */
984
0
err:
985
0
    penum->used.x = rsrc - psrc_initial;
986
0
    penum->used.y = 0;
987
0
    return code;
988
898k
}
989
990
#ifdef WITH_CAL
991
static int
992
image_render_mono_ht_cal_skip_line(gx_image_enum *penum,
993
                                   gx_device     *dev)
994
{
995
    return !cal_halftone_next_line_required(penum->cal_ht);
996
}
997
998
static int
999
image_render_mono_ht_cal(gx_image_enum * penum, const byte * buffer, int data_x,
1000
    uint w, int h, gx_device * dev)
1001
{
1002
    const byte *input = buffer + data_x;
1003
1004
    if (buffer == NULL)
1005
        return 0;
1006
1007
    return cal_halftone_process_planar(penum->cal_ht, penum->memory->non_gc_memory,
1008
                                       (const byte * const *)&input, halftone_callback, dev);
1009
}
1010
#else
1011
/*
1012
 An image render case where the source color is monochrome or indexed and
1013
 the output is to be halftoned.  If the source color requires decoding,
1014
 an index look-up or ICC color managment, these operations have already been
1015
 performed on the index values and we are ready now to halftone */
1016
static int
1017
image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x,
1018
                  uint w, int h, gx_device * dev)
1019
9.29k
{
1020
9.29k
    gx_image_enum *penum = penum_orig; /* const within proc */
1021
9.29k
    image_posture posture = penum->posture;
1022
9.29k
    int vdi;  /* amounts to replicate */
1023
9.29k
    fixed xrun;
1024
9.29k
    byte *thresh_align;
1025
9.29k
    int spp_out = penum->dev->color_info.num_components;
1026
9.29k
    byte *devc_contone[GX_DEVICE_COLOR_MAX_COMPONENTS];
1027
9.29k
    byte *devc_contone_gray;
1028
9.29k
    const byte *psrc = buffer + data_x;
1029
9.29k
    int dest_width, dest_height, data_length;
1030
9.29k
    byte *color_cache;
1031
9.29k
    int position, k, j;
1032
9.29k
    int offset_bits = penum->ht_offset_bits;
1033
9.29k
    int contone_stride = 0;  /* Not used in landscape case */
1034
9.29k
    fixed offset;
1035
9.29k
    int src_size;
1036
9.29k
    bool flush_buff = false;
1037
9.29k
    int offset_contone[GX_DEVICE_COLOR_MAX_COMPONENTS];    /* to ensure 128 bit boundary */
1038
9.29k
    int offset_threshold;  /* to ensure 128 bit boundary */
1039
9.29k
    gx_dda_fixed dda_ht;
1040
9.29k
    int xn, xr;   /* destination position (pixel, not contone buffer offset) */
1041
9.29k
    int code = 0;
1042
9.29k
    byte *dev_value;
1043
1044
9.29k
    if (h == 0 || penum->line_size == 0) {      /* line_size == 0, nothing to do */
1045
483
        if (penum->ht_landscape.count == 0 || posture == image_portrait) {
1046
482
            return 0;
1047
482
        } else {
1048
            /* Need to flush the buffer */
1049
1
            offset_bits = penum->ht_landscape.count;
1050
1
            penum->ht_offset_bits = offset_bits;
1051
1
            penum->ht_landscape.offset_set = true;
1052
1
            flush_buff = true;
1053
1
        }
1054
483
    }
1055
8.80k
    src_size = penum->rect.w;
1056
1057
    /* Set up the dda.  We could move this out but the cost is pretty small */
1058
8.80k
    dda_ht = (posture == image_portrait) ? penum->dda.pixel0.x : penum->dda.pixel0.y;
1059
8.80k
    if (penum->dxx > 0)
1060
8.80k
        dda_translate(dda_ht, -fixed_epsilon);      /* to match rounding in non-fast code */
1061
1062
8.80k
    switch (posture) {
1063
8.80k
        case image_portrait:
1064
            /* Figure out our offset in the contone and threshold data
1065
               buffers so that we ensure that we are on the 128bit
1066
               memory boundaries when we get offset_bits into the data. */
1067
            /* Can't do this earlier, as GC might move the buffers. */
1068
8.80k
            xrun = dda_current(dda_ht);
1069
8.80k
            dest_width = gxht_dda_length(&dda_ht, src_size);
1070
8.80k
            if (penum->x_extent.x < 0)
1071
0
                xrun += penum->x_extent.x;
1072
8.80k
            vdi = penum->hci;
1073
8.80k
            contone_stride = penum->line_size;
1074
8.80k
            offset_threshold = (- (((int)(intptr_t)(penum->thresh_buffer)) +
1075
8.80k
                                   penum->ht_offset_bits)) & 15;
1076
36.6k
            for (k = 0; k < spp_out; k ++) {
1077
27.8k
                offset_contone[k]   = (- (((int)(intptr_t)(penum->line)) +
1078
27.8k
                                           contone_stride * k +
1079
27.8k
                                           penum->ht_offset_bits)) & 15;
1080
27.8k
            }
1081
8.80k
            data_length = dest_width;
1082
8.80k
            dest_height = fixed2int_var_rounded(any_abs(penum->y_extent.y));
1083
#ifdef DEBUG
1084
            /* Help in spotting problems */
1085
            memset(penum->ht_buffer, 0x00, penum->ht_stride * vdi * spp_out);
1086
#endif
1087
8.80k
            break;
1088
2
        case image_landscape:
1089
2
        default:
1090
            /* Figure out our offset in the contone and threshold data buffers
1091
               so that we ensure that we are on the 128bit memory boundaries.
1092
               Can't do this earlier as GC may move the buffers.
1093
             */
1094
2
            vdi = penum->wci;
1095
2
            contone_stride = penum->line_size;
1096
2
            dest_width = fixed2int_var_rounded(any_abs(penum->y_extent.x));
1097
            /* match height in gxht_thresh.c dev_width calculation */
1098
2
            xrun = dda_current(dda_ht);            /* really yrun, but just used here for landscape */
1099
2
            dest_height = gxht_dda_length(&dda_ht, src_size);
1100
2
            data_length = dest_height;
1101
2
            offset_threshold = (-(int)(intptr_t)(penum->thresh_buffer)) & 15;
1102
4
            for (k = 0; k < spp_out; k ++) {
1103
2
                offset_contone[k] = (- ((int)(intptr_t)(penum->line) +
1104
2
                                        contone_stride * k)) & 15;
1105
2
            }
1106
            /* In the landscaped case, we want to accumulate multiple columns
1107
               of data before sending to the device.  We want to have a full
1108
               byte of HT data in one write.  This may not be possible at the
1109
               left or right and for those and for those we have so send partial
1110
               chunks */
1111
            /* Initialize our xstart and compute our partial bit chunk so
1112
               that we get in sync with the 1 bit mem device 16 bit positions
1113
               for the rest of the chunks */
1114
2
            if (penum->ht_landscape.count == 0) {
1115
                /* In the landscape case, the size depends upon
1116
                   if we are moving left to right or right to left with
1117
                   the image data.  This offset is to ensure that we  get
1118
                   aligned in our chunks along 16 bit boundaries */
1119
1
                penum->ht_landscape.offset_set = true;
1120
1
                if (penum->ht_landscape.index < 0) {
1121
0
                    penum->ht_landscape.xstart = penum->xci + vdi - 1;
1122
0
                    offset_bits = (penum->ht_landscape.xstart % 16) + 1;
1123
                    /* xci can be negative, so allow for that */
1124
0
                    if (offset_bits <= 0) offset_bits += 16;
1125
1
                } else {
1126
1
                    penum->ht_landscape.xstart = penum->xci;
1127
                    /* xci can be negative, see Bug 692569. */
1128
1
                    offset_bits = 16 - penum->xci % 16;
1129
1
                    if (offset_bits >= 16) offset_bits -= 16;
1130
1
                }
1131
1
                if (offset_bits == 0 || offset_bits == 16) {
1132
1
                    penum->ht_landscape.offset_set = false;
1133
1
                    penum->ht_offset_bits = 0;
1134
1
                } else {
1135
0
                    penum->ht_offset_bits = offset_bits;
1136
0
                }
1137
1
            }
1138
2
            break;
1139
8.80k
    }
1140
8.80k
    if (flush_buff)
1141
1
        goto flush;  /* All done */
1142
1143
    /* Get the pointers to our buffers */
1144
36.6k
    for (k = 0; k < spp_out; k++) {
1145
27.8k
        if (posture == image_portrait) {
1146
27.8k
            devc_contone[k] = penum->line + contone_stride * k +
1147
27.8k
                              offset_contone[k];
1148
27.8k
        } else {
1149
1
            devc_contone[k] = penum->line + offset_contone[k] +
1150
1
                              LAND_BITS * k * contone_stride;
1151
1
        }
1152
27.8k
    }
1153
8.80k
    xr = fixed2int_var_rounded(dda_current(dda_ht));  /* indexes in the destination (contone) */
1154
1155
8.80k
    devc_contone_gray = devc_contone[0];
1156
8.80k
    if (penum->color_cache == NULL) {
1157
        /* No look-up in the cache to fill the source buffer. Still need to
1158
           have the data at device resolution.  Do these in quick small
1159
           loops.  This likely could be a vectorized function.  Note that
1160
           since the color_cache is NULL we must be in a case where we
1161
           are going to a monochrome device. */
1162
2.46k
        switch (posture) {
1163
2.46k
            case image_portrait:
1164
2.46k
                if (penum->dst_width > 0) {
1165
2.46k
                    if (src_size == dest_width) {
1166
2.46k
                        memcpy(devc_contone_gray, psrc, data_length);
1167
2.46k
                    } else if (src_size * 2 == dest_width) {
1168
0
                        const byte *psrc_temp = psrc;
1169
0
                        for (k = 0; k < data_length; k+=2, devc_contone_gray+=2,
1170
0
                             psrc_temp++) {
1171
0
                            *devc_contone_gray = *(devc_contone_gray+1) = *psrc_temp;
1172
0
                        }
1173
0
                    } else {
1174
                        /* Mono case, forward */
1175
0
                        for (k=0; k<src_size; k++) {
1176
0
                            byte c = *psrc++;
1177
0
                            dda_next(dda_ht);
1178
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1179
0
                            while (xr < xn) {
1180
0
                                *devc_contone_gray++ = c;
1181
0
                                xr++;
1182
0
                            }           /* at loop exit xn will be >= xr */
1183
0
                        }
1184
0
                    }
1185
2.46k
                } else {
1186
                    /* Mono case, backwards */
1187
0
                    devc_contone_gray += (data_length - 1);
1188
0
                    for (k=0; k<src_size; k++) {
1189
0
                        byte c = *psrc++;
1190
0
                        dda_next(dda_ht);
1191
0
                        xn = fixed2int_var_rounded(dda_current(dda_ht));
1192
0
                        while (xr > xn) {
1193
0
                            *devc_contone_gray-- = c;
1194
0
                            xr--;
1195
0
                        }           /* at loop exit xn will be >= xr */
1196
0
                    }
1197
0
                }
1198
2.46k
                break;
1199
1
            case image_landscape:
1200
                /* We store the data at this point into a column. Depending
1201
                   upon our landscape direction we may be going left to right
1202
                   or right to left. */
1203
1
                if (penum->ht_landscape.flipy) {
1204
0
                    position = penum->ht_landscape.curr_pos +
1205
0
                                LAND_BITS * (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[position] = c;
1212
0
                            position -= LAND_BITS;
1213
0
                            xr--;
1214
0
                        }           /* at loop exit xn will be <= xr */
1215
0
                    }
1216
1
                } else {
1217
1
                    position = penum->ht_landscape.curr_pos;
1218
                    /* Code up special cases for when we have no scaling
1219
                       and 2x scaling which we will run into in 300 and
1220
                       600dpi devices and content */
1221
1
                    if (src_size == dest_height) {
1222
0
                        for (k = 0; k < data_length; k++) {
1223
0
                            devc_contone_gray[position] = psrc[k];
1224
0
                            position += LAND_BITS;
1225
0
                        }
1226
1
                    } else if (src_size*2 == dest_height) {
1227
0
                        for (k = 0; k < data_length; k+=2) {
1228
0
                            offset = fixed2int_rounded(fixed_half * k);
1229
0
                            devc_contone_gray[position] =
1230
0
                                devc_contone_gray[position + LAND_BITS] = psrc[offset];
1231
0
                            position += LAND_BITS*2;
1232
0
                        }
1233
1
                    } else {
1234
                        /* use dda */
1235
257
                        for (k=0; k<src_size; k++) {
1236
256
                            byte c = *psrc++;
1237
256
                            dda_next(dda_ht);
1238
256
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1239
259
                            while (xr < xn) {
1240
3
                                devc_contone_gray[position] = c;
1241
3
                                position += LAND_BITS;
1242
3
                                xr++;
1243
3
                            }           /* at loop exit xn will be >= xr */
1244
256
                        }
1245
1
                    }
1246
1
                }
1247
                /* Store the width information and update our counts */
1248
1
                penum->ht_landscape.count += vdi;
1249
1
                penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
1250
1
                penum->ht_landscape.curr_pos += penum->ht_landscape.index;
1251
1
                penum->ht_landscape.num_contones++;
1252
1
                break;
1253
0
            default:
1254
                /* error not allowed */
1255
0
                break;
1256
2.46k
            }
1257
6.33k
    } else {
1258
        /* look-up in the cache to fill the source buffer.  If our spp_out
1259
           is 4 then we need to write out the pixels in the color_cache into
1260
           the planes */
1261
6.33k
        color_cache = penum->color_cache->device_contone;
1262
6.33k
        switch (posture) {
1263
6.33k
            case image_portrait:
1264
6.33k
                if (penum->dst_width > 0) {
1265
                    /* loop filling contone values selected from the source */
1266
6.33k
                    if (spp_out == 1) {
1267
                        /* Mono case, forward */
1268
0
                        for (k=0; k<src_size; k++) {
1269
0
                            byte c = color_cache[*psrc++];
1270
0
                            dda_next(dda_ht);
1271
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1272
0
                            while (xr < xn) {
1273
0
                                *devc_contone_gray++ = c;
1274
0
                                xr++;
1275
0
                            }           /* at loop exit xn will be >= xr */
1276
0
                        }
1277
6.33k
                    } else {
1278
                        /* CMYK case, forward */
1279
2.50M
                        for (k=0; k<src_size; k++) {
1280
2.50M
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1281
2.50M
                            dda_next(dda_ht);
1282
2.50M
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1283
5.73M
                            while (xr < xn) {
1284
16.1M
                                for (j = 0; j < spp_out; j++) {
1285
12.9M
                                    *(devc_contone[j])++ = dev_value[j];
1286
12.9M
                                }
1287
3.22M
                                xr++;
1288
3.22M
                            }           /* at loop exit xn will be >= xr */
1289
2.50M
                        }
1290
6.33k
                    }
1291
6.33k
                } else {
1292
0
                    if (spp_out == 1) {
1293
                        /* Mono case, backwards */
1294
0
                        devc_contone_gray += data_length - 1;   /* move to end */
1295
0
                        for (k=0; k<src_size; k++) {
1296
0
                            byte c = color_cache[*psrc++];
1297
0
                            dda_next(dda_ht);
1298
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1299
0
                            while (xr > xn) {
1300
0
                                *devc_contone_gray-- = c;
1301
0
                                xr--;
1302
0
                            }           /* at loop exit xn will be <= xr */
1303
0
                        }
1304
0
                    } else {
1305
                        /* CMYK case, backwards */
1306
                        /* Move to the other end and we will decrement */
1307
0
                        for (j = 0; j < spp_out; j++) {
1308
0
                            devc_contone[j] = devc_contone[j] + data_length - 1;
1309
0
                        }
1310
0
                        for (k=0; k<src_size; k++) {
1311
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1312
0
                            dda_next(dda_ht);
1313
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1314
0
                            while (xr > xn) {
1315
0
                                for (j = 0; j < spp_out; j++) {
1316
0
                                    *(devc_contone[j])-- = dev_value[j];
1317
0
                                }
1318
0
                                xr--;
1319
0
                            }           /* at loop exit xn will be <= xr */
1320
0
                        }
1321
0
                    }
1322
0
                }
1323
6.33k
                break;
1324
0
            case image_landscape:
1325
                /* We store the data at this point into a column. Depending
1326
                   upon our landscape direction we may be going left to right
1327
                   or right to left. */
1328
0
                if (penum->ht_landscape.flipy) {
1329
0
                    position = penum->ht_landscape.curr_pos +
1330
0
                                LAND_BITS * (data_length - 1);
1331
                    /* use dda */
1332
0
                    if (spp_out == 1) {
1333
                        /* Mono case */
1334
                        /* loop filling contone values selected from the source */
1335
0
                        for (k=0; k<src_size; k++) {
1336
0
                            byte c = color_cache[*psrc++];
1337
0
                            dda_next(dda_ht);
1338
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1339
0
                            while (xr > xn) {
1340
0
                                devc_contone_gray[position] = c;
1341
0
                                position -= LAND_BITS;
1342
0
                                xr--;
1343
0
                            }           /* at loop exit xn will be <= xr */
1344
0
                        }
1345
0
                    } else {
1346
                        /* CMYK case */
1347
0
                        for (k=0; k<src_size; k++) {
1348
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1349
0
                            dda_next(dda_ht);
1350
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1351
0
                            while (xr > xn) {
1352
0
                                for (j = 0; j < spp_out; j++) {
1353
0
                                    *(devc_contone[j] + position) = dev_value[j];
1354
0
                                }
1355
0
                                position -= LAND_BITS;
1356
0
                                xr--;
1357
0
                            }           /* at loop exit xn will be <= xr */
1358
0
                        }
1359
0
                    }
1360
0
                } else {  /* Not flipped in Y */
1361
0
                    position = penum->ht_landscape.curr_pos;
1362
                    /* use dda */
1363
0
                    if (spp_out == 1) {
1364
                        /* Mono case */
1365
                        /* loop filling contone values selected from the source */
1366
0
                        for (k=0; k<src_size; k++) {
1367
0
                            byte c = color_cache[*psrc++];
1368
0
                            dda_next(dda_ht);
1369
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1370
0
                            while (xr < xn) {
1371
0
                                devc_contone_gray[position] = c;
1372
0
                                position += LAND_BITS;
1373
0
                                xr++;
1374
0
                            }           /* at loop exit xn will be >= xr */
1375
0
                        }
1376
0
                    } else {
1377
                        /* CMYK case */
1378
                        /* Apply initial offset */
1379
0
                        for (k = 0; k < spp_out; k++) {
1380
0
                            devc_contone[k] = devc_contone[k] + position;
1381
0
                        }
1382
                        /* CMYK case */
1383
0
                        for (k=0; k<src_size; k++) {
1384
0
                            dev_value = &(color_cache[*psrc++ * spp_out]);
1385
0
                            dda_next(dda_ht);
1386
0
                            xn = fixed2int_var_rounded(dda_current(dda_ht));
1387
0
                            while (xr < xn) {
1388
0
                                for (j = 0; j < spp_out; j++) {
1389
0
                                    *(devc_contone[j] + position) = dev_value[j];
1390
0
                                }
1391
0
                                position += LAND_BITS;
1392
0
                                xr++;
1393
0
                            }           /* at loop exit xn will be >= xr */
1394
0
                        }
1395
0
                    }
1396
0
                }
1397
                /* Store the width information and update our counts */
1398
0
                penum->ht_landscape.count += vdi;
1399
0
                penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
1400
0
                penum->ht_landscape.curr_pos += penum->ht_landscape.index;
1401
0
                penum->ht_landscape.num_contones++;
1402
0
                break;
1403
0
            default:
1404
                /* error not allowed */
1405
0
                break;
1406
6.33k
        }
1407
6.33k
    }
1408
    /* Apply threshold array to image data */
1409
8.80k
flush:
1410
8.80k
    thresh_align = penum->thresh_buffer + offset_threshold;
1411
8.80k
    code = gxht_thresh_planes(penum, xrun, dest_width, dest_height,
1412
8.80k
                              thresh_align, dev, offset_contone,
1413
8.80k
                              contone_stride);
1414
8.80k
    return code;
1415
8.80k
}
1416
#endif