Commit message: None
CVE: CVE-2016-10218
CWE: CWE-476
Vulnerability description: The pdf14_pop_transparency_group function in base/gdevp14.c in the PDF Transparency module in Artifex Software, Inc. Ghostscript 9.20 allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) via a crafted file.

Project: ghostscript
File: gdevp14.c

c_pdf14trans_clist_read_update(gs_composite_t *	pcte, gx_device	* cdev,
                gx_device * tdev, gs_gstate * pgs, gs_memory_t * mem)
{
    pdf14_device * p14dev = (pdf14_device *)tdev;
    gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
    gs_devn_params * pclist_devn_params;
    gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)cdev;
    cmm_profile_t *cl_icc_profile, *p14_icc_profile;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;

    dev_proc(cdev, get_profile)(cdev,  &dev_profile);
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &cl_icc_profile,
                          &render_cond);
    dev_proc(p14dev, get_profile)((gx_device *)p14dev,  &dev_profile);
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &p14_icc_profile,
                          &render_cond);
    /*
     * We only handle the push/pop operations. Save and restore the color_info
     * field for the clist device.  (This is needed since the process color
     * model of the clist device needs to match the PDF 1.4 compositing
     * device.
     */
    switch (pdf14pct->params.pdf14_op) {
        case PDF14_PUSH_DEVICE:
            /* If the CMM is not threadsafe, then the pdf14 device actually
               needs to inherit the ICC profile from the clist thread device
               not the target device.   */
#if !CMM_THREAD_SAFE
            gx_monitor_enter(p14_icc_profile->lock);
            rc_assign(p14dev->icc_struct->device_profile[0], cl_icc_profile,
                      "c_pdf14trans_clist_read_update");
            gx_monitor_leave(p14_icc_profile->lock);
#endif
            /*
             * If we are blending using spot colors (i.e. the output device
             * supports spot colors) then we need to transfer
             * color info from the clist PDF 1.4 compositing reader device
             * to the clist writer PDF 1.4 compositing device.
             * This info was transfered from that device to the output
             * device as a set of device parameters.  However the clist
             * reader PDF 1.4 compositing device did not exist when the
             * device parameters were read from the clist.  So that info
             * was buffered into the output device.
             */
            pclist_devn_params = dev_proc(cdev, ret_devn_params)(cdev);
            if (pclist_devn_params != NULL && pclist_devn_params->page_spot_colors != 0) {
                int num_comp = p14dev->color_info.num_components;
                /*
                 * The number of components for the PDF14 device is the sum
                 * of the process components and the number of spot colors
                 * for the page.  If the color capabilities of the parent
                 * device (which coming into this are the same as the p14dev)
                 * are smaller than the number of page spot colors then
                 * use that for the number of components. Otherwise use
                 * the page_spot_colors.
                 */
                p14dev->devn_params.page_spot_colors =
                    pclist_devn_params->page_spot_colors;
                if (num_comp < p14dev->devn_params.page_spot_colors + 4 ) {
                    p14dev->color_info.num_components = num_comp;
                } else {
                    p14dev->color_info.num_components =
                        p14dev->devn_params.num_std_colorant_names +
                        p14dev->devn_params.page_spot_colors;
                }
                /* Transfer the data for the spot color names
                   But we have to free what may be there before we do this */
                devn_free_params((gx_device*) p14dev);
                p14dev->devn_params.separations =
                    pclist_devn_params->pdf14_separations;
                p14dev->free_devicen = false;  /* to avoid freeing the clist ones */
                if (num_comp != p14dev->color_info.num_components) {
                    /* When the pdf14 device is opened it creates a context
                       and some soft mask related objects.  The push device
                       compositor action will have already created these but
                       they are the wrong size.  We must destroy them though
                       before reopening the device */
                    if (p14dev->ctx != NULL) {
                        pdf14_ctx_free(p14dev->ctx);
                    }
                    dev_proc(tdev, open_device) (tdev);
                }
            }
            /* Check if we need to swap out the ICC profile for the pdf14
               device.  This will occur if our source profile for our device
               happens to be something like CIELAB.  Then we will blend in
               RGB (unless a trans group is specified) */
            if (cl_icc_profile->data_cs == gsCIELAB || cl_icc_profile->islab) {
                cl_icc_profile =
                    gsicc_read_serial_icc(cdev, pcrdev->trans_dev_icc_hash);
                /* Keep a pointer to the clist device */
                cl_icc_profile->dev = (gx_device *) cdev;
                gx_monitor_enter(p14_icc_profile->lock);
                rc_assign(p14dev->icc_struct->device_profile[0], cl_icc_profile,
                          "c_pdf14trans_clist_read_update");
                /* Initial ref count was ok.  remove increment from assign */
                rc_decrement(p14dev->icc_struct->device_profile[0],
                             "c_pdf14trans_clist_read_update");
                gx_monitor_leave(p14_icc_profile->lock);
            }
            break;

        case PDF14_POP_DEVICE:
#	    if 0 /* Disabled because *p14dev has no forwarding methods during
                    the clist playback. This code is not executed while clist
                    writing. */
            cdev->color_info = p14dev->saved_target_color_info;
#	    endif
            break;

        default:
            break;		/* do nothing for remaining ops */
    }

    return 0;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
                gx_device ** pcdev, gs_gstate * pgs, gs_memory_t * mem)
{
    gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer;
    const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pcte;
    int code = 0;

    /* We only handle the push/pop operations */
    switch (pdf14pct->params.pdf14_op) {
        case PDF14_PUSH_DEVICE:
            return gs_pdf14_clist_device_push(mem, pgs, pcdev, dev, pdf14pct);

        case PDF14_POP_DEVICE:
#	    if 0 /* Disabled because pdf14_clist_create_compositor does so. */
            /*
             * Ensure that the tranfer functions, etc.  are current before we
             * dump our transparency image to the output device.
             */
            if (pgs->dev_ht)
                code = cmd_put_halftone((gx_device_clist_writer *)
                           (((pdf14_clist_device *)dev)->target), pgs->dev_ht);
#	    else
            code = 0;
#	    endif
            code = clist_writer_check_empty_cropping_stack(cdev);
            break;

        case PDF14_BEGIN_TRANS_GROUP:
            {	/* HACK: store mask_id into our params for subsequent
                   calls of c_pdf14trans_write. To do this we must
                   break const. */
                gs_pdf14trans_t * pdf14pct_noconst;

                pdf14pct_noconst = (gs_pdf14trans_t *) pcte;
                /* What ever the current mask ID is, that is the
                   softmask group through which this transparency
                   group must be rendered. Store it now. */
                pdf14pct_noconst->params.mask_id = cdev->mask_id;
                if_debug1m('v', pgs->memory,
                           "[v]c_pdf14trans_clist_write_update group mask_id=%d \n",
                           cdev->mask_id);
            }
            break;
        case PDF14_END_TRANS_GROUP:
            code = 0; /* A place for breakpoint. */
            break;
        case PDF14_BEGIN_TRANS_MASK:
            /* A new mask has been started */
            cdev->mask_id = ++cdev->mask_id_count;
            /* replacing is set everytime that we
               have a zpushtransparencymaskgroup */
            {	/* HACK: store mask_id into our params for subsequent
                   calls of c_pdf14trans_write. To do this we must
                   break const. */
                gs_pdf14trans_t * pdf14pct_noconst;

                pdf14pct_noconst = (gs_pdf14trans_t *) pcte;
                pdf14pct_noconst->params.mask_id = cdev->mask_id;
                if_debug1m('v', pgs->memory,
                           "[v]c_pdf14trans_clist_write_update mask mask_id=%d \n",
                           cdev->mask_id);
            }
            break;
        case PDF14_END_TRANS_MASK:
            code = 0; /* A place for breakpoint. */
            break;
        case PDF14_PUSH_TRANS_STATE:
            code = 0; /* A place for breakpoint. */
            break;
        case PDF14_POP_TRANS_STATE:
            code = 0; /* A place for breakpoint. */
            break;
        case PDF14_ABORT_DEVICE:
            code = 0;
            break;
        case PDF14_PUSH_SMASK_COLOR:
            return 0;
            break;
        case PDF14_POP_SMASK_COLOR:
            return 0;
            break;
        default:
            break;		/* do nothing for remaining ops */
    }
    *pcdev = dev;
    if (code < 0)
        return code;
    /* See c_pdf14trans_write, c_pdf14trans_adjust_ctm, and
       apply_create_compositor. */
    code = gs_gstate_setmatrix(&cdev->gs_gstate, &pdf14pct->params.ctm);
    /* Wrote an extra ctm. */
    cmd_clear_known(cdev, ctm_known);

    return code;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_create_default_compositor(const gs_composite_t * pct,
    gx_device ** pp14dev, gx_device * tdev, gs_gstate * pgs,
    gs_memory_t * mem)
{
    const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
    gx_device * p14dev = NULL;
    int code = 0;

    /*
     * We only handle the push operation.  All other operations are ignored.
     * The other operations will be handled by the create_compositor routine
     * for the PDF 1.4 compositing device.
     */
    switch (pdf14pct->params.pdf14_op) {
        case PDF14_PUSH_DEVICE:
            code = gs_pdf14_device_push(mem, pgs, &p14dev, tdev, pdf14pct);
            *pp14dev = p14dev;
            break;
        default:
            *pp14dev = tdev;
            break;
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_equal(const gs_composite_t	* pct0,	const gs_composite_t * pct1)
{
    return false;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_get_cropping(const gs_composite_t *pcte, int *ry, int *rheight,
                          int cropping_min, int cropping_max)
{
    gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
    switch (pdf14pct->params.pdf14_op) {
        case PDF14_PUSH_DEVICE: return ALLBANDS; /* Applies to all bands. */
        case PDF14_POP_DEVICE:  return ALLBANDS; /* Applies to all bands. */
        case PDF14_ABORT_DEVICE: return ALLBANDS; /* Applies to all bands */
        case PDF14_BEGIN_TRANS_GROUP:
            {	gs_int_rect rect;

                pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm,
                                                &pdf14pct->params.bbox, &rect);
                /* We have to crop this by the parent object.   */
                *ry = max(rect.p.y, cropping_min);
                *rheight = min(rect.q.y, cropping_max) - *ry;
                return PUSHCROP; /* Push cropping. */
            }
        case PDF14_BEGIN_TRANS_MASK:
            {	gs_int_rect rect;

                pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm,
                                                    &pdf14pct->params.bbox, &rect);
                /* We have to crop this by the parent object and worry about the BC outside
                   the range, except for image SMask which don't affect areas outside the image */
                if ( pdf14pct->params.GrayBackground == 1.0 || pdf14pct->params.mask_is_image) {
                    /* In this case there will not be a background effect to
                       worry about.  The mask will not have any effect outside
                       the bounding box.  This is NOT the default or common case. */
                    *ry = max(rect.p.y, cropping_min);
                    *rheight = min(rect.q.y, cropping_max) - *ry;
                    return PUSHCROP; /* Push cropping. */
                }  else {
                    /* We need to make the soft mask range as large as the parent
                       due to the fact that the background color can have an impact
                       OUTSIDE the bounding box of the soft mask */
                    *ry = cropping_min;
                    *rheight = cropping_max - cropping_min;
                    if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None)
                        return SAMEAS_PUSHCROP_BUTNOPUSH;
                    else
                        return PUSHCROP; /* Push cropping. */
                }
            }
        case PDF14_END_TRANS_GROUP: return POPCROP; /* Pop cropping. */
        case PDF14_END_TRANS_MASK: return POPCROP;   /* Pop the cropping */
        case PDF14_PUSH_TRANS_STATE: return CURRBANDS;
        case PDF14_POP_TRANS_STATE: return CURRBANDS;
        case PDF14_SET_BLEND_PARAMS: return ALLBANDS;
        case PDF14_PUSH_SMASK_COLOR: return POPCROP; /* Pop cropping. */
        case PDF14_POP_SMASK_COLOR: return POPCROP;   /* Pop the cropping */
    }
    return ALLBANDS;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_is_closing(const gs_composite_t * composite_action, gs_composite_t ** ppcte,
                        gx_device *dev)
{
    gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action;
    int op0 = pct0->params.pdf14_op;

    switch (op0) {
        default: return_error(gs_error_unregistered); /* Must not happen. */
        case PDF14_PUSH_DEVICE:
            return COMP_ENQUEUE;
        case PDF14_ABORT_DEVICE:
            return COMP_ENQUEUE;
        case PDF14_POP_DEVICE:
            if (*ppcte == NULL)
                return COMP_ENQUEUE;
            else {
                gs_compositor_closing_state state = find_opening_op(PDF14_PUSH_DEVICE, ppcte, COMP_EXEC_IDLE);

                if (state == COMP_EXEC_IDLE)
                    return COMP_DROP_QUEUE;
                return state;
            }
        case PDF14_BEGIN_TRANS_GROUP:
            return COMP_ENQUEUE;
        case PDF14_END_TRANS_GROUP:
            if (*ppcte == NULL)
                return COMP_EXEC_QUEUE;
            return find_opening_op(PDF14_BEGIN_TRANS_GROUP, ppcte, COMP_MARK_IDLE);
        case PDF14_BEGIN_TRANS_MASK:
            return COMP_ENQUEUE;
        case PDF14_PUSH_TRANS_STATE:
            return COMP_ENQUEUE;
        case PDF14_POP_TRANS_STATE:
            return COMP_ENQUEUE;
        case PDF14_PUSH_SMASK_COLOR:
            return COMP_ENQUEUE;
            break;
        case PDF14_POP_SMASK_COLOR:
            return COMP_ENQUEUE;
            break;
        case PDF14_END_TRANS_MASK:
            if (*ppcte == NULL)
                return COMP_EXEC_QUEUE;
            return find_opening_op(PDF14_BEGIN_TRANS_MASK, ppcte, COMP_MARK_IDLE);
        case PDF14_SET_BLEND_PARAMS:
            if (*ppcte == NULL)
                return COMP_ENQUEUE;
            /* hack : ignore csel - here it is always zero : */
            return find_same_op(composite_action, PDF14_SET_BLEND_PARAMS, ppcte);
    }
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_is_friendly(const gs_composite_t * composite_action, byte cmd0, byte cmd1)
{
    gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action;
    int op0 = pct0->params.pdf14_op;

    if (op0 == PDF14_PUSH_DEVICE || op0 == PDF14_END_TRANS_GROUP) {
        /* Halftone commands are always passed to the target printer device,
           because transparency buffers are always contone.
           So we're safe to execute them before queued transparency compositors. */
        if (cmd0 == cmd_opv_extend && (cmd1 == cmd_opv_ext_put_halftone ||
                                       cmd1 == cmd_opv_ext_put_ht_seg))
            return true;
        if (cmd0 == cmd_opv_set_misc && (cmd1 >> 6) == (cmd_set_misc_map >> 6))
            return true;
    }
    return false;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_read(gs_composite_t * * ppct, const byte *	data,
                                uint size, gs_memory_t * mem )
{
    gs_pdf14trans_params_t params = {0};
    const byte * start = data;
    int used, code = 0;

    if (size < 1)
        return_error(gs_error_rangecheck);

    /* Read PDF 1.4 compositor data from the clist */
    params.pdf14_op = *data++;
    if_debug2m('v', mem, "[v] c_pdf14trans_read: opcode = %s  avail = %d",
               pdf14_opcode_names[params.pdf14_op], size);
    memset(&params.ctm, 0, sizeof(params.ctm));
    switch (params.pdf14_op) {
        default:			/* Should not occur. */
            break;
        case PDF14_PUSH_DEVICE:
            read_value(data, params.num_spot_colors);
            read_value(data, params.is_pattern);
            break;
        case PDF14_ABORT_DEVICE:
            break;
        case PDF14_POP_DEVICE:
            read_value(data, params.is_pattern);
            break;
        case PDF14_END_TRANS_GROUP:
            code += 0; /* A good place for a breakpoint. */
            break;			/* No data */
        case PDF14_PUSH_TRANS_STATE:
            break;
        case PDF14_POP_TRANS_STATE:
            break;
        case PDF14_BEGIN_TRANS_GROUP:
            /*
             * We are currently not using the bbox or the colorspace so they were
             * not placed in the clist
             */
            data = cmd_read_matrix(&params.ctm, data);
            params.Isolated = (*data) & 1;
            params.Knockout = (*data++ >> 1) & 1;
            params.blend_mode = *data++;
            params.group_color = *data++;  /* Trans group color */
            read_value(data,params.group_color_numcomps);  /* color group size */
            read_value(data, params.opacity.alpha);
            read_value(data, params.shape.alpha);
            read_value(data, params.bbox);
            read_value(data, params.mask_id);
            read_value(data, params.icc_hash);
            break;
        case PDF14_BEGIN_TRANS_MASK:
                /* This is the largest transparency parameter at this time (potentially
                 * 1531 bytes in size if Background_components =
                 * GS_CLIENT_COLOR_MAX_COMPONENTS and Matte_components =
                 * GS_CLIENT_COLOR_MAX_COMPONENTS and we have a transfer function as well).
                 *
                 * NOTE:
                 * The clist reader must be able to handle this sized device.
                 * If any changes are made here the #define MAX_CLIST_COMPOSITOR_SIZE
                 * may also need to be changed correspondingly (defined in gstparam.h)
                 * Also... if another compositor param should exceed this size, this
                 * same condition applies.
                 */
            data = cmd_read_matrix(&params.ctm, data);
            read_value(data, params.subtype);
            params.group_color = *data++;
            read_value(data, params.group_color_numcomps);
            params.replacing = *data++;
            params.function_is_identity = *data++;
            params.Background_components = *data++;
            params.Matte_components = *data++;
            read_value(data, params.bbox);
            read_value(data, params.mask_id);
            if (params.Background_components) {
                const int l = sizeof(params.Background[0]) * params.Background_components;

                memcpy(params.Background, data, l);
                data += l;
                memcpy(&params.GrayBackground, data, sizeof(params.GrayBackground));
                data += sizeof(params.GrayBackground);
            }
            if (params.Matte_components) {
                const int m = sizeof(params.Matte[0]) * params.Matte_components;

                memcpy(params.Matte, data, m);
                data += m;
            }
            read_value(data, params.icc_hash);
            if (params.function_is_identity) {
                int i;

                for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
                    params.transfer_fn[i] = (byte)floor(i *
                        (255.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)) + 0.5);
                }
            } else {
                read_value(data, params.transfer_fn);
            }
            break;
        case PDF14_END_TRANS_MASK:
            break;
        case PDF14_PUSH_SMASK_COLOR:
            return 0;
            break;
        case PDF14_POP_SMASK_COLOR:
            return 0;
            break;
        case PDF14_SET_BLEND_PARAMS:
            params.changed = *data++;
            if (params.changed & PDF14_SET_BLEND_MODE)
                params.blend_mode = *data++;
            if (params.changed & PDF14_SET_TEXT_KNOCKOUT)
                params.text_knockout = *data++;
            if (params.changed & PDF14_SET_OPACITY_ALPHA)
                read_value(data, params.opacity.alpha);
            if (params.changed & PDF14_SET_SHAPE_ALPHA)
                read_value(data, params.shape.alpha);
            if (params.changed & PDF14_SET_OVERPRINT)
                read_value(data, params.overprint);
            if (params.changed & PDF14_SET_OVERPRINT_MODE)
                read_value(data, params.overprint_mode);
            break;
    }
    code = gs_create_pdf14trans(ppct, &params, mem);
    if (code < 0)
        return code;
    used = data - start;
    if_debug2m('v', mem, " mask_id=%d used = %d\n", params.mask_id, used);

    /* If we read more than the maximum expected, return a rangecheck error */
    if ( used + 3 > MAX_CLIST_COMPOSITOR_SIZE )
        return_error(gs_error_rangecheck);
    else
        return used;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_write(const gs_composite_t	* pct, byte * data, uint * psize,
                   gx_device_clist_writer *cdev)
{
    const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params;
    int need, avail = *psize;
    byte buf[MAX_CLIST_TRANSPARENCY_BUFFER_SIZE]; /* Must be large enough
        to fit the data written below. We don't implement a dynamic check for
        the buffer owerflow, assuming that the consistency is verified in the
        coding phase. See the definition of MAX_CLIST_TRANSPARENCY_BUFFER_SIZE. */
    byte * pbuf = buf;
    int opcode = pparams->pdf14_op;
    int mask_size = 0;
    uint mask_id = 0;
    int code;
    bool found_icc;
    int64_t hashcode = 0;
    cmm_profile_t *icc_profile;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;
    /* We maintain and update working copies until we actually write the clist */
    int pdf14_needed = cdev->pdf14_needed;
    int trans_group_level = cdev->pdf14_trans_group_level;
    int smask_level = cdev->pdf14_smask_level;

    code = dev_proc((gx_device *) cdev, get_profile)((gx_device *) cdev,
                                                     &dev_profile);
    if (code < 0)
        return code;
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
                          &render_cond);
    *pbuf++ = opcode;			/* 1 byte */
    switch (opcode) {
        default:			/* Should not occur. */
            break;
        case PDF14_PUSH_DEVICE:
            trans_group_level = 0;
            cdev->pdf14_smask_level = 0;
            cdev->page_pdf14_needed = false;
            put_value(pbuf, pparams->num_spot_colors);
            put_value(pbuf, pparams->is_pattern);
            /* If we happen to be going to a color space like CIELAB then
               we are going to do our blending in default RGB and convert
               to CIELAB at the end.  To do this, we need to store the
               default RGB profile in the clist so that we can grab it
               later on during the clist read back and put image command */
            if (icc_profile->data_cs == gsCIELAB || icc_profile->islab) {
                /* Get the default RGB profile.  Set the device hash code
                   so that we can extract it during the put_image operation. */
                cdev->trans_dev_icc_hash = pparams->iccprofile->hashcode;
                found_icc =
                    clist_icc_searchtable(cdev, pparams->iccprofile->hashcode);
                if (!found_icc) {
                    /* Add it to the table */
                    clist_icc_addentry(cdev, pparams->iccprofile->hashcode,
                                       pparams->iccprofile);
                }
            }
            break;
        case PDF14_POP_DEVICE:
            pdf14_needed = false;		/* reset pdf14_needed */
            trans_group_level = 0;
            smask_level = 0;
            put_value(pbuf, pparams->is_pattern);
            break;
        case PDF14_END_TRANS_GROUP:
            trans_group_level--;	/* if now at page level, pdf14_needed will be updated */
            if (smask_level == 0 && trans_group_level == 0)
                pdf14_needed = cdev->page_pdf14_needed;
            break;			/* No data */
        case PDF14_BEGIN_TRANS_GROUP:
            pdf14_needed = true;		/* the compositor will be needed while reading */
            trans_group_level++;
            code = c_pdf14trans_write_ctm(&pbuf, pparams);
            if (code < 0)
                return code;
            *pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1);
            *pbuf++ = pparams->blend_mode;
            *pbuf++ = pparams->group_color;
            put_value(pbuf, pparams->group_color_numcomps);
            put_value(pbuf, pparams->opacity.alpha);
            put_value(pbuf, pparams->shape.alpha);
            put_value(pbuf, pparams->bbox);
            mask_id = pparams->mask_id;
            put_value(pbuf, mask_id);
            /* Color space information maybe ICC based
               in this case we need to store the ICC
               profile or the ID if it is cached already */
            if (pparams->group_color == ICC) {
                /* Check if it is already in the ICC clist table */
                hashcode = pparams->iccprofile->hashcode;
                found_icc = clist_icc_searchtable(cdev, hashcode);
                if (!found_icc) {
                    /* Add it to the table */
                    clist_icc_addentry(cdev, hashcode, pparams->iccprofile);
                    put_value(pbuf, hashcode);
                } else {
                    /* It will be in the clist. Just write out the hashcode */
                    put_value(pbuf, hashcode);
                }
            } else {
                put_value(pbuf, hashcode);
            }
            break;
        case PDF14_BEGIN_TRANS_MASK:
            if (pparams->subtype != TRANSPARENCY_MASK_None) {
                pdf14_needed = true;		/* the compositor will be needed while reading */
                smask_level++;
            }
            code = c_pdf14trans_write_ctm(&pbuf, pparams);
            if (code < 0)
                return code;
            put_value(pbuf, pparams->subtype);
            *pbuf++ = pparams->group_color;
            put_value(pbuf, pparams->group_color_numcomps);
            *pbuf++ = pparams->replacing;
            *pbuf++ = pparams->function_is_identity;
            *pbuf++ = pparams->Background_components;
            *pbuf++ = pparams->Matte_components;
            put_value(pbuf, pparams->bbox);
            mask_id = pparams->mask_id;
            put_value(pbuf, mask_id);
            if (pparams->Background_components) {
                const int l = sizeof(pparams->Background[0]) * pparams->Background_components;

                memcpy(pbuf, pparams->Background, l);
                pbuf += l;
                memcpy(pbuf, &pparams->GrayBackground, sizeof(pparams->GrayBackground));
                pbuf += sizeof(pparams->GrayBackground);
            }
            if (pparams->Matte_components) {
                const int m = sizeof(pparams->Matte[0]) * pparams->Matte_components;

                memcpy(pbuf, pparams->Matte, m);
                pbuf += m;
            }
            if (!pparams->function_is_identity)
                mask_size = sizeof(pparams->transfer_fn);
            /* Color space information may be ICC based
               in this case we need to store the ICC
               profile or the ID if it is cached already */
            if (pparams->group_color == ICC) {
                /* Check if it is already in the ICC clist table */
                hashcode = pparams->iccprofile->hashcode;
                found_icc = clist_icc_searchtable(cdev, hashcode);
                if (!found_icc) {
                    /* Add it to the table */
                    clist_icc_addentry(cdev, hashcode, pparams->iccprofile);
                    put_value(pbuf, hashcode);
                } else {
                    /* It will be in the clist. Just write out the hashcode */
                    put_value(pbuf, hashcode);
                }
            } else {
                put_value(pbuf, hashcode);
            }
            break;
        case PDF14_END_TRANS_MASK:
            smask_level--;
            if (smask_level == 0 && trans_group_level == 0)
                pdf14_needed = cdev->page_pdf14_needed;
            break;
        case PDF14_SET_BLEND_PARAMS:
            if (pparams->blend_mode != BLEND_MODE_Normal || pparams->opacity.alpha != 1.0 ||
                pparams->shape.alpha != 1.0)
                pdf14_needed = true;		/* the compositor will be needed while reading */
            else if (smask_level == 0 && trans_group_level == 0)
                pdf14_needed = false;		/* At page level, set back to false */
            if (smask_level == 0 && trans_group_level == 0)
                cdev->page_pdf14_needed = pdf14_needed;         /* save for after popping to page level */
            *pbuf++ = pparams->changed;
            if (pparams->changed & PDF14_SET_BLEND_MODE)
                *pbuf++ = pparams->blend_mode;
            if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT)
                *pbuf++ = pparams->text_knockout;
            if (pparams->changed & PDF14_SET_OPACITY_ALPHA)
                put_value(pbuf, pparams->opacity.alpha);
            if (pparams->changed & PDF14_SET_SHAPE_ALPHA)
                put_value(pbuf, pparams->shape.alpha);
            if (pparams->changed & PDF14_SET_OVERPRINT)
                put_value(pbuf, pparams->overprint);
            if (pparams->changed & PDF14_SET_OVERPRINT_MODE)
                put_value(pbuf, pparams->overprint_mode);
            break;
        case PDF14_PUSH_TRANS_STATE:
            break;
        case PDF14_POP_TRANS_STATE:
            break;
        case PDF14_PUSH_SMASK_COLOR:
            return 0;   /* We really should never be here */
            break;
        case PDF14_POP_SMASK_COLOR:
            return 0;   /* We really should never be here */
            break;
    }

    /* check for fit */
    need = (pbuf - buf) + mask_size;
    *psize = need;
    if (need > avail) {
        if (avail)
            return_error(gs_error_rangecheck);
        else
            return gs_error_rangecheck;
    }

    /* If we are writing more than the maximum ever expected,
     * return a rangecheck error. Second check is for Coverity
     */
    if ((need + 3 > MAX_CLIST_COMPOSITOR_SIZE) ||
        (need + 3 - mask_size > MAX_CLIST_TRANSPARENCY_BUFFER_SIZE) )
        return_error(gs_error_rangecheck);

    /* Copy our serialized data into the output buffer */
    memcpy(data, buf, need - mask_size);
    if (mask_size)	/* Include the transfer mask data if present */
        memcpy(data + need - mask_size, pparams->transfer_fn, mask_size);
    if_debug3m('v', cdev->memory,
               "[v] c_pdf14trans_write: opcode = %s mask_id=%d need = %d\n",
               pdf14_opcode_names[opcode], mask_id, need);
    cdev->pdf14_needed = pdf14_needed;          /* all OK to update */
    cdev->pdf14_trans_group_level = trans_group_level;
    cdev->pdf14_smask_level = smask_level;
    return 0;
}

