Commit message: Bug 699670: disallow copying of the epo device

The erasepage optimisation (epo) subclass device shouldn't be allowed to be
copied because the subclass private data, child and parent pointers end up
being shared between the original device and the copy.

Add an epo_finish_copydevice which NULLs the three offending pointers, and
then communicates to the caller that copying is not allowed.

This also exposed a separate issue with the stype for subclasses devices.
Devices are, I think, unique in having two stype objects associated with them:
the usual one in the memory manager header, and the other stored in the device
structere directly. In order for the stype to be correct, we have to use the
stype for the incoming device, with the ssize of the original device (ssize
should reflect the size of the memory allocation). We correctly did so with the
stype in the device structure, but then used the prototype device's stype to
patch the memory manager stype - meaning the ssize potentially no longer
matched the allocated memory. This caused problems in the garbager where there
is an implicit assumption that the size of a single object clump (c_alone == 1)
is also the size (+ memory manager overheads) of the single object it contains.

The solution is to use the same stype instance to patch the memory manager
data as we do in the device structure (with the correct ssize).
CVE: None
Vulnerability description: None

Project: ghostpdl
File: gdevdflt.c

gx_default_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox)
{
    pbox->p.x = 0;
    pbox->p.y = 0;
    pbox->q.x = int2fixed(dev->width);
    pbox->q.y = int2fixed(dev->height);
}

Project: ghostpdl
File: gdevdflt.c

gx_device_fill_in_procs(register gx_device * dev)
{
    gx_device_set_procs(dev);
    fill_dev_proc(dev, open_device, gx_default_open_device);
    fill_dev_proc(dev, get_initial_matrix, gx_default_get_initial_matrix);
    fill_dev_proc(dev, sync_output, gx_default_sync_output);
    fill_dev_proc(dev, output_page, gx_default_output_page);
    fill_dev_proc(dev, close_device, gx_default_close_device);
    /* see below for map_rgb_color */
    fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb);
    /* NOT fill_rectangle */
    fill_dev_proc(dev, tile_rectangle, gx_default_tile_rectangle);
    fill_dev_proc(dev, copy_mono, gx_default_copy_mono);
    fill_dev_proc(dev, copy_color, gx_default_copy_color);
    fill_dev_proc(dev, obsolete_draw_line, gx_default_draw_line);
    fill_dev_proc(dev, get_bits, gx_default_get_bits);
    fill_dev_proc(dev, get_params, gx_default_get_params);
    fill_dev_proc(dev, put_params, gx_default_put_params);
    /* see below for map_cmyk_color */
    fill_dev_proc(dev, get_xfont_procs, gx_default_get_xfont_procs);
    fill_dev_proc(dev, get_xfont_device, gx_default_get_xfont_device);
    fill_dev_proc(dev, map_rgb_alpha_color, gx_default_map_rgb_alpha_color);
    fill_dev_proc(dev, get_page_device, gx_default_get_page_device);
    fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
    fill_dev_proc(dev, copy_alpha, gx_default_copy_alpha);
    fill_dev_proc(dev, get_band, gx_default_get_band);
    fill_dev_proc(dev, copy_rop, gx_default_copy_rop);
    fill_dev_proc(dev, fill_path, gx_default_fill_path);
    fill_dev_proc(dev, stroke_path, gx_default_stroke_path);
    fill_dev_proc(dev, fill_mask, gx_default_fill_mask);
    fill_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid);
    fill_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram);
    fill_dev_proc(dev, fill_triangle, gx_default_fill_triangle);
    fill_dev_proc(dev, draw_thin_line, gx_default_draw_thin_line);
    fill_dev_proc(dev, begin_image, gx_default_begin_image);
    /*
     * We always replace get_alpha_bits, image_data, and end_image with the
     * new procedures, and, if in a DEBUG configuration, print a warning if
     * the definitions aren't the default ones.
     */
#ifdef DEBUG
#  define CHECK_NON_DEFAULT(proc, default, procname)\
    BEGIN\
        if ( dev_proc(dev, proc) != NULL && dev_proc(dev, proc) != default )\
            dmprintf2(dev->memory, "**** Warning: device %s implements obsolete procedure %s\n",\
                     dev->dname, procname);\
    END
#else
#  define CHECK_NON_DEFAULT(proc, default, procname)\
    DO_NOTHING
#endif
    CHECK_NON_DEFAULT(get_alpha_bits, gx_default_get_alpha_bits,
                      "get_alpha_bits");
    set_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
    CHECK_NON_DEFAULT(image_data, gx_default_image_data, "image_data");
    set_dev_proc(dev, image_data, gx_default_image_data);
    CHECK_NON_DEFAULT(end_image, gx_default_end_image, "end_image");
    set_dev_proc(dev, end_image, gx_default_end_image);
#undef CHECK_NON_DEFAULT
    fill_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle);
    fill_dev_proc(dev, strip_copy_rop, gx_default_strip_copy_rop);
    fill_dev_proc(dev, strip_copy_rop2, gx_default_strip_copy_rop2);
    fill_dev_proc(dev, strip_tile_rect_devn, gx_default_strip_tile_rect_devn);
    fill_dev_proc(dev, get_clipping_box, gx_default_get_clipping_box);
    fill_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image);
    fill_dev_proc(dev, get_bits_rectangle, gx_default_get_bits_rectangle);
    fill_dev_proc(dev, map_color_rgb_alpha, gx_default_map_color_rgb_alpha);
    fill_dev_proc(dev, create_compositor, gx_default_create_compositor);
    fill_dev_proc(dev, get_hardware_params, gx_default_get_hardware_params);
    fill_dev_proc(dev, text_begin, gx_default_text_begin);
    fill_dev_proc(dev, finish_copydevice, gx_default_finish_copydevice);

    set_dev_proc(dev, encode_color, get_encode_color(dev));
    if (dev->color_info.num_components == 3)
        set_dev_proc(dev, map_rgb_color, dev_proc(dev, encode_color));
    if (dev->color_info.num_components == 4)
        set_dev_proc(dev, map_cmyk_color, dev_proc(dev, encode_color));

    if (colors_are_separable_and_linear(&dev->color_info)) {
        fill_dev_proc(dev, encode_color, gx_default_encode_color);
        fill_dev_proc(dev, map_cmyk_color, gx_default_encode_color);
        fill_dev_proc(dev, map_rgb_color, gx_default_encode_color);
    } else {
        /* if it isn't set now punt */
        fill_dev_proc(dev, encode_color, gx_error_encode_color);
        fill_dev_proc(dev, map_cmyk_color, gx_error_encode_color);
        fill_dev_proc(dev, map_rgb_color, gx_error_encode_color);
    }

    /*
     * Fill in the color mapping procedures and the component index
     * assignment procedure if they have not been provided by the client.
     *
     * Because it is difficult to provide default encoding procedures
     * that handle level inversion, this code needs to check both
     * the number of components and the polarity of color model.
     */
    switch (dev->color_info.num_components) {
    case 1:     /* DeviceGray or DeviceInvertGray */
        /*
         * If not gray then the device must provide the color
         * mapping procs.
         */
        if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) {
            fill_dev_proc( dev,
                       get_color_mapping_procs,
                       gx_default_DevGray_get_color_mapping_procs );
        } else
            fill_dev_proc(dev, get_color_mapping_procs, gx_error_get_color_mapping_procs);
        fill_dev_proc( dev,
                       get_color_comp_index,
                       gx_default_DevGray_get_color_comp_index );
        break;

    case 3:
        if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) {
            fill_dev_proc( dev,
                       get_color_mapping_procs,
                       gx_default_DevRGB_get_color_mapping_procs );
            fill_dev_proc( dev,
                       get_color_comp_index,
                       gx_default_DevRGB_get_color_comp_index );
        } else {
            fill_dev_proc(dev, get_color_mapping_procs, gx_error_get_color_mapping_procs);
            fill_dev_proc(dev, get_color_comp_index, gx_error_get_color_comp_index);
        }
        break;

    case 4:
        fill_dev_proc(dev, get_color_mapping_procs, gx_default_DevCMYK_get_color_mapping_procs);
        fill_dev_proc(dev, get_color_comp_index, gx_default_DevCMYK_get_color_comp_index);
        break;
    default:		/* Unknown color model - set error handlers */
        if (dev_proc(dev, get_color_mapping_procs) == NULL) {
            fill_dev_proc(dev, get_color_mapping_procs, gx_error_get_color_mapping_procs);
            fill_dev_proc(dev, get_color_comp_index, gx_error_get_color_comp_index);
        }
    }

    set_dev_proc(dev, decode_color, get_decode_color(dev));
    fill_dev_proc(dev, get_profile, gx_default_get_profile);
    fill_dev_proc(dev, set_graphics_type_tag, gx_default_set_graphics_type_tag);

    /*
     * If the device is known not to support overprint mode, indicate this now.
     * Note that we do not insist that a device be use a strict DeviceCMYK
     * encoding; any color model that is subtractive and supports the cyan,
     * magenta, yellow, and black color components will do. We defer a more
     * explicit check until this information is explicitly required.
     */
    if ( dev->color_info.opmode == GX_CINFO_OPMODE_UNKNOWN          &&
         (dev->color_info.num_components < 4                     ||
          dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ||
          dev->color_info.gray_index == GX_CINFO_COMP_NO_INDEX     )  )
        dev->color_info.opmode = GX_CINFO_OPMODE_NOT;

    fill_dev_proc(dev, fill_rectangle_hl_color, gx_default_fill_rectangle_hl_color);
    fill_dev_proc(dev, include_color_space, gx_default_include_color_space);
    fill_dev_proc(dev, fill_linear_color_scanline, gx_default_fill_linear_color_scanline);
    fill_dev_proc(dev, fill_linear_color_trapezoid, gx_default_fill_linear_color_trapezoid);
    fill_dev_proc(dev, fill_linear_color_triangle, gx_default_fill_linear_color_triangle);
    fill_dev_proc(dev, update_spot_equivalent_colors, gx_default_update_spot_equivalent_colors);
    fill_dev_proc(dev, ret_devn_params, gx_default_ret_devn_params);
    fill_dev_proc(dev, fillpage, gx_default_fillpage);
    fill_dev_proc(dev, copy_alpha_hl_color, gx_default_no_copy_alpha_hl_color);

    fill_dev_proc(dev, begin_transparency_group, gx_default_begin_transparency_group);
    fill_dev_proc(dev, end_transparency_group, gx_default_end_transparency_group);

    fill_dev_proc(dev, begin_transparency_mask, gx_default_begin_transparency_mask);
    fill_dev_proc(dev, end_transparency_mask, gx_default_end_transparency_mask);
    fill_dev_proc(dev, discard_transparency_layer, gx_default_discard_transparency_layer);

    fill_dev_proc(dev, pattern_manage, gx_default_pattern_manage);
    fill_dev_proc(dev, push_transparency_state, gx_default_push_transparency_state);
    fill_dev_proc(dev, pop_transparency_state, gx_default_pop_transparency_state);

    fill_dev_proc(dev, put_image, gx_default_put_image);

    fill_dev_proc(dev, dev_spec_op, gx_default_dev_spec_op);
    fill_dev_proc(dev, copy_planes, gx_default_copy_planes);
    fill_dev_proc(dev, process_page, gx_default_process_page);
}

