~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to base/gximag3x.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: gximag3x.c 12227 2011-03-02 18:51:23Z mvrhel $ */
 
14
/* $Id$ */
15
15
/* ImageType 3x image implementation */
16
16
/****** THE REAL WORK IS NYI ******/
17
17
#include "math_.h"              /* for ceil, floor */
81
81
typedef struct image3x_channel_state_s {
82
82
    gx_image_enum_common_t *info;
83
83
    gx_device *mdev;            /* gx_device_memory in default impl. */
84
 
                                /* (only for masks) */
 
84
                                /* (only for masks) */
85
85
    gs_image3_interleave_type_t InterleaveType;
86
86
    int width, height, full_height, depth;
87
87
    byte *data;                 /* (if chunky) */
88
88
    /* Only the following change dynamically. */
89
89
    int y;
90
90
    int skip;                   /* only for masks, # of rows to skip, */
91
 
                                /* see below */
 
91
                                /* see below */
92
92
} image3x_channel_state_t;
93
93
typedef struct gx_image3x_enum_s {
94
94
    gx_image_enum_common;
116
116
    gs_image_t image;
117
117
} image3x_channel_values_t;
118
118
static int check_image3x_mask(const gs_image3x_t *pim,
119
 
                               const gs_image3x_mask_t *pimm,
120
 
                               const image3x_channel_values_t *ppcv,
121
 
                               image3x_channel_values_t *pmcv,
122
 
                               image3x_channel_state_t *pmcs,
123
 
                               gs_memory_t *mem);
 
119
                               const gs_image3x_mask_t *pimm,
 
120
                               const image3x_channel_values_t *ppcv,
 
121
                               image3x_channel_values_t *pmcv,
 
122
                               image3x_channel_state_t *pmcs,
 
123
                               gs_memory_t *mem);
124
124
int
125
125
gx_begin_image3x_generic(gx_device * dev,
126
 
                        const gs_imager_state *pis, const gs_matrix *pmat,
127
 
                        const gs_image_common_t *pic, const gs_int_rect *prect,
128
 
                        const gx_drawing_color *pdcolor,
129
 
                        const gx_clip_path *pcpath, gs_memory_t *mem,
130
 
                        image3x_make_mid_proc_t make_mid,
131
 
                        image3x_make_mcde_proc_t make_mcde,
132
 
                        gx_image_enum_common_t **pinfo)
 
126
                        const gs_imager_state *pis, const gs_matrix *pmat,
 
127
                        const gs_image_common_t *pic, const gs_int_rect *prect,
 
128
                        const gx_drawing_color *pdcolor,
 
129
                        const gx_clip_path *pcpath, gs_memory_t *mem,
 
130
                        image3x_make_mid_proc_t make_mid,
 
131
                        image3x_make_mcde_proc_t make_mcde,
 
132
                        gx_image_enum_common_t **pinfo)
133
133
{
134
134
    const gs_image3x_t *pim = (const gs_image3x_t *)pic;
135
135
    gx_image3x_enum_t *penum;
144
144
 
145
145
    /* Validate the parameters. */
146
146
    if (pim->Height <= 0)
147
 
        return_error(gs_error_rangecheck);
 
147
        return_error(gs_error_rangecheck);
148
148
    penum = gs_alloc_struct(mem, gx_image3x_enum_t, &st_image3x_enum,
149
 
                            "gx_begin_image3x");
 
149
                            "gx_begin_image3x");
150
150
    if (penum == 0)
151
 
        return_error(gs_error_VMerror);
 
151
        return_error(gs_error_VMerror);
152
152
    /* Initialize pointers now in case we bail out. */
153
153
    penum->mask[0].info = 0, penum->mask[0].mdev = 0, penum->mask[0].data = 0;
154
154
    penum->mask[1].info = 0, penum->mask[1].mdev = 0, penum->mask[1].data = 0;
155
155
    penum->pixel.info = 0, penum->pixel.data = 0;
156
156
    if (prect)
157
 
        pixel.rect = *prect;
 
157
        pixel.rect = *prect;
158
158
    else {
159
 
        pixel.rect.p.x = pixel.rect.p.y = 0;
160
 
        pixel.rect.q.x = pim->Width;
161
 
        pixel.rect.q.y = pim->Height;
 
159
        pixel.rect.p.x = pixel.rect.p.y = 0;
 
160
        pixel.rect.q.x = pim->Width;
 
161
        pixel.rect.q.y = pim->Height;
162
162
    }
163
163
    if ((code = gs_matrix_invert(&pim->ImageMatrix, &pixel.matrix)) < 0 ||
164
 
        (code = gs_point_transform(pim->Width, pim->Height, &pixel.matrix,
165
 
                                   &pixel.corner)) < 0 ||
166
 
        (code = check_image3x_mask(pim, &pim->Opacity, &pixel, &mask[0],
167
 
                                   &penum->mask[0], mem)) < 0 ||
168
 
        (code = check_image3x_mask(pim, &pim->Shape, &pixel, &mask[1],
169
 
                                   &penum->mask[1], mem)) < 0
170
 
        ) {
171
 
        goto out0;
 
164
        (code = gs_point_transform(pim->Width, pim->Height, &pixel.matrix,
 
165
                                   &pixel.corner)) < 0 ||
 
166
        (code = check_image3x_mask(pim, &pim->Opacity, &pixel, &mask[0],
 
167
                                   &penum->mask[0], mem)) < 0 ||
 
168
        (code = check_image3x_mask(pim, &pim->Shape, &pixel, &mask[1],
 
169
                                   &penum->mask[1], mem)) < 0
 
170
        ) {
 
171
        goto out0;
172
172
    }
173
173
    penum->num_components =
174
 
        gs_color_space_num_components(pim->ColorSpace);
 
174
        gs_color_space_num_components(pim->ColorSpace);
175
175
    gx_image_enum_common_init((gx_image_enum_common_t *) penum,
176
 
                              (const gs_data_image_t *)pim,
177
 
                              &image3x_enum_procs, dev,
178
 
                              1 + penum->num_components,
179
 
                              pim->format);
 
176
                              (const gs_data_image_t *)pim,
 
177
                              &image3x_enum_procs, dev,
 
178
                              1 + penum->num_components,
 
179
                              pim->format);
180
180
    penum->pixel.width = pixel.rect.q.x - pixel.rect.p.x;
181
181
    penum->pixel.height = pixel.rect.q.y - pixel.rect.p.y;
182
182
    penum->pixel.full_height = pim->Height;
183
183
    penum->pixel.y = 0;
184
184
    if (penum->mask[0].data || penum->mask[1].data) {
185
 
        /* Also allocate a row buffer for the pixel data. */
186
 
        penum->pixel.data =
187
 
            gs_alloc_bytes(mem,
188
 
                           (penum->pixel.width * pim->BitsPerComponent *
189
 
                            penum->num_components + 7) >> 3,
190
 
                           "gx_begin_image3x(pixel.data)");
191
 
        if (penum->pixel.data == 0) {
192
 
            code = gs_note_error(gs_error_VMerror);
193
 
            goto out1;
194
 
        }
 
185
        /* Also allocate a row buffer for the pixel data. */
 
186
        penum->pixel.data =
 
187
            gs_alloc_bytes(mem,
 
188
                           (penum->pixel.width * pim->BitsPerComponent *
 
189
                            penum->num_components + 7) >> 3,
 
190
                           "gx_begin_image3x(pixel.data)");
 
191
        if (penum->pixel.data == 0) {
 
192
            code = gs_note_error(gs_error_VMerror);
 
193
            goto out1;
 
194
        }
195
195
    }