Project: ghostscript
File: gdevp14.c

c_pdf14trans_write_ctm(byte **ppbuf, const gs_pdf14trans_params_t *pparams)
{
    /* Note: We can't skip writing CTM if it is equal to pgs->ctm,
       because clist writer may skip this command for some bands.
       For a better result we need individual CTM for each band.
     */
    byte *pbuf = *ppbuf;
    int len, code;

    len = cmd_write_ctm_return_length_nodevice(&pparams->ctm);
    pbuf--; /* For cmd_write_ctm. */
    code = cmd_write_ctm(&pparams->ctm, pbuf, len);
    if (code < 0)
        return code;
    pbuf += len + 1;
    *ppbuf = pbuf;
    return 0;
}

Project: ghostscript
File: gdevp14.c

dump_mask_stack(pdf14_mask_t *mask_stack)
{
    pdf14_mask_t *curr_mask = mask_stack;
    int level = 0;

    while (curr_mask != NULL) {
        if_debug1m('v', curr_mask->memory, "[v]mask_level, %d\n", level);
        if_debug1m('v', curr_mask->memory, "[v]mask_buf, %x\n", curr_mask->rc_mask->mask_buf);
        if_debug1m('v', curr_mask->memory, "[v]rc_count, %d\n", curr_mask->rc_mask->rc);
        level++;
        curr_mask = curr_mask->previous;
    }
}

Project: ghostscript
File: gdevp14.c

find_opening_op(int opening_op, gs_composite_t **ppcte,
                gs_compositor_closing_state return_code)
{
    /* Assuming a right *BEGIN* - *END* operation balance. */
    gs_composite_t *pcte = *ppcte;

    for (;;) {
        if (pcte->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
            gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pcte;
            int op = pct->params.pdf14_op;

            *ppcte = pcte;
            if (op == opening_op)
                return return_code;
            if (op != PDF14_SET_BLEND_PARAMS) {
                if (opening_op == PDF14_BEGIN_TRANS_MASK)
                    return COMP_ENQUEUE;
                if (opening_op == PDF14_BEGIN_TRANS_GROUP) {
                    if (op != PDF14_BEGIN_TRANS_MASK && op != PDF14_END_TRANS_MASK)
                        return COMP_ENQUEUE;
                }
                if (opening_op == PDF14_PUSH_DEVICE) {
                    if (op != PDF14_BEGIN_TRANS_MASK && op != PDF14_END_TRANS_MASK &&
                        op != PDF14_BEGIN_TRANS_GROUP && op != PDF14_END_TRANS_GROUP)
                        return COMP_ENQUEUE;
                }
            }
        } else
            return COMP_ENQUEUE;
        pcte = pcte->prev;
        if (pcte == NULL)
            return COMP_EXEC_QUEUE; /* Not in queue. */
    }
}

Project: ghostscript
File: gdevp14.c

find_same_op(const gs_composite_t *composite_action, int my_op, gs_composite_t **ppcte)
{
    const gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action;
    gs_composite_t *pct = *ppcte;

    for (;;) {
        if (pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
            gs_pdf14trans_t *pct_pdf14 = (gs_pdf14trans_t *)pct;

            *ppcte = pct;
            if (pct_pdf14->params.pdf14_op != my_op)
                return COMP_ENQUEUE;
            if (pct_pdf14->params.csel == pct0->params.csel) {
                /* If the new parameters completely replace the old ones
                   then remove the old one from the queu */
                if ((pct_pdf14->params.changed & pct0->params.changed) ==
                    pct_pdf14->params.changed) {
                    return COMP_REPLACE_CURR;
                } else {
                    return COMP_ENQUEUE;
                }
            }
        } else
            return COMP_ENQUEUE;
        pct = pct->prev;
        if (pct == NULL)
            return COMP_ENQUEUE; /* Not in queue. */
    }
}

Project: ghostscript
File: gdevp14.c

get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto,
        pdf14_clist_device * ptempdevproto, gs_gstate * pgs,
        const gs_pdf14trans_t * pdf14pct, bool use_pdf14_accum)
{
    bool using_blend_cs;
    pdf14_default_colorspace_t dev_cs =
                pdf14_determine_default_blend_cs(dev, use_pdf14_accum,
                                                 &using_blend_cs);

    switch (dev_cs) {
        case PDF14_DeviceGray:
            *pdevproto = (pdf14_clist_device *)&pdf14_clist_Gray_device;
           /* We want gray to be single channel.  Low level
               initialization of gray device prototype is
               peculiar in that in dci_std_color_num_components
               the comment is
              "A device is monochrome only if it is bi-level"
              Here we want monochrome anytime we have a gray device.
              To avoid breaking things elsewhere, we will overide
              the prototype intialization here */
            *ptempdevproto = **pdevproto;
            ptempdevproto->color_info.max_components = 1;
            ptempdevproto->color_info.num_components =
                                    ptempdevproto->color_info.max_components;
            ptempdevproto->color_info.max_gray = 255;
            ptempdevproto->color_info.gray_index = 0; /* Avoid halftoning */
            ptempdevproto->color_info.dither_grays = 256;
            ptempdevproto->color_info.anti_alias = dev->color_info.anti_alias;
            ptempdevproto->sep_device = false;
            *pdevproto = ptempdevproto;
            break;
        case PDF14_DeviceRGB:
            *pdevproto = (pdf14_clist_device *)&pdf14_clist_RGB_device;
            *ptempdevproto = **pdevproto;
            ptempdevproto->color_info.anti_alias = dev->color_info.anti_alias;
            ptempdevproto->sep_device = false;
            *pdevproto = ptempdevproto;
            break;
        case PDF14_DeviceCMYK:
            *pdevproto = (pdf14_clist_device *)&pdf14_clist_CMYK_device;
            *ptempdevproto = **pdevproto;
            ptempdevproto->color_info.anti_alias = dev->color_info.anti_alias;
            ptempdevproto->sep_device = false;
            *pdevproto = ptempdevproto;
            break;
        case PDF14_DeviceCMYKspot:
            *pdevproto = (pdf14_clist_device *)&pdf14_clist_CMYKspot_device;
            *ptempdevproto = **pdevproto;
            /*
             * The number of components for the PDF14 device is the sum
             * of the process components and the number of spot colors
             * for the page.
             */
            if (pdf14pct->params.num_spot_colors >= 0) {
                ptempdevproto->devn_params.page_spot_colors =
                    pdf14pct->params.num_spot_colors;
                ptempdevproto->color_info.num_components =
                    ptempdevproto->devn_params.num_std_colorant_names +
                    pdf14pct->params.num_spot_colors;
                if (ptempdevproto->color_info.num_components >
                        ptempdevproto->color_info.max_components)
                    ptempdevproto->color_info.num_components =
                        ptempdevproto->color_info.max_components;
                ptempdevproto->color_info.depth =
                                    ptempdevproto->color_info.num_components * 8;
            }
            ptempdevproto->color_info.anti_alias = dev->color_info.anti_alias;
            ptempdevproto->sep_device = true;
            *pdevproto = ptempdevproto;
            break;
        case PDF14_DeviceCustom:
            /*
             * We are using the output device's process color model.  The
             * color_info for the PDF 1.4 compositing device needs to match
             * the output device.
             */
            *ptempdevproto = pdf14_clist_custom_device;
            ptempdevproto->color_info = dev->color_info;
            /* The pdf14 device has to be 8 bit continuous tone. Force it */
            ptempdevproto->color_info.depth =
                ptempdevproto->color_info.num_components * 8;
            ptempdevproto->color_info.max_gray = 255;
            ptempdevproto->color_info.max_color = 255;
            ptempdevproto->color_info.dither_grays = 256;
            ptempdevproto->color_info.dither_colors = 256;
            ptempdevproto->color_info.anti_alias = dev->color_info.anti_alias;
            *pdevproto = ptempdevproto;
            break;
        default:			/* Should not occur */
            return_error(gs_error_rangecheck);
    }
    ptempdevproto->using_blend_cs = using_blend_cs;
    return 0;
}

Project: ghostscript
File: gdevp14.c

gs_create_pdf14trans(
    gs_composite_t **               ppct,
    const gs_pdf14trans_params_t *  pparams,
    gs_memory_t *                   mem )
{
    gs_pdf14trans_t *                pct;

    pct = gs_alloc_struct(mem, gs_pdf14trans_t, &st_pdf14trans,
                             "gs_create_pdf14trans");
    if (pct == NULL)
        return_error(gs_error_VMerror);
    pct->type = &gs_composite_pdf14trans_type;
    pct->id = gs_next_ids(mem, 1);
    pct->params = *pparams;
    pct->idle = false;
    *ppct = (gs_composite_t *)pct;
    return 0;
}

Project: ghostscript
File: gdevp14.c

gs_is_pdf14trans_compositor(const gs_composite_t * pct)
{
    return (pct->type == &gs_composite_pdf14trans_type
                || pct->type == &gs_composite_pdf14trans_no_clist_writer_type);
}

Project: ghostscript
File: gdevp14.c

gs_pdf14_clist_device_push(gs_memory_t *mem, gs_gstate *pgs, gx_device **pcdev,
                           gx_device *dev, const gs_pdf14trans_t *pdf14pct)
{
    int code;
    pdf14_clist_device *p14dev;
    gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer;

    code = pdf14_create_clist_device(mem, pgs, pcdev, dev, pdf14pct);
    /*
     * Set the color_info of the clist device to match the compositing
     * device.  We will restore it when the compositor is popped.
     * See pdf14_clist_create_compositor for the restore.  Do the
     * same with the gs_gstate's get_cmap_procs.  We do not want
     * the gs_gstate to use transfer functions on our color values.
     * The transfer functions will be applied at the end after we
     * have done our PDF 1.4 blend operations.
     */
    p14dev = (pdf14_clist_device *)(*pcdev);
    p14dev->saved_target_color_info = dev->color_info;
    dev->color_info = (*pcdev)->color_info;
    /* Make sure that we keep the anti-alias information though */
    dev->color_info.anti_alias = p14dev->saved_target_color_info.anti_alias;
    p14dev->color_info.anti_alias = dev->color_info.anti_alias;

    /* adjust the clist_color_info now */
    cdev->clist_color_info.depth = p14dev->color_info.depth;
    cdev->clist_color_info.polarity = p14dev->color_info.polarity;
    cdev->clist_color_info.num_components = p14dev->color_info.num_components;
    cdev->clist_color_info.max_color = p14dev->color_info.max_color;
    cdev->clist_color_info.max_gray = p14dev->color_info.max_gray;

    p14dev->saved_target_encode_color = dev->procs.encode_color;
    p14dev->saved_target_decode_color = dev->procs.decode_color;
    dev->procs.encode_color = p14dev->procs.encode_color =
                              p14dev->my_encode_color;
    dev->procs.decode_color = p14dev->procs.decode_color =
                              p14dev->my_decode_color;
    p14dev->saved_target_get_color_mapping_procs =
                              dev->procs.get_color_mapping_procs;
    p14dev->saved_target_get_color_comp_index =
                              dev->procs.get_color_comp_index;
    dev->procs.get_color_mapping_procs =
        p14dev->procs.get_color_mapping_procs =
        p14dev->my_get_color_mapping_procs;
    dev->procs.get_color_comp_index =
        p14dev->procs.get_color_comp_index =
        p14dev->my_get_color_comp_index;
    p14dev->save_get_cmap_procs = pgs->get_cmap_procs;
    pgs->get_cmap_procs = pdf14_get_cmap_procs;
    gx_set_cmap_procs(pgs, dev);
    return code;
}

Project: ghostscript
File: gdevp14.c

gs_pdf14_device_color_mon_set(gx_device *pdev, bool monitoring)
{
    pdf14_device * p14dev = (pdf14_device *)pdev;
    gx_device *targ = p14dev->target;
    cmm_dev_profile_t *dev_profile;
    int code = dev_proc(targ, get_profile)((gx_device*) targ, &dev_profile);

    if (code == 0)
        dev_profile->pageneutralcolor = monitoring;
    return code;
}

Project: ghostscript
File: gdevp14.c

gs_pdf14_device_copy_params(gx_device *dev, const gx_device *target)
{
    cmm_dev_profile_t *profile_targ;
    cmm_dev_profile_t *profile_dev14;
    pdf14_device *pdev = (pdf14_device*) dev;

    COPY_PARAM(width);
    COPY_PARAM(height);
    COPY_ARRAY_PARAM(MediaSize);
    COPY_ARRAY_PARAM(ImagingBBox);
    COPY_PARAM(ImagingBBox_set);
    COPY_ARRAY_PARAM(HWResolution);
    COPY_ARRAY_PARAM(Margins);
    COPY_ARRAY_PARAM(HWMargins);
    COPY_PARAM(PageCount);
    COPY_PARAM(MaxPatternBitmap);
    memcpy(&(dev->space_params), &(target->space_params), sizeof(gdev_space_params));
    /* The PDF14 device copies only the default profile not the text etc.
       TODO: MJV.  It has to make its own device structure but
       can grab a copy of the profile.  This allows swapping of profiles
       in the PDF14 device without messing up the target device profile.
       Also if the device is using a blend color space it will grab that too */
    if (dev->icc_struct == NULL) {
        dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
        profile_dev14 = dev->icc_struct;
        dev_proc((gx_device *) target, get_profile)((gx_device *) target,
                                          &(profile_targ));
        profile_dev14->device_profile[0] = profile_targ->device_profile[0];
        dev->icc_struct->devicegraytok = profile_targ->devicegraytok;
        dev->icc_struct->graydetection = profile_targ->graydetection;
        dev->icc_struct->pageneutralcolor = profile_targ->pageneutralcolor;
        dev->icc_struct->supports_devn = profile_targ->supports_devn;
        dev->icc_struct->usefastcolor = profile_targ->usefastcolor;
        gx_monitor_enter(profile_dev14->device_profile[0]->lock);
        rc_increment(profile_dev14->device_profile[0]);
        gx_monitor_leave(profile_dev14->device_profile[0]->lock);
        profile_dev14->rendercond[0] = profile_targ->rendercond[0];
        if (pdev->using_blend_cs) {
            /* Swap the device profile and the blend profile. */
            profile_dev14->blend_profile = profile_targ->device_profile[0];
            profile_dev14->device_profile[0] = profile_targ->blend_profile;
            gx_monitor_enter(profile_dev14->device_profile[0]->lock);
            rc_increment(profile_dev14->device_profile[0]);
            gx_monitor_leave(profile_dev14->device_profile[0]->lock);
        }
        profile_dev14->sim_overprint = profile_targ->sim_overprint;
    }
    dev->graphics_type_tag = target->graphics_type_tag;	/* initialize to same as target */
#undef COPY_ARRAY_PARAM
#undef COPY_PARAM
}