Project: ghostpdl
File: gdevdflt.c

void check_device_compatible_encoding(gx_device *dev)
{
    gx_device_color_info * pinfo = &(dev->color_info);
    int num_components = pinfo->num_components;
    gx_color_index mul, color_index;
    int i, j;
    gx_color_value colorants[GX_DEVICE_COLOR_MAX_COMPONENTS];

    if (pinfo->separable_and_linear == GX_CINFO_UNKNOWN_SEP_LIN)
        check_device_separable(dev);
    if (pinfo->separable_and_linear != GX_CINFO_SEP_LIN)
        return;

    if (dev_proc(dev, ret_devn_params)(dev) != NULL) {
        /* We know all devn devices are compatible. */
        pinfo->separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;
        return;
    }

    /* Do the superficial quick checks */
    for (i = 0; i < num_components; i++) {
        int shift = (num_components-1-i)*8;
        if (pinfo->comp_shift[i] != shift)
            goto bad;
        if (pinfo->comp_bits[i] != 8)
            goto bad;
        if (pinfo->comp_mask[i] != ((gx_color_index)255)<<shift)
            goto bad;
    }

    /* OK, now we are going to be slower. */
    mul = 0;
    for (i = 0; i < num_components; i++) {
        mul = (mul<<8) | 1;
    }
    for (i = 0; i < 255; i++) {
        for (j = 0; j < num_components; j++)
            colorants[j] = i*257;
        color_index = dev_proc(dev, encode_color)(dev, colorants);
        if (color_index != i*mul && (i*mul != gx_no_color_index_value))
            goto bad;
    }
    /* If we reach here, then every value matched, except possibly the last one.
     * We'll allow that to differ just in the lowest bits. */
    if ((color_index | mul) != 255*mul)
        goto bad;

    pinfo->separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;
    return;
bad:
    pinfo->separable_and_linear = GX_CINFO_SEP_LIN_NON_STANDARD;
}

Project: ghostpdl
File: gdevdflt.c

int gx_subclass_create_compositor(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
{
    pdf14_clist_device *p14dev;
    generic_subclass_data *psubclass_data;
    int code = 0;

    p14dev = (pdf14_clist_device *)dev;
    psubclass_data = p14dev->target->subclass_data;

    set_dev_proc(dev, create_compositor, psubclass_data->saved_compositor_method);

    if (gs_is_pdf14trans_compositor(pcte) != 0 && strncmp(dev->dname, "pdf14clist", 10) == 0) {
        const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pcte;

        switch (pdf14pct->params.pdf14_op) {
            case PDF14_POP_DEVICE:
                {
                    pdf14_clist_device *p14dev = (pdf14_clist_device *)dev;
                    gx_device *subclass_device;

                    p14dev->target->color_info = p14dev->saved_target_color_info;
                    if (p14dev->target->child) {
                        p14dev->target->child->color_info = p14dev->saved_target_color_info;

                        set_dev_proc(p14dev->target->child, encode_color, p14dev->saved_target_encode_color);
                        set_dev_proc(p14dev->target->child, decode_color, p14dev->saved_target_decode_color);
                        set_dev_proc(p14dev->target->child, get_color_mapping_procs, p14dev->saved_target_get_color_mapping_procs);
                        set_dev_proc(p14dev->target->child, get_color_comp_index, p14dev->saved_target_get_color_comp_index);
                    }

                    pgs->get_cmap_procs = p14dev->save_get_cmap_procs;
                    gx_set_cmap_procs(pgs, p14dev->target);

                    subclass_device = p14dev->target;
                    p14dev->target = p14dev->target->child;

                    code = dev_proc(dev, create_compositor)(dev, pcdev, pcte, pgs, memory, cdev);

                    p14dev->target = subclass_device;

                    return code;
                }
                break;
            default:
                code = dev_proc(dev, create_compositor)(dev, pcdev, pcte, pgs, memory, cdev);
                break;
        }
    } else {
        code = dev_proc(dev, create_compositor)(dev, pcdev, pcte, pgs, memory, cdev);
    }
    set_dev_proc(dev, create_compositor, gx_subclass_create_compositor);
    return code;
}

Project: ghostpdl
File: gdevepo.c

int epo_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 *memory, gx_image_enum_common_t **pinfo)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, begin_typed_image)(dev, pgs, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_include_color_space(gx_device *pdev, gs_color_space *cspace,
        const byte *res_name, int name_length)
{
    return 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_copy_color(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,\
    int x, int y, int width, int height)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, copy_color)(dev, data, data_x, raster, id, x, y, width, height);
}

Project: ghostpdl
File: gdevdflt.c