196
196
    penum->bpc = pim->BitsPerComponent;
197
197
    penum->memory = mem;
198
198
    if (pmat == 0)
199
 
        pmat = &ctm_only(pis);
 
199
        pmat = &ctm_only(pis);
200
200
    for (i = 0; i < NUM_MASKS; ++i) {
201
 
        gs_rect mrect;
202
 
        gx_device *mdev;
203
 
        /*
204
 
         * The mask data has to be defined in a DevicePixel color space
205
 
         * of the correct depth so that no color mapping will occur.
206
 
         */
207
 
        /****** FREE COLOR SPACE ON ERROR OR AT END ******/
208
 
        gs_color_space *pmcs;
 
201
        gs_rect mrect;
 
202
        gx_device *mdev;
 
203
        /*
 
204
         * The mask data has to be defined in a DevicePixel color space
 
205
         * of the correct depth so that no color mapping will occur.
 
206
         */
 
207
        /****** FREE COLOR SPACE ON ERROR OR AT END ******/
 
208
        gs_color_space *pmcs;
209
209
 
210
 
        if (penum->mask[i].depth == 0) {        /* mask not supplied */
211
 
            midev[i] = 0;
212
 
            minfo[i] = 0;
213
 
            continue;
214
 
        }
215
 
        code = gs_cspace_new_DevicePixel(mem, &pmcs, penum->mask[i].depth);
216
 
        if (code < 0)
217
 
            return code;
218
 
        mrect.p.x = mrect.p.y = 0;
219
 
        mrect.q.x = penum->mask[i].width;
220
 
        mrect.q.y = penum->mask[i].height;
221
 
        if ((code = gs_matrix_multiply(&mask[i].matrix, pmat, &mat)) < 0 ||
222
 
            (code = gs_bbox_transform(&mrect, &mat, &mrect)) < 0
223
 
            )
224
 
            return code;
225
 
        origin[i].x = (int)floor(mrect.p.x);
226
 
        origin[i].y = (int)floor(mrect.p.y);
227
 
        code = make_mid(&mdev, dev,
228
 
                        (int)ceil(mrect.q.x) - origin[i].x,
229
 
                        (int)ceil(mrect.q.y) - origin[i].y,
230
 
                        penum->mask[i].depth, mem);
231
 
        mdev->device_icc_profile = dev->device_icc_profile;
232
 
        rc_increment(dev->device_icc_profile);
233
 
        if (code < 0)
234
 
            goto out1;
235
 
        penum->mask[i].mdev = mdev;
 
210
        if (penum->mask[i].depth == 0) {        /* mask not supplied */
 
211
            midev[i] = 0;
 
212
            minfo[i] = 0;
 
213
            continue;
 
214
        }
 
215
        code = gs_cspace_new_DevicePixel(mem, &pmcs, penum->mask[i].depth);
 
216
        if (code < 0)
 
217
            return code;
 
218
        mrect.p.x = mrect.p.y = 0;
 
219
        mrect.q.x = penum->mask[i].width;
 
220
        mrect.q.y = penum->mask[i].height;
 
221
        if ((code = gs_matrix_multiply(&mask[i].matrix, pmat, &mat)) < 0 ||
 
222
            (code = gs_bbox_transform(&mrect, &mat, &mrect)) < 0
 
223
            )
 
224
            return code;
 
225
        origin[i].x = (int)floor(mrect.p.x);
 
226
        origin[i].y = (int)floor(mrect.p.y);
 
227
        code = make_mid(&mdev, dev,
 
228
                        (int)ceil(mrect.q.x) - origin[i].x,
 
229
                        (int)ceil(mrect.q.y) - origin[i].y,
 
230
                        penum->mask[i].depth, mem);
 
231
        code = dev_proc(dev, get_profile)(dev, &mdev->icc_array);
 
232
        rc_increment(mdev->icc_array);
 
233
        if (code < 0)
 
234
            goto out1;
 
235
        penum->mask[i].mdev = mdev;
236
236
        gs_image_t_init(&mask[i].image, pmcs);
237
 
        mask[i].image.ColorSpace = pmcs;
238
 
        mask[i].image.adjust = false;
 
237
        mask[i].image.ColorSpace = pmcs;
 
238
        mask[i].image.adjust = false;
239
239
        mask[i].image.image_parent_type = gs_image_type3x;
240
 
        {
241
 
            const gx_image_type_t *type1 = mask[i].image.type;
242
 
            const gs_image3x_mask_t *pixm =
243
 
                (i == 0 ? &pim->Opacity : &pim->Shape);
 
240
        {
 
241
            const gx_image_type_t *type1 = mask[i].image.type;
 
242
            const gs_image3x_mask_t *pixm =
 
243
                (i == 0 ? &pim->Opacity : &pim->Shape);
244
244
 
245
245
            /* Use memcpy because direct assignment breaks ANSI aliasing */
246
246
            /* rules and causes SEGV with gcc 4.5.1 */
247
247
            memcpy(&mask[i].image, &pixm->MaskDict, sizeof(pixm->MaskDict));
248
 
            mask[i].image.type = type1;
249
 
            mask[i].image.BitsPerComponent = pixm->MaskDict.BitsPerComponent;
250
 
        }
251
 
        {
252
 
            gs_matrix m_mat;
 
248
            mask[i].image.type = type1;
 
249
            mask[i].image.BitsPerComponent = pixm->MaskDict.BitsPerComponent;
 
250
        }
 
251
        {
 
252
            gs_matrix m_mat;
253
253
 
254
 
            /*
255
 
             * Adjust the translation for rendering the mask to include a
256
 
             * negative translation by origin.{x,y} in device space.
257
 
             */
258
 
            m_mat = *pmat;
259
 
            m_mat.tx -= origin[i].x;
260
 
            m_mat.ty -= origin[i].y;
261
 
            /*
262
 
             * Peter put in a comment that said " Note that pis = NULL here,
263
 
             * since we don't want to have to create another imager state with
264
 
             * default log_op, etc." and passed NULL instead of pis to this
265
 
             * routine.  However Image type 1 need the imager state (see
266
 
             * bug 688348) thus his optimization was removed.
267
 
             * dcolor = NULL is OK because this is an opaque image with
268
 
             * CombineWithColor = false.
269
 
             */
270
 
            code = gx_device_begin_typed_image(mdev, pis, &m_mat,
271
 
                               (const gs_image_common_t *)&mask[i].image,
272
 
                                               &mask[i].rect, NULL, NULL,
273
 
                                               mem, &penum->mask[i].info);
274
 
            if (code < 0)
275
 
                goto out2;
276
 
        }
277
 
        midev[i] = mdev;
278
 
        minfo[i] = penum->mask[i].info;
 
254
            /*
 
255
             * Adjust the translation for rendering the mask to include a
 
256
             * negative translation by origin.{x,y} in device space.
 
257
             */
 
258
            m_mat = *pmat;
 
259
            m_mat.tx -= origin[i].x;
 
260
            m_mat.ty -= origin[i].y;
 
261
            /*
 
262
             * Peter put in a comment that said " Note that pis = NULL here,
 
263
             * since we don't want to have to create another imager state with
 
264
             * default log_op, etc." and passed NULL instead of pis to this
 
265
             * routine.  However Image type 1 need the imager state (see
 
266
             * bug 688348) thus his optimization was removed.
 
267
             * dcolor = NULL is OK because this is an opaque image with
 
268
             * CombineWithColor = false.
 
269
             */
 
270
            code = gx_device_begin_typed_image(mdev, pis, &m_mat,
 
271
                               (const gs_image_common_t *)&mask[i].image,
 
272
                                               &mask[i].rect, NULL, NULL,
 
273
                                               mem, &penum->mask[i].info);
 
274
            if (code < 0)
 
275
                goto out2;
 
276
        }
 
277
        midev[i] = mdev;
 
278
        minfo[i] = penum->mask[i].info;
279
279
    }
