#include "gdevprn.h"
#include "gdevpccm.h"
#include "gsparam.h"
#include <stdlib.h>
#ifdef DISABLE_NLS
#include "gdevstp-print.h"
#else
#include <gimp-print/gimp-print.h>
#endif
private int stp_debug = 0;
#define STP_DEBUG(x) do { if (stp_debug || getenv("STP_DEBUG")) x; } while (0)
#define X_DPI 360
#define Y_DPI 360
private dev_proc_map_rgb_color(stp_map_16m_rgb_color);
private dev_proc_map_color_rgb(stp_map_16m_color_rgb);
private dev_proc_print_page(stp_print_page);
private dev_proc_get_params(stp_get_params);
private dev_proc_put_params(stp_put_params);
private dev_proc_open_device(stp_open);
private const gx_device_procs stpm_procs =
prn_color_params_procs(
stp_open,
gdev_prn_output_page,
gdev_prn_close,
stp_map_16m_rgb_color,
stp_map_16m_color_rgb,
stp_get_params,
stp_put_params
);
gx_device_printer gs_stp_device =
prn_device(stpm_procs, "stp",
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
X_DPI, Y_DPI,
0, 0, 0, 0,
24, stp_print_page);
typedef struct
{
int topoffset;
int bottom;
stp_vars_t v;
} privdata_t;
private privdata_t stp_data =
{ 0, 0, NULL };
typedef struct
{
gx_device_printer *dev;
privdata_t *data;
uint raster;
} stp_priv_image_t;
static const char *Image_get_appname(stp_image_t *image);
static void Image_progress_conclude(stp_image_t *image);
static void Image_note_progress(stp_image_t *image,
double current, double total);
static void Image_progress_init(stp_image_t *image);
static stp_image_status_t Image_get_row(stp_image_t *image,
unsigned char *data, int row);
static int Image_height(stp_image_t *image);
static int Image_width(stp_image_t *image);
static int Image_bpp(stp_image_t *image);
static void Image_rotate_180(stp_image_t *image);
static void Image_rotate_cw(stp_image_t *image);
static void Image_rotate_ccw(stp_image_t *image);
static void Image_init(stp_image_t *image);
static stp_image_t theImage =
{
Image_init,
NULL,
NULL,
NULL,
NULL,
NULL,
Image_rotate_ccw,
Image_rotate_cw,
Image_rotate_180,
Image_bpp,
Image_width,
Image_height,
Image_get_row,
Image_get_appname,
Image_progress_init,
Image_note_progress,
Image_progress_conclude,
NULL
};
private void
stp_dbg(const char *msg, const privdata_t *stp_data)
{
fprintf(gs_stderr,"%s Settings: c: %f m: %f y: %f\n",
msg, stp_get_cyan(stp_data->v), stp_get_magenta(stp_data->v),
stp_get_yellow(stp_data->v));
fprintf(gs_stderr, "Ink type %s\n", stp_get_ink_type(stp_data->v));
fprintf(gs_stderr,"Settings: bright: %f contrast: %f\n",
stp_get_brightness(stp_data->v), stp_get_contrast(stp_data->v));
fprintf(gs_stderr,"Settings: Gamma: %f Saturation: %f Density: %f\n",
stp_get_gamma(stp_data->v), stp_get_saturation(stp_data->v),
stp_get_density(stp_data->v));
fprintf(gs_stderr, "Settings: width %d, height %d\n",
stp_get_page_width(stp_data->v), stp_get_page_height(stp_data->v));
fprintf(gs_stderr, "Settings: output type %d image type %d\n",
stp_get_output_type(stp_data->v), stp_get_image_type(stp_data->v));
fprintf(gs_stderr, "Settings: Quality %s\n",
stp_get_resolution(stp_data->v));
fprintf(gs_stderr, "Settings: Dither %s\n",
stp_get_dither_algorithm(stp_data->v));
fprintf(gs_stderr, "Settings: InputSlot %s\n",
stp_get_media_source(stp_data->v));
fprintf(gs_stderr, "Settings: MediaType %s\n",
stp_get_media_type(stp_data->v));
fprintf(gs_stderr, "Settings: MediaSize %s\n",
stp_get_media_size(stp_data->v));
fprintf(gs_stderr, "Settings: Model %s\n", stp_get_driver(stp_data->v));
fprintf(gs_stderr, "Settings: InkType %s\n", stp_get_ink_type(stp_data->v));
fprintf(gs_stderr, "Settings: OutputTo %s\n", stp_get_output_to(stp_data->v));
}
private void
stp_print_dbg(const char *msg, gx_device_printer *pdev,
const privdata_t *stp_data)
{
STP_DEBUG(if (pdev)
fprintf(gs_stderr,"%s Image: %d x %d pixels, %f x %f dpi\n",
msg, pdev->width, pdev->height, pdev->x_pixels_per_inch,
pdev->y_pixels_per_inch));
STP_DEBUG(stp_dbg(msg, stp_data));
}
private void
stp_print_debug(const char *msg, gx_device *pdev,
const privdata_t *stp_data)
{
STP_DEBUG(if (pdev)
fprintf(gs_stderr,"%s Image: %d x %d pixels, %f x %f dpi\n",
msg, pdev->width, pdev->height, pdev->x_pixels_per_inch,
pdev->y_pixels_per_inch));
STP_DEBUG(stp_dbg(msg, stp_data));
}
private void
stp_init_vars(void)
{
STP_DEBUG(fprintf(gs_stderr, "Calling "));
if (! stp_data.v)
{
STP_DEBUG(fprintf(gs_stderr, "and initializing "));
stp_init();
stp_data.v = stp_allocate_vars();
stp_set_driver(stp_data.v, "");
}
STP_DEBUG(fprintf(gs_stderr, "stp_init_vars\n"));
}
private void
stp_writefunc(void *file, const char *buf, size_t bytes)
{
FILE *prn = (FILE *)file;
fwrite(buf, 1, bytes, prn);
}
private int
stp_print_page(gx_device_printer * pdev, FILE * file)
{
stp_priv_image_t gsImage;
private int printvars_merged = 0;
int code;
stp_printer_t printer = NULL;
uint stp_raster;
byte *stp_row;
stp_papersize_t p;
theImage.rep = &gsImage;
stp_init_vars();
stp_print_dbg("stp_print_page", pdev, &stp_data);
code = 0;
stp_raster = gdev_prn_raster(pdev);
printer = stp_get_printer_by_driver(stp_get_driver(stp_data.v));
if (printer == NULL)
{
fprintf(gs_stderr, "Printer %s is not a known printer model\n",
stp_get_driver(stp_data.v));
return_error(gs_error_rangecheck);
}
if (!printvars_merged)
{
stp_merge_printvars(stp_data.v, stp_printer_get_printvars(printer));
printvars_merged = 1;
}
stp_row = gs_alloc_bytes(pdev->memory, stp_raster, "stp file buffer");
if (stp_row == 0)
return_error(gs_error_VMerror);
if (strlen(stp_get_resolution(stp_data.v)) == 0)
stp_set_resolution(stp_data.v,
((*stp_printer_get_printfuncs(printer)->default_parameters)
(printer, NULL, "Resolution")));
if (strlen(stp_get_dither_algorithm(stp_data.v)) == 0)
stp_set_dither_algorithm(stp_data.v, stp_default_dither_algorithm());
stp_set_scaling(stp_data.v, -pdev->x_pixels_per_inch);
stp_set_app_gamma(stp_data.v, 1.7);
stp_data.topoffset = 0;
stp_set_cmap(stp_data.v, NULL);
stp_set_page_width(stp_data.v, pdev->MediaSize[0]);
stp_set_page_height(stp_data.v, pdev->MediaSize[1]);
if ((p = stp_get_papersize_by_size(stp_get_page_height(stp_data.v),
stp_get_page_width(stp_data.v))) != NULL)
stp_set_media_size(stp_data.v, stp_papersize_get_name(p));
stp_print_dbg("stp_print_page", pdev, &stp_data);
gsImage.dev = pdev;
gsImage.data = &stp_data;
gsImage.raster = stp_raster;
stp_set_outfunc(stp_data.v, stp_writefunc);
stp_set_errfunc(stp_data.v, stp_writefunc);
stp_set_outdata(stp_data.v, file);
stp_set_errdata(stp_data.v, gs_stderr);
if (stp_printer_get_printfuncs(printer)->verify(printer, stp_data.v))
(stp_printer_get_printfuncs(printer)->print)
(printer, &theImage, stp_data.v);
else
code = 1;
gs_free_object(pdev->memory, stp_row, "stp row buffer");
stp_row = NULL;
if (code)
return_error(gs_error_rangecheck);
else
return 0;
}
private gx_color_index
stp_map_16m_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
gx_color_value b)
{
return gx_color_value_to_byte(b) +
((uint) gx_color_value_to_byte(g) << 8) +
((ulong) gx_color_value_to_byte(r) << 16);
}
private int
stp_map_16m_color_rgb(gx_device * dev, gx_color_index color,
gx_color_value prgb[3])
{
prgb[2] = gx_color_value_from_byte(color & 0xff);
prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
prgb[0] = gx_color_value_from_byte(color >> 16);
return 0;
}
private int
stp_write_float(gs_param_list *plist, const char *name, float value)
{
return param_write_float(plist, name, &value);
}
private int
stp_write_int(gs_param_list *plist, const char *name, int value)
{
return param_write_int(plist, name, &value);
}
private char *
c_strdup(const char *s)
{
char *ret;
if (!s)
{
STP_DEBUG(fprintf(gs_stderr, "c_strdup null ptr\n"));
ret = malloc(1);
ret[0] = 0;
return ret;
}
else
{
STP_DEBUG(fprintf(gs_stderr, "c_strdup |%s|\n", s));
ret = malloc(strlen(s) + 1);
strcpy(ret, s);
return ret;
}
}
private int
stp_get_params(gx_device *pdev, gs_param_list *plist)
{
int code;
gs_param_string pinktype;
gs_param_string pmodel;
gs_param_string pmediatype;
gs_param_string pInputSlot;
gs_param_string palgorithm;
gs_param_string pquality;
char *pmediatypestr;
char *pInputSlotstr;
char *pinktypestr;
char *pmodelstr;
char *palgorithmstr;
char *pqualitystr;
stp_init_vars();
stp_print_debug("stp_get_params(0)", pdev, &stp_data);
code = gdev_prn_get_params(pdev, plist);
stp_print_debug("stp_get_params(1)", pdev, &stp_data);
pmodelstr = c_strdup(stp_get_driver(stp_data.v));
pInputSlotstr = c_strdup(stp_get_media_source(stp_data.v));
pmediatypestr = c_strdup(stp_get_media_type(stp_data.v));
pinktypestr = c_strdup(stp_get_ink_type(stp_data.v));
palgorithmstr = c_strdup(stp_get_dither_algorithm(stp_data.v));
pqualitystr = c_strdup(stp_get_resolution(stp_data.v));
param_string_from_string(pmodel, pmodelstr);
param_string_from_string(pInputSlot, pInputSlotstr);
param_string_from_string(pmediatype, pmediatypestr);
param_string_from_string(pinktype, pinktypestr);
param_string_from_string(palgorithm, palgorithmstr);
param_string_from_string(pquality, pqualitystr);
if (code < 0 ||
(code = stp_write_float(plist, "Cyan", stp_get_cyan(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Magenta", stp_get_magenta(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Yellow", stp_get_yellow(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Brightness", stp_get_brightness(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Contrast", stp_get_contrast(stp_data.v))) < 0 ||
(code = stp_write_int(plist, "Color", stp_get_output_type(stp_data.v))) < 0 ||
(code = stp_write_int(plist, "ImageType", stp_get_image_type(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Gamma", stp_get_gamma(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Saturation", stp_get_saturation(stp_data.v))) < 0 ||
(code = stp_write_float(plist, "Density", stp_get_density(stp_data.v))) < 0 ||
(code = param_write_string(plist, "Model", &pmodel)) < 0 ||
(code = param_write_string(plist, "Dither", &palgorithm)) < 0 ||
(code = param_write_string(plist, "Quality", &pquality)) < 0 ||
(code = param_write_string(plist, "InkType", &pinktype) < 0) ||
(code = param_write_string(plist, "MediaType", &pmediatype)) < 0 ||
(code = param_write_string(plist, "stpMediaType", &pmediatype)) < 0 ||
(code = param_write_string(plist, "InputSlot", &pInputSlot)) < 0
)
{
free(pmodelstr);
free(pInputSlotstr);
free(pmediatypestr);
free(pinktypestr);
free(palgorithmstr);
free(pqualitystr);
STP_DEBUG(fprintf(stderr, "stp_get_params returns %d\n", code));
return code;
}
return 0;
}
#define STP_PUT_PARAM(plist, gtype, v, name, param, ecode) \
do { \
int code; \
gtype value; \
\
code = param_read_##gtype(plist, name, &value); \
switch (code) \
{ \
case 0: \
if (value < stp_get_##param(lower) || value > stp_get_##param(upper)) \
{ \
param_signal_error(plist, name, gs_error_rangecheck); \
ecode = -100; \
} \
else \
stp_set_##param(v, value); \
break; \
case 1: \
break; \
default: \
ecode = code; \
break; \
} \
} while (0)
private int
stp_put_params(gx_device *pdev, gs_param_list *plist)
{
const stp_vars_t lower = stp_minimum_settings();
const stp_vars_t upper = stp_maximum_settings();
gs_param_string pmediatype;
gs_param_string pInputSlot;
gs_param_string pinktype;
gs_param_string pmodel;
gs_param_string palgorithm;
gs_param_string pquality;
char *pmediatypestr;
char *pInputSlotstr;
char *pinktypestr;
char *pmodelstr;
char *palgorithmstr;
char *pqualitystr;
int code = 0;
stp_printer_t printer;
stp_init_vars();
stp_print_debug("stp_put_params(0)", pdev, &stp_data);
pmodelstr = c_strdup(stp_get_driver(stp_data.v));
pInputSlotstr = c_strdup(stp_get_media_source(stp_data.v));
pmediatypestr = c_strdup(stp_get_media_type(stp_data.v));
pinktypestr = c_strdup(stp_get_ink_type(stp_data.v));
palgorithmstr = c_strdup(stp_get_dither_algorithm(stp_data.v));
pqualitystr = c_strdup(stp_get_resolution(stp_data.v));
param_string_from_string(pmodel, pmodelstr);
param_string_from_string(pInputSlot, pInputSlotstr);
param_string_from_string(pmediatype, pmediatypestr);
param_string_from_string(pinktype, pinktypestr);
param_string_from_string(palgorithm, palgorithmstr);
param_string_from_string(pquality, pqualitystr);
STP_PUT_PARAM(plist, float, stp_data.v, "Cyan", cyan, code);
STP_PUT_PARAM(plist, float, stp_data.v, "Magenta", magenta, code);
STP_PUT_PARAM(plist, float, stp_data.v, "Yellow", yellow, code);
STP_PUT_PARAM(plist, float, stp_data.v, "Brightness", brightness, code);
STP_PUT_PARAM(plist, float, stp_data.v, "Contrast", contrast, code);
STP_PUT_PARAM(plist, int, stp_data.v, "Color", output_type, code);
STP_PUT_PARAM(plist, int, stp_data.v, "ImageType", image_type, code);
STP_PUT_PARAM(plist, float, stp_data.v, "Gamma", gamma, code);
STP_PUT_PARAM(plist, float, stp_data.v, "Saturation", saturation ,code);
STP_PUT_PARAM(plist, float, stp_data.v, "Density", density, code);
param_read_string(plist, "Quality", &pquality);
param_read_string(plist, "Dither", &palgorithm);
param_read_string(plist, "InputSlot", &pInputSlot);
param_read_string(plist, "stpMediaType", &pmediatype);
if (!pmediatype.data || pmediatype.size == 0)
param_read_string(plist, "MediaType", &pmediatype);
param_read_string(plist, "Model", &pmodel);
param_read_string(plist, "InkType", &pinktype);
if (stp_get_output_type(stp_data.v) == OUTPUT_RAW_CMYK)
{
param_signal_error(plist, "Color", gs_error_rangecheck);
code = -100;
}
if ( code < 0 )
{
free(pmodelstr);
free(pInputSlotstr);
free(pmediatypestr);
free(pinktypestr);
free(palgorithmstr);
free(pqualitystr);
return code;
}
STP_DEBUG(fprintf(gs_stderr, "pmodel.size %d pmodel.data %s\n",
pmodel.size, pmodel.data));
STP_DEBUG(fprintf(gs_stderr, "pinktype.size %d pinktype.data %s\n",
pinktype.size, pinktype.data));
STP_DEBUG(fprintf(gs_stderr, "pquality.size %d pquality.data %s\n",
pquality.size, pquality.data));
stp_set_driver_n(stp_data.v, pmodel.data, pmodel.size);
printer = stp_get_printer_by_driver(stp_get_driver(stp_data.v));
if (printer)
stp_set_printer_defaults(stp_data.v, printer, NULL);
if (pmediatype.data && pmediatype.size != 0)
stp_set_media_type_n(stp_data.v, pmediatype.data, pmediatype.size);
if (pInputSlot.data && pInputSlot.size != 0)
stp_set_media_source_n(stp_data.v, pInputSlot.data, pInputSlot.size);
if (pinktype.data && pinktype.size != 0)
stp_set_ink_type_n(stp_data.v, pinktype.data, pinktype.size);
if (palgorithm.data && palgorithm.size != 0)
stp_set_dither_algorithm_n(stp_data.v, palgorithm.data, palgorithm.size);
if (pquality.data && pquality.size != 0)
stp_set_resolution_n(stp_data.v, pquality.data, pquality.size);
stp_print_debug("stp_put_params(1)", pdev, &stp_data);
code = gdev_prn_put_params(pdev, plist);
free(pmodelstr);
free(pInputSlotstr);
free(pmediatypestr);
free(pinktypestr);
free(palgorithmstr);
free(pqualitystr);
return code;
}
private int
stp_open(gx_device *pdev)
{
float st[4];
int left,right,bottom,top,width,height;
stp_printer_t printer;
stp_init_vars();
stp_print_debug("stp_open", pdev, &stp_data);
printer = stp_get_printer_by_driver(stp_get_driver(stp_data.v));
if (!printer)
{
if (strlen(stp_get_driver(stp_data.v)) == 0)
fprintf(gs_stderr, "Printer must be specified with -sModel\n");
else
fprintf(gs_stderr, "Printer %s is not a known model\n",
stp_get_driver(stp_data.v));
return_error(gs_error_undefined);
}
stp_set_page_width(stp_data.v, pdev->MediaSize[0]);
stp_set_page_height(stp_data.v, pdev->MediaSize[1]);
(*stp_printer_get_printfuncs(printer)->media_size)
(printer, stp_data.v, &width, &height);
(*stp_printer_get_printfuncs(printer)->imageable_area)
(printer, stp_data.v, &left, &right, &bottom, &top);
st[1] = (float)bottom / 72;
st[3] = (float)(height-top) / 72;
st[0] = (float)left / 72;
st[2] = (float)(width-right) / 72;
stp_set_top(stp_data.v, 0);
stp_set_left(stp_data.v, 0);
stp_set_orientation(stp_data.v, ORIENT_PORTRAIT);
stp_data.bottom = bottom + height-top;
stp_print_debug("stp_open", pdev, &stp_data);
STP_DEBUG(fprintf(gs_stderr, "margins: l %f b %f r %f t %f\n",
st[0], st[1], st[2], st[3]));
gx_device_set_margins(pdev, st, true);
return gdev_prn_open(pdev);
}
private stp_image_status_t
Image_get_row(stp_image_t *image, unsigned char *data, int row)
{
stp_priv_image_t *im = (stp_priv_image_t *) (image->rep);
memset(data, 0, im->dev->width * 3);
if (im->dev->x_pixels_per_inch == im->dev->y_pixels_per_inch)
{
gdev_prn_copy_scan_lines(im->dev, im->data->topoffset+row,
data, im->raster);
}
else if (im->dev->x_pixels_per_inch > im->dev->y_pixels_per_inch)
{
int ratio = (im->dev->x_pixels_per_inch / im->dev->y_pixels_per_inch);
gdev_prn_copy_scan_lines(im->dev, (im->data->topoffset + row) / ratio,
data, im->raster);
}
else
{
int ratio = (im->dev->y_pixels_per_inch / im->dev->x_pixels_per_inch);
gdev_prn_copy_scan_lines(im->dev, (im->data->topoffset + row) * ratio,
data, im->raster);
}
return STP_IMAGE_OK;
}
private int
Image_bpp(stp_image_t *image)
{
return 3;
}
private int
Image_width(stp_image_t *image)
{
stp_priv_image_t *im = (stp_priv_image_t *) (image->rep);
return im->dev->width;
}
private int
Image_height(stp_image_t *image)
{
stp_priv_image_t *im = (stp_priv_image_t *) (image->rep);
float tmp,tmp2;
tmp = stp_get_top(im->data->v) + im->data->bottom;
tmp2 = (float)(im->dev->height) / (float)(im->dev->y_pixels_per_inch) * 72.;
tmp2 -= tmp;
tmp2 *= (float)(im->dev->x_pixels_per_inch) / 72.;
STP_DEBUG(fprintf(gs_stderr,"corrected page height %f\n",tmp2));
return (int)tmp2;
}
private void
Image_rotate_ccw(stp_image_t *image)
{
}
private void
Image_rotate_cw(stp_image_t *image)
{
}
private void
Image_rotate_180(stp_image_t *image)
{
}
private void
Image_init(stp_image_t *image)
{
}
private void
Image_progress_init(stp_image_t *image)
{
}
private void
Image_note_progress(stp_image_t *image, double current, double total)
{
STP_DEBUG(fprintf(gs_stderr, "."));
}
private void
Image_progress_conclude(stp_image_t *image)
{
STP_DEBUG(fprintf(gs_stderr, "\n"));
}
private const char *
Image_get_appname(stp_image_t *image)
{
return "GhostScript/stp";
}