(*get_encode_color(gx_device *dev))(gx_device *, const gx_color_value *)
{
    dev_proc_encode_color(*encode_proc);

    /* use encode_color if it has been provided */
    if ((encode_proc = dev_proc(dev, encode_color)) == 0) {
        if (dev->color_info.num_components == 1                          &&
            dev_proc(dev, map_rgb_color) != 0) {
            set_cinfo_polarity(dev, GX_CINFO_POLARITY_ADDITIVE);
            encode_proc = gx_backwards_compatible_gray_encode;
        } else  if ( (dev->color_info.num_components == 3    )           &&
             (encode_proc = dev_proc(dev, map_rgb_color)) != 0  )
            set_cinfo_polarity(dev, GX_CINFO_POLARITY_ADDITIVE);
        else if ( dev->color_info.num_components == 4                    &&
                 (encode_proc = dev_proc(dev, map_cmyk_color)) != 0   )
            set_cinfo_polarity(dev, GX_CINFO_POLARITY_SUBTRACTIVE);
    }

    /*
     * If no encode_color procedure at this point, the color model had
     * better be monochrome (though not necessarily bi-level). In this
     * case, it is assumed to be additive, as that is consistent with
     * the pre-DeviceN code.
     *
     * If this is not the case, then the color model had better be known
     * to be separable and linear, for there is no other way to derive
     * an encoding. This is the case even for weakly linear and separable
     * color models with a known polarity.
     */
    if (encode_proc == 0) {
        if (dev->color_info.num_components == 1 && dev->color_info.depth != 0) {
            set_cinfo_polarity(dev, GX_CINFO_POLARITY_ADDITIVE);
            if (dev->color_info.max_gray == (1 << dev->color_info.depth) - 1)
                encode_proc = gx_default_gray_fast_encode;
            else
                encode_proc = gx_default_gray_encode;
            dev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
        } else if (colors_are_separable_and_linear(&dev->color_info)) {
            gx_color_value  max_gray = dev->color_info.max_gray;
            gx_color_value  max_color = dev->color_info.max_color;

            if ( (max_gray & (max_gray + 1)) == 0  &&
                 (max_color & (max_color + 1)) == 0  )
                /* NB should be gx_default_fast_encode_color */
                encode_proc = gx_default_encode_color;
            else
                encode_proc = gx_default_encode_color;
        }
    }

    return encode_proc;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_pop_transparency_state(gx_device *dev, gs_gstate *pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_open_device(gx_device * dev)
{
    /* Initialize the separable status if not known. */
    check_device_separable(dev);
    return 0;
}

Project: ghostpdl
File: gdevepo.c

device_wants_optimization(gx_device *dev)
{
    return (dev_proc(dev, fillpage) == gx_default_fillpage);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_pattern_manage(gx_device *pdev, gx_bitmap_id id, gs_pattern1_instance_t *pinst, pattern_manage_t function)
{
    return_error(gs_error_undefined);
}

Project: ghostpdl
File: gdevdflt.c

is_like_DeviceCMYK(gx_device * dev)
{
    subclass_color_mappings         scm;
    frac                            cm_comp_fracs[4];
    int                             i;

    if ( dev->color_info.num_components != 4                      ||
         dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE  )
        return false;
    scm = get_color_mapping_procs_subclass(dev);

    /* check the values 1/4, 1/3, 3/4, and 1/8 */

    map_cmyk_subclass( scm,
                        frac_1 / 4,
                        frac_1 / 3,
                        3 * frac_1 / 4,
                        frac_1 / 8,
                        cm_comp_fracs );

    /* verify results to .01 */
    cm_comp_fracs[0] -= frac_1 / 4;
    cm_comp_fracs[1] -= frac_1 / 3;
    cm_comp_fracs[2] -= 3 * frac_1 / 4;
    cm_comp_fracs[3] -= frac_1 / 8;
    for ( i = 0;
           i < 4                            &&
           -frac_1 / 100 < cm_comp_fracs[i] &&
           cm_comp_fracs[i] < frac_1 / 100;
          i++ )
        ;
    return i == 4;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_ret_devn_params(gx_device *pdev)
{
    return NULL;
}

Project: ghostpdl
File: gdevdflt.c

int gx_update_from_subclass(gx_device *dev)
{
    if (!dev->child)
        return 0;

    memcpy(&dev->color_info, &dev->child->color_info, sizeof(gx_device_color_info));
    memcpy(&dev->cached_colors, &dev->child->cached_colors, sizeof(gx_device_cached_colors_t));
    dev->max_fill_band = dev->child->max_fill_band;
    dev->width = dev->child->width;
    dev->height = dev->child->height;
    dev->pad = dev->child->pad;
    dev->log2_align_mod = dev->child->log2_align_mod;
    dev->max_fill_band = dev->child->max_fill_band;
    dev->is_planar = dev->child->is_planar;
    dev->LeadingEdge = dev->child->LeadingEdge;
    memcpy(&dev->ImagingBBox, &dev->child->ImagingBBox, sizeof(dev->child->ImagingBBox));
    dev->ImagingBBox_set = dev->child->ImagingBBox_set;
    memcpy(&dev->MediaSize, &dev->child->MediaSize, sizeof(dev->child->MediaSize));
    memcpy(&dev->HWResolution, &dev->child->HWResolution, sizeof(dev->child->HWResolution));
    memcpy(&dev->Margins, &dev->child->Margins, sizeof(dev->child->Margins));
    memcpy(&dev->HWMargins, &dev->child->HWMargins, sizeof(dev->child->HWMargins));
    dev->FirstPage = dev->child->FirstPage;
    dev->LastPage = dev->child->LastPage;
    dev->PageCount = dev->child->PageCount;
    dev->ShowpageCount = dev->child->ShowpageCount;
    dev->NumCopies = dev->child->NumCopies;
    dev->NumCopies_set = dev->child->NumCopies_set;
    dev->IgnoreNumCopies = dev->child->IgnoreNumCopies;
    dev->UseCIEColor = dev->child->UseCIEColor;
    dev->LockSafetyParams= dev->child->LockSafetyParams;
    dev->band_offset_x = dev->child->band_offset_y;
    dev->sgr = dev->child->sgr;
    dev->MaxPatternBitmap = dev->child->MaxPatternBitmap;
    dev->page_uses_transparency = dev->child->page_uses_transparency;
    memcpy(&dev->space_params, &dev->child->space_params, sizeof(gdev_space_params));
    dev->graphics_type_tag = dev->child->graphics_type_tag;

    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_1bit_cmyk_decode_color(
    gx_device *     dev,
    gx_color_index  color,
    gx_color_value  cv[4] )
{
    cv[0] = ((color & 0x8) != 0 ? gx_max_color_value : 0);
    cv[1] = ((color & 0x4) != 0 ? gx_max_color_value : 0);
    cv[2] = ((color & 0x2) != 0 ? gx_max_color_value : 0);
    cv[3] = ((color & 0x1) != 0 ? gx_max_color_value : 0);
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

int gx_copy_device_procs(gx_device *dest, gx_device *src, gx_device *prototype)
{
    set_dev_proc(dest, open_device, dev_proc(prototype, open_device));
    set_dev_proc(dest, get_initial_matrix, dev_proc(prototype, get_initial_matrix));
    set_dev_proc(dest, sync_output, dev_proc(prototype, sync_output));
    set_dev_proc(dest, output_page, dev_proc(prototype, output_page));
    set_dev_proc(dest, close_device, dev_proc(prototype, close_device));
    set_dev_proc(dest, map_rgb_color, dev_proc(prototype, map_rgb_color));
    set_dev_proc(dest, map_color_rgb, dev_proc(prototype, map_color_rgb));
    set_dev_proc(dest, fill_rectangle, dev_proc(prototype, fill_rectangle));
    set_dev_proc(dest, tile_rectangle, dev_proc(prototype, tile_rectangle));
    set_dev_proc(dest, copy_mono, dev_proc(prototype, copy_mono));
    set_dev_proc(dest, copy_color, dev_proc(prototype, copy_color));
    set_dev_proc(dest, obsolete_draw_line, dev_proc(prototype, obsolete_draw_line));
    set_dev_proc(dest, get_bits, dev_proc(prototype, get_bits));
    set_dev_proc(dest, get_params, dev_proc(prototype, get_params));
    set_dev_proc(dest, put_params, dev_proc(prototype, put_params));
    set_dev_proc(dest, map_cmyk_color, dev_proc(prototype, map_cmyk_color));
    set_dev_proc(dest, get_xfont_procs, dev_proc(prototype, get_xfont_procs));
    set_dev_proc(dest, get_xfont_device, dev_proc(prototype, get_xfont_device));
    set_dev_proc(dest, map_rgb_alpha_color, dev_proc(prototype, map_rgb_alpha_color));
    set_dev_proc(dest, get_page_device, dev_proc(prototype, get_page_device));
    set_dev_proc(dest, get_alpha_bits, dev_proc(prototype, get_alpha_bits));
    set_dev_proc(dest, copy_alpha, dev_proc(prototype, copy_alpha));
    set_dev_proc(dest, get_band, dev_proc(prototype, get_band));
    set_dev_proc(dest, copy_rop, dev_proc(prototype, copy_rop));
    set_dev_proc(dest, fill_path, dev_proc(prototype, fill_path));
    set_dev_proc(dest, stroke_path, dev_proc(prototype, stroke_path));
    set_dev_proc(dest, fill_trapezoid, dev_proc(prototype, fill_trapezoid));
    set_dev_proc(dest, fill_parallelogram, dev_proc(prototype, fill_parallelogram));
    set_dev_proc(dest, fill_triangle, dev_proc(prototype, fill_triangle));
    set_dev_proc(dest, draw_thin_line, dev_proc(prototype, draw_thin_line));
    set_dev_proc(dest, begin_image, dev_proc(prototype, begin_image));
    set_dev_proc(dest, image_data, dev_proc(prototype, image_data));
    set_dev_proc(dest, end_image, dev_proc(prototype, end_image));
    set_dev_proc(dest, strip_tile_rectangle, dev_proc(prototype, strip_tile_rectangle));
    set_dev_proc(dest, strip_copy_rop, dev_proc(prototype, strip_copy_rop));
    set_dev_proc(dest, get_clipping_box, dev_proc(prototype, get_clipping_box));
    set_dev_proc(dest, begin_typed_image, dev_proc(prototype, begin_typed_image));
    set_dev_proc(dest, get_bits_rectangle, dev_proc(prototype, get_bits_rectangle));
    set_dev_proc(dest, map_color_rgb_alpha, dev_proc(prototype, map_color_rgb_alpha));
    set_dev_proc(dest, create_compositor, dev_proc(prototype, create_compositor));
    set_dev_proc(dest, get_hardware_params, dev_proc(prototype, get_hardware_params));
    set_dev_proc(dest, text_begin, dev_proc(prototype, text_begin));
    set_dev_proc(dest, finish_copydevice, dev_proc(prototype, finish_copydevice));
    set_dev_proc(dest, discard_transparency_layer, dev_proc(prototype, discard_transparency_layer));
    set_dev_proc(dest, get_color_mapping_procs, dev_proc(prototype, get_color_mapping_procs));
    set_dev_proc(dest, get_color_comp_index, dev_proc(prototype, get_color_comp_index));
    set_dev_proc(dest, encode_color, dev_proc(prototype, encode_color));
    set_dev_proc(dest, decode_color, dev_proc(prototype, decode_color));
    set_dev_proc(dest, pattern_manage, dev_proc(prototype, pattern_manage));
    set_dev_proc(dest, fill_rectangle_hl_color, dev_proc(prototype, fill_rectangle_hl_color));
    set_dev_proc(dest, include_color_space, dev_proc(prototype, include_color_space));
    set_dev_proc(dest, fill_linear_color_scanline, dev_proc(prototype, fill_linear_color_scanline));
    set_dev_proc(dest, fill_linear_color_trapezoid, dev_proc(prototype, fill_linear_color_trapezoid));
    set_dev_proc(dest, fill_linear_color_triangle, dev_proc(prototype, fill_linear_color_triangle));
    set_dev_proc(dest, update_spot_equivalent_colors, dev_proc(prototype, update_spot_equivalent_colors));
    set_dev_proc(dest, ret_devn_params, dev_proc(prototype, ret_devn_params));
    set_dev_proc(dest, fillpage, dev_proc(prototype, fillpage));
    set_dev_proc(dest, push_transparency_state, dev_proc(prototype, push_transparency_state));
    set_dev_proc(dest, pop_transparency_state, dev_proc(prototype, pop_transparency_state));
    set_dev_proc(dest, dev_spec_op, dev_proc(prototype, dev_spec_op));
    set_dev_proc(dest, get_profile, dev_proc(prototype, get_profile));
    set_dev_proc(dest, strip_copy_rop2, dev_proc(prototype, strip_copy_rop2));
    set_dev_proc(dest, strip_tile_rect_devn, dev_proc(prototype, strip_tile_rect_devn));
    set_dev_proc(dest, process_page, dev_proc(prototype, process_page));

    /*
     * We absolutely must set the 'set_graphics_type_tag' to the default subclass one
     * even if the subclassed device is using the default. This is because the
     * default implementation sets a flag in the device structure, and if we
     * copy the default method, we'lll end up setting the flag in the subclassing device
     * instead of the subclassed device!
     */
    set_dev_proc(dest, set_graphics_type_tag, dev_proc(prototype, set_graphics_type_tag));

    /* These are the routines whose existence is checked against the default at
     * some point in the code. The code path differs when the device implements a
     * method other than the default, so the subclassing device needs to ensure that
     * if the subclassed device has one of these methods set to the default, we
     * do not overwrite the default method.
     */
    if (dev_proc(src, fill_mask) != gx_default_fill_mask)
        set_dev_proc(dest, fill_mask, dev_proc(prototype, fill_mask));
    if (dev_proc(src, begin_transparency_group) != gx_default_begin_transparency_group)
        set_dev_proc(dest, begin_transparency_group, dev_proc(prototype, begin_transparency_group));
    if (dev_proc(src, end_transparency_group) != gx_default_end_transparency_group)
        set_dev_proc(dest, end_transparency_group, dev_proc(prototype, end_transparency_group));
    if (dev_proc(src, put_image) != gx_default_put_image)
        set_dev_proc(dest, put_image, dev_proc(prototype, put_image));
    if (dev_proc(src, copy_planes) != gx_default_copy_planes)
        set_dev_proc(dest, copy_planes, dev_proc(prototype, copy_planes));
    if (dev_proc(src, copy_alpha_hl_color) != gx_default_no_copy_alpha_hl_color)
        set_dev_proc(dest, copy_alpha_hl_color, dev_proc(prototype, copy_alpha_hl_color));
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_composite_clist_read_update(gs_composite_t *pxcte, gx_device * cdev,
                gx_device * tdev, gs_gstate * pgs, gs_memory_t * mem)
{
    return 0;			/* Do nothing */
}

Project: ghostpdl
File: gdevdflt.c

gx_default_end_transparency_group(gx_device *dev, gs_gstate *pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
    int x, int y, int width, int height, int plane_height)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, copy_planes)(dev, data, data_x, raster, id, x, y, width, height, plane_height);
}

Project: ghostpdl
File: gdevepo.c

int epo_strip_copy_rop2(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
    const gx_color_index *scolors, const gx_strip_bitmap *textures, const gx_color_index *tcolors,
    int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop, uint planar_height)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, strip_copy_rop2)(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, phase_x, phase_y, lop, planar_height);
}

Project: ghostpdl
File: gdevdflt.c

check_device_separable(gx_device * dev)
{
    int i, j;
    gx_device_color_info * pinfo = &(dev->color_info);
    int num_components = pinfo->num_components;
    byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS];
    byte comp_bits[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index comp_mask[GX_DEVICE_COLOR_MAX_COMPONENTS];
    gx_color_index color_index;
    gx_color_index current_bits = 0;
    gx_color_value colorants[GX_DEVICE_COLOR_MAX_COMPONENTS] = { 0 };

    /* If this is already known then we do not need to do anything. */
    if (pinfo->separable_and_linear != GX_CINFO_UNKNOWN_SEP_LIN)
        return;
    /* If there is not an encode_color_routine then we cannot proceed. */
    if (dev_proc(dev, encode_color) == NULL)
        return;
    /*
     * If these values do not check then we should have an error.  However
     * we do not know what to do so we are simply exitting and hoping that
     * the device will clean up its values.
     */
    if (pinfo->gray_index < num_components &&
        (!pinfo->dither_grays || pinfo->dither_grays != (pinfo->max_gray + 1)))
            return;
    if ((num_components > 1 || pinfo->gray_index != 0) &&
        (!pinfo->dither_colors || pinfo->dither_colors != (pinfo->max_color + 1)))
        return;
    /*
     * If dither_grays or dither_colors is not a power of two then we assume
     * that the device is not separable.  In theory this not a requirement
     * but it has been true for all of the devices that we have seen so far.
     * This assumption also makes the logic in the next section easier.
     */
    if (!is_power_of_two(pinfo->dither_grays)
                    || !is_power_of_two(pinfo->dither_colors))
        return;
    /*
     * Use the encode_color routine to try to verify that the device is
     * separable and to determine the shift count, etc. for each colorant.
     */
    color_index = dev_proc(dev, encode_color)(dev, colorants);
    if (color_index != 0)
        return;		/* Exit if zero colorants produce a non zero index */
    for (i = 0; i < num_components; i++) {
        /* Check this colorant = max with all others = 0 */
        for (j = 0; j < num_components; j++)
            colorants[j] = 0;
        colorants[i] = gx_max_color_value;
        color_index = dev_proc(dev, encode_color)(dev, colorants);
        if (color_index == 0)	/* If no bits then we have a problem */
            return;
        if (color_index & current_bits)	/* Check for overlapping bits */
            return;
        current_bits |= color_index;
        comp_mask[i] = color_index;
        /* Determine the shift count for the colorant */
        for (j = 0; (color_index & 1) == 0 && color_index != 0; j++)
            color_index >>= 1;
        comp_shift[i] = j;
        /* Determine the bit count for the colorant */
        for (j = 0; color_index != 0; j++) {
            if ((color_index & 1) == 0) /* check for non-consecutive bits */
                return;
            color_index >>= 1;
        }
        comp_bits[i] = j;
        /*
         * We could verify that the bit count matches the dither_grays or
         * dither_colors values, but this is not really required unless we
         * are halftoning.  Thus we are allowing for non equal colorant sizes.
         */
        /* Check for overlap with other colorant if they are all maxed */
        for (j = 0; j < num_components; j++)
            colorants[j] = gx_max_color_value;
        colorants[i] = 0;
        color_index = dev_proc(dev, encode_color)(dev, colorants);
        if (color_index & comp_mask[i])	/* Check for overlapping bits */
            return;
    }
    /* If we get to here then the device is very likely to be separable. */
    pinfo->separable_and_linear = GX_CINFO_SEP_LIN;
    for (i = 0; i < num_components; i++) {
        pinfo->comp_shift[i] = comp_shift[i];
        pinfo->comp_bits[i] = comp_bits[i];
        pinfo->comp_mask[i] = comp_mask[i];
    }
    /*
     * The 'gray_index' value allows one colorant to have a different number
     * of shades from the remainder.  Since the default macros only guess at
     * an appropriate value, we are setting its value based upon the data that
     * we just determined.  Note:  In some cases the macros set max_gray to 0
     * and dither_grays to 1.  This is not valid so ignore this case.
     */
    for (i = 0; i < num_components; i++) {
        int dither = 1 << comp_bits[i];

        if (pinfo->dither_grays != 1 && dither == pinfo->dither_grays) {
            pinfo->gray_index = i;
            break;
        }
    }
}

Project: ghostpdl
File: gdevdflt.c

gx_default_get_initial_matrix(gx_device * dev, register gs_matrix * pmat)
{
    /* NB this device has no paper margins */
    double fs_res = dev->HWResolution[0] / 72.0;
    double ss_res = dev->HWResolution[1] / 72.0;

    switch(dev->LeadingEdge & LEADINGEDGE_MASK) {
    case 1: /* 90 degrees */
        pmat->xx = 0;
        pmat->xy = -ss_res;
        pmat->yx = -fs_res;
        pmat->yy = 0;
        pmat->tx = (float)dev->width;
        pmat->ty = (float)dev->height;
        break;
    case 2: /* 180 degrees */
        pmat->xx = -fs_res;
        pmat->xy = 0;
        pmat->yx = 0;
        pmat->yy = ss_res;
        pmat->tx = (float)dev->width;
        pmat->ty = 0;
        break;
    case 3: /* 270 degrees */
        pmat->xx = 0;
        pmat->xy = ss_res;
        pmat->yx = fs_res;
        pmat->yy = 0;
        pmat->tx = 0;
        pmat->ty = 0;
        break;
    default:
    case 0:
        pmat->xx = fs_res;
        pmat->xy = 0;
        pmat->yx = 0;
        pmat->yy = -ss_res;
        pmat->tx = 0;
        pmat->ty = (float)dev->height;
        /****** tx/y is WRONG for devices with ******/
        /****** arbitrary initial matrix ******/
        break;
    }
}

Project: ghostpdl
File: gdevdflt.c

gx_default_fill_rectangle_hl_color(gx_device *pdev,
    const gs_fixed_rect *rect,
    const gs_gstate *pgs, const gx_drawing_color *pdcolor,
    const gx_clip_path *pcpath)
{
    return_error(gs_error_rangecheck);
}

Project: ghostpdl
File: gdevdflt.c

is_like_DeviceRGB(gx_device * dev)
{
    subclass_color_mappings         scm;
    frac                            cm_comp_fracs[3];
    int                             i;

    if ( dev->color_info.num_components != 3                   ||
         dev->color_info.polarity != GX_CINFO_POLARITY_ADDITIVE  )
        return false;

    scm = get_color_mapping_procs_subclass(dev);

    /* check the values 1/4, 1/3, and 3/4 */
    map_rgb_subclass(scm, 0, frac_1 / 4, frac_1 / 3, 3 * frac_1 / 4,cm_comp_fracs);

    /* verify results to .01 */
    cm_comp_fracs[0] -= frac_1 / 4;
    cm_comp_fracs[1] -= frac_1 / 3;
    cm_comp_fracs[2] -= 3 * frac_1 / 4;
    for ( i = 0;
           i < 3                            &&
           -frac_1 / 100 < cm_comp_fracs[i] &&
           cm_comp_fracs[i] < frac_1 / 100;
          i++ )
        ;
    return i == 3;
}

Project: ghostpdl
File: gdevepo.c

int epo_process_page(gx_device *dev, gx_process_page_options_t *options)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, process_page)(dev, options);
}

Project: ghostpdl
File: gdevepo.c

int epo_create_compositor(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, create_compositor)(dev, pcdev, pcte, pgs, memory, cdev);
}

