summaryrefslogtreecommitdiff
path: root/contrib/opvp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/opvp')
-rw-r--r--contrib/opvp/gdevopvp.c5406
-rw-r--r--contrib/opvp/opvp.h299
-rw-r--r--contrib/opvp/opvp_0_2_0.h298
-rw-r--r--contrib/opvp/opvp_common.h53
-rw-r--r--contrib/opvp/opvp_media.def166
5 files changed, 6222 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Set compatibility flag just in case we have GNU iconv.h */
+#ifndef USE_LIBICONV_GNU
+# define LIBICONV_PLUG
+#endif
+#include <iconv.h>
+
+#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<m ? (c<y ? c : y) : (m<y ? m : y));
+ c -= k;
+ m -= k;
+ y -= k;
+ } else {
+ k = 0;
+ }
+ return (k + (y << 8) + (m << 16) + (c << 24));
+ break;
+ case OPVP_CSPACE_DEVICEGRAY:
+#if GS_VERSION_MAJOR >= 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<<OPVP_FIX_FRACT_WIDTH)
+#define OPVP_FIX_FLOOR_WIDTH (sizeof(int)*8-OPVP_FIX_FRACT_WIDTH)
+
+/* convert macro */
+#define OPVP_I2FIX(i,fix) (fix=i<<OPVP_FIX_FRACT_WIDTH)
+#define OPVP_F2FIX(f,fix) (fix=((int)floor(f)<<OPVP_FIX_FRACT_WIDTH)\
+ |((int)((f-floor(f))*OPVP_FIX_FRACT_DENOM)\
+ &(OPVP_FIX_FRACT_DENOM-1)))
+
+/* graphic elements */
+typedef struct _opvp_point {
+ opvp_fix_t x, y;
+} opvp_point_t;
+
+typedef struct _opvp_rectangle {
+ opvp_point_t p0; /* start point */
+ opvp_point_t p1; /* diagonal point */
+} opvp_rectangle_t;
+
+typedef struct _opvp_roundrectangle {
+ opvp_point_t p0; /* start point */
+ opvp_point_t p1; /* diagonal point */
+ opvp_fix_t xellipse, yellipse;
+} opvp_roundrectangle_t;
+
+/* Image Formats */
+typedef enum _opvp_imageformat {
+ OPVP_IFORMAT_RAW = 0,
+ OPVP_IFORMAT_MASK = 1,
+ OPVP_IFORMAT_RLE = 2,
+ OPVP_IFORMAT_JPEG = 3,
+ OPVP_IFORMAT_PNG = 4
+} opvp_imageformat_t;
+
+/* Color Presentation */
+typedef enum _opvp_colormapping {
+ OPVP_CMAP_DIRECT = 0,
+ OPVP_CMAP_INDEXED = 1
+} opvp_colormapping_t;
+
+typedef enum _opvp_cspace {
+ OPVP_CSPACE_BW = 0,
+ OPVP_CSPACE_DEVICEGRAY = 1,
+ OPVP_CSPACE_DEVICECMY = 2,
+ OPVP_CSPACE_DEVICECMYK = 3,
+ OPVP_CSPACE_DEVICERGB = 4,
+ OPVP_CSPACE_DEVICEKRGB = 5,
+ OPVP_CSPACE_STANDARDRGB = 6,
+ OPVP_CSPACE_STANDARDRGB64 = 7
+} opvp_cspace_t;
+
+/* Fill, Paint, Clip */
+typedef enum _opvp_fillmode {
+ OPVP_FILLMODE_EVENODD = 0,
+ OPVP_FILLMODE_WINDING = 1
+} opvp_fillmode_t;
+
+typedef enum _opvp_paintmode {
+ OPVP_PAINTMODE_OPAQUE = 0,
+ OPVP_PAINTMODE_TRANSPARENT = 1
+} opvp_paintmode_t;
+
+typedef enum _opvp_cliprule {
+ OPVP_CLIPRULE_EVENODD = 0,
+ OPVP_CLIPRULE_WINDING = 1
+} opvp_cliprule_t;
+
+/* Line */
+typedef enum _opvp_linestyle {
+ OPVP_LINESTYLE_SOLID = 0,
+ OPVP_LINESTYLE_DASH = 1
+} opvp_linestyle_t;
+
+typedef enum _opvp_linecap {
+ OPVP_LINECAP_BUTT = 0,
+ OPVP_LINECAP_ROUND = 1,
+ OPVP_LINECAP_SQUARE = 2
+} opvp_linecap_t;
+
+typedef enum _opvp_linejoin {
+ OPVP_LINEJOIN_MITER = 0,
+ OPVP_LINEJOIN_ROUND = 1,
+ OPVP_LINEJOIN_BEVEL = 2
+} opvp_linejoin_t;
+
+/* Brush */
+typedef enum _opvp_bdtype {
+ OPVP_BDTYPE_NORMAL = 0
+} opvp_bdtype_t;
+
+typedef struct _opvp_brushdata {
+ opvp_bdtype_t type;
+ opvp_int_t width, height, pitch;
+#if defined(__GNUC__) && __GNUC__ <= 2
+ opvp_byte_t data[1];
+#elif defined(__SUNPRO_C)
+ opvp_byte_t data[1];
+#elif defined(__HP_cc)
+ opvp_byte_t data[1];
+#else
+ opvp_byte_t data[];
+#endif
+
+} opvp_brushdata_t;
+
+typedef struct _opvp_brush {
+ opvp_cspace_t colorSpace;
+ opvp_int_t color[4]; /* aRGB quadruplet */
+ opvp_int_t xorg, yorg; /* brush origin */
+ /* ignored for opvpSetBgColor */
+ opvp_brushdata_t *pbrush; /* pointer to brush data */
+ /* solid brush used, if NULL */
+} opvp_brush_t;
+
+/* Misc. Flags */
+typedef enum _opvp_arcmode {
+ OPVP_ARC = 0,
+ OPVP_CHORD = 1,
+ OPVP_PIE = 2
+} opvp_arcmode_t;
+
+typedef enum _opvp_arcdir {
+ OPVP_CLOCKWISE = 0,
+ OPVP_COUNTERCLOCKWISE = 1
+} opvp_arcdir_t;
+
+typedef enum _opvp_pathmode {
+ OPVP_PATHCLOSE = 0,
+ OPVP_PATHOPEN = 1
+} opvp_pathmode_t;
+
+/* CTM */
+typedef struct _opvp_ctm {
+ opvp_float_t a, b, c, d, e, f;
+} opvp_ctm_t;
+
+/* Device Information and Capabilites */
+typedef enum _opvp_queryinfoflags {
+ OPVP_QF_DEVICERESOLUTION = 0x00000001,
+ OPVP_QF_MEDIASIZE = 0x00000002,
+ OPVP_QF_PAGEROTATION = 0x00000004,
+ OPVP_QF_MEDIANUP = 0x00000008,
+ OPVP_QF_MEDIADUPLEX = 0x00000010,
+ OPVP_QF_MEDIASOURCE = 0x00000020,
+ OPVP_QF_MEDIADESTINATION = 0x00000040,
+ OPVP_QF_MEDIATYPE = 0x00000080,
+ OPVP_QF_MEDIACOPY = 0x00000100, /* Maximum copy number
+ supported */
+ OPVP_QF_PRINTREGION = 0x00010000 /* only for opvpQueryDeviceInfo */
+} opvp_queryinfoflags_t;
+
+/* API Procedure Entries */
+typedef struct _opvp_api_procs {
+ opvp_dc_t (*opvpOpenPrinter)(opvp_int_t,const opvp_char_t*,const opvp_int_t[2],struct _opvp_api_procs**);
+ opvp_result_t (*opvpClosePrinter)(opvp_dc_t);
+ opvp_result_t (*opvpStartJob)(opvp_dc_t,const opvp_char_t*);
+ opvp_result_t (*opvpEndJob)(opvp_dc_t);
+ opvp_result_t (*opvpAbortJob)(opvp_dc_t);
+ opvp_result_t (*opvpStartDoc)(opvp_dc_t,const opvp_char_t*);
+ opvp_result_t (*opvpEndDoc)(opvp_dc_t);
+ opvp_result_t (*opvpStartPage)(opvp_dc_t,const opvp_char_t*);
+ opvp_result_t (*opvpEndPage)(opvp_dc_t);
+ opvp_result_t (*opvpQueryDeviceCapability)(opvp_dc_t,opvp_flag_t,opvp_int_t*,opvp_byte_t*);
+ opvp_result_t (*opvpQueryDeviceInfo)(opvp_dc_t,opvp_flag_t,opvp_int_t*,opvp_char_t*);
+ opvp_result_t (*opvpResetCTM)(opvp_dc_t);
+ opvp_result_t (*opvpSetCTM)(opvp_dc_t,const opvp_ctm_t*);
+ opvp_result_t (*opvpGetCTM)(opvp_dc_t,opvp_ctm_t*);
+ opvp_result_t (*opvpInitGS)(opvp_dc_t);
+ opvp_result_t (*opvpSaveGS)(opvp_dc_t);
+ opvp_result_t (*opvpRestoreGS)(opvp_dc_t);
+ opvp_result_t (*opvpQueryColorSpace)(opvp_dc_t,opvp_int_t*,opvp_cspace_t*);
+ opvp_result_t (*opvpSetColorSpace)(opvp_dc_t,opvp_cspace_t);
+ opvp_result_t (*opvpGetColorSpace)(opvp_dc_t,opvp_cspace_t*);
+ opvp_result_t (*opvpSetFillMode)(opvp_dc_t,opvp_fillmode_t);
+ opvp_result_t (*opvpGetFillMode)(opvp_dc_t,opvp_fillmode_t*);
+ opvp_result_t (*opvpSetAlphaConstant)(opvp_dc_t,opvp_float_t);
+ opvp_result_t (*opvpGetAlphaConstant)(opvp_dc_t,opvp_float_t*);
+ opvp_result_t (*opvpSetLineWidth)(opvp_dc_t,opvp_fix_t);
+ opvp_result_t (*opvpGetLineWidth)(opvp_dc_t,opvp_fix_t*);
+ opvp_result_t (*opvpSetLineDash)(opvp_dc_t,opvp_int_t,const opvp_fix_t*);
+ opvp_result_t (*opvpGetLineDash)(opvp_dc_t,opvp_int_t*,opvp_fix_t*);
+ opvp_result_t (*opvpSetLineDashOffset)(opvp_dc_t,opvp_fix_t);
+ opvp_result_t (*opvpGetLineDashOffset)(opvp_dc_t,opvp_fix_t*);
+ opvp_result_t (*opvpSetLineStyle)(opvp_dc_t,opvp_linestyle_t);
+ opvp_result_t (*opvpGetLineStyle)(opvp_dc_t,opvp_linestyle_t*);
+ opvp_result_t (*opvpSetLineCap)(opvp_dc_t,opvp_linecap_t);
+ opvp_result_t (*opvpGetLineCap)(opvp_dc_t,opvp_linecap_t*);
+ opvp_result_t (*opvpSetLineJoin)(opvp_dc_t,opvp_linejoin_t);
+ opvp_result_t (*opvpGetLineJoin)(opvp_dc_t,opvp_linejoin_t*);
+ opvp_result_t (*opvpSetMiterLimit)(opvp_dc_t,opvp_fix_t);
+ opvp_result_t (*opvpGetMiterLimit)(opvp_dc_t,opvp_fix_t*);
+ opvp_result_t (*opvpSetPaintMode)(opvp_dc_t,opvp_paintmode_t);
+ opvp_result_t (*opvpGetPaintMode)(opvp_dc_t,opvp_paintmode_t*);
+ opvp_result_t (*opvpSetStrokeColor)(opvp_dc_t,const opvp_brush_t*);
+ opvp_result_t (*opvpSetFillColor)(opvp_dc_t,const opvp_brush_t*);
+ opvp_result_t (*opvpSetBgColor)(opvp_dc_t,const opvp_brush_t*);
+ opvp_result_t (*opvpNewPath)(opvp_dc_t);
+ opvp_result_t (*opvpEndPath)(opvp_dc_t);
+ opvp_result_t (*opvpStrokePath)(opvp_dc_t);
+ opvp_result_t (*opvpFillPath)(opvp_dc_t);
+ opvp_result_t (*opvpStrokeFillPath)(opvp_dc_t);
+ opvp_result_t (*opvpSetClipPath)(opvp_dc_t,opvp_cliprule_t);
+ opvp_result_t (*opvpResetClipPath)(opvp_dc_t);
+ opvp_result_t (*opvpSetCurrentPoint)(opvp_dc_t,opvp_fix_t,opvp_fix_t);
+ opvp_result_t (*opvpLinePath)(opvp_dc_t,opvp_pathmode_t,opvp_int_t,const opvp_point_t*);
+ opvp_result_t (*opvpPolygonPath)(opvp_dc_t,opvp_int_t,const opvp_int_t*,const opvp_point_t*);
+ opvp_result_t (*opvpRectanglePath)(opvp_dc_t,opvp_int_t,const opvp_rectangle_t*);
+ opvp_result_t (*opvpRoundRectanglePath)(opvp_dc_t,opvp_int_t,const opvp_roundrectangle_t*);
+ opvp_result_t (*opvpBezierPath)(opvp_dc_t,opvp_int_t,const opvp_point_t*);
+ opvp_result_t (*opvpArcPath)(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);
+ opvp_result_t (*opvpDrawImage)(opvp_dc_t,opvp_int_t,opvp_int_t,opvp_int_t,opvp_imageformat_t,opvp_int_t, opvp_int_t ,const void*);
+ opvp_result_t (*opvpStartDrawImage)(opvp_dc_t,opvp_int_t,opvp_int_t,opvp_int_t,opvp_imageformat_t,opvp_int_t, opvp_int_t);
+ opvp_result_t (*opvpTransferDrawImage)(opvp_dc_t,opvp_int_t,const void*);
+ opvp_result_t (*opvpEndDrawImage)(opvp_dc_t);
+ opvp_result_t (*opvpStartScanline)(opvp_dc_t,opvp_int_t);
+ opvp_result_t (*opvpScanline)(opvp_dc_t,opvp_int_t,const opvp_int_t*);
+ opvp_result_t (*opvpEndScanline)(opvp_dc_t);
+ opvp_result_t (*opvpStartRaster)(opvp_dc_t,opvp_int_t);
+ opvp_result_t (*opvpTransferRasterData)(opvp_dc_t,opvp_int_t,const opvp_byte_t*);
+ opvp_result_t (*opvpSkipRaster)(opvp_dc_t,opvp_int_t);
+ opvp_result_t (*opvpEndRaster)(opvp_dc_t);
+ opvp_result_t (*opvpStartStream)(opvp_dc_t);
+ opvp_result_t (*opvpTransferStreamData)(opvp_dc_t,opvp_int_t,const void*);
+ opvp_result_t (*opvpEndStream)(opvp_dc_t);
+} opvp_api_procs_t;
+
+/* Function prototype */
+opvp_dc_t opvpOpenPrinter(
+ opvp_int_t outputFD,
+ const opvp_char_t *printerModel,
+ const opvp_int_t apiVersion[2],
+ opvp_api_procs_t **apiProcs);
+
+/* error no */
+extern opvp_int_t opvpErrorNo;
+
+#endif /* _OPVP_H_ */
diff --git a/contrib/opvp/opvp_0_2_0.h b/contrib/opvp/opvp_0_2_0.h
new file mode 100644
index 000000000..6030971a3
--- /dev/null
+++ b/contrib/opvp/opvp_0_2_0.h
@@ -0,0 +1,298 @@
+/*
+
+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.
+
+*/
+/* $Id: opvp_0_2_0.h 85 2007-02-15 08:48:56Z sho-otani $ */
+/* opvp_common.h ver.1.00 rel.1.0 26 Nov 2004 */
+/* OpenPrinting Vector Printer Driver Glue Code */
+
+#ifndef _FSGPD_0_2_0_H
+#define _FSGPD_0_2_0_H
+
+#define _PDAPI_VERSION_MAJOR_ 0
+#define _PDAPI_VERSION_MINOR_ 2
+
+/* Return Values */
+#define OPVP_OK 0 /* error is -1 */
+
+/* Error Codes */
+#define OPVP_FATALERROR -101 /* unrecoverable error occurred within the */
+ /* library */
+#define OPVP_BADREQUEST -102 /* invalid function parameters */
+#define OPVP_BADCONTEXT -103 /* bad parameter precontext */
+#define OPVP_NOTSUPPORTED -104 /* printer or driver request not supported */
+#define OPVP_JOBCANCELED -105 /* job cancelled */
+#define OPVP_PARAMERROR -106 /* illegal parameter combination */
+
+/* Info params */
+#define OPVP_INFO_PREFIX "updf:"
+
+/* Fix */
+#define OPVP_FIX_FRACT_WIDTH 8
+#define OPVP_FIX_FRACT_DENOM (1<<OPVP_FIX_FRACT_WIDTH)
+#define OPVP_FIX_FLOOR_WIDTH (sizeof(int)*8-OPVP_FIX_FRACT_WIDTH)
+#if 0
+typedef struct {
+ unsigned int fract : OPVP_FIX_FRACT_WIDTH;
+ signed int floor : OPVP_FIX_FLOOR_WIDTH;
+} OPVP_Fix;
+#define OPVP_i2Fix(i,fix) (fix.fract=0,fix.floor=i)
+#define OPVP_Fix2f(fix,f) (f=(double)fix.floor\
+ +(double)(fix.fract)/OPVP_FIX_FRACT_DENOM)
+#define OPVP_f2Fix(f,fix) (fix.fract=(f-floor(f))*OPVP_FIX_FRACT_DENOM,\
+ fix.floor=floor(f))
+#else
+typedef int OPVP_Fix;
+#define OPVP_i2Fix(i,fix) (fix=i<<8)
+#define OPVP_f2Fix(f,fix) (fix=((int)floor(f)<<8)\
+ |((int)((f-floor(f))*OPVP_FIX_FRACT_DENOM)\
+ &0x000000ff))
+#endif
+
+/* Basic Types */
+typedef struct _OPVP_Point {
+ OPVP_Fix x;
+ OPVP_Fix y;
+} OPVP_Point;
+
+typedef struct _OPVP_Rectangle {
+ OPVP_Point p0; /* start point */
+ OPVP_Point p1; /* end point */
+} OPVP_Rectangle;
+
+typedef struct _OPVP_RoundRectangle {
+ OPVP_Point p0; /* start point */
+ OPVP_Point p1; /* end point */
+ OPVP_Fix xellipse;
+ OPVP_Fix yellipse;
+} OPVP_RoundRectangle;
+
+/* Image Formats */
+typedef enum _OPVP_ImageFormat {
+ OPVP_iformatRaw = 0,
+ OPVP_iformatRLE = 1,
+ OPVP_iformatJPEG = 2,
+ OPVP_iformatPNG = 3
+} OPVP_ImageFormat;
+
+/* Color Presentation */
+typedef enum _OPVP_ColorMapping {
+ OPVP_cmapDirect = 0,
+ OPVP_cmapIndexed = 1
+} OPVP_ColorMapping;
+
+typedef enum _OPVP_ColorSpace {
+ OPVP_cspaceBW = 0,
+ OPVP_cspaceDeviceGray = 1,
+ OPVP_cspaceDeviceCMY = 2,
+ OPVP_cspaceDeviceCMYK = 3,
+ OPVP_cspaceDeviceRGB = 4,
+ OPVP_cspaceStandardRGB = 5,
+ OPVP_cspaceStandardRGB64 = 6
+} OPVP_ColorSpace;
+
+/* Raster Operation modes */
+typedef enum _OPVP_ROP {
+ OPVP_ropPset = 0,
+ OPVP_ropPreset = 1,
+ OPVP_ropOr = 2,
+ OPVP_ropAnd = 3,
+ OPVP_ropXor = 4
+} OPVP_ROP;
+
+/* Fill, Paint, Clip */
+typedef enum _OPVP_FillMode {
+ OPVP_fillModeEvenOdd = 0,
+ OPVP_fillModeWinding = 1
+} OPVP_FillMode;
+
+typedef enum _OPVP_PaintMode {
+ OPVP_paintModeOpaque = 0,
+ OPVP_paintModeTransparent = 1
+} OPVP_PaintMode;
+
+typedef enum _OPVP_ClipRule {
+ OPVP_clipRuleEvenOdd = 0,
+ OPVP_clipRuleWinding = 1
+} OPVP_ClipRule;
+
+/* Line */
+typedef enum _OPVP_LineStyle {
+ OPVP_lineStyleSolid = 0,
+ OPVP_lineStyleDash = 1
+} OPVP_LineStyle;
+
+typedef enum _OPVP_LineCap {
+ OPVP_lineCapButt = 0,
+ OPVP_lineCapRound = 1,
+ OPVP_lineCapSquare = 2
+} OPVP_LineCap;
+
+typedef enum _OPVP_LineJoin {
+ OPVP_lineJoinMiter = 0,
+ OPVP_lineJoinRound = 1,
+ OPVP_lineJoinBevel = 2
+} OPVP_LineJoin;
+
+/* Brush */
+typedef enum _OPVP_BrushDataType {
+ OPVP_bdtypeNormal = 0
+} OPVP_BrushDataType;
+
+typedef struct _OPVP_BrushData {
+ OPVP_BrushDataType type;
+ int width;
+ int height;
+ int pitch;
+#if (_PDAPI_VERSION_MAJOR_ == 0 && _PDAPI_VERSION_MINOR_ < 2)
+ void *data; /* pointer to actual data */
+#else
+ char data[1];
+#endif
+} OPVP_BrushData;
+
+typedef struct _OPVP_Brush {
+ OPVP_ColorSpace colorSpace;
+ int color[4]; /* aRGB quadruplet */
+#if (_PDAPI_VERSION_MAJOR_ == 0 && _PDAPI_VERSION_MINOR_ < 2)
+ OPVP_BrushData *pbrush; /* pointer to brush data */
+ /* solid brush used, if null */
+ int xorg; /* brush origin */
+ int yorg; /* ignored for SetBgColor */
+#else
+ int xorg; /* brush origin */
+ int yorg; /* ignored for SetBgColor */
+ OPVP_BrushData *pbrush; /* pointer to brush data */
+ /* solid brush used, if null */
+#endif
+} OPVP_Brush;
+
+/* Misc. Flags */
+#define OPVP_Arc 0 /* circular arc */
+#define OPVP_Chord 1 /* arch */
+#define OPVP_Pie 2 /* pie section */
+#define OPVP_Clockwise 0 /* clockwise */
+#define OPVP_Counterclockwise 1 /* counter-clockwise */
+#define OPVP_PathClose 0 /* Close path when using LinePath */
+#define OPVP_PathOpen 1 /* Do not close path when using LinePath */
+
+/* CTM */
+typedef struct _OPVP_CTM {
+ float a;
+ float b;
+ float c;
+ float d;
+ float e;
+ float f;
+} OPVP_CTM;
+
+/* Vector Driver API Proc. Entries */
+typedef struct _OPVP_api_procs {
+ int (*OpenPrinter)(int,char *,int *,struct _OPVP_api_procs **);
+ int (*ClosePrinter)(int);
+ int (*StartJob)(int,char *);
+ int (*EndJob)(int);
+ int (*StartDoc)(int,char *);
+ int (*EndDoc)(int);
+ int (*StartPage)(int,char *);
+ int (*EndPage)(int);
+#if (_PDAPI_VERSION_MAJOR_ > 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},