280
280
    gs_image_t_init(&pixel.image, pim->ColorSpace);
281
281
    {
282
 
        const gx_image_type_t *type1 = pixel.image.type;
 
282
        const gx_image_type_t *type1 = pixel.image.type;
283
283
 
284
 
        *(gs_pixel_image_t *)&pixel.image = *(const gs_pixel_image_t *)pim;
285
 
        pixel.image.type = type1;
 
284
        *(gs_pixel_image_t *)&pixel.image = *(const gs_pixel_image_t *)pim;
 
285
        pixel.image.type = type1;
286
286
        pixel.image.image_parent_type = gs_image_type3x;
287
287
    }
288
288
    code = make_mcde(dev, pis, pmat, (const gs_image_common_t *)&pixel.image,
289
 
                     prect, pdcolor, pcpath, mem, &penum->pixel.info,
290
 
                     &pcdev, midev, minfo, origin, pim);
 
289
                     prect, pdcolor, pcpath, mem, &penum->pixel.info,
 
290
                     &pcdev, midev, minfo, origin, pim);
291
291
    if (code < 0)
292
 
        goto out3;
 
292
        goto out3;
293
293
    penum->pcdev = pcdev;
294
294
    /*
295
295
     * Set num_planes, plane_widths, and plane_depths from the values in the
296
296
     * enumerators for the mask(s) and the image data.
297
297
     */
298
298
    {
299
 
        int added_depth = 0;
300
 
        int pi = 0;
 
299
        int added_depth = 0;
 
300
        int pi = 0;
301
301
 
302
 
        for (i = 0; i < NUM_MASKS; ++i) {
303
 
            if (penum->mask[i].depth == 0)      /* no mask */
304
 
                continue;
305
 
            switch (penum->mask[i].InterleaveType) {
306
 
            case interleave_chunky:
307
 
                /* Add the mask data to the depth of the image data. */
308
 
                added_depth += pim->BitsPerComponent;
309
 
                break;
310
 
            case interleave_separate_source:
311
 
                /* Insert the mask as a separate plane. */
312
 
                penum->plane_widths[pi] = penum->mask[i].width;
313
 
                penum->plane_depths[pi] = penum->mask[i].depth;
314
 
                ++pi;
315
 
                break;
316
 
            default:            /* can't happen */
317
 
                code = gs_note_error(gs_error_Fatal);
318
 
                goto out3;
319
 
            }
320
 
        }
321
 
        memcpy(&penum->plane_widths[pi], &penum->pixel.info->plane_widths[0],
322
 
               penum->pixel.info->num_planes * sizeof(penum->plane_widths[0]));
323
 
        memcpy(&penum->plane_depths[pi], &penum->pixel.info->plane_depths[0],
324
 
               penum->pixel.info->num_planes * sizeof(penum->plane_depths[0]));
325
 
        penum->plane_depths[pi] += added_depth;
326
 
        penum->num_planes = pi + penum->pixel.info->num_planes;
 
302
        for (i = 0; i < NUM_MASKS; ++i) {
 
303
            if (penum->mask[i].depth == 0)      /* no mask */
 
304
                continue;
 
305
            switch (penum->mask[i].InterleaveType) {
 
306
            case interleave_chunky:
 
307
                /* Add the mask data to the depth of the image data. */
 
308
                added_depth += pim->BitsPerComponent;
 
309
                break;
 
310
            case interleave_separate_source:
 
311
                /* Insert the mask as a separate plane. */
 
312
                penum->plane_widths[pi] = penum->mask[i].width;
 
313
                penum->plane_depths[pi] = penum->mask[i].depth;
 
314
                ++pi;
 
315
                break;
 
316
            default:            /* can't happen */
 
317
                code = gs_note_error(gs_error_Fatal);
 
318
                goto out3;
 
319
            }
 
320
        }
 
321
        memcpy(&penum->plane_widths[pi], &penum->pixel.info->plane_widths[0],
 
322
               penum->pixel.info->num_planes * sizeof(penum->plane_widths[0]));
 
323
        memcpy(&penum->plane_depths[pi], &penum->pixel.info->plane_depths[0],
 
324
               penum->pixel.info->num_planes * sizeof(penum->plane_depths[0]));
 
325
        penum->plane_depths[pi] += added_depth;
 
326
        penum->num_planes = pi + penum->pixel.info->num_planes;
327
327
    }
328
328
    if (midev[0])
329
 
        gx_device_retain(midev[0], true); /* will free explicitly */
 
329
        gx_device_retain(midev[0], true); /* will free explicitly */
330
330
    if (midev[1])
331
 
        gx_device_retain(midev[1], true); /* ditto */
 
331
        gx_device_retain(midev[1], true); /* ditto */
332
332
    gx_device_retain(pcdev, true); /* ditto */
333
333
    *pinfo = (gx_image_enum_common_t *) penum;
334
334
    return 0;
335
335
  out3:
336
336
    if (penum->mask[1].info)
337
 
        gx_image_end(penum->mask[1].info, false);
 
337
        gx_image_end(penum->mask[1].info, false);
338
338
    if (penum->mask[0].info)
339
 
        gx_image_end(penum->mask[0].info, false);
 
339
        gx_image_end(penum->mask[0].info, false);
340
340
  out2:
341
341
    if (penum->mask[1].mdev) {
342
 
        gs_closedevice(penum->mask[1].mdev);
343
 
        gs_free_object(mem, penum->mask[1].mdev,
344
 
                       "gx_begin_image3x(mask[1].mdev)");
 
342
        gs_closedevice(penum->mask[1].mdev);
 
343
        gs_free_object(mem, penum->mask[1].mdev,
 
344
                       "gx_begin_image3x(mask[1].mdev)");
345
345
    }
346
346
    if (penum->mask[0].mdev) {
347
 
        gs_closedevice(penum->mask[0].mdev);
348
 
        gs_free_object(mem, penum->mask[0].mdev,
349
 
                       "gx_begin_image3x(mask[0].mdev)");
 
347
        gs_closedevice(penum->mask[0].mdev);
 
348
        gs_free_object(mem, penum->mask[0].mdev,
 
349
                       "gx_begin_image3x(mask[0].mdev)");
350
350
    }
351
351
  out1:
352
352
    gs_free_object(mem, penum->mask[0].data, "gx_begin_image3x(mask[0].data)");
360
360
check_image3x_extent(floatp mask_coeff, floatp data_coeff)
361
361
{
362
362
    if (mask_coeff == 0)
363
 
        return data_coeff == 0;
 
363
        return data_coeff == 0;
364
364
    if (data_coeff == 0 || (mask_coeff > 0) != (data_coeff > 0))
365
 
        return false;
 
365
        return false;
366
366
    return true;
367
367
}
368
368
/*
373
373
 */