Project: ghostpdl
File: gdevdflt.c

gx_no_create_compositor(gx_device * dev, gx_device ** pcdev,
                        const gs_composite_t * pcte,
                        gs_gstate * pgs, gs_memory_t * memory,
                        gx_device *cdev)
{
    return_error(gs_error_unknownerror);	/* not implemented */
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_trapezoid(gx_device *dev, const gs_fixed_edge *left, const gs_fixed_edge *right,
    fixed ybot, fixed ytop, bool swap_axes,
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_trapezoid)(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_rectangle(gx_device *dev, int x, int y, int width, int height, gx_color_index color)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_rectangle)(dev, x, y, width, height, color);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_composite_get_cropping(const gs_composite_t *pxcte, int *ry, int *rheight,
                                  int cropping_min, int cropping_max)
{
    return 0;			/* No cropping. */
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
        const gs_fixed_point *p0, const gs_fixed_point *p1,
        const gs_fixed_point *p2, const gs_fixed_point *p3,
        const frac31 *c0, const frac31 *c1,
        const frac31 *c2, const frac31 *c3)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_linear_color_trapezoid)(dev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
}

Project: ghostpdl
File: gdevepo.c

int epo_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)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_rectangle_hl_color)(dev, rect, pgs, pdcolor, pcpath);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_push_transparency_state(gx_device *dev, gs_gstate *pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

int gx_device_subclass(gx_device *dev_to_subclass, gx_device *new_prototype, unsigned int private_data_size)
{
    gx_device *child_dev;
    void *psubclass_data;
    gs_memory_struct_type_t *a_std, *b_std;
    int dynamic = dev_to_subclass->stype_is_dynamic;
    char *ptr, *ptr1;

    /* If this happens we are stuffed, as there is no way to get hold
     * of the original device's stype structure, which means we cannot
     * allocate a replacement structure. Abort if so.
     * Also abort if the new_prototype device struct is too large.
     */
    if (!dev_to_subclass->stype ||
        dev_to_subclass->stype->ssize < new_prototype->params_size)
        return_error(gs_error_VMerror);

    /* We make a 'stype' structure for our new device, and copy the old stype into it
     * This means our new device will always have the 'stype_is_dynamic' flag set
     */
    a_std = (gs_memory_struct_type_t *)
        gs_alloc_bytes_immovable(dev_to_subclass->memory->non_gc_memory, sizeof(*a_std),
                                 "gs_device_subclass(stype)");
    if (!a_std)
        return_error(gs_error_VMerror);
    *a_std = *dev_to_subclass->stype;
    a_std->ssize = dev_to_subclass->params_size;

    if (!dynamic) {
        b_std = (gs_memory_struct_type_t *)
            gs_alloc_bytes_immovable(dev_to_subclass->memory->non_gc_memory, sizeof(*b_std),
                                     "gs_device_subclass(stype)");
        if (!b_std)
            return_error(gs_error_VMerror);
    }

    /* Allocate a device structure for the new child device */
    child_dev = gs_alloc_struct_immovable(dev_to_subclass->memory->stable_memory, gx_device, a_std,
                                        "gs_device_subclass(device)");
    if (child_dev == 0) {
        gs_free_const_object(dev_to_subclass->memory->non_gc_memory, a_std, "gs_device_subclass(stype)");
        gs_free_const_object(dev_to_subclass->memory->non_gc_memory, b_std, "gs_device_subclass(stype)");
        return_error(gs_error_VMerror);
    }

    /* Make sure all methods are filled in, note this won't work for a forwarding device
     * so forwarding devices will have to be filled in before being subclassed. This doesn't fill
     * in the fill_rectangle proc, that gets done in the ultimate device's open proc.
     */
    gx_device_fill_in_procs(dev_to_subclass);
    memcpy(child_dev, dev_to_subclass, dev_to_subclass->stype->ssize);
    child_dev->stype = a_std;
    child_dev->stype_is_dynamic = 1;

    psubclass_data = (void *)gs_alloc_bytes(dev_to_subclass->memory->non_gc_memory, private_data_size, "subclass memory for subclassing device");
    if (psubclass_data == 0){
        gs_free_const_object(dev_to_subclass->memory->non_gc_memory, a_std, "gs_device_subclass(stype)");
        gs_free_const_object(dev_to_subclass->memory->non_gc_memory, b_std, "gs_device_subclass(stype)");
        gs_free_object(dev_to_subclass->memory->stable_memory, child_dev, "free subclass memory for subclassing device");
        return_error(gs_error_VMerror);
    }
    memset(psubclass_data, 0x00, private_data_size);

    gx_copy_device_procs(dev_to_subclass, child_dev, new_prototype);
    set_dev_proc(dev_to_subclass, fill_rectangle, dev_proc(new_prototype, fill_rectangle));
    set_dev_proc(dev_to_subclass, copy_planes, dev_proc(new_prototype, copy_planes));
    dev_to_subclass->finalize = new_prototype->finalize;
    dev_to_subclass->dname = new_prototype->dname;
    if (dev_to_subclass->icc_struct)
        rc_increment(dev_to_subclass->icc_struct);
    if (dev_to_subclass->PageList)
        rc_increment(dev_to_subclass->PageList);

    /* In case the new device we're creating has already been initialised, copy
     * its additional data.
     */
    ptr = ((char *)dev_to_subclass) + sizeof(gx_device);
    ptr1 = ((char *)new_prototype) + sizeof(gx_device);
    memcpy(ptr, ptr1, new_prototype->params_size - sizeof(gx_device));

    /* If the original device's stype structure was dynamically allocated, we need
     * to 'fixup' the contents, it's procs need to point to the new device's procs
     * for instance.
     */
    if (dynamic) {
        if (new_prototype->stype) {
            b_std = (gs_memory_struct_type_t *)dev_to_subclass->stype;
            *b_std = *new_prototype->stype;
            b_std->ssize = a_std->ssize;
            dev_to_subclass->stype_is_dynamic = 1;
        } else {
            gs_free_const_object(child_dev->memory->non_gc_memory, dev_to_subclass->stype,
                             "unsubclass");
            dev_to_subclass->stype = NULL;
            b_std = (gs_memory_struct_type_t *)new_prototype->stype;
            dev_to_subclass->stype_is_dynamic = 0;
        }
    }
    else {
        *b_std = *new_prototype->stype;
        b_std->ssize = a_std->ssize;
        dev_to_subclass->stype_is_dynamic = 1;
    }
    dev_to_subclass->stype = b_std;
    /* We have to patch up the "type" parameters that the memory manage/garbage
     * collector will use, as well.
     */
    gs_set_object_type(child_dev->memory, dev_to_subclass, b_std);

    dev_to_subclass->subclass_data = psubclass_data;
    dev_to_subclass->child = child_dev;
    if (child_dev->parent) {
        dev_to_subclass->parent = child_dev->parent;
        child_dev->parent->child = dev_to_subclass;
    }
    if (child_dev->child) {
        child_dev->child->parent = child_dev;
    }
    child_dev->parent = dev_to_subclass;

    return 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_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)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_path)(dev, pgs, ppath, params, pdcolor, pcpath);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_composite_clist_write_update(const gs_composite_t *pcte, gx_device * dev,
                gx_device ** pcdev, gs_gstate * pgs, gs_memory_t * mem)
{
    *pcdev = dev;		/* Do nothing -> return the same device */
    return 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_copy_alpha(gx_device *dev, const byte *data, int data_x,
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
    gx_color_index color, int depth)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, copy_alpha)(dev, data, data_x, raster, id, x, y, width, height, color, depth);
}