Project: ghostscript
File: gdevp14.c

gx_update_pdf14_compositor(gx_device * pdev, gs_gstate * pgs,
    const gs_pdf14trans_t * pdf14pct, gs_memory_t * mem )
{
    pdf14_device *p14dev = (pdf14_device *)pdev;
    gs_pdf14trans_params_t params = pdf14pct->params;
    int code = 0;

    params.idle = pdf14pct->idle;
    switch (params.pdf14_op) {
        default:			/* Should not occur. */
            break;
        case PDF14_PUSH_DEVICE:
            if (!(params.is_pattern)) {
                p14dev->blend_mode = 0;
                p14dev->opacity = p14dev->shape = 0.0;
                pdf14_recreate_device(mem, pgs, pdev, pdf14pct);
            }
            break;
        case PDF14_ABORT_DEVICE:
            /* Something has gone very wrong.  Let transparency device clean up
               what ever it has allocated and then we are shutting it down */
            code = gx_abort_trans_device(pgs, pdev);
            if (p14dev->free_devicen) {
                devn_free_params(pdev);
            }
            pdf14_disable_device(pdev);
            pdf14_close(pdev);
            break;
        case PDF14_POP_DEVICE:
            if (!(params.is_pattern)) {
                if_debug0m('v', pdev->memory,
                           "[v]gx_update_pdf14_compositor(PDF14_POP_DEVICE)\n");
                pgs->get_cmap_procs = p14dev->save_get_cmap_procs;
                gx_set_cmap_procs(pgs, p14dev->target);
                /* Send image out raster data to output device */
                {
                    /* Make a copy so we can change the ROP */
                    gs_gstate new_pgs = *pgs;

                    /* We don't use the gs_gstate log_op since this is for the */
                    /* clist playback. Putting the image (band in the case of the */
                    /* clist) only needs to use the default ROP to copy the data  */
                    new_pgs.log_op = rop3_default;
                    code = p14dev->pdf14_procs->put_image(pdev, &new_pgs, p14dev->target);
                }
                /* Before we disable the device release any deviceN structures.
                    free_devicen is set if the pdf14 device had inherited its
                    deviceN parameters from the target clist device.  In this
                    case they should not be freed */
                if (p14dev->free_devicen) {
                    devn_free_params(pdev);
                }
                pdf14_disable_device(pdev);
                pdf14_close(pdev);
            }
            break;
        case PDF14_BEGIN_TRANS_GROUP:
            code = gx_begin_transparency_group(pgs, pdev, &params);
            break;
        case PDF14_END_TRANS_GROUP:
            code = gx_end_transparency_group(pgs, pdev);
            break;
        case PDF14_BEGIN_TRANS_MASK:
            code = gx_begin_transparency_mask(pgs, pdev, &params);
            break;
        case PDF14_END_TRANS_MASK:
            code = gx_end_transparency_mask(pgs, pdev, &params);
            break;
        case PDF14_SET_BLEND_PARAMS:
            pdf14_set_params(pgs, pdev, &pdf14pct->params);
            break;
        case PDF14_PUSH_TRANS_STATE:
            code = gx_push_transparency_state(pgs, pdev);
            break;
        case PDF14_POP_TRANS_STATE:
            code = gx_pop_transparency_state(pgs, pdev);
            break;
        case PDF14_PUSH_SMASK_COLOR:
            code = pdf14_increment_smask_color(pgs, pdev);
            break;
        case PDF14_POP_SMASK_COLOR:
            code = pdf14_decrement_smask_color(pgs, pdev);
            break;
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

map_components_to_colorants(const frac * pcc,
        const gs_devicen_color_map * pcolor_component_map, frac * plist)
{
    int i = pcolor_component_map->num_colorants - 1;
    int pos;

    /* Clear all output colorants first */
    for (; i >= 0; i--) {
        plist[i] = frac_0;
    }
    /* Map color components into output list */
    for (i = pcolor_component_map->num_components - 1; i >= 0; i--) {
        pos = pcolor_component_map->color_map[i];
        if (pos >= 0)
            plist[pos] = pcc[i];
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_begin_transparency_group(gx_device *dev,
                              const gs_transparency_group_params_t *ptgp,
                              const gs_rect *pbbox,
                              gs_gstate *pgs, gs_memory_t *mem)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    double alpha = pgs->opacity.alpha * pgs->shape.alpha;
    gs_int_rect rect;
    int code;
    bool isolated = ptgp->Isolated;
    gs_transparency_color_t group_color;
    cmm_profile_t *group_profile;
    cmm_profile_t *tos_profile;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;
    bool cm_back_drop = false;
    bool new_icc = false;

    code = dev_proc(dev, get_profile)(dev,  &dev_profile);
    if (code < 0)
        return code;
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &tos_profile, &render_cond);

    code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs);
    if (code < 0)
        return code;
    if_debug4m('v', pdev->memory,
               "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d\n",
               ptgp->Isolated, ptgp->Knockout, alpha, pgs->blend_mode);

    /* If the group color is unknown then use the current device profile. */
    if (ptgp->group_color == UNKNOWN){
        group_color = ICC;
        group_profile = tos_profile;
    } else {
        group_color = ptgp->group_color;
        group_profile = ptgp->iccprofile;
    }

    /* We have to handle case where the profile is in the clist */
    if (group_profile == NULL && pdev->pclist_device != NULL) {
        /* Get the serialized data from the clist. */
        gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)(pdev->pclist_device);
        group_profile = gsicc_read_serial_icc((gx_device *) pcrdev, ptgp->icc_hashcode);
        if (group_profile == NULL)
            return gs_throw(gs_error_unknownerror, "ICC data not found in clist");
        /* Keep a pointer to the clist device */
        group_profile->dev = (gx_device *) pcrdev;
        new_icc = true;
    }
    if (group_profile != NULL) {
        /* If we have a non-isolated group and the color space is different,
            we will need to CM the backdrop. */
        if (!(group_profile->hash_is_valid)) {
            gsicc_get_icc_buff_hash(group_profile->buffer,
                                    &(group_profile->hashcode),
                                    group_profile->buffer_size);
            group_profile->hash_is_valid = true;
        }
        if (group_profile->hashcode != tos_profile->hashcode) {
            cm_back_drop = true;
        }
    }

    code = pdf14_update_device_color_procs(dev, group_color, ptgp->icc_hashcode,
        pgs, group_profile, false);
    if_debug0m('v', dev->memory, "[v]Transparency group color space update\n");
    if (code < 0)
        return code;
    code = pdf14_push_transparency_group(pdev->ctx, &rect, isolated, ptgp->Knockout,
                                         (byte)floor (255 * alpha + 0.5),
                                         (byte)floor (255 * pgs->shape.alpha + 0.5),
                                         pgs->blend_mode, ptgp->idle,
                                         ptgp->mask_id, pdev->color_info.num_components,
                                         cm_back_drop, group_profile, tos_profile,
                                         pgs, dev);
    if (new_icc)
        rc_decrement(group_profile, "pdf14_begin_transparency_group");
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_begin_transparency_mask(gx_device	*dev,
                              const gx_transparency_mask_params_t *ptmp,
                              const gs_rect *pbbox,
                              gs_gstate *pgs, gs_memory_t *mem)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    byte bg_alpha = 0;   /* By default the background alpha (area outside mask) is zero */
    byte *transfer_fn;
    gs_int_rect rect;
    int code;
    int group_color_numcomps;
    gs_transparency_color_t group_color;

    if (ptmp->subtype == TRANSPARENCY_MASK_None) {
        pdf14_ctx *ctx = pdev->ctx;

        /* free up any maskbuf on the current tos */
        if (ctx->mask_stack) {
            if (ctx->mask_stack->rc_mask->mask_buf != NULL ) {
                pdf14_buf_free(ctx->mask_stack->rc_mask->mask_buf, ctx->mask_stack->memory);
                ctx->mask_stack->rc_mask->mask_buf = NULL;
            }
        }
        return 0;
    }
    transfer_fn = (byte *)gs_alloc_bytes(pdev->ctx->memory, 256,
                                               "pdf14_begin_transparency_mask");
    if (transfer_fn == NULL)
        return_error(gs_error_VMerror);
    code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs);
    if (code < 0)
        return code;
    /* If we have background components the background alpha may be nonzero */
    if (ptmp->Background_components)
        bg_alpha = (int)(255 * ptmp->GrayBackground + 0.5);
    if_debug1m('v', dev->memory,
               "pdf14_begin_transparency_mask, bg_alpha = %d\n", bg_alpha);
    memcpy(transfer_fn, ptmp->transfer_fn, size_of(ptmp->transfer_fn));
   /* If the group color is unknown, then we must use the previous group color
       space or the device process color space */
    if (ptmp->group_color == UNKNOWN){
        if (pdev->ctx->stack){
            /* Use previous group color space */
            group_color_numcomps = pdev->ctx->stack->n_chan-1;  /* Remove alpha */
        } else {
            /* Use process color space */
            group_color_numcomps = pdev->color_info.num_components;
        }
        switch (group_color_numcomps) {
            case 1:
                group_color = GRAY_SCALE;
                break;
            case 3:
                group_color = DEVICE_RGB;
                break;
            case 4:
                group_color = DEVICE_CMYK;
            break;
            default:
                /* We can end up here if we are in a deviceN color space and
                   we have a sep output device */
                group_color = DEVICEN;
            break;
         }
    } else {
        group_color = ptmp->group_color;
        group_color_numcomps = ptmp->group_color_numcomps;
    }
    /* Always update the color mapping procs.  Otherwise we end up
       fowarding to the target device. */
    code = pdf14_update_device_color_procs(dev, group_color, ptmp->icc_hashcode,
                                           pgs, ptmp->iccprofile, true);
    if (code < 0)
        return code;
    /* Note that the soft mask always follows the group color requirements even
       when we have a separable device */
    return pdf14_push_transparency_mask(pdev->ctx, &rect, bg_alpha,
                                        transfer_fn, ptmp->idle, ptmp->replacing,
                                        ptmp->mask_id, ptmp->subtype,
                                        group_color_numcomps,
                                        ptmp->Background_components,
                                        ptmp->Background,
                                        ptmp->Matte_components,
                                        ptmp->Matte,
                                        ptmp->GrayBackground);
}

Project: ghostscript
File: gdevp14.c

pdf14_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
                           const gs_matrix *pmat, const gs_image_common_t *pic,
                           const gs_int_rect * prect,
                           const gx_drawing_color * pdcolor,
                           const gx_clip_path * pcpath, gs_memory_t * mem,
                           gx_image_enum_common_t ** pinfo)
{
    const gs_image_t *pim = (const gs_image_t *)pic;
    int code;

    /* If we are filling an image mask with a pattern that has a transparency
       then we need to do some special handling */
    if (pim->ImageMask) {
        if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)) {
            if( gx_pattern1_get_transptr(pdcolor) != NULL){
                /* If we are in a final run through here for this case then
                   go ahead and push the transparency group.   Also, update
                   the proc for the pattern color so that we used the
                   appropriate fill operation.  Note that the group
                   is popped and the proc will be reset when we flush the
                   image data.  This is handled in a special pdf14 image
                   renderer which will end up installed for this case.
                   Detect setting of begin_image to gx_no_begin_image.
                   (final recursive call) */
                if (dev->procs.begin_image != gx_default_begin_image) {
                    code = pdf14_patt_trans_image_fill(dev, pgs, pmat, pic,
                                                prect, pdcolor, pcpath, mem,
                                                pinfo);
                    return code;
                }
            }
        }
    }
    pdf14_set_marking_params(dev, pgs);
    return gx_default_begin_typed_image(dev, pgs, pmat, pic, prect, pdcolor,
                                        pcpath, mem, pinfo);
}

Project: ghostscript
File: gdevp14.c

pdf14_buf_free(pdf14_buf *buf, gs_memory_t *memory)
{
    pdf14_parent_color_t *old_parent_color_info = buf->parent_color_info_procs;

    if (buf->mask_stack && buf->mask_stack->rc_mask)
        rc_decrement(buf->mask_stack->rc_mask, "pdf14_buf_free");

    gs_free_object(memory, buf->mask_stack, "pdf14_buf_free");
    gs_free_object(memory, buf->transfer_fn, "pdf14_buf_free");
    gs_free_object(memory, buf->matte, "pdf14_buf_free");
    gs_free_object(memory, buf->data, "pdf14_buf_free");

    while (old_parent_color_info) {
       if (old_parent_color_info->icc_profile != NULL) {
           rc_decrement(old_parent_color_info->icc_profile, "pdf14_buf_free");
       }
       buf->parent_color_info_procs = old_parent_color_info->previous;
       gs_free_object(memory, old_parent_color_info, "pdf14_buf_free");
       old_parent_color_info = buf->parent_color_info_procs;
    }

    gs_free_object(memory, buf->backdrop, "pdf14_buf_free");
    gs_free_object(memory, buf, "pdf14_buf_free");
}

Project: ghostscript
File: gdevp14.c