374
374
static bool
375
375
check_image3x_mask(const gs_image3x_t *pim, const gs_image3x_mask_t *pimm,
376
 
                   const image3x_channel_values_t *ppcv,
377
 
                   image3x_channel_values_t *pmcv,
378
 
                   image3x_channel_state_t *pmcs, gs_memory_t *mem)
 
376
                   const image3x_channel_values_t *ppcv,
 
377
                   image3x_channel_values_t *pmcv,
 
378
                   image3x_channel_state_t *pmcs, gs_memory_t *mem)
379
379
{
380
380
    int mask_width = pimm->MaskDict.Width, mask_height = pimm->MaskDict.Height;
381
381
    int code;
382
382
 
383
383
    if (pimm->MaskDict.BitsPerComponent == 0) { /* mask missing */
384
 
        pmcs->depth = 0;
 
384
        pmcs->depth = 0;
385
385
        pmcs->InterleaveType = 0;       /* not a valid type */
386
 
        return 0;
 
386
        return 0;
387
387
    }
388
388
    if (mask_height <= 0)
389
 
        return_error(gs_error_rangecheck);
 
389
        return_error(gs_error_rangecheck);
390
390
    switch (pimm->InterleaveType) {
391
 
        /*case interleave_scan_lines:*/ /* not supported */
392
 
        default:
393
 
            return_error(gs_error_rangecheck);
394
 
        case interleave_chunky:
395
 
            if (mask_width != pim->Width ||
396
 
                mask_height != pim->Height ||
397
 
                pimm->MaskDict.BitsPerComponent != pim->BitsPerComponent ||
398
 
                pim->format != gs_image_format_chunky
399
 
                )
400
 
                return_error(gs_error_rangecheck);
401
 
            break;
402
 
        case interleave_separate_source:
403
 
            switch (pimm->MaskDict.BitsPerComponent) {
404
 
                    case 1: case 2: case 4: case 8: case 12: case 16:
405
 
                break;
406
 
            default:
407
 
                return_error(gs_error_rangecheck);
408
 
            }
 
391
        /*case interleave_scan_lines:*/ /* not supported */
 
392
        default:
 
393
            return_error(gs_error_rangecheck);
 
394
        case interleave_chunky:
 
395
            if (mask_width != pim->Width ||
 
396
                mask_height != pim->Height ||
 
397
                pimm->MaskDict.BitsPerComponent != pim->BitsPerComponent ||
 
398
                pim->format != gs_image_format_chunky
 
399
                )
 
400
                return_error(gs_error_rangecheck);
 
401
            break;
 
402
        case interleave_separate_source:
 
403
            switch (pimm->MaskDict.BitsPerComponent) {
 
404
                    case 1: case 2: case 4: case 8: case 12: case 16:
 
405
                break;
 
406
            default:
 
407
                return_error(gs_error_rangecheck);
 
408
            }
409
409
    }
410
410
    if (!check_image3x_extent(pim->ImageMatrix.xx,
411
 
                              pimm->MaskDict.ImageMatrix.xx) ||
412
 
        !check_image3x_extent(pim->ImageMatrix.xy,
413
 
                              pimm->MaskDict.ImageMatrix.xy) ||
414
 
        !check_image3x_extent(pim->ImageMatrix.yx,
415
 
                              pimm->MaskDict.ImageMatrix.yx) ||
416
 
        !check_image3x_extent(pim->ImageMatrix.yy,
417
 
                              pimm->MaskDict.ImageMatrix.yy)
418
 
        )
419
 
        return_error(gs_error_rangecheck);
 
411
                              pimm->MaskDict.ImageMatrix.xx) ||
 
412
        !check_image3x_extent(pim->ImageMatrix.xy,
 
413
                              pimm->MaskDict.ImageMatrix.xy) ||
 
414
        !check_image3x_extent(pim->ImageMatrix.yx,
 
415
                              pimm->MaskDict.ImageMatrix.yx) ||
 
416
        !check_image3x_extent(pim->ImageMatrix.yy,
 
417
                              pimm->MaskDict.ImageMatrix.yy)
 
418
        )
 
419
        return_error(gs_error_rangecheck);
420
420
    if ((code = gs_matrix_invert(&pimm->MaskDict.ImageMatrix, &pmcv->matrix)) < 0 ||
421
 
        (code = gs_point_transform(mask_width, mask_height,
422
 
                                   &pmcv->matrix, &pmcv->corner)) < 0
423
 
        )
424
 
        return code;
 
421
        (code = gs_point_transform(mask_width, mask_height,
 
422
                                   &pmcv->matrix, &pmcv->corner)) < 0
 
423
        )
 
424
        return code;
425
425
    if (fabs(ppcv->matrix.tx - pmcv->matrix.tx) >= 0.5 ||
426
 
        fabs(ppcv->matrix.ty - pmcv->matrix.ty) >= 0.5 ||
427
 
        fabs(ppcv->corner.x - pmcv->corner.x) >= 0.5 ||
428
 
        fabs(ppcv->corner.y - pmcv->corner.y) >= 0.5
429
 
        )
430
 
        return_error(gs_error_rangecheck);
 
426
        fabs(ppcv->matrix.ty - pmcv->matrix.ty) >= 0.5 ||
 
427
        fabs(ppcv->corner.x - pmcv->corner.x) >= 0.5 ||
 
428
        fabs(ppcv->corner.y - pmcv->corner.y) >= 0.5
 
429
        )
 
430
        return_error(gs_error_rangecheck);
431
431
    pmcv->rect.p.x = ppcv->rect.p.x * mask_width / pim->Width;
432
432
    pmcv->rect.p.y = ppcv->rect.p.y * mask_height / pim->Height;
433
433
    pmcv->rect.q.x = (ppcv->rect.q.x * mask_width + pim->Width - 1) /
434
 
        pim->Width;
 
434
        pim->Width;
435
435
    pmcv->rect.q.y = (ppcv->rect.q.y * mask_height + pim->Height - 1) /
436
 
        pim->Height;
 
436
        pim->Height;
437
437
    /* Initialize the channel state in the enumerator. */
438
438
    pmcs->InterleaveType = pimm->InterleaveType;
439
439
    pmcs->width = pmcv->rect.q.x - pmcv->rect.p.x;
441
441
    pmcs->full_height = pimm->MaskDict.Height;
442
442
    pmcs->depth = pimm->MaskDict.BitsPerComponent;
443
443
    if (pmcs->InterleaveType == interleave_chunky) {
444
 
        /* Allocate a buffer for the data. */
445
 
        pmcs->data =
446
 
            gs_alloc_bytes(mem,
447
 
                           (pmcs->width * pimm->MaskDict.BitsPerComponent + 7) >> 3,
448
 
                           "gx_begin_image3x(mask data)");
449
 
        if (pmcs->data == 0)
450
 
            return_error(gs_error_VMerror);
 
444
        /* Allocate a buffer for the data. */
 
445
        pmcs->data =
 
446
            gs_alloc_bytes(mem,
 
447
                           (pmcs->width * pimm->MaskDict.BitsPerComponent + 7) >> 3,
 
448
                           "gx_begin_image3x(mask data)");
 
449
        if (pmcs->data == 0)
 
450
            return_error(gs_error_VMerror);
451
451
    }
452
452
    pmcs->y = pmcs->skip = 0;
