pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect,	byte bg_alpha,
                             byte *transfer_fn, bool idle, bool replacing,
                             uint mask_id, gs_transparency_mask_subtype_t subtype,
                             int numcomps, int Background_components,
                             const float Background[], int Matte_components,
                             const float Matte[], const float GrayBackground)
{
    pdf14_buf *buf;
    unsigned char *curr_ptr, gray;

    if_debug2m('v', ctx->memory,
               "[v]pdf14_push_transparency_mask, idle=%d, replacing=%d\n",
               idle, replacing);
    ctx->smask_depth += 1;

    /* An optimization to consider is that if the SubType is Alpha
       then we really should only be allocating the alpha band and
       only draw with that channel.  Current architecture makes that
       a bit tricky.  We need to create this based upon the size of
       the color space + an alpha channel. NOT the device size
       or the previous ctx size */
    /* A mask doesnt worry about tags */
    buf = pdf14_buf_new(rect, false, false, false, idle, numcomps + 1, 0,
                        ctx->memory);
    if (buf == NULL)
        return_error(gs_error_VMerror);
    buf->alpha = bg_alpha;
    /* fill in, but these values aren't really used */
    buf->isolated = true;
    buf->knockout = false;
    buf->shape = 0xff;
    buf->blend_mode = BLEND_MODE_Normal;
    buf->transfer_fn = transfer_fn;
    buf->matte_num_comps = Matte_components;
    if (Matte_components) {
        buf->matte = (byte *)gs_alloc_bytes(ctx->memory, sizeof(float)*Matte_components,
                                            "pdf14_push_transparency_mask");
        if (buf->matte == NULL)
            return_error(gs_error_VMerror);
        memcpy(buf->matte, Matte, size_of(float)*Matte_components);
    }
    buf->mask_id = mask_id;
    /* If replacing=false, we start the mask for an image with SMask.
       In this case the image's SMask temporary replaces the
       mask of the containing group. Save the containing droup's mask
       in buf->mask_stack */
    buf->mask_stack = ctx->mask_stack;
    if (buf->mask_stack){
        rc_increment(buf->mask_stack->rc_mask);
    }
#if RAW_DUMP
    /* Dump the current buffer to see what we have. */
    if (ctx->stack->planestride > 0 ){
        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,
                    "Raw_Buf_PreSmask",ctx->stack->data);
        global_index++;
    }
#endif
    buf->saved = ctx->stack;
    ctx->stack = buf;
    /* Soft Mask related information so we know how to
       compute luminosity when we pop the soft mask */
    buf->SMask_SubType = subtype;
    if (buf->data != NULL){
        /* We need to initialize it to the BC if it existed */
        /* According to the spec, the CS has to be the same */
        /* If the back ground component is black, then don't bother
           with this.  Since we are forcing the rendering to gray
           earlier now, go ahead and just use the GrayBackGround color
           directly. */
        if ( Background_components && GrayBackground != 0.0 ) {
            curr_ptr = buf->data;
            gray = (unsigned char) (255.0 * GrayBackground);
            memset(curr_ptr, gray, buf->planestride);
                curr_ptr +=  buf->planestride;
            /* If we have a background component that was not black, then we
               need to set the alpha for this mask as if we had drawn in the
               entire soft mask buffer */
            memset(curr_ptr, 255, buf->planestride *(buf->n_chan - 1));
        } else {
            /* Compose mask with opaque background */
            memset(buf->data, 0, buf->planestride * buf->n_chan);
        }
    }
    return 0;
}