static void pdf14_cleanup_parent_color_profiles (pdf14_device *pdev)
{
    if (pdev->ctx) {
        pdf14_buf *buf, *next;

        for (buf = pdev->ctx->stack; buf != NULL; buf = next) {
            pdf14_parent_color_t *old_parent_color_info = buf->parent_color_info_procs;
            next = buf->saved;
            while (old_parent_color_info) {
               if (old_parent_color_info->icc_profile != NULL) {
                   cmm_profile_t *group_profile;
                   gsicc_rendering_param_t render_cond;
                   cmm_dev_profile_t *dev_profile;
                   int code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev,  &dev_profile);

                   if (code >= 0) {
                       gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile,
                                             &render_cond);

                       rc_decrement(group_profile,"pdf14_end_transparency_group");
                       pdev->icc_struct->device_profile[0] = old_parent_color_info->icc_profile;
                       rc_decrement(old_parent_color_info->icc_profile,"pdf14_end_transparency_group");
                       old_parent_color_info->icc_profile = NULL;
                   }
               }

               old_parent_color_info = old_parent_color_info->previous;
            }
        }
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_clist_begin_image(gx_device * dev,
                       const gs_gstate * pgs, const gs_image_t * pim,
                       gs_image_format_t format, const gs_int_rect * prect,
                       const gx_drawing_color * pdcolor,
                       const gx_clip_path * pcpath,
                       gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
{
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
    int code;

    /*
     * Ensure that that the PDF 1.4 reading compositor will have the current
     * blending parameters.  This is needed since the fill_rectangle routines
     * do not have access to the gs_gstate.  Thus we have to pass any
     * changes explictly.
     */
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
    if (code < 0)
        return code;
    /* Pass image to the target */
    code = gx_forward_begin_image(dev, pgs, pim, format, prect,
                                        pdcolor, pcpath, memory, pinfo);
    if (code < 0)
        return gx_default_begin_image(dev, pgs, pim, format, prect,
                                        pdcolor, pcpath, memory, pinfo);
    else return code;

}

Project: ghostscript
File: gdevp14.c

pdf14_clist_begin_typed_image(gx_device	* dev, const gs_gstate * pgs,
                           const gs_matrix *pmat, const gs_image_common_t *pic,
                           const gs_int_rect * prect,
                           const gx_drawing_color * pdcolor,
                           const gx_clip_path * pcpath, gs_memory_t * mem,
                           gx_image_enum_common_t ** pinfo)
{
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
    int code;
    gs_gstate * pgs_noconst = (gs_gstate *)pgs; /* Break 'const'. */
    const gs_image_t *pim = (const gs_image_t *)pic;
    gx_image_enum *penum;
    gx_color_tile *ptile;
    gs_rect bbox_in, bbox_out;
    gs_transparency_group_params_t tgp;
    /*
     * Ensure that that the PDF 1.4 reading compositor will have the current
     * blending parameters.  This is needed since the fill_rectangle routines
     * do not have access to the gs_gstate.  Thus we have to pass any
     * changes explictly.
     */
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
    if (code < 0)
        return code;
    /* Pass image to the target */
    /* Do a quick change to the gs_gstate so that if we can return with -1 in
       case the clist writer cannot handle this image itself.  In such a case,
       we want to make sure we dont use the target device.  I don't necc. like
       doing it this way.  Probably need to go back and do something a bit
       more elegant. */
    pgs_noconst->has_transparency = true;
    pgs_noconst->trans_device = dev;

    /* If we are filling an image mask with a pattern that has a transparency
       then we need to do some special handling */
    if (pim->ImageMask) {
        if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)) {
            if( gx_pattern1_get_transptr(pdcolor) != NULL){
                 if (dev->procs.begin_image != pdf14_clist_begin_image) {
                    ptile = pdcolor->colors.pattern.p_tile;
                    /* Set up things in the ptile so that we get the proper
                       blending etc */
                    /* Set the blending procs and the is_additive setting based
                       upon the number of channels */
                    if (ptile->ttrans->n_chan-1 < 4) {
                        ptile->ttrans->blending_procs = &rgb_blending_procs;
                        ptile->ttrans->is_additive = true;
                    } else {
                        ptile->ttrans->blending_procs = &cmyk_blending_procs;
                        ptile->ttrans->is_additive = false;
                    }
                    /* Set the blending mode in the ptile based upon the current
                       setting in the gs_gstate */
                    ptile->blending_mode = pgs->blend_mode;
                    /* Set the procs so that we use the proper filling method. */
                    /* Let the imaging stuff get set up */
                    code = gx_default_begin_typed_image(dev, pgs, pmat, pic,
                                                        prect, pdcolor,
                                                        pcpath, mem, pinfo);
                    if (code < 0)
                        return code;

                    penum = (gx_image_enum *) *pinfo;
                    /* Apply inverse of the image matrix to our
                       image size to get our bounding box. */
                    bbox_in.p.x = 0;
                    bbox_in.p.y = 0;
                    bbox_in.q.x = pim->Width;
                    bbox_in.q.y = pim->Height;
                    code = gs_bbox_transform_inverse(&bbox_in, &(pim->ImageMatrix),
                                                     &bbox_out);
                    if (code < 0) return code;
                    /* Set up a compositor action for pushing the group */
                    if_debug0m('v', pgs->memory, "[v]Pushing special trans group for image\n");
                    tgp.Isolated = true;
                    tgp.Knockout = false;
                    tgp.mask_id = 0;
                    tgp.image_with_SMask = false;
                    tgp.idle = false;
                    tgp.iccprofile = NULL;
                    tgp.icc_hashcode = 0;
                    tgp.group_color_numcomps = ptile->ttrans->n_chan-1;
                    tgp.ColorSpace = NULL;
                    /* This will handle the compositor command */
                    gs_begin_transparency_group((gs_gstate *) pgs_noconst, &tgp,
                                                &bbox_out);
                    ptile->ttrans->image_render = penum->render;
                    penum->render = &pdf14_pattern_trans_render;
                    ptile->trans_group_popped = false;
                    pgs_noconst->has_transparency = false;
                    pgs_noconst->trans_device = NULL;
                    return code;
                }
            }
        }
    }
    /* This basically tries high level images for clist. If that fails
       then we do the default */
    code = gx_forward_begin_typed_image(dev, pgs, pmat,
                            pic, prect, pdcolor, pcpath, mem, pinfo);
    if (code < 0){
        code = gx_default_begin_typed_image(dev, pgs, pmat, pic, prect,
                                        pdcolor, pcpath, mem, pinfo);
        pgs_noconst->has_transparency = false;
        pgs_noconst->trans_device = NULL;
        return code;
    } else {
        pgs_noconst->has_transparency = false;
        pgs_noconst->trans_device = NULL;
        return code;
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_clist_create_compositor(gx_device	* dev, gx_device ** pcdev,
    const gs_composite_t * pct, gs_gstate * pgs, gs_memory_t * mem,
    gx_device *cdev)
{
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
    int code, is_pdf14_compositor;
    const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;

    /* We only handle a few PDF 1.4 transparency operations */
    if ((is_pdf14_compositor = gs_is_pdf14trans_compositor(pct)) != 0) {
        switch (pdf14pct->params.pdf14_op) {
            case PDF14_PUSH_DEVICE:
                /* Re-activate the PDF 1.4 compositor */
                pdev->saved_target_color_info = pdev->target->color_info;
                pdev->target->color_info = pdev->color_info;
                pdev->saved_target_encode_color = pdev->target->procs.encode_color;
                pdev->saved_target_decode_color = pdev->target->procs.decode_color;
                pdev->target->procs.encode_color = pdev->procs.encode_color =
                                                   pdev->my_encode_color;
                pdev->target->procs.decode_color = pdev->procs.decode_color =
                                                   pdev->my_decode_color;
                pdev->saved_target_get_color_mapping_procs =
                                    pdev->target->procs.get_color_mapping_procs;
                pdev->saved_target_get_color_comp_index =
                                        pdev->target->procs.get_color_comp_index;
                pdev->target->procs.get_color_mapping_procs =
                        pdev->procs.get_color_mapping_procs =
                        pdev->my_get_color_mapping_procs;
                pdev->target->procs.get_color_comp_index =
                        pdev->procs.get_color_comp_index =
                        pdev->my_get_color_comp_index;
                pdev->save_get_cmap_procs = pgs->get_cmap_procs;
                pgs->get_cmap_procs = pdf14_get_cmap_procs;
                gx_set_cmap_procs(pgs, dev);
                code = pdf14_recreate_clist_device(mem, pgs, dev, pdf14pct);
                pdev->blend_mode = pdev->text_knockout = 0;
                pdev->opacity = pdev->shape = 0.0;
                if (code < 0)
                    return code;
                /*
                 * This routine is part of the PDF 1.4 clist write device.
                 * Change the compositor procs to not create another since we
                 * do not need to create a chain of identical devices.
                 */
                {
                    gs_composite_t pctemp = *pct;

                    pctemp.type = &gs_composite_pdf14trans_no_clist_writer_type;
                    code = dev_proc(pdev->target, create_compositor)
                                (pdev->target, pcdev, &pctemp, pgs, mem, cdev);
                    *pcdev = dev;
                    return code;
                }
            case PDF14_POP_DEVICE:
                /* Restore the color_info for the clist device */
                pdev->target->color_info = pdev->saved_target_color_info;
                pdev->target->procs.encode_color =
                                        pdev->saved_target_encode_color;
                pdev->target->procs.decode_color =
                                        pdev->saved_target_decode_color;
                pdev->target->procs.get_color_mapping_procs =
                                    pdev->saved_target_get_color_mapping_procs;
                pdev->target->procs.get_color_comp_index =
                                    pdev->saved_target_get_color_comp_index;
                pgs->get_cmap_procs = pdev->save_get_cmap_procs;
                gx_set_cmap_procs(pgs, pdev->target);
                gx_device_decache_colors(pdev->target);
                /* Disable the PDF 1.4 compositor */
                pdf14_disable_clist_device(mem, pgs, dev);
                /*
                 * Make sure that the transfer funtions, etc. are current.
                 */
                code = cmd_put_color_mapping(
                        (gx_device_clist_writer *)(pdev->target), pgs);
                if (code < 0)
                    return code;
                break;
            case PDF14_BEGIN_TRANS_GROUP:
                /*
                 * Keep track of any changes made in the blending parameters.
                   These need to be written out in the same bands as the group
                   information is written.  Hence the passing of the dimensions
                   for the group. */
                code = pdf14_clist_update_params(pdev, pgs, true,
                                                 (gs_pdf14trans_params_t *)&(pdf14pct->params));
                if (code < 0)
                    return code;
                if (pdf14pct->params.Background_components != 0 &&
                    pdf14pct->params.Background_components !=
                    pdev->color_info.num_components)
                    return_error(gs_error_rangecheck);
                /* We need to update the clist writer device procs based upon the
                   the group color space.  For simplicity, the list item is
                   created even if the color space did not change */
                /* First store the current ones */
                pdf14_push_parent_color(dev, pgs);

                code = pdf14_update_device_color_procs_push_c(dev,
                                pdf14pct->params.group_color,
                                pdf14pct->params.icc_hash, pgs,
                                pdf14pct->params.iccprofile, false);
                if (code < 0)
                    return code;
                break;
            case PDF14_BEGIN_TRANS_MASK:
                /* We need to update the clist writer device procs based upon the
                   the group color space.  For simplicity, the list item is created
                   even if the color space did not change */
                /* First store the current ones */
                if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None)
                    break;
                pdf14_push_parent_color(dev, pgs);
                /* If we are playing back from a clist, the iccprofile may need to be loaded */
                if (pdf14pct->params.iccprofile == NULL) {
                    gs_pdf14trans_params_t *pparams_noconst = (gs_pdf14trans_params_t *)&(pdf14pct->params);

                    pparams_noconst->iccprofile = gsicc_read_serial_icc((gx_device *) cdev,
                                                       pdf14pct->params.icc_hash);
                    if (pparams_noconst->iccprofile == NULL)
                        return gs_throw(-1, "ICC data not found in clist");
                    /* Keep a pointer to the clist device */
                    pparams_noconst->iccprofile->dev = (gx_device *)cdev;
                    /* Now we need to load the rest of the profile buffer */
                    if (pparams_noconst->iccprofile->buffer == NULL) {
                        gcmmhprofile_t dummy = gsicc_get_profile_handle_clist(pparams_noconst->iccprofile, mem);

                        if (dummy == NULL)
                            return_error(gs_error_VMerror);
                    }
                }
                /* Now update the device procs */
                code = pdf14_update_device_color_procs_push_c(dev,
                                  pdf14pct->params.group_color,
                                  pdf14pct->params.icc_hash, pgs,
                                  pdf14pct->params.iccprofile, true);
                if (code < 0)
                    return code;
                /* Also, if the BC is a value that may end up as something other
                  than transparent. We must use the parent colors bounding box in
                  determining the range of bands in which this mask can affect.
                  So, if needed change the masks bounding box at this time */
                break;
            case PDF14_END_TRANS_GROUP:
            case PDF14_END_TRANS_MASK:
                /* We need to update the clist writer device procs based upon the
                   the group color space. */
                code = pdf14_update_device_color_procs_pop_c(dev,pgs);
                if (code < 0)
                    return code;
                break;
            case PDF14_PUSH_TRANS_STATE:
                break;
            case PDF14_POP_TRANS_STATE:
                break;
            case PDF14_PUSH_SMASK_COLOR:
                code = pdf14_increment_smask_color(pgs,dev);
                *pcdev = dev;
                return code;  /* Note, this are NOT put in the clist */
                break;
            case PDF14_POP_SMASK_COLOR:
                code = pdf14_decrement_smask_color(pgs,dev);
                *pcdev = dev;
                return code;  /* Note, this are NOT put in the clist */
                break;
            case PDF14_SET_BLEND_PARAMS:
                /* If there is a change we go ahead and apply it to the target */
                code = pdf14_clist_update_params(pdev, pgs, false,
                                                 (gs_pdf14trans_params_t *)&(pdf14pct->params));
                *pcdev = dev;
                return code;
                break;
            case PDF14_ABORT_DEVICE:
                break;
            default:
                break;		/* Pass remaining ops to target */
        }
    }
    code = dev_proc(pdev->target, create_compositor)
                        (pdev->target, pcdev, pct, pgs, mem, cdev);
    /* If we were accumulating into a pdf14-clist-accum device, */
    /* we now have to render the page into it's target device */
    if (is_pdf14_compositor && pdf14pct->params.pdf14_op == PDF14_POP_DEVICE &&
        pdev->target->stype == &st_pdf14_accum) {

        int y, rows_used;
        byte *linebuf = gs_alloc_bytes(mem, gx_device_raster((gx_device *)pdev, true), "pdf14-clist_accum pop dev");
        byte *actual_data;
        gx_device *tdev = pdev->target;     /* the printer class clist device used to accumulate */
        /* get the target device we want to send the image to */
        gx_device *target = ((pdf14_device *)((gx_device_pdf14_accum *)(tdev))->save_p14dev)->target;
        gs_image1_t image;
        gs_color_space *pcs;
        gx_image_enum_common_t *info;
        gx_image_plane_t planes;
        gsicc_rendering_param_t render_cond;
        cmm_dev_profile_t *dev_profile;

        /*
         * Set color space in preparation for sending an image.
         */
        code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory);
        if (linebuf == NULL || pcs == NULL)
            goto put_accum_error;

        /* Need to set this to avoid color management during the
           image color render operation.  Exception is for the special case
           when the destination was CIELAB.  Then we need to convert from
           default RGB to CIELAB in the put image operation.  That will happen
           here as we should have set the profile for the pdf14 device to RGB
           and the target will be CIELAB */
        code = dev_proc(dev, get_profile)(dev,  &dev_profile);
        if (code < 0) {
            rc_decrement_only_cs(pcs, "pdf14_put_image");
            return code;
        }
        gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
                              &(pcs->cmm_icc_profile_data), &render_cond);
        /* pcs takes a reference to the profile data it just retrieved. */
        rc_increment(pcs->cmm_icc_profile_data);
        gscms_set_icc_range(&(pcs->cmm_icc_profile_data));

        gs_image_t_init_adjust(&image, pcs, false);
        image.ImageMatrix.xx = (float)pdev->width;
        image.ImageMatrix.yy = (float)pdev->height;
        image.Width = pdev->width;
        image.Height = pdev->height;
        image.BitsPerComponent = 8;
        ctm_only_writable(pgs).xx = (float)pdev->width;
        ctm_only_writable(pgs).xy = 0;
        ctm_only_writable(pgs).yx = 0;
        ctm_only_writable(pgs).yy = (float)pdev->height;
        ctm_only_writable(pgs).tx = 0.0;
        ctm_only_writable(pgs).ty = 0.0;
        code = dev_proc(target, begin_typed_image) (target,
                                                    pgs, NULL,
                                                    (gs_image_common_t *)&image,
                                                    NULL, NULL, NULL,
                                                    pgs->memory, &info);
        if (code < 0)
            goto put_accum_error;
        for (y=0; y < tdev->height; y++) {
            code = dev_proc(tdev, get_bits)(tdev, y, linebuf, &actual_data);
            planes.data = actual_data;
            planes.data_x = 0;
            planes.raster = tdev->width * tdev->color_info.num_components;
            if ((code = info->procs->plane_data(info, &planes, 1, &rows_used)) < 0)
                goto put_accum_error;
        }
        info->procs->end_image(info, true);