453
453
    return 0;
459
459
 */
460
460
static int
461
461
channel_next(const image3x_channel_state_t *pics1,
462
 
             const image3x_channel_state_t *pics2)
 
462
             const image3x_channel_state_t *pics2)
463
463
{
464
464
    /*
465
465
     * The invariant we need to maintain is that we always have at least as
476
476
 
477
477
#ifdef DEBUG
478
478
    if (current < 0)
479
 
        lprintf4("channel_next invariant fails: %d/%d < %d/%d\n",
480
 
                 pics1->y, pics1->full_height,
481
 
                 pics2->y, pics2->full_height);
 
479
        lprintf4("channel_next invariant fails: %d/%d < %d/%d\n",
 
480
                 pics1->y, pics1->full_height,
 
481
                 pics2->y, pics2->full_height);
482
482
#endif
483
483
    return ((current -= h1) >= 0 ? -1 :
484
 
            current + h2 >= 0 ? 0 : 1);
 
484
            current + h2 >= 0 ? 0 : 1);
485
485
}
486
486
 
487
487
/* Define the default implementation of ImageType 3 processing. */
488
488
static IMAGE3X_MAKE_MID_PROC(make_midx_default); /* check prototype */
489
489
static int
490
490
make_midx_default(gx_device **pmidev, gx_device *dev, int width, int height,
491
 
                 int depth, gs_memory_t *mem)
 
491
                 int depth, gs_memory_t *mem)
492
492
{
493
493
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth);
494
494
    gx_device_memory *midev;
495
495
    int code;
496
496
 
497
497
    if (width != 0)
498
 
        if (height > max_ulong/width)   /* protect against overflow in bitmap size */
499
 
            return_error(gs_error_VMerror);
 
498
        if (height > max_ulong/width)   /* protect against overflow in bitmap size */
 
499
            return_error(gs_error_VMerror);
500
500
    if (mdproto == 0)
501
 
        return_error(gs_error_rangecheck);
 
501
        return_error(gs_error_rangecheck);
502
502
    midev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
503
 
                            "make_mid_default");
 
503
                            "make_mid_default");
504
504
    if (midev == 0)
505
 
        return_error(gs_error_VMerror);
 
505
        return_error(gs_error_VMerror);
506
506
    gs_make_mem_device(midev, mdproto, mem, 0, NULL);
507
507
    midev->bitmap_memory = mem;
508
508
    midev->width = width;
511
511
    gx_device_fill_in_procs((gx_device *)midev);
512
512
    code = dev_proc(midev, open_device)((gx_device *)midev);
513
513
    if (code < 0) {
514
 
        gs_free_object(mem, midev, "make_midx_default");
515
 
        return code;
 
514
        gs_free_object(mem, midev, "make_midx_default");
 
515
        return code;
516
516
    }
517
517
    midev->is_open = true;
518
518
    dev_proc(midev, fill_rectangle)
519
 
        ((gx_device *)midev, 0, 0, width, height, (gx_color_index)0);
 
519
        ((gx_device *)midev, 0, 0, width, height, (gx_color_index)0);
520
520
    *pmidev = (gx_device *)midev;
521
521
    return 0;
522
522
}
523
523
static IMAGE3X_MAKE_MCDE_PROC(make_mcdex_default);  /* check prototype */
524
524
static int
525
525
make_mcdex_default(gx_device *dev, const gs_imager_state *pis,
526
 
                   const gs_matrix *pmat, const gs_image_common_t *pic,
527
 
                   const gs_int_rect *prect, const gx_drawing_color *pdcolor,
528
 
                   const gx_clip_path *pcpath, gs_memory_t *mem,
529
 
                   gx_image_enum_common_t **pinfo,
530
 
                   gx_device **pmcdev, gx_device *midev[2],
531
 
                   gx_image_enum_common_t *pminfo[2],
532
 
                   const gs_int_point origin[2],
533
 
                   const gs_image3x_t *pim)
 
526
                   const gs_matrix *pmat, const gs_image_common_t *pic,
 
527
                   const gs_int_rect *prect, const gx_drawing_color *pdcolor,
 
528
                   const gx_clip_path *pcpath, gs_memory_t *mem,
 
529
                   gx_image_enum_common_t **pinfo,
 
530
                   gx_device **pmcdev, gx_device *midev[2],
 
531
                   gx_image_enum_common_t *pminfo[2],
 
532
                   const gs_int_point origin[2],
 
533
                   const gs_image3x_t *pim)
534
534
{
535
535
    /**************** NYI ****************/
536
536
    /*
541
541
     * that can be freed at the end and that simply forwards all calls.
542
542
     * The most convenient device for this purpose is the bbox device.
543
543
     */
544
 
    gx_device_bbox *bbdev =
545
 
        gs_alloc_struct_immovable(mem, gx_device_bbox, &st_device_bbox,
546
 
                                  "make_mcdex_default");
 
544
    gx_device_bbox *bbdev;
547
545
    int code;
 
546
    cmm_dev_profile_t *icc_array;
 
547
 
 
548
    code = dev_proc(dev, get_profile)(dev, &icc_array);
 
549
    if (code < 0) {
 
550
        return(code);
 
551
    }
 
552
 
 
553
    bbdev = gs_alloc_struct_immovable(mem, gx_device_bbox, &st_device_bbox,
 
554
                                  "make_mcdex_default");
548
555
 
549
556
    if (bbdev == 0)
550
 
        return_error(gs_error_VMerror);
 
557
        return_error(gs_error_VMerror);
 
558
 
551
559
    gx_device_bbox_init(bbdev, dev, mem);
 
560
 
 
561
    bbdev->icc_array = icc_array;
 
562
    rc_increment(bbdev->icc_array);
 
563
 
552
564
    gx_device_bbox_fwd_open_close(bbdev, false);
553
565
    code = dev_proc(bbdev, begin_typed_image)
554
 
        ((gx_device *)bbdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
555
 
         pinfo);
 
566
        ((gx_device *)bbdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
 
567
         pinfo);
556
568
    if (code < 0) {
557
 
        gs_free_object(mem, bbdev, "make_mcdex_default");
558
 
        return code;
 
569
        gs_free_object(mem, bbdev, "make_mcdex_default");
 
570
        return code;
559
571
    }
560
572
    *pmcdev = (gx_device *)bbdev;
561
573
    return 0;
562
574
}
563
575
static int
564
576
gx_begin_image3x(gx_device * dev,
565
 
                const gs_imager_state * pis, const gs_matrix * pmat,
566
 
                const gs_image_common_t * pic, const gs_int_rect * prect,
567
 
                const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
568
 
                gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
 
577
                const gs_imager_state * pis, const gs_matrix * pmat,
 
578
                const gs_image_common_t * pic, const gs_int_rect * prect,
 
579
                const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
 
580
                gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
569
581
{
570
582
    return gx_begin_image3x_generic(dev, pis, pmat, pic, prect, pdcolor,
571
 
                                    pcpath, mem, make_midx_default,
572
 
                                    make_mcdex_default, pinfo);
 
583
                                    pcpath, mem, make_midx_default,
 
584
                                    make_mcdex_default, pinfo);
573
585
}
574
586
 
575
587
/* Process the next piece of an ImageType 3 image. */
576
588
static int
577
589
gx_image3x_plane_data(gx_image_enum_common_t * info,
578
 
                     const gx_image_plane_t * planes, int height,
579
 
                     int *rows_used)
 