Project: ghostpdl
File: gdevepo.c

int epo_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
{
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
    
    if (gs_debug_c(gs_debug_flag_epo_install_only)) {
        return default_subclass_fillpage(dev, pgs, pdevc);
    }

    /* If color is not pure, don't defer this, uninstall and do it now */
    if (!color_is_pure(pdevc)) {
        DPRINTF(dev->memory, "epo_fillpage(), color is not pure, uninstalling\n");
        gx_device_unsubclass(dev);        
        return dev_proc(dev, fillpage)(dev, pgs, pdevc);
    }
    
    /* Save the color being requested, and swallow the fillpage */
    data->last_color = pdevc->colors.pure;
    
    DPRINTF(dev->memory, "Swallowing fillpage\n");
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_install(gx_device * dev, gs_gstate * pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

set_cinfo_polarity(gx_device * dev, gx_color_polarity_t new_polarity)
{
#ifdef DEBUG
    /* sanity check */
    if (new_polarity == GX_CINFO_POLARITY_UNKNOWN) {
        dmprintf(dev->memory, "set_cinfo_polarity: illegal operand\n");
        return;
    }
#endif
    /*
     * The meory devices assume that single color devices are gray.
     * This may not be true if SeparationOrder is specified.  Thus only
     * change the value if the current value is unknown.
     */
    if (dev->color_info.polarity == GX_CINFO_POLARITY_UNKNOWN)
        dev->color_info.polarity = new_polarity;
}

Project: ghostpdl
File: gdevepo.c

int epo_draw_line(gx_device *dev, int x0, int y0, int x1, int y1, gx_color_index color)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, obsolete_draw_line)(dev, x0, y0, x1, y1, color);
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_triangle(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_triangle)(dev, px, py, ax, ay, bx, by, pdcolor, lop);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_end_page(gx_device * dev, int reason, gs_gstate * pgs)
{
    return (reason != 2 ? 1 : 0);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_output_page(gx_device * dev, int num_copies, int flush)
{
    int code = dev_proc(dev, sync_output)(dev);

    if (code >= 0)
        code = gx_finish_output_page(dev, num_copies, flush);
    return code;
}

Project: ghostpdl
File: gdevepo.c

int epo_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 **ppte)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, text_begin)(dev, pgs, text, font, path, pdcolor, pcpath, memory, ppte);
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_mask(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
    int x, int y, int width, int height,
    const gx_drawing_color *pdcolor, int depth,
    gs_logical_operation_t lop, const gx_clip_path *pcpath)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_mask)(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth, lop, pcpath);
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
        const gs_fixed_point *p0, const gs_fixed_point *p1,
        const gs_fixed_point *p2, const frac31 *c0, const frac31 *c1, const frac31 *c2)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_linear_color_triangle)(dev, fa, p0, p1, p2, c0, c1, c2);
}