put_accum_error:
        gs_free_object(pdev->memory, linebuf, "pdf14_put_image");
        /* This will also decrement the device profile */
        rc_decrement_only_cs(pcs, "pdf14_put_image");
        dev_proc(tdev, close_device)(tdev);	/* frees the prn_device memory */
        /* Now unhook the clist device and hook to the original so we can clean up */
        gx_device_set_target((gx_device_forward *)pdev,
                             ((gx_device_pdf14_accum *)(pdev->target))->save_p14dev);
        pdev->pclist_device = pdev->target;         /* FIXME: is this kosher ? */
        *pcdev = pdev->target;			    /* pass upwards to switch devices */
        pdev->color_info = target->color_info;      /* same as in pdf14_disable_clist */
        gs_free_object(tdev->memory, tdev, "popdevice pdf14-accum");
        return 0;		/* DON'T perform set_target */
    }

    if (*pcdev != pdev->target)
        gx_device_set_target((gx_device_forward *)pdev, *pcdev);
    *pcdev = dev;
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_clist_fill_path(gx_device	*dev, const gs_gstate *pgs,
                           gx_path *ppath, const gx_fill_params *params,
                           const gx_drawing_color *pdcolor,
                           const gx_clip_path *pcpath)
{
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
    gs_gstate new_pgs = *pgs;
    int code;
    gs_pattern2_instance_t *pinst = NULL;
    gx_device_forward * fdev = (gx_device_forward *)dev;
    cmm_dev_profile_t *dev_profile, *fwd_profile;
    gsicc_rendering_param_t render_cond;
    cmm_profile_t *icc_profile_fwd, *icc_profile_dev;

    code = dev_proc(dev, get_profile)(dev,  &dev_profile);
    if (code < 0)
        return code;
    code = dev_proc(fdev->target, get_profile)(fdev->target,  &fwd_profile);
    if (code < 0)
        return code;

    gsicc_extract_profile(GS_UNKNOWN_TAG, fwd_profile, &icc_profile_fwd,
                          &render_cond);
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile_dev,
                          &render_cond);

    /*
     * Ensure that that the PDF 1.4 reading compositor will have the current
     * blending parameters.  This is needed since the fill_rectangle routines
     * do not have access to the gs_gstate.  Thus we have to pass any
     * changes explictly.
     */
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
    if (code < 0)
        return code;
    /* If we are doing a shading fill and we are in a transparency group of a
       different color space, then we do not want to do the shading in the
       device color space. It must occur in the source space.  To handle it in
       the device space would require knowing all the nested transparency group
       color space as well as the transparency.  Some of the shading code ignores
       this, so we have to pass on the clist_writer device to enable proper
       mapping to the transparency group color space. */

    if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor)) {
        pinst =
            (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
           pinst->saved->has_transparency = true;
           /* The transparency color space operations are driven by the pdf14
              clist writer device.  */
           pinst->saved->trans_device = dev;
    }
    update_lop_for_pdf14(&new_pgs, pdcolor);
    new_pgs.trans_device = dev;
    new_pgs.has_transparency = true;
    code = gx_forward_fill_path(dev, &new_pgs, ppath, params, pdcolor, pcpath);
    new_pgs.trans_device = NULL;
    new_pgs.has_transparency = false;
    if (pinst != NULL){
        pinst->saved->trans_device = NULL;
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_clist_stroke_path(gx_device *dev,	const gs_gstate *pgs,
                             gx_path *ppath, const gx_stroke_params *params,
                             const gx_drawing_color *pdcolor,
                             const gx_clip_path *pcpath)
{
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
    gs_gstate new_pgs = *pgs;
    int code;
    gs_pattern2_instance_t *pinst = NULL;

    /*
     * Ensure that that the PDF 1.4 reading compositor will have the current
     * blending parameters.  This is needed since the fill_rectangle routines
     * do not have access to the gs_gstate.  Thus we have to pass any
     * changes explictly.
     */
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
    if (code < 0)
        return code;
    /* If we are doing a shading stroke and we are in a transparency group of a
       different color space, then we need to get the proper device information
       passed along so that we use the correct color procs and colorinfo about
       the transparency device and not the final target device */
    if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor) &&
        pdev->trans_group_parent_cmap_procs != NULL) {
        pinst =
            (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
           pinst->saved->has_transparency = true;
           /* The transparency color space operations are driven
              by the pdf14 clist writer device.  */
           pinst->saved->trans_device = dev;
    }

    update_lop_for_pdf14(&new_pgs, pdcolor);
    new_pgs.trans_device = dev;
    new_pgs.has_transparency = true;
    code = gx_forward_stroke_path(dev, &new_pgs, ppath, params, pdcolor, pcpath);
    new_pgs.trans_device = NULL;
    new_pgs.has_transparency = false;
    if (pinst != NULL){
        pinst->saved->trans_device = NULL;
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
     const gs_gstate * pgs, gx_device * dev, gs_color_select_t select,
     const gs_color_space *pcs)
{
    int i,ncomps;
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index color;
    gx_device *trans_device;

    /* If trans device is set, we need to use its procs. */
    if (pgs->trans_device != NULL){
        trans_device = pgs->trans_device;
    } else {
        trans_device = dev;
    }
    ncomps = trans_device->color_info.num_components;
    /* map to the color model */
    dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_cmyk(trans_device, c, m, y, k, cm_comps);
    for (i = 0; i < ncomps; i++)
        cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
    /* if output device supports devn, we need to make sure we send it the
       proper color type */
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
        for (i = 0; i < ncomps; i++)
            pdc->colors.devn.values[i] = cv[i];
        pdc->type = gx_dc_type_devn;
    } else {
    /* encode as a color index */
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
        /* check if the encoding was successful; we presume failure is rare */
        if (color != gx_no_color_index)
            color_set_pure(pdc, color);
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_cmap_devicen_direct(const	frac * pcc,
    gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev,
    gs_color_select_t select)
{
    int i, ncomps = dev->color_info.num_components;
    int num_spots = pdf14_get_num_spots(dev);
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index color;
    gx_device *trans_device;

     /*  We may be coming from the clist writer which often forwards us the
         target device. If this occurs we actually need to get to the color
         space defined by the transparency group and we use the operators
         defined by the transparency device to do the job.
       */
    if (pgs->trans_device != NULL){
        trans_device = pgs->trans_device;
    } else {
        trans_device = dev;
    }
    ncomps = trans_device->color_info.num_components;
    /* map to the color model */
    map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps);;
    /* apply the transfer function(s); convert to color values */
    if (trans_device->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) {
        for (i = 0; i < ncomps; i++)
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
        /* We are in an additive mode (blend space) and drawing with a sep color
        into a sep device.  Make sure we are drawing "white" with the process
        colorants */
        for (i = 0; i < ncomps - num_spots; i++)
            cv[i] = gx_max_color_value;
    } else
        for (i = 0; i < ncomps; i++)
            cv[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, (frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
    /* if output device supports devn, we need to make sure we send it the
       proper color type */
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
        for (i = 0; i < ncomps; i++)
            pdc->colors.devn.values[i] = cv[i];
        pdc->type = gx_dc_type_devn;
    } else {
    /* encode as a color index */
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
        /* check if the encoding was successful; we presume failure is rare */
        if (color != gx_no_color_index)
            color_set_pure(pdc, color);
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_gstate * pgs,
                 gx_device * dev, gs_color_select_t select)
{
    int i,ncomps;
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index color;
    gx_device *trans_device;

    /* If trans device is set, we need to use its procs. */
    if (pgs->trans_device != NULL) {
        trans_device = pgs->trans_device;
    } else {
        trans_device = dev;
    }
    ncomps = trans_device->color_info.num_components;
    /* map to the color model */
    dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_gray(trans_device, gray, cm_comps);

    /* If we are in a Gray blending color space and have spots then we have
     * possibly an issue here with the transfer function */
    if (pgs->trans_device != NULL) {
        cv[0] = frac2cv(gx_map_color_frac(pgs, cm_comps[0], effective_transfer[0]));
        for (i = 1; i < ncomps; i++)
            cv[i] = gx_color_value_from_byte(cm_comps[i]);
    } else {
        /* Not a transparency device.  Just use the transfer functions directly */
        for (i = 0; i < ncomps; i++)
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
    }

    /* if output device supports devn, we need to make sure we send it the
    proper color type.  We now support Gray + spots as devn colors */
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
        for (i = 0; i < ncomps; i++)
            pdc->colors.devn.values[i] = cv[i];
        pdc->type = gx_dc_type_devn;
    } else {
        /* encode as a color index */
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
        /* check if the encoding was successful; we presume failure is rare */
        if (color != gx_no_color_index)
            color_set_pure(pdc, color);
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_cmap_rgb_direct(frac r, frac g, frac b, gx_device_color *	pdc,
     const gs_gstate * pgs, gx_device * dev, gs_color_select_t select)
{
    int i,ncomps;
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index color;
    gx_device *trans_device;

    /* If trans device is set, we need to use its procs. */
    if (pgs->trans_device != NULL){
        trans_device = pgs->trans_device;
    } else {
        trans_device = dev;
    }
    ncomps = trans_device->color_info.num_components;
    /* map to the color model */
    dev_proc(trans_device, get_color_mapping_procs)(trans_device)->map_rgb(trans_device, pgs, r, g, b, cm_comps);

    /* If we are in an RGB blending color space and have spots then we have
    * possibly an issue here with the transfer function */
    if (pgs->trans_device != NULL) {
        for (i = 0; i < 3; i++)
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
        for (i = 3; i < ncomps; i++)
            cv[i] = gx_color_value_from_byte(cm_comps[i]);
    } else {
        /* Not a transparency device.  Just use the transfer functions directly */
        for (i = 0; i < ncomps; i++)
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
    }

    /* if output device supports devn, we need to make sure we send it the
       proper color type.  We now support RGB + spots as devn colors */
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
        for (i = 0; i < ncomps; i++)
            pdc->colors.devn.values[i] = cv[i];
        pdc->type = gx_dc_type_devn;
    } else {
        /* encode as a color index */
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
        /* check if the encoding was successful; we presume failure is rare */
        if (color != gx_no_color_index)
            color_set_pure(pdc, color);
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_cmap_separation_direct(frac all, gx_device_color * pdc, const gs_gstate * pgs,
                 gx_device * dev, gs_color_select_t select)
{
    int i, ncomps = dev->color_info.num_components;
    int num_spots = pdf14_get_num_spots(dev);
    bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE;
    frac comp_value = all;
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index color;

    if (pgs->color_component_map.sep_type == SEP_ALL) {
        /*
         * Invert the photometric interpretation for additive
         * color spaces because separations are always subtractive.
         */
        if (additive)
            comp_value = frac_1 - comp_value;
        /* Use the "all" value for all components */
        i = pgs->color_component_map.num_colorants - 1;
        for (; i >= 0; i--)
            cm_comps[i] = comp_value;
    } else {
        /* map to the color model */
        map_components_to_colorants(&comp_value, &(pgs->color_component_map), cm_comps);
    }
    /* apply the transfer function(s); convert to color values */
    if (additive) {
        for (i = 0; i < ncomps; i++)
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
        /* We are in an additive mode (blend space) and drawing with a sep color
        into a sep device.  Make sure we are drawing "white" with the process
        colorants, but only if we are not in an ALL case */
        if (pgs->color_component_map.sep_type != SEP_ALL)
            for (i = 0; i < ncomps - num_spots; i++)
                cv[i] = gx_max_color_value;
    } else
        for (i = 0; i < ncomps; i++)
            cv[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, (frac)(frac_1 - cm_comps[i]), effective_transfer[i]));


    /* if output device supports devn, we need to make sure we send it the
       proper color type */
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) {
        for (i = 0; i < ncomps; i++)
            pdc->colors.devn.values[i] = cv[i];
        pdc->type = gx_dc_type_devn;
    } else {
        /* encode as a color index */
        color = dev_proc(dev, encode_color)(dev, cv);
        /* check if the encoding was successful; we presume failure is rare */
        if (color != gx_no_color_index)
            color_set_pure(pdc, color);
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_cmykspot_get_color_comp_index(gx_device * dev, const char * pname,
    int name_size, int component_type)
{
    return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 4);
}

Project: ghostscript
File: gdevp14.c

pdf14_compute_group_device_int_rect(const gs_matrix *ctm,
                                    const gs_rect *pbbox, gs_int_rect *rect)
{
    gs_rect dev_bbox;
    int code;

    code = gs_bbox_transform(pbbox, ctm, &dev_bbox);
    if (code < 0)
        return code;
    rect->p.x = (int)floor(dev_bbox.p.x);
    rect->p.y = (int)floor(dev_bbox.p.y);
    rect->q.x = (int)ceil(dev_bbox.q.x);
    rect->q.y = (int)ceil(dev_bbox.q.y);
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_copy_mono(gx_device * dev,
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
{
    const byte *sptr;
    const byte *line;
    int sbit, first_bit;
    int code, sbyte, bit, count;
    int run_length, startx, current_bit, bit_value;
    gx_color_index current_color;

    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
    line = base + (sourcex >> 3);
    sbit = sourcex & 7;
    first_bit = 7 - sbit;

    /* Loop through the height of the specfied area. */
    while (h-- > 0) {
        /* Set up for the start of each line of the area. */
        sptr = line;
        sbyte = *sptr++;
        bit = first_bit;
        count = w;
        run_length = 0;
        startx = x;
        current_bit = 0;
        current_color = zero;

        /* Loop across each pixel of a line. */
        do {
            bit_value = (sbyte >> bit) & 1;
            if (bit_value == current_bit) {
                /* The value did not change, simply increment our run length */
                run_length++;
            } else {
                /* The value changed, fill the current rectangle. */
                if (run_length != 0) {
                    if (current_color != gx_no_color_index) {
                        code = (*dev_proc(dev, fill_rectangle))
                                (dev, startx, y, run_length, 1, current_color);
                        if (code < 0)
                            return code;
                    }
                    startx += run_length;
                }
                run_length = 1;
                current_color = bit_value ? one : zero;
                current_bit = bit_value;
            }
            /* Move to the next input bit. */
            if (bit == 0) {
                bit = 7;
                sbyte = *sptr++;
            }
            else
                bit--;
        } while (--count > 0);
        /* Fill the last rectangle in the line. */
        if (run_length != 0 && current_color != gx_no_color_index) {
            code = (*dev_proc(dev, fill_rectangle))
                        (dev, startx, y, run_length, 1, current_color);
            if (code < 0)
                return code;
        }
        /* Move to the next line */
        line += sraster;
        y++;
    }
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_copy_planes(gx_device * dev, const byte * data, int data_x, int raster,
                  gx_bitmap_id id, int x, int y, int w, int h, int plane_height)
{
    pdf14_device *pdev = (pdf14_device *)dev;
#if RAW_DUMP
    pdf14_ctx *ctx = pdev->ctx;
#endif
    pdf14_buf *buf = pdev->ctx->stack;
    uchar num_planes = dev->color_info.num_components;
    byte *dptr = (byte *)data + data_x;
    int yinc, xinc;
    uchar pi;
    gx_drawing_color dcolor;
    int code = 0;

    fit_fill_xywh(dev, x, y, w, h);
    if (w <= 0 || h <= 0)
        return 0;

    dcolor.type = gx_dc_type_devn;
    /* Because of the complexity of the blending and my desire to finish
       this planar sep device work, I am going to make this a series of
       rect fills.  ToDo: optimize this for more efficient planar operation.
       It would be interesting to use the put_image procedure. */
    for (yinc = 0; yinc < h; yinc++) {
        for (xinc = 0; xinc < w; xinc++) {
            for (pi = 0; pi < num_planes; pi++) {
                dcolor.colors.devn.values[pi] = *(dptr + plane_height * raster * pi) << 8;
            }
            if (buf->knockout)
                code =
                    pdf14_mark_fill_rectangle_ko_simple(dev, x + xinc,
                                                        y + yinc, 1, 1, 0,
                                                        &dcolor, true);
            else
                code =
                    pdf14_mark_fill_rectangle(dev, x + xinc, y + yinc, 1, 1, 0,
                                               &dcolor, true);
            if (code < 0)
                return code;
            dptr++;
        }
        dptr = (byte *)data + raster * yinc + data_x;
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_create_clist_device(gs_memory_t *mem, gs_gstate * pgs,
                                gx_device ** ppdev, gx_device * target,
                                const gs_pdf14trans_t * pdf14pct)
{
    pdf14_clist_device * dev_proto;
    pdf14_clist_device * pdev, temp_dev_proto;
    int code;
    bool has_tags = target->graphics_type_tag & GS_DEVICE_ENCODES_TAGS;
    cmm_profile_t *target_profile;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;
    uchar k;

    code = dev_proc(target, get_profile)(target,  &dev_profile);
    if (code < 0)
        return code;
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &target_profile,
                          &render_cond);
    if_debug0m('v', pgs->memory, "[v]pdf14_create_clist_device\n");
    code = get_pdf14_clist_device_proto(target, &dev_proto,
                                 &temp_dev_proto, pgs, pdf14pct, false);
    if (code < 0)
        return code;
    code = gs_copydevice((gx_device **) &pdev,
                         (const gx_device *) dev_proto, mem);
    if (code < 0)
        return code;
    /* The number of color planes should not exceed that of the target */
    if (pdev->color_info.num_components > target->color_info.num_components)
        pdev->color_info.num_components = target->color_info.num_components;
    if (pdev->color_info.max_components > target->color_info.max_components)
        pdev->color_info.max_components = target->color_info.max_components;
    pdev->color_info.depth = pdev->color_info.num_components * 8;
    pdev->pad = target->pad;
    pdev->log2_align_mod = target->log2_align_mod;
    pdev->is_planar = target->is_planar;
    /* If we have a tag device then go ahead and do a special encoder decoder
       for the pdf14 device to make sure we maintain this information in the
       encoded color information.  We could use the target device's methods but
       the PDF14 device has to maintain 8 bit color always and we could run
       into other issues if the number of colorants became large.  If we need to
       do compressed color with tags that will be a special project at that time */
    if (has_tags) {
        pdev->procs.encode_color = pdf14_encode_color_tag;
        pdev->color_info.depth += 8;
    }
    check_device_separable((gx_device *)pdev);
    gx_device_fill_in_procs((gx_device *)pdev);
    gs_pdf14_device_copy_params((gx_device *)pdev, target);
    gx_device_set_target((gx_device_forward *)pdev, target);
    /* Components shift, etc have to be based upon 8 bit */
    for (k = 0; k < pdev->color_info.num_components; k++) {
        pdev->color_info.comp_bits[k] = 8;
        pdev->color_info.comp_shift[k] = (pdev->color_info.num_components - 1 - k) * 8;
    }
    code = dev_proc((gx_device *) pdev, open_device) ((gx_device *) pdev);
    pdev->pclist_device = target;
    /* If the target profile was CIELAB, then overide with default RGB for
       proper blending.  During put_image we will convert from RGB to
       CIELAB */
    if ((target_profile->data_cs == gsCIELAB || target_profile->islab) &&
        !pdev->using_blend_cs) {
        rc_assign(pdev->icc_struct->device_profile[0],
                  pgs->icc_manager->default_rgb, "pdf14_create_clist_device");
    }
    pdev->my_encode_color = pdev->procs.encode_color;
    pdev->my_decode_color = pdev->procs.decode_color;
    pdev->my_get_color_mapping_procs = pdev->procs.get_color_mapping_procs;
    pdev->my_get_color_comp_index = pdev->procs.get_color_comp_index;
    pdev->color_info.separable_and_linear =
        target->color_info.separable_and_linear;
    *ppdev = (gx_device *) pdev;
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_ctx_free(pdf14_ctx *ctx)
{
    pdf14_buf *buf, *next;

    if (ctx->mask_stack) {
        /* A mask was created but was not used in this band. */
        rc_decrement(ctx->mask_stack->rc_mask, "pdf14_ctx_free");
        gs_free_object(ctx->memory,ctx->mask_stack,"pdf14_ctx_free");
    }
    for (buf = ctx->stack; buf != NULL; buf = next) {
        next = buf->saved;
        pdf14_buf_free(buf, ctx->memory);
    }
    gs_free_object (ctx->memory, ctx, "pdf14_ctx_free");
}

Project: ghostscript
File: gdevp14.c

pdf14_ctx_new(gs_int_rect *rect, int n_chan, bool additive, gx_device *dev)
{
    pdf14_ctx *result;
    pdf14_buf *buf;
    gs_memory_t	*memory = dev->memory;
    bool has_tags = dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS;
    pdf14_device *pdev = (pdf14_device *)dev;

    result = gs_alloc_struct(memory, pdf14_ctx, &st_pdf14_ctx, "pdf14_ctx_new");
    if (result == NULL)
        return result;
    /* Note:  buffer creation expects alpha to be in number of channels */
    buf = pdf14_buf_new(rect, has_tags, false, false, false, n_chan + 1,
                        pdev->devn_params.page_spot_colors, memory);
    if (buf == NULL) {
        gs_free_object(memory, result, "pdf14_ctx_new");
        return NULL;
    }
    if_debug4m('v', memory,
               "[v]base buf: %d x %d, %d color channels, %d planes\n",
               buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes);
    if (buf->data != NULL) {
        if (buf->has_tags) {
            memset(buf->data, 0, buf->planestride * (buf->n_planes-1));
        } else {
            memset(buf->data, 0, buf->planestride * buf->n_planes);
        }
    }
    buf->saved = NULL;
    result->stack = buf;
    result->mask_stack = pdf14_mask_element_new(memory);
    result->mask_stack->rc_mask = pdf14_rcmask_new(memory);
    result->n_chan = n_chan;
    result->memory = memory;
    result->rect = *rect;
    result->additive = additive;
    result->smask_depth = 0;
    result->smask_blend = false;
    return result;
}

Project: ghostscript
File: gdevp14.c

pdf14_debug_mask_stack_state(pdf14_ctx *ctx)
{
    if_debug1m('v', ctx->memory, "[v]ctx_maskstack, %x\n", ctx->mask_stack);
    if (ctx->mask_stack != NULL) {
        dump_mask_stack(ctx->mask_stack);
    }
    if_debug1m('v', ctx->memory, "[v]ctx_stack, %x\n", ctx->stack);
    if (ctx->stack != NULL) {
        if_debug1m('v', ctx->memory, "[v]ctx_stack_maskstack, %x\n", ctx->stack->mask_stack);
        if (ctx->stack->mask_stack != NULL) {
            dump_mask_stack(ctx->stack->mask_stack);
        }
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_decrement_smask_color(gs_gstate * pgs, gx_device * dev)
{
    pdf14_device * pdev = (pdf14_device *) dev;
    pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor;
    gsicc_manager_t *icc_manager = pgs->icc_manager;
    int k;

    /* See comment in pdf14_increment_smask_color to understand this one */
    if (pdev->smaskcolor == NULL && pgs->icc_manager->smask_profiles != NULL &&
        pgs->icc_manager->smask_profiles->swapped) {
            return 0;
    }
    if (smaskcolor != NULL) {
        smaskcolor->ref_count--;
        if_debug1m(gs_debug_flag_icc, pgs->memory,
                   "[icc] Decrement smask color.  Now %d\n",
                   smaskcolor->ref_count);
        if (smaskcolor->ref_count == 0) {
            if_debug0m(gs_debug_flag_icc, pgs->memory, "[icc] Reset smask color.\n");
            /* Lets return the profiles and clean up */
            /* First see if we need to "reset" the profiles that are in
               the graphic state */
            if_debug0m(gs_debug_flag_icc, pgs->memory, "[icc] Reseting graphic state color spaces\n");
            for (k = 0; k < 2; k++) {
                gs_color_space *pcs = pgs->color[k].color_space;
                cmm_profile_t  *profile = pcs->cmm_icc_profile_data;
                if (profile != NULL) {
                    switch(profile->data_cs) {
                        case gsGRAY:
                            if (profile->hashcode ==
                                pgs->icc_manager->default_gray->hashcode) {
                                    profile =
                                        smaskcolor->profiles->smask_gray;
                            }
                            break;
                        case gsRGB:
                            if (profile->hashcode ==
                                pgs->icc_manager->default_rgb->hashcode) {
                                    profile =
                                        smaskcolor->profiles->smask_rgb;
                            }
                            break;
                        case gsCMYK:
                            if (profile->hashcode ==
                                pgs->icc_manager->default_cmyk->hashcode) {
                                    profile =
                                        smaskcolor->profiles->smask_cmyk;
                            }
                            break;
                        default:

                            break;
                    }
                    rc_assign(pcs->cmm_icc_profile_data, profile,
                              "pdf14_decrement_smask_color");
                }
            }

            icc_manager->default_gray = smaskcolor->profiles->smask_gray;
            icc_manager->default_rgb = smaskcolor->profiles->smask_rgb;
            icc_manager->default_cmyk = smaskcolor->profiles->smask_cmyk;
            icc_manager->smask_profiles->swapped = false;
            /* We didn't increment the reference count when we assigned these
             * so NULL them to avoid decrementing when smaskcolor is freed
             */
            smaskcolor->profiles->smask_gray =
              smaskcolor->profiles->smask_rgb =
              smaskcolor->profiles->smask_cmyk = NULL;

            pdf14_free_smask_color(pdev);
        }
    }
    return(0);
}

Project: ghostscript
File: gdevp14.c

pdf14_device_finalize(const gs_memory_t *cmem, void *vptr)
{
    gx_device * const dev = (gx_device *)vptr;
    pdf14_device * pdev = (pdf14_device *)dev;

    pdf14_cleanup_parent_color_profiles (pdev);

    if (pdev->ctx) {
        pdf14_ctx_free(pdev->ctx);
        pdev->ctx = NULL;
    }

    while (pdev->trans_group_parent_cmap_procs) {
        pdf14_pop_parent_color(dev, NULL);
    }
    gx_device_finalize(cmem, vptr);
}

Project: ghostscript
File: gdevp14.c

pdf14_discard_trans_layer(gx_device *dev, gs_gstate * pgs)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    /* The things that need to be cleaned up */
    pdf14_ctx *ctx = pdev->ctx;
    pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor;
    pdf14_parent_color_t *group_procs = pdev->trans_group_parent_cmap_procs;

    /* Free up the smask color */
    if (smaskcolor != NULL) {
        smaskcolor->ref_count = 1;
        pdf14_decrement_smask_color(pgs, dev);
        pdev->smaskcolor = NULL;
    }

    /* Free up the nested color procs and decrement the profiles */
    if (group_procs != NULL) {
        while (group_procs->previous != NULL)
            pdf14_pop_parent_color(dev, pgs);
        gs_free_object(dev->memory, group_procs, "pdf14_discard_trans_layer");
        pdev->trans_group_parent_cmap_procs = NULL;
    }

    /* Start the contex clean up */
    if (ctx != NULL) {
        pdf14_buf *buf, *next;
        pdf14_parent_color_t *procs, *prev_procs;

        if (ctx->mask_stack != NULL) {
            pdf14_free_mask_stack(ctx, ctx->memory);
        }

        /* Now the stack of buffers */
        for (buf = ctx->stack; buf != NULL; buf = next) {
            next = buf->saved;

            gs_free_object(ctx->memory, buf->transfer_fn, "pdf14_discard_trans_layer");
            gs_free_object(ctx->memory, buf->matte, "pdf14_discard_trans_layer");
            gs_free_object(ctx->memory, buf->data, "pdf14_discard_trans_layer");
            gs_free_object(ctx->memory, buf->backdrop, "pdf14_discard_trans_layer");
            /* During the soft mask push, the mask_stack was copied (not moved) from
               the ctx to the tos mask_stack. We are done with this now so it is safe
               to free this one object */
            gs_free_object(ctx->memory, buf->mask_stack, "pdf14_discard_trans_layer");
            for (procs = buf->parent_color_info_procs; procs != NULL; procs = prev_procs) {
                prev_procs = procs->previous;
                gs_free_object(ctx->memory, procs, "pdf14_discard_trans_layer");
            }
            gs_free_object(ctx->memory, buf, "pdf14_discard_trans_layer");
        }
        /* Finally the context itself */
        gs_free_object (ctx->memory, ctx, "pdf14_discard_trans_layer");
        pdev->ctx = NULL;
    }
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_end_transparency_group(gx_device *dev,
                              gs_gstate *pgs)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    int code;
    pdf14_parent_color_t *parent_color;
    cmm_profile_t *group_profile;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;

    code = dev_proc(dev, get_profile)(dev,  &dev_profile);
    if (code < 0)
        return code;
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile,
                          &render_cond);
    if_debug0m('v', dev->memory, "[v]pdf14_end_transparency_group\n");
    code = pdf14_pop_transparency_group(pgs, pdev->ctx, pdev->blend_procs,
                                pdev->color_info.num_components, group_profile,
                                (gx_device *) pdev);
#ifdef DEBUG
    pdf14_debug_mask_stack_state(pdev->ctx);
#endif
   /* May need to reset some color stuff related
     * to a mismatch between the parents color space
     * and the group blending space */
    parent_color = pdev->ctx->stack->parent_color_info_procs;
        if (!(parent_color->parent_color_mapping_procs == NULL &&
                parent_color->parent_color_comp_index == NULL)) {
            pgs->get_cmap_procs = parent_color->get_cmap_procs;
            gx_set_cmap_procs(pgs, dev);
            pdev->procs.get_color_mapping_procs =
                parent_color->parent_color_mapping_procs;
            pdev->procs.get_color_comp_index =
                parent_color->parent_color_comp_index;
            pdev->color_info.polarity = parent_color->polarity;
            pdev->color_info.num_components = parent_color->num_components;
            pdev->blend_procs = parent_color->parent_blending_procs;
            pdev->ctx->additive = parent_color->isadditive;
            pdev->pdf14_procs = parent_color->unpack_procs;
            pdev->color_info.depth = parent_color->depth;
            pdev->color_info.max_color = parent_color->max_color;
            pdev->color_info.max_gray = parent_color->max_gray;
            memcpy(&(pdev->color_info.comp_bits),&(parent_color->comp_bits),
                            GX_DEVICE_COLOR_MAX_COMPONENTS);
            memcpy(&(pdev->color_info.comp_shift),&(parent_color->comp_shift),
                            GX_DEVICE_COLOR_MAX_COMPONENTS);
            parent_color->get_cmap_procs = NULL;
            parent_color->parent_color_comp_index = NULL;
            parent_color->parent_color_mapping_procs = NULL;
        if (parent_color->icc_profile != NULL) {
            /* make sure to decrement the device profile.  If it was allocated
               with the push then it will be freed. */
            rc_decrement(group_profile,"pdf14_end_transparency_group");
            dev->icc_struct->device_profile[0] = parent_color->icc_profile;
            rc_decrement(parent_color->icc_profile,"pdf14_end_transparency_group");
            parent_color->icc_profile = NULL;
        }
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_parent_color_t *parent_color;
    int ok;

    if_debug0m('v', dev->memory, "pdf14_end_transparency_mask\n");
    ok = pdf14_pop_transparency_mask(pdev->ctx, pgs, dev);
#ifdef DEBUG
    pdf14_debug_mask_stack_state(pdev->ctx);
#endif
    /* May need to reset some color stuff related
     * to a mismatch between the Smask color space
     * and the Smask blending space */
    if (pdev->ctx->stack != NULL ) {
        parent_color = pdev->ctx->stack->parent_color_info_procs;
        if (!(parent_color->parent_color_mapping_procs == NULL &&
            parent_color->parent_color_comp_index == NULL)) {
            pgs->get_cmap_procs = parent_color->get_cmap_procs;
            gx_set_cmap_procs(pgs, dev);
            pdev->procs.get_color_mapping_procs = parent_color->parent_color_mapping_procs;
            pdev->procs.get_color_comp_index = parent_color->parent_color_comp_index;
            pdev->color_info.polarity = parent_color->polarity;
            pdev->color_info.num_components = parent_color->num_components;
            pdev->color_info.depth = parent_color->depth;
            pdev->blend_procs = parent_color->parent_blending_procs;
            pdev->ctx->additive = parent_color->isadditive;
            pdev->pdf14_procs = parent_color->unpack_procs;
            pdev->color_info.max_color = parent_color->max_color;
            pdev->color_info.max_gray = parent_color->max_gray;
            parent_color->get_cmap_procs = NULL;
            parent_color->parent_color_comp_index = NULL;
            parent_color->parent_color_mapping_procs = NULL;
            pdev->procs.encode_color = parent_color->encode;
            pdev->procs.decode_color = parent_color->decode;
            memcpy(&(pdev->color_info.comp_bits),&(parent_color->comp_bits),
                                GX_DEVICE_COLOR_MAX_COMPONENTS);
            memcpy(&(pdev->color_info.comp_shift),&(parent_color->comp_shift),
                                GX_DEVICE_COLOR_MAX_COMPONENTS);
            /* Take care of the ICC profile */
            if (parent_color->icc_profile != NULL) {
                rc_decrement(dev->icc_struct->device_profile[0],"pdf14_end_transparency_mask");
                dev->icc_struct->device_profile[0] = parent_color->icc_profile;
                rc_decrement(parent_color->icc_profile,"pdf14_end_transparency_mask");
                parent_color->icc_profile = NULL;
            }
        }
    }
    return ok;
}

Project: ghostscript
File: gdevp14.c

pdf14_fill_rectangle(gx_device * dev,
                    int x, int y, int w, int h, gx_color_index color)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_buf *buf = pdev->ctx->stack;

    fit_fill_xywh(dev, x, y, w, h);
    if (w <= 0 || h <= 0)
        return 0;
    if (buf->knockout)
        return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color, NULL,
                                                   false);
    else
        return pdf14_mark_fill_rectangle(dev, x, y, w, h, color, NULL, false);
}

Project: ghostscript
File: gdevp14.c

pdf14_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
    const gs_gstate *pgs, const gx_drawing_color *pdcolor,
    const gx_clip_path *pcpath)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_buf *buf = pdev->ctx->stack;
    int x = fixed2int(rect->p.x);
    int y = fixed2int(rect->p.y);
    int w = fixed2int(rect->q.x) - x;
    int h = fixed2int(rect->q.y) -y;

    fit_fill_xywh(dev, x, y, w, h);
    if (w <= 0 || h <= 0)
        return 0;
    if (buf->knockout)
        return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, 0, pdcolor,
                                                   true);
    else
        return pdf14_mark_fill_rectangle(dev, x, y, w, h, 0, pdcolor, true);
}

Project: ghostscript
File: gdevp14.c

pdf14_free_smask_color(pdf14_device * pdev)
{
    if (pdev->smaskcolor != NULL) {
        if ( pdev->smaskcolor->profiles != NULL) {
            /* Do not decrement the softmask enties.  They will remain
               in the icc_manager softmask member.  They were not
               incremented when moved here */
            gs_free_object(pdev->memory, pdev->smaskcolor->profiles,
                        "pdf14_free_smask_color");
        }
        gs_free_object(pdev->memory, pdev->smaskcolor, "pdf14_free_smask_color");
        pdev->smaskcolor = NULL;
    }
}

Project: ghostscript
File: gdevp14.c

pdf14_get_buffer_information(const gx_device * dev,
                             gx_pattern_trans_t *transbuff, gs_memory_t *mem,
                             bool free_device)
{
    const pdf14_device * pdev = (pdf14_device *)dev;
    pdf14_buf *buf;
    gs_int_rect rect;
    int x1,y1,width,height;

    if ( pdev->ctx == NULL){
        return 0;  /* this can occur if the pattern is a clist */
    }
#ifdef DEBUG
    pdf14_debug_mask_stack_state(pdev->ctx);
#endif
    buf = pdev->ctx->stack;
    rect = buf->rect;
    transbuff->dirty = &buf->dirty;
    x1 = min(pdev->width, rect.q.x);
    y1 = min(pdev->height, rect.q.y);
    width = x1 - rect.p.x;
    height = y1 - rect.p.y;
    if (width <= 0 || height <= 0 || buf->data == NULL)
        return 0;
    transbuff->n_chan    = buf->n_chan;
    transbuff->has_shape = buf->has_shape;
    transbuff->width     = buf->rect.q.x - buf->rect.p.x;
    transbuff->height    = buf->rect.q.y - buf->rect.p.y;

    if (free_device) {
        transbuff->pdev14 = NULL;
        transbuff->rect = rect;
        if ((width < transbuff->width) || (height < transbuff->height)) {
            /* If the bbox is smaller than the whole buffer than go ahead and
               create a new one to use.  This can occur if we drew in a smaller
               area than was specified by the transparency group rect. */
            int rowstride = (width + 3) & -4;
            int planestride = rowstride * height;
            int k, j;
            byte *buff_ptr_src, *buff_ptr_des;

            transbuff->planestride = planestride;
            transbuff->rowstride = rowstride;
            transbuff->transbytes = gs_alloc_bytes(mem, planestride*buf->n_chan,
                                                   "pdf14_get_buffer_information");
            transbuff->mem = mem;
            for (j = 0; j < transbuff->n_chan; j++) {
                buff_ptr_src = buf->data + j * buf->planestride +
                           buf->rowstride * rect.p.y + rect.p.x;
                buff_ptr_des = transbuff->transbytes + j * planestride;
                for (k = 0; k < height; k++) {
                    memcpy(buff_ptr_des, buff_ptr_src,rowstride);
                    buff_ptr_des += rowstride;
                    buff_ptr_src += buf->rowstride;
                }
            }

        } else {
            /* The entire buffer is used.  Go ahead and grab the pointer and
               clear the pointer in the pdf14 device data buffer so it is not
               freed when we close the device */
            transbuff->planestride = buf->planestride;
            transbuff->rowstride = buf->rowstride;
            transbuff->transbytes = buf->data;
            transbuff->mem = dev->memory;
            buf->data = NULL;  /* So that the buffer is not freed */
        }
        /* Go ahead and free up the pdf14 device */
        dev_proc(dev, close_device)((gx_device *)dev);
#if RAW_DUMP
        /* Dump the buffer that should be going into the pattern */;
        dump_raw_buffer(height, width, transbuff->n_chan,
                    transbuff->planestride, transbuff->rowstride,
                    "pdf14_pattern_buff", transbuff->transbytes);
        global_index++;
#endif
    } else {
        /* Here we are coming from one of the fill image / pattern / mask
           operations */
        transbuff->pdev14 = dev;
        transbuff->planestride = buf->planestride;
        transbuff->rowstride = buf->rowstride;
        transbuff->transbytes = buf->data;
        transbuff->mem = dev->memory;
        transbuff->rect = rect;
#if RAW_DUMP
    /* Dump the buffer that should be going into the pattern */;
        dump_raw_buffer(height, width, buf->n_chan,
                    pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                    "pdf14_pattern_buff", buf->data +
                    transbuff->rowstride * transbuff->rect.p.y +
                    transbuff->rect.p.x);
        global_index++;
#endif
    }
    return(0);
}

Project: ghostscript
File: gdevp14.c

pdf14_get_cmap_procs(const gs_gstate *pgs, const gx_device * dev)
{
    /* The pdf14 marking device itself is always continuous tone. */
    return &pdf14_cmap_many;
}

Project: ghostscript
File: gdevp14.c

pdf14_get_num_spots(gx_device * dev)
{
    cmm_dev_profile_t *dev_profile;
    cmm_profile_t *icc_profile;
    gsicc_rendering_param_t render_cond;

    dev_proc(dev, get_profile)(dev, &dev_profile);
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
        &render_cond);
    return dev->color_info.num_components - icc_profile->num_comps;
}

Project: ghostscript
File: gdevp14.c

pdf14_grayspot_get_color_comp_index(gx_device * dev, const char * pname,
    int name_size, int component_type)
{
    return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 1);
}

Project: ghostscript
File: gdevp14.c

pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev)
{
    pdf14_device * pdev = (pdf14_device *) dev;
    pdf14_smaskcolor_t *result;
    gsicc_smask_t *smask_profiles = pgs->icc_manager->smask_profiles;
    int k;

    /* See if we have profiles already in place.   Note we also have to
       worry about a corner case where this device does not have a
       smaskcolor stucture to store the profiles AND the profiles were
       already swapped out in the icc_manager.  This can occur when we
       pushed a transparency mask and then inside the mask we have a pattern
       which also has a transparency mask.   The state of the icc_manager
       is that it already has done the swap and there is no need to fool
       with any of this while dealing with the soft mask within the pattern */
    if (pdev->smaskcolor == NULL && pgs->icc_manager->smask_profiles != NULL &&
        pgs->icc_manager->smask_profiles->swapped) {
            return 0;
    }
    if (pdev->smaskcolor != NULL) {
        pdev->smaskcolor->ref_count++;
        if_debug1m(gs_debug_flag_icc, dev->memory,
                   "[icc] Increment smask color now %d\n",
                   pdev->smaskcolor->ref_count);
    } else {
        /* Allocate and swap out the current profiles.  The softmask
           profiles should already be in place */
        result = gs_alloc_struct(pdev->memory, pdf14_smaskcolor_t,
                                &st_pdf14_smaskcolor,
                                "pdf14_increment_smask_color");
        if (result == NULL ) return(-1);
        result->profiles = gsicc_new_iccsmask(pdev->memory);
        if (result->profiles == NULL ) return(-1);
        pdev->smaskcolor = result;
        /* Theoretically there should not be any reason to change ref counts
            on the profiles for a well-formed PDF with clean soft mask groups.
           The only issue could be if the graphic state is popped while we
           are still within a softmask group. */
        result->profiles->smask_gray = pgs->icc_manager->default_gray;
        result->profiles->smask_rgb = pgs->icc_manager->default_rgb;
        result->profiles->smask_cmyk = pgs->icc_manager->default_cmyk;
        pgs->icc_manager->default_gray = smask_profiles->smask_gray;
        pgs->icc_manager->default_rgb = smask_profiles->smask_rgb;
        pgs->icc_manager->default_cmyk = smask_profiles->smask_cmyk;
        pgs->icc_manager->smask_profiles->swapped = true;
        if_debug0m(gs_debug_flag_icc, pgs->memory,
                   "[icc] Initial creation of smask color. Ref count 1\n");
        pdev->smaskcolor->ref_count = 1;
        /* We also need to update the profile that is currently in the
           color spaces of the graphic state.  Otherwise this can be
           referenced, which will result in a mismatch.  What we want to do
           is see if it was the original default and only swap in that case. */
        for (k = 0; k < 2; k++) {
            gs_color_space *pcs     = pgs->color[k].color_space;
            cmm_profile_t  *profile = pcs->cmm_icc_profile_data;
            if (profile != NULL) {
                switch(profile->data_cs) {
                    case gsGRAY:
                        if (profile->hashcode ==
                            result->profiles->smask_gray->hashcode) {
                                profile = pgs->icc_manager->default_gray;
                        }
                        break;
                    case gsRGB:
                        if (profile->hashcode ==
                            result->profiles->smask_rgb->hashcode) {
                                profile = pgs->icc_manager->default_rgb;
                        }
                        break;
                    case gsCMYK:
                        if (profile->hashcode ==
                            result->profiles->smask_cmyk->hashcode) {
                                profile = pgs->icc_manager->default_cmyk;
                        }
                        break;
                    default:

                        break;
                }
                rc_assign(pcs->cmm_icc_profile_data, profile,
                          "pdf14_increment_smask_color");
            }
        }
    }
    return(0);
}

Project: ghostscript
File: gdevp14.c

pdf14_mark_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
                          gx_color_index color, const gx_device_color *pdc,
                          bool devn)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_buf *buf = pdev->ctx->stack;
    int i, j, k;
    byte *dst_ptr;
    byte src[PDF14_MAX_PLANES];
    byte dst[PDF14_MAX_PLANES] = { 0 };
    gs_blend_mode_t blend_mode = pdev->blend_mode;
    bool additive = pdev->ctx->additive;
    int rowstride = buf->rowstride;
    int planestride = buf->planestride;
    gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quite compiler */
    bool has_alpha_g = buf->has_alpha_g;
    bool has_shape = buf->has_shape;
    bool has_tags = buf->has_tags;
    int num_chan = buf->n_chan;
    int num_comp = num_chan - 1;
    int shape_off = num_chan * planestride;
    int alpha_g_off = shape_off + (has_shape ? planestride : 0);
    int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
    bool overprint = pdev->overprint;
    gx_color_index drawn_comps = pdev->drawn_comps;
    gx_color_index comps;
    byte shape = 0; /* Quiet compiler. */
    byte src_alpha;
    const gx_color_index mask = ((gx_color_index)1 << 8) - 1;
    const int shift = 8;
    int num_spots = buf->num_spots;

    if (buf->data == NULL)
        return 0;
    /* NB: gx_color_index is 4 or 8 bytes */
#if 0
    if (sizeof(color) <= sizeof(ulong))
        if_debug8m('v', dev->memory,
                   "[v]pdf14_mark_fill_rectangle, (%d, %d), %d x %d color = %lx  bm %d, nc %d, overprint %d\n",
                   x, y, w, h, (ulong)color, blend_mode, num_chan, overprint);
    else
        if_debug9m('v', dev->memory,
                   "[v]pdf14_mark_fill_rectangle, (%d, %d), %d x %d color = %08lx%08lx  bm %d, nc %d, overprint %d\n",
                   x, y, w, h,
                   (ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color,
                   blend_mode, num_chan, overprint);
#endif
    /*
     * Unpack the gx_color_index values.  Complement the components for subtractive
     * color spaces.
     */
    if (has_tags) {
        curr_tag = (color >> (num_comp*8)) & 0xff;
    }
    if (devn) {
        if (additive) {
            for (j = 0; j < (num_comp - num_spots); j++) {
                src[j] = ((pdc->colors.devn.values[j]) >> shift & mask);
            }
            for (j = 0; j < num_spots; j++) {
                src[j + num_comp - num_spots] =
                    255 - ((pdc->colors.devn.values[j + num_comp - num_spots]) >> shift & mask);
            }
        } else {
            for (j = 0; j < num_comp; j++) {
                src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask);
            }
        }
    } else
        pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src);
    src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
    if (has_shape)
        shape = (byte)floor (255 * pdev->shape + 0.5);
    /* Fit the mark into the bounds of the buffer */
    if (x < buf->rect.p.x) {
        w += x - buf->rect.p.x;
        x = buf->rect.p.x;
    }
    if (y < buf->rect.p.y) {
      h += y - buf->rect.p.y;
      y = buf->rect.p.y;
    }
    if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
    if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
    /* Update the dirty rectangle with the mark */
    if (x < buf->dirty.p.x) buf->dirty.p.x = x;
    if (y < buf->dirty.p.y) buf->dirty.p.y = y;
    if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
    if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
    dst_ptr = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
    src_alpha = 255-src_alpha;
    shape = 255-shape;
    if (!has_alpha_g)
        alpha_g_off = 0;
    if (!has_shape)
        shape_off = 0;
    if (!has_tags)
        tag_off = 0;
    rowstride -= w;
    /* The num_comp == 1 && additive case is very common (mono output
     * devices no spot support), so we optimise that specifically here. */
    if (num_comp == 1 && additive && num_spots == 0) {
        for (j = h; j > 0; --j) {
            for (i = w; i > 0; --i) {
                if (src[1] == 0) {
                    /* background empty, nothing to change */
                } else if (dst_ptr[planestride] == 0) {
                    dst_ptr[0] = src[0];
                    dst_ptr[planestride] = src[1];
                } else {
                    art_pdf_composite_pixel_alpha_8_fast_mono(dst_ptr, src,
                                                blend_mode, pdev->blend_procs,
                                                planestride, pdev);
                }
                if (alpha_g_off) {
                    int tmp = (255 - dst_ptr[alpha_g_off]) * src_alpha + 0x80;
                    dst_ptr[alpha_g_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
                }
                if (shape_off) {
                    int tmp = (255 - dst_ptr[shape_off]) * shape + 0x80;
                    dst_ptr[shape_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
                }
                if (tag_off) {
                    /* If alpha is 100% then set to pure path, else or */
                    if (dst_ptr[planestride] == 255) {
                        dst_ptr[tag_off] = curr_tag;
                    } else {
                        dst_ptr[tag_off] = ( dst_ptr[tag_off] |curr_tag ) & ~GS_UNTOUCHED_TAG;
                    }
                }
                ++dst_ptr;
            }
            dst_ptr += rowstride;
        }
    } else {
        for (j = h; j > 0; --j) {
            for (i = w; i > 0; --i) {
                /* If source alpha is zero avoid all of this */
                if (src[num_comp] != 0) {
                    if (dst_ptr[num_comp * planestride] == 0) {
                        /* dest alpha is zero just use source. */
                        if (additive) {
                            /* Hybrid case */
                            for (k = 0; k < (num_comp - num_spots); k++) {
                                dst_ptr[k * planestride] = src[k];
                            }
                            for (k = 0; k < num_spots; k++) {
                                dst_ptr[(k + num_comp - num_spots) * planestride] =
                                    255 - src[k + num_comp - num_spots];
                            }
                        } else {
                            /* Pure subtractive */
                            for (k = 0; k < num_comp; k++) {
                                dst_ptr[k * planestride] = 255 - src[k];
                            }
                        }
                        /* alpha */
                        dst_ptr[num_comp * planestride] = src[num_comp];
                    } else if (additive && num_spots == 0) {
                        /* Pure additive case, no spots */
                        art_pdf_composite_pixel_alpha_8_fast(dst_ptr, src,
                            num_comp, blend_mode, pdev->blend_procs, planestride,
                            pdev);
                    } else {
                        /* Complement subtractive planes */
                        if (!additive) {
                            /* Pure subtractive */
                            for (k = 0; k < num_comp; ++k)
                                dst[k] = 255 - dst_ptr[k * planestride];
                        } else {
                            /* Hybrid case, additive with subtractive spots */
                            for (k = 0; k < (num_comp - num_spots); k++) {
                                dst[k] = dst_ptr[k * planestride];
                            }
                            for (k = 0; k < num_spots; k++) {
                                dst[k + num_comp - num_spots] =
                                    255 - dst_ptr[(k + num_comp - num_spots) * planestride];
                            }
                        }
                        dst[num_comp] = dst_ptr[num_comp * planestride];
                        /* If we have spots and a non_white preserving or a
                           non-separable, blend mode then we need special handling */
                        if (num_spots > 0 && !blend_valid_for_spot(blend_mode))
                        {
                            /* Split and do the spots with normal blend mode.
                               Blending functions assume alpha is last
                               component so do some movements here */
                            byte temp_spot_src = src[num_comp - num_spots];
                            byte temp_spot_dst = dst[num_comp - num_spots];
                            src[num_comp - num_spots] = src[num_comp];
                            dst[num_comp - num_spots] = dst[num_comp];

                            /* Blend process */
                            art_pdf_composite_pixel_alpha_8(dst, src,
                                num_comp - num_spots, blend_mode,
                                pdev->blend_procs, pdev);

                            /* Restore colorants that were blown away by alpha */
                            dst[num_comp - num_spots] = temp_spot_dst;
                            src[num_comp - num_spots] = temp_spot_src;
                            art_pdf_composite_pixel_alpha_8(&(dst[num_comp - num_spots]),
                                &(src[num_comp - num_spots]), num_spots,
                                BLEND_MODE_Normal, pdev->blend_procs, pdev);
                        } else {
                            art_pdf_composite_pixel_alpha_8(dst, src, num_comp, blend_mode,
                                pdev->blend_procs, pdev);
                        }
                        /* Until I see otherwise in AR or the spec, do not fool
                           with spot overprinting while we are in an RGB or Gray
                           blend color space. */
                        if (!additive && overprint) {
                            for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
                                if ((comps & 0x1) != 0) {
                                    dst_ptr[k * planestride] = 255 - dst[k];
                                }
                            }
                        } else {
                            /* Post blend complement for subtractive */
                            if (!additive) {
                                /* Pure subtractive */
                                for (k = 0; k < num_comp; ++k)
                                    dst_ptr[k * planestride] = 255 - dst[k];

                            } else {
                                /* Hybrid case, additive with subtractive spots */
                                for (k = 0; k < (num_comp - num_spots); k++) {
                                    dst_ptr[k * planestride] = dst[k];
                                }
                                for (k = 0; k < num_spots; k++) {
                                    dst_ptr[(k + num_comp - num_spots) * planestride] =
                                        255 - dst[k + num_comp - num_spots];
                                }
                            }
                        }
                        /* The alpha channel */
                        dst_ptr[num_comp * planestride] = dst[num_comp];
                    }
                }
                if (alpha_g_off) {
                    int tmp = (255 - dst_ptr[alpha_g_off]) * src_alpha + 0x80;
                    dst_ptr[alpha_g_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
                }
                if (shape_off) {
                    int tmp = (255 - dst_ptr[shape_off]) * shape + 0x80;
                    dst_ptr[shape_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
                }
                if (tag_off) {
                    /* If alpha is 100% then set to pure path, else or */
                    if (dst[num_comp] == 255) {
                        dst_ptr[tag_off] = curr_tag;
                    } else {
                        dst_ptr[tag_off] = ( dst_ptr[tag_off] |curr_tag ) & ~GS_UNTOUCHED_TAG;
                    }
                }
                ++dst_ptr;
            }
            dst_ptr += rowstride;
        }
    }

#if 0
/* #if RAW_DUMP */
    /* Dump the current buffer to see what we have. */

        if(global_index/10.0 == (int) (global_index/10.0) )
                dump_raw_buffer(pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
                                        pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
                                        pdev->ctx->stack->n_planes,
                                        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                                        "Draw_Rect",pdev->ctx->stack->data);

    global_index++;
#endif
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_mark_fill_rectangle_ko_simple(gx_device *	dev, int x, int y, int w, int h,
                                    gx_color_index color,
                                    const gx_device_color *pdc, bool devn)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_buf *buf = pdev->ctx->stack;
    gs_blend_mode_t blend_mode = pdev->blend_mode;
    int i, j, k;
    byte *bline, *bg_ptr, *line, *dst_ptr;
    byte src[PDF14_MAX_PLANES];
    byte dst[PDF14_MAX_PLANES] = { 0 };
    int rowstride = buf->rowstride;
    int planestride = buf->planestride;
    int num_chan = buf->n_chan;
    int num_comp = num_chan - 1;
    int shape_off = num_chan * planestride;
    bool has_shape = buf->has_shape;
    bool has_alpha_g = buf->has_alpha_g;
    int alpha_g_off = shape_off + (has_shape ? planestride : 0);
    int tag_off = shape_off + (has_alpha_g ? planestride : 0) +
                              (has_shape ? planestride : 0);
    bool has_tags = buf->has_tags;
    bool additive = pdev->ctx->additive;
    gs_graphics_type_tag_t curr_tag = dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS;
    gx_color_index mask = ((gx_color_index)1 << 8) - 1;
    int shift = 8;
    byte shape = 0; /* Quiet compiler. */
    byte src_alpha;

    if (buf->data == NULL)
        return 0;
#if 0
    if (sizeof(color) <= sizeof(ulong))
        if_debug6m('v', dev->memory,
                   "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %lx, nc %d,\n",
                   x, y, w, h, (ulong)color, num_chan);
    else
        if_debug7m('v', dev->memory,
                   "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %8lx%08lx, nc %d,\n",
                   x, y, w, h,
                   (ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color,
                   num_chan);
#endif
    /*
     * Unpack the gx_color_index values.  Complement the components for subtractive
     * color spaces.
     */
    if (devn) {
        if (additive) {
            for (j = 0; j < num_comp; j++) {
                src[j] = ((pdc->colors.devn.values[j]) >> shift & mask);
            }
        } else {
            for (j = 0; j < num_comp; j++) {
                src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask);
            }
        }
    } else
        pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src);

    src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
    if (has_shape) {
        shape = (byte)floor (255 * pdev->shape + 0.5);
    } else {
        shape_off = 0;
    }
    if (has_tags) {
        curr_tag = (color >> (num_comp*8)) & 0xff;
    } else {
        tag_off = 0;
    }
    if (!has_alpha_g)
        alpha_g_off = 0;
    src_alpha = 255 - src_alpha;
    shape = 255 - shape;

    /* Fit the mark into the bounds of the buffer */
    if (x < buf->rect.p.x) {
        w += x - buf->rect.p.x;
        x = buf->rect.p.x;
    }
    if (y < buf->rect.p.y) {
      h += y - buf->rect.p.y;
      y = buf->rect.p.y;
    }
    if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
    if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
    /* Update the dirty rectangle with the mark. */
    if (x < buf->dirty.p.x) buf->dirty.p.x = x;
    if (y < buf->dirty.p.y) buf->dirty.p.y = y;
    if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
    if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;

    /* composite with backdrop only */
    bline = buf->backdrop + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
    line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;

    for (j = 0; j < h; ++j) {
        bg_ptr = bline;
        dst_ptr = line;
        for (i = 0; i < w; ++i) {
            /* Complement the components for subtractive color spaces */
            if (additive) {
                for (k = 0; k < num_chan; ++k)
                    dst[k] = bg_ptr[k * planestride];
            } else {
                for (k = 0; k < num_comp; ++k)
                    dst[k] = 255 - bg_ptr[k * planestride];
            }
            dst[num_comp] = bg_ptr[num_comp * planestride];	/* alpha doesn't invert */
            if (buf->isolated) {
                art_pdf_knockoutisolated_group_8(dst, src, num_comp);
            } else {
                art_pdf_composite_knockout_8(dst, src, num_comp,
                                             blend_mode, pdev->blend_procs, pdev);
            }
            /* Complement the results for subtractive color spaces */
            if (additive) {
                for (k = 0; k < num_chan; ++k)
                    dst_ptr[k * planestride] = dst[k];
            } else {
                for (k = 0; k < num_comp; ++k)
                    dst_ptr[k * planestride] = 255 - dst[k];
                dst_ptr[num_comp * planestride] = dst[num_comp];
            }
            if (tag_off) {
                dst_ptr[tag_off] = curr_tag;
            }
            if (alpha_g_off) {
                int tmp = (255 - dst_ptr[alpha_g_off]) * src_alpha + 0x80;
                dst_ptr[alpha_g_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
            }
            if (shape_off) {
                int tmp = (255 - dst_ptr[shape_off]) * shape + 0x80;
                dst_ptr[shape_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
            }
            ++dst_ptr;
            ++bg_ptr;
        }
        bline += rowstride;
        line += rowstride;
    }
#if 0
/* #if RAW_DUMP */
    /* Dump the current buffer to see what we have. */
    dump_raw_buffer(pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
                            pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
                            pdev->ctx->stack->n_planes,
                            pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                            "Draw_Rect_KO",pdev->ctx->stack->data);
    global_index++;
#endif
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_ok_to_optimize(gx_device *dev)
{
    bool using_blend_cs;
    pdf14_default_colorspace_t pdf14_cs =
        pdf14_determine_default_blend_cs(dev, false, &using_blend_cs);
    gsicc_colorbuffer_t dev_icc_cs;
    bool ok = false;
    int tag_depth = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) ? 8 : 0;
    cmm_dev_profile_t *dev_profile;
    int code = dev_proc(dev, get_profile)(dev,  &dev_profile);

    if (code < 0)
        return false;
    dev_icc_cs = dev_profile->device_profile[0]->data_cs;
    /* If the outputprofile is not "standard" then colors converted to device color */
    /* during clist writing won't match the colors written for the pdf14 clist dev  */
    if (!(dev_icc_cs == gsGRAY || dev_icc_cs == gsRGB || dev_icc_cs == gsCMYK) || using_blend_cs)
        return false;                           /* can't handle funky output profiles */

    switch (pdf14_cs) {
        case PDF14_DeviceGray:
            ok = dev->color_info.max_gray == 255 && dev->color_info.depth == 8 + tag_depth;
            break;
        case PDF14_DeviceRGB:
            ok = dev->color_info.max_color == 255 && dev->color_info.depth == 24 + tag_depth;
            break;
        case PDF14_DeviceCMYK:
            ok = dev->color_info.max_color == 255 && dev->color_info.depth == 32 + tag_depth;
            break;
        case PDF14_DeviceCMYKspot:
            ok = false;			/* punt for this case */
            break;
        case PDF14_DeviceCustom:
            /*
             * We are using the output device's process color model.  The
             * color_info for the PDF 1.4 compositing device needs to match
             * the output device, but it may not have been contone.
             */
            ok = dev->color_info.depth == dev->color_info.num_components * 8 + tag_depth;
            break;
        default:			/* Should not occur */
            ok = false;
    }
    return ok;
}

Project: ghostscript
File: gdevp14.c

pdf14_open(gx_device *dev)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    gs_int_rect rect;

    if_debug2m('v', dev->memory, "[v]pdf14_open: width = %d, height = %d\n",
               dev->width, dev->height);
    rect.p.x = 0;
    rect.p.y = 0;
    rect.q.x = dev->width;
    rect.q.y = dev->height;
    pdev->ctx = pdf14_ctx_new(&rect, dev->color_info.num_components,
        pdev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, dev);
    if (pdev->ctx == NULL)
        return_error(gs_error_VMerror);
    pdev->free_devicen = true;
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_patt_trans_image_fill(gx_device * dev, const gs_gstate * pgs,
                           const gs_matrix *pmat, const gs_image_common_t *pic,
                           const gs_int_rect * prect,
                           const gx_drawing_color * pdcolor,
                           const gx_clip_path * pcpath, gs_memory_t * mem,
                           gx_image_enum_common_t ** pinfo)
{
    const gs_image_t *pim = (const gs_image_t *)pic;
    pdf14_device * p14dev = (pdf14_device *)dev;
    gx_color_tile *ptile;
    int code;
    gs_int_rect group_rect;
    gx_image_enum *penum;
    gs_rect bbox_in, bbox_out;
    gx_pattern_trans_t *fill_trans_buffer;

    ptile = pdcolor->colors.pattern.p_tile;
    /* Set up things in the ptile so that we get the proper
       blending etc */
    /* Set the blending procs and the is_additive setting based
       upon the number of channels */
    if (ptile->ttrans->n_chan-1 < 4) {
        ptile->ttrans->blending_procs = &rgb_blending_procs;
        ptile->ttrans->is_additive = true;
    } else {
        ptile->ttrans->blending_procs = &cmyk_blending_procs;
        ptile->ttrans->is_additive = false;
    }
    /* Set the blending mode in the ptile based upon the current
       setting in the gs_gstate */
    ptile->blending_mode = pgs->blend_mode;
    /* Based upon if the tiles overlap pick the type of rect
       fill that we will want to use */
    if (ptile->has_overlap) {
        /* This one does blending since there is tile overlap */
        ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend;
    } else {
        /* This one does no blending since there is no tile overlap */
        ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple;
    }
    /* Set the procs so that we use the proper filling method. */
    gx_set_pattern_procs_trans((gx_device_color*) pdcolor);
    /* Let the imaging stuff get set up */
    code = gx_default_begin_typed_image(dev, pgs, pmat, pic,
                            prect, pdcolor,pcpath, mem, pinfo);
    if (code < 0)
        return code;
    /* Now Push the group */
    /* First apply the inverse of the image matrix to our
       image size to get our bounding box. */
    bbox_in.p.x = 0;
    bbox_in.p.y = 0;
    bbox_in.q.x = pim->Width;
    bbox_in.q.y = pim->Height;
    code = gs_bbox_transform_inverse(&bbox_in, &(pim->ImageMatrix),
                                &bbox_out);
    if (code < 0)
        return code;
    /* That in turn will get hit by the matrix in the gs_gstate */
    code = compute_group_device_int_rect(p14dev, &group_rect,
                                            &bbox_out, (gs_gstate *)pgs);
    if (code < 0)
        return code;
    if (!(pim->Width == 0 || pim->Height == 0)) {
        if_debug2m('?', p14dev->ctx->memory,
                   "[v*] Pushing trans group patt_trans_image_fill, uid = %ld id = %ld \n",
                   ptile->uid.id, ptile->id);
        code = pdf14_push_transparency_group(p14dev->ctx, &group_rect, 1, 0, 255,255,
                                             pgs->blend_mode, 0, 0,
                                             ptile->ttrans->n_chan-1, false, NULL,
                                             NULL, (gs_gstate *)pgs, dev);
        /* Set up the output buffer information now that we have
           pushed the group */
        fill_trans_buffer = new_pattern_trans_buff(pgs->memory);
        pdf14_get_buffer_information(dev, fill_trans_buffer, NULL, false);
        /* Store this in the appropriate place in pdcolor.  This
           is released later in pdf14_pattern_trans_render when
           we are all done with the mask fill */
        ptile->ttrans->fill_trans_buffer = fill_trans_buffer;
        /* Change the renderer to handle this case so we can catch the
           end.  We will then pop the group and reset the pdcolor proc.
           Keep the base renderer also. */
        penum = (gx_image_enum *) *pinfo;
        ptile->ttrans->image_render = penum->render;
        penum->render = &pdf14_pattern_trans_render;
        ptile->trans_group_popped = false;
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_pattern_trans_render(gx_image_enum * penum, const byte * buffer, int data_x,
                    uint w, int h, gx_device * dev)
{
    int code;
    pdf14_device * p14dev;
    const gs_gstate * pgs = penum->pgs;
    gx_device_color * pdcolor = (penum->icolor1);
    gx_color_tile *ptile = pdcolor->colors.pattern.p_tile;

    /* Pass along to the original renderer */
    code = (ptile->ttrans->image_render)(penum, buffer, data_x, w, h, dev);
    if (code < 0)
        return code;
    /* On our final time through here, go ahead and pop the transparency
       group and reset the procs in the device color. And free the fill
       trans buffer object */
    if (h == 0 && ptile->trans_group_popped == false) {
        p14dev = find_pdf14_device(dev);

        if (p14dev->pclist_device == NULL) {
            /* Used if we are on clist writing phase.  Would only
               occur if we somehow failed in high level clist
               image writing */
            code = gs_end_transparency_group((gs_gstate *) pgs);
        } else {
            /* Used if we are on clist reading phase.  If we had high level
               image in clist */
            cmm_dev_profile_t *dev_profile;
            code = dev_proc(dev, get_profile)(dev,  &dev_profile);
            if (code < 0)
                return code;

            if_debug2m('?', p14dev->ctx->memory,
                      "[?] Popping trans group pattern fill, uid = %ld id = %ld \n",
                       ptile->uid.id, ptile->id);
            code = pdf14_pop_transparency_group(NULL, p14dev->ctx, p14dev->blend_procs,
                    p14dev->color_info.num_components, dev_profile->device_profile[0],
                    (gx_device *) p14dev);
        }
        pdcolor->colors.pattern.p_tile->trans_group_popped = true;
        gs_free_object(pgs->memory, ptile->ttrans->fill_trans_buffer,
                       "pdf14_pattern_trans_render");
        ptile->ttrans->fill_trans_buffer = NULL;  /* Avoid GC issues */
    }
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_pop_parent_color(gx_device *dev, const gs_gstate *pgs)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_parent_color_t *old_parent_color_info = pdev->trans_group_parent_cmap_procs;

    if_debug0m('v', dev->memory, "[v]pdf14_pop_parent_color\n");
    /* We need to compliment pdf14_push_parent color */
    if (old_parent_color_info->icc_profile != NULL)
        rc_decrement(old_parent_color_info->icc_profile, "pdf14_pop_parent_color");
    /* Update the link */
    pdev->trans_group_parent_cmap_procs = old_parent_color_info->previous;
    /* Free the old one */
    gs_free_object(dev->memory, old_parent_color_info, "pdf14_clr_free");
}

Project: ghostscript
File: gdevp14.c

pdf14_pop_transparency_mask(pdf14_ctx *ctx, gs_gstate *pgs, gx_device *dev)
{
    pdf14_buf *tos = ctx->stack;
    byte *new_data_buf;
    int icc_match;
    cmm_profile_t *des_profile = tos->parent_color_info_procs->icc_profile; /* If set, this should be a gray profile */
    cmm_profile_t *src_profile;
    gsicc_rendering_param_t rendering_params;
    gsicc_link_t *icc_link;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;

    dev_proc(dev, get_profile)(dev,  &dev_profile);
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &src_profile,
                          &render_cond);
    ctx->smask_depth -= 1;
    /* icc_match == -1 means old non-icc code.
       icc_match == 0 means use icc code
       icc_match == 1 mean no conversion needed */
    if ( des_profile != NULL && src_profile != NULL ) {
        icc_match = (des_profile->hashcode ==  src_profile->hashcode);
    } else {
        icc_match = -1;
    }
    if_debug1m('v', ctx->memory, "[v]pdf14_pop_transparency_mask, idle=%d\n",
               tos->idle);
    ctx->stack = tos->saved;
    tos->saved = NULL;  /* To avoid issues with GC */
    if (tos->mask_stack) {
        /* During the soft mask push, the mask_stack was copied (not moved) from
           the ctx to the tos mask_stack. We are done with this now so it is safe to
           just set to NULL.  However, before we do that we must perform
           rc decrement to match the increment that occured was made.  Also,
           if this is the last ref count of the rc_mask, we should free the
           buffer now since no other groups need it. */
        rc_decrement(tos->mask_stack->rc_mask,
                     "pdf14_pop_transparency_mask(tos->mask_stack->rc_mask)");
        if (tos->mask_stack->rc_mask) {
            if (tos->mask_stack->rc_mask->rc.ref_count == 1){
                rc_decrement(tos->mask_stack->rc_mask,
                            "pdf14_pop_transparency_mask(tos->mask_stack->rc_mask)");
            }
        }
        tos->mask_stack = NULL;
    }
    if (tos->data == NULL ) {
        /* This can occur in clist rendering if the soft mask does
           not intersect the current band.  It would be nice to
           catch this earlier and just avoid creating the structure
           to begin with.  For now we need to delete the structure
           that was created.  Only delete if the alpha value is 255 */
        if (tos->alpha == 255) {
            pdf14_buf_free(tos, ctx->memory);
            if (ctx->mask_stack != NULL) {
                pdf14_free_mask_stack(ctx, ctx->memory);
            }
        } else {
            /* Assign as mask buffer */
            if (ctx->mask_stack != NULL) {
                pdf14_free_mask_stack(ctx, ctx->memory);
            }
            ctx->mask_stack = pdf14_mask_element_new(ctx->memory);
            ctx->mask_stack->rc_mask = pdf14_rcmask_new(ctx->memory);
            ctx->mask_stack->rc_mask->mask_buf = tos;
        }
        ctx->smask_blend = false;  /* just in case */
    } else {
        /* If we are already in the source space then there is no reason
           to do the transformation */
        /* Lets get this to a monochrome buffer and map it to a luminance only value */
        /* This will reduce our memory.  We won't reuse the existing one, due */
        /* Due to the fact that on certain systems we may have issues recovering */
        /* the data after a resize */
        new_data_buf = gs_alloc_bytes(ctx->memory, tos->planestride,
                                        "pdf14_pop_transparency_mask");
        if (new_data_buf == NULL)
            return_error(gs_error_VMerror);
        /* Initialize with 0.  Need to do this since in Smask_Luminosity_Mapping
           we won't be filling everything during the remap if it had not been
           written into by the PDF14 fill rect */
        memset(new_data_buf, 0, tos->planestride);
        /* If the subtype was alpha, then just grab the alpha channel now
           and we are all done */
        if (tos->SMask_SubType == TRANSPARENCY_MASK_Alpha) {
            ctx->smask_blend = false;  /* not used in this case */
            smask_copy(tos->rect.q.y - tos->rect.p.y,
                       tos->rect.q.x - tos->rect.p.x,
                       tos->rowstride,
                       (tos->data)+tos->planestride, new_data_buf);
#if RAW_DUMP
            /* Dump the current buffer to see what we have. */
            dump_raw_buffer(tos->rect.q.y-tos->rect.p.y,
                        tos->rowstride, tos->n_planes,
                        tos->planestride, tos->rowstride,
                        "SMask_Pop_Alpha(Mask_Plane1)",tos->data);
            global_index++;
#endif
        } else {
            if ( icc_match == 1 || tos->n_chan == 2) {
#if RAW_DUMP
                /* Dump the current buffer to see what we have. */
                dump_raw_buffer(tos->rect.q.y-tos->rect.p.y,
                            tos->rowstride, tos->n_planes,
                            tos->planestride, tos->rowstride,
                            "SMask_Pop_Lum(Mask_Plane0)",tos->data);
                global_index++;
#endif
                /* There is no need to color convert.  Data is already gray scale.
                   We just need to copy the gray plane.  However it is
                   possible that the soft mask could have a soft mask which
                   would end us up with some alpha blending information
                   (Bug691803). In fact, according to the spec, the alpha
                   blending has to occur.  See FTS test fts_26_2601.pdf
                   for an example of this.  Softmask buffer is intialized
                   with BG values.  It would be nice to keep track if buffer
                   ever has a alpha value not 1 so that we could detect and
                   avoid this blend if not needed. */
                smask_blend(tos->data, tos->rect.q.x - tos->rect.p.x,
                            tos->rect.q.y - tos->rect.p.y, tos->rowstride,
                            tos->planestride);
#if RAW_DUMP
                /* Dump the current buffer to see what we have. */
                dump_raw_buffer(tos->rect.q.y-tos->rect.p.y,
                            tos->rowstride, tos->n_planes,
                            tos->planestride, tos->rowstride,
                            "SMask_Pop_Lum_Post_Blend",tos->data);
                global_index++;
#endif
                smask_copy(tos->rect.q.y - tos->rect.p.y,
                           tos->rect.q.x - tos->rect.p.x,
                           tos->rowstride, tos->data, new_data_buf);
            } else {
                if ( icc_match == -1 ) {
                    /* The slow old fashioned way */
                    smask_luminosity_mapping(tos->rect.q.y - tos->rect.p.y ,
                        tos->rect.q.x - tos->rect.p.x,tos->n_chan,
                        tos->rowstride, tos->planestride,
                        tos->data,  new_data_buf, ctx->additive, tos->SMask_SubType);
                } else {
                    /* ICC case where we use the CMM */
                    /* Request the ICC link for the transform that we will need to use */
                    rendering_params.black_point_comp = gsBLACKPTCOMP_OFF;
                    rendering_params.graphics_type_tag = GS_IMAGE_TAG;
                    rendering_params.override_icc = false;
                    rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
                    rendering_params.rendering_intent = gsPERCEPTUAL;
                    rendering_params.cmm = gsCMM_DEFAULT;
                    icc_link = gsicc_get_link_profile(pgs, dev, des_profile,
                        src_profile, &rendering_params, pgs->memory, false);
                    smask_icc(dev, tos->rect.q.y - tos->rect.p.y,
                              tos->rect.q.x - tos->rect.p.x,tos->n_chan,
                              tos->rowstride, tos->planestride,
                              tos->data, new_data_buf, icc_link);
                    /* Release the link */
                    gsicc_release_link(icc_link);
                }
            }
        }
        /* Free the old object, NULL test was above */
        gs_free_object(ctx->memory, tos->data, "pdf14_pop_transparency_mask");
        tos->data = new_data_buf;
        /* Data is single channel now */
        tos->n_chan = 1;
        tos->n_planes = 1;
        /* Assign as reference counted mask buffer */
        if (ctx->mask_stack != NULL) {
            /* In this case, the source file is wacky as it already had a
               softmask and now is getting a replacement. We need to clean
               up the softmask stack before doing this free and creating
               a new stack. Bug 693312 */
            pdf14_free_mask_stack(ctx, ctx->memory);
        }
        ctx->mask_stack = pdf14_mask_element_new(ctx->memory);
        if (ctx->mask_stack == NULL)
            return gs_note_error(gs_error_VMerror);
        ctx->mask_stack->rc_mask = pdf14_rcmask_new(ctx->memory);
        if (ctx->mask_stack->rc_mask == NULL)
            return gs_note_error(gs_error_VMerror);
        ctx->mask_stack->rc_mask->mask_buf = tos;
    }
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_push_parent_color(gx_device *dev, const gs_gstate *pgs)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    pdf14_parent_color_t *new_parent_color;
    cmm_profile_t *icc_profile;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;

    dev_proc(dev, get_profile)(dev,  &dev_profile);
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
                          &render_cond);
    if_debug0m('v', dev->memory, "[v]pdf14_push_parent_color\n");
    /* Allocate a new one */
    new_parent_color = gs_alloc_struct(dev->memory, pdf14_parent_color_t,
                                        &st_pdf14_clr,"pdf14_clr_new");
    /* Link to old one */
    new_parent_color->previous = pdev->trans_group_parent_cmap_procs;
    /* Reassign new one to dev */
    pdev->trans_group_parent_cmap_procs = new_parent_color;
    /* Initialize with values */
    new_parent_color->get_cmap_procs = pgs->get_cmap_procs;
    new_parent_color->parent_color_mapping_procs =
        pdev->procs.get_color_mapping_procs;
    new_parent_color->parent_color_comp_index =
        pdev->procs.get_color_comp_index;
    new_parent_color->parent_blending_procs = pdev->blend_procs;
    new_parent_color->polarity = pdev->color_info.polarity;
    new_parent_color->num_components = pdev->color_info.num_components;
    new_parent_color->unpack_procs = pdev->pdf14_procs;
    new_parent_color->depth = pdev->color_info.depth;
    new_parent_color->max_color = pdev->color_info.max_color;
    new_parent_color->max_gray = pdev->color_info.max_gray;
    new_parent_color->decode = pdev->procs.decode_color;
    new_parent_color->encode = pdev->procs.encode_color;
    memcpy(&(new_parent_color->comp_bits),&(pdev->color_info.comp_bits),
                        GX_DEVICE_COLOR_MAX_COMPONENTS);
    memcpy(&(new_parent_color->comp_shift),&(pdev->color_info.comp_shift),
                        GX_DEVICE_COLOR_MAX_COMPONENTS);
    /* The ICC manager has the ICC profile for the device */
    new_parent_color->icc_profile = icc_profile;
    rc_increment(icc_profile);
    /* isadditive is only used in ctx */
    if (pdev->ctx) {
        new_parent_color->isadditive = pdev->ctx->additive;
    }
}

Project: ghostscript

pdf14_push_transparency_group(pdf14_ctx	*ctx, gs_int_rect *rect, bool isolated,
                              bool knockout, byte alpha, byte shape,
                              gs_blend_mode_t blend_mode, bool idle, uint mask_id,
                              int numcomps, bool cm_back_drop,
                              cmm_profile_t *group_profile,
                              cmm_profile_t *tos_profile, gs_gstate *pgs,
                              gx_device *dev)
{
    pdf14_buf *tos = ctx->stack;
    pdf14_buf *buf, *backdrop;
    bool has_shape, has_tags;

    if_debug1m('v', ctx->memory,
               "[v]pdf14_push_transparency_group, idle = %d\n", idle);

    /* We are going to use the shape in the knockout computation.  If previous
       buffer has a shape or if this is a knockout then we will have a shape here */
    has_shape = tos->has_shape || tos->knockout;
    /* If previous buffer has tags, then add tags here */
    has_tags = tos->has_tags;

    /* If the group is NOT isolated we add in the alpha_g plane.  This enables
       recompositing to be performed ala art_pdf_recomposite_group_8 so that
       the backdrop is only included one time in the computation. */
    /* Order of buffer data is color data, followed by alpha channel, followed by
       shape (if present), then alpha_g (if present), then tags (if present) */
    buf = pdf14_buf_new(rect, has_tags, !isolated, has_shape, idle, numcomps + 1,
                        tos->num_spots, ctx->memory);
    if_debug4m('v', ctx->memory,
               "[v]base buf: %d x %d, %d color channels, %d planes\n",
               buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes);
    if (buf == NULL)
        return_error(gs_error_VMerror);
    buf->isolated = isolated;
    buf->knockout = knockout;
    buf->alpha = alpha;
    buf->shape = shape;
    buf->blend_mode = blend_mode;
    buf->mask_id = mask_id;
    buf->mask_stack = ctx->mask_stack; /* Save because the group rendering may
                                          set up another (nested) mask. */
    ctx->mask_stack = NULL; /* Clean the mask field for rendering this group.
                            See pdf14_pop_transparency_group how to handle it. */
    buf->saved = tos;
    ctx->stack = buf;
    if (buf->data == NULL)
        return 0;
    if (idle)
        return 0;
    backdrop = pdf14_find_backdrop_buf(ctx);
    if (backdrop == NULL) {
        memset(buf->data, 0, buf->planestride * (buf->n_chan +
                                                 (buf->has_shape ? 1 : 0) +
                                                 (buf->has_alpha_g ? 1 : 0) +
                                                 (buf->has_tags ? 1 : 0)));
    } else {
        if (!buf->knockout) {
            if (!cm_back_drop) {
                pdf14_preserve_backdrop(buf, tos, false);
            } else {
                /* We must have an non-isolated group with a mismatch in color spaces.
                   In this case, we can't just copy the buffer but must CM it */
                pdf14_preserve_backdrop_cm(buf, group_profile, tos, tos_profile,
                                           ctx->memory, pgs, dev, false);
            }
        }
    }

    /* If knockout, we have to maintain a copy of the backdrop in case we are
       drawing nonisolated groups on top of the knockout group. */
    if (buf->knockout) {
        buf->backdrop = gs_alloc_bytes(ctx->memory, buf->planestride * buf->n_chan,
                                        "pdf14_push_transparency_group");
        if (buf->backdrop == NULL) {
            gs_free_object(ctx->memory, buf->backdrop, "pdf14_push_transparency_group");
            return gs_throw(gs_error_VMerror, "Knockout backdrop allocation failed");
        }
        if (buf->isolated) {
            /* We will have opaque backdrop for non-isolated compositing */
            memset(buf->backdrop, 0, buf->planestride * buf->n_chan);
        } else {
            /* Save knockout backdrop for non-isolated compositing */
            /* Note that we need to drill down through the non-isolated groups in our
               stack and make sure that we are not embedded in another knockout group */
            pdf14_buf *check = tos;
            pdf14_buf *child = NULL;  /* Needed so we can get profile */
            cmm_profile_t *prev_knockout_profile;

            while (check != NULL) {
                if (check->isolated)
                    break;
                if (check->knockout) {
                    break;
                }
                child = check;
                check = check->saved;
            }
            /* Here we need to grab a back drop from a knockout parent group and
                potentially worry about color differences. */
            if (check == NULL) {
                prev_knockout_profile = tos_profile;
                check = tos;
            } else {
                if (child == NULL) {
                    prev_knockout_profile = tos_profile;
                } else {
                    prev_knockout_profile  = child->parent_color_info_procs->icc_profile;
                }
            }
            if (!cm_back_drop) {
                pdf14_preserve_backdrop(buf, check, false);
            } else {
                /* We must have an non-isolated group with a mismatch in color spaces.
                   In this case, we can't just copy the buffer but must CM it */
                pdf14_preserve_backdrop_cm(buf, group_profile, check,
                                           prev_knockout_profile, ctx->memory, pgs,
                                           dev, false);
            }
            memcpy(buf->backdrop, buf->data, buf->planestride * buf->n_chan);
        }
#if RAW_DUMP
        /* Dump the current buffer to see what we have. */
        dump_raw_buffer(ctx->stack->rect.q.y-ctx->stack->rect.p.y,
                    ctx->stack->rowstride, buf->n_chan,
                    ctx->stack->planestride, ctx->stack->rowstride,
                    "KnockoutBackDrop", buf->backdrop);
        global_index++;
#endif
    } else {
        buf->backdrop = NULL;
    }
#if RAW_DUMP
    /* Dump the current buffer to see what we have. */
    dump_raw_buffer(ctx->stack->rect.q.y-ctx->stack->rect.p.y,
                ctx->stack->rowstride, ctx->stack->n_planes,
                ctx->stack->planestride, ctx->stack->rowstride,
                "TransGroupPush", ctx->stack->data);
    global_index++;
#endif
    return 0;
}

Project: ghostscript
File: gdevp14.c

pdf14_put_devn_params(gx_device * pdev, gs_devn_params * pdevn_params,
                                        gs_param_list * plist)
{
    int code;
    code = put_param_pdf14_spot_names(pdev,
                       &pdevn_params->pdf14_separations, plist);
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
{
    const pdf14_device * pdev = (pdf14_device *)dev;
    int code;
    gs_image1_t image;
    gx_image_enum_common_t *info;
    pdf14_buf *buf = pdev->ctx->stack;
    gs_int_rect rect = buf->rect;
    int y;
    int num_comp = buf->n_chan - 1;
    byte *linebuf;
    gs_color_space *pcs;
    const byte bg = pdev->ctx->additive ? 255 : 0;
    int x1, y1, width, height;
    byte *buf_ptr;
    bool data_blended = false;
    int num_rows_left;
    gsicc_rendering_param_t render_cond;
    cmm_dev_profile_t *dev_profile;
    cmm_dev_profile_t *target_profile;

    /* Make sure that this is the only item on the stack. Fuzzing revealed a
       potential problem. Bug 694190 */
    if (buf->saved != NULL) {
        return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync");
    }

    if_debug0m('v', dev->memory, "[v]pdf14_put_image\n");
    rect_intersect(rect, buf->dirty);
    x1 = min(pdev->width, rect.q.x);
    y1 = min(pdev->height, rect.q.y);
    width = x1 - rect.p.x;
    height = y1 - rect.p.y;
#ifdef DUMP_TO_PNG
    dump_planar_rgba(pdev->memory, buf);
#endif
    if (width <= 0 || height <= 0 || buf->data == NULL)
        return 0;
    buf_ptr = buf->data + rect.p.y * buf->rowstride + rect.p.x;

    /* Check that target is OK.  From fuzzing results the target could have been
       destroyed, for e.g if it were a pattern accumulator that was closed
       prematurely (Bug 694154).  We should always
       be able to to get an ICC profile from the target. */
    code = dev_proc(target, get_profile)(target,  &target_profile);
    if (code < 0)
        return code;
    if (target_profile == NULL)
        return gs_throw_code(gs_error_Fatal);

    /* See if the target device has a put_image command.  If
       yes then see if it can handle the image data directly.
       If it cannot, then we will need to use the begin_typed_image
       interface, which cannot pass along tag nor alpha data to
       the target device.  Also, if a blend color space was used, we will
       also use the begin_typed_image interface */
    if (target->procs.put_image != NULL && !pdev->using_blend_cs) {
        /* See if the target device can handle the data in its current
           form with the alpha component */
        int alpha_offset = num_comp;
        int tag_offset = buf->has_tags ? num_comp+1 : 0;
        const byte *buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
        int i;
        for (i = 0; i < num_comp; i++)
            buf_ptrs[i] = buf_ptr + i * buf->planestride;
        code = dev_proc(target, put_image) (target, buf_ptrs, num_comp,
                                            rect.p.x, rect.p.y, width, height,
                                            buf->rowstride,
                                            num_comp, tag_offset);
        if (code == 0) {
            /* Device could not handle the alpha data.  Go ahead and
               preblend now. Note that if we do this, and we end up in the
               default below, we only need to repack in chunky not blend */
#if RAW_DUMP
            /* Dump before and after the blend to make sure we are doing that ok */
            dump_raw_buffer(height, width, buf->n_planes,
                        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                        "pre_final_blend",buf_ptr);
            global_index++;
#endif
            gx_blend_image_buffer(buf_ptr, width, height, buf->rowstride,
                                  buf->planestride, num_comp, bg);
#if RAW_DUMP
            /* Dump before and after the blend to make sure we are doing that ok */
            dump_raw_buffer(height, width, buf->n_planes,
                        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                        "post_final_blend",buf_ptr);
            global_index++;
            clist_band_count++;
#endif
            data_blended = true;
            /* Try again now */
            alpha_offset = 0;
            code = dev_proc(target, put_image) (target, buf_ptrs, num_comp,
                                                rect.p.x, rect.p.y, width, height,
                                                buf->rowstride,
                                                alpha_offset, tag_offset);
        }
        if (code > 0) {
            /* We processed some or all of the rows.  Continue until we are done */
            num_rows_left = height - code;
            while (num_rows_left > 0) {
                code = dev_proc(target, put_image) (target, buf_ptrs, buf->n_planes,
                                                    rect.p.x, rect.p.y+code, width,
                                                    num_rows_left, buf->rowstride,
                                                    alpha_offset, tag_offset);
                num_rows_left = num_rows_left - code;
            }
            return 0;
        }
    }
    /*
     * Set color space in preparation for sending an image.
     */
    code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory);
    if (pcs == NULL)
        return_error(gs_error_VMerror);
    if (code < 0)
        return code;
    /* Need to set this to avoid color management during the
       image color render operation.  Exception is for the special case
       when the destination was CIELAB.  Then we need to convert from
       default RGB to CIELAB in the put image operation.  That will happen
       here as we should have set the profile for the pdf14 device to RGB
       and the target will be CIELAB.  In addition, the case when we have a
       blend color space that is different than the target device color space */
    code = dev_proc(dev, get_profile)(dev,  &dev_profile);
    if (code < 0) {
        rc_decrement_only_cs(pcs, "pdf14_put_image");
        return code;
    }
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
                          &(pcs->cmm_icc_profile_data), &render_cond);
    /* pcs takes a reference to the profile data it just retrieved. */
    rc_increment(pcs->cmm_icc_profile_data);
    gscms_set_icc_range(&(pcs->cmm_icc_profile_data));
    gs_image_t_init_adjust(&image, pcs, false);
    image.ImageMatrix.xx = (float)width;
    image.ImageMatrix.yy = (float)height;
    image.Width = width;
    image.Height = height;
    image.BitsPerComponent = 8;
    ctm_only_writable(pgs).xx = (float)width;
    ctm_only_writable(pgs).xy = 0;
    ctm_only_writable(pgs).yx = 0;
    ctm_only_writable(pgs).yy = (float)height;
    ctm_only_writable(pgs).tx = (float)rect.p.x;
    ctm_only_writable(pgs).ty = (float)rect.p.y;
    code = dev_proc(target, begin_typed_image) (target,
                                                pgs, NULL,
                                                (gs_image_common_t *)&image,
                                                NULL, NULL, NULL,
                                                pgs->memory, &info);
    if (code < 0) {
        rc_decrement_only_cs(pcs, "pdf14_put_image");
        return code;
    }
#if RAW_DUMP
    /* Dump the current buffer to see what we have. */
    dump_raw_buffer(pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
                pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
                                pdev->ctx->stack->n_planes,
                pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                "pdF14_putimage",pdev->ctx->stack->data);
    dump_raw_buffer(height, width, num_comp+1,
                pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
                "PDF14_PUTIMAGE_SMALL",buf_ptr);
    global_index++;
    if (!data_blended) {
        clist_band_count++;
    }
#endif
    linebuf = gs_alloc_bytes(pdev->memory, width * num_comp, "pdf14_put_image");
    for (y = 0; y < height; y++) {
        gx_image_plane_t planes;
        int rows_used,k,x;

        if (data_blended) {
            for (x = 0; x < width; x++) {
                for (k = 0; k < num_comp; k++) {
                    linebuf[x * num_comp + k] = buf_ptr[x + buf->planestride * k];
                }
            }
        } else {
            gx_build_blended_image_row(buf_ptr, y, buf->planestride, width,
                                       num_comp, bg, linebuf);
        }
        planes.data = linebuf;
        planes.data_x = 0;
        planes.raster = width * num_comp;
        info->procs->plane_data(info, &planes, 1, &rows_used);
        /* todo: check return value */
        buf_ptr += buf->rowstride;
    }
    gs_free_object(pdev->memory, linebuf, "pdf14_put_image");
    info->procs->end_image(info, true);
    /* This will also decrement the device profile */
    rc_decrement_only_cs(pcs, "pdf14_put_image");
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_recreate_clist_device(gs_memory_t	*mem, gs_gstate *	pgs,
                gx_device * dev, const gs_pdf14trans_t * pdf14pct)
{
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
    gx_device * target = pdev->target;
    pdf14_clist_device * dev_proto;
    pdf14_clist_device temp_dev_proto;
    int code;

    if_debug0m('v', pgs->memory, "[v]pdf14_recreate_clist_device\n");
    /*
     * We will not use the entire prototype device but we will set the
     * color related info to match the prototype.
     */
    code = get_pdf14_clist_device_proto(target, &dev_proto,
                                 &temp_dev_proto, pgs, pdf14pct, false);
    if (code < 0)
        return code;
    pdev->color_info = dev_proto->color_info;
    pdev->procs = dev_proto->procs;
    pdev->pad = target->pad;
    pdev->log2_align_mod = target->log2_align_mod;
    pdev->is_planar = target->is_planar;
    gx_device_fill_in_procs(dev);
    check_device_separable((gx_device *)pdev);
    return code;
}

Project: ghostscript
File: gdevp14.c

pdf14_recreate_device(gs_memory_t *mem,	gs_gstate	* pgs,
                gx_device * dev, const gs_pdf14trans_t * pdf14pct)
{
    pdf14_device * pdev = (pdf14_device *)dev;
    gx_device * target = pdev->target;
    pdf14_device * dev_proto;
    pdf14_device temp_dev_proto;
    bool has_tags = dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS;
    int code;

    if_debug0m('v', dev->memory, "[v]pdf14_recreate_device\n");

    /*
     * We will not use the entire prototype device but we will set the
     * color related info and the device procs to match the prototype.
     */
    code = get_pdf14_device_proto(target, &dev_proto, &temp_dev_proto, pgs,
                                  pdf14pct, false);
    if (code < 0)
        return code;
    pdev->color_info = dev_proto->color_info;
    pdev->pad = target->pad;
    pdev->log2_align_mod = target->log2_align_mod;
    pdev->is_planar = target->is_planar;
    pdev->procs = dev_proto->procs;
    if (has_tags) {
        pdev->procs.encode_color = pdf14_encode_color_tag;
        pdev->color_info.depth += 8;
    }
    dev->static_procs = dev_proto->static_procs;
    gx_device_set_procs(dev);
    gx_device_fill_in_procs(dev);
    check_device_separable(dev);
    return dev_proc(pdev, open_device)(dev);
}

Project: ghostscript
File: gdevp14.c

pdf14_ret_devn_params(gx_device *pdev)
{
    pdf14_device *p14dev = (pdf14_device *)pdev;

    return(&(p14dev->devn_params));
}

Project: ghostscript
File: gdevp14.c

pdf14_spot_get_color_comp_index(gx_device *dev, const char *pname,
    int name_size, int component_type, int num_process_colors)
{
    pdf14_device *pdev = (pdf14_device *)dev;
    gx_device *tdev = pdev->target;
    gs_devn_params *pdevn_params = &pdev->devn_params;
    gs_separations *pseparations = &pdevn_params->separations;
    int comp_index;
    dev_proc_get_color_comp_index(*target_get_color_comp_index);
    int offset = 4 - num_process_colors;


    while (tdev->child) {
        tdev = tdev->child;
    }

    /* If num_process_colors is 3 or 1 (RGB or Gray) then we are in a situation
     * where we are in a blend color space that is RGB or Gray based and we
     * have a spot colorant.  If the spot colorant name is Cyan, Magenta
     * Yellow or Black, then we should use the alternate tint transform */
    if (num_process_colors < 4) {
        int k;
        for (k = 0; k < 4; k++) {
            if (strncmp(pname, pdev->devn_params.std_colorant_names[k], name_size) == 0)
                return -1;
        }
    }

    target_get_color_comp_index = dev_proc(tdev, get_color_comp_index);

    /* The pdf14_clist_create_compositor may have set the color procs.
       We need the real target procs */
    if (target_get_color_comp_index == pdf14_cmykspot_get_color_comp_index)
        target_get_color_comp_index =
        ((pdf14_clist_device *)pdev)->saved_target_get_color_comp_index;
    /*
    * If this is not a separation name then simply forward it to the target
    * device.
    */
    if (component_type == NO_COMP_NAME_TYPE)
        return  (*target_get_color_comp_index)(tdev, pname, name_size, component_type);
    /*
    * Check if the component is in either the process color model list
    * or in the SeparationNames list.
    */
    comp_index = check_pcm_and_separation_names(dev, pdevn_params, pname,
        name_size, component_type);
    /*
    * Return the colorant number if we know this name.  Note adjustment for
    * compensating of blend color space.
    */
    if (comp_index >= 0)
        return comp_index - offset;
    /*
    * If we do not know this color, check if the output (target) device does.
    */
    comp_index = (*target_get_color_comp_index)(tdev, pname, name_size, component_type);
    /*
    * Ignore color if unknown to the output device or if color is not being
    * imaged due to the SeparationOrder device parameter.
    */
    if (comp_index < 0 || comp_index == GX_DEVICE_COLOR_MAX_COMPONENTS)
        return comp_index - offset;

    /*
    * This is a new colorant.  Add it to our list of colorants.
    */
    if (pseparations->num_separations < GX_DEVICE_COLOR_MAX_COMPONENTS - 1) {
        int sep_num = pseparations->num_separations++;
        int color_component_number;
        byte * sep_name;

        sep_name = gs_alloc_bytes(dev->memory->stable_memory,
            name_size, "pdf14_spot_get_color_comp_index");
        memcpy(sep_name, pname, name_size);
        pseparations->names[sep_num].size = name_size;
        pseparations->names[sep_num].data = sep_name;
        color_component_number = sep_num + num_process_colors;
        if (color_component_number >= dev->color_info.num_components)
            color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
        else
            pdevn_params->separation_order_map[color_component_number] =
            color_component_number;
        return color_component_number;
    }

    return GX_DEVICE_COLOR_MAX_COMPONENTS;
}

Project: ghostscript
File: gdevp14.c

pdf14_text_begin(gx_device * dev, gs_gstate * pgs,
                 const gs_text_params_t * text, gs_font * font,
                 gx_path * path, const gx_device_color * pdcolor,
                 const gx_clip_path * pcpath, gs_memory_t * memory,
                 gs_text_enum_t ** ppenum)
{
    int code;
    gs_text_enum_t *penum;

    if_debug0m('v', memory, "[v]pdf14_text_begin\n");
    pdf14_set_marking_params(dev, pgs);
    code = gx_default_text_begin(dev, pgs, text, font, path, pdcolor, pcpath,
                                 memory, &penum);
    if (code < 0)
        return code;
    *ppenum = (gs_text_enum_t *)penum;
    return code;
}