590
                     const gx_image_plane_t * planes, int height,
 
591
                     int *rows_used)
580
592
{
581
593
    gx_image3x_enum_t *penum = (gx_image3x_enum_t *) info;
582
594
    int pixel_height = penum->pixel.height;
592
604
    int num_chunky = 0;
593
605
 
594
606
    for (i = 0; i < NUM_MASKS; ++i) {
595
 
        int mh = mask_height[i] = penum->mask[i].height;
 
607
        int mh = mask_height[i] = penum->mask[i].height;
596
608
 
597
 
        mask_plane[i].data = 0;
598
 
        mask_used[i] = 0;
599
 
        if (!penum->mask[i].depth)
600
 
            continue;
601
 
        h1 = min(h1, mh - penum->mask[i].y);
602
 
        if (penum->mask[i].InterleaveType == interleave_chunky)
603
 
            ++num_chunky;
 
609
        mask_plane[i].data = 0;
 
610
        mask_used[i] = 0;
 
611
        if (!penum->mask[i].depth)
 
612
            continue;
 
613
        h1 = min(h1, mh - penum->mask[i].y);
 
614
        if (penum->mask[i].InterleaveType == interleave_chunky)
 
615
            ++num_chunky;
604
616
    }
605
617
    h = min(height, h1);
606
618
    /* Initialized rows_used in case we get an error. */
609
621
/* FIX_ME.  In the soft mask branch
610
622
   the file associated with bug 689290
611
623
   gets into an endless loop.  This
612
 
   is related to the size mismatch of the 
613
 
   soft mask which is 1x1 and the 
 
624
   is related to the size mismatch of the
 
625
   soft mask which is 1x1 and the
614
626
   image size */
615
627
 
616
628
    if (h <= 0)
617
 
#ifdef ENDLESS_LOOP     
618
 
        return 0;
 
629
#ifdef ENDLESS_LOOP
 
630
        return 0;
619
631
#else
620
632
        return 1;
621
633
#endif
622
634
 
623
635
    /* Handle masks from separate sources. */
624
636
    for (i = 0; i < NUM_MASKS; ++i)
625
 
        if (penum->mask[i].InterleaveType == interleave_separate_source) {
626
 
            /*
627
 
             * In order to be able to recover from interruptions, we must
628
 
             * limit separate-source processing to 1 scan line at a time.
629
 
             */
630
 
            if (h > 1)
631
 
                h = 1;
632
 
            mask_plane[i] = planes[pi++];
633
 
        }
 
637
        if (penum->mask[i].InterleaveType == interleave_separate_source) {
 
638
            /*
 
639
             * In order to be able to recover from interruptions, we must
 
640
             * limit separate-source processing to 1 scan line at a time.
 
641
             */
 
642
            if (h > 1)
 
643
                h = 1;
 
644
            mask_plane[i] = planes[pi++];
 
645
        }
634
646
    pixel_planes = &planes[pi];
635
647
 
636
648
    /* Handle chunky masks. */
637
649
    if (num_chunky) {
638
 
        int bpc = penum->bpc;
639
 
        int num_components = penum->num_components;
640
 
        int width = penum->pixel.width;
641
 
        /* Pull apart the source data and the mask data. */
642
 
        /* We do this in the simplest (not fastest) way for now. */
643
 
        uint bit_x = bpc * (num_components + num_chunky) * planes[pi].data_x;
644
 
        sample_load_declare_setup(sptr, sbit, planes[0].data + (bit_x >> 3),
645
 
                                  bit_x & 7, bpc);
646
 
        sample_store_declare_setup(pptr, pbit, pbbyte,
647
 
                                   penum->pixel.data, 0, bpc);
648
 
        sample_store_declare(dptr[NUM_MASKS], dbit[NUM_MASKS],
649
 
                             dbbyte[NUM_MASKS]);
650
 
        int depth[NUM_MASKS];
651
 
        int x;
652
 
 
653
 
        if (h > 1) {
654
 
            /* Do the operation one row at a time. */
655
 
            h = 1;
656
 
        }
657
 
        for (i = 0; i < NUM_MASKS; ++i)
658
 
            if (penum->mask[i].data) {
659
 
                depth[i] = penum->mask[i].depth;
660
 
                mask_plane[i].data = dptr[i] = penum->mask[i].data;
661
 
                mask_plane[i].data_x = 0;
662
 
                /* raster doesn't matter */
663
 
                sample_store_setup(dbit[i], 0, depth[i]);
664
 
                sample_store_preload(dbbyte[i], dptr[i], 0, depth[i]);
665
 
            } else
666
 
                depth[i] = 0;
667
 
        pixel_plane.data = pptr;
668
 
        pixel_plane.data_x = 0;
669
 
        /* raster doesn't matter */
670
 
        pixel_planes = &pixel_plane;
671
 
        for (x = 0; x < width; ++x) {
672
 
            uint value;
673
 
 
674
 
            for (i = 0; i < NUM_MASKS; ++i)
675
 
                if (depth[i]) {
676
 
                    sample_load_next12(value, sptr, sbit, bpc);
677
 
                    sample_store_next12(value, dptr[i], dbit[i], depth[i],
678
 
                                        dbbyte[i]);
679
 
                }
680
 
            for (i = 0; i < num_components; ++i) {
681
 
                sample_load_next12(value, sptr, sbit, bpc);
682
 
                sample_store_next12(value, pptr, pbit, bpc, pbbyte);
683
 
            }
684
 
        }
685
 
        for (i = 0; i < NUM_MASKS; ++i)
686
 
            if (penum->mask[i].data)
687
 
                sample_store_flush(dptr[i], dbit[i], depth[i], dbbyte[i]);
688
 
        sample_store_flush(pptr, pbit, bpc, pbbyte);
689
 
        }
 
650
        int bpc = penum->bpc;
 
651
        int num_components = penum->num_components;
 
652
        int width = penum->pixel.width;
 
653
        /* Pull apart the source data and the mask data. */
 
654
        /* We do this in the simplest (not fastest) way for now. */
 
655
        uint bit_x = bpc * (num_components + num_chunky) * planes[pi].data_x;
 
656
        sample_load_declare_setup(sptr, sbit, planes[0].data + (bit_x >> 3),
 
657
                                  bit_x & 7, bpc);
 
658
        sample_store_declare_setup(pptr, pbit, pbbyte,
 
659
                                   penum->pixel.data, 0, bpc);
 
660
        sample_store_declare(dptr[NUM_MASKS], dbit[NUM_MASKS],
 
661
                             dbbyte[NUM_MASKS]);
 
662
        int depth[NUM_MASKS];
 
663
        int x;
 
664
 
 
665
        if (h > 1) {
 
666
            /* Do the operation one row at a time. */
 
667
            h = 1;
 
668
        }
 
669
        for (i = 0; i < NUM_MASKS; ++i)
 
670
            if (penum->mask[i].data) {
 
671
                depth[i] = penum->mask[i].depth;
 
672
                mask_plane[i].data = dptr[i] = penum->mask[i].data;
 
673
                mask_plane[i].data_x = 0;
 
674
                /* raster doesn't matter */
 
675
                sample_store_setup(dbit[i], 0, depth[i]);
 
676
                sample_store_preload(dbbyte[i], dptr[i], 0, depth[i]);
 
677
            } else
 
678
                depth[i] = 0;
 
679
        pixel_plane.data = pptr;
 
680
        pixel_plane.data_x = 0;
 
681
        /* raster doesn't matter */
 
682
        pixel_planes = &pixel_plane;
 
683
        for (x = 0; x < width; ++x) {
 
684
            uint value;
 
685
 
 
686
            for (i = 0; i < NUM_MASKS; ++i)
 
687
                if (depth[i]) {
 
688
                    sample_load_next12(value, sptr, sbit, bpc);
 
689
                    sample_store_next12(value, dptr[i], dbit[i], depth[i],
 
690
                                        dbbyte[i]);
 
691
                }
 
692
            for (i = 0; i < num_components; ++i) {
 
693
                sample_load_next12(value, sptr, sbit, bpc);
 
694
                sample_store_next12(value, pptr, pbit, bpc, pbbyte);
 
695
            }
 
696
        }
 
697
        for (i = 0; i < NUM_MASKS; ++i)
 
698
            if (penum->mask[i].data)
 
699
                sample_store_flush(dptr[i], dbit[i], depth[i], dbbyte[i]);
 
700
        sample_store_flush(pptr, pbit, bpc, pbbyte);
 
701
        }