Project: ghostpdl
File: gdevepo.c

epo_check_and_install(gx_device *dev)
{
    int code = 0;
    bool is_installed;
    bool can_optimize = false;
    
    /* Debugging mode to totally disable this */
    if (gs_debug_c(gs_debug_flag_epo_disable)) {
        return code;
    }
    
    DPRINTF1(dev->memory, "current device is %s\n", dev->dname);

    is_installed = is_device_installed(dev, EPO_DEVICENAME);
    
    if (is_installed) {
        DPRINTF1(dev->memory, "device %s already installed\n", EPO_DEVICENAME);
        /* This is looking for the case where the device
         * changed into something we can't optimize, after it was already installed
         * (could be clist or some other weird thing)
         */
        if (dev->child) {
            can_optimize = device_wants_optimization(dev->child);
        }
        if (!can_optimize) {
            DPRINTF1(dev->memory, "child %s can't be optimized, uninstalling\n", dev->child->dname);
            /* Not doing any pending fillpages because we are about to do
             * a fillpage anyway
             */
            gx_device_unsubclass(dev);        
            return code;
        }
    } else {
        can_optimize = device_wants_optimization(dev);
    }

    /* Already installed, nothing to do */
    if (is_installed) {
        return code;
    }

    /* See if we can optimize */
    if (!can_optimize) {
        DPRINTF(dev->memory, "device doesn't want optimization, not installing\n");
        return code;
    }

    /* Install subclass for optimization */
    code = gx_device_subclass(dev, (gx_device *)&gs_epo_device, sizeof(erasepage_subclass_data));
    if (code < 0) {
        DPRINTF1(dev->memory, "ERROR installing device %s\n", EPO_DEVICENAME);
        return code;
    }
        
    DPRINTF1(dev->memory, "SUCCESS installed device %s\n", dev->dname);
    return code;
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_parallelogram(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_parallelogram)(dev, px, py, ax, ay, bx, by, pdcolor, lop);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_sync_output(gx_device * dev)
{
    return 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_copy_mono(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
    int x, int y, int width, int height,
    gx_color_index color0, gx_color_index color1)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, copy_mono)(dev, data, data_x, raster, id, x, y, width, height, color0, color1);
}

Project: ghostpdl
File: gdevepo.c

is_device_installed(gx_device *dev, const char *name)
{
    while (dev) {
        if (!strcmp(dev->dname, name)) {
            return true;
        }
        dev = dev->child;
    }
    return false;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
{
    switch(dev_spec_op) {
        case gxdso_form_begin:
        case gxdso_form_end:
        case gxdso_pattern_can_accum:
        case gxdso_pattern_start_accum:
        case gxdso_pattern_finish_accum:
        case gxdso_pattern_load:
        case gxdso_pattern_shading_area:
        case gxdso_pattern_is_cpath_accum:
        case gxdso_pattern_handles_clip_path:
        case gxdso_is_pdf14_device:
        case gxdso_supports_devn:
        case gxdso_supports_hlcolor:
        case gxdso_supports_saved_pages:
        case gxdso_needs_invariant_palette:
        case gxdso_supports_iccpostrender:
            return 0;
        case gxdso_pattern_shfill_doesnt_need_path:
            return (dev_proc(pdev, fill_path) == gx_default_fill_path);
        case gxdso_is_std_cmyk_1bit:
            return (dev_proc(pdev, map_cmyk_color) == cmyk_1bit_map_cmyk_color);
        case gxdso_interpolate_antidropout:
            return pdev->color_info.use_antidropout_downscaler;
        case gxdso_interpolate_threshold:
            if ((pdev->color_info.num_components == 1 &&
                 pdev->color_info.max_gray < 15) ||
                (pdev->color_info.num_components > 1 &&
                 pdev->color_info.max_color < 15)) {
                /* If we are a limited color device (i.e. we are halftoning)
                 * then only interpolate if we are upscaling by at least 4 */
                return 4;
            }
            return 0; /* Otherwise no change */
        case gxdso_get_dev_param:
            {
                dev_param_req_t *request = (dev_param_req_t *)data;
                return gx_default_get_param(pdev, request->Param, request->list);
            }
    }
    return_error(gs_error_undefined);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_discard_transparency_layer(gx_device *dev, gs_gstate *pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevepo.c

epo_disable(int flag)
{
    gs_debug[gs_debug_flag_epo_disable] = flag;
}

Project: ghostpdl
File: gdevepo.c

int epo_finish_copydevice(gx_device *dev, const gx_device *from_dev)
{
    /* We musn't allow the following pointers to remain shared with the from_dev
       because we're about to tell the caller it's only allowed to copy the prototype
       and free the attempted copy of a non-prototype. If from_dev is the prototype
       these pointers won't be set, anyway.
     */
    dev->child = NULL;
    dev->parent = NULL;
    dev->subclass_data = NULL;
    /* Only allow copying the prototype. */
    return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_finish_copydevice(gx_device *dev, const gx_device *from_dev)
{
    /* Only allow copying the prototype. */
    return (from_dev->memory ? gs_note_error(gs_error_rangecheck) : 0);
}

Project: ghostpdl
File: gdevepo.c

int epo_copy_alpha_hl_color(gx_device *dev, const byte *data, int data_x,
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
    const gx_drawing_color *pdcolor, int depth)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, copy_alpha_hl_color)(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
}

Project: ghostpdl
File: gdevepo.c

int epo_tile_rectangle(gx_device *dev, const gx_tile_bitmap *tile, int x, int y, int width, int height,
    gx_color_index color0, gx_color_index color1,
    int phase_x, int phase_y)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, tile_rectangle)(dev, tile, x, y, width, height, color0, color1, phase_x, phase_y);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_no_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x, int raster, gx_bitmap_id id, int x, int y, int width, int height, const gx_drawing_color *pdcolor, int depth)
{
    return_error(gs_error_undefined);
}

Project: ghostpdl
File: gdevepo.c

static RELOC_PTRS_WITH(epo_reloc_ptrs, gx_device *dev)
{
    dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
    dev->child = gx_device_reloc_ptr(dev->child, gcst);
}RELOC_PTRS_END

Project: ghostpdl
File: gdevdflt.c

gx_default_get_alpha_bits(gx_device * dev, graphics_object_type type)
{
    return (type == go_text ? dev->color_info.anti_alias.text_bits :
            dev->color_info.anti_alias.graphics_bits);
}

Project: ghostpdl
File: gdevepo.c

int epo_strip_copy_rop(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
    const gx_color_index *scolors,
    const gx_strip_bitmap *textures, const gx_color_index *tcolors,
    int x, int y, int width, int height,
    int phase_x, int phase_y, gs_logical_operation_t lop)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, strip_copy_rop)(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, phase_x, phase_y, lop);
}

