template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restrict src, int num_comp, int num_spots, int first_blend_spot,
               byte src_alpha, int rowstride, int planestride, bool additive, pdf14_device *pdev, gs_blend_mode_t blend_mode,
               bool overprint, gx_color_index drawn_comps, int tag_off, gs_graphics_type_tag_t curr_tag,
               int alpha_g_off, int shape_off, byte shape, bool isolated)
{
    int i, j, k;
    gx_color_index comps;
    byte dst[PDF14_MAX_PLANES] = { 0 };
    byte dest_alpha;
    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
        blend_mode == BLEND_MODE_Compatible ||
        blend_mode == BLEND_MODE_CompatibleOverprint;

    for (j = h; j > 0; --j) {
        for (i = w; i > 0; --i) {
            if ((blend_mode == BLEND_MODE_Normal && src[num_comp] == 0xff && !overprint) || dst_ptr[num_comp * planestride] == 0) {
                /* dest alpha is zero (or normal, and solid src) 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 (src[num_comp] != 0) {
                byte *pdst;
                /* 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];
                dest_alpha = dst[num_comp];
                pdst = art_pdf_composite_pixel_alpha_8_inline(dst, src, num_comp, blend_mode, first_blend_spot,
                            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) {
                    /* If this is an overprint case, and alpha_r is different
                       than alpha_d then we will need to adjust
                       the colors of the non-drawn components here too */
                    for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
                        if ((comps & 0x1) != 0) {
                            dst_ptr[k * planestride] = 255 - pdst[k];
                        } else if (dest_alpha != pdst[num_comp]) {
                            /* We need val_new = (val_old * old_alpha) / new_alpha */
                            if (pdst[num_comp] != 0) {
                                int val = (int)floor(((float)dest_alpha / (float)pdst[num_comp]) * (255 - pdst[k]) + 0.5);
                                if (val < 0)
                                    val = 0;
                                else if (val > 255)
                                    val = 255;
                                dst_ptr[k * planestride] = val;
                            }
                        }
                    }
                } else {
                    /* Post blend complement for subtractive */
                    if (!additive) {
                        /* Pure subtractive */
                        for (k = 0; k < num_comp; ++k)
                            dst_ptr[k * planestride] = 255 - pdst[k];

                    } else {
                        /* Hybrid case, additive with subtractive spots */
                        for (k = 0; k < (num_comp - num_spots); k++) {
                            dst_ptr[k * planestride] = pdst[k];
                        }
                        for (k = 0; k < num_spots; k++) {
                            dst_ptr[(k + num_comp - num_spots) * planestride] =
                                    255 - pdst[k + num_comp - num_spots];
                        }
                    }
                }
                /* The alpha channel */
                dst_ptr[num_comp * planestride] = pdst[num_comp];
            }
            if (tag_off) {
                /* If src alpha is 100% then set to curr_tag, else or */
                /* other than Normal BM, we always OR */
                if (src[num_comp] == 255 && tag_blend) {
                    dst_ptr[tag_off] = curr_tag;
                } else {
                    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;
        }
        dst_ptr += rowstride;
    }
}