690
702
    /*
691
703
     * Process the mask data first, so it will set up the mask
692
704
     * device for clipping the pixel data.
693
705
     */
694
706
    for (i = 0; i < NUM_MASKS; ++i)
695
 
        if (mask_plane[i].data) {
696
 
            /*
697
 
             * If, on the last call, we processed some mask rows
698
 
             * successfully but processing the pixel rows was interrupted,
699
 
             * we set rows_used to indicate the number of pixel rows
700
 
             * processed (since there is no way to return two rows_used
701
 
             * values).  If this happened, some mask rows may get presented
702
 
             * again.  We must skip over them rather than processing them
703
 
             * again.
704
 
             */
705
 
            int skip = penum->mask[i].skip;
706
 
 
707
 
            if (skip >= h) {
708
 
                penum->mask[i].skip = skip - (mask_used[i] = h);
709
 
            } else {
710
 
                int mask_h = h - skip;
711
 
 
712
 
                mask_plane[i].data += skip * mask_plane[i].raster;
713
 
                penum->mask[i].skip = 0;
714
 
                code = gx_image_plane_data_rows(penum->mask[i].info,
715
 
                                                &mask_plane[i],
716
 
                                                mask_h, &mask_used[i]);
717
 
                mask_used[i] += skip;
718
 
            }
719
 
            *rows_used = mask_used[i];
720
 
            penum->mask[i].y += mask_used[i];
721
 
            if (code < 0)
722
 
                return code;
723
 
        }
 
707
        if (mask_plane[i].data) {
 
708
            /*
 
709
             * If, on the last call, we processed some mask rows
 
710
             * successfully but processing the pixel rows was interrupted,
 
711
             * we set rows_used to indicate the number of pixel rows
 
712
             * processed (since there is no way to return two rows_used
 
713
             * values).  If this happened, some mask rows may get presented
 
714
             * again.  We must skip over them rather than processing them
 
715
             * again.
 
716
             */
 
717
            int skip = penum->mask[i].skip;
 
718
 
 
719
            if (skip >= h) {
 
720
                penum->mask[i].skip = skip - (mask_used[i] = h);
 
721
            } else {
 
722
                int mask_h = h - skip;
 
723
 
 
724
                mask_plane[i].data += skip * mask_plane[i].raster;
 
725
                penum->mask[i].skip = 0;
 
726
                code = gx_image_plane_data_rows(penum->mask[i].info,
 
727
                                                &mask_plane[i],
 
728
                                                mask_h, &mask_used[i]);
 
729
                mask_used[i] += skip;
 
730
            }
 
731
            *rows_used = mask_used[i];
 
732
            penum->mask[i].y += mask_used[i];
 
733
            if (code < 0)
 
734
                return code;
 
735
        }
724
736
    if (pixel_planes[0].data) {
725
 
        /*
726
 
         * If necessary, flush any buffered mask data to the mask clipping
727
 
         * device.
728
 
         */
729
 
        for (i = 0; i < NUM_MASKS; ++i)
730
 
            if (penum->mask[i].info)
731
 
                gx_image_flush(penum->mask[i].info);
732
 
        code = gx_image_plane_data_rows(penum->pixel.info, pixel_planes, h,
733
 
                                        &pixel_used);
734
 
        /*
735
 
         * There isn't any way to set rows_used if different amounts of
736
 
         * the mask and pixel data were used.  Fake it.
737
 
         */
738
 
        *rows_used = pixel_used;
739
 
        /*
740
 
         * Don't return code yet: we must account for the fact that
741
 
         * some mask data may have been processed.
742
 
         */
743
 
        penum->pixel.y += pixel_used;
744
 
        if (code < 0) {
745
 
            /*
746
 
             * We must prevent the mask data from being processed again.
747
 
             * We rely on the fact that h > 1 is only possible if the
748
 
             * mask and pixel data have the same Y scaling.
749
 
             */
750
 
            for (i = 0; i < NUM_MASKS; ++i)
751
 
                if (mask_used[i] > pixel_used) {
752
 
                    int skip = mask_used[i] - pixel_used;
 
737
        /*
 
738
         * If necessary, flush any buffered mask data to the mask clipping
 
739
         * device.
 
740
         */
 
741
        for (i = 0; i < NUM_MASKS; ++i)
 
742
            if (penum->mask[i].info)
 
743
                gx_image_flush(penum->mask[i].info);
 
744
        code = gx_image_plane_data_rows(penum->pixel.info, pixel_planes, h,
 
745
                                        &pixel_used);
 
746
        /*
 
747
         * There isn't any way to set rows_used if different amounts of
 
748
         * the mask and pixel data were used.  Fake it.
 
749
         */
 
750
        *rows_used = pixel_used;
 
751
        /*
 
752
         * Don't return code yet: we must account for the fact that
 
753
         * some mask data may have been processed.
 
754
         */
 
755
        penum->pixel.y += pixel_used;
 
756
        if (code < 0) {
 
757
            /*
 
758
             * We must prevent the mask data from being processed again.
 
759
             * We rely on the fact that h > 1 is only possible if the
 
760
             * mask and pixel data have the same Y scaling.
 
761
             */
 
762
            for (i = 0; i < NUM_MASKS; ++i)
 
763
                if (mask_used[i] > pixel_used) {
 
764
                    int skip = mask_used[i] - pixel_used;
753
765
 
754
 
                    penum->mask[i].skip = skip;
755
 
                    penum->mask[i].y -= skip;
756
 
                    mask_used[i] = pixel_used;
757
 
                }
758
 
        }
 
766
                    penum->mask[i].skip = skip;
 
767
                    penum->mask[i].y -= skip;
 
768
                    mask_used[i] = pixel_used;
 
769
                }
 
770
        }
759
771
    }
760
772
    if_debug7('b', "[b]image3x h=%d %sopacity.y=%d %sopacity.y=%d %spixel.y=%d\n",
761
 
              h, (mask_plane[0].data ? "+" : ""), penum->mask[0].y,
762
 
              (mask_plane[1].data ? "+" : ""), penum->mask[1].y,
763
 
              (pixel_planes[0].data ? "+" : ""), penum->pixel.y);
 
773
              h, (mask_plane[0].data ? "+" : ""), penum->mask[0].y,
 
774
              (mask_plane[1].data ? "+" : ""), penum->mask[1].y,
 