Project: ghostpdl
File: gdevdflt.c

gx_page_device_get_page_device(gx_device * dev)
{
    return dev;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_1_sub_decode_color(
    gx_device *     dev,
    gx_color_index  color,
    gx_color_value  cv[1] )
{
    gx_color_value  rgb[3];
    int             code = dev_proc(dev, map_color_rgb)(dev, color, rgb);

    cv[0] = gx_max_color_value - rgb[0];
    return code;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_begin_page(gx_device * dev, gs_gstate * pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_begin_transparency_group(gx_device *dev, const gs_transparency_group_params_t *ptgp, const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
{
    return 0;
}

Project: ghostpdl
File: gdevepo.c

epo_handle_erase_page(gx_device *dev)
{
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
    int code = 0;
    
    if (gs_debug_c(gs_debug_flag_epo_install_only)) {
        gx_device_unsubclass(dev);
        DPRINTF1(dev->memory, "Uninstall erasepage, device=%s\n", dev->dname);
        return code;
    }

    DPRINTF1(dev->memory, "Do fillpage, Uninstall erasepage, device %s\n", dev->dname);

    /* Just do a fill_rectangle (using saved color) */
    if (dev->child) {
        code = dev_proc(dev->child, fill_rectangle)(dev->child,
                                                    0, 0,
                                                    dev->child->width,
                                                    dev->child->height,
                                                    data->last_color);
    }
    /* Remove the epo device */
    gx_device_unsubclass(dev);

    return code;
}

Project: ghostpdl
File: gdevepo.c

int epo_put_image(gx_device *dev, const byte **buffers, int num_chan, int x, int y,
            int width, int height, int row_stride,
            int alpha_plane_index, int tag_plane_index)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, put_image)(dev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_close_device(gx_device * dev)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_get_xfont_procs(gx_device * dev)
{
    return NULL;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_process_page(gx_device *dev, gx_process_page_options_t *options)
{
    gs_int_rect rect;
    int code = 0;
    void *buffer = NULL;

    /* Possible future improvements in here could be given by us dividing the
     * page up into n chunks, and spawning a thread per chunk to do the
     * process_fn call on. n could be given by NumRenderingThreads. This
     * would give us multi-core advantages even without clist. */
    if (options->init_buffer_fn) {
        code = options->init_buffer_fn(options->arg, dev, dev->memory, dev->width, dev->height, &buffer);
        if (code < 0)
            return code;
    }

    rect.p.x = 0;
    rect.p.y = 0;
    rect.q.x = dev->width;
    rect.q.y = dev->height;
    if (options->process_fn)
        code = options->process_fn(options->arg, dev, dev, &rect, buffer);
    if (code >= 0 && options->output_fn)
        code = options->output_fn(options->arg, dev, buffer);

    if (options->free_buffer_fn)
        options->free_buffer_fn(options->arg, dev, dev->memory, buffer);

    return code;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_create_compositor(gx_device * dev, gx_device ** pcdev,
                             const gs_composite_t * pcte,
                             gs_gstate * pgs, gs_memory_t * memory,
                             gx_device *cdev)
{
    return pcte->type->procs.create_default_compositor
        (pcte, pcdev, dev, pgs, memory);
}

Project: ghostpdl
File: gdevepo.c

int epo_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)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, stroke_path)(dev, pgs, ppath, params, pdcolor, pcpath);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_composite_is_friendly(const gs_composite_t *this, byte cmd0, byte cmd1)
{
    return false;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_put_image(gx_device *dev, const byte **buffers, int num_chan, int x, int y, int width, int height, int row_stride, int alpha_plane_index, int tag_plane_index)
{
    return_error(gs_error_undefined);
}

Project: ghostpdl
File: gdevepo.c

int epo_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)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, begin_image)(dev, pgs, pim, format, prect, pdcolor, pcpath, memory, pinfo);
}

Project: ghostpdl
File: gdevdflt.c

gx_upright_get_initial_matrix(gx_device * dev, register gs_matrix * pmat)
{
    pmat->xx = dev->HWResolution[0] / 72.0;	/* x_pixels_per_inch */
    pmat->xy = 0;
    pmat->yx = 0;
    pmat->yy = dev->HWResolution[1] / 72.0;	/* y_pixels_per_inch */
    /****** tx/y is WRONG for devices with ******/
    /****** arbitrary initial matrix ******/
    pmat->tx = 0;
    pmat->ty = 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_output_page(gx_device *dev, int num_copies, int flush)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, output_page)(dev, num_copies, flush);
}

Project: ghostpdl
File: gdevdflt.c

set_linear_color_bits_mask_shift(gx_device * dev)
{
    int i;
    byte gray_index = dev->color_info.gray_index;
    gx_color_value max_gray = dev->color_info.max_gray;
    gx_color_value max_color = dev->color_info.max_color;
    int num_components = dev->color_info.num_components;

#define comp_bits (dev->color_info.comp_bits)
#define comp_mask (dev->color_info.comp_mask)
#define comp_shift (dev->color_info.comp_shift)
    comp_shift[num_components - 1] = 0;
    for ( i = num_components - 1 - 1; i >= 0; i-- ) {
        comp_shift[i] = comp_shift[i + 1] +
            ( i == gray_index ? ilog2(max_gray + 1) : ilog2(max_color + 1) );
    }
    for ( i = 0; i < num_components; i++ ) {
        comp_bits[i] = ( i == gray_index ?
                         ilog2(max_gray + 1) :
                         ilog2(max_color + 1) );
        comp_mask[i] = (((gx_color_index)1 << comp_bits[i]) - 1)
                                               << comp_shift[i];
    }
#undef comp_bits
#undef comp_mask
#undef comp_shift
}

Project: ghostpdl
File: gdevdflt.c

gx_default_composite_is_closing(const gs_composite_t *this, gs_composite_t **pcte, gx_device *dev)
{
    return COMP_ENQUEUE;
}

Project: ghostpdl
File: gdevepo.c

int epo_copy_rop(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
    const gx_color_index *scolors,
    const gx_tile_bitmap *texture, const gx_color_index *tcolors,
    int x, int y, int width, int height,
    int phase_x, int phase_y, gs_logical_operation_t lop)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, copy_rop)(dev, sdata, sourcex, sraster, id, scolors, texture, tcolors, x, y, width, height, phase_x, phase_y, lop);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_update_spot_equivalent_colors(gx_device *pdev, const gs_gstate * pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevepo.c

int epo_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
        int i, int j, int w, const frac31 *c0, const int32_t *c0_f, const int32_t *cg_num,
        int32_t cg_den)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, fill_linear_color_scanline)(dev, fa, i, j, w, c0, c0_f, cg_num, cg_den);
}

Project: ghostpdl
File: gdevepo.c

int epo_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1,
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
    fixed adjustx, fixed adjusty)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, draw_thin_line)(dev, fx0, fy0, fx1, fy1, pdcolor, lop, adjustx, adjusty);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

