template_compose_group16(uint16_t *gs_restrict tos_ptr, bool tos_isolated,
                         int tos_planestride, int tos_rowstride,
                         uint16_t alpha, uint16_t shape, gs_blend_mode_t blend_mode,
                         bool tos_has_shape, int tos_shape_offset,
                         int tos_alpha_g_offset, int tos_tag_offset,
                         bool tos_has_tag, uint16_t *gs_restrict nos_ptr,
                         bool nos_isolated, int nos_planestride,
                         int nos_rowstride, uint16_t *gs_restrict nos_alpha_g_ptr,
                         bool nos_knockout, int nos_shape_offset,
                         int nos_tag_offset, uint16_t *gs_restrict mask_row_ptr,
                         int has_mask, pdf14_buf *gs_restrict maskbuf,
                         uint16_t mask_bg_alpha, const uint16_t *gs_restrict mask_tr_fn,
                         uint16_t *gs_restrict backdrop_ptr, bool has_matte,
                         int n_chan, bool additive, int num_spots,
                         bool overprint, gx_color_index drawn_comps,
                         int x0, int y0, int x1, int y1,
                         const pdf14_nonseparable_blending_procs_t *pblend_procs,
                         pdf14_device *pdev, int has_alpha, bool tos_is_be)
{
    uint16_t *gs_restrict mask_curr_ptr = NULL;
    int width = x1 - x0;
    int x, y;
    int i;
    uint16_t tos_pixel[PDF14_MAX_PLANES];
    uint16_t nos_pixel[PDF14_MAX_PLANES];
    uint16_t back_drop[PDF14_MAX_PLANES];
    gx_color_index comps;
    bool in_mask_rect_y;
    bool in_mask_rect;
    uint16_t pix_alpha;
    uint16_t matte_alpha = 0xffff;
    int first_spot = n_chan - num_spots;
    int first_blend_spot = n_chan;
    bool has_mask2 = has_mask;
    uint16_t *gs_restrict dst;
    uint16_t global_shape = (uint16_t)(65535 * pdev->shape + 0.5);

    if (!nos_knockout && num_spots > 0 && !blend_valid_for_spot(blend_mode)) {
        first_blend_spot = first_spot;
    }
    if (blend_mode == BLEND_MODE_Normal)
        first_blend_spot = 0;
    if (!nos_isolated && backdrop_ptr != NULL)
        has_mask2 = false;

/* TOS data being passed to this routine is usually in native
 * endian format (i.e. if it's from another pdf14 buffer). Occasionally,
 * if it's being passed in from pdf_compose_alphaless_group16, it can be
 * from memory produced by another memory device (such as a pattern
 * cache device). That data is in big endian form. So we have a crufty
 * macro to get 16 bits of data from either native or bigendian into
 * a native value. This should resolve nicely at compile time. */
#define GET16_2NATIVE(be, v) \
    ((be) ? ((((byte *)&v)[0]<<8) | (((byte *)&v)[1])) : v)

    for (y = y1 - y0; y > 0; --y) {
        mask_curr_ptr = mask_row_ptr;
        in_mask_rect_y = (has_mask && y1 - y >= maskbuf->rect.p.y && y1 - y < maskbuf->rect.q.y);
        for (x = 0; x < width; x++) {
            in_mask_rect = (in_mask_rect_y && x0 + x >= maskbuf->rect.p.x && x0 + x < maskbuf->rect.q.x);
            pix_alpha = alpha;
            /* If we have a soft mask, then we have some special handling of the
               group alpha value */
            if (maskbuf != NULL) {
                if (!in_mask_rect) {
                    /* Special case where we have a soft mask but are outside
                       the range of the soft mask and must use the background
                       alpha value */
                    pix_alpha = mask_bg_alpha;
                    matte_alpha = 0xffff;
                } else {
                    if (has_matte)
                        matte_alpha = interp16(mask_tr_fn, *mask_curr_ptr);
                }
            }

            /* Matte present, need to undo premultiplied alpha prior to blend */
            if (has_matte && matte_alpha != 0 && matte_alpha != 0xffff) {
                for (i = 0; i < n_chan; i++) {
                    /* undo */
                    int val = GET16_2NATIVE(tos_is_be, tos_ptr[i * tos_planestride]) - maskbuf->matte[i];
                    int temp = (((unsigned int)(val * 0xffff)) / matte_alpha) + maskbuf->matte[i];

                    /* clip */
                    if (temp > 0xffff)
                        tos_pixel[i] = 0xffff;
                    else if (temp < 0)
                        tos_pixel[i] = 0;
                    else
                        tos_pixel[i] = temp;

                    if (!additive) {
                        /* Pure subtractive */
                        tos_pixel[i] = 65535 - tos_pixel[i];
                        nos_pixel[i] = 65535 - nos_ptr[i * nos_planestride];
                    } else {
                        /* additive or hybrid */
                        if (i >= first_spot)
                            nos_pixel[i] = 65535 - nos_ptr[i * nos_planestride];
                        else
                            nos_pixel[i] = nos_ptr[i * nos_planestride];
                    }
                }
            } else {
                /* No matte present */
                if (!additive) {
                    /* Pure subtractive */
                    for (i = 0; i < n_chan; ++i) {
                        tos_pixel[i] = 65535 - GET16_2NATIVE(tos_is_be, tos_ptr[i * tos_planestride]);
                        nos_pixel[i] = 65535 - nos_ptr[i * nos_planestride];
                    }
                } else {
                    /* Additive or hybrid */
                    for (i = 0; i < first_spot; ++i) {
                        tos_pixel[i] = GET16_2NATIVE(tos_is_be, tos_ptr[i * tos_planestride]);
                        nos_pixel[i] = nos_ptr[i * nos_planestride];
                    }
                    for (; i < n_chan; i++) {
                        tos_pixel[i] = 65535 - GET16_2NATIVE(tos_is_be, tos_ptr[i * tos_planestride]);
                        nos_pixel[i] = 65535 - nos_ptr[i * nos_planestride];
                    }
                }
            }
            /* alpha */
            tos_pixel[n_chan] = has_alpha ? GET16_2NATIVE(tos_is_be, tos_ptr[n_chan * tos_planestride]) : 65535;
            nos_pixel[n_chan] = has_alpha ? nos_ptr[n_chan * nos_planestride] : 65535;

            if (mask_curr_ptr != NULL) {
                if (in_mask_rect) {
                    uint16_t mask = interp16(mask_tr_fn, *mask_curr_ptr++);
                    int tmp = pix_alpha * (mask+(mask>>15)) + 0x8000;
                    pix_alpha = (tmp >> 16);
                } else {
                    mask_curr_ptr++;
                }
            }

            dst = nos_pixel;
            if (nos_knockout) {
                /* We need to be knocking out what ever is on the nos, but may
                   need to combine with it's backdrop */
                uint16_t tos_shape = 65535;

                if (tos_has_shape)
                    tos_shape = GET16_2NATIVE(tos_is_be, tos_ptr[tos_shape_offset]);

                if (nos_isolated || backdrop_ptr == NULL) {
                    /* We do not need to compose with the backdrop */
                    back_drop[n_chan] = 0;
                    /* FIXME: The blend here can be simplified */
                } else {
                    /* Per the PDF spec, since the tos is not isolated and we are
                       going onto a knock out group, we do the composition with
                       the nos initial backdrop. */
                    if (additive) {
                        /* additive or hybrid */
                        for (i = 0; i < first_spot; ++i) {
                            back_drop[i] = backdrop_ptr[i * nos_planestride];
                        }
                        for (; i < n_chan; i++) {
                            back_drop[i] = 65535 - backdrop_ptr[i * nos_planestride];
                        }
                    } else {
                        /* pure subtractive */
                        for (i = 0; i < n_chan; ++i) {
                            back_drop[i] = 65535 - backdrop_ptr[i * nos_planestride];
                        }
                    }
                    /* alpha */
                    back_drop[n_chan] = backdrop_ptr[n_chan * nos_planestride];
                }
                art_pdf_composite_knockout_group_16(back_drop, tos_shape,
                                                    nos_pixel, nos_alpha_g_ptr,
                                                    tos_pixel, n_chan, pix_alpha,
                                                    blend_mode, pblend_procs,
                                                    pdev, has_mask2);
            }
            else if (tos_isolated ?
                       art_pdf_composite_group_16(nos_pixel, nos_alpha_g_ptr,
                                                  tos_pixel, n_chan, pix_alpha) :
                       art_pdf_recomposite_group_16(&dst, nos_alpha_g_ptr,
                                                    tos_pixel,
                                                    has_alpha ? GET16_2NATIVE(tos_is_be, tos_ptr[tos_alpha_g_offset]) : 65535,
                                                    n_chan,
                                                    pix_alpha, blend_mode, first_blend_spot,
                                                    pblend_procs, pdev)) {
                dst = art_pdf_composite_pixel_alpha_16_inline(nos_pixel, tos_pixel, n_chan,
                                                blend_mode, first_blend_spot,
                                                pblend_procs, pdev);
            }
            if (nos_shape_offset && pix_alpha != 0) {
                nos_ptr[nos_shape_offset] =
                    art_pdf_union_mul_16(nos_ptr[nos_shape_offset],
                                         has_alpha ? GET16_2NATIVE(tos_is_be, tos_ptr[tos_shape_offset]) : global_shape,
                                         shape);
            }
            if (dst)
            {
                /* Complement the results for subtractive color spaces.  Again,
                 * if we are in an additive blending color space, we are not
                 * going to be fooling with overprint of spot colors */
                if (additive) {
                    /* additive or hybrid */
                    for (i = 0; i < first_spot; ++i) {
                        nos_ptr[i * nos_planestride] = dst[i];
                    }
                    for (; i < n_chan; i++) {
                        nos_ptr[i * nos_planestride] = 65535 - dst[i];
                    }
                } else {
                    /* Pure subtractive */
                    /* If we were running in the compatible overprint blend mode
                    * and popping the group, we don't need to fool with the
                    * drawn components as that should have already have been
                    * handled during the blending within our special non-isolated
                    * group.  So in other words, if the blend mode is normal
                    * (or compatible) and we are doing overprint, the overprint
                    * has NOT been handled by compatible overprint mode and we
                    * need to take care of it now */
                    if (overprint) {
                        for (i = 0, comps = drawn_comps; comps != 0; ++i, comps >>= 1) {
                            if ((comps & 0x1) != 0) {
                                nos_ptr[i * nos_planestride] = 65535 - dst[i];
                            }
                        }
                    } else {
                        for (i = 0; i < n_chan; ++i)
                            nos_ptr[i * nos_planestride] = 65535 - dst[i];
                    }
                }
                /* alpha */
                nos_ptr[n_chan * nos_planestride] = dst[n_chan];
            }
            /* tags */
            if (nos_tag_offset && tos_has_tag) {
                nos_ptr[nos_tag_offset] |= tos_ptr[tos_tag_offset];
             }

            if (nos_alpha_g_ptr != NULL)
                ++nos_alpha_g_ptr;
            if (backdrop_ptr != NULL)
                ++backdrop_ptr;
            ++tos_ptr;
            ++nos_ptr;
        }
        tos_ptr += tos_rowstride - width;
        nos_ptr += nos_rowstride - width;
        if (nos_alpha_g_ptr != NULL)
            nos_alpha_g_ptr += nos_rowstride - width;
        if (mask_row_ptr != NULL)
            mask_row_ptr += maskbuf->rowstride>>1;
        if (backdrop_ptr != NULL)
            backdrop_ptr += nos_rowstride - width;
    }
}