775
              (pixel_planes[0].data ? "+" : ""), penum->pixel.y);
764
776
    if (penum->mask[0].depth == 0 || penum->mask[0].y >= penum->mask[0].height) {
765
777
        if (penum->mask[1].depth == 0 || penum->mask[1].y >= penum->mask[1].height) {
766
 
            if (penum->pixel.y >= penum->pixel.height) {
767
 
                return 1;
 
778
            if (penum->pixel.y >= penum->pixel.height) {
 
779
                return 1;
768
780
            }
769
781
        }
770
782
    }
783
795
    int code = gx_image_flush(penum->mask[0].info);
784
796
 
785
797
    if (code >= 0)
786
 
        code = gx_image_flush(penum->mask[1].info);
 
798
        code = gx_image_flush(penum->mask[1].info);
787
799
    if (code >= 0)
788
 
        code = gx_image_flush(penum->pixel.info);
 
800
        code = gx_image_flush(penum->pixel.info);
789
801
    return code;
790
802
}
791
803
 
799
811
     * pixel data.
800
812
     */
801
813
    bool
802
 
        sso = penum->mask[0].InterleaveType == interleave_separate_source,
803
 
        sss = penum->mask[1].InterleaveType == interleave_separate_source;
 
814
        sso = penum->mask[0].InterleaveType == interleave_separate_source,
 
815
        sss = penum->mask[1].InterleaveType == interleave_separate_source;
804
816
 
805
817
    if (sso & sss) {
806
 
        /* Both masks have separate sources. */
807
 
        int mask_next = channel_next(&penum->mask[1], &penum->pixel);
 
818
        /* Both masks have separate sources. */
 
819
        int mask_next = channel_next(&penum->mask[1], &penum->pixel);
808
820
 
809
 
        memset(wanted + 2, (mask_next <= 0 ? 0xff : 0), info->num_planes - 2);
810
 
        wanted[1] = (mask_next >= 0 ? 0xff : 0);
811
 
        if (wanted[1]) {
812
 
            mask_next = channel_next(&penum->mask[0], &penum->mask[1]);
813
 
            wanted[0] = mask_next >= 0;
814
 
        } else
815
 
            wanted[0] = 0;
816
 
        return false;           /* see below */
 
821
        memset(wanted + 2, (mask_next <= 0 ? 0xff : 0), info->num_planes - 2);
 
822
        wanted[1] = (mask_next >= 0 ? 0xff : 0);
 
823
        if (wanted[1]) {
 
824
            mask_next = channel_next(&penum->mask[0], &penum->mask[1]);
 
825
            wanted[0] = mask_next >= 0;
 
826
        } else
 
827
            wanted[0] = 0;
 
828
        return false;           /* see below */
817
829
    } else if (sso | sss) {
818
 
        /* Only one separate source. */
819
 
        const image3x_channel_state_t *pics =
820
 
            (sso ? &penum->mask[0] : &penum->mask[1]);
821
 
        int mask_next = channel_next(pics, &penum->pixel);
 
830
        /* Only one separate source. */
 
831
        const image3x_channel_state_t *pics =
 
832
            (sso ? &penum->mask[0] : &penum->mask[1]);
 
833
        int mask_next = channel_next(pics, &penum->pixel);
822
834
 
823
 
        wanted[0] = (mask_next >= 0 ? 0xff : 0);
824
 
        memset(wanted + 1, (mask_next <= 0 ? 0xff : 0), info->num_planes - 1);
825
 
        /*
826
 
         * In principle, wanted will always be true for both mask and pixel
827
 
         * data if the full_heights are equal.  Unfortunately, even in this
828
 
         * case, processing may be interrupted after a mask row has been
829
 
         * passed to the underlying image processor but before the data row
830
 
         * has been passed, in which case pixel data will be 'wanted', but
831
 
         * not mask data, for the next call.  Therefore, we must return
832
 
         * false.
833
 
         */
834
 
        return false
835
 
            /*(next == 0 &&
836
 
              pics->full_height == penum->pixel.full_height)*/;
 
835
        wanted[0] = (mask_next >= 0 ? 0xff : 0);
 
836
        memset(wanted + 1, (mask_next <= 0 ? 0xff : 0), info->num_planes - 1);
 
837
        /*
 
838
         * In principle, wanted will always be true for both mask and pixel
 
839
         * data if the full_heights are equal.  Unfortunately, even in this
 
840
         * case, processing may be interrupted after a mask row has been
 
841
         * passed to the underlying image processor but before the data row
 
842
         * has been passed, in which case pixel data will be 'wanted', but
 
843
         * not mask data, for the next call.  Therefore, we must return
 
844
         * false.
 
845
         */
 
846
        return false
 
847
            /*(next == 0 &&
 
848
              pics->full_height == penum->pixel.full_height)*/;
837
849
    } else {
838
 
        /* Everything is chunky, only 1 plane. */
839
 
        wanted[0] = 0xff;
840
 
        return true;
 
850
        /* Everything is chunky, only 1 plane. */
 
851
        wanted[0] = 0xff;
 
852
        return true;
841
853
    }
842
854
}
843
855
 
849
861
    gs_memory_t *mem = penum->memory;
850
862
    gx_device *mdev0 = penum->mask[0].mdev;
851
863
    int ocode =
852
 
        (penum->mask[0].info ? gx_image_end(penum->mask[0].info, draw_last) :
853
 
         0);
 
864
        (penum->mask[0].info ? gx_image_end(penum->mask[0].info, draw_last) :
 
865
         0);
854
866
    gx_device *mdev1 = penum->mask[1].mdev;
855
867
    int scode =
856
 
        (penum->mask[1].info ? gx_image_end(penum->mask[1].info, draw_last) :
857
 
         0);
 
868
        (penum->mask[1].info ? gx_image_end(penum->mask[1].info, draw_last) :
 
869
         0);
858
870
    gx_device *pcdev = penum->pcdev;
859
871
    int pcode = gx_image_end(penum->pixel.info, draw_last);
860
872
 
 
873
    rc_decrement(pcdev->icc_array, "gx_image3x_end_image(pcdev->icc_array)");
 
874
    pcdev->icc_array = NULL;
 
875
 
861
876
    gs_closedevice(pcdev);
862
877
    if (mdev0)
863
 
        gs_closedevice(mdev0);
 
878
        gs_closedevice(mdev0);
864
879
    if (mdev1)
865
 
        gs_closedevice(mdev1);
 
880
        gs_closedevice(mdev1);
866
881
    gs_free_object(mem, penum->mask[0].data,
867
 
                   "gx_image3x_end_image(mask[0].data)");
 
882
                   "gx_image3x_end_image(mask[0].data)");
868
883
    gs_free_object(mem, penum->mask[1].data,
869
 
                   "gx_image3x_end_image(mask[1].data)");
 
884
                   "gx_image3x_end_image(mask[1].data)");
870
885
    gs_free_object(mem, penum->pixel.data,
871
 
                   "gx_image3x_end_image(pixel.data)");
 
886
                   "gx_image3x_end_image(pixel.data)");
872
887
    gs_free_object(mem, pcdev, "gx_image3x_end_image(pcdev)");
873
888
    gs_free_object(mem, mdev0, "gx_image3x_end_image(mask[0].mdev)");
874
889
    gs_free_object(mem, mdev1, "gx_image3x_end_image(mask[1].mdev)");