(*get_decode_color(gx_device * dev))(gx_device *, gx_color_index, gx_color_value *)
{
    /* if a method has already been provided, use it */
    if (dev_proc(dev, decode_color) != 0)
        return dev_proc(dev, decode_color);

    /*
     * If a map_color_rgb method has been provided, we may be able to use it.
     * Currently this will always be the case, as a default value will be
     * provided this method. While this default may not be correct, we are not
     * introducing any new errors by using it.
     */
    if (dev_proc(dev, map_color_rgb) != 0) {

        /* if the device has a DeviceRGB color model, use map_color_rgb */
        if (is_like_DeviceRGB(dev))
            return dev_proc(dev, map_color_rgb);

        /* If separable ande linear then use default */
        if (colors_are_separable_and_linear(&dev->color_info))
            return &gx_default_decode_color;

        /* gray devices can be handled based on their polarity */
        if ( dev->color_info.num_components == 1 &&
             dev->color_info.gray_index == 0       )
            return dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE
                       ? &gx_default_1_add_decode_color
                       : &gx_default_1_sub_decode_color;

        /*
         * There is no accurate way to decode colors for cmyk devices
         * using the map_color_rgb procedure. Unfortunately, this cases
         * arises with some frequency, so it is useful not to generate an
         * error in this case. The mechanism below assumes full undercolor
         * removal and black generation, which may not be accurate but are
         * the  best that can be done in the general case in the absence of
         * other information.
         *
         * As a hack to handle certain common devices, if the map_rgb_color
         * routine is cmyk_1bit_map_color_rgb, we provide a direct one-bit
         * decoder.
         */
        if (is_like_DeviceCMYK(dev)) {
            if (dev_proc(dev, map_color_rgb) == cmyk_1bit_map_color_rgb)
                return &gx_1bit_cmyk_decode_color;
            else
                return &gx_default_cmyk_decode_color;
        }
    }

    /*
     * The separable and linear case will already have been handled by
     * code in gx_device_fill_in_procs, so at this point we can only hope
     * the device doesn't use the decode_color method.
     */
    if (colors_are_separable_and_linear(&dev->color_info))
        return &gx_default_decode_color;
    else
        return &gx_error_decode_color;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_get_xfont_device(gx_device * dev)
{
    return dev;
}

Project: ghostpdl
File: gdevepo.c

int epo_strip_tile_rectangle(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
    gx_color_index color0, gx_color_index color1,
    int phase_x, int phase_y)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, strip_tile_rectangle)(dev, tiles, x, y, width, height, color0, color1, phase_x, phase_y);
}

Project: ghostpdl
File: gdevdflt.c

int gx_device_unsubclass(gx_device *dev)
{
    generic_subclass_data *psubclass_data;
    gx_device *parent, *child;
    gs_memory_struct_type_t *a_std = 0, *b_std = 0;
    int dynamic, ref_count;

    /* This should not happen... */
    if (!dev)
        return 0;

    ref_count = dev->rc.ref_count;
    child = dev->child;
    psubclass_data = (generic_subclass_data *)dev->subclass_data;
    parent = dev->parent;
    dynamic = dev->stype_is_dynamic;

    /* We need to account for the fact that we are removing ourselves from
     * the device chain after a clist device has been pushed, due to a
     * compositor action. Since we patched the clist 'create_compositor'
     * method (and target device) when it was pushed.
     * A point to note; we *don't* want to change the forwarding device's
     * 'target', because when we copy the child up to replace 'this' device
     * we do still want the forwarding device to point here. NB its the *child*
     * device that goes away.
     */
    if (psubclass_data != NULL && psubclass_data->forwarding_dev != NULL && psubclass_data->saved_compositor_method)
        psubclass_data->forwarding_dev->procs.create_compositor = psubclass_data->saved_compositor_method;

    /* If ths device's stype is dynamically allocated, keep a copy of it
     * in case we might need it.
     */
    if (dynamic) {
        a_std = (gs_memory_struct_type_t *)dev->stype;
        if (child)
            *a_std = *child->stype;
    }

    /* If ths device has any private storage, free it now */
    if (psubclass_data)
        gs_free_object(dev->memory->non_gc_memory, psubclass_data, "subclass memory for first-last page");

    /* Copy the child device into ths device's memory */
    if (child) {
        b_std = (gs_memory_struct_type_t *)dev->stype;
        rc_decrement(dev->icc_struct, "unsubclass device");
        rc_increment(child->icc_struct);
        memcpy(dev, child, child->stype->ssize);
        /* Patch back the 'stype' in the memory manager */
        gs_set_object_type(child->memory, dev, b_std);

        dev->stype = b_std;
        /* The reference count of the subclassing device may have been changed
         * (eg graphics states pointing to it) after we subclassed the device. We
         * need to ensure that we do not overwrite this when we copy back the subclassed
         * device.
         */
        dev->rc.ref_count = ref_count;

        /* If we have a chain of devices, make sure the chain beond the device we're unsubclassing
         * doesn't get broken, we needd to detach the lower chain and reattach it at the new
         * highest level
         */
        if (child->child)
            child->child->parent = dev;
        child->parent->child = child->child;
    }

    /* How can we have a subclass device with no child ? Simples; when we hit the end of job
     * restore, the devices are not freed in device chain order. To make sure we don't end up
     * following stale pointers, when a device is freed we remove it from the chain and update
     * any danlging poitners to NULL. When we later free the remaining devices its possible that
     * their child pointer can then be NULL.
     */
    if (child) {
        if (child->icc_struct)
            rc_decrement(child->icc_struct, "gx_unsubclass_device, icc_struct");
        if (child->PageList)
            rc_decrement(child->PageList, "gx_unsubclass_device, PageList");
        /* we cannot afford to free the child device if its stype is not dynamic because
         * we can't 'null' the finalise routine, and we cannot permit the device to be finalised
         * because we have copied it up one level, not discarded it.
         * (this shouldn't happen! Child devices are always created with a dynamic stype)
         * If this ever happens garbage collecton will eventually clean up the memory.
         */
        if (child->stype_is_dynamic) {
            /* Make sure that nothing will tyr to follow the device chain, just security here */
            child->parent = NULL;
            child->child = NULL;
            /* Make certainthe memory will be freed, zap the reference count */
            child->rc.ref_count = 0;
            /* We *don't* want to run the finalize routine. This would free the stype and
             * properly handle the icc_struct and PageList, but for devices with a custom
             * finalize (eg psdcmyk) it might also free memory it had allocated, and we're
             * still pointing at that memory in the parent.
             * The indirection through a variable is just to get rid of const warnings.
             */
            b_std = (gs_memory_struct_type_t *)child->stype;
            b_std->finalize = NULL;
            /* Having patched the stype, we need to make sure the memory manager uses it.
             * It keeps a copy in its own data structure, and would use that copy, which would
             * mean it would call the finalize routine that we just patched out.
             */
            gs_set_object_type(dev->memory->stable_memory, child, b_std);
            /* Now (finally) free the child memory */
            gs_free_object(dev->memory->stable_memory, child, "gx_unsubclass_device(device)");
            /* And the stype for it */
            gs_free_const_object(dev->memory->non_gc_memory, b_std, "gs_device_unsubclass(stype)");
            child = 0;
        }
    }
    if(child)
        child->parent = dev;
    dev->parent = parent;

    /* If this device has a dynamic stype, we wnt to keep using it, but we copied
     * the stype pointer from the child when we copied the rest of the device. So
     * we update the stype pointer with the saved pointer to this device's stype.
     */
    if (dynamic) {
        dev->stype = a_std;
        dev->stype_is_dynamic = 1;
    } else {
        dev->stype_is_dynamic = 0;
    }

    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_get_page_device(gx_device * dev)
{
    return NULL;
}

Project: ghostpdl
File: gdevdflt.c

gx_get_largest_clipping_box(gx_device * dev, gs_fixed_rect * pbox)
{
    pbox->p.x = min_fixed;
    pbox->p.y = min_fixed;
    pbox->q.x = max_fixed;
    pbox->q.y = max_fixed;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_1_add_decode_color(
    gx_device *     dev,
    gx_color_index  color,
    gx_color_value  cv[1] )
{
    gx_color_value  rgb[3];
    int             code = dev_proc(dev, map_color_rgb)(dev, color, rgb);

    cv[0] = rgb[0];
    return code;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_composite_adjust_ctm(gs_composite_t *pcte, int x0, int y0, gs_gstate *pgs)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_begin_transparency_mask(gx_device *dev, const gx_transparency_mask_params_t *ptgp, const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
{
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id, int x, int y, int width, int height, int plane_height)
{
    return_error(gs_error_undefined);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_cmyk_decode_color(
    gx_device *     dev,
    gx_color_index  color,
    gx_color_value  cv[4] )
{
    /* The device may have been determined to be 'separable'. */
    if (colors_are_separable_and_linear(&dev->color_info))
        return gx_default_decode_color(dev, color, cv);
    else {
        int i, code = dev_proc(dev, map_color_rgb)(dev, color, cv);
        gx_color_value min_val = gx_max_color_value;

        for (i = 0; i < 3; i++) {
            if ((cv[i] = gx_max_color_value - cv[i]) < min_val)
                min_val = cv[i];
        }
        for (i = 0; i < 3; i++)
            cv[i] -= min_val;
        cv[3] = min_val;

        return code;
    }
}

Project: ghostpdl
File: gdevdflt.c

gx_null_create_compositor(gx_device * dev, gx_device ** pcdev,
                          const gs_composite_t * pcte,
                          gs_gstate * pgs, gs_memory_t * memory,
                          gx_device *cdev)
{
    *pcdev = dev;
    return 0;
}

Project: ghostpdl
File: gdevdflt.c

gx_default_set_graphics_type_tag(gx_device *dev, gs_graphics_type_tag_t graphics_type_tag)
{
    /* set the tag but carefully preserve GS_DEVICE_ENCODES_TAGS */
    dev->graphics_type_tag = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) | graphics_type_tag;
}

Project: ghostpdl
File: gdevepo.c

int epo_get_bits(gx_device *dev, int y, byte *data, byte **actual_data)
{
    int code = epo_handle_erase_page(dev);

    if (code != 0)
        return code;
    return dev_proc(dev, get_bits)(dev, y, data, actual_data);
}

Project: ghostpdl
File: gdevdflt.c

gx_default_get_band(gx_device * dev, int y, int *band_start)
{
    return 0;
}