From 6948650efd3fb9e2a70b8cf16aca57e9d0b7eb0a Mon Sep 17 00:00:00 2001 From: Chris Liddell Date: Tue, 23 Jul 2013 16:24:19 +0100 Subject: Commit of build_consolidation branch Squashed into one commit (see branch for details of the evolution of the branch). This brings gpcl6 and gxps into the Ghostscript build system, and a shared set of graphics library object files for all the interpreters. Also, brings the same configuration options to the pcl and xps products as we have for Ghostscript. --- contrib/opvp/gdevopvp.c | 5406 +++++++++++++++++++++++++++++++++++++++++++ contrib/opvp/opvp.h | 299 +++ contrib/opvp/opvp_0_2_0.h | 298 +++ contrib/opvp/opvp_common.h | 53 + contrib/opvp/opvp_media.def | 166 ++ 5 files changed, 6222 insertions(+) create mode 100644 contrib/opvp/gdevopvp.c create mode 100644 contrib/opvp/opvp.h create mode 100644 contrib/opvp/opvp_0_2_0.h create mode 100644 contrib/opvp/opvp_common.h create mode 100644 contrib/opvp/opvp_media.def (limited to 'contrib/opvp') diff --git a/contrib/opvp/gdevopvp.c b/contrib/opvp/gdevopvp.c new file mode 100644 index 000000000..c32e435d5 --- /dev/null +++ b/contrib/opvp/gdevopvp.c @@ -0,0 +1,5406 @@ +/* Copyright (c) 2003-2004, AXE, Inc. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to: + + Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor + Boston, MA 02110-1301 + USA + +*/ + +/* $Id: gdevopvp.c 728 2008-03-03 02:56:05Z sho-otani $ */ +/* gdevopvp.c ver.1.00 rel.1.0 26 Nov 2004 */ +/* OpenPrinting Vector Printer Driver Glue Code */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Set compatibility flag just in case we have GNU iconv.h */ +#ifndef USE_LIBICONV_GNU +# define LIBICONV_PLUG +#endif +#include + +#include "string_.h" +#include "math_.h" +#include "gx.h" + +#include "gscdefs.h" +#include "gsexit.h" +#include "gsstruct.h" +#include "gserrors.h" +#include "gsmatrix.h" +#include "gsparam.h" +#include "gxdevice.h" +#include "gxdcconv.h" +#include "gscspace.h" +#include "gsutil.h" +#include "gdevprn.h" +#include "gdevvec.h" +#include "spprint.h" +#include "ghost.h" +#include "gzstate.h" + +#include "gspath.h" +#include "gzpath.h" +#include "gzcpath.h" +#include "gsropt.h" +#include "gsiparam.h" +#include "gxxfont.h" + +/* added for image gamma correction */ +#include "gximage.h" +#include "gxfmap.h" +#include "gxfrac.h" +#include "gxcvalue.h" + +#include "opvp_common.h" + +#define ENABLE_SIMPLE_MODE 1 +#define ENABLE_SKIP_RASTER 1 +#define ENABLE_AUTO_REVERSE 1 + +/* ----- data types/macros ----- */ + +/* for debug */ +#ifdef printf +#undef printf +#endif +#ifdef fprintf +#undef fprintf +#endif + +/* buffer */ +#define OPVP_BUFF_SIZE 1024 + +/* ROP */ +#define OPVP_0_2_ROP_S 0xCC +#define OPVP_0_2_ROP_P 0xF0 +#define OPVP_0_2_ROP_OR 0xB8 + +/* paper */ +#define PS_DPI 72 +#define MMPI 25.4 +#define TOLERANCE 3.0 + +typedef struct { + const char *region; + const char *name; + float width; + float height; +} OPVP_Paper; + +#define X_DPI 300 +#define Y_DPI 300 + +#define MAX_PATH_POINTS 1000 + +/* driver */ +typedef struct gx_device_opvp_s { + gx_device_vector_common; +} gx_device_opvp; + +typedef struct gx_device_oprp_s { + gx_device_common; + gx_prn_device_common; +} gx_device_oprp; + +/* point (internal) */ +typedef struct { + double x; + double y; +} _fPoint; + +/* ----- private function prototypes ----- */ + +/* Utilities */ +static int opvp_startpage(gx_device *); +static int opvp_endpage(void); +static char *opvp_alloc_string(char **, const char *); +static char *opvp_cat_string(char **, const char *); +static char *opvp_adjust_num_string(char *); +static char **opvp_gen_dynamic_lib_name(void); +static char *opvp_to_utf8(char *); +#define opvp_check_in_page(pdev) \ + ((beginPage) || (inkjet) ? 0 \ + : (*vdev_proc(pdev, beginpage))((gx_device_vector*)pdev)) +static int opvp_get_papertable_index(gx_device *); +static char *opvp_get_sizestring(float, float); +/* not used static const char *opvp_get_papersize_region(gx_device *);*/ +/* not used static const char *opvp_get_papersize_name(gx_device *);*/ +/* not used static char *opvp_get_papersize_inch(gx_device *);*/ +/* not used static const char *opvp_get_papersize(gx_device *);*/ +static char *opvp_get_mediasize(gx_device *); +static char *opvp_gen_page_info(gx_device *); +static char *opvp_gen_doc_info(gx_device *); +static char *opvp_gen_job_info(gx_device *); +static int opvp_set_brush_color(gx_device_opvp *, gx_color_index, + opvp_brush_t *); +static int opvp_draw_image(gx_device_opvp *, int, + int, int, int, int, int, int, const byte *); + +/* load/unload vector driver */ +static int opvp_load_vector_driver(void); +static int opvp_unload_vector_driver(void); +static int prepare_open(gx_device *); + +/* driver procs */ +static int opvp_open(gx_device *); +static int oprp_open(gx_device *); +static void opvp_get_initial_matrix(gx_device *, gs_matrix *); +static int opvp_output_page(gx_device *, int, int); +static int opvp_close(gx_device *); +#if GS_VERSION_MAJOR >= 8 +static gx_color_index opvp_map_rgb_color(gx_device *, const gx_color_value *); /* modified for gs 8.15 */ +#else +static gx_color_index opvp_map_rgb_color(gx_device *, gx_color_value, + gx_color_value, gx_color_value); +#endif +static int opvp_map_color_rgb(gx_device *, gx_color_index, gx_color_value *); +static int opvp_copy_mono(gx_device *, const byte *, int, int, + gx_bitmap_id, int, int, int, int, + gx_color_index, gx_color_index); +static int opvp_copy_color(gx_device *, const byte *, int, int, + gx_bitmap_id, int, int, int, int); +static int _get_params(gs_param_list *); +static int opvp_get_params(gx_device *, gs_param_list *); +static int oprp_get_params(gx_device *, gs_param_list *); +static int _put_params(gs_param_list *); +static int opvp_put_params(gx_device *, gs_param_list *); +static int oprp_put_params(gx_device *, gs_param_list *); +static int opvp_fill_path(gx_device *, const gs_imager_state *, gx_path *, + const gx_fill_params *, const gx_device_color *, + const gx_clip_path *); +static int opvp_stroke_path(gx_device *, const gs_imager_state *, gx_path *, + const gx_stroke_params *, const gx_drawing_color *, + const gx_clip_path *); +static int opvp_fill_mask(gx_device *, const byte *, int, int, gx_bitmap_id, + int, int, int, int, const gx_drawing_color *, + int, gs_logical_operation_t, const gx_clip_path *); + +/* available color spaces */ + +static char cspace_available[] = { + 0, /* OPVP_CSPACE_BW */ + 0, /* OPVP_CSPACE_DEVICEGRAY */ + 0, /* OPVP_CSPACE_DEVICECMY */ + 0, /* OPVP_CSPACE_DEVICECMYK */ + 0, /* OPVP_CSPACE_DEVICERGB */ + 0, /* OPVP_CSPACE_DEVICEKRGB */ + 1, /* OPVP_CSPACE_STANDARDRGB */ + 0 /* OPVP_CSPACE_STANDARDRGB64 */ +}; + +/* vector driver procs */ +static int opvp_beginpage(gx_device_vector *); +static int opvp_setlinewidth(gx_device_vector *, double); +static int opvp_setlinecap(gx_device_vector *, gs_line_cap); +static int opvp_setlinejoin(gx_device_vector *, gs_line_join); +static int opvp_setmiterlimit(gx_device_vector *, double); +static int opvp_setdash(gx_device_vector *, const float *, uint, double); +static int opvp_setflat(gx_device_vector *, double); +static int opvp_setlogop(gx_device_vector *, gs_logical_operation_t, + gs_logical_operation_t); +#if GS_VERSION_MAJOR >= 8 +static int opvp_can_handle_hl_color(gx_device_vector *, const gs_imager_state *, const gx_drawing_color *); +static int opvp_setfillcolor(gx_device_vector *, const gs_imager_state *, const gx_drawing_color *); +static int opvp_setstrokecolor(gx_device_vector *, const gs_imager_state *,const gx_drawing_color *); +#else +static int opvp_setfillcolor(gx_device_vector *, const gx_drawing_color *); +static int opvp_setstrokecolor(gx_device_vector *, const gx_drawing_color *); +#endif +static int opvp_vector_dopath(gx_device_vector *, const gx_path *, + gx_path_type_t, const gs_matrix *); +static int opvp_vector_dorect(gx_device_vector *, fixed, fixed, fixed, fixed, + gx_path_type_t); +static int opvp_beginpath(gx_device_vector *, gx_path_type_t); +static int opvp_moveto(gx_device_vector *, double, double, double, double, + gx_path_type_t); +static int opvp_lineto(gx_device_vector *, double, double, double, double, + gx_path_type_t); +static int opvp_curveto(gx_device_vector *, double, double, double, double, + double, double, double, double, gx_path_type_t); +static int opvp_closepath(gx_device_vector *, double, double, double, double, + gx_path_type_t); +static int opvp_endpath(gx_device_vector *, gx_path_type_t); + +/* ----- Paper definition ----- */ +OPVP_Paper paperTable[] = +{ +#if 0 + {"jpn","hagaki",100/MMPI*PS_DPI,148/MMPI*PS_DPI}, + {"iso","a6" ,105/MMPI*PS_DPI,148/MMPI*PS_DPI}, + {"jis","b6" ,128/MMPI*PS_DPI,182/MMPI*PS_DPI}, + {"jpn","oufuku",148/MMPI*PS_DPI,200/MMPI*PS_DPI}, + {"iso","a5" ,148/MMPI*PS_DPI,210/MMPI*PS_DPI}, + {"jis","b5" ,182/MMPI*PS_DPI,257/MMPI*PS_DPI}, + {"iso","a4" ,210/MMPI*PS_DPI,297/MMPI*PS_DPI}, + {"na" ,"letter", 8.5*PS_DPI, 11*PS_DPI},/* 215.9x279.4 */ + {"na" ,"legal" , 8.5*PS_DPI, 14*PS_DPI},/* 215.9x355.6 */ + {"jis","b4" ,257/MMPI*PS_DPI,364/MMPI*PS_DPI}, + {"iso","a3" ,297/MMPI*PS_DPI,420/MMPI*PS_DPI}, +#else +#include "opvp_media.def" +#endif + {NULL ,NULL , 0, 0} +}; + +/* ----- Driver definition ----- */ + +/* Driver procedures */ +static dev_proc_open_device(opvp_open); +static dev_proc_open_device(oprp_open); +static dev_proc_output_page(opvp_output_page); +static dev_proc_print_page(oprp_print_page); +static dev_proc_close_device(opvp_close); +static dev_proc_get_params(opvp_get_params); +static dev_proc_get_params(oprp_get_params); +static dev_proc_put_params(opvp_put_params); +static dev_proc_put_params(oprp_put_params); +static dev_proc_fill_rectangle(opvp_fill_rectangle); +static dev_proc_begin_image(opvp_begin_image); +static image_enum_proc_plane_data(opvp_image_plane_data); +static image_enum_proc_end_image(opvp_image_end_image); + +gs_public_st_suffix_add0_final( + st_device_opvp, + gx_device_opvp, + "gx_device_opvp", + device_opvp_enum_ptrs, + device_opvp_reloc_ptrs, + gx_device_finalize, + st_device_vector +); + +#define opvp_initial_values \ + NULL, /* *vectorDriver */\ + NULL, /* *printerModel */\ + NULL, /* *handle */\ + NULL, /* (*OpenPrinter)() */\ + NULL, /* *ErrorNo */\ + -1, /* outputFD */\ + 0, /* nApiEntry */\ + NULL, /* *apiEntry */\ + -1, /* printerContext */\ + NULL, /* *jobInfo */\ + NULL /* *docInfo */ + +/* device procs */ +#define opvp_procs \ +{\ + opvp_open,\ + opvp_get_initial_matrix,\ + NULL, /* sync_output */\ + opvp_output_page,\ + opvp_close,\ + opvp_map_rgb_color,\ + opvp_map_color_rgb,\ + opvp_fill_rectangle, /*gdev_vector_fill_rectangle,*/\ + NULL, /* tile_rectangle OBSOLETE */\ + opvp_copy_mono,\ + opvp_copy_color,\ + NULL, /* draw_line OBSOLETE */\ + NULL, /* get_bits */\ + opvp_get_params,\ + opvp_put_params,\ + NULL, /* map_cmyk_color */\ + NULL, /* get_xfont_procs */\ + NULL, /* get_xfont_device */\ + NULL, /* map_rgb_alpha_color */\ + gx_page_device_get_page_device,\ + NULL, /* get_alpha_bits OBSOLETE */\ + NULL, /* copy_alpha */\ + NULL, /* get_band */\ + NULL, /* copy_rop */\ + opvp_fill_path,\ + opvp_stroke_path,\ + opvp_fill_mask,\ + gdev_vector_fill_trapezoid,\ + gdev_vector_fill_parallelogram,\ + gdev_vector_fill_triangle,\ + NULL, /* draw_thin_line */\ + opvp_begin_image,\ + NULL, /* image_data */\ + NULL, /* end_image */\ + NULL, /* strip_tile_rectangle */\ + NULL, /* strip_copy_rop */\ + NULL, /* get_clipping_box */\ + NULL, /* begin_typed_image */\ + NULL, /* get_bits_rectangle */\ + NULL, /* map_color_rgb_alpha */\ + NULL, /* create_compositor */\ + NULL, /* get_hardware_params */\ + NULL, /* text_begin */\ + NULL, /* finish_copydevice */\ + NULL, /* begin_transparency_group */\ + NULL, /* end_transparency_group */\ + NULL, /* begin_transparency_mask */\ + NULL, /* end_transparency_mask */\ + NULL /* discard_transparency_layer */\ +} + +/* vector procs */ +static gx_device_vector_procs opvp_vector_procs = +{ + /* Page management */ + opvp_beginpage, + /* Imager state */ + opvp_setlinewidth, + opvp_setlinecap, + opvp_setlinejoin, + opvp_setmiterlimit, + opvp_setdash, + opvp_setflat, + opvp_setlogop, + /* Other state */ +#if GS_VERSION_MAJOR >= 8 + opvp_can_handle_hl_color, /* added for gs 8.15 */ +#endif + opvp_setfillcolor, + opvp_setstrokecolor, + /* Paths */ + opvp_vector_dopath, + opvp_vector_dorect, + opvp_beginpath, + opvp_moveto, + opvp_lineto, + opvp_curveto, + opvp_closepath, + opvp_endpath +}; + +const gx_device_opvp gs_opvp_device = +{ + std_device_dci_type_body( + gx_device_opvp, + 0, + "opvp", + &st_device_opvp, + DEFAULT_WIDTH_10THS_A4 * X_DPI / 10, + DEFAULT_HEIGHT_10THS_A4 * Y_DPI / 10, + X_DPI, + Y_DPI, + 3, + 24, + 255, + 255, + 256, + 256 + ), + opvp_procs +}; + +/* for inkjet */ +static gx_device_procs prn_oprp_procs = + prn_color_params_procs( + oprp_open, + opvp_output_page, + opvp_close, + opvp_map_rgb_color, + opvp_map_color_rgb, + oprp_get_params, + oprp_put_params + ); + +const gx_device_oprp gs_oprp_device = +{ + prn_device_std_margins_body( + gx_device_oprp, + prn_oprp_procs, + "oprp", + DEFAULT_WIDTH_10THS_A4, + DEFAULT_HEIGHT_10THS_A4, + X_DPI, + Y_DPI, + 0, 0, 0, 0, 0, 0, + 24, + oprp_print_page + ) +}; + +/* driver mode */ +static bool vector = true; +static bool inkjet = false; +static char *vectorDriver = NULL; +static char *printerModel = NULL; +static void *handle = NULL; +static opvp_dc_t (*OpenPrinter)(opvp_int_t,const opvp_char_t*, + const opvp_int_t[2], + opvp_api_procs_t**) = NULL; +static int (*OpenPrinter_0_2)(int,char*,int*, + OPVP_api_procs**) = NULL; +static opvp_int_t *ErrorNo = NULL; +static opvp_int_t outputFD = -1; +static opvp_int_t nApiEntry = 0; +static opvp_api_procs_t *apiEntry = NULL; +static OPVP_api_procs *apiEntry_0_2 = NULL; +static opvp_dc_t printerContext = -1; +static char *jobInfo = NULL; +static char *docInfo = NULL; +static opvp_cspace_t colorSpace = OPVP_CSPACE_STANDARDRGB; +static opvp_cspace_t savedColorSpace; +static opvp_brush_t *vectorFillColor = NULL; +static float margins[4] = {0, 0, 0, 0}; +static float zoom[2] = {1, 1}; +static float shift[2] = {0, 0}; +static bool zoomAuto = false; +static bool zooming = false; +static bool beginPage = false; + +static int +GetLastError_1_0(void) +{ + return *ErrorNo; +} + +static int (*GetLastError)(void) = GetLastError_1_0; + +/* Wrapper functions that keep compatible with 0.2 */ + +/* color space mapping 0.2 to 1.0 */ +static opvp_cspace_t cspace_0_2_to_1_0[] = { + OPVP_CSPACE_BW, + OPVP_CSPACE_DEVICEGRAY, + OPVP_CSPACE_DEVICECMY, + OPVP_CSPACE_DEVICECMYK, + OPVP_CSPACE_DEVICERGB, + OPVP_CSPACE_STANDARDRGB, + OPVP_CSPACE_STANDARDRGB64 +}; + +/* color space mapping 1.0 to 0.2 */ +static opvp_cspace_t cspace_1_0_to_0_2[] = { + OPVP_cspaceBW, + OPVP_cspaceDeviceGray, + OPVP_cspaceDeviceCMY, + OPVP_cspaceDeviceCMYK, + OPVP_cspaceDeviceRGB, + 0, /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */ + OPVP_cspaceStandardRGB, + OPVP_cspaceStandardRGB64, +}; + +/* image format mapping 1.0 to 0.2 */ +static opvp_imageformat_t iformat_1_0_to_0_2[] = { + OPVP_iformatRaw, + OPVP_iformatRaw, /* OPVP_IFORMAT_MASK use iformat raw in 0.2 */ + OPVP_iformatRLE, + OPVP_iformatJPEG, + OPVP_iformatPNG, +}; +/* image colorDepth needed in 0.2 */ +static int colorDepth_0_2[] = { + 1, /* OPVP_CSPACE_BW */ + 8, /* OPVP_CSPACE_DEVICEGRAY */ + 24, /* OPVP_CSPACE_DEVICECMY */ + 32, /* OPVP_CSPACE_DEVICECMYK */ + 24, /* OPVP_CSPACE_DEVICERGB */ + 32, /* OPVP_CSPACE_DEVICEKRGB */ + 24, /* OPVP_CSPACE_STANDARDRGB */ + 64, /* OPVP_CSPACE_STANDARDRGB64 */ +}; + +/* translate error code */ +static int +GetLastError_0_2(void) +{ + switch(*ErrorNo) { + case OPVP_FATALERROR_0_2: + return OPVP_FATALERROR; + break; + case OPVP_BADREQUEST_0_2: + return OPVP_BADREQUEST; + break; + case OPVP_BADCONTEXT_0_2: + return OPVP_BADCONTEXT; + break; + case OPVP_NOTSUPPORTED_0_2: + return OPVP_NOTSUPPORTED; + break; + case OPVP_JOBCANCELED_0_2: + return OPVP_JOBCANCELED; + break; + case OPVP_PARAMERROR_0_2: + return OPVP_PARAMERROR; + break; + default: + break; + } + /* unknown error no */ + /* return FATALERROR instead */ + return OPVP_FATALERROR; +} + +static opvp_result_t +StartPageWrapper(opvp_dc_t printerContext, const opvp_char_t *pageInfo) +{ + int r; + + if ((r = apiEntry_0_2->StartPage(printerContext, + /* discard const */(char *)pageInfo)) != OPVP_OK) { + /* error */ + return r; + } + /* initialize ROP */ + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext, + OPVP_0_2_ROP_P); + } + return OPVP_OK; +} + +static opvp_result_t +InitGSWrapper(opvp_dc_t printerContext) +{ + int r; + + if ((r = apiEntry_0_2->InitGS(printerContext)) != OPVP_OK) { + /* error */ + return r; + } + /* initialize ROP */ + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext, + OPVP_0_2_ROP_P); + } + return OPVP_OK; +} + +static opvp_result_t +QueryColorSpaceWrapper( opvp_dc_t printerContext, opvp_int_t *pnum, + opvp_cspace_t *pcspace) +{ + int r; + int i; + + if ((r = apiEntry_0_2->QueryColorSpace(printerContext, + (OPVP_ColorSpace *)pcspace,pnum)) != OPVP_OK) { + /* error */ + return r; + } + /* translate cspaces */ + for (i = 0;i < *pnum;i++) { + if (pcspace[i] + >= sizeof(cspace_0_2_to_1_0)/sizeof(opvp_cspace_t)) { + /* unknown color space */ + /* set DEVICERGB instead */ + pcspace[i] = OPVP_CSPACE_DEVICERGB; + } else { + pcspace[i] = cspace_0_2_to_1_0[pcspace[i]]; + } + } + return OPVP_OK; +} + +static opvp_result_t +SetColorSpaceWrapper(opvp_dc_t printerContext, opvp_cspace_t cspace) +{ + if (cspace == OPVP_CSPACE_DEVICEKRGB) { + /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */ + *ErrorNo = OPVP_NOTSUPPORTED_0_2; + return -1; + } + if (cspace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + return apiEntry_0_2->SetColorSpace(printerContext, + cspace_1_0_to_0_2[cspace]); +} + +static opvp_result_t +GetColorSpaceWrapper(opvp_dc_t printerContext, opvp_cspace_t *pcspace) +{ + int r; + + if ((r = apiEntry_0_2->GetColorSpace(printerContext, + (OPVP_ColorSpace *)pcspace)) != OPVP_OK) { + /* error */ + return r; + } + if (*pcspace + >= sizeof(cspace_0_2_to_1_0)/sizeof(opvp_cspace_t)) { + /* unknown color space */ + /* set DEVICERGB instead */ + *pcspace = OPVP_CSPACE_DEVICERGB; + } else { + *pcspace = cspace_0_2_to_1_0[*pcspace]; + } + return r; +} + +static opvp_result_t +SetStrokeColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) +{ + OPVP_Brush brush_0_2; + + if (brush == NULL) { + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) { + /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */ + return OPVP_NOTSUPPORTED; + } + if (brush->colorSpace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace]; + brush_0_2.xorg = brush->xorg; + brush_0_2.yorg = brush->yorg; + brush_0_2.pbrush = (OPVP_BrushData *)brush->pbrush; + memcpy(brush_0_2.color,brush->color,sizeof(brush_0_2.color)); + return apiEntry_0_2->SetStrokeColor(printerContext,&brush_0_2); +} + +static opvp_result_t +SetFillColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) +{ + OPVP_Brush brush_0_2; + + if (brush == NULL) { + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) { + /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */ + return OPVP_NOTSUPPORTED; + } + if (brush->colorSpace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace]; + brush_0_2.xorg = brush->xorg; + brush_0_2.yorg = brush->yorg; + brush_0_2.pbrush = (OPVP_BrushData *)brush->pbrush; + memcpy(brush_0_2.color,brush->color,sizeof(brush_0_2.color)); + return apiEntry_0_2->SetFillColor(printerContext,&brush_0_2); +} + +static opvp_result_t +SetBgColorWrapper(opvp_dc_t printerContext, const opvp_brush_t *brush) +{ + OPVP_Brush brush_0_2; + + if (brush == NULL) { + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + if (brush->colorSpace == OPVP_CSPACE_DEVICEKRGB) { + /* 0.2 doesn't have OPVP_CSPACE_DEVICEKRGB */ + *ErrorNo = OPVP_NOTSUPPORTED_0_2; + return -1; + } + if (brush->colorSpace + >= sizeof(cspace_1_0_to_0_2)/sizeof(OPVP_ColorSpace)) { + /* unknown color space */ + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + brush_0_2.colorSpace = cspace_1_0_to_0_2[brush->colorSpace]; + brush_0_2.xorg = brush->xorg; + brush_0_2.yorg = brush->yorg; + brush_0_2.pbrush = (OPVP_BrushData *)brush->pbrush; + memcpy(brush_0_2.color,brush->color,sizeof(brush_0_2.color)); + return apiEntry_0_2->SetBgColor(printerContext,&brush_0_2); +} + +static opvp_result_t +DrawImageWrapper( + opvp_dc_t printerContext, + opvp_int_t sourceWidth, + opvp_int_t sourceHeight, + opvp_int_t sourcePitch, + opvp_imageformat_t imageFormat, + opvp_int_t destinationWidth, + opvp_int_t destinationHeight, + const void *imagedata) +{ + int r; + OPVP_Rectangle rect; + OPVP_ImageFormat iformat_0_2; + OPVP_PaintMode paintmode_0_2 = OPVP_paintModeTransparent; + int depth; + + if (imageFormat == OPVP_IFORMAT_MASK) { + if (apiEntry_0_2->GetPaintMode != NULL) { + apiEntry_0_2->GetPaintMode(printerContext, + &paintmode_0_2); + } + if (paintmode_0_2 != OPVP_paintModeTransparent) { + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext, + OPVP_0_2_ROP_S); + } + } + else { + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext, + OPVP_0_2_ROP_OR); + } + } + depth = 1; + } else { + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S); + } + depth = colorDepth_0_2[colorSpace]; + } + + OPVP_I2FIX(0,rect.p0.x); + OPVP_I2FIX(0,rect.p0.y); + OPVP_I2FIX(destinationWidth,rect.p1.x); + OPVP_I2FIX(destinationHeight,rect.p1.y); + if (imageFormat >= sizeof(iformat_1_0_to_0_2)/sizeof(OPVP_ImageFormat)) { + /* illegal image format */ + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + iformat_0_2 = iformat_1_0_to_0_2[imageFormat]; + r = apiEntry_0_2->DrawImage(printerContext,sourceWidth,sourceHeight, + depth,iformat_0_2,rect, + sourcePitch*sourceHeight, + /* remove const */ (void *)imagedata); + + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_P); + } + + return r; +} + +static opvp_result_t +StartDrawImageWrapper( + opvp_dc_t printerContext, + opvp_int_t sourceWidth, + opvp_int_t sourceHeight, + opvp_int_t sourcePitch, + opvp_imageformat_t imageFormat, + opvp_int_t destinationWidth, + opvp_int_t destinationHeight) +{ + int r; + OPVP_Rectangle rect; + OPVP_ImageFormat iformat_0_2; + OPVP_PaintMode paintmode_0_2 = OPVP_paintModeTransparent; + int depth; + + if (imageFormat == OPVP_IFORMAT_MASK) { + if (apiEntry_0_2->GetPaintMode != NULL) { + apiEntry_0_2->GetPaintMode(printerContext, + &paintmode_0_2); + } + if (paintmode_0_2 != OPVP_paintModeTransparent) { + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S); + } + } + else { + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_OR); + } + } + depth = 1; + } else { + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_S); + } + depth = colorDepth_0_2[colorSpace]; + } + + OPVP_I2FIX(0,rect.p0.x); + OPVP_I2FIX(0,rect.p0.y); + OPVP_I2FIX(destinationWidth,rect.p1.x); + OPVP_I2FIX(destinationHeight,rect.p1.y); + if (imageFormat >= sizeof(iformat_1_0_to_0_2)/sizeof(OPVP_ImageFormat)) { + /* illegal image format */ + *ErrorNo = OPVP_PARAMERROR_0_2; + return -1; + } + iformat_0_2 = iformat_1_0_to_0_2[imageFormat]; + r = apiEntry_0_2->StartDrawImage(printerContext, + sourceWidth,sourceHeight, + depth,iformat_0_2,rect); + + return r; +} + +static opvp_result_t +EndDrawImageWrapper(opvp_dc_t printerContext) +{ + int r; + + r = apiEntry_0_2->EndDrawImage(printerContext); + + /* make sure rop is pattern copy */ + if (apiEntry_0_2->SetROP != NULL) { + apiEntry_0_2->SetROP(printerContext,OPVP_0_2_ROP_P); + } + + return r; +} + +static opvp_result_t +QueryDeviceCapabilityWrapper( + opvp_dc_t printerContext, + opvp_queryinfoflags_t queryflag, + opvp_int_t *buflen, + opvp_char_t *infoBuf) +{ + return apiEntry_0_2->QueryDeviceCapability(printerContext,queryflag, + *buflen,(char *)infoBuf); +} + +static opvp_result_t +QueryDeviceInfoWrapper( + opvp_dc_t printerContext, + opvp_queryinfoflags_t queryflag, + opvp_int_t *buflen, + opvp_char_t *infoBuf) +{ + if (queryflag & OPVP_QF_MEDIACOPY) { + *ErrorNo = OPVP_NOTSUPPORTED; + return -1; + } + if (queryflag & OPVP_QF_PRINTREGION) { + queryflag &= ~OPVP_QF_PRINTREGION; + queryflag |= 0x0020000; + } + return apiEntry_0_2->QueryDeviceInfo(printerContext,queryflag, + *buflen,(char *)infoBuf); +} + +static opvp_result_t +SetLineDashWrapper(opvp_dc_t printerContext, opvp_int_t num, + const opvp_fix_t *pdash) +{ + return apiEntry_0_2->SetLineDash(printerContext, + /* remove const */ (OPVP_Fix *)pdash,num); +} + +static opvp_result_t +GetLineDashWrapper(opvp_dc_t printerContext, opvp_int_t *pnum, + opvp_fix_t *pdash) +{ + return apiEntry_0_2->GetLineDash(printerContext, + pdash,pnum); +} + +static opvp_dc_t +OpenPrinterWrapper( + opvp_int_t outputFD, + const opvp_char_t *printerModel, + const opvp_int_t apiVersion[2], + opvp_api_procs_t **apiProcs) +{ + opvp_dc_t dc = -1; + + if (OpenPrinter != NULL) { + dc = (*OpenPrinter)(outputFD,printerModel,apiVersion,apiProcs); + } else { + /* try version 0.2 */ + + if (OpenPrinter_0_2 != NULL) { + static opvp_api_procs_t tEntry; + int nApiEntry; + + dc = (*OpenPrinter_0_2)(outputFD, + /* remove const */ + (char *)printerModel, + &nApiEntry,&apiEntry_0_2); + /* setting functions */ + tEntry.opvpClosePrinter + = apiEntry_0_2->ClosePrinter; + tEntry.opvpStartJob + = (opvp_result_t (*)(opvp_int_t, + const opvp_char_t*)) + apiEntry_0_2->StartJob; + tEntry.opvpEndJob = apiEntry_0_2->EndJob; + tEntry.opvpAbortJob = NULL; + tEntry.opvpStartDoc + = (opvp_result_t (*)(opvp_dc_t, + const opvp_char_t*)) + apiEntry_0_2->StartDoc; + tEntry.opvpEndDoc = apiEntry_0_2->EndDoc; + if (apiEntry_0_2->StartPage != NULL) { + tEntry.opvpStartPage = StartPageWrapper; + } else { + tEntry.opvpStartPage = NULL; + } + tEntry.opvpEndPage = apiEntry_0_2->EndPage; + + if (apiEntry_0_2->QueryDeviceCapability != NULL) { + tEntry.opvpQueryDeviceCapability + = QueryDeviceCapabilityWrapper; + } else { + tEntry.opvpQueryDeviceCapability = NULL; + } + + if (apiEntry_0_2->QueryDeviceInfo != NULL) { + tEntry.opvpQueryDeviceInfo = QueryDeviceInfoWrapper; + } else { + tEntry.opvpQueryDeviceInfo = NULL; + } + + tEntry.opvpResetCTM = apiEntry_0_2->ResetCTM; + tEntry.opvpSetCTM = (opvp_result_t (*)(opvp_dc_t, + const opvp_ctm_t*)) + apiEntry_0_2->SetCTM; + tEntry.opvpGetCTM = (opvp_result_t (*)(opvp_dc_t,opvp_ctm_t*)) + apiEntry_0_2->GetCTM; + if (apiEntry_0_2->InitGS != NULL) { + tEntry.opvpInitGS = InitGSWrapper; + } else { + tEntry.opvpInitGS = NULL; + } + tEntry.opvpSaveGS = apiEntry_0_2->SaveGS; + tEntry.opvpRestoreGS = apiEntry_0_2->RestoreGS; + if (apiEntry_0_2->QueryColorSpace != NULL) { + tEntry.opvpQueryColorSpace = QueryColorSpaceWrapper; + } else { + tEntry.opvpQueryColorSpace = NULL; + } + if (apiEntry_0_2->SetColorSpace != NULL) { + tEntry.opvpSetColorSpace = SetColorSpaceWrapper; + } else { + tEntry.opvpSetColorSpace = NULL; + } + if (apiEntry_0_2->GetColorSpace != NULL) { + tEntry.opvpGetColorSpace = GetColorSpaceWrapper; + } else { + tEntry.opvpGetColorSpace = NULL; + } + tEntry.opvpSetFillMode + = (opvp_result_t (*)(opvp_dc_t,opvp_fillmode_t)) + apiEntry_0_2->SetFillMode; + tEntry.opvpGetFillMode + = (opvp_result_t (*)(opvp_dc_t,opvp_fillmode_t*)) + apiEntry_0_2->GetFillMode; + tEntry.opvpSetAlphaConstant = apiEntry_0_2->SetAlphaConstant; + tEntry.opvpGetAlphaConstant = apiEntry_0_2->GetAlphaConstant; + tEntry.opvpSetLineWidth = apiEntry_0_2->SetLineWidth; + tEntry.opvpGetLineWidth = apiEntry_0_2->GetLineWidth; + if (apiEntry_0_2->SetLineDash != NULL) { + tEntry.opvpSetLineDash = SetLineDashWrapper; + } else { + tEntry.opvpSetLineDash = NULL; + } + if (apiEntry_0_2->GetLineDash != NULL) { + tEntry.opvpGetLineDash = GetLineDashWrapper; + } else { + tEntry.opvpGetLineDash = NULL; + } + tEntry.opvpSetLineDashOffset + = apiEntry_0_2->SetLineDashOffset; + tEntry.opvpGetLineDashOffset + = apiEntry_0_2->GetLineDashOffset; + tEntry.opvpSetLineStyle + = (opvp_result_t (*)(opvp_dc_t,opvp_linestyle_t)) + apiEntry_0_2->SetLineStyle; + tEntry.opvpGetLineStyle + = (opvp_result_t (*)(opvp_dc_t,opvp_linestyle_t*)) + apiEntry_0_2->GetLineStyle; + tEntry.opvpSetLineCap + = (opvp_result_t (*)(opvp_dc_t,opvp_linecap_t)) + apiEntry_0_2->SetLineCap; + tEntry.opvpGetLineCap + = (opvp_result_t (*)(opvp_dc_t,opvp_linecap_t*)) + apiEntry_0_2->GetLineCap; + tEntry.opvpSetLineJoin + = (opvp_result_t (*)(opvp_dc_t,opvp_linejoin_t)) + apiEntry_0_2->SetLineJoin; + tEntry.opvpGetLineJoin + = (opvp_result_t (*)(opvp_dc_t,opvp_linejoin_t*)) + apiEntry_0_2->GetLineJoin; + tEntry.opvpSetMiterLimit = apiEntry_0_2->SetMiterLimit; + tEntry.opvpGetMiterLimit = apiEntry_0_2->GetMiterLimit; + tEntry.opvpSetPaintMode + = (opvp_result_t (*)(opvp_dc_t,opvp_paintmode_t)) + apiEntry_0_2->SetPaintMode; + tEntry.opvpGetPaintMode + = (opvp_result_t (*)(opvp_dc_t,opvp_paintmode_t*)) + apiEntry_0_2->GetPaintMode; + if (apiEntry_0_2->SetStrokeColor != NULL) { + tEntry.opvpSetStrokeColor = SetStrokeColorWrapper; + } else { + tEntry.opvpSetStrokeColor = NULL; + } + if (apiEntry_0_2->SetFillColor != NULL) { + tEntry.opvpSetFillColor = SetFillColorWrapper; + } else { + tEntry.opvpSetFillColor = NULL; + } + if (apiEntry_0_2->SetBgColor != NULL) { + tEntry.opvpSetBgColor = SetBgColorWrapper; + } else { + tEntry.opvpSetBgColor = NULL; + } + tEntry.opvpNewPath = apiEntry_0_2->NewPath; + tEntry.opvpEndPath = apiEntry_0_2->EndPath; + tEntry.opvpStrokePath = apiEntry_0_2->StrokePath; + tEntry.opvpFillPath = apiEntry_0_2->FillPath; + tEntry.opvpStrokeFillPath = apiEntry_0_2->StrokeFillPath; + tEntry.opvpSetClipPath + = (opvp_result_t (*)(opvp_dc_t,opvp_cliprule_t)) + apiEntry_0_2->SetClipPath; + tEntry.opvpResetClipPath = apiEntry_0_2->ResetClipPath; + tEntry.opvpSetCurrentPoint = apiEntry_0_2->SetCurrentPoint; + tEntry.opvpLinePath + = (opvp_result_t (*)(opvp_dc_t, + opvp_pathmode_t,opvp_int_t, + const opvp_point_t*)) + apiEntry_0_2->LinePath; + tEntry.opvpPolygonPath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_int_t*, + const opvp_point_t*)) + apiEntry_0_2->PolygonPath; + tEntry.opvpRectanglePath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_rectangle_t*)) + apiEntry_0_2->RectanglePath; + tEntry.opvpRoundRectanglePath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_roundrectangle_t*)) + apiEntry_0_2->RoundRectanglePath; + tEntry.opvpBezierPath + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_point_t*)) + apiEntry_0_2->BezierPath; + tEntry.opvpArcPath + = (opvp_result_t (*)(opvp_dc_t,opvp_arcmode_t, + opvp_arcdir_t,opvp_fix_t,opvp_fix_t,opvp_fix_t, + opvp_fix_t,opvp_fix_t,opvp_fix_t,opvp_fix_t, + opvp_fix_t))apiEntry_0_2->ArcPath; + if (apiEntry_0_2->DrawImage != NULL) { + tEntry.opvpDrawImage = DrawImageWrapper; + } else { + tEntry.opvpDrawImage = NULL; + } + if (apiEntry_0_2->StartDrawImage != NULL) { + tEntry.opvpStartDrawImage = StartDrawImageWrapper; + } else { + tEntry.opvpStartDrawImage = NULL; + } + tEntry.opvpTransferDrawImage = + (opvp_result_t (*)(opvp_dc_t,opvp_int_t,const void*)) + apiEntry_0_2->TransferDrawImage; + if (apiEntry_0_2->EndDrawImage != NULL) { + tEntry.opvpEndDrawImage = EndDrawImageWrapper; + } else { + tEntry.opvpEndDrawImage = NULL; + } + tEntry.opvpStartScanline = apiEntry_0_2->StartScanline; + tEntry.opvpScanline + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_int_t*)) + apiEntry_0_2->Scanline; + tEntry.opvpEndScanline = apiEntry_0_2->EndScanline; + tEntry.opvpStartRaster = apiEntry_0_2->StartRaster; + tEntry.opvpTransferRasterData + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const opvp_byte_t*)) + apiEntry_0_2->TransferRasterData; + tEntry.opvpSkipRaster = apiEntry_0_2->SkipRaster; + tEntry.opvpEndRaster = apiEntry_0_2->EndRaster; + tEntry.opvpStartStream = apiEntry_0_2->StartStream; + tEntry.opvpTransferStreamData + = (opvp_result_t (*)(opvp_dc_t,opvp_int_t, + const void *)) + apiEntry_0_2->TransferStreamData; + tEntry.opvpEndStream = apiEntry_0_2->EndStream; + + *apiProcs = &tEntry; + + GetLastError = GetLastError_0_2; + } + } + return dc; +} + +/* for image */ +static const +gx_image_enum_procs_t opvp_image_enum_procs = +{ + opvp_image_plane_data, + opvp_image_end_image +}; +typedef enum _FastImageSupportMode { + FastImageDisable, + FastImageNoCTM, + FastImageNoRotate, + FastImageRightAngle, + FastImageReverseAngle, + FastImageAll +} FastImageSupportMode; + +static char *fastImage = NULL; +static FastImageSupportMode FastImageMode = FastImageDisable; +static bool begin_image = false; +static bool change_paint_mode = false; +static bool change_cspace = false; +static gs_color_space_index color_index = 0; +static gs_color_space_index base_color_index = 0; +static byte palette[3*256]; +static float imageDecode[GS_IMAGE_MAX_COMPONENTS * 2]; +static bool reverse_image = false; + +/* added for image gamma correction */ +typedef struct bbox_image_enum_s { + gx_image_enum_common; +/* gs_memory_t *memory; */ + gs_matrix matrix; /* map from image space to device dpace */ + const gx_clip_path *pcpath; + gx_image_enum_common_t *target_info; + bool params_are_const; + int x0, x1; + int y, height; +} bbox_image_enum; + +/* The following is already defined in stdpre.h */ +/*#define min(a, b) (((a) < (b))? (a) : (b))*/ + +/* ----- Utilities ----- */ + +/* initialize Graphic State */ +/* No defaults in OPVP 1.0 */ +static int +InitGS(void) +{ + if (apiEntry->opvpInitGS != NULL) { + if (apiEntry->opvpInitGS(printerContext) != OPVP_OK) { + return -1; + } + } + if (apiEntry->opvpSetColorSpace != NULL) { + if (apiEntry->opvpSetColorSpace(printerContext,colorSpace) + != OPVP_OK) { + return -1; + } + } + if (apiEntry->opvpSetPaintMode != NULL) { + if (apiEntry->opvpSetPaintMode(printerContext, + OPVP_PAINTMODE_TRANSPARENT) != OPVP_OK) { + return -1; + } + } + if (apiEntry->opvpSetAlphaConstant != NULL) { + if (apiEntry->opvpSetAlphaConstant(printerContext,1.0) + != OPVP_OK) { + return -1; + } + } + + /* other properties are set by GhostScript */ + return 0; +} + +static int +opvp_startpage(gx_device *dev) +{ + int ecode = 0; + opvp_result_t r = -1; + static char *page_info = NULL; + + /* page info */ + page_info = opvp_alloc_string(&page_info, OPVP_INFO_PREFIX); + page_info = opvp_cat_string(&page_info, opvp_gen_page_info(dev)); + + /* call StartPage */ + if (printerContext != -1) { + if (apiEntry->opvpStartPage) + r = apiEntry->opvpStartPage(printerContext, + (opvp_char_t *)opvp_to_utf8(page_info)); + if (r != OPVP_OK) { + ecode = -1; + } else { + ecode = InitGS(); + } + } + + return ecode; +} + +static int +opvp_endpage(void) +{ + int ecode = 0; + opvp_result_t r = -1; + + /* call EndPage */ + if (printerContext != -1) { + if (apiEntry->opvpEndPage) + r = apiEntry->opvpEndPage(printerContext); + if (r != OPVP_OK) { + ecode = -1; + } + } + + return ecode; +} + +static char * +opvp_alloc_string(char **destin, const char *source) +{ + if (!destin) return NULL; + + if (*destin) { + if (source) { + *destin = realloc(*destin, strlen(source)+1); + } else { + free(*destin); + *destin = NULL; + } + } else { + if (source) { + *destin = malloc(strlen(source)+1); + } + } + if (*destin && source) { + if (*destin != source) { + strcpy(*destin, source); + } + } + + return *destin; +} + +static char * +opvp_cat_string(char **destin, const char *string) +{ + if (!destin) return NULL; + if (!(*destin)) return opvp_alloc_string(destin, string); + + if (string) { + *destin = realloc(*destin, strlen(*destin) +strlen(string)+1); + strcat(*destin, string); + } + + return *destin; +} + +static char * +opvp_adjust_num_string(char *num_string) +{ + char *pp; + char *lp; + + if (!num_string) return NULL; + + if ((pp = strrchr(num_string, '.'))) { + for (lp = &(num_string[strlen(num_string)-1]); lp > pp; lp--) { + if (*lp == '0') { + *lp = '\0'; + } else { + break; + } + } + if (lp == pp) *lp = '\0'; + } + + return num_string; +} + +static char ** +opvp_gen_dynamic_lib_name(void) +{ + static char *buff[5] = {NULL,NULL,NULL,NULL,NULL}; + char tbuff[OPVP_BUFF_SIZE]; + + if (!vectorDriver) { + return NULL; + } + + memset((void*)tbuff, 0, OPVP_BUFF_SIZE); + strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 1); + opvp_alloc_string(&(buff[0]), tbuff); + + memset((void*)tbuff, 0, OPVP_BUFF_SIZE); + strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 4); + strcat(tbuff, ".so"); + opvp_alloc_string(&(buff[1]), tbuff); + + memset((void*)tbuff, 0, OPVP_BUFF_SIZE); + strncpy(tbuff, vectorDriver, OPVP_BUFF_SIZE - 5); + strcat(tbuff, ".dll"); + opvp_alloc_string(&(buff[2]), tbuff); + + memset((void*)tbuff, 0, OPVP_BUFF_SIZE); + strcpy(tbuff, "lib"); + strncat(tbuff, vectorDriver, OPVP_BUFF_SIZE - 7); + strcat(tbuff, ".so"); + opvp_alloc_string(&(buff[3]), tbuff); + + buff[4] = NULL; + + return buff; +} + +static char * +opvp_to_utf8(char *string) +{ + char *locale; + iconv_t cd; + char *buff = NULL; + size_t ib, ob; + int complete = false; + char *ibuff, *obuff; + char *ostring = NULL; + + if (string) { + ib = strlen(string); + if (ib > 0) { + ob = ib * 4; + buff = malloc(ob+1); + setlocale(LC_CTYPE, ""); +#ifdef CODESET + locale = nl_langinfo(CODESET); +#else + locale = "UTF-8"; +#endif /* CODESET */ + if (locale) { + if (strcmp(locale, "C") && buff) { + if ((cd = iconv_open("UTF-8", locale)) != (iconv_t)-1) { + ibuff = string; + obuff = buff; + if (iconv(cd, &ibuff, &ib, &obuff, &ob) != -1) { + *obuff = 0; + complete = true; + } + iconv_close(cd); + } + } + } + } + } + + if (complete) { + ostring = opvp_alloc_string(&ostring, buff); + } else { + ostring = string; + } + + if (buff) free(buff); + return ostring; +} + +static float +opvp_fabsf(float f) +{ + return (float)fabs((double)f); +} + +static int +opvp_get_papertable_index(gx_device *pdev) +{ + int i; + float width, height; + bool landscape; + float paper_w, paper_h; + float prev = -1; + int paper = -1; + int candidate = -1; + int smaller = -1; + int larger = -1; + int s_candi = -1; + int l_candi = -1; + float h_delta = TOLERANCE; + float sw_delta = TOLERANCE; + float sh_delta = TOLERANCE; + float lw_delta = TOLERANCE; + float lh_delta = TOLERANCE; + bool match = false; + float f; + + /* portrait or landscape */ + landscape = (pdev->MediaSize[0] < pdev->MediaSize[1] ? false : true); + + /* paper size */ + width = (landscape ? pdev->MediaSize[1] : pdev->MediaSize[0]); + height = (landscape ? pdev->MediaSize[0] : pdev->MediaSize[1]); + + for (i=0; paperTable[i].name != NULL; i++) { + paper_w = paperTable[i].width; + paper_h = paperTable[i].height; + if (width == paper_w) { + if (height == paper_h) { + paper = i; + match = true; + break; + } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) { + if (f < h_delta) { + h_delta = f; + candidate = i; + } + } + } else if (candidate != -1) { + paper = candidate; + match = true; + break; + } else if (prev != paper_w) { + prev = paper_w; + if (paper_w < width) { + if ((f = opvp_fabsf(width - paper_w)) < TOLERANCE) { + if (f < sw_delta) { + sw_delta = f; + smaller = i; + } + } + } else { + if ((f = opvp_fabsf(width - paper_w)) < TOLERANCE) { + if (f < lw_delta) { + lw_delta = f; + larger = i; + } + } + } + } + } + if (!match) { + paper = i; + if (smaller != -1) { + paper_w = paperTable[smaller].width; + for (i = smaller; paperTable[i].width == paper_w; i++) { + paper_h = paperTable[i].height; + if (height == paper_h) { + sh_delta = 0; + s_candi = i; + break; + } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) { + if (f < sh_delta) { + sh_delta = f; + s_candi = i; + } + } + } + } + if (larger != -1) { + paper_w = paperTable[larger].width; + for (i = larger; paperTable[i].width == paper_w; i++) { + paper_h = paperTable[i].height; + if (height == paper_h) { + lh_delta = 0; + l_candi = i; + break; + } else if ((f = opvp_fabsf(height - paper_h)) < TOLERANCE) { + if (f < lh_delta) { + lh_delta = f; + l_candi = i; + } + } + } + } + if (s_candi != -1) { + if (l_candi != -1) { + if ((sw_delta + sh_delta) + < (lw_delta + lh_delta)) { + paper = s_candi; + } else { + paper = l_candi; + } + } else { + paper = s_candi; + } + } else { + if (l_candi != -1) { + paper = l_candi; + } + } + } + + return paper; +} + +static char * +opvp_get_sizestring(float width, float height) +{ + char nbuff[OPVP_BUFF_SIZE]; + char nbuff1[OPVP_BUFF_SIZE / 2]; + char nbuff2[OPVP_BUFF_SIZE / 2]; + static char *buff = NULL; + + memset((void*)nbuff, 0, OPVP_BUFF_SIZE); + memset((void*)nbuff1, 0, OPVP_BUFF_SIZE / 2); + memset((void*)nbuff2, 0, OPVP_BUFF_SIZE / 2); + + snprintf(nbuff1, OPVP_BUFF_SIZE / 2 - 1, "%.3f", width); + snprintf(nbuff2, OPVP_BUFF_SIZE / 2 - 1, "%.3f", height); + snprintf(nbuff, OPVP_BUFF_SIZE - 1, "%sx%s", + opvp_adjust_num_string(nbuff1), + opvp_adjust_num_string(nbuff2)); + + return opvp_alloc_string(&buff, nbuff); +} + +static char * +opvp_get_mediasize(gx_device *pdev) +{ + int i; + char wbuff[OPVP_BUFF_SIZE]; + static char *buff = NULL; + const char *region; + const char *name; + float width; + float height; + const char *unit; + bool landscape; + + i = opvp_get_papertable_index(pdev); + + if (paperTable[i].name) { + region = paperTable[i].region; + name = paperTable[i].name; + width = paperTable[i].width / PS_DPI; + height = paperTable[i].height / PS_DPI; + if((strcmp(region, "na" ) == 0) || + (strcmp(region, "asme") == 0) || + (strcmp(region, "roc" ) == 0) || + (strcmp(region, "oe" ) == 0)) { + unit = "in"; + } else { + width *= MMPI; + height *= MMPI; + unit = "mm"; + } + } else { + landscape = (pdev->MediaSize[0] < pdev->MediaSize[1] ? + false : true); + region = "custom"; + name = "opvp"; + width = (landscape ? pdev->MediaSize[1] : pdev->MediaSize[0]) + / PS_DPI; + height = (landscape ? pdev->MediaSize[0] : pdev->MediaSize[1]) + / PS_DPI; + unit = "in"; + } + memset((void*)wbuff, 0, OPVP_BUFF_SIZE); + snprintf(wbuff, OPVP_BUFF_SIZE - 1, "%s_%s_%s%s", region, name, + opvp_get_sizestring(width, height), + unit); + buff = opvp_alloc_string(&buff, wbuff); + + return buff; +} + +static char * +opvp_gen_page_info(gx_device *dev) +{ + static char *buff = NULL; + int num_copies = 1; + bool landscape; + char tbuff[OPVP_BUFF_SIZE]; + + /* copies */ + if (!inkjet) { + if (dev->IgnoreNumCopies) { + num_copies = 1; + } else if (dev->NumCopies_set > 0) { + num_copies = dev->NumCopies; + } + } + + landscape = (dev->MediaSize[0] < dev->MediaSize[1] ? false + : true); + memset((void*)tbuff, 0, OPVP_BUFF_SIZE); + snprintf(tbuff, OPVP_BUFF_SIZE - 1, + "MediaCopy=%d;DeviceResolution=deviceResolution_%s;" + "MediaPageRotation=%s;MediaSize=%s", + num_copies, + opvp_get_sizestring(dev->x_pixels_per_inch, dev->y_pixels_per_inch), + (landscape ? "landscape" : "portrait"), + opvp_get_mediasize(dev)); + + opvp_alloc_string(&buff, tbuff); + + return buff; +} + +static char * +opvp_gen_doc_info(gx_device *dev) +{ + return opvp_gen_page_info(dev); +} + +static char * +opvp_gen_job_info(gx_device *dev) +{ + return opvp_gen_doc_info(dev); +} + +static int +opvp_set_brush_color(gx_device_opvp *pdev, gx_color_index color, + opvp_brush_t *brush) +{ + int code; + int ecode = 0; + gx_color_value rgb[3]; + + code = opvp_map_color_rgb((gx_device *)pdev, color, rgb); + if (code) { + ecode = -1; + } else { +#if ENABLE_SIMPLE_MODE + brush->colorSpace = colorSpace; +#else + opvp_result_t r = -1; + /* call GetColorSpace */ + if (apiEntry->opvpGetColorSpace) { + r = apiEntry->opvpGetColorSpace(printerContext, + &(brush->colorSpace)); + } + if (r != OPVP_OK) { + brush->colorSpace = OPVP_CSPACE_DEVICEKRGB; + } +#endif + brush->pbrush = NULL; + brush->xorg = brush->yorg = 0; + brush->color[3] = (color == gx_no_color_index ? -1 : 0); + brush->color[2] = rgb[0]; + brush->color[1] = rgb[1]; + brush->color[0] = rgb[2]; + } + + return ecode; +} + +static int +opvp_draw_image( + gx_device_opvp *pdev, + int depth, + int sw, + int sh, + int dw, + int dh, + int raster, + int mask, + const byte *data) +{ + opvp_result_t r = -1; + int ecode = 0; + int count; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* image size */ + count = raster * sh; + + /* call DrawImage */ + if (apiEntry->opvpDrawImage) { + r = apiEntry->opvpDrawImage(printerContext, + sw,sh, + raster, + mask ? OPVP_IFORMAT_MASK : OPVP_IFORMAT_RAW, + dw,dh, + /* discard 'const' qualifier */ + (void *)data); + } + if (r != OPVP_OK) { + /* call StartDrawImage */ + if (apiEntry->opvpStartDrawImage) { + r = apiEntry->opvpStartDrawImage(printerContext, + sw,sh, + raster, + mask ? OPVP_IFORMAT_MASK : OPVP_IFORMAT_RAW, + dw,dh); + } + if (r == OPVP_OK) { + /* call TansferDrawImage */ + if (apiEntry->opvpTransferDrawImage) { + r = apiEntry->opvpTransferDrawImage( + printerContext, + count, + /* discard 'const' qualifier */ + (void *)data); + } + if (r != OPVP_OK) ecode = -1; + + /* call EndDrawImage */ + if (apiEntry->opvpEndDrawImage) { + apiEntry->opvpEndDrawImage(printerContext); + } + } else { + ecode = 0; /* continue... */ + } + } + + return ecode; +} + +/* ----- load/unload vector driver ----- */ + +/* + * load vector-driver + */ +static int +opvp_load_vector_driver(void) +{ + char **list = NULL; + int i; + void *h; + + if (handle) { + opvp_unload_vector_driver(); + } + + if (vectorDriver) { + list = opvp_gen_dynamic_lib_name(); + } + + if (list) { + i = 0; + while (list[i]) { + if ((h = dlopen(list[i],RTLD_NOW))) { + OpenPrinter = dlsym(h,"opvpOpenPrinter"); + ErrorNo = dlsym(h,"opvpErrorNo"); + if (OpenPrinter && ErrorNo) { + handle = h; + break; + } + OpenPrinter = NULL; + ErrorNo = NULL; + /* try version 0.2 driver */ + OpenPrinter_0_2 = dlsym(h,"OpenPrinter"); + ErrorNo = dlsym(h,"errorno"); + if (OpenPrinter_0_2 && ErrorNo) { + handle = h; + break; + } + OpenPrinter_0_2 = NULL; + ErrorNo = NULL; + } + i++; + } + } + + if (handle) { + return 0; + } else { + return -1; + } +} + +/* + * unload vector-driver + */ +static int +opvp_unload_vector_driver(void) +{ + if (handle) { + dlclose(handle); + handle = NULL; + OpenPrinter = NULL; + ErrorNo = NULL; + } + return 0; +} + +/* + * prepare open + */ +static int +prepare_open(gx_device *dev) +{ + int ecode = 0; + int code; + opvp_result_t r = -1; + opvp_api_procs_t *api_entry; + int dumFD = -1; + opvp_dc_t dumContext = -1; + opvp_cspace_t cspace = OPVP_CSPACE_STANDARDRGB; + + /* open dummy device */ + code = open("/dev/null", O_RDWR); + if (code < 0) ecode = code; + else dumFD = code; + + /* load vector driver */ + if (!ecode) { + if ((code = opvp_load_vector_driver())) { + ecode = code; + } + } + + /* prepare array of function pointer for PDAPI */ + if (!ecode) { + if (!apiEntry) { + if (!(apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) { + ecode = -1; + } + } else { + memset(apiEntry, 0, sizeof(opvp_api_procs_t)); + } + } + + /* call opvpOpenPrinter as dummy */ + if (!ecode) { + opvp_dc_t dc; + opvp_int_t apiVersion[2]; + + /* require version 1.0 */ + apiVersion[0] = 1; + apiVersion[1] = 0; + dc = OpenPrinterWrapper(dumFD, (opvp_char_t *)printerModel, + apiVersion,&api_entry); + if (dc == -1) { + ecode = -1; + } else { + dumContext = dc; + } + } + + /* set apiEntry */ + if (!ecode) { + nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *); + memcpy(apiEntry, api_entry, nApiEntry*sizeof(void *)); + } else { + if (apiEntry) free(apiEntry); + apiEntry = NULL; + } + + /* check vector fucntion */ + if (apiEntry) { + if (!inkjet) { + if (!(apiEntry->opvpNewPath) || + !(apiEntry->opvpEndPath) || + !(apiEntry->opvpStrokePath) || + !(apiEntry->opvpSetCurrentPoint) || + !(apiEntry->opvpLinePath) || + !(apiEntry->opvpBezierPath)) { + /* NOT avail vector drawing mode */ + vector = false; + } + } + /* call GetColorSpace */ + if (apiEntry->opvpGetColorSpace) { + r = apiEntry->opvpGetColorSpace(dumContext, &cspace); + } + if (cspace == OPVP_CSPACE_BW) { + /* mono-color */ + colorSpace = cspace; + dev->color_info.num_components = 1; + dev->color_info.depth = 1; + dev->color_info.max_gray = 0; + dev->color_info.max_color = 0; + dev->color_info.dither_grays = 1; + dev->color_info.dither_colors = 1; + } else if (cspace == OPVP_CSPACE_DEVICEGRAY) { + /* gray-scale */ + colorSpace = cspace; + dev->color_info.num_components = 1; + dev->color_info.depth = 8; + dev->color_info.max_gray = 255; + dev->color_info.max_color = 255; + dev->color_info.dither_grays = 256; + dev->color_info.dither_colors = 256; + } else { + /* rgb color */ + colorSpace = OPVP_CSPACE_STANDARDRGB; + dev->color_info.num_components = 3; + dev->color_info.depth = 24; + dev->color_info.max_gray = 255; + dev->color_info.max_color = 255; + dev->color_info.dither_grays = 256; + dev->color_info.dither_colors = 256; + } +#if GS_VERSION_MAJOR >= 8 + dev->procs.get_color_mapping_procs = NULL; + dev->procs.get_color_comp_index = NULL; + gx_device_fill_in_procs(dev); +#endif + } + + /* call Closerinter as dummy */ + if (dumContext != -1) { + /* call ClosePrinter */ + if (apiEntry->opvpClosePrinter) { + apiEntry->opvpClosePrinter(dumContext); + } + dumContext = -1; + } + + /* close device for dummy */ + if (dumFD != -1) { + close(dumFD); + dumFD = -1; + } + + /* un-load vector driver */ + opvp_unload_vector_driver(); + + return ecode; +} + +/* ----- driver procs ----- */ +/* + * open device + */ +static int +opvp_open(gx_device *dev) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + gx_device_oprp *rdev = (gx_device_oprp *)dev; + int ecode = 0; + int code; + opvp_result_t r = -1; + opvp_dc_t dc; + opvp_api_procs_t *api_entry; + char *job_info = NULL; + char *doc_info = NULL; + char *tmp_info = NULL; + float margin_width = 0; + float margin_height = 0; + float adj_margins[4]; + opvp_int_t apiVersion[2]; + + /* prepare open : load and open as dummy */ + code = prepare_open(dev); + if (code) { + ecode = code; + return ecode; + } + + /* set margins */ + if (zoomAuto) { + margin_width = (margins[0] + margins[2]) + * dev->HWResolution[0]; + margin_height = (margins[1] + margins[3]) + * dev->HWResolution[1]; + zoom[0] = (dev->width - margin_width) / dev->width; + zoom[1] = (dev->height - margin_height) / dev->height; + if (zoom[0] < zoom[1]) { + zoom[1] = zoom[0]; + } else { + zoom[0] = zoom[1]; + } + } + if (inkjet) { + if ((margins[0] != 0) || + (margins[1] != 0) || (margins[3] != 0)) { + shift[0] = margins[0] * dev->HWResolution[0]; + shift[1] = (margins[1] + margins[3]) + * dev->HWResolution[1]; + zooming = true; + } + dev->width -= margins[2] * dev->HWResolution[0]; + dev->height -= margins[1] * dev->HWResolution[1]; + } else { + if ((margins[0] != 0) || (margins[1] != 0)) { + shift[0] = margins[0] * dev->HWResolution[0]; + shift[1] = margins[3] * dev->HWResolution[1]; + zooming = true; + } + adj_margins[0] = 0; + adj_margins[3] = 0; + adj_margins[1] = dev->height * zoom[1] / dev->HWResolution[1] + - (dev->MediaSize[1] / PS_DPI + - (margins[1] + margins[3])); + if (adj_margins[1] < 0) adj_margins[0] = 0; + adj_margins[2] = dev->width * zoom[0] / dev->HWResolution[0] + - (dev->MediaSize[0] / PS_DPI + - (margins[0] + margins[2])); + if (adj_margins[2] < 0) adj_margins[2] = 0; + gx_device_set_margins(dev, adj_margins, true); + } + if ((zoom[0] != 1) || (zoom[1] != 1)) zooming = true; + + /* open file for output device */ + if (!inkjet) { + pdev->v_memory = gs_memory_stable(pdev->memory); + /* open output stream */ + code = gdev_vector_open_file_options((gx_device_vector*)dev, + 512, + (VECTOR_OPEN_FILE_SEQUENTIAL + |VECTOR_OPEN_FILE_BBOX + )); + if (code < 0) { + ecode = code; + return ecode; + } + while (dev->child) { + dev = dev->child; + } + rdev = (gx_device_oprp *)(dev); + pdev = (gx_device_opvp *)(dev); +#if GS_VERSION_MAJOR >= 8 + if (pdev->bbox_device != NULL) { + if (pdev->bbox_device->memory == NULL) { + pdev->bbox_device->memory = gs_memory_stable(dev->memory); + } + } +#endif + outputFD = fileno(pdev->file); + } else { + /* open printer device */ + code = gdev_prn_open(dev); + if (code < 0) { + ecode = ecode; + return ecode; + } + while (dev->child) { + dev = dev->child; + } + rdev = (gx_device_oprp *)(dev); + pdev = (gx_device_opvp *)(dev); + /* open output stream */ + code = gdev_prn_open_printer_seekable(dev, true, false); + if (code < 0) { + ecode = code; + return ecode; + } + outputFD = fileno(rdev->file); + } + + /* RE-load vector driver */ + if ((code = opvp_load_vector_driver())) { + ecode = code; + return ecode; + } + + /* call opvpOpenPrinter */ + /* require version 1.0 */ + apiVersion[0] = 1; + apiVersion[1] = 0; + dc = OpenPrinterWrapper(outputFD,(opvp_char_t *)printerModel, + apiVersion,&api_entry); + if (!apiEntry) { + if (!(apiEntry = calloc(sizeof(opvp_api_procs_t), 1))) { + ecode = -1; + } + } else { + memset(apiEntry, 0, sizeof(opvp_api_procs_t)); + } + if (dc == -1) { + ecode = -1; + if (apiEntry) free(apiEntry); + apiEntry = NULL; + opvp_unload_vector_driver(); + if (inkjet) gdev_prn_close(dev); + else gdev_vector_close_file((gx_device_vector *)pdev); + return ecode; + } + printerContext = dc; + nApiEntry = sizeof(opvp_api_procs_t)/sizeof(void *); + memcpy(apiEntry, api_entry, nApiEntry*sizeof(void *)); + + /* initialize */ + if ((!ecode) && (!inkjet)) { + pdev->vec_procs = &opvp_vector_procs; + if (vector) gdev_vector_init((gx_device_vector *)pdev); + } + + if (apiEntry->opvpQueryColorSpace) { + int n = sizeof(cspace_available); + int nn = n; + opvp_cspace_t *p = malloc(n*sizeof(opvp_cspace_t)); + + if ((r = apiEntry->opvpQueryColorSpace(printerContext,&nn,p)) + == OPVP_PARAMERROR && nn > n) { + /* realloc buffer and retry */ + p = realloc(p,nn*sizeof(opvp_cspace_t)); + r = apiEntry->opvpQueryColorSpace(printerContext,&nn,p); + } + if (r == OPVP_OK) { + int i; + + for (i = 0;i < nn;i++) { + if (p[i] < sizeof(cspace_available)) { + cspace_available[p[i]] = 1; + } + } + } + free(p); + } + /* start job */ + if (!ecode) { + /* job info */ + if (jobInfo) { + if (strlen(jobInfo) > 0) { + job_info = opvp_alloc_string(&job_info,jobInfo); + } + } + tmp_info = opvp_alloc_string(&tmp_info,opvp_gen_job_info(dev)); + if (tmp_info) { + if (strlen(tmp_info) > 0) { + if (job_info) { + if (strlen(job_info) > 0) { + opvp_cat_string(&job_info, ";"); + } + } + job_info = opvp_cat_string(&job_info,OPVP_INFO_PREFIX); + job_info = opvp_cat_string(&job_info,tmp_info); + } + } + + /* call StartJob */ + if (apiEntry->opvpStartJob) { + r = apiEntry->opvpStartJob(printerContext, + (opvp_char_t *)opvp_to_utf8(job_info)); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + /* start doc */ + if (!ecode) { + /* doc info */ + if (docInfo) { + if (strlen(docInfo) > 0) { + doc_info = opvp_alloc_string(&doc_info,docInfo); + } + } + tmp_info = opvp_alloc_string(&tmp_info, opvp_gen_doc_info(dev)); + if (tmp_info) { + if (strlen(tmp_info) > 0) { + if (doc_info) { + if (strlen(doc_info) > 0) { + opvp_cat_string(&doc_info, ";"); + } + } + doc_info = opvp_cat_string(&doc_info,OPVP_INFO_PREFIX); + doc_info = opvp_cat_string(&doc_info,tmp_info); + } + } + + /* call StartDoc */ + if (apiEntry->opvpStartDoc) { + r = apiEntry->opvpStartDoc(printerContext, + (opvp_char_t *)opvp_to_utf8(doc_info)); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + if (tmp_info) opvp_alloc_string(&tmp_info, NULL); + if (doc_info) opvp_alloc_string(&doc_info, NULL); + if (job_info) opvp_alloc_string(&job_info, NULL); + + return ecode; +} + +/* + * open device for inkjet + */ +static int +oprp_open(gx_device *dev) +{ + /* set inkjet mode */ + vector = false; + inkjet = true; + + /* matrix */ + dev->procs.get_initial_matrix = opvp_get_initial_matrix; + return opvp_open(dev); +} + +/* + * get initial matrix + */ +static void +opvp_get_initial_matrix(gx_device *dev, gs_matrix *pmat) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + opvp_ctm_t omat; + + gx_default_get_initial_matrix(dev,pmat); + if (zooming) { + /* gs matrix */ + pmat->xx *= zoom[0]; + pmat->xy *= zoom[1]; + pmat->yx *= zoom[0]; + pmat->yy *= zoom[1]; + pmat->tx = pmat->tx * zoom[0] + shift[0]; + pmat->ty = pmat->ty * zoom[1] + shift[1]; + } + + if (pdev->is_open) { + /* call ResetCTM */ + if (apiEntry->opvpResetCTM) { + apiEntry->opvpResetCTM(printerContext); + } else { + /* call SetCTM */ + omat.a = 1; + omat.b = 0; + omat.c = 0; + omat.d = 1; + omat.e = 0; + omat.f = 0; + if (apiEntry->opvpSetCTM) { + apiEntry->opvpSetCTM(printerContext, &omat); + } + } + } + + return; +} + +/* + * output page + */ +static int +opvp_output_page(gx_device *dev, int num_copies, int flush) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + int ecode = 0; + int code = -1; + + if (inkjet) return gdev_prn_output_page(dev, num_copies, flush); + +#ifdef OPVP_IGNORE_BLANK_PAGE + if (pdev->in_page) { +#else + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; +#endif + /* end page */ + code = opvp_endpage(); + if (code) ecode = code; + + pdev->in_page = false; + beginPage = false; +#ifdef OPVP_IGNORE_BLANK_PAGE + } +#endif + + if (vector) { + gdev_vector_reset((gx_device_vector *)pdev); + } + + code = gx_finish_output_page(dev, num_copies, flush); + if (code) ecode = code; + + return ecode; +} + +/* + * print page + */ +static int +oprp_print_page(gx_device_printer *pdev, FILE *prn_stream) +{ + int ecode = 0; + int code = -1; + opvp_result_t r = -1; + int raster_size; + int buff_size; + byte *buff = NULL; + int line; + int scan_lines; + byte *data; + int rasterWidth; + bool start_page = false; + bool start_raster = false; +#if ENABLE_SKIP_RASTER + int i; + byte check; +#endif + + /* get raster/pixel size */ + raster_size = gx_device_raster((gx_device *)pdev, 0); + buff_size = ((raster_size + 3) >> 2) << 2; + scan_lines = dev_print_scan_lines(pdev); + rasterWidth = pdev->width; + + /* allocate buffer */ + buff = (byte*)calloc(1, buff_size); + if (!buff) return ecode = -1; + + /* start page */ + if (!ecode) { + code = opvp_startpage((gx_device *)pdev); + if (code) ecode = code; + else start_page = true; + } + + /* moveto origin */ + if (!ecode) + opvp_moveto((gx_device_vector*)pdev, 0, 0, 0, 0, 0); + + /* call StartRaster */ + if (!ecode) { + if (apiEntry->opvpStartRaster) { + r = apiEntry->opvpStartRaster(printerContext,rasterWidth); + } + if (r != OPVP_OK) { + ecode = r; + } else { + start_raster = true; + } + } + + /* line */ + for (line = 0; (line < scan_lines) && (!ecode); line++) { + /* get raster data */ + if (!ecode) { + code = gdev_prn_get_bits(pdev, line, buff, &data); + if (code) { + ecode = code; + break; + } + } +#if ENABLE_SKIP_RASTER + /* check support SkipRaster */ + if (apiEntry->opvpSkipRaster) { + /* check all white */ + if (pdev->color_info.depth > 8) { + for (check = 0xff, i = 0; i < raster_size; i++) + { + check &= data[i]; + if (check != 0xff) break; + } + /* if all white call SkipRaster */ + if (check == 0xff) { + r = apiEntry->opvpSkipRaster(printerContext, 1); + if (r == OPVP_OK) continue; + } + } else { + for (check = 0, i = 0; i < raster_size; i++) { + check |= data[i]; + if (check) break; + } + /* if all zero call SkipRaster */ + if (check) { + r = apiEntry->opvpSkipRaster(printerContext, 1); + if (r == OPVP_OK) continue; + } + } + } +#endif + /* call TransferRasterData */ + if (!ecode) { + if (apiEntry->opvpTransferRasterData) { + r = apiEntry->opvpTransferRasterData(printerContext, + raster_size, + data); + } + if (r != OPVP_OK) ecode = r; + } + } + + /* call EndRaster */ + if (start_raster) { + if (apiEntry->opvpEndRaster) { + r = apiEntry->opvpEndRaster(printerContext); + } + if (r != OPVP_OK) ecode = r; + start_raster = false; + } + + /* end page */ + if (start_page) { + code = opvp_endpage(); + if (code) ecode = code; + start_page = false; + } + + /* free buffer */ + if (buff) { + free(buff); + buff = NULL; + } + + return ecode; +} + +/* + * close device + */ +static int +opvp_close(gx_device *dev) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + int ecode = 0; + + /* finalize */ + if (printerContext != -1) { + /* call EndDoc */ + if (apiEntry->opvpEndDoc) { + apiEntry->opvpEndDoc(printerContext); + } + + /* call EndJob */ + if (apiEntry->opvpEndJob) { + apiEntry->opvpEndJob(printerContext); + } + + /* call ClosePrinter */ + if (apiEntry->opvpClosePrinter) { + apiEntry->opvpClosePrinter(printerContext); + } + printerContext = -1; + } + + /* unload vector driver */ + if (apiEntry) free(apiEntry); + apiEntry = NULL; + opvp_unload_vector_driver(); + + if (inkjet) { + /* close printer */ + gdev_prn_close(dev); + } else { + /* close output stream */ + gdev_vector_close_file((gx_device_vector *)pdev); + } + outputFD = -1; + + return ecode; +} + +/* + * map rgb color + */ +#if GS_VERSION_MAJOR >= 8 +static gx_color_index +opvp_map_rgb_color(gx_device *dev, + const gx_color_value *prgb /* modified for gs 8.15 */) +#else +static gx_color_index +opvp_map_rgb_color(gx_device *dev, + gx_color_value r, + gx_color_value g, + gx_color_value b) +#endif +{ + opvp_cspace_t cs; + uint c, m, y, k; + +#if !(ENABLE_SIMPLE_MODE) + gx_device_opvp *pdev; + opvp_result_t r; +#endif + +#if GS_VERSION_MAJOR >= 8 + gx_color_value r, g, b; /* added for gs 8.15 */ + r = prgb[0]; + g = prgb[1]; + b = prgb[2]; +#endif + +#if !(ENABLE_SIMPLE_MODE) + pdev = (gx_device_opvp *)dev; + r = -1; +#endif + cs = OPVP_CSPACE_STANDARDRGB; + +#if ENABLE_SIMPLE_MODE + cs = colorSpace; +#else + if (pdev->is_open) { + /* call GetColorSpace */ + if (apiEntry->opvpGetColorSpace) { + r = apiEntry->opvpGetColorSpace(printerContext, &cs); + } + if (r != OPVP_OK) { + if (pdev->color_info.depth > 32) { + cs = OPVP_CSPACE_STANDARDRGB64; + } else if (pdev->color_info.depth > 8 ) { + cs = OPVP_CSPACE_STANDARDRGB; + } else if (pdev->color_info.depth > 1 ) { + cs = OPVP_CSPACE_DEVICEGRAY; + } else { + cs = OPVP_CSPACE_BW; + } + } + } +#endif + + switch (cs) { + case OPVP_CSPACE_STANDARDRGB64: + /* unsupported */ + if (sizeof(gx_color_index) >= 6) { + return (long long)b + + ((long long)g << 16) + + ((long long)b << 32); + } else { + return gx_color_value_to_byte(b) + + ((uint)gx_color_value_to_byte(g) << 8) + + ((ulong)gx_color_value_to_byte(r) << 16); + } + break; + case OPVP_CSPACE_DEVICECMYK: + case OPVP_CSPACE_DEVICECMY: + /* unsupported */ + c = gx_color_value_to_byte(~r); + m = gx_color_value_to_byte(~g); + y = gx_color_value_to_byte(~b); + if (cs == OPVP_CSPACE_DEVICECMYK) { + k = (c= 8 + { + gx_color_value rgb[3]; + rgb[0] = rgb[1] = rgb[2] = r; + return gx_default_gray_map_rgb_color(dev, rgb); + } +#else + return gx_default_gray_map_rgb_color(dev, r, g, b); +#endif + break; + case OPVP_CSPACE_BW : +#if GS_VERSION_MAJOR >= 8 + return gx_default_b_w_map_rgb_color(dev, prgb); +#else + return gx_default_b_w_map_rgb_color(dev, r, g, b); +#endif + break; + case OPVP_CSPACE_STANDARDRGB: + case OPVP_CSPACE_DEVICEKRGB: + default: +#if GS_VERSION_MAJOR >= 8 + return gx_default_rgb_map_rgb_color(dev, prgb); +#else + return gx_default_rgb_map_rgb_color(dev, r, g, b); +#endif + break; + } +} + +/* + * map color rgb + */ +static int +opvp_map_color_rgb(gx_device *dev, gx_color_index color, + gx_color_value prgb[3]) +{ +#if !(ENABLE_SIMPLE_MODE) + gx_device_opvp *pdev = (gx_device_opvp *)dev; + opvp_result_t r = -1; +#endif + opvp_cspace_t cs = OPVP_CSPACE_STANDARDRGB; + uint c, m, y, k; + +#if ENABLE_SIMPLE_MODE + cs = colorSpace; +#else + /* call GetColorSpace */ + if (pdev->is_open) { + if (apiEntry->opvpGetColorSpace) { + r = apiEntry->opvpGetColorSpace(printerContext, &cs); + } + if (r != OPVP_OK) { + if (pdev->color_info.depth > 32) { + cs = OPVP_CSPACE_STANDARDRGB64; + } else if (pdev->color_info.depth > 8 ) { + cs = OPVP_CSPACE_STANDARDRGB; + } else if (pdev->color_info.depth > 1 ) { + cs = OPVP_CSPACE_DEVICEGRAY; + } else { + cs = OPVP_CSPACE_BW; + } + } + } +#endif + + switch (cs) { + case OPVP_CSPACE_STANDARDRGB64: + /* unsupported */ + if (sizeof(gx_color_index) >= 6) { + prgb[0] = ((long long)color >> 32) & 0xffff; + prgb[1] = ((long long)color >> 16) & 0xffff; + prgb[2] = color & 0xffff; + } else { + prgb[0] = gx_color_value_from_byte((color >> 16) & 0xff); + prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff); + prgb[2] = gx_color_value_from_byte(color & 0xff); + } + break; + case OPVP_CSPACE_DEVICECMYK: + case OPVP_CSPACE_DEVICECMY: + /* unsupported */ + c = gx_color_value_from_byte((color >> 24) & 0xff); + m = gx_color_value_from_byte((color >> 16) & 0xff); + y = gx_color_value_from_byte((color >> 8) & 0xff); + if (cs == OPVP_CSPACE_DEVICECMYK) { + k = gx_color_value_from_byte(color & 0xff); + c += k; if (c > 255) c = 255; + m += k; if (m > 255) m = 255; + y += k; if (y > 255) y = 255; + } + prgb[0] = gx_color_value_from_byte(~c & 0xff); + prgb[1] = gx_color_value_from_byte(~m & 0xff); + prgb[2] = gx_color_value_from_byte(~y & 0xff); + break; + case OPVP_CSPACE_DEVICEGRAY: + return gx_default_gray_map_color_rgb(dev, color, prgb); + break; + case OPVP_CSPACE_BW: + return gx_default_b_w_map_color_rgb(dev, color, prgb); + break; + case OPVP_CSPACE_STANDARDRGB: + case OPVP_CSPACE_DEVICEKRGB: + default: + return gx_default_rgb_map_color_rgb(dev, color, prgb); + break; + } + + return 0; +} + +/* + * fill rectangle + */ +static int +opvp_fill_rectangle( + gx_device *dev, + int x, + int y, + int w, + int h, + gx_color_index color) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + byte data[8] = {0xC0, 0, 0, 0, 0xC0, 0, 0, 0}; + int code = -1; + int ecode = 0; + opvp_brush_t brush; + opvp_point_t point; + + if (vector) { + return gdev_vector_fill_rectangle( dev, x, y, w, h, color); + } + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + +#if !(ENABLE_SIMPLE_MODE) + /* call SaveGS */ + if (apiEntry->opvpSaveGS) { + apiEntry->opvpSaveGS(printerContext); + } +#endif + + /* one-color */ + opvp_set_brush_color(pdev, color, &brush); + + /* call SetFillColor */ + if (apiEntry->opvpSetFillColor) { + apiEntry->opvpSetFillColor(printerContext, &brush); + } + + /* call SetCurrentPoint */ + OPVP_I2FIX(x, point.x); + OPVP_I2FIX(y, point.y); + if (apiEntry->opvpSetCurrentPoint) { + apiEntry->opvpSetCurrentPoint(printerContext,point.x, point.y); + } + + /* draw image */ + code = opvp_draw_image(pdev, + 1, + 2, 2, + w, h, + 4, + 0, + data); + if (code) { + ecode = code; + } + + /* restore fill color */ + if (vectorFillColor) { + /* call SetFillColor */ + if (apiEntry->opvpSetFillColor) { + apiEntry->opvpSetFillColor(printerContext,vectorFillColor); + } + } + +#if !(ENABLE_SIMPLE_MODE) + /* call RestoreGS */ + if (apiEntry->opvpRestoreGS) { + apiEntry->opvpRestoreGS(printerContext); + } +#endif + + return ecode; +} + +/* + * copy mono + */ +static int +opvp_copy_mono( + gx_device *dev, + const byte *data, + int data_x, + int raster, + gx_bitmap_id id, + int x, + int y, + int w, + int h, + gx_color_index zero, + gx_color_index one) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + int code = -1; + int ecode = 0; + opvp_brush_t brush; + opvp_point_t point; + const byte *buff = data; + byte *mybuf = NULL; + int i, j; + byte *d; + const byte *s; + int byte_offset = 0; + int byte_length = raster; + int bit_shift = 0; + int adj_raster = raster; + unsigned char bit_mask = 0xff; + bool reverse = false; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* data offset */ + if (data_x) { + byte_offset = data_x >> 3; + bit_shift = data_x & 0x07; + if (bit_shift) bit_mask <<= (8 - bit_shift); + + byte_length = ((w + 7) >> 3); + adj_raster = ((byte_length + 3) >> 2) << 2; + + buff = mybuf = calloc(adj_raster, h); + if (!mybuf) { + /* memory error */ + return -1; + } + s = &(data[byte_offset]); + d = mybuf; + if (bit_shift) { + for (i = 0;i < h; i++, d += adj_raster, s+= raster) { + for (j = 0; j < byte_length; j++) { + d[j] = ((s[j] & ~bit_mask) << bit_shift) + | ((s[j + 1] & bit_mask) >> (8 - bit_shift)); + } + } + } else { + for (i = 0;i < h; i++, d += adj_raster, s+= raster) { + for (j = 0; j < byte_length; j++) { + d[j] = s[j]; + } + } + } + byte_offset = 0; + } + +#if !(ENABLE_SIMPLE_MODE) + /* call SaveGS */ + if (apiEntry->opvpSaveGS) { + apiEntry->opvpSaveGS(printerContext); + } +#endif + if (one == gx_no_color_index) { + gx_color_index tc; + + reverse = (!reverse); + tc = zero; + zero = one; + one = tc; + } + + if (zero != gx_no_color_index) { + /* not mask */ + /* Set PaintMode */ + if (apiEntry->opvpSetPaintMode) { + apiEntry->opvpSetPaintMode(printerContext,OPVP_PAINTMODE_OPAQUE); + } + /* zero-color */ + opvp_set_brush_color(pdev, zero, &brush); + + /* call SetBgColor */ + if (apiEntry->opvpSetBgColor) { + apiEntry->opvpSetBgColor(printerContext, &brush); + } + } + + /* one-color */ + opvp_set_brush_color(pdev, one, &brush); + + /* call SetFillColor */ + if (apiEntry->opvpSetFillColor) { + apiEntry->opvpSetFillColor(printerContext, &brush); + } + + if (reverse) { + /* 0/1 reverse image */ + int n = adj_raster*h; + + if (buff == data) { + /* buff was not allocated from this function yet */ + /* allocate here */ + if ((mybuf = malloc(n)) == 0) return -1; + } + for (i = 0;i < n;i++) { + mybuf[i] = ~buff[i]; + } + buff = mybuf; + } + /* call SetCurrentPoint */ + OPVP_I2FIX(x, point.x); + OPVP_I2FIX(y, point.y); + if (apiEntry->opvpSetCurrentPoint) { + apiEntry->opvpSetCurrentPoint(printerContext,point.x, point.y); + } + + /* draw image */ + code = opvp_draw_image(pdev, + 1, + w, h, + w, h, + adj_raster, + 1, + &(buff[byte_offset])); + if (code) { + ecode = code; + } + + if (zero != gx_no_color_index) { + /* restore PaintMode */ + if (apiEntry->opvpSetPaintMode) { + apiEntry->opvpSetPaintMode(printerContext, + OPVP_PAINTMODE_TRANSPARENT); + } + } + /* restore fill color */ + if (vectorFillColor) { + /* call SetFillColor */ + if (apiEntry->opvpSetFillColor) { + apiEntry->opvpSetFillColor(printerContext,vectorFillColor); + } + } + +#if !(ENABLE_SIMPLE_MODE) + /* call RestoreGS */ + if (apiEntry->opvpRestoreGS) { + apiEntry->opvpRestoreGS(printerContext); + } +#endif + + if (buff != data) { + /* buff was allocated from this function */ + if (mybuf) free(mybuf); + } + + return ecode; +} + +/* + * copy color + */ +static int +opvp_copy_color( + gx_device *dev, + const byte *data, + int data_x, + int raster, + gx_bitmap_id id, + int x, + int y, + int w, + int h) +{ + gx_device_opvp *pdev = (gx_device_opvp *)dev; + int code = -1; + int ecode = 0; + opvp_point_t point; + const byte *buff = data; + byte *mybuf = NULL; + int i; + byte *d; + const byte *s; + int byte_length = raster; + int depth; + int pixel; + int adj_raster = raster; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* data offset */ + if (data_x) { + depth = pdev->color_info.depth; + pixel = (depth + 7) >> 3; + byte_length = pixel * w; + adj_raster = ((byte_length + 3) >> 2) << 2; + + buff = mybuf = malloc(adj_raster * h); + if (!mybuf) { + /* memory error */ + return -1; + } + s = &(data[data_x*pixel]); + d = mybuf; + for (i = 0;i < h; i++, d += adj_raster, s += raster) { + memcpy(d, s, byte_length); + } + data_x = 0; + } + +#if !(ENABLE_SIMPLE_MODE) + /* call SaveGS */ + if (apiEntry->opvpSaveGS) { + apiEntry->opvpSaveGS(printerContext); + } +#endif + + /* call SetCurrentPoint */ + OPVP_I2FIX(x, point.x); + OPVP_I2FIX(y, point.y); + if (apiEntry->opvpSetCurrentPoint) { + apiEntry->opvpSetCurrentPoint(printerContext, point.x, point.y); + } + + /* draw image */ + code = opvp_draw_image(pdev, + pdev->color_info.depth, + w, h, + w, h, + adj_raster, + 0, + &(buff[data_x])); + if (code) { + ecode = code; + } + +#if !(ENABLE_SIMPLE_MODE) + /* call RestoreGS */ + if (apiEntry->opvpRestoreGS) { + apiEntry->opvpRestoreGS(printerContext); + } +#endif + + if (buff != data) { + /* buff was allocated from this function */ + if (mybuf) free(mybuf); + } + + return ecode; +} + +/* + * get params + */ +static int +_get_params(gs_param_list *plist) +{ + int code; + int ecode = 0; + gs_param_name pname; + gs_param_string vdps; + gs_param_string pmps; + gs_param_string jips; + gs_param_string dips; + gs_param_string fips; + gs_param_string mlps; + gs_param_string mtps; + gs_param_string mrps; + gs_param_string mbps; + gs_param_string zmps; + char buff[OPVP_BUFF_SIZE]; + + /* get params */ + + /* vector driver name */ + pname = "Driver"; + vdps.data = (byte *)vectorDriver; + vdps.size = (vectorDriver ? strlen(vectorDriver) + 1 : 0); + vdps.persistent = false; + code = param_write_string(plist, pname, &vdps); + if (code) ecode = code; + + /* printer model name */ + pname = "Model"; + pmps.data = (byte *)printerModel; + pmps.size = (printerModel ? strlen(printerModel) + 1 : 0); + pmps.persistent = false; + code = param_write_string(plist, pname, &pmps); + if (code) ecode = code; + + /* job info */ + pname = "JobInfo"; + jips.data = (byte *)jobInfo; + jips.size = (jobInfo ? strlen(jobInfo) + 1 : 0); + jips.persistent = false; + code = param_write_string(plist, pname, &jips); + if (code) ecode = code; + + /* doc info */ + pname = "DocInfo"; + dips.data = (byte *)docInfo; + dips.size = (docInfo ? strlen(docInfo) + 1 : 0); + dips.persistent = false; + code = param_write_string(plist, pname, &dips); + if (code) ecode = code; + + /* fast image support */ + switch (FastImageMode) { + case FastImageNoCTM: + opvp_alloc_string(&fastImage, "NoCTM"); + break; + case FastImageNoRotate: + opvp_alloc_string(&fastImage, "NoRotateCTM"); + break; + case FastImageRightAngle: + opvp_alloc_string(&fastImage, "RightAngleCTM"); + break; + case FastImageReverseAngle: + opvp_alloc_string(&fastImage, "ReverseAngleCTM"); + break; + case FastImageAll: + opvp_alloc_string(&fastImage, "All"); + break; + case FastImageDisable: + default: + opvp_alloc_string(&fastImage, NULL); + break; + } + pname = "FastImage"; + fips.data = (byte *)fastImage; + fips.size = (fastImage ? strlen(fastImage) + 1 : 0); + fips.persistent = false; + code = param_write_string(plist, pname, &fips); + if (code) ecode = code; + + /* margins */ + memset((void*)buff, 0, OPVP_BUFF_SIZE); + pname = "MarginLeft"; + snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[0]); + mlps.data = (byte *)buff; + mlps.size = strlen(buff) + 1; + mlps.persistent = false; + code = param_write_string(plist, pname, &mlps); + if (code) ecode = code; + pname = "MarginTop"; + snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[3]); + mtps.data = (byte *)buff; + mtps.size = strlen(buff) + 1; + mtps.persistent = false; + code = param_write_string(plist, pname, &mtps); + if (code) ecode = code; + pname = "MarginRight"; + snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[2]); + mrps.data = (byte *)buff; + mrps.size = strlen(buff) + 1; + mrps.persistent = false; + code = param_write_string(plist, pname, &mrps); + if (code) ecode = code; + pname = "MarginBottom"; + snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",margins[1]); + mbps.data = (byte *)buff; + mbps.size = strlen(buff) + 1; + mbps.persistent = false; + code = param_write_string(plist, pname, &mbps); + if (code) ecode = code; + + /* zoom */ + pname = "Zoom"; + snprintf(buff, OPVP_BUFF_SIZE - 1, "%f",zoom[0]); + zmps.data = (byte *)buff; + zmps.size = strlen(buff) + 1; + zmps.persistent = false; + code = param_write_string(plist, pname, &zmps); + if (code) ecode = code; + + return ecode; +} + +/* + * get params for vector + */ +static int +opvp_get_params(gx_device *dev, gs_param_list *plist) +{ + int code; + + /* get default params */ + code = gdev_vector_get_params(dev, plist); + if (code) return code; + + /* get params */ + return _get_params(plist); +} + +/* + * get params for inkjet + */ +static int +oprp_get_params(gx_device *dev, gs_param_list *plist) +{ + int code; + + /* get default params */ + code = gdev_prn_get_params(dev, plist); + if (code) return code; + + /* get params */ + return _get_params(plist); +} + +/* + * put params + */ +static int +_put_params(gs_param_list *plist) +{ + int code; + int ecode = 0; + gs_param_name pname; + char *buff = NULL; + gs_param_string vdps; + gs_param_string pmps; + gs_param_string jips; + gs_param_string dips; + gs_param_string fips; + gs_param_string mlps; + gs_param_string mtps; + gs_param_string mrps; + gs_param_string mbps; + gs_param_string zmps; + + /* vector driver name */ + pname = "Driver"; + code = param_read_string(plist, pname, &vdps); + switch (code) { + case 0: + buff = realloc(buff, vdps.size + 1); + memcpy(buff, vdps.data, vdps.size); + buff[vdps.size] = 0; + opvp_alloc_string(&vectorDriver, buff); + break; + case 1: + /* opvp_alloc_string(&vectorDriver, NULL);*/ + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + /* printer model name */ + pname = "Model"; + code = param_read_string(plist, pname, &pmps); + switch (code) { + case 0: + buff = realloc(buff, pmps.size + 1); + memcpy(buff, pmps.data, pmps.size); + buff[pmps.size] = 0; + opvp_alloc_string(&printerModel, buff); + break; + case 1: + /*opvp_alloc_string(&printerModel, NULL);*/ + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + /* job info */ + pname = "JobInfo"; + code = param_read_string(plist, pname, &jips); + switch (code) { + case 0: + buff = realloc(buff, jips.size + 1); + memcpy(buff, jips.data, jips.size); + buff[jips.size] = 0; + opvp_alloc_string(&jobInfo, buff); + break; + case 1: + /*opvp_alloc_string(&jobInfo, NULL);*/ + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + /* doc info */ + pname = "DocInfo"; + code = param_read_string(plist, pname, &dips); + switch (code) { + case 0: + buff = realloc(buff, dips.size + 1); + memcpy(buff, dips.data, dips.size); + buff[dips.size] = 0; + opvp_alloc_string(&docInfo, buff); + break; + case 1: + /*opvp_alloc_string(&docInfo, NULL);*/ + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + /* fast image support */ + pname = "FastImage"; + code = param_read_string(plist, pname, &fips); + switch (code) { + case 0: + buff = realloc(buff, fips.size + 1); + memcpy(buff, fips.data, fips.size); + buff[fips.size] = 0; + opvp_alloc_string(&fastImage, buff); + if (strcasecmp(fastImage,"NoCTM")==0) { + FastImageMode = FastImageNoCTM; + } else if (strncasecmp(fastImage,"NoRotate",8)==0) { + FastImageMode = FastImageNoRotate; + } else if (strncasecmp(fastImage,"Right",5)==0) { + FastImageMode = FastImageRightAngle; + } else if (strncasecmp(fastImage,"Reverse",7)==0) { + FastImageMode = FastImageReverseAngle; + } else if (strncasecmp(fastImage,"All",3)==0) { + FastImageMode = FastImageAll; + } else { + FastImageMode = FastImageDisable; + } + break; + case 1: + /*opvp_alloc_string(&fastImage, NULL);*/ + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + /* margins */ + pname = "MarginLeft"; + code = param_read_string(plist, pname, &mlps); + switch (code) { + case 0: + buff = realloc(buff, mlps.size + 1); + memcpy(buff, mlps.data, mlps.size); + buff[mlps.size] = 0; + margins[0] = atof(buff); + break; + case 1: + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + pname = "MarginTop"; + code = param_read_string(plist, pname, &mtps); + switch (code) { + case 0: + buff = realloc(buff, mtps.size + 1); + memcpy(buff, mtps.data, mtps.size); + buff[mtps.size] = 0; + margins[3] = atof(buff); + break; + case 1: + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + pname = "MarginRight"; + code = param_read_string(plist, pname, &mrps); + switch (code) { + case 0: + buff = realloc(buff, mrps.size + 1); + memcpy(buff, mrps.data, mrps.size); + buff[mrps.size] = 0; + margins[2] = atof(buff); + break; + case 1: + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + pname = "MarginBottom"; + code = param_read_string(plist, pname, &mbps); + switch (code) { + case 0: + buff = realloc(buff, mbps.size + 1); + memcpy(buff, mbps.data, mbps.size); + buff[mbps.size] = 0; + margins[1] = atof(buff); + break; + case 1: + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + /* zoom */ + pname = "Zoom"; + code = param_read_string(plist, pname, &zmps); + switch (code) { + case 0: + buff = realloc(buff, zmps.size + 1); + memcpy(buff, zmps.data, zmps.size); + buff[zmps.size] = 0; + if (strncasecmp(buff, "Auto", 4)) { + zoom[0] = atof(buff); + if (zoom[0] > 0) { + zoom[1] = zoom[0]; + } else { + zoom[0] = zoom[1] = 1; + } + } else { + zoom[0] = zoom[1] = 1; + zoomAuto = true; + } + break; + case 1: + break; + default: + ecode = code; + param_signal_error(plist, pname, ecode); + } + + if (buff) free(buff); + + return ecode; +} + +/* + * put params for vector + */ +static int +opvp_put_params(gx_device *dev, gs_param_list *plist) +{ + int code; + + /* put params */ + code = _put_params(plist); + if (code) return code; + + /* put default params */ + return gdev_vector_put_params(dev, plist); +} + +/* + * put params for inkjet + */ +static int +oprp_put_params(gx_device *dev, gs_param_list *plist) +{ + int code; + + /* put params */ + code = _put_params(plist); + if (code) return code; + + /* put default params */ + return gdev_prn_put_params(dev, plist); +} + +static int checkPath(const gx_path *ppath) +{ + unsigned int npoints = 0; + fixed vs[6]; + int op; + gs_path_enum path; + + gx_path_enum_init(&path, ppath); + + while ((op = gx_path_enum_next(&path, (gs_fixed_point *)vs)) != 0) { + switch (op) { + case gs_pe_lineto: + case gs_pe_moveto: + npoints += 1; + break; + case gs_pe_curveto: + npoints += 3; + break; + case gs_pe_closepath: + break; + default: + break; + } + if (npoints > MAX_PATH_POINTS) { + return 0; + } + + } + return 1; +} + +static int checkCPath(const gx_clip_path *pcpath) +{ + const gx_clip_list *list; + const gx_clip_rect *prect; + int npoints; + + if (pcpath == 0) return 1; + if (pcpath->path_valid) { + return checkPath(&pcpath->path); + } + list = gx_cpath_list(pcpath); + prect = list->head; + if (prect == 0) { + prect = &list->single; + } + npoints = 0; + for (;prect != 0;prect = prect->next) { + npoints += 4; + if (npoints > MAX_PATH_POINTS) { + return 0; + } + } + return 1; +} + +/* + * fill path + */ +static int +opvp_fill_path( + gx_device *dev, + const gs_imager_state *pis, + gx_path *ppath, + const gx_fill_params *params, + const gx_device_color *pdevc, + const gx_clip_path *pxpath) +{ + bool draw_image = false; + gs_fixed_rect inner, outer; + + /* check if paths are too complex */ + if (!checkPath(ppath) || !checkCPath(pxpath)) { + return gx_default_fill_path(dev, pis, ppath, params, pdevc, pxpath); + } + /* check clippath support */ + if (!(apiEntry->opvpSetClipPath)) { + /* get clipping box area */ + gx_cpath_inner_box(pxpath,&inner); + gx_cpath_outer_box(pxpath,&outer); + /* check difference between inner-box and outer-box */ + if ((inner.p.x != outer.p.x) || (inner.p.y != outer.p.y) || + (inner.q.x != outer.q.x) || (inner.q.y != outer.q.y)) { + /* set draw by image */ + draw_image = true; + } + } + + if (!vector || draw_image) { + return gx_default_fill_path(dev, pis, ppath, params, pdevc, pxpath); + } + + return gdev_vector_fill_path(dev, pis, ppath, params, pdevc, pxpath); +} + +/* + * stroke path + */ +static int +opvp_stroke_path( + gx_device *dev, + const gs_imager_state *pis, + gx_path *ppath, + const gx_stroke_params *params, + const gx_drawing_color *pdcolor, + const gx_clip_path *pxpath) +{ + bool draw_image = false; + gs_fixed_rect inner, outer; + + /* check if paths are too complex */ + if (!checkPath(ppath) || !checkCPath(pxpath)) { + return gx_default_stroke_path(dev, pis, ppath, + params, pdcolor, pxpath); + } + /* check clippath support */ + if (!(apiEntry->opvpSetClipPath)) { + /* get clipping box area */ + gx_cpath_inner_box(pxpath,&inner); + gx_cpath_outer_box(pxpath,&outer); + /* check difference between inner-box and outer-box */ + if ((inner.p.x != outer.p.x) || (inner.p.y != outer.p.y) || + (inner.q.x != outer.q.x) || (inner.q.y != outer.q.y)) { + /* set draw by image */ + draw_image = true; + } + } + + if (!vector || draw_image) { + return gx_default_stroke_path(dev, pis, ppath, + params, pdcolor, pxpath); + } + + return gdev_vector_stroke_path(dev, pis, ppath, + params, pdcolor, pxpath); +} + +/* + * fill mask + */ +static int +opvp_fill_mask( + gx_device *dev, + const byte *data, + int data_x, + int raster, + gx_bitmap_id id, + int x, + int y, + int w, + int h, + const gx_drawing_color *pdcolor, + int depth, + gs_logical_operation_t lop, + const gx_clip_path *pcpath) +{ + if (vector) { +#if GS_VERSION_MAJOR >= 8 /* for gs 8.15 */ + gdev_vector_update_fill_color((gx_device_vector *)dev, NULL, pdcolor); +#else + gdev_vector_update_fill_color((gx_device_vector *)dev, pdcolor); +#endif + gdev_vector_update_clip_path((gx_device_vector *)dev, pcpath); + gdev_vector_update_log_op((gx_device_vector *)dev, lop); + } + + return gx_default_fill_mask(dev, data, data_x, raster, id, + x, y, w, h, pdcolor, depth, lop, pcpath); +} + +/* + * begin image + */ +static int +opvp_begin_image( + gx_device *dev, + const gs_imager_state *pis, + 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 *mem, + gx_image_enum_common_t **pinfo) +{ + gx_device_vector *vdev =(gx_device_vector *)dev; + gdev_vector_image_enum_t *vinfo; + gs_matrix mtx; + opvp_ctm_t ctm; + bool draw_image = false; + bool supported_angle = false; + int code = -1; + opvp_result_t r = -1; + int ecode = 0; + int bits_per_pixel = 24; + bool can_reverse = false; + int p; + float mag[2] = {1, 1}; + const gs_color_space *pcs = pim->ColorSpace; + + /* check if paths are too complex */ + if (!checkCPath(pcpath)) { + return gx_default_begin_image( + dev, pis, pim, format, + prect, pdcolor, pcpath, + mem, pinfo); + } + + color_index = 0; + + vinfo = gs_alloc_struct(mem, gdev_vector_image_enum_t, + &st_vector_image_enum, + "opvp_begin_image"); + + if (vinfo) { + memcpy(imageDecode,pim->Decode,sizeof(pim->Decode)); + vinfo->memory =mem; + code = gdev_vector_begin_image(vdev, pis, pim, format, prect, + pdcolor, pcpath, mem, + &opvp_image_enum_procs, + vinfo); + if (code) ecode = code; + + if (!ecode) { + /* bits per pixel */ + for (bits_per_pixel=0, p=0; p < vinfo->num_planes; p++) { + bits_per_pixel += vinfo->plane_depths[p]; + } + + /* for indexed color */ + if (!(pim->ImageMask)) { + color_index = gs_color_space_get_index(pcs); + if (color_index == gs_color_space_index_Indexed) { + base_color_index + = gs_color_space_indexed_base_space(pcs)->type->index; + if (((pcs->params.indexed.hival + 1) > 256) + || (bits_per_pixel != 8 && bits_per_pixel != 1)) { + return gx_default_begin_image( + dev, pis, pim, format, + prect, pdcolor, pcpath, + mem, pinfo); + } else if (base_color_index + == gs_color_space_index_DeviceCMYK) { + /* for CMYK indexed color */ + int count; + const unsigned char *p + = pcs->params.indexed.lookup.table.data; + frac rgb[3]; + + for(count = 0;count < + (pcs->params.indexed.hival + 1); count++) { + memset(rgb, 0, sizeof(rgb)); + color_cmyk_to_rgb( + byte2frac((*(p + 0 + (count * 4)))), + byte2frac((*(p + 1 + (count * 4)))), + byte2frac((*(p + 2 + (count * 4)))), + byte2frac((*(p + 3 + (count * 4)))), +#if GS_VERSION_MAJOR >= 9 + pis, rgb, mem); +#else + pis, rgb); +#endif + *(palette + 0 + (count * 3)) = frac2byte(rgb[0]); + *(palette + 1 + (count * 3)) = frac2byte(rgb[1]); + *(palette + 2 + (count * 3)) = frac2byte(rgb[2]); + } + + bits_per_pixel = 24; + } else if (base_color_index + == gs_color_space_index_DeviceRGB || + base_color_index == gs_color_space_index_CIEABC) { + /* for RGB or CalRGB indexed color */ + memcpy(palette, pcs->params.indexed.lookup.table.data,\ + pcs->params.indexed.lookup.table.size); + bits_per_pixel = 24; + } else if (base_color_index + == gs_color_space_index_DeviceGray || + base_color_index == gs_color_space_index_CIEA) { + /* for Gray or CalGray indexed color */ + memcpy(palette, pcs->params.indexed.lookup.table.data,\ + pcs->params.indexed.lookup.table.size); + bits_per_pixel = 8; + } else { + /* except CMYK and RGB */ + return gx_default_begin_image( + dev, pis, pim, format, + prect, pdcolor, pcpath, + mem, pinfo); + } + } + } + +#if ENABLE_AUTO_REVERSE + if (bits_per_pixel % 8 == 0) { + can_reverse = true; + } +#endif + /* adjust matrix */ + reverse_image = false; + gs_matrix_invert(&pim->ImageMatrix, &mtx); + gs_matrix_multiply(&mtx, &ctm_only(pis), &mtx); + switch (FastImageMode) { + case FastImageNoCTM: + if ((mtx.xy==0)&&(mtx.yx==0)&& (mtx.yy>=0)) { + if (mtx.xx>=0) { + mag[0] = mtx.xx; + mag[1] = mtx.yy; + mtx.xx = 1; + mtx.yy = 1; + supported_angle = true; + } else if (can_reverse) { + mtx.xx *= -1; + mag[0] = mtx.xx; + mag[1] = mtx.yy; + mtx.xx = 1; + mtx.yy = 1; + mtx.tx -= vinfo->width + * mag[0]; + supported_angle = true; + reverse_image = true; + } + } + break; + case FastImageNoRotate: + if ((mtx.xy==0)&&(mtx.yx==0)&& (mtx.yy>=0)) { + if (mtx.xx>=0) { + supported_angle = true; + } else if (can_reverse) { + mtx.xx *= -1; + mtx.tx -= vinfo->width + * mtx.xx; + supported_angle = true; + reverse_image = true; + } + } + break; + case FastImageRightAngle: + if ((mtx.xy==0)&&(mtx.yx==0)) { + if (((mtx.xx>=0)&&(mtx.yy>=0))|| + ((mtx.xx<=0)&&(mtx.yy<=0))){ + supported_angle = true; + } else if (can_reverse) { + mtx.xx *= -1; + mtx.tx -= vinfo->width + * mtx.xx; + supported_angle = true; + reverse_image = true; + } + } else if ((mtx.xx==0)&&(mtx.yy==0)) { + if (((mtx.xy>=0)&&(mtx.yx<=0))|| + ((mtx.xy<=0)&&(mtx.yx>=0))){ + supported_angle = true; + } else if (can_reverse) { + mtx.xy *= -1; + mtx.ty -= vinfo->height + * mtx.xy; + supported_angle = true; + reverse_image = true; + } + } + break; + case FastImageReverseAngle: + if (((mtx.xy==0)&&(mtx.yx==0))|| + ((mtx.xx==0)&&(mtx.yy==0))) { + supported_angle = true; + } + break; + case FastImageAll: + supported_angle = true; + break; + case FastImageDisable: + default: + break; + } + } + + if ((!ecode) && supported_angle) { + if ((!prect) && + ((vinfo->num_planes == 1) || + ((vinfo->num_planes == 3) && + (vinfo->plane_depths[0] == 8) && + (vinfo->plane_depths[1] == 8) && + (vinfo->plane_depths[2] == 8)) + ) + ) { + /* + * avail only + * 1 plane image + * or + * 3 planes 24 bits color image + * (8 bits per plane) + */ + if (apiEntry->opvpStartDrawImage) { + draw_image = true; + } + } + } + } + + if (draw_image) { + *pinfo = (gx_image_enum_common_t *)vinfo; + + if (!ecode) { + if (!pim->ImageMask) { + /* call SetPaintMode */ + if (apiEntry->opvpSetPaintMode) { + apiEntry->opvpSetPaintMode(printerContext, + OPVP_PAINTMODE_OPAQUE); + change_paint_mode = true; + } + /* set color space */ + if (apiEntry->opvpSetColorSpace != NULL) { + opvp_cspace_t ncspace; + + savedColorSpace = colorSpace; + switch (bits_per_pixel) { + case 1: + ncspace = OPVP_CSPACE_DEVICEGRAY; + bits_per_pixel = 8; + if (!cspace_available[ncspace]) { + ncspace = OPVP_CSPACE_STANDARDRGB; + bits_per_pixel = 24; + } + break; + case 8: + ncspace = OPVP_CSPACE_DEVICEGRAY; + if (!cspace_available[ncspace]) { + ncspace = OPVP_CSPACE_STANDARDRGB; + bits_per_pixel = 24; + } + break; + case 24: + ncspace = OPVP_CSPACE_DEVICERGB; + if (!cspace_available[ncspace]) { + ncspace = OPVP_CSPACE_STANDARDRGB; + } + break; + default: + r = -1; + goto fallthrough; + break; + } + if (ncspace != colorSpace) { + if (apiEntry->opvpSetColorSpace(printerContext,ncspace) + != OPVP_OK) { + r = -1; + goto fallthrough; + } + colorSpace = ncspace; + change_cspace = true; + } + } + } + } + if (!ecode) { + if (supported_angle) { + /* moveto */ + opvp_moveto(vdev, 0, 0, mtx.tx, mtx.ty, 0); + } + if ((supported_angle) && (FastImageMode != FastImageNoCTM)) { + /* call SetCTM */ + ctm.a = mtx.xx; + ctm.b = mtx.xy; + ctm.c = mtx.yx; + ctm.d = mtx.yy; + ctm.e = mtx.tx; + ctm.f = mtx.ty; + if (apiEntry->opvpSetCTM) { + r = apiEntry->opvpSetCTM(printerContext, &ctm); + } + else r = -1; + if (r != OPVP_OK) ecode = r; + } + } + if (!ecode) { + int dw,dh; + + /* image size */ + if (mag[0] != 1) { + dw = floor(vinfo->width * mag[0]+0.5); + } else { + dw = vinfo->width; + } + if (mag[1] != 1) { + dh = floor(vinfo->height * mag[1]+0.5); + } else { + dh = vinfo->height; + } + /* call StartDrawImage */ + if (apiEntry->opvpStartDrawImage) { + opvp_int_t adj_raster; + + adj_raster = bits_per_pixel*vinfo->width; + adj_raster = ((adj_raster+31) >> 5) << 2; + r = apiEntry->opvpStartDrawImage( + printerContext, + vinfo->width, + vinfo->height, + adj_raster, + pim->ImageMask ? + OPVP_IFORMAT_MASK: + OPVP_IFORMAT_RAW, + dw,dh); + if(r != OPVP_OK) { + if (apiEntry->opvpEndDrawImage) { + apiEntry->opvpEndDrawImage(printerContext); + } + } + } + + /* bugfix for 32bit CMYK image print error */ +fallthrough: + if(r != OPVP_OK) { + if (change_paint_mode) { + /* restore paint mode */ + if (apiEntry->opvpSetPaintMode) { + apiEntry->opvpSetPaintMode(printerContext, + OPVP_PAINTMODE_TRANSPARENT); + } + change_paint_mode = false; + } + if (change_cspace) { + /* restore color space */ + colorSpace = savedColorSpace; + if (apiEntry->opvpSetColorSpace) { + apiEntry->opvpSetColorSpace(printerContext, + colorSpace); + } + change_cspace = false; + } + if(apiEntry->opvpResetCTM) { + apiEntry->opvpResetCTM(printerContext); /* reset CTM */ + } + return gx_default_begin_image(dev, pis, pim, format, + prect, pdcolor, pcpath, mem, pinfo); + } + } + + if (!ecode) { + begin_image = true; + } + + return ecode; + } + + return gx_default_begin_image(dev, pis, pim, format, prect, + pdcolor, pcpath, mem, pinfo); +} + +/* + * plane data + */ +static int +opvp_image_plane_data( + gx_image_enum_common_t *info, + const gx_image_plane_t *planes, + int height, + int *rows_used) +{ + gdev_vector_image_enum_t *vinfo; + byte *tmp_buf = NULL; + byte *buf = NULL; + int bits_per_pixel; + int data_bytes, dst_bytes; + int raster_length, dst_length; + int p; + int x; + int d; + int h; + int ecode = 0; + int i, j; + byte *src_ptr, *dst_ptr, *ppalette; + byte *ptr; + bbox_image_enum *pbe; + gx_image_enum *tinfo; + const gs_imager_state *pis; + + vinfo = (gdev_vector_image_enum_t *)info; + + if (!begin_image) return 0; + + for (bits_per_pixel=0, p=0; p < vinfo->num_planes; p++) { + bits_per_pixel += vinfo->plane_depths[p]; + } + + data_bytes = (bits_per_pixel * vinfo->width + 7) >> 3; + raster_length = ((data_bytes + 3) >> 2) << 2; + buf = calloc(raster_length, height); + + if (vinfo->default_info) { + gx_image_plane_data(vinfo->default_info, planes, height); + } + if (vinfo->bbox_info) { + gx_image_plane_data(vinfo->bbox_info, planes, height); + } + + if (buf) { + /* Adjust image data gamma */ + pbe = (bbox_image_enum *)vinfo->bbox_info; + tinfo = (gx_image_enum *)pbe->target_info; + pis = tinfo->pis; + + if (vinfo->num_planes == 1) { + for (h = 0; h < height; h++) { + d = raster_length * h; + if (reverse_image) { + int bytes_per_pixel = bits_per_pixel / 8; + for (x = data_bytes * (h + 1) - bytes_per_pixel; + x >= data_bytes * h; + x-=bytes_per_pixel, + d+=bytes_per_pixel) { + memcpy(buf+d, planes[0].data+x, bytes_per_pixel); + } + } else { + memcpy(buf + d, + planes[0].data + + (data_bytes * h), + data_bytes); + } + } + } else { + for (h = 0; h < height; h++) { + d = raster_length * h; + if (reverse_image) { + for (x = vinfo->width * (h + 1) - 1; + x >= vinfo->width * h; + x--) { + for (p = 0; + p < vinfo->num_planes; + p++, d++) { + buf[d] = (byte)(planes[p].data[x]); + } + } + } else { + for (x = vinfo->width * h; + x < vinfo->width * (h + 1); + x++) { + for (p = 0; + p < vinfo->num_planes; + p++, d++) { + buf[d] = (byte) + (planes[p].data[x]); + } + } + } + } + } + + if (tinfo->masked) { + bool reverse = false; + + /* image mask */ + if (imageDecode[0] == 0) { + reverse = true; + } + if (reverse) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + for (j = 0; j < data_bytes; j++) { + src_ptr[j] ^= 0xff; + } + } + } + } else { + if(color_index == gs_color_space_index_Indexed) { + if (base_color_index == gs_color_space_index_DeviceGray || + base_color_index == gs_color_space_index_CIEA) { + if (colorSpace == OPVP_CSPACE_DEVICEGRAY) { + /* Convert indexed gray color -> Gray */ + if (bits_per_pixel == 8) { /* 8bit image */ + dst_bytes = data_bytes; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < data_bytes; j++) { + ppalette = palette + src_ptr[j] ; + dst_ptr[j] = ppalette[0]; + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 8; + } + } else { /* 1bit image */ + dst_bytes = vinfo->width; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); + ppalette = palette + o; + dst_ptr[j] = ppalette[0]; + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 8; + } + } + } else { + /* Convert indexed Gray color -> RGB */ + if (bits_per_pixel == 8) { /* 8bit image */ + dst_bytes = data_bytes * 3; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < data_bytes; j++) { + ppalette = palette + src_ptr[j] * 3; + dst_ptr[j*3] = ppalette[0]; /* R */ + dst_ptr[j*3 + 1] = ppalette[0]; /* G */ + dst_ptr[j*3 + 2] = ppalette[0]; /* B */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 24; + } + } else { /* 1bit image */ + dst_bytes = vinfo->width * 3; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); + ppalette = palette + o * 3; + dst_ptr[j*3] = ppalette[0]; /* R */ + dst_ptr[j*3 + 1] = ppalette[0]; /* G */ + dst_ptr[j*3 + 2] = ppalette[0]; /* B */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 24; + } + } + } + } else { + /* Convert indexed color -> RGB */ + if (bits_per_pixel == 8) { /* 8bit image */ + dst_bytes = data_bytes * 3; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < data_bytes; j++) { + ppalette = palette + src_ptr[j] * 3; + dst_ptr[j*3] = ppalette[0]; /* R */ + dst_ptr[j*3 + 1] = ppalette[1]; /* G */ + dst_ptr[j*3 + 2] = ppalette[2]; /* B */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 24; + } + } else { /* 1bit image */ + dst_bytes = vinfo->width * 3; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); + ppalette = palette + o * 3; + dst_ptr[j*3] = ppalette[0]; /* R */ + dst_ptr[j*3 + 1] = ppalette[1]; /* G */ + dst_ptr[j*3 + 2] = ppalette[2]; /* B */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 24; + } + } + } + } + + /* Convert Gray */ + if(color_index == gs_color_space_index_DeviceGray || + color_index == gs_color_space_index_CIEA) { + if (colorSpace == OPVP_CSPACE_STANDARDRGB + || colorSpace == OPVP_CSPACE_DEVICERGB) { + /* convert to RGB */ + if (bits_per_pixel == 8) { /* 8bit image */ + dst_bytes = data_bytes * 3; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < data_bytes; j++) { + unsigned char d = floor( + imageDecode[0]*255 + src_ptr[j]* + (imageDecode[1]-imageDecode[0])+0.5); + + dst_ptr[j*3] = d; /* R */ + dst_ptr[j*3 + 1] = d; /* G */ + dst_ptr[j*3 + 2] = d; /* B */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 24; + } + } else { /* 1bit image */ + dst_bytes = vinfo->width * 3; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); + unsigned char d = floor( + imageDecode[0]*255 + o* + (imageDecode[1]-imageDecode[0])*255+0.5); + dst_ptr[j*3] = d; /* R */ + dst_ptr[j*3 + 1] = d; /* G */ + dst_ptr[j*3 + 2] =d; /* B */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 24; + } + } + } else if (colorSpace == OPVP_CSPACE_DEVICEGRAY) { + if (bits_per_pixel == 1) { /* 1bit image */ + dst_bytes = vinfo->width; + dst_length = ((dst_bytes + 3) >> 2) << 2; + + tmp_buf = calloc(dst_length, height); + if (tmp_buf) { + for (i = 0; i < height; i++) { + src_ptr = buf + raster_length * i; + dst_ptr = tmp_buf + dst_length * i; + for (j = 0; j < vinfo->width; j++) { + int o = ((src_ptr[j/8] & (1 << (7 - (j & 7)))) + != 0); + unsigned char d = floor( + imageDecode[0]*255 + o* + (imageDecode[1]-imageDecode[0])*255+0.5); + dst_ptr[j] = d; /* R */ + } + } + + free (buf); + buf = tmp_buf; + data_bytes = dst_bytes; + raster_length = dst_length; + vinfo->bits_per_pixel = 8; + } + } + } + } + } +#if GS_VERSION_MAJOR >= 8 + if (vinfo->bits_per_pixel == 24) { /* 24bit RGB color */ + for (i = 0; i < height; i++) { + ptr = buf + raster_length * i; + for (j = 0; j < vinfo->width; j++) { + ptr[j*3] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j*3]), effective_transfer[0]))); + ptr[j*3+1] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j*3+1]), effective_transfer[1]))); + ptr[j*3+2] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j*3+2]), effective_transfer[2]))); + } + } + } else if (vinfo->bits_per_pixel == 8) { /* 8bit Gray image */ + for (i = 0; i < height; i++) { + ptr = buf + raster_length * i; + for (j=0; j < vinfo->width; j++) { + ptr[j] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j]), effective_transfer[3]))); + } + } + } +#else + if (vinfo->bits_per_pixel == 24) { /* 24bit RGB color */ + for (i = 0; i < height; i++) { + ptr = buf + raster_length * i; + for (j = 0; j < vinfo->width; j++) { + ptr[j*3] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j*3]), effective_transfer.colored.red))); + ptr[j*3+1] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j*3+1]), effective_transfer.colored.green))); + ptr[j*3+2] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j*3+2]), effective_transfer.colored.blue))); + } + } + } else if (vinfo->bits_per_pixel == 8) { /* 8bit Gray image */ + for (i = 0; i < height; i++) { + ptr = buf + raster_length * i; + for (j = 0; j < vinfo->width; j++) { + ptr[j] = min(255, frac2cv(gx_map_color_frac(pis, + cv2frac(ptr[j]), effective_transfer.colored.gray))); + } + } + } +#endif + + /* call TansferDrawImage */ + if (apiEntry->opvpTransferDrawImage) { + apiEntry->opvpTransferDrawImage(printerContext, + raster_length * height, (void *)buf); + } + if (buf) { + free(buf); /* free buffer */ + } + } + + vinfo->y += height; + ecode = (vinfo->y >= vinfo->height); + + return ecode; +} + +/* + * end image + */ +static int +opvp_image_end_image(gx_image_enum_common_t *info, bool draw_last) +{ + gx_device *dev = info->dev; + gx_device_vector *vdev = (gx_device_vector *)dev; + gdev_vector_image_enum_t *vinfo; + opvp_ctm_t ctm; + + vinfo = (gdev_vector_image_enum_t *)info; + + if (begin_image) { + /* call EndDrawImage */ + if (apiEntry->opvpEndDrawImage) { + apiEntry->opvpEndDrawImage(printerContext); + } + + begin_image = false; + + if (FastImageMode != FastImageNoCTM) { + /* call ResetCTM */ + if (apiEntry->opvpResetCTM) { + apiEntry->opvpResetCTM(printerContext); + } else { + /* call SetCTM */ + ctm.a = 1; + ctm.b = 0; + ctm.c = 0; + ctm.d = 1; + ctm.e = 0; + ctm.f = 0; + if (apiEntry->opvpSetCTM) { + apiEntry->opvpSetCTM(printerContext, &ctm); + } + } + } + if (change_paint_mode) { + /* restore paint mode */ + if (apiEntry->opvpSetPaintMode) { + apiEntry->opvpSetPaintMode(printerContext, + OPVP_PAINTMODE_TRANSPARENT); + } + change_paint_mode = false; + } + if (change_cspace) { + /* restore color space */ + colorSpace = savedColorSpace; + if (apiEntry->opvpSetColorSpace) { + apiEntry->opvpSetColorSpace(printerContext, + colorSpace); + } + change_cspace = false; + } + } + + return gdev_vector_end_image(vdev, vinfo, draw_last, vdev->white); +} + +/* ----- vector driver procs ----- */ +/* + * begin page + */ +static int +opvp_beginpage(gx_device_vector *vdev) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + int code = -1; + int ecode = 0; + +#ifdef OPVP_IGNORE_BLANK_PAGE + if (pdev->in_page) return 0; +#endif + /* start page */ + code = opvp_startpage((gx_device *)pdev); + if (code) { + ecode = code; + } else { + pdev->in_page = true; /* added '05.12.07 */ + beginPage = true; + } + + return ecode; +} + +/* + * set line width + */ +static int +opvp_setlinewidth(gx_device_vector *vdev, double width) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_fix_t w; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* call SetLineWidth */ + OPVP_F2FIX(width, w); + if (apiEntry->opvpSetLineWidth) { + r = apiEntry->opvpSetLineWidth(printerContext, w); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * set line cap + */ +static int +opvp_setlinecap(gx_device_vector *vdev, gs_line_cap cap) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_linecap_t linecap; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + switch (cap) { + case gs_cap_butt: + linecap = OPVP_LINECAP_BUTT; + break; + case gs_cap_round: + linecap = OPVP_LINECAP_ROUND; + break; + case gs_cap_square: + linecap = OPVP_LINECAP_SQUARE; + break; + case gs_cap_triangle: + default: + linecap = OPVP_LINECAP_BUTT; + break; + } + + /* call SetLineCap */ + if (apiEntry->opvpSetLineCap) { + r = apiEntry->opvpSetLineCap(printerContext, linecap); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * set line join + */ +static int +opvp_setlinejoin(gx_device_vector *vdev, gs_line_join join) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_linejoin_t linejoin; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + switch (join) { + case gs_join_miter: + linejoin = OPVP_LINEJOIN_MITER; + break; + case gs_join_round: + linejoin = OPVP_LINEJOIN_ROUND; + break; + case gs_join_bevel: + linejoin = OPVP_LINEJOIN_BEVEL; + break; + case gs_join_none: + case gs_join_triangle: + default: + linejoin = OPVP_LINEJOIN_MITER; + break; + } + + /* call SetLineJoin */ + if (apiEntry->opvpSetLineJoin) { + r = apiEntry->opvpSetLineJoin(printerContext, linejoin); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * set miter limit + */ +static int +opvp_setmiterlimit(gx_device_vector *vdev, double limit) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_fix_t l; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* call SetMiterLimit */ + OPVP_F2FIX(limit, l); + if (apiEntry->opvpSetMiterLimit) { + r = apiEntry->opvpSetMiterLimit(printerContext, l); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * set dash + */ +static int +opvp_setdash( + gx_device_vector *vdev, + const float *pattern, + uint count, + double offset) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_fix_t *p = NULL; + opvp_fix_t o; + int i; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* pattern */ + if (count) { + p = calloc(sizeof(opvp_fix_t), count); + if (p) { + for (i = 0; i < count; i++) { + OPVP_F2FIX(pattern[i], p[i]); + } + } else { + ecode = -1; + } + } + + /* call SetLineDash */ + if (!ecode) { + if (apiEntry->opvpSetLineDash) { + r = apiEntry->opvpSetLineDash(printerContext, count,p); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + /* call SetLineDashOffset */ + if (!ecode) { + OPVP_F2FIX(offset, o); + if (apiEntry->opvpSetLineDashOffset) { + r = apiEntry->opvpSetLineDashOffset(printerContext, o); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + /* call SetLineStyle */ + if (!ecode) { + if (apiEntry->opvpSetLineStyle) { + r = apiEntry->opvpSetLineStyle(printerContext, + (count ? + OPVP_LINESTYLE_DASH : + OPVP_LINESTYLE_SOLID)); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + if (p) free(p); + + return ecode; +} + +/* + * set flat + */ +static int +opvp_setflat(gx_device_vector *vdev, double flatness) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + int ecode = 0; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* what to do ? */ + + return ecode; +} + +/* + * set logical operation + */ +static int +opvp_setlogop( + gx_device_vector *vdev, + gs_logical_operation_t lop, + gs_logical_operation_t diff) +{ + /* nothing done */ + return 0; +} + +#if GS_VERSION_MAJOR >= 8 +/*--- added for Ghostscritp 8.15 ---*/ +static int +opvp_can_handle_hl_color(gx_device_vector * vdev, + const gs_imager_state * pis1, const gx_drawing_color * pdc) +{ + return false; /* High level color is not implemented yet. */ +} +#endif + +/* + * set fill color + */ +#if GS_VERSION_MAJOR >= 8 +static int +opvp_setfillcolor( + gx_device_vector *vdev, + const gs_imager_state *pis, /* added for gs 8.15 */ + const gx_drawing_color *pdc) +#else +static int +opvp_setfillcolor(gx_device_vector *vdev, const gx_drawing_color *pdc) +#endif +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + gx_color_index color; + static opvp_brush_t brush; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck); + + /* color */ + if (!vectorFillColor) vectorFillColor = &brush; + color = gx_dc_pure_color(pdc); + opvp_set_brush_color(pdev, color, vectorFillColor); + + /* call SetFillColor */ + if (apiEntry->opvpSetFillColor) { + r = apiEntry->opvpSetFillColor(printerContext, vectorFillColor); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * set stroke color + */ +#if GS_VERSION_MAJOR >= 8 +static int +opvp_setstrokecolor( + gx_device_vector *vdev, + const gs_imager_state *pis, /* added for gs 8.15 */ + const gx_drawing_color *pdc) +#else +static int +opvp_setstrokecolor(gx_device_vector *vdev, const gx_drawing_color *pdc) +#endif +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + gx_color_index color; + opvp_brush_t brush; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + if (!gx_dc_is_pure(pdc)) return_error(gs_error_rangecheck); + + /* color */ + color = gx_dc_pure_color(pdc); + opvp_set_brush_color(pdev, color, &brush); + + /* call SetStrokeColor */ + if (apiEntry->opvpSetStrokeColor) { + r = apiEntry->opvpSetStrokeColor(printerContext, &brush); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +#define OPVP_OPT_MULTI_PATH + +/* + * vector do path + */ +static int +opvp_vector_dopath( + gx_device_vector *vdev, + const gx_path *ppath, + gx_path_type_t type, + const gs_matrix *pmat) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int code = -1; + int ecode = 0; + gs_fixed_rect rect; + gs_path_enum path; + gs_point scale; + int op; +#ifdef OPVP_OPT_MULTI_PATH + int i; + int pop = 0; + int npoints = 0; + int *cp_num = NULL; + _fPoint *points = NULL; + opvp_point_t *opvp_p = NULL; + _fPoint current; +#else + _fPoint points[4]; +#endif + _fPoint start; + fixed vs[6]; + bool begin = true; + + start.x = start.y = 0; +#ifdef OPVP_OPT_MULTI_PATH + current.x = current.y = 0; +#endif + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + if (gx_path_is_rectangle(ppath, &rect)) + return (*vdev_proc(vdev, dorect))(vdev, + rect.p.x, rect.p.y, + rect.q.x, rect.q.y, + type); + + /* begin path */ + code = (*vdev_proc(vdev, beginpath))(vdev, type); + if (code) ecode = code; + scale = vdev->scale; + gx_path_enum_init(&path, ppath); + + while (!ecode) { + op = gx_path_enum_next(&path, (gs_fixed_point *)vs); + if (begin) { + /* start point */ + start.x = fixed2float(vs[0]) / scale.x; + start.y = fixed2float(vs[1]) / scale.y; + begin = false; + +#ifdef OPVP_OPT_MULTI_PATH + npoints = 1; + points = realloc(points, sizeof(_fPoint)); + current = start; +#endif + + points[0] = start; + +#ifdef OPVP_OPT_MULTI_PATH + } else if (op != pop) { + /* convert float to Fix */ + opvp_p = realloc(opvp_p, sizeof(opvp_point_t) * npoints); + for (i = 0; i < npoints; i++) { + OPVP_F2FIX(points[i].x, opvp_p[i].x); + OPVP_F2FIX(points[i].y, opvp_p[i].y); + } + + switch (pop) { + case gs_pe_moveto: + /* call SetCurrentPoint */ + if (apiEntry->opvpSetCurrentPoint) { + r = apiEntry->opvpSetCurrentPoint( + printerContext, + opvp_p[npoints-1].x, + opvp_p[npoints-1].y); + } + if (r != OPVP_OK) ecode = -1; + break; + case gs_pe_lineto: + /* call LinePath */ + if (apiEntry->opvpLinePath) { + r = apiEntry->opvpLinePath( + printerContext, + OPVP_PATHOPEN, + npoints - 1, + &(opvp_p[1])); + } + if (r != OPVP_OK) ecode = -1; + break; + case gs_pe_curveto: + /* npoints */ + if (!cp_num) + cp_num = calloc(sizeof(int), 2); + cp_num[0] = npoints; + cp_num[1] = 0; + + /* call BezierPath */ + if (apiEntry->opvpBezierPath) { + r = apiEntry->opvpBezierPath( + printerContext, + npoints - 1, + &(opvp_p[1]) + ); + } + if (r != OPVP_OK) ecode = -1; + break; + case gs_pe_closepath: + /* close path */ + break; + default: + /* error */ + return_error(gs_error_unknownerror); + break; + } + + /* reset */ + npoints = 1; + if (cp_num) free(cp_num), cp_num = NULL; + points = realloc(points, sizeof(_fPoint)); + points[0] = current; +#endif + } + + if (!op) break; /* END */ + + switch (op) { + case gs_pe_moveto: +#ifdef OPVP_OPT_MULTI_PATH + /* move to */ + i = npoints; + npoints += 1; + points = realloc(points, sizeof(_fPoint) * npoints); + points[i].x = fixed2float(vs[0]) / scale.x; + points[i].y = fixed2float(vs[1]) / scale.y; + current = points[i]; + start = current; + +#else + + /* move to */ + points[1].x = fixed2float(vs[0]) / scale.x; + points[1].y = fixed2float(vs[1]) / scale.y; + code = (*vdev_proc(vdev, moveto))(vdev, + points[0].x, + points[0].y, + points[1].x, + points[1].y, + type); + if (code) ecode = code; + points[0] = points[1]; + start = points[0]; +#endif + break; + case gs_pe_lineto: +#ifdef OPVP_OPT_MULTI_PATH + /* line to */ + i = npoints; + npoints += 1; + points = realloc(points, sizeof(_fPoint) * npoints); + points[i].x = fixed2float(vs[0]) / scale.x; + points[i].y = fixed2float(vs[1]) / scale.y; + current = points[i]; +#else + /* line to */ + points[1].x = fixed2float(vs[0]) / scale.x; + points[1].y = fixed2float(vs[1]) / scale.y; + code = (*vdev_proc(vdev, lineto))(vdev, + points[0].x, + points[0].y, + points[1].x, + points[1].y, + type); + if (code) ecode = code; + points[0] = points[1]; +#endif + break; + case gs_pe_curveto: +#ifdef OPVP_OPT_MULTI_PATH + /* curve to */ + + i = npoints; + npoints += 3; + points = realloc(points, sizeof(_fPoint) * npoints); + points[i ].x = fixed2float(vs[0]) / scale.x; + points[i ].y = fixed2float(vs[1]) / scale.y; + points[i+1].x = fixed2float(vs[2]) / scale.x; + points[i+1].y = fixed2float(vs[3]) / scale.y; + points[i+2].x = fixed2float(vs[4]) / scale.x; + points[i+2].y = fixed2float(vs[5]) / scale.y; + current = points[i+2]; +#else + /* curve to */ + points[1].x = fixed2float(vs[0]) / scale.x; + points[1].y = fixed2float(vs[1]) / scale.y; + points[2].x = fixed2float(vs[2]) / scale.x; + points[2].y = fixed2float(vs[3]) / scale.y; + points[3].x = fixed2float(vs[4]) / scale.x; + points[3].y = fixed2float(vs[5]) / scale.y; + code = (*vdev_proc(vdev, curveto))(vdev, + points[0].x, + points[0].y, + points[1].x, + points[1].y, + points[2].x, + points[2].y, + points[3].x, + points[3].y, + type); + if (code) ecode = code; + points[0] = points[3]; +#endif + break; + case gs_pe_closepath: + /* close path */ + code = (*vdev_proc(vdev, closepath))( + vdev, + points[0].x, + points[0].y, + start.x, + start.y, + type); + if (code) ecode = code; + points[0] = start; +#ifdef OPVP_OPT_MULTI_PATH + current = start; +#endif + break; + default: + /* error */ + return_error(gs_error_unknownerror); + break; + } + +#ifdef OPVP_OPT_MULTI_PATH + pop = op; +#endif + } + + /* end path */ + code = (*vdev_proc(vdev, endpath))(vdev, type); + if (code) ecode = code; + +#ifdef OPVP_OPT_MULTI_PATH + if (points) free(points); + if (opvp_p) free(opvp_p); + if (cp_num) free(cp_num); +#endif + return ecode; +} + +/* + * vector do rect + */ +static int +opvp_vector_dorect( + gx_device_vector *vdev, + fixed x0, + fixed y0, + fixed x1, + fixed y1, + gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int code = -1; + int ecode = 0; + gs_point scale; + opvp_rectangle_t rectangles[1]; + _fPoint p; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* begin path */ + code = (*vdev_proc(vdev, beginpath))(vdev, type); + if (code) ecode = code; + scale = vdev->scale; + + if (!ecode) { + /* rectangle */ + p.x = fixed2float(x0) / scale.x; + p.y = fixed2float(y0) / scale.y; + OPVP_F2FIX(p.x, rectangles[0].p0.x); + OPVP_F2FIX(p.y, rectangles[0].p0.y); + p.x = fixed2float(x1) / scale.x; + p.y = fixed2float(y1) / scale.y; + OPVP_F2FIX(p.x, rectangles[0].p1.x); + OPVP_F2FIX(p.y, rectangles[0].p1.y); + + /* call RectanglePath */ + if (apiEntry->opvpRectanglePath) { + r = apiEntry->opvpRectanglePath(printerContext, + 1, + rectangles); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + /* end path */ + if (!ecode) { + code = (*vdev_proc(vdev, endpath))(vdev, type); + if (code) ecode = code; + } + + /* fallback */ + if (ecode) return gdev_vector_dorect(vdev,x0,y0,x1,y1,type); + + return ecode; +} + +/* + * begin path + */ +static int +opvp_beginpath(gx_device_vector *vdev, gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* check clip-path */ + if (type & gx_path_type_clip) { + if (apiEntry->opvpResetClipPath) + apiEntry->opvpResetClipPath(printerContext); + } + + /* call NewPath */ + if (apiEntry->opvpNewPath) { + r = apiEntry->opvpNewPath(printerContext); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * move to + */ +static int +opvp_moveto( + gx_device_vector *vdev, + double x0, + double y0, + double x1, + double y1, + gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_point_t p; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* call SetCurrentPoint */ + OPVP_F2FIX(x1, p.x); + OPVP_F2FIX(y1, p.y); + if (apiEntry->opvpSetCurrentPoint) { + r = apiEntry->opvpSetCurrentPoint(printerContext, p.x, p.y); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * line to + */ +static int +opvp_lineto( + gx_device_vector *vdev, + double x0, + double y0, + double x1, + double y1, + gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_point_t points[1]; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* point */ + OPVP_F2FIX(x1, points[0].x); + OPVP_F2FIX(y1, points[0].y); + + /* call LinePath */ + if (apiEntry->opvpLinePath) { + r = apiEntry->opvpLinePath(printerContext, OPVP_PATHOPEN, 1, points); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * curve to + */ +static int +opvp_curveto( + gx_device_vector *vdev, + double x0, + double y0, + double x1, + double y1, + double x2, + double y2, + double x3, + double y3, + gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_point_t points[4]; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* points */ + OPVP_F2FIX(x0, points[0].x); + OPVP_F2FIX(y0, points[0].y); + OPVP_F2FIX(x1, points[1].x); + OPVP_F2FIX(y1, points[1].y); + OPVP_F2FIX(x2, points[2].x); + OPVP_F2FIX(y2, points[2].y); + OPVP_F2FIX(x3, points[3].x); + OPVP_F2FIX(y3, points[3].y); + + /* call BezierPath */ + if (apiEntry->opvpBezierPath) { + r = apiEntry->opvpBezierPath(printerContext, + 3, + &(points[1]) + ); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * close path + */ +static int +opvp_closepath( + gx_device_vector *vdev, + double x, + double y, + double x_start, + double y_start, + gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + opvp_point_t points[1]; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* point */ + OPVP_F2FIX(x_start, points[0].x); + OPVP_F2FIX(y_start, points[0].y); + + /* call LinePath */ + if (apiEntry->opvpLinePath) { + r = apiEntry->opvpLinePath(printerContext, OPVP_PATHCLOSE, 1, points); + } + if (r != OPVP_OK) { + ecode = -1; + } + + return ecode; +} + +/* + * end path + */ +static int +opvp_endpath(gx_device_vector *vdev, gx_path_type_t type) +{ + gx_device_opvp *pdev = (gx_device_opvp *)vdev; + opvp_result_t r = -1; + int ecode = 0; + + /* check page-in */ + if (opvp_check_in_page(pdev)) return -1; + + /* call EndPath */ + if (apiEntry->opvpEndPath) { + r = apiEntry->opvpEndPath(printerContext); + } + if (r != OPVP_OK) { + ecode = -1; + } + + if (type & gx_path_type_fill) { + /* fill mode */ + if (type & gx_path_type_even_odd) { + /* call SetFillMode */ + if (apiEntry->opvpSetFillMode) { + r = apiEntry->opvpSetFillMode( + printerContext, + OPVP_FILLMODE_EVENODD + ); + } + if (r != OPVP_OK) { + ecode = -1; + } + } else { + /* call SetFillMode */ + if (apiEntry->opvpSetFillMode) { + r = apiEntry->opvpSetFillMode( + printerContext, + OPVP_FILLMODE_WINDING + ); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + if (type & gx_path_type_stroke) { + /* call StrokeFillPath */ + if (apiEntry->opvpStrokeFillPath) { + r = apiEntry->opvpStrokeFillPath(printerContext); + } + if (r != OPVP_OK) { + ecode = -1; + } + } else { + /* call FillPath */ + if (apiEntry->opvpFillPath) { + r = apiEntry->opvpFillPath(printerContext); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + } else if (type & gx_path_type_clip) { + /* call SetClipPath */ + if (apiEntry->opvpSetClipPath) { + r = apiEntry->opvpSetClipPath( + printerContext, + (type & gx_path_type_even_odd + ? OPVP_CLIPRULE_EVENODD + : OPVP_CLIPRULE_WINDING)); + } + if (r != OPVP_OK) { + ecode = -1; + } + } else if (type & gx_path_type_stroke) { + /* call StrokePath */ + if (apiEntry->opvpStrokePath) { + r = apiEntry->opvpStrokePath(printerContext); + } + if (r != OPVP_OK) { + ecode = -1; + } + } + + return ecode; +} diff --git a/contrib/opvp/opvp.h b/contrib/opvp/opvp.h new file mode 100644 index 000000000..426e8cf74 --- /dev/null +++ b/contrib/opvp/opvp.h @@ -0,0 +1,299 @@ +/* + * OpenPrinting Vector Printer Driver API Definitions [opvp.h] + * + * Copyright (c) 2006 Free Standards Group + * Copyright (c) 2006 Fuji Xerox Printing Systems Co., Ltd. + * Copyright (c) 2006 Canon Inc. + * Copyright (c) 2003-2006 AXE Inc. + * + * All Rights Reserverd. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation. + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + /* + 2007 Modified for OPVP 1.0 by BBR Inc. + */ + +#ifndef _OPVP_H_ +#define _OPVP_H_ + +/* Return Values and Error Codes */ +#define OPVP_OK 0 /* -1 for errors */ +#define OPVP_FATALERROR -1 /* error: cannot be recovered */ +#define OPVP_BADREQUEST -2 /* error: called where it should + not be called */ +#define OPVP_BADCONTEXT -3 /* error: invalid printer context */ +#define OPVP_NOTSUPPORTED -4 /* error: combination of + parameters are set + which cannot be handled + by driver or printer */ +#define OPVP_JOBCANCELED -5 /* error: job has been canceled + by some cause */ +#define OPVP_PARAMERROR -6 /* error: invalid parameter */ +#define OPVP_VERSIONERROR -7 /* error: invalid API version */ + +/* Basic Types */ +typedef int opvp_dc_t; /* driver/device context */ +typedef int opvp_result_t; /* return value */ +typedef unsigned char opvp_byte_t; /* BYTE */ +typedef unsigned char opvp_char_t; /* character (string) */ +typedef int opvp_int_t; /* integer */ +typedef int opvp_fix_t; /* fixed integer */ +typedef float opvp_float_t; /* float */ +typedef unsigned int opvp_flag_t; /* flags */ +typedef unsigned int opvp_rop_t; /* raster operation */ + +/* for opvp_fix_t */ +#define OPVP_FIX_FRACT_WIDTH 8 +#define OPVP_FIX_FRACT_DENOM (1< 0 || _PDAPI_VERSION_MINOR_ >= 2) + int (*QueryDeviceCapability)(int,int,int,char *); + int (*QueryDeviceInfo)(int,int,int,char *); +#endif + int (*ResetCTM)(int); + int (*SetCTM)(int,OPVP_CTM *); + int (*GetCTM)(int,OPVP_CTM *); + int (*InitGS)(int); + int (*SaveGS)(int); + int (*RestoreGS)(int); + int (*QueryColorSpace)(int,OPVP_ColorSpace *,int *); + int (*SetColorSpace)(int,OPVP_ColorSpace); + int (*GetColorSpace)(int,OPVP_ColorSpace *); + int (*QueryROP)(int,int *,int *); + int (*SetROP)(int,int); + int (*GetROP)(int,int *); + int (*SetFillMode)(int,OPVP_FillMode); + int (*GetFillMode)(int,OPVP_FillMode *); + int (*SetAlphaConstant)(int,float); + int (*GetAlphaConstant)(int,float *); + int (*SetLineWidth)(int,OPVP_Fix); + int (*GetLineWidth)(int,OPVP_Fix *); + int (*SetLineDash)(int,OPVP_Fix *,int); + int (*GetLineDash)(int,OPVP_Fix *,int *); + int (*SetLineDashOffset)(int,OPVP_Fix); + int (*GetLineDashOffset)(int,OPVP_Fix *); + int (*SetLineStyle)(int,OPVP_LineStyle); + int (*GetLineStyle)(int,OPVP_LineStyle *); + int (*SetLineCap)(int,OPVP_LineCap); + int (*GetLineCap)(int,OPVP_LineCap *); + int (*SetLineJoin)(int,OPVP_LineJoin); + int (*GetLineJoin)(int,OPVP_LineJoin *); + int (*SetMiterLimit)(int,OPVP_Fix); + int (*GetMiterLimit)(int,OPVP_Fix *); + int (*SetPaintMode)(int,OPVP_PaintMode); + int (*GetPaintMode)(int,OPVP_PaintMode *); + int (*SetStrokeColor)(int,OPVP_Brush *); + int (*SetFillColor)(int,OPVP_Brush *); + int (*SetBgColor)(int,OPVP_Brush *); + int (*NewPath)(int); + int (*EndPath)(int); + int (*StrokePath)(int); + int (*FillPath)(int); + int (*StrokeFillPath)(int); + int (*SetClipPath)(int,OPVP_ClipRule); +#if (_PDAPI_VERSION_MAJOR_ > 0 || _PDAPI_VERSION_MINOR_ >= 2) + int (*ResetClipPath)(int); +#endif + int (*SetCurrentPoint)(int,OPVP_Fix,OPVP_Fix); + int (*LinePath)(int,int,int,OPVP_Point *); + int (*PolygonPath)(int,int,int *,OPVP_Point *); + int (*RectanglePath)(int,int,OPVP_Rectangle *); + int (*RoundRectanglePath)(int,int,OPVP_RoundRectangle *); +#if (_PDAPI_VERSION_MAJOR_ == 0 && _PDAPI_VERSION_MINOR_ < 2) + int (*BezierPath)(int,int *,OPVP_Point *); +#else + int (*BezierPath)(int,int,OPVP_Point *); +#endif + int (*ArcPath)(int,int,int,OPVP_Fix,OPVP_Fix,OPVP_Fix,OPVP_Fix, + OPVP_Fix,OPVP_Fix,OPVP_Fix,OPVP_Fix); + int (*DrawBitmapText)(int,int,int,int,void *); + int (*DrawImage)(int,int,int,int, + OPVP_ImageFormat,OPVP_Rectangle,int,void *); + int (*StartDrawImage)(int,int,int,int, + OPVP_ImageFormat,OPVP_Rectangle); + int (*TransferDrawImage)(int,int,void *); + int (*EndDrawImage)(int); + int (*StartScanline)(int,int); + int (*Scanline)(int,int,int *); + int (*EndScanline)(int); + int (*StartRaster)(int,int); + int (*TransferRasterData)(int,int,unsigned char *); + int (*SkipRaster)(int,int); + int (*EndRaster)(int); + int (*StartStream)(int); + int (*TransferStreamData)(int,int,void *); + int (*EndStream)(int); +} OPVP_api_procs; + +#endif /* _OPVP_COMMON_H_ */ diff --git a/contrib/opvp/opvp_common.h b/contrib/opvp/opvp_common.h new file mode 100644 index 000000000..9161c4bc6 --- /dev/null +++ b/contrib/opvp/opvp_common.h @@ -0,0 +1,53 @@ +/* + +Copyright (c) 2003-2004, AXE, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ +/* OpenPrinting Vector Printer Driver Glue Code */ + +#ifndef _OPVP_COMMON_H_ +#define _OPVP_COMMON_H_ + +#include "opvp_0_2_0.h" +#undef _PDAPI_VERSION_MAJOR_ +#undef _PDAPI_VERSION_MINOR_ +/* undefine conflicted macros */ +#undef OPVP_INFO_PREFIX +#undef OPVP_OK +#undef OPVP_FATALERROR +#undef OPVP_BADREQUEST +#undef OPVP_BADCONTEXT +#undef OPVP_NOTSUPPORTED +#undef OPVP_JOBCANCELED +#undef OPVP_PARAMERROR +/* define 0_2 error no as different macros */ +#define OPVP_FATALERROR_0_2 -101 +#define OPVP_BADREQUEST_0_2 -102 +#define OPVP_BADCONTEXT_0_2 -103 +#define OPVP_NOTSUPPORTED_0_2 -104 +#define OPVP_JOBCANCELED_0_2 -105 +#define OPVP_PARAMERROR_0_2 -106 + +#include "opvp.h" +#define OPVP_INFO_PREFIX "" + +#endif /* _OPVP_COMMON_H_ */ diff --git a/contrib/opvp/opvp_media.def b/contrib/opvp/opvp_media.def new file mode 100644 index 000000000..33fb81db6 --- /dev/null +++ b/contrib/opvp/opvp_media.def @@ -0,0 +1,166 @@ +/* $Id: opvp_media.def 74 2005-06-10 16:53:36Z gishi $ */ +{"iso" ,"a10" , 26/MMPI*PS_DPI, 37/MMPI*PS_DPI}, +{"iso" ,"c10" , 28/MMPI*PS_DPI, 40/MMPI*PS_DPI}, +{"iso" ,"b10" , 31/MMPI*PS_DPI, 44/MMPI*PS_DPI}, +{"jis" ,"b10" , 32/MMPI*PS_DPI, 45/MMPI*PS_DPI}, +{"iso" ,"a9" , 37/MMPI*PS_DPI, 52/MMPI*PS_DPI}, +{"iso" ,"c9" , 40/MMPI*PS_DPI, 57/MMPI*PS_DPI}, +{"iso" ,"b9" , 44/MMPI*PS_DPI, 62/MMPI*PS_DPI}, +{"jis" ,"b9" , 45/MMPI*PS_DPI, 64/MMPI*PS_DPI}, +{"iso" ,"a8" , 52/MMPI*PS_DPI, 74/MMPI*PS_DPI}, +{"iso" ,"c8" , 57/MMPI*PS_DPI, 81/MMPI*PS_DPI}, +{"iso" ,"b8" , 62/MMPI*PS_DPI, 88/MMPI*PS_DPI}, +{"jis" ,"b8" , 64/MMPI*PS_DPI, 91/MMPI*PS_DPI}, +{"iso" ,"a7" , 74/MMPI*PS_DPI, 105/MMPI*PS_DPI}, +{"na" ,"index-3x5" , 3*PS_DPI, 5*PS_DPI},/*76.2x127*/ +{"iso" ,"c7" , 81/MMPI*PS_DPI, 114/MMPI*PS_DPI}, +{"iso" ,"c7c6" , 81/MMPI*PS_DPI, 162/MMPI*PS_DPI}, +{"iso" ,"b7" , 88/MMPI*PS_DPI, 125/MMPI*PS_DPI}, +{"jpn" ,"chou4" , 90/MMPI*PS_DPI, 205/MMPI*PS_DPI}, +{"jis" ,"b7" , 91/MMPI*PS_DPI, 128/MMPI*PS_DPI}, +{"na" ,"personal" , 3.625*PS_DPI, 6.5*PS_DPI},/*92.075x165.1*/ +{"prc" ,"32k" , 97/MMPI*PS_DPI, 151/MMPI*PS_DPI}, +{"na" ,"monarch" , 3.875*PS_DPI, 7.5*PS_DPI},/*98.425x190.5*/ +{"na" ,"number-9" , 3.875*PS_DPI, 8.875*PS_DPI},/*98.425x225.425*/ +{"jpn" ,"hagaki" , 100/MMPI*PS_DPI, 148/MMPI*PS_DPI}, +{"om" ,"small-photo" , 100/MMPI*PS_DPI, 150/MMPI*PS_DPI}, +{"om" ,"italian" , 100/MMPI*PS_DPI, 230/MMPI*PS_DPI}, +{"na" ,"index-4x6" , 4*PS_DPI, 6*PS_DPI},/*101.6x152.4*/ +{"prc" ,"1" , 102/MMPI*PS_DPI, 165/MMPI*PS_DPI}, +{"prc" ,"2" , 102/MMPI*PS_DPI, 176/MMPI*PS_DPI}, +{"na" ,"number-10" , 4.125*PS_DPI, 9.5*PS_DPI},/*104.775x241.3*/ +{"iso" ,"a6" , 105/MMPI*PS_DPI, 148/MMPI*PS_DPI}, +{"jpn" ,"you4" , 105/MMPI*PS_DPI, 235/MMPI*PS_DPI}, +{"prc" ,"4" , 110/MMPI*PS_DPI, 208/MMPI*PS_DPI}, +{"iso" ,"dl" , 110/MMPI*PS_DPI, 220/MMPI*PS_DPI}, +{"prc" ,"5" , 110/MMPI*PS_DPI, 220/MMPI*PS_DPI}, +{"jpn" ,"chou2" ,111.1/MMPI*PS_DPI, 146/MMPI*PS_DPI}, +{"na" ,"a2" , 4.375*PS_DPI, 5.75*PS_DPI},/*111.125x146.05*/ +{"iso" ,"c6" , 114/MMPI*PS_DPI, 162/MMPI*PS_DPI}, +{"iso" ,"c6c5" , 114/MMPI*PS_DPI, 229/MMPI*PS_DPI}, +{"om" ,"postfix" , 114/MMPI*PS_DPI, 229/MMPI*PS_DPI}, +{"na" ,"number-11" , 4.5*PS_DPI, 10.375*PS_DPI},/*114.3x263.525*/ +{"jpn" ,"chou3" , 120/MMPI*PS_DPI, 235/MMPI*PS_DPI}, +{"prc" ,"8" , 120/MMPI*PS_DPI, 309/MMPI*PS_DPI}, +{"prc" ,"6" , 120/MMPI*PS_DPI, 320/MMPI*PS_DPI}, +{"na" ,"number-12" , 4.75*PS_DPI, 11*PS_DPI},/*120.65x279.4*/ +{"iso" ,"b6" , 125/MMPI*PS_DPI, 176/MMPI*PS_DPI}, +{"prc" ,"3" , 125/MMPI*PS_DPI, 176/MMPI*PS_DPI}, +{"iso" ,"b6c4" , 125/MMPI*PS_DPI, 324/MMPI*PS_DPI}, +{"na" ,"5x7" , 5*PS_DPI, 7*PS_DPI},/*127x177.8*/ +{"na" ,"index-5x8" , 5*PS_DPI, 8*PS_DPI},/*127x203.2*/ +{"na" ,"number-14" , 5*PS_DPI, 11.5*PS_DPI},/*127x292.1*/ +{"jis" ,"b6" , 128/MMPI*PS_DPI, 182/MMPI*PS_DPI}, +{"na" ,"invoice" , 5.5*PS_DPI, 8.5*PS_DPI},/*139.7x215.9*/ +{"prc" ,"16k" , 146/MMPI*PS_DPI, 215/MMPI*PS_DPI}, +{"jpn" ,"oufuku" , 148/MMPI*PS_DPI, 200/MMPI*PS_DPI}, +{"iso" ,"a5" , 148/MMPI*PS_DPI, 210/MMPI*PS_DPI}, +{"na" ,"index-4x6-ext", 6*PS_DPI, 8*PS_DPI},/*152.4x203.2*/ +{"na" ,"6x9" , 6*PS_DPI, 9*PS_DPI},/*152.4x228.6*/ +{"prc" ,"7" , 160/MMPI*PS_DPI, 230/MMPI*PS_DPI}, +{"iso" ,"c5" , 162/MMPI*PS_DPI, 229/MMPI*PS_DPI}, +{"na" ,"c5" , 6.5*PS_DPI, 9.5*PS_DPI},/*165.1x241.3*/ +{"iso" ,"a5-extra" , 174/MMPI*PS_DPI, 235/MMPI*PS_DPI}, +{"iso" ,"b5" , 176/MMPI*PS_DPI, 250/MMPI*PS_DPI}, +{"na" ,"7x9" , 7*PS_DPI, 9*PS_DPI},/*177.8x228.6*/ +{"jis" ,"b5" , 182/MMPI*PS_DPI, 257/MMPI*PS_DPI}, +{"na" ,"executive" , 7.25*PS_DPI, 10.5*PS_DPI},/*184.15x266.7*/ +{"roc" ,"16k" , 7.75*PS_DPI, 10.75*PS_DPI},/*196.85x273.05*/ +{"om" ,"juuro-ku-kai" , 198/MMPI*PS_DPI, 275/MMPI*PS_DPI}, +{"om" ,"large-photo" , 200/MMPI*PS_DPI, 300/MMPI*PS_DPI}, +{"iso" ,"b5-extra" , 201/MMPI*PS_DPI, 276/MMPI*PS_DPI}, +{"na" ,"govt-letter" , 8*PS_DPI, 10*PS_DPI},/*203.2x254*/ +{"na" ,"govt-legal" , 8*PS_DPI, 13*PS_DPI},/*203.2x330.2*/ +{"iso" ,"a4" , 210/MMPI*PS_DPI, 297/MMPI*PS_DPI}, +{"om" ,"folio" , 210/MMPI*PS_DPI, 330/MMPI*PS_DPI}, +{"om" ,"folio-sp" , 215/MMPI*PS_DPI, 315/MMPI*PS_DPI}, +{"na" ,"quarto" , 8.5*PS_DPI, 10.83*PS_DPI},/*215.9x275.082*/ +{"na" ,"letter" , 8.5*PS_DPI, 11*PS_DPI},/*215.9x279.4*/ +{"na" ,"fanfold-eur" , 8.5*PS_DPI, 12*PS_DPI},/*215.9x304.8*/ +{"na" ,"letter-plus" , 8.5*PS_DPI, 12.69*PS_DPI},/*215.9x322.326*/ +{"na" ,"foolscap" , 8.5*PS_DPI, 13*PS_DPI},/*215.9x330.2*/ +{"na" ,"legal" , 8.5*PS_DPI, 14*PS_DPI},/*215.9x355.6*/ +{"jis" ,"exec" , 216/MMPI*PS_DPI, 330/MMPI*PS_DPI}, +{"om" ,"invite" , 220/MMPI*PS_DPI, 220/MMPI*PS_DPI}, +{"iso" ,"a4-tab" , 225/MMPI*PS_DPI, 297/MMPI*PS_DPI}, +{"na" ,"super-a" , 8.94*PS_DPI, 14*PS_DPI},/*227.076x355.6*/ +{"na" ,"9x11" , 9*PS_DPI, 11*PS_DPI},/*228.6x279.4*/ +{"na" ,"arch-a" , 9*PS_DPI, 12*PS_DPI},/*228.6x304.8*/ +{"iso" ,"c4" , 229/MMPI*PS_DPI, 324/MMPI*PS_DPI}, +{"iso" ,"a4-extra" ,235.5/MMPI*PS_DPI,322.3/MMPI*PS_DPI}, +{"jpn" ,"kahu" , 240/MMPI*PS_DPI,322.1/MMPI*PS_DPI}, +{"jpn" ,"kaku2" , 240/MMPI*PS_DPI, 332/MMPI*PS_DPI}, +{"na" ,"letter-extra" , 9.5*PS_DPI, 12*PS_DPI},/*241.3x304.8*/ +{"na" ,"legal-extra" , 9.5*PS_DPI, 15*PS_DPI},/*241.3x381*/ +{"iso" ,"b4" , 250/MMPI*PS_DPI, 353/MMPI*PS_DPI}, +{"na" ,"10x11" , 10*PS_DPI, 11*PS_DPI},/*254x279.4*/ +{"na" ,"10x13" , 10*PS_DPI, 13*PS_DPI},/*254x330.2*/ +{"na" ,"10x14" , 10*PS_DPI, 14*PS_DPI},/*254x355.6*/ +{"na" ,"10x15" , 10*PS_DPI, 15*PS_DPI},/*254x381*/ +{"jis" ,"b4" , 257/MMPI*PS_DPI, 364/MMPI*PS_DPI}, +{"om" ,"pa-kai" , 267/MMPI*PS_DPI, 389/MMPI*PS_DPI}, +{"roc" ,"8k" , 10.75*PS_DPI, 15.5*PS_DPI},/*273.05x393.7*/ +{"om" ,"dai-pa-kai" , 275/MMPI*PS_DPI, 395/MMPI*PS_DPI}, +{"na" ,"11x12" , 11*PS_DPI, 12*PS_DPI},/*279.4x304.8*/ +{"na" ,"edp" , 11*PS_DPI, 14*PS_DPI},/*279.4x355.6*/ +{"na" ,"fanfold-us" , 11*PS_DPI, 14.875*PS_DPI},/*279.4x377.825*/ +{"na" ,"11x15" , 11*PS_DPI, 15*PS_DPI},/*279.4x381*/ +{"na" ,"ledger" , 11*PS_DPI, 17*PS_DPI},/*279.4x431.8*/ +{"iso" ,"a3" , 297/MMPI*PS_DPI, 420/MMPI*PS_DPI}, +{"iso" ,"a4x3" , 297/MMPI*PS_DPI, 630/MMPI*PS_DPI}, +{"iso" ,"a4x4" , 297/MMPI*PS_DPI, 841/MMPI*PS_DPI}, +{"iso" ,"a4x5" , 297/MMPI*PS_DPI, 1051/MMPI*PS_DPI}, +{"iso" ,"a4x6" , 297/MMPI*PS_DPI, 1261/MMPI*PS_DPI}, +{"iso" ,"a4x7" , 297/MMPI*PS_DPI, 1471/MMPI*PS_DPI}, +{"iso" ,"a4x8" , 297/MMPI*PS_DPI, 1682/MMPI*PS_DPI}, +{"iso" ,"a4x9" , 297/MMPI*PS_DPI, 1892/MMPI*PS_DPI}, +{"na" ,"eur-edp" , 12*PS_DPI, 14*PS_DPI},/*304.8x355.6*/ +{"na" ,"arch-b" , 12*PS_DPI, 18*PS_DPI},/*304.8x457.2*/ +{"na" ,"12x19" , 12*PS_DPI, 19*PS_DPI},/*304.8x482.6*/ +{"na" ,"b-plus" , 12*PS_DPI, 19.17*PS_DPI},/*304.8x486.918*/ +{"iso" ,"a3-extra" , 322/MMPI*PS_DPI, 445/MMPI*PS_DPI}, +{"iso" ,"c3" , 324/MMPI*PS_DPI, 458/MMPI*PS_DPI}, +{"prc" ,"10" , 324/MMPI*PS_DPI, 458/MMPI*PS_DPI}, +{"na" ,"super-b" , 13*PS_DPI, 19*PS_DPI},/*330.2x482.6*/ +{"iso" ,"b3" , 353/MMPI*PS_DPI, 500/MMPI*PS_DPI}, +{"jis" ,"b3" , 364/MMPI*PS_DPI, 515/MMPI*PS_DPI}, +{"iso" ,"a2" , 420/MMPI*PS_DPI, 594/MMPI*PS_DPI}, +{"iso" ,"a3x3" , 420/MMPI*PS_DPI, 891/MMPI*PS_DPI}, +{"iso" ,"a3x4" , 420/MMPI*PS_DPI, 1189/MMPI*PS_DPI}, +{"iso" ,"a3x5" , 420/MMPI*PS_DPI, 1486/MMPI*PS_DPI}, +{"iso" ,"a3x6" , 420/MMPI*PS_DPI, 1783/MMPI*PS_DPI}, +{"iso" ,"a3x7" , 420/MMPI*PS_DPI, 2080/MMPI*PS_DPI}, +{"iso" ,"ra2" , 430/MMPI*PS_DPI, 610/MMPI*PS_DPI}, +{"na" ,"c" , 17*PS_DPI, 22*PS_DPI},/*431.8x558.8*/ +{"iso" ,"sra2" , 450/MMPI*PS_DPI, 640/MMPI*PS_DPI}, +{"na" ,"arch-c" , 18*PS_DPI, 24*PS_DPI},/*457.2x609.6*/ +{"iso" ,"c2" , 458/MMPI*PS_DPI, 648/MMPI*PS_DPI}, +{"iso" ,"b2" , 500/MMPI*PS_DPI, 707/MMPI*PS_DPI}, +{"jis" ,"b2" , 515/MMPI*PS_DPI, 728/MMPI*PS_DPI}, +{"na" ,"d" , 22*PS_DPI, 34*PS_DPI},/*558.8x863.6*/ +{"iso" ,"a1" , 594/MMPI*PS_DPI, 841/MMPI*PS_DPI}, +{"iso" ,"a2x3" , 594/MMPI*PS_DPI, 1261/MMPI*PS_DPI}, +{"iso" ,"a2x4" , 594/MMPI*PS_DPI, 1682/MMPI*PS_DPI}, +{"iso" ,"a2x5" , 594/MMPI*PS_DPI, 2102/MMPI*PS_DPI}, +{"na" ,"arch-d" , 24*PS_DPI, 36*PS_DPI},/*609.6x914.4*/ +{"iso" ,"ra1" , 610/MMPI*PS_DPI, 860/MMPI*PS_DPI}, +{"iso" ,"sra1" , 640/MMPI*PS_DPI, 900/MMPI*PS_DPI}, +{"iso" ,"c1" , 648/MMPI*PS_DPI, 917/MMPI*PS_DPI}, +{"iso" ,"b1" , 707/MMPI*PS_DPI, 1000/MMPI*PS_DPI}, +{"asme","f" , 28*PS_DPI, 40*PS_DPI},/*711.2x1016*/ +{"jis" ,"b1" , 728/MMPI*PS_DPI, 1030/MMPI*PS_DPI}, +{"na" ,"wide-format" , 30*PS_DPI, 42*PS_DPI},/*762x1066.8*/ +{"iso" ,"a0" , 841/MMPI*PS_DPI, 1189/MMPI*PS_DPI}, +{"iso" ,"a1x3" , 841/MMPI*PS_DPI, 1783/MMPI*PS_DPI}, +{"iso" ,"a1x4" , 841/MMPI*PS_DPI, 2378/MMPI*PS_DPI}, +{"iso" ,"ra0" , 860/MMPI*PS_DPI, 1220/MMPI*PS_DPI}, +{"na" ,"e" , 34*PS_DPI, 44*PS_DPI},/*863.6x1117.6*/ +{"iso" ,"sra0" , 900/MMPI*PS_DPI, 1280/MMPI*PS_DPI}, +{"na" ,"arch-e" , 36*PS_DPI, 48*PS_DPI},/*914.4x1219.2*/ +{"iso" ,"c0" , 917/MMPI*PS_DPI, 1297/MMPI*PS_DPI}, +{"iso" ,"b0" , 1000/MMPI*PS_DPI, 1414/MMPI*PS_DPI}, +{"jis" ,"b0" , 1030/MMPI*PS_DPI, 1456/MMPI*PS_DPI}, +{"na" ,"f" , 44*PS_DPI, 68*PS_DPI},/*1117.6x1727.2*/ +{"iso" ,"2a0" , 1189/MMPI*PS_DPI, 1682/MMPI*PS_DPI}, +{"iso" ,"a0x3" , 1189/MMPI*PS_DPI, 2523/MMPI*PS_DPI}, +{"iso" ,"4a0" , 1682/MMPI*PS_DPI, 2378/MMPI*PS_DPI}, -- cgit v1.2.1